From 8b67064ad50cb8ea0c141109cba5923e9ca84da0 Mon Sep 17 00:00:00 2001 From: David Blackman Date: Fri, 26 Mar 2021 08:54:32 -0400 Subject: [PATCH 01/79] Multi get, pluggable hashing and some code cleanup (#1) --- .gitignore | 1 + lib/memjs/constants.js | 159 ++ lib/memjs/memjs.js | 285 ++- lib/memjs/server.js | 4 + lib/memjs/utils.js | 53 +- package-lock.json | 3850 +++++++++++++++++++++++++--------------- package.json | 5 +- test/client_test.js | 360 +++- 8 files changed, 3125 insertions(+), 1592 deletions(-) create mode 100644 lib/memjs/constants.js diff --git a/.gitignore b/.gitignore index d514894..55e3af2 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,4 @@ build/ node_modules npm-debug.log +.nyc_output/ diff --git a/lib/memjs/constants.js b/lib/memjs/constants.js new file mode 100644 index 0000000..37ce8ac --- /dev/null +++ b/lib/memjs/constants.js @@ -0,0 +1,159 @@ + +/* +Constants from memcached binary protocol docs +https://github.com/couchbase/memcached/blob/master/docs/BinaryProtocol.md#0x0d-getkq-get-with-key-quietly + +Note: not all constants in here are implemented in this library, not all constants from the docs are included here +*/ + +exports.OP_GET = 0x00; +exports.OP_SET = 0x01; +exports.OP_ADD = 0x02; +exports.OP_REPLACE = 0x03; +exports.OP_DELETE = 0x04; +exports.OP_INCREMENT = 0x05; +exports.OP_DECREMENT = 0x06; +exports.OP_QUIT = 0x07; +exports.OP_FLUSH = 0x08; +exports.OP_GETQ = 0x09; +exports.OP_NO_OP = 0x0A; +exports.OP_VERSION = 0x0B; +exports.OP_GETK = 0x0C; +exports.OP_GETKQ = 0x0D; +exports.OP_APPEND = 0x0E; +exports.OP_PREPEND = 0x0F; +exports.OP_STAT = 0x10; +exports.OP_SETQ = 0x11; +exports.OP_ADDQ = 0x12; +exports.OP_REPLACEQ = 0x13; +exports.OP_DELETEQ = 0x14; +exports.OP_INCREMENTQ = 0x15; +exports.OP_DECREMENTQ = 0x16; +exports.OP_QUITQ = 0x17; +exports.OP_FLUSHQ = 0x18; +exports.OP_APPENDQ = 0x19; +exports.OP_PREPENDQ = 0x1A; +exports.OP_VERBOSITY = 0x1B; +exports.OP_TOUCH = 0x1C; +exports.OP_GAT = 0x1D; +exports.OP_GATQ = 0x1E; +exports.OP_HELO = 0x1F; +exports.OP_SASL_LIST_MECHS = 0x20; +exports.OP_SASL_AUTH = 0x21; +exports.OP_SASL_STEP = 0x22; +exports.OP_IOCTL_GET = 0x23; +exports.OP_IOCTL_SET = 0x24; +exports.OP_CONFIG_VALIDATE = 0x25; +exports.OP_CONFIG_RELOAD = 0x26; +exports.OP_AUDIT_PUT = 0x27; +exports.OP_AUDIT_CONFIG_RELOAD = 0x28; +exports.OP_SHUTDOWN = 0x29; +exports.OP_RGET = 0x30; +exports.OP_RSET = 0x31; +exports.OP_RSETQ = 0x32; +exports.OP_RAPPEND = 0x33; +exports.OP_RAPPENDQ = 0x34; +exports.OP_RPREPEND = 0x35; +exports.OP_RPREPENDQ = 0x36; +exports.OP_RDELETE = 0x37; +exports.OP_RDELETEQ = 0x38; +exports.OP_RINCR = 0x39; +exports.OP_RINCRQ = 0x3A; +exports.OP_RDECR = 0x3B; +exports.OP_RDECRQ = 0x3C; +exports.OP_SET_VBUCKET = 0x3D; +exports.OP_GET_VBUCKET = 0x3E; +exports.OP_DEL_VBUCKET = 0x3F; +exports.OP_TAP_CONNECT = 0x40; +exports.OP_TAP_MUTATION = 0x41; +exports.OP_TAP_DELETE = 0x42; +exports.OP_TAP_FLUSH = 0x43; +exports.OP_TAP_OPAQUE = 0x44; +exports.OP_TAP_VBUCKET_SET = 0x45; +exports.OP_TAP_CHECKOUT_START = 0x46; +exports.OP_TAP_CHECKPOINT_END = 0x47; +exports.OP_GET_ALL_VB_SEQNOS = 0x48; +exports.OP_DCP_OPEN = 0x50; +exports.OP_DCP_ADD_STREAM = 0x51; +exports.OP_DCP_CLOSE_STREAM = 0x52; +exports.OP_DCP_STREAM_REQ = 0x53; +exports.OP_DCP_GET_FAILOVER_LOG = 0x54; +exports.OP_DCP_STREAM_END = 0x55; +exports.OP_DCP_SNAPSHOT_MARKER = 0x56; +exports.OP_DCP_MUTATION = 0x57; +exports.OP_DCP_DELETION = 0x58; +exports.OP_DCP_EXPIRATION = 0x59; +exports.OP_DCP_FLUSH = 0x5A; +exports.OP_DCP_SET_VBUCKET_STATE = 0x5B; +exports.OP_DCP_NOOP = 0x5C; +exports.OP_DCP_BUFFER_ACKNOWLEDGEMENT = 0x5D; +exports.OP_DCP_CONTROL = 0x5E; +exports.OP_DCP_RESERVED4 = 0x5F; +exports.OP_STOP_PERSISTENCE = 0x80; +exports.OP_START_PERSISTENCE = 0x81; +exports.OP_SET_PARAM = 0x82; +exports.OP_GET_REPLICA = 0x83; +exports.OP_CREATE_BUCKET = 0x85; +exports.OP_DELETE_BUCKET = 0x86; +exports.OP_LIST_BUCKETS = 0x87; +exports.OP_SELECT_BUCKET = 0x89; +exports.OP_ASSUME_ROLE = 0x8A; +exports.OP_OBSERVE_SEQNO = 0x91; +exports.OP_OBSERVE = 0x92; +exports.OP_EVICT_KEY = 0x93; +exports.OP_GET_LOCKED = 0x94; +exports.OP_UNLOCK_KEY = 0x95; +exports.OP_LAST_CLOSED_CHECKPOINT = 0x97; +exports.OP_DEREGISTER_TAP_CLIENT = 0x9E; +exports.OP_RESET_REPLICATION_CHAIN = 0x9F; +exports.OP_GET_META = 0xA0; +exports.OP_GETQ_META = 0xA1; +exports.OP_SET_WITH_META = 0xA2; +exports.OP_SETQ_WITH_META = 0xA3; +exports.OP_ADD_WITH_META = 0xA4; +exports.OP_ADDQ_WITH_META = 0xA5; +exports.OP_SNAPSHOT_VB_STATES = 0xA6; +exports.OP_VBUCKET_BATCH_COUNT = 0xA7; +exports.OP_DEL_WITH_META = 0xA8; +exports.OP_DELQ_WITH_META = 0xA9; +exports.OP_CREATE_CHECKPOINT = 0xAA; +exports.OP_NOTIFY_VBUCKET_UPDATE = 0xAC; +exports.OP_ENABLE_TRAFFIC = 0xAD; +exports.OP_DISABLE_TRAFFIC = 0xAE; +exports.OP_CHANGE_VB_FILTER = 0xB0; +exports.OP_CHECKPOINT_PERSISTENCE = 0xB1; +exports.OP_RETURN_META = 0xB2; +exports.OP_COMPACT_DB = 0xB3; +exports.OP_SET_CLUSTER_CONFIG = 0xB4; +exports.OP_GET_CLUSTER_CONFIG = 0xB5; +exports.OP_GET_RANDOM_KEY = 0xB6; +exports.OP_SEQNO_PERSISTENCE = 0xB7; +exports.OP_GET_KEYS = 0xB8; +exports.OP_SET_DRIFT_COUNTER_STATE = 0xC1; +exports.OP_GET_ADJUSTED_TIME = 0xC2; +exports.OP_SUBDOC_GET = 0xC5; +exports.OP_SUBDOC_EXISTS = 0xC6; +exports.OP_SUBDOC_DICT_ADD = 0xC7; +exports.OP_SUBDOC_DICT_UPSERT = 0xC8; +exports.OP_SUBDOC_DELETE = 0xC9; +exports.OP_SUBDOC_REPLACE = 0xCA; +exports.OP_SUBDOC_ARRAY_PUSH_LAST = 0xCB; +exports.OP_SUBDOC_ARRAY_PUSH_FIRST = 0xCC; +exports.OP_SUBDOC_ARRAY_INSERT = 0xCD; +exports.OP_SUBDOC_ARRAY_ADD_UNIQUE = 0xCE; +exports.OP_SUBDOC_COUNTER = 0xCF; +exports.OP_SUBDOC_MULTI_LOOKUP = 0xD0; +exports.OP_SUBDOC_MULTI_MUTATION = 0xD1; +exports.OP_SUBDOC_GET_COUNT = 0xD2; +exports.OP_SCRUB = 0xF0; +exports.OP_ISASL_REFRESH = 0xF1; +exports.OP_SSL_CERTS_REFRESH = 0xF2; +exports.OP_GET_CMD_TIMER = 0xF3; +exports.OP_SET_CTRL_TOKEN = 0xF4; +exports.OP_GET_CTRL_TOKEN = 0xF5; +exports.OP_INIT_COMPLETE = 0xF6; + +// Named "No Error" in the memcache docs but this seems like it will be clearer +exports.RESPONSE_STATUS_SUCCCESS = 0x00; +exports.RESPONSE_STATUS_KEY_NOT_FOUND = 0x01; +exports.RESPONSE_STATUS_KEY_EXISTS = 0x02; \ No newline at end of file diff --git a/lib/memjs/memjs.js b/lib/memjs/memjs.js index b8eac35..da77878 100644 --- a/lib/memjs/memjs.js +++ b/lib/memjs/memjs.js @@ -1,13 +1,25 @@ +// TODO +// test that handlers are cleaned up on errors +// --> see if handler.false is even needed + // # MemJS Memcache Client var errors = require('./protocol').errors; var Server = require('./server').Server; var noopSerializer = require('./noop-serializer').noopSerializer; var makeRequestBuffer = require('./utils').makeRequestBuffer; -var hashCode = require('./utils').hashCode; +var copyIntoRequestBuffer = require('./utils').copyIntoRequestBuffer; var merge = require('./utils').merge; var makeExpiration = require('./utils').makeExpiration; var makeAmountInitialAndExpiration = require('./utils').makeAmountInitialAndExpiration; +var constants = require('./constants'); +var hashCode = require('./utils').hashCode; + +function defaultKeyToServerHashFunction(servers, key) { + var total = servers.length; + var index = (total > 1) ? (hashCode(key) % total) : 0; + return servers[index]; +} // Client initializer takes a list of `Server`s and an `options` dictionary. // See `Client.create` for details. @@ -15,9 +27,21 @@ var Client = function(servers, options) { this.servers = servers; this.seq = 0; this.options = merge(options || {}, - {failoverTime: 60, retries: 2, retry_delay: 0.2, expires: 0, logger: console}); + {retries: 2, retry_delay: 0.2, expires: 0, logger: console, + keyToServerHashFunction: defaultKeyToServerHashFunction + }); this.serializer = this.options.serializer || noopSerializer; + + // Store a mapping from hostport -> server so we can quickly get a server object from the serverKey returned by the hashing function + var serverMap = {}; + this.servers.forEach(function(server) { + serverMap[server.hostportString()] = server; + }); + this.serverMap = serverMap; + + // store a list of all our serverKeys so we don't need to constantly reallocate this array + this.serverKeys = Object.keys(this.serverMap); }; // Creates a new client given an optional config string and optional hash of @@ -36,9 +60,6 @@ var Client = function(servers, options) { // expire). If `expires` is greater than 30 days (60 x 60 x 24 x 30), it is // treated as a UNIX time (number of seconds since January 1, 1970). // * `logger` - a logger object that responds to `log(string)` method calls. -// * `failover` - whether to failover to next server. Defaults to false. -// * `failoverTime` - how much to wait until retring a failed server. Default -// is 60 seconds. // // ~~~~ // log(msg1[, msg2[, msg3[...]]]) @@ -46,7 +67,7 @@ var Client = function(servers, options) { // // Defaults to `console`. // * `serializer` - the object which will (de)serialize the data. It needs -// two public methods: serialize and deserialize. It defaults to the +// two public methods: serialize and deserialize. It defaults to the // noopSerializer: // // ~~~~ @@ -69,6 +90,9 @@ var Client = function(servers, options) { // * `keepAlive` whether to enable keep-alive functionality. Defaults to false. // * `keepAliveDelay` in seconds to the initial delay before the first keepalive // probe is sent on an idle socket. Defaults is 30 seconds. +// * `keyToServerHashFunction` a function to map keys to servers, with the signature +// (serverKeys: string[], key: string): string +// NOTE: if you need to do some expensive initialization, *please* do it lazily the first time you this function is called with an array of serverKeys, not on every call Client.create = function(serversStr, options) { serversStr = serversStr || process.env.MEMCACHIER_SERVERS || process.env.MEMCACHE_SERVERS || 'localhost:11211'; @@ -82,23 +106,26 @@ Client.create = function(serversStr, options) { return new Client(servers, options); }; -// Chooses the server to talk to by hashing the given key. -Client.prototype.server = function(key) { - // TODO(alevy): should use consistent hashing and/or allow swapping hashing - // mechanisms - var total = this.servers.length; - var origIdx = (total > 1) ? (hashCode(key) % total) : 0; - var idx = origIdx; - var serv = this.servers[idx]; - while (serv.wakeupAt && - serv.wakeupAt > Date.now()) { - idx = (idx + 1) % total; - if (idx === origIdx) { - return null; - } - serv = this.servers[idx]; - } - return serv; +/** + * Given a serverKey fromlookupKeyToServerKey, return the corresponding Server instance + * + * @param {string} serverKey + * @returns {Server} +*/ +Client.prototype.serverKeyToServer = function(serverKey) { + return this.serverMap[serverKey]; +}; + +/** + * Given a key to look up in memcache, return a serverKey (based on some + * hashing function) which +can be used to index this.serverMap + * + * @param {string} key + * * @returns {string} + */ +Client.prototype.lookupKeyToServerKey = function(key) { + return this.options.keyToServerHashFunction(this.serverKeys, key); }; // converts a call into a promise-returning one @@ -133,7 +160,7 @@ var promisify = function(command) { // // callback(err, value, flags) // -// _value_ and _flags_ are both `Buffer`s. If the key is not found, the +// _value_ and _flags_ are both `string`s. If the key is not found, the // callback is invoked with null for both arguments and no error. Client.prototype.get = function(key, callback) { var self = this; @@ -146,20 +173,20 @@ Client.prototype.get = function(key, callback) { } var logger = this.options.logger; this.incrSeq(); - var request = makeRequestBuffer(0, key, '', '', this.seq); + var request = makeRequestBuffer(constants.OP_GET, key, '', '', this.seq); this.perform(key, request, this.seq, function(err, response) { if (err) { if (callback) { callback(err, null, null); } return; } switch (response.header.status) { - case 0: + case constants.RESPONSE_STATUS_SUCCCESS: if (callback) { var deserialized = self.serializer.deserialize(response.header.opcode, response.val, response.extras); callback(null, deserialized.value, deserialized.extras); } break; - case 1: + case constants.RESPONSE_STATUS_KEY_NOT_FOUND: if (callback) { callback(null, null, null); } break; default: @@ -170,6 +197,136 @@ Client.prototype.get = function(key, callback) { }); }; +/** Build a pipelined get multi request by sending one GETKQ for each key (quiet, meaning it won't respond if the value is missing) followed by a no-op to force a response (and to give us a sentinel response that the pipeline is done) + * + * cf https://github.com/couchbase/memcached/blob/master/docs/BinaryProtocol.md#0x0d-getkq-get-with-key-quietly + */ +Client.prototype._buildGetMultiRequest = function(keys) { + // start at 24 for the no-op command at the end + var requestSize = 24; + for (var keyIdx in keys) { + requestSize += Buffer.byteLength(keys[keyIdx], 'utf8') + 24; + } + + var request = Buffer.alloc(requestSize); + request.fill(); + + var bytesWritten = 0; + for (keyIdx in keys) { + var key = keys[keyIdx]; + bytesWritten += copyIntoRequestBuffer(constants.OP_GETKQ, key, '', '', this.seq, request, bytesWritten); + } + + bytesWritten += copyIntoRequestBuffer( + constants.OP_NO_OP, '', '', '', this.seq, request, bytesWritten); + + return request; +}; + +/** Executing a pipelined (multi) get against a single server. This is a private implementation detail of getMulti. */ +Client.prototype._getMultiToServer = function (serv, keys, callback) { + var self = this; + + var responseMap = {}; + + var handle = function(response) { + switch (response.header.status) { + case constants.RESPONSE_STATUS_SUCCCESS: + if (callback) { + var deserialized = self.serializer.deserialize(response.header.opcode, response.val, response.extras); + // When we get the no-op response, we are done with this one getMulti in the per-backend fan-out + if (response.header.opcode === constants.OP_NO_OP) { + // This ensures the handler will be deleted from the responseCallbacks map in server.js + // This isn't technically needed here because the logic in server.js also checks if totalBodyLength === 0, but our unittests aren't great about setting that field, and also this makes it more explicit + handle.quiet = false; + callback(null, responseMap); + } else { + var key = response.key.toString(); + responseMap[key] = deserialized.value; + } + } + break; + case constants.RESPONSE_STATUS_KEY_NOT_FOUND: + if (callback) { callback(null, null, null); } + break; + default: + var errorMessage = 'MemJS GET: ' + errors[response.header.status]; + self.options.logger.log(errorMessage); + if (callback) { callback(new Error(errorMessage), null, null); } + } + }; + // This prevents the handler from being deleted + // after the first response. Logic in server.js. + handle.quiet = true; + + var request = this._buildGetMultiRequest(keys); + serv.onResponse(this.seq, handle); + serv.onError(this.seq, function(err) { + if (callback) { callback(err, serv.hostportString(), null); } + }); + this.incrSeq(); + serv.write(request); +}; + +// MULTI-GET / GET-MULTI +// +// Retrieves the value at the given keys in memcache. +// +// The callback signature is: +// +// callback(err, values, flags) +// +// _values_ is a map of key->string +// _flags_ is a `string`. +Client.prototype.getMulti = function(keys, callback) { + var self = this; + if(callback === undefined) { + return promisify(function(callback) { + self.getMulti(keys, function(err, values, flags) { + callback(err, {values: values, flags: flags}); + }); + }); + } + + + var serverKeytoLookupKeys = {}; + keys.forEach(function(lookupKey) { + var serverKey = self.lookupKeyToServerKey(lookupKey); + if (!serverKeytoLookupKeys[serverKey]) { + serverKeytoLookupKeys[serverKey] = []; + } + serverKeytoLookupKeys[serverKey].push(lookupKey); + }); + + var usedServerKeys = Object.keys(serverKeytoLookupKeys); + var outstandingCalls = usedServerKeys.length; + var recordMap = {}; + var hadError = false; + function latchCallback(err, values, flags) { + if (hadError) { + return; + } + + if (err) { + hadError = true; + callback(err, null, null); + return; + } + + merge(recordMap, values); + outstandingCalls -= 1; + if (outstandingCalls === 0) { + callback(null, recordMap, flags); + } + } + + for (var serverKeyIndex in usedServerKeys) { + var serverKey = usedServerKeys[serverKeyIndex]; + var server = this.serverKeyToServer(serverKey); + this._getMultiToServer(server, serverKeytoLookupKeys[serverKey], latchCallback); + } +}; + // SET // // Sets the given _key_ and _value_ in memcache. @@ -214,7 +371,7 @@ Client.prototype.set = function(key, value, options, callback) { return; } switch (response.header.status) { - case 0: + case constants.RESPONSE_STATUS_SUCCCESS: if (callback) { callback(null, true); } break; default: @@ -270,10 +427,10 @@ Client.prototype.add = function(key, value, options, callback) { return; } switch (response.header.status) { - case 0: + case constants.RESPONSE_STATUS_SUCCCESS: if (callback) { callback(null, true); } break; - case 2: + case constants.RESPONSE_STATUS_KEY_EXISTS: if (callback) { callback(null, false); } break; default: @@ -329,10 +486,10 @@ Client.prototype.replace = function(key, value, options, callback) { return; } switch (response.header.status) { - case 0: + case constants.RESPONSE_STATUS_SUCCCESS: if (callback) { callback(null, true); } break; - case 1: + case constants.RESPONSE_STATUS_KEY_NOT_FOUND: if (callback) { callback(null, false); } break; default: @@ -366,10 +523,10 @@ Client.prototype.delete = function(key, callback) { return; } switch (response.header.status) { - case 0: + case constants.RESPONSE_STATUS_SUCCCESS: if (callback) { callback(null, true); } break; - case 1: + case constants.RESPONSE_STATUS_KEY_NOT_FOUND: if (callback) { callback(null, false); } break; default: @@ -430,7 +587,7 @@ Client.prototype.increment = function(key, amount, options, callback) { return; } switch (response.header.status) { - case 0: + case constants.RESPONSE_STATUS_SUCCCESS: var bufInt = (response.val.readUInt32BE(0) << 8) + response.val.readUInt32BE(4); if (callback) { callback(null, true, bufInt); } break; @@ -492,7 +649,7 @@ Client.prototype.decrement = function(key, amount, options, callback) { return; } switch (response.header.status) { - case 0: + case constants.RESPONSE_STATUS_SUCCCESS: var bufInt = (response.val.readUInt32BE(0) << 8) + response.val.readUInt32BE(4); if (callback) { callback(null, true, bufInt); } break; @@ -528,10 +685,10 @@ Client.prototype.append = function(key, value, callback) { return; } switch (response.header.status) { - case 0: + case constants.RESPONSE_STATUS_SUCCCESS: if (callback) { callback(null, true); } break; - case 1: + case constants.RESPONSE_STATUS_KEY_NOT_FOUND: if (callback) { callback(null, false); } break; default: @@ -567,10 +724,10 @@ Client.prototype.prepend = function(key, value, callback) { return; } switch (response.header.status) { - case 0: + case constants.RESPONSE_STATUS_SUCCCESS: if (callback) { callback(null, true); } break; - case 1: + case constants.RESPONSE_STATUS_KEY_NOT_FOUND: if (callback) { callback(null, false); } break; default: @@ -604,10 +761,10 @@ Client.prototype.touch = function(key, expires, callback) { return; } switch (response.header.status) { - case 0: + case constants.RESPONSE_STATUS_SUCCCESS: if (callback) { callback(null, true); } break; - case 1: + case constants.RESPONSE_STATUS_KEY_NOT_FOUND: if (callback) { callback(null, false); } break; default: @@ -643,7 +800,7 @@ Client.prototype.flush = function(callback) { var handleFlush = function(seq, serv) { serv.onResponse(seq, function(/* response */) { count -= 1; - result[serv.host + ':' + serv.port] = true; + result[serv.hostportString()] = true; if (callback && count === 0) { callback(lastErr, result); } @@ -651,7 +808,7 @@ Client.prototype.flush = function(callback) { serv.onError(seq, function(err) { count -= 1; lastErr = err; - result[serv.host + ':' + serv.port] = err; + result[serv.hostportString()] = err; if (callback && count === 0) { callback(lastErr, result); } @@ -684,12 +841,12 @@ Client.prototype.statsWithKey = function(key, callback) { var handle = function(response) { // end of stat responses if (response.header.totalBodyLength === 0) { - if (callback) { callback(null, serv.host + ':' + serv.port, result); } + if (callback) { callback(null, serv.hostportString(), result); } return; } // process single stat line response switch (response.header.status) { - case 0: + case constants.RESPONSE_STATUS_SUCCCESS: result[response.key.toString()] = response.val.toString(); break; default: @@ -697,7 +854,7 @@ Client.prototype.statsWithKey = function(key, callback) { errors[response.header.status]; logger.log(errorMessage, false); if (callback) { - callback(new Error(errorMessage), serv.host + ':' + serv.port, null); + callback(new Error(errorMessage), serv.hostportString(), null); } } }; @@ -705,7 +862,7 @@ Client.prototype.statsWithKey = function(key, callback) { serv.onResponse(seq, handle); serv.onError(seq, function(err) { - if (callback) { callback(err, serv.host + ':' + serv.port, null); } + if (callback) { callback(err, serv.hostportString(), null); } }); serv.write(request); }; @@ -793,16 +950,21 @@ Client.prototype.close = function() { // fails // retries: number of times to retry request on failure Client.prototype.perform = function(key, request, seq, callback, retries) { - var _this = this; - var serv = this.server(key); - if (!serv) { + var serverKey = this.lookupKeyToServerKey(key); + + var server = this.serverKeyToServer(serverKey); + + if (!server) { if (callback) { callback(new Error('No servers available'), null); } return; } + return this.performOnServer(server, request, seq, callback, retries); +}; + +Client.prototype.performOnServer = function(server, request, seq, callback, retries) { + var _this = this; retries = retries || this.options.retries; - var failover = this.options.failover; - var failoverTime = this.options.failoverTime; var origRetries = this.options.retries; var logger = this.options.logger; var retry_delay = this.options.retry_delay; @@ -815,24 +977,19 @@ Client.prototype.perform = function(key, request, seq, callback, retries) { if (--retries > 0) { // Wait for retry_delay setTimeout(function() { - _this.perform(key, request, seq, callback, retries); + _this.performOnServer(server, request, seq, callback, retries); }, 1000 * retry_delay); } else { - logger.log('MemJS: Server <' + serv.host + ':' + serv.port + + logger.log('MemJS: Server <' + server.hostportString() + '> failed after (' + origRetries + ') retries with error - ' + error.message); - if (failover) { - serv.wakeupAt = Date.now() + failoverTime * 1000; - _this.perform(key, request, seq, callback, origRetries); - } else { - if (callback) { callback(error, null); } - } + if (callback) { callback(error, null); } } }; - serv.onResponse(seq, responseHandler); - serv.onError(seq, errorHandler); - serv.write(request); + server.onResponse(seq, responseHandler); + server.onError(seq, errorHandler); + server.write(request); }; // Increment the seq value diff --git a/lib/memjs/server.js b/lib/memjs/server.js index ea04af9..26d6b0a 100644 --- a/lib/memjs/server.js +++ b/lib/memjs/server.js @@ -242,4 +242,8 @@ Server.prototype.toString = function() { return ''; }; +Server.prototype.hostportString = function() { + return this.host + ':' + this.port; +}; + exports.Server = Server; diff --git a/lib/memjs/utils.js b/lib/memjs/utils.js index a30956a..8ae28bd 100644 --- a/lib/memjs/utils.js +++ b/lib/memjs/utils.js @@ -5,13 +5,20 @@ var header = require('./header'); var bufferify = function(val) { return Buffer.isBuffer(val) ? val : Buffer.from(val); }; +exports.bufferify = bufferify; -exports.makeRequestBuffer = function(opcode, key, extras, value, opaque) { +exports.copyIntoRequestBuffer = function(opcode, key, extras, value, opaque, buf, _bufTargetWriteOffset) { key = bufferify(key); extras = bufferify(extras); value = bufferify(value); - var buf = Buffer.alloc(24 + key.length + extras.length + value.length); - buf.fill(); + + var bufTargetWriteOffset = _bufTargetWriteOffset || 0; + var totalBytesWritten = 0; + function copyIntoBuffer(toWriteBuffer) { + var bytesWritten = toWriteBuffer.copy(buf, bufTargetWriteOffset + totalBytesWritten); + totalBytesWritten += bytesWritten; + } + var requestHeader = { magic: 0x80, opcode: opcode, @@ -20,10 +27,26 @@ exports.makeRequestBuffer = function(opcode, key, extras, value, opaque) { totalBodyLength: key.length + value.length + extras.length, opaque: opaque }; - header.toBuffer(requestHeader).copy(buf); - extras.copy(buf, 24); - key.copy(buf, 24 + extras.length); - value.copy(buf, 24 + extras.length + key.length); + var headerBuffer = header.toBuffer(requestHeader); + + copyIntoBuffer(headerBuffer); + copyIntoBuffer(extras); + copyIntoBuffer(key); + copyIntoBuffer(value); + + return totalBytesWritten; +}; + +exports.makeRequestBuffer = function(opcode, key, extras, value, opaque) { + key = bufferify(key); + extras = bufferify(extras); + value = bufferify(value); + + var bufSize = 24 + key.length + extras.length + value.length; + + var buf = Buffer.alloc(bufSize); + buf.fill(); + exports.copyIntoRequestBuffer(opcode, key, extras, value, opaque, buf); return buf; }; @@ -56,6 +79,7 @@ exports.parseMessage = function(dataBuf) { return false; } var responseHeader = header.fromBuffer(dataBuf); + if (dataBuf.length < responseHeader.totalBodyLength + 24 || responseHeader.totalBodyLength < responseHeader.keyLength + responseHeader.extrasLength) { @@ -72,6 +96,21 @@ exports.parseMessage = function(dataBuf) { return {header: responseHeader, key: key, extras: extras, val: val}; }; +exports.parseMessages = function(dataBuf) { + var messages = []; + + do { + var message = exports.parseMessage(dataBuf); + if (message) { + messages.push(message); + var messageLength = message.header.totalBodyLength + 24; + dataBuf = dataBuf.slice(messageLength); + } + } while (message); + + return messages; +}; + exports.merge = function(original, deflt) { var attr, originalValue; for (attr in deflt) { diff --git a/package-lock.json b/package-lock.json index 1dcc3d2..591b998 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,10 +4,197 @@ "lockfileVersion": 1, "requires": true, "dependencies": { - "abbrev": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", - "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", + "@babel/code-frame": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz", + "integrity": "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==", + "dev": true, + "requires": { + "@babel/highlight": "^7.12.13" + } + }, + "@babel/generator": { + "version": "7.13.9", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.13.9.tgz", + "integrity": "sha512-mHOOmY0Axl/JCTkxTU6Lf5sWOg/v8nUa+Xkt4zMTftX0wqmb6Sh7J8gvcehBw7q0AhrhAR+FDacKjCZ2X8K+Sw==", + "dev": true, + "requires": { + "@babel/types": "^7.13.0", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "@babel/helper-function-name": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.12.13.tgz", + "integrity": "sha512-TZvmPn0UOqmvi5G4vvw0qZTpVptGkB1GL61R6lKvrSdIxGm5Pky7Q3fpKiIkQCAtRCBUwB0PaThlx9vebCDSwA==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.12.13", + "@babel/template": "^7.12.13", + "@babel/types": "^7.12.13" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.13.tgz", + "integrity": "sha512-DjEVzQNz5LICkzN0REdpD5prGoidvbdYk1BVgRUOINaWJP2t6avB27X1guXK1kXNrX0WMfsrm1A/ZBthYuIMQg==", + "dev": true, + "requires": { + "@babel/types": "^7.12.13" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.13.tgz", + "integrity": "sha512-tCJDltF83htUtXx5NLcaDqRmknv652ZWCHyoTETf1CXYJdPC7nohZohjUgieXhv0hTJdRf2FjDueFehdNucpzg==", + "dev": true, + "requires": { + "@babel/types": "^7.12.13" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", + "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", + "dev": true + }, + "@babel/highlight": { + "version": "7.13.10", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.13.10.tgz", + "integrity": "sha512-5aPpe5XQPzflQrFwL1/QoeHkP2MsA4JCntcXHRhEsdsfPVkvPi2w7Qix4iV7t5S/oC9OodGrggd8aco1g3SZFg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.12.11", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@babel/parser": { + "version": "7.13.12", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.13.12.tgz", + "integrity": "sha512-4T7Pb244rxH24yR116LAuJ+adxXXnHhZaLJjegJVKSdoNCe4x1eDBaud5YIcQFcqzsaD5BHvJw5BQ0AZapdCRw==", + "dev": true + }, + "@babel/template": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.12.13.tgz", + "integrity": "sha512-/7xxiGA57xMo/P2GVvdEumr8ONhFOhfgq2ihK3h1e6THqzTAkHbkXgB0xI9yeTfIUoH3+oAeHhqm/I43OTbbjA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.12.13", + "@babel/parser": "^7.12.13", + "@babel/types": "^7.12.13" + } + }, + "@babel/traverse": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.13.0.tgz", + "integrity": "sha512-xys5xi5JEhzC3RzEmSGrs/b3pJW/o87SypZ+G/PhaE7uqVQNv/jlmVIBXuoh5atqQ434LfXV+sf23Oxj0bchJQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.12.13", + "@babel/generator": "^7.13.0", + "@babel/helper-function-name": "^7.12.13", + "@babel/helper-split-export-declaration": "^7.12.13", + "@babel/parser": "^7.13.0", + "@babel/types": "^7.13.0", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.19" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "@babel/types": { + "version": "7.13.12", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.13.12.tgz", + "integrity": "sha512-K4nY2xFN4QMvQwkQ+zmBDp6ANMbVNw6BbxWmYA4qNjhR9W+Lj/8ky5MEY2Me5r+B2c6/v6F53oMndG+f9s3IiA==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + }, + "dependencies": { + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + } + } + }, + "@types/yoga-layout": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@types/yoga-layout/-/yoga-layout-1.9.2.tgz", + "integrity": "sha512-S9q47ByT2pPvD65IvrWp7qppVMpk9WGMbVq9wbWZOHg6tnXSD4vyhao6nOSBwwfDdV2p3Kx9evA9vI+XWTfDvw==", "dev": true }, "acorn": { @@ -51,13 +238,6 @@ "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=", "dev": true }, - "amdefine": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", - "dev": true, - "optional": true - }, "ansi-escapes": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", @@ -76,69 +256,87 @@ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", "dev": true }, - "append-transform": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-0.2.2.tgz", - "integrity": "sha1-xB83Y+kQz+eWRgkmZ+ZHGAmTjIU=", + "ansicolors": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.3.2.tgz", + "integrity": "sha1-ZlWX3oap/+Oqm/vmyuXG6kJrSXk=", "dev": true }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "anymatch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", + "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", "dev": true, "requires": { - "sprintf-js": "~1.0.2" + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" } }, - "arr-diff": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-1.1.0.tgz", - "integrity": "sha1-aHwydYFjWI/vfeezb6vklesaOZo=", + "append-transform": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-1.0.0.tgz", + "integrity": "sha512-P009oYkeHyU742iSZJzZZywj4QRJdnTWffaKuJQLablCZ1uz6/cW4yaRgcDaoQ+uwOxxnt0gRUcwfsNP2ri0gw==", "dev": true, "requires": { - "arr-flatten": "^1.0.1", - "array-slice": "^0.2.3" + "default-require-extensions": "^2.0.0" } }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", "dev": true }, - "array-slice": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", - "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=", + "arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", "dev": true }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, "arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", "dev": true }, "asn1": { - "version": "0.1.11", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz", - "integrity": "sha1-VZvhg3bQik7E2+gId9J4GGObLfc=", + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", "dev": true, - "optional": true + "requires": { + "safer-buffer": "~2.1.0" + } }, "assert-plus": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz", - "integrity": "sha1-7nQAlBMALYTOxyGcasgRgS5yMWA=", - "dev": true, - "optional": true + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true }, - "async": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", - "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", + "astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true + }, + "async-hook-domain": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/async-hook-domain/-/async-hook-domain-1.1.3.tgz", + "integrity": "sha512-ZovMxSbADV3+biB7oR1GL5lGyptI24alp0LWHlmz1OFc5oL47pz3EiIF6nXOkDW7yLqih4NtsiYduzdDW0i+Wg==", "dev": true, - "optional": true + "requires": { + "source-map-support": "^0.5.11" + } }, "asynckit": { "version": "0.4.0", @@ -146,17 +344,22 @@ "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", "dev": true }, + "auto-bind": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/auto-bind/-/auto-bind-4.0.0.tgz", + "integrity": "sha512-Hdw8qdNiqdJ8LqT0iK0sVzkFbzg6fhnQqqfWhBDxcHZvU75+B+ayzTy8x+k5Ix0Y92XOhOUlx74ps+bA6BeYMQ==", + "dev": true + }, "aws-sign2": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz", - "integrity": "sha1-xXED96F/wDfwLXwuZLYC6iI/fWM=", - "dev": true, - "optional": true + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "dev": true }, "aws4": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", - "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", + "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==", "dev": true }, "babel-code-frame": { @@ -170,6 +373,235 @@ "js-tokens": "^3.0.2" } }, + "babel-core": { + "version": "6.26.3", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.3.tgz", + "integrity": "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==", + "dev": true, + "requires": { + "babel-code-frame": "^6.26.0", + "babel-generator": "^6.26.0", + "babel-helpers": "^6.24.1", + "babel-messages": "^6.23.0", + "babel-register": "^6.26.0", + "babel-runtime": "^6.26.0", + "babel-template": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "convert-source-map": "^1.5.1", + "debug": "^2.6.9", + "json5": "^0.5.1", + "lodash": "^4.17.4", + "minimatch": "^3.0.4", + "path-is-absolute": "^1.0.1", + "private": "^0.1.8", + "slash": "^1.0.0", + "source-map": "^0.5.7" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "babel-generator": { + "version": "6.26.1", + "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", + "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", + "dev": true, + "requires": { + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "detect-indent": "^4.0.0", + "jsesc": "^1.3.0", + "lodash": "^4.17.4", + "source-map": "^0.5.7", + "trim-right": "^1.0.1" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "babel-helper-builder-react-jsx": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz", + "integrity": "sha1-Of+DE7dci2Xc7/HzHTg+D/KkCKA=", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "esutils": "^2.0.2" + } + }, + "babel-helpers": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", + "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } + }, + "babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-syntax-jsx": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", + "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=", + "dev": true + }, + "babel-plugin-syntax-object-rest-spread": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", + "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=", + "dev": true + }, + "babel-plugin-transform-es2015-destructuring": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", + "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-object-rest-spread": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz", + "integrity": "sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY=", + "dev": true, + "requires": { + "babel-plugin-syntax-object-rest-spread": "^6.8.0", + "babel-runtime": "^6.26.0" + } + }, + "babel-plugin-transform-react-jsx": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz", + "integrity": "sha1-hAoCjn30YN/DotKfDA2R9jduZqM=", + "dev": true, + "requires": { + "babel-helper-builder-react-jsx": "^6.24.1", + "babel-plugin-syntax-jsx": "^6.8.0", + "babel-runtime": "^6.22.0" + } + }, + "babel-register": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", + "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", + "dev": true, + "requires": { + "babel-core": "^6.26.0", + "babel-runtime": "^6.26.0", + "core-js": "^2.5.0", + "home-or-tmp": "^2.0.0", + "lodash": "^4.17.4", + "mkdirp": "^0.5.1", + "source-map-support": "^0.4.15" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "source-map-support": { + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", + "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", + "dev": true, + "requires": { + "source-map": "^0.5.6" + } + } + } + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "dev": true, + "requires": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + } + }, + "babel-template": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", + "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "lodash": "^4.17.4" + } + }, + "babel-traverse": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", + "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", + "dev": true, + "requires": { + "babel-code-frame": "^6.26.0", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "debug": "^2.6.8", + "globals": "^9.18.0", + "invariant": "^2.2.2", + "lodash": "^4.17.4" + }, + "dependencies": { + "globals": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", + "dev": true + } + } + }, + "babel-types": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "esutils": "^2.0.2", + "lodash": "^4.17.4", + "to-fast-properties": "^1.0.3" + } + }, + "babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", + "dev": true + }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", @@ -203,15 +635,17 @@ } } }, - "boom": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/boom/-/boom-0.4.2.tgz", - "integrity": "sha1-emNune1O/O+xnO9JR6PGffrukRs=", - "dev": true, - "optional": true, - "requires": { - "hoek": "0.9.x" - } + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true + }, + "bind-obj-methods": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/bind-obj-methods/-/bind-obj-methods-2.0.1.tgz", + "integrity": "sha512-kKzUyCuc+jsWH4C2nW5KB2nh+rQRbQcdphfo9UN3j1uwIFGZ3JB8njtRZOiUAQCkxazH0nDQPN6x/zhvFcbZIw==", + "dev": true }, "brace-expansion": { "version": "1.1.11", @@ -224,16 +658,20 @@ } }, "braces": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", - "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "dev": true, "requires": { - "expand-range": "^1.8.1", - "preserve": "^0.2.0", - "repeat-element": "^1.1.2" + "fill-range": "^7.0.1" } }, + "browser-process-hrtime": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", + "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", + "dev": true + }, "buffer-from": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", @@ -241,14 +679,32 @@ "dev": true }, "caching-transform": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-1.0.1.tgz", - "integrity": "sha1-bb2y8g+Nj7znnz6U6dF0Lc31wKE=", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-3.0.2.tgz", + "integrity": "sha512-Mtgcv3lh3U0zRii/6qVgQODdPA4G3zhG+jtbCWj39RXuUFTMzH0vcdMtaJS1jPowd+It2Pqr6y3NJMQqOqCE2w==", "dev": true, "requires": { - "md5-hex": "^1.2.0", - "mkdirp": "^0.5.1", - "write-file-atomic": "^1.1.4" + "hasha": "^3.0.0", + "make-dir": "^2.0.0", + "package-hash": "^3.0.0", + "write-file-atomic": "^2.4.2" + } + }, + "caller-callsite": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", + "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=", + "dev": true, + "requires": { + "callsites": "^2.0.0" + }, + "dependencies": { + "callsites": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", + "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=", + "dev": true + } } }, "caller-path": { @@ -267,15 +723,31 @@ "dev": true }, "camelcase": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "capture-stack-trace": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz", + "integrity": "sha512-mYQLZnx5Qt1JgB1WEiMCf2647plpGeQ2NMR/5L0HNZzGQo4fuSPnK+wjfPnKZV0aiJDgzmWqqkV/g7JD+DW0qw==", "dev": true }, + "cardinal": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/cardinal/-/cardinal-2.1.1.tgz", + "integrity": "sha1-fMEFXYItISlU0HsIXeolHMe8VQU=", + "dev": true, + "requires": { + "ansicolors": "~0.3.2", + "redeyed": "~2.1.0" + } + }, "caseless": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.6.0.tgz", - "integrity": "sha1-gWfBq4OX+1u5X5bSjlqBxQ8kesQ=", + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", "dev": true }, "chalk": { @@ -297,6 +769,28 @@ "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", "dev": true }, + "chokidar": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", + "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", + "dev": true, + "requires": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.3.1", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.5.0" + } + }, + "ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true + }, "circular-json": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", @@ -312,6 +806,91 @@ "restore-cursor": "^2.0.0" } }, + "cli-truncate": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", + "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", + "dev": true, + "requires": { + "slice-ansi": "^3.0.0", + "string-width": "^4.2.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "slice-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", + "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + } + }, + "string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + } + } + }, "cli-width": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz", @@ -319,14 +898,31 @@ "dev": true }, "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", + "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", "dev": true, "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", "wrap-ansi": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } } }, "co": { @@ -341,16 +937,6 @@ "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", "dev": true }, - "codecov.io": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/codecov.io/-/codecov.io-0.1.6.tgz", - "integrity": "sha1-Wd/QLaH/McL7K5Uq2K0W/TeBtyg=", - "dev": true, - "requires": { - "request": "2.42.0", - "urlgrey": "0.4.0" - } - }, "color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -373,13 +959,12 @@ "dev": true }, "combined-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz", - "integrity": "sha1-ATfmV7qlp1QcV6w3rF/AfXO03B8=", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "dev": true, - "optional": true, "requires": { - "delayed-stream": "0.0.5" + "delayed-stream": "~1.0.0" } }, "commander": { @@ -413,14 +998,20 @@ } }, "convert-source-map": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", - "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", "dev": true, "requires": { "safe-buffer": "~5.1.1" } }, + "core-js": { + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", + "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", + "dev": true + }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", @@ -428,224 +1019,39 @@ "dev": true }, "coveralls": { - "version": "2.13.3", - "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-2.13.3.tgz", - "integrity": "sha512-iiAmn+l1XqRwNLXhW8Rs5qHZRFMYp9ZIPjEOVRpC/c4so6Y/f4/lFi0FfR5B9cCqgyhkJ5cZmbvcVRfP8MHchw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.1.0.tgz", + "integrity": "sha512-sHxOu2ELzW8/NC1UP5XVLbZDzO4S3VxfFye3XYCznopHy02YjNkHcj5bKaVw2O7hVaBdBjEdQGpie4II1mWhuQ==", "dev": true, "requires": { - "js-yaml": "3.6.1", - "lcov-parse": "0.0.10", - "log-driver": "1.2.5", - "minimist": "1.2.0", - "request": "2.79.0" + "js-yaml": "^3.13.1", + "lcov-parse": "^1.0.0", + "log-driver": "^1.2.7", + "minimist": "^1.2.5", + "request": "^2.88.2" }, "dependencies": { - "assert-plus": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", - "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", - "dev": true - }, - "aws-sign2": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", - "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", - "dev": true - }, - "boom": { - "version": "2.10.1", - "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", - "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", - "dev": true, - "requires": { - "hoek": "2.x.x" - } - }, - "caseless": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", - "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=", - "dev": true - }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "cryptiles": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", - "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", - "dev": true, - "requires": { - "boom": "2.x.x" - } - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true - }, - "esprima": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", - "dev": true - }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "dev": true - }, - "form-data": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", - "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.5", - "mime-types": "^2.1.12" - } - }, - "hawk": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", - "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", - "dev": true, - "requires": { - "boom": "2.x.x", - "cryptiles": "2.x.x", - "hoek": "2.x.x", - "sntp": "1.x.x" - } - }, - "hoek": { - "version": "2.16.3", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", - "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", - "dev": true - }, - "http-signature": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", - "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", - "dev": true, - "requires": { - "assert-plus": "^0.2.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, - "js-yaml": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.6.1.tgz", - "integrity": "sha1-bl/mfYsgXOTSL60Ft3geja3MSzA=", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^2.6.0" - } - }, - "mime-types": { - "version": "2.1.24", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", - "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", - "dev": true, - "requires": { - "mime-db": "1.40.0" - } - }, "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - }, - "oauth-sign": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", - "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", - "dev": true - }, - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true - }, - "qs": { - "version": "6.3.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.3.2.tgz", - "integrity": "sha1-51vV9uJoEioqDgvaYwslUMFmUCw=", - "dev": true - }, - "request": { - "version": "2.79.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.79.0.tgz", - "integrity": "sha1-Tf5b9r6LjNw3/Pk+BLZVd3InEN4=", - "dev": true, - "requires": { - "aws-sign2": "~0.6.0", - "aws4": "^1.2.1", - "caseless": "~0.11.0", - "combined-stream": "~1.0.5", - "extend": "~3.0.0", - "forever-agent": "~0.6.1", - "form-data": "~2.1.1", - "har-validator": "~2.0.6", - "hawk": "~3.1.3", - "http-signature": "~1.1.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.7", - "oauth-sign": "~0.8.1", - "qs": "~6.3.0", - "stringstream": "~0.0.4", - "tough-cookie": "~2.3.0", - "tunnel-agent": "~0.4.1", - "uuid": "^3.0.0" - } - }, - "sntp": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", - "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", - "dev": true, - "requires": { - "hoek": "2.x.x" - } - }, - "tough-cookie": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", - "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", - "dev": true, - "requires": { - "punycode": "^1.4.1" - } - }, - "tunnel-agent": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", - "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", - "dev": true - }, - "uuid": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", "dev": true } } }, + "cp-file": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/cp-file/-/cp-file-6.2.0.tgz", + "integrity": "sha512-fmvV4caBnofhPe8kOcitBwSn2f39QLjnAnGq3gO9dfd75mUytzKNZB1hde6QHunW2Rt+OwuBOMc3i1tNElbszA==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "make-dir": "^2.0.0", + "nested-error-stacks": "^2.0.0", + "pify": "^4.0.1", + "safe-buffer": "^5.0.1" + } + }, "cross-spawn": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.2.tgz", @@ -656,23 +1062,6 @@ "which": "^1.2.9" } }, - "cryptiles": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-0.2.2.tgz", - "integrity": "sha1-7ZH/HxetE9N0gohZT4pIoNJvMlw=", - "dev": true, - "optional": true, - "requires": { - "boom": "0.4.x" - } - }, - "ctype": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/ctype/-/ctype-0.5.3.tgz", - "integrity": "sha1-gsGMJGH3QRTvFsE1IkrQuRRMoS8=", - "dev": true, - "optional": true - }, "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", @@ -680,14 +1069,6 @@ "dev": true, "requires": { "assert-plus": "^1.0.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } } }, "debug": { @@ -705,41 +1086,40 @@ "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", "dev": true }, - "deep-equal": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-0.1.2.tgz", - "integrity": "sha1-skbCuApXCkfBG+HZvRBw7IeLh84=", - "dev": true - }, "deep-is": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", "dev": true }, - "deeper": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/deeper/-/deeper-2.1.0.tgz", - "integrity": "sha1-vFZOX3MXT98gHgiwADDooU2nQ2g=", - "dev": true + "default-require-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-2.0.0.tgz", + "integrity": "sha1-9fj7sYp9bVCyH2QfZJ67Uiz+JPc=", + "dev": true, + "requires": { + "strip-bom": "^3.0.0" + } }, - "defined": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/defined/-/defined-0.0.0.tgz", - "integrity": "sha1-817qfXBekzuvE7LwOz+D2SFAOz4=", + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", "dev": true }, - "delayed-stream": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz", - "integrity": "sha1-1LH0OpPoKW3+AmlPRoC8N6MTxz8=", + "detect-indent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", + "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", "dev": true, - "optional": true + "requires": { + "repeating": "^2.0.0" + } }, "diff": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-1.4.0.tgz", - "integrity": "sha1-fyjS657nsVqX79ic5j3P2qPMur8=", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", "dev": true }, "docco": { @@ -764,10 +1144,10 @@ "esutils": "^2.0.2" } }, - "duplexer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", - "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", + "domain-browser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", "dev": true }, "ecc-jsbn": { @@ -780,6 +1160,12 @@ "safer-buffer": "^2.1.0" } }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, "error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -789,84 +1175,17 @@ "is-arrayish": "^0.2.1" } }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "escodegen": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", - "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", - "dev": true, - "requires": { - "esprima": "^2.7.1", - "estraverse": "^1.9.1", - "esutils": "^2.0.2", - "optionator": "^0.8.1", - "source-map": "~0.2.0" - }, - "dependencies": { - "esprima": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", - "dev": true - }, - "estraverse": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", - "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", - "dev": true - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - } - }, - "optionator": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", - "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", - "dev": true, - "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.4", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "wordwrap": "~1.0.0" - } - }, - "source-map": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", - "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", - "dev": true, - "optional": true, - "requires": { - "amdefine": ">=0.0.4" - } - }, - "wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", - "dev": true - } - } + "es6-error": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", + "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true }, "eslint": { "version": "4.18.2", @@ -1031,6 +1350,12 @@ "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", "dev": true }, + "esm": { + "version": "3.2.25", + "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz", + "integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==", + "dev": true + }, "espree": { "version": "3.5.4", "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", @@ -1099,24 +1424,6 @@ "integrity": "sha1-LUH1Y+H+QA7Uli/hpNXGp1Od9/Y=", "dev": true }, - "expand-brackets": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", - "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", - "dev": true, - "requires": { - "is-posix-bracket": "^0.1.0" - } - }, - "expand-range": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", - "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", - "dev": true, - "requires": { - "fill-range": "^2.1.0" - } - }, "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -1177,46 +1484,41 @@ "object-assign": "^4.0.1" } }, - "filename-regex": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", - "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", - "dev": true - }, "fill-range": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", - "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "dev": true, "requires": { - "is-number": "^2.1.0", - "isobject": "^2.0.0", - "randomatic": "^3.0.0", - "repeat-element": "^1.1.2", - "repeat-string": "^1.5.2" + "to-regex-range": "^5.0.1" } }, "find-cache-dir": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-0.1.1.tgz", - "integrity": "sha1-yN765XyKUqinhPnjHFfHQumToLk=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", "dev": true, "requires": { "commondir": "^1.0.1", - "mkdirp": "^0.5.1", - "pkg-dir": "^1.0.0" + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" } }, "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", "dev": true, "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" + "locate-path": "^3.0.0" } }, + "findit": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/findit/-/findit-2.0.0.tgz", + "integrity": "sha1-ZQnwEmr0wXhVHPqZOU4DLhOk1W4=", + "dev": true + }, "flat-cache": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz", @@ -1229,21 +1531,6 @@ "write": "^0.2.1" } }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true - }, - "for-own": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", - "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", - "dev": true, - "requires": { - "for-in": "^1.0.1" - } - }, "foreground-child": { "version": "1.5.6", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-1.5.6.tgz", @@ -1255,23 +1542,28 @@ } }, "forever-agent": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.5.2.tgz", - "integrity": "sha1-bQ4JxJIflKJ/Y9O0nF/v8epMUTA=", + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", "dev": true }, "form-data": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-0.1.4.tgz", - "integrity": "sha1-kavXiKupcCsaq/qLwBAxoqyeOxI=", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", "dev": true, - "optional": true, "requires": { - "async": "~0.9.0", - "combined-stream": "~0.0.4", - "mime": "~1.2.11" + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" } }, + "fs-exists-cached": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-exists-cached/-/fs-exists-cached-1.0.0.tgz", + "integrity": "sha1-zyVVTKBQ3EmuZla0HeQiWJidy84=", + "dev": true + }, "fs-extra": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-5.0.0.tgz", @@ -1289,29 +1581,36 @@ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "function-loop": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/function-loop/-/function-loop-1.0.2.tgz", + "integrity": "sha512-Iw4MzMfS3udk/rqxTiDDCllhGwlOrsr50zViTOO/W6lS/9y6B1J0BD2VZzrnWUYBJsl3aeqjgR5v7bWWhZSYbA==", + "dev": true + }, "functional-red-black-tree": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "dev": true }, - "generate-function": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", - "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", - "dev": true, - "requires": { - "is-property": "^1.0.2" - } - }, - "generate-object-property": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", - "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", - "dev": true, - "requires": { - "is-property": "^1.0.0" - } + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true }, "getpass": { "version": "0.1.7", @@ -1320,68 +1619,29 @@ "dev": true, "requires": { "assert-plus": "^1.0.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } } }, "glob": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", "dev": true, "requires": { + "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", - "minimatch": "2 || 3", + "minimatch": "^3.0.4", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, - "glob-base": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", - "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", - "dev": true, - "requires": { - "glob-parent": "^2.0.0", - "is-glob": "^2.0.0" - }, - "dependencies": { - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "^1.0.0" - } - } - } - }, "glob-parent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", - "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, "requires": { - "is-glob": "^2.0.0" - }, - "dependencies": { - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "^1.0.0" - } - } + "is-glob": "^4.0.1" } }, "globals": { @@ -1396,43 +1656,55 @@ "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", "dev": true }, - "handlebars": { - "version": "4.7.6", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.6.tgz", - "integrity": "sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA==", + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "dev": true + }, + "har-validator": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", "dev": true, "requires": { - "minimist": "^1.2.5", - "neo-async": "^2.6.0", - "source-map": "^0.6.1", - "uglify-js": "^3.1.4", - "wordwrap": "^1.0.0" + "ajv": "^6.12.3", + "har-schema": "^2.0.0" }, "dependencies": { - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, - "wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true } } }, - "har-validator": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", - "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=", + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "dev": true, "requires": { - "chalk": "^1.1.1", - "commander": "^2.9.0", - "is-my-json-valid": "^2.12.4", - "pinkie-promise": "^2.0.0" + "function-bind": "^1.1.1" } }, "has-ansi": { @@ -1445,22 +1717,18 @@ } }, "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, - "hawk": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/hawk/-/hawk-1.1.1.tgz", - "integrity": "sha1-h81JH5tG5OKurKM1QWdmiF0tHtk=", + "hasha": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hasha/-/hasha-3.0.0.tgz", + "integrity": "sha1-UqMvq4Vp1BymmmH/GiFPjrfIvTk=", "dev": true, - "optional": true, "requires": { - "boom": "0.4.x", - "cryptiles": "0.2.x", - "hoek": "0.9.x", - "sntp": "0.2.x" + "is-stream": "^1.0.1" } }, "highlight.js": { @@ -1469,29 +1737,37 @@ "integrity": "sha512-yR5lWvNz7c85OhVAEAeFhVCc/GV4C30Fjzc/rCP0aCWzc1UUOPUk55dK/qdwTZHBvMZo+eZ2jpk62ndX/xMFlg==", "dev": true }, - "hoek": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-0.9.1.tgz", - "integrity": "sha1-PTIkYrrfB3Fup+uFuviAec3c5QU=", + "home-or-tmp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", + "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", "dev": true, - "optional": true + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.1" + } }, "hosted-git-info": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", - "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "dev": true + }, + "html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, "http-signature": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-0.10.1.tgz", - "integrity": "sha1-T72sEyVZqoMjEh5UB3nAoBKyfmY=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", "dev": true, - "optional": true, "requires": { - "asn1": "0.1.11", - "assert-plus": "^0.1.5", - "ctype": "0.5.3" + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" } }, "iconv-lite": { @@ -1509,6 +1785,31 @@ "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", "dev": true }, + "import-jsx": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-jsx/-/import-jsx-2.0.0.tgz", + "integrity": "sha512-xmrgtiRnAdjIaRzKwsHut54FA8nx59WqN4MpQvPFr/8yD6BamavkmKHrA5dotAlnIiF4uqMzg/lA5yhPdpIXsA==", + "dev": true, + "requires": { + "babel-core": "^6.25.0", + "babel-plugin-transform-es2015-destructuring": "^6.23.0", + "babel-plugin-transform-object-rest-spread": "^6.23.0", + "babel-plugin-transform-react-jsx": "^6.24.1", + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" + }, + "dependencies": { + "caller-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", + "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=", + "dev": true, + "requires": { + "caller-callsite": "^2.0.0" + } + } + } + }, "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -1531,6 +1832,238 @@ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", "dev": true }, + "ink": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/ink/-/ink-2.7.1.tgz", + "integrity": "sha512-s7lJuQDJEdjqtaIWhp3KYHl6WV3J04U9zoQ6wVc+Xoa06XM27SXUY57qC5DO46xkF0CfgXMKkKNcgvSu/SAEpA==", + "dev": true, + "requires": { + "ansi-escapes": "^4.2.1", + "arrify": "^2.0.1", + "auto-bind": "^4.0.0", + "chalk": "^3.0.0", + "cli-cursor": "^3.1.0", + "cli-truncate": "^2.1.0", + "is-ci": "^2.0.0", + "lodash.throttle": "^4.1.1", + "log-update": "^3.0.0", + "prop-types": "^15.6.2", + "react-reconciler": "^0.24.0", + "scheduler": "^0.18.0", + "signal-exit": "^3.0.2", + "slice-ansi": "^3.0.0", + "string-length": "^3.1.0", + "widest-line": "^3.1.0", + "wrap-ansi": "^6.2.0", + "yoga-layout-prebuilt": "^1.9.3" + }, + "dependencies": { + "ansi-escapes": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz", + "integrity": "sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==", + "dev": true, + "requires": { + "type-fest": "^0.11.0" + } + }, + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "requires": { + "restore-cursor": "^3.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "requires": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + } + }, + "slice-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", + "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + } + }, + "string-length": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-3.1.0.tgz", + "integrity": "sha512-Ttp5YvkGm5v9Ijagtaz1BnN+k9ObpvS0eIBblPMp2YWL8FBmi9qblQ9fexc2k/CXFgrTIteU3jAw3payCnwSTA==", + "dev": true, + "requires": { + "astral-regex": "^1.0.0", + "strip-ansi": "^5.2.0" + }, + "dependencies": { + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "dev": true + } + } + }, + "string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + } + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + } + } + } + } + }, "inquirer": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", @@ -1621,18 +2154,14 @@ } } }, - "invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true - }, - "ip-regex": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz", - "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=", + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", "dev": true, - "optional": true + "requires": { + "loose-envify": "^1.0.0" + } }, "is-arrayish": { "version": "0.2.1", @@ -1640,103 +2169,64 @@ "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", "dev": true }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "is-dotfile": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", - "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", - "dev": true - }, - "is-equal-shallow": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", - "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, "requires": { - "is-primitive": "^2.0.0" + "binary-extensions": "^2.0.0" } }, - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", "dev": true, "requires": { - "number-is-nan": "^1.0.0" + "ci-info": "^2.0.0" } }, - "is-glob": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-1.1.3.tgz", - "integrity": "sha1-tMZLgwPTkRRJKkYNNkzPsNPAoEU=", - "dev": true - }, - "is-my-ip-valid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz", - "integrity": "sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ==", - "dev": true - }, - "is-my-json-valid": { - "version": "2.20.0", - "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.20.0.tgz", - "integrity": "sha512-XTHBZSIIxNsIsZXg7XB5l8z/OBFosl1Wao4tXLpeC7eKU4Vm/kdop2azkPqULwnfGQjmeDIyey9g7afMMtdWAA==", + "is-core-module": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz", + "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==", "dev": true, "requires": { - "generate-function": "^2.0.0", - "generate-object-property": "^1.1.0", - "is-my-ip-valid": "^1.0.0", - "jsonpointer": "^4.0.0", - "xtend": "^4.0.0" + "has": "^1.0.3" } }, - "is-number": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", - "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true }, - "is-posix-bracket": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", - "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", + "is-finite": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz", + "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==", "dev": true }, - "is-primitive": { + "is-fullwidth-code-point": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", - "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", "dev": true }, - "is-property": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", - "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true }, "is-resolvable": { @@ -1745,18 +2235,18 @@ "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", "dev": true }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", "dev": true }, - "is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true - }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", @@ -1769,72 +2259,154 @@ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.0.0" - } - }, "isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", "dev": true }, - "istanbul": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", - "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=", - "dev": true, - "requires": { - "abbrev": "1.0.x", - "async": "1.x", - "escodegen": "1.8.x", - "esprima": "2.7.x", - "glob": "^5.0.15", - "handlebars": "^4.0.1", - "js-yaml": "3.x", - "mkdirp": "0.5.x", - "nopt": "3.x", - "once": "1.x", - "resolve": "1.1.x", - "supports-color": "^3.1.0", - "which": "^1.1.1", - "wordwrap": "^1.0.0" + "istanbul-lib-coverage": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", + "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==", + "dev": true + }, + "istanbul-lib-hook": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-2.0.7.tgz", + "integrity": "sha512-vrRztU9VRRFDyC+aklfLoeXyNdTfga2EI3udDGn4cZ6fpSXpHLV9X6CHvfoMCPtggg8zvDDmC4b9xfu0z6/llA==", + "dev": true, + "requires": { + "append-transform": "^1.0.0" + } + }, + "istanbul-lib-instrument": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz", + "integrity": "sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==", + "dev": true, + "requires": { + "@babel/generator": "^7.4.0", + "@babel/parser": "^7.4.3", + "@babel/template": "^7.4.0", + "@babel/traverse": "^7.4.3", + "@babel/types": "^7.4.0", + "istanbul-lib-coverage": "^2.0.5", + "semver": "^6.0.0" }, "dependencies": { - "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true + } + } + }, + "istanbul-lib-processinfo": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-1.0.0.tgz", + "integrity": "sha512-FY0cPmWa4WoQNlvB8VOcafiRoB5nB+l2Pz2xGuXHRSy1KM8QFOYfz/rN+bGMCAeejrY3mrpF5oJHcN0s/garCg==", + "dev": true, + "requires": { + "archy": "^1.0.0", + "cross-spawn": "^6.0.5", + "istanbul-lib-coverage": "^2.0.3", + "rimraf": "^2.6.3", + "uuid": "^3.3.2" + }, + "dependencies": { + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } }, - "esprima": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "dev": true - }, + } + } + }, + "istanbul-lib-report": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz", + "integrity": "sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ==", + "dev": true, + "requires": { + "istanbul-lib-coverage": "^2.0.5", + "make-dir": "^2.1.0", + "supports-color": "^6.1.0" + }, + "dependencies": { "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "istanbul-lib-source-maps": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz", + "integrity": "sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^2.0.5", + "make-dir": "^2.1.0", + "rimraf": "^2.6.3", + "source-map": "^0.6.1" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", "dev": true, "requires": { - "has-flag": "^1.0.0" + "ms": "2.1.2" } }, - "wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true } } }, + "istanbul-reports": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.2.7.tgz", + "integrity": "sha512-uu1F/L1o5Y6LzPVSVZXNOoD/KXpJue9aeLRd0sM9uMXfZvzomB0WxVamWb5ue8kA2vVWEmW7EG+A5n3f1kqHKg==", + "dev": true, + "requires": { + "html-escaper": "^2.0.0" + } + }, + "jackspeak": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-1.4.0.tgz", + "integrity": "sha512-VDcSunT+wcccoG46FtzuBAyQKlzhHjli4q31e1fIHGOsRspqNUFjVzGb+7eIFDlTvqLygxapDHPHS0ouT2o/tw==", + "dev": true, + "requires": { + "cliui": "^4.1.0" + } + }, "js-tokens": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", @@ -1842,21 +2414,13 @@ "dev": true }, "js-yaml": { - "version": "3.4.5", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.4.5.tgz", - "integrity": "sha1-w0A3l98SuRhmV08t4jZG/oyvtE0=", + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, "requires": { - "argparse": "^1.0.2", - "esprima": "^2.6.0" - }, - "dependencies": { - "esprima": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", - "dev": true - } + "argparse": "^1.0.7", + "esprima": "^4.0.0" } }, "jsbn": { @@ -1865,6 +2429,18 @@ "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", "dev": true }, + "jsesc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", + "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", + "dev": true + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, "json-schema": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", @@ -1889,6 +2465,12 @@ "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", "dev": true }, + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true + }, "jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", @@ -1898,18 +2480,6 @@ "graceful-fs": "^4.1.6" } }, - "jsonify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", - "dev": true - }, - "jsonpointer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", - "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", - "dev": true - }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", @@ -1920,35 +2490,12 @@ "extsprintf": "1.3.0", "json-schema": "0.2.3", "verror": "1.10.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } - } - }, - "kind-of": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz", - "integrity": "sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ=", - "dev": true - }, - "lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "requires": { - "invert-kv": "^1.0.0" } }, "lcov-parse": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/lcov-parse/-/lcov-parse-0.0.10.tgz", - "integrity": "sha1-GwuP+ayceIklBYK3C3ExXZ2m2aM=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcov-parse/-/lcov-parse-1.0.0.tgz", + "integrity": "sha1-6w1GtUER68VhrLTECO+TY73I9+A=", "dev": true }, "levn": { @@ -1962,30 +2509,127 @@ } }, "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", "dev": true, "requires": { "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" } }, "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "lodash.flattendeep": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", + "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", + "dev": true + }, + "lodash.throttle": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", + "integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ=", "dev": true }, "log-driver": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.5.tgz", - "integrity": "sha1-euTsJXMC/XkNVXyxDJcQDYV7AFY=", + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.7.tgz", + "integrity": "sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg==", "dev": true }, + "log-update": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-3.4.0.tgz", + "integrity": "sha512-ILKe88NeMt4gmDvk/eb615U/IVn7K9KWGkoYbdatQ69Z65nj1ZzjM6fHXfcs0Uge+e+EGnMW7DY4T9yko8vWFg==", + "dev": true, + "requires": { + "ansi-escapes": "^3.2.0", + "cli-cursor": "^2.1.0", + "wrap-ansi": "^5.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + } + } + } + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, "lru-cache": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", @@ -1996,49 +2640,43 @@ "yallist": "^2.1.2" } }, - "marked": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/marked/-/marked-0.3.9.tgz", - "integrity": "sha512-nW5u0dxpXxHfkHzzrveY45gCbi+R4PaO4WRZYqZNl+vB0hVGeqlFn0aOg1c8AKL63TrNFn9Bm2UP4AdiZ9TPLw==", - "dev": true - }, - "math-random": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.4.tgz", - "integrity": "sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A==", - "dev": true - }, - "md5-hex": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/md5-hex/-/md5-hex-1.3.0.tgz", - "integrity": "sha1-0sSv6YPENwZiF5uMrRRSGRNQRsQ=", + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", "dev": true, "requires": { - "md5-o-matic": "^0.1.1" + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } } }, - "md5-o-matic": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/md5-o-matic/-/md5-o-matic-0.1.1.tgz", - "integrity": "sha1-givM1l4RfFFPqxdrJZRdVBAKA8M=", + "make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "marked": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/marked/-/marked-0.3.9.tgz", + "integrity": "sha512-nW5u0dxpXxHfkHzzrveY45gCbi+R4PaO4WRZYqZNl+vB0hVGeqlFn0aOg1c8AKL63TrNFn9Bm2UP4AdiZ9TPLw==", "dev": true }, - "micromatch": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.1.6.tgz", - "integrity": "sha1-UaZancv7khEykqBx4E2jWoHpBQ4=", + "merge-source-map": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz", + "integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==", "dev": true, "requires": { - "arr-diff": "^1.0.1", - "braces": "^1.8.0", - "debug": "^2.1.3", - "expand-brackets": "^0.1.1", - "filename-regex": "^2.0.0", - "is-glob": "^1.1.3", - "kind-of": "^1.1.0", - "object.omit": "^0.2.1", - "parse-glob": "^3.0.0", - "regex-cache": "^0.4.0" + "source-map": "^0.6.1" } }, "microtime": { @@ -2051,24 +2689,20 @@ "node-gyp-build": "^3.8.0" } }, - "mime": { - "version": "1.2.11", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz", - "integrity": "sha1-WCA+7Ybjpe8XrtK32evUfwpg3RA=", - "dev": true, - "optional": true - }, "mime-db": { - "version": "1.40.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", - "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==", + "version": "1.46.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.46.0.tgz", + "integrity": "sha512-svXaP8UQRZ5K7or+ZmfNhg2xX3yKDMUzqadsSqi4NCH/KomcH75MAMYAGVlvXn4+b/xOPhS3I2uHKRUzvjY7BQ==", "dev": true }, "mime-types": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-1.0.2.tgz", - "integrity": "sha1-mVrhOSq4r/y/yyZB3QVOlDwNXc4=", - "dev": true + "version": "2.1.29", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.29.tgz", + "integrity": "sha512-Y/jMt/S5sR9OaqteJtslsFZKWOIIqMACsJSiHghlCAyhf7jfVYjKBmLiX8OgpWeW+fjJ2b+Az69aPFPkUOY6xQ==", + "dev": true, + "requires": { + "mime-db": "1.46.0" + } }, "mimic-fn": { "version": "1.2.0", @@ -2091,6 +2725,30 @@ "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "dev": true }, + "minipass": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + } + } + }, "mkdirp": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", @@ -2118,10 +2776,16 @@ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "dev": true }, - "neo-async": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz", - "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==", + "nested-error-stacks": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/nested-error-stacks/-/nested-error-stacks-2.1.0.tgz", + "integrity": "sha512-AO81vsIO1k1sM4Zrd6Hu7regmJN1NSiAja10gc4bX3F0wd+9rQmcuHQaHVQCYIEC8iFXnE+mavh23GOt7wBgug==", + "dev": true + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", "dev": true }, "node-addon-api": { @@ -2136,21 +2800,6 @@ "integrity": "sha512-zLcTg6P4AbcHPq465ZMFNXx7XpKKJh+7kkN699NiQWisR2uWYOWNWqRHAmbnmKiL4e9aLSlmy5U7rEMUXV59+A==", "dev": true }, - "node-uuid": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz", - "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc=", - "dev": true - }, - "nopt": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", - "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "dev": true, - "requires": { - "abbrev": "1" - } - }, "normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", @@ -2161,86 +2810,66 @@ "resolve": "^1.10.0", "semver": "2 || 3 || 4 || 5", "validate-npm-package-license": "^3.0.1" - }, - "dependencies": { - "resolve": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.0.tgz", - "integrity": "sha512-WL2pBDjqT6pGUNSUzMw00o4T7If+z4H2x3Gz893WoUQ5KW8Vr9txp00ykiP16VBaZF5+j/OcXJHZ9+PCvdiDKw==", - "dev": true, - "requires": { - "path-parse": "^1.0.6" - } - } } }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, "number-is-nan": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", "dev": true - }, - "nyc": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/nyc/-/nyc-5.6.0.tgz", - "integrity": "sha1-DrOU0W8++f8bRA/ZOxp6tTAJJ1Q=", - "dev": true, - "requires": { - "append-transform": "^0.2.0", - "arrify": "^1.0.1", - "caching-transform": "^1.0.0", - "convert-source-map": "^1.1.2", - "find-cache-dir": "^0.1.1", - "foreground-child": "^1.3.5", - "glob": "^6.0.2", - "istanbul": "^0.4.1", - "md5-hex": "^1.2.0", - "micromatch": "~2.1.6", - "mkdirp": "^0.5.0", - "pkg-up": "^1.0.0", - "read-pkg": "^1.1.0", - "resolve-from": "^2.0.0", - "rimraf": "^2.5.0", - "signal-exit": "^2.1.1", - "source-map": "^0.5.3", - "spawn-wrap": "^1.1.1", - "strip-bom": "^2.0.0", - "yargs": "^3.15.0" - }, - "dependencies": { - "glob": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", - "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=", - "dev": true, - "requires": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "2 || 3", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "signal-exit": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-2.1.2.tgz", - "integrity": "sha1-N1h5sfkuvDszRIDQONxUam1VhWQ=", - "dev": true - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + }, + "nyc": { + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/nyc/-/nyc-14.1.1.tgz", + "integrity": "sha512-OI0vm6ZGUnoGZv/tLdZ2esSVzDwUC88SNs+6JoSOMVxA+gKMB8Tk7jBwgemLx4O40lhhvZCVw1C+OYLOBOPXWw==", + "dev": true, + "requires": { + "archy": "^1.0.0", + "caching-transform": "^3.0.2", + "convert-source-map": "^1.6.0", + "cp-file": "^6.2.0", + "find-cache-dir": "^2.1.0", + "find-up": "^3.0.0", + "foreground-child": "^1.5.6", + "glob": "^7.1.3", + "istanbul-lib-coverage": "^2.0.5", + "istanbul-lib-hook": "^2.0.7", + "istanbul-lib-instrument": "^3.3.0", + "istanbul-lib-report": "^2.0.8", + "istanbul-lib-source-maps": "^3.0.6", + "istanbul-reports": "^2.2.4", + "js-yaml": "^3.13.1", + "make-dir": "^2.1.0", + "merge-source-map": "^1.1.0", + "resolve-from": "^4.0.0", + "rimraf": "^2.6.3", + "signal-exit": "^3.0.2", + "spawn-wrap": "^1.4.2", + "test-exclude": "^5.2.3", + "uuid": "^3.3.2", + "yargs": "^13.2.2", + "yargs-parser": "^13.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true } } }, "oauth-sign": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.4.0.tgz", - "integrity": "sha1-8ilW8x6nFRqCHl8vsywRPK2Ln2k=", - "dev": true, - "optional": true + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true }, "object-assign": { "version": "4.1.1", @@ -2248,24 +2877,6 @@ "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", "dev": true }, - "object.omit": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-0.2.1.tgz", - "integrity": "sha1-ypr2Yx32iD/mG65034Kk+8nfLpI=", - "dev": true, - "requires": { - "for-own": "^0.1.1", - "isobject": "^0.2.0" - }, - "dependencies": { - "isobject": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-0.2.0.tgz", - "integrity": "sha1-o0MhkvObkQtfAsyYlIeDbscKqF4=", - "dev": true - } - } - }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -2284,16 +2895,10 @@ "mimic-fn": "^1.0.0" } }, - "only-shallow": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/only-shallow/-/only-shallow-1.2.0.tgz", - "integrity": "sha1-cc7O26kyS8BRiu8Q7AgNMkncJGU=", - "dev": true - }, "opener": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.1.tgz", - "integrity": "sha512-goYSy5c2UXE4Ra1xixabeVh1guIX/ZV/YokJksb6q2lubWu6UbvPQ20p542/sFIll1nl8JnCyK9oBaOcCWXwvA==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", + "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", "dev": true }, "optionator": { @@ -2316,61 +2921,86 @@ "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "dev": true }, - "os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, - "requires": { - "lcid": "^1.0.0" - } - }, "os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true }, - "parse-glob": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", - "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "own-or": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/own-or/-/own-or-1.0.0.tgz", + "integrity": "sha1-Tod/vtqaLsgAD7wLyuOWRe6L+Nw=", + "dev": true + }, + "own-or-env": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/own-or-env/-/own-or-env-1.0.1.tgz", + "integrity": "sha512-y8qULRbRAlL6x2+M0vIe7jJbJx/kmUTzYonRAa2ayesR2qWLswninkVyeJe4x3IEXhdgoNodzjQRKAoEs6Fmrw==", + "dev": true, + "requires": { + "own-or": "^1.0.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "package-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-3.0.0.tgz", + "integrity": "sha512-lOtmukMDVvtkL84rJHI7dpTYq+0rli8N2wlnqUcBuDWCfVhRUfOmnR9SsoHFMLpACvEV60dX7rd0rFaYDZI+FA==", "dev": true, "requires": { - "glob-base": "^0.3.0", - "is-dotfile": "^1.0.0", - "is-extglob": "^1.0.0", - "is-glob": "^2.0.0" + "graceful-fs": "^4.1.15", + "hasha": "^3.0.0", + "lodash.flattendeep": "^4.4.0", + "release-zalgo": "^1.0.0" }, "dependencies": { - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "^1.0.0" - } + "graceful-fs": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", + "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==", + "dev": true } } }, "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", "dev": true, "requires": { - "error-ex": "^1.2.0" + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" } }, "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "requires": { - "pinkie-promise": "^2.0.0" - } + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true }, "path-is-absolute": { "version": "1.0.1", @@ -2384,6 +3014,12 @@ "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", "dev": true }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, "path-parse": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", @@ -2391,53 +3027,47 @@ "dev": true }, "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" + "pify": "^3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } } }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", "dev": true }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "picomatch": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", "dev": true }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, - "requires": { - "pinkie": "^2.0.0" - } + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true }, "pkg-dir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", - "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", - "dev": true, - "requires": { - "find-up": "^1.0.0" - } - }, - "pkg-up": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-1.0.0.tgz", - "integrity": "sha1-Pgj7RhUlxEIWJKM7n35tCvWwWiY=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", "dev": true, "requires": { - "find-up": "^1.0.0" + "find-up": "^3.0.0" } }, "platform": { @@ -2458,10 +3088,10 @@ "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", "dev": true }, - "preserve": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", - "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "private": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", "dev": true }, "process-nextick-args": { @@ -2476,6 +3106,17 @@ "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "dev": true }, + "prop-types": { + "version": "15.7.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", + "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "dev": true, + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.8.1" + } + }, "pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", @@ -2483,59 +3124,71 @@ "dev": true }, "psl": { - "version": "1.1.32", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.32.tgz", - "integrity": "sha512-MHACAkHpihU/REGGPLj4sEfc/XKW2bheigvHO1dUqjaKigMp1C8+WLQYRGgeKFMsw5PMfegZcaN8IDXK/cD0+g==", - "dev": true, - "optional": true + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", + "dev": true }, "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true, - "optional": true + "dev": true }, "qs": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-1.2.2.tgz", - "integrity": "sha1-GbV/8k3CqZzh+L32r82ln472H4g=", + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", "dev": true }, - "randomatic": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz", - "integrity": "sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==", + "react": { + "version": "16.14.0", + "resolved": "https://registry.npmjs.org/react/-/react-16.14.0.tgz", + "integrity": "sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g==", "dev": true, "requires": { - "is-number": "^4.0.0", - "kind-of": "^6.0.0", - "math-random": "^1.0.1" - }, - "dependencies": { - "is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - } + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2" + } + }, + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true + }, + "react-reconciler": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/react-reconciler/-/react-reconciler-0.24.0.tgz", + "integrity": "sha512-gAGnwWkf+NOTig9oOowqid9O0HjTDC+XVGBCAmJYYJ2A2cN/O4gDdIuuUQjv8A4v6GDwVfJkagpBBLW5OW9HSw==", + "dev": true, + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2", + "scheduler": "^0.18.0" } }, "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", "dev": true, "requires": { - "load-json-file": "^1.0.0", + "load-json-file": "^4.0.0", "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" + "path-type": "^3.0.0" + } + }, + "read-pkg-up": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-4.0.0.tgz", + "integrity": "sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA==", + "dev": true, + "requires": { + "find-up": "^3.0.0", + "read-pkg": "^3.0.0" } }, "readable-stream": { @@ -2553,91 +3206,96 @@ "util-deprecate": "~1.0.1" } }, - "regex-cache": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", - "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "readdirp": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", + "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", "dev": true, "requires": { - "is-equal-shallow": "^0.1.3" + "picomatch": "^2.2.1" } }, - "repeat-element": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", - "dev": true + "redeyed": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/redeyed/-/redeyed-2.1.1.tgz", + "integrity": "sha1-iYS1gV2ZyyIEacme7v/jiRPmzAs=", + "dev": true, + "requires": { + "esprima": "~4.0.0" + } }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", "dev": true }, + "release-zalgo": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", + "integrity": "sha1-CXALflB0Mpc5Mw5TXFqQ+2eFFzA=", + "dev": true, + "requires": { + "es6-error": "^4.0.1" + } + }, + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "dev": true, + "requires": { + "is-finite": "^1.0.0" + } + }, "request": { - "version": "2.42.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.42.0.tgz", - "integrity": "sha1-VyvQFIk4VkBArHqxSLlkI6BjMEo=", - "dev": true, - "requires": { - "aws-sign2": "~0.5.0", - "bl": "~0.9.0", - "caseless": "~0.6.0", - "forever-agent": "~0.5.0", - "form-data": "~0.1.0", - "hawk": "1.1.1", - "http-signature": "~0.10.0", - "json-stringify-safe": "~5.0.0", - "mime-types": "~1.0.1", - "node-uuid": "~1.4.0", - "oauth-sign": "~0.4.0", - "qs": "~1.2.0", - "stringstream": "~0.0.4", - "tough-cookie": ">=0.12.0", - "tunnel-agent": "~0.4.0" + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "dev": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" }, "dependencies": { - "bl": { - "version": "0.9.5", - "resolved": "https://registry.npmjs.org/bl/-/bl-0.9.5.tgz", - "integrity": "sha1-wGt5evCF6gC8Unr8jvzxHeIjIFQ=", - "dev": true, - "requires": { - "readable-stream": "~1.0.26" - } - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "tunnel-agent": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", - "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "dev": true } } }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, "require-uncached": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", @@ -2657,15 +3315,19 @@ } }, "resolve": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", - "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", - "dev": true + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dev": true, + "requires": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + } }, "resolve-from": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", - "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", "dev": true }, "restore-cursor": { @@ -2678,15 +3340,6 @@ "signal-exit": "^3.0.2" } }, - "resumer": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/resumer/-/resumer-0.0.0.tgz", - "integrity": "sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k=", - "dev": true, - "requires": { - "through": "~2.3.4" - } - }, "rimraf": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", @@ -2745,12 +3398,28 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true }, + "scheduler": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.18.0.tgz", + "integrity": "sha512-agTSHR1Nbfi6ulI0kYNK0203joW2Y5W4po4l+v03tOoiJKpTBbxpNhWDvqc/4IcOw+KLmSiQLTasZ4cab2/UWQ==", + "dev": true, + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + }, "semver": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", "dev": true }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, "shebang-command": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", @@ -2772,6 +3441,12 @@ "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "dev": true }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dev": true + }, "slice-ansi": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", @@ -2789,32 +3464,26 @@ } } }, - "slide": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz", - "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=", - "dev": true - }, - "sntp": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/sntp/-/sntp-0.2.4.tgz", - "integrity": "sha1-+4hfGLDzqtGJ+CSGJTa87ux1CQA=", - "dev": true, - "optional": true, - "requires": { - "hoek": "0.9.x" - } - }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true }, + "source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, "spawn-wrap": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-1.4.2.tgz", - "integrity": "sha512-vMwR3OmmDhnxCVxM8M+xO/FtIp6Ju/mNaDfCMMW7FDcLRTPFWUswec4LXJHTJE2hwTI9O0YBfygu4DalFl7Ylg==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-1.4.3.tgz", + "integrity": "sha512-IgB8md0QW/+tWqcavuFgKYR/qIRvJkRLPJDFaoXtLLUaVcCDK0+HeFTkmQHj3eprcYhc+gOl0aEA1w7qZlYezw==", "dev": true, "requires": { "foreground-child": "^1.5.6", @@ -2826,9 +3495,9 @@ } }, "spdx-correct": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", - "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", "dev": true, "requires": { "spdx-expression-parse": "^3.0.0", @@ -2836,15 +3505,15 @@ } }, "spdx-exceptions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", - "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", "dev": true }, "spdx-expression-parse": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", - "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", "dev": true, "requires": { "spdx-exceptions": "^2.1.0", @@ -2852,20 +3521,11 @@ } }, "spdx-license-ids": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.4.tgz", - "integrity": "sha512-7j8LYJLeY/Yb6ACbQ7F76qy5jHkp0U6jgBfJsk97bwWlVUnUWsAgpyaCvo17h0/RQGnQ036tVDomiwoI4pDkQA==", + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.7.tgz", + "integrity": "sha512-U+MTEOO0AiDzxwFvoa4JVnMV6mZlJKk2sBLt90s7G0Gd0Mlknc7kxEn3nuDPNZRta7O2uy8oLcZLVT+4sqNZHQ==", "dev": true }, - "split": { - "version": "0.2.10", - "resolved": "https://registry.npmjs.org/split/-/split-0.2.10.tgz", - "integrity": "sha1-Zwl8YB1pfOE2j0GPBs0gHPBSGlc=", - "dev": true, - "requires": { - "through": "2" - } - }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -2887,45 +3547,85 @@ "jsbn": "~0.1.0", "safer-buffer": "^2.0.2", "tweetnacl": "~0.14.0" + } + }, + "stack-utils": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-1.0.4.tgz", + "integrity": "sha512-IPDJfugEGbfizBwBZRZ3xpccMdRyP5lqsBWXGQWimVjua/ccLCeMOAVjlc1R7LxFjo5sEDhyNIXd8mo/AiDS9w==", + "dev": true, + "requires": { + "escape-string-regexp": "^2.0.0" + }, + "dependencies": { + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true + } + } + }, + "string-length": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-2.0.0.tgz", + "integrity": "sha1-1A27aGo6zpYMHP/KVivyxF+DY+0=", + "dev": true, + "requires": { + "astral-regex": "^1.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" }, "dependencies": { - "asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { - "safer-buffer": "~2.1.0" + "ansi-regex": "^3.0.0" } - }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true } } }, - "stream-combiner": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", - "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", - "dev": true, - "requires": { - "duplexer": "~0.1.1" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, "string_decoder": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", @@ -2935,12 +3635,6 @@ "safe-buffer": "~5.1.0" } }, - "stringstream": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.6.tgz", - "integrity": "sha512-87GEBAkegbBcweToUrdzf3eLhWNg06FJTebl4BVJz/JgWy8CvEr9dRtX5qWphiynMSQlxxi+QqN0z5T32SLlhA==", - "dev": true - }, "strip-ansi": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", @@ -2951,13 +3645,10 @@ } }, "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "^0.2.0" - } + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true }, "strip-json-comments": { "version": "2.0.1", @@ -3054,60 +3745,58 @@ } }, "tap": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/tap/-/tap-4.0.0.tgz", - "integrity": "sha1-bjufJycMgSsEGsKsSMjPTDmwncs=", + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/tap/-/tap-14.0.0.tgz", + "integrity": "sha512-4690TGCbBTwyIhJWH918o/1zLoWUqc+8o0/zQtLjFLzQ76vlurNtMfVLkVS9dNztjuv01fgol+YhNJbzg/dfUA==", "dev": true, "requires": { - "codecov.io": "^0.1.6", - "coveralls": "^2.11.2", - "deeper": "^2.1.0", - "foreground-child": "^1.2.0", - "glob": "^6.0.1", - "js-yaml": "^3.3.1", - "mkdirp": "^0.5.0", - "nyc": "^5.1.0", - "only-shallow": "^1.0.2", - "opener": "^1.4.1", - "readable-stream": "^2.0.2", - "signal-exit": "^2.0.0", - "supports-color": "^1.3.1", - "tap-mocha-reporter": "0.0 || 1", - "tap-parser": "^1.2.2", - "tmatch": "^1.0.2" - }, - "dependencies": { - "glob": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", - "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=", - "dev": true, - "requires": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "2 || 3", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "signal-exit": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-2.1.2.tgz", - "integrity": "sha1-N1h5sfkuvDszRIDQONxUam1VhWQ=", - "dev": true - }, - "supports-color": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-1.3.1.tgz", - "integrity": "sha1-FXWN8J2P87SswwdTn6vicJXhBC0=", - "dev": true - } + "async-hook-domain": "^1.1.0", + "bind-obj-methods": "^2.0.0", + "browser-process-hrtime": "^1.0.0", + "capture-stack-trace": "^1.0.0", + "chokidar": "^3.0.0", + "color-support": "^1.1.0", + "coveralls": "^3.0.3", + "diff": "^4.0.1", + "domain-browser": "^1.2.0", + "esm": "^3.2.25", + "findit": "^2.0.0", + "foreground-child": "^1.3.3", + "fs-exists-cached": "^1.0.0", + "function-loop": "^1.0.2", + "glob": "^7.1.4", + "import-jsx": "^2.0.0", + "isexe": "^2.0.0", + "istanbul-lib-processinfo": "^1.0.0", + "jackspeak": "^1.3.8", + "minipass": "^2.3.5", + "mkdirp": "^0.5.1", + "nyc": "^14.1.0", + "opener": "^1.5.1", + "own-or": "^1.0.0", + "own-or-env": "^1.0.1", + "rimraf": "^2.6.3", + "signal-exit": "^3.0.0", + "source-map-support": "^0.5.12", + "stack-utils": "^1.0.2", + "tap-mocha-reporter": "^4.0.1", + "tap-parser": "^9.3.2", + "tap-yaml": "^1.0.0", + "tcompare": "^2.3.0", + "treport": "^0.3.0", + "trivial-deferred": "^1.0.1", + "ts-node": "^8.1.0", + "typescript": "^3.4.5", + "which": "^1.3.1", + "write-file-atomic": "^2.4.2", + "yaml": "^1.5.1", + "yapool": "^1.0.0" } }, "tap-mocha-reporter": { - "version": "0.0.27", - "resolved": "https://registry.npmjs.org/tap-mocha-reporter/-/tap-mocha-reporter-0.0.27.tgz", - "integrity": "sha1-svcvPh6Lp4DuApGPzes6QNqAGPc=", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/tap-mocha-reporter/-/tap-mocha-reporter-4.0.1.tgz", + "integrity": "sha512-/KfXaaYeSPn8qBi5Be8WSIP3iKV83s2uj2vzImJAXmjNu22kzqZ+1Dv1riYWa53sPCiyo1R1w1jbJrftF8SpcQ==", "dev": true, "requires": { "color-support": "^1.1.0", @@ -3115,81 +3804,67 @@ "diff": "^1.3.2", "escape-string-regexp": "^1.0.3", "glob": "^7.0.5", - "js-yaml": "^3.3.1", - "readable-stream": "^1.1.13", - "tap-parser": "^1.0.4", + "readable-stream": "^2.1.5", + "tap-parser": "^8.0.0", + "tap-yaml": "0 || 1", "unicode-length": "^1.0.0" }, "dependencies": { - "glob": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", - "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true, - "optional": true + "diff": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-1.4.0.tgz", + "integrity": "sha1-fyjS657nsVqX79ic5j3P2qPMur8=", + "dev": true }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "tap-parser": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/tap-parser/-/tap-parser-8.1.0.tgz", + "integrity": "sha512-GgOzgDwThYLxhVR83RbS1JUR1TxcT+jfZsrETgPAvFdr12lUOnuvrHOBaUQgpkAp6ZyeW6r2Nwd91t88M0ru3w==", "dev": true, - "optional": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" + "events-to-array": "^1.0.1", + "minipass": "^2.2.0", + "tap-yaml": "0 || 1" } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true, - "optional": true } } }, "tap-parser": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/tap-parser/-/tap-parser-1.3.2.tgz", - "integrity": "sha1-EgxQiciMPIp5PvKIhn3jIeGPjCI=", + "version": "9.3.3", + "resolved": "https://registry.npmjs.org/tap-parser/-/tap-parser-9.3.3.tgz", + "integrity": "sha512-VlC7tlSZ3EGt2qPLSa9CTJepNkc2yCh7uzhzAF5DxnuujeKbFbKxMA+fxtTWEN2j/KgfGi+mgooiZPKkOhEQyw==", "dev": true, "requires": { "events-to-array": "^1.0.1", - "inherits": "~2.0.1", - "js-yaml": "^3.2.7", - "readable-stream": "^2" + "minipass": "^2.2.0", + "tap-yaml": "^1.0.0" } }, - "tape": { + "tap-yaml": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/tap-yaml/-/tap-yaml-1.0.0.tgz", + "integrity": "sha512-Rxbx4EnrWkYk0/ztcm5u3/VznbyFJpyXO12dDBHKWiDVxy7O2Qw6MRrwO5H6Ww0U5YhRY/4C/VzWmFPhBQc4qQ==", + "dev": true, + "requires": { + "yaml": "^1.5.0" + } + }, + "tcompare": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tape/-/tape-2.3.0.tgz", - "integrity": "sha1-Df7scJIn+8yRcKvn8EaWKycUMds=", + "resolved": "https://registry.npmjs.org/tcompare/-/tcompare-2.3.0.tgz", + "integrity": "sha512-fAfA73uFtFGybWGt4+IYT6UPLYVZQ4NfsP+IXEZGY0vh8e2IF7LVKafcQNMRBLqP0wzEA65LM9Tqj+FSmO8GLw==", + "dev": true + }, + "test-exclude": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.3.tgz", + "integrity": "sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g==", "dev": true, "requires": { - "deep-equal": "~0.1.0", - "defined": "~0.0.0", - "inherits": "~2.0.1", - "jsonify": "~0.0.0", - "resumer": "~0.0.0", - "split": "~0.2.10", - "stream-combiner": "~0.0.2", - "through": "~2.3.4" + "glob": "^7.1.3", + "minimatch": "^3.0.4", + "read-pkg-up": "^4.0.0", + "require-main-filename": "^2.0.0" } }, "text-table": { @@ -3204,12 +3879,6 @@ "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", "dev": true }, - "tmatch": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/tmatch/-/tmatch-1.0.2.tgz", - "integrity": "sha1-RYx5SN4L1SLHgfxBI1dpqjxEclc=", - "dev": true - }, "tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", @@ -3219,18 +3888,129 @@ "os-tmpdir": "~1.0.2" } }, + "to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, "tough-cookie": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-3.0.1.tgz", - "integrity": "sha512-yQyJ0u4pZsv9D4clxO69OEjLWYw+jbgspjTue4lTQZLfV0c5l1VmK2y1JK8E9ahdpltPOaAThPcp5nKPUgSnsg==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", "dev": true, - "optional": true, "requires": { - "ip-regex": "^2.1.0", "psl": "^1.1.28", "punycode": "^2.1.1" } }, + "treport": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/treport/-/treport-0.3.0.tgz", + "integrity": "sha512-THr7NS5iLJewcAiaBkxAuCVoakw84hAVY9n2kFNZqlFKHrZeGw8sNR4VhmT23JB1/JnCmPcIOmooTdYYVTI5hA==", + "dev": true, + "requires": { + "cardinal": "^2.1.1", + "chalk": "^2.4.2", + "import-jsx": "^2.0.0", + "ink": "^2.1.1", + "ms": "^2.1.1", + "react": "^16.8.6", + "string-length": "^2.0.0", + "tap-parser": "^9.3.2", + "unicode-length": "^2.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "unicode-length": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unicode-length/-/unicode-length-2.0.2.tgz", + "integrity": "sha512-Ph/j1VbS3/r77nhoY2WU0GWGjVYOHL3xpKp0y/Eq2e5r0mT/6b649vm7KFO6RdAdrZkYLdxphYVgvODxPB+Ebg==", + "dev": true, + "requires": { + "punycode": "^2.0.0", + "strip-ansi": "^3.0.1" + } + } + } + }, + "trim-right": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", + "dev": true + }, + "trivial-deferred": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trivial-deferred/-/trivial-deferred-1.0.1.tgz", + "integrity": "sha1-N21NKdlR1jaKb3oK6FwvTV4GWPM=", + "dev": true + }, + "ts-node": { + "version": "8.10.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.10.2.tgz", + "integrity": "sha512-ISJJGgkIpDdBhWVu3jufsWpK3Rzo7bdiIXJjQc0ynKxVOVcg2oIrf2H2cejminGrptVc6q6/uynAHNCuWGbpVA==", + "dev": true, + "requires": { + "arg": "^4.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "source-map-support": "^0.5.17", + "yn": "3.1.1" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "requires": { + "safe-buffer": "^5.0.1" + } + }, "tweetnacl": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", @@ -3246,31 +4026,23 @@ "prelude-ls": "~1.1.2" } }, + "type-fest": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz", + "integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==", + "dev": true + }, "typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", "dev": true }, - "uglify-js": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.0.tgz", - "integrity": "sha512-W+jrUHJr3DXKhrsS7NUVxn3zqMOFn0hL/Ei6v0anCIMoKC93TjcflTagwIHLW7SfMFfiQuktQyFVCFHGUE0+yg==", - "dev": true, - "optional": true, - "requires": { - "commander": "~2.20.0", - "source-map": "~0.6.1" - }, - "dependencies": { - "commander": { - "version": "2.20.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", - "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==", - "dev": true, - "optional": true - } - } + "typescript": { + "version": "3.9.9", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.9.tgz", + "integrity": "sha512-kdMjTiekY+z/ubJCATUPlRDl39vXYiMV9iyeMuEuXZh2we6zz80uovNN2WlAxmmdE/Z/YQe+EbOEXB5RHEED3w==", + "dev": true }, "underscore": { "version": "1.8.3", @@ -3302,13 +4074,13 @@ "integrity": "sha1-+nG63UQ3r0wUiEHjs7Fl+enlkLc=", "dev": true }, - "urlgrey": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/urlgrey/-/urlgrey-0.4.0.tgz", - "integrity": "sha1-8GU1cED7NcOzEdTl3DZITZbb6gY=", + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, "requires": { - "tape": "2.3.0" + "punycode": "^2.1.0" } }, "util-deprecate": { @@ -3317,6 +4089,12 @@ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true + }, "validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", @@ -3336,14 +4114,6 @@ "assert-plus": "^1.0.0", "core-util-is": "1.0.2", "extsprintf": "^1.2.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } } }, "which": { @@ -3355,12 +4125,61 @@ "isexe": "^2.0.0" } }, - "window-size": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", - "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY=", + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, + "widest-line": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "dev": true, + "requires": { + "string-width": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + } + } + }, "word-wrap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", @@ -3375,6 +4194,28 @@ "requires": { "string-width": "^1.0.1", "strip-ansi": "^3.0.1" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } } }, "wrappy": { @@ -3393,26 +4234,20 @@ } }, "write-file-atomic": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-1.3.4.tgz", - "integrity": "sha1-+Aek8LHZ6ROuekgRLmzDrxmRtF8=", + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", + "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", "dev": true, "requires": { "graceful-fs": "^4.1.11", "imurmurhash": "^0.1.4", - "slide": "^1.1.5" + "signal-exit": "^3.0.2" } }, - "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", - "dev": true - }, "y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz", + "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==", "dev": true }, "yallist": { @@ -3421,19 +4256,118 @@ "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", "dev": true }, + "yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true + }, + "yapool": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/yapool/-/yapool-1.0.0.tgz", + "integrity": "sha1-9pPymjFbUNmp2iZGp6ZkXJaYW2o=", + "dev": true + }, "yargs": { - "version": "3.32.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz", - "integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=", + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "dev": true, + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + } + } + } + }, + "yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", "dev": true, "requires": { - "camelcase": "^2.0.1", - "cliui": "^3.0.3", - "decamelize": "^1.1.1", - "os-locale": "^1.4.0", - "string-width": "^1.0.1", - "window-size": "^0.1.4", - "y18n": "^3.2.0" + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true + }, + "yoga-layout-prebuilt": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/yoga-layout-prebuilt/-/yoga-layout-prebuilt-1.10.0.tgz", + "integrity": "sha512-YnOmtSbv4MTf7RGJMK0FvZ+KD8OEe/J5BNnR0GHhD8J/XcG/Qvxgszm0Un6FTHWW4uHlTgP0IztiXQnGyIR45g==", + "dev": true, + "requires": { + "@types/yoga-layout": "1.9.2" } } } diff --git a/package.json b/package.json index d63f2d2..cbdae08 100644 --- a/package.json +++ b/package.json @@ -23,16 +23,15 @@ "lib": "./lib/memjs" }, "scripts": { - "test": "eslint ./lib/memjs/ ./test/ && tap -R spec ./test/*.js", + "test": "eslint ./lib/memjs/ ./test/ && tap --no-coverage -R spec ./test/*.js", "bench": "NODE_PATH=lib/memjs/ node bench/memjs.js", "bench-timers": "NODE_PATH=lib/memjs/ node bench/timers.js" }, - "dependencies": {}, "devDependencies": { "benchmark": "^2.1.4", "docco": "^0.8.0", "eslint": "4.18.2", "microtime": "^3.0.0", - "tap": "4.0.*" + "tap": "14.0.*" } } diff --git a/test/client_test.js b/test/client_test.js index 25a7af9..c4a2fb0 100644 --- a/test/client_test.js +++ b/test/client_test.js @@ -1,10 +1,20 @@ -var test = require('tap').test; +var tap = require('tap'); +var test = tap.test; + var errors = require('../lib/memjs/protocol').errors; var MemJS = require('../'); +var constants = require('../lib/memjs/constants'); + +function testAllCallbacksEmpty(t, server) { + t.deepEqual(Object.keys(server.responseCallbacks).length, 0); + t.deepEqual(Object.keys(server.errorCallbacks).length, 0); + + t.deepEqual(server.requestTimeouts, []); +} test('GetSuccessful', function(t) { var n = 0; - var dummyServer = new MemJS.Server(); + var dummyServer = new MemJS.Server('dummyServer'); dummyServer.write = function(requestBuf) { var request = MemJS.Utils.parseMessage(requestBuf); t.equal('hello', request.key.toString()); @@ -30,7 +40,7 @@ test('GetSuccessful', function(t) { test('GetNotFound', function(t) { var n = 0; - var dummyServer = new MemJS.Server(); + var dummyServer = new MemJS.Server('dummyServer'); dummyServer.write = function(requestBuf) { var request = MemJS.Utils.parseMessage(requestBuf); t.equal('hello', request.key.toString()); @@ -44,19 +54,19 @@ test('GetNotFound', function(t) { t.equal(null, val); t.equal(null, flags); t.equal(1, n, 'Ensure get is called'); - t.end(); }; client.get('hello', assertor); n = 0; return client.get('hello').then(function(res) { assertor(null, res.value, res.extras); + t.end(); }); }); test('GetSerializer', function(t) { var n = 0; var dn = 0; - var dummyServer = new MemJS.Server(); + var dummyServer = new MemJS.Server('dummyServer'); dummyServer.write = function(requestBuf) { var request = MemJS.Utils.parseMessage(requestBuf); t.equal('hello', request.key.toString()); @@ -92,9 +102,239 @@ test('GetSerializer', function(t) { }); }); +tap.only('GetMultiSuccessful_SingleBackend', function(t) { + var n = 0; + var dummyServer = new MemJS.Server('dummyServer'); + dummyServer.write = function(requestBuf) { + var requests = MemJS.Utils.parseMessages(requestBuf); + t.equal(requests.length, 4); + n += 1; + + function checkAndRespond(request, key, value) { + t.equal(key, request.key.toString()); + t.equal(constants.OP_GETKQ, request.header.opcode); + + dummyServer.respond( + {header: {status: 0, opaque: request.header.opaque, opcode: request.header.opcode}, + key: key, val: value, extras: 'flagshere'}); + } + checkAndRespond(requests[0], 'hello1', 'world1'); + checkAndRespond(requests[1], 'hello2', 'world2'); + checkAndRespond(requests[2], 'hello3', 'world3'); + + t.equal(constants.OP_NO_OP, requests[3].header.opcode); + dummyServer.respond( + {header: {status: 0, opaque: requests[3].header.opaque, opcode: requests[3].header.opcode}}); + }; + + var client = new MemJS.Client([dummyServer]); + var assertor = function(err, val, flags) { + t.deepEqual({ + hello1: 'world1', + hello2: 'world2', + hello3: 'world3', + }, val); + t.false(flags); + t.equal(null, err); + t.equal(1, n, 'Ensure getMulti is called'); + }; + client.getMulti(['hello1', 'hello2', 'hello3'], assertor); + testAllCallbacksEmpty(t, dummyServer); + + n = 0; + return client.getMulti(['hello1', 'hello2', 'hello3']).then(function(res) { + assertor(null, res.values, res.flags); + }); +}); + +function makeDummyMultiGetServerResponder(t, responseMap, serverName) { + var server = new MemJS.Server(serverName || 'dummyServer'); + var responder = function(requestBuf) { + var requests = MemJS.Utils.parseMessages(requestBuf); + t.equal(requests.length, Object.keys(responseMap).length + 1); + + function checkAndRespond(request, key, value) { + t.equal(constants.OP_GETKQ, request.header.opcode); + + if (value !== undefined) { + server.respond( + {header: {status: 0, opaque: request.header.opaque, opcode: request.header.opcode}, + key: key, val: value, extras: 'flagshere'}); + } + } + + for (var requestIndex in requests) { + var request = requests[requestIndex]; + + if (requestIndex === (requests.length - 1).toString()) { + t.equal(constants.OP_NO_OP, request.header.opcode); + server.respond( + {header: {status: 0, opaque: request.header.opaque, opcode: request.header.opcode}}); + } else { + var key = request.key.toString(); + checkAndRespond(request, key, responseMap[key]); + } + } + }; + server.write = responder; + return server; +} + +test('GetMultiSuccessful_MultiBackend', function(t) { + // the mappings from key to server were computer by just manually running the default hash on them + + var dummyServer1 = makeDummyMultiGetServerResponder(t, { + 'hello2': 'world2', + 'hello4': 'world4', + }, 'dummyServer1'); + var dummyServer2 = makeDummyMultiGetServerResponder(t, { + 'hello1': 'world1', + 'hello3': 'world3', + }, 'dummyServer2'); + var servers = [dummyServer1, dummyServer2]; + + var client = new MemJS.Client(servers); + + var assertor = function(err, val, flags) { + t.deepEqual({ + hello1: 'world1', + hello2: 'world2', + hello3: 'world3', + hello4: 'world4', + }, val); + t.false(flags); + t.equal(null, err); + }; + client.getMulti(['hello1', 'hello2', 'hello3', 'hello4'], assertor); + testAllCallbacksEmpty(t, dummyServer1); + testAllCallbacksEmpty(t, dummyServer2); + + return client.getMulti(['hello1', 'hello2', 'hello3', 'hello4']).then(function(res) { + assertor(null, res.values, res.flags); + }); +}); + +test('GetMultiSuccessful_MissingKeys_MultiBackend', function(t) { + // the mappings from key to server were computed by just manually running the default hash on them + var dummyServer1 = makeDummyMultiGetServerResponder(t, { + 'hello2': undefined, + 'hello4': 'world4', + }, 'dummyServer1'); + var dummyServer2 = makeDummyMultiGetServerResponder(t, { + 'hello1': 'world1', + 'hello3': 'world3', + }, 'dummyServer2'); + var servers = [dummyServer1, dummyServer2]; + + var client = new MemJS.Client(servers); + + var assertor = function(err, val, flags) { + t.deepEqual({ + hello1: 'world1', + hello3: 'world3', + hello4: 'world4', + }, val); + t.false(flags); + t.equal(null, err); + }; + client.getMulti(['hello1', 'hello2', 'hello3', 'hello4'], assertor); + testAllCallbacksEmpty(t, dummyServer1); + testAllCallbacksEmpty(t, dummyServer2); + + return client.getMulti(['hello1', 'hello2', 'hello3', 'hello4']).then(function(res) { + assertor(null, res.values, res.flags); + }); +}); + +test('GetMultiError_MultiBackend', function(t) { + // the mappings from key to server were computed by just manually running the default hash on them + var dummyServer1 = makeDummyMultiGetServerResponder(t, { + 'hello2': undefined, + 'hello4': 'world4', + }, 'dummyServer1'); + var dummyServer2 = makeDummyMultiGetServerResponder(t, { + 'hello1': 'world1', + 'hello3': 'world3' + }, 'dummyServer2'); + dummyServer2.write = function() { + dummyServer2.error({message: 'This is an expected error.'}); + }; + var servers = [dummyServer1, dummyServer2]; + + var client = new MemJS.Client(servers); + + var assertor = function(err) { + t.notEqual(null, err); + t.equal('This is an expected error.', err.message); + }; + client.getMulti(['hello1', 'hello2', 'hello3', 'hello4'], assertor); + testAllCallbacksEmpty(t, dummyServer1); + testAllCallbacksEmpty(t, dummyServer2); + + return client.getMulti(['hello1', 'hello2', 'hello3', 'hello4']).catch(function(err) { + assertor(err); + return true; + }); +}); + +test('GetMultiSuccessfulWithMissingKeys', function(t) { + var dummyServer = makeDummyMultiGetServerResponder(t, { + 'hello1': 'world1', + 'hello2': undefined, + 'hello3': 'world3', + }); + + var client = new MemJS.Client([dummyServer]); + var assertor = function(err, val, flags) { + t.deepEqual({ + hello1: 'world1', + hello3: 'world3', + }, val); + t.false(flags); + t.equal(null, err); + }; + client.getMulti(['hello1', 'hello2', 'hello3'], assertor); + testAllCallbacksEmpty(t, dummyServer); + return client.getMulti(['hello1', 'hello2', 'hello3']).then(function(res) { + assertor(null, res.values, res.flags); + }); +}); + +test('GetMultiError', function(t) { + var dummyServer = new MemJS.Server('dummyServer'); + dummyServer.write = function(requestBuf) { + var requests = MemJS.Utils.parseMessages(requestBuf); + t.equal(requests.length, 4); + + function checkAndRespond(request, key, value) { + t.equal(key, request.key.toString()); + t.equal(constants.OP_GETKQ, request.header.opcode); + + dummyServer.respond( + {header: {status: 0, opaque: request.header.opaque, opcode: request.header.opcode}, + key: key, val: value, extras: 'flagshere'}); + } + checkAndRespond(requests[0], 'hello1', 'world1'); + dummyServer.error({message: 'This is an expected error.'}); + }; + + var client = new MemJS.Client([dummyServer]); + var assertor = function(err) { + t.notEqual(null, err); + t.equal('This is an expected error.', err.message); + }; + client.getMulti(['hello1', 'hello2', 'hello3'], assertor); + testAllCallbacksEmpty(t, dummyServer); + + return client.getMulti(['hello1', 'hello2', 'hello3']).catch(function(err) { + assertor(err); + return true; + }); +}); + test('SetSuccessful', function(t) { var n = 0; - var dummyServer = new MemJS.Server(); + var dummyServer = new MemJS.Server('dummyServer'); dummyServer.write = function(requestBuf) { var request = MemJS.Utils.parseMessage(requestBuf); t.equal('hello', request.key.toString()); @@ -118,7 +358,7 @@ test('SetSuccessful', function(t) { test('SetSuccessfulWithoutOption', function(t) { var n = 0; - var dummyServer = new MemJS.Server(); + var dummyServer = new MemJS.Server('dummyServer'); dummyServer.write = function(requestBuf) { var request = MemJS.Utils.parseMessage(requestBuf); t.equal('hello', request.key.toString()); @@ -138,7 +378,7 @@ test('SetSuccessfulWithoutOption', function(t) { test('SetPromiseWithoutOption', function(t) { var n = 0; - var dummyServer = new MemJS.Server(); + var dummyServer = new MemJS.Server('dummyServer'); dummyServer.write = function(requestBuf) { var request = MemJS.Utils.parseMessage(requestBuf); t.equal('hello', request.key.toString()); @@ -157,7 +397,7 @@ test('SetPromiseWithoutOption', function(t) { test('SetWithExpiration', function(t) { var n = 0; - var dummyServer = new MemJS.Server(); + var dummyServer = new MemJS.Server('dummyServer'); dummyServer.write = function(requestBuf) { var request = MemJS.Utils.parseMessage(requestBuf); t.equal('hello', request.key.toString()); @@ -178,7 +418,7 @@ test('SetWithExpiration', function(t) { test('SetUnsuccessful', function(t) { var n = 0; - var dummyServer = new MemJS.Server(); + var dummyServer = new MemJS.Server('dummyServer'); dummyServer.write = function(requestBuf) { var request = MemJS.Utils.parseMessage(requestBuf); t.equal('hello', request.key.toString()); @@ -202,7 +442,7 @@ test('SetUnsuccessful', function(t) { test('SetError', function(t) { var n = 0; - var dummyServer = new MemJS.Server(); + var dummyServer = new MemJS.Server('dummyServer'); dummyServer.write = function(requestBuf) { var request = MemJS.Utils.parseMessage(requestBuf); t.equal('hello', request.key.toString()); @@ -223,7 +463,7 @@ test('SetError', function(t) { test('SetError', function(t) { var n = 0; - var dummyServer = new MemJS.Server(); + var dummyServer = new MemJS.Server('dummyServer'); dummyServer.write = function(requestBuf) { var request = MemJS.Utils.parseMessage(requestBuf); t.equal('hello', request.key.toString()); @@ -247,7 +487,7 @@ test('SetErrorConcurrent', function(t) { var n = 0; var callbn1 = 0; var callbn2 = 0; - var dummyServer = new MemJS.Server(); + var dummyServer = new MemJS.Server('dummyServer'); dummyServer.write = function(/* requestBuf */) { n += 1; dummyServer.error({message: 'This is an expected error.'}); @@ -283,7 +523,7 @@ test('SetErrorConcurrent', function(t) { test('SetUnicode', function(t) { var n = 0; - var dummyServer = new MemJS.Server(); + var dummyServer = new MemJS.Server('dummyServer'); dummyServer.write = function(requestBuf) { var request = MemJS.Utils.parseMessage(requestBuf); t.equal('hello', request.key.toString()); @@ -303,7 +543,7 @@ test('SetUnicode', function(t) { test('SetSerialize', function(t) { var n = 0; var sn = 0; - var dummyServer = new MemJS.Server(); + var dummyServer = new MemJS.Server('dummyServer'); dummyServer.write = function(requestBuf) { var request = MemJS.Utils.parseMessage(requestBuf); t.equal('hello', request.key.toString()); @@ -339,7 +579,7 @@ test('SetSerialize', function(t) { test('AddSuccessful', function(t) { var n = 0; - var dummyServer = new MemJS.Server(); + var dummyServer = new MemJS.Server('dummyServer'); dummyServer.write = function(requestBuf) { var request = MemJS.Utils.parseMessage(requestBuf); t.equal('hello', request.key.toString()); @@ -364,7 +604,7 @@ test('AddSuccessful', function(t) { test('AddSuccessfulWithoutOption', function(t) { var n = 0; - var dummyServer = new MemJS.Server(); + var dummyServer = new MemJS.Server('dummyServer'); dummyServer.write = function(requestBuf) { var request = MemJS.Utils.parseMessage(requestBuf); t.equal('hello', request.key.toString()); @@ -385,7 +625,7 @@ test('AddSuccessfulWithoutOption', function(t) { test('AddKeyExists', function(t) { var n = 0; - var dummyServer = new MemJS.Server(); + var dummyServer = new MemJS.Server('dummyServer'); dummyServer.write = function(requestBuf) { var request = MemJS.Utils.parseMessage(requestBuf); t.equal('hello', request.key.toString()); @@ -406,7 +646,7 @@ test('AddKeyExists', function(t) { test('AddSerializer', function(t) { var n = 0; var sn = 0; - var dummyServer = new MemJS.Server(); + var dummyServer = new MemJS.Server('dummyServer'); dummyServer.write = function(requestBuf) { var request = MemJS.Utils.parseMessage(requestBuf); t.equal('hello', request.key.toString()); @@ -445,7 +685,7 @@ test('AddSerializer', function(t) { test('ReplaceSuccessful', function(t) { var n = 0; - var dummyServer = new MemJS.Server(); + var dummyServer = new MemJS.Server('dummyServer'); dummyServer.write = function(requestBuf) { var request = MemJS.Utils.parseMessage(requestBuf); t.equal('hello', request.key.toString()); @@ -470,7 +710,7 @@ test('ReplaceSuccessful', function(t) { test('ReplaceSuccessfulWithoutOption', function(t) { var n = 0; - var dummyServer = new MemJS.Server(); + var dummyServer = new MemJS.Server('dummyServer'); dummyServer.write = function(requestBuf) { var request = MemJS.Utils.parseMessage(requestBuf); t.equal('hello', request.key.toString()); @@ -491,7 +731,7 @@ test('ReplaceSuccessfulWithoutOption', function(t) { test('ReplaceKeyDNE', function(t) { var n = 0; - var dummyServer = new MemJS.Server(); + var dummyServer = new MemJS.Server('dummyServer'); dummyServer.write = function(requestBuf) { var request = MemJS.Utils.parseMessage(requestBuf); t.equal('hello', request.key.toString()); @@ -511,7 +751,7 @@ test('ReplaceKeyDNE', function(t) { test('DeleteSuccessful', function(t) { var n = 0; - var dummyServer = new MemJS.Server(); + var dummyServer = new MemJS.Server('dummyServer'); dummyServer.write = function(requestBuf) { var request = MemJS.Utils.parseMessage(requestBuf); t.equal('hello', request.key.toString()); @@ -534,7 +774,7 @@ test('DeleteSuccessful', function(t) { test('DeleteKeyDNE', function(t) { var n = 0; - var dummyServer = new MemJS.Server(); + var dummyServer = new MemJS.Server('dummyServer'); dummyServer.write = function(requestBuf) { var request = MemJS.Utils.parseMessage(requestBuf); t.equal('hello', request.key.toString()); @@ -553,7 +793,7 @@ test('DeleteKeyDNE', function(t) { test('Flush', function(t) { var n = 0; - var dummyServer = new MemJS.Server(); + var dummyServer = new MemJS.Server('dummyServer'); dummyServer.host = 'example.com'; dummyServer.port = 1234; dummyServer.write = function(requestBuf) { @@ -578,7 +818,7 @@ test('Flush', function(t) { test('Stats', function(t) { var n = 0; - var dummyServer = new MemJS.Server(); + var dummyServer = new MemJS.Server('dummyServer'); dummyServer.host = 'myhostname'; dummyServer.port = 5544; dummyServer.write = function(requestBuf) { @@ -609,7 +849,7 @@ test('Stats', function(t) { test('IncrementSuccessful', function(t) { var n = 0; var callbn = 0; - var dummyServer = new MemJS.Server(); + var dummyServer = new MemJS.Server('dummyServer'); var expectedExtras = [ '\0\0\0\0\0\0\0\5\0\0\0\0\0\0\0\0\0\0\0\0', @@ -662,7 +902,7 @@ test('IncrementSuccessful', function(t) { test('DecrementSuccessful', function(t) { var n = 0; - var dummyServer = new MemJS.Server(); + var dummyServer = new MemJS.Server('dummyServer'); dummyServer.write = function(requestBuf) { var request = MemJS.Utils.parseMessage(requestBuf); t.equal(6, request.header.opcode); @@ -690,7 +930,7 @@ test('DecrementSuccessful', function(t) { test('DecrementSuccessfulWithoutOption', function(t) { var n = 0; - var dummyServer = new MemJS.Server(); + var dummyServer = new MemJS.Server('dummyServer'); dummyServer.write = function(requestBuf) { var request = MemJS.Utils.parseMessage(requestBuf); t.equal(6, request.header.opcode); @@ -718,7 +958,7 @@ test('DecrementSuccessfulWithoutOption', function(t) { test('AppendSuccessful', function(t) { var n = 0; - var dummyServer = new MemJS.Server(); + var dummyServer = new MemJS.Server('dummyServer'); dummyServer.write = function(requestBuf) { var request = MemJS.Utils.parseMessage(requestBuf); t.equal('hello', request.key.toString()); @@ -738,7 +978,7 @@ test('AppendSuccessful', function(t) { test('AppendKeyDNE', function(t) { var n = 0; - var dummyServer = new MemJS.Server(); + var dummyServer = new MemJS.Server('dummyServer'); dummyServer.write = function(requestBuf) { var request = MemJS.Utils.parseMessage(requestBuf); t.equal('hello', request.key.toString()); @@ -758,7 +998,7 @@ test('AppendKeyDNE', function(t) { test('PrependSuccessful', function(t) { var n = 0; - var dummyServer = new MemJS.Server(); + var dummyServer = new MemJS.Server('dummyServer'); dummyServer.write = function(requestBuf) { var request = MemJS.Utils.parseMessage(requestBuf); t.equal('hello', request.key.toString()); @@ -778,7 +1018,7 @@ test('PrependSuccessful', function(t) { test('PrependKeyDNE', function(t) { var n = 0; - var dummyServer = new MemJS.Server(); + var dummyServer = new MemJS.Server('dummyServer'); dummyServer.write = function(requestBuf) { var request = MemJS.Utils.parseMessage(requestBuf); t.equal('hello', request.key.toString()); @@ -798,7 +1038,7 @@ test('PrependKeyDNE', function(t) { test('TouchSuccessful', function(t) { var n = 0; - var dummyServer = new MemJS.Server(); + var dummyServer = new MemJS.Server('dummyServer'); dummyServer.write = function(requestBuf) { var request = MemJS.Utils.parseMessage(requestBuf); t.equal('hello', request.key.toString()); @@ -819,7 +1059,7 @@ test('TouchSuccessful', function(t) { test('TouchKeyDNE', function(t) { var n = 0; - var dummyServer = new MemJS.Server(); + var dummyServer = new MemJS.Server('dummyServer'); dummyServer.write = function(requestBuf) { var request = MemJS.Utils.parseMessage(requestBuf); t.equal('hello', request.key.toString()); @@ -838,34 +1078,34 @@ test('TouchKeyDNE', function(t) { }); }); -test('Failover', function(t) { - var n1 = 0; - var n2 = 0; - var dummyServer1 = new MemJS.Server(); - dummyServer1.write = function(/* requestBuf*/) { - n1 += 1; - dummyServer1.error(new Error('connection failure')); - }; - var dummyServer2 = new MemJS.Server(); - dummyServer2.write = function(requestBuf) { - n2 += 1; - var request = MemJS.Utils.parseMessage(requestBuf); - dummyServer2.respond({header: {status: 0, opaque: request.header.opaque}}); - }; - - var client = new MemJS.Client([dummyServer1, dummyServer2], {failover: true}); - client.get('\0', function(err/*, val */){ - t.equal(null, err); - t.equal(2, n1); - t.equal(1, n2); - t.end(); - }); - -}); +// test('Failover', function(t) { +// var n1 = 0; +// var n2 = 0; +// var dummyServer1 = new MemJS.Server('dummyServer'); +// dummyServer1.write = function(/* requestBuf*/) { +// n1 += 1; +// dummyServer1.error(new Error('connection failure')); +// }; +// var dummyServer2 = new MemJS.Server('dummyServer'); +// dummyServer2.write = function(requestBuf) { +// n2 += 1; +// var request = MemJS.Utils.parseMessage(requestBuf); +// dummyServer2.respond({header: {status: 0, opaque: request.header.opaque}}); +// }; + +// var client = new MemJS.Client([dummyServer1, dummyServer2], {failover: true}); +// client.get('\0', function(err/*, val */){ +// t.equal(null, err); +// t.equal(2, n1); +// t.equal(1, n2); +// t.end(); +// }); + +// }); test('Very Large Client Seq', function(t) { var n = 0; - var dummyServer = new MemJS.Server(); + var dummyServer = new MemJS.Server('dummyServer'); dummyServer.write = function(requestBuf) { var request = MemJS.Utils.parseMessage(requestBuf); t.equal('hello', request.key.toString()); From ba337625612ce38aad57453a85572b9e7fefad2e Mon Sep 17 00:00:00 2001 From: David Blackman Date: Fri, 26 Mar 2021 08:56:56 -0400 Subject: [PATCH 02/79] remove comment to self --- lib/memjs/memjs.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lib/memjs/memjs.js b/lib/memjs/memjs.js index da77878..a5a1a7d 100644 --- a/lib/memjs/memjs.js +++ b/lib/memjs/memjs.js @@ -1,7 +1,3 @@ -// TODO -// test that handlers are cleaned up on errors -// --> see if handler.false is even needed - // # MemJS Memcache Client var errors = require('./protocol').errors; From 76539852136f9ecab05aeae3c2b6245a1c2e79e2 Mon Sep 17 00:00:00 2001 From: Jake Teton-Landis Date: Fri, 26 Mar 2021 17:06:51 -0700 Subject: [PATCH 03/79] .d.ts --- lib/memjs/index.d.ts | 531 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 531 insertions(+) create mode 100644 lib/memjs/index.d.ts diff --git a/lib/memjs/index.d.ts b/lib/memjs/index.d.ts new file mode 100644 index 0000000..ed78abc --- /dev/null +++ b/lib/memjs/index.d.ts @@ -0,0 +1,531 @@ +// Type definitions for memjs 1.2 +// Project: http://github.com/memcachier/memjs +// Definitions by: Zongmin Lei +// BendingBender +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped +// TypeScript Version: 2.1 + +/// + +export interface ClientOptions { + /** + * The number of times to retry an operation in lieu of failures. + * @default 2 + */ + retries?: number; + /** + * @default 0.2 + */ + retry_delay?: number; + /** + * The default expiration in seconds to use. A `0` means never expire, + * if it is greater than 30 days (60 x 60 x 24 x 30), it is + * treated as a UNIX time (number of seconds since January 1, 1970). + * @default 0 + */ + expires?: number; + /** + * A logger object that responds to `log(string)` method calls. + * @default console + */ + logger?: { + log(...args: any[]): void; + }; + /** + * A function to map keys to servers. + * NOTE: if you need to do some expensive initialization, *please* do it lazily + * the first time you this function is called with an array of serverKeys, not on + * every call. + */ + keyToServerHashFunction?: (serverKeys: string[], key: string) => string; +} +export interface ServerOptions { + /** + * Server username for fallback SASL authentication credentials. + */ + username?: string; + /** + * Server password for fallback SASL authentication credentials. + */ + password?: string; + /** + * `timeout` in seconds to determine failure for operations. + * @default 0.5 + */ + timeout?: number; + /** + * `conntimeout` in seconds to connection failure. + * @default 2 * timeout + */ + conntimeout?: number; + /** + * Whether to enable keep-alive functionality. + * @default false + */ + keepAlive?: boolean; + /** + * `keepAliveDelay` in seconds to the initial delay before the first keep- + * alive probe is sent on an idle socket. + * @default 30 + */ + keepAliveDelay?: number; +} +export class Client { + /** + * Creates a new client given an optional config string and optional hash of + * options. The config string should be of the form: + * + * "[user:pass@]server1[:11211],[user:pass@]server2[:11211],..." + * + * If the argument is not given, fallback on the `MEMCACHIER_SERVERS` environment + * variable, `MEMCACHE_SERVERS` environment variable or `"localhost:11211"`. + * + * The options hash may contain the options: + * + * * `retries` - the number of times to retry an operation in lieu of failures + * (default 2) + * * `expires` - the default expiration in seconds to use (default 0 - never + * expire). If `expires` is greater than 30 days (60 x 60 x 24 x 30), it is + * treated as a UNIX time (number of seconds since January 1, 1970). + * * `logger` - a logger object that responds to `log(string)` method calls. + * * `failover` - whether to failover to next server. Defaults to false. + * * `failoverTime` - how much to wait until retring a failed server. Default + * is 60 seconds. + * + * ~~~~ + * log(msg1[, msg2[, msg3[...]]]) + * ~~~~ + * + * Defaults to `console`. + * + * Or options for the servers including: + * * `username` and `password` for fallback SASL authentication credentials. + * * `timeout` in seconds to determine failure for operations. Default is 0.5 + * seconds. + * * 'conntimeout' in seconds to connection failure. Default is twice the value + * of `timeout`. + * * `keepAlive` whether to enable keep-alive functionality. Defaults to false. + * * `keepAliveDelay` in seconds to the initial delay before the first keepalive + * probe is sent on an idle socket. Defaults is 30 seconds. + */ + static create( + serversStr?: string, + options?: ClientOptions | ServerOptions + ): Client; + + servers: string[]; + + /** + * Client initializer takes a list of Servers and an options dictionary. See Client.create for details. + * @param servers + * @param options + */ + constructor(servers: string, options?: ClientOptions); + + /** + * Chooses the server to talk to by hashing the given key. + * @param key + */ + server(key: string): string; + + /** + * GET + * + * Retrieves the value at the given key in memcache. + * + * The callback signature is: + * + * callback(err, value, flags) + * + * _value_ and _flags_ are both `Buffer`s. If the key is not found, the + * callback is invoked with null for both arguments and no error + * @param key + * @param callback + */ + get(key: string): Promise<{ value: Buffer; flags: Buffer }>; + get( + key: string, + callback: ( + err: Error | null, + value: Buffer | null, + flags: Buffer | null + ) => void + ): void; + + /** + * MULTI-GET / GET-MULTI + * + * Retrieves the value at the given keys in memcache. + * + * The callback signature is: + * + * callback(err, values, flags) + * + * _values_ is a map of key->string + * _flags_ is a `string`. + */ + getMulti( + keys: Keys[] + ): Promise<{ values: { [K in Keys]?: string | null }; flags: Buffer | null }>; + getMulti( + keys: Keys[], + callback: ( + err: Error | null, + values: { [K in Keys]: string | null } | null, + flags: Buffer | null + ) => void + ): void; + + /** + * SET + * + * Sets the given _key_ and _value_ in memcache. + * + * The options dictionary takes: + * * _expires_: overrides the default expiration (see `Client.create`) for this + * particular key-value pair. + * + * The callback signature is: + * + * callback(err, success) + * @param key + * @param value + * @param options + * @param callback + */ + set( + key: string, + value: string | Buffer, + options: { expires?: number } + ): Promise; + set( + key: string, + value: string | Buffer, + options: { expires?: number }, + callback: (err: Error | null, success: boolean | null) => void + ): void; + + /** + * ADD + * + * Adds the given _key_ and _value_ to memcache. The operation only succeeds + * if the key is not already set. + * + * The options dictionary takes: + * * _expires_: overrides the default expiration (see `Client.create`) for this + * particular key-value pair. + * + * The callback signature is: + * + * callback(err, success) + * @param key + * @param value + * @param options + * @param callback + */ + add( + key: string, + value: string | Buffer, + options: { expires?: number } + ): Promise; + add( + key: string, + value: string | Buffer, + options: { expires?: number }, + callback: (err: Error | null, success: boolean | null) => void + ): void; + + /** + * REPLACE + * + * Replaces the given _key_ and _value_ to memcache. The operation only succeeds + * if the key is already present. + * + * The options dictionary takes: + * * _expires_: overrides the default expiration (see `Client.create`) for this + * particular key-value pair. + * + * The callback signature is: + * + * callback(err, success) + * @param key + * @param value + * @param options + * @param callback + */ + replace( + key: string, + value: string | Buffer, + options: { expires?: number } + ): Promise; + replace( + key: string, + value: string | Buffer, + options: { expires?: number }, + callback: (err: Error | null, success: boolean | null) => void + ): void; + + /** + * DELETE + * + * Deletes the given _key_ from memcache. The operation only succeeds + * if the key is already present. + * + * The callback signature is: + * + * callback(err, success) + * @param key + * @param callback + */ + delete(key: string): Promise; + delete( + key: string, + callback: (err: Error | null, success: boolean | null) => void + ): void; + + /** + * INCREMENT + * + * Increments the given _key_ in memcache. + * + * The options dictionary takes: + * * _initial_: the value for the key if not already present, defaults to 0. + * * _expires_: overrides the default expiration (see `Client.create`) for this + * particular key-value pair. + * + * The callback signature is: + * + * callback(err, success, value) + * @param key + * @param amount + * @param options + * @param callback + */ + increment( + key: string, + amount: number, + options: { initial?: number; expires?: number } + ): Promise<{ success: boolean; value?: number | null }>; + increment( + key: string, + amount: number, + options: { initial?: number; expires?: number }, + callback: ( + err: Error | null, + success: boolean | null, + value?: number | null + ) => void + ): void; + + /** + * DECREMENT + * + * Decrements the given _key_ in memcache. + * + * The options dictionary takes: + * * _initial_: the value for the key if not already present, defaults to 0. + * * _expires_: overrides the default expiration (see `Client.create`) for this + * particular key-value pair. + * + * The callback signature is: + * + * callback(err, success, value) + * @param key + * @param amount + * @param options + * @param callback + */ + decrement( + key: string, + amount: number, + options: { initial?: number; expires?: number } + ): Promise<{ success: boolean; value?: number | null }>; + decrement( + key: string, + amount: number, + options: { initial?: number; expires?: number }, + callback: ( + err: Error | null, + success: boolean | null, + value?: number | null + ) => void + ): void; + + /** + * APPEND + * + * Append the given _value_ to the value associated with the given _key_ in + * memcache. The operation only succeeds if the key is already present. The + * callback signature is: + * + * callback(err, success) + * @param key + * @param value + * @param callback + */ + append(key: string, value: string | Buffer): Promise; + append( + key: string, + value: string | Buffer, + callback: (err: Error | null, success: boolean | null) => void + ): void; + + /** + * PREPEND + * + * Prepend the given _value_ to the value associated with the given _key_ in + * memcache. The operation only succeeds if the key is already present. The + * callback signature is: + * + * callback(err, success) + * @param key + * @param value + * @param callback + */ + prepend(key: string, value: string | Buffer): Promise; + prepend( + key: string, + value: string | Buffer, + callback: (err: Error | null, success: boolean | null) => void + ): void; + + /** + * TOUCH + * + * Touch sets an expiration value, given by _expires_, on the given _key_ in + * memcache. The operation only succeeds if the key is already present. The + * callback signature is: + * + * callback(err, success) + * @param key + * @param expires + * @param callback + */ + touch(key: string, expires: number): Promise; + touch( + key: string, + expires: number, + callback: (err: Error | null, success: boolean | null) => void + ): void; + + /** + * FLUSH + * + * Flushes the cache on each connected server. The callback signature is: + * + * callback(lastErr, results) + * + * where _lastErr_ is the last error encountered (or null, in the common case + * of no errors). _results_ is a dictionary mapping `"hostname:port"` to either + * `true` (if the operation was successful), or an error. + * @param callback + */ + flush(): Promise>; + flush( + callback: (err: Error | null, results: Record) => void + ): void; + + /** + * STATS_WITH_KEY + * + * Sends a memcache stats command with a key to each connected server. The + * callback is invoked **ONCE PER SERVER** and has the signature: + * + * callback(err, server, stats) + * + * _server_ is the `"hostname:port"` of the server, and _stats_ is a dictionary + * mapping the stat name to the value of the statistic as a string. + * @param key + * @param callback + */ + statsWithKey( + key: string, + callback?: ( + err: Error | null, + server: string, + stats: Record | null + ) => void + ): void; + + /** + * STATS + * + * Fetches memcache stats from each connected server. The callback is invoked + * **ONCE PER SERVER** and has the signature: + * + * callback(err, server, stats) + * + * _server_ is the `"hostname:port"` of the server, and _stats_ is a + * dictionary mapping the stat name to the value of the statistic as a string. + * @param callback + */ + stats( + callback?: ( + err: Error | null, + server: string, + stats: Record | null + ) => void + ): void; + + /** + * RESET_STATS + * + * Reset the statistics each server is keeping back to zero. This doesn't clear + * stats such as item count, but temporary stats such as total number of + * connections over time. + * + * The callback is invoked **ONCE PER SERVER** and has the signature: + * + * callback(err, server) + * + * _server_ is the `"hostname:port"` of the server. + * @param callback + */ + resetStats( + callback?: ( + err: Error | null, + server: string, + stats: Record | null + ) => void + ): void; + + /** + * QUIT + * + * Closes the connection to each server, notifying them of this intention. Note + * that quit can race against already outstanding requests when those requests + * fail and are retried, leading to the quit command winning and closing the + * connection before the retries complete. + */ + quit(): void; + + /** + * CLOSE + * + * Closes (abruptly) connections to all the servers. + */ + close(): void; + + /** + * Perform a generic single response operation (get, set etc) on a server + * serv: the server to perform the operation on + * request: a buffer containing the request + * seq: the sequence number of the operation. It is used to pin the callbacks + * to a specific operation and should never change during a `perform`. + * callback: a callback invoked when a response is received or the request + * fails + * retries: number of times to retry request on failure + * @param key + * @param request + * @param seq + * @param callback + * @param retries + */ + perform( + key: string, + request: Buffer, + seq: number, + callback?: (err: Error | null, ...args: any[]) => void, + retries?: number + ): void; +} From 9e2520efd55b67c365c4a183e358e5f8bc8a624d Mon Sep 17 00:00:00 2001 From: Jake Teton-Landis Date: Fri, 26 Mar 2021 17:20:36 -0700 Subject: [PATCH 04/79] confirmed these were actually Buffers --- lib/memjs/index.d.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/memjs/index.d.ts b/lib/memjs/index.d.ts index ed78abc..b9ac5e4 100644 --- a/lib/memjs/index.d.ts +++ b/lib/memjs/index.d.ts @@ -161,17 +161,17 @@ export class Client { * * callback(err, values, flags) * - * _values_ is a map of key->string - * _flags_ is a `string`. + * @param keys + * @param callback */ getMulti( keys: Keys[] - ): Promise<{ values: { [K in Keys]?: string | null }; flags: Buffer | null }>; + ): Promise<{ values: { [K in Keys]?: Buffer | null }; flags: Buffer | null }>; getMulti( keys: Keys[], callback: ( err: Error | null, - values: { [K in Keys]: string | null } | null, + values: { [K in Keys]: Buffer | null } | null, flags: Buffer | null ) => void ): void; From 9d925d23db80205205008d8c8da5b01bd918681f Mon Sep 17 00:00:00 2001 From: Jake Teton-Landis Date: Mon, 29 Mar 2021 08:57:23 -0700 Subject: [PATCH 05/79] fix file name --- lib/memjs/{index.d.ts => memjs.d.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename lib/memjs/{index.d.ts => memjs.d.ts} (100%) diff --git a/lib/memjs/index.d.ts b/lib/memjs/memjs.d.ts similarity index 100% rename from lib/memjs/index.d.ts rename to lib/memjs/memjs.d.ts From 7b57c8b3981697eb6a16393188aec33806da3eb5 Mon Sep 17 00:00:00 2001 From: David Blackman Date: Mon, 29 Mar 2021 12:31:24 -0400 Subject: [PATCH 06/79] add version command (#5) --- lib/memjs/memjs.js | 56 ++++++++++++++++++++++++++++++++++++++------- test/client_test.js | 45 ++++++++++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+), 8 deletions(-) diff --git a/lib/memjs/memjs.js b/lib/memjs/memjs.js index a5a1a7d..88e5b23 100644 --- a/lib/memjs/memjs.js +++ b/lib/memjs/memjs.js @@ -927,6 +927,44 @@ Client.prototype.quit = function() { } }; +// VERSION +// +// Request the server version from the "first" server in the backend pool +// +// The server responds with a packet containing the version string in the body with the following format: "x.y.z" +Client.prototype.version = function(callback) { + var self = this; + if(callback === undefined) { + return promisify(function(callback) { + self.version(function(err, value, flags) { + callback(err, {value: value, flags: flags}); + }); + }); + } + + this.incrSeq(); + var request = makeRequestBuffer(constants.OP_VERSION, '', '', '', this.seq); + var serverKey = this.serverKeys[0]; + var logger = this.options.logger; + + this.perform(serverKey, request, this.seq, function (err, response) { + if (err) { + if (callback) { callback(err, null, null); } + return; + } + switch (response.header.status) { + case constants.RESPONSE_STATUS_SUCCCESS: + var deserialized = self.serializer.deserialize(response.header.opcode, response.val, response.extras); + callback(null, deserialized.value, deserialized.extras); + break; + default: + var errorMessage = 'MemJS VERSION: ' + errors[response.header.status]; + logger.log(errorMessage); + if (callback) { callback(new Error(errorMessage), null, null); } + } + }); +}; + // CLOSE // // Closes (abruptly) connections to all the servers. @@ -937,14 +975,16 @@ Client.prototype.close = function() { } }; -// Perform a generic single response operation (get, set etc) on a server -// serv: the server to perform the operation on -// request: a buffer containing the request -// seq: the sequence number of the operation. It is used to pin the callbacks -// to a specific operation and should never change during a `perform`. -// callback: a callback invoked when a response is received or the request -// fails -// retries: number of times to retry request on failure +/** + * Perform a generic single response operation (get, set etc) on one server + * + * @param {string} key the key to hash to get a server from the pool + * @param {buffer} request a buffer containing the request + * @param {number} seq the sequence number of the operation. It is used to pin the callbacks + to a specific operation and should never change during a `perform`. + * @param {*} callback a callback invoked when a response is received or the request fails + * @param {*} retries number of times to retry request on failure + */ Client.prototype.perform = function(key, request, seq, callback, retries) { var serverKey = this.lookupKeyToServerKey(key); diff --git a/test/client_test.js b/test/client_test.js index c4a2fb0..8a5c26a 100644 --- a/test/client_test.js +++ b/test/client_test.js @@ -1128,4 +1128,49 @@ test('Very Large Client Seq', function(t) { assertor(null, success); }); }); + + +tap.only('VersionSuccessful', function(t) { + var dummyServer = new MemJS.Server('dummyServer'); + dummyServer.write = function(requestBuf) { + var request = MemJS.Utils.parseMessage(requestBuf); + t.deepEqual(Buffer.from(''), request.key); + dummyServer.respond( + {header: {status: 0, opaque: request.header.opaque}, + val: '1.3.1', extras: 'flagshere'}); + }; + + var client = new MemJS.Client([dummyServer]); + var assertor = function(err, val, flags) { + t.equal('1.3.1', val); + t.equal('flagshere', flags); + t.equal(null, err); + }; + + client.version(assertor); + return client.version().then(function(res) { + assertor(null, res.value, res.flags); + }); +}); + + +tap.only('VersionError', function(t) { + var dummyServer = new MemJS.Server('dummyServer'); + dummyServer.write = function() { + dummyServer.error({message: 'This is an expected error.'}); + }; + + var client = new MemJS.Client([dummyServer]); + var assertor = function(err) { + t.notEqual(null, err); + t.equal('This is an expected error.', err.message); + }; + + client.version(assertor); + return client.version().catch(function(err) { + assertor(err); + return true; + }); +}); + return; From 2fc73ae69e8807b8d2c50861f1f09392fb056a3c Mon Sep 17 00:00:00 2001 From: Jake Teton-Landis Date: Mon, 29 Mar 2021 11:22:20 -0700 Subject: [PATCH 07/79] fix comment to accurately describe as buffer --- lib/memjs/memjs.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/memjs/memjs.js b/lib/memjs/memjs.js index a5a1a7d..ce3b810 100644 --- a/lib/memjs/memjs.js +++ b/lib/memjs/memjs.js @@ -272,7 +272,7 @@ Client.prototype._getMultiToServer = function (serv, keys, callback) { // // callback(err, values, flags) // -// _values_ is a map of key->string +// _values_ is a map of { [key]: Buffer } // _flags_ is a `string`. Client.prototype.getMulti = function(keys, callback) { var self = this; From 9a88a2b242f01dcf1a314fba5d3b54e663095a3e Mon Sep 17 00:00:00 2001 From: David Blackman Date: Mon, 29 Mar 2021 18:29:32 -0400 Subject: [PATCH 08/79] version and versionAll (#6) * version and versionAll * PR feedback --- .eslintrc.json | 8 +- lib/memjs/memjs.d.ts | 43 +- lib/memjs/memjs.js | 50 +- lib/memjs/server.js | 7 +- lib/memjs/utils.js | 11 +- package-lock.json | 1222 +++++++++++++++++++----------------------- package.json | 4 +- test/client_test.js | 84 ++- 8 files changed, 731 insertions(+), 698 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index 24f122c..4fba8ce 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -15,7 +15,8 @@ "semi": [ 2, "always" - ] + ], + "no-unused-vars": 0 }, "globals": { "Promise": "readonly" @@ -24,5 +25,10 @@ "node": true, "browser": true }, + "parserOptions": { + "es6": true, + "ecmaVersion": 6, + "sourceType": "module" + }, "extends": "eslint:recommended" } diff --git a/lib/memjs/memjs.d.ts b/lib/memjs/memjs.d.ts index b9ac5e4..f907eac 100644 --- a/lib/memjs/memjs.d.ts +++ b/lib/memjs/memjs.d.ts @@ -159,7 +159,7 @@ export class Client { * * The callback signature is: * - * callback(err, values, flags) + * callback(err, value, flags) * * @param keys * @param callback @@ -528,4 +528,45 @@ export class Client { callback?: (err: Error | null, ...args: any[]) => void, retries?: number ): void; + + /** + * VERSION + * + * Retrieves the server version from the "first" server in the backend pool + * + * The callback signature is: + * + * callback(err, value, flags) + * + * @param keys + * @param callback + */ + version(): Promise<{ value: string; flags: Buffer | null }>; + version(callback: ( + err: Error | null, + value: { [K in Keys]: Buffer | null } | null, + flags: Buffer | null + ) => void): void + + + /** + * VERSION-ALL + * + * Retrieves the server version from all the servers + * in the backend pool, errors if any one of them has an + * error + * + * The callback signature is: + * + * callback(err, value, flags) + * + * @param keys + * @param callback + */ + versionAll(): Promise<{ values: Record; flags: Buffer | null }>; + versionAll(callback: ( + err: Error | null, + values: Record, + flags: Buffer | null + ) => void): void } diff --git a/lib/memjs/memjs.js b/lib/memjs/memjs.js index ba7fccb..e66c7f2 100644 --- a/lib/memjs/memjs.js +++ b/lib/memjs/memjs.js @@ -927,16 +927,11 @@ Client.prototype.quit = function() { } }; -// VERSION -// -// Request the server version from the "first" server in the backend pool -// -// The server responds with a packet containing the version string in the body with the following format: "x.y.z" -Client.prototype.version = function(callback) { +Client.prototype._version = function(server, callback) { var self = this; if(callback === undefined) { return promisify(function(callback) { - self.version(function(err, value, flags) { + self._version(server, function(err, value, flags) { callback(err, {value: value, flags: flags}); }); }); @@ -944,14 +939,14 @@ Client.prototype.version = function(callback) { this.incrSeq(); var request = makeRequestBuffer(constants.OP_VERSION, '', '', '', this.seq); - var serverKey = this.serverKeys[0]; var logger = this.options.logger; - this.perform(serverKey, request, this.seq, function (err, response) { + this.performOnServer(server, request, this.seq, function (err, response) { if (err) { if (callback) { callback(err, null, null); } return; } + switch (response.header.status) { case constants.RESPONSE_STATUS_SUCCCESS: var deserialized = self.serializer.deserialize(response.header.opcode, response.val, response.extras); @@ -965,6 +960,43 @@ Client.prototype.version = function(callback) { }); }; +// VERSION +// +// Request the server version from the "first" server in the backend pool +// +// The server responds with a packet containing the version string in the body with the following format: "x.y.z" + +Client.prototype.version = function(callback) { + const server = this.serverKeyToServer(this.serverKeys[0]); + + return this._version(server, callback); +}; + +Client.prototype.versionAll = function(callback) { + const promise = Promise.all(this.serverKeys.map((serverKey) => { + const server = this.serverKeyToServer(serverKey); + + return this._version(server).then((response) => { + return {serverKey: serverKey, value: response.value}; + }); + })).then(versionObjects => { + const values = versionObjects.reduce((accumulator, versionObject) => { + accumulator[versionObject.serverKey] = versionObject.value; + return accumulator; + }, {}); + return {values: values}; + }); + + if(callback === undefined) { + return promise; + } + return promise.then((response) =>{ + callback(null, response.values); + }).catch((err) => { + callback(err, null); + }); +}; + // CLOSE // // Closes (abruptly) connections to all the servers. diff --git a/lib/memjs/server.js b/lib/memjs/server.js index 26d6b0a..48d7772 100644 --- a/lib/memjs/server.js +++ b/lib/memjs/server.js @@ -65,11 +65,8 @@ Server.prototype.error = function(err) { this._socket.destroy(); delete(this._socket); } - var k; - for (k in errcalls) { - if (errcalls.hasOwnProperty(k)) { - errcalls[k](err); - } + for (let errcall of Object.values(errcalls)) { + errcall(err); } }; diff --git a/lib/memjs/utils.js b/lib/memjs/utils.js index 8ae28bd..759085c 100644 --- a/lib/memjs/utils.js +++ b/lib/memjs/utils.js @@ -112,14 +112,11 @@ exports.parseMessages = function(dataBuf) { }; exports.merge = function(original, deflt) { - var attr, originalValue; - for (attr in deflt) { - if (deflt.hasOwnProperty(attr)) { - originalValue = original[attr]; + for (let attr of Object.keys(deflt)) { + const originalValue = original[attr]; - if (originalValue === undefined || originalValue === null) { - original[attr] = deflt[attr]; - } + if (originalValue === undefined || originalValue === null) { + original[attr] = deflt[attr]; } } return original; diff --git a/package-lock.json b/package-lock.json index 591b998..fcc418e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -70,14 +70,12 @@ "@babel/helper-validator-identifier": { "version": "7.12.11", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", - "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", - "dev": true + "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==" }, "@babel/highlight": { "version": "7.13.10", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.13.10.tgz", "integrity": "sha512-5aPpe5XQPzflQrFwL1/QoeHkP2MsA4JCntcXHRhEsdsfPVkvPi2w7Qix4iV7t5S/oC9OodGrggd8aco1g3SZFg==", - "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.12.11", "chalk": "^2.0.0", @@ -88,7 +86,6 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, "requires": { "color-convert": "^1.9.0" } @@ -97,7 +94,6 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -107,14 +103,12 @@ "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, "requires": { "has-flag": "^3.0.0" } @@ -191,6 +185,50 @@ } } }, + "@eslint/eslintrc": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.0.tgz", + "integrity": "sha512-2ZPCc+uNbjV5ERJr+aKSPRwZgKd2z11x0EgLvb1PURmUrn9QNRXFqje0Ldq454PfAVyaJYyrDvvIKSFP4NnBog==", + "requires": { + "ajv": "^6.12.4", + "debug": "^4.1.1", + "espree": "^7.3.0", + "globals": "^12.1.0", + "ignore": "^4.0.6", + "import-fresh": "^3.2.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "requires": { + "ms": "2.1.2" + } + }, + "globals": { + "version": "12.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", + "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "requires": { + "type-fest": "^0.8.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==" + } + } + }, "@types/yoga-layout": { "version": "1.9.2", "resolved": "https://registry.npmjs.org/@types/yoga-layout/-/yoga-layout-1.9.2.tgz", @@ -198,45 +236,30 @@ "dev": true }, "acorn": { - "version": "5.7.4", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.4.tgz", - "integrity": "sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==", - "dev": true + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==" }, "acorn-jsx": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", - "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", - "dev": true, - "requires": { - "acorn": "^3.0.4" - }, - "dependencies": { - "acorn": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", - "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", - "dev": true - } - } + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", + "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==" }, "ajv": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", - "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", - "dev": true, + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "requires": { - "co": "^4.6.0", - "fast-deep-equal": "^1.0.0", + "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.3.0" + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" } }, - "ajv-keywords": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", - "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=", - "dev": true + "ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==" }, "ansi-escapes": { "version": "3.2.0", @@ -297,7 +320,6 @@ "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, "requires": { "sprintf-js": "~1.0.2" } @@ -326,8 +348,7 @@ "astral-regex": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==" }, "async-hook-domain": { "version": "1.1.3", @@ -605,8 +626,7 @@ "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" }, "bcrypt-pbkdf": { "version": "1.0.2", @@ -651,7 +671,6 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -690,6 +709,15 @@ "write-file-atomic": "^2.4.2" } }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, "caller-callsite": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", @@ -707,20 +735,10 @@ } } }, - "caller-path": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", - "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", - "dev": true, - "requires": { - "callsites": "^0.2.0" - } - }, "callsites": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", - "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", - "dev": true + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" }, "camelcase": { "version": "5.3.1", @@ -763,12 +781,6 @@ "supports-color": "^2.0.0" } }, - "chardet": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", - "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", - "dev": true - }, "chokidar": { "version": "3.5.1", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", @@ -791,12 +803,6 @@ "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", "dev": true }, - "circular-json": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", - "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", - "dev": true - }, "cli-cursor": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", @@ -891,12 +897,6 @@ } } }, - "cli-width": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz", - "integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==", - "dev": true - }, "cliui": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", @@ -925,12 +925,6 @@ } } }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "dev": true - }, "code-point-at": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", @@ -941,7 +935,6 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, "requires": { "color-name": "1.1.3" } @@ -949,8 +942,7 @@ "color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, "color-support": { "version": "1.1.3", @@ -982,20 +974,7 @@ "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, "convert-source-map": { "version": "1.7.0", @@ -1089,8 +1068,7 @@ "deep-is": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" }, "default-require-extensions": { "version": "2.0.0", @@ -1136,10 +1114,9 @@ } }, "doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "requires": { "esutils": "^2.0.2" } @@ -1166,6 +1143,14 @@ "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", "dev": true }, + "enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "requires": { + "ansi-colors": "^4.1.1" + } + }, "error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -1184,171 +1169,229 @@ "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, "eslint": { - "version": "4.18.2", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.18.2.tgz", - "integrity": "sha512-qy4i3wODqKMYfz9LUI8N2qYDkHkoieTbiHpMrYUI/WbjhXJQr7lI4VngixTgaG+yHX+NBCv7nW4hA0ShbvaNKw==", - "dev": true, - "requires": { - "ajv": "^5.3.0", - "babel-code-frame": "^6.22.0", - "chalk": "^2.1.0", - "concat-stream": "^1.6.0", - "cross-spawn": "^5.1.0", - "debug": "^3.1.0", - "doctrine": "^2.1.0", - "eslint-scope": "^3.7.1", - "eslint-visitor-keys": "^1.0.0", - "espree": "^3.5.2", - "esquery": "^1.0.0", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.23.0.tgz", + "integrity": "sha512-kqvNVbdkjzpFy0XOszNwjkKzZ+6TcwCQ/h+ozlcIWwaimBBuhlQ4nN6kbiM2L+OjDcznkTJxzYfRFH92sx4a0Q==", + "requires": { + "@babel/code-frame": "7.12.11", + "@eslint/eslintrc": "^0.4.0", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "enquirer": "^2.3.5", + "eslint-scope": "^5.1.1", + "eslint-utils": "^2.1.0", + "eslint-visitor-keys": "^2.0.0", + "espree": "^7.3.1", + "esquery": "^1.4.0", "esutils": "^2.0.2", - "file-entry-cache": "^2.0.0", + "file-entry-cache": "^6.0.1", "functional-red-black-tree": "^1.0.1", - "glob": "^7.1.2", - "globals": "^11.0.1", - "ignore": "^3.3.3", + "glob-parent": "^5.0.0", + "globals": "^13.6.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", - "inquirer": "^3.0.6", - "is-resolvable": "^1.0.0", - "js-yaml": "^3.9.1", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.3.0", - "lodash": "^4.17.4", - "minimatch": "^3.0.2", - "mkdirp": "^0.5.1", + "levn": "^0.4.1", + "lodash": "^4.17.21", + "minimatch": "^3.0.4", "natural-compare": "^1.4.0", - "optionator": "^0.8.2", - "path-is-inside": "^1.0.2", - "pluralize": "^7.0.0", + "optionator": "^0.9.1", "progress": "^2.0.0", - "require-uncached": "^1.0.3", - "semver": "^5.3.0", - "strip-ansi": "^4.0.0", - "strip-json-comments": "~2.0.1", - "table": "4.0.2", - "text-table": "~0.2.0" + "regexpp": "^3.1.0", + "semver": "^7.2.1", + "strip-ansi": "^6.0.0", + "strip-json-comments": "^3.1.0", + "table": "^6.0.4", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" }, "dependencies": { + "@babel/code-frame": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", + "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", + "requires": { + "@babel/highlight": "^7.10.4" + } + }, "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" }, "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "requires": { - "color-convert": "^1.9.0" + "color-convert": "^2.0.1" } }, "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" } }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, "cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "dev": true, + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "requires": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" } }, "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", "requires": { - "ms": "^2.1.1" + "ms": "2.1.2" } }, - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, + "globals": { + "version": "13.7.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.7.0.tgz", + "integrity": "sha512-Aipsz6ZKRxa/xQkZhNg0qIWXT6x6rD46f6x/PCnBomlttdIyAPak4YD9jTmKpZ72uROSMU87qJtcgpgHaVchiA==", "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "type-fest": "^0.20.2" } }, "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" }, - "js-yaml": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", - "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", - "dev": true, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "yallist": "^4.0.0" } }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" + }, + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "requires": { + "lru-cache": "^6.0.0" + } + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" }, "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", "requires": { - "ansi-regex": "^3.0.0" + "ansi-regex": "^5.0.0" } }, "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "requires": { - "has-flag": "^3.0.0" + "has-flag": "^4.0.0" + } + }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==" + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "requires": { + "isexe": "^2.0.0" } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" } } }, "eslint-scope": { - "version": "3.7.3", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.3.tgz", - "integrity": "sha512-W+B0SvF4gamyCTmUc+uITPY0989iXVfKvhwtmJocTaYoc/3khEHmEmvfY/Gn9HA9VV75jrQECsHizkNw1b68FA==", - "dev": true, + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", "requires": { - "esrecurse": "^4.1.0", + "esrecurse": "^4.3.0", "estraverse": "^4.1.1" } }, + "eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "requires": { + "eslint-visitor-keys": "^1.1.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==" + } + } + }, "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz", + "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==" }, "esm": { "version": "3.2.25", @@ -1357,26 +1400,31 @@ "dev": true }, "espree": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", - "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", - "dev": true, + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", + "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", "requires": { - "acorn": "^5.5.0", - "acorn-jsx": "^3.0.0" + "acorn": "^7.4.0", + "acorn-jsx": "^5.3.1", + "eslint-visitor-keys": "^1.3.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==" + } } }, "esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" }, "esquery": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz", - "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==", - "dev": true, + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", "requires": { "estraverse": "^5.1.0" }, @@ -1384,8 +1432,7 @@ "estraverse": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==" } } }, @@ -1393,7 +1440,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, "requires": { "estraverse": "^5.2.0" }, @@ -1401,22 +1447,19 @@ "estraverse": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==" } } }, "estraverse": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==" }, "esutils": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", - "dev": true + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" }, "events-to-array": { "version": "1.1.2", @@ -1430,17 +1473,6 @@ "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", "dev": true }, - "external-editor": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", - "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", - "dev": true, - "requires": { - "chardet": "^0.4.0", - "iconv-lite": "^0.4.17", - "tmp": "^0.0.33" - } - }, "extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", @@ -1448,40 +1480,26 @@ "dev": true }, "fast-deep-equal": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", - "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", - "dev": true + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, "fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "figures": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", - "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5" - } + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" }, "file-entry-cache": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", - "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", - "dev": true, + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", "requires": { - "flat-cache": "^1.2.1", - "object-assign": "^4.0.1" + "flat-cache": "^3.0.4" } }, "fill-range": { @@ -1520,17 +1538,29 @@ "dev": true }, "flat-cache": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz", - "integrity": "sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg==", - "dev": true, + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", "requires": { - "circular-json": "^0.3.1", - "graceful-fs": "^4.1.2", - "rimraf": "~2.6.2", - "write": "^0.2.1" + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, + "dependencies": { + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "requires": { + "glob": "^7.1.3" + } + } } }, + "flatted": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.1.tgz", + "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==" + }, "foreground-child": { "version": "1.5.6", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-1.5.6.tgz", @@ -1578,8 +1608,7 @@ "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "fsevents": { "version": "2.3.2", @@ -1591,8 +1620,7 @@ "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, "function-loop": { "version": "1.0.2", @@ -1603,8 +1631,7 @@ "functional-red-black-tree": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=" }, "get-caller-file": { "version": "2.0.5", @@ -1612,6 +1639,16 @@ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true }, + "get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + } + }, "getpass": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", @@ -1625,7 +1662,6 @@ "version": "7.1.6", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -1639,7 +1675,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, "requires": { "is-glob": "^4.0.1" } @@ -1702,7 +1737,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, "requires": { "function-bind": "^1.1.1" } @@ -1719,8 +1753,12 @@ "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "has-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==" }, "hasha": { "version": "3.0.0", @@ -1770,21 +1808,27 @@ "sshpk": "^1.7.0" } }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==" + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "requires": { - "safer-buffer": ">= 2.1.2 < 3" + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==" + } } }, - "ignore": { - "version": "3.3.10", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", - "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", - "dev": true - }, "import-jsx": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/import-jsx/-/import-jsx-2.0.0.tgz", @@ -1813,14 +1857,12 @@ "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, "requires": { "once": "^1.3.0", "wrappy": "1" @@ -1829,8 +1871,7 @@ "inherits": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, "ink": { "version": "2.7.1", @@ -2011,145 +2052,55 @@ "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", "dev": true, "requires": { - "ansi-regex": "^5.0.0" - } - } - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.0" - } - } - } - } - } - }, - "inquirer": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", - "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", - "dev": true, - "requires": { - "ansi-escapes": "^3.0.0", - "chalk": "^2.0.0", - "cli-cursor": "^2.1.0", - "cli-width": "^2.0.0", - "external-editor": "^2.0.4", - "figures": "^2.0.0", - "lodash": "^4.3.0", - "mute-stream": "0.0.7", - "run-async": "^2.2.0", - "rx-lite": "^4.0.8", - "rx-lite-aggregates": "^4.0.8", - "string-width": "^2.1.0", - "strip-ansi": "^4.0.0", - "through": "^2.3.6" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "ansi-regex": "^5.0.0" + } + } } }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", "dev": true, "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" + "ansi-regex": "^4.1.0" } }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { - "ansi-regex": "^3.0.0" + "has-flag": "^4.0.0" } }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", "dev": true, "requires": { - "has-flag": "^3.0.0" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + } } } } @@ -2178,6 +2129,14 @@ "binary-extensions": "^2.0.0" } }, + "is-boolean-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.0.tgz", + "integrity": "sha512-a7Uprx8UtD+HWdyYwnD1+ExtTgqQtD2k/1yJgtXP6wnMm8byhkoTZRl+95LLThpzNZJ5aEvi46cdH+ayMFRwmA==", + "requires": { + "call-bind": "^1.0.0" + } + }, "is-ci": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", @@ -2199,8 +2158,7 @@ "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" }, "is-finite": { "version": "1.1.0", @@ -2218,7 +2176,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dev": true, "requires": { "is-extglob": "^2.1.1" } @@ -2229,11 +2186,10 @@ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true }, - "is-resolvable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", - "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", - "dev": true + "is-number-object": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.4.tgz", + "integrity": "sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw==" }, "is-stream": { "version": "1.1.0", @@ -2241,6 +2197,11 @@ "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", "dev": true }, + "is-string": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", + "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==" + }, "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", @@ -2251,13 +2212,13 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true + "dev": true, + "optional": true }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, "isstream": { "version": "0.1.2", @@ -2417,7 +2378,6 @@ "version": "3.14.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, "requires": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -2448,16 +2408,14 @@ "dev": true }, "json-schema-traverse": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", - "dev": true + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, "json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=" }, "json-stringify-safe": { "version": "5.0.1", @@ -2499,13 +2457,12 @@ "dev": true }, "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true, + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" } }, "load-json-file": { @@ -2541,8 +2498,17 @@ "lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=" + }, + "lodash.flatten": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", + "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=" }, "lodash.flattendeep": { "version": "4.4.0", @@ -2556,6 +2522,11 @@ "integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ=", "dev": true }, + "lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=" + }, "log-driver": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.7.tgz", @@ -2714,7 +2685,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, "requires": { "brace-expansion": "^1.1.7" } @@ -2764,17 +2734,10 @@ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true }, - "mute-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", - "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", - "dev": true - }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=" }, "nested-error-stacks": { "version": "2.1.0", @@ -2881,7 +2844,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, "requires": { "wrappy": "1" } @@ -2902,17 +2864,16 @@ "dev": true }, "optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "dev": true, + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" } }, "os-homedir": { @@ -2986,6 +2947,14 @@ } } }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "requires": { + "callsites": "^3.0.0" + } + }, "parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", @@ -3005,14 +2974,7 @@ "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", - "dev": true + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, "path-key": { "version": "2.0.1", @@ -3076,17 +3038,10 @@ "integrity": "sha512-TuvHS8AOIZNAlE77WUDiR4rySV/VMptyMfcfeoMgs4P8apaZM3JrnbzBiixKUv+XR6i+BXrQh8WAnjaSPFO65Q==", "dev": true }, - "pluralize": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", - "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", - "dev": true - }, "prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "dev": true + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==" }, "private": { "version": "0.1.8", @@ -3098,13 +3053,13 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", - "dev": true + "dev": true, + "optional": true }, "progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==" }, "prop-types": { "version": "15.7.2", @@ -3132,8 +3087,7 @@ "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" }, "qs": { "version": "6.5.2", @@ -3196,6 +3150,7 @@ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", "dev": true, + "optional": true, "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -3230,6 +3185,11 @@ "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", "dev": true }, + "regexpp": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", + "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==" + }, "release-zalgo": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", @@ -3290,30 +3250,17 @@ "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", "dev": true }, + "require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==" + }, "require-main-filename": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", "dev": true }, - "require-uncached": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", - "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", - "dev": true, - "requires": { - "caller-path": "^0.1.0", - "resolve-from": "^1.0.0" - }, - "dependencies": { - "resolve-from": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", - "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", - "dev": true - } - } - }, "resolve": { "version": "1.20.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", @@ -3365,27 +3312,6 @@ } } }, - "run-async": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", - "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", - "dev": true - }, - "rx-lite": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", - "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=", - "dev": true - }, - "rx-lite-aggregates": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", - "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", - "dev": true, - "requires": { - "rx-lite": "*" - } - }, "safe-buffer": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", @@ -3448,19 +3374,40 @@ "dev": true }, "slice-ansi": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", - "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", - "dev": true, + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", "requires": { - "is-fullwidth-code-point": "^2.0.0" + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" }, "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" } } }, @@ -3529,8 +3476,7 @@ "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" }, "sshpk": { "version": "1.16.1", @@ -3631,6 +3577,7 @@ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", "dev": true, + "optional": true, "requires": { "safe-buffer": "~5.1.0" } @@ -3651,10 +3598,9 @@ "dev": true }, "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==" }, "supports-color": { "version": "2.0.0", @@ -3663,83 +3609,68 @@ "dev": true }, "table": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz", - "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", - "dev": true, - "requires": { - "ajv": "^5.2.3", - "ajv-keywords": "^2.1.0", - "chalk": "^2.1.0", - "lodash": "^4.17.4", - "slice-ansi": "1.0.0", - "string-width": "^2.1.1" + "version": "6.0.8", + "resolved": "https://registry.npmjs.org/table/-/table-6.0.8.tgz", + "integrity": "sha512-OBAdezyozae8IvjHGXBDHByVkLCcsmffXUSj8LXkNb0SluRd4ug3GFCjk6JynZONIPhOkyr0Nnvbq1rlIspXyQ==", + "requires": { + "ajv": "^8.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "lodash.clonedeep": "^4.5.0", + "lodash.flatten": "^4.4.0", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.0" }, "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, + "ajv": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.0.1.tgz", + "integrity": "sha512-46ZA4TalFcLLqX1dEU3dhdY38wAtDydJ4e7QQTVekLUTzXkb1LfqU6VOBXC/a9wiv4T094WURqJH6ZitF92Kqw==", "requires": { - "color-convert": "^1.9.0" + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" } }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" }, "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" } }, "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", "requires": { - "has-flag": "^3.0.0" + "ansi-regex": "^5.0.0" } } } @@ -3870,23 +3801,7 @@ "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true - }, - "tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true, - "requires": { - "os-tmpdir": "~1.0.2" - } + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" }, "to-fast-properties": { "version": "1.0.3", @@ -4018,12 +3933,11 @@ "dev": true }, "type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dev": true, + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "requires": { - "prelude-ls": "~1.1.2" + "prelude-ls": "^1.2.1" } }, "type-fest": { @@ -4032,12 +3946,6 @@ "integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==", "dev": true }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true - }, "typescript": { "version": "3.9.9", "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.9.tgz", @@ -4078,7 +3986,6 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, "requires": { "punycode": "^2.1.0" } @@ -4087,7 +3994,8 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true + "dev": true, + "optional": true }, "uuid": { "version": "3.4.0", @@ -4095,6 +4003,11 @@ "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", "dev": true }, + "v8-compile-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==" + }, "validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", @@ -4183,8 +4096,7 @@ "word-wrap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==" }, "wrap-ansi": { "version": "2.1.0", @@ -4221,17 +4133,7 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "write": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", - "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", - "dev": true, - "requires": { - "mkdirp": "^0.5.1" - } + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "write-file-atomic": { "version": "2.4.3", diff --git a/package.json b/package.json index cbdae08..2d28ed1 100644 --- a/package.json +++ b/package.json @@ -30,8 +30,8 @@ "devDependencies": { "benchmark": "^2.1.4", "docco": "^0.8.0", - "eslint": "4.18.2", "microtime": "^3.0.0", - "tap": "14.0.*" + "tap": "14.0.*", + "eslint": "^7.23.0" } } diff --git a/test/client_test.js b/test/client_test.js index 8a5c26a..4a6e6fd 100644 --- a/test/client_test.js +++ b/test/client_test.js @@ -402,7 +402,7 @@ test('SetWithExpiration', function(t) { var request = MemJS.Utils.parseMessage(requestBuf); t.equal('hello', request.key.toString()); t.equal('world', request.val.toString()); - t.equal('\0\0\0\0\0\0\4\0', request.extras.toString()); + t.equal('\0\0\0\0\0\0\x04\0', request.extras.toString()); n += 1; dummyServer.respond({header: {status: 0, opaque: request.header.opaque}}); }; @@ -690,7 +690,7 @@ test('ReplaceSuccessful', function(t) { var request = MemJS.Utils.parseMessage(requestBuf); t.equal('hello', request.key.toString()); t.equal('world', request.val.toString()); - t.equal('\0\0\0\0\0\0\4\0', request.extras.toString()); + t.equal('\0\0\0\0\0\0\x04\0', request.extras.toString()); n += 1; dummyServer.respond({header: {status: 0, opaque: request.header.opaque}}); }; @@ -715,7 +715,7 @@ test('ReplaceSuccessfulWithoutOption', function(t) { var request = MemJS.Utils.parseMessage(requestBuf); t.equal('hello', request.key.toString()); t.equal('world', request.val.toString()); - t.equal('\0\0\0\0\0\0\4\0', request.extras.toString()); + t.equal('\0\0\0\0\0\0\x04\0', request.extras.toString()); n += 1; dummyServer.respond({header: {status: 0, opaque: request.header.opaque}}); }; @@ -852,8 +852,8 @@ test('IncrementSuccessful', function(t) { var dummyServer = new MemJS.Server('dummyServer'); var expectedExtras = [ - '\0\0\0\0\0\0\0\5\0\0\0\0\0\0\0\0\0\0\0\0', - '\0\0\0\0\0\0\0\5\0\0\0\0\0\0\0\3\0\0\0\0' + '\0\0\0\0\0\0\0\x05\0\0\0\0\0\0\0\0\0\0\0\0', + '\0\0\0\0\0\0\0\x05\0\0\0\0\0\0\0\x03\0\0\0\0' ]; dummyServer.write = function(requestBuf) { @@ -908,7 +908,7 @@ test('DecrementSuccessful', function(t) { t.equal(6, request.header.opcode); t.equal('number-decrement-test', request.key.toString()); t.equal('', request.val.toString()); - t.equal('\0\0\0\0\0\0\0\5\0\0\0\0\0\0\0\0\0\0\0\0', request.extras.toString()); + t.equal('\0\0\0\0\0\0\0\x05\0\0\0\0\0\0\0\0\0\0\0\0', request.extras.toString()); n += 1; process.nextTick(function() { var value = Buffer.alloc(8); @@ -936,7 +936,7 @@ test('DecrementSuccessfulWithoutOption', function(t) { t.equal(6, request.header.opcode); t.equal('number-decrement-test', request.key.toString()); t.equal('', request.val.toString()); - t.equal('\0\0\0\0\0\0\0\5\0\0\0\0\0\0\0\0\0\0\0\0', request.extras.toString()); + t.equal('\0\0\0\0\0\0\0\x05\0\0\0\0\0\0\0\0\0\0\0\0', request.extras.toString()); n += 1; process.nextTick(function() { var value = Buffer.alloc(8); @@ -1043,7 +1043,7 @@ test('TouchSuccessful', function(t) { var request = MemJS.Utils.parseMessage(requestBuf); t.equal('hello', request.key.toString()); t.equal('', request.val.toString()); - t.equal('\0\0\4\0', request.extras.toString()); + t.equal('\0\0\x04\0', request.extras.toString()); n += 1; dummyServer.respond({header: {status: 0, opaque: request.header.opaque}}); }; @@ -1064,7 +1064,7 @@ test('TouchKeyDNE', function(t) { var request = MemJS.Utils.parseMessage(requestBuf); t.equal('hello', request.key.toString()); t.equal('', request.val.toString()); - t.equal('\0\0\4\0', request.extras.toString()); + t.equal('\0\0\x04\0', request.extras.toString()); n += 1; dummyServer.respond({header: {status: 1, opaque: request.header.opaque}}); }; @@ -1129,12 +1129,26 @@ test('Very Large Client Seq', function(t) { }); }); +const makeDummyVersionServer = (t, serverKey, version) => { + var dummyServer = new MemJS.Server(serverKey); + dummyServer.write = function(requestBuf) { + var request = MemJS.Utils.parseMessage(requestBuf); + t.deepEqual(Buffer.from(''), request.key); + dummyServer.respond( + {header: {status: 0, opaque: request.header.opaque}, + val: version, extras: 'flagshere'}); + }; + return dummyServer; +}; -tap.only('VersionSuccessful', function(t) { - var dummyServer = new MemJS.Server('dummyServer'); +test('VersionSuccessful', function(t) { + var n = 0; + + var dummyServer = makeDummyVersionServer(t, 'dummyServer', '1.3.1'); dummyServer.write = function(requestBuf) { var request = MemJS.Utils.parseMessage(requestBuf); t.deepEqual(Buffer.from(''), request.key); + n += 1; dummyServer.respond( {header: {status: 0, opaque: request.header.opaque}, val: '1.3.1', extras: 'flagshere'}); @@ -1145,15 +1159,17 @@ tap.only('VersionSuccessful', function(t) { t.equal('1.3.1', val); t.equal('flagshere', flags); t.equal(null, err); + t.equal(n, 1, 'Ensure version is called'); }; client.version(assertor); + n = 0; + return client.version().then(function(res) { assertor(null, res.value, res.flags); }); }); - tap.only('VersionError', function(t) { var dummyServer = new MemJS.Server('dummyServer'); dummyServer.write = function() { @@ -1173,4 +1189,46 @@ tap.only('VersionError', function(t) { }); }); -return; +test('VersionAllSuccessful', function(t) { + const dummyServer1 = makeDummyVersionServer(t, 'dummyServer1', '1.0.0'); + const dummyServer2 = makeDummyVersionServer(t, 'dummyServer2', '2.0.0'); + const dummyServer3 = makeDummyVersionServer(t, 'dummyServer3', '3.0.0'); + + var client = new MemJS.Client([dummyServer1, dummyServer2, dummyServer3]); + var assertor = function(err, val) { + t.deepEqual({ + 'dummyServer1:undefined': '1.0.0', + 'dummyServer2:undefined': '2.0.0', + 'dummyServer3:undefined': '3.0.0' + }, val); + t.equal(null, err); + }; + + client.versionAll(assertor); + + return client.versionAll().then(function(res) { + assertor(null, res.values, res.flags); + }); +}); + + +tap.only('VersionAllSomeFailed', function(t) { + const dummyServer1 = makeDummyVersionServer(t, 'dummyServer1', '1.0.0'); + const dummyServer2 = makeDummyVersionServer(t, 'dummyServer2', '2.0.0'); + dummyServer2.write = function() { + dummyServer2.error({message: 'This is an expected error.'}); + }; + const dummyServer3 = makeDummyVersionServer(t, 'dummyServer3', '3.0.0'); + + var client = new MemJS.Client([dummyServer1, dummyServer2, dummyServer3]); + var assertor = function(err) { + t.notEqual(null, err); + t.equal('This is an expected error.', err.message); + }; + + client.versionAll(assertor); + + return client.versionAll().catch(function(err) { + assertor(err); + }); +}); \ No newline at end of file From d6d527cf8c097a572be499254750ab76232af7f5 Mon Sep 17 00:00:00 2001 From: David Blackman Date: Tue, 30 Mar 2021 11:46:09 -0400 Subject: [PATCH 09/79] no-op lint fix commit --- bench/memjs.js | 46 +++++++++++++++++++++++----------------------- bench/timers.js | 42 +++++++++++++++++++++--------------------- 2 files changed, 44 insertions(+), 44 deletions(-) diff --git a/bench/memjs.js b/bench/memjs.js index b8053cf..d94aa62 100644 --- a/bench/memjs.js +++ b/bench/memjs.js @@ -1,10 +1,10 @@ -var memjs = require("memjs"); +var memjs = require('memjs'); var header = require('header'); -var b = require("benchmark"); +var b = require('benchmark'); function makeString(n) { - var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; - var text = ""; + var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + var text = ''; var i; for(i=0; i < n; i++ ) { @@ -23,15 +23,15 @@ var x = (function() { suite.add('Header#fromBuffer', function() { header.fromBuffer(headerBuf); }) - .add('Header#toBuffer', function() { - header.toBuffer(parsedHeader); - }) + .add('Header#toBuffer', function() { + header.toBuffer(parsedHeader); + }) // add listeners - .on('cycle', function(event) { - console.log(String(event.target)); - }) + .on('cycle', function(event) { + console.log(String(event.target)); + }) // run async - .run({ 'async': true }); + .run({ 'async': true }); }()); x = (function() { @@ -66,15 +66,15 @@ x = (function() { suite.add('Server#respond', function() { server.respond('helloworldthisisatesttohowmuchyouareaversetocopyingoverthestargatecommisionandromanticizingaboutmylifelongpassionforlearningandyieldingtoyourdesires'); }) - .add('Server#responseHandler', function() { - server.responseHandler(buf); - }) + .add('Server#responseHandler', function() { + server.responseHandler(buf); + }) // add listeners - .on('cycle', function(event) { - console.log(String(event.target)); - }) + .on('cycle', function(event) { + console.log(String(event.target)); + }) // run async - .run({ 'async': true }); + .run({ 'async': true }); }()); x = (function() { @@ -83,15 +83,15 @@ x = (function() { suite.cycles = 0; suite.add('Client#get', function() { - client.get("hello", function(/* err, val */) { + client.get('hello', function(/* err, val */) { suite.cycles++; }); }) // add listeners - .on('cycle', function(event) { - console.log(String(event.target) + " " + suite.cycles); - }); - client.set("hello", makeString(10240), function(/* err, val */) { + .on('cycle', function(event) { + console.log(String(event.target) + ' ' + suite.cycles); + }); + client.set('hello', makeString(10240), function(/* err, val */) { // run async suite.run({ 'async': true }); }); diff --git a/bench/timers.js b/bench/timers.js index 4f9d165..8efcd7a 100644 --- a/bench/timers.js +++ b/bench/timers.js @@ -16,30 +16,30 @@ suite.add('Date.now()', function() { // system time, not-monotonic, ms Date.now(); }) -.add('Microtime.now()', function() { + .add('Microtime.now()', function() { // system time, not-monotonic, us (POSIX: gettimeofday) - Microtime.now(); -}) -.add('process.hrtime()', function() { + Microtime.now(); + }) + .add('process.hrtime()', function() { // monotonic, ns (returns: [seconds, nanoseconds]) - process.hrtime(); -}) -.add('process.hrtime() ms-round', function() { + process.hrtime(); + }) + .add('process.hrtime() ms-round', function() { // monotonic, ns (returns: [seconds, nanoseconds]) - var time = process.hrtime(); - return (time[0] * 1000) + Math.round(time[1] / 1000000); -}) -.add('process.hrtime() ms-floor', function() { + var time = process.hrtime(); + return (time[0] * 1000) + Math.round(time[1] / 1000000); + }) + .add('process.hrtime() ms-floor', function() { // monotonic, ns (returns: [seconds, nanoseconds]) - var time = process.hrtime(); - return (time[0] * 1000) + Math.floor(time[1] / 1000000); -}) + var time = process.hrtime(); + return (time[0] * 1000) + Math.floor(time[1] / 1000000); + }) // add listeners -.on('cycle', function(event) { - console.log(String(event.target)); -}) -.on('complete', function() { - console.log('Fastest is ' + this.filter('fastest').map('name')); -}) + .on('cycle', function(event) { + console.log(String(event.target)); + }) + .on('complete', function() { + console.log('Fastest is ' + this.filter('fastest').map('name')); + }) // run async -.run({ 'async': true }); + .run({ 'async': true }); From ef2b165812304634320bcbf83ac8cc3e7a29bcf6 Mon Sep 17 00:00:00 2001 From: Jake Teton-Landis Date: Fri, 9 Apr 2021 13:00:06 -0700 Subject: [PATCH 10/79] move sources into src/ --- {lib => src}/memjs/constants.js | 0 {lib => src}/memjs/header.js | 0 {lib => src}/memjs/memjs.d.ts | 0 {lib => src}/memjs/memjs.js | 0 {lib => src}/memjs/noop-serializer.js | 0 {lib => src}/memjs/protocol.js | 0 {lib => src}/memjs/server.js | 0 {lib => src}/memjs/utils.js | 0 {test => src/test}/client_test.js | 0 {test => src/test}/header_test.js | 0 {test => src/test}/server_test.js | 0 {test => src/test}/utils_test.js | 0 12 files changed, 0 insertions(+), 0 deletions(-) rename {lib => src}/memjs/constants.js (100%) rename {lib => src}/memjs/header.js (100%) rename {lib => src}/memjs/memjs.d.ts (100%) rename {lib => src}/memjs/memjs.js (100%) rename {lib => src}/memjs/noop-serializer.js (100%) rename {lib => src}/memjs/protocol.js (100%) rename {lib => src}/memjs/server.js (100%) rename {lib => src}/memjs/utils.js (100%) rename {test => src/test}/client_test.js (100%) rename {test => src/test}/header_test.js (100%) rename {test => src/test}/server_test.js (100%) rename {test => src/test}/utils_test.js (100%) diff --git a/lib/memjs/constants.js b/src/memjs/constants.js similarity index 100% rename from lib/memjs/constants.js rename to src/memjs/constants.js diff --git a/lib/memjs/header.js b/src/memjs/header.js similarity index 100% rename from lib/memjs/header.js rename to src/memjs/header.js diff --git a/lib/memjs/memjs.d.ts b/src/memjs/memjs.d.ts similarity index 100% rename from lib/memjs/memjs.d.ts rename to src/memjs/memjs.d.ts diff --git a/lib/memjs/memjs.js b/src/memjs/memjs.js similarity index 100% rename from lib/memjs/memjs.js rename to src/memjs/memjs.js diff --git a/lib/memjs/noop-serializer.js b/src/memjs/noop-serializer.js similarity index 100% rename from lib/memjs/noop-serializer.js rename to src/memjs/noop-serializer.js diff --git a/lib/memjs/protocol.js b/src/memjs/protocol.js similarity index 100% rename from lib/memjs/protocol.js rename to src/memjs/protocol.js diff --git a/lib/memjs/server.js b/src/memjs/server.js similarity index 100% rename from lib/memjs/server.js rename to src/memjs/server.js diff --git a/lib/memjs/utils.js b/src/memjs/utils.js similarity index 100% rename from lib/memjs/utils.js rename to src/memjs/utils.js diff --git a/test/client_test.js b/src/test/client_test.js similarity index 100% rename from test/client_test.js rename to src/test/client_test.js diff --git a/test/header_test.js b/src/test/header_test.js similarity index 100% rename from test/header_test.js rename to src/test/header_test.js diff --git a/test/server_test.js b/src/test/server_test.js similarity index 100% rename from test/server_test.js rename to src/test/server_test.js diff --git a/test/utils_test.js b/src/test/utils_test.js similarity index 100% rename from test/utils_test.js rename to src/test/utils_test.js From ceaf4e72024c61f9e8b5a042769b91167b1d65c5 Mon Sep 17 00:00:00 2001 From: Jake Teton-Landis Date: Fri, 9 Apr 2021 13:00:16 -0700 Subject: [PATCH 11/79] tsconfig --- tsconfig.json | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 tsconfig.json diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..d1a0561 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,71 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig.json to read more about this file */ + + /* Basic Options */ + // "incremental": true, /* Enable incremental compilation */ + "target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ + "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ + // "lib": [], /* Specify library files to be included in the compilation. */ + "allowJs": true, /* Allow javascript files to be compiled. */ + "checkJs": true, /* Report errors in .js files. */ + // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', 'react', 'react-jsx' or 'react-jsxdev'. */ + "declaration": true, /* Generates corresponding '.d.ts' file. */ + "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ + "sourceMap": true, /* Generates corresponding '.map' file. */ + // "outFile": "./", /* Concatenate and emit output to single file. */ + "outDir": "./lib/", /* Redirect output structure to the directory. */ + // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ + // "composite": true, /* Enable project compilation */ + // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ + // "removeComments": true, /* Do not emit comments to output. */ + // "noEmit": true, /* Do not emit outputs. */ + // "importHelpers": true, /* Import emit helpers from 'tslib'. */ + // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ + // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ + + /* Strict Type-Checking Options */ + "strict": true, /* Enable all strict type-checking options. */ + // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* Enable strict null checks. */ + // "strictFunctionTypes": true, /* Enable strict checking of function types. */ + // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ + // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ + // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ + // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ + + /* Additional Checks */ + // "noUnusedLocals": true, /* Report errors on unused locals. */ + // "noUnusedParameters": true, /* Report errors on unused parameters. */ + // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ + // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ + // "noPropertyAccessFromIndexSignature": true, /* Require undeclared properties from index signatures to use element accesses. */ + + /* Module Resolution Options */ + "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ + // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ + // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ + // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ + // "typeRoots": [], /* List of folders to include type definitions from. */ + // "types": [], /* Type declaration files to be included in compilation. */ + // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ + "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ + // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ + + /* Source Map Options */ + // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ + "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ + + /* Experimental Options */ + // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ + // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ + + /* Advanced Options */ + "skipLibCheck": true, /* Skip type checking of declaration files. */ + "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ + }, + "include": ["src/**/*"], +} From f1cfc0e20ee0a378086f1195874f0d8281d3c072 Mon Sep 17 00:00:00 2001 From: Jake Teton-Landis Date: Fri, 9 Apr 2021 13:01:01 -0700 Subject: [PATCH 12/79] build with tsc --- .gitignore | 1 + package-lock.json | 295 ++++++++++++++++++++++++++++++++++------------ package.json | 10 +- 3 files changed, 227 insertions(+), 79 deletions(-) diff --git a/.gitignore b/.gitignore index 55e3af2..dde57a0 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ pids logs results build/ +lib/ node_modules npm-debug.log diff --git a/package-lock.json b/package-lock.json index fcc418e..9c028e0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -70,12 +70,14 @@ "@babel/helper-validator-identifier": { "version": "7.12.11", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", - "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==" + "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", + "dev": true }, "@babel/highlight": { "version": "7.13.10", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.13.10.tgz", "integrity": "sha512-5aPpe5XQPzflQrFwL1/QoeHkP2MsA4JCntcXHRhEsdsfPVkvPi2w7Qix4iV7t5S/oC9OodGrggd8aco1g3SZFg==", + "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.12.11", "chalk": "^2.0.0", @@ -86,6 +88,7 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, "requires": { "color-convert": "^1.9.0" } @@ -94,6 +97,7 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -103,12 +107,14 @@ "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, "requires": { "has-flag": "^3.0.0" } @@ -189,6 +195,7 @@ "version": "0.4.0", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.0.tgz", "integrity": "sha512-2ZPCc+uNbjV5ERJr+aKSPRwZgKd2z11x0EgLvb1PURmUrn9QNRXFqje0Ldq454PfAVyaJYyrDvvIKSFP4NnBog==", + "dev": true, "requires": { "ajv": "^6.12.4", "debug": "^4.1.1", @@ -205,6 +212,7 @@ "version": "4.3.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, "requires": { "ms": "2.1.2" } @@ -213,6 +221,7 @@ "version": "12.4.0", "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "dev": true, "requires": { "type-fest": "^0.8.1" } @@ -220,15 +229,23 @@ "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true }, "type-fest": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==" + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true } } }, + "@types/node": { + "version": "12.20.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.7.tgz", + "integrity": "sha512-gWL8VUkg8VRaCAUgG9WmhefMqHmMblxe2rVpMF86nZY/+ZysU+BkAp+3cz03AixWDSSz0ks5WX59yAhv/cDwFA==", + "dev": true + }, "@types/yoga-layout": { "version": "1.9.2", "resolved": "https://registry.npmjs.org/@types/yoga-layout/-/yoga-layout-1.9.2.tgz", @@ -238,17 +255,20 @@ "acorn": { "version": "7.4.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==" + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true }, "acorn-jsx": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", - "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==" + "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", + "dev": true }, "ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, "requires": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -259,7 +279,8 @@ "ansi-colors": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==" + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true }, "ansi-escapes": { "version": "3.2.0", @@ -320,6 +341,7 @@ "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, "requires": { "sprintf-js": "~1.0.2" } @@ -348,7 +370,8 @@ "astral-regex": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==" + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true }, "async-hook-domain": { "version": "1.1.3", @@ -626,7 +649,8 @@ "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true }, "bcrypt-pbkdf": { "version": "1.0.2", @@ -671,6 +695,7 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -713,6 +738,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, "requires": { "function-bind": "^1.1.1", "get-intrinsic": "^1.0.2" @@ -738,7 +764,8 @@ "callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true }, "camelcase": { "version": "5.3.1", @@ -935,6 +962,7 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, "requires": { "color-name": "1.1.3" } @@ -942,7 +970,8 @@ "color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true }, "color-support": { "version": "1.1.3", @@ -974,7 +1003,8 @@ "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true }, "convert-source-map": { "version": "1.7.0", @@ -1068,7 +1098,8 @@ "deep-is": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true }, "default-require-extensions": { "version": "2.0.0", @@ -1117,6 +1148,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, "requires": { "esutils": "^2.0.2" } @@ -1147,6 +1179,7 @@ "version": "2.3.6", "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, "requires": { "ansi-colors": "^4.1.1" } @@ -1169,12 +1202,14 @@ "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true }, "eslint": { "version": "7.23.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.23.0.tgz", "integrity": "sha512-kqvNVbdkjzpFy0XOszNwjkKzZ+6TcwCQ/h+ozlcIWwaimBBuhlQ4nN6kbiM2L+OjDcznkTJxzYfRFH92sx4a0Q==", + "dev": true, "requires": { "@babel/code-frame": "7.12.11", "@eslint/eslintrc": "^0.4.0", @@ -1219,6 +1254,7 @@ "version": "7.12.11", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", + "dev": true, "requires": { "@babel/highlight": "^7.10.4" } @@ -1226,12 +1262,14 @@ "ansi-regex": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true }, "ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "requires": { "color-convert": "^2.0.1" } @@ -1240,6 +1278,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -1249,6 +1288,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "requires": { "color-name": "~1.1.4" } @@ -1256,12 +1296,14 @@ "color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, "cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, "requires": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -1272,6 +1314,7 @@ "version": "4.3.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, "requires": { "ms": "2.1.2" } @@ -1280,6 +1323,7 @@ "version": "13.7.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.7.0.tgz", "integrity": "sha512-Aipsz6ZKRxa/xQkZhNg0qIWXT6x6rD46f6x/PCnBomlttdIyAPak4YD9jTmKpZ72uROSMU87qJtcgpgHaVchiA==", + "dev": true, "requires": { "type-fest": "^0.20.2" } @@ -1287,12 +1331,14 @@ "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true }, "lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, "requires": { "yallist": "^4.0.0" } @@ -1300,17 +1346,20 @@ "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true }, "path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true }, "semver": { "version": "7.3.5", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, "requires": { "lru-cache": "^6.0.0" } @@ -1319,6 +1368,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, "requires": { "shebang-regex": "^3.0.0" } @@ -1326,12 +1376,14 @@ "shebang-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true }, "strip-ansi": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, "requires": { "ansi-regex": "^5.0.0" } @@ -1340,6 +1392,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "requires": { "has-flag": "^4.0.0" } @@ -1347,12 +1400,14 @@ "type-fest": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==" + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, "requires": { "isexe": "^2.0.0" } @@ -1360,7 +1415,8 @@ "yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true } } }, @@ -1368,6 +1424,7 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, "requires": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" @@ -1377,6 +1434,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, "requires": { "eslint-visitor-keys": "^1.1.0" }, @@ -1384,14 +1442,16 @@ "eslint-visitor-keys": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==" + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true } } }, "eslint-visitor-keys": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz", - "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==" + "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==", + "dev": true }, "esm": { "version": "3.2.25", @@ -1403,6 +1463,7 @@ "version": "7.3.1", "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", + "dev": true, "requires": { "acorn": "^7.4.0", "acorn-jsx": "^5.3.1", @@ -1412,19 +1473,22 @@ "eslint-visitor-keys": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==" + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true } } }, "esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true }, "esquery": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "dev": true, "requires": { "estraverse": "^5.1.0" }, @@ -1432,7 +1496,8 @@ "estraverse": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==" + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true } } }, @@ -1440,6 +1505,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, "requires": { "estraverse": "^5.2.0" }, @@ -1447,19 +1513,22 @@ "estraverse": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==" + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true } } }, "estraverse": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==" + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true }, "esutils": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true }, "events-to-array": { "version": "1.1.2", @@ -1482,22 +1551,26 @@ "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true }, "fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true }, "fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true }, "file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, "requires": { "flat-cache": "^3.0.4" } @@ -1541,6 +1614,7 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, "requires": { "flatted": "^3.1.0", "rimraf": "^3.0.2" @@ -1550,6 +1624,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, "requires": { "glob": "^7.1.3" } @@ -1559,7 +1634,8 @@ "flatted": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.1.tgz", - "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==" + "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==", + "dev": true }, "foreground-child": { "version": "1.5.6", @@ -1608,7 +1684,8 @@ "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true }, "fsevents": { "version": "2.3.2", @@ -1620,7 +1697,8 @@ "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true }, "function-loop": { "version": "1.0.2", @@ -1631,7 +1709,8 @@ "functional-red-black-tree": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=" + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true }, "get-caller-file": { "version": "2.0.5", @@ -1643,6 +1722,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "dev": true, "requires": { "function-bind": "^1.1.1", "has": "^1.0.3", @@ -1662,6 +1742,7 @@ "version": "7.1.6", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -1675,6 +1756,7 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, "requires": { "is-glob": "^4.0.1" } @@ -1737,6 +1819,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, "requires": { "function-bind": "^1.1.1" } @@ -1753,12 +1836,14 @@ "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true }, "has-symbols": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==" + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "dev": true }, "hasha": { "version": "3.0.0", @@ -1811,12 +1896,14 @@ "ignore": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==" + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true }, "import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, "requires": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -1825,7 +1912,8 @@ "resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==" + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true } } }, @@ -1857,12 +1945,14 @@ "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, "requires": { "once": "^1.3.0", "wrappy": "1" @@ -1871,7 +1961,8 @@ "inherits": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true }, "ink": { "version": "2.7.1", @@ -2133,6 +2224,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.0.tgz", "integrity": "sha512-a7Uprx8UtD+HWdyYwnD1+ExtTgqQtD2k/1yJgtXP6wnMm8byhkoTZRl+95LLThpzNZJ5aEvi46cdH+ayMFRwmA==", + "dev": true, "requires": { "call-bind": "^1.0.0" } @@ -2158,7 +2250,8 @@ "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true }, "is-finite": { "version": "1.1.0", @@ -2176,6 +2269,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, "requires": { "is-extglob": "^2.1.1" } @@ -2189,7 +2283,8 @@ "is-number-object": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.4.tgz", - "integrity": "sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw==" + "integrity": "sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw==", + "dev": true }, "is-stream": { "version": "1.1.0", @@ -2200,7 +2295,8 @@ "is-string": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", - "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==" + "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", + "dev": true }, "is-typedarray": { "version": "1.0.0", @@ -2218,7 +2314,8 @@ "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true }, "isstream": { "version": "0.1.2", @@ -2378,6 +2475,7 @@ "version": "3.14.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, "requires": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -2410,12 +2508,14 @@ "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true }, "json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=" + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true }, "json-stringify-safe": { "version": "5.0.1", @@ -2460,6 +2560,7 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, "requires": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" @@ -2498,17 +2599,20 @@ "lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true }, "lodash.clonedeep": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=" + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", + "dev": true }, "lodash.flatten": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", - "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=" + "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=", + "dev": true }, "lodash.flattendeep": { "version": "4.4.0", @@ -2525,7 +2629,8 @@ "lodash.truncate": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", - "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=" + "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", + "dev": true }, "log-driver": { "version": "1.2.7", @@ -2685,6 +2790,7 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, "requires": { "brace-expansion": "^1.1.7" } @@ -2737,7 +2843,8 @@ "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=" + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true }, "nested-error-stacks": { "version": "2.1.0", @@ -2844,6 +2951,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, "requires": { "wrappy": "1" } @@ -2867,6 +2975,7 @@ "version": "0.9.1", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, "requires": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", @@ -2951,6 +3060,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, "requires": { "callsites": "^3.0.0" } @@ -2974,7 +3084,8 @@ "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true }, "path-key": { "version": "2.0.1", @@ -3041,7 +3152,8 @@ "prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==" + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true }, "private": { "version": "0.1.8", @@ -3059,7 +3171,8 @@ "progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==" + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true }, "prop-types": { "version": "15.7.2", @@ -3087,7 +3200,8 @@ "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true }, "qs": { "version": "6.5.2", @@ -3188,7 +3302,8 @@ "regexpp": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", - "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==" + "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", + "dev": true }, "release-zalgo": { "version": "1.0.0", @@ -3253,7 +3368,8 @@ "require-from-string": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==" + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true }, "require-main-filename": { "version": "2.0.0", @@ -3377,6 +3493,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, "requires": { "ansi-styles": "^4.0.0", "astral-regex": "^2.0.0", @@ -3387,6 +3504,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "requires": { "color-convert": "^2.0.1" } @@ -3395,6 +3513,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "requires": { "color-name": "~1.1.4" } @@ -3402,12 +3521,14 @@ "color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, "is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true } } }, @@ -3476,7 +3597,8 @@ "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true }, "sshpk": { "version": "1.16.1", @@ -3600,7 +3722,8 @@ "strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==" + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true }, "supports-color": { "version": "2.0.0", @@ -3612,6 +3735,7 @@ "version": "6.0.8", "resolved": "https://registry.npmjs.org/table/-/table-6.0.8.tgz", "integrity": "sha512-OBAdezyozae8IvjHGXBDHByVkLCcsmffXUSj8LXkNb0SluRd4ug3GFCjk6JynZONIPhOkyr0Nnvbq1rlIspXyQ==", + "dev": true, "requires": { "ajv": "^8.0.1", "is-boolean-object": "^1.1.0", @@ -3628,6 +3752,7 @@ "version": "8.0.1", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.0.1.tgz", "integrity": "sha512-46ZA4TalFcLLqX1dEU3dhdY38wAtDydJ4e7QQTVekLUTzXkb1LfqU6VOBXC/a9wiv4T094WURqJH6ZitF92Kqw==", + "dev": true, "requires": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", @@ -3638,27 +3763,32 @@ "ansi-regex": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true }, "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true }, "is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true }, "json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true }, "string-width": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dev": true, "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -3669,6 +3799,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, "requires": { "ansi-regex": "^5.0.0" } @@ -3722,6 +3853,14 @@ "write-file-atomic": "^2.4.2", "yaml": "^1.5.1", "yapool": "^1.0.0" + }, + "dependencies": { + "typescript": { + "version": "3.9.9", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.9.tgz", + "integrity": "sha512-kdMjTiekY+z/ubJCATUPlRDl39vXYiMV9iyeMuEuXZh2we6zz80uovNN2WlAxmmdE/Z/YQe+EbOEXB5RHEED3w==", + "dev": true + } } }, "tap-mocha-reporter": { @@ -3801,7 +3940,8 @@ "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true }, "to-fast-properties": { "version": "1.0.3", @@ -3936,6 +4076,7 @@ "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, "requires": { "prelude-ls": "^1.2.1" } @@ -3947,9 +4088,9 @@ "dev": true }, "typescript": { - "version": "3.9.9", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.9.tgz", - "integrity": "sha512-kdMjTiekY+z/ubJCATUPlRDl39vXYiMV9iyeMuEuXZh2we6zz80uovNN2WlAxmmdE/Z/YQe+EbOEXB5RHEED3w==", + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.4.tgz", + "integrity": "sha512-V+evlYHZnQkaz8TRBuxTA92yZBPotr5H+WhQ7bD3hZUndx5tGOa1fuCgeSjxAzM1RiN5IzvadIXTVefuuwZCRg==", "dev": true }, "underscore": { @@ -3986,6 +4127,7 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, "requires": { "punycode": "^2.1.0" } @@ -4006,7 +4148,8 @@ "v8-compile-cache": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==" + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "dev": true }, "validate-npm-package-license": { "version": "3.0.4", @@ -4096,7 +4239,8 @@ "word-wrap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==" + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true }, "wrap-ansi": { "version": "2.1.0", @@ -4133,7 +4277,8 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true }, "write-file-atomic": { "version": "2.4.3", diff --git a/package.json b/package.json index 2d28ed1..70759f4 100644 --- a/package.json +++ b/package.json @@ -23,15 +23,17 @@ "lib": "./lib/memjs" }, "scripts": { - "test": "eslint ./lib/memjs/ ./test/ && tap --no-coverage -R spec ./test/*.js", - "bench": "NODE_PATH=lib/memjs/ node bench/memjs.js", - "bench-timers": "NODE_PATH=lib/memjs/ node bench/timers.js" + "test": "eslint ./src && tsc && tap --no-coverage -R spec ./lib/test/*.js", + "bench": "tsc && NODE_PATH=lib/memjs/ node bench/memjs.js", + "bench-timers": "tsc && NODE_PATH=lib/memjs/ node bench/timers.js" }, "devDependencies": { + "@types/node": "12.20.7", "benchmark": "^2.1.4", "docco": "^0.8.0", + "eslint": "^7.23.0", "microtime": "^3.0.0", "tap": "14.0.*", - "eslint": "^7.23.0" + "typescript": "4.2.4" } } From 11198390a79ec5bdccf134c45a8c044c34f279b2 Mon Sep 17 00:00:00 2001 From: Jake Teton-Landis Date: Fri, 9 Apr 2021 13:17:16 -0700 Subject: [PATCH 13/79] rename .js to .ts --- src/memjs/{constants.js => constants.ts} | 0 src/memjs/{header.js => header.ts} | 0 src/memjs/{memjs.js => memjs.ts} | 0 src/memjs/{noop-serializer.js => noop-serializer.ts} | 0 src/memjs/{protocol.js => protocol.ts} | 0 src/memjs/{server.js => server.ts} | 0 src/memjs/{utils.js => utils.ts} | 0 src/test/{client_test.js => client_test.ts} | 0 src/test/{header_test.js => header_test.ts} | 0 src/test/{server_test.js => server_test.ts} | 0 src/test/{utils_test.js => utils_test.ts} | 0 11 files changed, 0 insertions(+), 0 deletions(-) rename src/memjs/{constants.js => constants.ts} (100%) rename src/memjs/{header.js => header.ts} (100%) rename src/memjs/{memjs.js => memjs.ts} (100%) rename src/memjs/{noop-serializer.js => noop-serializer.ts} (100%) rename src/memjs/{protocol.js => protocol.ts} (100%) rename src/memjs/{server.js => server.ts} (100%) rename src/memjs/{utils.js => utils.ts} (100%) rename src/test/{client_test.js => client_test.ts} (100%) rename src/test/{header_test.js => header_test.ts} (100%) rename src/test/{server_test.js => server_test.ts} (100%) rename src/test/{utils_test.js => utils_test.ts} (100%) diff --git a/src/memjs/constants.js b/src/memjs/constants.ts similarity index 100% rename from src/memjs/constants.js rename to src/memjs/constants.ts diff --git a/src/memjs/header.js b/src/memjs/header.ts similarity index 100% rename from src/memjs/header.js rename to src/memjs/header.ts diff --git a/src/memjs/memjs.js b/src/memjs/memjs.ts similarity index 100% rename from src/memjs/memjs.js rename to src/memjs/memjs.ts diff --git a/src/memjs/noop-serializer.js b/src/memjs/noop-serializer.ts similarity index 100% rename from src/memjs/noop-serializer.js rename to src/memjs/noop-serializer.ts diff --git a/src/memjs/protocol.js b/src/memjs/protocol.ts similarity index 100% rename from src/memjs/protocol.js rename to src/memjs/protocol.ts diff --git a/src/memjs/server.js b/src/memjs/server.ts similarity index 100% rename from src/memjs/server.js rename to src/memjs/server.ts diff --git a/src/memjs/utils.js b/src/memjs/utils.ts similarity index 100% rename from src/memjs/utils.js rename to src/memjs/utils.ts diff --git a/src/test/client_test.js b/src/test/client_test.ts similarity index 100% rename from src/test/client_test.js rename to src/test/client_test.ts diff --git a/src/test/header_test.js b/src/test/header_test.ts similarity index 100% rename from src/test/header_test.js rename to src/test/header_test.ts diff --git a/src/test/server_test.js b/src/test/server_test.ts similarity index 100% rename from src/test/server_test.js rename to src/test/server_test.ts diff --git a/src/test/utils_test.js b/src/test/utils_test.ts similarity index 100% rename from src/test/utils_test.js rename to src/test/utils_test.ts From 35a47898e7a15221c0fb98cca43b7e091379795a Mon Sep 17 00:00:00 2001 From: Jake Teton-Landis Date: Fri, 9 Apr 2021 13:18:00 -0700 Subject: [PATCH 14/79] constants: convert to module --- src/memjs/constants.ts | 300 ++++++++++++++++++++--------------------- 1 file changed, 150 insertions(+), 150 deletions(-) diff --git a/src/memjs/constants.ts b/src/memjs/constants.ts index 37ce8ac..a3f0012 100644 --- a/src/memjs/constants.ts +++ b/src/memjs/constants.ts @@ -1,4 +1,3 @@ - /* Constants from memcached binary protocol docs https://github.com/couchbase/memcached/blob/master/docs/BinaryProtocol.md#0x0d-getkq-get-with-key-quietly @@ -6,154 +5,155 @@ https://github.com/couchbase/memcached/blob/master/docs/BinaryProtocol.md#0x0d-g Note: not all constants in here are implemented in this library, not all constants from the docs are included here */ -exports.OP_GET = 0x00; -exports.OP_SET = 0x01; -exports.OP_ADD = 0x02; -exports.OP_REPLACE = 0x03; -exports.OP_DELETE = 0x04; -exports.OP_INCREMENT = 0x05; -exports.OP_DECREMENT = 0x06; -exports.OP_QUIT = 0x07; -exports.OP_FLUSH = 0x08; -exports.OP_GETQ = 0x09; -exports.OP_NO_OP = 0x0A; -exports.OP_VERSION = 0x0B; -exports.OP_GETK = 0x0C; -exports.OP_GETKQ = 0x0D; -exports.OP_APPEND = 0x0E; -exports.OP_PREPEND = 0x0F; -exports.OP_STAT = 0x10; -exports.OP_SETQ = 0x11; -exports.OP_ADDQ = 0x12; -exports.OP_REPLACEQ = 0x13; -exports.OP_DELETEQ = 0x14; -exports.OP_INCREMENTQ = 0x15; -exports.OP_DECREMENTQ = 0x16; -exports.OP_QUITQ = 0x17; -exports.OP_FLUSHQ = 0x18; -exports.OP_APPENDQ = 0x19; -exports.OP_PREPENDQ = 0x1A; -exports.OP_VERBOSITY = 0x1B; -exports.OP_TOUCH = 0x1C; -exports.OP_GAT = 0x1D; -exports.OP_GATQ = 0x1E; -exports.OP_HELO = 0x1F; -exports.OP_SASL_LIST_MECHS = 0x20; -exports.OP_SASL_AUTH = 0x21; -exports.OP_SASL_STEP = 0x22; -exports.OP_IOCTL_GET = 0x23; -exports.OP_IOCTL_SET = 0x24; -exports.OP_CONFIG_VALIDATE = 0x25; -exports.OP_CONFIG_RELOAD = 0x26; -exports.OP_AUDIT_PUT = 0x27; -exports.OP_AUDIT_CONFIG_RELOAD = 0x28; -exports.OP_SHUTDOWN = 0x29; -exports.OP_RGET = 0x30; -exports.OP_RSET = 0x31; -exports.OP_RSETQ = 0x32; -exports.OP_RAPPEND = 0x33; -exports.OP_RAPPENDQ = 0x34; -exports.OP_RPREPEND = 0x35; -exports.OP_RPREPENDQ = 0x36; -exports.OP_RDELETE = 0x37; -exports.OP_RDELETEQ = 0x38; -exports.OP_RINCR = 0x39; -exports.OP_RINCRQ = 0x3A; -exports.OP_RDECR = 0x3B; -exports.OP_RDECRQ = 0x3C; -exports.OP_SET_VBUCKET = 0x3D; -exports.OP_GET_VBUCKET = 0x3E; -exports.OP_DEL_VBUCKET = 0x3F; -exports.OP_TAP_CONNECT = 0x40; -exports.OP_TAP_MUTATION = 0x41; -exports.OP_TAP_DELETE = 0x42; -exports.OP_TAP_FLUSH = 0x43; -exports.OP_TAP_OPAQUE = 0x44; -exports.OP_TAP_VBUCKET_SET = 0x45; -exports.OP_TAP_CHECKOUT_START = 0x46; -exports.OP_TAP_CHECKPOINT_END = 0x47; -exports.OP_GET_ALL_VB_SEQNOS = 0x48; -exports.OP_DCP_OPEN = 0x50; -exports.OP_DCP_ADD_STREAM = 0x51; -exports.OP_DCP_CLOSE_STREAM = 0x52; -exports.OP_DCP_STREAM_REQ = 0x53; -exports.OP_DCP_GET_FAILOVER_LOG = 0x54; -exports.OP_DCP_STREAM_END = 0x55; -exports.OP_DCP_SNAPSHOT_MARKER = 0x56; -exports.OP_DCP_MUTATION = 0x57; -exports.OP_DCP_DELETION = 0x58; -exports.OP_DCP_EXPIRATION = 0x59; -exports.OP_DCP_FLUSH = 0x5A; -exports.OP_DCP_SET_VBUCKET_STATE = 0x5B; -exports.OP_DCP_NOOP = 0x5C; -exports.OP_DCP_BUFFER_ACKNOWLEDGEMENT = 0x5D; -exports.OP_DCP_CONTROL = 0x5E; -exports.OP_DCP_RESERVED4 = 0x5F; -exports.OP_STOP_PERSISTENCE = 0x80; -exports.OP_START_PERSISTENCE = 0x81; -exports.OP_SET_PARAM = 0x82; -exports.OP_GET_REPLICA = 0x83; -exports.OP_CREATE_BUCKET = 0x85; -exports.OP_DELETE_BUCKET = 0x86; -exports.OP_LIST_BUCKETS = 0x87; -exports.OP_SELECT_BUCKET = 0x89; -exports.OP_ASSUME_ROLE = 0x8A; -exports.OP_OBSERVE_SEQNO = 0x91; -exports.OP_OBSERVE = 0x92; -exports.OP_EVICT_KEY = 0x93; -exports.OP_GET_LOCKED = 0x94; -exports.OP_UNLOCK_KEY = 0x95; -exports.OP_LAST_CLOSED_CHECKPOINT = 0x97; -exports.OP_DEREGISTER_TAP_CLIENT = 0x9E; -exports.OP_RESET_REPLICATION_CHAIN = 0x9F; -exports.OP_GET_META = 0xA0; -exports.OP_GETQ_META = 0xA1; -exports.OP_SET_WITH_META = 0xA2; -exports.OP_SETQ_WITH_META = 0xA3; -exports.OP_ADD_WITH_META = 0xA4; -exports.OP_ADDQ_WITH_META = 0xA5; -exports.OP_SNAPSHOT_VB_STATES = 0xA6; -exports.OP_VBUCKET_BATCH_COUNT = 0xA7; -exports.OP_DEL_WITH_META = 0xA8; -exports.OP_DELQ_WITH_META = 0xA9; -exports.OP_CREATE_CHECKPOINT = 0xAA; -exports.OP_NOTIFY_VBUCKET_UPDATE = 0xAC; -exports.OP_ENABLE_TRAFFIC = 0xAD; -exports.OP_DISABLE_TRAFFIC = 0xAE; -exports.OP_CHANGE_VB_FILTER = 0xB0; -exports.OP_CHECKPOINT_PERSISTENCE = 0xB1; -exports.OP_RETURN_META = 0xB2; -exports.OP_COMPACT_DB = 0xB3; -exports.OP_SET_CLUSTER_CONFIG = 0xB4; -exports.OP_GET_CLUSTER_CONFIG = 0xB5; -exports.OP_GET_RANDOM_KEY = 0xB6; -exports.OP_SEQNO_PERSISTENCE = 0xB7; -exports.OP_GET_KEYS = 0xB8; -exports.OP_SET_DRIFT_COUNTER_STATE = 0xC1; -exports.OP_GET_ADJUSTED_TIME = 0xC2; -exports.OP_SUBDOC_GET = 0xC5; -exports.OP_SUBDOC_EXISTS = 0xC6; -exports.OP_SUBDOC_DICT_ADD = 0xC7; -exports.OP_SUBDOC_DICT_UPSERT = 0xC8; -exports.OP_SUBDOC_DELETE = 0xC9; -exports.OP_SUBDOC_REPLACE = 0xCA; -exports.OP_SUBDOC_ARRAY_PUSH_LAST = 0xCB; -exports.OP_SUBDOC_ARRAY_PUSH_FIRST = 0xCC; -exports.OP_SUBDOC_ARRAY_INSERT = 0xCD; -exports.OP_SUBDOC_ARRAY_ADD_UNIQUE = 0xCE; -exports.OP_SUBDOC_COUNTER = 0xCF; -exports.OP_SUBDOC_MULTI_LOOKUP = 0xD0; -exports.OP_SUBDOC_MULTI_MUTATION = 0xD1; -exports.OP_SUBDOC_GET_COUNT = 0xD2; -exports.OP_SCRUB = 0xF0; -exports.OP_ISASL_REFRESH = 0xF1; -exports.OP_SSL_CERTS_REFRESH = 0xF2; -exports.OP_GET_CMD_TIMER = 0xF3; -exports.OP_SET_CTRL_TOKEN = 0xF4; -exports.OP_GET_CTRL_TOKEN = 0xF5; -exports.OP_INIT_COMPLETE = 0xF6; +export const OP_GET = 0x00; +export const OP_SET = 0x01; +export const OP_ADD = 0x02; +export const OP_REPLACE = 0x03; +export const OP_DELETE = 0x04; +export const OP_INCREMENT = 0x05; +export const OP_DECREMENT = 0x06; +export const OP_QUIT = 0x07; +export const OP_FLUSH = 0x08; +export const OP_GETQ = 0x09; +export const OP_NO_OP = 0x0a; +export const OP_VERSION = 0x0b; +export const OP_GETK = 0x0c; +export const OP_GETKQ = 0x0d; +export const OP_APPEND = 0x0e; +export const OP_PREPEND = 0x0f; +export const OP_STAT = 0x10; +export const OP_SETQ = 0x11; +export const OP_ADDQ = 0x12; +export const OP_REPLACEQ = 0x13; +export const OP_DELETEQ = 0x14; +export const OP_INCREMENTQ = 0x15; +export const OP_DECREMENTQ = 0x16; +export const OP_QUITQ = 0x17; +export const OP_FLUSHQ = 0x18; +export const OP_APPENDQ = 0x19; +export const OP_PREPENDQ = 0x1a; +export const OP_VERBOSITY = 0x1b; +export const OP_TOUCH = 0x1c; +export const OP_GAT = 0x1d; +export const OP_GATQ = 0x1e; +export const OP_HELO = 0x1f; +export const OP_SASL_LIST_MECHS = 0x20; +export const OP_SASL_AUTH = 0x21; +export const OP_SASL_STEP = 0x22; +export const OP_IOCTL_GET = 0x23; +export const OP_IOCTL_SET = 0x24; +export const OP_CONFIG_VALIDATE = 0x25; +export const OP_CONFIG_RELOAD = 0x26; +export const OP_AUDIT_PUT = 0x27; +export const OP_AUDIT_CONFIG_RELOAD = 0x28; +export const OP_SHUTDOWN = 0x29; +export const OP_RGET = 0x30; +export const OP_RSET = 0x31; +export const OP_RSETQ = 0x32; +export const OP_RAPPEND = 0x33; +export const OP_RAPPENDQ = 0x34; +export const OP_RPREPEND = 0x35; +export const OP_RPREPENDQ = 0x36; +export const OP_RDELETE = 0x37; +export const OP_RDELETEQ = 0x38; +export const OP_RINCR = 0x39; +export const OP_RINCRQ = 0x3a; +export const OP_RDECR = 0x3b; +export const OP_RDECRQ = 0x3c; +export const OP_SET_VBUCKET = 0x3d; +export const OP_GET_VBUCKET = 0x3e; +export const OP_DEL_VBUCKET = 0x3f; +export const OP_TAP_CONNECT = 0x40; +export const OP_TAP_MUTATION = 0x41; +export const OP_TAP_DELETE = 0x42; +export const OP_TAP_FLUSH = 0x43; +export const OP_TAP_OPAQUE = 0x44; +export const OP_TAP_VBUCKET_SET = 0x45; +export const OP_TAP_CHECKOUT_START = 0x46; +export const OP_TAP_CHECKPOINT_END = 0x47; +export const OP_GET_ALL_VB_SEQNOS = 0x48; +export const OP_DCP_OPEN = 0x50; +export const OP_DCP_ADD_STREAM = 0x51; +export const OP_DCP_CLOSE_STREAM = 0x52; +export const OP_DCP_STREAM_REQ = 0x53; +export const OP_DCP_GET_FAILOVER_LOG = 0x54; +export const OP_DCP_STREAM_END = 0x55; +export const OP_DCP_SNAPSHOT_MARKER = 0x56; +export const OP_DCP_MUTATION = 0x57; +export const OP_DCP_DELETION = 0x58; +export const OP_DCP_EXPIRATION = 0x59; +export const OP_DCP_FLUSH = 0x5a; +export const OP_DCP_SET_VBUCKET_STATE = 0x5b; +export const OP_DCP_NOOP = 0x5c; +export const OP_DCP_BUFFER_ACKNOWLEDGEMENT = 0x5d; +export const OP_DCP_CONTROL = 0x5e; +export const OP_DCP_RESERVED4 = 0x5f; +export const OP_STOP_PERSISTENCE = 0x80; +export const OP_START_PERSISTENCE = 0x81; +export const OP_SET_PARAM = 0x82; +export const OP_GET_REPLICA = 0x83; +export const OP_CREATE_BUCKET = 0x85; +export const OP_DELETE_BUCKET = 0x86; +export const OP_LIST_BUCKETS = 0x87; +export const OP_SELECT_BUCKET = 0x89; +export const OP_ASSUME_ROLE = 0x8a; +export const OP_OBSERVE_SEQNO = 0x91; +export const OP_OBSERVE = 0x92; +export const OP_EVICT_KEY = 0x93; +export const OP_GET_LOCKED = 0x94; +export const OP_UNLOCK_KEY = 0x95; +export const OP_LAST_CLOSED_CHECKPOINT = 0x97; +export const OP_DEREGISTER_TAP_CLIENT = 0x9e; +export const OP_RESET_REPLICATION_CHAIN = 0x9f; +export const OP_GET_META = 0xa0; +export const OP_GETQ_META = 0xa1; +export const OP_SET_WITH_META = 0xa2; +export const OP_SETQ_WITH_META = 0xa3; +export const OP_ADD_WITH_META = 0xa4; +export const OP_ADDQ_WITH_META = 0xa5; +export const OP_SNAPSHOT_VB_STATES = 0xa6; +export const OP_VBUCKET_BATCH_COUNT = 0xa7; +export const OP_DEL_WITH_META = 0xa8; +export const OP_DELQ_WITH_META = 0xa9; +export const OP_CREATE_CHECKPOINT = 0xaa; +export const OP_NOTIFY_VBUCKET_UPDATE = 0xac; +export const OP_ENABLE_TRAFFIC = 0xad; +export const OP_DISABLE_TRAFFIC = 0xae; +export const OP_CHANGE_VB_FILTER = 0xb0; +export const OP_CHECKPOINT_PERSISTENCE = 0xb1; +export const OP_RETURN_META = 0xb2; +export const OP_COMPACT_DB = 0xb3; +export const OP_SET_CLUSTER_CONFIG = 0xb4; +export const OP_GET_CLUSTER_CONFIG = 0xb5; +export const OP_GET_RANDOM_KEY = 0xb6; +export const OP_SEQNO_PERSISTENCE = 0xb7; +export const OP_GET_KEYS = 0xb8; +export const OP_SET_DRIFT_COUNTER_STATE = 0xc1; +export const OP_GET_ADJUSTED_TIME = 0xc2; +export const OP_SUBDOC_GET = 0xc5; +export const OP_SUBDOC_EXISTS = 0xc6; +export const OP_SUBDOC_DICT_ADD = 0xc7; +export const OP_SUBDOC_DICT_UPSERT = 0xc8; +export const OP_SUBDOC_DELETE = 0xc9; +export const OP_SUBDOC_REPLACE = 0xca; +export const OP_SUBDOC_ARRAY_PUSH_LAST = 0xcb; +export const OP_SUBDOC_ARRAY_PUSH_FIRST = 0xcc; +export const OP_SUBDOC_ARRAY_INSERT = 0xcd; +export const OP_SUBDOC_ARRAY_ADD_UNIQUE = 0xce; +export const OP_SUBDOC_COUNTER = 0xcf; +export const OP_SUBDOC_MULTI_LOOKUP = 0xd0; +export const OP_SUBDOC_MULTI_MUTATION = 0xd1; +export const OP_SUBDOC_GET_COUNT = 0xd2; +export const OP_SCRUB = 0xf0; +export const OP_ISASL_REFRESH = 0xf1; +export const OP_SSL_CERTS_REFRESH = 0xf2; +export const OP_GET_CMD_TIMER = 0xf3; +export const OP_SET_CTRL_TOKEN = 0xf4; +export const OP_GET_CTRL_TOKEN = 0xf5; +export const OP_INIT_COMPLETE = 0xf6; // Named "No Error" in the memcache docs but this seems like it will be clearer -exports.RESPONSE_STATUS_SUCCCESS = 0x00; -exports.RESPONSE_STATUS_KEY_NOT_FOUND = 0x01; -exports.RESPONSE_STATUS_KEY_EXISTS = 0x02; \ No newline at end of file +export const RESPONSE_STATUS_SUCCCESS = 0x00; +export const RESPONSE_STATUS_KEY_NOT_FOUND = 0x01; +export const RESPONSE_STATUS_KEY_EXISTS = 0x02; + From fc911c6b1358effbbeee57503dda0d84fa6a9ff1 Mon Sep 17 00:00:00 2001 From: Jake Teton-Landis Date: Fri, 9 Apr 2021 13:24:38 -0700 Subject: [PATCH 15/79] tsify header.ts --- src/memjs/constants.ts | 152 +++++++++++++++++++++++++++++++++++++++++ src/memjs/header.ts | 46 ++++++++----- 2 files changed, 182 insertions(+), 16 deletions(-) diff --git a/src/memjs/constants.ts b/src/memjs/constants.ts index a3f0012..7b81690 100644 --- a/src/memjs/constants.ts +++ b/src/memjs/constants.ts @@ -152,8 +152,160 @@ export const OP_SET_CTRL_TOKEN = 0xf4; export const OP_GET_CTRL_TOKEN = 0xf5; export const OP_INIT_COMPLETE = 0xf6; +export type OP = + | typeof OP_GET + | typeof OP_SET + | typeof OP_ADD + | typeof OP_REPLACE + | typeof OP_DELETE + | typeof OP_INCREMENT + | typeof OP_DECREMENT + | typeof OP_QUIT + | typeof OP_FLUSH + | typeof OP_GETQ + | typeof OP_NO_OP + | typeof OP_VERSION + | typeof OP_GETK + | typeof OP_GETKQ + | typeof OP_APPEND + | typeof OP_PREPEND + | typeof OP_STAT + | typeof OP_SETQ + | typeof OP_ADDQ + | typeof OP_REPLACEQ + | typeof OP_DELETEQ + | typeof OP_INCREMENTQ + | typeof OP_DECREMENTQ + | typeof OP_QUITQ + | typeof OP_FLUSHQ + | typeof OP_APPENDQ + | typeof OP_PREPENDQ + | typeof OP_VERBOSITY + | typeof OP_TOUCH + | typeof OP_GAT + | typeof OP_GATQ + | typeof OP_HELO + | typeof OP_SASL_LIST_MECHS + | typeof OP_SASL_AUTH + | typeof OP_SASL_STEP + | typeof OP_IOCTL_GET + | typeof OP_IOCTL_SET + | typeof OP_CONFIG_VALIDATE + | typeof OP_CONFIG_RELOAD + | typeof OP_AUDIT_PUT + | typeof OP_AUDIT_CONFIG_RELOAD + | typeof OP_SHUTDOWN + | typeof OP_RGET + | typeof OP_RSET + | typeof OP_RSETQ + | typeof OP_RAPPEND + | typeof OP_RAPPENDQ + | typeof OP_RPREPEND + | typeof OP_RPREPENDQ + | typeof OP_RDELETE + | typeof OP_RDELETEQ + | typeof OP_RINCR + | typeof OP_RINCRQ + | typeof OP_RDECR + | typeof OP_RDECRQ + | typeof OP_SET_VBUCKET + | typeof OP_GET_VBUCKET + | typeof OP_DEL_VBUCKET + | typeof OP_TAP_CONNECT + | typeof OP_TAP_MUTATION + | typeof OP_TAP_DELETE + | typeof OP_TAP_FLUSH + | typeof OP_TAP_OPAQUE + | typeof OP_TAP_VBUCKET_SET + | typeof OP_TAP_CHECKOUT_START + | typeof OP_TAP_CHECKPOINT_END + | typeof OP_GET_ALL_VB_SEQNOS + | typeof OP_DCP_OPEN + | typeof OP_DCP_ADD_STREAM + | typeof OP_DCP_CLOSE_STREAM + | typeof OP_DCP_STREAM_REQ + | typeof OP_DCP_GET_FAILOVER_LOG + | typeof OP_DCP_STREAM_END + | typeof OP_DCP_SNAPSHOT_MARKER + | typeof OP_DCP_MUTATION + | typeof OP_DCP_DELETION + | typeof OP_DCP_EXPIRATION + | typeof OP_DCP_FLUSH + | typeof OP_DCP_SET_VBUCKET_STATE + | typeof OP_DCP_NOOP + | typeof OP_DCP_BUFFER_ACKNOWLEDGEMENT + | typeof OP_DCP_CONTROL + | typeof OP_DCP_RESERVED4 + | typeof OP_STOP_PERSISTENCE + | typeof OP_START_PERSISTENCE + | typeof OP_SET_PARAM + | typeof OP_GET_REPLICA + | typeof OP_CREATE_BUCKET + | typeof OP_DELETE_BUCKET + | typeof OP_LIST_BUCKETS + | typeof OP_SELECT_BUCKET + | typeof OP_ASSUME_ROLE + | typeof OP_OBSERVE_SEQNO + | typeof OP_OBSERVE + | typeof OP_EVICT_KEY + | typeof OP_GET_LOCKED + | typeof OP_UNLOCK_KEY + | typeof OP_LAST_CLOSED_CHECKPOINT + | typeof OP_DEREGISTER_TAP_CLIENT + | typeof OP_RESET_REPLICATION_CHAIN + | typeof OP_GET_META + | typeof OP_GETQ_META + | typeof OP_SET_WITH_META + | typeof OP_SETQ_WITH_META + | typeof OP_ADD_WITH_META + | typeof OP_ADDQ_WITH_META + | typeof OP_SNAPSHOT_VB_STATES + | typeof OP_VBUCKET_BATCH_COUNT + | typeof OP_DEL_WITH_META + | typeof OP_DELQ_WITH_META + | typeof OP_CREATE_CHECKPOINT + | typeof OP_NOTIFY_VBUCKET_UPDATE + | typeof OP_ENABLE_TRAFFIC + | typeof OP_DISABLE_TRAFFIC + | typeof OP_CHANGE_VB_FILTER + | typeof OP_CHECKPOINT_PERSISTENCE + | typeof OP_RETURN_META + | typeof OP_COMPACT_DB + | typeof OP_SET_CLUSTER_CONFIG + | typeof OP_GET_CLUSTER_CONFIG + | typeof OP_GET_RANDOM_KEY + | typeof OP_SEQNO_PERSISTENCE + | typeof OP_GET_KEYS + | typeof OP_SET_DRIFT_COUNTER_STATE + | typeof OP_GET_ADJUSTED_TIME + | typeof OP_SUBDOC_GET + | typeof OP_SUBDOC_EXISTS + | typeof OP_SUBDOC_DICT_ADD + | typeof OP_SUBDOC_DICT_UPSERT + | typeof OP_SUBDOC_DELETE + | typeof OP_SUBDOC_REPLACE + | typeof OP_SUBDOC_ARRAY_PUSH_LAST + | typeof OP_SUBDOC_ARRAY_PUSH_FIRST + | typeof OP_SUBDOC_ARRAY_INSERT + | typeof OP_SUBDOC_ARRAY_ADD_UNIQUE + | typeof OP_SUBDOC_COUNTER + | typeof OP_SUBDOC_MULTI_LOOKUP + | typeof OP_SUBDOC_MULTI_MUTATION + | typeof OP_SUBDOC_GET_COUNT + | typeof OP_SCRUB + | typeof OP_ISASL_REFRESH + | typeof OP_SSL_CERTS_REFRESH + | typeof OP_GET_CMD_TIMER + | typeof OP_SET_CTRL_TOKEN + | typeof OP_GET_CTRL_TOKEN + | typeof OP_INIT_COMPLETE; + // Named "No Error" in the memcache docs but this seems like it will be clearer export const RESPONSE_STATUS_SUCCCESS = 0x00; export const RESPONSE_STATUS_KEY_NOT_FOUND = 0x01; export const RESPONSE_STATUS_KEY_EXISTS = 0x02; +export type ResponseStatus = + | typeof RESPONSE_STATUS_SUCCCESS + | typeof RESPONSE_STATUS_KEY_NOT_FOUND + | typeof RESPONSE_STATUS_KEY_EXISTS; diff --git a/src/memjs/header.ts b/src/memjs/header.ts index e3ac306..8d754c3 100644 --- a/src/memjs/header.ts +++ b/src/memjs/header.ts @@ -1,27 +1,41 @@ // # MemJS Memcache binary protocol header -// fromBuffer converts a serialized header to a JS object. -exports.fromBuffer = function(headerBuf) { +import { OP, ResponseStatus } from "./constants"; + +export interface Header { + magic: number; + opcode: OP; + keyLength: number; + extrasLength: number; + dataType: number; + status: ResponseStatus; + totalBodyLength: number; + opaque: number; + cas: Buffer; +} + +/** fromBuffer converts a serialized header to a JS object. */ +export function fromBuffer(headerBuf: Buffer): Header | {} { if (!headerBuf) { return {}; } return { - magic: headerBuf.readUInt8(0), - opcode: headerBuf.readUInt8(1), - keyLength: headerBuf.readUInt16BE(2), - extrasLength: headerBuf.readUInt8(4), - dataType: headerBuf.readUInt8(5), - status: headerBuf.readUInt16BE(6), + magic: headerBuf.readUInt8(0), + opcode: headerBuf.readUInt8(1), + keyLength: headerBuf.readUInt16BE(2), + extrasLength: headerBuf.readUInt8(4), + dataType: headerBuf.readUInt8(5), + status: headerBuf.readUInt16BE(6), totalBodyLength: headerBuf.readUInt32BE(8), - opaque: headerBuf.readUInt32BE(12), - cas: headerBuf.slice(16, 24) + opaque: headerBuf.readUInt32BE(12), + cas: headerBuf.slice(16, 24), }; -}; +} -// toBuffer converts a JS memcache header object to a binary memcache header -exports.toBuffer = function(header) { +/** toBuffer converts a JS memcache header object to a binary memcache header */ +export function toBuffer(header: Header) { var headerBuf = Buffer.alloc(24); - headerBuf.fill(); + headerBuf.fill(0); headerBuf.writeUInt8(header.magic, 0); headerBuf.writeUInt8(header.opcode, 1); headerBuf.writeUInt16BE(header.keyLength, 2); @@ -33,7 +47,7 @@ exports.toBuffer = function(header) { if (header.cas) { header.cas.copy(headerBuf, 16); } else { - headerBuf.fill('\x00', 16); + headerBuf.fill("\x00", 16); } return headerBuf; -}; +} From 998ae68b7f8d28a2168ad384254d310b5786eb92 Mon Sep 17 00:00:00 2001 From: Jake Teton-Landis Date: Fri, 9 Apr 2021 13:27:29 -0700 Subject: [PATCH 16/79] protocol.ts --- src/memjs/protocol.ts | 37 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/src/memjs/protocol.ts b/src/memjs/protocol.ts index 8b4fa5d..2492cbd 100644 --- a/src/memjs/protocol.ts +++ b/src/memjs/protocol.ts @@ -1,19 +1,18 @@ -// # MemJS Memcache binary protocol errors - -exports.errors = {}; -exports.errors[0x0000] = 'No error'; -exports.errors[0x0001] = 'Key not found'; -exports.errors[0x0002] = 'Key exists'; -exports.errors[0x0003] = 'Value too large'; -exports.errors[0x0004] = 'Invalid arguments'; -exports.errors[0x0005] = 'Item not stored'; -exports.errors[0x0006] = 'Incr/Decr on non-numeric value'; -exports.errors[0x0007] = 'The vbucket belongs to another server'; -exports.errors[0x0008] = 'Authentication error'; -exports.errors[0x0009] = 'Authentication continue'; -exports.errors[0x0081] = 'Unknown command'; -exports.errors[0x0082] = 'Out of memory'; -exports.errors[0x0083] = 'Not supported'; -exports.errors[0x0084] = 'Internal error'; -exports.errors[0x0085] = 'Busy'; -exports.errors[0x0086] = 'Temporary failure'; +/** MemJS Memcache binary protocol errors */ +export const errors: { [key: number]: string } = {}; +errors[0x0000] = "No error"; +errors[0x0001] = "Key not found"; +errors[0x0002] = "Key exists"; +errors[0x0003] = "Value too large"; +errors[0x0004] = "Invalid arguments"; +errors[0x0005] = "Item not stored"; +errors[0x0006] = "Incr/Decr on non-numeric value"; +errors[0x0007] = "The vbucket belongs to another server"; +errors[0x0008] = "Authentication error"; +errors[0x0009] = "Authentication continue"; +errors[0x0081] = "Unknown command"; +errors[0x0082] = "Out of memory"; +errors[0x0083] = "Not supported"; +errors[0x0084] = "Internal error"; +errors[0x0085] = "Busy"; +errors[0x0086] = "Temporary failure"; From e553a664c4d664510113a0a7e9b0f8dbe3b6f5a8 Mon Sep 17 00:00:00 2001 From: Jake Teton-Landis Date: Fri, 9 Apr 2021 13:44:34 -0700 Subject: [PATCH 17/79] utils.ts --- src/memjs/header.ts | 14 +++---- src/memjs/utils.ts | 91 ++++++++++++++++++++++++++++++--------------- 2 files changed, 69 insertions(+), 36 deletions(-) diff --git a/src/memjs/header.ts b/src/memjs/header.ts index 8d754c3..483e1e6 100644 --- a/src/memjs/header.ts +++ b/src/memjs/header.ts @@ -7,25 +7,25 @@ export interface Header { opcode: OP; keyLength: number; extrasLength: number; - dataType: number; - status: ResponseStatus; + dataType?: number; + status?: ResponseStatus; totalBodyLength: number; opaque: number; - cas: Buffer; + cas?: Buffer; } /** fromBuffer converts a serialized header to a JS object. */ -export function fromBuffer(headerBuf: Buffer): Header | {} { +export function fromBuffer(headerBuf: Buffer): Header { if (!headerBuf) { - return {}; + return {} as any; // TODO } return { magic: headerBuf.readUInt8(0), - opcode: headerBuf.readUInt8(1), + opcode: headerBuf.readUInt8(1) as OP, // TODO: wrong type? keyLength: headerBuf.readUInt16BE(2), extrasLength: headerBuf.readUInt8(4), dataType: headerBuf.readUInt8(5), - status: headerBuf.readUInt16BE(6), + status: headerBuf.readUInt16BE(6) as ResponseStatus, // TODO: wrong type? totalBodyLength: headerBuf.readUInt32BE(8), opaque: headerBuf.readUInt32BE(12), cas: headerBuf.slice(16, 24), diff --git a/src/memjs/utils.ts b/src/memjs/utils.ts index 759085c..9e7541e 100644 --- a/src/memjs/utils.ts +++ b/src/memjs/utils.ts @@ -1,31 +1,44 @@ // # MemJS utility functions -var header = require('./header'); +import * as header from "./header"; +import { OP } from "./constants"; -var bufferify = function(val) { - return Buffer.isBuffer(val) ? val : Buffer.from(val); +type MaybeBuffer = string | Buffer; + +export const bufferify = function (val: MaybeBuffer) { + return Buffer.isBuffer(val) ? val : Buffer.from(val as any); }; -exports.bufferify = bufferify; -exports.copyIntoRequestBuffer = function(opcode, key, extras, value, opaque, buf, _bufTargetWriteOffset) { +export const copyIntoRequestBuffer = function ( + opcode: OP, + key: MaybeBuffer, + extras: MaybeBuffer, + value: MaybeBuffer, + opaque: number, + buf: Buffer, + _bufTargetWriteOffset?: number +) { key = bufferify(key); extras = bufferify(extras); value = bufferify(value); var bufTargetWriteOffset = _bufTargetWriteOffset || 0; var totalBytesWritten = 0; - function copyIntoBuffer(toWriteBuffer) { - var bytesWritten = toWriteBuffer.copy(buf, bufTargetWriteOffset + totalBytesWritten); + function copyIntoBuffer(toWriteBuffer: Buffer) { + var bytesWritten = toWriteBuffer.copy( + buf, + bufTargetWriteOffset + totalBytesWritten + ); totalBytesWritten += bytesWritten; } - var requestHeader = { + var requestHeader: header.Header = { magic: 0x80, opcode: opcode, keyLength: key.length, extrasLength: extras.length, totalBodyLength: key.length + value.length + extras.length, - opaque: opaque + opaque: opaque, }; var headerBuffer = header.toBuffer(requestHeader); @@ -37,7 +50,13 @@ exports.copyIntoRequestBuffer = function(opcode, key, extras, value, opaque, buf return totalBytesWritten; }; -exports.makeRequestBuffer = function(opcode, key, extras, value, opaque) { +export const makeRequestBuffer = function ( + opcode: OP, + key: MaybeBuffer, + extras: MaybeBuffer, + value: MaybeBuffer, + opaque: number +) { key = bufferify(key); extras = bufferify(extras); value = bufferify(value); @@ -45,12 +64,16 @@ exports.makeRequestBuffer = function(opcode, key, extras, value, opaque) { var bufSize = 24 + key.length + extras.length + value.length; var buf = Buffer.alloc(bufSize); - buf.fill(); + buf.fill(0); exports.copyIntoRequestBuffer(opcode, key, extras, value, opaque, buf); return buf; }; -exports.makeAmountInitialAndExpiration = function(amount, amountIfEmpty, expiration) { +exports.makeAmountInitialAndExpiration = function ( + amount: number, + amountIfEmpty: number, + expiration: number +) { var buf = Buffer.alloc(20); buf.writeUInt32BE(0, 0); buf.writeUInt32BE(amount, 4); @@ -60,29 +83,38 @@ exports.makeAmountInitialAndExpiration = function(amount, amountIfEmpty, expirat return buf; }; -exports.makeExpiration = function(expiration) { +export const makeExpiration = function (expiration: number) { var buf = Buffer.alloc(4); buf.writeUInt32BE(expiration, 0); return buf; }; -exports.hashCode = function(str) { +export const hashCode = function (str: string) { var ret, i, len; - for(ret = 0, i = 0, len = str.length; i < len; i++) { + for (ret = 0, i = 0, len = str.length; i < len; i++) { ret = (31 * ret + str.charCodeAt(i)) << 0; } return Math.abs(ret); }; -exports.parseMessage = function(dataBuf) { +interface Message { + header: header.Header; + key: Buffer; + val: Buffer; + extras: Buffer; +} + +export const parseMessage = function (dataBuf: Buffer): Message | false { if (dataBuf.length < 24) { return false; } var responseHeader = header.fromBuffer(dataBuf); - if (dataBuf.length < responseHeader.totalBodyLength + 24 || - responseHeader.totalBodyLength < - responseHeader.keyLength + responseHeader.extrasLength) { + if ( + dataBuf.length < responseHeader.totalBodyLength + 24 || + responseHeader.totalBodyLength < + responseHeader.keyLength + responseHeader.extrasLength + ) { return false; } @@ -93,10 +125,10 @@ exports.parseMessage = function(dataBuf) { pointer += responseHeader.keyLength; var val = dataBuf.slice(pointer, 24 + responseHeader.totalBodyLength); - return {header: responseHeader, key: key, extras: extras, val: val}; + return { header: responseHeader, key: key, extras: extras, val: val }; }; -exports.parseMessages = function(dataBuf) { +export const parseMessages = function (dataBuf: Buffer): Message[] { var messages = []; do { @@ -111,8 +143,9 @@ exports.parseMessages = function(dataBuf) { return messages; }; -exports.merge = function(original, deflt) { - for (let attr of Object.keys(deflt)) { +export const merge = function (original: T, deflt: T): T { + for (let attrT of Object.keys(deflt)) { + const attr: keyof T = attrT as any; const originalValue = original[attr]; if (originalValue === undefined || originalValue === null) { @@ -124,15 +157,15 @@ exports.merge = function(original, deflt) { // timestamp provides a monotonic timestamp with millisecond accuracy, useful // for timers. -exports.timestamp = function() { +export const timestamp = function () { var times = process.hrtime(); - return (times[0] * 1000) + Math.round((times[1] / 1000000)); + return times[0] * 1000 + Math.round(times[1] / 1000000); }; -if(!Buffer.concat) { - Buffer.concat = function(list, length) { +if (!Buffer.concat) { + Buffer.concat = function (list, length) { if (!Array.isArray(list)) { - throw new Error('Usage: Buffer.concat(list, [length])'); + throw new Error("Usage: Buffer.concat(list, [length])"); } if (list.length === 0) { @@ -144,7 +177,7 @@ if(!Buffer.concat) { var i, buf; - if (typeof length !== 'number') { + if (typeof length !== "number") { length = 0; for (i = 0; i < list.length; i++) { buf = list[i]; From efc52d6f0d7450cbcf28a84cb59a0a6d2fe4509e Mon Sep 17 00:00:00 2001 From: Jake Teton-Landis Date: Fri, 9 Apr 2021 13:49:36 -0700 Subject: [PATCH 18/79] serializer.ts --- src/memjs/noop-serializer.ts | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/memjs/noop-serializer.ts b/src/memjs/noop-serializer.ts index 69b7477..febc477 100644 --- a/src/memjs/noop-serializer.ts +++ b/src/memjs/noop-serializer.ts @@ -1,10 +1,24 @@ -var noopSerializer = { +import { OP } from "./constants"; +import { MaybeBuffer } from "./utils"; + +interface Serializer { + serialize( + opcode: OP, + value: Value, + extras: Extras + ): { value: MaybeBuffer; extras: MaybeBuffer }; + deserialize( + opcode: OP, + value: MaybeBuffer, + extras: MaybeBuffer + ): { value: Value; extras: Extras }; +} + +export const noopSerializer: Serializer = { serialize: function (opcode, value, extras) { return { value: value, extras: extras }; }, deserialize: function (opcode, value, extras) { return { value: value, extras: extras }; - } + }, }; - -exports.noopSerializer = noopSerializer; From 67db71508282ceacb2e1a7623022a1f01144c3b3 Mon Sep 17 00:00:00 2001 From: Jake Teton-Landis Date: Fri, 9 Apr 2021 15:01:11 -0700 Subject: [PATCH 19/79] server.ts --- src/memjs/header.ts | 2 +- src/memjs/server.ts | 437 +++++++++++++++++++++++++------------------- src/memjs/utils.ts | 14 +- 3 files changed, 260 insertions(+), 193 deletions(-) diff --git a/src/memjs/header.ts b/src/memjs/header.ts index 483e1e6..58f02d9 100644 --- a/src/memjs/header.ts +++ b/src/memjs/header.ts @@ -8,7 +8,7 @@ export interface Header { keyLength: number; extrasLength: number; dataType?: number; - status?: ResponseStatus; + status?: ResponseStatus | number; totalBodyLength: number; opaque: number; cas?: Buffer; diff --git a/src/memjs/server.ts b/src/memjs/server.ts index 48d7772..5ce3587 100644 --- a/src/memjs/server.ts +++ b/src/memjs/server.ts @@ -1,189 +1,291 @@ -var net = require('net'); -var events = require('events'); -var util = require('util'); -var makeRequestBuffer = require('./utils').makeRequestBuffer; -var parseMessage = require('./utils').parseMessage; -var merge = require('./utils').merge; -var timestamp = require('./utils').timestamp; - -var Server = function(host, port, username, password, options) { - events.EventEmitter.call(this); - this.responseBuffer = Buffer.from([]); - this.host = host; - this.port = port; - this.connected = false; - this.timeoutSet = false; - this.connectCallbacks = []; - this.responseCallbacks = {}; - this.requestTimeouts = []; - this.errorCallbacks = {}; - this.options = merge(options || {}, {timeout: 0.5, keepAlive: false, keepAliveDelay: 30}); - if (this.options.conntimeout === undefined || this.options.conntimeout === null) { - this.options.conntimeout = 2 * this.options.timeout; - } - this.username = username || this.options.username || process.env.MEMCACHIER_USERNAME || process.env.MEMCACHE_USERNAME; - this.password = password || this.options.password || process.env.MEMCACHIER_PASSWORD || process.env.MEMCACHE_PASSWORD; - return this; -}; +import net from "net"; +import events from "events"; +import { + makeRequestBuffer, + parseMessage, + merge, + timestamp, + Message, +} from "./utils"; -util.inherits(Server, events.EventEmitter); +interface ServerOptions { + timeout: number; + keepAlive: boolean; + keepAliveDelay: number; + conntimeout: number; + username?: string; + password?: string; +} -Server.prototype.onConnect = function(func) { - this.connectCallbacks.push(func); -}; +type Seq = string; -Server.prototype.onResponse = function(seq, func) { - this.responseCallbacks[seq] = func; -}; +interface OnConnectCallback { + (socket: net.Socket): void; +} -Server.prototype.respond = function(response) { - var callback = this.responseCallbacks[response.header.opaque]; - if (!callback) { - // in case of authentication, no callback is registered - return; +interface OnResponseCallback { + (message: Message): void; + quiet?: boolean; +} + +interface OnErrorCallback { + (error: Error | string): void; +} + +export class Server extends events.EventEmitter { + responseBuffer: Buffer; + host: string; + port: number; + connected: boolean; + timeoutSet: boolean; + connectCallbacks: OnConnectCallback[]; + responseCallbacks: { [seq: string]: OnResponseCallback }; + requestTimeouts: number[]; + errorCallbacks: { [seq: string]: OnErrorCallback }; + options: ServerOptions; + username: string | undefined; + password: string | undefined; + + _socket: net.Socket | undefined; + + constructor( + host: string, + port: number, + username?: string, + password?: string, + options?: Partial + ) { + super(); + this.responseBuffer = Buffer.from([]); + this.host = host; + this.port = port; + this.connected = false; + this.timeoutSet = false; + this.connectCallbacks = []; + this.responseCallbacks = {}; + this.requestTimeouts = []; + this.errorCallbacks = {}; + this.options = merge(options || {}, { + timeout: 0.5, + keepAlive: false, + keepAliveDelay: 30, + }) as ServerOptions; + if ( + this.options.conntimeout === undefined || + this.options.conntimeout === null + ) { + this.options.conntimeout = 2 * this.options.timeout; + } + this.username = + username || + this.options.username || + process.env.MEMCACHIER_USERNAME || + process.env.MEMCACHE_USERNAME; + this.password = + password || + this.options.password || + process.env.MEMCACHIER_PASSWORD || + process.env.MEMCACHE_PASSWORD; + return this; } - callback(response); - if (!callback.quiet || response.header.totalBodyLength === 0) { - delete(this.responseCallbacks[response.header.opaque]); - this.requestTimeouts.shift(); - delete(this.errorCallbacks[response.header.opaque]); + + onConnect(func: OnConnectCallback) { + this.connectCallbacks.push(func); } -}; -Server.prototype.onError = function(seq, func) { - this.errorCallbacks[seq] = func; -}; + onResponse(seq: Seq, func: OnResponseCallback) { + this.responseCallbacks[seq] = func; + } -Server.prototype.error = function(err) { - var errcalls = this.errorCallbacks; - this.connectCallbacks = []; - this.responseCallbacks = {}; - this.requestTimeouts = []; - this.errorCallbacks = {}; - this.timeoutSet = false; - if (this._socket) { - this._socket.destroy(); - delete(this._socket); + respond(response: Message) { + var callback = this.responseCallbacks[response.header.opaque]; + if (!callback) { + // in case of authentication, no callback is registered + return; + } + callback(response); + if (!callback.quiet || response.header.totalBodyLength === 0) { + delete this.responseCallbacks[response.header.opaque]; + this.requestTimeouts.shift(); + delete this.errorCallbacks[response.header.opaque]; + } } - for (let errcall of Object.values(errcalls)) { - errcall(err); + + onError(seq: Seq, func: OnErrorCallback) { + this.errorCallbacks[seq] = func; } -}; -Server.prototype.listSasl = function() { - var buf = makeRequestBuffer(0x20, '', '', ''); - this.writeSASL(buf); -}; + error(err: Error | string) { + var errcalls = this.errorCallbacks; + this.connectCallbacks = []; + this.responseCallbacks = {}; + this.requestTimeouts = []; + this.errorCallbacks = {}; + this.timeoutSet = false; + if (this._socket) { + this._socket.destroy(); + delete this._socket; + } + for (let errcall of Object.values(errcalls)) { + errcall(err); + } + } -Server.prototype.saslAuth = function() { - var authStr = '\x00' + this.username + '\x00' + this.password; - var buf = makeRequestBuffer(0x21, 'PLAIN', '', authStr); - this.writeSASL(buf); -}; + listSasl() { + var buf = makeRequestBuffer(0x20, "", "", ""); + this.writeSASL(buf); + } -Server.prototype.appendToBuffer = function(dataBuf) { - var old = this.responseBuffer; - this.responseBuffer = Buffer.alloc(old.length + dataBuf.length); - old.copy(this.responseBuffer, 0); - dataBuf.copy(this.responseBuffer, old.length); - return this.responseBuffer; -}; + saslAuth() { + var authStr = "\x00" + this.username + "\x00" + this.password; + var buf = makeRequestBuffer(0x21, "PLAIN", "", authStr); + this.writeSASL(buf); + } -Server.prototype.responseHandler = function(dataBuf) { - var response = parseMessage(this.appendToBuffer(dataBuf)); - var respLength; - while (response) { - if (response.header.opcode === 0x20) { - this.saslAuth(); - } else if (response.header.status === 0x20) { - this.error('Memcached server authentication failed!'); - } else if (response.header.opcode === 0x21) { - this.emit('authenticated'); - } else { - this.respond(response); + appendToBuffer(dataBuf: Buffer) { + var old = this.responseBuffer; + this.responseBuffer = Buffer.alloc(old.length + dataBuf.length); + old.copy(this.responseBuffer, 0); + dataBuf.copy(this.responseBuffer, old.length); + return this.responseBuffer; + } + responseHandler(dataBuf: Buffer) { + var response = parseMessage(this.appendToBuffer(dataBuf)); + var respLength; + while (response) { + if (response.header.opcode === 0x20) { + this.saslAuth(); + } else if (response.header.status === 0x20) { + this.error("Memcached server authentication failed!"); + } else if (response.header.opcode === 0x21) { + this.emit("authenticated"); + } else { + this.respond(response); + } + respLength = response.header.totalBodyLength + 24; + this.responseBuffer = this.responseBuffer.slice(respLength); + response = parseMessage(this.responseBuffer); } - respLength = response.header.totalBodyLength + 24; - this.responseBuffer = this.responseBuffer.slice(respLength); - response = parseMessage(this.responseBuffer); } -}; + sock(sasl: boolean, go: OnConnectCallback) { + var self = this; + + if (!self._socket) { + // CASE 1: completely new socket + self.connected = false; + self._socket = net.connect(this.port, this.host, function ( + this: net.Socket + ) { + // SASL authentication handler + self.once("authenticated", function () { + if (self._socket) { + const socket = self._socket; + self.connected = true; + // cancel connection timeout + self._socket.setTimeout(0); + self.timeoutSet = false; + // run actual request(s) + go(self._socket); + self.connectCallbacks.forEach(function (cb) { + cb(socket); + }); + self.connectCallbacks = []; + } + }); -Server.prototype.sock = function(sasl, go) { - var self = this; + // setup response handler + this.on("data", function (dataBuf) { + self.responseHandler(dataBuf); + }); - if (!self._socket) { - // CASE 1: completely new socket - self.connected = false; - self._socket = net.connect(this.port, this.host, function() { + // kick of SASL if needed + if (self.username && self.password) { + self.listSasl(); + } else { + self.emit("authenticated"); + } + }); - // SASL authentication handler - self.once('authenticated', function() { - if (self._socket) { - self.connected = true; - // cancel connection timeout - self._socket.setTimeout(0); + // setup error handler + self._socket.on("error", function (error) { + self.connected = false; + if (self.timeoutSet) { + if (self._socket) { + self._socket.setTimeout(0); + } self.timeoutSet = false; - // run actual request(s) - go(self._socket); - self.connectCallbacks.forEach(function(cb) { - cb(self._socket); - }); - self.connectCallbacks = []; } + self._socket = undefined; + self.error(error); }); - // setup response handler - this.on('data', function(dataBuf) { - self.responseHandler(dataBuf); + // setup connection timeout handler + self.timeoutSet = true; + self._socket.setTimeout(self.options.conntimeout * 1000, function ( + this: net.Socket + ) { + self.timeoutSet = false; + if (!self.connected) { + this.end(); + self._socket = undefined; + self.error(new Error("socket timed out connecting to server.")); + } }); - // kick of SASL if needed - if (self.username && self.password) { - self.listSasl(); - } else { - self.emit('authenticated'); - } - }); + // use TCP keep-alive + self._socket.setKeepAlive( + self.options.keepAlive, + self.options.keepAliveDelay * 1000 + ); + } else if (!self.connected && !sasl) { + // CASE 2: socket exists, but still connecting / authenticating + self.onConnect(go); + } else { + // CASE 3: socket exists and connected / ready to use + go(self._socket); + } + } - // setup error handler - self._socket.on('error', function(error) { - self.connected = false; - if (self.timeoutSet) { - self._socket.setTimeout(0); - self.timeoutSet = false; + write(blob: Buffer) { + var self = this; + var deadline = Math.round(self.options.timeout * 1000); + this.sock(false, function (s) { + s.write(blob); + self.requestTimeouts.push(timestamp() + deadline); + if (!self.timeoutSet) { + self.timeoutSet = true; + s.setTimeout(deadline, function (this: net.Socket) { + timeoutHandler(self, this); + }); } - self._socket = undefined; - self.error(error); }); + } - // setup connection timeout handler - self.timeoutSet = true; - self._socket.setTimeout(self.options.conntimeout * 1000, function() { - self.timeoutSet = false; - if (!self.connected) { - this.end(); - self._socket = undefined; - self.error(new Error('socket timed out connecting to server.')); - } + writeSASL(blob: Buffer) { + this.sock(true, function (s) { + s.write(blob); }); + } - // use TCP keep-alive - self._socket.setKeepAlive(self.options.keepAlive, self.options.keepAliveDelay * 1000); + close() { + if (this._socket) { + this._socket.end(); + } + } - } else if (!self.connected && !sasl) { - // CASE 2: socket exists, but still connecting / authenticating - self.onConnect(go); + toString() { + return ""; + } - } else { - // CASE 3: socket exists and connected / ready to use - go(self._socket); + hostportString() { + return this.host + ":" + this.port; } -}; +} // We handle tracking timeouts with an array of deadlines (requestTimeouts), as // node doesn't like us setting up lots of timers, and using just one is more // efficient anyway. -var timeoutHandler = function(server, sock) { +var timeoutHandler = function (server: Server, sock: net.Socket) { if (server.requestTimeouts.length === 0) { // nothing active server.timeoutSet = false; @@ -200,47 +302,12 @@ var timeoutHandler = function(server, sock) { server.connected = false; server._socket = undefined; server.timeoutSet = false; - server.error(new Error('socket timed out waiting on response.')); + server.error(new Error("socket timed out waiting on response.")); } else { // no timeout! Setup next one. var deadline = soonestTimeout - now; - sock.setTimeout(deadline, function() { + sock.setTimeout(deadline, function () { timeoutHandler(server, sock); }); } }; - -Server.prototype.write = function(blob) { - var self = this; - var deadline = Math.round(self.options.timeout * 1000); - this.sock(false, function(s) { - s.write(blob); - self.requestTimeouts.push(timestamp() + deadline); - if (!self.timeoutSet) { - self.timeoutSet = true; - s.setTimeout(deadline, function() { - timeoutHandler(self, this); - }); - } - }); -}; - -Server.prototype.writeSASL = function(blob) { - this.sock(true, function(s) { - s.write(blob); - }); -}; - -Server.prototype.close = function() { - if (this._socket) { this._socket.end(); } -}; - -Server.prototype.toString = function() { - return ''; -}; - -Server.prototype.hostportString = function() { - return this.host + ':' + this.port; -}; - -exports.Server = Server; diff --git a/src/memjs/utils.ts b/src/memjs/utils.ts index 9e7541e..a62f26a 100644 --- a/src/memjs/utils.ts +++ b/src/memjs/utils.ts @@ -3,7 +3,7 @@ import * as header from "./header"; import { OP } from "./constants"; -type MaybeBuffer = string | Buffer; +export type MaybeBuffer = string | Buffer; export const bufferify = function (val: MaybeBuffer) { return Buffer.isBuffer(val) ? val : Buffer.from(val as any); @@ -55,7 +55,7 @@ export const makeRequestBuffer = function ( key: MaybeBuffer, extras: MaybeBuffer, value: MaybeBuffer, - opaque: number + opaque?: number ) { key = bufferify(key); extras = bufferify(extras); @@ -65,11 +65,11 @@ export const makeRequestBuffer = function ( var buf = Buffer.alloc(bufSize); buf.fill(0); - exports.copyIntoRequestBuffer(opcode, key, extras, value, opaque, buf); + copyIntoRequestBuffer(opcode, key, extras, value, opaque || 0, buf); return buf; }; -exports.makeAmountInitialAndExpiration = function ( +export const makeAmountInitialAndExpiration = function ( amount: number, amountIfEmpty: number, expiration: number @@ -97,7 +97,7 @@ export const hashCode = function (str: string) { return Math.abs(ret); }; -interface Message { +export interface Message { header: header.Header; key: Buffer; val: Buffer; @@ -143,13 +143,13 @@ export const parseMessages = function (dataBuf: Buffer): Message[] { return messages; }; -export const merge = function (original: T, deflt: T): T { +export const merge = function (original: any, deflt: T): T { for (let attrT of Object.keys(deflt)) { const attr: keyof T = attrT as any; const originalValue = original[attr]; if (originalValue === undefined || originalValue === null) { - original[attr] = deflt[attr]; + original[attr] = deflt[attr] as any; } } return original; From 415b35aa0f27e23f5aab116326f9e8fb9600e001 Mon Sep 17 00:00:00 2001 From: Jake Teton-Landis Date: Fri, 9 Apr 2021 17:57:16 -0700 Subject: [PATCH 20/79] WIP --- src/memjs/memjs.ts | 2309 ++++++++++++++++++++-------------- src/memjs/noop-serializer.ts | 11 +- src/memjs/protocol.ts | 2 + src/memjs/server.ts | 99 +- 4 files changed, 1411 insertions(+), 1010 deletions(-) diff --git a/src/memjs/memjs.ts b/src/memjs/memjs.ts index e66c7f2..001124d 100644 --- a/src/memjs/memjs.ts +++ b/src/memjs/memjs.ts @@ -1,1013 +1,1380 @@ // # MemJS Memcache Client -var errors = require('./protocol').errors; -var Server = require('./server').Server; -var noopSerializer = require('./noop-serializer').noopSerializer; -var makeRequestBuffer = require('./utils').makeRequestBuffer; -var copyIntoRequestBuffer = require('./utils').copyIntoRequestBuffer; -var merge = require('./utils').merge; -var makeExpiration = require('./utils').makeExpiration; -var makeAmountInitialAndExpiration = require('./utils').makeAmountInitialAndExpiration; -var constants = require('./constants'); -var hashCode = require('./utils').hashCode; - -function defaultKeyToServerHashFunction(servers, key) { +import { errors, UNKNOWN_ERROR } from "./protocol"; +import { OnResponseCallback, Server, ServerOptions } from "./server"; +import { + noopSerializer, + Serializer, + SerializerResult, +} from "./noop-serializer"; +import { + makeRequestBuffer, + copyIntoRequestBuffer, + merge, + makeExpiration, + makeAmountInitialAndExpiration, + hashCode, + MaybeBuffer, + Message, +} from "./utils"; +import * as constants from "./constants"; +import { assert } from "node:console"; + +function defaultKeyToServerHashFunction(servers: string[], key: string) { var total = servers.length; - var index = (total > 1) ? (hashCode(key) % total) : 0; + var index = total > 1 ? hashCode(key) % total : 0; return servers[index]; } -// Client initializer takes a list of `Server`s and an `options` dictionary. -// See `Client.create` for details. -var Client = function(servers, options) { - this.servers = servers; - this.seq = 0; - this.options = merge(options || {}, - {retries: 2, retry_delay: 0.2, expires: 0, logger: console, - keyToServerHashFunction: defaultKeyToServerHashFunction +// converts a call into a promise-returning one +function promisify( + command: (callback: (error: Error | null, result: Result) => void) => void +): Promise { + return new Promise(function (resolve, reject) { + command(function (err, result) { + err ? reject(err) : resolve(result); }); + }); +} - this.serializer = this.options.serializer || noopSerializer; +type CallbackArgs> = [Error, ...Partial] | [null, ...T]; - // Store a mapping from hostport -> server so we can quickly get a server object from the serverKey returned by the hashing function - var serverMap = {}; - this.servers.forEach(function(server) { - serverMap[server.hostportString()] = server; - }); - this.serverMap = serverMap; - - // store a list of all our serverKeys so we don't need to constantly reallocate this array - this.serverKeys = Object.keys(this.serverMap); -}; - -// Creates a new client given an optional config string and optional hash of -// options. The config string should be of the form: -// -// "[user:pass@]server1[:11211],[user:pass@]server2[:11211],..." -// -// If the argument is not given, fallback on the `MEMCACHIER_SERVERS` environment -// variable, `MEMCACHE_SERVERS` environment variable or `"localhost:11211"`. -// -// The options hash may contain the options: -// -// * `retries` - the number of times to retry an operation in lieu of failures -// (default 2) -// * `expires` - the default expiration in seconds to use (default 0 - never -// expire). If `expires` is greater than 30 days (60 x 60 x 24 x 30), it is -// treated as a UNIX time (number of seconds since January 1, 1970). -// * `logger` - a logger object that responds to `log(string)` method calls. -// -// ~~~~ -// log(msg1[, msg2[, msg3[...]]]) -// ~~~~ -// -// Defaults to `console`. -// * `serializer` - the object which will (de)serialize the data. It needs -// two public methods: serialize and deserialize. It defaults to the -// noopSerializer: -// -// ~~~~ -// var noopSerializer = { -// serialize: function (opcode, value, extras) { -// return { value: value, extras: extras }; -// }, -// deserialize: function (opcode, value, extras) { -// return { value: value, extras: extras }; -// } -// }; -// ~~~~ -// -// Or options for the servers including: -// * `username` and `password` for fallback SASL authentication credentials. -// * `timeout` in seconds to determine failure for operations. Default is 0.5 -// seconds. -// * 'conntimeout' in seconds to connection failure. Default is twice the value -// of `timeout`. -// * `keepAlive` whether to enable keep-alive functionality. Defaults to false. -// * `keepAliveDelay` in seconds to the initial delay before the first keepalive -// probe is sent on an idle socket. Defaults is 30 seconds. -// * `keyToServerHashFunction` a function to map keys to servers, with the signature -// (serverKeys: string[], key: string): string -// NOTE: if you need to do some expensive initialization, *please* do it lazily the first time you this function is called with an array of serverKeys, not on every call -Client.create = function(serversStr, options) { - serversStr = serversStr || process.env.MEMCACHIER_SERVERS || - process.env.MEMCACHE_SERVERS || 'localhost:11211'; - var serverUris = serversStr.split(','); - var servers = serverUris.map(function(uri) { - var uriParts = uri.split('@'); - var hostPort = uriParts[uriParts.length - 1].split(':'); - var userPass = (uriParts[uriParts.length - 2] || '').split(':'); - return new Server(hostPort[0], parseInt(hostPort[1] || 11211, 10), userPass[0], userPass[1], options); - }); - return new Client(servers, options); -}; +type ResponseOrErrorCallback = ( + error: Error | null, + response: Message | null +) => void; -/** - * Given a serverKey fromlookupKeyToServerKey, return the corresponding Server instance - * - * @param {string} serverKey - * @returns {Server} -*/ -Client.prototype.serverKeyToServer = function(serverKey) { - return this.serverMap[serverKey]; -}; - -/** - * Given a key to look up in memcache, return a serverKey (based on some - * hashing function) which -can be used to index this.serverMap - * - * @param {string} key - * * @returns {string} - */ -Client.prototype.lookupKeyToServerKey = function(key) { - return this.options.keyToServerHashFunction(this.serverKeys, key); -}; +// interface ResponseOrErrorCallback { +// (error: Error, response: null): void; +// (error: null, response: Message): void; +// } -// converts a call into a promise-returning one -var promisify = function(command) { - return new Promise(function(resolve, reject) { - command(function(err, result) { - err ? reject(err) : resolve(result); - }); - }); -}; - -// ## Memcache Commands -// -// All commands return their results through a callback passed as the last -// required argument (some commands, like `Client#set`, take optional arguments -// after the callback). -// -// The callback signature always follows: -// -// callback(err, [arg1[, arg2[, arg3[...]]]]) -// -// In case of an error the _err_ argument will be non-null and contain the -// `Error`. A notable exception includes a `Client#get` on a key that doesn't -// exist. In this case, _err_ will be null, as will the _value and _extras_ -// arguments. - -// GET -// -// Retrieves the value at the given key in memcache. -// -// The callback signature is: -// -// callback(err, value, flags) -// -// _value_ and _flags_ are both `string`s. If the key is not found, the -// callback is invoked with null for both arguments and no error. -Client.prototype.get = function(key, callback) { - var self = this; - if(callback === undefined) { - return promisify(function(callback) { - self.get(key, function(err, value, flags) { - callback(err, {value: value, flags: flags}); - }); +interface BaseClientOptions { + retries: number; + retry_delay: number; + expires: number; + logger: { log: typeof console.log }; + keyToServerHashFunction: typeof defaultKeyToServerHashFunction; +} + +interface SerializerProp { + serializer: Serializer; +} + +type IfBuffer = Value extends Buffer + ? Extras extends Buffer + ? IsBuffer + : NotBuffer + : NotBuffer; + +type GivenClientOptions = Partial & + IfBuffer< + Value, + Extras, + Partial>, + SerializerProp + >; + +class Client { + servers: Server[]; + seq: number; + options: BaseClientOptions; + serializer: Serializer; + serverMap: { [hostport: string]: Server }; + serverKeys: string[]; + + // Client initializer takes a list of `Server`s and an `options` dictionary. + // See `Client.create` for details. + constructor(servers: Server[], options: GivenClientOptions) { + this.servers = servers; + this.seq = 0; + this.options = merge(options || {}, { + retries: 2, + retry_delay: 0.2, + expires: 0, + logger: console, + keyToServerHashFunction: defaultKeyToServerHashFunction, }); - } - var logger = this.options.logger; - this.incrSeq(); - var request = makeRequestBuffer(constants.OP_GET, key, '', '', this.seq); - this.perform(key, request, this.seq, function(err, response) { - if (err) { - if (callback) { callback(err, null, null); } - return; - } - switch (response.header.status) { - case constants.RESPONSE_STATUS_SUCCCESS: - if (callback) { - var deserialized = self.serializer.deserialize(response.header.opcode, response.val, response.extras); - callback(null, deserialized.value, deserialized.extras); - } - break; - case constants.RESPONSE_STATUS_KEY_NOT_FOUND: - if (callback) { callback(null, null, null); } - break; - default: - var errorMessage = 'MemJS GET: ' + errors[response.header.status]; - logger.log(errorMessage); - if (callback) { callback(new Error(errorMessage), null, null); } - } - }); -}; -/** Build a pipelined get multi request by sending one GETKQ for each key (quiet, meaning it won't respond if the value is missing) followed by a no-op to force a response (and to give us a sentinel response that the pipeline is done) - * - * cf https://github.com/couchbase/memcached/blob/master/docs/BinaryProtocol.md#0x0d-getkq-get-with-key-quietly - */ -Client.prototype._buildGetMultiRequest = function(keys) { - // start at 24 for the no-op command at the end - var requestSize = 24; - for (var keyIdx in keys) { - requestSize += Buffer.byteLength(keys[keyIdx], 'utf8') + 24; - } + this.serializer = options.serializer || (noopSerializer as any); - var request = Buffer.alloc(requestSize); - request.fill(); + // Store a mapping from hostport -> server so we can quickly get a server object from the serverKey returned by the hashing function + var serverMap: { [hostport: string]: Server } = {}; + this.servers.forEach(function (server) { + serverMap[server.hostportString()] = server; + }); + this.serverMap = serverMap; - var bytesWritten = 0; - for (keyIdx in keys) { - var key = keys[keyIdx]; - bytesWritten += copyIntoRequestBuffer(constants.OP_GETKQ, key, '', '', this.seq, request, bytesWritten); + // store a list of all our serverKeys so we don't need to constantly reallocate this array + this.serverKeys = Object.keys(this.serverMap); } - bytesWritten += copyIntoRequestBuffer( - constants.OP_NO_OP, '', '', '', this.seq, request, bytesWritten); - - return request; -}; + // Creates a new client given an optional config string and optional hash of + // options. The config string should be of the form: + // + // "[user:pass@]server1[:11211],[user:pass@]server2[:11211],..." + // + // If the argument is not given, fallback on the `MEMCACHIER_SERVERS` environment + // variable, `MEMCACHE_SERVERS` environment variable or `"localhost:11211"`. + // + // The options hash may contain the options: + // + // * `retries` - the number of times to retry an operation in lieu of failures + // (default 2) + // * `expires` - the default expiration in seconds to use (default 0 - never + // expire). If `expires` is greater than 30 days (60 x 60 x 24 x 30), it is + // treated as a UNIX time (number of seconds since January 1, 1970). + // * `logger` - a logger object that responds to `log(string)` method calls. + // + // ~~~~ + // log(msg1[, msg2[, msg3[...]]]) + // ~~~~ + // + // Defaults to `console`. + // * `serializer` - the object which will (de)serialize the data. It needs + // two public methods: serialize and deserialize. It defaults to the + // noopSerializer: + // + // ~~~~ + // var noopSerializer = { + // serialize: function (opcode, value, extras) { + // return { value: value, extras: extras }; + // }, + // deserialize: function (opcode, value, extras) { + // return { value: value, extras: extras }; + // } + // }; + // ~~~~ + // + // Or options for the servers including: + // * `username` and `password` for fallback SASL authentication credentials. + // * `timeout` in seconds to determine failure for operations. Default is 0.5 + // seconds. + // * 'conntimeout' in seconds to connection failure. Default is twice the value + // of `timeout`. + // * `keepAlive` whether to enable keep-alive functionality. Defaults to false. + // * `keepAliveDelay` in seconds to the initial delay before the first keepalive + // probe is sent on an idle socket. Defaults is 30 seconds. + // * `keyToServerHashFunction` a function to map keys to servers, with the signature + // (serverKeys: string[], key: string): string + // NOTE: if you need to do some expensive initialization, *please* do it lazily the first time you this function is called with an array of serverKeys, not on every call + static create( + serversStr: string | undefined, + options: IfBuffer< + Value, + Extras, + undefined | (Partial & GivenClientOptions), + Partial & GivenClientOptions + > + ): Client { + serversStr = + serversStr || + process.env.MEMCACHIER_SERVERS || + process.env.MEMCACHE_SERVERS || + "localhost:11211"; + var serverUris = serversStr.split(","); + var servers = serverUris.map(function (uri) { + var uriParts = uri.split("@"); + var hostPort = uriParts[uriParts.length - 1].split(":"); + var userPass = (uriParts[uriParts.length - 2] || "").split(":"); + return new Server( + hostPort[0], + parseInt(hostPort[1] || "11211", 10), + userPass[0], + userPass[1], + options + ); + }); + return new Client(servers, options as any); + } -/** Executing a pipelined (multi) get against a single server. This is a private implementation detail of getMulti. */ -Client.prototype._getMultiToServer = function (serv, keys, callback) { - var self = this; + /** + * Given a serverKey fromlookupKeyToServerKey, return the corresponding Server instance + * + * @param {string} serverKey + * @returns {Server} + */ + serverKeyToServer(serverKey: string) { + return this.serverMap[serverKey]; + } - var responseMap = {}; + /** + * Given a key to look up in memcache, return a serverKey (based on some + * hashing function) which can be used to index this.serverMap + * + * @param {string} key + * * @returns {string} + */ + lookupKeyToServerKey(key: string) { + return this.options.keyToServerHashFunction(this.serverKeys, key); + } - var handle = function(response) { - switch (response.header.status) { - case constants.RESPONSE_STATUS_SUCCCESS: - if (callback) { - var deserialized = self.serializer.deserialize(response.header.opcode, response.val, response.extras); - // When we get the no-op response, we are done with this one getMulti in the per-backend fan-out - if (response.header.opcode === constants.OP_NO_OP) { - // This ensures the handler will be deleted from the responseCallbacks map in server.js - // This isn't technically needed here because the logic in server.js also checks if totalBodyLength === 0, but our unittests aren't great about setting that field, and also this makes it more explicit - handle.quiet = false; - callback(null, responseMap); - } else { - var key = response.key.toString(); - responseMap[key] = deserialized.value; + // ## Memcache Commands + // + // All commands return their results through a callback passed as the last + // required argument (some commands, like `Client#set`, take optional arguments + // after the callback). + // + // The callback signature always follows: + // + // callback(err, [arg1[, arg2[, arg3[...]]]]) + // + // In case of an error the _err_ argument will be non-null and contain the + // `Error`. A notable exception includes a `Client#get` on a key that doesn't + // exist. In this case, _err_ will be null, as will the _value and _extras_ + // arguments. + + /** + * GET + * + * Retrieves the value at the given key in memcache. + * + * The callback signature is: + * + * callback(err, value, flags) + * + * _value_ and _flags_ are both `Buffer`s. If the key is not found, the + * callback is invoked with null for both arguments and no error + * @param key + * @param callback + */ + get(key: string): Promise<{ value: Value | null; flags: Extras | null }>; + get( + key: string, + callback: ( + error: Error | null, + value: Value | null, + flags: Extras | null + ) => void + ): void; + get( + key: string, + callback?: ( + error: Error | null, + value: Value | null, + flags: Extras | null + ) => void + ): Promise<{ value: Value | null; flags: Extras | null }> | void { + var self = this; + if (callback === undefined) { + return promisify(function (callback) { + self.get(key, function (err, value, flags) { + callback(err, { value: value, flags: flags }); + }); + }); + } + var logger = this.options.logger; + this.incrSeq(); + var request = makeRequestBuffer(constants.OP_GET, key, "", "", this.seq); + this.perform(key, request, this.seq, function (err, response) { + if (err) { + if (callback) { + callback(err, null, null); } + return; + } + switch (response!.header.status) { + case constants.RESPONSE_STATUS_SUCCCESS: + if (callback) { + var deserialized = self.serializer.deserialize( + response!.header.opcode, + response!.val, + response!.extras + ); + callback(null, deserialized.value, deserialized.extras); + } + break; + case constants.RESPONSE_STATUS_KEY_NOT_FOUND: + if (callback) { + callback(null, null, null); + } + break; + default: + var errorMessage = + "MemJS GET: " + errors[response!.header.status || UNKNOWN_ERROR]; + logger.log(errorMessage); + if (callback) { + callback(new Error(errorMessage), null, null); + } } - break; - case constants.RESPONSE_STATUS_KEY_NOT_FOUND: - if (callback) { callback(null, null, null); } - break; - default: - var errorMessage = 'MemJS GET: ' + errors[response.header.status]; - self.options.logger.log(errorMessage); - if (callback) { callback(new Error(errorMessage), null, null); } - } - }; - // This prevents the handler from being deleted - // after the first response. Logic in server.js. - handle.quiet = true; - - var request = this._buildGetMultiRequest(keys); - serv.onResponse(this.seq, handle); - serv.onError(this.seq, function(err) { - if (callback) { callback(err, serv.hostportString(), null); } - }); - this.incrSeq(); - serv.write(request); -}; - -// MULTI-GET / GET-MULTI -// -// Retrieves the value at the given keys in memcache. -// -// The callback signature is: -// -// callback(err, values, flags) -// -// _values_ is a map of { [key]: Buffer } -// _flags_ is a `string`. -Client.prototype.getMulti = function(keys, callback) { - var self = this; - if(callback === undefined) { - return promisify(function(callback) { - self.getMulti(keys, function(err, values, flags) { - callback(err, {values: values, flags: flags}); - }); }); } - - var serverKeytoLookupKeys = {}; - keys.forEach(function(lookupKey) { - var serverKey = self.lookupKeyToServerKey(lookupKey); - if (!serverKeytoLookupKeys[serverKey]) { - serverKeytoLookupKeys[serverKey] = []; - } - serverKeytoLookupKeys[serverKey].push(lookupKey); - }); - - var usedServerKeys = Object.keys(serverKeytoLookupKeys); - var outstandingCalls = usedServerKeys.length; - var recordMap = {}; - var hadError = false; - function latchCallback(err, values, flags) { - if (hadError) { - return; + /** Build a pipelined get multi request by sending one GETKQ for each key (quiet, meaning it won't respond if the value is missing) followed by a no-op to force a response (and to give us a sentinel response that the pipeline is done) + * + * cf https://github.com/couchbase/memcached/blob/master/docs/BinaryProtocol.md#0x0d-getkq-get-with-key-quietly + */ + _buildGetMultiRequest(keys: string[]) { + // start at 24 for the no-op command at the end + var requestSize = 24; + for (var keyIdx in keys) { + requestSize += Buffer.byteLength(keys[keyIdx], "utf8") + 24; } - if (err) { - hadError = true; - callback(err, null, null); - return; + var request = Buffer.alloc(requestSize); + request.fill(0); + + var bytesWritten = 0; + for (keyIdx in keys) { + var key = keys[keyIdx]; + bytesWritten += copyIntoRequestBuffer( + constants.OP_GETKQ, + key, + "", + "", + this.seq, + request, + bytesWritten + ); } - merge(recordMap, values); - outstandingCalls -= 1; - if (outstandingCalls === 0) { - callback(null, recordMap, flags); - } + bytesWritten += copyIntoRequestBuffer( + constants.OP_NO_OP, + "", + "", + "", + this.seq, + request, + bytesWritten + ); + + return request; } - for (var serverKeyIndex in usedServerKeys) { - var serverKey = usedServerKeys[serverKeyIndex]; - var server = this.serverKeyToServer(serverKey); - this._getMultiToServer(server, serverKeytoLookupKeys[serverKey], latchCallback); - } -}; - -// SET -// -// Sets the given _key_ and _value_ in memcache. -// -// The options dictionary takes: -// * _expires_: overrides the default expiration (see `Client.create`) for this -// particular key-value pair. -// -// The callback signature is: -// -// callback(err, success) -Client.prototype.set = function(key, value, options, callback) { - if(callback === undefined && typeof options !== 'function') { + /** Executing a pipelined (multi) get against a single server. This is a private implementation detail of getMulti. */ + _getMultiToServer( + serv: Server, + keys: string[], + callback: ( + error: Error | null, + values: { [key: string]: Value | null } | null, + flags: Extras | null + ) => void + ) { var self = this; - if (!options) options = {}; - return promisify(function(callback) { self.set(key, value, options, function(err, success) { callback(err, success); }); }); - } - var logger = this.options.logger; - var expires; - if (typeof options === 'function' || typeof callback === 'number') { - // OLD: function(key, value, callback, expires) - logger.log('MemJS SET: using deprecated call - arguments have changed'); - expires = callback; - callback = options; - options = {}; - } - logger = this.options.logger; - expires = options.expires; + var responseMap: { + [server: string]: Value | null; + } = {}; - // TODO: support flags, support version (CAS) - this.incrSeq(); - var expiration = makeExpiration(expires || this.options.expires); - var extras = Buffer.concat([Buffer.from('00000000', 'hex'), expiration]); + var handle: OnResponseCallback = function (response) { + switch (response.header.status) { + case constants.RESPONSE_STATUS_SUCCCESS: + if (callback) { + var deserialized = self.serializer.deserialize( + response.header.opcode, + response.val, + response.extras + ); + // When we get the no-op response, we are done with this one getMulti in the per-backend fan-out + if (response.header.opcode === constants.OP_NO_OP) { + // This ensures the handler will be deleted from the responseCallbacks map in server.js + // This isn't technically needed here because the logic in server.js also checks if totalBodyLength === 0, but our unittests aren't great about setting that field, and also this makes it more explicit + handle.quiet = false; + callback(null, responseMap, deserialized.extras); + } else { + var key = response.key.toString(); + responseMap[key] = deserialized.value; + } + } + break; + case constants.RESPONSE_STATUS_KEY_NOT_FOUND: + if (callback) { + callback(null, null, null); + } + break; + default: + var errorMessage = + "MemJS GET: " + errors[response.header.status || UNKNOWN_ERROR]; + self.options.logger.log(errorMessage); + if (callback) { + callback(new Error(errorMessage), null, null); + } + } + }; + // This prevents the handler from being deleted + // after the first response. Logic in server.js. + handle.quiet = true; - var opcode = 1; - var serialized = this.serializer.serialize(opcode, value, extras); - var request = makeRequestBuffer(opcode, key, serialized.extras, serialized.value, this.seq); - this.perform(key, request, this.seq, function(err, response) { - if (err) { - if (callback) { callback(err, null); } - return; - } - switch (response.header.status) { - case constants.RESPONSE_STATUS_SUCCCESS: - if (callback) { callback(null, true); } - break; - default: - var errorMessage = 'MemJS SET: ' + errors[response.header.status]; - logger.log(errorMessage); - if (callback) { callback(new Error(errorMessage), null, null); } - } - }); -}; - -// ADD -// -// Adds the given _key_ and _value_ to memcache. The operation only succeeds -// if the key is not already set. -// -// The options dictionary takes: -// * _expires_: overrides the default expiration (see `Client.create`) for this -// particular key-value pair. -// -// The callback signature is: -// -// callback(err, success) -Client.prototype.add = function(key, value, options, callback) { - if(callback === undefined && options !== 'function') { - var self = this; - if (!options) options = {}; - return promisify(function(callback) { self.add(key, value, options, function(err, success) { callback(err, success); }); }); - } - var logger = this.options.logger; - var expires; - if (typeof options === 'function') { - // OLD: function(key, value, callback, expires) - logger.log('MemJS ADD: using deprecated call - arguments have changed'); - expires = callback; - callback = options; - options = {}; + var request = this._buildGetMultiRequest(keys); + serv.onResponse(this.seq, handle); + serv.onError(this.seq, function (err) { + if (callback) { + callback(err, serv.hostportString() as any /* TODO */, null); + } + }); + this.incrSeq(); + serv.write(request); } - logger = this.options.logger; - expires = options.expires; - - // TODO: support flags, support version (CAS) - this.incrSeq(); - var expiration = makeExpiration(expires || this.options.expires); - var extras = Buffer.concat([Buffer.from('00000000', 'hex'), expiration]); - - var opcode = 2; - var serialized = this.serializer.serialize(opcode, value, extras); - var request = makeRequestBuffer(opcode, key, serialized.extras, serialized.value, this.seq); - this.perform(key, request, this.seq, function(err, response) { - if (err) { - if (callback) { callback(err, null, null); } - return; - } - switch (response.header.status) { - case constants.RESPONSE_STATUS_SUCCCESS: - if (callback) { callback(null, true); } - break; - case constants.RESPONSE_STATUS_KEY_EXISTS: - if (callback) { callback(null, false); } - break; - default: - var errorMessage = 'MemJS ADD: ' + errors[response.header.status]; - logger.log(errorMessage, false); - if (callback) { callback(new Error(errorMessage), null, null); } - } - }); -}; - -// REPLACE -// -// Replaces the given _key_ and _value_ to memcache. The operation only succeeds -// if the key is already present. -// -// The options dictionary takes: -// * _expires_: overrides the default expiration (see `Client.create`) for this -// particular key-value pair. -// -// The callback signature is: -// -// callback(err, success) -Client.prototype.replace = function(key, value, options, callback) { - if(callback === undefined && options !== 'function') { + /** + * MULTI-GET / GET-MULTI + * + * Retrieves the value at the given keys in memcache. + * + * The callback signature is: + * + * callback(err, value, flags) + * + * @param keys + * @param callback + */ + getMulti( + keys: Keys[] + ): Promise<{ + values: { [K in Keys]?: Value | null } | null; + flags: Extras | null; + }>; + getMulti( + keys: Keys[], + callback: ( + error: Error | null, + value: { [K in Keys]?: Value | null } | null, + flags: Extras | null + ) => void + ): void; + getMulti( + keys: Keys[], + callback?: ( + error: Error | null, + value: { [K in Keys]?: Value | null } | null, + flags: Extras | null + ) => void + ): Promise<{ + values: { [K in Keys]?: Value | null } | null; + flags: Extras | null; + }> | void { var self = this; - if (!options) options = {}; - return promisify(function(callback) { self.replace(key, value, options, function(err, success) { callback(err, success); }); }); - } - var logger = this.options.logger; - var expires; - if (typeof options === 'function') { - // OLD: function(key, value, callback, expires) - logger.log('MemJS REPLACE: using deprecated call - arguments have changed'); - expires = callback; - callback = options; - options = {}; - } + if (callback === undefined) { + return promisify(function (callback) { + self.getMulti(keys, function (err, values, flags) { + callback(err, { values: values, flags: flags }); + }); + }); + } - logger = this.options.logger; - expires = options.expires; + var serverKeytoLookupKeys: { + [serverKey: string]: string[]; + } = {}; + keys.forEach(function (lookupKey) { + var serverKey = self.lookupKeyToServerKey(lookupKey); + if (!serverKeytoLookupKeys[serverKey]) { + serverKeytoLookupKeys[serverKey] = []; + } + serverKeytoLookupKeys[serverKey].push(lookupKey); + }); - // TODO: support flags, support version (CAS) - this.incrSeq(); - var expiration = makeExpiration(expires || this.options.expires); - var extras = Buffer.concat([Buffer.from('00000000', 'hex'), expiration]); + var usedServerKeys = Object.keys(serverKeytoLookupKeys); + var outstandingCalls = usedServerKeys.length; + var recordMap = {}; + var hadError = false; + function latchCallback( + err: Error | null, + values: { [key: string]: Value | null } | null, + flags: Extras | null + ) { + if (hadError) { + return; + } - var opcode = 3; - var serialized = this.serializer.serialize(opcode, value, extras); - var request = makeRequestBuffer(opcode, key, serialized.extras, serialized.value, this.seq); - this.perform(key, request, this.seq, function(err, response) { - if (err) { - if (callback) { callback(err, null, null); } - return; + if (err) { + hadError = true; + callback!(err, null, null); + return; + } + + merge(recordMap, values); + outstandingCalls -= 1; + if (outstandingCalls === 0) { + callback!(null, recordMap, flags); + } } - switch (response.header.status) { - case constants.RESPONSE_STATUS_SUCCCESS: - if (callback) { callback(null, true); } - break; - case constants.RESPONSE_STATUS_KEY_NOT_FOUND: - if (callback) { callback(null, false); } - break; - default: - var errorMessage = 'MemJS REPLACE: ' + errors[response.header.status]; - logger.log(errorMessage, false); - if (callback) { callback(new Error(errorMessage), null, null); } + + for (var serverKeyIndex in usedServerKeys) { + var serverKey = usedServerKeys[serverKeyIndex]; + var server = this.serverKeyToServer(serverKey); + this._getMultiToServer( + server, + serverKeytoLookupKeys[serverKey], + latchCallback + ); } - }); -}; - -// DELETE -// -// Deletes the given _key_ from memcache. The operation only succeeds -// if the key is already present. -// -// The callback signature is: -// -// callback(err, success) -Client.prototype.delete = function(key, callback) { - if(callback === undefined) { - var self = this; - return promisify(function(callback) { self.delete(key, function(err, success) { callback(err, success); }); }); } - // TODO: Support version (CAS) - var logger = this.options.logger; - this.incrSeq(); - var request = makeRequestBuffer(4, key, '', '', this.seq); - this.perform(key, request, this.seq, function(err, response) { - if (err) { - if (callback) { callback(err, null, null); } - return; - } - switch (response.header.status) { - case constants.RESPONSE_STATUS_SUCCCESS: - if (callback) { callback(null, true); } - break; - case constants.RESPONSE_STATUS_KEY_NOT_FOUND: - if (callback) { callback(null, false); } - break; - default: - var errorMessage = 'MemJS DELETE: ' + errors[response.header.status]; - logger.log(errorMessage, false); - if (callback) { callback(new Error(errorMessage), null); } - } - }); -}; - -// INCREMENT -// -// Increments the given _key_ in memcache. -// -// The options dictionary takes: -// * _initial_: the value for the key if not already present, defaults to 0. -// * _expires_: overrides the default expiration (see `Client.create`) for this -// particular key-value pair. -// -// The callback signature is: -// -// callback(err, success, value) -Client.prototype.increment = function(key, amount, options, callback) { - if(callback === undefined && options !== 'function') { - var self = this; - return promisify(function(callback) { + + // SET + // + // Sets the given _key_ and _value_ in memcache. + // + // The options dictionary takes: + // * _expires_: overrides the default expiration (see `Client.create`) for this + // particular key-value pair. + // + // The callback signature is: + // + // callback(err, success) + set( + key: string, + value: Value, + options?: { expires?: number } + ): Promise; + set( + key: string, + value: Value, + callback: (error: Error | null, success: boolean | null) => void + ): void; + set( + key: string, + value: Value, + options: { expires?: number }, + callback: (error: Error | null, success: boolean | null) => void + ): void; + set( + key: string, + value: Value, + options: + | { expires?: number } + | ((error: Error | null, success: boolean | null) => void), + callback?: (error: Error | null, success: boolean | null) => void + ): Promise | void { + if (callback === undefined && typeof options !== "function") { + var self = this; if (!options) options = {}; - self.increment(key, amount, options, function(err, success, value) { - callback(err, {success: success, value: value}); + return promisify(function (callback) { + self.set( + key, + value, + options as { expires?: number }, + function (err, success) { + callback(err, success); + } + ); }); + } + var logger = this.options.logger; + var expires; + if (typeof options === "function" || typeof callback === "number") { + // OLD: function(key, value, callback, expires) + logger.log("MemJS SET: using deprecated call - arguments have changed"); + expires = callback; + callback = options as ( + error: Error | null, + success: boolean | null + ) => void; + options = {}; + } + + logger = this.options.logger; + expires = options.expires; + + // TODO: support flags, support version (CAS) + this.incrSeq(); + var expiration = makeExpiration(expires || this.options.expires); + var extras = Buffer.concat([Buffer.from("00000000", "hex"), expiration]); + + var opcode: constants.OP = 1; + var serialized = this.serializer.serialize( + opcode, + value, + extras as any /* TODO */ + ); + var request = makeRequestBuffer( + opcode, + key, + serialized.extras, + serialized.value, + this.seq + ); + this.perform(key, request, this.seq, function (err, response) { + if (err) { + if (callback) { + callback(err, null); + } + return; + } + switch (response!.header.status) { + case constants.RESPONSE_STATUS_SUCCCESS: + if (callback) { + callback(null, true); + } + break; + default: + var errorMessage = + "MemJS SET: " + errors[response!.header.status || UNKNOWN_ERROR]; + logger.log(errorMessage); + if (callback) { + callback(new Error(errorMessage), null); + } + } }); } - var logger = this.options.logger; - var initial; - var expires; - if (typeof options === 'function') { - // OLD: function(key, amount, callback, expires, initial) - logger.log('MemJS INCREMENT: using deprecated call - arguments have changed'); - initial = arguments[4]; - expires = callback; - callback = options; - options = {}; - } - logger = this.options.logger; - initial = options.initial; - expires = options.expires; - - // TODO: support version (CAS) - this.incrSeq(); - initial = initial || 0; - expires = expires || this.options.expires; - var extras = makeAmountInitialAndExpiration(amount, initial, expires); - var request = makeRequestBuffer(5, key, extras, '', this.seq); - this.perform(key, request, this.seq, function(err, response) { - if (err) { - if (callback) { callback(err, null); } - return; + // ADD + // + // Adds the given _key_ and _value_ to memcache. The operation only succeeds + // if the key is not already set. + // + // The options dictionary takes: + // * _expires_: overrides the default expiration (see `Client.create`) for this + // particular key-value pair. + // + // The callback signature is: + // + // callback(err, success) + add(key, value, options, callback) { + if (callback === undefined && options !== "function") { + var self = this; + if (!options) options = {}; + return promisify(function (callback) { + self.add(key, value, options, function (err, success) { + callback(err, success); + }); + }); } - switch (response.header.status) { - case constants.RESPONSE_STATUS_SUCCCESS: - var bufInt = (response.val.readUInt32BE(0) << 8) + response.val.readUInt32BE(4); - if (callback) { callback(null, true, bufInt); } - break; - default: - var errorMessage = 'MemJS INCREMENT: ' + errors[response.header.status]; - logger.log(errorMessage); - if (callback) { callback(new Error(errorMessage), null, null); } + var logger = this.options.logger; + var expires; + if (typeof options === "function") { + // OLD: function(key, value, callback, expires) + logger.log("MemJS ADD: using deprecated call - arguments have changed"); + expires = callback; + callback = options; + options = {}; } - }); -}; - -// DECREMENT -// -// Decrements the given _key_ in memcache. -// -// The options dictionary takes: -// * _initial_: the value for the key if not already present, defaults to 0. -// * _expires_: overrides the default expiration (see `Client.create`) for this -// particular key-value pair. -// -// The callback signature is: -// -// callback(err, success, value) -Client.prototype.decrement = function(key, amount, options, callback) { - if(callback === undefined && options !== 'function') { - var self = this; - return promisify(function(callback) { - self.decrement(key, amount, options, function(err, success, value) { - callback(err, {success: success, value: value}); - }); + + logger = this.options.logger; + expires = options.expires; + + // TODO: support flags, support version (CAS) + this.incrSeq(); + var expiration = makeExpiration(expires || this.options.expires); + var extras = Buffer.concat([Buffer.from("00000000", "hex"), expiration]); + + var opcode = 2; + var serialized = this.serializer.serialize(opcode, value, extras); + var request = makeRequestBuffer( + opcode, + key, + serialized.extras, + serialized.value, + this.seq + ); + this.perform(key, request, this.seq, function (err, response) { + if (err) { + if (callback) { + callback(err, null, null); + } + return; + } + switch (response.header.status) { + case constants.RESPONSE_STATUS_SUCCCESS: + if (callback) { + callback(null, true); + } + break; + case constants.RESPONSE_STATUS_KEY_EXISTS: + if (callback) { + callback(null, false); + } + break; + default: + var errorMessage = "MemJS ADD: " + errors[response.header.status]; + logger.log(errorMessage, false); + if (callback) { + callback(new Error(errorMessage), null, null); + } + } }); } - // TODO: support version (CAS) - var logger = this.options.logger; - var initial; - var expires; - if (typeof options === 'function') { - // OLD: function(key, amount, callback, expires, initial) - logger.log('MemJS DECREMENT: using deprecated call - arguments have changed'); - initial = arguments[4]; - expires = callback; - callback = options; - options = {}; - } - // TODO: support version (CAS) - logger = this.options.logger; - initial = options.initial; - expires = options.expires; - - this.incrSeq(); - initial = initial || 0; - expires = expires || this.options.expires; - var extras = makeAmountInitialAndExpiration(amount, initial, expires); - var request = makeRequestBuffer(6, key, extras, '', this.seq); - this.perform(key, request, this.seq, function(err, response) { - if (err) { - if (callback) { callback(err, null); } - return; + // REPLACE + // + // Replaces the given _key_ and _value_ to memcache. The operation only succeeds + // if the key is already present. + // + // The options dictionary takes: + // * _expires_: overrides the default expiration (see `Client.create`) for this + // particular key-value pair. + // + // The callback signature is: + // + // callback(err, success) + replace(key, value, options, callback) { + if (callback === undefined && options !== "function") { + var self = this; + if (!options) options = {}; + return promisify(function (callback) { + self.replace(key, value, options, function (err, success) { + callback(err, success); + }); + }); } - switch (response.header.status) { - case constants.RESPONSE_STATUS_SUCCCESS: - var bufInt = (response.val.readUInt32BE(0) << 8) + response.val.readUInt32BE(4); - if (callback) { callback(null, true, bufInt); } - break; - default: - var errorMessage = 'MemJS DECREMENT: ' + errors[response.header.status]; - logger.log(errorMessage); - if (callback) { callback(new Error(errorMessage), null, null); } + var logger = this.options.logger; + var expires; + if (typeof options === "function") { + // OLD: function(key, value, callback, expires) + logger.log( + "MemJS REPLACE: using deprecated call - arguments have changed" + ); + expires = callback; + callback = options; + options = {}; } - }); -}; - -// APPEND -// -// Append the given _value_ to the value associated with the given _key_ in -// memcache. The operation only succeeds if the key is already present. The -// callback signature is: -// -// callback(err, success) -Client.prototype.append = function(key, value, callback) { - if(callback === undefined) { - var self = this; - return promisify(function(callback) { self.append(key, value, function(err, success) { callback(err, success); }); }); + + logger = this.options.logger; + expires = options.expires; + + // TODO: support flags, support version (CAS) + this.incrSeq(); + var expiration = makeExpiration(expires || this.options.expires); + var extras = Buffer.concat([Buffer.from("00000000", "hex"), expiration]); + + var opcode = 3; + var serialized = this.serializer.serialize(opcode, value, extras); + var request = makeRequestBuffer( + opcode, + key, + serialized.extras, + serialized.value, + this.seq + ); + this.perform(key, request, this.seq, function (err, response) { + if (err) { + if (callback) { + callback(err, null, null); + } + return; + } + switch (response.header.status) { + case constants.RESPONSE_STATUS_SUCCCESS: + if (callback) { + callback(null, true); + } + break; + case constants.RESPONSE_STATUS_KEY_NOT_FOUND: + if (callback) { + callback(null, false); + } + break; + default: + var errorMessage = "MemJS REPLACE: " + errors[response.header.status]; + logger.log(errorMessage, false); + if (callback) { + callback(new Error(errorMessage), null, null); + } + } + }); } - // TODO: support version (CAS) - var logger = this.options.logger; - this.incrSeq(); - var opcode = 0x0E; - var serialized = this.serializer.serialize(opcode, value, ''); - var request = makeRequestBuffer(opcode, key, serialized.extras, serialized.value, this.seq); - this.perform(key, request, this.seq, function(err, response) { - if (err) { - if (callback) { callback(err, null); } - return; - } - switch (response.header.status) { - case constants.RESPONSE_STATUS_SUCCCESS: - if (callback) { callback(null, true); } - break; - case constants.RESPONSE_STATUS_KEY_NOT_FOUND: - if (callback) { callback(null, false); } - break; - default: - var errorMessage = 'MemJS APPEND: ' + errors[response.header.status]; - logger.log(errorMessage); - if (callback) { callback(new Error(errorMessage), null); } + + // DELETE + // + // Deletes the given _key_ from memcache. The operation only succeeds + // if the key is already present. + // + // The callback signature is: + // + // callback(err, success) + delete(key, callback) { + if (callback === undefined) { + var self = this; + return promisify(function (callback) { + self.delete(key, function (err, success) { + callback(err, success); + }); + }); } - }); -}; - -// PREPEND -// -// Prepend the given _value_ to the value associated with the given _key_ in -// memcache. The operation only succeeds if the key is already present. The -// callback signature is: -// -// callback(err, success) -Client.prototype.prepend = function(key, value, callback) { - if(callback === undefined) { - var self = this; - return promisify(function(callback) { self.prepend(key, value, function(err, success) { callback(err, success); }); }); + // TODO: Support version (CAS) + var logger = this.options.logger; + this.incrSeq(); + var request = makeRequestBuffer(4, key, "", "", this.seq); + this.perform(key, request, this.seq, function (err, response) { + if (err) { + if (callback) { + callback(err, null, null); + } + return; + } + switch (response.header.status) { + case constants.RESPONSE_STATUS_SUCCCESS: + if (callback) { + callback(null, true); + } + break; + case constants.RESPONSE_STATUS_KEY_NOT_FOUND: + if (callback) { + callback(null, false); + } + break; + default: + var errorMessage = "MemJS DELETE: " + errors[response.header.status]; + logger.log(errorMessage, false); + if (callback) { + callback(new Error(errorMessage), null); + } + } + }); } - // TODO: support version (CAS) - var logger = this.options.logger; - this.incrSeq(); - - var opcode = 0x0E; - var serialized = this.serializer.serialize(opcode, value, ''); - var request = makeRequestBuffer(opcode, key, serialized.extras, serialized.value, this.seq); - this.perform(key, request, this.seq, function(err, response) { - if (err) { - if (callback) { callback(err, null); } - return; + + // INCREMENT + // + // Increments the given _key_ in memcache. + // + // The options dictionary takes: + // * _initial_: the value for the key if not already present, defaults to 0. + // * _expires_: overrides the default expiration (see `Client.create`) for this + // particular key-value pair. + // + // The callback signature is: + // + // callback(err, success, value) + increment(key, amount, options, callback) { + if (callback === undefined && options !== "function") { + var self = this; + return promisify(function (callback) { + if (!options) options = {}; + self.increment(key, amount, options, function (err, success, value) { + callback(err, { success: success, value: value }); + }); + }); } - switch (response.header.status) { - case constants.RESPONSE_STATUS_SUCCCESS: - if (callback) { callback(null, true); } - break; - case constants.RESPONSE_STATUS_KEY_NOT_FOUND: - if (callback) { callback(null, false); } - break; - default: - var errorMessage = 'MemJS PREPEND: ' + errors[response.header.status]; - logger.log(errorMessage); - if (callback) { callback(new Error(errorMessage), null); } + var logger = this.options.logger; + var initial; + var expires; + if (typeof options === "function") { + // OLD: function(key, amount, callback, expires, initial) + logger.log( + "MemJS INCREMENT: using deprecated call - arguments have changed" + ); + initial = arguments[4]; + expires = callback; + callback = options; + options = {}; } - }); -}; - -// TOUCH -// -// Touch sets an expiration value, given by _expires_, on the given _key_ in -// memcache. The operation only succeeds if the key is already present. The -// callback signature is: -// -// callback(err, success) -Client.prototype.touch = function(key, expires, callback) { - if(callback === undefined) { - var self = this; - return promisify(function(callback) { self.touch(key, expires, function(err, success) { callback(err, success); }); }); + + logger = this.options.logger; + initial = options.initial; + expires = options.expires; + + // TODO: support version (CAS) + this.incrSeq(); + initial = initial || 0; + expires = expires || this.options.expires; + var extras = makeAmountInitialAndExpiration(amount, initial, expires); + var request = makeRequestBuffer(5, key, extras, "", this.seq); + this.perform(key, request, this.seq, function (err, response) { + if (err) { + if (callback) { + callback(err, null); + } + return; + } + switch (response.header.status) { + case constants.RESPONSE_STATUS_SUCCCESS: + var bufInt = + (response.val.readUInt32BE(0) << 8) + response.val.readUInt32BE(4); + if (callback) { + callback(null, true, bufInt); + } + break; + default: + var errorMessage = + "MemJS INCREMENT: " + errors[response.header.status]; + logger.log(errorMessage); + if (callback) { + callback(new Error(errorMessage), null, null); + } + } + }); } - // TODO: support version (CAS) - var logger = this.options.logger; - this.incrSeq(); - var extras = makeExpiration(expires || this.options.expires); - var request = makeRequestBuffer(0x1C, key, extras, '', this.seq); - this.perform(key, request, this.seq, function(err, response) { - if (err) { - if (callback) { callback(err, null); } - return; + + // DECREMENT + // + // Decrements the given _key_ in memcache. + // + // The options dictionary takes: + // * _initial_: the value for the key if not already present, defaults to 0. + // * _expires_: overrides the default expiration (see `Client.create`) for this + // particular key-value pair. + // + // The callback signature is: + // + // callback(err, success, value) + decrement(key, amount, options, callback) { + if (callback === undefined && options !== "function") { + var self = this; + return promisify(function (callback) { + self.decrement(key, amount, options, function (err, success, value) { + callback(err, { success: success, value: value }); + }); + }); } - switch (response.header.status) { - case constants.RESPONSE_STATUS_SUCCCESS: - if (callback) { callback(null, true); } - break; - case constants.RESPONSE_STATUS_KEY_NOT_FOUND: - if (callback) { callback(null, false); } - break; - default: - var errorMessage = 'MemJS TOUCH: ' + errors[response.header.status]; - logger.log(errorMessage); - if (callback) { callback(new Error(errorMessage), null); } + // TODO: support version (CAS) + var logger = this.options.logger; + var initial; + var expires; + if (typeof options === "function") { + // OLD: function(key, amount, callback, expires, initial) + logger.log( + "MemJS DECREMENT: using deprecated call - arguments have changed" + ); + initial = arguments[4]; + expires = callback; + callback = options; + options = {}; } - }); -}; - -// FLUSH -// -// Flushes the cache on each connected server. The callback signature is: -// -// callback(lastErr, results) -// -// where _lastErr_ is the last error encountered (or null, in the common case -// of no errors). _results_ is a dictionary mapping `"hostname:port"` to either -// `true` (if the operation was successful), or an error. -Client.prototype.flush = function(callback) { - if(callback === undefined) { - var self = this; - return promisify(function(callback) { self.flush(function(err, results) { callback(err, results); }); }); - } - // TODO: support expiration - this.incrSeq(); - var request = makeRequestBuffer(0x08, '', '', '', this.seq); - var count = this.servers.length; - var result = {}; - var lastErr = null; - var i; - - var handleFlush = function(seq, serv) { - serv.onResponse(seq, function(/* response */) { - count -= 1; - result[serv.hostportString()] = true; - if (callback && count === 0) { - callback(lastErr, result); + + // TODO: support version (CAS) + logger = this.options.logger; + initial = options.initial; + expires = options.expires; + + this.incrSeq(); + initial = initial || 0; + expires = expires || this.options.expires; + var extras = makeAmountInitialAndExpiration(amount, initial, expires); + var request = makeRequestBuffer(6, key, extras, "", this.seq); + this.perform(key, request, this.seq, function (err, response) { + if (err) { + if (callback) { + callback(err, null); + } + return; } - }); - serv.onError(seq, function(err) { - count -= 1; - lastErr = err; - result[serv.hostportString()] = err; - if (callback && count === 0) { - callback(lastErr, result); + switch (response.header.status) { + case constants.RESPONSE_STATUS_SUCCCESS: + var bufInt = + (response.val.readUInt32BE(0) << 8) + response.val.readUInt32BE(4); + if (callback) { + callback(null, true, bufInt); + } + break; + default: + var errorMessage = + "MemJS DECREMENT: " + errors[response.header.status]; + logger.log(errorMessage); + if (callback) { + callback(new Error(errorMessage), null, null); + } } }); - serv.write(request); - }; + } - for (i = 0; i < this.servers.length; i++) { - handleFlush(this.seq, this.servers[i]); + // APPEND + // + // Append the given _value_ to the value associated with the given _key_ in + // memcache. The operation only succeeds if the key is already present. The + // callback signature is: + // + // callback(err, success) + append(key, value, callback) { + if (callback === undefined) { + var self = this; + return promisify(function (callback) { + self.append(key, value, function (err, success) { + callback(err, success); + }); + }); + } + // TODO: support version (CAS) + var logger = this.options.logger; + this.incrSeq(); + var opcode = 0x0e; + var serialized = this.serializer.serialize(opcode, value, ""); + var request = makeRequestBuffer( + opcode, + key, + serialized.extras, + serialized.value, + this.seq + ); + this.perform(key, request, this.seq, function (err, response) { + if (err) { + if (callback) { + callback(err, null); + } + return; + } + switch (response.header.status) { + case constants.RESPONSE_STATUS_SUCCCESS: + if (callback) { + callback(null, true); + } + break; + case constants.RESPONSE_STATUS_KEY_NOT_FOUND: + if (callback) { + callback(null, false); + } + break; + default: + var errorMessage = "MemJS APPEND: " + errors[response.header.status]; + logger.log(errorMessage); + if (callback) { + callback(new Error(errorMessage), null); + } + } + }); } -}; - -// STATS_WITH_KEY -// -// Sends a memcache stats command with a key to each connected server. The -// callback is invoked **ONCE PER SERVER** and has the signature: -// -// callback(err, server, stats) -// -// _server_ is the `"hostname:port"` of the server, and _stats_ is a dictionary -// mapping the stat name to the value of the statistic as a string. -Client.prototype.statsWithKey = function(key, callback) { - var logger = this.options.logger; - this.incrSeq(); - var request = makeRequestBuffer(0x10, key, '', '', this.seq); - var i; - - var handleStats = function(seq, serv) { - var result = {}; - var handle = function(response) { - // end of stat responses - if (response.header.totalBodyLength === 0) { - if (callback) { callback(null, serv.hostportString(), result); } + + // PREPEND + // + // Prepend the given _value_ to the value associated with the given _key_ in + // memcache. The operation only succeeds if the key is already present. The + // callback signature is: + // + // callback(err, success) + prepend(key, value, callback) { + if (callback === undefined) { + var self = this; + return promisify(function (callback) { + self.prepend(key, value, function (err, success) { + callback(err, success); + }); + }); + } + // TODO: support version (CAS) + var logger = this.options.logger; + this.incrSeq(); + + var opcode = 0x0e; + var serialized = this.serializer.serialize(opcode, value, ""); + var request = makeRequestBuffer( + opcode, + key, + serialized.extras, + serialized.value, + this.seq + ); + this.perform(key, request, this.seq, function (err, response) { + if (err) { + if (callback) { + callback(err, null); + } return; } - // process single stat line response switch (response.header.status) { - case constants.RESPONSE_STATUS_SUCCCESS: - result[response.key.toString()] = response.val.toString(); - break; - default: - var errorMessage = 'MemJS STATS (' + key + '): ' + - errors[response.header.status]; - logger.log(errorMessage, false); + case constants.RESPONSE_STATUS_SUCCCESS: + if (callback) { + callback(null, true); + } + break; + case constants.RESPONSE_STATUS_KEY_NOT_FOUND: + if (callback) { + callback(null, false); + } + break; + default: + var errorMessage = "MemJS PREPEND: " + errors[response.header.status]; + logger.log(errorMessage); + if (callback) { + callback(new Error(errorMessage), null); + } + } + }); + } + + // TOUCH + // + // Touch sets an expiration value, given by _expires_, on the given _key_ in + // memcache. The operation only succeeds if the key is already present. The + // callback signature is: + // + // callback(err, success) + touch(key, expires, callback) { + if (callback === undefined) { + var self = this; + return promisify(function (callback) { + self.touch(key, expires, function (err, success) { + callback(err, success); + }); + }); + } + // TODO: support version (CAS) + var logger = this.options.logger; + this.incrSeq(); + var extras = makeExpiration(expires || this.options.expires); + var request = makeRequestBuffer(0x1c, key, extras, "", this.seq); + this.perform(key, request, this.seq, function (err, response) { + if (err) { if (callback) { - callback(new Error(errorMessage), serv.hostportString(), null); + callback(err, null); } + return; } + switch (response.header.status) { + case constants.RESPONSE_STATUS_SUCCCESS: + if (callback) { + callback(null, true); + } + break; + case constants.RESPONSE_STATUS_KEY_NOT_FOUND: + if (callback) { + callback(null, false); + } + break; + default: + var errorMessage = "MemJS TOUCH: " + errors[response.header.status]; + logger.log(errorMessage); + if (callback) { + callback(new Error(errorMessage), null); + } + } + }); + } + + // FLUSH + // + // Flushes the cache on each connected server. The callback signature is: + // + // callback(lastErr, results) + // + // where _lastErr_ is the last error encountered (or null, in the common case + // of no errors). _results_ is a dictionary mapping `"hostname:port"` to either + // `true` (if the operation was successful), or an error. + flush(callback) { + if (callback === undefined) { + var self = this; + return promisify(function (callback) { + self.flush(function (err, results) { + callback(err, results); + }); + }); + } + // TODO: support expiration + this.incrSeq(); + var request = makeRequestBuffer(0x08, "", "", "", this.seq); + var count = this.servers.length; + var result = {}; + var lastErr = null; + var i; + + var handleFlush = function (seq, serv) { + serv.onResponse(seq, function (/* response */) { + count -= 1; + result[serv.hostportString()] = true; + if (callback && count === 0) { + callback(lastErr, result); + } + }); + serv.onError(seq, function (err) { + count -= 1; + lastErr = err; + result[serv.hostportString()] = err; + if (callback && count === 0) { + callback(lastErr, result); + } + }); + serv.write(request); }; - handle.quiet = true; - serv.onResponse(seq, handle); - serv.onError(seq, function(err) { - if (callback) { callback(err, serv.hostportString(), null); } - }); - serv.write(request); - }; + for (i = 0; i < this.servers.length; i++) { + handleFlush(this.seq, this.servers[i]); + } + } + + // STATS_WITH_KEY + // + // Sends a memcache stats command with a key to each connected server. The + // callback is invoked **ONCE PER SERVER** and has the signature: + // + // callback(err, server, stats) + // + // _server_ is the `"hostname:port"` of the server, and _stats_ is a dictionary + // mapping the stat name to the value of the statistic as a string. + statsWithKey(key, callback) { + var logger = this.options.logger; + this.incrSeq(); + var request = makeRequestBuffer(0x10, key, "", "", this.seq); + var i; + + var handleStats = function (seq, serv) { + var result = {}; + var handle = function (response) { + // end of stat responses + if (response.header.totalBodyLength === 0) { + if (callback) { + callback(null, serv.hostportString(), result); + } + return; + } + // process single stat line response + switch (response.header.status) { + case constants.RESPONSE_STATUS_SUCCCESS: + result[response.key.toString()] = response.val.toString(); + break; + default: + var errorMessage = + "MemJS STATS (" + key + "): " + errors[response.header.status]; + logger.log(errorMessage, false); + if (callback) { + callback(new Error(errorMessage), serv.hostportString(), null); + } + } + }; + handle.quiet = true; + + serv.onResponse(seq, handle); + serv.onError(seq, function (err) { + if (callback) { + callback(err, serv.hostportString(), null); + } + }); + serv.write(request); + }; - for (i = 0; i < this.servers.length; i++) { - handleStats(this.seq, this.servers[i]); + for (i = 0; i < this.servers.length; i++) { + handleStats(this.seq, this.servers[i]); + } } -}; - - -// STATS -// -// Fetches memcache stats from each connected server. The callback is invoked -// **ONCE PER SERVER** and has the signature: -// -// callback(err, server, stats) -// -// _server_ is the `"hostname:port"` of the server, and _stats_ is a -// dictionary mapping the stat name to the value of the statistic as a string. -Client.prototype.stats = function(callback) { - this.statsWithKey('', callback); -}; - -// RESET_STATS -// -// Reset the statistics each server is keeping back to zero. This doesn't clear -// stats such as item count, but temporary stats such as total number of -// connections over time. -// -// The callback is invoked **ONCE PER SERVER** and has the signature: -// -// callback(err, server) -// -// _server_ is the `"hostname:port"` of the server. -Client.prototype.resetStats = function(callback) { - this.statsWithKey('reset', callback); -}; - -// QUIT -// -// Closes the connection to each server, notifying them of this intention. Note -// that quit can race against already outstanding requests when those requests -// fail and are retried, leading to the quit command winning and closing the -// connection before the retries complete. -Client.prototype.quit = function() { - this.incrSeq(); - // TODO: Nicer perhaps to do QUITQ (0x17) but need a new callback for when - // write is done. - var request = makeRequestBuffer(0x07, '', '', '', this.seq); // QUIT - var serv; - var i; - - var handleQuit = function(seq, serv) { - serv.onResponse(seq, function(/* response */) { - serv.close(); - }); - serv.onError(seq, function(/* err */) { - serv.close(); - }); - serv.write(request); - }; - for (i = 0; i < this.servers.length; i++) { - serv = this.servers[i]; - handleQuit(this.seq, serv); + // STATS + // + // Fetches memcache stats from each connected server. The callback is invoked + // **ONCE PER SERVER** and has the signature: + // + // callback(err, server, stats) + // + // _server_ is the `"hostname:port"` of the server, and _stats_ is a + // dictionary mapping the stat name to the value of the statistic as a string. + stats(callback) { + this.statsWithKey("", callback); } -}; - -Client.prototype._version = function(server, callback) { - var self = this; - if(callback === undefined) { - return promisify(function(callback) { - self._version(server, function(err, value, flags) { - callback(err, {value: value, flags: flags}); - }); - }); + + // RESET_STATS + // + // Reset the statistics each server is keeping back to zero. This doesn't clear + // stats such as item count, but temporary stats such as total number of + // connections over time. + // + // The callback is invoked **ONCE PER SERVER** and has the signature: + // + // callback(err, server) + // + // _server_ is the `"hostname:port"` of the server. + resetStats(callback) { + this.statsWithKey("reset", callback); } - this.incrSeq(); - var request = makeRequestBuffer(constants.OP_VERSION, '', '', '', this.seq); - var logger = this.options.logger; + // QUIT + // + // Closes the connection to each server, notifying them of this intention. Note + // that quit can race against already outstanding requests when those requests + // fail and are retried, leading to the quit command winning and closing the + // connection before the retries complete. + quit() { + this.incrSeq(); + // TODO: Nicer perhaps to do QUITQ (0x17) but need a new callback for when + // write is done. + var request = makeRequestBuffer(0x07, "", "", "", this.seq); // QUIT + var serv; + var i; + + var handleQuit = function (seq, serv) { + serv.onResponse(seq, function (/* response */) { + serv.close(); + }); + serv.onError(seq, function (/* err */) { + serv.close(); + }); + serv.write(request); + }; - this.performOnServer(server, request, this.seq, function (err, response) { - if (err) { - if (callback) { callback(err, null, null); } - return; + for (i = 0; i < this.servers.length; i++) { + serv = this.servers[i]; + handleQuit(this.seq, serv); } + } - switch (response.header.status) { - case constants.RESPONSE_STATUS_SUCCCESS: - var deserialized = self.serializer.deserialize(response.header.opcode, response.val, response.extras); - callback(null, deserialized.value, deserialized.extras); - break; - default: - var errorMessage = 'MemJS VERSION: ' + errors[response.header.status]; - logger.log(errorMessage); - if (callback) { callback(new Error(errorMessage), null, null); } + _version(server, callback) { + var self = this; + if (callback === undefined) { + return promisify(function (callback) { + self._version(server, function (err, value, flags) { + callback(err, { value: value, flags: flags }); + }); + }); } - }); -}; -// VERSION -// -// Request the server version from the "first" server in the backend pool -// -// The server responds with a packet containing the version string in the body with the following format: "x.y.z" + this.incrSeq(); + var request = makeRequestBuffer(constants.OP_VERSION, "", "", "", this.seq); + var logger = this.options.logger; -Client.prototype.version = function(callback) { - const server = this.serverKeyToServer(this.serverKeys[0]); + this.performOnServer(server, request, this.seq, function (err, response) { + if (err) { + if (callback) { + callback(err, null, null); + } + return; + } - return this._version(server, callback); -}; + switch (response.header.status) { + case constants.RESPONSE_STATUS_SUCCCESS: + var deserialized = self.serializer.deserialize( + response.header.opcode, + response.val, + response.extras + ); + callback(null, deserialized.value, deserialized.extras); + break; + default: + var errorMessage = "MemJS VERSION: " + errors[response.header.status]; + logger.log(errorMessage); + if (callback) { + callback(new Error(errorMessage), null, null); + } + } + }); + } + + // VERSION + // + // Request the server version from the "first" server in the backend pool + // + // The server responds with a packet containing the version string in the body with the following format: "x.y.z" -Client.prototype.versionAll = function(callback) { - const promise = Promise.all(this.serverKeys.map((serverKey) => { - const server = this.serverKeyToServer(serverKey); + version(callback) { + const server = this.serverKeyToServer(this.serverKeys[0]); + + return this._version(server, callback); + } - return this._version(server).then((response) => { - return {serverKey: serverKey, value: response.value}; + versionAll(callback) { + const promise = Promise.all( + this.serverKeys.map((serverKey) => { + const server = this.serverKeyToServer(serverKey); + + return this._version(server).then((response) => { + return { serverKey: serverKey, value: response.value }; + }); + }) + ).then((versionObjects) => { + const values = versionObjects.reduce((accumulator, versionObject) => { + accumulator[versionObject.serverKey] = versionObject.value; + return accumulator; + }, {}); + return { values: values }; }); - })).then(versionObjects => { - const values = versionObjects.reduce((accumulator, versionObject) => { - accumulator[versionObject.serverKey] = versionObject.value; - return accumulator; - }, {}); - return {values: values}; - }); - if(callback === undefined) { - return promise; + if (callback === undefined) { + return promise; + } + return promise + .then((response) => { + callback(null, response.values); + }) + .catch((err) => { + callback(err, null); + }); } - return promise.then((response) =>{ - callback(null, response.values); - }).catch((err) => { - callback(err, null); - }); -}; - -// CLOSE -// -// Closes (abruptly) connections to all the servers. -Client.prototype.close = function() { - var i; - for (i = 0; i < this.servers.length; i++) { - this.servers[i].close(); + + // CLOSE + // + // Closes (abruptly) connections to all the servers. + close() { + var i; + for (i = 0; i < this.servers.length; i++) { + this.servers[i].close(); + } } -}; -/** + /** * Perform a generic single response operation (get, set etc) on one server * * @param {string} key the key to hash to get a server from the pool @@ -1017,58 +1384,82 @@ Client.prototype.close = function() { * @param {*} callback a callback invoked when a response is received or the request fails * @param {*} retries number of times to retry request on failure */ -Client.prototype.perform = function(key, request, seq, callback, retries) { - var serverKey = this.lookupKeyToServerKey(key); + perform( + key: string, + request: Buffer, + seq: number, + callback: ResponseOrErrorCallback, + retries?: number + ) { + var serverKey = this.lookupKeyToServerKey(key); - var server = this.serverKeyToServer(serverKey); + var server = this.serverKeyToServer(serverKey); - if (!server) { - if (callback) { callback(new Error('No servers available'), null); } - return; - } - return this.performOnServer(server, request, seq, callback, retries); -}; - -Client.prototype.performOnServer = function(server, request, seq, callback, retries) { - var _this = this; - - retries = retries || this.options.retries; - var origRetries = this.options.retries; - var logger = this.options.logger; - var retry_delay = this.options.retry_delay; - - var responseHandler = function(response) { - if (callback) { callback(null, response); } - }; - - var errorHandler = function(error) { - if (--retries > 0) { - // Wait for retry_delay - setTimeout(function() { - _this.performOnServer(server, request, seq, callback, retries); - }, 1000 * retry_delay); - } else { - logger.log('MemJS: Server <' + server.hostportString() + - '> failed after (' + origRetries + - ') retries with error - ' + error.message); - if (callback) { callback(error, null); } + if (!server) { + if (callback) { + callback(new Error("No servers available"), null); + } + return; } - }; + return this.performOnServer(server, request, seq, callback, retries); + } + + performOnServer( + server: Server, + request: Buffer, + seq: Number, + callback: ResponseOrErrorCallback, + retries?: number + ) { + var _this = this; + + retries = retries || this.options.retries; + var origRetries = this.options.retries; + var logger = this.options.logger; + var retry_delay = this.options.retry_delay; + + var responseHandler = function (response) { + if (callback) { + callback(null, response); + } + }; - server.onResponse(seq, responseHandler); - server.onError(seq, errorHandler); - server.write(request); -}; + var errorHandler = function (error) { + if (--retries > 0) { + // Wait for retry_delay + setTimeout(function () { + _this.performOnServer(server, request, seq, callback, retries); + }, 1000 * retry_delay); + } else { + logger.log( + "MemJS: Server <" + + server.hostportString() + + "> failed after (" + + origRetries + + ") retries with error - " + + error.message + ); + if (callback) { + callback(error, null); + } + } + }; -// Increment the seq value -Client.prototype.incrSeq = function() { - this.seq++; + server.onResponse(seq, responseHandler); + server.onError(seq, errorHandler); + server.write(request); + } + + // Increment the seq value + incrSeq() { + this.seq++; - // Wrap `this.seq` to 32-bits since the field we fit it into is only 32-bits. - this.seq &= 0xffffffff; -}; + // Wrap `this.seq` to 32-bits since the field we fit it into is only 32-bits. + this.seq &= 0xffffffff; + } +} exports.Client = Client; exports.Server = Server; -exports.Utils = require('./utils'); -exports.Header = require('./header'); +exports.Utils = require("./utils"); +exports.Header = require("./header"); diff --git a/src/memjs/noop-serializer.ts b/src/memjs/noop-serializer.ts index febc477..b43b873 100644 --- a/src/memjs/noop-serializer.ts +++ b/src/memjs/noop-serializer.ts @@ -1,17 +1,22 @@ import { OP } from "./constants"; import { MaybeBuffer } from "./utils"; -interface Serializer { +export interface SerializerResult { + value: Value; + extras: Extras; +} + +export interface Serializer { serialize( opcode: OP, value: Value, extras: Extras - ): { value: MaybeBuffer; extras: MaybeBuffer }; + ): SerializerResult; deserialize( opcode: OP, value: MaybeBuffer, extras: MaybeBuffer - ): { value: Value; extras: Extras }; + ): SerializerResult; } export const noopSerializer: Serializer = { diff --git a/src/memjs/protocol.ts b/src/memjs/protocol.ts index 2492cbd..505b414 100644 --- a/src/memjs/protocol.ts +++ b/src/memjs/protocol.ts @@ -1,5 +1,7 @@ /** MemJS Memcache binary protocol errors */ +export const UNKNOWN_ERROR = -1; export const errors: { [key: number]: string } = {}; +errors[UNKNOWN_ERROR] = "Unknown error"; errors[0x0000] = "No error"; errors[0x0001] = "Key not found"; errors[0x0002] = "Key exists"; diff --git a/src/memjs/server.ts b/src/memjs/server.ts index 5ce3587..a7a7928 100644 --- a/src/memjs/server.ts +++ b/src/memjs/server.ts @@ -8,7 +8,7 @@ import { Message, } from "./utils"; -interface ServerOptions { +export interface ServerOptions { timeout: number; keepAlive: boolean; keepAliveDelay: number; @@ -17,19 +17,19 @@ interface ServerOptions { password?: string; } -type Seq = string; +type Seq = number; -interface OnConnectCallback { +export interface OnConnectCallback { (socket: net.Socket): void; } -interface OnResponseCallback { +export interface OnResponseCallback { (message: Message): void; quiet?: boolean; } -interface OnErrorCallback { - (error: Error | string): void; +export interface OnErrorCallback { + (error: Error): void; } export class Server extends events.EventEmitter { @@ -50,7 +50,7 @@ export class Server extends events.EventEmitter { constructor( host: string, - port: number, + port: string | number, username?: string, password?: string, options?: Partial @@ -58,7 +58,7 @@ export class Server extends events.EventEmitter { super(); this.responseBuffer = Buffer.from([]); this.host = host; - this.port = port; + this.port = parseInt(port.toString(), 10); this.connected = false; this.timeoutSet = false; this.connectCallbacks = []; @@ -115,7 +115,7 @@ export class Server extends events.EventEmitter { this.errorCallbacks[seq] = func; } - error(err: Error | string) { + error(err: Error) { var errcalls = this.errorCallbacks; this.connectCallbacks = []; this.responseCallbacks = {}; @@ -156,7 +156,7 @@ export class Server extends events.EventEmitter { if (response.header.opcode === 0x20) { this.saslAuth(); } else if (response.header.status === 0x20) { - this.error("Memcached server authentication failed!"); + this.error(new Error("Memcached server authentication failed!")); } else if (response.header.opcode === 0x21) { this.emit("authenticated"); } else { @@ -173,38 +173,40 @@ export class Server extends events.EventEmitter { if (!self._socket) { // CASE 1: completely new socket self.connected = false; - self._socket = net.connect(this.port, this.host, function ( - this: net.Socket - ) { - // SASL authentication handler - self.once("authenticated", function () { - if (self._socket) { - const socket = self._socket; - self.connected = true; - // cancel connection timeout - self._socket.setTimeout(0); - self.timeoutSet = false; - // run actual request(s) - go(self._socket); - self.connectCallbacks.forEach(function (cb) { - cb(socket); - }); - self.connectCallbacks = []; - } - }); + self._socket = net.connect( + this.port, + this.host, + function (this: net.Socket) { + // SASL authentication handler + self.once("authenticated", function () { + if (self._socket) { + const socket = self._socket; + self.connected = true; + // cancel connection timeout + self._socket.setTimeout(0); + self.timeoutSet = false; + // run actual request(s) + go(self._socket); + self.connectCallbacks.forEach(function (cb) { + cb(socket); + }); + self.connectCallbacks = []; + } + }); - // setup response handler - this.on("data", function (dataBuf) { - self.responseHandler(dataBuf); - }); + // setup response handler + this.on("data", function (dataBuf) { + self.responseHandler(dataBuf); + }); - // kick of SASL if needed - if (self.username && self.password) { - self.listSasl(); - } else { - self.emit("authenticated"); + // kick of SASL if needed + if (self.username && self.password) { + self.listSasl(); + } else { + self.emit("authenticated"); + } } - }); + ); // setup error handler self._socket.on("error", function (error) { @@ -221,16 +223,17 @@ export class Server extends events.EventEmitter { // setup connection timeout handler self.timeoutSet = true; - self._socket.setTimeout(self.options.conntimeout * 1000, function ( - this: net.Socket - ) { - self.timeoutSet = false; - if (!self.connected) { - this.end(); - self._socket = undefined; - self.error(new Error("socket timed out connecting to server.")); + self._socket.setTimeout( + self.options.conntimeout * 1000, + function (this: net.Socket) { + self.timeoutSet = false; + if (!self.connected) { + this.end(); + self._socket = undefined; + self.error(new Error("socket timed out connecting to server.")); + } } - }); + ); // use TCP keep-alive self._socket.setKeepAlive( From 9f58c61cb154732a8c760928a7878f94dc9424af Mon Sep 17 00:00:00 2001 From: Jake Teton-Landis Date: Fri, 9 Apr 2021 18:42:33 -0700 Subject: [PATCH 21/79] WIP2 --- src/memjs/memjs.ts | 761 +++++++++++++++++++++++++---------- src/memjs/noop-serializer.ts | 2 +- 2 files changed, 541 insertions(+), 222 deletions(-) diff --git a/src/memjs/memjs.ts b/src/memjs/memjs.ts index 001124d..642c441 100644 --- a/src/memjs/memjs.ts +++ b/src/memjs/memjs.ts @@ -1,7 +1,12 @@ // # MemJS Memcache Client import { errors, UNKNOWN_ERROR } from "./protocol"; -import { OnResponseCallback, Server, ServerOptions } from "./server"; +import { + OnErrorCallback, + OnResponseCallback, + Server, + ServerOptions, +} from "./server"; import { noopSerializer, Serializer, @@ -501,17 +506,23 @@ class Client { } } - // SET - // - // Sets the given _key_ and _value_ in memcache. - // - // The options dictionary takes: - // * _expires_: overrides the default expiration (see `Client.create`) for this - // particular key-value pair. - // - // The callback signature is: - // - // callback(err, success) + /** + * SET + * + * Sets the given _key_ and _value_ in memcache. + * + * The options dictionary takes: + * * _expires_: overrides the default expiration (see `Client.create`) for this + * particular key-value pair. + * + * The callback signature is: + * + * callback(err, success) + * @param key + * @param value + * @param options + * @param callback + */ set( key: string, value: Value, @@ -531,7 +542,7 @@ class Client { set( key: string, value: Value, - options: + options?: | { expires?: number } | ((error: Error | null, success: boolean | null) => void), callback?: (error: Error | null, success: boolean | null) => void @@ -564,7 +575,7 @@ class Client { } logger = this.options.logger; - expires = options.expires; + expires = (options || {}).expires; // TODO: support flags, support version (CAS) this.incrSeq(); @@ -572,11 +583,7 @@ class Client { var extras = Buffer.concat([Buffer.from("00000000", "hex"), expiration]); var opcode: constants.OP = 1; - var serialized = this.serializer.serialize( - opcode, - value, - extras as any /* TODO */ - ); + var serialized = this.serializer.serialize(opcode, value, extras); var request = makeRequestBuffer( opcode, key, @@ -608,26 +615,60 @@ class Client { }); } - // ADD - // - // Adds the given _key_ and _value_ to memcache. The operation only succeeds - // if the key is not already set. - // - // The options dictionary takes: - // * _expires_: overrides the default expiration (see `Client.create`) for this - // particular key-value pair. - // - // The callback signature is: - // - // callback(err, success) - add(key, value, options, callback) { + /** + * ADD + * + * Adds the given _key_ and _value_ to memcache. The operation only succeeds + * if the key is not already set. + * + * The options dictionary takes: + * * _expires_: overrides the default expiration (see `Client.create`) for this + * particular key-value pair. + * + * The callback signature is: + * + * callback(err, success) + * @param key + * @param value + * @param options + * @param callback + */ + add( + key: string, + value: Value, + options?: { expires?: number } + ): Promise; + add( + key: string, + value: Value, + callback: (error: Error | null, success: boolean | null) => void + ): void; + add( + key: string, + value: Value, + options: { expires?: number }, + callback: (error: Error | null, success: boolean | null) => void + ): void; + add( + key: string, + value: Value, + options?: + | { expires?: number } + | ((error: Error | null, success: boolean | null) => void), + callback?: (error: Error | null, success: boolean | null) => void + ): Promise | void { if (callback === undefined && options !== "function") { var self = this; if (!options) options = {}; return promisify(function (callback) { - self.add(key, value, options, function (err, success) { - callback(err, success); - }); + self.add( + key, + value, + options as { expires?: number }, + function (err, success) { + callback(err, success); + } + ); }); } var logger = this.options.logger; @@ -641,14 +682,14 @@ class Client { } logger = this.options.logger; - expires = options.expires; + expires = (options || {}).expires; // TODO: support flags, support version (CAS) this.incrSeq(); var expiration = makeExpiration(expires || this.options.expires); var extras = Buffer.concat([Buffer.from("00000000", "hex"), expiration]); - var opcode = 2; + var opcode: constants.OP = 2; var serialized = this.serializer.serialize(opcode, value, extras); var request = makeRequestBuffer( opcode, @@ -660,11 +701,11 @@ class Client { this.perform(key, request, this.seq, function (err, response) { if (err) { if (callback) { - callback(err, null, null); + callback(err, null); } return; } - switch (response.header.status) { + switch (response!.header.status) { case constants.RESPONSE_STATUS_SUCCCESS: if (callback) { callback(null, true); @@ -676,35 +717,70 @@ class Client { } break; default: - var errorMessage = "MemJS ADD: " + errors[response.header.status]; + var errorMessage = + "MemJS ADD: " + errors[response!.header.status || UNKNOWN_ERROR]; logger.log(errorMessage, false); if (callback) { - callback(new Error(errorMessage), null, null); + callback(new Error(errorMessage), null); } } }); } - // REPLACE - // - // Replaces the given _key_ and _value_ to memcache. The operation only succeeds - // if the key is already present. - // - // The options dictionary takes: - // * _expires_: overrides the default expiration (see `Client.create`) for this - // particular key-value pair. - // - // The callback signature is: - // - // callback(err, success) - replace(key, value, options, callback) { + /** + * REPLACE + * + * Replaces the given _key_ and _value_ to memcache. The operation only succeeds + * if the key is already present. + * + * The options dictionary takes: + * * _expires_: overrides the default expiration (see `Client.create`) for this + * particular key-value pair. + * + * The callback signature is: + * + * callback(err, success) + * @param key + * @param value + * @param options + * @param callback + */ + replace( + key: string, + value: Value, + options?: { expires?: number } + ): Promise; + replace( + key: string, + value: Value, + callback: (error: Error | null, success: boolean | null) => void + ): void; + replace( + key: string, + value: Value, + options: { expires?: number }, + callback: (error: Error | null, success: boolean | null) => void + ): void; + replace( + key: string, + value: Value, + options?: + | { expires?: number } + | ((error: Error | null, success: boolean | null) => void), + callback?: (error: Error | null, success: boolean | null) => void + ): Promise | void { if (callback === undefined && options !== "function") { var self = this; if (!options) options = {}; return promisify(function (callback) { - self.replace(key, value, options, function (err, success) { - callback(err, success); - }); + self.replace( + key, + value, + options as { expires?: number }, + function (err, success) { + callback(err, success); + } + ); }); } var logger = this.options.logger; @@ -720,14 +796,14 @@ class Client { } logger = this.options.logger; - expires = options.expires; + expires = (options || {}).expires; // TODO: support flags, support version (CAS) this.incrSeq(); var expiration = makeExpiration(expires || this.options.expires); var extras = Buffer.concat([Buffer.from("00000000", "hex"), expiration]); - var opcode = 3; + var opcode: constants.OP = 3; var serialized = this.serializer.serialize(opcode, value, extras); var request = makeRequestBuffer( opcode, @@ -739,11 +815,11 @@ class Client { this.perform(key, request, this.seq, function (err, response) { if (err) { if (callback) { - callback(err, null, null); + callback(err, null); } return; } - switch (response.header.status) { + switch (response!.header.status) { case constants.RESPONSE_STATUS_SUCCCESS: if (callback) { callback(null, true); @@ -755,29 +831,43 @@ class Client { } break; default: - var errorMessage = "MemJS REPLACE: " + errors[response.header.status]; + var errorMessage = + "MemJS REPLACE: " + + errors[response!.header.status || UNKNOWN_ERROR]; logger.log(errorMessage, false); if (callback) { - callback(new Error(errorMessage), null, null); + callback(new Error(errorMessage), null); } } }); } - // DELETE - // - // Deletes the given _key_ from memcache. The operation only succeeds - // if the key is already present. - // - // The callback signature is: - // - // callback(err, success) - delete(key, callback) { + /** + * DELETE + * + * Deletes the given _key_ from memcache. The operation only succeeds + * if the key is already present. + * + * The callback signature is: + * + * callback(err, success) + * @param key + * @param callback + */ + delete(key: string): Promise; + delete( + key: string, + callback: (err: Error | null, success: boolean | null) => void + ): void; + delete( + key: string, + callback?: (err: Error | null, success: boolean | null) => void + ): Promise | void { if (callback === undefined) { var self = this; return promisify(function (callback) { self.delete(key, function (err, success) { - callback(err, success); + callback(err, Boolean(success)); }); }); } @@ -788,11 +878,11 @@ class Client { this.perform(key, request, this.seq, function (err, response) { if (err) { if (callback) { - callback(err, null, null); + callback(err, null); } return; } - switch (response.header.status) { + switch (response!.header.status) { case constants.RESPONSE_STATUS_SUCCCESS: if (callback) { callback(null, true); @@ -804,7 +894,8 @@ class Client { } break; default: - var errorMessage = "MemJS DELETE: " + errors[response.header.status]; + var errorMessage = + "MemJS DELETE: " + errors[response!.header.status || UNKNOWN_ERROR]; logger.log(errorMessage, false); if (callback) { callback(new Error(errorMessage), null); @@ -813,25 +904,55 @@ class Client { }); } - // INCREMENT - // - // Increments the given _key_ in memcache. - // - // The options dictionary takes: - // * _initial_: the value for the key if not already present, defaults to 0. - // * _expires_: overrides the default expiration (see `Client.create`) for this - // particular key-value pair. - // - // The callback signature is: - // - // callback(err, success, value) - increment(key, amount, options, callback) { + /** + * INCREMENT + * + * Increments the given _key_ in memcache. + * + * The options dictionary takes: + * * _initial_: the value for the key if not already present, defaults to 0. + * * _expires_: overrides the default expiration (see `Client.create`) for this + * particular key-value pair. + * + * The callback signature is: + * + * callback(err, success, value) + * @param key + * @param amount + * @param options + * @param callback + */ + increment( + key: string, + amount: number, + options: { initial?: number; expires?: number } + ): Promise<{ value: number | null; success: boolean | null }>; + increment( + key: string, + amount: number, + options: { initial?: number; expires?: number }, + callback: ( + error: Error | null, + success: boolean | null, + value?: number | null + ) => void + ): void; + increment( + key: string, + amount: number, + options: { initial?: number; expires?: number }, + callback?: ( + error: Error | null, + success: boolean | null, + value?: number | null + ) => void + ): Promise<{ value: number | null; success: boolean | null }> | void { if (callback === undefined && options !== "function") { var self = this; return promisify(function (callback) { if (!options) options = {}; self.increment(key, amount, options, function (err, success, value) { - callback(err, { success: success, value: value }); + callback(err, { success: success, value: value || null }); }); }); } @@ -866,17 +987,19 @@ class Client { } return; } - switch (response.header.status) { + switch (response!.header.status) { case constants.RESPONSE_STATUS_SUCCCESS: var bufInt = - (response.val.readUInt32BE(0) << 8) + response.val.readUInt32BE(4); + (response!.val.readUInt32BE(0) << 8) + + response!.val.readUInt32BE(4); if (callback) { callback(null, true, bufInt); } break; default: var errorMessage = - "MemJS INCREMENT: " + errors[response.header.status]; + "MemJS INCREMENT: " + + errors[response!.header.status || UNKNOWN_ERROR]; logger.log(errorMessage); if (callback) { callback(new Error(errorMessage), null, null); @@ -897,12 +1020,36 @@ class Client { // The callback signature is: // // callback(err, success, value) - decrement(key, amount, options, callback) { + decrement( + key: string, + amount: number, + options: { initial?: number; expires?: number } + ): Promise<{ value: number | null; success: boolean | null }>; + decrement( + key: string, + amount: number, + options: { initial?: number; expires?: number }, + callback: ( + error: Error | null, + success: boolean | null, + value?: number | null + ) => void + ): void; + decrement( + key: string, + amount: number, + options: { initial?: number; expires?: number }, + callback?: ( + error: Error | null, + success: boolean | null, + value?: number | null + ) => void + ): Promise<{ value: number | null; success: boolean | null }> | void { if (callback === undefined && options !== "function") { var self = this; return promisify(function (callback) { self.decrement(key, amount, options, function (err, success, value) { - callback(err, { success: success, value: value }); + callback(err, { success: success, value: value || null }); }); }); } @@ -938,17 +1085,19 @@ class Client { } return; } - switch (response.header.status) { + switch (response!.header.status) { case constants.RESPONSE_STATUS_SUCCCESS: var bufInt = - (response.val.readUInt32BE(0) << 8) + response.val.readUInt32BE(4); + (response!.val.readUInt32BE(0) << 8) + + response!.val.readUInt32BE(4); if (callback) { callback(null, true, bufInt); } break; default: var errorMessage = - "MemJS DECREMENT: " + errors[response.header.status]; + "MemJS DECREMENT: " + + errors[response!.header.status || UNKNOWN_ERROR]; logger.log(errorMessage); if (callback) { callback(new Error(errorMessage), null, null); @@ -957,14 +1106,29 @@ class Client { }); } - // APPEND - // - // Append the given _value_ to the value associated with the given _key_ in - // memcache. The operation only succeeds if the key is already present. The - // callback signature is: - // - // callback(err, success) - append(key, value, callback) { + /** + * APPEND + * + * Append the given _value_ to the value associated with the given _key_ in + * memcache. The operation only succeeds if the key is already present. The + * callback signature is: + * + * callback(err, success) + * @param key + * @param value + * @param callback + */ + append(key: string, value: Value): Promise; + append( + key: string, + value: Value, + callback: (err: Error | null, success: boolean | null) => void + ): void; + append( + key: string, + value: Value, + callback?: (err: Error | null, success: boolean | null) => void + ) { if (callback === undefined) { var self = this; return promisify(function (callback) { @@ -976,7 +1140,7 @@ class Client { // TODO: support version (CAS) var logger = this.options.logger; this.incrSeq(); - var opcode = 0x0e; + var opcode: constants.OP = 0x0e; var serialized = this.serializer.serialize(opcode, value, ""); var request = makeRequestBuffer( opcode, @@ -992,7 +1156,7 @@ class Client { } return; } - switch (response.header.status) { + switch (response!.header.status) { case constants.RESPONSE_STATUS_SUCCCESS: if (callback) { callback(null, true); @@ -1004,7 +1168,8 @@ class Client { } break; default: - var errorMessage = "MemJS APPEND: " + errors[response.header.status]; + var errorMessage = + "MemJS APPEND: " + errors[response!.header.status || UNKNOWN_ERROR]; logger.log(errorMessage); if (callback) { callback(new Error(errorMessage), null); @@ -1013,14 +1178,29 @@ class Client { }); } - // PREPEND - // - // Prepend the given _value_ to the value associated with the given _key_ in - // memcache. The operation only succeeds if the key is already present. The - // callback signature is: - // - // callback(err, success) - prepend(key, value, callback) { + /** + * PREPEND + * + * Prepend the given _value_ to the value associated with the given _key_ in + * memcache. The operation only succeeds if the key is already present. The + * callback signature is: + * + * callback(err, success) + * @param key + * @param value + * @param callback + */ + prepend(key: string, value: Value): Promise; + prepend( + key: string, + value: Value, + callback: (err: Error | null, success: boolean | null) => void + ): void; + prepend( + key: string, + value: Value, + callback?: (err: Error | null, success: boolean | null) => void + ) { if (callback === undefined) { var self = this; return promisify(function (callback) { @@ -1033,7 +1213,7 @@ class Client { var logger = this.options.logger; this.incrSeq(); - var opcode = 0x0e; + var opcode: constants.OP = constants.OP_PREPEND; /* WAS WRONG IN ORIGINAL */ var serialized = this.serializer.serialize(opcode, value, ""); var request = makeRequestBuffer( opcode, @@ -1049,7 +1229,7 @@ class Client { } return; } - switch (response.header.status) { + switch (response!.header.status) { case constants.RESPONSE_STATUS_SUCCCESS: if (callback) { callback(null, true); @@ -1061,7 +1241,9 @@ class Client { } break; default: - var errorMessage = "MemJS PREPEND: " + errors[response.header.status]; + var errorMessage = + "MemJS PREPEND: " + + errors[response!.header.status || UNKNOWN_ERROR]; logger.log(errorMessage); if (callback) { callback(new Error(errorMessage), null); @@ -1070,19 +1252,34 @@ class Client { }); } - // TOUCH - // - // Touch sets an expiration value, given by _expires_, on the given _key_ in - // memcache. The operation only succeeds if the key is already present. The - // callback signature is: - // - // callback(err, success) - touch(key, expires, callback) { + /** + * TOUCH + * + * Touch sets an expiration value, given by _expires_, on the given _key_ in + * memcache. The operation only succeeds if the key is already present. The + * callback signature is: + * + * callback(err, success) + * @param key + * @param expires + * @param callback + */ + touch(key: string, expires: number): Promise; + touch( + key: string, + expires: number, + callback: (err: Error | null, success: boolean | null) => void + ): void; + touch( + key: string, + expires: number, + callback?: (err: Error | null, success: boolean | null) => void + ): Promise | void { if (callback === undefined) { var self = this; return promisify(function (callback) { self.touch(key, expires, function (err, success) { - callback(err, success); + callback(err, Boolean(success)); }); }); } @@ -1098,7 +1295,7 @@ class Client { } return; } - switch (response.header.status) { + switch (response!.header.status) { case constants.RESPONSE_STATUS_SUCCCESS: if (callback) { callback(null, true); @@ -1110,7 +1307,8 @@ class Client { } break; default: - var errorMessage = "MemJS TOUCH: " + errors[response.header.status]; + var errorMessage = + "MemJS TOUCH: " + errors[response!.header.status || UNKNOWN_ERROR]; logger.log(errorMessage); if (callback) { callback(new Error(errorMessage), null); @@ -1119,16 +1317,31 @@ class Client { }); } - // FLUSH - // - // Flushes the cache on each connected server. The callback signature is: - // - // callback(lastErr, results) - // - // where _lastErr_ is the last error encountered (or null, in the common case - // of no errors). _results_ is a dictionary mapping `"hostname:port"` to either - // `true` (if the operation was successful), or an error. - flush(callback) { + /** + * FLUSH + * + * Flushes the cache on each connected server. The callback signature is: + * + * callback(lastErr, results) + * + * where _lastErr_ is the last error encountered (or null, in the common case + * of no errors). _results_ is a dictionary mapping `"hostname:port"` to either + * `true` (if the operation was successful), or an error. + * @param callback + */ + flush(): Promise>; + flush( + callback: ( + err: Error | null, + results: Record + ) => void + ): void; + flush( + callback?: ( + err: Error | null, + results: Record + ) => void + ) { if (callback === undefined) { var self = this; return promisify(function (callback) { @@ -1141,11 +1354,11 @@ class Client { this.incrSeq(); var request = makeRequestBuffer(0x08, "", "", "", this.seq); var count = this.servers.length; - var result = {}; - var lastErr = null; + var result: Record = {}; + var lastErr: Error | null = null; var i; - var handleFlush = function (seq, serv) { + var handleFlush = function (seq: number, serv: Server) { serv.onResponse(seq, function (/* response */) { count -= 1; result[serv.hostportString()] = true; @@ -1169,24 +1382,35 @@ class Client { } } - // STATS_WITH_KEY - // - // Sends a memcache stats command with a key to each connected server. The - // callback is invoked **ONCE PER SERVER** and has the signature: - // - // callback(err, server, stats) - // - // _server_ is the `"hostname:port"` of the server, and _stats_ is a dictionary - // mapping the stat name to the value of the statistic as a string. - statsWithKey(key, callback) { + /** + * STATS_WITH_KEY + * + * Sends a memcache stats command with a key to each connected server. The + * callback is invoked **ONCE PER SERVER** and has the signature: + * + * callback(err, server, stats) + * + * _server_ is the `"hostname:port"` of the server, and _stats_ is a dictionary + * mapping the stat name to the value of the statistic as a string. + * @param key + * @param callback + */ + statsWithKey( + key: string, + callback?: ( + err: Error | null, + server: string, + stats: Record | null + ) => void + ): void { var logger = this.options.logger; this.incrSeq(); var request = makeRequestBuffer(0x10, key, "", "", this.seq); var i; - var handleStats = function (seq, serv) { - var result = {}; - var handle = function (response) { + var handleStats = function (seq: number, serv: Server) { + var result: Record = {}; + var handle: OnResponseCallback = function (response) { // end of stat responses if (response.header.totalBodyLength === 0) { if (callback) { @@ -1201,7 +1425,10 @@ class Client { break; default: var errorMessage = - "MemJS STATS (" + key + "): " + errors[response.header.status]; + "MemJS STATS (" + + key + + "): " + + errors[response.header.status || UNKNOWN_ERROR]; logger.log(errorMessage, false); if (callback) { callback(new Error(errorMessage), serv.hostportString(), null); @@ -1224,40 +1451,60 @@ class Client { } } - // STATS - // - // Fetches memcache stats from each connected server. The callback is invoked - // **ONCE PER SERVER** and has the signature: - // - // callback(err, server, stats) - // - // _server_ is the `"hostname:port"` of the server, and _stats_ is a - // dictionary mapping the stat name to the value of the statistic as a string. - stats(callback) { + /** + * STATS + * + * Fetches memcache stats from each connected server. The callback is invoked + * **ONCE PER SERVER** and has the signature: + * + * callback(err, server, stats) + * + * _server_ is the `"hostname:port"` of the server, and _stats_ is a + * dictionary mapping the stat name to the value of the statistic as a string. + * @param callback + */ + stats( + callback?: ( + err: Error | null, + server: string, + stats: Record | null + ) => void + ): void { this.statsWithKey("", callback); } - // RESET_STATS - // - // Reset the statistics each server is keeping back to zero. This doesn't clear - // stats such as item count, but temporary stats such as total number of - // connections over time. - // - // The callback is invoked **ONCE PER SERVER** and has the signature: - // - // callback(err, server) - // - // _server_ is the `"hostname:port"` of the server. - resetStats(callback) { + /** + * RESET_STATS + * + * Reset the statistics each server is keeping back to zero. This doesn't clear + * stats such as item count, but temporary stats such as total number of + * connections over time. + * + * The callback is invoked **ONCE PER SERVER** and has the signature: + * + * callback(err, server) + * + * _server_ is the `"hostname:port"` of the server. + * @param callback + */ + resetStats( + callback?: ( + err: Error | null, + server: string, + stats: Record | null + ) => void + ): void { this.statsWithKey("reset", callback); } - // QUIT - // - // Closes the connection to each server, notifying them of this intention. Note - // that quit can race against already outstanding requests when those requests - // fail and are retried, leading to the quit command winning and closing the - // connection before the retries complete. + /** + * QUIT + * + * Closes the connection to each server, notifying them of this intention. Note + * that quit can race against already outstanding requests when those requests + * fail and are retried, leading to the quit command winning and closing the + * connection before the retries complete. + */ quit() { this.incrSeq(); // TODO: Nicer perhaps to do QUITQ (0x17) but need a new callback for when @@ -1266,7 +1513,7 @@ class Client { var serv; var i; - var handleQuit = function (seq, serv) { + var handleQuit = function (seq: number, serv: Server) { serv.onResponse(seq, function (/* response */) { serv.close(); }); @@ -1282,7 +1529,25 @@ class Client { } } - _version(server, callback) { + _version( + server: Server + ): Promise<{ value: Value | null; flags: Extras | null }>; + _version( + server: Server, + callback: ( + error: Error | null, + value: Value | null, + flags: Extras | null + ) => void + ): void; + _version( + server: Server, + callback?: ( + error: Error | null, + value: Value | null, + extras: Extras | null + ) => void + ): Promise<{ value: Value | null; flags: Extras | null }> | void { var self = this; if (callback === undefined) { return promisify(function (callback) { @@ -1304,17 +1569,21 @@ class Client { return; } - switch (response.header.status) { + switch (response!.header.status) { case constants.RESPONSE_STATUS_SUCCCESS: + /* TODO: this is bugged, we should't use the deserializer here, since version always returns a version string. + The deserializer should only be used on user key data. */ var deserialized = self.serializer.deserialize( - response.header.opcode, - response.val, - response.extras + response!.header.opcode, + response!.val, + response!.extras ); callback(null, deserialized.value, deserialized.extras); break; default: - var errorMessage = "MemJS VERSION: " + errors[response.header.status]; + var errorMessage = + "MemJS VERSION: " + + errors[(response!.header.status, UNKNOWN_ERROR)]; logger.log(errorMessage); if (callback) { callback(new Error(errorMessage), null, null); @@ -1323,19 +1592,67 @@ class Client { }); } - // VERSION - // - // Request the server version from the "first" server in the backend pool - // - // The server responds with a packet containing the version string in the body with the following format: "x.y.z" - - version(callback) { + /** + * VERSION + * + * Request the server version from the "first" server in the backend pool. + * + * The server responds with a packet containing the version string in the body with the following format: "x.y.z" + */ + version(): Promise<{ value: Value | null; flags: Extras | null }>; + version( + callback: ( + error: Error | null, + value: Value | null, + flags: Extras | null + ) => void + ): void; + version( + callback?: ( + error: Error | null, + value: Value | null, + extras: Extras | null + ) => void + ) { const server = this.serverKeyToServer(this.serverKeys[0]); - - return this._version(server, callback); + if (callback) { + this._version(server, callback); + } else { + return this._version(server); + } } - versionAll(callback) { + /** + * VERSION-ALL + * + * Retrieves the server version from all the servers + * in the backend pool, errors if any one of them has an + * error + * + * The callback signature is: + * + * callback(err, value, flags) + * + * @param keys + * @param callback + */ + versionAll(): Promise<{ + values: Record; + }>; + versionAll( + callback: ( + err: Error | null, + values: Record | null + ) => void + ): void; + versionAll( + callback?: ( + err: Error | null, + values: Record | null + ) => void + ): Promise<{ + values: Record; + }> | void { const promise = Promise.all( this.serverKeys.map((serverKey) => { const server = this.serverKeyToServer(serverKey); @@ -1348,14 +1665,14 @@ class Client { const values = versionObjects.reduce((accumulator, versionObject) => { accumulator[versionObject.serverKey] = versionObject.value; return accumulator; - }, {}); + }, {} as Record); return { values: values }; }); if (callback === undefined) { return promise; } - return promise + promise .then((response) => { callback(null, response.values); }) @@ -1364,9 +1681,11 @@ class Client { }); } - // CLOSE - // - // Closes (abruptly) connections to all the servers. + /** + * CLOSE + * + * Closes (abruptly) connections to all the servers. + */ close() { var i; for (i = 0; i < this.servers.length; i++) { @@ -1375,15 +1694,15 @@ class Client { } /** - * Perform a generic single response operation (get, set etc) on one server - * - * @param {string} key the key to hash to get a server from the pool - * @param {buffer} request a buffer containing the request - * @param {number} seq the sequence number of the operation. It is used to pin the callbacks - to a specific operation and should never change during a `perform`. - * @param {*} callback a callback invoked when a response is received or the request fails - * @param {*} retries number of times to retry request on failure - */ + * Perform a generic single response operation (get, set etc) on one server + * + * @param {string} key the key to hash to get a server from the pool + * @param {buffer} request a buffer containing the request + * @param {number} seq the sequence number of the operation. It is used to pin the callbacks + to a specific operation and should never change during a `perform`. + * @param {*} callback a callback invoked when a response is received or the request fails + * @param {*} retries number of times to retry request on failure + */ perform( key: string, request: Buffer, @@ -1407,9 +1726,9 @@ class Client { performOnServer( server: Server, request: Buffer, - seq: Number, + seq: number, callback: ResponseOrErrorCallback, - retries?: number + retries: number = 0 ) { var _this = this; @@ -1418,13 +1737,13 @@ class Client { var logger = this.options.logger; var retry_delay = this.options.retry_delay; - var responseHandler = function (response) { + var responseHandler: OnResponseCallback = function (response) { if (callback) { callback(null, response); } }; - var errorHandler = function (error) { + var errorHandler: OnErrorCallback = function (error) { if (--retries > 0) { // Wait for retry_delay setTimeout(function () { diff --git a/src/memjs/noop-serializer.ts b/src/memjs/noop-serializer.ts index b43b873..2d91330 100644 --- a/src/memjs/noop-serializer.ts +++ b/src/memjs/noop-serializer.ts @@ -10,7 +10,7 @@ export interface Serializer { serialize( opcode: OP, value: Value, - extras: Extras + extras: MaybeBuffer ): SerializerResult; deserialize( opcode: OP, From f056af408fbd9ea3c7520133fbede11446b20a01 Mon Sep 17 00:00:00 2001 From: Jake Teton-Landis Date: Fri, 9 Apr 2021 18:44:18 -0700 Subject: [PATCH 22/79] memjs.ts --- src/memjs/memjs.d.ts | 572 ------------------------------------------- src/memjs/memjs.ts | 108 ++++---- 2 files changed, 51 insertions(+), 629 deletions(-) delete mode 100644 src/memjs/memjs.d.ts diff --git a/src/memjs/memjs.d.ts b/src/memjs/memjs.d.ts deleted file mode 100644 index f907eac..0000000 --- a/src/memjs/memjs.d.ts +++ /dev/null @@ -1,572 +0,0 @@ -// Type definitions for memjs 1.2 -// Project: http://github.com/memcachier/memjs -// Definitions by: Zongmin Lei -// BendingBender -// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped -// TypeScript Version: 2.1 - -/// - -export interface ClientOptions { - /** - * The number of times to retry an operation in lieu of failures. - * @default 2 - */ - retries?: number; - /** - * @default 0.2 - */ - retry_delay?: number; - /** - * The default expiration in seconds to use. A `0` means never expire, - * if it is greater than 30 days (60 x 60 x 24 x 30), it is - * treated as a UNIX time (number of seconds since January 1, 1970). - * @default 0 - */ - expires?: number; - /** - * A logger object that responds to `log(string)` method calls. - * @default console - */ - logger?: { - log(...args: any[]): void; - }; - /** - * A function to map keys to servers. - * NOTE: if you need to do some expensive initialization, *please* do it lazily - * the first time you this function is called with an array of serverKeys, not on - * every call. - */ - keyToServerHashFunction?: (serverKeys: string[], key: string) => string; -} -export interface ServerOptions { - /** - * Server username for fallback SASL authentication credentials. - */ - username?: string; - /** - * Server password for fallback SASL authentication credentials. - */ - password?: string; - /** - * `timeout` in seconds to determine failure for operations. - * @default 0.5 - */ - timeout?: number; - /** - * `conntimeout` in seconds to connection failure. - * @default 2 * timeout - */ - conntimeout?: number; - /** - * Whether to enable keep-alive functionality. - * @default false - */ - keepAlive?: boolean; - /** - * `keepAliveDelay` in seconds to the initial delay before the first keep- - * alive probe is sent on an idle socket. - * @default 30 - */ - keepAliveDelay?: number; -} -export class Client { - /** - * Creates a new client given an optional config string and optional hash of - * options. The config string should be of the form: - * - * "[user:pass@]server1[:11211],[user:pass@]server2[:11211],..." - * - * If the argument is not given, fallback on the `MEMCACHIER_SERVERS` environment - * variable, `MEMCACHE_SERVERS` environment variable or `"localhost:11211"`. - * - * The options hash may contain the options: - * - * * `retries` - the number of times to retry an operation in lieu of failures - * (default 2) - * * `expires` - the default expiration in seconds to use (default 0 - never - * expire). If `expires` is greater than 30 days (60 x 60 x 24 x 30), it is - * treated as a UNIX time (number of seconds since January 1, 1970). - * * `logger` - a logger object that responds to `log(string)` method calls. - * * `failover` - whether to failover to next server. Defaults to false. - * * `failoverTime` - how much to wait until retring a failed server. Default - * is 60 seconds. - * - * ~~~~ - * log(msg1[, msg2[, msg3[...]]]) - * ~~~~ - * - * Defaults to `console`. - * - * Or options for the servers including: - * * `username` and `password` for fallback SASL authentication credentials. - * * `timeout` in seconds to determine failure for operations. Default is 0.5 - * seconds. - * * 'conntimeout' in seconds to connection failure. Default is twice the value - * of `timeout`. - * * `keepAlive` whether to enable keep-alive functionality. Defaults to false. - * * `keepAliveDelay` in seconds to the initial delay before the first keepalive - * probe is sent on an idle socket. Defaults is 30 seconds. - */ - static create( - serversStr?: string, - options?: ClientOptions | ServerOptions - ): Client; - - servers: string[]; - - /** - * Client initializer takes a list of Servers and an options dictionary. See Client.create for details. - * @param servers - * @param options - */ - constructor(servers: string, options?: ClientOptions); - - /** - * Chooses the server to talk to by hashing the given key. - * @param key - */ - server(key: string): string; - - /** - * GET - * - * Retrieves the value at the given key in memcache. - * - * The callback signature is: - * - * callback(err, value, flags) - * - * _value_ and _flags_ are both `Buffer`s. If the key is not found, the - * callback is invoked with null for both arguments and no error - * @param key - * @param callback - */ - get(key: string): Promise<{ value: Buffer; flags: Buffer }>; - get( - key: string, - callback: ( - err: Error | null, - value: Buffer | null, - flags: Buffer | null - ) => void - ): void; - - /** - * MULTI-GET / GET-MULTI - * - * Retrieves the value at the given keys in memcache. - * - * The callback signature is: - * - * callback(err, value, flags) - * - * @param keys - * @param callback - */ - getMulti( - keys: Keys[] - ): Promise<{ values: { [K in Keys]?: Buffer | null }; flags: Buffer | null }>; - getMulti( - keys: Keys[], - callback: ( - err: Error | null, - values: { [K in Keys]: Buffer | null } | null, - flags: Buffer | null - ) => void - ): void; - - /** - * SET - * - * Sets the given _key_ and _value_ in memcache. - * - * The options dictionary takes: - * * _expires_: overrides the default expiration (see `Client.create`) for this - * particular key-value pair. - * - * The callback signature is: - * - * callback(err, success) - * @param key - * @param value - * @param options - * @param callback - */ - set( - key: string, - value: string | Buffer, - options: { expires?: number } - ): Promise; - set( - key: string, - value: string | Buffer, - options: { expires?: number }, - callback: (err: Error | null, success: boolean | null) => void - ): void; - - /** - * ADD - * - * Adds the given _key_ and _value_ to memcache. The operation only succeeds - * if the key is not already set. - * - * The options dictionary takes: - * * _expires_: overrides the default expiration (see `Client.create`) for this - * particular key-value pair. - * - * The callback signature is: - * - * callback(err, success) - * @param key - * @param value - * @param options - * @param callback - */ - add( - key: string, - value: string | Buffer, - options: { expires?: number } - ): Promise; - add( - key: string, - value: string | Buffer, - options: { expires?: number }, - callback: (err: Error | null, success: boolean | null) => void - ): void; - - /** - * REPLACE - * - * Replaces the given _key_ and _value_ to memcache. The operation only succeeds - * if the key is already present. - * - * The options dictionary takes: - * * _expires_: overrides the default expiration (see `Client.create`) for this - * particular key-value pair. - * - * The callback signature is: - * - * callback(err, success) - * @param key - * @param value - * @param options - * @param callback - */ - replace( - key: string, - value: string | Buffer, - options: { expires?: number } - ): Promise; - replace( - key: string, - value: string | Buffer, - options: { expires?: number }, - callback: (err: Error | null, success: boolean | null) => void - ): void; - - /** - * DELETE - * - * Deletes the given _key_ from memcache. The operation only succeeds - * if the key is already present. - * - * The callback signature is: - * - * callback(err, success) - * @param key - * @param callback - */ - delete(key: string): Promise; - delete( - key: string, - callback: (err: Error | null, success: boolean | null) => void - ): void; - - /** - * INCREMENT - * - * Increments the given _key_ in memcache. - * - * The options dictionary takes: - * * _initial_: the value for the key if not already present, defaults to 0. - * * _expires_: overrides the default expiration (see `Client.create`) for this - * particular key-value pair. - * - * The callback signature is: - * - * callback(err, success, value) - * @param key - * @param amount - * @param options - * @param callback - */ - increment( - key: string, - amount: number, - options: { initial?: number; expires?: number } - ): Promise<{ success: boolean; value?: number | null }>; - increment( - key: string, - amount: number, - options: { initial?: number; expires?: number }, - callback: ( - err: Error | null, - success: boolean | null, - value?: number | null - ) => void - ): void; - - /** - * DECREMENT - * - * Decrements the given _key_ in memcache. - * - * The options dictionary takes: - * * _initial_: the value for the key if not already present, defaults to 0. - * * _expires_: overrides the default expiration (see `Client.create`) for this - * particular key-value pair. - * - * The callback signature is: - * - * callback(err, success, value) - * @param key - * @param amount - * @param options - * @param callback - */ - decrement( - key: string, - amount: number, - options: { initial?: number; expires?: number } - ): Promise<{ success: boolean; value?: number | null }>; - decrement( - key: string, - amount: number, - options: { initial?: number; expires?: number }, - callback: ( - err: Error | null, - success: boolean | null, - value?: number | null - ) => void - ): void; - - /** - * APPEND - * - * Append the given _value_ to the value associated with the given _key_ in - * memcache. The operation only succeeds if the key is already present. The - * callback signature is: - * - * callback(err, success) - * @param key - * @param value - * @param callback - */ - append(key: string, value: string | Buffer): Promise; - append( - key: string, - value: string | Buffer, - callback: (err: Error | null, success: boolean | null) => void - ): void; - - /** - * PREPEND - * - * Prepend the given _value_ to the value associated with the given _key_ in - * memcache. The operation only succeeds if the key is already present. The - * callback signature is: - * - * callback(err, success) - * @param key - * @param value - * @param callback - */ - prepend(key: string, value: string | Buffer): Promise; - prepend( - key: string, - value: string | Buffer, - callback: (err: Error | null, success: boolean | null) => void - ): void; - - /** - * TOUCH - * - * Touch sets an expiration value, given by _expires_, on the given _key_ in - * memcache. The operation only succeeds if the key is already present. The - * callback signature is: - * - * callback(err, success) - * @param key - * @param expires - * @param callback - */ - touch(key: string, expires: number): Promise; - touch( - key: string, - expires: number, - callback: (err: Error | null, success: boolean | null) => void - ): void; - - /** - * FLUSH - * - * Flushes the cache on each connected server. The callback signature is: - * - * callback(lastErr, results) - * - * where _lastErr_ is the last error encountered (or null, in the common case - * of no errors). _results_ is a dictionary mapping `"hostname:port"` to either - * `true` (if the operation was successful), or an error. - * @param callback - */ - flush(): Promise>; - flush( - callback: (err: Error | null, results: Record) => void - ): void; - - /** - * STATS_WITH_KEY - * - * Sends a memcache stats command with a key to each connected server. The - * callback is invoked **ONCE PER SERVER** and has the signature: - * - * callback(err, server, stats) - * - * _server_ is the `"hostname:port"` of the server, and _stats_ is a dictionary - * mapping the stat name to the value of the statistic as a string. - * @param key - * @param callback - */ - statsWithKey( - key: string, - callback?: ( - err: Error | null, - server: string, - stats: Record | null - ) => void - ): void; - - /** - * STATS - * - * Fetches memcache stats from each connected server. The callback is invoked - * **ONCE PER SERVER** and has the signature: - * - * callback(err, server, stats) - * - * _server_ is the `"hostname:port"` of the server, and _stats_ is a - * dictionary mapping the stat name to the value of the statistic as a string. - * @param callback - */ - stats( - callback?: ( - err: Error | null, - server: string, - stats: Record | null - ) => void - ): void; - - /** - * RESET_STATS - * - * Reset the statistics each server is keeping back to zero. This doesn't clear - * stats such as item count, but temporary stats such as total number of - * connections over time. - * - * The callback is invoked **ONCE PER SERVER** and has the signature: - * - * callback(err, server) - * - * _server_ is the `"hostname:port"` of the server. - * @param callback - */ - resetStats( - callback?: ( - err: Error | null, - server: string, - stats: Record | null - ) => void - ): void; - - /** - * QUIT - * - * Closes the connection to each server, notifying them of this intention. Note - * that quit can race against already outstanding requests when those requests - * fail and are retried, leading to the quit command winning and closing the - * connection before the retries complete. - */ - quit(): void; - - /** - * CLOSE - * - * Closes (abruptly) connections to all the servers. - */ - close(): void; - - /** - * Perform a generic single response operation (get, set etc) on a server - * serv: the server to perform the operation on - * request: a buffer containing the request - * seq: the sequence number of the operation. It is used to pin the callbacks - * to a specific operation and should never change during a `perform`. - * callback: a callback invoked when a response is received or the request - * fails - * retries: number of times to retry request on failure - * @param key - * @param request - * @param seq - * @param callback - * @param retries - */ - perform( - key: string, - request: Buffer, - seq: number, - callback?: (err: Error | null, ...args: any[]) => void, - retries?: number - ): void; - - /** - * VERSION - * - * Retrieves the server version from the "first" server in the backend pool - * - * The callback signature is: - * - * callback(err, value, flags) - * - * @param keys - * @param callback - */ - version(): Promise<{ value: string; flags: Buffer | null }>; - version(callback: ( - err: Error | null, - value: { [K in Keys]: Buffer | null } | null, - flags: Buffer | null - ) => void): void - - - /** - * VERSION-ALL - * - * Retrieves the server version from all the servers - * in the backend pool, errors if any one of them has an - * error - * - * The callback signature is: - * - * callback(err, value, flags) - * - * @param keys - * @param callback - */ - versionAll(): Promise<{ values: Record; flags: Buffer | null }>; - versionAll(callback: ( - err: Error | null, - values: Record, - flags: Buffer | null - ) => void): void -} diff --git a/src/memjs/memjs.ts b/src/memjs/memjs.ts index 642c441..7b3a49e 100644 --- a/src/memjs/memjs.ts +++ b/src/memjs/memjs.ts @@ -23,7 +23,6 @@ import { Message, } from "./utils"; import * as constants from "./constants"; -import { assert } from "node:console"; function defaultKeyToServerHashFunction(servers: string[], key: string) { var total = servers.length; @@ -42,18 +41,11 @@ function promisify( }); } -type CallbackArgs> = [Error, ...Partial] | [null, ...T]; - type ResponseOrErrorCallback = ( error: Error | null, response: Message | null ) => void; -// interface ResponseOrErrorCallback { -// (error: Error, response: null): void; -// (error: null, response: Message): void; -// } - interface BaseClientOptions { retries: number; retry_delay: number; @@ -114,55 +106,57 @@ class Client { this.serverKeys = Object.keys(this.serverMap); } - // Creates a new client given an optional config string and optional hash of - // options. The config string should be of the form: - // - // "[user:pass@]server1[:11211],[user:pass@]server2[:11211],..." - // - // If the argument is not given, fallback on the `MEMCACHIER_SERVERS` environment - // variable, `MEMCACHE_SERVERS` environment variable or `"localhost:11211"`. - // - // The options hash may contain the options: - // - // * `retries` - the number of times to retry an operation in lieu of failures - // (default 2) - // * `expires` - the default expiration in seconds to use (default 0 - never - // expire). If `expires` is greater than 30 days (60 x 60 x 24 x 30), it is - // treated as a UNIX time (number of seconds since January 1, 1970). - // * `logger` - a logger object that responds to `log(string)` method calls. - // - // ~~~~ - // log(msg1[, msg2[, msg3[...]]]) - // ~~~~ - // - // Defaults to `console`. - // * `serializer` - the object which will (de)serialize the data. It needs - // two public methods: serialize and deserialize. It defaults to the - // noopSerializer: - // - // ~~~~ - // var noopSerializer = { - // serialize: function (opcode, value, extras) { - // return { value: value, extras: extras }; - // }, - // deserialize: function (opcode, value, extras) { - // return { value: value, extras: extras }; - // } - // }; - // ~~~~ - // - // Or options for the servers including: - // * `username` and `password` for fallback SASL authentication credentials. - // * `timeout` in seconds to determine failure for operations. Default is 0.5 - // seconds. - // * 'conntimeout' in seconds to connection failure. Default is twice the value - // of `timeout`. - // * `keepAlive` whether to enable keep-alive functionality. Defaults to false. - // * `keepAliveDelay` in seconds to the initial delay before the first keepalive - // probe is sent on an idle socket. Defaults is 30 seconds. - // * `keyToServerHashFunction` a function to map keys to servers, with the signature - // (serverKeys: string[], key: string): string - // NOTE: if you need to do some expensive initialization, *please* do it lazily the first time you this function is called with an array of serverKeys, not on every call + /** + * Creates a new client given an optional config string and optional hash of + * options. The config string should be of the form: + * + * "[user:pass@]server1[:11211],[user:pass@]server2[:11211],..." + * + * If the argument is not given, fallback on the `MEMCACHIER_SERVERS` environment + * variable, `MEMCACHE_SERVERS` environment variable or `"localhost:11211"`. + * + * The options hash may contain the options: + * + * * `retries` - the number of times to retry an operation in lieu of failures + * (default 2) + * * `expires` - the default expiration in seconds to use (default 0 - never + * expire). If `expires` is greater than 30 days (60 x 60 x 24 x 30), it is + * treated as a UNIX time (number of seconds since January 1, 1970). + * * `logger` - a logger object that responds to `log(string)` method calls. + * + * ~~~~ + * log(msg1[, msg2[, msg3[...]]]) + * ~~~~ + * + * Defaults to `console`. + * * `serializer` - the object which will (de)serialize the data. It needs + * two public methods: serialize and deserialize. It defaults to the + * noopSerializer: + * + * ~~~~ + * var noopSerializer = { + * serialize: function (opcode, value, extras) { + * return { value: value, extras: extras }; + * }, + * deserialize: function (opcode, value, extras) { + * return { value: value, extras: extras }; + * } + * }; + * ~~~~ + * + * Or options for the servers including: + * * `username` and `password` for fallback SASL authentication credentials. + * * `timeout` in seconds to determine failure for operations. Default is 0.5 + * seconds. + * * 'conntimeout' in seconds to connection failure. Default is twice the value + * of `timeout`. + * * `keepAlive` whether to enable keep-alive functionality. Defaults to false. + * * `keepAliveDelay` in seconds to the initial delay before the first keepalive + * probe is sent on an idle socket. Defaults is 30 seconds. + * * `keyToServerHashFunction` a function to map keys to servers, with the signature + * (serverKeys: string[], key: string): string + * NOTE: if you need to do some expensive initialization, *please* do it lazily the first time you this function is called with an array of serverKeys, not on every call + */ static create( serversStr: string | undefined, options: IfBuffer< From e15050a23afa83eda4a3c69b6bfd5af7b74f1d48 Mon Sep 17 00:00:00 2001 From: Jake Teton-Landis Date: Fri, 9 Apr 2021 18:51:49 -0700 Subject: [PATCH 23/79] fix exports --- src/memjs/memjs.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/memjs/memjs.ts b/src/memjs/memjs.ts index 7b3a49e..15d1f1b 100644 --- a/src/memjs/memjs.ts +++ b/src/memjs/memjs.ts @@ -23,6 +23,8 @@ import { Message, } from "./utils"; import * as constants from "./constants"; +import * as Utils from "./utils"; +import * as Header from "./header"; function defaultKeyToServerHashFunction(servers: string[], key: string) { var total = servers.length; @@ -1772,7 +1774,4 @@ class Client { } } -exports.Client = Client; -exports.Server = Server; -exports.Utils = require("./utils"); -exports.Header = require("./header"); +export { Client, Server, Utils, Header }; From b6a66fa0f1c72e63eedc9864edc3136f34e0cbb5 Mon Sep 17 00:00:00 2001 From: Jake Teton-Landis Date: Fri, 9 Apr 2021 18:55:50 -0700 Subject: [PATCH 24/79] revert changes to tests --- package.json | 2 +- src/index.ts | 1 + src/test/client_test.ts => test/client_test.js | 0 src/test/header_test.ts => test/header_test.js | 0 src/test/server_test.ts => test/server_test.js | 0 src/test/utils_test.ts => test/utils_test.js | 0 6 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 src/index.ts rename src/test/client_test.ts => test/client_test.js (100%) rename src/test/header_test.ts => test/header_test.js (100%) rename src/test/server_test.ts => test/server_test.js (100%) rename src/test/utils_test.ts => test/utils_test.js (100%) diff --git a/package.json b/package.json index 70759f4..7cd324c 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "lib": "./lib/memjs" }, "scripts": { - "test": "eslint ./src && tsc && tap --no-coverage -R spec ./lib/test/*.js", + "test": "tsc && tap --no-coverage -R spec ./test/*.js", "bench": "tsc && NODE_PATH=lib/memjs/ node bench/memjs.js", "bench-timers": "tsc && NODE_PATH=lib/memjs/ node bench/timers.js" }, diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..18dd75d --- /dev/null +++ b/src/index.ts @@ -0,0 +1 @@ +export * from "./memjs/memjs"; diff --git a/src/test/client_test.ts b/test/client_test.js similarity index 100% rename from src/test/client_test.ts rename to test/client_test.js diff --git a/src/test/header_test.ts b/test/header_test.js similarity index 100% rename from src/test/header_test.ts rename to test/header_test.js diff --git a/src/test/server_test.ts b/test/server_test.js similarity index 100% rename from src/test/server_test.ts rename to test/server_test.js diff --git a/src/test/utils_test.ts b/test/utils_test.js similarity index 100% rename from src/test/utils_test.ts rename to test/utils_test.js From a38b281a9783ac1b8b603652ab78a5c0e777b9b0 Mon Sep 17 00:00:00 2001 From: Jake Teton-Landis Date: Fri, 9 Apr 2021 19:01:44 -0700 Subject: [PATCH 25/79] fix tests --- src/memjs/memjs.ts | 4 ++-- src/memjs/server.ts | 12 ++++++++---- test/server_test.js | 2 +- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/memjs/memjs.ts b/src/memjs/memjs.ts index 15d1f1b..0e44274 100644 --- a/src/memjs/memjs.ts +++ b/src/memjs/memjs.ts @@ -77,7 +77,7 @@ type GivenClientOptions = Partial & class Client { servers: Server[]; seq: number; - options: BaseClientOptions; + options: BaseClientOptions & Partial>; serializer: Serializer; serverMap: { [hostport: string]: Server }; serverKeys: string[]; @@ -95,7 +95,7 @@ class Client { keyToServerHashFunction: defaultKeyToServerHashFunction, }); - this.serializer = options.serializer || (noopSerializer as any); + this.serializer = this.options.serializer || (noopSerializer as any); // Store a mapping from hostport -> server so we can quickly get a server object from the serverKey returned by the hashing function var serverMap: { [hostport: string]: Server } = {}; diff --git a/src/memjs/server.ts b/src/memjs/server.ts index a7a7928..f47b948 100644 --- a/src/memjs/server.ts +++ b/src/memjs/server.ts @@ -35,7 +35,7 @@ export interface OnErrorCallback { export class Server extends events.EventEmitter { responseBuffer: Buffer; host: string; - port: number; + port: string | number | undefined; connected: boolean; timeoutSet: boolean; connectCallbacks: OnConnectCallback[]; @@ -50,7 +50,8 @@ export class Server extends events.EventEmitter { constructor( host: string, - port: string | number, + /* TODO: allowing port to be string or undefined is used by the tests, but seems bad overall. */ + port?: string | number, username?: string, password?: string, options?: Partial @@ -58,7 +59,7 @@ export class Server extends events.EventEmitter { super(); this.responseBuffer = Buffer.from([]); this.host = host; - this.port = parseInt(port.toString(), 10); + this.port = port; this.connected = false; this.timeoutSet = false; this.connectCallbacks = []; @@ -174,7 +175,10 @@ export class Server extends events.EventEmitter { // CASE 1: completely new socket self.connected = false; self._socket = net.connect( - this.port, + /* TODO: allowing port to be string or undefined is used by the tests, but seems bad overall. */ + typeof this.port === "string" + ? parseInt(this.port, 10) + : this.port || 11211, this.host, function (this: net.Socket) { // SASL authentication handler diff --git a/test/server_test.js b/test/server_test.js index e251df9..f8d7eca 100644 --- a/test/server_test.js +++ b/test/server_test.js @@ -20,7 +20,7 @@ test('ResponseHandler with authentication error', function(t) { var server = new MemJS.Server('localhost', 11211); server.onError('test', function(err) { - t.equal('Memcached server authentication failed!', err); + t.equal('Memcached server authentication failed!', err.message); }); // Simulate a memcached server response, with an authentication error From 889ee89f4cb8c85d43020faf7386136dfc9fa84b Mon Sep 17 00:00:00 2001 From: David Blackman Date: Sun, 11 Apr 2021 12:11:42 -0400 Subject: [PATCH 26/79] WIP TSify more --- README.md | 4 +- bench/memjs.js | 36 +- bench/timers.js | 10 +- package-lock.json | 11 +- package.json | 3 +- src/memjs/header.ts | 2 +- src/memjs/memjs.ts | 423 +++++-------- src/memjs/server.ts | 30 +- src/memjs/utils.ts | 49 +- test/client_test.js | 1234 ------------------------------------- test/client_test.ts | 1438 +++++++++++++++++++++++++++++++++++++++++++ test/header_test.js | 16 +- test/server_test.js | 28 +- test/utils_test.js | 18 +- 14 files changed, 1699 insertions(+), 1603 deletions(-) delete mode 100644 test/client_test.js create mode 100644 test/client_test.ts diff --git a/README.md b/README.md index d5dd2e2..fe73bd9 100644 --- a/README.md +++ b/README.md @@ -65,8 +65,8 @@ Environment variables are only used as a fallback for explicit parameters. You can start using MemJS immediately from the node console: - $ var memjs = require('memjs') - $ var client = memjs.Client.create() + $ const memjs = require('memjs') + $ const client = memjs.Client.create() $ client.get('hello', function(err, val) { console.log(val); }) If callbacks are not specified, the command calls return promises. diff --git a/bench/memjs.js b/bench/memjs.js index d94aa62..4dbc3e1 100644 --- a/bench/memjs.js +++ b/bench/memjs.js @@ -1,11 +1,11 @@ -var memjs = require('memjs'); -var header = require('header'); -var b = require('benchmark'); +const memjs = require('memjs'); +const header = require('header'); +const b = require('benchmark'); function makeString(n) { - var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; - var text = ''; - var i; + const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + const text = ''; + const i; for(i=0; i < n; i++ ) { text += possible.charAt(Math.floor(Math.random() * possible.length)); @@ -14,11 +14,11 @@ function makeString(n) { return text; } -var x = (function() { - var suite = new b.Suite(); +const x = (function() { + const suite = new b.Suite(); - var headerBuf = Buffer.from([0x81, 1, 7, 0, 4, 0, 0, 1, 0, 0, 0, 9, 0, 0, 0, 0, 0x0a, 0, 0, 0, 0, 0, 0, 0]); - var parsedHeader = header.fromBuffer(headerBuf); + const headerBuf = Buffer.from([0x81, 1, 7, 0, 4, 0, 0, 1, 0, 0, 0, 9, 0, 0, 0, 0, 0x0a, 0, 0, 0, 0, 0, 0, 0]); + const parsedHeader = header.fromBuffer(headerBuf); suite.add('Header#fromBuffer', function() { header.fromBuffer(headerBuf); @@ -35,8 +35,8 @@ var x = (function() { }()); x = (function() { - var suite = new b.Suite(); - var responseHeader = { + const suite = new b.Suite(); + const responseHeader = { magic: 0x81, opcode: 1, keyLength: 15, @@ -47,18 +47,18 @@ x = (function() { opaque: 0, cas: Buffer.from([0x0a, 0, 0, 0, 0, 0, 0, 0]) }; - var buf = Buffer.alloc(24 + 15 + 1024 * 10); + const buf = Buffer.alloc(24 + 15 + 1024 * 10); header.toBuffer(responseHeader).copy(buf); buf.write(makeString(55)); - var server = new memjs.Server(); + const server = new memjs.Server(); - var dummyFunc = function(arg) { + const dummyFunc = function(arg) { server.onResponse(dummyFunc); return arg; }; - var i; + const i; for (i = 0; i < 10; i++) { server.onResponse(dummyFunc); } @@ -78,8 +78,8 @@ x = (function() { }()); x = (function() { - var suite = new b.Suite(); - var client = memjs.Client.create(); + const suite = new b.Suite(); + const client = memjs.Client.create(); suite.cycles = 0; suite.add('Client#get', function() { diff --git a/bench/timers.js b/bench/timers.js index 8efcd7a..7e24e84 100644 --- a/bench/timers.js +++ b/bench/timers.js @@ -6,10 +6,10 @@ * Check how fast various timers are in node. */ -var Benchmark = require('benchmark'); -var Microtime = require('microtime'); +const Benchmark = require('benchmark'); +const Microtime = require('microtime'); -var suite = new Benchmark.Suite(); +const suite = new Benchmark.Suite(); // add tests suite.add('Date.now()', function() { @@ -26,12 +26,12 @@ suite.add('Date.now()', function() { }) .add('process.hrtime() ms-round', function() { // monotonic, ns (returns: [seconds, nanoseconds]) - var time = process.hrtime(); + const time = process.hrtime(); return (time[0] * 1000) + Math.round(time[1] / 1000000); }) .add('process.hrtime() ms-floor', function() { // monotonic, ns (returns: [seconds, nanoseconds]) - var time = process.hrtime(); + const time = process.hrtime(); return (time[0] * 1000) + Math.floor(time[1] / 1000000); }) // add listeners diff --git a/package-lock.json b/package-lock.json index 9c028e0..1ee78f0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -243,8 +243,15 @@ "@types/node": { "version": "12.20.7", "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.7.tgz", - "integrity": "sha512-gWL8VUkg8VRaCAUgG9WmhefMqHmMblxe2rVpMF86nZY/+ZysU+BkAp+3cz03AixWDSSz0ks5WX59yAhv/cDwFA==", - "dev": true + "integrity": "sha512-gWL8VUkg8VRaCAUgG9WmhefMqHmMblxe2rVpMF86nZY/+ZysU+BkAp+3cz03AixWDSSz0ks5WX59yAhv/cDwFA==" + }, + "@types/tap": { + "version": "14.10.3", + "resolved": "https://registry.npmjs.org/@types/tap/-/tap-14.10.3.tgz", + "integrity": "sha512-pdibkMTqKxznrLTFRVJdv/zQ8AAvHe9puqiBt9Mp+hrBgs0ZqCsjCj2e6ez8+p39oapyVp491xxw09E732g1Qw==", + "requires": { + "@types/node": "*" + } }, "@types/yoga-layout": { "version": "1.9.2", diff --git a/package.json b/package.json index 7cd324c..ad29cd7 100644 --- a/package.json +++ b/package.json @@ -23,12 +23,13 @@ "lib": "./lib/memjs" }, "scripts": { - "test": "tsc && tap --no-coverage -R spec ./test/*.js", + "test": "tsc && tap --no-coverage -R spec ./test/*.js ./test/*.ts", "bench": "tsc && NODE_PATH=lib/memjs/ node bench/memjs.js", "bench-timers": "tsc && NODE_PATH=lib/memjs/ node bench/timers.js" }, "devDependencies": { "@types/node": "12.20.7", + "@types/tap": "^14.10.3", "benchmark": "^2.1.4", "docco": "^0.8.0", "eslint": "^7.23.0", diff --git a/src/memjs/header.ts b/src/memjs/header.ts index 58f02d9..7030621 100644 --- a/src/memjs/header.ts +++ b/src/memjs/header.ts @@ -34,7 +34,7 @@ export function fromBuffer(headerBuf: Buffer): Header { /** toBuffer converts a JS memcache header object to a binary memcache header */ export function toBuffer(header: Header) { - var headerBuf = Buffer.alloc(24); + const headerBuf = Buffer.alloc(24); headerBuf.fill(0); headerBuf.writeUInt8(header.magic, 0); headerBuf.writeUInt8(header.opcode, 1); diff --git a/src/memjs/memjs.ts b/src/memjs/memjs.ts index 0e44274..a47ab49 100644 --- a/src/memjs/memjs.ts +++ b/src/memjs/memjs.ts @@ -27,8 +27,8 @@ import * as Utils from "./utils"; import * as Header from "./header"; function defaultKeyToServerHashFunction(servers: string[], key: string) { - var total = servers.length; - var index = total > 1 ? hashCode(key) % total : 0; + const total = servers.length; + const index = total > 1 ? hashCode(key) % total : 0; return servers[index]; } @@ -66,7 +66,7 @@ type IfBuffer = Value extends Buffer : NotBuffer : NotBuffer; -type GivenClientOptions = Partial & +export type GivenClientOptions = Partial & IfBuffer< Value, Extras, @@ -98,7 +98,7 @@ class Client { this.serializer = this.options.serializer || (noopSerializer as any); // Store a mapping from hostport -> server so we can quickly get a server object from the serverKey returned by the hashing function - var serverMap: { [hostport: string]: Server } = {}; + const serverMap: { [hostport: string]: Server } = {}; this.servers.forEach(function (server) { serverMap[server.hostportString()] = server; }); @@ -136,7 +136,7 @@ class Client { * noopSerializer: * * ~~~~ - * var noopSerializer = { + * const noopSerializer = { * serialize: function (opcode, value, extras) { * return { value: value, extras: extras }; * }, @@ -173,11 +173,11 @@ class Client { process.env.MEMCACHIER_SERVERS || process.env.MEMCACHE_SERVERS || "localhost:11211"; - var serverUris = serversStr.split(","); - var servers = serverUris.map(function (uri) { - var uriParts = uri.split("@"); - var hostPort = uriParts[uriParts.length - 1].split(":"); - var userPass = (uriParts[uriParts.length - 2] || "").split(":"); + const serverUris = serversStr.split(","); + const servers = serverUris.map(function (uri) { + const uriParts = uri.split("@"); + const hostPort = uriParts[uriParts.length - 1].split(":"); + const userPass = (uriParts[uriParts.length - 2] || "").split(":"); return new Server( hostPort[0], parseInt(hostPort[1] || "11211", 10), @@ -256,18 +256,17 @@ class Client { flags: Extras | null ) => void ): Promise<{ value: Value | null; flags: Extras | null }> | void { - var self = this; if (callback === undefined) { - return promisify(function (callback) { - self.get(key, function (err, value, flags) { + return promisify((callback) => { + this.get(key, function (err, value, flags) { callback(err, { value: value, flags: flags }); }); }); } - var logger = this.options.logger; + const logger = this.options.logger; this.incrSeq(); - var request = makeRequestBuffer(constants.OP_GET, key, "", "", this.seq); - this.perform(key, request, this.seq, function (err, response) { + const request = makeRequestBuffer(constants.OP_GET, key, "", "", this.seq); + this.perform(key, request, this.seq, (err, response) => { if (err) { if (callback) { callback(err, null, null); @@ -277,7 +276,7 @@ class Client { switch (response!.header.status) { case constants.RESPONSE_STATUS_SUCCCESS: if (callback) { - var deserialized = self.serializer.deserialize( + const deserialized = this.serializer.deserialize( response!.header.opcode, response!.val, response!.extras @@ -291,7 +290,7 @@ class Client { } break; default: - var errorMessage = + const errorMessage = "MemJS GET: " + errors[response!.header.status || UNKNOWN_ERROR]; logger.log(errorMessage); if (callback) { @@ -307,17 +306,17 @@ class Client { */ _buildGetMultiRequest(keys: string[]) { // start at 24 for the no-op command at the end - var requestSize = 24; - for (var keyIdx in keys) { + let requestSize = 24; + for (const keyIdx in keys) { requestSize += Buffer.byteLength(keys[keyIdx], "utf8") + 24; } - var request = Buffer.alloc(requestSize); + const request = Buffer.alloc(requestSize); request.fill(0); - var bytesWritten = 0; - for (keyIdx in keys) { - var key = keys[keyIdx]; + let bytesWritten = 0; + for (const keyIdx in keys) { + const key = keys[keyIdx]; bytesWritten += copyIntoRequestBuffer( constants.OP_GETKQ, key, @@ -352,17 +351,15 @@ class Client { flags: Extras | null ) => void ) { - var self = this; - - var responseMap: { + const responseMap: { [server: string]: Value | null; } = {}; - var handle: OnResponseCallback = function (response) { + const handle: OnResponseCallback = (response) => { switch (response.header.status) { case constants.RESPONSE_STATUS_SUCCCESS: if (callback) { - var deserialized = self.serializer.deserialize( + const deserialized = this.serializer.deserialize( response.header.opcode, response.val, response.extras @@ -374,7 +371,7 @@ class Client { handle.quiet = false; callback(null, responseMap, deserialized.extras); } else { - var key = response.key.toString(); + const key = response.key.toString(); responseMap[key] = deserialized.value; } } @@ -385,9 +382,9 @@ class Client { } break; default: - var errorMessage = + const errorMessage = "MemJS GET: " + errors[response.header.status || UNKNOWN_ERROR]; - self.options.logger.log(errorMessage); + this.options.logger.log(errorMessage); if (callback) { callback(new Error(errorMessage), null, null); } @@ -397,7 +394,7 @@ class Client { // after the first response. Logic in server.js. handle.quiet = true; - var request = this._buildGetMultiRequest(keys); + const request = this._buildGetMultiRequest(keys); serv.onResponse(this.seq, handle); serv.onError(this.seq, function (err) { if (callback) { @@ -445,30 +442,29 @@ class Client { values: { [K in Keys]?: Value | null } | null; flags: Extras | null; }> | void { - var self = this; if (callback === undefined) { - return promisify(function (callback) { - self.getMulti(keys, function (err, values, flags) { + return promisify((callback) => { + this.getMulti(keys, function (err, values, flags) { callback(err, { values: values, flags: flags }); }); }); } - var serverKeytoLookupKeys: { + const serverKeytoLookupKeys: { [serverKey: string]: string[]; } = {}; - keys.forEach(function (lookupKey) { - var serverKey = self.lookupKeyToServerKey(lookupKey); + keys.forEach((lookupKey) => { + const serverKey = this.lookupKeyToServerKey(lookupKey); if (!serverKeytoLookupKeys[serverKey]) { serverKeytoLookupKeys[serverKey] = []; } serverKeytoLookupKeys[serverKey].push(lookupKey); }); - var usedServerKeys = Object.keys(serverKeytoLookupKeys); - var outstandingCalls = usedServerKeys.length; - var recordMap = {}; - var hadError = false; + const usedServerKeys = Object.keys(serverKeytoLookupKeys); + let outstandingCalls = usedServerKeys.length; + const recordMap = {}; + let hadError = false; function latchCallback( err: Error | null, values: { [key: string]: Value | null } | null, @@ -491,9 +487,9 @@ class Client { } } - for (var serverKeyIndex in usedServerKeys) { - var serverKey = usedServerKeys[serverKeyIndex]; - var server = this.serverKeyToServer(serverKey); + for (const serverKeyIndex in usedServerKeys) { + const serverKey = usedServerKeys[serverKeyIndex]; + const server = this.serverKeyToServer(serverKey); this._getMultiToServer( server, serverKeytoLookupKeys[serverKey], @@ -524,11 +520,6 @@ class Client { value: Value, options?: { expires?: number } ): Promise; - set( - key: string, - value: Value, - callback: (error: Error | null, success: boolean | null) => void - ): void; set( key: string, value: Value, @@ -538,16 +529,13 @@ class Client { set( key: string, value: Value, - options?: - | { expires?: number } - | ((error: Error | null, success: boolean | null) => void), + options: { expires?: number }, callback?: (error: Error | null, success: boolean | null) => void ): Promise | void { if (callback === undefined && typeof options !== "function") { - var self = this; if (!options) options = {}; - return promisify(function (callback) { - self.set( + return promisify((callback) => { + this.set( key, value, options as { expires?: number }, @@ -557,30 +545,19 @@ class Client { ); }); } - var logger = this.options.logger; - var expires; - if (typeof options === "function" || typeof callback === "number") { - // OLD: function(key, value, callback, expires) - logger.log("MemJS SET: using deprecated call - arguments have changed"); - expires = callback; - callback = options as ( - error: Error | null, - success: boolean | null - ) => void; - options = {}; - } - logger = this.options.logger; - expires = (options || {}).expires; + const logger = this.options.logger + const expires = (options || {}).expires; + // TODO: support flags, support version (CAS) this.incrSeq(); - var expiration = makeExpiration(expires || this.options.expires); - var extras = Buffer.concat([Buffer.from("00000000", "hex"), expiration]); + const expiration = makeExpiration(expires || this.options.expires); + const extras = Buffer.concat([Buffer.from("00000000", "hex"), expiration]); - var opcode: constants.OP = 1; - var serialized = this.serializer.serialize(opcode, value, extras); - var request = makeRequestBuffer( + const opcode: constants.OP = 1; + const serialized = this.serializer.serialize(opcode, value, extras); + const request = makeRequestBuffer( opcode, key, serialized.extras, @@ -601,7 +578,7 @@ class Client { } break; default: - var errorMessage = + const errorMessage = "MemJS SET: " + errors[response!.header.status || UNKNOWN_ERROR]; logger.log(errorMessage); if (callback) { @@ -634,11 +611,6 @@ class Client { value: Value, options?: { expires?: number } ): Promise; - add( - key: string, - value: Value, - callback: (error: Error | null, success: boolean | null) => void - ): void; add( key: string, value: Value, @@ -648,16 +620,13 @@ class Client { add( key: string, value: Value, - options?: - | { expires?: number } - | ((error: Error | null, success: boolean | null) => void), + options?: { expires?: number }, callback?: (error: Error | null, success: boolean | null) => void ): Promise | void { if (callback === undefined && options !== "function") { - var self = this; if (!options) options = {}; - return promisify(function (callback) { - self.add( + return promisify((callback) => { + this.add( key, value, options as { expires?: number }, @@ -667,27 +636,16 @@ class Client { ); }); } - var logger = this.options.logger; - var expires; - if (typeof options === "function") { - // OLD: function(key, value, callback, expires) - logger.log("MemJS ADD: using deprecated call - arguments have changed"); - expires = callback; - callback = options; - options = {}; - } - - logger = this.options.logger; - expires = (options || {}).expires; + const logger = this.options.logger; // TODO: support flags, support version (CAS) this.incrSeq(); - var expiration = makeExpiration(expires || this.options.expires); - var extras = Buffer.concat([Buffer.from("00000000", "hex"), expiration]); + const expiration = makeExpiration((options || {}).expires || this.options.expires); + const extras = Buffer.concat([Buffer.from("00000000", "hex"), expiration]); - var opcode: constants.OP = 2; - var serialized = this.serializer.serialize(opcode, value, extras); - var request = makeRequestBuffer( + const opcode: constants.OP = 2; + const serialized = this.serializer.serialize(opcode, value, extras); + const request = makeRequestBuffer( opcode, key, serialized.extras, @@ -713,7 +671,7 @@ class Client { } break; default: - var errorMessage = + const errorMessage = "MemJS ADD: " + errors[response!.header.status || UNKNOWN_ERROR]; logger.log(errorMessage, false); if (callback) { @@ -744,32 +702,13 @@ class Client { replace( key: string, value: Value, - options?: { expires?: number } - ): Promise; - replace( - key: string, - value: Value, - callback: (error: Error | null, success: boolean | null) => void - ): void; - replace( - key: string, - value: Value, - options: { expires?: number }, - callback: (error: Error | null, success: boolean | null) => void - ): void; - replace( - key: string, - value: Value, - options?: - | { expires?: number } - | ((error: Error | null, success: boolean | null) => void), + options?: { expires?: number }, callback?: (error: Error | null, success: boolean | null) => void ): Promise | void { if (callback === undefined && options !== "function") { - var self = this; if (!options) options = {}; - return promisify(function (callback) { - self.replace( + return promisify((callback) => { + this.replace( key, value, options as { expires?: number }, @@ -779,29 +718,16 @@ class Client { ); }); } - var logger = this.options.logger; - var expires; - if (typeof options === "function") { - // OLD: function(key, value, callback, expires) - logger.log( - "MemJS REPLACE: using deprecated call - arguments have changed" - ); - expires = callback; - callback = options; - options = {}; - } - - logger = this.options.logger; - expires = (options || {}).expires; + const logger = this.options.logger; // TODO: support flags, support version (CAS) this.incrSeq(); - var expiration = makeExpiration(expires || this.options.expires); - var extras = Buffer.concat([Buffer.from("00000000", "hex"), expiration]); + const expiration = makeExpiration((options || {}).expires || this.options.expires); + const extras = Buffer.concat([Buffer.from("00000000", "hex"), expiration]); - var opcode: constants.OP = 3; - var serialized = this.serializer.serialize(opcode, value, extras); - var request = makeRequestBuffer( + const opcode: constants.OP = 3; + const serialized = this.serializer.serialize(opcode, value, extras); + const request = makeRequestBuffer( opcode, key, serialized.extras, @@ -827,7 +753,7 @@ class Client { } break; default: - var errorMessage = + const errorMessage = "MemJS REPLACE: " + errors[response!.header.status || UNKNOWN_ERROR]; logger.log(errorMessage, false); @@ -860,17 +786,16 @@ class Client { callback?: (err: Error | null, success: boolean | null) => void ): Promise | void { if (callback === undefined) { - var self = this; - return promisify(function (callback) { - self.delete(key, function (err, success) { + return promisify((callback) => { + this.delete(key, function (err, success) { callback(err, Boolean(success)); }); }); } // TODO: Support version (CAS) - var logger = this.options.logger; + const logger = this.options.logger; this.incrSeq(); - var request = makeRequestBuffer(4, key, "", "", this.seq); + const request = makeRequestBuffer(4, key, "", "", this.seq); this.perform(key, request, this.seq, function (err, response) { if (err) { if (callback) { @@ -890,7 +815,7 @@ class Client { } break; default: - var errorMessage = + const errorMessage = "MemJS DELETE: " + errors[response!.header.status || UNKNOWN_ERROR]; logger.log(errorMessage, false); if (callback) { @@ -944,38 +869,21 @@ class Client { ) => void ): Promise<{ value: number | null; success: boolean | null }> | void { if (callback === undefined && options !== "function") { - var self = this; - return promisify(function (callback) { + return promisify((callback) => { if (!options) options = {}; - self.increment(key, amount, options, function (err, success, value) { + this.increment(key, amount, options, function (err, success, value) { callback(err, { success: success, value: value || null }); }); }); } - var logger = this.options.logger; - var initial; - var expires; - if (typeof options === "function") { - // OLD: function(key, amount, callback, expires, initial) - logger.log( - "MemJS INCREMENT: using deprecated call - arguments have changed" - ); - initial = arguments[4]; - expires = callback; - callback = options; - options = {}; - } - - logger = this.options.logger; - initial = options.initial; - expires = options.expires; + const logger = this.options.logger; // TODO: support version (CAS) this.incrSeq(); - initial = initial || 0; - expires = expires || this.options.expires; - var extras = makeAmountInitialAndExpiration(amount, initial, expires); - var request = makeRequestBuffer(5, key, extras, "", this.seq); + const initial = options.initial || 0; + const expires = options.expires || this.options.expires; + const extras = makeAmountInitialAndExpiration(amount, initial, expires); + const request = makeRequestBuffer(5, key, extras, "", this.seq); this.perform(key, request, this.seq, function (err, response) { if (err) { if (callback) { @@ -985,7 +893,7 @@ class Client { } switch (response!.header.status) { case constants.RESPONSE_STATUS_SUCCCESS: - var bufInt = + const bufInt = (response!.val.readUInt32BE(0) << 8) + response!.val.readUInt32BE(4); if (callback) { @@ -993,7 +901,7 @@ class Client { } break; default: - var errorMessage = + const errorMessage = "MemJS INCREMENT: " + errors[response!.header.status || UNKNOWN_ERROR]; logger.log(errorMessage); @@ -1042,38 +950,20 @@ class Client { ) => void ): Promise<{ value: number | null; success: boolean | null }> | void { if (callback === undefined && options !== "function") { - var self = this; - return promisify(function (callback) { - self.decrement(key, amount, options, function (err, success, value) { + return promisify((callback) => { + this.decrement(key, amount, options, function (err, success, value) { callback(err, { success: success, value: value || null }); }); }); } // TODO: support version (CAS) - var logger = this.options.logger; - var initial; - var expires; - if (typeof options === "function") { - // OLD: function(key, amount, callback, expires, initial) - logger.log( - "MemJS DECREMENT: using deprecated call - arguments have changed" - ); - initial = arguments[4]; - expires = callback; - callback = options; - options = {}; - } - - // TODO: support version (CAS) - logger = this.options.logger; - initial = options.initial; - expires = options.expires; + const logger = this.options.logger; this.incrSeq(); - initial = initial || 0; - expires = expires || this.options.expires; - var extras = makeAmountInitialAndExpiration(amount, initial, expires); - var request = makeRequestBuffer(6, key, extras, "", this.seq); + const initial = options.initial || 0; + const expires = options.expires || this.options.expires; + const extras = makeAmountInitialAndExpiration(amount, initial, expires); + const request = makeRequestBuffer(6, key, extras, "", this.seq); this.perform(key, request, this.seq, function (err, response) { if (err) { if (callback) { @@ -1083,7 +973,7 @@ class Client { } switch (response!.header.status) { case constants.RESPONSE_STATUS_SUCCCESS: - var bufInt = + const bufInt = (response!.val.readUInt32BE(0) << 8) + response!.val.readUInt32BE(4); if (callback) { @@ -1091,7 +981,7 @@ class Client { } break; default: - var errorMessage = + const errorMessage = "MemJS DECREMENT: " + errors[response!.header.status || UNKNOWN_ERROR]; logger.log(errorMessage); @@ -1126,19 +1016,18 @@ class Client { callback?: (err: Error | null, success: boolean | null) => void ) { if (callback === undefined) { - var self = this; - return promisify(function (callback) { - self.append(key, value, function (err, success) { + return promisify((callback) => { + this.append(key, value, function (err, success) { callback(err, success); }); }); } // TODO: support version (CAS) - var logger = this.options.logger; + const logger = this.options.logger; this.incrSeq(); - var opcode: constants.OP = 0x0e; - var serialized = this.serializer.serialize(opcode, value, ""); - var request = makeRequestBuffer( + const opcode: constants.OP = 0x0e; + const serialized = this.serializer.serialize(opcode, value, ""); + const request = makeRequestBuffer( opcode, key, serialized.extras, @@ -1164,7 +1053,7 @@ class Client { } break; default: - var errorMessage = + const errorMessage = "MemJS APPEND: " + errors[response!.header.status || UNKNOWN_ERROR]; logger.log(errorMessage); if (callback) { @@ -1198,20 +1087,19 @@ class Client { callback?: (err: Error | null, success: boolean | null) => void ) { if (callback === undefined) { - var self = this; - return promisify(function (callback) { - self.prepend(key, value, function (err, success) { + return promisify((callback) => { + this.prepend(key, value, function (err, success) { callback(err, success); }); }); } // TODO: support version (CAS) - var logger = this.options.logger; + const logger = this.options.logger; this.incrSeq(); - var opcode: constants.OP = constants.OP_PREPEND; /* WAS WRONG IN ORIGINAL */ - var serialized = this.serializer.serialize(opcode, value, ""); - var request = makeRequestBuffer( + const opcode: constants.OP = constants.OP_PREPEND; /* WAS WRONG IN ORIGINAL */ + const serialized = this.serializer.serialize(opcode, value, ""); + const request = makeRequestBuffer( opcode, key, serialized.extras, @@ -1237,7 +1125,7 @@ class Client { } break; default: - var errorMessage = + const errorMessage = "MemJS PREPEND: " + errors[response!.header.status || UNKNOWN_ERROR]; logger.log(errorMessage); @@ -1272,18 +1160,17 @@ class Client { callback?: (err: Error | null, success: boolean | null) => void ): Promise | void { if (callback === undefined) { - var self = this; - return promisify(function (callback) { - self.touch(key, expires, function (err, success) { + return promisify((callback) => { + this.touch(key, expires, function (err, success) { callback(err, Boolean(success)); }); }); } // TODO: support version (CAS) - var logger = this.options.logger; + const logger = this.options.logger; this.incrSeq(); - var extras = makeExpiration(expires || this.options.expires); - var request = makeRequestBuffer(0x1c, key, extras, "", this.seq); + const extras = makeExpiration(expires || this.options.expires); + const request = makeRequestBuffer(0x1c, key, extras, "", this.seq); this.perform(key, request, this.seq, function (err, response) { if (err) { if (callback) { @@ -1303,7 +1190,7 @@ class Client { } break; default: - var errorMessage = + const errorMessage = "MemJS TOUCH: " + errors[response!.header.status || UNKNOWN_ERROR]; logger.log(errorMessage); if (callback) { @@ -1339,22 +1226,20 @@ class Client { ) => void ) { if (callback === undefined) { - var self = this; - return promisify(function (callback) { - self.flush(function (err, results) { + return promisify((callback) => { + this.flush(function (err, results) { callback(err, results); }); }); } // TODO: support expiration this.incrSeq(); - var request = makeRequestBuffer(0x08, "", "", "", this.seq); - var count = this.servers.length; - var result: Record = {}; - var lastErr: Error | null = null; - var i; + const request = makeRequestBuffer(0x08, "", "", "", this.seq); + let count = this.servers.length; + const result: Record = {}; + let lastErr: Error | null = null; - var handleFlush = function (seq: number, serv: Server) { + const handleFlush = function (seq: number, serv: Server) { serv.onResponse(seq, function (/* response */) { count -= 1; result[serv.hostportString()] = true; @@ -1373,7 +1258,7 @@ class Client { serv.write(request); }; - for (i = 0; i < this.servers.length; i++) { + for (let i = 0; i < this.servers.length; i++) { handleFlush(this.seq, this.servers[i]); } } @@ -1399,14 +1284,13 @@ class Client { stats: Record | null ) => void ): void { - var logger = this.options.logger; + const logger = this.options.logger; this.incrSeq(); - var request = makeRequestBuffer(0x10, key, "", "", this.seq); - var i; + const request = makeRequestBuffer(0x10, key, "", "", this.seq); - var handleStats = function (seq: number, serv: Server) { - var result: Record = {}; - var handle: OnResponseCallback = function (response) { + const handleStats = function (seq: number, serv: Server) { + const result: Record = {}; + const handle: OnResponseCallback = function (response) { // end of stat responses if (response.header.totalBodyLength === 0) { if (callback) { @@ -1420,7 +1304,7 @@ class Client { result[response.key.toString()] = response.val.toString(); break; default: - var errorMessage = + const errorMessage = "MemJS STATS (" + key + "): " + @@ -1442,7 +1326,7 @@ class Client { serv.write(request); }; - for (i = 0; i < this.servers.length; i++) { + for (let i = 0; i < this.servers.length; i++) { handleStats(this.seq, this.servers[i]); } } @@ -1505,11 +1389,10 @@ class Client { this.incrSeq(); // TODO: Nicer perhaps to do QUITQ (0x17) but need a new callback for when // write is done. - var request = makeRequestBuffer(0x07, "", "", "", this.seq); // QUIT - var serv; - var i; + const request = makeRequestBuffer(0x07, "", "", "", this.seq); // QUIT + let serv; - var handleQuit = function (seq: number, serv: Server) { + const handleQuit = function (seq: number, serv: Server) { serv.onResponse(seq, function (/* response */) { serv.close(); }); @@ -1519,7 +1402,7 @@ class Client { serv.write(request); }; - for (i = 0; i < this.servers.length; i++) { + for (let i = 0; i < this.servers.length; i++) { serv = this.servers[i]; handleQuit(this.seq, serv); } @@ -1544,20 +1427,19 @@ class Client { extras: Extras | null ) => void ): Promise<{ value: Value | null; flags: Extras | null }> | void { - var self = this; if (callback === undefined) { - return promisify(function (callback) { - self._version(server, function (err, value, flags) { + return promisify((callback) => { + this._version(server, function (err, value, flags) { callback(err, { value: value, flags: flags }); }); }); } this.incrSeq(); - var request = makeRequestBuffer(constants.OP_VERSION, "", "", "", this.seq); - var logger = this.options.logger; + const request = makeRequestBuffer(constants.OP_VERSION, "", "", "", this.seq); + const logger = this.options.logger; - this.performOnServer(server, request, this.seq, function (err, response) { + this.performOnServer(server, request, this.seq, (err, response) => { if (err) { if (callback) { callback(err, null, null); @@ -1569,7 +1451,7 @@ class Client { case constants.RESPONSE_STATUS_SUCCCESS: /* TODO: this is bugged, we should't use the deserializer here, since version always returns a version string. The deserializer should only be used on user key data. */ - var deserialized = self.serializer.deserialize( + const deserialized = this.serializer.deserialize( response!.header.opcode, response!.val, response!.extras @@ -1577,7 +1459,7 @@ class Client { callback(null, deserialized.value, deserialized.extras); break; default: - var errorMessage = + const errorMessage = "MemJS VERSION: " + errors[(response!.header.status, UNKNOWN_ERROR)]; logger.log(errorMessage); @@ -1683,8 +1565,7 @@ class Client { * Closes (abruptly) connections to all the servers. */ close() { - var i; - for (i = 0; i < this.servers.length; i++) { + for (let i = 0; i < this.servers.length; i++) { this.servers[i].close(); } } @@ -1706,9 +1587,9 @@ class Client { callback: ResponseOrErrorCallback, retries?: number ) { - var serverKey = this.lookupKeyToServerKey(key); + const serverKey = this.lookupKeyToServerKey(key); - var server = this.serverKeyToServer(serverKey); + const server = this.serverKeyToServer(serverKey); if (!server) { if (callback) { @@ -1726,20 +1607,20 @@ class Client { callback: ResponseOrErrorCallback, retries: number = 0 ) { - var _this = this; + const _this = this; retries = retries || this.options.retries; - var origRetries = this.options.retries; - var logger = this.options.logger; - var retry_delay = this.options.retry_delay; + const origRetries = this.options.retries; + const logger = this.options.logger; + const retry_delay = this.options.retry_delay; - var responseHandler: OnResponseCallback = function (response) { + const responseHandler: OnResponseCallback = function (response) { if (callback) { callback(null, response); } }; - var errorHandler: OnErrorCallback = function (error) { + const errorHandler: OnErrorCallback = function (error) { if (--retries > 0) { // Wait for retry_delay setTimeout(function () { diff --git a/src/memjs/server.ts b/src/memjs/server.ts index f47b948..9ebd2bd 100644 --- a/src/memjs/server.ts +++ b/src/memjs/server.ts @@ -99,7 +99,7 @@ export class Server extends events.EventEmitter { } respond(response: Message) { - var callback = this.responseCallbacks[response.header.opaque]; + const callback = this.responseCallbacks[response.header.opaque]; if (!callback) { // in case of authentication, no callback is registered return; @@ -117,7 +117,7 @@ export class Server extends events.EventEmitter { } error(err: Error) { - var errcalls = this.errorCallbacks; + const errcalls = this.errorCallbacks; this.connectCallbacks = []; this.responseCallbacks = {}; this.requestTimeouts = []; @@ -133,26 +133,26 @@ export class Server extends events.EventEmitter { } listSasl() { - var buf = makeRequestBuffer(0x20, "", "", ""); + const buf = makeRequestBuffer(0x20, "", "", ""); this.writeSASL(buf); } saslAuth() { - var authStr = "\x00" + this.username + "\x00" + this.password; - var buf = makeRequestBuffer(0x21, "PLAIN", "", authStr); + const authStr = "\x00" + this.username + "\x00" + this.password; + const buf = makeRequestBuffer(0x21, "PLAIN", "", authStr); this.writeSASL(buf); } appendToBuffer(dataBuf: Buffer) { - var old = this.responseBuffer; + const old = this.responseBuffer; this.responseBuffer = Buffer.alloc(old.length + dataBuf.length); old.copy(this.responseBuffer, 0); dataBuf.copy(this.responseBuffer, old.length); return this.responseBuffer; } responseHandler(dataBuf: Buffer) { - var response = parseMessage(this.appendToBuffer(dataBuf)); - var respLength; + let response = parseMessage(this.appendToBuffer(dataBuf)); + let respLength: number; while (response) { if (response.header.opcode === 0x20) { this.saslAuth(); @@ -169,7 +169,7 @@ export class Server extends events.EventEmitter { } } sock(sasl: boolean, go: OnConnectCallback) { - var self = this; + const self = this; if (!self._socket) { // CASE 1: completely new socket @@ -254,8 +254,8 @@ export class Server extends events.EventEmitter { } write(blob: Buffer) { - var self = this; - var deadline = Math.round(self.options.timeout * 1000); + const self = this; + const deadline = Math.round(self.options.timeout * 1000); this.sock(false, function (s) { s.write(blob); self.requestTimeouts.push(timestamp() + deadline); @@ -292,7 +292,7 @@ export class Server extends events.EventEmitter { // We handle tracking timeouts with an array of deadlines (requestTimeouts), as // node doesn't like us setting up lots of timers, and using just one is more // efficient anyway. -var timeoutHandler = function (server: Server, sock: net.Socket) { +const timeoutHandler = function (server: Server, sock: net.Socket) { if (server.requestTimeouts.length === 0) { // nothing active server.timeoutSet = false; @@ -300,8 +300,8 @@ var timeoutHandler = function (server: Server, sock: net.Socket) { } // some requests outstanding, check if any have timed-out - var now = timestamp(); - var soonestTimeout = server.requestTimeouts[0]; + const now = timestamp(); + const soonestTimeout = server.requestTimeouts[0]; if (soonestTimeout <= now) { // timeout occurred! @@ -312,7 +312,7 @@ var timeoutHandler = function (server: Server, sock: net.Socket) { server.error(new Error("socket timed out waiting on response.")); } else { // no timeout! Setup next one. - var deadline = soonestTimeout - now; + const deadline = soonestTimeout - now; sock.setTimeout(deadline, function () { timeoutHandler(server, sock); }); diff --git a/src/memjs/utils.ts b/src/memjs/utils.ts index a62f26a..8bfc63c 100644 --- a/src/memjs/utils.ts +++ b/src/memjs/utils.ts @@ -22,17 +22,17 @@ export const copyIntoRequestBuffer = function ( extras = bufferify(extras); value = bufferify(value); - var bufTargetWriteOffset = _bufTargetWriteOffset || 0; - var totalBytesWritten = 0; + const bufTargetWriteOffset = _bufTargetWriteOffset || 0; + let totalBytesWritten = 0; function copyIntoBuffer(toWriteBuffer: Buffer) { - var bytesWritten = toWriteBuffer.copy( + const bytesWritten = toWriteBuffer.copy( buf, bufTargetWriteOffset + totalBytesWritten ); totalBytesWritten += bytesWritten; } - var requestHeader: header.Header = { + const requestHeader: header.Header = { magic: 0x80, opcode: opcode, keyLength: key.length, @@ -40,7 +40,7 @@ export const copyIntoRequestBuffer = function ( totalBodyLength: key.length + value.length + extras.length, opaque: opaque, }; - var headerBuffer = header.toBuffer(requestHeader); + const headerBuffer = header.toBuffer(requestHeader); copyIntoBuffer(headerBuffer); copyIntoBuffer(extras); @@ -61,9 +61,9 @@ export const makeRequestBuffer = function ( extras = bufferify(extras); value = bufferify(value); - var bufSize = 24 + key.length + extras.length + value.length; + const bufSize = 24 + key.length + extras.length + value.length; - var buf = Buffer.alloc(bufSize); + const buf = Buffer.alloc(bufSize); buf.fill(0); copyIntoRequestBuffer(opcode, key, extras, value, opaque || 0, buf); return buf; @@ -74,7 +74,7 @@ export const makeAmountInitialAndExpiration = function ( amountIfEmpty: number, expiration: number ) { - var buf = Buffer.alloc(20); + const buf = Buffer.alloc(20); buf.writeUInt32BE(0, 0); buf.writeUInt32BE(amount, 4); buf.writeUInt32BE(0, 8); @@ -84,13 +84,13 @@ export const makeAmountInitialAndExpiration = function ( }; export const makeExpiration = function (expiration: number) { - var buf = Buffer.alloc(4); + const buf = Buffer.alloc(4); buf.writeUInt32BE(expiration, 0); return buf; }; export const hashCode = function (str: string) { - var ret, i, len; + let ret, i, len; for (ret = 0, i = 0, len = str.length; i < len; i++) { ret = (31 * ret + str.charCodeAt(i)) << 0; } @@ -108,7 +108,7 @@ export const parseMessage = function (dataBuf: Buffer): Message | false { if (dataBuf.length < 24) { return false; } - var responseHeader = header.fromBuffer(dataBuf); + const responseHeader = header.fromBuffer(dataBuf); if ( dataBuf.length < responseHeader.totalBodyLength + 24 || @@ -118,24 +118,26 @@ export const parseMessage = function (dataBuf: Buffer): Message | false { return false; } - var pointer = 24; - var extras = dataBuf.slice(pointer, pointer + responseHeader.extrasLength); + let pointer = 24; + const extras = dataBuf.slice(pointer, pointer + responseHeader.extrasLength); pointer += responseHeader.extrasLength; - var key = dataBuf.slice(pointer, pointer + responseHeader.keyLength); + const key = dataBuf.slice(pointer, pointer + responseHeader.keyLength); pointer += responseHeader.keyLength; - var val = dataBuf.slice(pointer, 24 + responseHeader.totalBodyLength); + const val = dataBuf.slice(pointer, 24 + responseHeader.totalBodyLength); return { header: responseHeader, key: key, extras: extras, val: val }; }; export const parseMessages = function (dataBuf: Buffer): Message[] { - var messages = []; + const messages = []; + + let message: Message do { - var message = exports.parseMessage(dataBuf); + message = exports.parseMessage(dataBuf); if (message) { messages.push(message); - var messageLength = message.header.totalBodyLength + 24; + const messageLength = message.header.totalBodyLength + 24; dataBuf = dataBuf.slice(messageLength); } } while (message); @@ -158,7 +160,7 @@ export const merge = function (original: any, deflt: T): T { // timestamp provides a monotonic timestamp with millisecond accuracy, useful // for timers. export const timestamp = function () { - var times = process.hrtime(); + const times = process.hrtime(); return times[0] * 1000 + Math.round(times[1] / 1000000); }; @@ -175,7 +177,8 @@ if (!Buffer.concat) { return list[0]; } - var i, buf; + let i: number; + let buf: Buffer; if (typeof length !== "number") { length = 0; @@ -185,9 +188,9 @@ if (!Buffer.concat) { } } - var buffer = Buffer.alloc(length); - var pos = 0; - for (i = 0; i < list.length; i++) { + const buffer = Buffer.alloc(length); + let pos = 0; + for (let i = 0; i < list.length; i++) { buf = list[i]; buf.copy(buffer, pos); pos += buf.length; diff --git a/test/client_test.js b/test/client_test.js deleted file mode 100644 index 4a6e6fd..0000000 --- a/test/client_test.js +++ /dev/null @@ -1,1234 +0,0 @@ -var tap = require('tap'); -var test = tap.test; - -var errors = require('../lib/memjs/protocol').errors; -var MemJS = require('../'); -var constants = require('../lib/memjs/constants'); - -function testAllCallbacksEmpty(t, server) { - t.deepEqual(Object.keys(server.responseCallbacks).length, 0); - t.deepEqual(Object.keys(server.errorCallbacks).length, 0); - - t.deepEqual(server.requestTimeouts, []); -} - -test('GetSuccessful', function(t) { - var n = 0; - var dummyServer = new MemJS.Server('dummyServer'); - dummyServer.write = function(requestBuf) { - var request = MemJS.Utils.parseMessage(requestBuf); - t.equal('hello', request.key.toString()); - n += 1; - dummyServer.respond( - {header: {status: 0, opaque: request.header.opaque}, - val: 'world', extras: 'flagshere'}); - }; - - var client = new MemJS.Client([dummyServer]); - var assertor = function(err, val, flags) { - t.equal('world', val); - t.equal('flagshere', flags); - t.equal(null, err); - t.equal(1, n, 'Ensure get is called'); - }; - client.get('hello', assertor); - n = 0; - return client.get('hello').then(function(res) { - assertor(null, res.value, res.flags); - }); -}); - -test('GetNotFound', function(t) { - var n = 0; - var dummyServer = new MemJS.Server('dummyServer'); - dummyServer.write = function(requestBuf) { - var request = MemJS.Utils.parseMessage(requestBuf); - t.equal('hello', request.key.toString()); - n += 1; - dummyServer.respond( - {header: {status: 1, opaque: request.header.opaque}}); - }; - - var client = new MemJS.Client([dummyServer]); - var assertor = function(val, flags) { - t.equal(null, val); - t.equal(null, flags); - t.equal(1, n, 'Ensure get is called'); - }; - client.get('hello', assertor); - n = 0; - return client.get('hello').then(function(res) { - assertor(null, res.value, res.extras); - t.end(); - }); -}); - -test('GetSerializer', function(t) { - var n = 0; - var dn = 0; - var dummyServer = new MemJS.Server('dummyServer'); - dummyServer.write = function(requestBuf) { - var request = MemJS.Utils.parseMessage(requestBuf); - t.equal('hello', request.key.toString()); - n += 1; - dummyServer.respond( - {header: {status: 0, opaque: request.header.opaque}, - val: 'world', extras: 'flagshere'}); - }; - - var client = new MemJS.Client([dummyServer], { - serializer: { - serialize: function(opcode, value, extras){ - return { value: value, extras: extras }; - }, - deserialize: function (opcode, value, extras) { - dn += 1; - return { value: 'deserialized', extras: extras }; - } - } - }); - var assertor = function(err, val, flags) { - t.equal('deserialized', val); - t.equal('flagshere', flags); - t.equal(null, err); - t.equal(1, n, 'Ensure get is called'); - t.equal(1, dn, 'Ensure deserialization is called once'); - }; - client.get('hello', assertor); - n = 0; - dn = 0; - return client.get('hello').then(function(res) { - assertor(null, res.value, res.flags); - }); -}); - -tap.only('GetMultiSuccessful_SingleBackend', function(t) { - var n = 0; - var dummyServer = new MemJS.Server('dummyServer'); - dummyServer.write = function(requestBuf) { - var requests = MemJS.Utils.parseMessages(requestBuf); - t.equal(requests.length, 4); - n += 1; - - function checkAndRespond(request, key, value) { - t.equal(key, request.key.toString()); - t.equal(constants.OP_GETKQ, request.header.opcode); - - dummyServer.respond( - {header: {status: 0, opaque: request.header.opaque, opcode: request.header.opcode}, - key: key, val: value, extras: 'flagshere'}); - } - checkAndRespond(requests[0], 'hello1', 'world1'); - checkAndRespond(requests[1], 'hello2', 'world2'); - checkAndRespond(requests[2], 'hello3', 'world3'); - - t.equal(constants.OP_NO_OP, requests[3].header.opcode); - dummyServer.respond( - {header: {status: 0, opaque: requests[3].header.opaque, opcode: requests[3].header.opcode}}); - }; - - var client = new MemJS.Client([dummyServer]); - var assertor = function(err, val, flags) { - t.deepEqual({ - hello1: 'world1', - hello2: 'world2', - hello3: 'world3', - }, val); - t.false(flags); - t.equal(null, err); - t.equal(1, n, 'Ensure getMulti is called'); - }; - client.getMulti(['hello1', 'hello2', 'hello3'], assertor); - testAllCallbacksEmpty(t, dummyServer); - - n = 0; - return client.getMulti(['hello1', 'hello2', 'hello3']).then(function(res) { - assertor(null, res.values, res.flags); - }); -}); - -function makeDummyMultiGetServerResponder(t, responseMap, serverName) { - var server = new MemJS.Server(serverName || 'dummyServer'); - var responder = function(requestBuf) { - var requests = MemJS.Utils.parseMessages(requestBuf); - t.equal(requests.length, Object.keys(responseMap).length + 1); - - function checkAndRespond(request, key, value) { - t.equal(constants.OP_GETKQ, request.header.opcode); - - if (value !== undefined) { - server.respond( - {header: {status: 0, opaque: request.header.opaque, opcode: request.header.opcode}, - key: key, val: value, extras: 'flagshere'}); - } - } - - for (var requestIndex in requests) { - var request = requests[requestIndex]; - - if (requestIndex === (requests.length - 1).toString()) { - t.equal(constants.OP_NO_OP, request.header.opcode); - server.respond( - {header: {status: 0, opaque: request.header.opaque, opcode: request.header.opcode}}); - } else { - var key = request.key.toString(); - checkAndRespond(request, key, responseMap[key]); - } - } - }; - server.write = responder; - return server; -} - -test('GetMultiSuccessful_MultiBackend', function(t) { - // the mappings from key to server were computer by just manually running the default hash on them - - var dummyServer1 = makeDummyMultiGetServerResponder(t, { - 'hello2': 'world2', - 'hello4': 'world4', - }, 'dummyServer1'); - var dummyServer2 = makeDummyMultiGetServerResponder(t, { - 'hello1': 'world1', - 'hello3': 'world3', - }, 'dummyServer2'); - var servers = [dummyServer1, dummyServer2]; - - var client = new MemJS.Client(servers); - - var assertor = function(err, val, flags) { - t.deepEqual({ - hello1: 'world1', - hello2: 'world2', - hello3: 'world3', - hello4: 'world4', - }, val); - t.false(flags); - t.equal(null, err); - }; - client.getMulti(['hello1', 'hello2', 'hello3', 'hello4'], assertor); - testAllCallbacksEmpty(t, dummyServer1); - testAllCallbacksEmpty(t, dummyServer2); - - return client.getMulti(['hello1', 'hello2', 'hello3', 'hello4']).then(function(res) { - assertor(null, res.values, res.flags); - }); -}); - -test('GetMultiSuccessful_MissingKeys_MultiBackend', function(t) { - // the mappings from key to server were computed by just manually running the default hash on them - var dummyServer1 = makeDummyMultiGetServerResponder(t, { - 'hello2': undefined, - 'hello4': 'world4', - }, 'dummyServer1'); - var dummyServer2 = makeDummyMultiGetServerResponder(t, { - 'hello1': 'world1', - 'hello3': 'world3', - }, 'dummyServer2'); - var servers = [dummyServer1, dummyServer2]; - - var client = new MemJS.Client(servers); - - var assertor = function(err, val, flags) { - t.deepEqual({ - hello1: 'world1', - hello3: 'world3', - hello4: 'world4', - }, val); - t.false(flags); - t.equal(null, err); - }; - client.getMulti(['hello1', 'hello2', 'hello3', 'hello4'], assertor); - testAllCallbacksEmpty(t, dummyServer1); - testAllCallbacksEmpty(t, dummyServer2); - - return client.getMulti(['hello1', 'hello2', 'hello3', 'hello4']).then(function(res) { - assertor(null, res.values, res.flags); - }); -}); - -test('GetMultiError_MultiBackend', function(t) { - // the mappings from key to server were computed by just manually running the default hash on them - var dummyServer1 = makeDummyMultiGetServerResponder(t, { - 'hello2': undefined, - 'hello4': 'world4', - }, 'dummyServer1'); - var dummyServer2 = makeDummyMultiGetServerResponder(t, { - 'hello1': 'world1', - 'hello3': 'world3' - }, 'dummyServer2'); - dummyServer2.write = function() { - dummyServer2.error({message: 'This is an expected error.'}); - }; - var servers = [dummyServer1, dummyServer2]; - - var client = new MemJS.Client(servers); - - var assertor = function(err) { - t.notEqual(null, err); - t.equal('This is an expected error.', err.message); - }; - client.getMulti(['hello1', 'hello2', 'hello3', 'hello4'], assertor); - testAllCallbacksEmpty(t, dummyServer1); - testAllCallbacksEmpty(t, dummyServer2); - - return client.getMulti(['hello1', 'hello2', 'hello3', 'hello4']).catch(function(err) { - assertor(err); - return true; - }); -}); - -test('GetMultiSuccessfulWithMissingKeys', function(t) { - var dummyServer = makeDummyMultiGetServerResponder(t, { - 'hello1': 'world1', - 'hello2': undefined, - 'hello3': 'world3', - }); - - var client = new MemJS.Client([dummyServer]); - var assertor = function(err, val, flags) { - t.deepEqual({ - hello1: 'world1', - hello3: 'world3', - }, val); - t.false(flags); - t.equal(null, err); - }; - client.getMulti(['hello1', 'hello2', 'hello3'], assertor); - testAllCallbacksEmpty(t, dummyServer); - return client.getMulti(['hello1', 'hello2', 'hello3']).then(function(res) { - assertor(null, res.values, res.flags); - }); -}); - -test('GetMultiError', function(t) { - var dummyServer = new MemJS.Server('dummyServer'); - dummyServer.write = function(requestBuf) { - var requests = MemJS.Utils.parseMessages(requestBuf); - t.equal(requests.length, 4); - - function checkAndRespond(request, key, value) { - t.equal(key, request.key.toString()); - t.equal(constants.OP_GETKQ, request.header.opcode); - - dummyServer.respond( - {header: {status: 0, opaque: request.header.opaque, opcode: request.header.opcode}, - key: key, val: value, extras: 'flagshere'}); - } - checkAndRespond(requests[0], 'hello1', 'world1'); - dummyServer.error({message: 'This is an expected error.'}); - }; - - var client = new MemJS.Client([dummyServer]); - var assertor = function(err) { - t.notEqual(null, err); - t.equal('This is an expected error.', err.message); - }; - client.getMulti(['hello1', 'hello2', 'hello3'], assertor); - testAllCallbacksEmpty(t, dummyServer); - - return client.getMulti(['hello1', 'hello2', 'hello3']).catch(function(err) { - assertor(err); - return true; - }); -}); - -test('SetSuccessful', function(t) { - var n = 0; - var dummyServer = new MemJS.Server('dummyServer'); - dummyServer.write = function(requestBuf) { - var request = MemJS.Utils.parseMessage(requestBuf); - t.equal('hello', request.key.toString()); - t.equal('world', request.val.toString()); - n += 1; - dummyServer.respond({header: {status: 0, opaque: request.header.opaque}}); - }; - - var client = new MemJS.Client([dummyServer]); - var assertor = function(err, val) { - t.equal(true, val); - t.equal(null, err); - t.equal(1, n, 'Ensure set is called'); - }; - client.set('hello', 'world', {}, assertor); - n = 0; - return client.set('hello', 'world', {}).then(function (success){ - assertor(null, success); - }); -}); - -test('SetSuccessfulWithoutOption', function(t) { - var n = 0; - var dummyServer = new MemJS.Server('dummyServer'); - dummyServer.write = function(requestBuf) { - var request = MemJS.Utils.parseMessage(requestBuf); - t.equal('hello', request.key.toString()); - t.equal('world', request.val.toString()); - n += 1; - dummyServer.respond({header: {status: 0, opaque: request.header.opaque}}); - }; - - var client = new MemJS.Client([dummyServer]); - client.set('hello', 'world', function(err, val) { - t.equal(true, val); - t.equal(null, err); - t.equal(1, n, 'Ensure set is called'); - t.end(); - }); -}); - -test('SetPromiseWithoutOption', function(t) { - var n = 0; - var dummyServer = new MemJS.Server('dummyServer'); - dummyServer.write = function(requestBuf) { - var request = MemJS.Utils.parseMessage(requestBuf); - t.equal('hello', request.key.toString()); - t.equal('world', request.val.toString()); - n += 1; - dummyServer.respond({header: {status: 0, opaque: request.header.opaque}}); - }; - - var client = new MemJS.Client([dummyServer]); - return client.set('hello', 'world').then(function(val) { - t.equal(true, val); - t.equal(1, n, 'Ensure set is called'); - t.end(); - }); -}); - -test('SetWithExpiration', function(t) { - var n = 0; - var dummyServer = new MemJS.Server('dummyServer'); - dummyServer.write = function(requestBuf) { - var request = MemJS.Utils.parseMessage(requestBuf); - t.equal('hello', request.key.toString()); - t.equal('world', request.val.toString()); - t.equal('\0\0\0\0\0\0\x04\0', request.extras.toString()); - n += 1; - dummyServer.respond({header: {status: 0, opaque: request.header.opaque}}); - }; - - var client = new MemJS.Client([dummyServer], {expires: 1024}); - client.set('hello', 'world', {}, function(err, val) { - t.equal(null, err); - t.equal(true, val); - t.equal(1, n, 'Ensure set is called'); - t.end(); - }); -}); - -test('SetUnsuccessful', function(t) { - var n = 0; - var dummyServer = new MemJS.Server('dummyServer'); - dummyServer.write = function(requestBuf) { - var request = MemJS.Utils.parseMessage(requestBuf); - t.equal('hello', request.key.toString()); - t.equal('world', request.val.toString()); - n += 1; - dummyServer.respond({header: {status: 3, opaque: request.header.opaque}}); - }; - - var client = new MemJS.Client([dummyServer]); - var assertor = function(err, val) { - t.equal(null, val); - t.equal('MemJS SET: ' + errors[3], err.message); - t.equal(1, n, 'Ensure set is called'); - }; - client.set('hello', 'world', {}, assertor); - n = 0; - return client.set('hello', 'world', {}).catch(function(err) { - assertor(err, null); - }); -}); - -test('SetError', function(t) { - var n = 0; - var dummyServer = new MemJS.Server('dummyServer'); - dummyServer.write = function(requestBuf) { - var request = MemJS.Utils.parseMessage(requestBuf); - t.equal('hello', request.key.toString()); - t.equal('world', request.val.toString()); - n += 1; - dummyServer.error({message: 'This is an expected error.'}); - }; - - var client = new MemJS.Client([dummyServer]); - client.set('hello', 'world', {}, function(err, val) { - t.notEqual(null, err); - t.equal('This is an expected error.', err.message); - t.equal(null, val); - t.equal(2, n, 'Ensure set is retried once'); - t.end(); - }); -}); - -test('SetError', function(t) { - var n = 0; - var dummyServer = new MemJS.Server('dummyServer'); - dummyServer.write = function(requestBuf) { - var request = MemJS.Utils.parseMessage(requestBuf); - t.equal('hello', request.key.toString()); - t.equal('world', request.val.toString()); - setTimeout(function() { - n += 1; - dummyServer.error({message: 'This is an expected error.'}); - }, 100); - }; - - var client = new MemJS.Client([dummyServer], {retries: 2}); - client.set('hello', 'world', {}, function(err /*, val */) { - t.equal(2, n, 'Ensure set is retried once'); - t.ok(err, 'Ensure callback called with error'); - t.equal('This is an expected error.', err.message); - t.end(); - }); -}); - -test('SetErrorConcurrent', function(t) { - var n = 0; - var callbn1 = 0; - var callbn2 = 0; - var dummyServer = new MemJS.Server('dummyServer'); - dummyServer.write = function(/* requestBuf */) { - n += 1; - dummyServer.error({message: 'This is an expected error.'}); - }; - - var client = new MemJS.Client([dummyServer], {retries: 2}); - client.set('hello', 'world', {}, function(err /*, val */) { - t.ok(err, 'Ensure callback called with error'); - t.equal('This is an expected error.', err.message); - callbn1 += 1; - done(); - }); - - client.set('foo', 'bar', {}, function(err /*, val */) { - t.ok(err, 'Ensure callback called with error'); - t.equal('This is an expected error.', err.message); - callbn2 += 1; - done(); - }); - - var done =(function() { - var called = 0; - return function() { - called += 1; - if (called < 2) return; - t.equal(1, callbn1, 'Ensure callback 1 is called once'); - t.equal(1, callbn2, 'Ensure callback 2 is called once'); - t.equal(4, n, 'Ensure error sent twice for each set call'); - t.end(); - }; - })(); -}); - -test('SetUnicode', function(t) { - var n = 0; - var dummyServer = new MemJS.Server('dummyServer'); - dummyServer.write = function(requestBuf) { - var request = MemJS.Utils.parseMessage(requestBuf); - t.equal('hello', request.key.toString()); - t.equal('éééoào', request.val.toString()); - n += 1; - dummyServer.respond({header: {status: 0, opaque: request.header.opaque}}); - }; - - var client = new MemJS.Client([dummyServer]); - client.set('hello', 'éééoào', {}, function(err, val) { - t.equal(true, val); - t.equal(1, n, 'Ensure set is called'); - t.end(); - }); -}); - -test('SetSerialize', function(t) { - var n = 0; - var sn = 0; - var dummyServer = new MemJS.Server('dummyServer'); - dummyServer.write = function(requestBuf) { - var request = MemJS.Utils.parseMessage(requestBuf); - t.equal('hello', request.key.toString()); - t.equal('serialized', request.val.toString()); - n += 1; - dummyServer.respond({header: {status: 3, opaque: request.header.opaque}}); - }; - - var client = new MemJS.Client([dummyServer], { - serializer: { - serialize: function(opcode, value, extras){ - sn += 1; - return { value: 'serialized', extras: extras }; - }, - deserialize: function (opcode, value, extras) { - return { value: value, extras: extras }; - } - } - }); - var assertor = function(err, val) { - t.equal(null, val); - t.equal('MemJS SET: ' + errors[3], err.message); - t.equal(1, n, 'Ensure set is called'); - t.equal(1, sn, 'Ensure serialization is called once'); - }; - client.set('hello', 'world', {}, assertor); - n = 0; - sn = 0; - return client.set('hello', 'world', {}).catch(function(err) { - assertor(err, null); - }); -}); - -test('AddSuccessful', function(t) { - var n = 0; - var dummyServer = new MemJS.Server('dummyServer'); - dummyServer.write = function(requestBuf) { - var request = MemJS.Utils.parseMessage(requestBuf); - t.equal('hello', request.key.toString()); - t.equal('world', request.val.toString()); - t.equal('0000000000000400', request.extras.toString('hex')); - n += 1; - dummyServer.respond({header: {status: 0, opaque: request.header.opaque}}); - }; - - var client = new MemJS.Client([dummyServer], {expires: 1024}); - var assertor = function(err, val) { - t.equal(null, err); - t.equal(true, val); - t.equal(1, n, 'Ensure add is called'); - }; - client.add('hello', 'world', {}, assertor); - n = 0; - return client.add('hello', 'world', {}).then(function(success) { - assertor(null, success); - }); -}); - -test('AddSuccessfulWithoutOption', function(t) { - var n = 0; - var dummyServer = new MemJS.Server('dummyServer'); - dummyServer.write = function(requestBuf) { - var request = MemJS.Utils.parseMessage(requestBuf); - t.equal('hello', request.key.toString()); - t.equal('world', request.val.toString()); - t.equal('0000000000000400', request.extras.toString('hex')); - n += 1; - dummyServer.respond({header: {status: 0, opaque: request.header.opaque}}); - }; - - var client = new MemJS.Client([dummyServer], {expires: 1024}); - client.add('hello', 'world', function(err, val) { - t.equal(null, err); - t.equal(true, val); - t.equal(1, n, 'Ensure add is called'); - t.end(); - }); -}); - -test('AddKeyExists', function(t) { - var n = 0; - var dummyServer = new MemJS.Server('dummyServer'); - dummyServer.write = function(requestBuf) { - var request = MemJS.Utils.parseMessage(requestBuf); - t.equal('hello', request.key.toString()); - t.equal('world', request.val.toString()); - n += 1; - dummyServer.respond({header: {status: 2, opaque: request.header.opaque}}); - }; - - var client = new MemJS.Client([dummyServer]); - client.add('hello', 'world', {}, function(err, val) { - t.equal(null, err); - t.equal(false, val); - t.equal(1, n, 'Ensure add is called'); - t.end(); - }); -}); - -test('AddSerializer', function(t) { - var n = 0; - var sn = 0; - var dummyServer = new MemJS.Server('dummyServer'); - dummyServer.write = function(requestBuf) { - var request = MemJS.Utils.parseMessage(requestBuf); - t.equal('hello', request.key.toString()); - t.equal('serialized', request.val.toString()); - t.equal('0000000100000400', request.extras.toString('hex')); - n += 1; - dummyServer.respond({header: {status: 0, opaque: request.header.opaque}}); - }; - - var client = new MemJS.Client([dummyServer], { - expires: 1024, - serializer: { - serialize: function(opcode, value, extras){ - sn += 1; - extras.writeUInt32BE(1, 0); - return { value: 'serialized', extras: extras }; - }, - deserialize: function (opcode, value, extras) { - return { value: value, extras: extras }; - } - } - }); - var assertor = function(err, val) { - t.equal(null, err); - t.equal(true, val); - t.equal(1, n, 'Ensure add is called'); - t.equal(1, sn, 'Ensure serialization is called once'); - }; - client.add('hello', 'world', {}, assertor); - n = 0; - sn = 0; - return client.add('hello', 'world', {}).then(function(success) { - assertor(null, success); - }); -}); - -test('ReplaceSuccessful', function(t) { - var n = 0; - var dummyServer = new MemJS.Server('dummyServer'); - dummyServer.write = function(requestBuf) { - var request = MemJS.Utils.parseMessage(requestBuf); - t.equal('hello', request.key.toString()); - t.equal('world', request.val.toString()); - t.equal('\0\0\0\0\0\0\x04\0', request.extras.toString()); - n += 1; - dummyServer.respond({header: {status: 0, opaque: request.header.opaque}}); - }; - - var client = new MemJS.Client([dummyServer], {expires: 1024}); - var assertor = function(err, val) { - t.equal(null, err); - t.equal(true, val); - t.equal(1, n, 'Ensure replace is called'); - }; - client.replace('hello', 'world', {}, assertor); - n = 0; - return client.replace('hello', 'world', {}).then(function(success){ - assertor(null, success); - }); -}); - -test('ReplaceSuccessfulWithoutOption', function(t) { - var n = 0; - var dummyServer = new MemJS.Server('dummyServer'); - dummyServer.write = function(requestBuf) { - var request = MemJS.Utils.parseMessage(requestBuf); - t.equal('hello', request.key.toString()); - t.equal('world', request.val.toString()); - t.equal('\0\0\0\0\0\0\x04\0', request.extras.toString()); - n += 1; - dummyServer.respond({header: {status: 0, opaque: request.header.opaque}}); - }; - - var client = new MemJS.Client([dummyServer], {expires: 1024}); - client.replace('hello', 'world', function(err, val) { - t.equal(null, err); - t.equal(true, val); - t.equal(1, n, 'Ensure replace is called'); - t.end(); - }); -}); - -test('ReplaceKeyDNE', function(t) { - var n = 0; - var dummyServer = new MemJS.Server('dummyServer'); - dummyServer.write = function(requestBuf) { - var request = MemJS.Utils.parseMessage(requestBuf); - t.equal('hello', request.key.toString()); - t.equal('world', request.val.toString()); - n += 1; - dummyServer.respond({header: {status: 1, opaque: request.header.opaque}}); - }; - - var client = new MemJS.Client([dummyServer]); - client.replace('hello', 'world', {}, function(err, val) { - t.equal(null, err); - t.equal(false, val); - t.equal(1, n, 'Ensure replace is called'); - t.end(); - }); -}); - -test('DeleteSuccessful', function(t) { - var n = 0; - var dummyServer = new MemJS.Server('dummyServer'); - dummyServer.write = function(requestBuf) { - var request = MemJS.Utils.parseMessage(requestBuf); - t.equal('hello', request.key.toString()); - n += 1; - dummyServer.respond({header: {status: 0, opaque: request.header.opaque}}); - }; - - var client = new MemJS.Client([dummyServer]); - var assertor = function(err, val) { - t.equal(null, err); - t.equal(true, val); - t.equal(1, n, 'Ensure delete is called'); - }; - client.delete('hello', assertor); - n = 0; - return client.delete('hello').then(function(success) { - assertor(null, success); - }); -}); - -test('DeleteKeyDNE', function(t) { - var n = 0; - var dummyServer = new MemJS.Server('dummyServer'); - dummyServer.write = function(requestBuf) { - var request = MemJS.Utils.parseMessage(requestBuf); - t.equal('hello', request.key.toString()); - n += 1; - dummyServer.respond({header: {status: 1, opaque: request.header.opaque}}); - }; - - var client = new MemJS.Client([dummyServer]); - client.delete('hello', function(err, val) { - t.equal(null, err); - t.equal(false, val); - t.equal(1, n, 'Ensure delete is called'); - t.end(); - }); -}); - -test('Flush', function(t) { - var n = 0; - var dummyServer = new MemJS.Server('dummyServer'); - dummyServer.host = 'example.com'; - dummyServer.port = 1234; - dummyServer.write = function(requestBuf) { - var request = MemJS.Utils.parseMessage(requestBuf); - t.equal(0x08, request.header.opcode); - n += 1; - dummyServer.respond({header: {status: 1, opaque: request.header.opaque}}); - }; - - var client = new MemJS.Client([dummyServer, dummyServer]); - var assertor = function(err, results) { - t.equal(null, err); - t.equal(true, results['example.com:1234']); - t.equal(2, n, 'Ensure flush is called for each server'); - }; - client.flush(assertor); - n = 0; - return client.flush().then(function(results) { - assertor(null, results); - }); -}); - -test('Stats', function(t) { - var n = 0; - var dummyServer = new MemJS.Server('dummyServer'); - dummyServer.host = 'myhostname'; - dummyServer.port = 5544; - dummyServer.write = function(requestBuf) { - var request = MemJS.Utils.parseMessage(requestBuf); - t.equal(0x10, request.header.opcode); - n += 1; - dummyServer.respond({ - header: {status: 0, totalBodyLength: 9, opaque: request.header.opaque}, - key: 'bytes', val: '1432'}); - dummyServer.respond({ - header: {status: 0, totalBodyLength: 9, opaque: request.header.opaque}, - key: 'count', val: '5432'}); - dummyServer.respond({ - header: {status: 0, totalBodyLength: 0, opaque: request.header.opaque}}); - }; - - var client = new MemJS.Client([dummyServer]); - client.stats(function(err, server, stats) { - t.equal(null, err); - t.equal('1432', stats.bytes); - t.equal('5432', stats.count); - t.equal('myhostname:5544', server); - t.equal(1, n, 'Ensure stats is called'); - t.end(); - }); -}); - -test('IncrementSuccessful', function(t) { - var n = 0; - var callbn = 0; - var dummyServer = new MemJS.Server('dummyServer'); - - var expectedExtras = [ - '\0\0\0\0\0\0\0\x05\0\0\0\0\0\0\0\0\0\0\0\0', - '\0\0\0\0\0\0\0\x05\0\0\0\0\0\0\0\x03\0\0\0\0' - ]; - - dummyServer.write = function(requestBuf) { - var request = MemJS.Utils.parseMessage(requestBuf); - t.equal(5, request.header.opcode); - t.equal('number-increment-test', request.key.toString()); - t.equal('', request.val.toString()); - t.equal(expectedExtras[n], request.extras.toString()); - n += 1; - process.nextTick(function() { - var value = Buffer.alloc(8); - value.writeUInt32BE(request.header.opcode + 1, 4); - value.writeUInt32BE(0, 0); - dummyServer.respond({header: {status: 0, opaque: request.header.opaque}, val: value}); - }); - }; - - var client = new MemJS.Client([dummyServer]); - client.increment('number-increment-test', 5, {}, function(err, success, val){ - callbn += 1; - t.equal(true, success); - t.equal(6, val); - t.equal(null, err); - done(); - }); - - client.increment('number-increment-test', 5, { initial: 3 }, function(err, success, val) { - callbn += 1; - t.equal(true, success); - t.equal(6, val); - t.equal(null, err); - done(); - }); - - var done =(function() { - var called = 0; - return function() { - called += 1; - if (called < 2) return; - t.equal(2, n, 'Ensure increment is called twice'); - t.equal(2, callbn, 'Ensure callback is called twice'); - t.end(); - }; - })(); -}); - -test('DecrementSuccessful', function(t) { - var n = 0; - var dummyServer = new MemJS.Server('dummyServer'); - dummyServer.write = function(requestBuf) { - var request = MemJS.Utils.parseMessage(requestBuf); - t.equal(6, request.header.opcode); - t.equal('number-decrement-test', request.key.toString()); - t.equal('', request.val.toString()); - t.equal('\0\0\0\0\0\0\0\x05\0\0\0\0\0\0\0\0\0\0\0\0', request.extras.toString()); - n += 1; - process.nextTick(function() { - var value = Buffer.alloc(8); - value.writeUInt32BE(request.header.opcode, 4); - value.writeUInt32BE(0, 0); - dummyServer.respond({header: {status: 0, opaque: request.header.opaque}, val: value}); - }); - }; - - var client = new MemJS.Client([dummyServer]); - client.decrement('number-decrement-test', 5, {}, function(err, success, val) { - t.equal(true, success); - t.equal(6, val); - t.equal(null, err); - t.equal(1, n, 'Ensure decr is called'); - t.end(); - }); -}); - -test('DecrementSuccessfulWithoutOption', function(t) { - var n = 0; - var dummyServer = new MemJS.Server('dummyServer'); - dummyServer.write = function(requestBuf) { - var request = MemJS.Utils.parseMessage(requestBuf); - t.equal(6, request.header.opcode); - t.equal('number-decrement-test', request.key.toString()); - t.equal('', request.val.toString()); - t.equal('\0\0\0\0\0\0\0\x05\0\0\0\0\0\0\0\0\0\0\0\0', request.extras.toString()); - n += 1; - process.nextTick(function() { - var value = Buffer.alloc(8); - value.writeUInt32BE(request.header.opcode, 4); - value.writeUInt32BE(0, 0); - dummyServer.respond({header: {status: 0, opaque: request.header.opaque}, val: value}); - }); - }; - - var client = new MemJS.Client([dummyServer]); - client.decrement('number-decrement-test', 5, function(err, success, val) { - t.equal(true, success); - t.equal(6, val); - t.equal(null, err); - t.equal(1, n, 'Ensure decr is called'); - t.end(); - }); -}); - -test('AppendSuccessful', function(t) { - var n = 0; - var dummyServer = new MemJS.Server('dummyServer'); - dummyServer.write = function(requestBuf) { - var request = MemJS.Utils.parseMessage(requestBuf); - t.equal('hello', request.key.toString()); - t.equal('world', request.val.toString()); - n += 1; - dummyServer.respond({header: {status: 0, opaque: request.header.opaque}}); - }; - - var client = new MemJS.Client([dummyServer], {expires: 1024}); - client.append('hello', 'world', function(err, val) { - t.equal(null, err); - t.equal(true, val); - t.equal(1, n, 'Ensure append is called'); - t.end(); - }); -}); - -test('AppendKeyDNE', function(t) { - var n = 0; - var dummyServer = new MemJS.Server('dummyServer'); - dummyServer.write = function(requestBuf) { - var request = MemJS.Utils.parseMessage(requestBuf); - t.equal('hello', request.key.toString()); - t.equal('world', request.val.toString()); - n += 1; - dummyServer.respond({header: {status: 1, opaque: request.header.opaque}}); - }; - - var client = new MemJS.Client([dummyServer]); - client.append('hello', 'world', function(err, val) { - t.equal(null, err); - t.equal(false, val); - t.equal(1, n, 'Ensure append is called'); - t.end(); - }); -}); - -test('PrependSuccessful', function(t) { - var n = 0; - var dummyServer = new MemJS.Server('dummyServer'); - dummyServer.write = function(requestBuf) { - var request = MemJS.Utils.parseMessage(requestBuf); - t.equal('hello', request.key.toString()); - t.equal('world', request.val.toString()); - n += 1; - dummyServer.respond({header: {status: 0, opaque: request.header.opaque}}); - }; - - var client = new MemJS.Client([dummyServer], {expires: 1024}); - client.prepend('hello', 'world', function(err, val) { - t.equal(null, err); - t.equal(true, val); - t.equal(1, n, 'Ensure prepend is called'); - t.end(); - }); -}); - -test('PrependKeyDNE', function(t) { - var n = 0; - var dummyServer = new MemJS.Server('dummyServer'); - dummyServer.write = function(requestBuf) { - var request = MemJS.Utils.parseMessage(requestBuf); - t.equal('hello', request.key.toString()); - t.equal('world', request.val.toString()); - n += 1; - dummyServer.respond({header: {status: 1, opaque: request.header.opaque}}); - }; - - var client = new MemJS.Client([dummyServer]); - client.prepend('hello', 'world', function(err, val) { - t.equal(null, err); - t.equal(false, val); - t.equal(1, n, 'Ensure prepend is called'); - t.end(); - }); -}); - -test('TouchSuccessful', function(t) { - var n = 0; - var dummyServer = new MemJS.Server('dummyServer'); - dummyServer.write = function(requestBuf) { - var request = MemJS.Utils.parseMessage(requestBuf); - t.equal('hello', request.key.toString()); - t.equal('', request.val.toString()); - t.equal('\0\0\x04\0', request.extras.toString()); - n += 1; - dummyServer.respond({header: {status: 0, opaque: request.header.opaque}}); - }; - - var client = new MemJS.Client([dummyServer]); - client.touch('hello', 1024, function(err, val) { - t.equal(null, err); - t.equal(true, val); - t.equal(1, n, 'Ensure touch is called'); - t.end(); - }); -}); - -test('TouchKeyDNE', function(t) { - var n = 0; - var dummyServer = new MemJS.Server('dummyServer'); - dummyServer.write = function(requestBuf) { - var request = MemJS.Utils.parseMessage(requestBuf); - t.equal('hello', request.key.toString()); - t.equal('', request.val.toString()); - t.equal('\0\0\x04\0', request.extras.toString()); - n += 1; - dummyServer.respond({header: {status: 1, opaque: request.header.opaque}}); - }; - - var client = new MemJS.Client([dummyServer]); - client.touch('hello', 1024, function(err, val) { - t.equal(null, err); - t.equal(false, val); - t.equal(1, n, 'Ensure ptouch is called'); - t.end(); - }); -}); - -// test('Failover', function(t) { -// var n1 = 0; -// var n2 = 0; -// var dummyServer1 = new MemJS.Server('dummyServer'); -// dummyServer1.write = function(/* requestBuf*/) { -// n1 += 1; -// dummyServer1.error(new Error('connection failure')); -// }; -// var dummyServer2 = new MemJS.Server('dummyServer'); -// dummyServer2.write = function(requestBuf) { -// n2 += 1; -// var request = MemJS.Utils.parseMessage(requestBuf); -// dummyServer2.respond({header: {status: 0, opaque: request.header.opaque}}); -// }; - -// var client = new MemJS.Client([dummyServer1, dummyServer2], {failover: true}); -// client.get('\0', function(err/*, val */){ -// t.equal(null, err); -// t.equal(2, n1); -// t.equal(1, n2); -// t.end(); -// }); - -// }); - -test('Very Large Client Seq', function(t) { - var n = 0; - var dummyServer = new MemJS.Server('dummyServer'); - dummyServer.write = function(requestBuf) { - var request = MemJS.Utils.parseMessage(requestBuf); - t.equal('hello', request.key.toString()); - t.equal('world', request.val.toString()); - t.equal('0000000000000400', request.extras.toString('hex')); - n += 1; - dummyServer.respond({header: {status: 0, opaque: request.header.opaque}}); - }; - - var client = new MemJS.Client([dummyServer], {expires: 1024}); - client.seq = Math.pow(2,33); - var assertor = function(err, val) { - t.equal(null, err); - t.equal(true, val); - t.equal(1, n, 'Ensure add is called'); - }; - client.add('hello', 'world', {}, assertor); - n = 0; - return client.add('hello', 'world', {}).then(function(success) { - assertor(null, success); - }); -}); - -const makeDummyVersionServer = (t, serverKey, version) => { - var dummyServer = new MemJS.Server(serverKey); - dummyServer.write = function(requestBuf) { - var request = MemJS.Utils.parseMessage(requestBuf); - t.deepEqual(Buffer.from(''), request.key); - dummyServer.respond( - {header: {status: 0, opaque: request.header.opaque}, - val: version, extras: 'flagshere'}); - }; - return dummyServer; -}; - -test('VersionSuccessful', function(t) { - var n = 0; - - var dummyServer = makeDummyVersionServer(t, 'dummyServer', '1.3.1'); - dummyServer.write = function(requestBuf) { - var request = MemJS.Utils.parseMessage(requestBuf); - t.deepEqual(Buffer.from(''), request.key); - n += 1; - dummyServer.respond( - {header: {status: 0, opaque: request.header.opaque}, - val: '1.3.1', extras: 'flagshere'}); - }; - - var client = new MemJS.Client([dummyServer]); - var assertor = function(err, val, flags) { - t.equal('1.3.1', val); - t.equal('flagshere', flags); - t.equal(null, err); - t.equal(n, 1, 'Ensure version is called'); - }; - - client.version(assertor); - n = 0; - - return client.version().then(function(res) { - assertor(null, res.value, res.flags); - }); -}); - -tap.only('VersionError', function(t) { - var dummyServer = new MemJS.Server('dummyServer'); - dummyServer.write = function() { - dummyServer.error({message: 'This is an expected error.'}); - }; - - var client = new MemJS.Client([dummyServer]); - var assertor = function(err) { - t.notEqual(null, err); - t.equal('This is an expected error.', err.message); - }; - - client.version(assertor); - return client.version().catch(function(err) { - assertor(err); - return true; - }); -}); - -test('VersionAllSuccessful', function(t) { - const dummyServer1 = makeDummyVersionServer(t, 'dummyServer1', '1.0.0'); - const dummyServer2 = makeDummyVersionServer(t, 'dummyServer2', '2.0.0'); - const dummyServer3 = makeDummyVersionServer(t, 'dummyServer3', '3.0.0'); - - var client = new MemJS.Client([dummyServer1, dummyServer2, dummyServer3]); - var assertor = function(err, val) { - t.deepEqual({ - 'dummyServer1:undefined': '1.0.0', - 'dummyServer2:undefined': '2.0.0', - 'dummyServer3:undefined': '3.0.0' - }, val); - t.equal(null, err); - }; - - client.versionAll(assertor); - - return client.versionAll().then(function(res) { - assertor(null, res.values, res.flags); - }); -}); - - -tap.only('VersionAllSomeFailed', function(t) { - const dummyServer1 = makeDummyVersionServer(t, 'dummyServer1', '1.0.0'); - const dummyServer2 = makeDummyVersionServer(t, 'dummyServer2', '2.0.0'); - dummyServer2.write = function() { - dummyServer2.error({message: 'This is an expected error.'}); - }; - const dummyServer3 = makeDummyVersionServer(t, 'dummyServer3', '3.0.0'); - - var client = new MemJS.Client([dummyServer1, dummyServer2, dummyServer3]); - var assertor = function(err) { - t.notEqual(null, err); - t.equal('This is an expected error.', err.message); - }; - - client.versionAll(assertor); - - return client.versionAll().catch(function(err) { - assertor(err); - }); -}); \ No newline at end of file diff --git a/test/client_test.ts b/test/client_test.ts new file mode 100644 index 0000000..8aa906c --- /dev/null +++ b/test/client_test.ts @@ -0,0 +1,1438 @@ +import tap from 'tap' +const test = tap.test + +const errors = require("../lib/memjs/protocol").errors +import MemJS = require("../") +import constants = require("../lib/memjs/constants") +import { noopSerializer } from "../lib/memjs/noop-serializer" +import { Header } from "../lib/memjs/header" +import type { GivenClientOptions } from "../lib/memjs/memjs" +import * as Utils from "../lib/memjs/utils" +import { MaybeBuffer } from "../lib/memjs/utils" + +function testAllCallbacksEmpty(t: any, server: MemJS.Server) { + t.deepEqual(Object.keys(server.responseCallbacks).length, 0) + t.deepEqual(Object.keys(server.errorCallbacks).length, 0) + + t.deepEqual(server.requestTimeouts, []) +} + +function makeClient(dummyServer: MemJS.Server | MemJS.Server[], options?: GivenClientOptions) { + return new MemJS.Client( + Array.isArray(dummyServer) ? dummyServer : [dummyServer], + options || { serializer: noopSerializer } + ) +} + +function parseMessage(requestBuf: Buffer) { + const message = Utils.parseMessage(requestBuf) + if (!message) { + throw new Error("Expected message to parse successfully, but got false") + } + return message +} + +function makeDummyServer(name: string) { + return new MemJS.Server(name) as MemJS.Server & { + respond: (m: { + extras?: string | Buffer, + key?: string | Buffer, + val?: string | Buffer, + header: Partial
}) => void + } +} + +test("GetSuccessful", function (t) { + let n = 0 + const dummyServer = makeDummyServer("dummyServer") + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf) + t.equal("hello", request.key.toString()) + n += 1 + dummyServer.respond({ + header: { status: 0, opaque: request.header.opaque }, + val: Buffer.from("world"), + extras: Buffer.from("flagshere"), + }) + } + + const client = makeClient([dummyServer]) + const assertor = function (err: Error | null, val: string | MaybeBuffer, flags: string) { + t.equal("world", val) + t.equal("flagshere", flags) + t.equal(null, err) + t.equal(1, n, "Ensure get is called") + } + client.get("hello", assertor) + n = 0 + return client.get("hello").then(function (res) { + assertor(null, res.value, res.flags) + }) +}) + +test("GetNotFound", function (t) { + let n = 0 + const dummyServer = makeDummyServer("dummyServer") + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf) + t.equal("hello", request.key.toString()) + n += 1 + dummyServer.respond({ + header: { status: 1, opaque: request.header.opaque }, + }) + } + + const client = makeClient([dummyServer]) + const assertor = function (val, flags) { + t.equal(null, val) + t.equal(null, flags) + t.equal(1, n, "Ensure get is called") + } + client.get("hello", assertor) + n = 0 + return client.get("hello").then(function (res) { + assertor(null, res.value) + t.end() + }) +}) + +test("GetSerializer", function (t) { + let n = 0 + let dn = 0 + const dummyServer = makeDummyServer("dummyServer") + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf) + t.equal("hello", request.key.toString()) + n += 1 + dummyServer.respond({ + header: { status: 0, opaque: request.header.opaque }, + val: "world", + extras: "flagshere", + }) + } + + const client = makeClient([dummyServer], { + serializer: { + serialize: function (opcode, value, extras) { + return { value: value, extras: extras } + }, + deserialize: function (opcode, value, extras) { + dn += 1 + return { value: "deserialized", extras: extras } + }, + }, + }) + const assertor = function (err: Error | null, val: string | MaybeBuffer, flags: string) { + t.equal("deserialized", val) + t.equal("flagshere", flags) + t.equal(null, err) + t.equal(1, n, "Ensure get is called") + t.equal(1, dn, "Ensure deserialization is called once") + } + client.get("hello", assertor) + n = 0 + dn = 0 + return client.get("hello").then(function (res) { + assertor(null, res.value, res.flags) + }) +}) + +tap.only("GetMultiSuccessful_SingleBackend", function (t) { + let n = 0 + const dummyServer = makeDummyServer("dummyServer") + dummyServer.write = function (requestBuf) { + const requests = Utils.parseMessages(requestBuf) + t.equal(requests.length, 4) + n += 1 + + function checkAndRespond(request: Utils.Message, key: string, value: string) { + t.equal(key, request.key.toString()) + t.equal(constants.OP_GETKQ, request.header.opcode) + + dummyServer.respond({ + header: { + status: 0, + opaque: request.header.opaque, + opcode: request.header.opcode, + }, + key: key, + val: value, + extras: "flagshere", + }) + } + checkAndRespond(requests[0], "hello1", "world1") + checkAndRespond(requests[1], "hello2", "world2") + checkAndRespond(requests[2], "hello3", "world3") + + t.equal(constants.OP_NO_OP, requests[3].header.opcode) + dummyServer.respond({ + header: { + status: 0, + opaque: requests[3].header.opaque, + opcode: requests[3].header.opcode, + }, + }) + } + + const client = makeClient([dummyServer]) + const assertor = function (err: Error | null, val: any, flags: string) { + t.deepEqual( + { + hello1: "world1", + hello2: "world2", + hello3: "world3", + }, + val + ) + t.false(flags) + t.equal(null, err) + t.equal(1, n, "Ensure getMulti is called") + } + client.getMulti(["hello1", "hello2", "hello3"], assertor) + testAllCallbacksEmpty(t, dummyServer) + + n = 0 + return client.getMulti(["hello1", "hello2", "hello3"]).then(function (res) { + assertor(null, res.values, res.flags) + }) +}) + +function makeDummyMultiGetServerResponder(t, responseMap, serverName?: string) { + const server = makeDummyServer(serverName || "dummyServer") + const responder = function (requestBuf) { + const requests = Utils.parseMessages(requestBuf) + t.equal(requests.length, Object.keys(responseMap).length + 1) + + function checkAndRespond(request, key, value) { + t.equal(constants.OP_GETKQ, request.header.opcode) + + if (value !== undefined) { + server.respond({ + header: { + status: 0, + opaque: request.header.opaque, + opcode: request.header.opcode, + }, + key: key, + val: value, + extras: "flagshere", + }) + } + } + + for (const requestIndex in requests) { + const request = requests[requestIndex] + + if (requestIndex === (requests.length - 1).toString()) { + t.equal(constants.OP_NO_OP, request.header.opcode) + server.respond({ + header: { + status: 0, + opaque: request.header.opaque, + opcode: request.header.opcode, + }, + }) + } else { + const key = request.key.toString() + checkAndRespond(request, key, responseMap[key]) + } + } + } + server.write = responder + return server +} + +test("GetMultiSuccessful_MultiBackend", function (t) { + // the mappings from key to server were computer by just manually running the default hash on them + + const dummyServer1 = makeDummyMultiGetServerResponder( + t, + { + hello2: "world2", + hello4: "world4", + }, + "dummyServer1" + ) + const dummyServer2 = makeDummyMultiGetServerResponder( + t, + { + hello1: "world1", + hello3: "world3", + }, + "dummyServer2" + ) + const servers = [dummyServer1, dummyServer2] + + const client = makeClient(servers) + + const assertor = function (err: Error | null, val: any, flags: string) { + t.deepEqual( + { + hello1: "world1", + hello2: "world2", + hello3: "world3", + hello4: "world4", + }, + val + ) + t.false(flags) + t.equal(null, err) + } + client.getMulti(["hello1", "hello2", "hello3", "hello4"], assertor) + testAllCallbacksEmpty(t, dummyServer1) + testAllCallbacksEmpty(t, dummyServer2) + + return client + .getMulti(["hello1", "hello2", "hello3", "hello4"]) + .then(function (res) { + assertor(null, res.values, res.flags) + }) +}) + +test("GetMultiSuccessful_MissingKeys_MultiBackend", function (t) { + // the mappings from key to server were computed by just manually running the default hash on them + const dummyServer1 = makeDummyMultiGetServerResponder( + t, + { + hello2: undefined, + hello4: "world4", + }, + "dummyServer1" + ) + const dummyServer2 = makeDummyMultiGetServerResponder( + t, + { + hello1: "world1", + hello3: "world3", + }, + "dummyServer2" + ) + const servers = [dummyServer1, dummyServer2] + + const client = makeClient(servers) + + const assertor = function (err: Error | null, val: any, flags: string) { + t.deepEqual( + { + hello1: "world1", + hello3: "world3", + hello4: "world4", + }, + val + ) + t.false(flags) + t.equal(null, err) + } + client.getMulti(["hello1", "hello2", "hello3", "hello4"], assertor) + testAllCallbacksEmpty(t, dummyServer1) + testAllCallbacksEmpty(t, dummyServer2) + + return client + .getMulti(["hello1", "hello2", "hello3", "hello4"]) + .then(function (res) { + assertor(null, res.values, res.flags) + }) +}) + +test("GetMultiError_MultiBackend", function (t) { + // the mappings from key to server were computed by just manually running the default hash on them + const dummyServer1 = makeDummyMultiGetServerResponder( + t, + { + hello2: undefined, + hello4: "world4", + }, + "dummyServer1" + ) + const dummyServer2 = makeDummyMultiGetServerResponder( + t, + { + hello1: "world1", + hello3: "world3", + }, + "dummyServer2" + ) + dummyServer2.write = function () { + dummyServer2.error({ name: "ErrorName", message: "This is an expected error." }) + } + const servers = [dummyServer1, dummyServer2] + + const client = makeClient(servers) + + const assertor = function (err) { + t.notEqual(null, err) + t.equal("This is an expected error.", err.message) + } + client.getMulti(["hello1", "hello2", "hello3", "hello4"], assertor) + testAllCallbacksEmpty(t, dummyServer1) + testAllCallbacksEmpty(t, dummyServer2) + + return client + .getMulti(["hello1", "hello2", "hello3", "hello4"]) + .catch(function (err) { + assertor(err) + return true + }) +}) + +test("GetMultiSuccessfulWithMissingKeys", function (t) { + const dummyServer = makeDummyMultiGetServerResponder(t, { + hello1: "world1", + hello2: undefined, + hello3: "world3", + }) + + const client = makeClient([dummyServer], { serializer: noopSerializer }) + const assertor = function (err: Error | null, val: any, flags: string) { + t.deepEqual( + { + hello1: "world1", + hello3: "world3", + }, + val + ) + t.false(flags) + t.equal(null, err) + } + client.getMulti(["hello1", "hello2", "hello3"], assertor) + testAllCallbacksEmpty(t, dummyServer) + return client.getMulti(["hello1", "hello2", "hello3"]).then(function (res) { + assertor(null, res.values, res.flags) + }) +}) + +test("GetMultiError", function (t) { + const dummyServer = makeDummyServer("dummyServer") + dummyServer.write = function (requestBuf) { + const requests = Utils.parseMessages(requestBuf) + t.equal(requests.length, 4) + + function checkAndRespond(request, key, value) { + t.equal(key, request.key.toString()) + t.equal(constants.OP_GETKQ, request.header.opcode) + + dummyServer.respond({ + header: { + status: 0, + opaque: request.header.opaque, + opcode: request.header.opcode, + }, + key: key, + val: value, + extras: "flagshere", + }) + } + checkAndRespond(requests[0], "hello1", "world1") + dummyServer.error({ name: "ErrorName", message: "This is an expected error." }) + } + + const client = makeClient([dummyServer]) + const assertor = function (err) { + t.notEqual(null, err) + t.equal("This is an expected error.", err.message) + } + client.getMulti(["hello1", "hello2", "hello3"], assertor) + testAllCallbacksEmpty(t, dummyServer) + + return client.getMulti(["hello1", "hello2", "hello3"]).catch(function (err) { + assertor(err) + return true + }) +}) + +test("SetSuccessful", function (t) { + let n = 0 + const dummyServer = makeDummyServer("dummyServer") + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf) + t.equal("hello", request.key.toString()) + t.equal("world", request.val.toString()) + n += 1 + dummyServer.respond({ + header: { status: 0, opaque: request.header.opaque }, + }) + } + + const client = makeClient([dummyServer]) + const assertor = function (err, val) { + t.equal(true, val) + t.equal(null, err) + t.equal(1, n, "Ensure set is called") + } + client.set("hello", "world", {}, assertor) + n = 0 + return client.set("hello", "world", {}).then(function (success) { + assertor(null, success) + }) +}) + +test("SetSuccessfulWithoutOption", function (t) { + let n = 0 + const dummyServer = makeDummyServer("dummyServer") + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf) + t.equal("hello", request.key.toString()) + t.equal("world", request.val.toString()) + n += 1 + dummyServer.respond({ + header: { status: 0, opaque: request.header.opaque }, + }) + } + + const client = makeClient([dummyServer]) + client.set("hello", "world", {}, function (err, val) { + t.equal(true, val) + t.equal(null, err) + t.equal(1, n, "Ensure set is called") + t.end() + }) +}) + +test("SetPromiseWithoutOption", function (t) { + let n = 0 + const dummyServer = makeDummyServer("dummyServer") + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf) + t.equal("hello", request.key.toString()) + t.equal("world", request.val.toString()) + n += 1 + dummyServer.respond({ + header: { status: 0, opaque: request.header.opaque }, + }) + } + + const client = makeClient([dummyServer]) + return client.set("hello", "world").then(function (val) { + t.equal(true, val) + t.equal(1, n, "Ensure set is called") + t.end() + }) +}) + +test("SetWithExpiration", function (t) { + let n = 0 + const dummyServer = makeDummyServer("dummyServer") + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf) + t.equal("hello", request.key.toString()) + t.equal("world", request.val.toString()) + t.equal("\0\0\0\0\0\0\x04\0", request.extras.toString()) + n += 1 + dummyServer.respond({ + header: { status: 0, opaque: request.header.opaque }, + }) + } + + const client = makeClient([dummyServer], { expires: 1024 }) + client.set("hello", "world", {}, function (err, val) { + t.equal(null, err) + t.equal(true, val) + t.equal(1, n, "Ensure set is called") + t.end() + }) +}) + +test("SetUnsuccessful", function (t) { + let n = 0 + const dummyServer = makeDummyServer("dummyServer") + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf) + t.equal("hello", request.key.toString()) + t.equal("world", request.val.toString()) + n += 1 + dummyServer.respond({ + header: { status: 3, opaque: request.header.opaque }, + }) + } + + const client = makeClient([dummyServer]) + const assertor = function (err, val) { + t.equal(null, val) + t.equal("MemJS SET: " + errors[3], err.message) + t.equal(1, n, "Ensure set is called") + } + client.set("hello", "world", {}, assertor) + n = 0 + return client.set("hello", "world", {}).catch(function (err) { + assertor(err, null) + }) +}) + +test("SetError", function (t) { + let n = 0 + const dummyServer = makeDummyServer("dummyServer") + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf) + t.equal("hello", request.key.toString()) + t.equal("world", request.val.toString()) + n += 1 + dummyServer.error({ name: "ErrorName", message: "This is an expected error." }) + } + + const client = makeClient([dummyServer]) + client.set("hello", "world", {}, function (err, val) { + t.notEqual(null, err) + t.equal("This is an expected error.", err.message) + t.equal(null, val) + t.equal(2, n, "Ensure set is retried once") + t.end() + }) +}) + +test("SetError", function (t) { + let n = 0 + const dummyServer = makeDummyServer("dummyServer") + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf) + t.equal("hello", request.key.toString()) + t.equal("world", request.val.toString()) + setTimeout(function () { + n += 1 + dummyServer.error({ name: "ErrorName", message: "This is an expected error." }) + }, 100) + } + + const client = makeClient([dummyServer], { retries: 2 }) + client.set("hello", "world", {}, function (err /*, val */) { + t.equal(2, n, "Ensure set is retried once") + t.ok(err, "Ensure callback called with error") + t.equal("This is an expected error.", err.message) + t.end() + }) +}) + +test("SetErrorConcurrent", function (t) { + let n = 0 + let callbn1 = 0 + let callbn2 = 0 + const dummyServer = makeDummyServer("dummyServer") + dummyServer.write = function (/* requestBuf */) { + n += 1 + dummyServer.error({ name: "ErrorName", message: "This is an expected error." }) + } + + const client = makeClient([dummyServer], { retries: 2 }) + client.set("hello", "world", {}, function (err /*, val */) { + t.ok(err, "Ensure callback called with error") + t.equal("This is an expected error.", err.message) + callbn1 += 1 + done() + }) + + client.set("foo", "bar", {}, function (err /*, val */) { + t.ok(err, "Ensure callback called with error") + t.equal("This is an expected error.", err.message) + callbn2 += 1 + done() + }) + + const done = (function () { + let called = 0 + return function () { + called += 1 + if (called < 2) return + t.equal(1, callbn1, "Ensure callback 1 is called once") + t.equal(1, callbn2, "Ensure callback 2 is called once") + t.equal(4, n, "Ensure error sent twice for each set call") + t.end() + } + })() +}) + +test("SetUnicode", function (t) { + let n = 0 + const dummyServer = makeDummyServer("dummyServer") + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf) + t.equal("hello", request.key.toString()) + t.equal("éééoào", request.val.toString()) + n += 1 + dummyServer.respond({ + header: { status: 0, opaque: request.header.opaque }, + }) + } + + const client = makeClient([dummyServer]) + client.set("hello", "éééoào", {}, function (err, val) { + t.equal(true, val) + t.equal(1, n, "Ensure set is called") + t.end() + }) +}) + +test("SetSerialize", function (t) { + let n = 0 + let sn = 0 + const dummyServer = makeDummyServer("dummyServer") + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf) + t.equal("hello", request.key.toString()) + t.equal("serialized", request.val.toString()) + n += 1 + dummyServer.respond({ + header: { status: 3, opaque: request.header.opaque }, + }) + } + + const client = makeClient([dummyServer], { + serializer: { + serialize: function (opcode, value, extras) { + sn += 1 + return { value: "serialized", extras: extras } + }, + deserialize: function (opcode, value, extras) { + return { value: value, extras: extras } + }, + }, + }) + const assertor = function (err, val) { + t.equal(null, val) + t.equal("MemJS SET: " + errors[3], err.message) + t.equal(1, n, "Ensure set is called") + t.equal(1, sn, "Ensure serialization is called once") + } + client.set("hello", "world", {}, assertor) + n = 0 + sn = 0 + return client.set("hello", "world", {}).catch(function (err) { + assertor(err, null) + }) +}) + +test("AddSuccessful", function (t) { + let n = 0 + const dummyServer = makeDummyServer("dummyServer") + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf) + t.equal("hello", request.key.toString()) + t.equal("world", request.val.toString()) + t.equal("0000000000000400", request.extras.toString("hex")) + n += 1 + dummyServer.respond({ + header: { status: 0, opaque: request.header.opaque }, + }) + } + + const client = makeClient([dummyServer], { expires: 1024 }) + const assertor = function (err, val) { + t.equal(null, err) + t.equal(true, val) + t.equal(1, n, "Ensure add is called") + } + client.add("hello", "world", {}, assertor) + n = 0 + return client.add("hello", "world", {}).then(function (success) { + assertor(null, success) + }) +}) + +test("AddSuccessfulWithoutOption", function (t) { + let n = 0 + const dummyServer = makeDummyServer("dummyServer") + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf) + t.equal("hello", request.key.toString()) + t.equal("world", request.val.toString()) + t.equal("0000000000000400", request.extras.toString("hex")) + n += 1 + dummyServer.respond({ + header: { status: 0, opaque: request.header.opaque }, + }) + } + + const client = makeClient([dummyServer], { expires: 1024 }) + client.add("hello", "world", {}, function (err, val) { + t.equal(null, err) + t.equal(true, val) + t.equal(1, n, "Ensure add is called") + t.end() + }) +}) + +test("AddKeyExists", function (t) { + let n = 0 + const dummyServer = makeDummyServer("dummyServer") + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf) + t.equal("hello", request.key.toString()) + t.equal("world", request.val.toString()) + n += 1 + dummyServer.respond({ + header: { status: 2, opaque: request.header.opaque }, + }) + } + + const client = makeClient([dummyServer]) + client.add("hello", "world", {}, function (err, val) { + t.equal(null, err) + t.equal(false, val) + t.equal(1, n, "Ensure add is called") + t.end() + }) +}) + +test("AddSerializer", function (t) { + let n = 0 + let sn = 0 + const dummyServer = makeDummyServer("dummyServer") + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf) + t.equal("hello", request.key.toString()) + t.equal("serialized", request.val.toString()) + t.equal("0000000100000400", request.extras.toString("hex")) + n += 1 + dummyServer.respond({ + header: { status: 0, opaque: request.header.opaque }, + }) + } + + const client = makeClient([dummyServer], { + expires: 1024, + serializer: { + serialize: function (opcode, value, extras) { + sn += 1 + if (Buffer.isBuffer(extras)) { + extras.writeUInt32BE(1, 0) + } + return { value: "serialized", extras: extras } + }, + deserialize: function (opcode, value, extras) { + return { value: value, extras: extras } + }, + }, + }) + const assertor = function (err, val) { + t.equal(null, err) + t.equal(true, val) + t.equal(1, n, "Ensure add is called") + t.equal(1, sn, "Ensure serialization is called once") + } + client.add("hello", "world", {}, assertor) + n = 0 + sn = 0 + return client.add("hello", "world", {}).then(function (success) { + assertor(null, success) + }) +}) + +test("ReplaceSuccessful", function (t) { + let n = 0 + const dummyServer = makeDummyServer("dummyServer") + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf) + t.equal("hello", request.key.toString()) + t.equal("world", request.val.toString()) + t.equal("\0\0\0\0\0\0\x04\0", request.extras.toString()) + n += 1 + dummyServer.respond({ + header: { status: 0, opaque: request.header.opaque }, + }) + } + + const client = makeClient([dummyServer], { expires: 1024 }) + const assertor = function (err, val) { + t.equal(null, err) + t.equal(true, val) + t.equal(1, n, "Ensure replace is called") + } + client.replace("hello", "world", {}, assertor) + n = 0 + const replaceP = client.replace("hello", "world", {}) + if (!replaceP) { + return t.true(replaceP) + } else { + return replaceP.then(function (success) { + assertor(null, success) + }) + } +}) + +test("ReplaceSuccessfulWithoutOption", function (t) { + let n = 0 + const dummyServer = makeDummyServer("dummyServer") + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf) + t.equal("hello", request.key.toString()) + t.equal("world", request.val.toString()) + t.equal("\0\0\0\0\0\0\x04\0", request.extras.toString()) + n += 1 + dummyServer.respond({ + header: { status: 0, opaque: request.header.opaque }, + }) + } + + const client = makeClient([dummyServer], { expires: 1024 }) + client.replace("hello", "world", {}, function (err, val) { + t.equal(null, err) + t.equal(true, val) + t.equal(1, n, "Ensure replace is called") + t.end() + }) +}) + +test("ReplaceKeyDNE", function (t) { + let n = 0 + const dummyServer = makeDummyServer("dummyServer") + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf) + t.equal("hello", request.key.toString()) + t.equal("world", request.val.toString()) + n += 1 + dummyServer.respond({ + header: { status: 1, opaque: request.header.opaque }, + }) + } + + const client = makeClient([dummyServer]) + client.replace("hello", "world", {}, function (err, val) { + t.equal(null, err) + t.equal(false, val) + t.equal(1, n, "Ensure replace is called") + t.end() + }) +}) + +test("DeleteSuccessful", function (t) { + let n = 0 + const dummyServer = makeDummyServer("dummyServer") + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf) + t.equal("hello", request.key.toString()) + n += 1 + dummyServer.respond({ + header: { status: 0, opaque: request.header.opaque }, + }) + } + + const client = makeClient([dummyServer]) + const assertor = function (err, val) { + t.equal(null, err) + t.equal(true, val) + t.equal(1, n, "Ensure delete is called") + } + client.delete("hello", assertor) + n = 0 + return client.delete("hello").then(function (success) { + assertor(null, success) + }) +}) + +test("DeleteKeyDNE", function (t) { + let n = 0 + const dummyServer = makeDummyServer("dummyServer") + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf) + t.equal("hello", request.key.toString()) + n += 1 + dummyServer.respond({ + header: { status: 1, opaque: request.header.opaque }, + }) + } + + const client = makeClient([dummyServer]) + client.delete("hello", function (err, val) { + t.equal(null, err) + t.equal(false, val) + t.equal(1, n, "Ensure delete is called") + t.end() + }) +}) + +test("Flush", function (t) { + let n = 0 + const dummyServer = makeDummyServer("dummyServer") + dummyServer.host = "example.com" + dummyServer.port = 1234 + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf) + t.equal(0x08, request.header.opcode) + n += 1 + dummyServer.respond({ + header: { status: 1, opaque: request.header.opaque }, + }) + } + + const client = makeClient([dummyServer, dummyServer]) + const assertor = function (err, results) { + t.equal(null, err) + t.equal(true, results["example.com:1234"]) + t.equal(2, n, "Ensure flush is called for each server") + } + client.flush(assertor) + n = 0 + return client.flush().then(function (results) { + assertor(null, results) + }) +}) + +test("Stats", function (t) { + let n = 0 + const dummyServer = makeDummyServer("dummyServer") + dummyServer.host = "myhostname" + dummyServer.port = 5544 + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf) + t.equal(0x10, request.header.opcode) + n += 1 + dummyServer.respond({ + header: { status: 0, totalBodyLength: 9, opaque: request.header.opaque }, + key: "bytes", + val: "1432", + }) + dummyServer.respond({ + header: { status: 0, totalBodyLength: 9, opaque: request.header.opaque }, + key: "count", + val: "5432", + }) + dummyServer.respond({ + header: { status: 0, totalBodyLength: 0, opaque: request.header.opaque }, + }) + } + + const client = makeClient([dummyServer]) + client.stats(function (err, server, stats) { + t.equal(null, err) + t.equal("1432", stats.bytes) + t.equal("5432", stats.count) + t.equal("myhostname:5544", server) + t.equal(1, n, "Ensure stats is called") + t.end() + }) +}) + +test("IncrementSuccessful", function (t) { + let n = 0 + let callbn = 0 + const dummyServer = makeDummyServer("dummyServer") + + const expectedExtras = [ + "\0\0\0\0\0\0\0\x05\0\0\0\0\0\0\0\0\0\0\0\0", + "\0\0\0\0\0\0\0\x05\0\0\0\0\0\0\0\x03\0\0\0\0", + ] + + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf) + t.equal(5, request.header.opcode) + t.equal("number-increment-test", request.key.toString()) + t.equal("", request.val.toString()) + t.equal(expectedExtras[n], request.extras.toString()) + n += 1 + process.nextTick(function () { + const value = Buffer.alloc(8) + value.writeUInt32BE(request.header.opcode + 1, 4) + value.writeUInt32BE(0, 0) + dummyServer.respond({ + header: { status: 0, opaque: request.header.opaque }, + val: value, + }) + }) + } + + const client = makeClient([dummyServer]) + client.increment( + "number-increment-test", + 5, + {}, + function (err, success, val) { + callbn += 1 + t.equal(true, success) + t.equal(6, val) + t.equal(null, err) + done() + } + ) + + client.increment( + "number-increment-test", + 5, + { initial: 3 }, + function (err, success, val) { + callbn += 1 + t.equal(true, success) + t.equal(6, val) + t.equal(null, err) + done() + } + ) + + const done = (function () { + let called = 0 + return function () { + called += 1 + if (called < 2) return + t.equal(2, n, "Ensure increment is called twice") + t.equal(2, callbn, "Ensure callback is called twice") + t.end() + } + })() +}) + +test("DecrementSuccessful", function (t) { + let n = 0 + const dummyServer = makeDummyServer("dummyServer") + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf) + t.equal(6, request.header.opcode) + t.equal("number-decrement-test", request.key.toString()) + t.equal("", request.val.toString()) + t.equal( + "\0\0\0\0\0\0\0\x05\0\0\0\0\0\0\0\0\0\0\0\0", + request.extras.toString() + ) + n += 1 + process.nextTick(function () { + const value = Buffer.alloc(8) + value.writeUInt32BE(request.header.opcode, 4) + value.writeUInt32BE(0, 0) + dummyServer.respond({ + header: { status: 0, opaque: request.header.opaque }, + val: value, + }) + }) + } + + const client = makeClient([dummyServer]) + client.decrement( + "number-decrement-test", + 5, + {}, + function (err, success, val) { + t.equal(true, success) + t.equal(6, val) + t.equal(null, err) + t.equal(1, n, "Ensure decr is called") + t.end() + } + ) +}) + +test("DecrementSuccessfulWithoutOption", function (t) { + let n = 0 + const dummyServer = makeDummyServer("dummyServer") + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf) + t.equal(6, request.header.opcode) + t.equal("number-decrement-test", request.key.toString()) + t.equal("", request.val.toString()) + t.equal( + "\0\0\0\0\0\0\0\x05\0\0\0\0\0\0\0\0\0\0\0\0", + request.extras.toString() + ) + n += 1 + process.nextTick(function () { + const value = Buffer.alloc(8) + value.writeUInt32BE(request.header.opcode, 4) + value.writeUInt32BE(0, 0) + dummyServer.respond({ + header: { status: 0, opaque: request.header.opaque }, + val: value, + }) + }) + } + + const client = makeClient([dummyServer]) + client.decrement("number-decrement-test", 5, {}, function (err, success, val) { + t.equal(true, success) + t.equal(6, val) + t.equal(null, err) + t.equal(1, n, "Ensure decr is called") + t.end() + }) +}) + +test("AppendSuccessful", function (t) { + let n = 0 + const dummyServer = makeDummyServer("dummyServer") + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf) + t.equal("hello", request.key.toString()) + t.equal("world", request.val.toString()) + n += 1 + dummyServer.respond({ + header: { status: 0, opaque: request.header.opaque }, + }) + } + + const client = makeClient([dummyServer], { expires: 1024 }) + client.append("hello", "world", function (err, val) { + t.equal(null, err) + t.equal(true, val) + t.equal(1, n, "Ensure append is called") + t.end() + }) +}) + +test("AppendKeyDNE", function (t) { + let n = 0 + const dummyServer = makeDummyServer("dummyServer") + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf) + t.equal("hello", request.key.toString()) + t.equal("world", request.val.toString()) + n += 1 + dummyServer.respond({ + header: { status: 1, opaque: request.header.opaque }, + }) + } + + const client = makeClient([dummyServer]) + client.append("hello", "world", function (err, val) { + t.equal(null, err) + t.equal(false, val) + t.equal(1, n, "Ensure append is called") + t.end() + }) +}) + +test("PrependSuccessful", function (t) { + let n = 0 + const dummyServer = makeDummyServer("dummyServer") + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf) + t.equal("hello", request.key.toString()) + t.equal("world", request.val.toString()) + n += 1 + dummyServer.respond({ + header: { status: 0, opaque: request.header.opaque }, + }) + } + + const client = makeClient([dummyServer], { expires: 1024 }) + client.prepend("hello", "world", function (err, val) { + t.equal(null, err) + t.equal(true, val) + t.equal(1, n, "Ensure prepend is called") + t.end() + }) +}) + +test("PrependKeyDNE", function (t) { + let n = 0 + const dummyServer = makeDummyServer("dummyServer") + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf) + t.equal("hello", request.key.toString()) + t.equal("world", request.val.toString()) + n += 1 + dummyServer.respond({ + header: { status: 1, opaque: request.header.opaque }, + }) + } + + const client = makeClient([dummyServer]) + client.prepend("hello", "world", function (err, val) { + t.equal(null, err) + t.equal(false, val) + t.equal(1, n, "Ensure prepend is called") + t.end() + }) +}) + +test("TouchSuccessful", function (t) { + let n = 0 + const dummyServer = makeDummyServer("dummyServer") + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf) + t.equal("hello", request.key.toString()) + t.equal("", request.val.toString()) + t.equal("\0\0\x04\0", request.extras.toString()) + n += 1 + dummyServer.respond({ + header: { status: 0, opaque: request.header.opaque }, + }) + } + + const client = makeClient([dummyServer]) + client.touch("hello", 1024, function (err, val) { + t.equal(null, err) + t.equal(true, val) + t.equal(1, n, "Ensure touch is called") + t.end() + }) +}) + +test("TouchKeyDNE", function (t) { + let n = 0 + const dummyServer = makeDummyServer("dummyServer") + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf) + t.equal("hello", request.key.toString()) + t.equal("", request.val.toString()) + t.equal("\0\0\x04\0", request.extras.toString()) + n += 1 + dummyServer.respond({ + header: { status: 1, opaque: request.header.opaque }, + }) + } + + const client = makeClient([dummyServer]) + client.touch("hello", 1024, function (err, val) { + t.equal(null, err) + t.equal(false, val) + t.equal(1, n, "Ensure ptouch is called") + t.end() + }) +}) + +// test('Failover', function(t) { +// let n1 = 0; +// let n2 = 0; +// const dummyServer1 = makeDummyServer('dummyServer'); +// dummyServer1.write = function(/* requestBuf*/) { +// n1 += 1; +// dummyServer1.error(new Error('connection failure')); +// }; +// const dummyServer2 = makeDummyServer('dummyServer'); +// dummyServer2.write = function(requestBuf) { +// n2 += 1; +// const request = parseMessage(requestBuf); +// dummyServer2.respond({header: {status: 0, opaque: request.header.opaque}}); +// }; + +// const client = makeClient([dummyServer1, dummyServer2], {failover: true}); +// client.get('\0', function(err/*, val */){ +// t.equal(null, err); +// t.equal(2, n1); +// t.equal(1, n2); +// t.end(); +// }); + +// }); + +test("Very Large Client Seq", function (t) { + let n = 0 + const dummyServer = makeDummyServer("dummyServer") + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf) + t.equal("hello", request.key.toString()) + t.equal("world", request.val.toString()) + t.equal("0000000000000400", request.extras.toString("hex")) + n += 1 + dummyServer.respond({ + header: { status: 0, opaque: request.header.opaque }, + }) + } + + const client = makeClient([dummyServer], { expires: 1024 }) + client.seq = Math.pow(2, 33) + const assertor = function (err, val) { + t.equal(null, err) + t.equal(true, val) + t.equal(1, n, "Ensure add is called") + } + client.add("hello", "world", {}, assertor) + n = 0 + return client.add("hello", "world", {}).then(function (success) { + assertor(null, success) + }) +}) + +const makeDummyVersionServer = (t, serverKey, version) => { + const dummyServer = makeDummyServer(serverKey) + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf) + t.deepEqual(Buffer.from(""), request.key) + dummyServer.respond({ + header: { status: 0, opaque: request.header.opaque }, + val: version, + extras: "flagshere", + }) + } + return dummyServer +} + +test("VersionSuccessful", function (t) { + let n = 0 + + const dummyServer = makeDummyVersionServer(t, "dummyServer", "1.3.1") + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf) + t.deepEqual(Buffer.from(""), request.key) + n += 1 + dummyServer.respond({ + header: { status: 0, opaque: request.header.opaque }, + val: "1.3.1", + extras: "flagshere", + }) + } + + const client = makeClient([dummyServer]) + const assertor = function (err: Error | null, val: any, flags: string) { + t.equal("1.3.1", val) + t.equal("flagshere", flags) + t.equal(null, err) + t.equal(n, 1, "Ensure version is called") + } + + client.version(assertor) + n = 0 + + return client.version().then(function (res) { + assertor(null, res.value, res.flags) + }) +}) + +tap.only("VersionError", function (t) { + const dummyServer = makeDummyServer("dummyServer") + dummyServer.write = function () { + dummyServer.error({ name: "ErrorName", message: "This is an expected error." }) + } + + const client = makeClient([dummyServer]) + const assertor = function (err) { + t.notEqual(null, err) + t.equal("This is an expected error.", err.message) + } + + client.version(assertor) + return client.version().catch(function (err) { + assertor(err) + return true + }) +}) + +test("VersionAllSuccessful", function (t) { + const dummyServer1 = makeDummyVersionServer(t, "dummyServer1", "1.0.0") + const dummyServer2 = makeDummyVersionServer(t, "dummyServer2", "2.0.0") + const dummyServer3 = makeDummyVersionServer(t, "dummyServer3", "3.0.0") + + const client = makeClient([dummyServer1, dummyServer2, dummyServer3]) + const assertor = function (err, val) { + t.deepEqual( + { + "dummyServer1:undefined": "1.0.0", + "dummyServer2:undefined": "2.0.0", + "dummyServer3:undefined": "3.0.0", + }, + val + ) + t.equal(null, err) + } + + client.versionAll(assertor) + + return client.versionAll().then(function (res) { + assertor(null, res.values) + }) +}) + +tap.only("VersionAllSomeFailed", function (t) { + const dummyServer1 = makeDummyVersionServer(t, "dummyServer1", "1.0.0") + const dummyServer2 = makeDummyVersionServer(t, "dummyServer2", "2.0.0") + dummyServer2.write = function () { + dummyServer2.error({ name: "ErrorName", message: "This is an expected error." }) + } + const dummyServer3 = makeDummyVersionServer(t, "dummyServer3", "3.0.0") + + const client = makeClient([dummyServer1, dummyServer2, dummyServer3]) + const assertor = function (err) { + t.notEqual(null, err) + t.equal("This is an expected error.", err.message) + } + + client.versionAll(assertor) + + return client.versionAll().catch(function (err) { + assertor(err) + }) +}) diff --git a/test/header_test.js b/test/header_test.js index ab4bd04..802f2ae 100644 --- a/test/header_test.js +++ b/test/header_test.js @@ -1,9 +1,9 @@ -var test = require('tap').test; -var header = require('../lib/memjs/header'); +const test = require('tap').test; +const header = require('../lib/memjs/header'); test('ParseHeaderResponse', function(t) { - var headerBuf = Buffer.from([0x81, 1, 7, 0, 4, 3, 0, 1, 0, 0, 0, 9, 0, 0, 0, 0, 0x0a, 0, 0, 0, 0, 0, 0, 0]); - var responseHeader = header.fromBuffer(headerBuf); + const headerBuf = Buffer.from([0x81, 1, 7, 0, 4, 3, 0, 1, 0, 0, 0, 9, 0, 0, 0, 0, 0x0a, 0, 0, 0, 0, 0, 0, 0]); + const responseHeader = header.fromBuffer(headerBuf); t.equal(0x81, responseHeader.magic); t.equal(1, responseHeader.opcode); t.equal(0x0700, responseHeader.keyLength); @@ -17,7 +17,7 @@ test('ParseHeaderResponse', function(t) { }); test('DumpHeader', function(t) { - var responseHeader = { + const responseHeader = { magic: 0x81, opcode: 1, keyLength: 0x700, @@ -28,13 +28,13 @@ test('DumpHeader', function(t) { opaque: 0, cas: Buffer.from([0x0a, 0, 0, 0, 0, 0, 0, 0]) }; - var expected = Buffer.from([0x81, 1, 7, 0, 4, 0, 0, 1, 0, 0, 0, 9, 0, 0, 0, 0, 0x0a, 0, 0, 0, 0, 0, 0, 0]); + const expected = Buffer.from([0x81, 1, 7, 0, 4, 0, 0, 1, 0, 0, 0, 9, 0, 0, 0, 0, 0x0a, 0, 0, 0, 0, 0, 0, 0]); t.equal(header.toBuffer(responseHeader).toString(), expected.toString()); t.end(); }); test('DumpHeaderNoCas', function(t) { - var responseHeader = { + const responseHeader = { magic: 0x81, opcode: 0, keyLength: 0x0, @@ -44,7 +44,7 @@ test('DumpHeaderNoCas', function(t) { totalBodyLength: 0, opaque: 0 }; - var expected = Buffer.from([0x81, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); + const expected = Buffer.from([0x81, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); t.equal(header.toBuffer(responseHeader).toString(), expected.toString()); t.end(); }); diff --git a/test/server_test.js b/test/server_test.js index f8d7eca..c0d5fd1 100644 --- a/test/server_test.js +++ b/test/server_test.js @@ -1,15 +1,15 @@ -var test = require('tap').test; -var MemJS = require('../'); -var makeRequestBuffer = require('../lib/memjs/utils').makeRequestBuffer; +const test = require('tap').test; +const MemJS = require('../'); +const makeRequestBuffer = require('../lib/memjs/utils').makeRequestBuffer; test('AuthListMechanisms', function(t) { - var expectedBuf = makeRequestBuffer(0x20, '', '', ''); - var dummySocket = { + const expectedBuf = makeRequestBuffer(0x20, '', '', ''); + const dummySocket = { write: function(buf) { t.equal(expectedBuf.toString(), buf.toString()); } }; - var server = new MemJS.Server('test.example.com', 11211); + const server = new MemJS.Server('test.example.com', 11211); server._socket = dummySocket; server.listSasl(); t.end(); @@ -17,7 +17,7 @@ test('AuthListMechanisms', function(t) { test('ResponseHandler with authentication error', function(t) { - var server = new MemJS.Server('localhost', 11211); + const server = new MemJS.Server('localhost', 11211); server.onError('test', function(err) { t.equal('Memcached server authentication failed!', err.message); @@ -25,7 +25,7 @@ test('ResponseHandler with authentication error', function(t) { // Simulate a memcached server response, with an authentication error // No SASL configured, wrong credentials, ... - var responseBuf = makeRequestBuffer(0x21, '', '', ''); + const responseBuf = makeRequestBuffer(0x21, '', '', ''); // Override status // 0x20 = Authentication required / Not Successful responseBuf.writeUInt16BE(0x20, 6); @@ -36,20 +36,20 @@ test('ResponseHandler with authentication error', function(t) { }); test('Authenticate', function(t) { - var expectedBuf = makeRequestBuffer(0x21, 'PLAIN', '', '\0user1\0password'); - var dummySocket = { + const expectedBuf = makeRequestBuffer(0x21, 'PLAIN', '', '\0user1\0password'); + const dummySocket = { write: function(buf) { t.equal(expectedBuf.toString(), buf.toString()); } }; - var server = new MemJS.Server('test.example.com', 11211, 'user1', 'password', {}); + const server = new MemJS.Server('test.example.com', 11211, 'user1', 'password', {}); server._socket = dummySocket; server.saslAuth(); t.end(); }); test('SetSaslCredentials', function(t) { - var server; + let server; server = new MemJS.Server('test.example.com', 11211, undefined, undefined, {username: 'user1', password: 'password'}); t.equal('user1', server.username); @@ -69,8 +69,8 @@ test('SetSaslCredentials', function(t) { }); test('ResponseCallbackOrdering', function(t) { - var server = new MemJS.Server(); - var callbacksCalled = 0; + const server = new MemJS.Server(); + let callbacksCalled = 0; server.onResponse(1, function() { t.equal(0, callbacksCalled); diff --git a/test/utils_test.js b/test/utils_test.js index a6f79bc..b7e0438 100644 --- a/test/utils_test.js +++ b/test/utils_test.js @@ -1,29 +1,29 @@ -var test = require('tap').test; -var utils = require('../lib/memjs/utils'); +const test = require('tap').test; +const utils = require('../lib/memjs/utils'); test('MergePresereParameter', function(t) { - var result = utils.merge({}, { retries: 2 }); + const result = utils.merge({}, { retries: 2 }); t.equal(2, result.retries); t.end(); }); test('MergePresereParameterWhenZero', function(t) { - var result = utils.merge({ retries: 0 }, { retries: 2 }); + const result = utils.merge({ retries: 0 }, { retries: 2 }); t.equal(0, result.retries); t.end(); }); test('MergeDontPresereParameterWhenUndefinedOrNull', function(t) { - var result = utils.merge({ retries: undefined }, { retries: 2 }); + const result = utils.merge({ retries: undefined }, { retries: 2 }); t.equal(2, result.retries); - var result2 = utils.merge({ retries: null }, { retries: 2 }); + const result2 = utils.merge({ retries: null }, { retries: 2 }); t.equal(2, result2.retries); t.end(); }); test('MakeAmountInitialAndExpiration', function(t) { - var extras, buf, fixture; + let extras, buf, fixture; extras = utils.makeAmountInitialAndExpiration(1, 1, 1); fixture = Buffer.from('0000000000000001000000000000000100000001', 'hex'); t.equal(20, extras.length); @@ -43,8 +43,8 @@ test('MakeAmountInitialAndExpiration', function(t) { }); exports.testMakeRequestBufferExtrasLength = function(t) { - var extras = utils.makeAmountInitialAndExpiration(255, 1, 1); - var buf = utils.makeRequestBuffer(0, 'test', extras, 1, 0); + const extras = utils.makeAmountInitialAndExpiration(255, 1, 1); + const buf = utils.makeRequestBuffer(0, 'test', extras, 1, 0); t.equal(20, buf[4]); t.end(); }; From 42ad49da4ca8bf1c4acd73236b4ff8189c13409f Mon Sep 17 00:00:00 2001 From: David Blackman Date: Sun, 11 Apr 2021 21:47:34 -0400 Subject: [PATCH 27/79] TSify tests (poorly?) --- test/client_test.ts | 131 ++++++++++++++++++++++---------------------- tsconfig.json | 2 +- 2 files changed, 67 insertions(+), 66 deletions(-) diff --git a/test/client_test.ts b/test/client_test.ts index 8aa906c..0203505 100644 --- a/test/client_test.ts +++ b/test/client_test.ts @@ -1,16 +1,18 @@ import tap from 'tap' const test = tap.test -const errors = require("../lib/memjs/protocol").errors -import MemJS = require("../") -import constants = require("../lib/memjs/constants") -import { noopSerializer } from "../lib/memjs/noop-serializer" -import { Header } from "../lib/memjs/header" -import type { GivenClientOptions } from "../lib/memjs/memjs" -import * as Utils from "../lib/memjs/utils" -import { MaybeBuffer } from "../lib/memjs/utils" - -function testAllCallbacksEmpty(t: any, server: MemJS.Server) { +const errors = require("../src/memjs/protocol").errors +import MemJS = require("../src") +import constants = require("../src/memjs/constants") +import { noopSerializer } from "../src/memjs/noop-serializer" +import { Header } from "../src/memjs/header" +import type { GivenClientOptions } from "../src/memjs/memjs" +import * as Utils from "../src/memjs/utils" +import { MaybeBuffer } from "../src/memjs/utils" + +type TapType = any + +function testAllCallbacksEmpty(t: TapType, server: MemJS.Server) { t.deepEqual(Object.keys(server.responseCallbacks).length, 0) t.deepEqual(Object.keys(server.errorCallbacks).length, 0) @@ -57,7 +59,7 @@ test("GetSuccessful", function (t) { } const client = makeClient([dummyServer]) - const assertor = function (err: Error | null, val: string | MaybeBuffer, flags: string) { + const assertor = function (err: Error | null, val: string | MaybeBuffer | null, flags: string) { t.equal("world", val) t.equal("flagshere", flags) t.equal(null, err) @@ -83,9 +85,8 @@ test("GetNotFound", function (t) { } const client = makeClient([dummyServer]) - const assertor = function (val, flags) { + const assertor = function (err: Error | null, val: string | MaybeBuffer | null) { t.equal(null, val) - t.equal(null, flags) t.equal(1, n, "Ensure get is called") } client.get("hello", assertor) @@ -122,7 +123,7 @@ test("GetSerializer", function (t) { }, }, }) - const assertor = function (err: Error | null, val: string | MaybeBuffer, flags: string) { + const assertor = function (err: Error | null, val: string | Buffer | null, flags: string) { t.equal("deserialized", val) t.equal("flagshere", flags) t.equal(null, err) @@ -197,13 +198,13 @@ tap.only("GetMultiSuccessful_SingleBackend", function (t) { }) }) -function makeDummyMultiGetServerResponder(t, responseMap, serverName?: string) { +function makeDummyMultiGetServerResponder(t: TapType, responseMap: Record, serverName?: string) { const server = makeDummyServer(serverName || "dummyServer") - const responder = function (requestBuf) { + const responder = function (requestBuf: Buffer) { const requests = Utils.parseMessages(requestBuf) t.equal(requests.length, Object.keys(responseMap).length + 1) - function checkAndRespond(request, key, value) { + function checkAndRespond(request: Utils.Message, key: string, value: string | undefined) { t.equal(constants.OP_GETKQ, request.header.opcode) if (value !== undefined) { @@ -359,9 +360,9 @@ test("GetMultiError_MultiBackend", function (t) { const client = makeClient(servers) - const assertor = function (err) { + const assertor = function (err: Error | null) { t.notEqual(null, err) - t.equal("This is an expected error.", err.message) + t.equal("This is an expected error.", err?.message) } client.getMulti(["hello1", "hello2", "hello3", "hello4"], assertor) testAllCallbacksEmpty(t, dummyServer1) @@ -407,7 +408,7 @@ test("GetMultiError", function (t) { const requests = Utils.parseMessages(requestBuf) t.equal(requests.length, 4) - function checkAndRespond(request, key, value) { + function checkAndRespond(request: Utils.Message, key: string, value: string) { t.equal(key, request.key.toString()) t.equal(constants.OP_GETKQ, request.header.opcode) @@ -427,9 +428,9 @@ test("GetMultiError", function (t) { } const client = makeClient([dummyServer]) - const assertor = function (err) { + const assertor = function (err: Error | null) { t.notEqual(null, err) - t.equal("This is an expected error.", err.message) + t.equal("This is an expected error.", err?.message) } client.getMulti(["hello1", "hello2", "hello3"], assertor) testAllCallbacksEmpty(t, dummyServer) @@ -454,7 +455,7 @@ test("SetSuccessful", function (t) { } const client = makeClient([dummyServer]) - const assertor = function (err, val) { + const assertor = function (err: Error | null, val: boolean | null) { t.equal(true, val) t.equal(null, err) t.equal(1, n, "Ensure set is called") @@ -480,7 +481,7 @@ test("SetSuccessfulWithoutOption", function (t) { } const client = makeClient([dummyServer]) - client.set("hello", "world", {}, function (err, val) { + client.set("hello", "world", {}, function (err: Error | null, val) { t.equal(true, val) t.equal(null, err) t.equal(1, n, "Ensure set is called") @@ -524,7 +525,7 @@ test("SetWithExpiration", function (t) { } const client = makeClient([dummyServer], { expires: 1024 }) - client.set("hello", "world", {}, function (err, val) { + client.set("hello", "world", {}, function (err: Error | null, val) { t.equal(null, err) t.equal(true, val) t.equal(1, n, "Ensure set is called") @@ -546,9 +547,9 @@ test("SetUnsuccessful", function (t) { } const client = makeClient([dummyServer]) - const assertor = function (err, val) { + const assertor = function (err: Error | null, val: boolean | null) { t.equal(null, val) - t.equal("MemJS SET: " + errors[3], err.message) + t.equal("MemJS SET: " + errors[3], err?.message) t.equal(1, n, "Ensure set is called") } client.set("hello", "world", {}, assertor) @@ -570,9 +571,9 @@ test("SetError", function (t) { } const client = makeClient([dummyServer]) - client.set("hello", "world", {}, function (err, val) { + client.set("hello", "world", {}, function (err: Error | null, val) { t.notEqual(null, err) - t.equal("This is an expected error.", err.message) + t.equal("This is an expected error.", err?.message) t.equal(null, val) t.equal(2, n, "Ensure set is retried once") t.end() @@ -596,7 +597,7 @@ test("SetError", function (t) { client.set("hello", "world", {}, function (err /*, val */) { t.equal(2, n, "Ensure set is retried once") t.ok(err, "Ensure callback called with error") - t.equal("This is an expected error.", err.message) + t.equal("This is an expected error.", err?.message) t.end() }) }) @@ -614,14 +615,14 @@ test("SetErrorConcurrent", function (t) { const client = makeClient([dummyServer], { retries: 2 }) client.set("hello", "world", {}, function (err /*, val */) { t.ok(err, "Ensure callback called with error") - t.equal("This is an expected error.", err.message) + t.equal("This is an expected error.", err?.message) callbn1 += 1 done() }) client.set("foo", "bar", {}, function (err /*, val */) { t.ok(err, "Ensure callback called with error") - t.equal("This is an expected error.", err.message) + t.equal("This is an expected error.", err?.message) callbn2 += 1 done() }) @@ -653,7 +654,7 @@ test("SetUnicode", function (t) { } const client = makeClient([dummyServer]) - client.set("hello", "éééoào", {}, function (err, val) { + client.set("hello", "éééoào", {}, function (err: Error | null, val) { t.equal(true, val) t.equal(1, n, "Ensure set is called") t.end() @@ -685,9 +686,9 @@ test("SetSerialize", function (t) { }, }, }) - const assertor = function (err, val) { + const assertor = function (err: Error | null, val: boolean | null) { t.equal(null, val) - t.equal("MemJS SET: " + errors[3], err.message) + t.equal("MemJS SET: " + errors[3], err?.message) t.equal(1, n, "Ensure set is called") t.equal(1, sn, "Ensure serialization is called once") } @@ -714,7 +715,7 @@ test("AddSuccessful", function (t) { } const client = makeClient([dummyServer], { expires: 1024 }) - const assertor = function (err, val) { + const assertor = function (err: Error | null, val: boolean | null) { t.equal(null, err) t.equal(true, val) t.equal(1, n, "Ensure add is called") @@ -741,7 +742,7 @@ test("AddSuccessfulWithoutOption", function (t) { } const client = makeClient([dummyServer], { expires: 1024 }) - client.add("hello", "world", {}, function (err, val) { + client.add("hello", "world", {}, function (err: Error | null, val) { t.equal(null, err) t.equal(true, val) t.equal(1, n, "Ensure add is called") @@ -763,7 +764,7 @@ test("AddKeyExists", function (t) { } const client = makeClient([dummyServer]) - client.add("hello", "world", {}, function (err, val) { + client.add("hello", "world", {}, function (err: Error | null, val) { t.equal(null, err) t.equal(false, val) t.equal(1, n, "Ensure add is called") @@ -801,7 +802,7 @@ test("AddSerializer", function (t) { }, }, }) - const assertor = function (err, val) { + const assertor = function (err: Error | null, val: boolean | null) { t.equal(null, err) t.equal(true, val) t.equal(1, n, "Ensure add is called") @@ -830,7 +831,7 @@ test("ReplaceSuccessful", function (t) { } const client = makeClient([dummyServer], { expires: 1024 }) - const assertor = function (err, val) { + const assertor = function (err: Error | null, val: boolean | null) { t.equal(null, err) t.equal(true, val) t.equal(1, n, "Ensure replace is called") @@ -862,7 +863,7 @@ test("ReplaceSuccessfulWithoutOption", function (t) { } const client = makeClient([dummyServer], { expires: 1024 }) - client.replace("hello", "world", {}, function (err, val) { + client.replace("hello", "world", {}, function (err: Error | null, val) { t.equal(null, err) t.equal(true, val) t.equal(1, n, "Ensure replace is called") @@ -884,7 +885,7 @@ test("ReplaceKeyDNE", function (t) { } const client = makeClient([dummyServer]) - client.replace("hello", "world", {}, function (err, val) { + client.replace("hello", "world", {}, function (err: Error | null, val) { t.equal(null, err) t.equal(false, val) t.equal(1, n, "Ensure replace is called") @@ -905,7 +906,7 @@ test("DeleteSuccessful", function (t) { } const client = makeClient([dummyServer]) - const assertor = function (err, val) { + const assertor = function (err: Error | null, val: boolean | null) { t.equal(null, err) t.equal(true, val) t.equal(1, n, "Ensure delete is called") @@ -930,7 +931,7 @@ test("DeleteKeyDNE", function (t) { } const client = makeClient([dummyServer]) - client.delete("hello", function (err, val) { + client.delete("hello", function (err: Error | null, val) { t.equal(null, err) t.equal(false, val) t.equal(1, n, "Ensure delete is called") @@ -953,7 +954,7 @@ test("Flush", function (t) { } const client = makeClient([dummyServer, dummyServer]) - const assertor = function (err, results) { + const assertor = function (err: Error | null, results: Record) { t.equal(null, err) t.equal(true, results["example.com:1234"]) t.equal(2, n, "Ensure flush is called for each server") @@ -990,10 +991,10 @@ test("Stats", function (t) { } const client = makeClient([dummyServer]) - client.stats(function (err, server, stats) { + client.stats(function (err: Error | null, server, stats) { t.equal(null, err) - t.equal("1432", stats.bytes) - t.equal("5432", stats.count) + t.equal("1432", stats?.bytes) + t.equal("5432", stats?.count) t.equal("myhostname:5544", server) t.equal(1, n, "Ensure stats is called") t.end() @@ -1033,7 +1034,7 @@ test("IncrementSuccessful", function (t) { "number-increment-test", 5, {}, - function (err, success, val) { + function (err: Error | null, success, val) { callbn += 1 t.equal(true, success) t.equal(6, val) @@ -1046,7 +1047,7 @@ test("IncrementSuccessful", function (t) { "number-increment-test", 5, { initial: 3 }, - function (err, success, val) { + function (err: Error | null, success, val) { callbn += 1 t.equal(true, success) t.equal(6, val) @@ -1096,7 +1097,7 @@ test("DecrementSuccessful", function (t) { "number-decrement-test", 5, {}, - function (err, success, val) { + function (err: Error | null, success, val) { t.equal(true, success) t.equal(6, val) t.equal(null, err) @@ -1131,7 +1132,7 @@ test("DecrementSuccessfulWithoutOption", function (t) { } const client = makeClient([dummyServer]) - client.decrement("number-decrement-test", 5, {}, function (err, success, val) { + client.decrement("number-decrement-test", 5, {}, function (err: Error | null, success, val) { t.equal(true, success) t.equal(6, val) t.equal(null, err) @@ -1154,7 +1155,7 @@ test("AppendSuccessful", function (t) { } const client = makeClient([dummyServer], { expires: 1024 }) - client.append("hello", "world", function (err, val) { + client.append("hello", "world", function (err: Error | null, val) { t.equal(null, err) t.equal(true, val) t.equal(1, n, "Ensure append is called") @@ -1176,7 +1177,7 @@ test("AppendKeyDNE", function (t) { } const client = makeClient([dummyServer]) - client.append("hello", "world", function (err, val) { + client.append("hello", "world", function (err: Error | null, val) { t.equal(null, err) t.equal(false, val) t.equal(1, n, "Ensure append is called") @@ -1198,7 +1199,7 @@ test("PrependSuccessful", function (t) { } const client = makeClient([dummyServer], { expires: 1024 }) - client.prepend("hello", "world", function (err, val) { + client.prepend("hello", "world", function (err: Error | null, val) { t.equal(null, err) t.equal(true, val) t.equal(1, n, "Ensure prepend is called") @@ -1220,7 +1221,7 @@ test("PrependKeyDNE", function (t) { } const client = makeClient([dummyServer]) - client.prepend("hello", "world", function (err, val) { + client.prepend("hello", "world", function (err: Error | null, val) { t.equal(null, err) t.equal(false, val) t.equal(1, n, "Ensure prepend is called") @@ -1243,7 +1244,7 @@ test("TouchSuccessful", function (t) { } const client = makeClient([dummyServer]) - client.touch("hello", 1024, function (err, val) { + client.touch("hello", 1024, function (err: Error | null, val) { t.equal(null, err) t.equal(true, val) t.equal(1, n, "Ensure touch is called") @@ -1266,7 +1267,7 @@ test("TouchKeyDNE", function (t) { } const client = makeClient([dummyServer]) - client.touch("hello", 1024, function (err, val) { + client.touch("hello", 1024, function (err: Error | null, val) { t.equal(null, err) t.equal(false, val) t.equal(1, n, "Ensure ptouch is called") @@ -1315,7 +1316,7 @@ test("Very Large Client Seq", function (t) { const client = makeClient([dummyServer], { expires: 1024 }) client.seq = Math.pow(2, 33) - const assertor = function (err, val) { + const assertor = function (err: Error | null, val: boolean | null) { t.equal(null, err) t.equal(true, val) t.equal(1, n, "Ensure add is called") @@ -1327,7 +1328,7 @@ test("Very Large Client Seq", function (t) { }) }) -const makeDummyVersionServer = (t, serverKey, version) => { +const makeDummyVersionServer = (t: TapType, serverKey: string, version: string) => { const dummyServer = makeDummyServer(serverKey) dummyServer.write = function (requestBuf) { const request = parseMessage(requestBuf) @@ -1379,9 +1380,9 @@ tap.only("VersionError", function (t) { } const client = makeClient([dummyServer]) - const assertor = function (err) { + const assertor = function (err: Error | null, value?: string | Buffer | null, flags?: any) { t.notEqual(null, err) - t.equal("This is an expected error.", err.message) + t.equal("This is an expected error.", err?.message) } client.version(assertor) @@ -1397,7 +1398,7 @@ test("VersionAllSuccessful", function (t) { const dummyServer3 = makeDummyVersionServer(t, "dummyServer3", "3.0.0") const client = makeClient([dummyServer1, dummyServer2, dummyServer3]) - const assertor = function (err, val) { + const assertor = function (err: Error | null, val?: Record | null) { t.deepEqual( { "dummyServer1:undefined": "1.0.0", @@ -1425,9 +1426,9 @@ tap.only("VersionAllSomeFailed", function (t) { const dummyServer3 = makeDummyVersionServer(t, "dummyServer3", "3.0.0") const client = makeClient([dummyServer1, dummyServer2, dummyServer3]) - const assertor = function (err) { + const assertor = function (err: Error | null) { t.notEqual(null, err) - t.equal("This is an expected error.", err.message) + t.equal("This is an expected error.", err?.message) } client.versionAll(assertor) diff --git a/tsconfig.json b/tsconfig.json index d1a0561..97685f3 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -67,5 +67,5 @@ "skipLibCheck": true, /* Skip type checking of declaration files. */ "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ }, - "include": ["src/**/*"], + "include": ["src/**/*", "test/**/*ts", ], } From 0f7a3b4969443b496879f947dddb3da9842f4e8f Mon Sep 17 00:00:00 2001 From: David Blackman Date: Sun, 11 Apr 2021 21:49:29 -0400 Subject: [PATCH 28/79] all tests pass! --- test/client_test.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/test/client_test.ts b/test/client_test.ts index 0203505..7652a2b 100644 --- a/test/client_test.ts +++ b/test/client_test.ts @@ -35,6 +35,10 @@ function parseMessage(requestBuf: Buffer) { } function makeDummyServer(name: string) { + /* NOTE(blackmad): awful hack - MemJS natively speaks Buffers, but they are annoying + to test, so we shim it in some ugly ways to return strings which are easier to work + with. We should fix this at some point. + */ return new MemJS.Server(name) as MemJS.Server & { respond: (m: { extras?: string | Buffer, @@ -53,8 +57,8 @@ test("GetSuccessful", function (t) { n += 1 dummyServer.respond({ header: { status: 0, opaque: request.header.opaque }, - val: Buffer.from("world"), - extras: Buffer.from("flagshere"), + val: "world", + extras: "flagshere", }) } From f0051bdcfe52b79042871cd8c9eb3f8d89749c70 Mon Sep 17 00:00:00 2001 From: David Blackman Date: Sun, 11 Apr 2021 22:08:32 -0400 Subject: [PATCH 29/79] better tap test type --- test/client_test.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/test/client_test.ts b/test/client_test.ts index 7652a2b..cc12b4e 100644 --- a/test/client_test.ts +++ b/test/client_test.ts @@ -10,9 +10,10 @@ import type { GivenClientOptions } from "../src/memjs/memjs" import * as Utils from "../src/memjs/utils" import { MaybeBuffer } from "../src/memjs/utils" -type TapType = any +// I could not figure out a better way to extract this from the typedefs +type TapTestType = (typeof tap)["Test"]["prototype"] -function testAllCallbacksEmpty(t: TapType, server: MemJS.Server) { +function testAllCallbacksEmpty(t: TapTestType, server: MemJS.Server) { t.deepEqual(Object.keys(server.responseCallbacks).length, 0) t.deepEqual(Object.keys(server.errorCallbacks).length, 0) @@ -202,7 +203,7 @@ tap.only("GetMultiSuccessful_SingleBackend", function (t) { }) }) -function makeDummyMultiGetServerResponder(t: TapType, responseMap: Record, serverName?: string) { +function makeDummyMultiGetServerResponder(t: TapTestType, responseMap: Record, serverName?: string) { const server = makeDummyServer(serverName || "dummyServer") const responder = function (requestBuf: Buffer) { const requests = Utils.parseMessages(requestBuf) @@ -1332,7 +1333,7 @@ test("Very Large Client Seq", function (t) { }) }) -const makeDummyVersionServer = (t: TapType, serverKey: string, version: string) => { +const makeDummyVersionServer = (t: TapTestType, serverKey: string, version: string) => { const dummyServer = makeDummyServer(serverKey) dummyServer.write = function (requestBuf) { const request = parseMessage(requestBuf) From 95ebb585304454d32c5460cc936a0b599a73a6c0 Mon Sep 17 00:00:00 2001 From: Jake Teton-Landis Date: Mon, 12 Apr 2021 10:52:49 -0700 Subject: [PATCH 30/79] Update src/memjs/header.ts Co-authored-by: David Blackman --- src/memjs/header.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/memjs/header.ts b/src/memjs/header.ts index 7030621..2353523 100644 --- a/src/memjs/header.ts +++ b/src/memjs/header.ts @@ -33,7 +33,7 @@ export function fromBuffer(headerBuf: Buffer): Header { } /** toBuffer converts a JS memcache header object to a binary memcache header */ -export function toBuffer(header: Header) { +export function toBuffer(header: Header): Buffer { const headerBuf = Buffer.alloc(24); headerBuf.fill(0); headerBuf.writeUInt8(header.magic, 0); From 631e5738dba46ffbbb5205bab167264a670e540b Mon Sep 17 00:00:00 2001 From: Jake Teton-Landis Date: Mon, 12 Apr 2021 10:52:59 -0700 Subject: [PATCH 31/79] Update src/memjs/memjs.ts Co-authored-by: David Blackman --- src/memjs/memjs.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/memjs/memjs.ts b/src/memjs/memjs.ts index a47ab49..61cd266 100644 --- a/src/memjs/memjs.ts +++ b/src/memjs/memjs.ts @@ -1,4 +1,4 @@ -// # MemJS Memcache Client +// MemTS Memcache Client import { errors, UNKNOWN_ERROR } from "./protocol"; import { From 5246465fffe51cfea1c2de5a788e21f5644cd288 Mon Sep 17 00:00:00 2001 From: Jake Teton-Landis Date: Mon, 12 Apr 2021 10:53:06 -0700 Subject: [PATCH 32/79] Update src/memjs/memjs.ts Co-authored-by: David Blackman --- src/memjs/memjs.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/memjs/memjs.ts b/src/memjs/memjs.ts index 61cd266..f800383 100644 --- a/src/memjs/memjs.ts +++ b/src/memjs/memjs.ts @@ -26,7 +26,7 @@ import * as constants from "./constants"; import * as Utils from "./utils"; import * as Header from "./header"; -function defaultKeyToServerHashFunction(servers: string[], key: string) { +function defaultKeyToServerHashFunction(servers: string[], key: string): string { const total = servers.length; const index = total > 1 ? hashCode(key) % total : 0; return servers[index]; From 128be5838c942eba3acb9d7935b2707fe6bac28c Mon Sep 17 00:00:00 2001 From: Jake Teton-Landis Date: Mon, 12 Apr 2021 10:55:47 -0700 Subject: [PATCH 33/79] Update src/memjs/memjs.ts Co-authored-by: David Blackman --- src/memjs/memjs.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/memjs/memjs.ts b/src/memjs/memjs.ts index f800383..bd5c181 100644 --- a/src/memjs/memjs.ts +++ b/src/memjs/memjs.ts @@ -195,7 +195,7 @@ class Client { * @param {string} serverKey * @returns {Server} */ - serverKeyToServer(serverKey: string) { + serverKeyToServer(serverKey: string): Server { return this.serverMap[serverKey]; } From c54fec6faae38287db5635fb6a28da41edf478a1 Mon Sep 17 00:00:00 2001 From: Jake Teton-Landis Date: Mon, 12 Apr 2021 10:56:01 -0700 Subject: [PATCH 34/79] Update src/memjs/memjs.ts Co-authored-by: David Blackman --- src/memjs/memjs.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/memjs/memjs.ts b/src/memjs/memjs.ts index bd5c181..98c0e9c 100644 --- a/src/memjs/memjs.ts +++ b/src/memjs/memjs.ts @@ -204,7 +204,7 @@ class Client { * hashing function) which can be used to index this.serverMap * * @param {string} key - * * @returns {string} + * @returns {string} */ lookupKeyToServerKey(key: string) { return this.options.keyToServerHashFunction(this.serverKeys, key); From 07cb9a82817c5d164870fe8e96b3e72939d3141b Mon Sep 17 00:00:00 2001 From: Jake Teton-Landis Date: Mon, 12 Apr 2021 11:07:51 -0700 Subject: [PATCH 35/79] ci --- .github/workflows/ci.yml | 25 +++++++++++++++++++++++++ package.json | 3 ++- 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..897358e --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,25 @@ +name: Node.js CI + +on: + push: + branches: [ $default-branch ] + pull_request: + branches: [ $default-branch ] + +jobs: + build: + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [12.x] + + steps: + - uses: actions/checkout@v2 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node-version }} + - run: npm ci + - run: npm run build + - run: npm test diff --git a/package.json b/package.json index ad29cd7..9278978 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,8 @@ "lib": "./lib/memjs" }, "scripts": { - "test": "tsc && tap --no-coverage -R spec ./test/*.js ./test/*.ts", + "build": "tsc", + "test": "tap --no-coverage -R spec ./test/*.js ./test/*.ts", "bench": "tsc && NODE_PATH=lib/memjs/ node bench/memjs.js", "bench-timers": "tsc && NODE_PATH=lib/memjs/ node bench/timers.js" }, From ed0b4e1814047d6ad4480922433068f6f2e3e627 Mon Sep 17 00:00:00 2001 From: Jake Teton-Landis Date: Mon, 12 Apr 2021 12:12:00 -0700 Subject: [PATCH 36/79] return cas from get + getMulti --- package-lock.json | 4 +- src/memjs/memjs.ts | 192 ++++++++++++++++++++++----------------------- 2 files changed, 97 insertions(+), 99 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1ee78f0..36c9a82 100644 --- a/package-lock.json +++ b/package-lock.json @@ -243,12 +243,14 @@ "@types/node": { "version": "12.20.7", "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.7.tgz", - "integrity": "sha512-gWL8VUkg8VRaCAUgG9WmhefMqHmMblxe2rVpMF86nZY/+ZysU+BkAp+3cz03AixWDSSz0ks5WX59yAhv/cDwFA==" + "integrity": "sha512-gWL8VUkg8VRaCAUgG9WmhefMqHmMblxe2rVpMF86nZY/+ZysU+BkAp+3cz03AixWDSSz0ks5WX59yAhv/cDwFA==", + "dev": true }, "@types/tap": { "version": "14.10.3", "resolved": "https://registry.npmjs.org/@types/tap/-/tap-14.10.3.tgz", "integrity": "sha512-pdibkMTqKxznrLTFRVJdv/zQ8AAvHe9puqiBt9Mp+hrBgs0ZqCsjCj2e6ez8+p39oapyVp491xxw09E732g1Qw==", + "dev": true, "requires": { "@types/node": "*" } diff --git a/src/memjs/memjs.ts b/src/memjs/memjs.ts index 98c0e9c..19ead87 100644 --- a/src/memjs/memjs.ts +++ b/src/memjs/memjs.ts @@ -26,7 +26,10 @@ import * as constants from "./constants"; import * as Utils from "./utils"; import * as Header from "./header"; -function defaultKeyToServerHashFunction(servers: string[], key: string): string { +function defaultKeyToServerHashFunction( + servers: string[], + key: string +): string { const total = servers.length; const index = total > 1 ? hashCode(key) % total : 0; return servers[index]; @@ -60,9 +63,18 @@ interface SerializerProp { serializer: Serializer; } -type IfBuffer = Value extends Buffer +/** + * If Value and Extras are of type Buffer, then return type WhenBuffer. Otherwise, + * return type NotBuffer. + */ +type IfBuffer< + Value, + Extras, + WhenValueAndExtrasAreBuffers, + NotBuffer +> = Value extends Buffer ? Extras extends Buffer - ? IsBuffer + ? WhenValueAndExtrasAreBuffers : NotBuffer : NotBuffer; @@ -74,6 +86,18 @@ export type GivenClientOptions = Partial & SerializerProp >; +type CASToken = Buffer; + +interface GetResult { + value: Value; + extras: Extras; + cas: CASToken | undefined; +} + +type GetMultiResult = { + [K in Keys]: GetResult; +}; + class Client { servers: Server[]; seq: number; @@ -226,40 +250,27 @@ class Client { // arguments. /** - * GET - * * Retrieves the value at the given key in memcache. - * - * The callback signature is: - * - * callback(err, value, flags) - * - * _value_ and _flags_ are both `Buffer`s. If the key is not found, the - * callback is invoked with null for both arguments and no error - * @param key - * @param callback */ - get(key: string): Promise<{ value: Value | null; flags: Extras | null }>; + get(key: string): Promise | null>; get( key: string, callback: ( error: Error | null, - value: Value | null, - flags: Extras | null + result: GetResult | null ) => void ): void; get( key: string, callback?: ( error: Error | null, - value: Value | null, - flags: Extras | null + result: GetResult | null ) => void - ): Promise<{ value: Value | null; flags: Extras | null }> | void { + ): Promise | null> | void { if (callback === undefined) { return promisify((callback) => { - this.get(key, function (err, value, flags) { - callback(err, { value: value, flags: flags }); + this.get(key, function (err, value) { + callback(err, value); }); }); } @@ -269,7 +280,7 @@ class Client { this.perform(key, request, this.seq, (err, response) => { if (err) { if (callback) { - callback(err, null, null); + callback(err, null); } return; } @@ -281,12 +292,12 @@ class Client { response!.val, response!.extras ); - callback(null, deserialized.value, deserialized.extras); + callback(null, { ...deserialized, cas: response!.header.cas }); } break; case constants.RESPONSE_STATUS_KEY_NOT_FOUND: if (callback) { - callback(null, null, null); + callback(null, null); } break; default: @@ -294,7 +305,7 @@ class Client { "MemJS GET: " + errors[response!.header.status || UNKNOWN_ERROR]; logger.log(errorMessage); if (callback) { - callback(new Error(errorMessage), null, null); + callback(new Error(errorMessage), null); } } }); @@ -304,7 +315,7 @@ class Client { * * cf https://github.com/couchbase/memcached/blob/master/docs/BinaryProtocol.md#0x0d-getkq-get-with-key-quietly */ - _buildGetMultiRequest(keys: string[]) { + _buildGetMultiRequest(keys: string[]): Buffer { // start at 24 for the no-op command at the end let requestSize = 24; for (const keyIdx in keys) { @@ -342,18 +353,15 @@ class Client { } /** Executing a pipelined (multi) get against a single server. This is a private implementation detail of getMulti. */ - _getMultiToServer( + _getMultiToServer( serv: Server, - keys: string[], + keys: Keys[], callback: ( error: Error | null, - values: { [key: string]: Value | null } | null, - flags: Extras | null + values: GetMultiResult | null ) => void ) { - const responseMap: { - [server: string]: Value | null; - } = {}; + const responseMap: GetMultiResult = {}; const handle: OnResponseCallback = (response) => { switch (response.header.status) { @@ -369,16 +377,17 @@ class Client { // This ensures the handler will be deleted from the responseCallbacks map in server.js // This isn't technically needed here because the logic in server.js also checks if totalBodyLength === 0, but our unittests aren't great about setting that field, and also this makes it more explicit handle.quiet = false; - callback(null, responseMap, deserialized.extras); + callback(null, responseMap); } else { const key = response.key.toString(); - responseMap[key] = deserialized.value; + responseMap[key] = { ...deserialized, cas: response.header.cas }; } } break; case constants.RESPONSE_STATUS_KEY_NOT_FOUND: if (callback) { - callback(null, null, null); + // @blackmad: IS THIS CORRECT??? + callback(null, null); } break; default: @@ -386,7 +395,7 @@ class Client { "MemJS GET: " + errors[response.header.status || UNKNOWN_ERROR]; this.options.logger.log(errorMessage); if (callback) { - callback(new Error(errorMessage), null, null); + callback(new Error(errorMessage), null); } } }; @@ -398,7 +407,7 @@ class Client { serv.onResponse(this.seq, handle); serv.onError(this.seq, function (err) { if (callback) { - callback(err, serv.hostportString() as any /* TODO */, null); + callback(err, null); } }); this.incrSeq(); @@ -406,46 +415,30 @@ class Client { } /** - * MULTI-GET / GET-MULTI - * - * Retrieves the value at the given keys in memcache. - * - * The callback signature is: - * - * callback(err, value, flags) - * - * @param keys - * @param callback + * Retrievs the value at the given keys in memcached. Returns a map from the + * requested keys to results, or null if the key was not found. */ getMulti( keys: Keys[] - ): Promise<{ - values: { [K in Keys]?: Value | null } | null; - flags: Extras | null; - }>; + ): Promise | null>; getMulti( keys: Keys[], callback: ( error: Error | null, - value: { [K in Keys]?: Value | null } | null, - flags: Extras | null + value: GetMultiResult | null ) => void ): void; getMulti( keys: Keys[], callback?: ( error: Error | null, - value: { [K in Keys]?: Value | null } | null, - flags: Extras | null + value: GetMultiResult | null ) => void - ): Promise<{ - values: { [K in Keys]?: Value | null } | null; - flags: Extras | null; - }> | void { + ): Promise | null> | void { if (callback === undefined) { return promisify((callback) => { - this.getMulti(keys, function (err, values, flags) { - callback(err, { values: values, flags: flags }); + this.getMulti(keys, function (err, value) { + callback(err, value); }); }); } @@ -463,12 +456,11 @@ class Client { const usedServerKeys = Object.keys(serverKeytoLookupKeys); let outstandingCalls = usedServerKeys.length; - const recordMap = {}; + const recordMap: GetMultiResult = {}; let hadError = false; function latchCallback( err: Error | null, - values: { [key: string]: Value | null } | null, - flags: Extras | null + values: GetMultiResult | null ) { if (hadError) { return; @@ -476,14 +468,14 @@ class Client { if (err) { hadError = true; - callback!(err, null, null); + callback!(err, null); return; } merge(recordMap, values); outstandingCalls -= 1; if (outstandingCalls === 0) { - callback!(null, recordMap, flags); + callback!(null, recordMap); } } @@ -535,21 +527,18 @@ class Client { if (callback === undefined && typeof options !== "function") { if (!options) options = {}; return promisify((callback) => { - this.set( - key, - value, - options as { expires?: number }, - function (err, success) { - callback(err, success); - } - ); + this.set(key, value, options as { expires?: number }, function ( + err, + success + ) { + callback(err, success); + }); }); } - const logger = this.options.logger + const logger = this.options.logger; const expires = (options || {}).expires; - // TODO: support flags, support version (CAS) this.incrSeq(); const expiration = makeExpiration(expires || this.options.expires); @@ -626,21 +615,21 @@ class Client { if (callback === undefined && options !== "function") { if (!options) options = {}; return promisify((callback) => { - this.add( - key, - value, - options as { expires?: number }, - function (err, success) { - callback(err, success); - } - ); + this.add(key, value, options as { expires?: number }, function ( + err, + success + ) { + callback(err, success); + }); }); } const logger = this.options.logger; // TODO: support flags, support version (CAS) this.incrSeq(); - const expiration = makeExpiration((options || {}).expires || this.options.expires); + const expiration = makeExpiration( + (options || {}).expires || this.options.expires + ); const extras = Buffer.concat([Buffer.from("00000000", "hex"), expiration]); const opcode: constants.OP = 2; @@ -708,21 +697,21 @@ class Client { if (callback === undefined && options !== "function") { if (!options) options = {}; return promisify((callback) => { - this.replace( - key, - value, - options as { expires?: number }, - function (err, success) { - callback(err, success); - } - ); + this.replace(key, value, options as { expires?: number }, function ( + err, + success + ) { + callback(err, success); + }); }); } const logger = this.options.logger; // TODO: support flags, support version (CAS) this.incrSeq(); - const expiration = makeExpiration((options || {}).expires || this.options.expires); + const expiration = makeExpiration( + (options || {}).expires || this.options.expires + ); const extras = Buffer.concat([Buffer.from("00000000", "hex"), expiration]); const opcode: constants.OP = 3; @@ -1097,7 +1086,8 @@ class Client { const logger = this.options.logger; this.incrSeq(); - const opcode: constants.OP = constants.OP_PREPEND; /* WAS WRONG IN ORIGINAL */ + const opcode: constants.OP = + constants.OP_PREPEND; /* WAS WRONG IN ORIGINAL */ const serialized = this.serializer.serialize(opcode, value, ""); const request = makeRequestBuffer( opcode, @@ -1436,7 +1426,13 @@ class Client { } this.incrSeq(); - const request = makeRequestBuffer(constants.OP_VERSION, "", "", "", this.seq); + const request = makeRequestBuffer( + constants.OP_VERSION, + "", + "", + "", + this.seq + ); const logger = this.options.logger; this.performOnServer(server, request, this.seq, (err, response) => { From db2deee164304edb0b2b7f007f29d3e9aba4eaba Mon Sep 17 00:00:00 2001 From: Jake Teton-Landis Date: Mon, 12 Apr 2021 13:10:40 -0700 Subject: [PATCH 37/79] move test into src --- package.json | 8 +- src/memjs/memjs.ts | 18 +- src/test/client_test.ts | 1567 +++++++++++++++++++++++++++++ {test => src/test}/header_test.js | 2 +- {test => src/test}/server_test.js | 2 +- {test => src/test}/utils_test.js | 2 +- test/client_test.ts | 1444 -------------------------- tsconfig.json | 4 +- 8 files changed, 1585 insertions(+), 1462 deletions(-) create mode 100644 src/test/client_test.ts rename {test => src/test}/header_test.js (97%) rename {test => src/test}/server_test.js (97%) rename {test => src/test}/utils_test.js (97%) delete mode 100644 test/client_test.ts diff --git a/package.json b/package.json index 9278978..8d58d5a 100644 --- a/package.json +++ b/package.json @@ -23,10 +23,10 @@ "lib": "./lib/memjs" }, "scripts": { - "build": "tsc", - "test": "tap --no-coverage -R spec ./test/*.js ./test/*.ts", - "bench": "tsc && NODE_PATH=lib/memjs/ node bench/memjs.js", - "bench-timers": "tsc && NODE_PATH=lib/memjs/ node bench/timers.js" + "tsc": "rm -rf ./lib && tsc", + "test": "npm run-script tsc && tap --no-coverage -R spec ./lib/test/*.js", + "bench": "npm run-script tsc && NODE_PATH=lib/memjs/ node bench/memjs.js", + "bench-timers": "npm run-script tsc && NODE_PATH=lib/memjs/ node bench/timers.js" }, "devDependencies": { "@types/node": "12.20.7", diff --git a/src/memjs/memjs.ts b/src/memjs/memjs.ts index 19ead87..f8c0d8f 100644 --- a/src/memjs/memjs.ts +++ b/src/memjs/memjs.ts @@ -7,11 +7,7 @@ import { Server, ServerOptions, } from "./server"; -import { - noopSerializer, - Serializer, - SerializerResult, -} from "./noop-serializer"; +import { noopSerializer, Serializer } from "./noop-serializer"; import { makeRequestBuffer, copyIntoRequestBuffer, @@ -86,19 +82,23 @@ export type GivenClientOptions = Partial & SerializerProp >; -type CASToken = Buffer; +export type CASToken = Buffer; -interface GetResult { +export interface GetResult { value: Value; extras: Extras; cas: CASToken | undefined; } -type GetMultiResult = { +export type GetMultiResult< + Keys extends string = string, + Value = MaybeBuffer, + Extras = MaybeBuffer +> = { [K in Keys]: GetResult; }; -class Client { +class Client { servers: Server[]; seq: number; options: BaseClientOptions & Partial>; diff --git a/src/test/client_test.ts b/src/test/client_test.ts new file mode 100644 index 0000000..bc90bf7 --- /dev/null +++ b/src/test/client_test.ts @@ -0,0 +1,1567 @@ +import tap from "tap"; +const test = tap.test; + +const errors = require("../memjs/protocol").errors; +import MemJS = require(".."); +import constants = require("../memjs/constants"); +import { noopSerializer } from "../memjs/noop-serializer"; +import { Header } from "../memjs/header"; +import type { GivenClientOptions } from "../memjs/memjs"; +import * as Utils from "../memjs/utils"; +import { MaybeBuffer } from "../memjs/utils"; + +// I could not figure out a better way to extract this from the typedefs +type TapTestType = typeof tap["Test"]["prototype"]; + +function testAllCallbacksEmpty(t: TapTestType, server: MemJS.Server) { + t.deepEqual(Object.keys(server.responseCallbacks).length, 0); + t.deepEqual(Object.keys(server.errorCallbacks).length, 0); + + t.deepEqual(server.requestTimeouts, []); +} + +function makeClient( + dummyServer: MemJS.Server | MemJS.Server[], + options?: GivenClientOptions +) { + return new MemJS.Client( + Array.isArray(dummyServer) ? dummyServer : [dummyServer], + options || { serializer: noopSerializer } + ); +} + +function parseMessage(requestBuf: Buffer) { + const message = Utils.parseMessage(requestBuf); + if (!message) { + throw new Error("Expected message to parse successfully, but got false"); + } + return message; +} + +function makeDummyServer(name: string) { + /* NOTE(blackmad): awful hack - MemJS natively speaks Buffers, but they are annoying + to test, so we shim it in some ugly ways to return strings which are easier to work + with. We should fix this at some point. + */ + return new MemJS.Server(name) as MemJS.Server & { + respond: (m: { + extras?: string | Buffer; + key?: string | Buffer; + val?: string | Buffer; + header: Partial
; + }) => void; + }; +} + +test("GetSuccessful", function (t) { + let n = 0; + const dummyServer = makeDummyServer("dummyServer"); + const casToken = Buffer.from("cas data"); + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf); + t.equal("hello", request.key.toString()); + n += 1; + dummyServer.respond({ + header: { status: 0, opaque: request.header.opaque, cas: casToken }, + val: "world", + extras: "flagshere", + }); + }; + + const client = makeClient([dummyServer]); + const assertor = function (err: Error | null, val: MemJS.GetResult | null) { + if (!val) { + t.ok(val, "must return value"); + return; + } + t.equal("world", val.value); + t.equal("flagshere", val.extras); + t.equal(casToken, val.cas); + t.equal(null, err); + t.equal(1, n, "Ensure get is called"); + }; + client.get("hello", assertor); + n = 0; + return client.get("hello").then(function (res) { + assertor(null, res); + }); +}); + +test("GetNotFound", function (t) { + let n = 0; + const dummyServer = makeDummyServer("dummyServer"); + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf); + t.equal("hello", request.key.toString()); + n += 1; + dummyServer.respond({ + header: { status: 1, opaque: request.header.opaque }, + }); + }; + + const client = makeClient([dummyServer]); + const assertor = function (err: Error | null, val: MemJS.GetResult | null) { + t.equal(null, val); + t.equal(1, n, "Ensure get is called"); + }; + client.get("hello", assertor); + n = 0; + return client.get("hello").then(function (res) { + assertor(null, res); + t.end(); + }); +}); + +test("GetSerializer", function (t) { + let n = 0; + let dn = 0; + const dummyServer = makeDummyServer("dummyServer"); + const casToken = Buffer.from("cas shmoken"); + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf); + t.equal("hello", request.key.toString()); + n += 1; + dummyServer.respond({ + header: { status: 0, opaque: request.header.opaque, cas: casToken }, + val: "world", + extras: "flagshere", + }); + }; + + const client = makeClient([dummyServer], { + serializer: { + serialize: function (opcode, value, extras) { + return { value: value, extras: extras }; + }, + deserialize: function (opcode, value, extras) { + dn += 1; + return { value: "deserialized", extras: extras }; + }, + }, + }); + const assertor = function (err: Error | null, value: MemJS.GetResult | null) { + if (!value) { + t.ok(value, "must return value"); + return; + } + t.equal("deserialized", value.value); + t.equal("flagshere", value.extras); + t.equal(casToken, value.cas); + t.equal(null, err); + t.equal(1, n, "Ensure get is called"); + t.equal(1, dn, "Ensure deserialization is called once"); + }; + client.get("hello", assertor); + n = 0; + dn = 0; + return client.get("hello").then(function (res) { + assertor(null, res); + }); +}); + +tap.only("GetMultiSuccessful_SingleBackend", function (t) { + let n = 0; + const dummyServer = makeDummyServer("dummyServer"); + dummyServer.write = function (requestBuf) { + const requests = Utils.parseMessages(requestBuf); + t.equal(requests.length, 4); + n += 1; + + function checkAndRespond( + request: Utils.Message, + key: string, + value: string + ) { + t.equal(key, request.key.toString()); + t.equal(constants.OP_GETKQ, request.header.opcode); + + dummyServer.respond({ + header: { + status: 0, + opaque: request.header.opaque, + opcode: request.header.opcode, + cas: Buffer.from(`cas ${key}`), + }, + key: key, + val: value, + extras: "flagshere", + }); + } + checkAndRespond(requests[0], "hello1", "world1"); + checkAndRespond(requests[1], "hello2", "world2"); + checkAndRespond(requests[2], "hello3", "world3"); + + t.equal(constants.OP_NO_OP, requests[3].header.opcode); + dummyServer.respond({ + header: { + status: 0, + opaque: requests[3].header.opaque, + opcode: requests[3].header.opcode, + }, + }); + }; + + const client = makeClient([dummyServer]); + const assertor = function ( + err: Error | null, + result: MemJS.GetMultiResult | null + ) { + t.deepEqual( + { + hello1: { + value: "world1", + extras: "flagshere", + cas: Buffer.from("cas hello1"), + }, + hello2: { + value: "world2", + extras: "flagshere", + cas: Buffer.from("cas hello2"), + }, + hello3: { + value: "world3", + extras: "flagshere", + cas: Buffer.from("cas hello3"), + }, + }, + result + ); + t.equal(null, err); + t.equal(1, n, "Ensure getMulti is called"); + }; + client.getMulti(["hello1", "hello2", "hello3"], assertor); + testAllCallbacksEmpty(t, dummyServer); + + n = 0; + return client.getMulti(["hello1", "hello2", "hello3"]).then(function (res) { + assertor(null, res); + }); +}); + +const DummyMultiGetFlags = "flagshere"; + +function makeDummyMultiGetServerResponder( + t: TapTestType, + responseMap: Record, + serverName?: string +) { + const server = makeDummyServer(serverName || "dummyServer"); + const responder = function (requestBuf: Buffer) { + const requests = Utils.parseMessages(requestBuf); + t.equal(requests.length, Object.keys(responseMap).length + 1); + + function checkAndRespond( + request: Utils.Message, + key: string, + value: string | undefined + ) { + t.equal(constants.OP_GETKQ, request.header.opcode); + + if (value !== undefined) { + server.respond({ + header: { + status: 0, + opaque: request.header.opaque, + opcode: request.header.opcode, + }, + key: key, + val: value, + extras: DummyMultiGetFlags, + }); + } + } + + for (const requestIndex in requests) { + const request = requests[requestIndex]; + + if (requestIndex === (requests.length - 1).toString()) { + t.equal(constants.OP_NO_OP, request.header.opcode); + server.respond({ + header: { + status: 0, + opaque: request.header.opaque, + opcode: request.header.opcode, + }, + }); + } else { + const key = request.key.toString(); + checkAndRespond(request, key, responseMap[key]); + } + } + }; + server.write = responder; + return server; +} + +test("GetMultiSuccessful_MultiBackend", function (t) { + // the mappings from key to server were computer by just manually running the default hash on them + + const dummyServer1 = makeDummyMultiGetServerResponder( + t, + { + hello2: "world2", + hello4: "world4", + }, + "dummyServer1" + ); + const dummyServer2 = makeDummyMultiGetServerResponder( + t, + { + hello1: "world1", + hello3: "world3", + }, + "dummyServer2" + ); + const servers = [dummyServer1, dummyServer2]; + + const client = makeClient(servers); + + const assertor = function ( + err: Error | null, + val: MemJS.GetMultiResult | null + ) { + const expected: MemJS.GetMultiResult< + "hello1" | "hello2" | "hello3" | "hello4" + > = { + hello1: { + value: "world1", + extras: DummyMultiGetFlags, + cas: undefined, + }, + hello2: { + value: "world2", + extras: DummyMultiGetFlags, + cas: undefined, + }, + hello3: { + value: "world3", + extras: DummyMultiGetFlags, + cas: undefined, + }, + hello4: { + value: "world4", + extras: DummyMultiGetFlags, + cas: undefined, + }, + }; + t.deepEqual(expected, val); + t.equal(null, err); + }; + client.getMulti(["hello1", "hello2", "hello3", "hello4"], assertor); + testAllCallbacksEmpty(t, dummyServer1); + testAllCallbacksEmpty(t, dummyServer2); + + return client + .getMulti(["hello1", "hello2", "hello3", "hello4"]) + .then(function (res) { + assertor(null, res); + }); +}); + +test("GetMultiSuccessful_MissingKeys_MultiBackend", function (t) { + // the mappings from key to server were computed by just manually running the default hash on them + const dummyServer1 = makeDummyMultiGetServerResponder( + t, + { + hello2: undefined, + hello4: "world4", + }, + "dummyServer1" + ); + const dummyServer2 = makeDummyMultiGetServerResponder( + t, + { + hello1: "world1", + hello3: "world3", + }, + "dummyServer2" + ); + const servers = [dummyServer1, dummyServer2]; + + const client = makeClient(servers); + + const assertor = function ( + err: Error | null, + val: MemJS.GetMultiResult | null + ) { + const expected: MemJS.GetMultiResult<"hello1" | "hello2" | "hello3"> = { + hello1: { + value: "world1", + extras: DummyMultiGetFlags, + cas: undefined, + }, + hello2: { + value: "world2", + extras: DummyMultiGetFlags, + cas: undefined, + }, + hello3: { + value: "world3", + extras: DummyMultiGetFlags, + cas: undefined, + }, + }; + t.deepEqual(expected, val); + t.equal(null, err); + }; + client.getMulti(["hello1", "hello2", "hello3", "hello4"], assertor); + testAllCallbacksEmpty(t, dummyServer1); + testAllCallbacksEmpty(t, dummyServer2); + + return client + .getMulti(["hello1", "hello2", "hello3", "hello4"]) + .then(function (res) { + assertor(null, res); + }); +}); + +test("GetMultiError_MultiBackend", function (t) { + // the mappings from key to server were computed by just manually running the default hash on them + const dummyServer1 = makeDummyMultiGetServerResponder( + t, + { + hello2: undefined, + hello4: "world4", + }, + "dummyServer1" + ); + const dummyServer2 = makeDummyMultiGetServerResponder( + t, + { + hello1: "world1", + hello3: "world3", + }, + "dummyServer2" + ); + dummyServer2.write = function () { + dummyServer2.error({ + name: "ErrorName", + message: "This is an expected error.", + }); + }; + const servers = [dummyServer1, dummyServer2]; + + const client = makeClient(servers); + + const assertor = function (err: Error | null) { + t.notEqual(null, err); + t.equal("This is an expected error.", err?.message); + }; + client.getMulti(["hello1", "hello2", "hello3", "hello4"], assertor); + testAllCallbacksEmpty(t, dummyServer1); + testAllCallbacksEmpty(t, dummyServer2); + + return client + .getMulti(["hello1", "hello2", "hello3", "hello4"]) + .catch(function (err) { + assertor(err); + return true; + }); +}); + +test("GetMultiSuccessfulWithMissingKeys", function (t) { + const dummyServer = makeDummyMultiGetServerResponder(t, { + hello1: "world1", + hello2: undefined, + hello3: "world3", + }); + + const client = makeClient([dummyServer], { serializer: noopSerializer }); + const assertor = function ( + err: Error | null, + val: MemJS.GetMultiResult | null + ) { + const expected: MemJS.GetMultiResult<"hello1" | "hello3"> = { + hello1: { + value: "world1", + extras: DummyMultiGetFlags, + cas: undefined, + }, + hello3: { + value: "world3", + extras: DummyMultiGetFlags, + cas: undefined, + }, + }; + t.deepEqual(expected, val); + t.equal(null, err); + }; + client.getMulti(["hello1", "hello2", "hello3"], assertor); + testAllCallbacksEmpty(t, dummyServer); + return client.getMulti(["hello1", "hello2", "hello3"]).then(function (res) { + assertor(null, res); + }); +}); + +test("GetMultiError", function (t) { + const dummyServer = makeDummyServer("dummyServer"); + dummyServer.write = function (requestBuf) { + const requests = Utils.parseMessages(requestBuf); + t.equal(requests.length, 4); + + function checkAndRespond( + request: Utils.Message, + key: string, + value: string + ) { + t.equal(key, request.key.toString()); + t.equal(constants.OP_GETKQ, request.header.opcode); + + dummyServer.respond({ + header: { + status: 0, + opaque: request.header.opaque, + opcode: request.header.opcode, + }, + key: key, + val: value, + extras: "flagshere", + }); + } + checkAndRespond(requests[0], "hello1", "world1"); + dummyServer.error({ + name: "ErrorName", + message: "This is an expected error.", + }); + }; + + const client = makeClient([dummyServer]); + const assertor = function (err: Error | null) { + t.notEqual(null, err); + t.equal("This is an expected error.", err?.message); + }; + client.getMulti(["hello1", "hello2", "hello3"], assertor); + testAllCallbacksEmpty(t, dummyServer); + + return client.getMulti(["hello1", "hello2", "hello3"]).catch(function (err) { + assertor(err); + return true; + }); +}); + +test("SetSuccessful", function (t) { + let n = 0; + const dummyServer = makeDummyServer("dummyServer"); + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf); + t.equal("hello", request.key.toString()); + t.equal("world", request.val.toString()); + n += 1; + dummyServer.respond({ + header: { status: 0, opaque: request.header.opaque }, + }); + }; + + const client = makeClient([dummyServer]); + const assertor = function (err: Error | null, val: boolean | null) { + t.equal(true, val); + t.equal(null, err); + t.equal(1, n, "Ensure set is called"); + }; + client.set("hello", "world", {}, assertor); + n = 0; + return client.set("hello", "world", {}).then(function (success) { + assertor(null, success); + }); +}); + +test("SetSuccessfulWithoutOption", function (t) { + let n = 0; + const dummyServer = makeDummyServer("dummyServer"); + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf); + t.equal("hello", request.key.toString()); + t.equal("world", request.val.toString()); + n += 1; + dummyServer.respond({ + header: { status: 0, opaque: request.header.opaque }, + }); + }; + + const client = makeClient([dummyServer]); + client.set("hello", "world", {}, function (err: Error | null, val) { + t.equal(true, val); + t.equal(null, err); + t.equal(1, n, "Ensure set is called"); + t.end(); + }); +}); + +test("SetPromiseWithoutOption", function (t) { + let n = 0; + const dummyServer = makeDummyServer("dummyServer"); + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf); + t.equal("hello", request.key.toString()); + t.equal("world", request.val.toString()); + n += 1; + dummyServer.respond({ + header: { status: 0, opaque: request.header.opaque }, + }); + }; + + const client = makeClient([dummyServer]); + return client.set("hello", "world").then(function (val) { + t.equal(true, val); + t.equal(1, n, "Ensure set is called"); + t.end(); + }); +}); + +test("SetWithExpiration", function (t) { + let n = 0; + const dummyServer = makeDummyServer("dummyServer"); + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf); + t.equal("hello", request.key.toString()); + t.equal("world", request.val.toString()); + t.equal("\0\0\0\0\0\0\x04\0", request.extras.toString()); + n += 1; + dummyServer.respond({ + header: { status: 0, opaque: request.header.opaque }, + }); + }; + + const client = makeClient([dummyServer], { expires: 1024 }); + client.set("hello", "world", {}, function (err: Error | null, val) { + t.equal(null, err); + t.equal(true, val); + t.equal(1, n, "Ensure set is called"); + t.end(); + }); +}); + +test("SetUnsuccessful", function (t) { + let n = 0; + const dummyServer = makeDummyServer("dummyServer"); + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf); + t.equal("hello", request.key.toString()); + t.equal("world", request.val.toString()); + n += 1; + dummyServer.respond({ + header: { status: 3, opaque: request.header.opaque }, + }); + }; + + const client = makeClient([dummyServer]); + const assertor = function (err: Error | null, val: boolean | null) { + t.equal(null, val); + t.equal("MemJS SET: " + errors[3], err?.message); + t.equal(1, n, "Ensure set is called"); + }; + client.set("hello", "world", {}, assertor); + n = 0; + return client.set("hello", "world", {}).catch(function (err) { + assertor(err, null); + }); +}); + +test("SetError", function (t) { + let n = 0; + const dummyServer = makeDummyServer("dummyServer"); + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf); + t.equal("hello", request.key.toString()); + t.equal("world", request.val.toString()); + n += 1; + dummyServer.error({ + name: "ErrorName", + message: "This is an expected error.", + }); + }; + + const client = makeClient([dummyServer]); + client.set("hello", "world", {}, function (err: Error | null, val) { + t.notEqual(null, err); + t.equal("This is an expected error.", err?.message); + t.equal(null, val); + t.equal(2, n, "Ensure set is retried once"); + t.end(); + }); +}); + +test("SetError", function (t) { + let n = 0; + const dummyServer = makeDummyServer("dummyServer"); + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf); + t.equal("hello", request.key.toString()); + t.equal("world", request.val.toString()); + setTimeout(function () { + n += 1; + dummyServer.error({ + name: "ErrorName", + message: "This is an expected error.", + }); + }, 100); + }; + + const client = makeClient([dummyServer], { retries: 2 }); + client.set("hello", "world", {}, function (err /*, val */) { + t.equal(2, n, "Ensure set is retried once"); + t.ok(err, "Ensure callback called with error"); + t.equal("This is an expected error.", err?.message); + t.end(); + }); +}); + +test("SetErrorConcurrent", function (t) { + let n = 0; + let callbn1 = 0; + let callbn2 = 0; + const dummyServer = makeDummyServer("dummyServer"); + dummyServer.write = function (/* requestBuf */) { + n += 1; + dummyServer.error({ + name: "ErrorName", + message: "This is an expected error.", + }); + }; + + const client = makeClient([dummyServer], { retries: 2 }); + client.set("hello", "world", {}, function (err /*, val */) { + t.ok(err, "Ensure callback called with error"); + t.equal("This is an expected error.", err?.message); + callbn1 += 1; + done(); + }); + + client.set("foo", "bar", {}, function (err /*, val */) { + t.ok(err, "Ensure callback called with error"); + t.equal("This is an expected error.", err?.message); + callbn2 += 1; + done(); + }); + + const done = (function () { + let called = 0; + return function () { + called += 1; + if (called < 2) return; + t.equal(1, callbn1, "Ensure callback 1 is called once"); + t.equal(1, callbn2, "Ensure callback 2 is called once"); + t.equal(4, n, "Ensure error sent twice for each set call"); + t.end(); + }; + })(); +}); + +test("SetUnicode", function (t) { + let n = 0; + const dummyServer = makeDummyServer("dummyServer"); + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf); + t.equal("hello", request.key.toString()); + t.equal("éééoào", request.val.toString()); + n += 1; + dummyServer.respond({ + header: { status: 0, opaque: request.header.opaque }, + }); + }; + + const client = makeClient([dummyServer]); + client.set("hello", "éééoào", {}, function (err: Error | null, val) { + t.equal(true, val); + t.equal(1, n, "Ensure set is called"); + t.end(); + }); +}); + +test("SetSerialize", function (t) { + let n = 0; + let sn = 0; + const dummyServer = makeDummyServer("dummyServer"); + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf); + t.equal("hello", request.key.toString()); + t.equal("serialized", request.val.toString()); + n += 1; + dummyServer.respond({ + header: { status: 3, opaque: request.header.opaque }, + }); + }; + + const client = makeClient([dummyServer], { + serializer: { + serialize: function (opcode, value, extras) { + sn += 1; + return { value: "serialized", extras: extras }; + }, + deserialize: function (opcode, value, extras) { + return { value: value, extras: extras }; + }, + }, + }); + const assertor = function (err: Error | null, val: boolean | null) { + t.equal(null, val); + t.equal("MemJS SET: " + errors[3], err?.message); + t.equal(1, n, "Ensure set is called"); + t.equal(1, sn, "Ensure serialization is called once"); + }; + client.set("hello", "world", {}, assertor); + n = 0; + sn = 0; + return client.set("hello", "world", {}).catch(function (err) { + assertor(err, null); + }); +}); + +test("AddSuccessful", function (t) { + let n = 0; + const dummyServer = makeDummyServer("dummyServer"); + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf); + t.equal("hello", request.key.toString()); + t.equal("world", request.val.toString()); + t.equal("0000000000000400", request.extras.toString("hex")); + n += 1; + dummyServer.respond({ + header: { status: 0, opaque: request.header.opaque }, + }); + }; + + const client = makeClient([dummyServer], { expires: 1024 }); + const assertor = function (err: Error | null, val: boolean | null) { + t.equal(null, err); + t.equal(true, val); + t.equal(1, n, "Ensure add is called"); + }; + client.add("hello", "world", {}, assertor); + n = 0; + return client.add("hello", "world", {}).then(function (success) { + assertor(null, success); + }); +}); + +test("AddSuccessfulWithoutOption", function (t) { + let n = 0; + const dummyServer = makeDummyServer("dummyServer"); + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf); + t.equal("hello", request.key.toString()); + t.equal("world", request.val.toString()); + t.equal("0000000000000400", request.extras.toString("hex")); + n += 1; + dummyServer.respond({ + header: { status: 0, opaque: request.header.opaque }, + }); + }; + + const client = makeClient([dummyServer], { expires: 1024 }); + client.add("hello", "world", {}, function (err: Error | null, val) { + t.equal(null, err); + t.equal(true, val); + t.equal(1, n, "Ensure add is called"); + t.end(); + }); +}); + +test("AddKeyExists", function (t) { + let n = 0; + const dummyServer = makeDummyServer("dummyServer"); + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf); + t.equal("hello", request.key.toString()); + t.equal("world", request.val.toString()); + n += 1; + dummyServer.respond({ + header: { status: 2, opaque: request.header.opaque }, + }); + }; + + const client = makeClient([dummyServer]); + client.add("hello", "world", {}, function (err: Error | null, val) { + t.equal(null, err); + t.equal(false, val); + t.equal(1, n, "Ensure add is called"); + t.end(); + }); +}); + +test("AddSerializer", function (t) { + let n = 0; + let sn = 0; + const dummyServer = makeDummyServer("dummyServer"); + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf); + t.equal("hello", request.key.toString()); + t.equal("serialized", request.val.toString()); + t.equal("0000000100000400", request.extras.toString("hex")); + n += 1; + dummyServer.respond({ + header: { status: 0, opaque: request.header.opaque }, + }); + }; + + const client = makeClient([dummyServer], { + expires: 1024, + serializer: { + serialize: function (opcode, value, extras) { + sn += 1; + if (Buffer.isBuffer(extras)) { + extras.writeUInt32BE(1, 0); + } + return { value: "serialized", extras: extras }; + }, + deserialize: function (opcode, value, extras) { + return { value: value, extras: extras }; + }, + }, + }); + const assertor = function (err: Error | null, val: boolean | null) { + t.equal(null, err); + t.equal(true, val); + t.equal(1, n, "Ensure add is called"); + t.equal(1, sn, "Ensure serialization is called once"); + }; + client.add("hello", "world", {}, assertor); + n = 0; + sn = 0; + return client.add("hello", "world", {}).then(function (success) { + assertor(null, success); + }); +}); + +test("ReplaceSuccessful", function (t) { + let n = 0; + const dummyServer = makeDummyServer("dummyServer"); + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf); + t.equal("hello", request.key.toString()); + t.equal("world", request.val.toString()); + t.equal("\0\0\0\0\0\0\x04\0", request.extras.toString()); + n += 1; + dummyServer.respond({ + header: { status: 0, opaque: request.header.opaque }, + }); + }; + + const client = makeClient([dummyServer], { expires: 1024 }); + const assertor = function (err: Error | null, val: boolean | null) { + t.equal(null, err); + t.equal(true, val); + t.equal(1, n, "Ensure replace is called"); + }; + client.replace("hello", "world", {}, assertor); + n = 0; + const replaceP = client.replace("hello", "world", {}); + if (!replaceP) { + return t.true(replaceP); + } else { + return replaceP.then(function (success) { + assertor(null, success); + }); + } +}); + +test("ReplaceSuccessfulWithoutOption", function (t) { + let n = 0; + const dummyServer = makeDummyServer("dummyServer"); + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf); + t.equal("hello", request.key.toString()); + t.equal("world", request.val.toString()); + t.equal("\0\0\0\0\0\0\x04\0", request.extras.toString()); + n += 1; + dummyServer.respond({ + header: { status: 0, opaque: request.header.opaque }, + }); + }; + + const client = makeClient([dummyServer], { expires: 1024 }); + client.replace("hello", "world", {}, function (err: Error | null, val) { + t.equal(null, err); + t.equal(true, val); + t.equal(1, n, "Ensure replace is called"); + t.end(); + }); +}); + +test("ReplaceKeyDNE", function (t) { + let n = 0; + const dummyServer = makeDummyServer("dummyServer"); + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf); + t.equal("hello", request.key.toString()); + t.equal("world", request.val.toString()); + n += 1; + dummyServer.respond({ + header: { status: 1, opaque: request.header.opaque }, + }); + }; + + const client = makeClient([dummyServer]); + client.replace("hello", "world", {}, function (err: Error | null, val) { + t.equal(null, err); + t.equal(false, val); + t.equal(1, n, "Ensure replace is called"); + t.end(); + }); +}); + +test("DeleteSuccessful", function (t) { + let n = 0; + const dummyServer = makeDummyServer("dummyServer"); + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf); + t.equal("hello", request.key.toString()); + n += 1; + dummyServer.respond({ + header: { status: 0, opaque: request.header.opaque }, + }); + }; + + const client = makeClient([dummyServer]); + const assertor = function (err: Error | null, val: boolean | null) { + t.equal(null, err); + t.equal(true, val); + t.equal(1, n, "Ensure delete is called"); + }; + client.delete("hello", assertor); + n = 0; + return client.delete("hello").then(function (success) { + assertor(null, success); + }); +}); + +test("DeleteKeyDNE", function (t) { + let n = 0; + const dummyServer = makeDummyServer("dummyServer"); + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf); + t.equal("hello", request.key.toString()); + n += 1; + dummyServer.respond({ + header: { status: 1, opaque: request.header.opaque }, + }); + }; + + const client = makeClient([dummyServer]); + client.delete("hello", function (err: Error | null, val) { + t.equal(null, err); + t.equal(false, val); + t.equal(1, n, "Ensure delete is called"); + t.end(); + }); +}); + +test("Flush", function (t) { + let n = 0; + const dummyServer = makeDummyServer("dummyServer"); + dummyServer.host = "example.com"; + dummyServer.port = 1234; + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf); + t.equal(0x08, request.header.opcode); + n += 1; + dummyServer.respond({ + header: { status: 1, opaque: request.header.opaque }, + }); + }; + + const client = makeClient([dummyServer, dummyServer]); + const assertor = function ( + err: Error | null, + results: Record + ) { + t.equal(null, err); + t.equal(true, results["example.com:1234"]); + t.equal(2, n, "Ensure flush is called for each server"); + }; + client.flush(assertor); + n = 0; + return client.flush().then(function (results) { + assertor(null, results); + }); +}); + +test("Stats", function (t) { + let n = 0; + const dummyServer = makeDummyServer("dummyServer"); + dummyServer.host = "myhostname"; + dummyServer.port = 5544; + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf); + t.equal(0x10, request.header.opcode); + n += 1; + dummyServer.respond({ + header: { status: 0, totalBodyLength: 9, opaque: request.header.opaque }, + key: "bytes", + val: "1432", + }); + dummyServer.respond({ + header: { status: 0, totalBodyLength: 9, opaque: request.header.opaque }, + key: "count", + val: "5432", + }); + dummyServer.respond({ + header: { status: 0, totalBodyLength: 0, opaque: request.header.opaque }, + }); + }; + + const client = makeClient([dummyServer]); + client.stats(function (err: Error | null, server, stats) { + t.equal(null, err); + t.equal("1432", stats?.bytes); + t.equal("5432", stats?.count); + t.equal("myhostname:5544", server); + t.equal(1, n, "Ensure stats is called"); + t.end(); + }); +}); + +test("IncrementSuccessful", function (t) { + let n = 0; + let callbn = 0; + const dummyServer = makeDummyServer("dummyServer"); + + const expectedExtras = [ + "\0\0\0\0\0\0\0\x05\0\0\0\0\0\0\0\0\0\0\0\0", + "\0\0\0\0\0\0\0\x05\0\0\0\0\0\0\0\x03\0\0\0\0", + ]; + + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf); + t.equal(5, request.header.opcode); + t.equal("number-increment-test", request.key.toString()); + t.equal("", request.val.toString()); + t.equal(expectedExtras[n], request.extras.toString()); + n += 1; + process.nextTick(function () { + const value = Buffer.alloc(8); + value.writeUInt32BE(request.header.opcode + 1, 4); + value.writeUInt32BE(0, 0); + dummyServer.respond({ + header: { status: 0, opaque: request.header.opaque }, + val: value, + }); + }); + }; + + const client = makeClient([dummyServer]); + client.increment("number-increment-test", 5, {}, function ( + err: Error | null, + success, + val + ) { + callbn += 1; + t.equal(true, success); + t.equal(6, val); + t.equal(null, err); + done(); + }); + + client.increment("number-increment-test", 5, { initial: 3 }, function ( + err: Error | null, + success, + val + ) { + callbn += 1; + t.equal(true, success); + t.equal(6, val); + t.equal(null, err); + done(); + }); + + const done = (function () { + let called = 0; + return function () { + called += 1; + if (called < 2) return; + t.equal(2, n, "Ensure increment is called twice"); + t.equal(2, callbn, "Ensure callback is called twice"); + t.end(); + }; + })(); +}); + +test("DecrementSuccessful", function (t) { + let n = 0; + const dummyServer = makeDummyServer("dummyServer"); + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf); + t.equal(6, request.header.opcode); + t.equal("number-decrement-test", request.key.toString()); + t.equal("", request.val.toString()); + t.equal( + "\0\0\0\0\0\0\0\x05\0\0\0\0\0\0\0\0\0\0\0\0", + request.extras.toString() + ); + n += 1; + process.nextTick(function () { + const value = Buffer.alloc(8); + value.writeUInt32BE(request.header.opcode, 4); + value.writeUInt32BE(0, 0); + dummyServer.respond({ + header: { status: 0, opaque: request.header.opaque }, + val: value, + }); + }); + }; + + const client = makeClient([dummyServer]); + client.decrement("number-decrement-test", 5, {}, function ( + err: Error | null, + success, + val + ) { + t.equal(true, success); + t.equal(6, val); + t.equal(null, err); + t.equal(1, n, "Ensure decr is called"); + t.end(); + }); +}); + +test("DecrementSuccessfulWithoutOption", function (t) { + let n = 0; + const dummyServer = makeDummyServer("dummyServer"); + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf); + t.equal(6, request.header.opcode); + t.equal("number-decrement-test", request.key.toString()); + t.equal("", request.val.toString()); + t.equal( + "\0\0\0\0\0\0\0\x05\0\0\0\0\0\0\0\0\0\0\0\0", + request.extras.toString() + ); + n += 1; + process.nextTick(function () { + const value = Buffer.alloc(8); + value.writeUInt32BE(request.header.opcode, 4); + value.writeUInt32BE(0, 0); + dummyServer.respond({ + header: { status: 0, opaque: request.header.opaque }, + val: value, + }); + }); + }; + + const client = makeClient([dummyServer]); + client.decrement("number-decrement-test", 5, {}, function ( + err: Error | null, + success, + val + ) { + t.equal(true, success); + t.equal(6, val); + t.equal(null, err); + t.equal(1, n, "Ensure decr is called"); + t.end(); + }); +}); + +test("AppendSuccessful", function (t) { + let n = 0; + const dummyServer = makeDummyServer("dummyServer"); + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf); + t.equal("hello", request.key.toString()); + t.equal("world", request.val.toString()); + n += 1; + dummyServer.respond({ + header: { status: 0, opaque: request.header.opaque }, + }); + }; + + const client = makeClient([dummyServer], { expires: 1024 }); + client.append("hello", "world", function (err: Error | null, val) { + t.equal(null, err); + t.equal(true, val); + t.equal(1, n, "Ensure append is called"); + t.end(); + }); +}); + +test("AppendKeyDNE", function (t) { + let n = 0; + const dummyServer = makeDummyServer("dummyServer"); + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf); + t.equal("hello", request.key.toString()); + t.equal("world", request.val.toString()); + n += 1; + dummyServer.respond({ + header: { status: 1, opaque: request.header.opaque }, + }); + }; + + const client = makeClient([dummyServer]); + client.append("hello", "world", function (err: Error | null, val) { + t.equal(null, err); + t.equal(false, val); + t.equal(1, n, "Ensure append is called"); + t.end(); + }); +}); + +test("PrependSuccessful", function (t) { + let n = 0; + const dummyServer = makeDummyServer("dummyServer"); + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf); + t.equal("hello", request.key.toString()); + t.equal("world", request.val.toString()); + n += 1; + dummyServer.respond({ + header: { status: 0, opaque: request.header.opaque }, + }); + }; + + const client = makeClient([dummyServer], { expires: 1024 }); + client.prepend("hello", "world", function (err: Error | null, val) { + t.equal(null, err); + t.equal(true, val); + t.equal(1, n, "Ensure prepend is called"); + t.end(); + }); +}); + +test("PrependKeyDNE", function (t) { + let n = 0; + const dummyServer = makeDummyServer("dummyServer"); + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf); + t.equal("hello", request.key.toString()); + t.equal("world", request.val.toString()); + n += 1; + dummyServer.respond({ + header: { status: 1, opaque: request.header.opaque }, + }); + }; + + const client = makeClient([dummyServer]); + client.prepend("hello", "world", function (err: Error | null, val) { + t.equal(null, err); + t.equal(false, val); + t.equal(1, n, "Ensure prepend is called"); + t.end(); + }); +}); + +test("TouchSuccessful", function (t) { + let n = 0; + const dummyServer = makeDummyServer("dummyServer"); + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf); + t.equal("hello", request.key.toString()); + t.equal("", request.val.toString()); + t.equal("\0\0\x04\0", request.extras.toString()); + n += 1; + dummyServer.respond({ + header: { status: 0, opaque: request.header.opaque }, + }); + }; + + const client = makeClient([dummyServer]); + client.touch("hello", 1024, function (err: Error | null, val) { + t.equal(null, err); + t.equal(true, val); + t.equal(1, n, "Ensure touch is called"); + t.end(); + }); +}); + +test("TouchKeyDNE", function (t) { + let n = 0; + const dummyServer = makeDummyServer("dummyServer"); + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf); + t.equal("hello", request.key.toString()); + t.equal("", request.val.toString()); + t.equal("\0\0\x04\0", request.extras.toString()); + n += 1; + dummyServer.respond({ + header: { status: 1, opaque: request.header.opaque }, + }); + }; + + const client = makeClient([dummyServer]); + client.touch("hello", 1024, function (err: Error | null, val) { + t.equal(null, err); + t.equal(false, val); + t.equal(1, n, "Ensure ptouch is called"); + t.end(); + }); +}); + +// test('Failover', function(t) { +// let n1 = 0; +// let n2 = 0; +// const dummyServer1 = makeDummyServer('dummyServer'); +// dummyServer1.write = function(/* requestBuf*/) { +// n1 += 1; +// dummyServer1.error(new Error('connection failure')); +// }; +// const dummyServer2 = makeDummyServer('dummyServer'); +// dummyServer2.write = function(requestBuf) { +// n2 += 1; +// const request = parseMessage(requestBuf); +// dummyServer2.respond({header: {status: 0, opaque: request.header.opaque}}); +// }; + +// const client = makeClient([dummyServer1, dummyServer2], {failover: true}); +// client.get('\0', function(err/*, val */){ +// t.equal(null, err); +// t.equal(2, n1); +// t.equal(1, n2); +// t.end(); +// }); + +// }); + +test("Very Large Client Seq", function (t) { + let n = 0; + const dummyServer = makeDummyServer("dummyServer"); + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf); + t.equal("hello", request.key.toString()); + t.equal("world", request.val.toString()); + t.equal("0000000000000400", request.extras.toString("hex")); + n += 1; + dummyServer.respond({ + header: { status: 0, opaque: request.header.opaque }, + }); + }; + + const client = makeClient([dummyServer], { expires: 1024 }); + client.seq = Math.pow(2, 33); + const assertor = function (err: Error | null, val: boolean | null) { + t.equal(null, err); + t.equal(true, val); + t.equal(1, n, "Ensure add is called"); + }; + client.add("hello", "world", {}, assertor); + n = 0; + return client.add("hello", "world", {}).then(function (success) { + assertor(null, success); + }); +}); + +const makeDummyVersionServer = ( + t: TapTestType, + serverKey: string, + version: string +) => { + const dummyServer = makeDummyServer(serverKey); + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf); + t.deepEqual(Buffer.from(""), request.key); + dummyServer.respond({ + header: { status: 0, opaque: request.header.opaque }, + val: version, + extras: "flagshere", + }); + }; + return dummyServer; +}; + +test("VersionSuccessful", function (t) { + let n = 0; + + const dummyServer = makeDummyVersionServer(t, "dummyServer", "1.3.1"); + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf); + t.deepEqual(Buffer.from(""), request.key); + n += 1; + dummyServer.respond({ + header: { status: 0, opaque: request.header.opaque }, + val: "1.3.1", + extras: "flagshere", + }); + }; + + const client = makeClient([dummyServer]); + const assertor = function (err: Error | null, val: any, flags: string) { + t.equal("1.3.1", val); + t.equal("flagshere", flags); + t.equal(null, err); + t.equal(n, 1, "Ensure version is called"); + }; + + client.version(assertor); + n = 0; + + return client.version().then(function (res) { + assertor(null, res.value, res.flags); + }); +}); + +tap.only("VersionError", function (t) { + const dummyServer = makeDummyServer("dummyServer"); + dummyServer.write = function () { + dummyServer.error({ + name: "ErrorName", + message: "This is an expected error.", + }); + }; + + const client = makeClient([dummyServer]); + const assertor = function ( + err: Error | null, + value?: string | Buffer | null, + flags?: any + ) { + t.notEqual(null, err); + t.equal("This is an expected error.", err?.message); + }; + + client.version(assertor); + return client.version().catch(function (err) { + assertor(err); + return true; + }); +}); + +test("VersionAllSuccessful", function (t) { + const dummyServer1 = makeDummyVersionServer(t, "dummyServer1", "1.0.0"); + const dummyServer2 = makeDummyVersionServer(t, "dummyServer2", "2.0.0"); + const dummyServer3 = makeDummyVersionServer(t, "dummyServer3", "3.0.0"); + + const client = makeClient([dummyServer1, dummyServer2, dummyServer3]); + const assertor = function ( + err: Error | null, + val?: Record | null + ) { + t.deepEqual( + { + "dummyServer1:undefined": "1.0.0", + "dummyServer2:undefined": "2.0.0", + "dummyServer3:undefined": "3.0.0", + }, + val + ); + t.equal(null, err); + }; + + client.versionAll(assertor); + + return client.versionAll().then(function (res) { + assertor(null, res.values); + }); +}); + +tap.only("VersionAllSomeFailed", function (t) { + const dummyServer1 = makeDummyVersionServer(t, "dummyServer1", "1.0.0"); + const dummyServer2 = makeDummyVersionServer(t, "dummyServer2", "2.0.0"); + dummyServer2.write = function () { + dummyServer2.error({ + name: "ErrorName", + message: "This is an expected error.", + }); + }; + const dummyServer3 = makeDummyVersionServer(t, "dummyServer3", "3.0.0"); + + const client = makeClient([dummyServer1, dummyServer2, dummyServer3]); + const assertor = function (err: Error | null) { + t.notEqual(null, err); + t.equal("This is an expected error.", err?.message); + }; + + client.versionAll(assertor); + + return client.versionAll().catch(function (err) { + assertor(err); + }); +}); diff --git a/test/header_test.js b/src/test/header_test.js similarity index 97% rename from test/header_test.js rename to src/test/header_test.js index 802f2ae..f2e2fbf 100644 --- a/test/header_test.js +++ b/src/test/header_test.js @@ -1,5 +1,5 @@ const test = require('tap').test; -const header = require('../lib/memjs/header'); +const header = require('../memjs/header'); test('ParseHeaderResponse', function(t) { const headerBuf = Buffer.from([0x81, 1, 7, 0, 4, 3, 0, 1, 0, 0, 0, 9, 0, 0, 0, 0, 0x0a, 0, 0, 0, 0, 0, 0, 0]); diff --git a/test/server_test.js b/src/test/server_test.js similarity index 97% rename from test/server_test.js rename to src/test/server_test.js index c0d5fd1..7ed0112 100644 --- a/test/server_test.js +++ b/src/test/server_test.js @@ -1,6 +1,6 @@ const test = require('tap').test; const MemJS = require('../'); -const makeRequestBuffer = require('../lib/memjs/utils').makeRequestBuffer; +const makeRequestBuffer = require('../memjs/utils').makeRequestBuffer; test('AuthListMechanisms', function(t) { const expectedBuf = makeRequestBuffer(0x20, '', '', ''); diff --git a/test/utils_test.js b/src/test/utils_test.js similarity index 97% rename from test/utils_test.js rename to src/test/utils_test.js index b7e0438..efb6d29 100644 --- a/test/utils_test.js +++ b/src/test/utils_test.js @@ -1,5 +1,5 @@ const test = require('tap').test; -const utils = require('../lib/memjs/utils'); +const utils = require('../memjs/utils'); test('MergePresereParameter', function(t) { const result = utils.merge({}, { retries: 2 }); diff --git a/test/client_test.ts b/test/client_test.ts deleted file mode 100644 index cc12b4e..0000000 --- a/test/client_test.ts +++ /dev/null @@ -1,1444 +0,0 @@ -import tap from 'tap' -const test = tap.test - -const errors = require("../src/memjs/protocol").errors -import MemJS = require("../src") -import constants = require("../src/memjs/constants") -import { noopSerializer } from "../src/memjs/noop-serializer" -import { Header } from "../src/memjs/header" -import type { GivenClientOptions } from "../src/memjs/memjs" -import * as Utils from "../src/memjs/utils" -import { MaybeBuffer } from "../src/memjs/utils" - -// I could not figure out a better way to extract this from the typedefs -type TapTestType = (typeof tap)["Test"]["prototype"] - -function testAllCallbacksEmpty(t: TapTestType, server: MemJS.Server) { - t.deepEqual(Object.keys(server.responseCallbacks).length, 0) - t.deepEqual(Object.keys(server.errorCallbacks).length, 0) - - t.deepEqual(server.requestTimeouts, []) -} - -function makeClient(dummyServer: MemJS.Server | MemJS.Server[], options?: GivenClientOptions) { - return new MemJS.Client( - Array.isArray(dummyServer) ? dummyServer : [dummyServer], - options || { serializer: noopSerializer } - ) -} - -function parseMessage(requestBuf: Buffer) { - const message = Utils.parseMessage(requestBuf) - if (!message) { - throw new Error("Expected message to parse successfully, but got false") - } - return message -} - -function makeDummyServer(name: string) { - /* NOTE(blackmad): awful hack - MemJS natively speaks Buffers, but they are annoying - to test, so we shim it in some ugly ways to return strings which are easier to work - with. We should fix this at some point. - */ - return new MemJS.Server(name) as MemJS.Server & { - respond: (m: { - extras?: string | Buffer, - key?: string | Buffer, - val?: string | Buffer, - header: Partial
}) => void - } -} - -test("GetSuccessful", function (t) { - let n = 0 - const dummyServer = makeDummyServer("dummyServer") - dummyServer.write = function (requestBuf) { - const request = parseMessage(requestBuf) - t.equal("hello", request.key.toString()) - n += 1 - dummyServer.respond({ - header: { status: 0, opaque: request.header.opaque }, - val: "world", - extras: "flagshere", - }) - } - - const client = makeClient([dummyServer]) - const assertor = function (err: Error | null, val: string | MaybeBuffer | null, flags: string) { - t.equal("world", val) - t.equal("flagshere", flags) - t.equal(null, err) - t.equal(1, n, "Ensure get is called") - } - client.get("hello", assertor) - n = 0 - return client.get("hello").then(function (res) { - assertor(null, res.value, res.flags) - }) -}) - -test("GetNotFound", function (t) { - let n = 0 - const dummyServer = makeDummyServer("dummyServer") - dummyServer.write = function (requestBuf) { - const request = parseMessage(requestBuf) - t.equal("hello", request.key.toString()) - n += 1 - dummyServer.respond({ - header: { status: 1, opaque: request.header.opaque }, - }) - } - - const client = makeClient([dummyServer]) - const assertor = function (err: Error | null, val: string | MaybeBuffer | null) { - t.equal(null, val) - t.equal(1, n, "Ensure get is called") - } - client.get("hello", assertor) - n = 0 - return client.get("hello").then(function (res) { - assertor(null, res.value) - t.end() - }) -}) - -test("GetSerializer", function (t) { - let n = 0 - let dn = 0 - const dummyServer = makeDummyServer("dummyServer") - dummyServer.write = function (requestBuf) { - const request = parseMessage(requestBuf) - t.equal("hello", request.key.toString()) - n += 1 - dummyServer.respond({ - header: { status: 0, opaque: request.header.opaque }, - val: "world", - extras: "flagshere", - }) - } - - const client = makeClient([dummyServer], { - serializer: { - serialize: function (opcode, value, extras) { - return { value: value, extras: extras } - }, - deserialize: function (opcode, value, extras) { - dn += 1 - return { value: "deserialized", extras: extras } - }, - }, - }) - const assertor = function (err: Error | null, val: string | Buffer | null, flags: string) { - t.equal("deserialized", val) - t.equal("flagshere", flags) - t.equal(null, err) - t.equal(1, n, "Ensure get is called") - t.equal(1, dn, "Ensure deserialization is called once") - } - client.get("hello", assertor) - n = 0 - dn = 0 - return client.get("hello").then(function (res) { - assertor(null, res.value, res.flags) - }) -}) - -tap.only("GetMultiSuccessful_SingleBackend", function (t) { - let n = 0 - const dummyServer = makeDummyServer("dummyServer") - dummyServer.write = function (requestBuf) { - const requests = Utils.parseMessages(requestBuf) - t.equal(requests.length, 4) - n += 1 - - function checkAndRespond(request: Utils.Message, key: string, value: string) { - t.equal(key, request.key.toString()) - t.equal(constants.OP_GETKQ, request.header.opcode) - - dummyServer.respond({ - header: { - status: 0, - opaque: request.header.opaque, - opcode: request.header.opcode, - }, - key: key, - val: value, - extras: "flagshere", - }) - } - checkAndRespond(requests[0], "hello1", "world1") - checkAndRespond(requests[1], "hello2", "world2") - checkAndRespond(requests[2], "hello3", "world3") - - t.equal(constants.OP_NO_OP, requests[3].header.opcode) - dummyServer.respond({ - header: { - status: 0, - opaque: requests[3].header.opaque, - opcode: requests[3].header.opcode, - }, - }) - } - - const client = makeClient([dummyServer]) - const assertor = function (err: Error | null, val: any, flags: string) { - t.deepEqual( - { - hello1: "world1", - hello2: "world2", - hello3: "world3", - }, - val - ) - t.false(flags) - t.equal(null, err) - t.equal(1, n, "Ensure getMulti is called") - } - client.getMulti(["hello1", "hello2", "hello3"], assertor) - testAllCallbacksEmpty(t, dummyServer) - - n = 0 - return client.getMulti(["hello1", "hello2", "hello3"]).then(function (res) { - assertor(null, res.values, res.flags) - }) -}) - -function makeDummyMultiGetServerResponder(t: TapTestType, responseMap: Record, serverName?: string) { - const server = makeDummyServer(serverName || "dummyServer") - const responder = function (requestBuf: Buffer) { - const requests = Utils.parseMessages(requestBuf) - t.equal(requests.length, Object.keys(responseMap).length + 1) - - function checkAndRespond(request: Utils.Message, key: string, value: string | undefined) { - t.equal(constants.OP_GETKQ, request.header.opcode) - - if (value !== undefined) { - server.respond({ - header: { - status: 0, - opaque: request.header.opaque, - opcode: request.header.opcode, - }, - key: key, - val: value, - extras: "flagshere", - }) - } - } - - for (const requestIndex in requests) { - const request = requests[requestIndex] - - if (requestIndex === (requests.length - 1).toString()) { - t.equal(constants.OP_NO_OP, request.header.opcode) - server.respond({ - header: { - status: 0, - opaque: request.header.opaque, - opcode: request.header.opcode, - }, - }) - } else { - const key = request.key.toString() - checkAndRespond(request, key, responseMap[key]) - } - } - } - server.write = responder - return server -} - -test("GetMultiSuccessful_MultiBackend", function (t) { - // the mappings from key to server were computer by just manually running the default hash on them - - const dummyServer1 = makeDummyMultiGetServerResponder( - t, - { - hello2: "world2", - hello4: "world4", - }, - "dummyServer1" - ) - const dummyServer2 = makeDummyMultiGetServerResponder( - t, - { - hello1: "world1", - hello3: "world3", - }, - "dummyServer2" - ) - const servers = [dummyServer1, dummyServer2] - - const client = makeClient(servers) - - const assertor = function (err: Error | null, val: any, flags: string) { - t.deepEqual( - { - hello1: "world1", - hello2: "world2", - hello3: "world3", - hello4: "world4", - }, - val - ) - t.false(flags) - t.equal(null, err) - } - client.getMulti(["hello1", "hello2", "hello3", "hello4"], assertor) - testAllCallbacksEmpty(t, dummyServer1) - testAllCallbacksEmpty(t, dummyServer2) - - return client - .getMulti(["hello1", "hello2", "hello3", "hello4"]) - .then(function (res) { - assertor(null, res.values, res.flags) - }) -}) - -test("GetMultiSuccessful_MissingKeys_MultiBackend", function (t) { - // the mappings from key to server were computed by just manually running the default hash on them - const dummyServer1 = makeDummyMultiGetServerResponder( - t, - { - hello2: undefined, - hello4: "world4", - }, - "dummyServer1" - ) - const dummyServer2 = makeDummyMultiGetServerResponder( - t, - { - hello1: "world1", - hello3: "world3", - }, - "dummyServer2" - ) - const servers = [dummyServer1, dummyServer2] - - const client = makeClient(servers) - - const assertor = function (err: Error | null, val: any, flags: string) { - t.deepEqual( - { - hello1: "world1", - hello3: "world3", - hello4: "world4", - }, - val - ) - t.false(flags) - t.equal(null, err) - } - client.getMulti(["hello1", "hello2", "hello3", "hello4"], assertor) - testAllCallbacksEmpty(t, dummyServer1) - testAllCallbacksEmpty(t, dummyServer2) - - return client - .getMulti(["hello1", "hello2", "hello3", "hello4"]) - .then(function (res) { - assertor(null, res.values, res.flags) - }) -}) - -test("GetMultiError_MultiBackend", function (t) { - // the mappings from key to server were computed by just manually running the default hash on them - const dummyServer1 = makeDummyMultiGetServerResponder( - t, - { - hello2: undefined, - hello4: "world4", - }, - "dummyServer1" - ) - const dummyServer2 = makeDummyMultiGetServerResponder( - t, - { - hello1: "world1", - hello3: "world3", - }, - "dummyServer2" - ) - dummyServer2.write = function () { - dummyServer2.error({ name: "ErrorName", message: "This is an expected error." }) - } - const servers = [dummyServer1, dummyServer2] - - const client = makeClient(servers) - - const assertor = function (err: Error | null) { - t.notEqual(null, err) - t.equal("This is an expected error.", err?.message) - } - client.getMulti(["hello1", "hello2", "hello3", "hello4"], assertor) - testAllCallbacksEmpty(t, dummyServer1) - testAllCallbacksEmpty(t, dummyServer2) - - return client - .getMulti(["hello1", "hello2", "hello3", "hello4"]) - .catch(function (err) { - assertor(err) - return true - }) -}) - -test("GetMultiSuccessfulWithMissingKeys", function (t) { - const dummyServer = makeDummyMultiGetServerResponder(t, { - hello1: "world1", - hello2: undefined, - hello3: "world3", - }) - - const client = makeClient([dummyServer], { serializer: noopSerializer }) - const assertor = function (err: Error | null, val: any, flags: string) { - t.deepEqual( - { - hello1: "world1", - hello3: "world3", - }, - val - ) - t.false(flags) - t.equal(null, err) - } - client.getMulti(["hello1", "hello2", "hello3"], assertor) - testAllCallbacksEmpty(t, dummyServer) - return client.getMulti(["hello1", "hello2", "hello3"]).then(function (res) { - assertor(null, res.values, res.flags) - }) -}) - -test("GetMultiError", function (t) { - const dummyServer = makeDummyServer("dummyServer") - dummyServer.write = function (requestBuf) { - const requests = Utils.parseMessages(requestBuf) - t.equal(requests.length, 4) - - function checkAndRespond(request: Utils.Message, key: string, value: string) { - t.equal(key, request.key.toString()) - t.equal(constants.OP_GETKQ, request.header.opcode) - - dummyServer.respond({ - header: { - status: 0, - opaque: request.header.opaque, - opcode: request.header.opcode, - }, - key: key, - val: value, - extras: "flagshere", - }) - } - checkAndRespond(requests[0], "hello1", "world1") - dummyServer.error({ name: "ErrorName", message: "This is an expected error." }) - } - - const client = makeClient([dummyServer]) - const assertor = function (err: Error | null) { - t.notEqual(null, err) - t.equal("This is an expected error.", err?.message) - } - client.getMulti(["hello1", "hello2", "hello3"], assertor) - testAllCallbacksEmpty(t, dummyServer) - - return client.getMulti(["hello1", "hello2", "hello3"]).catch(function (err) { - assertor(err) - return true - }) -}) - -test("SetSuccessful", function (t) { - let n = 0 - const dummyServer = makeDummyServer("dummyServer") - dummyServer.write = function (requestBuf) { - const request = parseMessage(requestBuf) - t.equal("hello", request.key.toString()) - t.equal("world", request.val.toString()) - n += 1 - dummyServer.respond({ - header: { status: 0, opaque: request.header.opaque }, - }) - } - - const client = makeClient([dummyServer]) - const assertor = function (err: Error | null, val: boolean | null) { - t.equal(true, val) - t.equal(null, err) - t.equal(1, n, "Ensure set is called") - } - client.set("hello", "world", {}, assertor) - n = 0 - return client.set("hello", "world", {}).then(function (success) { - assertor(null, success) - }) -}) - -test("SetSuccessfulWithoutOption", function (t) { - let n = 0 - const dummyServer = makeDummyServer("dummyServer") - dummyServer.write = function (requestBuf) { - const request = parseMessage(requestBuf) - t.equal("hello", request.key.toString()) - t.equal("world", request.val.toString()) - n += 1 - dummyServer.respond({ - header: { status: 0, opaque: request.header.opaque }, - }) - } - - const client = makeClient([dummyServer]) - client.set("hello", "world", {}, function (err: Error | null, val) { - t.equal(true, val) - t.equal(null, err) - t.equal(1, n, "Ensure set is called") - t.end() - }) -}) - -test("SetPromiseWithoutOption", function (t) { - let n = 0 - const dummyServer = makeDummyServer("dummyServer") - dummyServer.write = function (requestBuf) { - const request = parseMessage(requestBuf) - t.equal("hello", request.key.toString()) - t.equal("world", request.val.toString()) - n += 1 - dummyServer.respond({ - header: { status: 0, opaque: request.header.opaque }, - }) - } - - const client = makeClient([dummyServer]) - return client.set("hello", "world").then(function (val) { - t.equal(true, val) - t.equal(1, n, "Ensure set is called") - t.end() - }) -}) - -test("SetWithExpiration", function (t) { - let n = 0 - const dummyServer = makeDummyServer("dummyServer") - dummyServer.write = function (requestBuf) { - const request = parseMessage(requestBuf) - t.equal("hello", request.key.toString()) - t.equal("world", request.val.toString()) - t.equal("\0\0\0\0\0\0\x04\0", request.extras.toString()) - n += 1 - dummyServer.respond({ - header: { status: 0, opaque: request.header.opaque }, - }) - } - - const client = makeClient([dummyServer], { expires: 1024 }) - client.set("hello", "world", {}, function (err: Error | null, val) { - t.equal(null, err) - t.equal(true, val) - t.equal(1, n, "Ensure set is called") - t.end() - }) -}) - -test("SetUnsuccessful", function (t) { - let n = 0 - const dummyServer = makeDummyServer("dummyServer") - dummyServer.write = function (requestBuf) { - const request = parseMessage(requestBuf) - t.equal("hello", request.key.toString()) - t.equal("world", request.val.toString()) - n += 1 - dummyServer.respond({ - header: { status: 3, opaque: request.header.opaque }, - }) - } - - const client = makeClient([dummyServer]) - const assertor = function (err: Error | null, val: boolean | null) { - t.equal(null, val) - t.equal("MemJS SET: " + errors[3], err?.message) - t.equal(1, n, "Ensure set is called") - } - client.set("hello", "world", {}, assertor) - n = 0 - return client.set("hello", "world", {}).catch(function (err) { - assertor(err, null) - }) -}) - -test("SetError", function (t) { - let n = 0 - const dummyServer = makeDummyServer("dummyServer") - dummyServer.write = function (requestBuf) { - const request = parseMessage(requestBuf) - t.equal("hello", request.key.toString()) - t.equal("world", request.val.toString()) - n += 1 - dummyServer.error({ name: "ErrorName", message: "This is an expected error." }) - } - - const client = makeClient([dummyServer]) - client.set("hello", "world", {}, function (err: Error | null, val) { - t.notEqual(null, err) - t.equal("This is an expected error.", err?.message) - t.equal(null, val) - t.equal(2, n, "Ensure set is retried once") - t.end() - }) -}) - -test("SetError", function (t) { - let n = 0 - const dummyServer = makeDummyServer("dummyServer") - dummyServer.write = function (requestBuf) { - const request = parseMessage(requestBuf) - t.equal("hello", request.key.toString()) - t.equal("world", request.val.toString()) - setTimeout(function () { - n += 1 - dummyServer.error({ name: "ErrorName", message: "This is an expected error." }) - }, 100) - } - - const client = makeClient([dummyServer], { retries: 2 }) - client.set("hello", "world", {}, function (err /*, val */) { - t.equal(2, n, "Ensure set is retried once") - t.ok(err, "Ensure callback called with error") - t.equal("This is an expected error.", err?.message) - t.end() - }) -}) - -test("SetErrorConcurrent", function (t) { - let n = 0 - let callbn1 = 0 - let callbn2 = 0 - const dummyServer = makeDummyServer("dummyServer") - dummyServer.write = function (/* requestBuf */) { - n += 1 - dummyServer.error({ name: "ErrorName", message: "This is an expected error." }) - } - - const client = makeClient([dummyServer], { retries: 2 }) - client.set("hello", "world", {}, function (err /*, val */) { - t.ok(err, "Ensure callback called with error") - t.equal("This is an expected error.", err?.message) - callbn1 += 1 - done() - }) - - client.set("foo", "bar", {}, function (err /*, val */) { - t.ok(err, "Ensure callback called with error") - t.equal("This is an expected error.", err?.message) - callbn2 += 1 - done() - }) - - const done = (function () { - let called = 0 - return function () { - called += 1 - if (called < 2) return - t.equal(1, callbn1, "Ensure callback 1 is called once") - t.equal(1, callbn2, "Ensure callback 2 is called once") - t.equal(4, n, "Ensure error sent twice for each set call") - t.end() - } - })() -}) - -test("SetUnicode", function (t) { - let n = 0 - const dummyServer = makeDummyServer("dummyServer") - dummyServer.write = function (requestBuf) { - const request = parseMessage(requestBuf) - t.equal("hello", request.key.toString()) - t.equal("éééoào", request.val.toString()) - n += 1 - dummyServer.respond({ - header: { status: 0, opaque: request.header.opaque }, - }) - } - - const client = makeClient([dummyServer]) - client.set("hello", "éééoào", {}, function (err: Error | null, val) { - t.equal(true, val) - t.equal(1, n, "Ensure set is called") - t.end() - }) -}) - -test("SetSerialize", function (t) { - let n = 0 - let sn = 0 - const dummyServer = makeDummyServer("dummyServer") - dummyServer.write = function (requestBuf) { - const request = parseMessage(requestBuf) - t.equal("hello", request.key.toString()) - t.equal("serialized", request.val.toString()) - n += 1 - dummyServer.respond({ - header: { status: 3, opaque: request.header.opaque }, - }) - } - - const client = makeClient([dummyServer], { - serializer: { - serialize: function (opcode, value, extras) { - sn += 1 - return { value: "serialized", extras: extras } - }, - deserialize: function (opcode, value, extras) { - return { value: value, extras: extras } - }, - }, - }) - const assertor = function (err: Error | null, val: boolean | null) { - t.equal(null, val) - t.equal("MemJS SET: " + errors[3], err?.message) - t.equal(1, n, "Ensure set is called") - t.equal(1, sn, "Ensure serialization is called once") - } - client.set("hello", "world", {}, assertor) - n = 0 - sn = 0 - return client.set("hello", "world", {}).catch(function (err) { - assertor(err, null) - }) -}) - -test("AddSuccessful", function (t) { - let n = 0 - const dummyServer = makeDummyServer("dummyServer") - dummyServer.write = function (requestBuf) { - const request = parseMessage(requestBuf) - t.equal("hello", request.key.toString()) - t.equal("world", request.val.toString()) - t.equal("0000000000000400", request.extras.toString("hex")) - n += 1 - dummyServer.respond({ - header: { status: 0, opaque: request.header.opaque }, - }) - } - - const client = makeClient([dummyServer], { expires: 1024 }) - const assertor = function (err: Error | null, val: boolean | null) { - t.equal(null, err) - t.equal(true, val) - t.equal(1, n, "Ensure add is called") - } - client.add("hello", "world", {}, assertor) - n = 0 - return client.add("hello", "world", {}).then(function (success) { - assertor(null, success) - }) -}) - -test("AddSuccessfulWithoutOption", function (t) { - let n = 0 - const dummyServer = makeDummyServer("dummyServer") - dummyServer.write = function (requestBuf) { - const request = parseMessage(requestBuf) - t.equal("hello", request.key.toString()) - t.equal("world", request.val.toString()) - t.equal("0000000000000400", request.extras.toString("hex")) - n += 1 - dummyServer.respond({ - header: { status: 0, opaque: request.header.opaque }, - }) - } - - const client = makeClient([dummyServer], { expires: 1024 }) - client.add("hello", "world", {}, function (err: Error | null, val) { - t.equal(null, err) - t.equal(true, val) - t.equal(1, n, "Ensure add is called") - t.end() - }) -}) - -test("AddKeyExists", function (t) { - let n = 0 - const dummyServer = makeDummyServer("dummyServer") - dummyServer.write = function (requestBuf) { - const request = parseMessage(requestBuf) - t.equal("hello", request.key.toString()) - t.equal("world", request.val.toString()) - n += 1 - dummyServer.respond({ - header: { status: 2, opaque: request.header.opaque }, - }) - } - - const client = makeClient([dummyServer]) - client.add("hello", "world", {}, function (err: Error | null, val) { - t.equal(null, err) - t.equal(false, val) - t.equal(1, n, "Ensure add is called") - t.end() - }) -}) - -test("AddSerializer", function (t) { - let n = 0 - let sn = 0 - const dummyServer = makeDummyServer("dummyServer") - dummyServer.write = function (requestBuf) { - const request = parseMessage(requestBuf) - t.equal("hello", request.key.toString()) - t.equal("serialized", request.val.toString()) - t.equal("0000000100000400", request.extras.toString("hex")) - n += 1 - dummyServer.respond({ - header: { status: 0, opaque: request.header.opaque }, - }) - } - - const client = makeClient([dummyServer], { - expires: 1024, - serializer: { - serialize: function (opcode, value, extras) { - sn += 1 - if (Buffer.isBuffer(extras)) { - extras.writeUInt32BE(1, 0) - } - return { value: "serialized", extras: extras } - }, - deserialize: function (opcode, value, extras) { - return { value: value, extras: extras } - }, - }, - }) - const assertor = function (err: Error | null, val: boolean | null) { - t.equal(null, err) - t.equal(true, val) - t.equal(1, n, "Ensure add is called") - t.equal(1, sn, "Ensure serialization is called once") - } - client.add("hello", "world", {}, assertor) - n = 0 - sn = 0 - return client.add("hello", "world", {}).then(function (success) { - assertor(null, success) - }) -}) - -test("ReplaceSuccessful", function (t) { - let n = 0 - const dummyServer = makeDummyServer("dummyServer") - dummyServer.write = function (requestBuf) { - const request = parseMessage(requestBuf) - t.equal("hello", request.key.toString()) - t.equal("world", request.val.toString()) - t.equal("\0\0\0\0\0\0\x04\0", request.extras.toString()) - n += 1 - dummyServer.respond({ - header: { status: 0, opaque: request.header.opaque }, - }) - } - - const client = makeClient([dummyServer], { expires: 1024 }) - const assertor = function (err: Error | null, val: boolean | null) { - t.equal(null, err) - t.equal(true, val) - t.equal(1, n, "Ensure replace is called") - } - client.replace("hello", "world", {}, assertor) - n = 0 - const replaceP = client.replace("hello", "world", {}) - if (!replaceP) { - return t.true(replaceP) - } else { - return replaceP.then(function (success) { - assertor(null, success) - }) - } -}) - -test("ReplaceSuccessfulWithoutOption", function (t) { - let n = 0 - const dummyServer = makeDummyServer("dummyServer") - dummyServer.write = function (requestBuf) { - const request = parseMessage(requestBuf) - t.equal("hello", request.key.toString()) - t.equal("world", request.val.toString()) - t.equal("\0\0\0\0\0\0\x04\0", request.extras.toString()) - n += 1 - dummyServer.respond({ - header: { status: 0, opaque: request.header.opaque }, - }) - } - - const client = makeClient([dummyServer], { expires: 1024 }) - client.replace("hello", "world", {}, function (err: Error | null, val) { - t.equal(null, err) - t.equal(true, val) - t.equal(1, n, "Ensure replace is called") - t.end() - }) -}) - -test("ReplaceKeyDNE", function (t) { - let n = 0 - const dummyServer = makeDummyServer("dummyServer") - dummyServer.write = function (requestBuf) { - const request = parseMessage(requestBuf) - t.equal("hello", request.key.toString()) - t.equal("world", request.val.toString()) - n += 1 - dummyServer.respond({ - header: { status: 1, opaque: request.header.opaque }, - }) - } - - const client = makeClient([dummyServer]) - client.replace("hello", "world", {}, function (err: Error | null, val) { - t.equal(null, err) - t.equal(false, val) - t.equal(1, n, "Ensure replace is called") - t.end() - }) -}) - -test("DeleteSuccessful", function (t) { - let n = 0 - const dummyServer = makeDummyServer("dummyServer") - dummyServer.write = function (requestBuf) { - const request = parseMessage(requestBuf) - t.equal("hello", request.key.toString()) - n += 1 - dummyServer.respond({ - header: { status: 0, opaque: request.header.opaque }, - }) - } - - const client = makeClient([dummyServer]) - const assertor = function (err: Error | null, val: boolean | null) { - t.equal(null, err) - t.equal(true, val) - t.equal(1, n, "Ensure delete is called") - } - client.delete("hello", assertor) - n = 0 - return client.delete("hello").then(function (success) { - assertor(null, success) - }) -}) - -test("DeleteKeyDNE", function (t) { - let n = 0 - const dummyServer = makeDummyServer("dummyServer") - dummyServer.write = function (requestBuf) { - const request = parseMessage(requestBuf) - t.equal("hello", request.key.toString()) - n += 1 - dummyServer.respond({ - header: { status: 1, opaque: request.header.opaque }, - }) - } - - const client = makeClient([dummyServer]) - client.delete("hello", function (err: Error | null, val) { - t.equal(null, err) - t.equal(false, val) - t.equal(1, n, "Ensure delete is called") - t.end() - }) -}) - -test("Flush", function (t) { - let n = 0 - const dummyServer = makeDummyServer("dummyServer") - dummyServer.host = "example.com" - dummyServer.port = 1234 - dummyServer.write = function (requestBuf) { - const request = parseMessage(requestBuf) - t.equal(0x08, request.header.opcode) - n += 1 - dummyServer.respond({ - header: { status: 1, opaque: request.header.opaque }, - }) - } - - const client = makeClient([dummyServer, dummyServer]) - const assertor = function (err: Error | null, results: Record) { - t.equal(null, err) - t.equal(true, results["example.com:1234"]) - t.equal(2, n, "Ensure flush is called for each server") - } - client.flush(assertor) - n = 0 - return client.flush().then(function (results) { - assertor(null, results) - }) -}) - -test("Stats", function (t) { - let n = 0 - const dummyServer = makeDummyServer("dummyServer") - dummyServer.host = "myhostname" - dummyServer.port = 5544 - dummyServer.write = function (requestBuf) { - const request = parseMessage(requestBuf) - t.equal(0x10, request.header.opcode) - n += 1 - dummyServer.respond({ - header: { status: 0, totalBodyLength: 9, opaque: request.header.opaque }, - key: "bytes", - val: "1432", - }) - dummyServer.respond({ - header: { status: 0, totalBodyLength: 9, opaque: request.header.opaque }, - key: "count", - val: "5432", - }) - dummyServer.respond({ - header: { status: 0, totalBodyLength: 0, opaque: request.header.opaque }, - }) - } - - const client = makeClient([dummyServer]) - client.stats(function (err: Error | null, server, stats) { - t.equal(null, err) - t.equal("1432", stats?.bytes) - t.equal("5432", stats?.count) - t.equal("myhostname:5544", server) - t.equal(1, n, "Ensure stats is called") - t.end() - }) -}) - -test("IncrementSuccessful", function (t) { - let n = 0 - let callbn = 0 - const dummyServer = makeDummyServer("dummyServer") - - const expectedExtras = [ - "\0\0\0\0\0\0\0\x05\0\0\0\0\0\0\0\0\0\0\0\0", - "\0\0\0\0\0\0\0\x05\0\0\0\0\0\0\0\x03\0\0\0\0", - ] - - dummyServer.write = function (requestBuf) { - const request = parseMessage(requestBuf) - t.equal(5, request.header.opcode) - t.equal("number-increment-test", request.key.toString()) - t.equal("", request.val.toString()) - t.equal(expectedExtras[n], request.extras.toString()) - n += 1 - process.nextTick(function () { - const value = Buffer.alloc(8) - value.writeUInt32BE(request.header.opcode + 1, 4) - value.writeUInt32BE(0, 0) - dummyServer.respond({ - header: { status: 0, opaque: request.header.opaque }, - val: value, - }) - }) - } - - const client = makeClient([dummyServer]) - client.increment( - "number-increment-test", - 5, - {}, - function (err: Error | null, success, val) { - callbn += 1 - t.equal(true, success) - t.equal(6, val) - t.equal(null, err) - done() - } - ) - - client.increment( - "number-increment-test", - 5, - { initial: 3 }, - function (err: Error | null, success, val) { - callbn += 1 - t.equal(true, success) - t.equal(6, val) - t.equal(null, err) - done() - } - ) - - const done = (function () { - let called = 0 - return function () { - called += 1 - if (called < 2) return - t.equal(2, n, "Ensure increment is called twice") - t.equal(2, callbn, "Ensure callback is called twice") - t.end() - } - })() -}) - -test("DecrementSuccessful", function (t) { - let n = 0 - const dummyServer = makeDummyServer("dummyServer") - dummyServer.write = function (requestBuf) { - const request = parseMessage(requestBuf) - t.equal(6, request.header.opcode) - t.equal("number-decrement-test", request.key.toString()) - t.equal("", request.val.toString()) - t.equal( - "\0\0\0\0\0\0\0\x05\0\0\0\0\0\0\0\0\0\0\0\0", - request.extras.toString() - ) - n += 1 - process.nextTick(function () { - const value = Buffer.alloc(8) - value.writeUInt32BE(request.header.opcode, 4) - value.writeUInt32BE(0, 0) - dummyServer.respond({ - header: { status: 0, opaque: request.header.opaque }, - val: value, - }) - }) - } - - const client = makeClient([dummyServer]) - client.decrement( - "number-decrement-test", - 5, - {}, - function (err: Error | null, success, val) { - t.equal(true, success) - t.equal(6, val) - t.equal(null, err) - t.equal(1, n, "Ensure decr is called") - t.end() - } - ) -}) - -test("DecrementSuccessfulWithoutOption", function (t) { - let n = 0 - const dummyServer = makeDummyServer("dummyServer") - dummyServer.write = function (requestBuf) { - const request = parseMessage(requestBuf) - t.equal(6, request.header.opcode) - t.equal("number-decrement-test", request.key.toString()) - t.equal("", request.val.toString()) - t.equal( - "\0\0\0\0\0\0\0\x05\0\0\0\0\0\0\0\0\0\0\0\0", - request.extras.toString() - ) - n += 1 - process.nextTick(function () { - const value = Buffer.alloc(8) - value.writeUInt32BE(request.header.opcode, 4) - value.writeUInt32BE(0, 0) - dummyServer.respond({ - header: { status: 0, opaque: request.header.opaque }, - val: value, - }) - }) - } - - const client = makeClient([dummyServer]) - client.decrement("number-decrement-test", 5, {}, function (err: Error | null, success, val) { - t.equal(true, success) - t.equal(6, val) - t.equal(null, err) - t.equal(1, n, "Ensure decr is called") - t.end() - }) -}) - -test("AppendSuccessful", function (t) { - let n = 0 - const dummyServer = makeDummyServer("dummyServer") - dummyServer.write = function (requestBuf) { - const request = parseMessage(requestBuf) - t.equal("hello", request.key.toString()) - t.equal("world", request.val.toString()) - n += 1 - dummyServer.respond({ - header: { status: 0, opaque: request.header.opaque }, - }) - } - - const client = makeClient([dummyServer], { expires: 1024 }) - client.append("hello", "world", function (err: Error | null, val) { - t.equal(null, err) - t.equal(true, val) - t.equal(1, n, "Ensure append is called") - t.end() - }) -}) - -test("AppendKeyDNE", function (t) { - let n = 0 - const dummyServer = makeDummyServer("dummyServer") - dummyServer.write = function (requestBuf) { - const request = parseMessage(requestBuf) - t.equal("hello", request.key.toString()) - t.equal("world", request.val.toString()) - n += 1 - dummyServer.respond({ - header: { status: 1, opaque: request.header.opaque }, - }) - } - - const client = makeClient([dummyServer]) - client.append("hello", "world", function (err: Error | null, val) { - t.equal(null, err) - t.equal(false, val) - t.equal(1, n, "Ensure append is called") - t.end() - }) -}) - -test("PrependSuccessful", function (t) { - let n = 0 - const dummyServer = makeDummyServer("dummyServer") - dummyServer.write = function (requestBuf) { - const request = parseMessage(requestBuf) - t.equal("hello", request.key.toString()) - t.equal("world", request.val.toString()) - n += 1 - dummyServer.respond({ - header: { status: 0, opaque: request.header.opaque }, - }) - } - - const client = makeClient([dummyServer], { expires: 1024 }) - client.prepend("hello", "world", function (err: Error | null, val) { - t.equal(null, err) - t.equal(true, val) - t.equal(1, n, "Ensure prepend is called") - t.end() - }) -}) - -test("PrependKeyDNE", function (t) { - let n = 0 - const dummyServer = makeDummyServer("dummyServer") - dummyServer.write = function (requestBuf) { - const request = parseMessage(requestBuf) - t.equal("hello", request.key.toString()) - t.equal("world", request.val.toString()) - n += 1 - dummyServer.respond({ - header: { status: 1, opaque: request.header.opaque }, - }) - } - - const client = makeClient([dummyServer]) - client.prepend("hello", "world", function (err: Error | null, val) { - t.equal(null, err) - t.equal(false, val) - t.equal(1, n, "Ensure prepend is called") - t.end() - }) -}) - -test("TouchSuccessful", function (t) { - let n = 0 - const dummyServer = makeDummyServer("dummyServer") - dummyServer.write = function (requestBuf) { - const request = parseMessage(requestBuf) - t.equal("hello", request.key.toString()) - t.equal("", request.val.toString()) - t.equal("\0\0\x04\0", request.extras.toString()) - n += 1 - dummyServer.respond({ - header: { status: 0, opaque: request.header.opaque }, - }) - } - - const client = makeClient([dummyServer]) - client.touch("hello", 1024, function (err: Error | null, val) { - t.equal(null, err) - t.equal(true, val) - t.equal(1, n, "Ensure touch is called") - t.end() - }) -}) - -test("TouchKeyDNE", function (t) { - let n = 0 - const dummyServer = makeDummyServer("dummyServer") - dummyServer.write = function (requestBuf) { - const request = parseMessage(requestBuf) - t.equal("hello", request.key.toString()) - t.equal("", request.val.toString()) - t.equal("\0\0\x04\0", request.extras.toString()) - n += 1 - dummyServer.respond({ - header: { status: 1, opaque: request.header.opaque }, - }) - } - - const client = makeClient([dummyServer]) - client.touch("hello", 1024, function (err: Error | null, val) { - t.equal(null, err) - t.equal(false, val) - t.equal(1, n, "Ensure ptouch is called") - t.end() - }) -}) - -// test('Failover', function(t) { -// let n1 = 0; -// let n2 = 0; -// const dummyServer1 = makeDummyServer('dummyServer'); -// dummyServer1.write = function(/* requestBuf*/) { -// n1 += 1; -// dummyServer1.error(new Error('connection failure')); -// }; -// const dummyServer2 = makeDummyServer('dummyServer'); -// dummyServer2.write = function(requestBuf) { -// n2 += 1; -// const request = parseMessage(requestBuf); -// dummyServer2.respond({header: {status: 0, opaque: request.header.opaque}}); -// }; - -// const client = makeClient([dummyServer1, dummyServer2], {failover: true}); -// client.get('\0', function(err/*, val */){ -// t.equal(null, err); -// t.equal(2, n1); -// t.equal(1, n2); -// t.end(); -// }); - -// }); - -test("Very Large Client Seq", function (t) { - let n = 0 - const dummyServer = makeDummyServer("dummyServer") - dummyServer.write = function (requestBuf) { - const request = parseMessage(requestBuf) - t.equal("hello", request.key.toString()) - t.equal("world", request.val.toString()) - t.equal("0000000000000400", request.extras.toString("hex")) - n += 1 - dummyServer.respond({ - header: { status: 0, opaque: request.header.opaque }, - }) - } - - const client = makeClient([dummyServer], { expires: 1024 }) - client.seq = Math.pow(2, 33) - const assertor = function (err: Error | null, val: boolean | null) { - t.equal(null, err) - t.equal(true, val) - t.equal(1, n, "Ensure add is called") - } - client.add("hello", "world", {}, assertor) - n = 0 - return client.add("hello", "world", {}).then(function (success) { - assertor(null, success) - }) -}) - -const makeDummyVersionServer = (t: TapTestType, serverKey: string, version: string) => { - const dummyServer = makeDummyServer(serverKey) - dummyServer.write = function (requestBuf) { - const request = parseMessage(requestBuf) - t.deepEqual(Buffer.from(""), request.key) - dummyServer.respond({ - header: { status: 0, opaque: request.header.opaque }, - val: version, - extras: "flagshere", - }) - } - return dummyServer -} - -test("VersionSuccessful", function (t) { - let n = 0 - - const dummyServer = makeDummyVersionServer(t, "dummyServer", "1.3.1") - dummyServer.write = function (requestBuf) { - const request = parseMessage(requestBuf) - t.deepEqual(Buffer.from(""), request.key) - n += 1 - dummyServer.respond({ - header: { status: 0, opaque: request.header.opaque }, - val: "1.3.1", - extras: "flagshere", - }) - } - - const client = makeClient([dummyServer]) - const assertor = function (err: Error | null, val: any, flags: string) { - t.equal("1.3.1", val) - t.equal("flagshere", flags) - t.equal(null, err) - t.equal(n, 1, "Ensure version is called") - } - - client.version(assertor) - n = 0 - - return client.version().then(function (res) { - assertor(null, res.value, res.flags) - }) -}) - -tap.only("VersionError", function (t) { - const dummyServer = makeDummyServer("dummyServer") - dummyServer.write = function () { - dummyServer.error({ name: "ErrorName", message: "This is an expected error." }) - } - - const client = makeClient([dummyServer]) - const assertor = function (err: Error | null, value?: string | Buffer | null, flags?: any) { - t.notEqual(null, err) - t.equal("This is an expected error.", err?.message) - } - - client.version(assertor) - return client.version().catch(function (err) { - assertor(err) - return true - }) -}) - -test("VersionAllSuccessful", function (t) { - const dummyServer1 = makeDummyVersionServer(t, "dummyServer1", "1.0.0") - const dummyServer2 = makeDummyVersionServer(t, "dummyServer2", "2.0.0") - const dummyServer3 = makeDummyVersionServer(t, "dummyServer3", "3.0.0") - - const client = makeClient([dummyServer1, dummyServer2, dummyServer3]) - const assertor = function (err: Error | null, val?: Record | null) { - t.deepEqual( - { - "dummyServer1:undefined": "1.0.0", - "dummyServer2:undefined": "2.0.0", - "dummyServer3:undefined": "3.0.0", - }, - val - ) - t.equal(null, err) - } - - client.versionAll(assertor) - - return client.versionAll().then(function (res) { - assertor(null, res.values) - }) -}) - -tap.only("VersionAllSomeFailed", function (t) { - const dummyServer1 = makeDummyVersionServer(t, "dummyServer1", "1.0.0") - const dummyServer2 = makeDummyVersionServer(t, "dummyServer2", "2.0.0") - dummyServer2.write = function () { - dummyServer2.error({ name: "ErrorName", message: "This is an expected error." }) - } - const dummyServer3 = makeDummyVersionServer(t, "dummyServer3", "3.0.0") - - const client = makeClient([dummyServer1, dummyServer2, dummyServer3]) - const assertor = function (err: Error | null) { - t.notEqual(null, err) - t.equal("This is an expected error.", err?.message) - } - - client.versionAll(assertor) - - return client.versionAll().catch(function (err) { - assertor(err) - }) -}) diff --git a/tsconfig.json b/tsconfig.json index 97685f3..65657dc 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -8,7 +8,7 @@ "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ // "lib": [], /* Specify library files to be included in the compilation. */ "allowJs": true, /* Allow javascript files to be compiled. */ - "checkJs": true, /* Report errors in .js files. */ + "checkJs": false, /* Report errors in .js files. */ // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', 'react', 'react-jsx' or 'react-jsxdev'. */ "declaration": true, /* Generates corresponding '.d.ts' file. */ "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ @@ -67,5 +67,5 @@ "skipLibCheck": true, /* Skip type checking of declaration files. */ "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ }, - "include": ["src/**/*", "test/**/*ts", ], + "include": ["src/**/*"], } From b4459f420d3232cf89126edbafef05c2408f5380 Mon Sep 17 00:00:00 2001 From: Jake Teton-Landis Date: Mon, 12 Apr 2021 13:12:52 -0700 Subject: [PATCH 38/79] mess with imports --- src/index.ts | 1 - src/test/client_test.ts | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) delete mode 100644 src/index.ts diff --git a/src/index.ts b/src/index.ts deleted file mode 100644 index 18dd75d..0000000 --- a/src/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./memjs/memjs"; diff --git a/src/test/client_test.ts b/src/test/client_test.ts index bc90bf7..4b30571 100644 --- a/src/test/client_test.ts +++ b/src/test/client_test.ts @@ -2,7 +2,7 @@ import tap from "tap"; const test = tap.test; const errors = require("../memjs/protocol").errors; -import MemJS = require(".."); +import MemJS = require("../memjs/memjs"); import constants = require("../memjs/constants"); import { noopSerializer } from "../memjs/noop-serializer"; import { Header } from "../memjs/header"; From 9456ef9ff205f4655c5525e0bf994c8daca52d65 Mon Sep 17 00:00:00 2001 From: Jake Teton-Landis Date: Mon, 12 Apr 2021 13:15:59 -0700 Subject: [PATCH 39/79] bench seems busted... --- bench/memjs.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bench/memjs.js b/bench/memjs.js index 4dbc3e1..48450eb 100644 --- a/bench/memjs.js +++ b/bench/memjs.js @@ -4,8 +4,8 @@ const b = require('benchmark'); function makeString(n) { const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; - const text = ''; - const i; + let text = ''; + let i; for(i=0; i < n; i++ ) { text += possible.charAt(Math.floor(Math.random() * possible.length)); @@ -14,7 +14,7 @@ function makeString(n) { return text; } -const x = (function() { +let x = (function() { const suite = new b.Suite(); const headerBuf = Buffer.from([0x81, 1, 7, 0, 4, 0, 0, 1, 0, 0, 0, 9, 0, 0, 0, 0, 0x0a, 0, 0, 0, 0, 0, 0, 0]); @@ -58,7 +58,7 @@ x = (function() { return arg; }; - const i; + let i; for (i = 0; i < 10; i++) { server.onResponse(dummyFunc); } From d55fe8683a6165103a05263b8909f00d2132dbe3 Mon Sep 17 00:00:00 2001 From: Jake Teton-Landis Date: Mon, 12 Apr 2021 13:28:54 -0700 Subject: [PATCH 40/79] ci on every branch pr? --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 897358e..4c7ea21 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,7 +4,7 @@ on: push: branches: [ $default-branch ] pull_request: - branches: [ $default-branch ] + branches: [ $default-branch, '*' ] jobs: build: From cdd75d95b8422be3121e8b9e376301389e75f18c Mon Sep 17 00:00:00 2001 From: Jake Teton-Landis Date: Mon, 12 Apr 2021 13:29:09 -0700 Subject: [PATCH 41/79] test includes tsc now --- .github/workflows/ci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4c7ea21..78c337e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,5 +21,4 @@ jobs: with: node-version: ${{ matrix.node-version }} - run: npm ci - - run: npm run build - run: npm test From e1cef376401bfc22f741b2b15f819db5d28e0c60 Mon Sep 17 00:00:00 2001 From: Jake Teton-Landis Date: Mon, 12 Apr 2021 13:34:49 -0700 Subject: [PATCH 42/79] pull request target?? --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 78c337e..8667437 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,6 +5,8 @@ on: branches: [ $default-branch ] pull_request: branches: [ $default-branch, '*' ] + pull_request_target: + types: [opened, synchronize, reopened] jobs: build: From 24164aaf5b96f9ca0747adabe6c9dea1068d9d1a Mon Sep 17 00:00:00 2001 From: Jake Teton-Landis Date: Mon, 12 Apr 2021 13:42:22 -0700 Subject: [PATCH 43/79] fix getmulti result --- .github/workflows/ci.yml | 2 -- src/memjs/memjs.ts | 2 +- src/test/client_test.ts | 11 ++++++----- src/test/server_test.js | 2 +- 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8667437..78c337e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,8 +5,6 @@ on: branches: [ $default-branch ] pull_request: branches: [ $default-branch, '*' ] - pull_request_target: - types: [opened, synchronize, reopened] jobs: build: diff --git a/src/memjs/memjs.ts b/src/memjs/memjs.ts index f8c0d8f..2524008 100644 --- a/src/memjs/memjs.ts +++ b/src/memjs/memjs.ts @@ -95,7 +95,7 @@ export type GetMultiResult< Value = MaybeBuffer, Extras = MaybeBuffer > = { - [K in Keys]: GetResult; + [K in Keys]?: GetResult; }; class Client { diff --git a/src/test/client_test.ts b/src/test/client_test.ts index 4b30571..a2e6e55 100644 --- a/src/test/client_test.ts +++ b/src/test/client_test.ts @@ -345,6 +345,7 @@ test("GetMultiSuccessful_MultiBackend", function (t) { }, }; t.deepEqual(expected, val); + console.log(val); t.equal(null, err); }; client.getMulti(["hello1", "hello2", "hello3", "hello4"], assertor); @@ -384,19 +385,19 @@ test("GetMultiSuccessful_MissingKeys_MultiBackend", function (t) { err: Error | null, val: MemJS.GetMultiResult | null ) { - const expected: MemJS.GetMultiResult<"hello1" | "hello2" | "hello3"> = { + const expected: MemJS.GetMultiResult<"hello1" | "hello3" | "hello4"> = { hello1: { value: "world1", extras: DummyMultiGetFlags, cas: undefined, }, - hello2: { - value: "world2", + hello3: { + value: "world3", extras: DummyMultiGetFlags, cas: undefined, }, - hello3: { - value: "world3", + hello4: { + value: "world4", extras: DummyMultiGetFlags, cas: undefined, }, diff --git a/src/test/server_test.js b/src/test/server_test.js index 7ed0112..7ffabe6 100644 --- a/src/test/server_test.js +++ b/src/test/server_test.js @@ -1,5 +1,5 @@ const test = require('tap').test; -const MemJS = require('../'); +const MemJS = require('../memjs/memjs'); const makeRequestBuffer = require('../memjs/utils').makeRequestBuffer; test('AuthListMechanisms', function(t) { From f6ae576b5d2ec9ce42a70b16b3d19577908cb681 Mon Sep 17 00:00:00 2001 From: Jake Teton-Landis Date: Mon, 12 Apr 2021 14:10:18 -0700 Subject: [PATCH 44/79] newer versions of makeRequestBuffer --- src/memjs/memjs.ts | 32 +++------------- src/memjs/utils.ts | 92 +++++++++++++++++++++++++++++++++------------- 2 files changed, 72 insertions(+), 52 deletions(-) diff --git a/src/memjs/memjs.ts b/src/memjs/memjs.ts index 2524008..45bd262 100644 --- a/src/memjs/memjs.ts +++ b/src/memjs/memjs.ts @@ -226,11 +226,8 @@ class Client { /** * Given a key to look up in memcache, return a serverKey (based on some * hashing function) which can be used to index this.serverMap - * - * @param {string} key - * @returns {string} */ - lookupKeyToServerKey(key: string) { + lookupKeyToServerKey(key: string): string { return this.options.keyToServerHashFunction(this.serverKeys, key); } @@ -491,46 +488,29 @@ class Client { } /** - * SET - * - * Sets the given _key_ and _value_ in memcache. - * - * The options dictionary takes: - * * _expires_: overrides the default expiration (see `Client.create`) for this - * particular key-value pair. - * - * The callback signature is: - * - * callback(err, success) - * @param key - * @param value - * @param options - * @param callback + * Sets the given _key_ to _value_. */ set( key: string, value: Value, - options?: { expires?: number } + options?: { expires?: number; cas?: CASToken } ): Promise; set( key: string, value: Value, - options: { expires?: number }, + options: { expires?: number; cas?: CASToken }, callback: (error: Error | null, success: boolean | null) => void ): void; set( key: string, value: Value, - options: { expires?: number }, + options: { expires?: number; cas?: CASToken }, callback?: (error: Error | null, success: boolean | null) => void ): Promise | void { if (callback === undefined && typeof options !== "function") { if (!options) options = {}; return promisify((callback) => { - this.set(key, value, options as { expires?: number }, function ( - err, - success - ) { + this.set(key, value, options, function (err, success) { callback(err, success); }); }); diff --git a/src/memjs/utils.ts b/src/memjs/utils.ts index 8bfc63c..39e7a59 100644 --- a/src/memjs/utils.ts +++ b/src/memjs/utils.ts @@ -9,37 +9,43 @@ export const bufferify = function (val: MaybeBuffer) { return Buffer.isBuffer(val) ? val : Buffer.from(val as any); }; -export const copyIntoRequestBuffer = function ( - opcode: OP, - key: MaybeBuffer, - extras: MaybeBuffer, - value: MaybeBuffer, - opaque: number, - buf: Buffer, - _bufTargetWriteOffset?: number +export interface EncodableRequest { + header: Omit< + header.Header, + "magic" | "keyLength" | "extrasLength" | "totalBodyLength" + >; + key: MaybeBuffer; + extras: MaybeBuffer; + value: MaybeBuffer; +} + +export function encodeRequestIntoBuffer( + buffer: Buffer, + offset: number, + request: EncodableRequest ) { - key = bufferify(key); - extras = bufferify(extras); - value = bufferify(value); + const key = bufferify(request.key); + const extras = bufferify(request.extras); + const value = bufferify(request.value); - const bufTargetWriteOffset = _bufTargetWriteOffset || 0; + const bufTargetWriteOffset = offset || 0; let totalBytesWritten = 0; function copyIntoBuffer(toWriteBuffer: Buffer) { const bytesWritten = toWriteBuffer.copy( - buf, + buffer, bufTargetWriteOffset + totalBytesWritten ); totalBytesWritten += bytesWritten; } const requestHeader: header.Header = { + ...request.header, magic: 0x80, - opcode: opcode, keyLength: key.length, extrasLength: extras.length, totalBodyLength: key.length + value.length + extras.length, - opaque: opaque, }; + const headerBuffer = header.toBuffer(requestHeader); copyIntoBuffer(headerBuffer); @@ -48,6 +54,41 @@ export const copyIntoRequestBuffer = function ( copyIntoBuffer(value); return totalBytesWritten; +} + +export function encodeRequest(request: EncodableRequest): Buffer { + const key = bufferify(request.key); + const extras = bufferify(request.extras); + const value = bufferify(request.value); + const bufSize = 24 + key.length + extras.length + value.length; + const buffer = Buffer.alloc(bufSize); + encodeRequestIntoBuffer(buffer, 0, { + ...request, + key, + extras, + value, + }); + return buffer; +} + +export const copyIntoRequestBuffer = function ( + opcode: OP, + key: MaybeBuffer, + extras: MaybeBuffer, + value: MaybeBuffer, + opaque: number, + buf: Buffer, + _bufTargetWriteOffset?: number +) { + return encodeRequestIntoBuffer(buf, _bufTargetWriteOffset || 0, { + header: { + opcode, + opaque, + }, + key, + extras, + value, + }); }; export const makeRequestBuffer = function ( @@ -57,16 +98,15 @@ export const makeRequestBuffer = function ( value: MaybeBuffer, opaque?: number ) { - key = bufferify(key); - extras = bufferify(extras); - value = bufferify(value); - - const bufSize = 24 + key.length + extras.length + value.length; - - const buf = Buffer.alloc(bufSize); - buf.fill(0); - copyIntoRequestBuffer(opcode, key, extras, value, opaque || 0, buf); - return buf; + return encodeRequest({ + extras, + key, + value, + header: { + opcode, + opaque: opaque || 0, + }, + }); }; export const makeAmountInitialAndExpiration = function ( @@ -131,7 +171,7 @@ export const parseMessage = function (dataBuf: Buffer): Message | false { export const parseMessages = function (dataBuf: Buffer): Message[] { const messages = []; - let message: Message + let message: Message; do { message = exports.parseMessage(dataBuf); From 9a1cd1ec98ca0be328dda292cfd7354f54e1f31e Mon Sep 17 00:00:00 2001 From: Jake Teton-Landis Date: Mon, 12 Apr 2021 14:15:38 -0700 Subject: [PATCH 45/79] set: pass through CAS token --- src/memjs/memjs.ts | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/memjs/memjs.ts b/src/memjs/memjs.ts index 45bd262..9469819 100644 --- a/src/memjs/memjs.ts +++ b/src/memjs/memjs.ts @@ -526,13 +526,17 @@ class Client { const opcode: constants.OP = 1; const serialized = this.serializer.serialize(opcode, value, extras); - const request = makeRequestBuffer( - opcode, + + const request = Utils.encodeRequest({ + header: { + opcode: constants.OP_SET, + opaque: this.seq, + cas: options.cas, + }, key, - serialized.extras, - serialized.value, - this.seq - ); + value: serialized.value, + extras: serialized.extras, + }); this.perform(key, request, this.seq, function (err, response) { if (err) { if (callback) { From 0f88a3a43fc20e25498893a3fe1fb1d76c969b5b Mon Sep 17 00:00:00 2001 From: Jake Teton-Landis Date: Mon, 12 Apr 2021 14:17:32 -0700 Subject: [PATCH 46/79] remove no-op fill(0), since Buffer.alloc returns zeroed buffer these days --- src/memjs/header.ts | 1 - src/memjs/memjs.ts | 1 - 2 files changed, 2 deletions(-) diff --git a/src/memjs/header.ts b/src/memjs/header.ts index 2353523..2568d90 100644 --- a/src/memjs/header.ts +++ b/src/memjs/header.ts @@ -35,7 +35,6 @@ export function fromBuffer(headerBuf: Buffer): Header { /** toBuffer converts a JS memcache header object to a binary memcache header */ export function toBuffer(header: Header): Buffer { const headerBuf = Buffer.alloc(24); - headerBuf.fill(0); headerBuf.writeUInt8(header.magic, 0); headerBuf.writeUInt8(header.opcode, 1); headerBuf.writeUInt16BE(header.keyLength, 2); diff --git a/src/memjs/memjs.ts b/src/memjs/memjs.ts index 9469819..002e68b 100644 --- a/src/memjs/memjs.ts +++ b/src/memjs/memjs.ts @@ -320,7 +320,6 @@ class Client { } const request = Buffer.alloc(requestSize); - request.fill(0); let bytesWritten = 0; for (const keyIdx in keys) { From 871fddd77eab4648ff619d8e139f4e8c8491b6b1 Mon Sep 17 00:00:00 2001 From: Jake Teton-Landis Date: Mon, 12 Apr 2021 14:38:54 -0700 Subject: [PATCH 47/79] verify cas is passed through to server --- src/test/client_test.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/test/client_test.ts b/src/test/client_test.ts index a2e6e55..f3e31ff 100644 --- a/src/test/client_test.ts +++ b/src/test/client_test.ts @@ -541,12 +541,14 @@ test("GetMultiError", function (t) { }); test("SetSuccessful", function (t) { + const casToken = Buffer.from("cas toke"); let n = 0; const dummyServer = makeDummyServer("dummyServer"); dummyServer.write = function (requestBuf) { const request = parseMessage(requestBuf); t.equal("hello", request.key.toString()); t.equal("world", request.val.toString()); + t.equal("cas toke", request.header.cas && request.header.cas.toString()); n += 1; dummyServer.respond({ header: { status: 0, opaque: request.header.opaque }, @@ -559,11 +561,13 @@ test("SetSuccessful", function (t) { t.equal(null, err); t.equal(1, n, "Ensure set is called"); }; - client.set("hello", "world", {}, assertor); + client.set("hello", "world", { cas: casToken }, assertor); n = 0; - return client.set("hello", "world", {}).then(function (success) { - assertor(null, success); - }); + return client + .set("hello", "world", { cas: casToken }) + .then(function (success) { + assertor(null, success); + }); }); test("SetSuccessfulWithoutOption", function (t) { From 6856969727c6cb8d595a2f09845d22f4d416ee31 Mon Sep 17 00:00:00 2001 From: Jake Teton-Landis Date: Mon, 12 Apr 2021 16:32:43 -0700 Subject: [PATCH 48/79] refactor to remove repeated error handling boilerplate --- src/memjs/constants.ts | 73 ++++++++-- src/memjs/header.ts | 2 +- src/memjs/memjs.ts | 304 ++++++++++++++++++---------------------- src/memjs/protocol.ts | 20 --- src/memjs/server.ts | 2 +- src/test/client_test.ts | 102 +++++++------- 6 files changed, 259 insertions(+), 244 deletions(-) delete mode 100644 src/memjs/protocol.ts diff --git a/src/memjs/constants.ts b/src/memjs/constants.ts index 7b81690..552d5ec 100644 --- a/src/memjs/constants.ts +++ b/src/memjs/constants.ts @@ -300,12 +300,69 @@ export type OP = | typeof OP_GET_CTRL_TOKEN | typeof OP_INIT_COMPLETE; -// Named "No Error" in the memcache docs but this seems like it will be clearer -export const RESPONSE_STATUS_SUCCCESS = 0x00; -export const RESPONSE_STATUS_KEY_NOT_FOUND = 0x01; -export const RESPONSE_STATUS_KEY_EXISTS = 0x02; +/** + * Response statuses + * https://github.com/memcached/memcached/wiki/BinaryProtocolRevamped#response-status + */ +export const ResponseStatus = { + /** Named "No error" in the memcached docs, but clearer in code as "SUCCESS". */ + SUCCESS: 0x0000, + KEY_NOT_FOUND: 0x0001, + KEY_EXISTS: 0x0002, + VALUE_TOO_LARGE: 0x0003, + INVALID_ARGUMENTS: 0x0004, + ITEM_NOT_STORED: 0x0005, + INCR_DECR_ON_NON_NUMERIC_VALUE: 0x0006, + THE_VBUCKET_BELONGS_TO_ANOTHER_SERVER: 0x0007, + AUTHENTICATION_ERROR: 0x0008, + AUTHENTICATION_CONTINUE: 0x0009, + UNKNOWN_COMMAND: 0x0081, + OUT_OF_MEMORY: 0x0082, + NOT_SUPPORTED: 0x0083, + INTERNAL_ERROR: 0x0084, + BUSY: 0x0085, + TEMPORARY_FAILURE: 0x0086, +} as const; -export type ResponseStatus = - | typeof RESPONSE_STATUS_SUCCCESS - | typeof RESPONSE_STATUS_KEY_NOT_FOUND - | typeof RESPONSE_STATUS_KEY_EXISTS; +export type ResponseStatus = typeof ResponseStatus[keyof typeof ResponseStatus]; + +export function responseStatusToString( + responseStatus: ResponseStatus | undefined +) { + switch (responseStatus) { + case 0x0000: + return "No error"; + case 0x0001: + return "Key not found"; + case 0x0002: + return "Key exists"; + case 0x0003: + return "Value too large"; + case 0x0004: + return "Invalid arguments"; + case 0x0005: + return "Item not stored"; + case 0x0006: + return "Incr/Decr on non-numeric value"; + case 0x0007: + return "The vbucket belongs to another server"; + case 0x0008: + return "Authentication error"; + case 0x0009: + return "Authentication continue"; + case 0x0081: + return "Unknown command"; + case 0x0082: + return "Out of memory"; + case 0x0083: + return "Not supported"; + case 0x0084: + return "Internal error"; + case 0x0085: + return "Busy"; + case 0x0086: + return "Temporary failure"; + default: + return `Unknown response status ${responseStatus}`; + } +} diff --git a/src/memjs/header.ts b/src/memjs/header.ts index 2568d90..d32771f 100644 --- a/src/memjs/header.ts +++ b/src/memjs/header.ts @@ -8,7 +8,7 @@ export interface Header { keyLength: number; extrasLength: number; dataType?: number; - status?: ResponseStatus | number; + status?: ResponseStatus; totalBodyLength: number; opaque: number; cas?: Buffer; diff --git a/src/memjs/memjs.ts b/src/memjs/memjs.ts index 002e68b..a77a8fd 100644 --- a/src/memjs/memjs.ts +++ b/src/memjs/memjs.ts @@ -1,6 +1,5 @@ // MemTS Memcache Client -import { errors, UNKNOWN_ERROR } from "./protocol"; import { OnErrorCallback, OnResponseCallback, @@ -19,6 +18,7 @@ import { Message, } from "./utils"; import * as constants from "./constants"; +import { ResponseStatus } from "./constants"; import * as Utils from "./utils"; import * as Header from "./header"; @@ -271,7 +271,6 @@ class Client { }); }); } - const logger = this.options.logger; this.incrSeq(); const request = makeRequestBuffer(constants.OP_GET, key, "", "", this.seq); this.perform(key, request, this.seq, (err, response) => { @@ -282,7 +281,7 @@ class Client { return; } switch (response!.header.status) { - case constants.RESPONSE_STATUS_SUCCCESS: + case ResponseStatus.SUCCESS: if (callback) { const deserialized = this.serializer.deserialize( response!.header.opcode, @@ -292,18 +291,13 @@ class Client { callback(null, { ...deserialized, cas: response!.header.cas }); } break; - case constants.RESPONSE_STATUS_KEY_NOT_FOUND: + case ResponseStatus.KEY_NOT_FOUND: if (callback) { callback(null, null); } break; default: - const errorMessage = - "MemJS GET: " + errors[response!.header.status || UNKNOWN_ERROR]; - logger.log(errorMessage); - if (callback) { - callback(new Error(errorMessage), null); - } + this.handleResponseError("GET", response?.header?.status, callback); } }); } @@ -361,7 +355,7 @@ class Client { const handle: OnResponseCallback = (response) => { switch (response.header.status) { - case constants.RESPONSE_STATUS_SUCCCESS: + case ResponseStatus.SUCCESS: if (callback) { const deserialized = this.serializer.deserialize( response.header.opcode, @@ -380,19 +374,14 @@ class Client { } } break; - case constants.RESPONSE_STATUS_KEY_NOT_FOUND: + case ResponseStatus.KEY_NOT_FOUND: if (callback) { // @blackmad: IS THIS CORRECT??? callback(null, null); } break; default: - const errorMessage = - "MemJS GET: " + errors[response.header.status || UNKNOWN_ERROR]; - this.options.logger.log(errorMessage); - if (callback) { - callback(new Error(errorMessage), null); - } + this.handleResponseError("GET", response.header.status, callback); } }; // This prevents the handler from being deleted @@ -536,7 +525,7 @@ class Client { value: serialized.value, extras: serialized.extras, }); - this.perform(key, request, this.seq, function (err, response) { + this.perform(key, request, this.seq, (err, response) => { if (err) { if (callback) { callback(err, null); @@ -544,18 +533,13 @@ class Client { return; } switch (response!.header.status) { - case constants.RESPONSE_STATUS_SUCCCESS: + case ResponseStatus.SUCCESS: if (callback) { callback(null, true); } break; default: - const errorMessage = - "MemJS SET: " + errors[response!.header.status || UNKNOWN_ERROR]; - logger.log(errorMessage); - if (callback) { - callback(new Error(errorMessage), null); - } + this.handleResponseError("SET", response?.header?.status, callback); } }); } @@ -598,12 +582,14 @@ class Client { if (callback === undefined && options !== "function") { if (!options) options = {}; return promisify((callback) => { - this.add(key, value, options as { expires?: number }, function ( - err, - success - ) { - callback(err, success); - }); + this.add( + key, + value, + options as { expires?: number }, + function (err, success) { + callback(err, success); + } + ); }); } const logger = this.options.logger; @@ -624,7 +610,7 @@ class Client { serialized.value, this.seq ); - this.perform(key, request, this.seq, function (err, response) { + this.perform(key, request, this.seq, (err, response) => { if (err) { if (callback) { callback(err, null); @@ -632,23 +618,22 @@ class Client { return; } switch (response!.header.status) { - case constants.RESPONSE_STATUS_SUCCCESS: + case ResponseStatus.SUCCESS: if (callback) { callback(null, true); } break; - case constants.RESPONSE_STATUS_KEY_EXISTS: + case ResponseStatus.KEY_EXISTS: if (callback) { callback(null, false); } break; default: - const errorMessage = - "MemJS ADD: " + errors[response!.header.status || UNKNOWN_ERROR]; - logger.log(errorMessage, false); - if (callback) { - callback(new Error(errorMessage), null); - } + return this.handleResponseError( + "ADD", + response?.header?.status, + callback + ); } }); } @@ -680,12 +665,14 @@ class Client { if (callback === undefined && options !== "function") { if (!options) options = {}; return promisify((callback) => { - this.replace(key, value, options as { expires?: number }, function ( - err, - success - ) { - callback(err, success); - }); + this.replace( + key, + value, + options as { expires?: number }, + function (err, success) { + callback(err, success); + } + ); }); } const logger = this.options.logger; @@ -706,7 +693,7 @@ class Client { serialized.value, this.seq ); - this.perform(key, request, this.seq, function (err, response) { + this.perform(key, request, this.seq, (err, response) => { if (err) { if (callback) { callback(err, null); @@ -714,24 +701,22 @@ class Client { return; } switch (response!.header.status) { - case constants.RESPONSE_STATUS_SUCCCESS: + case ResponseStatus.SUCCESS: if (callback) { callback(null, true); } break; - case constants.RESPONSE_STATUS_KEY_NOT_FOUND: + case ResponseStatus.KEY_NOT_FOUND: if (callback) { callback(null, false); } break; default: - const errorMessage = - "MemJS REPLACE: " + - errors[response!.header.status || UNKNOWN_ERROR]; - logger.log(errorMessage, false); - if (callback) { - callback(new Error(errorMessage), null); - } + this.handleResponseError( + "REPLACE", + response?.header?.status, + callback + ); } }); } @@ -768,7 +753,7 @@ class Client { const logger = this.options.logger; this.incrSeq(); const request = makeRequestBuffer(4, key, "", "", this.seq); - this.perform(key, request, this.seq, function (err, response) { + this.perform(key, request, this.seq, (err, response) => { if (err) { if (callback) { callback(err, null); @@ -776,23 +761,18 @@ class Client { return; } switch (response!.header.status) { - case constants.RESPONSE_STATUS_SUCCCESS: + case ResponseStatus.SUCCESS: if (callback) { callback(null, true); } break; - case constants.RESPONSE_STATUS_KEY_NOT_FOUND: + case ResponseStatus.KEY_NOT_FOUND: if (callback) { callback(null, false); } break; default: - const errorMessage = - "MemJS DELETE: " + errors[response!.header.status || UNKNOWN_ERROR]; - logger.log(errorMessage, false); - if (callback) { - callback(new Error(errorMessage), null); - } + this.handleResponseError("DELETE", response?.header.status, callback); } }); } @@ -855,8 +835,14 @@ class Client { const initial = options.initial || 0; const expires = options.expires || this.options.expires; const extras = makeAmountInitialAndExpiration(amount, initial, expires); - const request = makeRequestBuffer(5, key, extras, "", this.seq); - this.perform(key, request, this.seq, function (err, response) { + const request = makeRequestBuffer( + constants.OP_INCREMENT, + key, + extras, + "", + this.seq + ); + this.perform(key, request, this.seq, (err, response) => { if (err) { if (callback) { callback(err, null); @@ -864,7 +850,7 @@ class Client { return; } switch (response!.header.status) { - case constants.RESPONSE_STATUS_SUCCCESS: + case ResponseStatus.SUCCESS: const bufInt = (response!.val.readUInt32BE(0) << 8) + response!.val.readUInt32BE(4); @@ -873,12 +859,13 @@ class Client { } break; default: - const errorMessage = - "MemJS INCREMENT: " + - errors[response!.header.status || UNKNOWN_ERROR]; - logger.log(errorMessage); + const error = this.handleResponseError( + "INCREMENT", + response!.header.status, + undefined + ); if (callback) { - callback(new Error(errorMessage), null, null); + callback(error, null, null); } } }); @@ -935,8 +922,14 @@ class Client { const initial = options.initial || 0; const expires = options.expires || this.options.expires; const extras = makeAmountInitialAndExpiration(amount, initial, expires); - const request = makeRequestBuffer(6, key, extras, "", this.seq); - this.perform(key, request, this.seq, function (err, response) { + const request = makeRequestBuffer( + constants.OP_DECREMENT, + key, + extras, + "", + this.seq + ); + this.perform(key, request, this.seq, (err, response) => { if (err) { if (callback) { callback(err, null); @@ -944,7 +937,7 @@ class Client { return; } switch (response!.header.status) { - case constants.RESPONSE_STATUS_SUCCCESS: + case ResponseStatus.SUCCESS: const bufInt = (response!.val.readUInt32BE(0) << 8) + response!.val.readUInt32BE(4); @@ -953,12 +946,13 @@ class Client { } break; default: - const errorMessage = - "MemJS DECREMENT: " + - errors[response!.header.status || UNKNOWN_ERROR]; - logger.log(errorMessage); + const error = this.handleResponseError( + "DECREMENT", + response!.header.status, + undefined + ); if (callback) { - callback(new Error(errorMessage), null, null); + callback(error, null, null); } } }); @@ -997,7 +991,7 @@ class Client { // TODO: support version (CAS) const logger = this.options.logger; this.incrSeq(); - const opcode: constants.OP = 0x0e; + const opcode: constants.OP = constants.OP_APPEND; const serialized = this.serializer.serialize(opcode, value, ""); const request = makeRequestBuffer( opcode, @@ -1006,7 +1000,7 @@ class Client { serialized.value, this.seq ); - this.perform(key, request, this.seq, function (err, response) { + this.perform(key, request, this.seq, (err, response) => { if (err) { if (callback) { callback(err, null); @@ -1014,23 +1008,18 @@ class Client { return; } switch (response!.header.status) { - case constants.RESPONSE_STATUS_SUCCCESS: + case ResponseStatus.SUCCESS: if (callback) { callback(null, true); } break; - case constants.RESPONSE_STATUS_KEY_NOT_FOUND: + case ResponseStatus.KEY_NOT_FOUND: if (callback) { callback(null, false); } break; default: - const errorMessage = - "MemJS APPEND: " + errors[response!.header.status || UNKNOWN_ERROR]; - logger.log(errorMessage); - if (callback) { - callback(new Error(errorMessage), null); - } + this.handleResponseError("APPEND", response!.header.status, callback); } }); } @@ -1069,8 +1058,7 @@ class Client { const logger = this.options.logger; this.incrSeq(); - const opcode: constants.OP = - constants.OP_PREPEND; /* WAS WRONG IN ORIGINAL */ + const opcode: constants.OP = constants.OP_PREPEND; const serialized = this.serializer.serialize(opcode, value, ""); const request = makeRequestBuffer( opcode, @@ -1079,7 +1067,7 @@ class Client { serialized.value, this.seq ); - this.perform(key, request, this.seq, function (err, response) { + this.perform(key, request, this.seq, (err, response) => { if (err) { if (callback) { callback(err, null); @@ -1087,24 +1075,22 @@ class Client { return; } switch (response!.header.status) { - case constants.RESPONSE_STATUS_SUCCCESS: + case ResponseStatus.SUCCESS: if (callback) { callback(null, true); } break; - case constants.RESPONSE_STATUS_KEY_NOT_FOUND: + case ResponseStatus.KEY_NOT_FOUND: if (callback) { callback(null, false); } break; default: - const errorMessage = - "MemJS PREPEND: " + - errors[response!.header.status || UNKNOWN_ERROR]; - logger.log(errorMessage); - if (callback) { - callback(new Error(errorMessage), null); - } + this.handleResponseError( + "PREPEND", + response!.header.status, + callback + ); } }); } @@ -1144,7 +1130,7 @@ class Client { this.incrSeq(); const extras = makeExpiration(expires || this.options.expires); const request = makeRequestBuffer(0x1c, key, extras, "", this.seq); - this.perform(key, request, this.seq, function (err, response) { + this.perform(key, request, this.seq, (err, response) => { if (err) { if (callback) { callback(err, null); @@ -1152,23 +1138,18 @@ class Client { return; } switch (response!.header.status) { - case constants.RESPONSE_STATUS_SUCCCESS: + case ResponseStatus.SUCCESS: if (callback) { callback(null, true); } break; - case constants.RESPONSE_STATUS_KEY_NOT_FOUND: + case ResponseStatus.KEY_NOT_FOUND: if (callback) { callback(null, false); } break; default: - const errorMessage = - "MemJS TOUCH: " + errors[response!.header.status || UNKNOWN_ERROR]; - logger.log(errorMessage); - if (callback) { - callback(new Error(errorMessage), null); - } + this.handleResponseError("TOUCH", response!.header.status, callback); } }); } @@ -1261,9 +1242,9 @@ class Client { this.incrSeq(); const request = makeRequestBuffer(0x10, key, "", "", this.seq); - const handleStats = function (seq: number, serv: Server) { + const handleStats = (seq: number, serv: Server) => { const result: Record = {}; - const handle: OnResponseCallback = function (response) { + const handle: OnResponseCallback = (response) => { // end of stat responses if (response.header.totalBodyLength === 0) { if (callback) { @@ -1273,18 +1254,17 @@ class Client { } // process single stat line response switch (response.header.status) { - case constants.RESPONSE_STATUS_SUCCCESS: + case ResponseStatus.SUCCESS: result[response.key.toString()] = response.val.toString(); break; default: - const errorMessage = - "MemJS STATS (" + - key + - "): " + - errors[response.header.status || UNKNOWN_ERROR]; - logger.log(errorMessage, false); + const error = this.handleResponseError( + `STATS (${key})`, + response.header.status, + undefined + ); if (callback) { - callback(new Error(errorMessage), serv.hostportString(), null); + callback(error, serv.hostportString(), null); } } }; @@ -1381,29 +1361,19 @@ class Client { } } - _version( - server: Server - ): Promise<{ value: Value | null; flags: Extras | null }>; + _version(server: Server): Promise<{ value: Value | null }>; _version( server: Server, - callback: ( - error: Error | null, - value: Value | null, - flags: Extras | null - ) => void + callback: (error: Error | null, value: Value | null) => void ): void; _version( server: Server, - callback?: ( - error: Error | null, - value: Value | null, - extras: Extras | null - ) => void - ): Promise<{ value: Value | null; flags: Extras | null }> | void { + callback?: (error: Error | null, value: Value | null) => void + ): Promise<{ value: Value | null }> | void { if (callback === undefined) { return promisify((callback) => { - this._version(server, function (err, value, flags) { - callback(err, { value: value, flags: flags }); + this._version(server, function (err, value) { + callback(err, { value: value }); }); }); } @@ -1421,13 +1391,13 @@ class Client { this.performOnServer(server, request, this.seq, (err, response) => { if (err) { if (callback) { - callback(err, null, null); + callback(err, null); } return; } switch (response!.header.status) { - case constants.RESPONSE_STATUS_SUCCCESS: + case ResponseStatus.SUCCESS: /* TODO: this is bugged, we should't use the deserializer here, since version always returns a version string. The deserializer should only be used on user key data. */ const deserialized = this.serializer.deserialize( @@ -1435,16 +1405,14 @@ class Client { response!.val, response!.extras ); - callback(null, deserialized.value, deserialized.extras); + callback(null, deserialized.value); break; default: - const errorMessage = - "MemJS VERSION: " + - errors[(response!.header.status, UNKNOWN_ERROR)]; - logger.log(errorMessage); - if (callback) { - callback(new Error(errorMessage), null, null); - } + this.handleResponseError( + "VERSION", + response!.header.status, + callback + ); } }); } @@ -1456,21 +1424,9 @@ class Client { * * The server responds with a packet containing the version string in the body with the following format: "x.y.z" */ - version(): Promise<{ value: Value | null; flags: Extras | null }>; - version( - callback: ( - error: Error | null, - value: Value | null, - flags: Extras | null - ) => void - ): void; - version( - callback?: ( - error: Error | null, - value: Value | null, - extras: Extras | null - ) => void - ) { + version(): Promise<{ value: Value | null }>; + version(callback: (error: Error | null, value: Value | null) => void): void; + version(callback?: (error: Error | null, value: Value | null) => void) { const server = this.serverKeyToServer(this.serverKeys[0]); if (callback) { this._version(server, callback); @@ -1632,6 +1588,26 @@ class Client { // Wrap `this.seq` to 32-bits since the field we fit it into is only 32-bits. this.seq &= 0xffffffff; } + + /** + * Log an error to the logger, then return the error. + * If a callback is given, call it with callback(error, null). + */ + private handleResponseError( + commandName: string, + responseStatus: ResponseStatus | undefined, + callback: undefined | ((error: Error | null, other: null) => void) + ): Error { + const errorMessage = `MemJS ${commandName}: ${constants.responseStatusToString( + responseStatus + )}`; + this.options.logger.log(errorMessage); + const error = new Error(errorMessage); + if (callback) { + callback(error, null); + } + return error; + } } export { Client, Server, Utils, Header }; diff --git a/src/memjs/protocol.ts b/src/memjs/protocol.ts deleted file mode 100644 index 505b414..0000000 --- a/src/memjs/protocol.ts +++ /dev/null @@ -1,20 +0,0 @@ -/** MemJS Memcache binary protocol errors */ -export const UNKNOWN_ERROR = -1; -export const errors: { [key: number]: string } = {}; -errors[UNKNOWN_ERROR] = "Unknown error"; -errors[0x0000] = "No error"; -errors[0x0001] = "Key not found"; -errors[0x0002] = "Key exists"; -errors[0x0003] = "Value too large"; -errors[0x0004] = "Invalid arguments"; -errors[0x0005] = "Item not stored"; -errors[0x0006] = "Incr/Decr on non-numeric value"; -errors[0x0007] = "The vbucket belongs to another server"; -errors[0x0008] = "Authentication error"; -errors[0x0009] = "Authentication continue"; -errors[0x0081] = "Unknown command"; -errors[0x0082] = "Out of memory"; -errors[0x0083] = "Not supported"; -errors[0x0084] = "Internal error"; -errors[0x0085] = "Busy"; -errors[0x0086] = "Temporary failure"; diff --git a/src/memjs/server.ts b/src/memjs/server.ts index 9ebd2bd..b44601c 100644 --- a/src/memjs/server.ts +++ b/src/memjs/server.ts @@ -156,7 +156,7 @@ export class Server extends events.EventEmitter { while (response) { if (response.header.opcode === 0x20) { this.saslAuth(); - } else if (response.header.status === 0x20) { + } else if (response.header.status === (0x20 as any) /* TODO: wtf? */) { this.error(new Error("Memcached server authentication failed!")); } else if (response.header.opcode === 0x21) { this.emit("authenticated"); diff --git a/src/test/client_test.ts b/src/test/client_test.ts index f3e31ff..40eba01 100644 --- a/src/test/client_test.ts +++ b/src/test/client_test.ts @@ -1,7 +1,6 @@ import tap from "tap"; const test = tap.test; -const errors = require("../memjs/protocol").errors; import MemJS = require("../memjs/memjs"); import constants = require("../memjs/constants"); import { noopSerializer } from "../memjs/noop-serializer"; @@ -652,7 +651,7 @@ test("SetUnsuccessful", function (t) { const client = makeClient([dummyServer]); const assertor = function (err: Error | null, val: boolean | null) { t.equal(null, val); - t.equal("MemJS SET: " + errors[3], err?.message); + t.equal("MemJS SET: " + constants.responseStatusToString(3), err?.message); t.equal(1, n, "Ensure set is called"); }; client.set("hello", "world", {}, assertor); @@ -800,7 +799,7 @@ test("SetSerialize", function (t) { }); const assertor = function (err: Error | null, val: boolean | null) { t.equal(null, val); - t.equal("MemJS SET: " + errors[3], err?.message); + t.equal("MemJS SET: " + constants.responseStatusToString(3), err?.message); t.equal(1, n, "Ensure set is called"); t.equal(1, sn, "Ensure serialization is called once"); }; @@ -1145,29 +1144,31 @@ test("IncrementSuccessful", function (t) { }; const client = makeClient([dummyServer]); - client.increment("number-increment-test", 5, {}, function ( - err: Error | null, - success, - val - ) { - callbn += 1; - t.equal(true, success); - t.equal(6, val); - t.equal(null, err); - done(); - }); + client.increment( + "number-increment-test", + 5, + {}, + function (err: Error | null, success, val) { + callbn += 1; + t.equal(true, success); + t.equal(6, val); + t.equal(null, err); + done(); + } + ); - client.increment("number-increment-test", 5, { initial: 3 }, function ( - err: Error | null, - success, - val - ) { - callbn += 1; - t.equal(true, success); - t.equal(6, val); - t.equal(null, err); - done(); - }); + client.increment( + "number-increment-test", + 5, + { initial: 3 }, + function (err: Error | null, success, val) { + callbn += 1; + t.equal(true, success); + t.equal(6, val); + t.equal(null, err); + done(); + } + ); const done = (function () { let called = 0; @@ -1206,17 +1207,18 @@ test("DecrementSuccessful", function (t) { }; const client = makeClient([dummyServer]); - client.decrement("number-decrement-test", 5, {}, function ( - err: Error | null, - success, - val - ) { - t.equal(true, success); - t.equal(6, val); - t.equal(null, err); - t.equal(1, n, "Ensure decr is called"); - t.end(); - }); + client.decrement( + "number-decrement-test", + 5, + {}, + function (err: Error | null, success, val) { + t.equal(true, success); + t.equal(6, val); + t.equal(null, err); + t.equal(1, n, "Ensure decr is called"); + t.end(); + } + ); }); test("DecrementSuccessfulWithoutOption", function (t) { @@ -1244,17 +1246,18 @@ test("DecrementSuccessfulWithoutOption", function (t) { }; const client = makeClient([dummyServer]); - client.decrement("number-decrement-test", 5, {}, function ( - err: Error | null, - success, - val - ) { - t.equal(true, success); - t.equal(6, val); - t.equal(null, err); - t.equal(1, n, "Ensure decr is called"); - t.end(); - }); + client.decrement( + "number-decrement-test", + 5, + {}, + function (err: Error | null, success, val) { + t.equal(true, success); + t.equal(6, val); + t.equal(null, err); + t.equal(1, n, "Ensure decr is called"); + t.end(); + } + ); }); test("AppendSuccessful", function (t) { @@ -1478,9 +1481,8 @@ test("VersionSuccessful", function (t) { }; const client = makeClient([dummyServer]); - const assertor = function (err: Error | null, val: any, flags: string) { + const assertor = function (err: Error | null, val: any) { t.equal("1.3.1", val); - t.equal("flagshere", flags); t.equal(null, err); t.equal(n, 1, "Ensure version is called"); }; @@ -1489,7 +1491,7 @@ test("VersionSuccessful", function (t) { n = 0; return client.version().then(function (res) { - assertor(null, res.value, res.flags); + assertor(null, res.value); }); }); From 524856b3264ba751782f638860774bf868966618 Mon Sep 17 00:00:00 2001 From: Jake Teton-Landis Date: Mon, 12 Apr 2021 17:04:09 -0700 Subject: [PATCH 49/79] correctly handle CAS failure --- src/memjs/memjs.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/memjs/memjs.ts b/src/memjs/memjs.ts index a77a8fd..cdc2c94 100644 --- a/src/memjs/memjs.ts +++ b/src/memjs/memjs.ts @@ -538,6 +538,11 @@ class Client { callback(null, true); } break; + case ResponseStatus.KEY_EXISTS: + // CAS failed. + if (callback) { + callback(null, false); + } default: this.handleResponseError("SET", response?.header?.status, callback); } From 471d42df7d0365cd2f5a2d2cb94069263381056d Mon Sep 17 00:00:00 2001 From: Jake Teton-Landis Date: Mon, 12 Apr 2021 17:04:21 -0700 Subject: [PATCH 50/79] cli tester thingy --- cli.js | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 cli.js diff --git a/cli.js b/cli.js new file mode 100644 index 0000000..0f1afdd --- /dev/null +++ b/cli.js @@ -0,0 +1,52 @@ +const MemJS = require("."); +const client = MemJS.Client.create(); + +let i = 0; + +function next(promise) { + const id = i++; + const varname = `r${id}`; + + const assign = (r) => { + global[varname] = r; + global["r"] = r; + }; + + if (promise.then) { + promise.then( + (r) => { + console.log(`r${id} = resolved`, r); + assign(r); + }, + (r) => { + console.log(`r${id} = rejected`, r); + assign(r); + } + ); + } else { + console.log(`r${id} =`, promise); + assign(promise); + } +} + +Object.assign(global, { + MemJS, + client, + next, + p: next, +}); + +console.log(` +Run as node --inspect cli.js, +then open Chrome inspector up and click the little node icon. + +MemJS: memjs library export +client: a client connected to localhost:11211 +p: a function to resolve promises + +Example: + p(client.get('foo')) + r1.cas.toString() +`); + +setInterval(() => {}, 5000); From b7dbe881cbc9a56e3032d23eba4ca292340b7605 Mon Sep 17 00:00:00 2001 From: Jake Teton-Landis Date: Mon, 12 Apr 2021 17:07:23 -0700 Subject: [PATCH 51/79] make cli self-executing --- cli.js | 1 + 1 file changed, 1 insertion(+) mode change 100644 => 100755 cli.js diff --git a/cli.js b/cli.js old mode 100644 new mode 100755 index 0f1afdd..3a788e3 --- a/cli.js +++ b/cli.js @@ -1,3 +1,4 @@ +#! node --inspect const MemJS = require("."); const client = MemJS.Client.create(); From 477a74e3601fef98186f77d8a5a28e724c4fd917 Mon Sep 17 00:00:00 2001 From: Jake Teton-Landis Date: Mon, 12 Apr 2021 17:07:38 -0700 Subject: [PATCH 52/79] remove ambiguous getmulti case --- src/memjs/memjs.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/memjs/memjs.ts b/src/memjs/memjs.ts index cdc2c94..21965f4 100644 --- a/src/memjs/memjs.ts +++ b/src/memjs/memjs.ts @@ -374,12 +374,6 @@ class Client { } } break; - case ResponseStatus.KEY_NOT_FOUND: - if (callback) { - // @blackmad: IS THIS CORRECT??? - callback(null, null); - } - break; default: this.handleResponseError("GET", response.header.status, callback); } From 1fc7181b436a0382be842259e9c4e20e9b17109b Mon Sep 17 00:00:00 2001 From: Jake Teton-Landis Date: Mon, 12 Apr 2021 17:11:18 -0700 Subject: [PATCH 53/79] remove unused logger --- src/memjs/memjs.ts | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/src/memjs/memjs.ts b/src/memjs/memjs.ts index 21965f4..ca3b254 100644 --- a/src/memjs/memjs.ts +++ b/src/memjs/memjs.ts @@ -498,10 +498,9 @@ class Client { }); } - const logger = this.options.logger; - const expires = (options || {}).expires; + const expires = options.expires; - // TODO: support flags, support version (CAS) + // TODO: support flags this.incrSeq(); const expiration = makeExpiration(expires || this.options.expires); const extras = Buffer.concat([Buffer.from("00000000", "hex"), expiration]); @@ -538,7 +537,7 @@ class Client { callback(null, false); } default: - this.handleResponseError("SET", response?.header?.status, callback); + this.handleResponseError("SET", response!.header.status, callback); } }); } @@ -591,7 +590,6 @@ class Client { ); }); } - const logger = this.options.logger; // TODO: support flags, support version (CAS) this.incrSeq(); @@ -674,7 +672,6 @@ class Client { ); }); } - const logger = this.options.logger; // TODO: support flags, support version (CAS) this.incrSeq(); @@ -749,7 +746,6 @@ class Client { }); } // TODO: Support version (CAS) - const logger = this.options.logger; this.incrSeq(); const request = makeRequestBuffer(4, key, "", "", this.seq); this.perform(key, request, this.seq, (err, response) => { @@ -827,7 +823,6 @@ class Client { }); }); } - const logger = this.options.logger; // TODO: support version (CAS) this.incrSeq(); @@ -915,8 +910,6 @@ class Client { }); } // TODO: support version (CAS) - const logger = this.options.logger; - this.incrSeq(); const initial = options.initial || 0; const expires = options.expires || this.options.expires; @@ -988,7 +981,6 @@ class Client { }); } // TODO: support version (CAS) - const logger = this.options.logger; this.incrSeq(); const opcode: constants.OP = constants.OP_APPEND; const serialized = this.serializer.serialize(opcode, value, ""); @@ -1054,7 +1046,6 @@ class Client { }); } // TODO: support version (CAS) - const logger = this.options.logger; this.incrSeq(); const opcode: constants.OP = constants.OP_PREPEND; @@ -1125,7 +1116,6 @@ class Client { }); } // TODO: support version (CAS) - const logger = this.options.logger; this.incrSeq(); const extras = makeExpiration(expires || this.options.expires); const request = makeRequestBuffer(0x1c, key, extras, "", this.seq); @@ -1237,7 +1227,6 @@ class Client { stats: Record | null ) => void ): void { - const logger = this.options.logger; this.incrSeq(); const request = makeRequestBuffer(0x10, key, "", "", this.seq); @@ -1385,7 +1374,6 @@ class Client { "", this.seq ); - const logger = this.options.logger; this.performOnServer(server, request, this.seq, (err, response) => { if (err) { From 258c3a979b24e528a5d56767120430ff5f1ff8b7 Mon Sep 17 00:00:00 2001 From: Jake Teton-Landis Date: Mon, 12 Apr 2021 17:12:55 -0700 Subject: [PATCH 54/79] more commento --- src/memjs/memjs.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/memjs/memjs.ts b/src/memjs/memjs.ts index ca3b254..b4e5eb8 100644 --- a/src/memjs/memjs.ts +++ b/src/memjs/memjs.ts @@ -60,6 +60,9 @@ interface SerializerProp { } /** + * The client has partial support for serializing and deserializing values from the + * Buffer byte strings we recieve from the wire. The default serializer is for MaybeBuffer. + * * If Value and Extras are of type Buffer, then return type WhenBuffer. Otherwise, * return type NotBuffer. */ From ba50aeb75992a24c2b4a45791e1f50418c410e3d Mon Sep 17 00:00:00 2001 From: Jake Teton-Landis Date: Mon, 12 Apr 2021 17:21:29 -0700 Subject: [PATCH 55/79] test set w/ cas --- src/memjs/memjs.ts | 8 ++- src/test/client_test.ts | 124 ++++++++++++++++++++++++---------------- 2 files changed, 81 insertions(+), 51 deletions(-) diff --git a/src/memjs/memjs.ts b/src/memjs/memjs.ts index b4e5eb8..00f7c7c 100644 --- a/src/memjs/memjs.ts +++ b/src/memjs/memjs.ts @@ -535,9 +535,11 @@ class Client { } break; case ResponseStatus.KEY_EXISTS: - // CAS failed. - if (callback) { - callback(null, false); + if (options.cas) { + if (callback) { + callback(null, false); + } + break; } default: this.handleResponseError("SET", response!.header.status, callback); diff --git a/src/test/client_test.ts b/src/test/client_test.ts index 40eba01..d6bd032 100644 --- a/src/test/client_test.ts +++ b/src/test/client_test.ts @@ -635,6 +635,38 @@ test("SetWithExpiration", function (t) { }); }); +test("SetCASUnsuccessful", (t) => { + let n = 0; + const casToken = "verycool"; + const dummyServer = makeDummyServer("dummyServer"); + dummyServer.write = function (requestBuf) { + const request = parseMessage(requestBuf); + t.equal("hello", request.key.toString()); + t.equal("world", request.val.toString()); + t.equal(casToken, request.header.cas?.toString()); + n += 1; + dummyServer.respond({ + header: { + status: constants.ResponseStatus.KEY_EXISTS, + opaque: request.header.opaque, + }, + }); + }; + + const client = makeClient([dummyServer]); + const assertor = function (err: Error | null, val: boolean | null) { + t.equal(false, val, "Returns false on CAS failure"); + t.equal(1, n, "Ensure set is called"); + }; + client.set("hello", "world", { cas: Buffer.from(casToken) }, assertor); + n = 0; + return client + .set("hello", "world", { cas: Buffer.from(casToken) }) + .then(function (val) { + assertor(null, val); + }); +}); + test("SetUnsuccessful", function (t) { let n = 0; const dummyServer = makeDummyServer("dummyServer"); @@ -1144,31 +1176,29 @@ test("IncrementSuccessful", function (t) { }; const client = makeClient([dummyServer]); - client.increment( - "number-increment-test", - 5, - {}, - function (err: Error | null, success, val) { - callbn += 1; - t.equal(true, success); - t.equal(6, val); - t.equal(null, err); - done(); - } - ); + client.increment("number-increment-test", 5, {}, function ( + err: Error | null, + success, + val + ) { + callbn += 1; + t.equal(true, success); + t.equal(6, val); + t.equal(null, err); + done(); + }); - client.increment( - "number-increment-test", - 5, - { initial: 3 }, - function (err: Error | null, success, val) { - callbn += 1; - t.equal(true, success); - t.equal(6, val); - t.equal(null, err); - done(); - } - ); + client.increment("number-increment-test", 5, { initial: 3 }, function ( + err: Error | null, + success, + val + ) { + callbn += 1; + t.equal(true, success); + t.equal(6, val); + t.equal(null, err); + done(); + }); const done = (function () { let called = 0; @@ -1207,18 +1237,17 @@ test("DecrementSuccessful", function (t) { }; const client = makeClient([dummyServer]); - client.decrement( - "number-decrement-test", - 5, - {}, - function (err: Error | null, success, val) { - t.equal(true, success); - t.equal(6, val); - t.equal(null, err); - t.equal(1, n, "Ensure decr is called"); - t.end(); - } - ); + client.decrement("number-decrement-test", 5, {}, function ( + err: Error | null, + success, + val + ) { + t.equal(true, success); + t.equal(6, val); + t.equal(null, err); + t.equal(1, n, "Ensure decr is called"); + t.end(); + }); }); test("DecrementSuccessfulWithoutOption", function (t) { @@ -1246,18 +1275,17 @@ test("DecrementSuccessfulWithoutOption", function (t) { }; const client = makeClient([dummyServer]); - client.decrement( - "number-decrement-test", - 5, - {}, - function (err: Error | null, success, val) { - t.equal(true, success); - t.equal(6, val); - t.equal(null, err); - t.equal(1, n, "Ensure decr is called"); - t.end(); - } - ); + client.decrement("number-decrement-test", 5, {}, function ( + err: Error | null, + success, + val + ) { + t.equal(true, success); + t.equal(6, val); + t.equal(null, err); + t.equal(1, n, "Ensure decr is called"); + t.end(); + }); }); test("AppendSuccessful", function (t) { From 87cb9c7073aae3030401373e0c5b75ffbb0f6ccd Mon Sep 17 00:00:00 2001 From: Jake Teton-Landis Date: Tue, 13 Apr 2021 11:41:08 -0700 Subject: [PATCH 56/79] WIP: remove callbacks from public methods (#10) * WIP: remove callbacks from public methods * remove some ! * finish with methods that use this.perform * wip: fix test * wip 2 more tests * all tests pass --- src/memjs/memjs.ts | 1051 ++++++++++----------------------------- src/test/client_test.ts | 685 ++++++++++--------------- 2 files changed, 508 insertions(+), 1228 deletions(-) diff --git a/src/memjs/memjs.ts b/src/memjs/memjs.ts index 00f7c7c..0f82be2 100644 --- a/src/memjs/memjs.ts +++ b/src/memjs/memjs.ts @@ -234,75 +234,26 @@ class Client { return this.options.keyToServerHashFunction(this.serverKeys, key); } - // ## Memcache Commands - // - // All commands return their results through a callback passed as the last - // required argument (some commands, like `Client#set`, take optional arguments - // after the callback). - // - // The callback signature always follows: - // - // callback(err, [arg1[, arg2[, arg3[...]]]]) - // - // In case of an error the _err_ argument will be non-null and contain the - // `Error`. A notable exception includes a `Client#get` on a key that doesn't - // exist. In this case, _err_ will be null, as will the _value and _extras_ - // arguments. - /** * Retrieves the value at the given key in memcache. */ - get(key: string): Promise | null>; - get( - key: string, - callback: ( - error: Error | null, - result: GetResult | null - ) => void - ): void; - get( - key: string, - callback?: ( - error: Error | null, - result: GetResult | null - ) => void - ): Promise | null> | void { - if (callback === undefined) { - return promisify((callback) => { - this.get(key, function (err, value) { - callback(err, value); - }); - }); - } + async get(key: string): Promise | null> { this.incrSeq(); const request = makeRequestBuffer(constants.OP_GET, key, "", "", this.seq); - this.perform(key, request, this.seq, (err, response) => { - if (err) { - if (callback) { - callback(err, null); - } - return; - } - switch (response!.header.status) { - case ResponseStatus.SUCCESS: - if (callback) { - const deserialized = this.serializer.deserialize( - response!.header.opcode, - response!.val, - response!.extras - ); - callback(null, { ...deserialized, cas: response!.header.cas }); - } - break; - case ResponseStatus.KEY_NOT_FOUND: - if (callback) { - callback(null, null); - } - break; - default: - this.handleResponseError("GET", response?.header?.status, callback); - } - }); + const response = await this.perform(key, request, this.seq); + switch (response.header.status) { + case ResponseStatus.SUCCESS: + const deserialized = this.serializer.deserialize( + response.header.opcode, + response.val, + response.extras + ); + return { ...deserialized, cas: response.header.cas }; + case ResponseStatus.KEY_NOT_FOUND: + return null; + default: + throw this.createAndLogError("GET", response.header.status); + } } /** Build a pipelined get multi request by sending one GETKQ for each key (quiet, meaning it won't respond if the value is missing) followed by a no-op to force a response (and to give us a sentinel response that the pipeline is done) @@ -346,85 +297,57 @@ class Client { } /** Executing a pipelined (multi) get against a single server. This is a private implementation detail of getMulti. */ - _getMultiToServer( + async _getMultiToServer( serv: Server, - keys: Keys[], - callback: ( - error: Error | null, - values: GetMultiResult | null - ) => void - ) { - const responseMap: GetMultiResult = {}; + keys: Keys[] + ): Promise> { + return new Promise((resolve, reject) => { + const responseMap: GetMultiResult = {}; - const handle: OnResponseCallback = (response) => { - switch (response.header.status) { - case ResponseStatus.SUCCESS: - if (callback) { - const deserialized = this.serializer.deserialize( - response.header.opcode, - response.val, - response.extras - ); + const handle: OnResponseCallback = (response) => { + switch (response.header.status) { + case ResponseStatus.SUCCESS: // When we get the no-op response, we are done with this one getMulti in the per-backend fan-out if (response.header.opcode === constants.OP_NO_OP) { // This ensures the handler will be deleted from the responseCallbacks map in server.js // This isn't technically needed here because the logic in server.js also checks if totalBodyLength === 0, but our unittests aren't great about setting that field, and also this makes it more explicit handle.quiet = false; - callback(null, responseMap); + resolve(responseMap); } else { + const deserialized = this.serializer.deserialize( + response.header.opcode, + response.val, + response.extras + ); const key = response.key.toString(); responseMap[key] = { ...deserialized, cas: response.header.cas }; } - } - break; - default: - this.handleResponseError("GET", response.header.status, callback); - } - }; - // This prevents the handler from being deleted - // after the first response. Logic in server.js. - handle.quiet = true; + break; + default: + return reject( + this.createAndLogError("GET", response.header.status) + ); + } + }; + // This prevents the handler from being deleted + // after the first response. Logic in server.js. + handle.quiet = true; - const request = this._buildGetMultiRequest(keys); - serv.onResponse(this.seq, handle); - serv.onError(this.seq, function (err) { - if (callback) { - callback(err, null); - } + const request = this._buildGetMultiRequest(keys); + serv.onResponse(this.seq, handle); + serv.onError(this.seq, reject); + this.incrSeq(); + serv.write(request); }); - this.incrSeq(); - serv.write(request); } /** * Retrievs the value at the given keys in memcached. Returns a map from the * requested keys to results, or null if the key was not found. */ - getMulti( + async getMulti( keys: Keys[] - ): Promise | null>; - getMulti( - keys: Keys[], - callback: ( - error: Error | null, - value: GetMultiResult | null - ) => void - ): void; - getMulti( - keys: Keys[], - callback?: ( - error: Error | null, - value: GetMultiResult | null - ) => void - ): Promise | null> | void { - if (callback === undefined) { - return promisify((callback) => { - this.getMulti(keys, function (err, value) { - callback(err, value); - }); - }); - } - + ): Promise | null> { const serverKeytoLookupKeys: { [serverKey: string]: string[]; } = {}; @@ -437,114 +360,59 @@ class Client { }); const usedServerKeys = Object.keys(serverKeytoLookupKeys); - let outstandingCalls = usedServerKeys.length; - const recordMap: GetMultiResult = {}; - let hadError = false; - function latchCallback( - err: Error | null, - values: GetMultiResult | null - ) { - if (hadError) { - return; - } - - if (err) { - hadError = true; - callback!(err, null); - return; - } - - merge(recordMap, values); - outstandingCalls -= 1; - if (outstandingCalls === 0) { - callback!(null, recordMap); - } - } + const results = await Promise.all( + usedServerKeys.map((serverKey) => { + const server = this.serverKeyToServer(serverKey); + return this._getMultiToServer(server, serverKeytoLookupKeys[serverKey]); + }) + ); - for (const serverKeyIndex in usedServerKeys) { - const serverKey = usedServerKeys[serverKeyIndex]; - const server = this.serverKeyToServer(serverKey); - this._getMultiToServer( - server, - serverKeytoLookupKeys[serverKey], - latchCallback - ); - } + return Object.assign({}, ...results); } /** - * Sets the given _key_ to _value_. + * Sets `key` to `value`. */ - set( + async set( key: string, value: Value, options?: { expires?: number; cas?: CASToken } - ): Promise; - set( - key: string, - value: Value, - options: { expires?: number; cas?: CASToken }, - callback: (error: Error | null, success: boolean | null) => void - ): void; - set( - key: string, - value: Value, - options: { expires?: number; cas?: CASToken }, - callback?: (error: Error | null, success: boolean | null) => void - ): Promise | void { - if (callback === undefined && typeof options !== "function") { - if (!options) options = {}; - return promisify((callback) => { - this.set(key, value, options, function (err, success) { - callback(err, success); - }); - }); - } - - const expires = options.expires; + ): Promise { + const expires = options?.expires; + const cas = options?.cas; // TODO: support flags this.incrSeq(); const expiration = makeExpiration(expires || this.options.expires); const extras = Buffer.concat([Buffer.from("00000000", "hex"), expiration]); - - const opcode: constants.OP = 1; - const serialized = this.serializer.serialize(opcode, value, extras); - + const serialized = this.serializer.serialize( + constants.OP_SET, + value, + extras + ); const request = Utils.encodeRequest({ header: { opcode: constants.OP_SET, opaque: this.seq, - cas: options.cas, + cas, }, key, value: serialized.value, extras: serialized.extras, }); - this.perform(key, request, this.seq, (err, response) => { - if (err) { - if (callback) { - callback(err, null); + const response = await this.perform(key, request, this.seq); + switch (response.header.status) { + case ResponseStatus.SUCCESS: + return true; + case ResponseStatus.KEY_EXISTS: + if (cas) { + return false; + } else { + throw this.createAndLogError("SET", response.header.status); } - return; - } - switch (response!.header.status) { - case ResponseStatus.SUCCESS: - if (callback) { - callback(null, true); - } - break; - case ResponseStatus.KEY_EXISTS: - if (options.cas) { - if (callback) { - callback(null, false); - } - break; - } - default: - this.handleResponseError("SET", response!.header.status, callback); - } - }); + default: + throw this.createAndLogError("SET", response.header.status); + } } /** @@ -556,54 +424,18 @@ class Client { * The options dictionary takes: * * _expires_: overrides the default expiration (see `Client.create`) for this * particular key-value pair. - * - * The callback signature is: - * - * callback(err, success) - * @param key - * @param value - * @param options - * @param callback */ - add( + async add( key: string, value: Value, options?: { expires?: number } - ): Promise; - add( - key: string, - value: Value, - options: { expires?: number }, - callback: (error: Error | null, success: boolean | null) => void - ): void; - add( - key: string, - value: Value, - options?: { expires?: number }, - callback?: (error: Error | null, success: boolean | null) => void - ): Promise | void { - if (callback === undefined && options !== "function") { - if (!options) options = {}; - return promisify((callback) => { - this.add( - key, - value, - options as { expires?: number }, - function (err, success) { - callback(err, success); - } - ); - }); - } - + ): Promise { // TODO: support flags, support version (CAS) this.incrSeq(); - const expiration = makeExpiration( - (options || {}).expires || this.options.expires - ); + const expiration = makeExpiration(options?.expires || this.options.expires); const extras = Buffer.concat([Buffer.from("00000000", "hex"), expiration]); - const opcode: constants.OP = 2; + const opcode = constants.OP_ADD; const serialized = this.serializer.serialize(opcode, value, extras); const request = makeRequestBuffer( opcode, @@ -612,80 +444,33 @@ class Client { serialized.value, this.seq ); - this.perform(key, request, this.seq, (err, response) => { - if (err) { - if (callback) { - callback(err, null); - } - return; - } - switch (response!.header.status) { - case ResponseStatus.SUCCESS: - if (callback) { - callback(null, true); - } - break; - case ResponseStatus.KEY_EXISTS: - if (callback) { - callback(null, false); - } - break; - default: - return this.handleResponseError( - "ADD", - response?.header?.status, - callback - ); - } - }); + const response = await this.perform(key, request, this.seq); + switch (response.header.status) { + case ResponseStatus.SUCCESS: + return true; + case ResponseStatus.KEY_EXISTS: + return false; + break; + default: + throw this.createAndLogError("ADD", response.header.status); + } } /** - * REPLACE - * * Replaces the given _key_ and _value_ to memcache. The operation only succeeds * if the key is already present. - * - * The options dictionary takes: - * * _expires_: overrides the default expiration (see `Client.create`) for this - * particular key-value pair. - * - * The callback signature is: - * - * callback(err, success) - * @param key - * @param value - * @param options - * @param callback */ - replace( + async replace( key: string, value: Value, - options?: { expires?: number }, - callback?: (error: Error | null, success: boolean | null) => void - ): Promise | void { - if (callback === undefined && options !== "function") { - if (!options) options = {}; - return promisify((callback) => { - this.replace( - key, - value, - options as { expires?: number }, - function (err, success) { - callback(err, success); - } - ); - }); - } - + options?: { expires?: number } + ): Promise { // TODO: support flags, support version (CAS) this.incrSeq(); - const expiration = makeExpiration( - (options || {}).expires || this.options.expires - ); + const expiration = makeExpiration(options?.expires || this.options.expires); const extras = Buffer.concat([Buffer.from("00000000", "hex"), expiration]); - const opcode: constants.OP = 3; + const opcode: constants.OP = constants.OP_REPLACE; const serialized = this.serializer.serialize(opcode, value, extras); const request = makeRequestBuffer( opcode, @@ -694,145 +479,49 @@ class Client { serialized.value, this.seq ); - this.perform(key, request, this.seq, (err, response) => { - if (err) { - if (callback) { - callback(err, null); - } - return; - } - switch (response!.header.status) { - case ResponseStatus.SUCCESS: - if (callback) { - callback(null, true); - } - break; - case ResponseStatus.KEY_NOT_FOUND: - if (callback) { - callback(null, false); - } - break; - default: - this.handleResponseError( - "REPLACE", - response?.header?.status, - callback - ); - } - }); + const response = await this.perform(key, request, this.seq); + switch (response.header.status) { + case ResponseStatus.SUCCESS: + return true; + case ResponseStatus.KEY_NOT_FOUND: + return false; + default: + throw this.createAndLogError("REPLACE", response.header.status); + } } /** - * DELETE - * * Deletes the given _key_ from memcache. The operation only succeeds * if the key is already present. - * - * The callback signature is: - * - * callback(err, success) - * @param key - * @param callback */ - delete(key: string): Promise; - delete( - key: string, - callback: (err: Error | null, success: boolean | null) => void - ): void; - delete( - key: string, - callback?: (err: Error | null, success: boolean | null) => void - ): Promise | void { - if (callback === undefined) { - return promisify((callback) => { - this.delete(key, function (err, success) { - callback(err, Boolean(success)); - }); - }); - } + async delete(key: string): Promise { // TODO: Support version (CAS) this.incrSeq(); const request = makeRequestBuffer(4, key, "", "", this.seq); - this.perform(key, request, this.seq, (err, response) => { - if (err) { - if (callback) { - callback(err, null); - } - return; - } - switch (response!.header.status) { - case ResponseStatus.SUCCESS: - if (callback) { - callback(null, true); - } - break; - case ResponseStatus.KEY_NOT_FOUND: - if (callback) { - callback(null, false); - } - break; - default: - this.handleResponseError("DELETE", response?.header.status, callback); - } - }); + const response = await this.perform(key, request, this.seq); + + switch (response.header.status) { + case ResponseStatus.SUCCESS: + return true; + case ResponseStatus.KEY_NOT_FOUND: + return false; + default: + throw this.createAndLogError("DELETE", response?.header.status); + } } /** - * INCREMENT - * * Increments the given _key_ in memcache. - * - * The options dictionary takes: - * * _initial_: the value for the key if not already present, defaults to 0. - * * _expires_: overrides the default expiration (see `Client.create`) for this - * particular key-value pair. - * - * The callback signature is: - * - * callback(err, success, value) - * @param key - * @param amount - * @param options - * @param callback */ - increment( - key: string, - amount: number, - options: { initial?: number; expires?: number } - ): Promise<{ value: number | null; success: boolean | null }>; - increment( - key: string, - amount: number, - options: { initial?: number; expires?: number }, - callback: ( - error: Error | null, - success: boolean | null, - value?: number | null - ) => void - ): void; - increment( + async increment( key: string, amount: number, - options: { initial?: number; expires?: number }, - callback?: ( - error: Error | null, - success: boolean | null, - value?: number | null - ) => void - ): Promise<{ value: number | null; success: boolean | null }> | void { - if (callback === undefined && options !== "function") { - return promisify((callback) => { - if (!options) options = {}; - this.increment(key, amount, options, function (err, success, value) { - callback(err, { success: success, value: value || null }); - }); - }); - } - + options?: { initial?: number; expires?: number } + ): Promise<{ value: number | null; success: boolean | null }> { // TODO: support version (CAS) this.incrSeq(); - const initial = options.initial || 0; - const expires = options.expires || this.options.expires; + const initial = options?.initial || 0; + const expires = options?.expires || this.options.expires; const extras = makeAmountInitialAndExpiration(amount, initial, expires); const request = makeRequestBuffer( constants.OP_INCREMENT, @@ -841,79 +530,25 @@ class Client { "", this.seq ); - this.perform(key, request, this.seq, (err, response) => { - if (err) { - if (callback) { - callback(err, null); - } - return; - } - switch (response!.header.status) { - case ResponseStatus.SUCCESS: - const bufInt = - (response!.val.readUInt32BE(0) << 8) + - response!.val.readUInt32BE(4); - if (callback) { - callback(null, true, bufInt); - } - break; - default: - const error = this.handleResponseError( - "INCREMENT", - response!.header.status, - undefined - ); - if (callback) { - callback(error, null, null); - } - } - }); + const response = await this.perform(key, request, this.seq); + switch (response.header.status) { + case ResponseStatus.SUCCESS: + const bufInt = + (response.val.readUInt32BE(0) << 8) + response.val.readUInt32BE(4); + return { value: bufInt, success: true }; + default: + throw this.createAndLogError("INCREMENT", response.header.status); + } } - // DECREMENT - // - // Decrements the given _key_ in memcache. - // - // The options dictionary takes: - // * _initial_: the value for the key if not already present, defaults to 0. - // * _expires_: overrides the default expiration (see `Client.create`) for this - // particular key-value pair. - // - // The callback signature is: - // - // callback(err, success, value) - decrement( + /** + * Decrements the given `key` in memcache. + */ + async decrement( key: string, amount: number, options: { initial?: number; expires?: number } - ): Promise<{ value: number | null; success: boolean | null }>; - decrement( - key: string, - amount: number, - options: { initial?: number; expires?: number }, - callback: ( - error: Error | null, - success: boolean | null, - value?: number | null - ) => void - ): void; - decrement( - key: string, - amount: number, - options: { initial?: number; expires?: number }, - callback?: ( - error: Error | null, - success: boolean | null, - value?: number | null - ) => void - ): Promise<{ value: number | null; success: boolean | null }> | void { - if (callback === undefined && options !== "function") { - return promisify((callback) => { - this.decrement(key, amount, options, function (err, success, value) { - callback(err, { success: success, value: value || null }); - }); - }); - } + ): Promise<{ value: number | null; success: boolean | null }> { // TODO: support version (CAS) this.incrSeq(); const initial = options.initial || 0; @@ -926,65 +561,22 @@ class Client { "", this.seq ); - this.perform(key, request, this.seq, (err, response) => { - if (err) { - if (callback) { - callback(err, null); - } - return; - } - switch (response!.header.status) { - case ResponseStatus.SUCCESS: - const bufInt = - (response!.val.readUInt32BE(0) << 8) + - response!.val.readUInt32BE(4); - if (callback) { - callback(null, true, bufInt); - } - break; - default: - const error = this.handleResponseError( - "DECREMENT", - response!.header.status, - undefined - ); - if (callback) { - callback(error, null, null); - } - } - }); + const response = await this.perform(key, request, this.seq); + switch (response.header.status) { + case ResponseStatus.SUCCESS: + const bufInt = + (response.val.readUInt32BE(0) << 8) + response.val.readUInt32BE(4); + return { value: bufInt, success: true }; + default: + throw this.createAndLogError("DECREMENT", response.header.status); + } } /** - * APPEND - * * Append the given _value_ to the value associated with the given _key_ in - * memcache. The operation only succeeds if the key is already present. The - * callback signature is: - * - * callback(err, success) - * @param key - * @param value - * @param callback + * memcache. The operation only succeeds if the key is already present. */ - append(key: string, value: Value): Promise; - append( - key: string, - value: Value, - callback: (err: Error | null, success: boolean | null) => void - ): void; - append( - key: string, - value: Value, - callback?: (err: Error | null, success: boolean | null) => void - ) { - if (callback === undefined) { - return promisify((callback) => { - this.append(key, value, function (err, success) { - callback(err, success); - }); - }); - } + async append(key: string, value: Value): Promise { // TODO: support version (CAS) this.incrSeq(); const opcode: constants.OP = constants.OP_APPEND; @@ -996,63 +588,24 @@ class Client { serialized.value, this.seq ); - this.perform(key, request, this.seq, (err, response) => { - if (err) { - if (callback) { - callback(err, null); - } - return; - } - switch (response!.header.status) { - case ResponseStatus.SUCCESS: - if (callback) { - callback(null, true); - } - break; - case ResponseStatus.KEY_NOT_FOUND: - if (callback) { - callback(null, false); - } - break; - default: - this.handleResponseError("APPEND", response!.header.status, callback); - } - }); + const response = await this.perform(key, request, this.seq); + switch (response.header.status) { + case ResponseStatus.SUCCESS: + return true; + case ResponseStatus.KEY_NOT_FOUND: + return false; + default: + throw this.createAndLogError("APPEND", response.header.status); + } } /** - * PREPEND - * * Prepend the given _value_ to the value associated with the given _key_ in - * memcache. The operation only succeeds if the key is already present. The - * callback signature is: - * - * callback(err, success) - * @param key - * @param value - * @param callback + * memcache. The operation only succeeds if the key is already present. */ - prepend(key: string, value: Value): Promise; - prepend( - key: string, - value: Value, - callback: (err: Error | null, success: boolean | null) => void - ): void; - prepend( - key: string, - value: Value, - callback?: (err: Error | null, success: boolean | null) => void - ) { - if (callback === undefined) { - return promisify((callback) => { - this.prepend(key, value, function (err, success) { - callback(err, success); - }); - }); - } + async prepend(key: string, value: Value): Promise { // TODO: support version (CAS) this.incrSeq(); - const opcode: constants.OP = constants.OP_PREPEND; const serialized = this.serializer.serialize(opcode, value, ""); const request = makeRequestBuffer( @@ -1062,90 +615,35 @@ class Client { serialized.value, this.seq ); - this.perform(key, request, this.seq, (err, response) => { - if (err) { - if (callback) { - callback(err, null); - } - return; - } - switch (response!.header.status) { - case ResponseStatus.SUCCESS: - if (callback) { - callback(null, true); - } - break; - case ResponseStatus.KEY_NOT_FOUND: - if (callback) { - callback(null, false); - } - break; - default: - this.handleResponseError( - "PREPEND", - response!.header.status, - callback - ); - } - }); + const response = await this.perform(key, request, this.seq); + switch (response.header.status) { + case ResponseStatus.SUCCESS: + return true; + case ResponseStatus.KEY_NOT_FOUND: + return false; + default: + throw this.createAndLogError("PREPEND", response.header.status); + } } /** - * TOUCH - * * Touch sets an expiration value, given by _expires_, on the given _key_ in - * memcache. The operation only succeeds if the key is already present. The - * callback signature is: - * - * callback(err, success) - * @param key - * @param expires - * @param callback + * memcache. The operation only succeeds if the key is already present. */ - touch(key: string, expires: number): Promise; - touch( - key: string, - expires: number, - callback: (err: Error | null, success: boolean | null) => void - ): void; - touch( - key: string, - expires: number, - callback?: (err: Error | null, success: boolean | null) => void - ): Promise | void { - if (callback === undefined) { - return promisify((callback) => { - this.touch(key, expires, function (err, success) { - callback(err, Boolean(success)); - }); - }); - } + async touch(key: string, expires: number): Promise { // TODO: support version (CAS) this.incrSeq(); const extras = makeExpiration(expires || this.options.expires); const request = makeRequestBuffer(0x1c, key, extras, "", this.seq); - this.perform(key, request, this.seq, (err, response) => { - if (err) { - if (callback) { - callback(err, null); - } - return; - } - switch (response!.header.status) { - case ResponseStatus.SUCCESS: - if (callback) { - callback(null, true); - } - break; - case ResponseStatus.KEY_NOT_FOUND: - if (callback) { - callback(null, false); - } - break; - default: - this.handleResponseError("TOUCH", response!.header.status, callback); - } - }); + const response = await this.perform(key, request, this.seq); + switch (response.header.status) { + case ResponseStatus.SUCCESS: + return true; + case ResponseStatus.KEY_NOT_FOUND: + return false; + default: + throw this.createAndLogError("TOUCH", response.header.status); + } } /** @@ -1354,111 +852,58 @@ class Client { } } - _version(server: Server): Promise<{ value: Value | null }>; - _version( - server: Server, - callback: (error: Error | null, value: Value | null) => void - ): void; - _version( - server: Server, - callback?: (error: Error | null, value: Value | null) => void - ): Promise<{ value: Value | null }> | void { - if (callback === undefined) { - return promisify((callback) => { - this._version(server, function (err, value) { - callback(err, { value: value }); - }); - }); - } - - this.incrSeq(); - const request = makeRequestBuffer( - constants.OP_VERSION, - "", - "", - "", - this.seq - ); - - this.performOnServer(server, request, this.seq, (err, response) => { - if (err) { - if (callback) { - callback(err, null); + _version(server: Server): Promise<{ value: Value | null }> { + return new Promise((resolve, reject) => { + this.incrSeq(); + const request = makeRequestBuffer( + constants.OP_VERSION, + "", + "", + "", + this.seq + ); + this.performOnServer(server, request, this.seq, (err, response) => { + if (err) { + return reject(err); } - return; - } - switch (response!.header.status) { - case ResponseStatus.SUCCESS: - /* TODO: this is bugged, we should't use the deserializer here, since version always returns a version string. + switch (response!.header.status) { + case ResponseStatus.SUCCESS: + /* TODO: this is bugged, we should't use the deserializer here, since version always returns a version string. The deserializer should only be used on user key data. */ - const deserialized = this.serializer.deserialize( - response!.header.opcode, - response!.val, - response!.extras - ); - callback(null, deserialized.value); - break; - default: - this.handleResponseError( - "VERSION", - response!.header.status, - callback - ); - } + const deserialized = this.serializer.deserialize( + response!.header.opcode, + response!.val, + response!.extras + ); + return resolve({ value: deserialized.value }); + default: + return reject( + this.createAndLogError("VERSION", response!.header.status) + ); + } + }); }); } /** - * VERSION - * * Request the server version from the "first" server in the backend pool. - * * The server responds with a packet containing the version string in the body with the following format: "x.y.z" */ - version(): Promise<{ value: Value | null }>; - version(callback: (error: Error | null, value: Value | null) => void): void; - version(callback?: (error: Error | null, value: Value | null) => void) { + version(): Promise<{ value: Value | null }> { const server = this.serverKeyToServer(this.serverKeys[0]); - if (callback) { - this._version(server, callback); - } else { - return this._version(server); - } + return this._version(server); } /** - * VERSION-ALL - * * Retrieves the server version from all the servers * in the backend pool, errors if any one of them has an * error - * - * The callback signature is: - * - * callback(err, value, flags) - * - * @param keys - * @param callback */ - versionAll(): Promise<{ + async versionAll(): Promise<{ values: Record; - }>; - versionAll( - callback: ( - err: Error | null, - values: Record | null - ) => void - ): void; - versionAll( - callback?: ( - err: Error | null, - values: Record | null - ) => void - ): Promise<{ - values: Record; - }> | void { - const promise = Promise.all( + }> { + const versionObjects = await Promise.all( this.serverKeys.map((serverKey) => { const server = this.serverKeyToServer(serverKey); @@ -1466,30 +911,17 @@ class Client { return { serverKey: serverKey, value: response.value }; }); }) - ).then((versionObjects) => { - const values = versionObjects.reduce((accumulator, versionObject) => { - accumulator[versionObject.serverKey] = versionObject.value; - return accumulator; - }, {} as Record); - return { values: values }; - }); - - if (callback === undefined) { - return promise; - } - promise - .then((response) => { - callback(null, response.values); - }) - .catch((err) => { - callback(err, null); - }); + ); + const values = versionObjects.reduce((accumulator, versionObject) => { + accumulator[versionObject.serverKey] = versionObject.value; + return accumulator; + }, {} as Record); + return { values: values }; } /** - * CLOSE - * * Closes (abruptly) connections to all the servers. + * @see this.quit */ close() { for (let i = 0; i < this.servers.length; i++) { @@ -1504,27 +936,35 @@ class Client { * @param {buffer} request a buffer containing the request * @param {number} seq the sequence number of the operation. It is used to pin the callbacks to a specific operation and should never change during a `perform`. - * @param {*} callback a callback invoked when a response is received or the request fails - * @param {*} retries number of times to retry request on failure + * @param {number?} retries number of times to retry request on failure */ perform( key: string, request: Buffer, seq: number, - callback: ResponseOrErrorCallback, retries?: number - ) { - const serverKey = this.lookupKeyToServerKey(key); - - const server = this.serverKeyToServer(serverKey); + ): Promise { + return new Promise((resolve, reject) => { + const serverKey = this.lookupKeyToServerKey(key); + const server = this.serverKeyToServer(serverKey); - if (!server) { - if (callback) { - callback(new Error("No servers available"), null); + if (!server) { + return reject(new Error("No servers available")); } - return; - } - return this.performOnServer(server, request, seq, callback, retries); + + this.performOnServer( + server, + request, + seq, + (error, response) => { + if (error) { + return reject(error); + } + resolve(response!); + }, + retries + ); + }); } performOnServer( @@ -1581,6 +1021,17 @@ class Client { this.seq &= 0xffffffff; } + private createAndLogError( + commandName: string, + responseStatus: ResponseStatus | undefined + ): Error { + const errorMessage = `MemJS ${commandName}: ${constants.responseStatusToString( + responseStatus + )}`; + this.options.logger.log(errorMessage); + return new Error(errorMessage); + } + /** * Log an error to the logger, then return the error. * If a callback is given, call it with callback(error, null). @@ -1590,11 +1041,7 @@ class Client { responseStatus: ResponseStatus | undefined, callback: undefined | ((error: Error | null, other: null) => void) ): Error { - const errorMessage = `MemJS ${commandName}: ${constants.responseStatusToString( - responseStatus - )}`; - this.options.logger.log(errorMessage); - const error = new Error(errorMessage); + const error = this.createAndLogError(commandName, responseStatus); if (callback) { callback(error, null); } diff --git a/src/test/client_test.ts b/src/test/client_test.ts index d6bd032..ca995be 100644 --- a/src/test/client_test.ts +++ b/src/test/client_test.ts @@ -52,7 +52,25 @@ function makeDummyServer(name: string) { }; } -test("GetSuccessful", function (t) { +async function mustReject( + t: TapTestType, + promise: Promise, + matcher: (error: Error) => any +) { + let threwError: Error | undefined = undefined; + try { + await promise; + } catch (error) { + threwError = error; + } + + t.assert(threwError, "Expected promise to be rejected"); + if (threwError) { + return matcher(threwError); + } +} + +test("GetSuccessful", async function (t) { let n = 0; const dummyServer = makeDummyServer("dummyServer"); const casToken = Buffer.from("cas data"); @@ -68,25 +86,19 @@ test("GetSuccessful", function (t) { }; const client = makeClient([dummyServer]); - const assertor = function (err: Error | null, val: MemJS.GetResult | null) { - if (!val) { - t.ok(val, "must return value"); - return; - } - t.equal("world", val.value); - t.equal("flagshere", val.extras); - t.equal(casToken, val.cas); - t.equal(null, err); - t.equal(1, n, "Ensure get is called"); - }; - client.get("hello", assertor); - n = 0; - return client.get("hello").then(function (res) { - assertor(null, res); - }); + const val = await client.get("hello"); + + if (!val) { + t.ok(val, "must return value"); + return; + } + t.equal("world", val.value); + t.equal("flagshere", val.extras); + t.equal(casToken, val.cas); + t.equal(1, n, "Ensure get is called"); }); -test("GetNotFound", function (t) { +test("GetNotFound", async function (t) { let n = 0; const dummyServer = makeDummyServer("dummyServer"); dummyServer.write = function (requestBuf) { @@ -99,19 +111,12 @@ test("GetNotFound", function (t) { }; const client = makeClient([dummyServer]); - const assertor = function (err: Error | null, val: MemJS.GetResult | null) { - t.equal(null, val); - t.equal(1, n, "Ensure get is called"); - }; - client.get("hello", assertor); - n = 0; - return client.get("hello").then(function (res) { - assertor(null, res); - t.end(); - }); + const val = await client.get("hello"); + t.equal(null, val); + t.equal(1, n, "Ensure get is called"); }); -test("GetSerializer", function (t) { +test("GetSerializer", async function (t) { let n = 0; let dn = 0; const dummyServer = makeDummyServer("dummyServer"); @@ -138,27 +143,19 @@ test("GetSerializer", function (t) { }, }, }); - const assertor = function (err: Error | null, value: MemJS.GetResult | null) { - if (!value) { - t.ok(value, "must return value"); - return; - } - t.equal("deserialized", value.value); - t.equal("flagshere", value.extras); - t.equal(casToken, value.cas); - t.equal(null, err); - t.equal(1, n, "Ensure get is called"); - t.equal(1, dn, "Ensure deserialization is called once"); - }; - client.get("hello", assertor); - n = 0; - dn = 0; - return client.get("hello").then(function (res) { - assertor(null, res); - }); + const value = await client.get("hello"); + if (!value) { + t.ok(value, "must return value"); + return; + } + t.equal("deserialized", value.value); + t.equal("flagshere", value.extras); + t.equal(casToken, value.cas); + t.equal(1, n, "Ensure get is called"); + t.equal(1, dn, "Ensure deserialization is called once"); }); -tap.only("GetMultiSuccessful_SingleBackend", function (t) { +test("GetMultiSuccessful_SingleBackend", async function (t) { let n = 0; const dummyServer = makeDummyServer("dummyServer"); dummyServer.write = function (requestBuf) { @@ -201,40 +198,28 @@ tap.only("GetMultiSuccessful_SingleBackend", function (t) { }; const client = makeClient([dummyServer]); - const assertor = function ( - err: Error | null, - result: MemJS.GetMultiResult | null - ) { - t.deepEqual( - { - hello1: { - value: "world1", - extras: "flagshere", - cas: Buffer.from("cas hello1"), - }, - hello2: { - value: "world2", - extras: "flagshere", - cas: Buffer.from("cas hello2"), - }, - hello3: { - value: "world3", - extras: "flagshere", - cas: Buffer.from("cas hello3"), - }, + const result = await client.getMulti(["hello1", "hello2", "hello3"]); + t.deepEqual( + { + hello1: { + value: "world1", + extras: "flagshere", + cas: Buffer.from("cas hello1"), }, - result - ); - t.equal(null, err); - t.equal(1, n, "Ensure getMulti is called"); - }; - client.getMulti(["hello1", "hello2", "hello3"], assertor); - testAllCallbacksEmpty(t, dummyServer); - - n = 0; - return client.getMulti(["hello1", "hello2", "hello3"]).then(function (res) { - assertor(null, res); - }); + hello2: { + value: "world2", + extras: "flagshere", + cas: Buffer.from("cas hello2"), + }, + hello3: { + value: "world3", + extras: "flagshere", + cas: Buffer.from("cas hello3"), + }, + }, + result + ); + t.equal(1, n, "Ensure getMulti is called"); }); const DummyMultiGetFlags = "flagshere"; @@ -292,7 +277,7 @@ function makeDummyMultiGetServerResponder( return server; } -test("GetMultiSuccessful_MultiBackend", function (t) { +test("GetMultiSuccessful_MultiBackend", async function (t) { // the mappings from key to server were computer by just manually running the default hash on them const dummyServer1 = makeDummyMultiGetServerResponder( @@ -314,51 +299,38 @@ test("GetMultiSuccessful_MultiBackend", function (t) { const servers = [dummyServer1, dummyServer2]; const client = makeClient(servers); - - const assertor = function ( - err: Error | null, - val: MemJS.GetMultiResult | null - ) { - const expected: MemJS.GetMultiResult< - "hello1" | "hello2" | "hello3" | "hello4" - > = { - hello1: { - value: "world1", - extras: DummyMultiGetFlags, - cas: undefined, - }, - hello2: { - value: "world2", - extras: DummyMultiGetFlags, - cas: undefined, - }, - hello3: { - value: "world3", - extras: DummyMultiGetFlags, - cas: undefined, - }, - hello4: { - value: "world4", - extras: DummyMultiGetFlags, - cas: undefined, - }, - }; - t.deepEqual(expected, val); - console.log(val); - t.equal(null, err); + const val = await client.getMulti(["hello1", "hello2", "hello3", "hello4"]); + + const expected: MemJS.GetMultiResult< + "hello1" | "hello2" | "hello3" | "hello4" + > = { + hello1: { + value: "world1", + extras: DummyMultiGetFlags, + cas: undefined, + }, + hello2: { + value: "world2", + extras: DummyMultiGetFlags, + cas: undefined, + }, + hello3: { + value: "world3", + extras: DummyMultiGetFlags, + cas: undefined, + }, + hello4: { + value: "world4", + extras: DummyMultiGetFlags, + cas: undefined, + }, }; - client.getMulti(["hello1", "hello2", "hello3", "hello4"], assertor); + t.deepEqual(expected, val); testAllCallbacksEmpty(t, dummyServer1); testAllCallbacksEmpty(t, dummyServer2); - - return client - .getMulti(["hello1", "hello2", "hello3", "hello4"]) - .then(function (res) { - assertor(null, res); - }); }); -test("GetMultiSuccessful_MissingKeys_MultiBackend", function (t) { +test("GetMultiSuccessful_MissingKeys_MultiBackend", async function (t) { // the mappings from key to server were computed by just manually running the default hash on them const dummyServer1 = makeDummyMultiGetServerResponder( t, @@ -379,43 +351,31 @@ test("GetMultiSuccessful_MissingKeys_MultiBackend", function (t) { const servers = [dummyServer1, dummyServer2]; const client = makeClient(servers); + const val = await client.getMulti(["hello1", "hello2", "hello3", "hello4"]); - const assertor = function ( - err: Error | null, - val: MemJS.GetMultiResult | null - ) { - const expected: MemJS.GetMultiResult<"hello1" | "hello3" | "hello4"> = { - hello1: { - value: "world1", - extras: DummyMultiGetFlags, - cas: undefined, - }, - hello3: { - value: "world3", - extras: DummyMultiGetFlags, - cas: undefined, - }, - hello4: { - value: "world4", - extras: DummyMultiGetFlags, - cas: undefined, - }, - }; - t.deepEqual(expected, val); - t.equal(null, err); + const expected: MemJS.GetMultiResult<"hello1" | "hello3" | "hello4"> = { + hello1: { + value: "world1", + extras: DummyMultiGetFlags, + cas: undefined, + }, + hello3: { + value: "world3", + extras: DummyMultiGetFlags, + cas: undefined, + }, + hello4: { + value: "world4", + extras: DummyMultiGetFlags, + cas: undefined, + }, }; - client.getMulti(["hello1", "hello2", "hello3", "hello4"], assertor); + t.deepEqual(expected, val); testAllCallbacksEmpty(t, dummyServer1); testAllCallbacksEmpty(t, dummyServer2); - - return client - .getMulti(["hello1", "hello2", "hello3", "hello4"]) - .then(function (res) { - assertor(null, res); - }); }); -test("GetMultiError_MultiBackend", function (t) { +test("GetMultiError_MultiBackend", async function (t) { // the mappings from key to server were computed by just manually running the default hash on them const dummyServer1 = makeDummyMultiGetServerResponder( t, @@ -443,23 +403,18 @@ test("GetMultiError_MultiBackend", function (t) { const client = makeClient(servers); - const assertor = function (err: Error | null) { - t.notEqual(null, err); - t.equal("This is an expected error.", err?.message); - }; - client.getMulti(["hello1", "hello2", "hello3", "hello4"], assertor); - testAllCallbacksEmpty(t, dummyServer1); - testAllCallbacksEmpty(t, dummyServer2); - - return client - .getMulti(["hello1", "hello2", "hello3", "hello4"]) - .catch(function (err) { - assertor(err); - return true; - }); + await mustReject( + t, + client.getMulti(["hello1", "hello2", "hello3", "hello4"]), + (error) => { + t.equal("This is an expected error.", error.message); + testAllCallbacksEmpty(t, dummyServer1); + testAllCallbacksEmpty(t, dummyServer2); + } + ); }); -test("GetMultiSuccessfulWithMissingKeys", function (t) { +test("GetMultiSuccessfulWithMissingKeys", async function (t) { const dummyServer = makeDummyMultiGetServerResponder(t, { hello1: "world1", hello2: undefined, @@ -471,26 +426,23 @@ test("GetMultiSuccessfulWithMissingKeys", function (t) { err: Error | null, val: MemJS.GetMultiResult | null ) { - const expected: MemJS.GetMultiResult<"hello1" | "hello3"> = { - hello1: { - value: "world1", - extras: DummyMultiGetFlags, - cas: undefined, - }, - hello3: { - value: "world3", - extras: DummyMultiGetFlags, - cas: undefined, - }, - }; - t.deepEqual(expected, val); t.equal(null, err); }; - client.getMulti(["hello1", "hello2", "hello3"], assertor); + const val = await client.getMulti(["hello1", "hello2", "hello3"]); + const expected: MemJS.GetMultiResult<"hello1" | "hello3"> = { + hello1: { + value: "world1", + extras: DummyMultiGetFlags, + cas: undefined, + }, + hello3: { + value: "world3", + extras: DummyMultiGetFlags, + cas: undefined, + }, + }; + t.deepEqual(expected, val); testAllCallbacksEmpty(t, dummyServer); - return client.getMulti(["hello1", "hello2", "hello3"]).then(function (res) { - assertor(null, res); - }); }); test("GetMultiError", function (t) { @@ -528,18 +480,18 @@ test("GetMultiError", function (t) { const client = makeClient([dummyServer]); const assertor = function (err: Error | null) { t.notEqual(null, err); + testAllCallbacksEmpty(t, dummyServer); t.equal("This is an expected error.", err?.message); }; - client.getMulti(["hello1", "hello2", "hello3"], assertor); - testAllCallbacksEmpty(t, dummyServer); - return client.getMulti(["hello1", "hello2", "hello3"]).catch(function (err) { - assertor(err); - return true; - }); + return mustReject( + t, + client.getMulti(["hello1", "hello2", "hello3"]), + assertor + ); }); -test("SetSuccessful", function (t) { +test("SetSuccessful", async function (t) { const casToken = Buffer.from("cas toke"); let n = 0; const dummyServer = makeDummyServer("dummyServer"); @@ -555,21 +507,13 @@ test("SetSuccessful", function (t) { }; const client = makeClient([dummyServer]); - const assertor = function (err: Error | null, val: boolean | null) { - t.equal(true, val); - t.equal(null, err); - t.equal(1, n, "Ensure set is called"); - }; - client.set("hello", "world", { cas: casToken }, assertor); + const val = await client.set("hello", "world", { cas: casToken }); + t.equal(true, val); + t.equal(1, n, "Ensure set is called"); n = 0; - return client - .set("hello", "world", { cas: casToken }) - .then(function (success) { - assertor(null, success); - }); }); -test("SetSuccessfulWithoutOption", function (t) { +test("SetSuccessfulWithoutOption", async function (t) { let n = 0; const dummyServer = makeDummyServer("dummyServer"); dummyServer.write = function (requestBuf) { @@ -583,36 +527,12 @@ test("SetSuccessfulWithoutOption", function (t) { }; const client = makeClient([dummyServer]); - client.set("hello", "world", {}, function (err: Error | null, val) { - t.equal(true, val); - t.equal(null, err); - t.equal(1, n, "Ensure set is called"); - t.end(); - }); + const val = await client.set("hello", "world"); + t.equal(true, val); + t.equal(1, n, "Ensure set is called"); }); -test("SetPromiseWithoutOption", function (t) { - let n = 0; - const dummyServer = makeDummyServer("dummyServer"); - dummyServer.write = function (requestBuf) { - const request = parseMessage(requestBuf); - t.equal("hello", request.key.toString()); - t.equal("world", request.val.toString()); - n += 1; - dummyServer.respond({ - header: { status: 0, opaque: request.header.opaque }, - }); - }; - - const client = makeClient([dummyServer]); - return client.set("hello", "world").then(function (val) { - t.equal(true, val); - t.equal(1, n, "Ensure set is called"); - t.end(); - }); -}); - -test("SetWithExpiration", function (t) { +test("SetWithExpiration", async function (t) { let n = 0; const dummyServer = makeDummyServer("dummyServer"); dummyServer.write = function (requestBuf) { @@ -627,15 +547,12 @@ test("SetWithExpiration", function (t) { }; const client = makeClient([dummyServer], { expires: 1024 }); - client.set("hello", "world", {}, function (err: Error | null, val) { - t.equal(null, err); - t.equal(true, val); - t.equal(1, n, "Ensure set is called"); - t.end(); - }); + const val = await client.set("hello", "world", {}); + t.equal(true, val); + t.equal(1, n, "Ensure set is called"); }); -test("SetCASUnsuccessful", (t) => { +test("SetCASUnsuccessful", async (t) => { let n = 0; const casToken = "verycool"; const dummyServer = makeDummyServer("dummyServer"); @@ -654,17 +571,11 @@ test("SetCASUnsuccessful", (t) => { }; const client = makeClient([dummyServer]); - const assertor = function (err: Error | null, val: boolean | null) { - t.equal(false, val, "Returns false on CAS failure"); - t.equal(1, n, "Ensure set is called"); - }; - client.set("hello", "world", { cas: Buffer.from(casToken) }, assertor); - n = 0; - return client - .set("hello", "world", { cas: Buffer.from(casToken) }) - .then(function (val) { - assertor(null, val); - }); + const val = await client.set("hello", "world", { + cas: Buffer.from(casToken), + }); + t.equal(false, val, "Returns false on CAS failure"); + t.equal(1, n, "Ensure set is called"); }); test("SetUnsuccessful", function (t) { @@ -686,9 +597,7 @@ test("SetUnsuccessful", function (t) { t.equal("MemJS SET: " + constants.responseStatusToString(3), err?.message); t.equal(1, n, "Ensure set is called"); }; - client.set("hello", "world", {}, assertor); - n = 0; - return client.set("hello", "world", {}).catch(function (err) { + return mustReject(t, client.set("hello", "world", {}), function (err) { assertor(err, null); }); }); @@ -708,13 +617,16 @@ test("SetError", function (t) { }; const client = makeClient([dummyServer]); - client.set("hello", "world", {}, function (err: Error | null, val) { - t.notEqual(null, err); - t.equal("This is an expected error.", err?.message); - t.equal(null, val); - t.equal(2, n, "Ensure set is retried once"); - t.end(); - }); + return mustReject( + t, + client.set("hello", "world"), + function (err: Error | null) { + t.notEqual(null, err); + t.equal("This is an expected error.", err?.message); + t.equal(2, n, "Ensure set is retried once"); + t.end(); + } + ); }); test("SetError", function (t) { @@ -734,7 +646,9 @@ test("SetError", function (t) { }; const client = makeClient([dummyServer], { retries: 2 }); - client.set("hello", "world", {}, function (err /*, val */) { + return mustReject(t, client.set("hello", "world", {}), function ( + err /*, val */ + ) { t.equal(2, n, "Ensure set is retried once"); t.ok(err, "Ensure callback called with error"); t.equal("This is an expected error.", err?.message); @@ -756,14 +670,14 @@ test("SetErrorConcurrent", function (t) { }; const client = makeClient([dummyServer], { retries: 2 }); - client.set("hello", "world", {}, function (err /*, val */) { + mustReject(t, client.set("hello", "world", {}), function (err /*, val */) { t.ok(err, "Ensure callback called with error"); t.equal("This is an expected error.", err?.message); callbn1 += 1; done(); }); - client.set("foo", "bar", {}, function (err /*, val */) { + mustReject(t, client.set("foo", "bar", {}), function (err /*, val */) { t.ok(err, "Ensure callback called with error"); t.equal("This is an expected error.", err?.message); callbn2 += 1; @@ -783,7 +697,7 @@ test("SetErrorConcurrent", function (t) { })(); }); -test("SetUnicode", function (t) { +test("SetUnicode", async function (t) { let n = 0; const dummyServer = makeDummyServer("dummyServer"); dummyServer.write = function (requestBuf) { @@ -797,11 +711,9 @@ test("SetUnicode", function (t) { }; const client = makeClient([dummyServer]); - client.set("hello", "éééoào", {}, function (err: Error | null, val) { - t.equal(true, val); - t.equal(1, n, "Ensure set is called"); - t.end(); - }); + const val = await client.set("hello", "éééoào", {}); + t.equal(true, val); + t.equal(1, n, "Ensure set is called"); }); test("SetSerialize", function (t) { @@ -835,15 +747,12 @@ test("SetSerialize", function (t) { t.equal(1, n, "Ensure set is called"); t.equal(1, sn, "Ensure serialization is called once"); }; - client.set("hello", "world", {}, assertor); - n = 0; - sn = 0; - return client.set("hello", "world", {}).catch(function (err) { + return mustReject(t, client.set("hello", "world", {}), function (err) { assertor(err, null); }); }); -test("AddSuccessful", function (t) { +test("AddSuccessful", async function (t) { let n = 0; const dummyServer = makeDummyServer("dummyServer"); dummyServer.write = function (requestBuf) { @@ -858,19 +767,12 @@ test("AddSuccessful", function (t) { }; const client = makeClient([dummyServer], { expires: 1024 }); - const assertor = function (err: Error | null, val: boolean | null) { - t.equal(null, err); - t.equal(true, val); - t.equal(1, n, "Ensure add is called"); - }; - client.add("hello", "world", {}, assertor); - n = 0; - return client.add("hello", "world", {}).then(function (success) { - assertor(null, success); - }); + const val = await client.add("hello", "world", {}); + t.equal(true, val); + t.equal(1, n, "Ensure add is called"); }); -test("AddSuccessfulWithoutOption", function (t) { +test("AddSuccessfulWithoutOption", async function (t) { let n = 0; const dummyServer = makeDummyServer("dummyServer"); dummyServer.write = function (requestBuf) { @@ -885,15 +787,12 @@ test("AddSuccessfulWithoutOption", function (t) { }; const client = makeClient([dummyServer], { expires: 1024 }); - client.add("hello", "world", {}, function (err: Error | null, val) { - t.equal(null, err); - t.equal(true, val); - t.equal(1, n, "Ensure add is called"); - t.end(); - }); + const val = await client.add("hello", "world", {}); + t.equal(true, val); + t.equal(1, n, "Ensure add is called"); }); -test("AddKeyExists", function (t) { +test("AddKeyExists", async function (t) { let n = 0; const dummyServer = makeDummyServer("dummyServer"); dummyServer.write = function (requestBuf) { @@ -907,15 +806,12 @@ test("AddKeyExists", function (t) { }; const client = makeClient([dummyServer]); - client.add("hello", "world", {}, function (err: Error | null, val) { - t.equal(null, err); - t.equal(false, val); - t.equal(1, n, "Ensure add is called"); - t.end(); - }); + const val = await client.add("hello", "world", {}); + t.equal(false, val); + t.equal(1, n, "Ensure add is called"); }); -test("AddSerializer", function (t) { +test("AddSerializer", async function (t) { let n = 0; let sn = 0; const dummyServer = makeDummyServer("dummyServer"); @@ -945,21 +841,13 @@ test("AddSerializer", function (t) { }, }, }); - const assertor = function (err: Error | null, val: boolean | null) { - t.equal(null, err); - t.equal(true, val); - t.equal(1, n, "Ensure add is called"); - t.equal(1, sn, "Ensure serialization is called once"); - }; - client.add("hello", "world", {}, assertor); - n = 0; - sn = 0; - return client.add("hello", "world", {}).then(function (success) { - assertor(null, success); - }); + const val = await client.add("hello", "world", {}); + t.equal(true, val); + t.equal(1, n, "Ensure add is called"); + t.equal(1, sn, "Ensure serialization is called once"); }); -test("ReplaceSuccessful", function (t) { +test("ReplaceSuccessful", async function (t) { let n = 0; const dummyServer = makeDummyServer("dummyServer"); dummyServer.write = function (requestBuf) { @@ -976,22 +864,13 @@ test("ReplaceSuccessful", function (t) { const client = makeClient([dummyServer], { expires: 1024 }); const assertor = function (err: Error | null, val: boolean | null) { t.equal(null, err); - t.equal(true, val); - t.equal(1, n, "Ensure replace is called"); }; - client.replace("hello", "world", {}, assertor); - n = 0; - const replaceP = client.replace("hello", "world", {}); - if (!replaceP) { - return t.true(replaceP); - } else { - return replaceP.then(function (success) { - assertor(null, success); - }); - } + const val = await client.replace("hello", "world", {}); + t.equal(true, val); + t.equal(1, n, "Ensure replace is called"); }); -test("ReplaceSuccessfulWithoutOption", function (t) { +test("ReplaceSuccessfulWithoutOption", async function (t) { let n = 0; const dummyServer = makeDummyServer("dummyServer"); dummyServer.write = function (requestBuf) { @@ -1006,15 +885,12 @@ test("ReplaceSuccessfulWithoutOption", function (t) { }; const client = makeClient([dummyServer], { expires: 1024 }); - client.replace("hello", "world", {}, function (err: Error | null, val) { - t.equal(null, err); - t.equal(true, val); - t.equal(1, n, "Ensure replace is called"); - t.end(); - }); + const val = await client.replace("hello", "world", {}); + t.equal(true, val); + t.equal(1, n, "Ensure replace is called"); }); -test("ReplaceKeyDNE", function (t) { +test("ReplaceKeyDNE", async function (t) { let n = 0; const dummyServer = makeDummyServer("dummyServer"); dummyServer.write = function (requestBuf) { @@ -1028,15 +904,12 @@ test("ReplaceKeyDNE", function (t) { }; const client = makeClient([dummyServer]); - client.replace("hello", "world", {}, function (err: Error | null, val) { - t.equal(null, err); - t.equal(false, val); - t.equal(1, n, "Ensure replace is called"); - t.end(); - }); + const val = await client.replace("hello", "world", {}); + t.equal(false, val); + t.equal(1, n, "Ensure replace is called"); }); -test("DeleteSuccessful", function (t) { +test("DeleteSuccessful", async function (t) { let n = 0; const dummyServer = makeDummyServer("dummyServer"); dummyServer.write = function (requestBuf) { @@ -1049,19 +922,12 @@ test("DeleteSuccessful", function (t) { }; const client = makeClient([dummyServer]); - const assertor = function (err: Error | null, val: boolean | null) { - t.equal(null, err); - t.equal(true, val); - t.equal(1, n, "Ensure delete is called"); - }; - client.delete("hello", assertor); - n = 0; - return client.delete("hello").then(function (success) { - assertor(null, success); - }); + const val = await client.delete("hello"); + t.equal(true, val); + t.equal(1, n, "Ensure delete is called"); }); -test("DeleteKeyDNE", function (t) { +test("DeleteKeyDNE", async function (t) { let n = 0; const dummyServer = makeDummyServer("dummyServer"); dummyServer.write = function (requestBuf) { @@ -1074,12 +940,9 @@ test("DeleteKeyDNE", function (t) { }; const client = makeClient([dummyServer]); - client.delete("hello", function (err: Error | null, val) { - t.equal(null, err); - t.equal(false, val); - t.equal(1, n, "Ensure delete is called"); - t.end(); - }); + const val = await client.delete("hello"); + t.equal(false, val); + t.equal(1, n, "Ensure delete is called"); }); test("Flush", function (t) { @@ -1176,29 +1039,23 @@ test("IncrementSuccessful", function (t) { }; const client = makeClient([dummyServer]); - client.increment("number-increment-test", 5, {}, function ( - err: Error | null, - success, - val - ) { - callbn += 1; - t.equal(true, success); - t.equal(6, val); - t.equal(null, err); - done(); - }); + client + .increment("number-increment-test", 5, {}) + .then(function ({ success, value: val }) { + callbn += 1; + t.equal(true, success); + t.equal(6, val); + done(); + }); - client.increment("number-increment-test", 5, { initial: 3 }, function ( - err: Error | null, - success, - val - ) { - callbn += 1; - t.equal(true, success); - t.equal(6, val); - t.equal(null, err); - done(); - }); + client + .increment("number-increment-test", 5, { initial: 3 }) + .then(function ({ success, value: val }) { + callbn += 1; + t.equal(true, success); + t.equal(6, val); + done(); + }); const done = (function () { let called = 0; @@ -1237,17 +1094,13 @@ test("DecrementSuccessful", function (t) { }; const client = makeClient([dummyServer]); - client.decrement("number-decrement-test", 5, {}, function ( - err: Error | null, - success, - val - ) { - t.equal(true, success); - t.equal(6, val); - t.equal(null, err); - t.equal(1, n, "Ensure decr is called"); - t.end(); - }); + return client + .decrement("number-decrement-test", 5, {}) + .then(function ({ success, value: val }) { + t.equal(true, success); + t.equal(6, val); + t.equal(1, n, "Ensure decr is called"); + }); }); test("DecrementSuccessfulWithoutOption", function (t) { @@ -1275,17 +1128,14 @@ test("DecrementSuccessfulWithoutOption", function (t) { }; const client = makeClient([dummyServer]); - client.decrement("number-decrement-test", 5, {}, function ( - err: Error | null, - success, - val - ) { - t.equal(true, success); - t.equal(6, val); - t.equal(null, err); - t.equal(1, n, "Ensure decr is called"); - t.end(); - }); + client + .decrement("number-decrement-test", 5, {}) + .then(function ({ success, value: val }) { + t.equal(true, success); + t.equal(6, val); + t.equal(1, n, "Ensure decr is called"); + t.end(); + }); }); test("AppendSuccessful", function (t) { @@ -1302,8 +1152,7 @@ test("AppendSuccessful", function (t) { }; const client = makeClient([dummyServer], { expires: 1024 }); - client.append("hello", "world", function (err: Error | null, val) { - t.equal(null, err); + client.append("hello", "world").then(function (val) { t.equal(true, val); t.equal(1, n, "Ensure append is called"); t.end(); @@ -1324,8 +1173,7 @@ test("AppendKeyDNE", function (t) { }; const client = makeClient([dummyServer]); - client.append("hello", "world", function (err: Error | null, val) { - t.equal(null, err); + client.append("hello", "world").then(function (val) { t.equal(false, val); t.equal(1, n, "Ensure append is called"); t.end(); @@ -1346,8 +1194,7 @@ test("PrependSuccessful", function (t) { }; const client = makeClient([dummyServer], { expires: 1024 }); - client.prepend("hello", "world", function (err: Error | null, val) { - t.equal(null, err); + client.prepend("hello", "world").then(function (val) { t.equal(true, val); t.equal(1, n, "Ensure prepend is called"); t.end(); @@ -1368,8 +1215,7 @@ test("PrependKeyDNE", function (t) { }; const client = makeClient([dummyServer]); - client.prepend("hello", "world", function (err: Error | null, val) { - t.equal(null, err); + client.prepend("hello", "world").then(function (val) { t.equal(false, val); t.equal(1, n, "Ensure prepend is called"); t.end(); @@ -1391,8 +1237,7 @@ test("TouchSuccessful", function (t) { }; const client = makeClient([dummyServer]); - client.touch("hello", 1024, function (err: Error | null, val) { - t.equal(null, err); + client.touch("hello", 1024).then(function (val) { t.equal(true, val); t.equal(1, n, "Ensure touch is called"); t.end(); @@ -1414,10 +1259,9 @@ test("TouchKeyDNE", function (t) { }; const client = makeClient([dummyServer]); - client.touch("hello", 1024, function (err: Error | null, val) { - t.equal(null, err); + client.touch("hello", 1024).then(function (val) { t.equal(false, val); - t.equal(1, n, "Ensure ptouch is called"); + t.equal(1, n, "Ensure touch is called"); t.end(); }); }); @@ -1468,8 +1312,6 @@ test("Very Large Client Seq", function (t) { t.equal(true, val); t.equal(1, n, "Ensure add is called"); }; - client.add("hello", "world", {}, assertor); - n = 0; return client.add("hello", "world", {}).then(function (success) { assertor(null, success); }); @@ -1515,9 +1357,6 @@ test("VersionSuccessful", function (t) { t.equal(n, 1, "Ensure version is called"); }; - client.version(assertor); - n = 0; - return client.version().then(function (res) { assertor(null, res.value); }); @@ -1542,10 +1381,8 @@ tap.only("VersionError", function (t) { t.equal("This is an expected error.", err?.message); }; - client.version(assertor); - return client.version().catch(function (err) { + return mustReject(t, client.version(), function (err) { assertor(err); - return true; }); }); @@ -1570,8 +1407,6 @@ test("VersionAllSuccessful", function (t) { t.equal(null, err); }; - client.versionAll(assertor); - return client.versionAll().then(function (res) { assertor(null, res.values); }); @@ -1594,9 +1429,7 @@ tap.only("VersionAllSomeFailed", function (t) { t.equal("This is an expected error.", err?.message); }; - client.versionAll(assertor); - - return client.versionAll().catch(function (err) { + return mustReject(t, client.versionAll(), function (err) { assertor(err); }); }); From e7a523dd0a6d6ee9974d1d650aa0a63230c2f0cf Mon Sep 17 00:00:00 2001 From: Jake Teton-Landis Date: Tue, 13 Apr 2021 12:29:40 -0700 Subject: [PATCH 57/79] Check in and productionize typescript build (#11) * build settings for node@12 * node>=12 * set up everything to ensure we check in lib * smoketest * dont check in tests tho * ensure-clean: print the diff pls * ??? --- .github/workflows/ci.yml | 1 + .gitignore | 2 +- bin/ensure-clean.sh | 10 + lib/memjs/constants.d.ts | 173 +++++++ lib/memjs/constants.d.ts.map | 1 + lib/memjs/constants.js | 220 +++++++++ lib/memjs/header.d.ts | 18 + lib/memjs/header.d.ts.map | 1 + lib/memjs/header.js | 43 ++ lib/memjs/memjs.d.ts | 304 ++++++++++++ lib/memjs/memjs.d.ts.map | 1 + lib/memjs/memjs.js | 728 +++++++++++++++++++++++++++++ lib/memjs/noop-serializer.d.ts | 12 + lib/memjs/noop-serializer.d.ts.map | 1 + lib/memjs/noop-serializer.js | 12 + lib/memjs/server.d.ts | 60 +++ lib/memjs/server.d.ts.map | 1 + lib/memjs/server.js | 251 ++++++++++ lib/memjs/utils.d.ts | 29 ++ lib/memjs/utils.d.ts.map | 1 + lib/memjs/utils.js | 198 ++++++++ package.json | 5 +- smoketest.js | 50 ++ tsconfig.json | 8 +- 24 files changed, 2123 insertions(+), 7 deletions(-) create mode 100755 bin/ensure-clean.sh create mode 100644 lib/memjs/constants.d.ts create mode 100644 lib/memjs/constants.d.ts.map create mode 100644 lib/memjs/constants.js create mode 100644 lib/memjs/header.d.ts create mode 100644 lib/memjs/header.d.ts.map create mode 100644 lib/memjs/header.js create mode 100644 lib/memjs/memjs.d.ts create mode 100644 lib/memjs/memjs.d.ts.map create mode 100644 lib/memjs/memjs.js create mode 100644 lib/memjs/noop-serializer.d.ts create mode 100644 lib/memjs/noop-serializer.d.ts.map create mode 100644 lib/memjs/noop-serializer.js create mode 100644 lib/memjs/server.d.ts create mode 100644 lib/memjs/server.d.ts.map create mode 100644 lib/memjs/server.js create mode 100644 lib/memjs/utils.d.ts create mode 100644 lib/memjs/utils.d.ts.map create mode 100644 lib/memjs/utils.js create mode 100755 smoketest.js diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 78c337e..9a2d455 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,3 +22,4 @@ jobs: node-version: ${{ matrix.node-version }} - run: npm ci - run: npm test + - run: bin/ensure-clean.sh diff --git a/.gitignore b/.gitignore index dde57a0..55d8413 100644 --- a/.gitignore +++ b/.gitignore @@ -12,7 +12,7 @@ pids logs results build/ -lib/ +lib/test node_modules npm-debug.log diff --git a/bin/ensure-clean.sh b/bin/ensure-clean.sh new file mode 100755 index 0000000..eb8f316 --- /dev/null +++ b/bin/ensure-clean.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +if [[ -z "$(git status --porcelain)" ]]; then + echo "Git looks clean, you're good to go" > /dev/stderr +else + git status + git diff + echo "ERROR: Git looks dirty, see above. Check in all changes." > /dev/stderr + exit 2 +fi diff --git a/lib/memjs/constants.d.ts b/lib/memjs/constants.d.ts new file mode 100644 index 0000000..19a8ae6 --- /dev/null +++ b/lib/memjs/constants.d.ts @@ -0,0 +1,173 @@ +export declare const OP_GET = 0; +export declare const OP_SET = 1; +export declare const OP_ADD = 2; +export declare const OP_REPLACE = 3; +export declare const OP_DELETE = 4; +export declare const OP_INCREMENT = 5; +export declare const OP_DECREMENT = 6; +export declare const OP_QUIT = 7; +export declare const OP_FLUSH = 8; +export declare const OP_GETQ = 9; +export declare const OP_NO_OP = 10; +export declare const OP_VERSION = 11; +export declare const OP_GETK = 12; +export declare const OP_GETKQ = 13; +export declare const OP_APPEND = 14; +export declare const OP_PREPEND = 15; +export declare const OP_STAT = 16; +export declare const OP_SETQ = 17; +export declare const OP_ADDQ = 18; +export declare const OP_REPLACEQ = 19; +export declare const OP_DELETEQ = 20; +export declare const OP_INCREMENTQ = 21; +export declare const OP_DECREMENTQ = 22; +export declare const OP_QUITQ = 23; +export declare const OP_FLUSHQ = 24; +export declare const OP_APPENDQ = 25; +export declare const OP_PREPENDQ = 26; +export declare const OP_VERBOSITY = 27; +export declare const OP_TOUCH = 28; +export declare const OP_GAT = 29; +export declare const OP_GATQ = 30; +export declare const OP_HELO = 31; +export declare const OP_SASL_LIST_MECHS = 32; +export declare const OP_SASL_AUTH = 33; +export declare const OP_SASL_STEP = 34; +export declare const OP_IOCTL_GET = 35; +export declare const OP_IOCTL_SET = 36; +export declare const OP_CONFIG_VALIDATE = 37; +export declare const OP_CONFIG_RELOAD = 38; +export declare const OP_AUDIT_PUT = 39; +export declare const OP_AUDIT_CONFIG_RELOAD = 40; +export declare const OP_SHUTDOWN = 41; +export declare const OP_RGET = 48; +export declare const OP_RSET = 49; +export declare const OP_RSETQ = 50; +export declare const OP_RAPPEND = 51; +export declare const OP_RAPPENDQ = 52; +export declare const OP_RPREPEND = 53; +export declare const OP_RPREPENDQ = 54; +export declare const OP_RDELETE = 55; +export declare const OP_RDELETEQ = 56; +export declare const OP_RINCR = 57; +export declare const OP_RINCRQ = 58; +export declare const OP_RDECR = 59; +export declare const OP_RDECRQ = 60; +export declare const OP_SET_VBUCKET = 61; +export declare const OP_GET_VBUCKET = 62; +export declare const OP_DEL_VBUCKET = 63; +export declare const OP_TAP_CONNECT = 64; +export declare const OP_TAP_MUTATION = 65; +export declare const OP_TAP_DELETE = 66; +export declare const OP_TAP_FLUSH = 67; +export declare const OP_TAP_OPAQUE = 68; +export declare const OP_TAP_VBUCKET_SET = 69; +export declare const OP_TAP_CHECKOUT_START = 70; +export declare const OP_TAP_CHECKPOINT_END = 71; +export declare const OP_GET_ALL_VB_SEQNOS = 72; +export declare const OP_DCP_OPEN = 80; +export declare const OP_DCP_ADD_STREAM = 81; +export declare const OP_DCP_CLOSE_STREAM = 82; +export declare const OP_DCP_STREAM_REQ = 83; +export declare const OP_DCP_GET_FAILOVER_LOG = 84; +export declare const OP_DCP_STREAM_END = 85; +export declare const OP_DCP_SNAPSHOT_MARKER = 86; +export declare const OP_DCP_MUTATION = 87; +export declare const OP_DCP_DELETION = 88; +export declare const OP_DCP_EXPIRATION = 89; +export declare const OP_DCP_FLUSH = 90; +export declare const OP_DCP_SET_VBUCKET_STATE = 91; +export declare const OP_DCP_NOOP = 92; +export declare const OP_DCP_BUFFER_ACKNOWLEDGEMENT = 93; +export declare const OP_DCP_CONTROL = 94; +export declare const OP_DCP_RESERVED4 = 95; +export declare const OP_STOP_PERSISTENCE = 128; +export declare const OP_START_PERSISTENCE = 129; +export declare const OP_SET_PARAM = 130; +export declare const OP_GET_REPLICA = 131; +export declare const OP_CREATE_BUCKET = 133; +export declare const OP_DELETE_BUCKET = 134; +export declare const OP_LIST_BUCKETS = 135; +export declare const OP_SELECT_BUCKET = 137; +export declare const OP_ASSUME_ROLE = 138; +export declare const OP_OBSERVE_SEQNO = 145; +export declare const OP_OBSERVE = 146; +export declare const OP_EVICT_KEY = 147; +export declare const OP_GET_LOCKED = 148; +export declare const OP_UNLOCK_KEY = 149; +export declare const OP_LAST_CLOSED_CHECKPOINT = 151; +export declare const OP_DEREGISTER_TAP_CLIENT = 158; +export declare const OP_RESET_REPLICATION_CHAIN = 159; +export declare const OP_GET_META = 160; +export declare const OP_GETQ_META = 161; +export declare const OP_SET_WITH_META = 162; +export declare const OP_SETQ_WITH_META = 163; +export declare const OP_ADD_WITH_META = 164; +export declare const OP_ADDQ_WITH_META = 165; +export declare const OP_SNAPSHOT_VB_STATES = 166; +export declare const OP_VBUCKET_BATCH_COUNT = 167; +export declare const OP_DEL_WITH_META = 168; +export declare const OP_DELQ_WITH_META = 169; +export declare const OP_CREATE_CHECKPOINT = 170; +export declare const OP_NOTIFY_VBUCKET_UPDATE = 172; +export declare const OP_ENABLE_TRAFFIC = 173; +export declare const OP_DISABLE_TRAFFIC = 174; +export declare const OP_CHANGE_VB_FILTER = 176; +export declare const OP_CHECKPOINT_PERSISTENCE = 177; +export declare const OP_RETURN_META = 178; +export declare const OP_COMPACT_DB = 179; +export declare const OP_SET_CLUSTER_CONFIG = 180; +export declare const OP_GET_CLUSTER_CONFIG = 181; +export declare const OP_GET_RANDOM_KEY = 182; +export declare const OP_SEQNO_PERSISTENCE = 183; +export declare const OP_GET_KEYS = 184; +export declare const OP_SET_DRIFT_COUNTER_STATE = 193; +export declare const OP_GET_ADJUSTED_TIME = 194; +export declare const OP_SUBDOC_GET = 197; +export declare const OP_SUBDOC_EXISTS = 198; +export declare const OP_SUBDOC_DICT_ADD = 199; +export declare const OP_SUBDOC_DICT_UPSERT = 200; +export declare const OP_SUBDOC_DELETE = 201; +export declare const OP_SUBDOC_REPLACE = 202; +export declare const OP_SUBDOC_ARRAY_PUSH_LAST = 203; +export declare const OP_SUBDOC_ARRAY_PUSH_FIRST = 204; +export declare const OP_SUBDOC_ARRAY_INSERT = 205; +export declare const OP_SUBDOC_ARRAY_ADD_UNIQUE = 206; +export declare const OP_SUBDOC_COUNTER = 207; +export declare const OP_SUBDOC_MULTI_LOOKUP = 208; +export declare const OP_SUBDOC_MULTI_MUTATION = 209; +export declare const OP_SUBDOC_GET_COUNT = 210; +export declare const OP_SCRUB = 240; +export declare const OP_ISASL_REFRESH = 241; +export declare const OP_SSL_CERTS_REFRESH = 242; +export declare const OP_GET_CMD_TIMER = 243; +export declare const OP_SET_CTRL_TOKEN = 244; +export declare const OP_GET_CTRL_TOKEN = 245; +export declare const OP_INIT_COMPLETE = 246; +export declare type OP = typeof OP_GET | typeof OP_SET | typeof OP_ADD | typeof OP_REPLACE | typeof OP_DELETE | typeof OP_INCREMENT | typeof OP_DECREMENT | typeof OP_QUIT | typeof OP_FLUSH | typeof OP_GETQ | typeof OP_NO_OP | typeof OP_VERSION | typeof OP_GETK | typeof OP_GETKQ | typeof OP_APPEND | typeof OP_PREPEND | typeof OP_STAT | typeof OP_SETQ | typeof OP_ADDQ | typeof OP_REPLACEQ | typeof OP_DELETEQ | typeof OP_INCREMENTQ | typeof OP_DECREMENTQ | typeof OP_QUITQ | typeof OP_FLUSHQ | typeof OP_APPENDQ | typeof OP_PREPENDQ | typeof OP_VERBOSITY | typeof OP_TOUCH | typeof OP_GAT | typeof OP_GATQ | typeof OP_HELO | typeof OP_SASL_LIST_MECHS | typeof OP_SASL_AUTH | typeof OP_SASL_STEP | typeof OP_IOCTL_GET | typeof OP_IOCTL_SET | typeof OP_CONFIG_VALIDATE | typeof OP_CONFIG_RELOAD | typeof OP_AUDIT_PUT | typeof OP_AUDIT_CONFIG_RELOAD | typeof OP_SHUTDOWN | typeof OP_RGET | typeof OP_RSET | typeof OP_RSETQ | typeof OP_RAPPEND | typeof OP_RAPPENDQ | typeof OP_RPREPEND | typeof OP_RPREPENDQ | typeof OP_RDELETE | typeof OP_RDELETEQ | typeof OP_RINCR | typeof OP_RINCRQ | typeof OP_RDECR | typeof OP_RDECRQ | typeof OP_SET_VBUCKET | typeof OP_GET_VBUCKET | typeof OP_DEL_VBUCKET | typeof OP_TAP_CONNECT | typeof OP_TAP_MUTATION | typeof OP_TAP_DELETE | typeof OP_TAP_FLUSH | typeof OP_TAP_OPAQUE | typeof OP_TAP_VBUCKET_SET | typeof OP_TAP_CHECKOUT_START | typeof OP_TAP_CHECKPOINT_END | typeof OP_GET_ALL_VB_SEQNOS | typeof OP_DCP_OPEN | typeof OP_DCP_ADD_STREAM | typeof OP_DCP_CLOSE_STREAM | typeof OP_DCP_STREAM_REQ | typeof OP_DCP_GET_FAILOVER_LOG | typeof OP_DCP_STREAM_END | typeof OP_DCP_SNAPSHOT_MARKER | typeof OP_DCP_MUTATION | typeof OP_DCP_DELETION | typeof OP_DCP_EXPIRATION | typeof OP_DCP_FLUSH | typeof OP_DCP_SET_VBUCKET_STATE | typeof OP_DCP_NOOP | typeof OP_DCP_BUFFER_ACKNOWLEDGEMENT | typeof OP_DCP_CONTROL | typeof OP_DCP_RESERVED4 | typeof OP_STOP_PERSISTENCE | typeof OP_START_PERSISTENCE | typeof OP_SET_PARAM | typeof OP_GET_REPLICA | typeof OP_CREATE_BUCKET | typeof OP_DELETE_BUCKET | typeof OP_LIST_BUCKETS | typeof OP_SELECT_BUCKET | typeof OP_ASSUME_ROLE | typeof OP_OBSERVE_SEQNO | typeof OP_OBSERVE | typeof OP_EVICT_KEY | typeof OP_GET_LOCKED | typeof OP_UNLOCK_KEY | typeof OP_LAST_CLOSED_CHECKPOINT | typeof OP_DEREGISTER_TAP_CLIENT | typeof OP_RESET_REPLICATION_CHAIN | typeof OP_GET_META | typeof OP_GETQ_META | typeof OP_SET_WITH_META | typeof OP_SETQ_WITH_META | typeof OP_ADD_WITH_META | typeof OP_ADDQ_WITH_META | typeof OP_SNAPSHOT_VB_STATES | typeof OP_VBUCKET_BATCH_COUNT | typeof OP_DEL_WITH_META | typeof OP_DELQ_WITH_META | typeof OP_CREATE_CHECKPOINT | typeof OP_NOTIFY_VBUCKET_UPDATE | typeof OP_ENABLE_TRAFFIC | typeof OP_DISABLE_TRAFFIC | typeof OP_CHANGE_VB_FILTER | typeof OP_CHECKPOINT_PERSISTENCE | typeof OP_RETURN_META | typeof OP_COMPACT_DB | typeof OP_SET_CLUSTER_CONFIG | typeof OP_GET_CLUSTER_CONFIG | typeof OP_GET_RANDOM_KEY | typeof OP_SEQNO_PERSISTENCE | typeof OP_GET_KEYS | typeof OP_SET_DRIFT_COUNTER_STATE | typeof OP_GET_ADJUSTED_TIME | typeof OP_SUBDOC_GET | typeof OP_SUBDOC_EXISTS | typeof OP_SUBDOC_DICT_ADD | typeof OP_SUBDOC_DICT_UPSERT | typeof OP_SUBDOC_DELETE | typeof OP_SUBDOC_REPLACE | typeof OP_SUBDOC_ARRAY_PUSH_LAST | typeof OP_SUBDOC_ARRAY_PUSH_FIRST | typeof OP_SUBDOC_ARRAY_INSERT | typeof OP_SUBDOC_ARRAY_ADD_UNIQUE | typeof OP_SUBDOC_COUNTER | typeof OP_SUBDOC_MULTI_LOOKUP | typeof OP_SUBDOC_MULTI_MUTATION | typeof OP_SUBDOC_GET_COUNT | typeof OP_SCRUB | typeof OP_ISASL_REFRESH | typeof OP_SSL_CERTS_REFRESH | typeof OP_GET_CMD_TIMER | typeof OP_SET_CTRL_TOKEN | typeof OP_GET_CTRL_TOKEN | typeof OP_INIT_COMPLETE; +/** + * Response statuses + * https://github.com/memcached/memcached/wiki/BinaryProtocolRevamped#response-status + */ +export declare const ResponseStatus: { + /** Named "No error" in the memcached docs, but clearer in code as "SUCCESS". */ + readonly SUCCESS: 0; + readonly KEY_NOT_FOUND: 1; + readonly KEY_EXISTS: 2; + readonly VALUE_TOO_LARGE: 3; + readonly INVALID_ARGUMENTS: 4; + readonly ITEM_NOT_STORED: 5; + readonly INCR_DECR_ON_NON_NUMERIC_VALUE: 6; + readonly THE_VBUCKET_BELONGS_TO_ANOTHER_SERVER: 7; + readonly AUTHENTICATION_ERROR: 8; + readonly AUTHENTICATION_CONTINUE: 9; + readonly UNKNOWN_COMMAND: 129; + readonly OUT_OF_MEMORY: 130; + readonly NOT_SUPPORTED: 131; + readonly INTERNAL_ERROR: 132; + readonly BUSY: 133; + readonly TEMPORARY_FAILURE: 134; +}; +export declare type ResponseStatus = typeof ResponseStatus[keyof typeof ResponseStatus]; +export declare function responseStatusToString(responseStatus: ResponseStatus | undefined): string; +//# sourceMappingURL=constants.d.ts.map \ No newline at end of file diff --git a/lib/memjs/constants.d.ts.map b/lib/memjs/constants.d.ts.map new file mode 100644 index 0000000..634b85a --- /dev/null +++ b/lib/memjs/constants.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/memjs/constants.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/lib/memjs/constants.js b/lib/memjs/constants.js new file mode 100644 index 0000000..8f38bfa --- /dev/null +++ b/lib/memjs/constants.js @@ -0,0 +1,220 @@ +"use strict"; +/* +Constants from memcached binary protocol docs +https://github.com/couchbase/memcached/blob/master/docs/BinaryProtocol.md#0x0d-getkq-get-with-key-quietly + +Note: not all constants in here are implemented in this library, not all constants from the docs are included here +*/ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.OP_RDELETE = exports.OP_RPREPENDQ = exports.OP_RPREPEND = exports.OP_RAPPENDQ = exports.OP_RAPPEND = exports.OP_RSETQ = exports.OP_RSET = exports.OP_RGET = exports.OP_SHUTDOWN = exports.OP_AUDIT_CONFIG_RELOAD = exports.OP_AUDIT_PUT = exports.OP_CONFIG_RELOAD = exports.OP_CONFIG_VALIDATE = exports.OP_IOCTL_SET = exports.OP_IOCTL_GET = exports.OP_SASL_STEP = exports.OP_SASL_AUTH = exports.OP_SASL_LIST_MECHS = exports.OP_HELO = exports.OP_GATQ = exports.OP_GAT = exports.OP_TOUCH = exports.OP_VERBOSITY = exports.OP_PREPENDQ = exports.OP_APPENDQ = exports.OP_FLUSHQ = exports.OP_QUITQ = exports.OP_DECREMENTQ = exports.OP_INCREMENTQ = exports.OP_DELETEQ = exports.OP_REPLACEQ = exports.OP_ADDQ = exports.OP_SETQ = exports.OP_STAT = exports.OP_PREPEND = exports.OP_APPEND = exports.OP_GETKQ = exports.OP_GETK = exports.OP_VERSION = exports.OP_NO_OP = exports.OP_GETQ = exports.OP_FLUSH = exports.OP_QUIT = exports.OP_DECREMENT = exports.OP_INCREMENT = exports.OP_DELETE = exports.OP_REPLACE = exports.OP_ADD = exports.OP_SET = exports.OP_GET = void 0; +exports.OP_RESET_REPLICATION_CHAIN = exports.OP_DEREGISTER_TAP_CLIENT = exports.OP_LAST_CLOSED_CHECKPOINT = exports.OP_UNLOCK_KEY = exports.OP_GET_LOCKED = exports.OP_EVICT_KEY = exports.OP_OBSERVE = exports.OP_OBSERVE_SEQNO = exports.OP_ASSUME_ROLE = exports.OP_SELECT_BUCKET = exports.OP_LIST_BUCKETS = exports.OP_DELETE_BUCKET = exports.OP_CREATE_BUCKET = exports.OP_GET_REPLICA = exports.OP_SET_PARAM = exports.OP_START_PERSISTENCE = exports.OP_STOP_PERSISTENCE = exports.OP_DCP_RESERVED4 = exports.OP_DCP_CONTROL = exports.OP_DCP_BUFFER_ACKNOWLEDGEMENT = exports.OP_DCP_NOOP = exports.OP_DCP_SET_VBUCKET_STATE = exports.OP_DCP_FLUSH = exports.OP_DCP_EXPIRATION = exports.OP_DCP_DELETION = exports.OP_DCP_MUTATION = exports.OP_DCP_SNAPSHOT_MARKER = exports.OP_DCP_STREAM_END = exports.OP_DCP_GET_FAILOVER_LOG = exports.OP_DCP_STREAM_REQ = exports.OP_DCP_CLOSE_STREAM = exports.OP_DCP_ADD_STREAM = exports.OP_DCP_OPEN = exports.OP_GET_ALL_VB_SEQNOS = exports.OP_TAP_CHECKPOINT_END = exports.OP_TAP_CHECKOUT_START = exports.OP_TAP_VBUCKET_SET = exports.OP_TAP_OPAQUE = exports.OP_TAP_FLUSH = exports.OP_TAP_DELETE = exports.OP_TAP_MUTATION = exports.OP_TAP_CONNECT = exports.OP_DEL_VBUCKET = exports.OP_GET_VBUCKET = exports.OP_SET_VBUCKET = exports.OP_RDECRQ = exports.OP_RDECR = exports.OP_RINCRQ = exports.OP_RINCR = exports.OP_RDELETEQ = void 0; +exports.responseStatusToString = exports.ResponseStatus = exports.OP_INIT_COMPLETE = exports.OP_GET_CTRL_TOKEN = exports.OP_SET_CTRL_TOKEN = exports.OP_GET_CMD_TIMER = exports.OP_SSL_CERTS_REFRESH = exports.OP_ISASL_REFRESH = exports.OP_SCRUB = exports.OP_SUBDOC_GET_COUNT = exports.OP_SUBDOC_MULTI_MUTATION = exports.OP_SUBDOC_MULTI_LOOKUP = exports.OP_SUBDOC_COUNTER = exports.OP_SUBDOC_ARRAY_ADD_UNIQUE = exports.OP_SUBDOC_ARRAY_INSERT = exports.OP_SUBDOC_ARRAY_PUSH_FIRST = exports.OP_SUBDOC_ARRAY_PUSH_LAST = exports.OP_SUBDOC_REPLACE = exports.OP_SUBDOC_DELETE = exports.OP_SUBDOC_DICT_UPSERT = exports.OP_SUBDOC_DICT_ADD = exports.OP_SUBDOC_EXISTS = exports.OP_SUBDOC_GET = exports.OP_GET_ADJUSTED_TIME = exports.OP_SET_DRIFT_COUNTER_STATE = exports.OP_GET_KEYS = exports.OP_SEQNO_PERSISTENCE = exports.OP_GET_RANDOM_KEY = exports.OP_GET_CLUSTER_CONFIG = exports.OP_SET_CLUSTER_CONFIG = exports.OP_COMPACT_DB = exports.OP_RETURN_META = exports.OP_CHECKPOINT_PERSISTENCE = exports.OP_CHANGE_VB_FILTER = exports.OP_DISABLE_TRAFFIC = exports.OP_ENABLE_TRAFFIC = exports.OP_NOTIFY_VBUCKET_UPDATE = exports.OP_CREATE_CHECKPOINT = exports.OP_DELQ_WITH_META = exports.OP_DEL_WITH_META = exports.OP_VBUCKET_BATCH_COUNT = exports.OP_SNAPSHOT_VB_STATES = exports.OP_ADDQ_WITH_META = exports.OP_ADD_WITH_META = exports.OP_SETQ_WITH_META = exports.OP_SET_WITH_META = exports.OP_GETQ_META = exports.OP_GET_META = void 0; +exports.OP_GET = 0x00; +exports.OP_SET = 0x01; +exports.OP_ADD = 0x02; +exports.OP_REPLACE = 0x03; +exports.OP_DELETE = 0x04; +exports.OP_INCREMENT = 0x05; +exports.OP_DECREMENT = 0x06; +exports.OP_QUIT = 0x07; +exports.OP_FLUSH = 0x08; +exports.OP_GETQ = 0x09; +exports.OP_NO_OP = 0x0a; +exports.OP_VERSION = 0x0b; +exports.OP_GETK = 0x0c; +exports.OP_GETKQ = 0x0d; +exports.OP_APPEND = 0x0e; +exports.OP_PREPEND = 0x0f; +exports.OP_STAT = 0x10; +exports.OP_SETQ = 0x11; +exports.OP_ADDQ = 0x12; +exports.OP_REPLACEQ = 0x13; +exports.OP_DELETEQ = 0x14; +exports.OP_INCREMENTQ = 0x15; +exports.OP_DECREMENTQ = 0x16; +exports.OP_QUITQ = 0x17; +exports.OP_FLUSHQ = 0x18; +exports.OP_APPENDQ = 0x19; +exports.OP_PREPENDQ = 0x1a; +exports.OP_VERBOSITY = 0x1b; +exports.OP_TOUCH = 0x1c; +exports.OP_GAT = 0x1d; +exports.OP_GATQ = 0x1e; +exports.OP_HELO = 0x1f; +exports.OP_SASL_LIST_MECHS = 0x20; +exports.OP_SASL_AUTH = 0x21; +exports.OP_SASL_STEP = 0x22; +exports.OP_IOCTL_GET = 0x23; +exports.OP_IOCTL_SET = 0x24; +exports.OP_CONFIG_VALIDATE = 0x25; +exports.OP_CONFIG_RELOAD = 0x26; +exports.OP_AUDIT_PUT = 0x27; +exports.OP_AUDIT_CONFIG_RELOAD = 0x28; +exports.OP_SHUTDOWN = 0x29; +exports.OP_RGET = 0x30; +exports.OP_RSET = 0x31; +exports.OP_RSETQ = 0x32; +exports.OP_RAPPEND = 0x33; +exports.OP_RAPPENDQ = 0x34; +exports.OP_RPREPEND = 0x35; +exports.OP_RPREPENDQ = 0x36; +exports.OP_RDELETE = 0x37; +exports.OP_RDELETEQ = 0x38; +exports.OP_RINCR = 0x39; +exports.OP_RINCRQ = 0x3a; +exports.OP_RDECR = 0x3b; +exports.OP_RDECRQ = 0x3c; +exports.OP_SET_VBUCKET = 0x3d; +exports.OP_GET_VBUCKET = 0x3e; +exports.OP_DEL_VBUCKET = 0x3f; +exports.OP_TAP_CONNECT = 0x40; +exports.OP_TAP_MUTATION = 0x41; +exports.OP_TAP_DELETE = 0x42; +exports.OP_TAP_FLUSH = 0x43; +exports.OP_TAP_OPAQUE = 0x44; +exports.OP_TAP_VBUCKET_SET = 0x45; +exports.OP_TAP_CHECKOUT_START = 0x46; +exports.OP_TAP_CHECKPOINT_END = 0x47; +exports.OP_GET_ALL_VB_SEQNOS = 0x48; +exports.OP_DCP_OPEN = 0x50; +exports.OP_DCP_ADD_STREAM = 0x51; +exports.OP_DCP_CLOSE_STREAM = 0x52; +exports.OP_DCP_STREAM_REQ = 0x53; +exports.OP_DCP_GET_FAILOVER_LOG = 0x54; +exports.OP_DCP_STREAM_END = 0x55; +exports.OP_DCP_SNAPSHOT_MARKER = 0x56; +exports.OP_DCP_MUTATION = 0x57; +exports.OP_DCP_DELETION = 0x58; +exports.OP_DCP_EXPIRATION = 0x59; +exports.OP_DCP_FLUSH = 0x5a; +exports.OP_DCP_SET_VBUCKET_STATE = 0x5b; +exports.OP_DCP_NOOP = 0x5c; +exports.OP_DCP_BUFFER_ACKNOWLEDGEMENT = 0x5d; +exports.OP_DCP_CONTROL = 0x5e; +exports.OP_DCP_RESERVED4 = 0x5f; +exports.OP_STOP_PERSISTENCE = 0x80; +exports.OP_START_PERSISTENCE = 0x81; +exports.OP_SET_PARAM = 0x82; +exports.OP_GET_REPLICA = 0x83; +exports.OP_CREATE_BUCKET = 0x85; +exports.OP_DELETE_BUCKET = 0x86; +exports.OP_LIST_BUCKETS = 0x87; +exports.OP_SELECT_BUCKET = 0x89; +exports.OP_ASSUME_ROLE = 0x8a; +exports.OP_OBSERVE_SEQNO = 0x91; +exports.OP_OBSERVE = 0x92; +exports.OP_EVICT_KEY = 0x93; +exports.OP_GET_LOCKED = 0x94; +exports.OP_UNLOCK_KEY = 0x95; +exports.OP_LAST_CLOSED_CHECKPOINT = 0x97; +exports.OP_DEREGISTER_TAP_CLIENT = 0x9e; +exports.OP_RESET_REPLICATION_CHAIN = 0x9f; +exports.OP_GET_META = 0xa0; +exports.OP_GETQ_META = 0xa1; +exports.OP_SET_WITH_META = 0xa2; +exports.OP_SETQ_WITH_META = 0xa3; +exports.OP_ADD_WITH_META = 0xa4; +exports.OP_ADDQ_WITH_META = 0xa5; +exports.OP_SNAPSHOT_VB_STATES = 0xa6; +exports.OP_VBUCKET_BATCH_COUNT = 0xa7; +exports.OP_DEL_WITH_META = 0xa8; +exports.OP_DELQ_WITH_META = 0xa9; +exports.OP_CREATE_CHECKPOINT = 0xaa; +exports.OP_NOTIFY_VBUCKET_UPDATE = 0xac; +exports.OP_ENABLE_TRAFFIC = 0xad; +exports.OP_DISABLE_TRAFFIC = 0xae; +exports.OP_CHANGE_VB_FILTER = 0xb0; +exports.OP_CHECKPOINT_PERSISTENCE = 0xb1; +exports.OP_RETURN_META = 0xb2; +exports.OP_COMPACT_DB = 0xb3; +exports.OP_SET_CLUSTER_CONFIG = 0xb4; +exports.OP_GET_CLUSTER_CONFIG = 0xb5; +exports.OP_GET_RANDOM_KEY = 0xb6; +exports.OP_SEQNO_PERSISTENCE = 0xb7; +exports.OP_GET_KEYS = 0xb8; +exports.OP_SET_DRIFT_COUNTER_STATE = 0xc1; +exports.OP_GET_ADJUSTED_TIME = 0xc2; +exports.OP_SUBDOC_GET = 0xc5; +exports.OP_SUBDOC_EXISTS = 0xc6; +exports.OP_SUBDOC_DICT_ADD = 0xc7; +exports.OP_SUBDOC_DICT_UPSERT = 0xc8; +exports.OP_SUBDOC_DELETE = 0xc9; +exports.OP_SUBDOC_REPLACE = 0xca; +exports.OP_SUBDOC_ARRAY_PUSH_LAST = 0xcb; +exports.OP_SUBDOC_ARRAY_PUSH_FIRST = 0xcc; +exports.OP_SUBDOC_ARRAY_INSERT = 0xcd; +exports.OP_SUBDOC_ARRAY_ADD_UNIQUE = 0xce; +exports.OP_SUBDOC_COUNTER = 0xcf; +exports.OP_SUBDOC_MULTI_LOOKUP = 0xd0; +exports.OP_SUBDOC_MULTI_MUTATION = 0xd1; +exports.OP_SUBDOC_GET_COUNT = 0xd2; +exports.OP_SCRUB = 0xf0; +exports.OP_ISASL_REFRESH = 0xf1; +exports.OP_SSL_CERTS_REFRESH = 0xf2; +exports.OP_GET_CMD_TIMER = 0xf3; +exports.OP_SET_CTRL_TOKEN = 0xf4; +exports.OP_GET_CTRL_TOKEN = 0xf5; +exports.OP_INIT_COMPLETE = 0xf6; +/** + * Response statuses + * https://github.com/memcached/memcached/wiki/BinaryProtocolRevamped#response-status + */ +exports.ResponseStatus = { + /** Named "No error" in the memcached docs, but clearer in code as "SUCCESS". */ + SUCCESS: 0x0000, + KEY_NOT_FOUND: 0x0001, + KEY_EXISTS: 0x0002, + VALUE_TOO_LARGE: 0x0003, + INVALID_ARGUMENTS: 0x0004, + ITEM_NOT_STORED: 0x0005, + INCR_DECR_ON_NON_NUMERIC_VALUE: 0x0006, + THE_VBUCKET_BELONGS_TO_ANOTHER_SERVER: 0x0007, + AUTHENTICATION_ERROR: 0x0008, + AUTHENTICATION_CONTINUE: 0x0009, + UNKNOWN_COMMAND: 0x0081, + OUT_OF_MEMORY: 0x0082, + NOT_SUPPORTED: 0x0083, + INTERNAL_ERROR: 0x0084, + BUSY: 0x0085, + TEMPORARY_FAILURE: 0x0086, +}; +function responseStatusToString(responseStatus) { + switch (responseStatus) { + case 0x0000: + return "No error"; + case 0x0001: + return "Key not found"; + case 0x0002: + return "Key exists"; + case 0x0003: + return "Value too large"; + case 0x0004: + return "Invalid arguments"; + case 0x0005: + return "Item not stored"; + case 0x0006: + return "Incr/Decr on non-numeric value"; + case 0x0007: + return "The vbucket belongs to another server"; + case 0x0008: + return "Authentication error"; + case 0x0009: + return "Authentication continue"; + case 0x0081: + return "Unknown command"; + case 0x0082: + return "Out of memory"; + case 0x0083: + return "Not supported"; + case 0x0084: + return "Internal error"; + case 0x0085: + return "Busy"; + case 0x0086: + return "Temporary failure"; + default: + return `Unknown response status ${responseStatus}`; + } +} +exports.responseStatusToString = responseStatusToString; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uc3RhbnRzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL21lbWpzL2NvbnN0YW50cy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7O0VBS0U7Ozs7O0FBRVcsUUFBQSxNQUFNLEdBQUcsSUFBSSxDQUFDO0FBQ2QsUUFBQSxNQUFNLEdBQUcsSUFBSSxDQUFDO0FBQ2QsUUFBQSxNQUFNLEdBQUcsSUFBSSxDQUFDO0FBQ2QsUUFBQSxVQUFVLEdBQUcsSUFBSSxDQUFDO0FBQ2xCLFFBQUEsU0FBUyxHQUFHLElBQUksQ0FBQztBQUNqQixRQUFBLFlBQVksR0FBRyxJQUFJLENBQUM7QUFDcEIsUUFBQSxZQUFZLEdBQUcsSUFBSSxDQUFDO0FBQ3BCLFFBQUEsT0FBTyxHQUFHLElBQUksQ0FBQztBQUNmLFFBQUEsUUFBUSxHQUFHLElBQUksQ0FBQztBQUNoQixRQUFBLE9BQU8sR0FBRyxJQUFJLENBQUM7QUFDZixRQUFBLFFBQVEsR0FBRyxJQUFJLENBQUM7QUFDaEIsUUFBQSxVQUFVLEdBQUcsSUFBSSxDQUFDO0FBQ2xCLFFBQUEsT0FBTyxHQUFHLElBQUksQ0FBQztBQUNmLFFBQUEsUUFBUSxHQUFHLElBQUksQ0FBQztBQUNoQixRQUFBLFNBQVMsR0FBRyxJQUFJLENBQUM7QUFDakIsUUFBQSxVQUFVLEdBQUcsSUFBSSxDQUFDO0FBQ2xCLFFBQUEsT0FBTyxHQUFHLElBQUksQ0FBQztBQUNmLFFBQUEsT0FBTyxHQUFHLElBQUksQ0FBQztBQUNmLFFBQUEsT0FBTyxHQUFHLElBQUksQ0FBQztBQUNmLFFBQUEsV0FBVyxHQUFHLElBQUksQ0FBQztBQUNuQixRQUFBLFVBQVUsR0FBRyxJQUFJLENBQUM7QUFDbEIsUUFBQSxhQUFhLEdBQUcsSUFBSSxDQUFDO0FBQ3JCLFFBQUEsYUFBYSxHQUFHLElBQUksQ0FBQztBQUNyQixRQUFBLFFBQVEsR0FBRyxJQUFJLENBQUM7QUFDaEIsUUFBQSxTQUFTLEdBQUcsSUFBSSxDQUFD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LE9BQU8sbUJBQW1CLENBQUM7UUFDN0IsS0FBSyxNQUFNO1lBQ1QsT0FBTyxpQkFBaUIsQ0FBQztRQUMzQixLQUFLLE1BQU07WUFDVCxPQUFPLGdDQUFnQyxDQUFDO1FBQzFDLEtBQUssTUFBTTtZQUNULE9BQU8sdUNBQXVDLENBQUM7UUFDakQsS0FBSyxNQUFNO1lBQ1QsT0FBTyxzQkFBc0IsQ0FBQztRQUNoQyxLQUFLLE1BQU07WUFDVCxPQUFPLHlCQUF5QixDQUFDO1FBQ25DLEtBQUssTUFBTTtZQUNULE9BQU8saUJBQWlCLENBQUM7UUFDM0IsS0FBSyxNQUFNO1lBQ1QsT0FBTyxlQUFlLENBQUM7UUFDekIsS0FBSyxNQUFNO1lBQ1QsT0FBTyxlQUFlLENBQUM7UUFDekIsS0FBSyxNQUFNO1lBQ1QsT0FBTyxnQkFBZ0IsQ0FBQztRQUMxQixLQUFLLE1BQU07WUFDVCxPQUFPLE1BQU0sQ0FBQztRQUNoQixLQUFLLE1BQU07WUFDVCxPQUFPLG1CQUFtQixDQUFDO1FBQzdCO1lBQ0UsT0FBTywyQkFBMkIsY0FBYyxFQUFFLENBQUM7S0FDdEQ7QUFDSCxDQUFDO0FBdkNELHdEQXVDQyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG5Db25zdGFudHMgZnJvbSBtZW1jYWNoZWQgYmluYXJ5IHByb3RvY29sIGRvY3Ncbmh0dHBzOi8vZ2l0aHViLmNvbS9jb3VjaGJhc2UvbWVtY2FjaGVkL2Jsb2IvbWFzdGVyL2RvY3MvQmluYXJ5UHJvdG9jb2wubWQjMHgwZC1nZXRrcS1nZXQtd2l0aC1rZXktcXVpZXRseVxuXG5Ob3RlOiBub3QgYWxsIGNvbnN0YW50cyBpbiBoZXJlIGFyZSBpbXBsZW1lbnRlZCBpbiB0aGlzIGxpYnJhcnksIG5vdCBhbGwgY29uc3RhbnRzIGZyb20gdGhlIGRvY3MgYXJlIGluY2x1ZGVkIGhlcmVcbiovXG5cbmV4cG9ydCBjb25zdCBPUF9HRVQgPSAweDAwO1xuZXhwb3J0IGNvbnN0IE9QX1NFVCA9IDB4MDE7XG5leHBvcnQgY29uc3QgT1BfQUREID0gMHgwMjtcbmV4cG9ydCBjb25zdCBPUF9SRVBMQUNFID0gMHgwMztcbmV4cG9ydCBjb25zdCBPUF9ERUxFVEUgPSAweDA0O1xuZXhwb3J0IGNvbnN0IE9QX0lOQ1JFTUVOVCA9IDB4MDU7XG5leHBvcnQgY29uc3QgT1BfREVDUkVNRU5UID0gMHgwNjtcbmV4cG9ydCBjb25zdCBPUF9RVUlUID0gMHgwNztcbmV4cG9ydCBjb25zdCBPUF9GTFVTSCA9IDB4MDg7XG5leHBvcnQgY29uc3QgT1BfR0VUUSA9IDB4MDk7XG5leHBvcnQgY29uc3QgT1BfTk9fT1AgPSAweDBhO1xuZXhwb3J0IGNvbnN0IE9QX1ZFUlNJT04gPSAweDBiO1xuZXhwb3J0IGNvbnN0IE9QX0dFVEsgPSAweDBjO1xuZXhwb3J0IGNvbnN0IE9QX0dFVEtRID0gMHgwZDtcbmV4cG9ydCBjb25zdCBPUF9BUFBFTkQgPSAweDBlO1xuZXhwb3J0IGNvbnN0IE9QX1BSRVBFTkQgPSAweDBmO1xuZXhwb3J0IGNvbnN0IE9QX1NUQVQgPSAweDEwO1xuZXhwb3J0IGNvbnN0IE9QX1NFVFEgPSAweDExO1xuZXhwb3J0IGNvbnN0IE9QX0FERFEgPSAweDEyO1xuZXhwb3J0IGNvbnN0IE9QX1JFUExBQ0VRID0gMHgxMztcbmV4cG9ydCBjb25zdCBPUF9ERUxFVEVRID0gMHgxNDtcbmV4cG9ydCBjb25zdCBPUF9JTkNSRU1FTlRRID0gMHgxNTtcbmV4cG9ydCBjb25zdCBPUF9ERUNSRU1FTlRRID0gMHgxNjtcbmV4cG9ydCBjb25zdCBPUF9RVUlUUSA9IDB4MTc7XG5leHBvcnQgY29uc3QgT1BfRkxVU0hRID0gMHgxODtcbmV4cG9ydCBjb25zdCBPUF9BUFBFTkRRID0gMHgxOTtcbmV4cG9ydCBjb25zdCBPUF9QUkVQRU5EUSA9IDB4MWE7XG5leHBvcnQgY29uc3QgT1BfVkVSQk9TSVRZID0gMHgxYjtcbmV4cG9ydCBjb25zdCBPUF9UT1VDSCA9IDB4MWM7XG5leHBvcnQgY29uc3QgT1BfR0FUID0gMHgxZDtcbmV4cG9ydCBjb25zdCBPUF9HQVRRID0gMHgxZTtcbmV4cG9ydCBjb25zdCBPUF9IRUxPID0gMHgxZjtcbmV4cG9ydCBjb25zdCBPUF9TQVNMX0xJU1RfTUVDSFMgPSAweDIwO1xuZXhwb3J0IGNvbnN0IE9QX1NBU0xfQVVUSCA9IDB4MjE7XG5leHBvcnQgY29uc3QgT1BfU0FTTF9TVEVQID0gMHgyMjtcbmV4cG9ydCBjb25zdCBPUF9JT0NUTF9HRVQgPSAweDIzO1xuZXhwb3J0IGNvbnN0IE9QX0lPQ1RMX1NFVCA9IDB4MjQ7XG5leHBvcnQgY29uc3QgT1BfQ09ORklHX1ZBTElEQVRFID0gMHgyNTtcbmV4cG9ydCBjb25zdCBPUF9DT05GSUdfUkVMT0FEID0gMHgyNjtcbmV4cG9ydCBjb25zdCBPUF9BVURJVF9QVVQgPSAweDI3O1xuZXhwb3J0IGNvbnN0IE9QX0FVRElUX0NPTkZJR19SRUxPQUQgPSAweDI4O1xuZXhwb3J0IGNvbnN0IE9QX1NIVVRET1dOID0gMHgyOTtcbmV4cG9ydCBjb25zdCBPUF9SR0VUID0gMHgzMDtcbmV4cG9ydCBjb25zdCBPUF9SU0VUID0gMHgzMTtcbmV4cG9ydCBjb25zdCBPUF9SU0VUUSA9IDB4MzI7XG5leHBvcnQgY29uc3QgT1BfUkFQUEVORCA9IDB4MzM7XG5leHBvcnQgY29uc3QgT1BfUkFQUEVORFEgPSAweDM0O1xuZXhwb3J0IGNvbnN0IE9QX1JQUkVQRU5EID0gMHgzNTtcbmV4cG9ydCBjb25zdCBPUF9SUFJFUEVORFEgPSAweDM2O1xuZXhwb3J0IGNvbnN0IE9QX1JERUxFVEUgPSAweDM3O1xuZXhwb3J0IGNvbnN0IE9QX1JERUxFVEVRID0gMHgzODtcbmV4cG9ydCBjb25zdCBPUF9SSU5DUiA9IDB4Mzk7XG5leHBvcnQgY29uc3QgT1BfUklOQ1JRID0gMHgzYTtcbmV4cG9ydCBjb25zdCBPUF9SREVDUiA9IDB4M2I7XG5leHBvcnQgY29uc3QgT1BfUkRFQ1JRID0gMHgzYztcbmV4cG9ydCBjb25zdCBPUF9TRVRfVkJVQ0tFVCA9IDB4M2Q7XG5leHBvcnQgY29uc3QgT1BfR0VUX1ZCVUNLRVQgPSAweDNlO1xuZXhwb3J0IGNvbnN0IE9QX0RFTF9WQlVDS0VUID0gMHgzZjtcbmV4cG9ydCBjb25zdCBPUF9UQVBfQ09OTkVDVCA9IDB4NDA7XG5leHBvcnQgY29uc3QgT1BfVEFQX01VVEFUSU9OID0gMHg0MTtcbmV4cG9ydCBjb25zdCBPUF9UQVBfREVMRVRFID0gMHg0MjtcbmV4cG9ydCBjb25zdCBPUF9UQVBfRkxVU0ggPSAweDQzO1xuZXhwb3J0IGNvbnN0IE9QX1RBUF9PUEFRVUUgPSAweDQ0O1xuZXhwb3J0IGNvbnN0IE9QX1RBUF9WQlVDS0VUX1NFVCA9IDB4NDU7XG5leHBvcnQgY29uc3QgT1BfVEFQX0NIRUNLT1VUX1NUQVJUID0gMHg0NjtcbmV4cG9ydCBjb25zdCBPUF9UQVBfQ0hFQ0tQT0lOVF9FTkQgPSAweDQ3O1xuZXhwb3J0IGNvbnN0IE9QX0dFVF9BTExfVkJfU0VRTk9TID0gMHg0ODtcbmV4cG9ydCBjb25zdCBPUF9EQ1BfT1BFTiA9IDB4NTA7XG5leHBvcnQgY29uc3QgT1BfRENQX0FERF9TVFJFQU0gPSAweDUxO1xuZXhwb3J0IGNvbnN0IE9QX0RDUF9DTE9TRV9TVFJFQU0gPSAweDUyO1xuZXhwb3J0IGNvbnN0IE9QX0RDUF9TVFJFQU1fUkVRID0gMHg1MztcbmV4cG9ydCBjb25zdCBPUF9EQ1BfR0VUX0ZBSUxPVkVSX0xPRyA9IDB4NTQ7XG5leHBvcnQgY29uc3QgT1BfRENQX1NUUkVBTV9FTkQgPSAweDU1O1xuZXhwb3J0IGNvbnN0IE9QX0RDUF9TTkFQU0hPVF9NQVJLRVIgPSAweDU2O1xuZXhwb3J0IGNvbnN0IE9QX0RDUF9NVVRBVElPTiA9IDB4NTc7XG5leHBvcnQgY29uc3QgT1BfRENQX0RFTEVUSU9OID0gMHg1ODtcbmV4cG9ydCBjb25zdCBPUF9EQ1BfRVhQSVJBVElPTiA9IDB4NTk7XG5leHBvcnQgY29uc3QgT1BfRENQX0ZMVVNIID0gMHg1YTtcbmV4cG9ydCBjb25zdCBPUF9EQ1BfU0VUX1ZCVUNLRVRfU1RBVEUgPSAweDViO1xuZXhwb3J0IGNvbnN0IE9QX0RDUF9OT09QID0gMHg1YztcbmV4cG9ydCBjb25zdCBPUF9EQ1BfQlVGRkVSX0FDS05PV0xFREdFTUVOVCA9IDB4NWQ7XG5leHBvcnQgY29uc3QgT1BfRENQX0NPTlRST0wgPSAweDVlO1xuZXhwb3J0IGNvbnN0IE9QX0RDUF9SRVNFUlZFRDQgPSAweDVmO1xuZXhwb3J0IGNvbnN0IE9QX1NUT1BfUEVSU0lTVEVOQ0UgPSAweDgwO1xuZXhwb3J0IGNvbnN0IE9QX1NUQVJUX1BFUlNJU1RFTkNFID0gMHg4MTtcbmV4cG9ydCBjb25zdCBPUF9TRVRfUEFSQU0gPSAweDgyO1xuZXhwb3J0IGNvbnN0IE9QX0dFVF9SRVBMSUNBID0gMHg4MztcbmV4cG9ydCBjb25zdCBPUF9DUkVBVEVfQlVDS0VUID0gMHg4NTtcbmV4cG9ydCBjb25zdCBPUF9ERUxFVEVfQlVDS0VUID0gMHg4NjtcbmV4cG9ydCBjb25zdCBPUF9MSVNUX0JVQ0tFVFMgPSAweDg3O1xuZXhwb3J0IGNvbnN0IE9QX1NFTEVDVF9CVUNLRVQgPSAweDg5O1xuZXhwb3J0IGNvbnN0IE9QX0FTU1VNRV9ST0xFID0gMHg4YTtcbmV4cG9ydCBjb25zdCBPUF9PQlNFUlZFX1NFUU5PID0gMHg5MTtcbmV4cG9ydCBjb25zdCBPUF9PQlNFUlZFID0gMHg5MjtcbmV4cG9ydCBjb25zdCBPUF9FVklDVF9LRVkgPSAweDkzO1xuZXhwb3J0IGNvbnN0IE9QX0dFVF9MT0NLRUQgPSAweDk0O1xuZXhwb3J0IGNvbnN0IE9QX1VOTE9DS19LRVkgPSAweDk1O1xuZXhwb3J0IGNvbnN0IE9QX0xBU1RfQ0xPU0VEX0NIRUNLUE9JTlQgPSAweDk3O1xuZXhwb3J0IGNvbnN0IE9QX0RFUkVHSVNURVJfVEFQX0NMSUVOVCA9IDB4OWU7XG5leHBvcnQgY29uc3QgT1BfUkVTRVRfUkVQTElDQVRJT05fQ0hBSU4gPSAweDlmO1xuZXhwb3J0IGNvbnN0IE9QX0dFVF9NRVRBID0gMHhhMDtcbmV4cG9ydCBjb25zdCBPUF9HRVRRX01FVEEgPSAweGExO1xuZXhwb3J0IGNvbnN0IE9QX1NFVF9XSVRIX01FVEEgPSAweGEyO1xuZXhwb3J0IGNvbnN0IE9QX1NFVFFfV0lUSF9NRVRBID0gMHhhMztcbmV4cG9ydCBjb25zdCBPUF9BRERfV0lUSF9NRVRBID0gMHhhNDtcbmV4cG9ydCBjb25zdCBPUF9BRERRX1dJVEhfTUVUQSA9IDB4YTU7XG5leHBvcnQgY29uc3QgT1BfU05BUFNIT1RfVkJfU1RBVEVTID0gMHhhNjtcbmV4cG9ydCBjb25zdCBPUF9WQlVDS0VUX0JBVENIX0NPVU5UID0gMHhhNztcbmV4cG9ydCBjb25zdCBPUF9ERUxfV0lUSF9NRVRBID0gMHhhODtcbmV4cG9ydCBjb25zdCBPUF9ERUxRX1dJVEhfTUVUQSA9IDB4YTk7XG5leHBvcnQgY29uc3QgT1BfQ1JFQVRFX0NIRUNLUE9JTlQgPSAweGFhO1xuZXhwb3J0IGNvbnN0IE9QX05PVElGWV9WQlVDS0VUX1VQREFURSA9IDB4YWM7XG5leHBvcnQgY29uc3QgT1BfRU5BQkxFX1RSQUZGSUMgPSAweGFkO1xuZXhwb3J0IGNvbnN0IE9QX0RJU0FCTEVfVFJBRkZJQyA9IDB4YWU7XG5leHBvcnQgY29uc3QgT1BfQ0hBTkdFX1ZCX0ZJTFRFUiA9IDB4YjA7XG5leHBvcnQgY29uc3QgT1BfQ0hFQ0tQT0lOVF9QRVJTSVNURU5DRSA9IDB4YjE7XG5leHBvcnQgY29uc3QgT1BfUkVUVVJOX01FVEEgPSAweGIyO1xuZXhwb3J0IGNvbnN0IE9QX0NPTVBBQ1RfREIgPSAweGIzO1xuZXhwb3J0IGNvbnN0IE9QX1NFVF9DTFVTVEVSX0NPTkZJRyA9IDB4YjQ7XG5leHBvcnQgY29uc3QgT1BfR0VUX0NMVVNURVJfQ09ORklHID0gMHhiNTtcbmV4cG9ydCBjb25zdCBPUF9HRVRfUkFORE9NX0tFWSA9IDB4YjY7XG5leHBvcnQgY29uc3QgT1BfU0VRTk9fUEVSU0lTVEVOQ0UgPSAweGI3O1xuZXhwb3J0IGNvbnN0IE9QX0dFVF9LRVlTID0gMHhiODtcbmV4cG9ydCBjb25zdCBPUF9TRVRfRFJJRlRfQ09VTlRFUl9TVEFURSA9IDB4YzE7XG5leHBvcnQgY29uc3QgT1BfR0VUX0FESlVTVEVEX1RJTUUgPSAweGMyO1xuZXhwb3J0IGNvbnN0IE9QX1NVQkRPQ19HRVQgPSAweGM1O1xuZXhwb3J0IGNvbnN0IE9QX1NVQkRPQ19FWElTVFMgPSAweGM2O1xuZXhwb3J0IGNvbnN0IE9QX1NVQkRPQ19ESUNUX0FERCA9IDB4Yzc7XG5leHBvcnQgY29uc3QgT1BfU1VCRE9DX0RJQ1RfVVBTRVJUID0gMHhjODtcbmV4cG9ydCBjb25zdCBPUF9TVUJET0NfREVMRVRFID0gMHhjOTtcbmV4cG9ydCBjb25zdCBPUF9TVUJET0NfUkVQTEFDRSA9IDB4Y2E7XG5leHBvcnQgY29uc3QgT1BfU1VCRE9DX0FSUkFZX1BVU0hfTEFTVCA9IDB4Y2I7XG5leHBvcnQgY29uc3QgT1BfU1VCRE9DX0FSUkFZX1BVU0hfRklSU1QgPSAweGNjO1xuZXhwb3J0IGNvbnN0IE9QX1NVQkRPQ19BUlJBWV9JTlNFUlQgPSAweGNkO1xuZXhwb3J0IGNvbnN0IE9QX1NVQkRPQ19BUlJBWV9BRERfVU5JUVVFID0gMHhjZTtcbmV4cG9ydCBjb25zdCBPUF9TVUJET0NfQ09VTlRFUiA9IDB4Y2Y7XG5leHBvcnQgY29uc3QgT1BfU1VCRE9DX01VTFRJX0xPT0tVUCA9IDB4ZDA7XG5leHBvcnQgY29uc3QgT1BfU1VCRE9DX01VTFRJX01VVEFUSU9OID0gMHhkMTtcbmV4cG9ydCBjb25zdCBPUF9TVUJET0NfR0VUX0NPVU5UID0gMHhkMjtcbmV4cG9ydCBjb25zdCBPUF9TQ1JVQiA9IDB4ZjA7XG5leHBvcnQgY29uc3QgT1BfSVNBU0xfUkVGUkVTSCA9IDB4ZjE7XG5leHBvcnQgY29uc3QgT1BfU1NMX0NFUlRTX1JFRlJFU0ggPSAweGYyO1xuZXhwb3J0IGNvbnN0IE9QX0dFVF9DTURfVElNRVIgPSAweGYzO1xuZXhwb3J0IGNvbnN0IE9QX1NFVF9DVFJMX1RPS0VOID0gMHhmNDtcbmV4cG9ydCBjb25zdCBPUF9HRVRfQ1RSTF9UT0tFTiA9IDB4ZjU7XG5leHBvcnQgY29uc3QgT1BfSU5JVF9DT01QTEVURSA9IDB4ZjY7XG5cbmV4cG9ydCB0eXBlIE9QID1cbiAgfCB0eXBlb2YgT1BfR0VUXG4gIHwgdHlwZW9mIE9QX1NFVFxuICB8IHR5cGVvZiBPUF9BRERcbiAgfCB0eXBlb2YgT1BfUkVQTEFDRVxuICB8IHR5cGVvZiBPUF9ERUxFVEVcbiAgfCB0eXBlb2YgT1BfSU5DUkVNRU5UXG4gIHwgdHlwZW9mIE9QX0RFQ1JFTUVOVFxuICB8IHR5cGVvZiBPUF9RVUlUXG4gIHwgdHlwZW9mIE9QX0ZMVVNIXG4gIHwgdHlwZW9mIE9QX0dFVFFcbiAgfCB0eXBlb2YgT1BfTk9fT1BcbiAgfCB0eXBlb2YgT1BfVkVSU0lPTlxuICB8IHR5cGVvZiBPUF9HRVRLXG4gIHwgdHlwZW9mIE9QX0dFVEtRXG4gIHwgdHlwZW9mIE9QX0FQUEVORFxuICB8IHR5cGVvZiBPUF9QUkVQRU5EXG4gIHwgdHlwZW9mIE9QX1NUQVRcbiAgfCB0eXBlb2YgT1BfU0VUUVxuICB8IHR5cGVvZiBPUF9BRERRXG4gIHwgdHlwZW9mIE9QX1JFUExBQ0VRXG4gIHwgdHlwZW9mIE9QX0RFTEVURVFcbiAgfCB0eXBlb2YgT1BfSU5DUkVNRU5UUVxuICB8IHR5cGVvZiBPUF9ERUNSRU1FTlRRXG4gIHwgdHlwZW9mIE9QX1FVSVRRXG4gIHwgdHlwZW9mIE9QX0ZMVVNIUVxuICB8IHR5cGVvZiBPUF9BUFBFTkRRXG4gIHwgdHlwZW9mIE9QX1BSRVBFTkRRXG4gIHwgdHlwZW9mIE9QX1ZFUkJPU0lUWVxuICB8IHR5cGVvZiBPUF9UT1VDSFxuICB8IHR5cGVvZiBPUF9HQVRcbiAgfCB0eXBlb2YgT1BfR0FUUVxuICB8IHR5cGVvZiBPUF9IRUxPXG4gIHwgdHlwZW9mIE9QX1NBU0xfTElTVF9NRUNIU1xuICB8IHR5cGVvZiBPUF9TQVNMX0FVVEhcbiAgfCB0eXBlb2YgT1BfU0FTTF9TVEVQXG4gIHwgdHlwZW9mIE9QX0lPQ1RMX0dFVFxuICB8IHR5cGVvZiBPUF9JT0NUTF9TRVRcbiAgfCB0eXBlb2YgT1BfQ09ORklHX1ZBTElEQVRFXG4gIHwgdHlwZW9mIE9QX0NPTkZJR19SRUxPQURcbiAgfCB0eXBlb2YgT1BfQVVESVRfUFVUXG4gIHwgdHlwZW9mIE9QX0FVRElUX0NPTkZJR19SRUxPQURcbiAgfCB0eXBlb2YgT1BfU0hVVERPV05cbiAgfCB0eXBlb2YgT1BfUkdFVFxuICB8IHR5cGVvZiBPUF9SU0VUXG4gIHwgdHlwZW9mIE9QX1JTRVRRXG4gIHwgdHlwZW9mIE9QX1JBUFBFTkRcbiAgfCB0eXBlb2YgT1BfUkFQUEVORFFcbiAgfCB0eXBlb2YgT1BfUlBSRVBFTkRcbiAgfCB0eXBlb2YgT1BfUlBSRVBFTkRRXG4gIHwgdHlwZW9mIE9QX1JERUxFVEVcbiAgfCB0eXBlb2YgT1BfUkRFTEVURVFcbiAgfCB0eXBlb2YgT1BfUklOQ1JcbiAgfCB0eXBlb2YgT1BfUklOQ1JRXG4gIHwgdHlwZW9mIE9QX1JERUNSXG4gIHwgdHlwZW9mIE9QX1JERUNSUVxuICB8IHR5cGVvZiBPUF9TRVRfVkJVQ0tFVFxuICB8IHR5cGVvZiBPUF9HRVRfVkJVQ0tFVFxuICB8IHR5cGVvZiBPUF9ERUxfVkJVQ0tFVFxuICB8IHR5cGVvZiBPUF9UQVBfQ09OTkVDVFxuICB8IHR5cGVvZiBPUF9UQVBfTVVUQVRJT05cbiAgfCB0eXBlb2YgT1BfVEFQX0RFTEVURVxuICB8IHR5cGVvZiBPUF9UQVBfRkxVU0hcbiAgfCB0eXBlb2YgT1BfVEFQX09QQVFVRVxuICB8IHR5cGVvZiBPUF9UQVBfVkJVQ0tFVF9TRVRcbiAgfCB0eXBlb2YgT1BfVEFQX0NIRUNLT1VUX1NUQVJUXG4gIHwgdHlwZW9mIE9QX1RBUF9DSEVDS1BPSU5UX0VORFxuICB8IHR5cGVvZiBPUF9HRVRfQUxMX1ZCX1NFUU5PU1xuICB8IHR5cGVvZiBPUF9EQ1BfT1BFTlxuICB8IHR5cGVvZiBPUF9EQ1BfQUREX1NUUkVBTVxuICB8IHR5cGVvZiBPUF9EQ1BfQ0xPU0VfU1RSRUFNXG4gIHwgdHlwZW9mIE9QX0RDUF9TVFJFQU1fUkVRXG4gIHwgdHlwZW9mIE9QX0RDUF9HRVRfRkFJTE9WRVJfTE9HXG4gIHwgdHlwZW9mIE9QX0RDUF9TVFJFQU1fRU5EXG4gIHwgdHlwZW9mIE9QX0RDUF9TTkFQU0hPVF9NQVJLRVJcbiAgfCB0eXBlb2YgT1BfRENQX01VVEFUSU9OXG4gIHwgdHlwZW9mIE9QX0RDUF9ERUxFVElPTlxuICB8IHR5cGVvZiBPUF9EQ1BfRVhQSVJBVElPTlxuICB8IHR5cGVvZiBPUF9EQ1BfRkxVU0hcbiAgfCB0eXBlb2YgT1BfRENQX1NFVF9WQlVDS0VUX1NUQVRFXG4gIHwgdHlwZW9mIE9QX0RDUF9OT09QXG4gIHwgdHlwZW9mIE9QX0RDUF9CVUZGRVJfQUNLTk9XTEVER0VNRU5UXG4gIHwgdHlwZW9mIE9QX0RDUF9DT05UUk9MXG4gIHwgdHlwZW9mIE9QX0RDUF9SRVNFUlZFRDRcbiAgfCB0eXBlb2YgT1BfU1RPUF9QRVJTSVNURU5DRVxuICB8IHR5cGVvZiBPUF9TVEFSVF9QRVJTSVNURU5DRVxuICB8IHR5cGVvZiBPUF9TRVRfUEFSQU1cbiAgfCB0eXBlb2YgT1BfR0VUX1JFUExJQ0FcbiAgfCB0eXBlb2YgT1BfQ1JFQVRFX0JVQ0tFVFxuICB8IHR5cGVvZiBPUF9ERUxFVEVfQlVDS0VUXG4gIHwgdHlwZW9mIE9QX0xJU1RfQlVDS0VUU1xuICB8IHR5cGVvZiBPUF9TRUxFQ1RfQlVDS0VUXG4gIHwgdHlwZW9mIE9QX0FTU1VNRV9ST0xFXG4gIHwgdHlwZW9mIE9QX09CU0VSVkVfU0VRTk9cbiAgfCB0eXBlb2YgT1BfT0JTRVJWRVxuICB8IHR5cGVvZiBPUF9FVklDVF9LRVlcbiAgfCB0eXBlb2YgT1BfR0VUX0xPQ0tFRFxuICB8IHR5cGVvZiBPUF9VTkxPQ0tfS0VZXG4gIHwgdHlwZW9mIE9QX0xBU1RfQ0xPU0VEX0NIRUNLUE9JTlRcbiAgfCB0eXBlb2YgT1BfREVSRUdJU1RFUl9UQVBfQ0xJRU5UXG4gIHwgdHlwZW9mIE9QX1JFU0VUX1JFUExJQ0FUSU9OX0NIQUlOXG4gIHwgdHlwZW9mIE9QX0dFVF9NRVRBXG4gIHwgdHlwZW9mIE9QX0dFVFFfTUVUQVxuICB8IHR5cGVvZiBPUF9TRVRfV0lUSF9NRVRBXG4gIHwgdHlwZW9mIE9QX1NFVFFfV0lUSF9NRVRBXG4gIHwgdHlwZW9mIE9QX0FERF9XSVRIX01FVEFcbiAgfCB0eXBlb2YgT1BfQUREUV9XSVRIX01FVEFcbiAgfCB0eXBlb2YgT1BfU05BUFNIT1RfVkJfU1RBVEVTXG4gIHwgdHlwZW9mIE9QX1ZCVUNLRVRfQkFUQ0hfQ09VTlRcbiAgfCB0eXBlb2YgT1BfREVMX1dJVEhfTUVUQVxuICB8IHR5cGVvZiBPUF9ERUxRX1dJVEhfTUVUQVxuICB8IHR5cGVvZiBPUF9DUkVBVEVfQ0hFQ0tQT0lOVFxuICB8IHR5cGVvZiBPUF9OT1RJRllfVkJVQ0tFVF9VUERBVEVcbiAgfCB0eXBlb2YgT1BfRU5BQkxFX1RSQUZGSUNcbiAgfCB0eXBlb2YgT1BfRElTQUJMRV9UUkFGRklDXG4gIHwgdHlwZW9mIE9QX0NIQU5HRV9WQl9GSUxURVJcbiAgfCB0eXBlb2YgT1BfQ0hFQ0tQT0lOVF9QRVJTSVNURU5DRVxuICB8IHR5cGVvZiBPUF9SRVRVUk5fTUVUQVxuICB8IHR5cGVvZiBPUF9DT01QQUNUX0RCXG4gIHwgdHlwZW9mIE9QX1NFVF9DTFVTVEVSX0NPTkZJR1xuICB8IHR5cGVvZiBPUF9HRVRfQ0xVU1RFUl9DT05GSUdcbiAgfCB0eXBlb2YgT1BfR0VUX1JBTkRPTV9LRVlcbiAgfCB0eXBlb2YgT1BfU0VRTk9fUEVSU0lTVEVOQ0VcbiAgfCB0eXBlb2YgT1BfR0VUX0tFWVNcbiAgfCB0eXBlb2YgT1BfU0VUX0RSSUZUX0NPVU5URVJfU1RBVEVcbiAgfCB0eXBlb2YgT1BfR0VUX0FESlVTVEVEX1RJTUVcbiAgfCB0eXBlb2YgT1BfU1VCRE9DX0dFVFxuICB8IHR5cGVvZiBPUF9TVUJET0NfRVhJU1RTXG4gIHwgdHlwZW9mIE9QX1NVQkRPQ19ESUNUX0FERFxuICB8IHR5cGVvZiBPUF9TVUJET0NfRElDVF9VUFNFUlRcbiAgfCB0eXBlb2YgT1BfU1VCRE9DX0RFTEVURVxuICB8IHR5cGVvZiBPUF9TVUJET0NfUkVQTEFDRVxuICB8IHR5cGVvZiBPUF9TVUJET0NfQVJSQVlfUFVTSF9MQVNUXG4gIHwgdHlwZW9mIE9QX1NVQkRPQ19BUlJBWV9QVVNIX0ZJUlNUXG4gIHwgdHlwZW9mIE9QX1NVQkRPQ19BUlJBWV9JTlNFUlRcbiAgfCB0eXBlb2YgT1BfU1VCRE9DX0FSUkFZX0FERF9VTklRVUVcbiAgfCB0eXBlb2YgT1BfU1VCRE9DX0NPVU5URVJcbiAgfCB0eXBlb2YgT1BfU1VCRE9DX01VTFRJX0xPT0tVUFxuICB8IHR5cGVvZiBPUF9TVUJET0NfTVVMVElfTVVUQVRJT05cbiAgfCB0eXBlb2YgT1BfU1VCRE9DX0dFVF9DT1VOVFxuICB8IHR5cGVvZiBPUF9TQ1JVQlxuICB8IHR5cGVvZiBPUF9JU0FTTF9SRUZSRVNIXG4gIHwgdHlwZW9mIE9QX1NTTF9DRVJUU19SRUZSRVNIXG4gIHwgdHlwZW9mIE9QX0dFVF9DTURfVElNRVJcbiAgfCB0eXBlb2YgT1BfU0VUX0NUUkxfVE9LRU5cbiAgfCB0eXBlb2YgT1BfR0VUX0NUUkxfVE9LRU5cbiAgfCB0eXBlb2YgT1BfSU5JVF9DT01QTEVURTtcblxuLyoqXG4gKiBSZXNwb25zZSBzdGF0dXNlc1xuICogaHR0cHM6Ly9naXRodWIuY29tL21lbWNhY2hlZC9tZW1jYWNoZWQvd2lraS9CaW5hcnlQcm90b2NvbFJldmFtcGVkI3Jlc3BvbnNlLXN0YXR1c1xuICovXG5leHBvcnQgY29uc3QgUmVzcG9uc2VTdGF0dXMgPSB7XG4gIC8qKiBOYW1lZCBcIk5vIGVycm9yXCIgaW4gdGhlIG1lbWNhY2hlZCBkb2NzLCBidXQgY2xlYXJlciBpbiBjb2RlIGFzIFwiU1VDQ0VTU1wiLiAqL1xuICBTVUNDRVNTOiAweDAwMDAsXG4gIEtFWV9OT1RfRk9VTkQ6IDB4MDAwMSxcbiAgS0VZX0VYSVNUUzogMHgwMDAyLFxuICBWQUxVRV9UT09fTEFSR0U6IDB4MDAwMyxcbiAgSU5WQUxJRF9BUkdVTUVOVFM6IDB4MDAwNCxcbiAgSVRFTV9OT1RfU1RPUkVEOiAweDAwMDUsXG4gIElOQ1JfREVDUl9PTl9OT05fTlVNRVJJQ19WQUxVRTogMHgwMDA2LFxuICBUSEVfVkJVQ0tFVF9CRUxPTkdTX1RPX0FOT1RIRVJfU0VSVkVSOiAweDAwMDcsXG4gIEFVVEhFTlRJQ0FUSU9OX0VSUk9SOiAweDAwMDgsXG4gIEFVVEhFTlRJQ0FUSU9OX0NPTlRJTlVFOiAweDAwMDksXG4gIFVOS05PV05fQ09NTUFORDogMHgwMDgxLFxuICBPVVRfT0ZfTUVNT1JZOiAweDAwODIsXG4gIE5PVF9TVVBQT1JURUQ6IDB4MDA4MyxcbiAgSU5URVJOQUxfRVJST1I6IDB4MDA4NCxcbiAgQlVTWTogMHgwMDg1LFxuICBURU1QT1JBUllfRkFJTFVSRTogMHgwMDg2LFxufSBhcyBjb25zdDtcblxuZXhwb3J0IHR5cGUgUmVzcG9uc2VTdGF0dXMgPSB0eXBlb2YgUmVzcG9uc2VTdGF0dXNba2V5b2YgdHlwZW9mIFJlc3BvbnNlU3RhdHVzXTtcblxuZXhwb3J0IGZ1bmN0aW9uIHJlc3BvbnNlU3RhdHVzVG9TdHJpbmcoXG4gIHJlc3BvbnNlU3RhdHVzOiBSZXNwb25zZVN0YXR1cyB8IHVuZGVmaW5lZFxuKSB7XG4gIHN3aXRjaCAocmVzcG9uc2VTdGF0dXMpIHtcbiAgICBjYXNlIDB4MDAwMDpcbiAgICAgIHJldHVybiBcIk5vIGVycm9yXCI7XG4gICAgY2FzZSAweDAwMDE6XG4gICAgICByZXR1cm4gXCJLZXkgbm90IGZvdW5kXCI7XG4gICAgY2FzZSAweDAwMDI6XG4gICAgICByZXR1cm4gXCJLZXkgZXhpc3RzXCI7XG4gICAgY2FzZSAweDAwMDM6XG4gICAgICByZXR1cm4gXCJWYWx1ZSB0b28gbGFyZ2VcIjtcbiAgICBjYXNlIDB4MDAwNDpcbiAgICAgIHJldHVybiBcIkludmFsaWQgYXJndW1lbnRzXCI7XG4gICAgY2FzZSAweDAwMDU6XG4gICAgICByZXR1cm4gXCJJdGVtIG5vdCBzdG9yZWRcIjtcbiAgICBjYXNlIDB4MDAwNjpcbiAgICAgIHJldHVybiBcIkluY3IvRGVjciBvbiBub24tbnVtZXJpYyB2YWx1ZVwiO1xuICAgIGNhc2UgMHgwMDA3OlxuICAgICAgcmV0dXJuIFwiVGhlIHZidWNrZXQgYmVsb25ncyB0byBhbm90aGVyIHNlcnZlclwiO1xuICAgIGNhc2UgMHgwMDA4OlxuICAgICAgcmV0dXJuIFwiQXV0aGVudGljYXRpb24gZXJyb3JcIjtcbiAgICBjYXNlIDB4MDAwOTpcbiAgICAgIHJldHVybiBcIkF1dGhlbnRpY2F0aW9uIGNvbnRpbnVlXCI7XG4gICAgY2FzZSAweDAwODE6XG4gICAgICByZXR1cm4gXCJVbmtub3duIGNvbW1hbmRcIjtcbiAgICBjYXNlIDB4MDA4MjpcbiAgICAgIHJldHVybiBcIk91dCBvZiBtZW1vcnlcIjtcbiAgICBjYXNlIDB4MDA4MzpcbiAgICAgIHJldHVybiBcIk5vdCBzdXBwb3J0ZWRcIjtcbiAgICBjYXNlIDB4MDA4NDpcbiAgICAgIHJldHVybiBcIkludGVybmFsIGVycm9yXCI7XG4gICAgY2FzZSAweDAwODU6XG4gICAgICByZXR1cm4gXCJCdXN5XCI7XG4gICAgY2FzZSAweDAwODY6XG4gICAgICByZXR1cm4gXCJUZW1wb3JhcnkgZmFpbHVyZVwiO1xuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gYFVua25vd24gcmVzcG9uc2Ugc3RhdHVzICR7cmVzcG9uc2VTdGF0dXN9YDtcbiAgfVxufVxuIl19 \ No newline at end of file diff --git a/lib/memjs/header.d.ts b/lib/memjs/header.d.ts new file mode 100644 index 0000000..14640d8 --- /dev/null +++ b/lib/memjs/header.d.ts @@ -0,0 +1,18 @@ +/// +import { OP, ResponseStatus } from "./constants"; +export interface Header { + magic: number; + opcode: OP; + keyLength: number; + extrasLength: number; + dataType?: number; + status?: ResponseStatus; + totalBodyLength: number; + opaque: number; + cas?: Buffer; +} +/** fromBuffer converts a serialized header to a JS object. */ +export declare function fromBuffer(headerBuf: Buffer): Header; +/** toBuffer converts a JS memcache header object to a binary memcache header */ +export declare function toBuffer(header: Header): Buffer; +//# sourceMappingURL=header.d.ts.map \ No newline at end of file diff --git a/lib/memjs/header.d.ts.map b/lib/memjs/header.d.ts.map new file mode 100644 index 0000000..5495b8a --- /dev/null +++ b/lib/memjs/header.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"header.d.ts","sourceRoot":"","sources":["../../src/memjs/header.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,EAAE,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAEjD,MAAM,WAAW,MAAM;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,EAAE,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,8DAA8D;AAC9D,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAepD;AAED,gFAAgF;AAChF,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAgB/C"} \ No newline at end of file diff --git a/lib/memjs/header.js b/lib/memjs/header.js new file mode 100644 index 0000000..9d4ed57 --- /dev/null +++ b/lib/memjs/header.js @@ -0,0 +1,43 @@ +"use strict"; +// # MemJS Memcache binary protocol header +Object.defineProperty(exports, "__esModule", { value: true }); +exports.toBuffer = exports.fromBuffer = void 0; +/** fromBuffer converts a serialized header to a JS object. */ +function fromBuffer(headerBuf) { + if (!headerBuf) { + return {}; // TODO + } + return { + magic: headerBuf.readUInt8(0), + opcode: headerBuf.readUInt8(1), + keyLength: headerBuf.readUInt16BE(2), + extrasLength: headerBuf.readUInt8(4), + dataType: headerBuf.readUInt8(5), + status: headerBuf.readUInt16BE(6), + totalBodyLength: headerBuf.readUInt32BE(8), + opaque: headerBuf.readUInt32BE(12), + cas: headerBuf.slice(16, 24), + }; +} +exports.fromBuffer = fromBuffer; +/** toBuffer converts a JS memcache header object to a binary memcache header */ +function toBuffer(header) { + const headerBuf = Buffer.alloc(24); + headerBuf.writeUInt8(header.magic, 0); + headerBuf.writeUInt8(header.opcode, 1); + headerBuf.writeUInt16BE(header.keyLength, 2); + headerBuf.writeUInt8(header.extrasLength, 4); + headerBuf.writeUInt8(header.dataType || 0, 5); + headerBuf.writeUInt16BE(header.status || 0, 6); + headerBuf.writeUInt32BE(header.totalBodyLength, 8); + headerBuf.writeUInt32BE(header.opaque || 0, 12); + if (header.cas) { + header.cas.copy(headerBuf, 16); + } + else { + headerBuf.fill("\x00", 16); + } + return headerBuf; +} +exports.toBuffer = toBuffer; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGVhZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL21lbWpzL2hlYWRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsMENBQTBDOzs7QUFnQjFDLDhEQUE4RDtBQUM5RCxTQUFnQixVQUFVLENBQUMsU0FBaUI7SUFDMUMsSUFBSSxDQUFDLFNBQVMsRUFBRTtRQUNkLE9BQU8sRUFBUyxDQUFDLENBQUMsT0FBTztLQUMxQjtJQUNELE9BQU87UUFDTCxLQUFLLEVBQUUsU0FBUyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUM7UUFDN0IsTUFBTSxFQUFFLFNBQVMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFPO1FBQ3BDLFNBQVMsRUFBRSxTQUFTLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQztRQUNwQyxZQUFZLEVBQUUsU0FBUyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUM7UUFDcEMsUUFBUSxFQUFFLFNBQVMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDO1FBQ2hDLE1BQU0sRUFBRSxTQUFTLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBbUI7UUFDbkQsZUFBZSxFQUFFLFNBQVMsQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDO1FBQzFDLE1BQU0sRUFBRSxTQUFTLENBQUMsWUFBWSxDQUFDLEVBQUUsQ0FBQztRQUNsQyxHQUFHLEVBQUUsU0FBUyxDQUFDLEtBQUssQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDO0tBQzdCLENBQUM7QUFDSixDQUFDO0FBZkQsZ0NBZUM7QUFFRCxnRkFBZ0Y7QUFDaEYsU0FBZ0IsUUFBUSxDQUFDLE1BQWM7SUFDckMsTUFBTSxTQUFTLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUNuQyxTQUFTLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDdEMsU0FBUyxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ3ZDLFNBQVMsQ0FBQyxhQUFhLENBQUMsTUFBTSxDQUFDLFNBQVMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUM3QyxTQUFTLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxZQUFZLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDN0MsU0FBUyxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsUUFBUSxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUM5QyxTQUFTLENBQUMsYUFBYSxDQUFDLE1BQU0sQ0FBQyxNQUFNLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQy9DLFNBQVMsQ0FBQyxhQUFhLENBQUMsTUFBTSxDQUFDLGVBQWUsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNuRCxTQUFTLENBQUMsYUFBYSxDQUFDLE1BQU0sQ0FBQyxNQUFNLElBQUksQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ2hELElBQUksTUFBTSxDQUFDLEdBQUcsRUFBRTtRQUNkLE1BQU0sQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxFQUFFLENBQUMsQ0FBQztLQUNoQztTQUFNO1FBQ0wsU0FBUyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLENBQUM7S0FDNUI7SUFDRCxPQUFPLFNBQVMsQ0FBQztBQUNuQixDQUFDO0FBaEJELDRCQWdCQyIsInNvdXJjZXNDb250ZW50IjpbIi8vICMgTWVtSlMgTWVtY2FjaGUgYmluYXJ5IHByb3RvY29sIGhlYWRlclxuXG5pbXBvcnQgeyBPUCwgUmVzcG9uc2VTdGF0dXMgfSBmcm9tIFwiLi9jb25zdGFudHNcIjtcblxuZXhwb3J0IGludGVyZmFjZSBIZWFkZXIge1xuICBtYWdpYzogbnVtYmVyO1xuICBvcGNvZGU6IE9QO1xuICBrZXlMZW5ndGg6IG51bWJlcjtcbiAgZXh0cmFzTGVuZ3RoOiBudW1iZXI7XG4gIGRhdGFUeXBlPzogbnVtYmVyO1xuICBzdGF0dXM/OiBSZXNwb25zZVN0YXR1cztcbiAgdG90YWxCb2R5TGVuZ3RoOiBudW1iZXI7XG4gIG9wYXF1ZTogbnVtYmVyO1xuICBjYXM/OiBCdWZmZXI7XG59XG5cbi8qKiBmcm9tQnVmZmVyIGNvbnZlcnRzIGEgc2VyaWFsaXplZCBoZWFkZXIgdG8gYSBKUyBvYmplY3QuICovXG5leHBvcnQgZnVuY3Rpb24gZnJvbUJ1ZmZlcihoZWFkZXJCdWY6IEJ1ZmZlcik6IEhlYWRlciB7XG4gIGlmICghaGVhZGVyQnVmKSB7XG4gICAgcmV0dXJuIHt9IGFzIGFueTsgLy8gVE9ET1xuICB9XG4gIHJldHVybiB7XG4gICAgbWFnaWM6IGhlYWRlckJ1Zi5yZWFkVUludDgoMCksXG4gICAgb3Bjb2RlOiBoZWFkZXJCdWYucmVhZFVJbnQ4KDEpIGFzIE9QLCAvLyBUT0RPOiB3cm9uZyB0eXBlP1xuICAgIGtleUxlbmd0aDogaGVhZGVyQnVmLnJlYWRVSW50MTZCRSgyKSxcbiAgICBleHRyYXNMZW5ndGg6IGhlYWRlckJ1Zi5yZWFkVUludDgoNCksXG4gICAgZGF0YVR5cGU6IGhlYWRlckJ1Zi5yZWFkVUludDgoNSksXG4gICAgc3RhdHVzOiBoZWFkZXJCdWYucmVhZFVJbnQxNkJFKDYpIGFzIFJlc3BvbnNlU3RhdHVzLCAvLyBUT0RPOiB3cm9uZyB0eXBlP1xuICAgIHRvdGFsQm9keUxlbmd0aDogaGVhZGVyQnVmLnJlYWRVSW50MzJCRSg4KSxcbiAgICBvcGFxdWU6IGhlYWRlckJ1Zi5yZWFkVUludDMyQkUoMTIpLFxuICAgIGNhczogaGVhZGVyQnVmLnNsaWNlKDE2LCAyNCksXG4gIH07XG59XG5cbi8qKiB0b0J1ZmZlciBjb252ZXJ0cyBhIEpTIG1lbWNhY2hlIGhlYWRlciBvYmplY3QgdG8gYSBiaW5hcnkgbWVtY2FjaGUgaGVhZGVyICovXG5leHBvcnQgZnVuY3Rpb24gdG9CdWZmZXIoaGVhZGVyOiBIZWFkZXIpOiBCdWZmZXIge1xuICBjb25zdCBoZWFkZXJCdWYgPSBCdWZmZXIuYWxsb2MoMjQpO1xuICBoZWFkZXJCdWYud3JpdGVVSW50OChoZWFkZXIubWFnaWMsIDApO1xuICBoZWFkZXJCdWYud3JpdGVVSW50OChoZWFkZXIub3Bjb2RlLCAxKTtcbiAgaGVhZGVyQnVmLndyaXRlVUludDE2QkUoaGVhZGVyLmtleUxlbmd0aCwgMik7XG4gIGhlYWRlckJ1Zi53cml0ZVVJbnQ4KGhlYWRlci5leHRyYXNMZW5ndGgsIDQpO1xuICBoZWFkZXJCdWYud3JpdGVVSW50OChoZWFkZXIuZGF0YVR5cGUgfHwgMCwgNSk7XG4gIGhlYWRlckJ1Zi53cml0ZVVJbnQxNkJFKGhlYWRlci5zdGF0dXMgfHwgMCwgNik7XG4gIGhlYWRlckJ1Zi53cml0ZVVJbnQzMkJFKGhlYWRlci50b3RhbEJvZHlMZW5ndGgsIDgpO1xuICBoZWFkZXJCdWYud3JpdGVVSW50MzJCRShoZWFkZXIub3BhcXVlIHx8IDAsIDEyKTtcbiAgaWYgKGhlYWRlci5jYXMpIHtcbiAgICBoZWFkZXIuY2FzLmNvcHkoaGVhZGVyQnVmLCAxNik7XG4gIH0gZWxzZSB7XG4gICAgaGVhZGVyQnVmLmZpbGwoXCJcXHgwMFwiLCAxNik7XG4gIH1cbiAgcmV0dXJuIGhlYWRlckJ1Zjtcbn1cbiJdfQ== \ No newline at end of file diff --git a/lib/memjs/memjs.d.ts b/lib/memjs/memjs.d.ts new file mode 100644 index 0000000..80a0b14 --- /dev/null +++ b/lib/memjs/memjs.d.ts @@ -0,0 +1,304 @@ +/// +import { Server, ServerOptions } from "./server"; +import { Serializer } from "./noop-serializer"; +import { MaybeBuffer, Message } from "./utils"; +import * as Utils from "./utils"; +import * as Header from "./header"; +declare function defaultKeyToServerHashFunction(servers: string[], key: string): string; +declare type ResponseOrErrorCallback = (error: Error | null, response: Message | null) => void; +interface BaseClientOptions { + retries: number; + retry_delay: number; + expires: number; + logger: { + log: typeof console.log; + }; + keyToServerHashFunction: typeof defaultKeyToServerHashFunction; +} +interface SerializerProp { + serializer: Serializer; +} +/** + * The client has partial support for serializing and deserializing values from the + * Buffer byte strings we recieve from the wire. The default serializer is for MaybeBuffer. + * + * If Value and Extras are of type Buffer, then return type WhenBuffer. Otherwise, + * return type NotBuffer. + */ +declare type IfBuffer = Value extends Buffer ? Extras extends Buffer ? WhenValueAndExtrasAreBuffers : NotBuffer : NotBuffer; +export declare type GivenClientOptions = Partial & IfBuffer>, SerializerProp>; +export declare type CASToken = Buffer; +export interface GetResult { + value: Value; + extras: Extras; + cas: CASToken | undefined; +} +export declare type GetMultiResult = { + [K in Keys]?: GetResult; +}; +declare class Client { + servers: Server[]; + seq: number; + options: BaseClientOptions & Partial>; + serializer: Serializer; + serverMap: { + [hostport: string]: Server; + }; + serverKeys: string[]; + constructor(servers: Server[], options: GivenClientOptions); + /** + * Creates a new client given an optional config string and optional hash of + * options. The config string should be of the form: + * + * "[user:pass@]server1[:11211],[user:pass@]server2[:11211],..." + * + * If the argument is not given, fallback on the `MEMCACHIER_SERVERS` environment + * variable, `MEMCACHE_SERVERS` environment variable or `"localhost:11211"`. + * + * The options hash may contain the options: + * + * * `retries` - the number of times to retry an operation in lieu of failures + * (default 2) + * * `expires` - the default expiration in seconds to use (default 0 - never + * expire). If `expires` is greater than 30 days (60 x 60 x 24 x 30), it is + * treated as a UNIX time (number of seconds since January 1, 1970). + * * `logger` - a logger object that responds to `log(string)` method calls. + * + * ~~~~ + * log(msg1[, msg2[, msg3[...]]]) + * ~~~~ + * + * Defaults to `console`. + * * `serializer` - the object which will (de)serialize the data. It needs + * two public methods: serialize and deserialize. It defaults to the + * noopSerializer: + * + * ~~~~ + * const noopSerializer = { + * serialize: function (opcode, value, extras) { + * return { value: value, extras: extras }; + * }, + * deserialize: function (opcode, value, extras) { + * return { value: value, extras: extras }; + * } + * }; + * ~~~~ + * + * Or options for the servers including: + * * `username` and `password` for fallback SASL authentication credentials. + * * `timeout` in seconds to determine failure for operations. Default is 0.5 + * seconds. + * * 'conntimeout' in seconds to connection failure. Default is twice the value + * of `timeout`. + * * `keepAlive` whether to enable keep-alive functionality. Defaults to false. + * * `keepAliveDelay` in seconds to the initial delay before the first keepalive + * probe is sent on an idle socket. Defaults is 30 seconds. + * * `keyToServerHashFunction` a function to map keys to servers, with the signature + * (serverKeys: string[], key: string): string + * NOTE: if you need to do some expensive initialization, *please* do it lazily the first time you this function is called with an array of serverKeys, not on every call + */ + static create(serversStr: string | undefined, options: IfBuffer & GivenClientOptions), Partial & GivenClientOptions>): Client; + /** + * Given a serverKey fromlookupKeyToServerKey, return the corresponding Server instance + * + * @param {string} serverKey + * @returns {Server} + */ + serverKeyToServer(serverKey: string): Server; + /** + * Given a key to look up in memcache, return a serverKey (based on some + * hashing function) which can be used to index this.serverMap + */ + lookupKeyToServerKey(key: string): string; + /** + * Retrieves the value at the given key in memcache. + */ + get(key: string): Promise | null>; + /** Build a pipelined get multi request by sending one GETKQ for each key (quiet, meaning it won't respond if the value is missing) followed by a no-op to force a response (and to give us a sentinel response that the pipeline is done) + * + * cf https://github.com/couchbase/memcached/blob/master/docs/BinaryProtocol.md#0x0d-getkq-get-with-key-quietly + */ + _buildGetMultiRequest(keys: string[]): Buffer; + /** Executing a pipelined (multi) get against a single server. This is a private implementation detail of getMulti. */ + _getMultiToServer(serv: Server, keys: Keys[]): Promise>; + /** + * Retrievs the value at the given keys in memcached. Returns a map from the + * requested keys to results, or null if the key was not found. + */ + getMulti(keys: Keys[]): Promise | null>; + /** + * Sets `key` to `value`. + */ + set(key: string, value: Value, options?: { + expires?: number; + cas?: CASToken; + }): Promise; + /** + * ADD + * + * Adds the given _key_ and _value_ to memcache. The operation only succeeds + * if the key is not already set. + * + * The options dictionary takes: + * * _expires_: overrides the default expiration (see `Client.create`) for this + * particular key-value pair. + */ + add(key: string, value: Value, options?: { + expires?: number; + }): Promise; + /** + * Replaces the given _key_ and _value_ to memcache. The operation only succeeds + * if the key is already present. + */ + replace(key: string, value: Value, options?: { + expires?: number; + }): Promise; + /** + * Deletes the given _key_ from memcache. The operation only succeeds + * if the key is already present. + */ + delete(key: string): Promise; + /** + * Increments the given _key_ in memcache. + */ + increment(key: string, amount: number, options?: { + initial?: number; + expires?: number; + }): Promise<{ + value: number | null; + success: boolean | null; + }>; + /** + * Decrements the given `key` in memcache. + */ + decrement(key: string, amount: number, options: { + initial?: number; + expires?: number; + }): Promise<{ + value: number | null; + success: boolean | null; + }>; + /** + * Append the given _value_ to the value associated with the given _key_ in + * memcache. The operation only succeeds if the key is already present. + */ + append(key: string, value: Value): Promise; + /** + * Prepend the given _value_ to the value associated with the given _key_ in + * memcache. The operation only succeeds if the key is already present. + */ + prepend(key: string, value: Value): Promise; + /** + * Touch sets an expiration value, given by _expires_, on the given _key_ in + * memcache. The operation only succeeds if the key is already present. + */ + touch(key: string, expires: number): Promise; + /** + * FLUSH + * + * Flushes the cache on each connected server. The callback signature is: + * + * callback(lastErr, results) + * + * where _lastErr_ is the last error encountered (or null, in the common case + * of no errors). _results_ is a dictionary mapping `"hostname:port"` to either + * `true` (if the operation was successful), or an error. + * @param callback + */ + flush(): Promise>; + flush(callback: (err: Error | null, results: Record) => void): void; + /** + * STATS_WITH_KEY + * + * Sends a memcache stats command with a key to each connected server. The + * callback is invoked **ONCE PER SERVER** and has the signature: + * + * callback(err, server, stats) + * + * _server_ is the `"hostname:port"` of the server, and _stats_ is a dictionary + * mapping the stat name to the value of the statistic as a string. + * @param key + * @param callback + */ + statsWithKey(key: string, callback?: (err: Error | null, server: string, stats: Record | null) => void): void; + /** + * STATS + * + * Fetches memcache stats from each connected server. The callback is invoked + * **ONCE PER SERVER** and has the signature: + * + * callback(err, server, stats) + * + * _server_ is the `"hostname:port"` of the server, and _stats_ is a + * dictionary mapping the stat name to the value of the statistic as a string. + * @param callback + */ + stats(callback?: (err: Error | null, server: string, stats: Record | null) => void): void; + /** + * RESET_STATS + * + * Reset the statistics each server is keeping back to zero. This doesn't clear + * stats such as item count, but temporary stats such as total number of + * connections over time. + * + * The callback is invoked **ONCE PER SERVER** and has the signature: + * + * callback(err, server) + * + * _server_ is the `"hostname:port"` of the server. + * @param callback + */ + resetStats(callback?: (err: Error | null, server: string, stats: Record | null) => void): void; + /** + * QUIT + * + * Closes the connection to each server, notifying them of this intention. Note + * that quit can race against already outstanding requests when those requests + * fail and are retried, leading to the quit command winning and closing the + * connection before the retries complete. + */ + quit(): void; + _version(server: Server): Promise<{ + value: Value | null; + }>; + /** + * Request the server version from the "first" server in the backend pool. + * The server responds with a packet containing the version string in the body with the following format: "x.y.z" + */ + version(): Promise<{ + value: Value | null; + }>; + /** + * Retrieves the server version from all the servers + * in the backend pool, errors if any one of them has an + * error + */ + versionAll(): Promise<{ + values: Record; + }>; + /** + * Closes (abruptly) connections to all the servers. + * @see this.quit + */ + close(): void; + /** + * Perform a generic single response operation (get, set etc) on one server + * + * @param {string} key the key to hash to get a server from the pool + * @param {buffer} request a buffer containing the request + * @param {number} seq the sequence number of the operation. It is used to pin the callbacks + to a specific operation and should never change during a `perform`. + * @param {number?} retries number of times to retry request on failure + */ + perform(key: string, request: Buffer, seq: number, retries?: number): Promise; + performOnServer(server: Server, request: Buffer, seq: number, callback: ResponseOrErrorCallback, retries?: number): void; + incrSeq(): void; + private createAndLogError; + /** + * Log an error to the logger, then return the error. + * If a callback is given, call it with callback(error, null). + */ + private handleResponseError; +} +export { Client, Server, Utils, Header }; +//# sourceMappingURL=memjs.d.ts.map \ No newline at end of file diff --git a/lib/memjs/memjs.d.ts.map b/lib/memjs/memjs.d.ts.map new file mode 100644 index 0000000..2340dda --- /dev/null +++ b/lib/memjs/memjs.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"memjs.d.ts","sourceRoot":"","sources":["../../src/memjs/memjs.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/lib/memjs/memjs.js b/lib/memjs/memjs.js new file mode 100644 index 0000000..4d65003 --- /dev/null +++ b/lib/memjs/memjs.js @@ -0,0 +1,728 @@ +"use strict"; +// MemTS Memcache Client +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Header = exports.Utils = exports.Server = exports.Client = void 0; +const server_1 = require("./server"); +Object.defineProperty(exports, "Server", { enumerable: true, get: function () { return server_1.Server; } }); +const noop_serializer_1 = require("./noop-serializer"); +const utils_1 = require("./utils"); +const constants = __importStar(require("./constants")); +const constants_1 = require("./constants"); +const Utils = __importStar(require("./utils")); +exports.Utils = Utils; +const Header = __importStar(require("./header")); +exports.Header = Header; +function defaultKeyToServerHashFunction(servers, key) { + const total = servers.length; + const index = total > 1 ? utils_1.hashCode(key) % total : 0; + return servers[index]; +} +// converts a call into a promise-returning one +function promisify(command) { + return new Promise(function (resolve, reject) { + command(function (err, result) { + err ? reject(err) : resolve(result); + }); + }); +} +class Client { + // Client initializer takes a list of `Server`s and an `options` dictionary. + // See `Client.create` for details. + constructor(servers, options) { + this.servers = servers; + this.seq = 0; + this.options = utils_1.merge(options || {}, { + retries: 2, + retry_delay: 0.2, + expires: 0, + logger: console, + keyToServerHashFunction: defaultKeyToServerHashFunction, + }); + this.serializer = this.options.serializer || noop_serializer_1.noopSerializer; + // Store a mapping from hostport -> server so we can quickly get a server object from the serverKey returned by the hashing function + const serverMap = {}; + this.servers.forEach(function (server) { + serverMap[server.hostportString()] = server; + }); + this.serverMap = serverMap; + // store a list of all our serverKeys so we don't need to constantly reallocate this array + this.serverKeys = Object.keys(this.serverMap); + } + /** + * Creates a new client given an optional config string and optional hash of + * options. The config string should be of the form: + * + * "[user:pass@]server1[:11211],[user:pass@]server2[:11211],..." + * + * If the argument is not given, fallback on the `MEMCACHIER_SERVERS` environment + * variable, `MEMCACHE_SERVERS` environment variable or `"localhost:11211"`. + * + * The options hash may contain the options: + * + * * `retries` - the number of times to retry an operation in lieu of failures + * (default 2) + * * `expires` - the default expiration in seconds to use (default 0 - never + * expire). If `expires` is greater than 30 days (60 x 60 x 24 x 30), it is + * treated as a UNIX time (number of seconds since January 1, 1970). + * * `logger` - a logger object that responds to `log(string)` method calls. + * + * ~~~~ + * log(msg1[, msg2[, msg3[...]]]) + * ~~~~ + * + * Defaults to `console`. + * * `serializer` - the object which will (de)serialize the data. It needs + * two public methods: serialize and deserialize. It defaults to the + * noopSerializer: + * + * ~~~~ + * const noopSerializer = { + * serialize: function (opcode, value, extras) { + * return { value: value, extras: extras }; + * }, + * deserialize: function (opcode, value, extras) { + * return { value: value, extras: extras }; + * } + * }; + * ~~~~ + * + * Or options for the servers including: + * * `username` and `password` for fallback SASL authentication credentials. + * * `timeout` in seconds to determine failure for operations. Default is 0.5 + * seconds. + * * 'conntimeout' in seconds to connection failure. Default is twice the value + * of `timeout`. + * * `keepAlive` whether to enable keep-alive functionality. Defaults to false. + * * `keepAliveDelay` in seconds to the initial delay before the first keepalive + * probe is sent on an idle socket. Defaults is 30 seconds. + * * `keyToServerHashFunction` a function to map keys to servers, with the signature + * (serverKeys: string[], key: string): string + * NOTE: if you need to do some expensive initialization, *please* do it lazily the first time you this function is called with an array of serverKeys, not on every call + */ + static create(serversStr, options) { + serversStr = + serversStr || + process.env.MEMCACHIER_SERVERS || + process.env.MEMCACHE_SERVERS || + "localhost:11211"; + const serverUris = serversStr.split(","); + const servers = serverUris.map(function (uri) { + const uriParts = uri.split("@"); + const hostPort = uriParts[uriParts.length - 1].split(":"); + const userPass = (uriParts[uriParts.length - 2] || "").split(":"); + return new server_1.Server(hostPort[0], parseInt(hostPort[1] || "11211", 10), userPass[0], userPass[1], options); + }); + return new Client(servers, options); + } + /** + * Given a serverKey fromlookupKeyToServerKey, return the corresponding Server instance + * + * @param {string} serverKey + * @returns {Server} + */ + serverKeyToServer(serverKey) { + return this.serverMap[serverKey]; + } + /** + * Given a key to look up in memcache, return a serverKey (based on some + * hashing function) which can be used to index this.serverMap + */ + lookupKeyToServerKey(key) { + return this.options.keyToServerHashFunction(this.serverKeys, key); + } + /** + * Retrieves the value at the given key in memcache. + */ + async get(key) { + this.incrSeq(); + const request = utils_1.makeRequestBuffer(constants.OP_GET, key, "", "", this.seq); + const response = await this.perform(key, request, this.seq); + switch (response.header.status) { + case constants_1.ResponseStatus.SUCCESS: + const deserialized = this.serializer.deserialize(response.header.opcode, response.val, response.extras); + return { ...deserialized, cas: response.header.cas }; + case constants_1.ResponseStatus.KEY_NOT_FOUND: + return null; + default: + throw this.createAndLogError("GET", response.header.status); + } + } + /** Build a pipelined get multi request by sending one GETKQ for each key (quiet, meaning it won't respond if the value is missing) followed by a no-op to force a response (and to give us a sentinel response that the pipeline is done) + * + * cf https://github.com/couchbase/memcached/blob/master/docs/BinaryProtocol.md#0x0d-getkq-get-with-key-quietly + */ + _buildGetMultiRequest(keys) { + // start at 24 for the no-op command at the end + let requestSize = 24; + for (const keyIdx in keys) { + requestSize += Buffer.byteLength(keys[keyIdx], "utf8") + 24; + } + const request = Buffer.alloc(requestSize); + let bytesWritten = 0; + for (const keyIdx in keys) { + const key = keys[keyIdx]; + bytesWritten += utils_1.copyIntoRequestBuffer(constants.OP_GETKQ, key, "", "", this.seq, request, bytesWritten); + } + bytesWritten += utils_1.copyIntoRequestBuffer(constants.OP_NO_OP, "", "", "", this.seq, request, bytesWritten); + return request; + } + /** Executing a pipelined (multi) get against a single server. This is a private implementation detail of getMulti. */ + async _getMultiToServer(serv, keys) { + return new Promise((resolve, reject) => { + const responseMap = {}; + const handle = (response) => { + switch (response.header.status) { + case constants_1.ResponseStatus.SUCCESS: + // When we get the no-op response, we are done with this one getMulti in the per-backend fan-out + if (response.header.opcode === constants.OP_NO_OP) { + // This ensures the handler will be deleted from the responseCallbacks map in server.js + // This isn't technically needed here because the logic in server.js also checks if totalBodyLength === 0, but our unittests aren't great about setting that field, and also this makes it more explicit + handle.quiet = false; + resolve(responseMap); + } + else { + const deserialized = this.serializer.deserialize(response.header.opcode, response.val, response.extras); + const key = response.key.toString(); + responseMap[key] = { ...deserialized, cas: response.header.cas }; + } + break; + default: + return reject(this.createAndLogError("GET", response.header.status)); + } + }; + // This prevents the handler from being deleted + // after the first response. Logic in server.js. + handle.quiet = true; + const request = this._buildGetMultiRequest(keys); + serv.onResponse(this.seq, handle); + serv.onError(this.seq, reject); + this.incrSeq(); + serv.write(request); + }); + } + /** + * Retrievs the value at the given keys in memcached. Returns a map from the + * requested keys to results, or null if the key was not found. + */ + async getMulti(keys) { + const serverKeytoLookupKeys = {}; + keys.forEach((lookupKey) => { + const serverKey = this.lookupKeyToServerKey(lookupKey); + if (!serverKeytoLookupKeys[serverKey]) { + serverKeytoLookupKeys[serverKey] = []; + } + serverKeytoLookupKeys[serverKey].push(lookupKey); + }); + const usedServerKeys = Object.keys(serverKeytoLookupKeys); + const results = await Promise.all(usedServerKeys.map((serverKey) => { + const server = this.serverKeyToServer(serverKey); + return this._getMultiToServer(server, serverKeytoLookupKeys[serverKey]); + })); + return Object.assign({}, ...results); + } + /** + * Sets `key` to `value`. + */ + async set(key, value, options) { + const expires = options === null || options === void 0 ? void 0 : options.expires; + const cas = options === null || options === void 0 ? void 0 : options.cas; + // TODO: support flags + this.incrSeq(); + const expiration = utils_1.makeExpiration(expires || this.options.expires); + const extras = Buffer.concat([Buffer.from("00000000", "hex"), expiration]); + const serialized = this.serializer.serialize(constants.OP_SET, value, extras); + const request = Utils.encodeRequest({ + header: { + opcode: constants.OP_SET, + opaque: this.seq, + cas, + }, + key, + value: serialized.value, + extras: serialized.extras, + }); + const response = await this.perform(key, request, this.seq); + switch (response.header.status) { + case constants_1.ResponseStatus.SUCCESS: + return true; + case constants_1.ResponseStatus.KEY_EXISTS: + if (cas) { + return false; + } + else { + throw this.createAndLogError("SET", response.header.status); + } + default: + throw this.createAndLogError("SET", response.header.status); + } + } + /** + * ADD + * + * Adds the given _key_ and _value_ to memcache. The operation only succeeds + * if the key is not already set. + * + * The options dictionary takes: + * * _expires_: overrides the default expiration (see `Client.create`) for this + * particular key-value pair. + */ + async add(key, value, options) { + // TODO: support flags, support version (CAS) + this.incrSeq(); + const expiration = utils_1.makeExpiration((options === null || options === void 0 ? void 0 : options.expires) || this.options.expires); + const extras = Buffer.concat([Buffer.from("00000000", "hex"), expiration]); + const opcode = constants.OP_ADD; + const serialized = this.serializer.serialize(opcode, value, extras); + const request = utils_1.makeRequestBuffer(opcode, key, serialized.extras, serialized.value, this.seq); + const response = await this.perform(key, request, this.seq); + switch (response.header.status) { + case constants_1.ResponseStatus.SUCCESS: + return true; + case constants_1.ResponseStatus.KEY_EXISTS: + return false; + break; + default: + throw this.createAndLogError("ADD", response.header.status); + } + } + /** + * Replaces the given _key_ and _value_ to memcache. The operation only succeeds + * if the key is already present. + */ + async replace(key, value, options) { + // TODO: support flags, support version (CAS) + this.incrSeq(); + const expiration = utils_1.makeExpiration((options === null || options === void 0 ? void 0 : options.expires) || this.options.expires); + const extras = Buffer.concat([Buffer.from("00000000", "hex"), expiration]); + const opcode = constants.OP_REPLACE; + const serialized = this.serializer.serialize(opcode, value, extras); + const request = utils_1.makeRequestBuffer(opcode, key, serialized.extras, serialized.value, this.seq); + const response = await this.perform(key, request, this.seq); + switch (response.header.status) { + case constants_1.ResponseStatus.SUCCESS: + return true; + case constants_1.ResponseStatus.KEY_NOT_FOUND: + return false; + default: + throw this.createAndLogError("REPLACE", response.header.status); + } + } + /** + * Deletes the given _key_ from memcache. The operation only succeeds + * if the key is already present. + */ + async delete(key) { + // TODO: Support version (CAS) + this.incrSeq(); + const request = utils_1.makeRequestBuffer(4, key, "", "", this.seq); + const response = await this.perform(key, request, this.seq); + switch (response.header.status) { + case constants_1.ResponseStatus.SUCCESS: + return true; + case constants_1.ResponseStatus.KEY_NOT_FOUND: + return false; + default: + throw this.createAndLogError("DELETE", response === null || response === void 0 ? void 0 : response.header.status); + } + } + /** + * Increments the given _key_ in memcache. + */ + async increment(key, amount, options) { + // TODO: support version (CAS) + this.incrSeq(); + const initial = (options === null || options === void 0 ? void 0 : options.initial) || 0; + const expires = (options === null || options === void 0 ? void 0 : options.expires) || this.options.expires; + const extras = utils_1.makeAmountInitialAndExpiration(amount, initial, expires); + const request = utils_1.makeRequestBuffer(constants.OP_INCREMENT, key, extras, "", this.seq); + const response = await this.perform(key, request, this.seq); + switch (response.header.status) { + case constants_1.ResponseStatus.SUCCESS: + const bufInt = (response.val.readUInt32BE(0) << 8) + response.val.readUInt32BE(4); + return { value: bufInt, success: true }; + default: + throw this.createAndLogError("INCREMENT", response.header.status); + } + } + /** + * Decrements the given `key` in memcache. + */ + async decrement(key, amount, options) { + // TODO: support version (CAS) + this.incrSeq(); + const initial = options.initial || 0; + const expires = options.expires || this.options.expires; + const extras = utils_1.makeAmountInitialAndExpiration(amount, initial, expires); + const request = utils_1.makeRequestBuffer(constants.OP_DECREMENT, key, extras, "", this.seq); + const response = await this.perform(key, request, this.seq); + switch (response.header.status) { + case constants_1.ResponseStatus.SUCCESS: + const bufInt = (response.val.readUInt32BE(0) << 8) + response.val.readUInt32BE(4); + return { value: bufInt, success: true }; + default: + throw this.createAndLogError("DECREMENT", response.header.status); + } + } + /** + * Append the given _value_ to the value associated with the given _key_ in + * memcache. The operation only succeeds if the key is already present. + */ + async append(key, value) { + // TODO: support version (CAS) + this.incrSeq(); + const opcode = constants.OP_APPEND; + const serialized = this.serializer.serialize(opcode, value, ""); + const request = utils_1.makeRequestBuffer(opcode, key, serialized.extras, serialized.value, this.seq); + const response = await this.perform(key, request, this.seq); + switch (response.header.status) { + case constants_1.ResponseStatus.SUCCESS: + return true; + case constants_1.ResponseStatus.KEY_NOT_FOUND: + return false; + default: + throw this.createAndLogError("APPEND", response.header.status); + } + } + /** + * Prepend the given _value_ to the value associated with the given _key_ in + * memcache. The operation only succeeds if the key is already present. + */ + async prepend(key, value) { + // TODO: support version (CAS) + this.incrSeq(); + const opcode = constants.OP_PREPEND; + const serialized = this.serializer.serialize(opcode, value, ""); + const request = utils_1.makeRequestBuffer(opcode, key, serialized.extras, serialized.value, this.seq); + const response = await this.perform(key, request, this.seq); + switch (response.header.status) { + case constants_1.ResponseStatus.SUCCESS: + return true; + case constants_1.ResponseStatus.KEY_NOT_FOUND: + return false; + default: + throw this.createAndLogError("PREPEND", response.header.status); + } + } + /** + * Touch sets an expiration value, given by _expires_, on the given _key_ in + * memcache. The operation only succeeds if the key is already present. + */ + async touch(key, expires) { + // TODO: support version (CAS) + this.incrSeq(); + const extras = utils_1.makeExpiration(expires || this.options.expires); + const request = utils_1.makeRequestBuffer(0x1c, key, extras, "", this.seq); + const response = await this.perform(key, request, this.seq); + switch (response.header.status) { + case constants_1.ResponseStatus.SUCCESS: + return true; + case constants_1.ResponseStatus.KEY_NOT_FOUND: + return false; + default: + throw this.createAndLogError("TOUCH", response.header.status); + } + } + flush(callback) { + if (callback === undefined) { + return promisify((callback) => { + this.flush(function (err, results) { + callback(err, results); + }); + }); + } + // TODO: support expiration + this.incrSeq(); + const request = utils_1.makeRequestBuffer(0x08, "", "", "", this.seq); + let count = this.servers.length; + const result = {}; + let lastErr = null; + const handleFlush = function (seq, serv) { + serv.onResponse(seq, function ( /* response */) { + count -= 1; + result[serv.hostportString()] = true; + if (callback && count === 0) { + callback(lastErr, result); + } + }); + serv.onError(seq, function (err) { + count -= 1; + lastErr = err; + result[serv.hostportString()] = err; + if (callback && count === 0) { + callback(lastErr, result); + } + }); + serv.write(request); + }; + for (let i = 0; i < this.servers.length; i++) { + handleFlush(this.seq, this.servers[i]); + } + } + /** + * STATS_WITH_KEY + * + * Sends a memcache stats command with a key to each connected server. The + * callback is invoked **ONCE PER SERVER** and has the signature: + * + * callback(err, server, stats) + * + * _server_ is the `"hostname:port"` of the server, and _stats_ is a dictionary + * mapping the stat name to the value of the statistic as a string. + * @param key + * @param callback + */ + statsWithKey(key, callback) { + this.incrSeq(); + const request = utils_1.makeRequestBuffer(0x10, key, "", "", this.seq); + const handleStats = (seq, serv) => { + const result = {}; + const handle = (response) => { + // end of stat responses + if (response.header.totalBodyLength === 0) { + if (callback) { + callback(null, serv.hostportString(), result); + } + return; + } + // process single stat line response + switch (response.header.status) { + case constants_1.ResponseStatus.SUCCESS: + result[response.key.toString()] = response.val.toString(); + break; + default: + const error = this.handleResponseError(`STATS (${key})`, response.header.status, undefined); + if (callback) { + callback(error, serv.hostportString(), null); + } + } + }; + handle.quiet = true; + serv.onResponse(seq, handle); + serv.onError(seq, function (err) { + if (callback) { + callback(err, serv.hostportString(), null); + } + }); + serv.write(request); + }; + for (let i = 0; i < this.servers.length; i++) { + handleStats(this.seq, this.servers[i]); + } + } + /** + * STATS + * + * Fetches memcache stats from each connected server. The callback is invoked + * **ONCE PER SERVER** and has the signature: + * + * callback(err, server, stats) + * + * _server_ is the `"hostname:port"` of the server, and _stats_ is a + * dictionary mapping the stat name to the value of the statistic as a string. + * @param callback + */ + stats(callback) { + this.statsWithKey("", callback); + } + /** + * RESET_STATS + * + * Reset the statistics each server is keeping back to zero. This doesn't clear + * stats such as item count, but temporary stats such as total number of + * connections over time. + * + * The callback is invoked **ONCE PER SERVER** and has the signature: + * + * callback(err, server) + * + * _server_ is the `"hostname:port"` of the server. + * @param callback + */ + resetStats(callback) { + this.statsWithKey("reset", callback); + } + /** + * QUIT + * + * Closes the connection to each server, notifying them of this intention. Note + * that quit can race against already outstanding requests when those requests + * fail and are retried, leading to the quit command winning and closing the + * connection before the retries complete. + */ + quit() { + this.incrSeq(); + // TODO: Nicer perhaps to do QUITQ (0x17) but need a new callback for when + // write is done. + const request = utils_1.makeRequestBuffer(0x07, "", "", "", this.seq); // QUIT + let serv; + const handleQuit = function (seq, serv) { + serv.onResponse(seq, function ( /* response */) { + serv.close(); + }); + serv.onError(seq, function ( /* err */) { + serv.close(); + }); + serv.write(request); + }; + for (let i = 0; i < this.servers.length; i++) { + serv = this.servers[i]; + handleQuit(this.seq, serv); + } + } + _version(server) { + return new Promise((resolve, reject) => { + this.incrSeq(); + const request = utils_1.makeRequestBuffer(constants.OP_VERSION, "", "", "", this.seq); + this.performOnServer(server, request, this.seq, (err, response) => { + if (err) { + return reject(err); + } + switch (response.header.status) { + case constants_1.ResponseStatus.SUCCESS: + /* TODO: this is bugged, we should't use the deserializer here, since version always returns a version string. + The deserializer should only be used on user key data. */ + const deserialized = this.serializer.deserialize(response.header.opcode, response.val, response.extras); + return resolve({ value: deserialized.value }); + default: + return reject(this.createAndLogError("VERSION", response.header.status)); + } + }); + }); + } + /** + * Request the server version from the "first" server in the backend pool. + * The server responds with a packet containing the version string in the body with the following format: "x.y.z" + */ + version() { + const server = this.serverKeyToServer(this.serverKeys[0]); + return this._version(server); + } + /** + * Retrieves the server version from all the servers + * in the backend pool, errors if any one of them has an + * error + */ + async versionAll() { + const versionObjects = await Promise.all(this.serverKeys.map((serverKey) => { + const server = this.serverKeyToServer(serverKey); + return this._version(server).then((response) => { + return { serverKey: serverKey, value: response.value }; + }); + })); + const values = versionObjects.reduce((accumulator, versionObject) => { + accumulator[versionObject.serverKey] = versionObject.value; + return accumulator; + }, {}); + return { values: values }; + } + /** + * Closes (abruptly) connections to all the servers. + * @see this.quit + */ + close() { + for (let i = 0; i < this.servers.length; i++) { + this.servers[i].close(); + } + } + /** + * Perform a generic single response operation (get, set etc) on one server + * + * @param {string} key the key to hash to get a server from the pool + * @param {buffer} request a buffer containing the request + * @param {number} seq the sequence number of the operation. It is used to pin the callbacks + to a specific operation and should never change during a `perform`. + * @param {number?} retries number of times to retry request on failure + */ + perform(key, request, seq, retries) { + return new Promise((resolve, reject) => { + const serverKey = this.lookupKeyToServerKey(key); + const server = this.serverKeyToServer(serverKey); + if (!server) { + return reject(new Error("No servers available")); + } + this.performOnServer(server, request, seq, (error, response) => { + if (error) { + return reject(error); + } + resolve(response); + }, retries); + }); + } + performOnServer(server, request, seq, callback, retries = 0) { + const _this = this; + retries = retries || this.options.retries; + const origRetries = this.options.retries; + const logger = this.options.logger; + const retry_delay = this.options.retry_delay; + const responseHandler = function (response) { + if (callback) { + callback(null, response); + } + }; + const errorHandler = function (error) { + if (--retries > 0) { + // Wait for retry_delay + setTimeout(function () { + _this.performOnServer(server, request, seq, callback, retries); + }, 1000 * retry_delay); + } + else { + logger.log("MemJS: Server <" + + server.hostportString() + + "> failed after (" + + origRetries + + ") retries with error - " + + error.message); + if (callback) { + callback(error, null); + } + } + }; + server.onResponse(seq, responseHandler); + server.onError(seq, errorHandler); + server.write(request); + } + // Increment the seq value + incrSeq() { + this.seq++; + // Wrap `this.seq` to 32-bits since the field we fit it into is only 32-bits. + this.seq &= 0xffffffff; + } + createAndLogError(commandName, responseStatus) { + const errorMessage = `MemJS ${commandName}: ${constants.responseStatusToString(responseStatus)}`; + this.options.logger.log(errorMessage); + return new Error(errorMessage); + } + /** + * Log an error to the logger, then return the error. + * If a callback is given, call it with callback(error, null). + */ + handleResponseError(commandName, responseStatus, callback) { + const error = this.createAndLogError(commandName, responseStatus); + if (callback) { + callback(error, null); + } + return error; + } +} +exports.Client = Client; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVtanMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbWVtanMvbWVtanMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLHdCQUF3Qjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUV4QixxQ0FLa0I7QUFvaENELHVGQXRoQ2YsZUFBTSxPQXNoQ2U7QUFuaEN2Qix1REFBK0Q7QUFDL0QsbUNBU2lCO0FBQ2pCLHVEQUF5QztBQUN6QywyQ0FBNkM7QUFDN0MsK0NBQWlDO0FBc2dDUixzQkFBSztBQXJnQzlCLGlEQUFtQztBQXFnQ0gsd0JBQU07QUFuZ0N0QyxTQUFTLDhCQUE4QixDQUNyQyxPQUFpQixFQUNqQixHQUFXO0lBRVgsTUFBTSxLQUFLLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQztJQUM3QixNQUFNLEtBQUssR0FBRyxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxnQkFBUSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3BELE9BQU8sT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ3hCLENBQUM7QUFFRCwrQ0FBK0M7QUFDL0MsU0FBUyxTQUFTLENBQ2hCLE9BQTBFO0lBRTFFLE9BQU8sSUFBSSxPQUFPLENBQUMsVUFBVSxPQUFPLEVBQUUsTUFBTTtRQUMxQyxPQUFPLENBQUMsVUFBVSxHQUFHLEVBQUUsTUFBTTtZQUMzQixHQUFHLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3RDLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBNkRELE1BQU0sTUFBTTtJQVFWLDRFQUE0RTtJQUM1RSxtQ0FBbUM7SUFDbkMsWUFBWSxPQUFpQixFQUFFLE9BQTBDO1FBQ3ZFLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO1FBQ3ZCLElB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QyxDQUFDO2lCQUN2QjthQUNGO1FBQ0gsQ0FBQyxDQUFDO1FBRUYsTUFBTSxDQUFDLFVBQVUsQ0FBQyxHQUFHLEVBQUUsZUFBZSxDQUFDLENBQUM7UUFDeEMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUUsWUFBWSxDQUFDLENBQUM7UUFDbEMsTUFBTSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUN4QixDQUFDO0lBRUQsMEJBQTBCO0lBQzFCLE9BQU87UUFDTCxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7UUFFWCw2RUFBNkU7UUFDN0UsSUFBSSxDQUFDLEdBQUcsSUFBSSxVQUFVLENBQUM7SUFDekIsQ0FBQztJQUVPLGlCQUFpQixDQUN2QixXQUFtQixFQUNuQixjQUEwQztRQUUxQyxNQUFNLFlBQVksR0FBRyxTQUFTLFdBQVcsS0FBSyxTQUFTLENBQUMsc0JBQXNCLENBQzVFLGNBQWMsQ0FDZixFQUFFLENBQUM7UUFDSixJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDdEMsT0FBTyxJQUFJLEtBQUssQ0FBQyxZQUFZLENBQUMsQ0FBQztJQUNqQyxDQUFDO0lBRUQ7OztPQUdHO0lBQ0ssbUJBQW1CLENBQ3pCLFdBQW1CLEVBQ25CLGNBQTBDLEVBQzFDLFFBQWtFO1FBRWxFLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxXQUFXLEVBQUUsY0FBYyxDQUFDLENBQUM7UUFDbEUsSUFBSSxRQUFRLEVBQUU7WUFDWixRQUFRLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxDQUFDO1NBQ3ZCO1FBQ0QsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0NBQ0Y7QUFFUSx3QkFBTSIsInNvdXJjZXNDb250ZW50IjpbIi8vIE1lbVRTIE1lbWNhY2hlIENsaWVudFxuXG5pbXBvcnQge1xuICBPbkVycm9yQ2FsbGJhY2ssXG4gIE9uUmVzcG9uc2VDYWxsYmFjayxcbiAgU2VydmVyLFxuICBTZXJ2ZXJPcHRpb25zLFxufSBmcm9tIFwiLi9zZXJ2ZXJcIjtcbmltcG9ydCB7IG5vb3BTZXJpYWxpemVyLCBTZXJpYWxpemVyIH0gZnJvbSBcIi4vbm9vcC1zZXJpYWxpemVyXCI7XG5pbXBvcnQge1xuICBtYWtlUmVxdWVzdEJ1ZmZlcixcbiAgY29weUludG9SZXF1ZXN0QnVmZmVyLFxuICBtZXJnZSxcbiAgbWFrZUV4cGlyYXRpb24sXG4gIG1ha2VBbW91bnRJbml0aWFsQW5kRXhwaXJhdGlvbixcbiAgaGFzaENvZGUsXG4gIE1heWJlQnVmZmVyLFxuICBNZXNzYWdlLFxufSBmcm9tIFwiLi91dGlsc1wiO1xuaW1wb3J0ICogYXMgY29uc3RhbnRzIGZyb20gXCIuL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgUmVzcG9uc2VTdGF0dXMgfSBmcm9tIFwiLi9jb25zdGFudHNcIjtcbmltcG9ydCAqIGFzIFV0aWxzIGZyb20gXCIuL3V0aWxzXCI7XG5pbXBvcnQgKiBhcyBIZWFkZXIgZnJvbSBcIi4vaGVhZGVyXCI7XG5cbmZ1bmN0aW9uIGRlZmF1bHRLZXlUb1NlcnZlckhhc2hGdW5jdGlvbihcbiAgc2VydmVyczogc3RyaW5nW10sXG4gIGtleTogc3RyaW5nXG4pOiBzdHJpbmcge1xuICBjb25zdCB0b3RhbCA9IHNlcnZlcnMubGVuZ3RoO1xuICBjb25zdCBpbmRleCA9IHRvdGFsID4gMSA/IGhhc2hDb2RlKGtleSkgJSB0b3RhbCA6IDA7XG4gIHJldHVybiBzZXJ2ZXJzW2luZGV4XTtcbn1cblxuLy8gY29udmVydHMgYSBjYWxsIGludG8gYSBwcm9taXNlLXJldHVybmluZyBvbmVcbmZ1bmN0aW9uIHByb21pc2lmeTxSZXN1bHQ+KFxuICBjb21tYW5kOiAoY2FsbGJhY2s6IChlcnJvcjogRXJyb3IgfCBudWxsLCByZXN1bHQ6IFJlc3VsdCkgPT4gdm9pZCkgPT4gdm9pZFxuKTogUHJvbWlzZTxSZXN1bHQ+IHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICBjb21tYW5kKGZ1bmN0aW9uIChlcnIsIHJlc3VsdCkge1xuICAgICAgZXJyID8gcmVqZWN0KGVycikgOiByZXNvbHZlKHJlc3VsdCk7XG4gICAgfSk7XG4gIH0pO1xufVxuXG50eXBlIFJlc3BvbnNlT3JFcnJvckNhbGxiYWNrID0gKFxuICBlcnJvcjogRXJyb3IgfCBudWxsLFxuICByZXNwb25zZTogTWVzc2FnZSB8IG51bGxcbikgPT4gdm9pZDtcblxuaW50ZXJmYWNlIEJhc2VDbGllbnRPcHRpb25zIHtcbiAgcmV0cmllczogbnVtYmVyO1xuICByZXRyeV9kZWxheTogbnVtYmVyO1xuICBleHBpcmVzOiBudW1iZXI7XG4gIGxvZ2dlcjogeyBsb2c6IHR5cGVvZiBjb25zb2xlLmxvZyB9O1xuICBrZXlUb1NlcnZlckhhc2hGdW5jdGlvbjogdHlwZW9mIGRlZmF1bHRLZXlUb1NlcnZlckhhc2hGdW5jdGlvbjtcbn1cblxuaW50ZXJmYWNlIFNlcmlhbGl6ZXJQcm9wPFZhbHVlLCBFeHRyYXM+IHtcbiAgc2VyaWFsaXplcjogU2VyaWFsaXplcjxWYWx1ZSwgRXh0cmFzPjtcbn1cblxuLyoqXG4gKiBUaGUgY2xpZW50IGhhcyBwYXJ0aWFsIHN1cHBvcnQgZm9yIHNlcmlhbGl6aW5nIGFuZCBkZXNlcmlhbGl6aW5nIHZhbHVlcyBmcm9tIHRoZVxuICogQnVmZmVyIGJ5dGUgc3RyaW5ncyB3ZSByZWNpZXZlIGZyb20gdGhlIHdpcmUuIFRoZSBkZWZhdWx0IHNlcmlhbGl6ZXIgaXMgZm9yIE1heWJlQnVmZmVyLlxuICpcbiAqIElmIFZhbHVlIGFuZCBFeHRyYXMgYXJlIG9mIHR5cGUgQnVmZmVyLCB0aGVuIHJldHVybiB0eXBlIFdoZW5CdWZmZXIuIE90aGVyd2lzZSxcbiAqIHJldHVybiB0eXBlIE5vdEJ1ZmZlci5cbiAqL1xudHlwZSBJZkJ1ZmZlcjxcbiAgVmFsdWUsXG4gIEV4dHJhcyxcbiAgV2hlblZhbHVlQW5kRXh0cmFzQXJlQnVmZmVycyxcbiAgTm90QnVmZmVyXG4+ID0gVmFsdWUgZXh0ZW5kcyBCdWZmZXJcbiAgPyBFeHRyYXMgZXh0ZW5kcyBCdWZmZXJcbiAgICA/IFdoZW5WYWx1ZUFuZEV4dHJhc0FyZUJ1ZmZlcnNcbiAgICA6IE5vdEJ1ZmZlclxuICA6IE5vdEJ1ZmZlcjtcblxuZXhwb3J0IHR5cGUgR2l2ZW5DbGllbnRPcHRpb25zPFZhbHVlLCBFeHRyYXM+ID0gUGFydGlhbDxCYXNlQ2xpZW50T3B0aW9ucz4gJlxuICBJZkJ1ZmZlcjxcbiAgICBWYWx1ZSxcbiAgICBFeHRyYXMsXG4gICAgUGFydGlhbDxTZXJpYWxpemVyUHJvcDxWYWx1ZSwgRXh0cmFzPj4sXG4gICAgU2VyaWFsaXplclByb3A8VmFsdWUsIEV4dHJhcz5cbiAgPjtcblxuZXhwb3J0IHR5cGUgQ0FTVG9rZW4gPSBCdWZmZXI7XG5cbmV4cG9ydCBpbnRlcmZhY2UgR2V0UmVzdWx0PFZhbHVlID0gTWF5YmVCdWZmZXIsIEV4dHJhcyA9IE1heWJlQnVmZmVyPiB7XG4gIHZhbHVlOiBWYWx1ZTtcbiAgZXh0cmFzOiBFeHRyYXM7XG4gIGNhczogQ0FTVG9rZW4gfCB1bmRlZmluZWQ7XG59XG5cbmV4cG9ydCB0eXBlIEdldE11bHRpUmVzdWx0PFxuICBLZXlzIGV4dGVuZHMgc3RyaW5nID0gc3RyaW5nLFxuICBWYWx1ZSA9IE1heWJlQnVmZmVyLFxuICBFeHRyYXMgPSBNYXliZUJ1ZmZlclxuPiA9IHtcbiAgW0sgaW4gS2V5c10/OiBHZXRSZXN1bHQ8VmFsdWUsIEV4dHJhcz47XG59O1xuXG5jbGFzcyBDbGllbnQ8VmFsdWUgPSBNYXliZUJ1ZmZlciwgRXh0cmFzID0gTWF5YmVCdWZmZXI+IHtcbiAgc2VydmVyczogU2VydmVyW107XG4gIHNlcTogbnVtYmVyO1xuICBvcHRpb25zOiBCYXNlQ2xpZW50T3B0aW9ucyAmIFBhcnRpYWw8U2VyaWFsaXplclByb3A8VmFsdWUsIEV4dHJhcz4+O1xuICBzZXJpYWxpemVyOiBTZXJpYWxpemVyPFZhbHVlLCBFeHRyYXM+O1xuICBzZXJ2ZXJNYXA6IHsgW2hvc3Rwb3J0OiBzdHJpbmddOiBTZXJ2ZXIgfTtcbiAgc2VydmVyS2V5czogc3RyaW5nW107XG5cbiAgLy8gQ2xpZW50IGluaXRpYWxpemVyIHRha2VzIGEgbGlzdCBvZiBgU2VydmVyYHMgYW5kIGFuIGBvcHRpb25zYCBkaWN0aW9uYXJ5LlxuICAvLyBTZWUgYENsaWVudC5jcmVhdGVgIGZvciBkZXRhaWxzLlxuICBjb25zdHJ1Y3RvcihzZXJ2ZXJzOiBTZXJ2ZXJbXSwgb3B0aW9uczogR2l2ZW5DbGllbnRPcHRpb25zPFZhbHVlLCBFeHRyYXM+KSB7XG4gICAgdGhpcy5zZXJ2ZXJzID0gc2VydmVycztcbiAgICB0aGlzLnNlcSA9IDA7XG4gICAgdGhpcy5vcHRpb25zID0gbWVyZ2Uob3B0aW9ucyB8fCB7fSwge1xuICAgICAgcmV0cmllczogMixcbiAgICAgIHJldHJ5X2RlbGF5OiAwLjIsXG4gICAgICBleHBpcmVzOiAwLFxuICAgICAgbG9nZ2VyOiBjb25zb2xlLFxuICAgICAga2V5VG9TZXJ2ZXJIYXNoRnVuY3Rpb246IGRlZmF1bHRLZXlUb1NlcnZlckhhc2hGdW5jdGlvbixcbiAgICB9KTtcblxuICAgIHRoaXMuc2VyaWFsaXplciA9IHRoaXMub3B0aW9ucy5zZXJpYWxpemVyIHx8IChub29wU2VyaWFsaXplciBhcyBhbnkpO1xuXG4gICAgLy8gU3RvcmUgYSBtYXBwaW5nIGZyb20gaG9zdHBvcnQgLT4gc2VydmVyIHNvIHdlIGNhbiBxdWlja2x5IGdldCBhIHNlcnZlciBvYmplY3QgZnJvbSB0aGUgc2VydmVyS2V5IHJldHVybmVkIGJ5IHRoZSBoYXNoaW5nIGZ1bmN0aW9uXG4gICAgY29uc3Qgc2VydmVyTWFwOiB7IFtob3N0cG9ydDogc3RyaW5nXTogU2VydmVyIH0gPSB7fTtcbiAgICB0aGlzLnNlcnZlcnMuZm9yRWFjaChmdW5jdGlvbiAoc2VydmVyKSB7XG4gICAgICBzZXJ2ZXJNYXBbc2VydmVyLmhvc3Rwb3J0U3RyaW5nKCldID0gc2VydmVyO1xuICAgIH0pO1xuICAgIHRoaXMuc2VydmVyTWFwID0gc2VydmVyTWFwO1xuXG4gICAgLy8gc3RvcmUgYSBsaXN0IG9mIGFsbCBvdXIgc2VydmVyS2V5cyBzbyB3ZSBkb24ndCBuZWVkIHRvIGNvbnN0YW50bHkgcmVhbGxvY2F0ZSB0aGlzIGFycmF5XG4gICAgdGhpcy5zZXJ2ZXJLZXlzID0gT2JqZWN0LmtleXModGhpcy5zZXJ2ZXJNYXApO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBuZXcgY2xpZW50IGdpdmVuIGFuIG9wdGlvbmFsIGNvbmZpZyBzdHJpbmcgYW5kIG9wdGlvbmFsIGhhc2ggb2ZcbiAgICogb3B0aW9ucy4gVGhlIGNvbmZpZyBzdHJpbmcgc2hvdWxkIGJlIG9mIHRoZSBmb3JtOlxuICAgKlxuICAgKiAgICAgXCJbdXNlcjpwYXNzQF1zZXJ2ZXIxWzoxMTIxMV0sW3VzZXI6cGFzc0Bdc2VydmVyMls6MTEyMTFdLC4uLlwiXG4gICAqXG4gICAqIElmIHRoZSBhcmd1bWVudCBpcyBub3QgZ2l2ZW4sIGZhbGxiYWNrIG9uIHRoZSBgTUVNQ0FDSElFUl9TRVJWRVJTYCBlbnZpcm9ubWVudFxuICAgKiB2YXJpYWJsZSwgYE1FTUNBQ0hFX1NFUlZFUlNgIGVudmlyb25tZW50IHZhcmlhYmxlIG9yIGBcImxvY2FsaG9zdDoxMTIxMVwiYC5cbiAgICpcbiAgICogVGhlIG9wdGlvbnMgaGFzaCBtYXkgY29udGFpbiB0aGUgb3B0aW9uczpcbiAgICpcbiAgICogKiBgcmV0cmllc2AgLSB0aGUgbnVtYmVyIG9mIHRpbWVzIHRvIHJldHJ5IGFuIG9wZXJhdGlvbiBpbiBsaWV1IG9mIGZhaWx1cmVzXG4gICAqIChkZWZhdWx0IDIpXG4gICAqICogYGV4cGlyZXNgIC0gdGhlIGRlZmF1bHQgZXhwaXJhdGlvbiBpbiBzZWNvbmRzIHRvIHVzZSAoZGVmYXVsdCAwIC0gbmV2ZXJcbiAgICogZXhwaXJlKS4gSWYgYGV4cGlyZXNgIGlzIGdyZWF0ZXIgdGhhbiAzMCBkYXlzICg2MCB4IDYwIHggMjQgeCAzMCksIGl0IGlzXG4gICAqIHRyZWF0ZWQgYXMgYSBVTklYIHRpbWUgKG51bWJlciBvZiBzZWNvbmRzIHNpbmNlIEphbnVhcnkgMSwgMTk3MCkuXG4gICAqICogYGxvZ2dlcmAgLSBhIGxvZ2dlciBvYmplY3QgdGhhdCByZXNwb25kcyB0byBgbG9nKHN0cmluZylgIG1ldGhvZCBjYWxscy5cbiAgICpcbiAgICogICB+fn5+XG4gICAqICAgICBsb2cobXNnMVssIG1zZzJbLCBtc2czWy4uLl1dXSlcbiAgICogICB+fn5+XG4gICAqXG4gICAqICAgRGVmYXVsdHMgdG8gYGNvbnNvbGVgLlxuICAgKiAqIGBzZXJpYWxpemVyYCAtIHRoZSBvYmplY3Qgd2hpY2ggd2lsbCAoZGUpc2VyaWFsaXplIHRoZSBkYXRhLiBJdCBuZWVkc1xuICAgKiAgIHR3byBwdWJsaWMgbWV0aG9kczogc2VyaWFsaXplIGFuZCBkZXNlcmlhbGl6ZS4gSXQgZGVmYXVsdHMgdG8gdGhlXG4gICAqICAgbm9vcFNlcmlhbGl6ZXI6XG4gICAqXG4gICAqICAgfn5+flxuICAgKiAgIGNvbnN0IG5vb3BTZXJpYWxpemVyID0ge1xuICAgKiAgICAgc2VyaWFsaXplOiBmdW5jdGlvbiAob3Bjb2RlLCB2YWx1ZSwgZXh0cmFzKSB7XG4gICAqICAgICAgIHJldHVybiB7IHZhbHVlOiB2YWx1ZSwgZXh0cmFzOiBleHRyYXMgfTtcbiAgICogICAgIH0sXG4gICAqICAgICBkZXNlcmlhbGl6ZTogZnVuY3Rpb24gKG9wY29kZSwgdmFsdWUsIGV4dHJhcykge1xuICAgKiAgICAgICByZXR1cm4geyB2YWx1ZTogdmFsdWUsIGV4dHJhczogZXh0cmFzIH07XG4gICAqICAgICB9XG4gICAqICAgfTtcbiAgICogICB+fn5+XG4gICAqXG4gICAqIE9yIG9wdGlvbnMgZm9yIHRoZSBzZXJ2ZXJzIGluY2x1ZGluZzpcbiAgICogKiBgdXNlcm5hbWVgIGFuZCBgcGFzc3dvcmRgIGZvciBmYWxsYmFjayBTQVNMIGF1dGhlbnRpY2F0aW9uIGNyZWRlbnRpYWxzLlxuICAgKiAqIGB0aW1lb3V0YCBpbiBzZWNvbmRzIHRvIGRldGVybWluZSBmYWlsdXJlIGZvciBvcGVyYXRpb25zLiBEZWZhdWx0IGlzIDAuNVxuICAgKiAgICAgICAgICAgICBzZWNvbmRzLlxuICAgKiAqICdjb25udGltZW91dCcgaW4gc2Vjb25kcyB0byBjb25uZWN0aW9uIGZhaWx1cmUuIERlZmF1bHQgaXMgdHdpY2UgdGhlIHZhbHVlXG4gICAqICAgICAgICAgICAgICAgICBvZiBgdGltZW91dGAuXG4gICAqICogYGtlZXBBbGl2ZWAgd2hldGhlciB0byBlbmFibGUga2VlcC1hbGl2ZSBmdW5jdGlvbmFsaXR5LiBEZWZhdWx0cyB0byBmYWxzZS5cbiAgICogKiBga2VlcEFsaXZlRGVsYXlgIGluIHNlY29uZHMgdG8gdGhlIGluaXRpYWwgZGVsYXkgYmVmb3JlIHRoZSBmaXJzdCBrZWVwYWxpdmVcbiAgICogICAgICAgICAgICAgICAgICAgIHByb2JlIGlzIHNlbnQgb24gYW4gaWRsZSBzb2NrZXQuIERlZmF1bHRzIGlzIDMwIHNlY29uZHMuXG4gICAqICogYGtleVRvU2VydmVySGFzaEZ1bmN0aW9uYCBhIGZ1bmN0aW9uIHRvIG1hcCBrZXlzIHRvIHNlcnZlcnMsIHdpdGggdGhlIHNpZ25hdHVyZVxuICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoc2VydmVyS2V5czogc3RyaW5nW10sIGtleTogc3RyaW5nKTogc3RyaW5nXG4gICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgIE5PVEU6IGlmIHlvdSBuZWVkIHRvIGRvIHNvbWUgZXhwZW5zaXZlIGluaXRpYWxpemF0aW9uLCAqcGxlYXNlKiBkbyBpdCBsYXppbHkgdGhlIGZpcnN0IHRpbWUgeW91IHRoaXMgZnVuY3Rpb24gaXMgY2FsbGVkIHdpdGggYW4gYXJyYXkgb2Ygc2VydmVyS2V5cywgbm90IG9uIGV2ZXJ5IGNhbGxcbiAgICovXG4gIHN0YXRpYyBjcmVhdGU8VmFsdWUsIEV4dHJhcz4oXG4gICAgc2VydmVyc1N0cjogc3RyaW5nIHwgdW5kZWZpbmVkLFxuICAgIG9wdGlvbnM6IElmQnVmZmVyPFxuICAgICAgVmFsdWUsXG4gICAgICBFeHRyYXMsXG4gICAgICB1bmRlZmluZWQgfCAoUGFydGlhbDxTZXJ2ZXJPcHRpb25zPiAmIEdpdmVuQ2xpZW50T3B0aW9uczxWYWx1ZSwgRXh0cmFzPiksXG4gICAgICBQYXJ0aWFsPFNlcnZlck9wdGlvbnM+ICYgR2l2ZW5DbGllbnRPcHRpb25zPFZhbHVlLCBFeHRyYXM+XG4gICAgPlxuICApOiBDbGllbnQ8VmFsdWUsIEV4dHJhcz4ge1xuICAgIHNlcnZlcnNTdHIgPVxuICAgICAgc2VydmVyc1N0ciB8fFxuICAgICAgcHJvY2Vzcy5lbnYuTUVNQ0FDSElFUl9TRVJWRVJTIHx8XG4gICAgICBwcm9jZXNzLmVudi5NRU1DQUNIRV9TRVJWRVJTIHx8XG4gICAgICBcImxvY2FsaG9zdDoxMTIxMVwiO1xuICAgIGNvbnN0IHNlcnZlclVyaXMgPSBzZXJ2ZXJzU3RyLnNwbGl0KFwiLFwiKTtcbiAgICBjb25zdCBzZXJ2ZXJzID0gc2VydmVyVXJpcy5tYXAoZnVuY3Rpb24gKHVyaSkge1xuICAgICAgY29uc3QgdXJpUGFydHMgPSB1cmkuc3BsaXQoXCJAXCIpO1xuICAgICAgY29uc3QgaG9zdFBvcnQgPSB1cmlQYXJ0c1t1cmlQYXJ0cy5sZW5ndGggLSAxXS5zcGxpdChcIjpcIik7XG4gICAgICBjb25zdCB1c2VyUGFzcyA9ICh1cmlQYXJ0c1t1cmlQYXJ0cy5sZW5ndGggLSAyXSB8fCBcIlwiKS5zcGxpdChcIjpcIik7XG4gICAgICByZXR1cm4gbmV3IFNlcnZlcihcbiAgICAgICAgaG9zdFBvcnRbMF0sXG4gICAgICAgIHBhcnNlSW50KGhvc3RQb3J0WzFdIHx8IFwiMTEyMTFcIiwgMTApLFxuICAgICAgICB1c2VyUGFzc1swXSxcbiAgICAgICAgdXNlclBhc3NbMV0sXG4gICAgICAgIG9wdGlvbnNcbiAgICAgICk7XG4gICAgfSk7XG4gICAgcmV0dXJuIG5ldyBDbGllbnQoc2VydmVycywgb3B0aW9ucyBhcyBhbnkpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdpdmVuIGEgc2VydmVyS2V5IGZyb21sb29rdXBLZXlUb1NlcnZlcktleSwgcmV0dXJuIHRoZSBjb3JyZXNwb25kaW5nIFNlcnZlciBpbnN0YW5jZVxuICAgKlxuICAgKiBAcGFyYW0gIHtzdHJpbmd9IHNlcnZlcktleVxuICAgKiBAcmV0dXJucyB7U2VydmVyfVxuICAgKi9cbiAgc2VydmVyS2V5VG9TZXJ2ZXIoc2VydmVyS2V5OiBzdHJpbmcpOiBTZXJ2ZXIge1xuICAgIHJldHVybiB0aGlzLnNlcnZlck1hcFtzZXJ2ZXJLZXldO1xuICB9XG5cbiAgLyoqXG4gICAqIEdpdmVuIGEga2V5IHRvIGxvb2sgdXAgaW4gbWVtY2FjaGUsIHJldHVybiBhIHNlcnZlcktleSAoYmFzZWQgb24gc29tZVxuICAgKiBoYXNoaW5nIGZ1bmN0aW9uKSB3aGljaCBjYW4gYmUgdXNlZCB0byBpbmRleCB0aGlzLnNlcnZlck1hcFxuICAgKi9cbiAgbG9va3VwS2V5VG9TZXJ2ZXJLZXkoa2V5OiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLm9wdGlvbnMua2V5VG9TZXJ2ZXJIYXNoRnVuY3Rpb24odGhpcy5zZXJ2ZXJLZXlzLCBrZXkpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHJpZXZlcyB0aGUgdmFsdWUgYXQgdGhlIGdpdmVuIGtleSBpbiBtZW1jYWNoZS5cbiAgICovXG4gIGFzeW5jIGdldChrZXk6IHN0cmluZyk6IFByb21pc2U8R2V0UmVzdWx0PFZhbHVlLCBFeHRyYXM+IHwgbnVsbD4ge1xuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihjb25zdGFudHMuT1BfR0VULCBrZXksIFwiXCIsIFwiXCIsIHRoaXMuc2VxKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgY29uc3QgZGVzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLmRlc2VyaWFsaXplKFxuICAgICAgICAgIHJlc3BvbnNlLmhlYWRlci5vcGNvZGUsXG4gICAgICAgICAgcmVzcG9uc2UudmFsLFxuICAgICAgICAgIHJlc3BvbnNlLmV4dHJhc1xuICAgICAgICApO1xuICAgICAgICByZXR1cm4geyAuLi5kZXNlcmlhbGl6ZWQsIGNhczogcmVzcG9uc2UuaGVhZGVyLmNhcyB9O1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfTk9UX0ZPVU5EOlxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJHRVRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqIEJ1aWxkIGEgcGlwZWxpbmVkIGdldCBtdWx0aSByZXF1ZXN0IGJ5IHNlbmRpbmcgb25lIEdFVEtRIGZvciBlYWNoIGtleSAocXVpZXQsIG1lYW5pbmcgaXQgd29uJ3QgcmVzcG9uZCBpZiB0aGUgdmFsdWUgaXMgbWlzc2luZykgZm9sbG93ZWQgYnkgYSBuby1vcCB0byBmb3JjZSBhIHJlc3BvbnNlIChhbmQgdG8gZ2l2ZSB1cyBhIHNlbnRpbmVsIHJlc3BvbnNlIHRoYXQgdGhlIHBpcGVsaW5lIGlzIGRvbmUpXG4gICAqXG4gICAqIGNmIGh0dHBzOi8vZ2l0aHViLmNvbS9jb3VjaGJhc2UvbWVtY2FjaGVkL2Jsb2IvbWFzdGVyL2RvY3MvQmluYXJ5UHJvdG9jb2wubWQjMHgwZC1nZXRrcS1nZXQtd2l0aC1rZXktcXVpZXRseVxuICAgKi9cbiAgX2J1aWxkR2V0TXVsdGlSZXF1ZXN0KGtleXM6IHN0cmluZ1tdKTogQnVmZmVyIHtcbiAgICAvLyBzdGFydCBhdCAyNCBmb3IgdGhlIG5vLW9wIGNvbW1hbmQgYXQgdGhlIGVuZFxuICAgIGxldCByZXF1ZXN0U2l6ZSA9IDI0O1xuICAgIGZvciAoY29uc3Qga2V5SWR4IGluIGtleXMpIHtcbiAgICAgIHJlcXVlc3RTaXplICs9IEJ1ZmZlci5ieXRlTGVuZ3RoKGtleXNba2V5SWR4XSwgXCJ1dGY4XCIpICsgMjQ7XG4gICAgfVxuXG4gICAgY29uc3QgcmVxdWVzdCA9IEJ1ZmZlci5hbGxvYyhyZXF1ZXN0U2l6ZSk7XG5cbiAgICBsZXQgYnl0ZXNXcml0dGVuID0gMDtcbiAgICBmb3IgKGNvbnN0IGtleUlkeCBpbiBrZXlzKSB7XG4gICAgICBjb25zdCBrZXkgPSBrZXlzW2tleUlkeF07XG4gICAgICBieXRlc1dyaXR0ZW4gKz0gY29weUludG9SZXF1ZXN0QnVmZmVyKFxuICAgICAgICBjb25zdGFudHMuT1BfR0VUS1EsXG4gICAgICAgIGtleSxcbiAgICAgICAgXCJcIixcbiAgICAgICAgXCJcIixcbiAgICAgICAgdGhpcy5zZXEsXG4gICAgICAgIHJlcXVlc3QsXG4gICAgICAgIGJ5dGVzV3JpdHRlblxuICAgICAgKTtcbiAgICB9XG5cbiAgICBieXRlc1dyaXR0ZW4gKz0gY29weUludG9SZXF1ZXN0QnVmZmVyKFxuICAgICAgY29uc3RhbnRzLk9QX05PX09QLFxuICAgICAgXCJcIixcbiAgICAgIFwiXCIsXG4gICAgICBcIlwiLFxuICAgICAgdGhpcy5zZXEsXG4gICAgICByZXF1ZXN0LFxuICAgICAgYnl0ZXNXcml0dGVuXG4gICAgKTtcblxuICAgIHJldHVybiByZXF1ZXN0O1xuICB9XG5cbiAgLyoqIEV4ZWN1dGluZyBhIHBpcGVsaW5lZCAobXVsdGkpIGdldCBhZ2FpbnN0IGEgc2luZ2xlIHNlcnZlci4gVGhpcyBpcyBhIHByaXZhdGUgaW1wbGVtZW50YXRpb24gZGV0YWlsIG9mIGdldE11bHRpLiAqL1xuICBhc3luYyBfZ2V0TXVsdGlUb1NlcnZlcjxLZXlzIGV4dGVuZHMgc3RyaW5nPihcbiAgICBzZXJ2OiBTZXJ2ZXIsXG4gICAga2V5czogS2V5c1tdXG4gICk6IFByb21pc2U8R2V0TXVsdGlSZXN1bHQ8S2V5cywgVmFsdWUsIEV4dHJhcz4+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgY29uc3QgcmVzcG9uc2VNYXA6IEdldE11bHRpUmVzdWx0PHN0cmluZywgVmFsdWUsIEV4dHJhcz4gPSB7fTtcblxuICAgICAgY29uc3QgaGFuZGxlOiBPblJlc3BvbnNlQ2FsbGJhY2sgPSAocmVzcG9uc2UpID0+IHtcbiAgICAgICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICAgICAgLy8gV2hlbiB3ZSBnZXQgdGhlIG5vLW9wIHJlc3BvbnNlLCB3ZSBhcmUgZG9uZSB3aXRoIHRoaXMgb25lIGdldE11bHRpIGluIHRoZSBwZXItYmFja2VuZCBmYW4tb3V0XG4gICAgICAgICAgICBpZiAocmVzcG9uc2UuaGVhZGVyLm9wY29kZSA9PT0gY29uc3RhbnRzLk9QX05PX09QKSB7XG4gICAgICAgICAgICAgIC8vIFRoaXMgZW5zdXJlcyB0aGUgaGFuZGxlciB3aWxsIGJlIGRlbGV0ZWQgZnJvbSB0aGUgcmVzcG9uc2VDYWxsYmFja3MgbWFwIGluIHNlcnZlci5qc1xuICAgICAgICAgICAgICAvLyBUaGlzIGlzbid0IHRlY2huaWNhbGx5IG5lZWRlZCBoZXJlIGJlY2F1c2UgdGhlIGxvZ2ljIGluIHNlcnZlci5qcyBhbHNvIGNoZWNrcyBpZiB0b3RhbEJvZHlMZW5ndGggPT09IDAsIGJ1dCBvdXIgdW5pdHRlc3RzIGFyZW4ndCBncmVhdCBhYm91dCBzZXR0aW5nIHRoYXQgZmllbGQsIGFuZCBhbHNvIHRoaXMgbWFrZXMgaXQgbW9yZSBleHBsaWNpdFxuICAgICAgICAgICAgICBoYW5kbGUucXVpZXQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgcmVzb2x2ZShyZXNwb25zZU1hcCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBjb25zdCBkZXNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuZGVzZXJpYWxpemUoXG4gICAgICAgICAgICAgICAgcmVzcG9uc2UuaGVhZGVyLm9wY29kZSxcbiAgICAgICAgICAgICAgICByZXNwb25zZS52YWwsXG4gICAgICAgICAgICAgICAgcmVzcG9uc2UuZXh0cmFzXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgIGNvbnN0IGtleSA9IHJlc3BvbnNlLmtleS50b1N0cmluZygpO1xuICAgICAgICAgICAgICByZXNwb25zZU1hcFtrZXldID0geyAuLi5kZXNlcmlhbGl6ZWQsIGNhczogcmVzcG9uc2UuaGVhZGVyLmNhcyB9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHJldHVybiByZWplY3QoXG4gICAgICAgICAgICAgIHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJHRVRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cylcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH07XG4gICAgICAvLyBUaGlzIHByZXZlbnRzIHRoZSBoYW5kbGVyIGZyb20gYmVpbmcgZGVsZXRlZFxuICAgICAgLy8gYWZ0ZXIgdGhlIGZpcnN0IHJlc3BvbnNlLiBMb2dpYyBpbiBzZXJ2ZXIuanMuXG4gICAgICBoYW5kbGUucXVpZXQgPSB0cnVlO1xuXG4gICAgICBjb25zdCByZXF1ZXN0ID0gdGhpcy5fYnVpbGRHZXRNdWx0aVJlcXVlc3Qoa2V5cyk7XG4gICAgICBzZXJ2Lm9uUmVzcG9uc2UodGhpcy5zZXEsIGhhbmRsZSk7XG4gICAgICBzZXJ2Lm9uRXJyb3IodGhpcy5zZXEsIHJlamVjdCk7XG4gICAgICB0aGlzLmluY3JTZXEoKTtcbiAgICAgIHNlcnYud3JpdGUocmVxdWVzdCk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldnMgdGhlIHZhbHVlIGF0IHRoZSBnaXZlbiBrZXlzIGluIG1lbWNhY2hlZC4gUmV0dXJucyBhIG1hcCBmcm9tIHRoZVxuICAgKiByZXF1ZXN0ZWQga2V5cyB0byByZXN1bHRzLCBvciBudWxsIGlmIHRoZSBrZXkgd2FzIG5vdCBmb3VuZC5cbiAgICovXG4gIGFzeW5jIGdldE11bHRpPEtleXMgZXh0ZW5kcyBzdHJpbmc+KFxuICAgIGtleXM6IEtleXNbXVxuICApOiBQcm9taXNlPEdldE11bHRpUmVzdWx0PEtleXMsIFZhbHVlLCBFeHRyYXM+IHwgbnVsbD4ge1xuICAgIGNvbnN0IHNlcnZlcktleXRvTG9va3VwS2V5czoge1xuICAgICAgW3NlcnZlcktleTogc3RyaW5nXTogc3RyaW5nW107XG4gICAgfSA9IHt9O1xuICAgIGtleXMuZm9yRWFjaCgobG9va3VwS2V5KSA9PiB7XG4gICAgICBjb25zdCBzZXJ2ZXJLZXkgPSB0aGlzLmxvb2t1cEtleVRvU2VydmVyS2V5KGxvb2t1cEtleSk7XG4gICAgICBpZiAoIXNlcnZlcktleXRvTG9va3VwS2V5c1tzZXJ2ZXJLZXldKSB7XG4gICAgICAgIHNlcnZlcktleXRvTG9va3VwS2V5c1tzZXJ2ZXJLZXldID0gW107XG4gICAgICB9XG4gICAgICBzZXJ2ZXJLZXl0b0xvb2t1cEtleXNbc2VydmVyS2V5XS5wdXNoKGxvb2t1cEtleSk7XG4gICAgfSk7XG5cbiAgICBjb25zdCB1c2VkU2VydmVyS2V5cyA9IE9iamVjdC5rZXlzKHNlcnZlcktleXRvTG9va3VwS2V5cyk7XG4gICAgY29uc3QgcmVzdWx0cyA9IGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgdXNlZFNlcnZlcktleXMubWFwKChzZXJ2ZXJLZXkpID0+IHtcbiAgICAgICAgY29uc3Qgc2VydmVyID0gdGhpcy5zZXJ2ZXJLZXlUb1NlcnZlcihzZXJ2ZXJLZXkpO1xuICAgICAgICByZXR1cm4gdGhpcy5fZ2V0TXVsdGlUb1NlcnZlcihzZXJ2ZXIsIHNlcnZlcktleXRvTG9va3VwS2V5c1tzZXJ2ZXJLZXldKTtcbiAgICAgIH0pXG4gICAgKTtcblxuICAgIHJldHVybiBPYmplY3QuYXNzaWduKHt9LCAuLi5yZXN1bHRzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIGBrZXlgIHRvIGB2YWx1ZWAuXG4gICAqL1xuICBhc3luYyBzZXQoXG4gICAga2V5OiBzdHJpbmcsXG4gICAgdmFsdWU6IFZhbHVlLFxuICAgIG9wdGlvbnM/OiB7IGV4cGlyZXM/OiBudW1iZXI7IGNhcz86IENBU1Rva2VuIH1cbiAgKTogUHJvbWlzZTxib29sZWFuIHwgbnVsbD4ge1xuICAgIGNvbnN0IGV4cGlyZXMgPSBvcHRpb25zPy5leHBpcmVzO1xuICAgIGNvbnN0IGNhcyA9IG9wdGlvbnM/LmNhcztcblxuICAgIC8vIFRPRE86IHN1cHBvcnQgZmxhZ3NcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBleHBpcmF0aW9uID0gbWFrZUV4cGlyYXRpb24oZXhwaXJlcyB8fCB0aGlzLm9wdGlvbnMuZXhwaXJlcyk7XG4gICAgY29uc3QgZXh0cmFzID0gQnVmZmVyLmNvbmNhdChbQnVmZmVyLmZyb20oXCIwMDAwMDAwMFwiLCBcImhleFwiKSwgZXhwaXJhdGlvbl0pO1xuICAgIGNvbnN0IHNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuc2VyaWFsaXplKFxuICAgICAgY29uc3RhbnRzLk9QX1NFVCxcbiAgICAgIHZhbHVlLFxuICAgICAgZXh0cmFzXG4gICAgKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gVXRpbHMuZW5jb2RlUmVxdWVzdCh7XG4gICAgICBoZWFkZXI6IHtcbiAgICAgICAgb3Bjb2RlOiBjb25zdGFudHMuT1BfU0VULFxuICAgICAgICBvcGFxdWU6IHRoaXMuc2VxLFxuICAgICAgICBjYXMsXG4gICAgICB9LFxuICAgICAga2V5LFxuICAgICAgdmFsdWU6IHNlcmlhbGl6ZWQudmFsdWUsXG4gICAgICBleHRyYXM6IHNlcmlhbGl6ZWQuZXh0cmFzLFxuICAgIH0pO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuS0VZX0VYSVNUUzpcbiAgICAgICAgaWYgKGNhcykge1xuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiU0VUXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgICAgICB9XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiU0VUXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBBRERcbiAgICpcbiAgICogQWRkcyB0aGUgZ2l2ZW4gX2tleV8gYW5kIF92YWx1ZV8gdG8gbWVtY2FjaGUuIFRoZSBvcGVyYXRpb24gb25seSBzdWNjZWVkc1xuICAgKiBpZiB0aGUga2V5IGlzIG5vdCBhbHJlYWR5IHNldC5cbiAgICpcbiAgICogVGhlIG9wdGlvbnMgZGljdGlvbmFyeSB0YWtlczpcbiAgICogKiBfZXhwaXJlc186IG92ZXJyaWRlcyB0aGUgZGVmYXVsdCBleHBpcmF0aW9uIChzZWUgYENsaWVudC5jcmVhdGVgKSBmb3IgdGhpc1xuICAgKiAgICAgICAgICAgICAgcGFydGljdWxhciBrZXktdmFsdWUgcGFpci5cbiAgICovXG4gIGFzeW5jIGFkZChcbiAgICBrZXk6IHN0cmluZyxcbiAgICB2YWx1ZTogVmFsdWUsXG4gICAgb3B0aW9ucz86IHsgZXhwaXJlcz86IG51bWJlciB9XG4gICk6IFByb21pc2U8Ym9vbGVhbiB8IG51bGw+IHtcbiAgICAvLyBUT0RPOiBzdXBwb3J0IGZsYWdzLCBzdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBleHBpcmF0aW9uID0gbWFrZUV4cGlyYXRpb24ob3B0aW9ucz8uZXhwaXJlcyB8fCB0aGlzLm9wdGlvbnMuZXhwaXJlcyk7XG4gICAgY29uc3QgZXh0cmFzID0gQnVmZmVyLmNvbmNhdChbQnVmZmVyLmZyb20oXCIwMDAwMDAwMFwiLCBcImhleFwiKSwgZXhwaXJhdGlvbl0pO1xuXG4gICAgY29uc3Qgb3Bjb2RlID0gY29uc3RhbnRzLk9QX0FERDtcbiAgICBjb25zdCBzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLnNlcmlhbGl6ZShvcGNvZGUsIHZhbHVlLCBleHRyYXMpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgIG9wY29kZSxcbiAgICAgIGtleSxcbiAgICAgIHNlcmlhbGl6ZWQuZXh0cmFzLFxuICAgICAgc2VyaWFsaXplZC52YWx1ZSxcbiAgICAgIHRoaXMuc2VxXG4gICAgKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9FWElTVFM6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiQUREXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXBsYWNlcyB0aGUgZ2l2ZW4gX2tleV8gYW5kIF92YWx1ZV8gdG8gbWVtY2FjaGUuIFRoZSBvcGVyYXRpb24gb25seSBzdWNjZWVkc1xuICAgKiBpZiB0aGUga2V5IGlzIGFscmVhZHkgcHJlc2VudC5cbiAgICovXG4gIGFzeW5jIHJlcGxhY2UoXG4gICAga2V5OiBzdHJpbmcsXG4gICAgdmFsdWU6IFZhbHVlLFxuICAgIG9wdGlvbnM/OiB7IGV4cGlyZXM/OiBudW1iZXIgfVxuICApOiBQcm9taXNlPGJvb2xlYW4gfCBudWxsPiB7XG4gICAgLy8gVE9ETzogc3VwcG9ydCBmbGFncywgc3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgZXhwaXJhdGlvbiA9IG1ha2VFeHBpcmF0aW9uKG9wdGlvbnM/LmV4cGlyZXMgfHwgdGhpcy5vcHRpb25zLmV4cGlyZXMpO1xuICAgIGNvbnN0IGV4dHJhcyA9IEJ1ZmZlci5jb25jYXQoW0J1ZmZlci5mcm9tKFwiMDAwMDAwMDBcIiwgXCJoZXhcIiksIGV4cGlyYXRpb25dKTtcblxuICAgIGNvbnN0IG9wY29kZTogY29uc3RhbnRzLk9QID0gY29uc3RhbnRzLk9QX1JFUExBQ0U7XG4gICAgY29uc3Qgc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5zZXJpYWxpemUob3Bjb2RlLCB2YWx1ZSwgZXh0cmFzKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICBvcGNvZGUsXG4gICAgICBrZXksXG4gICAgICBzZXJpYWxpemVkLmV4dHJhcyxcbiAgICAgIHNlcmlhbGl6ZWQudmFsdWUsXG4gICAgICB0aGlzLnNlcVxuICAgICk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfTk9UX0ZPVU5EOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiUkVQTEFDRVwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRGVsZXRlcyB0aGUgZ2l2ZW4gX2tleV8gZnJvbSBtZW1jYWNoZS4gVGhlIG9wZXJhdGlvbiBvbmx5IHN1Y2NlZWRzXG4gICAqIGlmIHRoZSBrZXkgaXMgYWxyZWFkeSBwcmVzZW50LlxuICAgKi9cbiAgYXN5bmMgZGVsZXRlKGtleTogc3RyaW5nKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgLy8gVE9ETzogU3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKDQsIGtleSwgXCJcIiwgXCJcIiwgdGhpcy5zZXEpO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuXG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfTk9UX0ZPVU5EOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiREVMRVRFXCIsIHJlc3BvbnNlPy5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogSW5jcmVtZW50cyB0aGUgZ2l2ZW4gX2tleV8gaW4gbWVtY2FjaGUuXG4gICAqL1xuICBhc3luYyBpbmNyZW1lbnQoXG4gICAga2V5OiBzdHJpbmcsXG4gICAgYW1vdW50OiBudW1iZXIsXG4gICAgb3B0aW9ucz86IHsgaW5pdGlhbD86IG51bWJlcjsgZXhwaXJlcz86IG51bWJlciB9XG4gICk6IFByb21pc2U8eyB2YWx1ZTogbnVtYmVyIHwgbnVsbDsgc3VjY2VzczogYm9vbGVhbiB8IG51bGwgfT4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IGluaXRpYWwgPSBvcHRpb25zPy5pbml0aWFsIHx8IDA7XG4gICAgY29uc3QgZXhwaXJlcyA9IG9wdGlvbnM/LmV4cGlyZXMgfHwgdGhpcy5vcHRpb25zLmV4cGlyZXM7XG4gICAgY29uc3QgZXh0cmFzID0gbWFrZUFtb3VudEluaXRpYWxBbmRFeHBpcmF0aW9uKGFtb3VudCwgaW5pdGlhbCwgZXhwaXJlcyk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKFxuICAgICAgY29uc3RhbnRzLk9QX0lOQ1JFTUVOVCxcbiAgICAgIGtleSxcbiAgICAgIGV4dHJhcyxcbiAgICAgIFwiXCIsXG4gICAgICB0aGlzLnNlcVxuICAgICk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIGNvbnN0IGJ1ZkludCA9XG4gICAgICAgICAgKHJlc3BvbnNlLnZhbC5yZWFkVUludDMyQkUoMCkgPDwgOCkgKyByZXNwb25zZS52YWwucmVhZFVJbnQzMkJFKDQpO1xuICAgICAgICByZXR1cm4geyB2YWx1ZTogYnVmSW50LCBzdWNjZXNzOiB0cnVlIH07XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiSU5DUkVNRU5UXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBEZWNyZW1lbnRzIHRoZSBnaXZlbiBga2V5YCBpbiBtZW1jYWNoZS5cbiAgICovXG4gIGFzeW5jIGRlY3JlbWVudChcbiAgICBrZXk6IHN0cmluZyxcbiAgICBhbW91bnQ6IG51bWJlcixcbiAgICBvcHRpb25zOiB7IGluaXRpYWw/OiBudW1iZXI7IGV4cGlyZXM/OiBudW1iZXIgfVxuICApOiBQcm9taXNlPHsgdmFsdWU6IG51bWJlciB8IG51bGw7IHN1Y2Nlc3M6IGJvb2xlYW4gfCBudWxsIH0+IHtcbiAgICAvLyBUT0RPOiBzdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBpbml0aWFsID0gb3B0aW9ucy5pbml0aWFsIHx8IDA7XG4gICAgY29uc3QgZXhwaXJlcyA9IG9wdGlvbnMuZXhwaXJlcyB8fCB0aGlzLm9wdGlvbnMuZXhwaXJlcztcbiAgICBjb25zdCBleHRyYXMgPSBtYWtlQW1vdW50SW5pdGlhbEFuZEV4cGlyYXRpb24oYW1vdW50LCBpbml0aWFsLCBleHBpcmVzKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICBjb25zdGFudHMuT1BfREVDUkVNRU5ULFxuICAgICAga2V5LFxuICAgICAgZXh0cmFzLFxuICAgICAgXCJcIixcbiAgICAgIHRoaXMuc2VxXG4gICAgKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgY29uc3QgYnVmSW50ID1cbiAgICAgICAgICAocmVzcG9uc2UudmFsLnJlYWRVSW50MzJCRSgwKSA8PCA4KSArIHJlc3BvbnNlLnZhbC5yZWFkVUludDMyQkUoNCk7XG4gICAgICAgIHJldHVybiB7IHZhbHVlOiBidWZJbnQsIHN1Y2Nlc3M6IHRydWUgfTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJERUNSRU1FTlRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEFwcGVuZCB0aGUgZ2l2ZW4gX3ZhbHVlXyB0byB0aGUgdmFsdWUgYXNzb2NpYXRlZCB3aXRoIHRoZSBnaXZlbiBfa2V5XyBpblxuICAgKiBtZW1jYWNoZS4gVGhlIG9wZXJhdGlvbiBvbmx5IHN1Y2NlZWRzIGlmIHRoZSBrZXkgaXMgYWxyZWFkeSBwcmVzZW50LlxuICAgKi9cbiAgYXN5bmMgYXBwZW5kKGtleTogc3RyaW5nLCB2YWx1ZTogVmFsdWUpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAvLyBUT0RPOiBzdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBvcGNvZGU6IGNvbnN0YW50cy5PUCA9IGNvbnN0YW50cy5PUF9BUFBFTkQ7XG4gICAgY29uc3Qgc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5zZXJpYWxpemUob3Bjb2RlLCB2YWx1ZSwgXCJcIik7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKFxuICAgICAgb3Bjb2RlLFxuICAgICAga2V5LFxuICAgICAgc2VyaWFsaXplZC5leHRyYXMsXG4gICAgICBzZXJpYWxpemVkLnZhbHVlLFxuICAgICAgdGhpcy5zZXFcbiAgICApO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuS0VZX05PVF9GT1VORDpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIkFQUEVORFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUHJlcGVuZCB0aGUgZ2l2ZW4gX3ZhbHVlXyB0byB0aGUgdmFsdWUgYXNzb2NpYXRlZCB3aXRoIHRoZSBnaXZlbiBfa2V5XyBpblxuICAgKiBtZW1jYWNoZS4gVGhlIG9wZXJhdGlvbiBvbmx5IHN1Y2NlZWRzIGlmIHRoZSBrZXkgaXMgYWxyZWFkeSBwcmVzZW50LlxuICAgKi9cbiAgYXN5bmMgcHJlcGVuZChrZXk6IHN0cmluZywgdmFsdWU6IFZhbHVlKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgLy8gVE9ETzogc3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3Qgb3Bjb2RlOiBjb25zdGFudHMuT1AgPSBjb25zdGFudHMuT1BfUFJFUEVORDtcbiAgICBjb25zdCBzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLnNlcmlhbGl6ZShvcGNvZGUsIHZhbHVlLCBcIlwiKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICBvcGNvZGUsXG4gICAgICBrZXksXG4gICAgICBzZXJpYWxpemVkLmV4dHJhcyxcbiAgICAgIHNlcmlhbGl6ZWQudmFsdWUsXG4gICAgICB0aGlzLnNlcVxuICAgICk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfTk9UX0ZPVU5EOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiUFJFUEVORFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVG91Y2ggc2V0cyBhbiBleHBpcmF0aW9uIHZhbHVlLCBnaXZlbiBieSBfZXhwaXJlc18sIG9uIHRoZSBnaXZlbiBfa2V5XyBpblxuICAgKiBtZW1jYWNoZS4gVGhlIG9wZXJhdGlvbiBvbmx5IHN1Y2NlZWRzIGlmIHRoZSBrZXkgaXMgYWxyZWFkeSBwcmVzZW50LlxuICAgKi9cbiAgYXN5bmMgdG91Y2goa2V5OiBzdHJpbmcsIGV4cGlyZXM6IG51bWJlcik6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IGV4dHJhcyA9IG1ha2VFeHBpcmF0aW9uKGV4cGlyZXMgfHwgdGhpcy5vcHRpb25zLmV4cGlyZXMpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcigweDFjLCBrZXksIGV4dHJhcywgXCJcIiwgdGhpcy5zZXEpO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuS0VZX05PVF9GT1VORDpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIlRPVUNIXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBGTFVTSFxuICAgKlxuICAgKiBGbHVzaGVzIHRoZSBjYWNoZSBvbiBlYWNoIGNvbm5lY3RlZCBzZXJ2ZXIuIFRoZSBjYWxsYmFjayBzaWduYXR1cmUgaXM6XG4gICAqXG4gICAqICAgICBjYWxsYmFjayhsYXN0RXJyLCByZXN1bHRzKVxuICAgKlxuICAgKiB3aGVyZSBfbGFzdEVycl8gaXMgdGhlIGxhc3QgZXJyb3IgZW5jb3VudGVyZWQgKG9yIG51bGwsIGluIHRoZSBjb21tb24gY2FzZVxuICAgKiBvZiBubyBlcnJvcnMpLiBfcmVzdWx0c18gaXMgYSBkaWN0aW9uYXJ5IG1hcHBpbmcgYFwiaG9zdG5hbWU6cG9ydFwiYCB0byBlaXRoZXJcbiAgICogYHRydWVgIChpZiB0aGUgb3BlcmF0aW9uIHdhcyBzdWNjZXNzZnVsKSwgb3IgYW4gZXJyb3IuXG4gICAqIEBwYXJhbSBjYWxsYmFja1xuICAgKi9cbiAgZmx1c2goKTogUHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBib29sZWFuIHwgRXJyb3I+PjtcbiAgZmx1c2goXG4gICAgY2FsbGJhY2s6IChcbiAgICAgIGVycjogRXJyb3IgfCBudWxsLFxuICAgICAgcmVzdWx0czogUmVjb3JkPHN0cmluZywgYm9vbGVhbiB8IEVycm9yPlxuICAgICkgPT4gdm9pZFxuICApOiB2b2lkO1xuICBmbHVzaChcbiAgICBjYWxsYmFjaz86IChcbiAgICAgIGVycjogRXJyb3IgfCBudWxsLFxuICAgICAgcmVzdWx0czogUmVjb3JkPHN0cmluZywgYm9vbGVhbiB8IEVycm9yPlxuICAgICkgPT4gdm9pZFxuICApIHtcbiAgICBpZiAoY2FsbGJhY2sgPT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuIHByb21pc2lmeSgoY2FsbGJhY2spID0+IHtcbiAgICAgICAgdGhpcy5mbHVzaChmdW5jdGlvbiAoZXJyLCByZXN1bHRzKSB7XG4gICAgICAgICAgY2FsbGJhY2soZXJyLCByZXN1bHRzKTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9XG4gICAgLy8gVE9ETzogc3VwcG9ydCBleHBpcmF0aW9uXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKDB4MDgsIFwiXCIsIFwiXCIsIFwiXCIsIHRoaXMuc2VxKTtcbiAgICBsZXQgY291bnQgPSB0aGlzLnNlcnZlcnMubGVuZ3RoO1xuICAgIGNvbnN0IHJlc3VsdDogUmVjb3JkPHN0cmluZywgYm9vbGVhbiB8IEVycm9yPiA9IHt9O1xuICAgIGxldCBsYXN0RXJyOiBFcnJvciB8IG51bGwgPSBudWxsO1xuXG4gICAgY29uc3QgaGFuZGxlRmx1c2ggPSBmdW5jdGlvbiAoc2VxOiBudW1iZXIsIHNlcnY6IFNlcnZlcikge1xuICAgICAgc2Vydi5vblJlc3BvbnNlKHNlcSwgZnVuY3Rpb24gKC8qIHJlc3BvbnNlICovKSB7XG4gICAgICAgIGNvdW50IC09IDE7XG4gICAgICAgIHJlc3VsdFtzZXJ2Lmhvc3Rwb3J0U3RyaW5nKCldID0gdHJ1ZTtcbiAgICAgICAgaWYgKGNhbGxiYWNrICYmIGNvdW50ID09PSAwKSB7XG4gICAgICAgICAgY2FsbGJhY2sobGFzdEVyciwgcmVzdWx0KTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICBzZXJ2Lm9uRXJyb3Ioc2VxLCBmdW5jdGlvbiAoZXJyKSB7XG4gICAgICAgIGNvdW50IC09IDE7XG4gICAgICAgIGxhc3RFcnIgPSBlcnI7XG4gICAgICAgIHJlc3VsdFtzZXJ2Lmhvc3Rwb3J0U3RyaW5nKCldID0gZXJyO1xuICAgICAgICBpZiAoY2FsbGJhY2sgJiYgY291bnQgPT09IDApIHtcbiAgICAgICAgICBjYWxsYmFjayhsYXN0RXJyLCByZXN1bHQpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHNlcnYud3JpdGUocmVxdWVzdCk7XG4gICAgfTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5zZXJ2ZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBoYW5kbGVGbHVzaCh0aGlzLnNlcSwgdGhpcy5zZXJ2ZXJzW2ldKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU1RBVFNfV0lUSF9LRVlcbiAgICpcbiAgICogU2VuZHMgYSBtZW1jYWNoZSBzdGF0cyBjb21tYW5kIHdpdGggYSBrZXkgdG8gZWFjaCBjb25uZWN0ZWQgc2VydmVyLiBUaGVcbiAgICogY2FsbGJhY2sgaXMgaW52b2tlZCAqKk9OQ0UgUEVSIFNFUlZFUioqIGFuZCBoYXMgdGhlIHNpZ25hdHVyZTpcbiAgICpcbiAgICogICAgIGNhbGxiYWNrKGVyciwgc2VydmVyLCBzdGF0cylcbiAgICpcbiAgICogX3NlcnZlcl8gaXMgdGhlIGBcImhvc3RuYW1lOnBvcnRcImAgb2YgdGhlIHNlcnZlciwgYW5kIF9zdGF0c18gaXMgYSBkaWN0aW9uYXJ5XG4gICAqIG1hcHBpbmcgdGhlIHN0YXQgbmFtZSB0byB0aGUgdmFsdWUgb2YgdGhlIHN0YXRpc3RpYyBhcyBhIHN0cmluZy5cbiAgICogQHBhcmFtIGtleVxuICAgKiBAcGFyYW0gY2FsbGJhY2tcbiAgICovXG4gIHN0YXRzV2l0aEtleShcbiAgICBrZXk6IHN0cmluZyxcbiAgICBjYWxsYmFjaz86IChcbiAgICAgIGVycjogRXJyb3IgfCBudWxsLFxuICAgICAgc2VydmVyOiBzdHJpbmcsXG4gICAgICBzdGF0czogUmVjb3JkPHN0cmluZywgc3RyaW5nPiB8IG51bGxcbiAgICApID0+IHZvaWRcbiAgKTogdm9pZCB7XG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKDB4MTAsIGtleSwgXCJcIiwgXCJcIiwgdGhpcy5zZXEpO1xuXG4gICAgY29uc3QgaGFuZGxlU3RhdHMgPSAoc2VxOiBudW1iZXIsIHNlcnY6IFNlcnZlcikgPT4ge1xuICAgICAgY29uc3QgcmVzdWx0OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge307XG4gICAgICBjb25zdCBoYW5kbGU6IE9uUmVzcG9uc2VDYWxsYmFjayA9IChyZXNwb25zZSkgPT4ge1xuICAgICAgICAvLyBlbmQgb2Ygc3RhdCByZXNwb25zZXNcbiAgICAgICAgaWYgKHJlc3BvbnNlLmhlYWRlci50b3RhbEJvZHlMZW5ndGggPT09IDApIHtcbiAgICAgICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKG51bGwsIHNlcnYuaG9zdHBvcnRTdHJpbmcoKSwgcmVzdWx0KTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIC8vIHByb2Nlc3Mgc2luZ2xlIHN0YXQgbGluZSByZXNwb25zZVxuICAgICAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgICAgICByZXN1bHRbcmVzcG9uc2Uua2V5LnRvU3RyaW5nKCldID0gcmVzcG9uc2UudmFsLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgY29uc3QgZXJyb3IgPSB0aGlzLmhhbmRsZVJlc3BvbnNlRXJyb3IoXG4gICAgICAgICAgICAgIGBTVEFUUyAoJHtrZXl9KWAsXG4gICAgICAgICAgICAgIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMsXG4gICAgICAgICAgICAgIHVuZGVmaW5lZFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgICAgICBjYWxsYmFjayhlcnJvciwgc2Vydi5ob3N0cG9ydFN0cmluZygpLCBudWxsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfTtcbiAgICAgIGhhbmRsZS5xdWlldCA9IHRydWU7XG5cbiAgICAgIHNlcnYub25SZXNwb25zZShzZXEsIGhhbmRsZSk7XG4gICAgICBzZXJ2Lm9uRXJyb3Ioc2VxLCBmdW5jdGlvbiAoZXJyKSB7XG4gICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgIGNhbGxiYWNrKGVyciwgc2Vydi5ob3N0cG9ydFN0cmluZygpLCBudWxsKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICBzZXJ2LndyaXRlKHJlcXVlc3QpO1xuICAgIH07XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuc2VydmVycy5sZW5ndGg7IGkrKykge1xuICAgICAgaGFuZGxlU3RhdHModGhpcy5zZXEsIHRoaXMuc2VydmVyc1tpXSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNUQVRTXG4gICAqXG4gICAqIEZldGNoZXMgbWVtY2FjaGUgc3RhdHMgZnJvbSBlYWNoIGNvbm5lY3RlZCBzZXJ2ZXIuIFRoZSBjYWxsYmFjayBpcyBpbnZva2VkXG4gICAqICoqT05DRSBQRVIgU0VSVkVSKiogYW5kIGhhcyB0aGUgc2lnbmF0dXJlOlxuICAgKlxuICAgKiAgICAgY2FsbGJhY2soZXJyLCBzZXJ2ZXIsIHN0YXRzKVxuICAgKlxuICAgKiBfc2VydmVyXyBpcyB0aGUgYFwiaG9zdG5hbWU6cG9ydFwiYCBvZiB0aGUgc2VydmVyLCBhbmQgX3N0YXRzXyBpcyBhXG4gICAqIGRpY3Rpb25hcnkgbWFwcGluZyB0aGUgc3RhdCBuYW1lIHRvIHRoZSB2YWx1ZSBvZiB0aGUgc3RhdGlzdGljIGFzIGEgc3RyaW5nLlxuICAgKiBAcGFyYW0gY2FsbGJhY2tcbiAgICovXG4gIHN0YXRzKFxuICAgIGNhbGxiYWNrPzogKFxuICAgICAgZXJyOiBFcnJvciB8IG51bGwsXG4gICAgICBzZXJ2ZXI6IHN0cmluZyxcbiAgICAgIHN0YXRzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+IHwgbnVsbFxuICAgICkgPT4gdm9pZFxuICApOiB2b2lkIHtcbiAgICB0aGlzLnN0YXRzV2l0aEtleShcIlwiLCBjYWxsYmFjayk7XG4gIH1cblxuICAvKipcbiAgICogUkVTRVRfU1RBVFNcbiAgICpcbiAgICogUmVzZXQgdGhlIHN0YXRpc3RpY3MgZWFjaCBzZXJ2ZXIgaXMga2VlcGluZyBiYWNrIHRvIHplcm8uIFRoaXMgZG9lc24ndCBjbGVhclxuICAgKiBzdGF0cyBzdWNoIGFzIGl0ZW0gY291bnQsIGJ1dCB0ZW1wb3Jhcnkgc3RhdHMgc3VjaCBhcyB0b3RhbCBudW1iZXIgb2ZcbiAgICogY29ubmVjdGlvbnMgb3ZlciB0aW1lLlxuICAgKlxuICAgKiBUaGUgY2FsbGJhY2sgaXMgaW52b2tlZCAqKk9OQ0UgUEVSIFNFUlZFUioqIGFuZCBoYXMgdGhlIHNpZ25hdHVyZTpcbiAgICpcbiAgICogICAgIGNhbGxiYWNrKGVyciwgc2VydmVyKVxuICAgKlxuICAgKiBfc2VydmVyXyBpcyB0aGUgYFwiaG9zdG5hbWU6cG9ydFwiYCBvZiB0aGUgc2VydmVyLlxuICAgKiBAcGFyYW0gY2FsbGJhY2tcbiAgICovXG4gIHJlc2V0U3RhdHMoXG4gICAgY2FsbGJhY2s/OiAoXG4gICAgICBlcnI6IEVycm9yIHwgbnVsbCxcbiAgICAgIHNlcnZlcjogc3RyaW5nLFxuICAgICAgc3RhdHM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gfCBudWxsXG4gICAgKSA9PiB2b2lkXG4gICk6IHZvaWQge1xuICAgIHRoaXMuc3RhdHNXaXRoS2V5KFwicmVzZXRcIiwgY2FsbGJhY2spO1xuICB9XG5cbiAgLyoqXG4gICAqIFFVSVRcbiAgICpcbiAgICogQ2xvc2VzIHRoZSBjb25uZWN0aW9uIHRvIGVhY2ggc2VydmVyLCBub3RpZnlpbmcgdGhlbSBvZiB0aGlzIGludGVudGlvbi4gTm90ZVxuICAgKiB0aGF0IHF1aXQgY2FuIHJhY2UgYWdhaW5zdCBhbHJlYWR5IG91dHN0YW5kaW5nIHJlcXVlc3RzIHdoZW4gdGhvc2UgcmVxdWVzdHNcbiAgICogZmFpbCBhbmQgYXJlIHJldHJpZWQsIGxlYWRpbmcgdG8gdGhlIHF1aXQgY29tbWFuZCB3aW5uaW5nIGFuZCBjbG9zaW5nIHRoZVxuICAgKiBjb25uZWN0aW9uIGJlZm9yZSB0aGUgcmV0cmllcyBjb21wbGV0ZS5cbiAgICovXG4gIHF1aXQoKSB7XG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgLy8gVE9ETzogTmljZXIgcGVyaGFwcyB0byBkbyBRVUlUUSAoMHgxNykgYnV0IG5lZWQgYSBuZXcgY2FsbGJhY2sgZm9yIHdoZW5cbiAgICAvLyB3cml0ZSBpcyBkb25lLlxuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcigweDA3LCBcIlwiLCBcIlwiLCBcIlwiLCB0aGlzLnNlcSk7IC8vIFFVSVRcbiAgICBsZXQgc2VydjtcblxuICAgIGNvbnN0IGhhbmRsZVF1aXQgPSBmdW5jdGlvbiAoc2VxOiBudW1iZXIsIHNlcnY6IFNlcnZlcikge1xuICAgICAgc2Vydi5vblJlc3BvbnNlKHNlcSwgZnVuY3Rpb24gKC8qIHJlc3BvbnNlICovKSB7XG4gICAgICAgIHNlcnYuY2xvc2UoKTtcbiAgICAgIH0pO1xuICAgICAgc2Vydi5vbkVycm9yKHNlcSwgZnVuY3Rpb24gKC8qIGVyciAqLykge1xuICAgICAgICBzZXJ2LmNsb3NlKCk7XG4gICAgICB9KTtcbiAgICAgIHNlcnYud3JpdGUocmVxdWVzdCk7XG4gICAgfTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5zZXJ2ZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBzZXJ2ID0gdGhpcy5zZXJ2ZXJzW2ldO1xuICAgICAgaGFuZGxlUXVpdCh0aGlzLnNlcSwgc2Vydik7XG4gICAgfVxuICB9XG5cbiAgX3ZlcnNpb24oc2VydmVyOiBTZXJ2ZXIpOiBQcm9taXNlPHsgdmFsdWU6IFZhbHVlIHwgbnVsbCB9PiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIHRoaXMuaW5jclNlcSgpO1xuICAgICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKFxuICAgICAgICBjb25zdGFudHMuT1BfVkVSU0lPTixcbiAgICAgICAgXCJcIixcbiAgICAgICAgXCJcIixcbiAgICAgICAgXCJcIixcbiAgICAgICAgdGhpcy5zZXFcbiAgICAgICk7XG4gICAgICB0aGlzLnBlcmZvcm1PblNlcnZlcihzZXJ2ZXIsIHJlcXVlc3QsIHRoaXMuc2VxLCAoZXJyLCByZXNwb25zZSkgPT4ge1xuICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgcmV0dXJuIHJlamVjdChlcnIpO1xuICAgICAgICB9XG5cbiAgICAgICAgc3dpdGNoIChyZXNwb25zZSEuaGVhZGVyLnN0YXR1cykge1xuICAgICAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgICAgIC8qIFRPRE86IHRoaXMgaXMgYnVnZ2VkLCB3ZSBzaG91bGQndCB1c2UgdGhlIGRlc2VyaWFsaXplciBoZXJlLCBzaW5jZSB2ZXJzaW9uIGFsd2F5cyByZXR1cm5zIGEgdmVyc2lvbiBzdHJpbmcuXG4gICAgICAgICAgICAgVGhlIGRlc2VyaWFsaXplciBzaG91bGQgb25seSBiZSB1c2VkIG9uIHVzZXIga2V5IGRhdGEuICovXG4gICAgICAgICAgICBjb25zdCBkZXNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuZGVzZXJpYWxpemUoXG4gICAgICAgICAgICAgIHJlc3BvbnNlIS5oZWFkZXIub3Bjb2RlLFxuICAgICAgICAgICAgICByZXNwb25zZSEudmFsLFxuICAgICAgICAgICAgICByZXNwb25zZSEuZXh0cmFzXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgcmV0dXJuIHJlc29sdmUoeyB2YWx1ZTogZGVzZXJpYWxpemVkLnZhbHVlIH0pO1xuICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICByZXR1cm4gcmVqZWN0KFxuICAgICAgICAgICAgICB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiVkVSU0lPTlwiLCByZXNwb25zZSEuaGVhZGVyLnN0YXR1cylcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlcXVlc3QgdGhlIHNlcnZlciB2ZXJzaW9uIGZyb20gdGhlIFwiZmlyc3RcIiBzZXJ2ZXIgaW4gdGhlIGJhY2tlbmQgcG9vbC5cbiAgICogVGhlIHNlcnZlciByZXNwb25kcyB3aXRoIGEgcGFja2V0IGNvbnRhaW5pbmcgdGhlIHZlcnNpb24gc3RyaW5nIGluIHRoZSBib2R5IHdpdGggdGhlIGZvbGxvd2luZyBmb3JtYXQ6IFwieC55LnpcIlxuICAgKi9cbiAgdmVyc2lvbigpOiBQcm9taXNlPHsgdmFsdWU6IFZhbHVlIHwgbnVsbCB9PiB7XG4gICAgY29uc3Qgc2VydmVyID0gdGhpcy5zZXJ2ZXJLZXlUb1NlcnZlcih0aGlzLnNlcnZlcktleXNbMF0pO1xuICAgIHJldHVybiB0aGlzLl92ZXJzaW9uKHNlcnZlcik7XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldmVzIHRoZSBzZXJ2ZXIgdmVyc2lvbiBmcm9tIGFsbCB0aGUgc2VydmVyc1xuICAgKiBpbiB0aGUgYmFja2VuZCBwb29sLCBlcnJvcnMgaWYgYW55IG9uZSBvZiB0aGVtIGhhcyBhblxuICAgKiBlcnJvclxuICAgKi9cbiAgYXN5bmMgdmVyc2lvbkFsbCgpOiBQcm9taXNlPHtcbiAgICB2YWx1ZXM6IFJlY29yZDxzdHJpbmcsIFZhbHVlIHwgbnVsbD47XG4gIH0+IHtcbiAgICBjb25zdCB2ZXJzaW9uT2JqZWN0cyA9IGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgdGhpcy5zZXJ2ZXJLZXlzLm1hcCgoc2VydmVyS2V5KSA9PiB7XG4gICAgICAgIGNvbnN0IHNlcnZlciA9IHRoaXMuc2VydmVyS2V5VG9TZXJ2ZXIoc2VydmVyS2V5KTtcblxuICAgICAgICByZXR1cm4gdGhpcy5fdmVyc2lvbihzZXJ2ZXIpLnRoZW4oKHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgcmV0dXJuIHsgc2VydmVyS2V5OiBzZXJ2ZXJLZXksIHZhbHVlOiByZXNwb25zZS52YWx1ZSB9O1xuICAgICAgICB9KTtcbiAgICAgIH0pXG4gICAgKTtcbiAgICBjb25zdCB2YWx1ZXMgPSB2ZXJzaW9uT2JqZWN0cy5yZWR1Y2UoKGFjY3VtdWxhdG9yLCB2ZXJzaW9uT2JqZWN0KSA9PiB7XG4gICAgICBhY2N1bXVsYXRvclt2ZXJzaW9uT2JqZWN0LnNlcnZlcktleV0gPSB2ZXJzaW9uT2JqZWN0LnZhbHVlO1xuICAgICAgcmV0dXJuIGFjY3VtdWxhdG9yO1xuICAgIH0sIHt9IGFzIFJlY29yZDxzdHJpbmcsIFZhbHVlIHwgbnVsbD4pO1xuICAgIHJldHVybiB7IHZhbHVlczogdmFsdWVzIH07XG4gIH1cblxuICAvKipcbiAgICogQ2xvc2VzIChhYnJ1cHRseSkgY29ubmVjdGlvbnMgdG8gYWxsIHRoZSBzZXJ2ZXJzLlxuICAgKiBAc2VlIHRoaXMucXVpdFxuICAgKi9cbiAgY2xvc2UoKSB7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnNlcnZlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHRoaXMuc2VydmVyc1tpXS5jbG9zZSgpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBQZXJmb3JtIGEgZ2VuZXJpYyBzaW5nbGUgcmVzcG9uc2Ugb3BlcmF0aW9uIChnZXQsIHNldCBldGMpIG9uIG9uZSBzZXJ2ZXJcbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IGtleSB0aGUga2V5IHRvIGhhc2ggdG8gZ2V0IGEgc2VydmVyIGZyb20gdGhlIHBvb2xcbiAgICogQHBhcmFtIHtidWZmZXJ9IHJlcXVlc3QgYSBidWZmZXIgY29udGFpbmluZyB0aGUgcmVxdWVzdFxuICAgKiBAcGFyYW0ge251bWJlcn0gc2VxIHRoZSBzZXF1ZW5jZSBudW1iZXIgb2YgdGhlIG9wZXJhdGlvbi4gSXQgaXMgdXNlZCB0byBwaW4gdGhlIGNhbGxiYWNrc1xuICAgICAgICAgICAgICAgICAgICAgICAgIHRvIGEgc3BlY2lmaWMgb3BlcmF0aW9uIGFuZCBzaG91bGQgbmV2ZXIgY2hhbmdlIGR1cmluZyBhIGBwZXJmb3JtYC5cbiAgICogQHBhcmFtIHtudW1iZXI/fSByZXRyaWVzIG51bWJlciBvZiB0aW1lcyB0byByZXRyeSByZXF1ZXN0IG9uIGZhaWx1cmVcbiAgICovXG4gIHBlcmZvcm0oXG4gICAga2V5OiBzdHJpbmcsXG4gICAgcmVxdWVzdDogQnVmZmVyLFxuICAgIHNlcTogbnVtYmVyLFxuICAgIHJldHJpZXM/OiBudW1iZXJcbiAgKTogUHJvbWlzZTxNZXNzYWdlPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGNvbnN0IHNlcnZlcktleSA9IHRoaXMubG9va3VwS2V5VG9TZXJ2ZXJLZXkoa2V5KTtcbiAgICAgIGNvbnN0IHNlcnZlciA9IHRoaXMuc2VydmVyS2V5VG9TZXJ2ZXIoc2VydmVyS2V5KTtcblxuICAgICAgaWYgKCFzZXJ2ZXIpIHtcbiAgICAgICAgcmV0dXJuIHJlamVjdChuZXcgRXJyb3IoXCJObyBzZXJ2ZXJzIGF2YWlsYWJsZVwiKSk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMucGVyZm9ybU9uU2VydmVyKFxuICAgICAgICBzZXJ2ZXIsXG4gICAgICAgIHJlcXVlc3QsXG4gICAgICAgIHNlcSxcbiAgICAgICAgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgcmV0dXJuIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJlc29sdmUocmVzcG9uc2UhKTtcbiAgICAgICAgfSxcbiAgICAgICAgcmV0cmllc1xuICAgICAgKTtcbiAgICB9KTtcbiAgfVxuXG4gIHBlcmZvcm1PblNlcnZlcihcbiAgICBzZXJ2ZXI6IFNlcnZlcixcbiAgICByZXF1ZXN0OiBCdWZmZXIsXG4gICAgc2VxOiBudW1iZXIsXG4gICAgY2FsbGJhY2s6IFJlc3BvbnNlT3JFcnJvckNhbGxiYWNrLFxuICAgIHJldHJpZXM6IG51bWJlciA9IDBcbiAgKSB7XG4gICAgY29uc3QgX3RoaXMgPSB0aGlzO1xuXG4gICAgcmV0cmllcyA9IHJldHJpZXMgfHwgdGhpcy5vcHRpb25zLnJldHJpZXM7XG4gICAgY29uc3Qgb3JpZ1JldHJpZXMgPSB0aGlzLm9wdGlvbnMucmV0cmllcztcbiAgICBjb25zdCBsb2dnZXIgPSB0aGlzLm9wdGlvbnMubG9nZ2VyO1xuICAgIGNvbnN0IHJldHJ5X2RlbGF5ID0gdGhpcy5vcHRpb25zLnJldHJ5X2RlbGF5O1xuXG4gICAgY29uc3QgcmVzcG9uc2VIYW5kbGVyOiBPblJlc3BvbnNlQ2FsbGJhY2sgPSBmdW5jdGlvbiAocmVzcG9uc2UpIHtcbiAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICBjYWxsYmFjayhudWxsLCByZXNwb25zZSk7XG4gICAgICB9XG4gICAgfTtcblxuICAgIGNvbnN0IGVycm9ySGFuZGxlcjogT25FcnJvckNhbGxiYWNrID0gZnVuY3Rpb24gKGVycm9yKSB7XG4gICAgICBpZiAoLS1yZXRyaWVzID4gMCkge1xuICAgICAgICAvLyBXYWl0IGZvciByZXRyeV9kZWxheVxuICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICBfdGhpcy5wZXJmb3JtT25TZXJ2ZXIoc2VydmVyLCByZXF1ZXN0LCBzZXEsIGNhbGxiYWNrLCByZXRyaWVzKTtcbiAgICAgICAgfSwgMTAwMCAqIHJldHJ5X2RlbGF5KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGxvZ2dlci5sb2coXG4gICAgICAgICAgXCJNZW1KUzogU2VydmVyIDxcIiArXG4gICAgICAgICAgICBzZXJ2ZXIuaG9zdHBvcnRTdHJpbmcoKSArXG4gICAgICAgICAgICBcIj4gZmFpbGVkIGFmdGVyIChcIiArXG4gICAgICAgICAgICBvcmlnUmV0cmllcyArXG4gICAgICAgICAgICBcIikgcmV0cmllcyB3aXRoIGVycm9yIC0gXCIgK1xuICAgICAgICAgICAgZXJyb3IubWVzc2FnZVxuICAgICAgICApO1xuICAgICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgICBjYWxsYmFjayhlcnJvciwgbnVsbCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9O1xuXG4gICAgc2VydmVyLm9uUmVzcG9uc2Uoc2VxLCByZXNwb25zZUhhbmRsZXIpO1xuICAgIHNlcnZlci5vbkVycm9yKHNlcSwgZXJyb3JIYW5kbGVyKTtcbiAgICBzZXJ2ZXIud3JpdGUocmVxdWVzdCk7XG4gIH1cblxuICAvLyBJbmNyZW1lbnQgdGhlIHNlcSB2YWx1ZVxuICBpbmNyU2VxKCkge1xuICAgIHRoaXMuc2VxKys7XG5cbiAgICAvLyBXcmFwIGB0aGlzLnNlcWAgdG8gMzItYml0cyBzaW5jZSB0aGUgZmllbGQgd2UgZml0IGl0IGludG8gaXMgb25seSAzMi1iaXRzLlxuICAgIHRoaXMuc2VxICY9IDB4ZmZmZmZmZmY7XG4gIH1cblxuICBwcml2YXRlIGNyZWF0ZUFuZExvZ0Vycm9yKFxuICAgIGNvbW1hbmROYW1lOiBzdHJpbmcsXG4gICAgcmVzcG9uc2VTdGF0dXM6IFJlc3BvbnNlU3RhdHVzIHwgdW5kZWZpbmVkXG4gICk6IEVycm9yIHtcbiAgICBjb25zdCBlcnJvck1lc3NhZ2UgPSBgTWVtSlMgJHtjb21tYW5kTmFtZX06ICR7Y29uc3RhbnRzLnJlc3BvbnNlU3RhdHVzVG9TdHJpbmcoXG4gICAgICByZXNwb25zZVN0YXR1c1xuICAgICl9YDtcbiAgICB0aGlzLm9wdGlvbnMubG9nZ2VyLmxvZyhlcnJvck1lc3NhZ2UpO1xuICAgIHJldHVybiBuZXcgRXJyb3IoZXJyb3JNZXNzYWdlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBMb2cgYW4gZXJyb3IgdG8gdGhlIGxvZ2dlciwgdGhlbiByZXR1cm4gdGhlIGVycm9yLlxuICAgKiBJZiBhIGNhbGxiYWNrIGlzIGdpdmVuLCBjYWxsIGl0IHdpdGggY2FsbGJhY2soZXJyb3IsIG51bGwpLlxuICAgKi9cbiAgcHJpdmF0ZSBoYW5kbGVSZXNwb25zZUVycm9yKFxuICAgIGNvbW1hbmROYW1lOiBzdHJpbmcsXG4gICAgcmVzcG9uc2VTdGF0dXM6IFJlc3BvbnNlU3RhdHVzIHwgdW5kZWZpbmVkLFxuICAgIGNhbGxiYWNrOiB1bmRlZmluZWQgfCAoKGVycm9yOiBFcnJvciB8IG51bGwsIG90aGVyOiBudWxsKSA9PiB2b2lkKVxuICApOiBFcnJvciB7XG4gICAgY29uc3QgZXJyb3IgPSB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKGNvbW1hbmROYW1lLCByZXNwb25zZVN0YXR1cyk7XG4gICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICBjYWxsYmFjayhlcnJvciwgbnVsbCk7XG4gICAgfVxuICAgIHJldHVybiBlcnJvcjtcbiAgfVxufVxuXG5leHBvcnQgeyBDbGllbnQsIFNlcnZlciwgVXRpbHMsIEhlYWRlciB9O1xuIl19 \ No newline at end of file diff --git a/lib/memjs/noop-serializer.d.ts b/lib/memjs/noop-serializer.d.ts new file mode 100644 index 0000000..f4fed26 --- /dev/null +++ b/lib/memjs/noop-serializer.d.ts @@ -0,0 +1,12 @@ +import { OP } from "./constants"; +import { MaybeBuffer } from "./utils"; +export interface SerializerResult { + value: Value; + extras: Extras; +} +export interface Serializer { + serialize(opcode: OP, value: Value, extras: MaybeBuffer): SerializerResult; + deserialize(opcode: OP, value: MaybeBuffer, extras: MaybeBuffer): SerializerResult; +} +export declare const noopSerializer: Serializer; +//# sourceMappingURL=noop-serializer.d.ts.map \ No newline at end of file diff --git a/lib/memjs/noop-serializer.d.ts.map b/lib/memjs/noop-serializer.d.ts.map new file mode 100644 index 0000000..ca7319a --- /dev/null +++ b/lib/memjs/noop-serializer.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"noop-serializer.d.ts","sourceRoot":"","sources":["../../src/memjs/noop-serializer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAEtC,MAAM,WAAW,gBAAgB,CAAC,KAAK,EAAE,MAAM;IAC7C,KAAK,EAAE,KAAK,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,UAAU,CAAC,KAAK,EAAE,MAAM;IACvC,SAAS,CACP,MAAM,EAAE,EAAE,EACV,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,WAAW,GAClB,gBAAgB,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;IAC9C,WAAW,CACT,MAAM,EAAE,EAAE,EACV,KAAK,EAAE,WAAW,EAClB,MAAM,EAAE,WAAW,GAClB,gBAAgB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;CACpC;AAED,eAAO,MAAM,cAAc,EAAE,UAAU,CAAC,WAAW,EAAE,WAAW,CAO/D,CAAC"} \ No newline at end of file diff --git a/lib/memjs/noop-serializer.js b/lib/memjs/noop-serializer.js new file mode 100644 index 0000000..4a87396 --- /dev/null +++ b/lib/memjs/noop-serializer.js @@ -0,0 +1,12 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.noopSerializer = void 0; +exports.noopSerializer = { + serialize: function (opcode, value, extras) { + return { value: value, extras: extras }; + }, + deserialize: function (opcode, value, extras) { + return { value: value, extras: extras }; + }, +}; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm9vcC1zZXJpYWxpemVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL21lbWpzL25vb3Atc2VyaWFsaXplci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFxQmEsUUFBQSxjQUFjLEdBQXlDO0lBQ2xFLFNBQVMsRUFBRSxVQUFVLE1BQU0sRUFBRSxLQUFLLEVBQUUsTUFBTTtRQUN4QyxPQUFPLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLENBQUM7SUFDMUMsQ0FBQztJQUNELFdBQVcsRUFBRSxVQUFVLE1BQU0sRUFBRSxLQUFLLEVBQUUsTUFBTTtRQUMxQyxPQUFPLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLENBQUM7SUFDMUMsQ0FBQztDQUNGLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBPUCB9IGZyb20gXCIuL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgTWF5YmVCdWZmZXIgfSBmcm9tIFwiLi91dGlsc1wiO1xuXG5leHBvcnQgaW50ZXJmYWNlIFNlcmlhbGl6ZXJSZXN1bHQ8VmFsdWUsIEV4dHJhcz4ge1xuICB2YWx1ZTogVmFsdWU7XG4gIGV4dHJhczogRXh0cmFzO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFNlcmlhbGl6ZXI8VmFsdWUsIEV4dHJhcz4ge1xuICBzZXJpYWxpemUoXG4gICAgb3Bjb2RlOiBPUCxcbiAgICB2YWx1ZTogVmFsdWUsXG4gICAgZXh0cmFzOiBNYXliZUJ1ZmZlclxuICApOiBTZXJpYWxpemVyUmVzdWx0PE1heWJlQnVmZmVyLCBNYXliZUJ1ZmZlcj47XG4gIGRlc2VyaWFsaXplKFxuICAgIG9wY29kZTogT1AsXG4gICAgdmFsdWU6IE1heWJlQnVmZmVyLFxuICAgIGV4dHJhczogTWF5YmVCdWZmZXJcbiAgKTogU2VyaWFsaXplclJlc3VsdDxWYWx1ZSwgRXh0cmFzPjtcbn1cblxuZXhwb3J0IGNvbnN0IG5vb3BTZXJpYWxpemVyOiBTZXJpYWxpemVyPE1heWJlQnVmZmVyLCBNYXliZUJ1ZmZlcj4gPSB7XG4gIHNlcmlhbGl6ZTogZnVuY3Rpb24gKG9wY29kZSwgdmFsdWUsIGV4dHJhcykge1xuICAgIHJldHVybiB7IHZhbHVlOiB2YWx1ZSwgZXh0cmFzOiBleHRyYXMgfTtcbiAgfSxcbiAgZGVzZXJpYWxpemU6IGZ1bmN0aW9uIChvcGNvZGUsIHZhbHVlLCBleHRyYXMpIHtcbiAgICByZXR1cm4geyB2YWx1ZTogdmFsdWUsIGV4dHJhczogZXh0cmFzIH07XG4gIH0sXG59O1xuIl19 \ No newline at end of file diff --git a/lib/memjs/server.d.ts b/lib/memjs/server.d.ts new file mode 100644 index 0000000..53a41d6 --- /dev/null +++ b/lib/memjs/server.d.ts @@ -0,0 +1,60 @@ +/// +import net from "net"; +import events from "events"; +import { Message } from "./utils"; +export interface ServerOptions { + timeout: number; + keepAlive: boolean; + keepAliveDelay: number; + conntimeout: number; + username?: string; + password?: string; +} +declare type Seq = number; +export interface OnConnectCallback { + (socket: net.Socket): void; +} +export interface OnResponseCallback { + (message: Message): void; + quiet?: boolean; +} +export interface OnErrorCallback { + (error: Error): void; +} +export declare class Server extends events.EventEmitter { + responseBuffer: Buffer; + host: string; + port: string | number | undefined; + connected: boolean; + timeoutSet: boolean; + connectCallbacks: OnConnectCallback[]; + responseCallbacks: { + [seq: string]: OnResponseCallback; + }; + requestTimeouts: number[]; + errorCallbacks: { + [seq: string]: OnErrorCallback; + }; + options: ServerOptions; + username: string | undefined; + password: string | undefined; + _socket: net.Socket | undefined; + constructor(host: string, port?: string | number, username?: string, password?: string, options?: Partial); + onConnect(func: OnConnectCallback): void; + onResponse(seq: Seq, func: OnResponseCallback): void; + respond(response: Message): void; + onError(seq: Seq, func: OnErrorCallback): void; + error(err: Error): void; + listSasl(): void; + saslAuth(): void; + appendToBuffer(dataBuf: Buffer): Buffer; + responseHandler(dataBuf: Buffer): void; + sock(sasl: boolean, go: OnConnectCallback): void; + write(blob: Buffer): void; + writeSASL(blob: Buffer): void; + close(): void; + toString(): string; + hostportString(): string; +} +export {}; +//# sourceMappingURL=server.d.ts.map \ No newline at end of file diff --git a/lib/memjs/server.d.ts.map b/lib/memjs/server.d.ts.map new file mode 100644 index 0000000..d442462 --- /dev/null +++ b/lib/memjs/server.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/memjs/server.ts"],"names":[],"mappings":";AAAA,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAKL,OAAO,EACR,MAAM,SAAS,CAAC;AAEjB,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,aAAK,GAAG,GAAG,MAAM,CAAC;AAElB,MAAM,WAAW,iBAAiB;IAChC,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,MAAM,WAAW,kBAAkB;IACjC,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACzB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;CACtB;AAED,qBAAa,MAAO,SAAQ,MAAM,CAAC,YAAY;IAC7C,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IAClC,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;IACpB,gBAAgB,EAAE,iBAAiB,EAAE,CAAC;IACtC,iBAAiB,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,kBAAkB,CAAA;KAAE,CAAC;IACzD,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,cAAc,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,CAAA;KAAE,CAAC;IACnD,OAAO,EAAE,aAAa,CAAC;IACvB,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAE7B,OAAO,EAAE,GAAG,CAAC,MAAM,GAAG,SAAS,CAAC;gBAG9B,IAAI,EAAE,MAAM,EAEZ,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,EACtB,QAAQ,CAAC,EAAE,MAAM,EACjB,QAAQ,CAAC,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC;IAoClC,SAAS,CAAC,IAAI,EAAE,iBAAiB;IAIjC,UAAU,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,kBAAkB;IAI7C,OAAO,CAAC,QAAQ,EAAE,OAAO;IAczB,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,eAAe;IAIvC,KAAK,CAAC,GAAG,EAAE,KAAK;IAgBhB,QAAQ;IAKR,QAAQ;IAMR,cAAc,CAAC,OAAO,EAAE,MAAM;IAO9B,eAAe,CAAC,OAAO,EAAE,MAAM;IAkB/B,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,iBAAiB;IAqFzC,KAAK,CAAC,IAAI,EAAE,MAAM;IAelB,SAAS,CAAC,IAAI,EAAE,MAAM;IAMtB,KAAK;IAML,QAAQ;IAIR,cAAc;CAGf"} \ No newline at end of file diff --git a/lib/memjs/server.js b/lib/memjs/server.js new file mode 100644 index 0000000..08f2361 --- /dev/null +++ b/lib/memjs/server.js @@ -0,0 +1,251 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Server = void 0; +const net_1 = __importDefault(require("net")); +const events_1 = __importDefault(require("events")); +const utils_1 = require("./utils"); +class Server extends events_1.default.EventEmitter { + constructor(host, + /* TODO: allowing port to be string or undefined is used by the tests, but seems bad overall. */ + port, username, password, options) { + super(); + this.responseBuffer = Buffer.from([]); + this.host = host; + this.port = port; + this.connected = false; + this.timeoutSet = false; + this.connectCallbacks = []; + this.responseCallbacks = {}; + this.requestTimeouts = []; + this.errorCallbacks = {}; + this.options = utils_1.merge(options || {}, { + timeout: 0.5, + keepAlive: false, + keepAliveDelay: 30, + }); + if (this.options.conntimeout === undefined || + this.options.conntimeout === null) { + this.options.conntimeout = 2 * this.options.timeout; + } + this.username = + username || + this.options.username || + process.env.MEMCACHIER_USERNAME || + process.env.MEMCACHE_USERNAME; + this.password = + password || + this.options.password || + process.env.MEMCACHIER_PASSWORD || + process.env.MEMCACHE_PASSWORD; + return this; + } + onConnect(func) { + this.connectCallbacks.push(func); + } + onResponse(seq, func) { + this.responseCallbacks[seq] = func; + } + respond(response) { + const callback = this.responseCallbacks[response.header.opaque]; + if (!callback) { + // in case of authentication, no callback is registered + return; + } + callback(response); + if (!callback.quiet || response.header.totalBodyLength === 0) { + delete this.responseCallbacks[response.header.opaque]; + this.requestTimeouts.shift(); + delete this.errorCallbacks[response.header.opaque]; + } + } + onError(seq, func) { + this.errorCallbacks[seq] = func; + } + error(err) { + const errcalls = this.errorCallbacks; + this.connectCallbacks = []; + this.responseCallbacks = {}; + this.requestTimeouts = []; + this.errorCallbacks = {}; + this.timeoutSet = false; + if (this._socket) { + this._socket.destroy(); + delete this._socket; + } + for (let errcall of Object.values(errcalls)) { + errcall(err); + } + } + listSasl() { + const buf = utils_1.makeRequestBuffer(0x20, "", "", ""); + this.writeSASL(buf); + } + saslAuth() { + const authStr = "\x00" + this.username + "\x00" + this.password; + const buf = utils_1.makeRequestBuffer(0x21, "PLAIN", "", authStr); + this.writeSASL(buf); + } + appendToBuffer(dataBuf) { + const old = this.responseBuffer; + this.responseBuffer = Buffer.alloc(old.length + dataBuf.length); + old.copy(this.responseBuffer, 0); + dataBuf.copy(this.responseBuffer, old.length); + return this.responseBuffer; + } + responseHandler(dataBuf) { + let response = utils_1.parseMessage(this.appendToBuffer(dataBuf)); + let respLength; + while (response) { + if (response.header.opcode === 0x20) { + this.saslAuth(); + } + else if (response.header.status === 0x20 /* TODO: wtf? */) { + this.error(new Error("Memcached server authentication failed!")); + } + else if (response.header.opcode === 0x21) { + this.emit("authenticated"); + } + else { + this.respond(response); + } + respLength = response.header.totalBodyLength + 24; + this.responseBuffer = this.responseBuffer.slice(respLength); + response = utils_1.parseMessage(this.responseBuffer); + } + } + sock(sasl, go) { + const self = this; + if (!self._socket) { + // CASE 1: completely new socket + self.connected = false; + self._socket = net_1.default.connect( + /* TODO: allowing port to be string or undefined is used by the tests, but seems bad overall. */ + typeof this.port === "string" + ? parseInt(this.port, 10) + : this.port || 11211, this.host, function () { + // SASL authentication handler + self.once("authenticated", function () { + if (self._socket) { + const socket = self._socket; + self.connected = true; + // cancel connection timeout + self._socket.setTimeout(0); + self.timeoutSet = false; + // run actual request(s) + go(self._socket); + self.connectCallbacks.forEach(function (cb) { + cb(socket); + }); + self.connectCallbacks = []; + } + }); + // setup response handler + this.on("data", function (dataBuf) { + self.responseHandler(dataBuf); + }); + // kick of SASL if needed + if (self.username && self.password) { + self.listSasl(); + } + else { + self.emit("authenticated"); + } + }); + // setup error handler + self._socket.on("error", function (error) { + self.connected = false; + if (self.timeoutSet) { + if (self._socket) { + self._socket.setTimeout(0); + } + self.timeoutSet = false; + } + self._socket = undefined; + self.error(error); + }); + // setup connection timeout handler + self.timeoutSet = true; + self._socket.setTimeout(self.options.conntimeout * 1000, function () { + self.timeoutSet = false; + if (!self.connected) { + this.end(); + self._socket = undefined; + self.error(new Error("socket timed out connecting to server.")); + } + }); + // use TCP keep-alive + self._socket.setKeepAlive(self.options.keepAlive, self.options.keepAliveDelay * 1000); + } + else if (!self.connected && !sasl) { + // CASE 2: socket exists, but still connecting / authenticating + self.onConnect(go); + } + else { + // CASE 3: socket exists and connected / ready to use + go(self._socket); + } + } + write(blob) { + const self = this; + const deadline = Math.round(self.options.timeout * 1000); + this.sock(false, function (s) { + s.write(blob); + self.requestTimeouts.push(utils_1.timestamp() + deadline); + if (!self.timeoutSet) { + self.timeoutSet = true; + s.setTimeout(deadline, function () { + timeoutHandler(self, this); + }); + } + }); + } + writeSASL(blob) { + this.sock(true, function (s) { + s.write(blob); + }); + } + close() { + if (this._socket) { + this._socket.end(); + } + } + toString() { + return ""; + } + hostportString() { + return this.host + ":" + this.port; + } +} +exports.Server = Server; +// We handle tracking timeouts with an array of deadlines (requestTimeouts), as +// node doesn't like us setting up lots of timers, and using just one is more +// efficient anyway. +const timeoutHandler = function (server, sock) { + if (server.requestTimeouts.length === 0) { + // nothing active + server.timeoutSet = false; + return; + } + // some requests outstanding, check if any have timed-out + const now = utils_1.timestamp(); + const soonestTimeout = server.requestTimeouts[0]; + if (soonestTimeout <= now) { + // timeout occurred! + sock.end(); + server.connected = false; + server._socket = undefined; + server.timeoutSet = false; + server.error(new Error("socket timed out waiting on response.")); + } + else { + // no timeout! Setup next one. + const deadline = soonestTimeout - now; + sock.setTimeout(deadline, function () { + timeoutHandler(server, sock); + }); + } +}; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL21lbWpzL3NlcnZlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSw4Q0FBc0I7QUFDdEIsb0RBQTRCO0FBQzVCLG1DQU1pQjtBQTBCakIsTUFBYSxNQUFPLFNBQVEsZ0JBQU0sQ0FBQyxZQUFZO0lBZ0I3QyxZQUNFLElBQVk7SUFDWixnR0FBZ0c7SUFDaEcsSUFBc0IsRUFDdEIsUUFBaUIsRUFDakIsUUFBaUIsRUFDakIsT0FBZ0M7UUFFaEMsS0FBSyxFQUFFLENBQUM7UUFDUixJQUFJLENBQUMsY0FBYyxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDdEMsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUM7UUFDakIsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUM7UUFDakIsSUFBSSxDQUFDLFNBQVMsR0FBRyxLQUFLLENBQUM7UUFDdkIsSUFBSSxDQUFDLFVBQVUsR0FBRyxLQUFLLENBQUM7UUFDeEIsSUFBSSxDQUFDLGdCQUFnQixHQUFHLEVBQUUsQ0FBQztRQUMzQixJQUFJLENBQUMsaUJBQWlCLEdBQUcsRUFBRSxDQUFDO1FBQzVCLElBQUksQ0FBQyxlQUFlLEdBQUcsRUFBRSxDQUFDO1FBQzFCLElBQUksQ0FBQyxjQUFjLEdBQUcsRUFBRSxDQUFDO1FBQ3pCLElBQUksQ0FBQyxPQUFPLEdBQUcsYUFBSyxDQUFDLE9BQU8sSUFBSSxFQUFFLEVBQUU7WUFDbEMsT0FBTyxFQUFFLEdBQUc7WUFDWixTQUFTLEVBQUUsS0FBSztZQUNoQixjQUFjLEVBQUUsRUFBRTtTQUNuQixDQUFrQixDQUFDO1FBQ3BCLElBQ0UsSUFBSSxDQUFDLE9BQU8sQ0FBQyxXQUFXLEtBQUssU0FBUztZQUN0QyxJQUFJLENBQUMsT0FBTyxDQUFDLFdBQVcsS0FBSyxJQUFJLEVBQ2pDO1lBQ0EsSUFBSSxDQUFDLE9BQU8sQ0FBQyxXQUFXLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDO1NBQ3JEO1FBQ0QsSUFBSSxDQUFDLFFBQVE7WUFDWCxRQUFRO2dCQUNSLElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUTtnQkFDckIsT0FBTyxDQUFDLEdBQUcsQ0FBQyxtQkFBbUI7Z0JBQy9CLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUM7UUFDaEMsSUFBSSxDQUFDLFFBQVE7WUFDWCxRQUFRO2dCQUNSLElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUTtnQkFDckIsT0FBTyxDQUFDLEdBQUcsQ0FBQyxtQkFBbUI7Z0JBQy9CLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUM7UUFDaEMsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRUQsU0FBUyxDQUFDLElBQXVCO1FBQy9CLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDbkMsQ0FBQztJQUVELFVBQVUsQ0FBQyxHQUFRLEVBQUUsSUFBd0I7UUFDM0MsSUFBSSxDQUFDLGlCQUFpQixDQUFDLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQztJQUNyQyxDQUFDO0lBRUQsT0FBTyxDQUFDLFFBQWlCO1FBQ3ZCLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ2hFLElBQUksQ0FBQyxRQUFRLEVBQUU7WUFDYix1REFBdUQ7WUFDdkQsT0FBTztTQUNSO1FBQ0QsUUFBUSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ25CLElBQUksQ0FBQyxRQUFRLENBQUMsS0FBSyxJQUFJLFFBQVEsQ0FBQyxNQUFNLENBQUMsZUFBZSxLQUFLLENBQUMsRUFBRTtZQUM1RCxPQUFPLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQ3RELElBQUksQ0FBQyxlQUFlLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDN0IsT0FBTyxJQUFJLENBQUMsY0FBYyxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUM7U0FDcEQ7SUFDSCxDQUFDO0lBRUQsT0FBTyxDQUFDLEdBQVEsRUFBRSxJQUFxQjtRQUNyQyxJQUFJLENBQUMsY0FBYyxDQUFDLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQztJQUNsQyxDQUFDO0lBRUQsS0FBSyxDQUFDLEdBQVU7UUFDZCxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsY0FBYyxDQUFDO1FBQ3JDLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxFQUFFLENBQUM7UUFDM0IsSUFBSSxDQUFDLGlCQUFpQixHQUFHLEVBQUUsQ0FBQztRQUM1QixJQUFJLENBQUMsZUFBZSxHQUFHLEVBQUUsQ0FBQztRQUMxQixJQUFJLENBQUMsY0FBYyxHQUFHLEVBQUUsQ0FBQztRQUN6QixJQUFJLENBQUMsVUFBVSxHQUFHLEtBQUssQ0FBQztRQUN4QixJQUFJLElBQUksQ0FBQyxPQUFPLEVBQUU7WUFDaEIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUN2QixPQUFPLElBQUksQ0FBQyxPQUFPLENBQUM7U0FDckI7UUFDRCxLQUFLLElBQUksT0FBTyxJQUFJLE1BQU0sQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLEVBQUU7WUFDM0MsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1NBQ2Q7SUFDSCxDQUFDO0lBRUQsUUFBUTtRQUNOLE1BQU0sR0FBRyxHQUFHLHlCQUFpQixDQUFDLElBQUksRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBQ2hELElBQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDdEIsQ0FBQztJQUVELFFBQVE7UUFDTixNQUFNLE9BQU8sR0FBRyxNQUFNLEdBQUcsSUFBSSxDQUFDLFFBQVEsR0FBRyxNQUFNLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQztRQUNoRSxNQUFNLEdBQUcsR0FBRyx5QkFBaUIsQ0FBQyxJQUFJLEVBQUUsT0FBTyxFQUFFLEVBQUUsRUFBRSxPQUFPLENBQUMsQ0FBQztRQUMxRCxJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ3RCLENBQUM7SUFFRCxjQUFjLENBQUMsT0FBZTtRQUM1QixNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsY0FBYyxDQUFDO1FBQ2hDLElBQUksQ0FBQyxjQUFjLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsTUFBTSxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUNoRSxHQUFHLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDakMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsY0FBYyxFQUFFLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUM5QyxPQUFPLElBQUksQ0FBQyxjQUFjLENBQUM7SUFDN0IsQ0FBQztJQUNELGVBQWUsQ0FBQyxPQUFlO1FBQzdCLElBQUksUUFBUSxHQUFHLG9CQUFZLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO1FBQzFELElBQUksVUFBa0IsQ0FBQztRQUN2QixPQUFPLFFBQVEsRUFBRTtZQUNmLElBQUksUUFBUSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEtBQUssSUFBSSxFQUFFO2dCQUNuQyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7YUFDakI7aUJBQU0sSUFBSSxRQUFRLENBQUMsTUFBTSxDQUFDLE1BQU0sS0FBTSxJQUFZLENBQUMsZ0JBQWdCLEVBQUU7Z0JBQ3BFLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxLQUFLLENBQUMseUNBQXlDLENBQUMsQ0FBQyxDQUFDO2FBQ2xFO2lCQUFNLElBQUksUUFBUSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEtBQUssSUFBSSxFQUFFO2dCQUMxQyxJQUFJLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxDQUFDO2FBQzVCO2lCQUFNO2dCQUNMLElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUM7YUFDeEI7WUFDRCxVQUFVLEdBQUcsUUFBUSxDQUFDLE1BQU0sQ0FBQyxlQUFlLEdBQUcsRUFBRSxDQUFDO1lBQ2xELElBQUksQ0FBQyxjQUFjLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLENBQUM7WUFDNUQsUUFBUSxHQUFHLG9CQUFZLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxDQUFDO1NBQzlDO0lBQ0gsQ0FBQztJQUNELElBQUksQ0FBQyxJQUFhLEVBQUUsRUFBcUI7UUFDdkMsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDO1FBRWxCLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFO1lBQ2pCLGdDQUFnQztZQUNoQyxJQUFJLENBQUMsU0FBUyxHQUFHLEtBQUssQ0FBQztZQUN2QixJQUFJLENBQUMsT0FBTyxHQUFHLGFBQUcsQ0FBQyxPQUFPO1lBQ3hCLGdHQUFnRztZQUNoRyxPQUFPLElBQUksQ0FBQyxJQUFJLEtBQUssUUFBUTtnQkFDM0IsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQztnQkFDekIsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLElBQUksS0FBSyxFQUN0QixJQUFJLENBQUMsSUFBSSxFQUNUO2dCQUNFLDhCQUE4QjtnQkFDOUIsSUFBSSxDQUFDLElBQUksQ0FBQyxlQUFlLEVBQUU7b0JBQ3pCLElBQUksSUFBSSxDQUFDLE9BQU8sRUFBRTt3QkFDaEIsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQzt3QkFDNUIsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUM7d0JBQ3RCLDRCQUE0Qjt3QkFDNUIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUM7d0JBQzNCLElBQUksQ0FBQyxVQUFVLEdBQUcsS0FBSyxDQUFDO3dCQUN4Qix3QkFBd0I7d0JBQ3hCLEVBQUUsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7d0JBQ2pCLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLENBQUMsVUFBVSxFQUFFOzRCQUN4QyxFQUFFLENBQUMsTUFBTSxDQUFDLENBQUM7d0JBQ2IsQ0FBQyxDQUFDLENBQUM7d0JBQ0gsSUFBSSxDQUFDLGdCQUFnQixHQUFHLEVBQUUsQ0FBQztxQkFDNUI7Z0JBQ0gsQ0FBQyxDQUFDLENBQUM7Z0JBRUgseUJBQXlCO2dCQUN6QixJQUFJLENBQUMsRUFBRSxDQUFDLE1BQU0sRUFBRSxVQUFVLE9BQU87b0JBQy9CLElBQUksQ0FBQyxlQUFlLENBQUMsT0FBTyxDQUFDLENBQUM7Z0JBQ2hDLENBQUMsQ0FBQyxDQUFDO2dCQUVILHlCQUF5QjtnQkFDekIsSUFBSSxJQUFJLENBQUMsUUFBUSxJQUFJLElBQUksQ0FBQyxRQUFRLEVBQUU7b0JBQ2xDLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztpQkFDakI7cUJBQU07b0JBQ0wsSUFBSSxDQUFDLElBQUksQ0FBQyxlQUFlLENBQUMsQ0FBQztpQkFDNUI7WUFDSCxDQUFDLENBQ0YsQ0FBQztZQUVGLHNCQUFzQjtZQUN0QixJQUFJLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsVUFBVSxLQUFLO2dCQUN0QyxJQUFJLENBQUMsU0FBUyxHQUFHLEtBQUssQ0FBQztnQkFDdkIsSUFBSSxJQUFJLENBQUMsVUFBVSxFQUFFO29CQUNuQixJQUFJLElBQUksQ0FBQyxPQUFPLEVBQUU7d0JBQ2hCLElBQUksQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDO3FCQUM1QjtvQkFDRCxJQUFJLENBQUMsVUFBVSxHQUFHLEtBQUssQ0FBQztpQkFDekI7Z0JBQ0QsSUFBSSxDQUFDLE9BQU8sR0FBRyxTQUFTLENBQUM7Z0JBQ3pCLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDcEIsQ0FBQyxDQUFDLENBQUM7WUFFSCxtQ0FBbUM7WUFDbkMsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUM7WUFDdkIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQ3JCLElBQUksQ0FBQyxPQUFPLENBQUMsV0FBVyxHQUFHLElBQUksRUFDL0I7Z0JBQ0UsSUFBSSxDQUFDLFVBQVUsR0FBRyxLQUFLLENBQUM7Z0JBQ3hCLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFO29CQUNuQixJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7b0JBQ1gsSUFBSSxDQUFDLE9BQU8sR0FBRyxTQUFTLENBQUM7b0JBQ3pCLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxLQUFLLENBQUMsd0NBQXdDLENBQUMsQ0FBQyxDQUFDO2lCQUNqRTtZQUNILENBQUMsQ0FDRixDQUFDO1lBRUYscUJBQXFCO1lBQ3JCLElBQUksQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUN2QixJQUFJLENBQUMsT0FBTyxDQUFDLFNBQVMsRUFDdEIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxjQUFjLEdBQUcsSUFBSSxDQUNuQyxDQUFDO1NBQ0g7YUFBTSxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsSUFBSSxDQUFDLElBQUksRUFBRTtZQUNuQywrREFBK0Q7WUFDL0QsSUFBSSxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsQ0FBQztTQUNwQjthQUFNO1lBQ0wscURBQXFEO1lBQ3JELEVBQUUsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7U0FDbEI7SUFDSCxDQUFDO0lBRUQsS0FBSyxDQUFDLElBQVk7UUFDaEIsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDO1FBQ2xCLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDLENBQUM7UUFDekQsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsVUFBVSxDQUFDO1lBQzFCLENBQUMsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDZCxJQUFJLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxpQkFBUyxFQUFFLEdBQUcsUUFBUSxDQUFDLENBQUM7WUFDbEQsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLEVBQUU7Z0JBQ3BCLElBQUksQ0FBQyxVQUFVLEdBQUcsSUFBSSxDQUFDO2dCQUN2QixDQUFDLENBQUMsVUFBVSxDQUFDLFFBQVEsRUFBRTtvQkFDckIsY0FBYyxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQztnQkFDN0IsQ0FBQyxDQUFDLENBQUM7YUFDSjtRQUNILENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVELFNBQVMsQ0FBQyxJQUFZO1FBQ3BCLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLFVBQVUsQ0FBQztZQUN6QixDQUFDLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ2hCLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVELEtBQUs7UUFDSCxJQUFJLElBQUksQ0FBQyxPQUFPLEVBQUU7WUFDaEIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUUsQ0FBQztTQUNwQjtJQUNILENBQUM7SUFFRCxRQUFRO1FBQ04sT0FBTyxVQUFVLEdBQUcsSUFBSSxDQUFDLElBQUksR0FBRyxHQUFHLEdBQUcsSUFBSSxDQUFDLElBQUksR0FBRyxHQUFHLENBQUM7SUFDeEQsQ0FBQztJQUVELGNBQWM7UUFDWixPQUFPLElBQUksQ0FBQyxJQUFJLEdBQUcsR0FBRyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUM7SUFDckMsQ0FBQztDQUNGO0FBL1BELHdCQStQQztBQUVELCtFQUErRTtBQUMvRSw2RUFBNkU7QUFDN0Usb0JBQW9CO0FBQ3BCLE1BQU0sY0FBYyxHQUFHLFVBQVUsTUFBYyxFQUFFLElBQWdCO0lBQy9ELElBQUksTUFBTSxDQUFDLGVBQWUsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFO1FBQ3ZDLGlCQUFpQjtRQUNqQixNQUFNLENBQUMsVUFBVSxHQUFHLEtBQUssQ0FBQztRQUMxQixPQUFPO0tBQ1I7SUFFRCx5REFBeUQ7SUFDekQsTUFBTSxHQUFHLEdBQUcsaUJBQVMsRUFBRSxDQUFDO0lBQ3hCLE1BQU0sY0FBYyxHQUFHLE1BQU0sQ0FBQyxlQUFlLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFFakQsSUFBSSxjQUFjLElBQUksR0FBRyxFQUFFO1FBQ3pCLG9CQUFvQjtRQUNwQixJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7UUFDWCxNQUFNLENBQUMsU0FBUyxHQUFHLEtBQUssQ0FBQztRQUN6QixNQUFNLENBQUMsT0FBTyxHQUFHLFNBQVMsQ0FBQztRQUMzQixNQUFNLENBQUMsVUFBVSxHQUFHLEtBQUssQ0FBQztRQUMxQixNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksS0FBSyxDQUFDLHVDQUF1QyxDQUFDLENBQUMsQ0FBQztLQUNsRTtTQUFNO1FBQ0wsOEJBQThCO1FBQzlCLE1BQU0sUUFBUSxHQUFHLGNBQWMsR0FBRyxHQUFHLENBQUM7UUFDdEMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxRQUFRLEVBQUU7WUFDeEIsY0FBYyxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FBQztRQUMvQixDQUFDLENBQUMsQ0FBQztLQUNKO0FBQ0gsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IG5ldCBmcm9tIFwibmV0XCI7XG5pbXBvcnQgZXZlbnRzIGZyb20gXCJldmVudHNcIjtcbmltcG9ydCB7XG4gIG1ha2VSZXF1ZXN0QnVmZmVyLFxuICBwYXJzZU1lc3NhZ2UsXG4gIG1lcmdlLFxuICB0aW1lc3RhbXAsXG4gIE1lc3NhZ2UsXG59IGZyb20gXCIuL3V0aWxzXCI7XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2VydmVyT3B0aW9ucyB7XG4gIHRpbWVvdXQ6IG51bWJlcjtcbiAga2VlcEFsaXZlOiBib29sZWFuO1xuICBrZWVwQWxpdmVEZWxheTogbnVtYmVyO1xuICBjb25udGltZW91dDogbnVtYmVyO1xuICB1c2VybmFtZT86IHN0cmluZztcbiAgcGFzc3dvcmQ/OiBzdHJpbmc7XG59XG5cbnR5cGUgU2VxID0gbnVtYmVyO1xuXG5leHBvcnQgaW50ZXJmYWNlIE9uQ29ubmVjdENhbGxiYWNrIHtcbiAgKHNvY2tldDogbmV0LlNvY2tldCk6IHZvaWQ7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgT25SZXNwb25zZUNhbGxiYWNrIHtcbiAgKG1lc3NhZ2U6IE1lc3NhZ2UpOiB2b2lkO1xuICBxdWlldD86IGJvb2xlYW47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgT25FcnJvckNhbGxiYWNrIHtcbiAgKGVycm9yOiBFcnJvcik6IHZvaWQ7XG59XG5cbmV4cG9ydCBjbGFzcyBTZXJ2ZXIgZXh0ZW5kcyBldmVudHMuRXZlbnRFbWl0dGVyIHtcbiAgcmVzcG9uc2VCdWZmZXI6IEJ1ZmZlcjtcbiAgaG9zdDogc3RyaW5nO1xuICBwb3J0OiBzdHJpbmcgfCBudW1iZXIgfCB1bmRlZmluZWQ7XG4gIGNvbm5lY3RlZDogYm9vbGVhbjtcbiAgdGltZW91dFNldDogYm9vbGVhbjtcbiAgY29ubmVjdENhbGxiYWNrczogT25Db25uZWN0Q2FsbGJhY2tbXTtcbiAgcmVzcG9uc2VDYWxsYmFja3M6IHsgW3NlcTogc3RyaW5nXTogT25SZXNwb25zZUNhbGxiYWNrIH07XG4gIHJlcXVlc3RUaW1lb3V0czogbnVtYmVyW107XG4gIGVycm9yQ2FsbGJhY2tzOiB7IFtzZXE6IHN0cmluZ106IE9uRXJyb3JDYWxsYmFjayB9O1xuICBvcHRpb25zOiBTZXJ2ZXJPcHRpb25zO1xuICB1c2VybmFtZTogc3RyaW5nIHwgdW5kZWZpbmVkO1xuICBwYXNzd29yZDogc3RyaW5nIHwgdW5kZWZpbmVkO1xuXG4gIF9zb2NrZXQ6IG5ldC5Tb2NrZXQgfCB1bmRlZmluZWQ7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgaG9zdDogc3RyaW5nLFxuICAgIC8qIFRPRE86IGFsbG93aW5nIHBvcnQgdG8gYmUgc3RyaW5nIG9yIHVuZGVmaW5lZCBpcyB1c2VkIGJ5IHRoZSB0ZXN0cywgYnV0IHNlZW1zIGJhZCBvdmVyYWxsLiAqL1xuICAgIHBvcnQ/OiBzdHJpbmcgfCBudW1iZXIsXG4gICAgdXNlcm5hbWU/OiBzdHJpbmcsXG4gICAgcGFzc3dvcmQ/OiBzdHJpbmcsXG4gICAgb3B0aW9ucz86IFBhcnRpYWw8U2VydmVyT3B0aW9ucz5cbiAgKSB7XG4gICAgc3VwZXIoKTtcbiAgICB0aGlzLnJlc3BvbnNlQnVmZmVyID0gQnVmZmVyLmZyb20oW10pO1xuICAgIHRoaXMuaG9zdCA9IGhvc3Q7XG4gICAgdGhpcy5wb3J0ID0gcG9ydDtcbiAgICB0aGlzLmNvbm5lY3RlZCA9IGZhbHNlO1xuICAgIHRoaXMudGltZW91dFNldCA9IGZhbHNlO1xuICAgIHRoaXMuY29ubmVjdENhbGxiYWNrcyA9IFtdO1xuICAgIHRoaXMucmVzcG9uc2VDYWxsYmFja3MgPSB7fTtcbiAgICB0aGlzLnJlcXVlc3RUaW1lb3V0cyA9IFtdO1xuICAgIHRoaXMuZXJyb3JDYWxsYmFja3MgPSB7fTtcbiAgICB0aGlzLm9wdGlvbnMgPSBtZXJnZShvcHRpb25zIHx8IHt9LCB7XG4gICAgICB0aW1lb3V0OiAwLjUsXG4gICAgICBrZWVwQWxpdmU6IGZhbHNlLFxuICAgICAga2VlcEFsaXZlRGVsYXk6IDMwLFxuICAgIH0pIGFzIFNlcnZlck9wdGlvbnM7XG4gICAgaWYgKFxuICAgICAgdGhpcy5vcHRpb25zLmNvbm50aW1lb3V0ID09PSB1bmRlZmluZWQgfHxcbiAgICAgIHRoaXMub3B0aW9ucy5jb25udGltZW91dCA9PT0gbnVsbFxuICAgICkge1xuICAgICAgdGhpcy5vcHRpb25zLmNvbm50aW1lb3V0ID0gMiAqIHRoaXMub3B0aW9ucy50aW1lb3V0O1xuICAgIH1cbiAgICB0aGlzLnVzZXJuYW1lID1cbiAgICAgIHVzZXJuYW1lIHx8XG4gICAgICB0aGlzLm9wdGlvbnMudXNlcm5hbWUgfHxcbiAgICAgIHByb2Nlc3MuZW52Lk1FTUNBQ0hJRVJfVVNFUk5BTUUgfHxcbiAgICAgIHByb2Nlc3MuZW52Lk1FTUNBQ0hFX1VTRVJOQU1FO1xuICAgIHRoaXMucGFzc3dvcmQgPVxuICAgICAgcGFzc3dvcmQgfHxcbiAgICAgIHRoaXMub3B0aW9ucy5wYXNzd29yZCB8fFxuICAgICAgcHJvY2Vzcy5lbnYuTUVNQ0FDSElFUl9QQVNTV09SRCB8fFxuICAgICAgcHJvY2Vzcy5lbnYuTUVNQ0FDSEVfUEFTU1dPUkQ7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICBvbkNvbm5lY3QoZnVuYzogT25Db25uZWN0Q2FsbGJhY2spIHtcbiAgICB0aGlzLmNvbm5lY3RDYWxsYmFja3MucHVzaChmdW5jKTtcbiAgfVxuXG4gIG9uUmVzcG9uc2Uoc2VxOiBTZXEsIGZ1bmM6IE9uUmVzcG9uc2VDYWxsYmFjaykge1xuICAgIHRoaXMucmVzcG9uc2VDYWxsYmFja3Nbc2VxXSA9IGZ1bmM7XG4gIH1cblxuICByZXNwb25kKHJlc3BvbnNlOiBNZXNzYWdlKSB7XG4gICAgY29uc3QgY2FsbGJhY2sgPSB0aGlzLnJlc3BvbnNlQ2FsbGJhY2tzW3Jlc3BvbnNlLmhlYWRlci5vcGFxdWVdO1xuICAgIGlmICghY2FsbGJhY2spIHtcbiAgICAgIC8vIGluIGNhc2Ugb2YgYXV0aGVudGljYXRpb24sIG5vIGNhbGxiYWNrIGlzIHJlZ2lzdGVyZWRcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY2FsbGJhY2socmVzcG9uc2UpO1xuICAgIGlmICghY2FsbGJhY2sucXVpZXQgfHwgcmVzcG9uc2UuaGVhZGVyLnRvdGFsQm9keUxlbmd0aCA9PT0gMCkge1xuICAgICAgZGVsZXRlIHRoaXMucmVzcG9uc2VDYWxsYmFja3NbcmVzcG9uc2UuaGVhZGVyLm9wYXF1ZV07XG4gICAgICB0aGlzLnJlcXVlc3RUaW1lb3V0cy5zaGlmdCgpO1xuICAgICAgZGVsZXRlIHRoaXMuZXJyb3JDYWxsYmFja3NbcmVzcG9uc2UuaGVhZGVyLm9wYXF1ZV07XG4gICAgfVxuICB9XG5cbiAgb25FcnJvcihzZXE6IFNlcSwgZnVuYzogT25FcnJvckNhbGxiYWNrKSB7XG4gICAgdGhpcy5lcnJvckNhbGxiYWNrc1tzZXFdID0gZnVuYztcbiAgfVxuXG4gIGVycm9yKGVycjogRXJyb3IpIHtcbiAgICBjb25zdCBlcnJjYWxscyA9IHRoaXMuZXJyb3JDYWxsYmFja3M7XG4gICAgdGhpcy5jb25uZWN0Q2FsbGJhY2tzID0gW107XG4gICAgdGhpcy5yZXNwb25zZUNhbGxiYWNrcyA9IHt9O1xuICAgIHRoaXMucmVxdWVzdFRpbWVvdXRzID0gW107XG4gICAgdGhpcy5lcnJvckNhbGxiYWNrcyA9IHt9O1xuICAgIHRoaXMudGltZW91dFNldCA9IGZhbHNlO1xuICAgIGlmICh0aGlzLl9zb2NrZXQpIHtcbiAgICAgIHRoaXMuX3NvY2tldC5kZXN0cm95KCk7XG4gICAgICBkZWxldGUgdGhpcy5fc29ja2V0O1xuICAgIH1cbiAgICBmb3IgKGxldCBlcnJjYWxsIG9mIE9iamVjdC52YWx1ZXMoZXJyY2FsbHMpKSB7XG4gICAgICBlcnJjYWxsKGVycik7XG4gICAgfVxuICB9XG5cbiAgbGlzdFNhc2woKSB7XG4gICAgY29uc3QgYnVmID0gbWFrZVJlcXVlc3RCdWZmZXIoMHgyMCwgXCJcIiwgXCJcIiwgXCJcIik7XG4gICAgdGhpcy53cml0ZVNBU0woYnVmKTtcbiAgfVxuXG4gIHNhc2xBdXRoKCkge1xuICAgIGNvbnN0IGF1dGhTdHIgPSBcIlxceDAwXCIgKyB0aGlzLnVzZXJuYW1lICsgXCJcXHgwMFwiICsgdGhpcy5wYXNzd29yZDtcbiAgICBjb25zdCBidWYgPSBtYWtlUmVxdWVzdEJ1ZmZlcigweDIxLCBcIlBMQUlOXCIsIFwiXCIsIGF1dGhTdHIpO1xuICAgIHRoaXMud3JpdGVTQVNMKGJ1Zik7XG4gIH1cblxuICBhcHBlbmRUb0J1ZmZlcihkYXRhQnVmOiBCdWZmZXIpIHtcbiAgICBjb25zdCBvbGQgPSB0aGlzLnJlc3BvbnNlQnVmZmVyO1xuICAgIHRoaXMucmVzcG9uc2VCdWZmZXIgPSBCdWZmZXIuYWxsb2Mob2xkLmxlbmd0aCArIGRhdGFCdWYubGVuZ3RoKTtcbiAgICBvbGQuY29weSh0aGlzLnJlc3BvbnNlQnVmZmVyLCAwKTtcbiAgICBkYXRhQnVmLmNvcHkodGhpcy5yZXNwb25zZUJ1ZmZlciwgb2xkLmxlbmd0aCk7XG4gICAgcmV0dXJuIHRoaXMucmVzcG9uc2VCdWZmZXI7XG4gIH1cbiAgcmVzcG9uc2VIYW5kbGVyKGRhdGFCdWY6IEJ1ZmZlcikge1xuICAgIGxldCByZXNwb25zZSA9IHBhcnNlTWVzc2FnZSh0aGlzLmFwcGVuZFRvQnVmZmVyKGRhdGFCdWYpKTtcbiAgICBsZXQgcmVzcExlbmd0aDogbnVtYmVyO1xuICAgIHdoaWxlIChyZXNwb25zZSkge1xuICAgICAgaWYgKHJlc3BvbnNlLmhlYWRlci5vcGNvZGUgPT09IDB4MjApIHtcbiAgICAgICAgdGhpcy5zYXNsQXV0aCgpO1xuICAgICAgfSBlbHNlIGlmIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzID09PSAoMHgyMCBhcyBhbnkpIC8qIFRPRE86IHd0Zj8gKi8pIHtcbiAgICAgICAgdGhpcy5lcnJvcihuZXcgRXJyb3IoXCJNZW1jYWNoZWQgc2VydmVyIGF1dGhlbnRpY2F0aW9uIGZhaWxlZCFcIikpO1xuICAgICAgfSBlbHNlIGlmIChyZXNwb25zZS5oZWFkZXIub3Bjb2RlID09PSAweDIxKSB7XG4gICAgICAgIHRoaXMuZW1pdChcImF1dGhlbnRpY2F0ZWRcIik7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLnJlc3BvbmQocmVzcG9uc2UpO1xuICAgICAgfVxuICAgICAgcmVzcExlbmd0aCA9IHJlc3BvbnNlLmhlYWRlci50b3RhbEJvZHlMZW5ndGggKyAyNDtcbiAgICAgIHRoaXMucmVzcG9uc2VCdWZmZXIgPSB0aGlzLnJlc3BvbnNlQnVmZmVyLnNsaWNlKHJlc3BMZW5ndGgpO1xuICAgICAgcmVzcG9uc2UgPSBwYXJzZU1lc3NhZ2UodGhpcy5yZXNwb25zZUJ1ZmZlcik7XG4gICAgfVxuICB9XG4gIHNvY2soc2FzbDogYm9vbGVhbiwgZ286IE9uQ29ubmVjdENhbGxiYWNrKSB7XG4gICAgY29uc3Qgc2VsZiA9IHRoaXM7XG5cbiAgICBpZiAoIXNlbGYuX3NvY2tldCkge1xuICAgICAgLy8gQ0FTRSAxOiBjb21wbGV0ZWx5IG5ldyBzb2NrZXRcbiAgICAgIHNlbGYuY29ubmVjdGVkID0gZmFsc2U7XG4gICAgICBzZWxmLl9zb2NrZXQgPSBuZXQuY29ubmVjdChcbiAgICAgICAgLyogVE9ETzogYWxsb3dpbmcgcG9ydCB0byBiZSBzdHJpbmcgb3IgdW5kZWZpbmVkIGlzIHVzZWQgYnkgdGhlIHRlc3RzLCBidXQgc2VlbXMgYmFkIG92ZXJhbGwuICovXG4gICAgICAgIHR5cGVvZiB0aGlzLnBvcnQgPT09IFwic3RyaW5nXCJcbiAgICAgICAgICA/IHBhcnNlSW50KHRoaXMucG9ydCwgMTApXG4gICAgICAgICAgOiB0aGlzLnBvcnQgfHwgMTEyMTEsXG4gICAgICAgIHRoaXMuaG9zdCxcbiAgICAgICAgZnVuY3Rpb24gKHRoaXM6IG5ldC5Tb2NrZXQpIHtcbiAgICAgICAgICAvLyBTQVNMIGF1dGhlbnRpY2F0aW9uIGhhbmRsZXJcbiAgICAgICAgICBzZWxmLm9uY2UoXCJhdXRoZW50aWNhdGVkXCIsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmIChzZWxmLl9zb2NrZXQpIHtcbiAgICAgICAgICAgICAgY29uc3Qgc29ja2V0ID0gc2VsZi5fc29ja2V0O1xuICAgICAgICAgICAgICBzZWxmLmNvbm5lY3RlZCA9IHRydWU7XG4gICAgICAgICAgICAgIC8vIGNhbmNlbCBjb25uZWN0aW9uIHRpbWVvdXRcbiAgICAgICAgICAgICAgc2VsZi5fc29ja2V0LnNldFRpbWVvdXQoMCk7XG4gICAgICAgICAgICAgIHNlbGYudGltZW91dFNldCA9IGZhbHNlO1xuICAgICAgICAgICAgICAvLyBydW4gYWN0dWFsIHJlcXVlc3QocylcbiAgICAgICAgICAgICAgZ28oc2VsZi5fc29ja2V0KTtcbiAgICAgICAgICAgICAgc2VsZi5jb25uZWN0Q2FsbGJhY2tzLmZvckVhY2goZnVuY3Rpb24gKGNiKSB7XG4gICAgICAgICAgICAgICAgY2Ioc29ja2V0KTtcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIHNlbGYuY29ubmVjdENhbGxiYWNrcyA9IFtdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgLy8gc2V0dXAgcmVzcG9uc2UgaGFuZGxlclxuICAgICAgICAgIHRoaXMub24oXCJkYXRhXCIsIGZ1bmN0aW9uIChkYXRhQnVmKSB7XG4gICAgICAgICAgICBzZWxmLnJlc3BvbnNlSGFuZGxlcihkYXRhQnVmKTtcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIC8vIGtpY2sgb2YgU0FTTCBpZiBuZWVkZWRcbiAgICAgICAgICBpZiAoc2VsZi51c2VybmFtZSAmJiBzZWxmLnBhc3N3b3JkKSB7XG4gICAgICAgICAgICBzZWxmLmxpc3RTYXNsKCk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHNlbGYuZW1pdChcImF1dGhlbnRpY2F0ZWRcIik7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICApO1xuXG4gICAgICAvLyBzZXR1cCBlcnJvciBoYW5kbGVyXG4gICAgICBzZWxmLl9zb2NrZXQub24oXCJlcnJvclwiLCBmdW5jdGlvbiAoZXJyb3IpIHtcbiAgICAgICAgc2VsZi5jb25uZWN0ZWQgPSBmYWxzZTtcbiAgICAgICAgaWYgKHNlbGYudGltZW91dFNldCkge1xuICAgICAgICAgIGlmIChzZWxmLl9zb2NrZXQpIHtcbiAgICAgICAgICAgIHNlbGYuX3NvY2tldC5zZXRUaW1lb3V0KDApO1xuICAgICAgICAgIH1cbiAgICAgICAgICBzZWxmLnRpbWVvdXRTZXQgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBzZWxmLl9zb2NrZXQgPSB1bmRlZmluZWQ7XG4gICAgICAgIHNlbGYuZXJyb3IoZXJyb3IpO1xuICAgICAgfSk7XG5cbiAgICAgIC8vIHNldHVwIGNvbm5lY3Rpb24gdGltZW91dCBoYW5kbGVyXG4gICAgICBzZWxmLnRpbWVvdXRTZXQgPSB0cnVlO1xuICAgICAgc2VsZi5fc29ja2V0LnNldFRpbWVvdXQoXG4gICAgICAgIHNlbGYub3B0aW9ucy5jb25udGltZW91dCAqIDEwMDAsXG4gICAgICAgIGZ1bmN0aW9uICh0aGlzOiBuZXQuU29ja2V0KSB7XG4gICAgICAgICAgc2VsZi50aW1lb3V0U2V0ID0gZmFsc2U7XG4gICAgICAgICAgaWYgKCFzZWxmLmNvbm5lY3RlZCkge1xuICAgICAgICAgICAgdGhpcy5lbmQoKTtcbiAgICAgICAgICAgIHNlbGYuX3NvY2tldCA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIHNlbGYuZXJyb3IobmV3IEVycm9yKFwic29ja2V0IHRpbWVkIG91dCBjb25uZWN0aW5nIHRvIHNlcnZlci5cIikpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgKTtcblxuICAgICAgLy8gdXNlIFRDUCBrZWVwLWFsaXZlXG4gICAgICBzZWxmLl9zb2NrZXQuc2V0S2VlcEFsaXZlKFxuICAgICAgICBzZWxmLm9wdGlvbnMua2VlcEFsaXZlLFxuICAgICAgICBzZWxmLm9wdGlvbnMua2VlcEFsaXZlRGVsYXkgKiAxMDAwXG4gICAgICApO1xuICAgIH0gZWxzZSBpZiAoIXNlbGYuY29ubmVjdGVkICYmICFzYXNsKSB7XG4gICAgICAvLyBDQVNFIDI6IHNvY2tldCBleGlzdHMsIGJ1dCBzdGlsbCBjb25uZWN0aW5nIC8gYXV0aGVudGljYXRpbmdcbiAgICAgIHNlbGYub25Db25uZWN0KGdvKTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gQ0FTRSAzOiBzb2NrZXQgZXhpc3RzIGFuZCBjb25uZWN0ZWQgLyByZWFkeSB0byB1c2VcbiAgICAgIGdvKHNlbGYuX3NvY2tldCk7XG4gICAgfVxuICB9XG5cbiAgd3JpdGUoYmxvYjogQnVmZmVyKSB7XG4gICAgY29uc3Qgc2VsZiA9IHRoaXM7XG4gICAgY29uc3QgZGVhZGxpbmUgPSBNYXRoLnJvdW5kKHNlbGYub3B0aW9ucy50aW1lb3V0ICogMTAwMCk7XG4gICAgdGhpcy5zb2NrKGZhbHNlLCBmdW5jdGlvbiAocykge1xuICAgICAgcy53cml0ZShibG9iKTtcbiAgICAgIHNlbGYucmVxdWVzdFRpbWVvdXRzLnB1c2godGltZXN0YW1wKCkgKyBkZWFkbGluZSk7XG4gICAgICBpZiAoIXNlbGYudGltZW91dFNldCkge1xuICAgICAgICBzZWxmLnRpbWVvdXRTZXQgPSB0cnVlO1xuICAgICAgICBzLnNldFRpbWVvdXQoZGVhZGxpbmUsIGZ1bmN0aW9uICh0aGlzOiBuZXQuU29ja2V0KSB7XG4gICAgICAgICAgdGltZW91dEhhbmRsZXIoc2VsZiwgdGhpcyk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgd3JpdGVTQVNMKGJsb2I6IEJ1ZmZlcikge1xuICAgIHRoaXMuc29jayh0cnVlLCBmdW5jdGlvbiAocykge1xuICAgICAgcy53cml0ZShibG9iKTtcbiAgICB9KTtcbiAgfVxuXG4gIGNsb3NlKCkge1xuICAgIGlmICh0aGlzLl9zb2NrZXQpIHtcbiAgICAgIHRoaXMuX3NvY2tldC5lbmQoKTtcbiAgICB9XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICByZXR1cm4gXCI8U2VydmVyIFwiICsgdGhpcy5ob3N0ICsgXCI6XCIgKyB0aGlzLnBvcnQgKyBcIj5cIjtcbiAgfVxuXG4gIGhvc3Rwb3J0U3RyaW5nKCkge1xuICAgIHJldHVybiB0aGlzLmhvc3QgKyBcIjpcIiArIHRoaXMucG9ydDtcbiAgfVxufVxuXG4vLyBXZSBoYW5kbGUgdHJhY2tpbmcgdGltZW91dHMgd2l0aCBhbiBhcnJheSBvZiBkZWFkbGluZXMgKHJlcXVlc3RUaW1lb3V0cyksIGFzXG4vLyBub2RlIGRvZXNuJ3QgbGlrZSB1cyBzZXR0aW5nIHVwIGxvdHMgb2YgdGltZXJzLCBhbmQgdXNpbmcganVzdCBvbmUgaXMgbW9yZVxuLy8gZWZmaWNpZW50IGFueXdheS5cbmNvbnN0IHRpbWVvdXRIYW5kbGVyID0gZnVuY3Rpb24gKHNlcnZlcjogU2VydmVyLCBzb2NrOiBuZXQuU29ja2V0KSB7XG4gIGlmIChzZXJ2ZXIucmVxdWVzdFRpbWVvdXRzLmxlbmd0aCA9PT0gMCkge1xuICAgIC8vIG5vdGhpbmcgYWN0aXZlXG4gICAgc2VydmVyLnRpbWVvdXRTZXQgPSBmYWxzZTtcbiAgICByZXR1cm47XG4gIH1cblxuICAvLyBzb21lIHJlcXVlc3RzIG91dHN0YW5kaW5nLCBjaGVjayBpZiBhbnkgaGF2ZSB0aW1lZC1vdXRcbiAgY29uc3Qgbm93ID0gdGltZXN0YW1wKCk7XG4gIGNvbnN0IHNvb25lc3RUaW1lb3V0ID0gc2VydmVyLnJlcXVlc3RUaW1lb3V0c1swXTtcblxuICBpZiAoc29vbmVzdFRpbWVvdXQgPD0gbm93KSB7XG4gICAgLy8gdGltZW91dCBvY2N1cnJlZCFcbiAgICBzb2NrLmVuZCgpO1xuICAgIHNlcnZlci5jb25uZWN0ZWQgPSBmYWxzZTtcbiAgICBzZXJ2ZXIuX3NvY2tldCA9IHVuZGVmaW5lZDtcbiAgICBzZXJ2ZXIudGltZW91dFNldCA9IGZhbHNlO1xuICAgIHNlcnZlci5lcnJvcihuZXcgRXJyb3IoXCJzb2NrZXQgdGltZWQgb3V0IHdhaXRpbmcgb24gcmVzcG9uc2UuXCIpKTtcbiAgfSBlbHNlIHtcbiAgICAvLyBubyB0aW1lb3V0ISBTZXR1cCBuZXh0IG9uZS5cbiAgICBjb25zdCBkZWFkbGluZSA9IHNvb25lc3RUaW1lb3V0IC0gbm93O1xuICAgIHNvY2suc2V0VGltZW91dChkZWFkbGluZSwgZnVuY3Rpb24gKCkge1xuICAgICAgdGltZW91dEhhbmRsZXIoc2VydmVyLCBzb2NrKTtcbiAgICB9KTtcbiAgfVxufTtcbiJdfQ== \ No newline at end of file diff --git a/lib/memjs/utils.d.ts b/lib/memjs/utils.d.ts new file mode 100644 index 0000000..d7c3c28 --- /dev/null +++ b/lib/memjs/utils.d.ts @@ -0,0 +1,29 @@ +/// +import * as header from "./header"; +import { OP } from "./constants"; +export declare type MaybeBuffer = string | Buffer; +export declare const bufferify: (val: MaybeBuffer) => Buffer; +export interface EncodableRequest { + header: Omit; + key: MaybeBuffer; + extras: MaybeBuffer; + value: MaybeBuffer; +} +export declare function encodeRequestIntoBuffer(buffer: Buffer, offset: number, request: EncodableRequest): number; +export declare function encodeRequest(request: EncodableRequest): Buffer; +export declare const copyIntoRequestBuffer: (opcode: OP, key: MaybeBuffer, extras: MaybeBuffer, value: MaybeBuffer, opaque: number, buf: Buffer, _bufTargetWriteOffset?: number | undefined) => number; +export declare const makeRequestBuffer: (opcode: OP, key: MaybeBuffer, extras: MaybeBuffer, value: MaybeBuffer, opaque?: number | undefined) => Buffer; +export declare const makeAmountInitialAndExpiration: (amount: number, amountIfEmpty: number, expiration: number) => Buffer; +export declare const makeExpiration: (expiration: number) => Buffer; +export declare const hashCode: (str: string) => number; +export interface Message { + header: header.Header; + key: Buffer; + val: Buffer; + extras: Buffer; +} +export declare const parseMessage: (dataBuf: Buffer) => Message | false; +export declare const parseMessages: (dataBuf: Buffer) => Message[]; +export declare const merge: (original: any, deflt: T) => T; +export declare const timestamp: () => number; +//# sourceMappingURL=utils.d.ts.map \ No newline at end of file diff --git a/lib/memjs/utils.d.ts.map b/lib/memjs/utils.d.ts.map new file mode 100644 index 0000000..98971d9 --- /dev/null +++ b/lib/memjs/utils.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/memjs/utils.ts"],"names":[],"mappings":";AAEA,OAAO,KAAK,MAAM,MAAM,UAAU,CAAC;AACnC,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AAEjC,oBAAY,WAAW,GAAG,MAAM,GAAG,MAAM,CAAC;AAE1C,eAAO,MAAM,SAAS,QAAkB,WAAW,WAElD,CAAC;AAEF,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,IAAI,CACV,MAAM,CAAC,MAAM,EACb,OAAO,GAAG,WAAW,GAAG,cAAc,GAAG,iBAAiB,CAC3D,CAAC;IACF,GAAG,EAAE,WAAW,CAAC;IACjB,MAAM,EAAE,WAAW,CAAC;IACpB,KAAK,EAAE,WAAW,CAAC;CACpB;AAED,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,gBAAgB,UAgC1B;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,gBAAgB,GAAG,MAAM,CAa/D;AAED,eAAO,MAAM,qBAAqB,WACxB,EAAE,OACL,WAAW,UACR,WAAW,SACZ,WAAW,UACV,MAAM,OACT,MAAM,uDAYZ,CAAC;AAEF,eAAO,MAAM,iBAAiB,WACpB,EAAE,OACL,WAAW,UACR,WAAW,SACZ,WAAW,wCAYnB,CAAC;AAEF,eAAO,MAAM,8BAA8B,WACjC,MAAM,iBACC,MAAM,cACT,MAAM,WASnB,CAAC;AAEF,eAAO,MAAM,cAAc,eAAyB,MAAM,WAIzD,CAAC;AAEF,eAAO,MAAM,QAAQ,QAAkB,MAAM,WAM5C,CAAC;AAEF,MAAM,WAAW,OAAO;IACtB,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,eAAO,MAAM,YAAY,YAAsB,MAAM,KAAG,OAAO,GAAG,KAsBjE,CAAC;AAEF,eAAO,MAAM,aAAa,YAAsB,MAAM,KAAG,OAAO,EAe/D,CAAC;AAEF,eAAO,MAAM,KAAK,gBAA0B,GAAG,gBAU9C,CAAC;AAIF,eAAO,MAAM,SAAS,cAGrB,CAAC"} \ No newline at end of file diff --git a/lib/memjs/utils.js b/lib/memjs/utils.js new file mode 100644 index 0000000..9f71eb2 --- /dev/null +++ b/lib/memjs/utils.js @@ -0,0 +1,198 @@ +"use strict"; +// # MemJS utility functions +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.timestamp = exports.merge = exports.parseMessages = exports.parseMessage = exports.hashCode = exports.makeExpiration = exports.makeAmountInitialAndExpiration = exports.makeRequestBuffer = exports.copyIntoRequestBuffer = exports.encodeRequest = exports.encodeRequestIntoBuffer = exports.bufferify = void 0; +const header = __importStar(require("./header")); +const bufferify = function (val) { + return Buffer.isBuffer(val) ? val : Buffer.from(val); +}; +exports.bufferify = bufferify; +function encodeRequestIntoBuffer(buffer, offset, request) { + const key = exports.bufferify(request.key); + const extras = exports.bufferify(request.extras); + const value = exports.bufferify(request.value); + const bufTargetWriteOffset = offset || 0; + let totalBytesWritten = 0; + function copyIntoBuffer(toWriteBuffer) { + const bytesWritten = toWriteBuffer.copy(buffer, bufTargetWriteOffset + totalBytesWritten); + totalBytesWritten += bytesWritten; + } + const requestHeader = { + ...request.header, + magic: 0x80, + keyLength: key.length, + extrasLength: extras.length, + totalBodyLength: key.length + value.length + extras.length, + }; + const headerBuffer = header.toBuffer(requestHeader); + copyIntoBuffer(headerBuffer); + copyIntoBuffer(extras); + copyIntoBuffer(key); + copyIntoBuffer(value); + return totalBytesWritten; +} +exports.encodeRequestIntoBuffer = encodeRequestIntoBuffer; +function encodeRequest(request) { + const key = exports.bufferify(request.key); + const extras = exports.bufferify(request.extras); + const value = exports.bufferify(request.value); + const bufSize = 24 + key.length + extras.length + value.length; + const buffer = Buffer.alloc(bufSize); + encodeRequestIntoBuffer(buffer, 0, { + ...request, + key, + extras, + value, + }); + return buffer; +} +exports.encodeRequest = encodeRequest; +const copyIntoRequestBuffer = function (opcode, key, extras, value, opaque, buf, _bufTargetWriteOffset) { + return encodeRequestIntoBuffer(buf, _bufTargetWriteOffset || 0, { + header: { + opcode, + opaque, + }, + key, + extras, + value, + }); +}; +exports.copyIntoRequestBuffer = copyIntoRequestBuffer; +const makeRequestBuffer = function (opcode, key, extras, value, opaque) { + return encodeRequest({ + extras, + key, + value, + header: { + opcode, + opaque: opaque || 0, + }, + }); +}; +exports.makeRequestBuffer = makeRequestBuffer; +const makeAmountInitialAndExpiration = function (amount, amountIfEmpty, expiration) { + const buf = Buffer.alloc(20); + buf.writeUInt32BE(0, 0); + buf.writeUInt32BE(amount, 4); + buf.writeUInt32BE(0, 8); + buf.writeUInt32BE(amountIfEmpty, 12); + buf.writeUInt32BE(expiration, 16); + return buf; +}; +exports.makeAmountInitialAndExpiration = makeAmountInitialAndExpiration; +const makeExpiration = function (expiration) { + const buf = Buffer.alloc(4); + buf.writeUInt32BE(expiration, 0); + return buf; +}; +exports.makeExpiration = makeExpiration; +const hashCode = function (str) { + let ret, i, len; + for (ret = 0, i = 0, len = str.length; i < len; i++) { + ret = (31 * ret + str.charCodeAt(i)) << 0; + } + return Math.abs(ret); +}; +exports.hashCode = hashCode; +const parseMessage = function (dataBuf) { + if (dataBuf.length < 24) { + return false; + } + const responseHeader = header.fromBuffer(dataBuf); + if (dataBuf.length < responseHeader.totalBodyLength + 24 || + responseHeader.totalBodyLength < + responseHeader.keyLength + responseHeader.extrasLength) { + return false; + } + let pointer = 24; + const extras = dataBuf.slice(pointer, pointer + responseHeader.extrasLength); + pointer += responseHeader.extrasLength; + const key = dataBuf.slice(pointer, pointer + responseHeader.keyLength); + pointer += responseHeader.keyLength; + const val = dataBuf.slice(pointer, 24 + responseHeader.totalBodyLength); + return { header: responseHeader, key: key, extras: extras, val: val }; +}; +exports.parseMessage = parseMessage; +const parseMessages = function (dataBuf) { + const messages = []; + let message; + do { + message = exports.parseMessage(dataBuf); + if (message) { + messages.push(message); + const messageLength = message.header.totalBodyLength + 24; + dataBuf = dataBuf.slice(messageLength); + } + } while (message); + return messages; +}; +exports.parseMessages = parseMessages; +const merge = function (original, deflt) { + for (let attrT of Object.keys(deflt)) { + const attr = attrT; + const originalValue = original[attr]; + if (originalValue === undefined || originalValue === null) { + original[attr] = deflt[attr]; + } + } + return original; +}; +exports.merge = merge; +// timestamp provides a monotonic timestamp with millisecond accuracy, useful +// for timers. +const timestamp = function () { + const times = process.hrtime(); + return times[0] * 1000 + Math.round(times[1] / 1000000); +}; +exports.timestamp = timestamp; +if (!Buffer.concat) { + Buffer.concat = function (list, length) { + if (!Array.isArray(list)) { + throw new Error("Usage: Buffer.concat(list, [length])"); + } + if (list.length === 0) { + return Buffer.alloc(0); + } + if (list.length === 1) { + return list[0]; + } + let i; + let buf; + if (typeof length !== "number") { + length = 0; + for (i = 0; i < list.length; i++) { + buf = list[i]; + length += buf.length; + } + } + const buffer = Buffer.alloc(length); + let pos = 0; + for (let i = 0; i < list.length; i++) { + buf = list[i]; + buf.copy(buffer, pos); + pos += buf.length; + } + return buffer; + }; +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbWVtanMvdXRpbHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLDRCQUE0Qjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUU1QixpREFBbUM7QUFLNUIsTUFBTSxTQUFTLEdBQUcsVUFBVSxHQUFnQjtJQUNqRCxPQUFPLE1BQU0sQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFVLENBQUMsQ0FBQztBQUM5RCxDQUFDLENBQUM7QUFGVyxRQUFBLFNBQVMsYUFFcEI7QUFZRixTQUFnQix1QkFBdUIsQ0FDckMsTUFBYyxFQUNkLE1BQWMsRUFDZCxPQUF5QjtJQUV6QixNQUFNLEdBQUcsR0FBRyxpQkFBUyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNuQyxNQUFNLE1BQU0sR0FBRyxpQkFBUyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUN6QyxNQUFNLEtBQUssR0FBRyxpQkFBUyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUV2QyxNQUFNLG9CQUFvQixHQUFHLE1BQU0sSUFBSSxDQUFDLENBQUM7SUFDekMsSUFBSSxpQkFBaUIsR0FBRyxDQUFDLENBQUM7SUFDMUIsU0FBUyxjQUFjLENBQUMsYUFBcUI7UUFDM0MsTUFBTSxZQUFZLEdBQUcsYUFBYSxDQUFDLElBQUksQ0FDckMsTUFBTSxFQUNOLG9CQUFvQixHQUFHLGlCQUFpQixDQUN6QyxDQUFDO1FBQ0YsaUJBQWlCLElBQUksWUFBWSxDQUFDO0lBQ3BDLENBQUM7SUFFRCxNQUFNLGFBQWEsR0FBa0I7UUFDbkMsR0FBRyxPQUFPLENBQUMsTUFBTTtRQUNqQixLQUFLLEVBQUUsSUFBSTtRQUNYLFNBQVMsRUFBRSxHQUFHLENBQUMsTUFBTTtRQUNyQixZQUFZLEVBQUUsTUFBTSxD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LENBQUM7UUFFaEIsSUFBSSxPQUFPLE1BQU0sS0FBSyxRQUFRLEVBQUU7WUFDOUIsTUFBTSxHQUFHLENBQUMsQ0FBQztZQUNYLEtBQUssQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRTtnQkFDaEMsR0FBRyxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDZCxNQUFNLElBQUksR0FBRyxDQUFDLE1BQU0sQ0FBQzthQUN0QjtTQUNGO1FBRUQsTUFBTSxNQUFNLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUNwQyxJQUFJLEdBQUcsR0FBRyxDQUFDLENBQUM7UUFDWixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRTtZQUNwQyxHQUFHLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ2QsR0FBRyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUM7WUFDdEIsR0FBRyxJQUFJLEdBQUcsQ0FBQyxNQUFNLENBQUM7U0FDbkI7UUFDRCxPQUFPLE1BQU0sQ0FBQztJQUNoQixDQUFDLENBQUM7Q0FDSCIsInNvdXJjZXNDb250ZW50IjpbIi8vICMgTWVtSlMgdXRpbGl0eSBmdW5jdGlvbnNcblxuaW1wb3J0ICogYXMgaGVhZGVyIGZyb20gXCIuL2hlYWRlclwiO1xuaW1wb3J0IHsgT1AgfSBmcm9tIFwiLi9jb25zdGFudHNcIjtcblxuZXhwb3J0IHR5cGUgTWF5YmVCdWZmZXIgPSBzdHJpbmcgfCBCdWZmZXI7XG5cbmV4cG9ydCBjb25zdCBidWZmZXJpZnkgPSBmdW5jdGlvbiAodmFsOiBNYXliZUJ1ZmZlcikge1xuICByZXR1cm4gQnVmZmVyLmlzQnVmZmVyKHZhbCkgPyB2YWwgOiBCdWZmZXIuZnJvbSh2YWwgYXMgYW55KTtcbn07XG5cbmV4cG9ydCBpbnRlcmZhY2UgRW5jb2RhYmxlUmVxdWVzdCB7XG4gIGhlYWRlcjogT21pdDxcbiAgICBoZWFkZXIuSGVhZGVyLFxuICAgIFwibWFnaWNcIiB8IFwia2V5TGVuZ3RoXCIgfCBcImV4dHJhc0xlbmd0aFwiIHwgXCJ0b3RhbEJvZHlMZW5ndGhcIlxuICA+O1xuICBrZXk6IE1heWJlQnVmZmVyO1xuICBleHRyYXM6IE1heWJlQnVmZmVyO1xuICB2YWx1ZTogTWF5YmVCdWZmZXI7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBlbmNvZGVSZXF1ZXN0SW50b0J1ZmZlcihcbiAgYnVmZmVyOiBCdWZmZXIsXG4gIG9mZnNldDogbnVtYmVyLFxuICByZXF1ZXN0OiBFbmNvZGFibGVSZXF1ZXN0XG4pIHtcbiAgY29uc3Qga2V5ID0gYnVmZmVyaWZ5KHJlcXVlc3Qua2V5KTtcbiAgY29uc3QgZXh0cmFzID0gYnVmZmVyaWZ5KHJlcXVlc3QuZXh0cmFzKTtcbiAgY29uc3QgdmFsdWUgPSBidWZmZXJpZnkocmVxdWVzdC52YWx1ZSk7XG5cbiAgY29uc3QgYnVmVGFyZ2V0V3JpdGVPZmZzZXQgPSBvZmZzZXQgfHwgMDtcbiAgbGV0IHRvdGFsQnl0ZXNXcml0dGVuID0gMDtcbiAgZnVuY3Rpb24gY29weUludG9CdWZmZXIodG9Xcml0ZUJ1ZmZlcjogQnVmZmVyKSB7XG4gICAgY29uc3QgYnl0ZXNXcml0dGVuID0gdG9Xcml0ZUJ1ZmZlci5jb3B5KFxuICAgICAgYnVmZmVyLFxuICAgICAgYnVmVGFyZ2V0V3JpdGVPZmZzZXQgKyB0b3RhbEJ5dGVzV3JpdHRlblxuICAgICk7XG4gICAgdG90YWxCeXRlc1dyaXR0ZW4gKz0gYnl0ZXNXcml0dGVuO1xuICB9XG5cbiAgY29uc3QgcmVxdWVzdEhlYWRlcjogaGVhZGVyLkhlYWRlciA9IHtcbiAgICAuLi5yZXF1ZXN0LmhlYWRlcixcbiAgICBtYWdpYzogMHg4MCxcbiAgICBrZXlMZW5ndGg6IGtleS5sZW5ndGgsXG4gICAgZXh0cmFzTGVuZ3RoOiBleHRyYXMubGVuZ3RoLFxuICAgIHRvdGFsQm9keUxlbmd0aDoga2V5Lmxlbmd0aCArIHZhbHVlLmxlbmd0aCArIGV4dHJhcy5sZW5ndGgsXG4gIH07XG5cbiAgY29uc3QgaGVhZGVyQnVmZmVyID0gaGVhZGVyLnRvQnVmZmVyKHJlcXVlc3RIZWFkZXIpO1xuXG4gIGNvcHlJbnRvQnVmZmVyKGhlYWRlckJ1ZmZlcik7XG4gIGNvcHlJbnRvQnVmZmVyKGV4dHJhcyk7XG4gIGNvcHlJbnRvQnVmZmVyKGtleSk7XG4gIGNvcHlJbnRvQnVmZmVyKHZhbHVlKTtcblxuICByZXR1cm4gdG90YWxCeXRlc1dyaXR0ZW47XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBlbmNvZGVSZXF1ZXN0KHJlcXVlc3Q6IEVuY29kYWJsZVJlcXVlc3QpOiBCdWZmZXIge1xuICBjb25zdCBrZXkgPSBidWZmZXJpZnkocmVxdWVzdC5rZXkpO1xuICBjb25zdCBleHRyYXMgPSBidWZmZXJpZnkocmVxdWVzdC5leHRyYXMpO1xuICBjb25zdCB2YWx1ZSA9IGJ1ZmZlcmlmeShyZXF1ZXN0LnZhbHVlKTtcbiAgY29uc3QgYnVmU2l6ZSA9IDI0ICsga2V5Lmxlbmd0aCArIGV4dHJhcy5sZW5ndGggKyB2YWx1ZS5sZW5ndGg7XG4gIGNvbnN0IGJ1ZmZlciA9IEJ1ZmZlci5hbGxvYyhidWZTaXplKTtcbiAgZW5jb2RlUmVxdWVzdEludG9CdWZmZXIoYnVmZmVyLCAwLCB7XG4gICAgLi4ucmVxdWVzdCxcbiAgICBrZXksXG4gICAgZXh0cmFzLFxuICAgIHZhbHVlLFxuICB9KTtcbiAgcmV0dXJuIGJ1ZmZlcjtcbn1cblxuZXhwb3J0IGNvbnN0IGNvcHlJbnRvUmVxdWVzdEJ1ZmZlciA9IGZ1bmN0aW9uIChcbiAgb3Bjb2RlOiBPUCxcbiAga2V5OiBNYXliZUJ1ZmZlcixcbiAgZXh0cmFzOiBNYXliZUJ1ZmZlcixcbiAgdmFsdWU6IE1heWJlQnVmZmVyLFxuICBvcGFxdWU6IG51bWJlcixcbiAgYnVmOiBCdWZmZXIsXG4gIF9idWZUYXJnZXRXcml0ZU9mZnNldD86IG51bWJlclxuKSB7XG4gIHJldHVybiBlbmNvZGVSZXF1ZXN0SW50b0J1ZmZlcihidWYsIF9idWZUYXJnZXRXcml0ZU9mZnNldCB8fCAwLCB7XG4gICAgaGVhZGVyOiB7XG4gICAgICBvcGNvZGUsXG4gICAgICBvcGFxdWUsXG4gICAgfSxcbiAgICBrZXksXG4gICAgZXh0cmFzLFxuICAgIHZhbHVlLFxuICB9KTtcbn07XG5cbmV4cG9ydCBjb25zdCBtYWtlUmVxdWVzdEJ1ZmZlciA9IGZ1bmN0aW9uIChcbiAgb3Bjb2RlOiBPUCxcbiAga2V5OiBNYXliZUJ1ZmZlcixcbiAgZXh0cmFzOiBNYXliZUJ1ZmZlcixcbiAgdmFsdWU6IE1heWJlQnVmZmVyLFxuICBvcGFxdWU/OiBudW1iZXJcbikge1xuICByZXR1cm4gZW5jb2RlUmVxdWVzdCh7XG4gICAgZXh0cmFzLFxuICAgIGtleSxcbiAgICB2YWx1ZSxcbiAgICBoZWFkZXI6IHtcbiAgICAgIG9wY29kZSxcbiAgICAgIG9wYXF1ZTogb3BhcXVlIHx8IDAsXG4gICAgfSxcbiAgfSk7XG59O1xuXG5leHBvcnQgY29uc3QgbWFrZUFtb3VudEluaXRpYWxBbmRFeHBpcmF0aW9uID0gZnVuY3Rpb24gKFxuICBhbW91bnQ6IG51bWJlcixcbiAgYW1vdW50SWZFbXB0eTogbnVtYmVyLFxuICBleHBpcmF0aW9uOiBudW1iZXJcbikge1xuICBjb25zdCBidWYgPSBCdWZmZXIuYWxsb2MoMjApO1xuICBidWYud3JpdGVVSW50MzJCRSgwLCAwKTtcbiAgYnVmLndyaXRlVUludDMyQkUoYW1vdW50LCA0KTtcbiAgYnVmLndyaXRlVUludDMyQkUoMCwgOCk7XG4gIGJ1Zi53cml0ZVVJbnQzMkJFKGFtb3VudElmRW1wdHksIDEyKTtcbiAgYnVmLndyaXRlVUludDMyQkUoZXhwaXJhdGlvbiwgMTYpO1xuICByZXR1cm4gYnVmO1xufTtcblxuZXhwb3J0IGNvbnN0IG1ha2VFeHBpcmF0aW9uID0gZnVuY3Rpb24gKGV4cGlyYXRpb246IG51bWJlcikge1xuICBjb25zdCBidWYgPSBCdWZmZXIuYWxsb2MoNCk7XG4gIGJ1Zi53cml0ZVVJbnQzMkJFKGV4cGlyYXRpb24sIDApO1xuICByZXR1cm4gYnVmO1xufTtcblxuZXhwb3J0IGNvbnN0IGhhc2hDb2RlID0gZnVuY3Rpb24gKHN0cjogc3RyaW5nKSB7XG4gIGxldCByZXQsIGksIGxlbjtcbiAgZm9yIChyZXQgPSAwLCBpID0gMCwgbGVuID0gc3RyLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgcmV0ID0gKDMxICogcmV0ICsgc3RyLmNoYXJDb2RlQXQoaSkpIDw8IDA7XG4gIH1cbiAgcmV0dXJuIE1hdGguYWJzKHJldCk7XG59O1xuXG5leHBvcnQgaW50ZXJmYWNlIE1lc3NhZ2Uge1xuICBoZWFkZXI6IGhlYWRlci5IZWFkZXI7XG4gIGtleTogQnVmZmVyO1xuICB2YWw6IEJ1ZmZlcjtcbiAgZXh0cmFzOiBCdWZmZXI7XG59XG5cbmV4cG9ydCBjb25zdCBwYXJzZU1lc3NhZ2UgPSBmdW5jdGlvbiAoZGF0YUJ1ZjogQnVmZmVyKTogTWVzc2FnZSB8IGZhbHNlIHtcbiAgaWYgKGRhdGFCdWYubGVuZ3RoIDwgMjQpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgY29uc3QgcmVzcG9uc2VIZWFkZXIgPSBoZWFkZXIuZnJvbUJ1ZmZlcihkYXRhQnVmKTtcblxuICBpZiAoXG4gICAgZGF0YUJ1Zi5sZW5ndGggPCByZXNwb25zZUhlYWRlci50b3RhbEJvZHlMZW5ndGggKyAyNCB8fFxuICAgIHJlc3BvbnNlSGVhZGVyLnRvdGFsQm9keUxlbmd0aCA8XG4gICAgICByZXNwb25zZUhlYWRlci5rZXlMZW5ndGggKyByZXNwb25zZUhlYWRlci5leHRyYXNMZW5ndGhcbiAgKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgbGV0IHBvaW50ZXIgPSAyNDtcbiAgY29uc3QgZXh0cmFzID0gZGF0YUJ1Zi5zbGljZShwb2ludGVyLCBwb2ludGVyICsgcmVzcG9uc2VIZWFkZXIuZXh0cmFzTGVuZ3RoKTtcbiAgcG9pbnRlciArPSByZXNwb25zZUhlYWRlci5leHRyYXNMZW5ndGg7XG4gIGNvbnN0IGtleSA9IGRhdGFCdWYuc2xpY2UocG9pbnRlciwgcG9pbnRlciArIHJlc3BvbnNlSGVhZGVyLmtleUxlbmd0aCk7XG4gIHBvaW50ZXIgKz0gcmVzcG9uc2VIZWFkZXIua2V5TGVuZ3RoO1xuICBjb25zdCB2YWwgPSBkYXRhQnVmLnNsaWNlKHBvaW50ZXIsIDI0ICsgcmVzcG9uc2VIZWFkZXIudG90YWxCb2R5TGVuZ3RoKTtcblxuICByZXR1cm4geyBoZWFkZXI6IHJlc3BvbnNlSGVhZGVyLCBrZXk6IGtleSwgZXh0cmFzOiBleHRyYXMsIHZhbDogdmFsIH07XG59O1xuXG5leHBvcnQgY29uc3QgcGFyc2VNZXNzYWdlcyA9IGZ1bmN0aW9uIChkYXRhQnVmOiBCdWZmZXIpOiBNZXNzYWdlW10ge1xuICBjb25zdCBtZXNzYWdlcyA9IFtdO1xuXG4gIGxldCBtZXNzYWdlOiBNZXNzYWdlO1xuXG4gIGRvIHtcbiAgICBtZXNzYWdlID0gZXhwb3J0cy5wYXJzZU1lc3NhZ2UoZGF0YUJ1Zik7XG4gICAgaWYgKG1lc3NhZ2UpIHtcbiAgICAgIG1lc3NhZ2VzLnB1c2gobWVzc2FnZSk7XG4gICAgICBjb25zdCBtZXNzYWdlTGVuZ3RoID0gbWVzc2FnZS5oZWFkZXIudG90YWxCb2R5TGVuZ3RoICsgMjQ7XG4gICAgICBkYXRhQnVmID0gZGF0YUJ1Zi5zbGljZShtZXNzYWdlTGVuZ3RoKTtcbiAgICB9XG4gIH0gd2hpbGUgKG1lc3NhZ2UpO1xuXG4gIHJldHVybiBtZXNzYWdlcztcbn07XG5cbmV4cG9ydCBjb25zdCBtZXJnZSA9IGZ1bmN0aW9uIDxUPihvcmlnaW5hbDogYW55LCBkZWZsdDogVCk6IFQge1xuICBmb3IgKGxldCBhdHRyVCBvZiBPYmplY3Qua2V5cyhkZWZsdCkpIHtcbiAgICBjb25zdCBhdHRyOiBrZXlvZiBUID0gYXR0clQgYXMgYW55O1xuICAgIGNvbnN0IG9yaWdpbmFsVmFsdWUgPSBvcmlnaW5hbFthdHRyXTtcblxuICAgIGlmIChvcmlnaW5hbFZhbHVlID09PSB1bmRlZmluZWQgfHwgb3JpZ2luYWxWYWx1ZSA9PT0gbnVsbCkge1xuICAgICAgb3JpZ2luYWxbYXR0cl0gPSBkZWZsdFthdHRyXSBhcyBhbnk7XG4gICAgfVxuICB9XG4gIHJldHVybiBvcmlnaW5hbDtcbn07XG5cbi8vIHRpbWVzdGFtcCBwcm92aWRlcyBhIG1vbm90b25pYyB0aW1lc3RhbXAgd2l0aCBtaWxsaXNlY29uZCBhY2N1cmFjeSwgdXNlZnVsXG4vLyBmb3IgdGltZXJzLlxuZXhwb3J0IGNvbnN0IHRpbWVzdGFtcCA9IGZ1bmN0aW9uICgpIHtcbiAgY29uc3QgdGltZXMgPSBwcm9jZXNzLmhydGltZSgpO1xuICByZXR1cm4gdGltZXNbMF0gKiAxMDAwICsgTWF0aC5yb3VuZCh0aW1lc1sxXSAvIDEwMDAwMDApO1xufTtcblxuaWYgKCFCdWZmZXIuY29uY2F0KSB7XG4gIEJ1ZmZlci5jb25jYXQgPSBmdW5jdGlvbiAobGlzdCwgbGVuZ3RoKSB7XG4gICAgaWYgKCFBcnJheS5pc0FycmF5KGxpc3QpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJVc2FnZTogQnVmZmVyLmNvbmNhdChsaXN0LCBbbGVuZ3RoXSlcIik7XG4gICAgfVxuXG4gICAgaWYgKGxpc3QubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm4gQnVmZmVyLmFsbG9jKDApO1xuICAgIH1cbiAgICBpZiAobGlzdC5sZW5ndGggPT09IDEpIHtcbiAgICAgIHJldHVybiBsaXN0WzBdO1xuICAgIH1cblxuICAgIGxldCBpOiBudW1iZXI7XG4gICAgbGV0IGJ1ZjogQnVmZmVyO1xuXG4gICAgaWYgKHR5cGVvZiBsZW5ndGggIT09IFwibnVtYmVyXCIpIHtcbiAgICAgIGxlbmd0aCA9IDA7XG4gICAgICBmb3IgKGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICBidWYgPSBsaXN0W2ldO1xuICAgICAgICBsZW5ndGggKz0gYnVmLmxlbmd0aDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBidWZmZXIgPSBCdWZmZXIuYWxsb2MobGVuZ3RoKTtcbiAgICBsZXQgcG9zID0gMDtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICAgIGJ1ZiA9IGxpc3RbaV07XG4gICAgICBidWYuY29weShidWZmZXIsIHBvcyk7XG4gICAgICBwb3MgKz0gYnVmLmxlbmd0aDtcbiAgICB9XG4gICAgcmV0dXJuIGJ1ZmZlcjtcbiAgfTtcbn1cbiJdfQ== \ No newline at end of file diff --git a/package.json b/package.json index 8d58d5a..c907101 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "url": "git://github.com/memcachier/memjs.git" }, "engines": { - "node": ">=0.10.0" + "node": ">=12" }, "main": "./lib/memjs/memjs", "directories": { @@ -26,7 +26,8 @@ "tsc": "rm -rf ./lib && tsc", "test": "npm run-script tsc && tap --no-coverage -R spec ./lib/test/*.js", "bench": "npm run-script tsc && NODE_PATH=lib/memjs/ node bench/memjs.js", - "bench-timers": "npm run-script tsc && NODE_PATH=lib/memjs/ node bench/timers.js" + "bench-timers": "npm run-script tsc && NODE_PATH=lib/memjs/ node bench/timers.js", + "ensure-clean": "npm run-script tsc && bin/ensure-clean.sh" }, "devDependencies": { "@types/node": "12.20.7", diff --git a/smoketest.js b/smoketest.js new file mode 100755 index 0000000..4103eb1 --- /dev/null +++ b/smoketest.js @@ -0,0 +1,50 @@ +#! node +const MemJS = require("."); +const assert = require("assert"); +const client = MemJS.Client.create(); + +function assertBufferEqual(buf1, buf2, msg) { + assert.strictEqual(buf1.toString(), buf2.toString(), msg); +} + +async function body() { + await client.set("foo", "1"); + + let { value, cas } = await client.get("foo"); + assert.strictEqual(value.toString(), "1"); + assert.ok(cas, "must return a CAS token"); + + const successWithBadCas = await client.set("foo", "should not set", { + cas: Buffer.from("wrong"), + }); + assert.strictEqual(false, successWithBadCas, "should not set with a bad CAS"); + + const v2 = await client.get("foo"); + assert.strictEqual(v2.value.toString(), "1", "did not get set"); + assertBufferEqual(cas, v2.cas, "cas tokens are equal still"); + + assert.ok( + await client.set("foo", "1", { cas }), + "set with original cas token to identical value" + ); + let { cas: cas3 } = await client.get("foo"); + assert.notStrictEqual( + cas.toString(), + cas3.toString(), + "has new CAS after identical set" + ); +} + +async function main() { + try { + await body(); + console.log("smoketest ok"); + } catch (error) { + console.error("fatal", error); + process.exit(1); + } finally { + client.quit(); + } +} + +main(); diff --git a/tsconfig.json b/tsconfig.json index 65657dc..adf945a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,15 +4,15 @@ /* Basic Options */ // "incremental": true, /* Enable incremental compilation */ - "target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ + "target": "ES2019", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ - // "lib": [], /* Specify library files to be included in the compilation. */ + "lib": ["ES2019"], /* Specify library files to be included in the compilation. */ "allowJs": true, /* Allow javascript files to be compiled. */ "checkJs": false, /* Report errors in .js files. */ // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', 'react', 'react-jsx' or 'react-jsxdev'. */ "declaration": true, /* Generates corresponding '.d.ts' file. */ "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ - "sourceMap": true, /* Generates corresponding '.map' file. */ + "sourceMap": false, /* Generates corresponding '.map' file. */ // "outFile": "./", /* Concatenate and emit output to single file. */ "outDir": "./lib/", /* Redirect output structure to the directory. */ // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ @@ -56,7 +56,7 @@ /* Source Map Options */ // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ - // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ + "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ /* Experimental Options */ From c3432a4d79e7a1adaab5e2477e6c8cbc0013a25f Mon Sep 17 00:00:00 2001 From: Jake Teton-Landis Date: Tue, 13 Apr 2021 12:43:27 -0700 Subject: [PATCH 58/79] Make getMulti return type non-null (#12) * getMulti not null * derf --- lib/memjs/memjs.d.ts | 2 +- lib/memjs/memjs.d.ts.map | 2 +- lib/memjs/memjs.js | 2 +- src/memjs/memjs.ts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/memjs/memjs.d.ts b/lib/memjs/memjs.d.ts index 80a0b14..a300f96 100644 --- a/lib/memjs/memjs.d.ts +++ b/lib/memjs/memjs.d.ts @@ -125,7 +125,7 @@ declare class Client { * Retrievs the value at the given keys in memcached. Returns a map from the * requested keys to results, or null if the key was not found. */ - getMulti(keys: Keys[]): Promise | null>; + getMulti(keys: Keys[]): Promise>; /** * Sets `key` to `value`. */ diff --git a/lib/memjs/memjs.d.ts.map b/lib/memjs/memjs.d.ts.map index 2340dda..7ec9090 100644 --- a/lib/memjs/memjs.d.ts.map +++ b/lib/memjs/memjs.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"memjs.d.ts","sourceRoot":"","sources":["../../src/memjs/memjs.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"memjs.d.ts","sourceRoot":"","sources":["../../src/memjs/memjs.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/lib/memjs/memjs.js b/lib/memjs/memjs.js index 4d65003..a1e2da5 100644 --- a/lib/memjs/memjs.js +++ b/lib/memjs/memjs.js @@ -725,4 +725,4 @@ class Client { } } exports.Client = Client; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVtanMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbWVtanMvbWVtanMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLHdCQUF3Qjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUV4QixxQ0FLa0I7QUFvaENELHVGQXRoQ2YsZUFBTSxPQXNoQ2U7QUFuaEN2Qix1REFBK0Q7QUFDL0QsbUNBU2lCO0FBQ2pCLHVEQUF5QztBQUN6QywyQ0FBNkM7QUFDN0MsK0NBQWlDO0FBc2dDUixzQkFBSztBQXJnQzlCLGlEQUFtQztBQXFnQ0gsd0JBQU07QUFuZ0N0QyxTQUFTLDhCQUE4QixDQUNyQyxPQUFpQixFQUNqQixHQUFXO0lBRVgsTUFBTSxLQUFLLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQztJQUM3QixNQUFNLEtBQUssR0FBRyxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxnQkFBUSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3BELE9BQU8sT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ3hCLENBQUM7QUFFRCwrQ0FBK0M7QUFDL0MsU0FBUyxTQUFTLENBQ2hCLE9BQTBFO0lBRTFFLE9BQU8sSUFBSSxPQUFPLENBQUMsVUFBVSxPQUFPLEVBQUUsTUFBTTtRQUMxQyxPQUFPLENBQUMsVUFBVSxHQUFHLEVBQUUsTUFBTTtZQUMzQixHQUFHLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3RDLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBNkRELE1BQU0sTUFBTTtJQVFWLDRFQUE0RTtJQUM1RSxtQ0FBbUM7SUFDbkMsWUFBWSxPQUFpQixFQUFFLE9BQTBDO1FBQ3ZFLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO1FBQ3ZCLElB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QyxDQUFDO2lCQUN2QjthQUNGO1FBQ0gsQ0FBQyxDQUFDO1FBRUYsTUFBTSxDQUFDLFVBQVUsQ0FBQyxHQUFHLEVBQUUsZUFBZSxDQUFDLENBQUM7UUFDeEMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUUsWUFBWSxDQUFDLENBQUM7UUFDbEMsTUFBTSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUN4QixDQUFDO0lBRUQsMEJBQTBCO0lBQzFCLE9BQU87UUFDTCxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7UUFFWCw2RUFBNkU7UUFDN0UsSUFBSSxDQUFDLEdBQUcsSUFBSSxVQUFVLENBQUM7SUFDekIsQ0FBQztJQUVPLGlCQUFpQixDQUN2QixXQUFtQixFQUNuQixjQUEwQztRQUUxQyxNQUFNLFlBQVksR0FBRyxTQUFTLFdBQVcsS0FBSyxTQUFTLENBQUMsc0JBQXNCLENBQzVFLGNBQWMsQ0FDZixFQUFFLENBQUM7UUFDSixJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDdEMsT0FBTyxJQUFJLEtBQUssQ0FBQyxZQUFZLENBQUMsQ0FBQztJQUNqQyxDQUFDO0lBRUQ7OztPQUdHO0lBQ0ssbUJBQW1CLENBQ3pCLFdBQW1CLEVBQ25CLGNBQTBDLEVBQzFDLFFBQWtFO1FBRWxFLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxXQUFXLEVBQUUsY0FBYyxDQUFDLENBQUM7UUFDbEUsSUFBSSxRQUFRLEVBQUU7WUFDWixRQUFRLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxDQUFDO1NBQ3ZCO1FBQ0QsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0NBQ0Y7QUFFUSx3QkFBTSIsInNvdXJjZXNDb250ZW50IjpbIi8vIE1lbVRTIE1lbWNhY2hlIENsaWVudFxuXG5pbXBvcnQge1xuICBPbkVycm9yQ2FsbGJhY2ssXG4gIE9uUmVzcG9uc2VDYWxsYmFjayxcbiAgU2VydmVyLFxuICBTZXJ2ZXJPcHRpb25zLFxufSBmcm9tIFwiLi9zZXJ2ZXJcIjtcbmltcG9ydCB7IG5vb3BTZXJpYWxpemVyLCBTZXJpYWxpemVyIH0gZnJvbSBcIi4vbm9vcC1zZXJpYWxpemVyXCI7XG5pbXBvcnQge1xuICBtYWtlUmVxdWVzdEJ1ZmZlcixcbiAgY29weUludG9SZXF1ZXN0QnVmZmVyLFxuICBtZXJnZSxcbiAgbWFrZUV4cGlyYXRpb24sXG4gIG1ha2VBbW91bnRJbml0aWFsQW5kRXhwaXJhdGlvbixcbiAgaGFzaENvZGUsXG4gIE1heWJlQnVmZmVyLFxuICBNZXNzYWdlLFxufSBmcm9tIFwiLi91dGlsc1wiO1xuaW1wb3J0ICogYXMgY29uc3RhbnRzIGZyb20gXCIuL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgUmVzcG9uc2VTdGF0dXMgfSBmcm9tIFwiLi9jb25zdGFudHNcIjtcbmltcG9ydCAqIGFzIFV0aWxzIGZyb20gXCIuL3V0aWxzXCI7XG5pbXBvcnQgKiBhcyBIZWFkZXIgZnJvbSBcIi4vaGVhZGVyXCI7XG5cbmZ1bmN0aW9uIGRlZmF1bHRLZXlUb1NlcnZlckhhc2hGdW5jdGlvbihcbiAgc2VydmVyczogc3RyaW5nW10sXG4gIGtleTogc3RyaW5nXG4pOiBzdHJpbmcge1xuICBjb25zdCB0b3RhbCA9IHNlcnZlcnMubGVuZ3RoO1xuICBjb25zdCBpbmRleCA9IHRvdGFsID4gMSA/IGhhc2hDb2RlKGtleSkgJSB0b3RhbCA6IDA7XG4gIHJldHVybiBzZXJ2ZXJzW2luZGV4XTtcbn1cblxuLy8gY29udmVydHMgYSBjYWxsIGludG8gYSBwcm9taXNlLXJldHVybmluZyBvbmVcbmZ1bmN0aW9uIHByb21pc2lmeTxSZXN1bHQ+KFxuICBjb21tYW5kOiAoY2FsbGJhY2s6IChlcnJvcjogRXJyb3IgfCBudWxsLCByZXN1bHQ6IFJlc3VsdCkgPT4gdm9pZCkgPT4gdm9pZFxuKTogUHJvbWlzZTxSZXN1bHQ+IHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICBjb21tYW5kKGZ1bmN0aW9uIChlcnIsIHJlc3VsdCkge1xuICAgICAgZXJyID8gcmVqZWN0KGVycikgOiByZXNvbHZlKHJlc3VsdCk7XG4gICAgfSk7XG4gIH0pO1xufVxuXG50eXBlIFJlc3BvbnNlT3JFcnJvckNhbGxiYWNrID0gKFxuICBlcnJvcjogRXJyb3IgfCBudWxsLFxuICByZXNwb25zZTogTWVzc2FnZSB8IG51bGxcbikgPT4gdm9pZDtcblxuaW50ZXJmYWNlIEJhc2VDbGllbnRPcHRpb25zIHtcbiAgcmV0cmllczogbnVtYmVyO1xuICByZXRyeV9kZWxheTogbnVtYmVyO1xuICBleHBpcmVzOiBudW1iZXI7XG4gIGxvZ2dlcjogeyBsb2c6IHR5cGVvZiBjb25zb2xlLmxvZyB9O1xuICBrZXlUb1NlcnZlckhhc2hGdW5jdGlvbjogdHlwZW9mIGRlZmF1bHRLZXlUb1NlcnZlckhhc2hGdW5jdGlvbjtcbn1cblxuaW50ZXJmYWNlIFNlcmlhbGl6ZXJQcm9wPFZhbHVlLCBFeHRyYXM+IHtcbiAgc2VyaWFsaXplcjogU2VyaWFsaXplcjxWYWx1ZSwgRXh0cmFzPjtcbn1cblxuLyoqXG4gKiBUaGUgY2xpZW50IGhhcyBwYXJ0aWFsIHN1cHBvcnQgZm9yIHNlcmlhbGl6aW5nIGFuZCBkZXNlcmlhbGl6aW5nIHZhbHVlcyBmcm9tIHRoZVxuICogQnVmZmVyIGJ5dGUgc3RyaW5ncyB3ZSByZWNpZXZlIGZyb20gdGhlIHdpcmUuIFRoZSBkZWZhdWx0IHNlcmlhbGl6ZXIgaXMgZm9yIE1heWJlQnVmZmVyLlxuICpcbiAqIElmIFZhbHVlIGFuZCBFeHRyYXMgYXJlIG9mIHR5cGUgQnVmZmVyLCB0aGVuIHJldHVybiB0eXBlIFdoZW5CdWZmZXIuIE90aGVyd2lzZSxcbiAqIHJldHVybiB0eXBlIE5vdEJ1ZmZlci5cbiAqL1xudHlwZSBJZkJ1ZmZlcjxcbiAgVmFsdWUsXG4gIEV4dHJhcyxcbiAgV2hlblZhbHVlQW5kRXh0cmFzQXJlQnVmZmVycyxcbiAgTm90QnVmZmVyXG4+ID0gVmFsdWUgZXh0ZW5kcyBCdWZmZXJcbiAgPyBFeHRyYXMgZXh0ZW5kcyBCdWZmZXJcbiAgICA/IFdoZW5WYWx1ZUFuZEV4dHJhc0FyZUJ1ZmZlcnNcbiAgICA6IE5vdEJ1ZmZlclxuICA6IE5vdEJ1ZmZlcjtcblxuZXhwb3J0IHR5cGUgR2l2ZW5DbGllbnRPcHRpb25zPFZhbHVlLCBFeHRyYXM+ID0gUGFydGlhbDxCYXNlQ2xpZW50T3B0aW9ucz4gJlxuICBJZkJ1ZmZlcjxcbiAgICBWYWx1ZSxcbiAgICBFeHRyYXMsXG4gICAgUGFydGlhbDxTZXJpYWxpemVyUHJvcDxWYWx1ZSwgRXh0cmFzPj4sXG4gICAgU2VyaWFsaXplclByb3A8VmFsdWUsIEV4dHJhcz5cbiAgPjtcblxuZXhwb3J0IHR5cGUgQ0FTVG9rZW4gPSBCdWZmZXI7XG5cbmV4cG9ydCBpbnRlcmZhY2UgR2V0UmVzdWx0PFZhbHVlID0gTWF5YmVCdWZmZXIsIEV4dHJhcyA9IE1heWJlQnVmZmVyPiB7XG4gIHZhbHVlOiBWYWx1ZTtcbiAgZXh0cmFzOiBFeHRyYXM7XG4gIGNhczogQ0FTVG9rZW4gfCB1bmRlZmluZWQ7XG59XG5cbmV4cG9ydCB0eXBlIEdldE11bHRpUmVzdWx0PFxuICBLZXlzIGV4dGVuZHMgc3RyaW5nID0gc3RyaW5nLFxuICBWYWx1ZSA9IE1heWJlQnVmZmVyLFxuICBFeHRyYXMgPSBNYXliZUJ1ZmZlclxuPiA9IHtcbiAgW0sgaW4gS2V5c10/OiBHZXRSZXN1bHQ8VmFsdWUsIEV4dHJhcz47XG59O1xuXG5jbGFzcyBDbGllbnQ8VmFsdWUgPSBNYXliZUJ1ZmZlciwgRXh0cmFzID0gTWF5YmVCdWZmZXI+IHtcbiAgc2VydmVyczogU2VydmVyW107XG4gIHNlcTogbnVtYmVyO1xuICBvcHRpb25zOiBCYXNlQ2xpZW50T3B0aW9ucyAmIFBhcnRpYWw8U2VyaWFsaXplclByb3A8VmFsdWUsIEV4dHJhcz4+O1xuICBzZXJpYWxpemVyOiBTZXJpYWxpemVyPFZhbHVlLCBFeHRyYXM+O1xuICBzZXJ2ZXJNYXA6IHsgW2hvc3Rwb3J0OiBzdHJpbmddOiBTZXJ2ZXIgfTtcbiAgc2VydmVyS2V5czogc3RyaW5nW107XG5cbiAgLy8gQ2xpZW50IGluaXRpYWxpemVyIHRha2VzIGEgbGlzdCBvZiBgU2VydmVyYHMgYW5kIGFuIGBvcHRpb25zYCBkaWN0aW9uYXJ5LlxuICAvLyBTZWUgYENsaWVudC5jcmVhdGVgIGZvciBkZXRhaWxzLlxuICBjb25zdHJ1Y3RvcihzZXJ2ZXJzOiBTZXJ2ZXJbXSwgb3B0aW9uczogR2l2ZW5DbGllbnRPcHRpb25zPFZhbHVlLCBFeHRyYXM+KSB7XG4gICAgdGhpcy5zZXJ2ZXJzID0gc2VydmVycztcbiAgICB0aGlzLnNlcSA9IDA7XG4gICAgdGhpcy5vcHRpb25zID0gbWVyZ2Uob3B0aW9ucyB8fCB7fSwge1xuICAgICAgcmV0cmllczogMixcbiAgICAgIHJldHJ5X2RlbGF5OiAwLjIsXG4gICAgICBleHBpcmVzOiAwLFxuICAgICAgbG9nZ2VyOiBjb25zb2xlLFxuICAgICAga2V5VG9TZXJ2ZXJIYXNoRnVuY3Rpb246IGRlZmF1bHRLZXlUb1NlcnZlckhhc2hGdW5jdGlvbixcbiAgICB9KTtcblxuICAgIHRoaXMuc2VyaWFsaXplciA9IHRoaXMub3B0aW9ucy5zZXJpYWxpemVyIHx8IChub29wU2VyaWFsaXplciBhcyBhbnkpO1xuXG4gICAgLy8gU3RvcmUgYSBtYXBwaW5nIGZyb20gaG9zdHBvcnQgLT4gc2VydmVyIHNvIHdlIGNhbiBxdWlja2x5IGdldCBhIHNlcnZlciBvYmplY3QgZnJvbSB0aGUgc2VydmVyS2V5IHJldHVybmVkIGJ5IHRoZSBoYXNoaW5nIGZ1bmN0aW9uXG4gICAgY29uc3Qgc2VydmVyTWFwOiB7IFtob3N0cG9ydDogc3RyaW5nXTogU2VydmVyIH0gPSB7fTtcbiAgICB0aGlzLnNlcnZlcnMuZm9yRWFjaChmdW5jdGlvbiAoc2VydmVyKSB7XG4gICAgICBzZXJ2ZXJNYXBbc2VydmVyLmhvc3Rwb3J0U3RyaW5nKCldID0gc2VydmVyO1xuICAgIH0pO1xuICAgIHRoaXMuc2VydmVyTWFwID0gc2VydmVyTWFwO1xuXG4gICAgLy8gc3RvcmUgYSBsaXN0IG9mIGFsbCBvdXIgc2VydmVyS2V5cyBzbyB3ZSBkb24ndCBuZWVkIHRvIGNvbnN0YW50bHkgcmVhbGxvY2F0ZSB0aGlzIGFycmF5XG4gICAgdGhpcy5zZXJ2ZXJLZXlzID0gT2JqZWN0LmtleXModGhpcy5zZXJ2ZXJNYXApO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBuZXcgY2xpZW50IGdpdmVuIGFuIG9wdGlvbmFsIGNvbmZpZyBzdHJpbmcgYW5kIG9wdGlvbmFsIGhhc2ggb2ZcbiAgICogb3B0aW9ucy4gVGhlIGNvbmZpZyBzdHJpbmcgc2hvdWxkIGJlIG9mIHRoZSBmb3JtOlxuICAgKlxuICAgKiAgICAgXCJbdXNlcjpwYXNzQF1zZXJ2ZXIxWzoxMTIxMV0sW3VzZXI6cGFzc0Bdc2VydmVyMls6MTEyMTFdLC4uLlwiXG4gICAqXG4gICAqIElmIHRoZSBhcmd1bWVudCBpcyBub3QgZ2l2ZW4sIGZhbGxiYWNrIG9uIHRoZSBgTUVNQ0FDSElFUl9TRVJWRVJTYCBlbnZpcm9ubWVudFxuICAgKiB2YXJpYWJsZSwgYE1FTUNBQ0hFX1NFUlZFUlNgIGVudmlyb25tZW50IHZhcmlhYmxlIG9yIGBcImxvY2FsaG9zdDoxMTIxMVwiYC5cbiAgICpcbiAgICogVGhlIG9wdGlvbnMgaGFzaCBtYXkgY29udGFpbiB0aGUgb3B0aW9uczpcbiAgICpcbiAgICogKiBgcmV0cmllc2AgLSB0aGUgbnVtYmVyIG9mIHRpbWVzIHRvIHJldHJ5IGFuIG9wZXJhdGlvbiBpbiBsaWV1IG9mIGZhaWx1cmVzXG4gICAqIChkZWZhdWx0IDIpXG4gICAqICogYGV4cGlyZXNgIC0gdGhlIGRlZmF1bHQgZXhwaXJhdGlvbiBpbiBzZWNvbmRzIHRvIHVzZSAoZGVmYXVsdCAwIC0gbmV2ZXJcbiAgICogZXhwaXJlKS4gSWYgYGV4cGlyZXNgIGlzIGdyZWF0ZXIgdGhhbiAzMCBkYXlzICg2MCB4IDYwIHggMjQgeCAzMCksIGl0IGlzXG4gICAqIHRyZWF0ZWQgYXMgYSBVTklYIHRpbWUgKG51bWJlciBvZiBzZWNvbmRzIHNpbmNlIEphbnVhcnkgMSwgMTk3MCkuXG4gICAqICogYGxvZ2dlcmAgLSBhIGxvZ2dlciBvYmplY3QgdGhhdCByZXNwb25kcyB0byBgbG9nKHN0cmluZylgIG1ldGhvZCBjYWxscy5cbiAgICpcbiAgICogICB+fn5+XG4gICAqICAgICBsb2cobXNnMVssIG1zZzJbLCBtc2czWy4uLl1dXSlcbiAgICogICB+fn5+XG4gICAqXG4gICAqICAgRGVmYXVsdHMgdG8gYGNvbnNvbGVgLlxuICAgKiAqIGBzZXJpYWxpemVyYCAtIHRoZSBvYmplY3Qgd2hpY2ggd2lsbCAoZGUpc2VyaWFsaXplIHRoZSBkYXRhLiBJdCBuZWVkc1xuICAgKiAgIHR3byBwdWJsaWMgbWV0aG9kczogc2VyaWFsaXplIGFuZCBkZXNlcmlhbGl6ZS4gSXQgZGVmYXVsdHMgdG8gdGhlXG4gICAqICAgbm9vcFNlcmlhbGl6ZXI6XG4gICAqXG4gICAqICAgfn5+flxuICAgKiAgIGNvbnN0IG5vb3BTZXJpYWxpemVyID0ge1xuICAgKiAgICAgc2VyaWFsaXplOiBmdW5jdGlvbiAob3Bjb2RlLCB2YWx1ZSwgZXh0cmFzKSB7XG4gICAqICAgICAgIHJldHVybiB7IHZhbHVlOiB2YWx1ZSwgZXh0cmFzOiBleHRyYXMgfTtcbiAgICogICAgIH0sXG4gICAqICAgICBkZXNlcmlhbGl6ZTogZnVuY3Rpb24gKG9wY29kZSwgdmFsdWUsIGV4dHJhcykge1xuICAgKiAgICAgICByZXR1cm4geyB2YWx1ZTogdmFsdWUsIGV4dHJhczogZXh0cmFzIH07XG4gICAqICAgICB9XG4gICAqICAgfTtcbiAgICogICB+fn5+XG4gICAqXG4gICAqIE9yIG9wdGlvbnMgZm9yIHRoZSBzZXJ2ZXJzIGluY2x1ZGluZzpcbiAgICogKiBgdXNlcm5hbWVgIGFuZCBgcGFzc3dvcmRgIGZvciBmYWxsYmFjayBTQVNMIGF1dGhlbnRpY2F0aW9uIGNyZWRlbnRpYWxzLlxuICAgKiAqIGB0aW1lb3V0YCBpbiBzZWNvbmRzIHRvIGRldGVybWluZSBmYWlsdXJlIGZvciBvcGVyYXRpb25zLiBEZWZhdWx0IGlzIDAuNVxuICAgKiAgICAgICAgICAgICBzZWNvbmRzLlxuICAgKiAqICdjb25udGltZW91dCcgaW4gc2Vjb25kcyB0byBjb25uZWN0aW9uIGZhaWx1cmUuIERlZmF1bHQgaXMgdHdpY2UgdGhlIHZhbHVlXG4gICAqICAgICAgICAgICAgICAgICBvZiBgdGltZW91dGAuXG4gICAqICogYGtlZXBBbGl2ZWAgd2hldGhlciB0byBlbmFibGUga2VlcC1hbGl2ZSBmdW5jdGlvbmFsaXR5LiBEZWZhdWx0cyB0byBmYWxzZS5cbiAgICogKiBga2VlcEFsaXZlRGVsYXlgIGluIHNlY29uZHMgdG8gdGhlIGluaXRpYWwgZGVsYXkgYmVmb3JlIHRoZSBmaXJzdCBrZWVwYWxpdmVcbiAgICogICAgICAgICAgICAgICAgICAgIHByb2JlIGlzIHNlbnQgb24gYW4gaWRsZSBzb2NrZXQuIERlZmF1bHRzIGlzIDMwIHNlY29uZHMuXG4gICAqICogYGtleVRvU2VydmVySGFzaEZ1bmN0aW9uYCBhIGZ1bmN0aW9uIHRvIG1hcCBrZXlzIHRvIHNlcnZlcnMsIHdpdGggdGhlIHNpZ25hdHVyZVxuICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoc2VydmVyS2V5czogc3RyaW5nW10sIGtleTogc3RyaW5nKTogc3RyaW5nXG4gICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgIE5PVEU6IGlmIHlvdSBuZWVkIHRvIGRvIHNvbWUgZXhwZW5zaXZlIGluaXRpYWxpemF0aW9uLCAqcGxlYXNlKiBkbyBpdCBsYXppbHkgdGhlIGZpcnN0IHRpbWUgeW91IHRoaXMgZnVuY3Rpb24gaXMgY2FsbGVkIHdpdGggYW4gYXJyYXkgb2Ygc2VydmVyS2V5cywgbm90IG9uIGV2ZXJ5IGNhbGxcbiAgICovXG4gIHN0YXRpYyBjcmVhdGU8VmFsdWUsIEV4dHJhcz4oXG4gICAgc2VydmVyc1N0cjogc3RyaW5nIHwgdW5kZWZpbmVkLFxuICAgIG9wdGlvbnM6IElmQnVmZmVyPFxuICAgICAgVmFsdWUsXG4gICAgICBFeHRyYXMsXG4gICAgICB1bmRlZmluZWQgfCAoUGFydGlhbDxTZXJ2ZXJPcHRpb25zPiAmIEdpdmVuQ2xpZW50T3B0aW9uczxWYWx1ZSwgRXh0cmFzPiksXG4gICAgICBQYXJ0aWFsPFNlcnZlck9wdGlvbnM+ICYgR2l2ZW5DbGllbnRPcHRpb25zPFZhbHVlLCBFeHRyYXM+XG4gICAgPlxuICApOiBDbGllbnQ8VmFsdWUsIEV4dHJhcz4ge1xuICAgIHNlcnZlcnNTdHIgPVxuICAgICAgc2VydmVyc1N0ciB8fFxuICAgICAgcHJvY2Vzcy5lbnYuTUVNQ0FDSElFUl9TRVJWRVJTIHx8XG4gICAgICBwcm9jZXNzLmVudi5NRU1DQUNIRV9TRVJWRVJTIHx8XG4gICAgICBcImxvY2FsaG9zdDoxMTIxMVwiO1xuICAgIGNvbnN0IHNlcnZlclVyaXMgPSBzZXJ2ZXJzU3RyLnNwbGl0KFwiLFwiKTtcbiAgICBjb25zdCBzZXJ2ZXJzID0gc2VydmVyVXJpcy5tYXAoZnVuY3Rpb24gKHVyaSkge1xuICAgICAgY29uc3QgdXJpUGFydHMgPSB1cmkuc3BsaXQoXCJAXCIpO1xuICAgICAgY29uc3QgaG9zdFBvcnQgPSB1cmlQYXJ0c1t1cmlQYXJ0cy5sZW5ndGggLSAxXS5zcGxpdChcIjpcIik7XG4gICAgICBjb25zdCB1c2VyUGFzcyA9ICh1cmlQYXJ0c1t1cmlQYXJ0cy5sZW5ndGggLSAyXSB8fCBcIlwiKS5zcGxpdChcIjpcIik7XG4gICAgICByZXR1cm4gbmV3IFNlcnZlcihcbiAgICAgICAgaG9zdFBvcnRbMF0sXG4gICAgICAgIHBhcnNlSW50KGhvc3RQb3J0WzFdIHx8IFwiMTEyMTFcIiwgMTApLFxuICAgICAgICB1c2VyUGFzc1swXSxcbiAgICAgICAgdXNlclBhc3NbMV0sXG4gICAgICAgIG9wdGlvbnNcbiAgICAgICk7XG4gICAgfSk7XG4gICAgcmV0dXJuIG5ldyBDbGllbnQoc2VydmVycywgb3B0aW9ucyBhcyBhbnkpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdpdmVuIGEgc2VydmVyS2V5IGZyb21sb29rdXBLZXlUb1NlcnZlcktleSwgcmV0dXJuIHRoZSBjb3JyZXNwb25kaW5nIFNlcnZlciBpbnN0YW5jZVxuICAgKlxuICAgKiBAcGFyYW0gIHtzdHJpbmd9IHNlcnZlcktleVxuICAgKiBAcmV0dXJucyB7U2VydmVyfVxuICAgKi9cbiAgc2VydmVyS2V5VG9TZXJ2ZXIoc2VydmVyS2V5OiBzdHJpbmcpOiBTZXJ2ZXIge1xuICAgIHJldHVybiB0aGlzLnNlcnZlck1hcFtzZXJ2ZXJLZXldO1xuICB9XG5cbiAgLyoqXG4gICAqIEdpdmVuIGEga2V5IHRvIGxvb2sgdXAgaW4gbWVtY2FjaGUsIHJldHVybiBhIHNlcnZlcktleSAoYmFzZWQgb24gc29tZVxuICAgKiBoYXNoaW5nIGZ1bmN0aW9uKSB3aGljaCBjYW4gYmUgdXNlZCB0byBpbmRleCB0aGlzLnNlcnZlck1hcFxuICAgKi9cbiAgbG9va3VwS2V5VG9TZXJ2ZXJLZXkoa2V5OiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLm9wdGlvbnMua2V5VG9TZXJ2ZXJIYXNoRnVuY3Rpb24odGhpcy5zZXJ2ZXJLZXlzLCBrZXkpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHJpZXZlcyB0aGUgdmFsdWUgYXQgdGhlIGdpdmVuIGtleSBpbiBtZW1jYWNoZS5cbiAgICovXG4gIGFzeW5jIGdldChrZXk6IHN0cmluZyk6IFByb21pc2U8R2V0UmVzdWx0PFZhbHVlLCBFeHRyYXM+IHwgbnVsbD4ge1xuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihjb25zdGFudHMuT1BfR0VULCBrZXksIFwiXCIsIFwiXCIsIHRoaXMuc2VxKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgY29uc3QgZGVzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLmRlc2VyaWFsaXplKFxuICAgICAgICAgIHJlc3BvbnNlLmhlYWRlci5vcGNvZGUsXG4gICAgICAgICAgcmVzcG9uc2UudmFsLFxuICAgICAgICAgIHJlc3BvbnNlLmV4dHJhc1xuICAgICAgICApO1xuICAgICAgICByZXR1cm4geyAuLi5kZXNlcmlhbGl6ZWQsIGNhczogcmVzcG9uc2UuaGVhZGVyLmNhcyB9O1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfTk9UX0ZPVU5EOlxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJHRVRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqIEJ1aWxkIGEgcGlwZWxpbmVkIGdldCBtdWx0aSByZXF1ZXN0IGJ5IHNlbmRpbmcgb25lIEdFVEtRIGZvciBlYWNoIGtleSAocXVpZXQsIG1lYW5pbmcgaXQgd29uJ3QgcmVzcG9uZCBpZiB0aGUgdmFsdWUgaXMgbWlzc2luZykgZm9sbG93ZWQgYnkgYSBuby1vcCB0byBmb3JjZSBhIHJlc3BvbnNlIChhbmQgdG8gZ2l2ZSB1cyBhIHNlbnRpbmVsIHJlc3BvbnNlIHRoYXQgdGhlIHBpcGVsaW5lIGlzIGRvbmUpXG4gICAqXG4gICAqIGNmIGh0dHBzOi8vZ2l0aHViLmNvbS9jb3VjaGJhc2UvbWVtY2FjaGVkL2Jsb2IvbWFzdGVyL2RvY3MvQmluYXJ5UHJvdG9jb2wubWQjMHgwZC1nZXRrcS1nZXQtd2l0aC1rZXktcXVpZXRseVxuICAgKi9cbiAgX2J1aWxkR2V0TXVsdGlSZXF1ZXN0KGtleXM6IHN0cmluZ1tdKTogQnVmZmVyIHtcbiAgICAvLyBzdGFydCBhdCAyNCBmb3IgdGhlIG5vLW9wIGNvbW1hbmQgYXQgdGhlIGVuZFxuICAgIGxldCByZXF1ZXN0U2l6ZSA9IDI0O1xuICAgIGZvciAoY29uc3Qga2V5SWR4IGluIGtleXMpIHtcbiAgICAgIHJlcXVlc3RTaXplICs9IEJ1ZmZlci5ieXRlTGVuZ3RoKGtleXNba2V5SWR4XSwgXCJ1dGY4XCIpICsgMjQ7XG4gICAgfVxuXG4gICAgY29uc3QgcmVxdWVzdCA9IEJ1ZmZlci5hbGxvYyhyZXF1ZXN0U2l6ZSk7XG5cbiAgICBsZXQgYnl0ZXNXcml0dGVuID0gMDtcbiAgICBmb3IgKGNvbnN0IGtleUlkeCBpbiBrZXlzKSB7XG4gICAgICBjb25zdCBrZXkgPSBrZXlzW2tleUlkeF07XG4gICAgICBieXRlc1dyaXR0ZW4gKz0gY29weUludG9SZXF1ZXN0QnVmZmVyKFxuICAgICAgICBjb25zdGFudHMuT1BfR0VUS1EsXG4gICAgICAgIGtleSxcbiAgICAgICAgXCJcIixcbiAgICAgICAgXCJcIixcbiAgICAgICAgdGhpcy5zZXEsXG4gICAgICAgIHJlcXVlc3QsXG4gICAgICAgIGJ5dGVzV3JpdHRlblxuICAgICAgKTtcbiAgICB9XG5cbiAgICBieXRlc1dyaXR0ZW4gKz0gY29weUludG9SZXF1ZXN0QnVmZmVyKFxuICAgICAgY29uc3RhbnRzLk9QX05PX09QLFxuICAgICAgXCJcIixcbiAgICAgIFwiXCIsXG4gICAgICBcIlwiLFxuICAgICAgdGhpcy5zZXEsXG4gICAgICByZXF1ZXN0LFxuICAgICAgYnl0ZXNXcml0dGVuXG4gICAgKTtcblxuICAgIHJldHVybiByZXF1ZXN0O1xuICB9XG5cbiAgLyoqIEV4ZWN1dGluZyBhIHBpcGVsaW5lZCAobXVsdGkpIGdldCBhZ2FpbnN0IGEgc2luZ2xlIHNlcnZlci4gVGhpcyBpcyBhIHByaXZhdGUgaW1wbGVtZW50YXRpb24gZGV0YWlsIG9mIGdldE11bHRpLiAqL1xuICBhc3luYyBfZ2V0TXVsdGlUb1NlcnZlcjxLZXlzIGV4dGVuZHMgc3RyaW5nPihcbiAgICBzZXJ2OiBTZXJ2ZXIsXG4gICAga2V5czogS2V5c1tdXG4gICk6IFByb21pc2U8R2V0TXVsdGlSZXN1bHQ8S2V5cywgVmFsdWUsIEV4dHJhcz4+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgY29uc3QgcmVzcG9uc2VNYXA6IEdldE11bHRpUmVzdWx0PHN0cmluZywgVmFsdWUsIEV4dHJhcz4gPSB7fTtcblxuICAgICAgY29uc3QgaGFuZGxlOiBPblJlc3BvbnNlQ2FsbGJhY2sgPSAocmVzcG9uc2UpID0+IHtcbiAgICAgICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICAgICAgLy8gV2hlbiB3ZSBnZXQgdGhlIG5vLW9wIHJlc3BvbnNlLCB3ZSBhcmUgZG9uZSB3aXRoIHRoaXMgb25lIGdldE11bHRpIGluIHRoZSBwZXItYmFja2VuZCBmYW4tb3V0XG4gICAgICAgICAgICBpZiAocmVzcG9uc2UuaGVhZGVyLm9wY29kZSA9PT0gY29uc3RhbnRzLk9QX05PX09QKSB7XG4gICAgICAgICAgICAgIC8vIFRoaXMgZW5zdXJlcyB0aGUgaGFuZGxlciB3aWxsIGJlIGRlbGV0ZWQgZnJvbSB0aGUgcmVzcG9uc2VDYWxsYmFja3MgbWFwIGluIHNlcnZlci5qc1xuICAgICAgICAgICAgICAvLyBUaGlzIGlzbid0IHRlY2huaWNhbGx5IG5lZWRlZCBoZXJlIGJlY2F1c2UgdGhlIGxvZ2ljIGluIHNlcnZlci5qcyBhbHNvIGNoZWNrcyBpZiB0b3RhbEJvZHlMZW5ndGggPT09IDAsIGJ1dCBvdXIgdW5pdHRlc3RzIGFyZW4ndCBncmVhdCBhYm91dCBzZXR0aW5nIHRoYXQgZmllbGQsIGFuZCBhbHNvIHRoaXMgbWFrZXMgaXQgbW9yZSBleHBsaWNpdFxuICAgICAgICAgICAgICBoYW5kbGUucXVpZXQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgcmVzb2x2ZShyZXNwb25zZU1hcCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBjb25zdCBkZXNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuZGVzZXJpYWxpemUoXG4gICAgICAgICAgICAgICAgcmVzcG9uc2UuaGVhZGVyLm9wY29kZSxcbiAgICAgICAgICAgICAgICByZXNwb25zZS52YWwsXG4gICAgICAgICAgICAgICAgcmVzcG9uc2UuZXh0cmFzXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgIGNvbnN0IGtleSA9IHJlc3BvbnNlLmtleS50b1N0cmluZygpO1xuICAgICAgICAgICAgICByZXNwb25zZU1hcFtrZXldID0geyAuLi5kZXNlcmlhbGl6ZWQsIGNhczogcmVzcG9uc2UuaGVhZGVyLmNhcyB9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHJldHVybiByZWplY3QoXG4gICAgICAgICAgICAgIHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJHRVRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cylcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH07XG4gICAgICAvLyBUaGlzIHByZXZlbnRzIHRoZSBoYW5kbGVyIGZyb20gYmVpbmcgZGVsZXRlZFxuICAgICAgLy8gYWZ0ZXIgdGhlIGZpcnN0IHJlc3BvbnNlLiBMb2dpYyBpbiBzZXJ2ZXIuanMuXG4gICAgICBoYW5kbGUucXVpZXQgPSB0cnVlO1xuXG4gICAgICBjb25zdCByZXF1ZXN0ID0gdGhpcy5fYnVpbGRHZXRNdWx0aVJlcXVlc3Qoa2V5cyk7XG4gICAgICBzZXJ2Lm9uUmVzcG9uc2UodGhpcy5zZXEsIGhhbmRsZSk7XG4gICAgICBzZXJ2Lm9uRXJyb3IodGhpcy5zZXEsIHJlamVjdCk7XG4gICAgICB0aGlzLmluY3JTZXEoKTtcbiAgICAgIHNlcnYud3JpdGUocmVxdWVzdCk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldnMgdGhlIHZhbHVlIGF0IHRoZSBnaXZlbiBrZXlzIGluIG1lbWNhY2hlZC4gUmV0dXJucyBhIG1hcCBmcm9tIHRoZVxuICAgKiByZXF1ZXN0ZWQga2V5cyB0byByZXN1bHRzLCBvciBudWxsIGlmIHRoZSBrZXkgd2FzIG5vdCBmb3VuZC5cbiAgICovXG4gIGFzeW5jIGdldE11bHRpPEtleXMgZXh0ZW5kcyBzdHJpbmc+KFxuICAgIGtleXM6IEtleXNbXVxuICApOiBQcm9taXNlPEdldE11bHRpUmVzdWx0PEtleXMsIFZhbHVlLCBFeHRyYXM+IHwgbnVsbD4ge1xuICAgIGNvbnN0IHNlcnZlcktleXRvTG9va3VwS2V5czoge1xuICAgICAgW3NlcnZlcktleTogc3RyaW5nXTogc3RyaW5nW107XG4gICAgfSA9IHt9O1xuICAgIGtleXMuZm9yRWFjaCgobG9va3VwS2V5KSA9PiB7XG4gICAgICBjb25zdCBzZXJ2ZXJLZXkgPSB0aGlzLmxvb2t1cEtleVRvU2VydmVyS2V5KGxvb2t1cEtleSk7XG4gICAgICBpZiAoIXNlcnZlcktleXRvTG9va3VwS2V5c1tzZXJ2ZXJLZXldKSB7XG4gICAgICAgIHNlcnZlcktleXRvTG9va3VwS2V5c1tzZXJ2ZXJLZXldID0gW107XG4gICAgICB9XG4gICAgICBzZXJ2ZXJLZXl0b0xvb2t1cEtleXNbc2VydmVyS2V5XS5wdXNoKGxvb2t1cEtleSk7XG4gICAgfSk7XG5cbiAgICBjb25zdCB1c2VkU2VydmVyS2V5cyA9IE9iamVjdC5rZXlzKHNlcnZlcktleXRvTG9va3VwS2V5cyk7XG4gICAgY29uc3QgcmVzdWx0cyA9IGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgdXNlZFNlcnZlcktleXMubWFwKChzZXJ2ZXJLZXkpID0+IHtcbiAgICAgICAgY29uc3Qgc2VydmVyID0gdGhpcy5zZXJ2ZXJLZXlUb1NlcnZlcihzZXJ2ZXJLZXkpO1xuICAgICAgICByZXR1cm4gdGhpcy5fZ2V0TXVsdGlUb1NlcnZlcihzZXJ2ZXIsIHNlcnZlcktleXRvTG9va3VwS2V5c1tzZXJ2ZXJLZXldKTtcbiAgICAgIH0pXG4gICAgKTtcblxuICAgIHJldHVybiBPYmplY3QuYXNzaWduKHt9LCAuLi5yZXN1bHRzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIGBrZXlgIHRvIGB2YWx1ZWAuXG4gICAqL1xuICBhc3luYyBzZXQoXG4gICAga2V5OiBzdHJpbmcsXG4gICAgdmFsdWU6IFZhbHVlLFxuICAgIG9wdGlvbnM/OiB7IGV4cGlyZXM/OiBudW1iZXI7IGNhcz86IENBU1Rva2VuIH1cbiAgKTogUHJvbWlzZTxib29sZWFuIHwgbnVsbD4ge1xuICAgIGNvbnN0IGV4cGlyZXMgPSBvcHRpb25zPy5leHBpcmVzO1xuICAgIGNvbnN0IGNhcyA9IG9wdGlvbnM/LmNhcztcblxuICAgIC8vIFRPRE86IHN1cHBvcnQgZmxhZ3NcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBleHBpcmF0aW9uID0gbWFrZUV4cGlyYXRpb24oZXhwaXJlcyB8fCB0aGlzLm9wdGlvbnMuZXhwaXJlcyk7XG4gICAgY29uc3QgZXh0cmFzID0gQnVmZmVyLmNvbmNhdChbQnVmZmVyLmZyb20oXCIwMDAwMDAwMFwiLCBcImhleFwiKSwgZXhwaXJhdGlvbl0pO1xuICAgIGNvbnN0IHNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuc2VyaWFsaXplKFxuICAgICAgY29uc3RhbnRzLk9QX1NFVCxcbiAgICAgIHZhbHVlLFxuICAgICAgZXh0cmFzXG4gICAgKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gVXRpbHMuZW5jb2RlUmVxdWVzdCh7XG4gICAgICBoZWFkZXI6IHtcbiAgICAgICAgb3Bjb2RlOiBjb25zdGFudHMuT1BfU0VULFxuICAgICAgICBvcGFxdWU6IHRoaXMuc2VxLFxuICAgICAgICBjYXMsXG4gICAgICB9LFxuICAgICAga2V5LFxuICAgICAgdmFsdWU6IHNlcmlhbGl6ZWQudmFsdWUsXG4gICAgICBleHRyYXM6IHNlcmlhbGl6ZWQuZXh0cmFzLFxuICAgIH0pO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuS0VZX0VYSVNUUzpcbiAgICAgICAgaWYgKGNhcykge1xuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiU0VUXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgICAgICB9XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiU0VUXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBBRERcbiAgICpcbiAgICogQWRkcyB0aGUgZ2l2ZW4gX2tleV8gYW5kIF92YWx1ZV8gdG8gbWVtY2FjaGUuIFRoZSBvcGVyYXRpb24gb25seSBzdWNjZWVkc1xuICAgKiBpZiB0aGUga2V5IGlzIG5vdCBhbHJlYWR5IHNldC5cbiAgICpcbiAgICogVGhlIG9wdGlvbnMgZGljdGlvbmFyeSB0YWtlczpcbiAgICogKiBfZXhwaXJlc186IG92ZXJyaWRlcyB0aGUgZGVmYXVsdCBleHBpcmF0aW9uIChzZWUgYENsaWVudC5jcmVhdGVgKSBmb3IgdGhpc1xuICAgKiAgICAgICAgICAgICAgcGFydGljdWxhciBrZXktdmFsdWUgcGFpci5cbiAgICovXG4gIGFzeW5jIGFkZChcbiAgICBrZXk6IHN0cmluZyxcbiAgICB2YWx1ZTogVmFsdWUsXG4gICAgb3B0aW9ucz86IHsgZXhwaXJlcz86IG51bWJlciB9XG4gICk6IFByb21pc2U8Ym9vbGVhbiB8IG51bGw+IHtcbiAgICAvLyBUT0RPOiBzdXBwb3J0IGZsYWdzLCBzdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBleHBpcmF0aW9uID0gbWFrZUV4cGlyYXRpb24ob3B0aW9ucz8uZXhwaXJlcyB8fCB0aGlzLm9wdGlvbnMuZXhwaXJlcyk7XG4gICAgY29uc3QgZXh0cmFzID0gQnVmZmVyLmNvbmNhdChbQnVmZmVyLmZyb20oXCIwMDAwMDAwMFwiLCBcImhleFwiKSwgZXhwaXJhdGlvbl0pO1xuXG4gICAgY29uc3Qgb3Bjb2RlID0gY29uc3RhbnRzLk9QX0FERDtcbiAgICBjb25zdCBzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLnNlcmlhbGl6ZShvcGNvZGUsIHZhbHVlLCBleHRyYXMpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgIG9wY29kZSxcbiAgICAgIGtleSxcbiAgICAgIHNlcmlhbGl6ZWQuZXh0cmFzLFxuICAgICAgc2VyaWFsaXplZC52YWx1ZSxcbiAgICAgIHRoaXMuc2VxXG4gICAgKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9FWElTVFM6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiQUREXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXBsYWNlcyB0aGUgZ2l2ZW4gX2tleV8gYW5kIF92YWx1ZV8gdG8gbWVtY2FjaGUuIFRoZSBvcGVyYXRpb24gb25seSBzdWNjZWVkc1xuICAgKiBpZiB0aGUga2V5IGlzIGFscmVhZHkgcHJlc2VudC5cbiAgICovXG4gIGFzeW5jIHJlcGxhY2UoXG4gICAga2V5OiBzdHJpbmcsXG4gICAgdmFsdWU6IFZhbHVlLFxuICAgIG9wdGlvbnM/OiB7IGV4cGlyZXM/OiBudW1iZXIgfVxuICApOiBQcm9taXNlPGJvb2xlYW4gfCBudWxsPiB7XG4gICAgLy8gVE9ETzogc3VwcG9ydCBmbGFncywgc3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgZXhwaXJhdGlvbiA9IG1ha2VFeHBpcmF0aW9uKG9wdGlvbnM/LmV4cGlyZXMgfHwgdGhpcy5vcHRpb25zLmV4cGlyZXMpO1xuICAgIGNvbnN0IGV4dHJhcyA9IEJ1ZmZlci5jb25jYXQoW0J1ZmZlci5mcm9tKFwiMDAwMDAwMDBcIiwgXCJoZXhcIiksIGV4cGlyYXRpb25dKTtcblxuICAgIGNvbnN0IG9wY29kZTogY29uc3RhbnRzLk9QID0gY29uc3RhbnRzLk9QX1JFUExBQ0U7XG4gICAgY29uc3Qgc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5zZXJpYWxpemUob3Bjb2RlLCB2YWx1ZSwgZXh0cmFzKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICBvcGNvZGUsXG4gICAgICBrZXksXG4gICAgICBzZXJpYWxpemVkLmV4dHJhcyxcbiAgICAgIHNlcmlhbGl6ZWQudmFsdWUsXG4gICAgICB0aGlzLnNlcVxuICAgICk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfTk9UX0ZPVU5EOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiUkVQTEFDRVwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRGVsZXRlcyB0aGUgZ2l2ZW4gX2tleV8gZnJvbSBtZW1jYWNoZS4gVGhlIG9wZXJhdGlvbiBvbmx5IHN1Y2NlZWRzXG4gICAqIGlmIHRoZSBrZXkgaXMgYWxyZWFkeSBwcmVzZW50LlxuICAgKi9cbiAgYXN5bmMgZGVsZXRlKGtleTogc3RyaW5nKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgLy8gVE9ETzogU3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKDQsIGtleSwgXCJcIiwgXCJcIiwgdGhpcy5zZXEpO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuXG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfTk9UX0ZPVU5EOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiREVMRVRFXCIsIHJlc3BvbnNlPy5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogSW5jcmVtZW50cyB0aGUgZ2l2ZW4gX2tleV8gaW4gbWVtY2FjaGUuXG4gICAqL1xuICBhc3luYyBpbmNyZW1lbnQoXG4gICAga2V5OiBzdHJpbmcsXG4gICAgYW1vdW50OiBudW1iZXIsXG4gICAgb3B0aW9ucz86IHsgaW5pdGlhbD86IG51bWJlcjsgZXhwaXJlcz86IG51bWJlciB9XG4gICk6IFByb21pc2U8eyB2YWx1ZTogbnVtYmVyIHwgbnVsbDsgc3VjY2VzczogYm9vbGVhbiB8IG51bGwgfT4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IGluaXRpYWwgPSBvcHRpb25zPy5pbml0aWFsIHx8IDA7XG4gICAgY29uc3QgZXhwaXJlcyA9IG9wdGlvbnM/LmV4cGlyZXMgfHwgdGhpcy5vcHRpb25zLmV4cGlyZXM7XG4gICAgY29uc3QgZXh0cmFzID0gbWFrZUFtb3VudEluaXRpYWxBbmRFeHBpcmF0aW9uKGFtb3VudCwgaW5pdGlhbCwgZXhwaXJlcyk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKFxuICAgICAgY29uc3RhbnRzLk9QX0lOQ1JFTUVOVCxcbiAgICAgIGtleSxcbiAgICAgIGV4dHJhcyxcbiAgICAgIFwiXCIsXG4gICAgICB0aGlzLnNlcVxuICAgICk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIGNvbnN0IGJ1ZkludCA9XG4gICAgICAgICAgKHJlc3BvbnNlLnZhbC5yZWFkVUludDMyQkUoMCkgPDwgOCkgKyByZXNwb25zZS52YWwucmVhZFVJbnQzMkJFKDQpO1xuICAgICAgICByZXR1cm4geyB2YWx1ZTogYnVmSW50LCBzdWNjZXNzOiB0cnVlIH07XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiSU5DUkVNRU5UXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBEZWNyZW1lbnRzIHRoZSBnaXZlbiBga2V5YCBpbiBtZW1jYWNoZS5cbiAgICovXG4gIGFzeW5jIGRlY3JlbWVudChcbiAgICBrZXk6IHN0cmluZyxcbiAgICBhbW91bnQ6IG51bWJlcixcbiAgICBvcHRpb25zOiB7IGluaXRpYWw/OiBudW1iZXI7IGV4cGlyZXM/OiBudW1iZXIgfVxuICApOiBQcm9taXNlPHsgdmFsdWU6IG51bWJlciB8IG51bGw7IHN1Y2Nlc3M6IGJvb2xlYW4gfCBudWxsIH0+IHtcbiAgICAvLyBUT0RPOiBzdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBpbml0aWFsID0gb3B0aW9ucy5pbml0aWFsIHx8IDA7XG4gICAgY29uc3QgZXhwaXJlcyA9IG9wdGlvbnMuZXhwaXJlcyB8fCB0aGlzLm9wdGlvbnMuZXhwaXJlcztcbiAgICBjb25zdCBleHRyYXMgPSBtYWtlQW1vdW50SW5pdGlhbEFuZEV4cGlyYXRpb24oYW1vdW50LCBpbml0aWFsLCBleHBpcmVzKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICBjb25zdGFudHMuT1BfREVDUkVNRU5ULFxuICAgICAga2V5LFxuICAgICAgZXh0cmFzLFxuICAgICAgXCJcIixcbiAgICAgIHRoaXMuc2VxXG4gICAgKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgY29uc3QgYnVmSW50ID1cbiAgICAgICAgICAocmVzcG9uc2UudmFsLnJlYWRVSW50MzJCRSgwKSA8PCA4KSArIHJlc3BvbnNlLnZhbC5yZWFkVUludDMyQkUoNCk7XG4gICAgICAgIHJldHVybiB7IHZhbHVlOiBidWZJbnQsIHN1Y2Nlc3M6IHRydWUgfTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJERUNSRU1FTlRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEFwcGVuZCB0aGUgZ2l2ZW4gX3ZhbHVlXyB0byB0aGUgdmFsdWUgYXNzb2NpYXRlZCB3aXRoIHRoZSBnaXZlbiBfa2V5XyBpblxuICAgKiBtZW1jYWNoZS4gVGhlIG9wZXJhdGlvbiBvbmx5IHN1Y2NlZWRzIGlmIHRoZSBrZXkgaXMgYWxyZWFkeSBwcmVzZW50LlxuICAgKi9cbiAgYXN5bmMgYXBwZW5kKGtleTogc3RyaW5nLCB2YWx1ZTogVmFsdWUpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAvLyBUT0RPOiBzdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBvcGNvZGU6IGNvbnN0YW50cy5PUCA9IGNvbnN0YW50cy5PUF9BUFBFTkQ7XG4gICAgY29uc3Qgc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5zZXJpYWxpemUob3Bjb2RlLCB2YWx1ZSwgXCJcIik7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKFxuICAgICAgb3Bjb2RlLFxuICAgICAga2V5LFxuICAgICAgc2VyaWFsaXplZC5leHRyYXMsXG4gICAgICBzZXJpYWxpemVkLnZhbHVlLFxuICAgICAgdGhpcy5zZXFcbiAgICApO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuS0VZX05PVF9GT1VORDpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIkFQUEVORFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUHJlcGVuZCB0aGUgZ2l2ZW4gX3ZhbHVlXyB0byB0aGUgdmFsdWUgYXNzb2NpYXRlZCB3aXRoIHRoZSBnaXZlbiBfa2V5XyBpblxuICAgKiBtZW1jYWNoZS4gVGhlIG9wZXJhdGlvbiBvbmx5IHN1Y2NlZWRzIGlmIHRoZSBrZXkgaXMgYWxyZWFkeSBwcmVzZW50LlxuICAgKi9cbiAgYXN5bmMgcHJlcGVuZChrZXk6IHN0cmluZywgdmFsdWU6IFZhbHVlKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgLy8gVE9ETzogc3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3Qgb3Bjb2RlOiBjb25zdGFudHMuT1AgPSBjb25zdGFudHMuT1BfUFJFUEVORDtcbiAgICBjb25zdCBzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLnNlcmlhbGl6ZShvcGNvZGUsIHZhbHVlLCBcIlwiKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICBvcGNvZGUsXG4gICAgICBrZXksXG4gICAgICBzZXJpYWxpemVkLmV4dHJhcyxcbiAgICAgIHNlcmlhbGl6ZWQudmFsdWUsXG4gICAgICB0aGlzLnNlcVxuICAgICk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfTk9UX0ZPVU5EOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiUFJFUEVORFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVG91Y2ggc2V0cyBhbiBleHBpcmF0aW9uIHZhbHVlLCBnaXZlbiBieSBfZXhwaXJlc18sIG9uIHRoZSBnaXZlbiBfa2V5XyBpblxuICAgKiBtZW1jYWNoZS4gVGhlIG9wZXJhdGlvbiBvbmx5IHN1Y2NlZWRzIGlmIHRoZSBrZXkgaXMgYWxyZWFkeSBwcmVzZW50LlxuICAgKi9cbiAgYXN5bmMgdG91Y2goa2V5OiBzdHJpbmcsIGV4cGlyZXM6IG51bWJlcik6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IGV4dHJhcyA9IG1ha2VFeHBpcmF0aW9uKGV4cGlyZXMgfHwgdGhpcy5vcHRpb25zLmV4cGlyZXMpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcigweDFjLCBrZXksIGV4dHJhcywgXCJcIiwgdGhpcy5zZXEpO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuS0VZX05PVF9GT1VORDpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIlRPVUNIXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBGTFVTSFxuICAgKlxuICAgKiBGbHVzaGVzIHRoZSBjYWNoZSBvbiBlYWNoIGNvbm5lY3RlZCBzZXJ2ZXIuIFRoZSBjYWxsYmFjayBzaWduYXR1cmUgaXM6XG4gICAqXG4gICAqICAgICBjYWxsYmFjayhsYXN0RXJyLCByZXN1bHRzKVxuICAgKlxuICAgKiB3aGVyZSBfbGFzdEVycl8gaXMgdGhlIGxhc3QgZXJyb3IgZW5jb3VudGVyZWQgKG9yIG51bGwsIGluIHRoZSBjb21tb24gY2FzZVxuICAgKiBvZiBubyBlcnJvcnMpLiBfcmVzdWx0c18gaXMgYSBkaWN0aW9uYXJ5IG1hcHBpbmcgYFwiaG9zdG5hbWU6cG9ydFwiYCB0byBlaXRoZXJcbiAgICogYHRydWVgIChpZiB0aGUgb3BlcmF0aW9uIHdhcyBzdWNjZXNzZnVsKSwgb3IgYW4gZXJyb3IuXG4gICAqIEBwYXJhbSBjYWxsYmFja1xuICAgKi9cbiAgZmx1c2goKTogUHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBib29sZWFuIHwgRXJyb3I+PjtcbiAgZmx1c2goXG4gICAgY2FsbGJhY2s6IChcbiAgICAgIGVycjogRXJyb3IgfCBudWxsLFxuICAgICAgcmVzdWx0czogUmVjb3JkPHN0cmluZywgYm9vbGVhbiB8IEVycm9yPlxuICAgICkgPT4gdm9pZFxuICApOiB2b2lkO1xuICBmbHVzaChcbiAgICBjYWxsYmFjaz86IChcbiAgICAgIGVycjogRXJyb3IgfCBudWxsLFxuICAgICAgcmVzdWx0czogUmVjb3JkPHN0cmluZywgYm9vbGVhbiB8IEVycm9yPlxuICAgICkgPT4gdm9pZFxuICApIHtcbiAgICBpZiAoY2FsbGJhY2sgPT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuIHByb21pc2lmeSgoY2FsbGJhY2spID0+IHtcbiAgICAgICAgdGhpcy5mbHVzaChmdW5jdGlvbiAoZXJyLCByZXN1bHRzKSB7XG4gICAgICAgICAgY2FsbGJhY2soZXJyLCByZXN1bHRzKTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9XG4gICAgLy8gVE9ETzogc3VwcG9ydCBleHBpcmF0aW9uXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKDB4MDgsIFwiXCIsIFwiXCIsIFwiXCIsIHRoaXMuc2VxKTtcbiAgICBsZXQgY291bnQgPSB0aGlzLnNlcnZlcnMubGVuZ3RoO1xuICAgIGNvbnN0IHJlc3VsdDogUmVjb3JkPHN0cmluZywgYm9vbGVhbiB8IEVycm9yPiA9IHt9O1xuICAgIGxldCBsYXN0RXJyOiBFcnJvciB8IG51bGwgPSBudWxsO1xuXG4gICAgY29uc3QgaGFuZGxlRmx1c2ggPSBmdW5jdGlvbiAoc2VxOiBudW1iZXIsIHNlcnY6IFNlcnZlcikge1xuICAgICAgc2Vydi5vblJlc3BvbnNlKHNlcSwgZnVuY3Rpb24gKC8qIHJlc3BvbnNlICovKSB7XG4gICAgICAgIGNvdW50IC09IDE7XG4gICAgICAgIHJlc3VsdFtzZXJ2Lmhvc3Rwb3J0U3RyaW5nKCldID0gdHJ1ZTtcbiAgICAgICAgaWYgKGNhbGxiYWNrICYmIGNvdW50ID09PSAwKSB7XG4gICAgICAgICAgY2FsbGJhY2sobGFzdEVyciwgcmVzdWx0KTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICBzZXJ2Lm9uRXJyb3Ioc2VxLCBmdW5jdGlvbiAoZXJyKSB7XG4gICAgICAgIGNvdW50IC09IDE7XG4gICAgICAgIGxhc3RFcnIgPSBlcnI7XG4gICAgICAgIHJlc3VsdFtzZXJ2Lmhvc3Rwb3J0U3RyaW5nKCldID0gZXJyO1xuICAgICAgICBpZiAoY2FsbGJhY2sgJiYgY291bnQgPT09IDApIHtcbiAgICAgICAgICBjYWxsYmFjayhsYXN0RXJyLCByZXN1bHQpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHNlcnYud3JpdGUocmVxdWVzdCk7XG4gICAgfTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5zZXJ2ZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBoYW5kbGVGbHVzaCh0aGlzLnNlcSwgdGhpcy5zZXJ2ZXJzW2ldKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU1RBVFNfV0lUSF9LRVlcbiAgICpcbiAgICogU2VuZHMgYSBtZW1jYWNoZSBzdGF0cyBjb21tYW5kIHdpdGggYSBrZXkgdG8gZWFjaCBjb25uZWN0ZWQgc2VydmVyLiBUaGVcbiAgICogY2FsbGJhY2sgaXMgaW52b2tlZCAqKk9OQ0UgUEVSIFNFUlZFUioqIGFuZCBoYXMgdGhlIHNpZ25hdHVyZTpcbiAgICpcbiAgICogICAgIGNhbGxiYWNrKGVyciwgc2VydmVyLCBzdGF0cylcbiAgICpcbiAgICogX3NlcnZlcl8gaXMgdGhlIGBcImhvc3RuYW1lOnBvcnRcImAgb2YgdGhlIHNlcnZlciwgYW5kIF9zdGF0c18gaXMgYSBkaWN0aW9uYXJ5XG4gICAqIG1hcHBpbmcgdGhlIHN0YXQgbmFtZSB0byB0aGUgdmFsdWUgb2YgdGhlIHN0YXRpc3RpYyBhcyBhIHN0cmluZy5cbiAgICogQHBhcmFtIGtleVxuICAgKiBAcGFyYW0gY2FsbGJhY2tcbiAgICovXG4gIHN0YXRzV2l0aEtleShcbiAgICBrZXk6IHN0cmluZyxcbiAgICBjYWxsYmFjaz86IChcbiAgICAgIGVycjogRXJyb3IgfCBudWxsLFxuICAgICAgc2VydmVyOiBzdHJpbmcsXG4gICAgICBzdGF0czogUmVjb3JkPHN0cmluZywgc3RyaW5nPiB8IG51bGxcbiAgICApID0+IHZvaWRcbiAgKTogdm9pZCB7XG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKDB4MTAsIGtleSwgXCJcIiwgXCJcIiwgdGhpcy5zZXEpO1xuXG4gICAgY29uc3QgaGFuZGxlU3RhdHMgPSAoc2VxOiBudW1iZXIsIHNlcnY6IFNlcnZlcikgPT4ge1xuICAgICAgY29uc3QgcmVzdWx0OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge307XG4gICAgICBjb25zdCBoYW5kbGU6IE9uUmVzcG9uc2VDYWxsYmFjayA9IChyZXNwb25zZSkgPT4ge1xuICAgICAgICAvLyBlbmQgb2Ygc3RhdCByZXNwb25zZXNcbiAgICAgICAgaWYgKHJlc3BvbnNlLmhlYWRlci50b3RhbEJvZHlMZW5ndGggPT09IDApIHtcbiAgICAgICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKG51bGwsIHNlcnYuaG9zdHBvcnRTdHJpbmcoKSwgcmVzdWx0KTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIC8vIHByb2Nlc3Mgc2luZ2xlIHN0YXQgbGluZSByZXNwb25zZVxuICAgICAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgICAgICByZXN1bHRbcmVzcG9uc2Uua2V5LnRvU3RyaW5nKCldID0gcmVzcG9uc2UudmFsLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgY29uc3QgZXJyb3IgPSB0aGlzLmhhbmRsZVJlc3BvbnNlRXJyb3IoXG4gICAgICAgICAgICAgIGBTVEFUUyAoJHtrZXl9KWAsXG4gICAgICAgICAgICAgIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMsXG4gICAgICAgICAgICAgIHVuZGVmaW5lZFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgICAgICBjYWxsYmFjayhlcnJvciwgc2Vydi5ob3N0cG9ydFN0cmluZygpLCBudWxsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfTtcbiAgICAgIGhhbmRsZS5xdWlldCA9IHRydWU7XG5cbiAgICAgIHNlcnYub25SZXNwb25zZShzZXEsIGhhbmRsZSk7XG4gICAgICBzZXJ2Lm9uRXJyb3Ioc2VxLCBmdW5jdGlvbiAoZXJyKSB7XG4gICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgIGNhbGxiYWNrKGVyciwgc2Vydi5ob3N0cG9ydFN0cmluZygpLCBudWxsKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICBzZXJ2LndyaXRlKHJlcXVlc3QpO1xuICAgIH07XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuc2VydmVycy5sZW5ndGg7IGkrKykge1xuICAgICAgaGFuZGxlU3RhdHModGhpcy5zZXEsIHRoaXMuc2VydmVyc1tpXSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNUQVRTXG4gICAqXG4gICAqIEZldGNoZXMgbWVtY2FjaGUgc3RhdHMgZnJvbSBlYWNoIGNvbm5lY3RlZCBzZXJ2ZXIuIFRoZSBjYWxsYmFjayBpcyBpbnZva2VkXG4gICAqICoqT05DRSBQRVIgU0VSVkVSKiogYW5kIGhhcyB0aGUgc2lnbmF0dXJlOlxuICAgKlxuICAgKiAgICAgY2FsbGJhY2soZXJyLCBzZXJ2ZXIsIHN0YXRzKVxuICAgKlxuICAgKiBfc2VydmVyXyBpcyB0aGUgYFwiaG9zdG5hbWU6cG9ydFwiYCBvZiB0aGUgc2VydmVyLCBhbmQgX3N0YXRzXyBpcyBhXG4gICAqIGRpY3Rpb25hcnkgbWFwcGluZyB0aGUgc3RhdCBuYW1lIHRvIHRoZSB2YWx1ZSBvZiB0aGUgc3RhdGlzdGljIGFzIGEgc3RyaW5nLlxuICAgKiBAcGFyYW0gY2FsbGJhY2tcbiAgICovXG4gIHN0YXRzKFxuICAgIGNhbGxiYWNrPzogKFxuICAgICAgZXJyOiBFcnJvciB8IG51bGwsXG4gICAgICBzZXJ2ZXI6IHN0cmluZyxcbiAgICAgIHN0YXRzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+IHwgbnVsbFxuICAgICkgPT4gdm9pZFxuICApOiB2b2lkIHtcbiAgICB0aGlzLnN0YXRzV2l0aEtleShcIlwiLCBjYWxsYmFjayk7XG4gIH1cblxuICAvKipcbiAgICogUkVTRVRfU1RBVFNcbiAgICpcbiAgICogUmVzZXQgdGhlIHN0YXRpc3RpY3MgZWFjaCBzZXJ2ZXIgaXMga2VlcGluZyBiYWNrIHRvIHplcm8uIFRoaXMgZG9lc24ndCBjbGVhclxuICAgKiBzdGF0cyBzdWNoIGFzIGl0ZW0gY291bnQsIGJ1dCB0ZW1wb3Jhcnkgc3RhdHMgc3VjaCBhcyB0b3RhbCBudW1iZXIgb2ZcbiAgICogY29ubmVjdGlvbnMgb3ZlciB0aW1lLlxuICAgKlxuICAgKiBUaGUgY2FsbGJhY2sgaXMgaW52b2tlZCAqKk9OQ0UgUEVSIFNFUlZFUioqIGFuZCBoYXMgdGhlIHNpZ25hdHVyZTpcbiAgICpcbiAgICogICAgIGNhbGxiYWNrKGVyciwgc2VydmVyKVxuICAgKlxuICAgKiBfc2VydmVyXyBpcyB0aGUgYFwiaG9zdG5hbWU6cG9ydFwiYCBvZiB0aGUgc2VydmVyLlxuICAgKiBAcGFyYW0gY2FsbGJhY2tcbiAgICovXG4gIHJlc2V0U3RhdHMoXG4gICAgY2FsbGJhY2s/OiAoXG4gICAgICBlcnI6IEVycm9yIHwgbnVsbCxcbiAgICAgIHNlcnZlcjogc3RyaW5nLFxuICAgICAgc3RhdHM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gfCBudWxsXG4gICAgKSA9PiB2b2lkXG4gICk6IHZvaWQge1xuICAgIHRoaXMuc3RhdHNXaXRoS2V5KFwicmVzZXRcIiwgY2FsbGJhY2spO1xuICB9XG5cbiAgLyoqXG4gICAqIFFVSVRcbiAgICpcbiAgICogQ2xvc2VzIHRoZSBjb25uZWN0aW9uIHRvIGVhY2ggc2VydmVyLCBub3RpZnlpbmcgdGhlbSBvZiB0aGlzIGludGVudGlvbi4gTm90ZVxuICAgKiB0aGF0IHF1aXQgY2FuIHJhY2UgYWdhaW5zdCBhbHJlYWR5IG91dHN0YW5kaW5nIHJlcXVlc3RzIHdoZW4gdGhvc2UgcmVxdWVzdHNcbiAgICogZmFpbCBhbmQgYXJlIHJldHJpZWQsIGxlYWRpbmcgdG8gdGhlIHF1aXQgY29tbWFuZCB3aW5uaW5nIGFuZCBjbG9zaW5nIHRoZVxuICAgKiBjb25uZWN0aW9uIGJlZm9yZSB0aGUgcmV0cmllcyBjb21wbGV0ZS5cbiAgICovXG4gIHF1aXQoKSB7XG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgLy8gVE9ETzogTmljZXIgcGVyaGFwcyB0byBkbyBRVUlUUSAoMHgxNykgYnV0IG5lZWQgYSBuZXcgY2FsbGJhY2sgZm9yIHdoZW5cbiAgICAvLyB3cml0ZSBpcyBkb25lLlxuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcigweDA3LCBcIlwiLCBcIlwiLCBcIlwiLCB0aGlzLnNlcSk7IC8vIFFVSVRcbiAgICBsZXQgc2VydjtcblxuICAgIGNvbnN0IGhhbmRsZVF1aXQgPSBmdW5jdGlvbiAoc2VxOiBudW1iZXIsIHNlcnY6IFNlcnZlcikge1xuICAgICAgc2Vydi5vblJlc3BvbnNlKHNlcSwgZnVuY3Rpb24gKC8qIHJlc3BvbnNlICovKSB7XG4gICAgICAgIHNlcnYuY2xvc2UoKTtcbiAgICAgIH0pO1xuICAgICAgc2Vydi5vbkVycm9yKHNlcSwgZnVuY3Rpb24gKC8qIGVyciAqLykge1xuICAgICAgICBzZXJ2LmNsb3NlKCk7XG4gICAgICB9KTtcbiAgICAgIHNlcnYud3JpdGUocmVxdWVzdCk7XG4gICAgfTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5zZXJ2ZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBzZXJ2ID0gdGhpcy5zZXJ2ZXJzW2ldO1xuICAgICAgaGFuZGxlUXVpdCh0aGlzLnNlcSwgc2Vydik7XG4gICAgfVxuICB9XG5cbiAgX3ZlcnNpb24oc2VydmVyOiBTZXJ2ZXIpOiBQcm9taXNlPHsgdmFsdWU6IFZhbHVlIHwgbnVsbCB9PiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIHRoaXMuaW5jclNlcSgpO1xuICAgICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKFxuICAgICAgICBjb25zdGFudHMuT1BfVkVSU0lPTixcbiAgICAgICAgXCJcIixcbiAgICAgICAgXCJcIixcbiAgICAgICAgXCJcIixcbiAgICAgICAgdGhpcy5zZXFcbiAgICAgICk7XG4gICAgICB0aGlzLnBlcmZvcm1PblNlcnZlcihzZXJ2ZXIsIHJlcXVlc3QsIHRoaXMuc2VxLCAoZXJyLCByZXNwb25zZSkgPT4ge1xuICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgcmV0dXJuIHJlamVjdChlcnIpO1xuICAgICAgICB9XG5cbiAgICAgICAgc3dpdGNoIChyZXNwb25zZSEuaGVhZGVyLnN0YXR1cykge1xuICAgICAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgICAgIC8qIFRPRE86IHRoaXMgaXMgYnVnZ2VkLCB3ZSBzaG91bGQndCB1c2UgdGhlIGRlc2VyaWFsaXplciBoZXJlLCBzaW5jZSB2ZXJzaW9uIGFsd2F5cyByZXR1cm5zIGEgdmVyc2lvbiBzdHJpbmcuXG4gICAgICAgICAgICAgVGhlIGRlc2VyaWFsaXplciBzaG91bGQgb25seSBiZSB1c2VkIG9uIHVzZXIga2V5IGRhdGEuICovXG4gICAgICAgICAgICBjb25zdCBkZXNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuZGVzZXJpYWxpemUoXG4gICAgICAgICAgICAgIHJlc3BvbnNlIS5oZWFkZXIub3Bjb2RlLFxuICAgICAgICAgICAgICByZXNwb25zZSEudmFsLFxuICAgICAgICAgICAgICByZXNwb25zZSEuZXh0cmFzXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgcmV0dXJuIHJlc29sdmUoeyB2YWx1ZTogZGVzZXJpYWxpemVkLnZhbHVlIH0pO1xuICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICByZXR1cm4gcmVqZWN0KFxuICAgICAgICAgICAgICB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiVkVSU0lPTlwiLCByZXNwb25zZSEuaGVhZGVyLnN0YXR1cylcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlcXVlc3QgdGhlIHNlcnZlciB2ZXJzaW9uIGZyb20gdGhlIFwiZmlyc3RcIiBzZXJ2ZXIgaW4gdGhlIGJhY2tlbmQgcG9vbC5cbiAgICogVGhlIHNlcnZlciByZXNwb25kcyB3aXRoIGEgcGFja2V0IGNvbnRhaW5pbmcgdGhlIHZlcnNpb24gc3RyaW5nIGluIHRoZSBib2R5IHdpdGggdGhlIGZvbGxvd2luZyBmb3JtYXQ6IFwieC55LnpcIlxuICAgKi9cbiAgdmVyc2lvbigpOiBQcm9taXNlPHsgdmFsdWU6IFZhbHVlIHwgbnVsbCB9PiB7XG4gICAgY29uc3Qgc2VydmVyID0gdGhpcy5zZXJ2ZXJLZXlUb1NlcnZlcih0aGlzLnNlcnZlcktleXNbMF0pO1xuICAgIHJldHVybiB0aGlzLl92ZXJzaW9uKHNlcnZlcik7XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldmVzIHRoZSBzZXJ2ZXIgdmVyc2lvbiBmcm9tIGFsbCB0aGUgc2VydmVyc1xuICAgKiBpbiB0aGUgYmFja2VuZCBwb29sLCBlcnJvcnMgaWYgYW55IG9uZSBvZiB0aGVtIGhhcyBhblxuICAgKiBlcnJvclxuICAgKi9cbiAgYXN5bmMgdmVyc2lvbkFsbCgpOiBQcm9taXNlPHtcbiAgICB2YWx1ZXM6IFJlY29yZDxzdHJpbmcsIFZhbHVlIHwgbnVsbD47XG4gIH0+IHtcbiAgICBjb25zdCB2ZXJzaW9uT2JqZWN0cyA9IGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgdGhpcy5zZXJ2ZXJLZXlzLm1hcCgoc2VydmVyS2V5KSA9PiB7XG4gICAgICAgIGNvbnN0IHNlcnZlciA9IHRoaXMuc2VydmVyS2V5VG9TZXJ2ZXIoc2VydmVyS2V5KTtcblxuICAgICAgICByZXR1cm4gdGhpcy5fdmVyc2lvbihzZXJ2ZXIpLnRoZW4oKHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgcmV0dXJuIHsgc2VydmVyS2V5OiBzZXJ2ZXJLZXksIHZhbHVlOiByZXNwb25zZS52YWx1ZSB9O1xuICAgICAgICB9KTtcbiAgICAgIH0pXG4gICAgKTtcbiAgICBjb25zdCB2YWx1ZXMgPSB2ZXJzaW9uT2JqZWN0cy5yZWR1Y2UoKGFjY3VtdWxhdG9yLCB2ZXJzaW9uT2JqZWN0KSA9PiB7XG4gICAgICBhY2N1bXVsYXRvclt2ZXJzaW9uT2JqZWN0LnNlcnZlcktleV0gPSB2ZXJzaW9uT2JqZWN0LnZhbHVlO1xuICAgICAgcmV0dXJuIGFjY3VtdWxhdG9yO1xuICAgIH0sIHt9IGFzIFJlY29yZDxzdHJpbmcsIFZhbHVlIHwgbnVsbD4pO1xuICAgIHJldHVybiB7IHZhbHVlczogdmFsdWVzIH07XG4gIH1cblxuICAvKipcbiAgICogQ2xvc2VzIChhYnJ1cHRseSkgY29ubmVjdGlvbnMgdG8gYWxsIHRoZSBzZXJ2ZXJzLlxuICAgKiBAc2VlIHRoaXMucXVpdFxuICAgKi9cbiAgY2xvc2UoKSB7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnNlcnZlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHRoaXMuc2VydmVyc1tpXS5jbG9zZSgpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBQZXJmb3JtIGEgZ2VuZXJpYyBzaW5nbGUgcmVzcG9uc2Ugb3BlcmF0aW9uIChnZXQsIHNldCBldGMpIG9uIG9uZSBzZXJ2ZXJcbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IGtleSB0aGUga2V5IHRvIGhhc2ggdG8gZ2V0IGEgc2VydmVyIGZyb20gdGhlIHBvb2xcbiAgICogQHBhcmFtIHtidWZmZXJ9IHJlcXVlc3QgYSBidWZmZXIgY29udGFpbmluZyB0aGUgcmVxdWVzdFxuICAgKiBAcGFyYW0ge251bWJlcn0gc2VxIHRoZSBzZXF1ZW5jZSBudW1iZXIgb2YgdGhlIG9wZXJhdGlvbi4gSXQgaXMgdXNlZCB0byBwaW4gdGhlIGNhbGxiYWNrc1xuICAgICAgICAgICAgICAgICAgICAgICAgIHRvIGEgc3BlY2lmaWMgb3BlcmF0aW9uIGFuZCBzaG91bGQgbmV2ZXIgY2hhbmdlIGR1cmluZyBhIGBwZXJmb3JtYC5cbiAgICogQHBhcmFtIHtudW1iZXI/fSByZXRyaWVzIG51bWJlciBvZiB0aW1lcyB0byByZXRyeSByZXF1ZXN0IG9uIGZhaWx1cmVcbiAgICovXG4gIHBlcmZvcm0oXG4gICAga2V5OiBzdHJpbmcsXG4gICAgcmVxdWVzdDogQnVmZmVyLFxuICAgIHNlcTogbnVtYmVyLFxuICAgIHJldHJpZXM/OiBudW1iZXJcbiAgKTogUHJvbWlzZTxNZXNzYWdlPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGNvbnN0IHNlcnZlcktleSA9IHRoaXMubG9va3VwS2V5VG9TZXJ2ZXJLZXkoa2V5KTtcbiAgICAgIGNvbnN0IHNlcnZlciA9IHRoaXMuc2VydmVyS2V5VG9TZXJ2ZXIoc2VydmVyS2V5KTtcblxuICAgICAgaWYgKCFzZXJ2ZXIpIHtcbiAgICAgICAgcmV0dXJuIHJlamVjdChuZXcgRXJyb3IoXCJObyBzZXJ2ZXJzIGF2YWlsYWJsZVwiKSk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMucGVyZm9ybU9uU2VydmVyKFxuICAgICAgICBzZXJ2ZXIsXG4gICAgICAgIHJlcXVlc3QsXG4gICAgICAgIHNlcSxcbiAgICAgICAgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgcmV0dXJuIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJlc29sdmUocmVzcG9uc2UhKTtcbiAgICAgICAgfSxcbiAgICAgICAgcmV0cmllc1xuICAgICAgKTtcbiAgICB9KTtcbiAgfVxuXG4gIHBlcmZvcm1PblNlcnZlcihcbiAgICBzZXJ2ZXI6IFNlcnZlcixcbiAgICByZXF1ZXN0OiBCdWZmZXIsXG4gICAgc2VxOiBudW1iZXIsXG4gICAgY2FsbGJhY2s6IFJlc3BvbnNlT3JFcnJvckNhbGxiYWNrLFxuICAgIHJldHJpZXM6IG51bWJlciA9IDBcbiAgKSB7XG4gICAgY29uc3QgX3RoaXMgPSB0aGlzO1xuXG4gICAgcmV0cmllcyA9IHJldHJpZXMgfHwgdGhpcy5vcHRpb25zLnJldHJpZXM7XG4gICAgY29uc3Qgb3JpZ1JldHJpZXMgPSB0aGlzLm9wdGlvbnMucmV0cmllcztcbiAgICBjb25zdCBsb2dnZXIgPSB0aGlzLm9wdGlvbnMubG9nZ2VyO1xuICAgIGNvbnN0IHJldHJ5X2RlbGF5ID0gdGhpcy5vcHRpb25zLnJldHJ5X2RlbGF5O1xuXG4gICAgY29uc3QgcmVzcG9uc2VIYW5kbGVyOiBPblJlc3BvbnNlQ2FsbGJhY2sgPSBmdW5jdGlvbiAocmVzcG9uc2UpIHtcbiAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICBjYWxsYmFjayhudWxsLCByZXNwb25zZSk7XG4gICAgICB9XG4gICAgfTtcblxuICAgIGNvbnN0IGVycm9ySGFuZGxlcjogT25FcnJvckNhbGxiYWNrID0gZnVuY3Rpb24gKGVycm9yKSB7XG4gICAgICBpZiAoLS1yZXRyaWVzID4gMCkge1xuICAgICAgICAvLyBXYWl0IGZvciByZXRyeV9kZWxheVxuICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICBfdGhpcy5wZXJmb3JtT25TZXJ2ZXIoc2VydmVyLCByZXF1ZXN0LCBzZXEsIGNhbGxiYWNrLCByZXRyaWVzKTtcbiAgICAgICAgfSwgMTAwMCAqIHJldHJ5X2RlbGF5KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGxvZ2dlci5sb2coXG4gICAgICAgICAgXCJNZW1KUzogU2VydmVyIDxcIiArXG4gICAgICAgICAgICBzZXJ2ZXIuaG9zdHBvcnRTdHJpbmcoKSArXG4gICAgICAgICAgICBcIj4gZmFpbGVkIGFmdGVyIChcIiArXG4gICAgICAgICAgICBvcmlnUmV0cmllcyArXG4gICAgICAgICAgICBcIikgcmV0cmllcyB3aXRoIGVycm9yIC0gXCIgK1xuICAgICAgICAgICAgZXJyb3IubWVzc2FnZVxuICAgICAgICApO1xuICAgICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgICBjYWxsYmFjayhlcnJvciwgbnVsbCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9O1xuXG4gICAgc2VydmVyLm9uUmVzcG9uc2Uoc2VxLCByZXNwb25zZUhhbmRsZXIpO1xuICAgIHNlcnZlci5vbkVycm9yKHNlcSwgZXJyb3JIYW5kbGVyKTtcbiAgICBzZXJ2ZXIud3JpdGUocmVxdWVzdCk7XG4gIH1cblxuICAvLyBJbmNyZW1lbnQgdGhlIHNlcSB2YWx1ZVxuICBpbmNyU2VxKCkge1xuICAgIHRoaXMuc2VxKys7XG5cbiAgICAvLyBXcmFwIGB0aGlzLnNlcWAgdG8gMzItYml0cyBzaW5jZSB0aGUgZmllbGQgd2UgZml0IGl0IGludG8gaXMgb25seSAzMi1iaXRzLlxuICAgIHRoaXMuc2VxICY9IDB4ZmZmZmZmZmY7XG4gIH1cblxuICBwcml2YXRlIGNyZWF0ZUFuZExvZ0Vycm9yKFxuICAgIGNvbW1hbmROYW1lOiBzdHJpbmcsXG4gICAgcmVzcG9uc2VTdGF0dXM6IFJlc3BvbnNlU3RhdHVzIHwgdW5kZWZpbmVkXG4gICk6IEVycm9yIHtcbiAgICBjb25zdCBlcnJvck1lc3NhZ2UgPSBgTWVtSlMgJHtjb21tYW5kTmFtZX06ICR7Y29uc3RhbnRzLnJlc3BvbnNlU3RhdHVzVG9TdHJpbmcoXG4gICAgICByZXNwb25zZVN0YXR1c1xuICAgICl9YDtcbiAgICB0aGlzLm9wdGlvbnMubG9nZ2VyLmxvZyhlcnJvck1lc3NhZ2UpO1xuICAgIHJldHVybiBuZXcgRXJyb3IoZXJyb3JNZXNzYWdlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBMb2cgYW4gZXJyb3IgdG8gdGhlIGxvZ2dlciwgdGhlbiByZXR1cm4gdGhlIGVycm9yLlxuICAgKiBJZiBhIGNhbGxiYWNrIGlzIGdpdmVuLCBjYWxsIGl0IHdpdGggY2FsbGJhY2soZXJyb3IsIG51bGwpLlxuICAgKi9cbiAgcHJpdmF0ZSBoYW5kbGVSZXNwb25zZUVycm9yKFxuICAgIGNvbW1hbmROYW1lOiBzdHJpbmcsXG4gICAgcmVzcG9uc2VTdGF0dXM6IFJlc3BvbnNlU3RhdHVzIHwgdW5kZWZpbmVkLFxuICAgIGNhbGxiYWNrOiB1bmRlZmluZWQgfCAoKGVycm9yOiBFcnJvciB8IG51bGwsIG90aGVyOiBudWxsKSA9PiB2b2lkKVxuICApOiBFcnJvciB7XG4gICAgY29uc3QgZXJyb3IgPSB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKGNvbW1hbmROYW1lLCByZXNwb25zZVN0YXR1cyk7XG4gICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICBjYWxsYmFjayhlcnJvciwgbnVsbCk7XG4gICAgfVxuICAgIHJldHVybiBlcnJvcjtcbiAgfVxufVxuXG5leHBvcnQgeyBDbGllbnQsIFNlcnZlciwgVXRpbHMsIEhlYWRlciB9O1xuIl19 \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVtanMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbWVtanMvbWVtanMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLHdCQUF3Qjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUV4QixxQ0FLa0I7QUFvaENELHVGQXRoQ2YsZUFBTSxPQXNoQ2U7QUFuaEN2Qix1REFBK0Q7QUFDL0QsbUNBU2lCO0FBQ2pCLHVEQUF5QztBQUN6QywyQ0FBNkM7QUFDN0MsK0NBQWlDO0FBc2dDUixzQkFBSztBQXJnQzlCLGlEQUFtQztBQXFnQ0gsd0JBQU07QUFuZ0N0QyxTQUFTLDhCQUE4QixDQUNyQyxPQUFpQixFQUNqQixHQUFXO0lBRVgsTUFBTSxLQUFLLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQztJQUM3QixNQUFNLEtBQUssR0FBRyxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxnQkFBUSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3BELE9BQU8sT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ3hCLENBQUM7QUFFRCwrQ0FBK0M7QUFDL0MsU0FBUyxTQUFTLENBQ2hCLE9BQTBFO0lBRTFFLE9BQU8sSUFBSSxPQUFPLENBQUMsVUFBVSxPQUFPLEVBQUUsTUFBTTtRQUMxQyxPQUFPLENBQUMsVUFBVSxHQUFHLEVBQUUsTUFBTTtZQUMzQixHQUFHLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3RDLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBNkRELE1BQU0sTUFBTTtJQVFWLDRFQUE0RTtJQUM1RSxtQ0FBbUM7SUFDbkMsWUFBWSxPQUFpQixFQUFFLE9BQTBDO1FBQ3ZFLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO1FBQ3ZCLElB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QyxDQUFDO2lCQUN2QjthQUNGO1FBQ0gsQ0FBQyxDQUFDO1FBRUYsTUFBTSxDQUFDLFVBQVUsQ0FBQyxHQUFHLEVBQUUsZUFBZSxDQUFDLENBQUM7UUFDeEMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUUsWUFBWSxDQUFDLENBQUM7UUFDbEMsTUFBTSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUN4QixDQUFDO0lBRUQsMEJBQTBCO0lBQzFCLE9BQU87UUFDTCxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7UUFFWCw2RUFBNkU7UUFDN0UsSUFBSSxDQUFDLEdBQUcsSUFBSSxVQUFVLENBQUM7SUFDekIsQ0FBQztJQUVPLGlCQUFpQixDQUN2QixXQUFtQixFQUNuQixjQUEwQztRQUUxQyxNQUFNLFlBQVksR0FBRyxTQUFTLFdBQVcsS0FBSyxTQUFTLENBQUMsc0JBQXNCLENBQzVFLGNBQWMsQ0FDZixFQUFFLENBQUM7UUFDSixJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDdEMsT0FBTyxJQUFJLEtBQUssQ0FBQyxZQUFZLENBQUMsQ0FBQztJQUNqQyxDQUFDO0lBRUQ7OztPQUdHO0lBQ0ssbUJBQW1CLENBQ3pCLFdBQW1CLEVBQ25CLGNBQTBDLEVBQzFDLFFBQWtFO1FBRWxFLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxXQUFXLEVBQUUsY0FBYyxDQUFDLENBQUM7UUFDbEUsSUFBSSxRQUFRLEVBQUU7WUFDWixRQUFRLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxDQUFDO1NBQ3ZCO1FBQ0QsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0NBQ0Y7QUFFUSx3QkFBTSIsInNvdXJjZXNDb250ZW50IjpbIi8vIE1lbVRTIE1lbWNhY2hlIENsaWVudFxuXG5pbXBvcnQge1xuICBPbkVycm9yQ2FsbGJhY2ssXG4gIE9uUmVzcG9uc2VDYWxsYmFjayxcbiAgU2VydmVyLFxuICBTZXJ2ZXJPcHRpb25zLFxufSBmcm9tIFwiLi9zZXJ2ZXJcIjtcbmltcG9ydCB7IG5vb3BTZXJpYWxpemVyLCBTZXJpYWxpemVyIH0gZnJvbSBcIi4vbm9vcC1zZXJpYWxpemVyXCI7XG5pbXBvcnQge1xuICBtYWtlUmVxdWVzdEJ1ZmZlcixcbiAgY29weUludG9SZXF1ZXN0QnVmZmVyLFxuICBtZXJnZSxcbiAgbWFrZUV4cGlyYXRpb24sXG4gIG1ha2VBbW91bnRJbml0aWFsQW5kRXhwaXJhdGlvbixcbiAgaGFzaENvZGUsXG4gIE1heWJlQnVmZmVyLFxuICBNZXNzYWdlLFxufSBmcm9tIFwiLi91dGlsc1wiO1xuaW1wb3J0ICogYXMgY29uc3RhbnRzIGZyb20gXCIuL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgUmVzcG9uc2VTdGF0dXMgfSBmcm9tIFwiLi9jb25zdGFudHNcIjtcbmltcG9ydCAqIGFzIFV0aWxzIGZyb20gXCIuL3V0aWxzXCI7XG5pbXBvcnQgKiBhcyBIZWFkZXIgZnJvbSBcIi4vaGVhZGVyXCI7XG5cbmZ1bmN0aW9uIGRlZmF1bHRLZXlUb1NlcnZlckhhc2hGdW5jdGlvbihcbiAgc2VydmVyczogc3RyaW5nW10sXG4gIGtleTogc3RyaW5nXG4pOiBzdHJpbmcge1xuICBjb25zdCB0b3RhbCA9IHNlcnZlcnMubGVuZ3RoO1xuICBjb25zdCBpbmRleCA9IHRvdGFsID4gMSA/IGhhc2hDb2RlKGtleSkgJSB0b3RhbCA6IDA7XG4gIHJldHVybiBzZXJ2ZXJzW2luZGV4XTtcbn1cblxuLy8gY29udmVydHMgYSBjYWxsIGludG8gYSBwcm9taXNlLXJldHVybmluZyBvbmVcbmZ1bmN0aW9uIHByb21pc2lmeTxSZXN1bHQ+KFxuICBjb21tYW5kOiAoY2FsbGJhY2s6IChlcnJvcjogRXJyb3IgfCBudWxsLCByZXN1bHQ6IFJlc3VsdCkgPT4gdm9pZCkgPT4gdm9pZFxuKTogUHJvbWlzZTxSZXN1bHQ+IHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICBjb21tYW5kKGZ1bmN0aW9uIChlcnIsIHJlc3VsdCkge1xuICAgICAgZXJyID8gcmVqZWN0KGVycikgOiByZXNvbHZlKHJlc3VsdCk7XG4gICAgfSk7XG4gIH0pO1xufVxuXG50eXBlIFJlc3BvbnNlT3JFcnJvckNhbGxiYWNrID0gKFxuICBlcnJvcjogRXJyb3IgfCBudWxsLFxuICByZXNwb25zZTogTWVzc2FnZSB8IG51bGxcbikgPT4gdm9pZDtcblxuaW50ZXJmYWNlIEJhc2VDbGllbnRPcHRpb25zIHtcbiAgcmV0cmllczogbnVtYmVyO1xuICByZXRyeV9kZWxheTogbnVtYmVyO1xuICBleHBpcmVzOiBudW1iZXI7XG4gIGxvZ2dlcjogeyBsb2c6IHR5cGVvZiBjb25zb2xlLmxvZyB9O1xuICBrZXlUb1NlcnZlckhhc2hGdW5jdGlvbjogdHlwZW9mIGRlZmF1bHRLZXlUb1NlcnZlckhhc2hGdW5jdGlvbjtcbn1cblxuaW50ZXJmYWNlIFNlcmlhbGl6ZXJQcm9wPFZhbHVlLCBFeHRyYXM+IHtcbiAgc2VyaWFsaXplcjogU2VyaWFsaXplcjxWYWx1ZSwgRXh0cmFzPjtcbn1cblxuLyoqXG4gKiBUaGUgY2xpZW50IGhhcyBwYXJ0aWFsIHN1cHBvcnQgZm9yIHNlcmlhbGl6aW5nIGFuZCBkZXNlcmlhbGl6aW5nIHZhbHVlcyBmcm9tIHRoZVxuICogQnVmZmVyIGJ5dGUgc3RyaW5ncyB3ZSByZWNpZXZlIGZyb20gdGhlIHdpcmUuIFRoZSBkZWZhdWx0IHNlcmlhbGl6ZXIgaXMgZm9yIE1heWJlQnVmZmVyLlxuICpcbiAqIElmIFZhbHVlIGFuZCBFeHRyYXMgYXJlIG9mIHR5cGUgQnVmZmVyLCB0aGVuIHJldHVybiB0eXBlIFdoZW5CdWZmZXIuIE90aGVyd2lzZSxcbiAqIHJldHVybiB0eXBlIE5vdEJ1ZmZlci5cbiAqL1xudHlwZSBJZkJ1ZmZlcjxcbiAgVmFsdWUsXG4gIEV4dHJhcyxcbiAgV2hlblZhbHVlQW5kRXh0cmFzQXJlQnVmZmVycyxcbiAgTm90QnVmZmVyXG4+ID0gVmFsdWUgZXh0ZW5kcyBCdWZmZXJcbiAgPyBFeHRyYXMgZXh0ZW5kcyBCdWZmZXJcbiAgICA/IFdoZW5WYWx1ZUFuZEV4dHJhc0FyZUJ1ZmZlcnNcbiAgICA6IE5vdEJ1ZmZlclxuICA6IE5vdEJ1ZmZlcjtcblxuZXhwb3J0IHR5cGUgR2l2ZW5DbGllbnRPcHRpb25zPFZhbHVlLCBFeHRyYXM+ID0gUGFydGlhbDxCYXNlQ2xpZW50T3B0aW9ucz4gJlxuICBJZkJ1ZmZlcjxcbiAgICBWYWx1ZSxcbiAgICBFeHRyYXMsXG4gICAgUGFydGlhbDxTZXJpYWxpemVyUHJvcDxWYWx1ZSwgRXh0cmFzPj4sXG4gICAgU2VyaWFsaXplclByb3A8VmFsdWUsIEV4dHJhcz5cbiAgPjtcblxuZXhwb3J0IHR5cGUgQ0FTVG9rZW4gPSBCdWZmZXI7XG5cbmV4cG9ydCBpbnRlcmZhY2UgR2V0UmVzdWx0PFZhbHVlID0gTWF5YmVCdWZmZXIsIEV4dHJhcyA9IE1heWJlQnVmZmVyPiB7XG4gIHZhbHVlOiBWYWx1ZTtcbiAgZXh0cmFzOiBFeHRyYXM7XG4gIGNhczogQ0FTVG9rZW4gfCB1bmRlZmluZWQ7XG59XG5cbmV4cG9ydCB0eXBlIEdldE11bHRpUmVzdWx0PFxuICBLZXlzIGV4dGVuZHMgc3RyaW5nID0gc3RyaW5nLFxuICBWYWx1ZSA9IE1heWJlQnVmZmVyLFxuICBFeHRyYXMgPSBNYXliZUJ1ZmZlclxuPiA9IHtcbiAgW0sgaW4gS2V5c10/OiBHZXRSZXN1bHQ8VmFsdWUsIEV4dHJhcz47XG59O1xuXG5jbGFzcyBDbGllbnQ8VmFsdWUgPSBNYXliZUJ1ZmZlciwgRXh0cmFzID0gTWF5YmVCdWZmZXI+IHtcbiAgc2VydmVyczogU2VydmVyW107XG4gIHNlcTogbnVtYmVyO1xuICBvcHRpb25zOiBCYXNlQ2xpZW50T3B0aW9ucyAmIFBhcnRpYWw8U2VyaWFsaXplclByb3A8VmFsdWUsIEV4dHJhcz4+O1xuICBzZXJpYWxpemVyOiBTZXJpYWxpemVyPFZhbHVlLCBFeHRyYXM+O1xuICBzZXJ2ZXJNYXA6IHsgW2hvc3Rwb3J0OiBzdHJpbmddOiBTZXJ2ZXIgfTtcbiAgc2VydmVyS2V5czogc3RyaW5nW107XG5cbiAgLy8gQ2xpZW50IGluaXRpYWxpemVyIHRha2VzIGEgbGlzdCBvZiBgU2VydmVyYHMgYW5kIGFuIGBvcHRpb25zYCBkaWN0aW9uYXJ5LlxuICAvLyBTZWUgYENsaWVudC5jcmVhdGVgIGZvciBkZXRhaWxzLlxuICBjb25zdHJ1Y3RvcihzZXJ2ZXJzOiBTZXJ2ZXJbXSwgb3B0aW9uczogR2l2ZW5DbGllbnRPcHRpb25zPFZhbHVlLCBFeHRyYXM+KSB7XG4gICAgdGhpcy5zZXJ2ZXJzID0gc2VydmVycztcbiAgICB0aGlzLnNlcSA9IDA7XG4gICAgdGhpcy5vcHRpb25zID0gbWVyZ2Uob3B0aW9ucyB8fCB7fSwge1xuICAgICAgcmV0cmllczogMixcbiAgICAgIHJldHJ5X2RlbGF5OiAwLjIsXG4gICAgICBleHBpcmVzOiAwLFxuICAgICAgbG9nZ2VyOiBjb25zb2xlLFxuICAgICAga2V5VG9TZXJ2ZXJIYXNoRnVuY3Rpb246IGRlZmF1bHRLZXlUb1NlcnZlckhhc2hGdW5jdGlvbixcbiAgICB9KTtcblxuICAgIHRoaXMuc2VyaWFsaXplciA9IHRoaXMub3B0aW9ucy5zZXJpYWxpemVyIHx8IChub29wU2VyaWFsaXplciBhcyBhbnkpO1xuXG4gICAgLy8gU3RvcmUgYSBtYXBwaW5nIGZyb20gaG9zdHBvcnQgLT4gc2VydmVyIHNvIHdlIGNhbiBxdWlja2x5IGdldCBhIHNlcnZlciBvYmplY3QgZnJvbSB0aGUgc2VydmVyS2V5IHJldHVybmVkIGJ5IHRoZSBoYXNoaW5nIGZ1bmN0aW9uXG4gICAgY29uc3Qgc2VydmVyTWFwOiB7IFtob3N0cG9ydDogc3RyaW5nXTogU2VydmVyIH0gPSB7fTtcbiAgICB0aGlzLnNlcnZlcnMuZm9yRWFjaChmdW5jdGlvbiAoc2VydmVyKSB7XG4gICAgICBzZXJ2ZXJNYXBbc2VydmVyLmhvc3Rwb3J0U3RyaW5nKCldID0gc2VydmVyO1xuICAgIH0pO1xuICAgIHRoaXMuc2VydmVyTWFwID0gc2VydmVyTWFwO1xuXG4gICAgLy8gc3RvcmUgYSBsaXN0IG9mIGFsbCBvdXIgc2VydmVyS2V5cyBzbyB3ZSBkb24ndCBuZWVkIHRvIGNvbnN0YW50bHkgcmVhbGxvY2F0ZSB0aGlzIGFycmF5XG4gICAgdGhpcy5zZXJ2ZXJLZXlzID0gT2JqZWN0LmtleXModGhpcy5zZXJ2ZXJNYXApO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBuZXcgY2xpZW50IGdpdmVuIGFuIG9wdGlvbmFsIGNvbmZpZyBzdHJpbmcgYW5kIG9wdGlvbmFsIGhhc2ggb2ZcbiAgICogb3B0aW9ucy4gVGhlIGNvbmZpZyBzdHJpbmcgc2hvdWxkIGJlIG9mIHRoZSBmb3JtOlxuICAgKlxuICAgKiAgICAgXCJbdXNlcjpwYXNzQF1zZXJ2ZXIxWzoxMTIxMV0sW3VzZXI6cGFzc0Bdc2VydmVyMls6MTEyMTFdLC4uLlwiXG4gICAqXG4gICAqIElmIHRoZSBhcmd1bWVudCBpcyBub3QgZ2l2ZW4sIGZhbGxiYWNrIG9uIHRoZSBgTUVNQ0FDSElFUl9TRVJWRVJTYCBlbnZpcm9ubWVudFxuICAgKiB2YXJpYWJsZSwgYE1FTUNBQ0hFX1NFUlZFUlNgIGVudmlyb25tZW50IHZhcmlhYmxlIG9yIGBcImxvY2FsaG9zdDoxMTIxMVwiYC5cbiAgICpcbiAgICogVGhlIG9wdGlvbnMgaGFzaCBtYXkgY29udGFpbiB0aGUgb3B0aW9uczpcbiAgICpcbiAgICogKiBgcmV0cmllc2AgLSB0aGUgbnVtYmVyIG9mIHRpbWVzIHRvIHJldHJ5IGFuIG9wZXJhdGlvbiBpbiBsaWV1IG9mIGZhaWx1cmVzXG4gICAqIChkZWZhdWx0IDIpXG4gICAqICogYGV4cGlyZXNgIC0gdGhlIGRlZmF1bHQgZXhwaXJhdGlvbiBpbiBzZWNvbmRzIHRvIHVzZSAoZGVmYXVsdCAwIC0gbmV2ZXJcbiAgICogZXhwaXJlKS4gSWYgYGV4cGlyZXNgIGlzIGdyZWF0ZXIgdGhhbiAzMCBkYXlzICg2MCB4IDYwIHggMjQgeCAzMCksIGl0IGlzXG4gICAqIHRyZWF0ZWQgYXMgYSBVTklYIHRpbWUgKG51bWJlciBvZiBzZWNvbmRzIHNpbmNlIEphbnVhcnkgMSwgMTk3MCkuXG4gICAqICogYGxvZ2dlcmAgLSBhIGxvZ2dlciBvYmplY3QgdGhhdCByZXNwb25kcyB0byBgbG9nKHN0cmluZylgIG1ldGhvZCBjYWxscy5cbiAgICpcbiAgICogICB+fn5+XG4gICAqICAgICBsb2cobXNnMVssIG1zZzJbLCBtc2czWy4uLl1dXSlcbiAgICogICB+fn5+XG4gICAqXG4gICAqICAgRGVmYXVsdHMgdG8gYGNvbnNvbGVgLlxuICAgKiAqIGBzZXJpYWxpemVyYCAtIHRoZSBvYmplY3Qgd2hpY2ggd2lsbCAoZGUpc2VyaWFsaXplIHRoZSBkYXRhLiBJdCBuZWVkc1xuICAgKiAgIHR3byBwdWJsaWMgbWV0aG9kczogc2VyaWFsaXplIGFuZCBkZXNlcmlhbGl6ZS4gSXQgZGVmYXVsdHMgdG8gdGhlXG4gICAqICAgbm9vcFNlcmlhbGl6ZXI6XG4gICAqXG4gICAqICAgfn5+flxuICAgKiAgIGNvbnN0IG5vb3BTZXJpYWxpemVyID0ge1xuICAgKiAgICAgc2VyaWFsaXplOiBmdW5jdGlvbiAob3Bjb2RlLCB2YWx1ZSwgZXh0cmFzKSB7XG4gICAqICAgICAgIHJldHVybiB7IHZhbHVlOiB2YWx1ZSwgZXh0cmFzOiBleHRyYXMgfTtcbiAgICogICAgIH0sXG4gICAqICAgICBkZXNlcmlhbGl6ZTogZnVuY3Rpb24gKG9wY29kZSwgdmFsdWUsIGV4dHJhcykge1xuICAgKiAgICAgICByZXR1cm4geyB2YWx1ZTogdmFsdWUsIGV4dHJhczogZXh0cmFzIH07XG4gICAqICAgICB9XG4gICAqICAgfTtcbiAgICogICB+fn5+XG4gICAqXG4gICAqIE9yIG9wdGlvbnMgZm9yIHRoZSBzZXJ2ZXJzIGluY2x1ZGluZzpcbiAgICogKiBgdXNlcm5hbWVgIGFuZCBgcGFzc3dvcmRgIGZvciBmYWxsYmFjayBTQVNMIGF1dGhlbnRpY2F0aW9uIGNyZWRlbnRpYWxzLlxuICAgKiAqIGB0aW1lb3V0YCBpbiBzZWNvbmRzIHRvIGRldGVybWluZSBmYWlsdXJlIGZvciBvcGVyYXRpb25zLiBEZWZhdWx0IGlzIDAuNVxuICAgKiAgICAgICAgICAgICBzZWNvbmRzLlxuICAgKiAqICdjb25udGltZW91dCcgaW4gc2Vjb25kcyB0byBjb25uZWN0aW9uIGZhaWx1cmUuIERlZmF1bHQgaXMgdHdpY2UgdGhlIHZhbHVlXG4gICAqICAgICAgICAgICAgICAgICBvZiBgdGltZW91dGAuXG4gICAqICogYGtlZXBBbGl2ZWAgd2hldGhlciB0byBlbmFibGUga2VlcC1hbGl2ZSBmdW5jdGlvbmFsaXR5LiBEZWZhdWx0cyB0byBmYWxzZS5cbiAgICogKiBga2VlcEFsaXZlRGVsYXlgIGluIHNlY29uZHMgdG8gdGhlIGluaXRpYWwgZGVsYXkgYmVmb3JlIHRoZSBmaXJzdCBrZWVwYWxpdmVcbiAgICogICAgICAgICAgICAgICAgICAgIHByb2JlIGlzIHNlbnQgb24gYW4gaWRsZSBzb2NrZXQuIERlZmF1bHRzIGlzIDMwIHNlY29uZHMuXG4gICAqICogYGtleVRvU2VydmVySGFzaEZ1bmN0aW9uYCBhIGZ1bmN0aW9uIHRvIG1hcCBrZXlzIHRvIHNlcnZlcnMsIHdpdGggdGhlIHNpZ25hdHVyZVxuICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoc2VydmVyS2V5czogc3RyaW5nW10sIGtleTogc3RyaW5nKTogc3RyaW5nXG4gICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgIE5PVEU6IGlmIHlvdSBuZWVkIHRvIGRvIHNvbWUgZXhwZW5zaXZlIGluaXRpYWxpemF0aW9uLCAqcGxlYXNlKiBkbyBpdCBsYXppbHkgdGhlIGZpcnN0IHRpbWUgeW91IHRoaXMgZnVuY3Rpb24gaXMgY2FsbGVkIHdpdGggYW4gYXJyYXkgb2Ygc2VydmVyS2V5cywgbm90IG9uIGV2ZXJ5IGNhbGxcbiAgICovXG4gIHN0YXRpYyBjcmVhdGU8VmFsdWUsIEV4dHJhcz4oXG4gICAgc2VydmVyc1N0cjogc3RyaW5nIHwgdW5kZWZpbmVkLFxuICAgIG9wdGlvbnM6IElmQnVmZmVyPFxuICAgICAgVmFsdWUsXG4gICAgICBFeHRyYXMsXG4gICAgICB1bmRlZmluZWQgfCAoUGFydGlhbDxTZXJ2ZXJPcHRpb25zPiAmIEdpdmVuQ2xpZW50T3B0aW9uczxWYWx1ZSwgRXh0cmFzPiksXG4gICAgICBQYXJ0aWFsPFNlcnZlck9wdGlvbnM+ICYgR2l2ZW5DbGllbnRPcHRpb25zPFZhbHVlLCBFeHRyYXM+XG4gICAgPlxuICApOiBDbGllbnQ8VmFsdWUsIEV4dHJhcz4ge1xuICAgIHNlcnZlcnNTdHIgPVxuICAgICAgc2VydmVyc1N0ciB8fFxuICAgICAgcHJvY2Vzcy5lbnYuTUVNQ0FDSElFUl9TRVJWRVJTIHx8XG4gICAgICBwcm9jZXNzLmVudi5NRU1DQUNIRV9TRVJWRVJTIHx8XG4gICAgICBcImxvY2FsaG9zdDoxMTIxMVwiO1xuICAgIGNvbnN0IHNlcnZlclVyaXMgPSBzZXJ2ZXJzU3RyLnNwbGl0KFwiLFwiKTtcbiAgICBjb25zdCBzZXJ2ZXJzID0gc2VydmVyVXJpcy5tYXAoZnVuY3Rpb24gKHVyaSkge1xuICAgICAgY29uc3QgdXJpUGFydHMgPSB1cmkuc3BsaXQoXCJAXCIpO1xuICAgICAgY29uc3QgaG9zdFBvcnQgPSB1cmlQYXJ0c1t1cmlQYXJ0cy5sZW5ndGggLSAxXS5zcGxpdChcIjpcIik7XG4gICAgICBjb25zdCB1c2VyUGFzcyA9ICh1cmlQYXJ0c1t1cmlQYXJ0cy5sZW5ndGggLSAyXSB8fCBcIlwiKS5zcGxpdChcIjpcIik7XG4gICAgICByZXR1cm4gbmV3IFNlcnZlcihcbiAgICAgICAgaG9zdFBvcnRbMF0sXG4gICAgICAgIHBhcnNlSW50KGhvc3RQb3J0WzFdIHx8IFwiMTEyMTFcIiwgMTApLFxuICAgICAgICB1c2VyUGFzc1swXSxcbiAgICAgICAgdXNlclBhc3NbMV0sXG4gICAgICAgIG9wdGlvbnNcbiAgICAgICk7XG4gICAgfSk7XG4gICAgcmV0dXJuIG5ldyBDbGllbnQoc2VydmVycywgb3B0aW9ucyBhcyBhbnkpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdpdmVuIGEgc2VydmVyS2V5IGZyb21sb29rdXBLZXlUb1NlcnZlcktleSwgcmV0dXJuIHRoZSBjb3JyZXNwb25kaW5nIFNlcnZlciBpbnN0YW5jZVxuICAgKlxuICAgKiBAcGFyYW0gIHtzdHJpbmd9IHNlcnZlcktleVxuICAgKiBAcmV0dXJucyB7U2VydmVyfVxuICAgKi9cbiAgc2VydmVyS2V5VG9TZXJ2ZXIoc2VydmVyS2V5OiBzdHJpbmcpOiBTZXJ2ZXIge1xuICAgIHJldHVybiB0aGlzLnNlcnZlck1hcFtzZXJ2ZXJLZXldO1xuICB9XG5cbiAgLyoqXG4gICAqIEdpdmVuIGEga2V5IHRvIGxvb2sgdXAgaW4gbWVtY2FjaGUsIHJldHVybiBhIHNlcnZlcktleSAoYmFzZWQgb24gc29tZVxuICAgKiBoYXNoaW5nIGZ1bmN0aW9uKSB3aGljaCBjYW4gYmUgdXNlZCB0byBpbmRleCB0aGlzLnNlcnZlck1hcFxuICAgKi9cbiAgbG9va3VwS2V5VG9TZXJ2ZXJLZXkoa2V5OiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLm9wdGlvbnMua2V5VG9TZXJ2ZXJIYXNoRnVuY3Rpb24odGhpcy5zZXJ2ZXJLZXlzLCBrZXkpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHJpZXZlcyB0aGUgdmFsdWUgYXQgdGhlIGdpdmVuIGtleSBpbiBtZW1jYWNoZS5cbiAgICovXG4gIGFzeW5jIGdldChrZXk6IHN0cmluZyk6IFByb21pc2U8R2V0UmVzdWx0PFZhbHVlLCBFeHRyYXM+IHwgbnVsbD4ge1xuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihjb25zdGFudHMuT1BfR0VULCBrZXksIFwiXCIsIFwiXCIsIHRoaXMuc2VxKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgY29uc3QgZGVzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLmRlc2VyaWFsaXplKFxuICAgICAgICAgIHJlc3BvbnNlLmhlYWRlci5vcGNvZGUsXG4gICAgICAgICAgcmVzcG9uc2UudmFsLFxuICAgICAgICAgIHJlc3BvbnNlLmV4dHJhc1xuICAgICAgICApO1xuICAgICAgICByZXR1cm4geyAuLi5kZXNlcmlhbGl6ZWQsIGNhczogcmVzcG9uc2UuaGVhZGVyLmNhcyB9O1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfTk9UX0ZPVU5EOlxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJHRVRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqIEJ1aWxkIGEgcGlwZWxpbmVkIGdldCBtdWx0aSByZXF1ZXN0IGJ5IHNlbmRpbmcgb25lIEdFVEtRIGZvciBlYWNoIGtleSAocXVpZXQsIG1lYW5pbmcgaXQgd29uJ3QgcmVzcG9uZCBpZiB0aGUgdmFsdWUgaXMgbWlzc2luZykgZm9sbG93ZWQgYnkgYSBuby1vcCB0byBmb3JjZSBhIHJlc3BvbnNlIChhbmQgdG8gZ2l2ZSB1cyBhIHNlbnRpbmVsIHJlc3BvbnNlIHRoYXQgdGhlIHBpcGVsaW5lIGlzIGRvbmUpXG4gICAqXG4gICAqIGNmIGh0dHBzOi8vZ2l0aHViLmNvbS9jb3VjaGJhc2UvbWVtY2FjaGVkL2Jsb2IvbWFzdGVyL2RvY3MvQmluYXJ5UHJvdG9jb2wubWQjMHgwZC1nZXRrcS1nZXQtd2l0aC1rZXktcXVpZXRseVxuICAgKi9cbiAgX2J1aWxkR2V0TXVsdGlSZXF1ZXN0KGtleXM6IHN0cmluZ1tdKTogQnVmZmVyIHtcbiAgICAvLyBzdGFydCBhdCAyNCBmb3IgdGhlIG5vLW9wIGNvbW1hbmQgYXQgdGhlIGVuZFxuICAgIGxldCByZXF1ZXN0U2l6ZSA9IDI0O1xuICAgIGZvciAoY29uc3Qga2V5SWR4IGluIGtleXMpIHtcbiAgICAgIHJlcXVlc3RTaXplICs9IEJ1ZmZlci5ieXRlTGVuZ3RoKGtleXNba2V5SWR4XSwgXCJ1dGY4XCIpICsgMjQ7XG4gICAgfVxuXG4gICAgY29uc3QgcmVxdWVzdCA9IEJ1ZmZlci5hbGxvYyhyZXF1ZXN0U2l6ZSk7XG5cbiAgICBsZXQgYnl0ZXNXcml0dGVuID0gMDtcbiAgICBmb3IgKGNvbnN0IGtleUlkeCBpbiBrZXlzKSB7XG4gICAgICBjb25zdCBrZXkgPSBrZXlzW2tleUlkeF07XG4gICAgICBieXRlc1dyaXR0ZW4gKz0gY29weUludG9SZXF1ZXN0QnVmZmVyKFxuICAgICAgICBjb25zdGFudHMuT1BfR0VUS1EsXG4gICAgICAgIGtleSxcbiAgICAgICAgXCJcIixcbiAgICAgICAgXCJcIixcbiAgICAgICAgdGhpcy5zZXEsXG4gICAgICAgIHJlcXVlc3QsXG4gICAgICAgIGJ5dGVzV3JpdHRlblxuICAgICAgKTtcbiAgICB9XG5cbiAgICBieXRlc1dyaXR0ZW4gKz0gY29weUludG9SZXF1ZXN0QnVmZmVyKFxuICAgICAgY29uc3RhbnRzLk9QX05PX09QLFxuICAgICAgXCJcIixcbiAgICAgIFwiXCIsXG4gICAgICBcIlwiLFxuICAgICAgdGhpcy5zZXEsXG4gICAgICByZXF1ZXN0LFxuICAgICAgYnl0ZXNXcml0dGVuXG4gICAgKTtcblxuICAgIHJldHVybiByZXF1ZXN0O1xuICB9XG5cbiAgLyoqIEV4ZWN1dGluZyBhIHBpcGVsaW5lZCAobXVsdGkpIGdldCBhZ2FpbnN0IGEgc2luZ2xlIHNlcnZlci4gVGhpcyBpcyBhIHByaXZhdGUgaW1wbGVtZW50YXRpb24gZGV0YWlsIG9mIGdldE11bHRpLiAqL1xuICBhc3luYyBfZ2V0TXVsdGlUb1NlcnZlcjxLZXlzIGV4dGVuZHMgc3RyaW5nPihcbiAgICBzZXJ2OiBTZXJ2ZXIsXG4gICAga2V5czogS2V5c1tdXG4gICk6IFByb21pc2U8R2V0TXVsdGlSZXN1bHQ8S2V5cywgVmFsdWUsIEV4dHJhcz4+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgY29uc3QgcmVzcG9uc2VNYXA6IEdldE11bHRpUmVzdWx0PHN0cmluZywgVmFsdWUsIEV4dHJhcz4gPSB7fTtcblxuICAgICAgY29uc3QgaGFuZGxlOiBPblJlc3BvbnNlQ2FsbGJhY2sgPSAocmVzcG9uc2UpID0+IHtcbiAgICAgICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICAgICAgLy8gV2hlbiB3ZSBnZXQgdGhlIG5vLW9wIHJlc3BvbnNlLCB3ZSBhcmUgZG9uZSB3aXRoIHRoaXMgb25lIGdldE11bHRpIGluIHRoZSBwZXItYmFja2VuZCBmYW4tb3V0XG4gICAgICAgICAgICBpZiAocmVzcG9uc2UuaGVhZGVyLm9wY29kZSA9PT0gY29uc3RhbnRzLk9QX05PX09QKSB7XG4gICAgICAgICAgICAgIC8vIFRoaXMgZW5zdXJlcyB0aGUgaGFuZGxlciB3aWxsIGJlIGRlbGV0ZWQgZnJvbSB0aGUgcmVzcG9uc2VDYWxsYmFja3MgbWFwIGluIHNlcnZlci5qc1xuICAgICAgICAgICAgICAvLyBUaGlzIGlzbid0IHRlY2huaWNhbGx5IG5lZWRlZCBoZXJlIGJlY2F1c2UgdGhlIGxvZ2ljIGluIHNlcnZlci5qcyBhbHNvIGNoZWNrcyBpZiB0b3RhbEJvZHlMZW5ndGggPT09IDAsIGJ1dCBvdXIgdW5pdHRlc3RzIGFyZW4ndCBncmVhdCBhYm91dCBzZXR0aW5nIHRoYXQgZmllbGQsIGFuZCBhbHNvIHRoaXMgbWFrZXMgaXQgbW9yZSBleHBsaWNpdFxuICAgICAgICAgICAgICBoYW5kbGUucXVpZXQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgcmVzb2x2ZShyZXNwb25zZU1hcCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBjb25zdCBkZXNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuZGVzZXJpYWxpemUoXG4gICAgICAgICAgICAgICAgcmVzcG9uc2UuaGVhZGVyLm9wY29kZSxcbiAgICAgICAgICAgICAgICByZXNwb25zZS52YWwsXG4gICAgICAgICAgICAgICAgcmVzcG9uc2UuZXh0cmFzXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgIGNvbnN0IGtleSA9IHJlc3BvbnNlLmtleS50b1N0cmluZygpO1xuICAgICAgICAgICAgICByZXNwb25zZU1hcFtrZXldID0geyAuLi5kZXNlcmlhbGl6ZWQsIGNhczogcmVzcG9uc2UuaGVhZGVyLmNhcyB9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHJldHVybiByZWplY3QoXG4gICAgICAgICAgICAgIHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJHRVRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cylcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH07XG4gICAgICAvLyBUaGlzIHByZXZlbnRzIHRoZSBoYW5kbGVyIGZyb20gYmVpbmcgZGVsZXRlZFxuICAgICAgLy8gYWZ0ZXIgdGhlIGZpcnN0IHJlc3BvbnNlLiBMb2dpYyBpbiBzZXJ2ZXIuanMuXG4gICAgICBoYW5kbGUucXVpZXQgPSB0cnVlO1xuXG4gICAgICBjb25zdCByZXF1ZXN0ID0gdGhpcy5fYnVpbGRHZXRNdWx0aVJlcXVlc3Qoa2V5cyk7XG4gICAgICBzZXJ2Lm9uUmVzcG9uc2UodGhpcy5zZXEsIGhhbmRsZSk7XG4gICAgICBzZXJ2Lm9uRXJyb3IodGhpcy5zZXEsIHJlamVjdCk7XG4gICAgICB0aGlzLmluY3JTZXEoKTtcbiAgICAgIHNlcnYud3JpdGUocmVxdWVzdCk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldnMgdGhlIHZhbHVlIGF0IHRoZSBnaXZlbiBrZXlzIGluIG1lbWNhY2hlZC4gUmV0dXJucyBhIG1hcCBmcm9tIHRoZVxuICAgKiByZXF1ZXN0ZWQga2V5cyB0byByZXN1bHRzLCBvciBudWxsIGlmIHRoZSBrZXkgd2FzIG5vdCBmb3VuZC5cbiAgICovXG4gIGFzeW5jIGdldE11bHRpPEtleXMgZXh0ZW5kcyBzdHJpbmc+KFxuICAgIGtleXM6IEtleXNbXVxuICApOiBQcm9taXNlPEdldE11bHRpUmVzdWx0PEtleXMsIFZhbHVlLCBFeHRyYXM+PiB7XG4gICAgY29uc3Qgc2VydmVyS2V5dG9Mb29rdXBLZXlzOiB7XG4gICAgICBbc2VydmVyS2V5OiBzdHJpbmddOiBzdHJpbmdbXTtcbiAgICB9ID0ge307XG4gICAga2V5cy5mb3JFYWNoKChsb29rdXBLZXkpID0+IHtcbiAgICAgIGNvbnN0IHNlcnZlcktleSA9IHRoaXMubG9va3VwS2V5VG9TZXJ2ZXJLZXkobG9va3VwS2V5KTtcbiAgICAgIGlmICghc2VydmVyS2V5dG9Mb29rdXBLZXlzW3NlcnZlcktleV0pIHtcbiAgICAgICAgc2VydmVyS2V5dG9Mb29rdXBLZXlzW3NlcnZlcktleV0gPSBbXTtcbiAgICAgIH1cbiAgICAgIHNlcnZlcktleXRvTG9va3VwS2V5c1tzZXJ2ZXJLZXldLnB1c2gobG9va3VwS2V5KTtcbiAgICB9KTtcblxuICAgIGNvbnN0IHVzZWRTZXJ2ZXJLZXlzID0gT2JqZWN0LmtleXMoc2VydmVyS2V5dG9Mb29rdXBLZXlzKTtcbiAgICBjb25zdCByZXN1bHRzID0gYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICB1c2VkU2VydmVyS2V5cy5tYXAoKHNlcnZlcktleSkgPT4ge1xuICAgICAgICBjb25zdCBzZXJ2ZXIgPSB0aGlzLnNlcnZlcktleVRvU2VydmVyKHNlcnZlcktleSk7XG4gICAgICAgIHJldHVybiB0aGlzLl9nZXRNdWx0aVRvU2VydmVyKHNlcnZlciwgc2VydmVyS2V5dG9Mb29rdXBLZXlzW3NlcnZlcktleV0pO1xuICAgICAgfSlcbiAgICApO1xuXG4gICAgcmV0dXJuIE9iamVjdC5hc3NpZ24oe30sIC4uLnJlc3VsdHMpO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgYGtleWAgdG8gYHZhbHVlYC5cbiAgICovXG4gIGFzeW5jIHNldChcbiAgICBrZXk6IHN0cmluZyxcbiAgICB2YWx1ZTogVmFsdWUsXG4gICAgb3B0aW9ucz86IHsgZXhwaXJlcz86IG51bWJlcjsgY2FzPzogQ0FTVG9rZW4gfVxuICApOiBQcm9taXNlPGJvb2xlYW4gfCBudWxsPiB7XG4gICAgY29uc3QgZXhwaXJlcyA9IG9wdGlvbnM/LmV4cGlyZXM7XG4gICAgY29uc3QgY2FzID0gb3B0aW9ucz8uY2FzO1xuXG4gICAgLy8gVE9ETzogc3VwcG9ydCBmbGFnc1xuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IGV4cGlyYXRpb24gPSBtYWtlRXhwaXJhdGlvbihleHBpcmVzIHx8IHRoaXMub3B0aW9ucy5leHBpcmVzKTtcbiAgICBjb25zdCBleHRyYXMgPSBCdWZmZXIuY29uY2F0KFtCdWZmZXIuZnJvbShcIjAwMDAwMDAwXCIsIFwiaGV4XCIpLCBleHBpcmF0aW9uXSk7XG4gICAgY29uc3Qgc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5zZXJpYWxpemUoXG4gICAgICBjb25zdGFudHMuT1BfU0VULFxuICAgICAgdmFsdWUsXG4gICAgICBleHRyYXNcbiAgICApO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBVdGlscy5lbmNvZGVSZXF1ZXN0KHtcbiAgICAgIGhlYWRlcjoge1xuICAgICAgICBvcGNvZGU6IGNvbnN0YW50cy5PUF9TRVQsXG4gICAgICAgIG9wYXF1ZTogdGhpcy5zZXEsXG4gICAgICAgIGNhcyxcbiAgICAgIH0sXG4gICAgICBrZXksXG4gICAgICB2YWx1ZTogc2VyaWFsaXplZC52YWx1ZSxcbiAgICAgIGV4dHJhczogc2VyaWFsaXplZC5leHRyYXMsXG4gICAgfSk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfRVhJU1RTOlxuICAgICAgICBpZiAoY2FzKSB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJTRVRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgICAgIH1cbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJTRVRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEFERFxuICAgKlxuICAgKiBBZGRzIHRoZSBnaXZlbiBfa2V5XyBhbmQgX3ZhbHVlXyB0byBtZW1jYWNoZS4gVGhlIG9wZXJhdGlvbiBvbmx5IHN1Y2NlZWRzXG4gICAqIGlmIHRoZSBrZXkgaXMgbm90IGFscmVhZHkgc2V0LlxuICAgKlxuICAgKiBUaGUgb3B0aW9ucyBkaWN0aW9uYXJ5IHRha2VzOlxuICAgKiAqIF9leHBpcmVzXzogb3ZlcnJpZGVzIHRoZSBkZWZhdWx0IGV4cGlyYXRpb24gKHNlZSBgQ2xpZW50LmNyZWF0ZWApIGZvciB0aGlzXG4gICAqICAgICAgICAgICAgICBwYXJ0aWN1bGFyIGtleS12YWx1ZSBwYWlyLlxuICAgKi9cbiAgYXN5bmMgYWRkKFxuICAgIGtleTogc3RyaW5nLFxuICAgIHZhbHVlOiBWYWx1ZSxcbiAgICBvcHRpb25zPzogeyBleHBpcmVzPzogbnVtYmVyIH1cbiAgKTogUHJvbWlzZTxib29sZWFuIHwgbnVsbD4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgZmxhZ3MsIHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IGV4cGlyYXRpb24gPSBtYWtlRXhwaXJhdGlvbihvcHRpb25zPy5leHBpcmVzIHx8IHRoaXMub3B0aW9ucy5leHBpcmVzKTtcbiAgICBjb25zdCBleHRyYXMgPSBCdWZmZXIuY29uY2F0KFtCdWZmZXIuZnJvbShcIjAwMDAwMDAwXCIsIFwiaGV4XCIpLCBleHBpcmF0aW9uXSk7XG5cbiAgICBjb25zdCBvcGNvZGUgPSBjb25zdGFudHMuT1BfQUREO1xuICAgIGNvbnN0IHNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuc2VyaWFsaXplKG9wY29kZSwgdmFsdWUsIGV4dHJhcyk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKFxuICAgICAgb3Bjb2RlLFxuICAgICAga2V5LFxuICAgICAgc2VyaWFsaXplZC5leHRyYXMsXG4gICAgICBzZXJpYWxpemVkLnZhbHVlLFxuICAgICAgdGhpcy5zZXFcbiAgICApO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuS0VZX0VYSVNUUzpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJBRERcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlcGxhY2VzIHRoZSBnaXZlbiBfa2V5XyBhbmQgX3ZhbHVlXyB0byBtZW1jYWNoZS4gVGhlIG9wZXJhdGlvbiBvbmx5IHN1Y2NlZWRzXG4gICAqIGlmIHRoZSBrZXkgaXMgYWxyZWFkeSBwcmVzZW50LlxuICAgKi9cbiAgYXN5bmMgcmVwbGFjZShcbiAgICBrZXk6IHN0cmluZyxcbiAgICB2YWx1ZTogVmFsdWUsXG4gICAgb3B0aW9ucz86IHsgZXhwaXJlcz86IG51bWJlciB9XG4gICk6IFByb21pc2U8Ym9vbGVhbiB8IG51bGw+IHtcbiAgICAvLyBUT0RPOiBzdXBwb3J0IGZsYWdzLCBzdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBleHBpcmF0aW9uID0gbWFrZUV4cGlyYXRpb24ob3B0aW9ucz8uZXhwaXJlcyB8fCB0aGlzLm9wdGlvbnMuZXhwaXJlcyk7XG4gICAgY29uc3QgZXh0cmFzID0gQnVmZmVyLmNvbmNhdChbQnVmZmVyLmZyb20oXCIwMDAwMDAwMFwiLCBcImhleFwiKSwgZXhwaXJhdGlvbl0pO1xuXG4gICAgY29uc3Qgb3Bjb2RlOiBjb25zdGFudHMuT1AgPSBjb25zdGFudHMuT1BfUkVQTEFDRTtcbiAgICBjb25zdCBzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLnNlcmlhbGl6ZShvcGNvZGUsIHZhbHVlLCBleHRyYXMpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgIG9wY29kZSxcbiAgICAgIGtleSxcbiAgICAgIHNlcmlhbGl6ZWQuZXh0cmFzLFxuICAgICAgc2VyaWFsaXplZC52YWx1ZSxcbiAgICAgIHRoaXMuc2VxXG4gICAgKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJSRVBMQUNFXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBEZWxldGVzIHRoZSBnaXZlbiBfa2V5XyBmcm9tIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHNcbiAgICogaWYgdGhlIGtleSBpcyBhbHJlYWR5IHByZXNlbnQuXG4gICAqL1xuICBhc3luYyBkZWxldGUoa2V5OiBzdHJpbmcpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAvLyBUT0RPOiBTdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoNCwga2V5LCBcIlwiLCBcIlwiLCB0aGlzLnNlcSk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG5cbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJERUxFVEVcIiwgcmVzcG9uc2U/LmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBJbmNyZW1lbnRzIHRoZSBnaXZlbiBfa2V5XyBpbiBtZW1jYWNoZS5cbiAgICovXG4gIGFzeW5jIGluY3JlbWVudChcbiAgICBrZXk6IHN0cmluZyxcbiAgICBhbW91bnQ6IG51bWJlcixcbiAgICBvcHRpb25zPzogeyBpbml0aWFsPzogbnVtYmVyOyBleHBpcmVzPzogbnVtYmVyIH1cbiAgKTogUHJvbWlzZTx7IHZhbHVlOiBudW1iZXIgfCBudWxsOyBzdWNjZXNzOiBib29sZWFuIHwgbnVsbCB9PiB7XG4gICAgLy8gVE9ETzogc3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgaW5pdGlhbCA9IG9wdGlvbnM/LmluaXRpYWwgfHwgMDtcbiAgICBjb25zdCBleHBpcmVzID0gb3B0aW9ucz8uZXhwaXJlcyB8fCB0aGlzLm9wdGlvbnMuZXhwaXJlcztcbiAgICBjb25zdCBleHRyYXMgPSBtYWtlQW1vdW50SW5pdGlhbEFuZEV4cGlyYXRpb24oYW1vdW50LCBpbml0aWFsLCBleHBpcmVzKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICBjb25zdGFudHMuT1BfSU5DUkVNRU5ULFxuICAgICAga2V5LFxuICAgICAgZXh0cmFzLFxuICAgICAgXCJcIixcbiAgICAgIHRoaXMuc2VxXG4gICAgKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgY29uc3QgYnVmSW50ID1cbiAgICAgICAgICAocmVzcG9uc2UudmFsLnJlYWRVSW50MzJCRSgwKSA8PCA4KSArIHJlc3BvbnNlLnZhbC5yZWFkVUludDMyQkUoNCk7XG4gICAgICAgIHJldHVybiB7IHZhbHVlOiBidWZJbnQsIHN1Y2Nlc3M6IHRydWUgfTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJJTkNSRU1FTlRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIERlY3JlbWVudHMgdGhlIGdpdmVuIGBrZXlgIGluIG1lbWNhY2hlLlxuICAgKi9cbiAgYXN5bmMgZGVjcmVtZW50KFxuICAgIGtleTogc3RyaW5nLFxuICAgIGFtb3VudDogbnVtYmVyLFxuICAgIG9wdGlvbnM6IHsgaW5pdGlhbD86IG51bWJlcjsgZXhwaXJlcz86IG51bWJlciB9XG4gICk6IFByb21pc2U8eyB2YWx1ZTogbnVtYmVyIHwgbnVsbDsgc3VjY2VzczogYm9vbGVhbiB8IG51bGwgfT4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IGluaXRpYWwgPSBvcHRpb25zLmluaXRpYWwgfHwgMDtcbiAgICBjb25zdCBleHBpcmVzID0gb3B0aW9ucy5leHBpcmVzIHx8IHRoaXMub3B0aW9ucy5leHBpcmVzO1xuICAgIGNvbnN0IGV4dHJhcyA9IG1ha2VBbW91bnRJbml0aWFsQW5kRXhwaXJhdGlvbihhbW91bnQsIGluaXRpYWwsIGV4cGlyZXMpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgIGNvbnN0YW50cy5PUF9ERUNSRU1FTlQsXG4gICAgICBrZXksXG4gICAgICBleHRyYXMsXG4gICAgICBcIlwiLFxuICAgICAgdGhpcy5zZXFcbiAgICApO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICBjb25zdCBidWZJbnQgPVxuICAgICAgICAgIChyZXNwb25zZS52YWwucmVhZFVJbnQzMkJFKDApIDw8IDgpICsgcmVzcG9uc2UudmFsLnJlYWRVSW50MzJCRSg0KTtcbiAgICAgICAgcmV0dXJuIHsgdmFsdWU6IGJ1ZkludCwgc3VjY2VzczogdHJ1ZSB9O1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIkRFQ1JFTUVOVFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQXBwZW5kIHRoZSBnaXZlbiBfdmFsdWVfIHRvIHRoZSB2YWx1ZSBhc3NvY2lhdGVkIHdpdGggdGhlIGdpdmVuIF9rZXlfIGluXG4gICAqIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHMgaWYgdGhlIGtleSBpcyBhbHJlYWR5IHByZXNlbnQuXG4gICAqL1xuICBhc3luYyBhcHBlbmQoa2V5OiBzdHJpbmcsIHZhbHVlOiBWYWx1ZSk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IG9wY29kZTogY29uc3RhbnRzLk9QID0gY29uc3RhbnRzLk9QX0FQUEVORDtcbiAgICBjb25zdCBzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLnNlcmlhbGl6ZShvcGNvZGUsIHZhbHVlLCBcIlwiKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICBvcGNvZGUsXG4gICAgICBrZXksXG4gICAgICBzZXJpYWxpemVkLmV4dHJhcyxcbiAgICAgIHNlcmlhbGl6ZWQudmFsdWUsXG4gICAgICB0aGlzLnNlcVxuICAgICk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfTk9UX0ZPVU5EOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiQVBQRU5EXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBQcmVwZW5kIHRoZSBnaXZlbiBfdmFsdWVfIHRvIHRoZSB2YWx1ZSBhc3NvY2lhdGVkIHdpdGggdGhlIGdpdmVuIF9rZXlfIGluXG4gICAqIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHMgaWYgdGhlIGtleSBpcyBhbHJlYWR5IHByZXNlbnQuXG4gICAqL1xuICBhc3luYyBwcmVwZW5kKGtleTogc3RyaW5nLCB2YWx1ZTogVmFsdWUpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAvLyBUT0RPOiBzdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBvcGNvZGU6IGNvbnN0YW50cy5PUCA9IGNvbnN0YW50cy5PUF9QUkVQRU5EO1xuICAgIGNvbnN0IHNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuc2VyaWFsaXplKG9wY29kZSwgdmFsdWUsIFwiXCIpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgIG9wY29kZSxcbiAgICAgIGtleSxcbiAgICAgIHNlcmlhbGl6ZWQuZXh0cmFzLFxuICAgICAgc2VyaWFsaXplZC52YWx1ZSxcbiAgICAgIHRoaXMuc2VxXG4gICAgKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJQUkVQRU5EXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBUb3VjaCBzZXRzIGFuIGV4cGlyYXRpb24gdmFsdWUsIGdpdmVuIGJ5IF9leHBpcmVzXywgb24gdGhlIGdpdmVuIF9rZXlfIGluXG4gICAqIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHMgaWYgdGhlIGtleSBpcyBhbHJlYWR5IHByZXNlbnQuXG4gICAqL1xuICBhc3luYyB0b3VjaChrZXk6IHN0cmluZywgZXhwaXJlczogbnVtYmVyKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgLy8gVE9ETzogc3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgZXh0cmFzID0gbWFrZUV4cGlyYXRpb24oZXhwaXJlcyB8fCB0aGlzLm9wdGlvbnMuZXhwaXJlcyk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKDB4MWMsIGtleSwgZXh0cmFzLCBcIlwiLCB0aGlzLnNlcSk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfTk9UX0ZPVU5EOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiVE9VQ0hcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEZMVVNIXG4gICAqXG4gICAqIEZsdXNoZXMgdGhlIGNhY2hlIG9uIGVhY2ggY29ubmVjdGVkIHNlcnZlci4gVGhlIGNhbGxiYWNrIHNpZ25hdHVyZSBpczpcbiAgICpcbiAgICogICAgIGNhbGxiYWNrKGxhc3RFcnIsIHJlc3VsdHMpXG4gICAqXG4gICAqIHdoZXJlIF9sYXN0RXJyXyBpcyB0aGUgbGFzdCBlcnJvciBlbmNvdW50ZXJlZCAob3IgbnVsbCwgaW4gdGhlIGNvbW1vbiBjYXNlXG4gICAqIG9mIG5vIGVycm9ycykuIF9yZXN1bHRzXyBpcyBhIGRpY3Rpb25hcnkgbWFwcGluZyBgXCJob3N0bmFtZTpwb3J0XCJgIHRvIGVpdGhlclxuICAgKiBgdHJ1ZWAgKGlmIHRoZSBvcGVyYXRpb24gd2FzIHN1Y2Nlc3NmdWwpLCBvciBhbiBlcnJvci5cbiAgICogQHBhcmFtIGNhbGxiYWNrXG4gICAqL1xuICBmbHVzaCgpOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIGJvb2xlYW4gfCBFcnJvcj4+O1xuICBmbHVzaChcbiAgICBjYWxsYmFjazogKFxuICAgICAgZXJyOiBFcnJvciB8IG51bGwsXG4gICAgICByZXN1bHRzOiBSZWNvcmQ8c3RyaW5nLCBib29sZWFuIHwgRXJyb3I+XG4gICAgKSA9PiB2b2lkXG4gICk6IHZvaWQ7XG4gIGZsdXNoKFxuICAgIGNhbGxiYWNrPzogKFxuICAgICAgZXJyOiBFcnJvciB8IG51bGwsXG4gICAgICByZXN1bHRzOiBSZWNvcmQ8c3RyaW5nLCBib29sZWFuIHwgRXJyb3I+XG4gICAgKSA9PiB2b2lkXG4gICkge1xuICAgIGlmIChjYWxsYmFjayA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm4gcHJvbWlzaWZ5KChjYWxsYmFjaykgPT4ge1xuICAgICAgICB0aGlzLmZsdXNoKGZ1bmN0aW9uIChlcnIsIHJlc3VsdHMpIHtcbiAgICAgICAgICBjYWxsYmFjayhlcnIsIHJlc3VsdHMpO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH1cbiAgICAvLyBUT0RPOiBzdXBwb3J0IGV4cGlyYXRpb25cbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoMHgwOCwgXCJcIiwgXCJcIiwgXCJcIiwgdGhpcy5zZXEpO1xuICAgIGxldCBjb3VudCA9IHRoaXMuc2VydmVycy5sZW5ndGg7XG4gICAgY29uc3QgcmVzdWx0OiBSZWNvcmQ8c3RyaW5nLCBib29sZWFuIHwgRXJyb3I+ID0ge307XG4gICAgbGV0IGxhc3RFcnI6IEVycm9yIHwgbnVsbCA9IG51bGw7XG5cbiAgICBjb25zdCBoYW5kbGVGbHVzaCA9IGZ1bmN0aW9uIChzZXE6IG51bWJlciwgc2VydjogU2VydmVyKSB7XG4gICAgICBzZXJ2Lm9uUmVzcG9uc2Uoc2VxLCBmdW5jdGlvbiAoLyogcmVzcG9uc2UgKi8pIHtcbiAgICAgICAgY291bnQgLT0gMTtcbiAgICAgICAgcmVzdWx0W3NlcnYuaG9zdHBvcnRTdHJpbmcoKV0gPSB0cnVlO1xuICAgICAgICBpZiAoY2FsbGJhY2sgJiYgY291bnQgPT09IDApIHtcbiAgICAgICAgICBjYWxsYmFjayhsYXN0RXJyLCByZXN1bHQpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHNlcnYub25FcnJvcihzZXEsIGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgICAgY291bnQgLT0gMTtcbiAgICAgICAgbGFzdEVyciA9IGVycjtcbiAgICAgICAgcmVzdWx0W3NlcnYuaG9zdHBvcnRTdHJpbmcoKV0gPSBlcnI7XG4gICAgICAgIGlmIChjYWxsYmFjayAmJiBjb3VudCA9PT0gMCkge1xuICAgICAgICAgIGNhbGxiYWNrKGxhc3RFcnIsIHJlc3VsdCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgc2Vydi53cml0ZShyZXF1ZXN0KTtcbiAgICB9O1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnNlcnZlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGhhbmRsZUZsdXNoKHRoaXMuc2VxLCB0aGlzLnNlcnZlcnNbaV0pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTVEFUU19XSVRIX0tFWVxuICAgKlxuICAgKiBTZW5kcyBhIG1lbWNhY2hlIHN0YXRzIGNvbW1hbmQgd2l0aCBhIGtleSB0byBlYWNoIGNvbm5lY3RlZCBzZXJ2ZXIuIFRoZVxuICAgKiBjYWxsYmFjayBpcyBpbnZva2VkICoqT05DRSBQRVIgU0VSVkVSKiogYW5kIGhhcyB0aGUgc2lnbmF0dXJlOlxuICAgKlxuICAgKiAgICAgY2FsbGJhY2soZXJyLCBzZXJ2ZXIsIHN0YXRzKVxuICAgKlxuICAgKiBfc2VydmVyXyBpcyB0aGUgYFwiaG9zdG5hbWU6cG9ydFwiYCBvZiB0aGUgc2VydmVyLCBhbmQgX3N0YXRzXyBpcyBhIGRpY3Rpb25hcnlcbiAgICogbWFwcGluZyB0aGUgc3RhdCBuYW1lIHRvIHRoZSB2YWx1ZSBvZiB0aGUgc3RhdGlzdGljIGFzIGEgc3RyaW5nLlxuICAgKiBAcGFyYW0ga2V5XG4gICAqIEBwYXJhbSBjYWxsYmFja1xuICAgKi9cbiAgc3RhdHNXaXRoS2V5KFxuICAgIGtleTogc3RyaW5nLFxuICAgIGNhbGxiYWNrPzogKFxuICAgICAgZXJyOiBFcnJvciB8IG51bGwsXG4gICAgICBzZXJ2ZXI6IHN0cmluZyxcbiAgICAgIHN0YXRzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+IHwgbnVsbFxuICAgICkgPT4gdm9pZFxuICApOiB2b2lkIHtcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoMHgxMCwga2V5LCBcIlwiLCBcIlwiLCB0aGlzLnNlcSk7XG5cbiAgICBjb25zdCBoYW5kbGVTdGF0cyA9IChzZXE6IG51bWJlciwgc2VydjogU2VydmVyKSA9PiB7XG4gICAgICBjb25zdCByZXN1bHQ6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcbiAgICAgIGNvbnN0IGhhbmRsZTogT25SZXNwb25zZUNhbGxiYWNrID0gKHJlc3BvbnNlKSA9PiB7XG4gICAgICAgIC8vIGVuZCBvZiBzdGF0IHJlc3BvbnNlc1xuICAgICAgICBpZiAocmVzcG9uc2UuaGVhZGVyLnRvdGFsQm9keUxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgICAgY2FsbGJhY2sobnVsbCwgc2Vydi5ob3N0cG9ydFN0cmluZygpLCByZXN1bHQpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgLy8gcHJvY2VzcyBzaW5nbGUgc3RhdCBsaW5lIHJlc3BvbnNlXG4gICAgICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgICAgIHJlc3VsdFtyZXNwb25zZS5rZXkudG9TdHJpbmcoKV0gPSByZXNwb25zZS52YWwudG9TdHJpbmcoKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICBjb25zdCBlcnJvciA9IHRoaXMuaGFuZGxlUmVzcG9uc2VFcnJvcihcbiAgICAgICAgICAgICAgYFNUQVRTICgke2tleX0pYCxcbiAgICAgICAgICAgICAgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyxcbiAgICAgICAgICAgICAgdW5kZWZpbmVkXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgICAgICAgIGNhbGxiYWNrKGVycm9yLCBzZXJ2Lmhvc3Rwb3J0U3RyaW5nKCksIG51bGwpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9O1xuICAgICAgaGFuZGxlLnF1aWV0ID0gdHJ1ZTtcblxuICAgICAgc2Vydi5vblJlc3BvbnNlKHNlcSwgaGFuZGxlKTtcbiAgICAgIHNlcnYub25FcnJvcihzZXEsIGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgICAgY2FsbGJhY2soZXJyLCBzZXJ2Lmhvc3Rwb3J0U3RyaW5nKCksIG51bGwpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHNlcnYud3JpdGUocmVxdWVzdCk7XG4gICAgfTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5zZXJ2ZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBoYW5kbGVTdGF0cyh0aGlzLnNlcSwgdGhpcy5zZXJ2ZXJzW2ldKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU1RBVFNcbiAgICpcbiAgICogRmV0Y2hlcyBtZW1jYWNoZSBzdGF0cyBmcm9tIGVhY2ggY29ubmVjdGVkIHNlcnZlci4gVGhlIGNhbGxiYWNrIGlzIGludm9rZWRcbiAgICogKipPTkNFIFBFUiBTRVJWRVIqKiBhbmQgaGFzIHRoZSBzaWduYXR1cmU6XG4gICAqXG4gICAqICAgICBjYWxsYmFjayhlcnIsIHNlcnZlciwgc3RhdHMpXG4gICAqXG4gICAqIF9zZXJ2ZXJfIGlzIHRoZSBgXCJob3N0bmFtZTpwb3J0XCJgIG9mIHRoZSBzZXJ2ZXIsIGFuZCBfc3RhdHNfIGlzIGFcbiAgICogZGljdGlvbmFyeSBtYXBwaW5nIHRoZSBzdGF0IG5hbWUgdG8gdGhlIHZhbHVlIG9mIHRoZSBzdGF0aXN0aWMgYXMgYSBzdHJpbmcuXG4gICAqIEBwYXJhbSBjYWxsYmFja1xuICAgKi9cbiAgc3RhdHMoXG4gICAgY2FsbGJhY2s/OiAoXG4gICAgICBlcnI6IEVycm9yIHwgbnVsbCxcbiAgICAgIHNlcnZlcjogc3RyaW5nLFxuICAgICAgc3RhdHM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gfCBudWxsXG4gICAgKSA9PiB2b2lkXG4gICk6IHZvaWQge1xuICAgIHRoaXMuc3RhdHNXaXRoS2V5KFwiXCIsIGNhbGxiYWNrKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSRVNFVF9TVEFUU1xuICAgKlxuICAgKiBSZXNldCB0aGUgc3RhdGlzdGljcyBlYWNoIHNlcnZlciBpcyBrZWVwaW5nIGJhY2sgdG8gemVyby4gVGhpcyBkb2Vzbid0IGNsZWFyXG4gICAqIHN0YXRzIHN1Y2ggYXMgaXRlbSBjb3VudCwgYnV0IHRlbXBvcmFyeSBzdGF0cyBzdWNoIGFzIHRvdGFsIG51bWJlciBvZlxuICAgKiBjb25uZWN0aW9ucyBvdmVyIHRpbWUuXG4gICAqXG4gICAqIFRoZSBjYWxsYmFjayBpcyBpbnZva2VkICoqT05DRSBQRVIgU0VSVkVSKiogYW5kIGhhcyB0aGUgc2lnbmF0dXJlOlxuICAgKlxuICAgKiAgICAgY2FsbGJhY2soZXJyLCBzZXJ2ZXIpXG4gICAqXG4gICAqIF9zZXJ2ZXJfIGlzIHRoZSBgXCJob3N0bmFtZTpwb3J0XCJgIG9mIHRoZSBzZXJ2ZXIuXG4gICAqIEBwYXJhbSBjYWxsYmFja1xuICAgKi9cbiAgcmVzZXRTdGF0cyhcbiAgICBjYWxsYmFjaz86IChcbiAgICAgIGVycjogRXJyb3IgfCBudWxsLFxuICAgICAgc2VydmVyOiBzdHJpbmcsXG4gICAgICBzdGF0czogUmVjb3JkPHN0cmluZywgc3RyaW5nPiB8IG51bGxcbiAgICApID0+IHZvaWRcbiAgKTogdm9pZCB7XG4gICAgdGhpcy5zdGF0c1dpdGhLZXkoXCJyZXNldFwiLCBjYWxsYmFjayk7XG4gIH1cblxuICAvKipcbiAgICogUVVJVFxuICAgKlxuICAgKiBDbG9zZXMgdGhlIGNvbm5lY3Rpb24gdG8gZWFjaCBzZXJ2ZXIsIG5vdGlmeWluZyB0aGVtIG9mIHRoaXMgaW50ZW50aW9uLiBOb3RlXG4gICAqIHRoYXQgcXVpdCBjYW4gcmFjZSBhZ2FpbnN0IGFscmVhZHkgb3V0c3RhbmRpbmcgcmVxdWVzdHMgd2hlbiB0aG9zZSByZXF1ZXN0c1xuICAgKiBmYWlsIGFuZCBhcmUgcmV0cmllZCwgbGVhZGluZyB0byB0aGUgcXVpdCBjb21tYW5kIHdpbm5pbmcgYW5kIGNsb3NpbmcgdGhlXG4gICAqIGNvbm5lY3Rpb24gYmVmb3JlIHRoZSByZXRyaWVzIGNvbXBsZXRlLlxuICAgKi9cbiAgcXVpdCgpIHtcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICAvLyBUT0RPOiBOaWNlciBwZXJoYXBzIHRvIGRvIFFVSVRRICgweDE3KSBidXQgbmVlZCBhIG5ldyBjYWxsYmFjayBmb3Igd2hlblxuICAgIC8vIHdyaXRlIGlzIGRvbmUuXG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKDB4MDcsIFwiXCIsIFwiXCIsIFwiXCIsIHRoaXMuc2VxKTsgLy8gUVVJVFxuICAgIGxldCBzZXJ2O1xuXG4gICAgY29uc3QgaGFuZGxlUXVpdCA9IGZ1bmN0aW9uIChzZXE6IG51bWJlciwgc2VydjogU2VydmVyKSB7XG4gICAgICBzZXJ2Lm9uUmVzcG9uc2Uoc2VxLCBmdW5jdGlvbiAoLyogcmVzcG9uc2UgKi8pIHtcbiAgICAgICAgc2Vydi5jbG9zZSgpO1xuICAgICAgfSk7XG4gICAgICBzZXJ2Lm9uRXJyb3Ioc2VxLCBmdW5jdGlvbiAoLyogZXJyICovKSB7XG4gICAgICAgIHNlcnYuY2xvc2UoKTtcbiAgICAgIH0pO1xuICAgICAgc2Vydi53cml0ZShyZXF1ZXN0KTtcbiAgICB9O1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnNlcnZlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHNlcnYgPSB0aGlzLnNlcnZlcnNbaV07XG4gICAgICBoYW5kbGVRdWl0KHRoaXMuc2VxLCBzZXJ2KTtcbiAgICB9XG4gIH1cblxuICBfdmVyc2lvbihzZXJ2ZXI6IFNlcnZlcik6IFByb21pc2U8eyB2YWx1ZTogVmFsdWUgfCBudWxsIH0+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICAgIGNvbnN0YW50cy5PUF9WRVJTSU9OLFxuICAgICAgICBcIlwiLFxuICAgICAgICBcIlwiLFxuICAgICAgICBcIlwiLFxuICAgICAgICB0aGlzLnNlcVxuICAgICAgKTtcbiAgICAgIHRoaXMucGVyZm9ybU9uU2VydmVyKHNlcnZlciwgcmVxdWVzdCwgdGhpcy5zZXEsIChlcnIsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICByZXR1cm4gcmVqZWN0KGVycik7XG4gICAgICAgIH1cblxuICAgICAgICBzd2l0Y2ggKHJlc3BvbnNlIS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICAgICAgLyogVE9ETzogdGhpcyBpcyBidWdnZWQsIHdlIHNob3VsZCd0IHVzZSB0aGUgZGVzZXJpYWxpemVyIGhlcmUsIHNpbmNlIHZlcnNpb24gYWx3YXlzIHJldHVybnMgYSB2ZXJzaW9uIHN0cmluZy5cbiAgICAgICAgICAgICBUaGUgZGVzZXJpYWxpemVyIHNob3VsZCBvbmx5IGJlIHVzZWQgb24gdXNlciBrZXkgZGF0YS4gKi9cbiAgICAgICAgICAgIGNvbnN0IGRlc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5kZXNlcmlhbGl6ZShcbiAgICAgICAgICAgICAgcmVzcG9uc2UhLmhlYWRlci5vcGNvZGUsXG4gICAgICAgICAgICAgIHJlc3BvbnNlIS52YWwsXG4gICAgICAgICAgICAgIHJlc3BvbnNlIS5leHRyYXNcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICByZXR1cm4gcmVzb2x2ZSh7IHZhbHVlOiBkZXNlcmlhbGl6ZWQudmFsdWUgfSk7XG4gICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHJldHVybiByZWplY3QoXG4gICAgICAgICAgICAgIHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJWRVJTSU9OXCIsIHJlc3BvbnNlIS5oZWFkZXIuc3RhdHVzKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmVxdWVzdCB0aGUgc2VydmVyIHZlcnNpb24gZnJvbSB0aGUgXCJmaXJzdFwiIHNlcnZlciBpbiB0aGUgYmFja2VuZCBwb29sLlxuICAgKiBUaGUgc2VydmVyIHJlc3BvbmRzIHdpdGggYSBwYWNrZXQgY29udGFpbmluZyB0aGUgdmVyc2lvbiBzdHJpbmcgaW4gdGhlIGJvZHkgd2l0aCB0aGUgZm9sbG93aW5nIGZvcm1hdDogXCJ4LnkuelwiXG4gICAqL1xuICB2ZXJzaW9uKCk6IFByb21pc2U8eyB2YWx1ZTogVmFsdWUgfCBudWxsIH0+IHtcbiAgICBjb25zdCBzZXJ2ZXIgPSB0aGlzLnNlcnZlcktleVRvU2VydmVyKHRoaXMuc2VydmVyS2V5c1swXSk7XG4gICAgcmV0dXJuIHRoaXMuX3ZlcnNpb24oc2VydmVyKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXRyaWV2ZXMgdGhlIHNlcnZlciB2ZXJzaW9uIGZyb20gYWxsIHRoZSBzZXJ2ZXJzXG4gICAqIGluIHRoZSBiYWNrZW5kIHBvb2wsIGVycm9ycyBpZiBhbnkgb25lIG9mIHRoZW0gaGFzIGFuXG4gICAqIGVycm9yXG4gICAqL1xuICBhc3luYyB2ZXJzaW9uQWxsKCk6IFByb21pc2U8e1xuICAgIHZhbHVlczogUmVjb3JkPHN0cmluZywgVmFsdWUgfCBudWxsPjtcbiAgfT4ge1xuICAgIGNvbnN0IHZlcnNpb25PYmplY3RzID0gYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICB0aGlzLnNlcnZlcktleXMubWFwKChzZXJ2ZXJLZXkpID0+IHtcbiAgICAgICAgY29uc3Qgc2VydmVyID0gdGhpcy5zZXJ2ZXJLZXlUb1NlcnZlcihzZXJ2ZXJLZXkpO1xuXG4gICAgICAgIHJldHVybiB0aGlzLl92ZXJzaW9uKHNlcnZlcikudGhlbigocmVzcG9uc2UpID0+IHtcbiAgICAgICAgICByZXR1cm4geyBzZXJ2ZXJLZXk6IHNlcnZlcktleSwgdmFsdWU6IHJlc3BvbnNlLnZhbHVlIH07XG4gICAgICAgIH0pO1xuICAgICAgfSlcbiAgICApO1xuICAgIGNvbnN0IHZhbHVlcyA9IHZlcnNpb25PYmplY3RzLnJlZHVjZSgoYWNjdW11bGF0b3IsIHZlcnNpb25PYmplY3QpID0+IHtcbiAgICAgIGFjY3VtdWxhdG9yW3ZlcnNpb25PYmplY3Quc2VydmVyS2V5XSA9IHZlcnNpb25PYmplY3QudmFsdWU7XG4gICAgICByZXR1cm4gYWNjdW11bGF0b3I7XG4gICAgfSwge30gYXMgUmVjb3JkPHN0cmluZywgVmFsdWUgfCBudWxsPik7XG4gICAgcmV0dXJuIHsgdmFsdWVzOiB2YWx1ZXMgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDbG9zZXMgKGFicnVwdGx5KSBjb25uZWN0aW9ucyB0byBhbGwgdGhlIHNlcnZlcnMuXG4gICAqIEBzZWUgdGhpcy5xdWl0XG4gICAqL1xuICBjbG9zZSgpIHtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuc2VydmVycy5sZW5ndGg7IGkrKykge1xuICAgICAgdGhpcy5zZXJ2ZXJzW2ldLmNsb3NlKCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFBlcmZvcm0gYSBnZW5lcmljIHNpbmdsZSByZXNwb25zZSBvcGVyYXRpb24gKGdldCwgc2V0IGV0Yykgb24gb25lIHNlcnZlclxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IHRoZSBrZXkgdG8gaGFzaCB0byBnZXQgYSBzZXJ2ZXIgZnJvbSB0aGUgcG9vbFxuICAgKiBAcGFyYW0ge2J1ZmZlcn0gcmVxdWVzdCBhIGJ1ZmZlciBjb250YWluaW5nIHRoZSByZXF1ZXN0XG4gICAqIEBwYXJhbSB7bnVtYmVyfSBzZXEgdGhlIHNlcXVlbmNlIG51bWJlciBvZiB0aGUgb3BlcmF0aW9uLiBJdCBpcyB1c2VkIHRvIHBpbiB0aGUgY2FsbGJhY2tzXG4gICAgICAgICAgICAgICAgICAgICAgICAgdG8gYSBzcGVjaWZpYyBvcGVyYXRpb24gYW5kIHNob3VsZCBuZXZlciBjaGFuZ2UgZHVyaW5nIGEgYHBlcmZvcm1gLlxuICAgKiBAcGFyYW0ge251bWJlcj99IHJldHJpZXMgbnVtYmVyIG9mIHRpbWVzIHRvIHJldHJ5IHJlcXVlc3Qgb24gZmFpbHVyZVxuICAgKi9cbiAgcGVyZm9ybShcbiAgICBrZXk6IHN0cmluZyxcbiAgICByZXF1ZXN0OiBCdWZmZXIsXG4gICAgc2VxOiBudW1iZXIsXG4gICAgcmV0cmllcz86IG51bWJlclxuICApOiBQcm9taXNlPE1lc3NhZ2U+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgY29uc3Qgc2VydmVyS2V5ID0gdGhpcy5sb29rdXBLZXlUb1NlcnZlcktleShrZXkpO1xuICAgICAgY29uc3Qgc2VydmVyID0gdGhpcy5zZXJ2ZXJLZXlUb1NlcnZlcihzZXJ2ZXJLZXkpO1xuXG4gICAgICBpZiAoIXNlcnZlcikge1xuICAgICAgICByZXR1cm4gcmVqZWN0KG5ldyBFcnJvcihcIk5vIHNlcnZlcnMgYXZhaWxhYmxlXCIpKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5wZXJmb3JtT25TZXJ2ZXIoXG4gICAgICAgIHNlcnZlcixcbiAgICAgICAgcmVxdWVzdCxcbiAgICAgICAgc2VxLFxuICAgICAgICAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICByZXR1cm4gcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmVzb2x2ZShyZXNwb25zZSEpO1xuICAgICAgICB9LFxuICAgICAgICByZXRyaWVzXG4gICAgICApO1xuICAgIH0pO1xuICB9XG5cbiAgcGVyZm9ybU9uU2VydmVyKFxuICAgIHNlcnZlcjogU2VydmVyLFxuICAgIHJlcXVlc3Q6IEJ1ZmZlcixcbiAgICBzZXE6IG51bWJlcixcbiAgICBjYWxsYmFjazogUmVzcG9uc2VPckVycm9yQ2FsbGJhY2ssXG4gICAgcmV0cmllczogbnVtYmVyID0gMFxuICApIHtcbiAgICBjb25zdCBfdGhpcyA9IHRoaXM7XG5cbiAgICByZXRyaWVzID0gcmV0cmllcyB8fCB0aGlzLm9wdGlvbnMucmV0cmllcztcbiAgICBjb25zdCBvcmlnUmV0cmllcyA9IHRoaXMub3B0aW9ucy5yZXRyaWVzO1xuICAgIGNvbnN0IGxvZ2dlciA9IHRoaXMub3B0aW9ucy5sb2dnZXI7XG4gICAgY29uc3QgcmV0cnlfZGVsYXkgPSB0aGlzLm9wdGlvbnMucmV0cnlfZGVsYXk7XG5cbiAgICBjb25zdCByZXNwb25zZUhhbmRsZXI6IE9uUmVzcG9uc2VDYWxsYmFjayA9IGZ1bmN0aW9uIChyZXNwb25zZSkge1xuICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgIGNhbGxiYWNrKG51bGwsIHJlc3BvbnNlKTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgY29uc3QgZXJyb3JIYW5kbGVyOiBPbkVycm9yQ2FsbGJhY2sgPSBmdW5jdGlvbiAoZXJyb3IpIHtcbiAgICAgIGlmICgtLXJldHJpZXMgPiAwKSB7XG4gICAgICAgIC8vIFdhaXQgZm9yIHJldHJ5X2RlbGF5XG4gICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgIF90aGlzLnBlcmZvcm1PblNlcnZlcihzZXJ2ZXIsIHJlcXVlc3QsIHNlcSwgY2FsbGJhY2ssIHJldHJpZXMpO1xuICAgICAgICB9LCAxMDAwICogcmV0cnlfZGVsYXkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbG9nZ2VyLmxvZyhcbiAgICAgICAgICBcIk1lbUpTOiBTZXJ2ZXIgPFwiICtcbiAgICAgICAgICAgIHNlcnZlci5ob3N0cG9ydFN0cmluZygpICtcbiAgICAgICAgICAgIFwiPiBmYWlsZWQgYWZ0ZXIgKFwiICtcbiAgICAgICAgICAgIG9yaWdSZXRyaWVzICtcbiAgICAgICAgICAgIFwiKSByZXRyaWVzIHdpdGggZXJyb3IgLSBcIiArXG4gICAgICAgICAgICBlcnJvci5tZXNzYWdlXG4gICAgICAgICk7XG4gICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgIGNhbGxiYWNrKGVycm9yLCBudWxsKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH07XG5cbiAgICBzZXJ2ZXIub25SZXNwb25zZShzZXEsIHJlc3BvbnNlSGFuZGxlcik7XG4gICAgc2VydmVyLm9uRXJyb3Ioc2VxLCBlcnJvckhhbmRsZXIpO1xuICAgIHNlcnZlci53cml0ZShyZXF1ZXN0KTtcbiAgfVxuXG4gIC8vIEluY3JlbWVudCB0aGUgc2VxIHZhbHVlXG4gIGluY3JTZXEoKSB7XG4gICAgdGhpcy5zZXErKztcblxuICAgIC8vIFdyYXAgYHRoaXMuc2VxYCB0byAzMi1iaXRzIHNpbmNlIHRoZSBmaWVsZCB3ZSBmaXQgaXQgaW50byBpcyBvbmx5IDMyLWJpdHMuXG4gICAgdGhpcy5zZXEgJj0gMHhmZmZmZmZmZjtcbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlQW5kTG9nRXJyb3IoXG4gICAgY29tbWFuZE5hbWU6IHN0cmluZyxcbiAgICByZXNwb25zZVN0YXR1czogUmVzcG9uc2VTdGF0dXMgfCB1bmRlZmluZWRcbiAgKTogRXJyb3Ige1xuICAgIGNvbnN0IGVycm9yTWVzc2FnZSA9IGBNZW1KUyAke2NvbW1hbmROYW1lfTogJHtjb25zdGFudHMucmVzcG9uc2VTdGF0dXNUb1N0cmluZyhcbiAgICAgIHJlc3BvbnNlU3RhdHVzXG4gICAgKX1gO1xuICAgIHRoaXMub3B0aW9ucy5sb2dnZXIubG9nKGVycm9yTWVzc2FnZSk7XG4gICAgcmV0dXJuIG5ldyBFcnJvcihlcnJvck1lc3NhZ2UpO1xuICB9XG5cbiAgLyoqXG4gICAqIExvZyBhbiBlcnJvciB0byB0aGUgbG9nZ2VyLCB0aGVuIHJldHVybiB0aGUgZXJyb3IuXG4gICAqIElmIGEgY2FsbGJhY2sgaXMgZ2l2ZW4sIGNhbGwgaXQgd2l0aCBjYWxsYmFjayhlcnJvciwgbnVsbCkuXG4gICAqL1xuICBwcml2YXRlIGhhbmRsZVJlc3BvbnNlRXJyb3IoXG4gICAgY29tbWFuZE5hbWU6IHN0cmluZyxcbiAgICByZXNwb25zZVN0YXR1czogUmVzcG9uc2VTdGF0dXMgfCB1bmRlZmluZWQsXG4gICAgY2FsbGJhY2s6IHVuZGVmaW5lZCB8ICgoZXJyb3I6IEVycm9yIHwgbnVsbCwgb3RoZXI6IG51bGwpID0+IHZvaWQpXG4gICk6IEVycm9yIHtcbiAgICBjb25zdCBlcnJvciA9IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoY29tbWFuZE5hbWUsIHJlc3BvbnNlU3RhdHVzKTtcbiAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgIGNhbGxiYWNrKGVycm9yLCBudWxsKTtcbiAgICB9XG4gICAgcmV0dXJuIGVycm9yO1xuICB9XG59XG5cbmV4cG9ydCB7IENsaWVudCwgU2VydmVyLCBVdGlscywgSGVhZGVyIH07XG4iXX0= \ No newline at end of file diff --git a/src/memjs/memjs.ts b/src/memjs/memjs.ts index 0f82be2..cf67633 100644 --- a/src/memjs/memjs.ts +++ b/src/memjs/memjs.ts @@ -347,7 +347,7 @@ class Client { */ async getMulti( keys: Keys[] - ): Promise | null> { + ): Promise> { const serverKeytoLookupKeys: { [serverKey: string]: string[]; } = {}; From 2f3670a3457616256fc639a11d5aaf966c1f2a31 Mon Sep 17 00:00:00 2001 From: David Blackman Date: Tue, 18 May 2021 14:36:51 -0400 Subject: [PATCH 59/79] error on some weird edge cases we are having trouble debugging (#13) --- lib/memjs/memjs.d.ts.map | 2 +- lib/memjs/memjs.js | 10 ++++++++-- src/memjs/memjs.ts | 11 ++++++++++- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/lib/memjs/memjs.d.ts.map b/lib/memjs/memjs.d.ts.map index 7ec9090..8001864 100644 --- a/lib/memjs/memjs.d.ts.map +++ b/lib/memjs/memjs.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"memjs.d.ts","sourceRoot":"","sources":["../../src/memjs/memjs.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"memjs.d.ts","sourceRoot":"","sources":["../../src/memjs/memjs.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/lib/memjs/memjs.js b/lib/memjs/memjs.js index a1e2da5..8ad45f0 100644 --- a/lib/memjs/memjs.js +++ b/lib/memjs/memjs.js @@ -199,11 +199,17 @@ class Client { handle.quiet = false; resolve(responseMap); } - else { + else if (response.header.opcode === constants.OP_GETK || response.header.opcode === constants.OP_GETKQ) { const deserialized = this.serializer.deserialize(response.header.opcode, response.val, response.extras); const key = response.key.toString(); + if (key.length === 0) { + return reject(new Error("Recieved empty key in getMulti: " + JSON.stringify(response))); + } responseMap[key] = { ...deserialized, cas: response.header.cas }; } + else { + return reject(new Error("Recieved response in getMulti for unknown opcode: " + JSON.stringify(response))); + } break; default: return reject(this.createAndLogError("GET", response.header.status)); @@ -725,4 +731,4 @@ class Client { } } exports.Client = Client; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVtanMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbWVtanMvbWVtanMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLHdCQUF3Qjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUV4QixxQ0FLa0I7QUFvaENELHVGQXRoQ2YsZUFBTSxPQXNoQ2U7QUFuaEN2Qix1REFBK0Q7QUFDL0QsbUNBU2lCO0FBQ2pCLHVEQUF5QztBQUN6QywyQ0FBNkM7QUFDN0MsK0NBQWlDO0FBc2dDUixzQkFBSztBQXJnQzlCLGlEQUFtQztBQXFnQ0gsd0JBQU07QUFuZ0N0QyxTQUFTLDhCQUE4QixDQUNyQyxPQUFpQixFQUNqQixHQUFXO0lBRVgsTUFBTSxLQUFLLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQztJQUM3QixNQUFNLEtBQUssR0FBRyxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxnQkFBUSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3BELE9BQU8sT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ3hCLENBQUM7QUFFRCwrQ0FBK0M7QUFDL0MsU0FBUyxTQUFTLENBQ2hCLE9BQTBFO0lBRTFFLE9BQU8sSUFBSSxPQUFPLENBQUMsVUFBVSxPQUFPLEVBQUUsTUFBTTtRQUMxQyxPQUFPLENBQUMsVUFBVSxHQUFHLEVBQUUsTUFBTTtZQUMzQixHQUFHLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3RDLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBNkRELE1BQU0sTUFBTTtJQVFWLDRFQUE0RTtJQUM1RSxtQ0FBbUM7SUFDbkMsWUFBWSxPQUFpQixFQUFFLE9BQTBDO1FBQ3ZFLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO1FBQ3ZCLElB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QyxDQUFDO2lCQUN2QjthQUNGO1FBQ0gsQ0FBQyxDQUFDO1FBRUYsTUFBTSxDQUFDLFVBQVUsQ0FBQyxHQUFHLEVBQUUsZUFBZSxDQUFDLENBQUM7UUFDeEMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUUsWUFBWSxDQUFDLENBQUM7UUFDbEMsTUFBTSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUN4QixDQUFDO0lBRUQsMEJBQTBCO0lBQzFCLE9BQU87UUFDTCxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7UUFFWCw2RUFBNkU7UUFDN0UsSUFBSSxDQUFDLEdBQUcsSUFBSSxVQUFVLENBQUM7SUFDekIsQ0FBQztJQUVPLGlCQUFpQixDQUN2QixXQUFtQixFQUNuQixjQUEwQztRQUUxQyxNQUFNLFlBQVksR0FBRyxTQUFTLFdBQVcsS0FBSyxTQUFTLENBQUMsc0JBQXNCLENBQzVFLGNBQWMsQ0FDZixFQUFFLENBQUM7UUFDSixJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDdEMsT0FBTyxJQUFJLEtBQUssQ0FBQyxZQUFZLENBQUMsQ0FBQztJQUNqQyxDQUFDO0lBRUQ7OztPQUdHO0lBQ0ssbUJBQW1CLENBQ3pCLFdBQW1CLEVBQ25CLGNBQTBDLEVBQzFDLFFBQWtFO1FBRWxFLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxXQUFXLEVBQUUsY0FBYyxDQUFDLENBQUM7UUFDbEUsSUFBSSxRQUFRLEVBQUU7WUFDWixRQUFRLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxDQUFDO1NBQ3ZCO1FBQ0QsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0NBQ0Y7QUFFUSx3QkFBTSIsInNvdXJjZXNDb250ZW50IjpbIi8vIE1lbVRTIE1lbWNhY2hlIENsaWVudFxuXG5pbXBvcnQge1xuICBPbkVycm9yQ2FsbGJhY2ssXG4gIE9uUmVzcG9uc2VDYWxsYmFjayxcbiAgU2VydmVyLFxuICBTZXJ2ZXJPcHRpb25zLFxufSBmcm9tIFwiLi9zZXJ2ZXJcIjtcbmltcG9ydCB7IG5vb3BTZXJpYWxpemVyLCBTZXJpYWxpemVyIH0gZnJvbSBcIi4vbm9vcC1zZXJpYWxpemVyXCI7XG5pbXBvcnQge1xuICBtYWtlUmVxdWVzdEJ1ZmZlcixcbiAgY29weUludG9SZXF1ZXN0QnVmZmVyLFxuICBtZXJnZSxcbiAgbWFrZUV4cGlyYXRpb24sXG4gIG1ha2VBbW91bnRJbml0aWFsQW5kRXhwaXJhdGlvbixcbiAgaGFzaENvZGUsXG4gIE1heWJlQnVmZmVyLFxuICBNZXNzYWdlLFxufSBmcm9tIFwiLi91dGlsc1wiO1xuaW1wb3J0ICogYXMgY29uc3RhbnRzIGZyb20gXCIuL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgUmVzcG9uc2VTdGF0dXMgfSBmcm9tIFwiLi9jb25zdGFudHNcIjtcbmltcG9ydCAqIGFzIFV0aWxzIGZyb20gXCIuL3V0aWxzXCI7XG5pbXBvcnQgKiBhcyBIZWFkZXIgZnJvbSBcIi4vaGVhZGVyXCI7XG5cbmZ1bmN0aW9uIGRlZmF1bHRLZXlUb1NlcnZlckhhc2hGdW5jdGlvbihcbiAgc2VydmVyczogc3RyaW5nW10sXG4gIGtleTogc3RyaW5nXG4pOiBzdHJpbmcge1xuICBjb25zdCB0b3RhbCA9IHNlcnZlcnMubGVuZ3RoO1xuICBjb25zdCBpbmRleCA9IHRvdGFsID4gMSA/IGhhc2hDb2RlKGtleSkgJSB0b3RhbCA6IDA7XG4gIHJldHVybiBzZXJ2ZXJzW2luZGV4XTtcbn1cblxuLy8gY29udmVydHMgYSBjYWxsIGludG8gYSBwcm9taXNlLXJldHVybmluZyBvbmVcbmZ1bmN0aW9uIHByb21pc2lmeTxSZXN1bHQ+KFxuICBjb21tYW5kOiAoY2FsbGJhY2s6IChlcnJvcjogRXJyb3IgfCBudWxsLCByZXN1bHQ6IFJlc3VsdCkgPT4gdm9pZCkgPT4gdm9pZFxuKTogUHJvbWlzZTxSZXN1bHQ+IHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICBjb21tYW5kKGZ1bmN0aW9uIChlcnIsIHJlc3VsdCkge1xuICAgICAgZXJyID8gcmVqZWN0KGVycikgOiByZXNvbHZlKHJlc3VsdCk7XG4gICAgfSk7XG4gIH0pO1xufVxuXG50eXBlIFJlc3BvbnNlT3JFcnJvckNhbGxiYWNrID0gKFxuICBlcnJvcjogRXJyb3IgfCBudWxsLFxuICByZXNwb25zZTogTWVzc2FnZSB8IG51bGxcbikgPT4gdm9pZDtcblxuaW50ZXJmYWNlIEJhc2VDbGllbnRPcHRpb25zIHtcbiAgcmV0cmllczogbnVtYmVyO1xuICByZXRyeV9kZWxheTogbnVtYmVyO1xuICBleHBpcmVzOiBudW1iZXI7XG4gIGxvZ2dlcjogeyBsb2c6IHR5cGVvZiBjb25zb2xlLmxvZyB9O1xuICBrZXlUb1NlcnZlckhhc2hGdW5jdGlvbjogdHlwZW9mIGRlZmF1bHRLZXlUb1NlcnZlckhhc2hGdW5jdGlvbjtcbn1cblxuaW50ZXJmYWNlIFNlcmlhbGl6ZXJQcm9wPFZhbHVlLCBFeHRyYXM+IHtcbiAgc2VyaWFsaXplcjogU2VyaWFsaXplcjxWYWx1ZSwgRXh0cmFzPjtcbn1cblxuLyoqXG4gKiBUaGUgY2xpZW50IGhhcyBwYXJ0aWFsIHN1cHBvcnQgZm9yIHNlcmlhbGl6aW5nIGFuZCBkZXNlcmlhbGl6aW5nIHZhbHVlcyBmcm9tIHRoZVxuICogQnVmZmVyIGJ5dGUgc3RyaW5ncyB3ZSByZWNpZXZlIGZyb20gdGhlIHdpcmUuIFRoZSBkZWZhdWx0IHNlcmlhbGl6ZXIgaXMgZm9yIE1heWJlQnVmZmVyLlxuICpcbiAqIElmIFZhbHVlIGFuZCBFeHRyYXMgYXJlIG9mIHR5cGUgQnVmZmVyLCB0aGVuIHJldHVybiB0eXBlIFdoZW5CdWZmZXIuIE90aGVyd2lzZSxcbiAqIHJldHVybiB0eXBlIE5vdEJ1ZmZlci5cbiAqL1xudHlwZSBJZkJ1ZmZlcjxcbiAgVmFsdWUsXG4gIEV4dHJhcyxcbiAgV2hlblZhbHVlQW5kRXh0cmFzQXJlQnVmZmVycyxcbiAgTm90QnVmZmVyXG4+ID0gVmFsdWUgZXh0ZW5kcyBCdWZmZXJcbiAgPyBFeHRyYXMgZXh0ZW5kcyBCdWZmZXJcbiAgICA/IFdoZW5WYWx1ZUFuZEV4dHJhc0FyZUJ1ZmZlcnNcbiAgICA6IE5vdEJ1ZmZlclxuICA6IE5vdEJ1ZmZlcjtcblxuZXhwb3J0IHR5cGUgR2l2ZW5DbGllbnRPcHRpb25zPFZhbHVlLCBFeHRyYXM+ID0gUGFydGlhbDxCYXNlQ2xpZW50T3B0aW9ucz4gJlxuICBJZkJ1ZmZlcjxcbiAgICBWYWx1ZSxcbiAgICBFeHRyYXMsXG4gICAgUGFydGlhbDxTZXJpYWxpemVyUHJvcDxWYWx1ZSwgRXh0cmFzPj4sXG4gICAgU2VyaWFsaXplclByb3A8VmFsdWUsIEV4dHJhcz5cbiAgPjtcblxuZXhwb3J0IHR5cGUgQ0FTVG9rZW4gPSBCdWZmZXI7XG5cbmV4cG9ydCBpbnRlcmZhY2UgR2V0UmVzdWx0PFZhbHVlID0gTWF5YmVCdWZmZXIsIEV4dHJhcyA9IE1heWJlQnVmZmVyPiB7XG4gIHZhbHVlOiBWYWx1ZTtcbiAgZXh0cmFzOiBFeHRyYXM7XG4gIGNhczogQ0FTVG9rZW4gfCB1bmRlZmluZWQ7XG59XG5cbmV4cG9ydCB0eXBlIEdldE11bHRpUmVzdWx0PFxuICBLZXlzIGV4dGVuZHMgc3RyaW5nID0gc3RyaW5nLFxuICBWYWx1ZSA9IE1heWJlQnVmZmVyLFxuICBFeHRyYXMgPSBNYXliZUJ1ZmZlclxuPiA9IHtcbiAgW0sgaW4gS2V5c10/OiBHZXRSZXN1bHQ8VmFsdWUsIEV4dHJhcz47XG59O1xuXG5jbGFzcyBDbGllbnQ8VmFsdWUgPSBNYXliZUJ1ZmZlciwgRXh0cmFzID0gTWF5YmVCdWZmZXI+IHtcbiAgc2VydmVyczogU2VydmVyW107XG4gIHNlcTogbnVtYmVyO1xuICBvcHRpb25zOiBCYXNlQ2xpZW50T3B0aW9ucyAmIFBhcnRpYWw8U2VyaWFsaXplclByb3A8VmFsdWUsIEV4dHJhcz4+O1xuICBzZXJpYWxpemVyOiBTZXJpYWxpemVyPFZhbHVlLCBFeHRyYXM+O1xuICBzZXJ2ZXJNYXA6IHsgW2hvc3Rwb3J0OiBzdHJpbmddOiBTZXJ2ZXIgfTtcbiAgc2VydmVyS2V5czogc3RyaW5nW107XG5cbiAgLy8gQ2xpZW50IGluaXRpYWxpemVyIHRha2VzIGEgbGlzdCBvZiBgU2VydmVyYHMgYW5kIGFuIGBvcHRpb25zYCBkaWN0aW9uYXJ5LlxuICAvLyBTZWUgYENsaWVudC5jcmVhdGVgIGZvciBkZXRhaWxzLlxuICBjb25zdHJ1Y3RvcihzZXJ2ZXJzOiBTZXJ2ZXJbXSwgb3B0aW9uczogR2l2ZW5DbGllbnRPcHRpb25zPFZhbHVlLCBFeHRyYXM+KSB7XG4gICAgdGhpcy5zZXJ2ZXJzID0gc2VydmVycztcbiAgICB0aGlzLnNlcSA9IDA7XG4gICAgdGhpcy5vcHRpb25zID0gbWVyZ2Uob3B0aW9ucyB8fCB7fSwge1xuICAgICAgcmV0cmllczogMixcbiAgICAgIHJldHJ5X2RlbGF5OiAwLjIsXG4gICAgICBleHBpcmVzOiAwLFxuICAgICAgbG9nZ2VyOiBjb25zb2xlLFxuICAgICAga2V5VG9TZXJ2ZXJIYXNoRnVuY3Rpb246IGRlZmF1bHRLZXlUb1NlcnZlckhhc2hGdW5jdGlvbixcbiAgICB9KTtcblxuICAgIHRoaXMuc2VyaWFsaXplciA9IHRoaXMub3B0aW9ucy5zZXJpYWxpemVyIHx8IChub29wU2VyaWFsaXplciBhcyBhbnkpO1xuXG4gICAgLy8gU3RvcmUgYSBtYXBwaW5nIGZyb20gaG9zdHBvcnQgLT4gc2VydmVyIHNvIHdlIGNhbiBxdWlja2x5IGdldCBhIHNlcnZlciBvYmplY3QgZnJvbSB0aGUgc2VydmVyS2V5IHJldHVybmVkIGJ5IHRoZSBoYXNoaW5nIGZ1bmN0aW9uXG4gICAgY29uc3Qgc2VydmVyTWFwOiB7IFtob3N0cG9ydDogc3RyaW5nXTogU2VydmVyIH0gPSB7fTtcbiAgICB0aGlzLnNlcnZlcnMuZm9yRWFjaChmdW5jdGlvbiAoc2VydmVyKSB7XG4gICAgICBzZXJ2ZXJNYXBbc2VydmVyLmhvc3Rwb3J0U3RyaW5nKCldID0gc2VydmVyO1xuICAgIH0pO1xuICAgIHRoaXMuc2VydmVyTWFwID0gc2VydmVyTWFwO1xuXG4gICAgLy8gc3RvcmUgYSBsaXN0IG9mIGFsbCBvdXIgc2VydmVyS2V5cyBzbyB3ZSBkb24ndCBuZWVkIHRvIGNvbnN0YW50bHkgcmVhbGxvY2F0ZSB0aGlzIGFycmF5XG4gICAgdGhpcy5zZXJ2ZXJLZXlzID0gT2JqZWN0LmtleXModGhpcy5zZXJ2ZXJNYXApO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBuZXcgY2xpZW50IGdpdmVuIGFuIG9wdGlvbmFsIGNvbmZpZyBzdHJpbmcgYW5kIG9wdGlvbmFsIGhhc2ggb2ZcbiAgICogb3B0aW9ucy4gVGhlIGNvbmZpZyBzdHJpbmcgc2hvdWxkIGJlIG9mIHRoZSBmb3JtOlxuICAgKlxuICAgKiAgICAgXCJbdXNlcjpwYXNzQF1zZXJ2ZXIxWzoxMTIxMV0sW3VzZXI6cGFzc0Bdc2VydmVyMls6MTEyMTFdLC4uLlwiXG4gICAqXG4gICAqIElmIHRoZSBhcmd1bWVudCBpcyBub3QgZ2l2ZW4sIGZhbGxiYWNrIG9uIHRoZSBgTUVNQ0FDSElFUl9TRVJWRVJTYCBlbnZpcm9ubWVudFxuICAgKiB2YXJpYWJsZSwgYE1FTUNBQ0hFX1NFUlZFUlNgIGVudmlyb25tZW50IHZhcmlhYmxlIG9yIGBcImxvY2FsaG9zdDoxMTIxMVwiYC5cbiAgICpcbiAgICogVGhlIG9wdGlvbnMgaGFzaCBtYXkgY29udGFpbiB0aGUgb3B0aW9uczpcbiAgICpcbiAgICogKiBgcmV0cmllc2AgLSB0aGUgbnVtYmVyIG9mIHRpbWVzIHRvIHJldHJ5IGFuIG9wZXJhdGlvbiBpbiBsaWV1IG9mIGZhaWx1cmVzXG4gICAqIChkZWZhdWx0IDIpXG4gICAqICogYGV4cGlyZXNgIC0gdGhlIGRlZmF1bHQgZXhwaXJhdGlvbiBpbiBzZWNvbmRzIHRvIHVzZSAoZGVmYXVsdCAwIC0gbmV2ZXJcbiAgICogZXhwaXJlKS4gSWYgYGV4cGlyZXNgIGlzIGdyZWF0ZXIgdGhhbiAzMCBkYXlzICg2MCB4IDYwIHggMjQgeCAzMCksIGl0IGlzXG4gICAqIHRyZWF0ZWQgYXMgYSBVTklYIHRpbWUgKG51bWJlciBvZiBzZWNvbmRzIHNpbmNlIEphbnVhcnkgMSwgMTk3MCkuXG4gICAqICogYGxvZ2dlcmAgLSBhIGxvZ2dlciBvYmplY3QgdGhhdCByZXNwb25kcyB0byBgbG9nKHN0cmluZylgIG1ldGhvZCBjYWxscy5cbiAgICpcbiAgICogICB+fn5+XG4gICAqICAgICBsb2cobXNnMVssIG1zZzJbLCBtc2czWy4uLl1dXSlcbiAgICogICB+fn5+XG4gICAqXG4gICAqICAgRGVmYXVsdHMgdG8gYGNvbnNvbGVgLlxuICAgKiAqIGBzZXJpYWxpemVyYCAtIHRoZSBvYmplY3Qgd2hpY2ggd2lsbCAoZGUpc2VyaWFsaXplIHRoZSBkYXRhLiBJdCBuZWVkc1xuICAgKiAgIHR3byBwdWJsaWMgbWV0aG9kczogc2VyaWFsaXplIGFuZCBkZXNlcmlhbGl6ZS4gSXQgZGVmYXVsdHMgdG8gdGhlXG4gICAqICAgbm9vcFNlcmlhbGl6ZXI6XG4gICAqXG4gICAqICAgfn5+flxuICAgKiAgIGNvbnN0IG5vb3BTZXJpYWxpemVyID0ge1xuICAgKiAgICAgc2VyaWFsaXplOiBmdW5jdGlvbiAob3Bjb2RlLCB2YWx1ZSwgZXh0cmFzKSB7XG4gICAqICAgICAgIHJldHVybiB7IHZhbHVlOiB2YWx1ZSwgZXh0cmFzOiBleHRyYXMgfTtcbiAgICogICAgIH0sXG4gICAqICAgICBkZXNlcmlhbGl6ZTogZnVuY3Rpb24gKG9wY29kZSwgdmFsdWUsIGV4dHJhcykge1xuICAgKiAgICAgICByZXR1cm4geyB2YWx1ZTogdmFsdWUsIGV4dHJhczogZXh0cmFzIH07XG4gICAqICAgICB9XG4gICAqICAgfTtcbiAgICogICB+fn5+XG4gICAqXG4gICAqIE9yIG9wdGlvbnMgZm9yIHRoZSBzZXJ2ZXJzIGluY2x1ZGluZzpcbiAgICogKiBgdXNlcm5hbWVgIGFuZCBgcGFzc3dvcmRgIGZvciBmYWxsYmFjayBTQVNMIGF1dGhlbnRpY2F0aW9uIGNyZWRlbnRpYWxzLlxuICAgKiAqIGB0aW1lb3V0YCBpbiBzZWNvbmRzIHRvIGRldGVybWluZSBmYWlsdXJlIGZvciBvcGVyYXRpb25zLiBEZWZhdWx0IGlzIDAuNVxuICAgKiAgICAgICAgICAgICBzZWNvbmRzLlxuICAgKiAqICdjb25udGltZW91dCcgaW4gc2Vjb25kcyB0byBjb25uZWN0aW9uIGZhaWx1cmUuIERlZmF1bHQgaXMgdHdpY2UgdGhlIHZhbHVlXG4gICAqICAgICAgICAgICAgICAgICBvZiBgdGltZW91dGAuXG4gICAqICogYGtlZXBBbGl2ZWAgd2hldGhlciB0byBlbmFibGUga2VlcC1hbGl2ZSBmdW5jdGlvbmFsaXR5LiBEZWZhdWx0cyB0byBmYWxzZS5cbiAgICogKiBga2VlcEFsaXZlRGVsYXlgIGluIHNlY29uZHMgdG8gdGhlIGluaXRpYWwgZGVsYXkgYmVmb3JlIHRoZSBmaXJzdCBrZWVwYWxpdmVcbiAgICogICAgICAgICAgICAgICAgICAgIHByb2JlIGlzIHNlbnQgb24gYW4gaWRsZSBzb2NrZXQuIERlZmF1bHRzIGlzIDMwIHNlY29uZHMuXG4gICAqICogYGtleVRvU2VydmVySGFzaEZ1bmN0aW9uYCBhIGZ1bmN0aW9uIHRvIG1hcCBrZXlzIHRvIHNlcnZlcnMsIHdpdGggdGhlIHNpZ25hdHVyZVxuICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoc2VydmVyS2V5czogc3RyaW5nW10sIGtleTogc3RyaW5nKTogc3RyaW5nXG4gICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgIE5PVEU6IGlmIHlvdSBuZWVkIHRvIGRvIHNvbWUgZXhwZW5zaXZlIGluaXRpYWxpemF0aW9uLCAqcGxlYXNlKiBkbyBpdCBsYXppbHkgdGhlIGZpcnN0IHRpbWUgeW91IHRoaXMgZnVuY3Rpb24gaXMgY2FsbGVkIHdpdGggYW4gYXJyYXkgb2Ygc2VydmVyS2V5cywgbm90IG9uIGV2ZXJ5IGNhbGxcbiAgICovXG4gIHN0YXRpYyBjcmVhdGU8VmFsdWUsIEV4dHJhcz4oXG4gICAgc2VydmVyc1N0cjogc3RyaW5nIHwgdW5kZWZpbmVkLFxuICAgIG9wdGlvbnM6IElmQnVmZmVyPFxuICAgICAgVmFsdWUsXG4gICAgICBFeHRyYXMsXG4gICAgICB1bmRlZmluZWQgfCAoUGFydGlhbDxTZXJ2ZXJPcHRpb25zPiAmIEdpdmVuQ2xpZW50T3B0aW9uczxWYWx1ZSwgRXh0cmFzPiksXG4gICAgICBQYXJ0aWFsPFNlcnZlck9wdGlvbnM+ICYgR2l2ZW5DbGllbnRPcHRpb25zPFZhbHVlLCBFeHRyYXM+XG4gICAgPlxuICApOiBDbGllbnQ8VmFsdWUsIEV4dHJhcz4ge1xuICAgIHNlcnZlcnNTdHIgPVxuICAgICAgc2VydmVyc1N0ciB8fFxuICAgICAgcHJvY2Vzcy5lbnYuTUVNQ0FDSElFUl9TRVJWRVJTIHx8XG4gICAgICBwcm9jZXNzLmVudi5NRU1DQUNIRV9TRVJWRVJTIHx8XG4gICAgICBcImxvY2FsaG9zdDoxMTIxMVwiO1xuICAgIGNvbnN0IHNlcnZlclVyaXMgPSBzZXJ2ZXJzU3RyLnNwbGl0KFwiLFwiKTtcbiAgICBjb25zdCBzZXJ2ZXJzID0gc2VydmVyVXJpcy5tYXAoZnVuY3Rpb24gKHVyaSkge1xuICAgICAgY29uc3QgdXJpUGFydHMgPSB1cmkuc3BsaXQoXCJAXCIpO1xuICAgICAgY29uc3QgaG9zdFBvcnQgPSB1cmlQYXJ0c1t1cmlQYXJ0cy5sZW5ndGggLSAxXS5zcGxpdChcIjpcIik7XG4gICAgICBjb25zdCB1c2VyUGFzcyA9ICh1cmlQYXJ0c1t1cmlQYXJ0cy5sZW5ndGggLSAyXSB8fCBcIlwiKS5zcGxpdChcIjpcIik7XG4gICAgICByZXR1cm4gbmV3IFNlcnZlcihcbiAgICAgICAgaG9zdFBvcnRbMF0sXG4gICAgICAgIHBhcnNlSW50KGhvc3RQb3J0WzFdIHx8IFwiMTEyMTFcIiwgMTApLFxuICAgICAgICB1c2VyUGFzc1swXSxcbiAgICAgICAgdXNlclBhc3NbMV0sXG4gICAgICAgIG9wdGlvbnNcbiAgICAgICk7XG4gICAgfSk7XG4gICAgcmV0dXJuIG5ldyBDbGllbnQoc2VydmVycywgb3B0aW9ucyBhcyBhbnkpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdpdmVuIGEgc2VydmVyS2V5IGZyb21sb29rdXBLZXlUb1NlcnZlcktleSwgcmV0dXJuIHRoZSBjb3JyZXNwb25kaW5nIFNlcnZlciBpbnN0YW5jZVxuICAgKlxuICAgKiBAcGFyYW0gIHtzdHJpbmd9IHNlcnZlcktleVxuICAgKiBAcmV0dXJucyB7U2VydmVyfVxuICAgKi9cbiAgc2VydmVyS2V5VG9TZXJ2ZXIoc2VydmVyS2V5OiBzdHJpbmcpOiBTZXJ2ZXIge1xuICAgIHJldHVybiB0aGlzLnNlcnZlck1hcFtzZXJ2ZXJLZXldO1xuICB9XG5cbiAgLyoqXG4gICAqIEdpdmVuIGEga2V5IHRvIGxvb2sgdXAgaW4gbWVtY2FjaGUsIHJldHVybiBhIHNlcnZlcktleSAoYmFzZWQgb24gc29tZVxuICAgKiBoYXNoaW5nIGZ1bmN0aW9uKSB3aGljaCBjYW4gYmUgdXNlZCB0byBpbmRleCB0aGlzLnNlcnZlck1hcFxuICAgKi9cbiAgbG9va3VwS2V5VG9TZXJ2ZXJLZXkoa2V5OiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLm9wdGlvbnMua2V5VG9TZXJ2ZXJIYXNoRnVuY3Rpb24odGhpcy5zZXJ2ZXJLZXlzLCBrZXkpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHJpZXZlcyB0aGUgdmFsdWUgYXQgdGhlIGdpdmVuIGtleSBpbiBtZW1jYWNoZS5cbiAgICovXG4gIGFzeW5jIGdldChrZXk6IHN0cmluZyk6IFByb21pc2U8R2V0UmVzdWx0PFZhbHVlLCBFeHRyYXM+IHwgbnVsbD4ge1xuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihjb25zdGFudHMuT1BfR0VULCBrZXksIFwiXCIsIFwiXCIsIHRoaXMuc2VxKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgY29uc3QgZGVzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLmRlc2VyaWFsaXplKFxuICAgICAgICAgIHJlc3BvbnNlLmhlYWRlci5vcGNvZGUsXG4gICAgICAgICAgcmVzcG9uc2UudmFsLFxuICAgICAgICAgIHJlc3BvbnNlLmV4dHJhc1xuICAgICAgICApO1xuICAgICAgICByZXR1cm4geyAuLi5kZXNlcmlhbGl6ZWQsIGNhczogcmVzcG9uc2UuaGVhZGVyLmNhcyB9O1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfTk9UX0ZPVU5EOlxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJHRVRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqIEJ1aWxkIGEgcGlwZWxpbmVkIGdldCBtdWx0aSByZXF1ZXN0IGJ5IHNlbmRpbmcgb25lIEdFVEtRIGZvciBlYWNoIGtleSAocXVpZXQsIG1lYW5pbmcgaXQgd29uJ3QgcmVzcG9uZCBpZiB0aGUgdmFsdWUgaXMgbWlzc2luZykgZm9sbG93ZWQgYnkgYSBuby1vcCB0byBmb3JjZSBhIHJlc3BvbnNlIChhbmQgdG8gZ2l2ZSB1cyBhIHNlbnRpbmVsIHJlc3BvbnNlIHRoYXQgdGhlIHBpcGVsaW5lIGlzIGRvbmUpXG4gICAqXG4gICAqIGNmIGh0dHBzOi8vZ2l0aHViLmNvbS9jb3VjaGJhc2UvbWVtY2FjaGVkL2Jsb2IvbWFzdGVyL2RvY3MvQmluYXJ5UHJvdG9jb2wubWQjMHgwZC1nZXRrcS1nZXQtd2l0aC1rZXktcXVpZXRseVxuICAgKi9cbiAgX2J1aWxkR2V0TXVsdGlSZXF1ZXN0KGtleXM6IHN0cmluZ1tdKTogQnVmZmVyIHtcbiAgICAvLyBzdGFydCBhdCAyNCBmb3IgdGhlIG5vLW9wIGNvbW1hbmQgYXQgdGhlIGVuZFxuICAgIGxldCByZXF1ZXN0U2l6ZSA9IDI0O1xuICAgIGZvciAoY29uc3Qga2V5SWR4IGluIGtleXMpIHtcbiAgICAgIHJlcXVlc3RTaXplICs9IEJ1ZmZlci5ieXRlTGVuZ3RoKGtleXNba2V5SWR4XSwgXCJ1dGY4XCIpICsgMjQ7XG4gICAgfVxuXG4gICAgY29uc3QgcmVxdWVzdCA9IEJ1ZmZlci5hbGxvYyhyZXF1ZXN0U2l6ZSk7XG5cbiAgICBsZXQgYnl0ZXNXcml0dGVuID0gMDtcbiAgICBmb3IgKGNvbnN0IGtleUlkeCBpbiBrZXlzKSB7XG4gICAgICBjb25zdCBrZXkgPSBrZXlzW2tleUlkeF07XG4gICAgICBieXRlc1dyaXR0ZW4gKz0gY29weUludG9SZXF1ZXN0QnVmZmVyKFxuICAgICAgICBjb25zdGFudHMuT1BfR0VUS1EsXG4gICAgICAgIGtleSxcbiAgICAgICAgXCJcIixcbiAgICAgICAgXCJcIixcbiAgICAgICAgdGhpcy5zZXEsXG4gICAgICAgIHJlcXVlc3QsXG4gICAgICAgIGJ5dGVzV3JpdHRlblxuICAgICAgKTtcbiAgICB9XG5cbiAgICBieXRlc1dyaXR0ZW4gKz0gY29weUludG9SZXF1ZXN0QnVmZmVyKFxuICAgICAgY29uc3RhbnRzLk9QX05PX09QLFxuICAgICAgXCJcIixcbiAgICAgIFwiXCIsXG4gICAgICBcIlwiLFxuICAgICAgdGhpcy5zZXEsXG4gICAgICByZXF1ZXN0LFxuICAgICAgYnl0ZXNXcml0dGVuXG4gICAgKTtcblxuICAgIHJldHVybiByZXF1ZXN0O1xuICB9XG5cbiAgLyoqIEV4ZWN1dGluZyBhIHBpcGVsaW5lZCAobXVsdGkpIGdldCBhZ2FpbnN0IGEgc2luZ2xlIHNlcnZlci4gVGhpcyBpcyBhIHByaXZhdGUgaW1wbGVtZW50YXRpb24gZGV0YWlsIG9mIGdldE11bHRpLiAqL1xuICBhc3luYyBfZ2V0TXVsdGlUb1NlcnZlcjxLZXlzIGV4dGVuZHMgc3RyaW5nPihcbiAgICBzZXJ2OiBTZXJ2ZXIsXG4gICAga2V5czogS2V5c1tdXG4gICk6IFByb21pc2U8R2V0TXVsdGlSZXN1bHQ8S2V5cywgVmFsdWUsIEV4dHJhcz4+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgY29uc3QgcmVzcG9uc2VNYXA6IEdldE11bHRpUmVzdWx0PHN0cmluZywgVmFsdWUsIEV4dHJhcz4gPSB7fTtcblxuICAgICAgY29uc3QgaGFuZGxlOiBPblJlc3BvbnNlQ2FsbGJhY2sgPSAocmVzcG9uc2UpID0+IHtcbiAgICAgICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICAgICAgLy8gV2hlbiB3ZSBnZXQgdGhlIG5vLW9wIHJlc3BvbnNlLCB3ZSBhcmUgZG9uZSB3aXRoIHRoaXMgb25lIGdldE11bHRpIGluIHRoZSBwZXItYmFja2VuZCBmYW4tb3V0XG4gICAgICAgICAgICBpZiAocmVzcG9uc2UuaGVhZGVyLm9wY29kZSA9PT0gY29uc3RhbnRzLk9QX05PX09QKSB7XG4gICAgICAgICAgICAgIC8vIFRoaXMgZW5zdXJlcyB0aGUgaGFuZGxlciB3aWxsIGJlIGRlbGV0ZWQgZnJvbSB0aGUgcmVzcG9uc2VDYWxsYmFja3MgbWFwIGluIHNlcnZlci5qc1xuICAgICAgICAgICAgICAvLyBUaGlzIGlzbid0IHRlY2huaWNhbGx5IG5lZWRlZCBoZXJlIGJlY2F1c2UgdGhlIGxvZ2ljIGluIHNlcnZlci5qcyBhbHNvIGNoZWNrcyBpZiB0b3RhbEJvZHlMZW5ndGggPT09IDAsIGJ1dCBvdXIgdW5pdHRlc3RzIGFyZW4ndCBncmVhdCBhYm91dCBzZXR0aW5nIHRoYXQgZmllbGQsIGFuZCBhbHNvIHRoaXMgbWFrZXMgaXQgbW9yZSBleHBsaWNpdFxuICAgICAgICAgICAgICBoYW5kbGUucXVpZXQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgcmVzb2x2ZShyZXNwb25zZU1hcCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBjb25zdCBkZXNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuZGVzZXJpYWxpemUoXG4gICAgICAgICAgICAgICAgcmVzcG9uc2UuaGVhZGVyLm9wY29kZSxcbiAgICAgICAgICAgICAgICByZXNwb25zZS52YWwsXG4gICAgICAgICAgICAgICAgcmVzcG9uc2UuZXh0cmFzXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgIGNvbnN0IGtleSA9IHJlc3BvbnNlLmtleS50b1N0cmluZygpO1xuICAgICAgICAgICAgICByZXNwb25zZU1hcFtrZXldID0geyAuLi5kZXNlcmlhbGl6ZWQsIGNhczogcmVzcG9uc2UuaGVhZGVyLmNhcyB9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHJldHVybiByZWplY3QoXG4gICAgICAgICAgICAgIHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJHRVRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cylcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH07XG4gICAgICAvLyBUaGlzIHByZXZlbnRzIHRoZSBoYW5kbGVyIGZyb20gYmVpbmcgZGVsZXRlZFxuICAgICAgLy8gYWZ0ZXIgdGhlIGZpcnN0IHJlc3BvbnNlLiBMb2dpYyBpbiBzZXJ2ZXIuanMuXG4gICAgICBoYW5kbGUucXVpZXQgPSB0cnVlO1xuXG4gICAgICBjb25zdCByZXF1ZXN0ID0gdGhpcy5fYnVpbGRHZXRNdWx0aVJlcXVlc3Qoa2V5cyk7XG4gICAgICBzZXJ2Lm9uUmVzcG9uc2UodGhpcy5zZXEsIGhhbmRsZSk7XG4gICAgICBzZXJ2Lm9uRXJyb3IodGhpcy5zZXEsIHJlamVjdCk7XG4gICAgICB0aGlzLmluY3JTZXEoKTtcbiAgICAgIHNlcnYud3JpdGUocmVxdWVzdCk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldnMgdGhlIHZhbHVlIGF0IHRoZSBnaXZlbiBrZXlzIGluIG1lbWNhY2hlZC4gUmV0dXJucyBhIG1hcCBmcm9tIHRoZVxuICAgKiByZXF1ZXN0ZWQga2V5cyB0byByZXN1bHRzLCBvciBudWxsIGlmIHRoZSBrZXkgd2FzIG5vdCBmb3VuZC5cbiAgICovXG4gIGFzeW5jIGdldE11bHRpPEtleXMgZXh0ZW5kcyBzdHJpbmc+KFxuICAgIGtleXM6IEtleXNbXVxuICApOiBQcm9taXNlPEdldE11bHRpUmVzdWx0PEtleXMsIFZhbHVlLCBFeHRyYXM+PiB7XG4gICAgY29uc3Qgc2VydmVyS2V5dG9Mb29rdXBLZXlzOiB7XG4gICAgICBbc2VydmVyS2V5OiBzdHJpbmddOiBzdHJpbmdbXTtcbiAgICB9ID0ge307XG4gICAga2V5cy5mb3JFYWNoKChsb29rdXBLZXkpID0+IHtcbiAgICAgIGNvbnN0IHNlcnZlcktleSA9IHRoaXMubG9va3VwS2V5VG9TZXJ2ZXJLZXkobG9va3VwS2V5KTtcbiAgICAgIGlmICghc2VydmVyS2V5dG9Mb29rdXBLZXlzW3NlcnZlcktleV0pIHtcbiAgICAgICAgc2VydmVyS2V5dG9Mb29rdXBLZXlzW3NlcnZlcktleV0gPSBbXTtcbiAgICAgIH1cbiAgICAgIHNlcnZlcktleXRvTG9va3VwS2V5c1tzZXJ2ZXJLZXldLnB1c2gobG9va3VwS2V5KTtcbiAgICB9KTtcblxuICAgIGNvbnN0IHVzZWRTZXJ2ZXJLZXlzID0gT2JqZWN0LmtleXMoc2VydmVyS2V5dG9Mb29rdXBLZXlzKTtcbiAgICBjb25zdCByZXN1bHRzID0gYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICB1c2VkU2VydmVyS2V5cy5tYXAoKHNlcnZlcktleSkgPT4ge1xuICAgICAgICBjb25zdCBzZXJ2ZXIgPSB0aGlzLnNlcnZlcktleVRvU2VydmVyKHNlcnZlcktleSk7XG4gICAgICAgIHJldHVybiB0aGlzLl9nZXRNdWx0aVRvU2VydmVyKHNlcnZlciwgc2VydmVyS2V5dG9Mb29rdXBLZXlzW3NlcnZlcktleV0pO1xuICAgICAgfSlcbiAgICApO1xuXG4gICAgcmV0dXJuIE9iamVjdC5hc3NpZ24oe30sIC4uLnJlc3VsdHMpO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgYGtleWAgdG8gYHZhbHVlYC5cbiAgICovXG4gIGFzeW5jIHNldChcbiAgICBrZXk6IHN0cmluZyxcbiAgICB2YWx1ZTogVmFsdWUsXG4gICAgb3B0aW9ucz86IHsgZXhwaXJlcz86IG51bWJlcjsgY2FzPzogQ0FTVG9rZW4gfVxuICApOiBQcm9taXNlPGJvb2xlYW4gfCBudWxsPiB7XG4gICAgY29uc3QgZXhwaXJlcyA9IG9wdGlvbnM/LmV4cGlyZXM7XG4gICAgY29uc3QgY2FzID0gb3B0aW9ucz8uY2FzO1xuXG4gICAgLy8gVE9ETzogc3VwcG9ydCBmbGFnc1xuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IGV4cGlyYXRpb24gPSBtYWtlRXhwaXJhdGlvbihleHBpcmVzIHx8IHRoaXMub3B0aW9ucy5leHBpcmVzKTtcbiAgICBjb25zdCBleHRyYXMgPSBCdWZmZXIuY29uY2F0KFtCdWZmZXIuZnJvbShcIjAwMDAwMDAwXCIsIFwiaGV4XCIpLCBleHBpcmF0aW9uXSk7XG4gICAgY29uc3Qgc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5zZXJpYWxpemUoXG4gICAgICBjb25zdGFudHMuT1BfU0VULFxuICAgICAgdmFsdWUsXG4gICAgICBleHRyYXNcbiAgICApO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBVdGlscy5lbmNvZGVSZXF1ZXN0KHtcbiAgICAgIGhlYWRlcjoge1xuICAgICAgICBvcGNvZGU6IGNvbnN0YW50cy5PUF9TRVQsXG4gICAgICAgIG9wYXF1ZTogdGhpcy5zZXEsXG4gICAgICAgIGNhcyxcbiAgICAgIH0sXG4gICAgICBrZXksXG4gICAgICB2YWx1ZTogc2VyaWFsaXplZC52YWx1ZSxcbiAgICAgIGV4dHJhczogc2VyaWFsaXplZC5leHRyYXMsXG4gICAgfSk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfRVhJU1RTOlxuICAgICAgICBpZiAoY2FzKSB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJTRVRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgICAgIH1cbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJTRVRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEFERFxuICAgKlxuICAgKiBBZGRzIHRoZSBnaXZlbiBfa2V5XyBhbmQgX3ZhbHVlXyB0byBtZW1jYWNoZS4gVGhlIG9wZXJhdGlvbiBvbmx5IHN1Y2NlZWRzXG4gICAqIGlmIHRoZSBrZXkgaXMgbm90IGFscmVhZHkgc2V0LlxuICAgKlxuICAgKiBUaGUgb3B0aW9ucyBkaWN0aW9uYXJ5IHRha2VzOlxuICAgKiAqIF9leHBpcmVzXzogb3ZlcnJpZGVzIHRoZSBkZWZhdWx0IGV4cGlyYXRpb24gKHNlZSBgQ2xpZW50LmNyZWF0ZWApIGZvciB0aGlzXG4gICAqICAgICAgICAgICAgICBwYXJ0aWN1bGFyIGtleS12YWx1ZSBwYWlyLlxuICAgKi9cbiAgYXN5bmMgYWRkKFxuICAgIGtleTogc3RyaW5nLFxuICAgIHZhbHVlOiBWYWx1ZSxcbiAgICBvcHRpb25zPzogeyBleHBpcmVzPzogbnVtYmVyIH1cbiAgKTogUHJvbWlzZTxib29sZWFuIHwgbnVsbD4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgZmxhZ3MsIHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IGV4cGlyYXRpb24gPSBtYWtlRXhwaXJhdGlvbihvcHRpb25zPy5leHBpcmVzIHx8IHRoaXMub3B0aW9ucy5leHBpcmVzKTtcbiAgICBjb25zdCBleHRyYXMgPSBCdWZmZXIuY29uY2F0KFtCdWZmZXIuZnJvbShcIjAwMDAwMDAwXCIsIFwiaGV4XCIpLCBleHBpcmF0aW9uXSk7XG5cbiAgICBjb25zdCBvcGNvZGUgPSBjb25zdGFudHMuT1BfQUREO1xuICAgIGNvbnN0IHNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuc2VyaWFsaXplKG9wY29kZSwgdmFsdWUsIGV4dHJhcyk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKFxuICAgICAgb3Bjb2RlLFxuICAgICAga2V5LFxuICAgICAgc2VyaWFsaXplZC5leHRyYXMsXG4gICAgICBzZXJpYWxpemVkLnZhbHVlLFxuICAgICAgdGhpcy5zZXFcbiAgICApO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuS0VZX0VYSVNUUzpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJBRERcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlcGxhY2VzIHRoZSBnaXZlbiBfa2V5XyBhbmQgX3ZhbHVlXyB0byBtZW1jYWNoZS4gVGhlIG9wZXJhdGlvbiBvbmx5IHN1Y2NlZWRzXG4gICAqIGlmIHRoZSBrZXkgaXMgYWxyZWFkeSBwcmVzZW50LlxuICAgKi9cbiAgYXN5bmMgcmVwbGFjZShcbiAgICBrZXk6IHN0cmluZyxcbiAgICB2YWx1ZTogVmFsdWUsXG4gICAgb3B0aW9ucz86IHsgZXhwaXJlcz86IG51bWJlciB9XG4gICk6IFByb21pc2U8Ym9vbGVhbiB8IG51bGw+IHtcbiAgICAvLyBUT0RPOiBzdXBwb3J0IGZsYWdzLCBzdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBleHBpcmF0aW9uID0gbWFrZUV4cGlyYXRpb24ob3B0aW9ucz8uZXhwaXJlcyB8fCB0aGlzLm9wdGlvbnMuZXhwaXJlcyk7XG4gICAgY29uc3QgZXh0cmFzID0gQnVmZmVyLmNvbmNhdChbQnVmZmVyLmZyb20oXCIwMDAwMDAwMFwiLCBcImhleFwiKSwgZXhwaXJhdGlvbl0pO1xuXG4gICAgY29uc3Qgb3Bjb2RlOiBjb25zdGFudHMuT1AgPSBjb25zdGFudHMuT1BfUkVQTEFDRTtcbiAgICBjb25zdCBzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLnNlcmlhbGl6ZShvcGNvZGUsIHZhbHVlLCBleHRyYXMpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgIG9wY29kZSxcbiAgICAgIGtleSxcbiAgICAgIHNlcmlhbGl6ZWQuZXh0cmFzLFxuICAgICAgc2VyaWFsaXplZC52YWx1ZSxcbiAgICAgIHRoaXMuc2VxXG4gICAgKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJSRVBMQUNFXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBEZWxldGVzIHRoZSBnaXZlbiBfa2V5XyBmcm9tIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHNcbiAgICogaWYgdGhlIGtleSBpcyBhbHJlYWR5IHByZXNlbnQuXG4gICAqL1xuICBhc3luYyBkZWxldGUoa2V5OiBzdHJpbmcpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAvLyBUT0RPOiBTdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoNCwga2V5LCBcIlwiLCBcIlwiLCB0aGlzLnNlcSk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG5cbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJERUxFVEVcIiwgcmVzcG9uc2U/LmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBJbmNyZW1lbnRzIHRoZSBnaXZlbiBfa2V5XyBpbiBtZW1jYWNoZS5cbiAgICovXG4gIGFzeW5jIGluY3JlbWVudChcbiAgICBrZXk6IHN0cmluZyxcbiAgICBhbW91bnQ6IG51bWJlcixcbiAgICBvcHRpb25zPzogeyBpbml0aWFsPzogbnVtYmVyOyBleHBpcmVzPzogbnVtYmVyIH1cbiAgKTogUHJvbWlzZTx7IHZhbHVlOiBudW1iZXIgfCBudWxsOyBzdWNjZXNzOiBib29sZWFuIHwgbnVsbCB9PiB7XG4gICAgLy8gVE9ETzogc3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgaW5pdGlhbCA9IG9wdGlvbnM/LmluaXRpYWwgfHwgMDtcbiAgICBjb25zdCBleHBpcmVzID0gb3B0aW9ucz8uZXhwaXJlcyB8fCB0aGlzLm9wdGlvbnMuZXhwaXJlcztcbiAgICBjb25zdCBleHRyYXMgPSBtYWtlQW1vdW50SW5pdGlhbEFuZEV4cGlyYXRpb24oYW1vdW50LCBpbml0aWFsLCBleHBpcmVzKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICBjb25zdGFudHMuT1BfSU5DUkVNRU5ULFxuICAgICAga2V5LFxuICAgICAgZXh0cmFzLFxuICAgICAgXCJcIixcbiAgICAgIHRoaXMuc2VxXG4gICAgKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgY29uc3QgYnVmSW50ID1cbiAgICAgICAgICAocmVzcG9uc2UudmFsLnJlYWRVSW50MzJCRSgwKSA8PCA4KSArIHJlc3BvbnNlLnZhbC5yZWFkVUludDMyQkUoNCk7XG4gICAgICAgIHJldHVybiB7IHZhbHVlOiBidWZJbnQsIHN1Y2Nlc3M6IHRydWUgfTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJJTkNSRU1FTlRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIERlY3JlbWVudHMgdGhlIGdpdmVuIGBrZXlgIGluIG1lbWNhY2hlLlxuICAgKi9cbiAgYXN5bmMgZGVjcmVtZW50KFxuICAgIGtleTogc3RyaW5nLFxuICAgIGFtb3VudDogbnVtYmVyLFxuICAgIG9wdGlvbnM6IHsgaW5pdGlhbD86IG51bWJlcjsgZXhwaXJlcz86IG51bWJlciB9XG4gICk6IFByb21pc2U8eyB2YWx1ZTogbnVtYmVyIHwgbnVsbDsgc3VjY2VzczogYm9vbGVhbiB8IG51bGwgfT4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IGluaXRpYWwgPSBvcHRpb25zLmluaXRpYWwgfHwgMDtcbiAgICBjb25zdCBleHBpcmVzID0gb3B0aW9ucy5leHBpcmVzIHx8IHRoaXMub3B0aW9ucy5leHBpcmVzO1xuICAgIGNvbnN0IGV4dHJhcyA9IG1ha2VBbW91bnRJbml0aWFsQW5kRXhwaXJhdGlvbihhbW91bnQsIGluaXRpYWwsIGV4cGlyZXMpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgIGNvbnN0YW50cy5PUF9ERUNSRU1FTlQsXG4gICAgICBrZXksXG4gICAgICBleHRyYXMsXG4gICAgICBcIlwiLFxuICAgICAgdGhpcy5zZXFcbiAgICApO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICBjb25zdCBidWZJbnQgPVxuICAgICAgICAgIChyZXNwb25zZS52YWwucmVhZFVJbnQzMkJFKDApIDw8IDgpICsgcmVzcG9uc2UudmFsLnJlYWRVSW50MzJCRSg0KTtcbiAgICAgICAgcmV0dXJuIHsgdmFsdWU6IGJ1ZkludCwgc3VjY2VzczogdHJ1ZSB9O1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIkRFQ1JFTUVOVFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQXBwZW5kIHRoZSBnaXZlbiBfdmFsdWVfIHRvIHRoZSB2YWx1ZSBhc3NvY2lhdGVkIHdpdGggdGhlIGdpdmVuIF9rZXlfIGluXG4gICAqIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHMgaWYgdGhlIGtleSBpcyBhbHJlYWR5IHByZXNlbnQuXG4gICAqL1xuICBhc3luYyBhcHBlbmQoa2V5OiBzdHJpbmcsIHZhbHVlOiBWYWx1ZSk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IG9wY29kZTogY29uc3RhbnRzLk9QID0gY29uc3RhbnRzLk9QX0FQUEVORDtcbiAgICBjb25zdCBzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLnNlcmlhbGl6ZShvcGNvZGUsIHZhbHVlLCBcIlwiKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICBvcGNvZGUsXG4gICAgICBrZXksXG4gICAgICBzZXJpYWxpemVkLmV4dHJhcyxcbiAgICAgIHNlcmlhbGl6ZWQudmFsdWUsXG4gICAgICB0aGlzLnNlcVxuICAgICk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfTk9UX0ZPVU5EOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiQVBQRU5EXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBQcmVwZW5kIHRoZSBnaXZlbiBfdmFsdWVfIHRvIHRoZSB2YWx1ZSBhc3NvY2lhdGVkIHdpdGggdGhlIGdpdmVuIF9rZXlfIGluXG4gICAqIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHMgaWYgdGhlIGtleSBpcyBhbHJlYWR5IHByZXNlbnQuXG4gICAqL1xuICBhc3luYyBwcmVwZW5kKGtleTogc3RyaW5nLCB2YWx1ZTogVmFsdWUpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAvLyBUT0RPOiBzdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBvcGNvZGU6IGNvbnN0YW50cy5PUCA9IGNvbnN0YW50cy5PUF9QUkVQRU5EO1xuICAgIGNvbnN0IHNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuc2VyaWFsaXplKG9wY29kZSwgdmFsdWUsIFwiXCIpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgIG9wY29kZSxcbiAgICAgIGtleSxcbiAgICAgIHNlcmlhbGl6ZWQuZXh0cmFzLFxuICAgICAgc2VyaWFsaXplZC52YWx1ZSxcbiAgICAgIHRoaXMuc2VxXG4gICAgKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJQUkVQRU5EXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBUb3VjaCBzZXRzIGFuIGV4cGlyYXRpb24gdmFsdWUsIGdpdmVuIGJ5IF9leHBpcmVzXywgb24gdGhlIGdpdmVuIF9rZXlfIGluXG4gICAqIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHMgaWYgdGhlIGtleSBpcyBhbHJlYWR5IHByZXNlbnQuXG4gICAqL1xuICBhc3luYyB0b3VjaChrZXk6IHN0cmluZywgZXhwaXJlczogbnVtYmVyKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgLy8gVE9ETzogc3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgZXh0cmFzID0gbWFrZUV4cGlyYXRpb24oZXhwaXJlcyB8fCB0aGlzLm9wdGlvbnMuZXhwaXJlcyk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKDB4MWMsIGtleSwgZXh0cmFzLCBcIlwiLCB0aGlzLnNlcSk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfTk9UX0ZPVU5EOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiVE9VQ0hcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEZMVVNIXG4gICAqXG4gICAqIEZsdXNoZXMgdGhlIGNhY2hlIG9uIGVhY2ggY29ubmVjdGVkIHNlcnZlci4gVGhlIGNhbGxiYWNrIHNpZ25hdHVyZSBpczpcbiAgICpcbiAgICogICAgIGNhbGxiYWNrKGxhc3RFcnIsIHJlc3VsdHMpXG4gICAqXG4gICAqIHdoZXJlIF9sYXN0RXJyXyBpcyB0aGUgbGFzdCBlcnJvciBlbmNvdW50ZXJlZCAob3IgbnVsbCwgaW4gdGhlIGNvbW1vbiBjYXNlXG4gICAqIG9mIG5vIGVycm9ycykuIF9yZXN1bHRzXyBpcyBhIGRpY3Rpb25hcnkgbWFwcGluZyBgXCJob3N0bmFtZTpwb3J0XCJgIHRvIGVpdGhlclxuICAgKiBgdHJ1ZWAgKGlmIHRoZSBvcGVyYXRpb24gd2FzIHN1Y2Nlc3NmdWwpLCBvciBhbiBlcnJvci5cbiAgICogQHBhcmFtIGNhbGxiYWNrXG4gICAqL1xuICBmbHVzaCgpOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIGJvb2xlYW4gfCBFcnJvcj4+O1xuICBmbHVzaChcbiAgICBjYWxsYmFjazogKFxuICAgICAgZXJyOiBFcnJvciB8IG51bGwsXG4gICAgICByZXN1bHRzOiBSZWNvcmQ8c3RyaW5nLCBib29sZWFuIHwgRXJyb3I+XG4gICAgKSA9PiB2b2lkXG4gICk6IHZvaWQ7XG4gIGZsdXNoKFxuICAgIGNhbGxiYWNrPzogKFxuICAgICAgZXJyOiBFcnJvciB8IG51bGwsXG4gICAgICByZXN1bHRzOiBSZWNvcmQ8c3RyaW5nLCBib29sZWFuIHwgRXJyb3I+XG4gICAgKSA9PiB2b2lkXG4gICkge1xuICAgIGlmIChjYWxsYmFjayA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm4gcHJvbWlzaWZ5KChjYWxsYmFjaykgPT4ge1xuICAgICAgICB0aGlzLmZsdXNoKGZ1bmN0aW9uIChlcnIsIHJlc3VsdHMpIHtcbiAgICAgICAgICBjYWxsYmFjayhlcnIsIHJlc3VsdHMpO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH1cbiAgICAvLyBUT0RPOiBzdXBwb3J0IGV4cGlyYXRpb25cbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoMHgwOCwgXCJcIiwgXCJcIiwgXCJcIiwgdGhpcy5zZXEpO1xuICAgIGxldCBjb3VudCA9IHRoaXMuc2VydmVycy5sZW5ndGg7XG4gICAgY29uc3QgcmVzdWx0OiBSZWNvcmQ8c3RyaW5nLCBib29sZWFuIHwgRXJyb3I+ID0ge307XG4gICAgbGV0IGxhc3RFcnI6IEVycm9yIHwgbnVsbCA9IG51bGw7XG5cbiAgICBjb25zdCBoYW5kbGVGbHVzaCA9IGZ1bmN0aW9uIChzZXE6IG51bWJlciwgc2VydjogU2VydmVyKSB7XG4gICAgICBzZXJ2Lm9uUmVzcG9uc2Uoc2VxLCBmdW5jdGlvbiAoLyogcmVzcG9uc2UgKi8pIHtcbiAgICAgICAgY291bnQgLT0gMTtcbiAgICAgICAgcmVzdWx0W3NlcnYuaG9zdHBvcnRTdHJpbmcoKV0gPSB0cnVlO1xuICAgICAgICBpZiAoY2FsbGJhY2sgJiYgY291bnQgPT09IDApIHtcbiAgICAgICAgICBjYWxsYmFjayhsYXN0RXJyLCByZXN1bHQpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHNlcnYub25FcnJvcihzZXEsIGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgICAgY291bnQgLT0gMTtcbiAgICAgICAgbGFzdEVyciA9IGVycjtcbiAgICAgICAgcmVzdWx0W3NlcnYuaG9zdHBvcnRTdHJpbmcoKV0gPSBlcnI7XG4gICAgICAgIGlmIChjYWxsYmFjayAmJiBjb3VudCA9PT0gMCkge1xuICAgICAgICAgIGNhbGxiYWNrKGxhc3RFcnIsIHJlc3VsdCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgc2Vydi53cml0ZShyZXF1ZXN0KTtcbiAgICB9O1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnNlcnZlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGhhbmRsZUZsdXNoKHRoaXMuc2VxLCB0aGlzLnNlcnZlcnNbaV0pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTVEFUU19XSVRIX0tFWVxuICAgKlxuICAgKiBTZW5kcyBhIG1lbWNhY2hlIHN0YXRzIGNvbW1hbmQgd2l0aCBhIGtleSB0byBlYWNoIGNvbm5lY3RlZCBzZXJ2ZXIuIFRoZVxuICAgKiBjYWxsYmFjayBpcyBpbnZva2VkICoqT05DRSBQRVIgU0VSVkVSKiogYW5kIGhhcyB0aGUgc2lnbmF0dXJlOlxuICAgKlxuICAgKiAgICAgY2FsbGJhY2soZXJyLCBzZXJ2ZXIsIHN0YXRzKVxuICAgKlxuICAgKiBfc2VydmVyXyBpcyB0aGUgYFwiaG9zdG5hbWU6cG9ydFwiYCBvZiB0aGUgc2VydmVyLCBhbmQgX3N0YXRzXyBpcyBhIGRpY3Rpb25hcnlcbiAgICogbWFwcGluZyB0aGUgc3RhdCBuYW1lIHRvIHRoZSB2YWx1ZSBvZiB0aGUgc3RhdGlzdGljIGFzIGEgc3RyaW5nLlxuICAgKiBAcGFyYW0ga2V5XG4gICAqIEBwYXJhbSBjYWxsYmFja1xuICAgKi9cbiAgc3RhdHNXaXRoS2V5KFxuICAgIGtleTogc3RyaW5nLFxuICAgIGNhbGxiYWNrPzogKFxuICAgICAgZXJyOiBFcnJvciB8IG51bGwsXG4gICAgICBzZXJ2ZXI6IHN0cmluZyxcbiAgICAgIHN0YXRzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+IHwgbnVsbFxuICAgICkgPT4gdm9pZFxuICApOiB2b2lkIHtcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoMHgxMCwga2V5LCBcIlwiLCBcIlwiLCB0aGlzLnNlcSk7XG5cbiAgICBjb25zdCBoYW5kbGVTdGF0cyA9IChzZXE6IG51bWJlciwgc2VydjogU2VydmVyKSA9PiB7XG4gICAgICBjb25zdCByZXN1bHQ6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcbiAgICAgIGNvbnN0IGhhbmRsZTogT25SZXNwb25zZUNhbGxiYWNrID0gKHJlc3BvbnNlKSA9PiB7XG4gICAgICAgIC8vIGVuZCBvZiBzdGF0IHJlc3BvbnNlc1xuICAgICAgICBpZiAocmVzcG9uc2UuaGVhZGVyLnRvdGFsQm9keUxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgICAgY2FsbGJhY2sobnVsbCwgc2Vydi5ob3N0cG9ydFN0cmluZygpLCByZXN1bHQpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgLy8gcHJvY2VzcyBzaW5nbGUgc3RhdCBsaW5lIHJlc3BvbnNlXG4gICAgICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgICAgIHJlc3VsdFtyZXNwb25zZS5rZXkudG9TdHJpbmcoKV0gPSByZXNwb25zZS52YWwudG9TdHJpbmcoKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICBjb25zdCBlcnJvciA9IHRoaXMuaGFuZGxlUmVzcG9uc2VFcnJvcihcbiAgICAgICAgICAgICAgYFNUQVRTICgke2tleX0pYCxcbiAgICAgICAgICAgICAgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyxcbiAgICAgICAgICAgICAgdW5kZWZpbmVkXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgICAgICAgIGNhbGxiYWNrKGVycm9yLCBzZXJ2Lmhvc3Rwb3J0U3RyaW5nKCksIG51bGwpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9O1xuICAgICAgaGFuZGxlLnF1aWV0ID0gdHJ1ZTtcblxuICAgICAgc2Vydi5vblJlc3BvbnNlKHNlcSwgaGFuZGxlKTtcbiAgICAgIHNlcnYub25FcnJvcihzZXEsIGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgICAgY2FsbGJhY2soZXJyLCBzZXJ2Lmhvc3Rwb3J0U3RyaW5nKCksIG51bGwpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHNlcnYud3JpdGUocmVxdWVzdCk7XG4gICAgfTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5zZXJ2ZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBoYW5kbGVTdGF0cyh0aGlzLnNlcSwgdGhpcy5zZXJ2ZXJzW2ldKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU1RBVFNcbiAgICpcbiAgICogRmV0Y2hlcyBtZW1jYWNoZSBzdGF0cyBmcm9tIGVhY2ggY29ubmVjdGVkIHNlcnZlci4gVGhlIGNhbGxiYWNrIGlzIGludm9rZWRcbiAgICogKipPTkNFIFBFUiBTRVJWRVIqKiBhbmQgaGFzIHRoZSBzaWduYXR1cmU6XG4gICAqXG4gICAqICAgICBjYWxsYmFjayhlcnIsIHNlcnZlciwgc3RhdHMpXG4gICAqXG4gICAqIF9zZXJ2ZXJfIGlzIHRoZSBgXCJob3N0bmFtZTpwb3J0XCJgIG9mIHRoZSBzZXJ2ZXIsIGFuZCBfc3RhdHNfIGlzIGFcbiAgICogZGljdGlvbmFyeSBtYXBwaW5nIHRoZSBzdGF0IG5hbWUgdG8gdGhlIHZhbHVlIG9mIHRoZSBzdGF0aXN0aWMgYXMgYSBzdHJpbmcuXG4gICAqIEBwYXJhbSBjYWxsYmFja1xuICAgKi9cbiAgc3RhdHMoXG4gICAgY2FsbGJhY2s/OiAoXG4gICAgICBlcnI6IEVycm9yIHwgbnVsbCxcbiAgICAgIHNlcnZlcjogc3RyaW5nLFxuICAgICAgc3RhdHM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gfCBudWxsXG4gICAgKSA9PiB2b2lkXG4gICk6IHZvaWQge1xuICAgIHRoaXMuc3RhdHNXaXRoS2V5KFwiXCIsIGNhbGxiYWNrKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSRVNFVF9TVEFUU1xuICAgKlxuICAgKiBSZXNldCB0aGUgc3RhdGlzdGljcyBlYWNoIHNlcnZlciBpcyBrZWVwaW5nIGJhY2sgdG8gemVyby4gVGhpcyBkb2Vzbid0IGNsZWFyXG4gICAqIHN0YXRzIHN1Y2ggYXMgaXRlbSBjb3VudCwgYnV0IHRlbXBvcmFyeSBzdGF0cyBzdWNoIGFzIHRvdGFsIG51bWJlciBvZlxuICAgKiBjb25uZWN0aW9ucyBvdmVyIHRpbWUuXG4gICAqXG4gICAqIFRoZSBjYWxsYmFjayBpcyBpbnZva2VkICoqT05DRSBQRVIgU0VSVkVSKiogYW5kIGhhcyB0aGUgc2lnbmF0dXJlOlxuICAgKlxuICAgKiAgICAgY2FsbGJhY2soZXJyLCBzZXJ2ZXIpXG4gICAqXG4gICAqIF9zZXJ2ZXJfIGlzIHRoZSBgXCJob3N0bmFtZTpwb3J0XCJgIG9mIHRoZSBzZXJ2ZXIuXG4gICAqIEBwYXJhbSBjYWxsYmFja1xuICAgKi9cbiAgcmVzZXRTdGF0cyhcbiAgICBjYWxsYmFjaz86IChcbiAgICAgIGVycjogRXJyb3IgfCBudWxsLFxuICAgICAgc2VydmVyOiBzdHJpbmcsXG4gICAgICBzdGF0czogUmVjb3JkPHN0cmluZywgc3RyaW5nPiB8IG51bGxcbiAgICApID0+IHZvaWRcbiAgKTogdm9pZCB7XG4gICAgdGhpcy5zdGF0c1dpdGhLZXkoXCJyZXNldFwiLCBjYWxsYmFjayk7XG4gIH1cblxuICAvKipcbiAgICogUVVJVFxuICAgKlxuICAgKiBDbG9zZXMgdGhlIGNvbm5lY3Rpb24gdG8gZWFjaCBzZXJ2ZXIsIG5vdGlmeWluZyB0aGVtIG9mIHRoaXMgaW50ZW50aW9uLiBOb3RlXG4gICAqIHRoYXQgcXVpdCBjYW4gcmFjZSBhZ2FpbnN0IGFscmVhZHkgb3V0c3RhbmRpbmcgcmVxdWVzdHMgd2hlbiB0aG9zZSByZXF1ZXN0c1xuICAgKiBmYWlsIGFuZCBhcmUgcmV0cmllZCwgbGVhZGluZyB0byB0aGUgcXVpdCBjb21tYW5kIHdpbm5pbmcgYW5kIGNsb3NpbmcgdGhlXG4gICAqIGNvbm5lY3Rpb24gYmVmb3JlIHRoZSByZXRyaWVzIGNvbXBsZXRlLlxuICAgKi9cbiAgcXVpdCgpIHtcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICAvLyBUT0RPOiBOaWNlciBwZXJoYXBzIHRvIGRvIFFVSVRRICgweDE3KSBidXQgbmVlZCBhIG5ldyBjYWxsYmFjayBmb3Igd2hlblxuICAgIC8vIHdyaXRlIGlzIGRvbmUuXG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKDB4MDcsIFwiXCIsIFwiXCIsIFwiXCIsIHRoaXMuc2VxKTsgLy8gUVVJVFxuICAgIGxldCBzZXJ2O1xuXG4gICAgY29uc3QgaGFuZGxlUXVpdCA9IGZ1bmN0aW9uIChzZXE6IG51bWJlciwgc2VydjogU2VydmVyKSB7XG4gICAgICBzZXJ2Lm9uUmVzcG9uc2Uoc2VxLCBmdW5jdGlvbiAoLyogcmVzcG9uc2UgKi8pIHtcbiAgICAgICAgc2Vydi5jbG9zZSgpO1xuICAgICAgfSk7XG4gICAgICBzZXJ2Lm9uRXJyb3Ioc2VxLCBmdW5jdGlvbiAoLyogZXJyICovKSB7XG4gICAgICAgIHNlcnYuY2xvc2UoKTtcbiAgICAgIH0pO1xuICAgICAgc2Vydi53cml0ZShyZXF1ZXN0KTtcbiAgICB9O1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnNlcnZlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHNlcnYgPSB0aGlzLnNlcnZlcnNbaV07XG4gICAgICBoYW5kbGVRdWl0KHRoaXMuc2VxLCBzZXJ2KTtcbiAgICB9XG4gIH1cblxuICBfdmVyc2lvbihzZXJ2ZXI6IFNlcnZlcik6IFByb21pc2U8eyB2YWx1ZTogVmFsdWUgfCBudWxsIH0+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICAgIGNvbnN0YW50cy5PUF9WRVJTSU9OLFxuICAgICAgICBcIlwiLFxuICAgICAgICBcIlwiLFxuICAgICAgICBcIlwiLFxuICAgICAgICB0aGlzLnNlcVxuICAgICAgKTtcbiAgICAgIHRoaXMucGVyZm9ybU9uU2VydmVyKHNlcnZlciwgcmVxdWVzdCwgdGhpcy5zZXEsIChlcnIsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICByZXR1cm4gcmVqZWN0KGVycik7XG4gICAgICAgIH1cblxuICAgICAgICBzd2l0Y2ggKHJlc3BvbnNlIS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICAgICAgLyogVE9ETzogdGhpcyBpcyBidWdnZWQsIHdlIHNob3VsZCd0IHVzZSB0aGUgZGVzZXJpYWxpemVyIGhlcmUsIHNpbmNlIHZlcnNpb24gYWx3YXlzIHJldHVybnMgYSB2ZXJzaW9uIHN0cmluZy5cbiAgICAgICAgICAgICBUaGUgZGVzZXJpYWxpemVyIHNob3VsZCBvbmx5IGJlIHVzZWQgb24gdXNlciBrZXkgZGF0YS4gKi9cbiAgICAgICAgICAgIGNvbnN0IGRlc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5kZXNlcmlhbGl6ZShcbiAgICAgICAgICAgICAgcmVzcG9uc2UhLmhlYWRlci5vcGNvZGUsXG4gICAgICAgICAgICAgIHJlc3BvbnNlIS52YWwsXG4gICAgICAgICAgICAgIHJlc3BvbnNlIS5leHRyYXNcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICByZXR1cm4gcmVzb2x2ZSh7IHZhbHVlOiBkZXNlcmlhbGl6ZWQudmFsdWUgfSk7XG4gICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHJldHVybiByZWplY3QoXG4gICAgICAgICAgICAgIHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJWRVJTSU9OXCIsIHJlc3BvbnNlIS5oZWFkZXIuc3RhdHVzKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmVxdWVzdCB0aGUgc2VydmVyIHZlcnNpb24gZnJvbSB0aGUgXCJmaXJzdFwiIHNlcnZlciBpbiB0aGUgYmFja2VuZCBwb29sLlxuICAgKiBUaGUgc2VydmVyIHJlc3BvbmRzIHdpdGggYSBwYWNrZXQgY29udGFpbmluZyB0aGUgdmVyc2lvbiBzdHJpbmcgaW4gdGhlIGJvZHkgd2l0aCB0aGUgZm9sbG93aW5nIGZvcm1hdDogXCJ4LnkuelwiXG4gICAqL1xuICB2ZXJzaW9uKCk6IFByb21pc2U8eyB2YWx1ZTogVmFsdWUgfCBudWxsIH0+IHtcbiAgICBjb25zdCBzZXJ2ZXIgPSB0aGlzLnNlcnZlcktleVRvU2VydmVyKHRoaXMuc2VydmVyS2V5c1swXSk7XG4gICAgcmV0dXJuIHRoaXMuX3ZlcnNpb24oc2VydmVyKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXRyaWV2ZXMgdGhlIHNlcnZlciB2ZXJzaW9uIGZyb20gYWxsIHRoZSBzZXJ2ZXJzXG4gICAqIGluIHRoZSBiYWNrZW5kIHBvb2wsIGVycm9ycyBpZiBhbnkgb25lIG9mIHRoZW0gaGFzIGFuXG4gICAqIGVycm9yXG4gICAqL1xuICBhc3luYyB2ZXJzaW9uQWxsKCk6IFByb21pc2U8e1xuICAgIHZhbHVlczogUmVjb3JkPHN0cmluZywgVmFsdWUgfCBudWxsPjtcbiAgfT4ge1xuICAgIGNvbnN0IHZlcnNpb25PYmplY3RzID0gYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICB0aGlzLnNlcnZlcktleXMubWFwKChzZXJ2ZXJLZXkpID0+IHtcbiAgICAgICAgY29uc3Qgc2VydmVyID0gdGhpcy5zZXJ2ZXJLZXlUb1NlcnZlcihzZXJ2ZXJLZXkpO1xuXG4gICAgICAgIHJldHVybiB0aGlzLl92ZXJzaW9uKHNlcnZlcikudGhlbigocmVzcG9uc2UpID0+IHtcbiAgICAgICAgICByZXR1cm4geyBzZXJ2ZXJLZXk6IHNlcnZlcktleSwgdmFsdWU6IHJlc3BvbnNlLnZhbHVlIH07XG4gICAgICAgIH0pO1xuICAgICAgfSlcbiAgICApO1xuICAgIGNvbnN0IHZhbHVlcyA9IHZlcnNpb25PYmplY3RzLnJlZHVjZSgoYWNjdW11bGF0b3IsIHZlcnNpb25PYmplY3QpID0+IHtcbiAgICAgIGFjY3VtdWxhdG9yW3ZlcnNpb25PYmplY3Quc2VydmVyS2V5XSA9IHZlcnNpb25PYmplY3QudmFsdWU7XG4gICAgICByZXR1cm4gYWNjdW11bGF0b3I7XG4gICAgfSwge30gYXMgUmVjb3JkPHN0cmluZywgVmFsdWUgfCBudWxsPik7XG4gICAgcmV0dXJuIHsgdmFsdWVzOiB2YWx1ZXMgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDbG9zZXMgKGFicnVwdGx5KSBjb25uZWN0aW9ucyB0byBhbGwgdGhlIHNlcnZlcnMuXG4gICAqIEBzZWUgdGhpcy5xdWl0XG4gICAqL1xuICBjbG9zZSgpIHtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuc2VydmVycy5sZW5ndGg7IGkrKykge1xuICAgICAgdGhpcy5zZXJ2ZXJzW2ldLmNsb3NlKCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFBlcmZvcm0gYSBnZW5lcmljIHNpbmdsZSByZXNwb25zZSBvcGVyYXRpb24gKGdldCwgc2V0IGV0Yykgb24gb25lIHNlcnZlclxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IHRoZSBrZXkgdG8gaGFzaCB0byBnZXQgYSBzZXJ2ZXIgZnJvbSB0aGUgcG9vbFxuICAgKiBAcGFyYW0ge2J1ZmZlcn0gcmVxdWVzdCBhIGJ1ZmZlciBjb250YWluaW5nIHRoZSByZXF1ZXN0XG4gICAqIEBwYXJhbSB7bnVtYmVyfSBzZXEgdGhlIHNlcXVlbmNlIG51bWJlciBvZiB0aGUgb3BlcmF0aW9uLiBJdCBpcyB1c2VkIHRvIHBpbiB0aGUgY2FsbGJhY2tzXG4gICAgICAgICAgICAgICAgICAgICAgICAgdG8gYSBzcGVjaWZpYyBvcGVyYXRpb24gYW5kIHNob3VsZCBuZXZlciBjaGFuZ2UgZHVyaW5nIGEgYHBlcmZvcm1gLlxuICAgKiBAcGFyYW0ge251bWJlcj99IHJldHJpZXMgbnVtYmVyIG9mIHRpbWVzIHRvIHJldHJ5IHJlcXVlc3Qgb24gZmFpbHVyZVxuICAgKi9cbiAgcGVyZm9ybShcbiAgICBrZXk6IHN0cmluZyxcbiAgICByZXF1ZXN0OiBCdWZmZXIsXG4gICAgc2VxOiBudW1iZXIsXG4gICAgcmV0cmllcz86IG51bWJlclxuICApOiBQcm9taXNlPE1lc3NhZ2U+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgY29uc3Qgc2VydmVyS2V5ID0gdGhpcy5sb29rdXBLZXlUb1NlcnZlcktleShrZXkpO1xuICAgICAgY29uc3Qgc2VydmVyID0gdGhpcy5zZXJ2ZXJLZXlUb1NlcnZlcihzZXJ2ZXJLZXkpO1xuXG4gICAgICBpZiAoIXNlcnZlcikge1xuICAgICAgICByZXR1cm4gcmVqZWN0KG5ldyBFcnJvcihcIk5vIHNlcnZlcnMgYXZhaWxhYmxlXCIpKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5wZXJmb3JtT25TZXJ2ZXIoXG4gICAgICAgIHNlcnZlcixcbiAgICAgICAgcmVxdWVzdCxcbiAgICAgICAgc2VxLFxuICAgICAgICAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICByZXR1cm4gcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmVzb2x2ZShyZXNwb25zZSEpO1xuICAgICAgICB9LFxuICAgICAgICByZXRyaWVzXG4gICAgICApO1xuICAgIH0pO1xuICB9XG5cbiAgcGVyZm9ybU9uU2VydmVyKFxuICAgIHNlcnZlcjogU2VydmVyLFxuICAgIHJlcXVlc3Q6IEJ1ZmZlcixcbiAgICBzZXE6IG51bWJlcixcbiAgICBjYWxsYmFjazogUmVzcG9uc2VPckVycm9yQ2FsbGJhY2ssXG4gICAgcmV0cmllczogbnVtYmVyID0gMFxuICApIHtcbiAgICBjb25zdCBfdGhpcyA9IHRoaXM7XG5cbiAgICByZXRyaWVzID0gcmV0cmllcyB8fCB0aGlzLm9wdGlvbnMucmV0cmllcztcbiAgICBjb25zdCBvcmlnUmV0cmllcyA9IHRoaXMub3B0aW9ucy5yZXRyaWVzO1xuICAgIGNvbnN0IGxvZ2dlciA9IHRoaXMub3B0aW9ucy5sb2dnZXI7XG4gICAgY29uc3QgcmV0cnlfZGVsYXkgPSB0aGlzLm9wdGlvbnMucmV0cnlfZGVsYXk7XG5cbiAgICBjb25zdCByZXNwb25zZUhhbmRsZXI6IE9uUmVzcG9uc2VDYWxsYmFjayA9IGZ1bmN0aW9uIChyZXNwb25zZSkge1xuICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgIGNhbGxiYWNrKG51bGwsIHJlc3BvbnNlKTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgY29uc3QgZXJyb3JIYW5kbGVyOiBPbkVycm9yQ2FsbGJhY2sgPSBmdW5jdGlvbiAoZXJyb3IpIHtcbiAgICAgIGlmICgtLXJldHJpZXMgPiAwKSB7XG4gICAgICAgIC8vIFdhaXQgZm9yIHJldHJ5X2RlbGF5XG4gICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgIF90aGlzLnBlcmZvcm1PblNlcnZlcihzZXJ2ZXIsIHJlcXVlc3QsIHNlcSwgY2FsbGJhY2ssIHJldHJpZXMpO1xuICAgICAgICB9LCAxMDAwICogcmV0cnlfZGVsYXkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbG9nZ2VyLmxvZyhcbiAgICAgICAgICBcIk1lbUpTOiBTZXJ2ZXIgPFwiICtcbiAgICAgICAgICAgIHNlcnZlci5ob3N0cG9ydFN0cmluZygpICtcbiAgICAgICAgICAgIFwiPiBmYWlsZWQgYWZ0ZXIgKFwiICtcbiAgICAgICAgICAgIG9yaWdSZXRyaWVzICtcbiAgICAgICAgICAgIFwiKSByZXRyaWVzIHdpdGggZXJyb3IgLSBcIiArXG4gICAgICAgICAgICBlcnJvci5tZXNzYWdlXG4gICAgICAgICk7XG4gICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgIGNhbGxiYWNrKGVycm9yLCBudWxsKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH07XG5cbiAgICBzZXJ2ZXIub25SZXNwb25zZShzZXEsIHJlc3BvbnNlSGFuZGxlcik7XG4gICAgc2VydmVyLm9uRXJyb3Ioc2VxLCBlcnJvckhhbmRsZXIpO1xuICAgIHNlcnZlci53cml0ZShyZXF1ZXN0KTtcbiAgfVxuXG4gIC8vIEluY3JlbWVudCB0aGUgc2VxIHZhbHVlXG4gIGluY3JTZXEoKSB7XG4gICAgdGhpcy5zZXErKztcblxuICAgIC8vIFdyYXAgYHRoaXMuc2VxYCB0byAzMi1iaXRzIHNpbmNlIHRoZSBmaWVsZCB3ZSBmaXQgaXQgaW50byBpcyBvbmx5IDMyLWJpdHMuXG4gICAgdGhpcy5zZXEgJj0gMHhmZmZmZmZmZjtcbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlQW5kTG9nRXJyb3IoXG4gICAgY29tbWFuZE5hbWU6IHN0cmluZyxcbiAgICByZXNwb25zZVN0YXR1czogUmVzcG9uc2VTdGF0dXMgfCB1bmRlZmluZWRcbiAgKTogRXJyb3Ige1xuICAgIGNvbnN0IGVycm9yTWVzc2FnZSA9IGBNZW1KUyAke2NvbW1hbmROYW1lfTogJHtjb25zdGFudHMucmVzcG9uc2VTdGF0dXNUb1N0cmluZyhcbiAgICAgIHJlc3BvbnNlU3RhdHVzXG4gICAgKX1gO1xuICAgIHRoaXMub3B0aW9ucy5sb2dnZXIubG9nKGVycm9yTWVzc2FnZSk7XG4gICAgcmV0dXJuIG5ldyBFcnJvcihlcnJvck1lc3NhZ2UpO1xuICB9XG5cbiAgLyoqXG4gICAqIExvZyBhbiBlcnJvciB0byB0aGUgbG9nZ2VyLCB0aGVuIHJldHVybiB0aGUgZXJyb3IuXG4gICAqIElmIGEgY2FsbGJhY2sgaXMgZ2l2ZW4sIGNhbGwgaXQgd2l0aCBjYWxsYmFjayhlcnJvciwgbnVsbCkuXG4gICAqL1xuICBwcml2YXRlIGhhbmRsZVJlc3BvbnNlRXJyb3IoXG4gICAgY29tbWFuZE5hbWU6IHN0cmluZyxcbiAgICByZXNwb25zZVN0YXR1czogUmVzcG9uc2VTdGF0dXMgfCB1bmRlZmluZWQsXG4gICAgY2FsbGJhY2s6IHVuZGVmaW5lZCB8ICgoZXJyb3I6IEVycm9yIHwgbnVsbCwgb3RoZXI6IG51bGwpID0+IHZvaWQpXG4gICk6IEVycm9yIHtcbiAgICBjb25zdCBlcnJvciA9IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoY29tbWFuZE5hbWUsIHJlc3BvbnNlU3RhdHVzKTtcbiAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgIGNhbGxiYWNrKGVycm9yLCBudWxsKTtcbiAgICB9XG4gICAgcmV0dXJuIGVycm9yO1xuICB9XG59XG5cbmV4cG9ydCB7IENsaWVudCwgU2VydmVyLCBVdGlscywgSGVhZGVyIH07XG4iXX0= \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVtanMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbWVtanMvbWVtanMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLHdCQUF3Qjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUV4QixxQ0FLa0I7QUE2aENELHVGQS9oQ2YsZUFBTSxPQStoQ2U7QUE1aEN2Qix1REFBK0Q7QUFDL0QsbUNBU2lCO0FBQ2pCLHVEQUF5QztBQUN6QywyQ0FBNkM7QUFDN0MsK0NBQWlDO0FBK2dDUixzQkFBSztBQTlnQzlCLGlEQUFtQztBQThnQ0gsd0JBQU07QUE1Z0N0QyxTQUFTLDhCQUE4QixDQUNyQyxPQUFpQixFQUNqQixHQUFXO0lBRVgsTUFBTSxLQUFLLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQztJQUM3QixNQUFNLEtBQUssR0FBRyxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxnQkFBUSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3BELE9BQU8sT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ3hCLENBQUM7QUFFRCwrQ0FBK0M7QUFDL0MsU0FBUyxTQUFTLENBQ2hCLE9BQTBFO0lBRTFFLE9BQU8sSUFBSSxPQUFPLENBQUMsVUFBVSxPQUFPLEVBQUUsTUFBTTtRQUMxQyxPQUFPLENBQUMsVUFBVSxHQUFHLEVBQUUsTUFBTTtZQUMzQixHQUFHLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3RDLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBNkRELE1BQU0sTUFBTTtJQVFWLDRFQUE0RTtJQUM1RSxtQ0FBbUM7SUFDbkMsWUFBWSxPQUFpQixFQUFFLE9BQTBDO1FBQ3ZFLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO1FBQ3ZCLElB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QW1CLENBQ3pCLFdBQW1CLEVBQ25CLGNBQTBDLEVBQzFDLFFBQWtFO1FBRWxFLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxXQUFXLEVBQUUsY0FBYyxDQUFDLENBQUM7UUFDbEUsSUFBSSxRQUFRLEVBQUU7WUFDWixRQUFRLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxDQUFDO1NBQ3ZCO1FBQ0QsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0NBQ0Y7QUFFUSx3QkFBTSIsInNvdXJjZXNDb250ZW50IjpbIi8vIE1lbVRTIE1lbWNhY2hlIENsaWVudFxuXG5pbXBvcnQge1xuICBPbkVycm9yQ2FsbGJhY2ssXG4gIE9uUmVzcG9uc2VDYWxsYmFjayxcbiAgU2VydmVyLFxuICBTZXJ2ZXJPcHRpb25zLFxufSBmcm9tIFwiLi9zZXJ2ZXJcIjtcbmltcG9ydCB7IG5vb3BTZXJpYWxpemVyLCBTZXJpYWxpemVyIH0gZnJvbSBcIi4vbm9vcC1zZXJpYWxpemVyXCI7XG5pbXBvcnQge1xuICBtYWtlUmVxdWVzdEJ1ZmZlcixcbiAgY29weUludG9SZXF1ZXN0QnVmZmVyLFxuICBtZXJnZSxcbiAgbWFrZUV4cGlyYXRpb24sXG4gIG1ha2VBbW91bnRJbml0aWFsQW5kRXhwaXJhdGlvbixcbiAgaGFzaENvZGUsXG4gIE1heWJlQnVmZmVyLFxuICBNZXNzYWdlLFxufSBmcm9tIFwiLi91dGlsc1wiO1xuaW1wb3J0ICogYXMgY29uc3RhbnRzIGZyb20gXCIuL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgUmVzcG9uc2VTdGF0dXMgfSBmcm9tIFwiLi9jb25zdGFudHNcIjtcbmltcG9ydCAqIGFzIFV0aWxzIGZyb20gXCIuL3V0aWxzXCI7XG5pbXBvcnQgKiBhcyBIZWFkZXIgZnJvbSBcIi4vaGVhZGVyXCI7XG5cbmZ1bmN0aW9uIGRlZmF1bHRLZXlUb1NlcnZlckhhc2hGdW5jdGlvbihcbiAgc2VydmVyczogc3RyaW5nW10sXG4gIGtleTogc3RyaW5nXG4pOiBzdHJpbmcge1xuICBjb25zdCB0b3RhbCA9IHNlcnZlcnMubGVuZ3RoO1xuICBjb25zdCBpbmRleCA9IHRvdGFsID4gMSA/IGhhc2hDb2RlKGtleSkgJSB0b3RhbCA6IDA7XG4gIHJldHVybiBzZXJ2ZXJzW2luZGV4XTtcbn1cblxuLy8gY29udmVydHMgYSBjYWxsIGludG8gYSBwcm9taXNlLXJldHVybmluZyBvbmVcbmZ1bmN0aW9uIHByb21pc2lmeTxSZXN1bHQ+KFxuICBjb21tYW5kOiAoY2FsbGJhY2s6IChlcnJvcjogRXJyb3IgfCBudWxsLCByZXN1bHQ6IFJlc3VsdCkgPT4gdm9pZCkgPT4gdm9pZFxuKTogUHJvbWlzZTxSZXN1bHQ+IHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICBjb21tYW5kKGZ1bmN0aW9uIChlcnIsIHJlc3VsdCkge1xuICAgICAgZXJyID8gcmVqZWN0KGVycikgOiByZXNvbHZlKHJlc3VsdCk7XG4gICAgfSk7XG4gIH0pO1xufVxuXG50eXBlIFJlc3BvbnNlT3JFcnJvckNhbGxiYWNrID0gKFxuICBlcnJvcjogRXJyb3IgfCBudWxsLFxuICByZXNwb25zZTogTWVzc2FnZSB8IG51bGxcbikgPT4gdm9pZDtcblxuaW50ZXJmYWNlIEJhc2VDbGllbnRPcHRpb25zIHtcbiAgcmV0cmllczogbnVtYmVyO1xuICByZXRyeV9kZWxheTogbnVtYmVyO1xuICBleHBpcmVzOiBudW1iZXI7XG4gIGxvZ2dlcjogeyBsb2c6IHR5cGVvZiBjb25zb2xlLmxvZyB9O1xuICBrZXlUb1NlcnZlckhhc2hGdW5jdGlvbjogdHlwZW9mIGRlZmF1bHRLZXlUb1NlcnZlckhhc2hGdW5jdGlvbjtcbn1cblxuaW50ZXJmYWNlIFNlcmlhbGl6ZXJQcm9wPFZhbHVlLCBFeHRyYXM+IHtcbiAgc2VyaWFsaXplcjogU2VyaWFsaXplcjxWYWx1ZSwgRXh0cmFzPjtcbn1cblxuLyoqXG4gKiBUaGUgY2xpZW50IGhhcyBwYXJ0aWFsIHN1cHBvcnQgZm9yIHNlcmlhbGl6aW5nIGFuZCBkZXNlcmlhbGl6aW5nIHZhbHVlcyBmcm9tIHRoZVxuICogQnVmZmVyIGJ5dGUgc3RyaW5ncyB3ZSByZWNpZXZlIGZyb20gdGhlIHdpcmUuIFRoZSBkZWZhdWx0IHNlcmlhbGl6ZXIgaXMgZm9yIE1heWJlQnVmZmVyLlxuICpcbiAqIElmIFZhbHVlIGFuZCBFeHRyYXMgYXJlIG9mIHR5cGUgQnVmZmVyLCB0aGVuIHJldHVybiB0eXBlIFdoZW5CdWZmZXIuIE90aGVyd2lzZSxcbiAqIHJldHVybiB0eXBlIE5vdEJ1ZmZlci5cbiAqL1xudHlwZSBJZkJ1ZmZlcjxcbiAgVmFsdWUsXG4gIEV4dHJhcyxcbiAgV2hlblZhbHVlQW5kRXh0cmFzQXJlQnVmZmVycyxcbiAgTm90QnVmZmVyXG4+ID0gVmFsdWUgZXh0ZW5kcyBCdWZmZXJcbiAgPyBFeHRyYXMgZXh0ZW5kcyBCdWZmZXJcbiAgICA/IFdoZW5WYWx1ZUFuZEV4dHJhc0FyZUJ1ZmZlcnNcbiAgICA6IE5vdEJ1ZmZlclxuICA6IE5vdEJ1ZmZlcjtcblxuZXhwb3J0IHR5cGUgR2l2ZW5DbGllbnRPcHRpb25zPFZhbHVlLCBFeHRyYXM+ID0gUGFydGlhbDxCYXNlQ2xpZW50T3B0aW9ucz4gJlxuICBJZkJ1ZmZlcjxcbiAgICBWYWx1ZSxcbiAgICBFeHRyYXMsXG4gICAgUGFydGlhbDxTZXJpYWxpemVyUHJvcDxWYWx1ZSwgRXh0cmFzPj4sXG4gICAgU2VyaWFsaXplclByb3A8VmFsdWUsIEV4dHJhcz5cbiAgPjtcblxuZXhwb3J0IHR5cGUgQ0FTVG9rZW4gPSBCdWZmZXI7XG5cbmV4cG9ydCBpbnRlcmZhY2UgR2V0UmVzdWx0PFZhbHVlID0gTWF5YmVCdWZmZXIsIEV4dHJhcyA9IE1heWJlQnVmZmVyPiB7XG4gIHZhbHVlOiBWYWx1ZTtcbiAgZXh0cmFzOiBFeHRyYXM7XG4gIGNhczogQ0FTVG9rZW4gfCB1bmRlZmluZWQ7XG59XG5cbmV4cG9ydCB0eXBlIEdldE11bHRpUmVzdWx0PFxuICBLZXlzIGV4dGVuZHMgc3RyaW5nID0gc3RyaW5nLFxuICBWYWx1ZSA9IE1heWJlQnVmZmVyLFxuICBFeHRyYXMgPSBNYXliZUJ1ZmZlclxuPiA9IHtcbiAgW0sgaW4gS2V5c10/OiBHZXRSZXN1bHQ8VmFsdWUsIEV4dHJhcz47XG59O1xuXG5jbGFzcyBDbGllbnQ8VmFsdWUgPSBNYXliZUJ1ZmZlciwgRXh0cmFzID0gTWF5YmVCdWZmZXI+IHtcbiAgc2VydmVyczogU2VydmVyW107XG4gIHNlcTogbnVtYmVyO1xuICBvcHRpb25zOiBCYXNlQ2xpZW50T3B0aW9ucyAmIFBhcnRpYWw8U2VyaWFsaXplclByb3A8VmFsdWUsIEV4dHJhcz4+O1xuICBzZXJpYWxpemVyOiBTZXJpYWxpemVyPFZhbHVlLCBFeHRyYXM+O1xuICBzZXJ2ZXJNYXA6IHsgW2hvc3Rwb3J0OiBzdHJpbmddOiBTZXJ2ZXIgfTtcbiAgc2VydmVyS2V5czogc3RyaW5nW107XG5cbiAgLy8gQ2xpZW50IGluaXRpYWxpemVyIHRha2VzIGEgbGlzdCBvZiBgU2VydmVyYHMgYW5kIGFuIGBvcHRpb25zYCBkaWN0aW9uYXJ5LlxuICAvLyBTZWUgYENsaWVudC5jcmVhdGVgIGZvciBkZXRhaWxzLlxuICBjb25zdHJ1Y3RvcihzZXJ2ZXJzOiBTZXJ2ZXJbXSwgb3B0aW9uczogR2l2ZW5DbGllbnRPcHRpb25zPFZhbHVlLCBFeHRyYXM+KSB7XG4gICAgdGhpcy5zZXJ2ZXJzID0gc2VydmVycztcbiAgICB0aGlzLnNlcSA9IDA7XG4gICAgdGhpcy5vcHRpb25zID0gbWVyZ2Uob3B0aW9ucyB8fCB7fSwge1xuICAgICAgcmV0cmllczogMixcbiAgICAgIHJldHJ5X2RlbGF5OiAwLjIsXG4gICAgICBleHBpcmVzOiAwLFxuICAgICAgbG9nZ2VyOiBjb25zb2xlLFxuICAgICAga2V5VG9TZXJ2ZXJIYXNoRnVuY3Rpb246IGRlZmF1bHRLZXlUb1NlcnZlckhhc2hGdW5jdGlvbixcbiAgICB9KTtcblxuICAgIHRoaXMuc2VyaWFsaXplciA9IHRoaXMub3B0aW9ucy5zZXJpYWxpemVyIHx8IChub29wU2VyaWFsaXplciBhcyBhbnkpO1xuXG4gICAgLy8gU3RvcmUgYSBtYXBwaW5nIGZyb20gaG9zdHBvcnQgLT4gc2VydmVyIHNvIHdlIGNhbiBxdWlja2x5IGdldCBhIHNlcnZlciBvYmplY3QgZnJvbSB0aGUgc2VydmVyS2V5IHJldHVybmVkIGJ5IHRoZSBoYXNoaW5nIGZ1bmN0aW9uXG4gICAgY29uc3Qgc2VydmVyTWFwOiB7IFtob3N0cG9ydDogc3RyaW5nXTogU2VydmVyIH0gPSB7fTtcbiAgICB0aGlzLnNlcnZlcnMuZm9yRWFjaChmdW5jdGlvbiAoc2VydmVyKSB7XG4gICAgICBzZXJ2ZXJNYXBbc2VydmVyLmhvc3Rwb3J0U3RyaW5nKCldID0gc2VydmVyO1xuICAgIH0pO1xuICAgIHRoaXMuc2VydmVyTWFwID0gc2VydmVyTWFwO1xuXG4gICAgLy8gc3RvcmUgYSBsaXN0IG9mIGFsbCBvdXIgc2VydmVyS2V5cyBzbyB3ZSBkb24ndCBuZWVkIHRvIGNvbnN0YW50bHkgcmVhbGxvY2F0ZSB0aGlzIGFycmF5XG4gICAgdGhpcy5zZXJ2ZXJLZXlzID0gT2JqZWN0LmtleXModGhpcy5zZXJ2ZXJNYXApO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBuZXcgY2xpZW50IGdpdmVuIGFuIG9wdGlvbmFsIGNvbmZpZyBzdHJpbmcgYW5kIG9wdGlvbmFsIGhhc2ggb2ZcbiAgICogb3B0aW9ucy4gVGhlIGNvbmZpZyBzdHJpbmcgc2hvdWxkIGJlIG9mIHRoZSBmb3JtOlxuICAgKlxuICAgKiAgICAgXCJbdXNlcjpwYXNzQF1zZXJ2ZXIxWzoxMTIxMV0sW3VzZXI6cGFzc0Bdc2VydmVyMls6MTEyMTFdLC4uLlwiXG4gICAqXG4gICAqIElmIHRoZSBhcmd1bWVudCBpcyBub3QgZ2l2ZW4sIGZhbGxiYWNrIG9uIHRoZSBgTUVNQ0FDSElFUl9TRVJWRVJTYCBlbnZpcm9ubWVudFxuICAgKiB2YXJpYWJsZSwgYE1FTUNBQ0hFX1NFUlZFUlNgIGVudmlyb25tZW50IHZhcmlhYmxlIG9yIGBcImxvY2FsaG9zdDoxMTIxMVwiYC5cbiAgICpcbiAgICogVGhlIG9wdGlvbnMgaGFzaCBtYXkgY29udGFpbiB0aGUgb3B0aW9uczpcbiAgICpcbiAgICogKiBgcmV0cmllc2AgLSB0aGUgbnVtYmVyIG9mIHRpbWVzIHRvIHJldHJ5IGFuIG9wZXJhdGlvbiBpbiBsaWV1IG9mIGZhaWx1cmVzXG4gICAqIChkZWZhdWx0IDIpXG4gICAqICogYGV4cGlyZXNgIC0gdGhlIGRlZmF1bHQgZXhwaXJhdGlvbiBpbiBzZWNvbmRzIHRvIHVzZSAoZGVmYXVsdCAwIC0gbmV2ZXJcbiAgICogZXhwaXJlKS4gSWYgYGV4cGlyZXNgIGlzIGdyZWF0ZXIgdGhhbiAzMCBkYXlzICg2MCB4IDYwIHggMjQgeCAzMCksIGl0IGlzXG4gICAqIHRyZWF0ZWQgYXMgYSBVTklYIHRpbWUgKG51bWJlciBvZiBzZWNvbmRzIHNpbmNlIEphbnVhcnkgMSwgMTk3MCkuXG4gICAqICogYGxvZ2dlcmAgLSBhIGxvZ2dlciBvYmplY3QgdGhhdCByZXNwb25kcyB0byBgbG9nKHN0cmluZylgIG1ldGhvZCBjYWxscy5cbiAgICpcbiAgICogICB+fn5+XG4gICAqICAgICBsb2cobXNnMVssIG1zZzJbLCBtc2czWy4uLl1dXSlcbiAgICogICB+fn5+XG4gICAqXG4gICAqICAgRGVmYXVsdHMgdG8gYGNvbnNvbGVgLlxuICAgKiAqIGBzZXJpYWxpemVyYCAtIHRoZSBvYmplY3Qgd2hpY2ggd2lsbCAoZGUpc2VyaWFsaXplIHRoZSBkYXRhLiBJdCBuZWVkc1xuICAgKiAgIHR3byBwdWJsaWMgbWV0aG9kczogc2VyaWFsaXplIGFuZCBkZXNlcmlhbGl6ZS4gSXQgZGVmYXVsdHMgdG8gdGhlXG4gICAqICAgbm9vcFNlcmlhbGl6ZXI6XG4gICAqXG4gICAqICAgfn5+flxuICAgKiAgIGNvbnN0IG5vb3BTZXJpYWxpemVyID0ge1xuICAgKiAgICAgc2VyaWFsaXplOiBmdW5jdGlvbiAob3Bjb2RlLCB2YWx1ZSwgZXh0cmFzKSB7XG4gICAqICAgICAgIHJldHVybiB7IHZhbHVlOiB2YWx1ZSwgZXh0cmFzOiBleHRyYXMgfTtcbiAgICogICAgIH0sXG4gICAqICAgICBkZXNlcmlhbGl6ZTogZnVuY3Rpb24gKG9wY29kZSwgdmFsdWUsIGV4dHJhcykge1xuICAgKiAgICAgICByZXR1cm4geyB2YWx1ZTogdmFsdWUsIGV4dHJhczogZXh0cmFzIH07XG4gICAqICAgICB9XG4gICAqICAgfTtcbiAgICogICB+fn5+XG4gICAqXG4gICAqIE9yIG9wdGlvbnMgZm9yIHRoZSBzZXJ2ZXJzIGluY2x1ZGluZzpcbiAgICogKiBgdXNlcm5hbWVgIGFuZCBgcGFzc3dvcmRgIGZvciBmYWxsYmFjayBTQVNMIGF1dGhlbnRpY2F0aW9uIGNyZWRlbnRpYWxzLlxuICAgKiAqIGB0aW1lb3V0YCBpbiBzZWNvbmRzIHRvIGRldGVybWluZSBmYWlsdXJlIGZvciBvcGVyYXRpb25zLiBEZWZhdWx0IGlzIDAuNVxuICAgKiAgICAgICAgICAgICBzZWNvbmRzLlxuICAgKiAqICdjb25udGltZW91dCcgaW4gc2Vjb25kcyB0byBjb25uZWN0aW9uIGZhaWx1cmUuIERlZmF1bHQgaXMgdHdpY2UgdGhlIHZhbHVlXG4gICAqICAgICAgICAgICAgICAgICBvZiBgdGltZW91dGAuXG4gICAqICogYGtlZXBBbGl2ZWAgd2hldGhlciB0byBlbmFibGUga2VlcC1hbGl2ZSBmdW5jdGlvbmFsaXR5LiBEZWZhdWx0cyB0byBmYWxzZS5cbiAgICogKiBga2VlcEFsaXZlRGVsYXlgIGluIHNlY29uZHMgdG8gdGhlIGluaXRpYWwgZGVsYXkgYmVmb3JlIHRoZSBmaXJzdCBrZWVwYWxpdmVcbiAgICogICAgICAgICAgICAgICAgICAgIHByb2JlIGlzIHNlbnQgb24gYW4gaWRsZSBzb2NrZXQuIERlZmF1bHRzIGlzIDMwIHNlY29uZHMuXG4gICAqICogYGtleVRvU2VydmVySGFzaEZ1bmN0aW9uYCBhIGZ1bmN0aW9uIHRvIG1hcCBrZXlzIHRvIHNlcnZlcnMsIHdpdGggdGhlIHNpZ25hdHVyZVxuICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoc2VydmVyS2V5czogc3RyaW5nW10sIGtleTogc3RyaW5nKTogc3RyaW5nXG4gICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgIE5PVEU6IGlmIHlvdSBuZWVkIHRvIGRvIHNvbWUgZXhwZW5zaXZlIGluaXRpYWxpemF0aW9uLCAqcGxlYXNlKiBkbyBpdCBsYXppbHkgdGhlIGZpcnN0IHRpbWUgeW91IHRoaXMgZnVuY3Rpb24gaXMgY2FsbGVkIHdpdGggYW4gYXJyYXkgb2Ygc2VydmVyS2V5cywgbm90IG9uIGV2ZXJ5IGNhbGxcbiAgICovXG4gIHN0YXRpYyBjcmVhdGU8VmFsdWUsIEV4dHJhcz4oXG4gICAgc2VydmVyc1N0cjogc3RyaW5nIHwgdW5kZWZpbmVkLFxuICAgIG9wdGlvbnM6IElmQnVmZmVyPFxuICAgICAgVmFsdWUsXG4gICAgICBFeHRyYXMsXG4gICAgICB1bmRlZmluZWQgfCAoUGFydGlhbDxTZXJ2ZXJPcHRpb25zPiAmIEdpdmVuQ2xpZW50T3B0aW9uczxWYWx1ZSwgRXh0cmFzPiksXG4gICAgICBQYXJ0aWFsPFNlcnZlck9wdGlvbnM+ICYgR2l2ZW5DbGllbnRPcHRpb25zPFZhbHVlLCBFeHRyYXM+XG4gICAgPlxuICApOiBDbGllbnQ8VmFsdWUsIEV4dHJhcz4ge1xuICAgIHNlcnZlcnNTdHIgPVxuICAgICAgc2VydmVyc1N0ciB8fFxuICAgICAgcHJvY2Vzcy5lbnYuTUVNQ0FDSElFUl9TRVJWRVJTIHx8XG4gICAgICBwcm9jZXNzLmVudi5NRU1DQUNIRV9TRVJWRVJTIHx8XG4gICAgICBcImxvY2FsaG9zdDoxMTIxMVwiO1xuICAgIGNvbnN0IHNlcnZlclVyaXMgPSBzZXJ2ZXJzU3RyLnNwbGl0KFwiLFwiKTtcbiAgICBjb25zdCBzZXJ2ZXJzID0gc2VydmVyVXJpcy5tYXAoZnVuY3Rpb24gKHVyaSkge1xuICAgICAgY29uc3QgdXJpUGFydHMgPSB1cmkuc3BsaXQoXCJAXCIpO1xuICAgICAgY29uc3QgaG9zdFBvcnQgPSB1cmlQYXJ0c1t1cmlQYXJ0cy5sZW5ndGggLSAxXS5zcGxpdChcIjpcIik7XG4gICAgICBjb25zdCB1c2VyUGFzcyA9ICh1cmlQYXJ0c1t1cmlQYXJ0cy5sZW5ndGggLSAyXSB8fCBcIlwiKS5zcGxpdChcIjpcIik7XG4gICAgICByZXR1cm4gbmV3IFNlcnZlcihcbiAgICAgICAgaG9zdFBvcnRbMF0sXG4gICAgICAgIHBhcnNlSW50KGhvc3RQb3J0WzFdIHx8IFwiMTEyMTFcIiwgMTApLFxuICAgICAgICB1c2VyUGFzc1swXSxcbiAgICAgICAgdXNlclBhc3NbMV0sXG4gICAgICAgIG9wdGlvbnNcbiAgICAgICk7XG4gICAgfSk7XG4gICAgcmV0dXJuIG5ldyBDbGllbnQoc2VydmVycywgb3B0aW9ucyBhcyBhbnkpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdpdmVuIGEgc2VydmVyS2V5IGZyb21sb29rdXBLZXlUb1NlcnZlcktleSwgcmV0dXJuIHRoZSBjb3JyZXNwb25kaW5nIFNlcnZlciBpbnN0YW5jZVxuICAgKlxuICAgKiBAcGFyYW0gIHtzdHJpbmd9IHNlcnZlcktleVxuICAgKiBAcmV0dXJucyB7U2VydmVyfVxuICAgKi9cbiAgc2VydmVyS2V5VG9TZXJ2ZXIoc2VydmVyS2V5OiBzdHJpbmcpOiBTZXJ2ZXIge1xuICAgIHJldHVybiB0aGlzLnNlcnZlck1hcFtzZXJ2ZXJLZXldO1xuICB9XG5cbiAgLyoqXG4gICAqIEdpdmVuIGEga2V5IHRvIGxvb2sgdXAgaW4gbWVtY2FjaGUsIHJldHVybiBhIHNlcnZlcktleSAoYmFzZWQgb24gc29tZVxuICAgKiBoYXNoaW5nIGZ1bmN0aW9uKSB3aGljaCBjYW4gYmUgdXNlZCB0byBpbmRleCB0aGlzLnNlcnZlck1hcFxuICAgKi9cbiAgbG9va3VwS2V5VG9TZXJ2ZXJLZXkoa2V5OiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLm9wdGlvbnMua2V5VG9TZXJ2ZXJIYXNoRnVuY3Rpb24odGhpcy5zZXJ2ZXJLZXlzLCBrZXkpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHJpZXZlcyB0aGUgdmFsdWUgYXQgdGhlIGdpdmVuIGtleSBpbiBtZW1jYWNoZS5cbiAgICovXG4gIGFzeW5jIGdldChrZXk6IHN0cmluZyk6IFByb21pc2U8R2V0UmVzdWx0PFZhbHVlLCBFeHRyYXM+IHwgbnVsbD4ge1xuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihjb25zdGFudHMuT1BfR0VULCBrZXksIFwiXCIsIFwiXCIsIHRoaXMuc2VxKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgY29uc3QgZGVzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLmRlc2VyaWFsaXplKFxuICAgICAgICAgIHJlc3BvbnNlLmhlYWRlci5vcGNvZGUsXG4gICAgICAgICAgcmVzcG9uc2UudmFsLFxuICAgICAgICAgIHJlc3BvbnNlLmV4dHJhc1xuICAgICAgICApO1xuICAgICAgICByZXR1cm4geyAuLi5kZXNlcmlhbGl6ZWQsIGNhczogcmVzcG9uc2UuaGVhZGVyLmNhcyB9O1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfTk9UX0ZPVU5EOlxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJHRVRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqIEJ1aWxkIGEgcGlwZWxpbmVkIGdldCBtdWx0aSByZXF1ZXN0IGJ5IHNlbmRpbmcgb25lIEdFVEtRIGZvciBlYWNoIGtleSAocXVpZXQsIG1lYW5pbmcgaXQgd29uJ3QgcmVzcG9uZCBpZiB0aGUgdmFsdWUgaXMgbWlzc2luZykgZm9sbG93ZWQgYnkgYSBuby1vcCB0byBmb3JjZSBhIHJlc3BvbnNlIChhbmQgdG8gZ2l2ZSB1cyBhIHNlbnRpbmVsIHJlc3BvbnNlIHRoYXQgdGhlIHBpcGVsaW5lIGlzIGRvbmUpXG4gICAqXG4gICAqIGNmIGh0dHBzOi8vZ2l0aHViLmNvbS9jb3VjaGJhc2UvbWVtY2FjaGVkL2Jsb2IvbWFzdGVyL2RvY3MvQmluYXJ5UHJvdG9jb2wubWQjMHgwZC1nZXRrcS1nZXQtd2l0aC1rZXktcXVpZXRseVxuICAgKi9cbiAgX2J1aWxkR2V0TXVsdGlSZXF1ZXN0KGtleXM6IHN0cmluZ1tdKTogQnVmZmVyIHtcbiAgICAvLyBzdGFydCBhdCAyNCBmb3IgdGhlIG5vLW9wIGNvbW1hbmQgYXQgdGhlIGVuZFxuICAgIGxldCByZXF1ZXN0U2l6ZSA9IDI0O1xuICAgIGZvciAoY29uc3Qga2V5SWR4IGluIGtleXMpIHtcbiAgICAgIHJlcXVlc3RTaXplICs9IEJ1ZmZlci5ieXRlTGVuZ3RoKGtleXNba2V5SWR4XSwgXCJ1dGY4XCIpICsgMjQ7XG4gICAgfVxuXG4gICAgY29uc3QgcmVxdWVzdCA9IEJ1ZmZlci5hbGxvYyhyZXF1ZXN0U2l6ZSk7XG5cbiAgICBsZXQgYnl0ZXNXcml0dGVuID0gMDtcbiAgICBmb3IgKGNvbnN0IGtleUlkeCBpbiBrZXlzKSB7XG4gICAgICBjb25zdCBrZXkgPSBrZXlzW2tleUlkeF07XG4gICAgICBieXRlc1dyaXR0ZW4gKz0gY29weUludG9SZXF1ZXN0QnVmZmVyKFxuICAgICAgICBjb25zdGFudHMuT1BfR0VUS1EsXG4gICAgICAgIGtleSxcbiAgICAgICAgXCJcIixcbiAgICAgICAgXCJcIixcbiAgICAgICAgdGhpcy5zZXEsXG4gICAgICAgIHJlcXVlc3QsXG4gICAgICAgIGJ5dGVzV3JpdHRlblxuICAgICAgKTtcbiAgICB9XG5cbiAgICBieXRlc1dyaXR0ZW4gKz0gY29weUludG9SZXF1ZXN0QnVmZmVyKFxuICAgICAgY29uc3RhbnRzLk9QX05PX09QLFxuICAgICAgXCJcIixcbiAgICAgIFwiXCIsXG4gICAgICBcIlwiLFxuICAgICAgdGhpcy5zZXEsXG4gICAgICByZXF1ZXN0LFxuICAgICAgYnl0ZXNXcml0dGVuXG4gICAgKTtcblxuICAgIHJldHVybiByZXF1ZXN0O1xuICB9XG5cbiAgLyoqIEV4ZWN1dGluZyBhIHBpcGVsaW5lZCAobXVsdGkpIGdldCBhZ2FpbnN0IGEgc2luZ2xlIHNlcnZlci4gVGhpcyBpcyBhIHByaXZhdGUgaW1wbGVtZW50YXRpb24gZGV0YWlsIG9mIGdldE11bHRpLiAqL1xuICBhc3luYyBfZ2V0TXVsdGlUb1NlcnZlcjxLZXlzIGV4dGVuZHMgc3RyaW5nPihcbiAgICBzZXJ2OiBTZXJ2ZXIsXG4gICAga2V5czogS2V5c1tdXG4gICk6IFByb21pc2U8R2V0TXVsdGlSZXN1bHQ8S2V5cywgVmFsdWUsIEV4dHJhcz4+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgY29uc3QgcmVzcG9uc2VNYXA6IEdldE11bHRpUmVzdWx0PHN0cmluZywgVmFsdWUsIEV4dHJhcz4gPSB7fTtcblxuICAgICAgY29uc3QgaGFuZGxlOiBPblJlc3BvbnNlQ2FsbGJhY2sgPSAocmVzcG9uc2UpID0+IHtcbiAgICAgICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICAgICAgLy8gV2hlbiB3ZSBnZXQgdGhlIG5vLW9wIHJlc3BvbnNlLCB3ZSBhcmUgZG9uZSB3aXRoIHRoaXMgb25lIGdldE11bHRpIGluIHRoZSBwZXItYmFja2VuZCBmYW4tb3V0XG4gICAgICAgICAgICBpZiAocmVzcG9uc2UuaGVhZGVyLm9wY29kZSA9PT0gY29uc3RhbnRzLk9QX05PX09QKSB7XG4gICAgICAgICAgICAgIC8vIFRoaXMgZW5zdXJlcyB0aGUgaGFuZGxlciB3aWxsIGJlIGRlbGV0ZWQgZnJvbSB0aGUgcmVzcG9uc2VDYWxsYmFja3MgbWFwIGluIHNlcnZlci5qc1xuICAgICAgICAgICAgICAvLyBUaGlzIGlzbid0IHRlY2huaWNhbGx5IG5lZWRlZCBoZXJlIGJlY2F1c2UgdGhlIGxvZ2ljIGluIHNlcnZlci5qcyBhbHNvIGNoZWNrcyBpZiB0b3RhbEJvZHlMZW5ndGggPT09IDAsIGJ1dCBvdXIgdW5pdHRlc3RzIGFyZW4ndCBncmVhdCBhYm91dCBzZXR0aW5nIHRoYXQgZmllbGQsIGFuZCBhbHNvIHRoaXMgbWFrZXMgaXQgbW9yZSBleHBsaWNpdFxuICAgICAgICAgICAgICBoYW5kbGUucXVpZXQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgcmVzb2x2ZShyZXNwb25zZU1hcCk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHJlc3BvbnNlLmhlYWRlci5vcGNvZGUgPT09IGNvbnN0YW50cy5PUF9HRVRLIHx8IHJlc3BvbnNlLmhlYWRlci5vcGNvZGUgPT09IGNvbnN0YW50cy5PUF9HRVRLUSkge1xuICAgICAgICAgICAgICBjb25zdCBkZXNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuZGVzZXJpYWxpemUoXG4gICAgICAgICAgICAgICAgcmVzcG9uc2UuaGVhZGVyLm9wY29kZSxcbiAgICAgICAgICAgICAgICByZXNwb25zZS52YWwsXG4gICAgICAgICAgICAgICAgcmVzcG9uc2UuZXh0cmFzXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgIGNvbnN0IGtleSA9IHJlc3BvbnNlLmtleS50b1N0cmluZygpO1xuICAgICAgICAgICAgICBpZiAoa2V5Lmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiByZWplY3QoXG4gICAgICAgICAgICAgICAgICBuZXcgRXJyb3IoXCJSZWNpZXZlZCBlbXB0eSBrZXkgaW4gZ2V0TXVsdGk6IFwiICsgSlNPTi5zdHJpbmdpZnkocmVzcG9uc2UpKVxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgcmVzcG9uc2VNYXBba2V5XSA9IHsgLi4uZGVzZXJpYWxpemVkLCBjYXM6IHJlc3BvbnNlLmhlYWRlci5jYXMgfTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHJldHVybiByZWplY3QoXG4gICAgICAgICAgICAgICAgbmV3IEVycm9yKFwiUmVjaWV2ZWQgcmVzcG9uc2UgaW4gZ2V0TXVsdGkgZm9yIHVua25vd24gb3Bjb2RlOiBcIiArIEpTT04uc3RyaW5naWZ5KHJlc3BvbnNlKSlcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICByZXR1cm4gcmVqZWN0KFxuICAgICAgICAgICAgICB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiR0VUXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9O1xuICAgICAgLy8gVGhpcyBwcmV2ZW50cyB0aGUgaGFuZGxlciBmcm9tIGJlaW5nIGRlbGV0ZWRcbiAgICAgIC8vIGFmdGVyIHRoZSBmaXJzdCByZXNwb25zZS4gTG9naWMgaW4gc2VydmVyLmpzLlxuICAgICAgaGFuZGxlLnF1aWV0ID0gdHJ1ZTtcblxuICAgICAgY29uc3QgcmVxdWVzdCA9IHRoaXMuX2J1aWxkR2V0TXVsdGlSZXF1ZXN0KGtleXMpO1xuICAgICAgc2Vydi5vblJlc3BvbnNlKHRoaXMuc2VxLCBoYW5kbGUpO1xuICAgICAgc2Vydi5vbkVycm9yKHRoaXMuc2VxLCByZWplY3QpO1xuICAgICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgICBzZXJ2LndyaXRlKHJlcXVlc3QpO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHJpZXZzIHRoZSB2YWx1ZSBhdCB0aGUgZ2l2ZW4ga2V5cyBpbiBtZW1jYWNoZWQuIFJldHVybnMgYSBtYXAgZnJvbSB0aGVcbiAgICogcmVxdWVzdGVkIGtleXMgdG8gcmVzdWx0cywgb3IgbnVsbCBpZiB0aGUga2V5IHdhcyBub3QgZm91bmQuXG4gICAqL1xuICBhc3luYyBnZXRNdWx0aTxLZXlzIGV4dGVuZHMgc3RyaW5nPihcbiAgICBrZXlzOiBLZXlzW11cbiAgKTogUHJvbWlzZTxHZXRNdWx0aVJlc3VsdDxLZXlzLCBWYWx1ZSwgRXh0cmFzPj4ge1xuICAgIGNvbnN0IHNlcnZlcktleXRvTG9va3VwS2V5czoge1xuICAgICAgW3NlcnZlcktleTogc3RyaW5nXTogc3RyaW5nW107XG4gICAgfSA9IHt9O1xuICAgIGtleXMuZm9yRWFjaCgobG9va3VwS2V5KSA9PiB7XG4gICAgICBjb25zdCBzZXJ2ZXJLZXkgPSB0aGlzLmxvb2t1cEtleVRvU2VydmVyS2V5KGxvb2t1cEtleSk7XG4gICAgICBpZiAoIXNlcnZlcktleXRvTG9va3VwS2V5c1tzZXJ2ZXJLZXldKSB7XG4gICAgICAgIHNlcnZlcktleXRvTG9va3VwS2V5c1tzZXJ2ZXJLZXldID0gW107XG4gICAgICB9XG4gICAgICBzZXJ2ZXJLZXl0b0xvb2t1cEtleXNbc2VydmVyS2V5XS5wdXNoKGxvb2t1cEtleSk7XG4gICAgfSk7XG5cbiAgICBjb25zdCB1c2VkU2VydmVyS2V5cyA9IE9iamVjdC5rZXlzKHNlcnZlcktleXRvTG9va3VwS2V5cyk7XG4gICAgY29uc3QgcmVzdWx0cyA9IGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgdXNlZFNlcnZlcktleXMubWFwKChzZXJ2ZXJLZXkpID0+IHtcbiAgICAgICAgY29uc3Qgc2VydmVyID0gdGhpcy5zZXJ2ZXJLZXlUb1NlcnZlcihzZXJ2ZXJLZXkpO1xuICAgICAgICByZXR1cm4gdGhpcy5fZ2V0TXVsdGlUb1NlcnZlcihzZXJ2ZXIsIHNlcnZlcktleXRvTG9va3VwS2V5c1tzZXJ2ZXJLZXldKTtcbiAgICAgIH0pXG4gICAgKTtcblxuICAgIHJldHVybiBPYmplY3QuYXNzaWduKHt9LCAuLi5yZXN1bHRzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIGBrZXlgIHRvIGB2YWx1ZWAuXG4gICAqL1xuICBhc3luYyBzZXQoXG4gICAga2V5OiBzdHJpbmcsXG4gICAgdmFsdWU6IFZhbHVlLFxuICAgIG9wdGlvbnM/OiB7IGV4cGlyZXM/OiBudW1iZXI7IGNhcz86IENBU1Rva2VuIH1cbiAgKTogUHJvbWlzZTxib29sZWFuIHwgbnVsbD4ge1xuICAgIGNvbnN0IGV4cGlyZXMgPSBvcHRpb25zPy5leHBpcmVzO1xuICAgIGNvbnN0IGNhcyA9IG9wdGlvbnM/LmNhcztcblxuICAgIC8vIFRPRE86IHN1cHBvcnQgZmxhZ3NcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBleHBpcmF0aW9uID0gbWFrZUV4cGlyYXRpb24oZXhwaXJlcyB8fCB0aGlzLm9wdGlvbnMuZXhwaXJlcyk7XG4gICAgY29uc3QgZXh0cmFzID0gQnVmZmVyLmNvbmNhdChbQnVmZmVyLmZyb20oXCIwMDAwMDAwMFwiLCBcImhleFwiKSwgZXhwaXJhdGlvbl0pO1xuICAgIGNvbnN0IHNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuc2VyaWFsaXplKFxuICAgICAgY29uc3RhbnRzLk9QX1NFVCxcbiAgICAgIHZhbHVlLFxuICAgICAgZXh0cmFzXG4gICAgKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gVXRpbHMuZW5jb2RlUmVxdWVzdCh7XG4gICAgICBoZWFkZXI6IHtcbiAgICAgICAgb3Bjb2RlOiBjb25zdGFudHMuT1BfU0VULFxuICAgICAgICBvcGFxdWU6IHRoaXMuc2VxLFxuICAgICAgICBjYXMsXG4gICAgICB9LFxuICAgICAga2V5LFxuICAgICAgdmFsdWU6IHNlcmlhbGl6ZWQudmFsdWUsXG4gICAgICBleHRyYXM6IHNlcmlhbGl6ZWQuZXh0cmFzLFxuICAgIH0pO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuS0VZX0VYSVNUUzpcbiAgICAgICAgaWYgKGNhcykge1xuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiU0VUXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgICAgICB9XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiU0VUXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBBRERcbiAgICpcbiAgICogQWRkcyB0aGUgZ2l2ZW4gX2tleV8gYW5kIF92YWx1ZV8gdG8gbWVtY2FjaGUuIFRoZSBvcGVyYXRpb24gb25seSBzdWNjZWVkc1xuICAgKiBpZiB0aGUga2V5IGlzIG5vdCBhbHJlYWR5IHNldC5cbiAgICpcbiAgICogVGhlIG9wdGlvbnMgZGljdGlvbmFyeSB0YWtlczpcbiAgICogKiBfZXhwaXJlc186IG92ZXJyaWRlcyB0aGUgZGVmYXVsdCBleHBpcmF0aW9uIChzZWUgYENsaWVudC5jcmVhdGVgKSBmb3IgdGhpc1xuICAgKiAgICAgICAgICAgICAgcGFydGljdWxhciBrZXktdmFsdWUgcGFpci5cbiAgICovXG4gIGFzeW5jIGFkZChcbiAgICBrZXk6IHN0cmluZyxcbiAgICB2YWx1ZTogVmFsdWUsXG4gICAgb3B0aW9ucz86IHsgZXhwaXJlcz86IG51bWJlciB9XG4gICk6IFByb21pc2U8Ym9vbGVhbiB8IG51bGw+IHtcbiAgICAvLyBUT0RPOiBzdXBwb3J0IGZsYWdzLCBzdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBleHBpcmF0aW9uID0gbWFrZUV4cGlyYXRpb24ob3B0aW9ucz8uZXhwaXJlcyB8fCB0aGlzLm9wdGlvbnMuZXhwaXJlcyk7XG4gICAgY29uc3QgZXh0cmFzID0gQnVmZmVyLmNvbmNhdChbQnVmZmVyLmZyb20oXCIwMDAwMDAwMFwiLCBcImhleFwiKSwgZXhwaXJhdGlvbl0pO1xuXG4gICAgY29uc3Qgb3Bjb2RlID0gY29uc3RhbnRzLk9QX0FERDtcbiAgICBjb25zdCBzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLnNlcmlhbGl6ZShvcGNvZGUsIHZhbHVlLCBleHRyYXMpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgIG9wY29kZSxcbiAgICAgIGtleSxcbiAgICAgIHNlcmlhbGl6ZWQuZXh0cmFzLFxuICAgICAgc2VyaWFsaXplZC52YWx1ZSxcbiAgICAgIHRoaXMuc2VxXG4gICAgKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9FWElTVFM6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiQUREXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXBsYWNlcyB0aGUgZ2l2ZW4gX2tleV8gYW5kIF92YWx1ZV8gdG8gbWVtY2FjaGUuIFRoZSBvcGVyYXRpb24gb25seSBzdWNjZWVkc1xuICAgKiBpZiB0aGUga2V5IGlzIGFscmVhZHkgcHJlc2VudC5cbiAgICovXG4gIGFzeW5jIHJlcGxhY2UoXG4gICAga2V5OiBzdHJpbmcsXG4gICAgdmFsdWU6IFZhbHVlLFxuICAgIG9wdGlvbnM/OiB7IGV4cGlyZXM/OiBudW1iZXIgfVxuICApOiBQcm9taXNlPGJvb2xlYW4gfCBudWxsPiB7XG4gICAgLy8gVE9ETzogc3VwcG9ydCBmbGFncywgc3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgZXhwaXJhdGlvbiA9IG1ha2VFeHBpcmF0aW9uKG9wdGlvbnM/LmV4cGlyZXMgfHwgdGhpcy5vcHRpb25zLmV4cGlyZXMpO1xuICAgIGNvbnN0IGV4dHJhcyA9IEJ1ZmZlci5jb25jYXQoW0J1ZmZlci5mcm9tKFwiMDAwMDAwMDBcIiwgXCJoZXhcIiksIGV4cGlyYXRpb25dKTtcblxuICAgIGNvbnN0IG9wY29kZTogY29uc3RhbnRzLk9QID0gY29uc3RhbnRzLk9QX1JFUExBQ0U7XG4gICAgY29uc3Qgc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5zZXJpYWxpemUob3Bjb2RlLCB2YWx1ZSwgZXh0cmFzKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICBvcGNvZGUsXG4gICAgICBrZXksXG4gICAgICBzZXJpYWxpemVkLmV4dHJhcyxcbiAgICAgIHNlcmlhbGl6ZWQudmFsdWUsXG4gICAgICB0aGlzLnNlcVxuICAgICk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfTk9UX0ZPVU5EOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiUkVQTEFDRVwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRGVsZXRlcyB0aGUgZ2l2ZW4gX2tleV8gZnJvbSBtZW1jYWNoZS4gVGhlIG9wZXJhdGlvbiBvbmx5IHN1Y2NlZWRzXG4gICAqIGlmIHRoZSBrZXkgaXMgYWxyZWFkeSBwcmVzZW50LlxuICAgKi9cbiAgYXN5bmMgZGVsZXRlKGtleTogc3RyaW5nKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgLy8gVE9ETzogU3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKDQsIGtleSwgXCJcIiwgXCJcIiwgdGhpcy5zZXEpO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuXG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfTk9UX0ZPVU5EOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiREVMRVRFXCIsIHJlc3BvbnNlPy5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogSW5jcmVtZW50cyB0aGUgZ2l2ZW4gX2tleV8gaW4gbWVtY2FjaGUuXG4gICAqL1xuICBhc3luYyBpbmNyZW1lbnQoXG4gICAga2V5OiBzdHJpbmcsXG4gICAgYW1vdW50OiBudW1iZXIsXG4gICAgb3B0aW9ucz86IHsgaW5pdGlhbD86IG51bWJlcjsgZXhwaXJlcz86IG51bWJlciB9XG4gICk6IFByb21pc2U8eyB2YWx1ZTogbnVtYmVyIHwgbnVsbDsgc3VjY2VzczogYm9vbGVhbiB8IG51bGwgfT4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IGluaXRpYWwgPSBvcHRpb25zPy5pbml0aWFsIHx8IDA7XG4gICAgY29uc3QgZXhwaXJlcyA9IG9wdGlvbnM/LmV4cGlyZXMgfHwgdGhpcy5vcHRpb25zLmV4cGlyZXM7XG4gICAgY29uc3QgZXh0cmFzID0gbWFrZUFtb3VudEluaXRpYWxBbmRFeHBpcmF0aW9uKGFtb3VudCwgaW5pdGlhbCwgZXhwaXJlcyk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKFxuICAgICAgY29uc3RhbnRzLk9QX0lOQ1JFTUVOVCxcbiAgICAgIGtleSxcbiAgICAgIGV4dHJhcyxcbiAgICAgIFwiXCIsXG4gICAgICB0aGlzLnNlcVxuICAgICk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIGNvbnN0IGJ1ZkludCA9XG4gICAgICAgICAgKHJlc3BvbnNlLnZhbC5yZWFkVUludDMyQkUoMCkgPDwgOCkgKyByZXNwb25zZS52YWwucmVhZFVJbnQzMkJFKDQpO1xuICAgICAgICByZXR1cm4geyB2YWx1ZTogYnVmSW50LCBzdWNjZXNzOiB0cnVlIH07XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiSU5DUkVNRU5UXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBEZWNyZW1lbnRzIHRoZSBnaXZlbiBga2V5YCBpbiBtZW1jYWNoZS5cbiAgICovXG4gIGFzeW5jIGRlY3JlbWVudChcbiAgICBrZXk6IHN0cmluZyxcbiAgICBhbW91bnQ6IG51bWJlcixcbiAgICBvcHRpb25zOiB7IGluaXRpYWw/OiBudW1iZXI7IGV4cGlyZXM/OiBudW1iZXIgfVxuICApOiBQcm9taXNlPHsgdmFsdWU6IG51bWJlciB8IG51bGw7IHN1Y2Nlc3M6IGJvb2xlYW4gfCBudWxsIH0+IHtcbiAgICAvLyBUT0RPOiBzdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBpbml0aWFsID0gb3B0aW9ucy5pbml0aWFsIHx8IDA7XG4gICAgY29uc3QgZXhwaXJlcyA9IG9wdGlvbnMuZXhwaXJlcyB8fCB0aGlzLm9wdGlvbnMuZXhwaXJlcztcbiAgICBjb25zdCBleHRyYXMgPSBtYWtlQW1vdW50SW5pdGlhbEFuZEV4cGlyYXRpb24oYW1vdW50LCBpbml0aWFsLCBleHBpcmVzKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICBjb25zdGFudHMuT1BfREVDUkVNRU5ULFxuICAgICAga2V5LFxuICAgICAgZXh0cmFzLFxuICAgICAgXCJcIixcbiAgICAgIHRoaXMuc2VxXG4gICAgKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgY29uc3QgYnVmSW50ID1cbiAgICAgICAgICAocmVzcG9uc2UudmFsLnJlYWRVSW50MzJCRSgwKSA8PCA4KSArIHJlc3BvbnNlLnZhbC5yZWFkVUludDMyQkUoNCk7XG4gICAgICAgIHJldHVybiB7IHZhbHVlOiBidWZJbnQsIHN1Y2Nlc3M6IHRydWUgfTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJERUNSRU1FTlRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEFwcGVuZCB0aGUgZ2l2ZW4gX3ZhbHVlXyB0byB0aGUgdmFsdWUgYXNzb2NpYXRlZCB3aXRoIHRoZSBnaXZlbiBfa2V5XyBpblxuICAgKiBtZW1jYWNoZS4gVGhlIG9wZXJhdGlvbiBvbmx5IHN1Y2NlZWRzIGlmIHRoZSBrZXkgaXMgYWxyZWFkeSBwcmVzZW50LlxuICAgKi9cbiAgYXN5bmMgYXBwZW5kKGtleTogc3RyaW5nLCB2YWx1ZTogVmFsdWUpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAvLyBUT0RPOiBzdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBvcGNvZGU6IGNvbnN0YW50cy5PUCA9IGNvbnN0YW50cy5PUF9BUFBFTkQ7XG4gICAgY29uc3Qgc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5zZXJpYWxpemUob3Bjb2RlLCB2YWx1ZSwgXCJcIik7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKFxuICAgICAgb3Bjb2RlLFxuICAgICAga2V5LFxuICAgICAgc2VyaWFsaXplZC5leHRyYXMsXG4gICAgICBzZXJpYWxpemVkLnZhbHVlLFxuICAgICAgdGhpcy5zZXFcbiAgICApO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuS0VZX05PVF9GT1VORDpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIkFQUEVORFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUHJlcGVuZCB0aGUgZ2l2ZW4gX3ZhbHVlXyB0byB0aGUgdmFsdWUgYXNzb2NpYXRlZCB3aXRoIHRoZSBnaXZlbiBfa2V5XyBpblxuICAgKiBtZW1jYWNoZS4gVGhlIG9wZXJhdGlvbiBvbmx5IHN1Y2NlZWRzIGlmIHRoZSBrZXkgaXMgYWxyZWFkeSBwcmVzZW50LlxuICAgKi9cbiAgYXN5bmMgcHJlcGVuZChrZXk6IHN0cmluZywgdmFsdWU6IFZhbHVlKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgLy8gVE9ETzogc3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3Qgb3Bjb2RlOiBjb25zdGFudHMuT1AgPSBjb25zdGFudHMuT1BfUFJFUEVORDtcbiAgICBjb25zdCBzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLnNlcmlhbGl6ZShvcGNvZGUsIHZhbHVlLCBcIlwiKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICBvcGNvZGUsXG4gICAgICBrZXksXG4gICAgICBzZXJpYWxpemVkLmV4dHJhcyxcbiAgICAgIHNlcmlhbGl6ZWQudmFsdWUsXG4gICAgICB0aGlzLnNlcVxuICAgICk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfTk9UX0ZPVU5EOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiUFJFUEVORFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVG91Y2ggc2V0cyBhbiBleHBpcmF0aW9uIHZhbHVlLCBnaXZlbiBieSBfZXhwaXJlc18sIG9uIHRoZSBnaXZlbiBfa2V5XyBpblxuICAgKiBtZW1jYWNoZS4gVGhlIG9wZXJhdGlvbiBvbmx5IHN1Y2NlZWRzIGlmIHRoZSBrZXkgaXMgYWxyZWFkeSBwcmVzZW50LlxuICAgKi9cbiAgYXN5bmMgdG91Y2goa2V5OiBzdHJpbmcsIGV4cGlyZXM6IG51bWJlcik6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IGV4dHJhcyA9IG1ha2VFeHBpcmF0aW9uKGV4cGlyZXMgfHwgdGhpcy5vcHRpb25zLmV4cGlyZXMpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcigweDFjLCBrZXksIGV4dHJhcywgXCJcIiwgdGhpcy5zZXEpO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuS0VZX05PVF9GT1VORDpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIlRPVUNIXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBGTFVTSFxuICAgKlxuICAgKiBGbHVzaGVzIHRoZSBjYWNoZSBvbiBlYWNoIGNvbm5lY3RlZCBzZXJ2ZXIuIFRoZSBjYWxsYmFjayBzaWduYXR1cmUgaXM6XG4gICAqXG4gICAqICAgICBjYWxsYmFjayhsYXN0RXJyLCByZXN1bHRzKVxuICAgKlxuICAgKiB3aGVyZSBfbGFzdEVycl8gaXMgdGhlIGxhc3QgZXJyb3IgZW5jb3VudGVyZWQgKG9yIG51bGwsIGluIHRoZSBjb21tb24gY2FzZVxuICAgKiBvZiBubyBlcnJvcnMpLiBfcmVzdWx0c18gaXMgYSBkaWN0aW9uYXJ5IG1hcHBpbmcgYFwiaG9zdG5hbWU6cG9ydFwiYCB0byBlaXRoZXJcbiAgICogYHRydWVgIChpZiB0aGUgb3BlcmF0aW9uIHdhcyBzdWNjZXNzZnVsKSwgb3IgYW4gZXJyb3IuXG4gICAqIEBwYXJhbSBjYWxsYmFja1xuICAgKi9cbiAgZmx1c2goKTogUHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBib29sZWFuIHwgRXJyb3I+PjtcbiAgZmx1c2goXG4gICAgY2FsbGJhY2s6IChcbiAgICAgIGVycjogRXJyb3IgfCBudWxsLFxuICAgICAgcmVzdWx0czogUmVjb3JkPHN0cmluZywgYm9vbGVhbiB8IEVycm9yPlxuICAgICkgPT4gdm9pZFxuICApOiB2b2lkO1xuICBmbHVzaChcbiAgICBjYWxsYmFjaz86IChcbiAgICAgIGVycjogRXJyb3IgfCBudWxsLFxuICAgICAgcmVzdWx0czogUmVjb3JkPHN0cmluZywgYm9vbGVhbiB8IEVycm9yPlxuICAgICkgPT4gdm9pZFxuICApIHtcbiAgICBpZiAoY2FsbGJhY2sgPT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuIHByb21pc2lmeSgoY2FsbGJhY2spID0+IHtcbiAgICAgICAgdGhpcy5mbHVzaChmdW5jdGlvbiAoZXJyLCByZXN1bHRzKSB7XG4gICAgICAgICAgY2FsbGJhY2soZXJyLCByZXN1bHRzKTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9XG4gICAgLy8gVE9ETzogc3VwcG9ydCBleHBpcmF0aW9uXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKDB4MDgsIFwiXCIsIFwiXCIsIFwiXCIsIHRoaXMuc2VxKTtcbiAgICBsZXQgY291bnQgPSB0aGlzLnNlcnZlcnMubGVuZ3RoO1xuICAgIGNvbnN0IHJlc3VsdDogUmVjb3JkPHN0cmluZywgYm9vbGVhbiB8IEVycm9yPiA9IHt9O1xuICAgIGxldCBsYXN0RXJyOiBFcnJvciB8IG51bGwgPSBudWxsO1xuXG4gICAgY29uc3QgaGFuZGxlRmx1c2ggPSBmdW5jdGlvbiAoc2VxOiBudW1iZXIsIHNlcnY6IFNlcnZlcikge1xuICAgICAgc2Vydi5vblJlc3BvbnNlKHNlcSwgZnVuY3Rpb24gKC8qIHJlc3BvbnNlICovKSB7XG4gICAgICAgIGNvdW50IC09IDE7XG4gICAgICAgIHJlc3VsdFtzZXJ2Lmhvc3Rwb3J0U3RyaW5nKCldID0gdHJ1ZTtcbiAgICAgICAgaWYgKGNhbGxiYWNrICYmIGNvdW50ID09PSAwKSB7XG4gICAgICAgICAgY2FsbGJhY2sobGFzdEVyciwgcmVzdWx0KTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICBzZXJ2Lm9uRXJyb3Ioc2VxLCBmdW5jdGlvbiAoZXJyKSB7XG4gICAgICAgIGNvdW50IC09IDE7XG4gICAgICAgIGxhc3RFcnIgPSBlcnI7XG4gICAgICAgIHJlc3VsdFtzZXJ2Lmhvc3Rwb3J0U3RyaW5nKCldID0gZXJyO1xuICAgICAgICBpZiAoY2FsbGJhY2sgJiYgY291bnQgPT09IDApIHtcbiAgICAgICAgICBjYWxsYmFjayhsYXN0RXJyLCByZXN1bHQpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHNlcnYud3JpdGUocmVxdWVzdCk7XG4gICAgfTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5zZXJ2ZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBoYW5kbGVGbHVzaCh0aGlzLnNlcSwgdGhpcy5zZXJ2ZXJzW2ldKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU1RBVFNfV0lUSF9LRVlcbiAgICpcbiAgICogU2VuZHMgYSBtZW1jYWNoZSBzdGF0cyBjb21tYW5kIHdpdGggYSBrZXkgdG8gZWFjaCBjb25uZWN0ZWQgc2VydmVyLiBUaGVcbiAgICogY2FsbGJhY2sgaXMgaW52b2tlZCAqKk9OQ0UgUEVSIFNFUlZFUioqIGFuZCBoYXMgdGhlIHNpZ25hdHVyZTpcbiAgICpcbiAgICogICAgIGNhbGxiYWNrKGVyciwgc2VydmVyLCBzdGF0cylcbiAgICpcbiAgICogX3NlcnZlcl8gaXMgdGhlIGBcImhvc3RuYW1lOnBvcnRcImAgb2YgdGhlIHNlcnZlciwgYW5kIF9zdGF0c18gaXMgYSBkaWN0aW9uYXJ5XG4gICAqIG1hcHBpbmcgdGhlIHN0YXQgbmFtZSB0byB0aGUgdmFsdWUgb2YgdGhlIHN0YXRpc3RpYyBhcyBhIHN0cmluZy5cbiAgICogQHBhcmFtIGtleVxuICAgKiBAcGFyYW0gY2FsbGJhY2tcbiAgICovXG4gIHN0YXRzV2l0aEtleShcbiAgICBrZXk6IHN0cmluZyxcbiAgICBjYWxsYmFjaz86IChcbiAgICAgIGVycjogRXJyb3IgfCBudWxsLFxuICAgICAgc2VydmVyOiBzdHJpbmcsXG4gICAgICBzdGF0czogUmVjb3JkPHN0cmluZywgc3RyaW5nPiB8IG51bGxcbiAgICApID0+IHZvaWRcbiAgKTogdm9pZCB7XG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKDB4MTAsIGtleSwgXCJcIiwgXCJcIiwgdGhpcy5zZXEpO1xuXG4gICAgY29uc3QgaGFuZGxlU3RhdHMgPSAoc2VxOiBudW1iZXIsIHNlcnY6IFNlcnZlcikgPT4ge1xuICAgICAgY29uc3QgcmVzdWx0OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge307XG4gICAgICBjb25zdCBoYW5kbGU6IE9uUmVzcG9uc2VDYWxsYmFjayA9IChyZXNwb25zZSkgPT4ge1xuICAgICAgICAvLyBlbmQgb2Ygc3RhdCByZXNwb25zZXNcbiAgICAgICAgaWYgKHJlc3BvbnNlLmhlYWRlci50b3RhbEJvZHlMZW5ndGggPT09IDApIHtcbiAgICAgICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKG51bGwsIHNlcnYuaG9zdHBvcnRTdHJpbmcoKSwgcmVzdWx0KTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIC8vIHByb2Nlc3Mgc2luZ2xlIHN0YXQgbGluZSByZXNwb25zZVxuICAgICAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgICAgICByZXN1bHRbcmVzcG9uc2Uua2V5LnRvU3RyaW5nKCldID0gcmVzcG9uc2UudmFsLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgY29uc3QgZXJyb3IgPSB0aGlzLmhhbmRsZVJlc3BvbnNlRXJyb3IoXG4gICAgICAgICAgICAgIGBTVEFUUyAoJHtrZXl9KWAsXG4gICAgICAgICAgICAgIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMsXG4gICAgICAgICAgICAgIHVuZGVmaW5lZFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgICAgICBjYWxsYmFjayhlcnJvciwgc2Vydi5ob3N0cG9ydFN0cmluZygpLCBudWxsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfTtcbiAgICAgIGhhbmRsZS5xdWlldCA9IHRydWU7XG5cbiAgICAgIHNlcnYub25SZXNwb25zZShzZXEsIGhhbmRsZSk7XG4gICAgICBzZXJ2Lm9uRXJyb3Ioc2VxLCBmdW5jdGlvbiAoZXJyKSB7XG4gICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgIGNhbGxiYWNrKGVyciwgc2Vydi5ob3N0cG9ydFN0cmluZygpLCBudWxsKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICBzZXJ2LndyaXRlKHJlcXVlc3QpO1xuICAgIH07XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuc2VydmVycy5sZW5ndGg7IGkrKykge1xuICAgICAgaGFuZGxlU3RhdHModGhpcy5zZXEsIHRoaXMuc2VydmVyc1tpXSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNUQVRTXG4gICAqXG4gICAqIEZldGNoZXMgbWVtY2FjaGUgc3RhdHMgZnJvbSBlYWNoIGNvbm5lY3RlZCBzZXJ2ZXIuIFRoZSBjYWxsYmFjayBpcyBpbnZva2VkXG4gICAqICoqT05DRSBQRVIgU0VSVkVSKiogYW5kIGhhcyB0aGUgc2lnbmF0dXJlOlxuICAgKlxuICAgKiAgICAgY2FsbGJhY2soZXJyLCBzZXJ2ZXIsIHN0YXRzKVxuICAgKlxuICAgKiBfc2VydmVyXyBpcyB0aGUgYFwiaG9zdG5hbWU6cG9ydFwiYCBvZiB0aGUgc2VydmVyLCBhbmQgX3N0YXRzXyBpcyBhXG4gICAqIGRpY3Rpb25hcnkgbWFwcGluZyB0aGUgc3RhdCBuYW1lIHRvIHRoZSB2YWx1ZSBvZiB0aGUgc3RhdGlzdGljIGFzIGEgc3RyaW5nLlxuICAgKiBAcGFyYW0gY2FsbGJhY2tcbiAgICovXG4gIHN0YXRzKFxuICAgIGNhbGxiYWNrPzogKFxuICAgICAgZXJyOiBFcnJvciB8IG51bGwsXG4gICAgICBzZXJ2ZXI6IHN0cmluZyxcbiAgICAgIHN0YXRzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+IHwgbnVsbFxuICAgICkgPT4gdm9pZFxuICApOiB2b2lkIHtcbiAgICB0aGlzLnN0YXRzV2l0aEtleShcIlwiLCBjYWxsYmFjayk7XG4gIH1cblxuICAvKipcbiAgICogUkVTRVRfU1RBVFNcbiAgICpcbiAgICogUmVzZXQgdGhlIHN0YXRpc3RpY3MgZWFjaCBzZXJ2ZXIgaXMga2VlcGluZyBiYWNrIHRvIHplcm8uIFRoaXMgZG9lc24ndCBjbGVhclxuICAgKiBzdGF0cyBzdWNoIGFzIGl0ZW0gY291bnQsIGJ1dCB0ZW1wb3Jhcnkgc3RhdHMgc3VjaCBhcyB0b3RhbCBudW1iZXIgb2ZcbiAgICogY29ubmVjdGlvbnMgb3ZlciB0aW1lLlxuICAgKlxuICAgKiBUaGUgY2FsbGJhY2sgaXMgaW52b2tlZCAqKk9OQ0UgUEVSIFNFUlZFUioqIGFuZCBoYXMgdGhlIHNpZ25hdHVyZTpcbiAgICpcbiAgICogICAgIGNhbGxiYWNrKGVyciwgc2VydmVyKVxuICAgKlxuICAgKiBfc2VydmVyXyBpcyB0aGUgYFwiaG9zdG5hbWU6cG9ydFwiYCBvZiB0aGUgc2VydmVyLlxuICAgKiBAcGFyYW0gY2FsbGJhY2tcbiAgICovXG4gIHJlc2V0U3RhdHMoXG4gICAgY2FsbGJhY2s/OiAoXG4gICAgICBlcnI6IEVycm9yIHwgbnVsbCxcbiAgICAgIHNlcnZlcjogc3RyaW5nLFxuICAgICAgc3RhdHM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gfCBudWxsXG4gICAgKSA9PiB2b2lkXG4gICk6IHZvaWQge1xuICAgIHRoaXMuc3RhdHNXaXRoS2V5KFwicmVzZXRcIiwgY2FsbGJhY2spO1xuICB9XG5cbiAgLyoqXG4gICAqIFFVSVRcbiAgICpcbiAgICogQ2xvc2VzIHRoZSBjb25uZWN0aW9uIHRvIGVhY2ggc2VydmVyLCBub3RpZnlpbmcgdGhlbSBvZiB0aGlzIGludGVudGlvbi4gTm90ZVxuICAgKiB0aGF0IHF1aXQgY2FuIHJhY2UgYWdhaW5zdCBhbHJlYWR5IG91dHN0YW5kaW5nIHJlcXVlc3RzIHdoZW4gdGhvc2UgcmVxdWVzdHNcbiAgICogZmFpbCBhbmQgYXJlIHJldHJpZWQsIGxlYWRpbmcgdG8gdGhlIHF1aXQgY29tbWFuZCB3aW5uaW5nIGFuZCBjbG9zaW5nIHRoZVxuICAgKiBjb25uZWN0aW9uIGJlZm9yZSB0aGUgcmV0cmllcyBjb21wbGV0ZS5cbiAgICovXG4gIHF1aXQoKSB7XG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgLy8gVE9ETzogTmljZXIgcGVyaGFwcyB0byBkbyBRVUlUUSAoMHgxNykgYnV0IG5lZWQgYSBuZXcgY2FsbGJhY2sgZm9yIHdoZW5cbiAgICAvLyB3cml0ZSBpcyBkb25lLlxuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcigweDA3LCBcIlwiLCBcIlwiLCBcIlwiLCB0aGlzLnNlcSk7IC8vIFFVSVRcbiAgICBsZXQgc2VydjtcblxuICAgIGNvbnN0IGhhbmRsZVF1aXQgPSBmdW5jdGlvbiAoc2VxOiBudW1iZXIsIHNlcnY6IFNlcnZlcikge1xuICAgICAgc2Vydi5vblJlc3BvbnNlKHNlcSwgZnVuY3Rpb24gKC8qIHJlc3BvbnNlICovKSB7XG4gICAgICAgIHNlcnYuY2xvc2UoKTtcbiAgICAgIH0pO1xuICAgICAgc2Vydi5vbkVycm9yKHNlcSwgZnVuY3Rpb24gKC8qIGVyciAqLykge1xuICAgICAgICBzZXJ2LmNsb3NlKCk7XG4gICAgICB9KTtcbiAgICAgIHNlcnYud3JpdGUocmVxdWVzdCk7XG4gICAgfTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5zZXJ2ZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBzZXJ2ID0gdGhpcy5zZXJ2ZXJzW2ldO1xuICAgICAgaGFuZGxlUXVpdCh0aGlzLnNlcSwgc2Vydik7XG4gICAgfVxuICB9XG5cbiAgX3ZlcnNpb24oc2VydmVyOiBTZXJ2ZXIpOiBQcm9taXNlPHsgdmFsdWU6IFZhbHVlIHwgbnVsbCB9PiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIHRoaXMuaW5jclNlcSgpO1xuICAgICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKFxuICAgICAgICBjb25zdGFudHMuT1BfVkVSU0lPTixcbiAgICAgICAgXCJcIixcbiAgICAgICAgXCJcIixcbiAgICAgICAgXCJcIixcbiAgICAgICAgdGhpcy5zZXFcbiAgICAgICk7XG4gICAgICB0aGlzLnBlcmZvcm1PblNlcnZlcihzZXJ2ZXIsIHJlcXVlc3QsIHRoaXMuc2VxLCAoZXJyLCByZXNwb25zZSkgPT4ge1xuICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgcmV0dXJuIHJlamVjdChlcnIpO1xuICAgICAgICB9XG5cbiAgICAgICAgc3dpdGNoIChyZXNwb25zZSEuaGVhZGVyLnN0YXR1cykge1xuICAgICAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgICAgIC8qIFRPRE86IHRoaXMgaXMgYnVnZ2VkLCB3ZSBzaG91bGQndCB1c2UgdGhlIGRlc2VyaWFsaXplciBoZXJlLCBzaW5jZSB2ZXJzaW9uIGFsd2F5cyByZXR1cm5zIGEgdmVyc2lvbiBzdHJpbmcuXG4gICAgICAgICAgICAgVGhlIGRlc2VyaWFsaXplciBzaG91bGQgb25seSBiZSB1c2VkIG9uIHVzZXIga2V5IGRhdGEuICovXG4gICAgICAgICAgICBjb25zdCBkZXNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuZGVzZXJpYWxpemUoXG4gICAgICAgICAgICAgIHJlc3BvbnNlIS5oZWFkZXIub3Bjb2RlLFxuICAgICAgICAgICAgICByZXNwb25zZSEudmFsLFxuICAgICAgICAgICAgICByZXNwb25zZSEuZXh0cmFzXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgcmV0dXJuIHJlc29sdmUoeyB2YWx1ZTogZGVzZXJpYWxpemVkLnZhbHVlIH0pO1xuICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICByZXR1cm4gcmVqZWN0KFxuICAgICAgICAgICAgICB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiVkVSU0lPTlwiLCByZXNwb25zZSEuaGVhZGVyLnN0YXR1cylcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlcXVlc3QgdGhlIHNlcnZlciB2ZXJzaW9uIGZyb20gdGhlIFwiZmlyc3RcIiBzZXJ2ZXIgaW4gdGhlIGJhY2tlbmQgcG9vbC5cbiAgICogVGhlIHNlcnZlciByZXNwb25kcyB3aXRoIGEgcGFja2V0IGNvbnRhaW5pbmcgdGhlIHZlcnNpb24gc3RyaW5nIGluIHRoZSBib2R5IHdpdGggdGhlIGZvbGxvd2luZyBmb3JtYXQ6IFwieC55LnpcIlxuICAgKi9cbiAgdmVyc2lvbigpOiBQcm9taXNlPHsgdmFsdWU6IFZhbHVlIHwgbnVsbCB9PiB7XG4gICAgY29uc3Qgc2VydmVyID0gdGhpcy5zZXJ2ZXJLZXlUb1NlcnZlcih0aGlzLnNlcnZlcktleXNbMF0pO1xuICAgIHJldHVybiB0aGlzLl92ZXJzaW9uKHNlcnZlcik7XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldmVzIHRoZSBzZXJ2ZXIgdmVyc2lvbiBmcm9tIGFsbCB0aGUgc2VydmVyc1xuICAgKiBpbiB0aGUgYmFja2VuZCBwb29sLCBlcnJvcnMgaWYgYW55IG9uZSBvZiB0aGVtIGhhcyBhblxuICAgKiBlcnJvclxuICAgKi9cbiAgYXN5bmMgdmVyc2lvbkFsbCgpOiBQcm9taXNlPHtcbiAgICB2YWx1ZXM6IFJlY29yZDxzdHJpbmcsIFZhbHVlIHwgbnVsbD47XG4gIH0+IHtcbiAgICBjb25zdCB2ZXJzaW9uT2JqZWN0cyA9IGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgdGhpcy5zZXJ2ZXJLZXlzLm1hcCgoc2VydmVyS2V5KSA9PiB7XG4gICAgICAgIGNvbnN0IHNlcnZlciA9IHRoaXMuc2VydmVyS2V5VG9TZXJ2ZXIoc2VydmVyS2V5KTtcblxuICAgICAgICByZXR1cm4gdGhpcy5fdmVyc2lvbihzZXJ2ZXIpLnRoZW4oKHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgcmV0dXJuIHsgc2VydmVyS2V5OiBzZXJ2ZXJLZXksIHZhbHVlOiByZXNwb25zZS52YWx1ZSB9O1xuICAgICAgICB9KTtcbiAgICAgIH0pXG4gICAgKTtcbiAgICBjb25zdCB2YWx1ZXMgPSB2ZXJzaW9uT2JqZWN0cy5yZWR1Y2UoKGFjY3VtdWxhdG9yLCB2ZXJzaW9uT2JqZWN0KSA9PiB7XG4gICAgICBhY2N1bXVsYXRvclt2ZXJzaW9uT2JqZWN0LnNlcnZlcktleV0gPSB2ZXJzaW9uT2JqZWN0LnZhbHVlO1xuICAgICAgcmV0dXJuIGFjY3VtdWxhdG9yO1xuICAgIH0sIHt9IGFzIFJlY29yZDxzdHJpbmcsIFZhbHVlIHwgbnVsbD4pO1xuICAgIHJldHVybiB7IHZhbHVlczogdmFsdWVzIH07XG4gIH1cblxuICAvKipcbiAgICogQ2xvc2VzIChhYnJ1cHRseSkgY29ubmVjdGlvbnMgdG8gYWxsIHRoZSBzZXJ2ZXJzLlxuICAgKiBAc2VlIHRoaXMucXVpdFxuICAgKi9cbiAgY2xvc2UoKSB7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnNlcnZlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHRoaXMuc2VydmVyc1tpXS5jbG9zZSgpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBQZXJmb3JtIGEgZ2VuZXJpYyBzaW5nbGUgcmVzcG9uc2Ugb3BlcmF0aW9uIChnZXQsIHNldCBldGMpIG9uIG9uZSBzZXJ2ZXJcbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IGtleSB0aGUga2V5IHRvIGhhc2ggdG8gZ2V0IGEgc2VydmVyIGZyb20gdGhlIHBvb2xcbiAgICogQHBhcmFtIHtidWZmZXJ9IHJlcXVlc3QgYSBidWZmZXIgY29udGFpbmluZyB0aGUgcmVxdWVzdFxuICAgKiBAcGFyYW0ge251bWJlcn0gc2VxIHRoZSBzZXF1ZW5jZSBudW1iZXIgb2YgdGhlIG9wZXJhdGlvbi4gSXQgaXMgdXNlZCB0byBwaW4gdGhlIGNhbGxiYWNrc1xuICAgICAgICAgICAgICAgICAgICAgICAgIHRvIGEgc3BlY2lmaWMgb3BlcmF0aW9uIGFuZCBzaG91bGQgbmV2ZXIgY2hhbmdlIGR1cmluZyBhIGBwZXJmb3JtYC5cbiAgICogQHBhcmFtIHtudW1iZXI/fSByZXRyaWVzIG51bWJlciBvZiB0aW1lcyB0byByZXRyeSByZXF1ZXN0IG9uIGZhaWx1cmVcbiAgICovXG4gIHBlcmZvcm0oXG4gICAga2V5OiBzdHJpbmcsXG4gICAgcmVxdWVzdDogQnVmZmVyLFxuICAgIHNlcTogbnVtYmVyLFxuICAgIHJldHJpZXM/OiBudW1iZXJcbiAgKTogUHJvbWlzZTxNZXNzYWdlPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGNvbnN0IHNlcnZlcktleSA9IHRoaXMubG9va3VwS2V5VG9TZXJ2ZXJLZXkoa2V5KTtcbiAgICAgIGNvbnN0IHNlcnZlciA9IHRoaXMuc2VydmVyS2V5VG9TZXJ2ZXIoc2VydmVyS2V5KTtcblxuICAgICAgaWYgKCFzZXJ2ZXIpIHtcbiAgICAgICAgcmV0dXJuIHJlamVjdChuZXcgRXJyb3IoXCJObyBzZXJ2ZXJzIGF2YWlsYWJsZVwiKSk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMucGVyZm9ybU9uU2VydmVyKFxuICAgICAgICBzZXJ2ZXIsXG4gICAgICAgIHJlcXVlc3QsXG4gICAgICAgIHNlcSxcbiAgICAgICAgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgcmV0dXJuIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJlc29sdmUocmVzcG9uc2UhKTtcbiAgICAgICAgfSxcbiAgICAgICAgcmV0cmllc1xuICAgICAgKTtcbiAgICB9KTtcbiAgfVxuXG4gIHBlcmZvcm1PblNlcnZlcihcbiAgICBzZXJ2ZXI6IFNlcnZlcixcbiAgICByZXF1ZXN0OiBCdWZmZXIsXG4gICAgc2VxOiBudW1iZXIsXG4gICAgY2FsbGJhY2s6IFJlc3BvbnNlT3JFcnJvckNhbGxiYWNrLFxuICAgIHJldHJpZXM6IG51bWJlciA9IDBcbiAgKSB7XG4gICAgY29uc3QgX3RoaXMgPSB0aGlzO1xuXG4gICAgcmV0cmllcyA9IHJldHJpZXMgfHwgdGhpcy5vcHRpb25zLnJldHJpZXM7XG4gICAgY29uc3Qgb3JpZ1JldHJpZXMgPSB0aGlzLm9wdGlvbnMucmV0cmllcztcbiAgICBjb25zdCBsb2dnZXIgPSB0aGlzLm9wdGlvbnMubG9nZ2VyO1xuICAgIGNvbnN0IHJldHJ5X2RlbGF5ID0gdGhpcy5vcHRpb25zLnJldHJ5X2RlbGF5O1xuXG4gICAgY29uc3QgcmVzcG9uc2VIYW5kbGVyOiBPblJlc3BvbnNlQ2FsbGJhY2sgPSBmdW5jdGlvbiAocmVzcG9uc2UpIHtcbiAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICBjYWxsYmFjayhudWxsLCByZXNwb25zZSk7XG4gICAgICB9XG4gICAgfTtcblxuICAgIGNvbnN0IGVycm9ySGFuZGxlcjogT25FcnJvckNhbGxiYWNrID0gZnVuY3Rpb24gKGVycm9yKSB7XG4gICAgICBpZiAoLS1yZXRyaWVzID4gMCkge1xuICAgICAgICAvLyBXYWl0IGZvciByZXRyeV9kZWxheVxuICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICBfdGhpcy5wZXJmb3JtT25TZXJ2ZXIoc2VydmVyLCByZXF1ZXN0LCBzZXEsIGNhbGxiYWNrLCByZXRyaWVzKTtcbiAgICAgICAgfSwgMTAwMCAqIHJldHJ5X2RlbGF5KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGxvZ2dlci5sb2coXG4gICAgICAgICAgXCJNZW1KUzogU2VydmVyIDxcIiArXG4gICAgICAgICAgICBzZXJ2ZXIuaG9zdHBvcnRTdHJpbmcoKSArXG4gICAgICAgICAgICBcIj4gZmFpbGVkIGFmdGVyIChcIiArXG4gICAgICAgICAgICBvcmlnUmV0cmllcyArXG4gICAgICAgICAgICBcIikgcmV0cmllcyB3aXRoIGVycm9yIC0gXCIgK1xuICAgICAgICAgICAgZXJyb3IubWVzc2FnZVxuICAgICAgICApO1xuICAgICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgICBjYWxsYmFjayhlcnJvciwgbnVsbCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9O1xuXG4gICAgc2VydmVyLm9uUmVzcG9uc2Uoc2VxLCByZXNwb25zZUhhbmRsZXIpO1xuICAgIHNlcnZlci5vbkVycm9yKHNlcSwgZXJyb3JIYW5kbGVyKTtcbiAgICBzZXJ2ZXIud3JpdGUocmVxdWVzdCk7XG4gIH1cblxuICAvLyBJbmNyZW1lbnQgdGhlIHNlcSB2YWx1ZVxuICBpbmNyU2VxKCkge1xuICAgIHRoaXMuc2VxKys7XG5cbiAgICAvLyBXcmFwIGB0aGlzLnNlcWAgdG8gMzItYml0cyBzaW5jZSB0aGUgZmllbGQgd2UgZml0IGl0IGludG8gaXMgb25seSAzMi1iaXRzLlxuICAgIHRoaXMuc2VxICY9IDB4ZmZmZmZmZmY7XG4gIH1cblxuICBwcml2YXRlIGNyZWF0ZUFuZExvZ0Vycm9yKFxuICAgIGNvbW1hbmROYW1lOiBzdHJpbmcsXG4gICAgcmVzcG9uc2VTdGF0dXM6IFJlc3BvbnNlU3RhdHVzIHwgdW5kZWZpbmVkXG4gICk6IEVycm9yIHtcbiAgICBjb25zdCBlcnJvck1lc3NhZ2UgPSBgTWVtSlMgJHtjb21tYW5kTmFtZX06ICR7Y29uc3RhbnRzLnJlc3BvbnNlU3RhdHVzVG9TdHJpbmcoXG4gICAgICByZXNwb25zZVN0YXR1c1xuICAgICl9YDtcbiAgICB0aGlzLm9wdGlvbnMubG9nZ2VyLmxvZyhlcnJvck1lc3NhZ2UpO1xuICAgIHJldHVybiBuZXcgRXJyb3IoZXJyb3JNZXNzYWdlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBMb2cgYW4gZXJyb3IgdG8gdGhlIGxvZ2dlciwgdGhlbiByZXR1cm4gdGhlIGVycm9yLlxuICAgKiBJZiBhIGNhbGxiYWNrIGlzIGdpdmVuLCBjYWxsIGl0IHdpdGggY2FsbGJhY2soZXJyb3IsIG51bGwpLlxuICAgKi9cbiAgcHJpdmF0ZSBoYW5kbGVSZXNwb25zZUVycm9yKFxuICAgIGNvbW1hbmROYW1lOiBzdHJpbmcsXG4gICAgcmVzcG9uc2VTdGF0dXM6IFJlc3BvbnNlU3RhdHVzIHwgdW5kZWZpbmVkLFxuICAgIGNhbGxiYWNrOiB1bmRlZmluZWQgfCAoKGVycm9yOiBFcnJvciB8IG51bGwsIG90aGVyOiBudWxsKSA9PiB2b2lkKVxuICApOiBFcnJvciB7XG4gICAgY29uc3QgZXJyb3IgPSB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKGNvbW1hbmROYW1lLCByZXNwb25zZVN0YXR1cyk7XG4gICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICBjYWxsYmFjayhlcnJvciwgbnVsbCk7XG4gICAgfVxuICAgIHJldHVybiBlcnJvcjtcbiAgfVxufVxuXG5leHBvcnQgeyBDbGllbnQsIFNlcnZlciwgVXRpbHMsIEhlYWRlciB9O1xuIl19 \ No newline at end of file diff --git a/src/memjs/memjs.ts b/src/memjs/memjs.ts index cf67633..03c70c5 100644 --- a/src/memjs/memjs.ts +++ b/src/memjs/memjs.ts @@ -313,14 +313,23 @@ class Client { // This isn't technically needed here because the logic in server.js also checks if totalBodyLength === 0, but our unittests aren't great about setting that field, and also this makes it more explicit handle.quiet = false; resolve(responseMap); - } else { + } else if (response.header.opcode === constants.OP_GETK || response.header.opcode === constants.OP_GETKQ) { const deserialized = this.serializer.deserialize( response.header.opcode, response.val, response.extras ); const key = response.key.toString(); + if (key.length === 0) { + return reject( + new Error("Recieved empty key in getMulti: " + JSON.stringify(response)) + ); + } responseMap[key] = { ...deserialized, cas: response.header.cas }; + } else { + return reject( + new Error("Recieved response in getMulti for unknown opcode: " + JSON.stringify(response)) + ); } break; default: From 799b44b642bb952cfa775c893bae8f858cdb06ca Mon Sep 17 00:00:00 2001 From: David Blackman Date: Thu, 20 May 2021 11:35:33 -0400 Subject: [PATCH 60/79] Fix incr seq timing in get milti (#14) * error on some weird edge cases we are having trouble debugging * fix race in getMulti --- lib/memjs/memjs.d.ts | 4 ++-- lib/memjs/memjs.d.ts.map | 2 +- lib/memjs/memjs.js | 13 +++++++------ src/memjs/memjs.ts | 12 +++++++----- 4 files changed, 17 insertions(+), 14 deletions(-) diff --git a/lib/memjs/memjs.d.ts b/lib/memjs/memjs.d.ts index a300f96..764a387 100644 --- a/lib/memjs/memjs.d.ts +++ b/lib/memjs/memjs.d.ts @@ -118,7 +118,7 @@ declare class Client { * * cf https://github.com/couchbase/memcached/blob/master/docs/BinaryProtocol.md#0x0d-getkq-get-with-key-quietly */ - _buildGetMultiRequest(keys: string[]): Buffer; + _buildGetMultiRequest(keys: string[], seq: number): Buffer; /** Executing a pipelined (multi) get against a single server. This is a private implementation detail of getMulti. */ _getMultiToServer(serv: Server, keys: Keys[]): Promise>; /** @@ -292,7 +292,7 @@ declare class Client { */ perform(key: string, request: Buffer, seq: number, retries?: number): Promise; performOnServer(server: Server, request: Buffer, seq: number, callback: ResponseOrErrorCallback, retries?: number): void; - incrSeq(): void; + incrSeq(): number; private createAndLogError; /** * Log an error to the logger, then return the error. diff --git a/lib/memjs/memjs.d.ts.map b/lib/memjs/memjs.d.ts.map index 8001864..8a349b5 100644 --- a/lib/memjs/memjs.d.ts.map +++ b/lib/memjs/memjs.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"memjs.d.ts","sourceRoot":"","sources":["../../src/memjs/memjs.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"memjs.d.ts","sourceRoot":"","sources":["../../src/memjs/memjs.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/lib/memjs/memjs.js b/lib/memjs/memjs.js index 8ad45f0..9b3c435 100644 --- a/lib/memjs/memjs.js +++ b/lib/memjs/memjs.js @@ -170,7 +170,7 @@ class Client { * * cf https://github.com/couchbase/memcached/blob/master/docs/BinaryProtocol.md#0x0d-getkq-get-with-key-quietly */ - _buildGetMultiRequest(keys) { + _buildGetMultiRequest(keys, seq) { // start at 24 for the no-op command at the end let requestSize = 24; for (const keyIdx in keys) { @@ -180,9 +180,9 @@ class Client { let bytesWritten = 0; for (const keyIdx in keys) { const key = keys[keyIdx]; - bytesWritten += utils_1.copyIntoRequestBuffer(constants.OP_GETKQ, key, "", "", this.seq, request, bytesWritten); + bytesWritten += utils_1.copyIntoRequestBuffer(constants.OP_GETKQ, key, "", "", seq, request, bytesWritten); } - bytesWritten += utils_1.copyIntoRequestBuffer(constants.OP_NO_OP, "", "", "", this.seq, request, bytesWritten); + bytesWritten += utils_1.copyIntoRequestBuffer(constants.OP_NO_OP, "", "", "", seq, request, bytesWritten); return request; } /** Executing a pipelined (multi) get against a single server. This is a private implementation detail of getMulti. */ @@ -218,10 +218,10 @@ class Client { // This prevents the handler from being deleted // after the first response. Logic in server.js. handle.quiet = true; - const request = this._buildGetMultiRequest(keys); + const seq = this.incrSeq(); + const request = this._buildGetMultiRequest(keys, seq); serv.onResponse(this.seq, handle); serv.onError(this.seq, reject); - this.incrSeq(); serv.write(request); }); } @@ -712,6 +712,7 @@ class Client { this.seq++; // Wrap `this.seq` to 32-bits since the field we fit it into is only 32-bits. this.seq &= 0xffffffff; + return this.seq; } createAndLogError(commandName, responseStatus) { const errorMessage = `MemJS ${commandName}: ${constants.responseStatusToString(responseStatus)}`; @@ -731,4 +732,4 @@ class Client { } } exports.Client = Client; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVtanMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbWVtanMvbWVtanMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLHdCQUF3Qjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUV4QixxQ0FLa0I7QUE2aENELHVGQS9oQ2YsZUFBTSxPQStoQ2U7QUE1aEN2Qix1REFBK0Q7QUFDL0QsbUNBU2lCO0FBQ2pCLHVEQUF5QztBQUN6QywyQ0FBNkM7QUFDN0MsK0NBQWlDO0FBK2dDUixzQkFBSztBQTlnQzlCLGlEQUFtQztBQThnQ0gsd0JBQU07QUE1Z0N0QyxTQUFTLDhCQUE4QixDQUNyQyxPQUFpQixFQUNqQixHQUFXO0lBRVgsTUFBTSxLQUFLLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQztJQUM3QixNQUFNLEtBQUssR0FBRyxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxnQkFBUSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3BELE9BQU8sT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ3hCLENBQUM7QUFFRCwrQ0FBK0M7QUFDL0MsU0FBUyxTQUFTLENBQ2hCLE9BQTBFO0lBRTFFLE9BQU8sSUFBSSxPQUFPLENBQUMsVUFBVSxPQUFPLEVBQUUsTUFBTTtRQUMxQyxPQUFPLENBQUMsVUFBVSxHQUFHLEVBQUUsTUFBTTtZQUMzQixHQUFHLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3RDLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBNkRELE1BQU0sTUFBTTtJQVFWLDRFQUE0RTtJQUM1RSxtQ0FBbUM7SUFDbkMsWUFBWSxPQUFpQixFQUFFLE9BQTBDO1FBQ3ZFLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO1FBQ3ZCLElB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QW1CLENBQ3pCLFdBQW1CLEVBQ25CLGNBQTBDLEVBQzFDLFFBQWtFO1FBRWxFLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxXQUFXLEVBQUUsY0FBYyxDQUFDLENBQUM7UUFDbEUsSUFBSSxRQUFRLEVBQUU7WUFDWixRQUFRLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxDQUFDO1NBQ3ZCO1FBQ0QsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0NBQ0Y7QUFFUSx3QkFBTSIsInNvdXJjZXNDb250ZW50IjpbIi8vIE1lbVRTIE1lbWNhY2hlIENsaWVudFxuXG5pbXBvcnQge1xuICBPbkVycm9yQ2FsbGJhY2ssXG4gIE9uUmVzcG9uc2VDYWxsYmFjayxcbiAgU2VydmVyLFxuICBTZXJ2ZXJPcHRpb25zLFxufSBmcm9tIFwiLi9zZXJ2ZXJcIjtcbmltcG9ydCB7IG5vb3BTZXJpYWxpemVyLCBTZXJpYWxpemVyIH0gZnJvbSBcIi4vbm9vcC1zZXJpYWxpemVyXCI7XG5pbXBvcnQge1xuICBtYWtlUmVxdWVzdEJ1ZmZlcixcbiAgY29weUludG9SZXF1ZXN0QnVmZmVyLFxuICBtZXJnZSxcbiAgbWFrZUV4cGlyYXRpb24sXG4gIG1ha2VBbW91bnRJbml0aWFsQW5kRXhwaXJhdGlvbixcbiAgaGFzaENvZGUsXG4gIE1heWJlQnVmZmVyLFxuICBNZXNzYWdlLFxufSBmcm9tIFwiLi91dGlsc1wiO1xuaW1wb3J0ICogYXMgY29uc3RhbnRzIGZyb20gXCIuL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgUmVzcG9uc2VTdGF0dXMgfSBmcm9tIFwiLi9jb25zdGFudHNcIjtcbmltcG9ydCAqIGFzIFV0aWxzIGZyb20gXCIuL3V0aWxzXCI7XG5pbXBvcnQgKiBhcyBIZWFkZXIgZnJvbSBcIi4vaGVhZGVyXCI7XG5cbmZ1bmN0aW9uIGRlZmF1bHRLZXlUb1NlcnZlckhhc2hGdW5jdGlvbihcbiAgc2VydmVyczogc3RyaW5nW10sXG4gIGtleTogc3RyaW5nXG4pOiBzdHJpbmcge1xuICBjb25zdCB0b3RhbCA9IHNlcnZlcnMubGVuZ3RoO1xuICBjb25zdCBpbmRleCA9IHRvdGFsID4gMSA/IGhhc2hDb2RlKGtleSkgJSB0b3RhbCA6IDA7XG4gIHJldHVybiBzZXJ2ZXJzW2luZGV4XTtcbn1cblxuLy8gY29udmVydHMgYSBjYWxsIGludG8gYSBwcm9taXNlLXJldHVybmluZyBvbmVcbmZ1bmN0aW9uIHByb21pc2lmeTxSZXN1bHQ+KFxuICBjb21tYW5kOiAoY2FsbGJhY2s6IChlcnJvcjogRXJyb3IgfCBudWxsLCByZXN1bHQ6IFJlc3VsdCkgPT4gdm9pZCkgPT4gdm9pZFxuKTogUHJvbWlzZTxSZXN1bHQ+IHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICBjb21tYW5kKGZ1bmN0aW9uIChlcnIsIHJlc3VsdCkge1xuICAgICAgZXJyID8gcmVqZWN0KGVycikgOiByZXNvbHZlKHJlc3VsdCk7XG4gICAgfSk7XG4gIH0pO1xufVxuXG50eXBlIFJlc3BvbnNlT3JFcnJvckNhbGxiYWNrID0gKFxuICBlcnJvcjogRXJyb3IgfCBudWxsLFxuICByZXNwb25zZTogTWVzc2FnZSB8IG51bGxcbikgPT4gdm9pZDtcblxuaW50ZXJmYWNlIEJhc2VDbGllbnRPcHRpb25zIHtcbiAgcmV0cmllczogbnVtYmVyO1xuICByZXRyeV9kZWxheTogbnVtYmVyO1xuICBleHBpcmVzOiBudW1iZXI7XG4gIGxvZ2dlcjogeyBsb2c6IHR5cGVvZiBjb25zb2xlLmxvZyB9O1xuICBrZXlUb1NlcnZlckhhc2hGdW5jdGlvbjogdHlwZW9mIGRlZmF1bHRLZXlUb1NlcnZlckhhc2hGdW5jdGlvbjtcbn1cblxuaW50ZXJmYWNlIFNlcmlhbGl6ZXJQcm9wPFZhbHVlLCBFeHRyYXM+IHtcbiAgc2VyaWFsaXplcjogU2VyaWFsaXplcjxWYWx1ZSwgRXh0cmFzPjtcbn1cblxuLyoqXG4gKiBUaGUgY2xpZW50IGhhcyBwYXJ0aWFsIHN1cHBvcnQgZm9yIHNlcmlhbGl6aW5nIGFuZCBkZXNlcmlhbGl6aW5nIHZhbHVlcyBmcm9tIHRoZVxuICogQnVmZmVyIGJ5dGUgc3RyaW5ncyB3ZSByZWNpZXZlIGZyb20gdGhlIHdpcmUuIFRoZSBkZWZhdWx0IHNlcmlhbGl6ZXIgaXMgZm9yIE1heWJlQnVmZmVyLlxuICpcbiAqIElmIFZhbHVlIGFuZCBFeHRyYXMgYXJlIG9mIHR5cGUgQnVmZmVyLCB0aGVuIHJldHVybiB0eXBlIFdoZW5CdWZmZXIuIE90aGVyd2lzZSxcbiAqIHJldHVybiB0eXBlIE5vdEJ1ZmZlci5cbiAqL1xudHlwZSBJZkJ1ZmZlcjxcbiAgVmFsdWUsXG4gIEV4dHJhcyxcbiAgV2hlblZhbHVlQW5kRXh0cmFzQXJlQnVmZmVycyxcbiAgTm90QnVmZmVyXG4+ID0gVmFsdWUgZXh0ZW5kcyBCdWZmZXJcbiAgPyBFeHRyYXMgZXh0ZW5kcyBCdWZmZXJcbiAgICA/IFdoZW5WYWx1ZUFuZEV4dHJhc0FyZUJ1ZmZlcnNcbiAgICA6IE5vdEJ1ZmZlclxuICA6IE5vdEJ1ZmZlcjtcblxuZXhwb3J0IHR5cGUgR2l2ZW5DbGllbnRPcHRpb25zPFZhbHVlLCBFeHRyYXM+ID0gUGFydGlhbDxCYXNlQ2xpZW50T3B0aW9ucz4gJlxuICBJZkJ1ZmZlcjxcbiAgICBWYWx1ZSxcbiAgICBFeHRyYXMsXG4gICAgUGFydGlhbDxTZXJpYWxpemVyUHJvcDxWYWx1ZSwgRXh0cmFzPj4sXG4gICAgU2VyaWFsaXplclByb3A8VmFsdWUsIEV4dHJhcz5cbiAgPjtcblxuZXhwb3J0IHR5cGUgQ0FTVG9rZW4gPSBCdWZmZXI7XG5cbmV4cG9ydCBpbnRlcmZhY2UgR2V0UmVzdWx0PFZhbHVlID0gTWF5YmVCdWZmZXIsIEV4dHJhcyA9IE1heWJlQnVmZmVyPiB7XG4gIHZhbHVlOiBWYWx1ZTtcbiAgZXh0cmFzOiBFeHRyYXM7XG4gIGNhczogQ0FTVG9rZW4gfCB1bmRlZmluZWQ7XG59XG5cbmV4cG9ydCB0eXBlIEdldE11bHRpUmVzdWx0PFxuICBLZXlzIGV4dGVuZHMgc3RyaW5nID0gc3RyaW5nLFxuICBWYWx1ZSA9IE1heWJlQnVmZmVyLFxuICBFeHRyYXMgPSBNYXliZUJ1ZmZlclxuPiA9IHtcbiAgW0sgaW4gS2V5c10/OiBHZXRSZXN1bHQ8VmFsdWUsIEV4dHJhcz47XG59O1xuXG5jbGFzcyBDbGllbnQ8VmFsdWUgPSBNYXliZUJ1ZmZlciwgRXh0cmFzID0gTWF5YmVCdWZmZXI+IHtcbiAgc2VydmVyczogU2VydmVyW107XG4gIHNlcTogbnVtYmVyO1xuICBvcHRpb25zOiBCYXNlQ2xpZW50T3B0aW9ucyAmIFBhcnRpYWw8U2VyaWFsaXplclByb3A8VmFsdWUsIEV4dHJhcz4+O1xuICBzZXJpYWxpemVyOiBTZXJpYWxpemVyPFZhbHVlLCBFeHRyYXM+O1xuICBzZXJ2ZXJNYXA6IHsgW2hvc3Rwb3J0OiBzdHJpbmddOiBTZXJ2ZXIgfTtcbiAgc2VydmVyS2V5czogc3RyaW5nW107XG5cbiAgLy8gQ2xpZW50IGluaXRpYWxpemVyIHRha2VzIGEgbGlzdCBvZiBgU2VydmVyYHMgYW5kIGFuIGBvcHRpb25zYCBkaWN0aW9uYXJ5LlxuICAvLyBTZWUgYENsaWVudC5jcmVhdGVgIGZvciBkZXRhaWxzLlxuICBjb25zdHJ1Y3RvcihzZXJ2ZXJzOiBTZXJ2ZXJbXSwgb3B0aW9uczogR2l2ZW5DbGllbnRPcHRpb25zPFZhbHVlLCBFeHRyYXM+KSB7XG4gICAgdGhpcy5zZXJ2ZXJzID0gc2VydmVycztcbiAgICB0aGlzLnNlcSA9IDA7XG4gICAgdGhpcy5vcHRpb25zID0gbWVyZ2Uob3B0aW9ucyB8fCB7fSwge1xuICAgICAgcmV0cmllczogMixcbiAgICAgIHJldHJ5X2RlbGF5OiAwLjIsXG4gICAgICBleHBpcmVzOiAwLFxuICAgICAgbG9nZ2VyOiBjb25zb2xlLFxuICAgICAga2V5VG9TZXJ2ZXJIYXNoRnVuY3Rpb246IGRlZmF1bHRLZXlUb1NlcnZlckhhc2hGdW5jdGlvbixcbiAgICB9KTtcblxuICAgIHRoaXMuc2VyaWFsaXplciA9IHRoaXMub3B0aW9ucy5zZXJpYWxpemVyIHx8IChub29wU2VyaWFsaXplciBhcyBhbnkpO1xuXG4gICAgLy8gU3RvcmUgYSBtYXBwaW5nIGZyb20gaG9zdHBvcnQgLT4gc2VydmVyIHNvIHdlIGNhbiBxdWlja2x5IGdldCBhIHNlcnZlciBvYmplY3QgZnJvbSB0aGUgc2VydmVyS2V5IHJldHVybmVkIGJ5IHRoZSBoYXNoaW5nIGZ1bmN0aW9uXG4gICAgY29uc3Qgc2VydmVyTWFwOiB7IFtob3N0cG9ydDogc3RyaW5nXTogU2VydmVyIH0gPSB7fTtcbiAgICB0aGlzLnNlcnZlcnMuZm9yRWFjaChmdW5jdGlvbiAoc2VydmVyKSB7XG4gICAgICBzZXJ2ZXJNYXBbc2VydmVyLmhvc3Rwb3J0U3RyaW5nKCldID0gc2VydmVyO1xuICAgIH0pO1xuICAgIHRoaXMuc2VydmVyTWFwID0gc2VydmVyTWFwO1xuXG4gICAgLy8gc3RvcmUgYSBsaXN0IG9mIGFsbCBvdXIgc2VydmVyS2V5cyBzbyB3ZSBkb24ndCBuZWVkIHRvIGNvbnN0YW50bHkgcmVhbGxvY2F0ZSB0aGlzIGFycmF5XG4gICAgdGhpcy5zZXJ2ZXJLZXlzID0gT2JqZWN0LmtleXModGhpcy5zZXJ2ZXJNYXApO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBuZXcgY2xpZW50IGdpdmVuIGFuIG9wdGlvbmFsIGNvbmZpZyBzdHJpbmcgYW5kIG9wdGlvbmFsIGhhc2ggb2ZcbiAgICogb3B0aW9ucy4gVGhlIGNvbmZpZyBzdHJpbmcgc2hvdWxkIGJlIG9mIHRoZSBmb3JtOlxuICAgKlxuICAgKiAgICAgXCJbdXNlcjpwYXNzQF1zZXJ2ZXIxWzoxMTIxMV0sW3VzZXI6cGFzc0Bdc2VydmVyMls6MTEyMTFdLC4uLlwiXG4gICAqXG4gICAqIElmIHRoZSBhcmd1bWVudCBpcyBub3QgZ2l2ZW4sIGZhbGxiYWNrIG9uIHRoZSBgTUVNQ0FDSElFUl9TRVJWRVJTYCBlbnZpcm9ubWVudFxuICAgKiB2YXJpYWJsZSwgYE1FTUNBQ0hFX1NFUlZFUlNgIGVudmlyb25tZW50IHZhcmlhYmxlIG9yIGBcImxvY2FsaG9zdDoxMTIxMVwiYC5cbiAgICpcbiAgICogVGhlIG9wdGlvbnMgaGFzaCBtYXkgY29udGFpbiB0aGUgb3B0aW9uczpcbiAgICpcbiAgICogKiBgcmV0cmllc2AgLSB0aGUgbnVtYmVyIG9mIHRpbWVzIHRvIHJldHJ5IGFuIG9wZXJhdGlvbiBpbiBsaWV1IG9mIGZhaWx1cmVzXG4gICAqIChkZWZhdWx0IDIpXG4gICAqICogYGV4cGlyZXNgIC0gdGhlIGRlZmF1bHQgZXhwaXJhdGlvbiBpbiBzZWNvbmRzIHRvIHVzZSAoZGVmYXVsdCAwIC0gbmV2ZXJcbiAgICogZXhwaXJlKS4gSWYgYGV4cGlyZXNgIGlzIGdyZWF0ZXIgdGhhbiAzMCBkYXlzICg2MCB4IDYwIHggMjQgeCAzMCksIGl0IGlzXG4gICAqIHRyZWF0ZWQgYXMgYSBVTklYIHRpbWUgKG51bWJlciBvZiBzZWNvbmRzIHNpbmNlIEphbnVhcnkgMSwgMTk3MCkuXG4gICAqICogYGxvZ2dlcmAgLSBhIGxvZ2dlciBvYmplY3QgdGhhdCByZXNwb25kcyB0byBgbG9nKHN0cmluZylgIG1ldGhvZCBjYWxscy5cbiAgICpcbiAgICogICB+fn5+XG4gICAqICAgICBsb2cobXNnMVssIG1zZzJbLCBtc2czWy4uLl1dXSlcbiAgICogICB+fn5+XG4gICAqXG4gICAqICAgRGVmYXVsdHMgdG8gYGNvbnNvbGVgLlxuICAgKiAqIGBzZXJpYWxpemVyYCAtIHRoZSBvYmplY3Qgd2hpY2ggd2lsbCAoZGUpc2VyaWFsaXplIHRoZSBkYXRhLiBJdCBuZWVkc1xuICAgKiAgIHR3byBwdWJsaWMgbWV0aG9kczogc2VyaWFsaXplIGFuZCBkZXNlcmlhbGl6ZS4gSXQgZGVmYXVsdHMgdG8gdGhlXG4gICAqICAgbm9vcFNlcmlhbGl6ZXI6XG4gICAqXG4gICAqICAgfn5+flxuICAgKiAgIGNvbnN0IG5vb3BTZXJpYWxpemVyID0ge1xuICAgKiAgICAgc2VyaWFsaXplOiBmdW5jdGlvbiAob3Bjb2RlLCB2YWx1ZSwgZXh0cmFzKSB7XG4gICAqICAgICAgIHJldHVybiB7IHZhbHVlOiB2YWx1ZSwgZXh0cmFzOiBleHRyYXMgfTtcbiAgICogICAgIH0sXG4gICAqICAgICBkZXNlcmlhbGl6ZTogZnVuY3Rpb24gKG9wY29kZSwgdmFsdWUsIGV4dHJhcykge1xuICAgKiAgICAgICByZXR1cm4geyB2YWx1ZTogdmFsdWUsIGV4dHJhczogZXh0cmFzIH07XG4gICAqICAgICB9XG4gICAqICAgfTtcbiAgICogICB+fn5+XG4gICAqXG4gICAqIE9yIG9wdGlvbnMgZm9yIHRoZSBzZXJ2ZXJzIGluY2x1ZGluZzpcbiAgICogKiBgdXNlcm5hbWVgIGFuZCBgcGFzc3dvcmRgIGZvciBmYWxsYmFjayBTQVNMIGF1dGhlbnRpY2F0aW9uIGNyZWRlbnRpYWxzLlxuICAgKiAqIGB0aW1lb3V0YCBpbiBzZWNvbmRzIHRvIGRldGVybWluZSBmYWlsdXJlIGZvciBvcGVyYXRpb25zLiBEZWZhdWx0IGlzIDAuNVxuICAgKiAgICAgICAgICAgICBzZWNvbmRzLlxuICAgKiAqICdjb25udGltZW91dCcgaW4gc2Vjb25kcyB0byBjb25uZWN0aW9uIGZhaWx1cmUuIERlZmF1bHQgaXMgdHdpY2UgdGhlIHZhbHVlXG4gICAqICAgICAgICAgICAgICAgICBvZiBgdGltZW91dGAuXG4gICAqICogYGtlZXBBbGl2ZWAgd2hldGhlciB0byBlbmFibGUga2VlcC1hbGl2ZSBmdW5jdGlvbmFsaXR5LiBEZWZhdWx0cyB0byBmYWxzZS5cbiAgICogKiBga2VlcEFsaXZlRGVsYXlgIGluIHNlY29uZHMgdG8gdGhlIGluaXRpYWwgZGVsYXkgYmVmb3JlIHRoZSBmaXJzdCBrZWVwYWxpdmVcbiAgICogICAgICAgICAgICAgICAgICAgIHByb2JlIGlzIHNlbnQgb24gYW4gaWRsZSBzb2NrZXQuIERlZmF1bHRzIGlzIDMwIHNlY29uZHMuXG4gICAqICogYGtleVRvU2VydmVySGFzaEZ1bmN0aW9uYCBhIGZ1bmN0aW9uIHRvIG1hcCBrZXlzIHRvIHNlcnZlcnMsIHdpdGggdGhlIHNpZ25hdHVyZVxuICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoc2VydmVyS2V5czogc3RyaW5nW10sIGtleTogc3RyaW5nKTogc3RyaW5nXG4gICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgIE5PVEU6IGlmIHlvdSBuZWVkIHRvIGRvIHNvbWUgZXhwZW5zaXZlIGluaXRpYWxpemF0aW9uLCAqcGxlYXNlKiBkbyBpdCBsYXppbHkgdGhlIGZpcnN0IHRpbWUgeW91IHRoaXMgZnVuY3Rpb24gaXMgY2FsbGVkIHdpdGggYW4gYXJyYXkgb2Ygc2VydmVyS2V5cywgbm90IG9uIGV2ZXJ5IGNhbGxcbiAgICovXG4gIHN0YXRpYyBjcmVhdGU8VmFsdWUsIEV4dHJhcz4oXG4gICAgc2VydmVyc1N0cjogc3RyaW5nIHwgdW5kZWZpbmVkLFxuICAgIG9wdGlvbnM6IElmQnVmZmVyPFxuICAgICAgVmFsdWUsXG4gICAgICBFeHRyYXMsXG4gICAgICB1bmRlZmluZWQgfCAoUGFydGlhbDxTZXJ2ZXJPcHRpb25zPiAmIEdpdmVuQ2xpZW50T3B0aW9uczxWYWx1ZSwgRXh0cmFzPiksXG4gICAgICBQYXJ0aWFsPFNlcnZlck9wdGlvbnM+ICYgR2l2ZW5DbGllbnRPcHRpb25zPFZhbHVlLCBFeHRyYXM+XG4gICAgPlxuICApOiBDbGllbnQ8VmFsdWUsIEV4dHJhcz4ge1xuICAgIHNlcnZlcnNTdHIgPVxuICAgICAgc2VydmVyc1N0ciB8fFxuICAgICAgcHJvY2Vzcy5lbnYuTUVNQ0FDSElFUl9TRVJWRVJTIHx8XG4gICAgICBwcm9jZXNzLmVudi5NRU1DQUNIRV9TRVJWRVJTIHx8XG4gICAgICBcImxvY2FsaG9zdDoxMTIxMVwiO1xuICAgIGNvbnN0IHNlcnZlclVyaXMgPSBzZXJ2ZXJzU3RyLnNwbGl0KFwiLFwiKTtcbiAgICBjb25zdCBzZXJ2ZXJzID0gc2VydmVyVXJpcy5tYXAoZnVuY3Rpb24gKHVyaSkge1xuICAgICAgY29uc3QgdXJpUGFydHMgPSB1cmkuc3BsaXQoXCJAXCIpO1xuICAgICAgY29uc3QgaG9zdFBvcnQgPSB1cmlQYXJ0c1t1cmlQYXJ0cy5sZW5ndGggLSAxXS5zcGxpdChcIjpcIik7XG4gICAgICBjb25zdCB1c2VyUGFzcyA9ICh1cmlQYXJ0c1t1cmlQYXJ0cy5sZW5ndGggLSAyXSB8fCBcIlwiKS5zcGxpdChcIjpcIik7XG4gICAgICByZXR1cm4gbmV3IFNlcnZlcihcbiAgICAgICAgaG9zdFBvcnRbMF0sXG4gICAgICAgIHBhcnNlSW50KGhvc3RQb3J0WzFdIHx8IFwiMTEyMTFcIiwgMTApLFxuICAgICAgICB1c2VyUGFzc1swXSxcbiAgICAgICAgdXNlclBhc3NbMV0sXG4gICAgICAgIG9wdGlvbnNcbiAgICAgICk7XG4gICAgfSk7XG4gICAgcmV0dXJuIG5ldyBDbGllbnQoc2VydmVycywgb3B0aW9ucyBhcyBhbnkpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdpdmVuIGEgc2VydmVyS2V5IGZyb21sb29rdXBLZXlUb1NlcnZlcktleSwgcmV0dXJuIHRoZSBjb3JyZXNwb25kaW5nIFNlcnZlciBpbnN0YW5jZVxuICAgKlxuICAgKiBAcGFyYW0gIHtzdHJpbmd9IHNlcnZlcktleVxuICAgKiBAcmV0dXJucyB7U2VydmVyfVxuICAgKi9cbiAgc2VydmVyS2V5VG9TZXJ2ZXIoc2VydmVyS2V5OiBzdHJpbmcpOiBTZXJ2ZXIge1xuICAgIHJldHVybiB0aGlzLnNlcnZlck1hcFtzZXJ2ZXJLZXldO1xuICB9XG5cbiAgLyoqXG4gICAqIEdpdmVuIGEga2V5IHRvIGxvb2sgdXAgaW4gbWVtY2FjaGUsIHJldHVybiBhIHNlcnZlcktleSAoYmFzZWQgb24gc29tZVxuICAgKiBoYXNoaW5nIGZ1bmN0aW9uKSB3aGljaCBjYW4gYmUgdXNlZCB0byBpbmRleCB0aGlzLnNlcnZlck1hcFxuICAgKi9cbiAgbG9va3VwS2V5VG9TZXJ2ZXJLZXkoa2V5OiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLm9wdGlvbnMua2V5VG9TZXJ2ZXJIYXNoRnVuY3Rpb24odGhpcy5zZXJ2ZXJLZXlzLCBrZXkpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHJpZXZlcyB0aGUgdmFsdWUgYXQgdGhlIGdpdmVuIGtleSBpbiBtZW1jYWNoZS5cbiAgICovXG4gIGFzeW5jIGdldChrZXk6IHN0cmluZyk6IFByb21pc2U8R2V0UmVzdWx0PFZhbHVlLCBFeHRyYXM+IHwgbnVsbD4ge1xuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihjb25zdGFudHMuT1BfR0VULCBrZXksIFwiXCIsIFwiXCIsIHRoaXMuc2VxKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgY29uc3QgZGVzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLmRlc2VyaWFsaXplKFxuICAgICAgICAgIHJlc3BvbnNlLmhlYWRlci5vcGNvZGUsXG4gICAgICAgICAgcmVzcG9uc2UudmFsLFxuICAgICAgICAgIHJlc3BvbnNlLmV4dHJhc1xuICAgICAgICApO1xuICAgICAgICByZXR1cm4geyAuLi5kZXNlcmlhbGl6ZWQsIGNhczogcmVzcG9uc2UuaGVhZGVyLmNhcyB9O1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfTk9UX0ZPVU5EOlxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJHRVRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqIEJ1aWxkIGEgcGlwZWxpbmVkIGdldCBtdWx0aSByZXF1ZXN0IGJ5IHNlbmRpbmcgb25lIEdFVEtRIGZvciBlYWNoIGtleSAocXVpZXQsIG1lYW5pbmcgaXQgd29uJ3QgcmVzcG9uZCBpZiB0aGUgdmFsdWUgaXMgbWlzc2luZykgZm9sbG93ZWQgYnkgYSBuby1vcCB0byBmb3JjZSBhIHJlc3BvbnNlIChhbmQgdG8gZ2l2ZSB1cyBhIHNlbnRpbmVsIHJlc3BvbnNlIHRoYXQgdGhlIHBpcGVsaW5lIGlzIGRvbmUpXG4gICAqXG4gICAqIGNmIGh0dHBzOi8vZ2l0aHViLmNvbS9jb3VjaGJhc2UvbWVtY2FjaGVkL2Jsb2IvbWFzdGVyL2RvY3MvQmluYXJ5UHJvdG9jb2wubWQjMHgwZC1nZXRrcS1nZXQtd2l0aC1rZXktcXVpZXRseVxuICAgKi9cbiAgX2J1aWxkR2V0TXVsdGlSZXF1ZXN0KGtleXM6IHN0cmluZ1tdKTogQnVmZmVyIHtcbiAgICAvLyBzdGFydCBhdCAyNCBmb3IgdGhlIG5vLW9wIGNvbW1hbmQgYXQgdGhlIGVuZFxuICAgIGxldCByZXF1ZXN0U2l6ZSA9IDI0O1xuICAgIGZvciAoY29uc3Qga2V5SWR4IGluIGtleXMpIHtcbiAgICAgIHJlcXVlc3RTaXplICs9IEJ1ZmZlci5ieXRlTGVuZ3RoKGtleXNba2V5SWR4XSwgXCJ1dGY4XCIpICsgMjQ7XG4gICAgfVxuXG4gICAgY29uc3QgcmVxdWVzdCA9IEJ1ZmZlci5hbGxvYyhyZXF1ZXN0U2l6ZSk7XG5cbiAgICBsZXQgYnl0ZXNXcml0dGVuID0gMDtcbiAgICBmb3IgKGNvbnN0IGtleUlkeCBpbiBrZXlzKSB7XG4gICAgICBjb25zdCBrZXkgPSBrZXlzW2tleUlkeF07XG4gICAgICBieXRlc1dyaXR0ZW4gKz0gY29weUludG9SZXF1ZXN0QnVmZmVyKFxuICAgICAgICBjb25zdGFudHMuT1BfR0VUS1EsXG4gICAgICAgIGtleSxcbiAgICAgICAgXCJcIixcbiAgICAgICAgXCJcIixcbiAgICAgICAgdGhpcy5zZXEsXG4gICAgICAgIHJlcXVlc3QsXG4gICAgICAgIGJ5dGVzV3JpdHRlblxuICAgICAgKTtcbiAgICB9XG5cbiAgICBieXRlc1dyaXR0ZW4gKz0gY29weUludG9SZXF1ZXN0QnVmZmVyKFxuICAgICAgY29uc3RhbnRzLk9QX05PX09QLFxuICAgICAgXCJcIixcbiAgICAgIFwiXCIsXG4gICAgICBcIlwiLFxuICAgICAgdGhpcy5zZXEsXG4gICAgICByZXF1ZXN0LFxuICAgICAgYnl0ZXNXcml0dGVuXG4gICAgKTtcblxuICAgIHJldHVybiByZXF1ZXN0O1xuICB9XG5cbiAgLyoqIEV4ZWN1dGluZyBhIHBpcGVsaW5lZCAobXVsdGkpIGdldCBhZ2FpbnN0IGEgc2luZ2xlIHNlcnZlci4gVGhpcyBpcyBhIHByaXZhdGUgaW1wbGVtZW50YXRpb24gZGV0YWlsIG9mIGdldE11bHRpLiAqL1xuICBhc3luYyBfZ2V0TXVsdGlUb1NlcnZlcjxLZXlzIGV4dGVuZHMgc3RyaW5nPihcbiAgICBzZXJ2OiBTZXJ2ZXIsXG4gICAga2V5czogS2V5c1tdXG4gICk6IFByb21pc2U8R2V0TXVsdGlSZXN1bHQ8S2V5cywgVmFsdWUsIEV4dHJhcz4+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgY29uc3QgcmVzcG9uc2VNYXA6IEdldE11bHRpUmVzdWx0PHN0cmluZywgVmFsdWUsIEV4dHJhcz4gPSB7fTtcblxuICAgICAgY29uc3QgaGFuZGxlOiBPblJlc3BvbnNlQ2FsbGJhY2sgPSAocmVzcG9uc2UpID0+IHtcbiAgICAgICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICAgICAgLy8gV2hlbiB3ZSBnZXQgdGhlIG5vLW9wIHJlc3BvbnNlLCB3ZSBhcmUgZG9uZSB3aXRoIHRoaXMgb25lIGdldE11bHRpIGluIHRoZSBwZXItYmFja2VuZCBmYW4tb3V0XG4gICAgICAgICAgICBpZiAocmVzcG9uc2UuaGVhZGVyLm9wY29kZSA9PT0gY29uc3RhbnRzLk9QX05PX09QKSB7XG4gICAgICAgICAgICAgIC8vIFRoaXMgZW5zdXJlcyB0aGUgaGFuZGxlciB3aWxsIGJlIGRlbGV0ZWQgZnJvbSB0aGUgcmVzcG9uc2VDYWxsYmFja3MgbWFwIGluIHNlcnZlci5qc1xuICAgICAgICAgICAgICAvLyBUaGlzIGlzbid0IHRlY2huaWNhbGx5IG5lZWRlZCBoZXJlIGJlY2F1c2UgdGhlIGxvZ2ljIGluIHNlcnZlci5qcyBhbHNvIGNoZWNrcyBpZiB0b3RhbEJvZHlMZW5ndGggPT09IDAsIGJ1dCBvdXIgdW5pdHRlc3RzIGFyZW4ndCBncmVhdCBhYm91dCBzZXR0aW5nIHRoYXQgZmllbGQsIGFuZCBhbHNvIHRoaXMgbWFrZXMgaXQgbW9yZSBleHBsaWNpdFxuICAgICAgICAgICAgICBoYW5kbGUucXVpZXQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgcmVzb2x2ZShyZXNwb25zZU1hcCk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHJlc3BvbnNlLmhlYWRlci5vcGNvZGUgPT09IGNvbnN0YW50cy5PUF9HRVRLIHx8IHJlc3BvbnNlLmhlYWRlci5vcGNvZGUgPT09IGNvbnN0YW50cy5PUF9HRVRLUSkge1xuICAgICAgICAgICAgICBjb25zdCBkZXNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuZGVzZXJpYWxpemUoXG4gICAgICAgICAgICAgICAgcmVzcG9uc2UuaGVhZGVyLm9wY29kZSxcbiAgICAgICAgICAgICAgICByZXNwb25zZS52YWwsXG4gICAgICAgICAgICAgICAgcmVzcG9uc2UuZXh0cmFzXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgIGNvbnN0IGtleSA9IHJlc3BvbnNlLmtleS50b1N0cmluZygpO1xuICAgICAgICAgICAgICBpZiAoa2V5Lmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiByZWplY3QoXG4gICAgICAgICAgICAgICAgICBuZXcgRXJyb3IoXCJSZWNpZXZlZCBlbXB0eSBrZXkgaW4gZ2V0TXVsdGk6IFwiICsgSlNPTi5zdHJpbmdpZnkocmVzcG9uc2UpKVxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgcmVzcG9uc2VNYXBba2V5XSA9IHsgLi4uZGVzZXJpYWxpemVkLCBjYXM6IHJlc3BvbnNlLmhlYWRlci5jYXMgfTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHJldHVybiByZWplY3QoXG4gICAgICAgICAgICAgICAgbmV3IEVycm9yKFwiUmVjaWV2ZWQgcmVzcG9uc2UgaW4gZ2V0TXVsdGkgZm9yIHVua25vd24gb3Bjb2RlOiBcIiArIEpTT04uc3RyaW5naWZ5KHJlc3BvbnNlKSlcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICByZXR1cm4gcmVqZWN0KFxuICAgICAgICAgICAgICB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiR0VUXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9O1xuICAgICAgLy8gVGhpcyBwcmV2ZW50cyB0aGUgaGFuZGxlciBmcm9tIGJlaW5nIGRlbGV0ZWRcbiAgICAgIC8vIGFmdGVyIHRoZSBmaXJzdCByZXNwb25zZS4gTG9naWMgaW4gc2VydmVyLmpzLlxuICAgICAgaGFuZGxlLnF1aWV0ID0gdHJ1ZTtcblxuICAgICAgY29uc3QgcmVxdWVzdCA9IHRoaXMuX2J1aWxkR2V0TXVsdGlSZXF1ZXN0KGtleXMpO1xuICAgICAgc2Vydi5vblJlc3BvbnNlKHRoaXMuc2VxLCBoYW5kbGUpO1xuICAgICAgc2Vydi5vbkVycm9yKHRoaXMuc2VxLCByZWplY3QpO1xuICAgICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgICBzZXJ2LndyaXRlKHJlcXVlc3QpO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHJpZXZzIHRoZSB2YWx1ZSBhdCB0aGUgZ2l2ZW4ga2V5cyBpbiBtZW1jYWNoZWQuIFJldHVybnMgYSBtYXAgZnJvbSB0aGVcbiAgICogcmVxdWVzdGVkIGtleXMgdG8gcmVzdWx0cywgb3IgbnVsbCBpZiB0aGUga2V5IHdhcyBub3QgZm91bmQuXG4gICAqL1xuICBhc3luYyBnZXRNdWx0aTxLZXlzIGV4dGVuZHMgc3RyaW5nPihcbiAgICBrZXlzOiBLZXlzW11cbiAgKTogUHJvbWlzZTxHZXRNdWx0aVJlc3VsdDxLZXlzLCBWYWx1ZSwgRXh0cmFzPj4ge1xuICAgIGNvbnN0IHNlcnZlcktleXRvTG9va3VwS2V5czoge1xuICAgICAgW3NlcnZlcktleTogc3RyaW5nXTogc3RyaW5nW107XG4gICAgfSA9IHt9O1xuICAgIGtleXMuZm9yRWFjaCgobG9va3VwS2V5KSA9PiB7XG4gICAgICBjb25zdCBzZXJ2ZXJLZXkgPSB0aGlzLmxvb2t1cEtleVRvU2VydmVyS2V5KGxvb2t1cEtleSk7XG4gICAgICBpZiAoIXNlcnZlcktleXRvTG9va3VwS2V5c1tzZXJ2ZXJLZXldKSB7XG4gICAgICAgIHNlcnZlcktleXRvTG9va3VwS2V5c1tzZXJ2ZXJLZXldID0gW107XG4gICAgICB9XG4gICAgICBzZXJ2ZXJLZXl0b0xvb2t1cEtleXNbc2VydmVyS2V5XS5wdXNoKGxvb2t1cEtleSk7XG4gICAgfSk7XG5cbiAgICBjb25zdCB1c2VkU2VydmVyS2V5cyA9IE9iamVjdC5rZXlzKHNlcnZlcktleXRvTG9va3VwS2V5cyk7XG4gICAgY29uc3QgcmVzdWx0cyA9IGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgdXNlZFNlcnZlcktleXMubWFwKChzZXJ2ZXJLZXkpID0+IHtcbiAgICAgICAgY29uc3Qgc2VydmVyID0gdGhpcy5zZXJ2ZXJLZXlUb1NlcnZlcihzZXJ2ZXJLZXkpO1xuICAgICAgICByZXR1cm4gdGhpcy5fZ2V0TXVsdGlUb1NlcnZlcihzZXJ2ZXIsIHNlcnZlcktleXRvTG9va3VwS2V5c1tzZXJ2ZXJLZXldKTtcbiAgICAgIH0pXG4gICAgKTtcblxuICAgIHJldHVybiBPYmplY3QuYXNzaWduKHt9LCAuLi5yZXN1bHRzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIGBrZXlgIHRvIGB2YWx1ZWAuXG4gICAqL1xuICBhc3luYyBzZXQoXG4gICAga2V5OiBzdHJpbmcsXG4gICAgdmFsdWU6IFZhbHVlLFxuICAgIG9wdGlvbnM/OiB7IGV4cGlyZXM/OiBudW1iZXI7IGNhcz86IENBU1Rva2VuIH1cbiAgKTogUHJvbWlzZTxib29sZWFuIHwgbnVsbD4ge1xuICAgIGNvbnN0IGV4cGlyZXMgPSBvcHRpb25zPy5leHBpcmVzO1xuICAgIGNvbnN0IGNhcyA9IG9wdGlvbnM/LmNhcztcblxuICAgIC8vIFRPRE86IHN1cHBvcnQgZmxhZ3NcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBleHBpcmF0aW9uID0gbWFrZUV4cGlyYXRpb24oZXhwaXJlcyB8fCB0aGlzLm9wdGlvbnMuZXhwaXJlcyk7XG4gICAgY29uc3QgZXh0cmFzID0gQnVmZmVyLmNvbmNhdChbQnVmZmVyLmZyb20oXCIwMDAwMDAwMFwiLCBcImhleFwiKSwgZXhwaXJhdGlvbl0pO1xuICAgIGNvbnN0IHNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuc2VyaWFsaXplKFxuICAgICAgY29uc3RhbnRzLk9QX1NFVCxcbiAgICAgIHZhbHVlLFxuICAgICAgZXh0cmFzXG4gICAgKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gVXRpbHMuZW5jb2RlUmVxdWVzdCh7XG4gICAgICBoZWFkZXI6IHtcbiAgICAgICAgb3Bjb2RlOiBjb25zdGFudHMuT1BfU0VULFxuICAgICAgICBvcGFxdWU6IHRoaXMuc2VxLFxuICAgICAgICBjYXMsXG4gICAgICB9LFxuICAgICAga2V5LFxuICAgICAgdmFsdWU6IHNlcmlhbGl6ZWQudmFsdWUsXG4gICAgICBleHRyYXM6IHNlcmlhbGl6ZWQuZXh0cmFzLFxuICAgIH0pO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuS0VZX0VYSVNUUzpcbiAgICAgICAgaWYgKGNhcykge1xuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiU0VUXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgICAgICB9XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiU0VUXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBBRERcbiAgICpcbiAgICogQWRkcyB0aGUgZ2l2ZW4gX2tleV8gYW5kIF92YWx1ZV8gdG8gbWVtY2FjaGUuIFRoZSBvcGVyYXRpb24gb25seSBzdWNjZWVkc1xuICAgKiBpZiB0aGUga2V5IGlzIG5vdCBhbHJlYWR5IHNldC5cbiAgICpcbiAgICogVGhlIG9wdGlvbnMgZGljdGlvbmFyeSB0YWtlczpcbiAgICogKiBfZXhwaXJlc186IG92ZXJyaWRlcyB0aGUgZGVmYXVsdCBleHBpcmF0aW9uIChzZWUgYENsaWVudC5jcmVhdGVgKSBmb3IgdGhpc1xuICAgKiAgICAgICAgICAgICAgcGFydGljdWxhciBrZXktdmFsdWUgcGFpci5cbiAgICovXG4gIGFzeW5jIGFkZChcbiAgICBrZXk6IHN0cmluZyxcbiAgICB2YWx1ZTogVmFsdWUsXG4gICAgb3B0aW9ucz86IHsgZXhwaXJlcz86IG51bWJlciB9XG4gICk6IFByb21pc2U8Ym9vbGVhbiB8IG51bGw+IHtcbiAgICAvLyBUT0RPOiBzdXBwb3J0IGZsYWdzLCBzdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBleHBpcmF0aW9uID0gbWFrZUV4cGlyYXRpb24ob3B0aW9ucz8uZXhwaXJlcyB8fCB0aGlzLm9wdGlvbnMuZXhwaXJlcyk7XG4gICAgY29uc3QgZXh0cmFzID0gQnVmZmVyLmNvbmNhdChbQnVmZmVyLmZyb20oXCIwMDAwMDAwMFwiLCBcImhleFwiKSwgZXhwaXJhdGlvbl0pO1xuXG4gICAgY29uc3Qgb3Bjb2RlID0gY29uc3RhbnRzLk9QX0FERDtcbiAgICBjb25zdCBzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLnNlcmlhbGl6ZShvcGNvZGUsIHZhbHVlLCBleHRyYXMpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgIG9wY29kZSxcbiAgICAgIGtleSxcbiAgICAgIHNlcmlhbGl6ZWQuZXh0cmFzLFxuICAgICAgc2VyaWFsaXplZC52YWx1ZSxcbiAgICAgIHRoaXMuc2VxXG4gICAgKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9FWElTVFM6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiQUREXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXBsYWNlcyB0aGUgZ2l2ZW4gX2tleV8gYW5kIF92YWx1ZV8gdG8gbWVtY2FjaGUuIFRoZSBvcGVyYXRpb24gb25seSBzdWNjZWVkc1xuICAgKiBpZiB0aGUga2V5IGlzIGFscmVhZHkgcHJlc2VudC5cbiAgICovXG4gIGFzeW5jIHJlcGxhY2UoXG4gICAga2V5OiBzdHJpbmcsXG4gICAgdmFsdWU6IFZhbHVlLFxuICAgIG9wdGlvbnM/OiB7IGV4cGlyZXM/OiBudW1iZXIgfVxuICApOiBQcm9taXNlPGJvb2xlYW4gfCBudWxsPiB7XG4gICAgLy8gVE9ETzogc3VwcG9ydCBmbGFncywgc3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgZXhwaXJhdGlvbiA9IG1ha2VFeHBpcmF0aW9uKG9wdGlvbnM/LmV4cGlyZXMgfHwgdGhpcy5vcHRpb25zLmV4cGlyZXMpO1xuICAgIGNvbnN0IGV4dHJhcyA9IEJ1ZmZlci5jb25jYXQoW0J1ZmZlci5mcm9tKFwiMDAwMDAwMDBcIiwgXCJoZXhcIiksIGV4cGlyYXRpb25dKTtcblxuICAgIGNvbnN0IG9wY29kZTogY29uc3RhbnRzLk9QID0gY29uc3RhbnRzLk9QX1JFUExBQ0U7XG4gICAgY29uc3Qgc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5zZXJpYWxpemUob3Bjb2RlLCB2YWx1ZSwgZXh0cmFzKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICBvcGNvZGUsXG4gICAgICBrZXksXG4gICAgICBzZXJpYWxpemVkLmV4dHJhcyxcbiAgICAgIHNlcmlhbGl6ZWQudmFsdWUsXG4gICAgICB0aGlzLnNlcVxuICAgICk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfTk9UX0ZPVU5EOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiUkVQTEFDRVwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRGVsZXRlcyB0aGUgZ2l2ZW4gX2tleV8gZnJvbSBtZW1jYWNoZS4gVGhlIG9wZXJhdGlvbiBvbmx5IHN1Y2NlZWRzXG4gICAqIGlmIHRoZSBrZXkgaXMgYWxyZWFkeSBwcmVzZW50LlxuICAgKi9cbiAgYXN5bmMgZGVsZXRlKGtleTogc3RyaW5nKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgLy8gVE9ETzogU3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKDQsIGtleSwgXCJcIiwgXCJcIiwgdGhpcy5zZXEpO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuXG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfTk9UX0ZPVU5EOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiREVMRVRFXCIsIHJlc3BvbnNlPy5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogSW5jcmVtZW50cyB0aGUgZ2l2ZW4gX2tleV8gaW4gbWVtY2FjaGUuXG4gICAqL1xuICBhc3luYyBpbmNyZW1lbnQoXG4gICAga2V5OiBzdHJpbmcsXG4gICAgYW1vdW50OiBudW1iZXIsXG4gICAgb3B0aW9ucz86IHsgaW5pdGlhbD86IG51bWJlcjsgZXhwaXJlcz86IG51bWJlciB9XG4gICk6IFByb21pc2U8eyB2YWx1ZTogbnVtYmVyIHwgbnVsbDsgc3VjY2VzczogYm9vbGVhbiB8IG51bGwgfT4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IGluaXRpYWwgPSBvcHRpb25zPy5pbml0aWFsIHx8IDA7XG4gICAgY29uc3QgZXhwaXJlcyA9IG9wdGlvbnM/LmV4cGlyZXMgfHwgdGhpcy5vcHRpb25zLmV4cGlyZXM7XG4gICAgY29uc3QgZXh0cmFzID0gbWFrZUFtb3VudEluaXRpYWxBbmRFeHBpcmF0aW9uKGFtb3VudCwgaW5pdGlhbCwgZXhwaXJlcyk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKFxuICAgICAgY29uc3RhbnRzLk9QX0lOQ1JFTUVOVCxcbiAgICAgIGtleSxcbiAgICAgIGV4dHJhcyxcbiAgICAgIFwiXCIsXG4gICAgICB0aGlzLnNlcVxuICAgICk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIGNvbnN0IGJ1ZkludCA9XG4gICAgICAgICAgKHJlc3BvbnNlLnZhbC5yZWFkVUludDMyQkUoMCkgPDwgOCkgKyByZXNwb25zZS52YWwucmVhZFVJbnQzMkJFKDQpO1xuICAgICAgICByZXR1cm4geyB2YWx1ZTogYnVmSW50LCBzdWNjZXNzOiB0cnVlIH07XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiSU5DUkVNRU5UXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBEZWNyZW1lbnRzIHRoZSBnaXZlbiBga2V5YCBpbiBtZW1jYWNoZS5cbiAgICovXG4gIGFzeW5jIGRlY3JlbWVudChcbiAgICBrZXk6IHN0cmluZyxcbiAgICBhbW91bnQ6IG51bWJlcixcbiAgICBvcHRpb25zOiB7IGluaXRpYWw/OiBudW1iZXI7IGV4cGlyZXM/OiBudW1iZXIgfVxuICApOiBQcm9taXNlPHsgdmFsdWU6IG51bWJlciB8IG51bGw7IHN1Y2Nlc3M6IGJvb2xlYW4gfCBudWxsIH0+IHtcbiAgICAvLyBUT0RPOiBzdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBpbml0aWFsID0gb3B0aW9ucy5pbml0aWFsIHx8IDA7XG4gICAgY29uc3QgZXhwaXJlcyA9IG9wdGlvbnMuZXhwaXJlcyB8fCB0aGlzLm9wdGlvbnMuZXhwaXJlcztcbiAgICBjb25zdCBleHRyYXMgPSBtYWtlQW1vdW50SW5pdGlhbEFuZEV4cGlyYXRpb24oYW1vdW50LCBpbml0aWFsLCBleHBpcmVzKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICBjb25zdGFudHMuT1BfREVDUkVNRU5ULFxuICAgICAga2V5LFxuICAgICAgZXh0cmFzLFxuICAgICAgXCJcIixcbiAgICAgIHRoaXMuc2VxXG4gICAgKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgY29uc3QgYnVmSW50ID1cbiAgICAgICAgICAocmVzcG9uc2UudmFsLnJlYWRVSW50MzJCRSgwKSA8PCA4KSArIHJlc3BvbnNlLnZhbC5yZWFkVUludDMyQkUoNCk7XG4gICAgICAgIHJldHVybiB7IHZhbHVlOiBidWZJbnQsIHN1Y2Nlc3M6IHRydWUgfTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJERUNSRU1FTlRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEFwcGVuZCB0aGUgZ2l2ZW4gX3ZhbHVlXyB0byB0aGUgdmFsdWUgYXNzb2NpYXRlZCB3aXRoIHRoZSBnaXZlbiBfa2V5XyBpblxuICAgKiBtZW1jYWNoZS4gVGhlIG9wZXJhdGlvbiBvbmx5IHN1Y2NlZWRzIGlmIHRoZSBrZXkgaXMgYWxyZWFkeSBwcmVzZW50LlxuICAgKi9cbiAgYXN5bmMgYXBwZW5kKGtleTogc3RyaW5nLCB2YWx1ZTogVmFsdWUpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAvLyBUT0RPOiBzdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBvcGNvZGU6IGNvbnN0YW50cy5PUCA9IGNvbnN0YW50cy5PUF9BUFBFTkQ7XG4gICAgY29uc3Qgc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5zZXJpYWxpemUob3Bjb2RlLCB2YWx1ZSwgXCJcIik7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKFxuICAgICAgb3Bjb2RlLFxuICAgICAga2V5LFxuICAgICAgc2VyaWFsaXplZC5leHRyYXMsXG4gICAgICBzZXJpYWxpemVkLnZhbHVlLFxuICAgICAgdGhpcy5zZXFcbiAgICApO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuS0VZX05PVF9GT1VORDpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIkFQUEVORFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUHJlcGVuZCB0aGUgZ2l2ZW4gX3ZhbHVlXyB0byB0aGUgdmFsdWUgYXNzb2NpYXRlZCB3aXRoIHRoZSBnaXZlbiBfa2V5XyBpblxuICAgKiBtZW1jYWNoZS4gVGhlIG9wZXJhdGlvbiBvbmx5IHN1Y2NlZWRzIGlmIHRoZSBrZXkgaXMgYWxyZWFkeSBwcmVzZW50LlxuICAgKi9cbiAgYXN5bmMgcHJlcGVuZChrZXk6IHN0cmluZywgdmFsdWU6IFZhbHVlKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgLy8gVE9ETzogc3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3Qgb3Bjb2RlOiBjb25zdGFudHMuT1AgPSBjb25zdGFudHMuT1BfUFJFUEVORDtcbiAgICBjb25zdCBzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLnNlcmlhbGl6ZShvcGNvZGUsIHZhbHVlLCBcIlwiKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICBvcGNvZGUsXG4gICAgICBrZXksXG4gICAgICBzZXJpYWxpemVkLmV4dHJhcyxcbiAgICAgIHNlcmlhbGl6ZWQudmFsdWUsXG4gICAgICB0aGlzLnNlcVxuICAgICk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfTk9UX0ZPVU5EOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiUFJFUEVORFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVG91Y2ggc2V0cyBhbiBleHBpcmF0aW9uIHZhbHVlLCBnaXZlbiBieSBfZXhwaXJlc18sIG9uIHRoZSBnaXZlbiBfa2V5XyBpblxuICAgKiBtZW1jYWNoZS4gVGhlIG9wZXJhdGlvbiBvbmx5IHN1Y2NlZWRzIGlmIHRoZSBrZXkgaXMgYWxyZWFkeSBwcmVzZW50LlxuICAgKi9cbiAgYXN5bmMgdG91Y2goa2V5OiBzdHJpbmcsIGV4cGlyZXM6IG51bWJlcik6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IGV4dHJhcyA9IG1ha2VFeHBpcmF0aW9uKGV4cGlyZXMgfHwgdGhpcy5vcHRpb25zLmV4cGlyZXMpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcigweDFjLCBrZXksIGV4dHJhcywgXCJcIiwgdGhpcy5zZXEpO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuS0VZX05PVF9GT1VORDpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIlRPVUNIXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBGTFVTSFxuICAgKlxuICAgKiBGbHVzaGVzIHRoZSBjYWNoZSBvbiBlYWNoIGNvbm5lY3RlZCBzZXJ2ZXIuIFRoZSBjYWxsYmFjayBzaWduYXR1cmUgaXM6XG4gICAqXG4gICAqICAgICBjYWxsYmFjayhsYXN0RXJyLCByZXN1bHRzKVxuICAgKlxuICAgKiB3aGVyZSBfbGFzdEVycl8gaXMgdGhlIGxhc3QgZXJyb3IgZW5jb3VudGVyZWQgKG9yIG51bGwsIGluIHRoZSBjb21tb24gY2FzZVxuICAgKiBvZiBubyBlcnJvcnMpLiBfcmVzdWx0c18gaXMgYSBkaWN0aW9uYXJ5IG1hcHBpbmcgYFwiaG9zdG5hbWU6cG9ydFwiYCB0byBlaXRoZXJcbiAgICogYHRydWVgIChpZiB0aGUgb3BlcmF0aW9uIHdhcyBzdWNjZXNzZnVsKSwgb3IgYW4gZXJyb3IuXG4gICAqIEBwYXJhbSBjYWxsYmFja1xuICAgKi9cbiAgZmx1c2goKTogUHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBib29sZWFuIHwgRXJyb3I+PjtcbiAgZmx1c2goXG4gICAgY2FsbGJhY2s6IChcbiAgICAgIGVycjogRXJyb3IgfCBudWxsLFxuICAgICAgcmVzdWx0czogUmVjb3JkPHN0cmluZywgYm9vbGVhbiB8IEVycm9yPlxuICAgICkgPT4gdm9pZFxuICApOiB2b2lkO1xuICBmbHVzaChcbiAgICBjYWxsYmFjaz86IChcbiAgICAgIGVycjogRXJyb3IgfCBudWxsLFxuICAgICAgcmVzdWx0czogUmVjb3JkPHN0cmluZywgYm9vbGVhbiB8IEVycm9yPlxuICAgICkgPT4gdm9pZFxuICApIHtcbiAgICBpZiAoY2FsbGJhY2sgPT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuIHByb21pc2lmeSgoY2FsbGJhY2spID0+IHtcbiAgICAgICAgdGhpcy5mbHVzaChmdW5jdGlvbiAoZXJyLCByZXN1bHRzKSB7XG4gICAgICAgICAgY2FsbGJhY2soZXJyLCByZXN1bHRzKTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9XG4gICAgLy8gVE9ETzogc3VwcG9ydCBleHBpcmF0aW9uXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKDB4MDgsIFwiXCIsIFwiXCIsIFwiXCIsIHRoaXMuc2VxKTtcbiAgICBsZXQgY291bnQgPSB0aGlzLnNlcnZlcnMubGVuZ3RoO1xuICAgIGNvbnN0IHJlc3VsdDogUmVjb3JkPHN0cmluZywgYm9vbGVhbiB8IEVycm9yPiA9IHt9O1xuICAgIGxldCBsYXN0RXJyOiBFcnJvciB8IG51bGwgPSBudWxsO1xuXG4gICAgY29uc3QgaGFuZGxlRmx1c2ggPSBmdW5jdGlvbiAoc2VxOiBudW1iZXIsIHNlcnY6IFNlcnZlcikge1xuICAgICAgc2Vydi5vblJlc3BvbnNlKHNlcSwgZnVuY3Rpb24gKC8qIHJlc3BvbnNlICovKSB7XG4gICAgICAgIGNvdW50IC09IDE7XG4gICAgICAgIHJlc3VsdFtzZXJ2Lmhvc3Rwb3J0U3RyaW5nKCldID0gdHJ1ZTtcbiAgICAgICAgaWYgKGNhbGxiYWNrICYmIGNvdW50ID09PSAwKSB7XG4gICAgICAgICAgY2FsbGJhY2sobGFzdEVyciwgcmVzdWx0KTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICBzZXJ2Lm9uRXJyb3Ioc2VxLCBmdW5jdGlvbiAoZXJyKSB7XG4gICAgICAgIGNvdW50IC09IDE7XG4gICAgICAgIGxhc3RFcnIgPSBlcnI7XG4gICAgICAgIHJlc3VsdFtzZXJ2Lmhvc3Rwb3J0U3RyaW5nKCldID0gZXJyO1xuICAgICAgICBpZiAoY2FsbGJhY2sgJiYgY291bnQgPT09IDApIHtcbiAgICAgICAgICBjYWxsYmFjayhsYXN0RXJyLCByZXN1bHQpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHNlcnYud3JpdGUocmVxdWVzdCk7XG4gICAgfTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5zZXJ2ZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBoYW5kbGVGbHVzaCh0aGlzLnNlcSwgdGhpcy5zZXJ2ZXJzW2ldKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU1RBVFNfV0lUSF9LRVlcbiAgICpcbiAgICogU2VuZHMgYSBtZW1jYWNoZSBzdGF0cyBjb21tYW5kIHdpdGggYSBrZXkgdG8gZWFjaCBjb25uZWN0ZWQgc2VydmVyLiBUaGVcbiAgICogY2FsbGJhY2sgaXMgaW52b2tlZCAqKk9OQ0UgUEVSIFNFUlZFUioqIGFuZCBoYXMgdGhlIHNpZ25hdHVyZTpcbiAgICpcbiAgICogICAgIGNhbGxiYWNrKGVyciwgc2VydmVyLCBzdGF0cylcbiAgICpcbiAgICogX3NlcnZlcl8gaXMgdGhlIGBcImhvc3RuYW1lOnBvcnRcImAgb2YgdGhlIHNlcnZlciwgYW5kIF9zdGF0c18gaXMgYSBkaWN0aW9uYXJ5XG4gICAqIG1hcHBpbmcgdGhlIHN0YXQgbmFtZSB0byB0aGUgdmFsdWUgb2YgdGhlIHN0YXRpc3RpYyBhcyBhIHN0cmluZy5cbiAgICogQHBhcmFtIGtleVxuICAgKiBAcGFyYW0gY2FsbGJhY2tcbiAgICovXG4gIHN0YXRzV2l0aEtleShcbiAgICBrZXk6IHN0cmluZyxcbiAgICBjYWxsYmFjaz86IChcbiAgICAgIGVycjogRXJyb3IgfCBudWxsLFxuICAgICAgc2VydmVyOiBzdHJpbmcsXG4gICAgICBzdGF0czogUmVjb3JkPHN0cmluZywgc3RyaW5nPiB8IG51bGxcbiAgICApID0+IHZvaWRcbiAgKTogdm9pZCB7XG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKDB4MTAsIGtleSwgXCJcIiwgXCJcIiwgdGhpcy5zZXEpO1xuXG4gICAgY29uc3QgaGFuZGxlU3RhdHMgPSAoc2VxOiBudW1iZXIsIHNlcnY6IFNlcnZlcikgPT4ge1xuICAgICAgY29uc3QgcmVzdWx0OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge307XG4gICAgICBjb25zdCBoYW5kbGU6IE9uUmVzcG9uc2VDYWxsYmFjayA9IChyZXNwb25zZSkgPT4ge1xuICAgICAgICAvLyBlbmQgb2Ygc3RhdCByZXNwb25zZXNcbiAgICAgICAgaWYgKHJlc3BvbnNlLmhlYWRlci50b3RhbEJvZHlMZW5ndGggPT09IDApIHtcbiAgICAgICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKG51bGwsIHNlcnYuaG9zdHBvcnRTdHJpbmcoKSwgcmVzdWx0KTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIC8vIHByb2Nlc3Mgc2luZ2xlIHN0YXQgbGluZSByZXNwb25zZVxuICAgICAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgICAgICByZXN1bHRbcmVzcG9uc2Uua2V5LnRvU3RyaW5nKCldID0gcmVzcG9uc2UudmFsLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgY29uc3QgZXJyb3IgPSB0aGlzLmhhbmRsZVJlc3BvbnNlRXJyb3IoXG4gICAgICAgICAgICAgIGBTVEFUUyAoJHtrZXl9KWAsXG4gICAgICAgICAgICAgIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMsXG4gICAgICAgICAgICAgIHVuZGVmaW5lZFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgICAgICBjYWxsYmFjayhlcnJvciwgc2Vydi5ob3N0cG9ydFN0cmluZygpLCBudWxsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfTtcbiAgICAgIGhhbmRsZS5xdWlldCA9IHRydWU7XG5cbiAgICAgIHNlcnYub25SZXNwb25zZShzZXEsIGhhbmRsZSk7XG4gICAgICBzZXJ2Lm9uRXJyb3Ioc2VxLCBmdW5jdGlvbiAoZXJyKSB7XG4gICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgIGNhbGxiYWNrKGVyciwgc2Vydi5ob3N0cG9ydFN0cmluZygpLCBudWxsKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICBzZXJ2LndyaXRlKHJlcXVlc3QpO1xuICAgIH07XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuc2VydmVycy5sZW5ndGg7IGkrKykge1xuICAgICAgaGFuZGxlU3RhdHModGhpcy5zZXEsIHRoaXMuc2VydmVyc1tpXSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNUQVRTXG4gICAqXG4gICAqIEZldGNoZXMgbWVtY2FjaGUgc3RhdHMgZnJvbSBlYWNoIGNvbm5lY3RlZCBzZXJ2ZXIuIFRoZSBjYWxsYmFjayBpcyBpbnZva2VkXG4gICAqICoqT05DRSBQRVIgU0VSVkVSKiogYW5kIGhhcyB0aGUgc2lnbmF0dXJlOlxuICAgKlxuICAgKiAgICAgY2FsbGJhY2soZXJyLCBzZXJ2ZXIsIHN0YXRzKVxuICAgKlxuICAgKiBfc2VydmVyXyBpcyB0aGUgYFwiaG9zdG5hbWU6cG9ydFwiYCBvZiB0aGUgc2VydmVyLCBhbmQgX3N0YXRzXyBpcyBhXG4gICAqIGRpY3Rpb25hcnkgbWFwcGluZyB0aGUgc3RhdCBuYW1lIHRvIHRoZSB2YWx1ZSBvZiB0aGUgc3RhdGlzdGljIGFzIGEgc3RyaW5nLlxuICAgKiBAcGFyYW0gY2FsbGJhY2tcbiAgICovXG4gIHN0YXRzKFxuICAgIGNhbGxiYWNrPzogKFxuICAgICAgZXJyOiBFcnJvciB8IG51bGwsXG4gICAgICBzZXJ2ZXI6IHN0cmluZyxcbiAgICAgIHN0YXRzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+IHwgbnVsbFxuICAgICkgPT4gdm9pZFxuICApOiB2b2lkIHtcbiAgICB0aGlzLnN0YXRzV2l0aEtleShcIlwiLCBjYWxsYmFjayk7XG4gIH1cblxuICAvKipcbiAgICogUkVTRVRfU1RBVFNcbiAgICpcbiAgICogUmVzZXQgdGhlIHN0YXRpc3RpY3MgZWFjaCBzZXJ2ZXIgaXMga2VlcGluZyBiYWNrIHRvIHplcm8uIFRoaXMgZG9lc24ndCBjbGVhclxuICAgKiBzdGF0cyBzdWNoIGFzIGl0ZW0gY291bnQsIGJ1dCB0ZW1wb3Jhcnkgc3RhdHMgc3VjaCBhcyB0b3RhbCBudW1iZXIgb2ZcbiAgICogY29ubmVjdGlvbnMgb3ZlciB0aW1lLlxuICAgKlxuICAgKiBUaGUgY2FsbGJhY2sgaXMgaW52b2tlZCAqKk9OQ0UgUEVSIFNFUlZFUioqIGFuZCBoYXMgdGhlIHNpZ25hdHVyZTpcbiAgICpcbiAgICogICAgIGNhbGxiYWNrKGVyciwgc2VydmVyKVxuICAgKlxuICAgKiBfc2VydmVyXyBpcyB0aGUgYFwiaG9zdG5hbWU6cG9ydFwiYCBvZiB0aGUgc2VydmVyLlxuICAgKiBAcGFyYW0gY2FsbGJhY2tcbiAgICovXG4gIHJlc2V0U3RhdHMoXG4gICAgY2FsbGJhY2s/OiAoXG4gICAgICBlcnI6IEVycm9yIHwgbnVsbCxcbiAgICAgIHNlcnZlcjogc3RyaW5nLFxuICAgICAgc3RhdHM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gfCBudWxsXG4gICAgKSA9PiB2b2lkXG4gICk6IHZvaWQge1xuICAgIHRoaXMuc3RhdHNXaXRoS2V5KFwicmVzZXRcIiwgY2FsbGJhY2spO1xuICB9XG5cbiAgLyoqXG4gICAqIFFVSVRcbiAgICpcbiAgICogQ2xvc2VzIHRoZSBjb25uZWN0aW9uIHRvIGVhY2ggc2VydmVyLCBub3RpZnlpbmcgdGhlbSBvZiB0aGlzIGludGVudGlvbi4gTm90ZVxuICAgKiB0aGF0IHF1aXQgY2FuIHJhY2UgYWdhaW5zdCBhbHJlYWR5IG91dHN0YW5kaW5nIHJlcXVlc3RzIHdoZW4gdGhvc2UgcmVxdWVzdHNcbiAgICogZmFpbCBhbmQgYXJlIHJldHJpZWQsIGxlYWRpbmcgdG8gdGhlIHF1aXQgY29tbWFuZCB3aW5uaW5nIGFuZCBjbG9zaW5nIHRoZVxuICAgKiBjb25uZWN0aW9uIGJlZm9yZSB0aGUgcmV0cmllcyBjb21wbGV0ZS5cbiAgICovXG4gIHF1aXQoKSB7XG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgLy8gVE9ETzogTmljZXIgcGVyaGFwcyB0byBkbyBRVUlUUSAoMHgxNykgYnV0IG5lZWQgYSBuZXcgY2FsbGJhY2sgZm9yIHdoZW5cbiAgICAvLyB3cml0ZSBpcyBkb25lLlxuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcigweDA3LCBcIlwiLCBcIlwiLCBcIlwiLCB0aGlzLnNlcSk7IC8vIFFVSVRcbiAgICBsZXQgc2VydjtcblxuICAgIGNvbnN0IGhhbmRsZVF1aXQgPSBmdW5jdGlvbiAoc2VxOiBudW1iZXIsIHNlcnY6IFNlcnZlcikge1xuICAgICAgc2Vydi5vblJlc3BvbnNlKHNlcSwgZnVuY3Rpb24gKC8qIHJlc3BvbnNlICovKSB7XG4gICAgICAgIHNlcnYuY2xvc2UoKTtcbiAgICAgIH0pO1xuICAgICAgc2Vydi5vbkVycm9yKHNlcSwgZnVuY3Rpb24gKC8qIGVyciAqLykge1xuICAgICAgICBzZXJ2LmNsb3NlKCk7XG4gICAgICB9KTtcbiAgICAgIHNlcnYud3JpdGUocmVxdWVzdCk7XG4gICAgfTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5zZXJ2ZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBzZXJ2ID0gdGhpcy5zZXJ2ZXJzW2ldO1xuICAgICAgaGFuZGxlUXVpdCh0aGlzLnNlcSwgc2Vydik7XG4gICAgfVxuICB9XG5cbiAgX3ZlcnNpb24oc2VydmVyOiBTZXJ2ZXIpOiBQcm9taXNlPHsgdmFsdWU6IFZhbHVlIHwgbnVsbCB9PiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIHRoaXMuaW5jclNlcSgpO1xuICAgICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKFxuICAgICAgICBjb25zdGFudHMuT1BfVkVSU0lPTixcbiAgICAgICAgXCJcIixcbiAgICAgICAgXCJcIixcbiAgICAgICAgXCJcIixcbiAgICAgICAgdGhpcy5zZXFcbiAgICAgICk7XG4gICAgICB0aGlzLnBlcmZvcm1PblNlcnZlcihzZXJ2ZXIsIHJlcXVlc3QsIHRoaXMuc2VxLCAoZXJyLCByZXNwb25zZSkgPT4ge1xuICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgcmV0dXJuIHJlamVjdChlcnIpO1xuICAgICAgICB9XG5cbiAgICAgICAgc3dpdGNoIChyZXNwb25zZSEuaGVhZGVyLnN0YXR1cykge1xuICAgICAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgICAgIC8qIFRPRE86IHRoaXMgaXMgYnVnZ2VkLCB3ZSBzaG91bGQndCB1c2UgdGhlIGRlc2VyaWFsaXplciBoZXJlLCBzaW5jZSB2ZXJzaW9uIGFsd2F5cyByZXR1cm5zIGEgdmVyc2lvbiBzdHJpbmcuXG4gICAgICAgICAgICAgVGhlIGRlc2VyaWFsaXplciBzaG91bGQgb25seSBiZSB1c2VkIG9uIHVzZXIga2V5IGRhdGEuICovXG4gICAgICAgICAgICBjb25zdCBkZXNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuZGVzZXJpYWxpemUoXG4gICAgICAgICAgICAgIHJlc3BvbnNlIS5oZWFkZXIub3Bjb2RlLFxuICAgICAgICAgICAgICByZXNwb25zZSEudmFsLFxuICAgICAgICAgICAgICByZXNwb25zZSEuZXh0cmFzXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgcmV0dXJuIHJlc29sdmUoeyB2YWx1ZTogZGVzZXJpYWxpemVkLnZhbHVlIH0pO1xuICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICByZXR1cm4gcmVqZWN0KFxuICAgICAgICAgICAgICB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiVkVSU0lPTlwiLCByZXNwb25zZSEuaGVhZGVyLnN0YXR1cylcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlcXVlc3QgdGhlIHNlcnZlciB2ZXJzaW9uIGZyb20gdGhlIFwiZmlyc3RcIiBzZXJ2ZXIgaW4gdGhlIGJhY2tlbmQgcG9vbC5cbiAgICogVGhlIHNlcnZlciByZXNwb25kcyB3aXRoIGEgcGFja2V0IGNvbnRhaW5pbmcgdGhlIHZlcnNpb24gc3RyaW5nIGluIHRoZSBib2R5IHdpdGggdGhlIGZvbGxvd2luZyBmb3JtYXQ6IFwieC55LnpcIlxuICAgKi9cbiAgdmVyc2lvbigpOiBQcm9taXNlPHsgdmFsdWU6IFZhbHVlIHwgbnVsbCB9PiB7XG4gICAgY29uc3Qgc2VydmVyID0gdGhpcy5zZXJ2ZXJLZXlUb1NlcnZlcih0aGlzLnNlcnZlcktleXNbMF0pO1xuICAgIHJldHVybiB0aGlzLl92ZXJzaW9uKHNlcnZlcik7XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldmVzIHRoZSBzZXJ2ZXIgdmVyc2lvbiBmcm9tIGFsbCB0aGUgc2VydmVyc1xuICAgKiBpbiB0aGUgYmFja2VuZCBwb29sLCBlcnJvcnMgaWYgYW55IG9uZSBvZiB0aGVtIGhhcyBhblxuICAgKiBlcnJvclxuICAgKi9cbiAgYXN5bmMgdmVyc2lvbkFsbCgpOiBQcm9taXNlPHtcbiAgICB2YWx1ZXM6IFJlY29yZDxzdHJpbmcsIFZhbHVlIHwgbnVsbD47XG4gIH0+IHtcbiAgICBjb25zdCB2ZXJzaW9uT2JqZWN0cyA9IGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgdGhpcy5zZXJ2ZXJLZXlzLm1hcCgoc2VydmVyS2V5KSA9PiB7XG4gICAgICAgIGNvbnN0IHNlcnZlciA9IHRoaXMuc2VydmVyS2V5VG9TZXJ2ZXIoc2VydmVyS2V5KTtcblxuICAgICAgICByZXR1cm4gdGhpcy5fdmVyc2lvbihzZXJ2ZXIpLnRoZW4oKHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgcmV0dXJuIHsgc2VydmVyS2V5OiBzZXJ2ZXJLZXksIHZhbHVlOiByZXNwb25zZS52YWx1ZSB9O1xuICAgICAgICB9KTtcbiAgICAgIH0pXG4gICAgKTtcbiAgICBjb25zdCB2YWx1ZXMgPSB2ZXJzaW9uT2JqZWN0cy5yZWR1Y2UoKGFjY3VtdWxhdG9yLCB2ZXJzaW9uT2JqZWN0KSA9PiB7XG4gICAgICBhY2N1bXVsYXRvclt2ZXJzaW9uT2JqZWN0LnNlcnZlcktleV0gPSB2ZXJzaW9uT2JqZWN0LnZhbHVlO1xuICAgICAgcmV0dXJuIGFjY3VtdWxhdG9yO1xuICAgIH0sIHt9IGFzIFJlY29yZDxzdHJpbmcsIFZhbHVlIHwgbnVsbD4pO1xuICAgIHJldHVybiB7IHZhbHVlczogdmFsdWVzIH07XG4gIH1cblxuICAvKipcbiAgICogQ2xvc2VzIChhYnJ1cHRseSkgY29ubmVjdGlvbnMgdG8gYWxsIHRoZSBzZXJ2ZXJzLlxuICAgKiBAc2VlIHRoaXMucXVpdFxuICAgKi9cbiAgY2xvc2UoKSB7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnNlcnZlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHRoaXMuc2VydmVyc1tpXS5jbG9zZSgpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBQZXJmb3JtIGEgZ2VuZXJpYyBzaW5nbGUgcmVzcG9uc2Ugb3BlcmF0aW9uIChnZXQsIHNldCBldGMpIG9uIG9uZSBzZXJ2ZXJcbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IGtleSB0aGUga2V5IHRvIGhhc2ggdG8gZ2V0IGEgc2VydmVyIGZyb20gdGhlIHBvb2xcbiAgICogQHBhcmFtIHtidWZmZXJ9IHJlcXVlc3QgYSBidWZmZXIgY29udGFpbmluZyB0aGUgcmVxdWVzdFxuICAgKiBAcGFyYW0ge251bWJlcn0gc2VxIHRoZSBzZXF1ZW5jZSBudW1iZXIgb2YgdGhlIG9wZXJhdGlvbi4gSXQgaXMgdXNlZCB0byBwaW4gdGhlIGNhbGxiYWNrc1xuICAgICAgICAgICAgICAgICAgICAgICAgIHRvIGEgc3BlY2lmaWMgb3BlcmF0aW9uIGFuZCBzaG91bGQgbmV2ZXIgY2hhbmdlIGR1cmluZyBhIGBwZXJmb3JtYC5cbiAgICogQHBhcmFtIHtudW1iZXI/fSByZXRyaWVzIG51bWJlciBvZiB0aW1lcyB0byByZXRyeSByZXF1ZXN0IG9uIGZhaWx1cmVcbiAgICovXG4gIHBlcmZvcm0oXG4gICAga2V5OiBzdHJpbmcsXG4gICAgcmVxdWVzdDogQnVmZmVyLFxuICAgIHNlcTogbnVtYmVyLFxuICAgIHJldHJpZXM/OiBudW1iZXJcbiAgKTogUHJvbWlzZTxNZXNzYWdlPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGNvbnN0IHNlcnZlcktleSA9IHRoaXMubG9va3VwS2V5VG9TZXJ2ZXJLZXkoa2V5KTtcbiAgICAgIGNvbnN0IHNlcnZlciA9IHRoaXMuc2VydmVyS2V5VG9TZXJ2ZXIoc2VydmVyS2V5KTtcblxuICAgICAgaWYgKCFzZXJ2ZXIpIHtcbiAgICAgICAgcmV0dXJuIHJlamVjdChuZXcgRXJyb3IoXCJObyBzZXJ2ZXJzIGF2YWlsYWJsZVwiKSk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMucGVyZm9ybU9uU2VydmVyKFxuICAgICAgICBzZXJ2ZXIsXG4gICAgICAgIHJlcXVlc3QsXG4gICAgICAgIHNlcSxcbiAgICAgICAgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgcmV0dXJuIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJlc29sdmUocmVzcG9uc2UhKTtcbiAgICAgICAgfSxcbiAgICAgICAgcmV0cmllc1xuICAgICAgKTtcbiAgICB9KTtcbiAgfVxuXG4gIHBlcmZvcm1PblNlcnZlcihcbiAgICBzZXJ2ZXI6IFNlcnZlcixcbiAgICByZXF1ZXN0OiBCdWZmZXIsXG4gICAgc2VxOiBudW1iZXIsXG4gICAgY2FsbGJhY2s6IFJlc3BvbnNlT3JFcnJvckNhbGxiYWNrLFxuICAgIHJldHJpZXM6IG51bWJlciA9IDBcbiAgKSB7XG4gICAgY29uc3QgX3RoaXMgPSB0aGlzO1xuXG4gICAgcmV0cmllcyA9IHJldHJpZXMgfHwgdGhpcy5vcHRpb25zLnJldHJpZXM7XG4gICAgY29uc3Qgb3JpZ1JldHJpZXMgPSB0aGlzLm9wdGlvbnMucmV0cmllcztcbiAgICBjb25zdCBsb2dnZXIgPSB0aGlzLm9wdGlvbnMubG9nZ2VyO1xuICAgIGNvbnN0IHJldHJ5X2RlbGF5ID0gdGhpcy5vcHRpb25zLnJldHJ5X2RlbGF5O1xuXG4gICAgY29uc3QgcmVzcG9uc2VIYW5kbGVyOiBPblJlc3BvbnNlQ2FsbGJhY2sgPSBmdW5jdGlvbiAocmVzcG9uc2UpIHtcbiAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICBjYWxsYmFjayhudWxsLCByZXNwb25zZSk7XG4gICAgICB9XG4gICAgfTtcblxuICAgIGNvbnN0IGVycm9ySGFuZGxlcjogT25FcnJvckNhbGxiYWNrID0gZnVuY3Rpb24gKGVycm9yKSB7XG4gICAgICBpZiAoLS1yZXRyaWVzID4gMCkge1xuICAgICAgICAvLyBXYWl0IGZvciByZXRyeV9kZWxheVxuICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICBfdGhpcy5wZXJmb3JtT25TZXJ2ZXIoc2VydmVyLCByZXF1ZXN0LCBzZXEsIGNhbGxiYWNrLCByZXRyaWVzKTtcbiAgICAgICAgfSwgMTAwMCAqIHJldHJ5X2RlbGF5KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGxvZ2dlci5sb2coXG4gICAgICAgICAgXCJNZW1KUzogU2VydmVyIDxcIiArXG4gICAgICAgICAgICBzZXJ2ZXIuaG9zdHBvcnRTdHJpbmcoKSArXG4gICAgICAgICAgICBcIj4gZmFpbGVkIGFmdGVyIChcIiArXG4gICAgICAgICAgICBvcmlnUmV0cmllcyArXG4gICAgICAgICAgICBcIikgcmV0cmllcyB3aXRoIGVycm9yIC0gXCIgK1xuICAgICAgICAgICAgZXJyb3IubWVzc2FnZVxuICAgICAgICApO1xuICAgICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgICBjYWxsYmFjayhlcnJvciwgbnVsbCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9O1xuXG4gICAgc2VydmVyLm9uUmVzcG9uc2Uoc2VxLCByZXNwb25zZUhhbmRsZXIpO1xuICAgIHNlcnZlci5vbkVycm9yKHNlcSwgZXJyb3JIYW5kbGVyKTtcbiAgICBzZXJ2ZXIud3JpdGUocmVxdWVzdCk7XG4gIH1cblxuICAvLyBJbmNyZW1lbnQgdGhlIHNlcSB2YWx1ZVxuICBpbmNyU2VxKCkge1xuICAgIHRoaXMuc2VxKys7XG5cbiAgICAvLyBXcmFwIGB0aGlzLnNlcWAgdG8gMzItYml0cyBzaW5jZSB0aGUgZmllbGQgd2UgZml0IGl0IGludG8gaXMgb25seSAzMi1iaXRzLlxuICAgIHRoaXMuc2VxICY9IDB4ZmZmZmZmZmY7XG4gIH1cblxuICBwcml2YXRlIGNyZWF0ZUFuZExvZ0Vycm9yKFxuICAgIGNvbW1hbmROYW1lOiBzdHJpbmcsXG4gICAgcmVzcG9uc2VTdGF0dXM6IFJlc3BvbnNlU3RhdHVzIHwgdW5kZWZpbmVkXG4gICk6IEVycm9yIHtcbiAgICBjb25zdCBlcnJvck1lc3NhZ2UgPSBgTWVtSlMgJHtjb21tYW5kTmFtZX06ICR7Y29uc3RhbnRzLnJlc3BvbnNlU3RhdHVzVG9TdHJpbmcoXG4gICAgICByZXNwb25zZVN0YXR1c1xuICAgICl9YDtcbiAgICB0aGlzLm9wdGlvbnMubG9nZ2VyLmxvZyhlcnJvck1lc3NhZ2UpO1xuICAgIHJldHVybiBuZXcgRXJyb3IoZXJyb3JNZXNzYWdlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBMb2cgYW4gZXJyb3IgdG8gdGhlIGxvZ2dlciwgdGhlbiByZXR1cm4gdGhlIGVycm9yLlxuICAgKiBJZiBhIGNhbGxiYWNrIGlzIGdpdmVuLCBjYWxsIGl0IHdpdGggY2FsbGJhY2soZXJyb3IsIG51bGwpLlxuICAgKi9cbiAgcHJpdmF0ZSBoYW5kbGVSZXNwb25zZUVycm9yKFxuICAgIGNvbW1hbmROYW1lOiBzdHJpbmcsXG4gICAgcmVzcG9uc2VTdGF0dXM6IFJlc3BvbnNlU3RhdHVzIHwgdW5kZWZpbmVkLFxuICAgIGNhbGxiYWNrOiB1bmRlZmluZWQgfCAoKGVycm9yOiBFcnJvciB8IG51bGwsIG90aGVyOiBudWxsKSA9PiB2b2lkKVxuICApOiBFcnJvciB7XG4gICAgY29uc3QgZXJyb3IgPSB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKGNvbW1hbmROYW1lLCByZXNwb25zZVN0YXR1cyk7XG4gICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICBjYWxsYmFjayhlcnJvciwgbnVsbCk7XG4gICAgfVxuICAgIHJldHVybiBlcnJvcjtcbiAgfVxufVxuXG5leHBvcnQgeyBDbGllbnQsIFNlcnZlciwgVXRpbHMsIEhlYWRlciB9O1xuIl19 \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVtanMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbWVtanMvbWVtanMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLHdCQUF3Qjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUV4QixxQ0FLa0I7QUEraENELHVGQWppQ2YsZUFBTSxPQWlpQ2U7QUE5aEN2Qix1REFBK0Q7QUFDL0QsbUNBU2lCO0FBQ2pCLHVEQUF5QztBQUN6QywyQ0FBNkM7QUFDN0MsK0NBQWlDO0FBaWhDUixzQkFBSztBQWhoQzlCLGlEQUFtQztBQWdoQ0gsd0JBQU07QUE5Z0N0QyxTQUFTLDhCQUE4QixDQUNyQyxPQUFpQixFQUNqQixHQUFXO0lBRVgsTUFBTSxLQUFLLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQztJQUM3QixNQUFNLEtBQUssR0FBRyxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxnQkFBUSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3BELE9BQU8sT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ3hCLENBQUM7QUFFRCwrQ0FBK0M7QUFDL0MsU0FBUyxTQUFTLENBQ2hCLE9BQTBFO0lBRTFFLE9BQU8sSUFBSSxPQUFPLENBQUMsVUFBVSxPQUFPLEVBQUUsTUFBTTtRQUMxQyxPQUFPLENBQUMsVUFBVSxHQUFHLEVBQUUsTUFBTTtZQUMzQixHQUFHLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3RDLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBNkRELE1BQU0sTUFBTTtJQVFWLDRFQUE0RTtJQUM1RSxtQ0FBbUM7SUFDbkMsWUFBWSxPQUFpQixFQUFFLE9BQTBDO1FBQ3ZFLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO1FBQ3ZCLElB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LFlBQVksQ0FBQyxDQUFDO0lBQ2pDLENBQUM7SUFFRDs7O09BR0c7SUFDSyxtQkFBbUIsQ0FDekIsV0FBbUIsRUFDbkIsY0FBMEMsRUFDMUMsUUFBa0U7UUFFbEUsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixDQUFDLFdBQVcsRUFBRSxjQUFjLENBQUMsQ0FBQztRQUNsRSxJQUFJLFFBQVEsRUFBRTtZQUNaLFFBQVEsQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLENBQUM7U0FDdkI7UUFDRCxPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7Q0FDRjtBQUVRLHdCQUFNIiwic291cmNlc0NvbnRlbnQiOlsiLy8gTWVtVFMgTWVtY2FjaGUgQ2xpZW50XG5cbmltcG9ydCB7XG4gIE9uRXJyb3JDYWxsYmFjayxcbiAgT25SZXNwb25zZUNhbGxiYWNrLFxuICBTZXJ2ZXIsXG4gIFNlcnZlck9wdGlvbnMsXG59IGZyb20gXCIuL3NlcnZlclwiO1xuaW1wb3J0IHsgbm9vcFNlcmlhbGl6ZXIsIFNlcmlhbGl6ZXIgfSBmcm9tIFwiLi9ub29wLXNlcmlhbGl6ZXJcIjtcbmltcG9ydCB7XG4gIG1ha2VSZXF1ZXN0QnVmZmVyLFxuICBjb3B5SW50b1JlcXVlc3RCdWZmZXIsXG4gIG1lcmdlLFxuICBtYWtlRXhwaXJhdGlvbixcbiAgbWFrZUFtb3VudEluaXRpYWxBbmRFeHBpcmF0aW9uLFxuICBoYXNoQ29kZSxcbiAgTWF5YmVCdWZmZXIsXG4gIE1lc3NhZ2UsXG59IGZyb20gXCIuL3V0aWxzXCI7XG5pbXBvcnQgKiBhcyBjb25zdGFudHMgZnJvbSBcIi4vY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBSZXNwb25zZVN0YXR1cyB9IGZyb20gXCIuL2NvbnN0YW50c1wiO1xuaW1wb3J0ICogYXMgVXRpbHMgZnJvbSBcIi4vdXRpbHNcIjtcbmltcG9ydCAqIGFzIEhlYWRlciBmcm9tIFwiLi9oZWFkZXJcIjtcblxuZnVuY3Rpb24gZGVmYXVsdEtleVRvU2VydmVySGFzaEZ1bmN0aW9uKFxuICBzZXJ2ZXJzOiBzdHJpbmdbXSxcbiAga2V5OiBzdHJpbmdcbik6IHN0cmluZyB7XG4gIGNvbnN0IHRvdGFsID0gc2VydmVycy5sZW5ndGg7XG4gIGNvbnN0IGluZGV4ID0gdG90YWwgPiAxID8gaGFzaENvZGUoa2V5KSAlIHRvdGFsIDogMDtcbiAgcmV0dXJuIHNlcnZlcnNbaW5kZXhdO1xufVxuXG4vLyBjb252ZXJ0cyBhIGNhbGwgaW50byBhIHByb21pc2UtcmV0dXJuaW5nIG9uZVxuZnVuY3Rpb24gcHJvbWlzaWZ5PFJlc3VsdD4oXG4gIGNvbW1hbmQ6IChjYWxsYmFjazogKGVycm9yOiBFcnJvciB8IG51bGwsIHJlc3VsdDogUmVzdWx0KSA9PiB2b2lkKSA9PiB2b2lkXG4pOiBQcm9taXNlPFJlc3VsdD4ge1xuICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuICAgIGNvbW1hbmQoZnVuY3Rpb24gKGVyciwgcmVzdWx0KSB7XG4gICAgICBlcnIgPyByZWplY3QoZXJyKSA6IHJlc29sdmUocmVzdWx0KTtcbiAgICB9KTtcbiAgfSk7XG59XG5cbnR5cGUgUmVzcG9uc2VPckVycm9yQ2FsbGJhY2sgPSAoXG4gIGVycm9yOiBFcnJvciB8IG51bGwsXG4gIHJlc3BvbnNlOiBNZXNzYWdlIHwgbnVsbFxuKSA9PiB2b2lkO1xuXG5pbnRlcmZhY2UgQmFzZUNsaWVudE9wdGlvbnMge1xuICByZXRyaWVzOiBudW1iZXI7XG4gIHJldHJ5X2RlbGF5OiBudW1iZXI7XG4gIGV4cGlyZXM6IG51bWJlcjtcbiAgbG9nZ2VyOiB7IGxvZzogdHlwZW9mIGNvbnNvbGUubG9nIH07XG4gIGtleVRvU2VydmVySGFzaEZ1bmN0aW9uOiB0eXBlb2YgZGVmYXVsdEtleVRvU2VydmVySGFzaEZ1bmN0aW9uO1xufVxuXG5pbnRlcmZhY2UgU2VyaWFsaXplclByb3A8VmFsdWUsIEV4dHJhcz4ge1xuICBzZXJpYWxpemVyOiBTZXJpYWxpemVyPFZhbHVlLCBFeHRyYXM+O1xufVxuXG4vKipcbiAqIFRoZSBjbGllbnQgaGFzIHBhcnRpYWwgc3VwcG9ydCBmb3Igc2VyaWFsaXppbmcgYW5kIGRlc2VyaWFsaXppbmcgdmFsdWVzIGZyb20gdGhlXG4gKiBCdWZmZXIgYnl0ZSBzdHJpbmdzIHdlIHJlY2lldmUgZnJvbSB0aGUgd2lyZS4gVGhlIGRlZmF1bHQgc2VyaWFsaXplciBpcyBmb3IgTWF5YmVCdWZmZXIuXG4gKlxuICogSWYgVmFsdWUgYW5kIEV4dHJhcyBhcmUgb2YgdHlwZSBCdWZmZXIsIHRoZW4gcmV0dXJuIHR5cGUgV2hlbkJ1ZmZlci4gT3RoZXJ3aXNlLFxuICogcmV0dXJuIHR5cGUgTm90QnVmZmVyLlxuICovXG50eXBlIElmQnVmZmVyPFxuICBWYWx1ZSxcbiAgRXh0cmFzLFxuICBXaGVuVmFsdWVBbmRFeHRyYXNBcmVCdWZmZXJzLFxuICBOb3RCdWZmZXJcbj4gPSBWYWx1ZSBleHRlbmRzIEJ1ZmZlclxuICA/IEV4dHJhcyBleHRlbmRzIEJ1ZmZlclxuICAgID8gV2hlblZhbHVlQW5kRXh0cmFzQXJlQnVmZmVyc1xuICAgIDogTm90QnVmZmVyXG4gIDogTm90QnVmZmVyO1xuXG5leHBvcnQgdHlwZSBHaXZlbkNsaWVudE9wdGlvbnM8VmFsdWUsIEV4dHJhcz4gPSBQYXJ0aWFsPEJhc2VDbGllbnRPcHRpb25zPiAmXG4gIElmQnVmZmVyPFxuICAgIFZhbHVlLFxuICAgIEV4dHJhcyxcbiAgICBQYXJ0aWFsPFNlcmlhbGl6ZXJQcm9wPFZhbHVlLCBFeHRyYXM+PixcbiAgICBTZXJpYWxpemVyUHJvcDxWYWx1ZSwgRXh0cmFzPlxuICA+O1xuXG5leHBvcnQgdHlwZSBDQVNUb2tlbiA9IEJ1ZmZlcjtcblxuZXhwb3J0IGludGVyZmFjZSBHZXRSZXN1bHQ8VmFsdWUgPSBNYXliZUJ1ZmZlciwgRXh0cmFzID0gTWF5YmVCdWZmZXI+IHtcbiAgdmFsdWU6IFZhbHVlO1xuICBleHRyYXM6IEV4dHJhcztcbiAgY2FzOiBDQVNUb2tlbiB8IHVuZGVmaW5lZDtcbn1cblxuZXhwb3J0IHR5cGUgR2V0TXVsdGlSZXN1bHQ8XG4gIEtleXMgZXh0ZW5kcyBzdHJpbmcgPSBzdHJpbmcsXG4gIFZhbHVlID0gTWF5YmVCdWZmZXIsXG4gIEV4dHJhcyA9IE1heWJlQnVmZmVyXG4+ID0ge1xuICBbSyBpbiBLZXlzXT86IEdldFJlc3VsdDxWYWx1ZSwgRXh0cmFzPjtcbn07XG5cbmNsYXNzIENsaWVudDxWYWx1ZSA9IE1heWJlQnVmZmVyLCBFeHRyYXMgPSBNYXliZUJ1ZmZlcj4ge1xuICBzZXJ2ZXJzOiBTZXJ2ZXJbXTtcbiAgc2VxOiBudW1iZXI7XG4gIG9wdGlvbnM6IEJhc2VDbGllbnRPcHRpb25zICYgUGFydGlhbDxTZXJpYWxpemVyUHJvcDxWYWx1ZSwgRXh0cmFzPj47XG4gIHNlcmlhbGl6ZXI6IFNlcmlhbGl6ZXI8VmFsdWUsIEV4dHJhcz47XG4gIHNlcnZlck1hcDogeyBbaG9zdHBvcnQ6IHN0cmluZ106IFNlcnZlciB9O1xuICBzZXJ2ZXJLZXlzOiBzdHJpbmdbXTtcblxuICAvLyBDbGllbnQgaW5pdGlhbGl6ZXIgdGFrZXMgYSBsaXN0IG9mIGBTZXJ2ZXJgcyBhbmQgYW4gYG9wdGlvbnNgIGRpY3Rpb25hcnkuXG4gIC8vIFNlZSBgQ2xpZW50LmNyZWF0ZWAgZm9yIGRldGFpbHMuXG4gIGNvbnN0cnVjdG9yKHNlcnZlcnM6IFNlcnZlcltdLCBvcHRpb25zOiBHaXZlbkNsaWVudE9wdGlvbnM8VmFsdWUsIEV4dHJhcz4pIHtcbiAgICB0aGlzLnNlcnZlcnMgPSBzZXJ2ZXJzO1xuICAgIHRoaXMuc2VxID0gMDtcbiAgICB0aGlzLm9wdGlvbnMgPSBtZXJnZShvcHRpb25zIHx8IHt9LCB7XG4gICAgICByZXRyaWVzOiAyLFxuICAgICAgcmV0cnlfZGVsYXk6IDAuMixcbiAgICAgIGV4cGlyZXM6IDAsXG4gICAgICBsb2dnZXI6IGNvbnNvbGUsXG4gICAgICBrZXlUb1NlcnZlckhhc2hGdW5jdGlvbjogZGVmYXVsdEtleVRvU2VydmVySGFzaEZ1bmN0aW9uLFxuICAgIH0pO1xuXG4gICAgdGhpcy5zZXJpYWxpemVyID0gdGhpcy5vcHRpb25zLnNlcmlhbGl6ZXIgfHwgKG5vb3BTZXJpYWxpemVyIGFzIGFueSk7XG5cbiAgICAvLyBTdG9yZSBhIG1hcHBpbmcgZnJvbSBob3N0cG9ydCAtPiBzZXJ2ZXIgc28gd2UgY2FuIHF1aWNrbHkgZ2V0IGEgc2VydmVyIG9iamVjdCBmcm9tIHRoZSBzZXJ2ZXJLZXkgcmV0dXJuZWQgYnkgdGhlIGhhc2hpbmcgZnVuY3Rpb25cbiAgICBjb25zdCBzZXJ2ZXJNYXA6IHsgW2hvc3Rwb3J0OiBzdHJpbmddOiBTZXJ2ZXIgfSA9IHt9O1xuICAgIHRoaXMuc2VydmVycy5mb3JFYWNoKGZ1bmN0aW9uIChzZXJ2ZXIpIHtcbiAgICAgIHNlcnZlck1hcFtzZXJ2ZXIuaG9zdHBvcnRTdHJpbmcoKV0gPSBzZXJ2ZXI7XG4gICAgfSk7XG4gICAgdGhpcy5zZXJ2ZXJNYXAgPSBzZXJ2ZXJNYXA7XG5cbiAgICAvLyBzdG9yZSBhIGxpc3Qgb2YgYWxsIG91ciBzZXJ2ZXJLZXlzIHNvIHdlIGRvbid0IG5lZWQgdG8gY29uc3RhbnRseSByZWFsbG9jYXRlIHRoaXMgYXJyYXlcbiAgICB0aGlzLnNlcnZlcktleXMgPSBPYmplY3Qua2V5cyh0aGlzLnNlcnZlck1hcCk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIG5ldyBjbGllbnQgZ2l2ZW4gYW4gb3B0aW9uYWwgY29uZmlnIHN0cmluZyBhbmQgb3B0aW9uYWwgaGFzaCBvZlxuICAgKiBvcHRpb25zLiBUaGUgY29uZmlnIHN0cmluZyBzaG91bGQgYmUgb2YgdGhlIGZvcm06XG4gICAqXG4gICAqICAgICBcIlt1c2VyOnBhc3NAXXNlcnZlcjFbOjExMjExXSxbdXNlcjpwYXNzQF1zZXJ2ZXIyWzoxMTIxMV0sLi4uXCJcbiAgICpcbiAgICogSWYgdGhlIGFyZ3VtZW50IGlzIG5vdCBnaXZlbiwgZmFsbGJhY2sgb24gdGhlIGBNRU1DQUNISUVSX1NFUlZFUlNgIGVudmlyb25tZW50XG4gICAqIHZhcmlhYmxlLCBgTUVNQ0FDSEVfU0VSVkVSU2AgZW52aXJvbm1lbnQgdmFyaWFibGUgb3IgYFwibG9jYWxob3N0OjExMjExXCJgLlxuICAgKlxuICAgKiBUaGUgb3B0aW9ucyBoYXNoIG1heSBjb250YWluIHRoZSBvcHRpb25zOlxuICAgKlxuICAgKiAqIGByZXRyaWVzYCAtIHRoZSBudW1iZXIgb2YgdGltZXMgdG8gcmV0cnkgYW4gb3BlcmF0aW9uIGluIGxpZXUgb2YgZmFpbHVyZXNcbiAgICogKGRlZmF1bHQgMilcbiAgICogKiBgZXhwaXJlc2AgLSB0aGUgZGVmYXVsdCBleHBpcmF0aW9uIGluIHNlY29uZHMgdG8gdXNlIChkZWZhdWx0IDAgLSBuZXZlclxuICAgKiBleHBpcmUpLiBJZiBgZXhwaXJlc2AgaXMgZ3JlYXRlciB0aGFuIDMwIGRheXMgKDYwIHggNjAgeCAyNCB4IDMwKSwgaXQgaXNcbiAgICogdHJlYXRlZCBhcyBhIFVOSVggdGltZSAobnVtYmVyIG9mIHNlY29uZHMgc2luY2UgSmFudWFyeSAxLCAxOTcwKS5cbiAgICogKiBgbG9nZ2VyYCAtIGEgbG9nZ2VyIG9iamVjdCB0aGF0IHJlc3BvbmRzIHRvIGBsb2coc3RyaW5nKWAgbWV0aG9kIGNhbGxzLlxuICAgKlxuICAgKiAgIH5+fn5cbiAgICogICAgIGxvZyhtc2cxWywgbXNnMlssIG1zZzNbLi4uXV1dKVxuICAgKiAgIH5+fn5cbiAgICpcbiAgICogICBEZWZhdWx0cyB0byBgY29uc29sZWAuXG4gICAqICogYHNlcmlhbGl6ZXJgIC0gdGhlIG9iamVjdCB3aGljaCB3aWxsIChkZSlzZXJpYWxpemUgdGhlIGRhdGEuIEl0IG5lZWRzXG4gICAqICAgdHdvIHB1YmxpYyBtZXRob2RzOiBzZXJpYWxpemUgYW5kIGRlc2VyaWFsaXplLiBJdCBkZWZhdWx0cyB0byB0aGVcbiAgICogICBub29wU2VyaWFsaXplcjpcbiAgICpcbiAgICogICB+fn5+XG4gICAqICAgY29uc3Qgbm9vcFNlcmlhbGl6ZXIgPSB7XG4gICAqICAgICBzZXJpYWxpemU6IGZ1bmN0aW9uIChvcGNvZGUsIHZhbHVlLCBleHRyYXMpIHtcbiAgICogICAgICAgcmV0dXJuIHsgdmFsdWU6IHZhbHVlLCBleHRyYXM6IGV4dHJhcyB9O1xuICAgKiAgICAgfSxcbiAgICogICAgIGRlc2VyaWFsaXplOiBmdW5jdGlvbiAob3Bjb2RlLCB2YWx1ZSwgZXh0cmFzKSB7XG4gICAqICAgICAgIHJldHVybiB7IHZhbHVlOiB2YWx1ZSwgZXh0cmFzOiBleHRyYXMgfTtcbiAgICogICAgIH1cbiAgICogICB9O1xuICAgKiAgIH5+fn5cbiAgICpcbiAgICogT3Igb3B0aW9ucyBmb3IgdGhlIHNlcnZlcnMgaW5jbHVkaW5nOlxuICAgKiAqIGB1c2VybmFtZWAgYW5kIGBwYXNzd29yZGAgZm9yIGZhbGxiYWNrIFNBU0wgYXV0aGVudGljYXRpb24gY3JlZGVudGlhbHMuXG4gICAqICogYHRpbWVvdXRgIGluIHNlY29uZHMgdG8gZGV0ZXJtaW5lIGZhaWx1cmUgZm9yIG9wZXJhdGlvbnMuIERlZmF1bHQgaXMgMC41XG4gICAqICAgICAgICAgICAgIHNlY29uZHMuXG4gICAqICogJ2Nvbm50aW1lb3V0JyBpbiBzZWNvbmRzIHRvIGNvbm5lY3Rpb24gZmFpbHVyZS4gRGVmYXVsdCBpcyB0d2ljZSB0aGUgdmFsdWVcbiAgICogICAgICAgICAgICAgICAgIG9mIGB0aW1lb3V0YC5cbiAgICogKiBga2VlcEFsaXZlYCB3aGV0aGVyIHRvIGVuYWJsZSBrZWVwLWFsaXZlIGZ1bmN0aW9uYWxpdHkuIERlZmF1bHRzIHRvIGZhbHNlLlxuICAgKiAqIGBrZWVwQWxpdmVEZWxheWAgaW4gc2Vjb25kcyB0byB0aGUgaW5pdGlhbCBkZWxheSBiZWZvcmUgdGhlIGZpcnN0IGtlZXBhbGl2ZVxuICAgKiAgICAgICAgICAgICAgICAgICAgcHJvYmUgaXMgc2VudCBvbiBhbiBpZGxlIHNvY2tldC4gRGVmYXVsdHMgaXMgMzAgc2Vjb25kcy5cbiAgICogKiBga2V5VG9TZXJ2ZXJIYXNoRnVuY3Rpb25gIGEgZnVuY3Rpb24gdG8gbWFwIGtleXMgdG8gc2VydmVycywgd2l0aCB0aGUgc2lnbmF0dXJlXG4gICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgIChzZXJ2ZXJLZXlzOiBzdHJpbmdbXSwga2V5OiBzdHJpbmcpOiBzdHJpbmdcbiAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgTk9URTogaWYgeW91IG5lZWQgdG8gZG8gc29tZSBleHBlbnNpdmUgaW5pdGlhbGl6YXRpb24sICpwbGVhc2UqIGRvIGl0IGxhemlseSB0aGUgZmlyc3QgdGltZSB5b3UgdGhpcyBmdW5jdGlvbiBpcyBjYWxsZWQgd2l0aCBhbiBhcnJheSBvZiBzZXJ2ZXJLZXlzLCBub3Qgb24gZXZlcnkgY2FsbFxuICAgKi9cbiAgc3RhdGljIGNyZWF0ZTxWYWx1ZSwgRXh0cmFzPihcbiAgICBzZXJ2ZXJzU3RyOiBzdHJpbmcgfCB1bmRlZmluZWQsXG4gICAgb3B0aW9uczogSWZCdWZmZXI8XG4gICAgICBWYWx1ZSxcbiAgICAgIEV4dHJhcyxcbiAgICAgIHVuZGVmaW5lZCB8IChQYXJ0aWFsPFNlcnZlck9wdGlvbnM+ICYgR2l2ZW5DbGllbnRPcHRpb25zPFZhbHVlLCBFeHRyYXM+KSxcbiAgICAgIFBhcnRpYWw8U2VydmVyT3B0aW9ucz4gJiBHaXZlbkNsaWVudE9wdGlvbnM8VmFsdWUsIEV4dHJhcz5cbiAgICA+XG4gICk6IENsaWVudDxWYWx1ZSwgRXh0cmFzPiB7XG4gICAgc2VydmVyc1N0ciA9XG4gICAgICBzZXJ2ZXJzU3RyIHx8XG4gICAgICBwcm9jZXNzLmVudi5NRU1DQUNISUVSX1NFUlZFUlMgfHxcbiAgICAgIHByb2Nlc3MuZW52Lk1FTUNBQ0hFX1NFUlZFUlMgfHxcbiAgICAgIFwibG9jYWxob3N0OjExMjExXCI7XG4gICAgY29uc3Qgc2VydmVyVXJpcyA9IHNlcnZlcnNTdHIuc3BsaXQoXCIsXCIpO1xuICAgIGNvbnN0IHNlcnZlcnMgPSBzZXJ2ZXJVcmlzLm1hcChmdW5jdGlvbiAodXJpKSB7XG4gICAgICBjb25zdCB1cmlQYXJ0cyA9IHVyaS5zcGxpdChcIkBcIik7XG4gICAgICBjb25zdCBob3N0UG9ydCA9IHVyaVBhcnRzW3VyaVBhcnRzLmxlbmd0aCAtIDFdLnNwbGl0KFwiOlwiKTtcbiAgICAgIGNvbnN0IHVzZXJQYXNzID0gKHVyaVBhcnRzW3VyaVBhcnRzLmxlbmd0aCAtIDJdIHx8IFwiXCIpLnNwbGl0KFwiOlwiKTtcbiAgICAgIHJldHVybiBuZXcgU2VydmVyKFxuICAgICAgICBob3N0UG9ydFswXSxcbiAgICAgICAgcGFyc2VJbnQoaG9zdFBvcnRbMV0gfHwgXCIxMTIxMVwiLCAxMCksXG4gICAgICAgIHVzZXJQYXNzWzBdLFxuICAgICAgICB1c2VyUGFzc1sxXSxcbiAgICAgICAgb3B0aW9uc1xuICAgICAgKTtcbiAgICB9KTtcbiAgICByZXR1cm4gbmV3IENsaWVudChzZXJ2ZXJzLCBvcHRpb25zIGFzIGFueSk7XG4gIH1cblxuICAvKipcbiAgICogR2l2ZW4gYSBzZXJ2ZXJLZXkgZnJvbWxvb2t1cEtleVRvU2VydmVyS2V5LCByZXR1cm4gdGhlIGNvcnJlc3BvbmRpbmcgU2VydmVyIGluc3RhbmNlXG4gICAqXG4gICAqIEBwYXJhbSAge3N0cmluZ30gc2VydmVyS2V5XG4gICAqIEByZXR1cm5zIHtTZXJ2ZXJ9XG4gICAqL1xuICBzZXJ2ZXJLZXlUb1NlcnZlcihzZXJ2ZXJLZXk6IHN0cmluZyk6IFNlcnZlciB7XG4gICAgcmV0dXJuIHRoaXMuc2VydmVyTWFwW3NlcnZlcktleV07XG4gIH1cblxuICAvKipcbiAgICogR2l2ZW4gYSBrZXkgdG8gbG9vayB1cCBpbiBtZW1jYWNoZSwgcmV0dXJuIGEgc2VydmVyS2V5IChiYXNlZCBvbiBzb21lXG4gICAqIGhhc2hpbmcgZnVuY3Rpb24pIHdoaWNoIGNhbiBiZSB1c2VkIHRvIGluZGV4IHRoaXMuc2VydmVyTWFwXG4gICAqL1xuICBsb29rdXBLZXlUb1NlcnZlcktleShrZXk6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMub3B0aW9ucy5rZXlUb1NlcnZlckhhc2hGdW5jdGlvbih0aGlzLnNlcnZlcktleXMsIGtleSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldmVzIHRoZSB2YWx1ZSBhdCB0aGUgZ2l2ZW4ga2V5IGluIG1lbWNhY2hlLlxuICAgKi9cbiAgYXN5bmMgZ2V0KGtleTogc3RyaW5nKTogUHJvbWlzZTxHZXRSZXN1bHQ8VmFsdWUsIEV4dHJhcz4gfCBudWxsPiB7XG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKGNvbnN0YW50cy5PUF9HRVQsIGtleSwgXCJcIiwgXCJcIiwgdGhpcy5zZXEpO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICBjb25zdCBkZXNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuZGVzZXJpYWxpemUoXG4gICAgICAgICAgcmVzcG9uc2UuaGVhZGVyLm9wY29kZSxcbiAgICAgICAgICByZXNwb25zZS52YWwsXG4gICAgICAgICAgcmVzcG9uc2UuZXh0cmFzXG4gICAgICAgICk7XG4gICAgICAgIHJldHVybiB7IC4uLmRlc2VyaWFsaXplZCwgY2FzOiByZXNwb25zZS5oZWFkZXIuY2FzIH07XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIkdFVFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKiogQnVpbGQgYSBwaXBlbGluZWQgZ2V0IG11bHRpIHJlcXVlc3QgYnkgc2VuZGluZyBvbmUgR0VUS1EgZm9yIGVhY2gga2V5IChxdWlldCwgbWVhbmluZyBpdCB3b24ndCByZXNwb25kIGlmIHRoZSB2YWx1ZSBpcyBtaXNzaW5nKSBmb2xsb3dlZCBieSBhIG5vLW9wIHRvIGZvcmNlIGEgcmVzcG9uc2UgKGFuZCB0byBnaXZlIHVzIGEgc2VudGluZWwgcmVzcG9uc2UgdGhhdCB0aGUgcGlwZWxpbmUgaXMgZG9uZSlcbiAgICpcbiAgICogY2YgaHR0cHM6Ly9naXRodWIuY29tL2NvdWNoYmFzZS9tZW1jYWNoZWQvYmxvYi9tYXN0ZXIvZG9jcy9CaW5hcnlQcm90b2NvbC5tZCMweDBkLWdldGtxLWdldC13aXRoLWtleS1xdWlldGx5XG4gICAqL1xuICBfYnVpbGRHZXRNdWx0aVJlcXVlc3Qoa2V5czogc3RyaW5nW10sIHNlcTogbnVtYmVyKTogQnVmZmVyIHtcbiAgICAvLyBzdGFydCBhdCAyNCBmb3IgdGhlIG5vLW9wIGNvbW1hbmQgYXQgdGhlIGVuZFxuICAgIGxldCByZXF1ZXN0U2l6ZSA9IDI0O1xuICAgIGZvciAoY29uc3Qga2V5SWR4IGluIGtleXMpIHtcbiAgICAgIHJlcXVlc3RTaXplICs9IEJ1ZmZlci5ieXRlTGVuZ3RoKGtleXNba2V5SWR4XSwgXCJ1dGY4XCIpICsgMjQ7XG4gICAgfVxuXG4gICAgY29uc3QgcmVxdWVzdCA9IEJ1ZmZlci5hbGxvYyhyZXF1ZXN0U2l6ZSk7XG5cbiAgICBsZXQgYnl0ZXNXcml0dGVuID0gMDtcbiAgICBmb3IgKGNvbnN0IGtleUlkeCBpbiBrZXlzKSB7XG4gICAgICBjb25zdCBrZXkgPSBrZXlzW2tleUlkeF07XG4gICAgICBieXRlc1dyaXR0ZW4gKz0gY29weUludG9SZXF1ZXN0QnVmZmVyKFxuICAgICAgICBjb25zdGFudHMuT1BfR0VUS1EsXG4gICAgICAgIGtleSxcbiAgICAgICAgXCJcIixcbiAgICAgICAgXCJcIixcbiAgICAgICAgc2VxLFxuICAgICAgICByZXF1ZXN0LFxuICAgICAgICBieXRlc1dyaXR0ZW5cbiAgICAgICk7XG4gICAgfVxuXG4gICAgYnl0ZXNXcml0dGVuICs9IGNvcHlJbnRvUmVxdWVzdEJ1ZmZlcihcbiAgICAgIGNvbnN0YW50cy5PUF9OT19PUCxcbiAgICAgIFwiXCIsXG4gICAgICBcIlwiLFxuICAgICAgXCJcIixcbiAgICAgIHNlcSxcbiAgICAgIHJlcXVlc3QsXG4gICAgICBieXRlc1dyaXR0ZW5cbiAgICApO1xuXG4gICAgcmV0dXJuIHJlcXVlc3Q7XG4gIH1cblxuICAvKiogRXhlY3V0aW5nIGEgcGlwZWxpbmVkIChtdWx0aSkgZ2V0IGFnYWluc3QgYSBzaW5nbGUgc2VydmVyLiBUaGlzIGlzIGEgcHJpdmF0ZSBpbXBsZW1lbnRhdGlvbiBkZXRhaWwgb2YgZ2V0TXVsdGkuICovXG4gIGFzeW5jIF9nZXRNdWx0aVRvU2VydmVyPEtleXMgZXh0ZW5kcyBzdHJpbmc+KFxuICAgIHNlcnY6IFNlcnZlcixcbiAgICBrZXlzOiBLZXlzW11cbiAgKTogUHJvbWlzZTxHZXRNdWx0aVJlc3VsdDxLZXlzLCBWYWx1ZSwgRXh0cmFzPj4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBjb25zdCByZXNwb25zZU1hcDogR2V0TXVsdGlSZXN1bHQ8c3RyaW5nLCBWYWx1ZSwgRXh0cmFzPiA9IHt9O1xuXG4gICAgICBjb25zdCBoYW5kbGU6IE9uUmVzcG9uc2VDYWxsYmFjayA9IChyZXNwb25zZSkgPT4ge1xuICAgICAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgICAgICAvLyBXaGVuIHdlIGdldCB0aGUgbm8tb3AgcmVzcG9uc2UsIHdlIGFyZSBkb25lIHdpdGggdGhpcyBvbmUgZ2V0TXVsdGkgaW4gdGhlIHBlci1iYWNrZW5kIGZhbi1vdXRcbiAgICAgICAgICAgIGlmIChyZXNwb25zZS5oZWFkZXIub3Bjb2RlID09PSBjb25zdGFudHMuT1BfTk9fT1ApIHtcbiAgICAgICAgICAgICAgLy8gVGhpcyBlbnN1cmVzIHRoZSBoYW5kbGVyIHdpbGwgYmUgZGVsZXRlZCBmcm9tIHRoZSByZXNwb25zZUNhbGxiYWNrcyBtYXAgaW4gc2VydmVyLmpzXG4gICAgICAgICAgICAgIC8vIFRoaXMgaXNuJ3QgdGVjaG5pY2FsbHkgbmVlZGVkIGhlcmUgYmVjYXVzZSB0aGUgbG9naWMgaW4gc2VydmVyLmpzIGFsc28gY2hlY2tzIGlmIHRvdGFsQm9keUxlbmd0aCA9PT0gMCwgYnV0IG91ciB1bml0dGVzdHMgYXJlbid0IGdyZWF0IGFib3V0IHNldHRpbmcgdGhhdCBmaWVsZCwgYW5kIGFsc28gdGhpcyBtYWtlcyBpdCBtb3JlIGV4cGxpY2l0XG4gICAgICAgICAgICAgIGhhbmRsZS5xdWlldCA9IGZhbHNlO1xuICAgICAgICAgICAgICByZXNvbHZlKHJlc3BvbnNlTWFwKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAocmVzcG9uc2UuaGVhZGVyLm9wY29kZSA9PT0gY29uc3RhbnRzLk9QX0dFVEsgfHwgcmVzcG9uc2UuaGVhZGVyLm9wY29kZSA9PT0gY29uc3RhbnRzLk9QX0dFVEtRKSB7XG4gICAgICAgICAgICAgIGNvbnN0IGRlc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5kZXNlcmlhbGl6ZShcbiAgICAgICAgICAgICAgICByZXNwb25zZS5oZWFkZXIub3Bjb2RlLFxuICAgICAgICAgICAgICAgIHJlc3BvbnNlLnZhbCxcbiAgICAgICAgICAgICAgICByZXNwb25zZS5leHRyYXNcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgY29uc3Qga2V5ID0gcmVzcG9uc2Uua2V5LnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgIGlmIChrZXkubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlamVjdChcbiAgICAgICAgICAgICAgICAgIG5ldyBFcnJvcihcIlJlY2lldmVkIGVtcHR5IGtleSBpbiBnZXRNdWx0aTogXCIgKyBKU09OLnN0cmluZ2lmeShyZXNwb25zZSkpXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICByZXNwb25zZU1hcFtrZXldID0geyAuLi5kZXNlcmlhbGl6ZWQsIGNhczogcmVzcG9uc2UuaGVhZGVyLmNhcyB9O1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgcmV0dXJuIHJlamVjdChcbiAgICAgICAgICAgICAgICBuZXcgRXJyb3IoXCJSZWNpZXZlZCByZXNwb25zZSBpbiBnZXRNdWx0aSBmb3IgdW5rbm93biBvcGNvZGU6IFwiICsgSlNPTi5zdHJpbmdpZnkocmVzcG9uc2UpKVxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHJldHVybiByZWplY3QoXG4gICAgICAgICAgICAgIHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJHRVRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cylcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH07XG4gICAgICAvLyBUaGlzIHByZXZlbnRzIHRoZSBoYW5kbGVyIGZyb20gYmVpbmcgZGVsZXRlZFxuICAgICAgLy8gYWZ0ZXIgdGhlIGZpcnN0IHJlc3BvbnNlLiBMb2dpYyBpbiBzZXJ2ZXIuanMuXG4gICAgICBoYW5kbGUucXVpZXQgPSB0cnVlO1xuXG4gICAgICBjb25zdCBzZXEgPSB0aGlzLmluY3JTZXEoKTtcbiAgICAgIGNvbnN0IHJlcXVlc3QgPSB0aGlzLl9idWlsZEdldE11bHRpUmVxdWVzdChrZXlzLCBzZXEpO1xuICAgICAgc2Vydi5vblJlc3BvbnNlKHRoaXMuc2VxLCBoYW5kbGUpO1xuICAgICAgc2Vydi5vbkVycm9yKHRoaXMuc2VxLCByZWplY3QpO1xuICAgICAgc2Vydi53cml0ZShyZXF1ZXN0KTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXRyaWV2cyB0aGUgdmFsdWUgYXQgdGhlIGdpdmVuIGtleXMgaW4gbWVtY2FjaGVkLiBSZXR1cm5zIGEgbWFwIGZyb20gdGhlXG4gICAqIHJlcXVlc3RlZCBrZXlzIHRvIHJlc3VsdHMsIG9yIG51bGwgaWYgdGhlIGtleSB3YXMgbm90IGZvdW5kLlxuICAgKi9cbiAgYXN5bmMgZ2V0TXVsdGk8S2V5cyBleHRlbmRzIHN0cmluZz4oXG4gICAga2V5czogS2V5c1tdXG4gICk6IFByb21pc2U8R2V0TXVsdGlSZXN1bHQ8S2V5cywgVmFsdWUsIEV4dHJhcz4+IHtcbiAgICBjb25zdCBzZXJ2ZXJLZXl0b0xvb2t1cEtleXM6IHtcbiAgICAgIFtzZXJ2ZXJLZXk6IHN0cmluZ106IHN0cmluZ1tdO1xuICAgIH0gPSB7fTtcbiAgICBrZXlzLmZvckVhY2goKGxvb2t1cEtleSkgPT4ge1xuICAgICAgY29uc3Qgc2VydmVyS2V5ID0gdGhpcy5sb29rdXBLZXlUb1NlcnZlcktleShsb29rdXBLZXkpO1xuICAgICAgaWYgKCFzZXJ2ZXJLZXl0b0xvb2t1cEtleXNbc2VydmVyS2V5XSkge1xuICAgICAgICBzZXJ2ZXJLZXl0b0xvb2t1cEtleXNbc2VydmVyS2V5XSA9IFtdO1xuICAgICAgfVxuICAgICAgc2VydmVyS2V5dG9Mb29rdXBLZXlzW3NlcnZlcktleV0ucHVzaChsb29rdXBLZXkpO1xuICAgIH0pO1xuXG4gICAgY29uc3QgdXNlZFNlcnZlcktleXMgPSBPYmplY3Qua2V5cyhzZXJ2ZXJLZXl0b0xvb2t1cEtleXMpO1xuICAgIGNvbnN0IHJlc3VsdHMgPSBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIHVzZWRTZXJ2ZXJLZXlzLm1hcCgoc2VydmVyS2V5KSA9PiB7XG4gICAgICAgIGNvbnN0IHNlcnZlciA9IHRoaXMuc2VydmVyS2V5VG9TZXJ2ZXIoc2VydmVyS2V5KTtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2dldE11bHRpVG9TZXJ2ZXIoc2VydmVyLCBzZXJ2ZXJLZXl0b0xvb2t1cEtleXNbc2VydmVyS2V5XSk7XG4gICAgICB9KVxuICAgICk7XG5cbiAgICByZXR1cm4gT2JqZWN0LmFzc2lnbih7fSwgLi4ucmVzdWx0cyk7XG4gIH1cblxuICAvKipcbiAgICogU2V0cyBga2V5YCB0byBgdmFsdWVgLlxuICAgKi9cbiAgYXN5bmMgc2V0KFxuICAgIGtleTogc3RyaW5nLFxuICAgIHZhbHVlOiBWYWx1ZSxcbiAgICBvcHRpb25zPzogeyBleHBpcmVzPzogbnVtYmVyOyBjYXM/OiBDQVNUb2tlbiB9XG4gICk6IFByb21pc2U8Ym9vbGVhbiB8IG51bGw+IHtcbiAgICBjb25zdCBleHBpcmVzID0gb3B0aW9ucz8uZXhwaXJlcztcbiAgICBjb25zdCBjYXMgPSBvcHRpb25zPy5jYXM7XG5cbiAgICAvLyBUT0RPOiBzdXBwb3J0IGZsYWdzXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgZXhwaXJhdGlvbiA9IG1ha2VFeHBpcmF0aW9uKGV4cGlyZXMgfHwgdGhpcy5vcHRpb25zLmV4cGlyZXMpO1xuICAgIGNvbnN0IGV4dHJhcyA9IEJ1ZmZlci5jb25jYXQoW0J1ZmZlci5mcm9tKFwiMDAwMDAwMDBcIiwgXCJoZXhcIiksIGV4cGlyYXRpb25dKTtcbiAgICBjb25zdCBzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLnNlcmlhbGl6ZShcbiAgICAgIGNvbnN0YW50cy5PUF9TRVQsXG4gICAgICB2YWx1ZSxcbiAgICAgIGV4dHJhc1xuICAgICk7XG4gICAgY29uc3QgcmVxdWVzdCA9IFV0aWxzLmVuY29kZVJlcXVlc3Qoe1xuICAgICAgaGVhZGVyOiB7XG4gICAgICAgIG9wY29kZTogY29uc3RhbnRzLk9QX1NFVCxcbiAgICAgICAgb3BhcXVlOiB0aGlzLnNlcSxcbiAgICAgICAgY2FzLFxuICAgICAgfSxcbiAgICAgIGtleSxcbiAgICAgIHZhbHVlOiBzZXJpYWxpemVkLnZhbHVlLFxuICAgICAgZXh0cmFzOiBzZXJpYWxpemVkLmV4dHJhcyxcbiAgICB9KTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9FWElTVFM6XG4gICAgICAgIGlmIChjYXMpIHtcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIlNFVFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICAgICAgfVxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIlNFVFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQUREXG4gICAqXG4gICAqIEFkZHMgdGhlIGdpdmVuIF9rZXlfIGFuZCBfdmFsdWVfIHRvIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHNcbiAgICogaWYgdGhlIGtleSBpcyBub3QgYWxyZWFkeSBzZXQuXG4gICAqXG4gICAqIFRoZSBvcHRpb25zIGRpY3Rpb25hcnkgdGFrZXM6XG4gICAqICogX2V4cGlyZXNfOiBvdmVycmlkZXMgdGhlIGRlZmF1bHQgZXhwaXJhdGlvbiAoc2VlIGBDbGllbnQuY3JlYXRlYCkgZm9yIHRoaXNcbiAgICogICAgICAgICAgICAgIHBhcnRpY3VsYXIga2V5LXZhbHVlIHBhaXIuXG4gICAqL1xuICBhc3luYyBhZGQoXG4gICAga2V5OiBzdHJpbmcsXG4gICAgdmFsdWU6IFZhbHVlLFxuICAgIG9wdGlvbnM/OiB7IGV4cGlyZXM/OiBudW1iZXIgfVxuICApOiBQcm9taXNlPGJvb2xlYW4gfCBudWxsPiB7XG4gICAgLy8gVE9ETzogc3VwcG9ydCBmbGFncywgc3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgZXhwaXJhdGlvbiA9IG1ha2VFeHBpcmF0aW9uKG9wdGlvbnM/LmV4cGlyZXMgfHwgdGhpcy5vcHRpb25zLmV4cGlyZXMpO1xuICAgIGNvbnN0IGV4dHJhcyA9IEJ1ZmZlci5jb25jYXQoW0J1ZmZlci5mcm9tKFwiMDAwMDAwMDBcIiwgXCJoZXhcIiksIGV4cGlyYXRpb25dKTtcblxuICAgIGNvbnN0IG9wY29kZSA9IGNvbnN0YW50cy5PUF9BREQ7XG4gICAgY29uc3Qgc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5zZXJpYWxpemUob3Bjb2RlLCB2YWx1ZSwgZXh0cmFzKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICBvcGNvZGUsXG4gICAgICBrZXksXG4gICAgICBzZXJpYWxpemVkLmV4dHJhcyxcbiAgICAgIHNlcmlhbGl6ZWQudmFsdWUsXG4gICAgICB0aGlzLnNlcVxuICAgICk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfRVhJU1RTOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIkFERFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmVwbGFjZXMgdGhlIGdpdmVuIF9rZXlfIGFuZCBfdmFsdWVfIHRvIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHNcbiAgICogaWYgdGhlIGtleSBpcyBhbHJlYWR5IHByZXNlbnQuXG4gICAqL1xuICBhc3luYyByZXBsYWNlKFxuICAgIGtleTogc3RyaW5nLFxuICAgIHZhbHVlOiBWYWx1ZSxcbiAgICBvcHRpb25zPzogeyBleHBpcmVzPzogbnVtYmVyIH1cbiAgKTogUHJvbWlzZTxib29sZWFuIHwgbnVsbD4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgZmxhZ3MsIHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IGV4cGlyYXRpb24gPSBtYWtlRXhwaXJhdGlvbihvcHRpb25zPy5leHBpcmVzIHx8IHRoaXMub3B0aW9ucy5leHBpcmVzKTtcbiAgICBjb25zdCBleHRyYXMgPSBCdWZmZXIuY29uY2F0KFtCdWZmZXIuZnJvbShcIjAwMDAwMDAwXCIsIFwiaGV4XCIpLCBleHBpcmF0aW9uXSk7XG5cbiAgICBjb25zdCBvcGNvZGU6IGNvbnN0YW50cy5PUCA9IGNvbnN0YW50cy5PUF9SRVBMQUNFO1xuICAgIGNvbnN0IHNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuc2VyaWFsaXplKG9wY29kZSwgdmFsdWUsIGV4dHJhcyk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKFxuICAgICAgb3Bjb2RlLFxuICAgICAga2V5LFxuICAgICAgc2VyaWFsaXplZC5leHRyYXMsXG4gICAgICBzZXJpYWxpemVkLnZhbHVlLFxuICAgICAgdGhpcy5zZXFcbiAgICApO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuS0VZX05PVF9GT1VORDpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIlJFUExBQ0VcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIERlbGV0ZXMgdGhlIGdpdmVuIF9rZXlfIGZyb20gbWVtY2FjaGUuIFRoZSBvcGVyYXRpb24gb25seSBzdWNjZWVkc1xuICAgKiBpZiB0aGUga2V5IGlzIGFscmVhZHkgcHJlc2VudC5cbiAgICovXG4gIGFzeW5jIGRlbGV0ZShrZXk6IHN0cmluZyk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIC8vIFRPRE86IFN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcig0LCBrZXksIFwiXCIsIFwiXCIsIHRoaXMuc2VxKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcblxuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuS0VZX05PVF9GT1VORDpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIkRFTEVURVwiLCByZXNwb25zZT8uaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEluY3JlbWVudHMgdGhlIGdpdmVuIF9rZXlfIGluIG1lbWNhY2hlLlxuICAgKi9cbiAgYXN5bmMgaW5jcmVtZW50KFxuICAgIGtleTogc3RyaW5nLFxuICAgIGFtb3VudDogbnVtYmVyLFxuICAgIG9wdGlvbnM/OiB7IGluaXRpYWw/OiBudW1iZXI7IGV4cGlyZXM/OiBudW1iZXIgfVxuICApOiBQcm9taXNlPHsgdmFsdWU6IG51bWJlciB8IG51bGw7IHN1Y2Nlc3M6IGJvb2xlYW4gfCBudWxsIH0+IHtcbiAgICAvLyBUT0RPOiBzdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBpbml0aWFsID0gb3B0aW9ucz8uaW5pdGlhbCB8fCAwO1xuICAgIGNvbnN0IGV4cGlyZXMgPSBvcHRpb25zPy5leHBpcmVzIHx8IHRoaXMub3B0aW9ucy5leHBpcmVzO1xuICAgIGNvbnN0IGV4dHJhcyA9IG1ha2VBbW91bnRJbml0aWFsQW5kRXhwaXJhdGlvbihhbW91bnQsIGluaXRpYWwsIGV4cGlyZXMpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgIGNvbnN0YW50cy5PUF9JTkNSRU1FTlQsXG4gICAgICBrZXksXG4gICAgICBleHRyYXMsXG4gICAgICBcIlwiLFxuICAgICAgdGhpcy5zZXFcbiAgICApO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICBjb25zdCBidWZJbnQgPVxuICAgICAgICAgIChyZXNwb25zZS52YWwucmVhZFVJbnQzMkJFKDApIDw8IDgpICsgcmVzcG9uc2UudmFsLnJlYWRVSW50MzJCRSg0KTtcbiAgICAgICAgcmV0dXJuIHsgdmFsdWU6IGJ1ZkludCwgc3VjY2VzczogdHJ1ZSB9O1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIklOQ1JFTUVOVFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRGVjcmVtZW50cyB0aGUgZ2l2ZW4gYGtleWAgaW4gbWVtY2FjaGUuXG4gICAqL1xuICBhc3luYyBkZWNyZW1lbnQoXG4gICAga2V5OiBzdHJpbmcsXG4gICAgYW1vdW50OiBudW1iZXIsXG4gICAgb3B0aW9uczogeyBpbml0aWFsPzogbnVtYmVyOyBleHBpcmVzPzogbnVtYmVyIH1cbiAgKTogUHJvbWlzZTx7IHZhbHVlOiBudW1iZXIgfCBudWxsOyBzdWNjZXNzOiBib29sZWFuIHwgbnVsbCB9PiB7XG4gICAgLy8gVE9ETzogc3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgaW5pdGlhbCA9IG9wdGlvbnMuaW5pdGlhbCB8fCAwO1xuICAgIGNvbnN0IGV4cGlyZXMgPSBvcHRpb25zLmV4cGlyZXMgfHwgdGhpcy5vcHRpb25zLmV4cGlyZXM7XG4gICAgY29uc3QgZXh0cmFzID0gbWFrZUFtb3VudEluaXRpYWxBbmRFeHBpcmF0aW9uKGFtb3VudCwgaW5pdGlhbCwgZXhwaXJlcyk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKFxuICAgICAgY29uc3RhbnRzLk9QX0RFQ1JFTUVOVCxcbiAgICAgIGtleSxcbiAgICAgIGV4dHJhcyxcbiAgICAgIFwiXCIsXG4gICAgICB0aGlzLnNlcVxuICAgICk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIGNvbnN0IGJ1ZkludCA9XG4gICAgICAgICAgKHJlc3BvbnNlLnZhbC5yZWFkVUludDMyQkUoMCkgPDwgOCkgKyByZXNwb25zZS52YWwucmVhZFVJbnQzMkJFKDQpO1xuICAgICAgICByZXR1cm4geyB2YWx1ZTogYnVmSW50LCBzdWNjZXNzOiB0cnVlIH07XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiREVDUkVNRU5UXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBBcHBlbmQgdGhlIGdpdmVuIF92YWx1ZV8gdG8gdGhlIHZhbHVlIGFzc29jaWF0ZWQgd2l0aCB0aGUgZ2l2ZW4gX2tleV8gaW5cbiAgICogbWVtY2FjaGUuIFRoZSBvcGVyYXRpb24gb25seSBzdWNjZWVkcyBpZiB0aGUga2V5IGlzIGFscmVhZHkgcHJlc2VudC5cbiAgICovXG4gIGFzeW5jIGFwcGVuZChrZXk6IHN0cmluZywgdmFsdWU6IFZhbHVlKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgLy8gVE9ETzogc3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3Qgb3Bjb2RlOiBjb25zdGFudHMuT1AgPSBjb25zdGFudHMuT1BfQVBQRU5EO1xuICAgIGNvbnN0IHNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuc2VyaWFsaXplKG9wY29kZSwgdmFsdWUsIFwiXCIpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgIG9wY29kZSxcbiAgICAgIGtleSxcbiAgICAgIHNlcmlhbGl6ZWQuZXh0cmFzLFxuICAgICAgc2VyaWFsaXplZC52YWx1ZSxcbiAgICAgIHRoaXMuc2VxXG4gICAgKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJBUFBFTkRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFByZXBlbmQgdGhlIGdpdmVuIF92YWx1ZV8gdG8gdGhlIHZhbHVlIGFzc29jaWF0ZWQgd2l0aCB0aGUgZ2l2ZW4gX2tleV8gaW5cbiAgICogbWVtY2FjaGUuIFRoZSBvcGVyYXRpb24gb25seSBzdWNjZWVkcyBpZiB0aGUga2V5IGlzIGFscmVhZHkgcHJlc2VudC5cbiAgICovXG4gIGFzeW5jIHByZXBlbmQoa2V5OiBzdHJpbmcsIHZhbHVlOiBWYWx1ZSk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IG9wY29kZTogY29uc3RhbnRzLk9QID0gY29uc3RhbnRzLk9QX1BSRVBFTkQ7XG4gICAgY29uc3Qgc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5zZXJpYWxpemUob3Bjb2RlLCB2YWx1ZSwgXCJcIik7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKFxuICAgICAgb3Bjb2RlLFxuICAgICAga2V5LFxuICAgICAgc2VyaWFsaXplZC5leHRyYXMsXG4gICAgICBzZXJpYWxpemVkLnZhbHVlLFxuICAgICAgdGhpcy5zZXFcbiAgICApO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuS0VZX05PVF9GT1VORDpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIlBSRVBFTkRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFRvdWNoIHNldHMgYW4gZXhwaXJhdGlvbiB2YWx1ZSwgZ2l2ZW4gYnkgX2V4cGlyZXNfLCBvbiB0aGUgZ2l2ZW4gX2tleV8gaW5cbiAgICogbWVtY2FjaGUuIFRoZSBvcGVyYXRpb24gb25seSBzdWNjZWVkcyBpZiB0aGUga2V5IGlzIGFscmVhZHkgcHJlc2VudC5cbiAgICovXG4gIGFzeW5jIHRvdWNoKGtleTogc3RyaW5nLCBleHBpcmVzOiBudW1iZXIpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAvLyBUT0RPOiBzdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBleHRyYXMgPSBtYWtlRXhwaXJhdGlvbihleHBpcmVzIHx8IHRoaXMub3B0aW9ucy5leHBpcmVzKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoMHgxYywga2V5LCBleHRyYXMsIFwiXCIsIHRoaXMuc2VxKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJUT1VDSFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRkxVU0hcbiAgICpcbiAgICogRmx1c2hlcyB0aGUgY2FjaGUgb24gZWFjaCBjb25uZWN0ZWQgc2VydmVyLiBUaGUgY2FsbGJhY2sgc2lnbmF0dXJlIGlzOlxuICAgKlxuICAgKiAgICAgY2FsbGJhY2sobGFzdEVyciwgcmVzdWx0cylcbiAgICpcbiAgICogd2hlcmUgX2xhc3RFcnJfIGlzIHRoZSBsYXN0IGVycm9yIGVuY291bnRlcmVkIChvciBudWxsLCBpbiB0aGUgY29tbW9uIGNhc2VcbiAgICogb2Ygbm8gZXJyb3JzKS4gX3Jlc3VsdHNfIGlzIGEgZGljdGlvbmFyeSBtYXBwaW5nIGBcImhvc3RuYW1lOnBvcnRcImAgdG8gZWl0aGVyXG4gICAqIGB0cnVlYCAoaWYgdGhlIG9wZXJhdGlvbiB3YXMgc3VjY2Vzc2Z1bCksIG9yIGFuIGVycm9yLlxuICAgKiBAcGFyYW0gY2FsbGJhY2tcbiAgICovXG4gIGZsdXNoKCk6IFByb21pc2U8UmVjb3JkPHN0cmluZywgYm9vbGVhbiB8IEVycm9yPj47XG4gIGZsdXNoKFxuICAgIGNhbGxiYWNrOiAoXG4gICAgICBlcnI6IEVycm9yIHwgbnVsbCxcbiAgICAgIHJlc3VsdHM6IFJlY29yZDxzdHJpbmcsIGJvb2xlYW4gfCBFcnJvcj5cbiAgICApID0+IHZvaWRcbiAgKTogdm9pZDtcbiAgZmx1c2goXG4gICAgY2FsbGJhY2s/OiAoXG4gICAgICBlcnI6IEVycm9yIHwgbnVsbCxcbiAgICAgIHJlc3VsdHM6IFJlY29yZDxzdHJpbmcsIGJvb2xlYW4gfCBFcnJvcj5cbiAgICApID0+IHZvaWRcbiAgKSB7XG4gICAgaWYgKGNhbGxiYWNrID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybiBwcm9taXNpZnkoKGNhbGxiYWNrKSA9PiB7XG4gICAgICAgIHRoaXMuZmx1c2goZnVuY3Rpb24gKGVyciwgcmVzdWx0cykge1xuICAgICAgICAgIGNhbGxiYWNrKGVyciwgcmVzdWx0cyk7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfVxuICAgIC8vIFRPRE86IHN1cHBvcnQgZXhwaXJhdGlvblxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcigweDA4LCBcIlwiLCBcIlwiLCBcIlwiLCB0aGlzLnNlcSk7XG4gICAgbGV0IGNvdW50ID0gdGhpcy5zZXJ2ZXJzLmxlbmd0aDtcbiAgICBjb25zdCByZXN1bHQ6IFJlY29yZDxzdHJpbmcsIGJvb2xlYW4gfCBFcnJvcj4gPSB7fTtcbiAgICBsZXQgbGFzdEVycjogRXJyb3IgfCBudWxsID0gbnVsbDtcblxuICAgIGNvbnN0IGhhbmRsZUZsdXNoID0gZnVuY3Rpb24gKHNlcTogbnVtYmVyLCBzZXJ2OiBTZXJ2ZXIpIHtcbiAgICAgIHNlcnYub25SZXNwb25zZShzZXEsIGZ1bmN0aW9uICgvKiByZXNwb25zZSAqLykge1xuICAgICAgICBjb3VudCAtPSAxO1xuICAgICAgICByZXN1bHRbc2Vydi5ob3N0cG9ydFN0cmluZygpXSA9IHRydWU7XG4gICAgICAgIGlmIChjYWxsYmFjayAmJiBjb3VudCA9PT0gMCkge1xuICAgICAgICAgIGNhbGxiYWNrKGxhc3RFcnIsIHJlc3VsdCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgc2Vydi5vbkVycm9yKHNlcSwgZnVuY3Rpb24gKGVycikge1xuICAgICAgICBjb3VudCAtPSAxO1xuICAgICAgICBsYXN0RXJyID0gZXJyO1xuICAgICAgICByZXN1bHRbc2Vydi5ob3N0cG9ydFN0cmluZygpXSA9IGVycjtcbiAgICAgICAgaWYgKGNhbGxiYWNrICYmIGNvdW50ID09PSAwKSB7XG4gICAgICAgICAgY2FsbGJhY2sobGFzdEVyciwgcmVzdWx0KTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICBzZXJ2LndyaXRlKHJlcXVlc3QpO1xuICAgIH07XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuc2VydmVycy5sZW5ndGg7IGkrKykge1xuICAgICAgaGFuZGxlRmx1c2godGhpcy5zZXEsIHRoaXMuc2VydmVyc1tpXSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNUQVRTX1dJVEhfS0VZXG4gICAqXG4gICAqIFNlbmRzIGEgbWVtY2FjaGUgc3RhdHMgY29tbWFuZCB3aXRoIGEga2V5IHRvIGVhY2ggY29ubmVjdGVkIHNlcnZlci4gVGhlXG4gICAqIGNhbGxiYWNrIGlzIGludm9rZWQgKipPTkNFIFBFUiBTRVJWRVIqKiBhbmQgaGFzIHRoZSBzaWduYXR1cmU6XG4gICAqXG4gICAqICAgICBjYWxsYmFjayhlcnIsIHNlcnZlciwgc3RhdHMpXG4gICAqXG4gICAqIF9zZXJ2ZXJfIGlzIHRoZSBgXCJob3N0bmFtZTpwb3J0XCJgIG9mIHRoZSBzZXJ2ZXIsIGFuZCBfc3RhdHNfIGlzIGEgZGljdGlvbmFyeVxuICAgKiBtYXBwaW5nIHRoZSBzdGF0IG5hbWUgdG8gdGhlIHZhbHVlIG9mIHRoZSBzdGF0aXN0aWMgYXMgYSBzdHJpbmcuXG4gICAqIEBwYXJhbSBrZXlcbiAgICogQHBhcmFtIGNhbGxiYWNrXG4gICAqL1xuICBzdGF0c1dpdGhLZXkoXG4gICAga2V5OiBzdHJpbmcsXG4gICAgY2FsbGJhY2s/OiAoXG4gICAgICBlcnI6IEVycm9yIHwgbnVsbCxcbiAgICAgIHNlcnZlcjogc3RyaW5nLFxuICAgICAgc3RhdHM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gfCBudWxsXG4gICAgKSA9PiB2b2lkXG4gICk6IHZvaWQge1xuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcigweDEwLCBrZXksIFwiXCIsIFwiXCIsIHRoaXMuc2VxKTtcblxuICAgIGNvbnN0IGhhbmRsZVN0YXRzID0gKHNlcTogbnVtYmVyLCBzZXJ2OiBTZXJ2ZXIpID0+IHtcbiAgICAgIGNvbnN0IHJlc3VsdDogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHt9O1xuICAgICAgY29uc3QgaGFuZGxlOiBPblJlc3BvbnNlQ2FsbGJhY2sgPSAocmVzcG9uc2UpID0+IHtcbiAgICAgICAgLy8gZW5kIG9mIHN0YXQgcmVzcG9uc2VzXG4gICAgICAgIGlmIChyZXNwb25zZS5oZWFkZXIudG90YWxCb2R5TGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgICAgICBjYWxsYmFjayhudWxsLCBzZXJ2Lmhvc3Rwb3J0U3RyaW5nKCksIHJlc3VsdCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICAvLyBwcm9jZXNzIHNpbmdsZSBzdGF0IGxpbmUgcmVzcG9uc2VcbiAgICAgICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICAgICAgcmVzdWx0W3Jlc3BvbnNlLmtleS50b1N0cmluZygpXSA9IHJlc3BvbnNlLnZhbC50b1N0cmluZygpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIGNvbnN0IGVycm9yID0gdGhpcy5oYW5kbGVSZXNwb25zZUVycm9yKFxuICAgICAgICAgICAgICBgU1RBVFMgKCR7a2V5fSlgLFxuICAgICAgICAgICAgICByZXNwb25zZS5oZWFkZXIuc3RhdHVzLFxuICAgICAgICAgICAgICB1bmRlZmluZWRcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgY2FsbGJhY2soZXJyb3IsIHNlcnYuaG9zdHBvcnRTdHJpbmcoKSwgbnVsbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH07XG4gICAgICBoYW5kbGUucXVpZXQgPSB0cnVlO1xuXG4gICAgICBzZXJ2Lm9uUmVzcG9uc2Uoc2VxLCBoYW5kbGUpO1xuICAgICAgc2Vydi5vbkVycm9yKHNlcSwgZnVuY3Rpb24gKGVycikge1xuICAgICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgICBjYWxsYmFjayhlcnIsIHNlcnYuaG9zdHBvcnRTdHJpbmcoKSwgbnVsbCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgc2Vydi53cml0ZShyZXF1ZXN0KTtcbiAgICB9O1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnNlcnZlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGhhbmRsZVN0YXRzKHRoaXMuc2VxLCB0aGlzLnNlcnZlcnNbaV0pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTVEFUU1xuICAgKlxuICAgKiBGZXRjaGVzIG1lbWNhY2hlIHN0YXRzIGZyb20gZWFjaCBjb25uZWN0ZWQgc2VydmVyLiBUaGUgY2FsbGJhY2sgaXMgaW52b2tlZFxuICAgKiAqKk9OQ0UgUEVSIFNFUlZFUioqIGFuZCBoYXMgdGhlIHNpZ25hdHVyZTpcbiAgICpcbiAgICogICAgIGNhbGxiYWNrKGVyciwgc2VydmVyLCBzdGF0cylcbiAgICpcbiAgICogX3NlcnZlcl8gaXMgdGhlIGBcImhvc3RuYW1lOnBvcnRcImAgb2YgdGhlIHNlcnZlciwgYW5kIF9zdGF0c18gaXMgYVxuICAgKiBkaWN0aW9uYXJ5IG1hcHBpbmcgdGhlIHN0YXQgbmFtZSB0byB0aGUgdmFsdWUgb2YgdGhlIHN0YXRpc3RpYyBhcyBhIHN0cmluZy5cbiAgICogQHBhcmFtIGNhbGxiYWNrXG4gICAqL1xuICBzdGF0cyhcbiAgICBjYWxsYmFjaz86IChcbiAgICAgIGVycjogRXJyb3IgfCBudWxsLFxuICAgICAgc2VydmVyOiBzdHJpbmcsXG4gICAgICBzdGF0czogUmVjb3JkPHN0cmluZywgc3RyaW5nPiB8IG51bGxcbiAgICApID0+IHZvaWRcbiAgKTogdm9pZCB7XG4gICAgdGhpcy5zdGF0c1dpdGhLZXkoXCJcIiwgY2FsbGJhY2spO1xuICB9XG5cbiAgLyoqXG4gICAqIFJFU0VUX1NUQVRTXG4gICAqXG4gICAqIFJlc2V0IHRoZSBzdGF0aXN0aWNzIGVhY2ggc2VydmVyIGlzIGtlZXBpbmcgYmFjayB0byB6ZXJvLiBUaGlzIGRvZXNuJ3QgY2xlYXJcbiAgICogc3RhdHMgc3VjaCBhcyBpdGVtIGNvdW50LCBidXQgdGVtcG9yYXJ5IHN0YXRzIHN1Y2ggYXMgdG90YWwgbnVtYmVyIG9mXG4gICAqIGNvbm5lY3Rpb25zIG92ZXIgdGltZS5cbiAgICpcbiAgICogVGhlIGNhbGxiYWNrIGlzIGludm9rZWQgKipPTkNFIFBFUiBTRVJWRVIqKiBhbmQgaGFzIHRoZSBzaWduYXR1cmU6XG4gICAqXG4gICAqICAgICBjYWxsYmFjayhlcnIsIHNlcnZlcilcbiAgICpcbiAgICogX3NlcnZlcl8gaXMgdGhlIGBcImhvc3RuYW1lOnBvcnRcImAgb2YgdGhlIHNlcnZlci5cbiAgICogQHBhcmFtIGNhbGxiYWNrXG4gICAqL1xuICByZXNldFN0YXRzKFxuICAgIGNhbGxiYWNrPzogKFxuICAgICAgZXJyOiBFcnJvciB8IG51bGwsXG4gICAgICBzZXJ2ZXI6IHN0cmluZyxcbiAgICAgIHN0YXRzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+IHwgbnVsbFxuICAgICkgPT4gdm9pZFxuICApOiB2b2lkIHtcbiAgICB0aGlzLnN0YXRzV2l0aEtleShcInJlc2V0XCIsIGNhbGxiYWNrKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBRVUlUXG4gICAqXG4gICAqIENsb3NlcyB0aGUgY29ubmVjdGlvbiB0byBlYWNoIHNlcnZlciwgbm90aWZ5aW5nIHRoZW0gb2YgdGhpcyBpbnRlbnRpb24uIE5vdGVcbiAgICogdGhhdCBxdWl0IGNhbiByYWNlIGFnYWluc3QgYWxyZWFkeSBvdXRzdGFuZGluZyByZXF1ZXN0cyB3aGVuIHRob3NlIHJlcXVlc3RzXG4gICAqIGZhaWwgYW5kIGFyZSByZXRyaWVkLCBsZWFkaW5nIHRvIHRoZSBxdWl0IGNvbW1hbmQgd2lubmluZyBhbmQgY2xvc2luZyB0aGVcbiAgICogY29ubmVjdGlvbiBiZWZvcmUgdGhlIHJldHJpZXMgY29tcGxldGUuXG4gICAqL1xuICBxdWl0KCkge1xuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIC8vIFRPRE86IE5pY2VyIHBlcmhhcHMgdG8gZG8gUVVJVFEgKDB4MTcpIGJ1dCBuZWVkIGEgbmV3IGNhbGxiYWNrIGZvciB3aGVuXG4gICAgLy8gd3JpdGUgaXMgZG9uZS5cbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoMHgwNywgXCJcIiwgXCJcIiwgXCJcIiwgdGhpcy5zZXEpOyAvLyBRVUlUXG4gICAgbGV0IHNlcnY7XG5cbiAgICBjb25zdCBoYW5kbGVRdWl0ID0gZnVuY3Rpb24gKHNlcTogbnVtYmVyLCBzZXJ2OiBTZXJ2ZXIpIHtcbiAgICAgIHNlcnYub25SZXNwb25zZShzZXEsIGZ1bmN0aW9uICgvKiByZXNwb25zZSAqLykge1xuICAgICAgICBzZXJ2LmNsb3NlKCk7XG4gICAgICB9KTtcbiAgICAgIHNlcnYub25FcnJvcihzZXEsIGZ1bmN0aW9uICgvKiBlcnIgKi8pIHtcbiAgICAgICAgc2Vydi5jbG9zZSgpO1xuICAgICAgfSk7XG4gICAgICBzZXJ2LndyaXRlKHJlcXVlc3QpO1xuICAgIH07XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuc2VydmVycy5sZW5ndGg7IGkrKykge1xuICAgICAgc2VydiA9IHRoaXMuc2VydmVyc1tpXTtcbiAgICAgIGhhbmRsZVF1aXQodGhpcy5zZXEsIHNlcnYpO1xuICAgIH1cbiAgfVxuXG4gIF92ZXJzaW9uKHNlcnZlcjogU2VydmVyKTogUHJvbWlzZTx7IHZhbHVlOiBWYWx1ZSB8IG51bGwgfT4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICB0aGlzLmluY3JTZXEoKTtcbiAgICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgICAgY29uc3RhbnRzLk9QX1ZFUlNJT04sXG4gICAgICAgIFwiXCIsXG4gICAgICAgIFwiXCIsXG4gICAgICAgIFwiXCIsXG4gICAgICAgIHRoaXMuc2VxXG4gICAgICApO1xuICAgICAgdGhpcy5wZXJmb3JtT25TZXJ2ZXIoc2VydmVyLCByZXF1ZXN0LCB0aGlzLnNlcSwgKGVyciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgIHJldHVybiByZWplY3QoZXJyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHN3aXRjaCAocmVzcG9uc2UhLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgICAgICAvKiBUT0RPOiB0aGlzIGlzIGJ1Z2dlZCwgd2Ugc2hvdWxkJ3QgdXNlIHRoZSBkZXNlcmlhbGl6ZXIgaGVyZSwgc2luY2UgdmVyc2lvbiBhbHdheXMgcmV0dXJucyBhIHZlcnNpb24gc3RyaW5nLlxuICAgICAgICAgICAgIFRoZSBkZXNlcmlhbGl6ZXIgc2hvdWxkIG9ubHkgYmUgdXNlZCBvbiB1c2VyIGtleSBkYXRhLiAqL1xuICAgICAgICAgICAgY29uc3QgZGVzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLmRlc2VyaWFsaXplKFxuICAgICAgICAgICAgICByZXNwb25zZSEuaGVhZGVyLm9wY29kZSxcbiAgICAgICAgICAgICAgcmVzcG9uc2UhLnZhbCxcbiAgICAgICAgICAgICAgcmVzcG9uc2UhLmV4dHJhc1xuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHJldHVybiByZXNvbHZlKHsgdmFsdWU6IGRlc2VyaWFsaXplZC52YWx1ZSB9KTtcbiAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgcmV0dXJuIHJlamVjdChcbiAgICAgICAgICAgICAgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIlZFUlNJT05cIiwgcmVzcG9uc2UhLmhlYWRlci5zdGF0dXMpXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXF1ZXN0IHRoZSBzZXJ2ZXIgdmVyc2lvbiBmcm9tIHRoZSBcImZpcnN0XCIgc2VydmVyIGluIHRoZSBiYWNrZW5kIHBvb2wuXG4gICAqIFRoZSBzZXJ2ZXIgcmVzcG9uZHMgd2l0aCBhIHBhY2tldCBjb250YWluaW5nIHRoZSB2ZXJzaW9uIHN0cmluZyBpbiB0aGUgYm9keSB3aXRoIHRoZSBmb2xsb3dpbmcgZm9ybWF0OiBcIngueS56XCJcbiAgICovXG4gIHZlcnNpb24oKTogUHJvbWlzZTx7IHZhbHVlOiBWYWx1ZSB8IG51bGwgfT4ge1xuICAgIGNvbnN0IHNlcnZlciA9IHRoaXMuc2VydmVyS2V5VG9TZXJ2ZXIodGhpcy5zZXJ2ZXJLZXlzWzBdKTtcbiAgICByZXR1cm4gdGhpcy5fdmVyc2lvbihzZXJ2ZXIpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHJpZXZlcyB0aGUgc2VydmVyIHZlcnNpb24gZnJvbSBhbGwgdGhlIHNlcnZlcnNcbiAgICogaW4gdGhlIGJhY2tlbmQgcG9vbCwgZXJyb3JzIGlmIGFueSBvbmUgb2YgdGhlbSBoYXMgYW5cbiAgICogZXJyb3JcbiAgICovXG4gIGFzeW5jIHZlcnNpb25BbGwoKTogUHJvbWlzZTx7XG4gICAgdmFsdWVzOiBSZWNvcmQ8c3RyaW5nLCBWYWx1ZSB8IG51bGw+O1xuICB9PiB7XG4gICAgY29uc3QgdmVyc2lvbk9iamVjdHMgPSBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIHRoaXMuc2VydmVyS2V5cy5tYXAoKHNlcnZlcktleSkgPT4ge1xuICAgICAgICBjb25zdCBzZXJ2ZXIgPSB0aGlzLnNlcnZlcktleVRvU2VydmVyKHNlcnZlcktleSk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuX3ZlcnNpb24oc2VydmVyKS50aGVuKChyZXNwb25zZSkgPT4ge1xuICAgICAgICAgIHJldHVybiB7IHNlcnZlcktleTogc2VydmVyS2V5LCB2YWx1ZTogcmVzcG9uc2UudmFsdWUgfTtcbiAgICAgICAgfSk7XG4gICAgICB9KVxuICAgICk7XG4gICAgY29uc3QgdmFsdWVzID0gdmVyc2lvbk9iamVjdHMucmVkdWNlKChhY2N1bXVsYXRvciwgdmVyc2lvbk9iamVjdCkgPT4ge1xuICAgICAgYWNjdW11bGF0b3JbdmVyc2lvbk9iamVjdC5zZXJ2ZXJLZXldID0gdmVyc2lvbk9iamVjdC52YWx1ZTtcbiAgICAgIHJldHVybiBhY2N1bXVsYXRvcjtcbiAgICB9LCB7fSBhcyBSZWNvcmQ8c3RyaW5nLCBWYWx1ZSB8IG51bGw+KTtcbiAgICByZXR1cm4geyB2YWx1ZXM6IHZhbHVlcyB9O1xuICB9XG5cbiAgLyoqXG4gICAqIENsb3NlcyAoYWJydXB0bHkpIGNvbm5lY3Rpb25zIHRvIGFsbCB0aGUgc2VydmVycy5cbiAgICogQHNlZSB0aGlzLnF1aXRcbiAgICovXG4gIGNsb3NlKCkge1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5zZXJ2ZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB0aGlzLnNlcnZlcnNbaV0uY2xvc2UoKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUGVyZm9ybSBhIGdlbmVyaWMgc2luZ2xlIHJlc3BvbnNlIG9wZXJhdGlvbiAoZ2V0LCBzZXQgZXRjKSBvbiBvbmUgc2VydmVyXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgdGhlIGtleSB0byBoYXNoIHRvIGdldCBhIHNlcnZlciBmcm9tIHRoZSBwb29sXG4gICAqIEBwYXJhbSB7YnVmZmVyfSByZXF1ZXN0IGEgYnVmZmVyIGNvbnRhaW5pbmcgdGhlIHJlcXVlc3RcbiAgICogQHBhcmFtIHtudW1iZXJ9IHNlcSB0aGUgc2VxdWVuY2UgbnVtYmVyIG9mIHRoZSBvcGVyYXRpb24uIEl0IGlzIHVzZWQgdG8gcGluIHRoZSBjYWxsYmFja3NcbiAgICAgICAgICAgICAgICAgICAgICAgICB0byBhIHNwZWNpZmljIG9wZXJhdGlvbiBhbmQgc2hvdWxkIG5ldmVyIGNoYW5nZSBkdXJpbmcgYSBgcGVyZm9ybWAuXG4gICAqIEBwYXJhbSB7bnVtYmVyP30gcmV0cmllcyBudW1iZXIgb2YgdGltZXMgdG8gcmV0cnkgcmVxdWVzdCBvbiBmYWlsdXJlXG4gICAqL1xuICBwZXJmb3JtKFxuICAgIGtleTogc3RyaW5nLFxuICAgIHJlcXVlc3Q6IEJ1ZmZlcixcbiAgICBzZXE6IG51bWJlcixcbiAgICByZXRyaWVzPzogbnVtYmVyXG4gICk6IFByb21pc2U8TWVzc2FnZT4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBjb25zdCBzZXJ2ZXJLZXkgPSB0aGlzLmxvb2t1cEtleVRvU2VydmVyS2V5KGtleSk7XG4gICAgICBjb25zdCBzZXJ2ZXIgPSB0aGlzLnNlcnZlcktleVRvU2VydmVyKHNlcnZlcktleSk7XG5cbiAgICAgIGlmICghc2VydmVyKSB7XG4gICAgICAgIHJldHVybiByZWplY3QobmV3IEVycm9yKFwiTm8gc2VydmVycyBhdmFpbGFibGVcIikpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLnBlcmZvcm1PblNlcnZlcihcbiAgICAgICAgc2VydmVyLFxuICAgICAgICByZXF1ZXN0LFxuICAgICAgICBzZXEsXG4gICAgICAgIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgIHJldHVybiByZWplY3QoZXJyb3IpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXNvbHZlKHJlc3BvbnNlISk7XG4gICAgICAgIH0sXG4gICAgICAgIHJldHJpZXNcbiAgICAgICk7XG4gICAgfSk7XG4gIH1cblxuICBwZXJmb3JtT25TZXJ2ZXIoXG4gICAgc2VydmVyOiBTZXJ2ZXIsXG4gICAgcmVxdWVzdDogQnVmZmVyLFxuICAgIHNlcTogbnVtYmVyLFxuICAgIGNhbGxiYWNrOiBSZXNwb25zZU9yRXJyb3JDYWxsYmFjayxcbiAgICByZXRyaWVzOiBudW1iZXIgPSAwXG4gICkge1xuICAgIGNvbnN0IF90aGlzID0gdGhpcztcblxuICAgIHJldHJpZXMgPSByZXRyaWVzIHx8IHRoaXMub3B0aW9ucy5yZXRyaWVzO1xuICAgIGNvbnN0IG9yaWdSZXRyaWVzID0gdGhpcy5vcHRpb25zLnJldHJpZXM7XG4gICAgY29uc3QgbG9nZ2VyID0gdGhpcy5vcHRpb25zLmxvZ2dlcjtcbiAgICBjb25zdCByZXRyeV9kZWxheSA9IHRoaXMub3B0aW9ucy5yZXRyeV9kZWxheTtcblxuICAgIGNvbnN0IHJlc3BvbnNlSGFuZGxlcjogT25SZXNwb25zZUNhbGxiYWNrID0gZnVuY3Rpb24gKHJlc3BvbnNlKSB7XG4gICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgY2FsbGJhY2sobnVsbCwgcmVzcG9uc2UpO1xuICAgICAgfVxuICAgIH07XG5cbiAgICBjb25zdCBlcnJvckhhbmRsZXI6IE9uRXJyb3JDYWxsYmFjayA9IGZ1bmN0aW9uIChlcnJvcikge1xuICAgICAgaWYgKC0tcmV0cmllcyA+IDApIHtcbiAgICAgICAgLy8gV2FpdCBmb3IgcmV0cnlfZGVsYXlcbiAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgX3RoaXMucGVyZm9ybU9uU2VydmVyKHNlcnZlciwgcmVxdWVzdCwgc2VxLCBjYWxsYmFjaywgcmV0cmllcyk7XG4gICAgICAgIH0sIDEwMDAgKiByZXRyeV9kZWxheSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBsb2dnZXIubG9nKFxuICAgICAgICAgIFwiTWVtSlM6IFNlcnZlciA8XCIgK1xuICAgICAgICAgICAgc2VydmVyLmhvc3Rwb3J0U3RyaW5nKCkgK1xuICAgICAgICAgICAgXCI+IGZhaWxlZCBhZnRlciAoXCIgK1xuICAgICAgICAgICAgb3JpZ1JldHJpZXMgK1xuICAgICAgICAgICAgXCIpIHJldHJpZXMgd2l0aCBlcnJvciAtIFwiICtcbiAgICAgICAgICAgIGVycm9yLm1lc3NhZ2VcbiAgICAgICAgKTtcbiAgICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgICAgY2FsbGJhY2soZXJyb3IsIG51bGwpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfTtcblxuICAgIHNlcnZlci5vblJlc3BvbnNlKHNlcSwgcmVzcG9uc2VIYW5kbGVyKTtcbiAgICBzZXJ2ZXIub25FcnJvcihzZXEsIGVycm9ySGFuZGxlcik7XG4gICAgc2VydmVyLndyaXRlKHJlcXVlc3QpO1xuICB9XG5cbiAgLy8gSW5jcmVtZW50IHRoZSBzZXEgdmFsdWVcbiAgaW5jclNlcSgpIHtcbiAgICB0aGlzLnNlcSsrO1xuXG4gICAgLy8gV3JhcCBgdGhpcy5zZXFgIHRvIDMyLWJpdHMgc2luY2UgdGhlIGZpZWxkIHdlIGZpdCBpdCBpbnRvIGlzIG9ubHkgMzItYml0cy5cbiAgICB0aGlzLnNlcSAmPSAweGZmZmZmZmZmO1xuXG4gICAgcmV0dXJuIHRoaXMuc2VxXG4gIH1cblxuICBwcml2YXRlIGNyZWF0ZUFuZExvZ0Vycm9yKFxuICAgIGNvbW1hbmROYW1lOiBzdHJpbmcsXG4gICAgcmVzcG9uc2VTdGF0dXM6IFJlc3BvbnNlU3RhdHVzIHwgdW5kZWZpbmVkXG4gICk6IEVycm9yIHtcbiAgICBjb25zdCBlcnJvck1lc3NhZ2UgPSBgTWVtSlMgJHtjb21tYW5kTmFtZX06ICR7Y29uc3RhbnRzLnJlc3BvbnNlU3RhdHVzVG9TdHJpbmcoXG4gICAgICByZXNwb25zZVN0YXR1c1xuICAgICl9YDtcbiAgICB0aGlzLm9wdGlvbnMubG9nZ2VyLmxvZyhlcnJvck1lc3NhZ2UpO1xuICAgIHJldHVybiBuZXcgRXJyb3IoZXJyb3JNZXNzYWdlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBMb2cgYW4gZXJyb3IgdG8gdGhlIGxvZ2dlciwgdGhlbiByZXR1cm4gdGhlIGVycm9yLlxuICAgKiBJZiBhIGNhbGxiYWNrIGlzIGdpdmVuLCBjYWxsIGl0IHdpdGggY2FsbGJhY2soZXJyb3IsIG51bGwpLlxuICAgKi9cbiAgcHJpdmF0ZSBoYW5kbGVSZXNwb25zZUVycm9yKFxuICAgIGNvbW1hbmROYW1lOiBzdHJpbmcsXG4gICAgcmVzcG9uc2VTdGF0dXM6IFJlc3BvbnNlU3RhdHVzIHwgdW5kZWZpbmVkLFxuICAgIGNhbGxiYWNrOiB1bmRlZmluZWQgfCAoKGVycm9yOiBFcnJvciB8IG51bGwsIG90aGVyOiBudWxsKSA9PiB2b2lkKVxuICApOiBFcnJvciB7XG4gICAgY29uc3QgZXJyb3IgPSB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKGNvbW1hbmROYW1lLCByZXNwb25zZVN0YXR1cyk7XG4gICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICBjYWxsYmFjayhlcnJvciwgbnVsbCk7XG4gICAgfVxuICAgIHJldHVybiBlcnJvcjtcbiAgfVxufVxuXG5leHBvcnQgeyBDbGllbnQsIFNlcnZlciwgVXRpbHMsIEhlYWRlciB9O1xuIl19 \ No newline at end of file diff --git a/src/memjs/memjs.ts b/src/memjs/memjs.ts index 03c70c5..b509c4f 100644 --- a/src/memjs/memjs.ts +++ b/src/memjs/memjs.ts @@ -260,7 +260,7 @@ class Client { * * cf https://github.com/couchbase/memcached/blob/master/docs/BinaryProtocol.md#0x0d-getkq-get-with-key-quietly */ - _buildGetMultiRequest(keys: string[]): Buffer { + _buildGetMultiRequest(keys: string[], seq: number): Buffer { // start at 24 for the no-op command at the end let requestSize = 24; for (const keyIdx in keys) { @@ -277,7 +277,7 @@ class Client { key, "", "", - this.seq, + seq, request, bytesWritten ); @@ -288,7 +288,7 @@ class Client { "", "", "", - this.seq, + seq, request, bytesWritten ); @@ -342,10 +342,10 @@ class Client { // after the first response. Logic in server.js. handle.quiet = true; - const request = this._buildGetMultiRequest(keys); + const seq = this.incrSeq(); + const request = this._buildGetMultiRequest(keys, seq); serv.onResponse(this.seq, handle); serv.onError(this.seq, reject); - this.incrSeq(); serv.write(request); }); } @@ -1028,6 +1028,8 @@ class Client { // Wrap `this.seq` to 32-bits since the field we fit it into is only 32-bits. this.seq &= 0xffffffff; + + return this.seq } private createAndLogError( From fdb2efe917d2a8f69763b75d51428a9ad6e22c50 Mon Sep 17 00:00:00 2001 From: Arturo Olvera Date: Mon, 6 Feb 2023 09:40:36 -0800 Subject: [PATCH 61/79] added callbacks to versionAll for better errors --- lib/memjs/memjs.d.ts | 2 +- lib/memjs/memjs.d.ts.map | 2 +- lib/memjs/memjs.js | 10 +- package-lock.json | 5561 +++++++++++++++++++++++++++++++++++++- src/memjs/memjs.ts | 9 +- 5 files changed, 5566 insertions(+), 18 deletions(-) diff --git a/lib/memjs/memjs.d.ts b/lib/memjs/memjs.d.ts index 764a387..b62c300 100644 --- a/lib/memjs/memjs.d.ts +++ b/lib/memjs/memjs.d.ts @@ -273,7 +273,7 @@ declare class Client { * in the backend pool, errors if any one of them has an * error */ - versionAll(): Promise<{ + versionAll(triedCallback?: (response: string) => void, resultCallback?: (response: string) => void): Promise<{ values: Record; }>; /** diff --git a/lib/memjs/memjs.d.ts.map b/lib/memjs/memjs.d.ts.map index 8a349b5..2af5f5a 100644 --- a/lib/memjs/memjs.d.ts.map +++ b/lib/memjs/memjs.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"memjs.d.ts","sourceRoot":"","sources":["../../src/memjs/memjs.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"memjs.d.ts","sourceRoot":"","sources":["../../src/memjs/memjs.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/lib/memjs/memjs.js b/lib/memjs/memjs.js index 9b3c435..e057eda 100644 --- a/lib/memjs/memjs.js +++ b/lib/memjs/memjs.js @@ -627,10 +627,16 @@ class Client { * in the backend pool, errors if any one of them has an * error */ - async versionAll() { + async versionAll(triedCallback, resultCallback) { const versionObjects = await Promise.all(this.serverKeys.map((serverKey) => { + if (triedCallback !== undefined) { + triedCallback(serverKey); + } const server = this.serverKeyToServer(serverKey); return this._version(server).then((response) => { + if (resultCallback !== undefined) { + resultCallback(serverKey); + } return { serverKey: serverKey, value: response.value }; }); })); @@ -732,4 +738,4 @@ class Client { } } exports.Client = Client; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVtanMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbWVtanMvbWVtanMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLHdCQUF3Qjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUV4QixxQ0FLa0I7QUEraENELHVGQWppQ2YsZUFBTSxPQWlpQ2U7QUE5aEN2Qix1REFBK0Q7QUFDL0QsbUNBU2lCO0FBQ2pCLHVEQUF5QztBQUN6QywyQ0FBNkM7QUFDN0MsK0NBQWlDO0FBaWhDUixzQkFBSztBQWhoQzlCLGlEQUFtQztBQWdoQ0gsd0JBQU07QUE5Z0N0QyxTQUFTLDhCQUE4QixDQUNyQyxPQUFpQixFQUNqQixHQUFXO0lBRVgsTUFBTSxLQUFLLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQztJQUM3QixNQUFNLEtBQUssR0FBRyxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxnQkFBUSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3BELE9BQU8sT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ3hCLENBQUM7QUFFRCwrQ0FBK0M7QUFDL0MsU0FBUyxTQUFTLENBQ2hCLE9BQTBFO0lBRTFFLE9BQU8sSUFBSSxPQUFPLENBQUMsVUFBVSxPQUFPLEVBQUUsTUFBTTtRQUMxQyxPQUFPLENBQUMsVUFBVSxHQUFHLEVBQUUsTUFBTTtZQUMzQixHQUFHLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3RDLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBNkRELE1BQU0sTUFBTTtJQVFWLDRFQUE0RTtJQUM1RSxtQ0FBbUM7SUFDbkMsWUFBWSxPQUFpQixFQUFFLE9BQTBDO1FBQ3ZFLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO1FBQ3ZCLElB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LFlBQVksQ0FBQyxDQUFDO0lBQ2pDLENBQUM7SUFFRDs7O09BR0c7SUFDSyxtQkFBbUIsQ0FDekIsV0FBbUIsRUFDbkIsY0FBMEMsRUFDMUMsUUFBa0U7UUFFbEUsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixDQUFDLFdBQVcsRUFBRSxjQUFjLENBQUMsQ0FBQztRQUNsRSxJQUFJLFFBQVEsRUFBRTtZQUNaLFFBQVEsQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLENBQUM7U0FDdkI7UUFDRCxPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7Q0FDRjtBQUVRLHdCQUFNIiwic291cmNlc0NvbnRlbnQiOlsiLy8gTWVtVFMgTWVtY2FjaGUgQ2xpZW50XG5cbmltcG9ydCB7XG4gIE9uRXJyb3JDYWxsYmFjayxcbiAgT25SZXNwb25zZUNhbGxiYWNrLFxuICBTZXJ2ZXIsXG4gIFNlcnZlck9wdGlvbnMsXG59IGZyb20gXCIuL3NlcnZlclwiO1xuaW1wb3J0IHsgbm9vcFNlcmlhbGl6ZXIsIFNlcmlhbGl6ZXIgfSBmcm9tIFwiLi9ub29wLXNlcmlhbGl6ZXJcIjtcbmltcG9ydCB7XG4gIG1ha2VSZXF1ZXN0QnVmZmVyLFxuICBjb3B5SW50b1JlcXVlc3RCdWZmZXIsXG4gIG1lcmdlLFxuICBtYWtlRXhwaXJhdGlvbixcbiAgbWFrZUFtb3VudEluaXRpYWxBbmRFeHBpcmF0aW9uLFxuICBoYXNoQ29kZSxcbiAgTWF5YmVCdWZmZXIsXG4gIE1lc3NhZ2UsXG59IGZyb20gXCIuL3V0aWxzXCI7XG5pbXBvcnQgKiBhcyBjb25zdGFudHMgZnJvbSBcIi4vY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBSZXNwb25zZVN0YXR1cyB9IGZyb20gXCIuL2NvbnN0YW50c1wiO1xuaW1wb3J0ICogYXMgVXRpbHMgZnJvbSBcIi4vdXRpbHNcIjtcbmltcG9ydCAqIGFzIEhlYWRlciBmcm9tIFwiLi9oZWFkZXJcIjtcblxuZnVuY3Rpb24gZGVmYXVsdEtleVRvU2VydmVySGFzaEZ1bmN0aW9uKFxuICBzZXJ2ZXJzOiBzdHJpbmdbXSxcbiAga2V5OiBzdHJpbmdcbik6IHN0cmluZyB7XG4gIGNvbnN0IHRvdGFsID0gc2VydmVycy5sZW5ndGg7XG4gIGNvbnN0IGluZGV4ID0gdG90YWwgPiAxID8gaGFzaENvZGUoa2V5KSAlIHRvdGFsIDogMDtcbiAgcmV0dXJuIHNlcnZlcnNbaW5kZXhdO1xufVxuXG4vLyBjb252ZXJ0cyBhIGNhbGwgaW50byBhIHByb21pc2UtcmV0dXJuaW5nIG9uZVxuZnVuY3Rpb24gcHJvbWlzaWZ5PFJlc3VsdD4oXG4gIGNvbW1hbmQ6IChjYWxsYmFjazogKGVycm9yOiBFcnJvciB8IG51bGwsIHJlc3VsdDogUmVzdWx0KSA9PiB2b2lkKSA9PiB2b2lkXG4pOiBQcm9taXNlPFJlc3VsdD4ge1xuICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuICAgIGNvbW1hbmQoZnVuY3Rpb24gKGVyciwgcmVzdWx0KSB7XG4gICAgICBlcnIgPyByZWplY3QoZXJyKSA6IHJlc29sdmUocmVzdWx0KTtcbiAgICB9KTtcbiAgfSk7XG59XG5cbnR5cGUgUmVzcG9uc2VPckVycm9yQ2FsbGJhY2sgPSAoXG4gIGVycm9yOiBFcnJvciB8IG51bGwsXG4gIHJlc3BvbnNlOiBNZXNzYWdlIHwgbnVsbFxuKSA9PiB2b2lkO1xuXG5pbnRlcmZhY2UgQmFzZUNsaWVudE9wdGlvbnMge1xuICByZXRyaWVzOiBudW1iZXI7XG4gIHJldHJ5X2RlbGF5OiBudW1iZXI7XG4gIGV4cGlyZXM6IG51bWJlcjtcbiAgbG9nZ2VyOiB7IGxvZzogdHlwZW9mIGNvbnNvbGUubG9nIH07XG4gIGtleVRvU2VydmVySGFzaEZ1bmN0aW9uOiB0eXBlb2YgZGVmYXVsdEtleVRvU2VydmVySGFzaEZ1bmN0aW9uO1xufVxuXG5pbnRlcmZhY2UgU2VyaWFsaXplclByb3A8VmFsdWUsIEV4dHJhcz4ge1xuICBzZXJpYWxpemVyOiBTZXJpYWxpemVyPFZhbHVlLCBFeHRyYXM+O1xufVxuXG4vKipcbiAqIFRoZSBjbGllbnQgaGFzIHBhcnRpYWwgc3VwcG9ydCBmb3Igc2VyaWFsaXppbmcgYW5kIGRlc2VyaWFsaXppbmcgdmFsdWVzIGZyb20gdGhlXG4gKiBCdWZmZXIgYnl0ZSBzdHJpbmdzIHdlIHJlY2lldmUgZnJvbSB0aGUgd2lyZS4gVGhlIGRlZmF1bHQgc2VyaWFsaXplciBpcyBmb3IgTWF5YmVCdWZmZXIuXG4gKlxuICogSWYgVmFsdWUgYW5kIEV4dHJhcyBhcmUgb2YgdHlwZSBCdWZmZXIsIHRoZW4gcmV0dXJuIHR5cGUgV2hlbkJ1ZmZlci4gT3RoZXJ3aXNlLFxuICogcmV0dXJuIHR5cGUgTm90QnVmZmVyLlxuICovXG50eXBlIElmQnVmZmVyPFxuICBWYWx1ZSxcbiAgRXh0cmFzLFxuICBXaGVuVmFsdWVBbmRFeHRyYXNBcmVCdWZmZXJzLFxuICBOb3RCdWZmZXJcbj4gPSBWYWx1ZSBleHRlbmRzIEJ1ZmZlclxuICA/IEV4dHJhcyBleHRlbmRzIEJ1ZmZlclxuICAgID8gV2hlblZhbHVlQW5kRXh0cmFzQXJlQnVmZmVyc1xuICAgIDogTm90QnVmZmVyXG4gIDogTm90QnVmZmVyO1xuXG5leHBvcnQgdHlwZSBHaXZlbkNsaWVudE9wdGlvbnM8VmFsdWUsIEV4dHJhcz4gPSBQYXJ0aWFsPEJhc2VDbGllbnRPcHRpb25zPiAmXG4gIElmQnVmZmVyPFxuICAgIFZhbHVlLFxuICAgIEV4dHJhcyxcbiAgICBQYXJ0aWFsPFNlcmlhbGl6ZXJQcm9wPFZhbHVlLCBFeHRyYXM+PixcbiAgICBTZXJpYWxpemVyUHJvcDxWYWx1ZSwgRXh0cmFzPlxuICA+O1xuXG5leHBvcnQgdHlwZSBDQVNUb2tlbiA9IEJ1ZmZlcjtcblxuZXhwb3J0IGludGVyZmFjZSBHZXRSZXN1bHQ8VmFsdWUgPSBNYXliZUJ1ZmZlciwgRXh0cmFzID0gTWF5YmVCdWZmZXI+IHtcbiAgdmFsdWU6IFZhbHVlO1xuICBleHRyYXM6IEV4dHJhcztcbiAgY2FzOiBDQVNUb2tlbiB8IHVuZGVmaW5lZDtcbn1cblxuZXhwb3J0IHR5cGUgR2V0TXVsdGlSZXN1bHQ8XG4gIEtleXMgZXh0ZW5kcyBzdHJpbmcgPSBzdHJpbmcsXG4gIFZhbHVlID0gTWF5YmVCdWZmZXIsXG4gIEV4dHJhcyA9IE1heWJlQnVmZmVyXG4+ID0ge1xuICBbSyBpbiBLZXlzXT86IEdldFJlc3VsdDxWYWx1ZSwgRXh0cmFzPjtcbn07XG5cbmNsYXNzIENsaWVudDxWYWx1ZSA9IE1heWJlQnVmZmVyLCBFeHRyYXMgPSBNYXliZUJ1ZmZlcj4ge1xuICBzZXJ2ZXJzOiBTZXJ2ZXJbXTtcbiAgc2VxOiBudW1iZXI7XG4gIG9wdGlvbnM6IEJhc2VDbGllbnRPcHRpb25zICYgUGFydGlhbDxTZXJpYWxpemVyUHJvcDxWYWx1ZSwgRXh0cmFzPj47XG4gIHNlcmlhbGl6ZXI6IFNlcmlhbGl6ZXI8VmFsdWUsIEV4dHJhcz47XG4gIHNlcnZlck1hcDogeyBbaG9zdHBvcnQ6IHN0cmluZ106IFNlcnZlciB9O1xuICBzZXJ2ZXJLZXlzOiBzdHJpbmdbXTtcblxuICAvLyBDbGllbnQgaW5pdGlhbGl6ZXIgdGFrZXMgYSBsaXN0IG9mIGBTZXJ2ZXJgcyBhbmQgYW4gYG9wdGlvbnNgIGRpY3Rpb25hcnkuXG4gIC8vIFNlZSBgQ2xpZW50LmNyZWF0ZWAgZm9yIGRldGFpbHMuXG4gIGNvbnN0cnVjdG9yKHNlcnZlcnM6IFNlcnZlcltdLCBvcHRpb25zOiBHaXZlbkNsaWVudE9wdGlvbnM8VmFsdWUsIEV4dHJhcz4pIHtcbiAgICB0aGlzLnNlcnZlcnMgPSBzZXJ2ZXJzO1xuICAgIHRoaXMuc2VxID0gMDtcbiAgICB0aGlzLm9wdGlvbnMgPSBtZXJnZShvcHRpb25zIHx8IHt9LCB7XG4gICAgICByZXRyaWVzOiAyLFxuICAgICAgcmV0cnlfZGVsYXk6IDAuMixcbiAgICAgIGV4cGlyZXM6IDAsXG4gICAgICBsb2dnZXI6IGNvbnNvbGUsXG4gICAgICBrZXlUb1NlcnZlckhhc2hGdW5jdGlvbjogZGVmYXVsdEtleVRvU2VydmVySGFzaEZ1bmN0aW9uLFxuICAgIH0pO1xuXG4gICAgdGhpcy5zZXJpYWxpemVyID0gdGhpcy5vcHRpb25zLnNlcmlhbGl6ZXIgfHwgKG5vb3BTZXJpYWxpemVyIGFzIGFueSk7XG5cbiAgICAvLyBTdG9yZSBhIG1hcHBpbmcgZnJvbSBob3N0cG9ydCAtPiBzZXJ2ZXIgc28gd2UgY2FuIHF1aWNrbHkgZ2V0IGEgc2VydmVyIG9iamVjdCBmcm9tIHRoZSBzZXJ2ZXJLZXkgcmV0dXJuZWQgYnkgdGhlIGhhc2hpbmcgZnVuY3Rpb25cbiAgICBjb25zdCBzZXJ2ZXJNYXA6IHsgW2hvc3Rwb3J0OiBzdHJpbmddOiBTZXJ2ZXIgfSA9IHt9O1xuICAgIHRoaXMuc2VydmVycy5mb3JFYWNoKGZ1bmN0aW9uIChzZXJ2ZXIpIHtcbiAgICAgIHNlcnZlck1hcFtzZXJ2ZXIuaG9zdHBvcnRTdHJpbmcoKV0gPSBzZXJ2ZXI7XG4gICAgfSk7XG4gICAgdGhpcy5zZXJ2ZXJNYXAgPSBzZXJ2ZXJNYXA7XG5cbiAgICAvLyBzdG9yZSBhIGxpc3Qgb2YgYWxsIG91ciBzZXJ2ZXJLZXlzIHNvIHdlIGRvbid0IG5lZWQgdG8gY29uc3RhbnRseSByZWFsbG9jYXRlIHRoaXMgYXJyYXlcbiAgICB0aGlzLnNlcnZlcktleXMgPSBPYmplY3Qua2V5cyh0aGlzLnNlcnZlck1hcCk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIG5ldyBjbGllbnQgZ2l2ZW4gYW4gb3B0aW9uYWwgY29uZmlnIHN0cmluZyBhbmQgb3B0aW9uYWwgaGFzaCBvZlxuICAgKiBvcHRpb25zLiBUaGUgY29uZmlnIHN0cmluZyBzaG91bGQgYmUgb2YgdGhlIGZvcm06XG4gICAqXG4gICAqICAgICBcIlt1c2VyOnBhc3NAXXNlcnZlcjFbOjExMjExXSxbdXNlcjpwYXNzQF1zZXJ2ZXIyWzoxMTIxMV0sLi4uXCJcbiAgICpcbiAgICogSWYgdGhlIGFyZ3VtZW50IGlzIG5vdCBnaXZlbiwgZmFsbGJhY2sgb24gdGhlIGBNRU1DQUNISUVSX1NFUlZFUlNgIGVudmlyb25tZW50XG4gICAqIHZhcmlhYmxlLCBgTUVNQ0FDSEVfU0VSVkVSU2AgZW52aXJvbm1lbnQgdmFyaWFibGUgb3IgYFwibG9jYWxob3N0OjExMjExXCJgLlxuICAgKlxuICAgKiBUaGUgb3B0aW9ucyBoYXNoIG1heSBjb250YWluIHRoZSBvcHRpb25zOlxuICAgKlxuICAgKiAqIGByZXRyaWVzYCAtIHRoZSBudW1iZXIgb2YgdGltZXMgdG8gcmV0cnkgYW4gb3BlcmF0aW9uIGluIGxpZXUgb2YgZmFpbHVyZXNcbiAgICogKGRlZmF1bHQgMilcbiAgICogKiBgZXhwaXJlc2AgLSB0aGUgZGVmYXVsdCBleHBpcmF0aW9uIGluIHNlY29uZHMgdG8gdXNlIChkZWZhdWx0IDAgLSBuZXZlclxuICAgKiBleHBpcmUpLiBJZiBgZXhwaXJlc2AgaXMgZ3JlYXRlciB0aGFuIDMwIGRheXMgKDYwIHggNjAgeCAyNCB4IDMwKSwgaXQgaXNcbiAgICogdHJlYXRlZCBhcyBhIFVOSVggdGltZSAobnVtYmVyIG9mIHNlY29uZHMgc2luY2UgSmFudWFyeSAxLCAxOTcwKS5cbiAgICogKiBgbG9nZ2VyYCAtIGEgbG9nZ2VyIG9iamVjdCB0aGF0IHJlc3BvbmRzIHRvIGBsb2coc3RyaW5nKWAgbWV0aG9kIGNhbGxzLlxuICAgKlxuICAgKiAgIH5+fn5cbiAgICogICAgIGxvZyhtc2cxWywgbXNnMlssIG1zZzNbLi4uXV1dKVxuICAgKiAgIH5+fn5cbiAgICpcbiAgICogICBEZWZhdWx0cyB0byBgY29uc29sZWAuXG4gICAqICogYHNlcmlhbGl6ZXJgIC0gdGhlIG9iamVjdCB3aGljaCB3aWxsIChkZSlzZXJpYWxpemUgdGhlIGRhdGEuIEl0IG5lZWRzXG4gICAqICAgdHdvIHB1YmxpYyBtZXRob2RzOiBzZXJpYWxpemUgYW5kIGRlc2VyaWFsaXplLiBJdCBkZWZhdWx0cyB0byB0aGVcbiAgICogICBub29wU2VyaWFsaXplcjpcbiAgICpcbiAgICogICB+fn5+XG4gICAqICAgY29uc3Qgbm9vcFNlcmlhbGl6ZXIgPSB7XG4gICAqICAgICBzZXJpYWxpemU6IGZ1bmN0aW9uIChvcGNvZGUsIHZhbHVlLCBleHRyYXMpIHtcbiAgICogICAgICAgcmV0dXJuIHsgdmFsdWU6IHZhbHVlLCBleHRyYXM6IGV4dHJhcyB9O1xuICAgKiAgICAgfSxcbiAgICogICAgIGRlc2VyaWFsaXplOiBmdW5jdGlvbiAob3Bjb2RlLCB2YWx1ZSwgZXh0cmFzKSB7XG4gICAqICAgICAgIHJldHVybiB7IHZhbHVlOiB2YWx1ZSwgZXh0cmFzOiBleHRyYXMgfTtcbiAgICogICAgIH1cbiAgICogICB9O1xuICAgKiAgIH5+fn5cbiAgICpcbiAgICogT3Igb3B0aW9ucyBmb3IgdGhlIHNlcnZlcnMgaW5jbHVkaW5nOlxuICAgKiAqIGB1c2VybmFtZWAgYW5kIGBwYXNzd29yZGAgZm9yIGZhbGxiYWNrIFNBU0wgYXV0aGVudGljYXRpb24gY3JlZGVudGlhbHMuXG4gICAqICogYHRpbWVvdXRgIGluIHNlY29uZHMgdG8gZGV0ZXJtaW5lIGZhaWx1cmUgZm9yIG9wZXJhdGlvbnMuIERlZmF1bHQgaXMgMC41XG4gICAqICAgICAgICAgICAgIHNlY29uZHMuXG4gICAqICogJ2Nvbm50aW1lb3V0JyBpbiBzZWNvbmRzIHRvIGNvbm5lY3Rpb24gZmFpbHVyZS4gRGVmYXVsdCBpcyB0d2ljZSB0aGUgdmFsdWVcbiAgICogICAgICAgICAgICAgICAgIG9mIGB0aW1lb3V0YC5cbiAgICogKiBga2VlcEFsaXZlYCB3aGV0aGVyIHRvIGVuYWJsZSBrZWVwLWFsaXZlIGZ1bmN0aW9uYWxpdHkuIERlZmF1bHRzIHRvIGZhbHNlLlxuICAgKiAqIGBrZWVwQWxpdmVEZWxheWAgaW4gc2Vjb25kcyB0byB0aGUgaW5pdGlhbCBkZWxheSBiZWZvcmUgdGhlIGZpcnN0IGtlZXBhbGl2ZVxuICAgKiAgICAgICAgICAgICAgICAgICAgcHJvYmUgaXMgc2VudCBvbiBhbiBpZGxlIHNvY2tldC4gRGVmYXVsdHMgaXMgMzAgc2Vjb25kcy5cbiAgICogKiBga2V5VG9TZXJ2ZXJIYXNoRnVuY3Rpb25gIGEgZnVuY3Rpb24gdG8gbWFwIGtleXMgdG8gc2VydmVycywgd2l0aCB0aGUgc2lnbmF0dXJlXG4gICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgIChzZXJ2ZXJLZXlzOiBzdHJpbmdbXSwga2V5OiBzdHJpbmcpOiBzdHJpbmdcbiAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgTk9URTogaWYgeW91IG5lZWQgdG8gZG8gc29tZSBleHBlbnNpdmUgaW5pdGlhbGl6YXRpb24sICpwbGVhc2UqIGRvIGl0IGxhemlseSB0aGUgZmlyc3QgdGltZSB5b3UgdGhpcyBmdW5jdGlvbiBpcyBjYWxsZWQgd2l0aCBhbiBhcnJheSBvZiBzZXJ2ZXJLZXlzLCBub3Qgb24gZXZlcnkgY2FsbFxuICAgKi9cbiAgc3RhdGljIGNyZWF0ZTxWYWx1ZSwgRXh0cmFzPihcbiAgICBzZXJ2ZXJzU3RyOiBzdHJpbmcgfCB1bmRlZmluZWQsXG4gICAgb3B0aW9uczogSWZCdWZmZXI8XG4gICAgICBWYWx1ZSxcbiAgICAgIEV4dHJhcyxcbiAgICAgIHVuZGVmaW5lZCB8IChQYXJ0aWFsPFNlcnZlck9wdGlvbnM+ICYgR2l2ZW5DbGllbnRPcHRpb25zPFZhbHVlLCBFeHRyYXM+KSxcbiAgICAgIFBhcnRpYWw8U2VydmVyT3B0aW9ucz4gJiBHaXZlbkNsaWVudE9wdGlvbnM8VmFsdWUsIEV4dHJhcz5cbiAgICA+XG4gICk6IENsaWVudDxWYWx1ZSwgRXh0cmFzPiB7XG4gICAgc2VydmVyc1N0ciA9XG4gICAgICBzZXJ2ZXJzU3RyIHx8XG4gICAgICBwcm9jZXNzLmVudi5NRU1DQUNISUVSX1NFUlZFUlMgfHxcbiAgICAgIHByb2Nlc3MuZW52Lk1FTUNBQ0hFX1NFUlZFUlMgfHxcbiAgICAgIFwibG9jYWxob3N0OjExMjExXCI7XG4gICAgY29uc3Qgc2VydmVyVXJpcyA9IHNlcnZlcnNTdHIuc3BsaXQoXCIsXCIpO1xuICAgIGNvbnN0IHNlcnZlcnMgPSBzZXJ2ZXJVcmlzLm1hcChmdW5jdGlvbiAodXJpKSB7XG4gICAgICBjb25zdCB1cmlQYXJ0cyA9IHVyaS5zcGxpdChcIkBcIik7XG4gICAgICBjb25zdCBob3N0UG9ydCA9IHVyaVBhcnRzW3VyaVBhcnRzLmxlbmd0aCAtIDFdLnNwbGl0KFwiOlwiKTtcbiAgICAgIGNvbnN0IHVzZXJQYXNzID0gKHVyaVBhcnRzW3VyaVBhcnRzLmxlbmd0aCAtIDJdIHx8IFwiXCIpLnNwbGl0KFwiOlwiKTtcbiAgICAgIHJldHVybiBuZXcgU2VydmVyKFxuICAgICAgICBob3N0UG9ydFswXSxcbiAgICAgICAgcGFyc2VJbnQoaG9zdFBvcnRbMV0gfHwgXCIxMTIxMVwiLCAxMCksXG4gICAgICAgIHVzZXJQYXNzWzBdLFxuICAgICAgICB1c2VyUGFzc1sxXSxcbiAgICAgICAgb3B0aW9uc1xuICAgICAgKTtcbiAgICB9KTtcbiAgICByZXR1cm4gbmV3IENsaWVudChzZXJ2ZXJzLCBvcHRpb25zIGFzIGFueSk7XG4gIH1cblxuICAvKipcbiAgICogR2l2ZW4gYSBzZXJ2ZXJLZXkgZnJvbWxvb2t1cEtleVRvU2VydmVyS2V5LCByZXR1cm4gdGhlIGNvcnJlc3BvbmRpbmcgU2VydmVyIGluc3RhbmNlXG4gICAqXG4gICAqIEBwYXJhbSAge3N0cmluZ30gc2VydmVyS2V5XG4gICAqIEByZXR1cm5zIHtTZXJ2ZXJ9XG4gICAqL1xuICBzZXJ2ZXJLZXlUb1NlcnZlcihzZXJ2ZXJLZXk6IHN0cmluZyk6IFNlcnZlciB7XG4gICAgcmV0dXJuIHRoaXMuc2VydmVyTWFwW3NlcnZlcktleV07XG4gIH1cblxuICAvKipcbiAgICogR2l2ZW4gYSBrZXkgdG8gbG9vayB1cCBpbiBtZW1jYWNoZSwgcmV0dXJuIGEgc2VydmVyS2V5IChiYXNlZCBvbiBzb21lXG4gICAqIGhhc2hpbmcgZnVuY3Rpb24pIHdoaWNoIGNhbiBiZSB1c2VkIHRvIGluZGV4IHRoaXMuc2VydmVyTWFwXG4gICAqL1xuICBsb29rdXBLZXlUb1NlcnZlcktleShrZXk6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMub3B0aW9ucy5rZXlUb1NlcnZlckhhc2hGdW5jdGlvbih0aGlzLnNlcnZlcktleXMsIGtleSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldmVzIHRoZSB2YWx1ZSBhdCB0aGUgZ2l2ZW4ga2V5IGluIG1lbWNhY2hlLlxuICAgKi9cbiAgYXN5bmMgZ2V0KGtleTogc3RyaW5nKTogUHJvbWlzZTxHZXRSZXN1bHQ8VmFsdWUsIEV4dHJhcz4gfCBudWxsPiB7XG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKGNvbnN0YW50cy5PUF9HRVQsIGtleSwgXCJcIiwgXCJcIiwgdGhpcy5zZXEpO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICBjb25zdCBkZXNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuZGVzZXJpYWxpemUoXG4gICAgICAgICAgcmVzcG9uc2UuaGVhZGVyLm9wY29kZSxcbiAgICAgICAgICByZXNwb25zZS52YWwsXG4gICAgICAgICAgcmVzcG9uc2UuZXh0cmFzXG4gICAgICAgICk7XG4gICAgICAgIHJldHVybiB7IC4uLmRlc2VyaWFsaXplZCwgY2FzOiByZXNwb25zZS5oZWFkZXIuY2FzIH07XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIkdFVFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKiogQnVpbGQgYSBwaXBlbGluZWQgZ2V0IG11bHRpIHJlcXVlc3QgYnkgc2VuZGluZyBvbmUgR0VUS1EgZm9yIGVhY2gga2V5IChxdWlldCwgbWVhbmluZyBpdCB3b24ndCByZXNwb25kIGlmIHRoZSB2YWx1ZSBpcyBtaXNzaW5nKSBmb2xsb3dlZCBieSBhIG5vLW9wIHRvIGZvcmNlIGEgcmVzcG9uc2UgKGFuZCB0byBnaXZlIHVzIGEgc2VudGluZWwgcmVzcG9uc2UgdGhhdCB0aGUgcGlwZWxpbmUgaXMgZG9uZSlcbiAgICpcbiAgICogY2YgaHR0cHM6Ly9naXRodWIuY29tL2NvdWNoYmFzZS9tZW1jYWNoZWQvYmxvYi9tYXN0ZXIvZG9jcy9CaW5hcnlQcm90b2NvbC5tZCMweDBkLWdldGtxLWdldC13aXRoLWtleS1xdWlldGx5XG4gICAqL1xuICBfYnVpbGRHZXRNdWx0aVJlcXVlc3Qoa2V5czogc3RyaW5nW10sIHNlcTogbnVtYmVyKTogQnVmZmVyIHtcbiAgICAvLyBzdGFydCBhdCAyNCBmb3IgdGhlIG5vLW9wIGNvbW1hbmQgYXQgdGhlIGVuZFxuICAgIGxldCByZXF1ZXN0U2l6ZSA9IDI0O1xuICAgIGZvciAoY29uc3Qga2V5SWR4IGluIGtleXMpIHtcbiAgICAgIHJlcXVlc3RTaXplICs9IEJ1ZmZlci5ieXRlTGVuZ3RoKGtleXNba2V5SWR4XSwgXCJ1dGY4XCIpICsgMjQ7XG4gICAgfVxuXG4gICAgY29uc3QgcmVxdWVzdCA9IEJ1ZmZlci5hbGxvYyhyZXF1ZXN0U2l6ZSk7XG5cbiAgICBsZXQgYnl0ZXNXcml0dGVuID0gMDtcbiAgICBmb3IgKGNvbnN0IGtleUlkeCBpbiBrZXlzKSB7XG4gICAgICBjb25zdCBrZXkgPSBrZXlzW2tleUlkeF07XG4gICAgICBieXRlc1dyaXR0ZW4gKz0gY29weUludG9SZXF1ZXN0QnVmZmVyKFxuICAgICAgICBjb25zdGFudHMuT1BfR0VUS1EsXG4gICAgICAgIGtleSxcbiAgICAgICAgXCJcIixcbiAgICAgICAgXCJcIixcbiAgICAgICAgc2VxLFxuICAgICAgICByZXF1ZXN0LFxuICAgICAgICBieXRlc1dyaXR0ZW5cbiAgICAgICk7XG4gICAgfVxuXG4gICAgYnl0ZXNXcml0dGVuICs9IGNvcHlJbnRvUmVxdWVzdEJ1ZmZlcihcbiAgICAgIGNvbnN0YW50cy5PUF9OT19PUCxcbiAgICAgIFwiXCIsXG4gICAgICBcIlwiLFxuICAgICAgXCJcIixcbiAgICAgIHNlcSxcbiAgICAgIHJlcXVlc3QsXG4gICAgICBieXRlc1dyaXR0ZW5cbiAgICApO1xuXG4gICAgcmV0dXJuIHJlcXVlc3Q7XG4gIH1cblxuICAvKiogRXhlY3V0aW5nIGEgcGlwZWxpbmVkIChtdWx0aSkgZ2V0IGFnYWluc3QgYSBzaW5nbGUgc2VydmVyLiBUaGlzIGlzIGEgcHJpdmF0ZSBpbXBsZW1lbnRhdGlvbiBkZXRhaWwgb2YgZ2V0TXVsdGkuICovXG4gIGFzeW5jIF9nZXRNdWx0aVRvU2VydmVyPEtleXMgZXh0ZW5kcyBzdHJpbmc+KFxuICAgIHNlcnY6IFNlcnZlcixcbiAgICBrZXlzOiBLZXlzW11cbiAgKTogUHJvbWlzZTxHZXRNdWx0aVJlc3VsdDxLZXlzLCBWYWx1ZSwgRXh0cmFzPj4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBjb25zdCByZXNwb25zZU1hcDogR2V0TXVsdGlSZXN1bHQ8c3RyaW5nLCBWYWx1ZSwgRXh0cmFzPiA9IHt9O1xuXG4gICAgICBjb25zdCBoYW5kbGU6IE9uUmVzcG9uc2VDYWxsYmFjayA9IChyZXNwb25zZSkgPT4ge1xuICAgICAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgICAgICAvLyBXaGVuIHdlIGdldCB0aGUgbm8tb3AgcmVzcG9uc2UsIHdlIGFyZSBkb25lIHdpdGggdGhpcyBvbmUgZ2V0TXVsdGkgaW4gdGhlIHBlci1iYWNrZW5kIGZhbi1vdXRcbiAgICAgICAgICAgIGlmIChyZXNwb25zZS5oZWFkZXIub3Bjb2RlID09PSBjb25zdGFudHMuT1BfTk9fT1ApIHtcbiAgICAgICAgICAgICAgLy8gVGhpcyBlbnN1cmVzIHRoZSBoYW5kbGVyIHdpbGwgYmUgZGVsZXRlZCBmcm9tIHRoZSByZXNwb25zZUNhbGxiYWNrcyBtYXAgaW4gc2VydmVyLmpzXG4gICAgICAgICAgICAgIC8vIFRoaXMgaXNuJ3QgdGVjaG5pY2FsbHkgbmVlZGVkIGhlcmUgYmVjYXVzZSB0aGUgbG9naWMgaW4gc2VydmVyLmpzIGFsc28gY2hlY2tzIGlmIHRvdGFsQm9keUxlbmd0aCA9PT0gMCwgYnV0IG91ciB1bml0dGVzdHMgYXJlbid0IGdyZWF0IGFib3V0IHNldHRpbmcgdGhhdCBmaWVsZCwgYW5kIGFsc28gdGhpcyBtYWtlcyBpdCBtb3JlIGV4cGxpY2l0XG4gICAgICAgICAgICAgIGhhbmRsZS5xdWlldCA9IGZhbHNlO1xuICAgICAgICAgICAgICByZXNvbHZlKHJlc3BvbnNlTWFwKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAocmVzcG9uc2UuaGVhZGVyLm9wY29kZSA9PT0gY29uc3RhbnRzLk9QX0dFVEsgfHwgcmVzcG9uc2UuaGVhZGVyLm9wY29kZSA9PT0gY29uc3RhbnRzLk9QX0dFVEtRKSB7XG4gICAgICAgICAgICAgIGNvbnN0IGRlc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5kZXNlcmlhbGl6ZShcbiAgICAgICAgICAgICAgICByZXNwb25zZS5oZWFkZXIub3Bjb2RlLFxuICAgICAgICAgICAgICAgIHJlc3BvbnNlLnZhbCxcbiAgICAgICAgICAgICAgICByZXNwb25zZS5leHRyYXNcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgY29uc3Qga2V5ID0gcmVzcG9uc2Uua2V5LnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgIGlmIChrZXkubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlamVjdChcbiAgICAgICAgICAgICAgICAgIG5ldyBFcnJvcihcIlJlY2lldmVkIGVtcHR5IGtleSBpbiBnZXRNdWx0aTogXCIgKyBKU09OLnN0cmluZ2lmeShyZXNwb25zZSkpXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICByZXNwb25zZU1hcFtrZXldID0geyAuLi5kZXNlcmlhbGl6ZWQsIGNhczogcmVzcG9uc2UuaGVhZGVyLmNhcyB9O1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgcmV0dXJuIHJlamVjdChcbiAgICAgICAgICAgICAgICBuZXcgRXJyb3IoXCJSZWNpZXZlZCByZXNwb25zZSBpbiBnZXRNdWx0aSBmb3IgdW5rbm93biBvcGNvZGU6IFwiICsgSlNPTi5zdHJpbmdpZnkocmVzcG9uc2UpKVxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHJldHVybiByZWplY3QoXG4gICAgICAgICAgICAgIHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJHRVRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cylcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH07XG4gICAgICAvLyBUaGlzIHByZXZlbnRzIHRoZSBoYW5kbGVyIGZyb20gYmVpbmcgZGVsZXRlZFxuICAgICAgLy8gYWZ0ZXIgdGhlIGZpcnN0IHJlc3BvbnNlLiBMb2dpYyBpbiBzZXJ2ZXIuanMuXG4gICAgICBoYW5kbGUucXVpZXQgPSB0cnVlO1xuXG4gICAgICBjb25zdCBzZXEgPSB0aGlzLmluY3JTZXEoKTtcbiAgICAgIGNvbnN0IHJlcXVlc3QgPSB0aGlzLl9idWlsZEdldE11bHRpUmVxdWVzdChrZXlzLCBzZXEpO1xuICAgICAgc2Vydi5vblJlc3BvbnNlKHRoaXMuc2VxLCBoYW5kbGUpO1xuICAgICAgc2Vydi5vbkVycm9yKHRoaXMuc2VxLCByZWplY3QpO1xuICAgICAgc2Vydi53cml0ZShyZXF1ZXN0KTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXRyaWV2cyB0aGUgdmFsdWUgYXQgdGhlIGdpdmVuIGtleXMgaW4gbWVtY2FjaGVkLiBSZXR1cm5zIGEgbWFwIGZyb20gdGhlXG4gICAqIHJlcXVlc3RlZCBrZXlzIHRvIHJlc3VsdHMsIG9yIG51bGwgaWYgdGhlIGtleSB3YXMgbm90IGZvdW5kLlxuICAgKi9cbiAgYXN5bmMgZ2V0TXVsdGk8S2V5cyBleHRlbmRzIHN0cmluZz4oXG4gICAga2V5czogS2V5c1tdXG4gICk6IFByb21pc2U8R2V0TXVsdGlSZXN1bHQ8S2V5cywgVmFsdWUsIEV4dHJhcz4+IHtcbiAgICBjb25zdCBzZXJ2ZXJLZXl0b0xvb2t1cEtleXM6IHtcbiAgICAgIFtzZXJ2ZXJLZXk6IHN0cmluZ106IHN0cmluZ1tdO1xuICAgIH0gPSB7fTtcbiAgICBrZXlzLmZvckVhY2goKGxvb2t1cEtleSkgPT4ge1xuICAgICAgY29uc3Qgc2VydmVyS2V5ID0gdGhpcy5sb29rdXBLZXlUb1NlcnZlcktleShsb29rdXBLZXkpO1xuICAgICAgaWYgKCFzZXJ2ZXJLZXl0b0xvb2t1cEtleXNbc2VydmVyS2V5XSkge1xuICAgICAgICBzZXJ2ZXJLZXl0b0xvb2t1cEtleXNbc2VydmVyS2V5XSA9IFtdO1xuICAgICAgfVxuICAgICAgc2VydmVyS2V5dG9Mb29rdXBLZXlzW3NlcnZlcktleV0ucHVzaChsb29rdXBLZXkpO1xuICAgIH0pO1xuXG4gICAgY29uc3QgdXNlZFNlcnZlcktleXMgPSBPYmplY3Qua2V5cyhzZXJ2ZXJLZXl0b0xvb2t1cEtleXMpO1xuICAgIGNvbnN0IHJlc3VsdHMgPSBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIHVzZWRTZXJ2ZXJLZXlzLm1hcCgoc2VydmVyS2V5KSA9PiB7XG4gICAgICAgIGNvbnN0IHNlcnZlciA9IHRoaXMuc2VydmVyS2V5VG9TZXJ2ZXIoc2VydmVyS2V5KTtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2dldE11bHRpVG9TZXJ2ZXIoc2VydmVyLCBzZXJ2ZXJLZXl0b0xvb2t1cEtleXNbc2VydmVyS2V5XSk7XG4gICAgICB9KVxuICAgICk7XG5cbiAgICByZXR1cm4gT2JqZWN0LmFzc2lnbih7fSwgLi4ucmVzdWx0cyk7XG4gIH1cblxuICAvKipcbiAgICogU2V0cyBga2V5YCB0byBgdmFsdWVgLlxuICAgKi9cbiAgYXN5bmMgc2V0KFxuICAgIGtleTogc3RyaW5nLFxuICAgIHZhbHVlOiBWYWx1ZSxcbiAgICBvcHRpb25zPzogeyBleHBpcmVzPzogbnVtYmVyOyBjYXM/OiBDQVNUb2tlbiB9XG4gICk6IFByb21pc2U8Ym9vbGVhbiB8IG51bGw+IHtcbiAgICBjb25zdCBleHBpcmVzID0gb3B0aW9ucz8uZXhwaXJlcztcbiAgICBjb25zdCBjYXMgPSBvcHRpb25zPy5jYXM7XG5cbiAgICAvLyBUT0RPOiBzdXBwb3J0IGZsYWdzXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgZXhwaXJhdGlvbiA9IG1ha2VFeHBpcmF0aW9uKGV4cGlyZXMgfHwgdGhpcy5vcHRpb25zLmV4cGlyZXMpO1xuICAgIGNvbnN0IGV4dHJhcyA9IEJ1ZmZlci5jb25jYXQoW0J1ZmZlci5mcm9tKFwiMDAwMDAwMDBcIiwgXCJoZXhcIiksIGV4cGlyYXRpb25dKTtcbiAgICBjb25zdCBzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLnNlcmlhbGl6ZShcbiAgICAgIGNvbnN0YW50cy5PUF9TRVQsXG4gICAgICB2YWx1ZSxcbiAgICAgIGV4dHJhc1xuICAgICk7XG4gICAgY29uc3QgcmVxdWVzdCA9IFV0aWxzLmVuY29kZVJlcXVlc3Qoe1xuICAgICAgaGVhZGVyOiB7XG4gICAgICAgIG9wY29kZTogY29uc3RhbnRzLk9QX1NFVCxcbiAgICAgICAgb3BhcXVlOiB0aGlzLnNlcSxcbiAgICAgICAgY2FzLFxuICAgICAgfSxcbiAgICAgIGtleSxcbiAgICAgIHZhbHVlOiBzZXJpYWxpemVkLnZhbHVlLFxuICAgICAgZXh0cmFzOiBzZXJpYWxpemVkLmV4dHJhcyxcbiAgICB9KTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9FWElTVFM6XG4gICAgICAgIGlmIChjYXMpIHtcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIlNFVFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICAgICAgfVxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIlNFVFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQUREXG4gICAqXG4gICAqIEFkZHMgdGhlIGdpdmVuIF9rZXlfIGFuZCBfdmFsdWVfIHRvIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHNcbiAgICogaWYgdGhlIGtleSBpcyBub3QgYWxyZWFkeSBzZXQuXG4gICAqXG4gICAqIFRoZSBvcHRpb25zIGRpY3Rpb25hcnkgdGFrZXM6XG4gICAqICogX2V4cGlyZXNfOiBvdmVycmlkZXMgdGhlIGRlZmF1bHQgZXhwaXJhdGlvbiAoc2VlIGBDbGllbnQuY3JlYXRlYCkgZm9yIHRoaXNcbiAgICogICAgICAgICAgICAgIHBhcnRpY3VsYXIga2V5LXZhbHVlIHBhaXIuXG4gICAqL1xuICBhc3luYyBhZGQoXG4gICAga2V5OiBzdHJpbmcsXG4gICAgdmFsdWU6IFZhbHVlLFxuICAgIG9wdGlvbnM/OiB7IGV4cGlyZXM/OiBudW1iZXIgfVxuICApOiBQcm9taXNlPGJvb2xlYW4gfCBudWxsPiB7XG4gICAgLy8gVE9ETzogc3VwcG9ydCBmbGFncywgc3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgZXhwaXJhdGlvbiA9IG1ha2VFeHBpcmF0aW9uKG9wdGlvbnM/LmV4cGlyZXMgfHwgdGhpcy5vcHRpb25zLmV4cGlyZXMpO1xuICAgIGNvbnN0IGV4dHJhcyA9IEJ1ZmZlci5jb25jYXQoW0J1ZmZlci5mcm9tKFwiMDAwMDAwMDBcIiwgXCJoZXhcIiksIGV4cGlyYXRpb25dKTtcblxuICAgIGNvbnN0IG9wY29kZSA9IGNvbnN0YW50cy5PUF9BREQ7XG4gICAgY29uc3Qgc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5zZXJpYWxpemUob3Bjb2RlLCB2YWx1ZSwgZXh0cmFzKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICBvcGNvZGUsXG4gICAgICBrZXksXG4gICAgICBzZXJpYWxpemVkLmV4dHJhcyxcbiAgICAgIHNlcmlhbGl6ZWQudmFsdWUsXG4gICAgICB0aGlzLnNlcVxuICAgICk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfRVhJU1RTOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIkFERFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmVwbGFjZXMgdGhlIGdpdmVuIF9rZXlfIGFuZCBfdmFsdWVfIHRvIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHNcbiAgICogaWYgdGhlIGtleSBpcyBhbHJlYWR5IHByZXNlbnQuXG4gICAqL1xuICBhc3luYyByZXBsYWNlKFxuICAgIGtleTogc3RyaW5nLFxuICAgIHZhbHVlOiBWYWx1ZSxcbiAgICBvcHRpb25zPzogeyBleHBpcmVzPzogbnVtYmVyIH1cbiAgKTogUHJvbWlzZTxib29sZWFuIHwgbnVsbD4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgZmxhZ3MsIHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IGV4cGlyYXRpb24gPSBtYWtlRXhwaXJhdGlvbihvcHRpb25zPy5leHBpcmVzIHx8IHRoaXMub3B0aW9ucy5leHBpcmVzKTtcbiAgICBjb25zdCBleHRyYXMgPSBCdWZmZXIuY29uY2F0KFtCdWZmZXIuZnJvbShcIjAwMDAwMDAwXCIsIFwiaGV4XCIpLCBleHBpcmF0aW9uXSk7XG5cbiAgICBjb25zdCBvcGNvZGU6IGNvbnN0YW50cy5PUCA9IGNvbnN0YW50cy5PUF9SRVBMQUNFO1xuICAgIGNvbnN0IHNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuc2VyaWFsaXplKG9wY29kZSwgdmFsdWUsIGV4dHJhcyk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKFxuICAgICAgb3Bjb2RlLFxuICAgICAga2V5LFxuICAgICAgc2VyaWFsaXplZC5leHRyYXMsXG4gICAgICBzZXJpYWxpemVkLnZhbHVlLFxuICAgICAgdGhpcy5zZXFcbiAgICApO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuS0VZX05PVF9GT1VORDpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIlJFUExBQ0VcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIERlbGV0ZXMgdGhlIGdpdmVuIF9rZXlfIGZyb20gbWVtY2FjaGUuIFRoZSBvcGVyYXRpb24gb25seSBzdWNjZWVkc1xuICAgKiBpZiB0aGUga2V5IGlzIGFscmVhZHkgcHJlc2VudC5cbiAgICovXG4gIGFzeW5jIGRlbGV0ZShrZXk6IHN0cmluZyk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIC8vIFRPRE86IFN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcig0LCBrZXksIFwiXCIsIFwiXCIsIHRoaXMuc2VxKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcblxuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuS0VZX05PVF9GT1VORDpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIkRFTEVURVwiLCByZXNwb25zZT8uaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEluY3JlbWVudHMgdGhlIGdpdmVuIF9rZXlfIGluIG1lbWNhY2hlLlxuICAgKi9cbiAgYXN5bmMgaW5jcmVtZW50KFxuICAgIGtleTogc3RyaW5nLFxuICAgIGFtb3VudDogbnVtYmVyLFxuICAgIG9wdGlvbnM/OiB7IGluaXRpYWw/OiBudW1iZXI7IGV4cGlyZXM/OiBudW1iZXIgfVxuICApOiBQcm9taXNlPHsgdmFsdWU6IG51bWJlciB8IG51bGw7IHN1Y2Nlc3M6IGJvb2xlYW4gfCBudWxsIH0+IHtcbiAgICAvLyBUT0RPOiBzdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBpbml0aWFsID0gb3B0aW9ucz8uaW5pdGlhbCB8fCAwO1xuICAgIGNvbnN0IGV4cGlyZXMgPSBvcHRpb25zPy5leHBpcmVzIHx8IHRoaXMub3B0aW9ucy5leHBpcmVzO1xuICAgIGNvbnN0IGV4dHJhcyA9IG1ha2VBbW91bnRJbml0aWFsQW5kRXhwaXJhdGlvbihhbW91bnQsIGluaXRpYWwsIGV4cGlyZXMpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgIGNvbnN0YW50cy5PUF9JTkNSRU1FTlQsXG4gICAgICBrZXksXG4gICAgICBleHRyYXMsXG4gICAgICBcIlwiLFxuICAgICAgdGhpcy5zZXFcbiAgICApO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICBjb25zdCBidWZJbnQgPVxuICAgICAgICAgIChyZXNwb25zZS52YWwucmVhZFVJbnQzMkJFKDApIDw8IDgpICsgcmVzcG9uc2UudmFsLnJlYWRVSW50MzJCRSg0KTtcbiAgICAgICAgcmV0dXJuIHsgdmFsdWU6IGJ1ZkludCwgc3VjY2VzczogdHJ1ZSB9O1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIklOQ1JFTUVOVFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRGVjcmVtZW50cyB0aGUgZ2l2ZW4gYGtleWAgaW4gbWVtY2FjaGUuXG4gICAqL1xuICBhc3luYyBkZWNyZW1lbnQoXG4gICAga2V5OiBzdHJpbmcsXG4gICAgYW1vdW50OiBudW1iZXIsXG4gICAgb3B0aW9uczogeyBpbml0aWFsPzogbnVtYmVyOyBleHBpcmVzPzogbnVtYmVyIH1cbiAgKTogUHJvbWlzZTx7IHZhbHVlOiBudW1iZXIgfCBudWxsOyBzdWNjZXNzOiBib29sZWFuIHwgbnVsbCB9PiB7XG4gICAgLy8gVE9ETzogc3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgaW5pdGlhbCA9IG9wdGlvbnMuaW5pdGlhbCB8fCAwO1xuICAgIGNvbnN0IGV4cGlyZXMgPSBvcHRpb25zLmV4cGlyZXMgfHwgdGhpcy5vcHRpb25zLmV4cGlyZXM7XG4gICAgY29uc3QgZXh0cmFzID0gbWFrZUFtb3VudEluaXRpYWxBbmRFeHBpcmF0aW9uKGFtb3VudCwgaW5pdGlhbCwgZXhwaXJlcyk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKFxuICAgICAgY29uc3RhbnRzLk9QX0RFQ1JFTUVOVCxcbiAgICAgIGtleSxcbiAgICAgIGV4dHJhcyxcbiAgICAgIFwiXCIsXG4gICAgICB0aGlzLnNlcVxuICAgICk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIGNvbnN0IGJ1ZkludCA9XG4gICAgICAgICAgKHJlc3BvbnNlLnZhbC5yZWFkVUludDMyQkUoMCkgPDwgOCkgKyByZXNwb25zZS52YWwucmVhZFVJbnQzMkJFKDQpO1xuICAgICAgICByZXR1cm4geyB2YWx1ZTogYnVmSW50LCBzdWNjZXNzOiB0cnVlIH07XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiREVDUkVNRU5UXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBBcHBlbmQgdGhlIGdpdmVuIF92YWx1ZV8gdG8gdGhlIHZhbHVlIGFzc29jaWF0ZWQgd2l0aCB0aGUgZ2l2ZW4gX2tleV8gaW5cbiAgICogbWVtY2FjaGUuIFRoZSBvcGVyYXRpb24gb25seSBzdWNjZWVkcyBpZiB0aGUga2V5IGlzIGFscmVhZHkgcHJlc2VudC5cbiAgICovXG4gIGFzeW5jIGFwcGVuZChrZXk6IHN0cmluZywgdmFsdWU6IFZhbHVlKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgLy8gVE9ETzogc3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3Qgb3Bjb2RlOiBjb25zdGFudHMuT1AgPSBjb25zdGFudHMuT1BfQVBQRU5EO1xuICAgIGNvbnN0IHNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuc2VyaWFsaXplKG9wY29kZSwgdmFsdWUsIFwiXCIpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgIG9wY29kZSxcbiAgICAgIGtleSxcbiAgICAgIHNlcmlhbGl6ZWQuZXh0cmFzLFxuICAgICAgc2VyaWFsaXplZC52YWx1ZSxcbiAgICAgIHRoaXMuc2VxXG4gICAgKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJBUFBFTkRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFByZXBlbmQgdGhlIGdpdmVuIF92YWx1ZV8gdG8gdGhlIHZhbHVlIGFzc29jaWF0ZWQgd2l0aCB0aGUgZ2l2ZW4gX2tleV8gaW5cbiAgICogbWVtY2FjaGUuIFRoZSBvcGVyYXRpb24gb25seSBzdWNjZWVkcyBpZiB0aGUga2V5IGlzIGFscmVhZHkgcHJlc2VudC5cbiAgICovXG4gIGFzeW5jIHByZXBlbmQoa2V5OiBzdHJpbmcsIHZhbHVlOiBWYWx1ZSk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IG9wY29kZTogY29uc3RhbnRzLk9QID0gY29uc3RhbnRzLk9QX1BSRVBFTkQ7XG4gICAgY29uc3Qgc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5zZXJpYWxpemUob3Bjb2RlLCB2YWx1ZSwgXCJcIik7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKFxuICAgICAgb3Bjb2RlLFxuICAgICAga2V5LFxuICAgICAgc2VyaWFsaXplZC5leHRyYXMsXG4gICAgICBzZXJpYWxpemVkLnZhbHVlLFxuICAgICAgdGhpcy5zZXFcbiAgICApO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuS0VZX05PVF9GT1VORDpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIlBSRVBFTkRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFRvdWNoIHNldHMgYW4gZXhwaXJhdGlvbiB2YWx1ZSwgZ2l2ZW4gYnkgX2V4cGlyZXNfLCBvbiB0aGUgZ2l2ZW4gX2tleV8gaW5cbiAgICogbWVtY2FjaGUuIFRoZSBvcGVyYXRpb24gb25seSBzdWNjZWVkcyBpZiB0aGUga2V5IGlzIGFscmVhZHkgcHJlc2VudC5cbiAgICovXG4gIGFzeW5jIHRvdWNoKGtleTogc3RyaW5nLCBleHBpcmVzOiBudW1iZXIpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAvLyBUT0RPOiBzdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBleHRyYXMgPSBtYWtlRXhwaXJhdGlvbihleHBpcmVzIHx8IHRoaXMub3B0aW9ucy5leHBpcmVzKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoMHgxYywga2V5LCBleHRyYXMsIFwiXCIsIHRoaXMuc2VxKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJUT1VDSFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRkxVU0hcbiAgICpcbiAgICogRmx1c2hlcyB0aGUgY2FjaGUgb24gZWFjaCBjb25uZWN0ZWQgc2VydmVyLiBUaGUgY2FsbGJhY2sgc2lnbmF0dXJlIGlzOlxuICAgKlxuICAgKiAgICAgY2FsbGJhY2sobGFzdEVyciwgcmVzdWx0cylcbiAgICpcbiAgICogd2hlcmUgX2xhc3RFcnJfIGlzIHRoZSBsYXN0IGVycm9yIGVuY291bnRlcmVkIChvciBudWxsLCBpbiB0aGUgY29tbW9uIGNhc2VcbiAgICogb2Ygbm8gZXJyb3JzKS4gX3Jlc3VsdHNfIGlzIGEgZGljdGlvbmFyeSBtYXBwaW5nIGBcImhvc3RuYW1lOnBvcnRcImAgdG8gZWl0aGVyXG4gICAqIGB0cnVlYCAoaWYgdGhlIG9wZXJhdGlvbiB3YXMgc3VjY2Vzc2Z1bCksIG9yIGFuIGVycm9yLlxuICAgKiBAcGFyYW0gY2FsbGJhY2tcbiAgICovXG4gIGZsdXNoKCk6IFByb21pc2U8UmVjb3JkPHN0cmluZywgYm9vbGVhbiB8IEVycm9yPj47XG4gIGZsdXNoKFxuICAgIGNhbGxiYWNrOiAoXG4gICAgICBlcnI6IEVycm9yIHwgbnVsbCxcbiAgICAgIHJlc3VsdHM6IFJlY29yZDxzdHJpbmcsIGJvb2xlYW4gfCBFcnJvcj5cbiAgICApID0+IHZvaWRcbiAgKTogdm9pZDtcbiAgZmx1c2goXG4gICAgY2FsbGJhY2s/OiAoXG4gICAgICBlcnI6IEVycm9yIHwgbnVsbCxcbiAgICAgIHJlc3VsdHM6IFJlY29yZDxzdHJpbmcsIGJvb2xlYW4gfCBFcnJvcj5cbiAgICApID0+IHZvaWRcbiAgKSB7XG4gICAgaWYgKGNhbGxiYWNrID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybiBwcm9taXNpZnkoKGNhbGxiYWNrKSA9PiB7XG4gICAgICAgIHRoaXMuZmx1c2goZnVuY3Rpb24gKGVyciwgcmVzdWx0cykge1xuICAgICAgICAgIGNhbGxiYWNrKGVyciwgcmVzdWx0cyk7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfVxuICAgIC8vIFRPRE86IHN1cHBvcnQgZXhwaXJhdGlvblxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcigweDA4LCBcIlwiLCBcIlwiLCBcIlwiLCB0aGlzLnNlcSk7XG4gICAgbGV0IGNvdW50ID0gdGhpcy5zZXJ2ZXJzLmxlbmd0aDtcbiAgICBjb25zdCByZXN1bHQ6IFJlY29yZDxzdHJpbmcsIGJvb2xlYW4gfCBFcnJvcj4gPSB7fTtcbiAgICBsZXQgbGFzdEVycjogRXJyb3IgfCBudWxsID0gbnVsbDtcblxuICAgIGNvbnN0IGhhbmRsZUZsdXNoID0gZnVuY3Rpb24gKHNlcTogbnVtYmVyLCBzZXJ2OiBTZXJ2ZXIpIHtcbiAgICAgIHNlcnYub25SZXNwb25zZShzZXEsIGZ1bmN0aW9uICgvKiByZXNwb25zZSAqLykge1xuICAgICAgICBjb3VudCAtPSAxO1xuICAgICAgICByZXN1bHRbc2Vydi5ob3N0cG9ydFN0cmluZygpXSA9IHRydWU7XG4gICAgICAgIGlmIChjYWxsYmFjayAmJiBjb3VudCA9PT0gMCkge1xuICAgICAgICAgIGNhbGxiYWNrKGxhc3RFcnIsIHJlc3VsdCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgc2Vydi5vbkVycm9yKHNlcSwgZnVuY3Rpb24gKGVycikge1xuICAgICAgICBjb3VudCAtPSAxO1xuICAgICAgICBsYXN0RXJyID0gZXJyO1xuICAgICAgICByZXN1bHRbc2Vydi5ob3N0cG9ydFN0cmluZygpXSA9IGVycjtcbiAgICAgICAgaWYgKGNhbGxiYWNrICYmIGNvdW50ID09PSAwKSB7XG4gICAgICAgICAgY2FsbGJhY2sobGFzdEVyciwgcmVzdWx0KTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICBzZXJ2LndyaXRlKHJlcXVlc3QpO1xuICAgIH07XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuc2VydmVycy5sZW5ndGg7IGkrKykge1xuICAgICAgaGFuZGxlRmx1c2godGhpcy5zZXEsIHRoaXMuc2VydmVyc1tpXSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNUQVRTX1dJVEhfS0VZXG4gICAqXG4gICAqIFNlbmRzIGEgbWVtY2FjaGUgc3RhdHMgY29tbWFuZCB3aXRoIGEga2V5IHRvIGVhY2ggY29ubmVjdGVkIHNlcnZlci4gVGhlXG4gICAqIGNhbGxiYWNrIGlzIGludm9rZWQgKipPTkNFIFBFUiBTRVJWRVIqKiBhbmQgaGFzIHRoZSBzaWduYXR1cmU6XG4gICAqXG4gICAqICAgICBjYWxsYmFjayhlcnIsIHNlcnZlciwgc3RhdHMpXG4gICAqXG4gICAqIF9zZXJ2ZXJfIGlzIHRoZSBgXCJob3N0bmFtZTpwb3J0XCJgIG9mIHRoZSBzZXJ2ZXIsIGFuZCBfc3RhdHNfIGlzIGEgZGljdGlvbmFyeVxuICAgKiBtYXBwaW5nIHRoZSBzdGF0IG5hbWUgdG8gdGhlIHZhbHVlIG9mIHRoZSBzdGF0aXN0aWMgYXMgYSBzdHJpbmcuXG4gICAqIEBwYXJhbSBrZXlcbiAgICogQHBhcmFtIGNhbGxiYWNrXG4gICAqL1xuICBzdGF0c1dpdGhLZXkoXG4gICAga2V5OiBzdHJpbmcsXG4gICAgY2FsbGJhY2s/OiAoXG4gICAgICBlcnI6IEVycm9yIHwgbnVsbCxcbiAgICAgIHNlcnZlcjogc3RyaW5nLFxuICAgICAgc3RhdHM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gfCBudWxsXG4gICAgKSA9PiB2b2lkXG4gICk6IHZvaWQge1xuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcigweDEwLCBrZXksIFwiXCIsIFwiXCIsIHRoaXMuc2VxKTtcblxuICAgIGNvbnN0IGhhbmRsZVN0YXRzID0gKHNlcTogbnVtYmVyLCBzZXJ2OiBTZXJ2ZXIpID0+IHtcbiAgICAgIGNvbnN0IHJlc3VsdDogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHt9O1xuICAgICAgY29uc3QgaGFuZGxlOiBPblJlc3BvbnNlQ2FsbGJhY2sgPSAocmVzcG9uc2UpID0+IHtcbiAgICAgICAgLy8gZW5kIG9mIHN0YXQgcmVzcG9uc2VzXG4gICAgICAgIGlmIChyZXNwb25zZS5oZWFkZXIudG90YWxCb2R5TGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgICAgICBjYWxsYmFjayhudWxsLCBzZXJ2Lmhvc3Rwb3J0U3RyaW5nKCksIHJlc3VsdCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICAvLyBwcm9jZXNzIHNpbmdsZSBzdGF0IGxpbmUgcmVzcG9uc2VcbiAgICAgICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICAgICAgcmVzdWx0W3Jlc3BvbnNlLmtleS50b1N0cmluZygpXSA9IHJlc3BvbnNlLnZhbC50b1N0cmluZygpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIGNvbnN0IGVycm9yID0gdGhpcy5oYW5kbGVSZXNwb25zZUVycm9yKFxuICAgICAgICAgICAgICBgU1RBVFMgKCR7a2V5fSlgLFxuICAgICAgICAgICAgICByZXNwb25zZS5oZWFkZXIuc3RhdHVzLFxuICAgICAgICAgICAgICB1bmRlZmluZWRcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgY2FsbGJhY2soZXJyb3IsIHNlcnYuaG9zdHBvcnRTdHJpbmcoKSwgbnVsbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH07XG4gICAgICBoYW5kbGUucXVpZXQgPSB0cnVlO1xuXG4gICAgICBzZXJ2Lm9uUmVzcG9uc2Uoc2VxLCBoYW5kbGUpO1xuICAgICAgc2Vydi5vbkVycm9yKHNlcSwgZnVuY3Rpb24gKGVycikge1xuICAgICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgICBjYWxsYmFjayhlcnIsIHNlcnYuaG9zdHBvcnRTdHJpbmcoKSwgbnVsbCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgc2Vydi53cml0ZShyZXF1ZXN0KTtcbiAgICB9O1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnNlcnZlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGhhbmRsZVN0YXRzKHRoaXMuc2VxLCB0aGlzLnNlcnZlcnNbaV0pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTVEFUU1xuICAgKlxuICAgKiBGZXRjaGVzIG1lbWNhY2hlIHN0YXRzIGZyb20gZWFjaCBjb25uZWN0ZWQgc2VydmVyLiBUaGUgY2FsbGJhY2sgaXMgaW52b2tlZFxuICAgKiAqKk9OQ0UgUEVSIFNFUlZFUioqIGFuZCBoYXMgdGhlIHNpZ25hdHVyZTpcbiAgICpcbiAgICogICAgIGNhbGxiYWNrKGVyciwgc2VydmVyLCBzdGF0cylcbiAgICpcbiAgICogX3NlcnZlcl8gaXMgdGhlIGBcImhvc3RuYW1lOnBvcnRcImAgb2YgdGhlIHNlcnZlciwgYW5kIF9zdGF0c18gaXMgYVxuICAgKiBkaWN0aW9uYXJ5IG1hcHBpbmcgdGhlIHN0YXQgbmFtZSB0byB0aGUgdmFsdWUgb2YgdGhlIHN0YXRpc3RpYyBhcyBhIHN0cmluZy5cbiAgICogQHBhcmFtIGNhbGxiYWNrXG4gICAqL1xuICBzdGF0cyhcbiAgICBjYWxsYmFjaz86IChcbiAgICAgIGVycjogRXJyb3IgfCBudWxsLFxuICAgICAgc2VydmVyOiBzdHJpbmcsXG4gICAgICBzdGF0czogUmVjb3JkPHN0cmluZywgc3RyaW5nPiB8IG51bGxcbiAgICApID0+IHZvaWRcbiAgKTogdm9pZCB7XG4gICAgdGhpcy5zdGF0c1dpdGhLZXkoXCJcIiwgY2FsbGJhY2spO1xuICB9XG5cbiAgLyoqXG4gICAqIFJFU0VUX1NUQVRTXG4gICAqXG4gICAqIFJlc2V0IHRoZSBzdGF0aXN0aWNzIGVhY2ggc2VydmVyIGlzIGtlZXBpbmcgYmFjayB0byB6ZXJvLiBUaGlzIGRvZXNuJ3QgY2xlYXJcbiAgICogc3RhdHMgc3VjaCBhcyBpdGVtIGNvdW50LCBidXQgdGVtcG9yYXJ5IHN0YXRzIHN1Y2ggYXMgdG90YWwgbnVtYmVyIG9mXG4gICAqIGNvbm5lY3Rpb25zIG92ZXIgdGltZS5cbiAgICpcbiAgICogVGhlIGNhbGxiYWNrIGlzIGludm9rZWQgKipPTkNFIFBFUiBTRVJWRVIqKiBhbmQgaGFzIHRoZSBzaWduYXR1cmU6XG4gICAqXG4gICAqICAgICBjYWxsYmFjayhlcnIsIHNlcnZlcilcbiAgICpcbiAgICogX3NlcnZlcl8gaXMgdGhlIGBcImhvc3RuYW1lOnBvcnRcImAgb2YgdGhlIHNlcnZlci5cbiAgICogQHBhcmFtIGNhbGxiYWNrXG4gICAqL1xuICByZXNldFN0YXRzKFxuICAgIGNhbGxiYWNrPzogKFxuICAgICAgZXJyOiBFcnJvciB8IG51bGwsXG4gICAgICBzZXJ2ZXI6IHN0cmluZyxcbiAgICAgIHN0YXRzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+IHwgbnVsbFxuICAgICkgPT4gdm9pZFxuICApOiB2b2lkIHtcbiAgICB0aGlzLnN0YXRzV2l0aEtleShcInJlc2V0XCIsIGNhbGxiYWNrKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBRVUlUXG4gICAqXG4gICAqIENsb3NlcyB0aGUgY29ubmVjdGlvbiB0byBlYWNoIHNlcnZlciwgbm90aWZ5aW5nIHRoZW0gb2YgdGhpcyBpbnRlbnRpb24uIE5vdGVcbiAgICogdGhhdCBxdWl0IGNhbiByYWNlIGFnYWluc3QgYWxyZWFkeSBvdXRzdGFuZGluZyByZXF1ZXN0cyB3aGVuIHRob3NlIHJlcXVlc3RzXG4gICAqIGZhaWwgYW5kIGFyZSByZXRyaWVkLCBsZWFkaW5nIHRvIHRoZSBxdWl0IGNvbW1hbmQgd2lubmluZyBhbmQgY2xvc2luZyB0aGVcbiAgICogY29ubmVjdGlvbiBiZWZvcmUgdGhlIHJldHJpZXMgY29tcGxldGUuXG4gICAqL1xuICBxdWl0KCkge1xuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIC8vIFRPRE86IE5pY2VyIHBlcmhhcHMgdG8gZG8gUVVJVFEgKDB4MTcpIGJ1dCBuZWVkIGEgbmV3IGNhbGxiYWNrIGZvciB3aGVuXG4gICAgLy8gd3JpdGUgaXMgZG9uZS5cbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoMHgwNywgXCJcIiwgXCJcIiwgXCJcIiwgdGhpcy5zZXEpOyAvLyBRVUlUXG4gICAgbGV0IHNlcnY7XG5cbiAgICBjb25zdCBoYW5kbGVRdWl0ID0gZnVuY3Rpb24gKHNlcTogbnVtYmVyLCBzZXJ2OiBTZXJ2ZXIpIHtcbiAgICAgIHNlcnYub25SZXNwb25zZShzZXEsIGZ1bmN0aW9uICgvKiByZXNwb25zZSAqLykge1xuICAgICAgICBzZXJ2LmNsb3NlKCk7XG4gICAgICB9KTtcbiAgICAgIHNlcnYub25FcnJvcihzZXEsIGZ1bmN0aW9uICgvKiBlcnIgKi8pIHtcbiAgICAgICAgc2Vydi5jbG9zZSgpO1xuICAgICAgfSk7XG4gICAgICBzZXJ2LndyaXRlKHJlcXVlc3QpO1xuICAgIH07XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuc2VydmVycy5sZW5ndGg7IGkrKykge1xuICAgICAgc2VydiA9IHRoaXMuc2VydmVyc1tpXTtcbiAgICAgIGhhbmRsZVF1aXQodGhpcy5zZXEsIHNlcnYpO1xuICAgIH1cbiAgfVxuXG4gIF92ZXJzaW9uKHNlcnZlcjogU2VydmVyKTogUHJvbWlzZTx7IHZhbHVlOiBWYWx1ZSB8IG51bGwgfT4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICB0aGlzLmluY3JTZXEoKTtcbiAgICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgICAgY29uc3RhbnRzLk9QX1ZFUlNJT04sXG4gICAgICAgIFwiXCIsXG4gICAgICAgIFwiXCIsXG4gICAgICAgIFwiXCIsXG4gICAgICAgIHRoaXMuc2VxXG4gICAgICApO1xuICAgICAgdGhpcy5wZXJmb3JtT25TZXJ2ZXIoc2VydmVyLCByZXF1ZXN0LCB0aGlzLnNlcSwgKGVyciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgIHJldHVybiByZWplY3QoZXJyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHN3aXRjaCAocmVzcG9uc2UhLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgICAgICAvKiBUT0RPOiB0aGlzIGlzIGJ1Z2dlZCwgd2Ugc2hvdWxkJ3QgdXNlIHRoZSBkZXNlcmlhbGl6ZXIgaGVyZSwgc2luY2UgdmVyc2lvbiBhbHdheXMgcmV0dXJucyBhIHZlcnNpb24gc3RyaW5nLlxuICAgICAgICAgICAgIFRoZSBkZXNlcmlhbGl6ZXIgc2hvdWxkIG9ubHkgYmUgdXNlZCBvbiB1c2VyIGtleSBkYXRhLiAqL1xuICAgICAgICAgICAgY29uc3QgZGVzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLmRlc2VyaWFsaXplKFxuICAgICAgICAgICAgICByZXNwb25zZSEuaGVhZGVyLm9wY29kZSxcbiAgICAgICAgICAgICAgcmVzcG9uc2UhLnZhbCxcbiAgICAgICAgICAgICAgcmVzcG9uc2UhLmV4dHJhc1xuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHJldHVybiByZXNvbHZlKHsgdmFsdWU6IGRlc2VyaWFsaXplZC52YWx1ZSB9KTtcbiAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgcmV0dXJuIHJlamVjdChcbiAgICAgICAgICAgICAgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIlZFUlNJT05cIiwgcmVzcG9uc2UhLmhlYWRlci5zdGF0dXMpXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXF1ZXN0IHRoZSBzZXJ2ZXIgdmVyc2lvbiBmcm9tIHRoZSBcImZpcnN0XCIgc2VydmVyIGluIHRoZSBiYWNrZW5kIHBvb2wuXG4gICAqIFRoZSBzZXJ2ZXIgcmVzcG9uZHMgd2l0aCBhIHBhY2tldCBjb250YWluaW5nIHRoZSB2ZXJzaW9uIHN0cmluZyBpbiB0aGUgYm9keSB3aXRoIHRoZSBmb2xsb3dpbmcgZm9ybWF0OiBcIngueS56XCJcbiAgICovXG4gIHZlcnNpb24oKTogUHJvbWlzZTx7IHZhbHVlOiBWYWx1ZSB8IG51bGwgfT4ge1xuICAgIGNvbnN0IHNlcnZlciA9IHRoaXMuc2VydmVyS2V5VG9TZXJ2ZXIodGhpcy5zZXJ2ZXJLZXlzWzBdKTtcbiAgICByZXR1cm4gdGhpcy5fdmVyc2lvbihzZXJ2ZXIpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHJpZXZlcyB0aGUgc2VydmVyIHZlcnNpb24gZnJvbSBhbGwgdGhlIHNlcnZlcnNcbiAgICogaW4gdGhlIGJhY2tlbmQgcG9vbCwgZXJyb3JzIGlmIGFueSBvbmUgb2YgdGhlbSBoYXMgYW5cbiAgICogZXJyb3JcbiAgICovXG4gIGFzeW5jIHZlcnNpb25BbGwoKTogUHJvbWlzZTx7XG4gICAgdmFsdWVzOiBSZWNvcmQ8c3RyaW5nLCBWYWx1ZSB8IG51bGw+O1xuICB9PiB7XG4gICAgY29uc3QgdmVyc2lvbk9iamVjdHMgPSBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIHRoaXMuc2VydmVyS2V5cy5tYXAoKHNlcnZlcktleSkgPT4ge1xuICAgICAgICBjb25zdCBzZXJ2ZXIgPSB0aGlzLnNlcnZlcktleVRvU2VydmVyKHNlcnZlcktleSk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuX3ZlcnNpb24oc2VydmVyKS50aGVuKChyZXNwb25zZSkgPT4ge1xuICAgICAgICAgIHJldHVybiB7IHNlcnZlcktleTogc2VydmVyS2V5LCB2YWx1ZTogcmVzcG9uc2UudmFsdWUgfTtcbiAgICAgICAgfSk7XG4gICAgICB9KVxuICAgICk7XG4gICAgY29uc3QgdmFsdWVzID0gdmVyc2lvbk9iamVjdHMucmVkdWNlKChhY2N1bXVsYXRvciwgdmVyc2lvbk9iamVjdCkgPT4ge1xuICAgICAgYWNjdW11bGF0b3JbdmVyc2lvbk9iamVjdC5zZXJ2ZXJLZXldID0gdmVyc2lvbk9iamVjdC52YWx1ZTtcbiAgICAgIHJldHVybiBhY2N1bXVsYXRvcjtcbiAgICB9LCB7fSBhcyBSZWNvcmQ8c3RyaW5nLCBWYWx1ZSB8IG51bGw+KTtcbiAgICByZXR1cm4geyB2YWx1ZXM6IHZhbHVlcyB9O1xuICB9XG5cbiAgLyoqXG4gICAqIENsb3NlcyAoYWJydXB0bHkpIGNvbm5lY3Rpb25zIHRvIGFsbCB0aGUgc2VydmVycy5cbiAgICogQHNlZSB0aGlzLnF1aXRcbiAgICovXG4gIGNsb3NlKCkge1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5zZXJ2ZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB0aGlzLnNlcnZlcnNbaV0uY2xvc2UoKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUGVyZm9ybSBhIGdlbmVyaWMgc2luZ2xlIHJlc3BvbnNlIG9wZXJhdGlvbiAoZ2V0LCBzZXQgZXRjKSBvbiBvbmUgc2VydmVyXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgdGhlIGtleSB0byBoYXNoIHRvIGdldCBhIHNlcnZlciBmcm9tIHRoZSBwb29sXG4gICAqIEBwYXJhbSB7YnVmZmVyfSByZXF1ZXN0IGEgYnVmZmVyIGNvbnRhaW5pbmcgdGhlIHJlcXVlc3RcbiAgICogQHBhcmFtIHtudW1iZXJ9IHNlcSB0aGUgc2VxdWVuY2UgbnVtYmVyIG9mIHRoZSBvcGVyYXRpb24uIEl0IGlzIHVzZWQgdG8gcGluIHRoZSBjYWxsYmFja3NcbiAgICAgICAgICAgICAgICAgICAgICAgICB0byBhIHNwZWNpZmljIG9wZXJhdGlvbiBhbmQgc2hvdWxkIG5ldmVyIGNoYW5nZSBkdXJpbmcgYSBgcGVyZm9ybWAuXG4gICAqIEBwYXJhbSB7bnVtYmVyP30gcmV0cmllcyBudW1iZXIgb2YgdGltZXMgdG8gcmV0cnkgcmVxdWVzdCBvbiBmYWlsdXJlXG4gICAqL1xuICBwZXJmb3JtKFxuICAgIGtleTogc3RyaW5nLFxuICAgIHJlcXVlc3Q6IEJ1ZmZlcixcbiAgICBzZXE6IG51bWJlcixcbiAgICByZXRyaWVzPzogbnVtYmVyXG4gICk6IFByb21pc2U8TWVzc2FnZT4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBjb25zdCBzZXJ2ZXJLZXkgPSB0aGlzLmxvb2t1cEtleVRvU2VydmVyS2V5KGtleSk7XG4gICAgICBjb25zdCBzZXJ2ZXIgPSB0aGlzLnNlcnZlcktleVRvU2VydmVyKHNlcnZlcktleSk7XG5cbiAgICAgIGlmICghc2VydmVyKSB7XG4gICAgICAgIHJldHVybiByZWplY3QobmV3IEVycm9yKFwiTm8gc2VydmVycyBhdmFpbGFibGVcIikpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLnBlcmZvcm1PblNlcnZlcihcbiAgICAgICAgc2VydmVyLFxuICAgICAgICByZXF1ZXN0LFxuICAgICAgICBzZXEsXG4gICAgICAgIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgIHJldHVybiByZWplY3QoZXJyb3IpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXNvbHZlKHJlc3BvbnNlISk7XG4gICAgICAgIH0sXG4gICAgICAgIHJldHJpZXNcbiAgICAgICk7XG4gICAgfSk7XG4gIH1cblxuICBwZXJmb3JtT25TZXJ2ZXIoXG4gICAgc2VydmVyOiBTZXJ2ZXIsXG4gICAgcmVxdWVzdDogQnVmZmVyLFxuICAgIHNlcTogbnVtYmVyLFxuICAgIGNhbGxiYWNrOiBSZXNwb25zZU9yRXJyb3JDYWxsYmFjayxcbiAgICByZXRyaWVzOiBudW1iZXIgPSAwXG4gICkge1xuICAgIGNvbnN0IF90aGlzID0gdGhpcztcblxuICAgIHJldHJpZXMgPSByZXRyaWVzIHx8IHRoaXMub3B0aW9ucy5yZXRyaWVzO1xuICAgIGNvbnN0IG9yaWdSZXRyaWVzID0gdGhpcy5vcHRpb25zLnJldHJpZXM7XG4gICAgY29uc3QgbG9nZ2VyID0gdGhpcy5vcHRpb25zLmxvZ2dlcjtcbiAgICBjb25zdCByZXRyeV9kZWxheSA9IHRoaXMub3B0aW9ucy5yZXRyeV9kZWxheTtcblxuICAgIGNvbnN0IHJlc3BvbnNlSGFuZGxlcjogT25SZXNwb25zZUNhbGxiYWNrID0gZnVuY3Rpb24gKHJlc3BvbnNlKSB7XG4gICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgY2FsbGJhY2sobnVsbCwgcmVzcG9uc2UpO1xuICAgICAgfVxuICAgIH07XG5cbiAgICBjb25zdCBlcnJvckhhbmRsZXI6IE9uRXJyb3JDYWxsYmFjayA9IGZ1bmN0aW9uIChlcnJvcikge1xuICAgICAgaWYgKC0tcmV0cmllcyA+IDApIHtcbiAgICAgICAgLy8gV2FpdCBmb3IgcmV0cnlfZGVsYXlcbiAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgX3RoaXMucGVyZm9ybU9uU2VydmVyKHNlcnZlciwgcmVxdWVzdCwgc2VxLCBjYWxsYmFjaywgcmV0cmllcyk7XG4gICAgICAgIH0sIDEwMDAgKiByZXRyeV9kZWxheSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBsb2dnZXIubG9nKFxuICAgICAgICAgIFwiTWVtSlM6IFNlcnZlciA8XCIgK1xuICAgICAgICAgICAgc2VydmVyLmhvc3Rwb3J0U3RyaW5nKCkgK1xuICAgICAgICAgICAgXCI+IGZhaWxlZCBhZnRlciAoXCIgK1xuICAgICAgICAgICAgb3JpZ1JldHJpZXMgK1xuICAgICAgICAgICAgXCIpIHJldHJpZXMgd2l0aCBlcnJvciAtIFwiICtcbiAgICAgICAgICAgIGVycm9yLm1lc3NhZ2VcbiAgICAgICAgKTtcbiAgICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgICAgY2FsbGJhY2soZXJyb3IsIG51bGwpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfTtcblxuICAgIHNlcnZlci5vblJlc3BvbnNlKHNlcSwgcmVzcG9uc2VIYW5kbGVyKTtcbiAgICBzZXJ2ZXIub25FcnJvcihzZXEsIGVycm9ySGFuZGxlcik7XG4gICAgc2VydmVyLndyaXRlKHJlcXVlc3QpO1xuICB9XG5cbiAgLy8gSW5jcmVtZW50IHRoZSBzZXEgdmFsdWVcbiAgaW5jclNlcSgpIHtcbiAgICB0aGlzLnNlcSsrO1xuXG4gICAgLy8gV3JhcCBgdGhpcy5zZXFgIHRvIDMyLWJpdHMgc2luY2UgdGhlIGZpZWxkIHdlIGZpdCBpdCBpbnRvIGlzIG9ubHkgMzItYml0cy5cbiAgICB0aGlzLnNlcSAmPSAweGZmZmZmZmZmO1xuXG4gICAgcmV0dXJuIHRoaXMuc2VxXG4gIH1cblxuICBwcml2YXRlIGNyZWF0ZUFuZExvZ0Vycm9yKFxuICAgIGNvbW1hbmROYW1lOiBzdHJpbmcsXG4gICAgcmVzcG9uc2VTdGF0dXM6IFJlc3BvbnNlU3RhdHVzIHwgdW5kZWZpbmVkXG4gICk6IEVycm9yIHtcbiAgICBjb25zdCBlcnJvck1lc3NhZ2UgPSBgTWVtSlMgJHtjb21tYW5kTmFtZX06ICR7Y29uc3RhbnRzLnJlc3BvbnNlU3RhdHVzVG9TdHJpbmcoXG4gICAgICByZXNwb25zZVN0YXR1c1xuICAgICl9YDtcbiAgICB0aGlzLm9wdGlvbnMubG9nZ2VyLmxvZyhlcnJvck1lc3NhZ2UpO1xuICAgIHJldHVybiBuZXcgRXJyb3IoZXJyb3JNZXNzYWdlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBMb2cgYW4gZXJyb3IgdG8gdGhlIGxvZ2dlciwgdGhlbiByZXR1cm4gdGhlIGVycm9yLlxuICAgKiBJZiBhIGNhbGxiYWNrIGlzIGdpdmVuLCBjYWxsIGl0IHdpdGggY2FsbGJhY2soZXJyb3IsIG51bGwpLlxuICAgKi9cbiAgcHJpdmF0ZSBoYW5kbGVSZXNwb25zZUVycm9yKFxuICAgIGNvbW1hbmROYW1lOiBzdHJpbmcsXG4gICAgcmVzcG9uc2VTdGF0dXM6IFJlc3BvbnNlU3RhdHVzIHwgdW5kZWZpbmVkLFxuICAgIGNhbGxiYWNrOiB1bmRlZmluZWQgfCAoKGVycm9yOiBFcnJvciB8IG51bGwsIG90aGVyOiBudWxsKSA9PiB2b2lkKVxuICApOiBFcnJvciB7XG4gICAgY29uc3QgZXJyb3IgPSB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKGNvbW1hbmROYW1lLCByZXNwb25zZVN0YXR1cyk7XG4gICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICBjYWxsYmFjayhlcnJvciwgbnVsbCk7XG4gICAgfVxuICAgIHJldHVybiBlcnJvcjtcbiAgfVxufVxuXG5leHBvcnQgeyBDbGllbnQsIFNlcnZlciwgVXRpbHMsIEhlYWRlciB9O1xuIl19 \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVtanMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbWVtanMvbWVtanMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLHdCQUF3Qjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUV4QixxQ0FLa0I7QUFvaUNELHVGQXRpQ2YsZUFBTSxPQXNpQ2U7QUFuaUN2Qix1REFBK0Q7QUFDL0QsbUNBU2lCO0FBQ2pCLHVEQUF5QztBQUN6QywyQ0FBNkM7QUFDN0MsK0NBQWlDO0FBc2hDUixzQkFBSztBQXJoQzlCLGlEQUFtQztBQXFoQ0gsd0JBQU07QUFuaEN0QyxTQUFTLDhCQUE4QixDQUNyQyxPQUFpQixFQUNqQixHQUFXO0lBRVgsTUFBTSxLQUFLLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQztJQUM3QixNQUFNLEtBQUssR0FBRyxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxnQkFBUSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3BELE9BQU8sT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ3hCLENBQUM7QUFFRCwrQ0FBK0M7QUFDL0MsU0FBUyxTQUFTLENBQ2hCLE9BQTBFO0lBRTFFLE9BQU8sSUFBSSxPQUFPLENBQUMsVUFBVSxPQUFPLEVBQUUsTUFBTTtRQUMxQyxPQUFPLENBQUMsVUFBVSxHQUFHLEVBQUUsTUFBTTtZQUMzQixHQUFHLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3RDLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBNkRELE1BQU0sTUFBTTtJQVFWLDRFQUE0RTtJQUM1RSxtQ0FBbUM7SUFDbkMsWUFBWSxPQUFpQixFQUFFLE9BQTBDO1FBQ3ZFLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO1FBQ3ZCLElB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MUMsTUFBTSxZQUFZLEdBQUcsU0FBUyxXQUFXLEtBQUssU0FBUyxDQUFDLHNCQUFzQixDQUM1RSxjQUFjLENBQ2YsRUFBRSxDQUFDO1FBQ0osSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLFlBQVksQ0FBQyxDQUFDO1FBQ3RDLE9BQU8sSUFBSSxLQUFLLENBQUMsWUFBWSxDQUFDLENBQUM7SUFDakMsQ0FBQztJQUVEOzs7T0FHRztJQUNLLG1CQUFtQixDQUN6QixXQUFtQixFQUNuQixjQUEwQyxFQUMxQyxRQUFrRTtRQUVsRSxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsaUJBQWlCLENBQUMsV0FBVyxFQUFFLGNBQWMsQ0FBQyxDQUFDO1FBQ2xFLElBQUksUUFBUSxFQUFFO1lBQ1osUUFBUSxDQUFDLEtBQUssRUFBRSxJQUFJLENBQUMsQ0FBQztTQUN2QjtRQUNELE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQztDQUNGO0FBRVEsd0JBQU0iLCJzb3VyY2VzQ29udGVudCI6WyIvLyBNZW1UUyBNZW1jYWNoZSBDbGllbnRcblxuaW1wb3J0IHtcbiAgT25FcnJvckNhbGxiYWNrLFxuICBPblJlc3BvbnNlQ2FsbGJhY2ssXG4gIFNlcnZlcixcbiAgU2VydmVyT3B0aW9ucyxcbn0gZnJvbSBcIi4vc2VydmVyXCI7XG5pbXBvcnQgeyBub29wU2VyaWFsaXplciwgU2VyaWFsaXplciB9IGZyb20gXCIuL25vb3Atc2VyaWFsaXplclwiO1xuaW1wb3J0IHtcbiAgbWFrZVJlcXVlc3RCdWZmZXIsXG4gIGNvcHlJbnRvUmVxdWVzdEJ1ZmZlcixcbiAgbWVyZ2UsXG4gIG1ha2VFeHBpcmF0aW9uLFxuICBtYWtlQW1vdW50SW5pdGlhbEFuZEV4cGlyYXRpb24sXG4gIGhhc2hDb2RlLFxuICBNYXliZUJ1ZmZlcixcbiAgTWVzc2FnZSxcbn0gZnJvbSBcIi4vdXRpbHNcIjtcbmltcG9ydCAqIGFzIGNvbnN0YW50cyBmcm9tIFwiLi9jb25zdGFudHNcIjtcbmltcG9ydCB7IFJlc3BvbnNlU3RhdHVzIH0gZnJvbSBcIi4vY29uc3RhbnRzXCI7XG5pbXBvcnQgKiBhcyBVdGlscyBmcm9tIFwiLi91dGlsc1wiO1xuaW1wb3J0ICogYXMgSGVhZGVyIGZyb20gXCIuL2hlYWRlclwiO1xuXG5mdW5jdGlvbiBkZWZhdWx0S2V5VG9TZXJ2ZXJIYXNoRnVuY3Rpb24oXG4gIHNlcnZlcnM6IHN0cmluZ1tdLFxuICBrZXk6IHN0cmluZ1xuKTogc3RyaW5nIHtcbiAgY29uc3QgdG90YWwgPSBzZXJ2ZXJzLmxlbmd0aDtcbiAgY29uc3QgaW5kZXggPSB0b3RhbCA+IDEgPyBoYXNoQ29kZShrZXkpICUgdG90YWwgOiAwO1xuICByZXR1cm4gc2VydmVyc1tpbmRleF07XG59XG5cbi8vIGNvbnZlcnRzIGEgY2FsbCBpbnRvIGEgcHJvbWlzZS1yZXR1cm5pbmcgb25lXG5mdW5jdGlvbiBwcm9taXNpZnk8UmVzdWx0PihcbiAgY29tbWFuZDogKGNhbGxiYWNrOiAoZXJyb3I6IEVycm9yIHwgbnVsbCwgcmVzdWx0OiBSZXN1bHQpID0+IHZvaWQpID0+IHZvaWRcbik6IFByb21pc2U8UmVzdWx0PiB7XG4gIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgY29tbWFuZChmdW5jdGlvbiAoZXJyLCByZXN1bHQpIHtcbiAgICAgIGVyciA/IHJlamVjdChlcnIpIDogcmVzb2x2ZShyZXN1bHQpO1xuICAgIH0pO1xuICB9KTtcbn1cblxudHlwZSBSZXNwb25zZU9yRXJyb3JDYWxsYmFjayA9IChcbiAgZXJyb3I6IEVycm9yIHwgbnVsbCxcbiAgcmVzcG9uc2U6IE1lc3NhZ2UgfCBudWxsXG4pID0+IHZvaWQ7XG5cbmludGVyZmFjZSBCYXNlQ2xpZW50T3B0aW9ucyB7XG4gIHJldHJpZXM6IG51bWJlcjtcbiAgcmV0cnlfZGVsYXk6IG51bWJlcjtcbiAgZXhwaXJlczogbnVtYmVyO1xuICBsb2dnZXI6IHsgbG9nOiB0eXBlb2YgY29uc29sZS5sb2cgfTtcbiAga2V5VG9TZXJ2ZXJIYXNoRnVuY3Rpb246IHR5cGVvZiBkZWZhdWx0S2V5VG9TZXJ2ZXJIYXNoRnVuY3Rpb247XG59XG5cbmludGVyZmFjZSBTZXJpYWxpemVyUHJvcDxWYWx1ZSwgRXh0cmFzPiB7XG4gIHNlcmlhbGl6ZXI6IFNlcmlhbGl6ZXI8VmFsdWUsIEV4dHJhcz47XG59XG5cbi8qKlxuICogVGhlIGNsaWVudCBoYXMgcGFydGlhbCBzdXBwb3J0IGZvciBzZXJpYWxpemluZyBhbmQgZGVzZXJpYWxpemluZyB2YWx1ZXMgZnJvbSB0aGVcbiAqIEJ1ZmZlciBieXRlIHN0cmluZ3Mgd2UgcmVjaWV2ZSBmcm9tIHRoZSB3aXJlLiBUaGUgZGVmYXVsdCBzZXJpYWxpemVyIGlzIGZvciBNYXliZUJ1ZmZlci5cbiAqXG4gKiBJZiBWYWx1ZSBhbmQgRXh0cmFzIGFyZSBvZiB0eXBlIEJ1ZmZlciwgdGhlbiByZXR1cm4gdHlwZSBXaGVuQnVmZmVyLiBPdGhlcndpc2UsXG4gKiByZXR1cm4gdHlwZSBOb3RCdWZmZXIuXG4gKi9cbnR5cGUgSWZCdWZmZXI8XG4gIFZhbHVlLFxuICBFeHRyYXMsXG4gIFdoZW5WYWx1ZUFuZEV4dHJhc0FyZUJ1ZmZlcnMsXG4gIE5vdEJ1ZmZlclxuPiA9IFZhbHVlIGV4dGVuZHMgQnVmZmVyXG4gID8gRXh0cmFzIGV4dGVuZHMgQnVmZmVyXG4gICAgPyBXaGVuVmFsdWVBbmRFeHRyYXNBcmVCdWZmZXJzXG4gICAgOiBOb3RCdWZmZXJcbiAgOiBOb3RCdWZmZXI7XG5cbmV4cG9ydCB0eXBlIEdpdmVuQ2xpZW50T3B0aW9uczxWYWx1ZSwgRXh0cmFzPiA9IFBhcnRpYWw8QmFzZUNsaWVudE9wdGlvbnM+ICZcbiAgSWZCdWZmZXI8XG4gICAgVmFsdWUsXG4gICAgRXh0cmFzLFxuICAgIFBhcnRpYWw8U2VyaWFsaXplclByb3A8VmFsdWUsIEV4dHJhcz4+LFxuICAgIFNlcmlhbGl6ZXJQcm9wPFZhbHVlLCBFeHRyYXM+XG4gID47XG5cbmV4cG9ydCB0eXBlIENBU1Rva2VuID0gQnVmZmVyO1xuXG5leHBvcnQgaW50ZXJmYWNlIEdldFJlc3VsdDxWYWx1ZSA9IE1heWJlQnVmZmVyLCBFeHRyYXMgPSBNYXliZUJ1ZmZlcj4ge1xuICB2YWx1ZTogVmFsdWU7XG4gIGV4dHJhczogRXh0cmFzO1xuICBjYXM6IENBU1Rva2VuIHwgdW5kZWZpbmVkO1xufVxuXG5leHBvcnQgdHlwZSBHZXRNdWx0aVJlc3VsdDxcbiAgS2V5cyBleHRlbmRzIHN0cmluZyA9IHN0cmluZyxcbiAgVmFsdWUgPSBNYXliZUJ1ZmZlcixcbiAgRXh0cmFzID0gTWF5YmVCdWZmZXJcbj4gPSB7XG4gIFtLIGluIEtleXNdPzogR2V0UmVzdWx0PFZhbHVlLCBFeHRyYXM+O1xufTtcblxuY2xhc3MgQ2xpZW50PFZhbHVlID0gTWF5YmVCdWZmZXIsIEV4dHJhcyA9IE1heWJlQnVmZmVyPiB7XG4gIHNlcnZlcnM6IFNlcnZlcltdO1xuICBzZXE6IG51bWJlcjtcbiAgb3B0aW9uczogQmFzZUNsaWVudE9wdGlvbnMgJiBQYXJ0aWFsPFNlcmlhbGl6ZXJQcm9wPFZhbHVlLCBFeHRyYXM+PjtcbiAgc2VyaWFsaXplcjogU2VyaWFsaXplcjxWYWx1ZSwgRXh0cmFzPjtcbiAgc2VydmVyTWFwOiB7IFtob3N0cG9ydDogc3RyaW5nXTogU2VydmVyIH07XG4gIHNlcnZlcktleXM6IHN0cmluZ1tdO1xuXG4gIC8vIENsaWVudCBpbml0aWFsaXplciB0YWtlcyBhIGxpc3Qgb2YgYFNlcnZlcmBzIGFuZCBhbiBgb3B0aW9uc2AgZGljdGlvbmFyeS5cbiAgLy8gU2VlIGBDbGllbnQuY3JlYXRlYCBmb3IgZGV0YWlscy5cbiAgY29uc3RydWN0b3Ioc2VydmVyczogU2VydmVyW10sIG9wdGlvbnM6IEdpdmVuQ2xpZW50T3B0aW9uczxWYWx1ZSwgRXh0cmFzPikge1xuICAgIHRoaXMuc2VydmVycyA9IHNlcnZlcnM7XG4gICAgdGhpcy5zZXEgPSAwO1xuICAgIHRoaXMub3B0aW9ucyA9IG1lcmdlKG9wdGlvbnMgfHwge30sIHtcbiAgICAgIHJldHJpZXM6IDIsXG4gICAgICByZXRyeV9kZWxheTogMC4yLFxuICAgICAgZXhwaXJlczogMCxcbiAgICAgIGxvZ2dlcjogY29uc29sZSxcbiAgICAgIGtleVRvU2VydmVySGFzaEZ1bmN0aW9uOiBkZWZhdWx0S2V5VG9TZXJ2ZXJIYXNoRnVuY3Rpb24sXG4gICAgfSk7XG5cbiAgICB0aGlzLnNlcmlhbGl6ZXIgPSB0aGlzLm9wdGlvbnMuc2VyaWFsaXplciB8fCAobm9vcFNlcmlhbGl6ZXIgYXMgYW55KTtcblxuICAgIC8vIFN0b3JlIGEgbWFwcGluZyBmcm9tIGhvc3Rwb3J0IC0+IHNlcnZlciBzbyB3ZSBjYW4gcXVpY2tseSBnZXQgYSBzZXJ2ZXIgb2JqZWN0IGZyb20gdGhlIHNlcnZlcktleSByZXR1cm5lZCBieSB0aGUgaGFzaGluZyBmdW5jdGlvblxuICAgIGNvbnN0IHNlcnZlck1hcDogeyBbaG9zdHBvcnQ6IHN0cmluZ106IFNlcnZlciB9ID0ge307XG4gICAgdGhpcy5zZXJ2ZXJzLmZvckVhY2goZnVuY3Rpb24gKHNlcnZlcikge1xuICAgICAgc2VydmVyTWFwW3NlcnZlci5ob3N0cG9ydFN0cmluZygpXSA9IHNlcnZlcjtcbiAgICB9KTtcbiAgICB0aGlzLnNlcnZlck1hcCA9IHNlcnZlck1hcDtcblxuICAgIC8vIHN0b3JlIGEgbGlzdCBvZiBhbGwgb3VyIHNlcnZlcktleXMgc28gd2UgZG9uJ3QgbmVlZCB0byBjb25zdGFudGx5IHJlYWxsb2NhdGUgdGhpcyBhcnJheVxuICAgIHRoaXMuc2VydmVyS2V5cyA9IE9iamVjdC5rZXlzKHRoaXMuc2VydmVyTWFwKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgbmV3IGNsaWVudCBnaXZlbiBhbiBvcHRpb25hbCBjb25maWcgc3RyaW5nIGFuZCBvcHRpb25hbCBoYXNoIG9mXG4gICAqIG9wdGlvbnMuIFRoZSBjb25maWcgc3RyaW5nIHNob3VsZCBiZSBvZiB0aGUgZm9ybTpcbiAgICpcbiAgICogICAgIFwiW3VzZXI6cGFzc0Bdc2VydmVyMVs6MTEyMTFdLFt1c2VyOnBhc3NAXXNlcnZlcjJbOjExMjExXSwuLi5cIlxuICAgKlxuICAgKiBJZiB0aGUgYXJndW1lbnQgaXMgbm90IGdpdmVuLCBmYWxsYmFjayBvbiB0aGUgYE1FTUNBQ0hJRVJfU0VSVkVSU2AgZW52aXJvbm1lbnRcbiAgICogdmFyaWFibGUsIGBNRU1DQUNIRV9TRVJWRVJTYCBlbnZpcm9ubWVudCB2YXJpYWJsZSBvciBgXCJsb2NhbGhvc3Q6MTEyMTFcImAuXG4gICAqXG4gICAqIFRoZSBvcHRpb25zIGhhc2ggbWF5IGNvbnRhaW4gdGhlIG9wdGlvbnM6XG4gICAqXG4gICAqICogYHJldHJpZXNgIC0gdGhlIG51bWJlciBvZiB0aW1lcyB0byByZXRyeSBhbiBvcGVyYXRpb24gaW4gbGlldSBvZiBmYWlsdXJlc1xuICAgKiAoZGVmYXVsdCAyKVxuICAgKiAqIGBleHBpcmVzYCAtIHRoZSBkZWZhdWx0IGV4cGlyYXRpb24gaW4gc2Vjb25kcyB0byB1c2UgKGRlZmF1bHQgMCAtIG5ldmVyXG4gICAqIGV4cGlyZSkuIElmIGBleHBpcmVzYCBpcyBncmVhdGVyIHRoYW4gMzAgZGF5cyAoNjAgeCA2MCB4IDI0IHggMzApLCBpdCBpc1xuICAgKiB0cmVhdGVkIGFzIGEgVU5JWCB0aW1lIChudW1iZXIgb2Ygc2Vjb25kcyBzaW5jZSBKYW51YXJ5IDEsIDE5NzApLlxuICAgKiAqIGBsb2dnZXJgIC0gYSBsb2dnZXIgb2JqZWN0IHRoYXQgcmVzcG9uZHMgdG8gYGxvZyhzdHJpbmcpYCBtZXRob2QgY2FsbHMuXG4gICAqXG4gICAqICAgfn5+flxuICAgKiAgICAgbG9nKG1zZzFbLCBtc2cyWywgbXNnM1suLi5dXV0pXG4gICAqICAgfn5+flxuICAgKlxuICAgKiAgIERlZmF1bHRzIHRvIGBjb25zb2xlYC5cbiAgICogKiBgc2VyaWFsaXplcmAgLSB0aGUgb2JqZWN0IHdoaWNoIHdpbGwgKGRlKXNlcmlhbGl6ZSB0aGUgZGF0YS4gSXQgbmVlZHNcbiAgICogICB0d28gcHVibGljIG1ldGhvZHM6IHNlcmlhbGl6ZSBhbmQgZGVzZXJpYWxpemUuIEl0IGRlZmF1bHRzIHRvIHRoZVxuICAgKiAgIG5vb3BTZXJpYWxpemVyOlxuICAgKlxuICAgKiAgIH5+fn5cbiAgICogICBjb25zdCBub29wU2VyaWFsaXplciA9IHtcbiAgICogICAgIHNlcmlhbGl6ZTogZnVuY3Rpb24gKG9wY29kZSwgdmFsdWUsIGV4dHJhcykge1xuICAgKiAgICAgICByZXR1cm4geyB2YWx1ZTogdmFsdWUsIGV4dHJhczogZXh0cmFzIH07XG4gICAqICAgICB9LFxuICAgKiAgICAgZGVzZXJpYWxpemU6IGZ1bmN0aW9uIChvcGNvZGUsIHZhbHVlLCBleHRyYXMpIHtcbiAgICogICAgICAgcmV0dXJuIHsgdmFsdWU6IHZhbHVlLCBleHRyYXM6IGV4dHJhcyB9O1xuICAgKiAgICAgfVxuICAgKiAgIH07XG4gICAqICAgfn5+flxuICAgKlxuICAgKiBPciBvcHRpb25zIGZvciB0aGUgc2VydmVycyBpbmNsdWRpbmc6XG4gICAqICogYHVzZXJuYW1lYCBhbmQgYHBhc3N3b3JkYCBmb3IgZmFsbGJhY2sgU0FTTCBhdXRoZW50aWNhdGlvbiBjcmVkZW50aWFscy5cbiAgICogKiBgdGltZW91dGAgaW4gc2Vjb25kcyB0byBkZXRlcm1pbmUgZmFpbHVyZSBmb3Igb3BlcmF0aW9ucy4gRGVmYXVsdCBpcyAwLjVcbiAgICogICAgICAgICAgICAgc2Vjb25kcy5cbiAgICogKiAnY29ubnRpbWVvdXQnIGluIHNlY29uZHMgdG8gY29ubmVjdGlvbiBmYWlsdXJlLiBEZWZhdWx0IGlzIHR3aWNlIHRoZSB2YWx1ZVxuICAgKiAgICAgICAgICAgICAgICAgb2YgYHRpbWVvdXRgLlxuICAgKiAqIGBrZWVwQWxpdmVgIHdoZXRoZXIgdG8gZW5hYmxlIGtlZXAtYWxpdmUgZnVuY3Rpb25hbGl0eS4gRGVmYXVsdHMgdG8gZmFsc2UuXG4gICAqICogYGtlZXBBbGl2ZURlbGF5YCBpbiBzZWNvbmRzIHRvIHRoZSBpbml0aWFsIGRlbGF5IGJlZm9yZSB0aGUgZmlyc3Qga2VlcGFsaXZlXG4gICAqICAgICAgICAgICAgICAgICAgICBwcm9iZSBpcyBzZW50IG9uIGFuIGlkbGUgc29ja2V0LiBEZWZhdWx0cyBpcyAzMCBzZWNvbmRzLlxuICAgKiAqIGBrZXlUb1NlcnZlckhhc2hGdW5jdGlvbmAgYSBmdW5jdGlvbiB0byBtYXAga2V5cyB0byBzZXJ2ZXJzLCB3aXRoIHRoZSBzaWduYXR1cmVcbiAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgKHNlcnZlcktleXM6IHN0cmluZ1tdLCBrZXk6IHN0cmluZyk6IHN0cmluZ1xuICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICBOT1RFOiBpZiB5b3UgbmVlZCB0byBkbyBzb21lIGV4cGVuc2l2ZSBpbml0aWFsaXphdGlvbiwgKnBsZWFzZSogZG8gaXQgbGF6aWx5IHRoZSBmaXJzdCB0aW1lIHlvdSB0aGlzIGZ1bmN0aW9uIGlzIGNhbGxlZCB3aXRoIGFuIGFycmF5IG9mIHNlcnZlcktleXMsIG5vdCBvbiBldmVyeSBjYWxsXG4gICAqL1xuICBzdGF0aWMgY3JlYXRlPFZhbHVlLCBFeHRyYXM+KFxuICAgIHNlcnZlcnNTdHI6IHN0cmluZyB8IHVuZGVmaW5lZCxcbiAgICBvcHRpb25zOiBJZkJ1ZmZlcjxcbiAgICAgIFZhbHVlLFxuICAgICAgRXh0cmFzLFxuICAgICAgdW5kZWZpbmVkIHwgKFBhcnRpYWw8U2VydmVyT3B0aW9ucz4gJiBHaXZlbkNsaWVudE9wdGlvbnM8VmFsdWUsIEV4dHJhcz4pLFxuICAgICAgUGFydGlhbDxTZXJ2ZXJPcHRpb25zPiAmIEdpdmVuQ2xpZW50T3B0aW9uczxWYWx1ZSwgRXh0cmFzPlxuICAgID5cbiAgKTogQ2xpZW50PFZhbHVlLCBFeHRyYXM+IHtcbiAgICBzZXJ2ZXJzU3RyID1cbiAgICAgIHNlcnZlcnNTdHIgfHxcbiAgICAgIHByb2Nlc3MuZW52Lk1FTUNBQ0hJRVJfU0VSVkVSUyB8fFxuICAgICAgcHJvY2Vzcy5lbnYuTUVNQ0FDSEVfU0VSVkVSUyB8fFxuICAgICAgXCJsb2NhbGhvc3Q6MTEyMTFcIjtcbiAgICBjb25zdCBzZXJ2ZXJVcmlzID0gc2VydmVyc1N0ci5zcGxpdChcIixcIik7XG4gICAgY29uc3Qgc2VydmVycyA9IHNlcnZlclVyaXMubWFwKGZ1bmN0aW9uICh1cmkpIHtcbiAgICAgIGNvbnN0IHVyaVBhcnRzID0gdXJpLnNwbGl0KFwiQFwiKTtcbiAgICAgIGNvbnN0IGhvc3RQb3J0ID0gdXJpUGFydHNbdXJpUGFydHMubGVuZ3RoIC0gMV0uc3BsaXQoXCI6XCIpO1xuICAgICAgY29uc3QgdXNlclBhc3MgPSAodXJpUGFydHNbdXJpUGFydHMubGVuZ3RoIC0gMl0gfHwgXCJcIikuc3BsaXQoXCI6XCIpO1xuICAgICAgcmV0dXJuIG5ldyBTZXJ2ZXIoXG4gICAgICAgIGhvc3RQb3J0WzBdLFxuICAgICAgICBwYXJzZUludChob3N0UG9ydFsxXSB8fCBcIjExMjExXCIsIDEwKSxcbiAgICAgICAgdXNlclBhc3NbMF0sXG4gICAgICAgIHVzZXJQYXNzWzFdLFxuICAgICAgICBvcHRpb25zXG4gICAgICApO1xuICAgIH0pO1xuICAgIHJldHVybiBuZXcgQ2xpZW50KHNlcnZlcnMsIG9wdGlvbnMgYXMgYW55KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHaXZlbiBhIHNlcnZlcktleSBmcm9tbG9va3VwS2V5VG9TZXJ2ZXJLZXksIHJldHVybiB0aGUgY29ycmVzcG9uZGluZyBTZXJ2ZXIgaW5zdGFuY2VcbiAgICpcbiAgICogQHBhcmFtICB7c3RyaW5nfSBzZXJ2ZXJLZXlcbiAgICogQHJldHVybnMge1NlcnZlcn1cbiAgICovXG4gIHNlcnZlcktleVRvU2VydmVyKHNlcnZlcktleTogc3RyaW5nKTogU2VydmVyIHtcbiAgICByZXR1cm4gdGhpcy5zZXJ2ZXJNYXBbc2VydmVyS2V5XTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHaXZlbiBhIGtleSB0byBsb29rIHVwIGluIG1lbWNhY2hlLCByZXR1cm4gYSBzZXJ2ZXJLZXkgKGJhc2VkIG9uIHNvbWVcbiAgICogaGFzaGluZyBmdW5jdGlvbikgd2hpY2ggY2FuIGJlIHVzZWQgdG8gaW5kZXggdGhpcy5zZXJ2ZXJNYXBcbiAgICovXG4gIGxvb2t1cEtleVRvU2VydmVyS2V5KGtleTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5vcHRpb25zLmtleVRvU2VydmVySGFzaEZ1bmN0aW9uKHRoaXMuc2VydmVyS2V5cywga2V5KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXRyaWV2ZXMgdGhlIHZhbHVlIGF0IHRoZSBnaXZlbiBrZXkgaW4gbWVtY2FjaGUuXG4gICAqL1xuICBhc3luYyBnZXQoa2V5OiBzdHJpbmcpOiBQcm9taXNlPEdldFJlc3VsdDxWYWx1ZSwgRXh0cmFzPiB8IG51bGw+IHtcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoY29uc3RhbnRzLk9QX0dFVCwga2V5LCBcIlwiLCBcIlwiLCB0aGlzLnNlcSk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIGNvbnN0IGRlc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5kZXNlcmlhbGl6ZShcbiAgICAgICAgICByZXNwb25zZS5oZWFkZXIub3Bjb2RlLFxuICAgICAgICAgIHJlc3BvbnNlLnZhbCxcbiAgICAgICAgICByZXNwb25zZS5leHRyYXNcbiAgICAgICAgKTtcbiAgICAgICAgcmV0dXJuIHsgLi4uZGVzZXJpYWxpemVkLCBjYXM6IHJlc3BvbnNlLmhlYWRlci5jYXMgfTtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuS0VZX05PVF9GT1VORDpcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiR0VUXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBCdWlsZCBhIHBpcGVsaW5lZCBnZXQgbXVsdGkgcmVxdWVzdCBieSBzZW5kaW5nIG9uZSBHRVRLUSBmb3IgZWFjaCBrZXkgKHF1aWV0LCBtZWFuaW5nIGl0IHdvbid0IHJlc3BvbmQgaWYgdGhlIHZhbHVlIGlzIG1pc3NpbmcpIGZvbGxvd2VkIGJ5IGEgbm8tb3AgdG8gZm9yY2UgYSByZXNwb25zZSAoYW5kIHRvIGdpdmUgdXMgYSBzZW50aW5lbCByZXNwb25zZSB0aGF0IHRoZSBwaXBlbGluZSBpcyBkb25lKVxuICAgKlxuICAgKiBjZiBodHRwczovL2dpdGh1Yi5jb20vY291Y2hiYXNlL21lbWNhY2hlZC9ibG9iL21hc3Rlci9kb2NzL0JpbmFyeVByb3RvY29sLm1kIzB4MGQtZ2V0a3EtZ2V0LXdpdGgta2V5LXF1aWV0bHlcbiAgICovXG4gIF9idWlsZEdldE11bHRpUmVxdWVzdChrZXlzOiBzdHJpbmdbXSwgc2VxOiBudW1iZXIpOiBCdWZmZXIge1xuICAgIC8vIHN0YXJ0IGF0IDI0IGZvciB0aGUgbm8tb3AgY29tbWFuZCBhdCB0aGUgZW5kXG4gICAgbGV0IHJlcXVlc3RTaXplID0gMjQ7XG4gICAgZm9yIChjb25zdCBrZXlJZHggaW4ga2V5cykge1xuICAgICAgcmVxdWVzdFNpemUgKz0gQnVmZmVyLmJ5dGVMZW5ndGgoa2V5c1trZXlJZHhdLCBcInV0ZjhcIikgKyAyNDtcbiAgICB9XG5cbiAgICBjb25zdCByZXF1ZXN0ID0gQnVmZmVyLmFsbG9jKHJlcXVlc3RTaXplKTtcblxuICAgIGxldCBieXRlc1dyaXR0ZW4gPSAwO1xuICAgIGZvciAoY29uc3Qga2V5SWR4IGluIGtleXMpIHtcbiAgICAgIGNvbnN0IGtleSA9IGtleXNba2V5SWR4XTtcbiAgICAgIGJ5dGVzV3JpdHRlbiArPSBjb3B5SW50b1JlcXVlc3RCdWZmZXIoXG4gICAgICAgIGNvbnN0YW50cy5PUF9HRVRLUSxcbiAgICAgICAga2V5LFxuICAgICAgICBcIlwiLFxuICAgICAgICBcIlwiLFxuICAgICAgICBzZXEsXG4gICAgICAgIHJlcXVlc3QsXG4gICAgICAgIGJ5dGVzV3JpdHRlblxuICAgICAgKTtcbiAgICB9XG5cbiAgICBieXRlc1dyaXR0ZW4gKz0gY29weUludG9SZXF1ZXN0QnVmZmVyKFxuICAgICAgY29uc3RhbnRzLk9QX05PX09QLFxuICAgICAgXCJcIixcbiAgICAgIFwiXCIsXG4gICAgICBcIlwiLFxuICAgICAgc2VxLFxuICAgICAgcmVxdWVzdCxcbiAgICAgIGJ5dGVzV3JpdHRlblxuICAgICk7XG5cbiAgICByZXR1cm4gcmVxdWVzdDtcbiAgfVxuXG4gIC8qKiBFeGVjdXRpbmcgYSBwaXBlbGluZWQgKG11bHRpKSBnZXQgYWdhaW5zdCBhIHNpbmdsZSBzZXJ2ZXIuIFRoaXMgaXMgYSBwcml2YXRlIGltcGxlbWVudGF0aW9uIGRldGFpbCBvZiBnZXRNdWx0aS4gKi9cbiAgYXN5bmMgX2dldE11bHRpVG9TZXJ2ZXI8S2V5cyBleHRlbmRzIHN0cmluZz4oXG4gICAgc2VydjogU2VydmVyLFxuICAgIGtleXM6IEtleXNbXVxuICApOiBQcm9taXNlPEdldE11bHRpUmVzdWx0PEtleXMsIFZhbHVlLCBFeHRyYXM+PiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGNvbnN0IHJlc3BvbnNlTWFwOiBHZXRNdWx0aVJlc3VsdDxzdHJpbmcsIFZhbHVlLCBFeHRyYXM+ID0ge307XG5cbiAgICAgIGNvbnN0IGhhbmRsZTogT25SZXNwb25zZUNhbGxiYWNrID0gKHJlc3BvbnNlKSA9PiB7XG4gICAgICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgICAgIC8vIFdoZW4gd2UgZ2V0IHRoZSBuby1vcCByZXNwb25zZSwgd2UgYXJlIGRvbmUgd2l0aCB0aGlzIG9uZSBnZXRNdWx0aSBpbiB0aGUgcGVyLWJhY2tlbmQgZmFuLW91dFxuICAgICAgICAgICAgaWYgKHJlc3BvbnNlLmhlYWRlci5vcGNvZGUgPT09IGNvbnN0YW50cy5PUF9OT19PUCkge1xuICAgICAgICAgICAgICAvLyBUaGlzIGVuc3VyZXMgdGhlIGhhbmRsZXIgd2lsbCBiZSBkZWxldGVkIGZyb20gdGhlIHJlc3BvbnNlQ2FsbGJhY2tzIG1hcCBpbiBzZXJ2ZXIuanNcbiAgICAgICAgICAgICAgLy8gVGhpcyBpc24ndCB0ZWNobmljYWxseSBuZWVkZWQgaGVyZSBiZWNhdXNlIHRoZSBsb2dpYyBpbiBzZXJ2ZXIuanMgYWxzbyBjaGVja3MgaWYgdG90YWxCb2R5TGVuZ3RoID09PSAwLCBidXQgb3VyIHVuaXR0ZXN0cyBhcmVuJ3QgZ3JlYXQgYWJvdXQgc2V0dGluZyB0aGF0IGZpZWxkLCBhbmQgYWxzbyB0aGlzIG1ha2VzIGl0IG1vcmUgZXhwbGljaXRcbiAgICAgICAgICAgICAgaGFuZGxlLnF1aWV0ID0gZmFsc2U7XG4gICAgICAgICAgICAgIHJlc29sdmUocmVzcG9uc2VNYXApO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChyZXNwb25zZS5oZWFkZXIub3Bjb2RlID09PSBjb25zdGFudHMuT1BfR0VUSyB8fCByZXNwb25zZS5oZWFkZXIub3Bjb2RlID09PSBjb25zdGFudHMuT1BfR0VUS1EpIHtcbiAgICAgICAgICAgICAgY29uc3QgZGVzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLmRlc2VyaWFsaXplKFxuICAgICAgICAgICAgICAgIHJlc3BvbnNlLmhlYWRlci5vcGNvZGUsXG4gICAgICAgICAgICAgICAgcmVzcG9uc2UudmFsLFxuICAgICAgICAgICAgICAgIHJlc3BvbnNlLmV4dHJhc1xuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICBjb25zdCBrZXkgPSByZXNwb25zZS5rZXkudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgaWYgKGtleS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVqZWN0KFxuICAgICAgICAgICAgICAgICAgbmV3IEVycm9yKFwiUmVjaWV2ZWQgZW1wdHkga2V5IGluIGdldE11bHRpOiBcIiArIEpTT04uc3RyaW5naWZ5KHJlc3BvbnNlKSlcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIHJlc3BvbnNlTWFwW2tleV0gPSB7IC4uLmRlc2VyaWFsaXplZCwgY2FzOiByZXNwb25zZS5oZWFkZXIuY2FzIH07XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICByZXR1cm4gcmVqZWN0KFxuICAgICAgICAgICAgICAgIG5ldyBFcnJvcihcIlJlY2lldmVkIHJlc3BvbnNlIGluIGdldE11bHRpIGZvciB1bmtub3duIG9wY29kZTogXCIgKyBKU09OLnN0cmluZ2lmeShyZXNwb25zZSkpXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgcmV0dXJuIHJlamVjdChcbiAgICAgICAgICAgICAgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIkdFVFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfTtcbiAgICAgIC8vIFRoaXMgcHJldmVudHMgdGhlIGhhbmRsZXIgZnJvbSBiZWluZyBkZWxldGVkXG4gICAgICAvLyBhZnRlciB0aGUgZmlyc3QgcmVzcG9uc2UuIExvZ2ljIGluIHNlcnZlci5qcy5cbiAgICAgIGhhbmRsZS5xdWlldCA9IHRydWU7XG5cbiAgICAgIGNvbnN0IHNlcSA9IHRoaXMuaW5jclNlcSgpO1xuICAgICAgY29uc3QgcmVxdWVzdCA9IHRoaXMuX2J1aWxkR2V0TXVsdGlSZXF1ZXN0KGtleXMsIHNlcSk7XG4gICAgICBzZXJ2Lm9uUmVzcG9uc2UodGhpcy5zZXEsIGhhbmRsZSk7XG4gICAgICBzZXJ2Lm9uRXJyb3IodGhpcy5zZXEsIHJlamVjdCk7XG4gICAgICBzZXJ2LndyaXRlKHJlcXVlc3QpO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHJpZXZzIHRoZSB2YWx1ZSBhdCB0aGUgZ2l2ZW4ga2V5cyBpbiBtZW1jYWNoZWQuIFJldHVybnMgYSBtYXAgZnJvbSB0aGVcbiAgICogcmVxdWVzdGVkIGtleXMgdG8gcmVzdWx0cywgb3IgbnVsbCBpZiB0aGUga2V5IHdhcyBub3QgZm91bmQuXG4gICAqL1xuICBhc3luYyBnZXRNdWx0aTxLZXlzIGV4dGVuZHMgc3RyaW5nPihcbiAgICBrZXlzOiBLZXlzW11cbiAgKTogUHJvbWlzZTxHZXRNdWx0aVJlc3VsdDxLZXlzLCBWYWx1ZSwgRXh0cmFzPj4ge1xuICAgIGNvbnN0IHNlcnZlcktleXRvTG9va3VwS2V5czoge1xuICAgICAgW3NlcnZlcktleTogc3RyaW5nXTogc3RyaW5nW107XG4gICAgfSA9IHt9O1xuICAgIGtleXMuZm9yRWFjaCgobG9va3VwS2V5KSA9PiB7XG4gICAgICBjb25zdCBzZXJ2ZXJLZXkgPSB0aGlzLmxvb2t1cEtleVRvU2VydmVyS2V5KGxvb2t1cEtleSk7XG4gICAgICBpZiAoIXNlcnZlcktleXRvTG9va3VwS2V5c1tzZXJ2ZXJLZXldKSB7XG4gICAgICAgIHNlcnZlcktleXRvTG9va3VwS2V5c1tzZXJ2ZXJLZXldID0gW107XG4gICAgICB9XG4gICAgICBzZXJ2ZXJLZXl0b0xvb2t1cEtleXNbc2VydmVyS2V5XS5wdXNoKGxvb2t1cEtleSk7XG4gICAgfSk7XG5cbiAgICBjb25zdCB1c2VkU2VydmVyS2V5cyA9IE9iamVjdC5rZXlzKHNlcnZlcktleXRvTG9va3VwS2V5cyk7XG4gICAgY29uc3QgcmVzdWx0cyA9IGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgdXNlZFNlcnZlcktleXMubWFwKChzZXJ2ZXJLZXkpID0+IHtcbiAgICAgICAgY29uc3Qgc2VydmVyID0gdGhpcy5zZXJ2ZXJLZXlUb1NlcnZlcihzZXJ2ZXJLZXkpO1xuICAgICAgICByZXR1cm4gdGhpcy5fZ2V0TXVsdGlUb1NlcnZlcihzZXJ2ZXIsIHNlcnZlcktleXRvTG9va3VwS2V5c1tzZXJ2ZXJLZXldKTtcbiAgICAgIH0pXG4gICAgKTtcblxuICAgIHJldHVybiBPYmplY3QuYXNzaWduKHt9LCAuLi5yZXN1bHRzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIGBrZXlgIHRvIGB2YWx1ZWAuXG4gICAqL1xuICBhc3luYyBzZXQoXG4gICAga2V5OiBzdHJpbmcsXG4gICAgdmFsdWU6IFZhbHVlLFxuICAgIG9wdGlvbnM/OiB7IGV4cGlyZXM/OiBudW1iZXI7IGNhcz86IENBU1Rva2VuIH1cbiAgKTogUHJvbWlzZTxib29sZWFuIHwgbnVsbD4ge1xuICAgIGNvbnN0IGV4cGlyZXMgPSBvcHRpb25zPy5leHBpcmVzO1xuICAgIGNvbnN0IGNhcyA9IG9wdGlvbnM/LmNhcztcblxuICAgIC8vIFRPRE86IHN1cHBvcnQgZmxhZ3NcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBleHBpcmF0aW9uID0gbWFrZUV4cGlyYXRpb24oZXhwaXJlcyB8fCB0aGlzLm9wdGlvbnMuZXhwaXJlcyk7XG4gICAgY29uc3QgZXh0cmFzID0gQnVmZmVyLmNvbmNhdChbQnVmZmVyLmZyb20oXCIwMDAwMDAwMFwiLCBcImhleFwiKSwgZXhwaXJhdGlvbl0pO1xuICAgIGNvbnN0IHNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuc2VyaWFsaXplKFxuICAgICAgY29uc3RhbnRzLk9QX1NFVCxcbiAgICAgIHZhbHVlLFxuICAgICAgZXh0cmFzXG4gICAgKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gVXRpbHMuZW5jb2RlUmVxdWVzdCh7XG4gICAgICBoZWFkZXI6IHtcbiAgICAgICAgb3Bjb2RlOiBjb25zdGFudHMuT1BfU0VULFxuICAgICAgICBvcGFxdWU6IHRoaXMuc2VxLFxuICAgICAgICBjYXMsXG4gICAgICB9LFxuICAgICAga2V5LFxuICAgICAgdmFsdWU6IHNlcmlhbGl6ZWQudmFsdWUsXG4gICAgICBleHRyYXM6IHNlcmlhbGl6ZWQuZXh0cmFzLFxuICAgIH0pO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuS0VZX0VYSVNUUzpcbiAgICAgICAgaWYgKGNhcykge1xuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiU0VUXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgICAgICB9XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiU0VUXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBBRERcbiAgICpcbiAgICogQWRkcyB0aGUgZ2l2ZW4gX2tleV8gYW5kIF92YWx1ZV8gdG8gbWVtY2FjaGUuIFRoZSBvcGVyYXRpb24gb25seSBzdWNjZWVkc1xuICAgKiBpZiB0aGUga2V5IGlzIG5vdCBhbHJlYWR5IHNldC5cbiAgICpcbiAgICogVGhlIG9wdGlvbnMgZGljdGlvbmFyeSB0YWtlczpcbiAgICogKiBfZXhwaXJlc186IG92ZXJyaWRlcyB0aGUgZGVmYXVsdCBleHBpcmF0aW9uIChzZWUgYENsaWVudC5jcmVhdGVgKSBmb3IgdGhpc1xuICAgKiAgICAgICAgICAgICAgcGFydGljdWxhciBrZXktdmFsdWUgcGFpci5cbiAgICovXG4gIGFzeW5jIGFkZChcbiAgICBrZXk6IHN0cmluZyxcbiAgICB2YWx1ZTogVmFsdWUsXG4gICAgb3B0aW9ucz86IHsgZXhwaXJlcz86IG51bWJlciB9XG4gICk6IFByb21pc2U8Ym9vbGVhbiB8IG51bGw+IHtcbiAgICAvLyBUT0RPOiBzdXBwb3J0IGZsYWdzLCBzdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBleHBpcmF0aW9uID0gbWFrZUV4cGlyYXRpb24ob3B0aW9ucz8uZXhwaXJlcyB8fCB0aGlzLm9wdGlvbnMuZXhwaXJlcyk7XG4gICAgY29uc3QgZXh0cmFzID0gQnVmZmVyLmNvbmNhdChbQnVmZmVyLmZyb20oXCIwMDAwMDAwMFwiLCBcImhleFwiKSwgZXhwaXJhdGlvbl0pO1xuXG4gICAgY29uc3Qgb3Bjb2RlID0gY29uc3RhbnRzLk9QX0FERDtcbiAgICBjb25zdCBzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLnNlcmlhbGl6ZShvcGNvZGUsIHZhbHVlLCBleHRyYXMpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgIG9wY29kZSxcbiAgICAgIGtleSxcbiAgICAgIHNlcmlhbGl6ZWQuZXh0cmFzLFxuICAgICAgc2VyaWFsaXplZC52YWx1ZSxcbiAgICAgIHRoaXMuc2VxXG4gICAgKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9FWElTVFM6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiQUREXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXBsYWNlcyB0aGUgZ2l2ZW4gX2tleV8gYW5kIF92YWx1ZV8gdG8gbWVtY2FjaGUuIFRoZSBvcGVyYXRpb24gb25seSBzdWNjZWVkc1xuICAgKiBpZiB0aGUga2V5IGlzIGFscmVhZHkgcHJlc2VudC5cbiAgICovXG4gIGFzeW5jIHJlcGxhY2UoXG4gICAga2V5OiBzdHJpbmcsXG4gICAgdmFsdWU6IFZhbHVlLFxuICAgIG9wdGlvbnM/OiB7IGV4cGlyZXM/OiBudW1iZXIgfVxuICApOiBQcm9taXNlPGJvb2xlYW4gfCBudWxsPiB7XG4gICAgLy8gVE9ETzogc3VwcG9ydCBmbGFncywgc3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgZXhwaXJhdGlvbiA9IG1ha2VFeHBpcmF0aW9uKG9wdGlvbnM/LmV4cGlyZXMgfHwgdGhpcy5vcHRpb25zLmV4cGlyZXMpO1xuICAgIGNvbnN0IGV4dHJhcyA9IEJ1ZmZlci5jb25jYXQoW0J1ZmZlci5mcm9tKFwiMDAwMDAwMDBcIiwgXCJoZXhcIiksIGV4cGlyYXRpb25dKTtcblxuICAgIGNvbnN0IG9wY29kZTogY29uc3RhbnRzLk9QID0gY29uc3RhbnRzLk9QX1JFUExBQ0U7XG4gICAgY29uc3Qgc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5zZXJpYWxpemUob3Bjb2RlLCB2YWx1ZSwgZXh0cmFzKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICBvcGNvZGUsXG4gICAgICBrZXksXG4gICAgICBzZXJpYWxpemVkLmV4dHJhcyxcbiAgICAgIHNlcmlhbGl6ZWQudmFsdWUsXG4gICAgICB0aGlzLnNlcVxuICAgICk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfTk9UX0ZPVU5EOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiUkVQTEFDRVwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRGVsZXRlcyB0aGUgZ2l2ZW4gX2tleV8gZnJvbSBtZW1jYWNoZS4gVGhlIG9wZXJhdGlvbiBvbmx5IHN1Y2NlZWRzXG4gICAqIGlmIHRoZSBrZXkgaXMgYWxyZWFkeSBwcmVzZW50LlxuICAgKi9cbiAgYXN5bmMgZGVsZXRlKGtleTogc3RyaW5nKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgLy8gVE9ETzogU3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKDQsIGtleSwgXCJcIiwgXCJcIiwgdGhpcy5zZXEpO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuXG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfTk9UX0ZPVU5EOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiREVMRVRFXCIsIHJlc3BvbnNlPy5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogSW5jcmVtZW50cyB0aGUgZ2l2ZW4gX2tleV8gaW4gbWVtY2FjaGUuXG4gICAqL1xuICBhc3luYyBpbmNyZW1lbnQoXG4gICAga2V5OiBzdHJpbmcsXG4gICAgYW1vdW50OiBudW1iZXIsXG4gICAgb3B0aW9ucz86IHsgaW5pdGlhbD86IG51bWJlcjsgZXhwaXJlcz86IG51bWJlciB9XG4gICk6IFByb21pc2U8eyB2YWx1ZTogbnVtYmVyIHwgbnVsbDsgc3VjY2VzczogYm9vbGVhbiB8IG51bGwgfT4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IGluaXRpYWwgPSBvcHRpb25zPy5pbml0aWFsIHx8IDA7XG4gICAgY29uc3QgZXhwaXJlcyA9IG9wdGlvbnM/LmV4cGlyZXMgfHwgdGhpcy5vcHRpb25zLmV4cGlyZXM7XG4gICAgY29uc3QgZXh0cmFzID0gbWFrZUFtb3VudEluaXRpYWxBbmRFeHBpcmF0aW9uKGFtb3VudCwgaW5pdGlhbCwgZXhwaXJlcyk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKFxuICAgICAgY29uc3RhbnRzLk9QX0lOQ1JFTUVOVCxcbiAgICAgIGtleSxcbiAgICAgIGV4dHJhcyxcbiAgICAgIFwiXCIsXG4gICAgICB0aGlzLnNlcVxuICAgICk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIGNvbnN0IGJ1ZkludCA9XG4gICAgICAgICAgKHJlc3BvbnNlLnZhbC5yZWFkVUludDMyQkUoMCkgPDwgOCkgKyByZXNwb25zZS52YWwucmVhZFVJbnQzMkJFKDQpO1xuICAgICAgICByZXR1cm4geyB2YWx1ZTogYnVmSW50LCBzdWNjZXNzOiB0cnVlIH07XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiSU5DUkVNRU5UXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBEZWNyZW1lbnRzIHRoZSBnaXZlbiBga2V5YCBpbiBtZW1jYWNoZS5cbiAgICovXG4gIGFzeW5jIGRlY3JlbWVudChcbiAgICBrZXk6IHN0cmluZyxcbiAgICBhbW91bnQ6IG51bWJlcixcbiAgICBvcHRpb25zOiB7IGluaXRpYWw/OiBudW1iZXI7IGV4cGlyZXM/OiBudW1iZXIgfVxuICApOiBQcm9taXNlPHsgdmFsdWU6IG51bWJlciB8IG51bGw7IHN1Y2Nlc3M6IGJvb2xlYW4gfCBudWxsIH0+IHtcbiAgICAvLyBUT0RPOiBzdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBpbml0aWFsID0gb3B0aW9ucy5pbml0aWFsIHx8IDA7XG4gICAgY29uc3QgZXhwaXJlcyA9IG9wdGlvbnMuZXhwaXJlcyB8fCB0aGlzLm9wdGlvbnMuZXhwaXJlcztcbiAgICBjb25zdCBleHRyYXMgPSBtYWtlQW1vdW50SW5pdGlhbEFuZEV4cGlyYXRpb24oYW1vdW50LCBpbml0aWFsLCBleHBpcmVzKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICBjb25zdGFudHMuT1BfREVDUkVNRU5ULFxuICAgICAga2V5LFxuICAgICAgZXh0cmFzLFxuICAgICAgXCJcIixcbiAgICAgIHRoaXMuc2VxXG4gICAgKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgY29uc3QgYnVmSW50ID1cbiAgICAgICAgICAocmVzcG9uc2UudmFsLnJlYWRVSW50MzJCRSgwKSA8PCA4KSArIHJlc3BvbnNlLnZhbC5yZWFkVUludDMyQkUoNCk7XG4gICAgICAgIHJldHVybiB7IHZhbHVlOiBidWZJbnQsIHN1Y2Nlc3M6IHRydWUgfTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJERUNSRU1FTlRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEFwcGVuZCB0aGUgZ2l2ZW4gX3ZhbHVlXyB0byB0aGUgdmFsdWUgYXNzb2NpYXRlZCB3aXRoIHRoZSBnaXZlbiBfa2V5XyBpblxuICAgKiBtZW1jYWNoZS4gVGhlIG9wZXJhdGlvbiBvbmx5IHN1Y2NlZWRzIGlmIHRoZSBrZXkgaXMgYWxyZWFkeSBwcmVzZW50LlxuICAgKi9cbiAgYXN5bmMgYXBwZW5kKGtleTogc3RyaW5nLCB2YWx1ZTogVmFsdWUpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAvLyBUT0RPOiBzdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBvcGNvZGU6IGNvbnN0YW50cy5PUCA9IGNvbnN0YW50cy5PUF9BUFBFTkQ7XG4gICAgY29uc3Qgc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5zZXJpYWxpemUob3Bjb2RlLCB2YWx1ZSwgXCJcIik7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKFxuICAgICAgb3Bjb2RlLFxuICAgICAga2V5LFxuICAgICAgc2VyaWFsaXplZC5leHRyYXMsXG4gICAgICBzZXJpYWxpemVkLnZhbHVlLFxuICAgICAgdGhpcy5zZXFcbiAgICApO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuS0VZX05PVF9GT1VORDpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIkFQUEVORFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUHJlcGVuZCB0aGUgZ2l2ZW4gX3ZhbHVlXyB0byB0aGUgdmFsdWUgYXNzb2NpYXRlZCB3aXRoIHRoZSBnaXZlbiBfa2V5XyBpblxuICAgKiBtZW1jYWNoZS4gVGhlIG9wZXJhdGlvbiBvbmx5IHN1Y2NlZWRzIGlmIHRoZSBrZXkgaXMgYWxyZWFkeSBwcmVzZW50LlxuICAgKi9cbiAgYXN5bmMgcHJlcGVuZChrZXk6IHN0cmluZywgdmFsdWU6IFZhbHVlKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgLy8gVE9ETzogc3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3Qgb3Bjb2RlOiBjb25zdGFudHMuT1AgPSBjb25zdGFudHMuT1BfUFJFUEVORDtcbiAgICBjb25zdCBzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLnNlcmlhbGl6ZShvcGNvZGUsIHZhbHVlLCBcIlwiKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICBvcGNvZGUsXG4gICAgICBrZXksXG4gICAgICBzZXJpYWxpemVkLmV4dHJhcyxcbiAgICAgIHNlcmlhbGl6ZWQudmFsdWUsXG4gICAgICB0aGlzLnNlcVxuICAgICk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfTk9UX0ZPVU5EOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiUFJFUEVORFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVG91Y2ggc2V0cyBhbiBleHBpcmF0aW9uIHZhbHVlLCBnaXZlbiBieSBfZXhwaXJlc18sIG9uIHRoZSBnaXZlbiBfa2V5XyBpblxuICAgKiBtZW1jYWNoZS4gVGhlIG9wZXJhdGlvbiBvbmx5IHN1Y2NlZWRzIGlmIHRoZSBrZXkgaXMgYWxyZWFkeSBwcmVzZW50LlxuICAgKi9cbiAgYXN5bmMgdG91Y2goa2V5OiBzdHJpbmcsIGV4cGlyZXM6IG51bWJlcik6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IGV4dHJhcyA9IG1ha2VFeHBpcmF0aW9uKGV4cGlyZXMgfHwgdGhpcy5vcHRpb25zLmV4cGlyZXMpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcigweDFjLCBrZXksIGV4dHJhcywgXCJcIiwgdGhpcy5zZXEpO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuS0VZX05PVF9GT1VORDpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIlRPVUNIXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBGTFVTSFxuICAgKlxuICAgKiBGbHVzaGVzIHRoZSBjYWNoZSBvbiBlYWNoIGNvbm5lY3RlZCBzZXJ2ZXIuIFRoZSBjYWxsYmFjayBzaWduYXR1cmUgaXM6XG4gICAqXG4gICAqICAgICBjYWxsYmFjayhsYXN0RXJyLCByZXN1bHRzKVxuICAgKlxuICAgKiB3aGVyZSBfbGFzdEVycl8gaXMgdGhlIGxhc3QgZXJyb3IgZW5jb3VudGVyZWQgKG9yIG51bGwsIGluIHRoZSBjb21tb24gY2FzZVxuICAgKiBvZiBubyBlcnJvcnMpLiBfcmVzdWx0c18gaXMgYSBkaWN0aW9uYXJ5IG1hcHBpbmcgYFwiaG9zdG5hbWU6cG9ydFwiYCB0byBlaXRoZXJcbiAgICogYHRydWVgIChpZiB0aGUgb3BlcmF0aW9uIHdhcyBzdWNjZXNzZnVsKSwgb3IgYW4gZXJyb3IuXG4gICAqIEBwYXJhbSBjYWxsYmFja1xuICAgKi9cbiAgZmx1c2goKTogUHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBib29sZWFuIHwgRXJyb3I+PjtcbiAgZmx1c2goXG4gICAgY2FsbGJhY2s6IChcbiAgICAgIGVycjogRXJyb3IgfCBudWxsLFxuICAgICAgcmVzdWx0czogUmVjb3JkPHN0cmluZywgYm9vbGVhbiB8IEVycm9yPlxuICAgICkgPT4gdm9pZFxuICApOiB2b2lkO1xuICBmbHVzaChcbiAgICBjYWxsYmFjaz86IChcbiAgICAgIGVycjogRXJyb3IgfCBudWxsLFxuICAgICAgcmVzdWx0czogUmVjb3JkPHN0cmluZywgYm9vbGVhbiB8IEVycm9yPlxuICAgICkgPT4gdm9pZFxuICApIHtcbiAgICBpZiAoY2FsbGJhY2sgPT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuIHByb21pc2lmeSgoY2FsbGJhY2spID0+IHtcbiAgICAgICAgdGhpcy5mbHVzaChmdW5jdGlvbiAoZXJyLCByZXN1bHRzKSB7XG4gICAgICAgICAgY2FsbGJhY2soZXJyLCByZXN1bHRzKTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9XG4gICAgLy8gVE9ETzogc3VwcG9ydCBleHBpcmF0aW9uXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKDB4MDgsIFwiXCIsIFwiXCIsIFwiXCIsIHRoaXMuc2VxKTtcbiAgICBsZXQgY291bnQgPSB0aGlzLnNlcnZlcnMubGVuZ3RoO1xuICAgIGNvbnN0IHJlc3VsdDogUmVjb3JkPHN0cmluZywgYm9vbGVhbiB8IEVycm9yPiA9IHt9O1xuICAgIGxldCBsYXN0RXJyOiBFcnJvciB8IG51bGwgPSBudWxsO1xuXG4gICAgY29uc3QgaGFuZGxlRmx1c2ggPSBmdW5jdGlvbiAoc2VxOiBudW1iZXIsIHNlcnY6IFNlcnZlcikge1xuICAgICAgc2Vydi5vblJlc3BvbnNlKHNlcSwgZnVuY3Rpb24gKC8qIHJlc3BvbnNlICovKSB7XG4gICAgICAgIGNvdW50IC09IDE7XG4gICAgICAgIHJlc3VsdFtzZXJ2Lmhvc3Rwb3J0U3RyaW5nKCldID0gdHJ1ZTtcbiAgICAgICAgaWYgKGNhbGxiYWNrICYmIGNvdW50ID09PSAwKSB7XG4gICAgICAgICAgY2FsbGJhY2sobGFzdEVyciwgcmVzdWx0KTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICBzZXJ2Lm9uRXJyb3Ioc2VxLCBmdW5jdGlvbiAoZXJyKSB7XG4gICAgICAgIGNvdW50IC09IDE7XG4gICAgICAgIGxhc3RFcnIgPSBlcnI7XG4gICAgICAgIHJlc3VsdFtzZXJ2Lmhvc3Rwb3J0U3RyaW5nKCldID0gZXJyO1xuICAgICAgICBpZiAoY2FsbGJhY2sgJiYgY291bnQgPT09IDApIHtcbiAgICAgICAgICBjYWxsYmFjayhsYXN0RXJyLCByZXN1bHQpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHNlcnYud3JpdGUocmVxdWVzdCk7XG4gICAgfTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5zZXJ2ZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBoYW5kbGVGbHVzaCh0aGlzLnNlcSwgdGhpcy5zZXJ2ZXJzW2ldKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU1RBVFNfV0lUSF9LRVlcbiAgICpcbiAgICogU2VuZHMgYSBtZW1jYWNoZSBzdGF0cyBjb21tYW5kIHdpdGggYSBrZXkgdG8gZWFjaCBjb25uZWN0ZWQgc2VydmVyLiBUaGVcbiAgICogY2FsbGJhY2sgaXMgaW52b2tlZCAqKk9OQ0UgUEVSIFNFUlZFUioqIGFuZCBoYXMgdGhlIHNpZ25hdHVyZTpcbiAgICpcbiAgICogICAgIGNhbGxiYWNrKGVyciwgc2VydmVyLCBzdGF0cylcbiAgICpcbiAgICogX3NlcnZlcl8gaXMgdGhlIGBcImhvc3RuYW1lOnBvcnRcImAgb2YgdGhlIHNlcnZlciwgYW5kIF9zdGF0c18gaXMgYSBkaWN0aW9uYXJ5XG4gICAqIG1hcHBpbmcgdGhlIHN0YXQgbmFtZSB0byB0aGUgdmFsdWUgb2YgdGhlIHN0YXRpc3RpYyBhcyBhIHN0cmluZy5cbiAgICogQHBhcmFtIGtleVxuICAgKiBAcGFyYW0gY2FsbGJhY2tcbiAgICovXG4gIHN0YXRzV2l0aEtleShcbiAgICBrZXk6IHN0cmluZyxcbiAgICBjYWxsYmFjaz86IChcbiAgICAgIGVycjogRXJyb3IgfCBudWxsLFxuICAgICAgc2VydmVyOiBzdHJpbmcsXG4gICAgICBzdGF0czogUmVjb3JkPHN0cmluZywgc3RyaW5nPiB8IG51bGxcbiAgICApID0+IHZvaWRcbiAgKTogdm9pZCB7XG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKDB4MTAsIGtleSwgXCJcIiwgXCJcIiwgdGhpcy5zZXEpO1xuXG4gICAgY29uc3QgaGFuZGxlU3RhdHMgPSAoc2VxOiBudW1iZXIsIHNlcnY6IFNlcnZlcikgPT4ge1xuICAgICAgY29uc3QgcmVzdWx0OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge307XG4gICAgICBjb25zdCBoYW5kbGU6IE9uUmVzcG9uc2VDYWxsYmFjayA9IChyZXNwb25zZSkgPT4ge1xuICAgICAgICAvLyBlbmQgb2Ygc3RhdCByZXNwb25zZXNcbiAgICAgICAgaWYgKHJlc3BvbnNlLmhlYWRlci50b3RhbEJvZHlMZW5ndGggPT09IDApIHtcbiAgICAgICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKG51bGwsIHNlcnYuaG9zdHBvcnRTdHJpbmcoKSwgcmVzdWx0KTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIC8vIHByb2Nlc3Mgc2luZ2xlIHN0YXQgbGluZSByZXNwb25zZVxuICAgICAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgICAgICByZXN1bHRbcmVzcG9uc2Uua2V5LnRvU3RyaW5nKCldID0gcmVzcG9uc2UudmFsLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgY29uc3QgZXJyb3IgPSB0aGlzLmhhbmRsZVJlc3BvbnNlRXJyb3IoXG4gICAgICAgICAgICAgIGBTVEFUUyAoJHtrZXl9KWAsXG4gICAgICAgICAgICAgIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMsXG4gICAgICAgICAgICAgIHVuZGVmaW5lZFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgICAgICBjYWxsYmFjayhlcnJvciwgc2Vydi5ob3N0cG9ydFN0cmluZygpLCBudWxsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfTtcbiAgICAgIGhhbmRsZS5xdWlldCA9IHRydWU7XG5cbiAgICAgIHNlcnYub25SZXNwb25zZShzZXEsIGhhbmRsZSk7XG4gICAgICBzZXJ2Lm9uRXJyb3Ioc2VxLCBmdW5jdGlvbiAoZXJyKSB7XG4gICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgIGNhbGxiYWNrKGVyciwgc2Vydi5ob3N0cG9ydFN0cmluZygpLCBudWxsKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICBzZXJ2LndyaXRlKHJlcXVlc3QpO1xuICAgIH07XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuc2VydmVycy5sZW5ndGg7IGkrKykge1xuICAgICAgaGFuZGxlU3RhdHModGhpcy5zZXEsIHRoaXMuc2VydmVyc1tpXSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNUQVRTXG4gICAqXG4gICAqIEZldGNoZXMgbWVtY2FjaGUgc3RhdHMgZnJvbSBlYWNoIGNvbm5lY3RlZCBzZXJ2ZXIuIFRoZSBjYWxsYmFjayBpcyBpbnZva2VkXG4gICAqICoqT05DRSBQRVIgU0VSVkVSKiogYW5kIGhhcyB0aGUgc2lnbmF0dXJlOlxuICAgKlxuICAgKiAgICAgY2FsbGJhY2soZXJyLCBzZXJ2ZXIsIHN0YXRzKVxuICAgKlxuICAgKiBfc2VydmVyXyBpcyB0aGUgYFwiaG9zdG5hbWU6cG9ydFwiYCBvZiB0aGUgc2VydmVyLCBhbmQgX3N0YXRzXyBpcyBhXG4gICAqIGRpY3Rpb25hcnkgbWFwcGluZyB0aGUgc3RhdCBuYW1lIHRvIHRoZSB2YWx1ZSBvZiB0aGUgc3RhdGlzdGljIGFzIGEgc3RyaW5nLlxuICAgKiBAcGFyYW0gY2FsbGJhY2tcbiAgICovXG4gIHN0YXRzKFxuICAgIGNhbGxiYWNrPzogKFxuICAgICAgZXJyOiBFcnJvciB8IG51bGwsXG4gICAgICBzZXJ2ZXI6IHN0cmluZyxcbiAgICAgIHN0YXRzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+IHwgbnVsbFxuICAgICkgPT4gdm9pZFxuICApOiB2b2lkIHtcbiAgICB0aGlzLnN0YXRzV2l0aEtleShcIlwiLCBjYWxsYmFjayk7XG4gIH1cblxuICAvKipcbiAgICogUkVTRVRfU1RBVFNcbiAgICpcbiAgICogUmVzZXQgdGhlIHN0YXRpc3RpY3MgZWFjaCBzZXJ2ZXIgaXMga2VlcGluZyBiYWNrIHRvIHplcm8uIFRoaXMgZG9lc24ndCBjbGVhclxuICAgKiBzdGF0cyBzdWNoIGFzIGl0ZW0gY291bnQsIGJ1dCB0ZW1wb3Jhcnkgc3RhdHMgc3VjaCBhcyB0b3RhbCBudW1iZXIgb2ZcbiAgICogY29ubmVjdGlvbnMgb3ZlciB0aW1lLlxuICAgKlxuICAgKiBUaGUgY2FsbGJhY2sgaXMgaW52b2tlZCAqKk9OQ0UgUEVSIFNFUlZFUioqIGFuZCBoYXMgdGhlIHNpZ25hdHVyZTpcbiAgICpcbiAgICogICAgIGNhbGxiYWNrKGVyciwgc2VydmVyKVxuICAgKlxuICAgKiBfc2VydmVyXyBpcyB0aGUgYFwiaG9zdG5hbWU6cG9ydFwiYCBvZiB0aGUgc2VydmVyLlxuICAgKiBAcGFyYW0gY2FsbGJhY2tcbiAgICovXG4gIHJlc2V0U3RhdHMoXG4gICAgY2FsbGJhY2s/OiAoXG4gICAgICBlcnI6IEVycm9yIHwgbnVsbCxcbiAgICAgIHNlcnZlcjogc3RyaW5nLFxuICAgICAgc3RhdHM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gfCBudWxsXG4gICAgKSA9PiB2b2lkXG4gICk6IHZvaWQge1xuICAgIHRoaXMuc3RhdHNXaXRoS2V5KFwicmVzZXRcIiwgY2FsbGJhY2spO1xuICB9XG5cbiAgLyoqXG4gICAqIFFVSVRcbiAgICpcbiAgICogQ2xvc2VzIHRoZSBjb25uZWN0aW9uIHRvIGVhY2ggc2VydmVyLCBub3RpZnlpbmcgdGhlbSBvZiB0aGlzIGludGVudGlvbi4gTm90ZVxuICAgKiB0aGF0IHF1aXQgY2FuIHJhY2UgYWdhaW5zdCBhbHJlYWR5IG91dHN0YW5kaW5nIHJlcXVlc3RzIHdoZW4gdGhvc2UgcmVxdWVzdHNcbiAgICogZmFpbCBhbmQgYXJlIHJldHJpZWQsIGxlYWRpbmcgdG8gdGhlIHF1aXQgY29tbWFuZCB3aW5uaW5nIGFuZCBjbG9zaW5nIHRoZVxuICAgKiBjb25uZWN0aW9uIGJlZm9yZSB0aGUgcmV0cmllcyBjb21wbGV0ZS5cbiAgICovXG4gIHF1aXQoKSB7XG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgLy8gVE9ETzogTmljZXIgcGVyaGFwcyB0byBkbyBRVUlUUSAoMHgxNykgYnV0IG5lZWQgYSBuZXcgY2FsbGJhY2sgZm9yIHdoZW5cbiAgICAvLyB3cml0ZSBpcyBkb25lLlxuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcigweDA3LCBcIlwiLCBcIlwiLCBcIlwiLCB0aGlzLnNlcSk7IC8vIFFVSVRcbiAgICBsZXQgc2VydjtcblxuICAgIGNvbnN0IGhhbmRsZVF1aXQgPSBmdW5jdGlvbiAoc2VxOiBudW1iZXIsIHNlcnY6IFNlcnZlcikge1xuICAgICAgc2Vydi5vblJlc3BvbnNlKHNlcSwgZnVuY3Rpb24gKC8qIHJlc3BvbnNlICovKSB7XG4gICAgICAgIHNlcnYuY2xvc2UoKTtcbiAgICAgIH0pO1xuICAgICAgc2Vydi5vbkVycm9yKHNlcSwgZnVuY3Rpb24gKC8qIGVyciAqLykge1xuICAgICAgICBzZXJ2LmNsb3NlKCk7XG4gICAgICB9KTtcbiAgICAgIHNlcnYud3JpdGUocmVxdWVzdCk7XG4gICAgfTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5zZXJ2ZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBzZXJ2ID0gdGhpcy5zZXJ2ZXJzW2ldO1xuICAgICAgaGFuZGxlUXVpdCh0aGlzLnNlcSwgc2Vydik7XG4gICAgfVxuICB9XG5cbiAgX3ZlcnNpb24oc2VydmVyOiBTZXJ2ZXIpOiBQcm9taXNlPHsgdmFsdWU6IFZhbHVlIHwgbnVsbCB9PiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIHRoaXMuaW5jclNlcSgpO1xuICAgICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKFxuICAgICAgICBjb25zdGFudHMuT1BfVkVSU0lPTixcbiAgICAgICAgXCJcIixcbiAgICAgICAgXCJcIixcbiAgICAgICAgXCJcIixcbiAgICAgICAgdGhpcy5zZXFcbiAgICAgICk7XG4gICAgICB0aGlzLnBlcmZvcm1PblNlcnZlcihzZXJ2ZXIsIHJlcXVlc3QsIHRoaXMuc2VxLCAoZXJyLCByZXNwb25zZSkgPT4ge1xuICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgcmV0dXJuIHJlamVjdChlcnIpO1xuICAgICAgICB9XG5cbiAgICAgICAgc3dpdGNoIChyZXNwb25zZSEuaGVhZGVyLnN0YXR1cykge1xuICAgICAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgICAgIC8qIFRPRE86IHRoaXMgaXMgYnVnZ2VkLCB3ZSBzaG91bGQndCB1c2UgdGhlIGRlc2VyaWFsaXplciBoZXJlLCBzaW5jZSB2ZXJzaW9uIGFsd2F5cyByZXR1cm5zIGEgdmVyc2lvbiBzdHJpbmcuXG4gICAgICAgICAgICAgVGhlIGRlc2VyaWFsaXplciBzaG91bGQgb25seSBiZSB1c2VkIG9uIHVzZXIga2V5IGRhdGEuICovXG4gICAgICAgICAgICBjb25zdCBkZXNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuZGVzZXJpYWxpemUoXG4gICAgICAgICAgICAgIHJlc3BvbnNlIS5oZWFkZXIub3Bjb2RlLFxuICAgICAgICAgICAgICByZXNwb25zZSEudmFsLFxuICAgICAgICAgICAgICByZXNwb25zZSEuZXh0cmFzXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgcmV0dXJuIHJlc29sdmUoeyB2YWx1ZTogZGVzZXJpYWxpemVkLnZhbHVlIH0pO1xuICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICByZXR1cm4gcmVqZWN0KFxuICAgICAgICAgICAgICB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiVkVSU0lPTlwiLCByZXNwb25zZSEuaGVhZGVyLnN0YXR1cylcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlcXVlc3QgdGhlIHNlcnZlciB2ZXJzaW9uIGZyb20gdGhlIFwiZmlyc3RcIiBzZXJ2ZXIgaW4gdGhlIGJhY2tlbmQgcG9vbC5cbiAgICogVGhlIHNlcnZlciByZXNwb25kcyB3aXRoIGEgcGFja2V0IGNvbnRhaW5pbmcgdGhlIHZlcnNpb24gc3RyaW5nIGluIHRoZSBib2R5IHdpdGggdGhlIGZvbGxvd2luZyBmb3JtYXQ6IFwieC55LnpcIlxuICAgKi9cbiAgdmVyc2lvbigpOiBQcm9taXNlPHsgdmFsdWU6IFZhbHVlIHwgbnVsbCB9PiB7XG4gICAgY29uc3Qgc2VydmVyID0gdGhpcy5zZXJ2ZXJLZXlUb1NlcnZlcih0aGlzLnNlcnZlcktleXNbMF0pO1xuICAgIHJldHVybiB0aGlzLl92ZXJzaW9uKHNlcnZlcik7XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldmVzIHRoZSBzZXJ2ZXIgdmVyc2lvbiBmcm9tIGFsbCB0aGUgc2VydmVyc1xuICAgKiBpbiB0aGUgYmFja2VuZCBwb29sLCBlcnJvcnMgaWYgYW55IG9uZSBvZiB0aGVtIGhhcyBhblxuICAgKiBlcnJvclxuICAgKi9cbiAgYXN5bmMgdmVyc2lvbkFsbCh0cmllZENhbGxiYWNrPzogKHJlc3BvbnNlOiBzdHJpbmcpID0+IHZvaWQsIHJlc3VsdENhbGxiYWNrPzogKHJlc3BvbnNlOiBzdHJpbmcpID0+IHZvaWQpOiBQcm9taXNlPHtcbiAgICB2YWx1ZXM6IFJlY29yZDxzdHJpbmcsIFZhbHVlIHwgbnVsbD47XG4gIH0+IHtcbiAgICBjb25zdCB2ZXJzaW9uT2JqZWN0cyA9IGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgdGhpcy5zZXJ2ZXJLZXlzLm1hcCgoc2VydmVyS2V5KSA9PiB7XG4gICAgICAgIGlmICh0cmllZENhbGxiYWNrICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICB0cmllZENhbGxiYWNrKHNlcnZlcktleSk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3Qgc2VydmVyID0gdGhpcy5zZXJ2ZXJLZXlUb1NlcnZlcihzZXJ2ZXJLZXkpO1xuICAgICAgICByZXR1cm4gdGhpcy5fdmVyc2lvbihzZXJ2ZXIpLnRoZW4oKHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgaWYgKHJlc3VsdENhbGxiYWNrICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHJlc3VsdENhbGxiYWNrKHNlcnZlcktleSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiB7IHNlcnZlcktleTogc2VydmVyS2V5LCB2YWx1ZTogcmVzcG9uc2UudmFsdWUgfTtcbiAgICAgICAgfSk7XG4gICAgICB9KVxuICAgICk7XG4gICAgY29uc3QgdmFsdWVzID0gdmVyc2lvbk9iamVjdHMucmVkdWNlKChhY2N1bXVsYXRvciwgdmVyc2lvbk9iamVjdCkgPT4ge1xuICAgICAgYWNjdW11bGF0b3JbdmVyc2lvbk9iamVjdC5zZXJ2ZXJLZXldID0gdmVyc2lvbk9iamVjdC52YWx1ZTtcbiAgICAgIHJldHVybiBhY2N1bXVsYXRvcjtcbiAgICB9LCB7fSBhcyBSZWNvcmQ8c3RyaW5nLCBWYWx1ZSB8IG51bGw+KTtcbiAgICByZXR1cm4geyB2YWx1ZXM6IHZhbHVlcyB9O1xuICB9XG5cbiAgLyoqXG4gICAqIENsb3NlcyAoYWJydXB0bHkpIGNvbm5lY3Rpb25zIHRvIGFsbCB0aGUgc2VydmVycy5cbiAgICogQHNlZSB0aGlzLnF1aXRcbiAgICovXG4gIGNsb3NlKCkge1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5zZXJ2ZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB0aGlzLnNlcnZlcnNbaV0uY2xvc2UoKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUGVyZm9ybSBhIGdlbmVyaWMgc2luZ2xlIHJlc3BvbnNlIG9wZXJhdGlvbiAoZ2V0LCBzZXQgZXRjKSBvbiBvbmUgc2VydmVyXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgdGhlIGtleSB0byBoYXNoIHRvIGdldCBhIHNlcnZlciBmcm9tIHRoZSBwb29sXG4gICAqIEBwYXJhbSB7YnVmZmVyfSByZXF1ZXN0IGEgYnVmZmVyIGNvbnRhaW5pbmcgdGhlIHJlcXVlc3RcbiAgICogQHBhcmFtIHtudW1iZXJ9IHNlcSB0aGUgc2VxdWVuY2UgbnVtYmVyIG9mIHRoZSBvcGVyYXRpb24uIEl0IGlzIHVzZWQgdG8gcGluIHRoZSBjYWxsYmFja3NcbiAgICAgICAgICAgICAgICAgICAgICAgICB0byBhIHNwZWNpZmljIG9wZXJhdGlvbiBhbmQgc2hvdWxkIG5ldmVyIGNoYW5nZSBkdXJpbmcgYSBgcGVyZm9ybWAuXG4gICAqIEBwYXJhbSB7bnVtYmVyP30gcmV0cmllcyBudW1iZXIgb2YgdGltZXMgdG8gcmV0cnkgcmVxdWVzdCBvbiBmYWlsdXJlXG4gICAqL1xuICBwZXJmb3JtKFxuICAgIGtleTogc3RyaW5nLFxuICAgIHJlcXVlc3Q6IEJ1ZmZlcixcbiAgICBzZXE6IG51bWJlcixcbiAgICByZXRyaWVzPzogbnVtYmVyXG4gICk6IFByb21pc2U8TWVzc2FnZT4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBjb25zdCBzZXJ2ZXJLZXkgPSB0aGlzLmxvb2t1cEtleVRvU2VydmVyS2V5KGtleSk7XG4gICAgICBjb25zdCBzZXJ2ZXIgPSB0aGlzLnNlcnZlcktleVRvU2VydmVyKHNlcnZlcktleSk7XG5cbiAgICAgIGlmICghc2VydmVyKSB7XG4gICAgICAgIHJldHVybiByZWplY3QobmV3IEVycm9yKFwiTm8gc2VydmVycyBhdmFpbGFibGVcIikpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLnBlcmZvcm1PblNlcnZlcihcbiAgICAgICAgc2VydmVyLFxuICAgICAgICByZXF1ZXN0LFxuICAgICAgICBzZXEsXG4gICAgICAgIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgIHJldHVybiByZWplY3QoZXJyb3IpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXNvbHZlKHJlc3BvbnNlISk7XG4gICAgICAgIH0sXG4gICAgICAgIHJldHJpZXNcbiAgICAgICk7XG4gICAgfSk7XG4gIH1cblxuICBwZXJmb3JtT25TZXJ2ZXIoXG4gICAgc2VydmVyOiBTZXJ2ZXIsXG4gICAgcmVxdWVzdDogQnVmZmVyLFxuICAgIHNlcTogbnVtYmVyLFxuICAgIGNhbGxiYWNrOiBSZXNwb25zZU9yRXJyb3JDYWxsYmFjayxcbiAgICByZXRyaWVzOiBudW1iZXIgPSAwXG4gICkge1xuICAgIGNvbnN0IF90aGlzID0gdGhpcztcblxuICAgIHJldHJpZXMgPSByZXRyaWVzIHx8IHRoaXMub3B0aW9ucy5yZXRyaWVzO1xuICAgIGNvbnN0IG9yaWdSZXRyaWVzID0gdGhpcy5vcHRpb25zLnJldHJpZXM7XG4gICAgY29uc3QgbG9nZ2VyID0gdGhpcy5vcHRpb25zLmxvZ2dlcjtcbiAgICBjb25zdCByZXRyeV9kZWxheSA9IHRoaXMub3B0aW9ucy5yZXRyeV9kZWxheTtcblxuICAgIGNvbnN0IHJlc3BvbnNlSGFuZGxlcjogT25SZXNwb25zZUNhbGxiYWNrID0gZnVuY3Rpb24gKHJlc3BvbnNlKSB7XG4gICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgY2FsbGJhY2sobnVsbCwgcmVzcG9uc2UpO1xuICAgICAgfVxuICAgIH07XG5cbiAgICBjb25zdCBlcnJvckhhbmRsZXI6IE9uRXJyb3JDYWxsYmFjayA9IGZ1bmN0aW9uIChlcnJvcikge1xuICAgICAgaWYgKC0tcmV0cmllcyA+IDApIHtcbiAgICAgICAgLy8gV2FpdCBmb3IgcmV0cnlfZGVsYXlcbiAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgX3RoaXMucGVyZm9ybU9uU2VydmVyKHNlcnZlciwgcmVxdWVzdCwgc2VxLCBjYWxsYmFjaywgcmV0cmllcyk7XG4gICAgICAgIH0sIDEwMDAgKiByZXRyeV9kZWxheSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBsb2dnZXIubG9nKFxuICAgICAgICAgIFwiTWVtSlM6IFNlcnZlciA8XCIgK1xuICAgICAgICAgICAgc2VydmVyLmhvc3Rwb3J0U3RyaW5nKCkgK1xuICAgICAgICAgICAgXCI+IGZhaWxlZCBhZnRlciAoXCIgK1xuICAgICAgICAgICAgb3JpZ1JldHJpZXMgK1xuICAgICAgICAgICAgXCIpIHJldHJpZXMgd2l0aCBlcnJvciAtIFwiICtcbiAgICAgICAgICAgIGVycm9yLm1lc3NhZ2VcbiAgICAgICAgKTtcbiAgICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgICAgY2FsbGJhY2soZXJyb3IsIG51bGwpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfTtcblxuICAgIHNlcnZlci5vblJlc3BvbnNlKHNlcSwgcmVzcG9uc2VIYW5kbGVyKTtcbiAgICBzZXJ2ZXIub25FcnJvcihzZXEsIGVycm9ySGFuZGxlcik7XG4gICAgc2VydmVyLndyaXRlKHJlcXVlc3QpO1xuICB9XG5cbiAgLy8gSW5jcmVtZW50IHRoZSBzZXEgdmFsdWVcbiAgaW5jclNlcSgpIHtcbiAgICB0aGlzLnNlcSsrO1xuXG4gICAgLy8gV3JhcCBgdGhpcy5zZXFgIHRvIDMyLWJpdHMgc2luY2UgdGhlIGZpZWxkIHdlIGZpdCBpdCBpbnRvIGlzIG9ubHkgMzItYml0cy5cbiAgICB0aGlzLnNlcSAmPSAweGZmZmZmZmZmO1xuXG4gICAgcmV0dXJuIHRoaXMuc2VxXG4gIH1cblxuICBwcml2YXRlIGNyZWF0ZUFuZExvZ0Vycm9yKFxuICAgIGNvbW1hbmROYW1lOiBzdHJpbmcsXG4gICAgcmVzcG9uc2VTdGF0dXM6IFJlc3BvbnNlU3RhdHVzIHwgdW5kZWZpbmVkXG4gICk6IEVycm9yIHtcbiAgICBjb25zdCBlcnJvck1lc3NhZ2UgPSBgTWVtSlMgJHtjb21tYW5kTmFtZX06ICR7Y29uc3RhbnRzLnJlc3BvbnNlU3RhdHVzVG9TdHJpbmcoXG4gICAgICByZXNwb25zZVN0YXR1c1xuICAgICl9YDtcbiAgICB0aGlzLm9wdGlvbnMubG9nZ2VyLmxvZyhlcnJvck1lc3NhZ2UpO1xuICAgIHJldHVybiBuZXcgRXJyb3IoZXJyb3JNZXNzYWdlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBMb2cgYW4gZXJyb3IgdG8gdGhlIGxvZ2dlciwgdGhlbiByZXR1cm4gdGhlIGVycm9yLlxuICAgKiBJZiBhIGNhbGxiYWNrIGlzIGdpdmVuLCBjYWxsIGl0IHdpdGggY2FsbGJhY2soZXJyb3IsIG51bGwpLlxuICAgKi9cbiAgcHJpdmF0ZSBoYW5kbGVSZXNwb25zZUVycm9yKFxuICAgIGNvbW1hbmROYW1lOiBzdHJpbmcsXG4gICAgcmVzcG9uc2VTdGF0dXM6IFJlc3BvbnNlU3RhdHVzIHwgdW5kZWZpbmVkLFxuICAgIGNhbGxiYWNrOiB1bmRlZmluZWQgfCAoKGVycm9yOiBFcnJvciB8IG51bGwsIG90aGVyOiBudWxsKSA9PiB2b2lkKVxuICApOiBFcnJvciB7XG4gICAgY29uc3QgZXJyb3IgPSB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKGNvbW1hbmROYW1lLCByZXNwb25zZVN0YXR1cyk7XG4gICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICBjYWxsYmFjayhlcnJvciwgbnVsbCk7XG4gICAgfVxuICAgIHJldHVybiBlcnJvcjtcbiAgfVxufVxuXG5leHBvcnQgeyBDbGllbnQsIFNlcnZlciwgVXRpbHMsIEhlYWRlciB9O1xuIl19 \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 36c9a82..b664ffd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,8 +1,5544 @@ { "name": "memjs", "version": "1.2.2", - "lockfileVersion": 1, + "lockfileVersion": 2, "requires": true, + "packages": { + "": { + "name": "memjs", + "version": "1.2.2", + "license": "MIT", + "devDependencies": { + "@types/node": "12.20.7", + "@types/tap": "^14.10.3", + "benchmark": "^2.1.4", + "docco": "^0.8.0", + "eslint": "^7.23.0", + "microtime": "^3.0.0", + "tap": "14.0.*", + "typescript": "4.2.4" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz", + "integrity": "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.12.13" + } + }, + "node_modules/@babel/generator": { + "version": "7.13.9", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.13.9.tgz", + "integrity": "sha512-mHOOmY0Axl/JCTkxTU6Lf5sWOg/v8nUa+Xkt4zMTftX0wqmb6Sh7J8gvcehBw7q0AhrhAR+FDacKjCZ2X8K+Sw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.13.0", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + } + }, + "node_modules/@babel/generator/node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/generator/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.12.13.tgz", + "integrity": "sha512-TZvmPn0UOqmvi5G4vvw0qZTpVptGkB1GL61R6lKvrSdIxGm5Pky7Q3fpKiIkQCAtRCBUwB0PaThlx9vebCDSwA==", + "dev": true, + "dependencies": { + "@babel/helper-get-function-arity": "^7.12.13", + "@babel/template": "^7.12.13", + "@babel/types": "^7.12.13" + } + }, + "node_modules/@babel/helper-get-function-arity": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.13.tgz", + "integrity": "sha512-DjEVzQNz5LICkzN0REdpD5prGoidvbdYk1BVgRUOINaWJP2t6avB27X1guXK1kXNrX0WMfsrm1A/ZBthYuIMQg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.12.13" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.13.tgz", + "integrity": "sha512-tCJDltF83htUtXx5NLcaDqRmknv652ZWCHyoTETf1CXYJdPC7nohZohjUgieXhv0hTJdRf2FjDueFehdNucpzg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.12.13" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", + "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", + "dev": true + }, + "node_modules/@babel/highlight": { + "version": "7.13.10", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.13.10.tgz", + "integrity": "sha512-5aPpe5XQPzflQrFwL1/QoeHkP2MsA4JCntcXHRhEsdsfPVkvPi2w7Qix4iV7t5S/oC9OodGrggd8aco1g3SZFg==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.12.11", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/parser": { + "version": "7.13.12", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.13.12.tgz", + "integrity": "sha512-4T7Pb244rxH24yR116LAuJ+adxXXnHhZaLJjegJVKSdoNCe4x1eDBaud5YIcQFcqzsaD5BHvJw5BQ0AZapdCRw==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/template": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.12.13.tgz", + "integrity": "sha512-/7xxiGA57xMo/P2GVvdEumr8ONhFOhfgq2ihK3h1e6THqzTAkHbkXgB0xI9yeTfIUoH3+oAeHhqm/I43OTbbjA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@babel/parser": "^7.12.13", + "@babel/types": "^7.12.13" + } + }, + "node_modules/@babel/traverse": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.13.0.tgz", + "integrity": "sha512-xys5xi5JEhzC3RzEmSGrs/b3pJW/o87SypZ+G/PhaE7uqVQNv/jlmVIBXuoh5atqQ434LfXV+sf23Oxj0bchJQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@babel/generator": "^7.13.0", + "@babel/helper-function-name": "^7.12.13", + "@babel/helper-split-export-declaration": "^7.12.13", + "@babel/parser": "^7.13.0", + "@babel/types": "^7.13.0", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.19" + } + }, + "node_modules/@babel/traverse/node_modules/debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/traverse/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@babel/types": { + "version": "7.13.12", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.13.12.tgz", + "integrity": "sha512-K4nY2xFN4QMvQwkQ+zmBDp6ANMbVNw6BbxWmYA4qNjhR9W+Lj/8ky5MEY2Me5r+B2c6/v6F53oMndG+f9s3IiA==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + }, + "node_modules/@babel/types/node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.0.tgz", + "integrity": "sha512-2ZPCc+uNbjV5ERJr+aKSPRwZgKd2z11x0EgLvb1PURmUrn9QNRXFqje0Ldq454PfAVyaJYyrDvvIKSFP4NnBog==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.1.1", + "espree": "^7.3.0", + "globals": "^12.1.0", + "ignore": "^4.0.6", + "import-fresh": "^3.2.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/@eslint/eslintrc/node_modules/debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "12.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", + "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "dev": true, + "dependencies": { + "type-fest": "^0.8.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/eslintrc/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@eslint/eslintrc/node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@types/node": { + "version": "12.20.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.7.tgz", + "integrity": "sha512-gWL8VUkg8VRaCAUgG9WmhefMqHmMblxe2rVpMF86nZY/+ZysU+BkAp+3cz03AixWDSSz0ks5WX59yAhv/cDwFA==", + "dev": true + }, + "node_modules/@types/tap": { + "version": "14.10.3", + "resolved": "https://registry.npmjs.org/@types/tap/-/tap-14.10.3.tgz", + "integrity": "sha512-pdibkMTqKxznrLTFRVJdv/zQ8AAvHe9puqiBt9Mp+hrBgs0ZqCsjCj2e6ez8+p39oapyVp491xxw09E732g1Qw==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/yoga-layout": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@types/yoga-layout/-/yoga-layout-1.9.2.tgz", + "integrity": "sha512-S9q47ByT2pPvD65IvrWp7qppVMpk9WGMbVq9wbWZOHg6tnXSD4vyhao6nOSBwwfDdV2p3Kx9evA9vI+XWTfDvw==", + "dev": true + }, + "node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", + "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ansicolors": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.3.2.tgz", + "integrity": "sha1-ZlWX3oap/+Oqm/vmyuXG6kJrSXk=", + "dev": true + }, + "node_modules/anymatch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", + "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/append-transform": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-1.0.0.tgz", + "integrity": "sha512-P009oYkeHyU742iSZJzZZywj4QRJdnTWffaKuJQLablCZ1uz6/cW4yaRgcDaoQ+uwOxxnt0gRUcwfsNP2ri0gw==", + "dev": true, + "dependencies": { + "default-require-extensions": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", + "dev": true + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/arrify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "dev": true, + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/async-hook-domain": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/async-hook-domain/-/async-hook-domain-1.1.3.tgz", + "integrity": "sha512-ZovMxSbADV3+biB7oR1GL5lGyptI24alp0LWHlmz1OFc5oL47pz3EiIF6nXOkDW7yLqih4NtsiYduzdDW0i+Wg==", + "dev": true, + "dependencies": { + "source-map-support": "^0.5.11" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "node_modules/auto-bind": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/auto-bind/-/auto-bind-4.0.0.tgz", + "integrity": "sha512-Hdw8qdNiqdJ8LqT0iK0sVzkFbzg6fhnQqqfWhBDxcHZvU75+B+ayzTy8x+k5Ix0Y92XOhOUlx74ps+bA6BeYMQ==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/aws4": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", + "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==", + "dev": true + }, + "node_modules/babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "dev": true, + "dependencies": { + "chalk": "^1.1.3", + "esutils": "^2.0.2", + "js-tokens": "^3.0.2" + } + }, + "node_modules/babel-core": { + "version": "6.26.3", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.3.tgz", + "integrity": "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==", + "dev": true, + "dependencies": { + "babel-code-frame": "^6.26.0", + "babel-generator": "^6.26.0", + "babel-helpers": "^6.24.1", + "babel-messages": "^6.23.0", + "babel-register": "^6.26.0", + "babel-runtime": "^6.26.0", + "babel-template": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "convert-source-map": "^1.5.1", + "debug": "^2.6.9", + "json5": "^0.5.1", + "lodash": "^4.17.4", + "minimatch": "^3.0.4", + "path-is-absolute": "^1.0.1", + "private": "^0.1.8", + "slash": "^1.0.0", + "source-map": "^0.5.7" + } + }, + "node_modules/babel-core/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/babel-generator": { + "version": "6.26.1", + "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", + "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", + "dev": true, + "dependencies": { + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "detect-indent": "^4.0.0", + "jsesc": "^1.3.0", + "lodash": "^4.17.4", + "source-map": "^0.5.7", + "trim-right": "^1.0.1" + } + }, + "node_modules/babel-generator/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/babel-helper-builder-react-jsx": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz", + "integrity": "sha1-Of+DE7dci2Xc7/HzHTg+D/KkCKA=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "esutils": "^2.0.2" + } + }, + "node_modules/babel-helpers": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", + "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } + }, + "node_modules/babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.22.0" + } + }, + "node_modules/babel-plugin-syntax-jsx": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", + "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=", + "dev": true + }, + "node_modules/babel-plugin-syntax-object-rest-spread": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", + "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=", + "dev": true + }, + "node_modules/babel-plugin-transform-es2015-destructuring": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", + "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.22.0" + } + }, + "node_modules/babel-plugin-transform-object-rest-spread": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz", + "integrity": "sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY=", + "dev": true, + "dependencies": { + "babel-plugin-syntax-object-rest-spread": "^6.8.0", + "babel-runtime": "^6.26.0" + } + }, + "node_modules/babel-plugin-transform-react-jsx": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz", + "integrity": "sha1-hAoCjn30YN/DotKfDA2R9jduZqM=", + "dev": true, + "dependencies": { + "babel-helper-builder-react-jsx": "^6.24.1", + "babel-plugin-syntax-jsx": "^6.8.0", + "babel-runtime": "^6.22.0" + } + }, + "node_modules/babel-register": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", + "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", + "dev": true, + "dependencies": { + "babel-core": "^6.26.0", + "babel-runtime": "^6.26.0", + "core-js": "^2.5.0", + "home-or-tmp": "^2.0.0", + "lodash": "^4.17.4", + "mkdirp": "^0.5.1", + "source-map-support": "^0.4.15" + } + }, + "node_modules/babel-register/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/babel-register/node_modules/source-map-support": { + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", + "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", + "dev": true, + "dependencies": { + "source-map": "^0.5.6" + } + }, + "node_modules/babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "dev": true, + "dependencies": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + } + }, + "node_modules/babel-template": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", + "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "lodash": "^4.17.4" + } + }, + "node_modules/babel-traverse": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", + "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", + "dev": true, + "dependencies": { + "babel-code-frame": "^6.26.0", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "debug": "^2.6.8", + "globals": "^9.18.0", + "invariant": "^2.2.2", + "lodash": "^4.17.4" + } + }, + "node_modules/babel-traverse/node_modules/globals": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/babel-types": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.26.0", + "esutils": "^2.0.2", + "lodash": "^4.17.4", + "to-fast-properties": "^1.0.3" + } + }, + "node_modules/babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", + "dev": true, + "bin": { + "babylon": "bin/babylon.js" + } + }, + "node_modules/balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "dev": true, + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, + "node_modules/benchmark": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/benchmark/-/benchmark-2.1.4.tgz", + "integrity": "sha1-CfPeMckWQl1JjMLuVloOvzwqVik=", + "dev": true, + "dependencies": { + "lodash": "^4.17.4", + "platform": "^1.3.3" + } + }, + "node_modules/benchmark/node_modules/lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "dev": true + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/bind-obj-methods": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/bind-obj-methods/-/bind-obj-methods-2.0.1.tgz", + "integrity": "sha512-kKzUyCuc+jsWH4C2nW5KB2nh+rQRbQcdphfo9UN3j1uwIFGZ3JB8njtRZOiUAQCkxazH0nDQPN6x/zhvFcbZIw==", + "deprecated": "do not use this version, it is broken", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browser-process-hrtime": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", + "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", + "dev": true + }, + "node_modules/buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "node_modules/caching-transform": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-3.0.2.tgz", + "integrity": "sha512-Mtgcv3lh3U0zRii/6qVgQODdPA4G3zhG+jtbCWj39RXuUFTMzH0vcdMtaJS1jPowd+It2Pqr6y3NJMQqOqCE2w==", + "dev": true, + "dependencies": { + "hasha": "^3.0.0", + "make-dir": "^2.0.0", + "package-hash": "^3.0.0", + "write-file-atomic": "^2.4.2" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/caller-callsite": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", + "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=", + "dev": true, + "dependencies": { + "callsites": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/caller-callsite/node_modules/callsites": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", + "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/capture-stack-trace": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz", + "integrity": "sha512-mYQLZnx5Qt1JgB1WEiMCf2647plpGeQ2NMR/5L0HNZzGQo4fuSPnK+wjfPnKZV0aiJDgzmWqqkV/g7JD+DW0qw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cardinal": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/cardinal/-/cardinal-2.1.1.tgz", + "integrity": "sha1-fMEFXYItISlU0HsIXeolHMe8VQU=", + "dev": true, + "dependencies": { + "ansicolors": "~0.3.2", + "redeyed": "~2.1.0" + }, + "bin": { + "cdl": "bin/cdl.js" + } + }, + "node_modules/caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true + }, + "node_modules/chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "dependencies": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/chokidar": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", + "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.5.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.1" + } + }, + "node_modules/ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true + }, + "node_modules/cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, + "dependencies": { + "restore-cursor": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cli-truncate": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", + "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", + "dev": true, + "dependencies": { + "slice-ansi": "^3.0.0", + "string-width": "^4.2.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate/node_modules/ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-truncate/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/cli-truncate/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/cli-truncate/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/cli-truncate/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/cli-truncate/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-truncate/node_modules/slice-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", + "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-truncate/node_modules/string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-truncate/node_modules/strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", + "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", + "dev": true, + "dependencies": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" + } + }, + "node_modules/cliui/node_modules/ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "dependencies": { + "ansi-regex": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "dev": true, + "bin": { + "color-support": "bin.js" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.12.1.tgz", + "integrity": "sha512-PCNLExLlI5HiPdaJs4pMXwOTHkSCpNQ1QJH9ykZLKtKEyKu3p9HgmH5l97vM8c0IUz6d54l+xEu2GG9yuYrFzA==", + "dev": true + }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "node_modules/convert-source-map": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.1" + } + }, + "node_modules/core-js": { + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", + "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", + "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.", + "dev": true, + "hasInstallScript": true + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "node_modules/coveralls": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.1.0.tgz", + "integrity": "sha512-sHxOu2ELzW8/NC1UP5XVLbZDzO4S3VxfFye3XYCznopHy02YjNkHcj5bKaVw2O7hVaBdBjEdQGpie4II1mWhuQ==", + "dev": true, + "dependencies": { + "js-yaml": "^3.13.1", + "lcov-parse": "^1.0.0", + "log-driver": "^1.2.7", + "minimist": "^1.2.5", + "request": "^2.88.2" + }, + "bin": { + "coveralls": "bin/coveralls.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/coveralls/node_modules/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "node_modules/cp-file": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/cp-file/-/cp-file-6.2.0.tgz", + "integrity": "sha512-fmvV4caBnofhPe8kOcitBwSn2f39QLjnAnGq3gO9dfd75mUytzKNZB1hde6QHunW2Rt+OwuBOMc3i1tNElbszA==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "make-dir": "^2.0.0", + "nested-error-stacks": "^2.0.0", + "pify": "^4.0.1", + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/cross-spawn": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.2.tgz", + "integrity": "sha1-e5JHYhwjrf3ThWAEqCPL45dCTUE=", + "dev": true, + "dependencies": { + "lru-cache": "^4.0.1", + "which": "^1.2.9" + } + }, + "node_modules/dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "node_modules/default-require-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-2.0.0.tgz", + "integrity": "sha1-9fj7sYp9bVCyH2QfZJ67Uiz+JPc=", + "dev": true, + "dependencies": { + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/detect-indent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", + "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", + "dev": true, + "dependencies": { + "repeating": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/docco": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/docco/-/docco-0.8.0.tgz", + "integrity": "sha512-QcWBDnnGaT+rgC0wqynznXv0/4hd6nAFdWNs2fN4FvkH2yAnCYVeRU7GIZXNCeUQ955Lufq+TmZcSXiBa1cGQQ==", + "dev": true, + "dependencies": { + "commander": ">= 0.5.2", + "fs-extra": ">= 0.6.0", + "highlight.js": ">= 8.0.x", + "marked": ">= 0.2.7", + "underscore": ">= 1.0.0" + }, + "bin": { + "docco": "bin/docco" + }, + "engines": { + "node": ">=0.2.0" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/domain-browser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", + "dev": true, + "engines": { + "node": ">=0.4", + "npm": ">=1.2" + } + }, + "node_modules/ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "dev": true, + "dependencies": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "node_modules/enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, + "dependencies": { + "ansi-colors": "^4.1.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es6-error": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", + "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", + "dev": true + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/eslint": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.23.0.tgz", + "integrity": "sha512-kqvNVbdkjzpFy0XOszNwjkKzZ+6TcwCQ/h+ozlcIWwaimBBuhlQ4nN6kbiM2L+OjDcznkTJxzYfRFH92sx4a0Q==", + "dev": true, + "dependencies": { + "@babel/code-frame": "7.12.11", + "@eslint/eslintrc": "^0.4.0", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "enquirer": "^2.3.5", + "eslint-scope": "^5.1.1", + "eslint-utils": "^2.1.0", + "eslint-visitor-keys": "^2.0.0", + "espree": "^7.3.1", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "file-entry-cache": "^6.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.0.0", + "globals": "^13.6.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash": "^4.17.21", + "minimatch": "^3.0.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "progress": "^2.0.0", + "regexpp": "^3.1.0", + "semver": "^7.2.1", + "strip-ansi": "^6.0.0", + "strip-json-comments": "^3.1.0", + "table": "^6.0.4", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^1.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz", + "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint/node_modules/@babel/code-frame": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", + "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.10.4" + } + }, + "node_modules/eslint/node_modules/ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/eslint/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/eslint/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/eslint/node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/eslint/node_modules/debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/eslint/node_modules/globals": { + "version": "13.7.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.7.0.tgz", + "integrity": "sha512-Aipsz6ZKRxa/xQkZhNg0qIWXT6x6rD46f6x/PCnBomlttdIyAPak4YD9jTmKpZ72uROSMU87qJtcgpgHaVchiA==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/eslint/node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint/node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/eslint/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/esm": { + "version": "3.2.25", + "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz", + "integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/espree": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", + "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", + "dev": true, + "dependencies": { + "acorn": "^7.4.0", + "acorn-jsx": "^5.3.1", + "eslint-visitor-keys": "^1.3.0" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esquery/node_modules/estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/events-to-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/events-to-array/-/events-to-array-1.1.2.tgz", + "integrity": "sha1-LUH1Y+H+QA7Uli/hpNXGp1Od9/Y=", + "dev": true + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "node_modules/extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true, + "engines": [ + "node >=0.6.0" + ] + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/findit": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/findit/-/findit-2.0.0.tgz", + "integrity": "sha1-ZQnwEmr0wXhVHPqZOU4DLhOk1W4=", + "dev": true + }, + "node_modules/flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "dependencies": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flat-cache/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/flatted": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.1.tgz", + "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==", + "dev": true + }, + "node_modules/foreground-child": { + "version": "1.5.6", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-1.5.6.tgz", + "integrity": "sha1-T9ca0t/elnibmApcCilZN8svXOk=", + "dev": true, + "dependencies": { + "cross-spawn": "^4", + "signal-exit": "^3.0.0" + } + }, + "node_modules/forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/fs-exists-cached": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-exists-cached/-/fs-exists-cached-1.0.0.tgz", + "integrity": "sha1-zyVVTKBQ3EmuZla0HeQiWJidy84=", + "dev": true + }, + "node_modules/fs-extra": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-5.0.0.tgz", + "integrity": "sha512-66Pm4RYbjzdyeuqudYqhFiNBbCIuI9kgRqLPSHIlXHidW8NIQtVdkM1yeZ4lXwuhbTETv3EUGMNHAAw6hiundQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/function-loop": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/function-loop/-/function-loop-1.0.2.tgz", + "integrity": "sha512-Iw4MzMfS3udk/rqxTiDDCllhGwlOrsr50zViTOO/W6lS/9y6B1J0BD2VZzrnWUYBJsl3aeqjgR5v7bWWhZSYbA==", + "dev": true + }, + "node_modules/functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "dependencies": { + "assert-plus": "^1.0.0" + } + }, + "node_modules/glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/har-validator": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "deprecated": "this library is no longer supported", + "dev": true, + "dependencies": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/har-validator/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/har-validator/node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/har-validator/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/has-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasha": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hasha/-/hasha-3.0.0.tgz", + "integrity": "sha1-UqMvq4Vp1BymmmH/GiFPjrfIvTk=", + "dev": true, + "dependencies": { + "is-stream": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/highlight.js": { + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.4.1.tgz", + "integrity": "sha512-yR5lWvNz7c85OhVAEAeFhVCc/GV4C30Fjzc/rCP0aCWzc1UUOPUk55dK/qdwTZHBvMZo+eZ2jpk62ndX/xMFlg==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/home-or-tmp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", + "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", + "dev": true, + "dependencies": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/hosted-git-info": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "dev": true + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "node_modules/http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dev": true, + "dependencies": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + }, + "engines": { + "node": ">=0.8", + "npm": ">=1.3.7" + } + }, + "node_modules/ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/import-jsx": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-jsx/-/import-jsx-2.0.0.tgz", + "integrity": "sha512-xmrgtiRnAdjIaRzKwsHut54FA8nx59WqN4MpQvPFr/8yD6BamavkmKHrA5dotAlnIiF4uqMzg/lA5yhPdpIXsA==", + "dev": true, + "dependencies": { + "babel-core": "^6.25.0", + "babel-plugin-transform-es2015-destructuring": "^6.23.0", + "babel-plugin-transform-object-rest-spread": "^6.23.0", + "babel-plugin-transform-react-jsx": "^6.24.1", + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-jsx/node_modules/caller-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", + "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=", + "dev": true, + "dependencies": { + "caller-callsite": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "node_modules/ink": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/ink/-/ink-2.7.1.tgz", + "integrity": "sha512-s7lJuQDJEdjqtaIWhp3KYHl6WV3J04U9zoQ6wVc+Xoa06XM27SXUY57qC5DO46xkF0CfgXMKkKNcgvSu/SAEpA==", + "dev": true, + "dependencies": { + "ansi-escapes": "^4.2.1", + "arrify": "^2.0.1", + "auto-bind": "^4.0.0", + "chalk": "^3.0.0", + "cli-cursor": "^3.1.0", + "cli-truncate": "^2.1.0", + "is-ci": "^2.0.0", + "lodash.throttle": "^4.1.1", + "log-update": "^3.0.0", + "prop-types": "^15.6.2", + "react-reconciler": "^0.24.0", + "scheduler": "^0.18.0", + "signal-exit": "^3.0.2", + "slice-ansi": "^3.0.0", + "string-length": "^3.1.0", + "widest-line": "^3.1.0", + "wrap-ansi": "^6.2.0", + "yoga-layout-prebuilt": "^1.9.3" + }, + "engines": { + "node": ">=8" + }, + "peerDependencies": { + "@types/react": ">=16.8.0", + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/ink/node_modules/ansi-escapes": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz", + "integrity": "sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==", + "dev": true, + "dependencies": { + "type-fest": "^0.11.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ink/node_modules/ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ink/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ink/node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ink/node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ink/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/ink/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/ink/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/ink/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ink/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ink/node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ink/node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ink/node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ink/node_modules/slice-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", + "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ink/node_modules/string-length": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-3.1.0.tgz", + "integrity": "sha512-Ttp5YvkGm5v9Ijagtaz1BnN+k9ObpvS0eIBblPMp2YWL8FBmi9qblQ9fexc2k/CXFgrTIteU3jAw3payCnwSTA==", + "dev": true, + "dependencies": { + "astral-regex": "^1.0.0", + "strip-ansi": "^5.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ink/node_modules/string-length/node_modules/astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ink/node_modules/string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ink/node_modules/string-width/node_modules/ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ink/node_modules/string-width/node_modules/strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ink/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ink/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ink/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ink/node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ink/node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dev": true, + "dependencies": { + "loose-envify": "^1.0.0" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.0.tgz", + "integrity": "sha512-a7Uprx8UtD+HWdyYwnD1+ExtTgqQtD2k/1yJgtXP6wnMm8byhkoTZRl+95LLThpzNZJ5aEvi46cdH+ayMFRwmA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "dev": true, + "dependencies": { + "ci-info": "^2.0.0" + }, + "bin": { + "is-ci": "bin.js" + } + }, + "node_modules/is-core-module": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz", + "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-finite": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz", + "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==", + "dev": true, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.4.tgz", + "integrity": "sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-string": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", + "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true, + "optional": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "node_modules/istanbul-lib-coverage": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", + "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/istanbul-lib-hook": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-2.0.7.tgz", + "integrity": "sha512-vrRztU9VRRFDyC+aklfLoeXyNdTfga2EI3udDGn4cZ6fpSXpHLV9X6CHvfoMCPtggg8zvDDmC4b9xfu0z6/llA==", + "dev": true, + "dependencies": { + "append-transform": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz", + "integrity": "sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==", + "dev": true, + "dependencies": { + "@babel/generator": "^7.4.0", + "@babel/parser": "^7.4.3", + "@babel/template": "^7.4.0", + "@babel/traverse": "^7.4.3", + "@babel/types": "^7.4.0", + "istanbul-lib-coverage": "^2.0.5", + "semver": "^6.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/istanbul-lib-processinfo": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-1.0.0.tgz", + "integrity": "sha512-FY0cPmWa4WoQNlvB8VOcafiRoB5nB+l2Pz2xGuXHRSy1KM8QFOYfz/rN+bGMCAeejrY3mrpF5oJHcN0s/garCg==", + "dev": true, + "dependencies": { + "archy": "^1.0.0", + "cross-spawn": "^6.0.5", + "istanbul-lib-coverage": "^2.0.3", + "rimraf": "^2.6.3", + "uuid": "^3.3.2" + } + }, + "node_modules/istanbul-lib-processinfo/node_modules/cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "dependencies": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "engines": { + "node": ">=4.8" + } + }, + "node_modules/istanbul-lib-processinfo/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/istanbul-lib-report": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz", + "integrity": "sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ==", + "dev": true, + "dependencies": { + "istanbul-lib-coverage": "^2.0.5", + "make-dir": "^2.1.0", + "supports-color": "^6.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/istanbul-lib-report/node_modules/supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz", + "integrity": "sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^2.0.5", + "make-dir": "^2.1.0", + "rimraf": "^2.6.3", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/istanbul-reports": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.2.7.tgz", + "integrity": "sha512-uu1F/L1o5Y6LzPVSVZXNOoD/KXpJue9aeLRd0sM9uMXfZvzomB0WxVamWb5ue8kA2vVWEmW7EG+A5n3f1kqHKg==", + "dev": true, + "dependencies": { + "html-escaper": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jackspeak": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-1.4.0.tgz", + "integrity": "sha512-VDcSunT+wcccoG46FtzuBAyQKlzhHjli4q31e1fIHGOsRspqNUFjVzGb+7eIFDlTvqLygxapDHPHS0ouT2o/tw==", + "dev": true, + "dependencies": { + "cliui": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "dev": true + }, + "node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true + }, + "node_modules/jsesc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", + "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + } + }, + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "node_modules/json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "node_modules/json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "node_modules/lcov-parse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcov-parse/-/lcov-parse-1.0.0.tgz", + "integrity": "sha1-6w1GtUER68VhrLTECO+TY73I9+A=", + "dev": true, + "bin": { + "lcov-parse": "bin/cli.js" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/load-json-file/node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "node_modules/lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", + "dev": true + }, + "node_modules/lodash.flatten": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", + "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=", + "dev": true + }, + "node_modules/lodash.flattendeep": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", + "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", + "dev": true + }, + "node_modules/lodash.throttle": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", + "integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ=", + "dev": true + }, + "node_modules/lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", + "dev": true + }, + "node_modules/log-driver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.7.tgz", + "integrity": "sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg==", + "dev": true, + "engines": { + "node": ">=0.8.6" + } + }, + "node_modules/log-update": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-3.4.0.tgz", + "integrity": "sha512-ILKe88NeMt4gmDvk/eb615U/IVn7K9KWGkoYbdatQ69Z65nj1ZzjM6fHXfcs0Uge+e+EGnMW7DY4T9yko8vWFg==", + "dev": true, + "dependencies": { + "ansi-escapes": "^3.2.0", + "cli-cursor": "^2.1.0", + "wrap-ansi": "^5.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/log-update/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/log-update/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/log-update/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/log-update/node_modules/wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, + "dependencies": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "node_modules/marked": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/marked/-/marked-0.3.9.tgz", + "integrity": "sha512-nW5u0dxpXxHfkHzzrveY45gCbi+R4PaO4WRZYqZNl+vB0hVGeqlFn0aOg1c8AKL63TrNFn9Bm2UP4AdiZ9TPLw==", + "dev": true, + "bin": { + "marked": "bin/marked" + } + }, + "node_modules/merge-source-map": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz", + "integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==", + "dev": true, + "dependencies": { + "source-map": "^0.6.1" + } + }, + "node_modules/microtime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/microtime/-/microtime-3.0.0.tgz", + "integrity": "sha512-SirJr7ZL4ow2iWcb54bekS4aWyBQNVcEDBiwAz9D/sTgY59A+uE8UJU15cp5wyZmPBwg/3zf8lyCJ5NUe1nVlQ==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "node-addon-api": "^1.2.0", + "node-gyp-build": "^3.8.0" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/mime-db": { + "version": "1.46.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.46.0.tgz", + "integrity": "sha512-svXaP8UQRZ5K7or+ZmfNhg2xX3yKDMUzqadsSqi4NCH/KomcH75MAMYAGVlvXn4+b/xOPhS3I2uHKRUzvjY7BQ==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.29", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.29.tgz", + "integrity": "sha512-Y/jMt/S5sR9OaqteJtslsFZKWOIIqMACsJSiHghlCAyhf7jfVYjKBmLiX8OgpWeW+fjJ2b+Az69aPFPkUOY6xQ==", + "dev": true, + "dependencies": { + "mime-db": "1.46.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "node_modules/minipass": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "node_modules/minipass/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/minipass/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "node_modules/mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)", + "dev": true, + "dependencies": { + "minimist": "0.0.8" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "node_modules/nested-error-stacks": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/nested-error-stacks/-/nested-error-stacks-2.1.0.tgz", + "integrity": "sha512-AO81vsIO1k1sM4Zrd6Hu7regmJN1NSiAja10gc4bX3F0wd+9rQmcuHQaHVQCYIEC8iFXnE+mavh23GOt7wBgug==", + "dev": true + }, + "node_modules/nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "node_modules/node-addon-api": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.7.2.tgz", + "integrity": "sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==", + "dev": true + }, + "node_modules/node-gyp-build": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-3.9.0.tgz", + "integrity": "sha512-zLcTg6P4AbcHPq465ZMFNXx7XpKKJh+7kkN699NiQWisR2uWYOWNWqRHAmbnmKiL4e9aLSlmy5U7rEMUXV59+A==", + "dev": true, + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nyc": { + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/nyc/-/nyc-14.1.1.tgz", + "integrity": "sha512-OI0vm6ZGUnoGZv/tLdZ2esSVzDwUC88SNs+6JoSOMVxA+gKMB8Tk7jBwgemLx4O40lhhvZCVw1C+OYLOBOPXWw==", + "dev": true, + "dependencies": { + "archy": "^1.0.0", + "caching-transform": "^3.0.2", + "convert-source-map": "^1.6.0", + "cp-file": "^6.2.0", + "find-cache-dir": "^2.1.0", + "find-up": "^3.0.0", + "foreground-child": "^1.5.6", + "glob": "^7.1.3", + "istanbul-lib-coverage": "^2.0.5", + "istanbul-lib-hook": "^2.0.7", + "istanbul-lib-instrument": "^3.3.0", + "istanbul-lib-report": "^2.0.8", + "istanbul-lib-source-maps": "^3.0.6", + "istanbul-reports": "^2.2.4", + "js-yaml": "^3.13.1", + "make-dir": "^2.1.0", + "merge-source-map": "^1.1.0", + "resolve-from": "^4.0.0", + "rimraf": "^2.6.3", + "signal-exit": "^3.0.2", + "spawn-wrap": "^1.4.2", + "test-exclude": "^5.2.3", + "uuid": "^3.3.2", + "yargs": "^13.2.2", + "yargs-parser": "^13.0.0" + }, + "bin": { + "nyc": "bin/nyc.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/nyc/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "dependencies": { + "mimic-fn": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/opener": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", + "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", + "dev": true, + "bin": { + "opener": "bin/opener-bin.js" + } + }, + "node_modules/optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/own-or": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/own-or/-/own-or-1.0.0.tgz", + "integrity": "sha1-Tod/vtqaLsgAD7wLyuOWRe6L+Nw=", + "dev": true + }, + "node_modules/own-or-env": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/own-or-env/-/own-or-env-1.0.1.tgz", + "integrity": "sha512-y8qULRbRAlL6x2+M0vIe7jJbJx/kmUTzYonRAa2ayesR2qWLswninkVyeJe4x3IEXhdgoNodzjQRKAoEs6Fmrw==", + "dev": true, + "dependencies": { + "own-or": "^1.0.0" + } + }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/package-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-3.0.0.tgz", + "integrity": "sha512-lOtmukMDVvtkL84rJHI7dpTYq+0rli8N2wlnqUcBuDWCfVhRUfOmnR9SsoHFMLpACvEV60dX7rd0rFaYDZI+FA==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.15", + "hasha": "^3.0.0", + "lodash.flattendeep": "^4.4.0", + "release-zalgo": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/package-hash/node_modules/graceful-fs": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", + "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==", + "dev": true + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "node_modules/path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "dependencies": { + "pify": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/path-type/node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/platform": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.5.tgz", + "integrity": "sha512-TuvHS8AOIZNAlE77WUDiR4rySV/VMptyMfcfeoMgs4P8apaZM3JrnbzBiixKUv+XR6i+BXrQh8WAnjaSPFO65Q==", + "dev": true + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/private": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true, + "optional": true + }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/prop-types": { + "version": "15.7.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", + "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "dev": true, + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.8.1" + } + }, + "node_modules/pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "node_modules/psl": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", + "dev": true + }, + "node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/react": { + "version": "16.14.0", + "resolved": "https://registry.npmjs.org/react/-/react-16.14.0.tgz", + "integrity": "sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g==", + "dev": true, + "dependencies": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true + }, + "node_modules/react-reconciler": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/react-reconciler/-/react-reconciler-0.24.0.tgz", + "integrity": "sha512-gAGnwWkf+NOTig9oOowqid9O0HjTDC+XVGBCAmJYYJ2A2cN/O4gDdIuuUQjv8A4v6GDwVfJkagpBBLW5OW9HSw==", + "dev": true, + "dependencies": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2", + "scheduler": "^0.18.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "peerDependencies": { + "react": "^16.0.0" + } + }, + "node_modules/read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "dev": true, + "dependencies": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg-up": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-4.0.0.tgz", + "integrity": "sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA==", + "dev": true, + "dependencies": { + "find-up": "^3.0.0", + "read-pkg": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "optional": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.0.3", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readdirp": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", + "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/redeyed": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/redeyed/-/redeyed-2.1.1.tgz", + "integrity": "sha1-iYS1gV2ZyyIEacme7v/jiRPmzAs=", + "dev": true, + "dependencies": { + "esprima": "~4.0.0" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", + "dev": true + }, + "node_modules/regexpp": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", + "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "node_modules/release-zalgo": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", + "integrity": "sha1-CXALflB0Mpc5Mw5TXFqQ+2eFFzA=", + "dev": true, + "dependencies": { + "es6-error": "^4.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "dev": true, + "dependencies": { + "is-finite": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", + "dev": true, + "dependencies": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/request/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "node_modules/resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dev": true, + "dependencies": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true, + "dependencies": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/rimraf/node_modules/glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", + "dev": true + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "node_modules/scheduler": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.18.0.tgz", + "integrity": "sha512-agTSHR1Nbfi6ulI0kYNK0203joW2Y5W4po4l+v03tOoiJKpTBbxpNhWDvqc/4IcOw+KLmSiQLTasZ4cab2/UWQ==", + "dev": true, + "dependencies": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + }, + "node_modules/semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "node_modules/slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/slice-ansi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/spawn-wrap": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-1.4.3.tgz", + "integrity": "sha512-IgB8md0QW/+tWqcavuFgKYR/qIRvJkRLPJDFaoXtLLUaVcCDK0+HeFTkmQHj3eprcYhc+gOl0aEA1w7qZlYezw==", + "dev": true, + "dependencies": { + "foreground-child": "^1.5.6", + "mkdirp": "^0.5.0", + "os-homedir": "^1.0.1", + "rimraf": "^2.6.2", + "signal-exit": "^3.0.2", + "which": "^1.3.0" + } + }, + "node_modules/spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dev": true, + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.7.tgz", + "integrity": "sha512-U+MTEOO0AiDzxwFvoa4JVnMV6mZlJKk2sBLt90s7G0Gd0Mlknc7kxEn3nuDPNZRta7O2uy8oLcZLVT+4sqNZHQ==", + "dev": true + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "node_modules/sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "dev": true, + "dependencies": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stack-utils": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-1.0.4.tgz", + "integrity": "sha512-IPDJfugEGbfizBwBZRZ3xpccMdRyP5lqsBWXGQWimVjua/ccLCeMOAVjlc1R7LxFjo5sEDhyNIXd8mo/AiDS9w==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "optional": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-length": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-2.0.0.tgz", + "integrity": "sha1-1A27aGo6zpYMHP/KVivyxF+DY+0=", + "dev": true, + "dependencies": { + "astral-regex": "^1.0.0", + "strip-ansi": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/string-length/node_modules/ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/string-length/node_modules/astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/string-length/node_modules/strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "dependencies": { + "ansi-regex": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "dependencies": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "dependencies": { + "ansi-regex": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/table": { + "version": "6.0.8", + "resolved": "https://registry.npmjs.org/table/-/table-6.0.8.tgz", + "integrity": "sha512-OBAdezyozae8IvjHGXBDHByVkLCcsmffXUSj8LXkNb0SluRd4ug3GFCjk6JynZONIPhOkyr0Nnvbq1rlIspXyQ==", + "dev": true, + "dependencies": { + "ajv": "^8.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "lodash.clonedeep": "^4.5.0", + "lodash.flatten": "^4.4.0", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/table/node_modules/ajv": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.0.1.tgz", + "integrity": "sha512-46ZA4TalFcLLqX1dEU3dhdY38wAtDydJ4e7QQTVekLUTzXkb1LfqU6VOBXC/a9wiv4T094WURqJH6ZitF92Kqw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/table/node_modules/ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/table/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/table/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/table/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/table/node_modules/string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/table/node_modules/strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tap": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/tap/-/tap-14.0.0.tgz", + "integrity": "sha512-4690TGCbBTwyIhJWH918o/1zLoWUqc+8o0/zQtLjFLzQ76vlurNtMfVLkVS9dNztjuv01fgol+YhNJbzg/dfUA==", + "dev": true, + "dependencies": { + "async-hook-domain": "^1.1.0", + "bind-obj-methods": "^2.0.0", + "browser-process-hrtime": "^1.0.0", + "capture-stack-trace": "^1.0.0", + "chokidar": "^3.0.0", + "color-support": "^1.1.0", + "coveralls": "^3.0.3", + "diff": "^4.0.1", + "domain-browser": "^1.2.0", + "esm": "^3.2.25", + "findit": "^2.0.0", + "foreground-child": "^1.3.3", + "fs-exists-cached": "^1.0.0", + "function-loop": "^1.0.2", + "glob": "^7.1.4", + "import-jsx": "^2.0.0", + "isexe": "^2.0.0", + "istanbul-lib-processinfo": "^1.0.0", + "jackspeak": "^1.3.8", + "minipass": "^2.3.5", + "mkdirp": "^0.5.1", + "nyc": "^14.1.0", + "opener": "^1.5.1", + "own-or": "^1.0.0", + "own-or-env": "^1.0.1", + "rimraf": "^2.6.3", + "signal-exit": "^3.0.0", + "source-map-support": "^0.5.12", + "stack-utils": "^1.0.2", + "tap-mocha-reporter": "^4.0.1", + "tap-parser": "^9.3.2", + "tap-yaml": "^1.0.0", + "tcompare": "^2.3.0", + "treport": "^0.3.0", + "trivial-deferred": "^1.0.1", + "ts-node": "^8.1.0", + "typescript": "^3.4.5", + "which": "^1.3.1", + "write-file-atomic": "^2.4.2", + "yaml": "^1.5.1", + "yapool": "^1.0.0" + }, + "bin": { + "tap": "bin/run.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tap-mocha-reporter": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/tap-mocha-reporter/-/tap-mocha-reporter-4.0.1.tgz", + "integrity": "sha512-/KfXaaYeSPn8qBi5Be8WSIP3iKV83s2uj2vzImJAXmjNu22kzqZ+1Dv1riYWa53sPCiyo1R1w1jbJrftF8SpcQ==", + "dev": true, + "dependencies": { + "color-support": "^1.1.0", + "debug": "^2.1.3", + "diff": "^1.3.2", + "escape-string-regexp": "^1.0.3", + "glob": "^7.0.5", + "tap-parser": "^8.0.0", + "tap-yaml": "0 || 1", + "unicode-length": "^1.0.0" + }, + "bin": { + "tap-mocha-reporter": "index.js" + }, + "optionalDependencies": { + "readable-stream": "^2.1.5" + } + }, + "node_modules/tap-mocha-reporter/node_modules/diff": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-1.4.0.tgz", + "integrity": "sha1-fyjS657nsVqX79ic5j3P2qPMur8=", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/tap-mocha-reporter/node_modules/tap-parser": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/tap-parser/-/tap-parser-8.1.0.tgz", + "integrity": "sha512-GgOzgDwThYLxhVR83RbS1JUR1TxcT+jfZsrETgPAvFdr12lUOnuvrHOBaUQgpkAp6ZyeW6r2Nwd91t88M0ru3w==", + "dev": true, + "dependencies": { + "events-to-array": "^1.0.1", + "minipass": "^2.2.0", + "tap-yaml": "0 || 1" + }, + "bin": { + "tap-parser": "bin/cmd.js" + } + }, + "node_modules/tap-parser": { + "version": "9.3.3", + "resolved": "https://registry.npmjs.org/tap-parser/-/tap-parser-9.3.3.tgz", + "integrity": "sha512-VlC7tlSZ3EGt2qPLSa9CTJepNkc2yCh7uzhzAF5DxnuujeKbFbKxMA+fxtTWEN2j/KgfGi+mgooiZPKkOhEQyw==", + "dev": true, + "dependencies": { + "events-to-array": "^1.0.1", + "minipass": "^2.2.0", + "tap-yaml": "^1.0.0" + }, + "bin": { + "tap-parser": "bin/cmd.js" + } + }, + "node_modules/tap-yaml": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/tap-yaml/-/tap-yaml-1.0.0.tgz", + "integrity": "sha512-Rxbx4EnrWkYk0/ztcm5u3/VznbyFJpyXO12dDBHKWiDVxy7O2Qw6MRrwO5H6Ww0U5YhRY/4C/VzWmFPhBQc4qQ==", + "dev": true, + "dependencies": { + "yaml": "^1.5.0" + } + }, + "node_modules/tap/node_modules/typescript": { + "version": "3.9.9", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.9.tgz", + "integrity": "sha512-kdMjTiekY+z/ubJCATUPlRDl39vXYiMV9iyeMuEuXZh2we6zz80uovNN2WlAxmmdE/Z/YQe+EbOEXB5RHEED3w==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/tcompare": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tcompare/-/tcompare-2.3.0.tgz", + "integrity": "sha512-fAfA73uFtFGybWGt4+IYT6UPLYVZQ4NfsP+IXEZGY0vh8e2IF7LVKafcQNMRBLqP0wzEA65LM9Tqj+FSmO8GLw==", + "dev": true + }, + "node_modules/test-exclude": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.3.tgz", + "integrity": "sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g==", + "dev": true, + "dependencies": { + "glob": "^7.1.3", + "minimatch": "^3.0.4", + "read-pkg-up": "^4.0.0", + "require-main-filename": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "node_modules/to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dev": true, + "dependencies": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/treport": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/treport/-/treport-0.3.0.tgz", + "integrity": "sha512-THr7NS5iLJewcAiaBkxAuCVoakw84hAVY9n2kFNZqlFKHrZeGw8sNR4VhmT23JB1/JnCmPcIOmooTdYYVTI5hA==", + "dev": true, + "dependencies": { + "cardinal": "^2.1.1", + "chalk": "^2.4.2", + "import-jsx": "^2.0.0", + "ink": "^2.1.1", + "ms": "^2.1.1", + "react": "^16.8.6", + "string-length": "^2.0.0", + "tap-parser": "^9.3.2", + "unicode-length": "^2.0.1" + } + }, + "node_modules/treport/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/treport/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/treport/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/treport/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/treport/node_modules/unicode-length": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unicode-length/-/unicode-length-2.0.2.tgz", + "integrity": "sha512-Ph/j1VbS3/r77nhoY2WU0GWGjVYOHL3xpKp0y/Eq2e5r0mT/6b649vm7KFO6RdAdrZkYLdxphYVgvODxPB+Ebg==", + "dev": true, + "dependencies": { + "punycode": "^2.0.0", + "strip-ansi": "^3.0.1" + } + }, + "node_modules/trim-right": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/trivial-deferred": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trivial-deferred/-/trivial-deferred-1.0.1.tgz", + "integrity": "sha1-N21NKdlR1jaKb3oK6FwvTV4GWPM=", + "dev": true + }, + "node_modules/ts-node": { + "version": "8.10.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.10.2.tgz", + "integrity": "sha512-ISJJGgkIpDdBhWVu3jufsWpK3Rzo7bdiIXJjQc0ynKxVOVcg2oIrf2H2cejminGrptVc6q6/uynAHNCuWGbpVA==", + "dev": true, + "dependencies": { + "arg": "^4.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "source-map-support": "^0.5.17", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "engines": { + "node": ">=6.0.0" + }, + "peerDependencies": { + "typescript": ">=2.7" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz", + "integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.4.tgz", + "integrity": "sha512-V+evlYHZnQkaz8TRBuxTA92yZBPotr5H+WhQ7bD3hZUndx5tGOa1fuCgeSjxAzM1RiN5IzvadIXTVefuuwZCRg==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=", + "dev": true + }, + "node_modules/unicode-length": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/unicode-length/-/unicode-length-1.0.3.tgz", + "integrity": "sha1-Wtp6f+1RhBpBijKM8UlHisg1irs=", + "dev": true, + "dependencies": { + "punycode": "^1.3.2", + "strip-ansi": "^3.0.1" + } + }, + "node_modules/unicode-length/node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, + "node_modules/universalify": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.1.tgz", + "integrity": "sha1-+nG63UQ3r0wUiEHjs7Fl+enlkLc=", + "dev": true + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true, + "optional": true + }, + "node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "dev": true, + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/v8-compile-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "dev": true + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "node_modules/widest-line": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "dev": true, + "dependencies": { + "string-width": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/widest-line/node_modules/ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/widest-line/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/widest-line/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/widest-line/node_modules/string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/widest-line/node_modules/strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "dependencies": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi/node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "node_modules/write-file-atomic": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", + "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, + "node_modules/y18n": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz", + "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==", + "dev": true + }, + "node_modules/yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + }, + "node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/yapool": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/yapool/-/yapool-1.0.0.tgz", + "integrity": "sha1-9pPymjFbUNmp2iZGp6ZkXJaYW2o=", + "dev": true + }, + "node_modules/yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "dev": true, + "dependencies": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + } + }, + "node_modules/yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "dev": true, + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "node_modules/yargs/node_modules/ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/yargs/node_modules/cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "dependencies": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "node_modules/yargs/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/yoga-layout-prebuilt": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/yoga-layout-prebuilt/-/yoga-layout-prebuilt-1.10.0.tgz", + "integrity": "sha512-YnOmtSbv4MTf7RGJMK0FvZ+KD8OEe/J5BNnR0GHhD8J/XcG/Qvxgszm0Un6FTHWW4uHlTgP0IztiXQnGyIR45g==", + "dev": true, + "dependencies": { + "@types/yoga-layout": "1.9.2" + }, + "engines": { + "node": ">=8" + } + } + }, "dependencies": { "@babel/code-frame": { "version": "7.12.13", @@ -271,7 +5807,8 @@ "version": "5.3.1", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", - "dev": true + "dev": true, + "requires": {} }, "ajv": { "version": "6.12.6", @@ -3643,6 +9180,16 @@ } } }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, "string-length": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/string-length/-/string-length-2.0.0.tgz", @@ -3703,16 +9250,6 @@ } } }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, "strip-ansi": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", diff --git a/src/memjs/memjs.ts b/src/memjs/memjs.ts index b509c4f..acbfd28 100644 --- a/src/memjs/memjs.ts +++ b/src/memjs/memjs.ts @@ -909,14 +909,19 @@ class Client { * in the backend pool, errors if any one of them has an * error */ - async versionAll(): Promise<{ + async versionAll(triedCallback?: (response: string) => void, resultCallback?: (response: string) => void): Promise<{ values: Record; }> { const versionObjects = await Promise.all( this.serverKeys.map((serverKey) => { + if (triedCallback !== undefined) { + triedCallback(serverKey); + } const server = this.serverKeyToServer(serverKey); - return this._version(server).then((response) => { + if (resultCallback !== undefined) { + resultCallback(serverKey); + } return { serverKey: serverKey, value: response.value }; }); }) From 9a781ea39ea3381de170f4a49174d03dc7c8c420 Mon Sep 17 00:00:00 2001 From: Arturo Olvera Date: Mon, 6 Feb 2023 10:27:10 -0800 Subject: [PATCH 62/79] readme, gitignore, linting --- .gitignore | 3 +++ README.md | 37 +++++++++++++++++++++++++++++++++++++ src/memjs/memjs.ts | 40 ++++++++++++++++++++++++---------------- 3 files changed, 64 insertions(+), 16 deletions(-) diff --git a/.gitignore b/.gitignore index 55d8413..1a7b8f6 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,6 @@ lib/test node_modules npm-debug.log .nyc_output/ + +.vscode +.DS_Store* \ No newline at end of file diff --git a/README.md b/README.md index fe73bd9..dbe2f53 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,43 @@ MemJS [![Build Status](https://secure.travis-ci.org/alevy/memjs.png)](http://travis-ci.org/alevy/memjs?branch=master) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/alevy/memjs?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) +--- + +Notion fork of MemJS + +## Making Changes + +see [this](https://dev.notion.so/notion/Developing-dependencies-locally-6705f66af9a24944ac875c44234e68f1) doc + +**Linking** + +Clone `memjs`, run `npm install`, link `memjs` to local Notion: + +``` +cd ~/memjs +npm link + +cd ~/notion-next +npm link memjs +``` + +**Developing** + +Run `npx tsc --watch` in the `memjs` directory. + +**Unlinking** + +``` +cd ~/notion-next +npm unlink --no-save package-js + +cd ~/package-js/ +npm unlink +``` + +--- + + MemJS is a pure Node.js client library for using memcache, in particular, the [MemCachier](http://memcachier.com/) service. It uses the binary protocol and support SASL authentication. diff --git a/src/memjs/memjs.ts b/src/memjs/memjs.ts index acbfd28..6f93166 100644 --- a/src/memjs/memjs.ts +++ b/src/memjs/memjs.ts @@ -61,21 +61,17 @@ interface SerializerProp { /** * The client has partial support for serializing and deserializing values from the - * Buffer byte strings we recieve from the wire. The default serializer is for MaybeBuffer. + * Buffer byte strings we receive from the wire. The default serializer is for MaybeBuffer. * * If Value and Extras are of type Buffer, then return type WhenBuffer. Otherwise, * return type NotBuffer. */ -type IfBuffer< - Value, - Extras, - WhenValueAndExtrasAreBuffers, - NotBuffer -> = Value extends Buffer - ? Extras extends Buffer - ? WhenValueAndExtrasAreBuffers - : NotBuffer - : NotBuffer; +type IfBuffer = + Value extends Buffer + ? Extras extends Buffer + ? WhenValueAndExtrasAreBuffers + : NotBuffer + : NotBuffer; export type GivenClientOptions = Partial & IfBuffer< @@ -313,7 +309,10 @@ class Client { // This isn't technically needed here because the logic in server.js also checks if totalBodyLength === 0, but our unittests aren't great about setting that field, and also this makes it more explicit handle.quiet = false; resolve(responseMap); - } else if (response.header.opcode === constants.OP_GETK || response.header.opcode === constants.OP_GETKQ) { + } else if ( + response.header.opcode === constants.OP_GETK || + response.header.opcode === constants.OP_GETKQ + ) { const deserialized = this.serializer.deserialize( response.header.opcode, response.val, @@ -322,13 +321,19 @@ class Client { const key = response.key.toString(); if (key.length === 0) { return reject( - new Error("Recieved empty key in getMulti: " + JSON.stringify(response)) + new Error( + "Recieved empty key in getMulti: " + + JSON.stringify(response) + ) ); } responseMap[key] = { ...deserialized, cas: response.header.cas }; } else { return reject( - new Error("Recieved response in getMulti for unknown opcode: " + JSON.stringify(response)) + new Error( + "Recieved response in getMulti for unknown opcode: " + + JSON.stringify(response) + ) ); } break; @@ -909,7 +914,10 @@ class Client { * in the backend pool, errors if any one of them has an * error */ - async versionAll(triedCallback?: (response: string) => void, resultCallback?: (response: string) => void): Promise<{ + async versionAll( + triedCallback?: (response: string) => void, + resultCallback?: (response: string) => void + ): Promise<{ values: Record; }> { const versionObjects = await Promise.all( @@ -1034,7 +1042,7 @@ class Client { // Wrap `this.seq` to 32-bits since the field we fit it into is only 32-bits. this.seq &= 0xffffffff; - return this.seq + return this.seq; } private createAndLogError( From 59493e2a55a9e0a189ec11da6b1266d53690c293 Mon Sep 17 00:00:00 2001 From: Arturo Olvera Date: Mon, 6 Feb 2023 14:07:45 -0800 Subject: [PATCH 63/79] naming and notation --- lib/memjs/memjs.d.ts | 7 +++++-- lib/memjs/memjs.d.ts.map | 2 +- lib/memjs/memjs.js | 23 ++++++++++++----------- src/memjs/memjs.ts | 16 ++++++---------- 4 files changed, 24 insertions(+), 24 deletions(-) diff --git a/lib/memjs/memjs.d.ts b/lib/memjs/memjs.d.ts index b62c300..e97d877 100644 --- a/lib/memjs/memjs.d.ts +++ b/lib/memjs/memjs.d.ts @@ -20,7 +20,7 @@ interface SerializerProp { } /** * The client has partial support for serializing and deserializing values from the - * Buffer byte strings we recieve from the wire. The default serializer is for MaybeBuffer. + * Buffer byte strings we receive from the wire. The default serializer is for MaybeBuffer. * * If Value and Extras are of type Buffer, then return type WhenBuffer. Otherwise, * return type NotBuffer. @@ -273,7 +273,10 @@ declare class Client { * in the backend pool, errors if any one of them has an * error */ - versionAll(triedCallback?: (response: string) => void, resultCallback?: (response: string) => void): Promise<{ + versionAll(callbacks?: { + beforePing?: (response: string) => void; + afterPing?: (response: string) => void; + }): Promise<{ values: Record; }>; /** diff --git a/lib/memjs/memjs.d.ts.map b/lib/memjs/memjs.d.ts.map index 2af5f5a..1a2be61 100644 --- a/lib/memjs/memjs.d.ts.map +++ b/lib/memjs/memjs.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"memjs.d.ts","sourceRoot":"","sources":["../../src/memjs/memjs.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"memjs.d.ts","sourceRoot":"","sources":["../../src/memjs/memjs.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/lib/memjs/memjs.js b/lib/memjs/memjs.js index e057eda..759d1f7 100644 --- a/lib/memjs/memjs.js +++ b/lib/memjs/memjs.js @@ -199,16 +199,19 @@ class Client { handle.quiet = false; resolve(responseMap); } - else if (response.header.opcode === constants.OP_GETK || response.header.opcode === constants.OP_GETKQ) { + else if (response.header.opcode === constants.OP_GETK || + response.header.opcode === constants.OP_GETKQ) { const deserialized = this.serializer.deserialize(response.header.opcode, response.val, response.extras); const key = response.key.toString(); if (key.length === 0) { - return reject(new Error("Recieved empty key in getMulti: " + JSON.stringify(response))); + return reject(new Error("Recieved empty key in getMulti: " + + JSON.stringify(response))); } responseMap[key] = { ...deserialized, cas: response.header.cas }; } else { - return reject(new Error("Recieved response in getMulti for unknown opcode: " + JSON.stringify(response))); + return reject(new Error("Recieved response in getMulti for unknown opcode: " + + JSON.stringify(response))); } break; default: @@ -627,16 +630,14 @@ class Client { * in the backend pool, errors if any one of them has an * error */ - async versionAll(triedCallback, resultCallback) { + async versionAll(callbacks) { const versionObjects = await Promise.all(this.serverKeys.map((serverKey) => { - if (triedCallback !== undefined) { - triedCallback(serverKey); - } + var _a; const server = this.serverKeyToServer(serverKey); + (_a = callbacks === null || callbacks === void 0 ? void 0 : callbacks.beforePing) === null || _a === void 0 ? void 0 : _a.call(callbacks, serverKey); return this._version(server).then((response) => { - if (resultCallback !== undefined) { - resultCallback(serverKey); - } + var _a; + (_a = callbacks === null || callbacks === void 0 ? void 0 : callbacks.afterPing) === null || _a === void 0 ? void 0 : _a.call(callbacks, serverKey); return { serverKey: serverKey, value: response.value }; }); })); @@ -738,4 +739,4 @@ class Client { } } exports.Client = Client; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVtanMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbWVtanMvbWVtanMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLHdCQUF3Qjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUV4QixxQ0FLa0I7QUFvaUNELHVGQXRpQ2YsZUFBTSxPQXNpQ2U7QUFuaUN2Qix1REFBK0Q7QUFDL0QsbUNBU2lCO0FBQ2pCLHVEQUF5QztBQUN6QywyQ0FBNkM7QUFDN0MsK0NBQWlDO0FBc2hDUixzQkFBSztBQXJoQzlCLGlEQUFtQztBQXFoQ0gsd0JBQU07QUFuaEN0QyxTQUFTLDhCQUE4QixDQUNyQyxPQUFpQixFQUNqQixHQUFXO0lBRVgsTUFBTSxLQUFLLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQztJQUM3QixNQUFNLEtBQUssR0FBRyxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxnQkFBUSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3BELE9BQU8sT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ3hCLENBQUM7QUFFRCwrQ0FBK0M7QUFDL0MsU0FBUyxTQUFTLENBQ2hCLE9BQTBFO0lBRTFFLE9BQU8sSUFBSSxPQUFPLENBQUMsVUFBVSxPQUFPLEVBQUUsTUFBTTtRQUMxQyxPQUFPLENBQUMsVUFBVSxHQUFHLEVBQUUsTUFBTTtZQUMzQixHQUFHLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3RDLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBNkRELE1BQU0sTUFBTTtJQVFWLDRFQUE0RTtJQUM1RSxtQ0FBbUM7SUFDbkMsWUFBWSxPQUFpQixFQUFFLE9BQTBDO1FBQ3ZFLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO1FBQ3ZCLElB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MUMsTUFBTSxZQUFZLEdBQUcsU0FBUyxXQUFXLEtBQUssU0FBUyxDQUFDLHNCQUFzQixDQUM1RSxjQUFjLENBQ2YsRUFBRSxDQUFDO1FBQ0osSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLFlBQVksQ0FBQyxDQUFDO1FBQ3RDLE9BQU8sSUFBSSxLQUFLLENBQUMsWUFBWSxDQUFDLENBQUM7SUFDakMsQ0FBQztJQUVEOzs7T0FHRztJQUNLLG1CQUFtQixDQUN6QixXQUFtQixFQUNuQixjQUEwQyxFQUMxQyxRQUFrRTtRQUVsRSxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsaUJBQWlCLENBQUMsV0FBVyxFQUFFLGNBQWMsQ0FBQyxDQUFDO1FBQ2xFLElBQUksUUFBUSxFQUFFO1lBQ1osUUFBUSxDQUFDLEtBQUssRUFBRSxJQUFJLENBQUMsQ0FBQztTQUN2QjtRQUNELE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQztDQUNGO0FBRVEsd0JBQU0iLCJzb3VyY2VzQ29udGVudCI6WyIvLyBNZW1UUyBNZW1jYWNoZSBDbGllbnRcblxuaW1wb3J0IHtcbiAgT25FcnJvckNhbGxiYWNrLFxuICBPblJlc3BvbnNlQ2FsbGJhY2ssXG4gIFNlcnZlcixcbiAgU2VydmVyT3B0aW9ucyxcbn0gZnJvbSBcIi4vc2VydmVyXCI7XG5pbXBvcnQgeyBub29wU2VyaWFsaXplciwgU2VyaWFsaXplciB9IGZyb20gXCIuL25vb3Atc2VyaWFsaXplclwiO1xuaW1wb3J0IHtcbiAgbWFrZVJlcXVlc3RCdWZmZXIsXG4gIGNvcHlJbnRvUmVxdWVzdEJ1ZmZlcixcbiAgbWVyZ2UsXG4gIG1ha2VFeHBpcmF0aW9uLFxuICBtYWtlQW1vdW50SW5pdGlhbEFuZEV4cGlyYXRpb24sXG4gIGhhc2hDb2RlLFxuICBNYXliZUJ1ZmZlcixcbiAgTWVzc2FnZSxcbn0gZnJvbSBcIi4vdXRpbHNcIjtcbmltcG9ydCAqIGFzIGNvbnN0YW50cyBmcm9tIFwiLi9jb25zdGFudHNcIjtcbmltcG9ydCB7IFJlc3BvbnNlU3RhdHVzIH0gZnJvbSBcIi4vY29uc3RhbnRzXCI7XG5pbXBvcnQgKiBhcyBVdGlscyBmcm9tIFwiLi91dGlsc1wiO1xuaW1wb3J0ICogYXMgSGVhZGVyIGZyb20gXCIuL2hlYWRlclwiO1xuXG5mdW5jdGlvbiBkZWZhdWx0S2V5VG9TZXJ2ZXJIYXNoRnVuY3Rpb24oXG4gIHNlcnZlcnM6IHN0cmluZ1tdLFxuICBrZXk6IHN0cmluZ1xuKTogc3RyaW5nIHtcbiAgY29uc3QgdG90YWwgPSBzZXJ2ZXJzLmxlbmd0aDtcbiAgY29uc3QgaW5kZXggPSB0b3RhbCA+IDEgPyBoYXNoQ29kZShrZXkpICUgdG90YWwgOiAwO1xuICByZXR1cm4gc2VydmVyc1tpbmRleF07XG59XG5cbi8vIGNvbnZlcnRzIGEgY2FsbCBpbnRvIGEgcHJvbWlzZS1yZXR1cm5pbmcgb25lXG5mdW5jdGlvbiBwcm9taXNpZnk8UmVzdWx0PihcbiAgY29tbWFuZDogKGNhbGxiYWNrOiAoZXJyb3I6IEVycm9yIHwgbnVsbCwgcmVzdWx0OiBSZXN1bHQpID0+IHZvaWQpID0+IHZvaWRcbik6IFByb21pc2U8UmVzdWx0PiB7XG4gIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgY29tbWFuZChmdW5jdGlvbiAoZXJyLCByZXN1bHQpIHtcbiAgICAgIGVyciA/IHJlamVjdChlcnIpIDogcmVzb2x2ZShyZXN1bHQpO1xuICAgIH0pO1xuICB9KTtcbn1cblxudHlwZSBSZXNwb25zZU9yRXJyb3JDYWxsYmFjayA9IChcbiAgZXJyb3I6IEVycm9yIHwgbnVsbCxcbiAgcmVzcG9uc2U6IE1lc3NhZ2UgfCBudWxsXG4pID0+IHZvaWQ7XG5cbmludGVyZmFjZSBCYXNlQ2xpZW50T3B0aW9ucyB7XG4gIHJldHJpZXM6IG51bWJlcjtcbiAgcmV0cnlfZGVsYXk6IG51bWJlcjtcbiAgZXhwaXJlczogbnVtYmVyO1xuICBsb2dnZXI6IHsgbG9nOiB0eXBlb2YgY29uc29sZS5sb2cgfTtcbiAga2V5VG9TZXJ2ZXJIYXNoRnVuY3Rpb246IHR5cGVvZiBkZWZhdWx0S2V5VG9TZXJ2ZXJIYXNoRnVuY3Rpb247XG59XG5cbmludGVyZmFjZSBTZXJpYWxpemVyUHJvcDxWYWx1ZSwgRXh0cmFzPiB7XG4gIHNlcmlhbGl6ZXI6IFNlcmlhbGl6ZXI8VmFsdWUsIEV4dHJhcz47XG59XG5cbi8qKlxuICogVGhlIGNsaWVudCBoYXMgcGFydGlhbCBzdXBwb3J0IGZvciBzZXJpYWxpemluZyBhbmQgZGVzZXJpYWxpemluZyB2YWx1ZXMgZnJvbSB0aGVcbiAqIEJ1ZmZlciBieXRlIHN0cmluZ3Mgd2UgcmVjaWV2ZSBmcm9tIHRoZSB3aXJlLiBUaGUgZGVmYXVsdCBzZXJpYWxpemVyIGlzIGZvciBNYXliZUJ1ZmZlci5cbiAqXG4gKiBJZiBWYWx1ZSBhbmQgRXh0cmFzIGFyZSBvZiB0eXBlIEJ1ZmZlciwgdGhlbiByZXR1cm4gdHlwZSBXaGVuQnVmZmVyLiBPdGhlcndpc2UsXG4gKiByZXR1cm4gdHlwZSBOb3RCdWZmZXIuXG4gKi9cbnR5cGUgSWZCdWZmZXI8XG4gIFZhbHVlLFxuICBFeHRyYXMsXG4gIFdoZW5WYWx1ZUFuZEV4dHJhc0FyZUJ1ZmZlcnMsXG4gIE5vdEJ1ZmZlclxuPiA9IFZhbHVlIGV4dGVuZHMgQnVmZmVyXG4gID8gRXh0cmFzIGV4dGVuZHMgQnVmZmVyXG4gICAgPyBXaGVuVmFsdWVBbmRFeHRyYXNBcmVCdWZmZXJzXG4gICAgOiBOb3RCdWZmZXJcbiAgOiBOb3RCdWZmZXI7XG5cbmV4cG9ydCB0eXBlIEdpdmVuQ2xpZW50T3B0aW9uczxWYWx1ZSwgRXh0cmFzPiA9IFBhcnRpYWw8QmFzZUNsaWVudE9wdGlvbnM+ICZcbiAgSWZCdWZmZXI8XG4gICAgVmFsdWUsXG4gICAgRXh0cmFzLFxuICAgIFBhcnRpYWw8U2VyaWFsaXplclByb3A8VmFsdWUsIEV4dHJhcz4+LFxuICAgIFNlcmlhbGl6ZXJQcm9wPFZhbHVlLCBFeHRyYXM+XG4gID47XG5cbmV4cG9ydCB0eXBlIENBU1Rva2VuID0gQnVmZmVyO1xuXG5leHBvcnQgaW50ZXJmYWNlIEdldFJlc3VsdDxWYWx1ZSA9IE1heWJlQnVmZmVyLCBFeHRyYXMgPSBNYXliZUJ1ZmZlcj4ge1xuICB2YWx1ZTogVmFsdWU7XG4gIGV4dHJhczogRXh0cmFzO1xuICBjYXM6IENBU1Rva2VuIHwgdW5kZWZpbmVkO1xufVxuXG5leHBvcnQgdHlwZSBHZXRNdWx0aVJlc3VsdDxcbiAgS2V5cyBleHRlbmRzIHN0cmluZyA9IHN0cmluZyxcbiAgVmFsdWUgPSBNYXliZUJ1ZmZlcixcbiAgRXh0cmFzID0gTWF5YmVCdWZmZXJcbj4gPSB7XG4gIFtLIGluIEtleXNdPzogR2V0UmVzdWx0PFZhbHVlLCBFeHRyYXM+O1xufTtcblxuY2xhc3MgQ2xpZW50PFZhbHVlID0gTWF5YmVCdWZmZXIsIEV4dHJhcyA9IE1heWJlQnVmZmVyPiB7XG4gIHNlcnZlcnM6IFNlcnZlcltdO1xuICBzZXE6IG51bWJlcjtcbiAgb3B0aW9uczogQmFzZUNsaWVudE9wdGlvbnMgJiBQYXJ0aWFsPFNlcmlhbGl6ZXJQcm9wPFZhbHVlLCBFeHRyYXM+PjtcbiAgc2VyaWFsaXplcjogU2VyaWFsaXplcjxWYWx1ZSwgRXh0cmFzPjtcbiAgc2VydmVyTWFwOiB7IFtob3N0cG9ydDogc3RyaW5nXTogU2VydmVyIH07XG4gIHNlcnZlcktleXM6IHN0cmluZ1tdO1xuXG4gIC8vIENsaWVudCBpbml0aWFsaXplciB0YWtlcyBhIGxpc3Qgb2YgYFNlcnZlcmBzIGFuZCBhbiBgb3B0aW9uc2AgZGljdGlvbmFyeS5cbiAgLy8gU2VlIGBDbGllbnQuY3JlYXRlYCBmb3IgZGV0YWlscy5cbiAgY29uc3RydWN0b3Ioc2VydmVyczogU2VydmVyW10sIG9wdGlvbnM6IEdpdmVuQ2xpZW50T3B0aW9uczxWYWx1ZSwgRXh0cmFzPikge1xuICAgIHRoaXMuc2VydmVycyA9IHNlcnZlcnM7XG4gICAgdGhpcy5zZXEgPSAwO1xuICAgIHRoaXMub3B0aW9ucyA9IG1lcmdlKG9wdGlvbnMgfHwge30sIHtcbiAgICAgIHJldHJpZXM6IDIsXG4gICAgICByZXRyeV9kZWxheTogMC4yLFxuICAgICAgZXhwaXJlczogMCxcbiAgICAgIGxvZ2dlcjogY29uc29sZSxcbiAgICAgIGtleVRvU2VydmVySGFzaEZ1bmN0aW9uOiBkZWZhdWx0S2V5VG9TZXJ2ZXJIYXNoRnVuY3Rpb24sXG4gICAgfSk7XG5cbiAgICB0aGlzLnNlcmlhbGl6ZXIgPSB0aGlzLm9wdGlvbnMuc2VyaWFsaXplciB8fCAobm9vcFNlcmlhbGl6ZXIgYXMgYW55KTtcblxuICAgIC8vIFN0b3JlIGEgbWFwcGluZyBmcm9tIGhvc3Rwb3J0IC0+IHNlcnZlciBzbyB3ZSBjYW4gcXVpY2tseSBnZXQgYSBzZXJ2ZXIgb2JqZWN0IGZyb20gdGhlIHNlcnZlcktleSByZXR1cm5lZCBieSB0aGUgaGFzaGluZyBmdW5jdGlvblxuICAgIGNvbnN0IHNlcnZlck1hcDogeyBbaG9zdHBvcnQ6IHN0cmluZ106IFNlcnZlciB9ID0ge307XG4gICAgdGhpcy5zZXJ2ZXJzLmZvckVhY2goZnVuY3Rpb24gKHNlcnZlcikge1xuICAgICAgc2VydmVyTWFwW3NlcnZlci5ob3N0cG9ydFN0cmluZygpXSA9IHNlcnZlcjtcbiAgICB9KTtcbiAgICB0aGlzLnNlcnZlck1hcCA9IHNlcnZlck1hcDtcblxuICAgIC8vIHN0b3JlIGEgbGlzdCBvZiBhbGwgb3VyIHNlcnZlcktleXMgc28gd2UgZG9uJ3QgbmVlZCB0byBjb25zdGFudGx5IHJlYWxsb2NhdGUgdGhpcyBhcnJheVxuICAgIHRoaXMuc2VydmVyS2V5cyA9IE9iamVjdC5rZXlzKHRoaXMuc2VydmVyTWFwKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgbmV3IGNsaWVudCBnaXZlbiBhbiBvcHRpb25hbCBjb25maWcgc3RyaW5nIGFuZCBvcHRpb25hbCBoYXNoIG9mXG4gICAqIG9wdGlvbnMuIFRoZSBjb25maWcgc3RyaW5nIHNob3VsZCBiZSBvZiB0aGUgZm9ybTpcbiAgICpcbiAgICogICAgIFwiW3VzZXI6cGFzc0Bdc2VydmVyMVs6MTEyMTFdLFt1c2VyOnBhc3NAXXNlcnZlcjJbOjExMjExXSwuLi5cIlxuICAgKlxuICAgKiBJZiB0aGUgYXJndW1lbnQgaXMgbm90IGdpdmVuLCBmYWxsYmFjayBvbiB0aGUgYE1FTUNBQ0hJRVJfU0VSVkVSU2AgZW52aXJvbm1lbnRcbiAgICogdmFyaWFibGUsIGBNRU1DQUNIRV9TRVJWRVJTYCBlbnZpcm9ubWVudCB2YXJpYWJsZSBvciBgXCJsb2NhbGhvc3Q6MTEyMTFcImAuXG4gICAqXG4gICAqIFRoZSBvcHRpb25zIGhhc2ggbWF5IGNvbnRhaW4gdGhlIG9wdGlvbnM6XG4gICAqXG4gICAqICogYHJldHJpZXNgIC0gdGhlIG51bWJlciBvZiB0aW1lcyB0byByZXRyeSBhbiBvcGVyYXRpb24gaW4gbGlldSBvZiBmYWlsdXJlc1xuICAgKiAoZGVmYXVsdCAyKVxuICAgKiAqIGBleHBpcmVzYCAtIHRoZSBkZWZhdWx0IGV4cGlyYXRpb24gaW4gc2Vjb25kcyB0byB1c2UgKGRlZmF1bHQgMCAtIG5ldmVyXG4gICAqIGV4cGlyZSkuIElmIGBleHBpcmVzYCBpcyBncmVhdGVyIHRoYW4gMzAgZGF5cyAoNjAgeCA2MCB4IDI0IHggMzApLCBpdCBpc1xuICAgKiB0cmVhdGVkIGFzIGEgVU5JWCB0aW1lIChudW1iZXIgb2Ygc2Vjb25kcyBzaW5jZSBKYW51YXJ5IDEsIDE5NzApLlxuICAgKiAqIGBsb2dnZXJgIC0gYSBsb2dnZXIgb2JqZWN0IHRoYXQgcmVzcG9uZHMgdG8gYGxvZyhzdHJpbmcpYCBtZXRob2QgY2FsbHMuXG4gICAqXG4gICAqICAgfn5+flxuICAgKiAgICAgbG9nKG1zZzFbLCBtc2cyWywgbXNnM1suLi5dXV0pXG4gICAqICAgfn5+flxuICAgKlxuICAgKiAgIERlZmF1bHRzIHRvIGBjb25zb2xlYC5cbiAgICogKiBgc2VyaWFsaXplcmAgLSB0aGUgb2JqZWN0IHdoaWNoIHdpbGwgKGRlKXNlcmlhbGl6ZSB0aGUgZGF0YS4gSXQgbmVlZHNcbiAgICogICB0d28gcHVibGljIG1ldGhvZHM6IHNlcmlhbGl6ZSBhbmQgZGVzZXJpYWxpemUuIEl0IGRlZmF1bHRzIHRvIHRoZVxuICAgKiAgIG5vb3BTZXJpYWxpemVyOlxuICAgKlxuICAgKiAgIH5+fn5cbiAgICogICBjb25zdCBub29wU2VyaWFsaXplciA9IHtcbiAgICogICAgIHNlcmlhbGl6ZTogZnVuY3Rpb24gKG9wY29kZSwgdmFsdWUsIGV4dHJhcykge1xuICAgKiAgICAgICByZXR1cm4geyB2YWx1ZTogdmFsdWUsIGV4dHJhczogZXh0cmFzIH07XG4gICAqICAgICB9LFxuICAgKiAgICAgZGVzZXJpYWxpemU6IGZ1bmN0aW9uIChvcGNvZGUsIHZhbHVlLCBleHRyYXMpIHtcbiAgICogICAgICAgcmV0dXJuIHsgdmFsdWU6IHZhbHVlLCBleHRyYXM6IGV4dHJhcyB9O1xuICAgKiAgICAgfVxuICAgKiAgIH07XG4gICAqICAgfn5+flxuICAgKlxuICAgKiBPciBvcHRpb25zIGZvciB0aGUgc2VydmVycyBpbmNsdWRpbmc6XG4gICAqICogYHVzZXJuYW1lYCBhbmQgYHBhc3N3b3JkYCBmb3IgZmFsbGJhY2sgU0FTTCBhdXRoZW50aWNhdGlvbiBjcmVkZW50aWFscy5cbiAgICogKiBgdGltZW91dGAgaW4gc2Vjb25kcyB0byBkZXRlcm1pbmUgZmFpbHVyZSBmb3Igb3BlcmF0aW9ucy4gRGVmYXVsdCBpcyAwLjVcbiAgICogICAgICAgICAgICAgc2Vjb25kcy5cbiAgICogKiAnY29ubnRpbWVvdXQnIGluIHNlY29uZHMgdG8gY29ubmVjdGlvbiBmYWlsdXJlLiBEZWZhdWx0IGlzIHR3aWNlIHRoZSB2YWx1ZVxuICAgKiAgICAgICAgICAgICAgICAgb2YgYHRpbWVvdXRgLlxuICAgKiAqIGBrZWVwQWxpdmVgIHdoZXRoZXIgdG8gZW5hYmxlIGtlZXAtYWxpdmUgZnVuY3Rpb25hbGl0eS4gRGVmYXVsdHMgdG8gZmFsc2UuXG4gICAqICogYGtlZXBBbGl2ZURlbGF5YCBpbiBzZWNvbmRzIHRvIHRoZSBpbml0aWFsIGRlbGF5IGJlZm9yZSB0aGUgZmlyc3Qga2VlcGFsaXZlXG4gICAqICAgICAgICAgICAgICAgICAgICBwcm9iZSBpcyBzZW50IG9uIGFuIGlkbGUgc29ja2V0LiBEZWZhdWx0cyBpcyAzMCBzZWNvbmRzLlxuICAgKiAqIGBrZXlUb1NlcnZlckhhc2hGdW5jdGlvbmAgYSBmdW5jdGlvbiB0byBtYXAga2V5cyB0byBzZXJ2ZXJzLCB3aXRoIHRoZSBzaWduYXR1cmVcbiAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgKHNlcnZlcktleXM6IHN0cmluZ1tdLCBrZXk6IHN0cmluZyk6IHN0cmluZ1xuICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICBOT1RFOiBpZiB5b3UgbmVlZCB0byBkbyBzb21lIGV4cGVuc2l2ZSBpbml0aWFsaXphdGlvbiwgKnBsZWFzZSogZG8gaXQgbGF6aWx5IHRoZSBmaXJzdCB0aW1lIHlvdSB0aGlzIGZ1bmN0aW9uIGlzIGNhbGxlZCB3aXRoIGFuIGFycmF5IG9mIHNlcnZlcktleXMsIG5vdCBvbiBldmVyeSBjYWxsXG4gICAqL1xuICBzdGF0aWMgY3JlYXRlPFZhbHVlLCBFeHRyYXM+KFxuICAgIHNlcnZlcnNTdHI6IHN0cmluZyB8IHVuZGVmaW5lZCxcbiAgICBvcHRpb25zOiBJZkJ1ZmZlcjxcbiAgICAgIFZhbHVlLFxuICAgICAgRXh0cmFzLFxuICAgICAgdW5kZWZpbmVkIHwgKFBhcnRpYWw8U2VydmVyT3B0aW9ucz4gJiBHaXZlbkNsaWVudE9wdGlvbnM8VmFsdWUsIEV4dHJhcz4pLFxuICAgICAgUGFydGlhbDxTZXJ2ZXJPcHRpb25zPiAmIEdpdmVuQ2xpZW50T3B0aW9uczxWYWx1ZSwgRXh0cmFzPlxuICAgID5cbiAgKTogQ2xpZW50PFZhbHVlLCBFeHRyYXM+IHtcbiAgICBzZXJ2ZXJzU3RyID1cbiAgICAgIHNlcnZlcnNTdHIgfHxcbiAgICAgIHByb2Nlc3MuZW52Lk1FTUNBQ0hJRVJfU0VSVkVSUyB8fFxuICAgICAgcHJvY2Vzcy5lbnYuTUVNQ0FDSEVfU0VSVkVSUyB8fFxuICAgICAgXCJsb2NhbGhvc3Q6MTEyMTFcIjtcbiAgICBjb25zdCBzZXJ2ZXJVcmlzID0gc2VydmVyc1N0ci5zcGxpdChcIixcIik7XG4gICAgY29uc3Qgc2VydmVycyA9IHNlcnZlclVyaXMubWFwKGZ1bmN0aW9uICh1cmkpIHtcbiAgICAgIGNvbnN0IHVyaVBhcnRzID0gdXJpLnNwbGl0KFwiQFwiKTtcbiAgICAgIGNvbnN0IGhvc3RQb3J0ID0gdXJpUGFydHNbdXJpUGFydHMubGVuZ3RoIC0gMV0uc3BsaXQoXCI6XCIpO1xuICAgICAgY29uc3QgdXNlclBhc3MgPSAodXJpUGFydHNbdXJpUGFydHMubGVuZ3RoIC0gMl0gfHwgXCJcIikuc3BsaXQoXCI6XCIpO1xuICAgICAgcmV0dXJuIG5ldyBTZXJ2ZXIoXG4gICAgICAgIGhvc3RQb3J0WzBdLFxuICAgICAgICBwYXJzZUludChob3N0UG9ydFsxXSB8fCBcIjExMjExXCIsIDEwKSxcbiAgICAgICAgdXNlclBhc3NbMF0sXG4gICAgICAgIHVzZXJQYXNzWzFdLFxuICAgICAgICBvcHRpb25zXG4gICAgICApO1xuICAgIH0pO1xuICAgIHJldHVybiBuZXcgQ2xpZW50KHNlcnZlcnMsIG9wdGlvbnMgYXMgYW55KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHaXZlbiBhIHNlcnZlcktleSBmcm9tbG9va3VwS2V5VG9TZXJ2ZXJLZXksIHJldHVybiB0aGUgY29ycmVzcG9uZGluZyBTZXJ2ZXIgaW5zdGFuY2VcbiAgICpcbiAgICogQHBhcmFtICB7c3RyaW5nfSBzZXJ2ZXJLZXlcbiAgICogQHJldHVybnMge1NlcnZlcn1cbiAgICovXG4gIHNlcnZlcktleVRvU2VydmVyKHNlcnZlcktleTogc3RyaW5nKTogU2VydmVyIHtcbiAgICByZXR1cm4gdGhpcy5zZXJ2ZXJNYXBbc2VydmVyS2V5XTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHaXZlbiBhIGtleSB0byBsb29rIHVwIGluIG1lbWNhY2hlLCByZXR1cm4gYSBzZXJ2ZXJLZXkgKGJhc2VkIG9uIHNvbWVcbiAgICogaGFzaGluZyBmdW5jdGlvbikgd2hpY2ggY2FuIGJlIHVzZWQgdG8gaW5kZXggdGhpcy5zZXJ2ZXJNYXBcbiAgICovXG4gIGxvb2t1cEtleVRvU2VydmVyS2V5KGtleTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5vcHRpb25zLmtleVRvU2VydmVySGFzaEZ1bmN0aW9uKHRoaXMuc2VydmVyS2V5cywga2V5KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXRyaWV2ZXMgdGhlIHZhbHVlIGF0IHRoZSBnaXZlbiBrZXkgaW4gbWVtY2FjaGUuXG4gICAqL1xuICBhc3luYyBnZXQoa2V5OiBzdHJpbmcpOiBQcm9taXNlPEdldFJlc3VsdDxWYWx1ZSwgRXh0cmFzPiB8IG51bGw+IHtcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoY29uc3RhbnRzLk9QX0dFVCwga2V5LCBcIlwiLCBcIlwiLCB0aGlzLnNlcSk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIGNvbnN0IGRlc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5kZXNlcmlhbGl6ZShcbiAgICAgICAgICByZXNwb25zZS5oZWFkZXIub3Bjb2RlLFxuICAgICAgICAgIHJlc3BvbnNlLnZhbCxcbiAgICAgICAgICByZXNwb25zZS5leHRyYXNcbiAgICAgICAgKTtcbiAgICAgICAgcmV0dXJuIHsgLi4uZGVzZXJpYWxpemVkLCBjYXM6IHJlc3BvbnNlLmhlYWRlci5jYXMgfTtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuS0VZX05PVF9GT1VORDpcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiR0VUXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBCdWlsZCBhIHBpcGVsaW5lZCBnZXQgbXVsdGkgcmVxdWVzdCBieSBzZW5kaW5nIG9uZSBHRVRLUSBmb3IgZWFjaCBrZXkgKHF1aWV0LCBtZWFuaW5nIGl0IHdvbid0IHJlc3BvbmQgaWYgdGhlIHZhbHVlIGlzIG1pc3NpbmcpIGZvbGxvd2VkIGJ5IGEgbm8tb3AgdG8gZm9yY2UgYSByZXNwb25zZSAoYW5kIHRvIGdpdmUgdXMgYSBzZW50aW5lbCByZXNwb25zZSB0aGF0IHRoZSBwaXBlbGluZSBpcyBkb25lKVxuICAgKlxuICAgKiBjZiBodHRwczovL2dpdGh1Yi5jb20vY291Y2hiYXNlL21lbWNhY2hlZC9ibG9iL21hc3Rlci9kb2NzL0JpbmFyeVByb3RvY29sLm1kIzB4MGQtZ2V0a3EtZ2V0LXdpdGgta2V5LXF1aWV0bHlcbiAgICovXG4gIF9idWlsZEdldE11bHRpUmVxdWVzdChrZXlzOiBzdHJpbmdbXSwgc2VxOiBudW1iZXIpOiBCdWZmZXIge1xuICAgIC8vIHN0YXJ0IGF0IDI0IGZvciB0aGUgbm8tb3AgY29tbWFuZCBhdCB0aGUgZW5kXG4gICAgbGV0IHJlcXVlc3RTaXplID0gMjQ7XG4gICAgZm9yIChjb25zdCBrZXlJZHggaW4ga2V5cykge1xuICAgICAgcmVxdWVzdFNpemUgKz0gQnVmZmVyLmJ5dGVMZW5ndGgoa2V5c1trZXlJZHhdLCBcInV0ZjhcIikgKyAyNDtcbiAgICB9XG5cbiAgICBjb25zdCByZXF1ZXN0ID0gQnVmZmVyLmFsbG9jKHJlcXVlc3RTaXplKTtcblxuICAgIGxldCBieXRlc1dyaXR0ZW4gPSAwO1xuICAgIGZvciAoY29uc3Qga2V5SWR4IGluIGtleXMpIHtcbiAgICAgIGNvbnN0IGtleSA9IGtleXNba2V5SWR4XTtcbiAgICAgIGJ5dGVzV3JpdHRlbiArPSBjb3B5SW50b1JlcXVlc3RCdWZmZXIoXG4gICAgICAgIGNvbnN0YW50cy5PUF9HRVRLUSxcbiAgICAgICAga2V5LFxuICAgICAgICBcIlwiLFxuICAgICAgICBcIlwiLFxuICAgICAgICBzZXEsXG4gICAgICAgIHJlcXVlc3QsXG4gICAgICAgIGJ5dGVzV3JpdHRlblxuICAgICAgKTtcbiAgICB9XG5cbiAgICBieXRlc1dyaXR0ZW4gKz0gY29weUludG9SZXF1ZXN0QnVmZmVyKFxuICAgICAgY29uc3RhbnRzLk9QX05PX09QLFxuICAgICAgXCJcIixcbiAgICAgIFwiXCIsXG4gICAgICBcIlwiLFxuICAgICAgc2VxLFxuICAgICAgcmVxdWVzdCxcbiAgICAgIGJ5dGVzV3JpdHRlblxuICAgICk7XG5cbiAgICByZXR1cm4gcmVxdWVzdDtcbiAgfVxuXG4gIC8qKiBFeGVjdXRpbmcgYSBwaXBlbGluZWQgKG11bHRpKSBnZXQgYWdhaW5zdCBhIHNpbmdsZSBzZXJ2ZXIuIFRoaXMgaXMgYSBwcml2YXRlIGltcGxlbWVudGF0aW9uIGRldGFpbCBvZiBnZXRNdWx0aS4gKi9cbiAgYXN5bmMgX2dldE11bHRpVG9TZXJ2ZXI8S2V5cyBleHRlbmRzIHN0cmluZz4oXG4gICAgc2VydjogU2VydmVyLFxuICAgIGtleXM6IEtleXNbXVxuICApOiBQcm9taXNlPEdldE11bHRpUmVzdWx0PEtleXMsIFZhbHVlLCBFeHRyYXM+PiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGNvbnN0IHJlc3BvbnNlTWFwOiBHZXRNdWx0aVJlc3VsdDxzdHJpbmcsIFZhbHVlLCBFeHRyYXM+ID0ge307XG5cbiAgICAgIGNvbnN0IGhhbmRsZTogT25SZXNwb25zZUNhbGxiYWNrID0gKHJlc3BvbnNlKSA9PiB7XG4gICAgICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgICAgIC8vIFdoZW4gd2UgZ2V0IHRoZSBuby1vcCByZXNwb25zZSwgd2UgYXJlIGRvbmUgd2l0aCB0aGlzIG9uZSBnZXRNdWx0aSBpbiB0aGUgcGVyLWJhY2tlbmQgZmFuLW91dFxuICAgICAgICAgICAgaWYgKHJlc3BvbnNlLmhlYWRlci5vcGNvZGUgPT09IGNvbnN0YW50cy5PUF9OT19PUCkge1xuICAgICAgICAgICAgICAvLyBUaGlzIGVuc3VyZXMgdGhlIGhhbmRsZXIgd2lsbCBiZSBkZWxldGVkIGZyb20gdGhlIHJlc3BvbnNlQ2FsbGJhY2tzIG1hcCBpbiBzZXJ2ZXIuanNcbiAgICAgICAgICAgICAgLy8gVGhpcyBpc24ndCB0ZWNobmljYWxseSBuZWVkZWQgaGVyZSBiZWNhdXNlIHRoZSBsb2dpYyBpbiBzZXJ2ZXIuanMgYWxzbyBjaGVja3MgaWYgdG90YWxCb2R5TGVuZ3RoID09PSAwLCBidXQgb3VyIHVuaXR0ZXN0cyBhcmVuJ3QgZ3JlYXQgYWJvdXQgc2V0dGluZyB0aGF0IGZpZWxkLCBhbmQgYWxzbyB0aGlzIG1ha2VzIGl0IG1vcmUgZXhwbGljaXRcbiAgICAgICAgICAgICAgaGFuZGxlLnF1aWV0ID0gZmFsc2U7XG4gICAgICAgICAgICAgIHJlc29sdmUocmVzcG9uc2VNYXApO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChyZXNwb25zZS5oZWFkZXIub3Bjb2RlID09PSBjb25zdGFudHMuT1BfR0VUSyB8fCByZXNwb25zZS5oZWFkZXIub3Bjb2RlID09PSBjb25zdGFudHMuT1BfR0VUS1EpIHtcbiAgICAgICAgICAgICAgY29uc3QgZGVzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLmRlc2VyaWFsaXplKFxuICAgICAgICAgICAgICAgIHJlc3BvbnNlLmhlYWRlci5vcGNvZGUsXG4gICAgICAgICAgICAgICAgcmVzcG9uc2UudmFsLFxuICAgICAgICAgICAgICAgIHJlc3BvbnNlLmV4dHJhc1xuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICBjb25zdCBrZXkgPSByZXNwb25zZS5rZXkudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgaWYgKGtleS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVqZWN0KFxuICAgICAgICAgICAgICAgICAgbmV3IEVycm9yKFwiUmVjaWV2ZWQgZW1wdHkga2V5IGluIGdldE11bHRpOiBcIiArIEpTT04uc3RyaW5naWZ5KHJlc3BvbnNlKSlcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIHJlc3BvbnNlTWFwW2tleV0gPSB7IC4uLmRlc2VyaWFsaXplZCwgY2FzOiByZXNwb25zZS5oZWFkZXIuY2FzIH07XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICByZXR1cm4gcmVqZWN0KFxuICAgICAgICAgICAgICAgIG5ldyBFcnJvcihcIlJlY2lldmVkIHJlc3BvbnNlIGluIGdldE11bHRpIGZvciB1bmtub3duIG9wY29kZTogXCIgKyBKU09OLnN0cmluZ2lmeShyZXNwb25zZSkpXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgcmV0dXJuIHJlamVjdChcbiAgICAgICAgICAgICAgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIkdFVFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfTtcbiAgICAgIC8vIFRoaXMgcHJldmVudHMgdGhlIGhhbmRsZXIgZnJvbSBiZWluZyBkZWxldGVkXG4gICAgICAvLyBhZnRlciB0aGUgZmlyc3QgcmVzcG9uc2UuIExvZ2ljIGluIHNlcnZlci5qcy5cbiAgICAgIGhhbmRsZS5xdWlldCA9IHRydWU7XG5cbiAgICAgIGNvbnN0IHNlcSA9IHRoaXMuaW5jclNlcSgpO1xuICAgICAgY29uc3QgcmVxdWVzdCA9IHRoaXMuX2J1aWxkR2V0TXVsdGlSZXF1ZXN0KGtleXMsIHNlcSk7XG4gICAgICBzZXJ2Lm9uUmVzcG9uc2UodGhpcy5zZXEsIGhhbmRsZSk7XG4gICAgICBzZXJ2Lm9uRXJyb3IodGhpcy5zZXEsIHJlamVjdCk7XG4gICAgICBzZXJ2LndyaXRlKHJlcXVlc3QpO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHJpZXZzIHRoZSB2YWx1ZSBhdCB0aGUgZ2l2ZW4ga2V5cyBpbiBtZW1jYWNoZWQuIFJldHVybnMgYSBtYXAgZnJvbSB0aGVcbiAgICogcmVxdWVzdGVkIGtleXMgdG8gcmVzdWx0cywgb3IgbnVsbCBpZiB0aGUga2V5IHdhcyBub3QgZm91bmQuXG4gICAqL1xuICBhc3luYyBnZXRNdWx0aTxLZXlzIGV4dGVuZHMgc3RyaW5nPihcbiAgICBrZXlzOiBLZXlzW11cbiAgKTogUHJvbWlzZTxHZXRNdWx0aVJlc3VsdDxLZXlzLCBWYWx1ZSwgRXh0cmFzPj4ge1xuICAgIGNvbnN0IHNlcnZlcktleXRvTG9va3VwS2V5czoge1xuICAgICAgW3NlcnZlcktleTogc3RyaW5nXTogc3RyaW5nW107XG4gICAgfSA9IHt9O1xuICAgIGtleXMuZm9yRWFjaCgobG9va3VwS2V5KSA9PiB7XG4gICAgICBjb25zdCBzZXJ2ZXJLZXkgPSB0aGlzLmxvb2t1cEtleVRvU2VydmVyS2V5KGxvb2t1cEtleSk7XG4gICAgICBpZiAoIXNlcnZlcktleXRvTG9va3VwS2V5c1tzZXJ2ZXJLZXldKSB7XG4gICAgICAgIHNlcnZlcktleXRvTG9va3VwS2V5c1tzZXJ2ZXJLZXldID0gW107XG4gICAgICB9XG4gICAgICBzZXJ2ZXJLZXl0b0xvb2t1cEtleXNbc2VydmVyS2V5XS5wdXNoKGxvb2t1cEtleSk7XG4gICAgfSk7XG5cbiAgICBjb25zdCB1c2VkU2VydmVyS2V5cyA9IE9iamVjdC5rZXlzKHNlcnZlcktleXRvTG9va3VwS2V5cyk7XG4gICAgY29uc3QgcmVzdWx0cyA9IGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgdXNlZFNlcnZlcktleXMubWFwKChzZXJ2ZXJLZXkpID0+IHtcbiAgICAgICAgY29uc3Qgc2VydmVyID0gdGhpcy5zZXJ2ZXJLZXlUb1NlcnZlcihzZXJ2ZXJLZXkpO1xuICAgICAgICByZXR1cm4gdGhpcy5fZ2V0TXVsdGlUb1NlcnZlcihzZXJ2ZXIsIHNlcnZlcktleXRvTG9va3VwS2V5c1tzZXJ2ZXJLZXldKTtcbiAgICAgIH0pXG4gICAgKTtcblxuICAgIHJldHVybiBPYmplY3QuYXNzaWduKHt9LCAuLi5yZXN1bHRzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIGBrZXlgIHRvIGB2YWx1ZWAuXG4gICAqL1xuICBhc3luYyBzZXQoXG4gICAga2V5OiBzdHJpbmcsXG4gICAgdmFsdWU6IFZhbHVlLFxuICAgIG9wdGlvbnM/OiB7IGV4cGlyZXM/OiBudW1iZXI7IGNhcz86IENBU1Rva2VuIH1cbiAgKTogUHJvbWlzZTxib29sZWFuIHwgbnVsbD4ge1xuICAgIGNvbnN0IGV4cGlyZXMgPSBvcHRpb25zPy5leHBpcmVzO1xuICAgIGNvbnN0IGNhcyA9IG9wdGlvbnM/LmNhcztcblxuICAgIC8vIFRPRE86IHN1cHBvcnQgZmxhZ3NcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBleHBpcmF0aW9uID0gbWFrZUV4cGlyYXRpb24oZXhwaXJlcyB8fCB0aGlzLm9wdGlvbnMuZXhwaXJlcyk7XG4gICAgY29uc3QgZXh0cmFzID0gQnVmZmVyLmNvbmNhdChbQnVmZmVyLmZyb20oXCIwMDAwMDAwMFwiLCBcImhleFwiKSwgZXhwaXJhdGlvbl0pO1xuICAgIGNvbnN0IHNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuc2VyaWFsaXplKFxuICAgICAgY29uc3RhbnRzLk9QX1NFVCxcbiAgICAgIHZhbHVlLFxuICAgICAgZXh0cmFzXG4gICAgKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gVXRpbHMuZW5jb2RlUmVxdWVzdCh7XG4gICAgICBoZWFkZXI6IHtcbiAgICAgICAgb3Bjb2RlOiBjb25zdGFudHMuT1BfU0VULFxuICAgICAgICBvcGFxdWU6IHRoaXMuc2VxLFxuICAgICAgICBjYXMsXG4gICAgICB9LFxuICAgICAga2V5LFxuICAgICAgdmFsdWU6IHNlcmlhbGl6ZWQudmFsdWUsXG4gICAgICBleHRyYXM6IHNlcmlhbGl6ZWQuZXh0cmFzLFxuICAgIH0pO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuS0VZX0VYSVNUUzpcbiAgICAgICAgaWYgKGNhcykge1xuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiU0VUXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgICAgICB9XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiU0VUXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBBRERcbiAgICpcbiAgICogQWRkcyB0aGUgZ2l2ZW4gX2tleV8gYW5kIF92YWx1ZV8gdG8gbWVtY2FjaGUuIFRoZSBvcGVyYXRpb24gb25seSBzdWNjZWVkc1xuICAgKiBpZiB0aGUga2V5IGlzIG5vdCBhbHJlYWR5IHNldC5cbiAgICpcbiAgICogVGhlIG9wdGlvbnMgZGljdGlvbmFyeSB0YWtlczpcbiAgICogKiBfZXhwaXJlc186IG92ZXJyaWRlcyB0aGUgZGVmYXVsdCBleHBpcmF0aW9uIChzZWUgYENsaWVudC5jcmVhdGVgKSBmb3IgdGhpc1xuICAgKiAgICAgICAgICAgICAgcGFydGljdWxhciBrZXktdmFsdWUgcGFpci5cbiAgICovXG4gIGFzeW5jIGFkZChcbiAgICBrZXk6IHN0cmluZyxcbiAgICB2YWx1ZTogVmFsdWUsXG4gICAgb3B0aW9ucz86IHsgZXhwaXJlcz86IG51bWJlciB9XG4gICk6IFByb21pc2U8Ym9vbGVhbiB8IG51bGw+IHtcbiAgICAvLyBUT0RPOiBzdXBwb3J0IGZsYWdzLCBzdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBleHBpcmF0aW9uID0gbWFrZUV4cGlyYXRpb24ob3B0aW9ucz8uZXhwaXJlcyB8fCB0aGlzLm9wdGlvbnMuZXhwaXJlcyk7XG4gICAgY29uc3QgZXh0cmFzID0gQnVmZmVyLmNvbmNhdChbQnVmZmVyLmZyb20oXCIwMDAwMDAwMFwiLCBcImhleFwiKSwgZXhwaXJhdGlvbl0pO1xuXG4gICAgY29uc3Qgb3Bjb2RlID0gY29uc3RhbnRzLk9QX0FERDtcbiAgICBjb25zdCBzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLnNlcmlhbGl6ZShvcGNvZGUsIHZhbHVlLCBleHRyYXMpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgIG9wY29kZSxcbiAgICAgIGtleSxcbiAgICAgIHNlcmlhbGl6ZWQuZXh0cmFzLFxuICAgICAgc2VyaWFsaXplZC52YWx1ZSxcbiAgICAgIHRoaXMuc2VxXG4gICAgKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9FWElTVFM6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiQUREXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXBsYWNlcyB0aGUgZ2l2ZW4gX2tleV8gYW5kIF92YWx1ZV8gdG8gbWVtY2FjaGUuIFRoZSBvcGVyYXRpb24gb25seSBzdWNjZWVkc1xuICAgKiBpZiB0aGUga2V5IGlzIGFscmVhZHkgcHJlc2VudC5cbiAgICovXG4gIGFzeW5jIHJlcGxhY2UoXG4gICAga2V5OiBzdHJpbmcsXG4gICAgdmFsdWU6IFZhbHVlLFxuICAgIG9wdGlvbnM/OiB7IGV4cGlyZXM/OiBudW1iZXIgfVxuICApOiBQcm9taXNlPGJvb2xlYW4gfCBudWxsPiB7XG4gICAgLy8gVE9ETzogc3VwcG9ydCBmbGFncywgc3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgZXhwaXJhdGlvbiA9IG1ha2VFeHBpcmF0aW9uKG9wdGlvbnM/LmV4cGlyZXMgfHwgdGhpcy5vcHRpb25zLmV4cGlyZXMpO1xuICAgIGNvbnN0IGV4dHJhcyA9IEJ1ZmZlci5jb25jYXQoW0J1ZmZlci5mcm9tKFwiMDAwMDAwMDBcIiwgXCJoZXhcIiksIGV4cGlyYXRpb25dKTtcblxuICAgIGNvbnN0IG9wY29kZTogY29uc3RhbnRzLk9QID0gY29uc3RhbnRzLk9QX1JFUExBQ0U7XG4gICAgY29uc3Qgc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5zZXJpYWxpemUob3Bjb2RlLCB2YWx1ZSwgZXh0cmFzKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICBvcGNvZGUsXG4gICAgICBrZXksXG4gICAgICBzZXJpYWxpemVkLmV4dHJhcyxcbiAgICAgIHNlcmlhbGl6ZWQudmFsdWUsXG4gICAgICB0aGlzLnNlcVxuICAgICk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfTk9UX0ZPVU5EOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiUkVQTEFDRVwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRGVsZXRlcyB0aGUgZ2l2ZW4gX2tleV8gZnJvbSBtZW1jYWNoZS4gVGhlIG9wZXJhdGlvbiBvbmx5IHN1Y2NlZWRzXG4gICAqIGlmIHRoZSBrZXkgaXMgYWxyZWFkeSBwcmVzZW50LlxuICAgKi9cbiAgYXN5bmMgZGVsZXRlKGtleTogc3RyaW5nKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgLy8gVE9ETzogU3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKDQsIGtleSwgXCJcIiwgXCJcIiwgdGhpcy5zZXEpO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuXG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfTk9UX0ZPVU5EOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiREVMRVRFXCIsIHJlc3BvbnNlPy5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogSW5jcmVtZW50cyB0aGUgZ2l2ZW4gX2tleV8gaW4gbWVtY2FjaGUuXG4gICAqL1xuICBhc3luYyBpbmNyZW1lbnQoXG4gICAga2V5OiBzdHJpbmcsXG4gICAgYW1vdW50OiBudW1iZXIsXG4gICAgb3B0aW9ucz86IHsgaW5pdGlhbD86IG51bWJlcjsgZXhwaXJlcz86IG51bWJlciB9XG4gICk6IFByb21pc2U8eyB2YWx1ZTogbnVtYmVyIHwgbnVsbDsgc3VjY2VzczogYm9vbGVhbiB8IG51bGwgfT4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IGluaXRpYWwgPSBvcHRpb25zPy5pbml0aWFsIHx8IDA7XG4gICAgY29uc3QgZXhwaXJlcyA9IG9wdGlvbnM/LmV4cGlyZXMgfHwgdGhpcy5vcHRpb25zLmV4cGlyZXM7XG4gICAgY29uc3QgZXh0cmFzID0gbWFrZUFtb3VudEluaXRpYWxBbmRFeHBpcmF0aW9uKGFtb3VudCwgaW5pdGlhbCwgZXhwaXJlcyk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKFxuICAgICAgY29uc3RhbnRzLk9QX0lOQ1JFTUVOVCxcbiAgICAgIGtleSxcbiAgICAgIGV4dHJhcyxcbiAgICAgIFwiXCIsXG4gICAgICB0aGlzLnNlcVxuICAgICk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIGNvbnN0IGJ1ZkludCA9XG4gICAgICAgICAgKHJlc3BvbnNlLnZhbC5yZWFkVUludDMyQkUoMCkgPDwgOCkgKyByZXNwb25zZS52YWwucmVhZFVJbnQzMkJFKDQpO1xuICAgICAgICByZXR1cm4geyB2YWx1ZTogYnVmSW50LCBzdWNjZXNzOiB0cnVlIH07XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiSU5DUkVNRU5UXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBEZWNyZW1lbnRzIHRoZSBnaXZlbiBga2V5YCBpbiBtZW1jYWNoZS5cbiAgICovXG4gIGFzeW5jIGRlY3JlbWVudChcbiAgICBrZXk6IHN0cmluZyxcbiAgICBhbW91bnQ6IG51bWJlcixcbiAgICBvcHRpb25zOiB7IGluaXRpYWw/OiBudW1iZXI7IGV4cGlyZXM/OiBudW1iZXIgfVxuICApOiBQcm9taXNlPHsgdmFsdWU6IG51bWJlciB8IG51bGw7IHN1Y2Nlc3M6IGJvb2xlYW4gfCBudWxsIH0+IHtcbiAgICAvLyBUT0RPOiBzdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBpbml0aWFsID0gb3B0aW9ucy5pbml0aWFsIHx8IDA7XG4gICAgY29uc3QgZXhwaXJlcyA9IG9wdGlvbnMuZXhwaXJlcyB8fCB0aGlzLm9wdGlvbnMuZXhwaXJlcztcbiAgICBjb25zdCBleHRyYXMgPSBtYWtlQW1vdW50SW5pdGlhbEFuZEV4cGlyYXRpb24oYW1vdW50LCBpbml0aWFsLCBleHBpcmVzKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICBjb25zdGFudHMuT1BfREVDUkVNRU5ULFxuICAgICAga2V5LFxuICAgICAgZXh0cmFzLFxuICAgICAgXCJcIixcbiAgICAgIHRoaXMuc2VxXG4gICAgKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgY29uc3QgYnVmSW50ID1cbiAgICAgICAgICAocmVzcG9uc2UudmFsLnJlYWRVSW50MzJCRSgwKSA8PCA4KSArIHJlc3BvbnNlLnZhbC5yZWFkVUludDMyQkUoNCk7XG4gICAgICAgIHJldHVybiB7IHZhbHVlOiBidWZJbnQsIHN1Y2Nlc3M6IHRydWUgfTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJERUNSRU1FTlRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEFwcGVuZCB0aGUgZ2l2ZW4gX3ZhbHVlXyB0byB0aGUgdmFsdWUgYXNzb2NpYXRlZCB3aXRoIHRoZSBnaXZlbiBfa2V5XyBpblxuICAgKiBtZW1jYWNoZS4gVGhlIG9wZXJhdGlvbiBvbmx5IHN1Y2NlZWRzIGlmIHRoZSBrZXkgaXMgYWxyZWFkeSBwcmVzZW50LlxuICAgKi9cbiAgYXN5bmMgYXBwZW5kKGtleTogc3RyaW5nLCB2YWx1ZTogVmFsdWUpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAvLyBUT0RPOiBzdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBvcGNvZGU6IGNvbnN0YW50cy5PUCA9IGNvbnN0YW50cy5PUF9BUFBFTkQ7XG4gICAgY29uc3Qgc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5zZXJpYWxpemUob3Bjb2RlLCB2YWx1ZSwgXCJcIik7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKFxuICAgICAgb3Bjb2RlLFxuICAgICAga2V5LFxuICAgICAgc2VyaWFsaXplZC5leHRyYXMsXG4gICAgICBzZXJpYWxpemVkLnZhbHVlLFxuICAgICAgdGhpcy5zZXFcbiAgICApO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuS0VZX05PVF9GT1VORDpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIkFQUEVORFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUHJlcGVuZCB0aGUgZ2l2ZW4gX3ZhbHVlXyB0byB0aGUgdmFsdWUgYXNzb2NpYXRlZCB3aXRoIHRoZSBnaXZlbiBfa2V5XyBpblxuICAgKiBtZW1jYWNoZS4gVGhlIG9wZXJhdGlvbiBvbmx5IHN1Y2NlZWRzIGlmIHRoZSBrZXkgaXMgYWxyZWFkeSBwcmVzZW50LlxuICAgKi9cbiAgYXN5bmMgcHJlcGVuZChrZXk6IHN0cmluZywgdmFsdWU6IFZhbHVlKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgLy8gVE9ETzogc3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3Qgb3Bjb2RlOiBjb25zdGFudHMuT1AgPSBjb25zdGFudHMuT1BfUFJFUEVORDtcbiAgICBjb25zdCBzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLnNlcmlhbGl6ZShvcGNvZGUsIHZhbHVlLCBcIlwiKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICBvcGNvZGUsXG4gICAgICBrZXksXG4gICAgICBzZXJpYWxpemVkLmV4dHJhcyxcbiAgICAgIHNlcmlhbGl6ZWQudmFsdWUsXG4gICAgICB0aGlzLnNlcVxuICAgICk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfTk9UX0ZPVU5EOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiUFJFUEVORFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVG91Y2ggc2V0cyBhbiBleHBpcmF0aW9uIHZhbHVlLCBnaXZlbiBieSBfZXhwaXJlc18sIG9uIHRoZSBnaXZlbiBfa2V5XyBpblxuICAgKiBtZW1jYWNoZS4gVGhlIG9wZXJhdGlvbiBvbmx5IHN1Y2NlZWRzIGlmIHRoZSBrZXkgaXMgYWxyZWFkeSBwcmVzZW50LlxuICAgKi9cbiAgYXN5bmMgdG91Y2goa2V5OiBzdHJpbmcsIGV4cGlyZXM6IG51bWJlcik6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IGV4dHJhcyA9IG1ha2VFeHBpcmF0aW9uKGV4cGlyZXMgfHwgdGhpcy5vcHRpb25zLmV4cGlyZXMpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcigweDFjLCBrZXksIGV4dHJhcywgXCJcIiwgdGhpcy5zZXEpO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuS0VZX05PVF9GT1VORDpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIlRPVUNIXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBGTFVTSFxuICAgKlxuICAgKiBGbHVzaGVzIHRoZSBjYWNoZSBvbiBlYWNoIGNvbm5lY3RlZCBzZXJ2ZXIuIFRoZSBjYWxsYmFjayBzaWduYXR1cmUgaXM6XG4gICAqXG4gICAqICAgICBjYWxsYmFjayhsYXN0RXJyLCByZXN1bHRzKVxuICAgKlxuICAgKiB3aGVyZSBfbGFzdEVycl8gaXMgdGhlIGxhc3QgZXJyb3IgZW5jb3VudGVyZWQgKG9yIG51bGwsIGluIHRoZSBjb21tb24gY2FzZVxuICAgKiBvZiBubyBlcnJvcnMpLiBfcmVzdWx0c18gaXMgYSBkaWN0aW9uYXJ5IG1hcHBpbmcgYFwiaG9zdG5hbWU6cG9ydFwiYCB0byBlaXRoZXJcbiAgICogYHRydWVgIChpZiB0aGUgb3BlcmF0aW9uIHdhcyBzdWNjZXNzZnVsKSwgb3IgYW4gZXJyb3IuXG4gICAqIEBwYXJhbSBjYWxsYmFja1xuICAgKi9cbiAgZmx1c2goKTogUHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBib29sZWFuIHwgRXJyb3I+PjtcbiAgZmx1c2goXG4gICAgY2FsbGJhY2s6IChcbiAgICAgIGVycjogRXJyb3IgfCBudWxsLFxuICAgICAgcmVzdWx0czogUmVjb3JkPHN0cmluZywgYm9vbGVhbiB8IEVycm9yPlxuICAgICkgPT4gdm9pZFxuICApOiB2b2lkO1xuICBmbHVzaChcbiAgICBjYWxsYmFjaz86IChcbiAgICAgIGVycjogRXJyb3IgfCBudWxsLFxuICAgICAgcmVzdWx0czogUmVjb3JkPHN0cmluZywgYm9vbGVhbiB8IEVycm9yPlxuICAgICkgPT4gdm9pZFxuICApIHtcbiAgICBpZiAoY2FsbGJhY2sgPT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuIHByb21pc2lmeSgoY2FsbGJhY2spID0+IHtcbiAgICAgICAgdGhpcy5mbHVzaChmdW5jdGlvbiAoZXJyLCByZXN1bHRzKSB7XG4gICAgICAgICAgY2FsbGJhY2soZXJyLCByZXN1bHRzKTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9XG4gICAgLy8gVE9ETzogc3VwcG9ydCBleHBpcmF0aW9uXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKDB4MDgsIFwiXCIsIFwiXCIsIFwiXCIsIHRoaXMuc2VxKTtcbiAgICBsZXQgY291bnQgPSB0aGlzLnNlcnZlcnMubGVuZ3RoO1xuICAgIGNvbnN0IHJlc3VsdDogUmVjb3JkPHN0cmluZywgYm9vbGVhbiB8IEVycm9yPiA9IHt9O1xuICAgIGxldCBsYXN0RXJyOiBFcnJvciB8IG51bGwgPSBudWxsO1xuXG4gICAgY29uc3QgaGFuZGxlRmx1c2ggPSBmdW5jdGlvbiAoc2VxOiBudW1iZXIsIHNlcnY6IFNlcnZlcikge1xuICAgICAgc2Vydi5vblJlc3BvbnNlKHNlcSwgZnVuY3Rpb24gKC8qIHJlc3BvbnNlICovKSB7XG4gICAgICAgIGNvdW50IC09IDE7XG4gICAgICAgIHJlc3VsdFtzZXJ2Lmhvc3Rwb3J0U3RyaW5nKCldID0gdHJ1ZTtcbiAgICAgICAgaWYgKGNhbGxiYWNrICYmIGNvdW50ID09PSAwKSB7XG4gICAgICAgICAgY2FsbGJhY2sobGFzdEVyciwgcmVzdWx0KTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICBzZXJ2Lm9uRXJyb3Ioc2VxLCBmdW5jdGlvbiAoZXJyKSB7XG4gICAgICAgIGNvdW50IC09IDE7XG4gICAgICAgIGxhc3RFcnIgPSBlcnI7XG4gICAgICAgIHJlc3VsdFtzZXJ2Lmhvc3Rwb3J0U3RyaW5nKCldID0gZXJyO1xuICAgICAgICBpZiAoY2FsbGJhY2sgJiYgY291bnQgPT09IDApIHtcbiAgICAgICAgICBjYWxsYmFjayhsYXN0RXJyLCByZXN1bHQpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHNlcnYud3JpdGUocmVxdWVzdCk7XG4gICAgfTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5zZXJ2ZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBoYW5kbGVGbHVzaCh0aGlzLnNlcSwgdGhpcy5zZXJ2ZXJzW2ldKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU1RBVFNfV0lUSF9LRVlcbiAgICpcbiAgICogU2VuZHMgYSBtZW1jYWNoZSBzdGF0cyBjb21tYW5kIHdpdGggYSBrZXkgdG8gZWFjaCBjb25uZWN0ZWQgc2VydmVyLiBUaGVcbiAgICogY2FsbGJhY2sgaXMgaW52b2tlZCAqKk9OQ0UgUEVSIFNFUlZFUioqIGFuZCBoYXMgdGhlIHNpZ25hdHVyZTpcbiAgICpcbiAgICogICAgIGNhbGxiYWNrKGVyciwgc2VydmVyLCBzdGF0cylcbiAgICpcbiAgICogX3NlcnZlcl8gaXMgdGhlIGBcImhvc3RuYW1lOnBvcnRcImAgb2YgdGhlIHNlcnZlciwgYW5kIF9zdGF0c18gaXMgYSBkaWN0aW9uYXJ5XG4gICAqIG1hcHBpbmcgdGhlIHN0YXQgbmFtZSB0byB0aGUgdmFsdWUgb2YgdGhlIHN0YXRpc3RpYyBhcyBhIHN0cmluZy5cbiAgICogQHBhcmFtIGtleVxuICAgKiBAcGFyYW0gY2FsbGJhY2tcbiAgICovXG4gIHN0YXRzV2l0aEtleShcbiAgICBrZXk6IHN0cmluZyxcbiAgICBjYWxsYmFjaz86IChcbiAgICAgIGVycjogRXJyb3IgfCBudWxsLFxuICAgICAgc2VydmVyOiBzdHJpbmcsXG4gICAgICBzdGF0czogUmVjb3JkPHN0cmluZywgc3RyaW5nPiB8IG51bGxcbiAgICApID0+IHZvaWRcbiAgKTogdm9pZCB7XG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKDB4MTAsIGtleSwgXCJcIiwgXCJcIiwgdGhpcy5zZXEpO1xuXG4gICAgY29uc3QgaGFuZGxlU3RhdHMgPSAoc2VxOiBudW1iZXIsIHNlcnY6IFNlcnZlcikgPT4ge1xuICAgICAgY29uc3QgcmVzdWx0OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge307XG4gICAgICBjb25zdCBoYW5kbGU6IE9uUmVzcG9uc2VDYWxsYmFjayA9IChyZXNwb25zZSkgPT4ge1xuICAgICAgICAvLyBlbmQgb2Ygc3RhdCByZXNwb25zZXNcbiAgICAgICAgaWYgKHJlc3BvbnNlLmhlYWRlci50b3RhbEJvZHlMZW5ndGggPT09IDApIHtcbiAgICAgICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKG51bGwsIHNlcnYuaG9zdHBvcnRTdHJpbmcoKSwgcmVzdWx0KTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIC8vIHByb2Nlc3Mgc2luZ2xlIHN0YXQgbGluZSByZXNwb25zZVxuICAgICAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgICAgICByZXN1bHRbcmVzcG9uc2Uua2V5LnRvU3RyaW5nKCldID0gcmVzcG9uc2UudmFsLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgY29uc3QgZXJyb3IgPSB0aGlzLmhhbmRsZVJlc3BvbnNlRXJyb3IoXG4gICAgICAgICAgICAgIGBTVEFUUyAoJHtrZXl9KWAsXG4gICAgICAgICAgICAgIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMsXG4gICAgICAgICAgICAgIHVuZGVmaW5lZFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgICAgICBjYWxsYmFjayhlcnJvciwgc2Vydi5ob3N0cG9ydFN0cmluZygpLCBudWxsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfTtcbiAgICAgIGhhbmRsZS5xdWlldCA9IHRydWU7XG5cbiAgICAgIHNlcnYub25SZXNwb25zZShzZXEsIGhhbmRsZSk7XG4gICAgICBzZXJ2Lm9uRXJyb3Ioc2VxLCBmdW5jdGlvbiAoZXJyKSB7XG4gICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgIGNhbGxiYWNrKGVyciwgc2Vydi5ob3N0cG9ydFN0cmluZygpLCBudWxsKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICBzZXJ2LndyaXRlKHJlcXVlc3QpO1xuICAgIH07XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuc2VydmVycy5sZW5ndGg7IGkrKykge1xuICAgICAgaGFuZGxlU3RhdHModGhpcy5zZXEsIHRoaXMuc2VydmVyc1tpXSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNUQVRTXG4gICAqXG4gICAqIEZldGNoZXMgbWVtY2FjaGUgc3RhdHMgZnJvbSBlYWNoIGNvbm5lY3RlZCBzZXJ2ZXIuIFRoZSBjYWxsYmFjayBpcyBpbnZva2VkXG4gICAqICoqT05DRSBQRVIgU0VSVkVSKiogYW5kIGhhcyB0aGUgc2lnbmF0dXJlOlxuICAgKlxuICAgKiAgICAgY2FsbGJhY2soZXJyLCBzZXJ2ZXIsIHN0YXRzKVxuICAgKlxuICAgKiBfc2VydmVyXyBpcyB0aGUgYFwiaG9zdG5hbWU6cG9ydFwiYCBvZiB0aGUgc2VydmVyLCBhbmQgX3N0YXRzXyBpcyBhXG4gICAqIGRpY3Rpb25hcnkgbWFwcGluZyB0aGUgc3RhdCBuYW1lIHRvIHRoZSB2YWx1ZSBvZiB0aGUgc3RhdGlzdGljIGFzIGEgc3RyaW5nLlxuICAgKiBAcGFyYW0gY2FsbGJhY2tcbiAgICovXG4gIHN0YXRzKFxuICAgIGNhbGxiYWNrPzogKFxuICAgICAgZXJyOiBFcnJvciB8IG51bGwsXG4gICAgICBzZXJ2ZXI6IHN0cmluZyxcbiAgICAgIHN0YXRzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+IHwgbnVsbFxuICAgICkgPT4gdm9pZFxuICApOiB2b2lkIHtcbiAgICB0aGlzLnN0YXRzV2l0aEtleShcIlwiLCBjYWxsYmFjayk7XG4gIH1cblxuICAvKipcbiAgICogUkVTRVRfU1RBVFNcbiAgICpcbiAgICogUmVzZXQgdGhlIHN0YXRpc3RpY3MgZWFjaCBzZXJ2ZXIgaXMga2VlcGluZyBiYWNrIHRvIHplcm8uIFRoaXMgZG9lc24ndCBjbGVhclxuICAgKiBzdGF0cyBzdWNoIGFzIGl0ZW0gY291bnQsIGJ1dCB0ZW1wb3Jhcnkgc3RhdHMgc3VjaCBhcyB0b3RhbCBudW1iZXIgb2ZcbiAgICogY29ubmVjdGlvbnMgb3ZlciB0aW1lLlxuICAgKlxuICAgKiBUaGUgY2FsbGJhY2sgaXMgaW52b2tlZCAqKk9OQ0UgUEVSIFNFUlZFUioqIGFuZCBoYXMgdGhlIHNpZ25hdHVyZTpcbiAgICpcbiAgICogICAgIGNhbGxiYWNrKGVyciwgc2VydmVyKVxuICAgKlxuICAgKiBfc2VydmVyXyBpcyB0aGUgYFwiaG9zdG5hbWU6cG9ydFwiYCBvZiB0aGUgc2VydmVyLlxuICAgKiBAcGFyYW0gY2FsbGJhY2tcbiAgICovXG4gIHJlc2V0U3RhdHMoXG4gICAgY2FsbGJhY2s/OiAoXG4gICAgICBlcnI6IEVycm9yIHwgbnVsbCxcbiAgICAgIHNlcnZlcjogc3RyaW5nLFxuICAgICAgc3RhdHM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gfCBudWxsXG4gICAgKSA9PiB2b2lkXG4gICk6IHZvaWQge1xuICAgIHRoaXMuc3RhdHNXaXRoS2V5KFwicmVzZXRcIiwgY2FsbGJhY2spO1xuICB9XG5cbiAgLyoqXG4gICAqIFFVSVRcbiAgICpcbiAgICogQ2xvc2VzIHRoZSBjb25uZWN0aW9uIHRvIGVhY2ggc2VydmVyLCBub3RpZnlpbmcgdGhlbSBvZiB0aGlzIGludGVudGlvbi4gTm90ZVxuICAgKiB0aGF0IHF1aXQgY2FuIHJhY2UgYWdhaW5zdCBhbHJlYWR5IG91dHN0YW5kaW5nIHJlcXVlc3RzIHdoZW4gdGhvc2UgcmVxdWVzdHNcbiAgICogZmFpbCBhbmQgYXJlIHJldHJpZWQsIGxlYWRpbmcgdG8gdGhlIHF1aXQgY29tbWFuZCB3aW5uaW5nIGFuZCBjbG9zaW5nIHRoZVxuICAgKiBjb25uZWN0aW9uIGJlZm9yZSB0aGUgcmV0cmllcyBjb21wbGV0ZS5cbiAgICovXG4gIHF1aXQoKSB7XG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgLy8gVE9ETzogTmljZXIgcGVyaGFwcyB0byBkbyBRVUlUUSAoMHgxNykgYnV0IG5lZWQgYSBuZXcgY2FsbGJhY2sgZm9yIHdoZW5cbiAgICAvLyB3cml0ZSBpcyBkb25lLlxuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcigweDA3LCBcIlwiLCBcIlwiLCBcIlwiLCB0aGlzLnNlcSk7IC8vIFFVSVRcbiAgICBsZXQgc2VydjtcblxuICAgIGNvbnN0IGhhbmRsZVF1aXQgPSBmdW5jdGlvbiAoc2VxOiBudW1iZXIsIHNlcnY6IFNlcnZlcikge1xuICAgICAgc2Vydi5vblJlc3BvbnNlKHNlcSwgZnVuY3Rpb24gKC8qIHJlc3BvbnNlICovKSB7XG4gICAgICAgIHNlcnYuY2xvc2UoKTtcbiAgICAgIH0pO1xuICAgICAgc2Vydi5vbkVycm9yKHNlcSwgZnVuY3Rpb24gKC8qIGVyciAqLykge1xuICAgICAgICBzZXJ2LmNsb3NlKCk7XG4gICAgICB9KTtcbiAgICAgIHNlcnYud3JpdGUocmVxdWVzdCk7XG4gICAgfTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5zZXJ2ZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBzZXJ2ID0gdGhpcy5zZXJ2ZXJzW2ldO1xuICAgICAgaGFuZGxlUXVpdCh0aGlzLnNlcSwgc2Vydik7XG4gICAgfVxuICB9XG5cbiAgX3ZlcnNpb24oc2VydmVyOiBTZXJ2ZXIpOiBQcm9taXNlPHsgdmFsdWU6IFZhbHVlIHwgbnVsbCB9PiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIHRoaXMuaW5jclNlcSgpO1xuICAgICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKFxuICAgICAgICBjb25zdGFudHMuT1BfVkVSU0lPTixcbiAgICAgICAgXCJcIixcbiAgICAgICAgXCJcIixcbiAgICAgICAgXCJcIixcbiAgICAgICAgdGhpcy5zZXFcbiAgICAgICk7XG4gICAgICB0aGlzLnBlcmZvcm1PblNlcnZlcihzZXJ2ZXIsIHJlcXVlc3QsIHRoaXMuc2VxLCAoZXJyLCByZXNwb25zZSkgPT4ge1xuICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgcmV0dXJuIHJlamVjdChlcnIpO1xuICAgICAgICB9XG5cbiAgICAgICAgc3dpdGNoIChyZXNwb25zZSEuaGVhZGVyLnN0YXR1cykge1xuICAgICAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgICAgIC8qIFRPRE86IHRoaXMgaXMgYnVnZ2VkLCB3ZSBzaG91bGQndCB1c2UgdGhlIGRlc2VyaWFsaXplciBoZXJlLCBzaW5jZSB2ZXJzaW9uIGFsd2F5cyByZXR1cm5zIGEgdmVyc2lvbiBzdHJpbmcuXG4gICAgICAgICAgICAgVGhlIGRlc2VyaWFsaXplciBzaG91bGQgb25seSBiZSB1c2VkIG9uIHVzZXIga2V5IGRhdGEuICovXG4gICAgICAgICAgICBjb25zdCBkZXNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuZGVzZXJpYWxpemUoXG4gICAgICAgICAgICAgIHJlc3BvbnNlIS5oZWFkZXIub3Bjb2RlLFxuICAgICAgICAgICAgICByZXNwb25zZSEudmFsLFxuICAgICAgICAgICAgICByZXNwb25zZSEuZXh0cmFzXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgcmV0dXJuIHJlc29sdmUoeyB2YWx1ZTogZGVzZXJpYWxpemVkLnZhbHVlIH0pO1xuICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICByZXR1cm4gcmVqZWN0KFxuICAgICAgICAgICAgICB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiVkVSU0lPTlwiLCByZXNwb25zZSEuaGVhZGVyLnN0YXR1cylcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlcXVlc3QgdGhlIHNlcnZlciB2ZXJzaW9uIGZyb20gdGhlIFwiZmlyc3RcIiBzZXJ2ZXIgaW4gdGhlIGJhY2tlbmQgcG9vbC5cbiAgICogVGhlIHNlcnZlciByZXNwb25kcyB3aXRoIGEgcGFja2V0IGNvbnRhaW5pbmcgdGhlIHZlcnNpb24gc3RyaW5nIGluIHRoZSBib2R5IHdpdGggdGhlIGZvbGxvd2luZyBmb3JtYXQ6IFwieC55LnpcIlxuICAgKi9cbiAgdmVyc2lvbigpOiBQcm9taXNlPHsgdmFsdWU6IFZhbHVlIHwgbnVsbCB9PiB7XG4gICAgY29uc3Qgc2VydmVyID0gdGhpcy5zZXJ2ZXJLZXlUb1NlcnZlcih0aGlzLnNlcnZlcktleXNbMF0pO1xuICAgIHJldHVybiB0aGlzLl92ZXJzaW9uKHNlcnZlcik7XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldmVzIHRoZSBzZXJ2ZXIgdmVyc2lvbiBmcm9tIGFsbCB0aGUgc2VydmVyc1xuICAgKiBpbiB0aGUgYmFja2VuZCBwb29sLCBlcnJvcnMgaWYgYW55IG9uZSBvZiB0aGVtIGhhcyBhblxuICAgKiBlcnJvclxuICAgKi9cbiAgYXN5bmMgdmVyc2lvbkFsbCh0cmllZENhbGxiYWNrPzogKHJlc3BvbnNlOiBzdHJpbmcpID0+IHZvaWQsIHJlc3VsdENhbGxiYWNrPzogKHJlc3BvbnNlOiBzdHJpbmcpID0+IHZvaWQpOiBQcm9taXNlPHtcbiAgICB2YWx1ZXM6IFJlY29yZDxzdHJpbmcsIFZhbHVlIHwgbnVsbD47XG4gIH0+IHtcbiAgICBjb25zdCB2ZXJzaW9uT2JqZWN0cyA9IGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgdGhpcy5zZXJ2ZXJLZXlzLm1hcCgoc2VydmVyS2V5KSA9PiB7XG4gICAgICAgIGlmICh0cmllZENhbGxiYWNrICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICB0cmllZENhbGxiYWNrKHNlcnZlcktleSk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3Qgc2VydmVyID0gdGhpcy5zZXJ2ZXJLZXlUb1NlcnZlcihzZXJ2ZXJLZXkpO1xuICAgICAgICByZXR1cm4gdGhpcy5fdmVyc2lvbihzZXJ2ZXIpLnRoZW4oKHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgaWYgKHJlc3VsdENhbGxiYWNrICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHJlc3VsdENhbGxiYWNrKHNlcnZlcktleSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiB7IHNlcnZlcktleTogc2VydmVyS2V5LCB2YWx1ZTogcmVzcG9uc2UudmFsdWUgfTtcbiAgICAgICAgfSk7XG4gICAgICB9KVxuICAgICk7XG4gICAgY29uc3QgdmFsdWVzID0gdmVyc2lvbk9iamVjdHMucmVkdWNlKChhY2N1bXVsYXRvciwgdmVyc2lvbk9iamVjdCkgPT4ge1xuICAgICAgYWNjdW11bGF0b3JbdmVyc2lvbk9iamVjdC5zZXJ2ZXJLZXldID0gdmVyc2lvbk9iamVjdC52YWx1ZTtcbiAgICAgIHJldHVybiBhY2N1bXVsYXRvcjtcbiAgICB9LCB7fSBhcyBSZWNvcmQ8c3RyaW5nLCBWYWx1ZSB8IG51bGw+KTtcbiAgICByZXR1cm4geyB2YWx1ZXM6IHZhbHVlcyB9O1xuICB9XG5cbiAgLyoqXG4gICAqIENsb3NlcyAoYWJydXB0bHkpIGNvbm5lY3Rpb25zIHRvIGFsbCB0aGUgc2VydmVycy5cbiAgICogQHNlZSB0aGlzLnF1aXRcbiAgICovXG4gIGNsb3NlKCkge1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5zZXJ2ZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB0aGlzLnNlcnZlcnNbaV0uY2xvc2UoKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUGVyZm9ybSBhIGdlbmVyaWMgc2luZ2xlIHJlc3BvbnNlIG9wZXJhdGlvbiAoZ2V0LCBzZXQgZXRjKSBvbiBvbmUgc2VydmVyXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgdGhlIGtleSB0byBoYXNoIHRvIGdldCBhIHNlcnZlciBmcm9tIHRoZSBwb29sXG4gICAqIEBwYXJhbSB7YnVmZmVyfSByZXF1ZXN0IGEgYnVmZmVyIGNvbnRhaW5pbmcgdGhlIHJlcXVlc3RcbiAgICogQHBhcmFtIHtudW1iZXJ9IHNlcSB0aGUgc2VxdWVuY2UgbnVtYmVyIG9mIHRoZSBvcGVyYXRpb24uIEl0IGlzIHVzZWQgdG8gcGluIHRoZSBjYWxsYmFja3NcbiAgICAgICAgICAgICAgICAgICAgICAgICB0byBhIHNwZWNpZmljIG9wZXJhdGlvbiBhbmQgc2hvdWxkIG5ldmVyIGNoYW5nZSBkdXJpbmcgYSBgcGVyZm9ybWAuXG4gICAqIEBwYXJhbSB7bnVtYmVyP30gcmV0cmllcyBudW1iZXIgb2YgdGltZXMgdG8gcmV0cnkgcmVxdWVzdCBvbiBmYWlsdXJlXG4gICAqL1xuICBwZXJmb3JtKFxuICAgIGtleTogc3RyaW5nLFxuICAgIHJlcXVlc3Q6IEJ1ZmZlcixcbiAgICBzZXE6IG51bWJlcixcbiAgICByZXRyaWVzPzogbnVtYmVyXG4gICk6IFByb21pc2U8TWVzc2FnZT4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBjb25zdCBzZXJ2ZXJLZXkgPSB0aGlzLmxvb2t1cEtleVRvU2VydmVyS2V5KGtleSk7XG4gICAgICBjb25zdCBzZXJ2ZXIgPSB0aGlzLnNlcnZlcktleVRvU2VydmVyKHNlcnZlcktleSk7XG5cbiAgICAgIGlmICghc2VydmVyKSB7XG4gICAgICAgIHJldHVybiByZWplY3QobmV3IEVycm9yKFwiTm8gc2VydmVycyBhdmFpbGFibGVcIikpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLnBlcmZvcm1PblNlcnZlcihcbiAgICAgICAgc2VydmVyLFxuICAgICAgICByZXF1ZXN0LFxuICAgICAgICBzZXEsXG4gICAgICAgIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgIHJldHVybiByZWplY3QoZXJyb3IpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXNvbHZlKHJlc3BvbnNlISk7XG4gICAgICAgIH0sXG4gICAgICAgIHJldHJpZXNcbiAgICAgICk7XG4gICAgfSk7XG4gIH1cblxuICBwZXJmb3JtT25TZXJ2ZXIoXG4gICAgc2VydmVyOiBTZXJ2ZXIsXG4gICAgcmVxdWVzdDogQnVmZmVyLFxuICAgIHNlcTogbnVtYmVyLFxuICAgIGNhbGxiYWNrOiBSZXNwb25zZU9yRXJyb3JDYWxsYmFjayxcbiAgICByZXRyaWVzOiBudW1iZXIgPSAwXG4gICkge1xuICAgIGNvbnN0IF90aGlzID0gdGhpcztcblxuICAgIHJldHJpZXMgPSByZXRyaWVzIHx8IHRoaXMub3B0aW9ucy5yZXRyaWVzO1xuICAgIGNvbnN0IG9yaWdSZXRyaWVzID0gdGhpcy5vcHRpb25zLnJldHJpZXM7XG4gICAgY29uc3QgbG9nZ2VyID0gdGhpcy5vcHRpb25zLmxvZ2dlcjtcbiAgICBjb25zdCByZXRyeV9kZWxheSA9IHRoaXMub3B0aW9ucy5yZXRyeV9kZWxheTtcblxuICAgIGNvbnN0IHJlc3BvbnNlSGFuZGxlcjogT25SZXNwb25zZUNhbGxiYWNrID0gZnVuY3Rpb24gKHJlc3BvbnNlKSB7XG4gICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgY2FsbGJhY2sobnVsbCwgcmVzcG9uc2UpO1xuICAgICAgfVxuICAgIH07XG5cbiAgICBjb25zdCBlcnJvckhhbmRsZXI6IE9uRXJyb3JDYWxsYmFjayA9IGZ1bmN0aW9uIChlcnJvcikge1xuICAgICAgaWYgKC0tcmV0cmllcyA+IDApIHtcbiAgICAgICAgLy8gV2FpdCBmb3IgcmV0cnlfZGVsYXlcbiAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgX3RoaXMucGVyZm9ybU9uU2VydmVyKHNlcnZlciwgcmVxdWVzdCwgc2VxLCBjYWxsYmFjaywgcmV0cmllcyk7XG4gICAgICAgIH0sIDEwMDAgKiByZXRyeV9kZWxheSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBsb2dnZXIubG9nKFxuICAgICAgICAgIFwiTWVtSlM6IFNlcnZlciA8XCIgK1xuICAgICAgICAgICAgc2VydmVyLmhvc3Rwb3J0U3RyaW5nKCkgK1xuICAgICAgICAgICAgXCI+IGZhaWxlZCBhZnRlciAoXCIgK1xuICAgICAgICAgICAgb3JpZ1JldHJpZXMgK1xuICAgICAgICAgICAgXCIpIHJldHJpZXMgd2l0aCBlcnJvciAtIFwiICtcbiAgICAgICAgICAgIGVycm9yLm1lc3NhZ2VcbiAgICAgICAgKTtcbiAgICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgICAgY2FsbGJhY2soZXJyb3IsIG51bGwpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfTtcblxuICAgIHNlcnZlci5vblJlc3BvbnNlKHNlcSwgcmVzcG9uc2VIYW5kbGVyKTtcbiAgICBzZXJ2ZXIub25FcnJvcihzZXEsIGVycm9ySGFuZGxlcik7XG4gICAgc2VydmVyLndyaXRlKHJlcXVlc3QpO1xuICB9XG5cbiAgLy8gSW5jcmVtZW50IHRoZSBzZXEgdmFsdWVcbiAgaW5jclNlcSgpIHtcbiAgICB0aGlzLnNlcSsrO1xuXG4gICAgLy8gV3JhcCBgdGhpcy5zZXFgIHRvIDMyLWJpdHMgc2luY2UgdGhlIGZpZWxkIHdlIGZpdCBpdCBpbnRvIGlzIG9ubHkgMzItYml0cy5cbiAgICB0aGlzLnNlcSAmPSAweGZmZmZmZmZmO1xuXG4gICAgcmV0dXJuIHRoaXMuc2VxXG4gIH1cblxuICBwcml2YXRlIGNyZWF0ZUFuZExvZ0Vycm9yKFxuICAgIGNvbW1hbmROYW1lOiBzdHJpbmcsXG4gICAgcmVzcG9uc2VTdGF0dXM6IFJlc3BvbnNlU3RhdHVzIHwgdW5kZWZpbmVkXG4gICk6IEVycm9yIHtcbiAgICBjb25zdCBlcnJvck1lc3NhZ2UgPSBgTWVtSlMgJHtjb21tYW5kTmFtZX06ICR7Y29uc3RhbnRzLnJlc3BvbnNlU3RhdHVzVG9TdHJpbmcoXG4gICAgICByZXNwb25zZVN0YXR1c1xuICAgICl9YDtcbiAgICB0aGlzLm9wdGlvbnMubG9nZ2VyLmxvZyhlcnJvck1lc3NhZ2UpO1xuICAgIHJldHVybiBuZXcgRXJyb3IoZXJyb3JNZXNzYWdlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBMb2cgYW4gZXJyb3IgdG8gdGhlIGxvZ2dlciwgdGhlbiByZXR1cm4gdGhlIGVycm9yLlxuICAgKiBJZiBhIGNhbGxiYWNrIGlzIGdpdmVuLCBjYWxsIGl0IHdpdGggY2FsbGJhY2soZXJyb3IsIG51bGwpLlxuICAgKi9cbiAgcHJpdmF0ZSBoYW5kbGVSZXNwb25zZUVycm9yKFxuICAgIGNvbW1hbmROYW1lOiBzdHJpbmcsXG4gICAgcmVzcG9uc2VTdGF0dXM6IFJlc3BvbnNlU3RhdHVzIHwgdW5kZWZpbmVkLFxuICAgIGNhbGxiYWNrOiB1bmRlZmluZWQgfCAoKGVycm9yOiBFcnJvciB8IG51bGwsIG90aGVyOiBudWxsKSA9PiB2b2lkKVxuICApOiBFcnJvciB7XG4gICAgY29uc3QgZXJyb3IgPSB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKGNvbW1hbmROYW1lLCByZXNwb25zZVN0YXR1cyk7XG4gICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICBjYWxsYmFjayhlcnJvciwgbnVsbCk7XG4gICAgfVxuICAgIHJldHVybiBlcnJvcjtcbiAgfVxufVxuXG5leHBvcnQgeyBDbGllbnQsIFNlcnZlciwgVXRpbHMsIEhlYWRlciB9O1xuIl19 \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVtanMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbWVtanMvbWVtanMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLHdCQUF3Qjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUV4QixxQ0FLa0I7QUF3aUNELHVGQTFpQ2YsZUFBTSxPQTBpQ2U7QUF2aUN2Qix1REFBK0Q7QUFDL0QsbUNBU2lCO0FBQ2pCLHVEQUF5QztBQUN6QywyQ0FBNkM7QUFDN0MsK0NBQWlDO0FBMGhDUixzQkFBSztBQXpoQzlCLGlEQUFtQztBQXloQ0gsd0JBQU07QUF2aEN0QyxTQUFTLDhCQUE4QixDQUNyQyxPQUFpQixFQUNqQixHQUFXO0lBRVgsTUFBTSxLQUFLLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQztJQUM3QixNQUFNLEtBQUssR0FBRyxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxnQkFBUSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3BELE9BQU8sT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ3hCLENBQUM7QUFFRCwrQ0FBK0M7QUFDL0MsU0FBUyxTQUFTLENBQ2hCLE9BQTBFO0lBRTFFLE9BQU8sSUFBSSxPQUFPLENBQUMsVUFBVSxPQUFPLEVBQUUsTUFBTTtRQUMxQyxPQUFPLENBQUMsVUFBVSxHQUFHLEVBQUUsTUFBTTtZQUMzQixHQUFHLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3RDLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBeURELE1BQU0sTUFBTTtJQVFWLDRFQUE0RTtJQUM1RSxtQ0FBbUM7SUFDbkMsWUFBWSxPQUFpQixFQUFFLE9BQTBDO1FBQ3ZFLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO1FBQ3ZCLElB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QixFQUNuQixjQUEwQztRQUUxQyxNQUFNLFlBQVksR0FBRyxTQUFTLFdBQVcsS0FBSyxTQUFTLENBQUMsc0JBQXNCLENBQzVFLGNBQWMsQ0FDZixFQUFFLENBQUM7UUFDSixJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDdEMsT0FBTyxJQUFJLEtBQUssQ0FBQyxZQUFZLENBQUMsQ0FBQztJQUNqQyxDQUFDO0lBRUQ7OztPQUdHO0lBQ0ssbUJBQW1CLENBQ3pCLFdBQW1CLEVBQ25CLGNBQTBDLEVBQzFDLFFBQWtFO1FBRWxFLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxXQUFXLEVBQUUsY0FBYyxDQUFDLENBQUM7UUFDbEUsSUFBSSxRQUFRLEVBQUU7WUFDWixRQUFRLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxDQUFDO1NBQ3ZCO1FBQ0QsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0NBQ0Y7QUFFUSx3QkFBTSIsInNvdXJjZXNDb250ZW50IjpbIi8vIE1lbVRTIE1lbWNhY2hlIENsaWVudFxuXG5pbXBvcnQge1xuICBPbkVycm9yQ2FsbGJhY2ssXG4gIE9uUmVzcG9uc2VDYWxsYmFjayxcbiAgU2VydmVyLFxuICBTZXJ2ZXJPcHRpb25zLFxufSBmcm9tIFwiLi9zZXJ2ZXJcIjtcbmltcG9ydCB7IG5vb3BTZXJpYWxpemVyLCBTZXJpYWxpemVyIH0gZnJvbSBcIi4vbm9vcC1zZXJpYWxpemVyXCI7XG5pbXBvcnQge1xuICBtYWtlUmVxdWVzdEJ1ZmZlcixcbiAgY29weUludG9SZXF1ZXN0QnVmZmVyLFxuICBtZXJnZSxcbiAgbWFrZUV4cGlyYXRpb24sXG4gIG1ha2VBbW91bnRJbml0aWFsQW5kRXhwaXJhdGlvbixcbiAgaGFzaENvZGUsXG4gIE1heWJlQnVmZmVyLFxuICBNZXNzYWdlLFxufSBmcm9tIFwiLi91dGlsc1wiO1xuaW1wb3J0ICogYXMgY29uc3RhbnRzIGZyb20gXCIuL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgUmVzcG9uc2VTdGF0dXMgfSBmcm9tIFwiLi9jb25zdGFudHNcIjtcbmltcG9ydCAqIGFzIFV0aWxzIGZyb20gXCIuL3V0aWxzXCI7XG5pbXBvcnQgKiBhcyBIZWFkZXIgZnJvbSBcIi4vaGVhZGVyXCI7XG5cbmZ1bmN0aW9uIGRlZmF1bHRLZXlUb1NlcnZlckhhc2hGdW5jdGlvbihcbiAgc2VydmVyczogc3RyaW5nW10sXG4gIGtleTogc3RyaW5nXG4pOiBzdHJpbmcge1xuICBjb25zdCB0b3RhbCA9IHNlcnZlcnMubGVuZ3RoO1xuICBjb25zdCBpbmRleCA9IHRvdGFsID4gMSA/IGhhc2hDb2RlKGtleSkgJSB0b3RhbCA6IDA7XG4gIHJldHVybiBzZXJ2ZXJzW2luZGV4XTtcbn1cblxuLy8gY29udmVydHMgYSBjYWxsIGludG8gYSBwcm9taXNlLXJldHVybmluZyBvbmVcbmZ1bmN0aW9uIHByb21pc2lmeTxSZXN1bHQ+KFxuICBjb21tYW5kOiAoY2FsbGJhY2s6IChlcnJvcjogRXJyb3IgfCBudWxsLCByZXN1bHQ6IFJlc3VsdCkgPT4gdm9pZCkgPT4gdm9pZFxuKTogUHJvbWlzZTxSZXN1bHQ+IHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICBjb21tYW5kKGZ1bmN0aW9uIChlcnIsIHJlc3VsdCkge1xuICAgICAgZXJyID8gcmVqZWN0KGVycikgOiByZXNvbHZlKHJlc3VsdCk7XG4gICAgfSk7XG4gIH0pO1xufVxuXG50eXBlIFJlc3BvbnNlT3JFcnJvckNhbGxiYWNrID0gKFxuICBlcnJvcjogRXJyb3IgfCBudWxsLFxuICByZXNwb25zZTogTWVzc2FnZSB8IG51bGxcbikgPT4gdm9pZDtcblxuaW50ZXJmYWNlIEJhc2VDbGllbnRPcHRpb25zIHtcbiAgcmV0cmllczogbnVtYmVyO1xuICByZXRyeV9kZWxheTogbnVtYmVyO1xuICBleHBpcmVzOiBudW1iZXI7XG4gIGxvZ2dlcjogeyBsb2c6IHR5cGVvZiBjb25zb2xlLmxvZyB9O1xuICBrZXlUb1NlcnZlckhhc2hGdW5jdGlvbjogdHlwZW9mIGRlZmF1bHRLZXlUb1NlcnZlckhhc2hGdW5jdGlvbjtcbn1cblxuaW50ZXJmYWNlIFNlcmlhbGl6ZXJQcm9wPFZhbHVlLCBFeHRyYXM+IHtcbiAgc2VyaWFsaXplcjogU2VyaWFsaXplcjxWYWx1ZSwgRXh0cmFzPjtcbn1cblxuLyoqXG4gKiBUaGUgY2xpZW50IGhhcyBwYXJ0aWFsIHN1cHBvcnQgZm9yIHNlcmlhbGl6aW5nIGFuZCBkZXNlcmlhbGl6aW5nIHZhbHVlcyBmcm9tIHRoZVxuICogQnVmZmVyIGJ5dGUgc3RyaW5ncyB3ZSByZWNlaXZlIGZyb20gdGhlIHdpcmUuIFRoZSBkZWZhdWx0IHNlcmlhbGl6ZXIgaXMgZm9yIE1heWJlQnVmZmVyLlxuICpcbiAqIElmIFZhbHVlIGFuZCBFeHRyYXMgYXJlIG9mIHR5cGUgQnVmZmVyLCB0aGVuIHJldHVybiB0eXBlIFdoZW5CdWZmZXIuIE90aGVyd2lzZSxcbiAqIHJldHVybiB0eXBlIE5vdEJ1ZmZlci5cbiAqL1xudHlwZSBJZkJ1ZmZlcjxWYWx1ZSwgRXh0cmFzLCBXaGVuVmFsdWVBbmRFeHRyYXNBcmVCdWZmZXJzLCBOb3RCdWZmZXI+ID1cbiAgVmFsdWUgZXh0ZW5kcyBCdWZmZXJcbiAgICA/IEV4dHJhcyBleHRlbmRzIEJ1ZmZlclxuICAgICAgPyBXaGVuVmFsdWVBbmRFeHRyYXNBcmVCdWZmZXJzXG4gICAgICA6IE5vdEJ1ZmZlclxuICAgIDogTm90QnVmZmVyO1xuXG5leHBvcnQgdHlwZSBHaXZlbkNsaWVudE9wdGlvbnM8VmFsdWUsIEV4dHJhcz4gPSBQYXJ0aWFsPEJhc2VDbGllbnRPcHRpb25zPiAmXG4gIElmQnVmZmVyPFxuICAgIFZhbHVlLFxuICAgIEV4dHJhcyxcbiAgICBQYXJ0aWFsPFNlcmlhbGl6ZXJQcm9wPFZhbHVlLCBFeHRyYXM+PixcbiAgICBTZXJpYWxpemVyUHJvcDxWYWx1ZSwgRXh0cmFzPlxuICA+O1xuXG5leHBvcnQgdHlwZSBDQVNUb2tlbiA9IEJ1ZmZlcjtcblxuZXhwb3J0IGludGVyZmFjZSBHZXRSZXN1bHQ8VmFsdWUgPSBNYXliZUJ1ZmZlciwgRXh0cmFzID0gTWF5YmVCdWZmZXI+IHtcbiAgdmFsdWU6IFZhbHVlO1xuICBleHRyYXM6IEV4dHJhcztcbiAgY2FzOiBDQVNUb2tlbiB8IHVuZGVmaW5lZDtcbn1cblxuZXhwb3J0IHR5cGUgR2V0TXVsdGlSZXN1bHQ8XG4gIEtleXMgZXh0ZW5kcyBzdHJpbmcgPSBzdHJpbmcsXG4gIFZhbHVlID0gTWF5YmVCdWZmZXIsXG4gIEV4dHJhcyA9IE1heWJlQnVmZmVyXG4+ID0ge1xuICBbSyBpbiBLZXlzXT86IEdldFJlc3VsdDxWYWx1ZSwgRXh0cmFzPjtcbn07XG5cbmNsYXNzIENsaWVudDxWYWx1ZSA9IE1heWJlQnVmZmVyLCBFeHRyYXMgPSBNYXliZUJ1ZmZlcj4ge1xuICBzZXJ2ZXJzOiBTZXJ2ZXJbXTtcbiAgc2VxOiBudW1iZXI7XG4gIG9wdGlvbnM6IEJhc2VDbGllbnRPcHRpb25zICYgUGFydGlhbDxTZXJpYWxpemVyUHJvcDxWYWx1ZSwgRXh0cmFzPj47XG4gIHNlcmlhbGl6ZXI6IFNlcmlhbGl6ZXI8VmFsdWUsIEV4dHJhcz47XG4gIHNlcnZlck1hcDogeyBbaG9zdHBvcnQ6IHN0cmluZ106IFNlcnZlciB9O1xuICBzZXJ2ZXJLZXlzOiBzdHJpbmdbXTtcblxuICAvLyBDbGllbnQgaW5pdGlhbGl6ZXIgdGFrZXMgYSBsaXN0IG9mIGBTZXJ2ZXJgcyBhbmQgYW4gYG9wdGlvbnNgIGRpY3Rpb25hcnkuXG4gIC8vIFNlZSBgQ2xpZW50LmNyZWF0ZWAgZm9yIGRldGFpbHMuXG4gIGNvbnN0cnVjdG9yKHNlcnZlcnM6IFNlcnZlcltdLCBvcHRpb25zOiBHaXZlbkNsaWVudE9wdGlvbnM8VmFsdWUsIEV4dHJhcz4pIHtcbiAgICB0aGlzLnNlcnZlcnMgPSBzZXJ2ZXJzO1xuICAgIHRoaXMuc2VxID0gMDtcbiAgICB0aGlzLm9wdGlvbnMgPSBtZXJnZShvcHRpb25zIHx8IHt9LCB7XG4gICAgICByZXRyaWVzOiAyLFxuICAgICAgcmV0cnlfZGVsYXk6IDAuMixcbiAgICAgIGV4cGlyZXM6IDAsXG4gICAgICBsb2dnZXI6IGNvbnNvbGUsXG4gICAgICBrZXlUb1NlcnZlckhhc2hGdW5jdGlvbjogZGVmYXVsdEtleVRvU2VydmVySGFzaEZ1bmN0aW9uLFxuICAgIH0pO1xuXG4gICAgdGhpcy5zZXJpYWxpemVyID0gdGhpcy5vcHRpb25zLnNlcmlhbGl6ZXIgfHwgKG5vb3BTZXJpYWxpemVyIGFzIGFueSk7XG5cbiAgICAvLyBTdG9yZSBhIG1hcHBpbmcgZnJvbSBob3N0cG9ydCAtPiBzZXJ2ZXIgc28gd2UgY2FuIHF1aWNrbHkgZ2V0IGEgc2VydmVyIG9iamVjdCBmcm9tIHRoZSBzZXJ2ZXJLZXkgcmV0dXJuZWQgYnkgdGhlIGhhc2hpbmcgZnVuY3Rpb25cbiAgICBjb25zdCBzZXJ2ZXJNYXA6IHsgW2hvc3Rwb3J0OiBzdHJpbmddOiBTZXJ2ZXIgfSA9IHt9O1xuICAgIHRoaXMuc2VydmVycy5mb3JFYWNoKGZ1bmN0aW9uIChzZXJ2ZXIpIHtcbiAgICAgIHNlcnZlck1hcFtzZXJ2ZXIuaG9zdHBvcnRTdHJpbmcoKV0gPSBzZXJ2ZXI7XG4gICAgfSk7XG4gICAgdGhpcy5zZXJ2ZXJNYXAgPSBzZXJ2ZXJNYXA7XG5cbiAgICAvLyBzdG9yZSBhIGxpc3Qgb2YgYWxsIG91ciBzZXJ2ZXJLZXlzIHNvIHdlIGRvbid0IG5lZWQgdG8gY29uc3RhbnRseSByZWFsbG9jYXRlIHRoaXMgYXJyYXlcbiAgICB0aGlzLnNlcnZlcktleXMgPSBPYmplY3Qua2V5cyh0aGlzLnNlcnZlck1hcCk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIG5ldyBjbGllbnQgZ2l2ZW4gYW4gb3B0aW9uYWwgY29uZmlnIHN0cmluZyBhbmQgb3B0aW9uYWwgaGFzaCBvZlxuICAgKiBvcHRpb25zLiBUaGUgY29uZmlnIHN0cmluZyBzaG91bGQgYmUgb2YgdGhlIGZvcm06XG4gICAqXG4gICAqICAgICBcIlt1c2VyOnBhc3NAXXNlcnZlcjFbOjExMjExXSxbdXNlcjpwYXNzQF1zZXJ2ZXIyWzoxMTIxMV0sLi4uXCJcbiAgICpcbiAgICogSWYgdGhlIGFyZ3VtZW50IGlzIG5vdCBnaXZlbiwgZmFsbGJhY2sgb24gdGhlIGBNRU1DQUNISUVSX1NFUlZFUlNgIGVudmlyb25tZW50XG4gICAqIHZhcmlhYmxlLCBgTUVNQ0FDSEVfU0VSVkVSU2AgZW52aXJvbm1lbnQgdmFyaWFibGUgb3IgYFwibG9jYWxob3N0OjExMjExXCJgLlxuICAgKlxuICAgKiBUaGUgb3B0aW9ucyBoYXNoIG1heSBjb250YWluIHRoZSBvcHRpb25zOlxuICAgKlxuICAgKiAqIGByZXRyaWVzYCAtIHRoZSBudW1iZXIgb2YgdGltZXMgdG8gcmV0cnkgYW4gb3BlcmF0aW9uIGluIGxpZXUgb2YgZmFpbHVyZXNcbiAgICogKGRlZmF1bHQgMilcbiAgICogKiBgZXhwaXJlc2AgLSB0aGUgZGVmYXVsdCBleHBpcmF0aW9uIGluIHNlY29uZHMgdG8gdXNlIChkZWZhdWx0IDAgLSBuZXZlclxuICAgKiBleHBpcmUpLiBJZiBgZXhwaXJlc2AgaXMgZ3JlYXRlciB0aGFuIDMwIGRheXMgKDYwIHggNjAgeCAyNCB4IDMwKSwgaXQgaXNcbiAgICogdHJlYXRlZCBhcyBhIFVOSVggdGltZSAobnVtYmVyIG9mIHNlY29uZHMgc2luY2UgSmFudWFyeSAxLCAxOTcwKS5cbiAgICogKiBgbG9nZ2VyYCAtIGEgbG9nZ2VyIG9iamVjdCB0aGF0IHJlc3BvbmRzIHRvIGBsb2coc3RyaW5nKWAgbWV0aG9kIGNhbGxzLlxuICAgKlxuICAgKiAgIH5+fn5cbiAgICogICAgIGxvZyhtc2cxWywgbXNnMlssIG1zZzNbLi4uXV1dKVxuICAgKiAgIH5+fn5cbiAgICpcbiAgICogICBEZWZhdWx0cyB0byBgY29uc29sZWAuXG4gICAqICogYHNlcmlhbGl6ZXJgIC0gdGhlIG9iamVjdCB3aGljaCB3aWxsIChkZSlzZXJpYWxpemUgdGhlIGRhdGEuIEl0IG5lZWRzXG4gICAqICAgdHdvIHB1YmxpYyBtZXRob2RzOiBzZXJpYWxpemUgYW5kIGRlc2VyaWFsaXplLiBJdCBkZWZhdWx0cyB0byB0aGVcbiAgICogICBub29wU2VyaWFsaXplcjpcbiAgICpcbiAgICogICB+fn5+XG4gICAqICAgY29uc3Qgbm9vcFNlcmlhbGl6ZXIgPSB7XG4gICAqICAgICBzZXJpYWxpemU6IGZ1bmN0aW9uIChvcGNvZGUsIHZhbHVlLCBleHRyYXMpIHtcbiAgICogICAgICAgcmV0dXJuIHsgdmFsdWU6IHZhbHVlLCBleHRyYXM6IGV4dHJhcyB9O1xuICAgKiAgICAgfSxcbiAgICogICAgIGRlc2VyaWFsaXplOiBmdW5jdGlvbiAob3Bjb2RlLCB2YWx1ZSwgZXh0cmFzKSB7XG4gICAqICAgICAgIHJldHVybiB7IHZhbHVlOiB2YWx1ZSwgZXh0cmFzOiBleHRyYXMgfTtcbiAgICogICAgIH1cbiAgICogICB9O1xuICAgKiAgIH5+fn5cbiAgICpcbiAgICogT3Igb3B0aW9ucyBmb3IgdGhlIHNlcnZlcnMgaW5jbHVkaW5nOlxuICAgKiAqIGB1c2VybmFtZWAgYW5kIGBwYXNzd29yZGAgZm9yIGZhbGxiYWNrIFNBU0wgYXV0aGVudGljYXRpb24gY3JlZGVudGlhbHMuXG4gICAqICogYHRpbWVvdXRgIGluIHNlY29uZHMgdG8gZGV0ZXJtaW5lIGZhaWx1cmUgZm9yIG9wZXJhdGlvbnMuIERlZmF1bHQgaXMgMC41XG4gICAqICAgICAgICAgICAgIHNlY29uZHMuXG4gICAqICogJ2Nvbm50aW1lb3V0JyBpbiBzZWNvbmRzIHRvIGNvbm5lY3Rpb24gZmFpbHVyZS4gRGVmYXVsdCBpcyB0d2ljZSB0aGUgdmFsdWVcbiAgICogICAgICAgICAgICAgICAgIG9mIGB0aW1lb3V0YC5cbiAgICogKiBga2VlcEFsaXZlYCB3aGV0aGVyIHRvIGVuYWJsZSBrZWVwLWFsaXZlIGZ1bmN0aW9uYWxpdHkuIERlZmF1bHRzIHRvIGZhbHNlLlxuICAgKiAqIGBrZWVwQWxpdmVEZWxheWAgaW4gc2Vjb25kcyB0byB0aGUgaW5pdGlhbCBkZWxheSBiZWZvcmUgdGhlIGZpcnN0IGtlZXBhbGl2ZVxuICAgKiAgICAgICAgICAgICAgICAgICAgcHJvYmUgaXMgc2VudCBvbiBhbiBpZGxlIHNvY2tldC4gRGVmYXVsdHMgaXMgMzAgc2Vjb25kcy5cbiAgICogKiBga2V5VG9TZXJ2ZXJIYXNoRnVuY3Rpb25gIGEgZnVuY3Rpb24gdG8gbWFwIGtleXMgdG8gc2VydmVycywgd2l0aCB0aGUgc2lnbmF0dXJlXG4gICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgIChzZXJ2ZXJLZXlzOiBzdHJpbmdbXSwga2V5OiBzdHJpbmcpOiBzdHJpbmdcbiAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgTk9URTogaWYgeW91IG5lZWQgdG8gZG8gc29tZSBleHBlbnNpdmUgaW5pdGlhbGl6YXRpb24sICpwbGVhc2UqIGRvIGl0IGxhemlseSB0aGUgZmlyc3QgdGltZSB5b3UgdGhpcyBmdW5jdGlvbiBpcyBjYWxsZWQgd2l0aCBhbiBhcnJheSBvZiBzZXJ2ZXJLZXlzLCBub3Qgb24gZXZlcnkgY2FsbFxuICAgKi9cbiAgc3RhdGljIGNyZWF0ZTxWYWx1ZSwgRXh0cmFzPihcbiAgICBzZXJ2ZXJzU3RyOiBzdHJpbmcgfCB1bmRlZmluZWQsXG4gICAgb3B0aW9uczogSWZCdWZmZXI8XG4gICAgICBWYWx1ZSxcbiAgICAgIEV4dHJhcyxcbiAgICAgIHVuZGVmaW5lZCB8IChQYXJ0aWFsPFNlcnZlck9wdGlvbnM+ICYgR2l2ZW5DbGllbnRPcHRpb25zPFZhbHVlLCBFeHRyYXM+KSxcbiAgICAgIFBhcnRpYWw8U2VydmVyT3B0aW9ucz4gJiBHaXZlbkNsaWVudE9wdGlvbnM8VmFsdWUsIEV4dHJhcz5cbiAgICA+XG4gICk6IENsaWVudDxWYWx1ZSwgRXh0cmFzPiB7XG4gICAgc2VydmVyc1N0ciA9XG4gICAgICBzZXJ2ZXJzU3RyIHx8XG4gICAgICBwcm9jZXNzLmVudi5NRU1DQUNISUVSX1NFUlZFUlMgfHxcbiAgICAgIHByb2Nlc3MuZW52Lk1FTUNBQ0hFX1NFUlZFUlMgfHxcbiAgICAgIFwibG9jYWxob3N0OjExMjExXCI7XG4gICAgY29uc3Qgc2VydmVyVXJpcyA9IHNlcnZlcnNTdHIuc3BsaXQoXCIsXCIpO1xuICAgIGNvbnN0IHNlcnZlcnMgPSBzZXJ2ZXJVcmlzLm1hcChmdW5jdGlvbiAodXJpKSB7XG4gICAgICBjb25zdCB1cmlQYXJ0cyA9IHVyaS5zcGxpdChcIkBcIik7XG4gICAgICBjb25zdCBob3N0UG9ydCA9IHVyaVBhcnRzW3VyaVBhcnRzLmxlbmd0aCAtIDFdLnNwbGl0KFwiOlwiKTtcbiAgICAgIGNvbnN0IHVzZXJQYXNzID0gKHVyaVBhcnRzW3VyaVBhcnRzLmxlbmd0aCAtIDJdIHx8IFwiXCIpLnNwbGl0KFwiOlwiKTtcbiAgICAgIHJldHVybiBuZXcgU2VydmVyKFxuICAgICAgICBob3N0UG9ydFswXSxcbiAgICAgICAgcGFyc2VJbnQoaG9zdFBvcnRbMV0gfHwgXCIxMTIxMVwiLCAxMCksXG4gICAgICAgIHVzZXJQYXNzWzBdLFxuICAgICAgICB1c2VyUGFzc1sxXSxcbiAgICAgICAgb3B0aW9uc1xuICAgICAgKTtcbiAgICB9KTtcbiAgICByZXR1cm4gbmV3IENsaWVudChzZXJ2ZXJzLCBvcHRpb25zIGFzIGFueSk7XG4gIH1cblxuICAvKipcbiAgICogR2l2ZW4gYSBzZXJ2ZXJLZXkgZnJvbWxvb2t1cEtleVRvU2VydmVyS2V5LCByZXR1cm4gdGhlIGNvcnJlc3BvbmRpbmcgU2VydmVyIGluc3RhbmNlXG4gICAqXG4gICAqIEBwYXJhbSAge3N0cmluZ30gc2VydmVyS2V5XG4gICAqIEByZXR1cm5zIHtTZXJ2ZXJ9XG4gICAqL1xuICBzZXJ2ZXJLZXlUb1NlcnZlcihzZXJ2ZXJLZXk6IHN0cmluZyk6IFNlcnZlciB7XG4gICAgcmV0dXJuIHRoaXMuc2VydmVyTWFwW3NlcnZlcktleV07XG4gIH1cblxuICAvKipcbiAgICogR2l2ZW4gYSBrZXkgdG8gbG9vayB1cCBpbiBtZW1jYWNoZSwgcmV0dXJuIGEgc2VydmVyS2V5IChiYXNlZCBvbiBzb21lXG4gICAqIGhhc2hpbmcgZnVuY3Rpb24pIHdoaWNoIGNhbiBiZSB1c2VkIHRvIGluZGV4IHRoaXMuc2VydmVyTWFwXG4gICAqL1xuICBsb29rdXBLZXlUb1NlcnZlcktleShrZXk6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMub3B0aW9ucy5rZXlUb1NlcnZlckhhc2hGdW5jdGlvbih0aGlzLnNlcnZlcktleXMsIGtleSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldmVzIHRoZSB2YWx1ZSBhdCB0aGUgZ2l2ZW4ga2V5IGluIG1lbWNhY2hlLlxuICAgKi9cbiAgYXN5bmMgZ2V0KGtleTogc3RyaW5nKTogUHJvbWlzZTxHZXRSZXN1bHQ8VmFsdWUsIEV4dHJhcz4gfCBudWxsPiB7XG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKGNvbnN0YW50cy5PUF9HRVQsIGtleSwgXCJcIiwgXCJcIiwgdGhpcy5zZXEpO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICBjb25zdCBkZXNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuZGVzZXJpYWxpemUoXG4gICAgICAgICAgcmVzcG9uc2UuaGVhZGVyLm9wY29kZSxcbiAgICAgICAgICByZXNwb25zZS52YWwsXG4gICAgICAgICAgcmVzcG9uc2UuZXh0cmFzXG4gICAgICAgICk7XG4gICAgICAgIHJldHVybiB7IC4uLmRlc2VyaWFsaXplZCwgY2FzOiByZXNwb25zZS5oZWFkZXIuY2FzIH07XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIkdFVFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKiogQnVpbGQgYSBwaXBlbGluZWQgZ2V0IG11bHRpIHJlcXVlc3QgYnkgc2VuZGluZyBvbmUgR0VUS1EgZm9yIGVhY2gga2V5IChxdWlldCwgbWVhbmluZyBpdCB3b24ndCByZXNwb25kIGlmIHRoZSB2YWx1ZSBpcyBtaXNzaW5nKSBmb2xsb3dlZCBieSBhIG5vLW9wIHRvIGZvcmNlIGEgcmVzcG9uc2UgKGFuZCB0byBnaXZlIHVzIGEgc2VudGluZWwgcmVzcG9uc2UgdGhhdCB0aGUgcGlwZWxpbmUgaXMgZG9uZSlcbiAgICpcbiAgICogY2YgaHR0cHM6Ly9naXRodWIuY29tL2NvdWNoYmFzZS9tZW1jYWNoZWQvYmxvYi9tYXN0ZXIvZG9jcy9CaW5hcnlQcm90b2NvbC5tZCMweDBkLWdldGtxLWdldC13aXRoLWtleS1xdWlldGx5XG4gICAqL1xuICBfYnVpbGRHZXRNdWx0aVJlcXVlc3Qoa2V5czogc3RyaW5nW10sIHNlcTogbnVtYmVyKTogQnVmZmVyIHtcbiAgICAvLyBzdGFydCBhdCAyNCBmb3IgdGhlIG5vLW9wIGNvbW1hbmQgYXQgdGhlIGVuZFxuICAgIGxldCByZXF1ZXN0U2l6ZSA9IDI0O1xuICAgIGZvciAoY29uc3Qga2V5SWR4IGluIGtleXMpIHtcbiAgICAgIHJlcXVlc3RTaXplICs9IEJ1ZmZlci5ieXRlTGVuZ3RoKGtleXNba2V5SWR4XSwgXCJ1dGY4XCIpICsgMjQ7XG4gICAgfVxuXG4gICAgY29uc3QgcmVxdWVzdCA9IEJ1ZmZlci5hbGxvYyhyZXF1ZXN0U2l6ZSk7XG5cbiAgICBsZXQgYnl0ZXNXcml0dGVuID0gMDtcbiAgICBmb3IgKGNvbnN0IGtleUlkeCBpbiBrZXlzKSB7XG4gICAgICBjb25zdCBrZXkgPSBrZXlzW2tleUlkeF07XG4gICAgICBieXRlc1dyaXR0ZW4gKz0gY29weUludG9SZXF1ZXN0QnVmZmVyKFxuICAgICAgICBjb25zdGFudHMuT1BfR0VUS1EsXG4gICAgICAgIGtleSxcbiAgICAgICAgXCJcIixcbiAgICAgICAgXCJcIixcbiAgICAgICAgc2VxLFxuICAgICAgICByZXF1ZXN0LFxuICAgICAgICBieXRlc1dyaXR0ZW5cbiAgICAgICk7XG4gICAgfVxuXG4gICAgYnl0ZXNXcml0dGVuICs9IGNvcHlJbnRvUmVxdWVzdEJ1ZmZlcihcbiAgICAgIGNvbnN0YW50cy5PUF9OT19PUCxcbiAgICAgIFwiXCIsXG4gICAgICBcIlwiLFxuICAgICAgXCJcIixcbiAgICAgIHNlcSxcbiAgICAgIHJlcXVlc3QsXG4gICAgICBieXRlc1dyaXR0ZW5cbiAgICApO1xuXG4gICAgcmV0dXJuIHJlcXVlc3Q7XG4gIH1cblxuICAvKiogRXhlY3V0aW5nIGEgcGlwZWxpbmVkIChtdWx0aSkgZ2V0IGFnYWluc3QgYSBzaW5nbGUgc2VydmVyLiBUaGlzIGlzIGEgcHJpdmF0ZSBpbXBsZW1lbnRhdGlvbiBkZXRhaWwgb2YgZ2V0TXVsdGkuICovXG4gIGFzeW5jIF9nZXRNdWx0aVRvU2VydmVyPEtleXMgZXh0ZW5kcyBzdHJpbmc+KFxuICAgIHNlcnY6IFNlcnZlcixcbiAgICBrZXlzOiBLZXlzW11cbiAgKTogUHJvbWlzZTxHZXRNdWx0aVJlc3VsdDxLZXlzLCBWYWx1ZSwgRXh0cmFzPj4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBjb25zdCByZXNwb25zZU1hcDogR2V0TXVsdGlSZXN1bHQ8c3RyaW5nLCBWYWx1ZSwgRXh0cmFzPiA9IHt9O1xuXG4gICAgICBjb25zdCBoYW5kbGU6IE9uUmVzcG9uc2VDYWxsYmFjayA9IChyZXNwb25zZSkgPT4ge1xuICAgICAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgICAgICAvLyBXaGVuIHdlIGdldCB0aGUgbm8tb3AgcmVzcG9uc2UsIHdlIGFyZSBkb25lIHdpdGggdGhpcyBvbmUgZ2V0TXVsdGkgaW4gdGhlIHBlci1iYWNrZW5kIGZhbi1vdXRcbiAgICAgICAgICAgIGlmIChyZXNwb25zZS5oZWFkZXIub3Bjb2RlID09PSBjb25zdGFudHMuT1BfTk9fT1ApIHtcbiAgICAgICAgICAgICAgLy8gVGhpcyBlbnN1cmVzIHRoZSBoYW5kbGVyIHdpbGwgYmUgZGVsZXRlZCBmcm9tIHRoZSByZXNwb25zZUNhbGxiYWNrcyBtYXAgaW4gc2VydmVyLmpzXG4gICAgICAgICAgICAgIC8vIFRoaXMgaXNuJ3QgdGVjaG5pY2FsbHkgbmVlZGVkIGhlcmUgYmVjYXVzZSB0aGUgbG9naWMgaW4gc2VydmVyLmpzIGFsc28gY2hlY2tzIGlmIHRvdGFsQm9keUxlbmd0aCA9PT0gMCwgYnV0IG91ciB1bml0dGVzdHMgYXJlbid0IGdyZWF0IGFib3V0IHNldHRpbmcgdGhhdCBmaWVsZCwgYW5kIGFsc28gdGhpcyBtYWtlcyBpdCBtb3JlIGV4cGxpY2l0XG4gICAgICAgICAgICAgIGhhbmRsZS5xdWlldCA9IGZhbHNlO1xuICAgICAgICAgICAgICByZXNvbHZlKHJlc3BvbnNlTWFwKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgICAgICAgIHJlc3BvbnNlLmhlYWRlci5vcGNvZGUgPT09IGNvbnN0YW50cy5PUF9HRVRLIHx8XG4gICAgICAgICAgICAgIHJlc3BvbnNlLmhlYWRlci5vcGNvZGUgPT09IGNvbnN0YW50cy5PUF9HRVRLUVxuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgIGNvbnN0IGRlc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5kZXNlcmlhbGl6ZShcbiAgICAgICAgICAgICAgICByZXNwb25zZS5oZWFkZXIub3Bjb2RlLFxuICAgICAgICAgICAgICAgIHJlc3BvbnNlLnZhbCxcbiAgICAgICAgICAgICAgICByZXNwb25zZS5leHRyYXNcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgY29uc3Qga2V5ID0gcmVzcG9uc2Uua2V5LnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgIGlmIChrZXkubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlamVjdChcbiAgICAgICAgICAgICAgICAgIG5ldyBFcnJvcihcbiAgICAgICAgICAgICAgICAgICAgXCJSZWNpZXZlZCBlbXB0eSBrZXkgaW4gZ2V0TXVsdGk6IFwiICtcbiAgICAgICAgICAgICAgICAgICAgICBKU09OLnN0cmluZ2lmeShyZXNwb25zZSlcbiAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIHJlc3BvbnNlTWFwW2tleV0gPSB7IC4uLmRlc2VyaWFsaXplZCwgY2FzOiByZXNwb25zZS5oZWFkZXIuY2FzIH07XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICByZXR1cm4gcmVqZWN0KFxuICAgICAgICAgICAgICAgIG5ldyBFcnJvcihcbiAgICAgICAgICAgICAgICAgIFwiUmVjaWV2ZWQgcmVzcG9uc2UgaW4gZ2V0TXVsdGkgZm9yIHVua25vd24gb3Bjb2RlOiBcIiArXG4gICAgICAgICAgICAgICAgICAgIEpTT04uc3RyaW5naWZ5KHJlc3BvbnNlKVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICByZXR1cm4gcmVqZWN0KFxuICAgICAgICAgICAgICB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiR0VUXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9O1xuICAgICAgLy8gVGhpcyBwcmV2ZW50cyB0aGUgaGFuZGxlciBmcm9tIGJlaW5nIGRlbGV0ZWRcbiAgICAgIC8vIGFmdGVyIHRoZSBmaXJzdCByZXNwb25zZS4gTG9naWMgaW4gc2VydmVyLmpzLlxuICAgICAgaGFuZGxlLnF1aWV0ID0gdHJ1ZTtcblxuICAgICAgY29uc3Qgc2VxID0gdGhpcy5pbmNyU2VxKCk7XG4gICAgICBjb25zdCByZXF1ZXN0ID0gdGhpcy5fYnVpbGRHZXRNdWx0aVJlcXVlc3Qoa2V5cywgc2VxKTtcbiAgICAgIHNlcnYub25SZXNwb25zZSh0aGlzLnNlcSwgaGFuZGxlKTtcbiAgICAgIHNlcnYub25FcnJvcih0aGlzLnNlcSwgcmVqZWN0KTtcbiAgICAgIHNlcnYud3JpdGUocmVxdWVzdCk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldnMgdGhlIHZhbHVlIGF0IHRoZSBnaXZlbiBrZXlzIGluIG1lbWNhY2hlZC4gUmV0dXJucyBhIG1hcCBmcm9tIHRoZVxuICAgKiByZXF1ZXN0ZWQga2V5cyB0byByZXN1bHRzLCBvciBudWxsIGlmIHRoZSBrZXkgd2FzIG5vdCBmb3VuZC5cbiAgICovXG4gIGFzeW5jIGdldE11bHRpPEtleXMgZXh0ZW5kcyBzdHJpbmc+KFxuICAgIGtleXM6IEtleXNbXVxuICApOiBQcm9taXNlPEdldE11bHRpUmVzdWx0PEtleXMsIFZhbHVlLCBFeHRyYXM+PiB7XG4gICAgY29uc3Qgc2VydmVyS2V5dG9Mb29rdXBLZXlzOiB7XG4gICAgICBbc2VydmVyS2V5OiBzdHJpbmddOiBzdHJpbmdbXTtcbiAgICB9ID0ge307XG4gICAga2V5cy5mb3JFYWNoKChsb29rdXBLZXkpID0+IHtcbiAgICAgIGNvbnN0IHNlcnZlcktleSA9IHRoaXMubG9va3VwS2V5VG9TZXJ2ZXJLZXkobG9va3VwS2V5KTtcbiAgICAgIGlmICghc2VydmVyS2V5dG9Mb29rdXBLZXlzW3NlcnZlcktleV0pIHtcbiAgICAgICAgc2VydmVyS2V5dG9Mb29rdXBLZXlzW3NlcnZlcktleV0gPSBbXTtcbiAgICAgIH1cbiAgICAgIHNlcnZlcktleXRvTG9va3VwS2V5c1tzZXJ2ZXJLZXldLnB1c2gobG9va3VwS2V5KTtcbiAgICB9KTtcblxuICAgIGNvbnN0IHVzZWRTZXJ2ZXJLZXlzID0gT2JqZWN0LmtleXMoc2VydmVyS2V5dG9Mb29rdXBLZXlzKTtcbiAgICBjb25zdCByZXN1bHRzID0gYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICB1c2VkU2VydmVyS2V5cy5tYXAoKHNlcnZlcktleSkgPT4ge1xuICAgICAgICBjb25zdCBzZXJ2ZXIgPSB0aGlzLnNlcnZlcktleVRvU2VydmVyKHNlcnZlcktleSk7XG4gICAgICAgIHJldHVybiB0aGlzLl9nZXRNdWx0aVRvU2VydmVyKHNlcnZlciwgc2VydmVyS2V5dG9Mb29rdXBLZXlzW3NlcnZlcktleV0pO1xuICAgICAgfSlcbiAgICApO1xuXG4gICAgcmV0dXJuIE9iamVjdC5hc3NpZ24oe30sIC4uLnJlc3VsdHMpO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgYGtleWAgdG8gYHZhbHVlYC5cbiAgICovXG4gIGFzeW5jIHNldChcbiAgICBrZXk6IHN0cmluZyxcbiAgICB2YWx1ZTogVmFsdWUsXG4gICAgb3B0aW9ucz86IHsgZXhwaXJlcz86IG51bWJlcjsgY2FzPzogQ0FTVG9rZW4gfVxuICApOiBQcm9taXNlPGJvb2xlYW4gfCBudWxsPiB7XG4gICAgY29uc3QgZXhwaXJlcyA9IG9wdGlvbnM/LmV4cGlyZXM7XG4gICAgY29uc3QgY2FzID0gb3B0aW9ucz8uY2FzO1xuXG4gICAgLy8gVE9ETzogc3VwcG9ydCBmbGFnc1xuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IGV4cGlyYXRpb24gPSBtYWtlRXhwaXJhdGlvbihleHBpcmVzIHx8IHRoaXMub3B0aW9ucy5leHBpcmVzKTtcbiAgICBjb25zdCBleHRyYXMgPSBCdWZmZXIuY29uY2F0KFtCdWZmZXIuZnJvbShcIjAwMDAwMDAwXCIsIFwiaGV4XCIpLCBleHBpcmF0aW9uXSk7XG4gICAgY29uc3Qgc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5zZXJpYWxpemUoXG4gICAgICBjb25zdGFudHMuT1BfU0VULFxuICAgICAgdmFsdWUsXG4gICAgICBleHRyYXNcbiAgICApO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBVdGlscy5lbmNvZGVSZXF1ZXN0KHtcbiAgICAgIGhlYWRlcjoge1xuICAgICAgICBvcGNvZGU6IGNvbnN0YW50cy5PUF9TRVQsXG4gICAgICAgIG9wYXF1ZTogdGhpcy5zZXEsXG4gICAgICAgIGNhcyxcbiAgICAgIH0sXG4gICAgICBrZXksXG4gICAgICB2YWx1ZTogc2VyaWFsaXplZC52YWx1ZSxcbiAgICAgIGV4dHJhczogc2VyaWFsaXplZC5leHRyYXMsXG4gICAgfSk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfRVhJU1RTOlxuICAgICAgICBpZiAoY2FzKSB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJTRVRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgICAgIH1cbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJTRVRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEFERFxuICAgKlxuICAgKiBBZGRzIHRoZSBnaXZlbiBfa2V5XyBhbmQgX3ZhbHVlXyB0byBtZW1jYWNoZS4gVGhlIG9wZXJhdGlvbiBvbmx5IHN1Y2NlZWRzXG4gICAqIGlmIHRoZSBrZXkgaXMgbm90IGFscmVhZHkgc2V0LlxuICAgKlxuICAgKiBUaGUgb3B0aW9ucyBkaWN0aW9uYXJ5IHRha2VzOlxuICAgKiAqIF9leHBpcmVzXzogb3ZlcnJpZGVzIHRoZSBkZWZhdWx0IGV4cGlyYXRpb24gKHNlZSBgQ2xpZW50LmNyZWF0ZWApIGZvciB0aGlzXG4gICAqICAgICAgICAgICAgICBwYXJ0aWN1bGFyIGtleS12YWx1ZSBwYWlyLlxuICAgKi9cbiAgYXN5bmMgYWRkKFxuICAgIGtleTogc3RyaW5nLFxuICAgIHZhbHVlOiBWYWx1ZSxcbiAgICBvcHRpb25zPzogeyBleHBpcmVzPzogbnVtYmVyIH1cbiAgKTogUHJvbWlzZTxib29sZWFuIHwgbnVsbD4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgZmxhZ3MsIHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IGV4cGlyYXRpb24gPSBtYWtlRXhwaXJhdGlvbihvcHRpb25zPy5leHBpcmVzIHx8IHRoaXMub3B0aW9ucy5leHBpcmVzKTtcbiAgICBjb25zdCBleHRyYXMgPSBCdWZmZXIuY29uY2F0KFtCdWZmZXIuZnJvbShcIjAwMDAwMDAwXCIsIFwiaGV4XCIpLCBleHBpcmF0aW9uXSk7XG5cbiAgICBjb25zdCBvcGNvZGUgPSBjb25zdGFudHMuT1BfQUREO1xuICAgIGNvbnN0IHNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuc2VyaWFsaXplKG9wY29kZSwgdmFsdWUsIGV4dHJhcyk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKFxuICAgICAgb3Bjb2RlLFxuICAgICAga2V5LFxuICAgICAgc2VyaWFsaXplZC5leHRyYXMsXG4gICAgICBzZXJpYWxpemVkLnZhbHVlLFxuICAgICAgdGhpcy5zZXFcbiAgICApO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuS0VZX0VYSVNUUzpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJBRERcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlcGxhY2VzIHRoZSBnaXZlbiBfa2V5XyBhbmQgX3ZhbHVlXyB0byBtZW1jYWNoZS4gVGhlIG9wZXJhdGlvbiBvbmx5IHN1Y2NlZWRzXG4gICAqIGlmIHRoZSBrZXkgaXMgYWxyZWFkeSBwcmVzZW50LlxuICAgKi9cbiAgYXN5bmMgcmVwbGFjZShcbiAgICBrZXk6IHN0cmluZyxcbiAgICB2YWx1ZTogVmFsdWUsXG4gICAgb3B0aW9ucz86IHsgZXhwaXJlcz86IG51bWJlciB9XG4gICk6IFByb21pc2U8Ym9vbGVhbiB8IG51bGw+IHtcbiAgICAvLyBUT0RPOiBzdXBwb3J0IGZsYWdzLCBzdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBleHBpcmF0aW9uID0gbWFrZUV4cGlyYXRpb24ob3B0aW9ucz8uZXhwaXJlcyB8fCB0aGlzLm9wdGlvbnMuZXhwaXJlcyk7XG4gICAgY29uc3QgZXh0cmFzID0gQnVmZmVyLmNvbmNhdChbQnVmZmVyLmZyb20oXCIwMDAwMDAwMFwiLCBcImhleFwiKSwgZXhwaXJhdGlvbl0pO1xuXG4gICAgY29uc3Qgb3Bjb2RlOiBjb25zdGFudHMuT1AgPSBjb25zdGFudHMuT1BfUkVQTEFDRTtcbiAgICBjb25zdCBzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLnNlcmlhbGl6ZShvcGNvZGUsIHZhbHVlLCBleHRyYXMpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgIG9wY29kZSxcbiAgICAgIGtleSxcbiAgICAgIHNlcmlhbGl6ZWQuZXh0cmFzLFxuICAgICAgc2VyaWFsaXplZC52YWx1ZSxcbiAgICAgIHRoaXMuc2VxXG4gICAgKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJSRVBMQUNFXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBEZWxldGVzIHRoZSBnaXZlbiBfa2V5XyBmcm9tIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHNcbiAgICogaWYgdGhlIGtleSBpcyBhbHJlYWR5IHByZXNlbnQuXG4gICAqL1xuICBhc3luYyBkZWxldGUoa2V5OiBzdHJpbmcpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAvLyBUT0RPOiBTdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoNCwga2V5LCBcIlwiLCBcIlwiLCB0aGlzLnNlcSk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG5cbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJERUxFVEVcIiwgcmVzcG9uc2U/LmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBJbmNyZW1lbnRzIHRoZSBnaXZlbiBfa2V5XyBpbiBtZW1jYWNoZS5cbiAgICovXG4gIGFzeW5jIGluY3JlbWVudChcbiAgICBrZXk6IHN0cmluZyxcbiAgICBhbW91bnQ6IG51bWJlcixcbiAgICBvcHRpb25zPzogeyBpbml0aWFsPzogbnVtYmVyOyBleHBpcmVzPzogbnVtYmVyIH1cbiAgKTogUHJvbWlzZTx7IHZhbHVlOiBudW1iZXIgfCBudWxsOyBzdWNjZXNzOiBib29sZWFuIHwgbnVsbCB9PiB7XG4gICAgLy8gVE9ETzogc3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgaW5pdGlhbCA9IG9wdGlvbnM/LmluaXRpYWwgfHwgMDtcbiAgICBjb25zdCBleHBpcmVzID0gb3B0aW9ucz8uZXhwaXJlcyB8fCB0aGlzLm9wdGlvbnMuZXhwaXJlcztcbiAgICBjb25zdCBleHRyYXMgPSBtYWtlQW1vdW50SW5pdGlhbEFuZEV4cGlyYXRpb24oYW1vdW50LCBpbml0aWFsLCBleHBpcmVzKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICBjb25zdGFudHMuT1BfSU5DUkVNRU5ULFxuICAgICAga2V5LFxuICAgICAgZXh0cmFzLFxuICAgICAgXCJcIixcbiAgICAgIHRoaXMuc2VxXG4gICAgKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgY29uc3QgYnVmSW50ID1cbiAgICAgICAgICAocmVzcG9uc2UudmFsLnJlYWRVSW50MzJCRSgwKSA8PCA4KSArIHJlc3BvbnNlLnZhbC5yZWFkVUludDMyQkUoNCk7XG4gICAgICAgIHJldHVybiB7IHZhbHVlOiBidWZJbnQsIHN1Y2Nlc3M6IHRydWUgfTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJJTkNSRU1FTlRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIERlY3JlbWVudHMgdGhlIGdpdmVuIGBrZXlgIGluIG1lbWNhY2hlLlxuICAgKi9cbiAgYXN5bmMgZGVjcmVtZW50KFxuICAgIGtleTogc3RyaW5nLFxuICAgIGFtb3VudDogbnVtYmVyLFxuICAgIG9wdGlvbnM6IHsgaW5pdGlhbD86IG51bWJlcjsgZXhwaXJlcz86IG51bWJlciB9XG4gICk6IFByb21pc2U8eyB2YWx1ZTogbnVtYmVyIHwgbnVsbDsgc3VjY2VzczogYm9vbGVhbiB8IG51bGwgfT4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IGluaXRpYWwgPSBvcHRpb25zLmluaXRpYWwgfHwgMDtcbiAgICBjb25zdCBleHBpcmVzID0gb3B0aW9ucy5leHBpcmVzIHx8IHRoaXMub3B0aW9ucy5leHBpcmVzO1xuICAgIGNvbnN0IGV4dHJhcyA9IG1ha2VBbW91bnRJbml0aWFsQW5kRXhwaXJhdGlvbihhbW91bnQsIGluaXRpYWwsIGV4cGlyZXMpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgIGNvbnN0YW50cy5PUF9ERUNSRU1FTlQsXG4gICAgICBrZXksXG4gICAgICBleHRyYXMsXG4gICAgICBcIlwiLFxuICAgICAgdGhpcy5zZXFcbiAgICApO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICBjb25zdCBidWZJbnQgPVxuICAgICAgICAgIChyZXNwb25zZS52YWwucmVhZFVJbnQzMkJFKDApIDw8IDgpICsgcmVzcG9uc2UudmFsLnJlYWRVSW50MzJCRSg0KTtcbiAgICAgICAgcmV0dXJuIHsgdmFsdWU6IGJ1ZkludCwgc3VjY2VzczogdHJ1ZSB9O1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIkRFQ1JFTUVOVFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQXBwZW5kIHRoZSBnaXZlbiBfdmFsdWVfIHRvIHRoZSB2YWx1ZSBhc3NvY2lhdGVkIHdpdGggdGhlIGdpdmVuIF9rZXlfIGluXG4gICAqIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHMgaWYgdGhlIGtleSBpcyBhbHJlYWR5IHByZXNlbnQuXG4gICAqL1xuICBhc3luYyBhcHBlbmQoa2V5OiBzdHJpbmcsIHZhbHVlOiBWYWx1ZSk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IG9wY29kZTogY29uc3RhbnRzLk9QID0gY29uc3RhbnRzLk9QX0FQUEVORDtcbiAgICBjb25zdCBzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLnNlcmlhbGl6ZShvcGNvZGUsIHZhbHVlLCBcIlwiKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICBvcGNvZGUsXG4gICAgICBrZXksXG4gICAgICBzZXJpYWxpemVkLmV4dHJhcyxcbiAgICAgIHNlcmlhbGl6ZWQudmFsdWUsXG4gICAgICB0aGlzLnNlcVxuICAgICk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfTk9UX0ZPVU5EOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiQVBQRU5EXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBQcmVwZW5kIHRoZSBnaXZlbiBfdmFsdWVfIHRvIHRoZSB2YWx1ZSBhc3NvY2lhdGVkIHdpdGggdGhlIGdpdmVuIF9rZXlfIGluXG4gICAqIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHMgaWYgdGhlIGtleSBpcyBhbHJlYWR5IHByZXNlbnQuXG4gICAqL1xuICBhc3luYyBwcmVwZW5kKGtleTogc3RyaW5nLCB2YWx1ZTogVmFsdWUpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAvLyBUT0RPOiBzdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBvcGNvZGU6IGNvbnN0YW50cy5PUCA9IGNvbnN0YW50cy5PUF9QUkVQRU5EO1xuICAgIGNvbnN0IHNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuc2VyaWFsaXplKG9wY29kZSwgdmFsdWUsIFwiXCIpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgIG9wY29kZSxcbiAgICAgIGtleSxcbiAgICAgIHNlcmlhbGl6ZWQuZXh0cmFzLFxuICAgICAgc2VyaWFsaXplZC52YWx1ZSxcbiAgICAgIHRoaXMuc2VxXG4gICAgKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJQUkVQRU5EXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBUb3VjaCBzZXRzIGFuIGV4cGlyYXRpb24gdmFsdWUsIGdpdmVuIGJ5IF9leHBpcmVzXywgb24gdGhlIGdpdmVuIF9rZXlfIGluXG4gICAqIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHMgaWYgdGhlIGtleSBpcyBhbHJlYWR5IHByZXNlbnQuXG4gICAqL1xuICBhc3luYyB0b3VjaChrZXk6IHN0cmluZywgZXhwaXJlczogbnVtYmVyKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgLy8gVE9ETzogc3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgZXh0cmFzID0gbWFrZUV4cGlyYXRpb24oZXhwaXJlcyB8fCB0aGlzLm9wdGlvbnMuZXhwaXJlcyk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKDB4MWMsIGtleSwgZXh0cmFzLCBcIlwiLCB0aGlzLnNlcSk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfTk9UX0ZPVU5EOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiVE9VQ0hcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEZMVVNIXG4gICAqXG4gICAqIEZsdXNoZXMgdGhlIGNhY2hlIG9uIGVhY2ggY29ubmVjdGVkIHNlcnZlci4gVGhlIGNhbGxiYWNrIHNpZ25hdHVyZSBpczpcbiAgICpcbiAgICogICAgIGNhbGxiYWNrKGxhc3RFcnIsIHJlc3VsdHMpXG4gICAqXG4gICAqIHdoZXJlIF9sYXN0RXJyXyBpcyB0aGUgbGFzdCBlcnJvciBlbmNvdW50ZXJlZCAob3IgbnVsbCwgaW4gdGhlIGNvbW1vbiBjYXNlXG4gICAqIG9mIG5vIGVycm9ycykuIF9yZXN1bHRzXyBpcyBhIGRpY3Rpb25hcnkgbWFwcGluZyBgXCJob3N0bmFtZTpwb3J0XCJgIHRvIGVpdGhlclxuICAgKiBgdHJ1ZWAgKGlmIHRoZSBvcGVyYXRpb24gd2FzIHN1Y2Nlc3NmdWwpLCBvciBhbiBlcnJvci5cbiAgICogQHBhcmFtIGNhbGxiYWNrXG4gICAqL1xuICBmbHVzaCgpOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIGJvb2xlYW4gfCBFcnJvcj4+O1xuICBmbHVzaChcbiAgICBjYWxsYmFjazogKFxuICAgICAgZXJyOiBFcnJvciB8IG51bGwsXG4gICAgICByZXN1bHRzOiBSZWNvcmQ8c3RyaW5nLCBib29sZWFuIHwgRXJyb3I+XG4gICAgKSA9PiB2b2lkXG4gICk6IHZvaWQ7XG4gIGZsdXNoKFxuICAgIGNhbGxiYWNrPzogKFxuICAgICAgZXJyOiBFcnJvciB8IG51bGwsXG4gICAgICByZXN1bHRzOiBSZWNvcmQ8c3RyaW5nLCBib29sZWFuIHwgRXJyb3I+XG4gICAgKSA9PiB2b2lkXG4gICkge1xuICAgIGlmIChjYWxsYmFjayA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm4gcHJvbWlzaWZ5KChjYWxsYmFjaykgPT4ge1xuICAgICAgICB0aGlzLmZsdXNoKGZ1bmN0aW9uIChlcnIsIHJlc3VsdHMpIHtcbiAgICAgICAgICBjYWxsYmFjayhlcnIsIHJlc3VsdHMpO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH1cbiAgICAvLyBUT0RPOiBzdXBwb3J0IGV4cGlyYXRpb25cbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoMHgwOCwgXCJcIiwgXCJcIiwgXCJcIiwgdGhpcy5zZXEpO1xuICAgIGxldCBjb3VudCA9IHRoaXMuc2VydmVycy5sZW5ndGg7XG4gICAgY29uc3QgcmVzdWx0OiBSZWNvcmQ8c3RyaW5nLCBib29sZWFuIHwgRXJyb3I+ID0ge307XG4gICAgbGV0IGxhc3RFcnI6IEVycm9yIHwgbnVsbCA9IG51bGw7XG5cbiAgICBjb25zdCBoYW5kbGVGbHVzaCA9IGZ1bmN0aW9uIChzZXE6IG51bWJlciwgc2VydjogU2VydmVyKSB7XG4gICAgICBzZXJ2Lm9uUmVzcG9uc2Uoc2VxLCBmdW5jdGlvbiAoLyogcmVzcG9uc2UgKi8pIHtcbiAgICAgICAgY291bnQgLT0gMTtcbiAgICAgICAgcmVzdWx0W3NlcnYuaG9zdHBvcnRTdHJpbmcoKV0gPSB0cnVlO1xuICAgICAgICBpZiAoY2FsbGJhY2sgJiYgY291bnQgPT09IDApIHtcbiAgICAgICAgICBjYWxsYmFjayhsYXN0RXJyLCByZXN1bHQpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHNlcnYub25FcnJvcihzZXEsIGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgICAgY291bnQgLT0gMTtcbiAgICAgICAgbGFzdEVyciA9IGVycjtcbiAgICAgICAgcmVzdWx0W3NlcnYuaG9zdHBvcnRTdHJpbmcoKV0gPSBlcnI7XG4gICAgICAgIGlmIChjYWxsYmFjayAmJiBjb3VudCA9PT0gMCkge1xuICAgICAgICAgIGNhbGxiYWNrKGxhc3RFcnIsIHJlc3VsdCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgc2Vydi53cml0ZShyZXF1ZXN0KTtcbiAgICB9O1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnNlcnZlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGhhbmRsZUZsdXNoKHRoaXMuc2VxLCB0aGlzLnNlcnZlcnNbaV0pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTVEFUU19XSVRIX0tFWVxuICAgKlxuICAgKiBTZW5kcyBhIG1lbWNhY2hlIHN0YXRzIGNvbW1hbmQgd2l0aCBhIGtleSB0byBlYWNoIGNvbm5lY3RlZCBzZXJ2ZXIuIFRoZVxuICAgKiBjYWxsYmFjayBpcyBpbnZva2VkICoqT05DRSBQRVIgU0VSVkVSKiogYW5kIGhhcyB0aGUgc2lnbmF0dXJlOlxuICAgKlxuICAgKiAgICAgY2FsbGJhY2soZXJyLCBzZXJ2ZXIsIHN0YXRzKVxuICAgKlxuICAgKiBfc2VydmVyXyBpcyB0aGUgYFwiaG9zdG5hbWU6cG9ydFwiYCBvZiB0aGUgc2VydmVyLCBhbmQgX3N0YXRzXyBpcyBhIGRpY3Rpb25hcnlcbiAgICogbWFwcGluZyB0aGUgc3RhdCBuYW1lIHRvIHRoZSB2YWx1ZSBvZiB0aGUgc3RhdGlzdGljIGFzIGEgc3RyaW5nLlxuICAgKiBAcGFyYW0ga2V5XG4gICAqIEBwYXJhbSBjYWxsYmFja1xuICAgKi9cbiAgc3RhdHNXaXRoS2V5KFxuICAgIGtleTogc3RyaW5nLFxuICAgIGNhbGxiYWNrPzogKFxuICAgICAgZXJyOiBFcnJvciB8IG51bGwsXG4gICAgICBzZXJ2ZXI6IHN0cmluZyxcbiAgICAgIHN0YXRzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+IHwgbnVsbFxuICAgICkgPT4gdm9pZFxuICApOiB2b2lkIHtcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoMHgxMCwga2V5LCBcIlwiLCBcIlwiLCB0aGlzLnNlcSk7XG5cbiAgICBjb25zdCBoYW5kbGVTdGF0cyA9IChzZXE6IG51bWJlciwgc2VydjogU2VydmVyKSA9PiB7XG4gICAgICBjb25zdCByZXN1bHQ6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcbiAgICAgIGNvbnN0IGhhbmRsZTogT25SZXNwb25zZUNhbGxiYWNrID0gKHJlc3BvbnNlKSA9PiB7XG4gICAgICAgIC8vIGVuZCBvZiBzdGF0IHJlc3BvbnNlc1xuICAgICAgICBpZiAocmVzcG9uc2UuaGVhZGVyLnRvdGFsQm9keUxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgICAgY2FsbGJhY2sobnVsbCwgc2Vydi5ob3N0cG9ydFN0cmluZygpLCByZXN1bHQpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgLy8gcHJvY2VzcyBzaW5nbGUgc3RhdCBsaW5lIHJlc3BvbnNlXG4gICAgICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgICAgIHJlc3VsdFtyZXNwb25zZS5rZXkudG9TdHJpbmcoKV0gPSByZXNwb25zZS52YWwudG9TdHJpbmcoKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICBjb25zdCBlcnJvciA9IHRoaXMuaGFuZGxlUmVzcG9uc2VFcnJvcihcbiAgICAgICAgICAgICAgYFNUQVRTICgke2tleX0pYCxcbiAgICAgICAgICAgICAgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyxcbiAgICAgICAgICAgICAgdW5kZWZpbmVkXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgICAgICAgIGNhbGxiYWNrKGVycm9yLCBzZXJ2Lmhvc3Rwb3J0U3RyaW5nKCksIG51bGwpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9O1xuICAgICAgaGFuZGxlLnF1aWV0ID0gdHJ1ZTtcblxuICAgICAgc2Vydi5vblJlc3BvbnNlKHNlcSwgaGFuZGxlKTtcbiAgICAgIHNlcnYub25FcnJvcihzZXEsIGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgICAgY2FsbGJhY2soZXJyLCBzZXJ2Lmhvc3Rwb3J0U3RyaW5nKCksIG51bGwpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHNlcnYud3JpdGUocmVxdWVzdCk7XG4gICAgfTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5zZXJ2ZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBoYW5kbGVTdGF0cyh0aGlzLnNlcSwgdGhpcy5zZXJ2ZXJzW2ldKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU1RBVFNcbiAgICpcbiAgICogRmV0Y2hlcyBtZW1jYWNoZSBzdGF0cyBmcm9tIGVhY2ggY29ubmVjdGVkIHNlcnZlci4gVGhlIGNhbGxiYWNrIGlzIGludm9rZWRcbiAgICogKipPTkNFIFBFUiBTRVJWRVIqKiBhbmQgaGFzIHRoZSBzaWduYXR1cmU6XG4gICAqXG4gICAqICAgICBjYWxsYmFjayhlcnIsIHNlcnZlciwgc3RhdHMpXG4gICAqXG4gICAqIF9zZXJ2ZXJfIGlzIHRoZSBgXCJob3N0bmFtZTpwb3J0XCJgIG9mIHRoZSBzZXJ2ZXIsIGFuZCBfc3RhdHNfIGlzIGFcbiAgICogZGljdGlvbmFyeSBtYXBwaW5nIHRoZSBzdGF0IG5hbWUgdG8gdGhlIHZhbHVlIG9mIHRoZSBzdGF0aXN0aWMgYXMgYSBzdHJpbmcuXG4gICAqIEBwYXJhbSBjYWxsYmFja1xuICAgKi9cbiAgc3RhdHMoXG4gICAgY2FsbGJhY2s/OiAoXG4gICAgICBlcnI6IEVycm9yIHwgbnVsbCxcbiAgICAgIHNlcnZlcjogc3RyaW5nLFxuICAgICAgc3RhdHM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gfCBudWxsXG4gICAgKSA9PiB2b2lkXG4gICk6IHZvaWQge1xuICAgIHRoaXMuc3RhdHNXaXRoS2V5KFwiXCIsIGNhbGxiYWNrKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSRVNFVF9TVEFUU1xuICAgKlxuICAgKiBSZXNldCB0aGUgc3RhdGlzdGljcyBlYWNoIHNlcnZlciBpcyBrZWVwaW5nIGJhY2sgdG8gemVyby4gVGhpcyBkb2Vzbid0IGNsZWFyXG4gICAqIHN0YXRzIHN1Y2ggYXMgaXRlbSBjb3VudCwgYnV0IHRlbXBvcmFyeSBzdGF0cyBzdWNoIGFzIHRvdGFsIG51bWJlciBvZlxuICAgKiBjb25uZWN0aW9ucyBvdmVyIHRpbWUuXG4gICAqXG4gICAqIFRoZSBjYWxsYmFjayBpcyBpbnZva2VkICoqT05DRSBQRVIgU0VSVkVSKiogYW5kIGhhcyB0aGUgc2lnbmF0dXJlOlxuICAgKlxuICAgKiAgICAgY2FsbGJhY2soZXJyLCBzZXJ2ZXIpXG4gICAqXG4gICAqIF9zZXJ2ZXJfIGlzIHRoZSBgXCJob3N0bmFtZTpwb3J0XCJgIG9mIHRoZSBzZXJ2ZXIuXG4gICAqIEBwYXJhbSBjYWxsYmFja1xuICAgKi9cbiAgcmVzZXRTdGF0cyhcbiAgICBjYWxsYmFjaz86IChcbiAgICAgIGVycjogRXJyb3IgfCBudWxsLFxuICAgICAgc2VydmVyOiBzdHJpbmcsXG4gICAgICBzdGF0czogUmVjb3JkPHN0cmluZywgc3RyaW5nPiB8IG51bGxcbiAgICApID0+IHZvaWRcbiAgKTogdm9pZCB7XG4gICAgdGhpcy5zdGF0c1dpdGhLZXkoXCJyZXNldFwiLCBjYWxsYmFjayk7XG4gIH1cblxuICAvKipcbiAgICogUVVJVFxuICAgKlxuICAgKiBDbG9zZXMgdGhlIGNvbm5lY3Rpb24gdG8gZWFjaCBzZXJ2ZXIsIG5vdGlmeWluZyB0aGVtIG9mIHRoaXMgaW50ZW50aW9uLiBOb3RlXG4gICAqIHRoYXQgcXVpdCBjYW4gcmFjZSBhZ2FpbnN0IGFscmVhZHkgb3V0c3RhbmRpbmcgcmVxdWVzdHMgd2hlbiB0aG9zZSByZXF1ZXN0c1xuICAgKiBmYWlsIGFuZCBhcmUgcmV0cmllZCwgbGVhZGluZyB0byB0aGUgcXVpdCBjb21tYW5kIHdpbm5pbmcgYW5kIGNsb3NpbmcgdGhlXG4gICAqIGNvbm5lY3Rpb24gYmVmb3JlIHRoZSByZXRyaWVzIGNvbXBsZXRlLlxuICAgKi9cbiAgcXVpdCgpIHtcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICAvLyBUT0RPOiBOaWNlciBwZXJoYXBzIHRvIGRvIFFVSVRRICgweDE3KSBidXQgbmVlZCBhIG5ldyBjYWxsYmFjayBmb3Igd2hlblxuICAgIC8vIHdyaXRlIGlzIGRvbmUuXG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKDB4MDcsIFwiXCIsIFwiXCIsIFwiXCIsIHRoaXMuc2VxKTsgLy8gUVVJVFxuICAgIGxldCBzZXJ2O1xuXG4gICAgY29uc3QgaGFuZGxlUXVpdCA9IGZ1bmN0aW9uIChzZXE6IG51bWJlciwgc2VydjogU2VydmVyKSB7XG4gICAgICBzZXJ2Lm9uUmVzcG9uc2Uoc2VxLCBmdW5jdGlvbiAoLyogcmVzcG9uc2UgKi8pIHtcbiAgICAgICAgc2Vydi5jbG9zZSgpO1xuICAgICAgfSk7XG4gICAgICBzZXJ2Lm9uRXJyb3Ioc2VxLCBmdW5jdGlvbiAoLyogZXJyICovKSB7XG4gICAgICAgIHNlcnYuY2xvc2UoKTtcbiAgICAgIH0pO1xuICAgICAgc2Vydi53cml0ZShyZXF1ZXN0KTtcbiAgICB9O1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnNlcnZlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHNlcnYgPSB0aGlzLnNlcnZlcnNbaV07XG4gICAgICBoYW5kbGVRdWl0KHRoaXMuc2VxLCBzZXJ2KTtcbiAgICB9XG4gIH1cblxuICBfdmVyc2lvbihzZXJ2ZXI6IFNlcnZlcik6IFByb21pc2U8eyB2YWx1ZTogVmFsdWUgfCBudWxsIH0+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICAgIGNvbnN0YW50cy5PUF9WRVJTSU9OLFxuICAgICAgICBcIlwiLFxuICAgICAgICBcIlwiLFxuICAgICAgICBcIlwiLFxuICAgICAgICB0aGlzLnNlcVxuICAgICAgKTtcbiAgICAgIHRoaXMucGVyZm9ybU9uU2VydmVyKHNlcnZlciwgcmVxdWVzdCwgdGhpcy5zZXEsIChlcnIsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICByZXR1cm4gcmVqZWN0KGVycik7XG4gICAgICAgIH1cblxuICAgICAgICBzd2l0Y2ggKHJlc3BvbnNlIS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICAgICAgLyogVE9ETzogdGhpcyBpcyBidWdnZWQsIHdlIHNob3VsZCd0IHVzZSB0aGUgZGVzZXJpYWxpemVyIGhlcmUsIHNpbmNlIHZlcnNpb24gYWx3YXlzIHJldHVybnMgYSB2ZXJzaW9uIHN0cmluZy5cbiAgICAgICAgICAgICBUaGUgZGVzZXJpYWxpemVyIHNob3VsZCBvbmx5IGJlIHVzZWQgb24gdXNlciBrZXkgZGF0YS4gKi9cbiAgICAgICAgICAgIGNvbnN0IGRlc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5kZXNlcmlhbGl6ZShcbiAgICAgICAgICAgICAgcmVzcG9uc2UhLmhlYWRlci5vcGNvZGUsXG4gICAgICAgICAgICAgIHJlc3BvbnNlIS52YWwsXG4gICAgICAgICAgICAgIHJlc3BvbnNlIS5leHRyYXNcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICByZXR1cm4gcmVzb2x2ZSh7IHZhbHVlOiBkZXNlcmlhbGl6ZWQudmFsdWUgfSk7XG4gICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHJldHVybiByZWplY3QoXG4gICAgICAgICAgICAgIHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJWRVJTSU9OXCIsIHJlc3BvbnNlIS5oZWFkZXIuc3RhdHVzKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmVxdWVzdCB0aGUgc2VydmVyIHZlcnNpb24gZnJvbSB0aGUgXCJmaXJzdFwiIHNlcnZlciBpbiB0aGUgYmFja2VuZCBwb29sLlxuICAgKiBUaGUgc2VydmVyIHJlc3BvbmRzIHdpdGggYSBwYWNrZXQgY29udGFpbmluZyB0aGUgdmVyc2lvbiBzdHJpbmcgaW4gdGhlIGJvZHkgd2l0aCB0aGUgZm9sbG93aW5nIGZvcm1hdDogXCJ4LnkuelwiXG4gICAqL1xuICB2ZXJzaW9uKCk6IFByb21pc2U8eyB2YWx1ZTogVmFsdWUgfCBudWxsIH0+IHtcbiAgICBjb25zdCBzZXJ2ZXIgPSB0aGlzLnNlcnZlcktleVRvU2VydmVyKHRoaXMuc2VydmVyS2V5c1swXSk7XG4gICAgcmV0dXJuIHRoaXMuX3ZlcnNpb24oc2VydmVyKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXRyaWV2ZXMgdGhlIHNlcnZlciB2ZXJzaW9uIGZyb20gYWxsIHRoZSBzZXJ2ZXJzXG4gICAqIGluIHRoZSBiYWNrZW5kIHBvb2wsIGVycm9ycyBpZiBhbnkgb25lIG9mIHRoZW0gaGFzIGFuXG4gICAqIGVycm9yXG4gICAqL1xuICBhc3luYyB2ZXJzaW9uQWxsKGNhbGxiYWNrcz86IHtcbiAgICBiZWZvcmVQaW5nPzogKHJlc3BvbnNlOiBzdHJpbmcpID0+IHZvaWQ7XG4gICAgYWZ0ZXJQaW5nPzogKHJlc3BvbnNlOiBzdHJpbmcpID0+IHZvaWQ7XG4gIH0pOiBQcm9taXNlPHtcbiAgICB2YWx1ZXM6IFJlY29yZDxzdHJpbmcsIFZhbHVlIHwgbnVsbD47XG4gIH0+IHtcbiAgICBjb25zdCB2ZXJzaW9uT2JqZWN0cyA9IGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgdGhpcy5zZXJ2ZXJLZXlzLm1hcCgoc2VydmVyS2V5KSA9PiB7XG4gICAgICAgIGNvbnN0IHNlcnZlciA9IHRoaXMuc2VydmVyS2V5VG9TZXJ2ZXIoc2VydmVyS2V5KTtcbiAgICAgICAgY2FsbGJhY2tzPy5iZWZvcmVQaW5nPy4oc2VydmVyS2V5KTtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3ZlcnNpb24oc2VydmVyKS50aGVuKChyZXNwb25zZSkgPT4ge1xuICAgICAgICAgIGNhbGxiYWNrcz8uYWZ0ZXJQaW5nPy4oc2VydmVyS2V5KTtcbiAgICAgICAgICByZXR1cm4geyBzZXJ2ZXJLZXk6IHNlcnZlcktleSwgdmFsdWU6IHJlc3BvbnNlLnZhbHVlIH07XG4gICAgICAgIH0pO1xuICAgICAgfSlcbiAgICApO1xuICAgIGNvbnN0IHZhbHVlcyA9IHZlcnNpb25PYmplY3RzLnJlZHVjZSgoYWNjdW11bGF0b3IsIHZlcnNpb25PYmplY3QpID0+IHtcbiAgICAgIGFjY3VtdWxhdG9yW3ZlcnNpb25PYmplY3Quc2VydmVyS2V5XSA9IHZlcnNpb25PYmplY3QudmFsdWU7XG4gICAgICByZXR1cm4gYWNjdW11bGF0b3I7XG4gICAgfSwge30gYXMgUmVjb3JkPHN0cmluZywgVmFsdWUgfCBudWxsPik7XG4gICAgcmV0dXJuIHsgdmFsdWVzOiB2YWx1ZXMgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDbG9zZXMgKGFicnVwdGx5KSBjb25uZWN0aW9ucyB0byBhbGwgdGhlIHNlcnZlcnMuXG4gICAqIEBzZWUgdGhpcy5xdWl0XG4gICAqL1xuICBjbG9zZSgpIHtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuc2VydmVycy5sZW5ndGg7IGkrKykge1xuICAgICAgdGhpcy5zZXJ2ZXJzW2ldLmNsb3NlKCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFBlcmZvcm0gYSBnZW5lcmljIHNpbmdsZSByZXNwb25zZSBvcGVyYXRpb24gKGdldCwgc2V0IGV0Yykgb24gb25lIHNlcnZlclxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IHRoZSBrZXkgdG8gaGFzaCB0byBnZXQgYSBzZXJ2ZXIgZnJvbSB0aGUgcG9vbFxuICAgKiBAcGFyYW0ge2J1ZmZlcn0gcmVxdWVzdCBhIGJ1ZmZlciBjb250YWluaW5nIHRoZSByZXF1ZXN0XG4gICAqIEBwYXJhbSB7bnVtYmVyfSBzZXEgdGhlIHNlcXVlbmNlIG51bWJlciBvZiB0aGUgb3BlcmF0aW9uLiBJdCBpcyB1c2VkIHRvIHBpbiB0aGUgY2FsbGJhY2tzXG4gICAgICAgICAgICAgICAgICAgICAgICAgdG8gYSBzcGVjaWZpYyBvcGVyYXRpb24gYW5kIHNob3VsZCBuZXZlciBjaGFuZ2UgZHVyaW5nIGEgYHBlcmZvcm1gLlxuICAgKiBAcGFyYW0ge251bWJlcj99IHJldHJpZXMgbnVtYmVyIG9mIHRpbWVzIHRvIHJldHJ5IHJlcXVlc3Qgb24gZmFpbHVyZVxuICAgKi9cbiAgcGVyZm9ybShcbiAgICBrZXk6IHN0cmluZyxcbiAgICByZXF1ZXN0OiBCdWZmZXIsXG4gICAgc2VxOiBudW1iZXIsXG4gICAgcmV0cmllcz86IG51bWJlclxuICApOiBQcm9taXNlPE1lc3NhZ2U+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgY29uc3Qgc2VydmVyS2V5ID0gdGhpcy5sb29rdXBLZXlUb1NlcnZlcktleShrZXkpO1xuICAgICAgY29uc3Qgc2VydmVyID0gdGhpcy5zZXJ2ZXJLZXlUb1NlcnZlcihzZXJ2ZXJLZXkpO1xuXG4gICAgICBpZiAoIXNlcnZlcikge1xuICAgICAgICByZXR1cm4gcmVqZWN0KG5ldyBFcnJvcihcIk5vIHNlcnZlcnMgYXZhaWxhYmxlXCIpKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5wZXJmb3JtT25TZXJ2ZXIoXG4gICAgICAgIHNlcnZlcixcbiAgICAgICAgcmVxdWVzdCxcbiAgICAgICAgc2VxLFxuICAgICAgICAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICByZXR1cm4gcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmVzb2x2ZShyZXNwb25zZSEpO1xuICAgICAgICB9LFxuICAgICAgICByZXRyaWVzXG4gICAgICApO1xuICAgIH0pO1xuICB9XG5cbiAgcGVyZm9ybU9uU2VydmVyKFxuICAgIHNlcnZlcjogU2VydmVyLFxuICAgIHJlcXVlc3Q6IEJ1ZmZlcixcbiAgICBzZXE6IG51bWJlcixcbiAgICBjYWxsYmFjazogUmVzcG9uc2VPckVycm9yQ2FsbGJhY2ssXG4gICAgcmV0cmllczogbnVtYmVyID0gMFxuICApIHtcbiAgICBjb25zdCBfdGhpcyA9IHRoaXM7XG5cbiAgICByZXRyaWVzID0gcmV0cmllcyB8fCB0aGlzLm9wdGlvbnMucmV0cmllcztcbiAgICBjb25zdCBvcmlnUmV0cmllcyA9IHRoaXMub3B0aW9ucy5yZXRyaWVzO1xuICAgIGNvbnN0IGxvZ2dlciA9IHRoaXMub3B0aW9ucy5sb2dnZXI7XG4gICAgY29uc3QgcmV0cnlfZGVsYXkgPSB0aGlzLm9wdGlvbnMucmV0cnlfZGVsYXk7XG5cbiAgICBjb25zdCByZXNwb25zZUhhbmRsZXI6IE9uUmVzcG9uc2VDYWxsYmFjayA9IGZ1bmN0aW9uIChyZXNwb25zZSkge1xuICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgIGNhbGxiYWNrKG51bGwsIHJlc3BvbnNlKTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgY29uc3QgZXJyb3JIYW5kbGVyOiBPbkVycm9yQ2FsbGJhY2sgPSBmdW5jdGlvbiAoZXJyb3IpIHtcbiAgICAgIGlmICgtLXJldHJpZXMgPiAwKSB7XG4gICAgICAgIC8vIFdhaXQgZm9yIHJldHJ5X2RlbGF5XG4gICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgIF90aGlzLnBlcmZvcm1PblNlcnZlcihzZXJ2ZXIsIHJlcXVlc3QsIHNlcSwgY2FsbGJhY2ssIHJldHJpZXMpO1xuICAgICAgICB9LCAxMDAwICogcmV0cnlfZGVsYXkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbG9nZ2VyLmxvZyhcbiAgICAgICAgICBcIk1lbUpTOiBTZXJ2ZXIgPFwiICtcbiAgICAgICAgICAgIHNlcnZlci5ob3N0cG9ydFN0cmluZygpICtcbiAgICAgICAgICAgIFwiPiBmYWlsZWQgYWZ0ZXIgKFwiICtcbiAgICAgICAgICAgIG9yaWdSZXRyaWVzICtcbiAgICAgICAgICAgIFwiKSByZXRyaWVzIHdpdGggZXJyb3IgLSBcIiArXG4gICAgICAgICAgICBlcnJvci5tZXNzYWdlXG4gICAgICAgICk7XG4gICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgIGNhbGxiYWNrKGVycm9yLCBudWxsKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH07XG5cbiAgICBzZXJ2ZXIub25SZXNwb25zZShzZXEsIHJlc3BvbnNlSGFuZGxlcik7XG4gICAgc2VydmVyLm9uRXJyb3Ioc2VxLCBlcnJvckhhbmRsZXIpO1xuICAgIHNlcnZlci53cml0ZShyZXF1ZXN0KTtcbiAgfVxuXG4gIC8vIEluY3JlbWVudCB0aGUgc2VxIHZhbHVlXG4gIGluY3JTZXEoKSB7XG4gICAgdGhpcy5zZXErKztcblxuICAgIC8vIFdyYXAgYHRoaXMuc2VxYCB0byAzMi1iaXRzIHNpbmNlIHRoZSBmaWVsZCB3ZSBmaXQgaXQgaW50byBpcyBvbmx5IDMyLWJpdHMuXG4gICAgdGhpcy5zZXEgJj0gMHhmZmZmZmZmZjtcblxuICAgIHJldHVybiB0aGlzLnNlcTtcbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlQW5kTG9nRXJyb3IoXG4gICAgY29tbWFuZE5hbWU6IHN0cmluZyxcbiAgICByZXNwb25zZVN0YXR1czogUmVzcG9uc2VTdGF0dXMgfCB1bmRlZmluZWRcbiAgKTogRXJyb3Ige1xuICAgIGNvbnN0IGVycm9yTWVzc2FnZSA9IGBNZW1KUyAke2NvbW1hbmROYW1lfTogJHtjb25zdGFudHMucmVzcG9uc2VTdGF0dXNUb1N0cmluZyhcbiAgICAgIHJlc3BvbnNlU3RhdHVzXG4gICAgKX1gO1xuICAgIHRoaXMub3B0aW9ucy5sb2dnZXIubG9nKGVycm9yTWVzc2FnZSk7XG4gICAgcmV0dXJuIG5ldyBFcnJvcihlcnJvck1lc3NhZ2UpO1xuICB9XG5cbiAgLyoqXG4gICAqIExvZyBhbiBlcnJvciB0byB0aGUgbG9nZ2VyLCB0aGVuIHJldHVybiB0aGUgZXJyb3IuXG4gICAqIElmIGEgY2FsbGJhY2sgaXMgZ2l2ZW4sIGNhbGwgaXQgd2l0aCBjYWxsYmFjayhlcnJvciwgbnVsbCkuXG4gICAqL1xuICBwcml2YXRlIGhhbmRsZVJlc3BvbnNlRXJyb3IoXG4gICAgY29tbWFuZE5hbWU6IHN0cmluZyxcbiAgICByZXNwb25zZVN0YXR1czogUmVzcG9uc2VTdGF0dXMgfCB1bmRlZmluZWQsXG4gICAgY2FsbGJhY2s6IHVuZGVmaW5lZCB8ICgoZXJyb3I6IEVycm9yIHwgbnVsbCwgb3RoZXI6IG51bGwpID0+IHZvaWQpXG4gICk6IEVycm9yIHtcbiAgICBjb25zdCBlcnJvciA9IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoY29tbWFuZE5hbWUsIHJlc3BvbnNlU3RhdHVzKTtcbiAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgIGNhbGxiYWNrKGVycm9yLCBudWxsKTtcbiAgICB9XG4gICAgcmV0dXJuIGVycm9yO1xuICB9XG59XG5cbmV4cG9ydCB7IENsaWVudCwgU2VydmVyLCBVdGlscywgSGVhZGVyIH07XG4iXX0= \ No newline at end of file diff --git a/src/memjs/memjs.ts b/src/memjs/memjs.ts index 6f93166..60a38bd 100644 --- a/src/memjs/memjs.ts +++ b/src/memjs/memjs.ts @@ -914,22 +914,18 @@ class Client { * in the backend pool, errors if any one of them has an * error */ - async versionAll( - triedCallback?: (response: string) => void, - resultCallback?: (response: string) => void - ): Promise<{ + async versionAll(callbacks?: { + beforePing?: (response: string) => void; + afterPing?: (response: string) => void; + }): Promise<{ values: Record; }> { const versionObjects = await Promise.all( this.serverKeys.map((serverKey) => { - if (triedCallback !== undefined) { - triedCallback(serverKey); - } const server = this.serverKeyToServer(serverKey); + callbacks?.beforePing?.(serverKey); return this._version(server).then((response) => { - if (resultCallback !== undefined) { - resultCallback(serverKey); - } + callbacks?.afterPing?.(serverKey); return { serverKey: serverKey, value: response.value }; }); }) From 4a0e8e0238d32019d11a9e857022ff3c68642712 Mon Sep 17 00:00:00 2001 From: Arturo Olvera Date: Mon, 6 Feb 2023 14:29:25 -0800 Subject: [PATCH 64/79] naming --- lib/memjs/memjs.d.ts | 4 ++-- lib/memjs/memjs.d.ts.map | 2 +- lib/memjs/memjs.js | 2 +- src/memjs/memjs.ts | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/memjs/memjs.d.ts b/lib/memjs/memjs.d.ts index e97d877..e2bb5bd 100644 --- a/lib/memjs/memjs.d.ts +++ b/lib/memjs/memjs.d.ts @@ -274,8 +274,8 @@ declare class Client { * error */ versionAll(callbacks?: { - beforePing?: (response: string) => void; - afterPing?: (response: string) => void; + beforePing?: (serverKey: string) => void; + afterPing?: (serverKey: string) => void; }): Promise<{ values: Record; }>; diff --git a/lib/memjs/memjs.d.ts.map b/lib/memjs/memjs.d.ts.map index 1a2be61..242d930 100644 --- a/lib/memjs/memjs.d.ts.map +++ b/lib/memjs/memjs.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"memjs.d.ts","sourceRoot":"","sources":["../../src/memjs/memjs.ts"],"names":[],"mappings":";AAEA,OAAO,EAGL,MAAM,EACN,aAAa,EACd,MAAM,UAAU,CAAC;AAClB,OAAO,EAAkB,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAOL,WAAW,EACX,OAAO,EACR,MAAM,SAAS,CAAC;AAGjB,OAAO,KAAK,KAAK,MAAM,SAAS,CAAC;AACjC,OAAO,KAAK,MAAM,MAAM,UAAU,CAAC;AAEnC,iBAAS,8BAA8B,CACrC,OAAO,EAAE,MAAM,EAAE,EACjB,GAAG,EAAE,MAAM,GACV,MAAM,CAIR;AAaD,aAAK,uBAAuB,GAAG,CAC7B,KAAK,EAAE,KAAK,GAAG,IAAI,EACnB,QAAQ,EAAE,OAAO,GAAG,IAAI,KACrB,IAAI,CAAC;AAEV,UAAU,iBAAiB;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE;QAAE,GAAG,EAAE,OAAO,OAAO,CAAC,GAAG,CAAA;KAAE,CAAC;IACpC,uBAAuB,EAAE,OAAO,8BAA8B,CAAC;CAChE;AAED,UAAU,cAAc,CAAC,KAAK,EAAE,MAAM;IACpC,UAAU,EAAE,UAAU,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;CACvC;AAED;;;;;;GAMG;AACH,aAAK,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,4BAA4B,EAAE,SAAS,IAClE,KAAK,SAAS,MAAM,GAChB,MAAM,SAAS,MAAM,GACnB,4BAA4B,GAC5B,SAAS,GACX,SAAS,CAAC;AAEhB,oBAAY,kBAAkB,CAAC,KAAK,EAAE,MAAM,IAAI,OAAO,CAAC,iBAAiB,CAAC,GACxE,QAAQ,CACN,KAAK,EACL,MAAM,EACN,OAAO,CAAC,cAAc,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,EACtC,cAAc,CAAC,KAAK,EAAE,MAAM,CAAC,CAC9B,CAAC;AAEJ,oBAAY,QAAQ,GAAG,MAAM,CAAC;AAE9B,MAAM,WAAW,SAAS,CAAC,KAAK,GAAG,WAAW,EAAE,MAAM,GAAG,WAAW;IAClE,KAAK,EAAE,KAAK,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,QAAQ,GAAG,SAAS,CAAC;CAC3B;AAED,oBAAY,cAAc,CACxB,IAAI,SAAS,MAAM,GAAG,MAAM,EAC5B,KAAK,GAAG,WAAW,EACnB,MAAM,GAAG,WAAW,IAClB;KACD,CAAC,IAAI,IAAI,CAAC,CAAC,EAAE,SAAS,CAAC,KAAK,EAAE,MAAM,CAAC;CACvC,CAAC;AAEF,cAAM,MAAM,CAAC,KAAK,GAAG,WAAW,EAAE,MAAM,GAAG,WAAW;IACpD,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,cAAc,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC;IACpE,UAAU,EAAE,UAAU,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IACtC,SAAS,EAAE;QAAE,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;IAC1C,UAAU,EAAE,MAAM,EAAE,CAAC;gBAIT,OAAO,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,kBAAkB,CAAC,KAAK,EAAE,MAAM,CAAC;IAwBzE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAkDG;IACH,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,EACzB,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,OAAO,EAAE,QAAQ,CACf,KAAK,EACL,MAAM,EACN,SAAS,GAAG,CAAC,OAAO,CAAC,aAAa,CAAC,GAAG,kBAAkB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,EACxE,OAAO,CAAC,aAAa,CAAC,GAAG,kBAAkB,CAAC,KAAK,EAAE,MAAM,CAAC,CAC3D,GACA,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC;IAsBxB;;;;;OAKG;IACH,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;IAI5C;;;OAGG;IACH,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IAIzC;;OAEG;IACG,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC;IAmBhE;;;OAGG;IACH,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM;IAoC1D,sHAAsH;IAChH,iBAAiB,CAAC,IAAI,SAAS,MAAM,EACzC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,IAAI,EAAE,GACX,OAAO,CAAC,cAAc,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;IA2D/C;;;OAGG;IACG,QAAQ,CAAC,IAAI,SAAS,MAAM,EAChC,IAAI,EAAE,IAAI,EAAE,GACX,OAAO,CAAC,cAAc,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;IAuB/C;;OAEG;IACG,GAAG,CACP,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,KAAK,EACZ,OAAO,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,QAAQ,CAAA;KAAE,GAC7C,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IAsC1B;;;;;;;;;OASG;IACG,GAAG,CACP,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,KAAK,EACZ,OAAO,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAC7B,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IA2B1B;;;OAGG;IACG,OAAO,CACX,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,KAAK,EACZ,OAAO,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAC7B,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IA0B1B;;;OAGG;IACG,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAgB3C;;OAEG;IACG,SAAS,CACb,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAC/C,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAA;KAAE,CAAC;IAwB7D;;OAEG;IACG,SAAS,CACb,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,EACd,OAAO,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAC9C,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAA;KAAE,CAAC;IAwB7D;;;OAGG;IACG,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC;IAuBzD;;;OAGG;IACG,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC;IAuB1D;;;OAGG;IACG,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAgB3D;;;;;;;;;;;OAWG;IACH,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,GAAG,KAAK,CAAC,CAAC;IACjD,KAAK,CACH,QAAQ,EAAE,CACR,GAAG,EAAE,KAAK,GAAG,IAAI,EACjB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,GAAG,KAAK,CAAC,KACrC,IAAI,GACR,IAAI;IA6CP;;;;;;;;;;;;OAYG;IACH,YAAY,CACV,GAAG,EAAE,MAAM,EACX,QAAQ,CAAC,EAAE,CACT,GAAG,EAAE,KAAK,GAAG,IAAI,EACjB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,KACjC,IAAI,GACR,IAAI;IA8CP;;;;;;;;;;;OAWG;IACH,KAAK,CACH,QAAQ,CAAC,EAAE,CACT,GAAG,EAAE,KAAK,GAAG,IAAI,EACjB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,KACjC,IAAI,GACR,IAAI;IAIP;;;;;;;;;;;;;OAaG;IACH,UAAU,CACR,QAAQ,CAAC,EAAE,CACT,GAAG,EAAE,KAAK,GAAG,IAAI,EACjB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,KACjC,IAAI,GACR,IAAI;IAIP;;;;;;;OAOG;IACH,IAAI;IAuBJ,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,KAAK,GAAG,IAAI,CAAA;KAAE,CAAC;IAkC1D;;;OAGG;IACH,OAAO,IAAI,OAAO,CAAC;QAAE,KAAK,EAAE,KAAK,GAAG,IAAI,CAAA;KAAE,CAAC;IAK3C;;;;OAIG;IACG,UAAU,CAAC,SAAS,CAAC,EAAE;QAC3B,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;QACxC,SAAS,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;KACxC,GAAG,OAAO,CAAC;QACV,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,GAAG,IAAI,CAAC,CAAC;KACtC,CAAC;IAkBF;;;OAGG;IACH,KAAK;IAML;;;;;;;;OAQG;IACH,OAAO,CACL,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,OAAO,CAAC;IAwBnB,eAAe,CACb,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,uBAAuB,EACjC,OAAO,GAAE,MAAU;IA0CrB,OAAO;IASP,OAAO,CAAC,iBAAiB;IAWzB;;;OAGG;IACH,OAAO,CAAC,mBAAmB;CAW5B;AAED,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC"} \ No newline at end of file +{"version":3,"file":"memjs.d.ts","sourceRoot":"","sources":["../../src/memjs/memjs.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/lib/memjs/memjs.js b/lib/memjs/memjs.js index 759d1f7..5ed79fe 100644 --- a/lib/memjs/memjs.js +++ b/lib/memjs/memjs.js @@ -739,4 +739,4 @@ class Client { } } exports.Client = Client; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVtanMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbWVtanMvbWVtanMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLHdCQUF3Qjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUV4QixxQ0FLa0I7QUF3aUNELHVGQTFpQ2YsZUFBTSxPQTBpQ2U7QUF2aUN2Qix1REFBK0Q7QUFDL0QsbUNBU2lCO0FBQ2pCLHVEQUF5QztBQUN6QywyQ0FBNkM7QUFDN0MsK0NBQWlDO0FBMGhDUixzQkFBSztBQXpoQzlCLGlEQUFtQztBQXloQ0gsd0JBQU07QUF2aEN0QyxTQUFTLDhCQUE4QixDQUNyQyxPQUFpQixFQUNqQixHQUFXO0lBRVgsTUFBTSxLQUFLLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQztJQUM3QixNQUFNLEtBQUssR0FBRyxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxnQkFBUSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3BELE9BQU8sT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ3hCLENBQUM7QUFFRCwrQ0FBK0M7QUFDL0MsU0FBUyxTQUFTLENBQ2hCLE9BQTBFO0lBRTFFLE9BQU8sSUFBSSxPQUFPLENBQUMsVUFBVSxPQUFPLEVBQUUsTUFBTTtRQUMxQyxPQUFPLENBQUMsVUFBVSxHQUFHLEVBQUUsTUFBTTtZQUMzQixHQUFHLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3RDLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBeURELE1BQU0sTUFBTTtJQVFWLDRFQUE0RTtJQUM1RSxtQ0FBbUM7SUFDbkMsWUFBWSxPQUFpQixFQUFFLE9BQTBDO1FBQ3ZFLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO1FBQ3ZCLElB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QixFQUNuQixjQUEwQztRQUUxQyxNQUFNLFlBQVksR0FBRyxTQUFTLFdBQVcsS0FBSyxTQUFTLENBQUMsc0JBQXNCLENBQzVFLGNBQWMsQ0FDZixFQUFFLENBQUM7UUFDSixJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDdEMsT0FBTyxJQUFJLEtBQUssQ0FBQyxZQUFZLENBQUMsQ0FBQztJQUNqQyxDQUFDO0lBRUQ7OztPQUdHO0lBQ0ssbUJBQW1CLENBQ3pCLFdBQW1CLEVBQ25CLGNBQTBDLEVBQzFDLFFBQWtFO1FBRWxFLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxXQUFXLEVBQUUsY0FBYyxDQUFDLENBQUM7UUFDbEUsSUFBSSxRQUFRLEVBQUU7WUFDWixRQUFRLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxDQUFDO1NBQ3ZCO1FBQ0QsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0NBQ0Y7QUFFUSx3QkFBTSIsInNvdXJjZXNDb250ZW50IjpbIi8vIE1lbVRTIE1lbWNhY2hlIENsaWVudFxuXG5pbXBvcnQge1xuICBPbkVycm9yQ2FsbGJhY2ssXG4gIE9uUmVzcG9uc2VDYWxsYmFjayxcbiAgU2VydmVyLFxuICBTZXJ2ZXJPcHRpb25zLFxufSBmcm9tIFwiLi9zZXJ2ZXJcIjtcbmltcG9ydCB7IG5vb3BTZXJpYWxpemVyLCBTZXJpYWxpemVyIH0gZnJvbSBcIi4vbm9vcC1zZXJpYWxpemVyXCI7XG5pbXBvcnQge1xuICBtYWtlUmVxdWVzdEJ1ZmZlcixcbiAgY29weUludG9SZXF1ZXN0QnVmZmVyLFxuICBtZXJnZSxcbiAgbWFrZUV4cGlyYXRpb24sXG4gIG1ha2VBbW91bnRJbml0aWFsQW5kRXhwaXJhdGlvbixcbiAgaGFzaENvZGUsXG4gIE1heWJlQnVmZmVyLFxuICBNZXNzYWdlLFxufSBmcm9tIFwiLi91dGlsc1wiO1xuaW1wb3J0ICogYXMgY29uc3RhbnRzIGZyb20gXCIuL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgUmVzcG9uc2VTdGF0dXMgfSBmcm9tIFwiLi9jb25zdGFudHNcIjtcbmltcG9ydCAqIGFzIFV0aWxzIGZyb20gXCIuL3V0aWxzXCI7XG5pbXBvcnQgKiBhcyBIZWFkZXIgZnJvbSBcIi4vaGVhZGVyXCI7XG5cbmZ1bmN0aW9uIGRlZmF1bHRLZXlUb1NlcnZlckhhc2hGdW5jdGlvbihcbiAgc2VydmVyczogc3RyaW5nW10sXG4gIGtleTogc3RyaW5nXG4pOiBzdHJpbmcge1xuICBjb25zdCB0b3RhbCA9IHNlcnZlcnMubGVuZ3RoO1xuICBjb25zdCBpbmRleCA9IHRvdGFsID4gMSA/IGhhc2hDb2RlKGtleSkgJSB0b3RhbCA6IDA7XG4gIHJldHVybiBzZXJ2ZXJzW2luZGV4XTtcbn1cblxuLy8gY29udmVydHMgYSBjYWxsIGludG8gYSBwcm9taXNlLXJldHVybmluZyBvbmVcbmZ1bmN0aW9uIHByb21pc2lmeTxSZXN1bHQ+KFxuICBjb21tYW5kOiAoY2FsbGJhY2s6IChlcnJvcjogRXJyb3IgfCBudWxsLCByZXN1bHQ6IFJlc3VsdCkgPT4gdm9pZCkgPT4gdm9pZFxuKTogUHJvbWlzZTxSZXN1bHQ+IHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICBjb21tYW5kKGZ1bmN0aW9uIChlcnIsIHJlc3VsdCkge1xuICAgICAgZXJyID8gcmVqZWN0KGVycikgOiByZXNvbHZlKHJlc3VsdCk7XG4gICAgfSk7XG4gIH0pO1xufVxuXG50eXBlIFJlc3BvbnNlT3JFcnJvckNhbGxiYWNrID0gKFxuICBlcnJvcjogRXJyb3IgfCBudWxsLFxuICByZXNwb25zZTogTWVzc2FnZSB8IG51bGxcbikgPT4gdm9pZDtcblxuaW50ZXJmYWNlIEJhc2VDbGllbnRPcHRpb25zIHtcbiAgcmV0cmllczogbnVtYmVyO1xuICByZXRyeV9kZWxheTogbnVtYmVyO1xuICBleHBpcmVzOiBudW1iZXI7XG4gIGxvZ2dlcjogeyBsb2c6IHR5cGVvZiBjb25zb2xlLmxvZyB9O1xuICBrZXlUb1NlcnZlckhhc2hGdW5jdGlvbjogdHlwZW9mIGRlZmF1bHRLZXlUb1NlcnZlckhhc2hGdW5jdGlvbjtcbn1cblxuaW50ZXJmYWNlIFNlcmlhbGl6ZXJQcm9wPFZhbHVlLCBFeHRyYXM+IHtcbiAgc2VyaWFsaXplcjogU2VyaWFsaXplcjxWYWx1ZSwgRXh0cmFzPjtcbn1cblxuLyoqXG4gKiBUaGUgY2xpZW50IGhhcyBwYXJ0aWFsIHN1cHBvcnQgZm9yIHNlcmlhbGl6aW5nIGFuZCBkZXNlcmlhbGl6aW5nIHZhbHVlcyBmcm9tIHRoZVxuICogQnVmZmVyIGJ5dGUgc3RyaW5ncyB3ZSByZWNlaXZlIGZyb20gdGhlIHdpcmUuIFRoZSBkZWZhdWx0IHNlcmlhbGl6ZXIgaXMgZm9yIE1heWJlQnVmZmVyLlxuICpcbiAqIElmIFZhbHVlIGFuZCBFeHRyYXMgYXJlIG9mIHR5cGUgQnVmZmVyLCB0aGVuIHJldHVybiB0eXBlIFdoZW5CdWZmZXIuIE90aGVyd2lzZSxcbiAqIHJldHVybiB0eXBlIE5vdEJ1ZmZlci5cbiAqL1xudHlwZSBJZkJ1ZmZlcjxWYWx1ZSwgRXh0cmFzLCBXaGVuVmFsdWVBbmRFeHRyYXNBcmVCdWZmZXJzLCBOb3RCdWZmZXI+ID1cbiAgVmFsdWUgZXh0ZW5kcyBCdWZmZXJcbiAgICA/IEV4dHJhcyBleHRlbmRzIEJ1ZmZlclxuICAgICAgPyBXaGVuVmFsdWVBbmRFeHRyYXNBcmVCdWZmZXJzXG4gICAgICA6IE5vdEJ1ZmZlclxuICAgIDogTm90QnVmZmVyO1xuXG5leHBvcnQgdHlwZSBHaXZlbkNsaWVudE9wdGlvbnM8VmFsdWUsIEV4dHJhcz4gPSBQYXJ0aWFsPEJhc2VDbGllbnRPcHRpb25zPiAmXG4gIElmQnVmZmVyPFxuICAgIFZhbHVlLFxuICAgIEV4dHJhcyxcbiAgICBQYXJ0aWFsPFNlcmlhbGl6ZXJQcm9wPFZhbHVlLCBFeHRyYXM+PixcbiAgICBTZXJpYWxpemVyUHJvcDxWYWx1ZSwgRXh0cmFzPlxuICA+O1xuXG5leHBvcnQgdHlwZSBDQVNUb2tlbiA9IEJ1ZmZlcjtcblxuZXhwb3J0IGludGVyZmFjZSBHZXRSZXN1bHQ8VmFsdWUgPSBNYXliZUJ1ZmZlciwgRXh0cmFzID0gTWF5YmVCdWZmZXI+IHtcbiAgdmFsdWU6IFZhbHVlO1xuICBleHRyYXM6IEV4dHJhcztcbiAgY2FzOiBDQVNUb2tlbiB8IHVuZGVmaW5lZDtcbn1cblxuZXhwb3J0IHR5cGUgR2V0TXVsdGlSZXN1bHQ8XG4gIEtleXMgZXh0ZW5kcyBzdHJpbmcgPSBzdHJpbmcsXG4gIFZhbHVlID0gTWF5YmVCdWZmZXIsXG4gIEV4dHJhcyA9IE1heWJlQnVmZmVyXG4+ID0ge1xuICBbSyBpbiBLZXlzXT86IEdldFJlc3VsdDxWYWx1ZSwgRXh0cmFzPjtcbn07XG5cbmNsYXNzIENsaWVudDxWYWx1ZSA9IE1heWJlQnVmZmVyLCBFeHRyYXMgPSBNYXliZUJ1ZmZlcj4ge1xuICBzZXJ2ZXJzOiBTZXJ2ZXJbXTtcbiAgc2VxOiBudW1iZXI7XG4gIG9wdGlvbnM6IEJhc2VDbGllbnRPcHRpb25zICYgUGFydGlhbDxTZXJpYWxpemVyUHJvcDxWYWx1ZSwgRXh0cmFzPj47XG4gIHNlcmlhbGl6ZXI6IFNlcmlhbGl6ZXI8VmFsdWUsIEV4dHJhcz47XG4gIHNlcnZlck1hcDogeyBbaG9zdHBvcnQ6IHN0cmluZ106IFNlcnZlciB9O1xuICBzZXJ2ZXJLZXlzOiBzdHJpbmdbXTtcblxuICAvLyBDbGllbnQgaW5pdGlhbGl6ZXIgdGFrZXMgYSBsaXN0IG9mIGBTZXJ2ZXJgcyBhbmQgYW4gYG9wdGlvbnNgIGRpY3Rpb25hcnkuXG4gIC8vIFNlZSBgQ2xpZW50LmNyZWF0ZWAgZm9yIGRldGFpbHMuXG4gIGNvbnN0cnVjdG9yKHNlcnZlcnM6IFNlcnZlcltdLCBvcHRpb25zOiBHaXZlbkNsaWVudE9wdGlvbnM8VmFsdWUsIEV4dHJhcz4pIHtcbiAgICB0aGlzLnNlcnZlcnMgPSBzZXJ2ZXJzO1xuICAgIHRoaXMuc2VxID0gMDtcbiAgICB0aGlzLm9wdGlvbnMgPSBtZXJnZShvcHRpb25zIHx8IHt9LCB7XG4gICAgICByZXRyaWVzOiAyLFxuICAgICAgcmV0cnlfZGVsYXk6IDAuMixcbiAgICAgIGV4cGlyZXM6IDAsXG4gICAgICBsb2dnZXI6IGNvbnNvbGUsXG4gICAgICBrZXlUb1NlcnZlckhhc2hGdW5jdGlvbjogZGVmYXVsdEtleVRvU2VydmVySGFzaEZ1bmN0aW9uLFxuICAgIH0pO1xuXG4gICAgdGhpcy5zZXJpYWxpemVyID0gdGhpcy5vcHRpb25zLnNlcmlhbGl6ZXIgfHwgKG5vb3BTZXJpYWxpemVyIGFzIGFueSk7XG5cbiAgICAvLyBTdG9yZSBhIG1hcHBpbmcgZnJvbSBob3N0cG9ydCAtPiBzZXJ2ZXIgc28gd2UgY2FuIHF1aWNrbHkgZ2V0IGEgc2VydmVyIG9iamVjdCBmcm9tIHRoZSBzZXJ2ZXJLZXkgcmV0dXJuZWQgYnkgdGhlIGhhc2hpbmcgZnVuY3Rpb25cbiAgICBjb25zdCBzZXJ2ZXJNYXA6IHsgW2hvc3Rwb3J0OiBzdHJpbmddOiBTZXJ2ZXIgfSA9IHt9O1xuICAgIHRoaXMuc2VydmVycy5mb3JFYWNoKGZ1bmN0aW9uIChzZXJ2ZXIpIHtcbiAgICAgIHNlcnZlck1hcFtzZXJ2ZXIuaG9zdHBvcnRTdHJpbmcoKV0gPSBzZXJ2ZXI7XG4gICAgfSk7XG4gICAgdGhpcy5zZXJ2ZXJNYXAgPSBzZXJ2ZXJNYXA7XG5cbiAgICAvLyBzdG9yZSBhIGxpc3Qgb2YgYWxsIG91ciBzZXJ2ZXJLZXlzIHNvIHdlIGRvbid0IG5lZWQgdG8gY29uc3RhbnRseSByZWFsbG9jYXRlIHRoaXMgYXJyYXlcbiAgICB0aGlzLnNlcnZlcktleXMgPSBPYmplY3Qua2V5cyh0aGlzLnNlcnZlck1hcCk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIG5ldyBjbGllbnQgZ2l2ZW4gYW4gb3B0aW9uYWwgY29uZmlnIHN0cmluZyBhbmQgb3B0aW9uYWwgaGFzaCBvZlxuICAgKiBvcHRpb25zLiBUaGUgY29uZmlnIHN0cmluZyBzaG91bGQgYmUgb2YgdGhlIGZvcm06XG4gICAqXG4gICAqICAgICBcIlt1c2VyOnBhc3NAXXNlcnZlcjFbOjExMjExXSxbdXNlcjpwYXNzQF1zZXJ2ZXIyWzoxMTIxMV0sLi4uXCJcbiAgICpcbiAgICogSWYgdGhlIGFyZ3VtZW50IGlzIG5vdCBnaXZlbiwgZmFsbGJhY2sgb24gdGhlIGBNRU1DQUNISUVSX1NFUlZFUlNgIGVudmlyb25tZW50XG4gICAqIHZhcmlhYmxlLCBgTUVNQ0FDSEVfU0VSVkVSU2AgZW52aXJvbm1lbnQgdmFyaWFibGUgb3IgYFwibG9jYWxob3N0OjExMjExXCJgLlxuICAgKlxuICAgKiBUaGUgb3B0aW9ucyBoYXNoIG1heSBjb250YWluIHRoZSBvcHRpb25zOlxuICAgKlxuICAgKiAqIGByZXRyaWVzYCAtIHRoZSBudW1iZXIgb2YgdGltZXMgdG8gcmV0cnkgYW4gb3BlcmF0aW9uIGluIGxpZXUgb2YgZmFpbHVyZXNcbiAgICogKGRlZmF1bHQgMilcbiAgICogKiBgZXhwaXJlc2AgLSB0aGUgZGVmYXVsdCBleHBpcmF0aW9uIGluIHNlY29uZHMgdG8gdXNlIChkZWZhdWx0IDAgLSBuZXZlclxuICAgKiBleHBpcmUpLiBJZiBgZXhwaXJlc2AgaXMgZ3JlYXRlciB0aGFuIDMwIGRheXMgKDYwIHggNjAgeCAyNCB4IDMwKSwgaXQgaXNcbiAgICogdHJlYXRlZCBhcyBhIFVOSVggdGltZSAobnVtYmVyIG9mIHNlY29uZHMgc2luY2UgSmFudWFyeSAxLCAxOTcwKS5cbiAgICogKiBgbG9nZ2VyYCAtIGEgbG9nZ2VyIG9iamVjdCB0aGF0IHJlc3BvbmRzIHRvIGBsb2coc3RyaW5nKWAgbWV0aG9kIGNhbGxzLlxuICAgKlxuICAgKiAgIH5+fn5cbiAgICogICAgIGxvZyhtc2cxWywgbXNnMlssIG1zZzNbLi4uXV1dKVxuICAgKiAgIH5+fn5cbiAgICpcbiAgICogICBEZWZhdWx0cyB0byBgY29uc29sZWAuXG4gICAqICogYHNlcmlhbGl6ZXJgIC0gdGhlIG9iamVjdCB3aGljaCB3aWxsIChkZSlzZXJpYWxpemUgdGhlIGRhdGEuIEl0IG5lZWRzXG4gICAqICAgdHdvIHB1YmxpYyBtZXRob2RzOiBzZXJpYWxpemUgYW5kIGRlc2VyaWFsaXplLiBJdCBkZWZhdWx0cyB0byB0aGVcbiAgICogICBub29wU2VyaWFsaXplcjpcbiAgICpcbiAgICogICB+fn5+XG4gICAqICAgY29uc3Qgbm9vcFNlcmlhbGl6ZXIgPSB7XG4gICAqICAgICBzZXJpYWxpemU6IGZ1bmN0aW9uIChvcGNvZGUsIHZhbHVlLCBleHRyYXMpIHtcbiAgICogICAgICAgcmV0dXJuIHsgdmFsdWU6IHZhbHVlLCBleHRyYXM6IGV4dHJhcyB9O1xuICAgKiAgICAgfSxcbiAgICogICAgIGRlc2VyaWFsaXplOiBmdW5jdGlvbiAob3Bjb2RlLCB2YWx1ZSwgZXh0cmFzKSB7XG4gICAqICAgICAgIHJldHVybiB7IHZhbHVlOiB2YWx1ZSwgZXh0cmFzOiBleHRyYXMgfTtcbiAgICogICAgIH1cbiAgICogICB9O1xuICAgKiAgIH5+fn5cbiAgICpcbiAgICogT3Igb3B0aW9ucyBmb3IgdGhlIHNlcnZlcnMgaW5jbHVkaW5nOlxuICAgKiAqIGB1c2VybmFtZWAgYW5kIGBwYXNzd29yZGAgZm9yIGZhbGxiYWNrIFNBU0wgYXV0aGVudGljYXRpb24gY3JlZGVudGlhbHMuXG4gICAqICogYHRpbWVvdXRgIGluIHNlY29uZHMgdG8gZGV0ZXJtaW5lIGZhaWx1cmUgZm9yIG9wZXJhdGlvbnMuIERlZmF1bHQgaXMgMC41XG4gICAqICAgICAgICAgICAgIHNlY29uZHMuXG4gICAqICogJ2Nvbm50aW1lb3V0JyBpbiBzZWNvbmRzIHRvIGNvbm5lY3Rpb24gZmFpbHVyZS4gRGVmYXVsdCBpcyB0d2ljZSB0aGUgdmFsdWVcbiAgICogICAgICAgICAgICAgICAgIG9mIGB0aW1lb3V0YC5cbiAgICogKiBga2VlcEFsaXZlYCB3aGV0aGVyIHRvIGVuYWJsZSBrZWVwLWFsaXZlIGZ1bmN0aW9uYWxpdHkuIERlZmF1bHRzIHRvIGZhbHNlLlxuICAgKiAqIGBrZWVwQWxpdmVEZWxheWAgaW4gc2Vjb25kcyB0byB0aGUgaW5pdGlhbCBkZWxheSBiZWZvcmUgdGhlIGZpcnN0IGtlZXBhbGl2ZVxuICAgKiAgICAgICAgICAgICAgICAgICAgcHJvYmUgaXMgc2VudCBvbiBhbiBpZGxlIHNvY2tldC4gRGVmYXVsdHMgaXMgMzAgc2Vjb25kcy5cbiAgICogKiBga2V5VG9TZXJ2ZXJIYXNoRnVuY3Rpb25gIGEgZnVuY3Rpb24gdG8gbWFwIGtleXMgdG8gc2VydmVycywgd2l0aCB0aGUgc2lnbmF0dXJlXG4gICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgIChzZXJ2ZXJLZXlzOiBzdHJpbmdbXSwga2V5OiBzdHJpbmcpOiBzdHJpbmdcbiAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgTk9URTogaWYgeW91IG5lZWQgdG8gZG8gc29tZSBleHBlbnNpdmUgaW5pdGlhbGl6YXRpb24sICpwbGVhc2UqIGRvIGl0IGxhemlseSB0aGUgZmlyc3QgdGltZSB5b3UgdGhpcyBmdW5jdGlvbiBpcyBjYWxsZWQgd2l0aCBhbiBhcnJheSBvZiBzZXJ2ZXJLZXlzLCBub3Qgb24gZXZlcnkgY2FsbFxuICAgKi9cbiAgc3RhdGljIGNyZWF0ZTxWYWx1ZSwgRXh0cmFzPihcbiAgICBzZXJ2ZXJzU3RyOiBzdHJpbmcgfCB1bmRlZmluZWQsXG4gICAgb3B0aW9uczogSWZCdWZmZXI8XG4gICAgICBWYWx1ZSxcbiAgICAgIEV4dHJhcyxcbiAgICAgIHVuZGVmaW5lZCB8IChQYXJ0aWFsPFNlcnZlck9wdGlvbnM+ICYgR2l2ZW5DbGllbnRPcHRpb25zPFZhbHVlLCBFeHRyYXM+KSxcbiAgICAgIFBhcnRpYWw8U2VydmVyT3B0aW9ucz4gJiBHaXZlbkNsaWVudE9wdGlvbnM8VmFsdWUsIEV4dHJhcz5cbiAgICA+XG4gICk6IENsaWVudDxWYWx1ZSwgRXh0cmFzPiB7XG4gICAgc2VydmVyc1N0ciA9XG4gICAgICBzZXJ2ZXJzU3RyIHx8XG4gICAgICBwcm9jZXNzLmVudi5NRU1DQUNISUVSX1NFUlZFUlMgfHxcbiAgICAgIHByb2Nlc3MuZW52Lk1FTUNBQ0hFX1NFUlZFUlMgfHxcbiAgICAgIFwibG9jYWxob3N0OjExMjExXCI7XG4gICAgY29uc3Qgc2VydmVyVXJpcyA9IHNlcnZlcnNTdHIuc3BsaXQoXCIsXCIpO1xuICAgIGNvbnN0IHNlcnZlcnMgPSBzZXJ2ZXJVcmlzLm1hcChmdW5jdGlvbiAodXJpKSB7XG4gICAgICBjb25zdCB1cmlQYXJ0cyA9IHVyaS5zcGxpdChcIkBcIik7XG4gICAgICBjb25zdCBob3N0UG9ydCA9IHVyaVBhcnRzW3VyaVBhcnRzLmxlbmd0aCAtIDFdLnNwbGl0KFwiOlwiKTtcbiAgICAgIGNvbnN0IHVzZXJQYXNzID0gKHVyaVBhcnRzW3VyaVBhcnRzLmxlbmd0aCAtIDJdIHx8IFwiXCIpLnNwbGl0KFwiOlwiKTtcbiAgICAgIHJldHVybiBuZXcgU2VydmVyKFxuICAgICAgICBob3N0UG9ydFswXSxcbiAgICAgICAgcGFyc2VJbnQoaG9zdFBvcnRbMV0gfHwgXCIxMTIxMVwiLCAxMCksXG4gICAgICAgIHVzZXJQYXNzWzBdLFxuICAgICAgICB1c2VyUGFzc1sxXSxcbiAgICAgICAgb3B0aW9uc1xuICAgICAgKTtcbiAgICB9KTtcbiAgICByZXR1cm4gbmV3IENsaWVudChzZXJ2ZXJzLCBvcHRpb25zIGFzIGFueSk7XG4gIH1cblxuICAvKipcbiAgICogR2l2ZW4gYSBzZXJ2ZXJLZXkgZnJvbWxvb2t1cEtleVRvU2VydmVyS2V5LCByZXR1cm4gdGhlIGNvcnJlc3BvbmRpbmcgU2VydmVyIGluc3RhbmNlXG4gICAqXG4gICAqIEBwYXJhbSAge3N0cmluZ30gc2VydmVyS2V5XG4gICAqIEByZXR1cm5zIHtTZXJ2ZXJ9XG4gICAqL1xuICBzZXJ2ZXJLZXlUb1NlcnZlcihzZXJ2ZXJLZXk6IHN0cmluZyk6IFNlcnZlciB7XG4gICAgcmV0dXJuIHRoaXMuc2VydmVyTWFwW3NlcnZlcktleV07XG4gIH1cblxuICAvKipcbiAgICogR2l2ZW4gYSBrZXkgdG8gbG9vayB1cCBpbiBtZW1jYWNoZSwgcmV0dXJuIGEgc2VydmVyS2V5IChiYXNlZCBvbiBzb21lXG4gICAqIGhhc2hpbmcgZnVuY3Rpb24pIHdoaWNoIGNhbiBiZSB1c2VkIHRvIGluZGV4IHRoaXMuc2VydmVyTWFwXG4gICAqL1xuICBsb29rdXBLZXlUb1NlcnZlcktleShrZXk6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMub3B0aW9ucy5rZXlUb1NlcnZlckhhc2hGdW5jdGlvbih0aGlzLnNlcnZlcktleXMsIGtleSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldmVzIHRoZSB2YWx1ZSBhdCB0aGUgZ2l2ZW4ga2V5IGluIG1lbWNhY2hlLlxuICAgKi9cbiAgYXN5bmMgZ2V0KGtleTogc3RyaW5nKTogUHJvbWlzZTxHZXRSZXN1bHQ8VmFsdWUsIEV4dHJhcz4gfCBudWxsPiB7XG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKGNvbnN0YW50cy5PUF9HRVQsIGtleSwgXCJcIiwgXCJcIiwgdGhpcy5zZXEpO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICBjb25zdCBkZXNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuZGVzZXJpYWxpemUoXG4gICAgICAgICAgcmVzcG9uc2UuaGVhZGVyLm9wY29kZSxcbiAgICAgICAgICByZXNwb25zZS52YWwsXG4gICAgICAgICAgcmVzcG9uc2UuZXh0cmFzXG4gICAgICAgICk7XG4gICAgICAgIHJldHVybiB7IC4uLmRlc2VyaWFsaXplZCwgY2FzOiByZXNwb25zZS5oZWFkZXIuY2FzIH07XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIkdFVFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKiogQnVpbGQgYSBwaXBlbGluZWQgZ2V0IG11bHRpIHJlcXVlc3QgYnkgc2VuZGluZyBvbmUgR0VUS1EgZm9yIGVhY2gga2V5IChxdWlldCwgbWVhbmluZyBpdCB3b24ndCByZXNwb25kIGlmIHRoZSB2YWx1ZSBpcyBtaXNzaW5nKSBmb2xsb3dlZCBieSBhIG5vLW9wIHRvIGZvcmNlIGEgcmVzcG9uc2UgKGFuZCB0byBnaXZlIHVzIGEgc2VudGluZWwgcmVzcG9uc2UgdGhhdCB0aGUgcGlwZWxpbmUgaXMgZG9uZSlcbiAgICpcbiAgICogY2YgaHR0cHM6Ly9naXRodWIuY29tL2NvdWNoYmFzZS9tZW1jYWNoZWQvYmxvYi9tYXN0ZXIvZG9jcy9CaW5hcnlQcm90b2NvbC5tZCMweDBkLWdldGtxLWdldC13aXRoLWtleS1xdWlldGx5XG4gICAqL1xuICBfYnVpbGRHZXRNdWx0aVJlcXVlc3Qoa2V5czogc3RyaW5nW10sIHNlcTogbnVtYmVyKTogQnVmZmVyIHtcbiAgICAvLyBzdGFydCBhdCAyNCBmb3IgdGhlIG5vLW9wIGNvbW1hbmQgYXQgdGhlIGVuZFxuICAgIGxldCByZXF1ZXN0U2l6ZSA9IDI0O1xuICAgIGZvciAoY29uc3Qga2V5SWR4IGluIGtleXMpIHtcbiAgICAgIHJlcXVlc3RTaXplICs9IEJ1ZmZlci5ieXRlTGVuZ3RoKGtleXNba2V5SWR4XSwgXCJ1dGY4XCIpICsgMjQ7XG4gICAgfVxuXG4gICAgY29uc3QgcmVxdWVzdCA9IEJ1ZmZlci5hbGxvYyhyZXF1ZXN0U2l6ZSk7XG5cbiAgICBsZXQgYnl0ZXNXcml0dGVuID0gMDtcbiAgICBmb3IgKGNvbnN0IGtleUlkeCBpbiBrZXlzKSB7XG4gICAgICBjb25zdCBrZXkgPSBrZXlzW2tleUlkeF07XG4gICAgICBieXRlc1dyaXR0ZW4gKz0gY29weUludG9SZXF1ZXN0QnVmZmVyKFxuICAgICAgICBjb25zdGFudHMuT1BfR0VUS1EsXG4gICAgICAgIGtleSxcbiAgICAgICAgXCJcIixcbiAgICAgICAgXCJcIixcbiAgICAgICAgc2VxLFxuICAgICAgICByZXF1ZXN0LFxuICAgICAgICBieXRlc1dyaXR0ZW5cbiAgICAgICk7XG4gICAgfVxuXG4gICAgYnl0ZXNXcml0dGVuICs9IGNvcHlJbnRvUmVxdWVzdEJ1ZmZlcihcbiAgICAgIGNvbnN0YW50cy5PUF9OT19PUCxcbiAgICAgIFwiXCIsXG4gICAgICBcIlwiLFxuICAgICAgXCJcIixcbiAgICAgIHNlcSxcbiAgICAgIHJlcXVlc3QsXG4gICAgICBieXRlc1dyaXR0ZW5cbiAgICApO1xuXG4gICAgcmV0dXJuIHJlcXVlc3Q7XG4gIH1cblxuICAvKiogRXhlY3V0aW5nIGEgcGlwZWxpbmVkIChtdWx0aSkgZ2V0IGFnYWluc3QgYSBzaW5nbGUgc2VydmVyLiBUaGlzIGlzIGEgcHJpdmF0ZSBpbXBsZW1lbnRhdGlvbiBkZXRhaWwgb2YgZ2V0TXVsdGkuICovXG4gIGFzeW5jIF9nZXRNdWx0aVRvU2VydmVyPEtleXMgZXh0ZW5kcyBzdHJpbmc+KFxuICAgIHNlcnY6IFNlcnZlcixcbiAgICBrZXlzOiBLZXlzW11cbiAgKTogUHJvbWlzZTxHZXRNdWx0aVJlc3VsdDxLZXlzLCBWYWx1ZSwgRXh0cmFzPj4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBjb25zdCByZXNwb25zZU1hcDogR2V0TXVsdGlSZXN1bHQ8c3RyaW5nLCBWYWx1ZSwgRXh0cmFzPiA9IHt9O1xuXG4gICAgICBjb25zdCBoYW5kbGU6IE9uUmVzcG9uc2VDYWxsYmFjayA9IChyZXNwb25zZSkgPT4ge1xuICAgICAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgICAgICAvLyBXaGVuIHdlIGdldCB0aGUgbm8tb3AgcmVzcG9uc2UsIHdlIGFyZSBkb25lIHdpdGggdGhpcyBvbmUgZ2V0TXVsdGkgaW4gdGhlIHBlci1iYWNrZW5kIGZhbi1vdXRcbiAgICAgICAgICAgIGlmIChyZXNwb25zZS5oZWFkZXIub3Bjb2RlID09PSBjb25zdGFudHMuT1BfTk9fT1ApIHtcbiAgICAgICAgICAgICAgLy8gVGhpcyBlbnN1cmVzIHRoZSBoYW5kbGVyIHdpbGwgYmUgZGVsZXRlZCBmcm9tIHRoZSByZXNwb25zZUNhbGxiYWNrcyBtYXAgaW4gc2VydmVyLmpzXG4gICAgICAgICAgICAgIC8vIFRoaXMgaXNuJ3QgdGVjaG5pY2FsbHkgbmVlZGVkIGhlcmUgYmVjYXVzZSB0aGUgbG9naWMgaW4gc2VydmVyLmpzIGFsc28gY2hlY2tzIGlmIHRvdGFsQm9keUxlbmd0aCA9PT0gMCwgYnV0IG91ciB1bml0dGVzdHMgYXJlbid0IGdyZWF0IGFib3V0IHNldHRpbmcgdGhhdCBmaWVsZCwgYW5kIGFsc28gdGhpcyBtYWtlcyBpdCBtb3JlIGV4cGxpY2l0XG4gICAgICAgICAgICAgIGhhbmRsZS5xdWlldCA9IGZhbHNlO1xuICAgICAgICAgICAgICByZXNvbHZlKHJlc3BvbnNlTWFwKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgICAgICAgIHJlc3BvbnNlLmhlYWRlci5vcGNvZGUgPT09IGNvbnN0YW50cy5PUF9HRVRLIHx8XG4gICAgICAgICAgICAgIHJlc3BvbnNlLmhlYWRlci5vcGNvZGUgPT09IGNvbnN0YW50cy5PUF9HRVRLUVxuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgIGNvbnN0IGRlc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5kZXNlcmlhbGl6ZShcbiAgICAgICAgICAgICAgICByZXNwb25zZS5oZWFkZXIub3Bjb2RlLFxuICAgICAgICAgICAgICAgIHJlc3BvbnNlLnZhbCxcbiAgICAgICAgICAgICAgICByZXNwb25zZS5leHRyYXNcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgY29uc3Qga2V5ID0gcmVzcG9uc2Uua2V5LnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgIGlmIChrZXkubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlamVjdChcbiAgICAgICAgICAgICAgICAgIG5ldyBFcnJvcihcbiAgICAgICAgICAgICAgICAgICAgXCJSZWNpZXZlZCBlbXB0eSBrZXkgaW4gZ2V0TXVsdGk6IFwiICtcbiAgICAgICAgICAgICAgICAgICAgICBKU09OLnN0cmluZ2lmeShyZXNwb25zZSlcbiAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIHJlc3BvbnNlTWFwW2tleV0gPSB7IC4uLmRlc2VyaWFsaXplZCwgY2FzOiByZXNwb25zZS5oZWFkZXIuY2FzIH07XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICByZXR1cm4gcmVqZWN0KFxuICAgICAgICAgICAgICAgIG5ldyBFcnJvcihcbiAgICAgICAgICAgICAgICAgIFwiUmVjaWV2ZWQgcmVzcG9uc2UgaW4gZ2V0TXVsdGkgZm9yIHVua25vd24gb3Bjb2RlOiBcIiArXG4gICAgICAgICAgICAgICAgICAgIEpTT04uc3RyaW5naWZ5KHJlc3BvbnNlKVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICByZXR1cm4gcmVqZWN0KFxuICAgICAgICAgICAgICB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiR0VUXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9O1xuICAgICAgLy8gVGhpcyBwcmV2ZW50cyB0aGUgaGFuZGxlciBmcm9tIGJlaW5nIGRlbGV0ZWRcbiAgICAgIC8vIGFmdGVyIHRoZSBmaXJzdCByZXNwb25zZS4gTG9naWMgaW4gc2VydmVyLmpzLlxuICAgICAgaGFuZGxlLnF1aWV0ID0gdHJ1ZTtcblxuICAgICAgY29uc3Qgc2VxID0gdGhpcy5pbmNyU2VxKCk7XG4gICAgICBjb25zdCByZXF1ZXN0ID0gdGhpcy5fYnVpbGRHZXRNdWx0aVJlcXVlc3Qoa2V5cywgc2VxKTtcbiAgICAgIHNlcnYub25SZXNwb25zZSh0aGlzLnNlcSwgaGFuZGxlKTtcbiAgICAgIHNlcnYub25FcnJvcih0aGlzLnNlcSwgcmVqZWN0KTtcbiAgICAgIHNlcnYud3JpdGUocmVxdWVzdCk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldnMgdGhlIHZhbHVlIGF0IHRoZSBnaXZlbiBrZXlzIGluIG1lbWNhY2hlZC4gUmV0dXJucyBhIG1hcCBmcm9tIHRoZVxuICAgKiByZXF1ZXN0ZWQga2V5cyB0byByZXN1bHRzLCBvciBudWxsIGlmIHRoZSBrZXkgd2FzIG5vdCBmb3VuZC5cbiAgICovXG4gIGFzeW5jIGdldE11bHRpPEtleXMgZXh0ZW5kcyBzdHJpbmc+KFxuICAgIGtleXM6IEtleXNbXVxuICApOiBQcm9taXNlPEdldE11bHRpUmVzdWx0PEtleXMsIFZhbHVlLCBFeHRyYXM+PiB7XG4gICAgY29uc3Qgc2VydmVyS2V5dG9Mb29rdXBLZXlzOiB7XG4gICAgICBbc2VydmVyS2V5OiBzdHJpbmddOiBzdHJpbmdbXTtcbiAgICB9ID0ge307XG4gICAga2V5cy5mb3JFYWNoKChsb29rdXBLZXkpID0+IHtcbiAgICAgIGNvbnN0IHNlcnZlcktleSA9IHRoaXMubG9va3VwS2V5VG9TZXJ2ZXJLZXkobG9va3VwS2V5KTtcbiAgICAgIGlmICghc2VydmVyS2V5dG9Mb29rdXBLZXlzW3NlcnZlcktleV0pIHtcbiAgICAgICAgc2VydmVyS2V5dG9Mb29rdXBLZXlzW3NlcnZlcktleV0gPSBbXTtcbiAgICAgIH1cbiAgICAgIHNlcnZlcktleXRvTG9va3VwS2V5c1tzZXJ2ZXJLZXldLnB1c2gobG9va3VwS2V5KTtcbiAgICB9KTtcblxuICAgIGNvbnN0IHVzZWRTZXJ2ZXJLZXlzID0gT2JqZWN0LmtleXMoc2VydmVyS2V5dG9Mb29rdXBLZXlzKTtcbiAgICBjb25zdCByZXN1bHRzID0gYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICB1c2VkU2VydmVyS2V5cy5tYXAoKHNlcnZlcktleSkgPT4ge1xuICAgICAgICBjb25zdCBzZXJ2ZXIgPSB0aGlzLnNlcnZlcktleVRvU2VydmVyKHNlcnZlcktleSk7XG4gICAgICAgIHJldHVybiB0aGlzLl9nZXRNdWx0aVRvU2VydmVyKHNlcnZlciwgc2VydmVyS2V5dG9Mb29rdXBLZXlzW3NlcnZlcktleV0pO1xuICAgICAgfSlcbiAgICApO1xuXG4gICAgcmV0dXJuIE9iamVjdC5hc3NpZ24oe30sIC4uLnJlc3VsdHMpO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgYGtleWAgdG8gYHZhbHVlYC5cbiAgICovXG4gIGFzeW5jIHNldChcbiAgICBrZXk6IHN0cmluZyxcbiAgICB2YWx1ZTogVmFsdWUsXG4gICAgb3B0aW9ucz86IHsgZXhwaXJlcz86IG51bWJlcjsgY2FzPzogQ0FTVG9rZW4gfVxuICApOiBQcm9taXNlPGJvb2xlYW4gfCBudWxsPiB7XG4gICAgY29uc3QgZXhwaXJlcyA9IG9wdGlvbnM/LmV4cGlyZXM7XG4gICAgY29uc3QgY2FzID0gb3B0aW9ucz8uY2FzO1xuXG4gICAgLy8gVE9ETzogc3VwcG9ydCBmbGFnc1xuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IGV4cGlyYXRpb24gPSBtYWtlRXhwaXJhdGlvbihleHBpcmVzIHx8IHRoaXMub3B0aW9ucy5leHBpcmVzKTtcbiAgICBjb25zdCBleHRyYXMgPSBCdWZmZXIuY29uY2F0KFtCdWZmZXIuZnJvbShcIjAwMDAwMDAwXCIsIFwiaGV4XCIpLCBleHBpcmF0aW9uXSk7XG4gICAgY29uc3Qgc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5zZXJpYWxpemUoXG4gICAgICBjb25zdGFudHMuT1BfU0VULFxuICAgICAgdmFsdWUsXG4gICAgICBleHRyYXNcbiAgICApO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBVdGlscy5lbmNvZGVSZXF1ZXN0KHtcbiAgICAgIGhlYWRlcjoge1xuICAgICAgICBvcGNvZGU6IGNvbnN0YW50cy5PUF9TRVQsXG4gICAgICAgIG9wYXF1ZTogdGhpcy5zZXEsXG4gICAgICAgIGNhcyxcbiAgICAgIH0sXG4gICAgICBrZXksXG4gICAgICB2YWx1ZTogc2VyaWFsaXplZC52YWx1ZSxcbiAgICAgIGV4dHJhczogc2VyaWFsaXplZC5leHRyYXMsXG4gICAgfSk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfRVhJU1RTOlxuICAgICAgICBpZiAoY2FzKSB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJTRVRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgICAgIH1cbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJTRVRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEFERFxuICAgKlxuICAgKiBBZGRzIHRoZSBnaXZlbiBfa2V5XyBhbmQgX3ZhbHVlXyB0byBtZW1jYWNoZS4gVGhlIG9wZXJhdGlvbiBvbmx5IHN1Y2NlZWRzXG4gICAqIGlmIHRoZSBrZXkgaXMgbm90IGFscmVhZHkgc2V0LlxuICAgKlxuICAgKiBUaGUgb3B0aW9ucyBkaWN0aW9uYXJ5IHRha2VzOlxuICAgKiAqIF9leHBpcmVzXzogb3ZlcnJpZGVzIHRoZSBkZWZhdWx0IGV4cGlyYXRpb24gKHNlZSBgQ2xpZW50LmNyZWF0ZWApIGZvciB0aGlzXG4gICAqICAgICAgICAgICAgICBwYXJ0aWN1bGFyIGtleS12YWx1ZSBwYWlyLlxuICAgKi9cbiAgYXN5bmMgYWRkKFxuICAgIGtleTogc3RyaW5nLFxuICAgIHZhbHVlOiBWYWx1ZSxcbiAgICBvcHRpb25zPzogeyBleHBpcmVzPzogbnVtYmVyIH1cbiAgKTogUHJvbWlzZTxib29sZWFuIHwgbnVsbD4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgZmxhZ3MsIHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IGV4cGlyYXRpb24gPSBtYWtlRXhwaXJhdGlvbihvcHRpb25zPy5leHBpcmVzIHx8IHRoaXMub3B0aW9ucy5leHBpcmVzKTtcbiAgICBjb25zdCBleHRyYXMgPSBCdWZmZXIuY29uY2F0KFtCdWZmZXIuZnJvbShcIjAwMDAwMDAwXCIsIFwiaGV4XCIpLCBleHBpcmF0aW9uXSk7XG5cbiAgICBjb25zdCBvcGNvZGUgPSBjb25zdGFudHMuT1BfQUREO1xuICAgIGNvbnN0IHNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuc2VyaWFsaXplKG9wY29kZSwgdmFsdWUsIGV4dHJhcyk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKFxuICAgICAgb3Bjb2RlLFxuICAgICAga2V5LFxuICAgICAgc2VyaWFsaXplZC5leHRyYXMsXG4gICAgICBzZXJpYWxpemVkLnZhbHVlLFxuICAgICAgdGhpcy5zZXFcbiAgICApO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuS0VZX0VYSVNUUzpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJBRERcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlcGxhY2VzIHRoZSBnaXZlbiBfa2V5XyBhbmQgX3ZhbHVlXyB0byBtZW1jYWNoZS4gVGhlIG9wZXJhdGlvbiBvbmx5IHN1Y2NlZWRzXG4gICAqIGlmIHRoZSBrZXkgaXMgYWxyZWFkeSBwcmVzZW50LlxuICAgKi9cbiAgYXN5bmMgcmVwbGFjZShcbiAgICBrZXk6IHN0cmluZyxcbiAgICB2YWx1ZTogVmFsdWUsXG4gICAgb3B0aW9ucz86IHsgZXhwaXJlcz86IG51bWJlciB9XG4gICk6IFByb21pc2U8Ym9vbGVhbiB8IG51bGw+IHtcbiAgICAvLyBUT0RPOiBzdXBwb3J0IGZsYWdzLCBzdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBleHBpcmF0aW9uID0gbWFrZUV4cGlyYXRpb24ob3B0aW9ucz8uZXhwaXJlcyB8fCB0aGlzLm9wdGlvbnMuZXhwaXJlcyk7XG4gICAgY29uc3QgZXh0cmFzID0gQnVmZmVyLmNvbmNhdChbQnVmZmVyLmZyb20oXCIwMDAwMDAwMFwiLCBcImhleFwiKSwgZXhwaXJhdGlvbl0pO1xuXG4gICAgY29uc3Qgb3Bjb2RlOiBjb25zdGFudHMuT1AgPSBjb25zdGFudHMuT1BfUkVQTEFDRTtcbiAgICBjb25zdCBzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLnNlcmlhbGl6ZShvcGNvZGUsIHZhbHVlLCBleHRyYXMpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgIG9wY29kZSxcbiAgICAgIGtleSxcbiAgICAgIHNlcmlhbGl6ZWQuZXh0cmFzLFxuICAgICAgc2VyaWFsaXplZC52YWx1ZSxcbiAgICAgIHRoaXMuc2VxXG4gICAgKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJSRVBMQUNFXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBEZWxldGVzIHRoZSBnaXZlbiBfa2V5XyBmcm9tIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHNcbiAgICogaWYgdGhlIGtleSBpcyBhbHJlYWR5IHByZXNlbnQuXG4gICAqL1xuICBhc3luYyBkZWxldGUoa2V5OiBzdHJpbmcpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAvLyBUT0RPOiBTdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoNCwga2V5LCBcIlwiLCBcIlwiLCB0aGlzLnNlcSk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG5cbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJERUxFVEVcIiwgcmVzcG9uc2U/LmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBJbmNyZW1lbnRzIHRoZSBnaXZlbiBfa2V5XyBpbiBtZW1jYWNoZS5cbiAgICovXG4gIGFzeW5jIGluY3JlbWVudChcbiAgICBrZXk6IHN0cmluZyxcbiAgICBhbW91bnQ6IG51bWJlcixcbiAgICBvcHRpb25zPzogeyBpbml0aWFsPzogbnVtYmVyOyBleHBpcmVzPzogbnVtYmVyIH1cbiAgKTogUHJvbWlzZTx7IHZhbHVlOiBudW1iZXIgfCBudWxsOyBzdWNjZXNzOiBib29sZWFuIHwgbnVsbCB9PiB7XG4gICAgLy8gVE9ETzogc3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgaW5pdGlhbCA9IG9wdGlvbnM/LmluaXRpYWwgfHwgMDtcbiAgICBjb25zdCBleHBpcmVzID0gb3B0aW9ucz8uZXhwaXJlcyB8fCB0aGlzLm9wdGlvbnMuZXhwaXJlcztcbiAgICBjb25zdCBleHRyYXMgPSBtYWtlQW1vdW50SW5pdGlhbEFuZEV4cGlyYXRpb24oYW1vdW50LCBpbml0aWFsLCBleHBpcmVzKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICBjb25zdGFudHMuT1BfSU5DUkVNRU5ULFxuICAgICAga2V5LFxuICAgICAgZXh0cmFzLFxuICAgICAgXCJcIixcbiAgICAgIHRoaXMuc2VxXG4gICAgKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgY29uc3QgYnVmSW50ID1cbiAgICAgICAgICAocmVzcG9uc2UudmFsLnJlYWRVSW50MzJCRSgwKSA8PCA4KSArIHJlc3BvbnNlLnZhbC5yZWFkVUludDMyQkUoNCk7XG4gICAgICAgIHJldHVybiB7IHZhbHVlOiBidWZJbnQsIHN1Y2Nlc3M6IHRydWUgfTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJJTkNSRU1FTlRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIERlY3JlbWVudHMgdGhlIGdpdmVuIGBrZXlgIGluIG1lbWNhY2hlLlxuICAgKi9cbiAgYXN5bmMgZGVjcmVtZW50KFxuICAgIGtleTogc3RyaW5nLFxuICAgIGFtb3VudDogbnVtYmVyLFxuICAgIG9wdGlvbnM6IHsgaW5pdGlhbD86IG51bWJlcjsgZXhwaXJlcz86IG51bWJlciB9XG4gICk6IFByb21pc2U8eyB2YWx1ZTogbnVtYmVyIHwgbnVsbDsgc3VjY2VzczogYm9vbGVhbiB8IG51bGwgfT4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IGluaXRpYWwgPSBvcHRpb25zLmluaXRpYWwgfHwgMDtcbiAgICBjb25zdCBleHBpcmVzID0gb3B0aW9ucy5leHBpcmVzIHx8IHRoaXMub3B0aW9ucy5leHBpcmVzO1xuICAgIGNvbnN0IGV4dHJhcyA9IG1ha2VBbW91bnRJbml0aWFsQW5kRXhwaXJhdGlvbihhbW91bnQsIGluaXRpYWwsIGV4cGlyZXMpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgIGNvbnN0YW50cy5PUF9ERUNSRU1FTlQsXG4gICAgICBrZXksXG4gICAgICBleHRyYXMsXG4gICAgICBcIlwiLFxuICAgICAgdGhpcy5zZXFcbiAgICApO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICBjb25zdCBidWZJbnQgPVxuICAgICAgICAgIChyZXNwb25zZS52YWwucmVhZFVJbnQzMkJFKDApIDw8IDgpICsgcmVzcG9uc2UudmFsLnJlYWRVSW50MzJCRSg0KTtcbiAgICAgICAgcmV0dXJuIHsgdmFsdWU6IGJ1ZkludCwgc3VjY2VzczogdHJ1ZSB9O1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIkRFQ1JFTUVOVFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQXBwZW5kIHRoZSBnaXZlbiBfdmFsdWVfIHRvIHRoZSB2YWx1ZSBhc3NvY2lhdGVkIHdpdGggdGhlIGdpdmVuIF9rZXlfIGluXG4gICAqIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHMgaWYgdGhlIGtleSBpcyBhbHJlYWR5IHByZXNlbnQuXG4gICAqL1xuICBhc3luYyBhcHBlbmQoa2V5OiBzdHJpbmcsIHZhbHVlOiBWYWx1ZSk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IG9wY29kZTogY29uc3RhbnRzLk9QID0gY29uc3RhbnRzLk9QX0FQUEVORDtcbiAgICBjb25zdCBzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLnNlcmlhbGl6ZShvcGNvZGUsIHZhbHVlLCBcIlwiKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICBvcGNvZGUsXG4gICAgICBrZXksXG4gICAgICBzZXJpYWxpemVkLmV4dHJhcyxcbiAgICAgIHNlcmlhbGl6ZWQudmFsdWUsXG4gICAgICB0aGlzLnNlcVxuICAgICk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfTk9UX0ZPVU5EOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiQVBQRU5EXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBQcmVwZW5kIHRoZSBnaXZlbiBfdmFsdWVfIHRvIHRoZSB2YWx1ZSBhc3NvY2lhdGVkIHdpdGggdGhlIGdpdmVuIF9rZXlfIGluXG4gICAqIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHMgaWYgdGhlIGtleSBpcyBhbHJlYWR5IHByZXNlbnQuXG4gICAqL1xuICBhc3luYyBwcmVwZW5kKGtleTogc3RyaW5nLCB2YWx1ZTogVmFsdWUpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAvLyBUT0RPOiBzdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBvcGNvZGU6IGNvbnN0YW50cy5PUCA9IGNvbnN0YW50cy5PUF9QUkVQRU5EO1xuICAgIGNvbnN0IHNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuc2VyaWFsaXplKG9wY29kZSwgdmFsdWUsIFwiXCIpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgIG9wY29kZSxcbiAgICAgIGtleSxcbiAgICAgIHNlcmlhbGl6ZWQuZXh0cmFzLFxuICAgICAgc2VyaWFsaXplZC52YWx1ZSxcbiAgICAgIHRoaXMuc2VxXG4gICAgKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJQUkVQRU5EXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBUb3VjaCBzZXRzIGFuIGV4cGlyYXRpb24gdmFsdWUsIGdpdmVuIGJ5IF9leHBpcmVzXywgb24gdGhlIGdpdmVuIF9rZXlfIGluXG4gICAqIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHMgaWYgdGhlIGtleSBpcyBhbHJlYWR5IHByZXNlbnQuXG4gICAqL1xuICBhc3luYyB0b3VjaChrZXk6IHN0cmluZywgZXhwaXJlczogbnVtYmVyKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgLy8gVE9ETzogc3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgZXh0cmFzID0gbWFrZUV4cGlyYXRpb24oZXhwaXJlcyB8fCB0aGlzLm9wdGlvbnMuZXhwaXJlcyk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKDB4MWMsIGtleSwgZXh0cmFzLCBcIlwiLCB0aGlzLnNlcSk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfTk9UX0ZPVU5EOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiVE9VQ0hcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEZMVVNIXG4gICAqXG4gICAqIEZsdXNoZXMgdGhlIGNhY2hlIG9uIGVhY2ggY29ubmVjdGVkIHNlcnZlci4gVGhlIGNhbGxiYWNrIHNpZ25hdHVyZSBpczpcbiAgICpcbiAgICogICAgIGNhbGxiYWNrKGxhc3RFcnIsIHJlc3VsdHMpXG4gICAqXG4gICAqIHdoZXJlIF9sYXN0RXJyXyBpcyB0aGUgbGFzdCBlcnJvciBlbmNvdW50ZXJlZCAob3IgbnVsbCwgaW4gdGhlIGNvbW1vbiBjYXNlXG4gICAqIG9mIG5vIGVycm9ycykuIF9yZXN1bHRzXyBpcyBhIGRpY3Rpb25hcnkgbWFwcGluZyBgXCJob3N0bmFtZTpwb3J0XCJgIHRvIGVpdGhlclxuICAgKiBgdHJ1ZWAgKGlmIHRoZSBvcGVyYXRpb24gd2FzIHN1Y2Nlc3NmdWwpLCBvciBhbiBlcnJvci5cbiAgICogQHBhcmFtIGNhbGxiYWNrXG4gICAqL1xuICBmbHVzaCgpOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIGJvb2xlYW4gfCBFcnJvcj4+O1xuICBmbHVzaChcbiAgICBjYWxsYmFjazogKFxuICAgICAgZXJyOiBFcnJvciB8IG51bGwsXG4gICAgICByZXN1bHRzOiBSZWNvcmQ8c3RyaW5nLCBib29sZWFuIHwgRXJyb3I+XG4gICAgKSA9PiB2b2lkXG4gICk6IHZvaWQ7XG4gIGZsdXNoKFxuICAgIGNhbGxiYWNrPzogKFxuICAgICAgZXJyOiBFcnJvciB8IG51bGwsXG4gICAgICByZXN1bHRzOiBSZWNvcmQ8c3RyaW5nLCBib29sZWFuIHwgRXJyb3I+XG4gICAgKSA9PiB2b2lkXG4gICkge1xuICAgIGlmIChjYWxsYmFjayA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm4gcHJvbWlzaWZ5KChjYWxsYmFjaykgPT4ge1xuICAgICAgICB0aGlzLmZsdXNoKGZ1bmN0aW9uIChlcnIsIHJlc3VsdHMpIHtcbiAgICAgICAgICBjYWxsYmFjayhlcnIsIHJlc3VsdHMpO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH1cbiAgICAvLyBUT0RPOiBzdXBwb3J0IGV4cGlyYXRpb25cbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoMHgwOCwgXCJcIiwgXCJcIiwgXCJcIiwgdGhpcy5zZXEpO1xuICAgIGxldCBjb3VudCA9IHRoaXMuc2VydmVycy5sZW5ndGg7XG4gICAgY29uc3QgcmVzdWx0OiBSZWNvcmQ8c3RyaW5nLCBib29sZWFuIHwgRXJyb3I+ID0ge307XG4gICAgbGV0IGxhc3RFcnI6IEVycm9yIHwgbnVsbCA9IG51bGw7XG5cbiAgICBjb25zdCBoYW5kbGVGbHVzaCA9IGZ1bmN0aW9uIChzZXE6IG51bWJlciwgc2VydjogU2VydmVyKSB7XG4gICAgICBzZXJ2Lm9uUmVzcG9uc2Uoc2VxLCBmdW5jdGlvbiAoLyogcmVzcG9uc2UgKi8pIHtcbiAgICAgICAgY291bnQgLT0gMTtcbiAgICAgICAgcmVzdWx0W3NlcnYuaG9zdHBvcnRTdHJpbmcoKV0gPSB0cnVlO1xuICAgICAgICBpZiAoY2FsbGJhY2sgJiYgY291bnQgPT09IDApIHtcbiAgICAgICAgICBjYWxsYmFjayhsYXN0RXJyLCByZXN1bHQpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHNlcnYub25FcnJvcihzZXEsIGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgICAgY291bnQgLT0gMTtcbiAgICAgICAgbGFzdEVyciA9IGVycjtcbiAgICAgICAgcmVzdWx0W3NlcnYuaG9zdHBvcnRTdHJpbmcoKV0gPSBlcnI7XG4gICAgICAgIGlmIChjYWxsYmFjayAmJiBjb3VudCA9PT0gMCkge1xuICAgICAgICAgIGNhbGxiYWNrKGxhc3RFcnIsIHJlc3VsdCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgc2Vydi53cml0ZShyZXF1ZXN0KTtcbiAgICB9O1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnNlcnZlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGhhbmRsZUZsdXNoKHRoaXMuc2VxLCB0aGlzLnNlcnZlcnNbaV0pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTVEFUU19XSVRIX0tFWVxuICAgKlxuICAgKiBTZW5kcyBhIG1lbWNhY2hlIHN0YXRzIGNvbW1hbmQgd2l0aCBhIGtleSB0byBlYWNoIGNvbm5lY3RlZCBzZXJ2ZXIuIFRoZVxuICAgKiBjYWxsYmFjayBpcyBpbnZva2VkICoqT05DRSBQRVIgU0VSVkVSKiogYW5kIGhhcyB0aGUgc2lnbmF0dXJlOlxuICAgKlxuICAgKiAgICAgY2FsbGJhY2soZXJyLCBzZXJ2ZXIsIHN0YXRzKVxuICAgKlxuICAgKiBfc2VydmVyXyBpcyB0aGUgYFwiaG9zdG5hbWU6cG9ydFwiYCBvZiB0aGUgc2VydmVyLCBhbmQgX3N0YXRzXyBpcyBhIGRpY3Rpb25hcnlcbiAgICogbWFwcGluZyB0aGUgc3RhdCBuYW1lIHRvIHRoZSB2YWx1ZSBvZiB0aGUgc3RhdGlzdGljIGFzIGEgc3RyaW5nLlxuICAgKiBAcGFyYW0ga2V5XG4gICAqIEBwYXJhbSBjYWxsYmFja1xuICAgKi9cbiAgc3RhdHNXaXRoS2V5KFxuICAgIGtleTogc3RyaW5nLFxuICAgIGNhbGxiYWNrPzogKFxuICAgICAgZXJyOiBFcnJvciB8IG51bGwsXG4gICAgICBzZXJ2ZXI6IHN0cmluZyxcbiAgICAgIHN0YXRzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+IHwgbnVsbFxuICAgICkgPT4gdm9pZFxuICApOiB2b2lkIHtcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoMHgxMCwga2V5LCBcIlwiLCBcIlwiLCB0aGlzLnNlcSk7XG5cbiAgICBjb25zdCBoYW5kbGVTdGF0cyA9IChzZXE6IG51bWJlciwgc2VydjogU2VydmVyKSA9PiB7XG4gICAgICBjb25zdCByZXN1bHQ6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcbiAgICAgIGNvbnN0IGhhbmRsZTogT25SZXNwb25zZUNhbGxiYWNrID0gKHJlc3BvbnNlKSA9PiB7XG4gICAgICAgIC8vIGVuZCBvZiBzdGF0IHJlc3BvbnNlc1xuICAgICAgICBpZiAocmVzcG9uc2UuaGVhZGVyLnRvdGFsQm9keUxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgICAgY2FsbGJhY2sobnVsbCwgc2Vydi5ob3N0cG9ydFN0cmluZygpLCByZXN1bHQpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgLy8gcHJvY2VzcyBzaW5nbGUgc3RhdCBsaW5lIHJlc3BvbnNlXG4gICAgICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgICAgIHJlc3VsdFtyZXNwb25zZS5rZXkudG9TdHJpbmcoKV0gPSByZXNwb25zZS52YWwudG9TdHJpbmcoKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICBjb25zdCBlcnJvciA9IHRoaXMuaGFuZGxlUmVzcG9uc2VFcnJvcihcbiAgICAgICAgICAgICAgYFNUQVRTICgke2tleX0pYCxcbiAgICAgICAgICAgICAgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyxcbiAgICAgICAgICAgICAgdW5kZWZpbmVkXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgICAgICAgIGNhbGxiYWNrKGVycm9yLCBzZXJ2Lmhvc3Rwb3J0U3RyaW5nKCksIG51bGwpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9O1xuICAgICAgaGFuZGxlLnF1aWV0ID0gdHJ1ZTtcblxuICAgICAgc2Vydi5vblJlc3BvbnNlKHNlcSwgaGFuZGxlKTtcbiAgICAgIHNlcnYub25FcnJvcihzZXEsIGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgICAgY2FsbGJhY2soZXJyLCBzZXJ2Lmhvc3Rwb3J0U3RyaW5nKCksIG51bGwpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHNlcnYud3JpdGUocmVxdWVzdCk7XG4gICAgfTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5zZXJ2ZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBoYW5kbGVTdGF0cyh0aGlzLnNlcSwgdGhpcy5zZXJ2ZXJzW2ldKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU1RBVFNcbiAgICpcbiAgICogRmV0Y2hlcyBtZW1jYWNoZSBzdGF0cyBmcm9tIGVhY2ggY29ubmVjdGVkIHNlcnZlci4gVGhlIGNhbGxiYWNrIGlzIGludm9rZWRcbiAgICogKipPTkNFIFBFUiBTRVJWRVIqKiBhbmQgaGFzIHRoZSBzaWduYXR1cmU6XG4gICAqXG4gICAqICAgICBjYWxsYmFjayhlcnIsIHNlcnZlciwgc3RhdHMpXG4gICAqXG4gICAqIF9zZXJ2ZXJfIGlzIHRoZSBgXCJob3N0bmFtZTpwb3J0XCJgIG9mIHRoZSBzZXJ2ZXIsIGFuZCBfc3RhdHNfIGlzIGFcbiAgICogZGljdGlvbmFyeSBtYXBwaW5nIHRoZSBzdGF0IG5hbWUgdG8gdGhlIHZhbHVlIG9mIHRoZSBzdGF0aXN0aWMgYXMgYSBzdHJpbmcuXG4gICAqIEBwYXJhbSBjYWxsYmFja1xuICAgKi9cbiAgc3RhdHMoXG4gICAgY2FsbGJhY2s/OiAoXG4gICAgICBlcnI6IEVycm9yIHwgbnVsbCxcbiAgICAgIHNlcnZlcjogc3RyaW5nLFxuICAgICAgc3RhdHM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gfCBudWxsXG4gICAgKSA9PiB2b2lkXG4gICk6IHZvaWQge1xuICAgIHRoaXMuc3RhdHNXaXRoS2V5KFwiXCIsIGNhbGxiYWNrKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSRVNFVF9TVEFUU1xuICAgKlxuICAgKiBSZXNldCB0aGUgc3RhdGlzdGljcyBlYWNoIHNlcnZlciBpcyBrZWVwaW5nIGJhY2sgdG8gemVyby4gVGhpcyBkb2Vzbid0IGNsZWFyXG4gICAqIHN0YXRzIHN1Y2ggYXMgaXRlbSBjb3VudCwgYnV0IHRlbXBvcmFyeSBzdGF0cyBzdWNoIGFzIHRvdGFsIG51bWJlciBvZlxuICAgKiBjb25uZWN0aW9ucyBvdmVyIHRpbWUuXG4gICAqXG4gICAqIFRoZSBjYWxsYmFjayBpcyBpbnZva2VkICoqT05DRSBQRVIgU0VSVkVSKiogYW5kIGhhcyB0aGUgc2lnbmF0dXJlOlxuICAgKlxuICAgKiAgICAgY2FsbGJhY2soZXJyLCBzZXJ2ZXIpXG4gICAqXG4gICAqIF9zZXJ2ZXJfIGlzIHRoZSBgXCJob3N0bmFtZTpwb3J0XCJgIG9mIHRoZSBzZXJ2ZXIuXG4gICAqIEBwYXJhbSBjYWxsYmFja1xuICAgKi9cbiAgcmVzZXRTdGF0cyhcbiAgICBjYWxsYmFjaz86IChcbiAgICAgIGVycjogRXJyb3IgfCBudWxsLFxuICAgICAgc2VydmVyOiBzdHJpbmcsXG4gICAgICBzdGF0czogUmVjb3JkPHN0cmluZywgc3RyaW5nPiB8IG51bGxcbiAgICApID0+IHZvaWRcbiAgKTogdm9pZCB7XG4gICAgdGhpcy5zdGF0c1dpdGhLZXkoXCJyZXNldFwiLCBjYWxsYmFjayk7XG4gIH1cblxuICAvKipcbiAgICogUVVJVFxuICAgKlxuICAgKiBDbG9zZXMgdGhlIGNvbm5lY3Rpb24gdG8gZWFjaCBzZXJ2ZXIsIG5vdGlmeWluZyB0aGVtIG9mIHRoaXMgaW50ZW50aW9uLiBOb3RlXG4gICAqIHRoYXQgcXVpdCBjYW4gcmFjZSBhZ2FpbnN0IGFscmVhZHkgb3V0c3RhbmRpbmcgcmVxdWVzdHMgd2hlbiB0aG9zZSByZXF1ZXN0c1xuICAgKiBmYWlsIGFuZCBhcmUgcmV0cmllZCwgbGVhZGluZyB0byB0aGUgcXVpdCBjb21tYW5kIHdpbm5pbmcgYW5kIGNsb3NpbmcgdGhlXG4gICAqIGNvbm5lY3Rpb24gYmVmb3JlIHRoZSByZXRyaWVzIGNvbXBsZXRlLlxuICAgKi9cbiAgcXVpdCgpIHtcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICAvLyBUT0RPOiBOaWNlciBwZXJoYXBzIHRvIGRvIFFVSVRRICgweDE3KSBidXQgbmVlZCBhIG5ldyBjYWxsYmFjayBmb3Igd2hlblxuICAgIC8vIHdyaXRlIGlzIGRvbmUuXG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKDB4MDcsIFwiXCIsIFwiXCIsIFwiXCIsIHRoaXMuc2VxKTsgLy8gUVVJVFxuICAgIGxldCBzZXJ2O1xuXG4gICAgY29uc3QgaGFuZGxlUXVpdCA9IGZ1bmN0aW9uIChzZXE6IG51bWJlciwgc2VydjogU2VydmVyKSB7XG4gICAgICBzZXJ2Lm9uUmVzcG9uc2Uoc2VxLCBmdW5jdGlvbiAoLyogcmVzcG9uc2UgKi8pIHtcbiAgICAgICAgc2Vydi5jbG9zZSgpO1xuICAgICAgfSk7XG4gICAgICBzZXJ2Lm9uRXJyb3Ioc2VxLCBmdW5jdGlvbiAoLyogZXJyICovKSB7XG4gICAgICAgIHNlcnYuY2xvc2UoKTtcbiAgICAgIH0pO1xuICAgICAgc2Vydi53cml0ZShyZXF1ZXN0KTtcbiAgICB9O1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnNlcnZlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHNlcnYgPSB0aGlzLnNlcnZlcnNbaV07XG4gICAgICBoYW5kbGVRdWl0KHRoaXMuc2VxLCBzZXJ2KTtcbiAgICB9XG4gIH1cblxuICBfdmVyc2lvbihzZXJ2ZXI6IFNlcnZlcik6IFByb21pc2U8eyB2YWx1ZTogVmFsdWUgfCBudWxsIH0+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICAgIGNvbnN0YW50cy5PUF9WRVJTSU9OLFxuICAgICAgICBcIlwiLFxuICAgICAgICBcIlwiLFxuICAgICAgICBcIlwiLFxuICAgICAgICB0aGlzLnNlcVxuICAgICAgKTtcbiAgICAgIHRoaXMucGVyZm9ybU9uU2VydmVyKHNlcnZlciwgcmVxdWVzdCwgdGhpcy5zZXEsIChlcnIsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICByZXR1cm4gcmVqZWN0KGVycik7XG4gICAgICAgIH1cblxuICAgICAgICBzd2l0Y2ggKHJlc3BvbnNlIS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICAgICAgLyogVE9ETzogdGhpcyBpcyBidWdnZWQsIHdlIHNob3VsZCd0IHVzZSB0aGUgZGVzZXJpYWxpemVyIGhlcmUsIHNpbmNlIHZlcnNpb24gYWx3YXlzIHJldHVybnMgYSB2ZXJzaW9uIHN0cmluZy5cbiAgICAgICAgICAgICBUaGUgZGVzZXJpYWxpemVyIHNob3VsZCBvbmx5IGJlIHVzZWQgb24gdXNlciBrZXkgZGF0YS4gKi9cbiAgICAgICAgICAgIGNvbnN0IGRlc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5kZXNlcmlhbGl6ZShcbiAgICAgICAgICAgICAgcmVzcG9uc2UhLmhlYWRlci5vcGNvZGUsXG4gICAgICAgICAgICAgIHJlc3BvbnNlIS52YWwsXG4gICAgICAgICAgICAgIHJlc3BvbnNlIS5leHRyYXNcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICByZXR1cm4gcmVzb2x2ZSh7IHZhbHVlOiBkZXNlcmlhbGl6ZWQudmFsdWUgfSk7XG4gICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHJldHVybiByZWplY3QoXG4gICAgICAgICAgICAgIHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJWRVJTSU9OXCIsIHJlc3BvbnNlIS5oZWFkZXIuc3RhdHVzKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmVxdWVzdCB0aGUgc2VydmVyIHZlcnNpb24gZnJvbSB0aGUgXCJmaXJzdFwiIHNlcnZlciBpbiB0aGUgYmFja2VuZCBwb29sLlxuICAgKiBUaGUgc2VydmVyIHJlc3BvbmRzIHdpdGggYSBwYWNrZXQgY29udGFpbmluZyB0aGUgdmVyc2lvbiBzdHJpbmcgaW4gdGhlIGJvZHkgd2l0aCB0aGUgZm9sbG93aW5nIGZvcm1hdDogXCJ4LnkuelwiXG4gICAqL1xuICB2ZXJzaW9uKCk6IFByb21pc2U8eyB2YWx1ZTogVmFsdWUgfCBudWxsIH0+IHtcbiAgICBjb25zdCBzZXJ2ZXIgPSB0aGlzLnNlcnZlcktleVRvU2VydmVyKHRoaXMuc2VydmVyS2V5c1swXSk7XG4gICAgcmV0dXJuIHRoaXMuX3ZlcnNpb24oc2VydmVyKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXRyaWV2ZXMgdGhlIHNlcnZlciB2ZXJzaW9uIGZyb20gYWxsIHRoZSBzZXJ2ZXJzXG4gICAqIGluIHRoZSBiYWNrZW5kIHBvb2wsIGVycm9ycyBpZiBhbnkgb25lIG9mIHRoZW0gaGFzIGFuXG4gICAqIGVycm9yXG4gICAqL1xuICBhc3luYyB2ZXJzaW9uQWxsKGNhbGxiYWNrcz86IHtcbiAgICBiZWZvcmVQaW5nPzogKHJlc3BvbnNlOiBzdHJpbmcpID0+IHZvaWQ7XG4gICAgYWZ0ZXJQaW5nPzogKHJlc3BvbnNlOiBzdHJpbmcpID0+IHZvaWQ7XG4gIH0pOiBQcm9taXNlPHtcbiAgICB2YWx1ZXM6IFJlY29yZDxzdHJpbmcsIFZhbHVlIHwgbnVsbD47XG4gIH0+IHtcbiAgICBjb25zdCB2ZXJzaW9uT2JqZWN0cyA9IGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgdGhpcy5zZXJ2ZXJLZXlzLm1hcCgoc2VydmVyS2V5KSA9PiB7XG4gICAgICAgIGNvbnN0IHNlcnZlciA9IHRoaXMuc2VydmVyS2V5VG9TZXJ2ZXIoc2VydmVyS2V5KTtcbiAgICAgICAgY2FsbGJhY2tzPy5iZWZvcmVQaW5nPy4oc2VydmVyS2V5KTtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3ZlcnNpb24oc2VydmVyKS50aGVuKChyZXNwb25zZSkgPT4ge1xuICAgICAgICAgIGNhbGxiYWNrcz8uYWZ0ZXJQaW5nPy4oc2VydmVyS2V5KTtcbiAgICAgICAgICByZXR1cm4geyBzZXJ2ZXJLZXk6IHNlcnZlcktleSwgdmFsdWU6IHJlc3BvbnNlLnZhbHVlIH07XG4gICAgICAgIH0pO1xuICAgICAgfSlcbiAgICApO1xuICAgIGNvbnN0IHZhbHVlcyA9IHZlcnNpb25PYmplY3RzLnJlZHVjZSgoYWNjdW11bGF0b3IsIHZlcnNpb25PYmplY3QpID0+IHtcbiAgICAgIGFjY3VtdWxhdG9yW3ZlcnNpb25PYmplY3Quc2VydmVyS2V5XSA9IHZlcnNpb25PYmplY3QudmFsdWU7XG4gICAgICByZXR1cm4gYWNjdW11bGF0b3I7XG4gICAgfSwge30gYXMgUmVjb3JkPHN0cmluZywgVmFsdWUgfCBudWxsPik7XG4gICAgcmV0dXJuIHsgdmFsdWVzOiB2YWx1ZXMgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDbG9zZXMgKGFicnVwdGx5KSBjb25uZWN0aW9ucyB0byBhbGwgdGhlIHNlcnZlcnMuXG4gICAqIEBzZWUgdGhpcy5xdWl0XG4gICAqL1xuICBjbG9zZSgpIHtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuc2VydmVycy5sZW5ndGg7IGkrKykge1xuICAgICAgdGhpcy5zZXJ2ZXJzW2ldLmNsb3NlKCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFBlcmZvcm0gYSBnZW5lcmljIHNpbmdsZSByZXNwb25zZSBvcGVyYXRpb24gKGdldCwgc2V0IGV0Yykgb24gb25lIHNlcnZlclxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IHRoZSBrZXkgdG8gaGFzaCB0byBnZXQgYSBzZXJ2ZXIgZnJvbSB0aGUgcG9vbFxuICAgKiBAcGFyYW0ge2J1ZmZlcn0gcmVxdWVzdCBhIGJ1ZmZlciBjb250YWluaW5nIHRoZSByZXF1ZXN0XG4gICAqIEBwYXJhbSB7bnVtYmVyfSBzZXEgdGhlIHNlcXVlbmNlIG51bWJlciBvZiB0aGUgb3BlcmF0aW9uLiBJdCBpcyB1c2VkIHRvIHBpbiB0aGUgY2FsbGJhY2tzXG4gICAgICAgICAgICAgICAgICAgICAgICAgdG8gYSBzcGVjaWZpYyBvcGVyYXRpb24gYW5kIHNob3VsZCBuZXZlciBjaGFuZ2UgZHVyaW5nIGEgYHBlcmZvcm1gLlxuICAgKiBAcGFyYW0ge251bWJlcj99IHJldHJpZXMgbnVtYmVyIG9mIHRpbWVzIHRvIHJldHJ5IHJlcXVlc3Qgb24gZmFpbHVyZVxuICAgKi9cbiAgcGVyZm9ybShcbiAgICBrZXk6IHN0cmluZyxcbiAgICByZXF1ZXN0OiBCdWZmZXIsXG4gICAgc2VxOiBudW1iZXIsXG4gICAgcmV0cmllcz86IG51bWJlclxuICApOiBQcm9taXNlPE1lc3NhZ2U+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgY29uc3Qgc2VydmVyS2V5ID0gdGhpcy5sb29rdXBLZXlUb1NlcnZlcktleShrZXkpO1xuICAgICAgY29uc3Qgc2VydmVyID0gdGhpcy5zZXJ2ZXJLZXlUb1NlcnZlcihzZXJ2ZXJLZXkpO1xuXG4gICAgICBpZiAoIXNlcnZlcikge1xuICAgICAgICByZXR1cm4gcmVqZWN0KG5ldyBFcnJvcihcIk5vIHNlcnZlcnMgYXZhaWxhYmxlXCIpKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5wZXJmb3JtT25TZXJ2ZXIoXG4gICAgICAgIHNlcnZlcixcbiAgICAgICAgcmVxdWVzdCxcbiAgICAgICAgc2VxLFxuICAgICAgICAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICByZXR1cm4gcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmVzb2x2ZShyZXNwb25zZSEpO1xuICAgICAgICB9LFxuICAgICAgICByZXRyaWVzXG4gICAgICApO1xuICAgIH0pO1xuICB9XG5cbiAgcGVyZm9ybU9uU2VydmVyKFxuICAgIHNlcnZlcjogU2VydmVyLFxuICAgIHJlcXVlc3Q6IEJ1ZmZlcixcbiAgICBzZXE6IG51bWJlcixcbiAgICBjYWxsYmFjazogUmVzcG9uc2VPckVycm9yQ2FsbGJhY2ssXG4gICAgcmV0cmllczogbnVtYmVyID0gMFxuICApIHtcbiAgICBjb25zdCBfdGhpcyA9IHRoaXM7XG5cbiAgICByZXRyaWVzID0gcmV0cmllcyB8fCB0aGlzLm9wdGlvbnMucmV0cmllcztcbiAgICBjb25zdCBvcmlnUmV0cmllcyA9IHRoaXMub3B0aW9ucy5yZXRyaWVzO1xuICAgIGNvbnN0IGxvZ2dlciA9IHRoaXMub3B0aW9ucy5sb2dnZXI7XG4gICAgY29uc3QgcmV0cnlfZGVsYXkgPSB0aGlzLm9wdGlvbnMucmV0cnlfZGVsYXk7XG5cbiAgICBjb25zdCByZXNwb25zZUhhbmRsZXI6IE9uUmVzcG9uc2VDYWxsYmFjayA9IGZ1bmN0aW9uIChyZXNwb25zZSkge1xuICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgIGNhbGxiYWNrKG51bGwsIHJlc3BvbnNlKTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgY29uc3QgZXJyb3JIYW5kbGVyOiBPbkVycm9yQ2FsbGJhY2sgPSBmdW5jdGlvbiAoZXJyb3IpIHtcbiAgICAgIGlmICgtLXJldHJpZXMgPiAwKSB7XG4gICAgICAgIC8vIFdhaXQgZm9yIHJldHJ5X2RlbGF5XG4gICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgIF90aGlzLnBlcmZvcm1PblNlcnZlcihzZXJ2ZXIsIHJlcXVlc3QsIHNlcSwgY2FsbGJhY2ssIHJldHJpZXMpO1xuICAgICAgICB9LCAxMDAwICogcmV0cnlfZGVsYXkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbG9nZ2VyLmxvZyhcbiAgICAgICAgICBcIk1lbUpTOiBTZXJ2ZXIgPFwiICtcbiAgICAgICAgICAgIHNlcnZlci5ob3N0cG9ydFN0cmluZygpICtcbiAgICAgICAgICAgIFwiPiBmYWlsZWQgYWZ0ZXIgKFwiICtcbiAgICAgICAgICAgIG9yaWdSZXRyaWVzICtcbiAgICAgICAgICAgIFwiKSByZXRyaWVzIHdpdGggZXJyb3IgLSBcIiArXG4gICAgICAgICAgICBlcnJvci5tZXNzYWdlXG4gICAgICAgICk7XG4gICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgIGNhbGxiYWNrKGVycm9yLCBudWxsKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH07XG5cbiAgICBzZXJ2ZXIub25SZXNwb25zZShzZXEsIHJlc3BvbnNlSGFuZGxlcik7XG4gICAgc2VydmVyLm9uRXJyb3Ioc2VxLCBlcnJvckhhbmRsZXIpO1xuICAgIHNlcnZlci53cml0ZShyZXF1ZXN0KTtcbiAgfVxuXG4gIC8vIEluY3JlbWVudCB0aGUgc2VxIHZhbHVlXG4gIGluY3JTZXEoKSB7XG4gICAgdGhpcy5zZXErKztcblxuICAgIC8vIFdyYXAgYHRoaXMuc2VxYCB0byAzMi1iaXRzIHNpbmNlIHRoZSBmaWVsZCB3ZSBmaXQgaXQgaW50byBpcyBvbmx5IDMyLWJpdHMuXG4gICAgdGhpcy5zZXEgJj0gMHhmZmZmZmZmZjtcblxuICAgIHJldHVybiB0aGlzLnNlcTtcbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlQW5kTG9nRXJyb3IoXG4gICAgY29tbWFuZE5hbWU6IHN0cmluZyxcbiAgICByZXNwb25zZVN0YXR1czogUmVzcG9uc2VTdGF0dXMgfCB1bmRlZmluZWRcbiAgKTogRXJyb3Ige1xuICAgIGNvbnN0IGVycm9yTWVzc2FnZSA9IGBNZW1KUyAke2NvbW1hbmROYW1lfTogJHtjb25zdGFudHMucmVzcG9uc2VTdGF0dXNUb1N0cmluZyhcbiAgICAgIHJlc3BvbnNlU3RhdHVzXG4gICAgKX1gO1xuICAgIHRoaXMub3B0aW9ucy5sb2dnZXIubG9nKGVycm9yTWVzc2FnZSk7XG4gICAgcmV0dXJuIG5ldyBFcnJvcihlcnJvck1lc3NhZ2UpO1xuICB9XG5cbiAgLyoqXG4gICAqIExvZyBhbiBlcnJvciB0byB0aGUgbG9nZ2VyLCB0aGVuIHJldHVybiB0aGUgZXJyb3IuXG4gICAqIElmIGEgY2FsbGJhY2sgaXMgZ2l2ZW4sIGNhbGwgaXQgd2l0aCBjYWxsYmFjayhlcnJvciwgbnVsbCkuXG4gICAqL1xuICBwcml2YXRlIGhhbmRsZVJlc3BvbnNlRXJyb3IoXG4gICAgY29tbWFuZE5hbWU6IHN0cmluZyxcbiAgICByZXNwb25zZVN0YXR1czogUmVzcG9uc2VTdGF0dXMgfCB1bmRlZmluZWQsXG4gICAgY2FsbGJhY2s6IHVuZGVmaW5lZCB8ICgoZXJyb3I6IEVycm9yIHwgbnVsbCwgb3RoZXI6IG51bGwpID0+IHZvaWQpXG4gICk6IEVycm9yIHtcbiAgICBjb25zdCBlcnJvciA9IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoY29tbWFuZE5hbWUsIHJlc3BvbnNlU3RhdHVzKTtcbiAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgIGNhbGxiYWNrKGVycm9yLCBudWxsKTtcbiAgICB9XG4gICAgcmV0dXJuIGVycm9yO1xuICB9XG59XG5cbmV4cG9ydCB7IENsaWVudCwgU2VydmVyLCBVdGlscywgSGVhZGVyIH07XG4iXX0= \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVtanMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbWVtanMvbWVtanMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLHdCQUF3Qjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUV4QixxQ0FLa0I7QUF3aUNELHVGQTFpQ2YsZUFBTSxPQTBpQ2U7QUF2aUN2Qix1REFBK0Q7QUFDL0QsbUNBU2lCO0FBQ2pCLHVEQUF5QztBQUN6QywyQ0FBNkM7QUFDN0MsK0NBQWlDO0FBMGhDUixzQkFBSztBQXpoQzlCLGlEQUFtQztBQXloQ0gsd0JBQU07QUF2aEN0QyxTQUFTLDhCQUE4QixDQUNyQyxPQUFpQixFQUNqQixHQUFXO0lBRVgsTUFBTSxLQUFLLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQztJQUM3QixNQUFNLEtBQUssR0FBRyxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxnQkFBUSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3BELE9BQU8sT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ3hCLENBQUM7QUFFRCwrQ0FBK0M7QUFDL0MsU0FBUyxTQUFTLENBQ2hCLE9BQTBFO0lBRTFFLE9BQU8sSUFBSSxPQUFPLENBQUMsVUFBVSxPQUFPLEVBQUUsTUFBTTtRQUMxQyxPQUFPLENBQUMsVUFBVSxHQUFHLEVBQUUsTUFBTTtZQUMzQixHQUFHLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3RDLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBeURELE1BQU0sTUFBTTtJQVFWLDRFQUE0RTtJQUM1RSxtQ0FBbUM7SUFDbkMsWUFBWSxPQUFpQixFQUFFLE9BQTBDO1FBQ3ZFLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO1FBQ3ZCLElB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QixFQUNuQixjQUEwQztRQUUxQyxNQUFNLFlBQVksR0FBRyxTQUFTLFdBQVcsS0FBSyxTQUFTLENBQUMsc0JBQXNCLENBQzVFLGNBQWMsQ0FDZixFQUFFLENBQUM7UUFDSixJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDdEMsT0FBTyxJQUFJLEtBQUssQ0FBQyxZQUFZLENBQUMsQ0FBQztJQUNqQyxDQUFDO0lBRUQ7OztPQUdHO0lBQ0ssbUJBQW1CLENBQ3pCLFdBQW1CLEVBQ25CLGNBQTBDLEVBQzFDLFFBQWtFO1FBRWxFLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxXQUFXLEVBQUUsY0FBYyxDQUFDLENBQUM7UUFDbEUsSUFBSSxRQUFRLEVBQUU7WUFDWixRQUFRLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxDQUFDO1NBQ3ZCO1FBQ0QsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0NBQ0Y7QUFFUSx3QkFBTSIsInNvdXJjZXNDb250ZW50IjpbIi8vIE1lbVRTIE1lbWNhY2hlIENsaWVudFxuXG5pbXBvcnQge1xuICBPbkVycm9yQ2FsbGJhY2ssXG4gIE9uUmVzcG9uc2VDYWxsYmFjayxcbiAgU2VydmVyLFxuICBTZXJ2ZXJPcHRpb25zLFxufSBmcm9tIFwiLi9zZXJ2ZXJcIjtcbmltcG9ydCB7IG5vb3BTZXJpYWxpemVyLCBTZXJpYWxpemVyIH0gZnJvbSBcIi4vbm9vcC1zZXJpYWxpemVyXCI7XG5pbXBvcnQge1xuICBtYWtlUmVxdWVzdEJ1ZmZlcixcbiAgY29weUludG9SZXF1ZXN0QnVmZmVyLFxuICBtZXJnZSxcbiAgbWFrZUV4cGlyYXRpb24sXG4gIG1ha2VBbW91bnRJbml0aWFsQW5kRXhwaXJhdGlvbixcbiAgaGFzaENvZGUsXG4gIE1heWJlQnVmZmVyLFxuICBNZXNzYWdlLFxufSBmcm9tIFwiLi91dGlsc1wiO1xuaW1wb3J0ICogYXMgY29uc3RhbnRzIGZyb20gXCIuL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgUmVzcG9uc2VTdGF0dXMgfSBmcm9tIFwiLi9jb25zdGFudHNcIjtcbmltcG9ydCAqIGFzIFV0aWxzIGZyb20gXCIuL3V0aWxzXCI7XG5pbXBvcnQgKiBhcyBIZWFkZXIgZnJvbSBcIi4vaGVhZGVyXCI7XG5cbmZ1bmN0aW9uIGRlZmF1bHRLZXlUb1NlcnZlckhhc2hGdW5jdGlvbihcbiAgc2VydmVyczogc3RyaW5nW10sXG4gIGtleTogc3RyaW5nXG4pOiBzdHJpbmcge1xuICBjb25zdCB0b3RhbCA9IHNlcnZlcnMubGVuZ3RoO1xuICBjb25zdCBpbmRleCA9IHRvdGFsID4gMSA/IGhhc2hDb2RlKGtleSkgJSB0b3RhbCA6IDA7XG4gIHJldHVybiBzZXJ2ZXJzW2luZGV4XTtcbn1cblxuLy8gY29udmVydHMgYSBjYWxsIGludG8gYSBwcm9taXNlLXJldHVybmluZyBvbmVcbmZ1bmN0aW9uIHByb21pc2lmeTxSZXN1bHQ+KFxuICBjb21tYW5kOiAoY2FsbGJhY2s6IChlcnJvcjogRXJyb3IgfCBudWxsLCByZXN1bHQ6IFJlc3VsdCkgPT4gdm9pZCkgPT4gdm9pZFxuKTogUHJvbWlzZTxSZXN1bHQ+IHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICBjb21tYW5kKGZ1bmN0aW9uIChlcnIsIHJlc3VsdCkge1xuICAgICAgZXJyID8gcmVqZWN0KGVycikgOiByZXNvbHZlKHJlc3VsdCk7XG4gICAgfSk7XG4gIH0pO1xufVxuXG50eXBlIFJlc3BvbnNlT3JFcnJvckNhbGxiYWNrID0gKFxuICBlcnJvcjogRXJyb3IgfCBudWxsLFxuICByZXNwb25zZTogTWVzc2FnZSB8IG51bGxcbikgPT4gdm9pZDtcblxuaW50ZXJmYWNlIEJhc2VDbGllbnRPcHRpb25zIHtcbiAgcmV0cmllczogbnVtYmVyO1xuICByZXRyeV9kZWxheTogbnVtYmVyO1xuICBleHBpcmVzOiBudW1iZXI7XG4gIGxvZ2dlcjogeyBsb2c6IHR5cGVvZiBjb25zb2xlLmxvZyB9O1xuICBrZXlUb1NlcnZlckhhc2hGdW5jdGlvbjogdHlwZW9mIGRlZmF1bHRLZXlUb1NlcnZlckhhc2hGdW5jdGlvbjtcbn1cblxuaW50ZXJmYWNlIFNlcmlhbGl6ZXJQcm9wPFZhbHVlLCBFeHRyYXM+IHtcbiAgc2VyaWFsaXplcjogU2VyaWFsaXplcjxWYWx1ZSwgRXh0cmFzPjtcbn1cblxuLyoqXG4gKiBUaGUgY2xpZW50IGhhcyBwYXJ0aWFsIHN1cHBvcnQgZm9yIHNlcmlhbGl6aW5nIGFuZCBkZXNlcmlhbGl6aW5nIHZhbHVlcyBmcm9tIHRoZVxuICogQnVmZmVyIGJ5dGUgc3RyaW5ncyB3ZSByZWNlaXZlIGZyb20gdGhlIHdpcmUuIFRoZSBkZWZhdWx0IHNlcmlhbGl6ZXIgaXMgZm9yIE1heWJlQnVmZmVyLlxuICpcbiAqIElmIFZhbHVlIGFuZCBFeHRyYXMgYXJlIG9mIHR5cGUgQnVmZmVyLCB0aGVuIHJldHVybiB0eXBlIFdoZW5CdWZmZXIuIE90aGVyd2lzZSxcbiAqIHJldHVybiB0eXBlIE5vdEJ1ZmZlci5cbiAqL1xudHlwZSBJZkJ1ZmZlcjxWYWx1ZSwgRXh0cmFzLCBXaGVuVmFsdWVBbmRFeHRyYXNBcmVCdWZmZXJzLCBOb3RCdWZmZXI+ID1cbiAgVmFsdWUgZXh0ZW5kcyBCdWZmZXJcbiAgICA/IEV4dHJhcyBleHRlbmRzIEJ1ZmZlclxuICAgICAgPyBXaGVuVmFsdWVBbmRFeHRyYXNBcmVCdWZmZXJzXG4gICAgICA6IE5vdEJ1ZmZlclxuICAgIDogTm90QnVmZmVyO1xuXG5leHBvcnQgdHlwZSBHaXZlbkNsaWVudE9wdGlvbnM8VmFsdWUsIEV4dHJhcz4gPSBQYXJ0aWFsPEJhc2VDbGllbnRPcHRpb25zPiAmXG4gIElmQnVmZmVyPFxuICAgIFZhbHVlLFxuICAgIEV4dHJhcyxcbiAgICBQYXJ0aWFsPFNlcmlhbGl6ZXJQcm9wPFZhbHVlLCBFeHRyYXM+PixcbiAgICBTZXJpYWxpemVyUHJvcDxWYWx1ZSwgRXh0cmFzPlxuICA+O1xuXG5leHBvcnQgdHlwZSBDQVNUb2tlbiA9IEJ1ZmZlcjtcblxuZXhwb3J0IGludGVyZmFjZSBHZXRSZXN1bHQ8VmFsdWUgPSBNYXliZUJ1ZmZlciwgRXh0cmFzID0gTWF5YmVCdWZmZXI+IHtcbiAgdmFsdWU6IFZhbHVlO1xuICBleHRyYXM6IEV4dHJhcztcbiAgY2FzOiBDQVNUb2tlbiB8IHVuZGVmaW5lZDtcbn1cblxuZXhwb3J0IHR5cGUgR2V0TXVsdGlSZXN1bHQ8XG4gIEtleXMgZXh0ZW5kcyBzdHJpbmcgPSBzdHJpbmcsXG4gIFZhbHVlID0gTWF5YmVCdWZmZXIsXG4gIEV4dHJhcyA9IE1heWJlQnVmZmVyXG4+ID0ge1xuICBbSyBpbiBLZXlzXT86IEdldFJlc3VsdDxWYWx1ZSwgRXh0cmFzPjtcbn07XG5cbmNsYXNzIENsaWVudDxWYWx1ZSA9IE1heWJlQnVmZmVyLCBFeHRyYXMgPSBNYXliZUJ1ZmZlcj4ge1xuICBzZXJ2ZXJzOiBTZXJ2ZXJbXTtcbiAgc2VxOiBudW1iZXI7XG4gIG9wdGlvbnM6IEJhc2VDbGllbnRPcHRpb25zICYgUGFydGlhbDxTZXJpYWxpemVyUHJvcDxWYWx1ZSwgRXh0cmFzPj47XG4gIHNlcmlhbGl6ZXI6IFNlcmlhbGl6ZXI8VmFsdWUsIEV4dHJhcz47XG4gIHNlcnZlck1hcDogeyBbaG9zdHBvcnQ6IHN0cmluZ106IFNlcnZlciB9O1xuICBzZXJ2ZXJLZXlzOiBzdHJpbmdbXTtcblxuICAvLyBDbGllbnQgaW5pdGlhbGl6ZXIgdGFrZXMgYSBsaXN0IG9mIGBTZXJ2ZXJgcyBhbmQgYW4gYG9wdGlvbnNgIGRpY3Rpb25hcnkuXG4gIC8vIFNlZSBgQ2xpZW50LmNyZWF0ZWAgZm9yIGRldGFpbHMuXG4gIGNvbnN0cnVjdG9yKHNlcnZlcnM6IFNlcnZlcltdLCBvcHRpb25zOiBHaXZlbkNsaWVudE9wdGlvbnM8VmFsdWUsIEV4dHJhcz4pIHtcbiAgICB0aGlzLnNlcnZlcnMgPSBzZXJ2ZXJzO1xuICAgIHRoaXMuc2VxID0gMDtcbiAgICB0aGlzLm9wdGlvbnMgPSBtZXJnZShvcHRpb25zIHx8IHt9LCB7XG4gICAgICByZXRyaWVzOiAyLFxuICAgICAgcmV0cnlfZGVsYXk6IDAuMixcbiAgICAgIGV4cGlyZXM6IDAsXG4gICAgICBsb2dnZXI6IGNvbnNvbGUsXG4gICAgICBrZXlUb1NlcnZlckhhc2hGdW5jdGlvbjogZGVmYXVsdEtleVRvU2VydmVySGFzaEZ1bmN0aW9uLFxuICAgIH0pO1xuXG4gICAgdGhpcy5zZXJpYWxpemVyID0gdGhpcy5vcHRpb25zLnNlcmlhbGl6ZXIgfHwgKG5vb3BTZXJpYWxpemVyIGFzIGFueSk7XG5cbiAgICAvLyBTdG9yZSBhIG1hcHBpbmcgZnJvbSBob3N0cG9ydCAtPiBzZXJ2ZXIgc28gd2UgY2FuIHF1aWNrbHkgZ2V0IGEgc2VydmVyIG9iamVjdCBmcm9tIHRoZSBzZXJ2ZXJLZXkgcmV0dXJuZWQgYnkgdGhlIGhhc2hpbmcgZnVuY3Rpb25cbiAgICBjb25zdCBzZXJ2ZXJNYXA6IHsgW2hvc3Rwb3J0OiBzdHJpbmddOiBTZXJ2ZXIgfSA9IHt9O1xuICAgIHRoaXMuc2VydmVycy5mb3JFYWNoKGZ1bmN0aW9uIChzZXJ2ZXIpIHtcbiAgICAgIHNlcnZlck1hcFtzZXJ2ZXIuaG9zdHBvcnRTdHJpbmcoKV0gPSBzZXJ2ZXI7XG4gICAgfSk7XG4gICAgdGhpcy5zZXJ2ZXJNYXAgPSBzZXJ2ZXJNYXA7XG5cbiAgICAvLyBzdG9yZSBhIGxpc3Qgb2YgYWxsIG91ciBzZXJ2ZXJLZXlzIHNvIHdlIGRvbid0IG5lZWQgdG8gY29uc3RhbnRseSByZWFsbG9jYXRlIHRoaXMgYXJyYXlcbiAgICB0aGlzLnNlcnZlcktleXMgPSBPYmplY3Qua2V5cyh0aGlzLnNlcnZlck1hcCk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIG5ldyBjbGllbnQgZ2l2ZW4gYW4gb3B0aW9uYWwgY29uZmlnIHN0cmluZyBhbmQgb3B0aW9uYWwgaGFzaCBvZlxuICAgKiBvcHRpb25zLiBUaGUgY29uZmlnIHN0cmluZyBzaG91bGQgYmUgb2YgdGhlIGZvcm06XG4gICAqXG4gICAqICAgICBcIlt1c2VyOnBhc3NAXXNlcnZlcjFbOjExMjExXSxbdXNlcjpwYXNzQF1zZXJ2ZXIyWzoxMTIxMV0sLi4uXCJcbiAgICpcbiAgICogSWYgdGhlIGFyZ3VtZW50IGlzIG5vdCBnaXZlbiwgZmFsbGJhY2sgb24gdGhlIGBNRU1DQUNISUVSX1NFUlZFUlNgIGVudmlyb25tZW50XG4gICAqIHZhcmlhYmxlLCBgTUVNQ0FDSEVfU0VSVkVSU2AgZW52aXJvbm1lbnQgdmFyaWFibGUgb3IgYFwibG9jYWxob3N0OjExMjExXCJgLlxuICAgKlxuICAgKiBUaGUgb3B0aW9ucyBoYXNoIG1heSBjb250YWluIHRoZSBvcHRpb25zOlxuICAgKlxuICAgKiAqIGByZXRyaWVzYCAtIHRoZSBudW1iZXIgb2YgdGltZXMgdG8gcmV0cnkgYW4gb3BlcmF0aW9uIGluIGxpZXUgb2YgZmFpbHVyZXNcbiAgICogKGRlZmF1bHQgMilcbiAgICogKiBgZXhwaXJlc2AgLSB0aGUgZGVmYXVsdCBleHBpcmF0aW9uIGluIHNlY29uZHMgdG8gdXNlIChkZWZhdWx0IDAgLSBuZXZlclxuICAgKiBleHBpcmUpLiBJZiBgZXhwaXJlc2AgaXMgZ3JlYXRlciB0aGFuIDMwIGRheXMgKDYwIHggNjAgeCAyNCB4IDMwKSwgaXQgaXNcbiAgICogdHJlYXRlZCBhcyBhIFVOSVggdGltZSAobnVtYmVyIG9mIHNlY29uZHMgc2luY2UgSmFudWFyeSAxLCAxOTcwKS5cbiAgICogKiBgbG9nZ2VyYCAtIGEgbG9nZ2VyIG9iamVjdCB0aGF0IHJlc3BvbmRzIHRvIGBsb2coc3RyaW5nKWAgbWV0aG9kIGNhbGxzLlxuICAgKlxuICAgKiAgIH5+fn5cbiAgICogICAgIGxvZyhtc2cxWywgbXNnMlssIG1zZzNbLi4uXV1dKVxuICAgKiAgIH5+fn5cbiAgICpcbiAgICogICBEZWZhdWx0cyB0byBgY29uc29sZWAuXG4gICAqICogYHNlcmlhbGl6ZXJgIC0gdGhlIG9iamVjdCB3aGljaCB3aWxsIChkZSlzZXJpYWxpemUgdGhlIGRhdGEuIEl0IG5lZWRzXG4gICAqICAgdHdvIHB1YmxpYyBtZXRob2RzOiBzZXJpYWxpemUgYW5kIGRlc2VyaWFsaXplLiBJdCBkZWZhdWx0cyB0byB0aGVcbiAgICogICBub29wU2VyaWFsaXplcjpcbiAgICpcbiAgICogICB+fn5+XG4gICAqICAgY29uc3Qgbm9vcFNlcmlhbGl6ZXIgPSB7XG4gICAqICAgICBzZXJpYWxpemU6IGZ1bmN0aW9uIChvcGNvZGUsIHZhbHVlLCBleHRyYXMpIHtcbiAgICogICAgICAgcmV0dXJuIHsgdmFsdWU6IHZhbHVlLCBleHRyYXM6IGV4dHJhcyB9O1xuICAgKiAgICAgfSxcbiAgICogICAgIGRlc2VyaWFsaXplOiBmdW5jdGlvbiAob3Bjb2RlLCB2YWx1ZSwgZXh0cmFzKSB7XG4gICAqICAgICAgIHJldHVybiB7IHZhbHVlOiB2YWx1ZSwgZXh0cmFzOiBleHRyYXMgfTtcbiAgICogICAgIH1cbiAgICogICB9O1xuICAgKiAgIH5+fn5cbiAgICpcbiAgICogT3Igb3B0aW9ucyBmb3IgdGhlIHNlcnZlcnMgaW5jbHVkaW5nOlxuICAgKiAqIGB1c2VybmFtZWAgYW5kIGBwYXNzd29yZGAgZm9yIGZhbGxiYWNrIFNBU0wgYXV0aGVudGljYXRpb24gY3JlZGVudGlhbHMuXG4gICAqICogYHRpbWVvdXRgIGluIHNlY29uZHMgdG8gZGV0ZXJtaW5lIGZhaWx1cmUgZm9yIG9wZXJhdGlvbnMuIERlZmF1bHQgaXMgMC41XG4gICAqICAgICAgICAgICAgIHNlY29uZHMuXG4gICAqICogJ2Nvbm50aW1lb3V0JyBpbiBzZWNvbmRzIHRvIGNvbm5lY3Rpb24gZmFpbHVyZS4gRGVmYXVsdCBpcyB0d2ljZSB0aGUgdmFsdWVcbiAgICogICAgICAgICAgICAgICAgIG9mIGB0aW1lb3V0YC5cbiAgICogKiBga2VlcEFsaXZlYCB3aGV0aGVyIHRvIGVuYWJsZSBrZWVwLWFsaXZlIGZ1bmN0aW9uYWxpdHkuIERlZmF1bHRzIHRvIGZhbHNlLlxuICAgKiAqIGBrZWVwQWxpdmVEZWxheWAgaW4gc2Vjb25kcyB0byB0aGUgaW5pdGlhbCBkZWxheSBiZWZvcmUgdGhlIGZpcnN0IGtlZXBhbGl2ZVxuICAgKiAgICAgICAgICAgICAgICAgICAgcHJvYmUgaXMgc2VudCBvbiBhbiBpZGxlIHNvY2tldC4gRGVmYXVsdHMgaXMgMzAgc2Vjb25kcy5cbiAgICogKiBga2V5VG9TZXJ2ZXJIYXNoRnVuY3Rpb25gIGEgZnVuY3Rpb24gdG8gbWFwIGtleXMgdG8gc2VydmVycywgd2l0aCB0aGUgc2lnbmF0dXJlXG4gICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgIChzZXJ2ZXJLZXlzOiBzdHJpbmdbXSwga2V5OiBzdHJpbmcpOiBzdHJpbmdcbiAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgTk9URTogaWYgeW91IG5lZWQgdG8gZG8gc29tZSBleHBlbnNpdmUgaW5pdGlhbGl6YXRpb24sICpwbGVhc2UqIGRvIGl0IGxhemlseSB0aGUgZmlyc3QgdGltZSB5b3UgdGhpcyBmdW5jdGlvbiBpcyBjYWxsZWQgd2l0aCBhbiBhcnJheSBvZiBzZXJ2ZXJLZXlzLCBub3Qgb24gZXZlcnkgY2FsbFxuICAgKi9cbiAgc3RhdGljIGNyZWF0ZTxWYWx1ZSwgRXh0cmFzPihcbiAgICBzZXJ2ZXJzU3RyOiBzdHJpbmcgfCB1bmRlZmluZWQsXG4gICAgb3B0aW9uczogSWZCdWZmZXI8XG4gICAgICBWYWx1ZSxcbiAgICAgIEV4dHJhcyxcbiAgICAgIHVuZGVmaW5lZCB8IChQYXJ0aWFsPFNlcnZlck9wdGlvbnM+ICYgR2l2ZW5DbGllbnRPcHRpb25zPFZhbHVlLCBFeHRyYXM+KSxcbiAgICAgIFBhcnRpYWw8U2VydmVyT3B0aW9ucz4gJiBHaXZlbkNsaWVudE9wdGlvbnM8VmFsdWUsIEV4dHJhcz5cbiAgICA+XG4gICk6IENsaWVudDxWYWx1ZSwgRXh0cmFzPiB7XG4gICAgc2VydmVyc1N0ciA9XG4gICAgICBzZXJ2ZXJzU3RyIHx8XG4gICAgICBwcm9jZXNzLmVudi5NRU1DQUNISUVSX1NFUlZFUlMgfHxcbiAgICAgIHByb2Nlc3MuZW52Lk1FTUNBQ0hFX1NFUlZFUlMgfHxcbiAgICAgIFwibG9jYWxob3N0OjExMjExXCI7XG4gICAgY29uc3Qgc2VydmVyVXJpcyA9IHNlcnZlcnNTdHIuc3BsaXQoXCIsXCIpO1xuICAgIGNvbnN0IHNlcnZlcnMgPSBzZXJ2ZXJVcmlzLm1hcChmdW5jdGlvbiAodXJpKSB7XG4gICAgICBjb25zdCB1cmlQYXJ0cyA9IHVyaS5zcGxpdChcIkBcIik7XG4gICAgICBjb25zdCBob3N0UG9ydCA9IHVyaVBhcnRzW3VyaVBhcnRzLmxlbmd0aCAtIDFdLnNwbGl0KFwiOlwiKTtcbiAgICAgIGNvbnN0IHVzZXJQYXNzID0gKHVyaVBhcnRzW3VyaVBhcnRzLmxlbmd0aCAtIDJdIHx8IFwiXCIpLnNwbGl0KFwiOlwiKTtcbiAgICAgIHJldHVybiBuZXcgU2VydmVyKFxuICAgICAgICBob3N0UG9ydFswXSxcbiAgICAgICAgcGFyc2VJbnQoaG9zdFBvcnRbMV0gfHwgXCIxMTIxMVwiLCAxMCksXG4gICAgICAgIHVzZXJQYXNzWzBdLFxuICAgICAgICB1c2VyUGFzc1sxXSxcbiAgICAgICAgb3B0aW9uc1xuICAgICAgKTtcbiAgICB9KTtcbiAgICByZXR1cm4gbmV3IENsaWVudChzZXJ2ZXJzLCBvcHRpb25zIGFzIGFueSk7XG4gIH1cblxuICAvKipcbiAgICogR2l2ZW4gYSBzZXJ2ZXJLZXkgZnJvbWxvb2t1cEtleVRvU2VydmVyS2V5LCByZXR1cm4gdGhlIGNvcnJlc3BvbmRpbmcgU2VydmVyIGluc3RhbmNlXG4gICAqXG4gICAqIEBwYXJhbSAge3N0cmluZ30gc2VydmVyS2V5XG4gICAqIEByZXR1cm5zIHtTZXJ2ZXJ9XG4gICAqL1xuICBzZXJ2ZXJLZXlUb1NlcnZlcihzZXJ2ZXJLZXk6IHN0cmluZyk6IFNlcnZlciB7XG4gICAgcmV0dXJuIHRoaXMuc2VydmVyTWFwW3NlcnZlcktleV07XG4gIH1cblxuICAvKipcbiAgICogR2l2ZW4gYSBrZXkgdG8gbG9vayB1cCBpbiBtZW1jYWNoZSwgcmV0dXJuIGEgc2VydmVyS2V5IChiYXNlZCBvbiBzb21lXG4gICAqIGhhc2hpbmcgZnVuY3Rpb24pIHdoaWNoIGNhbiBiZSB1c2VkIHRvIGluZGV4IHRoaXMuc2VydmVyTWFwXG4gICAqL1xuICBsb29rdXBLZXlUb1NlcnZlcktleShrZXk6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMub3B0aW9ucy5rZXlUb1NlcnZlckhhc2hGdW5jdGlvbih0aGlzLnNlcnZlcktleXMsIGtleSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldmVzIHRoZSB2YWx1ZSBhdCB0aGUgZ2l2ZW4ga2V5IGluIG1lbWNhY2hlLlxuICAgKi9cbiAgYXN5bmMgZ2V0KGtleTogc3RyaW5nKTogUHJvbWlzZTxHZXRSZXN1bHQ8VmFsdWUsIEV4dHJhcz4gfCBudWxsPiB7XG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKGNvbnN0YW50cy5PUF9HRVQsIGtleSwgXCJcIiwgXCJcIiwgdGhpcy5zZXEpO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICBjb25zdCBkZXNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuZGVzZXJpYWxpemUoXG4gICAgICAgICAgcmVzcG9uc2UuaGVhZGVyLm9wY29kZSxcbiAgICAgICAgICByZXNwb25zZS52YWwsXG4gICAgICAgICAgcmVzcG9uc2UuZXh0cmFzXG4gICAgICAgICk7XG4gICAgICAgIHJldHVybiB7IC4uLmRlc2VyaWFsaXplZCwgY2FzOiByZXNwb25zZS5oZWFkZXIuY2FzIH07XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIkdFVFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKiogQnVpbGQgYSBwaXBlbGluZWQgZ2V0IG11bHRpIHJlcXVlc3QgYnkgc2VuZGluZyBvbmUgR0VUS1EgZm9yIGVhY2gga2V5IChxdWlldCwgbWVhbmluZyBpdCB3b24ndCByZXNwb25kIGlmIHRoZSB2YWx1ZSBpcyBtaXNzaW5nKSBmb2xsb3dlZCBieSBhIG5vLW9wIHRvIGZvcmNlIGEgcmVzcG9uc2UgKGFuZCB0byBnaXZlIHVzIGEgc2VudGluZWwgcmVzcG9uc2UgdGhhdCB0aGUgcGlwZWxpbmUgaXMgZG9uZSlcbiAgICpcbiAgICogY2YgaHR0cHM6Ly9naXRodWIuY29tL2NvdWNoYmFzZS9tZW1jYWNoZWQvYmxvYi9tYXN0ZXIvZG9jcy9CaW5hcnlQcm90b2NvbC5tZCMweDBkLWdldGtxLWdldC13aXRoLWtleS1xdWlldGx5XG4gICAqL1xuICBfYnVpbGRHZXRNdWx0aVJlcXVlc3Qoa2V5czogc3RyaW5nW10sIHNlcTogbnVtYmVyKTogQnVmZmVyIHtcbiAgICAvLyBzdGFydCBhdCAyNCBmb3IgdGhlIG5vLW9wIGNvbW1hbmQgYXQgdGhlIGVuZFxuICAgIGxldCByZXF1ZXN0U2l6ZSA9IDI0O1xuICAgIGZvciAoY29uc3Qga2V5SWR4IGluIGtleXMpIHtcbiAgICAgIHJlcXVlc3RTaXplICs9IEJ1ZmZlci5ieXRlTGVuZ3RoKGtleXNba2V5SWR4XSwgXCJ1dGY4XCIpICsgMjQ7XG4gICAgfVxuXG4gICAgY29uc3QgcmVxdWVzdCA9IEJ1ZmZlci5hbGxvYyhyZXF1ZXN0U2l6ZSk7XG5cbiAgICBsZXQgYnl0ZXNXcml0dGVuID0gMDtcbiAgICBmb3IgKGNvbnN0IGtleUlkeCBpbiBrZXlzKSB7XG4gICAgICBjb25zdCBrZXkgPSBrZXlzW2tleUlkeF07XG4gICAgICBieXRlc1dyaXR0ZW4gKz0gY29weUludG9SZXF1ZXN0QnVmZmVyKFxuICAgICAgICBjb25zdGFudHMuT1BfR0VUS1EsXG4gICAgICAgIGtleSxcbiAgICAgICAgXCJcIixcbiAgICAgICAgXCJcIixcbiAgICAgICAgc2VxLFxuICAgICAgICByZXF1ZXN0LFxuICAgICAgICBieXRlc1dyaXR0ZW5cbiAgICAgICk7XG4gICAgfVxuXG4gICAgYnl0ZXNXcml0dGVuICs9IGNvcHlJbnRvUmVxdWVzdEJ1ZmZlcihcbiAgICAgIGNvbnN0YW50cy5PUF9OT19PUCxcbiAgICAgIFwiXCIsXG4gICAgICBcIlwiLFxuICAgICAgXCJcIixcbiAgICAgIHNlcSxcbiAgICAgIHJlcXVlc3QsXG4gICAgICBieXRlc1dyaXR0ZW5cbiAgICApO1xuXG4gICAgcmV0dXJuIHJlcXVlc3Q7XG4gIH1cblxuICAvKiogRXhlY3V0aW5nIGEgcGlwZWxpbmVkIChtdWx0aSkgZ2V0IGFnYWluc3QgYSBzaW5nbGUgc2VydmVyLiBUaGlzIGlzIGEgcHJpdmF0ZSBpbXBsZW1lbnRhdGlvbiBkZXRhaWwgb2YgZ2V0TXVsdGkuICovXG4gIGFzeW5jIF9nZXRNdWx0aVRvU2VydmVyPEtleXMgZXh0ZW5kcyBzdHJpbmc+KFxuICAgIHNlcnY6IFNlcnZlcixcbiAgICBrZXlzOiBLZXlzW11cbiAgKTogUHJvbWlzZTxHZXRNdWx0aVJlc3VsdDxLZXlzLCBWYWx1ZSwgRXh0cmFzPj4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBjb25zdCByZXNwb25zZU1hcDogR2V0TXVsdGlSZXN1bHQ8c3RyaW5nLCBWYWx1ZSwgRXh0cmFzPiA9IHt9O1xuXG4gICAgICBjb25zdCBoYW5kbGU6IE9uUmVzcG9uc2VDYWxsYmFjayA9IChyZXNwb25zZSkgPT4ge1xuICAgICAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgICAgICAvLyBXaGVuIHdlIGdldCB0aGUgbm8tb3AgcmVzcG9uc2UsIHdlIGFyZSBkb25lIHdpdGggdGhpcyBvbmUgZ2V0TXVsdGkgaW4gdGhlIHBlci1iYWNrZW5kIGZhbi1vdXRcbiAgICAgICAgICAgIGlmIChyZXNwb25zZS5oZWFkZXIub3Bjb2RlID09PSBjb25zdGFudHMuT1BfTk9fT1ApIHtcbiAgICAgICAgICAgICAgLy8gVGhpcyBlbnN1cmVzIHRoZSBoYW5kbGVyIHdpbGwgYmUgZGVsZXRlZCBmcm9tIHRoZSByZXNwb25zZUNhbGxiYWNrcyBtYXAgaW4gc2VydmVyLmpzXG4gICAgICAgICAgICAgIC8vIFRoaXMgaXNuJ3QgdGVjaG5pY2FsbHkgbmVlZGVkIGhlcmUgYmVjYXVzZSB0aGUgbG9naWMgaW4gc2VydmVyLmpzIGFsc28gY2hlY2tzIGlmIHRvdGFsQm9keUxlbmd0aCA9PT0gMCwgYnV0IG91ciB1bml0dGVzdHMgYXJlbid0IGdyZWF0IGFib3V0IHNldHRpbmcgdGhhdCBmaWVsZCwgYW5kIGFsc28gdGhpcyBtYWtlcyBpdCBtb3JlIGV4cGxpY2l0XG4gICAgICAgICAgICAgIGhhbmRsZS5xdWlldCA9IGZhbHNlO1xuICAgICAgICAgICAgICByZXNvbHZlKHJlc3BvbnNlTWFwKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgICAgICAgIHJlc3BvbnNlLmhlYWRlci5vcGNvZGUgPT09IGNvbnN0YW50cy5PUF9HRVRLIHx8XG4gICAgICAgICAgICAgIHJlc3BvbnNlLmhlYWRlci5vcGNvZGUgPT09IGNvbnN0YW50cy5PUF9HRVRLUVxuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgIGNvbnN0IGRlc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5kZXNlcmlhbGl6ZShcbiAgICAgICAgICAgICAgICByZXNwb25zZS5oZWFkZXIub3Bjb2RlLFxuICAgICAgICAgICAgICAgIHJlc3BvbnNlLnZhbCxcbiAgICAgICAgICAgICAgICByZXNwb25zZS5leHRyYXNcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgY29uc3Qga2V5ID0gcmVzcG9uc2Uua2V5LnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgIGlmIChrZXkubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlamVjdChcbiAgICAgICAgICAgICAgICAgIG5ldyBFcnJvcihcbiAgICAgICAgICAgICAgICAgICAgXCJSZWNpZXZlZCBlbXB0eSBrZXkgaW4gZ2V0TXVsdGk6IFwiICtcbiAgICAgICAgICAgICAgICAgICAgICBKU09OLnN0cmluZ2lmeShyZXNwb25zZSlcbiAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIHJlc3BvbnNlTWFwW2tleV0gPSB7IC4uLmRlc2VyaWFsaXplZCwgY2FzOiByZXNwb25zZS5oZWFkZXIuY2FzIH07XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICByZXR1cm4gcmVqZWN0KFxuICAgICAgICAgICAgICAgIG5ldyBFcnJvcihcbiAgICAgICAgICAgICAgICAgIFwiUmVjaWV2ZWQgcmVzcG9uc2UgaW4gZ2V0TXVsdGkgZm9yIHVua25vd24gb3Bjb2RlOiBcIiArXG4gICAgICAgICAgICAgICAgICAgIEpTT04uc3RyaW5naWZ5KHJlc3BvbnNlKVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICByZXR1cm4gcmVqZWN0KFxuICAgICAgICAgICAgICB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiR0VUXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9O1xuICAgICAgLy8gVGhpcyBwcmV2ZW50cyB0aGUgaGFuZGxlciBmcm9tIGJlaW5nIGRlbGV0ZWRcbiAgICAgIC8vIGFmdGVyIHRoZSBmaXJzdCByZXNwb25zZS4gTG9naWMgaW4gc2VydmVyLmpzLlxuICAgICAgaGFuZGxlLnF1aWV0ID0gdHJ1ZTtcblxuICAgICAgY29uc3Qgc2VxID0gdGhpcy5pbmNyU2VxKCk7XG4gICAgICBjb25zdCByZXF1ZXN0ID0gdGhpcy5fYnVpbGRHZXRNdWx0aVJlcXVlc3Qoa2V5cywgc2VxKTtcbiAgICAgIHNlcnYub25SZXNwb25zZSh0aGlzLnNlcSwgaGFuZGxlKTtcbiAgICAgIHNlcnYub25FcnJvcih0aGlzLnNlcSwgcmVqZWN0KTtcbiAgICAgIHNlcnYud3JpdGUocmVxdWVzdCk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldnMgdGhlIHZhbHVlIGF0IHRoZSBnaXZlbiBrZXlzIGluIG1lbWNhY2hlZC4gUmV0dXJucyBhIG1hcCBmcm9tIHRoZVxuICAgKiByZXF1ZXN0ZWQga2V5cyB0byByZXN1bHRzLCBvciBudWxsIGlmIHRoZSBrZXkgd2FzIG5vdCBmb3VuZC5cbiAgICovXG4gIGFzeW5jIGdldE11bHRpPEtleXMgZXh0ZW5kcyBzdHJpbmc+KFxuICAgIGtleXM6IEtleXNbXVxuICApOiBQcm9taXNlPEdldE11bHRpUmVzdWx0PEtleXMsIFZhbHVlLCBFeHRyYXM+PiB7XG4gICAgY29uc3Qgc2VydmVyS2V5dG9Mb29rdXBLZXlzOiB7XG4gICAgICBbc2VydmVyS2V5OiBzdHJpbmddOiBzdHJpbmdbXTtcbiAgICB9ID0ge307XG4gICAga2V5cy5mb3JFYWNoKChsb29rdXBLZXkpID0+IHtcbiAgICAgIGNvbnN0IHNlcnZlcktleSA9IHRoaXMubG9va3VwS2V5VG9TZXJ2ZXJLZXkobG9va3VwS2V5KTtcbiAgICAgIGlmICghc2VydmVyS2V5dG9Mb29rdXBLZXlzW3NlcnZlcktleV0pIHtcbiAgICAgICAgc2VydmVyS2V5dG9Mb29rdXBLZXlzW3NlcnZlcktleV0gPSBbXTtcbiAgICAgIH1cbiAgICAgIHNlcnZlcktleXRvTG9va3VwS2V5c1tzZXJ2ZXJLZXldLnB1c2gobG9va3VwS2V5KTtcbiAgICB9KTtcblxuICAgIGNvbnN0IHVzZWRTZXJ2ZXJLZXlzID0gT2JqZWN0LmtleXMoc2VydmVyS2V5dG9Mb29rdXBLZXlzKTtcbiAgICBjb25zdCByZXN1bHRzID0gYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICB1c2VkU2VydmVyS2V5cy5tYXAoKHNlcnZlcktleSkgPT4ge1xuICAgICAgICBjb25zdCBzZXJ2ZXIgPSB0aGlzLnNlcnZlcktleVRvU2VydmVyKHNlcnZlcktleSk7XG4gICAgICAgIHJldHVybiB0aGlzLl9nZXRNdWx0aVRvU2VydmVyKHNlcnZlciwgc2VydmVyS2V5dG9Mb29rdXBLZXlzW3NlcnZlcktleV0pO1xuICAgICAgfSlcbiAgICApO1xuXG4gICAgcmV0dXJuIE9iamVjdC5hc3NpZ24oe30sIC4uLnJlc3VsdHMpO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgYGtleWAgdG8gYHZhbHVlYC5cbiAgICovXG4gIGFzeW5jIHNldChcbiAgICBrZXk6IHN0cmluZyxcbiAgICB2YWx1ZTogVmFsdWUsXG4gICAgb3B0aW9ucz86IHsgZXhwaXJlcz86IG51bWJlcjsgY2FzPzogQ0FTVG9rZW4gfVxuICApOiBQcm9taXNlPGJvb2xlYW4gfCBudWxsPiB7XG4gICAgY29uc3QgZXhwaXJlcyA9IG9wdGlvbnM/LmV4cGlyZXM7XG4gICAgY29uc3QgY2FzID0gb3B0aW9ucz8uY2FzO1xuXG4gICAgLy8gVE9ETzogc3VwcG9ydCBmbGFnc1xuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IGV4cGlyYXRpb24gPSBtYWtlRXhwaXJhdGlvbihleHBpcmVzIHx8IHRoaXMub3B0aW9ucy5leHBpcmVzKTtcbiAgICBjb25zdCBleHRyYXMgPSBCdWZmZXIuY29uY2F0KFtCdWZmZXIuZnJvbShcIjAwMDAwMDAwXCIsIFwiaGV4XCIpLCBleHBpcmF0aW9uXSk7XG4gICAgY29uc3Qgc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5zZXJpYWxpemUoXG4gICAgICBjb25zdGFudHMuT1BfU0VULFxuICAgICAgdmFsdWUsXG4gICAgICBleHRyYXNcbiAgICApO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBVdGlscy5lbmNvZGVSZXF1ZXN0KHtcbiAgICAgIGhlYWRlcjoge1xuICAgICAgICBvcGNvZGU6IGNvbnN0YW50cy5PUF9TRVQsXG4gICAgICAgIG9wYXF1ZTogdGhpcy5zZXEsXG4gICAgICAgIGNhcyxcbiAgICAgIH0sXG4gICAgICBrZXksXG4gICAgICB2YWx1ZTogc2VyaWFsaXplZC52YWx1ZSxcbiAgICAgIGV4dHJhczogc2VyaWFsaXplZC5leHRyYXMsXG4gICAgfSk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfRVhJU1RTOlxuICAgICAgICBpZiAoY2FzKSB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJTRVRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgICAgIH1cbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJTRVRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEFERFxuICAgKlxuICAgKiBBZGRzIHRoZSBnaXZlbiBfa2V5XyBhbmQgX3ZhbHVlXyB0byBtZW1jYWNoZS4gVGhlIG9wZXJhdGlvbiBvbmx5IHN1Y2NlZWRzXG4gICAqIGlmIHRoZSBrZXkgaXMgbm90IGFscmVhZHkgc2V0LlxuICAgKlxuICAgKiBUaGUgb3B0aW9ucyBkaWN0aW9uYXJ5IHRha2VzOlxuICAgKiAqIF9leHBpcmVzXzogb3ZlcnJpZGVzIHRoZSBkZWZhdWx0IGV4cGlyYXRpb24gKHNlZSBgQ2xpZW50LmNyZWF0ZWApIGZvciB0aGlzXG4gICAqICAgICAgICAgICAgICBwYXJ0aWN1bGFyIGtleS12YWx1ZSBwYWlyLlxuICAgKi9cbiAgYXN5bmMgYWRkKFxuICAgIGtleTogc3RyaW5nLFxuICAgIHZhbHVlOiBWYWx1ZSxcbiAgICBvcHRpb25zPzogeyBleHBpcmVzPzogbnVtYmVyIH1cbiAgKTogUHJvbWlzZTxib29sZWFuIHwgbnVsbD4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgZmxhZ3MsIHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IGV4cGlyYXRpb24gPSBtYWtlRXhwaXJhdGlvbihvcHRpb25zPy5leHBpcmVzIHx8IHRoaXMub3B0aW9ucy5leHBpcmVzKTtcbiAgICBjb25zdCBleHRyYXMgPSBCdWZmZXIuY29uY2F0KFtCdWZmZXIuZnJvbShcIjAwMDAwMDAwXCIsIFwiaGV4XCIpLCBleHBpcmF0aW9uXSk7XG5cbiAgICBjb25zdCBvcGNvZGUgPSBjb25zdGFudHMuT1BfQUREO1xuICAgIGNvbnN0IHNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuc2VyaWFsaXplKG9wY29kZSwgdmFsdWUsIGV4dHJhcyk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKFxuICAgICAgb3Bjb2RlLFxuICAgICAga2V5LFxuICAgICAgc2VyaWFsaXplZC5leHRyYXMsXG4gICAgICBzZXJpYWxpemVkLnZhbHVlLFxuICAgICAgdGhpcy5zZXFcbiAgICApO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuS0VZX0VYSVNUUzpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJBRERcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlcGxhY2VzIHRoZSBnaXZlbiBfa2V5XyBhbmQgX3ZhbHVlXyB0byBtZW1jYWNoZS4gVGhlIG9wZXJhdGlvbiBvbmx5IHN1Y2NlZWRzXG4gICAqIGlmIHRoZSBrZXkgaXMgYWxyZWFkeSBwcmVzZW50LlxuICAgKi9cbiAgYXN5bmMgcmVwbGFjZShcbiAgICBrZXk6IHN0cmluZyxcbiAgICB2YWx1ZTogVmFsdWUsXG4gICAgb3B0aW9ucz86IHsgZXhwaXJlcz86IG51bWJlciB9XG4gICk6IFByb21pc2U8Ym9vbGVhbiB8IG51bGw+IHtcbiAgICAvLyBUT0RPOiBzdXBwb3J0IGZsYWdzLCBzdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBleHBpcmF0aW9uID0gbWFrZUV4cGlyYXRpb24ob3B0aW9ucz8uZXhwaXJlcyB8fCB0aGlzLm9wdGlvbnMuZXhwaXJlcyk7XG4gICAgY29uc3QgZXh0cmFzID0gQnVmZmVyLmNvbmNhdChbQnVmZmVyLmZyb20oXCIwMDAwMDAwMFwiLCBcImhleFwiKSwgZXhwaXJhdGlvbl0pO1xuXG4gICAgY29uc3Qgb3Bjb2RlOiBjb25zdGFudHMuT1AgPSBjb25zdGFudHMuT1BfUkVQTEFDRTtcbiAgICBjb25zdCBzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLnNlcmlhbGl6ZShvcGNvZGUsIHZhbHVlLCBleHRyYXMpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgIG9wY29kZSxcbiAgICAgIGtleSxcbiAgICAgIHNlcmlhbGl6ZWQuZXh0cmFzLFxuICAgICAgc2VyaWFsaXplZC52YWx1ZSxcbiAgICAgIHRoaXMuc2VxXG4gICAgKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJSRVBMQUNFXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBEZWxldGVzIHRoZSBnaXZlbiBfa2V5XyBmcm9tIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHNcbiAgICogaWYgdGhlIGtleSBpcyBhbHJlYWR5IHByZXNlbnQuXG4gICAqL1xuICBhc3luYyBkZWxldGUoa2V5OiBzdHJpbmcpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAvLyBUT0RPOiBTdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoNCwga2V5LCBcIlwiLCBcIlwiLCB0aGlzLnNlcSk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG5cbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJERUxFVEVcIiwgcmVzcG9uc2U/LmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBJbmNyZW1lbnRzIHRoZSBnaXZlbiBfa2V5XyBpbiBtZW1jYWNoZS5cbiAgICovXG4gIGFzeW5jIGluY3JlbWVudChcbiAgICBrZXk6IHN0cmluZyxcbiAgICBhbW91bnQ6IG51bWJlcixcbiAgICBvcHRpb25zPzogeyBpbml0aWFsPzogbnVtYmVyOyBleHBpcmVzPzogbnVtYmVyIH1cbiAgKTogUHJvbWlzZTx7IHZhbHVlOiBudW1iZXIgfCBudWxsOyBzdWNjZXNzOiBib29sZWFuIHwgbnVsbCB9PiB7XG4gICAgLy8gVE9ETzogc3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgaW5pdGlhbCA9IG9wdGlvbnM/LmluaXRpYWwgfHwgMDtcbiAgICBjb25zdCBleHBpcmVzID0gb3B0aW9ucz8uZXhwaXJlcyB8fCB0aGlzLm9wdGlvbnMuZXhwaXJlcztcbiAgICBjb25zdCBleHRyYXMgPSBtYWtlQW1vdW50SW5pdGlhbEFuZEV4cGlyYXRpb24oYW1vdW50LCBpbml0aWFsLCBleHBpcmVzKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICBjb25zdGFudHMuT1BfSU5DUkVNRU5ULFxuICAgICAga2V5LFxuICAgICAgZXh0cmFzLFxuICAgICAgXCJcIixcbiAgICAgIHRoaXMuc2VxXG4gICAgKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgY29uc3QgYnVmSW50ID1cbiAgICAgICAgICAocmVzcG9uc2UudmFsLnJlYWRVSW50MzJCRSgwKSA8PCA4KSArIHJlc3BvbnNlLnZhbC5yZWFkVUludDMyQkUoNCk7XG4gICAgICAgIHJldHVybiB7IHZhbHVlOiBidWZJbnQsIHN1Y2Nlc3M6IHRydWUgfTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJJTkNSRU1FTlRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIERlY3JlbWVudHMgdGhlIGdpdmVuIGBrZXlgIGluIG1lbWNhY2hlLlxuICAgKi9cbiAgYXN5bmMgZGVjcmVtZW50KFxuICAgIGtleTogc3RyaW5nLFxuICAgIGFtb3VudDogbnVtYmVyLFxuICAgIG9wdGlvbnM6IHsgaW5pdGlhbD86IG51bWJlcjsgZXhwaXJlcz86IG51bWJlciB9XG4gICk6IFByb21pc2U8eyB2YWx1ZTogbnVtYmVyIHwgbnVsbDsgc3VjY2VzczogYm9vbGVhbiB8IG51bGwgfT4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IGluaXRpYWwgPSBvcHRpb25zLmluaXRpYWwgfHwgMDtcbiAgICBjb25zdCBleHBpcmVzID0gb3B0aW9ucy5leHBpcmVzIHx8IHRoaXMub3B0aW9ucy5leHBpcmVzO1xuICAgIGNvbnN0IGV4dHJhcyA9IG1ha2VBbW91bnRJbml0aWFsQW5kRXhwaXJhdGlvbihhbW91bnQsIGluaXRpYWwsIGV4cGlyZXMpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgIGNvbnN0YW50cy5PUF9ERUNSRU1FTlQsXG4gICAgICBrZXksXG4gICAgICBleHRyYXMsXG4gICAgICBcIlwiLFxuICAgICAgdGhpcy5zZXFcbiAgICApO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICBjb25zdCBidWZJbnQgPVxuICAgICAgICAgIChyZXNwb25zZS52YWwucmVhZFVJbnQzMkJFKDApIDw8IDgpICsgcmVzcG9uc2UudmFsLnJlYWRVSW50MzJCRSg0KTtcbiAgICAgICAgcmV0dXJuIHsgdmFsdWU6IGJ1ZkludCwgc3VjY2VzczogdHJ1ZSB9O1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIkRFQ1JFTUVOVFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQXBwZW5kIHRoZSBnaXZlbiBfdmFsdWVfIHRvIHRoZSB2YWx1ZSBhc3NvY2lhdGVkIHdpdGggdGhlIGdpdmVuIF9rZXlfIGluXG4gICAqIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHMgaWYgdGhlIGtleSBpcyBhbHJlYWR5IHByZXNlbnQuXG4gICAqL1xuICBhc3luYyBhcHBlbmQoa2V5OiBzdHJpbmcsIHZhbHVlOiBWYWx1ZSk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IG9wY29kZTogY29uc3RhbnRzLk9QID0gY29uc3RhbnRzLk9QX0FQUEVORDtcbiAgICBjb25zdCBzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLnNlcmlhbGl6ZShvcGNvZGUsIHZhbHVlLCBcIlwiKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICBvcGNvZGUsXG4gICAgICBrZXksXG4gICAgICBzZXJpYWxpemVkLmV4dHJhcyxcbiAgICAgIHNlcmlhbGl6ZWQudmFsdWUsXG4gICAgICB0aGlzLnNlcVxuICAgICk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfTk9UX0ZPVU5EOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiQVBQRU5EXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBQcmVwZW5kIHRoZSBnaXZlbiBfdmFsdWVfIHRvIHRoZSB2YWx1ZSBhc3NvY2lhdGVkIHdpdGggdGhlIGdpdmVuIF9rZXlfIGluXG4gICAqIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHMgaWYgdGhlIGtleSBpcyBhbHJlYWR5IHByZXNlbnQuXG4gICAqL1xuICBhc3luYyBwcmVwZW5kKGtleTogc3RyaW5nLCB2YWx1ZTogVmFsdWUpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAvLyBUT0RPOiBzdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBvcGNvZGU6IGNvbnN0YW50cy5PUCA9IGNvbnN0YW50cy5PUF9QUkVQRU5EO1xuICAgIGNvbnN0IHNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuc2VyaWFsaXplKG9wY29kZSwgdmFsdWUsIFwiXCIpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgIG9wY29kZSxcbiAgICAgIGtleSxcbiAgICAgIHNlcmlhbGl6ZWQuZXh0cmFzLFxuICAgICAgc2VyaWFsaXplZC52YWx1ZSxcbiAgICAgIHRoaXMuc2VxXG4gICAgKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJQUkVQRU5EXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBUb3VjaCBzZXRzIGFuIGV4cGlyYXRpb24gdmFsdWUsIGdpdmVuIGJ5IF9leHBpcmVzXywgb24gdGhlIGdpdmVuIF9rZXlfIGluXG4gICAqIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHMgaWYgdGhlIGtleSBpcyBhbHJlYWR5IHByZXNlbnQuXG4gICAqL1xuICBhc3luYyB0b3VjaChrZXk6IHN0cmluZywgZXhwaXJlczogbnVtYmVyKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgLy8gVE9ETzogc3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgZXh0cmFzID0gbWFrZUV4cGlyYXRpb24oZXhwaXJlcyB8fCB0aGlzLm9wdGlvbnMuZXhwaXJlcyk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKDB4MWMsIGtleSwgZXh0cmFzLCBcIlwiLCB0aGlzLnNlcSk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfTk9UX0ZPVU5EOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiVE9VQ0hcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEZMVVNIXG4gICAqXG4gICAqIEZsdXNoZXMgdGhlIGNhY2hlIG9uIGVhY2ggY29ubmVjdGVkIHNlcnZlci4gVGhlIGNhbGxiYWNrIHNpZ25hdHVyZSBpczpcbiAgICpcbiAgICogICAgIGNhbGxiYWNrKGxhc3RFcnIsIHJlc3VsdHMpXG4gICAqXG4gICAqIHdoZXJlIF9sYXN0RXJyXyBpcyB0aGUgbGFzdCBlcnJvciBlbmNvdW50ZXJlZCAob3IgbnVsbCwgaW4gdGhlIGNvbW1vbiBjYXNlXG4gICAqIG9mIG5vIGVycm9ycykuIF9yZXN1bHRzXyBpcyBhIGRpY3Rpb25hcnkgbWFwcGluZyBgXCJob3N0bmFtZTpwb3J0XCJgIHRvIGVpdGhlclxuICAgKiBgdHJ1ZWAgKGlmIHRoZSBvcGVyYXRpb24gd2FzIHN1Y2Nlc3NmdWwpLCBvciBhbiBlcnJvci5cbiAgICogQHBhcmFtIGNhbGxiYWNrXG4gICAqL1xuICBmbHVzaCgpOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIGJvb2xlYW4gfCBFcnJvcj4+O1xuICBmbHVzaChcbiAgICBjYWxsYmFjazogKFxuICAgICAgZXJyOiBFcnJvciB8IG51bGwsXG4gICAgICByZXN1bHRzOiBSZWNvcmQ8c3RyaW5nLCBib29sZWFuIHwgRXJyb3I+XG4gICAgKSA9PiB2b2lkXG4gICk6IHZvaWQ7XG4gIGZsdXNoKFxuICAgIGNhbGxiYWNrPzogKFxuICAgICAgZXJyOiBFcnJvciB8IG51bGwsXG4gICAgICByZXN1bHRzOiBSZWNvcmQ8c3RyaW5nLCBib29sZWFuIHwgRXJyb3I+XG4gICAgKSA9PiB2b2lkXG4gICkge1xuICAgIGlmIChjYWxsYmFjayA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm4gcHJvbWlzaWZ5KChjYWxsYmFjaykgPT4ge1xuICAgICAgICB0aGlzLmZsdXNoKGZ1bmN0aW9uIChlcnIsIHJlc3VsdHMpIHtcbiAgICAgICAgICBjYWxsYmFjayhlcnIsIHJlc3VsdHMpO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH1cbiAgICAvLyBUT0RPOiBzdXBwb3J0IGV4cGlyYXRpb25cbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoMHgwOCwgXCJcIiwgXCJcIiwgXCJcIiwgdGhpcy5zZXEpO1xuICAgIGxldCBjb3VudCA9IHRoaXMuc2VydmVycy5sZW5ndGg7XG4gICAgY29uc3QgcmVzdWx0OiBSZWNvcmQ8c3RyaW5nLCBib29sZWFuIHwgRXJyb3I+ID0ge307XG4gICAgbGV0IGxhc3RFcnI6IEVycm9yIHwgbnVsbCA9IG51bGw7XG5cbiAgICBjb25zdCBoYW5kbGVGbHVzaCA9IGZ1bmN0aW9uIChzZXE6IG51bWJlciwgc2VydjogU2VydmVyKSB7XG4gICAgICBzZXJ2Lm9uUmVzcG9uc2Uoc2VxLCBmdW5jdGlvbiAoLyogcmVzcG9uc2UgKi8pIHtcbiAgICAgICAgY291bnQgLT0gMTtcbiAgICAgICAgcmVzdWx0W3NlcnYuaG9zdHBvcnRTdHJpbmcoKV0gPSB0cnVlO1xuICAgICAgICBpZiAoY2FsbGJhY2sgJiYgY291bnQgPT09IDApIHtcbiAgICAgICAgICBjYWxsYmFjayhsYXN0RXJyLCByZXN1bHQpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHNlcnYub25FcnJvcihzZXEsIGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgICAgY291bnQgLT0gMTtcbiAgICAgICAgbGFzdEVyciA9IGVycjtcbiAgICAgICAgcmVzdWx0W3NlcnYuaG9zdHBvcnRTdHJpbmcoKV0gPSBlcnI7XG4gICAgICAgIGlmIChjYWxsYmFjayAmJiBjb3VudCA9PT0gMCkge1xuICAgICAgICAgIGNhbGxiYWNrKGxhc3RFcnIsIHJlc3VsdCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgc2Vydi53cml0ZShyZXF1ZXN0KTtcbiAgICB9O1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnNlcnZlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGhhbmRsZUZsdXNoKHRoaXMuc2VxLCB0aGlzLnNlcnZlcnNbaV0pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTVEFUU19XSVRIX0tFWVxuICAgKlxuICAgKiBTZW5kcyBhIG1lbWNhY2hlIHN0YXRzIGNvbW1hbmQgd2l0aCBhIGtleSB0byBlYWNoIGNvbm5lY3RlZCBzZXJ2ZXIuIFRoZVxuICAgKiBjYWxsYmFjayBpcyBpbnZva2VkICoqT05DRSBQRVIgU0VSVkVSKiogYW5kIGhhcyB0aGUgc2lnbmF0dXJlOlxuICAgKlxuICAgKiAgICAgY2FsbGJhY2soZXJyLCBzZXJ2ZXIsIHN0YXRzKVxuICAgKlxuICAgKiBfc2VydmVyXyBpcyB0aGUgYFwiaG9zdG5hbWU6cG9ydFwiYCBvZiB0aGUgc2VydmVyLCBhbmQgX3N0YXRzXyBpcyBhIGRpY3Rpb25hcnlcbiAgICogbWFwcGluZyB0aGUgc3RhdCBuYW1lIHRvIHRoZSB2YWx1ZSBvZiB0aGUgc3RhdGlzdGljIGFzIGEgc3RyaW5nLlxuICAgKiBAcGFyYW0ga2V5XG4gICAqIEBwYXJhbSBjYWxsYmFja1xuICAgKi9cbiAgc3RhdHNXaXRoS2V5KFxuICAgIGtleTogc3RyaW5nLFxuICAgIGNhbGxiYWNrPzogKFxuICAgICAgZXJyOiBFcnJvciB8IG51bGwsXG4gICAgICBzZXJ2ZXI6IHN0cmluZyxcbiAgICAgIHN0YXRzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+IHwgbnVsbFxuICAgICkgPT4gdm9pZFxuICApOiB2b2lkIHtcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoMHgxMCwga2V5LCBcIlwiLCBcIlwiLCB0aGlzLnNlcSk7XG5cbiAgICBjb25zdCBoYW5kbGVTdGF0cyA9IChzZXE6IG51bWJlciwgc2VydjogU2VydmVyKSA9PiB7XG4gICAgICBjb25zdCByZXN1bHQ6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcbiAgICAgIGNvbnN0IGhhbmRsZTogT25SZXNwb25zZUNhbGxiYWNrID0gKHJlc3BvbnNlKSA9PiB7XG4gICAgICAgIC8vIGVuZCBvZiBzdGF0IHJlc3BvbnNlc1xuICAgICAgICBpZiAocmVzcG9uc2UuaGVhZGVyLnRvdGFsQm9keUxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgICAgY2FsbGJhY2sobnVsbCwgc2Vydi5ob3N0cG9ydFN0cmluZygpLCByZXN1bHQpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgLy8gcHJvY2VzcyBzaW5nbGUgc3RhdCBsaW5lIHJlc3BvbnNlXG4gICAgICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgICAgIHJlc3VsdFtyZXNwb25zZS5rZXkudG9TdHJpbmcoKV0gPSByZXNwb25zZS52YWwudG9TdHJpbmcoKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICBjb25zdCBlcnJvciA9IHRoaXMuaGFuZGxlUmVzcG9uc2VFcnJvcihcbiAgICAgICAgICAgICAgYFNUQVRTICgke2tleX0pYCxcbiAgICAgICAgICAgICAgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyxcbiAgICAgICAgICAgICAgdW5kZWZpbmVkXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgICAgICAgIGNhbGxiYWNrKGVycm9yLCBzZXJ2Lmhvc3Rwb3J0U3RyaW5nKCksIG51bGwpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9O1xuICAgICAgaGFuZGxlLnF1aWV0ID0gdHJ1ZTtcblxuICAgICAgc2Vydi5vblJlc3BvbnNlKHNlcSwgaGFuZGxlKTtcbiAgICAgIHNlcnYub25FcnJvcihzZXEsIGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgICAgY2FsbGJhY2soZXJyLCBzZXJ2Lmhvc3Rwb3J0U3RyaW5nKCksIG51bGwpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHNlcnYud3JpdGUocmVxdWVzdCk7XG4gICAgfTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5zZXJ2ZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBoYW5kbGVTdGF0cyh0aGlzLnNlcSwgdGhpcy5zZXJ2ZXJzW2ldKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU1RBVFNcbiAgICpcbiAgICogRmV0Y2hlcyBtZW1jYWNoZSBzdGF0cyBmcm9tIGVhY2ggY29ubmVjdGVkIHNlcnZlci4gVGhlIGNhbGxiYWNrIGlzIGludm9rZWRcbiAgICogKipPTkNFIFBFUiBTRVJWRVIqKiBhbmQgaGFzIHRoZSBzaWduYXR1cmU6XG4gICAqXG4gICAqICAgICBjYWxsYmFjayhlcnIsIHNlcnZlciwgc3RhdHMpXG4gICAqXG4gICAqIF9zZXJ2ZXJfIGlzIHRoZSBgXCJob3N0bmFtZTpwb3J0XCJgIG9mIHRoZSBzZXJ2ZXIsIGFuZCBfc3RhdHNfIGlzIGFcbiAgICogZGljdGlvbmFyeSBtYXBwaW5nIHRoZSBzdGF0IG5hbWUgdG8gdGhlIHZhbHVlIG9mIHRoZSBzdGF0aXN0aWMgYXMgYSBzdHJpbmcuXG4gICAqIEBwYXJhbSBjYWxsYmFja1xuICAgKi9cbiAgc3RhdHMoXG4gICAgY2FsbGJhY2s/OiAoXG4gICAgICBlcnI6IEVycm9yIHwgbnVsbCxcbiAgICAgIHNlcnZlcjogc3RyaW5nLFxuICAgICAgc3RhdHM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gfCBudWxsXG4gICAgKSA9PiB2b2lkXG4gICk6IHZvaWQge1xuICAgIHRoaXMuc3RhdHNXaXRoS2V5KFwiXCIsIGNhbGxiYWNrKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSRVNFVF9TVEFUU1xuICAgKlxuICAgKiBSZXNldCB0aGUgc3RhdGlzdGljcyBlYWNoIHNlcnZlciBpcyBrZWVwaW5nIGJhY2sgdG8gemVyby4gVGhpcyBkb2Vzbid0IGNsZWFyXG4gICAqIHN0YXRzIHN1Y2ggYXMgaXRlbSBjb3VudCwgYnV0IHRlbXBvcmFyeSBzdGF0cyBzdWNoIGFzIHRvdGFsIG51bWJlciBvZlxuICAgKiBjb25uZWN0aW9ucyBvdmVyIHRpbWUuXG4gICAqXG4gICAqIFRoZSBjYWxsYmFjayBpcyBpbnZva2VkICoqT05DRSBQRVIgU0VSVkVSKiogYW5kIGhhcyB0aGUgc2lnbmF0dXJlOlxuICAgKlxuICAgKiAgICAgY2FsbGJhY2soZXJyLCBzZXJ2ZXIpXG4gICAqXG4gICAqIF9zZXJ2ZXJfIGlzIHRoZSBgXCJob3N0bmFtZTpwb3J0XCJgIG9mIHRoZSBzZXJ2ZXIuXG4gICAqIEBwYXJhbSBjYWxsYmFja1xuICAgKi9cbiAgcmVzZXRTdGF0cyhcbiAgICBjYWxsYmFjaz86IChcbiAgICAgIGVycjogRXJyb3IgfCBudWxsLFxuICAgICAgc2VydmVyOiBzdHJpbmcsXG4gICAgICBzdGF0czogUmVjb3JkPHN0cmluZywgc3RyaW5nPiB8IG51bGxcbiAgICApID0+IHZvaWRcbiAgKTogdm9pZCB7XG4gICAgdGhpcy5zdGF0c1dpdGhLZXkoXCJyZXNldFwiLCBjYWxsYmFjayk7XG4gIH1cblxuICAvKipcbiAgICogUVVJVFxuICAgKlxuICAgKiBDbG9zZXMgdGhlIGNvbm5lY3Rpb24gdG8gZWFjaCBzZXJ2ZXIsIG5vdGlmeWluZyB0aGVtIG9mIHRoaXMgaW50ZW50aW9uLiBOb3RlXG4gICAqIHRoYXQgcXVpdCBjYW4gcmFjZSBhZ2FpbnN0IGFscmVhZHkgb3V0c3RhbmRpbmcgcmVxdWVzdHMgd2hlbiB0aG9zZSByZXF1ZXN0c1xuICAgKiBmYWlsIGFuZCBhcmUgcmV0cmllZCwgbGVhZGluZyB0byB0aGUgcXVpdCBjb21tYW5kIHdpbm5pbmcgYW5kIGNsb3NpbmcgdGhlXG4gICAqIGNvbm5lY3Rpb24gYmVmb3JlIHRoZSByZXRyaWVzIGNvbXBsZXRlLlxuICAgKi9cbiAgcXVpdCgpIHtcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICAvLyBUT0RPOiBOaWNlciBwZXJoYXBzIHRvIGRvIFFVSVRRICgweDE3KSBidXQgbmVlZCBhIG5ldyBjYWxsYmFjayBmb3Igd2hlblxuICAgIC8vIHdyaXRlIGlzIGRvbmUuXG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKDB4MDcsIFwiXCIsIFwiXCIsIFwiXCIsIHRoaXMuc2VxKTsgLy8gUVVJVFxuICAgIGxldCBzZXJ2O1xuXG4gICAgY29uc3QgaGFuZGxlUXVpdCA9IGZ1bmN0aW9uIChzZXE6IG51bWJlciwgc2VydjogU2VydmVyKSB7XG4gICAgICBzZXJ2Lm9uUmVzcG9uc2Uoc2VxLCBmdW5jdGlvbiAoLyogcmVzcG9uc2UgKi8pIHtcbiAgICAgICAgc2Vydi5jbG9zZSgpO1xuICAgICAgfSk7XG4gICAgICBzZXJ2Lm9uRXJyb3Ioc2VxLCBmdW5jdGlvbiAoLyogZXJyICovKSB7XG4gICAgICAgIHNlcnYuY2xvc2UoKTtcbiAgICAgIH0pO1xuICAgICAgc2Vydi53cml0ZShyZXF1ZXN0KTtcbiAgICB9O1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnNlcnZlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHNlcnYgPSB0aGlzLnNlcnZlcnNbaV07XG4gICAgICBoYW5kbGVRdWl0KHRoaXMuc2VxLCBzZXJ2KTtcbiAgICB9XG4gIH1cblxuICBfdmVyc2lvbihzZXJ2ZXI6IFNlcnZlcik6IFByb21pc2U8eyB2YWx1ZTogVmFsdWUgfCBudWxsIH0+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICAgIGNvbnN0YW50cy5PUF9WRVJTSU9OLFxuICAgICAgICBcIlwiLFxuICAgICAgICBcIlwiLFxuICAgICAgICBcIlwiLFxuICAgICAgICB0aGlzLnNlcVxuICAgICAgKTtcbiAgICAgIHRoaXMucGVyZm9ybU9uU2VydmVyKHNlcnZlciwgcmVxdWVzdCwgdGhpcy5zZXEsIChlcnIsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICByZXR1cm4gcmVqZWN0KGVycik7XG4gICAgICAgIH1cblxuICAgICAgICBzd2l0Y2ggKHJlc3BvbnNlIS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICAgICAgLyogVE9ETzogdGhpcyBpcyBidWdnZWQsIHdlIHNob3VsZCd0IHVzZSB0aGUgZGVzZXJpYWxpemVyIGhlcmUsIHNpbmNlIHZlcnNpb24gYWx3YXlzIHJldHVybnMgYSB2ZXJzaW9uIHN0cmluZy5cbiAgICAgICAgICAgICBUaGUgZGVzZXJpYWxpemVyIHNob3VsZCBvbmx5IGJlIHVzZWQgb24gdXNlciBrZXkgZGF0YS4gKi9cbiAgICAgICAgICAgIGNvbnN0IGRlc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5kZXNlcmlhbGl6ZShcbiAgICAgICAgICAgICAgcmVzcG9uc2UhLmhlYWRlci5vcGNvZGUsXG4gICAgICAgICAgICAgIHJlc3BvbnNlIS52YWwsXG4gICAgICAgICAgICAgIHJlc3BvbnNlIS5leHRyYXNcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICByZXR1cm4gcmVzb2x2ZSh7IHZhbHVlOiBkZXNlcmlhbGl6ZWQudmFsdWUgfSk7XG4gICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHJldHVybiByZWplY3QoXG4gICAgICAgICAgICAgIHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJWRVJTSU9OXCIsIHJlc3BvbnNlIS5oZWFkZXIuc3RhdHVzKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmVxdWVzdCB0aGUgc2VydmVyIHZlcnNpb24gZnJvbSB0aGUgXCJmaXJzdFwiIHNlcnZlciBpbiB0aGUgYmFja2VuZCBwb29sLlxuICAgKiBUaGUgc2VydmVyIHJlc3BvbmRzIHdpdGggYSBwYWNrZXQgY29udGFpbmluZyB0aGUgdmVyc2lvbiBzdHJpbmcgaW4gdGhlIGJvZHkgd2l0aCB0aGUgZm9sbG93aW5nIGZvcm1hdDogXCJ4LnkuelwiXG4gICAqL1xuICB2ZXJzaW9uKCk6IFByb21pc2U8eyB2YWx1ZTogVmFsdWUgfCBudWxsIH0+IHtcbiAgICBjb25zdCBzZXJ2ZXIgPSB0aGlzLnNlcnZlcktleVRvU2VydmVyKHRoaXMuc2VydmVyS2V5c1swXSk7XG4gICAgcmV0dXJuIHRoaXMuX3ZlcnNpb24oc2VydmVyKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXRyaWV2ZXMgdGhlIHNlcnZlciB2ZXJzaW9uIGZyb20gYWxsIHRoZSBzZXJ2ZXJzXG4gICAqIGluIHRoZSBiYWNrZW5kIHBvb2wsIGVycm9ycyBpZiBhbnkgb25lIG9mIHRoZW0gaGFzIGFuXG4gICAqIGVycm9yXG4gICAqL1xuICBhc3luYyB2ZXJzaW9uQWxsKGNhbGxiYWNrcz86IHtcbiAgICBiZWZvcmVQaW5nPzogKHNlcnZlcktleTogc3RyaW5nKSA9PiB2b2lkO1xuICAgIGFmdGVyUGluZz86IChzZXJ2ZXJLZXk6IHN0cmluZykgPT4gdm9pZDtcbiAgfSk6IFByb21pc2U8e1xuICAgIHZhbHVlczogUmVjb3JkPHN0cmluZywgVmFsdWUgfCBudWxsPjtcbiAgfT4ge1xuICAgIGNvbnN0IHZlcnNpb25PYmplY3RzID0gYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICB0aGlzLnNlcnZlcktleXMubWFwKChzZXJ2ZXJLZXkpID0+IHtcbiAgICAgICAgY29uc3Qgc2VydmVyID0gdGhpcy5zZXJ2ZXJLZXlUb1NlcnZlcihzZXJ2ZXJLZXkpO1xuICAgICAgICBjYWxsYmFja3M/LmJlZm9yZVBpbmc/LihzZXJ2ZXJLZXkpO1xuICAgICAgICByZXR1cm4gdGhpcy5fdmVyc2lvbihzZXJ2ZXIpLnRoZW4oKHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgY2FsbGJhY2tzPy5hZnRlclBpbmc/LihzZXJ2ZXJLZXkpO1xuICAgICAgICAgIHJldHVybiB7IHNlcnZlcktleTogc2VydmVyS2V5LCB2YWx1ZTogcmVzcG9uc2UudmFsdWUgfTtcbiAgICAgICAgfSk7XG4gICAgICB9KVxuICAgICk7XG4gICAgY29uc3QgdmFsdWVzID0gdmVyc2lvbk9iamVjdHMucmVkdWNlKChhY2N1bXVsYXRvciwgdmVyc2lvbk9iamVjdCkgPT4ge1xuICAgICAgYWNjdW11bGF0b3JbdmVyc2lvbk9iamVjdC5zZXJ2ZXJLZXldID0gdmVyc2lvbk9iamVjdC52YWx1ZTtcbiAgICAgIHJldHVybiBhY2N1bXVsYXRvcjtcbiAgICB9LCB7fSBhcyBSZWNvcmQ8c3RyaW5nLCBWYWx1ZSB8IG51bGw+KTtcbiAgICByZXR1cm4geyB2YWx1ZXM6IHZhbHVlcyB9O1xuICB9XG5cbiAgLyoqXG4gICAqIENsb3NlcyAoYWJydXB0bHkpIGNvbm5lY3Rpb25zIHRvIGFsbCB0aGUgc2VydmVycy5cbiAgICogQHNlZSB0aGlzLnF1aXRcbiAgICovXG4gIGNsb3NlKCkge1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5zZXJ2ZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB0aGlzLnNlcnZlcnNbaV0uY2xvc2UoKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUGVyZm9ybSBhIGdlbmVyaWMgc2luZ2xlIHJlc3BvbnNlIG9wZXJhdGlvbiAoZ2V0LCBzZXQgZXRjKSBvbiBvbmUgc2VydmVyXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgdGhlIGtleSB0byBoYXNoIHRvIGdldCBhIHNlcnZlciBmcm9tIHRoZSBwb29sXG4gICAqIEBwYXJhbSB7YnVmZmVyfSByZXF1ZXN0IGEgYnVmZmVyIGNvbnRhaW5pbmcgdGhlIHJlcXVlc3RcbiAgICogQHBhcmFtIHtudW1iZXJ9IHNlcSB0aGUgc2VxdWVuY2UgbnVtYmVyIG9mIHRoZSBvcGVyYXRpb24uIEl0IGlzIHVzZWQgdG8gcGluIHRoZSBjYWxsYmFja3NcbiAgICAgICAgICAgICAgICAgICAgICAgICB0byBhIHNwZWNpZmljIG9wZXJhdGlvbiBhbmQgc2hvdWxkIG5ldmVyIGNoYW5nZSBkdXJpbmcgYSBgcGVyZm9ybWAuXG4gICAqIEBwYXJhbSB7bnVtYmVyP30gcmV0cmllcyBudW1iZXIgb2YgdGltZXMgdG8gcmV0cnkgcmVxdWVzdCBvbiBmYWlsdXJlXG4gICAqL1xuICBwZXJmb3JtKFxuICAgIGtleTogc3RyaW5nLFxuICAgIHJlcXVlc3Q6IEJ1ZmZlcixcbiAgICBzZXE6IG51bWJlcixcbiAgICByZXRyaWVzPzogbnVtYmVyXG4gICk6IFByb21pc2U8TWVzc2FnZT4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBjb25zdCBzZXJ2ZXJLZXkgPSB0aGlzLmxvb2t1cEtleVRvU2VydmVyS2V5KGtleSk7XG4gICAgICBjb25zdCBzZXJ2ZXIgPSB0aGlzLnNlcnZlcktleVRvU2VydmVyKHNlcnZlcktleSk7XG5cbiAgICAgIGlmICghc2VydmVyKSB7XG4gICAgICAgIHJldHVybiByZWplY3QobmV3IEVycm9yKFwiTm8gc2VydmVycyBhdmFpbGFibGVcIikpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLnBlcmZvcm1PblNlcnZlcihcbiAgICAgICAgc2VydmVyLFxuICAgICAgICByZXF1ZXN0LFxuICAgICAgICBzZXEsXG4gICAgICAgIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgIHJldHVybiByZWplY3QoZXJyb3IpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXNvbHZlKHJlc3BvbnNlISk7XG4gICAgICAgIH0sXG4gICAgICAgIHJldHJpZXNcbiAgICAgICk7XG4gICAgfSk7XG4gIH1cblxuICBwZXJmb3JtT25TZXJ2ZXIoXG4gICAgc2VydmVyOiBTZXJ2ZXIsXG4gICAgcmVxdWVzdDogQnVmZmVyLFxuICAgIHNlcTogbnVtYmVyLFxuICAgIGNhbGxiYWNrOiBSZXNwb25zZU9yRXJyb3JDYWxsYmFjayxcbiAgICByZXRyaWVzOiBudW1iZXIgPSAwXG4gICkge1xuICAgIGNvbnN0IF90aGlzID0gdGhpcztcblxuICAgIHJldHJpZXMgPSByZXRyaWVzIHx8IHRoaXMub3B0aW9ucy5yZXRyaWVzO1xuICAgIGNvbnN0IG9yaWdSZXRyaWVzID0gdGhpcy5vcHRpb25zLnJldHJpZXM7XG4gICAgY29uc3QgbG9nZ2VyID0gdGhpcy5vcHRpb25zLmxvZ2dlcjtcbiAgICBjb25zdCByZXRyeV9kZWxheSA9IHRoaXMub3B0aW9ucy5yZXRyeV9kZWxheTtcblxuICAgIGNvbnN0IHJlc3BvbnNlSGFuZGxlcjogT25SZXNwb25zZUNhbGxiYWNrID0gZnVuY3Rpb24gKHJlc3BvbnNlKSB7XG4gICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgY2FsbGJhY2sobnVsbCwgcmVzcG9uc2UpO1xuICAgICAgfVxuICAgIH07XG5cbiAgICBjb25zdCBlcnJvckhhbmRsZXI6IE9uRXJyb3JDYWxsYmFjayA9IGZ1bmN0aW9uIChlcnJvcikge1xuICAgICAgaWYgKC0tcmV0cmllcyA+IDApIHtcbiAgICAgICAgLy8gV2FpdCBmb3IgcmV0cnlfZGVsYXlcbiAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgX3RoaXMucGVyZm9ybU9uU2VydmVyKHNlcnZlciwgcmVxdWVzdCwgc2VxLCBjYWxsYmFjaywgcmV0cmllcyk7XG4gICAgICAgIH0sIDEwMDAgKiByZXRyeV9kZWxheSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBsb2dnZXIubG9nKFxuICAgICAgICAgIFwiTWVtSlM6IFNlcnZlciA8XCIgK1xuICAgICAgICAgICAgc2VydmVyLmhvc3Rwb3J0U3RyaW5nKCkgK1xuICAgICAgICAgICAgXCI+IGZhaWxlZCBhZnRlciAoXCIgK1xuICAgICAgICAgICAgb3JpZ1JldHJpZXMgK1xuICAgICAgICAgICAgXCIpIHJldHJpZXMgd2l0aCBlcnJvciAtIFwiICtcbiAgICAgICAgICAgIGVycm9yLm1lc3NhZ2VcbiAgICAgICAgKTtcbiAgICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgICAgY2FsbGJhY2soZXJyb3IsIG51bGwpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfTtcblxuICAgIHNlcnZlci5vblJlc3BvbnNlKHNlcSwgcmVzcG9uc2VIYW5kbGVyKTtcbiAgICBzZXJ2ZXIub25FcnJvcihzZXEsIGVycm9ySGFuZGxlcik7XG4gICAgc2VydmVyLndyaXRlKHJlcXVlc3QpO1xuICB9XG5cbiAgLy8gSW5jcmVtZW50IHRoZSBzZXEgdmFsdWVcbiAgaW5jclNlcSgpIHtcbiAgICB0aGlzLnNlcSsrO1xuXG4gICAgLy8gV3JhcCBgdGhpcy5zZXFgIHRvIDMyLWJpdHMgc2luY2UgdGhlIGZpZWxkIHdlIGZpdCBpdCBpbnRvIGlzIG9ubHkgMzItYml0cy5cbiAgICB0aGlzLnNlcSAmPSAweGZmZmZmZmZmO1xuXG4gICAgcmV0dXJuIHRoaXMuc2VxO1xuICB9XG5cbiAgcHJpdmF0ZSBjcmVhdGVBbmRMb2dFcnJvcihcbiAgICBjb21tYW5kTmFtZTogc3RyaW5nLFxuICAgIHJlc3BvbnNlU3RhdHVzOiBSZXNwb25zZVN0YXR1cyB8IHVuZGVmaW5lZFxuICApOiBFcnJvciB7XG4gICAgY29uc3QgZXJyb3JNZXNzYWdlID0gYE1lbUpTICR7Y29tbWFuZE5hbWV9OiAke2NvbnN0YW50cy5yZXNwb25zZVN0YXR1c1RvU3RyaW5nKFxuICAgICAgcmVzcG9uc2VTdGF0dXNcbiAgICApfWA7XG4gICAgdGhpcy5vcHRpb25zLmxvZ2dlci5sb2coZXJyb3JNZXNzYWdlKTtcbiAgICByZXR1cm4gbmV3IEVycm9yKGVycm9yTWVzc2FnZSk7XG4gIH1cblxuICAvKipcbiAgICogTG9nIGFuIGVycm9yIHRvIHRoZSBsb2dnZXIsIHRoZW4gcmV0dXJuIHRoZSBlcnJvci5cbiAgICogSWYgYSBjYWxsYmFjayBpcyBnaXZlbiwgY2FsbCBpdCB3aXRoIGNhbGxiYWNrKGVycm9yLCBudWxsKS5cbiAgICovXG4gIHByaXZhdGUgaGFuZGxlUmVzcG9uc2VFcnJvcihcbiAgICBjb21tYW5kTmFtZTogc3RyaW5nLFxuICAgIHJlc3BvbnNlU3RhdHVzOiBSZXNwb25zZVN0YXR1cyB8IHVuZGVmaW5lZCxcbiAgICBjYWxsYmFjazogdW5kZWZpbmVkIHwgKChlcnJvcjogRXJyb3IgfCBudWxsLCBvdGhlcjogbnVsbCkgPT4gdm9pZClcbiAgKTogRXJyb3Ige1xuICAgIGNvbnN0IGVycm9yID0gdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihjb21tYW5kTmFtZSwgcmVzcG9uc2VTdGF0dXMpO1xuICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgY2FsbGJhY2soZXJyb3IsIG51bGwpO1xuICAgIH1cbiAgICByZXR1cm4gZXJyb3I7XG4gIH1cbn1cblxuZXhwb3J0IHsgQ2xpZW50LCBTZXJ2ZXIsIFV0aWxzLCBIZWFkZXIgfTtcbiJdfQ== \ No newline at end of file diff --git a/src/memjs/memjs.ts b/src/memjs/memjs.ts index 60a38bd..4fa1dc6 100644 --- a/src/memjs/memjs.ts +++ b/src/memjs/memjs.ts @@ -915,8 +915,8 @@ class Client { * error */ async versionAll(callbacks?: { - beforePing?: (response: string) => void; - afterPing?: (response: string) => void; + beforePing?: (serverKey: string) => void; + afterPing?: (serverKey: string) => void; }): Promise<{ values: Record; }> { From bbf0e849fdc44f08ba93bf0df4b1e2b5b69f66ba Mon Sep 17 00:00:00 2001 From: Arturo Olvera Date: Thu, 9 Feb 2023 15:10:12 -0800 Subject: [PATCH 65/79] comments --- src/memjs/memjs.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/memjs/memjs.ts b/src/memjs/memjs.ts index 4fa1dc6..a14915a 100644 --- a/src/memjs/memjs.ts +++ b/src/memjs/memjs.ts @@ -913,6 +913,9 @@ class Client { * Retrieves the server version from all the servers * in the backend pool, errors if any one of them has an * error + * + * Callbacks functions are called before/after we ping memcached + * and used to log which hosts are timing out. */ async versionAll(callbacks?: { beforePing?: (serverKey: string) => void; From 2a63687e2faa3400c9e3670250d871de1681f118 Mon Sep 17 00:00:00 2001 From: Arturo Olvera Date: Thu, 9 Feb 2023 15:12:06 -0800 Subject: [PATCH 66/79] didnt compile --- lib/memjs/memjs.d.ts | 3 +++ lib/memjs/memjs.d.ts.map | 2 +- lib/memjs/memjs.js | 5 ++++- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/memjs/memjs.d.ts b/lib/memjs/memjs.d.ts index e2bb5bd..7d14614 100644 --- a/lib/memjs/memjs.d.ts +++ b/lib/memjs/memjs.d.ts @@ -272,6 +272,9 @@ declare class Client { * Retrieves the server version from all the servers * in the backend pool, errors if any one of them has an * error + * + * Callbacks functions are called before/after we ping memcached + * and used to log which hosts are timing out. */ versionAll(callbacks?: { beforePing?: (serverKey: string) => void; diff --git a/lib/memjs/memjs.d.ts.map b/lib/memjs/memjs.d.ts.map index 242d930..eba3c23 100644 --- a/lib/memjs/memjs.d.ts.map +++ b/lib/memjs/memjs.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"memjs.d.ts","sourceRoot":"","sources":["../../src/memjs/memjs.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"memjs.d.ts","sourceRoot":"","sources":["../../src/memjs/memjs.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/lib/memjs/memjs.js b/lib/memjs/memjs.js index 5ed79fe..f94461e 100644 --- a/lib/memjs/memjs.js +++ b/lib/memjs/memjs.js @@ -629,6 +629,9 @@ class Client { * Retrieves the server version from all the servers * in the backend pool, errors if any one of them has an * error + * + * Callbacks functions are called before/after we ping memcached + * and used to log which hosts are timing out. */ async versionAll(callbacks) { const versionObjects = await Promise.all(this.serverKeys.map((serverKey) => { @@ -739,4 +742,4 @@ class Client { } } exports.Client = Client; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVtanMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbWVtanMvbWVtanMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLHdCQUF3Qjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUV4QixxQ0FLa0I7QUF3aUNELHVGQTFpQ2YsZUFBTSxPQTBpQ2U7QUF2aUN2Qix1REFBK0Q7QUFDL0QsbUNBU2lCO0FBQ2pCLHVEQUF5QztBQUN6QywyQ0FBNkM7QUFDN0MsK0NBQWlDO0FBMGhDUixzQkFBSztBQXpoQzlCLGlEQUFtQztBQXloQ0gsd0JBQU07QUF2aEN0QyxTQUFTLDhCQUE4QixDQUNyQyxPQUFpQixFQUNqQixHQUFXO0lBRVgsTUFBTSxLQUFLLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQztJQUM3QixNQUFNLEtBQUssR0FBRyxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxnQkFBUSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3BELE9BQU8sT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ3hCLENBQUM7QUFFRCwrQ0FBK0M7QUFDL0MsU0FBUyxTQUFTLENBQ2hCLE9BQTBFO0lBRTFFLE9BQU8sSUFBSSxPQUFPLENBQUMsVUFBVSxPQUFPLEVBQUUsTUFBTTtRQUMxQyxPQUFPLENBQUMsVUFBVSxHQUFHLEVBQUUsTUFBTTtZQUMzQixHQUFHLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3RDLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBeURELE1BQU0sTUFBTTtJQVFWLDRFQUE0RTtJQUM1RSxtQ0FBbUM7SUFDbkMsWUFBWSxPQUFpQixFQUFFLE9BQTBDO1FBQ3ZFLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO1FBQ3ZCLElB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QixFQUNuQixjQUEwQztRQUUxQyxNQUFNLFlBQVksR0FBRyxTQUFTLFdBQVcsS0FBSyxTQUFTLENBQUMsc0JBQXNCLENBQzVFLGNBQWMsQ0FDZixFQUFFLENBQUM7UUFDSixJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDdEMsT0FBTyxJQUFJLEtBQUssQ0FBQyxZQUFZLENBQUMsQ0FBQztJQUNqQyxDQUFDO0lBRUQ7OztPQUdHO0lBQ0ssbUJBQW1CLENBQ3pCLFdBQW1CLEVBQ25CLGNBQTBDLEVBQzFDLFFBQWtFO1FBRWxFLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxXQUFXLEVBQUUsY0FBYyxDQUFDLENBQUM7UUFDbEUsSUFBSSxRQUFRLEVBQUU7WUFDWixRQUFRLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxDQUFDO1NBQ3ZCO1FBQ0QsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0NBQ0Y7QUFFUSx3QkFBTSIsInNvdXJjZXNDb250ZW50IjpbIi8vIE1lbVRTIE1lbWNhY2hlIENsaWVudFxuXG5pbXBvcnQge1xuICBPbkVycm9yQ2FsbGJhY2ssXG4gIE9uUmVzcG9uc2VDYWxsYmFjayxcbiAgU2VydmVyLFxuICBTZXJ2ZXJPcHRpb25zLFxufSBmcm9tIFwiLi9zZXJ2ZXJcIjtcbmltcG9ydCB7IG5vb3BTZXJpYWxpemVyLCBTZXJpYWxpemVyIH0gZnJvbSBcIi4vbm9vcC1zZXJpYWxpemVyXCI7XG5pbXBvcnQge1xuICBtYWtlUmVxdWVzdEJ1ZmZlcixcbiAgY29weUludG9SZXF1ZXN0QnVmZmVyLFxuICBtZXJnZSxcbiAgbWFrZUV4cGlyYXRpb24sXG4gIG1ha2VBbW91bnRJbml0aWFsQW5kRXhwaXJhdGlvbixcbiAgaGFzaENvZGUsXG4gIE1heWJlQnVmZmVyLFxuICBNZXNzYWdlLFxufSBmcm9tIFwiLi91dGlsc1wiO1xuaW1wb3J0ICogYXMgY29uc3RhbnRzIGZyb20gXCIuL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgUmVzcG9uc2VTdGF0dXMgfSBmcm9tIFwiLi9jb25zdGFudHNcIjtcbmltcG9ydCAqIGFzIFV0aWxzIGZyb20gXCIuL3V0aWxzXCI7XG5pbXBvcnQgKiBhcyBIZWFkZXIgZnJvbSBcIi4vaGVhZGVyXCI7XG5cbmZ1bmN0aW9uIGRlZmF1bHRLZXlUb1NlcnZlckhhc2hGdW5jdGlvbihcbiAgc2VydmVyczogc3RyaW5nW10sXG4gIGtleTogc3RyaW5nXG4pOiBzdHJpbmcge1xuICBjb25zdCB0b3RhbCA9IHNlcnZlcnMubGVuZ3RoO1xuICBjb25zdCBpbmRleCA9IHRvdGFsID4gMSA/IGhhc2hDb2RlKGtleSkgJSB0b3RhbCA6IDA7XG4gIHJldHVybiBzZXJ2ZXJzW2luZGV4XTtcbn1cblxuLy8gY29udmVydHMgYSBjYWxsIGludG8gYSBwcm9taXNlLXJldHVybmluZyBvbmVcbmZ1bmN0aW9uIHByb21pc2lmeTxSZXN1bHQ+KFxuICBjb21tYW5kOiAoY2FsbGJhY2s6IChlcnJvcjogRXJyb3IgfCBudWxsLCByZXN1bHQ6IFJlc3VsdCkgPT4gdm9pZCkgPT4gdm9pZFxuKTogUHJvbWlzZTxSZXN1bHQ+IHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICBjb21tYW5kKGZ1bmN0aW9uIChlcnIsIHJlc3VsdCkge1xuICAgICAgZXJyID8gcmVqZWN0KGVycikgOiByZXNvbHZlKHJlc3VsdCk7XG4gICAgfSk7XG4gIH0pO1xufVxuXG50eXBlIFJlc3BvbnNlT3JFcnJvckNhbGxiYWNrID0gKFxuICBlcnJvcjogRXJyb3IgfCBudWxsLFxuICByZXNwb25zZTogTWVzc2FnZSB8IG51bGxcbikgPT4gdm9pZDtcblxuaW50ZXJmYWNlIEJhc2VDbGllbnRPcHRpb25zIHtcbiAgcmV0cmllczogbnVtYmVyO1xuICByZXRyeV9kZWxheTogbnVtYmVyO1xuICBleHBpcmVzOiBudW1iZXI7XG4gIGxvZ2dlcjogeyBsb2c6IHR5cGVvZiBjb25zb2xlLmxvZyB9O1xuICBrZXlUb1NlcnZlckhhc2hGdW5jdGlvbjogdHlwZW9mIGRlZmF1bHRLZXlUb1NlcnZlckhhc2hGdW5jdGlvbjtcbn1cblxuaW50ZXJmYWNlIFNlcmlhbGl6ZXJQcm9wPFZhbHVlLCBFeHRyYXM+IHtcbiAgc2VyaWFsaXplcjogU2VyaWFsaXplcjxWYWx1ZSwgRXh0cmFzPjtcbn1cblxuLyoqXG4gKiBUaGUgY2xpZW50IGhhcyBwYXJ0aWFsIHN1cHBvcnQgZm9yIHNlcmlhbGl6aW5nIGFuZCBkZXNlcmlhbGl6aW5nIHZhbHVlcyBmcm9tIHRoZVxuICogQnVmZmVyIGJ5dGUgc3RyaW5ncyB3ZSByZWNlaXZlIGZyb20gdGhlIHdpcmUuIFRoZSBkZWZhdWx0IHNlcmlhbGl6ZXIgaXMgZm9yIE1heWJlQnVmZmVyLlxuICpcbiAqIElmIFZhbHVlIGFuZCBFeHRyYXMgYXJlIG9mIHR5cGUgQnVmZmVyLCB0aGVuIHJldHVybiB0eXBlIFdoZW5CdWZmZXIuIE90aGVyd2lzZSxcbiAqIHJldHVybiB0eXBlIE5vdEJ1ZmZlci5cbiAqL1xudHlwZSBJZkJ1ZmZlcjxWYWx1ZSwgRXh0cmFzLCBXaGVuVmFsdWVBbmRFeHRyYXNBcmVCdWZmZXJzLCBOb3RCdWZmZXI+ID1cbiAgVmFsdWUgZXh0ZW5kcyBCdWZmZXJcbiAgICA/IEV4dHJhcyBleHRlbmRzIEJ1ZmZlclxuICAgICAgPyBXaGVuVmFsdWVBbmRFeHRyYXNBcmVCdWZmZXJzXG4gICAgICA6IE5vdEJ1ZmZlclxuICAgIDogTm90QnVmZmVyO1xuXG5leHBvcnQgdHlwZSBHaXZlbkNsaWVudE9wdGlvbnM8VmFsdWUsIEV4dHJhcz4gPSBQYXJ0aWFsPEJhc2VDbGllbnRPcHRpb25zPiAmXG4gIElmQnVmZmVyPFxuICAgIFZhbHVlLFxuICAgIEV4dHJhcyxcbiAgICBQYXJ0aWFsPFNlcmlhbGl6ZXJQcm9wPFZhbHVlLCBFeHRyYXM+PixcbiAgICBTZXJpYWxpemVyUHJvcDxWYWx1ZSwgRXh0cmFzPlxuICA+O1xuXG5leHBvcnQgdHlwZSBDQVNUb2tlbiA9IEJ1ZmZlcjtcblxuZXhwb3J0IGludGVyZmFjZSBHZXRSZXN1bHQ8VmFsdWUgPSBNYXliZUJ1ZmZlciwgRXh0cmFzID0gTWF5YmVCdWZmZXI+IHtcbiAgdmFsdWU6IFZhbHVlO1xuICBleHRyYXM6IEV4dHJhcztcbiAgY2FzOiBDQVNUb2tlbiB8IHVuZGVmaW5lZDtcbn1cblxuZXhwb3J0IHR5cGUgR2V0TXVsdGlSZXN1bHQ8XG4gIEtleXMgZXh0ZW5kcyBzdHJpbmcgPSBzdHJpbmcsXG4gIFZhbHVlID0gTWF5YmVCdWZmZXIsXG4gIEV4dHJhcyA9IE1heWJlQnVmZmVyXG4+ID0ge1xuICBbSyBpbiBLZXlzXT86IEdldFJlc3VsdDxWYWx1ZSwgRXh0cmFzPjtcbn07XG5cbmNsYXNzIENsaWVudDxWYWx1ZSA9IE1heWJlQnVmZmVyLCBFeHRyYXMgPSBNYXliZUJ1ZmZlcj4ge1xuICBzZXJ2ZXJzOiBTZXJ2ZXJbXTtcbiAgc2VxOiBudW1iZXI7XG4gIG9wdGlvbnM6IEJhc2VDbGllbnRPcHRpb25zICYgUGFydGlhbDxTZXJpYWxpemVyUHJvcDxWYWx1ZSwgRXh0cmFzPj47XG4gIHNlcmlhbGl6ZXI6IFNlcmlhbGl6ZXI8VmFsdWUsIEV4dHJhcz47XG4gIHNlcnZlck1hcDogeyBbaG9zdHBvcnQ6IHN0cmluZ106IFNlcnZlciB9O1xuICBzZXJ2ZXJLZXlzOiBzdHJpbmdbXTtcblxuICAvLyBDbGllbnQgaW5pdGlhbGl6ZXIgdGFrZXMgYSBsaXN0IG9mIGBTZXJ2ZXJgcyBhbmQgYW4gYG9wdGlvbnNgIGRpY3Rpb25hcnkuXG4gIC8vIFNlZSBgQ2xpZW50LmNyZWF0ZWAgZm9yIGRldGFpbHMuXG4gIGNvbnN0cnVjdG9yKHNlcnZlcnM6IFNlcnZlcltdLCBvcHRpb25zOiBHaXZlbkNsaWVudE9wdGlvbnM8VmFsdWUsIEV4dHJhcz4pIHtcbiAgICB0aGlzLnNlcnZlcnMgPSBzZXJ2ZXJzO1xuICAgIHRoaXMuc2VxID0gMDtcbiAgICB0aGlzLm9wdGlvbnMgPSBtZXJnZShvcHRpb25zIHx8IHt9LCB7XG4gICAgICByZXRyaWVzOiAyLFxuICAgICAgcmV0cnlfZGVsYXk6IDAuMixcbiAgICAgIGV4cGlyZXM6IDAsXG4gICAgICBsb2dnZXI6IGNvbnNvbGUsXG4gICAgICBrZXlUb1NlcnZlckhhc2hGdW5jdGlvbjogZGVmYXVsdEtleVRvU2VydmVySGFzaEZ1bmN0aW9uLFxuICAgIH0pO1xuXG4gICAgdGhpcy5zZXJpYWxpemVyID0gdGhpcy5vcHRpb25zLnNlcmlhbGl6ZXIgfHwgKG5vb3BTZXJpYWxpemVyIGFzIGFueSk7XG5cbiAgICAvLyBTdG9yZSBhIG1hcHBpbmcgZnJvbSBob3N0cG9ydCAtPiBzZXJ2ZXIgc28gd2UgY2FuIHF1aWNrbHkgZ2V0IGEgc2VydmVyIG9iamVjdCBmcm9tIHRoZSBzZXJ2ZXJLZXkgcmV0dXJuZWQgYnkgdGhlIGhhc2hpbmcgZnVuY3Rpb25cbiAgICBjb25zdCBzZXJ2ZXJNYXA6IHsgW2hvc3Rwb3J0OiBzdHJpbmddOiBTZXJ2ZXIgfSA9IHt9O1xuICAgIHRoaXMuc2VydmVycy5mb3JFYWNoKGZ1bmN0aW9uIChzZXJ2ZXIpIHtcbiAgICAgIHNlcnZlck1hcFtzZXJ2ZXIuaG9zdHBvcnRTdHJpbmcoKV0gPSBzZXJ2ZXI7XG4gICAgfSk7XG4gICAgdGhpcy5zZXJ2ZXJNYXAgPSBzZXJ2ZXJNYXA7XG5cbiAgICAvLyBzdG9yZSBhIGxpc3Qgb2YgYWxsIG91ciBzZXJ2ZXJLZXlzIHNvIHdlIGRvbid0IG5lZWQgdG8gY29uc3RhbnRseSByZWFsbG9jYXRlIHRoaXMgYXJyYXlcbiAgICB0aGlzLnNlcnZlcktleXMgPSBPYmplY3Qua2V5cyh0aGlzLnNlcnZlck1hcCk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIG5ldyBjbGllbnQgZ2l2ZW4gYW4gb3B0aW9uYWwgY29uZmlnIHN0cmluZyBhbmQgb3B0aW9uYWwgaGFzaCBvZlxuICAgKiBvcHRpb25zLiBUaGUgY29uZmlnIHN0cmluZyBzaG91bGQgYmUgb2YgdGhlIGZvcm06XG4gICAqXG4gICAqICAgICBcIlt1c2VyOnBhc3NAXXNlcnZlcjFbOjExMjExXSxbdXNlcjpwYXNzQF1zZXJ2ZXIyWzoxMTIxMV0sLi4uXCJcbiAgICpcbiAgICogSWYgdGhlIGFyZ3VtZW50IGlzIG5vdCBnaXZlbiwgZmFsbGJhY2sgb24gdGhlIGBNRU1DQUNISUVSX1NFUlZFUlNgIGVudmlyb25tZW50XG4gICAqIHZhcmlhYmxlLCBgTUVNQ0FDSEVfU0VSVkVSU2AgZW52aXJvbm1lbnQgdmFyaWFibGUgb3IgYFwibG9jYWxob3N0OjExMjExXCJgLlxuICAgKlxuICAgKiBUaGUgb3B0aW9ucyBoYXNoIG1heSBjb250YWluIHRoZSBvcHRpb25zOlxuICAgKlxuICAgKiAqIGByZXRyaWVzYCAtIHRoZSBudW1iZXIgb2YgdGltZXMgdG8gcmV0cnkgYW4gb3BlcmF0aW9uIGluIGxpZXUgb2YgZmFpbHVyZXNcbiAgICogKGRlZmF1bHQgMilcbiAgICogKiBgZXhwaXJlc2AgLSB0aGUgZGVmYXVsdCBleHBpcmF0aW9uIGluIHNlY29uZHMgdG8gdXNlIChkZWZhdWx0IDAgLSBuZXZlclxuICAgKiBleHBpcmUpLiBJZiBgZXhwaXJlc2AgaXMgZ3JlYXRlciB0aGFuIDMwIGRheXMgKDYwIHggNjAgeCAyNCB4IDMwKSwgaXQgaXNcbiAgICogdHJlYXRlZCBhcyBhIFVOSVggdGltZSAobnVtYmVyIG9mIHNlY29uZHMgc2luY2UgSmFudWFyeSAxLCAxOTcwKS5cbiAgICogKiBgbG9nZ2VyYCAtIGEgbG9nZ2VyIG9iamVjdCB0aGF0IHJlc3BvbmRzIHRvIGBsb2coc3RyaW5nKWAgbWV0aG9kIGNhbGxzLlxuICAgKlxuICAgKiAgIH5+fn5cbiAgICogICAgIGxvZyhtc2cxWywgbXNnMlssIG1zZzNbLi4uXV1dKVxuICAgKiAgIH5+fn5cbiAgICpcbiAgICogICBEZWZhdWx0cyB0byBgY29uc29sZWAuXG4gICAqICogYHNlcmlhbGl6ZXJgIC0gdGhlIG9iamVjdCB3aGljaCB3aWxsIChkZSlzZXJpYWxpemUgdGhlIGRhdGEuIEl0IG5lZWRzXG4gICAqICAgdHdvIHB1YmxpYyBtZXRob2RzOiBzZXJpYWxpemUgYW5kIGRlc2VyaWFsaXplLiBJdCBkZWZhdWx0cyB0byB0aGVcbiAgICogICBub29wU2VyaWFsaXplcjpcbiAgICpcbiAgICogICB+fn5+XG4gICAqICAgY29uc3Qgbm9vcFNlcmlhbGl6ZXIgPSB7XG4gICAqICAgICBzZXJpYWxpemU6IGZ1bmN0aW9uIChvcGNvZGUsIHZhbHVlLCBleHRyYXMpIHtcbiAgICogICAgICAgcmV0dXJuIHsgdmFsdWU6IHZhbHVlLCBleHRyYXM6IGV4dHJhcyB9O1xuICAgKiAgICAgfSxcbiAgICogICAgIGRlc2VyaWFsaXplOiBmdW5jdGlvbiAob3Bjb2RlLCB2YWx1ZSwgZXh0cmFzKSB7XG4gICAqICAgICAgIHJldHVybiB7IHZhbHVlOiB2YWx1ZSwgZXh0cmFzOiBleHRyYXMgfTtcbiAgICogICAgIH1cbiAgICogICB9O1xuICAgKiAgIH5+fn5cbiAgICpcbiAgICogT3Igb3B0aW9ucyBmb3IgdGhlIHNlcnZlcnMgaW5jbHVkaW5nOlxuICAgKiAqIGB1c2VybmFtZWAgYW5kIGBwYXNzd29yZGAgZm9yIGZhbGxiYWNrIFNBU0wgYXV0aGVudGljYXRpb24gY3JlZGVudGlhbHMuXG4gICAqICogYHRpbWVvdXRgIGluIHNlY29uZHMgdG8gZGV0ZXJtaW5lIGZhaWx1cmUgZm9yIG9wZXJhdGlvbnMuIERlZmF1bHQgaXMgMC41XG4gICAqICAgICAgICAgICAgIHNlY29uZHMuXG4gICAqICogJ2Nvbm50aW1lb3V0JyBpbiBzZWNvbmRzIHRvIGNvbm5lY3Rpb24gZmFpbHVyZS4gRGVmYXVsdCBpcyB0d2ljZSB0aGUgdmFsdWVcbiAgICogICAgICAgICAgICAgICAgIG9mIGB0aW1lb3V0YC5cbiAgICogKiBga2VlcEFsaXZlYCB3aGV0aGVyIHRvIGVuYWJsZSBrZWVwLWFsaXZlIGZ1bmN0aW9uYWxpdHkuIERlZmF1bHRzIHRvIGZhbHNlLlxuICAgKiAqIGBrZWVwQWxpdmVEZWxheWAgaW4gc2Vjb25kcyB0byB0aGUgaW5pdGlhbCBkZWxheSBiZWZvcmUgdGhlIGZpcnN0IGtlZXBhbGl2ZVxuICAgKiAgICAgICAgICAgICAgICAgICAgcHJvYmUgaXMgc2VudCBvbiBhbiBpZGxlIHNvY2tldC4gRGVmYXVsdHMgaXMgMzAgc2Vjb25kcy5cbiAgICogKiBga2V5VG9TZXJ2ZXJIYXNoRnVuY3Rpb25gIGEgZnVuY3Rpb24gdG8gbWFwIGtleXMgdG8gc2VydmVycywgd2l0aCB0aGUgc2lnbmF0dXJlXG4gICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgIChzZXJ2ZXJLZXlzOiBzdHJpbmdbXSwga2V5OiBzdHJpbmcpOiBzdHJpbmdcbiAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgTk9URTogaWYgeW91IG5lZWQgdG8gZG8gc29tZSBleHBlbnNpdmUgaW5pdGlhbGl6YXRpb24sICpwbGVhc2UqIGRvIGl0IGxhemlseSB0aGUgZmlyc3QgdGltZSB5b3UgdGhpcyBmdW5jdGlvbiBpcyBjYWxsZWQgd2l0aCBhbiBhcnJheSBvZiBzZXJ2ZXJLZXlzLCBub3Qgb24gZXZlcnkgY2FsbFxuICAgKi9cbiAgc3RhdGljIGNyZWF0ZTxWYWx1ZSwgRXh0cmFzPihcbiAgICBzZXJ2ZXJzU3RyOiBzdHJpbmcgfCB1bmRlZmluZWQsXG4gICAgb3B0aW9uczogSWZCdWZmZXI8XG4gICAgICBWYWx1ZSxcbiAgICAgIEV4dHJhcyxcbiAgICAgIHVuZGVmaW5lZCB8IChQYXJ0aWFsPFNlcnZlck9wdGlvbnM+ICYgR2l2ZW5DbGllbnRPcHRpb25zPFZhbHVlLCBFeHRyYXM+KSxcbiAgICAgIFBhcnRpYWw8U2VydmVyT3B0aW9ucz4gJiBHaXZlbkNsaWVudE9wdGlvbnM8VmFsdWUsIEV4dHJhcz5cbiAgICA+XG4gICk6IENsaWVudDxWYWx1ZSwgRXh0cmFzPiB7XG4gICAgc2VydmVyc1N0ciA9XG4gICAgICBzZXJ2ZXJzU3RyIHx8XG4gICAgICBwcm9jZXNzLmVudi5NRU1DQUNISUVSX1NFUlZFUlMgfHxcbiAgICAgIHByb2Nlc3MuZW52Lk1FTUNBQ0hFX1NFUlZFUlMgfHxcbiAgICAgIFwibG9jYWxob3N0OjExMjExXCI7XG4gICAgY29uc3Qgc2VydmVyVXJpcyA9IHNlcnZlcnNTdHIuc3BsaXQoXCIsXCIpO1xuICAgIGNvbnN0IHNlcnZlcnMgPSBzZXJ2ZXJVcmlzLm1hcChmdW5jdGlvbiAodXJpKSB7XG4gICAgICBjb25zdCB1cmlQYXJ0cyA9IHVyaS5zcGxpdChcIkBcIik7XG4gICAgICBjb25zdCBob3N0UG9ydCA9IHVyaVBhcnRzW3VyaVBhcnRzLmxlbmd0aCAtIDFdLnNwbGl0KFwiOlwiKTtcbiAgICAgIGNvbnN0IHVzZXJQYXNzID0gKHVyaVBhcnRzW3VyaVBhcnRzLmxlbmd0aCAtIDJdIHx8IFwiXCIpLnNwbGl0KFwiOlwiKTtcbiAgICAgIHJldHVybiBuZXcgU2VydmVyKFxuICAgICAgICBob3N0UG9ydFswXSxcbiAgICAgICAgcGFyc2VJbnQoaG9zdFBvcnRbMV0gfHwgXCIxMTIxMVwiLCAxMCksXG4gICAgICAgIHVzZXJQYXNzWzBdLFxuICAgICAgICB1c2VyUGFzc1sxXSxcbiAgICAgICAgb3B0aW9uc1xuICAgICAgKTtcbiAgICB9KTtcbiAgICByZXR1cm4gbmV3IENsaWVudChzZXJ2ZXJzLCBvcHRpb25zIGFzIGFueSk7XG4gIH1cblxuICAvKipcbiAgICogR2l2ZW4gYSBzZXJ2ZXJLZXkgZnJvbWxvb2t1cEtleVRvU2VydmVyS2V5LCByZXR1cm4gdGhlIGNvcnJlc3BvbmRpbmcgU2VydmVyIGluc3RhbmNlXG4gICAqXG4gICAqIEBwYXJhbSAge3N0cmluZ30gc2VydmVyS2V5XG4gICAqIEByZXR1cm5zIHtTZXJ2ZXJ9XG4gICAqL1xuICBzZXJ2ZXJLZXlUb1NlcnZlcihzZXJ2ZXJLZXk6IHN0cmluZyk6IFNlcnZlciB7XG4gICAgcmV0dXJuIHRoaXMuc2VydmVyTWFwW3NlcnZlcktleV07XG4gIH1cblxuICAvKipcbiAgICogR2l2ZW4gYSBrZXkgdG8gbG9vayB1cCBpbiBtZW1jYWNoZSwgcmV0dXJuIGEgc2VydmVyS2V5IChiYXNlZCBvbiBzb21lXG4gICAqIGhhc2hpbmcgZnVuY3Rpb24pIHdoaWNoIGNhbiBiZSB1c2VkIHRvIGluZGV4IHRoaXMuc2VydmVyTWFwXG4gICAqL1xuICBsb29rdXBLZXlUb1NlcnZlcktleShrZXk6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMub3B0aW9ucy5rZXlUb1NlcnZlckhhc2hGdW5jdGlvbih0aGlzLnNlcnZlcktleXMsIGtleSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldmVzIHRoZSB2YWx1ZSBhdCB0aGUgZ2l2ZW4ga2V5IGluIG1lbWNhY2hlLlxuICAgKi9cbiAgYXN5bmMgZ2V0KGtleTogc3RyaW5nKTogUHJvbWlzZTxHZXRSZXN1bHQ8VmFsdWUsIEV4dHJhcz4gfCBudWxsPiB7XG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKGNvbnN0YW50cy5PUF9HRVQsIGtleSwgXCJcIiwgXCJcIiwgdGhpcy5zZXEpO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICBjb25zdCBkZXNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuZGVzZXJpYWxpemUoXG4gICAgICAgICAgcmVzcG9uc2UuaGVhZGVyLm9wY29kZSxcbiAgICAgICAgICByZXNwb25zZS52YWwsXG4gICAgICAgICAgcmVzcG9uc2UuZXh0cmFzXG4gICAgICAgICk7XG4gICAgICAgIHJldHVybiB7IC4uLmRlc2VyaWFsaXplZCwgY2FzOiByZXNwb25zZS5oZWFkZXIuY2FzIH07XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIkdFVFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKiogQnVpbGQgYSBwaXBlbGluZWQgZ2V0IG11bHRpIHJlcXVlc3QgYnkgc2VuZGluZyBvbmUgR0VUS1EgZm9yIGVhY2gga2V5IChxdWlldCwgbWVhbmluZyBpdCB3b24ndCByZXNwb25kIGlmIHRoZSB2YWx1ZSBpcyBtaXNzaW5nKSBmb2xsb3dlZCBieSBhIG5vLW9wIHRvIGZvcmNlIGEgcmVzcG9uc2UgKGFuZCB0byBnaXZlIHVzIGEgc2VudGluZWwgcmVzcG9uc2UgdGhhdCB0aGUgcGlwZWxpbmUgaXMgZG9uZSlcbiAgICpcbiAgICogY2YgaHR0cHM6Ly9naXRodWIuY29tL2NvdWNoYmFzZS9tZW1jYWNoZWQvYmxvYi9tYXN0ZXIvZG9jcy9CaW5hcnlQcm90b2NvbC5tZCMweDBkLWdldGtxLWdldC13aXRoLWtleS1xdWlldGx5XG4gICAqL1xuICBfYnVpbGRHZXRNdWx0aVJlcXVlc3Qoa2V5czogc3RyaW5nW10sIHNlcTogbnVtYmVyKTogQnVmZmVyIHtcbiAgICAvLyBzdGFydCBhdCAyNCBmb3IgdGhlIG5vLW9wIGNvbW1hbmQgYXQgdGhlIGVuZFxuICAgIGxldCByZXF1ZXN0U2l6ZSA9IDI0O1xuICAgIGZvciAoY29uc3Qga2V5SWR4IGluIGtleXMpIHtcbiAgICAgIHJlcXVlc3RTaXplICs9IEJ1ZmZlci5ieXRlTGVuZ3RoKGtleXNba2V5SWR4XSwgXCJ1dGY4XCIpICsgMjQ7XG4gICAgfVxuXG4gICAgY29uc3QgcmVxdWVzdCA9IEJ1ZmZlci5hbGxvYyhyZXF1ZXN0U2l6ZSk7XG5cbiAgICBsZXQgYnl0ZXNXcml0dGVuID0gMDtcbiAgICBmb3IgKGNvbnN0IGtleUlkeCBpbiBrZXlzKSB7XG4gICAgICBjb25zdCBrZXkgPSBrZXlzW2tleUlkeF07XG4gICAgICBieXRlc1dyaXR0ZW4gKz0gY29weUludG9SZXF1ZXN0QnVmZmVyKFxuICAgICAgICBjb25zdGFudHMuT1BfR0VUS1EsXG4gICAgICAgIGtleSxcbiAgICAgICAgXCJcIixcbiAgICAgICAgXCJcIixcbiAgICAgICAgc2VxLFxuICAgICAgICByZXF1ZXN0LFxuICAgICAgICBieXRlc1dyaXR0ZW5cbiAgICAgICk7XG4gICAgfVxuXG4gICAgYnl0ZXNXcml0dGVuICs9IGNvcHlJbnRvUmVxdWVzdEJ1ZmZlcihcbiAgICAgIGNvbnN0YW50cy5PUF9OT19PUCxcbiAgICAgIFwiXCIsXG4gICAgICBcIlwiLFxuICAgICAgXCJcIixcbiAgICAgIHNlcSxcbiAgICAgIHJlcXVlc3QsXG4gICAgICBieXRlc1dyaXR0ZW5cbiAgICApO1xuXG4gICAgcmV0dXJuIHJlcXVlc3Q7XG4gIH1cblxuICAvKiogRXhlY3V0aW5nIGEgcGlwZWxpbmVkIChtdWx0aSkgZ2V0IGFnYWluc3QgYSBzaW5nbGUgc2VydmVyLiBUaGlzIGlzIGEgcHJpdmF0ZSBpbXBsZW1lbnRhdGlvbiBkZXRhaWwgb2YgZ2V0TXVsdGkuICovXG4gIGFzeW5jIF9nZXRNdWx0aVRvU2VydmVyPEtleXMgZXh0ZW5kcyBzdHJpbmc+KFxuICAgIHNlcnY6IFNlcnZlcixcbiAgICBrZXlzOiBLZXlzW11cbiAgKTogUHJvbWlzZTxHZXRNdWx0aVJlc3VsdDxLZXlzLCBWYWx1ZSwgRXh0cmFzPj4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBjb25zdCByZXNwb25zZU1hcDogR2V0TXVsdGlSZXN1bHQ8c3RyaW5nLCBWYWx1ZSwgRXh0cmFzPiA9IHt9O1xuXG4gICAgICBjb25zdCBoYW5kbGU6IE9uUmVzcG9uc2VDYWxsYmFjayA9IChyZXNwb25zZSkgPT4ge1xuICAgICAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgICAgICAvLyBXaGVuIHdlIGdldCB0aGUgbm8tb3AgcmVzcG9uc2UsIHdlIGFyZSBkb25lIHdpdGggdGhpcyBvbmUgZ2V0TXVsdGkgaW4gdGhlIHBlci1iYWNrZW5kIGZhbi1vdXRcbiAgICAgICAgICAgIGlmIChyZXNwb25zZS5oZWFkZXIub3Bjb2RlID09PSBjb25zdGFudHMuT1BfTk9fT1ApIHtcbiAgICAgICAgICAgICAgLy8gVGhpcyBlbnN1cmVzIHRoZSBoYW5kbGVyIHdpbGwgYmUgZGVsZXRlZCBmcm9tIHRoZSByZXNwb25zZUNhbGxiYWNrcyBtYXAgaW4gc2VydmVyLmpzXG4gICAgICAgICAgICAgIC8vIFRoaXMgaXNuJ3QgdGVjaG5pY2FsbHkgbmVlZGVkIGhlcmUgYmVjYXVzZSB0aGUgbG9naWMgaW4gc2VydmVyLmpzIGFsc28gY2hlY2tzIGlmIHRvdGFsQm9keUxlbmd0aCA9PT0gMCwgYnV0IG91ciB1bml0dGVzdHMgYXJlbid0IGdyZWF0IGFib3V0IHNldHRpbmcgdGhhdCBmaWVsZCwgYW5kIGFsc28gdGhpcyBtYWtlcyBpdCBtb3JlIGV4cGxpY2l0XG4gICAgICAgICAgICAgIGhhbmRsZS5xdWlldCA9IGZhbHNlO1xuICAgICAgICAgICAgICByZXNvbHZlKHJlc3BvbnNlTWFwKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgICAgICAgIHJlc3BvbnNlLmhlYWRlci5vcGNvZGUgPT09IGNvbnN0YW50cy5PUF9HRVRLIHx8XG4gICAgICAgICAgICAgIHJlc3BvbnNlLmhlYWRlci5vcGNvZGUgPT09IGNvbnN0YW50cy5PUF9HRVRLUVxuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgIGNvbnN0IGRlc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5kZXNlcmlhbGl6ZShcbiAgICAgICAgICAgICAgICByZXNwb25zZS5oZWFkZXIub3Bjb2RlLFxuICAgICAgICAgICAgICAgIHJlc3BvbnNlLnZhbCxcbiAgICAgICAgICAgICAgICByZXNwb25zZS5leHRyYXNcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgY29uc3Qga2V5ID0gcmVzcG9uc2Uua2V5LnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgIGlmIChrZXkubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlamVjdChcbiAgICAgICAgICAgICAgICAgIG5ldyBFcnJvcihcbiAgICAgICAgICAgICAgICAgICAgXCJSZWNpZXZlZCBlbXB0eSBrZXkgaW4gZ2V0TXVsdGk6IFwiICtcbiAgICAgICAgICAgICAgICAgICAgICBKU09OLnN0cmluZ2lmeShyZXNwb25zZSlcbiAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIHJlc3BvbnNlTWFwW2tleV0gPSB7IC4uLmRlc2VyaWFsaXplZCwgY2FzOiByZXNwb25zZS5oZWFkZXIuY2FzIH07XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICByZXR1cm4gcmVqZWN0KFxuICAgICAgICAgICAgICAgIG5ldyBFcnJvcihcbiAgICAgICAgICAgICAgICAgIFwiUmVjaWV2ZWQgcmVzcG9uc2UgaW4gZ2V0TXVsdGkgZm9yIHVua25vd24gb3Bjb2RlOiBcIiArXG4gICAgICAgICAgICAgICAgICAgIEpTT04uc3RyaW5naWZ5KHJlc3BvbnNlKVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICByZXR1cm4gcmVqZWN0KFxuICAgICAgICAgICAgICB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiR0VUXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9O1xuICAgICAgLy8gVGhpcyBwcmV2ZW50cyB0aGUgaGFuZGxlciBmcm9tIGJlaW5nIGRlbGV0ZWRcbiAgICAgIC8vIGFmdGVyIHRoZSBmaXJzdCByZXNwb25zZS4gTG9naWMgaW4gc2VydmVyLmpzLlxuICAgICAgaGFuZGxlLnF1aWV0ID0gdHJ1ZTtcblxuICAgICAgY29uc3Qgc2VxID0gdGhpcy5pbmNyU2VxKCk7XG4gICAgICBjb25zdCByZXF1ZXN0ID0gdGhpcy5fYnVpbGRHZXRNdWx0aVJlcXVlc3Qoa2V5cywgc2VxKTtcbiAgICAgIHNlcnYub25SZXNwb25zZSh0aGlzLnNlcSwgaGFuZGxlKTtcbiAgICAgIHNlcnYub25FcnJvcih0aGlzLnNlcSwgcmVqZWN0KTtcbiAgICAgIHNlcnYud3JpdGUocmVxdWVzdCk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldnMgdGhlIHZhbHVlIGF0IHRoZSBnaXZlbiBrZXlzIGluIG1lbWNhY2hlZC4gUmV0dXJucyBhIG1hcCBmcm9tIHRoZVxuICAgKiByZXF1ZXN0ZWQga2V5cyB0byByZXN1bHRzLCBvciBudWxsIGlmIHRoZSBrZXkgd2FzIG5vdCBmb3VuZC5cbiAgICovXG4gIGFzeW5jIGdldE11bHRpPEtleXMgZXh0ZW5kcyBzdHJpbmc+KFxuICAgIGtleXM6IEtleXNbXVxuICApOiBQcm9taXNlPEdldE11bHRpUmVzdWx0PEtleXMsIFZhbHVlLCBFeHRyYXM+PiB7XG4gICAgY29uc3Qgc2VydmVyS2V5dG9Mb29rdXBLZXlzOiB7XG4gICAgICBbc2VydmVyS2V5OiBzdHJpbmddOiBzdHJpbmdbXTtcbiAgICB9ID0ge307XG4gICAga2V5cy5mb3JFYWNoKChsb29rdXBLZXkpID0+IHtcbiAgICAgIGNvbnN0IHNlcnZlcktleSA9IHRoaXMubG9va3VwS2V5VG9TZXJ2ZXJLZXkobG9va3VwS2V5KTtcbiAgICAgIGlmICghc2VydmVyS2V5dG9Mb29rdXBLZXlzW3NlcnZlcktleV0pIHtcbiAgICAgICAgc2VydmVyS2V5dG9Mb29rdXBLZXlzW3NlcnZlcktleV0gPSBbXTtcbiAgICAgIH1cbiAgICAgIHNlcnZlcktleXRvTG9va3VwS2V5c1tzZXJ2ZXJLZXldLnB1c2gobG9va3VwS2V5KTtcbiAgICB9KTtcblxuICAgIGNvbnN0IHVzZWRTZXJ2ZXJLZXlzID0gT2JqZWN0LmtleXMoc2VydmVyS2V5dG9Mb29rdXBLZXlzKTtcbiAgICBjb25zdCByZXN1bHRzID0gYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICB1c2VkU2VydmVyS2V5cy5tYXAoKHNlcnZlcktleSkgPT4ge1xuICAgICAgICBjb25zdCBzZXJ2ZXIgPSB0aGlzLnNlcnZlcktleVRvU2VydmVyKHNlcnZlcktleSk7XG4gICAgICAgIHJldHVybiB0aGlzLl9nZXRNdWx0aVRvU2VydmVyKHNlcnZlciwgc2VydmVyS2V5dG9Mb29rdXBLZXlzW3NlcnZlcktleV0pO1xuICAgICAgfSlcbiAgICApO1xuXG4gICAgcmV0dXJuIE9iamVjdC5hc3NpZ24oe30sIC4uLnJlc3VsdHMpO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgYGtleWAgdG8gYHZhbHVlYC5cbiAgICovXG4gIGFzeW5jIHNldChcbiAgICBrZXk6IHN0cmluZyxcbiAgICB2YWx1ZTogVmFsdWUsXG4gICAgb3B0aW9ucz86IHsgZXhwaXJlcz86IG51bWJlcjsgY2FzPzogQ0FTVG9rZW4gfVxuICApOiBQcm9taXNlPGJvb2xlYW4gfCBudWxsPiB7XG4gICAgY29uc3QgZXhwaXJlcyA9IG9wdGlvbnM/LmV4cGlyZXM7XG4gICAgY29uc3QgY2FzID0gb3B0aW9ucz8uY2FzO1xuXG4gICAgLy8gVE9ETzogc3VwcG9ydCBmbGFnc1xuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IGV4cGlyYXRpb24gPSBtYWtlRXhwaXJhdGlvbihleHBpcmVzIHx8IHRoaXMub3B0aW9ucy5leHBpcmVzKTtcbiAgICBjb25zdCBleHRyYXMgPSBCdWZmZXIuY29uY2F0KFtCdWZmZXIuZnJvbShcIjAwMDAwMDAwXCIsIFwiaGV4XCIpLCBleHBpcmF0aW9uXSk7XG4gICAgY29uc3Qgc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5zZXJpYWxpemUoXG4gICAgICBjb25zdGFudHMuT1BfU0VULFxuICAgICAgdmFsdWUsXG4gICAgICBleHRyYXNcbiAgICApO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBVdGlscy5lbmNvZGVSZXF1ZXN0KHtcbiAgICAgIGhlYWRlcjoge1xuICAgICAgICBvcGNvZGU6IGNvbnN0YW50cy5PUF9TRVQsXG4gICAgICAgIG9wYXF1ZTogdGhpcy5zZXEsXG4gICAgICAgIGNhcyxcbiAgICAgIH0sXG4gICAgICBrZXksXG4gICAgICB2YWx1ZTogc2VyaWFsaXplZC52YWx1ZSxcbiAgICAgIGV4dHJhczogc2VyaWFsaXplZC5leHRyYXMsXG4gICAgfSk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfRVhJU1RTOlxuICAgICAgICBpZiAoY2FzKSB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJTRVRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgICAgIH1cbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJTRVRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEFERFxuICAgKlxuICAgKiBBZGRzIHRoZSBnaXZlbiBfa2V5XyBhbmQgX3ZhbHVlXyB0byBtZW1jYWNoZS4gVGhlIG9wZXJhdGlvbiBvbmx5IHN1Y2NlZWRzXG4gICAqIGlmIHRoZSBrZXkgaXMgbm90IGFscmVhZHkgc2V0LlxuICAgKlxuICAgKiBUaGUgb3B0aW9ucyBkaWN0aW9uYXJ5IHRha2VzOlxuICAgKiAqIF9leHBpcmVzXzogb3ZlcnJpZGVzIHRoZSBkZWZhdWx0IGV4cGlyYXRpb24gKHNlZSBgQ2xpZW50LmNyZWF0ZWApIGZvciB0aGlzXG4gICAqICAgICAgICAgICAgICBwYXJ0aWN1bGFyIGtleS12YWx1ZSBwYWlyLlxuICAgKi9cbiAgYXN5bmMgYWRkKFxuICAgIGtleTogc3RyaW5nLFxuICAgIHZhbHVlOiBWYWx1ZSxcbiAgICBvcHRpb25zPzogeyBleHBpcmVzPzogbnVtYmVyIH1cbiAgKTogUHJvbWlzZTxib29sZWFuIHwgbnVsbD4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgZmxhZ3MsIHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IGV4cGlyYXRpb24gPSBtYWtlRXhwaXJhdGlvbihvcHRpb25zPy5leHBpcmVzIHx8IHRoaXMub3B0aW9ucy5leHBpcmVzKTtcbiAgICBjb25zdCBleHRyYXMgPSBCdWZmZXIuY29uY2F0KFtCdWZmZXIuZnJvbShcIjAwMDAwMDAwXCIsIFwiaGV4XCIpLCBleHBpcmF0aW9uXSk7XG5cbiAgICBjb25zdCBvcGNvZGUgPSBjb25zdGFudHMuT1BfQUREO1xuICAgIGNvbnN0IHNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuc2VyaWFsaXplKG9wY29kZSwgdmFsdWUsIGV4dHJhcyk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKFxuICAgICAgb3Bjb2RlLFxuICAgICAga2V5LFxuICAgICAgc2VyaWFsaXplZC5leHRyYXMsXG4gICAgICBzZXJpYWxpemVkLnZhbHVlLFxuICAgICAgdGhpcy5zZXFcbiAgICApO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuS0VZX0VYSVNUUzpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJBRERcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlcGxhY2VzIHRoZSBnaXZlbiBfa2V5XyBhbmQgX3ZhbHVlXyB0byBtZW1jYWNoZS4gVGhlIG9wZXJhdGlvbiBvbmx5IHN1Y2NlZWRzXG4gICAqIGlmIHRoZSBrZXkgaXMgYWxyZWFkeSBwcmVzZW50LlxuICAgKi9cbiAgYXN5bmMgcmVwbGFjZShcbiAgICBrZXk6IHN0cmluZyxcbiAgICB2YWx1ZTogVmFsdWUsXG4gICAgb3B0aW9ucz86IHsgZXhwaXJlcz86IG51bWJlciB9XG4gICk6IFByb21pc2U8Ym9vbGVhbiB8IG51bGw+IHtcbiAgICAvLyBUT0RPOiBzdXBwb3J0IGZsYWdzLCBzdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBleHBpcmF0aW9uID0gbWFrZUV4cGlyYXRpb24ob3B0aW9ucz8uZXhwaXJlcyB8fCB0aGlzLm9wdGlvbnMuZXhwaXJlcyk7XG4gICAgY29uc3QgZXh0cmFzID0gQnVmZmVyLmNvbmNhdChbQnVmZmVyLmZyb20oXCIwMDAwMDAwMFwiLCBcImhleFwiKSwgZXhwaXJhdGlvbl0pO1xuXG4gICAgY29uc3Qgb3Bjb2RlOiBjb25zdGFudHMuT1AgPSBjb25zdGFudHMuT1BfUkVQTEFDRTtcbiAgICBjb25zdCBzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLnNlcmlhbGl6ZShvcGNvZGUsIHZhbHVlLCBleHRyYXMpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgIG9wY29kZSxcbiAgICAgIGtleSxcbiAgICAgIHNlcmlhbGl6ZWQuZXh0cmFzLFxuICAgICAgc2VyaWFsaXplZC52YWx1ZSxcbiAgICAgIHRoaXMuc2VxXG4gICAgKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJSRVBMQUNFXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBEZWxldGVzIHRoZSBnaXZlbiBfa2V5XyBmcm9tIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHNcbiAgICogaWYgdGhlIGtleSBpcyBhbHJlYWR5IHByZXNlbnQuXG4gICAqL1xuICBhc3luYyBkZWxldGUoa2V5OiBzdHJpbmcpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAvLyBUT0RPOiBTdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoNCwga2V5LCBcIlwiLCBcIlwiLCB0aGlzLnNlcSk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG5cbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJERUxFVEVcIiwgcmVzcG9uc2U/LmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBJbmNyZW1lbnRzIHRoZSBnaXZlbiBfa2V5XyBpbiBtZW1jYWNoZS5cbiAgICovXG4gIGFzeW5jIGluY3JlbWVudChcbiAgICBrZXk6IHN0cmluZyxcbiAgICBhbW91bnQ6IG51bWJlcixcbiAgICBvcHRpb25zPzogeyBpbml0aWFsPzogbnVtYmVyOyBleHBpcmVzPzogbnVtYmVyIH1cbiAgKTogUHJvbWlzZTx7IHZhbHVlOiBudW1iZXIgfCBudWxsOyBzdWNjZXNzOiBib29sZWFuIHwgbnVsbCB9PiB7XG4gICAgLy8gVE9ETzogc3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgaW5pdGlhbCA9IG9wdGlvbnM/LmluaXRpYWwgfHwgMDtcbiAgICBjb25zdCBleHBpcmVzID0gb3B0aW9ucz8uZXhwaXJlcyB8fCB0aGlzLm9wdGlvbnMuZXhwaXJlcztcbiAgICBjb25zdCBleHRyYXMgPSBtYWtlQW1vdW50SW5pdGlhbEFuZEV4cGlyYXRpb24oYW1vdW50LCBpbml0aWFsLCBleHBpcmVzKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICBjb25zdGFudHMuT1BfSU5DUkVNRU5ULFxuICAgICAga2V5LFxuICAgICAgZXh0cmFzLFxuICAgICAgXCJcIixcbiAgICAgIHRoaXMuc2VxXG4gICAgKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgY29uc3QgYnVmSW50ID1cbiAgICAgICAgICAocmVzcG9uc2UudmFsLnJlYWRVSW50MzJCRSgwKSA8PCA4KSArIHJlc3BvbnNlLnZhbC5yZWFkVUludDMyQkUoNCk7XG4gICAgICAgIHJldHVybiB7IHZhbHVlOiBidWZJbnQsIHN1Y2Nlc3M6IHRydWUgfTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJJTkNSRU1FTlRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIERlY3JlbWVudHMgdGhlIGdpdmVuIGBrZXlgIGluIG1lbWNhY2hlLlxuICAgKi9cbiAgYXN5bmMgZGVjcmVtZW50KFxuICAgIGtleTogc3RyaW5nLFxuICAgIGFtb3VudDogbnVtYmVyLFxuICAgIG9wdGlvbnM6IHsgaW5pdGlhbD86IG51bWJlcjsgZXhwaXJlcz86IG51bWJlciB9XG4gICk6IFByb21pc2U8eyB2YWx1ZTogbnVtYmVyIHwgbnVsbDsgc3VjY2VzczogYm9vbGVhbiB8IG51bGwgfT4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IGluaXRpYWwgPSBvcHRpb25zLmluaXRpYWwgfHwgMDtcbiAgICBjb25zdCBleHBpcmVzID0gb3B0aW9ucy5leHBpcmVzIHx8IHRoaXMub3B0aW9ucy5leHBpcmVzO1xuICAgIGNvbnN0IGV4dHJhcyA9IG1ha2VBbW91bnRJbml0aWFsQW5kRXhwaXJhdGlvbihhbW91bnQsIGluaXRpYWwsIGV4cGlyZXMpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgIGNvbnN0YW50cy5PUF9ERUNSRU1FTlQsXG4gICAgICBrZXksXG4gICAgICBleHRyYXMsXG4gICAgICBcIlwiLFxuICAgICAgdGhpcy5zZXFcbiAgICApO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICBjb25zdCBidWZJbnQgPVxuICAgICAgICAgIChyZXNwb25zZS52YWwucmVhZFVJbnQzMkJFKDApIDw8IDgpICsgcmVzcG9uc2UudmFsLnJlYWRVSW50MzJCRSg0KTtcbiAgICAgICAgcmV0dXJuIHsgdmFsdWU6IGJ1ZkludCwgc3VjY2VzczogdHJ1ZSB9O1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIkRFQ1JFTUVOVFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQXBwZW5kIHRoZSBnaXZlbiBfdmFsdWVfIHRvIHRoZSB2YWx1ZSBhc3NvY2lhdGVkIHdpdGggdGhlIGdpdmVuIF9rZXlfIGluXG4gICAqIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHMgaWYgdGhlIGtleSBpcyBhbHJlYWR5IHByZXNlbnQuXG4gICAqL1xuICBhc3luYyBhcHBlbmQoa2V5OiBzdHJpbmcsIHZhbHVlOiBWYWx1ZSk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IG9wY29kZTogY29uc3RhbnRzLk9QID0gY29uc3RhbnRzLk9QX0FQUEVORDtcbiAgICBjb25zdCBzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLnNlcmlhbGl6ZShvcGNvZGUsIHZhbHVlLCBcIlwiKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICBvcGNvZGUsXG4gICAgICBrZXksXG4gICAgICBzZXJpYWxpemVkLmV4dHJhcyxcbiAgICAgIHNlcmlhbGl6ZWQudmFsdWUsXG4gICAgICB0aGlzLnNlcVxuICAgICk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfTk9UX0ZPVU5EOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiQVBQRU5EXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBQcmVwZW5kIHRoZSBnaXZlbiBfdmFsdWVfIHRvIHRoZSB2YWx1ZSBhc3NvY2lhdGVkIHdpdGggdGhlIGdpdmVuIF9rZXlfIGluXG4gICAqIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHMgaWYgdGhlIGtleSBpcyBhbHJlYWR5IHByZXNlbnQuXG4gICAqL1xuICBhc3luYyBwcmVwZW5kKGtleTogc3RyaW5nLCB2YWx1ZTogVmFsdWUpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAvLyBUT0RPOiBzdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBvcGNvZGU6IGNvbnN0YW50cy5PUCA9IGNvbnN0YW50cy5PUF9QUkVQRU5EO1xuICAgIGNvbnN0IHNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuc2VyaWFsaXplKG9wY29kZSwgdmFsdWUsIFwiXCIpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgIG9wY29kZSxcbiAgICAgIGtleSxcbiAgICAgIHNlcmlhbGl6ZWQuZXh0cmFzLFxuICAgICAgc2VyaWFsaXplZC52YWx1ZSxcbiAgICAgIHRoaXMuc2VxXG4gICAgKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJQUkVQRU5EXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBUb3VjaCBzZXRzIGFuIGV4cGlyYXRpb24gdmFsdWUsIGdpdmVuIGJ5IF9leHBpcmVzXywgb24gdGhlIGdpdmVuIF9rZXlfIGluXG4gICAqIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHMgaWYgdGhlIGtleSBpcyBhbHJlYWR5IHByZXNlbnQuXG4gICAqL1xuICBhc3luYyB0b3VjaChrZXk6IHN0cmluZywgZXhwaXJlczogbnVtYmVyKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgLy8gVE9ETzogc3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgZXh0cmFzID0gbWFrZUV4cGlyYXRpb24oZXhwaXJlcyB8fCB0aGlzLm9wdGlvbnMuZXhwaXJlcyk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKDB4MWMsIGtleSwgZXh0cmFzLCBcIlwiLCB0aGlzLnNlcSk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfTk9UX0ZPVU5EOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiVE9VQ0hcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEZMVVNIXG4gICAqXG4gICAqIEZsdXNoZXMgdGhlIGNhY2hlIG9uIGVhY2ggY29ubmVjdGVkIHNlcnZlci4gVGhlIGNhbGxiYWNrIHNpZ25hdHVyZSBpczpcbiAgICpcbiAgICogICAgIGNhbGxiYWNrKGxhc3RFcnIsIHJlc3VsdHMpXG4gICAqXG4gICAqIHdoZXJlIF9sYXN0RXJyXyBpcyB0aGUgbGFzdCBlcnJvciBlbmNvdW50ZXJlZCAob3IgbnVsbCwgaW4gdGhlIGNvbW1vbiBjYXNlXG4gICAqIG9mIG5vIGVycm9ycykuIF9yZXN1bHRzXyBpcyBhIGRpY3Rpb25hcnkgbWFwcGluZyBgXCJob3N0bmFtZTpwb3J0XCJgIHRvIGVpdGhlclxuICAgKiBgdHJ1ZWAgKGlmIHRoZSBvcGVyYXRpb24gd2FzIHN1Y2Nlc3NmdWwpLCBvciBhbiBlcnJvci5cbiAgICogQHBhcmFtIGNhbGxiYWNrXG4gICAqL1xuICBmbHVzaCgpOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIGJvb2xlYW4gfCBFcnJvcj4+O1xuICBmbHVzaChcbiAgICBjYWxsYmFjazogKFxuICAgICAgZXJyOiBFcnJvciB8IG51bGwsXG4gICAgICByZXN1bHRzOiBSZWNvcmQ8c3RyaW5nLCBib29sZWFuIHwgRXJyb3I+XG4gICAgKSA9PiB2b2lkXG4gICk6IHZvaWQ7XG4gIGZsdXNoKFxuICAgIGNhbGxiYWNrPzogKFxuICAgICAgZXJyOiBFcnJvciB8IG51bGwsXG4gICAgICByZXN1bHRzOiBSZWNvcmQ8c3RyaW5nLCBib29sZWFuIHwgRXJyb3I+XG4gICAgKSA9PiB2b2lkXG4gICkge1xuICAgIGlmIChjYWxsYmFjayA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm4gcHJvbWlzaWZ5KChjYWxsYmFjaykgPT4ge1xuICAgICAgICB0aGlzLmZsdXNoKGZ1bmN0aW9uIChlcnIsIHJlc3VsdHMpIHtcbiAgICAgICAgICBjYWxsYmFjayhlcnIsIHJlc3VsdHMpO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH1cbiAgICAvLyBUT0RPOiBzdXBwb3J0IGV4cGlyYXRpb25cbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoMHgwOCwgXCJcIiwgXCJcIiwgXCJcIiwgdGhpcy5zZXEpO1xuICAgIGxldCBjb3VudCA9IHRoaXMuc2VydmVycy5sZW5ndGg7XG4gICAgY29uc3QgcmVzdWx0OiBSZWNvcmQ8c3RyaW5nLCBib29sZWFuIHwgRXJyb3I+ID0ge307XG4gICAgbGV0IGxhc3RFcnI6IEVycm9yIHwgbnVsbCA9IG51bGw7XG5cbiAgICBjb25zdCBoYW5kbGVGbHVzaCA9IGZ1bmN0aW9uIChzZXE6IG51bWJlciwgc2VydjogU2VydmVyKSB7XG4gICAgICBzZXJ2Lm9uUmVzcG9uc2Uoc2VxLCBmdW5jdGlvbiAoLyogcmVzcG9uc2UgKi8pIHtcbiAgICAgICAgY291bnQgLT0gMTtcbiAgICAgICAgcmVzdWx0W3NlcnYuaG9zdHBvcnRTdHJpbmcoKV0gPSB0cnVlO1xuICAgICAgICBpZiAoY2FsbGJhY2sgJiYgY291bnQgPT09IDApIHtcbiAgICAgICAgICBjYWxsYmFjayhsYXN0RXJyLCByZXN1bHQpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHNlcnYub25FcnJvcihzZXEsIGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgICAgY291bnQgLT0gMTtcbiAgICAgICAgbGFzdEVyciA9IGVycjtcbiAgICAgICAgcmVzdWx0W3NlcnYuaG9zdHBvcnRTdHJpbmcoKV0gPSBlcnI7XG4gICAgICAgIGlmIChjYWxsYmFjayAmJiBjb3VudCA9PT0gMCkge1xuICAgICAgICAgIGNhbGxiYWNrKGxhc3RFcnIsIHJlc3VsdCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgc2Vydi53cml0ZShyZXF1ZXN0KTtcbiAgICB9O1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnNlcnZlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGhhbmRsZUZsdXNoKHRoaXMuc2VxLCB0aGlzLnNlcnZlcnNbaV0pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTVEFUU19XSVRIX0tFWVxuICAgKlxuICAgKiBTZW5kcyBhIG1lbWNhY2hlIHN0YXRzIGNvbW1hbmQgd2l0aCBhIGtleSB0byBlYWNoIGNvbm5lY3RlZCBzZXJ2ZXIuIFRoZVxuICAgKiBjYWxsYmFjayBpcyBpbnZva2VkICoqT05DRSBQRVIgU0VSVkVSKiogYW5kIGhhcyB0aGUgc2lnbmF0dXJlOlxuICAgKlxuICAgKiAgICAgY2FsbGJhY2soZXJyLCBzZXJ2ZXIsIHN0YXRzKVxuICAgKlxuICAgKiBfc2VydmVyXyBpcyB0aGUgYFwiaG9zdG5hbWU6cG9ydFwiYCBvZiB0aGUgc2VydmVyLCBhbmQgX3N0YXRzXyBpcyBhIGRpY3Rpb25hcnlcbiAgICogbWFwcGluZyB0aGUgc3RhdCBuYW1lIHRvIHRoZSB2YWx1ZSBvZiB0aGUgc3RhdGlzdGljIGFzIGEgc3RyaW5nLlxuICAgKiBAcGFyYW0ga2V5XG4gICAqIEBwYXJhbSBjYWxsYmFja1xuICAgKi9cbiAgc3RhdHNXaXRoS2V5KFxuICAgIGtleTogc3RyaW5nLFxuICAgIGNhbGxiYWNrPzogKFxuICAgICAgZXJyOiBFcnJvciB8IG51bGwsXG4gICAgICBzZXJ2ZXI6IHN0cmluZyxcbiAgICAgIHN0YXRzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+IHwgbnVsbFxuICAgICkgPT4gdm9pZFxuICApOiB2b2lkIHtcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoMHgxMCwga2V5LCBcIlwiLCBcIlwiLCB0aGlzLnNlcSk7XG5cbiAgICBjb25zdCBoYW5kbGVTdGF0cyA9IChzZXE6IG51bWJlciwgc2VydjogU2VydmVyKSA9PiB7XG4gICAgICBjb25zdCByZXN1bHQ6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcbiAgICAgIGNvbnN0IGhhbmRsZTogT25SZXNwb25zZUNhbGxiYWNrID0gKHJlc3BvbnNlKSA9PiB7XG4gICAgICAgIC8vIGVuZCBvZiBzdGF0IHJlc3BvbnNlc1xuICAgICAgICBpZiAocmVzcG9uc2UuaGVhZGVyLnRvdGFsQm9keUxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgICAgY2FsbGJhY2sobnVsbCwgc2Vydi5ob3N0cG9ydFN0cmluZygpLCByZXN1bHQpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgLy8gcHJvY2VzcyBzaW5nbGUgc3RhdCBsaW5lIHJlc3BvbnNlXG4gICAgICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgICAgIHJlc3VsdFtyZXNwb25zZS5rZXkudG9TdHJpbmcoKV0gPSByZXNwb25zZS52YWwudG9TdHJpbmcoKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICBjb25zdCBlcnJvciA9IHRoaXMuaGFuZGxlUmVzcG9uc2VFcnJvcihcbiAgICAgICAgICAgICAgYFNUQVRTICgke2tleX0pYCxcbiAgICAgICAgICAgICAgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyxcbiAgICAgICAgICAgICAgdW5kZWZpbmVkXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgICAgICAgIGNhbGxiYWNrKGVycm9yLCBzZXJ2Lmhvc3Rwb3J0U3RyaW5nKCksIG51bGwpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9O1xuICAgICAgaGFuZGxlLnF1aWV0ID0gdHJ1ZTtcblxuICAgICAgc2Vydi5vblJlc3BvbnNlKHNlcSwgaGFuZGxlKTtcbiAgICAgIHNlcnYub25FcnJvcihzZXEsIGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgICAgY2FsbGJhY2soZXJyLCBzZXJ2Lmhvc3Rwb3J0U3RyaW5nKCksIG51bGwpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHNlcnYud3JpdGUocmVxdWVzdCk7XG4gICAgfTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5zZXJ2ZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBoYW5kbGVTdGF0cyh0aGlzLnNlcSwgdGhpcy5zZXJ2ZXJzW2ldKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU1RBVFNcbiAgICpcbiAgICogRmV0Y2hlcyBtZW1jYWNoZSBzdGF0cyBmcm9tIGVhY2ggY29ubmVjdGVkIHNlcnZlci4gVGhlIGNhbGxiYWNrIGlzIGludm9rZWRcbiAgICogKipPTkNFIFBFUiBTRVJWRVIqKiBhbmQgaGFzIHRoZSBzaWduYXR1cmU6XG4gICAqXG4gICAqICAgICBjYWxsYmFjayhlcnIsIHNlcnZlciwgc3RhdHMpXG4gICAqXG4gICAqIF9zZXJ2ZXJfIGlzIHRoZSBgXCJob3N0bmFtZTpwb3J0XCJgIG9mIHRoZSBzZXJ2ZXIsIGFuZCBfc3RhdHNfIGlzIGFcbiAgICogZGljdGlvbmFyeSBtYXBwaW5nIHRoZSBzdGF0IG5hbWUgdG8gdGhlIHZhbHVlIG9mIHRoZSBzdGF0aXN0aWMgYXMgYSBzdHJpbmcuXG4gICAqIEBwYXJhbSBjYWxsYmFja1xuICAgKi9cbiAgc3RhdHMoXG4gICAgY2FsbGJhY2s/OiAoXG4gICAgICBlcnI6IEVycm9yIHwgbnVsbCxcbiAgICAgIHNlcnZlcjogc3RyaW5nLFxuICAgICAgc3RhdHM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gfCBudWxsXG4gICAgKSA9PiB2b2lkXG4gICk6IHZvaWQge1xuICAgIHRoaXMuc3RhdHNXaXRoS2V5KFwiXCIsIGNhbGxiYWNrKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSRVNFVF9TVEFUU1xuICAgKlxuICAgKiBSZXNldCB0aGUgc3RhdGlzdGljcyBlYWNoIHNlcnZlciBpcyBrZWVwaW5nIGJhY2sgdG8gemVyby4gVGhpcyBkb2Vzbid0IGNsZWFyXG4gICAqIHN0YXRzIHN1Y2ggYXMgaXRlbSBjb3VudCwgYnV0IHRlbXBvcmFyeSBzdGF0cyBzdWNoIGFzIHRvdGFsIG51bWJlciBvZlxuICAgKiBjb25uZWN0aW9ucyBvdmVyIHRpbWUuXG4gICAqXG4gICAqIFRoZSBjYWxsYmFjayBpcyBpbnZva2VkICoqT05DRSBQRVIgU0VSVkVSKiogYW5kIGhhcyB0aGUgc2lnbmF0dXJlOlxuICAgKlxuICAgKiAgICAgY2FsbGJhY2soZXJyLCBzZXJ2ZXIpXG4gICAqXG4gICAqIF9zZXJ2ZXJfIGlzIHRoZSBgXCJob3N0bmFtZTpwb3J0XCJgIG9mIHRoZSBzZXJ2ZXIuXG4gICAqIEBwYXJhbSBjYWxsYmFja1xuICAgKi9cbiAgcmVzZXRTdGF0cyhcbiAgICBjYWxsYmFjaz86IChcbiAgICAgIGVycjogRXJyb3IgfCBudWxsLFxuICAgICAgc2VydmVyOiBzdHJpbmcsXG4gICAgICBzdGF0czogUmVjb3JkPHN0cmluZywgc3RyaW5nPiB8IG51bGxcbiAgICApID0+IHZvaWRcbiAgKTogdm9pZCB7XG4gICAgdGhpcy5zdGF0c1dpdGhLZXkoXCJyZXNldFwiLCBjYWxsYmFjayk7XG4gIH1cblxuICAvKipcbiAgICogUVVJVFxuICAgKlxuICAgKiBDbG9zZXMgdGhlIGNvbm5lY3Rpb24gdG8gZWFjaCBzZXJ2ZXIsIG5vdGlmeWluZyB0aGVtIG9mIHRoaXMgaW50ZW50aW9uLiBOb3RlXG4gICAqIHRoYXQgcXVpdCBjYW4gcmFjZSBhZ2FpbnN0IGFscmVhZHkgb3V0c3RhbmRpbmcgcmVxdWVzdHMgd2hlbiB0aG9zZSByZXF1ZXN0c1xuICAgKiBmYWlsIGFuZCBhcmUgcmV0cmllZCwgbGVhZGluZyB0byB0aGUgcXVpdCBjb21tYW5kIHdpbm5pbmcgYW5kIGNsb3NpbmcgdGhlXG4gICAqIGNvbm5lY3Rpb24gYmVmb3JlIHRoZSByZXRyaWVzIGNvbXBsZXRlLlxuICAgKi9cbiAgcXVpdCgpIHtcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICAvLyBUT0RPOiBOaWNlciBwZXJoYXBzIHRvIGRvIFFVSVRRICgweDE3KSBidXQgbmVlZCBhIG5ldyBjYWxsYmFjayBmb3Igd2hlblxuICAgIC8vIHdyaXRlIGlzIGRvbmUuXG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKDB4MDcsIFwiXCIsIFwiXCIsIFwiXCIsIHRoaXMuc2VxKTsgLy8gUVVJVFxuICAgIGxldCBzZXJ2O1xuXG4gICAgY29uc3QgaGFuZGxlUXVpdCA9IGZ1bmN0aW9uIChzZXE6IG51bWJlciwgc2VydjogU2VydmVyKSB7XG4gICAgICBzZXJ2Lm9uUmVzcG9uc2Uoc2VxLCBmdW5jdGlvbiAoLyogcmVzcG9uc2UgKi8pIHtcbiAgICAgICAgc2Vydi5jbG9zZSgpO1xuICAgICAgfSk7XG4gICAgICBzZXJ2Lm9uRXJyb3Ioc2VxLCBmdW5jdGlvbiAoLyogZXJyICovKSB7XG4gICAgICAgIHNlcnYuY2xvc2UoKTtcbiAgICAgIH0pO1xuICAgICAgc2Vydi53cml0ZShyZXF1ZXN0KTtcbiAgICB9O1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnNlcnZlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHNlcnYgPSB0aGlzLnNlcnZlcnNbaV07XG4gICAgICBoYW5kbGVRdWl0KHRoaXMuc2VxLCBzZXJ2KTtcbiAgICB9XG4gIH1cblxuICBfdmVyc2lvbihzZXJ2ZXI6IFNlcnZlcik6IFByb21pc2U8eyB2YWx1ZTogVmFsdWUgfCBudWxsIH0+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICAgIGNvbnN0YW50cy5PUF9WRVJTSU9OLFxuICAgICAgICBcIlwiLFxuICAgICAgICBcIlwiLFxuICAgICAgICBcIlwiLFxuICAgICAgICB0aGlzLnNlcVxuICAgICAgKTtcbiAgICAgIHRoaXMucGVyZm9ybU9uU2VydmVyKHNlcnZlciwgcmVxdWVzdCwgdGhpcy5zZXEsIChlcnIsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICByZXR1cm4gcmVqZWN0KGVycik7XG4gICAgICAgIH1cblxuICAgICAgICBzd2l0Y2ggKHJlc3BvbnNlIS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICAgICAgLyogVE9ETzogdGhpcyBpcyBidWdnZWQsIHdlIHNob3VsZCd0IHVzZSB0aGUgZGVzZXJpYWxpemVyIGhlcmUsIHNpbmNlIHZlcnNpb24gYWx3YXlzIHJldHVybnMgYSB2ZXJzaW9uIHN0cmluZy5cbiAgICAgICAgICAgICBUaGUgZGVzZXJpYWxpemVyIHNob3VsZCBvbmx5IGJlIHVzZWQgb24gdXNlciBrZXkgZGF0YS4gKi9cbiAgICAgICAgICAgIGNvbnN0IGRlc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5kZXNlcmlhbGl6ZShcbiAgICAgICAgICAgICAgcmVzcG9uc2UhLmhlYWRlci5vcGNvZGUsXG4gICAgICAgICAgICAgIHJlc3BvbnNlIS52YWwsXG4gICAgICAgICAgICAgIHJlc3BvbnNlIS5leHRyYXNcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICByZXR1cm4gcmVzb2x2ZSh7IHZhbHVlOiBkZXNlcmlhbGl6ZWQudmFsdWUgfSk7XG4gICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHJldHVybiByZWplY3QoXG4gICAgICAgICAgICAgIHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJWRVJTSU9OXCIsIHJlc3BvbnNlIS5oZWFkZXIuc3RhdHVzKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmVxdWVzdCB0aGUgc2VydmVyIHZlcnNpb24gZnJvbSB0aGUgXCJmaXJzdFwiIHNlcnZlciBpbiB0aGUgYmFja2VuZCBwb29sLlxuICAgKiBUaGUgc2VydmVyIHJlc3BvbmRzIHdpdGggYSBwYWNrZXQgY29udGFpbmluZyB0aGUgdmVyc2lvbiBzdHJpbmcgaW4gdGhlIGJvZHkgd2l0aCB0aGUgZm9sbG93aW5nIGZvcm1hdDogXCJ4LnkuelwiXG4gICAqL1xuICB2ZXJzaW9uKCk6IFByb21pc2U8eyB2YWx1ZTogVmFsdWUgfCBudWxsIH0+IHtcbiAgICBjb25zdCBzZXJ2ZXIgPSB0aGlzLnNlcnZlcktleVRvU2VydmVyKHRoaXMuc2VydmVyS2V5c1swXSk7XG4gICAgcmV0dXJuIHRoaXMuX3ZlcnNpb24oc2VydmVyKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXRyaWV2ZXMgdGhlIHNlcnZlciB2ZXJzaW9uIGZyb20gYWxsIHRoZSBzZXJ2ZXJzXG4gICAqIGluIHRoZSBiYWNrZW5kIHBvb2wsIGVycm9ycyBpZiBhbnkgb25lIG9mIHRoZW0gaGFzIGFuXG4gICAqIGVycm9yXG4gICAqL1xuICBhc3luYyB2ZXJzaW9uQWxsKGNhbGxiYWNrcz86IHtcbiAgICBiZWZvcmVQaW5nPzogKHNlcnZlcktleTogc3RyaW5nKSA9PiB2b2lkO1xuICAgIGFmdGVyUGluZz86IChzZXJ2ZXJLZXk6IHN0cmluZykgPT4gdm9pZDtcbiAgfSk6IFByb21pc2U8e1xuICAgIHZhbHVlczogUmVjb3JkPHN0cmluZywgVmFsdWUgfCBudWxsPjtcbiAgfT4ge1xuICAgIGNvbnN0IHZlcnNpb25PYmplY3RzID0gYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICB0aGlzLnNlcnZlcktleXMubWFwKChzZXJ2ZXJLZXkpID0+IHtcbiAgICAgICAgY29uc3Qgc2VydmVyID0gdGhpcy5zZXJ2ZXJLZXlUb1NlcnZlcihzZXJ2ZXJLZXkpO1xuICAgICAgICBjYWxsYmFja3M/LmJlZm9yZVBpbmc/LihzZXJ2ZXJLZXkpO1xuICAgICAgICByZXR1cm4gdGhpcy5fdmVyc2lvbihzZXJ2ZXIpLnRoZW4oKHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgY2FsbGJhY2tzPy5hZnRlclBpbmc/LihzZXJ2ZXJLZXkpO1xuICAgICAgICAgIHJldHVybiB7IHNlcnZlcktleTogc2VydmVyS2V5LCB2YWx1ZTogcmVzcG9uc2UudmFsdWUgfTtcbiAgICAgICAgfSk7XG4gICAgICB9KVxuICAgICk7XG4gICAgY29uc3QgdmFsdWVzID0gdmVyc2lvbk9iamVjdHMucmVkdWNlKChhY2N1bXVsYXRvciwgdmVyc2lvbk9iamVjdCkgPT4ge1xuICAgICAgYWNjdW11bGF0b3JbdmVyc2lvbk9iamVjdC5zZXJ2ZXJLZXldID0gdmVyc2lvbk9iamVjdC52YWx1ZTtcbiAgICAgIHJldHVybiBhY2N1bXVsYXRvcjtcbiAgICB9LCB7fSBhcyBSZWNvcmQ8c3RyaW5nLCBWYWx1ZSB8IG51bGw+KTtcbiAgICByZXR1cm4geyB2YWx1ZXM6IHZhbHVlcyB9O1xuICB9XG5cbiAgLyoqXG4gICAqIENsb3NlcyAoYWJydXB0bHkpIGNvbm5lY3Rpb25zIHRvIGFsbCB0aGUgc2VydmVycy5cbiAgICogQHNlZSB0aGlzLnF1aXRcbiAgICovXG4gIGNsb3NlKCkge1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5zZXJ2ZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB0aGlzLnNlcnZlcnNbaV0uY2xvc2UoKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUGVyZm9ybSBhIGdlbmVyaWMgc2luZ2xlIHJlc3BvbnNlIG9wZXJhdGlvbiAoZ2V0LCBzZXQgZXRjKSBvbiBvbmUgc2VydmVyXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgdGhlIGtleSB0byBoYXNoIHRvIGdldCBhIHNlcnZlciBmcm9tIHRoZSBwb29sXG4gICAqIEBwYXJhbSB7YnVmZmVyfSByZXF1ZXN0IGEgYnVmZmVyIGNvbnRhaW5pbmcgdGhlIHJlcXVlc3RcbiAgICogQHBhcmFtIHtudW1iZXJ9IHNlcSB0aGUgc2VxdWVuY2UgbnVtYmVyIG9mIHRoZSBvcGVyYXRpb24uIEl0IGlzIHVzZWQgdG8gcGluIHRoZSBjYWxsYmFja3NcbiAgICAgICAgICAgICAgICAgICAgICAgICB0byBhIHNwZWNpZmljIG9wZXJhdGlvbiBhbmQgc2hvdWxkIG5ldmVyIGNoYW5nZSBkdXJpbmcgYSBgcGVyZm9ybWAuXG4gICAqIEBwYXJhbSB7bnVtYmVyP30gcmV0cmllcyBudW1iZXIgb2YgdGltZXMgdG8gcmV0cnkgcmVxdWVzdCBvbiBmYWlsdXJlXG4gICAqL1xuICBwZXJmb3JtKFxuICAgIGtleTogc3RyaW5nLFxuICAgIHJlcXVlc3Q6IEJ1ZmZlcixcbiAgICBzZXE6IG51bWJlcixcbiAgICByZXRyaWVzPzogbnVtYmVyXG4gICk6IFByb21pc2U8TWVzc2FnZT4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBjb25zdCBzZXJ2ZXJLZXkgPSB0aGlzLmxvb2t1cEtleVRvU2VydmVyS2V5KGtleSk7XG4gICAgICBjb25zdCBzZXJ2ZXIgPSB0aGlzLnNlcnZlcktleVRvU2VydmVyKHNlcnZlcktleSk7XG5cbiAgICAgIGlmICghc2VydmVyKSB7XG4gICAgICAgIHJldHVybiByZWplY3QobmV3IEVycm9yKFwiTm8gc2VydmVycyBhdmFpbGFibGVcIikpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLnBlcmZvcm1PblNlcnZlcihcbiAgICAgICAgc2VydmVyLFxuICAgICAgICByZXF1ZXN0LFxuICAgICAgICBzZXEsXG4gICAgICAgIChlcnJvciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgIHJldHVybiByZWplY3QoZXJyb3IpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXNvbHZlKHJlc3BvbnNlISk7XG4gICAgICAgIH0sXG4gICAgICAgIHJldHJpZXNcbiAgICAgICk7XG4gICAgfSk7XG4gIH1cblxuICBwZXJmb3JtT25TZXJ2ZXIoXG4gICAgc2VydmVyOiBTZXJ2ZXIsXG4gICAgcmVxdWVzdDogQnVmZmVyLFxuICAgIHNlcTogbnVtYmVyLFxuICAgIGNhbGxiYWNrOiBSZXNwb25zZU9yRXJyb3JDYWxsYmFjayxcbiAgICByZXRyaWVzOiBudW1iZXIgPSAwXG4gICkge1xuICAgIGNvbnN0IF90aGlzID0gdGhpcztcblxuICAgIHJldHJpZXMgPSByZXRyaWVzIHx8IHRoaXMub3B0aW9ucy5yZXRyaWVzO1xuICAgIGNvbnN0IG9yaWdSZXRyaWVzID0gdGhpcy5vcHRpb25zLnJldHJpZXM7XG4gICAgY29uc3QgbG9nZ2VyID0gdGhpcy5vcHRpb25zLmxvZ2dlcjtcbiAgICBjb25zdCByZXRyeV9kZWxheSA9IHRoaXMub3B0aW9ucy5yZXRyeV9kZWxheTtcblxuICAgIGNvbnN0IHJlc3BvbnNlSGFuZGxlcjogT25SZXNwb25zZUNhbGxiYWNrID0gZnVuY3Rpb24gKHJlc3BvbnNlKSB7XG4gICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgY2FsbGJhY2sobnVsbCwgcmVzcG9uc2UpO1xuICAgICAgfVxuICAgIH07XG5cbiAgICBjb25zdCBlcnJvckhhbmRsZXI6IE9uRXJyb3JDYWxsYmFjayA9IGZ1bmN0aW9uIChlcnJvcikge1xuICAgICAgaWYgKC0tcmV0cmllcyA+IDApIHtcbiAgICAgICAgLy8gV2FpdCBmb3IgcmV0cnlfZGVsYXlcbiAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgX3RoaXMucGVyZm9ybU9uU2VydmVyKHNlcnZlciwgcmVxdWVzdCwgc2VxLCBjYWxsYmFjaywgcmV0cmllcyk7XG4gICAgICAgIH0sIDEwMDAgKiByZXRyeV9kZWxheSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBsb2dnZXIubG9nKFxuICAgICAgICAgIFwiTWVtSlM6IFNlcnZlciA8XCIgK1xuICAgICAgICAgICAgc2VydmVyLmhvc3Rwb3J0U3RyaW5nKCkgK1xuICAgICAgICAgICAgXCI+IGZhaWxlZCBhZnRlciAoXCIgK1xuICAgICAgICAgICAgb3JpZ1JldHJpZXMgK1xuICAgICAgICAgICAgXCIpIHJldHJpZXMgd2l0aCBlcnJvciAtIFwiICtcbiAgICAgICAgICAgIGVycm9yLm1lc3NhZ2VcbiAgICAgICAgKTtcbiAgICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgICAgY2FsbGJhY2soZXJyb3IsIG51bGwpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfTtcblxuICAgIHNlcnZlci5vblJlc3BvbnNlKHNlcSwgcmVzcG9uc2VIYW5kbGVyKTtcbiAgICBzZXJ2ZXIub25FcnJvcihzZXEsIGVycm9ySGFuZGxlcik7XG4gICAgc2VydmVyLndyaXRlKHJlcXVlc3QpO1xuICB9XG5cbiAgLy8gSW5jcmVtZW50IHRoZSBzZXEgdmFsdWVcbiAgaW5jclNlcSgpIHtcbiAgICB0aGlzLnNlcSsrO1xuXG4gICAgLy8gV3JhcCBgdGhpcy5zZXFgIHRvIDMyLWJpdHMgc2luY2UgdGhlIGZpZWxkIHdlIGZpdCBpdCBpbnRvIGlzIG9ubHkgMzItYml0cy5cbiAgICB0aGlzLnNlcSAmPSAweGZmZmZmZmZmO1xuXG4gICAgcmV0dXJuIHRoaXMuc2VxO1xuICB9XG5cbiAgcHJpdmF0ZSBjcmVhdGVBbmRMb2dFcnJvcihcbiAgICBjb21tYW5kTmFtZTogc3RyaW5nLFxuICAgIHJlc3BvbnNlU3RhdHVzOiBSZXNwb25zZVN0YXR1cyB8IHVuZGVmaW5lZFxuICApOiBFcnJvciB7XG4gICAgY29uc3QgZXJyb3JNZXNzYWdlID0gYE1lbUpTICR7Y29tbWFuZE5hbWV9OiAke2NvbnN0YW50cy5yZXNwb25zZVN0YXR1c1RvU3RyaW5nKFxuICAgICAgcmVzcG9uc2VTdGF0dXNcbiAgICApfWA7XG4gICAgdGhpcy5vcHRpb25zLmxvZ2dlci5sb2coZXJyb3JNZXNzYWdlKTtcbiAgICByZXR1cm4gbmV3IEVycm9yKGVycm9yTWVzc2FnZSk7XG4gIH1cblxuICAvKipcbiAgICogTG9nIGFuIGVycm9yIHRvIHRoZSBsb2dnZXIsIHRoZW4gcmV0dXJuIHRoZSBlcnJvci5cbiAgICogSWYgYSBjYWxsYmFjayBpcyBnaXZlbiwgY2FsbCBpdCB3aXRoIGNhbGxiYWNrKGVycm9yLCBudWxsKS5cbiAgICovXG4gIHByaXZhdGUgaGFuZGxlUmVzcG9uc2VFcnJvcihcbiAgICBjb21tYW5kTmFtZTogc3RyaW5nLFxuICAgIHJlc3BvbnNlU3RhdHVzOiBSZXNwb25zZVN0YXR1cyB8IHVuZGVmaW5lZCxcbiAgICBjYWxsYmFjazogdW5kZWZpbmVkIHwgKChlcnJvcjogRXJyb3IgfCBudWxsLCBvdGhlcjogbnVsbCkgPT4gdm9pZClcbiAgKTogRXJyb3Ige1xuICAgIGNvbnN0IGVycm9yID0gdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihjb21tYW5kTmFtZSwgcmVzcG9uc2VTdGF0dXMpO1xuICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgY2FsbGJhY2soZXJyb3IsIG51bGwpO1xuICAgIH1cbiAgICByZXR1cm4gZXJyb3I7XG4gIH1cbn1cblxuZXhwb3J0IHsgQ2xpZW50LCBTZXJ2ZXIsIFV0aWxzLCBIZWFkZXIgfTtcbiJdfQ== \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVtanMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbWVtanMvbWVtanMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLHdCQUF3Qjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUV4QixxQ0FLa0I7QUEyaUNELHVGQTdpQ2YsZUFBTSxPQTZpQ2U7QUExaUN2Qix1REFBK0Q7QUFDL0QsbUNBU2lCO0FBQ2pCLHVEQUF5QztBQUN6QywyQ0FBNkM7QUFDN0MsK0NBQWlDO0FBNmhDUixzQkFBSztBQTVoQzlCLGlEQUFtQztBQTRoQ0gsd0JBQU07QUExaEN0QyxTQUFTLDhCQUE4QixDQUNyQyxPQUFpQixFQUNqQixHQUFXO0lBRVgsTUFBTSxLQUFLLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQztJQUM3QixNQUFNLEtBQUssR0FBRyxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxnQkFBUSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3BELE9BQU8sT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ3hCLENBQUM7QUFFRCwrQ0FBK0M7QUFDL0MsU0FBUyxTQUFTLENBQ2hCLE9BQTBFO0lBRTFFLE9BQU8sSUFBSSxPQUFPLENBQUMsVUFBVSxPQUFPLEVBQUUsTUFBTTtRQUMxQyxPQUFPLENBQUMsVUFBVSxHQUFHLEVBQUUsTUFBTTtZQUMzQixHQUFHLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3RDLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBeURELE1BQU0sTUFBTTtJQVFWLDRFQUE0RTtJQUM1RSxtQ0FBbUM7SUFDbkMsWUFBWSxPQUFpQixFQUFFLE9BQTBDO1FBQ3ZFLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO1FBQ3ZCLElB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QUFtQixFQUNuQixjQUEwQztRQUUxQyxNQUFNLFlBQVksR0FBRyxTQUFTLFdBQVcsS0FBSyxTQUFTLENBQUMsc0JBQXNCLENBQzVFLGNBQWMsQ0FDZixFQUFFLENBQUM7UUFDSixJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDdEMsT0FBTyxJQUFJLEtBQUssQ0FBQyxZQUFZLENBQUMsQ0FBQztJQUNqQyxDQUFDO0lBRUQ7OztPQUdHO0lBQ0ssbUJBQW1CLENBQ3pCLFdBQW1CLEVBQ25CLGNBQTBDLEVBQzFDLFFBQWtFO1FBRWxFLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxXQUFXLEVBQUUsY0FBYyxDQUFDLENBQUM7UUFDbEUsSUFBSSxRQUFRLEVBQUU7WUFDWixRQUFRLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxDQUFDO1NBQ3ZCO1FBQ0QsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0NBQ0Y7QUFFUSx3QkFBTSIsInNvdXJjZXNDb250ZW50IjpbIi8vIE1lbVRTIE1lbWNhY2hlIENsaWVudFxuXG5pbXBvcnQge1xuICBPbkVycm9yQ2FsbGJhY2ssXG4gIE9uUmVzcG9uc2VDYWxsYmFjayxcbiAgU2VydmVyLFxuICBTZXJ2ZXJPcHRpb25zLFxufSBmcm9tIFwiLi9zZXJ2ZXJcIjtcbmltcG9ydCB7IG5vb3BTZXJpYWxpemVyLCBTZXJpYWxpemVyIH0gZnJvbSBcIi4vbm9vcC1zZXJpYWxpemVyXCI7XG5pbXBvcnQge1xuICBtYWtlUmVxdWVzdEJ1ZmZlcixcbiAgY29weUludG9SZXF1ZXN0QnVmZmVyLFxuICBtZXJnZSxcbiAgbWFrZUV4cGlyYXRpb24sXG4gIG1ha2VBbW91bnRJbml0aWFsQW5kRXhwaXJhdGlvbixcbiAgaGFzaENvZGUsXG4gIE1heWJlQnVmZmVyLFxuICBNZXNzYWdlLFxufSBmcm9tIFwiLi91dGlsc1wiO1xuaW1wb3J0ICogYXMgY29uc3RhbnRzIGZyb20gXCIuL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgUmVzcG9uc2VTdGF0dXMgfSBmcm9tIFwiLi9jb25zdGFudHNcIjtcbmltcG9ydCAqIGFzIFV0aWxzIGZyb20gXCIuL3V0aWxzXCI7XG5pbXBvcnQgKiBhcyBIZWFkZXIgZnJvbSBcIi4vaGVhZGVyXCI7XG5cbmZ1bmN0aW9uIGRlZmF1bHRLZXlUb1NlcnZlckhhc2hGdW5jdGlvbihcbiAgc2VydmVyczogc3RyaW5nW10sXG4gIGtleTogc3RyaW5nXG4pOiBzdHJpbmcge1xuICBjb25zdCB0b3RhbCA9IHNlcnZlcnMubGVuZ3RoO1xuICBjb25zdCBpbmRleCA9IHRvdGFsID4gMSA/IGhhc2hDb2RlKGtleSkgJSB0b3RhbCA6IDA7XG4gIHJldHVybiBzZXJ2ZXJzW2luZGV4XTtcbn1cblxuLy8gY29udmVydHMgYSBjYWxsIGludG8gYSBwcm9taXNlLXJldHVybmluZyBvbmVcbmZ1bmN0aW9uIHByb21pc2lmeTxSZXN1bHQ+KFxuICBjb21tYW5kOiAoY2FsbGJhY2s6IChlcnJvcjogRXJyb3IgfCBudWxsLCByZXN1bHQ6IFJlc3VsdCkgPT4gdm9pZCkgPT4gdm9pZFxuKTogUHJvbWlzZTxSZXN1bHQ+IHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICBjb21tYW5kKGZ1bmN0aW9uIChlcnIsIHJlc3VsdCkge1xuICAgICAgZXJyID8gcmVqZWN0KGVycikgOiByZXNvbHZlKHJlc3VsdCk7XG4gICAgfSk7XG4gIH0pO1xufVxuXG50eXBlIFJlc3BvbnNlT3JFcnJvckNhbGxiYWNrID0gKFxuICBlcnJvcjogRXJyb3IgfCBudWxsLFxuICByZXNwb25zZTogTWVzc2FnZSB8IG51bGxcbikgPT4gdm9pZDtcblxuaW50ZXJmYWNlIEJhc2VDbGllbnRPcHRpb25zIHtcbiAgcmV0cmllczogbnVtYmVyO1xuICByZXRyeV9kZWxheTogbnVtYmVyO1xuICBleHBpcmVzOiBudW1iZXI7XG4gIGxvZ2dlcjogeyBsb2c6IHR5cGVvZiBjb25zb2xlLmxvZyB9O1xuICBrZXlUb1NlcnZlckhhc2hGdW5jdGlvbjogdHlwZW9mIGRlZmF1bHRLZXlUb1NlcnZlckhhc2hGdW5jdGlvbjtcbn1cblxuaW50ZXJmYWNlIFNlcmlhbGl6ZXJQcm9wPFZhbHVlLCBFeHRyYXM+IHtcbiAgc2VyaWFsaXplcjogU2VyaWFsaXplcjxWYWx1ZSwgRXh0cmFzPjtcbn1cblxuLyoqXG4gKiBUaGUgY2xpZW50IGhhcyBwYXJ0aWFsIHN1cHBvcnQgZm9yIHNlcmlhbGl6aW5nIGFuZCBkZXNlcmlhbGl6aW5nIHZhbHVlcyBmcm9tIHRoZVxuICogQnVmZmVyIGJ5dGUgc3RyaW5ncyB3ZSByZWNlaXZlIGZyb20gdGhlIHdpcmUuIFRoZSBkZWZhdWx0IHNlcmlhbGl6ZXIgaXMgZm9yIE1heWJlQnVmZmVyLlxuICpcbiAqIElmIFZhbHVlIGFuZCBFeHRyYXMgYXJlIG9mIHR5cGUgQnVmZmVyLCB0aGVuIHJldHVybiB0eXBlIFdoZW5CdWZmZXIuIE90aGVyd2lzZSxcbiAqIHJldHVybiB0eXBlIE5vdEJ1ZmZlci5cbiAqL1xudHlwZSBJZkJ1ZmZlcjxWYWx1ZSwgRXh0cmFzLCBXaGVuVmFsdWVBbmRFeHRyYXNBcmVCdWZmZXJzLCBOb3RCdWZmZXI+ID1cbiAgVmFsdWUgZXh0ZW5kcyBCdWZmZXJcbiAgICA/IEV4dHJhcyBleHRlbmRzIEJ1ZmZlclxuICAgICAgPyBXaGVuVmFsdWVBbmRFeHRyYXNBcmVCdWZmZXJzXG4gICAgICA6IE5vdEJ1ZmZlclxuICAgIDogTm90QnVmZmVyO1xuXG5leHBvcnQgdHlwZSBHaXZlbkNsaWVudE9wdGlvbnM8VmFsdWUsIEV4dHJhcz4gPSBQYXJ0aWFsPEJhc2VDbGllbnRPcHRpb25zPiAmXG4gIElmQnVmZmVyPFxuICAgIFZhbHVlLFxuICAgIEV4dHJhcyxcbiAgICBQYXJ0aWFsPFNlcmlhbGl6ZXJQcm9wPFZhbHVlLCBFeHRyYXM+PixcbiAgICBTZXJpYWxpemVyUHJvcDxWYWx1ZSwgRXh0cmFzPlxuICA+O1xuXG5leHBvcnQgdHlwZSBDQVNUb2tlbiA9IEJ1ZmZlcjtcblxuZXhwb3J0IGludGVyZmFjZSBHZXRSZXN1bHQ8VmFsdWUgPSBNYXliZUJ1ZmZlciwgRXh0cmFzID0gTWF5YmVCdWZmZXI+IHtcbiAgdmFsdWU6IFZhbHVlO1xuICBleHRyYXM6IEV4dHJhcztcbiAgY2FzOiBDQVNUb2tlbiB8IHVuZGVmaW5lZDtcbn1cblxuZXhwb3J0IHR5cGUgR2V0TXVsdGlSZXN1bHQ8XG4gIEtleXMgZXh0ZW5kcyBzdHJpbmcgPSBzdHJpbmcsXG4gIFZhbHVlID0gTWF5YmVCdWZmZXIsXG4gIEV4dHJhcyA9IE1heWJlQnVmZmVyXG4+ID0ge1xuICBbSyBpbiBLZXlzXT86IEdldFJlc3VsdDxWYWx1ZSwgRXh0cmFzPjtcbn07XG5cbmNsYXNzIENsaWVudDxWYWx1ZSA9IE1heWJlQnVmZmVyLCBFeHRyYXMgPSBNYXliZUJ1ZmZlcj4ge1xuICBzZXJ2ZXJzOiBTZXJ2ZXJbXTtcbiAgc2VxOiBudW1iZXI7XG4gIG9wdGlvbnM6IEJhc2VDbGllbnRPcHRpb25zICYgUGFydGlhbDxTZXJpYWxpemVyUHJvcDxWYWx1ZSwgRXh0cmFzPj47XG4gIHNlcmlhbGl6ZXI6IFNlcmlhbGl6ZXI8VmFsdWUsIEV4dHJhcz47XG4gIHNlcnZlck1hcDogeyBbaG9zdHBvcnQ6IHN0cmluZ106IFNlcnZlciB9O1xuICBzZXJ2ZXJLZXlzOiBzdHJpbmdbXTtcblxuICAvLyBDbGllbnQgaW5pdGlhbGl6ZXIgdGFrZXMgYSBsaXN0IG9mIGBTZXJ2ZXJgcyBhbmQgYW4gYG9wdGlvbnNgIGRpY3Rpb25hcnkuXG4gIC8vIFNlZSBgQ2xpZW50LmNyZWF0ZWAgZm9yIGRldGFpbHMuXG4gIGNvbnN0cnVjdG9yKHNlcnZlcnM6IFNlcnZlcltdLCBvcHRpb25zOiBHaXZlbkNsaWVudE9wdGlvbnM8VmFsdWUsIEV4dHJhcz4pIHtcbiAgICB0aGlzLnNlcnZlcnMgPSBzZXJ2ZXJzO1xuICAgIHRoaXMuc2VxID0gMDtcbiAgICB0aGlzLm9wdGlvbnMgPSBtZXJnZShvcHRpb25zIHx8IHt9LCB7XG4gICAgICByZXRyaWVzOiAyLFxuICAgICAgcmV0cnlfZGVsYXk6IDAuMixcbiAgICAgIGV4cGlyZXM6IDAsXG4gICAgICBsb2dnZXI6IGNvbnNvbGUsXG4gICAgICBrZXlUb1NlcnZlckhhc2hGdW5jdGlvbjogZGVmYXVsdEtleVRvU2VydmVySGFzaEZ1bmN0aW9uLFxuICAgIH0pO1xuXG4gICAgdGhpcy5zZXJpYWxpemVyID0gdGhpcy5vcHRpb25zLnNlcmlhbGl6ZXIgfHwgKG5vb3BTZXJpYWxpemVyIGFzIGFueSk7XG5cbiAgICAvLyBTdG9yZSBhIG1hcHBpbmcgZnJvbSBob3N0cG9ydCAtPiBzZXJ2ZXIgc28gd2UgY2FuIHF1aWNrbHkgZ2V0IGEgc2VydmVyIG9iamVjdCBmcm9tIHRoZSBzZXJ2ZXJLZXkgcmV0dXJuZWQgYnkgdGhlIGhhc2hpbmcgZnVuY3Rpb25cbiAgICBjb25zdCBzZXJ2ZXJNYXA6IHsgW2hvc3Rwb3J0OiBzdHJpbmddOiBTZXJ2ZXIgfSA9IHt9O1xuICAgIHRoaXMuc2VydmVycy5mb3JFYWNoKGZ1bmN0aW9uIChzZXJ2ZXIpIHtcbiAgICAgIHNlcnZlck1hcFtzZXJ2ZXIuaG9zdHBvcnRTdHJpbmcoKV0gPSBzZXJ2ZXI7XG4gICAgfSk7XG4gICAgdGhpcy5zZXJ2ZXJNYXAgPSBzZXJ2ZXJNYXA7XG5cbiAgICAvLyBzdG9yZSBhIGxpc3Qgb2YgYWxsIG91ciBzZXJ2ZXJLZXlzIHNvIHdlIGRvbid0IG5lZWQgdG8gY29uc3RhbnRseSByZWFsbG9jYXRlIHRoaXMgYXJyYXlcbiAgICB0aGlzLnNlcnZlcktleXMgPSBPYmplY3Qua2V5cyh0aGlzLnNlcnZlck1hcCk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIG5ldyBjbGllbnQgZ2l2ZW4gYW4gb3B0aW9uYWwgY29uZmlnIHN0cmluZyBhbmQgb3B0aW9uYWwgaGFzaCBvZlxuICAgKiBvcHRpb25zLiBUaGUgY29uZmlnIHN0cmluZyBzaG91bGQgYmUgb2YgdGhlIGZvcm06XG4gICAqXG4gICAqICAgICBcIlt1c2VyOnBhc3NAXXNlcnZlcjFbOjExMjExXSxbdXNlcjpwYXNzQF1zZXJ2ZXIyWzoxMTIxMV0sLi4uXCJcbiAgICpcbiAgICogSWYgdGhlIGFyZ3VtZW50IGlzIG5vdCBnaXZlbiwgZmFsbGJhY2sgb24gdGhlIGBNRU1DQUNISUVSX1NFUlZFUlNgIGVudmlyb25tZW50XG4gICAqIHZhcmlhYmxlLCBgTUVNQ0FDSEVfU0VSVkVSU2AgZW52aXJvbm1lbnQgdmFyaWFibGUgb3IgYFwibG9jYWxob3N0OjExMjExXCJgLlxuICAgKlxuICAgKiBUaGUgb3B0aW9ucyBoYXNoIG1heSBjb250YWluIHRoZSBvcHRpb25zOlxuICAgKlxuICAgKiAqIGByZXRyaWVzYCAtIHRoZSBudW1iZXIgb2YgdGltZXMgdG8gcmV0cnkgYW4gb3BlcmF0aW9uIGluIGxpZXUgb2YgZmFpbHVyZXNcbiAgICogKGRlZmF1bHQgMilcbiAgICogKiBgZXhwaXJlc2AgLSB0aGUgZGVmYXVsdCBleHBpcmF0aW9uIGluIHNlY29uZHMgdG8gdXNlIChkZWZhdWx0IDAgLSBuZXZlclxuICAgKiBleHBpcmUpLiBJZiBgZXhwaXJlc2AgaXMgZ3JlYXRlciB0aGFuIDMwIGRheXMgKDYwIHggNjAgeCAyNCB4IDMwKSwgaXQgaXNcbiAgICogdHJlYXRlZCBhcyBhIFVOSVggdGltZSAobnVtYmVyIG9mIHNlY29uZHMgc2luY2UgSmFudWFyeSAxLCAxOTcwKS5cbiAgICogKiBgbG9nZ2VyYCAtIGEgbG9nZ2VyIG9iamVjdCB0aGF0IHJlc3BvbmRzIHRvIGBsb2coc3RyaW5nKWAgbWV0aG9kIGNhbGxzLlxuICAgKlxuICAgKiAgIH5+fn5cbiAgICogICAgIGxvZyhtc2cxWywgbXNnMlssIG1zZzNbLi4uXV1dKVxuICAgKiAgIH5+fn5cbiAgICpcbiAgICogICBEZWZhdWx0cyB0byBgY29uc29sZWAuXG4gICAqICogYHNlcmlhbGl6ZXJgIC0gdGhlIG9iamVjdCB3aGljaCB3aWxsIChkZSlzZXJpYWxpemUgdGhlIGRhdGEuIEl0IG5lZWRzXG4gICAqICAgdHdvIHB1YmxpYyBtZXRob2RzOiBzZXJpYWxpemUgYW5kIGRlc2VyaWFsaXplLiBJdCBkZWZhdWx0cyB0byB0aGVcbiAgICogICBub29wU2VyaWFsaXplcjpcbiAgICpcbiAgICogICB+fn5+XG4gICAqICAgY29uc3Qgbm9vcFNlcmlhbGl6ZXIgPSB7XG4gICAqICAgICBzZXJpYWxpemU6IGZ1bmN0aW9uIChvcGNvZGUsIHZhbHVlLCBleHRyYXMpIHtcbiAgICogICAgICAgcmV0dXJuIHsgdmFsdWU6IHZhbHVlLCBleHRyYXM6IGV4dHJhcyB9O1xuICAgKiAgICAgfSxcbiAgICogICAgIGRlc2VyaWFsaXplOiBmdW5jdGlvbiAob3Bjb2RlLCB2YWx1ZSwgZXh0cmFzKSB7XG4gICAqICAgICAgIHJldHVybiB7IHZhbHVlOiB2YWx1ZSwgZXh0cmFzOiBleHRyYXMgfTtcbiAgICogICAgIH1cbiAgICogICB9O1xuICAgKiAgIH5+fn5cbiAgICpcbiAgICogT3Igb3B0aW9ucyBmb3IgdGhlIHNlcnZlcnMgaW5jbHVkaW5nOlxuICAgKiAqIGB1c2VybmFtZWAgYW5kIGBwYXNzd29yZGAgZm9yIGZhbGxiYWNrIFNBU0wgYXV0aGVudGljYXRpb24gY3JlZGVudGlhbHMuXG4gICAqICogYHRpbWVvdXRgIGluIHNlY29uZHMgdG8gZGV0ZXJtaW5lIGZhaWx1cmUgZm9yIG9wZXJhdGlvbnMuIERlZmF1bHQgaXMgMC41XG4gICAqICAgICAgICAgICAgIHNlY29uZHMuXG4gICAqICogJ2Nvbm50aW1lb3V0JyBpbiBzZWNvbmRzIHRvIGNvbm5lY3Rpb24gZmFpbHVyZS4gRGVmYXVsdCBpcyB0d2ljZSB0aGUgdmFsdWVcbiAgICogICAgICAgICAgICAgICAgIG9mIGB0aW1lb3V0YC5cbiAgICogKiBga2VlcEFsaXZlYCB3aGV0aGVyIHRvIGVuYWJsZSBrZWVwLWFsaXZlIGZ1bmN0aW9uYWxpdHkuIERlZmF1bHRzIHRvIGZhbHNlLlxuICAgKiAqIGBrZWVwQWxpdmVEZWxheWAgaW4gc2Vjb25kcyB0byB0aGUgaW5pdGlhbCBkZWxheSBiZWZvcmUgdGhlIGZpcnN0IGtlZXBhbGl2ZVxuICAgKiAgICAgICAgICAgICAgICAgICAgcHJvYmUgaXMgc2VudCBvbiBhbiBpZGxlIHNvY2tldC4gRGVmYXVsdHMgaXMgMzAgc2Vjb25kcy5cbiAgICogKiBga2V5VG9TZXJ2ZXJIYXNoRnVuY3Rpb25gIGEgZnVuY3Rpb24gdG8gbWFwIGtleXMgdG8gc2VydmVycywgd2l0aCB0aGUgc2lnbmF0dXJlXG4gICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgIChzZXJ2ZXJLZXlzOiBzdHJpbmdbXSwga2V5OiBzdHJpbmcpOiBzdHJpbmdcbiAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgTk9URTogaWYgeW91IG5lZWQgdG8gZG8gc29tZSBleHBlbnNpdmUgaW5pdGlhbGl6YXRpb24sICpwbGVhc2UqIGRvIGl0IGxhemlseSB0aGUgZmlyc3QgdGltZSB5b3UgdGhpcyBmdW5jdGlvbiBpcyBjYWxsZWQgd2l0aCBhbiBhcnJheSBvZiBzZXJ2ZXJLZXlzLCBub3Qgb24gZXZlcnkgY2FsbFxuICAgKi9cbiAgc3RhdGljIGNyZWF0ZTxWYWx1ZSwgRXh0cmFzPihcbiAgICBzZXJ2ZXJzU3RyOiBzdHJpbmcgfCB1bmRlZmluZWQsXG4gICAgb3B0aW9uczogSWZCdWZmZXI8XG4gICAgICBWYWx1ZSxcbiAgICAgIEV4dHJhcyxcbiAgICAgIHVuZGVmaW5lZCB8IChQYXJ0aWFsPFNlcnZlck9wdGlvbnM+ICYgR2l2ZW5DbGllbnRPcHRpb25zPFZhbHVlLCBFeHRyYXM+KSxcbiAgICAgIFBhcnRpYWw8U2VydmVyT3B0aW9ucz4gJiBHaXZlbkNsaWVudE9wdGlvbnM8VmFsdWUsIEV4dHJhcz5cbiAgICA+XG4gICk6IENsaWVudDxWYWx1ZSwgRXh0cmFzPiB7XG4gICAgc2VydmVyc1N0ciA9XG4gICAgICBzZXJ2ZXJzU3RyIHx8XG4gICAgICBwcm9jZXNzLmVudi5NRU1DQUNISUVSX1NFUlZFUlMgfHxcbiAgICAgIHByb2Nlc3MuZW52Lk1FTUNBQ0hFX1NFUlZFUlMgfHxcbiAgICAgIFwibG9jYWxob3N0OjExMjExXCI7XG4gICAgY29uc3Qgc2VydmVyVXJpcyA9IHNlcnZlcnNTdHIuc3BsaXQoXCIsXCIpO1xuICAgIGNvbnN0IHNlcnZlcnMgPSBzZXJ2ZXJVcmlzLm1hcChmdW5jdGlvbiAodXJpKSB7XG4gICAgICBjb25zdCB1cmlQYXJ0cyA9IHVyaS5zcGxpdChcIkBcIik7XG4gICAgICBjb25zdCBob3N0UG9ydCA9IHVyaVBhcnRzW3VyaVBhcnRzLmxlbmd0aCAtIDFdLnNwbGl0KFwiOlwiKTtcbiAgICAgIGNvbnN0IHVzZXJQYXNzID0gKHVyaVBhcnRzW3VyaVBhcnRzLmxlbmd0aCAtIDJdIHx8IFwiXCIpLnNwbGl0KFwiOlwiKTtcbiAgICAgIHJldHVybiBuZXcgU2VydmVyKFxuICAgICAgICBob3N0UG9ydFswXSxcbiAgICAgICAgcGFyc2VJbnQoaG9zdFBvcnRbMV0gfHwgXCIxMTIxMVwiLCAxMCksXG4gICAgICAgIHVzZXJQYXNzWzBdLFxuICAgICAgICB1c2VyUGFzc1sxXSxcbiAgICAgICAgb3B0aW9uc1xuICAgICAgKTtcbiAgICB9KTtcbiAgICByZXR1cm4gbmV3IENsaWVudChzZXJ2ZXJzLCBvcHRpb25zIGFzIGFueSk7XG4gIH1cblxuICAvKipcbiAgICogR2l2ZW4gYSBzZXJ2ZXJLZXkgZnJvbWxvb2t1cEtleVRvU2VydmVyS2V5LCByZXR1cm4gdGhlIGNvcnJlc3BvbmRpbmcgU2VydmVyIGluc3RhbmNlXG4gICAqXG4gICAqIEBwYXJhbSAge3N0cmluZ30gc2VydmVyS2V5XG4gICAqIEByZXR1cm5zIHtTZXJ2ZXJ9XG4gICAqL1xuICBzZXJ2ZXJLZXlUb1NlcnZlcihzZXJ2ZXJLZXk6IHN0cmluZyk6IFNlcnZlciB7XG4gICAgcmV0dXJuIHRoaXMuc2VydmVyTWFwW3NlcnZlcktleV07XG4gIH1cblxuICAvKipcbiAgICogR2l2ZW4gYSBrZXkgdG8gbG9vayB1cCBpbiBtZW1jYWNoZSwgcmV0dXJuIGEgc2VydmVyS2V5IChiYXNlZCBvbiBzb21lXG4gICAqIGhhc2hpbmcgZnVuY3Rpb24pIHdoaWNoIGNhbiBiZSB1c2VkIHRvIGluZGV4IHRoaXMuc2VydmVyTWFwXG4gICAqL1xuICBsb29rdXBLZXlUb1NlcnZlcktleShrZXk6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMub3B0aW9ucy5rZXlUb1NlcnZlckhhc2hGdW5jdGlvbih0aGlzLnNlcnZlcktleXMsIGtleSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldmVzIHRoZSB2YWx1ZSBhdCB0aGUgZ2l2ZW4ga2V5IGluIG1lbWNhY2hlLlxuICAgKi9cbiAgYXN5bmMgZ2V0KGtleTogc3RyaW5nKTogUHJvbWlzZTxHZXRSZXN1bHQ8VmFsdWUsIEV4dHJhcz4gfCBudWxsPiB7XG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKGNvbnN0YW50cy5PUF9HRVQsIGtleSwgXCJcIiwgXCJcIiwgdGhpcy5zZXEpO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICBjb25zdCBkZXNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuZGVzZXJpYWxpemUoXG4gICAgICAgICAgcmVzcG9uc2UuaGVhZGVyLm9wY29kZSxcbiAgICAgICAgICByZXNwb25zZS52YWwsXG4gICAgICAgICAgcmVzcG9uc2UuZXh0cmFzXG4gICAgICAgICk7XG4gICAgICAgIHJldHVybiB7IC4uLmRlc2VyaWFsaXplZCwgY2FzOiByZXNwb25zZS5oZWFkZXIuY2FzIH07XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIkdFVFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKiogQnVpbGQgYSBwaXBlbGluZWQgZ2V0IG11bHRpIHJlcXVlc3QgYnkgc2VuZGluZyBvbmUgR0VUS1EgZm9yIGVhY2gga2V5IChxdWlldCwgbWVhbmluZyBpdCB3b24ndCByZXNwb25kIGlmIHRoZSB2YWx1ZSBpcyBtaXNzaW5nKSBmb2xsb3dlZCBieSBhIG5vLW9wIHRvIGZvcmNlIGEgcmVzcG9uc2UgKGFuZCB0byBnaXZlIHVzIGEgc2VudGluZWwgcmVzcG9uc2UgdGhhdCB0aGUgcGlwZWxpbmUgaXMgZG9uZSlcbiAgICpcbiAgICogY2YgaHR0cHM6Ly9naXRodWIuY29tL2NvdWNoYmFzZS9tZW1jYWNoZWQvYmxvYi9tYXN0ZXIvZG9jcy9CaW5hcnlQcm90b2NvbC5tZCMweDBkLWdldGtxLWdldC13aXRoLWtleS1xdWlldGx5XG4gICAqL1xuICBfYnVpbGRHZXRNdWx0aVJlcXVlc3Qoa2V5czogc3RyaW5nW10sIHNlcTogbnVtYmVyKTogQnVmZmVyIHtcbiAgICAvLyBzdGFydCBhdCAyNCBmb3IgdGhlIG5vLW9wIGNvbW1hbmQgYXQgdGhlIGVuZFxuICAgIGxldCByZXF1ZXN0U2l6ZSA9IDI0O1xuICAgIGZvciAoY29uc3Qga2V5SWR4IGluIGtleXMpIHtcbiAgICAgIHJlcXVlc3RTaXplICs9IEJ1ZmZlci5ieXRlTGVuZ3RoKGtleXNba2V5SWR4XSwgXCJ1dGY4XCIpICsgMjQ7XG4gICAgfVxuXG4gICAgY29uc3QgcmVxdWVzdCA9IEJ1ZmZlci5hbGxvYyhyZXF1ZXN0U2l6ZSk7XG5cbiAgICBsZXQgYnl0ZXNXcml0dGVuID0gMDtcbiAgICBmb3IgKGNvbnN0IGtleUlkeCBpbiBrZXlzKSB7XG4gICAgICBjb25zdCBrZXkgPSBrZXlzW2tleUlkeF07XG4gICAgICBieXRlc1dyaXR0ZW4gKz0gY29weUludG9SZXF1ZXN0QnVmZmVyKFxuICAgICAgICBjb25zdGFudHMuT1BfR0VUS1EsXG4gICAgICAgIGtleSxcbiAgICAgICAgXCJcIixcbiAgICAgICAgXCJcIixcbiAgICAgICAgc2VxLFxuICAgICAgICByZXF1ZXN0LFxuICAgICAgICBieXRlc1dyaXR0ZW5cbiAgICAgICk7XG4gICAgfVxuXG4gICAgYnl0ZXNXcml0dGVuICs9IGNvcHlJbnRvUmVxdWVzdEJ1ZmZlcihcbiAgICAgIGNvbnN0YW50cy5PUF9OT19PUCxcbiAgICAgIFwiXCIsXG4gICAgICBcIlwiLFxuICAgICAgXCJcIixcbiAgICAgIHNlcSxcbiAgICAgIHJlcXVlc3QsXG4gICAgICBieXRlc1dyaXR0ZW5cbiAgICApO1xuXG4gICAgcmV0dXJuIHJlcXVlc3Q7XG4gIH1cblxuICAvKiogRXhlY3V0aW5nIGEgcGlwZWxpbmVkIChtdWx0aSkgZ2V0IGFnYWluc3QgYSBzaW5nbGUgc2VydmVyLiBUaGlzIGlzIGEgcHJpdmF0ZSBpbXBsZW1lbnRhdGlvbiBkZXRhaWwgb2YgZ2V0TXVsdGkuICovXG4gIGFzeW5jIF9nZXRNdWx0aVRvU2VydmVyPEtleXMgZXh0ZW5kcyBzdHJpbmc+KFxuICAgIHNlcnY6IFNlcnZlcixcbiAgICBrZXlzOiBLZXlzW11cbiAgKTogUHJvbWlzZTxHZXRNdWx0aVJlc3VsdDxLZXlzLCBWYWx1ZSwgRXh0cmFzPj4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBjb25zdCByZXNwb25zZU1hcDogR2V0TXVsdGlSZXN1bHQ8c3RyaW5nLCBWYWx1ZSwgRXh0cmFzPiA9IHt9O1xuXG4gICAgICBjb25zdCBoYW5kbGU6IE9uUmVzcG9uc2VDYWxsYmFjayA9IChyZXNwb25zZSkgPT4ge1xuICAgICAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgICAgICAvLyBXaGVuIHdlIGdldCB0aGUgbm8tb3AgcmVzcG9uc2UsIHdlIGFyZSBkb25lIHdpdGggdGhpcyBvbmUgZ2V0TXVsdGkgaW4gdGhlIHBlci1iYWNrZW5kIGZhbi1vdXRcbiAgICAgICAgICAgIGlmIChyZXNwb25zZS5oZWFkZXIub3Bjb2RlID09PSBjb25zdGFudHMuT1BfTk9fT1ApIHtcbiAgICAgICAgICAgICAgLy8gVGhpcyBlbnN1cmVzIHRoZSBoYW5kbGVyIHdpbGwgYmUgZGVsZXRlZCBmcm9tIHRoZSByZXNwb25zZUNhbGxiYWNrcyBtYXAgaW4gc2VydmVyLmpzXG4gICAgICAgICAgICAgIC8vIFRoaXMgaXNuJ3QgdGVjaG5pY2FsbHkgbmVlZGVkIGhlcmUgYmVjYXVzZSB0aGUgbG9naWMgaW4gc2VydmVyLmpzIGFsc28gY2hlY2tzIGlmIHRvdGFsQm9keUxlbmd0aCA9PT0gMCwgYnV0IG91ciB1bml0dGVzdHMgYXJlbid0IGdyZWF0IGFib3V0IHNldHRpbmcgdGhhdCBmaWVsZCwgYW5kIGFsc28gdGhpcyBtYWtlcyBpdCBtb3JlIGV4cGxpY2l0XG4gICAgICAgICAgICAgIGhhbmRsZS5xdWlldCA9IGZhbHNlO1xuICAgICAgICAgICAgICByZXNvbHZlKHJlc3BvbnNlTWFwKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgICAgICAgIHJlc3BvbnNlLmhlYWRlci5vcGNvZGUgPT09IGNvbnN0YW50cy5PUF9HRVRLIHx8XG4gICAgICAgICAgICAgIHJlc3BvbnNlLmhlYWRlci5vcGNvZGUgPT09IGNvbnN0YW50cy5PUF9HRVRLUVxuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgIGNvbnN0IGRlc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5kZXNlcmlhbGl6ZShcbiAgICAgICAgICAgICAgICByZXNwb25zZS5oZWFkZXIub3Bjb2RlLFxuICAgICAgICAgICAgICAgIHJlc3BvbnNlLnZhbCxcbiAgICAgICAgICAgICAgICByZXNwb25zZS5leHRyYXNcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgY29uc3Qga2V5ID0gcmVzcG9uc2Uua2V5LnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgIGlmIChrZXkubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlamVjdChcbiAgICAgICAgICAgICAgICAgIG5ldyBFcnJvcihcbiAgICAgICAgICAgICAgICAgICAgXCJSZWNpZXZlZCBlbXB0eSBrZXkgaW4gZ2V0TXVsdGk6IFwiICtcbiAgICAgICAgICAgICAgICAgICAgICBKU09OLnN0cmluZ2lmeShyZXNwb25zZSlcbiAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIHJlc3BvbnNlTWFwW2tleV0gPSB7IC4uLmRlc2VyaWFsaXplZCwgY2FzOiByZXNwb25zZS5oZWFkZXIuY2FzIH07XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICByZXR1cm4gcmVqZWN0KFxuICAgICAgICAgICAgICAgIG5ldyBFcnJvcihcbiAgICAgICAgICAgICAgICAgIFwiUmVjaWV2ZWQgcmVzcG9uc2UgaW4gZ2V0TXVsdGkgZm9yIHVua25vd24gb3Bjb2RlOiBcIiArXG4gICAgICAgICAgICAgICAgICAgIEpTT04uc3RyaW5naWZ5KHJlc3BvbnNlKVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICByZXR1cm4gcmVqZWN0KFxuICAgICAgICAgICAgICB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiR0VUXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9O1xuICAgICAgLy8gVGhpcyBwcmV2ZW50cyB0aGUgaGFuZGxlciBmcm9tIGJlaW5nIGRlbGV0ZWRcbiAgICAgIC8vIGFmdGVyIHRoZSBmaXJzdCByZXNwb25zZS4gTG9naWMgaW4gc2VydmVyLmpzLlxuICAgICAgaGFuZGxlLnF1aWV0ID0gdHJ1ZTtcblxuICAgICAgY29uc3Qgc2VxID0gdGhpcy5pbmNyU2VxKCk7XG4gICAgICBjb25zdCByZXF1ZXN0ID0gdGhpcy5fYnVpbGRHZXRNdWx0aVJlcXVlc3Qoa2V5cywgc2VxKTtcbiAgICAgIHNlcnYub25SZXNwb25zZSh0aGlzLnNlcSwgaGFuZGxlKTtcbiAgICAgIHNlcnYub25FcnJvcih0aGlzLnNlcSwgcmVqZWN0KTtcbiAgICAgIHNlcnYud3JpdGUocmVxdWVzdCk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldnMgdGhlIHZhbHVlIGF0IHRoZSBnaXZlbiBrZXlzIGluIG1lbWNhY2hlZC4gUmV0dXJucyBhIG1hcCBmcm9tIHRoZVxuICAgKiByZXF1ZXN0ZWQga2V5cyB0byByZXN1bHRzLCBvciBudWxsIGlmIHRoZSBrZXkgd2FzIG5vdCBmb3VuZC5cbiAgICovXG4gIGFzeW5jIGdldE11bHRpPEtleXMgZXh0ZW5kcyBzdHJpbmc+KFxuICAgIGtleXM6IEtleXNbXVxuICApOiBQcm9taXNlPEdldE11bHRpUmVzdWx0PEtleXMsIFZhbHVlLCBFeHRyYXM+PiB7XG4gICAgY29uc3Qgc2VydmVyS2V5dG9Mb29rdXBLZXlzOiB7XG4gICAgICBbc2VydmVyS2V5OiBzdHJpbmddOiBzdHJpbmdbXTtcbiAgICB9ID0ge307XG4gICAga2V5cy5mb3JFYWNoKChsb29rdXBLZXkpID0+IHtcbiAgICAgIGNvbnN0IHNlcnZlcktleSA9IHRoaXMubG9va3VwS2V5VG9TZXJ2ZXJLZXkobG9va3VwS2V5KTtcbiAgICAgIGlmICghc2VydmVyS2V5dG9Mb29rdXBLZXlzW3NlcnZlcktleV0pIHtcbiAgICAgICAgc2VydmVyS2V5dG9Mb29rdXBLZXlzW3NlcnZlcktleV0gPSBbXTtcbiAgICAgIH1cbiAgICAgIHNlcnZlcktleXRvTG9va3VwS2V5c1tzZXJ2ZXJLZXldLnB1c2gobG9va3VwS2V5KTtcbiAgICB9KTtcblxuICAgIGNvbnN0IHVzZWRTZXJ2ZXJLZXlzID0gT2JqZWN0LmtleXMoc2VydmVyS2V5dG9Mb29rdXBLZXlzKTtcbiAgICBjb25zdCByZXN1bHRzID0gYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICB1c2VkU2VydmVyS2V5cy5tYXAoKHNlcnZlcktleSkgPT4ge1xuICAgICAgICBjb25zdCBzZXJ2ZXIgPSB0aGlzLnNlcnZlcktleVRvU2VydmVyKHNlcnZlcktleSk7XG4gICAgICAgIHJldHVybiB0aGlzLl9nZXRNdWx0aVRvU2VydmVyKHNlcnZlciwgc2VydmVyS2V5dG9Mb29rdXBLZXlzW3NlcnZlcktleV0pO1xuICAgICAgfSlcbiAgICApO1xuXG4gICAgcmV0dXJuIE9iamVjdC5hc3NpZ24oe30sIC4uLnJlc3VsdHMpO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgYGtleWAgdG8gYHZhbHVlYC5cbiAgICovXG4gIGFzeW5jIHNldChcbiAgICBrZXk6IHN0cmluZyxcbiAgICB2YWx1ZTogVmFsdWUsXG4gICAgb3B0aW9ucz86IHsgZXhwaXJlcz86IG51bWJlcjsgY2FzPzogQ0FTVG9rZW4gfVxuICApOiBQcm9taXNlPGJvb2xlYW4gfCBudWxsPiB7XG4gICAgY29uc3QgZXhwaXJlcyA9IG9wdGlvbnM/LmV4cGlyZXM7XG4gICAgY29uc3QgY2FzID0gb3B0aW9ucz8uY2FzO1xuXG4gICAgLy8gVE9ETzogc3VwcG9ydCBmbGFnc1xuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IGV4cGlyYXRpb24gPSBtYWtlRXhwaXJhdGlvbihleHBpcmVzIHx8IHRoaXMub3B0aW9ucy5leHBpcmVzKTtcbiAgICBjb25zdCBleHRyYXMgPSBCdWZmZXIuY29uY2F0KFtCdWZmZXIuZnJvbShcIjAwMDAwMDAwXCIsIFwiaGV4XCIpLCBleHBpcmF0aW9uXSk7XG4gICAgY29uc3Qgc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5zZXJpYWxpemUoXG4gICAgICBjb25zdGFudHMuT1BfU0VULFxuICAgICAgdmFsdWUsXG4gICAgICBleHRyYXNcbiAgICApO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBVdGlscy5lbmNvZGVSZXF1ZXN0KHtcbiAgICAgIGhlYWRlcjoge1xuICAgICAgICBvcGNvZGU6IGNvbnN0YW50cy5PUF9TRVQsXG4gICAgICAgIG9wYXF1ZTogdGhpcy5zZXEsXG4gICAgICAgIGNhcyxcbiAgICAgIH0sXG4gICAgICBrZXksXG4gICAgICB2YWx1ZTogc2VyaWFsaXplZC52YWx1ZSxcbiAgICAgIGV4dHJhczogc2VyaWFsaXplZC5leHRyYXMsXG4gICAgfSk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfRVhJU1RTOlxuICAgICAgICBpZiAoY2FzKSB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJTRVRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgICAgIH1cbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJTRVRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEFERFxuICAgKlxuICAgKiBBZGRzIHRoZSBnaXZlbiBfa2V5XyBhbmQgX3ZhbHVlXyB0byBtZW1jYWNoZS4gVGhlIG9wZXJhdGlvbiBvbmx5IHN1Y2NlZWRzXG4gICAqIGlmIHRoZSBrZXkgaXMgbm90IGFscmVhZHkgc2V0LlxuICAgKlxuICAgKiBUaGUgb3B0aW9ucyBkaWN0aW9uYXJ5IHRha2VzOlxuICAgKiAqIF9leHBpcmVzXzogb3ZlcnJpZGVzIHRoZSBkZWZhdWx0IGV4cGlyYXRpb24gKHNlZSBgQ2xpZW50LmNyZWF0ZWApIGZvciB0aGlzXG4gICAqICAgICAgICAgICAgICBwYXJ0aWN1bGFyIGtleS12YWx1ZSBwYWlyLlxuICAgKi9cbiAgYXN5bmMgYWRkKFxuICAgIGtleTogc3RyaW5nLFxuICAgIHZhbHVlOiBWYWx1ZSxcbiAgICBvcHRpb25zPzogeyBleHBpcmVzPzogbnVtYmVyIH1cbiAgKTogUHJvbWlzZTxib29sZWFuIHwgbnVsbD4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgZmxhZ3MsIHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IGV4cGlyYXRpb24gPSBtYWtlRXhwaXJhdGlvbihvcHRpb25zPy5leHBpcmVzIHx8IHRoaXMub3B0aW9ucy5leHBpcmVzKTtcbiAgICBjb25zdCBleHRyYXMgPSBCdWZmZXIuY29uY2F0KFtCdWZmZXIuZnJvbShcIjAwMDAwMDAwXCIsIFwiaGV4XCIpLCBleHBpcmF0aW9uXSk7XG5cbiAgICBjb25zdCBvcGNvZGUgPSBjb25zdGFudHMuT1BfQUREO1xuICAgIGNvbnN0IHNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuc2VyaWFsaXplKG9wY29kZSwgdmFsdWUsIGV4dHJhcyk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKFxuICAgICAgb3Bjb2RlLFxuICAgICAga2V5LFxuICAgICAgc2VyaWFsaXplZC5leHRyYXMsXG4gICAgICBzZXJpYWxpemVkLnZhbHVlLFxuICAgICAgdGhpcy5zZXFcbiAgICApO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuS0VZX0VYSVNUUzpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJBRERcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlcGxhY2VzIHRoZSBnaXZlbiBfa2V5XyBhbmQgX3ZhbHVlXyB0byBtZW1jYWNoZS4gVGhlIG9wZXJhdGlvbiBvbmx5IHN1Y2NlZWRzXG4gICAqIGlmIHRoZSBrZXkgaXMgYWxyZWFkeSBwcmVzZW50LlxuICAgKi9cbiAgYXN5bmMgcmVwbGFjZShcbiAgICBrZXk6IHN0cmluZyxcbiAgICB2YWx1ZTogVmFsdWUsXG4gICAgb3B0aW9ucz86IHsgZXhwaXJlcz86IG51bWJlciB9XG4gICk6IFByb21pc2U8Ym9vbGVhbiB8IG51bGw+IHtcbiAgICAvLyBUT0RPOiBzdXBwb3J0IGZsYWdzLCBzdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBleHBpcmF0aW9uID0gbWFrZUV4cGlyYXRpb24ob3B0aW9ucz8uZXhwaXJlcyB8fCB0aGlzLm9wdGlvbnMuZXhwaXJlcyk7XG4gICAgY29uc3QgZXh0cmFzID0gQnVmZmVyLmNvbmNhdChbQnVmZmVyLmZyb20oXCIwMDAwMDAwMFwiLCBcImhleFwiKSwgZXhwaXJhdGlvbl0pO1xuXG4gICAgY29uc3Qgb3Bjb2RlOiBjb25zdGFudHMuT1AgPSBjb25zdGFudHMuT1BfUkVQTEFDRTtcbiAgICBjb25zdCBzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLnNlcmlhbGl6ZShvcGNvZGUsIHZhbHVlLCBleHRyYXMpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgIG9wY29kZSxcbiAgICAgIGtleSxcbiAgICAgIHNlcmlhbGl6ZWQuZXh0cmFzLFxuICAgICAgc2VyaWFsaXplZC52YWx1ZSxcbiAgICAgIHRoaXMuc2VxXG4gICAgKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJSRVBMQUNFXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBEZWxldGVzIHRoZSBnaXZlbiBfa2V5XyBmcm9tIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHNcbiAgICogaWYgdGhlIGtleSBpcyBhbHJlYWR5IHByZXNlbnQuXG4gICAqL1xuICBhc3luYyBkZWxldGUoa2V5OiBzdHJpbmcpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAvLyBUT0RPOiBTdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoNCwga2V5LCBcIlwiLCBcIlwiLCB0aGlzLnNlcSk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG5cbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJERUxFVEVcIiwgcmVzcG9uc2U/LmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBJbmNyZW1lbnRzIHRoZSBnaXZlbiBfa2V5XyBpbiBtZW1jYWNoZS5cbiAgICovXG4gIGFzeW5jIGluY3JlbWVudChcbiAgICBrZXk6IHN0cmluZyxcbiAgICBhbW91bnQ6IG51bWJlcixcbiAgICBvcHRpb25zPzogeyBpbml0aWFsPzogbnVtYmVyOyBleHBpcmVzPzogbnVtYmVyIH1cbiAgKTogUHJvbWlzZTx7IHZhbHVlOiBudW1iZXIgfCBudWxsOyBzdWNjZXNzOiBib29sZWFuIHwgbnVsbCB9PiB7XG4gICAgLy8gVE9ETzogc3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgaW5pdGlhbCA9IG9wdGlvbnM/LmluaXRpYWwgfHwgMDtcbiAgICBjb25zdCBleHBpcmVzID0gb3B0aW9ucz8uZXhwaXJlcyB8fCB0aGlzLm9wdGlvbnMuZXhwaXJlcztcbiAgICBjb25zdCBleHRyYXMgPSBtYWtlQW1vdW50SW5pdGlhbEFuZEV4cGlyYXRpb24oYW1vdW50LCBpbml0aWFsLCBleHBpcmVzKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICBjb25zdGFudHMuT1BfSU5DUkVNRU5ULFxuICAgICAga2V5LFxuICAgICAgZXh0cmFzLFxuICAgICAgXCJcIixcbiAgICAgIHRoaXMuc2VxXG4gICAgKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgY29uc3QgYnVmSW50ID1cbiAgICAgICAgICAocmVzcG9uc2UudmFsLnJlYWRVSW50MzJCRSgwKSA8PCA4KSArIHJlc3BvbnNlLnZhbC5yZWFkVUludDMyQkUoNCk7XG4gICAgICAgIHJldHVybiB7IHZhbHVlOiBidWZJbnQsIHN1Y2Nlc3M6IHRydWUgfTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJJTkNSRU1FTlRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIERlY3JlbWVudHMgdGhlIGdpdmVuIGBrZXlgIGluIG1lbWNhY2hlLlxuICAgKi9cbiAgYXN5bmMgZGVjcmVtZW50KFxuICAgIGtleTogc3RyaW5nLFxuICAgIGFtb3VudDogbnVtYmVyLFxuICAgIG9wdGlvbnM6IHsgaW5pdGlhbD86IG51bWJlcjsgZXhwaXJlcz86IG51bWJlciB9XG4gICk6IFByb21pc2U8eyB2YWx1ZTogbnVtYmVyIHwgbnVsbDsgc3VjY2VzczogYm9vbGVhbiB8IG51bGwgfT4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IGluaXRpYWwgPSBvcHRpb25zLmluaXRpYWwgfHwgMDtcbiAgICBjb25zdCBleHBpcmVzID0gb3B0aW9ucy5leHBpcmVzIHx8IHRoaXMub3B0aW9ucy5leHBpcmVzO1xuICAgIGNvbnN0IGV4dHJhcyA9IG1ha2VBbW91bnRJbml0aWFsQW5kRXhwaXJhdGlvbihhbW91bnQsIGluaXRpYWwsIGV4cGlyZXMpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgIGNvbnN0YW50cy5PUF9ERUNSRU1FTlQsXG4gICAgICBrZXksXG4gICAgICBleHRyYXMsXG4gICAgICBcIlwiLFxuICAgICAgdGhpcy5zZXFcbiAgICApO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICBjb25zdCBidWZJbnQgPVxuICAgICAgICAgIChyZXNwb25zZS52YWwucmVhZFVJbnQzMkJFKDApIDw8IDgpICsgcmVzcG9uc2UudmFsLnJlYWRVSW50MzJCRSg0KTtcbiAgICAgICAgcmV0dXJuIHsgdmFsdWU6IGJ1ZkludCwgc3VjY2VzczogdHJ1ZSB9O1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIkRFQ1JFTUVOVFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQXBwZW5kIHRoZSBnaXZlbiBfdmFsdWVfIHRvIHRoZSB2YWx1ZSBhc3NvY2lhdGVkIHdpdGggdGhlIGdpdmVuIF9rZXlfIGluXG4gICAqIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHMgaWYgdGhlIGtleSBpcyBhbHJlYWR5IHByZXNlbnQuXG4gICAqL1xuICBhc3luYyBhcHBlbmQoa2V5OiBzdHJpbmcsIHZhbHVlOiBWYWx1ZSk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IG9wY29kZTogY29uc3RhbnRzLk9QID0gY29uc3RhbnRzLk9QX0FQUEVORDtcbiAgICBjb25zdCBzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLnNlcmlhbGl6ZShvcGNvZGUsIHZhbHVlLCBcIlwiKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICBvcGNvZGUsXG4gICAgICBrZXksXG4gICAgICBzZXJpYWxpemVkLmV4dHJhcyxcbiAgICAgIHNlcmlhbGl6ZWQudmFsdWUsXG4gICAgICB0aGlzLnNlcVxuICAgICk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfTk9UX0ZPVU5EOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiQVBQRU5EXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBQcmVwZW5kIHRoZSBnaXZlbiBfdmFsdWVfIHRvIHRoZSB2YWx1ZSBhc3NvY2lhdGVkIHdpdGggdGhlIGdpdmVuIF9rZXlfIGluXG4gICAqIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHMgaWYgdGhlIGtleSBpcyBhbHJlYWR5IHByZXNlbnQuXG4gICAqL1xuICBhc3luYyBwcmVwZW5kKGtleTogc3RyaW5nLCB2YWx1ZTogVmFsdWUpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAvLyBUT0RPOiBzdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBvcGNvZGU6IGNvbnN0YW50cy5PUCA9IGNvbnN0YW50cy5PUF9QUkVQRU5EO1xuICAgIGNvbnN0IHNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuc2VyaWFsaXplKG9wY29kZSwgdmFsdWUsIFwiXCIpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgIG9wY29kZSxcbiAgICAgIGtleSxcbiAgICAgIHNlcmlhbGl6ZWQuZXh0cmFzLFxuICAgICAgc2VyaWFsaXplZC52YWx1ZSxcbiAgICAgIHRoaXMuc2VxXG4gICAgKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJQUkVQRU5EXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBUb3VjaCBzZXRzIGFuIGV4cGlyYXRpb24gdmFsdWUsIGdpdmVuIGJ5IF9leHBpcmVzXywgb24gdGhlIGdpdmVuIF9rZXlfIGluXG4gICAqIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHMgaWYgdGhlIGtleSBpcyBhbHJlYWR5IHByZXNlbnQuXG4gICAqL1xuICBhc3luYyB0b3VjaChrZXk6IHN0cmluZywgZXhwaXJlczogbnVtYmVyKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgLy8gVE9ETzogc3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgZXh0cmFzID0gbWFrZUV4cGlyYXRpb24oZXhwaXJlcyB8fCB0aGlzLm9wdGlvbnMuZXhwaXJlcyk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKDB4MWMsIGtleSwgZXh0cmFzLCBcIlwiLCB0aGlzLnNlcSk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfTk9UX0ZPVU5EOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiVE9VQ0hcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEZMVVNIXG4gICAqXG4gICAqIEZsdXNoZXMgdGhlIGNhY2hlIG9uIGVhY2ggY29ubmVjdGVkIHNlcnZlci4gVGhlIGNhbGxiYWNrIHNpZ25hdHVyZSBpczpcbiAgICpcbiAgICogICAgIGNhbGxiYWNrKGxhc3RFcnIsIHJlc3VsdHMpXG4gICAqXG4gICAqIHdoZXJlIF9sYXN0RXJyXyBpcyB0aGUgbGFzdCBlcnJvciBlbmNvdW50ZXJlZCAob3IgbnVsbCwgaW4gdGhlIGNvbW1vbiBjYXNlXG4gICAqIG9mIG5vIGVycm9ycykuIF9yZXN1bHRzXyBpcyBhIGRpY3Rpb25hcnkgbWFwcGluZyBgXCJob3N0bmFtZTpwb3J0XCJgIHRvIGVpdGhlclxuICAgKiBgdHJ1ZWAgKGlmIHRoZSBvcGVyYXRpb24gd2FzIHN1Y2Nlc3NmdWwpLCBvciBhbiBlcnJvci5cbiAgICogQHBhcmFtIGNhbGxiYWNrXG4gICAqL1xuICBmbHVzaCgpOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIGJvb2xlYW4gfCBFcnJvcj4+O1xuICBmbHVzaChcbiAgICBjYWxsYmFjazogKFxuICAgICAgZXJyOiBFcnJvciB8IG51bGwsXG4gICAgICByZXN1bHRzOiBSZWNvcmQ8c3RyaW5nLCBib29sZWFuIHwgRXJyb3I+XG4gICAgKSA9PiB2b2lkXG4gICk6IHZvaWQ7XG4gIGZsdXNoKFxuICAgIGNhbGxiYWNrPzogKFxuICAgICAgZXJyOiBFcnJvciB8IG51bGwsXG4gICAgICByZXN1bHRzOiBSZWNvcmQ8c3RyaW5nLCBib29sZWFuIHwgRXJyb3I+XG4gICAgKSA9PiB2b2lkXG4gICkge1xuICAgIGlmIChjYWxsYmFjayA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm4gcHJvbWlzaWZ5KChjYWxsYmFjaykgPT4ge1xuICAgICAgICB0aGlzLmZsdXNoKGZ1bmN0aW9uIChlcnIsIHJlc3VsdHMpIHtcbiAgICAgICAgICBjYWxsYmFjayhlcnIsIHJlc3VsdHMpO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH1cbiAgICAvLyBUT0RPOiBzdXBwb3J0IGV4cGlyYXRpb25cbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoMHgwOCwgXCJcIiwgXCJcIiwgXCJcIiwgdGhpcy5zZXEpO1xuICAgIGxldCBjb3VudCA9IHRoaXMuc2VydmVycy5sZW5ndGg7XG4gICAgY29uc3QgcmVzdWx0OiBSZWNvcmQ8c3RyaW5nLCBib29sZWFuIHwgRXJyb3I+ID0ge307XG4gICAgbGV0IGxhc3RFcnI6IEVycm9yIHwgbnVsbCA9IG51bGw7XG5cbiAgICBjb25zdCBoYW5kbGVGbHVzaCA9IGZ1bmN0aW9uIChzZXE6IG51bWJlciwgc2VydjogU2VydmVyKSB7XG4gICAgICBzZXJ2Lm9uUmVzcG9uc2Uoc2VxLCBmdW5jdGlvbiAoLyogcmVzcG9uc2UgKi8pIHtcbiAgICAgICAgY291bnQgLT0gMTtcbiAgICAgICAgcmVzdWx0W3NlcnYuaG9zdHBvcnRTdHJpbmcoKV0gPSB0cnVlO1xuICAgICAgICBpZiAoY2FsbGJhY2sgJiYgY291bnQgPT09IDApIHtcbiAgICAgICAgICBjYWxsYmFjayhsYXN0RXJyLCByZXN1bHQpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHNlcnYub25FcnJvcihzZXEsIGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgICAgY291bnQgLT0gMTtcbiAgICAgICAgbGFzdEVyciA9IGVycjtcbiAgICAgICAgcmVzdWx0W3NlcnYuaG9zdHBvcnRTdHJpbmcoKV0gPSBlcnI7XG4gICAgICAgIGlmIChjYWxsYmFjayAmJiBjb3VudCA9PT0gMCkge1xuICAgICAgICAgIGNhbGxiYWNrKGxhc3RFcnIsIHJlc3VsdCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgc2Vydi53cml0ZShyZXF1ZXN0KTtcbiAgICB9O1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnNlcnZlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGhhbmRsZUZsdXNoKHRoaXMuc2VxLCB0aGlzLnNlcnZlcnNbaV0pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTVEFUU19XSVRIX0tFWVxuICAgKlxuICAgKiBTZW5kcyBhIG1lbWNhY2hlIHN0YXRzIGNvbW1hbmQgd2l0aCBhIGtleSB0byBlYWNoIGNvbm5lY3RlZCBzZXJ2ZXIuIFRoZVxuICAgKiBjYWxsYmFjayBpcyBpbnZva2VkICoqT05DRSBQRVIgU0VSVkVSKiogYW5kIGhhcyB0aGUgc2lnbmF0dXJlOlxuICAgKlxuICAgKiAgICAgY2FsbGJhY2soZXJyLCBzZXJ2ZXIsIHN0YXRzKVxuICAgKlxuICAgKiBfc2VydmVyXyBpcyB0aGUgYFwiaG9zdG5hbWU6cG9ydFwiYCBvZiB0aGUgc2VydmVyLCBhbmQgX3N0YXRzXyBpcyBhIGRpY3Rpb25hcnlcbiAgICogbWFwcGluZyB0aGUgc3RhdCBuYW1lIHRvIHRoZSB2YWx1ZSBvZiB0aGUgc3RhdGlzdGljIGFzIGEgc3RyaW5nLlxuICAgKiBAcGFyYW0ga2V5XG4gICAqIEBwYXJhbSBjYWxsYmFja1xuICAgKi9cbiAgc3RhdHNXaXRoS2V5KFxuICAgIGtleTogc3RyaW5nLFxuICAgIGNhbGxiYWNrPzogKFxuICAgICAgZXJyOiBFcnJvciB8IG51bGwsXG4gICAgICBzZXJ2ZXI6IHN0cmluZyxcbiAgICAgIHN0YXRzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+IHwgbnVsbFxuICAgICkgPT4gdm9pZFxuICApOiB2b2lkIHtcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoMHgxMCwga2V5LCBcIlwiLCBcIlwiLCB0aGlzLnNlcSk7XG5cbiAgICBjb25zdCBoYW5kbGVTdGF0cyA9IChzZXE6IG51bWJlciwgc2VydjogU2VydmVyKSA9PiB7XG4gICAgICBjb25zdCByZXN1bHQ6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcbiAgICAgIGNvbnN0IGhhbmRsZTogT25SZXNwb25zZUNhbGxiYWNrID0gKHJlc3BvbnNlKSA9PiB7XG4gICAgICAgIC8vIGVuZCBvZiBzdGF0IHJlc3BvbnNlc1xuICAgICAgICBpZiAocmVzcG9uc2UuaGVhZGVyLnRvdGFsQm9keUxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgICAgY2FsbGJhY2sobnVsbCwgc2Vydi5ob3N0cG9ydFN0cmluZygpLCByZXN1bHQpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgLy8gcHJvY2VzcyBzaW5nbGUgc3RhdCBsaW5lIHJlc3BvbnNlXG4gICAgICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgICAgIHJlc3VsdFtyZXNwb25zZS5rZXkudG9TdHJpbmcoKV0gPSByZXNwb25zZS52YWwudG9TdHJpbmcoKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICBjb25zdCBlcnJvciA9IHRoaXMuaGFuZGxlUmVzcG9uc2VFcnJvcihcbiAgICAgICAgICAgICAgYFNUQVRTICgke2tleX0pYCxcbiAgICAgICAgICAgICAgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyxcbiAgICAgICAgICAgICAgdW5kZWZpbmVkXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgICAgICAgIGNhbGxiYWNrKGVycm9yLCBzZXJ2Lmhvc3Rwb3J0U3RyaW5nKCksIG51bGwpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9O1xuICAgICAgaGFuZGxlLnF1aWV0ID0gdHJ1ZTtcblxuICAgICAgc2Vydi5vblJlc3BvbnNlKHNlcSwgaGFuZGxlKTtcbiAgICAgIHNlcnYub25FcnJvcihzZXEsIGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgICAgY2FsbGJhY2soZXJyLCBzZXJ2Lmhvc3Rwb3J0U3RyaW5nKCksIG51bGwpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHNlcnYud3JpdGUocmVxdWVzdCk7XG4gICAgfTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5zZXJ2ZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBoYW5kbGVTdGF0cyh0aGlzLnNlcSwgdGhpcy5zZXJ2ZXJzW2ldKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU1RBVFNcbiAgICpcbiAgICogRmV0Y2hlcyBtZW1jYWNoZSBzdGF0cyBmcm9tIGVhY2ggY29ubmVjdGVkIHNlcnZlci4gVGhlIGNhbGxiYWNrIGlzIGludm9rZWRcbiAgICogKipPTkNFIFBFUiBTRVJWRVIqKiBhbmQgaGFzIHRoZSBzaWduYXR1cmU6XG4gICAqXG4gICAqICAgICBjYWxsYmFjayhlcnIsIHNlcnZlciwgc3RhdHMpXG4gICAqXG4gICAqIF9zZXJ2ZXJfIGlzIHRoZSBgXCJob3N0bmFtZTpwb3J0XCJgIG9mIHRoZSBzZXJ2ZXIsIGFuZCBfc3RhdHNfIGlzIGFcbiAgICogZGljdGlvbmFyeSBtYXBwaW5nIHRoZSBzdGF0IG5hbWUgdG8gdGhlIHZhbHVlIG9mIHRoZSBzdGF0aXN0aWMgYXMgYSBzdHJpbmcuXG4gICAqIEBwYXJhbSBjYWxsYmFja1xuICAgKi9cbiAgc3RhdHMoXG4gICAgY2FsbGJhY2s/OiAoXG4gICAgICBlcnI6IEVycm9yIHwgbnVsbCxcbiAgICAgIHNlcnZlcjogc3RyaW5nLFxuICAgICAgc3RhdHM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gfCBudWxsXG4gICAgKSA9PiB2b2lkXG4gICk6IHZvaWQge1xuICAgIHRoaXMuc3RhdHNXaXRoS2V5KFwiXCIsIGNhbGxiYWNrKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSRVNFVF9TVEFUU1xuICAgKlxuICAgKiBSZXNldCB0aGUgc3RhdGlzdGljcyBlYWNoIHNlcnZlciBpcyBrZWVwaW5nIGJhY2sgdG8gemVyby4gVGhpcyBkb2Vzbid0IGNsZWFyXG4gICAqIHN0YXRzIHN1Y2ggYXMgaXRlbSBjb3VudCwgYnV0IHRlbXBvcmFyeSBzdGF0cyBzdWNoIGFzIHRvdGFsIG51bWJlciBvZlxuICAgKiBjb25uZWN0aW9ucyBvdmVyIHRpbWUuXG4gICAqXG4gICAqIFRoZSBjYWxsYmFjayBpcyBpbnZva2VkICoqT05DRSBQRVIgU0VSVkVSKiogYW5kIGhhcyB0aGUgc2lnbmF0dXJlOlxuICAgKlxuICAgKiAgICAgY2FsbGJhY2soZXJyLCBzZXJ2ZXIpXG4gICAqXG4gICAqIF9zZXJ2ZXJfIGlzIHRoZSBgXCJob3N0bmFtZTpwb3J0XCJgIG9mIHRoZSBzZXJ2ZXIuXG4gICAqIEBwYXJhbSBjYWxsYmFja1xuICAgKi9cbiAgcmVzZXRTdGF0cyhcbiAgICBjYWxsYmFjaz86IChcbiAgICAgIGVycjogRXJyb3IgfCBudWxsLFxuICAgICAgc2VydmVyOiBzdHJpbmcsXG4gICAgICBzdGF0czogUmVjb3JkPHN0cmluZywgc3RyaW5nPiB8IG51bGxcbiAgICApID0+IHZvaWRcbiAgKTogdm9pZCB7XG4gICAgdGhpcy5zdGF0c1dpdGhLZXkoXCJyZXNldFwiLCBjYWxsYmFjayk7XG4gIH1cblxuICAvKipcbiAgICogUVVJVFxuICAgKlxuICAgKiBDbG9zZXMgdGhlIGNvbm5lY3Rpb24gdG8gZWFjaCBzZXJ2ZXIsIG5vdGlmeWluZyB0aGVtIG9mIHRoaXMgaW50ZW50aW9uLiBOb3RlXG4gICAqIHRoYXQgcXVpdCBjYW4gcmFjZSBhZ2FpbnN0IGFscmVhZHkgb3V0c3RhbmRpbmcgcmVxdWVzdHMgd2hlbiB0aG9zZSByZXF1ZXN0c1xuICAgKiBmYWlsIGFuZCBhcmUgcmV0cmllZCwgbGVhZGluZyB0byB0aGUgcXVpdCBjb21tYW5kIHdpbm5pbmcgYW5kIGNsb3NpbmcgdGhlXG4gICAqIGNvbm5lY3Rpb24gYmVmb3JlIHRoZSByZXRyaWVzIGNvbXBsZXRlLlxuICAgKi9cbiAgcXVpdCgpIHtcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICAvLyBUT0RPOiBOaWNlciBwZXJoYXBzIHRvIGRvIFFVSVRRICgweDE3KSBidXQgbmVlZCBhIG5ldyBjYWxsYmFjayBmb3Igd2hlblxuICAgIC8vIHdyaXRlIGlzIGRvbmUuXG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKDB4MDcsIFwiXCIsIFwiXCIsIFwiXCIsIHRoaXMuc2VxKTsgLy8gUVVJVFxuICAgIGxldCBzZXJ2O1xuXG4gICAgY29uc3QgaGFuZGxlUXVpdCA9IGZ1bmN0aW9uIChzZXE6IG51bWJlciwgc2VydjogU2VydmVyKSB7XG4gICAgICBzZXJ2Lm9uUmVzcG9uc2Uoc2VxLCBmdW5jdGlvbiAoLyogcmVzcG9uc2UgKi8pIHtcbiAgICAgICAgc2Vydi5jbG9zZSgpO1xuICAgICAgfSk7XG4gICAgICBzZXJ2Lm9uRXJyb3Ioc2VxLCBmdW5jdGlvbiAoLyogZXJyICovKSB7XG4gICAgICAgIHNlcnYuY2xvc2UoKTtcbiAgICAgIH0pO1xuICAgICAgc2Vydi53cml0ZShyZXF1ZXN0KTtcbiAgICB9O1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnNlcnZlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHNlcnYgPSB0aGlzLnNlcnZlcnNbaV07XG4gICAgICBoYW5kbGVRdWl0KHRoaXMuc2VxLCBzZXJ2KTtcbiAgICB9XG4gIH1cblxuICBfdmVyc2lvbihzZXJ2ZXI6IFNlcnZlcik6IFByb21pc2U8eyB2YWx1ZTogVmFsdWUgfCBudWxsIH0+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICAgIGNvbnN0YW50cy5PUF9WRVJTSU9OLFxuICAgICAgICBcIlwiLFxuICAgICAgICBcIlwiLFxuICAgICAgICBcIlwiLFxuICAgICAgICB0aGlzLnNlcVxuICAgICAgKTtcbiAgICAgIHRoaXMucGVyZm9ybU9uU2VydmVyKHNlcnZlciwgcmVxdWVzdCwgdGhpcy5zZXEsIChlcnIsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICByZXR1cm4gcmVqZWN0KGVycik7XG4gICAgICAgIH1cblxuICAgICAgICBzd2l0Y2ggKHJlc3BvbnNlIS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICAgICAgLyogVE9ETzogdGhpcyBpcyBidWdnZWQsIHdlIHNob3VsZCd0IHVzZSB0aGUgZGVzZXJpYWxpemVyIGhlcmUsIHNpbmNlIHZlcnNpb24gYWx3YXlzIHJldHVybnMgYSB2ZXJzaW9uIHN0cmluZy5cbiAgICAgICAgICAgICBUaGUgZGVzZXJpYWxpemVyIHNob3VsZCBvbmx5IGJlIHVzZWQgb24gdXNlciBrZXkgZGF0YS4gKi9cbiAgICAgICAgICAgIGNvbnN0IGRlc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5kZXNlcmlhbGl6ZShcbiAgICAgICAgICAgICAgcmVzcG9uc2UhLmhlYWRlci5vcGNvZGUsXG4gICAgICAgICAgICAgIHJlc3BvbnNlIS52YWwsXG4gICAgICAgICAgICAgIHJlc3BvbnNlIS5leHRyYXNcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICByZXR1cm4gcmVzb2x2ZSh7IHZhbHVlOiBkZXNlcmlhbGl6ZWQudmFsdWUgfSk7XG4gICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHJldHVybiByZWplY3QoXG4gICAgICAgICAgICAgIHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJWRVJTSU9OXCIsIHJlc3BvbnNlIS5oZWFkZXIuc3RhdHVzKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmVxdWVzdCB0aGUgc2VydmVyIHZlcnNpb24gZnJvbSB0aGUgXCJmaXJzdFwiIHNlcnZlciBpbiB0aGUgYmFja2VuZCBwb29sLlxuICAgKiBUaGUgc2VydmVyIHJlc3BvbmRzIHdpdGggYSBwYWNrZXQgY29udGFpbmluZyB0aGUgdmVyc2lvbiBzdHJpbmcgaW4gdGhlIGJvZHkgd2l0aCB0aGUgZm9sbG93aW5nIGZvcm1hdDogXCJ4LnkuelwiXG4gICAqL1xuICB2ZXJzaW9uKCk6IFByb21pc2U8eyB2YWx1ZTogVmFsdWUgfCBudWxsIH0+IHtcbiAgICBjb25zdCBzZXJ2ZXIgPSB0aGlzLnNlcnZlcktleVRvU2VydmVyKHRoaXMuc2VydmVyS2V5c1swXSk7XG4gICAgcmV0dXJuIHRoaXMuX3ZlcnNpb24oc2VydmVyKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXRyaWV2ZXMgdGhlIHNlcnZlciB2ZXJzaW9uIGZyb20gYWxsIHRoZSBzZXJ2ZXJzXG4gICAqIGluIHRoZSBiYWNrZW5kIHBvb2wsIGVycm9ycyBpZiBhbnkgb25lIG9mIHRoZW0gaGFzIGFuXG4gICAqIGVycm9yXG4gICAqIFxuICAgKiBDYWxsYmFja3MgZnVuY3Rpb25zIGFyZSBjYWxsZWQgYmVmb3JlL2FmdGVyIHdlIHBpbmcgbWVtY2FjaGVkXG4gICAqIGFuZCB1c2VkIHRvIGxvZyB3aGljaCBob3N0cyBhcmUgdGltaW5nIG91dC5cbiAgICovXG4gIGFzeW5jIHZlcnNpb25BbGwoY2FsbGJhY2tzPzoge1xuICAgIGJlZm9yZVBpbmc/OiAoc2VydmVyS2V5OiBzdHJpbmcpID0+IHZvaWQ7XG4gICAgYWZ0ZXJQaW5nPzogKHNlcnZlcktleTogc3RyaW5nKSA9PiB2b2lkO1xuICB9KTogUHJvbWlzZTx7XG4gICAgdmFsdWVzOiBSZWNvcmQ8c3RyaW5nLCBWYWx1ZSB8IG51bGw+O1xuICB9PiB7XG4gICAgY29uc3QgdmVyc2lvbk9iamVjdHMgPSBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIHRoaXMuc2VydmVyS2V5cy5tYXAoKHNlcnZlcktleSkgPT4ge1xuICAgICAgICBjb25zdCBzZXJ2ZXIgPSB0aGlzLnNlcnZlcktleVRvU2VydmVyKHNlcnZlcktleSk7XG4gICAgICAgIGNhbGxiYWNrcz8uYmVmb3JlUGluZz8uKHNlcnZlcktleSk7XG4gICAgICAgIHJldHVybiB0aGlzLl92ZXJzaW9uKHNlcnZlcikudGhlbigocmVzcG9uc2UpID0+IHtcbiAgICAgICAgICBjYWxsYmFja3M/LmFmdGVyUGluZz8uKHNlcnZlcktleSk7XG4gICAgICAgICAgcmV0dXJuIHsgc2VydmVyS2V5OiBzZXJ2ZXJLZXksIHZhbHVlOiByZXNwb25zZS52YWx1ZSB9O1xuICAgICAgICB9KTtcbiAgICAgIH0pXG4gICAgKTtcbiAgICBjb25zdCB2YWx1ZXMgPSB2ZXJzaW9uT2JqZWN0cy5yZWR1Y2UoKGFjY3VtdWxhdG9yLCB2ZXJzaW9uT2JqZWN0KSA9PiB7XG4gICAgICBhY2N1bXVsYXRvclt2ZXJzaW9uT2JqZWN0LnNlcnZlcktleV0gPSB2ZXJzaW9uT2JqZWN0LnZhbHVlO1xuICAgICAgcmV0dXJuIGFjY3VtdWxhdG9yO1xuICAgIH0sIHt9IGFzIFJlY29yZDxzdHJpbmcsIFZhbHVlIHwgbnVsbD4pO1xuICAgIHJldHVybiB7IHZhbHVlczogdmFsdWVzIH07XG4gIH1cblxuICAvKipcbiAgICogQ2xvc2VzIChhYnJ1cHRseSkgY29ubmVjdGlvbnMgdG8gYWxsIHRoZSBzZXJ2ZXJzLlxuICAgKiBAc2VlIHRoaXMucXVpdFxuICAgKi9cbiAgY2xvc2UoKSB7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnNlcnZlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHRoaXMuc2VydmVyc1tpXS5jbG9zZSgpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBQZXJmb3JtIGEgZ2VuZXJpYyBzaW5nbGUgcmVzcG9uc2Ugb3BlcmF0aW9uIChnZXQsIHNldCBldGMpIG9uIG9uZSBzZXJ2ZXJcbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IGtleSB0aGUga2V5IHRvIGhhc2ggdG8gZ2V0IGEgc2VydmVyIGZyb20gdGhlIHBvb2xcbiAgICogQHBhcmFtIHtidWZmZXJ9IHJlcXVlc3QgYSBidWZmZXIgY29udGFpbmluZyB0aGUgcmVxdWVzdFxuICAgKiBAcGFyYW0ge251bWJlcn0gc2VxIHRoZSBzZXF1ZW5jZSBudW1iZXIgb2YgdGhlIG9wZXJhdGlvbi4gSXQgaXMgdXNlZCB0byBwaW4gdGhlIGNhbGxiYWNrc1xuICAgICAgICAgICAgICAgICAgICAgICAgIHRvIGEgc3BlY2lmaWMgb3BlcmF0aW9uIGFuZCBzaG91bGQgbmV2ZXIgY2hhbmdlIGR1cmluZyBhIGBwZXJmb3JtYC5cbiAgICogQHBhcmFtIHtudW1iZXI/fSByZXRyaWVzIG51bWJlciBvZiB0aW1lcyB0byByZXRyeSByZXF1ZXN0IG9uIGZhaWx1cmVcbiAgICovXG4gIHBlcmZvcm0oXG4gICAga2V5OiBzdHJpbmcsXG4gICAgcmVxdWVzdDogQnVmZmVyLFxuICAgIHNlcTogbnVtYmVyLFxuICAgIHJldHJpZXM/OiBudW1iZXJcbiAgKTogUHJvbWlzZTxNZXNzYWdlPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGNvbnN0IHNlcnZlcktleSA9IHRoaXMubG9va3VwS2V5VG9TZXJ2ZXJLZXkoa2V5KTtcbiAgICAgIGNvbnN0IHNlcnZlciA9IHRoaXMuc2VydmVyS2V5VG9TZXJ2ZXIoc2VydmVyS2V5KTtcblxuICAgICAgaWYgKCFzZXJ2ZXIpIHtcbiAgICAgICAgcmV0dXJuIHJlamVjdChuZXcgRXJyb3IoXCJObyBzZXJ2ZXJzIGF2YWlsYWJsZVwiKSk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMucGVyZm9ybU9uU2VydmVyKFxuICAgICAgICBzZXJ2ZXIsXG4gICAgICAgIHJlcXVlc3QsXG4gICAgICAgIHNlcSxcbiAgICAgICAgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgcmV0dXJuIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJlc29sdmUocmVzcG9uc2UhKTtcbiAgICAgICAgfSxcbiAgICAgICAgcmV0cmllc1xuICAgICAgKTtcbiAgICB9KTtcbiAgfVxuXG4gIHBlcmZvcm1PblNlcnZlcihcbiAgICBzZXJ2ZXI6IFNlcnZlcixcbiAgICByZXF1ZXN0OiBCdWZmZXIsXG4gICAgc2VxOiBudW1iZXIsXG4gICAgY2FsbGJhY2s6IFJlc3BvbnNlT3JFcnJvckNhbGxiYWNrLFxuICAgIHJldHJpZXM6IG51bWJlciA9IDBcbiAgKSB7XG4gICAgY29uc3QgX3RoaXMgPSB0aGlzO1xuXG4gICAgcmV0cmllcyA9IHJldHJpZXMgfHwgdGhpcy5vcHRpb25zLnJldHJpZXM7XG4gICAgY29uc3Qgb3JpZ1JldHJpZXMgPSB0aGlzLm9wdGlvbnMucmV0cmllcztcbiAgICBjb25zdCBsb2dnZXIgPSB0aGlzLm9wdGlvbnMubG9nZ2VyO1xuICAgIGNvbnN0IHJldHJ5X2RlbGF5ID0gdGhpcy5vcHRpb25zLnJldHJ5X2RlbGF5O1xuXG4gICAgY29uc3QgcmVzcG9uc2VIYW5kbGVyOiBPblJlc3BvbnNlQ2FsbGJhY2sgPSBmdW5jdGlvbiAocmVzcG9uc2UpIHtcbiAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICBjYWxsYmFjayhudWxsLCByZXNwb25zZSk7XG4gICAgICB9XG4gICAgfTtcblxuICAgIGNvbnN0IGVycm9ySGFuZGxlcjogT25FcnJvckNhbGxiYWNrID0gZnVuY3Rpb24gKGVycm9yKSB7XG4gICAgICBpZiAoLS1yZXRyaWVzID4gMCkge1xuICAgICAgICAvLyBXYWl0IGZvciByZXRyeV9kZWxheVxuICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICBfdGhpcy5wZXJmb3JtT25TZXJ2ZXIoc2VydmVyLCByZXF1ZXN0LCBzZXEsIGNhbGxiYWNrLCByZXRyaWVzKTtcbiAgICAgICAgfSwgMTAwMCAqIHJldHJ5X2RlbGF5KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGxvZ2dlci5sb2coXG4gICAgICAgICAgXCJNZW1KUzogU2VydmVyIDxcIiArXG4gICAgICAgICAgICBzZXJ2ZXIuaG9zdHBvcnRTdHJpbmcoKSArXG4gICAgICAgICAgICBcIj4gZmFpbGVkIGFmdGVyIChcIiArXG4gICAgICAgICAgICBvcmlnUmV0cmllcyArXG4gICAgICAgICAgICBcIikgcmV0cmllcyB3aXRoIGVycm9yIC0gXCIgK1xuICAgICAgICAgICAgZXJyb3IubWVzc2FnZVxuICAgICAgICApO1xuICAgICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgICBjYWxsYmFjayhlcnJvciwgbnVsbCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9O1xuXG4gICAgc2VydmVyLm9uUmVzcG9uc2Uoc2VxLCByZXNwb25zZUhhbmRsZXIpO1xuICAgIHNlcnZlci5vbkVycm9yKHNlcSwgZXJyb3JIYW5kbGVyKTtcbiAgICBzZXJ2ZXIud3JpdGUocmVxdWVzdCk7XG4gIH1cblxuICAvLyBJbmNyZW1lbnQgdGhlIHNlcSB2YWx1ZVxuICBpbmNyU2VxKCkge1xuICAgIHRoaXMuc2VxKys7XG5cbiAgICAvLyBXcmFwIGB0aGlzLnNlcWAgdG8gMzItYml0cyBzaW5jZSB0aGUgZmllbGQgd2UgZml0IGl0IGludG8gaXMgb25seSAzMi1iaXRzLlxuICAgIHRoaXMuc2VxICY9IDB4ZmZmZmZmZmY7XG5cbiAgICByZXR1cm4gdGhpcy5zZXE7XG4gIH1cblxuICBwcml2YXRlIGNyZWF0ZUFuZExvZ0Vycm9yKFxuICAgIGNvbW1hbmROYW1lOiBzdHJpbmcsXG4gICAgcmVzcG9uc2VTdGF0dXM6IFJlc3BvbnNlU3RhdHVzIHwgdW5kZWZpbmVkXG4gICk6IEVycm9yIHtcbiAgICBjb25zdCBlcnJvck1lc3NhZ2UgPSBgTWVtSlMgJHtjb21tYW5kTmFtZX06ICR7Y29uc3RhbnRzLnJlc3BvbnNlU3RhdHVzVG9TdHJpbmcoXG4gICAgICByZXNwb25zZVN0YXR1c1xuICAgICl9YDtcbiAgICB0aGlzLm9wdGlvbnMubG9nZ2VyLmxvZyhlcnJvck1lc3NhZ2UpO1xuICAgIHJldHVybiBuZXcgRXJyb3IoZXJyb3JNZXNzYWdlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBMb2cgYW4gZXJyb3IgdG8gdGhlIGxvZ2dlciwgdGhlbiByZXR1cm4gdGhlIGVycm9yLlxuICAgKiBJZiBhIGNhbGxiYWNrIGlzIGdpdmVuLCBjYWxsIGl0IHdpdGggY2FsbGJhY2soZXJyb3IsIG51bGwpLlxuICAgKi9cbiAgcHJpdmF0ZSBoYW5kbGVSZXNwb25zZUVycm9yKFxuICAgIGNvbW1hbmROYW1lOiBzdHJpbmcsXG4gICAgcmVzcG9uc2VTdGF0dXM6IFJlc3BvbnNlU3RhdHVzIHwgdW5kZWZpbmVkLFxuICAgIGNhbGxiYWNrOiB1bmRlZmluZWQgfCAoKGVycm9yOiBFcnJvciB8IG51bGwsIG90aGVyOiBudWxsKSA9PiB2b2lkKVxuICApOiBFcnJvciB7XG4gICAgY29uc3QgZXJyb3IgPSB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKGNvbW1hbmROYW1lLCByZXNwb25zZVN0YXR1cyk7XG4gICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICBjYWxsYmFjayhlcnJvciwgbnVsbCk7XG4gICAgfVxuICAgIHJldHVybiBlcnJvcjtcbiAgfVxufVxuXG5leHBvcnQgeyBDbGllbnQsIFNlcnZlciwgVXRpbHMsIEhlYWRlciB9O1xuIl19 \ No newline at end of file From 2a19d80e5160ebc3f6e8ee9bd80199bda0484d12 Mon Sep 17 00:00:00 2001 From: Leon Wei Date: Fri, 7 Apr 2023 13:11:36 -0700 Subject: [PATCH 67/79] Hanlde server restart --- lib/memjs/memjs.js | 2 +- lib/memjs/server.d.ts.map | 2 +- lib/memjs/server.js | 11 ++++++----- smoketest.js | 19 +++++++++++++++++++ src/memjs/memjs.ts | 2 +- src/memjs/server.ts | 9 +++++---- 6 files changed, 33 insertions(+), 12 deletions(-) diff --git a/lib/memjs/memjs.js b/lib/memjs/memjs.js index f94461e..febe707 100644 --- a/lib/memjs/memjs.js +++ b/lib/memjs/memjs.js @@ -742,4 +742,4 @@ class Client { } } exports.Client = Client; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVtanMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbWVtanMvbWVtanMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLHdCQUF3Qjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUV4QixxQ0FLa0I7QUEyaUNELHVGQTdpQ2YsZUFBTSxPQTZpQ2U7QUExaUN2Qix1REFBK0Q7QUFDL0QsbUNBU2lCO0FBQ2pCLHVEQUF5QztBQUN6QywyQ0FBNkM7QUFDN0MsK0NBQWlDO0FBNmhDUixzQkFBSztBQTVoQzlCLGlEQUFtQztBQTRoQ0gsd0JBQU07QUExaEN0QyxTQUFTLDhCQUE4QixDQUNyQyxPQUFpQixFQUNqQixHQUFXO0lBRVgsTUFBTSxLQUFLLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQztJQUM3QixNQUFNLEtBQUssR0FBRyxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxnQkFBUSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3BELE9BQU8sT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ3hCLENBQUM7QUFFRCwrQ0FBK0M7QUFDL0MsU0FBUyxTQUFTLENBQ2hCLE9BQTBFO0lBRTFFLE9BQU8sSUFBSSxPQUFPLENBQUMsVUFBVSxPQUFPLEVBQUUsTUFBTTtRQUMxQyxPQUFPLENBQUMsVUFBVSxHQUFHLEVBQUUsTUFBTTtZQUMzQixHQUFHLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3RDLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBeURELE1BQU0sTUFBTTtJQVFWLDRFQUE0RTtJQUM1RSxtQ0FBbUM7SUFDbkMsWUFBWSxPQUFpQixFQUFFLE9BQTBDO1FBQ3ZFLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO1FBQ3ZCLElB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QUFtQixFQUNuQixjQUEwQztRQUUxQyxNQUFNLFlBQVksR0FBRyxTQUFTLFdBQVcsS0FBSyxTQUFTLENBQUMsc0JBQXNCLENBQzVFLGNBQWMsQ0FDZixFQUFFLENBQUM7UUFDSixJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDdEMsT0FBTyxJQUFJLEtBQUssQ0FBQyxZQUFZLENBQUMsQ0FBQztJQUNqQyxDQUFDO0lBRUQ7OztPQUdHO0lBQ0ssbUJBQW1CLENBQ3pCLFdBQW1CLEVBQ25CLGNBQTBDLEVBQzFDLFFBQWtFO1FBRWxFLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxXQUFXLEVBQUUsY0FBYyxDQUFDLENBQUM7UUFDbEUsSUFBSSxRQUFRLEVBQUU7WUFDWixRQUFRLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxDQUFDO1NBQ3ZCO1FBQ0QsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0NBQ0Y7QUFFUSx3QkFBTSIsInNvdXJjZXNDb250ZW50IjpbIi8vIE1lbVRTIE1lbWNhY2hlIENsaWVudFxuXG5pbXBvcnQge1xuICBPbkVycm9yQ2FsbGJhY2ssXG4gIE9uUmVzcG9uc2VDYWxsYmFjayxcbiAgU2VydmVyLFxuICBTZXJ2ZXJPcHRpb25zLFxufSBmcm9tIFwiLi9zZXJ2ZXJcIjtcbmltcG9ydCB7IG5vb3BTZXJpYWxpemVyLCBTZXJpYWxpemVyIH0gZnJvbSBcIi4vbm9vcC1zZXJpYWxpemVyXCI7XG5pbXBvcnQge1xuICBtYWtlUmVxdWVzdEJ1ZmZlcixcbiAgY29weUludG9SZXF1ZXN0QnVmZmVyLFxuICBtZXJnZSxcbiAgbWFrZUV4cGlyYXRpb24sXG4gIG1ha2VBbW91bnRJbml0aWFsQW5kRXhwaXJhdGlvbixcbiAgaGFzaENvZGUsXG4gIE1heWJlQnVmZmVyLFxuICBNZXNzYWdlLFxufSBmcm9tIFwiLi91dGlsc1wiO1xuaW1wb3J0ICogYXMgY29uc3RhbnRzIGZyb20gXCIuL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgUmVzcG9uc2VTdGF0dXMgfSBmcm9tIFwiLi9jb25zdGFudHNcIjtcbmltcG9ydCAqIGFzIFV0aWxzIGZyb20gXCIuL3V0aWxzXCI7XG5pbXBvcnQgKiBhcyBIZWFkZXIgZnJvbSBcIi4vaGVhZGVyXCI7XG5cbmZ1bmN0aW9uIGRlZmF1bHRLZXlUb1NlcnZlckhhc2hGdW5jdGlvbihcbiAgc2VydmVyczogc3RyaW5nW10sXG4gIGtleTogc3RyaW5nXG4pOiBzdHJpbmcge1xuICBjb25zdCB0b3RhbCA9IHNlcnZlcnMubGVuZ3RoO1xuICBjb25zdCBpbmRleCA9IHRvdGFsID4gMSA/IGhhc2hDb2RlKGtleSkgJSB0b3RhbCA6IDA7XG4gIHJldHVybiBzZXJ2ZXJzW2luZGV4XTtcbn1cblxuLy8gY29udmVydHMgYSBjYWxsIGludG8gYSBwcm9taXNlLXJldHVybmluZyBvbmVcbmZ1bmN0aW9uIHByb21pc2lmeTxSZXN1bHQ+KFxuICBjb21tYW5kOiAoY2FsbGJhY2s6IChlcnJvcjogRXJyb3IgfCBudWxsLCByZXN1bHQ6IFJlc3VsdCkgPT4gdm9pZCkgPT4gdm9pZFxuKTogUHJvbWlzZTxSZXN1bHQ+IHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICBjb21tYW5kKGZ1bmN0aW9uIChlcnIsIHJlc3VsdCkge1xuICAgICAgZXJyID8gcmVqZWN0KGVycikgOiByZXNvbHZlKHJlc3VsdCk7XG4gICAgfSk7XG4gIH0pO1xufVxuXG50eXBlIFJlc3BvbnNlT3JFcnJvckNhbGxiYWNrID0gKFxuICBlcnJvcjogRXJyb3IgfCBudWxsLFxuICByZXNwb25zZTogTWVzc2FnZSB8IG51bGxcbikgPT4gdm9pZDtcblxuaW50ZXJmYWNlIEJhc2VDbGllbnRPcHRpb25zIHtcbiAgcmV0cmllczogbnVtYmVyO1xuICByZXRyeV9kZWxheTogbnVtYmVyO1xuICBleHBpcmVzOiBudW1iZXI7XG4gIGxvZ2dlcjogeyBsb2c6IHR5cGVvZiBjb25zb2xlLmxvZyB9O1xuICBrZXlUb1NlcnZlckhhc2hGdW5jdGlvbjogdHlwZW9mIGRlZmF1bHRLZXlUb1NlcnZlckhhc2hGdW5jdGlvbjtcbn1cblxuaW50ZXJmYWNlIFNlcmlhbGl6ZXJQcm9wPFZhbHVlLCBFeHRyYXM+IHtcbiAgc2VyaWFsaXplcjogU2VyaWFsaXplcjxWYWx1ZSwgRXh0cmFzPjtcbn1cblxuLyoqXG4gKiBUaGUgY2xpZW50IGhhcyBwYXJ0aWFsIHN1cHBvcnQgZm9yIHNlcmlhbGl6aW5nIGFuZCBkZXNlcmlhbGl6aW5nIHZhbHVlcyBmcm9tIHRoZVxuICogQnVmZmVyIGJ5dGUgc3RyaW5ncyB3ZSByZWNlaXZlIGZyb20gdGhlIHdpcmUuIFRoZSBkZWZhdWx0IHNlcmlhbGl6ZXIgaXMgZm9yIE1heWJlQnVmZmVyLlxuICpcbiAqIElmIFZhbHVlIGFuZCBFeHRyYXMgYXJlIG9mIHR5cGUgQnVmZmVyLCB0aGVuIHJldHVybiB0eXBlIFdoZW5CdWZmZXIuIE90aGVyd2lzZSxcbiAqIHJldHVybiB0eXBlIE5vdEJ1ZmZlci5cbiAqL1xudHlwZSBJZkJ1ZmZlcjxWYWx1ZSwgRXh0cmFzLCBXaGVuVmFsdWVBbmRFeHRyYXNBcmVCdWZmZXJzLCBOb3RCdWZmZXI+ID1cbiAgVmFsdWUgZXh0ZW5kcyBCdWZmZXJcbiAgICA/IEV4dHJhcyBleHRlbmRzIEJ1ZmZlclxuICAgICAgPyBXaGVuVmFsdWVBbmRFeHRyYXNBcmVCdWZmZXJzXG4gICAgICA6IE5vdEJ1ZmZlclxuICAgIDogTm90QnVmZmVyO1xuXG5leHBvcnQgdHlwZSBHaXZlbkNsaWVudE9wdGlvbnM8VmFsdWUsIEV4dHJhcz4gPSBQYXJ0aWFsPEJhc2VDbGllbnRPcHRpb25zPiAmXG4gIElmQnVmZmVyPFxuICAgIFZhbHVlLFxuICAgIEV4dHJhcyxcbiAgICBQYXJ0aWFsPFNlcmlhbGl6ZXJQcm9wPFZhbHVlLCBFeHRyYXM+PixcbiAgICBTZXJpYWxpemVyUHJvcDxWYWx1ZSwgRXh0cmFzPlxuICA+O1xuXG5leHBvcnQgdHlwZSBDQVNUb2tlbiA9IEJ1ZmZlcjtcblxuZXhwb3J0IGludGVyZmFjZSBHZXRSZXN1bHQ8VmFsdWUgPSBNYXliZUJ1ZmZlciwgRXh0cmFzID0gTWF5YmVCdWZmZXI+IHtcbiAgdmFsdWU6IFZhbHVlO1xuICBleHRyYXM6IEV4dHJhcztcbiAgY2FzOiBDQVNUb2tlbiB8IHVuZGVmaW5lZDtcbn1cblxuZXhwb3J0IHR5cGUgR2V0TXVsdGlSZXN1bHQ8XG4gIEtleXMgZXh0ZW5kcyBzdHJpbmcgPSBzdHJpbmcsXG4gIFZhbHVlID0gTWF5YmVCdWZmZXIsXG4gIEV4dHJhcyA9IE1heWJlQnVmZmVyXG4+ID0ge1xuICBbSyBpbiBLZXlzXT86IEdldFJlc3VsdDxWYWx1ZSwgRXh0cmFzPjtcbn07XG5cbmNsYXNzIENsaWVudDxWYWx1ZSA9IE1heWJlQnVmZmVyLCBFeHRyYXMgPSBNYXliZUJ1ZmZlcj4ge1xuICBzZXJ2ZXJzOiBTZXJ2ZXJbXTtcbiAgc2VxOiBudW1iZXI7XG4gIG9wdGlvbnM6IEJhc2VDbGllbnRPcHRpb25zICYgUGFydGlhbDxTZXJpYWxpemVyUHJvcDxWYWx1ZSwgRXh0cmFzPj47XG4gIHNlcmlhbGl6ZXI6IFNlcmlhbGl6ZXI8VmFsdWUsIEV4dHJhcz47XG4gIHNlcnZlck1hcDogeyBbaG9zdHBvcnQ6IHN0cmluZ106IFNlcnZlciB9O1xuICBzZXJ2ZXJLZXlzOiBzdHJpbmdbXTtcblxuICAvLyBDbGllbnQgaW5pdGlhbGl6ZXIgdGFrZXMgYSBsaXN0IG9mIGBTZXJ2ZXJgcyBhbmQgYW4gYG9wdGlvbnNgIGRpY3Rpb25hcnkuXG4gIC8vIFNlZSBgQ2xpZW50LmNyZWF0ZWAgZm9yIGRldGFpbHMuXG4gIGNvbnN0cnVjdG9yKHNlcnZlcnM6IFNlcnZlcltdLCBvcHRpb25zOiBHaXZlbkNsaWVudE9wdGlvbnM8VmFsdWUsIEV4dHJhcz4pIHtcbiAgICB0aGlzLnNlcnZlcnMgPSBzZXJ2ZXJzO1xuICAgIHRoaXMuc2VxID0gMDtcbiAgICB0aGlzLm9wdGlvbnMgPSBtZXJnZShvcHRpb25zIHx8IHt9LCB7XG4gICAgICByZXRyaWVzOiAyLFxuICAgICAgcmV0cnlfZGVsYXk6IDAuMixcbiAgICAgIGV4cGlyZXM6IDAsXG4gICAgICBsb2dnZXI6IGNvbnNvbGUsXG4gICAgICBrZXlUb1NlcnZlckhhc2hGdW5jdGlvbjogZGVmYXVsdEtleVRvU2VydmVySGFzaEZ1bmN0aW9uLFxuICAgIH0pO1xuXG4gICAgdGhpcy5zZXJpYWxpemVyID0gdGhpcy5vcHRpb25zLnNlcmlhbGl6ZXIgfHwgKG5vb3BTZXJpYWxpemVyIGFzIGFueSk7XG5cbiAgICAvLyBTdG9yZSBhIG1hcHBpbmcgZnJvbSBob3N0cG9ydCAtPiBzZXJ2ZXIgc28gd2UgY2FuIHF1aWNrbHkgZ2V0IGEgc2VydmVyIG9iamVjdCBmcm9tIHRoZSBzZXJ2ZXJLZXkgcmV0dXJuZWQgYnkgdGhlIGhhc2hpbmcgZnVuY3Rpb25cbiAgICBjb25zdCBzZXJ2ZXJNYXA6IHsgW2hvc3Rwb3J0OiBzdHJpbmddOiBTZXJ2ZXIgfSA9IHt9O1xuICAgIHRoaXMuc2VydmVycy5mb3JFYWNoKGZ1bmN0aW9uIChzZXJ2ZXIpIHtcbiAgICAgIHNlcnZlck1hcFtzZXJ2ZXIuaG9zdHBvcnRTdHJpbmcoKV0gPSBzZXJ2ZXI7XG4gICAgfSk7XG4gICAgdGhpcy5zZXJ2ZXJNYXAgPSBzZXJ2ZXJNYXA7XG5cbiAgICAvLyBzdG9yZSBhIGxpc3Qgb2YgYWxsIG91ciBzZXJ2ZXJLZXlzIHNvIHdlIGRvbid0IG5lZWQgdG8gY29uc3RhbnRseSByZWFsbG9jYXRlIHRoaXMgYXJyYXlcbiAgICB0aGlzLnNlcnZlcktleXMgPSBPYmplY3Qua2V5cyh0aGlzLnNlcnZlck1hcCk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIG5ldyBjbGllbnQgZ2l2ZW4gYW4gb3B0aW9uYWwgY29uZmlnIHN0cmluZyBhbmQgb3B0aW9uYWwgaGFzaCBvZlxuICAgKiBvcHRpb25zLiBUaGUgY29uZmlnIHN0cmluZyBzaG91bGQgYmUgb2YgdGhlIGZvcm06XG4gICAqXG4gICAqICAgICBcIlt1c2VyOnBhc3NAXXNlcnZlcjFbOjExMjExXSxbdXNlcjpwYXNzQF1zZXJ2ZXIyWzoxMTIxMV0sLi4uXCJcbiAgICpcbiAgICogSWYgdGhlIGFyZ3VtZW50IGlzIG5vdCBnaXZlbiwgZmFsbGJhY2sgb24gdGhlIGBNRU1DQUNISUVSX1NFUlZFUlNgIGVudmlyb25tZW50XG4gICAqIHZhcmlhYmxlLCBgTUVNQ0FDSEVfU0VSVkVSU2AgZW52aXJvbm1lbnQgdmFyaWFibGUgb3IgYFwibG9jYWxob3N0OjExMjExXCJgLlxuICAgKlxuICAgKiBUaGUgb3B0aW9ucyBoYXNoIG1heSBjb250YWluIHRoZSBvcHRpb25zOlxuICAgKlxuICAgKiAqIGByZXRyaWVzYCAtIHRoZSBudW1iZXIgb2YgdGltZXMgdG8gcmV0cnkgYW4gb3BlcmF0aW9uIGluIGxpZXUgb2YgZmFpbHVyZXNcbiAgICogKGRlZmF1bHQgMilcbiAgICogKiBgZXhwaXJlc2AgLSB0aGUgZGVmYXVsdCBleHBpcmF0aW9uIGluIHNlY29uZHMgdG8gdXNlIChkZWZhdWx0IDAgLSBuZXZlclxuICAgKiBleHBpcmUpLiBJZiBgZXhwaXJlc2AgaXMgZ3JlYXRlciB0aGFuIDMwIGRheXMgKDYwIHggNjAgeCAyNCB4IDMwKSwgaXQgaXNcbiAgICogdHJlYXRlZCBhcyBhIFVOSVggdGltZSAobnVtYmVyIG9mIHNlY29uZHMgc2luY2UgSmFudWFyeSAxLCAxOTcwKS5cbiAgICogKiBgbG9nZ2VyYCAtIGEgbG9nZ2VyIG9iamVjdCB0aGF0IHJlc3BvbmRzIHRvIGBsb2coc3RyaW5nKWAgbWV0aG9kIGNhbGxzLlxuICAgKlxuICAgKiAgIH5+fn5cbiAgICogICAgIGxvZyhtc2cxWywgbXNnMlssIG1zZzNbLi4uXV1dKVxuICAgKiAgIH5+fn5cbiAgICpcbiAgICogICBEZWZhdWx0cyB0byBgY29uc29sZWAuXG4gICAqICogYHNlcmlhbGl6ZXJgIC0gdGhlIG9iamVjdCB3aGljaCB3aWxsIChkZSlzZXJpYWxpemUgdGhlIGRhdGEuIEl0IG5lZWRzXG4gICAqICAgdHdvIHB1YmxpYyBtZXRob2RzOiBzZXJpYWxpemUgYW5kIGRlc2VyaWFsaXplLiBJdCBkZWZhdWx0cyB0byB0aGVcbiAgICogICBub29wU2VyaWFsaXplcjpcbiAgICpcbiAgICogICB+fn5+XG4gICAqICAgY29uc3Qgbm9vcFNlcmlhbGl6ZXIgPSB7XG4gICAqICAgICBzZXJpYWxpemU6IGZ1bmN0aW9uIChvcGNvZGUsIHZhbHVlLCBleHRyYXMpIHtcbiAgICogICAgICAgcmV0dXJuIHsgdmFsdWU6IHZhbHVlLCBleHRyYXM6IGV4dHJhcyB9O1xuICAgKiAgICAgfSxcbiAgICogICAgIGRlc2VyaWFsaXplOiBmdW5jdGlvbiAob3Bjb2RlLCB2YWx1ZSwgZXh0cmFzKSB7XG4gICAqICAgICAgIHJldHVybiB7IHZhbHVlOiB2YWx1ZSwgZXh0cmFzOiBleHRyYXMgfTtcbiAgICogICAgIH1cbiAgICogICB9O1xuICAgKiAgIH5+fn5cbiAgICpcbiAgICogT3Igb3B0aW9ucyBmb3IgdGhlIHNlcnZlcnMgaW5jbHVkaW5nOlxuICAgKiAqIGB1c2VybmFtZWAgYW5kIGBwYXNzd29yZGAgZm9yIGZhbGxiYWNrIFNBU0wgYXV0aGVudGljYXRpb24gY3JlZGVudGlhbHMuXG4gICAqICogYHRpbWVvdXRgIGluIHNlY29uZHMgdG8gZGV0ZXJtaW5lIGZhaWx1cmUgZm9yIG9wZXJhdGlvbnMuIERlZmF1bHQgaXMgMC41XG4gICAqICAgICAgICAgICAgIHNlY29uZHMuXG4gICAqICogJ2Nvbm50aW1lb3V0JyBpbiBzZWNvbmRzIHRvIGNvbm5lY3Rpb24gZmFpbHVyZS4gRGVmYXVsdCBpcyB0d2ljZSB0aGUgdmFsdWVcbiAgICogICAgICAgICAgICAgICAgIG9mIGB0aW1lb3V0YC5cbiAgICogKiBga2VlcEFsaXZlYCB3aGV0aGVyIHRvIGVuYWJsZSBrZWVwLWFsaXZlIGZ1bmN0aW9uYWxpdHkuIERlZmF1bHRzIHRvIGZhbHNlLlxuICAgKiAqIGBrZWVwQWxpdmVEZWxheWAgaW4gc2Vjb25kcyB0byB0aGUgaW5pdGlhbCBkZWxheSBiZWZvcmUgdGhlIGZpcnN0IGtlZXBhbGl2ZVxuICAgKiAgICAgICAgICAgICAgICAgICAgcHJvYmUgaXMgc2VudCBvbiBhbiBpZGxlIHNvY2tldC4gRGVmYXVsdHMgaXMgMzAgc2Vjb25kcy5cbiAgICogKiBga2V5VG9TZXJ2ZXJIYXNoRnVuY3Rpb25gIGEgZnVuY3Rpb24gdG8gbWFwIGtleXMgdG8gc2VydmVycywgd2l0aCB0aGUgc2lnbmF0dXJlXG4gICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgIChzZXJ2ZXJLZXlzOiBzdHJpbmdbXSwga2V5OiBzdHJpbmcpOiBzdHJpbmdcbiAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgTk9URTogaWYgeW91IG5lZWQgdG8gZG8gc29tZSBleHBlbnNpdmUgaW5pdGlhbGl6YXRpb24sICpwbGVhc2UqIGRvIGl0IGxhemlseSB0aGUgZmlyc3QgdGltZSB5b3UgdGhpcyBmdW5jdGlvbiBpcyBjYWxsZWQgd2l0aCBhbiBhcnJheSBvZiBzZXJ2ZXJLZXlzLCBub3Qgb24gZXZlcnkgY2FsbFxuICAgKi9cbiAgc3RhdGljIGNyZWF0ZTxWYWx1ZSwgRXh0cmFzPihcbiAgICBzZXJ2ZXJzU3RyOiBzdHJpbmcgfCB1bmRlZmluZWQsXG4gICAgb3B0aW9uczogSWZCdWZmZXI8XG4gICAgICBWYWx1ZSxcbiAgICAgIEV4dHJhcyxcbiAgICAgIHVuZGVmaW5lZCB8IChQYXJ0aWFsPFNlcnZlck9wdGlvbnM+ICYgR2l2ZW5DbGllbnRPcHRpb25zPFZhbHVlLCBFeHRyYXM+KSxcbiAgICAgIFBhcnRpYWw8U2VydmVyT3B0aW9ucz4gJiBHaXZlbkNsaWVudE9wdGlvbnM8VmFsdWUsIEV4dHJhcz5cbiAgICA+XG4gICk6IENsaWVudDxWYWx1ZSwgRXh0cmFzPiB7XG4gICAgc2VydmVyc1N0ciA9XG4gICAgICBzZXJ2ZXJzU3RyIHx8XG4gICAgICBwcm9jZXNzLmVudi5NRU1DQUNISUVSX1NFUlZFUlMgfHxcbiAgICAgIHByb2Nlc3MuZW52Lk1FTUNBQ0hFX1NFUlZFUlMgfHxcbiAgICAgIFwibG9jYWxob3N0OjExMjExXCI7XG4gICAgY29uc3Qgc2VydmVyVXJpcyA9IHNlcnZlcnNTdHIuc3BsaXQoXCIsXCIpO1xuICAgIGNvbnN0IHNlcnZlcnMgPSBzZXJ2ZXJVcmlzLm1hcChmdW5jdGlvbiAodXJpKSB7XG4gICAgICBjb25zdCB1cmlQYXJ0cyA9IHVyaS5zcGxpdChcIkBcIik7XG4gICAgICBjb25zdCBob3N0UG9ydCA9IHVyaVBhcnRzW3VyaVBhcnRzLmxlbmd0aCAtIDFdLnNwbGl0KFwiOlwiKTtcbiAgICAgIGNvbnN0IHVzZXJQYXNzID0gKHVyaVBhcnRzW3VyaVBhcnRzLmxlbmd0aCAtIDJdIHx8IFwiXCIpLnNwbGl0KFwiOlwiKTtcbiAgICAgIHJldHVybiBuZXcgU2VydmVyKFxuICAgICAgICBob3N0UG9ydFswXSxcbiAgICAgICAgcGFyc2VJbnQoaG9zdFBvcnRbMV0gfHwgXCIxMTIxMVwiLCAxMCksXG4gICAgICAgIHVzZXJQYXNzWzBdLFxuICAgICAgICB1c2VyUGFzc1sxXSxcbiAgICAgICAgb3B0aW9uc1xuICAgICAgKTtcbiAgICB9KTtcbiAgICByZXR1cm4gbmV3IENsaWVudChzZXJ2ZXJzLCBvcHRpb25zIGFzIGFueSk7XG4gIH1cblxuICAvKipcbiAgICogR2l2ZW4gYSBzZXJ2ZXJLZXkgZnJvbWxvb2t1cEtleVRvU2VydmVyS2V5LCByZXR1cm4gdGhlIGNvcnJlc3BvbmRpbmcgU2VydmVyIGluc3RhbmNlXG4gICAqXG4gICAqIEBwYXJhbSAge3N0cmluZ30gc2VydmVyS2V5XG4gICAqIEByZXR1cm5zIHtTZXJ2ZXJ9XG4gICAqL1xuICBzZXJ2ZXJLZXlUb1NlcnZlcihzZXJ2ZXJLZXk6IHN0cmluZyk6IFNlcnZlciB7XG4gICAgcmV0dXJuIHRoaXMuc2VydmVyTWFwW3NlcnZlcktleV07XG4gIH1cblxuICAvKipcbiAgICogR2l2ZW4gYSBrZXkgdG8gbG9vayB1cCBpbiBtZW1jYWNoZSwgcmV0dXJuIGEgc2VydmVyS2V5IChiYXNlZCBvbiBzb21lXG4gICAqIGhhc2hpbmcgZnVuY3Rpb24pIHdoaWNoIGNhbiBiZSB1c2VkIHRvIGluZGV4IHRoaXMuc2VydmVyTWFwXG4gICAqL1xuICBsb29rdXBLZXlUb1NlcnZlcktleShrZXk6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMub3B0aW9ucy5rZXlUb1NlcnZlckhhc2hGdW5jdGlvbih0aGlzLnNlcnZlcktleXMsIGtleSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldmVzIHRoZSB2YWx1ZSBhdCB0aGUgZ2l2ZW4ga2V5IGluIG1lbWNhY2hlLlxuICAgKi9cbiAgYXN5bmMgZ2V0KGtleTogc3RyaW5nKTogUHJvbWlzZTxHZXRSZXN1bHQ8VmFsdWUsIEV4dHJhcz4gfCBudWxsPiB7XG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKGNvbnN0YW50cy5PUF9HRVQsIGtleSwgXCJcIiwgXCJcIiwgdGhpcy5zZXEpO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICBjb25zdCBkZXNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuZGVzZXJpYWxpemUoXG4gICAgICAgICAgcmVzcG9uc2UuaGVhZGVyLm9wY29kZSxcbiAgICAgICAgICByZXNwb25zZS52YWwsXG4gICAgICAgICAgcmVzcG9uc2UuZXh0cmFzXG4gICAgICAgICk7XG4gICAgICAgIHJldHVybiB7IC4uLmRlc2VyaWFsaXplZCwgY2FzOiByZXNwb25zZS5oZWFkZXIuY2FzIH07XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIkdFVFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKiogQnVpbGQgYSBwaXBlbGluZWQgZ2V0IG11bHRpIHJlcXVlc3QgYnkgc2VuZGluZyBvbmUgR0VUS1EgZm9yIGVhY2gga2V5IChxdWlldCwgbWVhbmluZyBpdCB3b24ndCByZXNwb25kIGlmIHRoZSB2YWx1ZSBpcyBtaXNzaW5nKSBmb2xsb3dlZCBieSBhIG5vLW9wIHRvIGZvcmNlIGEgcmVzcG9uc2UgKGFuZCB0byBnaXZlIHVzIGEgc2VudGluZWwgcmVzcG9uc2UgdGhhdCB0aGUgcGlwZWxpbmUgaXMgZG9uZSlcbiAgICpcbiAgICogY2YgaHR0cHM6Ly9naXRodWIuY29tL2NvdWNoYmFzZS9tZW1jYWNoZWQvYmxvYi9tYXN0ZXIvZG9jcy9CaW5hcnlQcm90b2NvbC5tZCMweDBkLWdldGtxLWdldC13aXRoLWtleS1xdWlldGx5XG4gICAqL1xuICBfYnVpbGRHZXRNdWx0aVJlcXVlc3Qoa2V5czogc3RyaW5nW10sIHNlcTogbnVtYmVyKTogQnVmZmVyIHtcbiAgICAvLyBzdGFydCBhdCAyNCBmb3IgdGhlIG5vLW9wIGNvbW1hbmQgYXQgdGhlIGVuZFxuICAgIGxldCByZXF1ZXN0U2l6ZSA9IDI0O1xuICAgIGZvciAoY29uc3Qga2V5SWR4IGluIGtleXMpIHtcbiAgICAgIHJlcXVlc3RTaXplICs9IEJ1ZmZlci5ieXRlTGVuZ3RoKGtleXNba2V5SWR4XSwgXCJ1dGY4XCIpICsgMjQ7XG4gICAgfVxuXG4gICAgY29uc3QgcmVxdWVzdCA9IEJ1ZmZlci5hbGxvYyhyZXF1ZXN0U2l6ZSk7XG5cbiAgICBsZXQgYnl0ZXNXcml0dGVuID0gMDtcbiAgICBmb3IgKGNvbnN0IGtleUlkeCBpbiBrZXlzKSB7XG4gICAgICBjb25zdCBrZXkgPSBrZXlzW2tleUlkeF07XG4gICAgICBieXRlc1dyaXR0ZW4gKz0gY29weUludG9SZXF1ZXN0QnVmZmVyKFxuICAgICAgICBjb25zdGFudHMuT1BfR0VUS1EsXG4gICAgICAgIGtleSxcbiAgICAgICAgXCJcIixcbiAgICAgICAgXCJcIixcbiAgICAgICAgc2VxLFxuICAgICAgICByZXF1ZXN0LFxuICAgICAgICBieXRlc1dyaXR0ZW5cbiAgICAgICk7XG4gICAgfVxuXG4gICAgYnl0ZXNXcml0dGVuICs9IGNvcHlJbnRvUmVxdWVzdEJ1ZmZlcihcbiAgICAgIGNvbnN0YW50cy5PUF9OT19PUCxcbiAgICAgIFwiXCIsXG4gICAgICBcIlwiLFxuICAgICAgXCJcIixcbiAgICAgIHNlcSxcbiAgICAgIHJlcXVlc3QsXG4gICAgICBieXRlc1dyaXR0ZW5cbiAgICApO1xuXG4gICAgcmV0dXJuIHJlcXVlc3Q7XG4gIH1cblxuICAvKiogRXhlY3V0aW5nIGEgcGlwZWxpbmVkIChtdWx0aSkgZ2V0IGFnYWluc3QgYSBzaW5nbGUgc2VydmVyLiBUaGlzIGlzIGEgcHJpdmF0ZSBpbXBsZW1lbnRhdGlvbiBkZXRhaWwgb2YgZ2V0TXVsdGkuICovXG4gIGFzeW5jIF9nZXRNdWx0aVRvU2VydmVyPEtleXMgZXh0ZW5kcyBzdHJpbmc+KFxuICAgIHNlcnY6IFNlcnZlcixcbiAgICBrZXlzOiBLZXlzW11cbiAgKTogUHJvbWlzZTxHZXRNdWx0aVJlc3VsdDxLZXlzLCBWYWx1ZSwgRXh0cmFzPj4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBjb25zdCByZXNwb25zZU1hcDogR2V0TXVsdGlSZXN1bHQ8c3RyaW5nLCBWYWx1ZSwgRXh0cmFzPiA9IHt9O1xuXG4gICAgICBjb25zdCBoYW5kbGU6IE9uUmVzcG9uc2VDYWxsYmFjayA9IChyZXNwb25zZSkgPT4ge1xuICAgICAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgICAgICAvLyBXaGVuIHdlIGdldCB0aGUgbm8tb3AgcmVzcG9uc2UsIHdlIGFyZSBkb25lIHdpdGggdGhpcyBvbmUgZ2V0TXVsdGkgaW4gdGhlIHBlci1iYWNrZW5kIGZhbi1vdXRcbiAgICAgICAgICAgIGlmIChyZXNwb25zZS5oZWFkZXIub3Bjb2RlID09PSBjb25zdGFudHMuT1BfTk9fT1ApIHtcbiAgICAgICAgICAgICAgLy8gVGhpcyBlbnN1cmVzIHRoZSBoYW5kbGVyIHdpbGwgYmUgZGVsZXRlZCBmcm9tIHRoZSByZXNwb25zZUNhbGxiYWNrcyBtYXAgaW4gc2VydmVyLmpzXG4gICAgICAgICAgICAgIC8vIFRoaXMgaXNuJ3QgdGVjaG5pY2FsbHkgbmVlZGVkIGhlcmUgYmVjYXVzZSB0aGUgbG9naWMgaW4gc2VydmVyLmpzIGFsc28gY2hlY2tzIGlmIHRvdGFsQm9keUxlbmd0aCA9PT0gMCwgYnV0IG91ciB1bml0dGVzdHMgYXJlbid0IGdyZWF0IGFib3V0IHNldHRpbmcgdGhhdCBmaWVsZCwgYW5kIGFsc28gdGhpcyBtYWtlcyBpdCBtb3JlIGV4cGxpY2l0XG4gICAgICAgICAgICAgIGhhbmRsZS5xdWlldCA9IGZhbHNlO1xuICAgICAgICAgICAgICByZXNvbHZlKHJlc3BvbnNlTWFwKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgICAgICAgIHJlc3BvbnNlLmhlYWRlci5vcGNvZGUgPT09IGNvbnN0YW50cy5PUF9HRVRLIHx8XG4gICAgICAgICAgICAgIHJlc3BvbnNlLmhlYWRlci5vcGNvZGUgPT09IGNvbnN0YW50cy5PUF9HRVRLUVxuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgIGNvbnN0IGRlc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5kZXNlcmlhbGl6ZShcbiAgICAgICAgICAgICAgICByZXNwb25zZS5oZWFkZXIub3Bjb2RlLFxuICAgICAgICAgICAgICAgIHJlc3BvbnNlLnZhbCxcbiAgICAgICAgICAgICAgICByZXNwb25zZS5leHRyYXNcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgY29uc3Qga2V5ID0gcmVzcG9uc2Uua2V5LnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgIGlmIChrZXkubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlamVjdChcbiAgICAgICAgICAgICAgICAgIG5ldyBFcnJvcihcbiAgICAgICAgICAgICAgICAgICAgXCJSZWNpZXZlZCBlbXB0eSBrZXkgaW4gZ2V0TXVsdGk6IFwiICtcbiAgICAgICAgICAgICAgICAgICAgICBKU09OLnN0cmluZ2lmeShyZXNwb25zZSlcbiAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIHJlc3BvbnNlTWFwW2tleV0gPSB7IC4uLmRlc2VyaWFsaXplZCwgY2FzOiByZXNwb25zZS5oZWFkZXIuY2FzIH07XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICByZXR1cm4gcmVqZWN0KFxuICAgICAgICAgICAgICAgIG5ldyBFcnJvcihcbiAgICAgICAgICAgICAgICAgIFwiUmVjaWV2ZWQgcmVzcG9uc2UgaW4gZ2V0TXVsdGkgZm9yIHVua25vd24gb3Bjb2RlOiBcIiArXG4gICAgICAgICAgICAgICAgICAgIEpTT04uc3RyaW5naWZ5KHJlc3BvbnNlKVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICByZXR1cm4gcmVqZWN0KFxuICAgICAgICAgICAgICB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiR0VUXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9O1xuICAgICAgLy8gVGhpcyBwcmV2ZW50cyB0aGUgaGFuZGxlciBmcm9tIGJlaW5nIGRlbGV0ZWRcbiAgICAgIC8vIGFmdGVyIHRoZSBmaXJzdCByZXNwb25zZS4gTG9naWMgaW4gc2VydmVyLmpzLlxuICAgICAgaGFuZGxlLnF1aWV0ID0gdHJ1ZTtcblxuICAgICAgY29uc3Qgc2VxID0gdGhpcy5pbmNyU2VxKCk7XG4gICAgICBjb25zdCByZXF1ZXN0ID0gdGhpcy5fYnVpbGRHZXRNdWx0aVJlcXVlc3Qoa2V5cywgc2VxKTtcbiAgICAgIHNlcnYub25SZXNwb25zZSh0aGlzLnNlcSwgaGFuZGxlKTtcbiAgICAgIHNlcnYub25FcnJvcih0aGlzLnNlcSwgcmVqZWN0KTtcbiAgICAgIHNlcnYud3JpdGUocmVxdWVzdCk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldnMgdGhlIHZhbHVlIGF0IHRoZSBnaXZlbiBrZXlzIGluIG1lbWNhY2hlZC4gUmV0dXJucyBhIG1hcCBmcm9tIHRoZVxuICAgKiByZXF1ZXN0ZWQga2V5cyB0byByZXN1bHRzLCBvciBudWxsIGlmIHRoZSBrZXkgd2FzIG5vdCBmb3VuZC5cbiAgICovXG4gIGFzeW5jIGdldE11bHRpPEtleXMgZXh0ZW5kcyBzdHJpbmc+KFxuICAgIGtleXM6IEtleXNbXVxuICApOiBQcm9taXNlPEdldE11bHRpUmVzdWx0PEtleXMsIFZhbHVlLCBFeHRyYXM+PiB7XG4gICAgY29uc3Qgc2VydmVyS2V5dG9Mb29rdXBLZXlzOiB7XG4gICAgICBbc2VydmVyS2V5OiBzdHJpbmddOiBzdHJpbmdbXTtcbiAgICB9ID0ge307XG4gICAga2V5cy5mb3JFYWNoKChsb29rdXBLZXkpID0+IHtcbiAgICAgIGNvbnN0IHNlcnZlcktleSA9IHRoaXMubG9va3VwS2V5VG9TZXJ2ZXJLZXkobG9va3VwS2V5KTtcbiAgICAgIGlmICghc2VydmVyS2V5dG9Mb29rdXBLZXlzW3NlcnZlcktleV0pIHtcbiAgICAgICAgc2VydmVyS2V5dG9Mb29rdXBLZXlzW3NlcnZlcktleV0gPSBbXTtcbiAgICAgIH1cbiAgICAgIHNlcnZlcktleXRvTG9va3VwS2V5c1tzZXJ2ZXJLZXldLnB1c2gobG9va3VwS2V5KTtcbiAgICB9KTtcblxuICAgIGNvbnN0IHVzZWRTZXJ2ZXJLZXlzID0gT2JqZWN0LmtleXMoc2VydmVyS2V5dG9Mb29rdXBLZXlzKTtcbiAgICBjb25zdCByZXN1bHRzID0gYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICB1c2VkU2VydmVyS2V5cy5tYXAoKHNlcnZlcktleSkgPT4ge1xuICAgICAgICBjb25zdCBzZXJ2ZXIgPSB0aGlzLnNlcnZlcktleVRvU2VydmVyKHNlcnZlcktleSk7XG4gICAgICAgIHJldHVybiB0aGlzLl9nZXRNdWx0aVRvU2VydmVyKHNlcnZlciwgc2VydmVyS2V5dG9Mb29rdXBLZXlzW3NlcnZlcktleV0pO1xuICAgICAgfSlcbiAgICApO1xuXG4gICAgcmV0dXJuIE9iamVjdC5hc3NpZ24oe30sIC4uLnJlc3VsdHMpO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgYGtleWAgdG8gYHZhbHVlYC5cbiAgICovXG4gIGFzeW5jIHNldChcbiAgICBrZXk6IHN0cmluZyxcbiAgICB2YWx1ZTogVmFsdWUsXG4gICAgb3B0aW9ucz86IHsgZXhwaXJlcz86IG51bWJlcjsgY2FzPzogQ0FTVG9rZW4gfVxuICApOiBQcm9taXNlPGJvb2xlYW4gfCBudWxsPiB7XG4gICAgY29uc3QgZXhwaXJlcyA9IG9wdGlvbnM/LmV4cGlyZXM7XG4gICAgY29uc3QgY2FzID0gb3B0aW9ucz8uY2FzO1xuXG4gICAgLy8gVE9ETzogc3VwcG9ydCBmbGFnc1xuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IGV4cGlyYXRpb24gPSBtYWtlRXhwaXJhdGlvbihleHBpcmVzIHx8IHRoaXMub3B0aW9ucy5leHBpcmVzKTtcbiAgICBjb25zdCBleHRyYXMgPSBCdWZmZXIuY29uY2F0KFtCdWZmZXIuZnJvbShcIjAwMDAwMDAwXCIsIFwiaGV4XCIpLCBleHBpcmF0aW9uXSk7XG4gICAgY29uc3Qgc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5zZXJpYWxpemUoXG4gICAgICBjb25zdGFudHMuT1BfU0VULFxuICAgICAgdmFsdWUsXG4gICAgICBleHRyYXNcbiAgICApO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBVdGlscy5lbmNvZGVSZXF1ZXN0KHtcbiAgICAgIGhlYWRlcjoge1xuICAgICAgICBvcGNvZGU6IGNvbnN0YW50cy5PUF9TRVQsXG4gICAgICAgIG9wYXF1ZTogdGhpcy5zZXEsXG4gICAgICAgIGNhcyxcbiAgICAgIH0sXG4gICAgICBrZXksXG4gICAgICB2YWx1ZTogc2VyaWFsaXplZC52YWx1ZSxcbiAgICAgIGV4dHJhczogc2VyaWFsaXplZC5leHRyYXMsXG4gICAgfSk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfRVhJU1RTOlxuICAgICAgICBpZiAoY2FzKSB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJTRVRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgICAgIH1cbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJTRVRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEFERFxuICAgKlxuICAgKiBBZGRzIHRoZSBnaXZlbiBfa2V5XyBhbmQgX3ZhbHVlXyB0byBtZW1jYWNoZS4gVGhlIG9wZXJhdGlvbiBvbmx5IHN1Y2NlZWRzXG4gICAqIGlmIHRoZSBrZXkgaXMgbm90IGFscmVhZHkgc2V0LlxuICAgKlxuICAgKiBUaGUgb3B0aW9ucyBkaWN0aW9uYXJ5IHRha2VzOlxuICAgKiAqIF9leHBpcmVzXzogb3ZlcnJpZGVzIHRoZSBkZWZhdWx0IGV4cGlyYXRpb24gKHNlZSBgQ2xpZW50LmNyZWF0ZWApIGZvciB0aGlzXG4gICAqICAgICAgICAgICAgICBwYXJ0aWN1bGFyIGtleS12YWx1ZSBwYWlyLlxuICAgKi9cbiAgYXN5bmMgYWRkKFxuICAgIGtleTogc3RyaW5nLFxuICAgIHZhbHVlOiBWYWx1ZSxcbiAgICBvcHRpb25zPzogeyBleHBpcmVzPzogbnVtYmVyIH1cbiAgKTogUHJvbWlzZTxib29sZWFuIHwgbnVsbD4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgZmxhZ3MsIHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IGV4cGlyYXRpb24gPSBtYWtlRXhwaXJhdGlvbihvcHRpb25zPy5leHBpcmVzIHx8IHRoaXMub3B0aW9ucy5leHBpcmVzKTtcbiAgICBjb25zdCBleHRyYXMgPSBCdWZmZXIuY29uY2F0KFtCdWZmZXIuZnJvbShcIjAwMDAwMDAwXCIsIFwiaGV4XCIpLCBleHBpcmF0aW9uXSk7XG5cbiAgICBjb25zdCBvcGNvZGUgPSBjb25zdGFudHMuT1BfQUREO1xuICAgIGNvbnN0IHNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuc2VyaWFsaXplKG9wY29kZSwgdmFsdWUsIGV4dHJhcyk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKFxuICAgICAgb3Bjb2RlLFxuICAgICAga2V5LFxuICAgICAgc2VyaWFsaXplZC5leHRyYXMsXG4gICAgICBzZXJpYWxpemVkLnZhbHVlLFxuICAgICAgdGhpcy5zZXFcbiAgICApO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuS0VZX0VYSVNUUzpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJBRERcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlcGxhY2VzIHRoZSBnaXZlbiBfa2V5XyBhbmQgX3ZhbHVlXyB0byBtZW1jYWNoZS4gVGhlIG9wZXJhdGlvbiBvbmx5IHN1Y2NlZWRzXG4gICAqIGlmIHRoZSBrZXkgaXMgYWxyZWFkeSBwcmVzZW50LlxuICAgKi9cbiAgYXN5bmMgcmVwbGFjZShcbiAgICBrZXk6IHN0cmluZyxcbiAgICB2YWx1ZTogVmFsdWUsXG4gICAgb3B0aW9ucz86IHsgZXhwaXJlcz86IG51bWJlciB9XG4gICk6IFByb21pc2U8Ym9vbGVhbiB8IG51bGw+IHtcbiAgICAvLyBUT0RPOiBzdXBwb3J0IGZsYWdzLCBzdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBleHBpcmF0aW9uID0gbWFrZUV4cGlyYXRpb24ob3B0aW9ucz8uZXhwaXJlcyB8fCB0aGlzLm9wdGlvbnMuZXhwaXJlcyk7XG4gICAgY29uc3QgZXh0cmFzID0gQnVmZmVyLmNvbmNhdChbQnVmZmVyLmZyb20oXCIwMDAwMDAwMFwiLCBcImhleFwiKSwgZXhwaXJhdGlvbl0pO1xuXG4gICAgY29uc3Qgb3Bjb2RlOiBjb25zdGFudHMuT1AgPSBjb25zdGFudHMuT1BfUkVQTEFDRTtcbiAgICBjb25zdCBzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLnNlcmlhbGl6ZShvcGNvZGUsIHZhbHVlLCBleHRyYXMpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgIG9wY29kZSxcbiAgICAgIGtleSxcbiAgICAgIHNlcmlhbGl6ZWQuZXh0cmFzLFxuICAgICAgc2VyaWFsaXplZC52YWx1ZSxcbiAgICAgIHRoaXMuc2VxXG4gICAgKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJSRVBMQUNFXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBEZWxldGVzIHRoZSBnaXZlbiBfa2V5XyBmcm9tIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHNcbiAgICogaWYgdGhlIGtleSBpcyBhbHJlYWR5IHByZXNlbnQuXG4gICAqL1xuICBhc3luYyBkZWxldGUoa2V5OiBzdHJpbmcpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAvLyBUT0RPOiBTdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoNCwga2V5LCBcIlwiLCBcIlwiLCB0aGlzLnNlcSk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG5cbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJERUxFVEVcIiwgcmVzcG9uc2U/LmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBJbmNyZW1lbnRzIHRoZSBnaXZlbiBfa2V5XyBpbiBtZW1jYWNoZS5cbiAgICovXG4gIGFzeW5jIGluY3JlbWVudChcbiAgICBrZXk6IHN0cmluZyxcbiAgICBhbW91bnQ6IG51bWJlcixcbiAgICBvcHRpb25zPzogeyBpbml0aWFsPzogbnVtYmVyOyBleHBpcmVzPzogbnVtYmVyIH1cbiAgKTogUHJvbWlzZTx7IHZhbHVlOiBudW1iZXIgfCBudWxsOyBzdWNjZXNzOiBib29sZWFuIHwgbnVsbCB9PiB7XG4gICAgLy8gVE9ETzogc3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgaW5pdGlhbCA9IG9wdGlvbnM/LmluaXRpYWwgfHwgMDtcbiAgICBjb25zdCBleHBpcmVzID0gb3B0aW9ucz8uZXhwaXJlcyB8fCB0aGlzLm9wdGlvbnMuZXhwaXJlcztcbiAgICBjb25zdCBleHRyYXMgPSBtYWtlQW1vdW50SW5pdGlhbEFuZEV4cGlyYXRpb24oYW1vdW50LCBpbml0aWFsLCBleHBpcmVzKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICBjb25zdGFudHMuT1BfSU5DUkVNRU5ULFxuICAgICAga2V5LFxuICAgICAgZXh0cmFzLFxuICAgICAgXCJcIixcbiAgICAgIHRoaXMuc2VxXG4gICAgKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgY29uc3QgYnVmSW50ID1cbiAgICAgICAgICAocmVzcG9uc2UudmFsLnJlYWRVSW50MzJCRSgwKSA8PCA4KSArIHJlc3BvbnNlLnZhbC5yZWFkVUludDMyQkUoNCk7XG4gICAgICAgIHJldHVybiB7IHZhbHVlOiBidWZJbnQsIHN1Y2Nlc3M6IHRydWUgfTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJJTkNSRU1FTlRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIERlY3JlbWVudHMgdGhlIGdpdmVuIGBrZXlgIGluIG1lbWNhY2hlLlxuICAgKi9cbiAgYXN5bmMgZGVjcmVtZW50KFxuICAgIGtleTogc3RyaW5nLFxuICAgIGFtb3VudDogbnVtYmVyLFxuICAgIG9wdGlvbnM6IHsgaW5pdGlhbD86IG51bWJlcjsgZXhwaXJlcz86IG51bWJlciB9XG4gICk6IFByb21pc2U8eyB2YWx1ZTogbnVtYmVyIHwgbnVsbDsgc3VjY2VzczogYm9vbGVhbiB8IG51bGwgfT4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IGluaXRpYWwgPSBvcHRpb25zLmluaXRpYWwgfHwgMDtcbiAgICBjb25zdCBleHBpcmVzID0gb3B0aW9ucy5leHBpcmVzIHx8IHRoaXMub3B0aW9ucy5leHBpcmVzO1xuICAgIGNvbnN0IGV4dHJhcyA9IG1ha2VBbW91bnRJbml0aWFsQW5kRXhwaXJhdGlvbihhbW91bnQsIGluaXRpYWwsIGV4cGlyZXMpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgIGNvbnN0YW50cy5PUF9ERUNSRU1FTlQsXG4gICAgICBrZXksXG4gICAgICBleHRyYXMsXG4gICAgICBcIlwiLFxuICAgICAgdGhpcy5zZXFcbiAgICApO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICBjb25zdCBidWZJbnQgPVxuICAgICAgICAgIChyZXNwb25zZS52YWwucmVhZFVJbnQzMkJFKDApIDw8IDgpICsgcmVzcG9uc2UudmFsLnJlYWRVSW50MzJCRSg0KTtcbiAgICAgICAgcmV0dXJuIHsgdmFsdWU6IGJ1ZkludCwgc3VjY2VzczogdHJ1ZSB9O1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIkRFQ1JFTUVOVFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQXBwZW5kIHRoZSBnaXZlbiBfdmFsdWVfIHRvIHRoZSB2YWx1ZSBhc3NvY2lhdGVkIHdpdGggdGhlIGdpdmVuIF9rZXlfIGluXG4gICAqIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHMgaWYgdGhlIGtleSBpcyBhbHJlYWR5IHByZXNlbnQuXG4gICAqL1xuICBhc3luYyBhcHBlbmQoa2V5OiBzdHJpbmcsIHZhbHVlOiBWYWx1ZSk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IG9wY29kZTogY29uc3RhbnRzLk9QID0gY29uc3RhbnRzLk9QX0FQUEVORDtcbiAgICBjb25zdCBzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLnNlcmlhbGl6ZShvcGNvZGUsIHZhbHVlLCBcIlwiKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICBvcGNvZGUsXG4gICAgICBrZXksXG4gICAgICBzZXJpYWxpemVkLmV4dHJhcyxcbiAgICAgIHNlcmlhbGl6ZWQudmFsdWUsXG4gICAgICB0aGlzLnNlcVxuICAgICk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfTk9UX0ZPVU5EOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiQVBQRU5EXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBQcmVwZW5kIHRoZSBnaXZlbiBfdmFsdWVfIHRvIHRoZSB2YWx1ZSBhc3NvY2lhdGVkIHdpdGggdGhlIGdpdmVuIF9rZXlfIGluXG4gICAqIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHMgaWYgdGhlIGtleSBpcyBhbHJlYWR5IHByZXNlbnQuXG4gICAqL1xuICBhc3luYyBwcmVwZW5kKGtleTogc3RyaW5nLCB2YWx1ZTogVmFsdWUpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAvLyBUT0RPOiBzdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBvcGNvZGU6IGNvbnN0YW50cy5PUCA9IGNvbnN0YW50cy5PUF9QUkVQRU5EO1xuICAgIGNvbnN0IHNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuc2VyaWFsaXplKG9wY29kZSwgdmFsdWUsIFwiXCIpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgIG9wY29kZSxcbiAgICAgIGtleSxcbiAgICAgIHNlcmlhbGl6ZWQuZXh0cmFzLFxuICAgICAgc2VyaWFsaXplZC52YWx1ZSxcbiAgICAgIHRoaXMuc2VxXG4gICAgKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJQUkVQRU5EXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBUb3VjaCBzZXRzIGFuIGV4cGlyYXRpb24gdmFsdWUsIGdpdmVuIGJ5IF9leHBpcmVzXywgb24gdGhlIGdpdmVuIF9rZXlfIGluXG4gICAqIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHMgaWYgdGhlIGtleSBpcyBhbHJlYWR5IHByZXNlbnQuXG4gICAqL1xuICBhc3luYyB0b3VjaChrZXk6IHN0cmluZywgZXhwaXJlczogbnVtYmVyKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgLy8gVE9ETzogc3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgZXh0cmFzID0gbWFrZUV4cGlyYXRpb24oZXhwaXJlcyB8fCB0aGlzLm9wdGlvbnMuZXhwaXJlcyk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKDB4MWMsIGtleSwgZXh0cmFzLCBcIlwiLCB0aGlzLnNlcSk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfTk9UX0ZPVU5EOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiVE9VQ0hcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEZMVVNIXG4gICAqXG4gICAqIEZsdXNoZXMgdGhlIGNhY2hlIG9uIGVhY2ggY29ubmVjdGVkIHNlcnZlci4gVGhlIGNhbGxiYWNrIHNpZ25hdHVyZSBpczpcbiAgICpcbiAgICogICAgIGNhbGxiYWNrKGxhc3RFcnIsIHJlc3VsdHMpXG4gICAqXG4gICAqIHdoZXJlIF9sYXN0RXJyXyBpcyB0aGUgbGFzdCBlcnJvciBlbmNvdW50ZXJlZCAob3IgbnVsbCwgaW4gdGhlIGNvbW1vbiBjYXNlXG4gICAqIG9mIG5vIGVycm9ycykuIF9yZXN1bHRzXyBpcyBhIGRpY3Rpb25hcnkgbWFwcGluZyBgXCJob3N0bmFtZTpwb3J0XCJgIHRvIGVpdGhlclxuICAgKiBgdHJ1ZWAgKGlmIHRoZSBvcGVyYXRpb24gd2FzIHN1Y2Nlc3NmdWwpLCBvciBhbiBlcnJvci5cbiAgICogQHBhcmFtIGNhbGxiYWNrXG4gICAqL1xuICBmbHVzaCgpOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIGJvb2xlYW4gfCBFcnJvcj4+O1xuICBmbHVzaChcbiAgICBjYWxsYmFjazogKFxuICAgICAgZXJyOiBFcnJvciB8IG51bGwsXG4gICAgICByZXN1bHRzOiBSZWNvcmQ8c3RyaW5nLCBib29sZWFuIHwgRXJyb3I+XG4gICAgKSA9PiB2b2lkXG4gICk6IHZvaWQ7XG4gIGZsdXNoKFxuICAgIGNhbGxiYWNrPzogKFxuICAgICAgZXJyOiBFcnJvciB8IG51bGwsXG4gICAgICByZXN1bHRzOiBSZWNvcmQ8c3RyaW5nLCBib29sZWFuIHwgRXJyb3I+XG4gICAgKSA9PiB2b2lkXG4gICkge1xuICAgIGlmIChjYWxsYmFjayA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm4gcHJvbWlzaWZ5KChjYWxsYmFjaykgPT4ge1xuICAgICAgICB0aGlzLmZsdXNoKGZ1bmN0aW9uIChlcnIsIHJlc3VsdHMpIHtcbiAgICAgICAgICBjYWxsYmFjayhlcnIsIHJlc3VsdHMpO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH1cbiAgICAvLyBUT0RPOiBzdXBwb3J0IGV4cGlyYXRpb25cbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoMHgwOCwgXCJcIiwgXCJcIiwgXCJcIiwgdGhpcy5zZXEpO1xuICAgIGxldCBjb3VudCA9IHRoaXMuc2VydmVycy5sZW5ndGg7XG4gICAgY29uc3QgcmVzdWx0OiBSZWNvcmQ8c3RyaW5nLCBib29sZWFuIHwgRXJyb3I+ID0ge307XG4gICAgbGV0IGxhc3RFcnI6IEVycm9yIHwgbnVsbCA9IG51bGw7XG5cbiAgICBjb25zdCBoYW5kbGVGbHVzaCA9IGZ1bmN0aW9uIChzZXE6IG51bWJlciwgc2VydjogU2VydmVyKSB7XG4gICAgICBzZXJ2Lm9uUmVzcG9uc2Uoc2VxLCBmdW5jdGlvbiAoLyogcmVzcG9uc2UgKi8pIHtcbiAgICAgICAgY291bnQgLT0gMTtcbiAgICAgICAgcmVzdWx0W3NlcnYuaG9zdHBvcnRTdHJpbmcoKV0gPSB0cnVlO1xuICAgICAgICBpZiAoY2FsbGJhY2sgJiYgY291bnQgPT09IDApIHtcbiAgICAgICAgICBjYWxsYmFjayhsYXN0RXJyLCByZXN1bHQpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHNlcnYub25FcnJvcihzZXEsIGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgICAgY291bnQgLT0gMTtcbiAgICAgICAgbGFzdEVyciA9IGVycjtcbiAgICAgICAgcmVzdWx0W3NlcnYuaG9zdHBvcnRTdHJpbmcoKV0gPSBlcnI7XG4gICAgICAgIGlmIChjYWxsYmFjayAmJiBjb3VudCA9PT0gMCkge1xuICAgICAgICAgIGNhbGxiYWNrKGxhc3RFcnIsIHJlc3VsdCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgc2Vydi53cml0ZShyZXF1ZXN0KTtcbiAgICB9O1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnNlcnZlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGhhbmRsZUZsdXNoKHRoaXMuc2VxLCB0aGlzLnNlcnZlcnNbaV0pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTVEFUU19XSVRIX0tFWVxuICAgKlxuICAgKiBTZW5kcyBhIG1lbWNhY2hlIHN0YXRzIGNvbW1hbmQgd2l0aCBhIGtleSB0byBlYWNoIGNvbm5lY3RlZCBzZXJ2ZXIuIFRoZVxuICAgKiBjYWxsYmFjayBpcyBpbnZva2VkICoqT05DRSBQRVIgU0VSVkVSKiogYW5kIGhhcyB0aGUgc2lnbmF0dXJlOlxuICAgKlxuICAgKiAgICAgY2FsbGJhY2soZXJyLCBzZXJ2ZXIsIHN0YXRzKVxuICAgKlxuICAgKiBfc2VydmVyXyBpcyB0aGUgYFwiaG9zdG5hbWU6cG9ydFwiYCBvZiB0aGUgc2VydmVyLCBhbmQgX3N0YXRzXyBpcyBhIGRpY3Rpb25hcnlcbiAgICogbWFwcGluZyB0aGUgc3RhdCBuYW1lIHRvIHRoZSB2YWx1ZSBvZiB0aGUgc3RhdGlzdGljIGFzIGEgc3RyaW5nLlxuICAgKiBAcGFyYW0ga2V5XG4gICAqIEBwYXJhbSBjYWxsYmFja1xuICAgKi9cbiAgc3RhdHNXaXRoS2V5KFxuICAgIGtleTogc3RyaW5nLFxuICAgIGNhbGxiYWNrPzogKFxuICAgICAgZXJyOiBFcnJvciB8IG51bGwsXG4gICAgICBzZXJ2ZXI6IHN0cmluZyxcbiAgICAgIHN0YXRzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+IHwgbnVsbFxuICAgICkgPT4gdm9pZFxuICApOiB2b2lkIHtcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoMHgxMCwga2V5LCBcIlwiLCBcIlwiLCB0aGlzLnNlcSk7XG5cbiAgICBjb25zdCBoYW5kbGVTdGF0cyA9IChzZXE6IG51bWJlciwgc2VydjogU2VydmVyKSA9PiB7XG4gICAgICBjb25zdCByZXN1bHQ6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcbiAgICAgIGNvbnN0IGhhbmRsZTogT25SZXNwb25zZUNhbGxiYWNrID0gKHJlc3BvbnNlKSA9PiB7XG4gICAgICAgIC8vIGVuZCBvZiBzdGF0IHJlc3BvbnNlc1xuICAgICAgICBpZiAocmVzcG9uc2UuaGVhZGVyLnRvdGFsQm9keUxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgICAgY2FsbGJhY2sobnVsbCwgc2Vydi5ob3N0cG9ydFN0cmluZygpLCByZXN1bHQpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgLy8gcHJvY2VzcyBzaW5nbGUgc3RhdCBsaW5lIHJlc3BvbnNlXG4gICAgICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgICAgIHJlc3VsdFtyZXNwb25zZS5rZXkudG9TdHJpbmcoKV0gPSByZXNwb25zZS52YWwudG9TdHJpbmcoKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICBjb25zdCBlcnJvciA9IHRoaXMuaGFuZGxlUmVzcG9uc2VFcnJvcihcbiAgICAgICAgICAgICAgYFNUQVRTICgke2tleX0pYCxcbiAgICAgICAgICAgICAgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyxcbiAgICAgICAgICAgICAgdW5kZWZpbmVkXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgICAgICAgIGNhbGxiYWNrKGVycm9yLCBzZXJ2Lmhvc3Rwb3J0U3RyaW5nKCksIG51bGwpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9O1xuICAgICAgaGFuZGxlLnF1aWV0ID0gdHJ1ZTtcblxuICAgICAgc2Vydi5vblJlc3BvbnNlKHNlcSwgaGFuZGxlKTtcbiAgICAgIHNlcnYub25FcnJvcihzZXEsIGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgICAgY2FsbGJhY2soZXJyLCBzZXJ2Lmhvc3Rwb3J0U3RyaW5nKCksIG51bGwpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHNlcnYud3JpdGUocmVxdWVzdCk7XG4gICAgfTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5zZXJ2ZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBoYW5kbGVTdGF0cyh0aGlzLnNlcSwgdGhpcy5zZXJ2ZXJzW2ldKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU1RBVFNcbiAgICpcbiAgICogRmV0Y2hlcyBtZW1jYWNoZSBzdGF0cyBmcm9tIGVhY2ggY29ubmVjdGVkIHNlcnZlci4gVGhlIGNhbGxiYWNrIGlzIGludm9rZWRcbiAgICogKipPTkNFIFBFUiBTRVJWRVIqKiBhbmQgaGFzIHRoZSBzaWduYXR1cmU6XG4gICAqXG4gICAqICAgICBjYWxsYmFjayhlcnIsIHNlcnZlciwgc3RhdHMpXG4gICAqXG4gICAqIF9zZXJ2ZXJfIGlzIHRoZSBgXCJob3N0bmFtZTpwb3J0XCJgIG9mIHRoZSBzZXJ2ZXIsIGFuZCBfc3RhdHNfIGlzIGFcbiAgICogZGljdGlvbmFyeSBtYXBwaW5nIHRoZSBzdGF0IG5hbWUgdG8gdGhlIHZhbHVlIG9mIHRoZSBzdGF0aXN0aWMgYXMgYSBzdHJpbmcuXG4gICAqIEBwYXJhbSBjYWxsYmFja1xuICAgKi9cbiAgc3RhdHMoXG4gICAgY2FsbGJhY2s/OiAoXG4gICAgICBlcnI6IEVycm9yIHwgbnVsbCxcbiAgICAgIHNlcnZlcjogc3RyaW5nLFxuICAgICAgc3RhdHM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gfCBudWxsXG4gICAgKSA9PiB2b2lkXG4gICk6IHZvaWQge1xuICAgIHRoaXMuc3RhdHNXaXRoS2V5KFwiXCIsIGNhbGxiYWNrKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSRVNFVF9TVEFUU1xuICAgKlxuICAgKiBSZXNldCB0aGUgc3RhdGlzdGljcyBlYWNoIHNlcnZlciBpcyBrZWVwaW5nIGJhY2sgdG8gemVyby4gVGhpcyBkb2Vzbid0IGNsZWFyXG4gICAqIHN0YXRzIHN1Y2ggYXMgaXRlbSBjb3VudCwgYnV0IHRlbXBvcmFyeSBzdGF0cyBzdWNoIGFzIHRvdGFsIG51bWJlciBvZlxuICAgKiBjb25uZWN0aW9ucyBvdmVyIHRpbWUuXG4gICAqXG4gICAqIFRoZSBjYWxsYmFjayBpcyBpbnZva2VkICoqT05DRSBQRVIgU0VSVkVSKiogYW5kIGhhcyB0aGUgc2lnbmF0dXJlOlxuICAgKlxuICAgKiAgICAgY2FsbGJhY2soZXJyLCBzZXJ2ZXIpXG4gICAqXG4gICAqIF9zZXJ2ZXJfIGlzIHRoZSBgXCJob3N0bmFtZTpwb3J0XCJgIG9mIHRoZSBzZXJ2ZXIuXG4gICAqIEBwYXJhbSBjYWxsYmFja1xuICAgKi9cbiAgcmVzZXRTdGF0cyhcbiAgICBjYWxsYmFjaz86IChcbiAgICAgIGVycjogRXJyb3IgfCBudWxsLFxuICAgICAgc2VydmVyOiBzdHJpbmcsXG4gICAgICBzdGF0czogUmVjb3JkPHN0cmluZywgc3RyaW5nPiB8IG51bGxcbiAgICApID0+IHZvaWRcbiAgKTogdm9pZCB7XG4gICAgdGhpcy5zdGF0c1dpdGhLZXkoXCJyZXNldFwiLCBjYWxsYmFjayk7XG4gIH1cblxuICAvKipcbiAgICogUVVJVFxuICAgKlxuICAgKiBDbG9zZXMgdGhlIGNvbm5lY3Rpb24gdG8gZWFjaCBzZXJ2ZXIsIG5vdGlmeWluZyB0aGVtIG9mIHRoaXMgaW50ZW50aW9uLiBOb3RlXG4gICAqIHRoYXQgcXVpdCBjYW4gcmFjZSBhZ2FpbnN0IGFscmVhZHkgb3V0c3RhbmRpbmcgcmVxdWVzdHMgd2hlbiB0aG9zZSByZXF1ZXN0c1xuICAgKiBmYWlsIGFuZCBhcmUgcmV0cmllZCwgbGVhZGluZyB0byB0aGUgcXVpdCBjb21tYW5kIHdpbm5pbmcgYW5kIGNsb3NpbmcgdGhlXG4gICAqIGNvbm5lY3Rpb24gYmVmb3JlIHRoZSByZXRyaWVzIGNvbXBsZXRlLlxuICAgKi9cbiAgcXVpdCgpIHtcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICAvLyBUT0RPOiBOaWNlciBwZXJoYXBzIHRvIGRvIFFVSVRRICgweDE3KSBidXQgbmVlZCBhIG5ldyBjYWxsYmFjayBmb3Igd2hlblxuICAgIC8vIHdyaXRlIGlzIGRvbmUuXG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKDB4MDcsIFwiXCIsIFwiXCIsIFwiXCIsIHRoaXMuc2VxKTsgLy8gUVVJVFxuICAgIGxldCBzZXJ2O1xuXG4gICAgY29uc3QgaGFuZGxlUXVpdCA9IGZ1bmN0aW9uIChzZXE6IG51bWJlciwgc2VydjogU2VydmVyKSB7XG4gICAgICBzZXJ2Lm9uUmVzcG9uc2Uoc2VxLCBmdW5jdGlvbiAoLyogcmVzcG9uc2UgKi8pIHtcbiAgICAgICAgc2Vydi5jbG9zZSgpO1xuICAgICAgfSk7XG4gICAgICBzZXJ2Lm9uRXJyb3Ioc2VxLCBmdW5jdGlvbiAoLyogZXJyICovKSB7XG4gICAgICAgIHNlcnYuY2xvc2UoKTtcbiAgICAgIH0pO1xuICAgICAgc2Vydi53cml0ZShyZXF1ZXN0KTtcbiAgICB9O1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnNlcnZlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHNlcnYgPSB0aGlzLnNlcnZlcnNbaV07XG4gICAgICBoYW5kbGVRdWl0KHRoaXMuc2VxLCBzZXJ2KTtcbiAgICB9XG4gIH1cblxuICBfdmVyc2lvbihzZXJ2ZXI6IFNlcnZlcik6IFByb21pc2U8eyB2YWx1ZTogVmFsdWUgfCBudWxsIH0+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICAgIGNvbnN0YW50cy5PUF9WRVJTSU9OLFxuICAgICAgICBcIlwiLFxuICAgICAgICBcIlwiLFxuICAgICAgICBcIlwiLFxuICAgICAgICB0aGlzLnNlcVxuICAgICAgKTtcbiAgICAgIHRoaXMucGVyZm9ybU9uU2VydmVyKHNlcnZlciwgcmVxdWVzdCwgdGhpcy5zZXEsIChlcnIsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICByZXR1cm4gcmVqZWN0KGVycik7XG4gICAgICAgIH1cblxuICAgICAgICBzd2l0Y2ggKHJlc3BvbnNlIS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICAgICAgLyogVE9ETzogdGhpcyBpcyBidWdnZWQsIHdlIHNob3VsZCd0IHVzZSB0aGUgZGVzZXJpYWxpemVyIGhlcmUsIHNpbmNlIHZlcnNpb24gYWx3YXlzIHJldHVybnMgYSB2ZXJzaW9uIHN0cmluZy5cbiAgICAgICAgICAgICBUaGUgZGVzZXJpYWxpemVyIHNob3VsZCBvbmx5IGJlIHVzZWQgb24gdXNlciBrZXkgZGF0YS4gKi9cbiAgICAgICAgICAgIGNvbnN0IGRlc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5kZXNlcmlhbGl6ZShcbiAgICAgICAgICAgICAgcmVzcG9uc2UhLmhlYWRlci5vcGNvZGUsXG4gICAgICAgICAgICAgIHJlc3BvbnNlIS52YWwsXG4gICAgICAgICAgICAgIHJlc3BvbnNlIS5leHRyYXNcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICByZXR1cm4gcmVzb2x2ZSh7IHZhbHVlOiBkZXNlcmlhbGl6ZWQudmFsdWUgfSk7XG4gICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHJldHVybiByZWplY3QoXG4gICAgICAgICAgICAgIHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJWRVJTSU9OXCIsIHJlc3BvbnNlIS5oZWFkZXIuc3RhdHVzKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmVxdWVzdCB0aGUgc2VydmVyIHZlcnNpb24gZnJvbSB0aGUgXCJmaXJzdFwiIHNlcnZlciBpbiB0aGUgYmFja2VuZCBwb29sLlxuICAgKiBUaGUgc2VydmVyIHJlc3BvbmRzIHdpdGggYSBwYWNrZXQgY29udGFpbmluZyB0aGUgdmVyc2lvbiBzdHJpbmcgaW4gdGhlIGJvZHkgd2l0aCB0aGUgZm9sbG93aW5nIGZvcm1hdDogXCJ4LnkuelwiXG4gICAqL1xuICB2ZXJzaW9uKCk6IFByb21pc2U8eyB2YWx1ZTogVmFsdWUgfCBudWxsIH0+IHtcbiAgICBjb25zdCBzZXJ2ZXIgPSB0aGlzLnNlcnZlcktleVRvU2VydmVyKHRoaXMuc2VydmVyS2V5c1swXSk7XG4gICAgcmV0dXJuIHRoaXMuX3ZlcnNpb24oc2VydmVyKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXRyaWV2ZXMgdGhlIHNlcnZlciB2ZXJzaW9uIGZyb20gYWxsIHRoZSBzZXJ2ZXJzXG4gICAqIGluIHRoZSBiYWNrZW5kIHBvb2wsIGVycm9ycyBpZiBhbnkgb25lIG9mIHRoZW0gaGFzIGFuXG4gICAqIGVycm9yXG4gICAqIFxuICAgKiBDYWxsYmFja3MgZnVuY3Rpb25zIGFyZSBjYWxsZWQgYmVmb3JlL2FmdGVyIHdlIHBpbmcgbWVtY2FjaGVkXG4gICAqIGFuZCB1c2VkIHRvIGxvZyB3aGljaCBob3N0cyBhcmUgdGltaW5nIG91dC5cbiAgICovXG4gIGFzeW5jIHZlcnNpb25BbGwoY2FsbGJhY2tzPzoge1xuICAgIGJlZm9yZVBpbmc/OiAoc2VydmVyS2V5OiBzdHJpbmcpID0+IHZvaWQ7XG4gICAgYWZ0ZXJQaW5nPzogKHNlcnZlcktleTogc3RyaW5nKSA9PiB2b2lkO1xuICB9KTogUHJvbWlzZTx7XG4gICAgdmFsdWVzOiBSZWNvcmQ8c3RyaW5nLCBWYWx1ZSB8IG51bGw+O1xuICB9PiB7XG4gICAgY29uc3QgdmVyc2lvbk9iamVjdHMgPSBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIHRoaXMuc2VydmVyS2V5cy5tYXAoKHNlcnZlcktleSkgPT4ge1xuICAgICAgICBjb25zdCBzZXJ2ZXIgPSB0aGlzLnNlcnZlcktleVRvU2VydmVyKHNlcnZlcktleSk7XG4gICAgICAgIGNhbGxiYWNrcz8uYmVmb3JlUGluZz8uKHNlcnZlcktleSk7XG4gICAgICAgIHJldHVybiB0aGlzLl92ZXJzaW9uKHNlcnZlcikudGhlbigocmVzcG9uc2UpID0+IHtcbiAgICAgICAgICBjYWxsYmFja3M/LmFmdGVyUGluZz8uKHNlcnZlcktleSk7XG4gICAgICAgICAgcmV0dXJuIHsgc2VydmVyS2V5OiBzZXJ2ZXJLZXksIHZhbHVlOiByZXNwb25zZS52YWx1ZSB9O1xuICAgICAgICB9KTtcbiAgICAgIH0pXG4gICAgKTtcbiAgICBjb25zdCB2YWx1ZXMgPSB2ZXJzaW9uT2JqZWN0cy5yZWR1Y2UoKGFjY3VtdWxhdG9yLCB2ZXJzaW9uT2JqZWN0KSA9PiB7XG4gICAgICBhY2N1bXVsYXRvclt2ZXJzaW9uT2JqZWN0LnNlcnZlcktleV0gPSB2ZXJzaW9uT2JqZWN0LnZhbHVlO1xuICAgICAgcmV0dXJuIGFjY3VtdWxhdG9yO1xuICAgIH0sIHt9IGFzIFJlY29yZDxzdHJpbmcsIFZhbHVlIHwgbnVsbD4pO1xuICAgIHJldHVybiB7IHZhbHVlczogdmFsdWVzIH07XG4gIH1cblxuICAvKipcbiAgICogQ2xvc2VzIChhYnJ1cHRseSkgY29ubmVjdGlvbnMgdG8gYWxsIHRoZSBzZXJ2ZXJzLlxuICAgKiBAc2VlIHRoaXMucXVpdFxuICAgKi9cbiAgY2xvc2UoKSB7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnNlcnZlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHRoaXMuc2VydmVyc1tpXS5jbG9zZSgpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBQZXJmb3JtIGEgZ2VuZXJpYyBzaW5nbGUgcmVzcG9uc2Ugb3BlcmF0aW9uIChnZXQsIHNldCBldGMpIG9uIG9uZSBzZXJ2ZXJcbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IGtleSB0aGUga2V5IHRvIGhhc2ggdG8gZ2V0IGEgc2VydmVyIGZyb20gdGhlIHBvb2xcbiAgICogQHBhcmFtIHtidWZmZXJ9IHJlcXVlc3QgYSBidWZmZXIgY29udGFpbmluZyB0aGUgcmVxdWVzdFxuICAgKiBAcGFyYW0ge251bWJlcn0gc2VxIHRoZSBzZXF1ZW5jZSBudW1iZXIgb2YgdGhlIG9wZXJhdGlvbi4gSXQgaXMgdXNlZCB0byBwaW4gdGhlIGNhbGxiYWNrc1xuICAgICAgICAgICAgICAgICAgICAgICAgIHRvIGEgc3BlY2lmaWMgb3BlcmF0aW9uIGFuZCBzaG91bGQgbmV2ZXIgY2hhbmdlIGR1cmluZyBhIGBwZXJmb3JtYC5cbiAgICogQHBhcmFtIHtudW1iZXI/fSByZXRyaWVzIG51bWJlciBvZiB0aW1lcyB0byByZXRyeSByZXF1ZXN0IG9uIGZhaWx1cmVcbiAgICovXG4gIHBlcmZvcm0oXG4gICAga2V5OiBzdHJpbmcsXG4gICAgcmVxdWVzdDogQnVmZmVyLFxuICAgIHNlcTogbnVtYmVyLFxuICAgIHJldHJpZXM/OiBudW1iZXJcbiAgKTogUHJvbWlzZTxNZXNzYWdlPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGNvbnN0IHNlcnZlcktleSA9IHRoaXMubG9va3VwS2V5VG9TZXJ2ZXJLZXkoa2V5KTtcbiAgICAgIGNvbnN0IHNlcnZlciA9IHRoaXMuc2VydmVyS2V5VG9TZXJ2ZXIoc2VydmVyS2V5KTtcblxuICAgICAgaWYgKCFzZXJ2ZXIpIHtcbiAgICAgICAgcmV0dXJuIHJlamVjdChuZXcgRXJyb3IoXCJObyBzZXJ2ZXJzIGF2YWlsYWJsZVwiKSk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMucGVyZm9ybU9uU2VydmVyKFxuICAgICAgICBzZXJ2ZXIsXG4gICAgICAgIHJlcXVlc3QsXG4gICAgICAgIHNlcSxcbiAgICAgICAgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgcmV0dXJuIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJlc29sdmUocmVzcG9uc2UhKTtcbiAgICAgICAgfSxcbiAgICAgICAgcmV0cmllc1xuICAgICAgKTtcbiAgICB9KTtcbiAgfVxuXG4gIHBlcmZvcm1PblNlcnZlcihcbiAgICBzZXJ2ZXI6IFNlcnZlcixcbiAgICByZXF1ZXN0OiBCdWZmZXIsXG4gICAgc2VxOiBudW1iZXIsXG4gICAgY2FsbGJhY2s6IFJlc3BvbnNlT3JFcnJvckNhbGxiYWNrLFxuICAgIHJldHJpZXM6IG51bWJlciA9IDBcbiAgKSB7XG4gICAgY29uc3QgX3RoaXMgPSB0aGlzO1xuXG4gICAgcmV0cmllcyA9IHJldHJpZXMgfHwgdGhpcy5vcHRpb25zLnJldHJpZXM7XG4gICAgY29uc3Qgb3JpZ1JldHJpZXMgPSB0aGlzLm9wdGlvbnMucmV0cmllcztcbiAgICBjb25zdCBsb2dnZXIgPSB0aGlzLm9wdGlvbnMubG9nZ2VyO1xuICAgIGNvbnN0IHJldHJ5X2RlbGF5ID0gdGhpcy5vcHRpb25zLnJldHJ5X2RlbGF5O1xuXG4gICAgY29uc3QgcmVzcG9uc2VIYW5kbGVyOiBPblJlc3BvbnNlQ2FsbGJhY2sgPSBmdW5jdGlvbiAocmVzcG9uc2UpIHtcbiAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICBjYWxsYmFjayhudWxsLCByZXNwb25zZSk7XG4gICAgICB9XG4gICAgfTtcblxuICAgIGNvbnN0IGVycm9ySGFuZGxlcjogT25FcnJvckNhbGxiYWNrID0gZnVuY3Rpb24gKGVycm9yKSB7XG4gICAgICBpZiAoLS1yZXRyaWVzID4gMCkge1xuICAgICAgICAvLyBXYWl0IGZvciByZXRyeV9kZWxheVxuICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICBfdGhpcy5wZXJmb3JtT25TZXJ2ZXIoc2VydmVyLCByZXF1ZXN0LCBzZXEsIGNhbGxiYWNrLCByZXRyaWVzKTtcbiAgICAgICAgfSwgMTAwMCAqIHJldHJ5X2RlbGF5KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGxvZ2dlci5sb2coXG4gICAgICAgICAgXCJNZW1KUzogU2VydmVyIDxcIiArXG4gICAgICAgICAgICBzZXJ2ZXIuaG9zdHBvcnRTdHJpbmcoKSArXG4gICAgICAgICAgICBcIj4gZmFpbGVkIGFmdGVyIChcIiArXG4gICAgICAgICAgICBvcmlnUmV0cmllcyArXG4gICAgICAgICAgICBcIikgcmV0cmllcyB3aXRoIGVycm9yIC0gXCIgK1xuICAgICAgICAgICAgZXJyb3IubWVzc2FnZVxuICAgICAgICApO1xuICAgICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgICBjYWxsYmFjayhlcnJvciwgbnVsbCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9O1xuXG4gICAgc2VydmVyLm9uUmVzcG9uc2Uoc2VxLCByZXNwb25zZUhhbmRsZXIpO1xuICAgIHNlcnZlci5vbkVycm9yKHNlcSwgZXJyb3JIYW5kbGVyKTtcbiAgICBzZXJ2ZXIud3JpdGUocmVxdWVzdCk7XG4gIH1cblxuICAvLyBJbmNyZW1lbnQgdGhlIHNlcSB2YWx1ZVxuICBpbmNyU2VxKCkge1xuICAgIHRoaXMuc2VxKys7XG5cbiAgICAvLyBXcmFwIGB0aGlzLnNlcWAgdG8gMzItYml0cyBzaW5jZSB0aGUgZmllbGQgd2UgZml0IGl0IGludG8gaXMgb25seSAzMi1iaXRzLlxuICAgIHRoaXMuc2VxICY9IDB4ZmZmZmZmZmY7XG5cbiAgICByZXR1cm4gdGhpcy5zZXE7XG4gIH1cblxuICBwcml2YXRlIGNyZWF0ZUFuZExvZ0Vycm9yKFxuICAgIGNvbW1hbmROYW1lOiBzdHJpbmcsXG4gICAgcmVzcG9uc2VTdGF0dXM6IFJlc3BvbnNlU3RhdHVzIHwgdW5kZWZpbmVkXG4gICk6IEVycm9yIHtcbiAgICBjb25zdCBlcnJvck1lc3NhZ2UgPSBgTWVtSlMgJHtjb21tYW5kTmFtZX06ICR7Y29uc3RhbnRzLnJlc3BvbnNlU3RhdHVzVG9TdHJpbmcoXG4gICAgICByZXNwb25zZVN0YXR1c1xuICAgICl9YDtcbiAgICB0aGlzLm9wdGlvbnMubG9nZ2VyLmxvZyhlcnJvck1lc3NhZ2UpO1xuICAgIHJldHVybiBuZXcgRXJyb3IoZXJyb3JNZXNzYWdlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBMb2cgYW4gZXJyb3IgdG8gdGhlIGxvZ2dlciwgdGhlbiByZXR1cm4gdGhlIGVycm9yLlxuICAgKiBJZiBhIGNhbGxiYWNrIGlzIGdpdmVuLCBjYWxsIGl0IHdpdGggY2FsbGJhY2soZXJyb3IsIG51bGwpLlxuICAgKi9cbiAgcHJpdmF0ZSBoYW5kbGVSZXNwb25zZUVycm9yKFxuICAgIGNvbW1hbmROYW1lOiBzdHJpbmcsXG4gICAgcmVzcG9uc2VTdGF0dXM6IFJlc3BvbnNlU3RhdHVzIHwgdW5kZWZpbmVkLFxuICAgIGNhbGxiYWNrOiB1bmRlZmluZWQgfCAoKGVycm9yOiBFcnJvciB8IG51bGwsIG90aGVyOiBudWxsKSA9PiB2b2lkKVxuICApOiBFcnJvciB7XG4gICAgY29uc3QgZXJyb3IgPSB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKGNvbW1hbmROYW1lLCByZXNwb25zZVN0YXR1cyk7XG4gICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICBjYWxsYmFjayhlcnJvciwgbnVsbCk7XG4gICAgfVxuICAgIHJldHVybiBlcnJvcjtcbiAgfVxufVxuXG5leHBvcnQgeyBDbGllbnQsIFNlcnZlciwgVXRpbHMsIEhlYWRlciB9O1xuIl19 \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVtanMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbWVtanMvbWVtanMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLHdCQUF3Qjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUV4QixxQ0FLa0I7QUEyaUNELHVGQTdpQ2YsZUFBTSxPQTZpQ2U7QUExaUN2Qix1REFBK0Q7QUFDL0QsbUNBU2lCO0FBQ2pCLHVEQUF5QztBQUN6QywyQ0FBNkM7QUFDN0MsK0NBQWlDO0FBNmhDUixzQkFBSztBQTVoQzlCLGlEQUFtQztBQTRoQ0gsd0JBQU07QUExaEN0QyxTQUFTLDhCQUE4QixDQUNyQyxPQUFpQixFQUNqQixHQUFXO0lBRVgsTUFBTSxLQUFLLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQztJQUM3QixNQUFNLEtBQUssR0FBRyxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxnQkFBUSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3BELE9BQU8sT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ3hCLENBQUM7QUFFRCwrQ0FBK0M7QUFDL0MsU0FBUyxTQUFTLENBQ2hCLE9BQTBFO0lBRTFFLE9BQU8sSUFBSSxPQUFPLENBQUMsVUFBVSxPQUFPLEVBQUUsTUFBTTtRQUMxQyxPQUFPLENBQUMsVUFBVSxHQUFHLEVBQUUsTUFBTTtZQUMzQixHQUFHLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3RDLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBeURELE1BQU0sTUFBTTtJQVFWLDRFQUE0RTtJQUM1RSxtQ0FBbUM7SUFDbkMsWUFBWSxPQUFpQixFQUFFLE9BQTBDO1FBQ3ZFLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO1FBQ3ZCLElB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QUFtQixFQUNuQixjQUEwQztRQUUxQyxNQUFNLFlBQVksR0FBRyxTQUFTLFdBQVcsS0FBSyxTQUFTLENBQUMsc0JBQXNCLENBQzVFLGNBQWMsQ0FDZixFQUFFLENBQUM7UUFDSixJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDdEMsT0FBTyxJQUFJLEtBQUssQ0FBQyxZQUFZLENBQUMsQ0FBQztJQUNqQyxDQUFDO0lBRUQ7OztPQUdHO0lBQ0ssbUJBQW1CLENBQ3pCLFdBQW1CLEVBQ25CLGNBQTBDLEVBQzFDLFFBQWtFO1FBRWxFLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxXQUFXLEVBQUUsY0FBYyxDQUFDLENBQUM7UUFDbEUsSUFBSSxRQUFRLEVBQUU7WUFDWixRQUFRLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxDQUFDO1NBQ3ZCO1FBQ0QsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0NBQ0Y7QUFFUSx3QkFBTSIsInNvdXJjZXNDb250ZW50IjpbIi8vIE1lbVRTIE1lbWNhY2hlIENsaWVudFxuXG5pbXBvcnQge1xuICBPbkVycm9yQ2FsbGJhY2ssXG4gIE9uUmVzcG9uc2VDYWxsYmFjayxcbiAgU2VydmVyLFxuICBTZXJ2ZXJPcHRpb25zLFxufSBmcm9tIFwiLi9zZXJ2ZXJcIjtcbmltcG9ydCB7IG5vb3BTZXJpYWxpemVyLCBTZXJpYWxpemVyIH0gZnJvbSBcIi4vbm9vcC1zZXJpYWxpemVyXCI7XG5pbXBvcnQge1xuICBtYWtlUmVxdWVzdEJ1ZmZlcixcbiAgY29weUludG9SZXF1ZXN0QnVmZmVyLFxuICBtZXJnZSxcbiAgbWFrZUV4cGlyYXRpb24sXG4gIG1ha2VBbW91bnRJbml0aWFsQW5kRXhwaXJhdGlvbixcbiAgaGFzaENvZGUsXG4gIE1heWJlQnVmZmVyLFxuICBNZXNzYWdlLFxufSBmcm9tIFwiLi91dGlsc1wiO1xuaW1wb3J0ICogYXMgY29uc3RhbnRzIGZyb20gXCIuL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgUmVzcG9uc2VTdGF0dXMgfSBmcm9tIFwiLi9jb25zdGFudHNcIjtcbmltcG9ydCAqIGFzIFV0aWxzIGZyb20gXCIuL3V0aWxzXCI7XG5pbXBvcnQgKiBhcyBIZWFkZXIgZnJvbSBcIi4vaGVhZGVyXCI7XG5cbmZ1bmN0aW9uIGRlZmF1bHRLZXlUb1NlcnZlckhhc2hGdW5jdGlvbihcbiAgc2VydmVyczogc3RyaW5nW10sXG4gIGtleTogc3RyaW5nXG4pOiBzdHJpbmcge1xuICBjb25zdCB0b3RhbCA9IHNlcnZlcnMubGVuZ3RoO1xuICBjb25zdCBpbmRleCA9IHRvdGFsID4gMSA/IGhhc2hDb2RlKGtleSkgJSB0b3RhbCA6IDA7XG4gIHJldHVybiBzZXJ2ZXJzW2luZGV4XTtcbn1cblxuLy8gY29udmVydHMgYSBjYWxsIGludG8gYSBwcm9taXNlLXJldHVybmluZyBvbmVcbmZ1bmN0aW9uIHByb21pc2lmeTxSZXN1bHQ+KFxuICBjb21tYW5kOiAoY2FsbGJhY2s6IChlcnJvcjogRXJyb3IgfCBudWxsLCByZXN1bHQ6IFJlc3VsdCkgPT4gdm9pZCkgPT4gdm9pZFxuKTogUHJvbWlzZTxSZXN1bHQ+IHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICBjb21tYW5kKGZ1bmN0aW9uIChlcnIsIHJlc3VsdCkge1xuICAgICAgZXJyID8gcmVqZWN0KGVycikgOiByZXNvbHZlKHJlc3VsdCk7XG4gICAgfSk7XG4gIH0pO1xufVxuXG50eXBlIFJlc3BvbnNlT3JFcnJvckNhbGxiYWNrID0gKFxuICBlcnJvcjogRXJyb3IgfCBudWxsLFxuICByZXNwb25zZTogTWVzc2FnZSB8IG51bGxcbikgPT4gdm9pZDtcblxuaW50ZXJmYWNlIEJhc2VDbGllbnRPcHRpb25zIHtcbiAgcmV0cmllczogbnVtYmVyO1xuICByZXRyeV9kZWxheTogbnVtYmVyO1xuICBleHBpcmVzOiBudW1iZXI7XG4gIGxvZ2dlcjogeyBsb2c6IHR5cGVvZiBjb25zb2xlLmxvZyB9O1xuICBrZXlUb1NlcnZlckhhc2hGdW5jdGlvbjogdHlwZW9mIGRlZmF1bHRLZXlUb1NlcnZlckhhc2hGdW5jdGlvbjtcbn1cblxuaW50ZXJmYWNlIFNlcmlhbGl6ZXJQcm9wPFZhbHVlLCBFeHRyYXM+IHtcbiAgc2VyaWFsaXplcjogU2VyaWFsaXplcjxWYWx1ZSwgRXh0cmFzPjtcbn1cblxuLyoqXG4gKiBUaGUgY2xpZW50IGhhcyBwYXJ0aWFsIHN1cHBvcnQgZm9yIHNlcmlhbGl6aW5nIGFuZCBkZXNlcmlhbGl6aW5nIHZhbHVlcyBmcm9tIHRoZVxuICogQnVmZmVyIGJ5dGUgc3RyaW5ncyB3ZSByZWNlaXZlIGZyb20gdGhlIHdpcmUuIFRoZSBkZWZhdWx0IHNlcmlhbGl6ZXIgaXMgZm9yIE1heWJlQnVmZmVyLlxuICpcbiAqIElmIFZhbHVlIGFuZCBFeHRyYXMgYXJlIG9mIHR5cGUgQnVmZmVyLCB0aGVuIHJldHVybiB0eXBlIFdoZW5CdWZmZXIuIE90aGVyd2lzZSxcbiAqIHJldHVybiB0eXBlIE5vdEJ1ZmZlci5cbiAqL1xudHlwZSBJZkJ1ZmZlcjxWYWx1ZSwgRXh0cmFzLCBXaGVuVmFsdWVBbmRFeHRyYXNBcmVCdWZmZXJzLCBOb3RCdWZmZXI+ID1cbiAgVmFsdWUgZXh0ZW5kcyBCdWZmZXJcbiAgICA/IEV4dHJhcyBleHRlbmRzIEJ1ZmZlclxuICAgICAgPyBXaGVuVmFsdWVBbmRFeHRyYXNBcmVCdWZmZXJzXG4gICAgICA6IE5vdEJ1ZmZlclxuICAgIDogTm90QnVmZmVyO1xuXG5leHBvcnQgdHlwZSBHaXZlbkNsaWVudE9wdGlvbnM8VmFsdWUsIEV4dHJhcz4gPSBQYXJ0aWFsPEJhc2VDbGllbnRPcHRpb25zPiAmXG4gIElmQnVmZmVyPFxuICAgIFZhbHVlLFxuICAgIEV4dHJhcyxcbiAgICBQYXJ0aWFsPFNlcmlhbGl6ZXJQcm9wPFZhbHVlLCBFeHRyYXM+PixcbiAgICBTZXJpYWxpemVyUHJvcDxWYWx1ZSwgRXh0cmFzPlxuICA+O1xuXG5leHBvcnQgdHlwZSBDQVNUb2tlbiA9IEJ1ZmZlcjtcblxuZXhwb3J0IGludGVyZmFjZSBHZXRSZXN1bHQ8VmFsdWUgPSBNYXliZUJ1ZmZlciwgRXh0cmFzID0gTWF5YmVCdWZmZXI+IHtcbiAgdmFsdWU6IFZhbHVlO1xuICBleHRyYXM6IEV4dHJhcztcbiAgY2FzOiBDQVNUb2tlbiB8IHVuZGVmaW5lZDtcbn1cblxuZXhwb3J0IHR5cGUgR2V0TXVsdGlSZXN1bHQ8XG4gIEtleXMgZXh0ZW5kcyBzdHJpbmcgPSBzdHJpbmcsXG4gIFZhbHVlID0gTWF5YmVCdWZmZXIsXG4gIEV4dHJhcyA9IE1heWJlQnVmZmVyXG4+ID0ge1xuICBbSyBpbiBLZXlzXT86IEdldFJlc3VsdDxWYWx1ZSwgRXh0cmFzPjtcbn07XG5cbmNsYXNzIENsaWVudDxWYWx1ZSA9IE1heWJlQnVmZmVyLCBFeHRyYXMgPSBNYXliZUJ1ZmZlcj4ge1xuICBzZXJ2ZXJzOiBTZXJ2ZXJbXTtcbiAgc2VxOiBudW1iZXI7XG4gIG9wdGlvbnM6IEJhc2VDbGllbnRPcHRpb25zICYgUGFydGlhbDxTZXJpYWxpemVyUHJvcDxWYWx1ZSwgRXh0cmFzPj47XG4gIHNlcmlhbGl6ZXI6IFNlcmlhbGl6ZXI8VmFsdWUsIEV4dHJhcz47XG4gIHNlcnZlck1hcDogeyBbaG9zdHBvcnQ6IHN0cmluZ106IFNlcnZlciB9O1xuICBzZXJ2ZXJLZXlzOiBzdHJpbmdbXTtcblxuICAvLyBDbGllbnQgaW5pdGlhbGl6ZXIgdGFrZXMgYSBsaXN0IG9mIGBTZXJ2ZXJgcyBhbmQgYW4gYG9wdGlvbnNgIGRpY3Rpb25hcnkuXG4gIC8vIFNlZSBgQ2xpZW50LmNyZWF0ZWAgZm9yIGRldGFpbHMuXG4gIGNvbnN0cnVjdG9yKHNlcnZlcnM6IFNlcnZlcltdLCBvcHRpb25zOiBHaXZlbkNsaWVudE9wdGlvbnM8VmFsdWUsIEV4dHJhcz4pIHtcbiAgICB0aGlzLnNlcnZlcnMgPSBzZXJ2ZXJzO1xuICAgIHRoaXMuc2VxID0gMDtcbiAgICB0aGlzLm9wdGlvbnMgPSBtZXJnZShvcHRpb25zIHx8IHt9LCB7XG4gICAgICByZXRyaWVzOiAyLFxuICAgICAgcmV0cnlfZGVsYXk6IDAuMixcbiAgICAgIGV4cGlyZXM6IDAsXG4gICAgICBsb2dnZXI6IGNvbnNvbGUsXG4gICAgICBrZXlUb1NlcnZlckhhc2hGdW5jdGlvbjogZGVmYXVsdEtleVRvU2VydmVySGFzaEZ1bmN0aW9uLFxuICAgIH0pO1xuXG4gICAgdGhpcy5zZXJpYWxpemVyID0gdGhpcy5vcHRpb25zLnNlcmlhbGl6ZXIgfHwgKG5vb3BTZXJpYWxpemVyIGFzIGFueSk7XG5cbiAgICAvLyBTdG9yZSBhIG1hcHBpbmcgZnJvbSBob3N0cG9ydCAtPiBzZXJ2ZXIgc28gd2UgY2FuIHF1aWNrbHkgZ2V0IGEgc2VydmVyIG9iamVjdCBmcm9tIHRoZSBzZXJ2ZXJLZXkgcmV0dXJuZWQgYnkgdGhlIGhhc2hpbmcgZnVuY3Rpb25cbiAgICBjb25zdCBzZXJ2ZXJNYXA6IHsgW2hvc3Rwb3J0OiBzdHJpbmddOiBTZXJ2ZXIgfSA9IHt9O1xuICAgIHRoaXMuc2VydmVycy5mb3JFYWNoKGZ1bmN0aW9uIChzZXJ2ZXIpIHtcbiAgICAgIHNlcnZlck1hcFtzZXJ2ZXIuaG9zdHBvcnRTdHJpbmcoKV0gPSBzZXJ2ZXI7XG4gICAgfSk7XG4gICAgdGhpcy5zZXJ2ZXJNYXAgPSBzZXJ2ZXJNYXA7XG5cbiAgICAvLyBzdG9yZSBhIGxpc3Qgb2YgYWxsIG91ciBzZXJ2ZXJLZXlzIHNvIHdlIGRvbid0IG5lZWQgdG8gY29uc3RhbnRseSByZWFsbG9jYXRlIHRoaXMgYXJyYXlcbiAgICB0aGlzLnNlcnZlcktleXMgPSBPYmplY3Qua2V5cyh0aGlzLnNlcnZlck1hcCk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIG5ldyBjbGllbnQgZ2l2ZW4gYW4gb3B0aW9uYWwgY29uZmlnIHN0cmluZyBhbmQgb3B0aW9uYWwgaGFzaCBvZlxuICAgKiBvcHRpb25zLiBUaGUgY29uZmlnIHN0cmluZyBzaG91bGQgYmUgb2YgdGhlIGZvcm06XG4gICAqXG4gICAqICAgICBcIlt1c2VyOnBhc3NAXXNlcnZlcjFbOjExMjExXSxbdXNlcjpwYXNzQF1zZXJ2ZXIyWzoxMTIxMV0sLi4uXCJcbiAgICpcbiAgICogSWYgdGhlIGFyZ3VtZW50IGlzIG5vdCBnaXZlbiwgZmFsbGJhY2sgb24gdGhlIGBNRU1DQUNISUVSX1NFUlZFUlNgIGVudmlyb25tZW50XG4gICAqIHZhcmlhYmxlLCBgTUVNQ0FDSEVfU0VSVkVSU2AgZW52aXJvbm1lbnQgdmFyaWFibGUgb3IgYFwibG9jYWxob3N0OjExMjExXCJgLlxuICAgKlxuICAgKiBUaGUgb3B0aW9ucyBoYXNoIG1heSBjb250YWluIHRoZSBvcHRpb25zOlxuICAgKlxuICAgKiAqIGByZXRyaWVzYCAtIHRoZSBudW1iZXIgb2YgdGltZXMgdG8gcmV0cnkgYW4gb3BlcmF0aW9uIGluIGxpZXUgb2YgZmFpbHVyZXNcbiAgICogKGRlZmF1bHQgMilcbiAgICogKiBgZXhwaXJlc2AgLSB0aGUgZGVmYXVsdCBleHBpcmF0aW9uIGluIHNlY29uZHMgdG8gdXNlIChkZWZhdWx0IDAgLSBuZXZlclxuICAgKiBleHBpcmUpLiBJZiBgZXhwaXJlc2AgaXMgZ3JlYXRlciB0aGFuIDMwIGRheXMgKDYwIHggNjAgeCAyNCB4IDMwKSwgaXQgaXNcbiAgICogdHJlYXRlZCBhcyBhIFVOSVggdGltZSAobnVtYmVyIG9mIHNlY29uZHMgc2luY2UgSmFudWFyeSAxLCAxOTcwKS5cbiAgICogKiBgbG9nZ2VyYCAtIGEgbG9nZ2VyIG9iamVjdCB0aGF0IHJlc3BvbmRzIHRvIGBsb2coc3RyaW5nKWAgbWV0aG9kIGNhbGxzLlxuICAgKlxuICAgKiAgIH5+fn5cbiAgICogICAgIGxvZyhtc2cxWywgbXNnMlssIG1zZzNbLi4uXV1dKVxuICAgKiAgIH5+fn5cbiAgICpcbiAgICogICBEZWZhdWx0cyB0byBgY29uc29sZWAuXG4gICAqICogYHNlcmlhbGl6ZXJgIC0gdGhlIG9iamVjdCB3aGljaCB3aWxsIChkZSlzZXJpYWxpemUgdGhlIGRhdGEuIEl0IG5lZWRzXG4gICAqICAgdHdvIHB1YmxpYyBtZXRob2RzOiBzZXJpYWxpemUgYW5kIGRlc2VyaWFsaXplLiBJdCBkZWZhdWx0cyB0byB0aGVcbiAgICogICBub29wU2VyaWFsaXplcjpcbiAgICpcbiAgICogICB+fn5+XG4gICAqICAgY29uc3Qgbm9vcFNlcmlhbGl6ZXIgPSB7XG4gICAqICAgICBzZXJpYWxpemU6IGZ1bmN0aW9uIChvcGNvZGUsIHZhbHVlLCBleHRyYXMpIHtcbiAgICogICAgICAgcmV0dXJuIHsgdmFsdWU6IHZhbHVlLCBleHRyYXM6IGV4dHJhcyB9O1xuICAgKiAgICAgfSxcbiAgICogICAgIGRlc2VyaWFsaXplOiBmdW5jdGlvbiAob3Bjb2RlLCB2YWx1ZSwgZXh0cmFzKSB7XG4gICAqICAgICAgIHJldHVybiB7IHZhbHVlOiB2YWx1ZSwgZXh0cmFzOiBleHRyYXMgfTtcbiAgICogICAgIH1cbiAgICogICB9O1xuICAgKiAgIH5+fn5cbiAgICpcbiAgICogT3Igb3B0aW9ucyBmb3IgdGhlIHNlcnZlcnMgaW5jbHVkaW5nOlxuICAgKiAqIGB1c2VybmFtZWAgYW5kIGBwYXNzd29yZGAgZm9yIGZhbGxiYWNrIFNBU0wgYXV0aGVudGljYXRpb24gY3JlZGVudGlhbHMuXG4gICAqICogYHRpbWVvdXRgIGluIHNlY29uZHMgdG8gZGV0ZXJtaW5lIGZhaWx1cmUgZm9yIG9wZXJhdGlvbnMuIERlZmF1bHQgaXMgMC41XG4gICAqICAgICAgICAgICAgIHNlY29uZHMuXG4gICAqICogJ2Nvbm50aW1lb3V0JyBpbiBzZWNvbmRzIHRvIGNvbm5lY3Rpb24gZmFpbHVyZS4gRGVmYXVsdCBpcyB0d2ljZSB0aGUgdmFsdWVcbiAgICogICAgICAgICAgICAgICAgIG9mIGB0aW1lb3V0YC5cbiAgICogKiBga2VlcEFsaXZlYCB3aGV0aGVyIHRvIGVuYWJsZSBrZWVwLWFsaXZlIGZ1bmN0aW9uYWxpdHkuIERlZmF1bHRzIHRvIGZhbHNlLlxuICAgKiAqIGBrZWVwQWxpdmVEZWxheWAgaW4gc2Vjb25kcyB0byB0aGUgaW5pdGlhbCBkZWxheSBiZWZvcmUgdGhlIGZpcnN0IGtlZXBhbGl2ZVxuICAgKiAgICAgICAgICAgICAgICAgICAgcHJvYmUgaXMgc2VudCBvbiBhbiBpZGxlIHNvY2tldC4gRGVmYXVsdHMgaXMgMzAgc2Vjb25kcy5cbiAgICogKiBga2V5VG9TZXJ2ZXJIYXNoRnVuY3Rpb25gIGEgZnVuY3Rpb24gdG8gbWFwIGtleXMgdG8gc2VydmVycywgd2l0aCB0aGUgc2lnbmF0dXJlXG4gICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgIChzZXJ2ZXJLZXlzOiBzdHJpbmdbXSwga2V5OiBzdHJpbmcpOiBzdHJpbmdcbiAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgTk9URTogaWYgeW91IG5lZWQgdG8gZG8gc29tZSBleHBlbnNpdmUgaW5pdGlhbGl6YXRpb24sICpwbGVhc2UqIGRvIGl0IGxhemlseSB0aGUgZmlyc3QgdGltZSB5b3UgdGhpcyBmdW5jdGlvbiBpcyBjYWxsZWQgd2l0aCBhbiBhcnJheSBvZiBzZXJ2ZXJLZXlzLCBub3Qgb24gZXZlcnkgY2FsbFxuICAgKi9cbiAgc3RhdGljIGNyZWF0ZTxWYWx1ZSwgRXh0cmFzPihcbiAgICBzZXJ2ZXJzU3RyOiBzdHJpbmcgfCB1bmRlZmluZWQsXG4gICAgb3B0aW9uczogSWZCdWZmZXI8XG4gICAgICBWYWx1ZSxcbiAgICAgIEV4dHJhcyxcbiAgICAgIHVuZGVmaW5lZCB8IChQYXJ0aWFsPFNlcnZlck9wdGlvbnM+ICYgR2l2ZW5DbGllbnRPcHRpb25zPFZhbHVlLCBFeHRyYXM+KSxcbiAgICAgIFBhcnRpYWw8U2VydmVyT3B0aW9ucz4gJiBHaXZlbkNsaWVudE9wdGlvbnM8VmFsdWUsIEV4dHJhcz5cbiAgICA+XG4gICk6IENsaWVudDxWYWx1ZSwgRXh0cmFzPiB7XG4gICAgc2VydmVyc1N0ciA9XG4gICAgICBzZXJ2ZXJzU3RyIHx8XG4gICAgICBwcm9jZXNzLmVudi5NRU1DQUNISUVSX1NFUlZFUlMgfHxcbiAgICAgIHByb2Nlc3MuZW52Lk1FTUNBQ0hFX1NFUlZFUlMgfHxcbiAgICAgIFwibG9jYWxob3N0OjExMjExXCI7XG4gICAgY29uc3Qgc2VydmVyVXJpcyA9IHNlcnZlcnNTdHIuc3BsaXQoXCIsXCIpO1xuICAgIGNvbnN0IHNlcnZlcnMgPSBzZXJ2ZXJVcmlzLm1hcChmdW5jdGlvbiAodXJpKSB7XG4gICAgICBjb25zdCB1cmlQYXJ0cyA9IHVyaS5zcGxpdChcIkBcIik7XG4gICAgICBjb25zdCBob3N0UG9ydCA9IHVyaVBhcnRzW3VyaVBhcnRzLmxlbmd0aCAtIDFdLnNwbGl0KFwiOlwiKTtcbiAgICAgIGNvbnN0IHVzZXJQYXNzID0gKHVyaVBhcnRzW3VyaVBhcnRzLmxlbmd0aCAtIDJdIHx8IFwiXCIpLnNwbGl0KFwiOlwiKTtcbiAgICAgIHJldHVybiBuZXcgU2VydmVyKFxuICAgICAgICBob3N0UG9ydFswXSxcbiAgICAgICAgcGFyc2VJbnQoaG9zdFBvcnRbMV0gfHwgXCIxMTIxMVwiLCAxMCksXG4gICAgICAgIHVzZXJQYXNzWzBdLFxuICAgICAgICB1c2VyUGFzc1sxXSxcbiAgICAgICAgb3B0aW9uc1xuICAgICAgKTtcbiAgICB9KTtcbiAgICByZXR1cm4gbmV3IENsaWVudChzZXJ2ZXJzLCBvcHRpb25zIGFzIGFueSk7XG4gIH1cblxuICAvKipcbiAgICogR2l2ZW4gYSBzZXJ2ZXJLZXkgZnJvbWxvb2t1cEtleVRvU2VydmVyS2V5LCByZXR1cm4gdGhlIGNvcnJlc3BvbmRpbmcgU2VydmVyIGluc3RhbmNlXG4gICAqXG4gICAqIEBwYXJhbSAge3N0cmluZ30gc2VydmVyS2V5XG4gICAqIEByZXR1cm5zIHtTZXJ2ZXJ9XG4gICAqL1xuICBzZXJ2ZXJLZXlUb1NlcnZlcihzZXJ2ZXJLZXk6IHN0cmluZyk6IFNlcnZlciB7XG4gICAgcmV0dXJuIHRoaXMuc2VydmVyTWFwW3NlcnZlcktleV07XG4gIH1cblxuICAvKipcbiAgICogR2l2ZW4gYSBrZXkgdG8gbG9vayB1cCBpbiBtZW1jYWNoZSwgcmV0dXJuIGEgc2VydmVyS2V5IChiYXNlZCBvbiBzb21lXG4gICAqIGhhc2hpbmcgZnVuY3Rpb24pIHdoaWNoIGNhbiBiZSB1c2VkIHRvIGluZGV4IHRoaXMuc2VydmVyTWFwXG4gICAqL1xuICBsb29rdXBLZXlUb1NlcnZlcktleShrZXk6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMub3B0aW9ucy5rZXlUb1NlcnZlckhhc2hGdW5jdGlvbih0aGlzLnNlcnZlcktleXMsIGtleSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldmVzIHRoZSB2YWx1ZSBhdCB0aGUgZ2l2ZW4ga2V5IGluIG1lbWNhY2hlLlxuICAgKi9cbiAgYXN5bmMgZ2V0KGtleTogc3RyaW5nKTogUHJvbWlzZTxHZXRSZXN1bHQ8VmFsdWUsIEV4dHJhcz4gfCBudWxsPiB7XG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKGNvbnN0YW50cy5PUF9HRVQsIGtleSwgXCJcIiwgXCJcIiwgdGhpcy5zZXEpO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICBjb25zdCBkZXNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuZGVzZXJpYWxpemUoXG4gICAgICAgICAgcmVzcG9uc2UuaGVhZGVyLm9wY29kZSxcbiAgICAgICAgICByZXNwb25zZS52YWwsXG4gICAgICAgICAgcmVzcG9uc2UuZXh0cmFzXG4gICAgICAgICk7XG4gICAgICAgIHJldHVybiB7IC4uLmRlc2VyaWFsaXplZCwgY2FzOiByZXNwb25zZS5oZWFkZXIuY2FzIH07XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIkdFVFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKiogQnVpbGQgYSBwaXBlbGluZWQgZ2V0IG11bHRpIHJlcXVlc3QgYnkgc2VuZGluZyBvbmUgR0VUS1EgZm9yIGVhY2gga2V5IChxdWlldCwgbWVhbmluZyBpdCB3b24ndCByZXNwb25kIGlmIHRoZSB2YWx1ZSBpcyBtaXNzaW5nKSBmb2xsb3dlZCBieSBhIG5vLW9wIHRvIGZvcmNlIGEgcmVzcG9uc2UgKGFuZCB0byBnaXZlIHVzIGEgc2VudGluZWwgcmVzcG9uc2UgdGhhdCB0aGUgcGlwZWxpbmUgaXMgZG9uZSlcbiAgICpcbiAgICogY2YgaHR0cHM6Ly9naXRodWIuY29tL2NvdWNoYmFzZS9tZW1jYWNoZWQvYmxvYi9tYXN0ZXIvZG9jcy9CaW5hcnlQcm90b2NvbC5tZCMweDBkLWdldGtxLWdldC13aXRoLWtleS1xdWlldGx5XG4gICAqL1xuICBfYnVpbGRHZXRNdWx0aVJlcXVlc3Qoa2V5czogc3RyaW5nW10sIHNlcTogbnVtYmVyKTogQnVmZmVyIHtcbiAgICAvLyBzdGFydCBhdCAyNCBmb3IgdGhlIG5vLW9wIGNvbW1hbmQgYXQgdGhlIGVuZFxuICAgIGxldCByZXF1ZXN0U2l6ZSA9IDI0O1xuICAgIGZvciAoY29uc3Qga2V5SWR4IGluIGtleXMpIHtcbiAgICAgIHJlcXVlc3RTaXplICs9IEJ1ZmZlci5ieXRlTGVuZ3RoKGtleXNba2V5SWR4XSwgXCJ1dGY4XCIpICsgMjQ7XG4gICAgfVxuXG4gICAgY29uc3QgcmVxdWVzdCA9IEJ1ZmZlci5hbGxvYyhyZXF1ZXN0U2l6ZSk7XG5cbiAgICBsZXQgYnl0ZXNXcml0dGVuID0gMDtcbiAgICBmb3IgKGNvbnN0IGtleUlkeCBpbiBrZXlzKSB7XG4gICAgICBjb25zdCBrZXkgPSBrZXlzW2tleUlkeF07XG4gICAgICBieXRlc1dyaXR0ZW4gKz0gY29weUludG9SZXF1ZXN0QnVmZmVyKFxuICAgICAgICBjb25zdGFudHMuT1BfR0VUS1EsXG4gICAgICAgIGtleSxcbiAgICAgICAgXCJcIixcbiAgICAgICAgXCJcIixcbiAgICAgICAgc2VxLFxuICAgICAgICByZXF1ZXN0LFxuICAgICAgICBieXRlc1dyaXR0ZW5cbiAgICAgICk7XG4gICAgfVxuXG4gICAgYnl0ZXNXcml0dGVuICs9IGNvcHlJbnRvUmVxdWVzdEJ1ZmZlcihcbiAgICAgIGNvbnN0YW50cy5PUF9OT19PUCxcbiAgICAgIFwiXCIsXG4gICAgICBcIlwiLFxuICAgICAgXCJcIixcbiAgICAgIHNlcSxcbiAgICAgIHJlcXVlc3QsXG4gICAgICBieXRlc1dyaXR0ZW5cbiAgICApO1xuXG4gICAgcmV0dXJuIHJlcXVlc3Q7XG4gIH1cblxuICAvKiogRXhlY3V0aW5nIGEgcGlwZWxpbmVkIChtdWx0aSkgZ2V0IGFnYWluc3QgYSBzaW5nbGUgc2VydmVyLiBUaGlzIGlzIGEgcHJpdmF0ZSBpbXBsZW1lbnRhdGlvbiBkZXRhaWwgb2YgZ2V0TXVsdGkuICovXG4gIGFzeW5jIF9nZXRNdWx0aVRvU2VydmVyPEtleXMgZXh0ZW5kcyBzdHJpbmc+KFxuICAgIHNlcnY6IFNlcnZlcixcbiAgICBrZXlzOiBLZXlzW11cbiAgKTogUHJvbWlzZTxHZXRNdWx0aVJlc3VsdDxLZXlzLCBWYWx1ZSwgRXh0cmFzPj4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBjb25zdCByZXNwb25zZU1hcDogR2V0TXVsdGlSZXN1bHQ8c3RyaW5nLCBWYWx1ZSwgRXh0cmFzPiA9IHt9O1xuXG4gICAgICBjb25zdCBoYW5kbGU6IE9uUmVzcG9uc2VDYWxsYmFjayA9IChyZXNwb25zZSkgPT4ge1xuICAgICAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgICAgICAvLyBXaGVuIHdlIGdldCB0aGUgbm8tb3AgcmVzcG9uc2UsIHdlIGFyZSBkb25lIHdpdGggdGhpcyBvbmUgZ2V0TXVsdGkgaW4gdGhlIHBlci1iYWNrZW5kIGZhbi1vdXRcbiAgICAgICAgICAgIGlmIChyZXNwb25zZS5oZWFkZXIub3Bjb2RlID09PSBjb25zdGFudHMuT1BfTk9fT1ApIHtcbiAgICAgICAgICAgICAgLy8gVGhpcyBlbnN1cmVzIHRoZSBoYW5kbGVyIHdpbGwgYmUgZGVsZXRlZCBmcm9tIHRoZSByZXNwb25zZUNhbGxiYWNrcyBtYXAgaW4gc2VydmVyLmpzXG4gICAgICAgICAgICAgIC8vIFRoaXMgaXNuJ3QgdGVjaG5pY2FsbHkgbmVlZGVkIGhlcmUgYmVjYXVzZSB0aGUgbG9naWMgaW4gc2VydmVyLmpzIGFsc28gY2hlY2tzIGlmIHRvdGFsQm9keUxlbmd0aCA9PT0gMCwgYnV0IG91ciB1bml0dGVzdHMgYXJlbid0IGdyZWF0IGFib3V0IHNldHRpbmcgdGhhdCBmaWVsZCwgYW5kIGFsc28gdGhpcyBtYWtlcyBpdCBtb3JlIGV4cGxpY2l0XG4gICAgICAgICAgICAgIGhhbmRsZS5xdWlldCA9IGZhbHNlO1xuICAgICAgICAgICAgICByZXNvbHZlKHJlc3BvbnNlTWFwKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgICAgICAgIHJlc3BvbnNlLmhlYWRlci5vcGNvZGUgPT09IGNvbnN0YW50cy5PUF9HRVRLIHx8XG4gICAgICAgICAgICAgIHJlc3BvbnNlLmhlYWRlci5vcGNvZGUgPT09IGNvbnN0YW50cy5PUF9HRVRLUVxuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgIGNvbnN0IGRlc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5kZXNlcmlhbGl6ZShcbiAgICAgICAgICAgICAgICByZXNwb25zZS5oZWFkZXIub3Bjb2RlLFxuICAgICAgICAgICAgICAgIHJlc3BvbnNlLnZhbCxcbiAgICAgICAgICAgICAgICByZXNwb25zZS5leHRyYXNcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgY29uc3Qga2V5ID0gcmVzcG9uc2Uua2V5LnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgIGlmIChrZXkubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlamVjdChcbiAgICAgICAgICAgICAgICAgIG5ldyBFcnJvcihcbiAgICAgICAgICAgICAgICAgICAgXCJSZWNpZXZlZCBlbXB0eSBrZXkgaW4gZ2V0TXVsdGk6IFwiICtcbiAgICAgICAgICAgICAgICAgICAgICBKU09OLnN0cmluZ2lmeShyZXNwb25zZSlcbiAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIHJlc3BvbnNlTWFwW2tleV0gPSB7IC4uLmRlc2VyaWFsaXplZCwgY2FzOiByZXNwb25zZS5oZWFkZXIuY2FzIH07XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICByZXR1cm4gcmVqZWN0KFxuICAgICAgICAgICAgICAgIG5ldyBFcnJvcihcbiAgICAgICAgICAgICAgICAgIFwiUmVjaWV2ZWQgcmVzcG9uc2UgaW4gZ2V0TXVsdGkgZm9yIHVua25vd24gb3Bjb2RlOiBcIiArXG4gICAgICAgICAgICAgICAgICAgIEpTT04uc3RyaW5naWZ5KHJlc3BvbnNlKVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICByZXR1cm4gcmVqZWN0KFxuICAgICAgICAgICAgICB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiR0VUXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9O1xuICAgICAgLy8gVGhpcyBwcmV2ZW50cyB0aGUgaGFuZGxlciBmcm9tIGJlaW5nIGRlbGV0ZWRcbiAgICAgIC8vIGFmdGVyIHRoZSBmaXJzdCByZXNwb25zZS4gTG9naWMgaW4gc2VydmVyLmpzLlxuICAgICAgaGFuZGxlLnF1aWV0ID0gdHJ1ZTtcblxuICAgICAgY29uc3Qgc2VxID0gdGhpcy5pbmNyU2VxKCk7XG4gICAgICBjb25zdCByZXF1ZXN0ID0gdGhpcy5fYnVpbGRHZXRNdWx0aVJlcXVlc3Qoa2V5cywgc2VxKTtcbiAgICAgIHNlcnYub25SZXNwb25zZSh0aGlzLnNlcSwgaGFuZGxlKTtcbiAgICAgIHNlcnYub25FcnJvcih0aGlzLnNlcSwgcmVqZWN0KTtcbiAgICAgIHNlcnYud3JpdGUocmVxdWVzdCk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldnMgdGhlIHZhbHVlIGF0IHRoZSBnaXZlbiBrZXlzIGluIG1lbWNhY2hlZC4gUmV0dXJucyBhIG1hcCBmcm9tIHRoZVxuICAgKiByZXF1ZXN0ZWQga2V5cyB0byByZXN1bHRzLCBvciBudWxsIGlmIHRoZSBrZXkgd2FzIG5vdCBmb3VuZC5cbiAgICovXG4gIGFzeW5jIGdldE11bHRpPEtleXMgZXh0ZW5kcyBzdHJpbmc+KFxuICAgIGtleXM6IEtleXNbXVxuICApOiBQcm9taXNlPEdldE11bHRpUmVzdWx0PEtleXMsIFZhbHVlLCBFeHRyYXM+PiB7XG4gICAgY29uc3Qgc2VydmVyS2V5dG9Mb29rdXBLZXlzOiB7XG4gICAgICBbc2VydmVyS2V5OiBzdHJpbmddOiBzdHJpbmdbXTtcbiAgICB9ID0ge307XG4gICAga2V5cy5mb3JFYWNoKChsb29rdXBLZXkpID0+IHtcbiAgICAgIGNvbnN0IHNlcnZlcktleSA9IHRoaXMubG9va3VwS2V5VG9TZXJ2ZXJLZXkobG9va3VwS2V5KTtcbiAgICAgIGlmICghc2VydmVyS2V5dG9Mb29rdXBLZXlzW3NlcnZlcktleV0pIHtcbiAgICAgICAgc2VydmVyS2V5dG9Mb29rdXBLZXlzW3NlcnZlcktleV0gPSBbXTtcbiAgICAgIH1cbiAgICAgIHNlcnZlcktleXRvTG9va3VwS2V5c1tzZXJ2ZXJLZXldLnB1c2gobG9va3VwS2V5KTtcbiAgICB9KTtcblxuICAgIGNvbnN0IHVzZWRTZXJ2ZXJLZXlzID0gT2JqZWN0LmtleXMoc2VydmVyS2V5dG9Mb29rdXBLZXlzKTtcbiAgICBjb25zdCByZXN1bHRzID0gYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICB1c2VkU2VydmVyS2V5cy5tYXAoKHNlcnZlcktleSkgPT4ge1xuICAgICAgICBjb25zdCBzZXJ2ZXIgPSB0aGlzLnNlcnZlcktleVRvU2VydmVyKHNlcnZlcktleSk7XG4gICAgICAgIHJldHVybiB0aGlzLl9nZXRNdWx0aVRvU2VydmVyKHNlcnZlciwgc2VydmVyS2V5dG9Mb29rdXBLZXlzW3NlcnZlcktleV0pO1xuICAgICAgfSlcbiAgICApO1xuXG4gICAgcmV0dXJuIE9iamVjdC5hc3NpZ24oe30sIC4uLnJlc3VsdHMpO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgYGtleWAgdG8gYHZhbHVlYC5cbiAgICovXG4gIGFzeW5jIHNldChcbiAgICBrZXk6IHN0cmluZyxcbiAgICB2YWx1ZTogVmFsdWUsXG4gICAgb3B0aW9ucz86IHsgZXhwaXJlcz86IG51bWJlcjsgY2FzPzogQ0FTVG9rZW4gfVxuICApOiBQcm9taXNlPGJvb2xlYW4gfCBudWxsPiB7XG4gICAgY29uc3QgZXhwaXJlcyA9IG9wdGlvbnM/LmV4cGlyZXM7XG4gICAgY29uc3QgY2FzID0gb3B0aW9ucz8uY2FzO1xuXG4gICAgLy8gVE9ETzogc3VwcG9ydCBmbGFnc1xuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IGV4cGlyYXRpb24gPSBtYWtlRXhwaXJhdGlvbihleHBpcmVzIHx8IHRoaXMub3B0aW9ucy5leHBpcmVzKTtcbiAgICBjb25zdCBleHRyYXMgPSBCdWZmZXIuY29uY2F0KFtCdWZmZXIuZnJvbShcIjAwMDAwMDAwXCIsIFwiaGV4XCIpLCBleHBpcmF0aW9uXSk7XG4gICAgY29uc3Qgc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5zZXJpYWxpemUoXG4gICAgICBjb25zdGFudHMuT1BfU0VULFxuICAgICAgdmFsdWUsXG4gICAgICBleHRyYXNcbiAgICApO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBVdGlscy5lbmNvZGVSZXF1ZXN0KHtcbiAgICAgIGhlYWRlcjoge1xuICAgICAgICBvcGNvZGU6IGNvbnN0YW50cy5PUF9TRVQsXG4gICAgICAgIG9wYXF1ZTogdGhpcy5zZXEsXG4gICAgICAgIGNhcyxcbiAgICAgIH0sXG4gICAgICBrZXksXG4gICAgICB2YWx1ZTogc2VyaWFsaXplZC52YWx1ZSxcbiAgICAgIGV4dHJhczogc2VyaWFsaXplZC5leHRyYXMsXG4gICAgfSk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfRVhJU1RTOlxuICAgICAgICBpZiAoY2FzKSB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJTRVRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgICAgIH1cbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJTRVRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEFERFxuICAgKlxuICAgKiBBZGRzIHRoZSBnaXZlbiBfa2V5XyBhbmQgX3ZhbHVlXyB0byBtZW1jYWNoZS4gVGhlIG9wZXJhdGlvbiBvbmx5IHN1Y2NlZWRzXG4gICAqIGlmIHRoZSBrZXkgaXMgbm90IGFscmVhZHkgc2V0LlxuICAgKlxuICAgKiBUaGUgb3B0aW9ucyBkaWN0aW9uYXJ5IHRha2VzOlxuICAgKiAqIF9leHBpcmVzXzogb3ZlcnJpZGVzIHRoZSBkZWZhdWx0IGV4cGlyYXRpb24gKHNlZSBgQ2xpZW50LmNyZWF0ZWApIGZvciB0aGlzXG4gICAqICAgICAgICAgICAgICBwYXJ0aWN1bGFyIGtleS12YWx1ZSBwYWlyLlxuICAgKi9cbiAgYXN5bmMgYWRkKFxuICAgIGtleTogc3RyaW5nLFxuICAgIHZhbHVlOiBWYWx1ZSxcbiAgICBvcHRpb25zPzogeyBleHBpcmVzPzogbnVtYmVyIH1cbiAgKTogUHJvbWlzZTxib29sZWFuIHwgbnVsbD4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgZmxhZ3MsIHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IGV4cGlyYXRpb24gPSBtYWtlRXhwaXJhdGlvbihvcHRpb25zPy5leHBpcmVzIHx8IHRoaXMub3B0aW9ucy5leHBpcmVzKTtcbiAgICBjb25zdCBleHRyYXMgPSBCdWZmZXIuY29uY2F0KFtCdWZmZXIuZnJvbShcIjAwMDAwMDAwXCIsIFwiaGV4XCIpLCBleHBpcmF0aW9uXSk7XG5cbiAgICBjb25zdCBvcGNvZGUgPSBjb25zdGFudHMuT1BfQUREO1xuICAgIGNvbnN0IHNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuc2VyaWFsaXplKG9wY29kZSwgdmFsdWUsIGV4dHJhcyk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKFxuICAgICAgb3Bjb2RlLFxuICAgICAga2V5LFxuICAgICAgc2VyaWFsaXplZC5leHRyYXMsXG4gICAgICBzZXJpYWxpemVkLnZhbHVlLFxuICAgICAgdGhpcy5zZXFcbiAgICApO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuS0VZX0VYSVNUUzpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJBRERcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlcGxhY2VzIHRoZSBnaXZlbiBfa2V5XyBhbmQgX3ZhbHVlXyB0byBtZW1jYWNoZS4gVGhlIG9wZXJhdGlvbiBvbmx5IHN1Y2NlZWRzXG4gICAqIGlmIHRoZSBrZXkgaXMgYWxyZWFkeSBwcmVzZW50LlxuICAgKi9cbiAgYXN5bmMgcmVwbGFjZShcbiAgICBrZXk6IHN0cmluZyxcbiAgICB2YWx1ZTogVmFsdWUsXG4gICAgb3B0aW9ucz86IHsgZXhwaXJlcz86IG51bWJlciB9XG4gICk6IFByb21pc2U8Ym9vbGVhbiB8IG51bGw+IHtcbiAgICAvLyBUT0RPOiBzdXBwb3J0IGZsYWdzLCBzdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBleHBpcmF0aW9uID0gbWFrZUV4cGlyYXRpb24ob3B0aW9ucz8uZXhwaXJlcyB8fCB0aGlzLm9wdGlvbnMuZXhwaXJlcyk7XG4gICAgY29uc3QgZXh0cmFzID0gQnVmZmVyLmNvbmNhdChbQnVmZmVyLmZyb20oXCIwMDAwMDAwMFwiLCBcImhleFwiKSwgZXhwaXJhdGlvbl0pO1xuXG4gICAgY29uc3Qgb3Bjb2RlOiBjb25zdGFudHMuT1AgPSBjb25zdGFudHMuT1BfUkVQTEFDRTtcbiAgICBjb25zdCBzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLnNlcmlhbGl6ZShvcGNvZGUsIHZhbHVlLCBleHRyYXMpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgIG9wY29kZSxcbiAgICAgIGtleSxcbiAgICAgIHNlcmlhbGl6ZWQuZXh0cmFzLFxuICAgICAgc2VyaWFsaXplZC52YWx1ZSxcbiAgICAgIHRoaXMuc2VxXG4gICAgKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJSRVBMQUNFXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBEZWxldGVzIHRoZSBnaXZlbiBfa2V5XyBmcm9tIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHNcbiAgICogaWYgdGhlIGtleSBpcyBhbHJlYWR5IHByZXNlbnQuXG4gICAqL1xuICBhc3luYyBkZWxldGUoa2V5OiBzdHJpbmcpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAvLyBUT0RPOiBTdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoNCwga2V5LCBcIlwiLCBcIlwiLCB0aGlzLnNlcSk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG5cbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJERUxFVEVcIiwgcmVzcG9uc2U/LmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBJbmNyZW1lbnRzIHRoZSBnaXZlbiBfa2V5XyBpbiBtZW1jYWNoZS5cbiAgICovXG4gIGFzeW5jIGluY3JlbWVudChcbiAgICBrZXk6IHN0cmluZyxcbiAgICBhbW91bnQ6IG51bWJlcixcbiAgICBvcHRpb25zPzogeyBpbml0aWFsPzogbnVtYmVyOyBleHBpcmVzPzogbnVtYmVyIH1cbiAgKTogUHJvbWlzZTx7IHZhbHVlOiBudW1iZXIgfCBudWxsOyBzdWNjZXNzOiBib29sZWFuIHwgbnVsbCB9PiB7XG4gICAgLy8gVE9ETzogc3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgaW5pdGlhbCA9IG9wdGlvbnM/LmluaXRpYWwgfHwgMDtcbiAgICBjb25zdCBleHBpcmVzID0gb3B0aW9ucz8uZXhwaXJlcyB8fCB0aGlzLm9wdGlvbnMuZXhwaXJlcztcbiAgICBjb25zdCBleHRyYXMgPSBtYWtlQW1vdW50SW5pdGlhbEFuZEV4cGlyYXRpb24oYW1vdW50LCBpbml0aWFsLCBleHBpcmVzKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICBjb25zdGFudHMuT1BfSU5DUkVNRU5ULFxuICAgICAga2V5LFxuICAgICAgZXh0cmFzLFxuICAgICAgXCJcIixcbiAgICAgIHRoaXMuc2VxXG4gICAgKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgY29uc3QgYnVmSW50ID1cbiAgICAgICAgICAocmVzcG9uc2UudmFsLnJlYWRVSW50MzJCRSgwKSA8PCA4KSArIHJlc3BvbnNlLnZhbC5yZWFkVUludDMyQkUoNCk7XG4gICAgICAgIHJldHVybiB7IHZhbHVlOiBidWZJbnQsIHN1Y2Nlc3M6IHRydWUgfTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJJTkNSRU1FTlRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIERlY3JlbWVudHMgdGhlIGdpdmVuIGBrZXlgIGluIG1lbWNhY2hlLlxuICAgKi9cbiAgYXN5bmMgZGVjcmVtZW50KFxuICAgIGtleTogc3RyaW5nLFxuICAgIGFtb3VudDogbnVtYmVyLFxuICAgIG9wdGlvbnM6IHsgaW5pdGlhbD86IG51bWJlcjsgZXhwaXJlcz86IG51bWJlciB9XG4gICk6IFByb21pc2U8eyB2YWx1ZTogbnVtYmVyIHwgbnVsbDsgc3VjY2VzczogYm9vbGVhbiB8IG51bGwgfT4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IGluaXRpYWwgPSBvcHRpb25zLmluaXRpYWwgfHwgMDtcbiAgICBjb25zdCBleHBpcmVzID0gb3B0aW9ucy5leHBpcmVzIHx8IHRoaXMub3B0aW9ucy5leHBpcmVzO1xuICAgIGNvbnN0IGV4dHJhcyA9IG1ha2VBbW91bnRJbml0aWFsQW5kRXhwaXJhdGlvbihhbW91bnQsIGluaXRpYWwsIGV4cGlyZXMpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgIGNvbnN0YW50cy5PUF9ERUNSRU1FTlQsXG4gICAgICBrZXksXG4gICAgICBleHRyYXMsXG4gICAgICBcIlwiLFxuICAgICAgdGhpcy5zZXFcbiAgICApO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICBjb25zdCBidWZJbnQgPVxuICAgICAgICAgIChyZXNwb25zZS52YWwucmVhZFVJbnQzMkJFKDApIDw8IDgpICsgcmVzcG9uc2UudmFsLnJlYWRVSW50MzJCRSg0KTtcbiAgICAgICAgcmV0dXJuIHsgdmFsdWU6IGJ1ZkludCwgc3VjY2VzczogdHJ1ZSB9O1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIkRFQ1JFTUVOVFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQXBwZW5kIHRoZSBnaXZlbiBfdmFsdWVfIHRvIHRoZSB2YWx1ZSBhc3NvY2lhdGVkIHdpdGggdGhlIGdpdmVuIF9rZXlfIGluXG4gICAqIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHMgaWYgdGhlIGtleSBpcyBhbHJlYWR5IHByZXNlbnQuXG4gICAqL1xuICBhc3luYyBhcHBlbmQoa2V5OiBzdHJpbmcsIHZhbHVlOiBWYWx1ZSk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IG9wY29kZTogY29uc3RhbnRzLk9QID0gY29uc3RhbnRzLk9QX0FQUEVORDtcbiAgICBjb25zdCBzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLnNlcmlhbGl6ZShvcGNvZGUsIHZhbHVlLCBcIlwiKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICBvcGNvZGUsXG4gICAgICBrZXksXG4gICAgICBzZXJpYWxpemVkLmV4dHJhcyxcbiAgICAgIHNlcmlhbGl6ZWQudmFsdWUsXG4gICAgICB0aGlzLnNlcVxuICAgICk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfTk9UX0ZPVU5EOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiQVBQRU5EXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBQcmVwZW5kIHRoZSBnaXZlbiBfdmFsdWVfIHRvIHRoZSB2YWx1ZSBhc3NvY2lhdGVkIHdpdGggdGhlIGdpdmVuIF9rZXlfIGluXG4gICAqIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHMgaWYgdGhlIGtleSBpcyBhbHJlYWR5IHByZXNlbnQuXG4gICAqL1xuICBhc3luYyBwcmVwZW5kKGtleTogc3RyaW5nLCB2YWx1ZTogVmFsdWUpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAvLyBUT0RPOiBzdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBvcGNvZGU6IGNvbnN0YW50cy5PUCA9IGNvbnN0YW50cy5PUF9QUkVQRU5EO1xuICAgIGNvbnN0IHNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuc2VyaWFsaXplKG9wY29kZSwgdmFsdWUsIFwiXCIpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgIG9wY29kZSxcbiAgICAgIGtleSxcbiAgICAgIHNlcmlhbGl6ZWQuZXh0cmFzLFxuICAgICAgc2VyaWFsaXplZC52YWx1ZSxcbiAgICAgIHRoaXMuc2VxXG4gICAgKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJQUkVQRU5EXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBUb3VjaCBzZXRzIGFuIGV4cGlyYXRpb24gdmFsdWUsIGdpdmVuIGJ5IF9leHBpcmVzXywgb24gdGhlIGdpdmVuIF9rZXlfIGluXG4gICAqIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHMgaWYgdGhlIGtleSBpcyBhbHJlYWR5IHByZXNlbnQuXG4gICAqL1xuICBhc3luYyB0b3VjaChrZXk6IHN0cmluZywgZXhwaXJlczogbnVtYmVyKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgLy8gVE9ETzogc3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgZXh0cmFzID0gbWFrZUV4cGlyYXRpb24oZXhwaXJlcyB8fCB0aGlzLm9wdGlvbnMuZXhwaXJlcyk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKDB4MWMsIGtleSwgZXh0cmFzLCBcIlwiLCB0aGlzLnNlcSk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfTk9UX0ZPVU5EOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiVE9VQ0hcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEZMVVNIXG4gICAqXG4gICAqIEZsdXNoZXMgdGhlIGNhY2hlIG9uIGVhY2ggY29ubmVjdGVkIHNlcnZlci4gVGhlIGNhbGxiYWNrIHNpZ25hdHVyZSBpczpcbiAgICpcbiAgICogICAgIGNhbGxiYWNrKGxhc3RFcnIsIHJlc3VsdHMpXG4gICAqXG4gICAqIHdoZXJlIF9sYXN0RXJyXyBpcyB0aGUgbGFzdCBlcnJvciBlbmNvdW50ZXJlZCAob3IgbnVsbCwgaW4gdGhlIGNvbW1vbiBjYXNlXG4gICAqIG9mIG5vIGVycm9ycykuIF9yZXN1bHRzXyBpcyBhIGRpY3Rpb25hcnkgbWFwcGluZyBgXCJob3N0bmFtZTpwb3J0XCJgIHRvIGVpdGhlclxuICAgKiBgdHJ1ZWAgKGlmIHRoZSBvcGVyYXRpb24gd2FzIHN1Y2Nlc3NmdWwpLCBvciBhbiBlcnJvci5cbiAgICogQHBhcmFtIGNhbGxiYWNrXG4gICAqL1xuICBmbHVzaCgpOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIGJvb2xlYW4gfCBFcnJvcj4+O1xuICBmbHVzaChcbiAgICBjYWxsYmFjazogKFxuICAgICAgZXJyOiBFcnJvciB8IG51bGwsXG4gICAgICByZXN1bHRzOiBSZWNvcmQ8c3RyaW5nLCBib29sZWFuIHwgRXJyb3I+XG4gICAgKSA9PiB2b2lkXG4gICk6IHZvaWQ7XG4gIGZsdXNoKFxuICAgIGNhbGxiYWNrPzogKFxuICAgICAgZXJyOiBFcnJvciB8IG51bGwsXG4gICAgICByZXN1bHRzOiBSZWNvcmQ8c3RyaW5nLCBib29sZWFuIHwgRXJyb3I+XG4gICAgKSA9PiB2b2lkXG4gICkge1xuICAgIGlmIChjYWxsYmFjayA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm4gcHJvbWlzaWZ5KChjYWxsYmFjaykgPT4ge1xuICAgICAgICB0aGlzLmZsdXNoKGZ1bmN0aW9uIChlcnIsIHJlc3VsdHMpIHtcbiAgICAgICAgICBjYWxsYmFjayhlcnIsIHJlc3VsdHMpO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH1cbiAgICAvLyBUT0RPOiBzdXBwb3J0IGV4cGlyYXRpb25cbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoMHgwOCwgXCJcIiwgXCJcIiwgXCJcIiwgdGhpcy5zZXEpO1xuICAgIGxldCBjb3VudCA9IHRoaXMuc2VydmVycy5sZW5ndGg7XG4gICAgY29uc3QgcmVzdWx0OiBSZWNvcmQ8c3RyaW5nLCBib29sZWFuIHwgRXJyb3I+ID0ge307XG4gICAgbGV0IGxhc3RFcnI6IEVycm9yIHwgbnVsbCA9IG51bGw7XG5cbiAgICBjb25zdCBoYW5kbGVGbHVzaCA9IGZ1bmN0aW9uIChzZXE6IG51bWJlciwgc2VydjogU2VydmVyKSB7XG4gICAgICBzZXJ2Lm9uUmVzcG9uc2Uoc2VxLCBmdW5jdGlvbiAoLyogcmVzcG9uc2UgKi8pIHtcbiAgICAgICAgY291bnQgLT0gMTtcbiAgICAgICAgcmVzdWx0W3NlcnYuaG9zdHBvcnRTdHJpbmcoKV0gPSB0cnVlO1xuICAgICAgICBpZiAoY2FsbGJhY2sgJiYgY291bnQgPT09IDApIHtcbiAgICAgICAgICBjYWxsYmFjayhsYXN0RXJyLCByZXN1bHQpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHNlcnYub25FcnJvcihzZXEsIGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgICAgY291bnQgLT0gMTtcbiAgICAgICAgbGFzdEVyciA9IGVycjtcbiAgICAgICAgcmVzdWx0W3NlcnYuaG9zdHBvcnRTdHJpbmcoKV0gPSBlcnI7XG4gICAgICAgIGlmIChjYWxsYmFjayAmJiBjb3VudCA9PT0gMCkge1xuICAgICAgICAgIGNhbGxiYWNrKGxhc3RFcnIsIHJlc3VsdCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgc2Vydi53cml0ZShyZXF1ZXN0KTtcbiAgICB9O1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnNlcnZlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGhhbmRsZUZsdXNoKHRoaXMuc2VxLCB0aGlzLnNlcnZlcnNbaV0pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTVEFUU19XSVRIX0tFWVxuICAgKlxuICAgKiBTZW5kcyBhIG1lbWNhY2hlIHN0YXRzIGNvbW1hbmQgd2l0aCBhIGtleSB0byBlYWNoIGNvbm5lY3RlZCBzZXJ2ZXIuIFRoZVxuICAgKiBjYWxsYmFjayBpcyBpbnZva2VkICoqT05DRSBQRVIgU0VSVkVSKiogYW5kIGhhcyB0aGUgc2lnbmF0dXJlOlxuICAgKlxuICAgKiAgICAgY2FsbGJhY2soZXJyLCBzZXJ2ZXIsIHN0YXRzKVxuICAgKlxuICAgKiBfc2VydmVyXyBpcyB0aGUgYFwiaG9zdG5hbWU6cG9ydFwiYCBvZiB0aGUgc2VydmVyLCBhbmQgX3N0YXRzXyBpcyBhIGRpY3Rpb25hcnlcbiAgICogbWFwcGluZyB0aGUgc3RhdCBuYW1lIHRvIHRoZSB2YWx1ZSBvZiB0aGUgc3RhdGlzdGljIGFzIGEgc3RyaW5nLlxuICAgKiBAcGFyYW0ga2V5XG4gICAqIEBwYXJhbSBjYWxsYmFja1xuICAgKi9cbiAgc3RhdHNXaXRoS2V5KFxuICAgIGtleTogc3RyaW5nLFxuICAgIGNhbGxiYWNrPzogKFxuICAgICAgZXJyOiBFcnJvciB8IG51bGwsXG4gICAgICBzZXJ2ZXI6IHN0cmluZyxcbiAgICAgIHN0YXRzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+IHwgbnVsbFxuICAgICkgPT4gdm9pZFxuICApOiB2b2lkIHtcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoMHgxMCwga2V5LCBcIlwiLCBcIlwiLCB0aGlzLnNlcSk7XG5cbiAgICBjb25zdCBoYW5kbGVTdGF0cyA9IChzZXE6IG51bWJlciwgc2VydjogU2VydmVyKSA9PiB7XG4gICAgICBjb25zdCByZXN1bHQ6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcbiAgICAgIGNvbnN0IGhhbmRsZTogT25SZXNwb25zZUNhbGxiYWNrID0gKHJlc3BvbnNlKSA9PiB7XG4gICAgICAgIC8vIGVuZCBvZiBzdGF0IHJlc3BvbnNlc1xuICAgICAgICBpZiAocmVzcG9uc2UuaGVhZGVyLnRvdGFsQm9keUxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgICAgY2FsbGJhY2sobnVsbCwgc2Vydi5ob3N0cG9ydFN0cmluZygpLCByZXN1bHQpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgLy8gcHJvY2VzcyBzaW5nbGUgc3RhdCBsaW5lIHJlc3BvbnNlXG4gICAgICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgICAgIHJlc3VsdFtyZXNwb25zZS5rZXkudG9TdHJpbmcoKV0gPSByZXNwb25zZS52YWwudG9TdHJpbmcoKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICBjb25zdCBlcnJvciA9IHRoaXMuaGFuZGxlUmVzcG9uc2VFcnJvcihcbiAgICAgICAgICAgICAgYFNUQVRTICgke2tleX0pYCxcbiAgICAgICAgICAgICAgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyxcbiAgICAgICAgICAgICAgdW5kZWZpbmVkXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgICAgICAgIGNhbGxiYWNrKGVycm9yLCBzZXJ2Lmhvc3Rwb3J0U3RyaW5nKCksIG51bGwpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9O1xuICAgICAgaGFuZGxlLnF1aWV0ID0gdHJ1ZTtcblxuICAgICAgc2Vydi5vblJlc3BvbnNlKHNlcSwgaGFuZGxlKTtcbiAgICAgIHNlcnYub25FcnJvcihzZXEsIGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgICAgY2FsbGJhY2soZXJyLCBzZXJ2Lmhvc3Rwb3J0U3RyaW5nKCksIG51bGwpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHNlcnYud3JpdGUocmVxdWVzdCk7XG4gICAgfTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5zZXJ2ZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBoYW5kbGVTdGF0cyh0aGlzLnNlcSwgdGhpcy5zZXJ2ZXJzW2ldKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU1RBVFNcbiAgICpcbiAgICogRmV0Y2hlcyBtZW1jYWNoZSBzdGF0cyBmcm9tIGVhY2ggY29ubmVjdGVkIHNlcnZlci4gVGhlIGNhbGxiYWNrIGlzIGludm9rZWRcbiAgICogKipPTkNFIFBFUiBTRVJWRVIqKiBhbmQgaGFzIHRoZSBzaWduYXR1cmU6XG4gICAqXG4gICAqICAgICBjYWxsYmFjayhlcnIsIHNlcnZlciwgc3RhdHMpXG4gICAqXG4gICAqIF9zZXJ2ZXJfIGlzIHRoZSBgXCJob3N0bmFtZTpwb3J0XCJgIG9mIHRoZSBzZXJ2ZXIsIGFuZCBfc3RhdHNfIGlzIGFcbiAgICogZGljdGlvbmFyeSBtYXBwaW5nIHRoZSBzdGF0IG5hbWUgdG8gdGhlIHZhbHVlIG9mIHRoZSBzdGF0aXN0aWMgYXMgYSBzdHJpbmcuXG4gICAqIEBwYXJhbSBjYWxsYmFja1xuICAgKi9cbiAgc3RhdHMoXG4gICAgY2FsbGJhY2s/OiAoXG4gICAgICBlcnI6IEVycm9yIHwgbnVsbCxcbiAgICAgIHNlcnZlcjogc3RyaW5nLFxuICAgICAgc3RhdHM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gfCBudWxsXG4gICAgKSA9PiB2b2lkXG4gICk6IHZvaWQge1xuICAgIHRoaXMuc3RhdHNXaXRoS2V5KFwiXCIsIGNhbGxiYWNrKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSRVNFVF9TVEFUU1xuICAgKlxuICAgKiBSZXNldCB0aGUgc3RhdGlzdGljcyBlYWNoIHNlcnZlciBpcyBrZWVwaW5nIGJhY2sgdG8gemVyby4gVGhpcyBkb2Vzbid0IGNsZWFyXG4gICAqIHN0YXRzIHN1Y2ggYXMgaXRlbSBjb3VudCwgYnV0IHRlbXBvcmFyeSBzdGF0cyBzdWNoIGFzIHRvdGFsIG51bWJlciBvZlxuICAgKiBjb25uZWN0aW9ucyBvdmVyIHRpbWUuXG4gICAqXG4gICAqIFRoZSBjYWxsYmFjayBpcyBpbnZva2VkICoqT05DRSBQRVIgU0VSVkVSKiogYW5kIGhhcyB0aGUgc2lnbmF0dXJlOlxuICAgKlxuICAgKiAgICAgY2FsbGJhY2soZXJyLCBzZXJ2ZXIpXG4gICAqXG4gICAqIF9zZXJ2ZXJfIGlzIHRoZSBgXCJob3N0bmFtZTpwb3J0XCJgIG9mIHRoZSBzZXJ2ZXIuXG4gICAqIEBwYXJhbSBjYWxsYmFja1xuICAgKi9cbiAgcmVzZXRTdGF0cyhcbiAgICBjYWxsYmFjaz86IChcbiAgICAgIGVycjogRXJyb3IgfCBudWxsLFxuICAgICAgc2VydmVyOiBzdHJpbmcsXG4gICAgICBzdGF0czogUmVjb3JkPHN0cmluZywgc3RyaW5nPiB8IG51bGxcbiAgICApID0+IHZvaWRcbiAgKTogdm9pZCB7XG4gICAgdGhpcy5zdGF0c1dpdGhLZXkoXCJyZXNldFwiLCBjYWxsYmFjayk7XG4gIH1cblxuICAvKipcbiAgICogUVVJVFxuICAgKlxuICAgKiBDbG9zZXMgdGhlIGNvbm5lY3Rpb24gdG8gZWFjaCBzZXJ2ZXIsIG5vdGlmeWluZyB0aGVtIG9mIHRoaXMgaW50ZW50aW9uLiBOb3RlXG4gICAqIHRoYXQgcXVpdCBjYW4gcmFjZSBhZ2FpbnN0IGFscmVhZHkgb3V0c3RhbmRpbmcgcmVxdWVzdHMgd2hlbiB0aG9zZSByZXF1ZXN0c1xuICAgKiBmYWlsIGFuZCBhcmUgcmV0cmllZCwgbGVhZGluZyB0byB0aGUgcXVpdCBjb21tYW5kIHdpbm5pbmcgYW5kIGNsb3NpbmcgdGhlXG4gICAqIGNvbm5lY3Rpb24gYmVmb3JlIHRoZSByZXRyaWVzIGNvbXBsZXRlLlxuICAgKi9cbiAgcXVpdCgpIHtcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICAvLyBUT0RPOiBOaWNlciBwZXJoYXBzIHRvIGRvIFFVSVRRICgweDE3KSBidXQgbmVlZCBhIG5ldyBjYWxsYmFjayBmb3Igd2hlblxuICAgIC8vIHdyaXRlIGlzIGRvbmUuXG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKDB4MDcsIFwiXCIsIFwiXCIsIFwiXCIsIHRoaXMuc2VxKTsgLy8gUVVJVFxuICAgIGxldCBzZXJ2O1xuXG4gICAgY29uc3QgaGFuZGxlUXVpdCA9IGZ1bmN0aW9uIChzZXE6IG51bWJlciwgc2VydjogU2VydmVyKSB7XG4gICAgICBzZXJ2Lm9uUmVzcG9uc2Uoc2VxLCBmdW5jdGlvbiAoLyogcmVzcG9uc2UgKi8pIHtcbiAgICAgICAgc2Vydi5jbG9zZSgpO1xuICAgICAgfSk7XG4gICAgICBzZXJ2Lm9uRXJyb3Ioc2VxLCBmdW5jdGlvbiAoLyogZXJyICovKSB7XG4gICAgICAgIHNlcnYuY2xvc2UoKTtcbiAgICAgIH0pO1xuICAgICAgc2Vydi53cml0ZShyZXF1ZXN0KTtcbiAgICB9O1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnNlcnZlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHNlcnYgPSB0aGlzLnNlcnZlcnNbaV07XG4gICAgICBoYW5kbGVRdWl0KHRoaXMuc2VxLCBzZXJ2KTtcbiAgICB9XG4gIH1cblxuICBfdmVyc2lvbihzZXJ2ZXI6IFNlcnZlcik6IFByb21pc2U8eyB2YWx1ZTogVmFsdWUgfCBudWxsIH0+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICAgIGNvbnN0YW50cy5PUF9WRVJTSU9OLFxuICAgICAgICBcIlwiLFxuICAgICAgICBcIlwiLFxuICAgICAgICBcIlwiLFxuICAgICAgICB0aGlzLnNlcVxuICAgICAgKTtcbiAgICAgIHRoaXMucGVyZm9ybU9uU2VydmVyKHNlcnZlciwgcmVxdWVzdCwgdGhpcy5zZXEsIChlcnIsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICByZXR1cm4gcmVqZWN0KGVycik7XG4gICAgICAgIH1cblxuICAgICAgICBzd2l0Y2ggKHJlc3BvbnNlIS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICAgICAgLyogVE9ETzogdGhpcyBpcyBidWdnZWQsIHdlIHNob3VsZCd0IHVzZSB0aGUgZGVzZXJpYWxpemVyIGhlcmUsIHNpbmNlIHZlcnNpb24gYWx3YXlzIHJldHVybnMgYSB2ZXJzaW9uIHN0cmluZy5cbiAgICAgICAgICAgICBUaGUgZGVzZXJpYWxpemVyIHNob3VsZCBvbmx5IGJlIHVzZWQgb24gdXNlciBrZXkgZGF0YS4gKi9cbiAgICAgICAgICAgIGNvbnN0IGRlc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5kZXNlcmlhbGl6ZShcbiAgICAgICAgICAgICAgcmVzcG9uc2UhLmhlYWRlci5vcGNvZGUsXG4gICAgICAgICAgICAgIHJlc3BvbnNlIS52YWwsXG4gICAgICAgICAgICAgIHJlc3BvbnNlIS5leHRyYXNcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICByZXR1cm4gcmVzb2x2ZSh7IHZhbHVlOiBkZXNlcmlhbGl6ZWQudmFsdWUgfSk7XG4gICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHJldHVybiByZWplY3QoXG4gICAgICAgICAgICAgIHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJWRVJTSU9OXCIsIHJlc3BvbnNlIS5oZWFkZXIuc3RhdHVzKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmVxdWVzdCB0aGUgc2VydmVyIHZlcnNpb24gZnJvbSB0aGUgXCJmaXJzdFwiIHNlcnZlciBpbiB0aGUgYmFja2VuZCBwb29sLlxuICAgKiBUaGUgc2VydmVyIHJlc3BvbmRzIHdpdGggYSBwYWNrZXQgY29udGFpbmluZyB0aGUgdmVyc2lvbiBzdHJpbmcgaW4gdGhlIGJvZHkgd2l0aCB0aGUgZm9sbG93aW5nIGZvcm1hdDogXCJ4LnkuelwiXG4gICAqL1xuICB2ZXJzaW9uKCk6IFByb21pc2U8eyB2YWx1ZTogVmFsdWUgfCBudWxsIH0+IHtcbiAgICBjb25zdCBzZXJ2ZXIgPSB0aGlzLnNlcnZlcktleVRvU2VydmVyKHRoaXMuc2VydmVyS2V5c1swXSk7XG4gICAgcmV0dXJuIHRoaXMuX3ZlcnNpb24oc2VydmVyKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXRyaWV2ZXMgdGhlIHNlcnZlciB2ZXJzaW9uIGZyb20gYWxsIHRoZSBzZXJ2ZXJzXG4gICAqIGluIHRoZSBiYWNrZW5kIHBvb2wsIGVycm9ycyBpZiBhbnkgb25lIG9mIHRoZW0gaGFzIGFuXG4gICAqIGVycm9yXG4gICAqXG4gICAqIENhbGxiYWNrcyBmdW5jdGlvbnMgYXJlIGNhbGxlZCBiZWZvcmUvYWZ0ZXIgd2UgcGluZyBtZW1jYWNoZWRcbiAgICogYW5kIHVzZWQgdG8gbG9nIHdoaWNoIGhvc3RzIGFyZSB0aW1pbmcgb3V0LlxuICAgKi9cbiAgYXN5bmMgdmVyc2lvbkFsbChjYWxsYmFja3M/OiB7XG4gICAgYmVmb3JlUGluZz86IChzZXJ2ZXJLZXk6IHN0cmluZykgPT4gdm9pZDtcbiAgICBhZnRlclBpbmc/OiAoc2VydmVyS2V5OiBzdHJpbmcpID0+IHZvaWQ7XG4gIH0pOiBQcm9taXNlPHtcbiAgICB2YWx1ZXM6IFJlY29yZDxzdHJpbmcsIFZhbHVlIHwgbnVsbD47XG4gIH0+IHtcbiAgICBjb25zdCB2ZXJzaW9uT2JqZWN0cyA9IGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgdGhpcy5zZXJ2ZXJLZXlzLm1hcCgoc2VydmVyS2V5KSA9PiB7XG4gICAgICAgIGNvbnN0IHNlcnZlciA9IHRoaXMuc2VydmVyS2V5VG9TZXJ2ZXIoc2VydmVyS2V5KTtcbiAgICAgICAgY2FsbGJhY2tzPy5iZWZvcmVQaW5nPy4oc2VydmVyS2V5KTtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3ZlcnNpb24oc2VydmVyKS50aGVuKChyZXNwb25zZSkgPT4ge1xuICAgICAgICAgIGNhbGxiYWNrcz8uYWZ0ZXJQaW5nPy4oc2VydmVyS2V5KTtcbiAgICAgICAgICByZXR1cm4geyBzZXJ2ZXJLZXk6IHNlcnZlcktleSwgdmFsdWU6IHJlc3BvbnNlLnZhbHVlIH07XG4gICAgICAgIH0pO1xuICAgICAgfSlcbiAgICApO1xuICAgIGNvbnN0IHZhbHVlcyA9IHZlcnNpb25PYmplY3RzLnJlZHVjZSgoYWNjdW11bGF0b3IsIHZlcnNpb25PYmplY3QpID0+IHtcbiAgICAgIGFjY3VtdWxhdG9yW3ZlcnNpb25PYmplY3Quc2VydmVyS2V5XSA9IHZlcnNpb25PYmplY3QudmFsdWU7XG4gICAgICByZXR1cm4gYWNjdW11bGF0b3I7XG4gICAgfSwge30gYXMgUmVjb3JkPHN0cmluZywgVmFsdWUgfCBudWxsPik7XG4gICAgcmV0dXJuIHsgdmFsdWVzOiB2YWx1ZXMgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDbG9zZXMgKGFicnVwdGx5KSBjb25uZWN0aW9ucyB0byBhbGwgdGhlIHNlcnZlcnMuXG4gICAqIEBzZWUgdGhpcy5xdWl0XG4gICAqL1xuICBjbG9zZSgpIHtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuc2VydmVycy5sZW5ndGg7IGkrKykge1xuICAgICAgdGhpcy5zZXJ2ZXJzW2ldLmNsb3NlKCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFBlcmZvcm0gYSBnZW5lcmljIHNpbmdsZSByZXNwb25zZSBvcGVyYXRpb24gKGdldCwgc2V0IGV0Yykgb24gb25lIHNlcnZlclxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IHRoZSBrZXkgdG8gaGFzaCB0byBnZXQgYSBzZXJ2ZXIgZnJvbSB0aGUgcG9vbFxuICAgKiBAcGFyYW0ge2J1ZmZlcn0gcmVxdWVzdCBhIGJ1ZmZlciBjb250YWluaW5nIHRoZSByZXF1ZXN0XG4gICAqIEBwYXJhbSB7bnVtYmVyfSBzZXEgdGhlIHNlcXVlbmNlIG51bWJlciBvZiB0aGUgb3BlcmF0aW9uLiBJdCBpcyB1c2VkIHRvIHBpbiB0aGUgY2FsbGJhY2tzXG4gICAgICAgICAgICAgICAgICAgICAgICAgdG8gYSBzcGVjaWZpYyBvcGVyYXRpb24gYW5kIHNob3VsZCBuZXZlciBjaGFuZ2UgZHVyaW5nIGEgYHBlcmZvcm1gLlxuICAgKiBAcGFyYW0ge251bWJlcj99IHJldHJpZXMgbnVtYmVyIG9mIHRpbWVzIHRvIHJldHJ5IHJlcXVlc3Qgb24gZmFpbHVyZVxuICAgKi9cbiAgcGVyZm9ybShcbiAgICBrZXk6IHN0cmluZyxcbiAgICByZXF1ZXN0OiBCdWZmZXIsXG4gICAgc2VxOiBudW1iZXIsXG4gICAgcmV0cmllcz86IG51bWJlclxuICApOiBQcm9taXNlPE1lc3NhZ2U+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgY29uc3Qgc2VydmVyS2V5ID0gdGhpcy5sb29rdXBLZXlUb1NlcnZlcktleShrZXkpO1xuICAgICAgY29uc3Qgc2VydmVyID0gdGhpcy5zZXJ2ZXJLZXlUb1NlcnZlcihzZXJ2ZXJLZXkpO1xuXG4gICAgICBpZiAoIXNlcnZlcikge1xuICAgICAgICByZXR1cm4gcmVqZWN0KG5ldyBFcnJvcihcIk5vIHNlcnZlcnMgYXZhaWxhYmxlXCIpKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5wZXJmb3JtT25TZXJ2ZXIoXG4gICAgICAgIHNlcnZlcixcbiAgICAgICAgcmVxdWVzdCxcbiAgICAgICAgc2VxLFxuICAgICAgICAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICByZXR1cm4gcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmVzb2x2ZShyZXNwb25zZSEpO1xuICAgICAgICB9LFxuICAgICAgICByZXRyaWVzXG4gICAgICApO1xuICAgIH0pO1xuICB9XG5cbiAgcGVyZm9ybU9uU2VydmVyKFxuICAgIHNlcnZlcjogU2VydmVyLFxuICAgIHJlcXVlc3Q6IEJ1ZmZlcixcbiAgICBzZXE6IG51bWJlcixcbiAgICBjYWxsYmFjazogUmVzcG9uc2VPckVycm9yQ2FsbGJhY2ssXG4gICAgcmV0cmllczogbnVtYmVyID0gMFxuICApIHtcbiAgICBjb25zdCBfdGhpcyA9IHRoaXM7XG5cbiAgICByZXRyaWVzID0gcmV0cmllcyB8fCB0aGlzLm9wdGlvbnMucmV0cmllcztcbiAgICBjb25zdCBvcmlnUmV0cmllcyA9IHRoaXMub3B0aW9ucy5yZXRyaWVzO1xuICAgIGNvbnN0IGxvZ2dlciA9IHRoaXMub3B0aW9ucy5sb2dnZXI7XG4gICAgY29uc3QgcmV0cnlfZGVsYXkgPSB0aGlzLm9wdGlvbnMucmV0cnlfZGVsYXk7XG5cbiAgICBjb25zdCByZXNwb25zZUhhbmRsZXI6IE9uUmVzcG9uc2VDYWxsYmFjayA9IGZ1bmN0aW9uIChyZXNwb25zZSkge1xuICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgIGNhbGxiYWNrKG51bGwsIHJlc3BvbnNlKTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgY29uc3QgZXJyb3JIYW5kbGVyOiBPbkVycm9yQ2FsbGJhY2sgPSBmdW5jdGlvbiAoZXJyb3IpIHtcbiAgICAgIGlmICgtLXJldHJpZXMgPiAwKSB7XG4gICAgICAgIC8vIFdhaXQgZm9yIHJldHJ5X2RlbGF5XG4gICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgIF90aGlzLnBlcmZvcm1PblNlcnZlcihzZXJ2ZXIsIHJlcXVlc3QsIHNlcSwgY2FsbGJhY2ssIHJldHJpZXMpO1xuICAgICAgICB9LCAxMDAwICogcmV0cnlfZGVsYXkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbG9nZ2VyLmxvZyhcbiAgICAgICAgICBcIk1lbUpTOiBTZXJ2ZXIgPFwiICtcbiAgICAgICAgICAgIHNlcnZlci5ob3N0cG9ydFN0cmluZygpICtcbiAgICAgICAgICAgIFwiPiBmYWlsZWQgYWZ0ZXIgKFwiICtcbiAgICAgICAgICAgIG9yaWdSZXRyaWVzICtcbiAgICAgICAgICAgIFwiKSByZXRyaWVzIHdpdGggZXJyb3IgLSBcIiArXG4gICAgICAgICAgICBlcnJvci5tZXNzYWdlXG4gICAgICAgICk7XG4gICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgIGNhbGxiYWNrKGVycm9yLCBudWxsKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH07XG5cbiAgICBzZXJ2ZXIub25SZXNwb25zZShzZXEsIHJlc3BvbnNlSGFuZGxlcik7XG4gICAgc2VydmVyLm9uRXJyb3Ioc2VxLCBlcnJvckhhbmRsZXIpO1xuICAgIHNlcnZlci53cml0ZShyZXF1ZXN0KTtcbiAgfVxuXG4gIC8vIEluY3JlbWVudCB0aGUgc2VxIHZhbHVlXG4gIGluY3JTZXEoKSB7XG4gICAgdGhpcy5zZXErKztcblxuICAgIC8vIFdyYXAgYHRoaXMuc2VxYCB0byAzMi1iaXRzIHNpbmNlIHRoZSBmaWVsZCB3ZSBmaXQgaXQgaW50byBpcyBvbmx5IDMyLWJpdHMuXG4gICAgdGhpcy5zZXEgJj0gMHhmZmZmZmZmZjtcblxuICAgIHJldHVybiB0aGlzLnNlcTtcbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlQW5kTG9nRXJyb3IoXG4gICAgY29tbWFuZE5hbWU6IHN0cmluZyxcbiAgICByZXNwb25zZVN0YXR1czogUmVzcG9uc2VTdGF0dXMgfCB1bmRlZmluZWRcbiAgKTogRXJyb3Ige1xuICAgIGNvbnN0IGVycm9yTWVzc2FnZSA9IGBNZW1KUyAke2NvbW1hbmROYW1lfTogJHtjb25zdGFudHMucmVzcG9uc2VTdGF0dXNUb1N0cmluZyhcbiAgICAgIHJlc3BvbnNlU3RhdHVzXG4gICAgKX1gO1xuICAgIHRoaXMub3B0aW9ucy5sb2dnZXIubG9nKGVycm9yTWVzc2FnZSk7XG4gICAgcmV0dXJuIG5ldyBFcnJvcihlcnJvck1lc3NhZ2UpO1xuICB9XG5cbiAgLyoqXG4gICAqIExvZyBhbiBlcnJvciB0byB0aGUgbG9nZ2VyLCB0aGVuIHJldHVybiB0aGUgZXJyb3IuXG4gICAqIElmIGEgY2FsbGJhY2sgaXMgZ2l2ZW4sIGNhbGwgaXQgd2l0aCBjYWxsYmFjayhlcnJvciwgbnVsbCkuXG4gICAqL1xuICBwcml2YXRlIGhhbmRsZVJlc3BvbnNlRXJyb3IoXG4gICAgY29tbWFuZE5hbWU6IHN0cmluZyxcbiAgICByZXNwb25zZVN0YXR1czogUmVzcG9uc2VTdGF0dXMgfCB1bmRlZmluZWQsXG4gICAgY2FsbGJhY2s6IHVuZGVmaW5lZCB8ICgoZXJyb3I6IEVycm9yIHwgbnVsbCwgb3RoZXI6IG51bGwpID0+IHZvaWQpXG4gICk6IEVycm9yIHtcbiAgICBjb25zdCBlcnJvciA9IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoY29tbWFuZE5hbWUsIHJlc3BvbnNlU3RhdHVzKTtcbiAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgIGNhbGxiYWNrKGVycm9yLCBudWxsKTtcbiAgICB9XG4gICAgcmV0dXJuIGVycm9yO1xuICB9XG59XG5cbmV4cG9ydCB7IENsaWVudCwgU2VydmVyLCBVdGlscywgSGVhZGVyIH07XG4iXX0= \ No newline at end of file diff --git a/lib/memjs/server.d.ts.map b/lib/memjs/server.d.ts.map index d442462..2744987 100644 --- a/lib/memjs/server.d.ts.map +++ b/lib/memjs/server.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/memjs/server.ts"],"names":[],"mappings":";AAAA,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAKL,OAAO,EACR,MAAM,SAAS,CAAC;AAEjB,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,aAAK,GAAG,GAAG,MAAM,CAAC;AAElB,MAAM,WAAW,iBAAiB;IAChC,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,MAAM,WAAW,kBAAkB;IACjC,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACzB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;CACtB;AAED,qBAAa,MAAO,SAAQ,MAAM,CAAC,YAAY;IAC7C,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IAClC,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;IACpB,gBAAgB,EAAE,iBAAiB,EAAE,CAAC;IACtC,iBAAiB,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,kBAAkB,CAAA;KAAE,CAAC;IACzD,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,cAAc,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,CAAA;KAAE,CAAC;IACnD,OAAO,EAAE,aAAa,CAAC;IACvB,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAE7B,OAAO,EAAE,GAAG,CAAC,MAAM,GAAG,SAAS,CAAC;gBAG9B,IAAI,EAAE,MAAM,EAEZ,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,EACtB,QAAQ,CAAC,EAAE,MAAM,EACjB,QAAQ,CAAC,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC;IAoClC,SAAS,CAAC,IAAI,EAAE,iBAAiB;IAIjC,UAAU,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,kBAAkB;IAI7C,OAAO,CAAC,QAAQ,EAAE,OAAO;IAczB,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,eAAe;IAIvC,KAAK,CAAC,GAAG,EAAE,KAAK;IAgBhB,QAAQ;IAKR,QAAQ;IAMR,cAAc,CAAC,OAAO,EAAE,MAAM;IAO9B,eAAe,CAAC,OAAO,EAAE,MAAM;IAkB/B,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,iBAAiB;IAqFzC,KAAK,CAAC,IAAI,EAAE,MAAM;IAelB,SAAS,CAAC,IAAI,EAAE,MAAM;IAMtB,KAAK;IAML,QAAQ;IAIR,cAAc;CAGf"} \ No newline at end of file +{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/memjs/server.ts"],"names":[],"mappings":";AAAA,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAKL,OAAO,EACR,MAAM,SAAS,CAAC;AAEjB,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,aAAK,GAAG,GAAG,MAAM,CAAC;AAElB,MAAM,WAAW,iBAAiB;IAChC,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,MAAM,WAAW,kBAAkB;IACjC,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACzB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;CACtB;AAED,qBAAa,MAAO,SAAQ,MAAM,CAAC,YAAY;IAC7C,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IAClC,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;IACpB,gBAAgB,EAAE,iBAAiB,EAAE,CAAC;IACtC,iBAAiB,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,kBAAkB,CAAA;KAAE,CAAC;IACzD,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,cAAc,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,CAAA;KAAE,CAAC;IACnD,OAAO,EAAE,aAAa,CAAC;IACvB,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAE7B,OAAO,EAAE,GAAG,CAAC,MAAM,GAAG,SAAS,CAAC;gBAG9B,IAAI,EAAE,MAAM,EAEZ,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,EACtB,QAAQ,CAAC,EAAE,MAAM,EACjB,QAAQ,CAAC,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC;IAoClC,SAAS,CAAC,IAAI,EAAE,iBAAiB;IAIjC,UAAU,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,kBAAkB;IAI7C,OAAO,CAAC,QAAQ,EAAE,OAAO;IAczB,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,eAAe;IAIvC,KAAK,CAAC,GAAG,EAAE,KAAK;IAgBhB,QAAQ;IAKR,QAAQ;IAMR,cAAc,CAAC,OAAO,EAAE,MAAM;IAO9B,eAAe,CAAC,OAAO,EAAE,MAAM;IAkB/B,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,iBAAiB;IAsFzC,KAAK,CAAC,IAAI,EAAE,MAAM;IAelB,SAAS,CAAC,IAAI,EAAE,MAAM;IAMtB,KAAK;IAML,QAAQ;IAIR,cAAc;CAGf"} \ No newline at end of file diff --git a/lib/memjs/server.js b/lib/memjs/server.js index 08f2361..e35d5d6 100644 --- a/lib/memjs/server.js +++ b/lib/memjs/server.js @@ -156,15 +156,16 @@ class Server extends events_1.default.EventEmitter { }); // setup error handler self._socket.on("error", function (error) { + self.error(error); + }); + self._socket.on("close", function () { + var _a; self.connected = false; if (self.timeoutSet) { - if (self._socket) { - self._socket.setTimeout(0); - } + (_a = self._socket) === null || _a === void 0 ? void 0 : _a.setTimeout(0); self.timeoutSet = false; } self._socket = undefined; - self.error(error); }); // setup connection timeout handler self.timeoutSet = true; @@ -248,4 +249,4 @@ const timeoutHandler = function (server, sock) { }); } }; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL21lbWpzL3NlcnZlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSw4Q0FBc0I7QUFDdEIsb0RBQTRCO0FBQzVCLG1DQU1pQjtBQTBCakIsTUFBYSxNQUFPLFNBQVEsZ0JBQU0sQ0FBQyxZQUFZO0lBZ0I3QyxZQUNFLElBQVk7SUFDWixnR0FBZ0c7SUFDaEcsSUFBc0IsRUFDdEIsUUFBaUIsRUFDakIsUUFBaUIsRUFDakIsT0FBZ0M7UUFFaEMsS0FBSyxFQUFFLENBQUM7UUFDUixJQUFJLENBQUMsY0FBYyxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDdEMsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUM7UUFDakIsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUM7UUFDakIsSUFBSSxDQUFDLFNBQVMsR0FBRyxLQUFLLENBQUM7UUFDdkIsSUFBSSxDQUFDLFVBQVUsR0FBRyxLQUFLLENBQUM7UUFDeEIsSUFBSSxDQUFDLGdCQUFnQixHQUFHLEVBQUUsQ0FBQztRQUMzQixJQUFJLENBQUMsaUJBQWlCLEdBQUcsRUFBRSxDQUFDO1FBQzVCLElBQUksQ0FBQyxlQUFlLEdBQUcsRUFBRSxDQUFDO1FBQzFCLElBQUksQ0FBQyxjQUFjLEdBQUcsRUFBRSxDQUFDO1FBQ3pCLElBQUksQ0FBQyxPQUFPLEdBQUcsYUFBSyxDQUFDLE9BQU8sSUFBSSxFQUFFLEVBQUU7WUFDbEMsT0FBTyxFQUFFLEdBQUc7WUFDWixTQUFTLEVBQUUsS0FBSztZQUNoQixjQUFjLEVBQUUsRUFBRTtTQUNuQixDQUFrQixDQUFDO1FBQ3BCLElBQ0UsSUFBSSxDQUFDLE9BQU8sQ0FBQyxXQUFXLEtBQUssU0FBUztZQUN0QyxJQUFJLENBQUMsT0FBTyxDQUFDLFdBQVcsS0FBSyxJQUFJLEVBQ2pDO1lBQ0EsSUFBSSxDQUFDLE9BQU8sQ0FBQyxXQUFXLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDO1NBQ3JEO1FBQ0QsSUFBSSxDQUFDLFFBQVE7WUFDWCxRQUFRO2dCQUNSLElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUTtnQkFDckIsT0FBTyxDQUFDLEdBQUcsQ0FBQyxtQkFBbUI7Z0JBQy9CLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUM7UUFDaEMsSUFBSSxDQUFDLFFBQVE7WUFDWCxRQUFRO2dCQUNSLElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUTtnQkFDckIsT0FBTyxDQUFDLEdBQUcsQ0FBQyxtQkFBbUI7Z0JBQy9CLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUM7UUFDaEMsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRUQsU0FBUyxDQUFDLElBQXVCO1FBQy9CLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDbkMsQ0FBQztJQUVELFVBQVUsQ0FBQyxHQUFRLEVBQUUsSUFBd0I7UUFDM0MsSUFBSSxDQUFDLGlCQUFpQixDQUFDLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQztJQUNyQyxDQUFDO0lBRUQsT0FBTyxDQUFDLFFBQWlCO1FBQ3ZCLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ2hFLElBQUksQ0FBQyxRQUFRLEVBQUU7WUFDYix1REFBdUQ7WUFDdkQsT0FBTztTQUNSO1FBQ0QsUUFBUSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ25CLElBQUksQ0FBQyxRQUFRLENBQUMsS0FBSyxJQUFJLFFBQVEsQ0FBQyxNQUFNLENBQUMsZUFBZSxLQUFLLENBQUMsRUFBRTtZQUM1RCxPQUFPLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQ3RELElBQUksQ0FBQyxlQUFlLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDN0IsT0FBTyxJQUFJLENBQUMsY0FBYyxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUM7U0FDcEQ7SUFDSCxDQUFDO0lBRUQsT0FBTyxDQUFDLEdBQVEsRUFBRSxJQUFxQjtRQUNyQyxJQUFJLENBQUMsY0FBYyxDQUFDLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQztJQUNsQyxDQUFDO0lBRUQsS0FBSyxDQUFDLEdBQVU7UUFDZCxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsY0FBYyxDQUFDO1FBQ3JDLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxFQUFFLENBQUM7UUFDM0IsSUFBSSxDQUFDLGlCQUFpQixHQUFHLEVBQUUsQ0FBQztRQUM1QixJQUFJLENBQUMsZUFBZSxHQUFHLEVBQUUsQ0FBQztRQUMxQixJQUFJLENBQUMsY0FBYyxHQUFHLEVBQUUsQ0FBQztRQUN6QixJQUFJLENBQUMsVUFBVSxHQUFHLEtBQUssQ0FBQztRQUN4QixJQUFJLElBQUksQ0FBQyxPQUFPLEVBQUU7WUFDaEIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUN2QixPQUFPLElBQUksQ0FBQyxPQUFPLENBQUM7U0FDckI7UUFDRCxLQUFLLElBQUksT0FBTyxJQUFJLE1BQU0sQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLEVBQUU7WUFDM0MsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1NBQ2Q7SUFDSCxDQUFDO0lBRUQsUUFBUTtRQUNOLE1BQU0sR0FBRyxHQUFHLHlCQUFpQixDQUFDLElBQUksRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBQ2hELElBQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDdEIsQ0FBQztJQUVELFFBQVE7UUFDTixNQUFNLE9BQU8sR0FBRyxNQUFNLEdBQUcsSUFBSSxDQUFDLFFBQVEsR0FBRyxNQUFNLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQztRQUNoRSxNQUFNLEdBQUcsR0FBRyx5QkFBaUIsQ0FBQyxJQUFJLEVBQUUsT0FBTyxFQUFFLEVBQUUsRUFBRSxPQUFPLENBQUMsQ0FBQztRQUMxRCxJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ3RCLENBQUM7SUFFRCxjQUFjLENBQUMsT0FBZTtRQUM1QixNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsY0FBYyxDQUFDO1FBQ2hDLElBQUksQ0FBQyxjQUFjLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsTUFBTSxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUNoRSxHQUFHLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDakMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsY0FBYyxFQUFFLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUM5QyxPQUFPLElBQUksQ0FBQyxjQUFjLENBQUM7SUFDN0IsQ0FBQztJQUNELGVBQWUsQ0FBQyxPQUFlO1FBQzdCLElBQUksUUFBUSxHQUFHLG9CQUFZLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO1FBQzFELElBQUksVUFBa0IsQ0FBQztRQUN2QixPQUFPLFFBQVEsRUFBRTtZQUNmLElBQUksUUFBUSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEtBQUssSUFBSSxFQUFFO2dCQUNuQyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7YUFDakI7aUJBQU0sSUFBSSxRQUFRLENBQUMsTUFBTSxDQUFDLE1BQU0sS0FBTSxJQUFZLENBQUMsZ0JBQWdCLEVBQUU7Z0JBQ3BFLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxLQUFLLENBQUMseUNBQXlDLENBQUMsQ0FBQyxDQUFDO2FBQ2xFO2lCQUFNLElBQUksUUFBUSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEtBQUssSUFBSSxFQUFFO2dCQUMxQyxJQUFJLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxDQUFDO2FBQzVCO2lCQUFNO2dCQUNMLElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUM7YUFDeEI7WUFDRCxVQUFVLEdBQUcsUUFBUSxDQUFDLE1BQU0sQ0FBQyxlQUFlLEdBQUcsRUFBRSxDQUFDO1lBQ2xELElBQUksQ0FBQyxjQUFjLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLENBQUM7WUFDNUQsUUFBUSxHQUFHLG9CQUFZLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxDQUFDO1NBQzlDO0lBQ0gsQ0FBQztJQUNELElBQUksQ0FBQyxJQUFhLEVBQUUsRUFBcUI7UUFDdkMsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDO1FBRWxCLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFO1lBQ2pCLGdDQUFnQztZQUNoQyxJQUFJLENBQUMsU0FBUyxHQUFHLEtBQUssQ0FBQztZQUN2QixJQUFJLENBQUMsT0FBTyxHQUFHLGFBQUcsQ0FBQyxPQUFPO1lBQ3hCLGdHQUFnRztZQUNoRyxPQUFPLElBQUksQ0FBQyxJQUFJLEtBQUssUUFBUTtnQkFDM0IsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQztnQkFDekIsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLElBQUksS0FBSyxFQUN0QixJQUFJLENBQUMsSUFBSSxFQUNUO2dCQUNFLDhCQUE4QjtnQkFDOUIsSUFBSSxDQUFDLElBQUksQ0FBQyxlQUFlLEVBQUU7b0JBQ3pCLElBQUksSUFBSSxDQUFDLE9BQU8sRUFBRTt3QkFDaEIsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQzt3QkFDNUIsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUM7d0JBQ3RCLDRCQUE0Qjt3QkFDNUIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUM7d0JBQzNCLElBQUksQ0FBQyxVQUFVLEdBQUcsS0FBSyxDQUFDO3dCQUN4Qix3QkFBd0I7d0JBQ3hCLEVBQUUsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7d0JBQ2pCLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLENBQUMsVUFBVSxFQUFFOzRCQUN4QyxFQUFFLENBQUMsTUFBTSxDQUFDLENBQUM7d0JBQ2IsQ0FBQyxDQUFDLENBQUM7d0JBQ0gsSUFBSSxDQUFDLGdCQUFnQixHQUFHLEVBQUUsQ0FBQztxQkFDNUI7Z0JBQ0gsQ0FBQyxDQUFDLENBQUM7Z0JBRUgseUJBQXlCO2dCQUN6QixJQUFJLENBQUMsRUFBRSxDQUFDLE1BQU0sRUFBRSxVQUFVLE9BQU87b0JBQy9CLElBQUksQ0FBQyxlQUFlLENBQUMsT0FBTyxDQUFDLENBQUM7Z0JBQ2hDLENBQUMsQ0FBQyxDQUFDO2dCQUVILHlCQUF5QjtnQkFDekIsSUFBSSxJQUFJLENBQUMsUUFBUSxJQUFJLElBQUksQ0FBQyxRQUFRLEVBQUU7b0JBQ2xDLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztpQkFDakI7cUJBQU07b0JBQ0wsSUFBSSxDQUFDLElBQUksQ0FBQyxlQUFlLENBQUMsQ0FBQztpQkFDNUI7WUFDSCxDQUFDLENBQ0YsQ0FBQztZQUVGLHNCQUFzQjtZQUN0QixJQUFJLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsVUFBVSxLQUFLO2dCQUN0QyxJQUFJLENBQUMsU0FBUyxHQUFHLEtBQUssQ0FBQztnQkFDdkIsSUFBSSxJQUFJLENBQUMsVUFBVSxFQUFFO29CQUNuQixJQUFJLElBQUksQ0FBQyxPQUFPLEVBQUU7d0JBQ2hCLElBQUksQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDO3FCQUM1QjtvQkFDRCxJQUFJLENBQUMsVUFBVSxHQUFHLEtBQUssQ0FBQztpQkFDekI7Z0JBQ0QsSUFBSSxDQUFDLE9BQU8sR0FBRyxTQUFTLENBQUM7Z0JBQ3pCLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDcEIsQ0FBQyxDQUFDLENBQUM7WUFFSCxtQ0FBbUM7WUFDbkMsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUM7WUFDdkIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQ3JCLElBQUksQ0FBQyxPQUFPLENBQUMsV0FBVyxHQUFHLElBQUksRUFDL0I7Z0JBQ0UsSUFBSSxDQUFDLFVBQVUsR0FBRyxLQUFLLENBQUM7Z0JBQ3hCLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFO29CQUNuQixJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7b0JBQ1gsSUFBSSxDQUFDLE9BQU8sR0FBRyxTQUFTLENBQUM7b0JBQ3pCLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxLQUFLLENBQUMsd0NBQXdDLENBQUMsQ0FBQyxDQUFDO2lCQUNqRTtZQUNILENBQUMsQ0FDRixDQUFDO1lBRUYscUJBQXFCO1lBQ3JCLElBQUksQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUN2QixJQUFJLENBQUMsT0FBTyxDQUFDLFNBQVMsRUFDdEIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxjQUFjLEdBQUcsSUFBSSxDQUNuQyxDQUFDO1NBQ0g7YUFBTSxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsSUFBSSxDQUFDLElBQUksRUFBRTtZQUNuQywrREFBK0Q7WUFDL0QsSUFBSSxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsQ0FBQztTQUNwQjthQUFNO1lBQ0wscURBQXFEO1lBQ3JELEVBQUUsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7U0FDbEI7SUFDSCxDQUFDO0lBRUQsS0FBSyxDQUFDLElBQVk7UUFDaEIsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDO1FBQ2xCLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDLENBQUM7UUFDekQsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsVUFBVSxDQUFDO1lBQzFCLENBQUMsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDZCxJQUFJLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxpQkFBUyxFQUFFLEdBQUcsUUFBUSxDQUFDLENBQUM7WUFDbEQsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLEVBQUU7Z0JBQ3BCLElBQUksQ0FBQyxVQUFVLEdBQUcsSUFBSSxDQUFDO2dCQUN2QixDQUFDLENBQUMsVUFBVSxDQUFDLFFBQVEsRUFBRTtvQkFDckIsY0FBYyxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQztnQkFDN0IsQ0FBQyxDQUFDLENBQUM7YUFDSjtRQUNILENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVELFNBQVMsQ0FBQyxJQUFZO1FBQ3BCLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLFVBQVUsQ0FBQztZQUN6QixDQUFDLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ2hCLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVELEtBQUs7UUFDSCxJQUFJLElBQUksQ0FBQyxPQUFPLEVBQUU7WUFDaEIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUUsQ0FBQztTQUNwQjtJQUNILENBQUM7SUFFRCxRQUFRO1FBQ04sT0FBTyxVQUFVLEdBQUcsSUFBSSxDQUFDLElBQUksR0FBRyxHQUFHLEdBQUcsSUFBSSxDQUFDLElBQUksR0FBRyxHQUFHLENBQUM7SUFDeEQsQ0FBQztJQUVELGNBQWM7UUFDWixPQUFPLElBQUksQ0FBQyxJQUFJLEdBQUcsR0FBRyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUM7SUFDckMsQ0FBQztDQUNGO0FBL1BELHdCQStQQztBQUVELCtFQUErRTtBQUMvRSw2RUFBNkU7QUFDN0Usb0JBQW9CO0FBQ3BCLE1BQU0sY0FBYyxHQUFHLFVBQVUsTUFBYyxFQUFFLElBQWdCO0lBQy9ELElBQUksTUFBTSxDQUFDLGVBQWUsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFO1FBQ3ZDLGlCQUFpQjtRQUNqQixNQUFNLENBQUMsVUFBVSxHQUFHLEtBQUssQ0FBQztRQUMxQixPQUFPO0tBQ1I7SUFFRCx5REFBeUQ7SUFDekQsTUFBTSxHQUFHLEdBQUcsaUJBQVMsRUFBRSxDQUFDO0lBQ3hCLE1BQU0sY0FBYyxHQUFHLE1BQU0sQ0FBQyxlQUFlLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFFakQsSUFBSSxjQUFjLElBQUksR0FBRyxFQUFFO1FBQ3pCLG9CQUFvQjtRQUNwQixJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7UUFDWCxNQUFNLENBQUMsU0FBUyxHQUFHLEtBQUssQ0FBQztRQUN6QixNQUFNLENBQUMsT0FBTyxHQUFHLFNBQVMsQ0FBQztRQUMzQixNQUFNLENBQUMsVUFBVSxHQUFHLEtBQUssQ0FBQztRQUMxQixNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksS0FBSyxDQUFDLHVDQUF1QyxDQUFDLENBQUMsQ0FBQztLQUNsRTtTQUFNO1FBQ0wsOEJBQThCO1FBQzlCLE1BQU0sUUFBUSxHQUFHLGNBQWMsR0FBRyxHQUFHLENBQUM7UUFDdEMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxRQUFRLEVBQUU7WUFDeEIsY0FBYyxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FBQztRQUMvQixDQUFDLENBQUMsQ0FBQztLQUNKO0FBQ0gsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IG5ldCBmcm9tIFwibmV0XCI7XG5pbXBvcnQgZXZlbnRzIGZyb20gXCJldmVudHNcIjtcbmltcG9ydCB7XG4gIG1ha2VSZXF1ZXN0QnVmZmVyLFxuICBwYXJzZU1lc3NhZ2UsXG4gIG1lcmdlLFxuICB0aW1lc3RhbXAsXG4gIE1lc3NhZ2UsXG59IGZyb20gXCIuL3V0aWxzXCI7XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2VydmVyT3B0aW9ucyB7XG4gIHRpbWVvdXQ6IG51bWJlcjtcbiAga2VlcEFsaXZlOiBib29sZWFuO1xuICBrZWVwQWxpdmVEZWxheTogbnVtYmVyO1xuICBjb25udGltZW91dDogbnVtYmVyO1xuICB1c2VybmFtZT86IHN0cmluZztcbiAgcGFzc3dvcmQ/OiBzdHJpbmc7XG59XG5cbnR5cGUgU2VxID0gbnVtYmVyO1xuXG5leHBvcnQgaW50ZXJmYWNlIE9uQ29ubmVjdENhbGxiYWNrIHtcbiAgKHNvY2tldDogbmV0LlNvY2tldCk6IHZvaWQ7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgT25SZXNwb25zZUNhbGxiYWNrIHtcbiAgKG1lc3NhZ2U6IE1lc3NhZ2UpOiB2b2lkO1xuICBxdWlldD86IGJvb2xlYW47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgT25FcnJvckNhbGxiYWNrIHtcbiAgKGVycm9yOiBFcnJvcik6IHZvaWQ7XG59XG5cbmV4cG9ydCBjbGFzcyBTZXJ2ZXIgZXh0ZW5kcyBldmVudHMuRXZlbnRFbWl0dGVyIHtcbiAgcmVzcG9uc2VCdWZmZXI6IEJ1ZmZlcjtcbiAgaG9zdDogc3RyaW5nO1xuICBwb3J0OiBzdHJpbmcgfCBudW1iZXIgfCB1bmRlZmluZWQ7XG4gIGNvbm5lY3RlZDogYm9vbGVhbjtcbiAgdGltZW91dFNldDogYm9vbGVhbjtcbiAgY29ubmVjdENhbGxiYWNrczogT25Db25uZWN0Q2FsbGJhY2tbXTtcbiAgcmVzcG9uc2VDYWxsYmFja3M6IHsgW3NlcTogc3RyaW5nXTogT25SZXNwb25zZUNhbGxiYWNrIH07XG4gIHJlcXVlc3RUaW1lb3V0czogbnVtYmVyW107XG4gIGVycm9yQ2FsbGJhY2tzOiB7IFtzZXE6IHN0cmluZ106IE9uRXJyb3JDYWxsYmFjayB9O1xuICBvcHRpb25zOiBTZXJ2ZXJPcHRpb25zO1xuICB1c2VybmFtZTogc3RyaW5nIHwgdW5kZWZpbmVkO1xuICBwYXNzd29yZDogc3RyaW5nIHwgdW5kZWZpbmVkO1xuXG4gIF9zb2NrZXQ6IG5ldC5Tb2NrZXQgfCB1bmRlZmluZWQ7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgaG9zdDogc3RyaW5nLFxuICAgIC8qIFRPRE86IGFsbG93aW5nIHBvcnQgdG8gYmUgc3RyaW5nIG9yIHVuZGVmaW5lZCBpcyB1c2VkIGJ5IHRoZSB0ZXN0cywgYnV0IHNlZW1zIGJhZCBvdmVyYWxsLiAqL1xuICAgIHBvcnQ/OiBzdHJpbmcgfCBudW1iZXIsXG4gICAgdXNlcm5hbWU/OiBzdHJpbmcsXG4gICAgcGFzc3dvcmQ/OiBzdHJpbmcsXG4gICAgb3B0aW9ucz86IFBhcnRpYWw8U2VydmVyT3B0aW9ucz5cbiAgKSB7XG4gICAgc3VwZXIoKTtcbiAgICB0aGlzLnJlc3BvbnNlQnVmZmVyID0gQnVmZmVyLmZyb20oW10pO1xuICAgIHRoaXMuaG9zdCA9IGhvc3Q7XG4gICAgdGhpcy5wb3J0ID0gcG9ydDtcbiAgICB0aGlzLmNvbm5lY3RlZCA9IGZhbHNlO1xuICAgIHRoaXMudGltZW91dFNldCA9IGZhbHNlO1xuICAgIHRoaXMuY29ubmVjdENhbGxiYWNrcyA9IFtdO1xuICAgIHRoaXMucmVzcG9uc2VDYWxsYmFja3MgPSB7fTtcbiAgICB0aGlzLnJlcXVlc3RUaW1lb3V0cyA9IFtdO1xuICAgIHRoaXMuZXJyb3JDYWxsYmFja3MgPSB7fTtcbiAgICB0aGlzLm9wdGlvbnMgPSBtZXJnZShvcHRpb25zIHx8IHt9LCB7XG4gICAgICB0aW1lb3V0OiAwLjUsXG4gICAgICBrZWVwQWxpdmU6IGZhbHNlLFxuICAgICAga2VlcEFsaXZlRGVsYXk6IDMwLFxuICAgIH0pIGFzIFNlcnZlck9wdGlvbnM7XG4gICAgaWYgKFxuICAgICAgdGhpcy5vcHRpb25zLmNvbm50aW1lb3V0ID09PSB1bmRlZmluZWQgfHxcbiAgICAgIHRoaXMub3B0aW9ucy5jb25udGltZW91dCA9PT0gbnVsbFxuICAgICkge1xuICAgICAgdGhpcy5vcHRpb25zLmNvbm50aW1lb3V0ID0gMiAqIHRoaXMub3B0aW9ucy50aW1lb3V0O1xuICAgIH1cbiAgICB0aGlzLnVzZXJuYW1lID1cbiAgICAgIHVzZXJuYW1lIHx8XG4gICAgICB0aGlzLm9wdGlvbnMudXNlcm5hbWUgfHxcbiAgICAgIHByb2Nlc3MuZW52Lk1FTUNBQ0hJRVJfVVNFUk5BTUUgfHxcbiAgICAgIHByb2Nlc3MuZW52Lk1FTUNBQ0hFX1VTRVJOQU1FO1xuICAgIHRoaXMucGFzc3dvcmQgPVxuICAgICAgcGFzc3dvcmQgfHxcbiAgICAgIHRoaXMub3B0aW9ucy5wYXNzd29yZCB8fFxuICAgICAgcHJvY2Vzcy5lbnYuTUVNQ0FDSElFUl9QQVNTV09SRCB8fFxuICAgICAgcHJvY2Vzcy5lbnYuTUVNQ0FDSEVfUEFTU1dPUkQ7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICBvbkNvbm5lY3QoZnVuYzogT25Db25uZWN0Q2FsbGJhY2spIHtcbiAgICB0aGlzLmNvbm5lY3RDYWxsYmFja3MucHVzaChmdW5jKTtcbiAgfVxuXG4gIG9uUmVzcG9uc2Uoc2VxOiBTZXEsIGZ1bmM6IE9uUmVzcG9uc2VDYWxsYmFjaykge1xuICAgIHRoaXMucmVzcG9uc2VDYWxsYmFja3Nbc2VxXSA9IGZ1bmM7XG4gIH1cblxuICByZXNwb25kKHJlc3BvbnNlOiBNZXNzYWdlKSB7XG4gICAgY29uc3QgY2FsbGJhY2sgPSB0aGlzLnJlc3BvbnNlQ2FsbGJhY2tzW3Jlc3BvbnNlLmhlYWRlci5vcGFxdWVdO1xuICAgIGlmICghY2FsbGJhY2spIHtcbiAgICAgIC8vIGluIGNhc2Ugb2YgYXV0aGVudGljYXRpb24sIG5vIGNhbGxiYWNrIGlzIHJlZ2lzdGVyZWRcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY2FsbGJhY2socmVzcG9uc2UpO1xuICAgIGlmICghY2FsbGJhY2sucXVpZXQgfHwgcmVzcG9uc2UuaGVhZGVyLnRvdGFsQm9keUxlbmd0aCA9PT0gMCkge1xuICAgICAgZGVsZXRlIHRoaXMucmVzcG9uc2VDYWxsYmFja3NbcmVzcG9uc2UuaGVhZGVyLm9wYXF1ZV07XG4gICAgICB0aGlzLnJlcXVlc3RUaW1lb3V0cy5zaGlmdCgpO1xuICAgICAgZGVsZXRlIHRoaXMuZXJyb3JDYWxsYmFja3NbcmVzcG9uc2UuaGVhZGVyLm9wYXF1ZV07XG4gICAgfVxuICB9XG5cbiAgb25FcnJvcihzZXE6IFNlcSwgZnVuYzogT25FcnJvckNhbGxiYWNrKSB7XG4gICAgdGhpcy5lcnJvckNhbGxiYWNrc1tzZXFdID0gZnVuYztcbiAgfVxuXG4gIGVycm9yKGVycjogRXJyb3IpIHtcbiAgICBjb25zdCBlcnJjYWxscyA9IHRoaXMuZXJyb3JDYWxsYmFja3M7XG4gICAgdGhpcy5jb25uZWN0Q2FsbGJhY2tzID0gW107XG4gICAgdGhpcy5yZXNwb25zZUNhbGxiYWNrcyA9IHt9O1xuICAgIHRoaXMucmVxdWVzdFRpbWVvdXRzID0gW107XG4gICAgdGhpcy5lcnJvckNhbGxiYWNrcyA9IHt9O1xuICAgIHRoaXMudGltZW91dFNldCA9IGZhbHNlO1xuICAgIGlmICh0aGlzLl9zb2NrZXQpIHtcbiAgICAgIHRoaXMuX3NvY2tldC5kZXN0cm95KCk7XG4gICAgICBkZWxldGUgdGhpcy5fc29ja2V0O1xuICAgIH1cbiAgICBmb3IgKGxldCBlcnJjYWxsIG9mIE9iamVjdC52YWx1ZXMoZXJyY2FsbHMpKSB7XG4gICAgICBlcnJjYWxsKGVycik7XG4gICAgfVxuICB9XG5cbiAgbGlzdFNhc2woKSB7XG4gICAgY29uc3QgYnVmID0gbWFrZVJlcXVlc3RCdWZmZXIoMHgyMCwgXCJcIiwgXCJcIiwgXCJcIik7XG4gICAgdGhpcy53cml0ZVNBU0woYnVmKTtcbiAgfVxuXG4gIHNhc2xBdXRoKCkge1xuICAgIGNvbnN0IGF1dGhTdHIgPSBcIlxceDAwXCIgKyB0aGlzLnVzZXJuYW1lICsgXCJcXHgwMFwiICsgdGhpcy5wYXNzd29yZDtcbiAgICBjb25zdCBidWYgPSBtYWtlUmVxdWVzdEJ1ZmZlcigweDIxLCBcIlBMQUlOXCIsIFwiXCIsIGF1dGhTdHIpO1xuICAgIHRoaXMud3JpdGVTQVNMKGJ1Zik7XG4gIH1cblxuICBhcHBlbmRUb0J1ZmZlcihkYXRhQnVmOiBCdWZmZXIpIHtcbiAgICBjb25zdCBvbGQgPSB0aGlzLnJlc3BvbnNlQnVmZmVyO1xuICAgIHRoaXMucmVzcG9uc2VCdWZmZXIgPSBCdWZmZXIuYWxsb2Mob2xkLmxlbmd0aCArIGRhdGFCdWYubGVuZ3RoKTtcbiAgICBvbGQuY29weSh0aGlzLnJlc3BvbnNlQnVmZmVyLCAwKTtcbiAgICBkYXRhQnVmLmNvcHkodGhpcy5yZXNwb25zZUJ1ZmZlciwgb2xkLmxlbmd0aCk7XG4gICAgcmV0dXJuIHRoaXMucmVzcG9uc2VCdWZmZXI7XG4gIH1cbiAgcmVzcG9uc2VIYW5kbGVyKGRhdGFCdWY6IEJ1ZmZlcikge1xuICAgIGxldCByZXNwb25zZSA9IHBhcnNlTWVzc2FnZSh0aGlzLmFwcGVuZFRvQnVmZmVyKGRhdGFCdWYpKTtcbiAgICBsZXQgcmVzcExlbmd0aDogbnVtYmVyO1xuICAgIHdoaWxlIChyZXNwb25zZSkge1xuICAgICAgaWYgKHJlc3BvbnNlLmhlYWRlci5vcGNvZGUgPT09IDB4MjApIHtcbiAgICAgICAgdGhpcy5zYXNsQXV0aCgpO1xuICAgICAgfSBlbHNlIGlmIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzID09PSAoMHgyMCBhcyBhbnkpIC8qIFRPRE86IHd0Zj8gKi8pIHtcbiAgICAgICAgdGhpcy5lcnJvcihuZXcgRXJyb3IoXCJNZW1jYWNoZWQgc2VydmVyIGF1dGhlbnRpY2F0aW9uIGZhaWxlZCFcIikpO1xuICAgICAgfSBlbHNlIGlmIChyZXNwb25zZS5oZWFkZXIub3Bjb2RlID09PSAweDIxKSB7XG4gICAgICAgIHRoaXMuZW1pdChcImF1dGhlbnRpY2F0ZWRcIik7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLnJlc3BvbmQocmVzcG9uc2UpO1xuICAgICAgfVxuICAgICAgcmVzcExlbmd0aCA9IHJlc3BvbnNlLmhlYWRlci50b3RhbEJvZHlMZW5ndGggKyAyNDtcbiAgICAgIHRoaXMucmVzcG9uc2VCdWZmZXIgPSB0aGlzLnJlc3BvbnNlQnVmZmVyLnNsaWNlKHJlc3BMZW5ndGgpO1xuICAgICAgcmVzcG9uc2UgPSBwYXJzZU1lc3NhZ2UodGhpcy5yZXNwb25zZUJ1ZmZlcik7XG4gICAgfVxuICB9XG4gIHNvY2soc2FzbDogYm9vbGVhbiwgZ286IE9uQ29ubmVjdENhbGxiYWNrKSB7XG4gICAgY29uc3Qgc2VsZiA9IHRoaXM7XG5cbiAgICBpZiAoIXNlbGYuX3NvY2tldCkge1xuICAgICAgLy8gQ0FTRSAxOiBjb21wbGV0ZWx5IG5ldyBzb2NrZXRcbiAgICAgIHNlbGYuY29ubmVjdGVkID0gZmFsc2U7XG4gICAgICBzZWxmLl9zb2NrZXQgPSBuZXQuY29ubmVjdChcbiAgICAgICAgLyogVE9ETzogYWxsb3dpbmcgcG9ydCB0byBiZSBzdHJpbmcgb3IgdW5kZWZpbmVkIGlzIHVzZWQgYnkgdGhlIHRlc3RzLCBidXQgc2VlbXMgYmFkIG92ZXJhbGwuICovXG4gICAgICAgIHR5cGVvZiB0aGlzLnBvcnQgPT09IFwic3RyaW5nXCJcbiAgICAgICAgICA/IHBhcnNlSW50KHRoaXMucG9ydCwgMTApXG4gICAgICAgICAgOiB0aGlzLnBvcnQgfHwgMTEyMTEsXG4gICAgICAgIHRoaXMuaG9zdCxcbiAgICAgICAgZnVuY3Rpb24gKHRoaXM6IG5ldC5Tb2NrZXQpIHtcbiAgICAgICAgICAvLyBTQVNMIGF1dGhlbnRpY2F0aW9uIGhhbmRsZXJcbiAgICAgICAgICBzZWxmLm9uY2UoXCJhdXRoZW50aWNhdGVkXCIsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmIChzZWxmLl9zb2NrZXQpIHtcbiAgICAgICAgICAgICAgY29uc3Qgc29ja2V0ID0gc2VsZi5fc29ja2V0O1xuICAgICAgICAgICAgICBzZWxmLmNvbm5lY3RlZCA9IHRydWU7XG4gICAgICAgICAgICAgIC8vIGNhbmNlbCBjb25uZWN0aW9uIHRpbWVvdXRcbiAgICAgICAgICAgICAgc2VsZi5fc29ja2V0LnNldFRpbWVvdXQoMCk7XG4gICAgICAgICAgICAgIHNlbGYudGltZW91dFNldCA9IGZhbHNlO1xuICAgICAgICAgICAgICAvLyBydW4gYWN0dWFsIHJlcXVlc3QocylcbiAgICAgICAgICAgICAgZ28oc2VsZi5fc29ja2V0KTtcbiAgICAgICAgICAgICAgc2VsZi5jb25uZWN0Q2FsbGJhY2tzLmZvckVhY2goZnVuY3Rpb24gKGNiKSB7XG4gICAgICAgICAgICAgICAgY2Ioc29ja2V0KTtcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIHNlbGYuY29ubmVjdENhbGxiYWNrcyA9IFtdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgLy8gc2V0dXAgcmVzcG9uc2UgaGFuZGxlclxuICAgICAgICAgIHRoaXMub24oXCJkYXRhXCIsIGZ1bmN0aW9uIChkYXRhQnVmKSB7XG4gICAgICAgICAgICBzZWxmLnJlc3BvbnNlSGFuZGxlcihkYXRhQnVmKTtcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIC8vIGtpY2sgb2YgU0FTTCBpZiBuZWVkZWRcbiAgICAgICAgICBpZiAoc2VsZi51c2VybmFtZSAmJiBzZWxmLnBhc3N3b3JkKSB7XG4gICAgICAgICAgICBzZWxmLmxpc3RTYXNsKCk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHNlbGYuZW1pdChcImF1dGhlbnRpY2F0ZWRcIik7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICApO1xuXG4gICAgICAvLyBzZXR1cCBlcnJvciBoYW5kbGVyXG4gICAgICBzZWxmLl9zb2NrZXQub24oXCJlcnJvclwiLCBmdW5jdGlvbiAoZXJyb3IpIHtcbiAgICAgICAgc2VsZi5jb25uZWN0ZWQgPSBmYWxzZTtcbiAgICAgICAgaWYgKHNlbGYudGltZW91dFNldCkge1xuICAgICAgICAgIGlmIChzZWxmLl9zb2NrZXQpIHtcbiAgICAgICAgICAgIHNlbGYuX3NvY2tldC5zZXRUaW1lb3V0KDApO1xuICAgICAgICAgIH1cbiAgICAgICAgICBzZWxmLnRpbWVvdXRTZXQgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBzZWxmLl9zb2NrZXQgPSB1bmRlZmluZWQ7XG4gICAgICAgIHNlbGYuZXJyb3IoZXJyb3IpO1xuICAgICAgfSk7XG5cbiAgICAgIC8vIHNldHVwIGNvbm5lY3Rpb24gdGltZW91dCBoYW5kbGVyXG4gICAgICBzZWxmLnRpbWVvdXRTZXQgPSB0cnVlO1xuICAgICAgc2VsZi5fc29ja2V0LnNldFRpbWVvdXQoXG4gICAgICAgIHNlbGYub3B0aW9ucy5jb25udGltZW91dCAqIDEwMDAsXG4gICAgICAgIGZ1bmN0aW9uICh0aGlzOiBuZXQuU29ja2V0KSB7XG4gICAgICAgICAgc2VsZi50aW1lb3V0U2V0ID0gZmFsc2U7XG4gICAgICAgICAgaWYgKCFzZWxmLmNvbm5lY3RlZCkge1xuICAgICAgICAgICAgdGhpcy5lbmQoKTtcbiAgICAgICAgICAgIHNlbGYuX3NvY2tldCA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIHNlbGYuZXJyb3IobmV3IEVycm9yKFwic29ja2V0IHRpbWVkIG91dCBjb25uZWN0aW5nIHRvIHNlcnZlci5cIikpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgKTtcblxuICAgICAgLy8gdXNlIFRDUCBrZWVwLWFsaXZlXG4gICAgICBzZWxmLl9zb2NrZXQuc2V0S2VlcEFsaXZlKFxuICAgICAgICBzZWxmLm9wdGlvbnMua2VlcEFsaXZlLFxuICAgICAgICBzZWxmLm9wdGlvbnMua2VlcEFsaXZlRGVsYXkgKiAxMDAwXG4gICAgICApO1xuICAgIH0gZWxzZSBpZiAoIXNlbGYuY29ubmVjdGVkICYmICFzYXNsKSB7XG4gICAgICAvLyBDQVNFIDI6IHNvY2tldCBleGlzdHMsIGJ1dCBzdGlsbCBjb25uZWN0aW5nIC8gYXV0aGVudGljYXRpbmdcbiAgICAgIHNlbGYub25Db25uZWN0KGdvKTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gQ0FTRSAzOiBzb2NrZXQgZXhpc3RzIGFuZCBjb25uZWN0ZWQgLyByZWFkeSB0byB1c2VcbiAgICAgIGdvKHNlbGYuX3NvY2tldCk7XG4gICAgfVxuICB9XG5cbiAgd3JpdGUoYmxvYjogQnVmZmVyKSB7XG4gICAgY29uc3Qgc2VsZiA9IHRoaXM7XG4gICAgY29uc3QgZGVhZGxpbmUgPSBNYXRoLnJvdW5kKHNlbGYub3B0aW9ucy50aW1lb3V0ICogMTAwMCk7XG4gICAgdGhpcy5zb2NrKGZhbHNlLCBmdW5jdGlvbiAocykge1xuICAgICAgcy53cml0ZShibG9iKTtcbiAgICAgIHNlbGYucmVxdWVzdFRpbWVvdXRzLnB1c2godGltZXN0YW1wKCkgKyBkZWFkbGluZSk7XG4gICAgICBpZiAoIXNlbGYudGltZW91dFNldCkge1xuICAgICAgICBzZWxmLnRpbWVvdXRTZXQgPSB0cnVlO1xuICAgICAgICBzLnNldFRpbWVvdXQoZGVhZGxpbmUsIGZ1bmN0aW9uICh0aGlzOiBuZXQuU29ja2V0KSB7XG4gICAgICAgICAgdGltZW91dEhhbmRsZXIoc2VsZiwgdGhpcyk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgd3JpdGVTQVNMKGJsb2I6IEJ1ZmZlcikge1xuICAgIHRoaXMuc29jayh0cnVlLCBmdW5jdGlvbiAocykge1xuICAgICAgcy53cml0ZShibG9iKTtcbiAgICB9KTtcbiAgfVxuXG4gIGNsb3NlKCkge1xuICAgIGlmICh0aGlzLl9zb2NrZXQpIHtcbiAgICAgIHRoaXMuX3NvY2tldC5lbmQoKTtcbiAgICB9XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICByZXR1cm4gXCI8U2VydmVyIFwiICsgdGhpcy5ob3N0ICsgXCI6XCIgKyB0aGlzLnBvcnQgKyBcIj5cIjtcbiAgfVxuXG4gIGhvc3Rwb3J0U3RyaW5nKCkge1xuICAgIHJldHVybiB0aGlzLmhvc3QgKyBcIjpcIiArIHRoaXMucG9ydDtcbiAgfVxufVxuXG4vLyBXZSBoYW5kbGUgdHJhY2tpbmcgdGltZW91dHMgd2l0aCBhbiBhcnJheSBvZiBkZWFkbGluZXMgKHJlcXVlc3RUaW1lb3V0cyksIGFzXG4vLyBub2RlIGRvZXNuJ3QgbGlrZSB1cyBzZXR0aW5nIHVwIGxvdHMgb2YgdGltZXJzLCBhbmQgdXNpbmcganVzdCBvbmUgaXMgbW9yZVxuLy8gZWZmaWNpZW50IGFueXdheS5cbmNvbnN0IHRpbWVvdXRIYW5kbGVyID0gZnVuY3Rpb24gKHNlcnZlcjogU2VydmVyLCBzb2NrOiBuZXQuU29ja2V0KSB7XG4gIGlmIChzZXJ2ZXIucmVxdWVzdFRpbWVvdXRzLmxlbmd0aCA9PT0gMCkge1xuICAgIC8vIG5vdGhpbmcgYWN0aXZlXG4gICAgc2VydmVyLnRpbWVvdXRTZXQgPSBmYWxzZTtcbiAgICByZXR1cm47XG4gIH1cblxuICAvLyBzb21lIHJlcXVlc3RzIG91dHN0YW5kaW5nLCBjaGVjayBpZiBhbnkgaGF2ZSB0aW1lZC1vdXRcbiAgY29uc3Qgbm93ID0gdGltZXN0YW1wKCk7XG4gIGNvbnN0IHNvb25lc3RUaW1lb3V0ID0gc2VydmVyLnJlcXVlc3RUaW1lb3V0c1swXTtcblxuICBpZiAoc29vbmVzdFRpbWVvdXQgPD0gbm93KSB7XG4gICAgLy8gdGltZW91dCBvY2N1cnJlZCFcbiAgICBzb2NrLmVuZCgpO1xuICAgIHNlcnZlci5jb25uZWN0ZWQgPSBmYWxzZTtcbiAgICBzZXJ2ZXIuX3NvY2tldCA9IHVuZGVmaW5lZDtcbiAgICBzZXJ2ZXIudGltZW91dFNldCA9IGZhbHNlO1xuICAgIHNlcnZlci5lcnJvcihuZXcgRXJyb3IoXCJzb2NrZXQgdGltZWQgb3V0IHdhaXRpbmcgb24gcmVzcG9uc2UuXCIpKTtcbiAgfSBlbHNlIHtcbiAgICAvLyBubyB0aW1lb3V0ISBTZXR1cCBuZXh0IG9uZS5cbiAgICBjb25zdCBkZWFkbGluZSA9IHNvb25lc3RUaW1lb3V0IC0gbm93O1xuICAgIHNvY2suc2V0VGltZW91dChkZWFkbGluZSwgZnVuY3Rpb24gKCkge1xuICAgICAgdGltZW91dEhhbmRsZXIoc2VydmVyLCBzb2NrKTtcbiAgICB9KTtcbiAgfVxufTtcbiJdfQ== \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL21lbWpzL3NlcnZlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSw4Q0FBc0I7QUFDdEIsb0RBQTRCO0FBQzVCLG1DQU1pQjtBQTBCakIsTUFBYSxNQUFPLFNBQVEsZ0JBQU0sQ0FBQyxZQUFZO0lBZ0I3QyxZQUNFLElBQVk7SUFDWixnR0FBZ0c7SUFDaEcsSUFBc0IsRUFDdEIsUUFBaUIsRUFDakIsUUFBaUIsRUFDakIsT0FBZ0M7UUFFaEMsS0FBSyxFQUFFLENBQUM7UUFDUixJQUFJLENBQUMsY0FBYyxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDdEMsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUM7UUFDakIsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUM7UUFDakIsSUFBSSxDQUFDLFNBQVMsR0FBRyxLQUFLLENBQUM7UUFDdkIsSUFBSSxDQUFDLFVBQVUsR0FBRyxLQUFLLENBQUM7UUFDeEIsSUFBSSxDQUFDLGdCQUFnQixHQUFHLEVBQUUsQ0FBQztRQUMzQixJQUFJLENBQUMsaUJBQWlCLEdBQUcsRUFBRSxDQUFDO1FBQzVCLElBQUksQ0FBQyxlQUFlLEdBQUcsRUFBRSxDQUFDO1FBQzFCLElBQUksQ0FBQyxjQUFjLEdBQUcsRUFBRSxDQUFDO1FBQ3pCLElBQUksQ0FBQyxPQUFPLEdBQUcsYUFBSyxDQUFDLE9BQU8sSUFBSSxFQUFFLEVBQUU7WUFDbEMsT0FBTyxFQUFFLEdBQUc7WUFDWixTQUFTLEVBQUUsS0FBSztZQUNoQixjQUFjLEVBQUUsRUFBRTtTQUNuQixDQUFrQixDQUFDO1FBQ3BCLElBQ0UsSUFBSSxDQUFDLE9BQU8sQ0FBQyxXQUFXLEtBQUssU0FBUztZQUN0QyxJQUFJLENBQUMsT0FBTyxDQUFDLFdBQVcsS0FBSyxJQUFJLEVBQ2pDO1lBQ0EsSUFBSSxDQUFDLE9BQU8sQ0FBQyxXQUFX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QUFNLEdBQUcsR0FBRyxpQkFBUyxFQUFFLENBQUM7SUFDeEIsTUFBTSxjQUFjLEdBQUcsTUFBTSxDQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUVqRCxJQUFJLGNBQWMsSUFBSSxHQUFHLEVBQUU7UUFDekIsb0JBQW9CO1FBQ3BCLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztRQUNYLE1BQU0sQ0FBQyxTQUFTLEdBQUcsS0FBSyxDQUFDO1FBQ3pCLE1BQU0sQ0FBQyxPQUFPLEdBQUcsU0FBUyxDQUFDO1FBQzNCLE1BQU0sQ0FBQyxVQUFVLEdBQUcsS0FBSyxDQUFDO1FBQzFCLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxLQUFLLENBQUMsdUNBQXVDLENBQUMsQ0FBQyxDQUFDO0tBQ2xFO1NBQU07UUFDTCw4QkFBOEI7UUFDOUIsTUFBTSxRQUFRLEdBQUcsY0FBYyxHQUFHLEdBQUcsQ0FBQztRQUN0QyxJQUFJLENBQUMsVUFBVSxDQUFDLFFBQVEsRUFBRTtZQUN4QixjQUFjLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQy9CLENBQUMsQ0FBQyxDQUFDO0tBQ0o7QUFDSCxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgbmV0IGZyb20gXCJuZXRcIjtcbmltcG9ydCBldmVudHMgZnJvbSBcImV2ZW50c1wiO1xuaW1wb3J0IHtcbiAgbWFrZVJlcXVlc3RCdWZmZXIsXG4gIHBhcnNlTWVzc2FnZSxcbiAgbWVyZ2UsXG4gIHRpbWVzdGFtcCxcbiAgTWVzc2FnZSxcbn0gZnJvbSBcIi4vdXRpbHNcIjtcblxuZXhwb3J0IGludGVyZmFjZSBTZXJ2ZXJPcHRpb25zIHtcbiAgdGltZW91dDogbnVtYmVyO1xuICBrZWVwQWxpdmU6IGJvb2xlYW47XG4gIGtlZXBBbGl2ZURlbGF5OiBudW1iZXI7XG4gIGNvbm50aW1lb3V0OiBudW1iZXI7XG4gIHVzZXJuYW1lPzogc3RyaW5nO1xuICBwYXNzd29yZD86IHN0cmluZztcbn1cblxudHlwZSBTZXEgPSBudW1iZXI7XG5cbmV4cG9ydCBpbnRlcmZhY2UgT25Db25uZWN0Q2FsbGJhY2sge1xuICAoc29ja2V0OiBuZXQuU29ja2V0KTogdm9pZDtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBPblJlc3BvbnNlQ2FsbGJhY2sge1xuICAobWVzc2FnZTogTWVzc2FnZSk6IHZvaWQ7XG4gIHF1aWV0PzogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBPbkVycm9yQ2FsbGJhY2sge1xuICAoZXJyb3I6IEVycm9yKTogdm9pZDtcbn1cblxuZXhwb3J0IGNsYXNzIFNlcnZlciBleHRlbmRzIGV2ZW50cy5FdmVudEVtaXR0ZXIge1xuICByZXNwb25zZUJ1ZmZlcjogQnVmZmVyO1xuICBob3N0OiBzdHJpbmc7XG4gIHBvcnQ6IHN0cmluZyB8IG51bWJlciB8IHVuZGVmaW5lZDtcbiAgY29ubmVjdGVkOiBib29sZWFuO1xuICB0aW1lb3V0U2V0OiBib29sZWFuO1xuICBjb25uZWN0Q2FsbGJhY2tzOiBPbkNvbm5lY3RDYWxsYmFja1tdO1xuICByZXNwb25zZUNhbGxiYWNrczogeyBbc2VxOiBzdHJpbmddOiBPblJlc3BvbnNlQ2FsbGJhY2sgfTtcbiAgcmVxdWVzdFRpbWVvdXRzOiBudW1iZXJbXTtcbiAgZXJyb3JDYWxsYmFja3M6IHsgW3NlcTogc3RyaW5nXTogT25FcnJvckNhbGxiYWNrIH07XG4gIG9wdGlvbnM6IFNlcnZlck9wdGlvbnM7XG4gIHVzZXJuYW1lOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gIHBhc3N3b3JkOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG5cbiAgX3NvY2tldDogbmV0LlNvY2tldCB8IHVuZGVmaW5lZDtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBob3N0OiBzdHJpbmcsXG4gICAgLyogVE9ETzogYWxsb3dpbmcgcG9ydCB0byBiZSBzdHJpbmcgb3IgdW5kZWZpbmVkIGlzIHVzZWQgYnkgdGhlIHRlc3RzLCBidXQgc2VlbXMgYmFkIG92ZXJhbGwuICovXG4gICAgcG9ydD86IHN0cmluZyB8IG51bWJlcixcbiAgICB1c2VybmFtZT86IHN0cmluZyxcbiAgICBwYXNzd29yZD86IHN0cmluZyxcbiAgICBvcHRpb25zPzogUGFydGlhbDxTZXJ2ZXJPcHRpb25zPlxuICApIHtcbiAgICBzdXBlcigpO1xuICAgIHRoaXMucmVzcG9uc2VCdWZmZXIgPSBCdWZmZXIuZnJvbShbXSk7XG4gICAgdGhpcy5ob3N0ID0gaG9zdDtcbiAgICB0aGlzLnBvcnQgPSBwb3J0O1xuICAgIHRoaXMuY29ubmVjdGVkID0gZmFsc2U7XG4gICAgdGhpcy50aW1lb3V0U2V0ID0gZmFsc2U7XG4gICAgdGhpcy5jb25uZWN0Q2FsbGJhY2tzID0gW107XG4gICAgdGhpcy5yZXNwb25zZUNhbGxiYWNrcyA9IHt9O1xuICAgIHRoaXMucmVxdWVzdFRpbWVvdXRzID0gW107XG4gICAgdGhpcy5lcnJvckNhbGxiYWNrcyA9IHt9O1xuICAgIHRoaXMub3B0aW9ucyA9IG1lcmdlKG9wdGlvbnMgfHwge30sIHtcbiAgICAgIHRpbWVvdXQ6IDAuNSxcbiAgICAgIGtlZXBBbGl2ZTogZmFsc2UsXG4gICAgICBrZWVwQWxpdmVEZWxheTogMzAsXG4gICAgfSkgYXMgU2VydmVyT3B0aW9ucztcbiAgICBpZiAoXG4gICAgICB0aGlzLm9wdGlvbnMuY29ubnRpbWVvdXQgPT09IHVuZGVmaW5lZCB8fFxuICAgICAgdGhpcy5vcHRpb25zLmNvbm50aW1lb3V0ID09PSBudWxsXG4gICAgKSB7XG4gICAgICB0aGlzLm9wdGlvbnMuY29ubnRpbWVvdXQgPSAyICogdGhpcy5vcHRpb25zLnRpbWVvdXQ7XG4gICAgfVxuICAgIHRoaXMudXNlcm5hbWUgPVxuICAgICAgdXNlcm5hbWUgfHxcbiAgICAgIHRoaXMub3B0aW9ucy51c2VybmFtZSB8fFxuICAgICAgcHJvY2Vzcy5lbnYuTUVNQ0FDSElFUl9VU0VSTkFNRSB8fFxuICAgICAgcHJvY2Vzcy5lbnYuTUVNQ0FDSEVfVVNFUk5BTUU7XG4gICAgdGhpcy5wYXNzd29yZCA9XG4gICAgICBwYXNzd29yZCB8fFxuICAgICAgdGhpcy5vcHRpb25zLnBhc3N3b3JkIHx8XG4gICAgICBwcm9jZXNzLmVudi5NRU1DQUNISUVSX1BBU1NXT1JEIHx8XG4gICAgICBwcm9jZXNzLmVudi5NRU1DQUNIRV9QQVNTV09SRDtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIG9uQ29ubmVjdChmdW5jOiBPbkNvbm5lY3RDYWxsYmFjaykge1xuICAgIHRoaXMuY29ubmVjdENhbGxiYWNrcy5wdXNoKGZ1bmMpO1xuICB9XG5cbiAgb25SZXNwb25zZShzZXE6IFNlcSwgZnVuYzogT25SZXNwb25zZUNhbGxiYWNrKSB7XG4gICAgdGhpcy5yZXNwb25zZUNhbGxiYWNrc1tzZXFdID0gZnVuYztcbiAgfVxuXG4gIHJlc3BvbmQocmVzcG9uc2U6IE1lc3NhZ2UpIHtcbiAgICBjb25zdCBjYWxsYmFjayA9IHRoaXMucmVzcG9uc2VDYWxsYmFja3NbcmVzcG9uc2UuaGVhZGVyLm9wYXF1ZV07XG4gICAgaWYgKCFjYWxsYmFjaykge1xuICAgICAgLy8gaW4gY2FzZSBvZiBhdXRoZW50aWNhdGlvbiwgbm8gY2FsbGJhY2sgaXMgcmVnaXN0ZXJlZFxuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjYWxsYmFjayhyZXNwb25zZSk7XG4gICAgaWYgKCFjYWxsYmFjay5xdWlldCB8fCByZXNwb25zZS5oZWFkZXIudG90YWxCb2R5TGVuZ3RoID09PSAwKSB7XG4gICAgICBkZWxldGUgdGhpcy5yZXNwb25zZUNhbGxiYWNrc1tyZXNwb25zZS5oZWFkZXIub3BhcXVlXTtcbiAgICAgIHRoaXMucmVxdWVzdFRpbWVvdXRzLnNoaWZ0KCk7XG4gICAgICBkZWxldGUgdGhpcy5lcnJvckNhbGxiYWNrc1tyZXNwb25zZS5oZWFkZXIub3BhcXVlXTtcbiAgICB9XG4gIH1cblxuICBvbkVycm9yKHNlcTogU2VxLCBmdW5jOiBPbkVycm9yQ2FsbGJhY2spIHtcbiAgICB0aGlzLmVycm9yQ2FsbGJhY2tzW3NlcV0gPSBmdW5jO1xuICB9XG5cbiAgZXJyb3IoZXJyOiBFcnJvcikge1xuICAgIGNvbnN0IGVycmNhbGxzID0gdGhpcy5lcnJvckNhbGxiYWNrcztcbiAgICB0aGlzLmNvbm5lY3RDYWxsYmFja3MgPSBbXTtcbiAgICB0aGlzLnJlc3BvbnNlQ2FsbGJhY2tzID0ge307XG4gICAgdGhpcy5yZXF1ZXN0VGltZW91dHMgPSBbXTtcbiAgICB0aGlzLmVycm9yQ2FsbGJhY2tzID0ge307XG4gICAgdGhpcy50aW1lb3V0U2V0ID0gZmFsc2U7XG4gICAgaWYgKHRoaXMuX3NvY2tldCkge1xuICAgICAgdGhpcy5fc29ja2V0LmRlc3Ryb3koKTtcbiAgICAgIGRlbGV0ZSB0aGlzLl9zb2NrZXQ7XG4gICAgfVxuICAgIGZvciAobGV0IGVycmNhbGwgb2YgT2JqZWN0LnZhbHVlcyhlcnJjYWxscykpIHtcbiAgICAgIGVycmNhbGwoZXJyKTtcbiAgICB9XG4gIH1cblxuICBsaXN0U2FzbCgpIHtcbiAgICBjb25zdCBidWYgPSBtYWtlUmVxdWVzdEJ1ZmZlcigweDIwLCBcIlwiLCBcIlwiLCBcIlwiKTtcbiAgICB0aGlzLndyaXRlU0FTTChidWYpO1xuICB9XG5cbiAgc2FzbEF1dGgoKSB7XG4gICAgY29uc3QgYXV0aFN0ciA9IFwiXFx4MDBcIiArIHRoaXMudXNlcm5hbWUgKyBcIlxceDAwXCIgKyB0aGlzLnBhc3N3b3JkO1xuICAgIGNvbnN0IGJ1ZiA9IG1ha2VSZXF1ZXN0QnVmZmVyKDB4MjEsIFwiUExBSU5cIiwgXCJcIiwgYXV0aFN0cik7XG4gICAgdGhpcy53cml0ZVNBU0woYnVmKTtcbiAgfVxuXG4gIGFwcGVuZFRvQnVmZmVyKGRhdGFCdWY6IEJ1ZmZlcikge1xuICAgIGNvbnN0IG9sZCA9IHRoaXMucmVzcG9uc2VCdWZmZXI7XG4gICAgdGhpcy5yZXNwb25zZUJ1ZmZlciA9IEJ1ZmZlci5hbGxvYyhvbGQubGVuZ3RoICsgZGF0YUJ1Zi5sZW5ndGgpO1xuICAgIG9sZC5jb3B5KHRoaXMucmVzcG9uc2VCdWZmZXIsIDApO1xuICAgIGRhdGFCdWYuY29weSh0aGlzLnJlc3BvbnNlQnVmZmVyLCBvbGQubGVuZ3RoKTtcbiAgICByZXR1cm4gdGhpcy5yZXNwb25zZUJ1ZmZlcjtcbiAgfVxuICByZXNwb25zZUhhbmRsZXIoZGF0YUJ1ZjogQnVmZmVyKSB7XG4gICAgbGV0IHJlc3BvbnNlID0gcGFyc2VNZXNzYWdlKHRoaXMuYXBwZW5kVG9CdWZmZXIoZGF0YUJ1ZikpO1xuICAgIGxldCByZXNwTGVuZ3RoOiBudW1iZXI7XG4gICAgd2hpbGUgKHJlc3BvbnNlKSB7XG4gICAgICBpZiAocmVzcG9uc2UuaGVhZGVyLm9wY29kZSA9PT0gMHgyMCkge1xuICAgICAgICB0aGlzLnNhc2xBdXRoKCk7XG4gICAgICB9IGVsc2UgaWYgKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMgPT09ICgweDIwIGFzIGFueSkgLyogVE9ETzogd3RmPyAqLykge1xuICAgICAgICB0aGlzLmVycm9yKG5ldyBFcnJvcihcIk1lbWNhY2hlZCBzZXJ2ZXIgYXV0aGVudGljYXRpb24gZmFpbGVkIVwiKSk7XG4gICAgICB9IGVsc2UgaWYgKHJlc3BvbnNlLmhlYWRlci5vcGNvZGUgPT09IDB4MjEpIHtcbiAgICAgICAgdGhpcy5lbWl0KFwiYXV0aGVudGljYXRlZFwiKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMucmVzcG9uZChyZXNwb25zZSk7XG4gICAgICB9XG4gICAgICByZXNwTGVuZ3RoID0gcmVzcG9uc2UuaGVhZGVyLnRvdGFsQm9keUxlbmd0aCArIDI0O1xuICAgICAgdGhpcy5yZXNwb25zZUJ1ZmZlciA9IHRoaXMucmVzcG9uc2VCdWZmZXIuc2xpY2UocmVzcExlbmd0aCk7XG4gICAgICByZXNwb25zZSA9IHBhcnNlTWVzc2FnZSh0aGlzLnJlc3BvbnNlQnVmZmVyKTtcbiAgICB9XG4gIH1cbiAgc29jayhzYXNsOiBib29sZWFuLCBnbzogT25Db25uZWN0Q2FsbGJhY2spIHtcbiAgICBjb25zdCBzZWxmID0gdGhpcztcblxuICAgIGlmICghc2VsZi5fc29ja2V0KSB7XG4gICAgICAvLyBDQVNFIDE6IGNvbXBsZXRlbHkgbmV3IHNvY2tldFxuICAgICAgc2VsZi5jb25uZWN0ZWQgPSBmYWxzZTtcbiAgICAgIHNlbGYuX3NvY2tldCA9IG5ldC5jb25uZWN0KFxuICAgICAgICAvKiBUT0RPOiBhbGxvd2luZyBwb3J0IHRvIGJlIHN0cmluZyBvciB1bmRlZmluZWQgaXMgdXNlZCBieSB0aGUgdGVzdHMsIGJ1dCBzZWVtcyBiYWQgb3ZlcmFsbC4gKi9cbiAgICAgICAgdHlwZW9mIHRoaXMucG9ydCA9PT0gXCJzdHJpbmdcIlxuICAgICAgICAgID8gcGFyc2VJbnQodGhpcy5wb3J0LCAxMClcbiAgICAgICAgICA6IHRoaXMucG9ydCB8fCAxMTIxMSxcbiAgICAgICAgdGhpcy5ob3N0LFxuICAgICAgICBmdW5jdGlvbiAodGhpczogbmV0LlNvY2tldCkge1xuICAgICAgICAgIC8vIFNBU0wgYXV0aGVudGljYXRpb24gaGFuZGxlclxuICAgICAgICAgIHNlbGYub25jZShcImF1dGhlbnRpY2F0ZWRcIiwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKHNlbGYuX3NvY2tldCkge1xuICAgICAgICAgICAgICBjb25zdCBzb2NrZXQgPSBzZWxmLl9zb2NrZXQ7XG4gICAgICAgICAgICAgIHNlbGYuY29ubmVjdGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgLy8gY2FuY2VsIGNvbm5lY3Rpb24gdGltZW91dFxuICAgICAgICAgICAgICBzZWxmLl9zb2NrZXQuc2V0VGltZW91dCgwKTtcbiAgICAgICAgICAgICAgc2VsZi50aW1lb3V0U2V0ID0gZmFsc2U7XG4gICAgICAgICAgICAgIC8vIHJ1biBhY3R1YWwgcmVxdWVzdChzKVxuICAgICAgICAgICAgICBnbyhzZWxmLl9zb2NrZXQpO1xuICAgICAgICAgICAgICBzZWxmLmNvbm5lY3RDYWxsYmFja3MuZm9yRWFjaChmdW5jdGlvbiAoY2IpIHtcbiAgICAgICAgICAgICAgICBjYihzb2NrZXQpO1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgc2VsZi5jb25uZWN0Q2FsbGJhY2tzID0gW107XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICAvLyBzZXR1cCByZXNwb25zZSBoYW5kbGVyXG4gICAgICAgICAgdGhpcy5vbihcImRhdGFcIiwgZnVuY3Rpb24gKGRhdGFCdWYpIHtcbiAgICAgICAgICAgIHNlbGYucmVzcG9uc2VIYW5kbGVyKGRhdGFCdWYpO1xuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgLy8ga2ljayBvZiBTQVNMIGlmIG5lZWRlZFxuICAgICAgICAgIGlmIChzZWxmLnVzZXJuYW1lICYmIHNlbGYucGFzc3dvcmQpIHtcbiAgICAgICAgICAgIHNlbGYubGlzdFNhc2woKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc2VsZi5lbWl0KFwiYXV0aGVudGljYXRlZFwiKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICk7XG5cbiAgICAgIC8vIHNldHVwIGVycm9yIGhhbmRsZXJcbiAgICAgIHNlbGYuX3NvY2tldC5vbihcImVycm9yXCIsIGZ1bmN0aW9uIChlcnJvcikge1xuICAgICAgICBzZWxmLmVycm9yKGVycm9yKTtcbiAgICAgIH0pO1xuXG4gICAgICBzZWxmLl9zb2NrZXQub24oXCJjbG9zZVwiLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHNlbGYuY29ubmVjdGVkID0gZmFsc2U7XG4gICAgICAgIGlmIChzZWxmLnRpbWVvdXRTZXQpIHtcbiAgICAgICAgICBzZWxmLl9zb2NrZXQ/LnNldFRpbWVvdXQoMCk7XG4gICAgICAgICAgc2VsZi50aW1lb3V0U2V0ID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgc2VsZi5fc29ja2V0ID0gdW5kZWZpbmVkO1xuICAgICAgfSk7XG5cbiAgICAgIC8vIHNldHVwIGNvbm5lY3Rpb24gdGltZW91dCBoYW5kbGVyXG4gICAgICBzZWxmLnRpbWVvdXRTZXQgPSB0cnVlO1xuICAgICAgc2VsZi5fc29ja2V0LnNldFRpbWVvdXQoXG4gICAgICAgIHNlbGYub3B0aW9ucy5jb25udGltZW91dCAqIDEwMDAsXG4gICAgICAgIGZ1bmN0aW9uICh0aGlzOiBuZXQuU29ja2V0KSB7XG4gICAgICAgICAgc2VsZi50aW1lb3V0U2V0ID0gZmFsc2U7XG4gICAgICAgICAgaWYgKCFzZWxmLmNvbm5lY3RlZCkge1xuICAgICAgICAgICAgdGhpcy5lbmQoKTtcbiAgICAgICAgICAgIHNlbGYuX3NvY2tldCA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIHNlbGYuZXJyb3IobmV3IEVycm9yKFwic29ja2V0IHRpbWVkIG91dCBjb25uZWN0aW5nIHRvIHNlcnZlci5cIikpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgKTtcblxuICAgICAgLy8gdXNlIFRDUCBrZWVwLWFsaXZlXG4gICAgICBzZWxmLl9zb2NrZXQuc2V0S2VlcEFsaXZlKFxuICAgICAgICBzZWxmLm9wdGlvbnMua2VlcEFsaXZlLFxuICAgICAgICBzZWxmLm9wdGlvbnMua2VlcEFsaXZlRGVsYXkgKiAxMDAwXG4gICAgICApO1xuICAgIH0gZWxzZSBpZiAoIXNlbGYuY29ubmVjdGVkICYmICFzYXNsKSB7XG4gICAgICAvLyBDQVNFIDI6IHNvY2tldCBleGlzdHMsIGJ1dCBzdGlsbCBjb25uZWN0aW5nIC8gYXV0aGVudGljYXRpbmdcbiAgICAgIHNlbGYub25Db25uZWN0KGdvKTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gQ0FTRSAzOiBzb2NrZXQgZXhpc3RzIGFuZCBjb25uZWN0ZWQgLyByZWFkeSB0byB1c2VcbiAgICAgIGdvKHNlbGYuX3NvY2tldCk7XG4gICAgfVxuICB9XG5cbiAgd3JpdGUoYmxvYjogQnVmZmVyKSB7XG4gICAgY29uc3Qgc2VsZiA9IHRoaXM7XG4gICAgY29uc3QgZGVhZGxpbmUgPSBNYXRoLnJvdW5kKHNlbGYub3B0aW9ucy50aW1lb3V0ICogMTAwMCk7XG4gICAgdGhpcy5zb2NrKGZhbHNlLCBmdW5jdGlvbiAocykge1xuICAgICAgcy53cml0ZShibG9iKTtcbiAgICAgIHNlbGYucmVxdWVzdFRpbWVvdXRzLnB1c2godGltZXN0YW1wKCkgKyBkZWFkbGluZSk7XG4gICAgICBpZiAoIXNlbGYudGltZW91dFNldCkge1xuICAgICAgICBzZWxmLnRpbWVvdXRTZXQgPSB0cnVlO1xuICAgICAgICBzLnNldFRpbWVvdXQoZGVhZGxpbmUsIGZ1bmN0aW9uICh0aGlzOiBuZXQuU29ja2V0KSB7XG4gICAgICAgICAgdGltZW91dEhhbmRsZXIoc2VsZiwgdGhpcyk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgd3JpdGVTQVNMKGJsb2I6IEJ1ZmZlcikge1xuICAgIHRoaXMuc29jayh0cnVlLCBmdW5jdGlvbiAocykge1xuICAgICAgcy53cml0ZShibG9iKTtcbiAgICB9KTtcbiAgfVxuXG4gIGNsb3NlKCkge1xuICAgIGlmICh0aGlzLl9zb2NrZXQpIHtcbiAgICAgIHRoaXMuX3NvY2tldC5lbmQoKTtcbiAgICB9XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICByZXR1cm4gXCI8U2VydmVyIFwiICsgdGhpcy5ob3N0ICsgXCI6XCIgKyB0aGlzLnBvcnQgKyBcIj5cIjtcbiAgfVxuXG4gIGhvc3Rwb3J0U3RyaW5nKCkge1xuICAgIHJldHVybiB0aGlzLmhvc3QgKyBcIjpcIiArIHRoaXMucG9ydDtcbiAgfVxufVxuXG4vLyBXZSBoYW5kbGUgdHJhY2tpbmcgdGltZW91dHMgd2l0aCBhbiBhcnJheSBvZiBkZWFkbGluZXMgKHJlcXVlc3RUaW1lb3V0cyksIGFzXG4vLyBub2RlIGRvZXNuJ3QgbGlrZSB1cyBzZXR0aW5nIHVwIGxvdHMgb2YgdGltZXJzLCBhbmQgdXNpbmcganVzdCBvbmUgaXMgbW9yZVxuLy8gZWZmaWNpZW50IGFueXdheS5cbmNvbnN0IHRpbWVvdXRIYW5kbGVyID0gZnVuY3Rpb24gKHNlcnZlcjogU2VydmVyLCBzb2NrOiBuZXQuU29ja2V0KSB7XG4gIGlmIChzZXJ2ZXIucmVxdWVzdFRpbWVvdXRzLmxlbmd0aCA9PT0gMCkge1xuICAgIC8vIG5vdGhpbmcgYWN0aXZlXG4gICAgc2VydmVyLnRpbWVvdXRTZXQgPSBmYWxzZTtcbiAgICByZXR1cm47XG4gIH1cblxuICAvLyBzb21lIHJlcXVlc3RzIG91dHN0YW5kaW5nLCBjaGVjayBpZiBhbnkgaGF2ZSB0aW1lZC1vdXRcbiAgY29uc3Qgbm93ID0gdGltZXN0YW1wKCk7XG4gIGNvbnN0IHNvb25lc3RUaW1lb3V0ID0gc2VydmVyLnJlcXVlc3RUaW1lb3V0c1swXTtcblxuICBpZiAoc29vbmVzdFRpbWVvdXQgPD0gbm93KSB7XG4gICAgLy8gdGltZW91dCBvY2N1cnJlZCFcbiAgICBzb2NrLmVuZCgpO1xuICAgIHNlcnZlci5jb25uZWN0ZWQgPSBmYWxzZTtcbiAgICBzZXJ2ZXIuX3NvY2tldCA9IHVuZGVmaW5lZDtcbiAgICBzZXJ2ZXIudGltZW91dFNldCA9IGZhbHNlO1xuICAgIHNlcnZlci5lcnJvcihuZXcgRXJyb3IoXCJzb2NrZXQgdGltZWQgb3V0IHdhaXRpbmcgb24gcmVzcG9uc2UuXCIpKTtcbiAgfSBlbHNlIHtcbiAgICAvLyBubyB0aW1lb3V0ISBTZXR1cCBuZXh0IG9uZS5cbiAgICBjb25zdCBkZWFkbGluZSA9IHNvb25lc3RUaW1lb3V0IC0gbm93O1xuICAgIHNvY2suc2V0VGltZW91dChkZWFkbGluZSwgZnVuY3Rpb24gKCkge1xuICAgICAgdGltZW91dEhhbmRsZXIoc2VydmVyLCBzb2NrKTtcbiAgICB9KTtcbiAgfVxufTtcbiJdfQ== \ No newline at end of file diff --git a/smoketest.js b/smoketest.js index 4103eb1..f41d253 100755 --- a/smoketest.js +++ b/smoketest.js @@ -2,11 +2,27 @@ const MemJS = require("."); const assert = require("assert"); const client = MemJS.Client.create(); +// We cannot fake Memcached server close for more than 1 second. +// So we reduce the retries to fake the server down. +const client2 = MemJS.Client.create(undefined, { retries: 1 }); function assertBufferEqual(buf1, buf2, msg) { assert.strictEqual(buf1.toString(), buf2.toString(), msg); } +async function testCloseConnection() { + await client2.set("foo2", "1"); + let { value } = await client2.get("foo2"); + assert.strictEqual(value.toString(), "1"); + + client2.close(); + // Some time to handle socket close event. + await new Promise((resolve) => setTimeout(resolve, 10)); + + const v3 = await client2.get("foo2"); + assert.strictEqual(v3.value.toString(), value.toString(), "did not get set"); +} + async function body() { await client.set("foo", "1"); @@ -33,6 +49,8 @@ async function body() { cas3.toString(), "has new CAS after identical set" ); + + await testCloseConnection(); } async function main() { @@ -44,6 +62,7 @@ async function main() { process.exit(1); } finally { client.quit(); + client2.quit(); } } diff --git a/src/memjs/memjs.ts b/src/memjs/memjs.ts index a14915a..6d359bf 100644 --- a/src/memjs/memjs.ts +++ b/src/memjs/memjs.ts @@ -913,7 +913,7 @@ class Client { * Retrieves the server version from all the servers * in the backend pool, errors if any one of them has an * error - * + * * Callbacks functions are called before/after we ping memcached * and used to log which hosts are timing out. */ diff --git a/src/memjs/server.ts b/src/memjs/server.ts index b44601c..b4c9184 100644 --- a/src/memjs/server.ts +++ b/src/memjs/server.ts @@ -214,15 +214,16 @@ export class Server extends events.EventEmitter { // setup error handler self._socket.on("error", function (error) { + self.error(error); + }); + + self._socket.on("close", function () { self.connected = false; if (self.timeoutSet) { - if (self._socket) { - self._socket.setTimeout(0); - } + self._socket?.setTimeout(0); self.timeoutSet = false; } self._socket = undefined; - self.error(error); }); // setup connection timeout handler From 53415596b3f54d57dddd0f7ef69914420c31046f Mon Sep 17 00:00:00 2001 From: Leon Wei Date: Fri, 7 Apr 2023 13:41:19 -0700 Subject: [PATCH 68/79] nit, remove white space --- lib/memjs/memjs.js | 2 +- src/memjs/memjs.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/memjs/memjs.js b/lib/memjs/memjs.js index febe707..f94461e 100644 --- a/lib/memjs/memjs.js +++ b/lib/memjs/memjs.js @@ -742,4 +742,4 @@ class Client { } } exports.Client = Client; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVtanMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbWVtanMvbWVtanMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLHdCQUF3Qjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUV4QixxQ0FLa0I7QUEyaUNELHVGQTdpQ2YsZUFBTSxPQTZpQ2U7QUExaUN2Qix1REFBK0Q7QUFDL0QsbUNBU2lCO0FBQ2pCLHVEQUF5QztBQUN6QywyQ0FBNkM7QUFDN0MsK0NBQWlDO0FBNmhDUixzQkFBSztBQTVoQzlCLGlEQUFtQztBQTRoQ0gsd0JBQU07QUExaEN0QyxTQUFTLDhCQUE4QixDQUNyQyxPQUFpQixFQUNqQixHQUFXO0lBRVgsTUFBTSxLQUFLLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQztJQUM3QixNQUFNLEtBQUssR0FBRyxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxnQkFBUSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3BELE9BQU8sT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ3hCLENBQUM7QUFFRCwrQ0FBK0M7QUFDL0MsU0FBUyxTQUFTLENBQ2hCLE9BQTBFO0lBRTFFLE9BQU8sSUFBSSxPQUFPLENBQUMsVUFBVSxPQUFPLEVBQUUsTUFBTTtRQUMxQyxPQUFPLENBQUMsVUFBVSxHQUFHLEVBQUUsTUFBTTtZQUMzQixHQUFHLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3RDLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBeURELE1BQU0sTUFBTTtJQVFWLDRFQUE0RTtJQUM1RSxtQ0FBbUM7SUFDbkMsWUFBWSxPQUFpQixFQUFFLE9BQTBDO1FBQ3ZFLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO1FBQ3ZCLElB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QUFtQixFQUNuQixjQUEwQztRQUUxQyxNQUFNLFlBQVksR0FBRyxTQUFTLFdBQVcsS0FBSyxTQUFTLENBQUMsc0JBQXNCLENBQzVFLGNBQWMsQ0FDZixFQUFFLENBQUM7UUFDSixJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDdEMsT0FBTyxJQUFJLEtBQUssQ0FBQyxZQUFZLENBQUMsQ0FBQztJQUNqQyxDQUFDO0lBRUQ7OztPQUdHO0lBQ0ssbUJBQW1CLENBQ3pCLFdBQW1CLEVBQ25CLGNBQTBDLEVBQzFDLFFBQWtFO1FBRWxFLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxXQUFXLEVBQUUsY0FBYyxDQUFDLENBQUM7UUFDbEUsSUFBSSxRQUFRLEVBQUU7WUFDWixRQUFRLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxDQUFDO1NBQ3ZCO1FBQ0QsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0NBQ0Y7QUFFUSx3QkFBTSIsInNvdXJjZXNDb250ZW50IjpbIi8vIE1lbVRTIE1lbWNhY2hlIENsaWVudFxuXG5pbXBvcnQge1xuICBPbkVycm9yQ2FsbGJhY2ssXG4gIE9uUmVzcG9uc2VDYWxsYmFjayxcbiAgU2VydmVyLFxuICBTZXJ2ZXJPcHRpb25zLFxufSBmcm9tIFwiLi9zZXJ2ZXJcIjtcbmltcG9ydCB7IG5vb3BTZXJpYWxpemVyLCBTZXJpYWxpemVyIH0gZnJvbSBcIi4vbm9vcC1zZXJpYWxpemVyXCI7XG5pbXBvcnQge1xuICBtYWtlUmVxdWVzdEJ1ZmZlcixcbiAgY29weUludG9SZXF1ZXN0QnVmZmVyLFxuICBtZXJnZSxcbiAgbWFrZUV4cGlyYXRpb24sXG4gIG1ha2VBbW91bnRJbml0aWFsQW5kRXhwaXJhdGlvbixcbiAgaGFzaENvZGUsXG4gIE1heWJlQnVmZmVyLFxuICBNZXNzYWdlLFxufSBmcm9tIFwiLi91dGlsc1wiO1xuaW1wb3J0ICogYXMgY29uc3RhbnRzIGZyb20gXCIuL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgUmVzcG9uc2VTdGF0dXMgfSBmcm9tIFwiLi9jb25zdGFudHNcIjtcbmltcG9ydCAqIGFzIFV0aWxzIGZyb20gXCIuL3V0aWxzXCI7XG5pbXBvcnQgKiBhcyBIZWFkZXIgZnJvbSBcIi4vaGVhZGVyXCI7XG5cbmZ1bmN0aW9uIGRlZmF1bHRLZXlUb1NlcnZlckhhc2hGdW5jdGlvbihcbiAgc2VydmVyczogc3RyaW5nW10sXG4gIGtleTogc3RyaW5nXG4pOiBzdHJpbmcge1xuICBjb25zdCB0b3RhbCA9IHNlcnZlcnMubGVuZ3RoO1xuICBjb25zdCBpbmRleCA9IHRvdGFsID4gMSA/IGhhc2hDb2RlKGtleSkgJSB0b3RhbCA6IDA7XG4gIHJldHVybiBzZXJ2ZXJzW2luZGV4XTtcbn1cblxuLy8gY29udmVydHMgYSBjYWxsIGludG8gYSBwcm9taXNlLXJldHVybmluZyBvbmVcbmZ1bmN0aW9uIHByb21pc2lmeTxSZXN1bHQ+KFxuICBjb21tYW5kOiAoY2FsbGJhY2s6IChlcnJvcjogRXJyb3IgfCBudWxsLCByZXN1bHQ6IFJlc3VsdCkgPT4gdm9pZCkgPT4gdm9pZFxuKTogUHJvbWlzZTxSZXN1bHQ+IHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICBjb21tYW5kKGZ1bmN0aW9uIChlcnIsIHJlc3VsdCkge1xuICAgICAgZXJyID8gcmVqZWN0KGVycikgOiByZXNvbHZlKHJlc3VsdCk7XG4gICAgfSk7XG4gIH0pO1xufVxuXG50eXBlIFJlc3BvbnNlT3JFcnJvckNhbGxiYWNrID0gKFxuICBlcnJvcjogRXJyb3IgfCBudWxsLFxuICByZXNwb25zZTogTWVzc2FnZSB8IG51bGxcbikgPT4gdm9pZDtcblxuaW50ZXJmYWNlIEJhc2VDbGllbnRPcHRpb25zIHtcbiAgcmV0cmllczogbnVtYmVyO1xuICByZXRyeV9kZWxheTogbnVtYmVyO1xuICBleHBpcmVzOiBudW1iZXI7XG4gIGxvZ2dlcjogeyBsb2c6IHR5cGVvZiBjb25zb2xlLmxvZyB9O1xuICBrZXlUb1NlcnZlckhhc2hGdW5jdGlvbjogdHlwZW9mIGRlZmF1bHRLZXlUb1NlcnZlckhhc2hGdW5jdGlvbjtcbn1cblxuaW50ZXJmYWNlIFNlcmlhbGl6ZXJQcm9wPFZhbHVlLCBFeHRyYXM+IHtcbiAgc2VyaWFsaXplcjogU2VyaWFsaXplcjxWYWx1ZSwgRXh0cmFzPjtcbn1cblxuLyoqXG4gKiBUaGUgY2xpZW50IGhhcyBwYXJ0aWFsIHN1cHBvcnQgZm9yIHNlcmlhbGl6aW5nIGFuZCBkZXNlcmlhbGl6aW5nIHZhbHVlcyBmcm9tIHRoZVxuICogQnVmZmVyIGJ5dGUgc3RyaW5ncyB3ZSByZWNlaXZlIGZyb20gdGhlIHdpcmUuIFRoZSBkZWZhdWx0IHNlcmlhbGl6ZXIgaXMgZm9yIE1heWJlQnVmZmVyLlxuICpcbiAqIElmIFZhbHVlIGFuZCBFeHRyYXMgYXJlIG9mIHR5cGUgQnVmZmVyLCB0aGVuIHJldHVybiB0eXBlIFdoZW5CdWZmZXIuIE90aGVyd2lzZSxcbiAqIHJldHVybiB0eXBlIE5vdEJ1ZmZlci5cbiAqL1xudHlwZSBJZkJ1ZmZlcjxWYWx1ZSwgRXh0cmFzLCBXaGVuVmFsdWVBbmRFeHRyYXNBcmVCdWZmZXJzLCBOb3RCdWZmZXI+ID1cbiAgVmFsdWUgZXh0ZW5kcyBCdWZmZXJcbiAgICA/IEV4dHJhcyBleHRlbmRzIEJ1ZmZlclxuICAgICAgPyBXaGVuVmFsdWVBbmRFeHRyYXNBcmVCdWZmZXJzXG4gICAgICA6IE5vdEJ1ZmZlclxuICAgIDogTm90QnVmZmVyO1xuXG5leHBvcnQgdHlwZSBHaXZlbkNsaWVudE9wdGlvbnM8VmFsdWUsIEV4dHJhcz4gPSBQYXJ0aWFsPEJhc2VDbGllbnRPcHRpb25zPiAmXG4gIElmQnVmZmVyPFxuICAgIFZhbHVlLFxuICAgIEV4dHJhcyxcbiAgICBQYXJ0aWFsPFNlcmlhbGl6ZXJQcm9wPFZhbHVlLCBFeHRyYXM+PixcbiAgICBTZXJpYWxpemVyUHJvcDxWYWx1ZSwgRXh0cmFzPlxuICA+O1xuXG5leHBvcnQgdHlwZSBDQVNUb2tlbiA9IEJ1ZmZlcjtcblxuZXhwb3J0IGludGVyZmFjZSBHZXRSZXN1bHQ8VmFsdWUgPSBNYXliZUJ1ZmZlciwgRXh0cmFzID0gTWF5YmVCdWZmZXI+IHtcbiAgdmFsdWU6IFZhbHVlO1xuICBleHRyYXM6IEV4dHJhcztcbiAgY2FzOiBDQVNUb2tlbiB8IHVuZGVmaW5lZDtcbn1cblxuZXhwb3J0IHR5cGUgR2V0TXVsdGlSZXN1bHQ8XG4gIEtleXMgZXh0ZW5kcyBzdHJpbmcgPSBzdHJpbmcsXG4gIFZhbHVlID0gTWF5YmVCdWZmZXIsXG4gIEV4dHJhcyA9IE1heWJlQnVmZmVyXG4+ID0ge1xuICBbSyBpbiBLZXlzXT86IEdldFJlc3VsdDxWYWx1ZSwgRXh0cmFzPjtcbn07XG5cbmNsYXNzIENsaWVudDxWYWx1ZSA9IE1heWJlQnVmZmVyLCBFeHRyYXMgPSBNYXliZUJ1ZmZlcj4ge1xuICBzZXJ2ZXJzOiBTZXJ2ZXJbXTtcbiAgc2VxOiBudW1iZXI7XG4gIG9wdGlvbnM6IEJhc2VDbGllbnRPcHRpb25zICYgUGFydGlhbDxTZXJpYWxpemVyUHJvcDxWYWx1ZSwgRXh0cmFzPj47XG4gIHNlcmlhbGl6ZXI6IFNlcmlhbGl6ZXI8VmFsdWUsIEV4dHJhcz47XG4gIHNlcnZlck1hcDogeyBbaG9zdHBvcnQ6IHN0cmluZ106IFNlcnZlciB9O1xuICBzZXJ2ZXJLZXlzOiBzdHJpbmdbXTtcblxuICAvLyBDbGllbnQgaW5pdGlhbGl6ZXIgdGFrZXMgYSBsaXN0IG9mIGBTZXJ2ZXJgcyBhbmQgYW4gYG9wdGlvbnNgIGRpY3Rpb25hcnkuXG4gIC8vIFNlZSBgQ2xpZW50LmNyZWF0ZWAgZm9yIGRldGFpbHMuXG4gIGNvbnN0cnVjdG9yKHNlcnZlcnM6IFNlcnZlcltdLCBvcHRpb25zOiBHaXZlbkNsaWVudE9wdGlvbnM8VmFsdWUsIEV4dHJhcz4pIHtcbiAgICB0aGlzLnNlcnZlcnMgPSBzZXJ2ZXJzO1xuICAgIHRoaXMuc2VxID0gMDtcbiAgICB0aGlzLm9wdGlvbnMgPSBtZXJnZShvcHRpb25zIHx8IHt9LCB7XG4gICAgICByZXRyaWVzOiAyLFxuICAgICAgcmV0cnlfZGVsYXk6IDAuMixcbiAgICAgIGV4cGlyZXM6IDAsXG4gICAgICBsb2dnZXI6IGNvbnNvbGUsXG4gICAgICBrZXlUb1NlcnZlckhhc2hGdW5jdGlvbjogZGVmYXVsdEtleVRvU2VydmVySGFzaEZ1bmN0aW9uLFxuICAgIH0pO1xuXG4gICAgdGhpcy5zZXJpYWxpemVyID0gdGhpcy5vcHRpb25zLnNlcmlhbGl6ZXIgfHwgKG5vb3BTZXJpYWxpemVyIGFzIGFueSk7XG5cbiAgICAvLyBTdG9yZSBhIG1hcHBpbmcgZnJvbSBob3N0cG9ydCAtPiBzZXJ2ZXIgc28gd2UgY2FuIHF1aWNrbHkgZ2V0IGEgc2VydmVyIG9iamVjdCBmcm9tIHRoZSBzZXJ2ZXJLZXkgcmV0dXJuZWQgYnkgdGhlIGhhc2hpbmcgZnVuY3Rpb25cbiAgICBjb25zdCBzZXJ2ZXJNYXA6IHsgW2hvc3Rwb3J0OiBzdHJpbmddOiBTZXJ2ZXIgfSA9IHt9O1xuICAgIHRoaXMuc2VydmVycy5mb3JFYWNoKGZ1bmN0aW9uIChzZXJ2ZXIpIHtcbiAgICAgIHNlcnZlck1hcFtzZXJ2ZXIuaG9zdHBvcnRTdHJpbmcoKV0gPSBzZXJ2ZXI7XG4gICAgfSk7XG4gICAgdGhpcy5zZXJ2ZXJNYXAgPSBzZXJ2ZXJNYXA7XG5cbiAgICAvLyBzdG9yZSBhIGxpc3Qgb2YgYWxsIG91ciBzZXJ2ZXJLZXlzIHNvIHdlIGRvbid0IG5lZWQgdG8gY29uc3RhbnRseSByZWFsbG9jYXRlIHRoaXMgYXJyYXlcbiAgICB0aGlzLnNlcnZlcktleXMgPSBPYmplY3Qua2V5cyh0aGlzLnNlcnZlck1hcCk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIG5ldyBjbGllbnQgZ2l2ZW4gYW4gb3B0aW9uYWwgY29uZmlnIHN0cmluZyBhbmQgb3B0aW9uYWwgaGFzaCBvZlxuICAgKiBvcHRpb25zLiBUaGUgY29uZmlnIHN0cmluZyBzaG91bGQgYmUgb2YgdGhlIGZvcm06XG4gICAqXG4gICAqICAgICBcIlt1c2VyOnBhc3NAXXNlcnZlcjFbOjExMjExXSxbdXNlcjpwYXNzQF1zZXJ2ZXIyWzoxMTIxMV0sLi4uXCJcbiAgICpcbiAgICogSWYgdGhlIGFyZ3VtZW50IGlzIG5vdCBnaXZlbiwgZmFsbGJhY2sgb24gdGhlIGBNRU1DQUNISUVSX1NFUlZFUlNgIGVudmlyb25tZW50XG4gICAqIHZhcmlhYmxlLCBgTUVNQ0FDSEVfU0VSVkVSU2AgZW52aXJvbm1lbnQgdmFyaWFibGUgb3IgYFwibG9jYWxob3N0OjExMjExXCJgLlxuICAgKlxuICAgKiBUaGUgb3B0aW9ucyBoYXNoIG1heSBjb250YWluIHRoZSBvcHRpb25zOlxuICAgKlxuICAgKiAqIGByZXRyaWVzYCAtIHRoZSBudW1iZXIgb2YgdGltZXMgdG8gcmV0cnkgYW4gb3BlcmF0aW9uIGluIGxpZXUgb2YgZmFpbHVyZXNcbiAgICogKGRlZmF1bHQgMilcbiAgICogKiBgZXhwaXJlc2AgLSB0aGUgZGVmYXVsdCBleHBpcmF0aW9uIGluIHNlY29uZHMgdG8gdXNlIChkZWZhdWx0IDAgLSBuZXZlclxuICAgKiBleHBpcmUpLiBJZiBgZXhwaXJlc2AgaXMgZ3JlYXRlciB0aGFuIDMwIGRheXMgKDYwIHggNjAgeCAyNCB4IDMwKSwgaXQgaXNcbiAgICogdHJlYXRlZCBhcyBhIFVOSVggdGltZSAobnVtYmVyIG9mIHNlY29uZHMgc2luY2UgSmFudWFyeSAxLCAxOTcwKS5cbiAgICogKiBgbG9nZ2VyYCAtIGEgbG9nZ2VyIG9iamVjdCB0aGF0IHJlc3BvbmRzIHRvIGBsb2coc3RyaW5nKWAgbWV0aG9kIGNhbGxzLlxuICAgKlxuICAgKiAgIH5+fn5cbiAgICogICAgIGxvZyhtc2cxWywgbXNnMlssIG1zZzNbLi4uXV1dKVxuICAgKiAgIH5+fn5cbiAgICpcbiAgICogICBEZWZhdWx0cyB0byBgY29uc29sZWAuXG4gICAqICogYHNlcmlhbGl6ZXJgIC0gdGhlIG9iamVjdCB3aGljaCB3aWxsIChkZSlzZXJpYWxpemUgdGhlIGRhdGEuIEl0IG5lZWRzXG4gICAqICAgdHdvIHB1YmxpYyBtZXRob2RzOiBzZXJpYWxpemUgYW5kIGRlc2VyaWFsaXplLiBJdCBkZWZhdWx0cyB0byB0aGVcbiAgICogICBub29wU2VyaWFsaXplcjpcbiAgICpcbiAgICogICB+fn5+XG4gICAqICAgY29uc3Qgbm9vcFNlcmlhbGl6ZXIgPSB7XG4gICAqICAgICBzZXJpYWxpemU6IGZ1bmN0aW9uIChvcGNvZGUsIHZhbHVlLCBleHRyYXMpIHtcbiAgICogICAgICAgcmV0dXJuIHsgdmFsdWU6IHZhbHVlLCBleHRyYXM6IGV4dHJhcyB9O1xuICAgKiAgICAgfSxcbiAgICogICAgIGRlc2VyaWFsaXplOiBmdW5jdGlvbiAob3Bjb2RlLCB2YWx1ZSwgZXh0cmFzKSB7XG4gICAqICAgICAgIHJldHVybiB7IHZhbHVlOiB2YWx1ZSwgZXh0cmFzOiBleHRyYXMgfTtcbiAgICogICAgIH1cbiAgICogICB9O1xuICAgKiAgIH5+fn5cbiAgICpcbiAgICogT3Igb3B0aW9ucyBmb3IgdGhlIHNlcnZlcnMgaW5jbHVkaW5nOlxuICAgKiAqIGB1c2VybmFtZWAgYW5kIGBwYXNzd29yZGAgZm9yIGZhbGxiYWNrIFNBU0wgYXV0aGVudGljYXRpb24gY3JlZGVudGlhbHMuXG4gICAqICogYHRpbWVvdXRgIGluIHNlY29uZHMgdG8gZGV0ZXJtaW5lIGZhaWx1cmUgZm9yIG9wZXJhdGlvbnMuIERlZmF1bHQgaXMgMC41XG4gICAqICAgICAgICAgICAgIHNlY29uZHMuXG4gICAqICogJ2Nvbm50aW1lb3V0JyBpbiBzZWNvbmRzIHRvIGNvbm5lY3Rpb24gZmFpbHVyZS4gRGVmYXVsdCBpcyB0d2ljZSB0aGUgdmFsdWVcbiAgICogICAgICAgICAgICAgICAgIG9mIGB0aW1lb3V0YC5cbiAgICogKiBga2VlcEFsaXZlYCB3aGV0aGVyIHRvIGVuYWJsZSBrZWVwLWFsaXZlIGZ1bmN0aW9uYWxpdHkuIERlZmF1bHRzIHRvIGZhbHNlLlxuICAgKiAqIGBrZWVwQWxpdmVEZWxheWAgaW4gc2Vjb25kcyB0byB0aGUgaW5pdGlhbCBkZWxheSBiZWZvcmUgdGhlIGZpcnN0IGtlZXBhbGl2ZVxuICAgKiAgICAgICAgICAgICAgICAgICAgcHJvYmUgaXMgc2VudCBvbiBhbiBpZGxlIHNvY2tldC4gRGVmYXVsdHMgaXMgMzAgc2Vjb25kcy5cbiAgICogKiBga2V5VG9TZXJ2ZXJIYXNoRnVuY3Rpb25gIGEgZnVuY3Rpb24gdG8gbWFwIGtleXMgdG8gc2VydmVycywgd2l0aCB0aGUgc2lnbmF0dXJlXG4gICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgIChzZXJ2ZXJLZXlzOiBzdHJpbmdbXSwga2V5OiBzdHJpbmcpOiBzdHJpbmdcbiAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgTk9URTogaWYgeW91IG5lZWQgdG8gZG8gc29tZSBleHBlbnNpdmUgaW5pdGlhbGl6YXRpb24sICpwbGVhc2UqIGRvIGl0IGxhemlseSB0aGUgZmlyc3QgdGltZSB5b3UgdGhpcyBmdW5jdGlvbiBpcyBjYWxsZWQgd2l0aCBhbiBhcnJheSBvZiBzZXJ2ZXJLZXlzLCBub3Qgb24gZXZlcnkgY2FsbFxuICAgKi9cbiAgc3RhdGljIGNyZWF0ZTxWYWx1ZSwgRXh0cmFzPihcbiAgICBzZXJ2ZXJzU3RyOiBzdHJpbmcgfCB1bmRlZmluZWQsXG4gICAgb3B0aW9uczogSWZCdWZmZXI8XG4gICAgICBWYWx1ZSxcbiAgICAgIEV4dHJhcyxcbiAgICAgIHVuZGVmaW5lZCB8IChQYXJ0aWFsPFNlcnZlck9wdGlvbnM+ICYgR2l2ZW5DbGllbnRPcHRpb25zPFZhbHVlLCBFeHRyYXM+KSxcbiAgICAgIFBhcnRpYWw8U2VydmVyT3B0aW9ucz4gJiBHaXZlbkNsaWVudE9wdGlvbnM8VmFsdWUsIEV4dHJhcz5cbiAgICA+XG4gICk6IENsaWVudDxWYWx1ZSwgRXh0cmFzPiB7XG4gICAgc2VydmVyc1N0ciA9XG4gICAgICBzZXJ2ZXJzU3RyIHx8XG4gICAgICBwcm9jZXNzLmVudi5NRU1DQUNISUVSX1NFUlZFUlMgfHxcbiAgICAgIHByb2Nlc3MuZW52Lk1FTUNBQ0hFX1NFUlZFUlMgfHxcbiAgICAgIFwibG9jYWxob3N0OjExMjExXCI7XG4gICAgY29uc3Qgc2VydmVyVXJpcyA9IHNlcnZlcnNTdHIuc3BsaXQoXCIsXCIpO1xuICAgIGNvbnN0IHNlcnZlcnMgPSBzZXJ2ZXJVcmlzLm1hcChmdW5jdGlvbiAodXJpKSB7XG4gICAgICBjb25zdCB1cmlQYXJ0cyA9IHVyaS5zcGxpdChcIkBcIik7XG4gICAgICBjb25zdCBob3N0UG9ydCA9IHVyaVBhcnRzW3VyaVBhcnRzLmxlbmd0aCAtIDFdLnNwbGl0KFwiOlwiKTtcbiAgICAgIGNvbnN0IHVzZXJQYXNzID0gKHVyaVBhcnRzW3VyaVBhcnRzLmxlbmd0aCAtIDJdIHx8IFwiXCIpLnNwbGl0KFwiOlwiKTtcbiAgICAgIHJldHVybiBuZXcgU2VydmVyKFxuICAgICAgICBob3N0UG9ydFswXSxcbiAgICAgICAgcGFyc2VJbnQoaG9zdFBvcnRbMV0gfHwgXCIxMTIxMVwiLCAxMCksXG4gICAgICAgIHVzZXJQYXNzWzBdLFxuICAgICAgICB1c2VyUGFzc1sxXSxcbiAgICAgICAgb3B0aW9uc1xuICAgICAgKTtcbiAgICB9KTtcbiAgICByZXR1cm4gbmV3IENsaWVudChzZXJ2ZXJzLCBvcHRpb25zIGFzIGFueSk7XG4gIH1cblxuICAvKipcbiAgICogR2l2ZW4gYSBzZXJ2ZXJLZXkgZnJvbWxvb2t1cEtleVRvU2VydmVyS2V5LCByZXR1cm4gdGhlIGNvcnJlc3BvbmRpbmcgU2VydmVyIGluc3RhbmNlXG4gICAqXG4gICAqIEBwYXJhbSAge3N0cmluZ30gc2VydmVyS2V5XG4gICAqIEByZXR1cm5zIHtTZXJ2ZXJ9XG4gICAqL1xuICBzZXJ2ZXJLZXlUb1NlcnZlcihzZXJ2ZXJLZXk6IHN0cmluZyk6IFNlcnZlciB7XG4gICAgcmV0dXJuIHRoaXMuc2VydmVyTWFwW3NlcnZlcktleV07XG4gIH1cblxuICAvKipcbiAgICogR2l2ZW4gYSBrZXkgdG8gbG9vayB1cCBpbiBtZW1jYWNoZSwgcmV0dXJuIGEgc2VydmVyS2V5IChiYXNlZCBvbiBzb21lXG4gICAqIGhhc2hpbmcgZnVuY3Rpb24pIHdoaWNoIGNhbiBiZSB1c2VkIHRvIGluZGV4IHRoaXMuc2VydmVyTWFwXG4gICAqL1xuICBsb29rdXBLZXlUb1NlcnZlcktleShrZXk6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMub3B0aW9ucy5rZXlUb1NlcnZlckhhc2hGdW5jdGlvbih0aGlzLnNlcnZlcktleXMsIGtleSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldmVzIHRoZSB2YWx1ZSBhdCB0aGUgZ2l2ZW4ga2V5IGluIG1lbWNhY2hlLlxuICAgKi9cbiAgYXN5bmMgZ2V0KGtleTogc3RyaW5nKTogUHJvbWlzZTxHZXRSZXN1bHQ8VmFsdWUsIEV4dHJhcz4gfCBudWxsPiB7XG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKGNvbnN0YW50cy5PUF9HRVQsIGtleSwgXCJcIiwgXCJcIiwgdGhpcy5zZXEpO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICBjb25zdCBkZXNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuZGVzZXJpYWxpemUoXG4gICAgICAgICAgcmVzcG9uc2UuaGVhZGVyLm9wY29kZSxcbiAgICAgICAgICByZXNwb25zZS52YWwsXG4gICAgICAgICAgcmVzcG9uc2UuZXh0cmFzXG4gICAgICAgICk7XG4gICAgICAgIHJldHVybiB7IC4uLmRlc2VyaWFsaXplZCwgY2FzOiByZXNwb25zZS5oZWFkZXIuY2FzIH07XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIkdFVFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKiogQnVpbGQgYSBwaXBlbGluZWQgZ2V0IG11bHRpIHJlcXVlc3QgYnkgc2VuZGluZyBvbmUgR0VUS1EgZm9yIGVhY2gga2V5IChxdWlldCwgbWVhbmluZyBpdCB3b24ndCByZXNwb25kIGlmIHRoZSB2YWx1ZSBpcyBtaXNzaW5nKSBmb2xsb3dlZCBieSBhIG5vLW9wIHRvIGZvcmNlIGEgcmVzcG9uc2UgKGFuZCB0byBnaXZlIHVzIGEgc2VudGluZWwgcmVzcG9uc2UgdGhhdCB0aGUgcGlwZWxpbmUgaXMgZG9uZSlcbiAgICpcbiAgICogY2YgaHR0cHM6Ly9naXRodWIuY29tL2NvdWNoYmFzZS9tZW1jYWNoZWQvYmxvYi9tYXN0ZXIvZG9jcy9CaW5hcnlQcm90b2NvbC5tZCMweDBkLWdldGtxLWdldC13aXRoLWtleS1xdWlldGx5XG4gICAqL1xuICBfYnVpbGRHZXRNdWx0aVJlcXVlc3Qoa2V5czogc3RyaW5nW10sIHNlcTogbnVtYmVyKTogQnVmZmVyIHtcbiAgICAvLyBzdGFydCBhdCAyNCBmb3IgdGhlIG5vLW9wIGNvbW1hbmQgYXQgdGhlIGVuZFxuICAgIGxldCByZXF1ZXN0U2l6ZSA9IDI0O1xuICAgIGZvciAoY29uc3Qga2V5SWR4IGluIGtleXMpIHtcbiAgICAgIHJlcXVlc3RTaXplICs9IEJ1ZmZlci5ieXRlTGVuZ3RoKGtleXNba2V5SWR4XSwgXCJ1dGY4XCIpICsgMjQ7XG4gICAgfVxuXG4gICAgY29uc3QgcmVxdWVzdCA9IEJ1ZmZlci5hbGxvYyhyZXF1ZXN0U2l6ZSk7XG5cbiAgICBsZXQgYnl0ZXNXcml0dGVuID0gMDtcbiAgICBmb3IgKGNvbnN0IGtleUlkeCBpbiBrZXlzKSB7XG4gICAgICBjb25zdCBrZXkgPSBrZXlzW2tleUlkeF07XG4gICAgICBieXRlc1dyaXR0ZW4gKz0gY29weUludG9SZXF1ZXN0QnVmZmVyKFxuICAgICAgICBjb25zdGFudHMuT1BfR0VUS1EsXG4gICAgICAgIGtleSxcbiAgICAgICAgXCJcIixcbiAgICAgICAgXCJcIixcbiAgICAgICAgc2VxLFxuICAgICAgICByZXF1ZXN0LFxuICAgICAgICBieXRlc1dyaXR0ZW5cbiAgICAgICk7XG4gICAgfVxuXG4gICAgYnl0ZXNXcml0dGVuICs9IGNvcHlJbnRvUmVxdWVzdEJ1ZmZlcihcbiAgICAgIGNvbnN0YW50cy5PUF9OT19PUCxcbiAgICAgIFwiXCIsXG4gICAgICBcIlwiLFxuICAgICAgXCJcIixcbiAgICAgIHNlcSxcbiAgICAgIHJlcXVlc3QsXG4gICAgICBieXRlc1dyaXR0ZW5cbiAgICApO1xuXG4gICAgcmV0dXJuIHJlcXVlc3Q7XG4gIH1cblxuICAvKiogRXhlY3V0aW5nIGEgcGlwZWxpbmVkIChtdWx0aSkgZ2V0IGFnYWluc3QgYSBzaW5nbGUgc2VydmVyLiBUaGlzIGlzIGEgcHJpdmF0ZSBpbXBsZW1lbnRhdGlvbiBkZXRhaWwgb2YgZ2V0TXVsdGkuICovXG4gIGFzeW5jIF9nZXRNdWx0aVRvU2VydmVyPEtleXMgZXh0ZW5kcyBzdHJpbmc+KFxuICAgIHNlcnY6IFNlcnZlcixcbiAgICBrZXlzOiBLZXlzW11cbiAgKTogUHJvbWlzZTxHZXRNdWx0aVJlc3VsdDxLZXlzLCBWYWx1ZSwgRXh0cmFzPj4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBjb25zdCByZXNwb25zZU1hcDogR2V0TXVsdGlSZXN1bHQ8c3RyaW5nLCBWYWx1ZSwgRXh0cmFzPiA9IHt9O1xuXG4gICAgICBjb25zdCBoYW5kbGU6IE9uUmVzcG9uc2VDYWxsYmFjayA9IChyZXNwb25zZSkgPT4ge1xuICAgICAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgICAgICAvLyBXaGVuIHdlIGdldCB0aGUgbm8tb3AgcmVzcG9uc2UsIHdlIGFyZSBkb25lIHdpdGggdGhpcyBvbmUgZ2V0TXVsdGkgaW4gdGhlIHBlci1iYWNrZW5kIGZhbi1vdXRcbiAgICAgICAgICAgIGlmIChyZXNwb25zZS5oZWFkZXIub3Bjb2RlID09PSBjb25zdGFudHMuT1BfTk9fT1ApIHtcbiAgICAgICAgICAgICAgLy8gVGhpcyBlbnN1cmVzIHRoZSBoYW5kbGVyIHdpbGwgYmUgZGVsZXRlZCBmcm9tIHRoZSByZXNwb25zZUNhbGxiYWNrcyBtYXAgaW4gc2VydmVyLmpzXG4gICAgICAgICAgICAgIC8vIFRoaXMgaXNuJ3QgdGVjaG5pY2FsbHkgbmVlZGVkIGhlcmUgYmVjYXVzZSB0aGUgbG9naWMgaW4gc2VydmVyLmpzIGFsc28gY2hlY2tzIGlmIHRvdGFsQm9keUxlbmd0aCA9PT0gMCwgYnV0IG91ciB1bml0dGVzdHMgYXJlbid0IGdyZWF0IGFib3V0IHNldHRpbmcgdGhhdCBmaWVsZCwgYW5kIGFsc28gdGhpcyBtYWtlcyBpdCBtb3JlIGV4cGxpY2l0XG4gICAgICAgICAgICAgIGhhbmRsZS5xdWlldCA9IGZhbHNlO1xuICAgICAgICAgICAgICByZXNvbHZlKHJlc3BvbnNlTWFwKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgICAgICAgIHJlc3BvbnNlLmhlYWRlci5vcGNvZGUgPT09IGNvbnN0YW50cy5PUF9HRVRLIHx8XG4gICAgICAgICAgICAgIHJlc3BvbnNlLmhlYWRlci5vcGNvZGUgPT09IGNvbnN0YW50cy5PUF9HRVRLUVxuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgIGNvbnN0IGRlc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5kZXNlcmlhbGl6ZShcbiAgICAgICAgICAgICAgICByZXNwb25zZS5oZWFkZXIub3Bjb2RlLFxuICAgICAgICAgICAgICAgIHJlc3BvbnNlLnZhbCxcbiAgICAgICAgICAgICAgICByZXNwb25zZS5leHRyYXNcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgY29uc3Qga2V5ID0gcmVzcG9uc2Uua2V5LnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgIGlmIChrZXkubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlamVjdChcbiAgICAgICAgICAgICAgICAgIG5ldyBFcnJvcihcbiAgICAgICAgICAgICAgICAgICAgXCJSZWNpZXZlZCBlbXB0eSBrZXkgaW4gZ2V0TXVsdGk6IFwiICtcbiAgICAgICAgICAgICAgICAgICAgICBKU09OLnN0cmluZ2lmeShyZXNwb25zZSlcbiAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIHJlc3BvbnNlTWFwW2tleV0gPSB7IC4uLmRlc2VyaWFsaXplZCwgY2FzOiByZXNwb25zZS5oZWFkZXIuY2FzIH07XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICByZXR1cm4gcmVqZWN0KFxuICAgICAgICAgICAgICAgIG5ldyBFcnJvcihcbiAgICAgICAgICAgICAgICAgIFwiUmVjaWV2ZWQgcmVzcG9uc2UgaW4gZ2V0TXVsdGkgZm9yIHVua25vd24gb3Bjb2RlOiBcIiArXG4gICAgICAgICAgICAgICAgICAgIEpTT04uc3RyaW5naWZ5KHJlc3BvbnNlKVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICByZXR1cm4gcmVqZWN0KFxuICAgICAgICAgICAgICB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiR0VUXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9O1xuICAgICAgLy8gVGhpcyBwcmV2ZW50cyB0aGUgaGFuZGxlciBmcm9tIGJlaW5nIGRlbGV0ZWRcbiAgICAgIC8vIGFmdGVyIHRoZSBmaXJzdCByZXNwb25zZS4gTG9naWMgaW4gc2VydmVyLmpzLlxuICAgICAgaGFuZGxlLnF1aWV0ID0gdHJ1ZTtcblxuICAgICAgY29uc3Qgc2VxID0gdGhpcy5pbmNyU2VxKCk7XG4gICAgICBjb25zdCByZXF1ZXN0ID0gdGhpcy5fYnVpbGRHZXRNdWx0aVJlcXVlc3Qoa2V5cywgc2VxKTtcbiAgICAgIHNlcnYub25SZXNwb25zZSh0aGlzLnNlcSwgaGFuZGxlKTtcbiAgICAgIHNlcnYub25FcnJvcih0aGlzLnNlcSwgcmVqZWN0KTtcbiAgICAgIHNlcnYud3JpdGUocmVxdWVzdCk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldnMgdGhlIHZhbHVlIGF0IHRoZSBnaXZlbiBrZXlzIGluIG1lbWNhY2hlZC4gUmV0dXJucyBhIG1hcCBmcm9tIHRoZVxuICAgKiByZXF1ZXN0ZWQga2V5cyB0byByZXN1bHRzLCBvciBudWxsIGlmIHRoZSBrZXkgd2FzIG5vdCBmb3VuZC5cbiAgICovXG4gIGFzeW5jIGdldE11bHRpPEtleXMgZXh0ZW5kcyBzdHJpbmc+KFxuICAgIGtleXM6IEtleXNbXVxuICApOiBQcm9taXNlPEdldE11bHRpUmVzdWx0PEtleXMsIFZhbHVlLCBFeHRyYXM+PiB7XG4gICAgY29uc3Qgc2VydmVyS2V5dG9Mb29rdXBLZXlzOiB7XG4gICAgICBbc2VydmVyS2V5OiBzdHJpbmddOiBzdHJpbmdbXTtcbiAgICB9ID0ge307XG4gICAga2V5cy5mb3JFYWNoKChsb29rdXBLZXkpID0+IHtcbiAgICAgIGNvbnN0IHNlcnZlcktleSA9IHRoaXMubG9va3VwS2V5VG9TZXJ2ZXJLZXkobG9va3VwS2V5KTtcbiAgICAgIGlmICghc2VydmVyS2V5dG9Mb29rdXBLZXlzW3NlcnZlcktleV0pIHtcbiAgICAgICAgc2VydmVyS2V5dG9Mb29rdXBLZXlzW3NlcnZlcktleV0gPSBbXTtcbiAgICAgIH1cbiAgICAgIHNlcnZlcktleXRvTG9va3VwS2V5c1tzZXJ2ZXJLZXldLnB1c2gobG9va3VwS2V5KTtcbiAgICB9KTtcblxuICAgIGNvbnN0IHVzZWRTZXJ2ZXJLZXlzID0gT2JqZWN0LmtleXMoc2VydmVyS2V5dG9Mb29rdXBLZXlzKTtcbiAgICBjb25zdCByZXN1bHRzID0gYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICB1c2VkU2VydmVyS2V5cy5tYXAoKHNlcnZlcktleSkgPT4ge1xuICAgICAgICBjb25zdCBzZXJ2ZXIgPSB0aGlzLnNlcnZlcktleVRvU2VydmVyKHNlcnZlcktleSk7XG4gICAgICAgIHJldHVybiB0aGlzLl9nZXRNdWx0aVRvU2VydmVyKHNlcnZlciwgc2VydmVyS2V5dG9Mb29rdXBLZXlzW3NlcnZlcktleV0pO1xuICAgICAgfSlcbiAgICApO1xuXG4gICAgcmV0dXJuIE9iamVjdC5hc3NpZ24oe30sIC4uLnJlc3VsdHMpO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgYGtleWAgdG8gYHZhbHVlYC5cbiAgICovXG4gIGFzeW5jIHNldChcbiAgICBrZXk6IHN0cmluZyxcbiAgICB2YWx1ZTogVmFsdWUsXG4gICAgb3B0aW9ucz86IHsgZXhwaXJlcz86IG51bWJlcjsgY2FzPzogQ0FTVG9rZW4gfVxuICApOiBQcm9taXNlPGJvb2xlYW4gfCBudWxsPiB7XG4gICAgY29uc3QgZXhwaXJlcyA9IG9wdGlvbnM/LmV4cGlyZXM7XG4gICAgY29uc3QgY2FzID0gb3B0aW9ucz8uY2FzO1xuXG4gICAgLy8gVE9ETzogc3VwcG9ydCBmbGFnc1xuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IGV4cGlyYXRpb24gPSBtYWtlRXhwaXJhdGlvbihleHBpcmVzIHx8IHRoaXMub3B0aW9ucy5leHBpcmVzKTtcbiAgICBjb25zdCBleHRyYXMgPSBCdWZmZXIuY29uY2F0KFtCdWZmZXIuZnJvbShcIjAwMDAwMDAwXCIsIFwiaGV4XCIpLCBleHBpcmF0aW9uXSk7XG4gICAgY29uc3Qgc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5zZXJpYWxpemUoXG4gICAgICBjb25zdGFudHMuT1BfU0VULFxuICAgICAgdmFsdWUsXG4gICAgICBleHRyYXNcbiAgICApO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBVdGlscy5lbmNvZGVSZXF1ZXN0KHtcbiAgICAgIGhlYWRlcjoge1xuICAgICAgICBvcGNvZGU6IGNvbnN0YW50cy5PUF9TRVQsXG4gICAgICAgIG9wYXF1ZTogdGhpcy5zZXEsXG4gICAgICAgIGNhcyxcbiAgICAgIH0sXG4gICAgICBrZXksXG4gICAgICB2YWx1ZTogc2VyaWFsaXplZC52YWx1ZSxcbiAgICAgIGV4dHJhczogc2VyaWFsaXplZC5leHRyYXMsXG4gICAgfSk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfRVhJU1RTOlxuICAgICAgICBpZiAoY2FzKSB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJTRVRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgICAgIH1cbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJTRVRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEFERFxuICAgKlxuICAgKiBBZGRzIHRoZSBnaXZlbiBfa2V5XyBhbmQgX3ZhbHVlXyB0byBtZW1jYWNoZS4gVGhlIG9wZXJhdGlvbiBvbmx5IHN1Y2NlZWRzXG4gICAqIGlmIHRoZSBrZXkgaXMgbm90IGFscmVhZHkgc2V0LlxuICAgKlxuICAgKiBUaGUgb3B0aW9ucyBkaWN0aW9uYXJ5IHRha2VzOlxuICAgKiAqIF9leHBpcmVzXzogb3ZlcnJpZGVzIHRoZSBkZWZhdWx0IGV4cGlyYXRpb24gKHNlZSBgQ2xpZW50LmNyZWF0ZWApIGZvciB0aGlzXG4gICAqICAgICAgICAgICAgICBwYXJ0aWN1bGFyIGtleS12YWx1ZSBwYWlyLlxuICAgKi9cbiAgYXN5bmMgYWRkKFxuICAgIGtleTogc3RyaW5nLFxuICAgIHZhbHVlOiBWYWx1ZSxcbiAgICBvcHRpb25zPzogeyBleHBpcmVzPzogbnVtYmVyIH1cbiAgKTogUHJvbWlzZTxib29sZWFuIHwgbnVsbD4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgZmxhZ3MsIHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IGV4cGlyYXRpb24gPSBtYWtlRXhwaXJhdGlvbihvcHRpb25zPy5leHBpcmVzIHx8IHRoaXMub3B0aW9ucy5leHBpcmVzKTtcbiAgICBjb25zdCBleHRyYXMgPSBCdWZmZXIuY29uY2F0KFtCdWZmZXIuZnJvbShcIjAwMDAwMDAwXCIsIFwiaGV4XCIpLCBleHBpcmF0aW9uXSk7XG5cbiAgICBjb25zdCBvcGNvZGUgPSBjb25zdGFudHMuT1BfQUREO1xuICAgIGNvbnN0IHNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuc2VyaWFsaXplKG9wY29kZSwgdmFsdWUsIGV4dHJhcyk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKFxuICAgICAgb3Bjb2RlLFxuICAgICAga2V5LFxuICAgICAgc2VyaWFsaXplZC5leHRyYXMsXG4gICAgICBzZXJpYWxpemVkLnZhbHVlLFxuICAgICAgdGhpcy5zZXFcbiAgICApO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuS0VZX0VYSVNUUzpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJBRERcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlcGxhY2VzIHRoZSBnaXZlbiBfa2V5XyBhbmQgX3ZhbHVlXyB0byBtZW1jYWNoZS4gVGhlIG9wZXJhdGlvbiBvbmx5IHN1Y2NlZWRzXG4gICAqIGlmIHRoZSBrZXkgaXMgYWxyZWFkeSBwcmVzZW50LlxuICAgKi9cbiAgYXN5bmMgcmVwbGFjZShcbiAgICBrZXk6IHN0cmluZyxcbiAgICB2YWx1ZTogVmFsdWUsXG4gICAgb3B0aW9ucz86IHsgZXhwaXJlcz86IG51bWJlciB9XG4gICk6IFByb21pc2U8Ym9vbGVhbiB8IG51bGw+IHtcbiAgICAvLyBUT0RPOiBzdXBwb3J0IGZsYWdzLCBzdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBleHBpcmF0aW9uID0gbWFrZUV4cGlyYXRpb24ob3B0aW9ucz8uZXhwaXJlcyB8fCB0aGlzLm9wdGlvbnMuZXhwaXJlcyk7XG4gICAgY29uc3QgZXh0cmFzID0gQnVmZmVyLmNvbmNhdChbQnVmZmVyLmZyb20oXCIwMDAwMDAwMFwiLCBcImhleFwiKSwgZXhwaXJhdGlvbl0pO1xuXG4gICAgY29uc3Qgb3Bjb2RlOiBjb25zdGFudHMuT1AgPSBjb25zdGFudHMuT1BfUkVQTEFDRTtcbiAgICBjb25zdCBzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLnNlcmlhbGl6ZShvcGNvZGUsIHZhbHVlLCBleHRyYXMpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgIG9wY29kZSxcbiAgICAgIGtleSxcbiAgICAgIHNlcmlhbGl6ZWQuZXh0cmFzLFxuICAgICAgc2VyaWFsaXplZC52YWx1ZSxcbiAgICAgIHRoaXMuc2VxXG4gICAgKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJSRVBMQUNFXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBEZWxldGVzIHRoZSBnaXZlbiBfa2V5XyBmcm9tIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHNcbiAgICogaWYgdGhlIGtleSBpcyBhbHJlYWR5IHByZXNlbnQuXG4gICAqL1xuICBhc3luYyBkZWxldGUoa2V5OiBzdHJpbmcpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAvLyBUT0RPOiBTdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoNCwga2V5LCBcIlwiLCBcIlwiLCB0aGlzLnNlcSk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG5cbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJERUxFVEVcIiwgcmVzcG9uc2U/LmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBJbmNyZW1lbnRzIHRoZSBnaXZlbiBfa2V5XyBpbiBtZW1jYWNoZS5cbiAgICovXG4gIGFzeW5jIGluY3JlbWVudChcbiAgICBrZXk6IHN0cmluZyxcbiAgICBhbW91bnQ6IG51bWJlcixcbiAgICBvcHRpb25zPzogeyBpbml0aWFsPzogbnVtYmVyOyBleHBpcmVzPzogbnVtYmVyIH1cbiAgKTogUHJvbWlzZTx7IHZhbHVlOiBudW1iZXIgfCBudWxsOyBzdWNjZXNzOiBib29sZWFuIHwgbnVsbCB9PiB7XG4gICAgLy8gVE9ETzogc3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgaW5pdGlhbCA9IG9wdGlvbnM/LmluaXRpYWwgfHwgMDtcbiAgICBjb25zdCBleHBpcmVzID0gb3B0aW9ucz8uZXhwaXJlcyB8fCB0aGlzLm9wdGlvbnMuZXhwaXJlcztcbiAgICBjb25zdCBleHRyYXMgPSBtYWtlQW1vdW50SW5pdGlhbEFuZEV4cGlyYXRpb24oYW1vdW50LCBpbml0aWFsLCBleHBpcmVzKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICBjb25zdGFudHMuT1BfSU5DUkVNRU5ULFxuICAgICAga2V5LFxuICAgICAgZXh0cmFzLFxuICAgICAgXCJcIixcbiAgICAgIHRoaXMuc2VxXG4gICAgKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgY29uc3QgYnVmSW50ID1cbiAgICAgICAgICAocmVzcG9uc2UudmFsLnJlYWRVSW50MzJCRSgwKSA8PCA4KSArIHJlc3BvbnNlLnZhbC5yZWFkVUludDMyQkUoNCk7XG4gICAgICAgIHJldHVybiB7IHZhbHVlOiBidWZJbnQsIHN1Y2Nlc3M6IHRydWUgfTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJJTkNSRU1FTlRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIERlY3JlbWVudHMgdGhlIGdpdmVuIGBrZXlgIGluIG1lbWNhY2hlLlxuICAgKi9cbiAgYXN5bmMgZGVjcmVtZW50KFxuICAgIGtleTogc3RyaW5nLFxuICAgIGFtb3VudDogbnVtYmVyLFxuICAgIG9wdGlvbnM6IHsgaW5pdGlhbD86IG51bWJlcjsgZXhwaXJlcz86IG51bWJlciB9XG4gICk6IFByb21pc2U8eyB2YWx1ZTogbnVtYmVyIHwgbnVsbDsgc3VjY2VzczogYm9vbGVhbiB8IG51bGwgfT4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IGluaXRpYWwgPSBvcHRpb25zLmluaXRpYWwgfHwgMDtcbiAgICBjb25zdCBleHBpcmVzID0gb3B0aW9ucy5leHBpcmVzIHx8IHRoaXMub3B0aW9ucy5leHBpcmVzO1xuICAgIGNvbnN0IGV4dHJhcyA9IG1ha2VBbW91bnRJbml0aWFsQW5kRXhwaXJhdGlvbihhbW91bnQsIGluaXRpYWwsIGV4cGlyZXMpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgIGNvbnN0YW50cy5PUF9ERUNSRU1FTlQsXG4gICAgICBrZXksXG4gICAgICBleHRyYXMsXG4gICAgICBcIlwiLFxuICAgICAgdGhpcy5zZXFcbiAgICApO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICBjb25zdCBidWZJbnQgPVxuICAgICAgICAgIChyZXNwb25zZS52YWwucmVhZFVJbnQzMkJFKDApIDw8IDgpICsgcmVzcG9uc2UudmFsLnJlYWRVSW50MzJCRSg0KTtcbiAgICAgICAgcmV0dXJuIHsgdmFsdWU6IGJ1ZkludCwgc3VjY2VzczogdHJ1ZSB9O1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIkRFQ1JFTUVOVFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQXBwZW5kIHRoZSBnaXZlbiBfdmFsdWVfIHRvIHRoZSB2YWx1ZSBhc3NvY2lhdGVkIHdpdGggdGhlIGdpdmVuIF9rZXlfIGluXG4gICAqIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHMgaWYgdGhlIGtleSBpcyBhbHJlYWR5IHByZXNlbnQuXG4gICAqL1xuICBhc3luYyBhcHBlbmQoa2V5OiBzdHJpbmcsIHZhbHVlOiBWYWx1ZSk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IG9wY29kZTogY29uc3RhbnRzLk9QID0gY29uc3RhbnRzLk9QX0FQUEVORDtcbiAgICBjb25zdCBzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLnNlcmlhbGl6ZShvcGNvZGUsIHZhbHVlLCBcIlwiKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICBvcGNvZGUsXG4gICAgICBrZXksXG4gICAgICBzZXJpYWxpemVkLmV4dHJhcyxcbiAgICAgIHNlcmlhbGl6ZWQudmFsdWUsXG4gICAgICB0aGlzLnNlcVxuICAgICk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfTk9UX0ZPVU5EOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiQVBQRU5EXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBQcmVwZW5kIHRoZSBnaXZlbiBfdmFsdWVfIHRvIHRoZSB2YWx1ZSBhc3NvY2lhdGVkIHdpdGggdGhlIGdpdmVuIF9rZXlfIGluXG4gICAqIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHMgaWYgdGhlIGtleSBpcyBhbHJlYWR5IHByZXNlbnQuXG4gICAqL1xuICBhc3luYyBwcmVwZW5kKGtleTogc3RyaW5nLCB2YWx1ZTogVmFsdWUpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAvLyBUT0RPOiBzdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBvcGNvZGU6IGNvbnN0YW50cy5PUCA9IGNvbnN0YW50cy5PUF9QUkVQRU5EO1xuICAgIGNvbnN0IHNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuc2VyaWFsaXplKG9wY29kZSwgdmFsdWUsIFwiXCIpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgIG9wY29kZSxcbiAgICAgIGtleSxcbiAgICAgIHNlcmlhbGl6ZWQuZXh0cmFzLFxuICAgICAgc2VyaWFsaXplZC52YWx1ZSxcbiAgICAgIHRoaXMuc2VxXG4gICAgKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJQUkVQRU5EXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBUb3VjaCBzZXRzIGFuIGV4cGlyYXRpb24gdmFsdWUsIGdpdmVuIGJ5IF9leHBpcmVzXywgb24gdGhlIGdpdmVuIF9rZXlfIGluXG4gICAqIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHMgaWYgdGhlIGtleSBpcyBhbHJlYWR5IHByZXNlbnQuXG4gICAqL1xuICBhc3luYyB0b3VjaChrZXk6IHN0cmluZywgZXhwaXJlczogbnVtYmVyKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgLy8gVE9ETzogc3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgZXh0cmFzID0gbWFrZUV4cGlyYXRpb24oZXhwaXJlcyB8fCB0aGlzLm9wdGlvbnMuZXhwaXJlcyk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKDB4MWMsIGtleSwgZXh0cmFzLCBcIlwiLCB0aGlzLnNlcSk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfTk9UX0ZPVU5EOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiVE9VQ0hcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEZMVVNIXG4gICAqXG4gICAqIEZsdXNoZXMgdGhlIGNhY2hlIG9uIGVhY2ggY29ubmVjdGVkIHNlcnZlci4gVGhlIGNhbGxiYWNrIHNpZ25hdHVyZSBpczpcbiAgICpcbiAgICogICAgIGNhbGxiYWNrKGxhc3RFcnIsIHJlc3VsdHMpXG4gICAqXG4gICAqIHdoZXJlIF9sYXN0RXJyXyBpcyB0aGUgbGFzdCBlcnJvciBlbmNvdW50ZXJlZCAob3IgbnVsbCwgaW4gdGhlIGNvbW1vbiBjYXNlXG4gICAqIG9mIG5vIGVycm9ycykuIF9yZXN1bHRzXyBpcyBhIGRpY3Rpb25hcnkgbWFwcGluZyBgXCJob3N0bmFtZTpwb3J0XCJgIHRvIGVpdGhlclxuICAgKiBgdHJ1ZWAgKGlmIHRoZSBvcGVyYXRpb24gd2FzIHN1Y2Nlc3NmdWwpLCBvciBhbiBlcnJvci5cbiAgICogQHBhcmFtIGNhbGxiYWNrXG4gICAqL1xuICBmbHVzaCgpOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIGJvb2xlYW4gfCBFcnJvcj4+O1xuICBmbHVzaChcbiAgICBjYWxsYmFjazogKFxuICAgICAgZXJyOiBFcnJvciB8IG51bGwsXG4gICAgICByZXN1bHRzOiBSZWNvcmQ8c3RyaW5nLCBib29sZWFuIHwgRXJyb3I+XG4gICAgKSA9PiB2b2lkXG4gICk6IHZvaWQ7XG4gIGZsdXNoKFxuICAgIGNhbGxiYWNrPzogKFxuICAgICAgZXJyOiBFcnJvciB8IG51bGwsXG4gICAgICByZXN1bHRzOiBSZWNvcmQ8c3RyaW5nLCBib29sZWFuIHwgRXJyb3I+XG4gICAgKSA9PiB2b2lkXG4gICkge1xuICAgIGlmIChjYWxsYmFjayA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm4gcHJvbWlzaWZ5KChjYWxsYmFjaykgPT4ge1xuICAgICAgICB0aGlzLmZsdXNoKGZ1bmN0aW9uIChlcnIsIHJlc3VsdHMpIHtcbiAgICAgICAgICBjYWxsYmFjayhlcnIsIHJlc3VsdHMpO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH1cbiAgICAvLyBUT0RPOiBzdXBwb3J0IGV4cGlyYXRpb25cbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoMHgwOCwgXCJcIiwgXCJcIiwgXCJcIiwgdGhpcy5zZXEpO1xuICAgIGxldCBjb3VudCA9IHRoaXMuc2VydmVycy5sZW5ndGg7XG4gICAgY29uc3QgcmVzdWx0OiBSZWNvcmQ8c3RyaW5nLCBib29sZWFuIHwgRXJyb3I+ID0ge307XG4gICAgbGV0IGxhc3RFcnI6IEVycm9yIHwgbnVsbCA9IG51bGw7XG5cbiAgICBjb25zdCBoYW5kbGVGbHVzaCA9IGZ1bmN0aW9uIChzZXE6IG51bWJlciwgc2VydjogU2VydmVyKSB7XG4gICAgICBzZXJ2Lm9uUmVzcG9uc2Uoc2VxLCBmdW5jdGlvbiAoLyogcmVzcG9uc2UgKi8pIHtcbiAgICAgICAgY291bnQgLT0gMTtcbiAgICAgICAgcmVzdWx0W3NlcnYuaG9zdHBvcnRTdHJpbmcoKV0gPSB0cnVlO1xuICAgICAgICBpZiAoY2FsbGJhY2sgJiYgY291bnQgPT09IDApIHtcbiAgICAgICAgICBjYWxsYmFjayhsYXN0RXJyLCByZXN1bHQpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHNlcnYub25FcnJvcihzZXEsIGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgICAgY291bnQgLT0gMTtcbiAgICAgICAgbGFzdEVyciA9IGVycjtcbiAgICAgICAgcmVzdWx0W3NlcnYuaG9zdHBvcnRTdHJpbmcoKV0gPSBlcnI7XG4gICAgICAgIGlmIChjYWxsYmFjayAmJiBjb3VudCA9PT0gMCkge1xuICAgICAgICAgIGNhbGxiYWNrKGxhc3RFcnIsIHJlc3VsdCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgc2Vydi53cml0ZShyZXF1ZXN0KTtcbiAgICB9O1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnNlcnZlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGhhbmRsZUZsdXNoKHRoaXMuc2VxLCB0aGlzLnNlcnZlcnNbaV0pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTVEFUU19XSVRIX0tFWVxuICAgKlxuICAgKiBTZW5kcyBhIG1lbWNhY2hlIHN0YXRzIGNvbW1hbmQgd2l0aCBhIGtleSB0byBlYWNoIGNvbm5lY3RlZCBzZXJ2ZXIuIFRoZVxuICAgKiBjYWxsYmFjayBpcyBpbnZva2VkICoqT05DRSBQRVIgU0VSVkVSKiogYW5kIGhhcyB0aGUgc2lnbmF0dXJlOlxuICAgKlxuICAgKiAgICAgY2FsbGJhY2soZXJyLCBzZXJ2ZXIsIHN0YXRzKVxuICAgKlxuICAgKiBfc2VydmVyXyBpcyB0aGUgYFwiaG9zdG5hbWU6cG9ydFwiYCBvZiB0aGUgc2VydmVyLCBhbmQgX3N0YXRzXyBpcyBhIGRpY3Rpb25hcnlcbiAgICogbWFwcGluZyB0aGUgc3RhdCBuYW1lIHRvIHRoZSB2YWx1ZSBvZiB0aGUgc3RhdGlzdGljIGFzIGEgc3RyaW5nLlxuICAgKiBAcGFyYW0ga2V5XG4gICAqIEBwYXJhbSBjYWxsYmFja1xuICAgKi9cbiAgc3RhdHNXaXRoS2V5KFxuICAgIGtleTogc3RyaW5nLFxuICAgIGNhbGxiYWNrPzogKFxuICAgICAgZXJyOiBFcnJvciB8IG51bGwsXG4gICAgICBzZXJ2ZXI6IHN0cmluZyxcbiAgICAgIHN0YXRzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+IHwgbnVsbFxuICAgICkgPT4gdm9pZFxuICApOiB2b2lkIHtcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoMHgxMCwga2V5LCBcIlwiLCBcIlwiLCB0aGlzLnNlcSk7XG5cbiAgICBjb25zdCBoYW5kbGVTdGF0cyA9IChzZXE6IG51bWJlciwgc2VydjogU2VydmVyKSA9PiB7XG4gICAgICBjb25zdCByZXN1bHQ6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcbiAgICAgIGNvbnN0IGhhbmRsZTogT25SZXNwb25zZUNhbGxiYWNrID0gKHJlc3BvbnNlKSA9PiB7XG4gICAgICAgIC8vIGVuZCBvZiBzdGF0IHJlc3BvbnNlc1xuICAgICAgICBpZiAocmVzcG9uc2UuaGVhZGVyLnRvdGFsQm9keUxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgICAgY2FsbGJhY2sobnVsbCwgc2Vydi5ob3N0cG9ydFN0cmluZygpLCByZXN1bHQpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgLy8gcHJvY2VzcyBzaW5nbGUgc3RhdCBsaW5lIHJlc3BvbnNlXG4gICAgICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgICAgIHJlc3VsdFtyZXNwb25zZS5rZXkudG9TdHJpbmcoKV0gPSByZXNwb25zZS52YWwudG9TdHJpbmcoKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICBjb25zdCBlcnJvciA9IHRoaXMuaGFuZGxlUmVzcG9uc2VFcnJvcihcbiAgICAgICAgICAgICAgYFNUQVRTICgke2tleX0pYCxcbiAgICAgICAgICAgICAgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyxcbiAgICAgICAgICAgICAgdW5kZWZpbmVkXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgICAgICAgIGNhbGxiYWNrKGVycm9yLCBzZXJ2Lmhvc3Rwb3J0U3RyaW5nKCksIG51bGwpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9O1xuICAgICAgaGFuZGxlLnF1aWV0ID0gdHJ1ZTtcblxuICAgICAgc2Vydi5vblJlc3BvbnNlKHNlcSwgaGFuZGxlKTtcbiAgICAgIHNlcnYub25FcnJvcihzZXEsIGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgICAgY2FsbGJhY2soZXJyLCBzZXJ2Lmhvc3Rwb3J0U3RyaW5nKCksIG51bGwpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHNlcnYud3JpdGUocmVxdWVzdCk7XG4gICAgfTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5zZXJ2ZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBoYW5kbGVTdGF0cyh0aGlzLnNlcSwgdGhpcy5zZXJ2ZXJzW2ldKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU1RBVFNcbiAgICpcbiAgICogRmV0Y2hlcyBtZW1jYWNoZSBzdGF0cyBmcm9tIGVhY2ggY29ubmVjdGVkIHNlcnZlci4gVGhlIGNhbGxiYWNrIGlzIGludm9rZWRcbiAgICogKipPTkNFIFBFUiBTRVJWRVIqKiBhbmQgaGFzIHRoZSBzaWduYXR1cmU6XG4gICAqXG4gICAqICAgICBjYWxsYmFjayhlcnIsIHNlcnZlciwgc3RhdHMpXG4gICAqXG4gICAqIF9zZXJ2ZXJfIGlzIHRoZSBgXCJob3N0bmFtZTpwb3J0XCJgIG9mIHRoZSBzZXJ2ZXIsIGFuZCBfc3RhdHNfIGlzIGFcbiAgICogZGljdGlvbmFyeSBtYXBwaW5nIHRoZSBzdGF0IG5hbWUgdG8gdGhlIHZhbHVlIG9mIHRoZSBzdGF0aXN0aWMgYXMgYSBzdHJpbmcuXG4gICAqIEBwYXJhbSBjYWxsYmFja1xuICAgKi9cbiAgc3RhdHMoXG4gICAgY2FsbGJhY2s/OiAoXG4gICAgICBlcnI6IEVycm9yIHwgbnVsbCxcbiAgICAgIHNlcnZlcjogc3RyaW5nLFxuICAgICAgc3RhdHM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gfCBudWxsXG4gICAgKSA9PiB2b2lkXG4gICk6IHZvaWQge1xuICAgIHRoaXMuc3RhdHNXaXRoS2V5KFwiXCIsIGNhbGxiYWNrKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSRVNFVF9TVEFUU1xuICAgKlxuICAgKiBSZXNldCB0aGUgc3RhdGlzdGljcyBlYWNoIHNlcnZlciBpcyBrZWVwaW5nIGJhY2sgdG8gemVyby4gVGhpcyBkb2Vzbid0IGNsZWFyXG4gICAqIHN0YXRzIHN1Y2ggYXMgaXRlbSBjb3VudCwgYnV0IHRlbXBvcmFyeSBzdGF0cyBzdWNoIGFzIHRvdGFsIG51bWJlciBvZlxuICAgKiBjb25uZWN0aW9ucyBvdmVyIHRpbWUuXG4gICAqXG4gICAqIFRoZSBjYWxsYmFjayBpcyBpbnZva2VkICoqT05DRSBQRVIgU0VSVkVSKiogYW5kIGhhcyB0aGUgc2lnbmF0dXJlOlxuICAgKlxuICAgKiAgICAgY2FsbGJhY2soZXJyLCBzZXJ2ZXIpXG4gICAqXG4gICAqIF9zZXJ2ZXJfIGlzIHRoZSBgXCJob3N0bmFtZTpwb3J0XCJgIG9mIHRoZSBzZXJ2ZXIuXG4gICAqIEBwYXJhbSBjYWxsYmFja1xuICAgKi9cbiAgcmVzZXRTdGF0cyhcbiAgICBjYWxsYmFjaz86IChcbiAgICAgIGVycjogRXJyb3IgfCBudWxsLFxuICAgICAgc2VydmVyOiBzdHJpbmcsXG4gICAgICBzdGF0czogUmVjb3JkPHN0cmluZywgc3RyaW5nPiB8IG51bGxcbiAgICApID0+IHZvaWRcbiAgKTogdm9pZCB7XG4gICAgdGhpcy5zdGF0c1dpdGhLZXkoXCJyZXNldFwiLCBjYWxsYmFjayk7XG4gIH1cblxuICAvKipcbiAgICogUVVJVFxuICAgKlxuICAgKiBDbG9zZXMgdGhlIGNvbm5lY3Rpb24gdG8gZWFjaCBzZXJ2ZXIsIG5vdGlmeWluZyB0aGVtIG9mIHRoaXMgaW50ZW50aW9uLiBOb3RlXG4gICAqIHRoYXQgcXVpdCBjYW4gcmFjZSBhZ2FpbnN0IGFscmVhZHkgb3V0c3RhbmRpbmcgcmVxdWVzdHMgd2hlbiB0aG9zZSByZXF1ZXN0c1xuICAgKiBmYWlsIGFuZCBhcmUgcmV0cmllZCwgbGVhZGluZyB0byB0aGUgcXVpdCBjb21tYW5kIHdpbm5pbmcgYW5kIGNsb3NpbmcgdGhlXG4gICAqIGNvbm5lY3Rpb24gYmVmb3JlIHRoZSByZXRyaWVzIGNvbXBsZXRlLlxuICAgKi9cbiAgcXVpdCgpIHtcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICAvLyBUT0RPOiBOaWNlciBwZXJoYXBzIHRvIGRvIFFVSVRRICgweDE3KSBidXQgbmVlZCBhIG5ldyBjYWxsYmFjayBmb3Igd2hlblxuICAgIC8vIHdyaXRlIGlzIGRvbmUuXG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKDB4MDcsIFwiXCIsIFwiXCIsIFwiXCIsIHRoaXMuc2VxKTsgLy8gUVVJVFxuICAgIGxldCBzZXJ2O1xuXG4gICAgY29uc3QgaGFuZGxlUXVpdCA9IGZ1bmN0aW9uIChzZXE6IG51bWJlciwgc2VydjogU2VydmVyKSB7XG4gICAgICBzZXJ2Lm9uUmVzcG9uc2Uoc2VxLCBmdW5jdGlvbiAoLyogcmVzcG9uc2UgKi8pIHtcbiAgICAgICAgc2Vydi5jbG9zZSgpO1xuICAgICAgfSk7XG4gICAgICBzZXJ2Lm9uRXJyb3Ioc2VxLCBmdW5jdGlvbiAoLyogZXJyICovKSB7XG4gICAgICAgIHNlcnYuY2xvc2UoKTtcbiAgICAgIH0pO1xuICAgICAgc2Vydi53cml0ZShyZXF1ZXN0KTtcbiAgICB9O1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnNlcnZlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHNlcnYgPSB0aGlzLnNlcnZlcnNbaV07XG4gICAgICBoYW5kbGVRdWl0KHRoaXMuc2VxLCBzZXJ2KTtcbiAgICB9XG4gIH1cblxuICBfdmVyc2lvbihzZXJ2ZXI6IFNlcnZlcik6IFByb21pc2U8eyB2YWx1ZTogVmFsdWUgfCBudWxsIH0+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICAgIGNvbnN0YW50cy5PUF9WRVJTSU9OLFxuICAgICAgICBcIlwiLFxuICAgICAgICBcIlwiLFxuICAgICAgICBcIlwiLFxuICAgICAgICB0aGlzLnNlcVxuICAgICAgKTtcbiAgICAgIHRoaXMucGVyZm9ybU9uU2VydmVyKHNlcnZlciwgcmVxdWVzdCwgdGhpcy5zZXEsIChlcnIsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICByZXR1cm4gcmVqZWN0KGVycik7XG4gICAgICAgIH1cblxuICAgICAgICBzd2l0Y2ggKHJlc3BvbnNlIS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICAgICAgLyogVE9ETzogdGhpcyBpcyBidWdnZWQsIHdlIHNob3VsZCd0IHVzZSB0aGUgZGVzZXJpYWxpemVyIGhlcmUsIHNpbmNlIHZlcnNpb24gYWx3YXlzIHJldHVybnMgYSB2ZXJzaW9uIHN0cmluZy5cbiAgICAgICAgICAgICBUaGUgZGVzZXJpYWxpemVyIHNob3VsZCBvbmx5IGJlIHVzZWQgb24gdXNlciBrZXkgZGF0YS4gKi9cbiAgICAgICAgICAgIGNvbnN0IGRlc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5kZXNlcmlhbGl6ZShcbiAgICAgICAgICAgICAgcmVzcG9uc2UhLmhlYWRlci5vcGNvZGUsXG4gICAgICAgICAgICAgIHJlc3BvbnNlIS52YWwsXG4gICAgICAgICAgICAgIHJlc3BvbnNlIS5leHRyYXNcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICByZXR1cm4gcmVzb2x2ZSh7IHZhbHVlOiBkZXNlcmlhbGl6ZWQudmFsdWUgfSk7XG4gICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHJldHVybiByZWplY3QoXG4gICAgICAgICAgICAgIHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJWRVJTSU9OXCIsIHJlc3BvbnNlIS5oZWFkZXIuc3RhdHVzKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmVxdWVzdCB0aGUgc2VydmVyIHZlcnNpb24gZnJvbSB0aGUgXCJmaXJzdFwiIHNlcnZlciBpbiB0aGUgYmFja2VuZCBwb29sLlxuICAgKiBUaGUgc2VydmVyIHJlc3BvbmRzIHdpdGggYSBwYWNrZXQgY29udGFpbmluZyB0aGUgdmVyc2lvbiBzdHJpbmcgaW4gdGhlIGJvZHkgd2l0aCB0aGUgZm9sbG93aW5nIGZvcm1hdDogXCJ4LnkuelwiXG4gICAqL1xuICB2ZXJzaW9uKCk6IFByb21pc2U8eyB2YWx1ZTogVmFsdWUgfCBudWxsIH0+IHtcbiAgICBjb25zdCBzZXJ2ZXIgPSB0aGlzLnNlcnZlcktleVRvU2VydmVyKHRoaXMuc2VydmVyS2V5c1swXSk7XG4gICAgcmV0dXJuIHRoaXMuX3ZlcnNpb24oc2VydmVyKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXRyaWV2ZXMgdGhlIHNlcnZlciB2ZXJzaW9uIGZyb20gYWxsIHRoZSBzZXJ2ZXJzXG4gICAqIGluIHRoZSBiYWNrZW5kIHBvb2wsIGVycm9ycyBpZiBhbnkgb25lIG9mIHRoZW0gaGFzIGFuXG4gICAqIGVycm9yXG4gICAqXG4gICAqIENhbGxiYWNrcyBmdW5jdGlvbnMgYXJlIGNhbGxlZCBiZWZvcmUvYWZ0ZXIgd2UgcGluZyBtZW1jYWNoZWRcbiAgICogYW5kIHVzZWQgdG8gbG9nIHdoaWNoIGhvc3RzIGFyZSB0aW1pbmcgb3V0LlxuICAgKi9cbiAgYXN5bmMgdmVyc2lvbkFsbChjYWxsYmFja3M/OiB7XG4gICAgYmVmb3JlUGluZz86IChzZXJ2ZXJLZXk6IHN0cmluZykgPT4gdm9pZDtcbiAgICBhZnRlclBpbmc/OiAoc2VydmVyS2V5OiBzdHJpbmcpID0+IHZvaWQ7XG4gIH0pOiBQcm9taXNlPHtcbiAgICB2YWx1ZXM6IFJlY29yZDxzdHJpbmcsIFZhbHVlIHwgbnVsbD47XG4gIH0+IHtcbiAgICBjb25zdCB2ZXJzaW9uT2JqZWN0cyA9IGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgdGhpcy5zZXJ2ZXJLZXlzLm1hcCgoc2VydmVyS2V5KSA9PiB7XG4gICAgICAgIGNvbnN0IHNlcnZlciA9IHRoaXMuc2VydmVyS2V5VG9TZXJ2ZXIoc2VydmVyS2V5KTtcbiAgICAgICAgY2FsbGJhY2tzPy5iZWZvcmVQaW5nPy4oc2VydmVyS2V5KTtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3ZlcnNpb24oc2VydmVyKS50aGVuKChyZXNwb25zZSkgPT4ge1xuICAgICAgICAgIGNhbGxiYWNrcz8uYWZ0ZXJQaW5nPy4oc2VydmVyS2V5KTtcbiAgICAgICAgICByZXR1cm4geyBzZXJ2ZXJLZXk6IHNlcnZlcktleSwgdmFsdWU6IHJlc3BvbnNlLnZhbHVlIH07XG4gICAgICAgIH0pO1xuICAgICAgfSlcbiAgICApO1xuICAgIGNvbnN0IHZhbHVlcyA9IHZlcnNpb25PYmplY3RzLnJlZHVjZSgoYWNjdW11bGF0b3IsIHZlcnNpb25PYmplY3QpID0+IHtcbiAgICAgIGFjY3VtdWxhdG9yW3ZlcnNpb25PYmplY3Quc2VydmVyS2V5XSA9IHZlcnNpb25PYmplY3QudmFsdWU7XG4gICAgICByZXR1cm4gYWNjdW11bGF0b3I7XG4gICAgfSwge30gYXMgUmVjb3JkPHN0cmluZywgVmFsdWUgfCBudWxsPik7XG4gICAgcmV0dXJuIHsgdmFsdWVzOiB2YWx1ZXMgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDbG9zZXMgKGFicnVwdGx5KSBjb25uZWN0aW9ucyB0byBhbGwgdGhlIHNlcnZlcnMuXG4gICAqIEBzZWUgdGhpcy5xdWl0XG4gICAqL1xuICBjbG9zZSgpIHtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuc2VydmVycy5sZW5ndGg7IGkrKykge1xuICAgICAgdGhpcy5zZXJ2ZXJzW2ldLmNsb3NlKCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFBlcmZvcm0gYSBnZW5lcmljIHNpbmdsZSByZXNwb25zZSBvcGVyYXRpb24gKGdldCwgc2V0IGV0Yykgb24gb25lIHNlcnZlclxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IHRoZSBrZXkgdG8gaGFzaCB0byBnZXQgYSBzZXJ2ZXIgZnJvbSB0aGUgcG9vbFxuICAgKiBAcGFyYW0ge2J1ZmZlcn0gcmVxdWVzdCBhIGJ1ZmZlciBjb250YWluaW5nIHRoZSByZXF1ZXN0XG4gICAqIEBwYXJhbSB7bnVtYmVyfSBzZXEgdGhlIHNlcXVlbmNlIG51bWJlciBvZiB0aGUgb3BlcmF0aW9uLiBJdCBpcyB1c2VkIHRvIHBpbiB0aGUgY2FsbGJhY2tzXG4gICAgICAgICAgICAgICAgICAgICAgICAgdG8gYSBzcGVjaWZpYyBvcGVyYXRpb24gYW5kIHNob3VsZCBuZXZlciBjaGFuZ2UgZHVyaW5nIGEgYHBlcmZvcm1gLlxuICAgKiBAcGFyYW0ge251bWJlcj99IHJldHJpZXMgbnVtYmVyIG9mIHRpbWVzIHRvIHJldHJ5IHJlcXVlc3Qgb24gZmFpbHVyZVxuICAgKi9cbiAgcGVyZm9ybShcbiAgICBrZXk6IHN0cmluZyxcbiAgICByZXF1ZXN0OiBCdWZmZXIsXG4gICAgc2VxOiBudW1iZXIsXG4gICAgcmV0cmllcz86IG51bWJlclxuICApOiBQcm9taXNlPE1lc3NhZ2U+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgY29uc3Qgc2VydmVyS2V5ID0gdGhpcy5sb29rdXBLZXlUb1NlcnZlcktleShrZXkpO1xuICAgICAgY29uc3Qgc2VydmVyID0gdGhpcy5zZXJ2ZXJLZXlUb1NlcnZlcihzZXJ2ZXJLZXkpO1xuXG4gICAgICBpZiAoIXNlcnZlcikge1xuICAgICAgICByZXR1cm4gcmVqZWN0KG5ldyBFcnJvcihcIk5vIHNlcnZlcnMgYXZhaWxhYmxlXCIpKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5wZXJmb3JtT25TZXJ2ZXIoXG4gICAgICAgIHNlcnZlcixcbiAgICAgICAgcmVxdWVzdCxcbiAgICAgICAgc2VxLFxuICAgICAgICAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICByZXR1cm4gcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmVzb2x2ZShyZXNwb25zZSEpO1xuICAgICAgICB9LFxuICAgICAgICByZXRyaWVzXG4gICAgICApO1xuICAgIH0pO1xuICB9XG5cbiAgcGVyZm9ybU9uU2VydmVyKFxuICAgIHNlcnZlcjogU2VydmVyLFxuICAgIHJlcXVlc3Q6IEJ1ZmZlcixcbiAgICBzZXE6IG51bWJlcixcbiAgICBjYWxsYmFjazogUmVzcG9uc2VPckVycm9yQ2FsbGJhY2ssXG4gICAgcmV0cmllczogbnVtYmVyID0gMFxuICApIHtcbiAgICBjb25zdCBfdGhpcyA9IHRoaXM7XG5cbiAgICByZXRyaWVzID0gcmV0cmllcyB8fCB0aGlzLm9wdGlvbnMucmV0cmllcztcbiAgICBjb25zdCBvcmlnUmV0cmllcyA9IHRoaXMub3B0aW9ucy5yZXRyaWVzO1xuICAgIGNvbnN0IGxvZ2dlciA9IHRoaXMub3B0aW9ucy5sb2dnZXI7XG4gICAgY29uc3QgcmV0cnlfZGVsYXkgPSB0aGlzLm9wdGlvbnMucmV0cnlfZGVsYXk7XG5cbiAgICBjb25zdCByZXNwb25zZUhhbmRsZXI6IE9uUmVzcG9uc2VDYWxsYmFjayA9IGZ1bmN0aW9uIChyZXNwb25zZSkge1xuICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgIGNhbGxiYWNrKG51bGwsIHJlc3BvbnNlKTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgY29uc3QgZXJyb3JIYW5kbGVyOiBPbkVycm9yQ2FsbGJhY2sgPSBmdW5jdGlvbiAoZXJyb3IpIHtcbiAgICAgIGlmICgtLXJldHJpZXMgPiAwKSB7XG4gICAgICAgIC8vIFdhaXQgZm9yIHJldHJ5X2RlbGF5XG4gICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgIF90aGlzLnBlcmZvcm1PblNlcnZlcihzZXJ2ZXIsIHJlcXVlc3QsIHNlcSwgY2FsbGJhY2ssIHJldHJpZXMpO1xuICAgICAgICB9LCAxMDAwICogcmV0cnlfZGVsYXkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbG9nZ2VyLmxvZyhcbiAgICAgICAgICBcIk1lbUpTOiBTZXJ2ZXIgPFwiICtcbiAgICAgICAgICAgIHNlcnZlci5ob3N0cG9ydFN0cmluZygpICtcbiAgICAgICAgICAgIFwiPiBmYWlsZWQgYWZ0ZXIgKFwiICtcbiAgICAgICAgICAgIG9yaWdSZXRyaWVzICtcbiAgICAgICAgICAgIFwiKSByZXRyaWVzIHdpdGggZXJyb3IgLSBcIiArXG4gICAgICAgICAgICBlcnJvci5tZXNzYWdlXG4gICAgICAgICk7XG4gICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgIGNhbGxiYWNrKGVycm9yLCBudWxsKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH07XG5cbiAgICBzZXJ2ZXIub25SZXNwb25zZShzZXEsIHJlc3BvbnNlSGFuZGxlcik7XG4gICAgc2VydmVyLm9uRXJyb3Ioc2VxLCBlcnJvckhhbmRsZXIpO1xuICAgIHNlcnZlci53cml0ZShyZXF1ZXN0KTtcbiAgfVxuXG4gIC8vIEluY3JlbWVudCB0aGUgc2VxIHZhbHVlXG4gIGluY3JTZXEoKSB7XG4gICAgdGhpcy5zZXErKztcblxuICAgIC8vIFdyYXAgYHRoaXMuc2VxYCB0byAzMi1iaXRzIHNpbmNlIHRoZSBmaWVsZCB3ZSBmaXQgaXQgaW50byBpcyBvbmx5IDMyLWJpdHMuXG4gICAgdGhpcy5zZXEgJj0gMHhmZmZmZmZmZjtcblxuICAgIHJldHVybiB0aGlzLnNlcTtcbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlQW5kTG9nRXJyb3IoXG4gICAgY29tbWFuZE5hbWU6IHN0cmluZyxcbiAgICByZXNwb25zZVN0YXR1czogUmVzcG9uc2VTdGF0dXMgfCB1bmRlZmluZWRcbiAgKTogRXJyb3Ige1xuICAgIGNvbnN0IGVycm9yTWVzc2FnZSA9IGBNZW1KUyAke2NvbW1hbmROYW1lfTogJHtjb25zdGFudHMucmVzcG9uc2VTdGF0dXNUb1N0cmluZyhcbiAgICAgIHJlc3BvbnNlU3RhdHVzXG4gICAgKX1gO1xuICAgIHRoaXMub3B0aW9ucy5sb2dnZXIubG9nKGVycm9yTWVzc2FnZSk7XG4gICAgcmV0dXJuIG5ldyBFcnJvcihlcnJvck1lc3NhZ2UpO1xuICB9XG5cbiAgLyoqXG4gICAqIExvZyBhbiBlcnJvciB0byB0aGUgbG9nZ2VyLCB0aGVuIHJldHVybiB0aGUgZXJyb3IuXG4gICAqIElmIGEgY2FsbGJhY2sgaXMgZ2l2ZW4sIGNhbGwgaXQgd2l0aCBjYWxsYmFjayhlcnJvciwgbnVsbCkuXG4gICAqL1xuICBwcml2YXRlIGhhbmRsZVJlc3BvbnNlRXJyb3IoXG4gICAgY29tbWFuZE5hbWU6IHN0cmluZyxcbiAgICByZXNwb25zZVN0YXR1czogUmVzcG9uc2VTdGF0dXMgfCB1bmRlZmluZWQsXG4gICAgY2FsbGJhY2s6IHVuZGVmaW5lZCB8ICgoZXJyb3I6IEVycm9yIHwgbnVsbCwgb3RoZXI6IG51bGwpID0+IHZvaWQpXG4gICk6IEVycm9yIHtcbiAgICBjb25zdCBlcnJvciA9IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoY29tbWFuZE5hbWUsIHJlc3BvbnNlU3RhdHVzKTtcbiAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgIGNhbGxiYWNrKGVycm9yLCBudWxsKTtcbiAgICB9XG4gICAgcmV0dXJuIGVycm9yO1xuICB9XG59XG5cbmV4cG9ydCB7IENsaWVudCwgU2VydmVyLCBVdGlscywgSGVhZGVyIH07XG4iXX0= \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVtanMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbWVtanMvbWVtanMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLHdCQUF3Qjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUV4QixxQ0FLa0I7QUEyaUNELHVGQTdpQ2YsZUFBTSxPQTZpQ2U7QUExaUN2Qix1REFBK0Q7QUFDL0QsbUNBU2lCO0FBQ2pCLHVEQUF5QztBQUN6QywyQ0FBNkM7QUFDN0MsK0NBQWlDO0FBNmhDUixzQkFBSztBQTVoQzlCLGlEQUFtQztBQTRoQ0gsd0JBQU07QUExaEN0QyxTQUFTLDhCQUE4QixDQUNyQyxPQUFpQixFQUNqQixHQUFXO0lBRVgsTUFBTSxLQUFLLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQztJQUM3QixNQUFNLEtBQUssR0FBRyxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxnQkFBUSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3BELE9BQU8sT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ3hCLENBQUM7QUFFRCwrQ0FBK0M7QUFDL0MsU0FBUyxTQUFTLENBQ2hCLE9BQTBFO0lBRTFFLE9BQU8sSUFBSSxPQUFPLENBQUMsVUFBVSxPQUFPLEVBQUUsTUFBTTtRQUMxQyxPQUFPLENBQUMsVUFBVSxHQUFHLEVBQUUsTUFBTTtZQUMzQixHQUFHLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3RDLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBeURELE1BQU0sTUFBTTtJQVFWLDRFQUE0RTtJQUM1RSxtQ0FBbUM7SUFDbkMsWUFBWSxPQUFpQixFQUFFLE9BQTBDO1FBQ3ZFLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO1FBQ3ZCLElB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QUFtQixFQUNuQixjQUEwQztRQUUxQyxNQUFNLFlBQVksR0FBRyxTQUFTLFdBQVcsS0FBSyxTQUFTLENBQUMsc0JBQXNCLENBQzVFLGNBQWMsQ0FDZixFQUFFLENBQUM7UUFDSixJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDdEMsT0FBTyxJQUFJLEtBQUssQ0FBQyxZQUFZLENBQUMsQ0FBQztJQUNqQyxDQUFDO0lBRUQ7OztPQUdHO0lBQ0ssbUJBQW1CLENBQ3pCLFdBQW1CLEVBQ25CLGNBQTBDLEVBQzFDLFFBQWtFO1FBRWxFLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxXQUFXLEVBQUUsY0FBYyxDQUFDLENBQUM7UUFDbEUsSUFBSSxRQUFRLEVBQUU7WUFDWixRQUFRLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxDQUFDO1NBQ3ZCO1FBQ0QsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0NBQ0Y7QUFFUSx3QkFBTSIsInNvdXJjZXNDb250ZW50IjpbIi8vIE1lbVRTIE1lbWNhY2hlIENsaWVudFxuXG5pbXBvcnQge1xuICBPbkVycm9yQ2FsbGJhY2ssXG4gIE9uUmVzcG9uc2VDYWxsYmFjayxcbiAgU2VydmVyLFxuICBTZXJ2ZXJPcHRpb25zLFxufSBmcm9tIFwiLi9zZXJ2ZXJcIjtcbmltcG9ydCB7IG5vb3BTZXJpYWxpemVyLCBTZXJpYWxpemVyIH0gZnJvbSBcIi4vbm9vcC1zZXJpYWxpemVyXCI7XG5pbXBvcnQge1xuICBtYWtlUmVxdWVzdEJ1ZmZlcixcbiAgY29weUludG9SZXF1ZXN0QnVmZmVyLFxuICBtZXJnZSxcbiAgbWFrZUV4cGlyYXRpb24sXG4gIG1ha2VBbW91bnRJbml0aWFsQW5kRXhwaXJhdGlvbixcbiAgaGFzaENvZGUsXG4gIE1heWJlQnVmZmVyLFxuICBNZXNzYWdlLFxufSBmcm9tIFwiLi91dGlsc1wiO1xuaW1wb3J0ICogYXMgY29uc3RhbnRzIGZyb20gXCIuL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgUmVzcG9uc2VTdGF0dXMgfSBmcm9tIFwiLi9jb25zdGFudHNcIjtcbmltcG9ydCAqIGFzIFV0aWxzIGZyb20gXCIuL3V0aWxzXCI7XG5pbXBvcnQgKiBhcyBIZWFkZXIgZnJvbSBcIi4vaGVhZGVyXCI7XG5cbmZ1bmN0aW9uIGRlZmF1bHRLZXlUb1NlcnZlckhhc2hGdW5jdGlvbihcbiAgc2VydmVyczogc3RyaW5nW10sXG4gIGtleTogc3RyaW5nXG4pOiBzdHJpbmcge1xuICBjb25zdCB0b3RhbCA9IHNlcnZlcnMubGVuZ3RoO1xuICBjb25zdCBpbmRleCA9IHRvdGFsID4gMSA/IGhhc2hDb2RlKGtleSkgJSB0b3RhbCA6IDA7XG4gIHJldHVybiBzZXJ2ZXJzW2luZGV4XTtcbn1cblxuLy8gY29udmVydHMgYSBjYWxsIGludG8gYSBwcm9taXNlLXJldHVybmluZyBvbmVcbmZ1bmN0aW9uIHByb21pc2lmeTxSZXN1bHQ+KFxuICBjb21tYW5kOiAoY2FsbGJhY2s6IChlcnJvcjogRXJyb3IgfCBudWxsLCByZXN1bHQ6IFJlc3VsdCkgPT4gdm9pZCkgPT4gdm9pZFxuKTogUHJvbWlzZTxSZXN1bHQ+IHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICBjb21tYW5kKGZ1bmN0aW9uIChlcnIsIHJlc3VsdCkge1xuICAgICAgZXJyID8gcmVqZWN0KGVycikgOiByZXNvbHZlKHJlc3VsdCk7XG4gICAgfSk7XG4gIH0pO1xufVxuXG50eXBlIFJlc3BvbnNlT3JFcnJvckNhbGxiYWNrID0gKFxuICBlcnJvcjogRXJyb3IgfCBudWxsLFxuICByZXNwb25zZTogTWVzc2FnZSB8IG51bGxcbikgPT4gdm9pZDtcblxuaW50ZXJmYWNlIEJhc2VDbGllbnRPcHRpb25zIHtcbiAgcmV0cmllczogbnVtYmVyO1xuICByZXRyeV9kZWxheTogbnVtYmVyO1xuICBleHBpcmVzOiBudW1iZXI7XG4gIGxvZ2dlcjogeyBsb2c6IHR5cGVvZiBjb25zb2xlLmxvZyB9O1xuICBrZXlUb1NlcnZlckhhc2hGdW5jdGlvbjogdHlwZW9mIGRlZmF1bHRLZXlUb1NlcnZlckhhc2hGdW5jdGlvbjtcbn1cblxuaW50ZXJmYWNlIFNlcmlhbGl6ZXJQcm9wPFZhbHVlLCBFeHRyYXM+IHtcbiAgc2VyaWFsaXplcjogU2VyaWFsaXplcjxWYWx1ZSwgRXh0cmFzPjtcbn1cblxuLyoqXG4gKiBUaGUgY2xpZW50IGhhcyBwYXJ0aWFsIHN1cHBvcnQgZm9yIHNlcmlhbGl6aW5nIGFuZCBkZXNlcmlhbGl6aW5nIHZhbHVlcyBmcm9tIHRoZVxuICogQnVmZmVyIGJ5dGUgc3RyaW5ncyB3ZSByZWNlaXZlIGZyb20gdGhlIHdpcmUuIFRoZSBkZWZhdWx0IHNlcmlhbGl6ZXIgaXMgZm9yIE1heWJlQnVmZmVyLlxuICpcbiAqIElmIFZhbHVlIGFuZCBFeHRyYXMgYXJlIG9mIHR5cGUgQnVmZmVyLCB0aGVuIHJldHVybiB0eXBlIFdoZW5CdWZmZXIuIE90aGVyd2lzZSxcbiAqIHJldHVybiB0eXBlIE5vdEJ1ZmZlci5cbiAqL1xudHlwZSBJZkJ1ZmZlcjxWYWx1ZSwgRXh0cmFzLCBXaGVuVmFsdWVBbmRFeHRyYXNBcmVCdWZmZXJzLCBOb3RCdWZmZXI+ID1cbiAgVmFsdWUgZXh0ZW5kcyBCdWZmZXJcbiAgICA/IEV4dHJhcyBleHRlbmRzIEJ1ZmZlclxuICAgICAgPyBXaGVuVmFsdWVBbmRFeHRyYXNBcmVCdWZmZXJzXG4gICAgICA6IE5vdEJ1ZmZlclxuICAgIDogTm90QnVmZmVyO1xuXG5leHBvcnQgdHlwZSBHaXZlbkNsaWVudE9wdGlvbnM8VmFsdWUsIEV4dHJhcz4gPSBQYXJ0aWFsPEJhc2VDbGllbnRPcHRpb25zPiAmXG4gIElmQnVmZmVyPFxuICAgIFZhbHVlLFxuICAgIEV4dHJhcyxcbiAgICBQYXJ0aWFsPFNlcmlhbGl6ZXJQcm9wPFZhbHVlLCBFeHRyYXM+PixcbiAgICBTZXJpYWxpemVyUHJvcDxWYWx1ZSwgRXh0cmFzPlxuICA+O1xuXG5leHBvcnQgdHlwZSBDQVNUb2tlbiA9IEJ1ZmZlcjtcblxuZXhwb3J0IGludGVyZmFjZSBHZXRSZXN1bHQ8VmFsdWUgPSBNYXliZUJ1ZmZlciwgRXh0cmFzID0gTWF5YmVCdWZmZXI+IHtcbiAgdmFsdWU6IFZhbHVlO1xuICBleHRyYXM6IEV4dHJhcztcbiAgY2FzOiBDQVNUb2tlbiB8IHVuZGVmaW5lZDtcbn1cblxuZXhwb3J0IHR5cGUgR2V0TXVsdGlSZXN1bHQ8XG4gIEtleXMgZXh0ZW5kcyBzdHJpbmcgPSBzdHJpbmcsXG4gIFZhbHVlID0gTWF5YmVCdWZmZXIsXG4gIEV4dHJhcyA9IE1heWJlQnVmZmVyXG4+ID0ge1xuICBbSyBpbiBLZXlzXT86IEdldFJlc3VsdDxWYWx1ZSwgRXh0cmFzPjtcbn07XG5cbmNsYXNzIENsaWVudDxWYWx1ZSA9IE1heWJlQnVmZmVyLCBFeHRyYXMgPSBNYXliZUJ1ZmZlcj4ge1xuICBzZXJ2ZXJzOiBTZXJ2ZXJbXTtcbiAgc2VxOiBudW1iZXI7XG4gIG9wdGlvbnM6IEJhc2VDbGllbnRPcHRpb25zICYgUGFydGlhbDxTZXJpYWxpemVyUHJvcDxWYWx1ZSwgRXh0cmFzPj47XG4gIHNlcmlhbGl6ZXI6IFNlcmlhbGl6ZXI8VmFsdWUsIEV4dHJhcz47XG4gIHNlcnZlck1hcDogeyBbaG9zdHBvcnQ6IHN0cmluZ106IFNlcnZlciB9O1xuICBzZXJ2ZXJLZXlzOiBzdHJpbmdbXTtcblxuICAvLyBDbGllbnQgaW5pdGlhbGl6ZXIgdGFrZXMgYSBsaXN0IG9mIGBTZXJ2ZXJgcyBhbmQgYW4gYG9wdGlvbnNgIGRpY3Rpb25hcnkuXG4gIC8vIFNlZSBgQ2xpZW50LmNyZWF0ZWAgZm9yIGRldGFpbHMuXG4gIGNvbnN0cnVjdG9yKHNlcnZlcnM6IFNlcnZlcltdLCBvcHRpb25zOiBHaXZlbkNsaWVudE9wdGlvbnM8VmFsdWUsIEV4dHJhcz4pIHtcbiAgICB0aGlzLnNlcnZlcnMgPSBzZXJ2ZXJzO1xuICAgIHRoaXMuc2VxID0gMDtcbiAgICB0aGlzLm9wdGlvbnMgPSBtZXJnZShvcHRpb25zIHx8IHt9LCB7XG4gICAgICByZXRyaWVzOiAyLFxuICAgICAgcmV0cnlfZGVsYXk6IDAuMixcbiAgICAgIGV4cGlyZXM6IDAsXG4gICAgICBsb2dnZXI6IGNvbnNvbGUsXG4gICAgICBrZXlUb1NlcnZlckhhc2hGdW5jdGlvbjogZGVmYXVsdEtleVRvU2VydmVySGFzaEZ1bmN0aW9uLFxuICAgIH0pO1xuXG4gICAgdGhpcy5zZXJpYWxpemVyID0gdGhpcy5vcHRpb25zLnNlcmlhbGl6ZXIgfHwgKG5vb3BTZXJpYWxpemVyIGFzIGFueSk7XG5cbiAgICAvLyBTdG9yZSBhIG1hcHBpbmcgZnJvbSBob3N0cG9ydCAtPiBzZXJ2ZXIgc28gd2UgY2FuIHF1aWNrbHkgZ2V0IGEgc2VydmVyIG9iamVjdCBmcm9tIHRoZSBzZXJ2ZXJLZXkgcmV0dXJuZWQgYnkgdGhlIGhhc2hpbmcgZnVuY3Rpb25cbiAgICBjb25zdCBzZXJ2ZXJNYXA6IHsgW2hvc3Rwb3J0OiBzdHJpbmddOiBTZXJ2ZXIgfSA9IHt9O1xuICAgIHRoaXMuc2VydmVycy5mb3JFYWNoKGZ1bmN0aW9uIChzZXJ2ZXIpIHtcbiAgICAgIHNlcnZlck1hcFtzZXJ2ZXIuaG9zdHBvcnRTdHJpbmcoKV0gPSBzZXJ2ZXI7XG4gICAgfSk7XG4gICAgdGhpcy5zZXJ2ZXJNYXAgPSBzZXJ2ZXJNYXA7XG5cbiAgICAvLyBzdG9yZSBhIGxpc3Qgb2YgYWxsIG91ciBzZXJ2ZXJLZXlzIHNvIHdlIGRvbid0IG5lZWQgdG8gY29uc3RhbnRseSByZWFsbG9jYXRlIHRoaXMgYXJyYXlcbiAgICB0aGlzLnNlcnZlcktleXMgPSBPYmplY3Qua2V5cyh0aGlzLnNlcnZlck1hcCk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIG5ldyBjbGllbnQgZ2l2ZW4gYW4gb3B0aW9uYWwgY29uZmlnIHN0cmluZyBhbmQgb3B0aW9uYWwgaGFzaCBvZlxuICAgKiBvcHRpb25zLiBUaGUgY29uZmlnIHN0cmluZyBzaG91bGQgYmUgb2YgdGhlIGZvcm06XG4gICAqXG4gICAqICAgICBcIlt1c2VyOnBhc3NAXXNlcnZlcjFbOjExMjExXSxbdXNlcjpwYXNzQF1zZXJ2ZXIyWzoxMTIxMV0sLi4uXCJcbiAgICpcbiAgICogSWYgdGhlIGFyZ3VtZW50IGlzIG5vdCBnaXZlbiwgZmFsbGJhY2sgb24gdGhlIGBNRU1DQUNISUVSX1NFUlZFUlNgIGVudmlyb25tZW50XG4gICAqIHZhcmlhYmxlLCBgTUVNQ0FDSEVfU0VSVkVSU2AgZW52aXJvbm1lbnQgdmFyaWFibGUgb3IgYFwibG9jYWxob3N0OjExMjExXCJgLlxuICAgKlxuICAgKiBUaGUgb3B0aW9ucyBoYXNoIG1heSBjb250YWluIHRoZSBvcHRpb25zOlxuICAgKlxuICAgKiAqIGByZXRyaWVzYCAtIHRoZSBudW1iZXIgb2YgdGltZXMgdG8gcmV0cnkgYW4gb3BlcmF0aW9uIGluIGxpZXUgb2YgZmFpbHVyZXNcbiAgICogKGRlZmF1bHQgMilcbiAgICogKiBgZXhwaXJlc2AgLSB0aGUgZGVmYXVsdCBleHBpcmF0aW9uIGluIHNlY29uZHMgdG8gdXNlIChkZWZhdWx0IDAgLSBuZXZlclxuICAgKiBleHBpcmUpLiBJZiBgZXhwaXJlc2AgaXMgZ3JlYXRlciB0aGFuIDMwIGRheXMgKDYwIHggNjAgeCAyNCB4IDMwKSwgaXQgaXNcbiAgICogdHJlYXRlZCBhcyBhIFVOSVggdGltZSAobnVtYmVyIG9mIHNlY29uZHMgc2luY2UgSmFudWFyeSAxLCAxOTcwKS5cbiAgICogKiBgbG9nZ2VyYCAtIGEgbG9nZ2VyIG9iamVjdCB0aGF0IHJlc3BvbmRzIHRvIGBsb2coc3RyaW5nKWAgbWV0aG9kIGNhbGxzLlxuICAgKlxuICAgKiAgIH5+fn5cbiAgICogICAgIGxvZyhtc2cxWywgbXNnMlssIG1zZzNbLi4uXV1dKVxuICAgKiAgIH5+fn5cbiAgICpcbiAgICogICBEZWZhdWx0cyB0byBgY29uc29sZWAuXG4gICAqICogYHNlcmlhbGl6ZXJgIC0gdGhlIG9iamVjdCB3aGljaCB3aWxsIChkZSlzZXJpYWxpemUgdGhlIGRhdGEuIEl0IG5lZWRzXG4gICAqICAgdHdvIHB1YmxpYyBtZXRob2RzOiBzZXJpYWxpemUgYW5kIGRlc2VyaWFsaXplLiBJdCBkZWZhdWx0cyB0byB0aGVcbiAgICogICBub29wU2VyaWFsaXplcjpcbiAgICpcbiAgICogICB+fn5+XG4gICAqICAgY29uc3Qgbm9vcFNlcmlhbGl6ZXIgPSB7XG4gICAqICAgICBzZXJpYWxpemU6IGZ1bmN0aW9uIChvcGNvZGUsIHZhbHVlLCBleHRyYXMpIHtcbiAgICogICAgICAgcmV0dXJuIHsgdmFsdWU6IHZhbHVlLCBleHRyYXM6IGV4dHJhcyB9O1xuICAgKiAgICAgfSxcbiAgICogICAgIGRlc2VyaWFsaXplOiBmdW5jdGlvbiAob3Bjb2RlLCB2YWx1ZSwgZXh0cmFzKSB7XG4gICAqICAgICAgIHJldHVybiB7IHZhbHVlOiB2YWx1ZSwgZXh0cmFzOiBleHRyYXMgfTtcbiAgICogICAgIH1cbiAgICogICB9O1xuICAgKiAgIH5+fn5cbiAgICpcbiAgICogT3Igb3B0aW9ucyBmb3IgdGhlIHNlcnZlcnMgaW5jbHVkaW5nOlxuICAgKiAqIGB1c2VybmFtZWAgYW5kIGBwYXNzd29yZGAgZm9yIGZhbGxiYWNrIFNBU0wgYXV0aGVudGljYXRpb24gY3JlZGVudGlhbHMuXG4gICAqICogYHRpbWVvdXRgIGluIHNlY29uZHMgdG8gZGV0ZXJtaW5lIGZhaWx1cmUgZm9yIG9wZXJhdGlvbnMuIERlZmF1bHQgaXMgMC41XG4gICAqICAgICAgICAgICAgIHNlY29uZHMuXG4gICAqICogJ2Nvbm50aW1lb3V0JyBpbiBzZWNvbmRzIHRvIGNvbm5lY3Rpb24gZmFpbHVyZS4gRGVmYXVsdCBpcyB0d2ljZSB0aGUgdmFsdWVcbiAgICogICAgICAgICAgICAgICAgIG9mIGB0aW1lb3V0YC5cbiAgICogKiBga2VlcEFsaXZlYCB3aGV0aGVyIHRvIGVuYWJsZSBrZWVwLWFsaXZlIGZ1bmN0aW9uYWxpdHkuIERlZmF1bHRzIHRvIGZhbHNlLlxuICAgKiAqIGBrZWVwQWxpdmVEZWxheWAgaW4gc2Vjb25kcyB0byB0aGUgaW5pdGlhbCBkZWxheSBiZWZvcmUgdGhlIGZpcnN0IGtlZXBhbGl2ZVxuICAgKiAgICAgICAgICAgICAgICAgICAgcHJvYmUgaXMgc2VudCBvbiBhbiBpZGxlIHNvY2tldC4gRGVmYXVsdHMgaXMgMzAgc2Vjb25kcy5cbiAgICogKiBga2V5VG9TZXJ2ZXJIYXNoRnVuY3Rpb25gIGEgZnVuY3Rpb24gdG8gbWFwIGtleXMgdG8gc2VydmVycywgd2l0aCB0aGUgc2lnbmF0dXJlXG4gICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgIChzZXJ2ZXJLZXlzOiBzdHJpbmdbXSwga2V5OiBzdHJpbmcpOiBzdHJpbmdcbiAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgTk9URTogaWYgeW91IG5lZWQgdG8gZG8gc29tZSBleHBlbnNpdmUgaW5pdGlhbGl6YXRpb24sICpwbGVhc2UqIGRvIGl0IGxhemlseSB0aGUgZmlyc3QgdGltZSB5b3UgdGhpcyBmdW5jdGlvbiBpcyBjYWxsZWQgd2l0aCBhbiBhcnJheSBvZiBzZXJ2ZXJLZXlzLCBub3Qgb24gZXZlcnkgY2FsbFxuICAgKi9cbiAgc3RhdGljIGNyZWF0ZTxWYWx1ZSwgRXh0cmFzPihcbiAgICBzZXJ2ZXJzU3RyOiBzdHJpbmcgfCB1bmRlZmluZWQsXG4gICAgb3B0aW9uczogSWZCdWZmZXI8XG4gICAgICBWYWx1ZSxcbiAgICAgIEV4dHJhcyxcbiAgICAgIHVuZGVmaW5lZCB8IChQYXJ0aWFsPFNlcnZlck9wdGlvbnM+ICYgR2l2ZW5DbGllbnRPcHRpb25zPFZhbHVlLCBFeHRyYXM+KSxcbiAgICAgIFBhcnRpYWw8U2VydmVyT3B0aW9ucz4gJiBHaXZlbkNsaWVudE9wdGlvbnM8VmFsdWUsIEV4dHJhcz5cbiAgICA+XG4gICk6IENsaWVudDxWYWx1ZSwgRXh0cmFzPiB7XG4gICAgc2VydmVyc1N0ciA9XG4gICAgICBzZXJ2ZXJzU3RyIHx8XG4gICAgICBwcm9jZXNzLmVudi5NRU1DQUNISUVSX1NFUlZFUlMgfHxcbiAgICAgIHByb2Nlc3MuZW52Lk1FTUNBQ0hFX1NFUlZFUlMgfHxcbiAgICAgIFwibG9jYWxob3N0OjExMjExXCI7XG4gICAgY29uc3Qgc2VydmVyVXJpcyA9IHNlcnZlcnNTdHIuc3BsaXQoXCIsXCIpO1xuICAgIGNvbnN0IHNlcnZlcnMgPSBzZXJ2ZXJVcmlzLm1hcChmdW5jdGlvbiAodXJpKSB7XG4gICAgICBjb25zdCB1cmlQYXJ0cyA9IHVyaS5zcGxpdChcIkBcIik7XG4gICAgICBjb25zdCBob3N0UG9ydCA9IHVyaVBhcnRzW3VyaVBhcnRzLmxlbmd0aCAtIDFdLnNwbGl0KFwiOlwiKTtcbiAgICAgIGNvbnN0IHVzZXJQYXNzID0gKHVyaVBhcnRzW3VyaVBhcnRzLmxlbmd0aCAtIDJdIHx8IFwiXCIpLnNwbGl0KFwiOlwiKTtcbiAgICAgIHJldHVybiBuZXcgU2VydmVyKFxuICAgICAgICBob3N0UG9ydFswXSxcbiAgICAgICAgcGFyc2VJbnQoaG9zdFBvcnRbMV0gfHwgXCIxMTIxMVwiLCAxMCksXG4gICAgICAgIHVzZXJQYXNzWzBdLFxuICAgICAgICB1c2VyUGFzc1sxXSxcbiAgICAgICAgb3B0aW9uc1xuICAgICAgKTtcbiAgICB9KTtcbiAgICByZXR1cm4gbmV3IENsaWVudChzZXJ2ZXJzLCBvcHRpb25zIGFzIGFueSk7XG4gIH1cblxuICAvKipcbiAgICogR2l2ZW4gYSBzZXJ2ZXJLZXkgZnJvbWxvb2t1cEtleVRvU2VydmVyS2V5LCByZXR1cm4gdGhlIGNvcnJlc3BvbmRpbmcgU2VydmVyIGluc3RhbmNlXG4gICAqXG4gICAqIEBwYXJhbSAge3N0cmluZ30gc2VydmVyS2V5XG4gICAqIEByZXR1cm5zIHtTZXJ2ZXJ9XG4gICAqL1xuICBzZXJ2ZXJLZXlUb1NlcnZlcihzZXJ2ZXJLZXk6IHN0cmluZyk6IFNlcnZlciB7XG4gICAgcmV0dXJuIHRoaXMuc2VydmVyTWFwW3NlcnZlcktleV07XG4gIH1cblxuICAvKipcbiAgICogR2l2ZW4gYSBrZXkgdG8gbG9vayB1cCBpbiBtZW1jYWNoZSwgcmV0dXJuIGEgc2VydmVyS2V5IChiYXNlZCBvbiBzb21lXG4gICAqIGhhc2hpbmcgZnVuY3Rpb24pIHdoaWNoIGNhbiBiZSB1c2VkIHRvIGluZGV4IHRoaXMuc2VydmVyTWFwXG4gICAqL1xuICBsb29rdXBLZXlUb1NlcnZlcktleShrZXk6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMub3B0aW9ucy5rZXlUb1NlcnZlckhhc2hGdW5jdGlvbih0aGlzLnNlcnZlcktleXMsIGtleSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldmVzIHRoZSB2YWx1ZSBhdCB0aGUgZ2l2ZW4ga2V5IGluIG1lbWNhY2hlLlxuICAgKi9cbiAgYXN5bmMgZ2V0KGtleTogc3RyaW5nKTogUHJvbWlzZTxHZXRSZXN1bHQ8VmFsdWUsIEV4dHJhcz4gfCBudWxsPiB7XG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKGNvbnN0YW50cy5PUF9HRVQsIGtleSwgXCJcIiwgXCJcIiwgdGhpcy5zZXEpO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICBjb25zdCBkZXNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuZGVzZXJpYWxpemUoXG4gICAgICAgICAgcmVzcG9uc2UuaGVhZGVyLm9wY29kZSxcbiAgICAgICAgICByZXNwb25zZS52YWwsXG4gICAgICAgICAgcmVzcG9uc2UuZXh0cmFzXG4gICAgICAgICk7XG4gICAgICAgIHJldHVybiB7IC4uLmRlc2VyaWFsaXplZCwgY2FzOiByZXNwb25zZS5oZWFkZXIuY2FzIH07XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIkdFVFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKiogQnVpbGQgYSBwaXBlbGluZWQgZ2V0IG11bHRpIHJlcXVlc3QgYnkgc2VuZGluZyBvbmUgR0VUS1EgZm9yIGVhY2gga2V5IChxdWlldCwgbWVhbmluZyBpdCB3b24ndCByZXNwb25kIGlmIHRoZSB2YWx1ZSBpcyBtaXNzaW5nKSBmb2xsb3dlZCBieSBhIG5vLW9wIHRvIGZvcmNlIGEgcmVzcG9uc2UgKGFuZCB0byBnaXZlIHVzIGEgc2VudGluZWwgcmVzcG9uc2UgdGhhdCB0aGUgcGlwZWxpbmUgaXMgZG9uZSlcbiAgICpcbiAgICogY2YgaHR0cHM6Ly9naXRodWIuY29tL2NvdWNoYmFzZS9tZW1jYWNoZWQvYmxvYi9tYXN0ZXIvZG9jcy9CaW5hcnlQcm90b2NvbC5tZCMweDBkLWdldGtxLWdldC13aXRoLWtleS1xdWlldGx5XG4gICAqL1xuICBfYnVpbGRHZXRNdWx0aVJlcXVlc3Qoa2V5czogc3RyaW5nW10sIHNlcTogbnVtYmVyKTogQnVmZmVyIHtcbiAgICAvLyBzdGFydCBhdCAyNCBmb3IgdGhlIG5vLW9wIGNvbW1hbmQgYXQgdGhlIGVuZFxuICAgIGxldCByZXF1ZXN0U2l6ZSA9IDI0O1xuICAgIGZvciAoY29uc3Qga2V5SWR4IGluIGtleXMpIHtcbiAgICAgIHJlcXVlc3RTaXplICs9IEJ1ZmZlci5ieXRlTGVuZ3RoKGtleXNba2V5SWR4XSwgXCJ1dGY4XCIpICsgMjQ7XG4gICAgfVxuXG4gICAgY29uc3QgcmVxdWVzdCA9IEJ1ZmZlci5hbGxvYyhyZXF1ZXN0U2l6ZSk7XG5cbiAgICBsZXQgYnl0ZXNXcml0dGVuID0gMDtcbiAgICBmb3IgKGNvbnN0IGtleUlkeCBpbiBrZXlzKSB7XG4gICAgICBjb25zdCBrZXkgPSBrZXlzW2tleUlkeF07XG4gICAgICBieXRlc1dyaXR0ZW4gKz0gY29weUludG9SZXF1ZXN0QnVmZmVyKFxuICAgICAgICBjb25zdGFudHMuT1BfR0VUS1EsXG4gICAgICAgIGtleSxcbiAgICAgICAgXCJcIixcbiAgICAgICAgXCJcIixcbiAgICAgICAgc2VxLFxuICAgICAgICByZXF1ZXN0LFxuICAgICAgICBieXRlc1dyaXR0ZW5cbiAgICAgICk7XG4gICAgfVxuXG4gICAgYnl0ZXNXcml0dGVuICs9IGNvcHlJbnRvUmVxdWVzdEJ1ZmZlcihcbiAgICAgIGNvbnN0YW50cy5PUF9OT19PUCxcbiAgICAgIFwiXCIsXG4gICAgICBcIlwiLFxuICAgICAgXCJcIixcbiAgICAgIHNlcSxcbiAgICAgIHJlcXVlc3QsXG4gICAgICBieXRlc1dyaXR0ZW5cbiAgICApO1xuXG4gICAgcmV0dXJuIHJlcXVlc3Q7XG4gIH1cblxuICAvKiogRXhlY3V0aW5nIGEgcGlwZWxpbmVkIChtdWx0aSkgZ2V0IGFnYWluc3QgYSBzaW5nbGUgc2VydmVyLiBUaGlzIGlzIGEgcHJpdmF0ZSBpbXBsZW1lbnRhdGlvbiBkZXRhaWwgb2YgZ2V0TXVsdGkuICovXG4gIGFzeW5jIF9nZXRNdWx0aVRvU2VydmVyPEtleXMgZXh0ZW5kcyBzdHJpbmc+KFxuICAgIHNlcnY6IFNlcnZlcixcbiAgICBrZXlzOiBLZXlzW11cbiAgKTogUHJvbWlzZTxHZXRNdWx0aVJlc3VsdDxLZXlzLCBWYWx1ZSwgRXh0cmFzPj4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBjb25zdCByZXNwb25zZU1hcDogR2V0TXVsdGlSZXN1bHQ8c3RyaW5nLCBWYWx1ZSwgRXh0cmFzPiA9IHt9O1xuXG4gICAgICBjb25zdCBoYW5kbGU6IE9uUmVzcG9uc2VDYWxsYmFjayA9IChyZXNwb25zZSkgPT4ge1xuICAgICAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgICAgICAvLyBXaGVuIHdlIGdldCB0aGUgbm8tb3AgcmVzcG9uc2UsIHdlIGFyZSBkb25lIHdpdGggdGhpcyBvbmUgZ2V0TXVsdGkgaW4gdGhlIHBlci1iYWNrZW5kIGZhbi1vdXRcbiAgICAgICAgICAgIGlmIChyZXNwb25zZS5oZWFkZXIub3Bjb2RlID09PSBjb25zdGFudHMuT1BfTk9fT1ApIHtcbiAgICAgICAgICAgICAgLy8gVGhpcyBlbnN1cmVzIHRoZSBoYW5kbGVyIHdpbGwgYmUgZGVsZXRlZCBmcm9tIHRoZSByZXNwb25zZUNhbGxiYWNrcyBtYXAgaW4gc2VydmVyLmpzXG4gICAgICAgICAgICAgIC8vIFRoaXMgaXNuJ3QgdGVjaG5pY2FsbHkgbmVlZGVkIGhlcmUgYmVjYXVzZSB0aGUgbG9naWMgaW4gc2VydmVyLmpzIGFsc28gY2hlY2tzIGlmIHRvdGFsQm9keUxlbmd0aCA9PT0gMCwgYnV0IG91ciB1bml0dGVzdHMgYXJlbid0IGdyZWF0IGFib3V0IHNldHRpbmcgdGhhdCBmaWVsZCwgYW5kIGFsc28gdGhpcyBtYWtlcyBpdCBtb3JlIGV4cGxpY2l0XG4gICAgICAgICAgICAgIGhhbmRsZS5xdWlldCA9IGZhbHNlO1xuICAgICAgICAgICAgICByZXNvbHZlKHJlc3BvbnNlTWFwKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgICAgICAgIHJlc3BvbnNlLmhlYWRlci5vcGNvZGUgPT09IGNvbnN0YW50cy5PUF9HRVRLIHx8XG4gICAgICAgICAgICAgIHJlc3BvbnNlLmhlYWRlci5vcGNvZGUgPT09IGNvbnN0YW50cy5PUF9HRVRLUVxuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgIGNvbnN0IGRlc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5kZXNlcmlhbGl6ZShcbiAgICAgICAgICAgICAgICByZXNwb25zZS5oZWFkZXIub3Bjb2RlLFxuICAgICAgICAgICAgICAgIHJlc3BvbnNlLnZhbCxcbiAgICAgICAgICAgICAgICByZXNwb25zZS5leHRyYXNcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgY29uc3Qga2V5ID0gcmVzcG9uc2Uua2V5LnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgIGlmIChrZXkubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlamVjdChcbiAgICAgICAgICAgICAgICAgIG5ldyBFcnJvcihcbiAgICAgICAgICAgICAgICAgICAgXCJSZWNpZXZlZCBlbXB0eSBrZXkgaW4gZ2V0TXVsdGk6IFwiICtcbiAgICAgICAgICAgICAgICAgICAgICBKU09OLnN0cmluZ2lmeShyZXNwb25zZSlcbiAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIHJlc3BvbnNlTWFwW2tleV0gPSB7IC4uLmRlc2VyaWFsaXplZCwgY2FzOiByZXNwb25zZS5oZWFkZXIuY2FzIH07XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICByZXR1cm4gcmVqZWN0KFxuICAgICAgICAgICAgICAgIG5ldyBFcnJvcihcbiAgICAgICAgICAgICAgICAgIFwiUmVjaWV2ZWQgcmVzcG9uc2UgaW4gZ2V0TXVsdGkgZm9yIHVua25vd24gb3Bjb2RlOiBcIiArXG4gICAgICAgICAgICAgICAgICAgIEpTT04uc3RyaW5naWZ5KHJlc3BvbnNlKVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICByZXR1cm4gcmVqZWN0KFxuICAgICAgICAgICAgICB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiR0VUXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9O1xuICAgICAgLy8gVGhpcyBwcmV2ZW50cyB0aGUgaGFuZGxlciBmcm9tIGJlaW5nIGRlbGV0ZWRcbiAgICAgIC8vIGFmdGVyIHRoZSBmaXJzdCByZXNwb25zZS4gTG9naWMgaW4gc2VydmVyLmpzLlxuICAgICAgaGFuZGxlLnF1aWV0ID0gdHJ1ZTtcblxuICAgICAgY29uc3Qgc2VxID0gdGhpcy5pbmNyU2VxKCk7XG4gICAgICBjb25zdCByZXF1ZXN0ID0gdGhpcy5fYnVpbGRHZXRNdWx0aVJlcXVlc3Qoa2V5cywgc2VxKTtcbiAgICAgIHNlcnYub25SZXNwb25zZSh0aGlzLnNlcSwgaGFuZGxlKTtcbiAgICAgIHNlcnYub25FcnJvcih0aGlzLnNlcSwgcmVqZWN0KTtcbiAgICAgIHNlcnYud3JpdGUocmVxdWVzdCk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldnMgdGhlIHZhbHVlIGF0IHRoZSBnaXZlbiBrZXlzIGluIG1lbWNhY2hlZC4gUmV0dXJucyBhIG1hcCBmcm9tIHRoZVxuICAgKiByZXF1ZXN0ZWQga2V5cyB0byByZXN1bHRzLCBvciBudWxsIGlmIHRoZSBrZXkgd2FzIG5vdCBmb3VuZC5cbiAgICovXG4gIGFzeW5jIGdldE11bHRpPEtleXMgZXh0ZW5kcyBzdHJpbmc+KFxuICAgIGtleXM6IEtleXNbXVxuICApOiBQcm9taXNlPEdldE11bHRpUmVzdWx0PEtleXMsIFZhbHVlLCBFeHRyYXM+PiB7XG4gICAgY29uc3Qgc2VydmVyS2V5dG9Mb29rdXBLZXlzOiB7XG4gICAgICBbc2VydmVyS2V5OiBzdHJpbmddOiBzdHJpbmdbXTtcbiAgICB9ID0ge307XG4gICAga2V5cy5mb3JFYWNoKChsb29rdXBLZXkpID0+IHtcbiAgICAgIGNvbnN0IHNlcnZlcktleSA9IHRoaXMubG9va3VwS2V5VG9TZXJ2ZXJLZXkobG9va3VwS2V5KTtcbiAgICAgIGlmICghc2VydmVyS2V5dG9Mb29rdXBLZXlzW3NlcnZlcktleV0pIHtcbiAgICAgICAgc2VydmVyS2V5dG9Mb29rdXBLZXlzW3NlcnZlcktleV0gPSBbXTtcbiAgICAgIH1cbiAgICAgIHNlcnZlcktleXRvTG9va3VwS2V5c1tzZXJ2ZXJLZXldLnB1c2gobG9va3VwS2V5KTtcbiAgICB9KTtcblxuICAgIGNvbnN0IHVzZWRTZXJ2ZXJLZXlzID0gT2JqZWN0LmtleXMoc2VydmVyS2V5dG9Mb29rdXBLZXlzKTtcbiAgICBjb25zdCByZXN1bHRzID0gYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICB1c2VkU2VydmVyS2V5cy5tYXAoKHNlcnZlcktleSkgPT4ge1xuICAgICAgICBjb25zdCBzZXJ2ZXIgPSB0aGlzLnNlcnZlcktleVRvU2VydmVyKHNlcnZlcktleSk7XG4gICAgICAgIHJldHVybiB0aGlzLl9nZXRNdWx0aVRvU2VydmVyKHNlcnZlciwgc2VydmVyS2V5dG9Mb29rdXBLZXlzW3NlcnZlcktleV0pO1xuICAgICAgfSlcbiAgICApO1xuXG4gICAgcmV0dXJuIE9iamVjdC5hc3NpZ24oe30sIC4uLnJlc3VsdHMpO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgYGtleWAgdG8gYHZhbHVlYC5cbiAgICovXG4gIGFzeW5jIHNldChcbiAgICBrZXk6IHN0cmluZyxcbiAgICB2YWx1ZTogVmFsdWUsXG4gICAgb3B0aW9ucz86IHsgZXhwaXJlcz86IG51bWJlcjsgY2FzPzogQ0FTVG9rZW4gfVxuICApOiBQcm9taXNlPGJvb2xlYW4gfCBudWxsPiB7XG4gICAgY29uc3QgZXhwaXJlcyA9IG9wdGlvbnM/LmV4cGlyZXM7XG4gICAgY29uc3QgY2FzID0gb3B0aW9ucz8uY2FzO1xuXG4gICAgLy8gVE9ETzogc3VwcG9ydCBmbGFnc1xuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IGV4cGlyYXRpb24gPSBtYWtlRXhwaXJhdGlvbihleHBpcmVzIHx8IHRoaXMub3B0aW9ucy5leHBpcmVzKTtcbiAgICBjb25zdCBleHRyYXMgPSBCdWZmZXIuY29uY2F0KFtCdWZmZXIuZnJvbShcIjAwMDAwMDAwXCIsIFwiaGV4XCIpLCBleHBpcmF0aW9uXSk7XG4gICAgY29uc3Qgc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5zZXJpYWxpemUoXG4gICAgICBjb25zdGFudHMuT1BfU0VULFxuICAgICAgdmFsdWUsXG4gICAgICBleHRyYXNcbiAgICApO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBVdGlscy5lbmNvZGVSZXF1ZXN0KHtcbiAgICAgIGhlYWRlcjoge1xuICAgICAgICBvcGNvZGU6IGNvbnN0YW50cy5PUF9TRVQsXG4gICAgICAgIG9wYXF1ZTogdGhpcy5zZXEsXG4gICAgICAgIGNhcyxcbiAgICAgIH0sXG4gICAgICBrZXksXG4gICAgICB2YWx1ZTogc2VyaWFsaXplZC52YWx1ZSxcbiAgICAgIGV4dHJhczogc2VyaWFsaXplZC5leHRyYXMsXG4gICAgfSk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfRVhJU1RTOlxuICAgICAgICBpZiAoY2FzKSB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJTRVRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgICAgIH1cbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJTRVRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEFERFxuICAgKlxuICAgKiBBZGRzIHRoZSBnaXZlbiBfa2V5XyBhbmQgX3ZhbHVlXyB0byBtZW1jYWNoZS4gVGhlIG9wZXJhdGlvbiBvbmx5IHN1Y2NlZWRzXG4gICAqIGlmIHRoZSBrZXkgaXMgbm90IGFscmVhZHkgc2V0LlxuICAgKlxuICAgKiBUaGUgb3B0aW9ucyBkaWN0aW9uYXJ5IHRha2VzOlxuICAgKiAqIF9leHBpcmVzXzogb3ZlcnJpZGVzIHRoZSBkZWZhdWx0IGV4cGlyYXRpb24gKHNlZSBgQ2xpZW50LmNyZWF0ZWApIGZvciB0aGlzXG4gICAqICAgICAgICAgICAgICBwYXJ0aWN1bGFyIGtleS12YWx1ZSBwYWlyLlxuICAgKi9cbiAgYXN5bmMgYWRkKFxuICAgIGtleTogc3RyaW5nLFxuICAgIHZhbHVlOiBWYWx1ZSxcbiAgICBvcHRpb25zPzogeyBleHBpcmVzPzogbnVtYmVyIH1cbiAgKTogUHJvbWlzZTxib29sZWFuIHwgbnVsbD4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgZmxhZ3MsIHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IGV4cGlyYXRpb24gPSBtYWtlRXhwaXJhdGlvbihvcHRpb25zPy5leHBpcmVzIHx8IHRoaXMub3B0aW9ucy5leHBpcmVzKTtcbiAgICBjb25zdCBleHRyYXMgPSBCdWZmZXIuY29uY2F0KFtCdWZmZXIuZnJvbShcIjAwMDAwMDAwXCIsIFwiaGV4XCIpLCBleHBpcmF0aW9uXSk7XG5cbiAgICBjb25zdCBvcGNvZGUgPSBjb25zdGFudHMuT1BfQUREO1xuICAgIGNvbnN0IHNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuc2VyaWFsaXplKG9wY29kZSwgdmFsdWUsIGV4dHJhcyk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKFxuICAgICAgb3Bjb2RlLFxuICAgICAga2V5LFxuICAgICAgc2VyaWFsaXplZC5leHRyYXMsXG4gICAgICBzZXJpYWxpemVkLnZhbHVlLFxuICAgICAgdGhpcy5zZXFcbiAgICApO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuS0VZX0VYSVNUUzpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJBRERcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlcGxhY2VzIHRoZSBnaXZlbiBfa2V5XyBhbmQgX3ZhbHVlXyB0byBtZW1jYWNoZS4gVGhlIG9wZXJhdGlvbiBvbmx5IHN1Y2NlZWRzXG4gICAqIGlmIHRoZSBrZXkgaXMgYWxyZWFkeSBwcmVzZW50LlxuICAgKi9cbiAgYXN5bmMgcmVwbGFjZShcbiAgICBrZXk6IHN0cmluZyxcbiAgICB2YWx1ZTogVmFsdWUsXG4gICAgb3B0aW9ucz86IHsgZXhwaXJlcz86IG51bWJlciB9XG4gICk6IFByb21pc2U8Ym9vbGVhbiB8IG51bGw+IHtcbiAgICAvLyBUT0RPOiBzdXBwb3J0IGZsYWdzLCBzdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBleHBpcmF0aW9uID0gbWFrZUV4cGlyYXRpb24ob3B0aW9ucz8uZXhwaXJlcyB8fCB0aGlzLm9wdGlvbnMuZXhwaXJlcyk7XG4gICAgY29uc3QgZXh0cmFzID0gQnVmZmVyLmNvbmNhdChbQnVmZmVyLmZyb20oXCIwMDAwMDAwMFwiLCBcImhleFwiKSwgZXhwaXJhdGlvbl0pO1xuXG4gICAgY29uc3Qgb3Bjb2RlOiBjb25zdGFudHMuT1AgPSBjb25zdGFudHMuT1BfUkVQTEFDRTtcbiAgICBjb25zdCBzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLnNlcmlhbGl6ZShvcGNvZGUsIHZhbHVlLCBleHRyYXMpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgIG9wY29kZSxcbiAgICAgIGtleSxcbiAgICAgIHNlcmlhbGl6ZWQuZXh0cmFzLFxuICAgICAgc2VyaWFsaXplZC52YWx1ZSxcbiAgICAgIHRoaXMuc2VxXG4gICAgKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJSRVBMQUNFXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBEZWxldGVzIHRoZSBnaXZlbiBfa2V5XyBmcm9tIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHNcbiAgICogaWYgdGhlIGtleSBpcyBhbHJlYWR5IHByZXNlbnQuXG4gICAqL1xuICBhc3luYyBkZWxldGUoa2V5OiBzdHJpbmcpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAvLyBUT0RPOiBTdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoNCwga2V5LCBcIlwiLCBcIlwiLCB0aGlzLnNlcSk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG5cbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJERUxFVEVcIiwgcmVzcG9uc2U/LmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBJbmNyZW1lbnRzIHRoZSBnaXZlbiBfa2V5XyBpbiBtZW1jYWNoZS5cbiAgICovXG4gIGFzeW5jIGluY3JlbWVudChcbiAgICBrZXk6IHN0cmluZyxcbiAgICBhbW91bnQ6IG51bWJlcixcbiAgICBvcHRpb25zPzogeyBpbml0aWFsPzogbnVtYmVyOyBleHBpcmVzPzogbnVtYmVyIH1cbiAgKTogUHJvbWlzZTx7IHZhbHVlOiBudW1iZXIgfCBudWxsOyBzdWNjZXNzOiBib29sZWFuIHwgbnVsbCB9PiB7XG4gICAgLy8gVE9ETzogc3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgaW5pdGlhbCA9IG9wdGlvbnM/LmluaXRpYWwgfHwgMDtcbiAgICBjb25zdCBleHBpcmVzID0gb3B0aW9ucz8uZXhwaXJlcyB8fCB0aGlzLm9wdGlvbnMuZXhwaXJlcztcbiAgICBjb25zdCBleHRyYXMgPSBtYWtlQW1vdW50SW5pdGlhbEFuZEV4cGlyYXRpb24oYW1vdW50LCBpbml0aWFsLCBleHBpcmVzKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICBjb25zdGFudHMuT1BfSU5DUkVNRU5ULFxuICAgICAga2V5LFxuICAgICAgZXh0cmFzLFxuICAgICAgXCJcIixcbiAgICAgIHRoaXMuc2VxXG4gICAgKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgY29uc3QgYnVmSW50ID1cbiAgICAgICAgICAocmVzcG9uc2UudmFsLnJlYWRVSW50MzJCRSgwKSA8PCA4KSArIHJlc3BvbnNlLnZhbC5yZWFkVUludDMyQkUoNCk7XG4gICAgICAgIHJldHVybiB7IHZhbHVlOiBidWZJbnQsIHN1Y2Nlc3M6IHRydWUgfTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJJTkNSRU1FTlRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIERlY3JlbWVudHMgdGhlIGdpdmVuIGBrZXlgIGluIG1lbWNhY2hlLlxuICAgKi9cbiAgYXN5bmMgZGVjcmVtZW50KFxuICAgIGtleTogc3RyaW5nLFxuICAgIGFtb3VudDogbnVtYmVyLFxuICAgIG9wdGlvbnM6IHsgaW5pdGlhbD86IG51bWJlcjsgZXhwaXJlcz86IG51bWJlciB9XG4gICk6IFByb21pc2U8eyB2YWx1ZTogbnVtYmVyIHwgbnVsbDsgc3VjY2VzczogYm9vbGVhbiB8IG51bGwgfT4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IGluaXRpYWwgPSBvcHRpb25zLmluaXRpYWwgfHwgMDtcbiAgICBjb25zdCBleHBpcmVzID0gb3B0aW9ucy5leHBpcmVzIHx8IHRoaXMub3B0aW9ucy5leHBpcmVzO1xuICAgIGNvbnN0IGV4dHJhcyA9IG1ha2VBbW91bnRJbml0aWFsQW5kRXhwaXJhdGlvbihhbW91bnQsIGluaXRpYWwsIGV4cGlyZXMpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgIGNvbnN0YW50cy5PUF9ERUNSRU1FTlQsXG4gICAgICBrZXksXG4gICAgICBleHRyYXMsXG4gICAgICBcIlwiLFxuICAgICAgdGhpcy5zZXFcbiAgICApO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICBjb25zdCBidWZJbnQgPVxuICAgICAgICAgIChyZXNwb25zZS52YWwucmVhZFVJbnQzMkJFKDApIDw8IDgpICsgcmVzcG9uc2UudmFsLnJlYWRVSW50MzJCRSg0KTtcbiAgICAgICAgcmV0dXJuIHsgdmFsdWU6IGJ1ZkludCwgc3VjY2VzczogdHJ1ZSB9O1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIkRFQ1JFTUVOVFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQXBwZW5kIHRoZSBnaXZlbiBfdmFsdWVfIHRvIHRoZSB2YWx1ZSBhc3NvY2lhdGVkIHdpdGggdGhlIGdpdmVuIF9rZXlfIGluXG4gICAqIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHMgaWYgdGhlIGtleSBpcyBhbHJlYWR5IHByZXNlbnQuXG4gICAqL1xuICBhc3luYyBhcHBlbmQoa2V5OiBzdHJpbmcsIHZhbHVlOiBWYWx1ZSk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IG9wY29kZTogY29uc3RhbnRzLk9QID0gY29uc3RhbnRzLk9QX0FQUEVORDtcbiAgICBjb25zdCBzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLnNlcmlhbGl6ZShvcGNvZGUsIHZhbHVlLCBcIlwiKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICBvcGNvZGUsXG4gICAgICBrZXksXG4gICAgICBzZXJpYWxpemVkLmV4dHJhcyxcbiAgICAgIHNlcmlhbGl6ZWQudmFsdWUsXG4gICAgICB0aGlzLnNlcVxuICAgICk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfTk9UX0ZPVU5EOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiQVBQRU5EXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBQcmVwZW5kIHRoZSBnaXZlbiBfdmFsdWVfIHRvIHRoZSB2YWx1ZSBhc3NvY2lhdGVkIHdpdGggdGhlIGdpdmVuIF9rZXlfIGluXG4gICAqIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHMgaWYgdGhlIGtleSBpcyBhbHJlYWR5IHByZXNlbnQuXG4gICAqL1xuICBhc3luYyBwcmVwZW5kKGtleTogc3RyaW5nLCB2YWx1ZTogVmFsdWUpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAvLyBUT0RPOiBzdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBvcGNvZGU6IGNvbnN0YW50cy5PUCA9IGNvbnN0YW50cy5PUF9QUkVQRU5EO1xuICAgIGNvbnN0IHNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuc2VyaWFsaXplKG9wY29kZSwgdmFsdWUsIFwiXCIpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgIG9wY29kZSxcbiAgICAgIGtleSxcbiAgICAgIHNlcmlhbGl6ZWQuZXh0cmFzLFxuICAgICAgc2VyaWFsaXplZC52YWx1ZSxcbiAgICAgIHRoaXMuc2VxXG4gICAgKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJQUkVQRU5EXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBUb3VjaCBzZXRzIGFuIGV4cGlyYXRpb24gdmFsdWUsIGdpdmVuIGJ5IF9leHBpcmVzXywgb24gdGhlIGdpdmVuIF9rZXlfIGluXG4gICAqIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHMgaWYgdGhlIGtleSBpcyBhbHJlYWR5IHByZXNlbnQuXG4gICAqL1xuICBhc3luYyB0b3VjaChrZXk6IHN0cmluZywgZXhwaXJlczogbnVtYmVyKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgLy8gVE9ETzogc3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgZXh0cmFzID0gbWFrZUV4cGlyYXRpb24oZXhwaXJlcyB8fCB0aGlzLm9wdGlvbnMuZXhwaXJlcyk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKDB4MWMsIGtleSwgZXh0cmFzLCBcIlwiLCB0aGlzLnNlcSk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfTk9UX0ZPVU5EOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiVE9VQ0hcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEZMVVNIXG4gICAqXG4gICAqIEZsdXNoZXMgdGhlIGNhY2hlIG9uIGVhY2ggY29ubmVjdGVkIHNlcnZlci4gVGhlIGNhbGxiYWNrIHNpZ25hdHVyZSBpczpcbiAgICpcbiAgICogICAgIGNhbGxiYWNrKGxhc3RFcnIsIHJlc3VsdHMpXG4gICAqXG4gICAqIHdoZXJlIF9sYXN0RXJyXyBpcyB0aGUgbGFzdCBlcnJvciBlbmNvdW50ZXJlZCAob3IgbnVsbCwgaW4gdGhlIGNvbW1vbiBjYXNlXG4gICAqIG9mIG5vIGVycm9ycykuIF9yZXN1bHRzXyBpcyBhIGRpY3Rpb25hcnkgbWFwcGluZyBgXCJob3N0bmFtZTpwb3J0XCJgIHRvIGVpdGhlclxuICAgKiBgdHJ1ZWAgKGlmIHRoZSBvcGVyYXRpb24gd2FzIHN1Y2Nlc3NmdWwpLCBvciBhbiBlcnJvci5cbiAgICogQHBhcmFtIGNhbGxiYWNrXG4gICAqL1xuICBmbHVzaCgpOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIGJvb2xlYW4gfCBFcnJvcj4+O1xuICBmbHVzaChcbiAgICBjYWxsYmFjazogKFxuICAgICAgZXJyOiBFcnJvciB8IG51bGwsXG4gICAgICByZXN1bHRzOiBSZWNvcmQ8c3RyaW5nLCBib29sZWFuIHwgRXJyb3I+XG4gICAgKSA9PiB2b2lkXG4gICk6IHZvaWQ7XG4gIGZsdXNoKFxuICAgIGNhbGxiYWNrPzogKFxuICAgICAgZXJyOiBFcnJvciB8IG51bGwsXG4gICAgICByZXN1bHRzOiBSZWNvcmQ8c3RyaW5nLCBib29sZWFuIHwgRXJyb3I+XG4gICAgKSA9PiB2b2lkXG4gICkge1xuICAgIGlmIChjYWxsYmFjayA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm4gcHJvbWlzaWZ5KChjYWxsYmFjaykgPT4ge1xuICAgICAgICB0aGlzLmZsdXNoKGZ1bmN0aW9uIChlcnIsIHJlc3VsdHMpIHtcbiAgICAgICAgICBjYWxsYmFjayhlcnIsIHJlc3VsdHMpO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH1cbiAgICAvLyBUT0RPOiBzdXBwb3J0IGV4cGlyYXRpb25cbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoMHgwOCwgXCJcIiwgXCJcIiwgXCJcIiwgdGhpcy5zZXEpO1xuICAgIGxldCBjb3VudCA9IHRoaXMuc2VydmVycy5sZW5ndGg7XG4gICAgY29uc3QgcmVzdWx0OiBSZWNvcmQ8c3RyaW5nLCBib29sZWFuIHwgRXJyb3I+ID0ge307XG4gICAgbGV0IGxhc3RFcnI6IEVycm9yIHwgbnVsbCA9IG51bGw7XG5cbiAgICBjb25zdCBoYW5kbGVGbHVzaCA9IGZ1bmN0aW9uIChzZXE6IG51bWJlciwgc2VydjogU2VydmVyKSB7XG4gICAgICBzZXJ2Lm9uUmVzcG9uc2Uoc2VxLCBmdW5jdGlvbiAoLyogcmVzcG9uc2UgKi8pIHtcbiAgICAgICAgY291bnQgLT0gMTtcbiAgICAgICAgcmVzdWx0W3NlcnYuaG9zdHBvcnRTdHJpbmcoKV0gPSB0cnVlO1xuICAgICAgICBpZiAoY2FsbGJhY2sgJiYgY291bnQgPT09IDApIHtcbiAgICAgICAgICBjYWxsYmFjayhsYXN0RXJyLCByZXN1bHQpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHNlcnYub25FcnJvcihzZXEsIGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgICAgY291bnQgLT0gMTtcbiAgICAgICAgbGFzdEVyciA9IGVycjtcbiAgICAgICAgcmVzdWx0W3NlcnYuaG9zdHBvcnRTdHJpbmcoKV0gPSBlcnI7XG4gICAgICAgIGlmIChjYWxsYmFjayAmJiBjb3VudCA9PT0gMCkge1xuICAgICAgICAgIGNhbGxiYWNrKGxhc3RFcnIsIHJlc3VsdCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgc2Vydi53cml0ZShyZXF1ZXN0KTtcbiAgICB9O1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnNlcnZlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGhhbmRsZUZsdXNoKHRoaXMuc2VxLCB0aGlzLnNlcnZlcnNbaV0pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTVEFUU19XSVRIX0tFWVxuICAgKlxuICAgKiBTZW5kcyBhIG1lbWNhY2hlIHN0YXRzIGNvbW1hbmQgd2l0aCBhIGtleSB0byBlYWNoIGNvbm5lY3RlZCBzZXJ2ZXIuIFRoZVxuICAgKiBjYWxsYmFjayBpcyBpbnZva2VkICoqT05DRSBQRVIgU0VSVkVSKiogYW5kIGhhcyB0aGUgc2lnbmF0dXJlOlxuICAgKlxuICAgKiAgICAgY2FsbGJhY2soZXJyLCBzZXJ2ZXIsIHN0YXRzKVxuICAgKlxuICAgKiBfc2VydmVyXyBpcyB0aGUgYFwiaG9zdG5hbWU6cG9ydFwiYCBvZiB0aGUgc2VydmVyLCBhbmQgX3N0YXRzXyBpcyBhIGRpY3Rpb25hcnlcbiAgICogbWFwcGluZyB0aGUgc3RhdCBuYW1lIHRvIHRoZSB2YWx1ZSBvZiB0aGUgc3RhdGlzdGljIGFzIGEgc3RyaW5nLlxuICAgKiBAcGFyYW0ga2V5XG4gICAqIEBwYXJhbSBjYWxsYmFja1xuICAgKi9cbiAgc3RhdHNXaXRoS2V5KFxuICAgIGtleTogc3RyaW5nLFxuICAgIGNhbGxiYWNrPzogKFxuICAgICAgZXJyOiBFcnJvciB8IG51bGwsXG4gICAgICBzZXJ2ZXI6IHN0cmluZyxcbiAgICAgIHN0YXRzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+IHwgbnVsbFxuICAgICkgPT4gdm9pZFxuICApOiB2b2lkIHtcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoMHgxMCwga2V5LCBcIlwiLCBcIlwiLCB0aGlzLnNlcSk7XG5cbiAgICBjb25zdCBoYW5kbGVTdGF0cyA9IChzZXE6IG51bWJlciwgc2VydjogU2VydmVyKSA9PiB7XG4gICAgICBjb25zdCByZXN1bHQ6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcbiAgICAgIGNvbnN0IGhhbmRsZTogT25SZXNwb25zZUNhbGxiYWNrID0gKHJlc3BvbnNlKSA9PiB7XG4gICAgICAgIC8vIGVuZCBvZiBzdGF0IHJlc3BvbnNlc1xuICAgICAgICBpZiAocmVzcG9uc2UuaGVhZGVyLnRvdGFsQm9keUxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgICAgY2FsbGJhY2sobnVsbCwgc2Vydi5ob3N0cG9ydFN0cmluZygpLCByZXN1bHQpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgLy8gcHJvY2VzcyBzaW5nbGUgc3RhdCBsaW5lIHJlc3BvbnNlXG4gICAgICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgICAgIHJlc3VsdFtyZXNwb25zZS5rZXkudG9TdHJpbmcoKV0gPSByZXNwb25zZS52YWwudG9TdHJpbmcoKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICBjb25zdCBlcnJvciA9IHRoaXMuaGFuZGxlUmVzcG9uc2VFcnJvcihcbiAgICAgICAgICAgICAgYFNUQVRTICgke2tleX0pYCxcbiAgICAgICAgICAgICAgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyxcbiAgICAgICAgICAgICAgdW5kZWZpbmVkXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgICAgICAgIGNhbGxiYWNrKGVycm9yLCBzZXJ2Lmhvc3Rwb3J0U3RyaW5nKCksIG51bGwpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9O1xuICAgICAgaGFuZGxlLnF1aWV0ID0gdHJ1ZTtcblxuICAgICAgc2Vydi5vblJlc3BvbnNlKHNlcSwgaGFuZGxlKTtcbiAgICAgIHNlcnYub25FcnJvcihzZXEsIGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgICAgY2FsbGJhY2soZXJyLCBzZXJ2Lmhvc3Rwb3J0U3RyaW5nKCksIG51bGwpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHNlcnYud3JpdGUocmVxdWVzdCk7XG4gICAgfTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5zZXJ2ZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBoYW5kbGVTdGF0cyh0aGlzLnNlcSwgdGhpcy5zZXJ2ZXJzW2ldKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU1RBVFNcbiAgICpcbiAgICogRmV0Y2hlcyBtZW1jYWNoZSBzdGF0cyBmcm9tIGVhY2ggY29ubmVjdGVkIHNlcnZlci4gVGhlIGNhbGxiYWNrIGlzIGludm9rZWRcbiAgICogKipPTkNFIFBFUiBTRVJWRVIqKiBhbmQgaGFzIHRoZSBzaWduYXR1cmU6XG4gICAqXG4gICAqICAgICBjYWxsYmFjayhlcnIsIHNlcnZlciwgc3RhdHMpXG4gICAqXG4gICAqIF9zZXJ2ZXJfIGlzIHRoZSBgXCJob3N0bmFtZTpwb3J0XCJgIG9mIHRoZSBzZXJ2ZXIsIGFuZCBfc3RhdHNfIGlzIGFcbiAgICogZGljdGlvbmFyeSBtYXBwaW5nIHRoZSBzdGF0IG5hbWUgdG8gdGhlIHZhbHVlIG9mIHRoZSBzdGF0aXN0aWMgYXMgYSBzdHJpbmcuXG4gICAqIEBwYXJhbSBjYWxsYmFja1xuICAgKi9cbiAgc3RhdHMoXG4gICAgY2FsbGJhY2s/OiAoXG4gICAgICBlcnI6IEVycm9yIHwgbnVsbCxcbiAgICAgIHNlcnZlcjogc3RyaW5nLFxuICAgICAgc3RhdHM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gfCBudWxsXG4gICAgKSA9PiB2b2lkXG4gICk6IHZvaWQge1xuICAgIHRoaXMuc3RhdHNXaXRoS2V5KFwiXCIsIGNhbGxiYWNrKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSRVNFVF9TVEFUU1xuICAgKlxuICAgKiBSZXNldCB0aGUgc3RhdGlzdGljcyBlYWNoIHNlcnZlciBpcyBrZWVwaW5nIGJhY2sgdG8gemVyby4gVGhpcyBkb2Vzbid0IGNsZWFyXG4gICAqIHN0YXRzIHN1Y2ggYXMgaXRlbSBjb3VudCwgYnV0IHRlbXBvcmFyeSBzdGF0cyBzdWNoIGFzIHRvdGFsIG51bWJlciBvZlxuICAgKiBjb25uZWN0aW9ucyBvdmVyIHRpbWUuXG4gICAqXG4gICAqIFRoZSBjYWxsYmFjayBpcyBpbnZva2VkICoqT05DRSBQRVIgU0VSVkVSKiogYW5kIGhhcyB0aGUgc2lnbmF0dXJlOlxuICAgKlxuICAgKiAgICAgY2FsbGJhY2soZXJyLCBzZXJ2ZXIpXG4gICAqXG4gICAqIF9zZXJ2ZXJfIGlzIHRoZSBgXCJob3N0bmFtZTpwb3J0XCJgIG9mIHRoZSBzZXJ2ZXIuXG4gICAqIEBwYXJhbSBjYWxsYmFja1xuICAgKi9cbiAgcmVzZXRTdGF0cyhcbiAgICBjYWxsYmFjaz86IChcbiAgICAgIGVycjogRXJyb3IgfCBudWxsLFxuICAgICAgc2VydmVyOiBzdHJpbmcsXG4gICAgICBzdGF0czogUmVjb3JkPHN0cmluZywgc3RyaW5nPiB8IG51bGxcbiAgICApID0+IHZvaWRcbiAgKTogdm9pZCB7XG4gICAgdGhpcy5zdGF0c1dpdGhLZXkoXCJyZXNldFwiLCBjYWxsYmFjayk7XG4gIH1cblxuICAvKipcbiAgICogUVVJVFxuICAgKlxuICAgKiBDbG9zZXMgdGhlIGNvbm5lY3Rpb24gdG8gZWFjaCBzZXJ2ZXIsIG5vdGlmeWluZyB0aGVtIG9mIHRoaXMgaW50ZW50aW9uLiBOb3RlXG4gICAqIHRoYXQgcXVpdCBjYW4gcmFjZSBhZ2FpbnN0IGFscmVhZHkgb3V0c3RhbmRpbmcgcmVxdWVzdHMgd2hlbiB0aG9zZSByZXF1ZXN0c1xuICAgKiBmYWlsIGFuZCBhcmUgcmV0cmllZCwgbGVhZGluZyB0byB0aGUgcXVpdCBjb21tYW5kIHdpbm5pbmcgYW5kIGNsb3NpbmcgdGhlXG4gICAqIGNvbm5lY3Rpb24gYmVmb3JlIHRoZSByZXRyaWVzIGNvbXBsZXRlLlxuICAgKi9cbiAgcXVpdCgpIHtcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICAvLyBUT0RPOiBOaWNlciBwZXJoYXBzIHRvIGRvIFFVSVRRICgweDE3KSBidXQgbmVlZCBhIG5ldyBjYWxsYmFjayBmb3Igd2hlblxuICAgIC8vIHdyaXRlIGlzIGRvbmUuXG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKDB4MDcsIFwiXCIsIFwiXCIsIFwiXCIsIHRoaXMuc2VxKTsgLy8gUVVJVFxuICAgIGxldCBzZXJ2O1xuXG4gICAgY29uc3QgaGFuZGxlUXVpdCA9IGZ1bmN0aW9uIChzZXE6IG51bWJlciwgc2VydjogU2VydmVyKSB7XG4gICAgICBzZXJ2Lm9uUmVzcG9uc2Uoc2VxLCBmdW5jdGlvbiAoLyogcmVzcG9uc2UgKi8pIHtcbiAgICAgICAgc2Vydi5jbG9zZSgpO1xuICAgICAgfSk7XG4gICAgICBzZXJ2Lm9uRXJyb3Ioc2VxLCBmdW5jdGlvbiAoLyogZXJyICovKSB7XG4gICAgICAgIHNlcnYuY2xvc2UoKTtcbiAgICAgIH0pO1xuICAgICAgc2Vydi53cml0ZShyZXF1ZXN0KTtcbiAgICB9O1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnNlcnZlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHNlcnYgPSB0aGlzLnNlcnZlcnNbaV07XG4gICAgICBoYW5kbGVRdWl0KHRoaXMuc2VxLCBzZXJ2KTtcbiAgICB9XG4gIH1cblxuICBfdmVyc2lvbihzZXJ2ZXI6IFNlcnZlcik6IFByb21pc2U8eyB2YWx1ZTogVmFsdWUgfCBudWxsIH0+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICAgIGNvbnN0YW50cy5PUF9WRVJTSU9OLFxuICAgICAgICBcIlwiLFxuICAgICAgICBcIlwiLFxuICAgICAgICBcIlwiLFxuICAgICAgICB0aGlzLnNlcVxuICAgICAgKTtcbiAgICAgIHRoaXMucGVyZm9ybU9uU2VydmVyKHNlcnZlciwgcmVxdWVzdCwgdGhpcy5zZXEsIChlcnIsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICByZXR1cm4gcmVqZWN0KGVycik7XG4gICAgICAgIH1cblxuICAgICAgICBzd2l0Y2ggKHJlc3BvbnNlIS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICAgICAgLyogVE9ETzogdGhpcyBpcyBidWdnZWQsIHdlIHNob3VsZCd0IHVzZSB0aGUgZGVzZXJpYWxpemVyIGhlcmUsIHNpbmNlIHZlcnNpb24gYWx3YXlzIHJldHVybnMgYSB2ZXJzaW9uIHN0cmluZy5cbiAgICAgICAgICAgICBUaGUgZGVzZXJpYWxpemVyIHNob3VsZCBvbmx5IGJlIHVzZWQgb24gdXNlciBrZXkgZGF0YS4gKi9cbiAgICAgICAgICAgIGNvbnN0IGRlc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5kZXNlcmlhbGl6ZShcbiAgICAgICAgICAgICAgcmVzcG9uc2UhLmhlYWRlci5vcGNvZGUsXG4gICAgICAgICAgICAgIHJlc3BvbnNlIS52YWwsXG4gICAgICAgICAgICAgIHJlc3BvbnNlIS5leHRyYXNcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICByZXR1cm4gcmVzb2x2ZSh7IHZhbHVlOiBkZXNlcmlhbGl6ZWQudmFsdWUgfSk7XG4gICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHJldHVybiByZWplY3QoXG4gICAgICAgICAgICAgIHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJWRVJTSU9OXCIsIHJlc3BvbnNlIS5oZWFkZXIuc3RhdHVzKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmVxdWVzdCB0aGUgc2VydmVyIHZlcnNpb24gZnJvbSB0aGUgXCJmaXJzdFwiIHNlcnZlciBpbiB0aGUgYmFja2VuZCBwb29sLlxuICAgKiBUaGUgc2VydmVyIHJlc3BvbmRzIHdpdGggYSBwYWNrZXQgY29udGFpbmluZyB0aGUgdmVyc2lvbiBzdHJpbmcgaW4gdGhlIGJvZHkgd2l0aCB0aGUgZm9sbG93aW5nIGZvcm1hdDogXCJ4LnkuelwiXG4gICAqL1xuICB2ZXJzaW9uKCk6IFByb21pc2U8eyB2YWx1ZTogVmFsdWUgfCBudWxsIH0+IHtcbiAgICBjb25zdCBzZXJ2ZXIgPSB0aGlzLnNlcnZlcktleVRvU2VydmVyKHRoaXMuc2VydmVyS2V5c1swXSk7XG4gICAgcmV0dXJuIHRoaXMuX3ZlcnNpb24oc2VydmVyKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXRyaWV2ZXMgdGhlIHNlcnZlciB2ZXJzaW9uIGZyb20gYWxsIHRoZSBzZXJ2ZXJzXG4gICAqIGluIHRoZSBiYWNrZW5kIHBvb2wsIGVycm9ycyBpZiBhbnkgb25lIG9mIHRoZW0gaGFzIGFuXG4gICAqIGVycm9yXG4gICAqIFxuICAgKiBDYWxsYmFja3MgZnVuY3Rpb25zIGFyZSBjYWxsZWQgYmVmb3JlL2FmdGVyIHdlIHBpbmcgbWVtY2FjaGVkXG4gICAqIGFuZCB1c2VkIHRvIGxvZyB3aGljaCBob3N0cyBhcmUgdGltaW5nIG91dC5cbiAgICovXG4gIGFzeW5jIHZlcnNpb25BbGwoY2FsbGJhY2tzPzoge1xuICAgIGJlZm9yZVBpbmc/OiAoc2VydmVyS2V5OiBzdHJpbmcpID0+IHZvaWQ7XG4gICAgYWZ0ZXJQaW5nPzogKHNlcnZlcktleTogc3RyaW5nKSA9PiB2b2lkO1xuICB9KTogUHJvbWlzZTx7XG4gICAgdmFsdWVzOiBSZWNvcmQ8c3RyaW5nLCBWYWx1ZSB8IG51bGw+O1xuICB9PiB7XG4gICAgY29uc3QgdmVyc2lvbk9iamVjdHMgPSBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIHRoaXMuc2VydmVyS2V5cy5tYXAoKHNlcnZlcktleSkgPT4ge1xuICAgICAgICBjb25zdCBzZXJ2ZXIgPSB0aGlzLnNlcnZlcktleVRvU2VydmVyKHNlcnZlcktleSk7XG4gICAgICAgIGNhbGxiYWNrcz8uYmVmb3JlUGluZz8uKHNlcnZlcktleSk7XG4gICAgICAgIHJldHVybiB0aGlzLl92ZXJzaW9uKHNlcnZlcikudGhlbigocmVzcG9uc2UpID0+IHtcbiAgICAgICAgICBjYWxsYmFja3M/LmFmdGVyUGluZz8uKHNlcnZlcktleSk7XG4gICAgICAgICAgcmV0dXJuIHsgc2VydmVyS2V5OiBzZXJ2ZXJLZXksIHZhbHVlOiByZXNwb25zZS52YWx1ZSB9O1xuICAgICAgICB9KTtcbiAgICAgIH0pXG4gICAgKTtcbiAgICBjb25zdCB2YWx1ZXMgPSB2ZXJzaW9uT2JqZWN0cy5yZWR1Y2UoKGFjY3VtdWxhdG9yLCB2ZXJzaW9uT2JqZWN0KSA9PiB7XG4gICAgICBhY2N1bXVsYXRvclt2ZXJzaW9uT2JqZWN0LnNlcnZlcktleV0gPSB2ZXJzaW9uT2JqZWN0LnZhbHVlO1xuICAgICAgcmV0dXJuIGFjY3VtdWxhdG9yO1xuICAgIH0sIHt9IGFzIFJlY29yZDxzdHJpbmcsIFZhbHVlIHwgbnVsbD4pO1xuICAgIHJldHVybiB7IHZhbHVlczogdmFsdWVzIH07XG4gIH1cblxuICAvKipcbiAgICogQ2xvc2VzIChhYnJ1cHRseSkgY29ubmVjdGlvbnMgdG8gYWxsIHRoZSBzZXJ2ZXJzLlxuICAgKiBAc2VlIHRoaXMucXVpdFxuICAgKi9cbiAgY2xvc2UoKSB7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnNlcnZlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHRoaXMuc2VydmVyc1tpXS5jbG9zZSgpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBQZXJmb3JtIGEgZ2VuZXJpYyBzaW5nbGUgcmVzcG9uc2Ugb3BlcmF0aW9uIChnZXQsIHNldCBldGMpIG9uIG9uZSBzZXJ2ZXJcbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IGtleSB0aGUga2V5IHRvIGhhc2ggdG8gZ2V0IGEgc2VydmVyIGZyb20gdGhlIHBvb2xcbiAgICogQHBhcmFtIHtidWZmZXJ9IHJlcXVlc3QgYSBidWZmZXIgY29udGFpbmluZyB0aGUgcmVxdWVzdFxuICAgKiBAcGFyYW0ge251bWJlcn0gc2VxIHRoZSBzZXF1ZW5jZSBudW1iZXIgb2YgdGhlIG9wZXJhdGlvbi4gSXQgaXMgdXNlZCB0byBwaW4gdGhlIGNhbGxiYWNrc1xuICAgICAgICAgICAgICAgICAgICAgICAgIHRvIGEgc3BlY2lmaWMgb3BlcmF0aW9uIGFuZCBzaG91bGQgbmV2ZXIgY2hhbmdlIGR1cmluZyBhIGBwZXJmb3JtYC5cbiAgICogQHBhcmFtIHtudW1iZXI/fSByZXRyaWVzIG51bWJlciBvZiB0aW1lcyB0byByZXRyeSByZXF1ZXN0IG9uIGZhaWx1cmVcbiAgICovXG4gIHBlcmZvcm0oXG4gICAga2V5OiBzdHJpbmcsXG4gICAgcmVxdWVzdDogQnVmZmVyLFxuICAgIHNlcTogbnVtYmVyLFxuICAgIHJldHJpZXM/OiBudW1iZXJcbiAgKTogUHJvbWlzZTxNZXNzYWdlPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGNvbnN0IHNlcnZlcktleSA9IHRoaXMubG9va3VwS2V5VG9TZXJ2ZXJLZXkoa2V5KTtcbiAgICAgIGNvbnN0IHNlcnZlciA9IHRoaXMuc2VydmVyS2V5VG9TZXJ2ZXIoc2VydmVyS2V5KTtcblxuICAgICAgaWYgKCFzZXJ2ZXIpIHtcbiAgICAgICAgcmV0dXJuIHJlamVjdChuZXcgRXJyb3IoXCJObyBzZXJ2ZXJzIGF2YWlsYWJsZVwiKSk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMucGVyZm9ybU9uU2VydmVyKFxuICAgICAgICBzZXJ2ZXIsXG4gICAgICAgIHJlcXVlc3QsXG4gICAgICAgIHNlcSxcbiAgICAgICAgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgcmV0dXJuIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJlc29sdmUocmVzcG9uc2UhKTtcbiAgICAgICAgfSxcbiAgICAgICAgcmV0cmllc1xuICAgICAgKTtcbiAgICB9KTtcbiAgfVxuXG4gIHBlcmZvcm1PblNlcnZlcihcbiAgICBzZXJ2ZXI6IFNlcnZlcixcbiAgICByZXF1ZXN0OiBCdWZmZXIsXG4gICAgc2VxOiBudW1iZXIsXG4gICAgY2FsbGJhY2s6IFJlc3BvbnNlT3JFcnJvckNhbGxiYWNrLFxuICAgIHJldHJpZXM6IG51bWJlciA9IDBcbiAgKSB7XG4gICAgY29uc3QgX3RoaXMgPSB0aGlzO1xuXG4gICAgcmV0cmllcyA9IHJldHJpZXMgfHwgdGhpcy5vcHRpb25zLnJldHJpZXM7XG4gICAgY29uc3Qgb3JpZ1JldHJpZXMgPSB0aGlzLm9wdGlvbnMucmV0cmllcztcbiAgICBjb25zdCBsb2dnZXIgPSB0aGlzLm9wdGlvbnMubG9nZ2VyO1xuICAgIGNvbnN0IHJldHJ5X2RlbGF5ID0gdGhpcy5vcHRpb25zLnJldHJ5X2RlbGF5O1xuXG4gICAgY29uc3QgcmVzcG9uc2VIYW5kbGVyOiBPblJlc3BvbnNlQ2FsbGJhY2sgPSBmdW5jdGlvbiAocmVzcG9uc2UpIHtcbiAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICBjYWxsYmFjayhudWxsLCByZXNwb25zZSk7XG4gICAgICB9XG4gICAgfTtcblxuICAgIGNvbnN0IGVycm9ySGFuZGxlcjogT25FcnJvckNhbGxiYWNrID0gZnVuY3Rpb24gKGVycm9yKSB7XG4gICAgICBpZiAoLS1yZXRyaWVzID4gMCkge1xuICAgICAgICAvLyBXYWl0IGZvciByZXRyeV9kZWxheVxuICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICBfdGhpcy5wZXJmb3JtT25TZXJ2ZXIoc2VydmVyLCByZXF1ZXN0LCBzZXEsIGNhbGxiYWNrLCByZXRyaWVzKTtcbiAgICAgICAgfSwgMTAwMCAqIHJldHJ5X2RlbGF5KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGxvZ2dlci5sb2coXG4gICAgICAgICAgXCJNZW1KUzogU2VydmVyIDxcIiArXG4gICAgICAgICAgICBzZXJ2ZXIuaG9zdHBvcnRTdHJpbmcoKSArXG4gICAgICAgICAgICBcIj4gZmFpbGVkIGFmdGVyIChcIiArXG4gICAgICAgICAgICBvcmlnUmV0cmllcyArXG4gICAgICAgICAgICBcIikgcmV0cmllcyB3aXRoIGVycm9yIC0gXCIgK1xuICAgICAgICAgICAgZXJyb3IubWVzc2FnZVxuICAgICAgICApO1xuICAgICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgICBjYWxsYmFjayhlcnJvciwgbnVsbCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9O1xuXG4gICAgc2VydmVyLm9uUmVzcG9uc2Uoc2VxLCByZXNwb25zZUhhbmRsZXIpO1xuICAgIHNlcnZlci5vbkVycm9yKHNlcSwgZXJyb3JIYW5kbGVyKTtcbiAgICBzZXJ2ZXIud3JpdGUocmVxdWVzdCk7XG4gIH1cblxuICAvLyBJbmNyZW1lbnQgdGhlIHNlcSB2YWx1ZVxuICBpbmNyU2VxKCkge1xuICAgIHRoaXMuc2VxKys7XG5cbiAgICAvLyBXcmFwIGB0aGlzLnNlcWAgdG8gMzItYml0cyBzaW5jZSB0aGUgZmllbGQgd2UgZml0IGl0IGludG8gaXMgb25seSAzMi1iaXRzLlxuICAgIHRoaXMuc2VxICY9IDB4ZmZmZmZmZmY7XG5cbiAgICByZXR1cm4gdGhpcy5zZXE7XG4gIH1cblxuICBwcml2YXRlIGNyZWF0ZUFuZExvZ0Vycm9yKFxuICAgIGNvbW1hbmROYW1lOiBzdHJpbmcsXG4gICAgcmVzcG9uc2VTdGF0dXM6IFJlc3BvbnNlU3RhdHVzIHwgdW5kZWZpbmVkXG4gICk6IEVycm9yIHtcbiAgICBjb25zdCBlcnJvck1lc3NhZ2UgPSBgTWVtSlMgJHtjb21tYW5kTmFtZX06ICR7Y29uc3RhbnRzLnJlc3BvbnNlU3RhdHVzVG9TdHJpbmcoXG4gICAgICByZXNwb25zZVN0YXR1c1xuICAgICl9YDtcbiAgICB0aGlzLm9wdGlvbnMubG9nZ2VyLmxvZyhlcnJvck1lc3NhZ2UpO1xuICAgIHJldHVybiBuZXcgRXJyb3IoZXJyb3JNZXNzYWdlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBMb2cgYW4gZXJyb3IgdG8gdGhlIGxvZ2dlciwgdGhlbiByZXR1cm4gdGhlIGVycm9yLlxuICAgKiBJZiBhIGNhbGxiYWNrIGlzIGdpdmVuLCBjYWxsIGl0IHdpdGggY2FsbGJhY2soZXJyb3IsIG51bGwpLlxuICAgKi9cbiAgcHJpdmF0ZSBoYW5kbGVSZXNwb25zZUVycm9yKFxuICAgIGNvbW1hbmROYW1lOiBzdHJpbmcsXG4gICAgcmVzcG9uc2VTdGF0dXM6IFJlc3BvbnNlU3RhdHVzIHwgdW5kZWZpbmVkLFxuICAgIGNhbGxiYWNrOiB1bmRlZmluZWQgfCAoKGVycm9yOiBFcnJvciB8IG51bGwsIG90aGVyOiBudWxsKSA9PiB2b2lkKVxuICApOiBFcnJvciB7XG4gICAgY29uc3QgZXJyb3IgPSB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKGNvbW1hbmROYW1lLCByZXNwb25zZVN0YXR1cyk7XG4gICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICBjYWxsYmFjayhlcnJvciwgbnVsbCk7XG4gICAgfVxuICAgIHJldHVybiBlcnJvcjtcbiAgfVxufVxuXG5leHBvcnQgeyBDbGllbnQsIFNlcnZlciwgVXRpbHMsIEhlYWRlciB9O1xuIl19 \ No newline at end of file diff --git a/src/memjs/memjs.ts b/src/memjs/memjs.ts index 6d359bf..a14915a 100644 --- a/src/memjs/memjs.ts +++ b/src/memjs/memjs.ts @@ -913,7 +913,7 @@ class Client { * Retrieves the server version from all the servers * in the backend pool, errors if any one of them has an * error - * + * * Callbacks functions are called before/after we ping memcached * and used to log which hosts are timing out. */ From 9d21572067d35dcd37735f8b5d9df7f9d159be11 Mon Sep 17 00:00:00 2001 From: Ben Hughes Date: Wed, 27 Sep 2023 12:23:31 -0400 Subject: [PATCH 69/79] Add getMultiWithErrors --- lib/memjs/memjs.d.ts | 10 +++++++ lib/memjs/memjs.d.ts.map | 2 +- lib/memjs/memjs.js | 36 ++++++++++++++++++++++++- src/memjs/memjs.ts | 57 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 103 insertions(+), 2 deletions(-) diff --git a/lib/memjs/memjs.d.ts b/lib/memjs/memjs.d.ts index 7d14614..90d55c3 100644 --- a/lib/memjs/memjs.d.ts +++ b/lib/memjs/memjs.d.ts @@ -36,6 +36,15 @@ export interface GetResult { export declare type GetMultiResult = { [K in Keys]?: GetResult; }; +export interface GetMultiError { + error: Error; + serverKey: string; + keys: Keys[]; +} +export interface GetMultiWithErrorsResult { + result: GetMultiResult; + errors: GetMultiError[]; +} declare class Client { servers: Server[]; seq: number; @@ -126,6 +135,7 @@ declare class Client { * requested keys to results, or null if the key was not found. */ getMulti(keys: Keys[]): Promise>; + getMultiWithErrors(keys: Keys[]): Promise>; /** * Sets `key` to `value`. */ diff --git a/lib/memjs/memjs.d.ts.map b/lib/memjs/memjs.d.ts.map index eba3c23..11015ca 100644 --- a/lib/memjs/memjs.d.ts.map +++ b/lib/memjs/memjs.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"memjs.d.ts","sourceRoot":"","sources":["../../src/memjs/memjs.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"memjs.d.ts","sourceRoot":"","sources":["../../src/memjs/memjs.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/lib/memjs/memjs.js b/lib/memjs/memjs.js index f94461e..e95376c 100644 --- a/lib/memjs/memjs.js +++ b/lib/memjs/memjs.js @@ -248,6 +248,40 @@ class Client { })); return Object.assign({}, ...results); } + async getMultiWithErrors(keys) { + const serverKeytoLookupKeys = {}; + keys.forEach((lookupKey) => { + const serverKey = this.lookupKeyToServerKey(lookupKey); + if (!serverKeytoLookupKeys[serverKey]) { + serverKeytoLookupKeys[serverKey] = []; + } + serverKeytoLookupKeys[serverKey].push(lookupKey); + }); + const usedServerKeys = Object.keys(serverKeytoLookupKeys); + const errors = []; + const results = await Promise.all(usedServerKeys.map(async (serverKey) => { + const server = this.serverKeyToServer(serverKey); + try { + return await this._getMultiToServer(server, serverKeytoLookupKeys[serverKey]); + } + catch (err) { + let error; + if (err instanceof Error) { + error = err; + } + else { + error = new Error("Unknown Error"); + error.thrown = err; + } + errors.push({ + error, + serverKey, + keys: serverKeytoLookupKeys[serverKey] + }); + } + })); + return { result: Object.assign({}, ...results), errors }; + } /** * Sets `key` to `value`. */ @@ -742,4 +776,4 @@ class Client { } } exports.Client = Client; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVtanMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbWVtanMvbWVtanMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLHdCQUF3Qjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUV4QixxQ0FLa0I7QUEyaUNELHVGQTdpQ2YsZUFBTSxPQTZpQ2U7QUExaUN2Qix1REFBK0Q7QUFDL0QsbUNBU2lCO0FBQ2pCLHVEQUF5QztBQUN6QywyQ0FBNkM7QUFDN0MsK0NBQWlDO0FBNmhDUixzQkFBSztBQTVoQzlCLGlEQUFtQztBQTRoQ0gsd0JBQU07QUExaEN0QyxTQUFTLDhCQUE4QixDQUNyQyxPQUFpQixFQUNqQixHQUFXO0lBRVgsTUFBTSxLQUFLLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQztJQUM3QixNQUFNLEtBQUssR0FBRyxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxnQkFBUSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3BELE9BQU8sT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ3hCLENBQUM7QUFFRCwrQ0FBK0M7QUFDL0MsU0FBUyxTQUFTLENBQ2hCLE9BQTBFO0lBRTFFLE9BQU8sSUFBSSxPQUFPLENBQUMsVUFBVSxPQUFPLEVBQUUsTUFBTTtRQUMxQyxPQUFPLENBQUMsVUFBVSxHQUFHLEVBQUUsTUFBTTtZQUMzQixHQUFHLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3RDLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBeURELE1BQU0sTUFBTTtJQVFWLDRFQUE0RTtJQUM1RSxtQ0FBbUM7SUFDbkMsWUFBWSxPQUFpQixFQUFFLE9BQTBDO1FBQ3ZFLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO1FBQ3ZCLElB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QUFtQixFQUNuQixjQUEwQztRQUUxQyxNQUFNLFlBQVksR0FBRyxTQUFTLFdBQVcsS0FBSyxTQUFTLENBQUMsc0JBQXNCLENBQzVFLGNBQWMsQ0FDZixFQUFFLENBQUM7UUFDSixJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDdEMsT0FBTyxJQUFJLEtBQUssQ0FBQyxZQUFZLENBQUMsQ0FBQztJQUNqQyxDQUFDO0lBRUQ7OztPQUdHO0lBQ0ssbUJBQW1CLENBQ3pCLFdBQW1CLEVBQ25CLGNBQTBDLEVBQzFDLFFBQWtFO1FBRWxFLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxXQUFXLEVBQUUsY0FBYyxDQUFDLENBQUM7UUFDbEUsSUFBSSxRQUFRLEVBQUU7WUFDWixRQUFRLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxDQUFDO1NBQ3ZCO1FBQ0QsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0NBQ0Y7QUFFUSx3QkFBTSIsInNvdXJjZXNDb250ZW50IjpbIi8vIE1lbVRTIE1lbWNhY2hlIENsaWVudFxuXG5pbXBvcnQge1xuICBPbkVycm9yQ2FsbGJhY2ssXG4gIE9uUmVzcG9uc2VDYWxsYmFjayxcbiAgU2VydmVyLFxuICBTZXJ2ZXJPcHRpb25zLFxufSBmcm9tIFwiLi9zZXJ2ZXJcIjtcbmltcG9ydCB7IG5vb3BTZXJpYWxpemVyLCBTZXJpYWxpemVyIH0gZnJvbSBcIi4vbm9vcC1zZXJpYWxpemVyXCI7XG5pbXBvcnQge1xuICBtYWtlUmVxdWVzdEJ1ZmZlcixcbiAgY29weUludG9SZXF1ZXN0QnVmZmVyLFxuICBtZXJnZSxcbiAgbWFrZUV4cGlyYXRpb24sXG4gIG1ha2VBbW91bnRJbml0aWFsQW5kRXhwaXJhdGlvbixcbiAgaGFzaENvZGUsXG4gIE1heWJlQnVmZmVyLFxuICBNZXNzYWdlLFxufSBmcm9tIFwiLi91dGlsc1wiO1xuaW1wb3J0ICogYXMgY29uc3RhbnRzIGZyb20gXCIuL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgUmVzcG9uc2VTdGF0dXMgfSBmcm9tIFwiLi9jb25zdGFudHNcIjtcbmltcG9ydCAqIGFzIFV0aWxzIGZyb20gXCIuL3V0aWxzXCI7XG5pbXBvcnQgKiBhcyBIZWFkZXIgZnJvbSBcIi4vaGVhZGVyXCI7XG5cbmZ1bmN0aW9uIGRlZmF1bHRLZXlUb1NlcnZlckhhc2hGdW5jdGlvbihcbiAgc2VydmVyczogc3RyaW5nW10sXG4gIGtleTogc3RyaW5nXG4pOiBzdHJpbmcge1xuICBjb25zdCB0b3RhbCA9IHNlcnZlcnMubGVuZ3RoO1xuICBjb25zdCBpbmRleCA9IHRvdGFsID4gMSA/IGhhc2hDb2RlKGtleSkgJSB0b3RhbCA6IDA7XG4gIHJldHVybiBzZXJ2ZXJzW2luZGV4XTtcbn1cblxuLy8gY29udmVydHMgYSBjYWxsIGludG8gYSBwcm9taXNlLXJldHVybmluZyBvbmVcbmZ1bmN0aW9uIHByb21pc2lmeTxSZXN1bHQ+KFxuICBjb21tYW5kOiAoY2FsbGJhY2s6IChlcnJvcjogRXJyb3IgfCBudWxsLCByZXN1bHQ6IFJlc3VsdCkgPT4gdm9pZCkgPT4gdm9pZFxuKTogUHJvbWlzZTxSZXN1bHQ+IHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICBjb21tYW5kKGZ1bmN0aW9uIChlcnIsIHJlc3VsdCkge1xuICAgICAgZXJyID8gcmVqZWN0KGVycikgOiByZXNvbHZlKHJlc3VsdCk7XG4gICAgfSk7XG4gIH0pO1xufVxuXG50eXBlIFJlc3BvbnNlT3JFcnJvckNhbGxiYWNrID0gKFxuICBlcnJvcjogRXJyb3IgfCBudWxsLFxuICByZXNwb25zZTogTWVzc2FnZSB8IG51bGxcbikgPT4gdm9pZDtcblxuaW50ZXJmYWNlIEJhc2VDbGllbnRPcHRpb25zIHtcbiAgcmV0cmllczogbnVtYmVyO1xuICByZXRyeV9kZWxheTogbnVtYmVyO1xuICBleHBpcmVzOiBudW1iZXI7XG4gIGxvZ2dlcjogeyBsb2c6IHR5cGVvZiBjb25zb2xlLmxvZyB9O1xuICBrZXlUb1NlcnZlckhhc2hGdW5jdGlvbjogdHlwZW9mIGRlZmF1bHRLZXlUb1NlcnZlckhhc2hGdW5jdGlvbjtcbn1cblxuaW50ZXJmYWNlIFNlcmlhbGl6ZXJQcm9wPFZhbHVlLCBFeHRyYXM+IHtcbiAgc2VyaWFsaXplcjogU2VyaWFsaXplcjxWYWx1ZSwgRXh0cmFzPjtcbn1cblxuLyoqXG4gKiBUaGUgY2xpZW50IGhhcyBwYXJ0aWFsIHN1cHBvcnQgZm9yIHNlcmlhbGl6aW5nIGFuZCBkZXNlcmlhbGl6aW5nIHZhbHVlcyBmcm9tIHRoZVxuICogQnVmZmVyIGJ5dGUgc3RyaW5ncyB3ZSByZWNlaXZlIGZyb20gdGhlIHdpcmUuIFRoZSBkZWZhdWx0IHNlcmlhbGl6ZXIgaXMgZm9yIE1heWJlQnVmZmVyLlxuICpcbiAqIElmIFZhbHVlIGFuZCBFeHRyYXMgYXJlIG9mIHR5cGUgQnVmZmVyLCB0aGVuIHJldHVybiB0eXBlIFdoZW5CdWZmZXIuIE90aGVyd2lzZSxcbiAqIHJldHVybiB0eXBlIE5vdEJ1ZmZlci5cbiAqL1xudHlwZSBJZkJ1ZmZlcjxWYWx1ZSwgRXh0cmFzLCBXaGVuVmFsdWVBbmRFeHRyYXNBcmVCdWZmZXJzLCBOb3RCdWZmZXI+ID1cbiAgVmFsdWUgZXh0ZW5kcyBCdWZmZXJcbiAgICA/IEV4dHJhcyBleHRlbmRzIEJ1ZmZlclxuICAgICAgPyBXaGVuVmFsdWVBbmRFeHRyYXNBcmVCdWZmZXJzXG4gICAgICA6IE5vdEJ1ZmZlclxuICAgIDogTm90QnVmZmVyO1xuXG5leHBvcnQgdHlwZSBHaXZlbkNsaWVudE9wdGlvbnM8VmFsdWUsIEV4dHJhcz4gPSBQYXJ0aWFsPEJhc2VDbGllbnRPcHRpb25zPiAmXG4gIElmQnVmZmVyPFxuICAgIFZhbHVlLFxuICAgIEV4dHJhcyxcbiAgICBQYXJ0aWFsPFNlcmlhbGl6ZXJQcm9wPFZhbHVlLCBFeHRyYXM+PixcbiAgICBTZXJpYWxpemVyUHJvcDxWYWx1ZSwgRXh0cmFzPlxuICA+O1xuXG5leHBvcnQgdHlwZSBDQVNUb2tlbiA9IEJ1ZmZlcjtcblxuZXhwb3J0IGludGVyZmFjZSBHZXRSZXN1bHQ8VmFsdWUgPSBNYXliZUJ1ZmZlciwgRXh0cmFzID0gTWF5YmVCdWZmZXI+IHtcbiAgdmFsdWU6IFZhbHVlO1xuICBleHRyYXM6IEV4dHJhcztcbiAgY2FzOiBDQVNUb2tlbiB8IHVuZGVmaW5lZDtcbn1cblxuZXhwb3J0IHR5cGUgR2V0TXVsdGlSZXN1bHQ8XG4gIEtleXMgZXh0ZW5kcyBzdHJpbmcgPSBzdHJpbmcsXG4gIFZhbHVlID0gTWF5YmVCdWZmZXIsXG4gIEV4dHJhcyA9IE1heWJlQnVmZmVyXG4+ID0ge1xuICBbSyBpbiBLZXlzXT86IEdldFJlc3VsdDxWYWx1ZSwgRXh0cmFzPjtcbn07XG5cbmNsYXNzIENsaWVudDxWYWx1ZSA9IE1heWJlQnVmZmVyLCBFeHRyYXMgPSBNYXliZUJ1ZmZlcj4ge1xuICBzZXJ2ZXJzOiBTZXJ2ZXJbXTtcbiAgc2VxOiBudW1iZXI7XG4gIG9wdGlvbnM6IEJhc2VDbGllbnRPcHRpb25zICYgUGFydGlhbDxTZXJpYWxpemVyUHJvcDxWYWx1ZSwgRXh0cmFzPj47XG4gIHNlcmlhbGl6ZXI6IFNlcmlhbGl6ZXI8VmFsdWUsIEV4dHJhcz47XG4gIHNlcnZlck1hcDogeyBbaG9zdHBvcnQ6IHN0cmluZ106IFNlcnZlciB9O1xuICBzZXJ2ZXJLZXlzOiBzdHJpbmdbXTtcblxuICAvLyBDbGllbnQgaW5pdGlhbGl6ZXIgdGFrZXMgYSBsaXN0IG9mIGBTZXJ2ZXJgcyBhbmQgYW4gYG9wdGlvbnNgIGRpY3Rpb25hcnkuXG4gIC8vIFNlZSBgQ2xpZW50LmNyZWF0ZWAgZm9yIGRldGFpbHMuXG4gIGNvbnN0cnVjdG9yKHNlcnZlcnM6IFNlcnZlcltdLCBvcHRpb25zOiBHaXZlbkNsaWVudE9wdGlvbnM8VmFsdWUsIEV4dHJhcz4pIHtcbiAgICB0aGlzLnNlcnZlcnMgPSBzZXJ2ZXJzO1xuICAgIHRoaXMuc2VxID0gMDtcbiAgICB0aGlzLm9wdGlvbnMgPSBtZXJnZShvcHRpb25zIHx8IHt9LCB7XG4gICAgICByZXRyaWVzOiAyLFxuICAgICAgcmV0cnlfZGVsYXk6IDAuMixcbiAgICAgIGV4cGlyZXM6IDAsXG4gICAgICBsb2dnZXI6IGNvbnNvbGUsXG4gICAgICBrZXlUb1NlcnZlckhhc2hGdW5jdGlvbjogZGVmYXVsdEtleVRvU2VydmVySGFzaEZ1bmN0aW9uLFxuICAgIH0pO1xuXG4gICAgdGhpcy5zZXJpYWxpemVyID0gdGhpcy5vcHRpb25zLnNlcmlhbGl6ZXIgfHwgKG5vb3BTZXJpYWxpemVyIGFzIGFueSk7XG5cbiAgICAvLyBTdG9yZSBhIG1hcHBpbmcgZnJvbSBob3N0cG9ydCAtPiBzZXJ2ZXIgc28gd2UgY2FuIHF1aWNrbHkgZ2V0IGEgc2VydmVyIG9iamVjdCBmcm9tIHRoZSBzZXJ2ZXJLZXkgcmV0dXJuZWQgYnkgdGhlIGhhc2hpbmcgZnVuY3Rpb25cbiAgICBjb25zdCBzZXJ2ZXJNYXA6IHsgW2hvc3Rwb3J0OiBzdHJpbmddOiBTZXJ2ZXIgfSA9IHt9O1xuICAgIHRoaXMuc2VydmVycy5mb3JFYWNoKGZ1bmN0aW9uIChzZXJ2ZXIpIHtcbiAgICAgIHNlcnZlck1hcFtzZXJ2ZXIuaG9zdHBvcnRTdHJpbmcoKV0gPSBzZXJ2ZXI7XG4gICAgfSk7XG4gICAgdGhpcy5zZXJ2ZXJNYXAgPSBzZXJ2ZXJNYXA7XG5cbiAgICAvLyBzdG9yZSBhIGxpc3Qgb2YgYWxsIG91ciBzZXJ2ZXJLZXlzIHNvIHdlIGRvbid0IG5lZWQgdG8gY29uc3RhbnRseSByZWFsbG9jYXRlIHRoaXMgYXJyYXlcbiAgICB0aGlzLnNlcnZlcktleXMgPSBPYmplY3Qua2V5cyh0aGlzLnNlcnZlck1hcCk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIG5ldyBjbGllbnQgZ2l2ZW4gYW4gb3B0aW9uYWwgY29uZmlnIHN0cmluZyBhbmQgb3B0aW9uYWwgaGFzaCBvZlxuICAgKiBvcHRpb25zLiBUaGUgY29uZmlnIHN0cmluZyBzaG91bGQgYmUgb2YgdGhlIGZvcm06XG4gICAqXG4gICAqICAgICBcIlt1c2VyOnBhc3NAXXNlcnZlcjFbOjExMjExXSxbdXNlcjpwYXNzQF1zZXJ2ZXIyWzoxMTIxMV0sLi4uXCJcbiAgICpcbiAgICogSWYgdGhlIGFyZ3VtZW50IGlzIG5vdCBnaXZlbiwgZmFsbGJhY2sgb24gdGhlIGBNRU1DQUNISUVSX1NFUlZFUlNgIGVudmlyb25tZW50XG4gICAqIHZhcmlhYmxlLCBgTUVNQ0FDSEVfU0VSVkVSU2AgZW52aXJvbm1lbnQgdmFyaWFibGUgb3IgYFwibG9jYWxob3N0OjExMjExXCJgLlxuICAgKlxuICAgKiBUaGUgb3B0aW9ucyBoYXNoIG1heSBjb250YWluIHRoZSBvcHRpb25zOlxuICAgKlxuICAgKiAqIGByZXRyaWVzYCAtIHRoZSBudW1iZXIgb2YgdGltZXMgdG8gcmV0cnkgYW4gb3BlcmF0aW9uIGluIGxpZXUgb2YgZmFpbHVyZXNcbiAgICogKGRlZmF1bHQgMilcbiAgICogKiBgZXhwaXJlc2AgLSB0aGUgZGVmYXVsdCBleHBpcmF0aW9uIGluIHNlY29uZHMgdG8gdXNlIChkZWZhdWx0IDAgLSBuZXZlclxuICAgKiBleHBpcmUpLiBJZiBgZXhwaXJlc2AgaXMgZ3JlYXRlciB0aGFuIDMwIGRheXMgKDYwIHggNjAgeCAyNCB4IDMwKSwgaXQgaXNcbiAgICogdHJlYXRlZCBhcyBhIFVOSVggdGltZSAobnVtYmVyIG9mIHNlY29uZHMgc2luY2UgSmFudWFyeSAxLCAxOTcwKS5cbiAgICogKiBgbG9nZ2VyYCAtIGEgbG9nZ2VyIG9iamVjdCB0aGF0IHJlc3BvbmRzIHRvIGBsb2coc3RyaW5nKWAgbWV0aG9kIGNhbGxzLlxuICAgKlxuICAgKiAgIH5+fn5cbiAgICogICAgIGxvZyhtc2cxWywgbXNnMlssIG1zZzNbLi4uXV1dKVxuICAgKiAgIH5+fn5cbiAgICpcbiAgICogICBEZWZhdWx0cyB0byBgY29uc29sZWAuXG4gICAqICogYHNlcmlhbGl6ZXJgIC0gdGhlIG9iamVjdCB3aGljaCB3aWxsIChkZSlzZXJpYWxpemUgdGhlIGRhdGEuIEl0IG5lZWRzXG4gICAqICAgdHdvIHB1YmxpYyBtZXRob2RzOiBzZXJpYWxpemUgYW5kIGRlc2VyaWFsaXplLiBJdCBkZWZhdWx0cyB0byB0aGVcbiAgICogICBub29wU2VyaWFsaXplcjpcbiAgICpcbiAgICogICB+fn5+XG4gICAqICAgY29uc3Qgbm9vcFNlcmlhbGl6ZXIgPSB7XG4gICAqICAgICBzZXJpYWxpemU6IGZ1bmN0aW9uIChvcGNvZGUsIHZhbHVlLCBleHRyYXMpIHtcbiAgICogICAgICAgcmV0dXJuIHsgdmFsdWU6IHZhbHVlLCBleHRyYXM6IGV4dHJhcyB9O1xuICAgKiAgICAgfSxcbiAgICogICAgIGRlc2VyaWFsaXplOiBmdW5jdGlvbiAob3Bjb2RlLCB2YWx1ZSwgZXh0cmFzKSB7XG4gICAqICAgICAgIHJldHVybiB7IHZhbHVlOiB2YWx1ZSwgZXh0cmFzOiBleHRyYXMgfTtcbiAgICogICAgIH1cbiAgICogICB9O1xuICAgKiAgIH5+fn5cbiAgICpcbiAgICogT3Igb3B0aW9ucyBmb3IgdGhlIHNlcnZlcnMgaW5jbHVkaW5nOlxuICAgKiAqIGB1c2VybmFtZWAgYW5kIGBwYXNzd29yZGAgZm9yIGZhbGxiYWNrIFNBU0wgYXV0aGVudGljYXRpb24gY3JlZGVudGlhbHMuXG4gICAqICogYHRpbWVvdXRgIGluIHNlY29uZHMgdG8gZGV0ZXJtaW5lIGZhaWx1cmUgZm9yIG9wZXJhdGlvbnMuIERlZmF1bHQgaXMgMC41XG4gICAqICAgICAgICAgICAgIHNlY29uZHMuXG4gICAqICogJ2Nvbm50aW1lb3V0JyBpbiBzZWNvbmRzIHRvIGNvbm5lY3Rpb24gZmFpbHVyZS4gRGVmYXVsdCBpcyB0d2ljZSB0aGUgdmFsdWVcbiAgICogICAgICAgICAgICAgICAgIG9mIGB0aW1lb3V0YC5cbiAgICogKiBga2VlcEFsaXZlYCB3aGV0aGVyIHRvIGVuYWJsZSBrZWVwLWFsaXZlIGZ1bmN0aW9uYWxpdHkuIERlZmF1bHRzIHRvIGZhbHNlLlxuICAgKiAqIGBrZWVwQWxpdmVEZWxheWAgaW4gc2Vjb25kcyB0byB0aGUgaW5pdGlhbCBkZWxheSBiZWZvcmUgdGhlIGZpcnN0IGtlZXBhbGl2ZVxuICAgKiAgICAgICAgICAgICAgICAgICAgcHJvYmUgaXMgc2VudCBvbiBhbiBpZGxlIHNvY2tldC4gRGVmYXVsdHMgaXMgMzAgc2Vjb25kcy5cbiAgICogKiBga2V5VG9TZXJ2ZXJIYXNoRnVuY3Rpb25gIGEgZnVuY3Rpb24gdG8gbWFwIGtleXMgdG8gc2VydmVycywgd2l0aCB0aGUgc2lnbmF0dXJlXG4gICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgIChzZXJ2ZXJLZXlzOiBzdHJpbmdbXSwga2V5OiBzdHJpbmcpOiBzdHJpbmdcbiAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgTk9URTogaWYgeW91IG5lZWQgdG8gZG8gc29tZSBleHBlbnNpdmUgaW5pdGlhbGl6YXRpb24sICpwbGVhc2UqIGRvIGl0IGxhemlseSB0aGUgZmlyc3QgdGltZSB5b3UgdGhpcyBmdW5jdGlvbiBpcyBjYWxsZWQgd2l0aCBhbiBhcnJheSBvZiBzZXJ2ZXJLZXlzLCBub3Qgb24gZXZlcnkgY2FsbFxuICAgKi9cbiAgc3RhdGljIGNyZWF0ZTxWYWx1ZSwgRXh0cmFzPihcbiAgICBzZXJ2ZXJzU3RyOiBzdHJpbmcgfCB1bmRlZmluZWQsXG4gICAgb3B0aW9uczogSWZCdWZmZXI8XG4gICAgICBWYWx1ZSxcbiAgICAgIEV4dHJhcyxcbiAgICAgIHVuZGVmaW5lZCB8IChQYXJ0aWFsPFNlcnZlck9wdGlvbnM+ICYgR2l2ZW5DbGllbnRPcHRpb25zPFZhbHVlLCBFeHRyYXM+KSxcbiAgICAgIFBhcnRpYWw8U2VydmVyT3B0aW9ucz4gJiBHaXZlbkNsaWVudE9wdGlvbnM8VmFsdWUsIEV4dHJhcz5cbiAgICA+XG4gICk6IENsaWVudDxWYWx1ZSwgRXh0cmFzPiB7XG4gICAgc2VydmVyc1N0ciA9XG4gICAgICBzZXJ2ZXJzU3RyIHx8XG4gICAgICBwcm9jZXNzLmVudi5NRU1DQUNISUVSX1NFUlZFUlMgfHxcbiAgICAgIHByb2Nlc3MuZW52Lk1FTUNBQ0hFX1NFUlZFUlMgfHxcbiAgICAgIFwibG9jYWxob3N0OjExMjExXCI7XG4gICAgY29uc3Qgc2VydmVyVXJpcyA9IHNlcnZlcnNTdHIuc3BsaXQoXCIsXCIpO1xuICAgIGNvbnN0IHNlcnZlcnMgPSBzZXJ2ZXJVcmlzLm1hcChmdW5jdGlvbiAodXJpKSB7XG4gICAgICBjb25zdCB1cmlQYXJ0cyA9IHVyaS5zcGxpdChcIkBcIik7XG4gICAgICBjb25zdCBob3N0UG9ydCA9IHVyaVBhcnRzW3VyaVBhcnRzLmxlbmd0aCAtIDFdLnNwbGl0KFwiOlwiKTtcbiAgICAgIGNvbnN0IHVzZXJQYXNzID0gKHVyaVBhcnRzW3VyaVBhcnRzLmxlbmd0aCAtIDJdIHx8IFwiXCIpLnNwbGl0KFwiOlwiKTtcbiAgICAgIHJldHVybiBuZXcgU2VydmVyKFxuICAgICAgICBob3N0UG9ydFswXSxcbiAgICAgICAgcGFyc2VJbnQoaG9zdFBvcnRbMV0gfHwgXCIxMTIxMVwiLCAxMCksXG4gICAgICAgIHVzZXJQYXNzWzBdLFxuICAgICAgICB1c2VyUGFzc1sxXSxcbiAgICAgICAgb3B0aW9uc1xuICAgICAgKTtcbiAgICB9KTtcbiAgICByZXR1cm4gbmV3IENsaWVudChzZXJ2ZXJzLCBvcHRpb25zIGFzIGFueSk7XG4gIH1cblxuICAvKipcbiAgICogR2l2ZW4gYSBzZXJ2ZXJLZXkgZnJvbWxvb2t1cEtleVRvU2VydmVyS2V5LCByZXR1cm4gdGhlIGNvcnJlc3BvbmRpbmcgU2VydmVyIGluc3RhbmNlXG4gICAqXG4gICAqIEBwYXJhbSAge3N0cmluZ30gc2VydmVyS2V5XG4gICAqIEByZXR1cm5zIHtTZXJ2ZXJ9XG4gICAqL1xuICBzZXJ2ZXJLZXlUb1NlcnZlcihzZXJ2ZXJLZXk6IHN0cmluZyk6IFNlcnZlciB7XG4gICAgcmV0dXJuIHRoaXMuc2VydmVyTWFwW3NlcnZlcktleV07XG4gIH1cblxuICAvKipcbiAgICogR2l2ZW4gYSBrZXkgdG8gbG9vayB1cCBpbiBtZW1jYWNoZSwgcmV0dXJuIGEgc2VydmVyS2V5IChiYXNlZCBvbiBzb21lXG4gICAqIGhhc2hpbmcgZnVuY3Rpb24pIHdoaWNoIGNhbiBiZSB1c2VkIHRvIGluZGV4IHRoaXMuc2VydmVyTWFwXG4gICAqL1xuICBsb29rdXBLZXlUb1NlcnZlcktleShrZXk6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMub3B0aW9ucy5rZXlUb1NlcnZlckhhc2hGdW5jdGlvbih0aGlzLnNlcnZlcktleXMsIGtleSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldmVzIHRoZSB2YWx1ZSBhdCB0aGUgZ2l2ZW4ga2V5IGluIG1lbWNhY2hlLlxuICAgKi9cbiAgYXN5bmMgZ2V0KGtleTogc3RyaW5nKTogUHJvbWlzZTxHZXRSZXN1bHQ8VmFsdWUsIEV4dHJhcz4gfCBudWxsPiB7XG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKGNvbnN0YW50cy5PUF9HRVQsIGtleSwgXCJcIiwgXCJcIiwgdGhpcy5zZXEpO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICBjb25zdCBkZXNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuZGVzZXJpYWxpemUoXG4gICAgICAgICAgcmVzcG9uc2UuaGVhZGVyLm9wY29kZSxcbiAgICAgICAgICByZXNwb25zZS52YWwsXG4gICAgICAgICAgcmVzcG9uc2UuZXh0cmFzXG4gICAgICAgICk7XG4gICAgICAgIHJldHVybiB7IC4uLmRlc2VyaWFsaXplZCwgY2FzOiByZXNwb25zZS5oZWFkZXIuY2FzIH07XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIkdFVFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKiogQnVpbGQgYSBwaXBlbGluZWQgZ2V0IG11bHRpIHJlcXVlc3QgYnkgc2VuZGluZyBvbmUgR0VUS1EgZm9yIGVhY2gga2V5IChxdWlldCwgbWVhbmluZyBpdCB3b24ndCByZXNwb25kIGlmIHRoZSB2YWx1ZSBpcyBtaXNzaW5nKSBmb2xsb3dlZCBieSBhIG5vLW9wIHRvIGZvcmNlIGEgcmVzcG9uc2UgKGFuZCB0byBnaXZlIHVzIGEgc2VudGluZWwgcmVzcG9uc2UgdGhhdCB0aGUgcGlwZWxpbmUgaXMgZG9uZSlcbiAgICpcbiAgICogY2YgaHR0cHM6Ly9naXRodWIuY29tL2NvdWNoYmFzZS9tZW1jYWNoZWQvYmxvYi9tYXN0ZXIvZG9jcy9CaW5hcnlQcm90b2NvbC5tZCMweDBkLWdldGtxLWdldC13aXRoLWtleS1xdWlldGx5XG4gICAqL1xuICBfYnVpbGRHZXRNdWx0aVJlcXVlc3Qoa2V5czogc3RyaW5nW10sIHNlcTogbnVtYmVyKTogQnVmZmVyIHtcbiAgICAvLyBzdGFydCBhdCAyNCBmb3IgdGhlIG5vLW9wIGNvbW1hbmQgYXQgdGhlIGVuZFxuICAgIGxldCByZXF1ZXN0U2l6ZSA9IDI0O1xuICAgIGZvciAoY29uc3Qga2V5SWR4IGluIGtleXMpIHtcbiAgICAgIHJlcXVlc3RTaXplICs9IEJ1ZmZlci5ieXRlTGVuZ3RoKGtleXNba2V5SWR4XSwgXCJ1dGY4XCIpICsgMjQ7XG4gICAgfVxuXG4gICAgY29uc3QgcmVxdWVzdCA9IEJ1ZmZlci5hbGxvYyhyZXF1ZXN0U2l6ZSk7XG5cbiAgICBsZXQgYnl0ZXNXcml0dGVuID0gMDtcbiAgICBmb3IgKGNvbnN0IGtleUlkeCBpbiBrZXlzKSB7XG4gICAgICBjb25zdCBrZXkgPSBrZXlzW2tleUlkeF07XG4gICAgICBieXRlc1dyaXR0ZW4gKz0gY29weUludG9SZXF1ZXN0QnVmZmVyKFxuICAgICAgICBjb25zdGFudHMuT1BfR0VUS1EsXG4gICAgICAgIGtleSxcbiAgICAgICAgXCJcIixcbiAgICAgICAgXCJcIixcbiAgICAgICAgc2VxLFxuICAgICAgICByZXF1ZXN0LFxuICAgICAgICBieXRlc1dyaXR0ZW5cbiAgICAgICk7XG4gICAgfVxuXG4gICAgYnl0ZXNXcml0dGVuICs9IGNvcHlJbnRvUmVxdWVzdEJ1ZmZlcihcbiAgICAgIGNvbnN0YW50cy5PUF9OT19PUCxcbiAgICAgIFwiXCIsXG4gICAgICBcIlwiLFxuICAgICAgXCJcIixcbiAgICAgIHNlcSxcbiAgICAgIHJlcXVlc3QsXG4gICAgICBieXRlc1dyaXR0ZW5cbiAgICApO1xuXG4gICAgcmV0dXJuIHJlcXVlc3Q7XG4gIH1cblxuICAvKiogRXhlY3V0aW5nIGEgcGlwZWxpbmVkIChtdWx0aSkgZ2V0IGFnYWluc3QgYSBzaW5nbGUgc2VydmVyLiBUaGlzIGlzIGEgcHJpdmF0ZSBpbXBsZW1lbnRhdGlvbiBkZXRhaWwgb2YgZ2V0TXVsdGkuICovXG4gIGFzeW5jIF9nZXRNdWx0aVRvU2VydmVyPEtleXMgZXh0ZW5kcyBzdHJpbmc+KFxuICAgIHNlcnY6IFNlcnZlcixcbiAgICBrZXlzOiBLZXlzW11cbiAgKTogUHJvbWlzZTxHZXRNdWx0aVJlc3VsdDxLZXlzLCBWYWx1ZSwgRXh0cmFzPj4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBjb25zdCByZXNwb25zZU1hcDogR2V0TXVsdGlSZXN1bHQ8c3RyaW5nLCBWYWx1ZSwgRXh0cmFzPiA9IHt9O1xuXG4gICAgICBjb25zdCBoYW5kbGU6IE9uUmVzcG9uc2VDYWxsYmFjayA9IChyZXNwb25zZSkgPT4ge1xuICAgICAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgICAgICAvLyBXaGVuIHdlIGdldCB0aGUgbm8tb3AgcmVzcG9uc2UsIHdlIGFyZSBkb25lIHdpdGggdGhpcyBvbmUgZ2V0TXVsdGkgaW4gdGhlIHBlci1iYWNrZW5kIGZhbi1vdXRcbiAgICAgICAgICAgIGlmIChyZXNwb25zZS5oZWFkZXIub3Bjb2RlID09PSBjb25zdGFudHMuT1BfTk9fT1ApIHtcbiAgICAgICAgICAgICAgLy8gVGhpcyBlbnN1cmVzIHRoZSBoYW5kbGVyIHdpbGwgYmUgZGVsZXRlZCBmcm9tIHRoZSByZXNwb25zZUNhbGxiYWNrcyBtYXAgaW4gc2VydmVyLmpzXG4gICAgICAgICAgICAgIC8vIFRoaXMgaXNuJ3QgdGVjaG5pY2FsbHkgbmVlZGVkIGhlcmUgYmVjYXVzZSB0aGUgbG9naWMgaW4gc2VydmVyLmpzIGFsc28gY2hlY2tzIGlmIHRvdGFsQm9keUxlbmd0aCA9PT0gMCwgYnV0IG91ciB1bml0dGVzdHMgYXJlbid0IGdyZWF0IGFib3V0IHNldHRpbmcgdGhhdCBmaWVsZCwgYW5kIGFsc28gdGhpcyBtYWtlcyBpdCBtb3JlIGV4cGxpY2l0XG4gICAgICAgICAgICAgIGhhbmRsZS5xdWlldCA9IGZhbHNlO1xuICAgICAgICAgICAgICByZXNvbHZlKHJlc3BvbnNlTWFwKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgICAgICAgIHJlc3BvbnNlLmhlYWRlci5vcGNvZGUgPT09IGNvbnN0YW50cy5PUF9HRVRLIHx8XG4gICAgICAgICAgICAgIHJlc3BvbnNlLmhlYWRlci5vcGNvZGUgPT09IGNvbnN0YW50cy5PUF9HRVRLUVxuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgIGNvbnN0IGRlc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5kZXNlcmlhbGl6ZShcbiAgICAgICAgICAgICAgICByZXNwb25zZS5oZWFkZXIub3Bjb2RlLFxuICAgICAgICAgICAgICAgIHJlc3BvbnNlLnZhbCxcbiAgICAgICAgICAgICAgICByZXNwb25zZS5leHRyYXNcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgY29uc3Qga2V5ID0gcmVzcG9uc2Uua2V5LnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgIGlmIChrZXkubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlamVjdChcbiAgICAgICAgICAgICAgICAgIG5ldyBFcnJvcihcbiAgICAgICAgICAgICAgICAgICAgXCJSZWNpZXZlZCBlbXB0eSBrZXkgaW4gZ2V0TXVsdGk6IFwiICtcbiAgICAgICAgICAgICAgICAgICAgICBKU09OLnN0cmluZ2lmeShyZXNwb25zZSlcbiAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIHJlc3BvbnNlTWFwW2tleV0gPSB7IC4uLmRlc2VyaWFsaXplZCwgY2FzOiByZXNwb25zZS5oZWFkZXIuY2FzIH07XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICByZXR1cm4gcmVqZWN0KFxuICAgICAgICAgICAgICAgIG5ldyBFcnJvcihcbiAgICAgICAgICAgICAgICAgIFwiUmVjaWV2ZWQgcmVzcG9uc2UgaW4gZ2V0TXVsdGkgZm9yIHVua25vd24gb3Bjb2RlOiBcIiArXG4gICAgICAgICAgICAgICAgICAgIEpTT04uc3RyaW5naWZ5KHJlc3BvbnNlKVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICByZXR1cm4gcmVqZWN0KFxuICAgICAgICAgICAgICB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiR0VUXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9O1xuICAgICAgLy8gVGhpcyBwcmV2ZW50cyB0aGUgaGFuZGxlciBmcm9tIGJlaW5nIGRlbGV0ZWRcbiAgICAgIC8vIGFmdGVyIHRoZSBmaXJzdCByZXNwb25zZS4gTG9naWMgaW4gc2VydmVyLmpzLlxuICAgICAgaGFuZGxlLnF1aWV0ID0gdHJ1ZTtcblxuICAgICAgY29uc3Qgc2VxID0gdGhpcy5pbmNyU2VxKCk7XG4gICAgICBjb25zdCByZXF1ZXN0ID0gdGhpcy5fYnVpbGRHZXRNdWx0aVJlcXVlc3Qoa2V5cywgc2VxKTtcbiAgICAgIHNlcnYub25SZXNwb25zZSh0aGlzLnNlcSwgaGFuZGxlKTtcbiAgICAgIHNlcnYub25FcnJvcih0aGlzLnNlcSwgcmVqZWN0KTtcbiAgICAgIHNlcnYud3JpdGUocmVxdWVzdCk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldnMgdGhlIHZhbHVlIGF0IHRoZSBnaXZlbiBrZXlzIGluIG1lbWNhY2hlZC4gUmV0dXJucyBhIG1hcCBmcm9tIHRoZVxuICAgKiByZXF1ZXN0ZWQga2V5cyB0byByZXN1bHRzLCBvciBudWxsIGlmIHRoZSBrZXkgd2FzIG5vdCBmb3VuZC5cbiAgICovXG4gIGFzeW5jIGdldE11bHRpPEtleXMgZXh0ZW5kcyBzdHJpbmc+KFxuICAgIGtleXM6IEtleXNbXVxuICApOiBQcm9taXNlPEdldE11bHRpUmVzdWx0PEtleXMsIFZhbHVlLCBFeHRyYXM+PiB7XG4gICAgY29uc3Qgc2VydmVyS2V5dG9Mb29rdXBLZXlzOiB7XG4gICAgICBbc2VydmVyS2V5OiBzdHJpbmddOiBzdHJpbmdbXTtcbiAgICB9ID0ge307XG4gICAga2V5cy5mb3JFYWNoKChsb29rdXBLZXkpID0+IHtcbiAgICAgIGNvbnN0IHNlcnZlcktleSA9IHRoaXMubG9va3VwS2V5VG9TZXJ2ZXJLZXkobG9va3VwS2V5KTtcbiAgICAgIGlmICghc2VydmVyS2V5dG9Mb29rdXBLZXlzW3NlcnZlcktleV0pIHtcbiAgICAgICAgc2VydmVyS2V5dG9Mb29rdXBLZXlzW3NlcnZlcktleV0gPSBbXTtcbiAgICAgIH1cbiAgICAgIHNlcnZlcktleXRvTG9va3VwS2V5c1tzZXJ2ZXJLZXldLnB1c2gobG9va3VwS2V5KTtcbiAgICB9KTtcblxuICAgIGNvbnN0IHVzZWRTZXJ2ZXJLZXlzID0gT2JqZWN0LmtleXMoc2VydmVyS2V5dG9Mb29rdXBLZXlzKTtcbiAgICBjb25zdCByZXN1bHRzID0gYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICB1c2VkU2VydmVyS2V5cy5tYXAoKHNlcnZlcktleSkgPT4ge1xuICAgICAgICBjb25zdCBzZXJ2ZXIgPSB0aGlzLnNlcnZlcktleVRvU2VydmVyKHNlcnZlcktleSk7XG4gICAgICAgIHJldHVybiB0aGlzLl9nZXRNdWx0aVRvU2VydmVyKHNlcnZlciwgc2VydmVyS2V5dG9Mb29rdXBLZXlzW3NlcnZlcktleV0pO1xuICAgICAgfSlcbiAgICApO1xuXG4gICAgcmV0dXJuIE9iamVjdC5hc3NpZ24oe30sIC4uLnJlc3VsdHMpO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgYGtleWAgdG8gYHZhbHVlYC5cbiAgICovXG4gIGFzeW5jIHNldChcbiAgICBrZXk6IHN0cmluZyxcbiAgICB2YWx1ZTogVmFsdWUsXG4gICAgb3B0aW9ucz86IHsgZXhwaXJlcz86IG51bWJlcjsgY2FzPzogQ0FTVG9rZW4gfVxuICApOiBQcm9taXNlPGJvb2xlYW4gfCBudWxsPiB7XG4gICAgY29uc3QgZXhwaXJlcyA9IG9wdGlvbnM/LmV4cGlyZXM7XG4gICAgY29uc3QgY2FzID0gb3B0aW9ucz8uY2FzO1xuXG4gICAgLy8gVE9ETzogc3VwcG9ydCBmbGFnc1xuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IGV4cGlyYXRpb24gPSBtYWtlRXhwaXJhdGlvbihleHBpcmVzIHx8IHRoaXMub3B0aW9ucy5leHBpcmVzKTtcbiAgICBjb25zdCBleHRyYXMgPSBCdWZmZXIuY29uY2F0KFtCdWZmZXIuZnJvbShcIjAwMDAwMDAwXCIsIFwiaGV4XCIpLCBleHBpcmF0aW9uXSk7XG4gICAgY29uc3Qgc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5zZXJpYWxpemUoXG4gICAgICBjb25zdGFudHMuT1BfU0VULFxuICAgICAgdmFsdWUsXG4gICAgICBleHRyYXNcbiAgICApO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBVdGlscy5lbmNvZGVSZXF1ZXN0KHtcbiAgICAgIGhlYWRlcjoge1xuICAgICAgICBvcGNvZGU6IGNvbnN0YW50cy5PUF9TRVQsXG4gICAgICAgIG9wYXF1ZTogdGhpcy5zZXEsXG4gICAgICAgIGNhcyxcbiAgICAgIH0sXG4gICAgICBrZXksXG4gICAgICB2YWx1ZTogc2VyaWFsaXplZC52YWx1ZSxcbiAgICAgIGV4dHJhczogc2VyaWFsaXplZC5leHRyYXMsXG4gICAgfSk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfRVhJU1RTOlxuICAgICAgICBpZiAoY2FzKSB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJTRVRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgICAgIH1cbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJTRVRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEFERFxuICAgKlxuICAgKiBBZGRzIHRoZSBnaXZlbiBfa2V5XyBhbmQgX3ZhbHVlXyB0byBtZW1jYWNoZS4gVGhlIG9wZXJhdGlvbiBvbmx5IHN1Y2NlZWRzXG4gICAqIGlmIHRoZSBrZXkgaXMgbm90IGFscmVhZHkgc2V0LlxuICAgKlxuICAgKiBUaGUgb3B0aW9ucyBkaWN0aW9uYXJ5IHRha2VzOlxuICAgKiAqIF9leHBpcmVzXzogb3ZlcnJpZGVzIHRoZSBkZWZhdWx0IGV4cGlyYXRpb24gKHNlZSBgQ2xpZW50LmNyZWF0ZWApIGZvciB0aGlzXG4gICAqICAgICAgICAgICAgICBwYXJ0aWN1bGFyIGtleS12YWx1ZSBwYWlyLlxuICAgKi9cbiAgYXN5bmMgYWRkKFxuICAgIGtleTogc3RyaW5nLFxuICAgIHZhbHVlOiBWYWx1ZSxcbiAgICBvcHRpb25zPzogeyBleHBpcmVzPzogbnVtYmVyIH1cbiAgKTogUHJvbWlzZTxib29sZWFuIHwgbnVsbD4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgZmxhZ3MsIHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IGV4cGlyYXRpb24gPSBtYWtlRXhwaXJhdGlvbihvcHRpb25zPy5leHBpcmVzIHx8IHRoaXMub3B0aW9ucy5leHBpcmVzKTtcbiAgICBjb25zdCBleHRyYXMgPSBCdWZmZXIuY29uY2F0KFtCdWZmZXIuZnJvbShcIjAwMDAwMDAwXCIsIFwiaGV4XCIpLCBleHBpcmF0aW9uXSk7XG5cbiAgICBjb25zdCBvcGNvZGUgPSBjb25zdGFudHMuT1BfQUREO1xuICAgIGNvbnN0IHNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuc2VyaWFsaXplKG9wY29kZSwgdmFsdWUsIGV4dHJhcyk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKFxuICAgICAgb3Bjb2RlLFxuICAgICAga2V5LFxuICAgICAgc2VyaWFsaXplZC5leHRyYXMsXG4gICAgICBzZXJpYWxpemVkLnZhbHVlLFxuICAgICAgdGhpcy5zZXFcbiAgICApO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuS0VZX0VYSVNUUzpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJBRERcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlcGxhY2VzIHRoZSBnaXZlbiBfa2V5XyBhbmQgX3ZhbHVlXyB0byBtZW1jYWNoZS4gVGhlIG9wZXJhdGlvbiBvbmx5IHN1Y2NlZWRzXG4gICAqIGlmIHRoZSBrZXkgaXMgYWxyZWFkeSBwcmVzZW50LlxuICAgKi9cbiAgYXN5bmMgcmVwbGFjZShcbiAgICBrZXk6IHN0cmluZyxcbiAgICB2YWx1ZTogVmFsdWUsXG4gICAgb3B0aW9ucz86IHsgZXhwaXJlcz86IG51bWJlciB9XG4gICk6IFByb21pc2U8Ym9vbGVhbiB8IG51bGw+IHtcbiAgICAvLyBUT0RPOiBzdXBwb3J0IGZsYWdzLCBzdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBleHBpcmF0aW9uID0gbWFrZUV4cGlyYXRpb24ob3B0aW9ucz8uZXhwaXJlcyB8fCB0aGlzLm9wdGlvbnMuZXhwaXJlcyk7XG4gICAgY29uc3QgZXh0cmFzID0gQnVmZmVyLmNvbmNhdChbQnVmZmVyLmZyb20oXCIwMDAwMDAwMFwiLCBcImhleFwiKSwgZXhwaXJhdGlvbl0pO1xuXG4gICAgY29uc3Qgb3Bjb2RlOiBjb25zdGFudHMuT1AgPSBjb25zdGFudHMuT1BfUkVQTEFDRTtcbiAgICBjb25zdCBzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLnNlcmlhbGl6ZShvcGNvZGUsIHZhbHVlLCBleHRyYXMpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgIG9wY29kZSxcbiAgICAgIGtleSxcbiAgICAgIHNlcmlhbGl6ZWQuZXh0cmFzLFxuICAgICAgc2VyaWFsaXplZC52YWx1ZSxcbiAgICAgIHRoaXMuc2VxXG4gICAgKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJSRVBMQUNFXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBEZWxldGVzIHRoZSBnaXZlbiBfa2V5XyBmcm9tIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHNcbiAgICogaWYgdGhlIGtleSBpcyBhbHJlYWR5IHByZXNlbnQuXG4gICAqL1xuICBhc3luYyBkZWxldGUoa2V5OiBzdHJpbmcpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAvLyBUT0RPOiBTdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoNCwga2V5LCBcIlwiLCBcIlwiLCB0aGlzLnNlcSk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG5cbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJERUxFVEVcIiwgcmVzcG9uc2U/LmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBJbmNyZW1lbnRzIHRoZSBnaXZlbiBfa2V5XyBpbiBtZW1jYWNoZS5cbiAgICovXG4gIGFzeW5jIGluY3JlbWVudChcbiAgICBrZXk6IHN0cmluZyxcbiAgICBhbW91bnQ6IG51bWJlcixcbiAgICBvcHRpb25zPzogeyBpbml0aWFsPzogbnVtYmVyOyBleHBpcmVzPzogbnVtYmVyIH1cbiAgKTogUHJvbWlzZTx7IHZhbHVlOiBudW1iZXIgfCBudWxsOyBzdWNjZXNzOiBib29sZWFuIHwgbnVsbCB9PiB7XG4gICAgLy8gVE9ETzogc3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgaW5pdGlhbCA9IG9wdGlvbnM/LmluaXRpYWwgfHwgMDtcbiAgICBjb25zdCBleHBpcmVzID0gb3B0aW9ucz8uZXhwaXJlcyB8fCB0aGlzLm9wdGlvbnMuZXhwaXJlcztcbiAgICBjb25zdCBleHRyYXMgPSBtYWtlQW1vdW50SW5pdGlhbEFuZEV4cGlyYXRpb24oYW1vdW50LCBpbml0aWFsLCBleHBpcmVzKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICBjb25zdGFudHMuT1BfSU5DUkVNRU5ULFxuICAgICAga2V5LFxuICAgICAgZXh0cmFzLFxuICAgICAgXCJcIixcbiAgICAgIHRoaXMuc2VxXG4gICAgKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgY29uc3QgYnVmSW50ID1cbiAgICAgICAgICAocmVzcG9uc2UudmFsLnJlYWRVSW50MzJCRSgwKSA8PCA4KSArIHJlc3BvbnNlLnZhbC5yZWFkVUludDMyQkUoNCk7XG4gICAgICAgIHJldHVybiB7IHZhbHVlOiBidWZJbnQsIHN1Y2Nlc3M6IHRydWUgfTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJJTkNSRU1FTlRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIERlY3JlbWVudHMgdGhlIGdpdmVuIGBrZXlgIGluIG1lbWNhY2hlLlxuICAgKi9cbiAgYXN5bmMgZGVjcmVtZW50KFxuICAgIGtleTogc3RyaW5nLFxuICAgIGFtb3VudDogbnVtYmVyLFxuICAgIG9wdGlvbnM6IHsgaW5pdGlhbD86IG51bWJlcjsgZXhwaXJlcz86IG51bWJlciB9XG4gICk6IFByb21pc2U8eyB2YWx1ZTogbnVtYmVyIHwgbnVsbDsgc3VjY2VzczogYm9vbGVhbiB8IG51bGwgfT4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IGluaXRpYWwgPSBvcHRpb25zLmluaXRpYWwgfHwgMDtcbiAgICBjb25zdCBleHBpcmVzID0gb3B0aW9ucy5leHBpcmVzIHx8IHRoaXMub3B0aW9ucy5leHBpcmVzO1xuICAgIGNvbnN0IGV4dHJhcyA9IG1ha2VBbW91bnRJbml0aWFsQW5kRXhwaXJhdGlvbihhbW91bnQsIGluaXRpYWwsIGV4cGlyZXMpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgIGNvbnN0YW50cy5PUF9ERUNSRU1FTlQsXG4gICAgICBrZXksXG4gICAgICBleHRyYXMsXG4gICAgICBcIlwiLFxuICAgICAgdGhpcy5zZXFcbiAgICApO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICBjb25zdCBidWZJbnQgPVxuICAgICAgICAgIChyZXNwb25zZS52YWwucmVhZFVJbnQzMkJFKDApIDw8IDgpICsgcmVzcG9uc2UudmFsLnJlYWRVSW50MzJCRSg0KTtcbiAgICAgICAgcmV0dXJuIHsgdmFsdWU6IGJ1ZkludCwgc3VjY2VzczogdHJ1ZSB9O1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIkRFQ1JFTUVOVFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQXBwZW5kIHRoZSBnaXZlbiBfdmFsdWVfIHRvIHRoZSB2YWx1ZSBhc3NvY2lhdGVkIHdpdGggdGhlIGdpdmVuIF9rZXlfIGluXG4gICAqIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHMgaWYgdGhlIGtleSBpcyBhbHJlYWR5IHByZXNlbnQuXG4gICAqL1xuICBhc3luYyBhcHBlbmQoa2V5OiBzdHJpbmcsIHZhbHVlOiBWYWx1ZSk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IG9wY29kZTogY29uc3RhbnRzLk9QID0gY29uc3RhbnRzLk9QX0FQUEVORDtcbiAgICBjb25zdCBzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLnNlcmlhbGl6ZShvcGNvZGUsIHZhbHVlLCBcIlwiKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICBvcGNvZGUsXG4gICAgICBrZXksXG4gICAgICBzZXJpYWxpemVkLmV4dHJhcyxcbiAgICAgIHNlcmlhbGl6ZWQudmFsdWUsXG4gICAgICB0aGlzLnNlcVxuICAgICk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfTk9UX0ZPVU5EOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiQVBQRU5EXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBQcmVwZW5kIHRoZSBnaXZlbiBfdmFsdWVfIHRvIHRoZSB2YWx1ZSBhc3NvY2lhdGVkIHdpdGggdGhlIGdpdmVuIF9rZXlfIGluXG4gICAqIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHMgaWYgdGhlIGtleSBpcyBhbHJlYWR5IHByZXNlbnQuXG4gICAqL1xuICBhc3luYyBwcmVwZW5kKGtleTogc3RyaW5nLCB2YWx1ZTogVmFsdWUpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAvLyBUT0RPOiBzdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBvcGNvZGU6IGNvbnN0YW50cy5PUCA9IGNvbnN0YW50cy5PUF9QUkVQRU5EO1xuICAgIGNvbnN0IHNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuc2VyaWFsaXplKG9wY29kZSwgdmFsdWUsIFwiXCIpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgIG9wY29kZSxcbiAgICAgIGtleSxcbiAgICAgIHNlcmlhbGl6ZWQuZXh0cmFzLFxuICAgICAgc2VyaWFsaXplZC52YWx1ZSxcbiAgICAgIHRoaXMuc2VxXG4gICAgKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJQUkVQRU5EXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBUb3VjaCBzZXRzIGFuIGV4cGlyYXRpb24gdmFsdWUsIGdpdmVuIGJ5IF9leHBpcmVzXywgb24gdGhlIGdpdmVuIF9rZXlfIGluXG4gICAqIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHMgaWYgdGhlIGtleSBpcyBhbHJlYWR5IHByZXNlbnQuXG4gICAqL1xuICBhc3luYyB0b3VjaChrZXk6IHN0cmluZywgZXhwaXJlczogbnVtYmVyKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgLy8gVE9ETzogc3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgZXh0cmFzID0gbWFrZUV4cGlyYXRpb24oZXhwaXJlcyB8fCB0aGlzLm9wdGlvbnMuZXhwaXJlcyk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKDB4MWMsIGtleSwgZXh0cmFzLCBcIlwiLCB0aGlzLnNlcSk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfTk9UX0ZPVU5EOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiVE9VQ0hcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEZMVVNIXG4gICAqXG4gICAqIEZsdXNoZXMgdGhlIGNhY2hlIG9uIGVhY2ggY29ubmVjdGVkIHNlcnZlci4gVGhlIGNhbGxiYWNrIHNpZ25hdHVyZSBpczpcbiAgICpcbiAgICogICAgIGNhbGxiYWNrKGxhc3RFcnIsIHJlc3VsdHMpXG4gICAqXG4gICAqIHdoZXJlIF9sYXN0RXJyXyBpcyB0aGUgbGFzdCBlcnJvciBlbmNvdW50ZXJlZCAob3IgbnVsbCwgaW4gdGhlIGNvbW1vbiBjYXNlXG4gICAqIG9mIG5vIGVycm9ycykuIF9yZXN1bHRzXyBpcyBhIGRpY3Rpb25hcnkgbWFwcGluZyBgXCJob3N0bmFtZTpwb3J0XCJgIHRvIGVpdGhlclxuICAgKiBgdHJ1ZWAgKGlmIHRoZSBvcGVyYXRpb24gd2FzIHN1Y2Nlc3NmdWwpLCBvciBhbiBlcnJvci5cbiAgICogQHBhcmFtIGNhbGxiYWNrXG4gICAqL1xuICBmbHVzaCgpOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIGJvb2xlYW4gfCBFcnJvcj4+O1xuICBmbHVzaChcbiAgICBjYWxsYmFjazogKFxuICAgICAgZXJyOiBFcnJvciB8IG51bGwsXG4gICAgICByZXN1bHRzOiBSZWNvcmQ8c3RyaW5nLCBib29sZWFuIHwgRXJyb3I+XG4gICAgKSA9PiB2b2lkXG4gICk6IHZvaWQ7XG4gIGZsdXNoKFxuICAgIGNhbGxiYWNrPzogKFxuICAgICAgZXJyOiBFcnJvciB8IG51bGwsXG4gICAgICByZXN1bHRzOiBSZWNvcmQ8c3RyaW5nLCBib29sZWFuIHwgRXJyb3I+XG4gICAgKSA9PiB2b2lkXG4gICkge1xuICAgIGlmIChjYWxsYmFjayA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm4gcHJvbWlzaWZ5KChjYWxsYmFjaykgPT4ge1xuICAgICAgICB0aGlzLmZsdXNoKGZ1bmN0aW9uIChlcnIsIHJlc3VsdHMpIHtcbiAgICAgICAgICBjYWxsYmFjayhlcnIsIHJlc3VsdHMpO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH1cbiAgICAvLyBUT0RPOiBzdXBwb3J0IGV4cGlyYXRpb25cbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoMHgwOCwgXCJcIiwgXCJcIiwgXCJcIiwgdGhpcy5zZXEpO1xuICAgIGxldCBjb3VudCA9IHRoaXMuc2VydmVycy5sZW5ndGg7XG4gICAgY29uc3QgcmVzdWx0OiBSZWNvcmQ8c3RyaW5nLCBib29sZWFuIHwgRXJyb3I+ID0ge307XG4gICAgbGV0IGxhc3RFcnI6IEVycm9yIHwgbnVsbCA9IG51bGw7XG5cbiAgICBjb25zdCBoYW5kbGVGbHVzaCA9IGZ1bmN0aW9uIChzZXE6IG51bWJlciwgc2VydjogU2VydmVyKSB7XG4gICAgICBzZXJ2Lm9uUmVzcG9uc2Uoc2VxLCBmdW5jdGlvbiAoLyogcmVzcG9uc2UgKi8pIHtcbiAgICAgICAgY291bnQgLT0gMTtcbiAgICAgICAgcmVzdWx0W3NlcnYuaG9zdHBvcnRTdHJpbmcoKV0gPSB0cnVlO1xuICAgICAgICBpZiAoY2FsbGJhY2sgJiYgY291bnQgPT09IDApIHtcbiAgICAgICAgICBjYWxsYmFjayhsYXN0RXJyLCByZXN1bHQpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHNlcnYub25FcnJvcihzZXEsIGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgICAgY291bnQgLT0gMTtcbiAgICAgICAgbGFzdEVyciA9IGVycjtcbiAgICAgICAgcmVzdWx0W3NlcnYuaG9zdHBvcnRTdHJpbmcoKV0gPSBlcnI7XG4gICAgICAgIGlmIChjYWxsYmFjayAmJiBjb3VudCA9PT0gMCkge1xuICAgICAgICAgIGNhbGxiYWNrKGxhc3RFcnIsIHJlc3VsdCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgc2Vydi53cml0ZShyZXF1ZXN0KTtcbiAgICB9O1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnNlcnZlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGhhbmRsZUZsdXNoKHRoaXMuc2VxLCB0aGlzLnNlcnZlcnNbaV0pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTVEFUU19XSVRIX0tFWVxuICAgKlxuICAgKiBTZW5kcyBhIG1lbWNhY2hlIHN0YXRzIGNvbW1hbmQgd2l0aCBhIGtleSB0byBlYWNoIGNvbm5lY3RlZCBzZXJ2ZXIuIFRoZVxuICAgKiBjYWxsYmFjayBpcyBpbnZva2VkICoqT05DRSBQRVIgU0VSVkVSKiogYW5kIGhhcyB0aGUgc2lnbmF0dXJlOlxuICAgKlxuICAgKiAgICAgY2FsbGJhY2soZXJyLCBzZXJ2ZXIsIHN0YXRzKVxuICAgKlxuICAgKiBfc2VydmVyXyBpcyB0aGUgYFwiaG9zdG5hbWU6cG9ydFwiYCBvZiB0aGUgc2VydmVyLCBhbmQgX3N0YXRzXyBpcyBhIGRpY3Rpb25hcnlcbiAgICogbWFwcGluZyB0aGUgc3RhdCBuYW1lIHRvIHRoZSB2YWx1ZSBvZiB0aGUgc3RhdGlzdGljIGFzIGEgc3RyaW5nLlxuICAgKiBAcGFyYW0ga2V5XG4gICAqIEBwYXJhbSBjYWxsYmFja1xuICAgKi9cbiAgc3RhdHNXaXRoS2V5KFxuICAgIGtleTogc3RyaW5nLFxuICAgIGNhbGxiYWNrPzogKFxuICAgICAgZXJyOiBFcnJvciB8IG51bGwsXG4gICAgICBzZXJ2ZXI6IHN0cmluZyxcbiAgICAgIHN0YXRzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+IHwgbnVsbFxuICAgICkgPT4gdm9pZFxuICApOiB2b2lkIHtcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoMHgxMCwga2V5LCBcIlwiLCBcIlwiLCB0aGlzLnNlcSk7XG5cbiAgICBjb25zdCBoYW5kbGVTdGF0cyA9IChzZXE6IG51bWJlciwgc2VydjogU2VydmVyKSA9PiB7XG4gICAgICBjb25zdCByZXN1bHQ6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcbiAgICAgIGNvbnN0IGhhbmRsZTogT25SZXNwb25zZUNhbGxiYWNrID0gKHJlc3BvbnNlKSA9PiB7XG4gICAgICAgIC8vIGVuZCBvZiBzdGF0IHJlc3BvbnNlc1xuICAgICAgICBpZiAocmVzcG9uc2UuaGVhZGVyLnRvdGFsQm9keUxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgICAgY2FsbGJhY2sobnVsbCwgc2Vydi5ob3N0cG9ydFN0cmluZygpLCByZXN1bHQpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgLy8gcHJvY2VzcyBzaW5nbGUgc3RhdCBsaW5lIHJlc3BvbnNlXG4gICAgICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgICAgIHJlc3VsdFtyZXNwb25zZS5rZXkudG9TdHJpbmcoKV0gPSByZXNwb25zZS52YWwudG9TdHJpbmcoKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICBjb25zdCBlcnJvciA9IHRoaXMuaGFuZGxlUmVzcG9uc2VFcnJvcihcbiAgICAgICAgICAgICAgYFNUQVRTICgke2tleX0pYCxcbiAgICAgICAgICAgICAgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyxcbiAgICAgICAgICAgICAgdW5kZWZpbmVkXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgICAgICAgIGNhbGxiYWNrKGVycm9yLCBzZXJ2Lmhvc3Rwb3J0U3RyaW5nKCksIG51bGwpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9O1xuICAgICAgaGFuZGxlLnF1aWV0ID0gdHJ1ZTtcblxuICAgICAgc2Vydi5vblJlc3BvbnNlKHNlcSwgaGFuZGxlKTtcbiAgICAgIHNlcnYub25FcnJvcihzZXEsIGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgICAgY2FsbGJhY2soZXJyLCBzZXJ2Lmhvc3Rwb3J0U3RyaW5nKCksIG51bGwpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHNlcnYud3JpdGUocmVxdWVzdCk7XG4gICAgfTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5zZXJ2ZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBoYW5kbGVTdGF0cyh0aGlzLnNlcSwgdGhpcy5zZXJ2ZXJzW2ldKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU1RBVFNcbiAgICpcbiAgICogRmV0Y2hlcyBtZW1jYWNoZSBzdGF0cyBmcm9tIGVhY2ggY29ubmVjdGVkIHNlcnZlci4gVGhlIGNhbGxiYWNrIGlzIGludm9rZWRcbiAgICogKipPTkNFIFBFUiBTRVJWRVIqKiBhbmQgaGFzIHRoZSBzaWduYXR1cmU6XG4gICAqXG4gICAqICAgICBjYWxsYmFjayhlcnIsIHNlcnZlciwgc3RhdHMpXG4gICAqXG4gICAqIF9zZXJ2ZXJfIGlzIHRoZSBgXCJob3N0bmFtZTpwb3J0XCJgIG9mIHRoZSBzZXJ2ZXIsIGFuZCBfc3RhdHNfIGlzIGFcbiAgICogZGljdGlvbmFyeSBtYXBwaW5nIHRoZSBzdGF0IG5hbWUgdG8gdGhlIHZhbHVlIG9mIHRoZSBzdGF0aXN0aWMgYXMgYSBzdHJpbmcuXG4gICAqIEBwYXJhbSBjYWxsYmFja1xuICAgKi9cbiAgc3RhdHMoXG4gICAgY2FsbGJhY2s/OiAoXG4gICAgICBlcnI6IEVycm9yIHwgbnVsbCxcbiAgICAgIHNlcnZlcjogc3RyaW5nLFxuICAgICAgc3RhdHM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gfCBudWxsXG4gICAgKSA9PiB2b2lkXG4gICk6IHZvaWQge1xuICAgIHRoaXMuc3RhdHNXaXRoS2V5KFwiXCIsIGNhbGxiYWNrKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSRVNFVF9TVEFUU1xuICAgKlxuICAgKiBSZXNldCB0aGUgc3RhdGlzdGljcyBlYWNoIHNlcnZlciBpcyBrZWVwaW5nIGJhY2sgdG8gemVyby4gVGhpcyBkb2Vzbid0IGNsZWFyXG4gICAqIHN0YXRzIHN1Y2ggYXMgaXRlbSBjb3VudCwgYnV0IHRlbXBvcmFyeSBzdGF0cyBzdWNoIGFzIHRvdGFsIG51bWJlciBvZlxuICAgKiBjb25uZWN0aW9ucyBvdmVyIHRpbWUuXG4gICAqXG4gICAqIFRoZSBjYWxsYmFjayBpcyBpbnZva2VkICoqT05DRSBQRVIgU0VSVkVSKiogYW5kIGhhcyB0aGUgc2lnbmF0dXJlOlxuICAgKlxuICAgKiAgICAgY2FsbGJhY2soZXJyLCBzZXJ2ZXIpXG4gICAqXG4gICAqIF9zZXJ2ZXJfIGlzIHRoZSBgXCJob3N0bmFtZTpwb3J0XCJgIG9mIHRoZSBzZXJ2ZXIuXG4gICAqIEBwYXJhbSBjYWxsYmFja1xuICAgKi9cbiAgcmVzZXRTdGF0cyhcbiAgICBjYWxsYmFjaz86IChcbiAgICAgIGVycjogRXJyb3IgfCBudWxsLFxuICAgICAgc2VydmVyOiBzdHJpbmcsXG4gICAgICBzdGF0czogUmVjb3JkPHN0cmluZywgc3RyaW5nPiB8IG51bGxcbiAgICApID0+IHZvaWRcbiAgKTogdm9pZCB7XG4gICAgdGhpcy5zdGF0c1dpdGhLZXkoXCJyZXNldFwiLCBjYWxsYmFjayk7XG4gIH1cblxuICAvKipcbiAgICogUVVJVFxuICAgKlxuICAgKiBDbG9zZXMgdGhlIGNvbm5lY3Rpb24gdG8gZWFjaCBzZXJ2ZXIsIG5vdGlmeWluZyB0aGVtIG9mIHRoaXMgaW50ZW50aW9uLiBOb3RlXG4gICAqIHRoYXQgcXVpdCBjYW4gcmFjZSBhZ2FpbnN0IGFscmVhZHkgb3V0c3RhbmRpbmcgcmVxdWVzdHMgd2hlbiB0aG9zZSByZXF1ZXN0c1xuICAgKiBmYWlsIGFuZCBhcmUgcmV0cmllZCwgbGVhZGluZyB0byB0aGUgcXVpdCBjb21tYW5kIHdpbm5pbmcgYW5kIGNsb3NpbmcgdGhlXG4gICAqIGNvbm5lY3Rpb24gYmVmb3JlIHRoZSByZXRyaWVzIGNvbXBsZXRlLlxuICAgKi9cbiAgcXVpdCgpIHtcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICAvLyBUT0RPOiBOaWNlciBwZXJoYXBzIHRvIGRvIFFVSVRRICgweDE3KSBidXQgbmVlZCBhIG5ldyBjYWxsYmFjayBmb3Igd2hlblxuICAgIC8vIHdyaXRlIGlzIGRvbmUuXG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKDB4MDcsIFwiXCIsIFwiXCIsIFwiXCIsIHRoaXMuc2VxKTsgLy8gUVVJVFxuICAgIGxldCBzZXJ2O1xuXG4gICAgY29uc3QgaGFuZGxlUXVpdCA9IGZ1bmN0aW9uIChzZXE6IG51bWJlciwgc2VydjogU2VydmVyKSB7XG4gICAgICBzZXJ2Lm9uUmVzcG9uc2Uoc2VxLCBmdW5jdGlvbiAoLyogcmVzcG9uc2UgKi8pIHtcbiAgICAgICAgc2Vydi5jbG9zZSgpO1xuICAgICAgfSk7XG4gICAgICBzZXJ2Lm9uRXJyb3Ioc2VxLCBmdW5jdGlvbiAoLyogZXJyICovKSB7XG4gICAgICAgIHNlcnYuY2xvc2UoKTtcbiAgICAgIH0pO1xuICAgICAgc2Vydi53cml0ZShyZXF1ZXN0KTtcbiAgICB9O1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnNlcnZlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHNlcnYgPSB0aGlzLnNlcnZlcnNbaV07XG4gICAgICBoYW5kbGVRdWl0KHRoaXMuc2VxLCBzZXJ2KTtcbiAgICB9XG4gIH1cblxuICBfdmVyc2lvbihzZXJ2ZXI6IFNlcnZlcik6IFByb21pc2U8eyB2YWx1ZTogVmFsdWUgfCBudWxsIH0+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICAgIGNvbnN0YW50cy5PUF9WRVJTSU9OLFxuICAgICAgICBcIlwiLFxuICAgICAgICBcIlwiLFxuICAgICAgICBcIlwiLFxuICAgICAgICB0aGlzLnNlcVxuICAgICAgKTtcbiAgICAgIHRoaXMucGVyZm9ybU9uU2VydmVyKHNlcnZlciwgcmVxdWVzdCwgdGhpcy5zZXEsIChlcnIsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICByZXR1cm4gcmVqZWN0KGVycik7XG4gICAgICAgIH1cblxuICAgICAgICBzd2l0Y2ggKHJlc3BvbnNlIS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICAgICAgLyogVE9ETzogdGhpcyBpcyBidWdnZWQsIHdlIHNob3VsZCd0IHVzZSB0aGUgZGVzZXJpYWxpemVyIGhlcmUsIHNpbmNlIHZlcnNpb24gYWx3YXlzIHJldHVybnMgYSB2ZXJzaW9uIHN0cmluZy5cbiAgICAgICAgICAgICBUaGUgZGVzZXJpYWxpemVyIHNob3VsZCBvbmx5IGJlIHVzZWQgb24gdXNlciBrZXkgZGF0YS4gKi9cbiAgICAgICAgICAgIGNvbnN0IGRlc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5kZXNlcmlhbGl6ZShcbiAgICAgICAgICAgICAgcmVzcG9uc2UhLmhlYWRlci5vcGNvZGUsXG4gICAgICAgICAgICAgIHJlc3BvbnNlIS52YWwsXG4gICAgICAgICAgICAgIHJlc3BvbnNlIS5leHRyYXNcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICByZXR1cm4gcmVzb2x2ZSh7IHZhbHVlOiBkZXNlcmlhbGl6ZWQudmFsdWUgfSk7XG4gICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHJldHVybiByZWplY3QoXG4gICAgICAgICAgICAgIHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJWRVJTSU9OXCIsIHJlc3BvbnNlIS5oZWFkZXIuc3RhdHVzKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmVxdWVzdCB0aGUgc2VydmVyIHZlcnNpb24gZnJvbSB0aGUgXCJmaXJzdFwiIHNlcnZlciBpbiB0aGUgYmFja2VuZCBwb29sLlxuICAgKiBUaGUgc2VydmVyIHJlc3BvbmRzIHdpdGggYSBwYWNrZXQgY29udGFpbmluZyB0aGUgdmVyc2lvbiBzdHJpbmcgaW4gdGhlIGJvZHkgd2l0aCB0aGUgZm9sbG93aW5nIGZvcm1hdDogXCJ4LnkuelwiXG4gICAqL1xuICB2ZXJzaW9uKCk6IFByb21pc2U8eyB2YWx1ZTogVmFsdWUgfCBudWxsIH0+IHtcbiAgICBjb25zdCBzZXJ2ZXIgPSB0aGlzLnNlcnZlcktleVRvU2VydmVyKHRoaXMuc2VydmVyS2V5c1swXSk7XG4gICAgcmV0dXJuIHRoaXMuX3ZlcnNpb24oc2VydmVyKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXRyaWV2ZXMgdGhlIHNlcnZlciB2ZXJzaW9uIGZyb20gYWxsIHRoZSBzZXJ2ZXJzXG4gICAqIGluIHRoZSBiYWNrZW5kIHBvb2wsIGVycm9ycyBpZiBhbnkgb25lIG9mIHRoZW0gaGFzIGFuXG4gICAqIGVycm9yXG4gICAqIFxuICAgKiBDYWxsYmFja3MgZnVuY3Rpb25zIGFyZSBjYWxsZWQgYmVmb3JlL2FmdGVyIHdlIHBpbmcgbWVtY2FjaGVkXG4gICAqIGFuZCB1c2VkIHRvIGxvZyB3aGljaCBob3N0cyBhcmUgdGltaW5nIG91dC5cbiAgICovXG4gIGFzeW5jIHZlcnNpb25BbGwoY2FsbGJhY2tzPzoge1xuICAgIGJlZm9yZVBpbmc/OiAoc2VydmVyS2V5OiBzdHJpbmcpID0+IHZvaWQ7XG4gICAgYWZ0ZXJQaW5nPzogKHNlcnZlcktleTogc3RyaW5nKSA9PiB2b2lkO1xuICB9KTogUHJvbWlzZTx7XG4gICAgdmFsdWVzOiBSZWNvcmQ8c3RyaW5nLCBWYWx1ZSB8IG51bGw+O1xuICB9PiB7XG4gICAgY29uc3QgdmVyc2lvbk9iamVjdHMgPSBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIHRoaXMuc2VydmVyS2V5cy5tYXAoKHNlcnZlcktleSkgPT4ge1xuICAgICAgICBjb25zdCBzZXJ2ZXIgPSB0aGlzLnNlcnZlcktleVRvU2VydmVyKHNlcnZlcktleSk7XG4gICAgICAgIGNhbGxiYWNrcz8uYmVmb3JlUGluZz8uKHNlcnZlcktleSk7XG4gICAgICAgIHJldHVybiB0aGlzLl92ZXJzaW9uKHNlcnZlcikudGhlbigocmVzcG9uc2UpID0+IHtcbiAgICAgICAgICBjYWxsYmFja3M/LmFmdGVyUGluZz8uKHNlcnZlcktleSk7XG4gICAgICAgICAgcmV0dXJuIHsgc2VydmVyS2V5OiBzZXJ2ZXJLZXksIHZhbHVlOiByZXNwb25zZS52YWx1ZSB9O1xuICAgICAgICB9KTtcbiAgICAgIH0pXG4gICAgKTtcbiAgICBjb25zdCB2YWx1ZXMgPSB2ZXJzaW9uT2JqZWN0cy5yZWR1Y2UoKGFjY3VtdWxhdG9yLCB2ZXJzaW9uT2JqZWN0KSA9PiB7XG4gICAgICBhY2N1bXVsYXRvclt2ZXJzaW9uT2JqZWN0LnNlcnZlcktleV0gPSB2ZXJzaW9uT2JqZWN0LnZhbHVlO1xuICAgICAgcmV0dXJuIGFjY3VtdWxhdG9yO1xuICAgIH0sIHt9IGFzIFJlY29yZDxzdHJpbmcsIFZhbHVlIHwgbnVsbD4pO1xuICAgIHJldHVybiB7IHZhbHVlczogdmFsdWVzIH07XG4gIH1cblxuICAvKipcbiAgICogQ2xvc2VzIChhYnJ1cHRseSkgY29ubmVjdGlvbnMgdG8gYWxsIHRoZSBzZXJ2ZXJzLlxuICAgKiBAc2VlIHRoaXMucXVpdFxuICAgKi9cbiAgY2xvc2UoKSB7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnNlcnZlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHRoaXMuc2VydmVyc1tpXS5jbG9zZSgpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBQZXJmb3JtIGEgZ2VuZXJpYyBzaW5nbGUgcmVzcG9uc2Ugb3BlcmF0aW9uIChnZXQsIHNldCBldGMpIG9uIG9uZSBzZXJ2ZXJcbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IGtleSB0aGUga2V5IHRvIGhhc2ggdG8gZ2V0IGEgc2VydmVyIGZyb20gdGhlIHBvb2xcbiAgICogQHBhcmFtIHtidWZmZXJ9IHJlcXVlc3QgYSBidWZmZXIgY29udGFpbmluZyB0aGUgcmVxdWVzdFxuICAgKiBAcGFyYW0ge251bWJlcn0gc2VxIHRoZSBzZXF1ZW5jZSBudW1iZXIgb2YgdGhlIG9wZXJhdGlvbi4gSXQgaXMgdXNlZCB0byBwaW4gdGhlIGNhbGxiYWNrc1xuICAgICAgICAgICAgICAgICAgICAgICAgIHRvIGEgc3BlY2lmaWMgb3BlcmF0aW9uIGFuZCBzaG91bGQgbmV2ZXIgY2hhbmdlIGR1cmluZyBhIGBwZXJmb3JtYC5cbiAgICogQHBhcmFtIHtudW1iZXI/fSByZXRyaWVzIG51bWJlciBvZiB0aW1lcyB0byByZXRyeSByZXF1ZXN0IG9uIGZhaWx1cmVcbiAgICovXG4gIHBlcmZvcm0oXG4gICAga2V5OiBzdHJpbmcsXG4gICAgcmVxdWVzdDogQnVmZmVyLFxuICAgIHNlcTogbnVtYmVyLFxuICAgIHJldHJpZXM/OiBudW1iZXJcbiAgKTogUHJvbWlzZTxNZXNzYWdlPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGNvbnN0IHNlcnZlcktleSA9IHRoaXMubG9va3VwS2V5VG9TZXJ2ZXJLZXkoa2V5KTtcbiAgICAgIGNvbnN0IHNlcnZlciA9IHRoaXMuc2VydmVyS2V5VG9TZXJ2ZXIoc2VydmVyS2V5KTtcblxuICAgICAgaWYgKCFzZXJ2ZXIpIHtcbiAgICAgICAgcmV0dXJuIHJlamVjdChuZXcgRXJyb3IoXCJObyBzZXJ2ZXJzIGF2YWlsYWJsZVwiKSk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMucGVyZm9ybU9uU2VydmVyKFxuICAgICAgICBzZXJ2ZXIsXG4gICAgICAgIHJlcXVlc3QsXG4gICAgICAgIHNlcSxcbiAgICAgICAgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgcmV0dXJuIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJlc29sdmUocmVzcG9uc2UhKTtcbiAgICAgICAgfSxcbiAgICAgICAgcmV0cmllc1xuICAgICAgKTtcbiAgICB9KTtcbiAgfVxuXG4gIHBlcmZvcm1PblNlcnZlcihcbiAgICBzZXJ2ZXI6IFNlcnZlcixcbiAgICByZXF1ZXN0OiBCdWZmZXIsXG4gICAgc2VxOiBudW1iZXIsXG4gICAgY2FsbGJhY2s6IFJlc3BvbnNlT3JFcnJvckNhbGxiYWNrLFxuICAgIHJldHJpZXM6IG51bWJlciA9IDBcbiAgKSB7XG4gICAgY29uc3QgX3RoaXMgPSB0aGlzO1xuXG4gICAgcmV0cmllcyA9IHJldHJpZXMgfHwgdGhpcy5vcHRpb25zLnJldHJpZXM7XG4gICAgY29uc3Qgb3JpZ1JldHJpZXMgPSB0aGlzLm9wdGlvbnMucmV0cmllcztcbiAgICBjb25zdCBsb2dnZXIgPSB0aGlzLm9wdGlvbnMubG9nZ2VyO1xuICAgIGNvbnN0IHJldHJ5X2RlbGF5ID0gdGhpcy5vcHRpb25zLnJldHJ5X2RlbGF5O1xuXG4gICAgY29uc3QgcmVzcG9uc2VIYW5kbGVyOiBPblJlc3BvbnNlQ2FsbGJhY2sgPSBmdW5jdGlvbiAocmVzcG9uc2UpIHtcbiAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICBjYWxsYmFjayhudWxsLCByZXNwb25zZSk7XG4gICAgICB9XG4gICAgfTtcblxuICAgIGNvbnN0IGVycm9ySGFuZGxlcjogT25FcnJvckNhbGxiYWNrID0gZnVuY3Rpb24gKGVycm9yKSB7XG4gICAgICBpZiAoLS1yZXRyaWVzID4gMCkge1xuICAgICAgICAvLyBXYWl0IGZvciByZXRyeV9kZWxheVxuICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICBfdGhpcy5wZXJmb3JtT25TZXJ2ZXIoc2VydmVyLCByZXF1ZXN0LCBzZXEsIGNhbGxiYWNrLCByZXRyaWVzKTtcbiAgICAgICAgfSwgMTAwMCAqIHJldHJ5X2RlbGF5KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGxvZ2dlci5sb2coXG4gICAgICAgICAgXCJNZW1KUzogU2VydmVyIDxcIiArXG4gICAgICAgICAgICBzZXJ2ZXIuaG9zdHBvcnRTdHJpbmcoKSArXG4gICAgICAgICAgICBcIj4gZmFpbGVkIGFmdGVyIChcIiArXG4gICAgICAgICAgICBvcmlnUmV0cmllcyArXG4gICAgICAgICAgICBcIikgcmV0cmllcyB3aXRoIGVycm9yIC0gXCIgK1xuICAgICAgICAgICAgZXJyb3IubWVzc2FnZVxuICAgICAgICApO1xuICAgICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgICBjYWxsYmFjayhlcnJvciwgbnVsbCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9O1xuXG4gICAgc2VydmVyLm9uUmVzcG9uc2Uoc2VxLCByZXNwb25zZUhhbmRsZXIpO1xuICAgIHNlcnZlci5vbkVycm9yKHNlcSwgZXJyb3JIYW5kbGVyKTtcbiAgICBzZXJ2ZXIud3JpdGUocmVxdWVzdCk7XG4gIH1cblxuICAvLyBJbmNyZW1lbnQgdGhlIHNlcSB2YWx1ZVxuICBpbmNyU2VxKCkge1xuICAgIHRoaXMuc2VxKys7XG5cbiAgICAvLyBXcmFwIGB0aGlzLnNlcWAgdG8gMzItYml0cyBzaW5jZSB0aGUgZmllbGQgd2UgZml0IGl0IGludG8gaXMgb25seSAzMi1iaXRzLlxuICAgIHRoaXMuc2VxICY9IDB4ZmZmZmZmZmY7XG5cbiAgICByZXR1cm4gdGhpcy5zZXE7XG4gIH1cblxuICBwcml2YXRlIGNyZWF0ZUFuZExvZ0Vycm9yKFxuICAgIGNvbW1hbmROYW1lOiBzdHJpbmcsXG4gICAgcmVzcG9uc2VTdGF0dXM6IFJlc3BvbnNlU3RhdHVzIHwgdW5kZWZpbmVkXG4gICk6IEVycm9yIHtcbiAgICBjb25zdCBlcnJvck1lc3NhZ2UgPSBgTWVtSlMgJHtjb21tYW5kTmFtZX06ICR7Y29uc3RhbnRzLnJlc3BvbnNlU3RhdHVzVG9TdHJpbmcoXG4gICAgICByZXNwb25zZVN0YXR1c1xuICAgICl9YDtcbiAgICB0aGlzLm9wdGlvbnMubG9nZ2VyLmxvZyhlcnJvck1lc3NhZ2UpO1xuICAgIHJldHVybiBuZXcgRXJyb3IoZXJyb3JNZXNzYWdlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBMb2cgYW4gZXJyb3IgdG8gdGhlIGxvZ2dlciwgdGhlbiByZXR1cm4gdGhlIGVycm9yLlxuICAgKiBJZiBhIGNhbGxiYWNrIGlzIGdpdmVuLCBjYWxsIGl0IHdpdGggY2FsbGJhY2soZXJyb3IsIG51bGwpLlxuICAgKi9cbiAgcHJpdmF0ZSBoYW5kbGVSZXNwb25zZUVycm9yKFxuICAgIGNvbW1hbmROYW1lOiBzdHJpbmcsXG4gICAgcmVzcG9uc2VTdGF0dXM6IFJlc3BvbnNlU3RhdHVzIHwgdW5kZWZpbmVkLFxuICAgIGNhbGxiYWNrOiB1bmRlZmluZWQgfCAoKGVycm9yOiBFcnJvciB8IG51bGwsIG90aGVyOiBudWxsKSA9PiB2b2lkKVxuICApOiBFcnJvciB7XG4gICAgY29uc3QgZXJyb3IgPSB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKGNvbW1hbmROYW1lLCByZXNwb25zZVN0YXR1cyk7XG4gICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICBjYWxsYmFjayhlcnJvciwgbnVsbCk7XG4gICAgfVxuICAgIHJldHVybiBlcnJvcjtcbiAgfVxufVxuXG5leHBvcnQgeyBDbGllbnQsIFNlcnZlciwgVXRpbHMsIEhlYWRlciB9O1xuIl19 \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVtanMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbWVtanMvbWVtanMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLHdCQUF3Qjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUV4QixxQ0FLa0I7QUFvbUNELHVGQXRtQ2YsZUFBTSxPQXNtQ2U7QUFubUN2Qix1REFBK0Q7QUFDL0QsbUNBU2lCO0FBQ2pCLHVEQUF5QztBQUN6QywyQ0FBNkM7QUFDN0MsK0NBQWlDO0FBc2xDUixzQkFBSztBQXJsQzlCLGlEQUFtQztBQXFsQ0gsd0JBQU07QUFubEN0QyxTQUFTLDhCQUE4QixDQUNyQyxPQUFpQixFQUNqQixHQUFXO0lBRVgsTUFBTSxLQUFLLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQztJQUM3QixNQUFNLEtBQUssR0FBRyxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxnQkFBUSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3BELE9BQU8sT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ3hCLENBQUM7QUFFRCwrQ0FBK0M7QUFDL0MsU0FBUyxTQUFTLENBQ2hCLE9BQTBFO0lBRTFFLE9BQU8sSUFBSSxPQUFPLENBQUMsVUFBVSxPQUFPLEVBQUUsTUFBTTtRQUMxQyxPQUFPLENBQUMsVUFBVSxHQUFHLEVBQUUsTUFBTTtZQUMzQixHQUFHLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3RDLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBd0VELE1BQU0sTUFBTTtJQVFWLDRFQUE0RTtJQUM1RSxtQ0FBbUM7SUFDbkMsWUFBWSxPQUFpQixFQUFFLE9BQTBDO1FBQ3ZFLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO1FBQ3ZCLElB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Q2xDLE1BQU0sQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDeEIsQ0FBQztJQUVELDBCQUEwQjtJQUMxQixPQUFPO1FBQ0wsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO1FBRVgsNkVBQTZFO1FBQzdFLElBQUksQ0FBQyxHQUFHLElBQUksVUFBVSxDQUFDO1FBRXZCLE9BQU8sSUFBSSxDQUFDLEdBQUcsQ0FBQztJQUNsQixDQUFDO0lBRU8saUJBQWlCLENBQ3ZCLFdBQW1CLEVBQ25CLGNBQTBDO1FBRTFDLE1BQU0sWUFBWSxHQUFHLFNBQVMsV0FBVyxLQUFLLFNBQVMsQ0FBQyxzQkFBc0IsQ0FDNUUsY0FBYyxDQUNmLEVBQUUsQ0FBQztRQUNKLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUN0QyxPQUFPLElBQUksS0FBSyxDQUFDLFlBQVksQ0FBQyxDQUFDO0lBQ2pDLENBQUM7SUFFRDs7O09BR0c7SUFDSyxtQkFBbUIsQ0FDekIsV0FBbUIsRUFDbkIsY0FBMEMsRUFDMUMsUUFBa0U7UUFFbEUsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixDQUFDLFdBQVcsRUFBRSxjQUFjLENBQUMsQ0FBQztRQUNsRSxJQUFJLFFBQVEsRUFBRTtZQUNaLFFBQVEsQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLENBQUM7U0FDdkI7UUFDRCxPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7Q0FDRjtBQUVRLHdCQUFNIiwic291cmNlc0NvbnRlbnQiOlsiLy8gTWVtVFMgTWVtY2FjaGUgQ2xpZW50XG5cbmltcG9ydCB7XG4gIE9uRXJyb3JDYWxsYmFjayxcbiAgT25SZXNwb25zZUNhbGxiYWNrLFxuICBTZXJ2ZXIsXG4gIFNlcnZlck9wdGlvbnMsXG59IGZyb20gXCIuL3NlcnZlclwiO1xuaW1wb3J0IHsgbm9vcFNlcmlhbGl6ZXIsIFNlcmlhbGl6ZXIgfSBmcm9tIFwiLi9ub29wLXNlcmlhbGl6ZXJcIjtcbmltcG9ydCB7XG4gIG1ha2VSZXF1ZXN0QnVmZmVyLFxuICBjb3B5SW50b1JlcXVlc3RCdWZmZXIsXG4gIG1lcmdlLFxuICBtYWtlRXhwaXJhdGlvbixcbiAgbWFrZUFtb3VudEluaXRpYWxBbmRFeHBpcmF0aW9uLFxuICBoYXNoQ29kZSxcbiAgTWF5YmVCdWZmZXIsXG4gIE1lc3NhZ2UsXG59IGZyb20gXCIuL3V0aWxzXCI7XG5pbXBvcnQgKiBhcyBjb25zdGFudHMgZnJvbSBcIi4vY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBSZXNwb25zZVN0YXR1cyB9IGZyb20gXCIuL2NvbnN0YW50c1wiO1xuaW1wb3J0ICogYXMgVXRpbHMgZnJvbSBcIi4vdXRpbHNcIjtcbmltcG9ydCAqIGFzIEhlYWRlciBmcm9tIFwiLi9oZWFkZXJcIjtcblxuZnVuY3Rpb24gZGVmYXVsdEtleVRvU2VydmVySGFzaEZ1bmN0aW9uKFxuICBzZXJ2ZXJzOiBzdHJpbmdbXSxcbiAga2V5OiBzdHJpbmdcbik6IHN0cmluZyB7XG4gIGNvbnN0IHRvdGFsID0gc2VydmVycy5sZW5ndGg7XG4gIGNvbnN0IGluZGV4ID0gdG90YWwgPiAxID8gaGFzaENvZGUoa2V5KSAlIHRvdGFsIDogMDtcbiAgcmV0dXJuIHNlcnZlcnNbaW5kZXhdO1xufVxuXG4vLyBjb252ZXJ0cyBhIGNhbGwgaW50byBhIHByb21pc2UtcmV0dXJuaW5nIG9uZVxuZnVuY3Rpb24gcHJvbWlzaWZ5PFJlc3VsdD4oXG4gIGNvbW1hbmQ6IChjYWxsYmFjazogKGVycm9yOiBFcnJvciB8IG51bGwsIHJlc3VsdDogUmVzdWx0KSA9PiB2b2lkKSA9PiB2b2lkXG4pOiBQcm9taXNlPFJlc3VsdD4ge1xuICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuICAgIGNvbW1hbmQoZnVuY3Rpb24gKGVyciwgcmVzdWx0KSB7XG4gICAgICBlcnIgPyByZWplY3QoZXJyKSA6IHJlc29sdmUocmVzdWx0KTtcbiAgICB9KTtcbiAgfSk7XG59XG5cbnR5cGUgUmVzcG9uc2VPckVycm9yQ2FsbGJhY2sgPSAoXG4gIGVycm9yOiBFcnJvciB8IG51bGwsXG4gIHJlc3BvbnNlOiBNZXNzYWdlIHwgbnVsbFxuKSA9PiB2b2lkO1xuXG5pbnRlcmZhY2UgQmFzZUNsaWVudE9wdGlvbnMge1xuICByZXRyaWVzOiBudW1iZXI7XG4gIHJldHJ5X2RlbGF5OiBudW1iZXI7XG4gIGV4cGlyZXM6IG51bWJlcjtcbiAgbG9nZ2VyOiB7IGxvZzogdHlwZW9mIGNvbnNvbGUubG9nIH07XG4gIGtleVRvU2VydmVySGFzaEZ1bmN0aW9uOiB0eXBlb2YgZGVmYXVsdEtleVRvU2VydmVySGFzaEZ1bmN0aW9uO1xufVxuXG5pbnRlcmZhY2UgU2VyaWFsaXplclByb3A8VmFsdWUsIEV4dHJhcz4ge1xuICBzZXJpYWxpemVyOiBTZXJpYWxpemVyPFZhbHVlLCBFeHRyYXM+O1xufVxuXG4vKipcbiAqIFRoZSBjbGllbnQgaGFzIHBhcnRpYWwgc3VwcG9ydCBmb3Igc2VyaWFsaXppbmcgYW5kIGRlc2VyaWFsaXppbmcgdmFsdWVzIGZyb20gdGhlXG4gKiBCdWZmZXIgYnl0ZSBzdHJpbmdzIHdlIHJlY2VpdmUgZnJvbSB0aGUgd2lyZS4gVGhlIGRlZmF1bHQgc2VyaWFsaXplciBpcyBmb3IgTWF5YmVCdWZmZXIuXG4gKlxuICogSWYgVmFsdWUgYW5kIEV4dHJhcyBhcmUgb2YgdHlwZSBCdWZmZXIsIHRoZW4gcmV0dXJuIHR5cGUgV2hlbkJ1ZmZlci4gT3RoZXJ3aXNlLFxuICogcmV0dXJuIHR5cGUgTm90QnVmZmVyLlxuICovXG50eXBlIElmQnVmZmVyPFZhbHVlLCBFeHRyYXMsIFdoZW5WYWx1ZUFuZEV4dHJhc0FyZUJ1ZmZlcnMsIE5vdEJ1ZmZlcj4gPVxuICBWYWx1ZSBleHRlbmRzIEJ1ZmZlclxuICAgID8gRXh0cmFzIGV4dGVuZHMgQnVmZmVyXG4gICAgICA/IFdoZW5WYWx1ZUFuZEV4dHJhc0FyZUJ1ZmZlcnNcbiAgICAgIDogTm90QnVmZmVyXG4gICAgOiBOb3RCdWZmZXI7XG5cbmV4cG9ydCB0eXBlIEdpdmVuQ2xpZW50T3B0aW9uczxWYWx1ZSwgRXh0cmFzPiA9IFBhcnRpYWw8QmFzZUNsaWVudE9wdGlvbnM+ICZcbiAgSWZCdWZmZXI8XG4gICAgVmFsdWUsXG4gICAgRXh0cmFzLFxuICAgIFBhcnRpYWw8U2VyaWFsaXplclByb3A8VmFsdWUsIEV4dHJhcz4+LFxuICAgIFNlcmlhbGl6ZXJQcm9wPFZhbHVlLCBFeHRyYXM+XG4gID47XG5cbmV4cG9ydCB0eXBlIENBU1Rva2VuID0gQnVmZmVyO1xuXG5leHBvcnQgaW50ZXJmYWNlIEdldFJlc3VsdDxWYWx1ZSA9IE1heWJlQnVmZmVyLCBFeHRyYXMgPSBNYXliZUJ1ZmZlcj4ge1xuICB2YWx1ZTogVmFsdWU7XG4gIGV4dHJhczogRXh0cmFzO1xuICBjYXM6IENBU1Rva2VuIHwgdW5kZWZpbmVkO1xufVxuXG5leHBvcnQgdHlwZSBHZXRNdWx0aVJlc3VsdDxcbiAgS2V5cyBleHRlbmRzIHN0cmluZyA9IHN0cmluZyxcbiAgVmFsdWUgPSBNYXliZUJ1ZmZlcixcbiAgRXh0cmFzID0gTWF5YmVCdWZmZXJcbj4gPSB7XG4gIFtLIGluIEtleXNdPzogR2V0UmVzdWx0PFZhbHVlLCBFeHRyYXM+O1xufTtcblxuZXhwb3J0IGludGVyZmFjZSBHZXRNdWx0aUVycm9yPEtleXMgZXh0ZW5kcyBzdHJpbmcgPSBzdHJpbmc+IHtcbiAgZXJyb3I6IEVycm9yO1xuICBzZXJ2ZXJLZXk6IHN0cmluZztcbiAga2V5czogS2V5c1tdO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEdldE11bHRpV2l0aEVycm9yc1Jlc3VsdDxcbktleXMgZXh0ZW5kcyBzdHJpbmcgPSBzdHJpbmcsXG5WYWx1ZSA9IE1heWJlQnVmZmVyLFxuRXh0cmFzID0gTWF5YmVCdWZmZXJcbj4ge1xuICByZXN1bHQ6IEdldE11bHRpUmVzdWx0PEtleXMsIFZhbHVlLCBFeHRyYXM+O1xuICBlcnJvcnM6IEdldE11bHRpRXJyb3I8S2V5cz5bXTtcbn1cblxuY2xhc3MgQ2xpZW50PFZhbHVlID0gTWF5YmVCdWZmZXIsIEV4dHJhcyA9IE1heWJlQnVmZmVyPiB7XG4gIHNlcnZlcnM6IFNlcnZlcltdO1xuICBzZXE6IG51bWJlcjtcbiAgb3B0aW9uczogQmFzZUNsaWVudE9wdGlvbnMgJiBQYXJ0aWFsPFNlcmlhbGl6ZXJQcm9wPFZhbHVlLCBFeHRyYXM+PjtcbiAgc2VyaWFsaXplcjogU2VyaWFsaXplcjxWYWx1ZSwgRXh0cmFzPjtcbiAgc2VydmVyTWFwOiB7IFtob3N0cG9ydDogc3RyaW5nXTogU2VydmVyIH07XG4gIHNlcnZlcktleXM6IHN0cmluZ1tdO1xuXG4gIC8vIENsaWVudCBpbml0aWFsaXplciB0YWtlcyBhIGxpc3Qgb2YgYFNlcnZlcmBzIGFuZCBhbiBgb3B0aW9uc2AgZGljdGlvbmFyeS5cbiAgLy8gU2VlIGBDbGllbnQuY3JlYXRlYCBmb3IgZGV0YWlscy5cbiAgY29uc3RydWN0b3Ioc2VydmVyczogU2VydmVyW10sIG9wdGlvbnM6IEdpdmVuQ2xpZW50T3B0aW9uczxWYWx1ZSwgRXh0cmFzPikge1xuICAgIHRoaXMuc2VydmVycyA9IHNlcnZlcnM7XG4gICAgdGhpcy5zZXEgPSAwO1xuICAgIHRoaXMub3B0aW9ucyA9IG1lcmdlKG9wdGlvbnMgfHwge30sIHtcbiAgICAgIHJldHJpZXM6IDIsXG4gICAgICByZXRyeV9kZWxheTogMC4yLFxuICAgICAgZXhwaXJlczogMCxcbiAgICAgIGxvZ2dlcjogY29uc29sZSxcbiAgICAgIGtleVRvU2VydmVySGFzaEZ1bmN0aW9uOiBkZWZhdWx0S2V5VG9TZXJ2ZXJIYXNoRnVuY3Rpb24sXG4gICAgfSk7XG5cbiAgICB0aGlzLnNlcmlhbGl6ZXIgPSB0aGlzLm9wdGlvbnMuc2VyaWFsaXplciB8fCAobm9vcFNlcmlhbGl6ZXIgYXMgYW55KTtcblxuICAgIC8vIFN0b3JlIGEgbWFwcGluZyBmcm9tIGhvc3Rwb3J0IC0+IHNlcnZlciBzbyB3ZSBjYW4gcXVpY2tseSBnZXQgYSBzZXJ2ZXIgb2JqZWN0IGZyb20gdGhlIHNlcnZlcktleSByZXR1cm5lZCBieSB0aGUgaGFzaGluZyBmdW5jdGlvblxuICAgIGNvbnN0IHNlcnZlck1hcDogeyBbaG9zdHBvcnQ6IHN0cmluZ106IFNlcnZlciB9ID0ge307XG4gICAgdGhpcy5zZXJ2ZXJzLmZvckVhY2goZnVuY3Rpb24gKHNlcnZlcikge1xuICAgICAgc2VydmVyTWFwW3NlcnZlci5ob3N0cG9ydFN0cmluZygpXSA9IHNlcnZlcjtcbiAgICB9KTtcbiAgICB0aGlzLnNlcnZlck1hcCA9IHNlcnZlck1hcDtcblxuICAgIC8vIHN0b3JlIGEgbGlzdCBvZiBhbGwgb3VyIHNlcnZlcktleXMgc28gd2UgZG9uJ3QgbmVlZCB0byBjb25zdGFudGx5IHJlYWxsb2NhdGUgdGhpcyBhcnJheVxuICAgIHRoaXMuc2VydmVyS2V5cyA9IE9iamVjdC5rZXlzKHRoaXMuc2VydmVyTWFwKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgbmV3IGNsaWVudCBnaXZlbiBhbiBvcHRpb25hbCBjb25maWcgc3RyaW5nIGFuZCBvcHRpb25hbCBoYXNoIG9mXG4gICAqIG9wdGlvbnMuIFRoZSBjb25maWcgc3RyaW5nIHNob3VsZCBiZSBvZiB0aGUgZm9ybTpcbiAgICpcbiAgICogICAgIFwiW3VzZXI6cGFzc0Bdc2VydmVyMVs6MTEyMTFdLFt1c2VyOnBhc3NAXXNlcnZlcjJbOjExMjExXSwuLi5cIlxuICAgKlxuICAgKiBJZiB0aGUgYXJndW1lbnQgaXMgbm90IGdpdmVuLCBmYWxsYmFjayBvbiB0aGUgYE1FTUNBQ0hJRVJfU0VSVkVSU2AgZW52aXJvbm1lbnRcbiAgICogdmFyaWFibGUsIGBNRU1DQUNIRV9TRVJWRVJTYCBlbnZpcm9ubWVudCB2YXJpYWJsZSBvciBgXCJsb2NhbGhvc3Q6MTEyMTFcImAuXG4gICAqXG4gICAqIFRoZSBvcHRpb25zIGhhc2ggbWF5IGNvbnRhaW4gdGhlIG9wdGlvbnM6XG4gICAqXG4gICAqICogYHJldHJpZXNgIC0gdGhlIG51bWJlciBvZiB0aW1lcyB0byByZXRyeSBhbiBvcGVyYXRpb24gaW4gbGlldSBvZiBmYWlsdXJlc1xuICAgKiAoZGVmYXVsdCAyKVxuICAgKiAqIGBleHBpcmVzYCAtIHRoZSBkZWZhdWx0IGV4cGlyYXRpb24gaW4gc2Vjb25kcyB0byB1c2UgKGRlZmF1bHQgMCAtIG5ldmVyXG4gICAqIGV4cGlyZSkuIElmIGBleHBpcmVzYCBpcyBncmVhdGVyIHRoYW4gMzAgZGF5cyAoNjAgeCA2MCB4IDI0IHggMzApLCBpdCBpc1xuICAgKiB0cmVhdGVkIGFzIGEgVU5JWCB0aW1lIChudW1iZXIgb2Ygc2Vjb25kcyBzaW5jZSBKYW51YXJ5IDEsIDE5NzApLlxuICAgKiAqIGBsb2dnZXJgIC0gYSBsb2dnZXIgb2JqZWN0IHRoYXQgcmVzcG9uZHMgdG8gYGxvZyhzdHJpbmcpYCBtZXRob2QgY2FsbHMuXG4gICAqXG4gICAqICAgfn5+flxuICAgKiAgICAgbG9nKG1zZzFbLCBtc2cyWywgbXNnM1suLi5dXV0pXG4gICAqICAgfn5+flxuICAgKlxuICAgKiAgIERlZmF1bHRzIHRvIGBjb25zb2xlYC5cbiAgICogKiBgc2VyaWFsaXplcmAgLSB0aGUgb2JqZWN0IHdoaWNoIHdpbGwgKGRlKXNlcmlhbGl6ZSB0aGUgZGF0YS4gSXQgbmVlZHNcbiAgICogICB0d28gcHVibGljIG1ldGhvZHM6IHNlcmlhbGl6ZSBhbmQgZGVzZXJpYWxpemUuIEl0IGRlZmF1bHRzIHRvIHRoZVxuICAgKiAgIG5vb3BTZXJpYWxpemVyOlxuICAgKlxuICAgKiAgIH5+fn5cbiAgICogICBjb25zdCBub29wU2VyaWFsaXplciA9IHtcbiAgICogICAgIHNlcmlhbGl6ZTogZnVuY3Rpb24gKG9wY29kZSwgdmFsdWUsIGV4dHJhcykge1xuICAgKiAgICAgICByZXR1cm4geyB2YWx1ZTogdmFsdWUsIGV4dHJhczogZXh0cmFzIH07XG4gICAqICAgICB9LFxuICAgKiAgICAgZGVzZXJpYWxpemU6IGZ1bmN0aW9uIChvcGNvZGUsIHZhbHVlLCBleHRyYXMpIHtcbiAgICogICAgICAgcmV0dXJuIHsgdmFsdWU6IHZhbHVlLCBleHRyYXM6IGV4dHJhcyB9O1xuICAgKiAgICAgfVxuICAgKiAgIH07XG4gICAqICAgfn5+flxuICAgKlxuICAgKiBPciBvcHRpb25zIGZvciB0aGUgc2VydmVycyBpbmNsdWRpbmc6XG4gICAqICogYHVzZXJuYW1lYCBhbmQgYHBhc3N3b3JkYCBmb3IgZmFsbGJhY2sgU0FTTCBhdXRoZW50aWNhdGlvbiBjcmVkZW50aWFscy5cbiAgICogKiBgdGltZW91dGAgaW4gc2Vjb25kcyB0byBkZXRlcm1pbmUgZmFpbHVyZSBmb3Igb3BlcmF0aW9ucy4gRGVmYXVsdCBpcyAwLjVcbiAgICogICAgICAgICAgICAgc2Vjb25kcy5cbiAgICogKiAnY29ubnRpbWVvdXQnIGluIHNlY29uZHMgdG8gY29ubmVjdGlvbiBmYWlsdXJlLiBEZWZhdWx0IGlzIHR3aWNlIHRoZSB2YWx1ZVxuICAgKiAgICAgICAgICAgICAgICAgb2YgYHRpbWVvdXRgLlxuICAgKiAqIGBrZWVwQWxpdmVgIHdoZXRoZXIgdG8gZW5hYmxlIGtlZXAtYWxpdmUgZnVuY3Rpb25hbGl0eS4gRGVmYXVsdHMgdG8gZmFsc2UuXG4gICAqICogYGtlZXBBbGl2ZURlbGF5YCBpbiBzZWNvbmRzIHRvIHRoZSBpbml0aWFsIGRlbGF5IGJlZm9yZSB0aGUgZmlyc3Qga2VlcGFsaXZlXG4gICAqICAgICAgICAgICAgICAgICAgICBwcm9iZSBpcyBzZW50IG9uIGFuIGlkbGUgc29ja2V0LiBEZWZhdWx0cyBpcyAzMCBzZWNvbmRzLlxuICAgKiAqIGBrZXlUb1NlcnZlckhhc2hGdW5jdGlvbmAgYSBmdW5jdGlvbiB0byBtYXAga2V5cyB0byBzZXJ2ZXJzLCB3aXRoIHRoZSBzaWduYXR1cmVcbiAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgKHNlcnZlcktleXM6IHN0cmluZ1tdLCBrZXk6IHN0cmluZyk6IHN0cmluZ1xuICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICBOT1RFOiBpZiB5b3UgbmVlZCB0byBkbyBzb21lIGV4cGVuc2l2ZSBpbml0aWFsaXphdGlvbiwgKnBsZWFzZSogZG8gaXQgbGF6aWx5IHRoZSBmaXJzdCB0aW1lIHlvdSB0aGlzIGZ1bmN0aW9uIGlzIGNhbGxlZCB3aXRoIGFuIGFycmF5IG9mIHNlcnZlcktleXMsIG5vdCBvbiBldmVyeSBjYWxsXG4gICAqL1xuICBzdGF0aWMgY3JlYXRlPFZhbHVlLCBFeHRyYXM+KFxuICAgIHNlcnZlcnNTdHI6IHN0cmluZyB8IHVuZGVmaW5lZCxcbiAgICBvcHRpb25zOiBJZkJ1ZmZlcjxcbiAgICAgIFZhbHVlLFxuICAgICAgRXh0cmFzLFxuICAgICAgdW5kZWZpbmVkIHwgKFBhcnRpYWw8U2VydmVyT3B0aW9ucz4gJiBHaXZlbkNsaWVudE9wdGlvbnM8VmFsdWUsIEV4dHJhcz4pLFxuICAgICAgUGFydGlhbDxTZXJ2ZXJPcHRpb25zPiAmIEdpdmVuQ2xpZW50T3B0aW9uczxWYWx1ZSwgRXh0cmFzPlxuICAgID5cbiAgKTogQ2xpZW50PFZhbHVlLCBFeHRyYXM+IHtcbiAgICBzZXJ2ZXJzU3RyID1cbiAgICAgIHNlcnZlcnNTdHIgfHxcbiAgICAgIHByb2Nlc3MuZW52Lk1FTUNBQ0hJRVJfU0VSVkVSUyB8fFxuICAgICAgcHJvY2Vzcy5lbnYuTUVNQ0FDSEVfU0VSVkVSUyB8fFxuICAgICAgXCJsb2NhbGhvc3Q6MTEyMTFcIjtcbiAgICBjb25zdCBzZXJ2ZXJVcmlzID0gc2VydmVyc1N0ci5zcGxpdChcIixcIik7XG4gICAgY29uc3Qgc2VydmVycyA9IHNlcnZlclVyaXMubWFwKGZ1bmN0aW9uICh1cmkpIHtcbiAgICAgIGNvbnN0IHVyaVBhcnRzID0gdXJpLnNwbGl0KFwiQFwiKTtcbiAgICAgIGNvbnN0IGhvc3RQb3J0ID0gdXJpUGFydHNbdXJpUGFydHMubGVuZ3RoIC0gMV0uc3BsaXQoXCI6XCIpO1xuICAgICAgY29uc3QgdXNlclBhc3MgPSAodXJpUGFydHNbdXJpUGFydHMubGVuZ3RoIC0gMl0gfHwgXCJcIikuc3BsaXQoXCI6XCIpO1xuICAgICAgcmV0dXJuIG5ldyBTZXJ2ZXIoXG4gICAgICAgIGhvc3RQb3J0WzBdLFxuICAgICAgICBwYXJzZUludChob3N0UG9ydFsxXSB8fCBcIjExMjExXCIsIDEwKSxcbiAgICAgICAgdXNlclBhc3NbMF0sXG4gICAgICAgIHVzZXJQYXNzWzFdLFxuICAgICAgICBvcHRpb25zXG4gICAgICApO1xuICAgIH0pO1xuICAgIHJldHVybiBuZXcgQ2xpZW50KHNlcnZlcnMsIG9wdGlvbnMgYXMgYW55KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHaXZlbiBhIHNlcnZlcktleSBmcm9tbG9va3VwS2V5VG9TZXJ2ZXJLZXksIHJldHVybiB0aGUgY29ycmVzcG9uZGluZyBTZXJ2ZXIgaW5zdGFuY2VcbiAgICpcbiAgICogQHBhcmFtICB7c3RyaW5nfSBzZXJ2ZXJLZXlcbiAgICogQHJldHVybnMge1NlcnZlcn1cbiAgICovXG4gIHNlcnZlcktleVRvU2VydmVyKHNlcnZlcktleTogc3RyaW5nKTogU2VydmVyIHtcbiAgICByZXR1cm4gdGhpcy5zZXJ2ZXJNYXBbc2VydmVyS2V5XTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHaXZlbiBhIGtleSB0byBsb29rIHVwIGluIG1lbWNhY2hlLCByZXR1cm4gYSBzZXJ2ZXJLZXkgKGJhc2VkIG9uIHNvbWVcbiAgICogaGFzaGluZyBmdW5jdGlvbikgd2hpY2ggY2FuIGJlIHVzZWQgdG8gaW5kZXggdGhpcy5zZXJ2ZXJNYXBcbiAgICovXG4gIGxvb2t1cEtleVRvU2VydmVyS2V5KGtleTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5vcHRpb25zLmtleVRvU2VydmVySGFzaEZ1bmN0aW9uKHRoaXMuc2VydmVyS2V5cywga2V5KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXRyaWV2ZXMgdGhlIHZhbHVlIGF0IHRoZSBnaXZlbiBrZXkgaW4gbWVtY2FjaGUuXG4gICAqL1xuICBhc3luYyBnZXQoa2V5OiBzdHJpbmcpOiBQcm9taXNlPEdldFJlc3VsdDxWYWx1ZSwgRXh0cmFzPiB8IG51bGw+IHtcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoY29uc3RhbnRzLk9QX0dFVCwga2V5LCBcIlwiLCBcIlwiLCB0aGlzLnNlcSk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIGNvbnN0IGRlc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5kZXNlcmlhbGl6ZShcbiAgICAgICAgICByZXNwb25zZS5oZWFkZXIub3Bjb2RlLFxuICAgICAgICAgIHJlc3BvbnNlLnZhbCxcbiAgICAgICAgICByZXNwb25zZS5leHRyYXNcbiAgICAgICAgKTtcbiAgICAgICAgcmV0dXJuIHsgLi4uZGVzZXJpYWxpemVkLCBjYXM6IHJlc3BvbnNlLmhlYWRlci5jYXMgfTtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuS0VZX05PVF9GT1VORDpcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiR0VUXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBCdWlsZCBhIHBpcGVsaW5lZCBnZXQgbXVsdGkgcmVxdWVzdCBieSBzZW5kaW5nIG9uZSBHRVRLUSBmb3IgZWFjaCBrZXkgKHF1aWV0LCBtZWFuaW5nIGl0IHdvbid0IHJlc3BvbmQgaWYgdGhlIHZhbHVlIGlzIG1pc3NpbmcpIGZvbGxvd2VkIGJ5IGEgbm8tb3AgdG8gZm9yY2UgYSByZXNwb25zZSAoYW5kIHRvIGdpdmUgdXMgYSBzZW50aW5lbCByZXNwb25zZSB0aGF0IHRoZSBwaXBlbGluZSBpcyBkb25lKVxuICAgKlxuICAgKiBjZiBodHRwczovL2dpdGh1Yi5jb20vY291Y2hiYXNlL21lbWNhY2hlZC9ibG9iL21hc3Rlci9kb2NzL0JpbmFyeVByb3RvY29sLm1kIzB4MGQtZ2V0a3EtZ2V0LXdpdGgta2V5LXF1aWV0bHlcbiAgICovXG4gIF9idWlsZEdldE11bHRpUmVxdWVzdChrZXlzOiBzdHJpbmdbXSwgc2VxOiBudW1iZXIpOiBCdWZmZXIge1xuICAgIC8vIHN0YXJ0IGF0IDI0IGZvciB0aGUgbm8tb3AgY29tbWFuZCBhdCB0aGUgZW5kXG4gICAgbGV0IHJlcXVlc3RTaXplID0gMjQ7XG4gICAgZm9yIChjb25zdCBrZXlJZHggaW4ga2V5cykge1xuICAgICAgcmVxdWVzdFNpemUgKz0gQnVmZmVyLmJ5dGVMZW5ndGgoa2V5c1trZXlJZHhdLCBcInV0ZjhcIikgKyAyNDtcbiAgICB9XG5cbiAgICBjb25zdCByZXF1ZXN0ID0gQnVmZmVyLmFsbG9jKHJlcXVlc3RTaXplKTtcblxuICAgIGxldCBieXRlc1dyaXR0ZW4gPSAwO1xuICAgIGZvciAoY29uc3Qga2V5SWR4IGluIGtleXMpIHtcbiAgICAgIGNvbnN0IGtleSA9IGtleXNba2V5SWR4XTtcbiAgICAgIGJ5dGVzV3JpdHRlbiArPSBjb3B5SW50b1JlcXVlc3RCdWZmZXIoXG4gICAgICAgIGNvbnN0YW50cy5PUF9HRVRLUSxcbiAgICAgICAga2V5LFxuICAgICAgICBcIlwiLFxuICAgICAgICBcIlwiLFxuICAgICAgICBzZXEsXG4gICAgICAgIHJlcXVlc3QsXG4gICAgICAgIGJ5dGVzV3JpdHRlblxuICAgICAgKTtcbiAgICB9XG5cbiAgICBieXRlc1dyaXR0ZW4gKz0gY29weUludG9SZXF1ZXN0QnVmZmVyKFxuICAgICAgY29uc3RhbnRzLk9QX05PX09QLFxuICAgICAgXCJcIixcbiAgICAgIFwiXCIsXG4gICAgICBcIlwiLFxuICAgICAgc2VxLFxuICAgICAgcmVxdWVzdCxcbiAgICAgIGJ5dGVzV3JpdHRlblxuICAgICk7XG5cbiAgICByZXR1cm4gcmVxdWVzdDtcbiAgfVxuXG4gIC8qKiBFeGVjdXRpbmcgYSBwaXBlbGluZWQgKG11bHRpKSBnZXQgYWdhaW5zdCBhIHNpbmdsZSBzZXJ2ZXIuIFRoaXMgaXMgYSBwcml2YXRlIGltcGxlbWVudGF0aW9uIGRldGFpbCBvZiBnZXRNdWx0aS4gKi9cbiAgYXN5bmMgX2dldE11bHRpVG9TZXJ2ZXI8S2V5cyBleHRlbmRzIHN0cmluZz4oXG4gICAgc2VydjogU2VydmVyLFxuICAgIGtleXM6IEtleXNbXVxuICApOiBQcm9taXNlPEdldE11bHRpUmVzdWx0PEtleXMsIFZhbHVlLCBFeHRyYXM+PiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGNvbnN0IHJlc3BvbnNlTWFwOiBHZXRNdWx0aVJlc3VsdDxzdHJpbmcsIFZhbHVlLCBFeHRyYXM+ID0ge307XG5cbiAgICAgIGNvbnN0IGhhbmRsZTogT25SZXNwb25zZUNhbGxiYWNrID0gKHJlc3BvbnNlKSA9PiB7XG4gICAgICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgICAgIC8vIFdoZW4gd2UgZ2V0IHRoZSBuby1vcCByZXNwb25zZSwgd2UgYXJlIGRvbmUgd2l0aCB0aGlzIG9uZSBnZXRNdWx0aSBpbiB0aGUgcGVyLWJhY2tlbmQgZmFuLW91dFxuICAgICAgICAgICAgaWYgKHJlc3BvbnNlLmhlYWRlci5vcGNvZGUgPT09IGNvbnN0YW50cy5PUF9OT19PUCkge1xuICAgICAgICAgICAgICAvLyBUaGlzIGVuc3VyZXMgdGhlIGhhbmRsZXIgd2lsbCBiZSBkZWxldGVkIGZyb20gdGhlIHJlc3BvbnNlQ2FsbGJhY2tzIG1hcCBpbiBzZXJ2ZXIuanNcbiAgICAgICAgICAgICAgLy8gVGhpcyBpc24ndCB0ZWNobmljYWxseSBuZWVkZWQgaGVyZSBiZWNhdXNlIHRoZSBsb2dpYyBpbiBzZXJ2ZXIuanMgYWxzbyBjaGVja3MgaWYgdG90YWxCb2R5TGVuZ3RoID09PSAwLCBidXQgb3VyIHVuaXR0ZXN0cyBhcmVuJ3QgZ3JlYXQgYWJvdXQgc2V0dGluZyB0aGF0IGZpZWxkLCBhbmQgYWxzbyB0aGlzIG1ha2VzIGl0IG1vcmUgZXhwbGljaXRcbiAgICAgICAgICAgICAgaGFuZGxlLnF1aWV0ID0gZmFsc2U7XG4gICAgICAgICAgICAgIHJlc29sdmUocmVzcG9uc2VNYXApO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgICAgICAgcmVzcG9uc2UuaGVhZGVyLm9wY29kZSA9PT0gY29uc3RhbnRzLk9QX0dFVEsgfHxcbiAgICAgICAgICAgICAgcmVzcG9uc2UuaGVhZGVyLm9wY29kZSA9PT0gY29uc3RhbnRzLk9QX0dFVEtRXG4gICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgY29uc3QgZGVzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLmRlc2VyaWFsaXplKFxuICAgICAgICAgICAgICAgIHJlc3BvbnNlLmhlYWRlci5vcGNvZGUsXG4gICAgICAgICAgICAgICAgcmVzcG9uc2UudmFsLFxuICAgICAgICAgICAgICAgIHJlc3BvbnNlLmV4dHJhc1xuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICBjb25zdCBrZXkgPSByZXNwb25zZS5rZXkudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgaWYgKGtleS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVqZWN0KFxuICAgICAgICAgICAgICAgICAgbmV3IEVycm9yKFxuICAgICAgICAgICAgICAgICAgICBcIlJlY2lldmVkIGVtcHR5IGtleSBpbiBnZXRNdWx0aTogXCIgK1xuICAgICAgICAgICAgICAgICAgICAgIEpTT04uc3RyaW5naWZ5KHJlc3BvbnNlKVxuICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgcmVzcG9uc2VNYXBba2V5XSA9IHsgLi4uZGVzZXJpYWxpemVkLCBjYXM6IHJlc3BvbnNlLmhlYWRlci5jYXMgfTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHJldHVybiByZWplY3QoXG4gICAgICAgICAgICAgICAgbmV3IEVycm9yKFxuICAgICAgICAgICAgICAgICAgXCJSZWNpZXZlZCByZXNwb25zZSBpbiBnZXRNdWx0aSBmb3IgdW5rbm93biBvcGNvZGU6IFwiICtcbiAgICAgICAgICAgICAgICAgICAgSlNPTi5zdHJpbmdpZnkocmVzcG9uc2UpXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHJldHVybiByZWplY3QoXG4gICAgICAgICAgICAgIHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJHRVRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cylcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH07XG4gICAgICAvLyBUaGlzIHByZXZlbnRzIHRoZSBoYW5kbGVyIGZyb20gYmVpbmcgZGVsZXRlZFxuICAgICAgLy8gYWZ0ZXIgdGhlIGZpcnN0IHJlc3BvbnNlLiBMb2dpYyBpbiBzZXJ2ZXIuanMuXG4gICAgICBoYW5kbGUucXVpZXQgPSB0cnVlO1xuXG4gICAgICBjb25zdCBzZXEgPSB0aGlzLmluY3JTZXEoKTtcbiAgICAgIGNvbnN0IHJlcXVlc3QgPSB0aGlzLl9idWlsZEdldE11bHRpUmVxdWVzdChrZXlzLCBzZXEpO1xuICAgICAgc2Vydi5vblJlc3BvbnNlKHRoaXMuc2VxLCBoYW5kbGUpO1xuICAgICAgc2Vydi5vbkVycm9yKHRoaXMuc2VxLCByZWplY3QpO1xuICAgICAgc2Vydi53cml0ZShyZXF1ZXN0KTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXRyaWV2cyB0aGUgdmFsdWUgYXQgdGhlIGdpdmVuIGtleXMgaW4gbWVtY2FjaGVkLiBSZXR1cm5zIGEgbWFwIGZyb20gdGhlXG4gICAqIHJlcXVlc3RlZCBrZXlzIHRvIHJlc3VsdHMsIG9yIG51bGwgaWYgdGhlIGtleSB3YXMgbm90IGZvdW5kLlxuICAgKi9cbiAgYXN5bmMgZ2V0TXVsdGk8S2V5cyBleHRlbmRzIHN0cmluZz4oXG4gICAga2V5czogS2V5c1tdXG4gICk6IFByb21pc2U8R2V0TXVsdGlSZXN1bHQ8S2V5cywgVmFsdWUsIEV4dHJhcz4+IHtcbiAgICBjb25zdCBzZXJ2ZXJLZXl0b0xvb2t1cEtleXM6IHtcbiAgICAgIFtzZXJ2ZXJLZXk6IHN0cmluZ106IHN0cmluZ1tdO1xuICAgIH0gPSB7fTtcbiAgICBrZXlzLmZvckVhY2goKGxvb2t1cEtleSkgPT4ge1xuICAgICAgY29uc3Qgc2VydmVyS2V5ID0gdGhpcy5sb29rdXBLZXlUb1NlcnZlcktleShsb29rdXBLZXkpO1xuICAgICAgaWYgKCFzZXJ2ZXJLZXl0b0xvb2t1cEtleXNbc2VydmVyS2V5XSkge1xuICAgICAgICBzZXJ2ZXJLZXl0b0xvb2t1cEtleXNbc2VydmVyS2V5XSA9IFtdO1xuICAgICAgfVxuICAgICAgc2VydmVyS2V5dG9Mb29rdXBLZXlzW3NlcnZlcktleV0ucHVzaChsb29rdXBLZXkpO1xuICAgIH0pO1xuXG4gICAgY29uc3QgdXNlZFNlcnZlcktleXMgPSBPYmplY3Qua2V5cyhzZXJ2ZXJLZXl0b0xvb2t1cEtleXMpO1xuICAgIGNvbnN0IHJlc3VsdHMgPSBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIHVzZWRTZXJ2ZXJLZXlzLm1hcCgoc2VydmVyS2V5KSA9PiB7XG4gICAgICAgIGNvbnN0IHNlcnZlciA9IHRoaXMuc2VydmVyS2V5VG9TZXJ2ZXIoc2VydmVyS2V5KTtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2dldE11bHRpVG9TZXJ2ZXIoc2VydmVyLCBzZXJ2ZXJLZXl0b0xvb2t1cEtleXNbc2VydmVyS2V5XSk7XG4gICAgICB9KVxuICAgICk7XG5cbiAgICByZXR1cm4gT2JqZWN0LmFzc2lnbih7fSwgLi4ucmVzdWx0cyk7XG4gIH1cblxuICBhc3luYyBnZXRNdWx0aVdpdGhFcnJvcnM8S2V5cyBleHRlbmRzIHN0cmluZz4oXG4gICAga2V5czogS2V5c1tdXG4gICk6IFByb21pc2U8R2V0TXVsdGlXaXRoRXJyb3JzUmVzdWx0PEtleXMsIFZhbHVlLCBFeHRyYXM+PiB7XG4gICAgY29uc3Qgc2VydmVyS2V5dG9Mb29rdXBLZXlzOiB7XG4gICAgICBbc2VydmVyS2V5OiBzdHJpbmddOiBLZXlzW107XG4gICAgfSA9IHt9O1xuICAgIGtleXMuZm9yRWFjaCgobG9va3VwS2V5KSA9PiB7XG4gICAgICBjb25zdCBzZXJ2ZXJLZXkgPSB0aGlzLmxvb2t1cEtleVRvU2VydmVyS2V5KGxvb2t1cEtleSk7XG4gICAgICBpZiAoIXNlcnZlcktleXRvTG9va3VwS2V5c1tzZXJ2ZXJLZXldKSB7XG4gICAgICAgIHNlcnZlcktleXRvTG9va3VwS2V5c1tzZXJ2ZXJLZXldID0gW107XG4gICAgICB9XG4gICAgICBzZXJ2ZXJLZXl0b0xvb2t1cEtleXNbc2VydmVyS2V5XS5wdXNoKGxvb2t1cEtleSk7XG4gICAgfSk7XG5cbiAgICBjb25zdCB1c2VkU2VydmVyS2V5cyA9IE9iamVjdC5rZXlzKHNlcnZlcktleXRvTG9va3VwS2V5cyk7XG4gICAgY29uc3QgZXJyb3JzOiBHZXRNdWx0aUVycm9yPEtleXM+W10gPSBbXTtcbiAgICBjb25zdCByZXN1bHRzID0gYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICB1c2VkU2VydmVyS2V5cy5tYXAoYXN5bmMgKHNlcnZlcktleSkgPT4ge1xuICAgICAgICBjb25zdCBzZXJ2ZXIgPSB0aGlzLnNlcnZlcktleVRvU2VydmVyKHNlcnZlcktleSk7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgcmV0dXJuIGF3YWl0IHRoaXMuX2dldE11bHRpVG9TZXJ2ZXIoc2VydmVyLCBzZXJ2ZXJLZXl0b0xvb2t1cEtleXNbc2VydmVyS2V5XSk7XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgIGxldCBlcnJvcjogRXJyb3I7XG4gICAgICAgICAgaWYgKGVyciBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgICAgICBlcnJvciA9IGVycjtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZXJyb3IgPSBuZXcgRXJyb3IoXCJVbmtub3duIEVycm9yXCIpO1xuICAgICAgICAgICAgKGVycm9yIGFzIGFueSkudGhyb3duID0gZXJyO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGVycm9ycy5wdXNoKHtcbiAgICAgICAgICAgIGVycm9yLFxuICAgICAgICAgICAgc2VydmVyS2V5LFxuICAgICAgICAgICAga2V5czogc2VydmVyS2V5dG9Mb29rdXBLZXlzW3NlcnZlcktleV1cbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfSlcbiAgICApO1xuXG4gICAgcmV0dXJuIHsgcmVzdWx0OiBPYmplY3QuYXNzaWduKHt9LCAuLi5yZXN1bHRzKSwgZXJyb3JzIH07XG4gIH1cblxuICAvKipcbiAgICogU2V0cyBga2V5YCB0byBgdmFsdWVgLlxuICAgKi9cbiAgYXN5bmMgc2V0KFxuICAgIGtleTogc3RyaW5nLFxuICAgIHZhbHVlOiBWYWx1ZSxcbiAgICBvcHRpb25zPzogeyBleHBpcmVzPzogbnVtYmVyOyBjYXM/OiBDQVNUb2tlbiB9XG4gICk6IFByb21pc2U8Ym9vbGVhbiB8IG51bGw+IHtcbiAgICBjb25zdCBleHBpcmVzID0gb3B0aW9ucz8uZXhwaXJlcztcbiAgICBjb25zdCBjYXMgPSBvcHRpb25zPy5jYXM7XG5cbiAgICAvLyBUT0RPOiBzdXBwb3J0IGZsYWdzXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgZXhwaXJhdGlvbiA9IG1ha2VFeHBpcmF0aW9uKGV4cGlyZXMgfHwgdGhpcy5vcHRpb25zLmV4cGlyZXMpO1xuICAgIGNvbnN0IGV4dHJhcyA9IEJ1ZmZlci5jb25jYXQoW0J1ZmZlci5mcm9tKFwiMDAwMDAwMDBcIiwgXCJoZXhcIiksIGV4cGlyYXRpb25dKTtcbiAgICBjb25zdCBzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLnNlcmlhbGl6ZShcbiAgICAgIGNvbnN0YW50cy5PUF9TRVQsXG4gICAgICB2YWx1ZSxcbiAgICAgIGV4dHJhc1xuICAgICk7XG4gICAgY29uc3QgcmVxdWVzdCA9IFV0aWxzLmVuY29kZVJlcXVlc3Qoe1xuICAgICAgaGVhZGVyOiB7XG4gICAgICAgIG9wY29kZTogY29uc3RhbnRzLk9QX1NFVCxcbiAgICAgICAgb3BhcXVlOiB0aGlzLnNlcSxcbiAgICAgICAgY2FzLFxuICAgICAgfSxcbiAgICAgIGtleSxcbiAgICAgIHZhbHVlOiBzZXJpYWxpemVkLnZhbHVlLFxuICAgICAgZXh0cmFzOiBzZXJpYWxpemVkLmV4dHJhcyxcbiAgICB9KTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9FWElTVFM6XG4gICAgICAgIGlmIChjYXMpIHtcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIlNFVFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICAgICAgfVxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIlNFVFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQUREXG4gICAqXG4gICAqIEFkZHMgdGhlIGdpdmVuIF9rZXlfIGFuZCBfdmFsdWVfIHRvIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHNcbiAgICogaWYgdGhlIGtleSBpcyBub3QgYWxyZWFkeSBzZXQuXG4gICAqXG4gICAqIFRoZSBvcHRpb25zIGRpY3Rpb25hcnkgdGFrZXM6XG4gICAqICogX2V4cGlyZXNfOiBvdmVycmlkZXMgdGhlIGRlZmF1bHQgZXhwaXJhdGlvbiAoc2VlIGBDbGllbnQuY3JlYXRlYCkgZm9yIHRoaXNcbiAgICogICAgICAgICAgICAgIHBhcnRpY3VsYXIga2V5LXZhbHVlIHBhaXIuXG4gICAqL1xuICBhc3luYyBhZGQoXG4gICAga2V5OiBzdHJpbmcsXG4gICAgdmFsdWU6IFZhbHVlLFxuICAgIG9wdGlvbnM/OiB7IGV4cGlyZXM/OiBudW1iZXIgfVxuICApOiBQcm9taXNlPGJvb2xlYW4gfCBudWxsPiB7XG4gICAgLy8gVE9ETzogc3VwcG9ydCBmbGFncywgc3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgZXhwaXJhdGlvbiA9IG1ha2VFeHBpcmF0aW9uKG9wdGlvbnM/LmV4cGlyZXMgfHwgdGhpcy5vcHRpb25zLmV4cGlyZXMpO1xuICAgIGNvbnN0IGV4dHJhcyA9IEJ1ZmZlci5jb25jYXQoW0J1ZmZlci5mcm9tKFwiMDAwMDAwMDBcIiwgXCJoZXhcIiksIGV4cGlyYXRpb25dKTtcblxuICAgIGNvbnN0IG9wY29kZSA9IGNvbnN0YW50cy5PUF9BREQ7XG4gICAgY29uc3Qgc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5zZXJpYWxpemUob3Bjb2RlLCB2YWx1ZSwgZXh0cmFzKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICBvcGNvZGUsXG4gICAgICBrZXksXG4gICAgICBzZXJpYWxpemVkLmV4dHJhcyxcbiAgICAgIHNlcmlhbGl6ZWQudmFsdWUsXG4gICAgICB0aGlzLnNlcVxuICAgICk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfRVhJU1RTOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIkFERFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmVwbGFjZXMgdGhlIGdpdmVuIF9rZXlfIGFuZCBfdmFsdWVfIHRvIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHNcbiAgICogaWYgdGhlIGtleSBpcyBhbHJlYWR5IHByZXNlbnQuXG4gICAqL1xuICBhc3luYyByZXBsYWNlKFxuICAgIGtleTogc3RyaW5nLFxuICAgIHZhbHVlOiBWYWx1ZSxcbiAgICBvcHRpb25zPzogeyBleHBpcmVzPzogbnVtYmVyIH1cbiAgKTogUHJvbWlzZTxib29sZWFuIHwgbnVsbD4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgZmxhZ3MsIHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IGV4cGlyYXRpb24gPSBtYWtlRXhwaXJhdGlvbihvcHRpb25zPy5leHBpcmVzIHx8IHRoaXMub3B0aW9ucy5leHBpcmVzKTtcbiAgICBjb25zdCBleHRyYXMgPSBCdWZmZXIuY29uY2F0KFtCdWZmZXIuZnJvbShcIjAwMDAwMDAwXCIsIFwiaGV4XCIpLCBleHBpcmF0aW9uXSk7XG5cbiAgICBjb25zdCBvcGNvZGU6IGNvbnN0YW50cy5PUCA9IGNvbnN0YW50cy5PUF9SRVBMQUNFO1xuICAgIGNvbnN0IHNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuc2VyaWFsaXplKG9wY29kZSwgdmFsdWUsIGV4dHJhcyk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKFxuICAgICAgb3Bjb2RlLFxuICAgICAga2V5LFxuICAgICAgc2VyaWFsaXplZC5leHRyYXMsXG4gICAgICBzZXJpYWxpemVkLnZhbHVlLFxuICAgICAgdGhpcy5zZXFcbiAgICApO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuS0VZX05PVF9GT1VORDpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIlJFUExBQ0VcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIERlbGV0ZXMgdGhlIGdpdmVuIF9rZXlfIGZyb20gbWVtY2FjaGUuIFRoZSBvcGVyYXRpb24gb25seSBzdWNjZWVkc1xuICAgKiBpZiB0aGUga2V5IGlzIGFscmVhZHkgcHJlc2VudC5cbiAgICovXG4gIGFzeW5jIGRlbGV0ZShrZXk6IHN0cmluZyk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIC8vIFRPRE86IFN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcig0LCBrZXksIFwiXCIsIFwiXCIsIHRoaXMuc2VxKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcblxuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuS0VZX05PVF9GT1VORDpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIkRFTEVURVwiLCByZXNwb25zZT8uaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEluY3JlbWVudHMgdGhlIGdpdmVuIF9rZXlfIGluIG1lbWNhY2hlLlxuICAgKi9cbiAgYXN5bmMgaW5jcmVtZW50KFxuICAgIGtleTogc3RyaW5nLFxuICAgIGFtb3VudDogbnVtYmVyLFxuICAgIG9wdGlvbnM/OiB7IGluaXRpYWw/OiBudW1iZXI7IGV4cGlyZXM/OiBudW1iZXIgfVxuICApOiBQcm9taXNlPHsgdmFsdWU6IG51bWJlciB8IG51bGw7IHN1Y2Nlc3M6IGJvb2xlYW4gfCBudWxsIH0+IHtcbiAgICAvLyBUT0RPOiBzdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBpbml0aWFsID0gb3B0aW9ucz8uaW5pdGlhbCB8fCAwO1xuICAgIGNvbnN0IGV4cGlyZXMgPSBvcHRpb25zPy5leHBpcmVzIHx8IHRoaXMub3B0aW9ucy5leHBpcmVzO1xuICAgIGNvbnN0IGV4dHJhcyA9IG1ha2VBbW91bnRJbml0aWFsQW5kRXhwaXJhdGlvbihhbW91bnQsIGluaXRpYWwsIGV4cGlyZXMpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgIGNvbnN0YW50cy5PUF9JTkNSRU1FTlQsXG4gICAgICBrZXksXG4gICAgICBleHRyYXMsXG4gICAgICBcIlwiLFxuICAgICAgdGhpcy5zZXFcbiAgICApO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICBjb25zdCBidWZJbnQgPVxuICAgICAgICAgIChyZXNwb25zZS52YWwucmVhZFVJbnQzMkJFKDApIDw8IDgpICsgcmVzcG9uc2UudmFsLnJlYWRVSW50MzJCRSg0KTtcbiAgICAgICAgcmV0dXJuIHsgdmFsdWU6IGJ1ZkludCwgc3VjY2VzczogdHJ1ZSB9O1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIklOQ1JFTUVOVFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRGVjcmVtZW50cyB0aGUgZ2l2ZW4gYGtleWAgaW4gbWVtY2FjaGUuXG4gICAqL1xuICBhc3luYyBkZWNyZW1lbnQoXG4gICAga2V5OiBzdHJpbmcsXG4gICAgYW1vdW50OiBudW1iZXIsXG4gICAgb3B0aW9uczogeyBpbml0aWFsPzogbnVtYmVyOyBleHBpcmVzPzogbnVtYmVyIH1cbiAgKTogUHJvbWlzZTx7IHZhbHVlOiBudW1iZXIgfCBudWxsOyBzdWNjZXNzOiBib29sZWFuIHwgbnVsbCB9PiB7XG4gICAgLy8gVE9ETzogc3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgaW5pdGlhbCA9IG9wdGlvbnMuaW5pdGlhbCB8fCAwO1xuICAgIGNvbnN0IGV4cGlyZXMgPSBvcHRpb25zLmV4cGlyZXMgfHwgdGhpcy5vcHRpb25zLmV4cGlyZXM7XG4gICAgY29uc3QgZXh0cmFzID0gbWFrZUFtb3VudEluaXRpYWxBbmRFeHBpcmF0aW9uKGFtb3VudCwgaW5pdGlhbCwgZXhwaXJlcyk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKFxuICAgICAgY29uc3RhbnRzLk9QX0RFQ1JFTUVOVCxcbiAgICAgIGtleSxcbiAgICAgIGV4dHJhcyxcbiAgICAgIFwiXCIsXG4gICAgICB0aGlzLnNlcVxuICAgICk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIGNvbnN0IGJ1ZkludCA9XG4gICAgICAgICAgKHJlc3BvbnNlLnZhbC5yZWFkVUludDMyQkUoMCkgPDwgOCkgKyByZXNwb25zZS52YWwucmVhZFVJbnQzMkJFKDQpO1xuICAgICAgICByZXR1cm4geyB2YWx1ZTogYnVmSW50LCBzdWNjZXNzOiB0cnVlIH07XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiREVDUkVNRU5UXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBBcHBlbmQgdGhlIGdpdmVuIF92YWx1ZV8gdG8gdGhlIHZhbHVlIGFzc29jaWF0ZWQgd2l0aCB0aGUgZ2l2ZW4gX2tleV8gaW5cbiAgICogbWVtY2FjaGUuIFRoZSBvcGVyYXRpb24gb25seSBzdWNjZWVkcyBpZiB0aGUga2V5IGlzIGFscmVhZHkgcHJlc2VudC5cbiAgICovXG4gIGFzeW5jIGFwcGVuZChrZXk6IHN0cmluZywgdmFsdWU6IFZhbHVlKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgLy8gVE9ETzogc3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3Qgb3Bjb2RlOiBjb25zdGFudHMuT1AgPSBjb25zdGFudHMuT1BfQVBQRU5EO1xuICAgIGNvbnN0IHNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuc2VyaWFsaXplKG9wY29kZSwgdmFsdWUsIFwiXCIpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgIG9wY29kZSxcbiAgICAgIGtleSxcbiAgICAgIHNlcmlhbGl6ZWQuZXh0cmFzLFxuICAgICAgc2VyaWFsaXplZC52YWx1ZSxcbiAgICAgIHRoaXMuc2VxXG4gICAgKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJBUFBFTkRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFByZXBlbmQgdGhlIGdpdmVuIF92YWx1ZV8gdG8gdGhlIHZhbHVlIGFzc29jaWF0ZWQgd2l0aCB0aGUgZ2l2ZW4gX2tleV8gaW5cbiAgICogbWVtY2FjaGUuIFRoZSBvcGVyYXRpb24gb25seSBzdWNjZWVkcyBpZiB0aGUga2V5IGlzIGFscmVhZHkgcHJlc2VudC5cbiAgICovXG4gIGFzeW5jIHByZXBlbmQoa2V5OiBzdHJpbmcsIHZhbHVlOiBWYWx1ZSk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IG9wY29kZTogY29uc3RhbnRzLk9QID0gY29uc3RhbnRzLk9QX1BSRVBFTkQ7XG4gICAgY29uc3Qgc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5zZXJpYWxpemUob3Bjb2RlLCB2YWx1ZSwgXCJcIik7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKFxuICAgICAgb3Bjb2RlLFxuICAgICAga2V5LFxuICAgICAgc2VyaWFsaXplZC5leHRyYXMsXG4gICAgICBzZXJpYWxpemVkLnZhbHVlLFxuICAgICAgdGhpcy5zZXFcbiAgICApO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuS0VZX05PVF9GT1VORDpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIlBSRVBFTkRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFRvdWNoIHNldHMgYW4gZXhwaXJhdGlvbiB2YWx1ZSwgZ2l2ZW4gYnkgX2V4cGlyZXNfLCBvbiB0aGUgZ2l2ZW4gX2tleV8gaW5cbiAgICogbWVtY2FjaGUuIFRoZSBvcGVyYXRpb24gb25seSBzdWNjZWVkcyBpZiB0aGUga2V5IGlzIGFscmVhZHkgcHJlc2VudC5cbiAgICovXG4gIGFzeW5jIHRvdWNoKGtleTogc3RyaW5nLCBleHBpcmVzOiBudW1iZXIpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAvLyBUT0RPOiBzdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBleHRyYXMgPSBtYWtlRXhwaXJhdGlvbihleHBpcmVzIHx8IHRoaXMub3B0aW9ucy5leHBpcmVzKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoMHgxYywga2V5LCBleHRyYXMsIFwiXCIsIHRoaXMuc2VxKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJUT1VDSFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRkxVU0hcbiAgICpcbiAgICogRmx1c2hlcyB0aGUgY2FjaGUgb24gZWFjaCBjb25uZWN0ZWQgc2VydmVyLiBUaGUgY2FsbGJhY2sgc2lnbmF0dXJlIGlzOlxuICAgKlxuICAgKiAgICAgY2FsbGJhY2sobGFzdEVyciwgcmVzdWx0cylcbiAgICpcbiAgICogd2hlcmUgX2xhc3RFcnJfIGlzIHRoZSBsYXN0IGVycm9yIGVuY291bnRlcmVkIChvciBudWxsLCBpbiB0aGUgY29tbW9uIGNhc2VcbiAgICogb2Ygbm8gZXJyb3JzKS4gX3Jlc3VsdHNfIGlzIGEgZGljdGlvbmFyeSBtYXBwaW5nIGBcImhvc3RuYW1lOnBvcnRcImAgdG8gZWl0aGVyXG4gICAqIGB0cnVlYCAoaWYgdGhlIG9wZXJhdGlvbiB3YXMgc3VjY2Vzc2Z1bCksIG9yIGFuIGVycm9yLlxuICAgKiBAcGFyYW0gY2FsbGJhY2tcbiAgICovXG4gIGZsdXNoKCk6IFByb21pc2U8UmVjb3JkPHN0cmluZywgYm9vbGVhbiB8IEVycm9yPj47XG4gIGZsdXNoKFxuICAgIGNhbGxiYWNrOiAoXG4gICAgICBlcnI6IEVycm9yIHwgbnVsbCxcbiAgICAgIHJlc3VsdHM6IFJlY29yZDxzdHJpbmcsIGJvb2xlYW4gfCBFcnJvcj5cbiAgICApID0+IHZvaWRcbiAgKTogdm9pZDtcbiAgZmx1c2goXG4gICAgY2FsbGJhY2s/OiAoXG4gICAgICBlcnI6IEVycm9yIHwgbnVsbCxcbiAgICAgIHJlc3VsdHM6IFJlY29yZDxzdHJpbmcsIGJvb2xlYW4gfCBFcnJvcj5cbiAgICApID0+IHZvaWRcbiAgKSB7XG4gICAgaWYgKGNhbGxiYWNrID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybiBwcm9taXNpZnkoKGNhbGxiYWNrKSA9PiB7XG4gICAgICAgIHRoaXMuZmx1c2goZnVuY3Rpb24gKGVyciwgcmVzdWx0cykge1xuICAgICAgICAgIGNhbGxiYWNrKGVyciwgcmVzdWx0cyk7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfVxuICAgIC8vIFRPRE86IHN1cHBvcnQgZXhwaXJhdGlvblxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcigweDA4LCBcIlwiLCBcIlwiLCBcIlwiLCB0aGlzLnNlcSk7XG4gICAgbGV0IGNvdW50ID0gdGhpcy5zZXJ2ZXJzLmxlbmd0aDtcbiAgICBjb25zdCByZXN1bHQ6IFJlY29yZDxzdHJpbmcsIGJvb2xlYW4gfCBFcnJvcj4gPSB7fTtcbiAgICBsZXQgbGFzdEVycjogRXJyb3IgfCBudWxsID0gbnVsbDtcblxuICAgIGNvbnN0IGhhbmRsZUZsdXNoID0gZnVuY3Rpb24gKHNlcTogbnVtYmVyLCBzZXJ2OiBTZXJ2ZXIpIHtcbiAgICAgIHNlcnYub25SZXNwb25zZShzZXEsIGZ1bmN0aW9uICgvKiByZXNwb25zZSAqLykge1xuICAgICAgICBjb3VudCAtPSAxO1xuICAgICAgICByZXN1bHRbc2Vydi5ob3N0cG9ydFN0cmluZygpXSA9IHRydWU7XG4gICAgICAgIGlmIChjYWxsYmFjayAmJiBjb3VudCA9PT0gMCkge1xuICAgICAgICAgIGNhbGxiYWNrKGxhc3RFcnIsIHJlc3VsdCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgc2Vydi5vbkVycm9yKHNlcSwgZnVuY3Rpb24gKGVycikge1xuICAgICAgICBjb3VudCAtPSAxO1xuICAgICAgICBsYXN0RXJyID0gZXJyO1xuICAgICAgICByZXN1bHRbc2Vydi5ob3N0cG9ydFN0cmluZygpXSA9IGVycjtcbiAgICAgICAgaWYgKGNhbGxiYWNrICYmIGNvdW50ID09PSAwKSB7XG4gICAgICAgICAgY2FsbGJhY2sobGFzdEVyciwgcmVzdWx0KTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICBzZXJ2LndyaXRlKHJlcXVlc3QpO1xuICAgIH07XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuc2VydmVycy5sZW5ndGg7IGkrKykge1xuICAgICAgaGFuZGxlRmx1c2godGhpcy5zZXEsIHRoaXMuc2VydmVyc1tpXSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNUQVRTX1dJVEhfS0VZXG4gICAqXG4gICAqIFNlbmRzIGEgbWVtY2FjaGUgc3RhdHMgY29tbWFuZCB3aXRoIGEga2V5IHRvIGVhY2ggY29ubmVjdGVkIHNlcnZlci4gVGhlXG4gICAqIGNhbGxiYWNrIGlzIGludm9rZWQgKipPTkNFIFBFUiBTRVJWRVIqKiBhbmQgaGFzIHRoZSBzaWduYXR1cmU6XG4gICAqXG4gICAqICAgICBjYWxsYmFjayhlcnIsIHNlcnZlciwgc3RhdHMpXG4gICAqXG4gICAqIF9zZXJ2ZXJfIGlzIHRoZSBgXCJob3N0bmFtZTpwb3J0XCJgIG9mIHRoZSBzZXJ2ZXIsIGFuZCBfc3RhdHNfIGlzIGEgZGljdGlvbmFyeVxuICAgKiBtYXBwaW5nIHRoZSBzdGF0IG5hbWUgdG8gdGhlIHZhbHVlIG9mIHRoZSBzdGF0aXN0aWMgYXMgYSBzdHJpbmcuXG4gICAqIEBwYXJhbSBrZXlcbiAgICogQHBhcmFtIGNhbGxiYWNrXG4gICAqL1xuICBzdGF0c1dpdGhLZXkoXG4gICAga2V5OiBzdHJpbmcsXG4gICAgY2FsbGJhY2s/OiAoXG4gICAgICBlcnI6IEVycm9yIHwgbnVsbCxcbiAgICAgIHNlcnZlcjogc3RyaW5nLFxuICAgICAgc3RhdHM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gfCBudWxsXG4gICAgKSA9PiB2b2lkXG4gICk6IHZvaWQge1xuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcigweDEwLCBrZXksIFwiXCIsIFwiXCIsIHRoaXMuc2VxKTtcblxuICAgIGNvbnN0IGhhbmRsZVN0YXRzID0gKHNlcTogbnVtYmVyLCBzZXJ2OiBTZXJ2ZXIpID0+IHtcbiAgICAgIGNvbnN0IHJlc3VsdDogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHt9O1xuICAgICAgY29uc3QgaGFuZGxlOiBPblJlc3BvbnNlQ2FsbGJhY2sgPSAocmVzcG9uc2UpID0+IHtcbiAgICAgICAgLy8gZW5kIG9mIHN0YXQgcmVzcG9uc2VzXG4gICAgICAgIGlmIChyZXNwb25zZS5oZWFkZXIudG90YWxCb2R5TGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgICAgICBjYWxsYmFjayhudWxsLCBzZXJ2Lmhvc3Rwb3J0U3RyaW5nKCksIHJlc3VsdCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICAvLyBwcm9jZXNzIHNpbmdsZSBzdGF0IGxpbmUgcmVzcG9uc2VcbiAgICAgICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICAgICAgcmVzdWx0W3Jlc3BvbnNlLmtleS50b1N0cmluZygpXSA9IHJlc3BvbnNlLnZhbC50b1N0cmluZygpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIGNvbnN0IGVycm9yID0gdGhpcy5oYW5kbGVSZXNwb25zZUVycm9yKFxuICAgICAgICAgICAgICBgU1RBVFMgKCR7a2V5fSlgLFxuICAgICAgICAgICAgICByZXNwb25zZS5oZWFkZXIuc3RhdHVzLFxuICAgICAgICAgICAgICB1bmRlZmluZWRcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgY2FsbGJhY2soZXJyb3IsIHNlcnYuaG9zdHBvcnRTdHJpbmcoKSwgbnVsbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH07XG4gICAgICBoYW5kbGUucXVpZXQgPSB0cnVlO1xuXG4gICAgICBzZXJ2Lm9uUmVzcG9uc2Uoc2VxLCBoYW5kbGUpO1xuICAgICAgc2Vydi5vbkVycm9yKHNlcSwgZnVuY3Rpb24gKGVycikge1xuICAgICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgICBjYWxsYmFjayhlcnIsIHNlcnYuaG9zdHBvcnRTdHJpbmcoKSwgbnVsbCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgc2Vydi53cml0ZShyZXF1ZXN0KTtcbiAgICB9O1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnNlcnZlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGhhbmRsZVN0YXRzKHRoaXMuc2VxLCB0aGlzLnNlcnZlcnNbaV0pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTVEFUU1xuICAgKlxuICAgKiBGZXRjaGVzIG1lbWNhY2hlIHN0YXRzIGZyb20gZWFjaCBjb25uZWN0ZWQgc2VydmVyLiBUaGUgY2FsbGJhY2sgaXMgaW52b2tlZFxuICAgKiAqKk9OQ0UgUEVSIFNFUlZFUioqIGFuZCBoYXMgdGhlIHNpZ25hdHVyZTpcbiAgICpcbiAgICogICAgIGNhbGxiYWNrKGVyciwgc2VydmVyLCBzdGF0cylcbiAgICpcbiAgICogX3NlcnZlcl8gaXMgdGhlIGBcImhvc3RuYW1lOnBvcnRcImAgb2YgdGhlIHNlcnZlciwgYW5kIF9zdGF0c18gaXMgYVxuICAgKiBkaWN0aW9uYXJ5IG1hcHBpbmcgdGhlIHN0YXQgbmFtZSB0byB0aGUgdmFsdWUgb2YgdGhlIHN0YXRpc3RpYyBhcyBhIHN0cmluZy5cbiAgICogQHBhcmFtIGNhbGxiYWNrXG4gICAqL1xuICBzdGF0cyhcbiAgICBjYWxsYmFjaz86IChcbiAgICAgIGVycjogRXJyb3IgfCBudWxsLFxuICAgICAgc2VydmVyOiBzdHJpbmcsXG4gICAgICBzdGF0czogUmVjb3JkPHN0cmluZywgc3RyaW5nPiB8IG51bGxcbiAgICApID0+IHZvaWRcbiAgKTogdm9pZCB7XG4gICAgdGhpcy5zdGF0c1dpdGhLZXkoXCJcIiwgY2FsbGJhY2spO1xuICB9XG5cbiAgLyoqXG4gICAqIFJFU0VUX1NUQVRTXG4gICAqXG4gICAqIFJlc2V0IHRoZSBzdGF0aXN0aWNzIGVhY2ggc2VydmVyIGlzIGtlZXBpbmcgYmFjayB0byB6ZXJvLiBUaGlzIGRvZXNuJ3QgY2xlYXJcbiAgICogc3RhdHMgc3VjaCBhcyBpdGVtIGNvdW50LCBidXQgdGVtcG9yYXJ5IHN0YXRzIHN1Y2ggYXMgdG90YWwgbnVtYmVyIG9mXG4gICAqIGNvbm5lY3Rpb25zIG92ZXIgdGltZS5cbiAgICpcbiAgICogVGhlIGNhbGxiYWNrIGlzIGludm9rZWQgKipPTkNFIFBFUiBTRVJWRVIqKiBhbmQgaGFzIHRoZSBzaWduYXR1cmU6XG4gICAqXG4gICAqICAgICBjYWxsYmFjayhlcnIsIHNlcnZlcilcbiAgICpcbiAgICogX3NlcnZlcl8gaXMgdGhlIGBcImhvc3RuYW1lOnBvcnRcImAgb2YgdGhlIHNlcnZlci5cbiAgICogQHBhcmFtIGNhbGxiYWNrXG4gICAqL1xuICByZXNldFN0YXRzKFxuICAgIGNhbGxiYWNrPzogKFxuICAgICAgZXJyOiBFcnJvciB8IG51bGwsXG4gICAgICBzZXJ2ZXI6IHN0cmluZyxcbiAgICAgIHN0YXRzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+IHwgbnVsbFxuICAgICkgPT4gdm9pZFxuICApOiB2b2lkIHtcbiAgICB0aGlzLnN0YXRzV2l0aEtleShcInJlc2V0XCIsIGNhbGxiYWNrKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBRVUlUXG4gICAqXG4gICAqIENsb3NlcyB0aGUgY29ubmVjdGlvbiB0byBlYWNoIHNlcnZlciwgbm90aWZ5aW5nIHRoZW0gb2YgdGhpcyBpbnRlbnRpb24uIE5vdGVcbiAgICogdGhhdCBxdWl0IGNhbiByYWNlIGFnYWluc3QgYWxyZWFkeSBvdXRzdGFuZGluZyByZXF1ZXN0cyB3aGVuIHRob3NlIHJlcXVlc3RzXG4gICAqIGZhaWwgYW5kIGFyZSByZXRyaWVkLCBsZWFkaW5nIHRvIHRoZSBxdWl0IGNvbW1hbmQgd2lubmluZyBhbmQgY2xvc2luZyB0aGVcbiAgICogY29ubmVjdGlvbiBiZWZvcmUgdGhlIHJldHJpZXMgY29tcGxldGUuXG4gICAqL1xuICBxdWl0KCkge1xuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIC8vIFRPRE86IE5pY2VyIHBlcmhhcHMgdG8gZG8gUVVJVFEgKDB4MTcpIGJ1dCBuZWVkIGEgbmV3IGNhbGxiYWNrIGZvciB3aGVuXG4gICAgLy8gd3JpdGUgaXMgZG9uZS5cbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoMHgwNywgXCJcIiwgXCJcIiwgXCJcIiwgdGhpcy5zZXEpOyAvLyBRVUlUXG4gICAgbGV0IHNlcnY7XG5cbiAgICBjb25zdCBoYW5kbGVRdWl0ID0gZnVuY3Rpb24gKHNlcTogbnVtYmVyLCBzZXJ2OiBTZXJ2ZXIpIHtcbiAgICAgIHNlcnYub25SZXNwb25zZShzZXEsIGZ1bmN0aW9uICgvKiByZXNwb25zZSAqLykge1xuICAgICAgICBzZXJ2LmNsb3NlKCk7XG4gICAgICB9KTtcbiAgICAgIHNlcnYub25FcnJvcihzZXEsIGZ1bmN0aW9uICgvKiBlcnIgKi8pIHtcbiAgICAgICAgc2Vydi5jbG9zZSgpO1xuICAgICAgfSk7XG4gICAgICBzZXJ2LndyaXRlKHJlcXVlc3QpO1xuICAgIH07XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuc2VydmVycy5sZW5ndGg7IGkrKykge1xuICAgICAgc2VydiA9IHRoaXMuc2VydmVyc1tpXTtcbiAgICAgIGhhbmRsZVF1aXQodGhpcy5zZXEsIHNlcnYpO1xuICAgIH1cbiAgfVxuXG4gIF92ZXJzaW9uKHNlcnZlcjogU2VydmVyKTogUHJvbWlzZTx7IHZhbHVlOiBWYWx1ZSB8IG51bGwgfT4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICB0aGlzLmluY3JTZXEoKTtcbiAgICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgICAgY29uc3RhbnRzLk9QX1ZFUlNJT04sXG4gICAgICAgIFwiXCIsXG4gICAgICAgIFwiXCIsXG4gICAgICAgIFwiXCIsXG4gICAgICAgIHRoaXMuc2VxXG4gICAgICApO1xuICAgICAgdGhpcy5wZXJmb3JtT25TZXJ2ZXIoc2VydmVyLCByZXF1ZXN0LCB0aGlzLnNlcSwgKGVyciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgIHJldHVybiByZWplY3QoZXJyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHN3aXRjaCAocmVzcG9uc2UhLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgICAgICAvKiBUT0RPOiB0aGlzIGlzIGJ1Z2dlZCwgd2Ugc2hvdWxkJ3QgdXNlIHRoZSBkZXNlcmlhbGl6ZXIgaGVyZSwgc2luY2UgdmVyc2lvbiBhbHdheXMgcmV0dXJucyBhIHZlcnNpb24gc3RyaW5nLlxuICAgICAgICAgICAgIFRoZSBkZXNlcmlhbGl6ZXIgc2hvdWxkIG9ubHkgYmUgdXNlZCBvbiB1c2VyIGtleSBkYXRhLiAqL1xuICAgICAgICAgICAgY29uc3QgZGVzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLmRlc2VyaWFsaXplKFxuICAgICAgICAgICAgICByZXNwb25zZSEuaGVhZGVyLm9wY29kZSxcbiAgICAgICAgICAgICAgcmVzcG9uc2UhLnZhbCxcbiAgICAgICAgICAgICAgcmVzcG9uc2UhLmV4dHJhc1xuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHJldHVybiByZXNvbHZlKHsgdmFsdWU6IGRlc2VyaWFsaXplZC52YWx1ZSB9KTtcbiAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgcmV0dXJuIHJlamVjdChcbiAgICAgICAgICAgICAgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIlZFUlNJT05cIiwgcmVzcG9uc2UhLmhlYWRlci5zdGF0dXMpXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXF1ZXN0IHRoZSBzZXJ2ZXIgdmVyc2lvbiBmcm9tIHRoZSBcImZpcnN0XCIgc2VydmVyIGluIHRoZSBiYWNrZW5kIHBvb2wuXG4gICAqIFRoZSBzZXJ2ZXIgcmVzcG9uZHMgd2l0aCBhIHBhY2tldCBjb250YWluaW5nIHRoZSB2ZXJzaW9uIHN0cmluZyBpbiB0aGUgYm9keSB3aXRoIHRoZSBmb2xsb3dpbmcgZm9ybWF0OiBcIngueS56XCJcbiAgICovXG4gIHZlcnNpb24oKTogUHJvbWlzZTx7IHZhbHVlOiBWYWx1ZSB8IG51bGwgfT4ge1xuICAgIGNvbnN0IHNlcnZlciA9IHRoaXMuc2VydmVyS2V5VG9TZXJ2ZXIodGhpcy5zZXJ2ZXJLZXlzWzBdKTtcbiAgICByZXR1cm4gdGhpcy5fdmVyc2lvbihzZXJ2ZXIpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHJpZXZlcyB0aGUgc2VydmVyIHZlcnNpb24gZnJvbSBhbGwgdGhlIHNlcnZlcnNcbiAgICogaW4gdGhlIGJhY2tlbmQgcG9vbCwgZXJyb3JzIGlmIGFueSBvbmUgb2YgdGhlbSBoYXMgYW5cbiAgICogZXJyb3JcbiAgICogXG4gICAqIENhbGxiYWNrcyBmdW5jdGlvbnMgYXJlIGNhbGxlZCBiZWZvcmUvYWZ0ZXIgd2UgcGluZyBtZW1jYWNoZWRcbiAgICogYW5kIHVzZWQgdG8gbG9nIHdoaWNoIGhvc3RzIGFyZSB0aW1pbmcgb3V0LlxuICAgKi9cbiAgYXN5bmMgdmVyc2lvbkFsbChjYWxsYmFja3M/OiB7XG4gICAgYmVmb3JlUGluZz86IChzZXJ2ZXJLZXk6IHN0cmluZykgPT4gdm9pZDtcbiAgICBhZnRlclBpbmc/OiAoc2VydmVyS2V5OiBzdHJpbmcpID0+IHZvaWQ7XG4gIH0pOiBQcm9taXNlPHtcbiAgICB2YWx1ZXM6IFJlY29yZDxzdHJpbmcsIFZhbHVlIHwgbnVsbD47XG4gIH0+IHtcbiAgICBjb25zdCB2ZXJzaW9uT2JqZWN0cyA9IGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgdGhpcy5zZXJ2ZXJLZXlzLm1hcCgoc2VydmVyS2V5KSA9PiB7XG4gICAgICAgIGNvbnN0IHNlcnZlciA9IHRoaXMuc2VydmVyS2V5VG9TZXJ2ZXIoc2VydmVyS2V5KTtcbiAgICAgICAgY2FsbGJhY2tzPy5iZWZvcmVQaW5nPy4oc2VydmVyS2V5KTtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3ZlcnNpb24oc2VydmVyKS50aGVuKChyZXNwb25zZSkgPT4ge1xuICAgICAgICAgIGNhbGxiYWNrcz8uYWZ0ZXJQaW5nPy4oc2VydmVyS2V5KTtcbiAgICAgICAgICByZXR1cm4geyBzZXJ2ZXJLZXk6IHNlcnZlcktleSwgdmFsdWU6IHJlc3BvbnNlLnZhbHVlIH07XG4gICAgICAgIH0pO1xuICAgICAgfSlcbiAgICApO1xuICAgIGNvbnN0IHZhbHVlcyA9IHZlcnNpb25PYmplY3RzLnJlZHVjZSgoYWNjdW11bGF0b3IsIHZlcnNpb25PYmplY3QpID0+IHtcbiAgICAgIGFjY3VtdWxhdG9yW3ZlcnNpb25PYmplY3Quc2VydmVyS2V5XSA9IHZlcnNpb25PYmplY3QudmFsdWU7XG4gICAgICByZXR1cm4gYWNjdW11bGF0b3I7XG4gICAgfSwge30gYXMgUmVjb3JkPHN0cmluZywgVmFsdWUgfCBudWxsPik7XG4gICAgcmV0dXJuIHsgdmFsdWVzOiB2YWx1ZXMgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDbG9zZXMgKGFicnVwdGx5KSBjb25uZWN0aW9ucyB0byBhbGwgdGhlIHNlcnZlcnMuXG4gICAqIEBzZWUgdGhpcy5xdWl0XG4gICAqL1xuICBjbG9zZSgpIHtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuc2VydmVycy5sZW5ndGg7IGkrKykge1xuICAgICAgdGhpcy5zZXJ2ZXJzW2ldLmNsb3NlKCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFBlcmZvcm0gYSBnZW5lcmljIHNpbmdsZSByZXNwb25zZSBvcGVyYXRpb24gKGdldCwgc2V0IGV0Yykgb24gb25lIHNlcnZlclxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IHRoZSBrZXkgdG8gaGFzaCB0byBnZXQgYSBzZXJ2ZXIgZnJvbSB0aGUgcG9vbFxuICAgKiBAcGFyYW0ge2J1ZmZlcn0gcmVxdWVzdCBhIGJ1ZmZlciBjb250YWluaW5nIHRoZSByZXF1ZXN0XG4gICAqIEBwYXJhbSB7bnVtYmVyfSBzZXEgdGhlIHNlcXVlbmNlIG51bWJlciBvZiB0aGUgb3BlcmF0aW9uLiBJdCBpcyB1c2VkIHRvIHBpbiB0aGUgY2FsbGJhY2tzXG4gICAgICAgICAgICAgICAgICAgICAgICAgdG8gYSBzcGVjaWZpYyBvcGVyYXRpb24gYW5kIHNob3VsZCBuZXZlciBjaGFuZ2UgZHVyaW5nIGEgYHBlcmZvcm1gLlxuICAgKiBAcGFyYW0ge251bWJlcj99IHJldHJpZXMgbnVtYmVyIG9mIHRpbWVzIHRvIHJldHJ5IHJlcXVlc3Qgb24gZmFpbHVyZVxuICAgKi9cbiAgcGVyZm9ybShcbiAgICBrZXk6IHN0cmluZyxcbiAgICByZXF1ZXN0OiBCdWZmZXIsXG4gICAgc2VxOiBudW1iZXIsXG4gICAgcmV0cmllcz86IG51bWJlclxuICApOiBQcm9taXNlPE1lc3NhZ2U+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgY29uc3Qgc2VydmVyS2V5ID0gdGhpcy5sb29rdXBLZXlUb1NlcnZlcktleShrZXkpO1xuICAgICAgY29uc3Qgc2VydmVyID0gdGhpcy5zZXJ2ZXJLZXlUb1NlcnZlcihzZXJ2ZXJLZXkpO1xuXG4gICAgICBpZiAoIXNlcnZlcikge1xuICAgICAgICByZXR1cm4gcmVqZWN0KG5ldyBFcnJvcihcIk5vIHNlcnZlcnMgYXZhaWxhYmxlXCIpKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5wZXJmb3JtT25TZXJ2ZXIoXG4gICAgICAgIHNlcnZlcixcbiAgICAgICAgcmVxdWVzdCxcbiAgICAgICAgc2VxLFxuICAgICAgICAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICByZXR1cm4gcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmVzb2x2ZShyZXNwb25zZSEpO1xuICAgICAgICB9LFxuICAgICAgICByZXRyaWVzXG4gICAgICApO1xuICAgIH0pO1xuICB9XG5cbiAgcGVyZm9ybU9uU2VydmVyKFxuICAgIHNlcnZlcjogU2VydmVyLFxuICAgIHJlcXVlc3Q6IEJ1ZmZlcixcbiAgICBzZXE6IG51bWJlcixcbiAgICBjYWxsYmFjazogUmVzcG9uc2VPckVycm9yQ2FsbGJhY2ssXG4gICAgcmV0cmllczogbnVtYmVyID0gMFxuICApIHtcbiAgICBjb25zdCBfdGhpcyA9IHRoaXM7XG5cbiAgICByZXRyaWVzID0gcmV0cmllcyB8fCB0aGlzLm9wdGlvbnMucmV0cmllcztcbiAgICBjb25zdCBvcmlnUmV0cmllcyA9IHRoaXMub3B0aW9ucy5yZXRyaWVzO1xuICAgIGNvbnN0IGxvZ2dlciA9IHRoaXMub3B0aW9ucy5sb2dnZXI7XG4gICAgY29uc3QgcmV0cnlfZGVsYXkgPSB0aGlzLm9wdGlvbnMucmV0cnlfZGVsYXk7XG5cbiAgICBjb25zdCByZXNwb25zZUhhbmRsZXI6IE9uUmVzcG9uc2VDYWxsYmFjayA9IGZ1bmN0aW9uIChyZXNwb25zZSkge1xuICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgIGNhbGxiYWNrKG51bGwsIHJlc3BvbnNlKTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgY29uc3QgZXJyb3JIYW5kbGVyOiBPbkVycm9yQ2FsbGJhY2sgPSBmdW5jdGlvbiAoZXJyb3IpIHtcbiAgICAgIGlmICgtLXJldHJpZXMgPiAwKSB7XG4gICAgICAgIC8vIFdhaXQgZm9yIHJldHJ5X2RlbGF5XG4gICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgIF90aGlzLnBlcmZvcm1PblNlcnZlcihzZXJ2ZXIsIHJlcXVlc3QsIHNlcSwgY2FsbGJhY2ssIHJldHJpZXMpO1xuICAgICAgICB9LCAxMDAwICogcmV0cnlfZGVsYXkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbG9nZ2VyLmxvZyhcbiAgICAgICAgICBcIk1lbUpTOiBTZXJ2ZXIgPFwiICtcbiAgICAgICAgICAgIHNlcnZlci5ob3N0cG9ydFN0cmluZygpICtcbiAgICAgICAgICAgIFwiPiBmYWlsZWQgYWZ0ZXIgKFwiICtcbiAgICAgICAgICAgIG9yaWdSZXRyaWVzICtcbiAgICAgICAgICAgIFwiKSByZXRyaWVzIHdpdGggZXJyb3IgLSBcIiArXG4gICAgICAgICAgICBlcnJvci5tZXNzYWdlXG4gICAgICAgICk7XG4gICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgIGNhbGxiYWNrKGVycm9yLCBudWxsKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH07XG5cbiAgICBzZXJ2ZXIub25SZXNwb25zZShzZXEsIHJlc3BvbnNlSGFuZGxlcik7XG4gICAgc2VydmVyLm9uRXJyb3Ioc2VxLCBlcnJvckhhbmRsZXIpO1xuICAgIHNlcnZlci53cml0ZShyZXF1ZXN0KTtcbiAgfVxuXG4gIC8vIEluY3JlbWVudCB0aGUgc2VxIHZhbHVlXG4gIGluY3JTZXEoKSB7XG4gICAgdGhpcy5zZXErKztcblxuICAgIC8vIFdyYXAgYHRoaXMuc2VxYCB0byAzMi1iaXRzIHNpbmNlIHRoZSBmaWVsZCB3ZSBmaXQgaXQgaW50byBpcyBvbmx5IDMyLWJpdHMuXG4gICAgdGhpcy5zZXEgJj0gMHhmZmZmZmZmZjtcblxuICAgIHJldHVybiB0aGlzLnNlcTtcbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlQW5kTG9nRXJyb3IoXG4gICAgY29tbWFuZE5hbWU6IHN0cmluZyxcbiAgICByZXNwb25zZVN0YXR1czogUmVzcG9uc2VTdGF0dXMgfCB1bmRlZmluZWRcbiAgKTogRXJyb3Ige1xuICAgIGNvbnN0IGVycm9yTWVzc2FnZSA9IGBNZW1KUyAke2NvbW1hbmROYW1lfTogJHtjb25zdGFudHMucmVzcG9uc2VTdGF0dXNUb1N0cmluZyhcbiAgICAgIHJlc3BvbnNlU3RhdHVzXG4gICAgKX1gO1xuICAgIHRoaXMub3B0aW9ucy5sb2dnZXIubG9nKGVycm9yTWVzc2FnZSk7XG4gICAgcmV0dXJuIG5ldyBFcnJvcihlcnJvck1lc3NhZ2UpO1xuICB9XG5cbiAgLyoqXG4gICAqIExvZyBhbiBlcnJvciB0byB0aGUgbG9nZ2VyLCB0aGVuIHJldHVybiB0aGUgZXJyb3IuXG4gICAqIElmIGEgY2FsbGJhY2sgaXMgZ2l2ZW4sIGNhbGwgaXQgd2l0aCBjYWxsYmFjayhlcnJvciwgbnVsbCkuXG4gICAqL1xuICBwcml2YXRlIGhhbmRsZVJlc3BvbnNlRXJyb3IoXG4gICAgY29tbWFuZE5hbWU6IHN0cmluZyxcbiAgICByZXNwb25zZVN0YXR1czogUmVzcG9uc2VTdGF0dXMgfCB1bmRlZmluZWQsXG4gICAgY2FsbGJhY2s6IHVuZGVmaW5lZCB8ICgoZXJyb3I6IEVycm9yIHwgbnVsbCwgb3RoZXI6IG51bGwpID0+IHZvaWQpXG4gICk6IEVycm9yIHtcbiAgICBjb25zdCBlcnJvciA9IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoY29tbWFuZE5hbWUsIHJlc3BvbnNlU3RhdHVzKTtcbiAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgIGNhbGxiYWNrKGVycm9yLCBudWxsKTtcbiAgICB9XG4gICAgcmV0dXJuIGVycm9yO1xuICB9XG59XG5cbmV4cG9ydCB7IENsaWVudCwgU2VydmVyLCBVdGlscywgSGVhZGVyIH07XG4iXX0= \ No newline at end of file diff --git a/src/memjs/memjs.ts b/src/memjs/memjs.ts index a14915a..66bbeaa 100644 --- a/src/memjs/memjs.ts +++ b/src/memjs/memjs.ts @@ -97,6 +97,21 @@ export type GetMultiResult< [K in Keys]?: GetResult; }; +export interface GetMultiError { + error: Error; + serverKey: string; + keys: Keys[]; +} + +export interface GetMultiWithErrorsResult< +Keys extends string = string, +Value = MaybeBuffer, +Extras = MaybeBuffer +> { + result: GetMultiResult; + errors: GetMultiError[]; +} + class Client { servers: Server[]; seq: number; @@ -384,6 +399,48 @@ class Client { return Object.assign({}, ...results); } + async getMultiWithErrors( + keys: Keys[] + ): Promise> { + const serverKeytoLookupKeys: { + [serverKey: string]: Keys[]; + } = {}; + keys.forEach((lookupKey) => { + const serverKey = this.lookupKeyToServerKey(lookupKey); + if (!serverKeytoLookupKeys[serverKey]) { + serverKeytoLookupKeys[serverKey] = []; + } + serverKeytoLookupKeys[serverKey].push(lookupKey); + }); + + const usedServerKeys = Object.keys(serverKeytoLookupKeys); + const errors: GetMultiError[] = []; + const results = await Promise.all( + usedServerKeys.map(async (serverKey) => { + const server = this.serverKeyToServer(serverKey); + try { + return await this._getMultiToServer(server, serverKeytoLookupKeys[serverKey]); + } catch (err) { + let error: Error; + if (err instanceof Error) { + error = err; + } else { + error = new Error("Unknown Error"); + (error as any).thrown = err; + } + + errors.push({ + error, + serverKey, + keys: serverKeytoLookupKeys[serverKey] + }); + } + }) + ); + + return { result: Object.assign({}, ...results), errors }; + } + /** * Sets `key` to `value`. */ From c334faac82538a7e43dbb0ff1288bb16bcef029a Mon Sep 17 00:00:00 2001 From: Ben Hughes Date: Fri, 29 Sep 2023 15:07:29 -0400 Subject: [PATCH 70/79] Test getMultiWithErrors --- lib/memjs/memjs.d.ts.map | 2 +- lib/memjs/memjs.js | 14 +- src/memjs/memjs.ts | 12 +- src/test/client_test.ts | 314 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 320 insertions(+), 22 deletions(-) diff --git a/lib/memjs/memjs.d.ts.map b/lib/memjs/memjs.d.ts.map index 11015ca..699e889 100644 --- a/lib/memjs/memjs.d.ts.map +++ b/lib/memjs/memjs.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"memjs.d.ts","sourceRoot":"","sources":["../../src/memjs/memjs.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"memjs.d.ts","sourceRoot":"","sources":["../../src/memjs/memjs.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/lib/memjs/memjs.js b/lib/memjs/memjs.js index e95376c..bc8c588 100644 --- a/lib/memjs/memjs.js +++ b/lib/memjs/memjs.js @@ -264,17 +264,9 @@ class Client { try { return await this._getMultiToServer(server, serverKeytoLookupKeys[serverKey]); } - catch (err) { - let error; - if (err instanceof Error) { - error = err; - } - else { - error = new Error("Unknown Error"); - error.thrown = err; - } + catch (error) { errors.push({ - error, + error: error, serverKey, keys: serverKeytoLookupKeys[serverKey] }); @@ -776,4 +768,4 @@ class Client { } } exports.Client = Client; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVtanMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbWVtanMvbWVtanMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLHdCQUF3Qjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUV4QixxQ0FLa0I7QUFvbUNELHVGQXRtQ2YsZUFBTSxPQXNtQ2U7QUFubUN2Qix1REFBK0Q7QUFDL0QsbUNBU2lCO0FBQ2pCLHVEQUF5QztBQUN6QywyQ0FBNkM7QUFDN0MsK0NBQWlDO0FBc2xDUixzQkFBSztBQXJsQzlCLGlEQUFtQztBQXFsQ0gsd0JBQU07QUFubEN0QyxTQUFTLDhCQUE4QixDQUNyQyxPQUFpQixFQUNqQixHQUFXO0lBRVgsTUFBTSxLQUFLLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQztJQUM3QixNQUFNLEtBQUssR0FBRyxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxnQkFBUSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3BELE9BQU8sT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ3hCLENBQUM7QUFFRCwrQ0FBK0M7QUFDL0MsU0FBUyxTQUFTLENBQ2hCLE9BQTBFO0lBRTFFLE9BQU8sSUFBSSxPQUFPLENBQUMsVUFBVSxPQUFPLEVBQUUsTUFBTTtRQUMxQyxPQUFPLENBQUMsVUFBVSxHQUFHLEVBQUUsTUFBTTtZQUMzQixHQUFHLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3RDLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBd0VELE1BQU0sTUFBTTtJQVFWLDRFQUE0RTtJQUM1RSxtQ0FBbUM7SUFDbkMsWUFBWSxPQUFpQixFQUFFLE9BQTBDO1FBQ3ZFLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO1FBQ3ZCLElB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Q2xDLE1BQU0sQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDeEIsQ0FBQztJQUVELDBCQUEwQjtJQUMxQixPQUFPO1FBQ0wsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO1FBRVgsNkVBQTZFO1FBQzdFLElBQUksQ0FBQyxHQUFHLElBQUksVUFBVSxDQUFDO1FBRXZCLE9BQU8sSUFBSSxDQUFDLEdBQUcsQ0FBQztJQUNsQixDQUFDO0lBRU8saUJBQWlCLENBQ3ZCLFdBQW1CLEVBQ25CLGNBQTBDO1FBRTFDLE1BQU0sWUFBWSxHQUFHLFNBQVMsV0FBVyxLQUFLLFNBQVMsQ0FBQyxzQkFBc0IsQ0FDNUUsY0FBYyxDQUNmLEVBQUUsQ0FBQztRQUNKLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUN0QyxPQUFPLElBQUksS0FBSyxDQUFDLFlBQVksQ0FBQyxDQUFDO0lBQ2pDLENBQUM7SUFFRDs7O09BR0c7SUFDSyxtQkFBbUIsQ0FDekIsV0FBbUIsRUFDbkIsY0FBMEMsRUFDMUMsUUFBa0U7UUFFbEUsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixDQUFDLFdBQVcsRUFBRSxjQUFjLENBQUMsQ0FBQztRQUNsRSxJQUFJLFFBQVEsRUFBRTtZQUNaLFFBQVEsQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLENBQUM7U0FDdkI7UUFDRCxPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7Q0FDRjtBQUVRLHdCQUFNIiwic291cmNlc0NvbnRlbnQiOlsiLy8gTWVtVFMgTWVtY2FjaGUgQ2xpZW50XG5cbmltcG9ydCB7XG4gIE9uRXJyb3JDYWxsYmFjayxcbiAgT25SZXNwb25zZUNhbGxiYWNrLFxuICBTZXJ2ZXIsXG4gIFNlcnZlck9wdGlvbnMsXG59IGZyb20gXCIuL3NlcnZlclwiO1xuaW1wb3J0IHsgbm9vcFNlcmlhbGl6ZXIsIFNlcmlhbGl6ZXIgfSBmcm9tIFwiLi9ub29wLXNlcmlhbGl6ZXJcIjtcbmltcG9ydCB7XG4gIG1ha2VSZXF1ZXN0QnVmZmVyLFxuICBjb3B5SW50b1JlcXVlc3RCdWZmZXIsXG4gIG1lcmdlLFxuICBtYWtlRXhwaXJhdGlvbixcbiAgbWFrZUFtb3VudEluaXRpYWxBbmRFeHBpcmF0aW9uLFxuICBoYXNoQ29kZSxcbiAgTWF5YmVCdWZmZXIsXG4gIE1lc3NhZ2UsXG59IGZyb20gXCIuL3V0aWxzXCI7XG5pbXBvcnQgKiBhcyBjb25zdGFudHMgZnJvbSBcIi4vY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBSZXNwb25zZVN0YXR1cyB9IGZyb20gXCIuL2NvbnN0YW50c1wiO1xuaW1wb3J0ICogYXMgVXRpbHMgZnJvbSBcIi4vdXRpbHNcIjtcbmltcG9ydCAqIGFzIEhlYWRlciBmcm9tIFwiLi9oZWFkZXJcIjtcblxuZnVuY3Rpb24gZGVmYXVsdEtleVRvU2VydmVySGFzaEZ1bmN0aW9uKFxuICBzZXJ2ZXJzOiBzdHJpbmdbXSxcbiAga2V5OiBzdHJpbmdcbik6IHN0cmluZyB7XG4gIGNvbnN0IHRvdGFsID0gc2VydmVycy5sZW5ndGg7XG4gIGNvbnN0IGluZGV4ID0gdG90YWwgPiAxID8gaGFzaENvZGUoa2V5KSAlIHRvdGFsIDogMDtcbiAgcmV0dXJuIHNlcnZlcnNbaW5kZXhdO1xufVxuXG4vLyBjb252ZXJ0cyBhIGNhbGwgaW50byBhIHByb21pc2UtcmV0dXJuaW5nIG9uZVxuZnVuY3Rpb24gcHJvbWlzaWZ5PFJlc3VsdD4oXG4gIGNvbW1hbmQ6IChjYWxsYmFjazogKGVycm9yOiBFcnJvciB8IG51bGwsIHJlc3VsdDogUmVzdWx0KSA9PiB2b2lkKSA9PiB2b2lkXG4pOiBQcm9taXNlPFJlc3VsdD4ge1xuICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuICAgIGNvbW1hbmQoZnVuY3Rpb24gKGVyciwgcmVzdWx0KSB7XG4gICAgICBlcnIgPyByZWplY3QoZXJyKSA6IHJlc29sdmUocmVzdWx0KTtcbiAgICB9KTtcbiAgfSk7XG59XG5cbnR5cGUgUmVzcG9uc2VPckVycm9yQ2FsbGJhY2sgPSAoXG4gIGVycm9yOiBFcnJvciB8IG51bGwsXG4gIHJlc3BvbnNlOiBNZXNzYWdlIHwgbnVsbFxuKSA9PiB2b2lkO1xuXG5pbnRlcmZhY2UgQmFzZUNsaWVudE9wdGlvbnMge1xuICByZXRyaWVzOiBudW1iZXI7XG4gIHJldHJ5X2RlbGF5OiBudW1iZXI7XG4gIGV4cGlyZXM6IG51bWJlcjtcbiAgbG9nZ2VyOiB7IGxvZzogdHlwZW9mIGNvbnNvbGUubG9nIH07XG4gIGtleVRvU2VydmVySGFzaEZ1bmN0aW9uOiB0eXBlb2YgZGVmYXVsdEtleVRvU2VydmVySGFzaEZ1bmN0aW9uO1xufVxuXG5pbnRlcmZhY2UgU2VyaWFsaXplclByb3A8VmFsdWUsIEV4dHJhcz4ge1xuICBzZXJpYWxpemVyOiBTZXJpYWxpemVyPFZhbHVlLCBFeHRyYXM+O1xufVxuXG4vKipcbiAqIFRoZSBjbGllbnQgaGFzIHBhcnRpYWwgc3VwcG9ydCBmb3Igc2VyaWFsaXppbmcgYW5kIGRlc2VyaWFsaXppbmcgdmFsdWVzIGZyb20gdGhlXG4gKiBCdWZmZXIgYnl0ZSBzdHJpbmdzIHdlIHJlY2VpdmUgZnJvbSB0aGUgd2lyZS4gVGhlIGRlZmF1bHQgc2VyaWFsaXplciBpcyBmb3IgTWF5YmVCdWZmZXIuXG4gKlxuICogSWYgVmFsdWUgYW5kIEV4dHJhcyBhcmUgb2YgdHlwZSBCdWZmZXIsIHRoZW4gcmV0dXJuIHR5cGUgV2hlbkJ1ZmZlci4gT3RoZXJ3aXNlLFxuICogcmV0dXJuIHR5cGUgTm90QnVmZmVyLlxuICovXG50eXBlIElmQnVmZmVyPFZhbHVlLCBFeHRyYXMsIFdoZW5WYWx1ZUFuZEV4dHJhc0FyZUJ1ZmZlcnMsIE5vdEJ1ZmZlcj4gPVxuICBWYWx1ZSBleHRlbmRzIEJ1ZmZlclxuICAgID8gRXh0cmFzIGV4dGVuZHMgQnVmZmVyXG4gICAgICA/IFdoZW5WYWx1ZUFuZEV4dHJhc0FyZUJ1ZmZlcnNcbiAgICAgIDogTm90QnVmZmVyXG4gICAgOiBOb3RCdWZmZXI7XG5cbmV4cG9ydCB0eXBlIEdpdmVuQ2xpZW50T3B0aW9uczxWYWx1ZSwgRXh0cmFzPiA9IFBhcnRpYWw8QmFzZUNsaWVudE9wdGlvbnM+ICZcbiAgSWZCdWZmZXI8XG4gICAgVmFsdWUsXG4gICAgRXh0cmFzLFxuICAgIFBhcnRpYWw8U2VyaWFsaXplclByb3A8VmFsdWUsIEV4dHJhcz4+LFxuICAgIFNlcmlhbGl6ZXJQcm9wPFZhbHVlLCBFeHRyYXM+XG4gID47XG5cbmV4cG9ydCB0eXBlIENBU1Rva2VuID0gQnVmZmVyO1xuXG5leHBvcnQgaW50ZXJmYWNlIEdldFJlc3VsdDxWYWx1ZSA9IE1heWJlQnVmZmVyLCBFeHRyYXMgPSBNYXliZUJ1ZmZlcj4ge1xuICB2YWx1ZTogVmFsdWU7XG4gIGV4dHJhczogRXh0cmFzO1xuICBjYXM6IENBU1Rva2VuIHwgdW5kZWZpbmVkO1xufVxuXG5leHBvcnQgdHlwZSBHZXRNdWx0aVJlc3VsdDxcbiAgS2V5cyBleHRlbmRzIHN0cmluZyA9IHN0cmluZyxcbiAgVmFsdWUgPSBNYXliZUJ1ZmZlcixcbiAgRXh0cmFzID0gTWF5YmVCdWZmZXJcbj4gPSB7XG4gIFtLIGluIEtleXNdPzogR2V0UmVzdWx0PFZhbHVlLCBFeHRyYXM+O1xufTtcblxuZXhwb3J0IGludGVyZmFjZSBHZXRNdWx0aUVycm9yPEtleXMgZXh0ZW5kcyBzdHJpbmcgPSBzdHJpbmc+IHtcbiAgZXJyb3I6IEVycm9yO1xuICBzZXJ2ZXJLZXk6IHN0cmluZztcbiAga2V5czogS2V5c1tdO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEdldE11bHRpV2l0aEVycm9yc1Jlc3VsdDxcbktleXMgZXh0ZW5kcyBzdHJpbmcgPSBzdHJpbmcsXG5WYWx1ZSA9IE1heWJlQnVmZmVyLFxuRXh0cmFzID0gTWF5YmVCdWZmZXJcbj4ge1xuICByZXN1bHQ6IEdldE11bHRpUmVzdWx0PEtleXMsIFZhbHVlLCBFeHRyYXM+O1xuICBlcnJvcnM6IEdldE11bHRpRXJyb3I8S2V5cz5bXTtcbn1cblxuY2xhc3MgQ2xpZW50PFZhbHVlID0gTWF5YmVCdWZmZXIsIEV4dHJhcyA9IE1heWJlQnVmZmVyPiB7XG4gIHNlcnZlcnM6IFNlcnZlcltdO1xuICBzZXE6IG51bWJlcjtcbiAgb3B0aW9uczogQmFzZUNsaWVudE9wdGlvbnMgJiBQYXJ0aWFsPFNlcmlhbGl6ZXJQcm9wPFZhbHVlLCBFeHRyYXM+PjtcbiAgc2VyaWFsaXplcjogU2VyaWFsaXplcjxWYWx1ZSwgRXh0cmFzPjtcbiAgc2VydmVyTWFwOiB7IFtob3N0cG9ydDogc3RyaW5nXTogU2VydmVyIH07XG4gIHNlcnZlcktleXM6IHN0cmluZ1tdO1xuXG4gIC8vIENsaWVudCBpbml0aWFsaXplciB0YWtlcyBhIGxpc3Qgb2YgYFNlcnZlcmBzIGFuZCBhbiBgb3B0aW9uc2AgZGljdGlvbmFyeS5cbiAgLy8gU2VlIGBDbGllbnQuY3JlYXRlYCBmb3IgZGV0YWlscy5cbiAgY29uc3RydWN0b3Ioc2VydmVyczogU2VydmVyW10sIG9wdGlvbnM6IEdpdmVuQ2xpZW50T3B0aW9uczxWYWx1ZSwgRXh0cmFzPikge1xuICAgIHRoaXMuc2VydmVycyA9IHNlcnZlcnM7XG4gICAgdGhpcy5zZXEgPSAwO1xuICAgIHRoaXMub3B0aW9ucyA9IG1lcmdlKG9wdGlvbnMgfHwge30sIHtcbiAgICAgIHJldHJpZXM6IDIsXG4gICAgICByZXRyeV9kZWxheTogMC4yLFxuICAgICAgZXhwaXJlczogMCxcbiAgICAgIGxvZ2dlcjogY29uc29sZSxcbiAgICAgIGtleVRvU2VydmVySGFzaEZ1bmN0aW9uOiBkZWZhdWx0S2V5VG9TZXJ2ZXJIYXNoRnVuY3Rpb24sXG4gICAgfSk7XG5cbiAgICB0aGlzLnNlcmlhbGl6ZXIgPSB0aGlzLm9wdGlvbnMuc2VyaWFsaXplciB8fCAobm9vcFNlcmlhbGl6ZXIgYXMgYW55KTtcblxuICAgIC8vIFN0b3JlIGEgbWFwcGluZyBmcm9tIGhvc3Rwb3J0IC0+IHNlcnZlciBzbyB3ZSBjYW4gcXVpY2tseSBnZXQgYSBzZXJ2ZXIgb2JqZWN0IGZyb20gdGhlIHNlcnZlcktleSByZXR1cm5lZCBieSB0aGUgaGFzaGluZyBmdW5jdGlvblxuICAgIGNvbnN0IHNlcnZlck1hcDogeyBbaG9zdHBvcnQ6IHN0cmluZ106IFNlcnZlciB9ID0ge307XG4gICAgdGhpcy5zZXJ2ZXJzLmZvckVhY2goZnVuY3Rpb24gKHNlcnZlcikge1xuICAgICAgc2VydmVyTWFwW3NlcnZlci5ob3N0cG9ydFN0cmluZygpXSA9IHNlcnZlcjtcbiAgICB9KTtcbiAgICB0aGlzLnNlcnZlck1hcCA9IHNlcnZlck1hcDtcblxuICAgIC8vIHN0b3JlIGEgbGlzdCBvZiBhbGwgb3VyIHNlcnZlcktleXMgc28gd2UgZG9uJ3QgbmVlZCB0byBjb25zdGFudGx5IHJlYWxsb2NhdGUgdGhpcyBhcnJheVxuICAgIHRoaXMuc2VydmVyS2V5cyA9IE9iamVjdC5rZXlzKHRoaXMuc2VydmVyTWFwKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgbmV3IGNsaWVudCBnaXZlbiBhbiBvcHRpb25hbCBjb25maWcgc3RyaW5nIGFuZCBvcHRpb25hbCBoYXNoIG9mXG4gICAqIG9wdGlvbnMuIFRoZSBjb25maWcgc3RyaW5nIHNob3VsZCBiZSBvZiB0aGUgZm9ybTpcbiAgICpcbiAgICogICAgIFwiW3VzZXI6cGFzc0Bdc2VydmVyMVs6MTEyMTFdLFt1c2VyOnBhc3NAXXNlcnZlcjJbOjExMjExXSwuLi5cIlxuICAgKlxuICAgKiBJZiB0aGUgYXJndW1lbnQgaXMgbm90IGdpdmVuLCBmYWxsYmFjayBvbiB0aGUgYE1FTUNBQ0hJRVJfU0VSVkVSU2AgZW52aXJvbm1lbnRcbiAgICogdmFyaWFibGUsIGBNRU1DQUNIRV9TRVJWRVJTYCBlbnZpcm9ubWVudCB2YXJpYWJsZSBvciBgXCJsb2NhbGhvc3Q6MTEyMTFcImAuXG4gICAqXG4gICAqIFRoZSBvcHRpb25zIGhhc2ggbWF5IGNvbnRhaW4gdGhlIG9wdGlvbnM6XG4gICAqXG4gICAqICogYHJldHJpZXNgIC0gdGhlIG51bWJlciBvZiB0aW1lcyB0byByZXRyeSBhbiBvcGVyYXRpb24gaW4gbGlldSBvZiBmYWlsdXJlc1xuICAgKiAoZGVmYXVsdCAyKVxuICAgKiAqIGBleHBpcmVzYCAtIHRoZSBkZWZhdWx0IGV4cGlyYXRpb24gaW4gc2Vjb25kcyB0byB1c2UgKGRlZmF1bHQgMCAtIG5ldmVyXG4gICAqIGV4cGlyZSkuIElmIGBleHBpcmVzYCBpcyBncmVhdGVyIHRoYW4gMzAgZGF5cyAoNjAgeCA2MCB4IDI0IHggMzApLCBpdCBpc1xuICAgKiB0cmVhdGVkIGFzIGEgVU5JWCB0aW1lIChudW1iZXIgb2Ygc2Vjb25kcyBzaW5jZSBKYW51YXJ5IDEsIDE5NzApLlxuICAgKiAqIGBsb2dnZXJgIC0gYSBsb2dnZXIgb2JqZWN0IHRoYXQgcmVzcG9uZHMgdG8gYGxvZyhzdHJpbmcpYCBtZXRob2QgY2FsbHMuXG4gICAqXG4gICAqICAgfn5+flxuICAgKiAgICAgbG9nKG1zZzFbLCBtc2cyWywgbXNnM1suLi5dXV0pXG4gICAqICAgfn5+flxuICAgKlxuICAgKiAgIERlZmF1bHRzIHRvIGBjb25zb2xlYC5cbiAgICogKiBgc2VyaWFsaXplcmAgLSB0aGUgb2JqZWN0IHdoaWNoIHdpbGwgKGRlKXNlcmlhbGl6ZSB0aGUgZGF0YS4gSXQgbmVlZHNcbiAgICogICB0d28gcHVibGljIG1ldGhvZHM6IHNlcmlhbGl6ZSBhbmQgZGVzZXJpYWxpemUuIEl0IGRlZmF1bHRzIHRvIHRoZVxuICAgKiAgIG5vb3BTZXJpYWxpemVyOlxuICAgKlxuICAgKiAgIH5+fn5cbiAgICogICBjb25zdCBub29wU2VyaWFsaXplciA9IHtcbiAgICogICAgIHNlcmlhbGl6ZTogZnVuY3Rpb24gKG9wY29kZSwgdmFsdWUsIGV4dHJhcykge1xuICAgKiAgICAgICByZXR1cm4geyB2YWx1ZTogdmFsdWUsIGV4dHJhczogZXh0cmFzIH07XG4gICAqICAgICB9LFxuICAgKiAgICAgZGVzZXJpYWxpemU6IGZ1bmN0aW9uIChvcGNvZGUsIHZhbHVlLCBleHRyYXMpIHtcbiAgICogICAgICAgcmV0dXJuIHsgdmFsdWU6IHZhbHVlLCBleHRyYXM6IGV4dHJhcyB9O1xuICAgKiAgICAgfVxuICAgKiAgIH07XG4gICAqICAgfn5+flxuICAgKlxuICAgKiBPciBvcHRpb25zIGZvciB0aGUgc2VydmVycyBpbmNsdWRpbmc6XG4gICAqICogYHVzZXJuYW1lYCBhbmQgYHBhc3N3b3JkYCBmb3IgZmFsbGJhY2sgU0FTTCBhdXRoZW50aWNhdGlvbiBjcmVkZW50aWFscy5cbiAgICogKiBgdGltZW91dGAgaW4gc2Vjb25kcyB0byBkZXRlcm1pbmUgZmFpbHVyZSBmb3Igb3BlcmF0aW9ucy4gRGVmYXVsdCBpcyAwLjVcbiAgICogICAgICAgICAgICAgc2Vjb25kcy5cbiAgICogKiAnY29ubnRpbWVvdXQnIGluIHNlY29uZHMgdG8gY29ubmVjdGlvbiBmYWlsdXJlLiBEZWZhdWx0IGlzIHR3aWNlIHRoZSB2YWx1ZVxuICAgKiAgICAgICAgICAgICAgICAgb2YgYHRpbWVvdXRgLlxuICAgKiAqIGBrZWVwQWxpdmVgIHdoZXRoZXIgdG8gZW5hYmxlIGtlZXAtYWxpdmUgZnVuY3Rpb25hbGl0eS4gRGVmYXVsdHMgdG8gZmFsc2UuXG4gICAqICogYGtlZXBBbGl2ZURlbGF5YCBpbiBzZWNvbmRzIHRvIHRoZSBpbml0aWFsIGRlbGF5IGJlZm9yZSB0aGUgZmlyc3Qga2VlcGFsaXZlXG4gICAqICAgICAgICAgICAgICAgICAgICBwcm9iZSBpcyBzZW50IG9uIGFuIGlkbGUgc29ja2V0LiBEZWZhdWx0cyBpcyAzMCBzZWNvbmRzLlxuICAgKiAqIGBrZXlUb1NlcnZlckhhc2hGdW5jdGlvbmAgYSBmdW5jdGlvbiB0byBtYXAga2V5cyB0byBzZXJ2ZXJzLCB3aXRoIHRoZSBzaWduYXR1cmVcbiAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgKHNlcnZlcktleXM6IHN0cmluZ1tdLCBrZXk6IHN0cmluZyk6IHN0cmluZ1xuICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICBOT1RFOiBpZiB5b3UgbmVlZCB0byBkbyBzb21lIGV4cGVuc2l2ZSBpbml0aWFsaXphdGlvbiwgKnBsZWFzZSogZG8gaXQgbGF6aWx5IHRoZSBmaXJzdCB0aW1lIHlvdSB0aGlzIGZ1bmN0aW9uIGlzIGNhbGxlZCB3aXRoIGFuIGFycmF5IG9mIHNlcnZlcktleXMsIG5vdCBvbiBldmVyeSBjYWxsXG4gICAqL1xuICBzdGF0aWMgY3JlYXRlPFZhbHVlLCBFeHRyYXM+KFxuICAgIHNlcnZlcnNTdHI6IHN0cmluZyB8IHVuZGVmaW5lZCxcbiAgICBvcHRpb25zOiBJZkJ1ZmZlcjxcbiAgICAgIFZhbHVlLFxuICAgICAgRXh0cmFzLFxuICAgICAgdW5kZWZpbmVkIHwgKFBhcnRpYWw8U2VydmVyT3B0aW9ucz4gJiBHaXZlbkNsaWVudE9wdGlvbnM8VmFsdWUsIEV4dHJhcz4pLFxuICAgICAgUGFydGlhbDxTZXJ2ZXJPcHRpb25zPiAmIEdpdmVuQ2xpZW50T3B0aW9uczxWYWx1ZSwgRXh0cmFzPlxuICAgID5cbiAgKTogQ2xpZW50PFZhbHVlLCBFeHRyYXM+IHtcbiAgICBzZXJ2ZXJzU3RyID1cbiAgICAgIHNlcnZlcnNTdHIgfHxcbiAgICAgIHByb2Nlc3MuZW52Lk1FTUNBQ0hJRVJfU0VSVkVSUyB8fFxuICAgICAgcHJvY2Vzcy5lbnYuTUVNQ0FDSEVfU0VSVkVSUyB8fFxuICAgICAgXCJsb2NhbGhvc3Q6MTEyMTFcIjtcbiAgICBjb25zdCBzZXJ2ZXJVcmlzID0gc2VydmVyc1N0ci5zcGxpdChcIixcIik7XG4gICAgY29uc3Qgc2VydmVycyA9IHNlcnZlclVyaXMubWFwKGZ1bmN0aW9uICh1cmkpIHtcbiAgICAgIGNvbnN0IHVyaVBhcnRzID0gdXJpLnNwbGl0KFwiQFwiKTtcbiAgICAgIGNvbnN0IGhvc3RQb3J0ID0gdXJpUGFydHNbdXJpUGFydHMubGVuZ3RoIC0gMV0uc3BsaXQoXCI6XCIpO1xuICAgICAgY29uc3QgdXNlclBhc3MgPSAodXJpUGFydHNbdXJpUGFydHMubGVuZ3RoIC0gMl0gfHwgXCJcIikuc3BsaXQoXCI6XCIpO1xuICAgICAgcmV0dXJuIG5ldyBTZXJ2ZXIoXG4gICAgICAgIGhvc3RQb3J0WzBdLFxuICAgICAgICBwYXJzZUludChob3N0UG9ydFsxXSB8fCBcIjExMjExXCIsIDEwKSxcbiAgICAgICAgdXNlclBhc3NbMF0sXG4gICAgICAgIHVzZXJQYXNzWzFdLFxuICAgICAgICBvcHRpb25zXG4gICAgICApO1xuICAgIH0pO1xuICAgIHJldHVybiBuZXcgQ2xpZW50KHNlcnZlcnMsIG9wdGlvbnMgYXMgYW55KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHaXZlbiBhIHNlcnZlcktleSBmcm9tbG9va3VwS2V5VG9TZXJ2ZXJLZXksIHJldHVybiB0aGUgY29ycmVzcG9uZGluZyBTZXJ2ZXIgaW5zdGFuY2VcbiAgICpcbiAgICogQHBhcmFtICB7c3RyaW5nfSBzZXJ2ZXJLZXlcbiAgICogQHJldHVybnMge1NlcnZlcn1cbiAgICovXG4gIHNlcnZlcktleVRvU2VydmVyKHNlcnZlcktleTogc3RyaW5nKTogU2VydmVyIHtcbiAgICByZXR1cm4gdGhpcy5zZXJ2ZXJNYXBbc2VydmVyS2V5XTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHaXZlbiBhIGtleSB0byBsb29rIHVwIGluIG1lbWNhY2hlLCByZXR1cm4gYSBzZXJ2ZXJLZXkgKGJhc2VkIG9uIHNvbWVcbiAgICogaGFzaGluZyBmdW5jdGlvbikgd2hpY2ggY2FuIGJlIHVzZWQgdG8gaW5kZXggdGhpcy5zZXJ2ZXJNYXBcbiAgICovXG4gIGxvb2t1cEtleVRvU2VydmVyS2V5KGtleTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5vcHRpb25zLmtleVRvU2VydmVySGFzaEZ1bmN0aW9uKHRoaXMuc2VydmVyS2V5cywga2V5KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXRyaWV2ZXMgdGhlIHZhbHVlIGF0IHRoZSBnaXZlbiBrZXkgaW4gbWVtY2FjaGUuXG4gICAqL1xuICBhc3luYyBnZXQoa2V5OiBzdHJpbmcpOiBQcm9taXNlPEdldFJlc3VsdDxWYWx1ZSwgRXh0cmFzPiB8IG51bGw+IHtcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoY29uc3RhbnRzLk9QX0dFVCwga2V5LCBcIlwiLCBcIlwiLCB0aGlzLnNlcSk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIGNvbnN0IGRlc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5kZXNlcmlhbGl6ZShcbiAgICAgICAgICByZXNwb25zZS5oZWFkZXIub3Bjb2RlLFxuICAgICAgICAgIHJlc3BvbnNlLnZhbCxcbiAgICAgICAgICByZXNwb25zZS5leHRyYXNcbiAgICAgICAgKTtcbiAgICAgICAgcmV0dXJuIHsgLi4uZGVzZXJpYWxpemVkLCBjYXM6IHJlc3BvbnNlLmhlYWRlci5jYXMgfTtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuS0VZX05PVF9GT1VORDpcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiR0VUXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBCdWlsZCBhIHBpcGVsaW5lZCBnZXQgbXVsdGkgcmVxdWVzdCBieSBzZW5kaW5nIG9uZSBHRVRLUSBmb3IgZWFjaCBrZXkgKHF1aWV0LCBtZWFuaW5nIGl0IHdvbid0IHJlc3BvbmQgaWYgdGhlIHZhbHVlIGlzIG1pc3NpbmcpIGZvbGxvd2VkIGJ5IGEgbm8tb3AgdG8gZm9yY2UgYSByZXNwb25zZSAoYW5kIHRvIGdpdmUgdXMgYSBzZW50aW5lbCByZXNwb25zZSB0aGF0IHRoZSBwaXBlbGluZSBpcyBkb25lKVxuICAgKlxuICAgKiBjZiBodHRwczovL2dpdGh1Yi5jb20vY291Y2hiYXNlL21lbWNhY2hlZC9ibG9iL21hc3Rlci9kb2NzL0JpbmFyeVByb3RvY29sLm1kIzB4MGQtZ2V0a3EtZ2V0LXdpdGgta2V5LXF1aWV0bHlcbiAgICovXG4gIF9idWlsZEdldE11bHRpUmVxdWVzdChrZXlzOiBzdHJpbmdbXSwgc2VxOiBudW1iZXIpOiBCdWZmZXIge1xuICAgIC8vIHN0YXJ0IGF0IDI0IGZvciB0aGUgbm8tb3AgY29tbWFuZCBhdCB0aGUgZW5kXG4gICAgbGV0IHJlcXVlc3RTaXplID0gMjQ7XG4gICAgZm9yIChjb25zdCBrZXlJZHggaW4ga2V5cykge1xuICAgICAgcmVxdWVzdFNpemUgKz0gQnVmZmVyLmJ5dGVMZW5ndGgoa2V5c1trZXlJZHhdLCBcInV0ZjhcIikgKyAyNDtcbiAgICB9XG5cbiAgICBjb25zdCByZXF1ZXN0ID0gQnVmZmVyLmFsbG9jKHJlcXVlc3RTaXplKTtcblxuICAgIGxldCBieXRlc1dyaXR0ZW4gPSAwO1xuICAgIGZvciAoY29uc3Qga2V5SWR4IGluIGtleXMpIHtcbiAgICAgIGNvbnN0IGtleSA9IGtleXNba2V5SWR4XTtcbiAgICAgIGJ5dGVzV3JpdHRlbiArPSBjb3B5SW50b1JlcXVlc3RCdWZmZXIoXG4gICAgICAgIGNvbnN0YW50cy5PUF9HRVRLUSxcbiAgICAgICAga2V5LFxuICAgICAgICBcIlwiLFxuICAgICAgICBcIlwiLFxuICAgICAgICBzZXEsXG4gICAgICAgIHJlcXVlc3QsXG4gICAgICAgIGJ5dGVzV3JpdHRlblxuICAgICAgKTtcbiAgICB9XG5cbiAgICBieXRlc1dyaXR0ZW4gKz0gY29weUludG9SZXF1ZXN0QnVmZmVyKFxuICAgICAgY29uc3RhbnRzLk9QX05PX09QLFxuICAgICAgXCJcIixcbiAgICAgIFwiXCIsXG4gICAgICBcIlwiLFxuICAgICAgc2VxLFxuICAgICAgcmVxdWVzdCxcbiAgICAgIGJ5dGVzV3JpdHRlblxuICAgICk7XG5cbiAgICByZXR1cm4gcmVxdWVzdDtcbiAgfVxuXG4gIC8qKiBFeGVjdXRpbmcgYSBwaXBlbGluZWQgKG11bHRpKSBnZXQgYWdhaW5zdCBhIHNpbmdsZSBzZXJ2ZXIuIFRoaXMgaXMgYSBwcml2YXRlIGltcGxlbWVudGF0aW9uIGRldGFpbCBvZiBnZXRNdWx0aS4gKi9cbiAgYXN5bmMgX2dldE11bHRpVG9TZXJ2ZXI8S2V5cyBleHRlbmRzIHN0cmluZz4oXG4gICAgc2VydjogU2VydmVyLFxuICAgIGtleXM6IEtleXNbXVxuICApOiBQcm9taXNlPEdldE11bHRpUmVzdWx0PEtleXMsIFZhbHVlLCBFeHRyYXM+PiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGNvbnN0IHJlc3BvbnNlTWFwOiBHZXRNdWx0aVJlc3VsdDxzdHJpbmcsIFZhbHVlLCBFeHRyYXM+ID0ge307XG5cbiAgICAgIGNvbnN0IGhhbmRsZTogT25SZXNwb25zZUNhbGxiYWNrID0gKHJlc3BvbnNlKSA9PiB7XG4gICAgICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgICAgIC8vIFdoZW4gd2UgZ2V0IHRoZSBuby1vcCByZXNwb25zZSwgd2UgYXJlIGRvbmUgd2l0aCB0aGlzIG9uZSBnZXRNdWx0aSBpbiB0aGUgcGVyLWJhY2tlbmQgZmFuLW91dFxuICAgICAgICAgICAgaWYgKHJlc3BvbnNlLmhlYWRlci5vcGNvZGUgPT09IGNvbnN0YW50cy5PUF9OT19PUCkge1xuICAgICAgICAgICAgICAvLyBUaGlzIGVuc3VyZXMgdGhlIGhhbmRsZXIgd2lsbCBiZSBkZWxldGVkIGZyb20gdGhlIHJlc3BvbnNlQ2FsbGJhY2tzIG1hcCBpbiBzZXJ2ZXIuanNcbiAgICAgICAgICAgICAgLy8gVGhpcyBpc24ndCB0ZWNobmljYWxseSBuZWVkZWQgaGVyZSBiZWNhdXNlIHRoZSBsb2dpYyBpbiBzZXJ2ZXIuanMgYWxzbyBjaGVja3MgaWYgdG90YWxCb2R5TGVuZ3RoID09PSAwLCBidXQgb3VyIHVuaXR0ZXN0cyBhcmVuJ3QgZ3JlYXQgYWJvdXQgc2V0dGluZyB0aGF0IGZpZWxkLCBhbmQgYWxzbyB0aGlzIG1ha2VzIGl0IG1vcmUgZXhwbGljaXRcbiAgICAgICAgICAgICAgaGFuZGxlLnF1aWV0ID0gZmFsc2U7XG4gICAgICAgICAgICAgIHJlc29sdmUocmVzcG9uc2VNYXApO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgICAgICAgcmVzcG9uc2UuaGVhZGVyLm9wY29kZSA9PT0gY29uc3RhbnRzLk9QX0dFVEsgfHxcbiAgICAgICAgICAgICAgcmVzcG9uc2UuaGVhZGVyLm9wY29kZSA9PT0gY29uc3RhbnRzLk9QX0dFVEtRXG4gICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgY29uc3QgZGVzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLmRlc2VyaWFsaXplKFxuICAgICAgICAgICAgICAgIHJlc3BvbnNlLmhlYWRlci5vcGNvZGUsXG4gICAgICAgICAgICAgICAgcmVzcG9uc2UudmFsLFxuICAgICAgICAgICAgICAgIHJlc3BvbnNlLmV4dHJhc1xuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICBjb25zdCBrZXkgPSByZXNwb25zZS5rZXkudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgaWYgKGtleS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVqZWN0KFxuICAgICAgICAgICAgICAgICAgbmV3IEVycm9yKFxuICAgICAgICAgICAgICAgICAgICBcIlJlY2lldmVkIGVtcHR5IGtleSBpbiBnZXRNdWx0aTogXCIgK1xuICAgICAgICAgICAgICAgICAgICAgIEpTT04uc3RyaW5naWZ5KHJlc3BvbnNlKVxuICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgcmVzcG9uc2VNYXBba2V5XSA9IHsgLi4uZGVzZXJpYWxpemVkLCBjYXM6IHJlc3BvbnNlLmhlYWRlci5jYXMgfTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHJldHVybiByZWplY3QoXG4gICAgICAgICAgICAgICAgbmV3IEVycm9yKFxuICAgICAgICAgICAgICAgICAgXCJSZWNpZXZlZCByZXNwb25zZSBpbiBnZXRNdWx0aSBmb3IgdW5rbm93biBvcGNvZGU6IFwiICtcbiAgICAgICAgICAgICAgICAgICAgSlNPTi5zdHJpbmdpZnkocmVzcG9uc2UpXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHJldHVybiByZWplY3QoXG4gICAgICAgICAgICAgIHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJHRVRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cylcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH07XG4gICAgICAvLyBUaGlzIHByZXZlbnRzIHRoZSBoYW5kbGVyIGZyb20gYmVpbmcgZGVsZXRlZFxuICAgICAgLy8gYWZ0ZXIgdGhlIGZpcnN0IHJlc3BvbnNlLiBMb2dpYyBpbiBzZXJ2ZXIuanMuXG4gICAgICBoYW5kbGUucXVpZXQgPSB0cnVlO1xuXG4gICAgICBjb25zdCBzZXEgPSB0aGlzLmluY3JTZXEoKTtcbiAgICAgIGNvbnN0IHJlcXVlc3QgPSB0aGlzLl9idWlsZEdldE11bHRpUmVxdWVzdChrZXlzLCBzZXEpO1xuICAgICAgc2Vydi5vblJlc3BvbnNlKHRoaXMuc2VxLCBoYW5kbGUpO1xuICAgICAgc2Vydi5vbkVycm9yKHRoaXMuc2VxLCByZWplY3QpO1xuICAgICAgc2Vydi53cml0ZShyZXF1ZXN0KTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXRyaWV2cyB0aGUgdmFsdWUgYXQgdGhlIGdpdmVuIGtleXMgaW4gbWVtY2FjaGVkLiBSZXR1cm5zIGEgbWFwIGZyb20gdGhlXG4gICAqIHJlcXVlc3RlZCBrZXlzIHRvIHJlc3VsdHMsIG9yIG51bGwgaWYgdGhlIGtleSB3YXMgbm90IGZvdW5kLlxuICAgKi9cbiAgYXN5bmMgZ2V0TXVsdGk8S2V5cyBleHRlbmRzIHN0cmluZz4oXG4gICAga2V5czogS2V5c1tdXG4gICk6IFByb21pc2U8R2V0TXVsdGlSZXN1bHQ8S2V5cywgVmFsdWUsIEV4dHJhcz4+IHtcbiAgICBjb25zdCBzZXJ2ZXJLZXl0b0xvb2t1cEtleXM6IHtcbiAgICAgIFtzZXJ2ZXJLZXk6IHN0cmluZ106IHN0cmluZ1tdO1xuICAgIH0gPSB7fTtcbiAgICBrZXlzLmZvckVhY2goKGxvb2t1cEtleSkgPT4ge1xuICAgICAgY29uc3Qgc2VydmVyS2V5ID0gdGhpcy5sb29rdXBLZXlUb1NlcnZlcktleShsb29rdXBLZXkpO1xuICAgICAgaWYgKCFzZXJ2ZXJLZXl0b0xvb2t1cEtleXNbc2VydmVyS2V5XSkge1xuICAgICAgICBzZXJ2ZXJLZXl0b0xvb2t1cEtleXNbc2VydmVyS2V5XSA9IFtdO1xuICAgICAgfVxuICAgICAgc2VydmVyS2V5dG9Mb29rdXBLZXlzW3NlcnZlcktleV0ucHVzaChsb29rdXBLZXkpO1xuICAgIH0pO1xuXG4gICAgY29uc3QgdXNlZFNlcnZlcktleXMgPSBPYmplY3Qua2V5cyhzZXJ2ZXJLZXl0b0xvb2t1cEtleXMpO1xuICAgIGNvbnN0IHJlc3VsdHMgPSBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIHVzZWRTZXJ2ZXJLZXlzLm1hcCgoc2VydmVyS2V5KSA9PiB7XG4gICAgICAgIGNvbnN0IHNlcnZlciA9IHRoaXMuc2VydmVyS2V5VG9TZXJ2ZXIoc2VydmVyS2V5KTtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2dldE11bHRpVG9TZXJ2ZXIoc2VydmVyLCBzZXJ2ZXJLZXl0b0xvb2t1cEtleXNbc2VydmVyS2V5XSk7XG4gICAgICB9KVxuICAgICk7XG5cbiAgICByZXR1cm4gT2JqZWN0LmFzc2lnbih7fSwgLi4ucmVzdWx0cyk7XG4gIH1cblxuICBhc3luYyBnZXRNdWx0aVdpdGhFcnJvcnM8S2V5cyBleHRlbmRzIHN0cmluZz4oXG4gICAga2V5czogS2V5c1tdXG4gICk6IFByb21pc2U8R2V0TXVsdGlXaXRoRXJyb3JzUmVzdWx0PEtleXMsIFZhbHVlLCBFeHRyYXM+PiB7XG4gICAgY29uc3Qgc2VydmVyS2V5dG9Mb29rdXBLZXlzOiB7XG4gICAgICBbc2VydmVyS2V5OiBzdHJpbmddOiBLZXlzW107XG4gICAgfSA9IHt9O1xuICAgIGtleXMuZm9yRWFjaCgobG9va3VwS2V5KSA9PiB7XG4gICAgICBjb25zdCBzZXJ2ZXJLZXkgPSB0aGlzLmxvb2t1cEtleVRvU2VydmVyS2V5KGxvb2t1cEtleSk7XG4gICAgICBpZiAoIXNlcnZlcktleXRvTG9va3VwS2V5c1tzZXJ2ZXJLZXldKSB7XG4gICAgICAgIHNlcnZlcktleXRvTG9va3VwS2V5c1tzZXJ2ZXJLZXldID0gW107XG4gICAgICB9XG4gICAgICBzZXJ2ZXJLZXl0b0xvb2t1cEtleXNbc2VydmVyS2V5XS5wdXNoKGxvb2t1cEtleSk7XG4gICAgfSk7XG5cbiAgICBjb25zdCB1c2VkU2VydmVyS2V5cyA9IE9iamVjdC5rZXlzKHNlcnZlcktleXRvTG9va3VwS2V5cyk7XG4gICAgY29uc3QgZXJyb3JzOiBHZXRNdWx0aUVycm9yPEtleXM+W10gPSBbXTtcbiAgICBjb25zdCByZXN1bHRzID0gYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICB1c2VkU2VydmVyS2V5cy5tYXAoYXN5bmMgKHNlcnZlcktleSkgPT4ge1xuICAgICAgICBjb25zdCBzZXJ2ZXIgPSB0aGlzLnNlcnZlcktleVRvU2VydmVyKHNlcnZlcktleSk7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgcmV0dXJuIGF3YWl0IHRoaXMuX2dldE11bHRpVG9TZXJ2ZXIoc2VydmVyLCBzZXJ2ZXJLZXl0b0xvb2t1cEtleXNbc2VydmVyS2V5XSk7XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgIGxldCBlcnJvcjogRXJyb3I7XG4gICAgICAgICAgaWYgKGVyciBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgICAgICBlcnJvciA9IGVycjtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZXJyb3IgPSBuZXcgRXJyb3IoXCJVbmtub3duIEVycm9yXCIpO1xuICAgICAgICAgICAgKGVycm9yIGFzIGFueSkudGhyb3duID0gZXJyO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGVycm9ycy5wdXNoKHtcbiAgICAgICAgICAgIGVycm9yLFxuICAgICAgICAgICAgc2VydmVyS2V5LFxuICAgICAgICAgICAga2V5czogc2VydmVyS2V5dG9Mb29rdXBLZXlzW3NlcnZlcktleV1cbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfSlcbiAgICApO1xuXG4gICAgcmV0dXJuIHsgcmVzdWx0OiBPYmplY3QuYXNzaWduKHt9LCAuLi5yZXN1bHRzKSwgZXJyb3JzIH07XG4gIH1cblxuICAvKipcbiAgICogU2V0cyBga2V5YCB0byBgdmFsdWVgLlxuICAgKi9cbiAgYXN5bmMgc2V0KFxuICAgIGtleTogc3RyaW5nLFxuICAgIHZhbHVlOiBWYWx1ZSxcbiAgICBvcHRpb25zPzogeyBleHBpcmVzPzogbnVtYmVyOyBjYXM/OiBDQVNUb2tlbiB9XG4gICk6IFByb21pc2U8Ym9vbGVhbiB8IG51bGw+IHtcbiAgICBjb25zdCBleHBpcmVzID0gb3B0aW9ucz8uZXhwaXJlcztcbiAgICBjb25zdCBjYXMgPSBvcHRpb25zPy5jYXM7XG5cbiAgICAvLyBUT0RPOiBzdXBwb3J0IGZsYWdzXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgZXhwaXJhdGlvbiA9IG1ha2VFeHBpcmF0aW9uKGV4cGlyZXMgfHwgdGhpcy5vcHRpb25zLmV4cGlyZXMpO1xuICAgIGNvbnN0IGV4dHJhcyA9IEJ1ZmZlci5jb25jYXQoW0J1ZmZlci5mcm9tKFwiMDAwMDAwMDBcIiwgXCJoZXhcIiksIGV4cGlyYXRpb25dKTtcbiAgICBjb25zdCBzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLnNlcmlhbGl6ZShcbiAgICAgIGNvbnN0YW50cy5PUF9TRVQsXG4gICAgICB2YWx1ZSxcbiAgICAgIGV4dHJhc1xuICAgICk7XG4gICAgY29uc3QgcmVxdWVzdCA9IFV0aWxzLmVuY29kZVJlcXVlc3Qoe1xuICAgICAgaGVhZGVyOiB7XG4gICAgICAgIG9wY29kZTogY29uc3RhbnRzLk9QX1NFVCxcbiAgICAgICAgb3BhcXVlOiB0aGlzLnNlcSxcbiAgICAgICAgY2FzLFxuICAgICAgfSxcbiAgICAgIGtleSxcbiAgICAgIHZhbHVlOiBzZXJpYWxpemVkLnZhbHVlLFxuICAgICAgZXh0cmFzOiBzZXJpYWxpemVkLmV4dHJhcyxcbiAgICB9KTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9FWElTVFM6XG4gICAgICAgIGlmIChjYXMpIHtcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIlNFVFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICAgICAgfVxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIlNFVFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQUREXG4gICAqXG4gICAqIEFkZHMgdGhlIGdpdmVuIF9rZXlfIGFuZCBfdmFsdWVfIHRvIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHNcbiAgICogaWYgdGhlIGtleSBpcyBub3QgYWxyZWFkeSBzZXQuXG4gICAqXG4gICAqIFRoZSBvcHRpb25zIGRpY3Rpb25hcnkgdGFrZXM6XG4gICAqICogX2V4cGlyZXNfOiBvdmVycmlkZXMgdGhlIGRlZmF1bHQgZXhwaXJhdGlvbiAoc2VlIGBDbGllbnQuY3JlYXRlYCkgZm9yIHRoaXNcbiAgICogICAgICAgICAgICAgIHBhcnRpY3VsYXIga2V5LXZhbHVlIHBhaXIuXG4gICAqL1xuICBhc3luYyBhZGQoXG4gICAga2V5OiBzdHJpbmcsXG4gICAgdmFsdWU6IFZhbHVlLFxuICAgIG9wdGlvbnM/OiB7IGV4cGlyZXM/OiBudW1iZXIgfVxuICApOiBQcm9taXNlPGJvb2xlYW4gfCBudWxsPiB7XG4gICAgLy8gVE9ETzogc3VwcG9ydCBmbGFncywgc3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgZXhwaXJhdGlvbiA9IG1ha2VFeHBpcmF0aW9uKG9wdGlvbnM/LmV4cGlyZXMgfHwgdGhpcy5vcHRpb25zLmV4cGlyZXMpO1xuICAgIGNvbnN0IGV4dHJhcyA9IEJ1ZmZlci5jb25jYXQoW0J1ZmZlci5mcm9tKFwiMDAwMDAwMDBcIiwgXCJoZXhcIiksIGV4cGlyYXRpb25dKTtcblxuICAgIGNvbnN0IG9wY29kZSA9IGNvbnN0YW50cy5PUF9BREQ7XG4gICAgY29uc3Qgc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5zZXJpYWxpemUob3Bjb2RlLCB2YWx1ZSwgZXh0cmFzKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICBvcGNvZGUsXG4gICAgICBrZXksXG4gICAgICBzZXJpYWxpemVkLmV4dHJhcyxcbiAgICAgIHNlcmlhbGl6ZWQudmFsdWUsXG4gICAgICB0aGlzLnNlcVxuICAgICk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfRVhJU1RTOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIkFERFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmVwbGFjZXMgdGhlIGdpdmVuIF9rZXlfIGFuZCBfdmFsdWVfIHRvIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHNcbiAgICogaWYgdGhlIGtleSBpcyBhbHJlYWR5IHByZXNlbnQuXG4gICAqL1xuICBhc3luYyByZXBsYWNlKFxuICAgIGtleTogc3RyaW5nLFxuICAgIHZhbHVlOiBWYWx1ZSxcbiAgICBvcHRpb25zPzogeyBleHBpcmVzPzogbnVtYmVyIH1cbiAgKTogUHJvbWlzZTxib29sZWFuIHwgbnVsbD4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgZmxhZ3MsIHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IGV4cGlyYXRpb24gPSBtYWtlRXhwaXJhdGlvbihvcHRpb25zPy5leHBpcmVzIHx8IHRoaXMub3B0aW9ucy5leHBpcmVzKTtcbiAgICBjb25zdCBleHRyYXMgPSBCdWZmZXIuY29uY2F0KFtCdWZmZXIuZnJvbShcIjAwMDAwMDAwXCIsIFwiaGV4XCIpLCBleHBpcmF0aW9uXSk7XG5cbiAgICBjb25zdCBvcGNvZGU6IGNvbnN0YW50cy5PUCA9IGNvbnN0YW50cy5PUF9SRVBMQUNFO1xuICAgIGNvbnN0IHNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuc2VyaWFsaXplKG9wY29kZSwgdmFsdWUsIGV4dHJhcyk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKFxuICAgICAgb3Bjb2RlLFxuICAgICAga2V5LFxuICAgICAgc2VyaWFsaXplZC5leHRyYXMsXG4gICAgICBzZXJpYWxpemVkLnZhbHVlLFxuICAgICAgdGhpcy5zZXFcbiAgICApO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuS0VZX05PVF9GT1VORDpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIlJFUExBQ0VcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIERlbGV0ZXMgdGhlIGdpdmVuIF9rZXlfIGZyb20gbWVtY2FjaGUuIFRoZSBvcGVyYXRpb24gb25seSBzdWNjZWVkc1xuICAgKiBpZiB0aGUga2V5IGlzIGFscmVhZHkgcHJlc2VudC5cbiAgICovXG4gIGFzeW5jIGRlbGV0ZShrZXk6IHN0cmluZyk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIC8vIFRPRE86IFN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcig0LCBrZXksIFwiXCIsIFwiXCIsIHRoaXMuc2VxKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcblxuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuS0VZX05PVF9GT1VORDpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIkRFTEVURVwiLCByZXNwb25zZT8uaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEluY3JlbWVudHMgdGhlIGdpdmVuIF9rZXlfIGluIG1lbWNhY2hlLlxuICAgKi9cbiAgYXN5bmMgaW5jcmVtZW50KFxuICAgIGtleTogc3RyaW5nLFxuICAgIGFtb3VudDogbnVtYmVyLFxuICAgIG9wdGlvbnM/OiB7IGluaXRpYWw/OiBudW1iZXI7IGV4cGlyZXM/OiBudW1iZXIgfVxuICApOiBQcm9taXNlPHsgdmFsdWU6IG51bWJlciB8IG51bGw7IHN1Y2Nlc3M6IGJvb2xlYW4gfCBudWxsIH0+IHtcbiAgICAvLyBUT0RPOiBzdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBpbml0aWFsID0gb3B0aW9ucz8uaW5pdGlhbCB8fCAwO1xuICAgIGNvbnN0IGV4cGlyZXMgPSBvcHRpb25zPy5leHBpcmVzIHx8IHRoaXMub3B0aW9ucy5leHBpcmVzO1xuICAgIGNvbnN0IGV4dHJhcyA9IG1ha2VBbW91bnRJbml0aWFsQW5kRXhwaXJhdGlvbihhbW91bnQsIGluaXRpYWwsIGV4cGlyZXMpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgIGNvbnN0YW50cy5PUF9JTkNSRU1FTlQsXG4gICAgICBrZXksXG4gICAgICBleHRyYXMsXG4gICAgICBcIlwiLFxuICAgICAgdGhpcy5zZXFcbiAgICApO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICBjb25zdCBidWZJbnQgPVxuICAgICAgICAgIChyZXNwb25zZS52YWwucmVhZFVJbnQzMkJFKDApIDw8IDgpICsgcmVzcG9uc2UudmFsLnJlYWRVSW50MzJCRSg0KTtcbiAgICAgICAgcmV0dXJuIHsgdmFsdWU6IGJ1ZkludCwgc3VjY2VzczogdHJ1ZSB9O1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIklOQ1JFTUVOVFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRGVjcmVtZW50cyB0aGUgZ2l2ZW4gYGtleWAgaW4gbWVtY2FjaGUuXG4gICAqL1xuICBhc3luYyBkZWNyZW1lbnQoXG4gICAga2V5OiBzdHJpbmcsXG4gICAgYW1vdW50OiBudW1iZXIsXG4gICAgb3B0aW9uczogeyBpbml0aWFsPzogbnVtYmVyOyBleHBpcmVzPzogbnVtYmVyIH1cbiAgKTogUHJvbWlzZTx7IHZhbHVlOiBudW1iZXIgfCBudWxsOyBzdWNjZXNzOiBib29sZWFuIHwgbnVsbCB9PiB7XG4gICAgLy8gVE9ETzogc3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgaW5pdGlhbCA9IG9wdGlvbnMuaW5pdGlhbCB8fCAwO1xuICAgIGNvbnN0IGV4cGlyZXMgPSBvcHRpb25zLmV4cGlyZXMgfHwgdGhpcy5vcHRpb25zLmV4cGlyZXM7XG4gICAgY29uc3QgZXh0cmFzID0gbWFrZUFtb3VudEluaXRpYWxBbmRFeHBpcmF0aW9uKGFtb3VudCwgaW5pdGlhbCwgZXhwaXJlcyk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKFxuICAgICAgY29uc3RhbnRzLk9QX0RFQ1JFTUVOVCxcbiAgICAgIGtleSxcbiAgICAgIGV4dHJhcyxcbiAgICAgIFwiXCIsXG4gICAgICB0aGlzLnNlcVxuICAgICk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIGNvbnN0IGJ1ZkludCA9XG4gICAgICAgICAgKHJlc3BvbnNlLnZhbC5yZWFkVUludDMyQkUoMCkgPDwgOCkgKyByZXNwb25zZS52YWwucmVhZFVJbnQzMkJFKDQpO1xuICAgICAgICByZXR1cm4geyB2YWx1ZTogYnVmSW50LCBzdWNjZXNzOiB0cnVlIH07XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiREVDUkVNRU5UXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBBcHBlbmQgdGhlIGdpdmVuIF92YWx1ZV8gdG8gdGhlIHZhbHVlIGFzc29jaWF0ZWQgd2l0aCB0aGUgZ2l2ZW4gX2tleV8gaW5cbiAgICogbWVtY2FjaGUuIFRoZSBvcGVyYXRpb24gb25seSBzdWNjZWVkcyBpZiB0aGUga2V5IGlzIGFscmVhZHkgcHJlc2VudC5cbiAgICovXG4gIGFzeW5jIGFwcGVuZChrZXk6IHN0cmluZywgdmFsdWU6IFZhbHVlKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgLy8gVE9ETzogc3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3Qgb3Bjb2RlOiBjb25zdGFudHMuT1AgPSBjb25zdGFudHMuT1BfQVBQRU5EO1xuICAgIGNvbnN0IHNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuc2VyaWFsaXplKG9wY29kZSwgdmFsdWUsIFwiXCIpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgIG9wY29kZSxcbiAgICAgIGtleSxcbiAgICAgIHNlcmlhbGl6ZWQuZXh0cmFzLFxuICAgICAgc2VyaWFsaXplZC52YWx1ZSxcbiAgICAgIHRoaXMuc2VxXG4gICAgKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJBUFBFTkRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFByZXBlbmQgdGhlIGdpdmVuIF92YWx1ZV8gdG8gdGhlIHZhbHVlIGFzc29jaWF0ZWQgd2l0aCB0aGUgZ2l2ZW4gX2tleV8gaW5cbiAgICogbWVtY2FjaGUuIFRoZSBvcGVyYXRpb24gb25seSBzdWNjZWVkcyBpZiB0aGUga2V5IGlzIGFscmVhZHkgcHJlc2VudC5cbiAgICovXG4gIGFzeW5jIHByZXBlbmQoa2V5OiBzdHJpbmcsIHZhbHVlOiBWYWx1ZSk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IG9wY29kZTogY29uc3RhbnRzLk9QID0gY29uc3RhbnRzLk9QX1BSRVBFTkQ7XG4gICAgY29uc3Qgc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5zZXJpYWxpemUob3Bjb2RlLCB2YWx1ZSwgXCJcIik7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKFxuICAgICAgb3Bjb2RlLFxuICAgICAga2V5LFxuICAgICAgc2VyaWFsaXplZC5leHRyYXMsXG4gICAgICBzZXJpYWxpemVkLnZhbHVlLFxuICAgICAgdGhpcy5zZXFcbiAgICApO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuS0VZX05PVF9GT1VORDpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIlBSRVBFTkRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFRvdWNoIHNldHMgYW4gZXhwaXJhdGlvbiB2YWx1ZSwgZ2l2ZW4gYnkgX2V4cGlyZXNfLCBvbiB0aGUgZ2l2ZW4gX2tleV8gaW5cbiAgICogbWVtY2FjaGUuIFRoZSBvcGVyYXRpb24gb25seSBzdWNjZWVkcyBpZiB0aGUga2V5IGlzIGFscmVhZHkgcHJlc2VudC5cbiAgICovXG4gIGFzeW5jIHRvdWNoKGtleTogc3RyaW5nLCBleHBpcmVzOiBudW1iZXIpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAvLyBUT0RPOiBzdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBleHRyYXMgPSBtYWtlRXhwaXJhdGlvbihleHBpcmVzIHx8IHRoaXMub3B0aW9ucy5leHBpcmVzKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoMHgxYywga2V5LCBleHRyYXMsIFwiXCIsIHRoaXMuc2VxKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJUT1VDSFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRkxVU0hcbiAgICpcbiAgICogRmx1c2hlcyB0aGUgY2FjaGUgb24gZWFjaCBjb25uZWN0ZWQgc2VydmVyLiBUaGUgY2FsbGJhY2sgc2lnbmF0dXJlIGlzOlxuICAgKlxuICAgKiAgICAgY2FsbGJhY2sobGFzdEVyciwgcmVzdWx0cylcbiAgICpcbiAgICogd2hlcmUgX2xhc3RFcnJfIGlzIHRoZSBsYXN0IGVycm9yIGVuY291bnRlcmVkIChvciBudWxsLCBpbiB0aGUgY29tbW9uIGNhc2VcbiAgICogb2Ygbm8gZXJyb3JzKS4gX3Jlc3VsdHNfIGlzIGEgZGljdGlvbmFyeSBtYXBwaW5nIGBcImhvc3RuYW1lOnBvcnRcImAgdG8gZWl0aGVyXG4gICAqIGB0cnVlYCAoaWYgdGhlIG9wZXJhdGlvbiB3YXMgc3VjY2Vzc2Z1bCksIG9yIGFuIGVycm9yLlxuICAgKiBAcGFyYW0gY2FsbGJhY2tcbiAgICovXG4gIGZsdXNoKCk6IFByb21pc2U8UmVjb3JkPHN0cmluZywgYm9vbGVhbiB8IEVycm9yPj47XG4gIGZsdXNoKFxuICAgIGNhbGxiYWNrOiAoXG4gICAgICBlcnI6IEVycm9yIHwgbnVsbCxcbiAgICAgIHJlc3VsdHM6IFJlY29yZDxzdHJpbmcsIGJvb2xlYW4gfCBFcnJvcj5cbiAgICApID0+IHZvaWRcbiAgKTogdm9pZDtcbiAgZmx1c2goXG4gICAgY2FsbGJhY2s/OiAoXG4gICAgICBlcnI6IEVycm9yIHwgbnVsbCxcbiAgICAgIHJlc3VsdHM6IFJlY29yZDxzdHJpbmcsIGJvb2xlYW4gfCBFcnJvcj5cbiAgICApID0+IHZvaWRcbiAgKSB7XG4gICAgaWYgKGNhbGxiYWNrID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybiBwcm9taXNpZnkoKGNhbGxiYWNrKSA9PiB7XG4gICAgICAgIHRoaXMuZmx1c2goZnVuY3Rpb24gKGVyciwgcmVzdWx0cykge1xuICAgICAgICAgIGNhbGxiYWNrKGVyciwgcmVzdWx0cyk7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfVxuICAgIC8vIFRPRE86IHN1cHBvcnQgZXhwaXJhdGlvblxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcigweDA4LCBcIlwiLCBcIlwiLCBcIlwiLCB0aGlzLnNlcSk7XG4gICAgbGV0IGNvdW50ID0gdGhpcy5zZXJ2ZXJzLmxlbmd0aDtcbiAgICBjb25zdCByZXN1bHQ6IFJlY29yZDxzdHJpbmcsIGJvb2xlYW4gfCBFcnJvcj4gPSB7fTtcbiAgICBsZXQgbGFzdEVycjogRXJyb3IgfCBudWxsID0gbnVsbDtcblxuICAgIGNvbnN0IGhhbmRsZUZsdXNoID0gZnVuY3Rpb24gKHNlcTogbnVtYmVyLCBzZXJ2OiBTZXJ2ZXIpIHtcbiAgICAgIHNlcnYub25SZXNwb25zZShzZXEsIGZ1bmN0aW9uICgvKiByZXNwb25zZSAqLykge1xuICAgICAgICBjb3VudCAtPSAxO1xuICAgICAgICByZXN1bHRbc2Vydi5ob3N0cG9ydFN0cmluZygpXSA9IHRydWU7XG4gICAgICAgIGlmIChjYWxsYmFjayAmJiBjb3VudCA9PT0gMCkge1xuICAgICAgICAgIGNhbGxiYWNrKGxhc3RFcnIsIHJlc3VsdCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgc2Vydi5vbkVycm9yKHNlcSwgZnVuY3Rpb24gKGVycikge1xuICAgICAgICBjb3VudCAtPSAxO1xuICAgICAgICBsYXN0RXJyID0gZXJyO1xuICAgICAgICByZXN1bHRbc2Vydi5ob3N0cG9ydFN0cmluZygpXSA9IGVycjtcbiAgICAgICAgaWYgKGNhbGxiYWNrICYmIGNvdW50ID09PSAwKSB7XG4gICAgICAgICAgY2FsbGJhY2sobGFzdEVyciwgcmVzdWx0KTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICBzZXJ2LndyaXRlKHJlcXVlc3QpO1xuICAgIH07XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuc2VydmVycy5sZW5ndGg7IGkrKykge1xuICAgICAgaGFuZGxlRmx1c2godGhpcy5zZXEsIHRoaXMuc2VydmVyc1tpXSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNUQVRTX1dJVEhfS0VZXG4gICAqXG4gICAqIFNlbmRzIGEgbWVtY2FjaGUgc3RhdHMgY29tbWFuZCB3aXRoIGEga2V5IHRvIGVhY2ggY29ubmVjdGVkIHNlcnZlci4gVGhlXG4gICAqIGNhbGxiYWNrIGlzIGludm9rZWQgKipPTkNFIFBFUiBTRVJWRVIqKiBhbmQgaGFzIHRoZSBzaWduYXR1cmU6XG4gICAqXG4gICAqICAgICBjYWxsYmFjayhlcnIsIHNlcnZlciwgc3RhdHMpXG4gICAqXG4gICAqIF9zZXJ2ZXJfIGlzIHRoZSBgXCJob3N0bmFtZTpwb3J0XCJgIG9mIHRoZSBzZXJ2ZXIsIGFuZCBfc3RhdHNfIGlzIGEgZGljdGlvbmFyeVxuICAgKiBtYXBwaW5nIHRoZSBzdGF0IG5hbWUgdG8gdGhlIHZhbHVlIG9mIHRoZSBzdGF0aXN0aWMgYXMgYSBzdHJpbmcuXG4gICAqIEBwYXJhbSBrZXlcbiAgICogQHBhcmFtIGNhbGxiYWNrXG4gICAqL1xuICBzdGF0c1dpdGhLZXkoXG4gICAga2V5OiBzdHJpbmcsXG4gICAgY2FsbGJhY2s/OiAoXG4gICAgICBlcnI6IEVycm9yIHwgbnVsbCxcbiAgICAgIHNlcnZlcjogc3RyaW5nLFxuICAgICAgc3RhdHM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gfCBudWxsXG4gICAgKSA9PiB2b2lkXG4gICk6IHZvaWQge1xuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcigweDEwLCBrZXksIFwiXCIsIFwiXCIsIHRoaXMuc2VxKTtcblxuICAgIGNvbnN0IGhhbmRsZVN0YXRzID0gKHNlcTogbnVtYmVyLCBzZXJ2OiBTZXJ2ZXIpID0+IHtcbiAgICAgIGNvbnN0IHJlc3VsdDogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHt9O1xuICAgICAgY29uc3QgaGFuZGxlOiBPblJlc3BvbnNlQ2FsbGJhY2sgPSAocmVzcG9uc2UpID0+IHtcbiAgICAgICAgLy8gZW5kIG9mIHN0YXQgcmVzcG9uc2VzXG4gICAgICAgIGlmIChyZXNwb25zZS5oZWFkZXIudG90YWxCb2R5TGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgICAgICBjYWxsYmFjayhudWxsLCBzZXJ2Lmhvc3Rwb3J0U3RyaW5nKCksIHJlc3VsdCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICAvLyBwcm9jZXNzIHNpbmdsZSBzdGF0IGxpbmUgcmVzcG9uc2VcbiAgICAgICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICAgICAgcmVzdWx0W3Jlc3BvbnNlLmtleS50b1N0cmluZygpXSA9IHJlc3BvbnNlLnZhbC50b1N0cmluZygpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIGNvbnN0IGVycm9yID0gdGhpcy5oYW5kbGVSZXNwb25zZUVycm9yKFxuICAgICAgICAgICAgICBgU1RBVFMgKCR7a2V5fSlgLFxuICAgICAgICAgICAgICByZXNwb25zZS5oZWFkZXIuc3RhdHVzLFxuICAgICAgICAgICAgICB1bmRlZmluZWRcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgY2FsbGJhY2soZXJyb3IsIHNlcnYuaG9zdHBvcnRTdHJpbmcoKSwgbnVsbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH07XG4gICAgICBoYW5kbGUucXVpZXQgPSB0cnVlO1xuXG4gICAgICBzZXJ2Lm9uUmVzcG9uc2Uoc2VxLCBoYW5kbGUpO1xuICAgICAgc2Vydi5vbkVycm9yKHNlcSwgZnVuY3Rpb24gKGVycikge1xuICAgICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgICBjYWxsYmFjayhlcnIsIHNlcnYuaG9zdHBvcnRTdHJpbmcoKSwgbnVsbCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgc2Vydi53cml0ZShyZXF1ZXN0KTtcbiAgICB9O1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnNlcnZlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGhhbmRsZVN0YXRzKHRoaXMuc2VxLCB0aGlzLnNlcnZlcnNbaV0pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTVEFUU1xuICAgKlxuICAgKiBGZXRjaGVzIG1lbWNhY2hlIHN0YXRzIGZyb20gZWFjaCBjb25uZWN0ZWQgc2VydmVyLiBUaGUgY2FsbGJhY2sgaXMgaW52b2tlZFxuICAgKiAqKk9OQ0UgUEVSIFNFUlZFUioqIGFuZCBoYXMgdGhlIHNpZ25hdHVyZTpcbiAgICpcbiAgICogICAgIGNhbGxiYWNrKGVyciwgc2VydmVyLCBzdGF0cylcbiAgICpcbiAgICogX3NlcnZlcl8gaXMgdGhlIGBcImhvc3RuYW1lOnBvcnRcImAgb2YgdGhlIHNlcnZlciwgYW5kIF9zdGF0c18gaXMgYVxuICAgKiBkaWN0aW9uYXJ5IG1hcHBpbmcgdGhlIHN0YXQgbmFtZSB0byB0aGUgdmFsdWUgb2YgdGhlIHN0YXRpc3RpYyBhcyBhIHN0cmluZy5cbiAgICogQHBhcmFtIGNhbGxiYWNrXG4gICAqL1xuICBzdGF0cyhcbiAgICBjYWxsYmFjaz86IChcbiAgICAgIGVycjogRXJyb3IgfCBudWxsLFxuICAgICAgc2VydmVyOiBzdHJpbmcsXG4gICAgICBzdGF0czogUmVjb3JkPHN0cmluZywgc3RyaW5nPiB8IG51bGxcbiAgICApID0+IHZvaWRcbiAgKTogdm9pZCB7XG4gICAgdGhpcy5zdGF0c1dpdGhLZXkoXCJcIiwgY2FsbGJhY2spO1xuICB9XG5cbiAgLyoqXG4gICAqIFJFU0VUX1NUQVRTXG4gICAqXG4gICAqIFJlc2V0IHRoZSBzdGF0aXN0aWNzIGVhY2ggc2VydmVyIGlzIGtlZXBpbmcgYmFjayB0byB6ZXJvLiBUaGlzIGRvZXNuJ3QgY2xlYXJcbiAgICogc3RhdHMgc3VjaCBhcyBpdGVtIGNvdW50LCBidXQgdGVtcG9yYXJ5IHN0YXRzIHN1Y2ggYXMgdG90YWwgbnVtYmVyIG9mXG4gICAqIGNvbm5lY3Rpb25zIG92ZXIgdGltZS5cbiAgICpcbiAgICogVGhlIGNhbGxiYWNrIGlzIGludm9rZWQgKipPTkNFIFBFUiBTRVJWRVIqKiBhbmQgaGFzIHRoZSBzaWduYXR1cmU6XG4gICAqXG4gICAqICAgICBjYWxsYmFjayhlcnIsIHNlcnZlcilcbiAgICpcbiAgICogX3NlcnZlcl8gaXMgdGhlIGBcImhvc3RuYW1lOnBvcnRcImAgb2YgdGhlIHNlcnZlci5cbiAgICogQHBhcmFtIGNhbGxiYWNrXG4gICAqL1xuICByZXNldFN0YXRzKFxuICAgIGNhbGxiYWNrPzogKFxuICAgICAgZXJyOiBFcnJvciB8IG51bGwsXG4gICAgICBzZXJ2ZXI6IHN0cmluZyxcbiAgICAgIHN0YXRzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+IHwgbnVsbFxuICAgICkgPT4gdm9pZFxuICApOiB2b2lkIHtcbiAgICB0aGlzLnN0YXRzV2l0aEtleShcInJlc2V0XCIsIGNhbGxiYWNrKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBRVUlUXG4gICAqXG4gICAqIENsb3NlcyB0aGUgY29ubmVjdGlvbiB0byBlYWNoIHNlcnZlciwgbm90aWZ5aW5nIHRoZW0gb2YgdGhpcyBpbnRlbnRpb24uIE5vdGVcbiAgICogdGhhdCBxdWl0IGNhbiByYWNlIGFnYWluc3QgYWxyZWFkeSBvdXRzdGFuZGluZyByZXF1ZXN0cyB3aGVuIHRob3NlIHJlcXVlc3RzXG4gICAqIGZhaWwgYW5kIGFyZSByZXRyaWVkLCBsZWFkaW5nIHRvIHRoZSBxdWl0IGNvbW1hbmQgd2lubmluZyBhbmQgY2xvc2luZyB0aGVcbiAgICogY29ubmVjdGlvbiBiZWZvcmUgdGhlIHJldHJpZXMgY29tcGxldGUuXG4gICAqL1xuICBxdWl0KCkge1xuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIC8vIFRPRE86IE5pY2VyIHBlcmhhcHMgdG8gZG8gUVVJVFEgKDB4MTcpIGJ1dCBuZWVkIGEgbmV3IGNhbGxiYWNrIGZvciB3aGVuXG4gICAgLy8gd3JpdGUgaXMgZG9uZS5cbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoMHgwNywgXCJcIiwgXCJcIiwgXCJcIiwgdGhpcy5zZXEpOyAvLyBRVUlUXG4gICAgbGV0IHNlcnY7XG5cbiAgICBjb25zdCBoYW5kbGVRdWl0ID0gZnVuY3Rpb24gKHNlcTogbnVtYmVyLCBzZXJ2OiBTZXJ2ZXIpIHtcbiAgICAgIHNlcnYub25SZXNwb25zZShzZXEsIGZ1bmN0aW9uICgvKiByZXNwb25zZSAqLykge1xuICAgICAgICBzZXJ2LmNsb3NlKCk7XG4gICAgICB9KTtcbiAgICAgIHNlcnYub25FcnJvcihzZXEsIGZ1bmN0aW9uICgvKiBlcnIgKi8pIHtcbiAgICAgICAgc2Vydi5jbG9zZSgpO1xuICAgICAgfSk7XG4gICAgICBzZXJ2LndyaXRlKHJlcXVlc3QpO1xuICAgIH07XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuc2VydmVycy5sZW5ndGg7IGkrKykge1xuICAgICAgc2VydiA9IHRoaXMuc2VydmVyc1tpXTtcbiAgICAgIGhhbmRsZVF1aXQodGhpcy5zZXEsIHNlcnYpO1xuICAgIH1cbiAgfVxuXG4gIF92ZXJzaW9uKHNlcnZlcjogU2VydmVyKTogUHJvbWlzZTx7IHZhbHVlOiBWYWx1ZSB8IG51bGwgfT4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICB0aGlzLmluY3JTZXEoKTtcbiAgICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgICAgY29uc3RhbnRzLk9QX1ZFUlNJT04sXG4gICAgICAgIFwiXCIsXG4gICAgICAgIFwiXCIsXG4gICAgICAgIFwiXCIsXG4gICAgICAgIHRoaXMuc2VxXG4gICAgICApO1xuICAgICAgdGhpcy5wZXJmb3JtT25TZXJ2ZXIoc2VydmVyLCByZXF1ZXN0LCB0aGlzLnNlcSwgKGVyciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgIHJldHVybiByZWplY3QoZXJyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHN3aXRjaCAocmVzcG9uc2UhLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgICAgICAvKiBUT0RPOiB0aGlzIGlzIGJ1Z2dlZCwgd2Ugc2hvdWxkJ3QgdXNlIHRoZSBkZXNlcmlhbGl6ZXIgaGVyZSwgc2luY2UgdmVyc2lvbiBhbHdheXMgcmV0dXJucyBhIHZlcnNpb24gc3RyaW5nLlxuICAgICAgICAgICAgIFRoZSBkZXNlcmlhbGl6ZXIgc2hvdWxkIG9ubHkgYmUgdXNlZCBvbiB1c2VyIGtleSBkYXRhLiAqL1xuICAgICAgICAgICAgY29uc3QgZGVzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLmRlc2VyaWFsaXplKFxuICAgICAgICAgICAgICByZXNwb25zZSEuaGVhZGVyLm9wY29kZSxcbiAgICAgICAgICAgICAgcmVzcG9uc2UhLnZhbCxcbiAgICAgICAgICAgICAgcmVzcG9uc2UhLmV4dHJhc1xuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHJldHVybiByZXNvbHZlKHsgdmFsdWU6IGRlc2VyaWFsaXplZC52YWx1ZSB9KTtcbiAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgcmV0dXJuIHJlamVjdChcbiAgICAgICAgICAgICAgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIlZFUlNJT05cIiwgcmVzcG9uc2UhLmhlYWRlci5zdGF0dXMpXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXF1ZXN0IHRoZSBzZXJ2ZXIgdmVyc2lvbiBmcm9tIHRoZSBcImZpcnN0XCIgc2VydmVyIGluIHRoZSBiYWNrZW5kIHBvb2wuXG4gICAqIFRoZSBzZXJ2ZXIgcmVzcG9uZHMgd2l0aCBhIHBhY2tldCBjb250YWluaW5nIHRoZSB2ZXJzaW9uIHN0cmluZyBpbiB0aGUgYm9keSB3aXRoIHRoZSBmb2xsb3dpbmcgZm9ybWF0OiBcIngueS56XCJcbiAgICovXG4gIHZlcnNpb24oKTogUHJvbWlzZTx7IHZhbHVlOiBWYWx1ZSB8IG51bGwgfT4ge1xuICAgIGNvbnN0IHNlcnZlciA9IHRoaXMuc2VydmVyS2V5VG9TZXJ2ZXIodGhpcy5zZXJ2ZXJLZXlzWzBdKTtcbiAgICByZXR1cm4gdGhpcy5fdmVyc2lvbihzZXJ2ZXIpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHJpZXZlcyB0aGUgc2VydmVyIHZlcnNpb24gZnJvbSBhbGwgdGhlIHNlcnZlcnNcbiAgICogaW4gdGhlIGJhY2tlbmQgcG9vbCwgZXJyb3JzIGlmIGFueSBvbmUgb2YgdGhlbSBoYXMgYW5cbiAgICogZXJyb3JcbiAgICogXG4gICAqIENhbGxiYWNrcyBmdW5jdGlvbnMgYXJlIGNhbGxlZCBiZWZvcmUvYWZ0ZXIgd2UgcGluZyBtZW1jYWNoZWRcbiAgICogYW5kIHVzZWQgdG8gbG9nIHdoaWNoIGhvc3RzIGFyZSB0aW1pbmcgb3V0LlxuICAgKi9cbiAgYXN5bmMgdmVyc2lvbkFsbChjYWxsYmFja3M/OiB7XG4gICAgYmVmb3JlUGluZz86IChzZXJ2ZXJLZXk6IHN0cmluZykgPT4gdm9pZDtcbiAgICBhZnRlclBpbmc/OiAoc2VydmVyS2V5OiBzdHJpbmcpID0+IHZvaWQ7XG4gIH0pOiBQcm9taXNlPHtcbiAgICB2YWx1ZXM6IFJlY29yZDxzdHJpbmcsIFZhbHVlIHwgbnVsbD47XG4gIH0+IHtcbiAgICBjb25zdCB2ZXJzaW9uT2JqZWN0cyA9IGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgdGhpcy5zZXJ2ZXJLZXlzLm1hcCgoc2VydmVyS2V5KSA9PiB7XG4gICAgICAgIGNvbnN0IHNlcnZlciA9IHRoaXMuc2VydmVyS2V5VG9TZXJ2ZXIoc2VydmVyS2V5KTtcbiAgICAgICAgY2FsbGJhY2tzPy5iZWZvcmVQaW5nPy4oc2VydmVyS2V5KTtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3ZlcnNpb24oc2VydmVyKS50aGVuKChyZXNwb25zZSkgPT4ge1xuICAgICAgICAgIGNhbGxiYWNrcz8uYWZ0ZXJQaW5nPy4oc2VydmVyS2V5KTtcbiAgICAgICAgICByZXR1cm4geyBzZXJ2ZXJLZXk6IHNlcnZlcktleSwgdmFsdWU6IHJlc3BvbnNlLnZhbHVlIH07XG4gICAgICAgIH0pO1xuICAgICAgfSlcbiAgICApO1xuICAgIGNvbnN0IHZhbHVlcyA9IHZlcnNpb25PYmplY3RzLnJlZHVjZSgoYWNjdW11bGF0b3IsIHZlcnNpb25PYmplY3QpID0+IHtcbiAgICAgIGFjY3VtdWxhdG9yW3ZlcnNpb25PYmplY3Quc2VydmVyS2V5XSA9IHZlcnNpb25PYmplY3QudmFsdWU7XG4gICAgICByZXR1cm4gYWNjdW11bGF0b3I7XG4gICAgfSwge30gYXMgUmVjb3JkPHN0cmluZywgVmFsdWUgfCBudWxsPik7XG4gICAgcmV0dXJuIHsgdmFsdWVzOiB2YWx1ZXMgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDbG9zZXMgKGFicnVwdGx5KSBjb25uZWN0aW9ucyB0byBhbGwgdGhlIHNlcnZlcnMuXG4gICAqIEBzZWUgdGhpcy5xdWl0XG4gICAqL1xuICBjbG9zZSgpIHtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuc2VydmVycy5sZW5ndGg7IGkrKykge1xuICAgICAgdGhpcy5zZXJ2ZXJzW2ldLmNsb3NlKCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFBlcmZvcm0gYSBnZW5lcmljIHNpbmdsZSByZXNwb25zZSBvcGVyYXRpb24gKGdldCwgc2V0IGV0Yykgb24gb25lIHNlcnZlclxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IHRoZSBrZXkgdG8gaGFzaCB0byBnZXQgYSBzZXJ2ZXIgZnJvbSB0aGUgcG9vbFxuICAgKiBAcGFyYW0ge2J1ZmZlcn0gcmVxdWVzdCBhIGJ1ZmZlciBjb250YWluaW5nIHRoZSByZXF1ZXN0XG4gICAqIEBwYXJhbSB7bnVtYmVyfSBzZXEgdGhlIHNlcXVlbmNlIG51bWJlciBvZiB0aGUgb3BlcmF0aW9uLiBJdCBpcyB1c2VkIHRvIHBpbiB0aGUgY2FsbGJhY2tzXG4gICAgICAgICAgICAgICAgICAgICAgICAgdG8gYSBzcGVjaWZpYyBvcGVyYXRpb24gYW5kIHNob3VsZCBuZXZlciBjaGFuZ2UgZHVyaW5nIGEgYHBlcmZvcm1gLlxuICAgKiBAcGFyYW0ge251bWJlcj99IHJldHJpZXMgbnVtYmVyIG9mIHRpbWVzIHRvIHJldHJ5IHJlcXVlc3Qgb24gZmFpbHVyZVxuICAgKi9cbiAgcGVyZm9ybShcbiAgICBrZXk6IHN0cmluZyxcbiAgICByZXF1ZXN0OiBCdWZmZXIsXG4gICAgc2VxOiBudW1iZXIsXG4gICAgcmV0cmllcz86IG51bWJlclxuICApOiBQcm9taXNlPE1lc3NhZ2U+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgY29uc3Qgc2VydmVyS2V5ID0gdGhpcy5sb29rdXBLZXlUb1NlcnZlcktleShrZXkpO1xuICAgICAgY29uc3Qgc2VydmVyID0gdGhpcy5zZXJ2ZXJLZXlUb1NlcnZlcihzZXJ2ZXJLZXkpO1xuXG4gICAgICBpZiAoIXNlcnZlcikge1xuICAgICAgICByZXR1cm4gcmVqZWN0KG5ldyBFcnJvcihcIk5vIHNlcnZlcnMgYXZhaWxhYmxlXCIpKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5wZXJmb3JtT25TZXJ2ZXIoXG4gICAgICAgIHNlcnZlcixcbiAgICAgICAgcmVxdWVzdCxcbiAgICAgICAgc2VxLFxuICAgICAgICAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICByZXR1cm4gcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmVzb2x2ZShyZXNwb25zZSEpO1xuICAgICAgICB9LFxuICAgICAgICByZXRyaWVzXG4gICAgICApO1xuICAgIH0pO1xuICB9XG5cbiAgcGVyZm9ybU9uU2VydmVyKFxuICAgIHNlcnZlcjogU2VydmVyLFxuICAgIHJlcXVlc3Q6IEJ1ZmZlcixcbiAgICBzZXE6IG51bWJlcixcbiAgICBjYWxsYmFjazogUmVzcG9uc2VPckVycm9yQ2FsbGJhY2ssXG4gICAgcmV0cmllczogbnVtYmVyID0gMFxuICApIHtcbiAgICBjb25zdCBfdGhpcyA9IHRoaXM7XG5cbiAgICByZXRyaWVzID0gcmV0cmllcyB8fCB0aGlzLm9wdGlvbnMucmV0cmllcztcbiAgICBjb25zdCBvcmlnUmV0cmllcyA9IHRoaXMub3B0aW9ucy5yZXRyaWVzO1xuICAgIGNvbnN0IGxvZ2dlciA9IHRoaXMub3B0aW9ucy5sb2dnZXI7XG4gICAgY29uc3QgcmV0cnlfZGVsYXkgPSB0aGlzLm9wdGlvbnMucmV0cnlfZGVsYXk7XG5cbiAgICBjb25zdCByZXNwb25zZUhhbmRsZXI6IE9uUmVzcG9uc2VDYWxsYmFjayA9IGZ1bmN0aW9uIChyZXNwb25zZSkge1xuICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgIGNhbGxiYWNrKG51bGwsIHJlc3BvbnNlKTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgY29uc3QgZXJyb3JIYW5kbGVyOiBPbkVycm9yQ2FsbGJhY2sgPSBmdW5jdGlvbiAoZXJyb3IpIHtcbiAgICAgIGlmICgtLXJldHJpZXMgPiAwKSB7XG4gICAgICAgIC8vIFdhaXQgZm9yIHJldHJ5X2RlbGF5XG4gICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgIF90aGlzLnBlcmZvcm1PblNlcnZlcihzZXJ2ZXIsIHJlcXVlc3QsIHNlcSwgY2FsbGJhY2ssIHJldHJpZXMpO1xuICAgICAgICB9LCAxMDAwICogcmV0cnlfZGVsYXkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbG9nZ2VyLmxvZyhcbiAgICAgICAgICBcIk1lbUpTOiBTZXJ2ZXIgPFwiICtcbiAgICAgICAgICAgIHNlcnZlci5ob3N0cG9ydFN0cmluZygpICtcbiAgICAgICAgICAgIFwiPiBmYWlsZWQgYWZ0ZXIgKFwiICtcbiAgICAgICAgICAgIG9yaWdSZXRyaWVzICtcbiAgICAgICAgICAgIFwiKSByZXRyaWVzIHdpdGggZXJyb3IgLSBcIiArXG4gICAgICAgICAgICBlcnJvci5tZXNzYWdlXG4gICAgICAgICk7XG4gICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgIGNhbGxiYWNrKGVycm9yLCBudWxsKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH07XG5cbiAgICBzZXJ2ZXIub25SZXNwb25zZShzZXEsIHJlc3BvbnNlSGFuZGxlcik7XG4gICAgc2VydmVyLm9uRXJyb3Ioc2VxLCBlcnJvckhhbmRsZXIpO1xuICAgIHNlcnZlci53cml0ZShyZXF1ZXN0KTtcbiAgfVxuXG4gIC8vIEluY3JlbWVudCB0aGUgc2VxIHZhbHVlXG4gIGluY3JTZXEoKSB7XG4gICAgdGhpcy5zZXErKztcblxuICAgIC8vIFdyYXAgYHRoaXMuc2VxYCB0byAzMi1iaXRzIHNpbmNlIHRoZSBmaWVsZCB3ZSBmaXQgaXQgaW50byBpcyBvbmx5IDMyLWJpdHMuXG4gICAgdGhpcy5zZXEgJj0gMHhmZmZmZmZmZjtcblxuICAgIHJldHVybiB0aGlzLnNlcTtcbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlQW5kTG9nRXJyb3IoXG4gICAgY29tbWFuZE5hbWU6IHN0cmluZyxcbiAgICByZXNwb25zZVN0YXR1czogUmVzcG9uc2VTdGF0dXMgfCB1bmRlZmluZWRcbiAgKTogRXJyb3Ige1xuICAgIGNvbnN0IGVycm9yTWVzc2FnZSA9IGBNZW1KUyAke2NvbW1hbmROYW1lfTogJHtjb25zdGFudHMucmVzcG9uc2VTdGF0dXNUb1N0cmluZyhcbiAgICAgIHJlc3BvbnNlU3RhdHVzXG4gICAgKX1gO1xuICAgIHRoaXMub3B0aW9ucy5sb2dnZXIubG9nKGVycm9yTWVzc2FnZSk7XG4gICAgcmV0dXJuIG5ldyBFcnJvcihlcnJvck1lc3NhZ2UpO1xuICB9XG5cbiAgLyoqXG4gICAqIExvZyBhbiBlcnJvciB0byB0aGUgbG9nZ2VyLCB0aGVuIHJldHVybiB0aGUgZXJyb3IuXG4gICAqIElmIGEgY2FsbGJhY2sgaXMgZ2l2ZW4sIGNhbGwgaXQgd2l0aCBjYWxsYmFjayhlcnJvciwgbnVsbCkuXG4gICAqL1xuICBwcml2YXRlIGhhbmRsZVJlc3BvbnNlRXJyb3IoXG4gICAgY29tbWFuZE5hbWU6IHN0cmluZyxcbiAgICByZXNwb25zZVN0YXR1czogUmVzcG9uc2VTdGF0dXMgfCB1bmRlZmluZWQsXG4gICAgY2FsbGJhY2s6IHVuZGVmaW5lZCB8ICgoZXJyb3I6IEVycm9yIHwgbnVsbCwgb3RoZXI6IG51bGwpID0+IHZvaWQpXG4gICk6IEVycm9yIHtcbiAgICBjb25zdCBlcnJvciA9IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoY29tbWFuZE5hbWUsIHJlc3BvbnNlU3RhdHVzKTtcbiAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgIGNhbGxiYWNrKGVycm9yLCBudWxsKTtcbiAgICB9XG4gICAgcmV0dXJuIGVycm9yO1xuICB9XG59XG5cbmV4cG9ydCB7IENsaWVudCwgU2VydmVyLCBVdGlscywgSGVhZGVyIH07XG4iXX0= \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVtanMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbWVtanMvbWVtanMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLHdCQUF3Qjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUV4QixxQ0FLa0I7QUE0bENELHVGQTlsQ2YsZUFBTSxPQThsQ2U7QUEzbEN2Qix1REFBK0Q7QUFDL0QsbUNBU2lCO0FBQ2pCLHVEQUF5QztBQUN6QywyQ0FBNkM7QUFDN0MsK0NBQWlDO0FBOGtDUixzQkFBSztBQTdrQzlCLGlEQUFtQztBQTZrQ0gsd0JBQU07QUEza0N0QyxTQUFTLDhCQUE4QixDQUNyQyxPQUFpQixFQUNqQixHQUFXO0lBRVgsTUFBTSxLQUFLLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQztJQUM3QixNQUFNLEtBQUssR0FBRyxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxnQkFBUSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3BELE9BQU8sT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ3hCLENBQUM7QUFFRCwrQ0FBK0M7QUFDL0MsU0FBUyxTQUFTLENBQ2hCLE9BQTBFO0lBRTFFLE9BQU8sSUFBSSxPQUFPLENBQUMsVUFBVSxPQUFPLEVBQUUsTUFBTTtRQUMxQyxPQUFPLENBQUMsVUFBVSxHQUFHLEVBQUUsTUFBTTtZQUMzQixHQUFHLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3RDLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBd0VELE1BQU0sTUFBTTtJQVFWLDRFQUE0RTtJQUM1RSxtQ0FBbUM7SUFDbkMsWUFBWSxPQUFpQixFQUFFLE9BQTBDO1FBQ3ZFLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO1FBQ3ZCLElB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LEdBQUcsQ0FBQztJQUNsQixDQUFDO0lBRU8saUJBQWlCLENBQ3ZCLFdBQW1CLEVBQ25CLGNBQTBDO1FBRTFDLE1BQU0sWUFBWSxHQUFHLFNBQVMsV0FBVyxLQUFLLFNBQVMsQ0FBQyxzQkFBc0IsQ0FDNUUsY0FBYyxDQUNmLEVBQUUsQ0FBQztRQUNKLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUN0QyxPQUFPLElBQUksS0FBSyxDQUFDLFlBQVksQ0FBQyxDQUFDO0lBQ2pDLENBQUM7SUFFRDs7O09BR0c7SUFDSyxtQkFBbUIsQ0FDekIsV0FBbUIsRUFDbkIsY0FBMEMsRUFDMUMsUUFBa0U7UUFFbEUsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixDQUFDLFdBQVcsRUFBRSxjQUFjLENBQUMsQ0FBQztRQUNsRSxJQUFJLFFBQVEsRUFBRTtZQUNaLFFBQVEsQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLENBQUM7U0FDdkI7UUFDRCxPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7Q0FDRjtBQUVRLHdCQUFNIiwic291cmNlc0NvbnRlbnQiOlsiLy8gTWVtVFMgTWVtY2FjaGUgQ2xpZW50XG5cbmltcG9ydCB7XG4gIE9uRXJyb3JDYWxsYmFjayxcbiAgT25SZXNwb25zZUNhbGxiYWNrLFxuICBTZXJ2ZXIsXG4gIFNlcnZlck9wdGlvbnMsXG59IGZyb20gXCIuL3NlcnZlclwiO1xuaW1wb3J0IHsgbm9vcFNlcmlhbGl6ZXIsIFNlcmlhbGl6ZXIgfSBmcm9tIFwiLi9ub29wLXNlcmlhbGl6ZXJcIjtcbmltcG9ydCB7XG4gIG1ha2VSZXF1ZXN0QnVmZmVyLFxuICBjb3B5SW50b1JlcXVlc3RCdWZmZXIsXG4gIG1lcmdlLFxuICBtYWtlRXhwaXJhdGlvbixcbiAgbWFrZUFtb3VudEluaXRpYWxBbmRFeHBpcmF0aW9uLFxuICBoYXNoQ29kZSxcbiAgTWF5YmVCdWZmZXIsXG4gIE1lc3NhZ2UsXG59IGZyb20gXCIuL3V0aWxzXCI7XG5pbXBvcnQgKiBhcyBjb25zdGFudHMgZnJvbSBcIi4vY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBSZXNwb25zZVN0YXR1cyB9IGZyb20gXCIuL2NvbnN0YW50c1wiO1xuaW1wb3J0ICogYXMgVXRpbHMgZnJvbSBcIi4vdXRpbHNcIjtcbmltcG9ydCAqIGFzIEhlYWRlciBmcm9tIFwiLi9oZWFkZXJcIjtcblxuZnVuY3Rpb24gZGVmYXVsdEtleVRvU2VydmVySGFzaEZ1bmN0aW9uKFxuICBzZXJ2ZXJzOiBzdHJpbmdbXSxcbiAga2V5OiBzdHJpbmdcbik6IHN0cmluZyB7XG4gIGNvbnN0IHRvdGFsID0gc2VydmVycy5sZW5ndGg7XG4gIGNvbnN0IGluZGV4ID0gdG90YWwgPiAxID8gaGFzaENvZGUoa2V5KSAlIHRvdGFsIDogMDtcbiAgcmV0dXJuIHNlcnZlcnNbaW5kZXhdO1xufVxuXG4vLyBjb252ZXJ0cyBhIGNhbGwgaW50byBhIHByb21pc2UtcmV0dXJuaW5nIG9uZVxuZnVuY3Rpb24gcHJvbWlzaWZ5PFJlc3VsdD4oXG4gIGNvbW1hbmQ6IChjYWxsYmFjazogKGVycm9yOiBFcnJvciB8IG51bGwsIHJlc3VsdDogUmVzdWx0KSA9PiB2b2lkKSA9PiB2b2lkXG4pOiBQcm9taXNlPFJlc3VsdD4ge1xuICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuICAgIGNvbW1hbmQoZnVuY3Rpb24gKGVyciwgcmVzdWx0KSB7XG4gICAgICBlcnIgPyByZWplY3QoZXJyKSA6IHJlc29sdmUocmVzdWx0KTtcbiAgICB9KTtcbiAgfSk7XG59XG5cbnR5cGUgUmVzcG9uc2VPckVycm9yQ2FsbGJhY2sgPSAoXG4gIGVycm9yOiBFcnJvciB8IG51bGwsXG4gIHJlc3BvbnNlOiBNZXNzYWdlIHwgbnVsbFxuKSA9PiB2b2lkO1xuXG5pbnRlcmZhY2UgQmFzZUNsaWVudE9wdGlvbnMge1xuICByZXRyaWVzOiBudW1iZXI7XG4gIHJldHJ5X2RlbGF5OiBudW1iZXI7XG4gIGV4cGlyZXM6IG51bWJlcjtcbiAgbG9nZ2VyOiB7IGxvZzogdHlwZW9mIGNvbnNvbGUubG9nIH07XG4gIGtleVRvU2VydmVySGFzaEZ1bmN0aW9uOiB0eXBlb2YgZGVmYXVsdEtleVRvU2VydmVySGFzaEZ1bmN0aW9uO1xufVxuXG5pbnRlcmZhY2UgU2VyaWFsaXplclByb3A8VmFsdWUsIEV4dHJhcz4ge1xuICBzZXJpYWxpemVyOiBTZXJpYWxpemVyPFZhbHVlLCBFeHRyYXM+O1xufVxuXG4vKipcbiAqIFRoZSBjbGllbnQgaGFzIHBhcnRpYWwgc3VwcG9ydCBmb3Igc2VyaWFsaXppbmcgYW5kIGRlc2VyaWFsaXppbmcgdmFsdWVzIGZyb20gdGhlXG4gKiBCdWZmZXIgYnl0ZSBzdHJpbmdzIHdlIHJlY2VpdmUgZnJvbSB0aGUgd2lyZS4gVGhlIGRlZmF1bHQgc2VyaWFsaXplciBpcyBmb3IgTWF5YmVCdWZmZXIuXG4gKlxuICogSWYgVmFsdWUgYW5kIEV4dHJhcyBhcmUgb2YgdHlwZSBCdWZmZXIsIHRoZW4gcmV0dXJuIHR5cGUgV2hlbkJ1ZmZlci4gT3RoZXJ3aXNlLFxuICogcmV0dXJuIHR5cGUgTm90QnVmZmVyLlxuICovXG50eXBlIElmQnVmZmVyPFZhbHVlLCBFeHRyYXMsIFdoZW5WYWx1ZUFuZEV4dHJhc0FyZUJ1ZmZlcnMsIE5vdEJ1ZmZlcj4gPVxuICBWYWx1ZSBleHRlbmRzIEJ1ZmZlclxuICAgID8gRXh0cmFzIGV4dGVuZHMgQnVmZmVyXG4gICAgICA/IFdoZW5WYWx1ZUFuZEV4dHJhc0FyZUJ1ZmZlcnNcbiAgICAgIDogTm90QnVmZmVyXG4gICAgOiBOb3RCdWZmZXI7XG5cbmV4cG9ydCB0eXBlIEdpdmVuQ2xpZW50T3B0aW9uczxWYWx1ZSwgRXh0cmFzPiA9IFBhcnRpYWw8QmFzZUNsaWVudE9wdGlvbnM+ICZcbiAgSWZCdWZmZXI8XG4gICAgVmFsdWUsXG4gICAgRXh0cmFzLFxuICAgIFBhcnRpYWw8U2VyaWFsaXplclByb3A8VmFsdWUsIEV4dHJhcz4+LFxuICAgIFNlcmlhbGl6ZXJQcm9wPFZhbHVlLCBFeHRyYXM+XG4gID47XG5cbmV4cG9ydCB0eXBlIENBU1Rva2VuID0gQnVmZmVyO1xuXG5leHBvcnQgaW50ZXJmYWNlIEdldFJlc3VsdDxWYWx1ZSA9IE1heWJlQnVmZmVyLCBFeHRyYXMgPSBNYXliZUJ1ZmZlcj4ge1xuICB2YWx1ZTogVmFsdWU7XG4gIGV4dHJhczogRXh0cmFzO1xuICBjYXM6IENBU1Rva2VuIHwgdW5kZWZpbmVkO1xufVxuXG5leHBvcnQgdHlwZSBHZXRNdWx0aVJlc3VsdDxcbiAgS2V5cyBleHRlbmRzIHN0cmluZyA9IHN0cmluZyxcbiAgVmFsdWUgPSBNYXliZUJ1ZmZlcixcbiAgRXh0cmFzID0gTWF5YmVCdWZmZXJcbj4gPSB7XG4gIFtLIGluIEtleXNdPzogR2V0UmVzdWx0PFZhbHVlLCBFeHRyYXM+O1xufTtcblxuZXhwb3J0IGludGVyZmFjZSBHZXRNdWx0aUVycm9yPEtleXMgZXh0ZW5kcyBzdHJpbmcgPSBzdHJpbmc+IHtcbiAgZXJyb3I6IEVycm9yO1xuICBzZXJ2ZXJLZXk6IHN0cmluZztcbiAga2V5czogS2V5c1tdO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEdldE11bHRpV2l0aEVycm9yc1Jlc3VsdDxcbktleXMgZXh0ZW5kcyBzdHJpbmcgPSBzdHJpbmcsXG5WYWx1ZSA9IE1heWJlQnVmZmVyLFxuRXh0cmFzID0gTWF5YmVCdWZmZXJcbj4ge1xuICByZXN1bHQ6IEdldE11bHRpUmVzdWx0PEtleXMsIFZhbHVlLCBFeHRyYXM+O1xuICBlcnJvcnM6IEdldE11bHRpRXJyb3I8S2V5cz5bXTtcbn1cblxuY2xhc3MgQ2xpZW50PFZhbHVlID0gTWF5YmVCdWZmZXIsIEV4dHJhcyA9IE1heWJlQnVmZmVyPiB7XG4gIHNlcnZlcnM6IFNlcnZlcltdO1xuICBzZXE6IG51bWJlcjtcbiAgb3B0aW9uczogQmFzZUNsaWVudE9wdGlvbnMgJiBQYXJ0aWFsPFNlcmlhbGl6ZXJQcm9wPFZhbHVlLCBFeHRyYXM+PjtcbiAgc2VyaWFsaXplcjogU2VyaWFsaXplcjxWYWx1ZSwgRXh0cmFzPjtcbiAgc2VydmVyTWFwOiB7IFtob3N0cG9ydDogc3RyaW5nXTogU2VydmVyIH07XG4gIHNlcnZlcktleXM6IHN0cmluZ1tdO1xuXG4gIC8vIENsaWVudCBpbml0aWFsaXplciB0YWtlcyBhIGxpc3Qgb2YgYFNlcnZlcmBzIGFuZCBhbiBgb3B0aW9uc2AgZGljdGlvbmFyeS5cbiAgLy8gU2VlIGBDbGllbnQuY3JlYXRlYCBmb3IgZGV0YWlscy5cbiAgY29uc3RydWN0b3Ioc2VydmVyczogU2VydmVyW10sIG9wdGlvbnM6IEdpdmVuQ2xpZW50T3B0aW9uczxWYWx1ZSwgRXh0cmFzPikge1xuICAgIHRoaXMuc2VydmVycyA9IHNlcnZlcnM7XG4gICAgdGhpcy5zZXEgPSAwO1xuICAgIHRoaXMub3B0aW9ucyA9IG1lcmdlKG9wdGlvbnMgfHwge30sIHtcbiAgICAgIHJldHJpZXM6IDIsXG4gICAgICByZXRyeV9kZWxheTogMC4yLFxuICAgICAgZXhwaXJlczogMCxcbiAgICAgIGxvZ2dlcjogY29uc29sZSxcbiAgICAgIGtleVRvU2VydmVySGFzaEZ1bmN0aW9uOiBkZWZhdWx0S2V5VG9TZXJ2ZXJIYXNoRnVuY3Rpb24sXG4gICAgfSk7XG5cbiAgICB0aGlzLnNlcmlhbGl6ZXIgPSB0aGlzLm9wdGlvbnMuc2VyaWFsaXplciB8fCAobm9vcFNlcmlhbGl6ZXIgYXMgYW55KTtcblxuICAgIC8vIFN0b3JlIGEgbWFwcGluZyBmcm9tIGhvc3Rwb3J0IC0+IHNlcnZlciBzbyB3ZSBjYW4gcXVpY2tseSBnZXQgYSBzZXJ2ZXIgb2JqZWN0IGZyb20gdGhlIHNlcnZlcktleSByZXR1cm5lZCBieSB0aGUgaGFzaGluZyBmdW5jdGlvblxuICAgIGNvbnN0IHNlcnZlck1hcDogeyBbaG9zdHBvcnQ6IHN0cmluZ106IFNlcnZlciB9ID0ge307XG4gICAgdGhpcy5zZXJ2ZXJzLmZvckVhY2goZnVuY3Rpb24gKHNlcnZlcikge1xuICAgICAgc2VydmVyTWFwW3NlcnZlci5ob3N0cG9ydFN0cmluZygpXSA9IHNlcnZlcjtcbiAgICB9KTtcbiAgICB0aGlzLnNlcnZlck1hcCA9IHNlcnZlck1hcDtcblxuICAgIC8vIHN0b3JlIGEgbGlzdCBvZiBhbGwgb3VyIHNlcnZlcktleXMgc28gd2UgZG9uJ3QgbmVlZCB0byBjb25zdGFudGx5IHJlYWxsb2NhdGUgdGhpcyBhcnJheVxuICAgIHRoaXMuc2VydmVyS2V5cyA9IE9iamVjdC5rZXlzKHRoaXMuc2VydmVyTWFwKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgbmV3IGNsaWVudCBnaXZlbiBhbiBvcHRpb25hbCBjb25maWcgc3RyaW5nIGFuZCBvcHRpb25hbCBoYXNoIG9mXG4gICAqIG9wdGlvbnMuIFRoZSBjb25maWcgc3RyaW5nIHNob3VsZCBiZSBvZiB0aGUgZm9ybTpcbiAgICpcbiAgICogICAgIFwiW3VzZXI6cGFzc0Bdc2VydmVyMVs6MTEyMTFdLFt1c2VyOnBhc3NAXXNlcnZlcjJbOjExMjExXSwuLi5cIlxuICAgKlxuICAgKiBJZiB0aGUgYXJndW1lbnQgaXMgbm90IGdpdmVuLCBmYWxsYmFjayBvbiB0aGUgYE1FTUNBQ0hJRVJfU0VSVkVSU2AgZW52aXJvbm1lbnRcbiAgICogdmFyaWFibGUsIGBNRU1DQUNIRV9TRVJWRVJTYCBlbnZpcm9ubWVudCB2YXJpYWJsZSBvciBgXCJsb2NhbGhvc3Q6MTEyMTFcImAuXG4gICAqXG4gICAqIFRoZSBvcHRpb25zIGhhc2ggbWF5IGNvbnRhaW4gdGhlIG9wdGlvbnM6XG4gICAqXG4gICAqICogYHJldHJpZXNgIC0gdGhlIG51bWJlciBvZiB0aW1lcyB0byByZXRyeSBhbiBvcGVyYXRpb24gaW4gbGlldSBvZiBmYWlsdXJlc1xuICAgKiAoZGVmYXVsdCAyKVxuICAgKiAqIGBleHBpcmVzYCAtIHRoZSBkZWZhdWx0IGV4cGlyYXRpb24gaW4gc2Vjb25kcyB0byB1c2UgKGRlZmF1bHQgMCAtIG5ldmVyXG4gICAqIGV4cGlyZSkuIElmIGBleHBpcmVzYCBpcyBncmVhdGVyIHRoYW4gMzAgZGF5cyAoNjAgeCA2MCB4IDI0IHggMzApLCBpdCBpc1xuICAgKiB0cmVhdGVkIGFzIGEgVU5JWCB0aW1lIChudW1iZXIgb2Ygc2Vjb25kcyBzaW5jZSBKYW51YXJ5IDEsIDE5NzApLlxuICAgKiAqIGBsb2dnZXJgIC0gYSBsb2dnZXIgb2JqZWN0IHRoYXQgcmVzcG9uZHMgdG8gYGxvZyhzdHJpbmcpYCBtZXRob2QgY2FsbHMuXG4gICAqXG4gICAqICAgfn5+flxuICAgKiAgICAgbG9nKG1zZzFbLCBtc2cyWywgbXNnM1suLi5dXV0pXG4gICAqICAgfn5+flxuICAgKlxuICAgKiAgIERlZmF1bHRzIHRvIGBjb25zb2xlYC5cbiAgICogKiBgc2VyaWFsaXplcmAgLSB0aGUgb2JqZWN0IHdoaWNoIHdpbGwgKGRlKXNlcmlhbGl6ZSB0aGUgZGF0YS4gSXQgbmVlZHNcbiAgICogICB0d28gcHVibGljIG1ldGhvZHM6IHNlcmlhbGl6ZSBhbmQgZGVzZXJpYWxpemUuIEl0IGRlZmF1bHRzIHRvIHRoZVxuICAgKiAgIG5vb3BTZXJpYWxpemVyOlxuICAgKlxuICAgKiAgIH5+fn5cbiAgICogICBjb25zdCBub29wU2VyaWFsaXplciA9IHtcbiAgICogICAgIHNlcmlhbGl6ZTogZnVuY3Rpb24gKG9wY29kZSwgdmFsdWUsIGV4dHJhcykge1xuICAgKiAgICAgICByZXR1cm4geyB2YWx1ZTogdmFsdWUsIGV4dHJhczogZXh0cmFzIH07XG4gICAqICAgICB9LFxuICAgKiAgICAgZGVzZXJpYWxpemU6IGZ1bmN0aW9uIChvcGNvZGUsIHZhbHVlLCBleHRyYXMpIHtcbiAgICogICAgICAgcmV0dXJuIHsgdmFsdWU6IHZhbHVlLCBleHRyYXM6IGV4dHJhcyB9O1xuICAgKiAgICAgfVxuICAgKiAgIH07XG4gICAqICAgfn5+flxuICAgKlxuICAgKiBPciBvcHRpb25zIGZvciB0aGUgc2VydmVycyBpbmNsdWRpbmc6XG4gICAqICogYHVzZXJuYW1lYCBhbmQgYHBhc3N3b3JkYCBmb3IgZmFsbGJhY2sgU0FTTCBhdXRoZW50aWNhdGlvbiBjcmVkZW50aWFscy5cbiAgICogKiBgdGltZW91dGAgaW4gc2Vjb25kcyB0byBkZXRlcm1pbmUgZmFpbHVyZSBmb3Igb3BlcmF0aW9ucy4gRGVmYXVsdCBpcyAwLjVcbiAgICogICAgICAgICAgICAgc2Vjb25kcy5cbiAgICogKiAnY29ubnRpbWVvdXQnIGluIHNlY29uZHMgdG8gY29ubmVjdGlvbiBmYWlsdXJlLiBEZWZhdWx0IGlzIHR3aWNlIHRoZSB2YWx1ZVxuICAgKiAgICAgICAgICAgICAgICAgb2YgYHRpbWVvdXRgLlxuICAgKiAqIGBrZWVwQWxpdmVgIHdoZXRoZXIgdG8gZW5hYmxlIGtlZXAtYWxpdmUgZnVuY3Rpb25hbGl0eS4gRGVmYXVsdHMgdG8gZmFsc2UuXG4gICAqICogYGtlZXBBbGl2ZURlbGF5YCBpbiBzZWNvbmRzIHRvIHRoZSBpbml0aWFsIGRlbGF5IGJlZm9yZSB0aGUgZmlyc3Qga2VlcGFsaXZlXG4gICAqICAgICAgICAgICAgICAgICAgICBwcm9iZSBpcyBzZW50IG9uIGFuIGlkbGUgc29ja2V0LiBEZWZhdWx0cyBpcyAzMCBzZWNvbmRzLlxuICAgKiAqIGBrZXlUb1NlcnZlckhhc2hGdW5jdGlvbmAgYSBmdW5jdGlvbiB0byBtYXAga2V5cyB0byBzZXJ2ZXJzLCB3aXRoIHRoZSBzaWduYXR1cmVcbiAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgKHNlcnZlcktleXM6IHN0cmluZ1tdLCBrZXk6IHN0cmluZyk6IHN0cmluZ1xuICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICBOT1RFOiBpZiB5b3UgbmVlZCB0byBkbyBzb21lIGV4cGVuc2l2ZSBpbml0aWFsaXphdGlvbiwgKnBsZWFzZSogZG8gaXQgbGF6aWx5IHRoZSBmaXJzdCB0aW1lIHlvdSB0aGlzIGZ1bmN0aW9uIGlzIGNhbGxlZCB3aXRoIGFuIGFycmF5IG9mIHNlcnZlcktleXMsIG5vdCBvbiBldmVyeSBjYWxsXG4gICAqL1xuICBzdGF0aWMgY3JlYXRlPFZhbHVlLCBFeHRyYXM+KFxuICAgIHNlcnZlcnNTdHI6IHN0cmluZyB8IHVuZGVmaW5lZCxcbiAgICBvcHRpb25zOiBJZkJ1ZmZlcjxcbiAgICAgIFZhbHVlLFxuICAgICAgRXh0cmFzLFxuICAgICAgdW5kZWZpbmVkIHwgKFBhcnRpYWw8U2VydmVyT3B0aW9ucz4gJiBHaXZlbkNsaWVudE9wdGlvbnM8VmFsdWUsIEV4dHJhcz4pLFxuICAgICAgUGFydGlhbDxTZXJ2ZXJPcHRpb25zPiAmIEdpdmVuQ2xpZW50T3B0aW9uczxWYWx1ZSwgRXh0cmFzPlxuICAgID5cbiAgKTogQ2xpZW50PFZhbHVlLCBFeHRyYXM+IHtcbiAgICBzZXJ2ZXJzU3RyID1cbiAgICAgIHNlcnZlcnNTdHIgfHxcbiAgICAgIHByb2Nlc3MuZW52Lk1FTUNBQ0hJRVJfU0VSVkVSUyB8fFxuICAgICAgcHJvY2Vzcy5lbnYuTUVNQ0FDSEVfU0VSVkVSUyB8fFxuICAgICAgXCJsb2NhbGhvc3Q6MTEyMTFcIjtcbiAgICBjb25zdCBzZXJ2ZXJVcmlzID0gc2VydmVyc1N0ci5zcGxpdChcIixcIik7XG4gICAgY29uc3Qgc2VydmVycyA9IHNlcnZlclVyaXMubWFwKGZ1bmN0aW9uICh1cmkpIHtcbiAgICAgIGNvbnN0IHVyaVBhcnRzID0gdXJpLnNwbGl0KFwiQFwiKTtcbiAgICAgIGNvbnN0IGhvc3RQb3J0ID0gdXJpUGFydHNbdXJpUGFydHMubGVuZ3RoIC0gMV0uc3BsaXQoXCI6XCIpO1xuICAgICAgY29uc3QgdXNlclBhc3MgPSAodXJpUGFydHNbdXJpUGFydHMubGVuZ3RoIC0gMl0gfHwgXCJcIikuc3BsaXQoXCI6XCIpO1xuICAgICAgcmV0dXJuIG5ldyBTZXJ2ZXIoXG4gICAgICAgIGhvc3RQb3J0WzBdLFxuICAgICAgICBwYXJzZUludChob3N0UG9ydFsxXSB8fCBcIjExMjExXCIsIDEwKSxcbiAgICAgICAgdXNlclBhc3NbMF0sXG4gICAgICAgIHVzZXJQYXNzWzFdLFxuICAgICAgICBvcHRpb25zXG4gICAgICApO1xuICAgIH0pO1xuICAgIHJldHVybiBuZXcgQ2xpZW50KHNlcnZlcnMsIG9wdGlvbnMgYXMgYW55KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHaXZlbiBhIHNlcnZlcktleSBmcm9tbG9va3VwS2V5VG9TZXJ2ZXJLZXksIHJldHVybiB0aGUgY29ycmVzcG9uZGluZyBTZXJ2ZXIgaW5zdGFuY2VcbiAgICpcbiAgICogQHBhcmFtICB7c3RyaW5nfSBzZXJ2ZXJLZXlcbiAgICogQHJldHVybnMge1NlcnZlcn1cbiAgICovXG4gIHNlcnZlcktleVRvU2VydmVyKHNlcnZlcktleTogc3RyaW5nKTogU2VydmVyIHtcbiAgICByZXR1cm4gdGhpcy5zZXJ2ZXJNYXBbc2VydmVyS2V5XTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHaXZlbiBhIGtleSB0byBsb29rIHVwIGluIG1lbWNhY2hlLCByZXR1cm4gYSBzZXJ2ZXJLZXkgKGJhc2VkIG9uIHNvbWVcbiAgICogaGFzaGluZyBmdW5jdGlvbikgd2hpY2ggY2FuIGJlIHVzZWQgdG8gaW5kZXggdGhpcy5zZXJ2ZXJNYXBcbiAgICovXG4gIGxvb2t1cEtleVRvU2VydmVyS2V5KGtleTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5vcHRpb25zLmtleVRvU2VydmVySGFzaEZ1bmN0aW9uKHRoaXMuc2VydmVyS2V5cywga2V5KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXRyaWV2ZXMgdGhlIHZhbHVlIGF0IHRoZSBnaXZlbiBrZXkgaW4gbWVtY2FjaGUuXG4gICAqL1xuICBhc3luYyBnZXQoa2V5OiBzdHJpbmcpOiBQcm9taXNlPEdldFJlc3VsdDxWYWx1ZSwgRXh0cmFzPiB8IG51bGw+IHtcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoY29uc3RhbnRzLk9QX0dFVCwga2V5LCBcIlwiLCBcIlwiLCB0aGlzLnNlcSk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIGNvbnN0IGRlc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5kZXNlcmlhbGl6ZShcbiAgICAgICAgICByZXNwb25zZS5oZWFkZXIub3Bjb2RlLFxuICAgICAgICAgIHJlc3BvbnNlLnZhbCxcbiAgICAgICAgICByZXNwb25zZS5leHRyYXNcbiAgICAgICAgKTtcbiAgICAgICAgcmV0dXJuIHsgLi4uZGVzZXJpYWxpemVkLCBjYXM6IHJlc3BvbnNlLmhlYWRlci5jYXMgfTtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuS0VZX05PVF9GT1VORDpcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiR0VUXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBCdWlsZCBhIHBpcGVsaW5lZCBnZXQgbXVsdGkgcmVxdWVzdCBieSBzZW5kaW5nIG9uZSBHRVRLUSBmb3IgZWFjaCBrZXkgKHF1aWV0LCBtZWFuaW5nIGl0IHdvbid0IHJlc3BvbmQgaWYgdGhlIHZhbHVlIGlzIG1pc3NpbmcpIGZvbGxvd2VkIGJ5IGEgbm8tb3AgdG8gZm9yY2UgYSByZXNwb25zZSAoYW5kIHRvIGdpdmUgdXMgYSBzZW50aW5lbCByZXNwb25zZSB0aGF0IHRoZSBwaXBlbGluZSBpcyBkb25lKVxuICAgKlxuICAgKiBjZiBodHRwczovL2dpdGh1Yi5jb20vY291Y2hiYXNlL21lbWNhY2hlZC9ibG9iL21hc3Rlci9kb2NzL0JpbmFyeVByb3RvY29sLm1kIzB4MGQtZ2V0a3EtZ2V0LXdpdGgta2V5LXF1aWV0bHlcbiAgICovXG4gIF9idWlsZEdldE11bHRpUmVxdWVzdChrZXlzOiBzdHJpbmdbXSwgc2VxOiBudW1iZXIpOiBCdWZmZXIge1xuICAgIC8vIHN0YXJ0IGF0IDI0IGZvciB0aGUgbm8tb3AgY29tbWFuZCBhdCB0aGUgZW5kXG4gICAgbGV0IHJlcXVlc3RTaXplID0gMjQ7XG4gICAgZm9yIChjb25zdCBrZXlJZHggaW4ga2V5cykge1xuICAgICAgcmVxdWVzdFNpemUgKz0gQnVmZmVyLmJ5dGVMZW5ndGgoa2V5c1trZXlJZHhdLCBcInV0ZjhcIikgKyAyNDtcbiAgICB9XG5cbiAgICBjb25zdCByZXF1ZXN0ID0gQnVmZmVyLmFsbG9jKHJlcXVlc3RTaXplKTtcblxuICAgIGxldCBieXRlc1dyaXR0ZW4gPSAwO1xuICAgIGZvciAoY29uc3Qga2V5SWR4IGluIGtleXMpIHtcbiAgICAgIGNvbnN0IGtleSA9IGtleXNba2V5SWR4XTtcbiAgICAgIGJ5dGVzV3JpdHRlbiArPSBjb3B5SW50b1JlcXVlc3RCdWZmZXIoXG4gICAgICAgIGNvbnN0YW50cy5PUF9HRVRLUSxcbiAgICAgICAga2V5LFxuICAgICAgICBcIlwiLFxuICAgICAgICBcIlwiLFxuICAgICAgICBzZXEsXG4gICAgICAgIHJlcXVlc3QsXG4gICAgICAgIGJ5dGVzV3JpdHRlblxuICAgICAgKTtcbiAgICB9XG5cbiAgICBieXRlc1dyaXR0ZW4gKz0gY29weUludG9SZXF1ZXN0QnVmZmVyKFxuICAgICAgY29uc3RhbnRzLk9QX05PX09QLFxuICAgICAgXCJcIixcbiAgICAgIFwiXCIsXG4gICAgICBcIlwiLFxuICAgICAgc2VxLFxuICAgICAgcmVxdWVzdCxcbiAgICAgIGJ5dGVzV3JpdHRlblxuICAgICk7XG5cbiAgICByZXR1cm4gcmVxdWVzdDtcbiAgfVxuXG4gIC8qKiBFeGVjdXRpbmcgYSBwaXBlbGluZWQgKG11bHRpKSBnZXQgYWdhaW5zdCBhIHNpbmdsZSBzZXJ2ZXIuIFRoaXMgaXMgYSBwcml2YXRlIGltcGxlbWVudGF0aW9uIGRldGFpbCBvZiBnZXRNdWx0aS4gKi9cbiAgYXN5bmMgX2dldE11bHRpVG9TZXJ2ZXI8S2V5cyBleHRlbmRzIHN0cmluZz4oXG4gICAgc2VydjogU2VydmVyLFxuICAgIGtleXM6IEtleXNbXVxuICApOiBQcm9taXNlPEdldE11bHRpUmVzdWx0PEtleXMsIFZhbHVlLCBFeHRyYXM+PiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGNvbnN0IHJlc3BvbnNlTWFwOiBHZXRNdWx0aVJlc3VsdDxzdHJpbmcsIFZhbHVlLCBFeHRyYXM+ID0ge307XG5cbiAgICAgIGNvbnN0IGhhbmRsZTogT25SZXNwb25zZUNhbGxiYWNrID0gKHJlc3BvbnNlKSA9PiB7XG4gICAgICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgICAgIC8vIFdoZW4gd2UgZ2V0IHRoZSBuby1vcCByZXNwb25zZSwgd2UgYXJlIGRvbmUgd2l0aCB0aGlzIG9uZSBnZXRNdWx0aSBpbiB0aGUgcGVyLWJhY2tlbmQgZmFuLW91dFxuICAgICAgICAgICAgaWYgKHJlc3BvbnNlLmhlYWRlci5vcGNvZGUgPT09IGNvbnN0YW50cy5PUF9OT19PUCkge1xuICAgICAgICAgICAgICAvLyBUaGlzIGVuc3VyZXMgdGhlIGhhbmRsZXIgd2lsbCBiZSBkZWxldGVkIGZyb20gdGhlIHJlc3BvbnNlQ2FsbGJhY2tzIG1hcCBpbiBzZXJ2ZXIuanNcbiAgICAgICAgICAgICAgLy8gVGhpcyBpc24ndCB0ZWNobmljYWxseSBuZWVkZWQgaGVyZSBiZWNhdXNlIHRoZSBsb2dpYyBpbiBzZXJ2ZXIuanMgYWxzbyBjaGVja3MgaWYgdG90YWxCb2R5TGVuZ3RoID09PSAwLCBidXQgb3VyIHVuaXR0ZXN0cyBhcmVuJ3QgZ3JlYXQgYWJvdXQgc2V0dGluZyB0aGF0IGZpZWxkLCBhbmQgYWxzbyB0aGlzIG1ha2VzIGl0IG1vcmUgZXhwbGljaXRcbiAgICAgICAgICAgICAgaGFuZGxlLnF1aWV0ID0gZmFsc2U7XG4gICAgICAgICAgICAgIHJlc29sdmUocmVzcG9uc2VNYXApO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgICAgICAgcmVzcG9uc2UuaGVhZGVyLm9wY29kZSA9PT0gY29uc3RhbnRzLk9QX0dFVEsgfHxcbiAgICAgICAgICAgICAgcmVzcG9uc2UuaGVhZGVyLm9wY29kZSA9PT0gY29uc3RhbnRzLk9QX0dFVEtRXG4gICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgY29uc3QgZGVzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLmRlc2VyaWFsaXplKFxuICAgICAgICAgICAgICAgIHJlc3BvbnNlLmhlYWRlci5vcGNvZGUsXG4gICAgICAgICAgICAgICAgcmVzcG9uc2UudmFsLFxuICAgICAgICAgICAgICAgIHJlc3BvbnNlLmV4dHJhc1xuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICBjb25zdCBrZXkgPSByZXNwb25zZS5rZXkudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgaWYgKGtleS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVqZWN0KFxuICAgICAgICAgICAgICAgICAgbmV3IEVycm9yKFxuICAgICAgICAgICAgICAgICAgICBcIlJlY2lldmVkIGVtcHR5IGtleSBpbiBnZXRNdWx0aTogXCIgK1xuICAgICAgICAgICAgICAgICAgICAgIEpTT04uc3RyaW5naWZ5KHJlc3BvbnNlKVxuICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgcmVzcG9uc2VNYXBba2V5XSA9IHsgLi4uZGVzZXJpYWxpemVkLCBjYXM6IHJlc3BvbnNlLmhlYWRlci5jYXMgfTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHJldHVybiByZWplY3QoXG4gICAgICAgICAgICAgICAgbmV3IEVycm9yKFxuICAgICAgICAgICAgICAgICAgXCJSZWNpZXZlZCByZXNwb25zZSBpbiBnZXRNdWx0aSBmb3IgdW5rbm93biBvcGNvZGU6IFwiICtcbiAgICAgICAgICAgICAgICAgICAgSlNPTi5zdHJpbmdpZnkocmVzcG9uc2UpXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHJldHVybiByZWplY3QoXG4gICAgICAgICAgICAgIHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJHRVRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cylcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH07XG4gICAgICAvLyBUaGlzIHByZXZlbnRzIHRoZSBoYW5kbGVyIGZyb20gYmVpbmcgZGVsZXRlZFxuICAgICAgLy8gYWZ0ZXIgdGhlIGZpcnN0IHJlc3BvbnNlLiBMb2dpYyBpbiBzZXJ2ZXIuanMuXG4gICAgICBoYW5kbGUucXVpZXQgPSB0cnVlO1xuXG4gICAgICBjb25zdCBzZXEgPSB0aGlzLmluY3JTZXEoKTtcbiAgICAgIGNvbnN0IHJlcXVlc3QgPSB0aGlzLl9idWlsZEdldE11bHRpUmVxdWVzdChrZXlzLCBzZXEpO1xuICAgICAgc2Vydi5vblJlc3BvbnNlKHRoaXMuc2VxLCBoYW5kbGUpO1xuICAgICAgc2Vydi5vbkVycm9yKHRoaXMuc2VxLCByZWplY3QpO1xuICAgICAgc2Vydi53cml0ZShyZXF1ZXN0KTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXRyaWV2cyB0aGUgdmFsdWUgYXQgdGhlIGdpdmVuIGtleXMgaW4gbWVtY2FjaGVkLiBSZXR1cm5zIGEgbWFwIGZyb20gdGhlXG4gICAqIHJlcXVlc3RlZCBrZXlzIHRvIHJlc3VsdHMsIG9yIG51bGwgaWYgdGhlIGtleSB3YXMgbm90IGZvdW5kLlxuICAgKi9cbiAgYXN5bmMgZ2V0TXVsdGk8S2V5cyBleHRlbmRzIHN0cmluZz4oXG4gICAga2V5czogS2V5c1tdXG4gICk6IFByb21pc2U8R2V0TXVsdGlSZXN1bHQ8S2V5cywgVmFsdWUsIEV4dHJhcz4+IHtcbiAgICBjb25zdCBzZXJ2ZXJLZXl0b0xvb2t1cEtleXM6IHtcbiAgICAgIFtzZXJ2ZXJLZXk6IHN0cmluZ106IHN0cmluZ1tdO1xuICAgIH0gPSB7fTtcbiAgICBrZXlzLmZvckVhY2goKGxvb2t1cEtleSkgPT4ge1xuICAgICAgY29uc3Qgc2VydmVyS2V5ID0gdGhpcy5sb29rdXBLZXlUb1NlcnZlcktleShsb29rdXBLZXkpO1xuICAgICAgaWYgKCFzZXJ2ZXJLZXl0b0xvb2t1cEtleXNbc2VydmVyS2V5XSkge1xuICAgICAgICBzZXJ2ZXJLZXl0b0xvb2t1cEtleXNbc2VydmVyS2V5XSA9IFtdO1xuICAgICAgfVxuICAgICAgc2VydmVyS2V5dG9Mb29rdXBLZXlzW3NlcnZlcktleV0ucHVzaChsb29rdXBLZXkpO1xuICAgIH0pO1xuXG4gICAgY29uc3QgdXNlZFNlcnZlcktleXMgPSBPYmplY3Qua2V5cyhzZXJ2ZXJLZXl0b0xvb2t1cEtleXMpO1xuICAgIGNvbnN0IHJlc3VsdHMgPSBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIHVzZWRTZXJ2ZXJLZXlzLm1hcCgoc2VydmVyS2V5KSA9PiB7XG4gICAgICAgIGNvbnN0IHNlcnZlciA9IHRoaXMuc2VydmVyS2V5VG9TZXJ2ZXIoc2VydmVyS2V5KTtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2dldE11bHRpVG9TZXJ2ZXIoc2VydmVyLCBzZXJ2ZXJLZXl0b0xvb2t1cEtleXNbc2VydmVyS2V5XSk7XG4gICAgICB9KVxuICAgICk7XG5cbiAgICByZXR1cm4gT2JqZWN0LmFzc2lnbih7fSwgLi4ucmVzdWx0cyk7XG4gIH1cblxuICBhc3luYyBnZXRNdWx0aVdpdGhFcnJvcnM8S2V5cyBleHRlbmRzIHN0cmluZz4oXG4gICAga2V5czogS2V5c1tdXG4gICk6IFByb21pc2U8R2V0TXVsdGlXaXRoRXJyb3JzUmVzdWx0PEtleXMsIFZhbHVlLCBFeHRyYXM+PiB7XG4gICAgY29uc3Qgc2VydmVyS2V5dG9Mb29rdXBLZXlzOiB7XG4gICAgICBbc2VydmVyS2V5OiBzdHJpbmddOiBLZXlzW107XG4gICAgfSA9IHt9O1xuICAgIGtleXMuZm9yRWFjaCgobG9va3VwS2V5KSA9PiB7XG4gICAgICBjb25zdCBzZXJ2ZXJLZXkgPSB0aGlzLmxvb2t1cEtleVRvU2VydmVyS2V5KGxvb2t1cEtleSk7XG4gICAgICBpZiAoIXNlcnZlcktleXRvTG9va3VwS2V5c1tzZXJ2ZXJLZXldKSB7XG4gICAgICAgIHNlcnZlcktleXRvTG9va3VwS2V5c1tzZXJ2ZXJLZXldID0gW107XG4gICAgICB9XG4gICAgICBzZXJ2ZXJLZXl0b0xvb2t1cEtleXNbc2VydmVyS2V5XS5wdXNoKGxvb2t1cEtleSk7XG4gICAgfSk7XG5cbiAgICBjb25zdCB1c2VkU2VydmVyS2V5cyA9IE9iamVjdC5rZXlzKHNlcnZlcktleXRvTG9va3VwS2V5cyk7XG4gICAgY29uc3QgZXJyb3JzOiBHZXRNdWx0aUVycm9yPEtleXM+W10gPSBbXTtcbiAgICBjb25zdCByZXN1bHRzID0gYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICB1c2VkU2VydmVyS2V5cy5tYXAoYXN5bmMgKHNlcnZlcktleSkgPT4ge1xuICAgICAgICBjb25zdCBzZXJ2ZXIgPSB0aGlzLnNlcnZlcktleVRvU2VydmVyKHNlcnZlcktleSk7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgcmV0dXJuIGF3YWl0IHRoaXMuX2dldE11bHRpVG9TZXJ2ZXIoc2VydmVyLCBzZXJ2ZXJLZXl0b0xvb2t1cEtleXNbc2VydmVyS2V5XSk7XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgZXJyb3JzLnB1c2goe1xuICAgICAgICAgICAgZXJyb3I6IGVycm9yIGFzIEVycm9yLFxuICAgICAgICAgICAgc2VydmVyS2V5LFxuICAgICAgICAgICAga2V5czogc2VydmVyS2V5dG9Mb29rdXBLZXlzW3NlcnZlcktleV1cbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfSlcbiAgICApO1xuXG4gICAgcmV0dXJuIHsgcmVzdWx0OiBPYmplY3QuYXNzaWduKHt9LCAuLi5yZXN1bHRzKSwgZXJyb3JzIH07XG4gIH1cblxuICAvKipcbiAgICogU2V0cyBga2V5YCB0byBgdmFsdWVgLlxuICAgKi9cbiAgYXN5bmMgc2V0KFxuICAgIGtleTogc3RyaW5nLFxuICAgIHZhbHVlOiBWYWx1ZSxcbiAgICBvcHRpb25zPzogeyBleHBpcmVzPzogbnVtYmVyOyBjYXM/OiBDQVNUb2tlbiB9XG4gICk6IFByb21pc2U8Ym9vbGVhbiB8IG51bGw+IHtcbiAgICBjb25zdCBleHBpcmVzID0gb3B0aW9ucz8uZXhwaXJlcztcbiAgICBjb25zdCBjYXMgPSBvcHRpb25zPy5jYXM7XG5cbiAgICAvLyBUT0RPOiBzdXBwb3J0IGZsYWdzXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgZXhwaXJhdGlvbiA9IG1ha2VFeHBpcmF0aW9uKGV4cGlyZXMgfHwgdGhpcy5vcHRpb25zLmV4cGlyZXMpO1xuICAgIGNvbnN0IGV4dHJhcyA9IEJ1ZmZlci5jb25jYXQoW0J1ZmZlci5mcm9tKFwiMDAwMDAwMDBcIiwgXCJoZXhcIiksIGV4cGlyYXRpb25dKTtcbiAgICBjb25zdCBzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLnNlcmlhbGl6ZShcbiAgICAgIGNvbnN0YW50cy5PUF9TRVQsXG4gICAgICB2YWx1ZSxcbiAgICAgIGV4dHJhc1xuICAgICk7XG4gICAgY29uc3QgcmVxdWVzdCA9IFV0aWxzLmVuY29kZVJlcXVlc3Qoe1xuICAgICAgaGVhZGVyOiB7XG4gICAgICAgIG9wY29kZTogY29uc3RhbnRzLk9QX1NFVCxcbiAgICAgICAgb3BhcXVlOiB0aGlzLnNlcSxcbiAgICAgICAgY2FzLFxuICAgICAgfSxcbiAgICAgIGtleSxcbiAgICAgIHZhbHVlOiBzZXJpYWxpemVkLnZhbHVlLFxuICAgICAgZXh0cmFzOiBzZXJpYWxpemVkLmV4dHJhcyxcbiAgICB9KTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9FWElTVFM6XG4gICAgICAgIGlmIChjYXMpIHtcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIlNFVFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICAgICAgfVxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIlNFVFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQUREXG4gICAqXG4gICAqIEFkZHMgdGhlIGdpdmVuIF9rZXlfIGFuZCBfdmFsdWVfIHRvIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHNcbiAgICogaWYgdGhlIGtleSBpcyBub3QgYWxyZWFkeSBzZXQuXG4gICAqXG4gICAqIFRoZSBvcHRpb25zIGRpY3Rpb25hcnkgdGFrZXM6XG4gICAqICogX2V4cGlyZXNfOiBvdmVycmlkZXMgdGhlIGRlZmF1bHQgZXhwaXJhdGlvbiAoc2VlIGBDbGllbnQuY3JlYXRlYCkgZm9yIHRoaXNcbiAgICogICAgICAgICAgICAgIHBhcnRpY3VsYXIga2V5LXZhbHVlIHBhaXIuXG4gICAqL1xuICBhc3luYyBhZGQoXG4gICAga2V5OiBzdHJpbmcsXG4gICAgdmFsdWU6IFZhbHVlLFxuICAgIG9wdGlvbnM/OiB7IGV4cGlyZXM/OiBudW1iZXIgfVxuICApOiBQcm9taXNlPGJvb2xlYW4gfCBudWxsPiB7XG4gICAgLy8gVE9ETzogc3VwcG9ydCBmbGFncywgc3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgZXhwaXJhdGlvbiA9IG1ha2VFeHBpcmF0aW9uKG9wdGlvbnM/LmV4cGlyZXMgfHwgdGhpcy5vcHRpb25zLmV4cGlyZXMpO1xuICAgIGNvbnN0IGV4dHJhcyA9IEJ1ZmZlci5jb25jYXQoW0J1ZmZlci5mcm9tKFwiMDAwMDAwMDBcIiwgXCJoZXhcIiksIGV4cGlyYXRpb25dKTtcblxuICAgIGNvbnN0IG9wY29kZSA9IGNvbnN0YW50cy5PUF9BREQ7XG4gICAgY29uc3Qgc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5zZXJpYWxpemUob3Bjb2RlLCB2YWx1ZSwgZXh0cmFzKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICBvcGNvZGUsXG4gICAgICBrZXksXG4gICAgICBzZXJpYWxpemVkLmV4dHJhcyxcbiAgICAgIHNlcmlhbGl6ZWQudmFsdWUsXG4gICAgICB0aGlzLnNlcVxuICAgICk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfRVhJU1RTOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIkFERFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmVwbGFjZXMgdGhlIGdpdmVuIF9rZXlfIGFuZCBfdmFsdWVfIHRvIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHNcbiAgICogaWYgdGhlIGtleSBpcyBhbHJlYWR5IHByZXNlbnQuXG4gICAqL1xuICBhc3luYyByZXBsYWNlKFxuICAgIGtleTogc3RyaW5nLFxuICAgIHZhbHVlOiBWYWx1ZSxcbiAgICBvcHRpb25zPzogeyBleHBpcmVzPzogbnVtYmVyIH1cbiAgKTogUHJvbWlzZTxib29sZWFuIHwgbnVsbD4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgZmxhZ3MsIHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IGV4cGlyYXRpb24gPSBtYWtlRXhwaXJhdGlvbihvcHRpb25zPy5leHBpcmVzIHx8IHRoaXMub3B0aW9ucy5leHBpcmVzKTtcbiAgICBjb25zdCBleHRyYXMgPSBCdWZmZXIuY29uY2F0KFtCdWZmZXIuZnJvbShcIjAwMDAwMDAwXCIsIFwiaGV4XCIpLCBleHBpcmF0aW9uXSk7XG5cbiAgICBjb25zdCBvcGNvZGU6IGNvbnN0YW50cy5PUCA9IGNvbnN0YW50cy5PUF9SRVBMQUNFO1xuICAgIGNvbnN0IHNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuc2VyaWFsaXplKG9wY29kZSwgdmFsdWUsIGV4dHJhcyk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKFxuICAgICAgb3Bjb2RlLFxuICAgICAga2V5LFxuICAgICAgc2VyaWFsaXplZC5leHRyYXMsXG4gICAgICBzZXJpYWxpemVkLnZhbHVlLFxuICAgICAgdGhpcy5zZXFcbiAgICApO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuS0VZX05PVF9GT1VORDpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIlJFUExBQ0VcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIERlbGV0ZXMgdGhlIGdpdmVuIF9rZXlfIGZyb20gbWVtY2FjaGUuIFRoZSBvcGVyYXRpb24gb25seSBzdWNjZWVkc1xuICAgKiBpZiB0aGUga2V5IGlzIGFscmVhZHkgcHJlc2VudC5cbiAgICovXG4gIGFzeW5jIGRlbGV0ZShrZXk6IHN0cmluZyk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIC8vIFRPRE86IFN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcig0LCBrZXksIFwiXCIsIFwiXCIsIHRoaXMuc2VxKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcblxuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuS0VZX05PVF9GT1VORDpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIkRFTEVURVwiLCByZXNwb25zZT8uaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEluY3JlbWVudHMgdGhlIGdpdmVuIF9rZXlfIGluIG1lbWNhY2hlLlxuICAgKi9cbiAgYXN5bmMgaW5jcmVtZW50KFxuICAgIGtleTogc3RyaW5nLFxuICAgIGFtb3VudDogbnVtYmVyLFxuICAgIG9wdGlvbnM/OiB7IGluaXRpYWw/OiBudW1iZXI7IGV4cGlyZXM/OiBudW1iZXIgfVxuICApOiBQcm9taXNlPHsgdmFsdWU6IG51bWJlciB8IG51bGw7IHN1Y2Nlc3M6IGJvb2xlYW4gfCBudWxsIH0+IHtcbiAgICAvLyBUT0RPOiBzdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBpbml0aWFsID0gb3B0aW9ucz8uaW5pdGlhbCB8fCAwO1xuICAgIGNvbnN0IGV4cGlyZXMgPSBvcHRpb25zPy5leHBpcmVzIHx8IHRoaXMub3B0aW9ucy5leHBpcmVzO1xuICAgIGNvbnN0IGV4dHJhcyA9IG1ha2VBbW91bnRJbml0aWFsQW5kRXhwaXJhdGlvbihhbW91bnQsIGluaXRpYWwsIGV4cGlyZXMpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgIGNvbnN0YW50cy5PUF9JTkNSRU1FTlQsXG4gICAgICBrZXksXG4gICAgICBleHRyYXMsXG4gICAgICBcIlwiLFxuICAgICAgdGhpcy5zZXFcbiAgICApO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICBjb25zdCBidWZJbnQgPVxuICAgICAgICAgIChyZXNwb25zZS52YWwucmVhZFVJbnQzMkJFKDApIDw8IDgpICsgcmVzcG9uc2UudmFsLnJlYWRVSW50MzJCRSg0KTtcbiAgICAgICAgcmV0dXJuIHsgdmFsdWU6IGJ1ZkludCwgc3VjY2VzczogdHJ1ZSB9O1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIklOQ1JFTUVOVFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRGVjcmVtZW50cyB0aGUgZ2l2ZW4gYGtleWAgaW4gbWVtY2FjaGUuXG4gICAqL1xuICBhc3luYyBkZWNyZW1lbnQoXG4gICAga2V5OiBzdHJpbmcsXG4gICAgYW1vdW50OiBudW1iZXIsXG4gICAgb3B0aW9uczogeyBpbml0aWFsPzogbnVtYmVyOyBleHBpcmVzPzogbnVtYmVyIH1cbiAgKTogUHJvbWlzZTx7IHZhbHVlOiBudW1iZXIgfCBudWxsOyBzdWNjZXNzOiBib29sZWFuIHwgbnVsbCB9PiB7XG4gICAgLy8gVE9ETzogc3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgaW5pdGlhbCA9IG9wdGlvbnMuaW5pdGlhbCB8fCAwO1xuICAgIGNvbnN0IGV4cGlyZXMgPSBvcHRpb25zLmV4cGlyZXMgfHwgdGhpcy5vcHRpb25zLmV4cGlyZXM7XG4gICAgY29uc3QgZXh0cmFzID0gbWFrZUFtb3VudEluaXRpYWxBbmRFeHBpcmF0aW9uKGFtb3VudCwgaW5pdGlhbCwgZXhwaXJlcyk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKFxuICAgICAgY29uc3RhbnRzLk9QX0RFQ1JFTUVOVCxcbiAgICAgIGtleSxcbiAgICAgIGV4dHJhcyxcbiAgICAgIFwiXCIsXG4gICAgICB0aGlzLnNlcVxuICAgICk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIGNvbnN0IGJ1ZkludCA9XG4gICAgICAgICAgKHJlc3BvbnNlLnZhbC5yZWFkVUludDMyQkUoMCkgPDwgOCkgKyByZXNwb25zZS52YWwucmVhZFVJbnQzMkJFKDQpO1xuICAgICAgICByZXR1cm4geyB2YWx1ZTogYnVmSW50LCBzdWNjZXNzOiB0cnVlIH07XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiREVDUkVNRU5UXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBBcHBlbmQgdGhlIGdpdmVuIF92YWx1ZV8gdG8gdGhlIHZhbHVlIGFzc29jaWF0ZWQgd2l0aCB0aGUgZ2l2ZW4gX2tleV8gaW5cbiAgICogbWVtY2FjaGUuIFRoZSBvcGVyYXRpb24gb25seSBzdWNjZWVkcyBpZiB0aGUga2V5IGlzIGFscmVhZHkgcHJlc2VudC5cbiAgICovXG4gIGFzeW5jIGFwcGVuZChrZXk6IHN0cmluZywgdmFsdWU6IFZhbHVlKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgLy8gVE9ETzogc3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3Qgb3Bjb2RlOiBjb25zdGFudHMuT1AgPSBjb25zdGFudHMuT1BfQVBQRU5EO1xuICAgIGNvbnN0IHNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuc2VyaWFsaXplKG9wY29kZSwgdmFsdWUsIFwiXCIpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgIG9wY29kZSxcbiAgICAgIGtleSxcbiAgICAgIHNlcmlhbGl6ZWQuZXh0cmFzLFxuICAgICAgc2VyaWFsaXplZC52YWx1ZSxcbiAgICAgIHRoaXMuc2VxXG4gICAgKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJBUFBFTkRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFByZXBlbmQgdGhlIGdpdmVuIF92YWx1ZV8gdG8gdGhlIHZhbHVlIGFzc29jaWF0ZWQgd2l0aCB0aGUgZ2l2ZW4gX2tleV8gaW5cbiAgICogbWVtY2FjaGUuIFRoZSBvcGVyYXRpb24gb25seSBzdWNjZWVkcyBpZiB0aGUga2V5IGlzIGFscmVhZHkgcHJlc2VudC5cbiAgICovXG4gIGFzeW5jIHByZXBlbmQoa2V5OiBzdHJpbmcsIHZhbHVlOiBWYWx1ZSk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IG9wY29kZTogY29uc3RhbnRzLk9QID0gY29uc3RhbnRzLk9QX1BSRVBFTkQ7XG4gICAgY29uc3Qgc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5zZXJpYWxpemUob3Bjb2RlLCB2YWx1ZSwgXCJcIik7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKFxuICAgICAgb3Bjb2RlLFxuICAgICAga2V5LFxuICAgICAgc2VyaWFsaXplZC5leHRyYXMsXG4gICAgICBzZXJpYWxpemVkLnZhbHVlLFxuICAgICAgdGhpcy5zZXFcbiAgICApO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuS0VZX05PVF9GT1VORDpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIlBSRVBFTkRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFRvdWNoIHNldHMgYW4gZXhwaXJhdGlvbiB2YWx1ZSwgZ2l2ZW4gYnkgX2V4cGlyZXNfLCBvbiB0aGUgZ2l2ZW4gX2tleV8gaW5cbiAgICogbWVtY2FjaGUuIFRoZSBvcGVyYXRpb24gb25seSBzdWNjZWVkcyBpZiB0aGUga2V5IGlzIGFscmVhZHkgcHJlc2VudC5cbiAgICovXG4gIGFzeW5jIHRvdWNoKGtleTogc3RyaW5nLCBleHBpcmVzOiBudW1iZXIpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAvLyBUT0RPOiBzdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBleHRyYXMgPSBtYWtlRXhwaXJhdGlvbihleHBpcmVzIHx8IHRoaXMub3B0aW9ucy5leHBpcmVzKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoMHgxYywga2V5LCBleHRyYXMsIFwiXCIsIHRoaXMuc2VxKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJUT1VDSFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRkxVU0hcbiAgICpcbiAgICogRmx1c2hlcyB0aGUgY2FjaGUgb24gZWFjaCBjb25uZWN0ZWQgc2VydmVyLiBUaGUgY2FsbGJhY2sgc2lnbmF0dXJlIGlzOlxuICAgKlxuICAgKiAgICAgY2FsbGJhY2sobGFzdEVyciwgcmVzdWx0cylcbiAgICpcbiAgICogd2hlcmUgX2xhc3RFcnJfIGlzIHRoZSBsYXN0IGVycm9yIGVuY291bnRlcmVkIChvciBudWxsLCBpbiB0aGUgY29tbW9uIGNhc2VcbiAgICogb2Ygbm8gZXJyb3JzKS4gX3Jlc3VsdHNfIGlzIGEgZGljdGlvbmFyeSBtYXBwaW5nIGBcImhvc3RuYW1lOnBvcnRcImAgdG8gZWl0aGVyXG4gICAqIGB0cnVlYCAoaWYgdGhlIG9wZXJhdGlvbiB3YXMgc3VjY2Vzc2Z1bCksIG9yIGFuIGVycm9yLlxuICAgKiBAcGFyYW0gY2FsbGJhY2tcbiAgICovXG4gIGZsdXNoKCk6IFByb21pc2U8UmVjb3JkPHN0cmluZywgYm9vbGVhbiB8IEVycm9yPj47XG4gIGZsdXNoKFxuICAgIGNhbGxiYWNrOiAoXG4gICAgICBlcnI6IEVycm9yIHwgbnVsbCxcbiAgICAgIHJlc3VsdHM6IFJlY29yZDxzdHJpbmcsIGJvb2xlYW4gfCBFcnJvcj5cbiAgICApID0+IHZvaWRcbiAgKTogdm9pZDtcbiAgZmx1c2goXG4gICAgY2FsbGJhY2s/OiAoXG4gICAgICBlcnI6IEVycm9yIHwgbnVsbCxcbiAgICAgIHJlc3VsdHM6IFJlY29yZDxzdHJpbmcsIGJvb2xlYW4gfCBFcnJvcj5cbiAgICApID0+IHZvaWRcbiAgKSB7XG4gICAgaWYgKGNhbGxiYWNrID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybiBwcm9taXNpZnkoKGNhbGxiYWNrKSA9PiB7XG4gICAgICAgIHRoaXMuZmx1c2goZnVuY3Rpb24gKGVyciwgcmVzdWx0cykge1xuICAgICAgICAgIGNhbGxiYWNrKGVyciwgcmVzdWx0cyk7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfVxuICAgIC8vIFRPRE86IHN1cHBvcnQgZXhwaXJhdGlvblxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcigweDA4LCBcIlwiLCBcIlwiLCBcIlwiLCB0aGlzLnNlcSk7XG4gICAgbGV0IGNvdW50ID0gdGhpcy5zZXJ2ZXJzLmxlbmd0aDtcbiAgICBjb25zdCByZXN1bHQ6IFJlY29yZDxzdHJpbmcsIGJvb2xlYW4gfCBFcnJvcj4gPSB7fTtcbiAgICBsZXQgbGFzdEVycjogRXJyb3IgfCBudWxsID0gbnVsbDtcblxuICAgIGNvbnN0IGhhbmRsZUZsdXNoID0gZnVuY3Rpb24gKHNlcTogbnVtYmVyLCBzZXJ2OiBTZXJ2ZXIpIHtcbiAgICAgIHNlcnYub25SZXNwb25zZShzZXEsIGZ1bmN0aW9uICgvKiByZXNwb25zZSAqLykge1xuICAgICAgICBjb3VudCAtPSAxO1xuICAgICAgICByZXN1bHRbc2Vydi5ob3N0cG9ydFN0cmluZygpXSA9IHRydWU7XG4gICAgICAgIGlmIChjYWxsYmFjayAmJiBjb3VudCA9PT0gMCkge1xuICAgICAgICAgIGNhbGxiYWNrKGxhc3RFcnIsIHJlc3VsdCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgc2Vydi5vbkVycm9yKHNlcSwgZnVuY3Rpb24gKGVycikge1xuICAgICAgICBjb3VudCAtPSAxO1xuICAgICAgICBsYXN0RXJyID0gZXJyO1xuICAgICAgICByZXN1bHRbc2Vydi5ob3N0cG9ydFN0cmluZygpXSA9IGVycjtcbiAgICAgICAgaWYgKGNhbGxiYWNrICYmIGNvdW50ID09PSAwKSB7XG4gICAgICAgICAgY2FsbGJhY2sobGFzdEVyciwgcmVzdWx0KTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICBzZXJ2LndyaXRlKHJlcXVlc3QpO1xuICAgIH07XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuc2VydmVycy5sZW5ndGg7IGkrKykge1xuICAgICAgaGFuZGxlRmx1c2godGhpcy5zZXEsIHRoaXMuc2VydmVyc1tpXSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNUQVRTX1dJVEhfS0VZXG4gICAqXG4gICAqIFNlbmRzIGEgbWVtY2FjaGUgc3RhdHMgY29tbWFuZCB3aXRoIGEga2V5IHRvIGVhY2ggY29ubmVjdGVkIHNlcnZlci4gVGhlXG4gICAqIGNhbGxiYWNrIGlzIGludm9rZWQgKipPTkNFIFBFUiBTRVJWRVIqKiBhbmQgaGFzIHRoZSBzaWduYXR1cmU6XG4gICAqXG4gICAqICAgICBjYWxsYmFjayhlcnIsIHNlcnZlciwgc3RhdHMpXG4gICAqXG4gICAqIF9zZXJ2ZXJfIGlzIHRoZSBgXCJob3N0bmFtZTpwb3J0XCJgIG9mIHRoZSBzZXJ2ZXIsIGFuZCBfc3RhdHNfIGlzIGEgZGljdGlvbmFyeVxuICAgKiBtYXBwaW5nIHRoZSBzdGF0IG5hbWUgdG8gdGhlIHZhbHVlIG9mIHRoZSBzdGF0aXN0aWMgYXMgYSBzdHJpbmcuXG4gICAqIEBwYXJhbSBrZXlcbiAgICogQHBhcmFtIGNhbGxiYWNrXG4gICAqL1xuICBzdGF0c1dpdGhLZXkoXG4gICAga2V5OiBzdHJpbmcsXG4gICAgY2FsbGJhY2s/OiAoXG4gICAgICBlcnI6IEVycm9yIHwgbnVsbCxcbiAgICAgIHNlcnZlcjogc3RyaW5nLFxuICAgICAgc3RhdHM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gfCBudWxsXG4gICAgKSA9PiB2b2lkXG4gICk6IHZvaWQge1xuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcigweDEwLCBrZXksIFwiXCIsIFwiXCIsIHRoaXMuc2VxKTtcblxuICAgIGNvbnN0IGhhbmRsZVN0YXRzID0gKHNlcTogbnVtYmVyLCBzZXJ2OiBTZXJ2ZXIpID0+IHtcbiAgICAgIGNvbnN0IHJlc3VsdDogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHt9O1xuICAgICAgY29uc3QgaGFuZGxlOiBPblJlc3BvbnNlQ2FsbGJhY2sgPSAocmVzcG9uc2UpID0+IHtcbiAgICAgICAgLy8gZW5kIG9mIHN0YXQgcmVzcG9uc2VzXG4gICAgICAgIGlmIChyZXNwb25zZS5oZWFkZXIudG90YWxCb2R5TGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgICAgICBjYWxsYmFjayhudWxsLCBzZXJ2Lmhvc3Rwb3J0U3RyaW5nKCksIHJlc3VsdCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICAvLyBwcm9jZXNzIHNpbmdsZSBzdGF0IGxpbmUgcmVzcG9uc2VcbiAgICAgICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICAgICAgcmVzdWx0W3Jlc3BvbnNlLmtleS50b1N0cmluZygpXSA9IHJlc3BvbnNlLnZhbC50b1N0cmluZygpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIGNvbnN0IGVycm9yID0gdGhpcy5oYW5kbGVSZXNwb25zZUVycm9yKFxuICAgICAgICAgICAgICBgU1RBVFMgKCR7a2V5fSlgLFxuICAgICAgICAgICAgICByZXNwb25zZS5oZWFkZXIuc3RhdHVzLFxuICAgICAgICAgICAgICB1bmRlZmluZWRcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgY2FsbGJhY2soZXJyb3IsIHNlcnYuaG9zdHBvcnRTdHJpbmcoKSwgbnVsbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH07XG4gICAgICBoYW5kbGUucXVpZXQgPSB0cnVlO1xuXG4gICAgICBzZXJ2Lm9uUmVzcG9uc2Uoc2VxLCBoYW5kbGUpO1xuICAgICAgc2Vydi5vbkVycm9yKHNlcSwgZnVuY3Rpb24gKGVycikge1xuICAgICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgICBjYWxsYmFjayhlcnIsIHNlcnYuaG9zdHBvcnRTdHJpbmcoKSwgbnVsbCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgc2Vydi53cml0ZShyZXF1ZXN0KTtcbiAgICB9O1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnNlcnZlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGhhbmRsZVN0YXRzKHRoaXMuc2VxLCB0aGlzLnNlcnZlcnNbaV0pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTVEFUU1xuICAgKlxuICAgKiBGZXRjaGVzIG1lbWNhY2hlIHN0YXRzIGZyb20gZWFjaCBjb25uZWN0ZWQgc2VydmVyLiBUaGUgY2FsbGJhY2sgaXMgaW52b2tlZFxuICAgKiAqKk9OQ0UgUEVSIFNFUlZFUioqIGFuZCBoYXMgdGhlIHNpZ25hdHVyZTpcbiAgICpcbiAgICogICAgIGNhbGxiYWNrKGVyciwgc2VydmVyLCBzdGF0cylcbiAgICpcbiAgICogX3NlcnZlcl8gaXMgdGhlIGBcImhvc3RuYW1lOnBvcnRcImAgb2YgdGhlIHNlcnZlciwgYW5kIF9zdGF0c18gaXMgYVxuICAgKiBkaWN0aW9uYXJ5IG1hcHBpbmcgdGhlIHN0YXQgbmFtZSB0byB0aGUgdmFsdWUgb2YgdGhlIHN0YXRpc3RpYyBhcyBhIHN0cmluZy5cbiAgICogQHBhcmFtIGNhbGxiYWNrXG4gICAqL1xuICBzdGF0cyhcbiAgICBjYWxsYmFjaz86IChcbiAgICAgIGVycjogRXJyb3IgfCBudWxsLFxuICAgICAgc2VydmVyOiBzdHJpbmcsXG4gICAgICBzdGF0czogUmVjb3JkPHN0cmluZywgc3RyaW5nPiB8IG51bGxcbiAgICApID0+IHZvaWRcbiAgKTogdm9pZCB7XG4gICAgdGhpcy5zdGF0c1dpdGhLZXkoXCJcIiwgY2FsbGJhY2spO1xuICB9XG5cbiAgLyoqXG4gICAqIFJFU0VUX1NUQVRTXG4gICAqXG4gICAqIFJlc2V0IHRoZSBzdGF0aXN0aWNzIGVhY2ggc2VydmVyIGlzIGtlZXBpbmcgYmFjayB0byB6ZXJvLiBUaGlzIGRvZXNuJ3QgY2xlYXJcbiAgICogc3RhdHMgc3VjaCBhcyBpdGVtIGNvdW50LCBidXQgdGVtcG9yYXJ5IHN0YXRzIHN1Y2ggYXMgdG90YWwgbnVtYmVyIG9mXG4gICAqIGNvbm5lY3Rpb25zIG92ZXIgdGltZS5cbiAgICpcbiAgICogVGhlIGNhbGxiYWNrIGlzIGludm9rZWQgKipPTkNFIFBFUiBTRVJWRVIqKiBhbmQgaGFzIHRoZSBzaWduYXR1cmU6XG4gICAqXG4gICAqICAgICBjYWxsYmFjayhlcnIsIHNlcnZlcilcbiAgICpcbiAgICogX3NlcnZlcl8gaXMgdGhlIGBcImhvc3RuYW1lOnBvcnRcImAgb2YgdGhlIHNlcnZlci5cbiAgICogQHBhcmFtIGNhbGxiYWNrXG4gICAqL1xuICByZXNldFN0YXRzKFxuICAgIGNhbGxiYWNrPzogKFxuICAgICAgZXJyOiBFcnJvciB8IG51bGwsXG4gICAgICBzZXJ2ZXI6IHN0cmluZyxcbiAgICAgIHN0YXRzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+IHwgbnVsbFxuICAgICkgPT4gdm9pZFxuICApOiB2b2lkIHtcbiAgICB0aGlzLnN0YXRzV2l0aEtleShcInJlc2V0XCIsIGNhbGxiYWNrKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBRVUlUXG4gICAqXG4gICAqIENsb3NlcyB0aGUgY29ubmVjdGlvbiB0byBlYWNoIHNlcnZlciwgbm90aWZ5aW5nIHRoZW0gb2YgdGhpcyBpbnRlbnRpb24uIE5vdGVcbiAgICogdGhhdCBxdWl0IGNhbiByYWNlIGFnYWluc3QgYWxyZWFkeSBvdXRzdGFuZGluZyByZXF1ZXN0cyB3aGVuIHRob3NlIHJlcXVlc3RzXG4gICAqIGZhaWwgYW5kIGFyZSByZXRyaWVkLCBsZWFkaW5nIHRvIHRoZSBxdWl0IGNvbW1hbmQgd2lubmluZyBhbmQgY2xvc2luZyB0aGVcbiAgICogY29ubmVjdGlvbiBiZWZvcmUgdGhlIHJldHJpZXMgY29tcGxldGUuXG4gICAqL1xuICBxdWl0KCkge1xuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIC8vIFRPRE86IE5pY2VyIHBlcmhhcHMgdG8gZG8gUVVJVFEgKDB4MTcpIGJ1dCBuZWVkIGEgbmV3IGNhbGxiYWNrIGZvciB3aGVuXG4gICAgLy8gd3JpdGUgaXMgZG9uZS5cbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoMHgwNywgXCJcIiwgXCJcIiwgXCJcIiwgdGhpcy5zZXEpOyAvLyBRVUlUXG4gICAgbGV0IHNlcnY7XG5cbiAgICBjb25zdCBoYW5kbGVRdWl0ID0gZnVuY3Rpb24gKHNlcTogbnVtYmVyLCBzZXJ2OiBTZXJ2ZXIpIHtcbiAgICAgIHNlcnYub25SZXNwb25zZShzZXEsIGZ1bmN0aW9uICgvKiByZXNwb25zZSAqLykge1xuICAgICAgICBzZXJ2LmNsb3NlKCk7XG4gICAgICB9KTtcbiAgICAgIHNlcnYub25FcnJvcihzZXEsIGZ1bmN0aW9uICgvKiBlcnIgKi8pIHtcbiAgICAgICAgc2Vydi5jbG9zZSgpO1xuICAgICAgfSk7XG4gICAgICBzZXJ2LndyaXRlKHJlcXVlc3QpO1xuICAgIH07XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuc2VydmVycy5sZW5ndGg7IGkrKykge1xuICAgICAgc2VydiA9IHRoaXMuc2VydmVyc1tpXTtcbiAgICAgIGhhbmRsZVF1aXQodGhpcy5zZXEsIHNlcnYpO1xuICAgIH1cbiAgfVxuXG4gIF92ZXJzaW9uKHNlcnZlcjogU2VydmVyKTogUHJvbWlzZTx7IHZhbHVlOiBWYWx1ZSB8IG51bGwgfT4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICB0aGlzLmluY3JTZXEoKTtcbiAgICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgICAgY29uc3RhbnRzLk9QX1ZFUlNJT04sXG4gICAgICAgIFwiXCIsXG4gICAgICAgIFwiXCIsXG4gICAgICAgIFwiXCIsXG4gICAgICAgIHRoaXMuc2VxXG4gICAgICApO1xuICAgICAgdGhpcy5wZXJmb3JtT25TZXJ2ZXIoc2VydmVyLCByZXF1ZXN0LCB0aGlzLnNlcSwgKGVyciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgIHJldHVybiByZWplY3QoZXJyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHN3aXRjaCAocmVzcG9uc2UhLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgICAgICAvKiBUT0RPOiB0aGlzIGlzIGJ1Z2dlZCwgd2Ugc2hvdWxkJ3QgdXNlIHRoZSBkZXNlcmlhbGl6ZXIgaGVyZSwgc2luY2UgdmVyc2lvbiBhbHdheXMgcmV0dXJucyBhIHZlcnNpb24gc3RyaW5nLlxuICAgICAgICAgICAgIFRoZSBkZXNlcmlhbGl6ZXIgc2hvdWxkIG9ubHkgYmUgdXNlZCBvbiB1c2VyIGtleSBkYXRhLiAqL1xuICAgICAgICAgICAgY29uc3QgZGVzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLmRlc2VyaWFsaXplKFxuICAgICAgICAgICAgICByZXNwb25zZSEuaGVhZGVyLm9wY29kZSxcbiAgICAgICAgICAgICAgcmVzcG9uc2UhLnZhbCxcbiAgICAgICAgICAgICAgcmVzcG9uc2UhLmV4dHJhc1xuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHJldHVybiByZXNvbHZlKHsgdmFsdWU6IGRlc2VyaWFsaXplZC52YWx1ZSB9KTtcbiAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgcmV0dXJuIHJlamVjdChcbiAgICAgICAgICAgICAgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIlZFUlNJT05cIiwgcmVzcG9uc2UhLmhlYWRlci5zdGF0dXMpXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXF1ZXN0IHRoZSBzZXJ2ZXIgdmVyc2lvbiBmcm9tIHRoZSBcImZpcnN0XCIgc2VydmVyIGluIHRoZSBiYWNrZW5kIHBvb2wuXG4gICAqIFRoZSBzZXJ2ZXIgcmVzcG9uZHMgd2l0aCBhIHBhY2tldCBjb250YWluaW5nIHRoZSB2ZXJzaW9uIHN0cmluZyBpbiB0aGUgYm9keSB3aXRoIHRoZSBmb2xsb3dpbmcgZm9ybWF0OiBcIngueS56XCJcbiAgICovXG4gIHZlcnNpb24oKTogUHJvbWlzZTx7IHZhbHVlOiBWYWx1ZSB8IG51bGwgfT4ge1xuICAgIGNvbnN0IHNlcnZlciA9IHRoaXMuc2VydmVyS2V5VG9TZXJ2ZXIodGhpcy5zZXJ2ZXJLZXlzWzBdKTtcbiAgICByZXR1cm4gdGhpcy5fdmVyc2lvbihzZXJ2ZXIpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHJpZXZlcyB0aGUgc2VydmVyIHZlcnNpb24gZnJvbSBhbGwgdGhlIHNlcnZlcnNcbiAgICogaW4gdGhlIGJhY2tlbmQgcG9vbCwgZXJyb3JzIGlmIGFueSBvbmUgb2YgdGhlbSBoYXMgYW5cbiAgICogZXJyb3JcbiAgICogXG4gICAqIENhbGxiYWNrcyBmdW5jdGlvbnMgYXJlIGNhbGxlZCBiZWZvcmUvYWZ0ZXIgd2UgcGluZyBtZW1jYWNoZWRcbiAgICogYW5kIHVzZWQgdG8gbG9nIHdoaWNoIGhvc3RzIGFyZSB0aW1pbmcgb3V0LlxuICAgKi9cbiAgYXN5bmMgdmVyc2lvbkFsbChjYWxsYmFja3M/OiB7XG4gICAgYmVmb3JlUGluZz86IChzZXJ2ZXJLZXk6IHN0cmluZykgPT4gdm9pZDtcbiAgICBhZnRlclBpbmc/OiAoc2VydmVyS2V5OiBzdHJpbmcpID0+IHZvaWQ7XG4gIH0pOiBQcm9taXNlPHtcbiAgICB2YWx1ZXM6IFJlY29yZDxzdHJpbmcsIFZhbHVlIHwgbnVsbD47XG4gIH0+IHtcbiAgICBjb25zdCB2ZXJzaW9uT2JqZWN0cyA9IGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgdGhpcy5zZXJ2ZXJLZXlzLm1hcCgoc2VydmVyS2V5KSA9PiB7XG4gICAgICAgIGNvbnN0IHNlcnZlciA9IHRoaXMuc2VydmVyS2V5VG9TZXJ2ZXIoc2VydmVyS2V5KTtcbiAgICAgICAgY2FsbGJhY2tzPy5iZWZvcmVQaW5nPy4oc2VydmVyS2V5KTtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3ZlcnNpb24oc2VydmVyKS50aGVuKChyZXNwb25zZSkgPT4ge1xuICAgICAgICAgIGNhbGxiYWNrcz8uYWZ0ZXJQaW5nPy4oc2VydmVyS2V5KTtcbiAgICAgICAgICByZXR1cm4geyBzZXJ2ZXJLZXk6IHNlcnZlcktleSwgdmFsdWU6IHJlc3BvbnNlLnZhbHVlIH07XG4gICAgICAgIH0pO1xuICAgICAgfSlcbiAgICApO1xuICAgIGNvbnN0IHZhbHVlcyA9IHZlcnNpb25PYmplY3RzLnJlZHVjZSgoYWNjdW11bGF0b3IsIHZlcnNpb25PYmplY3QpID0+IHtcbiAgICAgIGFjY3VtdWxhdG9yW3ZlcnNpb25PYmplY3Quc2VydmVyS2V5XSA9IHZlcnNpb25PYmplY3QudmFsdWU7XG4gICAgICByZXR1cm4gYWNjdW11bGF0b3I7XG4gICAgfSwge30gYXMgUmVjb3JkPHN0cmluZywgVmFsdWUgfCBudWxsPik7XG4gICAgcmV0dXJuIHsgdmFsdWVzOiB2YWx1ZXMgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDbG9zZXMgKGFicnVwdGx5KSBjb25uZWN0aW9ucyB0byBhbGwgdGhlIHNlcnZlcnMuXG4gICAqIEBzZWUgdGhpcy5xdWl0XG4gICAqL1xuICBjbG9zZSgpIHtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuc2VydmVycy5sZW5ndGg7IGkrKykge1xuICAgICAgdGhpcy5zZXJ2ZXJzW2ldLmNsb3NlKCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFBlcmZvcm0gYSBnZW5lcmljIHNpbmdsZSByZXNwb25zZSBvcGVyYXRpb24gKGdldCwgc2V0IGV0Yykgb24gb25lIHNlcnZlclxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IHRoZSBrZXkgdG8gaGFzaCB0byBnZXQgYSBzZXJ2ZXIgZnJvbSB0aGUgcG9vbFxuICAgKiBAcGFyYW0ge2J1ZmZlcn0gcmVxdWVzdCBhIGJ1ZmZlciBjb250YWluaW5nIHRoZSByZXF1ZXN0XG4gICAqIEBwYXJhbSB7bnVtYmVyfSBzZXEgdGhlIHNlcXVlbmNlIG51bWJlciBvZiB0aGUgb3BlcmF0aW9uLiBJdCBpcyB1c2VkIHRvIHBpbiB0aGUgY2FsbGJhY2tzXG4gICAgICAgICAgICAgICAgICAgICAgICAgdG8gYSBzcGVjaWZpYyBvcGVyYXRpb24gYW5kIHNob3VsZCBuZXZlciBjaGFuZ2UgZHVyaW5nIGEgYHBlcmZvcm1gLlxuICAgKiBAcGFyYW0ge251bWJlcj99IHJldHJpZXMgbnVtYmVyIG9mIHRpbWVzIHRvIHJldHJ5IHJlcXVlc3Qgb24gZmFpbHVyZVxuICAgKi9cbiAgcGVyZm9ybShcbiAgICBrZXk6IHN0cmluZyxcbiAgICByZXF1ZXN0OiBCdWZmZXIsXG4gICAgc2VxOiBudW1iZXIsXG4gICAgcmV0cmllcz86IG51bWJlclxuICApOiBQcm9taXNlPE1lc3NhZ2U+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgY29uc3Qgc2VydmVyS2V5ID0gdGhpcy5sb29rdXBLZXlUb1NlcnZlcktleShrZXkpO1xuICAgICAgY29uc3Qgc2VydmVyID0gdGhpcy5zZXJ2ZXJLZXlUb1NlcnZlcihzZXJ2ZXJLZXkpO1xuXG4gICAgICBpZiAoIXNlcnZlcikge1xuICAgICAgICByZXR1cm4gcmVqZWN0KG5ldyBFcnJvcihcIk5vIHNlcnZlcnMgYXZhaWxhYmxlXCIpKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5wZXJmb3JtT25TZXJ2ZXIoXG4gICAgICAgIHNlcnZlcixcbiAgICAgICAgcmVxdWVzdCxcbiAgICAgICAgc2VxLFxuICAgICAgICAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICByZXR1cm4gcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmVzb2x2ZShyZXNwb25zZSEpO1xuICAgICAgICB9LFxuICAgICAgICByZXRyaWVzXG4gICAgICApO1xuICAgIH0pO1xuICB9XG5cbiAgcGVyZm9ybU9uU2VydmVyKFxuICAgIHNlcnZlcjogU2VydmVyLFxuICAgIHJlcXVlc3Q6IEJ1ZmZlcixcbiAgICBzZXE6IG51bWJlcixcbiAgICBjYWxsYmFjazogUmVzcG9uc2VPckVycm9yQ2FsbGJhY2ssXG4gICAgcmV0cmllczogbnVtYmVyID0gMFxuICApIHtcbiAgICBjb25zdCBfdGhpcyA9IHRoaXM7XG5cbiAgICByZXRyaWVzID0gcmV0cmllcyB8fCB0aGlzLm9wdGlvbnMucmV0cmllcztcbiAgICBjb25zdCBvcmlnUmV0cmllcyA9IHRoaXMub3B0aW9ucy5yZXRyaWVzO1xuICAgIGNvbnN0IGxvZ2dlciA9IHRoaXMub3B0aW9ucy5sb2dnZXI7XG4gICAgY29uc3QgcmV0cnlfZGVsYXkgPSB0aGlzLm9wdGlvbnMucmV0cnlfZGVsYXk7XG5cbiAgICBjb25zdCByZXNwb25zZUhhbmRsZXI6IE9uUmVzcG9uc2VDYWxsYmFjayA9IGZ1bmN0aW9uIChyZXNwb25zZSkge1xuICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgIGNhbGxiYWNrKG51bGwsIHJlc3BvbnNlKTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgY29uc3QgZXJyb3JIYW5kbGVyOiBPbkVycm9yQ2FsbGJhY2sgPSBmdW5jdGlvbiAoZXJyb3IpIHtcbiAgICAgIGlmICgtLXJldHJpZXMgPiAwKSB7XG4gICAgICAgIC8vIFdhaXQgZm9yIHJldHJ5X2RlbGF5XG4gICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgIF90aGlzLnBlcmZvcm1PblNlcnZlcihzZXJ2ZXIsIHJlcXVlc3QsIHNlcSwgY2FsbGJhY2ssIHJldHJpZXMpO1xuICAgICAgICB9LCAxMDAwICogcmV0cnlfZGVsYXkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbG9nZ2VyLmxvZyhcbiAgICAgICAgICBcIk1lbUpTOiBTZXJ2ZXIgPFwiICtcbiAgICAgICAgICAgIHNlcnZlci5ob3N0cG9ydFN0cmluZygpICtcbiAgICAgICAgICAgIFwiPiBmYWlsZWQgYWZ0ZXIgKFwiICtcbiAgICAgICAgICAgIG9yaWdSZXRyaWVzICtcbiAgICAgICAgICAgIFwiKSByZXRyaWVzIHdpdGggZXJyb3IgLSBcIiArXG4gICAgICAgICAgICBlcnJvci5tZXNzYWdlXG4gICAgICAgICk7XG4gICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgIGNhbGxiYWNrKGVycm9yLCBudWxsKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH07XG5cbiAgICBzZXJ2ZXIub25SZXNwb25zZShzZXEsIHJlc3BvbnNlSGFuZGxlcik7XG4gICAgc2VydmVyLm9uRXJyb3Ioc2VxLCBlcnJvckhhbmRsZXIpO1xuICAgIHNlcnZlci53cml0ZShyZXF1ZXN0KTtcbiAgfVxuXG4gIC8vIEluY3JlbWVudCB0aGUgc2VxIHZhbHVlXG4gIGluY3JTZXEoKSB7XG4gICAgdGhpcy5zZXErKztcblxuICAgIC8vIFdyYXAgYHRoaXMuc2VxYCB0byAzMi1iaXRzIHNpbmNlIHRoZSBmaWVsZCB3ZSBmaXQgaXQgaW50byBpcyBvbmx5IDMyLWJpdHMuXG4gICAgdGhpcy5zZXEgJj0gMHhmZmZmZmZmZjtcblxuICAgIHJldHVybiB0aGlzLnNlcTtcbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlQW5kTG9nRXJyb3IoXG4gICAgY29tbWFuZE5hbWU6IHN0cmluZyxcbiAgICByZXNwb25zZVN0YXR1czogUmVzcG9uc2VTdGF0dXMgfCB1bmRlZmluZWRcbiAgKTogRXJyb3Ige1xuICAgIGNvbnN0IGVycm9yTWVzc2FnZSA9IGBNZW1KUyAke2NvbW1hbmROYW1lfTogJHtjb25zdGFudHMucmVzcG9uc2VTdGF0dXNUb1N0cmluZyhcbiAgICAgIHJlc3BvbnNlU3RhdHVzXG4gICAgKX1gO1xuICAgIHRoaXMub3B0aW9ucy5sb2dnZXIubG9nKGVycm9yTWVzc2FnZSk7XG4gICAgcmV0dXJuIG5ldyBFcnJvcihlcnJvck1lc3NhZ2UpO1xuICB9XG5cbiAgLyoqXG4gICAqIExvZyBhbiBlcnJvciB0byB0aGUgbG9nZ2VyLCB0aGVuIHJldHVybiB0aGUgZXJyb3IuXG4gICAqIElmIGEgY2FsbGJhY2sgaXMgZ2l2ZW4sIGNhbGwgaXQgd2l0aCBjYWxsYmFjayhlcnJvciwgbnVsbCkuXG4gICAqL1xuICBwcml2YXRlIGhhbmRsZVJlc3BvbnNlRXJyb3IoXG4gICAgY29tbWFuZE5hbWU6IHN0cmluZyxcbiAgICByZXNwb25zZVN0YXR1czogUmVzcG9uc2VTdGF0dXMgfCB1bmRlZmluZWQsXG4gICAgY2FsbGJhY2s6IHVuZGVmaW5lZCB8ICgoZXJyb3I6IEVycm9yIHwgbnVsbCwgb3RoZXI6IG51bGwpID0+IHZvaWQpXG4gICk6IEVycm9yIHtcbiAgICBjb25zdCBlcnJvciA9IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoY29tbWFuZE5hbWUsIHJlc3BvbnNlU3RhdHVzKTtcbiAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgIGNhbGxiYWNrKGVycm9yLCBudWxsKTtcbiAgICB9XG4gICAgcmV0dXJuIGVycm9yO1xuICB9XG59XG5cbmV4cG9ydCB7IENsaWVudCwgU2VydmVyLCBVdGlscywgSGVhZGVyIH07XG4iXX0= \ No newline at end of file diff --git a/src/memjs/memjs.ts b/src/memjs/memjs.ts index 66bbeaa..cec6ebf 100644 --- a/src/memjs/memjs.ts +++ b/src/memjs/memjs.ts @@ -420,17 +420,9 @@ class Client { const server = this.serverKeyToServer(serverKey); try { return await this._getMultiToServer(server, serverKeytoLookupKeys[serverKey]); - } catch (err) { - let error: Error; - if (err instanceof Error) { - error = err; - } else { - error = new Error("Unknown Error"); - (error as any).thrown = err; - } - + } catch (error) { errors.push({ - error, + error: error as Error, serverKey, keys: serverKeytoLookupKeys[serverKey] }); diff --git a/src/test/client_test.ts b/src/test/client_test.ts index ca995be..19a0d1c 100644 --- a/src/test/client_test.ts +++ b/src/test/client_test.ts @@ -491,6 +491,320 @@ test("GetMultiError", function (t) { ); }); +test("GetMultiWithErrorsSuccessful_SingleBackend", async function (t) { + let n = 0; + const dummyServer = makeDummyServer("dummyServer"); + dummyServer.write = function (requestBuf) { + const requests = Utils.parseMessages(requestBuf); + t.equal(requests.length, 4); + n += 1; + + function checkAndRespond( + request: Utils.Message, + key: string, + value: string + ) { + t.equal(key, request.key.toString()); + t.equal(constants.OP_GETKQ, request.header.opcode); + + dummyServer.respond({ + header: { + status: 0, + opaque: request.header.opaque, + opcode: request.header.opcode, + cas: Buffer.from(`cas ${key}`), + }, + key: key, + val: value, + extras: "flagshere", + }); + } + checkAndRespond(requests[0], "hello1", "world1"); + checkAndRespond(requests[1], "hello2", "world2"); + checkAndRespond(requests[2], "hello3", "world3"); + + t.equal(constants.OP_NO_OP, requests[3].header.opcode); + dummyServer.respond({ + header: { + status: 0, + opaque: requests[3].header.opaque, + opcode: requests[3].header.opcode, + }, + }); + }; + + const client = makeClient([dummyServer]); + const result = await client.getMultiWithErrors(["hello1", "hello2", "hello3"]); + t.deepEqual( + { + result: { + hello1: { + value: "world1", + extras: "flagshere", + cas: Buffer.from("cas hello1"), + }, + hello2: { + value: "world2", + extras: "flagshere", + cas: Buffer.from("cas hello2"), + }, + hello3: { + value: "world3", + extras: "flagshere", + cas: Buffer.from("cas hello3"), + }, + }, + errors: [] + } as MemJS.GetMultiWithErrorsResult<"hello1" | "hello2" | "hello3">, + result + ); + t.equal(1, n, "Ensure getMultiWithErrors is called"); +}); + +test("GetMultiWithErrorsSuccessful_MultiBackend", async function (t) { + // the mappings from key to server were computer by just manually running the default hash on them + + const dummyServer1 = makeDummyMultiGetServerResponder( + t, + { + hello2: "world2", + hello4: "world4", + }, + "dummyServer1" + ); + const dummyServer2 = makeDummyMultiGetServerResponder( + t, + { + hello1: "world1", + hello3: "world3", + }, + "dummyServer2" + ); + const servers = [dummyServer1, dummyServer2]; + + const client = makeClient(servers); + const val = await client.getMultiWithErrors(["hello1", "hello2", "hello3", "hello4"]); + + const expected: MemJS.GetMultiWithErrorsResult< + "hello1" | "hello2" | "hello3" | "hello4" + > = { + result: { + hello1: { + value: "world1", + extras: DummyMultiGetFlags, + cas: undefined, + }, + hello2: { + value: "world2", + extras: DummyMultiGetFlags, + cas: undefined, + }, + hello3: { + value: "world3", + extras: DummyMultiGetFlags, + cas: undefined, + }, + hello4: { + value: "world4", + extras: DummyMultiGetFlags, + cas: undefined, + }, + }, + errors: [], + }; + t.deepEqual(expected, val); + testAllCallbacksEmpty(t, dummyServer1); + testAllCallbacksEmpty(t, dummyServer2); +}); + +test("GetMultiWithErrorsSuccessful_MissingKeys_MultiBackend", async function (t) { + // the mappings from key to server were computed by just manually running the default hash on them + const dummyServer1 = makeDummyMultiGetServerResponder( + t, + { + hello2: undefined, + hello4: "world4", + }, + "dummyServer1" + ); + const dummyServer2 = makeDummyMultiGetServerResponder( + t, + { + hello1: "world1", + hello3: "world3", + }, + "dummyServer2" + ); + const servers = [dummyServer1, dummyServer2]; + + const client = makeClient(servers); + const val = await client.getMultiWithErrors(["hello1", "hello2", "hello3", "hello4"]); + + const expected: MemJS.GetMultiWithErrorsResult<"hello1" | "hello3" | "hello4"> = { + result: { + hello1: { + value: "world1", + extras: DummyMultiGetFlags, + cas: undefined, + }, + hello3: { + value: "world3", + extras: DummyMultiGetFlags, + cas: undefined, + }, + hello4: { + value: "world4", + extras: DummyMultiGetFlags, + cas: undefined, + }, + }, + errors: [] + }; + t.deepEqual(expected, val); + testAllCallbacksEmpty(t, dummyServer1); + testAllCallbacksEmpty(t, dummyServer2); +}); + +test("GetMultiWithErrorsError_MultiBackend", async function (t) { + // the mappings from key to server were computed by just manually running the default hash on them + const dummyServer1 = makeDummyMultiGetServerResponder( + t, + { + hello2: undefined, + hello4: "world4", + }, + "dummyServer1" + ); + const dummyServer2 = makeDummyMultiGetServerResponder( + t, + { + hello1: "world1", + hello3: "world3", + }, + "dummyServer2" + ); + dummyServer2.write = function () { + dummyServer2.error({ + name: "ErrorName", + message: "This is an expected error.", + }); + }; + const servers = [dummyServer1, dummyServer2]; + + const client = makeClient(servers); + + const val = await client.getMultiWithErrors(["hello1", "hello2", "hello3", "hello4"]); + + const expected: MemJS.GetMultiWithErrorsResult<"hello1" | "hello3" | "hello4"> = { + result: { + hello4: { + value: "world4", + extras: DummyMultiGetFlags, + cas: undefined, + }, + }, + errors: [ + { + error: { + name: "ErrorName", + message: "This is an expected error.", + }, + keys: ["hello1", "hello3"], + serverKey: "dummyServer2:undefined", // host:port + } + ], + }; + t.deepEqual(expected, val); + testAllCallbacksEmpty(t, dummyServer1); + testAllCallbacksEmpty(t, dummyServer2); +}); + +test("GetMultiWithErrorsSuccessfulWithMissingKeys", async function (t) { + const dummyServer = makeDummyMultiGetServerResponder(t, { + hello1: "world1", + hello2: undefined, + hello3: "world3", + }); + + const client = makeClient([dummyServer], { serializer: noopSerializer }); + const assertor = function ( + err: Error | null, + val: MemJS.GetMultiWithErrorsResult | null + ) { + t.equal(null, err); + }; + const val = await client.getMultiWithErrors(["hello1", "hello2", "hello3"]); + const expected: MemJS.GetMultiWithErrorsResult<"hello1" | "hello3"> = { + result: { + hello1: { + value: "world1", + extras: DummyMultiGetFlags, + cas: undefined, + }, + hello3: { + value: "world3", + extras: DummyMultiGetFlags, + cas: undefined, + }, + }, + errors: [], + }; + t.deepEqual(expected, val); + testAllCallbacksEmpty(t, dummyServer); +}); + +test("GetMultiWithErrorsError", async function (t) { + const dummyServer = makeDummyServer("dummyServer"); + dummyServer.write = function (requestBuf) { + const requests = Utils.parseMessages(requestBuf); + t.equal(requests.length, 4); + + function checkAndRespond( + request: Utils.Message, + key: string, + value: string + ) { + t.equal(key, request.key.toString()); + t.equal(constants.OP_GETKQ, request.header.opcode); + + dummyServer.respond({ + header: { + status: 0, + opaque: request.header.opaque, + opcode: request.header.opcode, + }, + key: key, + val: value, + extras: "flagshere", + }); + } + checkAndRespond(requests[0], "hello1", "world1"); + dummyServer.error({ + name: "ErrorName", + message: "This is an expected error.", + }); + }; + + const client = makeClient([dummyServer]); + + const val = await client.getMultiWithErrors(["hello1", "hello2", "hello3"]); + const expected: MemJS.GetMultiWithErrorsResult<"hello1" | "hello2" | "hello3"> = { + result: {}, + errors: [ + { + error: { + name: "ErrorName", + message: "This is an expected error.", + }, + keys: ["hello1", "hello2", "hello3"], + serverKey: "dummyServer:undefined", + } + ], + }; + t.deepEqual(expected, val); + testAllCallbacksEmpty(t, dummyServer); +}); + test("SetSuccessful", async function (t) { const casToken = Buffer.from("cas toke"); let n = 0; From bade4432e9ba6f233d3a6eb306377c0db2292721 Mon Sep 17 00:00:00 2001 From: Ben Hughes Date: Tue, 3 Oct 2023 09:14:23 -0400 Subject: [PATCH 71/79] Error out waiting clients on close, handle too many connections Previous behavior was to hang forever on unexpected close or unhandled error response. --- lib/memjs/server.d.ts.map | 2 +- lib/memjs/server.js | 14 ++++++++-- lib/memjs/utils.d.ts.map | 2 +- lib/memjs/utils.js | 8 +++++- lotofconnstest.js | 56 +++++++++++++++++++++++++++++++++++++++ src/memjs/server.ts | 12 ++++++++- src/memjs/utils.ts | 9 +++++++ src/test/server_test.js | 14 ++++++++++ 8 files changed, 111 insertions(+), 6 deletions(-) create mode 100755 lotofconnstest.js diff --git a/lib/memjs/server.d.ts.map b/lib/memjs/server.d.ts.map index 2744987..0c0c85e 100644 --- a/lib/memjs/server.d.ts.map +++ b/lib/memjs/server.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/memjs/server.ts"],"names":[],"mappings":";AAAA,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAKL,OAAO,EACR,MAAM,SAAS,CAAC;AAEjB,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,aAAK,GAAG,GAAG,MAAM,CAAC;AAElB,MAAM,WAAW,iBAAiB;IAChC,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,MAAM,WAAW,kBAAkB;IACjC,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACzB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;CACtB;AAED,qBAAa,MAAO,SAAQ,MAAM,CAAC,YAAY;IAC7C,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IAClC,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;IACpB,gBAAgB,EAAE,iBAAiB,EAAE,CAAC;IACtC,iBAAiB,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,kBAAkB,CAAA;KAAE,CAAC;IACzD,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,cAAc,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,CAAA;KAAE,CAAC;IACnD,OAAO,EAAE,aAAa,CAAC;IACvB,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAE7B,OAAO,EAAE,GAAG,CAAC,MAAM,GAAG,SAAS,CAAC;gBAG9B,IAAI,EAAE,MAAM,EAEZ,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,EACtB,QAAQ,CAAC,EAAE,MAAM,EACjB,QAAQ,CAAC,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC;IAoClC,SAAS,CAAC,IAAI,EAAE,iBAAiB;IAIjC,UAAU,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,kBAAkB;IAI7C,OAAO,CAAC,QAAQ,EAAE,OAAO;IAczB,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,eAAe;IAIvC,KAAK,CAAC,GAAG,EAAE,KAAK;IAgBhB,QAAQ;IAKR,QAAQ;IAMR,cAAc,CAAC,OAAO,EAAE,MAAM;IAO9B,eAAe,CAAC,OAAO,EAAE,MAAM;IAkB/B,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,iBAAiB;IAsFzC,KAAK,CAAC,IAAI,EAAE,MAAM;IAelB,SAAS,CAAC,IAAI,EAAE,MAAM;IAMtB,KAAK;IAML,QAAQ;IAIR,cAAc;CAGf"} \ No newline at end of file +{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/memjs/server.ts"],"names":[],"mappings":";AAAA,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAKL,OAAO,EACR,MAAM,SAAS,CAAC;AAEjB,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,aAAK,GAAG,GAAG,MAAM,CAAC;AAElB,MAAM,WAAW,iBAAiB;IAChC,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,MAAM,WAAW,kBAAkB;IACjC,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACzB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;CACtB;AAED,qBAAa,MAAO,SAAQ,MAAM,CAAC,YAAY;IAC7C,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IAClC,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;IACpB,gBAAgB,EAAE,iBAAiB,EAAE,CAAC;IACtC,iBAAiB,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,kBAAkB,CAAA;KAAE,CAAC;IACzD,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,cAAc,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,CAAA;KAAE,CAAC;IACnD,OAAO,EAAE,aAAa,CAAC;IACvB,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAE7B,OAAO,EAAE,GAAG,CAAC,MAAM,GAAG,SAAS,CAAC;gBAG9B,IAAI,EAAE,MAAM,EAEZ,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,EACtB,QAAQ,CAAC,EAAE,MAAM,EACjB,QAAQ,CAAC,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC;IAoClC,SAAS,CAAC,IAAI,EAAE,iBAAiB;IAIjC,UAAU,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,kBAAkB;IAI7C,OAAO,CAAC,QAAQ,EAAE,OAAO;IAczB,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,eAAe;IAIvC,KAAK,CAAC,GAAG,EAAE,KAAK;IAgBhB,QAAQ;IAKR,QAAQ;IAMR,cAAc,CAAC,OAAO,EAAE,MAAM;IAO9B,eAAe,CAAC,OAAO,EAAE,MAAM;IAyB/B,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,iBAAiB;IAyFzC,KAAK,CAAC,IAAI,EAAE,MAAM;IAelB,SAAS,CAAC,IAAI,EAAE,MAAM;IAMtB,KAAK;IAML,QAAQ;IAIR,cAAc;CAGf"} \ No newline at end of file diff --git a/lib/memjs/server.js b/lib/memjs/server.js index e35d5d6..e8fcefe 100644 --- a/lib/memjs/server.js +++ b/lib/memjs/server.js @@ -96,7 +96,14 @@ class Server extends events_1.default.EventEmitter { return this.responseBuffer; } responseHandler(dataBuf) { - let response = utils_1.parseMessage(this.appendToBuffer(dataBuf)); + let response; + try { + response = utils_1.parseMessage(this.appendToBuffer(dataBuf)); + } + catch (e) { + this.error(e); + return; + } let respLength; while (response) { if (response.header.opcode === 0x20) { @@ -160,6 +167,9 @@ class Server extends events_1.default.EventEmitter { }); self._socket.on("close", function () { var _a; + if (Object.keys(self.errorCallbacks).length > 0) { + self.error(new Error("socket closed unexpectedly.")); + } self.connected = false; if (self.timeoutSet) { (_a = self._socket) === null || _a === void 0 ? void 0 : _a.setTimeout(0); @@ -249,4 +259,4 @@ const timeoutHandler = function (server, sock) { }); } }; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL21lbWpzL3NlcnZlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSw4Q0FBc0I7QUFDdEIsb0RBQTRCO0FBQzVCLG1DQU1pQjtBQTBCakIsTUFBYSxNQUFPLFNBQVEsZ0JBQU0sQ0FBQyxZQUFZO0lBZ0I3QyxZQUNFLElBQVk7SUFDWixnR0FBZ0c7SUFDaEcsSUFBc0IsRUFDdEIsUUFBaUIsRUFDakIsUUFBaUIsRUFDakIsT0FBZ0M7UUFFaEMsS0FBSyxFQUFFLENBQUM7UUFDUixJQUFJLENBQUMsY0FBYyxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDdEMsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUM7UUFDakIsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUM7UUFDakIsSUFBSSxDQUFDLFNBQVMsR0FBRyxLQUFLLENBQUM7UUFDdkIsSUFBSSxDQUFDLFVBQVUsR0FBRyxLQUFLLENBQUM7UUFDeEIsSUFBSSxDQUFDLGdCQUFnQixHQUFHLEVBQUUsQ0FBQztRQUMzQixJQUFJLENBQUMsaUJBQWlCLEdBQUcsRUFBRSxDQUFDO1FBQzVCLElBQUksQ0FBQyxlQUFlLEdBQUcsRUFBRSxDQUFDO1FBQzFCLElBQUksQ0FBQyxjQUFjLEdBQUcsRUFBRSxDQUFDO1FBQ3pCLElBQUksQ0FBQyxPQUFPLEdBQUcsYUFBSyxDQUFDLE9BQU8sSUFBSSxFQUFFLEVBQUU7WUFDbEMsT0FBTyxFQUFFLEdBQUc7WUFDWixTQUFTLEVBQUUsS0FBSztZQUNoQixjQUFjLEVBQUUsRUFBRTtTQUNuQixDQUFrQixDQUFDO1FBQ3BCLElBQ0UsSUFBSSxDQUFDLE9BQU8sQ0FBQyxXQUFXLEtBQUssU0FBUztZQUN0QyxJQUFJLENBQUMsT0FBTyxDQUFDLFdBQVcsS0FBSyxJQUFJLEVBQ2pDO1lBQ0EsSUFBSSxDQUFDLE9BQU8sQ0FBQyxXQUFX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QUFNLEdBQUcsR0FBRyxpQkFBUyxFQUFFLENBQUM7SUFDeEIsTUFBTSxjQUFjLEdBQUcsTUFBTSxDQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUVqRCxJQUFJLGNBQWMsSUFBSSxHQUFHLEVBQUU7UUFDekIsb0JBQW9CO1FBQ3BCLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztRQUNYLE1BQU0sQ0FBQyxTQUFTLEdBQUcsS0FBSyxDQUFDO1FBQ3pCLE1BQU0sQ0FBQyxPQUFPLEdBQUcsU0FBUyxDQUFDO1FBQzNCLE1BQU0sQ0FBQyxVQUFVLEdBQUcsS0FBSyxDQUFDO1FBQzFCLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxLQUFLLENBQUMsdUNBQXVDLENBQUMsQ0FBQyxDQUFDO0tBQ2xFO1NBQU07UUFDTCw4QkFBOEI7UUFDOUIsTUFBTSxRQUFRLEdBQUcsY0FBYyxHQUFHLEdBQUcsQ0FBQztRQUN0QyxJQUFJLENBQUMsVUFBVSxDQUFDLFFBQVEsRUFBRTtZQUN4QixjQUFjLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQy9CLENBQUMsQ0FBQyxDQUFDO0tBQ0o7QUFDSCxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgbmV0IGZyb20gXCJuZXRcIjtcbmltcG9ydCBldmVudHMgZnJvbSBcImV2ZW50c1wiO1xuaW1wb3J0IHtcbiAgbWFrZVJlcXVlc3RCdWZmZXIsXG4gIHBhcnNlTWVzc2FnZSxcbiAgbWVyZ2UsXG4gIHRpbWVzdGFtcCxcbiAgTWVzc2FnZSxcbn0gZnJvbSBcIi4vdXRpbHNcIjtcblxuZXhwb3J0IGludGVyZmFjZSBTZXJ2ZXJPcHRpb25zIHtcbiAgdGltZW91dDogbnVtYmVyO1xuICBrZWVwQWxpdmU6IGJvb2xlYW47XG4gIGtlZXBBbGl2ZURlbGF5OiBudW1iZXI7XG4gIGNvbm50aW1lb3V0OiBudW1iZXI7XG4gIHVzZXJuYW1lPzogc3RyaW5nO1xuICBwYXNzd29yZD86IHN0cmluZztcbn1cblxudHlwZSBTZXEgPSBudW1iZXI7XG5cbmV4cG9ydCBpbnRlcmZhY2UgT25Db25uZWN0Q2FsbGJhY2sge1xuICAoc29ja2V0OiBuZXQuU29ja2V0KTogdm9pZDtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBPblJlc3BvbnNlQ2FsbGJhY2sge1xuICAobWVzc2FnZTogTWVzc2FnZSk6IHZvaWQ7XG4gIHF1aWV0PzogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBPbkVycm9yQ2FsbGJhY2sge1xuICAoZXJyb3I6IEVycm9yKTogdm9pZDtcbn1cblxuZXhwb3J0IGNsYXNzIFNlcnZlciBleHRlbmRzIGV2ZW50cy5FdmVudEVtaXR0ZXIge1xuICByZXNwb25zZUJ1ZmZlcjogQnVmZmVyO1xuICBob3N0OiBzdHJpbmc7XG4gIHBvcnQ6IHN0cmluZyB8IG51bWJlciB8IHVuZGVmaW5lZDtcbiAgY29ubmVjdGVkOiBib29sZWFuO1xuICB0aW1lb3V0U2V0OiBib29sZWFuO1xuICBjb25uZWN0Q2FsbGJhY2tzOiBPbkNvbm5lY3RDYWxsYmFja1tdO1xuICByZXNwb25zZUNhbGxiYWNrczogeyBbc2VxOiBzdHJpbmddOiBPblJlc3BvbnNlQ2FsbGJhY2sgfTtcbiAgcmVxdWVzdFRpbWVvdXRzOiBudW1iZXJbXTtcbiAgZXJyb3JDYWxsYmFja3M6IHsgW3NlcTogc3RyaW5nXTogT25FcnJvckNhbGxiYWNrIH07XG4gIG9wdGlvbnM6IFNlcnZlck9wdGlvbnM7XG4gIHVzZXJuYW1lOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gIHBhc3N3b3JkOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG5cbiAgX3NvY2tldDogbmV0LlNvY2tldCB8IHVuZGVmaW5lZDtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBob3N0OiBzdHJpbmcsXG4gICAgLyogVE9ETzogYWxsb3dpbmcgcG9ydCB0byBiZSBzdHJpbmcgb3IgdW5kZWZpbmVkIGlzIHVzZWQgYnkgdGhlIHRlc3RzLCBidXQgc2VlbXMgYmFkIG92ZXJhbGwuICovXG4gICAgcG9ydD86IHN0cmluZyB8IG51bWJlcixcbiAgICB1c2VybmFtZT86IHN0cmluZyxcbiAgICBwYXNzd29yZD86IHN0cmluZyxcbiAgICBvcHRpb25zPzogUGFydGlhbDxTZXJ2ZXJPcHRpb25zPlxuICApIHtcbiAgICBzdXBlcigpO1xuICAgIHRoaXMucmVzcG9uc2VCdWZmZXIgPSBCdWZmZXIuZnJvbShbXSk7XG4gICAgdGhpcy5ob3N0ID0gaG9zdDtcbiAgICB0aGlzLnBvcnQgPSBwb3J0O1xuICAgIHRoaXMuY29ubmVjdGVkID0gZmFsc2U7XG4gICAgdGhpcy50aW1lb3V0U2V0ID0gZmFsc2U7XG4gICAgdGhpcy5jb25uZWN0Q2FsbGJhY2tzID0gW107XG4gICAgdGhpcy5yZXNwb25zZUNhbGxiYWNrcyA9IHt9O1xuICAgIHRoaXMucmVxdWVzdFRpbWVvdXRzID0gW107XG4gICAgdGhpcy5lcnJvckNhbGxiYWNrcyA9IHt9O1xuICAgIHRoaXMub3B0aW9ucyA9IG1lcmdlKG9wdGlvbnMgfHwge30sIHtcbiAgICAgIHRpbWVvdXQ6IDAuNSxcbiAgICAgIGtlZXBBbGl2ZTogZmFsc2UsXG4gICAgICBrZWVwQWxpdmVEZWxheTogMzAsXG4gICAgfSkgYXMgU2VydmVyT3B0aW9ucztcbiAgICBpZiAoXG4gICAgICB0aGlzLm9wdGlvbnMuY29ubnRpbWVvdXQgPT09IHVuZGVmaW5lZCB8fFxuICAgICAgdGhpcy5vcHRpb25zLmNvbm50aW1lb3V0ID09PSBudWxsXG4gICAgKSB7XG4gICAgICB0aGlzLm9wdGlvbnMuY29ubnRpbWVvdXQgPSAyICogdGhpcy5vcHRpb25zLnRpbWVvdXQ7XG4gICAgfVxuICAgIHRoaXMudXNlcm5hbWUgPVxuICAgICAgdXNlcm5hbWUgfHxcbiAgICAgIHRoaXMub3B0aW9ucy51c2VybmFtZSB8fFxuICAgICAgcHJvY2Vzcy5lbnYuTUVNQ0FDSElFUl9VU0VSTkFNRSB8fFxuICAgICAgcHJvY2Vzcy5lbnYuTUVNQ0FDSEVfVVNFUk5BTUU7XG4gICAgdGhpcy5wYXNzd29yZCA9XG4gICAgICBwYXNzd29yZCB8fFxuICAgICAgdGhpcy5vcHRpb25zLnBhc3N3b3JkIHx8XG4gICAgICBwcm9jZXNzLmVudi5NRU1DQUNISUVSX1BBU1NXT1JEIHx8XG4gICAgICBwcm9jZXNzLmVudi5NRU1DQUNIRV9QQVNTV09SRDtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIG9uQ29ubmVjdChmdW5jOiBPbkNvbm5lY3RDYWxsYmFjaykge1xuICAgIHRoaXMuY29ubmVjdENhbGxiYWNrcy5wdXNoKGZ1bmMpO1xuICB9XG5cbiAgb25SZXNwb25zZShzZXE6IFNlcSwgZnVuYzogT25SZXNwb25zZUNhbGxiYWNrKSB7XG4gICAgdGhpcy5yZXNwb25zZUNhbGxiYWNrc1tzZXFdID0gZnVuYztcbiAgfVxuXG4gIHJlc3BvbmQocmVzcG9uc2U6IE1lc3NhZ2UpIHtcbiAgICBjb25zdCBjYWxsYmFjayA9IHRoaXMucmVzcG9uc2VDYWxsYmFja3NbcmVzcG9uc2UuaGVhZGVyLm9wYXF1ZV07XG4gICAgaWYgKCFjYWxsYmFjaykge1xuICAgICAgLy8gaW4gY2FzZSBvZiBhdXRoZW50aWNhdGlvbiwgbm8gY2FsbGJhY2sgaXMgcmVnaXN0ZXJlZFxuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjYWxsYmFjayhyZXNwb25zZSk7XG4gICAgaWYgKCFjYWxsYmFjay5xdWlldCB8fCByZXNwb25zZS5oZWFkZXIudG90YWxCb2R5TGVuZ3RoID09PSAwKSB7XG4gICAgICBkZWxldGUgdGhpcy5yZXNwb25zZUNhbGxiYWNrc1tyZXNwb25zZS5oZWFkZXIub3BhcXVlXTtcbiAgICAgIHRoaXMucmVxdWVzdFRpbWVvdXRzLnNoaWZ0KCk7XG4gICAgICBkZWxldGUgdGhpcy5lcnJvckNhbGxiYWNrc1tyZXNwb25zZS5oZWFkZXIub3BhcXVlXTtcbiAgICB9XG4gIH1cblxuICBvbkVycm9yKHNlcTogU2VxLCBmdW5jOiBPbkVycm9yQ2FsbGJhY2spIHtcbiAgICB0aGlzLmVycm9yQ2FsbGJhY2tzW3NlcV0gPSBmdW5jO1xuICB9XG5cbiAgZXJyb3IoZXJyOiBFcnJvcikge1xuICAgIGNvbnN0IGVycmNhbGxzID0gdGhpcy5lcnJvckNhbGxiYWNrcztcbiAgICB0aGlzLmNvbm5lY3RDYWxsYmFja3MgPSBbXTtcbiAgICB0aGlzLnJlc3BvbnNlQ2FsbGJhY2tzID0ge307XG4gICAgdGhpcy5yZXF1ZXN0VGltZW91dHMgPSBbXTtcbiAgICB0aGlzLmVycm9yQ2FsbGJhY2tzID0ge307XG4gICAgdGhpcy50aW1lb3V0U2V0ID0gZmFsc2U7XG4gICAgaWYgKHRoaXMuX3NvY2tldCkge1xuICAgICAgdGhpcy5fc29ja2V0LmRlc3Ryb3koKTtcbiAgICAgIGRlbGV0ZSB0aGlzLl9zb2NrZXQ7XG4gICAgfVxuICAgIGZvciAobGV0IGVycmNhbGwgb2YgT2JqZWN0LnZhbHVlcyhlcnJjYWxscykpIHtcbiAgICAgIGVycmNhbGwoZXJyKTtcbiAgICB9XG4gIH1cblxuICBsaXN0U2FzbCgpIHtcbiAgICBjb25zdCBidWYgPSBtYWtlUmVxdWVzdEJ1ZmZlcigweDIwLCBcIlwiLCBcIlwiLCBcIlwiKTtcbiAgICB0aGlzLndyaXRlU0FTTChidWYpO1xuICB9XG5cbiAgc2FzbEF1dGgoKSB7XG4gICAgY29uc3QgYXV0aFN0ciA9IFwiXFx4MDBcIiArIHRoaXMudXNlcm5hbWUgKyBcIlxceDAwXCIgKyB0aGlzLnBhc3N3b3JkO1xuICAgIGNvbnN0IGJ1ZiA9IG1ha2VSZXF1ZXN0QnVmZmVyKDB4MjEsIFwiUExBSU5cIiwgXCJcIiwgYXV0aFN0cik7XG4gICAgdGhpcy53cml0ZVNBU0woYnVmKTtcbiAgfVxuXG4gIGFwcGVuZFRvQnVmZmVyKGRhdGFCdWY6IEJ1ZmZlcikge1xuICAgIGNvbnN0IG9sZCA9IHRoaXMucmVzcG9uc2VCdWZmZXI7XG4gICAgdGhpcy5yZXNwb25zZUJ1ZmZlciA9IEJ1ZmZlci5hbGxvYyhvbGQubGVuZ3RoICsgZGF0YUJ1Zi5sZW5ndGgpO1xuICAgIG9sZC5jb3B5KHRoaXMucmVzcG9uc2VCdWZmZXIsIDApO1xuICAgIGRhdGFCdWYuY29weSh0aGlzLnJlc3BvbnNlQnVmZmVyLCBvbGQubGVuZ3RoKTtcbiAgICByZXR1cm4gdGhpcy5yZXNwb25zZUJ1ZmZlcjtcbiAgfVxuICByZXNwb25zZUhhbmRsZXIoZGF0YUJ1ZjogQnVmZmVyKSB7XG4gICAgbGV0IHJlc3BvbnNlID0gcGFyc2VNZXNzYWdlKHRoaXMuYXBwZW5kVG9CdWZmZXIoZGF0YUJ1ZikpO1xuICAgIGxldCByZXNwTGVuZ3RoOiBudW1iZXI7XG4gICAgd2hpbGUgKHJlc3BvbnNlKSB7XG4gICAgICBpZiAocmVzcG9uc2UuaGVhZGVyLm9wY29kZSA9PT0gMHgyMCkge1xuICAgICAgICB0aGlzLnNhc2xBdXRoKCk7XG4gICAgICB9IGVsc2UgaWYgKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMgPT09ICgweDIwIGFzIGFueSkgLyogVE9ETzogd3RmPyAqLykge1xuICAgICAgICB0aGlzLmVycm9yKG5ldyBFcnJvcihcIk1lbWNhY2hlZCBzZXJ2ZXIgYXV0aGVudGljYXRpb24gZmFpbGVkIVwiKSk7XG4gICAgICB9IGVsc2UgaWYgKHJlc3BvbnNlLmhlYWRlci5vcGNvZGUgPT09IDB4MjEpIHtcbiAgICAgICAgdGhpcy5lbWl0KFwiYXV0aGVudGljYXRlZFwiKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMucmVzcG9uZChyZXNwb25zZSk7XG4gICAgICB9XG4gICAgICByZXNwTGVuZ3RoID0gcmVzcG9uc2UuaGVhZGVyLnRvdGFsQm9keUxlbmd0aCArIDI0O1xuICAgICAgdGhpcy5yZXNwb25zZUJ1ZmZlciA9IHRoaXMucmVzcG9uc2VCdWZmZXIuc2xpY2UocmVzcExlbmd0aCk7XG4gICAgICByZXNwb25zZSA9IHBhcnNlTWVzc2FnZSh0aGlzLnJlc3BvbnNlQnVmZmVyKTtcbiAgICB9XG4gIH1cbiAgc29jayhzYXNsOiBib29sZWFuLCBnbzogT25Db25uZWN0Q2FsbGJhY2spIHtcbiAgICBjb25zdCBzZWxmID0gdGhpcztcblxuICAgIGlmICghc2VsZi5fc29ja2V0KSB7XG4gICAgICAvLyBDQVNFIDE6IGNvbXBsZXRlbHkgbmV3IHNvY2tldFxuICAgICAgc2VsZi5jb25uZWN0ZWQgPSBmYWxzZTtcbiAgICAgIHNlbGYuX3NvY2tldCA9IG5ldC5jb25uZWN0KFxuICAgICAgICAvKiBUT0RPOiBhbGxvd2luZyBwb3J0IHRvIGJlIHN0cmluZyBvciB1bmRlZmluZWQgaXMgdXNlZCBieSB0aGUgdGVzdHMsIGJ1dCBzZWVtcyBiYWQgb3ZlcmFsbC4gKi9cbiAgICAgICAgdHlwZW9mIHRoaXMucG9ydCA9PT0gXCJzdHJpbmdcIlxuICAgICAgICAgID8gcGFyc2VJbnQodGhpcy5wb3J0LCAxMClcbiAgICAgICAgICA6IHRoaXMucG9ydCB8fCAxMTIxMSxcbiAgICAgICAgdGhpcy5ob3N0LFxuICAgICAgICBmdW5jdGlvbiAodGhpczogbmV0LlNvY2tldCkge1xuICAgICAgICAgIC8vIFNBU0wgYXV0aGVudGljYXRpb24gaGFuZGxlclxuICAgICAgICAgIHNlbGYub25jZShcImF1dGhlbnRpY2F0ZWRcIiwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKHNlbGYuX3NvY2tldCkge1xuICAgICAgICAgICAgICBjb25zdCBzb2NrZXQgPSBzZWxmLl9zb2NrZXQ7XG4gICAgICAgICAgICAgIHNlbGYuY29ubmVjdGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgLy8gY2FuY2VsIGNvbm5lY3Rpb24gdGltZW91dFxuICAgICAgICAgICAgICBzZWxmLl9zb2NrZXQuc2V0VGltZW91dCgwKTtcbiAgICAgICAgICAgICAgc2VsZi50aW1lb3V0U2V0ID0gZmFsc2U7XG4gICAgICAgICAgICAgIC8vIHJ1biBhY3R1YWwgcmVxdWVzdChzKVxuICAgICAgICAgICAgICBnbyhzZWxmLl9zb2NrZXQpO1xuICAgICAgICAgICAgICBzZWxmLmNvbm5lY3RDYWxsYmFja3MuZm9yRWFjaChmdW5jdGlvbiAoY2IpIHtcbiAgICAgICAgICAgICAgICBjYihzb2NrZXQpO1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgc2VsZi5jb25uZWN0Q2FsbGJhY2tzID0gW107XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICAvLyBzZXR1cCByZXNwb25zZSBoYW5kbGVyXG4gICAgICAgICAgdGhpcy5vbihcImRhdGFcIiwgZnVuY3Rpb24gKGRhdGFCdWYpIHtcbiAgICAgICAgICAgIHNlbGYucmVzcG9uc2VIYW5kbGVyKGRhdGFCdWYpO1xuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgLy8ga2ljayBvZiBTQVNMIGlmIG5lZWRlZFxuICAgICAgICAgIGlmIChzZWxmLnVzZXJuYW1lICYmIHNlbGYucGFzc3dvcmQpIHtcbiAgICAgICAgICAgIHNlbGYubGlzdFNhc2woKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc2VsZi5lbWl0KFwiYXV0aGVudGljYXRlZFwiKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICk7XG5cbiAgICAgIC8vIHNldHVwIGVycm9yIGhhbmRsZXJcbiAgICAgIHNlbGYuX3NvY2tldC5vbihcImVycm9yXCIsIGZ1bmN0aW9uIChlcnJvcikge1xuICAgICAgICBzZWxmLmVycm9yKGVycm9yKTtcbiAgICAgIH0pO1xuXG4gICAgICBzZWxmLl9zb2NrZXQub24oXCJjbG9zZVwiLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHNlbGYuY29ubmVjdGVkID0gZmFsc2U7XG4gICAgICAgIGlmIChzZWxmLnRpbWVvdXRTZXQpIHtcbiAgICAgICAgICBzZWxmLl9zb2NrZXQ/LnNldFRpbWVvdXQoMCk7XG4gICAgICAgICAgc2VsZi50aW1lb3V0U2V0ID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgc2VsZi5fc29ja2V0ID0gdW5kZWZpbmVkO1xuICAgICAgfSk7XG5cbiAgICAgIC8vIHNldHVwIGNvbm5lY3Rpb24gdGltZW91dCBoYW5kbGVyXG4gICAgICBzZWxmLnRpbWVvdXRTZXQgPSB0cnVlO1xuICAgICAgc2VsZi5fc29ja2V0LnNldFRpbWVvdXQoXG4gICAgICAgIHNlbGYub3B0aW9ucy5jb25udGltZW91dCAqIDEwMDAsXG4gICAgICAgIGZ1bmN0aW9uICh0aGlzOiBuZXQuU29ja2V0KSB7XG4gICAgICAgICAgc2VsZi50aW1lb3V0U2V0ID0gZmFsc2U7XG4gICAgICAgICAgaWYgKCFzZWxmLmNvbm5lY3RlZCkge1xuICAgICAgICAgICAgdGhpcy5lbmQoKTtcbiAgICAgICAgICAgIHNlbGYuX3NvY2tldCA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIHNlbGYuZXJyb3IobmV3IEVycm9yKFwic29ja2V0IHRpbWVkIG91dCBjb25uZWN0aW5nIHRvIHNlcnZlci5cIikpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgKTtcblxuICAgICAgLy8gdXNlIFRDUCBrZWVwLWFsaXZlXG4gICAgICBzZWxmLl9zb2NrZXQuc2V0S2VlcEFsaXZlKFxuICAgICAgICBzZWxmLm9wdGlvbnMua2VlcEFsaXZlLFxuICAgICAgICBzZWxmLm9wdGlvbnMua2VlcEFsaXZlRGVsYXkgKiAxMDAwXG4gICAgICApO1xuICAgIH0gZWxzZSBpZiAoIXNlbGYuY29ubmVjdGVkICYmICFzYXNsKSB7XG4gICAgICAvLyBDQVNFIDI6IHNvY2tldCBleGlzdHMsIGJ1dCBzdGlsbCBjb25uZWN0aW5nIC8gYXV0aGVudGljYXRpbmdcbiAgICAgIHNlbGYub25Db25uZWN0KGdvKTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gQ0FTRSAzOiBzb2NrZXQgZXhpc3RzIGFuZCBjb25uZWN0ZWQgLyByZWFkeSB0byB1c2VcbiAgICAgIGdvKHNlbGYuX3NvY2tldCk7XG4gICAgfVxuICB9XG5cbiAgd3JpdGUoYmxvYjogQnVmZmVyKSB7XG4gICAgY29uc3Qgc2VsZiA9IHRoaXM7XG4gICAgY29uc3QgZGVhZGxpbmUgPSBNYXRoLnJvdW5kKHNlbGYub3B0aW9ucy50aW1lb3V0ICogMTAwMCk7XG4gICAgdGhpcy5zb2NrKGZhbHNlLCBmdW5jdGlvbiAocykge1xuICAgICAgcy53cml0ZShibG9iKTtcbiAgICAgIHNlbGYucmVxdWVzdFRpbWVvdXRzLnB1c2godGltZXN0YW1wKCkgKyBkZWFkbGluZSk7XG4gICAgICBpZiAoIXNlbGYudGltZW91dFNldCkge1xuICAgICAgICBzZWxmLnRpbWVvdXRTZXQgPSB0cnVlO1xuICAgICAgICBzLnNldFRpbWVvdXQoZGVhZGxpbmUsIGZ1bmN0aW9uICh0aGlzOiBuZXQuU29ja2V0KSB7XG4gICAgICAgICAgdGltZW91dEhhbmRsZXIoc2VsZiwgdGhpcyk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgd3JpdGVTQVNMKGJsb2I6IEJ1ZmZlcikge1xuICAgIHRoaXMuc29jayh0cnVlLCBmdW5jdGlvbiAocykge1xuICAgICAgcy53cml0ZShibG9iKTtcbiAgICB9KTtcbiAgfVxuXG4gIGNsb3NlKCkge1xuICAgIGlmICh0aGlzLl9zb2NrZXQpIHtcbiAgICAgIHRoaXMuX3NvY2tldC5lbmQoKTtcbiAgICB9XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICByZXR1cm4gXCI8U2VydmVyIFwiICsgdGhpcy5ob3N0ICsgXCI6XCIgKyB0aGlzLnBvcnQgKyBcIj5cIjtcbiAgfVxuXG4gIGhvc3Rwb3J0U3RyaW5nKCkge1xuICAgIHJldHVybiB0aGlzLmhvc3QgKyBcIjpcIiArIHRoaXMucG9ydDtcbiAgfVxufVxuXG4vLyBXZSBoYW5kbGUgdHJhY2tpbmcgdGltZW91dHMgd2l0aCBhbiBhcnJheSBvZiBkZWFkbGluZXMgKHJlcXVlc3RUaW1lb3V0cyksIGFzXG4vLyBub2RlIGRvZXNuJ3QgbGlrZSB1cyBzZXR0aW5nIHVwIGxvdHMgb2YgdGltZXJzLCBhbmQgdXNpbmcganVzdCBvbmUgaXMgbW9yZVxuLy8gZWZmaWNpZW50IGFueXdheS5cbmNvbnN0IHRpbWVvdXRIYW5kbGVyID0gZnVuY3Rpb24gKHNlcnZlcjogU2VydmVyLCBzb2NrOiBuZXQuU29ja2V0KSB7XG4gIGlmIChzZXJ2ZXIucmVxdWVzdFRpbWVvdXRzLmxlbmd0aCA9PT0gMCkge1xuICAgIC8vIG5vdGhpbmcgYWN0aXZlXG4gICAgc2VydmVyLnRpbWVvdXRTZXQgPSBmYWxzZTtcbiAgICByZXR1cm47XG4gIH1cblxuICAvLyBzb21lIHJlcXVlc3RzIG91dHN0YW5kaW5nLCBjaGVjayBpZiBhbnkgaGF2ZSB0aW1lZC1vdXRcbiAgY29uc3Qgbm93ID0gdGltZXN0YW1wKCk7XG4gIGNvbnN0IHNvb25lc3RUaW1lb3V0ID0gc2VydmVyLnJlcXVlc3RUaW1lb3V0c1swXTtcblxuICBpZiAoc29vbmVzdFRpbWVvdXQgPD0gbm93KSB7XG4gICAgLy8gdGltZW91dCBvY2N1cnJlZCFcbiAgICBzb2NrLmVuZCgpO1xuICAgIHNlcnZlci5jb25uZWN0ZWQgPSBmYWxzZTtcbiAgICBzZXJ2ZXIuX3NvY2tldCA9IHVuZGVmaW5lZDtcbiAgICBzZXJ2ZXIudGltZW91dFNldCA9IGZhbHNlO1xuICAgIHNlcnZlci5lcnJvcihuZXcgRXJyb3IoXCJzb2NrZXQgdGltZWQgb3V0IHdhaXRpbmcgb24gcmVzcG9uc2UuXCIpKTtcbiAgfSBlbHNlIHtcbiAgICAvLyBubyB0aW1lb3V0ISBTZXR1cCBuZXh0IG9uZS5cbiAgICBjb25zdCBkZWFkbGluZSA9IHNvb25lc3RUaW1lb3V0IC0gbm93O1xuICAgIHNvY2suc2V0VGltZW91dChkZWFkbGluZSwgZnVuY3Rpb24gKCkge1xuICAgICAgdGltZW91dEhhbmRsZXIoc2VydmVyLCBzb2NrKTtcbiAgICB9KTtcbiAgfVxufTtcbiJdfQ== \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL21lbWpzL3NlcnZlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSw4Q0FBc0I7QUFDdEIsb0RBQTRCO0FBQzVCLG1DQU1pQjtBQTBCakIsTUFBYSxNQUFPLFNBQVEsZ0JBQU0sQ0FBQyxZQUFZO0lBZ0I3QyxZQUNFLElBQVk7SUFDWixnR0FBZ0c7SUFDaEcsSUFBc0IsRUFDdEIsUUFBaUIsRUFDakIsUUFBaUIsRUFDakIsT0FBZ0M7UUFFaEMsS0FBSyxFQUFFLENBQUM7UUFDUixJQUFJLENBQUMsY0FBYyxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDdEMsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUM7UUFDakIsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUM7UUFDakIsSUFBSSxDQUFDLFNBQVMsR0FBRyxLQUFLLENBQUM7UUFDdkIsSUFBSSxDQUFDLFVBQVUsR0FBRyxLQUFLLENBQUM7UUFDeEIsSUFBSSxDQUFDLGdCQUFnQixHQUFHLEVBQUUsQ0FBQztRQUMzQixJQUFJLENBQUMsaUJBQWlCLEdBQUcsRUFBRSxDQUFDO1FBQzVCLElBQUksQ0FBQyxlQUFlLEdBQUcsRUFBRSxDQUFDO1FBQzFCLElBQUksQ0FBQyxjQUFjLEdBQUcsRUFBRSxDQUFDO1FBQ3pCLElBQUksQ0FBQyxPQUFPLEdBQUcsYUFBSyxDQUFDLE9BQU8sSUFBSSxFQUFFLEVBQUU7WUFDbEMsT0FBTyxFQUFFLEdBQUc7WUFDWixTQUFTLEVBQUUsS0FBSztZQUNoQixjQUFjLEVBQUUsRUFBRTtTQUNuQixDQUFrQixDQUFDO1FBQ3BCLElBQ0UsSUFBSSxDQUFDLE9BQU8sQ0FBQyxXQUFXLEtBQUssU0FBUztZQUN0QyxJQUFJLENBQUMsT0FBTyxDQUFDLFdBQVcsS0FBSyxJQUFJLEVBQ2pDO1lBQ0EsSUFBSSxDQUFDLE9BQU8sQ0FBQyxXQUFX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LElBQUksQ0FBQztJQUNyQyxDQUFDO0NBQ0Y7QUExUUQsd0JBMFFDO0FBRUQsK0VBQStFO0FBQy9FLDZFQUE2RTtBQUM3RSxvQkFBb0I7QUFDcEIsTUFBTSxjQUFjLEdBQUcsVUFBVSxNQUFjLEVBQUUsSUFBZ0I7SUFDL0QsSUFBSSxNQUFNLENBQUMsZUFBZSxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUU7UUFDdkMsaUJBQWlCO1FBQ2pCLE1BQU0sQ0FBQyxVQUFVLEdBQUcsS0FBSyxDQUFDO1FBQzFCLE9BQU87S0FDUjtJQUVELHlEQUF5RDtJQUN6RCxNQUFNLEdBQUcsR0FBRyxpQkFBUyxFQUFFLENBQUM7SUFDeEIsTUFBTSxjQUFjLEdBQUcsTUFBTSxDQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUVqRCxJQUFJLGNBQWMsSUFBSSxHQUFHLEVBQUU7UUFDekIsb0JBQW9CO1FBQ3BCLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztRQUNYLE1BQU0sQ0FBQyxTQUFTLEdBQUcsS0FBSyxDQUFDO1FBQ3pCLE1BQU0sQ0FBQyxPQUFPLEdBQUcsU0FBUyxDQUFDO1FBQzNCLE1BQU0sQ0FBQyxVQUFVLEdBQUcsS0FBSyxDQUFDO1FBQzFCLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxLQUFLLENBQUMsdUNBQXVDLENBQUMsQ0FBQyxDQUFDO0tBQ2xFO1NBQU07UUFDTCw4QkFBOEI7UUFDOUIsTUFBTSxRQUFRLEdBQUcsY0FBYyxHQUFHLEdBQUcsQ0FBQztRQUN0QyxJQUFJLENBQUMsVUFBVSxDQUFDLFFBQVEsRUFBRTtZQUN4QixjQUFjLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQy9CLENBQUMsQ0FBQyxDQUFDO0tBQ0o7QUFDSCxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgbmV0IGZyb20gXCJuZXRcIjtcbmltcG9ydCBldmVudHMgZnJvbSBcImV2ZW50c1wiO1xuaW1wb3J0IHtcbiAgbWFrZVJlcXVlc3RCdWZmZXIsXG4gIHBhcnNlTWVzc2FnZSxcbiAgbWVyZ2UsXG4gIHRpbWVzdGFtcCxcbiAgTWVzc2FnZSxcbn0gZnJvbSBcIi4vdXRpbHNcIjtcblxuZXhwb3J0IGludGVyZmFjZSBTZXJ2ZXJPcHRpb25zIHtcbiAgdGltZW91dDogbnVtYmVyO1xuICBrZWVwQWxpdmU6IGJvb2xlYW47XG4gIGtlZXBBbGl2ZURlbGF5OiBudW1iZXI7XG4gIGNvbm50aW1lb3V0OiBudW1iZXI7XG4gIHVzZXJuYW1lPzogc3RyaW5nO1xuICBwYXNzd29yZD86IHN0cmluZztcbn1cblxudHlwZSBTZXEgPSBudW1iZXI7XG5cbmV4cG9ydCBpbnRlcmZhY2UgT25Db25uZWN0Q2FsbGJhY2sge1xuICAoc29ja2V0OiBuZXQuU29ja2V0KTogdm9pZDtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBPblJlc3BvbnNlQ2FsbGJhY2sge1xuICAobWVzc2FnZTogTWVzc2FnZSk6IHZvaWQ7XG4gIHF1aWV0PzogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBPbkVycm9yQ2FsbGJhY2sge1xuICAoZXJyb3I6IEVycm9yKTogdm9pZDtcbn1cblxuZXhwb3J0IGNsYXNzIFNlcnZlciBleHRlbmRzIGV2ZW50cy5FdmVudEVtaXR0ZXIge1xuICByZXNwb25zZUJ1ZmZlcjogQnVmZmVyO1xuICBob3N0OiBzdHJpbmc7XG4gIHBvcnQ6IHN0cmluZyB8IG51bWJlciB8IHVuZGVmaW5lZDtcbiAgY29ubmVjdGVkOiBib29sZWFuO1xuICB0aW1lb3V0U2V0OiBib29sZWFuO1xuICBjb25uZWN0Q2FsbGJhY2tzOiBPbkNvbm5lY3RDYWxsYmFja1tdO1xuICByZXNwb25zZUNhbGxiYWNrczogeyBbc2VxOiBzdHJpbmddOiBPblJlc3BvbnNlQ2FsbGJhY2sgfTtcbiAgcmVxdWVzdFRpbWVvdXRzOiBudW1iZXJbXTtcbiAgZXJyb3JDYWxsYmFja3M6IHsgW3NlcTogc3RyaW5nXTogT25FcnJvckNhbGxiYWNrIH07XG4gIG9wdGlvbnM6IFNlcnZlck9wdGlvbnM7XG4gIHVzZXJuYW1lOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gIHBhc3N3b3JkOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG5cbiAgX3NvY2tldDogbmV0LlNvY2tldCB8IHVuZGVmaW5lZDtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBob3N0OiBzdHJpbmcsXG4gICAgLyogVE9ETzogYWxsb3dpbmcgcG9ydCB0byBiZSBzdHJpbmcgb3IgdW5kZWZpbmVkIGlzIHVzZWQgYnkgdGhlIHRlc3RzLCBidXQgc2VlbXMgYmFkIG92ZXJhbGwuICovXG4gICAgcG9ydD86IHN0cmluZyB8IG51bWJlcixcbiAgICB1c2VybmFtZT86IHN0cmluZyxcbiAgICBwYXNzd29yZD86IHN0cmluZyxcbiAgICBvcHRpb25zPzogUGFydGlhbDxTZXJ2ZXJPcHRpb25zPlxuICApIHtcbiAgICBzdXBlcigpO1xuICAgIHRoaXMucmVzcG9uc2VCdWZmZXIgPSBCdWZmZXIuZnJvbShbXSk7XG4gICAgdGhpcy5ob3N0ID0gaG9zdDtcbiAgICB0aGlzLnBvcnQgPSBwb3J0O1xuICAgIHRoaXMuY29ubmVjdGVkID0gZmFsc2U7XG4gICAgdGhpcy50aW1lb3V0U2V0ID0gZmFsc2U7XG4gICAgdGhpcy5jb25uZWN0Q2FsbGJhY2tzID0gW107XG4gICAgdGhpcy5yZXNwb25zZUNhbGxiYWNrcyA9IHt9O1xuICAgIHRoaXMucmVxdWVzdFRpbWVvdXRzID0gW107XG4gICAgdGhpcy5lcnJvckNhbGxiYWNrcyA9IHt9O1xuICAgIHRoaXMub3B0aW9ucyA9IG1lcmdlKG9wdGlvbnMgfHwge30sIHtcbiAgICAgIHRpbWVvdXQ6IDAuNSxcbiAgICAgIGtlZXBBbGl2ZTogZmFsc2UsXG4gICAgICBrZWVwQWxpdmVEZWxheTogMzAsXG4gICAgfSkgYXMgU2VydmVyT3B0aW9ucztcbiAgICBpZiAoXG4gICAgICB0aGlzLm9wdGlvbnMuY29ubnRpbWVvdXQgPT09IHVuZGVmaW5lZCB8fFxuICAgICAgdGhpcy5vcHRpb25zLmNvbm50aW1lb3V0ID09PSBudWxsXG4gICAgKSB7XG4gICAgICB0aGlzLm9wdGlvbnMuY29ubnRpbWVvdXQgPSAyICogdGhpcy5vcHRpb25zLnRpbWVvdXQ7XG4gICAgfVxuICAgIHRoaXMudXNlcm5hbWUgPVxuICAgICAgdXNlcm5hbWUgfHxcbiAgICAgIHRoaXMub3B0aW9ucy51c2VybmFtZSB8fFxuICAgICAgcHJvY2Vzcy5lbnYuTUVNQ0FDSElFUl9VU0VSTkFNRSB8fFxuICAgICAgcHJvY2Vzcy5lbnYuTUVNQ0FDSEVfVVNFUk5BTUU7XG4gICAgdGhpcy5wYXNzd29yZCA9XG4gICAgICBwYXNzd29yZCB8fFxuICAgICAgdGhpcy5vcHRpb25zLnBhc3N3b3JkIHx8XG4gICAgICBwcm9jZXNzLmVudi5NRU1DQUNISUVSX1BBU1NXT1JEIHx8XG4gICAgICBwcm9jZXNzLmVudi5NRU1DQUNIRV9QQVNTV09SRDtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIG9uQ29ubmVjdChmdW5jOiBPbkNvbm5lY3RDYWxsYmFjaykge1xuICAgIHRoaXMuY29ubmVjdENhbGxiYWNrcy5wdXNoKGZ1bmMpO1xuICB9XG5cbiAgb25SZXNwb25zZShzZXE6IFNlcSwgZnVuYzogT25SZXNwb25zZUNhbGxiYWNrKSB7XG4gICAgdGhpcy5yZXNwb25zZUNhbGxiYWNrc1tzZXFdID0gZnVuYztcbiAgfVxuXG4gIHJlc3BvbmQocmVzcG9uc2U6IE1lc3NhZ2UpIHtcbiAgICBjb25zdCBjYWxsYmFjayA9IHRoaXMucmVzcG9uc2VDYWxsYmFja3NbcmVzcG9uc2UuaGVhZGVyLm9wYXF1ZV07XG4gICAgaWYgKCFjYWxsYmFjaykge1xuICAgICAgLy8gaW4gY2FzZSBvZiBhdXRoZW50aWNhdGlvbiwgbm8gY2FsbGJhY2sgaXMgcmVnaXN0ZXJlZFxuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjYWxsYmFjayhyZXNwb25zZSk7XG4gICAgaWYgKCFjYWxsYmFjay5xdWlldCB8fCByZXNwb25zZS5oZWFkZXIudG90YWxCb2R5TGVuZ3RoID09PSAwKSB7XG4gICAgICBkZWxldGUgdGhpcy5yZXNwb25zZUNhbGxiYWNrc1tyZXNwb25zZS5oZWFkZXIub3BhcXVlXTtcbiAgICAgIHRoaXMucmVxdWVzdFRpbWVvdXRzLnNoaWZ0KCk7XG4gICAgICBkZWxldGUgdGhpcy5lcnJvckNhbGxiYWNrc1tyZXNwb25zZS5oZWFkZXIub3BhcXVlXTtcbiAgICB9XG4gIH1cblxuICBvbkVycm9yKHNlcTogU2VxLCBmdW5jOiBPbkVycm9yQ2FsbGJhY2spIHtcbiAgICB0aGlzLmVycm9yQ2FsbGJhY2tzW3NlcV0gPSBmdW5jO1xuICB9XG5cbiAgZXJyb3IoZXJyOiBFcnJvcikge1xuICAgIGNvbnN0IGVycmNhbGxzID0gdGhpcy5lcnJvckNhbGxiYWNrcztcbiAgICB0aGlzLmNvbm5lY3RDYWxsYmFja3MgPSBbXTtcbiAgICB0aGlzLnJlc3BvbnNlQ2FsbGJhY2tzID0ge307XG4gICAgdGhpcy5yZXF1ZXN0VGltZW91dHMgPSBbXTtcbiAgICB0aGlzLmVycm9yQ2FsbGJhY2tzID0ge307XG4gICAgdGhpcy50aW1lb3V0U2V0ID0gZmFsc2U7XG4gICAgaWYgKHRoaXMuX3NvY2tldCkge1xuICAgICAgdGhpcy5fc29ja2V0LmRlc3Ryb3koKTtcbiAgICAgIGRlbGV0ZSB0aGlzLl9zb2NrZXQ7XG4gICAgfVxuICAgIGZvciAobGV0IGVycmNhbGwgb2YgT2JqZWN0LnZhbHVlcyhlcnJjYWxscykpIHtcbiAgICAgIGVycmNhbGwoZXJyKTtcbiAgICB9XG4gIH1cblxuICBsaXN0U2FzbCgpIHtcbiAgICBjb25zdCBidWYgPSBtYWtlUmVxdWVzdEJ1ZmZlcigweDIwLCBcIlwiLCBcIlwiLCBcIlwiKTtcbiAgICB0aGlzLndyaXRlU0FTTChidWYpO1xuICB9XG5cbiAgc2FzbEF1dGgoKSB7XG4gICAgY29uc3QgYXV0aFN0ciA9IFwiXFx4MDBcIiArIHRoaXMudXNlcm5hbWUgKyBcIlxceDAwXCIgKyB0aGlzLnBhc3N3b3JkO1xuICAgIGNvbnN0IGJ1ZiA9IG1ha2VSZXF1ZXN0QnVmZmVyKDB4MjEsIFwiUExBSU5cIiwgXCJcIiwgYXV0aFN0cik7XG4gICAgdGhpcy53cml0ZVNBU0woYnVmKTtcbiAgfVxuXG4gIGFwcGVuZFRvQnVmZmVyKGRhdGFCdWY6IEJ1ZmZlcikge1xuICAgIGNvbnN0IG9sZCA9IHRoaXMucmVzcG9uc2VCdWZmZXI7XG4gICAgdGhpcy5yZXNwb25zZUJ1ZmZlciA9IEJ1ZmZlci5hbGxvYyhvbGQubGVuZ3RoICsgZGF0YUJ1Zi5sZW5ndGgpO1xuICAgIG9sZC5jb3B5KHRoaXMucmVzcG9uc2VCdWZmZXIsIDApO1xuICAgIGRhdGFCdWYuY29weSh0aGlzLnJlc3BvbnNlQnVmZmVyLCBvbGQubGVuZ3RoKTtcbiAgICByZXR1cm4gdGhpcy5yZXNwb25zZUJ1ZmZlcjtcbiAgfVxuICByZXNwb25zZUhhbmRsZXIoZGF0YUJ1ZjogQnVmZmVyKSB7XG4gICAgbGV0IHJlc3BvbnNlOiBNZXNzYWdlIHwgZmFsc2U7XG4gICAgdHJ5IHtcbiAgICAgIHJlc3BvbnNlID0gcGFyc2VNZXNzYWdlKHRoaXMuYXBwZW5kVG9CdWZmZXIoZGF0YUJ1ZikpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHRoaXMuZXJyb3IoZSBhcyBFcnJvcik7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgbGV0IHJlc3BMZW5ndGg6IG51bWJlcjtcbiAgICB3aGlsZSAocmVzcG9uc2UpIHtcbiAgICAgIGlmIChyZXNwb25zZS5oZWFkZXIub3Bjb2RlID09PSAweDIwKSB7XG4gICAgICAgIHRoaXMuc2FzbEF1dGgoKTtcbiAgICAgIH0gZWxzZSBpZiAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cyA9PT0gKDB4MjAgYXMgYW55KSAvKiBUT0RPOiB3dGY/ICovKSB7XG4gICAgICAgIHRoaXMuZXJyb3IobmV3IEVycm9yKFwiTWVtY2FjaGVkIHNlcnZlciBhdXRoZW50aWNhdGlvbiBmYWlsZWQhXCIpKTtcbiAgICAgIH0gZWxzZSBpZiAocmVzcG9uc2UuaGVhZGVyLm9wY29kZSA9PT0gMHgyMSkge1xuICAgICAgICB0aGlzLmVtaXQoXCJhdXRoZW50aWNhdGVkXCIpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5yZXNwb25kKHJlc3BvbnNlKTtcbiAgICAgIH1cbiAgICAgIHJlc3BMZW5ndGggPSByZXNwb25zZS5oZWFkZXIudG90YWxCb2R5TGVuZ3RoICsgMjQ7XG4gICAgICB0aGlzLnJlc3BvbnNlQnVmZmVyID0gdGhpcy5yZXNwb25zZUJ1ZmZlci5zbGljZShyZXNwTGVuZ3RoKTtcbiAgICAgIHJlc3BvbnNlID0gcGFyc2VNZXNzYWdlKHRoaXMucmVzcG9uc2VCdWZmZXIpO1xuICAgIH1cbiAgfVxuICBzb2NrKHNhc2w6IGJvb2xlYW4sIGdvOiBPbkNvbm5lY3RDYWxsYmFjaykge1xuICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuXG4gICAgaWYgKCFzZWxmLl9zb2NrZXQpIHtcbiAgICAgIC8vIENBU0UgMTogY29tcGxldGVseSBuZXcgc29ja2V0XG4gICAgICBzZWxmLmNvbm5lY3RlZCA9IGZhbHNlO1xuICAgICAgc2VsZi5fc29ja2V0ID0gbmV0LmNvbm5lY3QoXG4gICAgICAgIC8qIFRPRE86IGFsbG93aW5nIHBvcnQgdG8gYmUgc3RyaW5nIG9yIHVuZGVmaW5lZCBpcyB1c2VkIGJ5IHRoZSB0ZXN0cywgYnV0IHNlZW1zIGJhZCBvdmVyYWxsLiAqL1xuICAgICAgICB0eXBlb2YgdGhpcy5wb3J0ID09PSBcInN0cmluZ1wiXG4gICAgICAgICAgPyBwYXJzZUludCh0aGlzLnBvcnQsIDEwKVxuICAgICAgICAgIDogdGhpcy5wb3J0IHx8IDExMjExLFxuICAgICAgICB0aGlzLmhvc3QsXG4gICAgICAgIGZ1bmN0aW9uICh0aGlzOiBuZXQuU29ja2V0KSB7XG4gICAgICAgICAgLy8gU0FTTCBhdXRoZW50aWNhdGlvbiBoYW5kbGVyXG4gICAgICAgICAgc2VsZi5vbmNlKFwiYXV0aGVudGljYXRlZFwiLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAoc2VsZi5fc29ja2V0KSB7XG4gICAgICAgICAgICAgIGNvbnN0IHNvY2tldCA9IHNlbGYuX3NvY2tldDtcbiAgICAgICAgICAgICAgc2VsZi5jb25uZWN0ZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAvLyBjYW5jZWwgY29ubmVjdGlvbiB0aW1lb3V0XG4gICAgICAgICAgICAgIHNlbGYuX3NvY2tldC5zZXRUaW1lb3V0KDApO1xuICAgICAgICAgICAgICBzZWxmLnRpbWVvdXRTZXQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgLy8gcnVuIGFjdHVhbCByZXF1ZXN0KHMpXG4gICAgICAgICAgICAgIGdvKHNlbGYuX3NvY2tldCk7XG4gICAgICAgICAgICAgIHNlbGYuY29ubmVjdENhbGxiYWNrcy5mb3JFYWNoKGZ1bmN0aW9uIChjYikge1xuICAgICAgICAgICAgICAgIGNiKHNvY2tldCk7XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICBzZWxmLmNvbm5lY3RDYWxsYmFja3MgPSBbXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIC8vIHNldHVwIHJlc3BvbnNlIGhhbmRsZXJcbiAgICAgICAgICB0aGlzLm9uKFwiZGF0YVwiLCBmdW5jdGlvbiAoZGF0YUJ1Zikge1xuICAgICAgICAgICAgc2VsZi5yZXNwb25zZUhhbmRsZXIoZGF0YUJ1Zik7XG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICAvLyBraWNrIG9mIFNBU0wgaWYgbmVlZGVkXG4gICAgICAgICAgaWYgKHNlbGYudXNlcm5hbWUgJiYgc2VsZi5wYXNzd29yZCkge1xuICAgICAgICAgICAgc2VsZi5saXN0U2FzbCgpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzZWxmLmVtaXQoXCJhdXRoZW50aWNhdGVkXCIpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgKTtcblxuICAgICAgLy8gc2V0dXAgZXJyb3IgaGFuZGxlclxuICAgICAgc2VsZi5fc29ja2V0Lm9uKFwiZXJyb3JcIiwgZnVuY3Rpb24gKGVycm9yKSB7XG4gICAgICAgIHNlbGYuZXJyb3IoZXJyb3IpO1xuICAgICAgfSk7XG5cbiAgICAgIHNlbGYuX3NvY2tldC5vbihcImNsb3NlXCIsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKE9iamVjdC5rZXlzKHNlbGYuZXJyb3JDYWxsYmFja3MpLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICBzZWxmLmVycm9yKG5ldyBFcnJvcihcInNvY2tldCBjbG9zZWQgdW5leHBlY3RlZGx5LlwiKSk7XG4gICAgICAgIH1cbiAgICAgICAgc2VsZi5jb25uZWN0ZWQgPSBmYWxzZTtcbiAgICAgICAgaWYgKHNlbGYudGltZW91dFNldCkge1xuICAgICAgICAgIHNlbGYuX3NvY2tldD8uc2V0VGltZW91dCgwKTtcbiAgICAgICAgICBzZWxmLnRpbWVvdXRTZXQgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBzZWxmLl9zb2NrZXQgPSB1bmRlZmluZWQ7XG4gICAgICB9KTtcblxuICAgICAgLy8gc2V0dXAgY29ubmVjdGlvbiB0aW1lb3V0IGhhbmRsZXJcbiAgICAgIHNlbGYudGltZW91dFNldCA9IHRydWU7XG4gICAgICBzZWxmLl9zb2NrZXQuc2V0VGltZW91dChcbiAgICAgICAgc2VsZi5vcHRpb25zLmNvbm50aW1lb3V0ICogMTAwMCxcbiAgICAgICAgZnVuY3Rpb24gKHRoaXM6IG5ldC5Tb2NrZXQpIHtcbiAgICAgICAgICBzZWxmLnRpbWVvdXRTZXQgPSBmYWxzZTtcbiAgICAgICAgICBpZiAoIXNlbGYuY29ubmVjdGVkKSB7XG4gICAgICAgICAgICB0aGlzLmVuZCgpO1xuICAgICAgICAgICAgc2VsZi5fc29ja2V0ID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgc2VsZi5lcnJvcihuZXcgRXJyb3IoXCJzb2NrZXQgdGltZWQgb3V0IGNvbm5lY3RpbmcgdG8gc2VydmVyLlwiKSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICApO1xuXG4gICAgICAvLyB1c2UgVENQIGtlZXAtYWxpdmVcbiAgICAgIHNlbGYuX3NvY2tldC5zZXRLZWVwQWxpdmUoXG4gICAgICAgIHNlbGYub3B0aW9ucy5rZWVwQWxpdmUsXG4gICAgICAgIHNlbGYub3B0aW9ucy5rZWVwQWxpdmVEZWxheSAqIDEwMDBcbiAgICAgICk7XG4gICAgfSBlbHNlIGlmICghc2VsZi5jb25uZWN0ZWQgJiYgIXNhc2wpIHtcbiAgICAgIC8vIENBU0UgMjogc29ja2V0IGV4aXN0cywgYnV0IHN0aWxsIGNvbm5lY3RpbmcgLyBhdXRoZW50aWNhdGluZ1xuICAgICAgc2VsZi5vbkNvbm5lY3QoZ28pO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBDQVNFIDM6IHNvY2tldCBleGlzdHMgYW5kIGNvbm5lY3RlZCAvIHJlYWR5IHRvIHVzZVxuICAgICAgZ28oc2VsZi5fc29ja2V0KTtcbiAgICB9XG4gIH1cblxuICB3cml0ZShibG9iOiBCdWZmZXIpIHtcbiAgICBjb25zdCBzZWxmID0gdGhpcztcbiAgICBjb25zdCBkZWFkbGluZSA9IE1hdGgucm91bmQoc2VsZi5vcHRpb25zLnRpbWVvdXQgKiAxMDAwKTtcbiAgICB0aGlzLnNvY2soZmFsc2UsIGZ1bmN0aW9uIChzKSB7XG4gICAgICBzLndyaXRlKGJsb2IpO1xuICAgICAgc2VsZi5yZXF1ZXN0VGltZW91dHMucHVzaCh0aW1lc3RhbXAoKSArIGRlYWRsaW5lKTtcbiAgICAgIGlmICghc2VsZi50aW1lb3V0U2V0KSB7XG4gICAgICAgIHNlbGYudGltZW91dFNldCA9IHRydWU7XG4gICAgICAgIHMuc2V0VGltZW91dChkZWFkbGluZSwgZnVuY3Rpb24gKHRoaXM6IG5ldC5Tb2NrZXQpIHtcbiAgICAgICAgICB0aW1lb3V0SGFuZGxlcihzZWxmLCB0aGlzKTtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICB3cml0ZVNBU0woYmxvYjogQnVmZmVyKSB7XG4gICAgdGhpcy5zb2NrKHRydWUsIGZ1bmN0aW9uIChzKSB7XG4gICAgICBzLndyaXRlKGJsb2IpO1xuICAgIH0pO1xuICB9XG5cbiAgY2xvc2UoKSB7XG4gICAgaWYgKHRoaXMuX3NvY2tldCkge1xuICAgICAgdGhpcy5fc29ja2V0LmVuZCgpO1xuICAgIH1cbiAgfVxuXG4gIHRvU3RyaW5nKCkge1xuICAgIHJldHVybiBcIjxTZXJ2ZXIgXCIgKyB0aGlzLmhvc3QgKyBcIjpcIiArIHRoaXMucG9ydCArIFwiPlwiO1xuICB9XG5cbiAgaG9zdHBvcnRTdHJpbmcoKSB7XG4gICAgcmV0dXJuIHRoaXMuaG9zdCArIFwiOlwiICsgdGhpcy5wb3J0O1xuICB9XG59XG5cbi8vIFdlIGhhbmRsZSB0cmFja2luZyB0aW1lb3V0cyB3aXRoIGFuIGFycmF5IG9mIGRlYWRsaW5lcyAocmVxdWVzdFRpbWVvdXRzKSwgYXNcbi8vIG5vZGUgZG9lc24ndCBsaWtlIHVzIHNldHRpbmcgdXAgbG90cyBvZiB0aW1lcnMsIGFuZCB1c2luZyBqdXN0IG9uZSBpcyBtb3JlXG4vLyBlZmZpY2llbnQgYW55d2F5LlxuY29uc3QgdGltZW91dEhhbmRsZXIgPSBmdW5jdGlvbiAoc2VydmVyOiBTZXJ2ZXIsIHNvY2s6IG5ldC5Tb2NrZXQpIHtcbiAgaWYgKHNlcnZlci5yZXF1ZXN0VGltZW91dHMubGVuZ3RoID09PSAwKSB7XG4gICAgLy8gbm90aGluZyBhY3RpdmVcbiAgICBzZXJ2ZXIudGltZW91dFNldCA9IGZhbHNlO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIC8vIHNvbWUgcmVxdWVzdHMgb3V0c3RhbmRpbmcsIGNoZWNrIGlmIGFueSBoYXZlIHRpbWVkLW91dFxuICBjb25zdCBub3cgPSB0aW1lc3RhbXAoKTtcbiAgY29uc3Qgc29vbmVzdFRpbWVvdXQgPSBzZXJ2ZXIucmVxdWVzdFRpbWVvdXRzWzBdO1xuXG4gIGlmIChzb29uZXN0VGltZW91dCA8PSBub3cpIHtcbiAgICAvLyB0aW1lb3V0IG9jY3VycmVkIVxuICAgIHNvY2suZW5kKCk7XG4gICAgc2VydmVyLmNvbm5lY3RlZCA9IGZhbHNlO1xuICAgIHNlcnZlci5fc29ja2V0ID0gdW5kZWZpbmVkO1xuICAgIHNlcnZlci50aW1lb3V0U2V0ID0gZmFsc2U7XG4gICAgc2VydmVyLmVycm9yKG5ldyBFcnJvcihcInNvY2tldCB0aW1lZCBvdXQgd2FpdGluZyBvbiByZXNwb25zZS5cIikpO1xuICB9IGVsc2Uge1xuICAgIC8vIG5vIHRpbWVvdXQhIFNldHVwIG5leHQgb25lLlxuICAgIGNvbnN0IGRlYWRsaW5lID0gc29vbmVzdFRpbWVvdXQgLSBub3c7XG4gICAgc29jay5zZXRUaW1lb3V0KGRlYWRsaW5lLCBmdW5jdGlvbiAoKSB7XG4gICAgICB0aW1lb3V0SGFuZGxlcihzZXJ2ZXIsIHNvY2spO1xuICAgIH0pO1xuICB9XG59O1xuIl19 \ No newline at end of file diff --git a/lib/memjs/utils.d.ts.map b/lib/memjs/utils.d.ts.map index 98971d9..1394895 100644 --- a/lib/memjs/utils.d.ts.map +++ b/lib/memjs/utils.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/memjs/utils.ts"],"names":[],"mappings":";AAEA,OAAO,KAAK,MAAM,MAAM,UAAU,CAAC;AACnC,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AAEjC,oBAAY,WAAW,GAAG,MAAM,GAAG,MAAM,CAAC;AAE1C,eAAO,MAAM,SAAS,QAAkB,WAAW,WAElD,CAAC;AAEF,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,IAAI,CACV,MAAM,CAAC,MAAM,EACb,OAAO,GAAG,WAAW,GAAG,cAAc,GAAG,iBAAiB,CAC3D,CAAC;IACF,GAAG,EAAE,WAAW,CAAC;IACjB,MAAM,EAAE,WAAW,CAAC;IACpB,KAAK,EAAE,WAAW,CAAC;CACpB;AAED,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,gBAAgB,UAgC1B;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,gBAAgB,GAAG,MAAM,CAa/D;AAED,eAAO,MAAM,qBAAqB,WACxB,EAAE,OACL,WAAW,UACR,WAAW,SACZ,WAAW,UACV,MAAM,OACT,MAAM,uDAYZ,CAAC;AAEF,eAAO,MAAM,iBAAiB,WACpB,EAAE,OACL,WAAW,UACR,WAAW,SACZ,WAAW,wCAYnB,CAAC;AAEF,eAAO,MAAM,8BAA8B,WACjC,MAAM,iBACC,MAAM,cACT,MAAM,WASnB,CAAC;AAEF,eAAO,MAAM,cAAc,eAAyB,MAAM,WAIzD,CAAC;AAEF,eAAO,MAAM,QAAQ,QAAkB,MAAM,WAM5C,CAAC;AAEF,MAAM,WAAW,OAAO;IACtB,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,eAAO,MAAM,YAAY,YAAsB,MAAM,KAAG,OAAO,GAAG,KAsBjE,CAAC;AAEF,eAAO,MAAM,aAAa,YAAsB,MAAM,KAAG,OAAO,EAe/D,CAAC;AAEF,eAAO,MAAM,KAAK,gBAA0B,GAAG,gBAU9C,CAAC;AAIF,eAAO,MAAM,SAAS,cAGrB,CAAC"} \ No newline at end of file +{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/memjs/utils.ts"],"names":[],"mappings":";AAEA,OAAO,KAAK,MAAM,MAAM,UAAU,CAAC;AACnC,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AAEjC,oBAAY,WAAW,GAAG,MAAM,GAAG,MAAM,CAAC;AAE1C,eAAO,MAAM,SAAS,QAAkB,WAAW,WAElD,CAAC;AAEF,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,IAAI,CACV,MAAM,CAAC,MAAM,EACb,OAAO,GAAG,WAAW,GAAG,cAAc,GAAG,iBAAiB,CAC3D,CAAC;IACF,GAAG,EAAE,WAAW,CAAC;IACjB,MAAM,EAAE,WAAW,CAAC;IACpB,KAAK,EAAE,WAAW,CAAC;CACpB;AAED,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,gBAAgB,UAgC1B;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,gBAAgB,GAAG,MAAM,CAa/D;AAED,eAAO,MAAM,qBAAqB,WACxB,EAAE,OACL,WAAW,UACR,WAAW,SACZ,WAAW,UACV,MAAM,OACT,MAAM,uDAYZ,CAAC;AAEF,eAAO,MAAM,iBAAiB,WACpB,EAAE,OACL,WAAW,UACR,WAAW,SACZ,WAAW,wCAYnB,CAAC;AAEF,eAAO,MAAM,8BAA8B,WACjC,MAAM,iBACC,MAAM,cACT,MAAM,WASnB,CAAC;AAEF,eAAO,MAAM,cAAc,eAAyB,MAAM,WAIzD,CAAC;AAEF,eAAO,MAAM,QAAQ,QAAkB,MAAM,WAM5C,CAAC;AAEF,MAAM,WAAW,OAAO;IACtB,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;CAChB;AAID,eAAO,MAAM,YAAY,YAAsB,MAAM,KAAG,OAAO,GAAG,KA6BjE,CAAC;AAEF,eAAO,MAAM,aAAa,YAAsB,MAAM,KAAG,OAAO,EAe/D,CAAC;AAEF,eAAO,MAAM,KAAK,gBAA0B,GAAG,gBAU9C,CAAC;AAIF,eAAO,MAAM,SAAS,cAGrB,CAAC"} \ No newline at end of file diff --git a/lib/memjs/utils.js b/lib/memjs/utils.js index 9f71eb2..3179851 100644 --- a/lib/memjs/utils.js +++ b/lib/memjs/utils.js @@ -114,10 +114,16 @@ const hashCode = function (str) { return Math.abs(ret); }; exports.hashCode = hashCode; +const ERROR_TOO_MANY_OPEN_CONNECTIONS = "ERROR Too many open connections\r\n"; const parseMessage = function (dataBuf) { if (dataBuf.length < 24) { return false; } + if (dataBuf.length === ERROR_TOO_MANY_OPEN_CONNECTIONS.length) { + if (dataBuf.toString() === ERROR_TOO_MANY_OPEN_CONNECTIONS) { + throw new Error("ERROR Too many open connections"); + } + } const responseHeader = header.fromBuffer(dataBuf); if (dataBuf.length < responseHeader.totalBodyLength + 24 || responseHeader.totalBodyLength < @@ -195,4 +201,4 @@ if (!Buffer.concat) { return buffer; }; } -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbWVtanMvdXRpbHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLDRCQUE0Qjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUU1QixpREFBbUM7QUFLNUIsTUFBTSxTQUFTLEdBQUcsVUFBVSxHQUFnQjtJQUNqRCxPQUFPLE1BQU0sQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFVLENBQUMsQ0FBQztBQUM5RCxDQUFDLENBQUM7QUFGVyxRQUFBLFNBQVMsYUFFcEI7QUFZRixTQUFnQix1QkFBdUIsQ0FDckMsTUFBYyxFQUNkLE1BQWMsRUFDZCxPQUF5QjtJQUV6QixNQUFNLEdBQUcsR0FBRyxpQkFBUyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNuQyxNQUFNLE1BQU0sR0FBRyxpQkFBUyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUN6QyxNQUFNLEtBQUssR0FBRyxpQkFBUyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUV2QyxNQUFNLG9CQUFvQixHQUFHLE1BQU0sSUFBSSxDQUFDLENBQUM7SUFDekMsSUFBSSxpQkFBaUIsR0FBRyxDQUFDLENBQUM7SUFDMUIsU0FBUyxjQUFjLENBQUMsYUFBcUI7UUFDM0MsTUFBTSxZQUFZLEdBQUcsYUFBYSxDQUFDLElBQUksQ0FDckMsTUFBTSxFQUNOLG9CQUFvQixHQUFHLGlCQUFpQixDQUN6QyxDQUFDO1FBQ0YsaUJBQWlCLElBQUksWUFBWSxDQUFDO0lBQ3BDLENBQUM7SUFFRCxNQUFNLGFBQWEsR0FBa0I7UUFDbkMsR0FBRyxPQUFPLENBQUMsTUFBTTtRQUNqQixLQUFLLEVBQUUsSUFBSTtRQUNYLFNBQVMsRUFBRSxHQUFHLENBQUMsTUFBTTtRQUNyQixZQUFZLEVBQUUsTUFBTSxD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LENBQUM7UUFFaEIsSUFBSSxPQUFPLE1BQU0sS0FBSyxRQUFRLEVBQUU7WUFDOUIsTUFBTSxHQUFHLENBQUMsQ0FBQztZQUNYLEtBQUssQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRTtnQkFDaEMsR0FBRyxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDZCxNQUFNLElBQUksR0FBRyxDQUFDLE1BQU0sQ0FBQzthQUN0QjtTQUNGO1FBRUQsTUFBTSxNQUFNLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUNwQyxJQUFJLEdBQUcsR0FBRyxDQUFDLENBQUM7UUFDWixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRTtZQUNwQyxHQUFHLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ2QsR0FBRyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUM7WUFDdEIsR0FBRyxJQUFJLEdBQUcsQ0FBQyxNQUFNLENBQUM7U0FDbkI7UUFDRCxPQUFPLE1BQU0sQ0FBQztJQUNoQixDQUFDLENBQUM7Q0FDSCIsInNvdXJjZXNDb250ZW50IjpbIi8vICMgTWVtSlMgdXRpbGl0eSBmdW5jdGlvbnNcblxuaW1wb3J0ICogYXMgaGVhZGVyIGZyb20gXCIuL2hlYWRlclwiO1xuaW1wb3J0IHsgT1AgfSBmcm9tIFwiLi9jb25zdGFudHNcIjtcblxuZXhwb3J0IHR5cGUgTWF5YmVCdWZmZXIgPSBzdHJpbmcgfCBCdWZmZXI7XG5cbmV4cG9ydCBjb25zdCBidWZmZXJpZnkgPSBmdW5jdGlvbiAodmFsOiBNYXliZUJ1ZmZlcikge1xuICByZXR1cm4gQnVmZmVyLmlzQnVmZmVyKHZhbCkgPyB2YWwgOiBCdWZmZXIuZnJvbSh2YWwgYXMgYW55KTtcbn07XG5cbmV4cG9ydCBpbnRlcmZhY2UgRW5jb2RhYmxlUmVxdWVzdCB7XG4gIGhlYWRlcjogT21pdDxcbiAgICBoZWFkZXIuSGVhZGVyLFxuICAgIFwibWFnaWNcIiB8IFwia2V5TGVuZ3RoXCIgfCBcImV4dHJhc0xlbmd0aFwiIHwgXCJ0b3RhbEJvZHlMZW5ndGhcIlxuICA+O1xuICBrZXk6IE1heWJlQnVmZmVyO1xuICBleHRyYXM6IE1heWJlQnVmZmVyO1xuICB2YWx1ZTogTWF5YmVCdWZmZXI7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBlbmNvZGVSZXF1ZXN0SW50b0J1ZmZlcihcbiAgYnVmZmVyOiBCdWZmZXIsXG4gIG9mZnNldDogbnVtYmVyLFxuICByZXF1ZXN0OiBFbmNvZGFibGVSZXF1ZXN0XG4pIHtcbiAgY29uc3Qga2V5ID0gYnVmZmVyaWZ5KHJlcXVlc3Qua2V5KTtcbiAgY29uc3QgZXh0cmFzID0gYnVmZmVyaWZ5KHJlcXVlc3QuZXh0cmFzKTtcbiAgY29uc3QgdmFsdWUgPSBidWZmZXJpZnkocmVxdWVzdC52YWx1ZSk7XG5cbiAgY29uc3QgYnVmVGFyZ2V0V3JpdGVPZmZzZXQgPSBvZmZzZXQgfHwgMDtcbiAgbGV0IHRvdGFsQnl0ZXNXcml0dGVuID0gMDtcbiAgZnVuY3Rpb24gY29weUludG9CdWZmZXIodG9Xcml0ZUJ1ZmZlcjogQnVmZmVyKSB7XG4gICAgY29uc3QgYnl0ZXNXcml0dGVuID0gdG9Xcml0ZUJ1ZmZlci5jb3B5KFxuICAgICAgYnVmZmVyLFxuICAgICAgYnVmVGFyZ2V0V3JpdGVPZmZzZXQgKyB0b3RhbEJ5dGVzV3JpdHRlblxuICAgICk7XG4gICAgdG90YWxCeXRlc1dyaXR0ZW4gKz0gYnl0ZXNXcml0dGVuO1xuICB9XG5cbiAgY29uc3QgcmVxdWVzdEhlYWRlcjogaGVhZGVyLkhlYWRlciA9IHtcbiAgICAuLi5yZXF1ZXN0LmhlYWRlcixcbiAgICBtYWdpYzogMHg4MCxcbiAgICBrZXlMZW5ndGg6IGtleS5sZW5ndGgsXG4gICAgZXh0cmFzTGVuZ3RoOiBleHRyYXMubGVuZ3RoLFxuICAgIHRvdGFsQm9keUxlbmd0aDoga2V5Lmxlbmd0aCArIHZhbHVlLmxlbmd0aCArIGV4dHJhcy5sZW5ndGgsXG4gIH07XG5cbiAgY29uc3QgaGVhZGVyQnVmZmVyID0gaGVhZGVyLnRvQnVmZmVyKHJlcXVlc3RIZWFkZXIpO1xuXG4gIGNvcHlJbnRvQnVmZmVyKGhlYWRlckJ1ZmZlcik7XG4gIGNvcHlJbnRvQnVmZmVyKGV4dHJhcyk7XG4gIGNvcHlJbnRvQnVmZmVyKGtleSk7XG4gIGNvcHlJbnRvQnVmZmVyKHZhbHVlKTtcblxuICByZXR1cm4gdG90YWxCeXRlc1dyaXR0ZW47XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBlbmNvZGVSZXF1ZXN0KHJlcXVlc3Q6IEVuY29kYWJsZVJlcXVlc3QpOiBCdWZmZXIge1xuICBjb25zdCBrZXkgPSBidWZmZXJpZnkocmVxdWVzdC5rZXkpO1xuICBjb25zdCBleHRyYXMgPSBidWZmZXJpZnkocmVxdWVzdC5leHRyYXMpO1xuICBjb25zdCB2YWx1ZSA9IGJ1ZmZlcmlmeShyZXF1ZXN0LnZhbHVlKTtcbiAgY29uc3QgYnVmU2l6ZSA9IDI0ICsga2V5Lmxlbmd0aCArIGV4dHJhcy5sZW5ndGggKyB2YWx1ZS5sZW5ndGg7XG4gIGNvbnN0IGJ1ZmZlciA9IEJ1ZmZlci5hbGxvYyhidWZTaXplKTtcbiAgZW5jb2RlUmVxdWVzdEludG9CdWZmZXIoYnVmZmVyLCAwLCB7XG4gICAgLi4ucmVxdWVzdCxcbiAgICBrZXksXG4gICAgZXh0cmFzLFxuICAgIHZhbHVlLFxuICB9KTtcbiAgcmV0dXJuIGJ1ZmZlcjtcbn1cblxuZXhwb3J0IGNvbnN0IGNvcHlJbnRvUmVxdWVzdEJ1ZmZlciA9IGZ1bmN0aW9uIChcbiAgb3Bjb2RlOiBPUCxcbiAga2V5OiBNYXliZUJ1ZmZlcixcbiAgZXh0cmFzOiBNYXliZUJ1ZmZlcixcbiAgdmFsdWU6IE1heWJlQnVmZmVyLFxuICBvcGFxdWU6IG51bWJlcixcbiAgYnVmOiBCdWZmZXIsXG4gIF9idWZUYXJnZXRXcml0ZU9mZnNldD86IG51bWJlclxuKSB7XG4gIHJldHVybiBlbmNvZGVSZXF1ZXN0SW50b0J1ZmZlcihidWYsIF9idWZUYXJnZXRXcml0ZU9mZnNldCB8fCAwLCB7XG4gICAgaGVhZGVyOiB7XG4gICAgICBvcGNvZGUsXG4gICAgICBvcGFxdWUsXG4gICAgfSxcbiAgICBrZXksXG4gICAgZXh0cmFzLFxuICAgIHZhbHVlLFxuICB9KTtcbn07XG5cbmV4cG9ydCBjb25zdCBtYWtlUmVxdWVzdEJ1ZmZlciA9IGZ1bmN0aW9uIChcbiAgb3Bjb2RlOiBPUCxcbiAga2V5OiBNYXliZUJ1ZmZlcixcbiAgZXh0cmFzOiBNYXliZUJ1ZmZlcixcbiAgdmFsdWU6IE1heWJlQnVmZmVyLFxuICBvcGFxdWU/OiBudW1iZXJcbikge1xuICByZXR1cm4gZW5jb2RlUmVxdWVzdCh7XG4gICAgZXh0cmFzLFxuICAgIGtleSxcbiAgICB2YWx1ZSxcbiAgICBoZWFkZXI6IHtcbiAgICAgIG9wY29kZSxcbiAgICAgIG9wYXF1ZTogb3BhcXVlIHx8IDAsXG4gICAgfSxcbiAgfSk7XG59O1xuXG5leHBvcnQgY29uc3QgbWFrZUFtb3VudEluaXRpYWxBbmRFeHBpcmF0aW9uID0gZnVuY3Rpb24gKFxuICBhbW91bnQ6IG51bWJlcixcbiAgYW1vdW50SWZFbXB0eTogbnVtYmVyLFxuICBleHBpcmF0aW9uOiBudW1iZXJcbikge1xuICBjb25zdCBidWYgPSBCdWZmZXIuYWxsb2MoMjApO1xuICBidWYud3JpdGVVSW50MzJCRSgwLCAwKTtcbiAgYnVmLndyaXRlVUludDMyQkUoYW1vdW50LCA0KTtcbiAgYnVmLndyaXRlVUludDMyQkUoMCwgOCk7XG4gIGJ1Zi53cml0ZVVJbnQzMkJFKGFtb3VudElmRW1wdHksIDEyKTtcbiAgYnVmLndyaXRlVUludDMyQkUoZXhwaXJhdGlvbiwgMTYpO1xuICByZXR1cm4gYnVmO1xufTtcblxuZXhwb3J0IGNvbnN0IG1ha2VFeHBpcmF0aW9uID0gZnVuY3Rpb24gKGV4cGlyYXRpb246IG51bWJlcikge1xuICBjb25zdCBidWYgPSBCdWZmZXIuYWxsb2MoNCk7XG4gIGJ1Zi53cml0ZVVJbnQzMkJFKGV4cGlyYXRpb24sIDApO1xuICByZXR1cm4gYnVmO1xufTtcblxuZXhwb3J0IGNvbnN0IGhhc2hDb2RlID0gZnVuY3Rpb24gKHN0cjogc3RyaW5nKSB7XG4gIGxldCByZXQsIGksIGxlbjtcbiAgZm9yIChyZXQgPSAwLCBpID0gMCwgbGVuID0gc3RyLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgcmV0ID0gKDMxICogcmV0ICsgc3RyLmNoYXJDb2RlQXQoaSkpIDw8IDA7XG4gIH1cbiAgcmV0dXJuIE1hdGguYWJzKHJldCk7XG59O1xuXG5leHBvcnQgaW50ZXJmYWNlIE1lc3NhZ2Uge1xuICBoZWFkZXI6IGhlYWRlci5IZWFkZXI7XG4gIGtleTogQnVmZmVyO1xuICB2YWw6IEJ1ZmZlcjtcbiAgZXh0cmFzOiBCdWZmZXI7XG59XG5cbmV4cG9ydCBjb25zdCBwYXJzZU1lc3NhZ2UgPSBmdW5jdGlvbiAoZGF0YUJ1ZjogQnVmZmVyKTogTWVzc2FnZSB8IGZhbHNlIHtcbiAgaWYgKGRhdGFCdWYubGVuZ3RoIDwgMjQpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgY29uc3QgcmVzcG9uc2VIZWFkZXIgPSBoZWFkZXIuZnJvbUJ1ZmZlcihkYXRhQnVmKTtcblxuICBpZiAoXG4gICAgZGF0YUJ1Zi5sZW5ndGggPCByZXNwb25zZUhlYWRlci50b3RhbEJvZHlMZW5ndGggKyAyNCB8fFxuICAgIHJlc3BvbnNlSGVhZGVyLnRvdGFsQm9keUxlbmd0aCA8XG4gICAgICByZXNwb25zZUhlYWRlci5rZXlMZW5ndGggKyByZXNwb25zZUhlYWRlci5leHRyYXNMZW5ndGhcbiAgKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgbGV0IHBvaW50ZXIgPSAyNDtcbiAgY29uc3QgZXh0cmFzID0gZGF0YUJ1Zi5zbGljZShwb2ludGVyLCBwb2ludGVyICsgcmVzcG9uc2VIZWFkZXIuZXh0cmFzTGVuZ3RoKTtcbiAgcG9pbnRlciArPSByZXNwb25zZUhlYWRlci5leHRyYXNMZW5ndGg7XG4gIGNvbnN0IGtleSA9IGRhdGFCdWYuc2xpY2UocG9pbnRlciwgcG9pbnRlciArIHJlc3BvbnNlSGVhZGVyLmtleUxlbmd0aCk7XG4gIHBvaW50ZXIgKz0gcmVzcG9uc2VIZWFkZXIua2V5TGVuZ3RoO1xuICBjb25zdCB2YWwgPSBkYXRhQnVmLnNsaWNlKHBvaW50ZXIsIDI0ICsgcmVzcG9uc2VIZWFkZXIudG90YWxCb2R5TGVuZ3RoKTtcblxuICByZXR1cm4geyBoZWFkZXI6IHJlc3BvbnNlSGVhZGVyLCBrZXk6IGtleSwgZXh0cmFzOiBleHRyYXMsIHZhbDogdmFsIH07XG59O1xuXG5leHBvcnQgY29uc3QgcGFyc2VNZXNzYWdlcyA9IGZ1bmN0aW9uIChkYXRhQnVmOiBCdWZmZXIpOiBNZXNzYWdlW10ge1xuICBjb25zdCBtZXNzYWdlcyA9IFtdO1xuXG4gIGxldCBtZXNzYWdlOiBNZXNzYWdlO1xuXG4gIGRvIHtcbiAgICBtZXNzYWdlID0gZXhwb3J0cy5wYXJzZU1lc3NhZ2UoZGF0YUJ1Zik7XG4gICAgaWYgKG1lc3NhZ2UpIHtcbiAgICAgIG1lc3NhZ2VzLnB1c2gobWVzc2FnZSk7XG4gICAgICBjb25zdCBtZXNzYWdlTGVuZ3RoID0gbWVzc2FnZS5oZWFkZXIudG90YWxCb2R5TGVuZ3RoICsgMjQ7XG4gICAgICBkYXRhQnVmID0gZGF0YUJ1Zi5zbGljZShtZXNzYWdlTGVuZ3RoKTtcbiAgICB9XG4gIH0gd2hpbGUgKG1lc3NhZ2UpO1xuXG4gIHJldHVybiBtZXNzYWdlcztcbn07XG5cbmV4cG9ydCBjb25zdCBtZXJnZSA9IGZ1bmN0aW9uIDxUPihvcmlnaW5hbDogYW55LCBkZWZsdDogVCk6IFQge1xuICBmb3IgKGxldCBhdHRyVCBvZiBPYmplY3Qua2V5cyhkZWZsdCkpIHtcbiAgICBjb25zdCBhdHRyOiBrZXlvZiBUID0gYXR0clQgYXMgYW55O1xuICAgIGNvbnN0IG9yaWdpbmFsVmFsdWUgPSBvcmlnaW5hbFthdHRyXTtcblxuICAgIGlmIChvcmlnaW5hbFZhbHVlID09PSB1bmRlZmluZWQgfHwgb3JpZ2luYWxWYWx1ZSA9PT0gbnVsbCkge1xuICAgICAgb3JpZ2luYWxbYXR0cl0gPSBkZWZsdFthdHRyXSBhcyBhbnk7XG4gICAgfVxuICB9XG4gIHJldHVybiBvcmlnaW5hbDtcbn07XG5cbi8vIHRpbWVzdGFtcCBwcm92aWRlcyBhIG1vbm90b25pYyB0aW1lc3RhbXAgd2l0aCBtaWxsaXNlY29uZCBhY2N1cmFjeSwgdXNlZnVsXG4vLyBmb3IgdGltZXJzLlxuZXhwb3J0IGNvbnN0IHRpbWVzdGFtcCA9IGZ1bmN0aW9uICgpIHtcbiAgY29uc3QgdGltZXMgPSBwcm9jZXNzLmhydGltZSgpO1xuICByZXR1cm4gdGltZXNbMF0gKiAxMDAwICsgTWF0aC5yb3VuZCh0aW1lc1sxXSAvIDEwMDAwMDApO1xufTtcblxuaWYgKCFCdWZmZXIuY29uY2F0KSB7XG4gIEJ1ZmZlci5jb25jYXQgPSBmdW5jdGlvbiAobGlzdCwgbGVuZ3RoKSB7XG4gICAgaWYgKCFBcnJheS5pc0FycmF5KGxpc3QpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJVc2FnZTogQnVmZmVyLmNvbmNhdChsaXN0LCBbbGVuZ3RoXSlcIik7XG4gICAgfVxuXG4gICAgaWYgKGxpc3QubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm4gQnVmZmVyLmFsbG9jKDApO1xuICAgIH1cbiAgICBpZiAobGlzdC5sZW5ndGggPT09IDEpIHtcbiAgICAgIHJldHVybiBsaXN0WzBdO1xuICAgIH1cblxuICAgIGxldCBpOiBudW1iZXI7XG4gICAgbGV0IGJ1ZjogQnVmZmVyO1xuXG4gICAgaWYgKHR5cGVvZiBsZW5ndGggIT09IFwibnVtYmVyXCIpIHtcbiAgICAgIGxlbmd0aCA9IDA7XG4gICAgICBmb3IgKGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICBidWYgPSBsaXN0W2ldO1xuICAgICAgICBsZW5ndGggKz0gYnVmLmxlbmd0aDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBidWZmZXIgPSBCdWZmZXIuYWxsb2MobGVuZ3RoKTtcbiAgICBsZXQgcG9zID0gMDtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICAgIGJ1ZiA9IGxpc3RbaV07XG4gICAgICBidWYuY29weShidWZmZXIsIHBvcyk7XG4gICAgICBwb3MgKz0gYnVmLmxlbmd0aDtcbiAgICB9XG4gICAgcmV0dXJuIGJ1ZmZlcjtcbiAgfTtcbn1cbiJdfQ== \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbWVtanMvdXRpbHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLDRCQUE0Qjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUU1QixpREFBbUM7QUFLNUIsTUFBTSxTQUFTLEdBQUcsVUFBVSxHQUFnQjtJQUNqRCxPQUFPLE1BQU0sQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFVLENBQUMsQ0FBQztBQUM5RCxDQUFDLENBQUM7QUFGVyxRQUFBLFNBQVMsYUFFcEI7QUFZRixTQUFnQix1QkFBdUIsQ0FDckMsTUFBYyxFQUNkLE1BQWMsRUFDZCxPQUF5QjtJQUV6QixNQUFNLEdBQUcsR0FBRyxpQkFBUyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNuQyxNQUFNLE1BQU0sR0FBRyxpQkFBUyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUN6QyxNQUFNLEtBQUssR0FBRyxpQkFBUyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUV2QyxNQUFNLG9CQUFvQixHQUFHLE1BQU0sSUFBSSxDQUFDLENBQUM7SUFDekMsSUFBSSxpQkFBaUIsR0FBRyxDQUFDLENBQUM7SUFDMUIsU0FBUyxjQUFjLENBQUMsYUFBcUI7UUFDM0MsTUFBTSxZQUFZLEdBQUcsYUFBYSxDQUFDLElBQUksQ0FDckMsTUFBTSxFQUNOLG9CQUFvQixHQUFHLGlCQUFpQixDQUN6QyxDQUFDO1FBQ0YsaUJBQWlCLElBQUksWUFBWSxDQUFDO0lBQ3BDLENBQUM7SUFFRCxNQUFNLGFBQWEsR0FBa0I7UUFDbkMsR0FBRyxPQUFPLENBQUMsTUFBTTtRQUNqQixLQUFLLEVBQUUsSUFBSTtRQUNYLFNBQVMsRUFBRSxHQUFHLENBQUMsTUFBTTtRQUNyQixZQUFZLEVBQUUsTUFBTSxDQUFDLE1BQU07UUFDM0IsZUFBZSxFQUFFLEdBQUcsQ0FBQyxNQUFNLEdBQUcsS0FBSyxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUMsTUFBTTtLQUMzRCxDQUFDO0lBRUYsTUFBTSxZQUFZLEdBQUcsTUFBTSxDQUFDLFFBQVEsQ0FBQyxhQUFhLENBQUMsQ0FBQztJQUVwRCxjQUFjLENBQUMsWUFBWSxDQUFDLENBQUM7SUFDN0IsY0FBYyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ3ZCLGNBQWMsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNwQixjQUFjLENBQUMsS0FBSyxDQUFDLENBQUM7SUFFdEIsT0FBTyxpQkFBaUIsQ0FBQztBQUMzQixDQUFDO0FBbkNELDBEQW1DQztBQUVELFNBQWdCLGFBQWEsQ0FBQyxPQUF5QjtJQUNyRCxNQUFNLEdBQUcsR0FBRyxpQkFBUyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNuQyxNQUFNLE1BQU0sR0FBRyxpQkFBUyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUN6QyxNQUFNLEtBQUssR0FBRyxpQkFBUyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUN2QyxNQUFNLE9BQU8sR0FBRyxFQUFFLEdBQUcsR0FBRyxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUMsTUFBTSxHQUFHLEtBQUssQ0FBQyxNQUFNLENBQUM7SUFDL0QsTUFBTSxNQUFNLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUNyQyx1QkFBdUIsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFO1FBQ2pDLEdBQUcsT0FBTztRQUNWLEdBQUc7UUFDSCxNQUFNO1FBQ04sS0FBSztLQUNOLENBQUMsQ0FBQztJQUNILE9BQU8sTUFBTSxDQUFDO0FBQ2hCLENBQUM7QUFiRCxzQ0FhQztBQUVNLE1BQU0scUJBQXFCLEdBQUcsVUFDbkMsTUFBVSxFQUNWLEdBQWdCLEVBQ2hCLE1BQW1CLEVBQ25CLEtBQWtCLEVBQ2xCLE1BQWMsRUFDZCxHQUFXLEVBQ1gscUJBQThCO0lBRTlCLE9BQU8sdUJBQXVCLENBQUMsR0FBRyxFQUFFLHFCQUFxQixJQUFJLENBQUMsRUFBRTtRQUM5RCxNQUFNLEVBQUU7WUFDTixNQUFNO1lBQ04sTUFBTTtTQUNQO1FBQ0QsR0FBRztRQUNILE1BQU07UUFDTixLQUFLO0tBQ04sQ0FBQyxDQUFDO0FBQ0wsQ0FBQyxDQUFDO0FBbEJXLFFBQUEscUJBQXFCLHlCQWtCaEM7QUFFSyxNQUFNLGlCQUFpQixHQUFHLFVBQy9CLE1BQVUsRUFDVixHQUFnQixFQUNoQixNQUFtQixFQUNuQixLQUFrQixFQUNsQixNQUFlO0lBRWYsT0FBTyxhQUFhLENBQUM7UUFDbkIsTUFBTTtRQUNOLEdBQUc7UUFDSCxLQUFLO1FBQ0wsTUFBTSxFQUFFO1lBQ04sTUFBTTtZQUNOLE1BQU0sRUFBRSxNQUFNLElBQUksQ0FBQztTQUNwQjtLQUNGLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQztBQWhCVyxRQUFBLGlCQUFpQixxQkFnQjVCO0FBRUssTUFBTSw4QkFBOEIsR0FBRyxVQUM1QyxNQUFjLEVBQ2QsYUFBcUIsRUFDckIsVUFBa0I7SUFFbEIsTUFBTSxHQUFHLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUM3QixHQUFHLENBQUMsYUFBYSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUN4QixHQUFHLENBQUMsYUFBYSxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQztJQUM3QixHQUFHLENBQUMsYUFBYSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUN4QixHQUFHLENBQUMsYUFBYSxDQUFDLGFBQWEsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUNyQyxHQUFHLENBQUMsYUFBYSxDQUFDLFVBQVUsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUNsQyxPQUFPLEdBQUcsQ0FBQztBQUNiLENBQUMsQ0FBQztBQVpXLFFBQUEsOEJBQThCLGtDQVl6QztBQUVLLE1BQU0sY0FBYyxHQUFHLFVBQVUsVUFBa0I7SUFDeEQsTUFBTSxHQUFHLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUM1QixHQUFHLENBQUMsYUFBYSxDQUFDLFVBQVUsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNqQyxPQUFPLEdBQUcsQ0FBQztBQUNiLENBQUMsQ0FBQztBQUpXLFFBQUEsY0FBYyxrQkFJekI7QUFFSyxNQUFNLFFBQVEsR0FBRyxVQUFVLEdBQVc7SUFDM0MsSUFBSSxHQUFHLEVBQUUsQ0FBQyxFQUFFLEdBQUcsQ0FBQztJQUNoQixLQUFLLEdBQUcsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxHQUFHLEdBQUcsR0FBRyxDQUFDLE1BQU0sRUFBRSxDQUFDLEdBQUcsR0FBRyxFQUFFLENBQUMsRUFBRSxFQUFFO1FBQ25ELEdBQUcsR0FBRyxDQUFDLEVBQUUsR0FBRyxHQUFHLEdBQUcsR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQztLQUMzQztJQUNELE9BQU8sSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztBQUN2QixDQUFDLENBQUM7QUFOVyxRQUFBLFFBQVEsWUFNbkI7QUFTRixNQUFNLCtCQUErQixHQUFHLHFDQUFxQyxDQUFDO0FBRXZFLE1BQU0sWUFBWSxHQUFHLFVBQVUsT0FBZTtJQUNuRCxJQUFJLE9BQU8sQ0FBQyxNQUFNLEdBQUcsRUFBRSxFQUFFO1FBQ3ZCLE9BQU8sS0FBSyxDQUFDO0tBQ2Q7SUFFRCxJQUFJLE9BQU8sQ0FBQyxNQUFNLEtBQUssK0JBQStCLENBQUMsTUFBTSxFQUFFO1FBQzdELElBQUksT0FBTyxDQUFDLFFBQVEsRUFBRSxLQUFLLCtCQUErQixFQUFFO1lBQzFELE1BQU0sSUFBSSxLQUFLLENBQUMsaUNBQWlDLENBQUMsQ0FBQztTQUNwRDtLQUNGO0lBRUQsTUFBTSxjQUFjLEdBQUcsTUFBTSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUVsRCxJQUNFLE9BQU8sQ0FBQyxNQUFNLEdBQUcsY0FBYyxDQUFDLGVBQWUsR0FBRyxFQUFFO1FBQ3BELGNBQWMsQ0FBQyxlQUFlO1lBQzVCLGNBQWMsQ0FBQyxTQUFTLEdBQUcsY0FBYyxDQUFDLFlBQVksRUFDeEQ7UUFDQSxPQUFPLEtBQUssQ0FBQztLQUNkO0lBRUQsSUFBSSxPQUFPLEdBQUcsRUFBRSxDQUFDO0lBQ2pCLE1BQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQyxLQUFLLENBQUMsT0FBTyxFQUFFLE9BQU8sR0FBRyxjQUFjLENBQUMsWUFBWSxDQUFDLENBQUM7SUFDN0UsT0FBTyxJQUFJLGNBQWMsQ0FBQyxZQUFZLENBQUM7SUFDdkMsTUFBTSxHQUFHLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQyxPQUFPLEVBQUUsT0FBTyxHQUFHLGNBQWMsQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUN2RSxPQUFPLElBQUksY0FBYyxDQUFDLFNBQVMsQ0FBQztJQUNwQyxNQUFNLEdBQUcsR0FBRyxPQUFPLENBQUMsS0FBSyxDQUFDLE9BQU8sRUFBRSxFQUFFLEdBQUcsY0FBYyxDQUFDLGVBQWUsQ0FBQyxDQUFDO0lBRXhFLE9BQU8sRUFBRSxNQUFNLEVBQUUsY0FBYyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLENBQUM7QUFDeEUsQ0FBQyxDQUFDO0FBN0JXLFFBQUEsWUFBWSxnQkE2QnZCO0FBRUssTUFBTSxhQUFhLEdBQUcsVUFBVSxPQUFlO0lBQ3BELE1BQU0sUUFBUSxHQUFHLEVBQUUsQ0FBQztJQUVwQixJQUFJLE9BQWdCLENBQUM7SUFFckIsR0FBRztRQUNELE9BQU8sR0FBRyxPQUFPLENBQUMsWUFBWSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ3hDLElBQUksT0FBTyxFQUFFO1lBQ1gsUUFBUSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUN2QixNQUFNLGFBQWEsR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLGVBQWUsR0FBRyxFQUFFLENBQUM7WUFDMUQsT0FBTyxHQUFHLE9BQU8sQ0FBQyxLQUFLLENBQUMsYUFBYSxDQUFDLENBQUM7U0FDeEM7S0FDRixRQUFRLE9BQU8sRUFBRTtJQUVsQixPQUFPLFFBQVEsQ0FBQztBQUNsQixDQUFDLENBQUM7QUFmVyxRQUFBLGFBQWEsaUJBZXhCO0FBRUssTUFBTSxLQUFLLEdBQUcsVUFBYSxRQUFhLEVBQUUsS0FBUTtJQUN2RCxLQUFLLElBQUksS0FBSyxJQUFJLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEVBQUU7UUFDcEMsTUFBTSxJQUFJLEdBQVksS0FBWSxDQUFDO1FBQ25DLE1BQU0sYUFBYSxHQUFHLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUVyQyxJQUFJLGFBQWEsS0FBSyxTQUFTLElBQUksYUFBYSxLQUFLLElBQUksRUFBRTtZQUN6RCxRQUFRLENBQUMsSUFBSSxDQUFDLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBUSxDQUFDO1NBQ3JDO0tBQ0Y7SUFDRCxPQUFPLFFBQVEsQ0FBQztBQUNsQixDQUFDLENBQUM7QUFWVyxRQUFBLEtBQUssU0FVaEI7QUFFRiw2RUFBNkU7QUFDN0UsY0FBYztBQUNQLE1BQU0sU0FBUyxHQUFHO0lBQ3ZCLE1BQU0sS0FBSyxHQUFHLE9BQU8sQ0FBQyxNQUFNLEVBQUUsQ0FBQztJQUMvQixPQUFPLEtBQUssQ0FBQyxDQUFDLENBQUMsR0FBRyxJQUFJLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEdBQUcsT0FBTyxDQUFDLENBQUM7QUFDMUQsQ0FBQyxDQUFDO0FBSFcsUUFBQSxTQUFTLGFBR3BCO0FBRUYsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEVBQUU7SUFDbEIsTUFBTSxDQUFDLE1BQU0sR0FBRyxVQUFVLElBQUksRUFBRSxNQUFNO1FBQ3BDLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxFQUFFO1lBQ3hCLE1BQU0sSUFBSSxLQUFLLENBQUMsc0NBQXNDLENBQUMsQ0FBQztTQUN6RDtRQUVELElBQUksSUFBSSxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUU7WUFDckIsT0FBTyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1NBQ3hCO1FBQ0QsSUFBSSxJQUFJLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRTtZQUNyQixPQUFPLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNoQjtRQUVELElBQUksQ0FBUyxDQUFDO1FBQ2QsSUFBSSxHQUFXLENBQUM7UUFFaEIsSUFBSSxPQUFPLE1BQU0sS0FBSyxRQUFRLEVBQUU7WUFDOUIsTUFBTSxHQUFHLENBQUMsQ0FBQztZQUNYLEtBQUssQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRTtnQkFDaEMsR0FBRyxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDZCxNQUFNLElBQUksR0FBRyxDQUFDLE1BQU0sQ0FBQzthQUN0QjtTQUNGO1FBRUQsTUFBTSxNQUFNLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUNwQyxJQUFJLEdBQUcsR0FBRyxDQUFDLENBQUM7UUFDWixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRTtZQUNwQyxHQUFHLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ2QsR0FBRyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUM7WUFDdEIsR0FBRyxJQUFJLEdBQUcsQ0FBQyxNQUFNLENBQUM7U0FDbkI7UUFDRCxPQUFPLE1BQU0sQ0FBQztJQUNoQixDQUFDLENBQUM7Q0FDSCIsInNvdXJjZXNDb250ZW50IjpbIi8vICMgTWVtSlMgdXRpbGl0eSBmdW5jdGlvbnNcblxuaW1wb3J0ICogYXMgaGVhZGVyIGZyb20gXCIuL2hlYWRlclwiO1xuaW1wb3J0IHsgT1AgfSBmcm9tIFwiLi9jb25zdGFudHNcIjtcblxuZXhwb3J0IHR5cGUgTWF5YmVCdWZmZXIgPSBzdHJpbmcgfCBCdWZmZXI7XG5cbmV4cG9ydCBjb25zdCBidWZmZXJpZnkgPSBmdW5jdGlvbiAodmFsOiBNYXliZUJ1ZmZlcikge1xuICByZXR1cm4gQnVmZmVyLmlzQnVmZmVyKHZhbCkgPyB2YWwgOiBCdWZmZXIuZnJvbSh2YWwgYXMgYW55KTtcbn07XG5cbmV4cG9ydCBpbnRlcmZhY2UgRW5jb2RhYmxlUmVxdWVzdCB7XG4gIGhlYWRlcjogT21pdDxcbiAgICBoZWFkZXIuSGVhZGVyLFxuICAgIFwibWFnaWNcIiB8IFwia2V5TGVuZ3RoXCIgfCBcImV4dHJhc0xlbmd0aFwiIHwgXCJ0b3RhbEJvZHlMZW5ndGhcIlxuICA+O1xuICBrZXk6IE1heWJlQnVmZmVyO1xuICBleHRyYXM6IE1heWJlQnVmZmVyO1xuICB2YWx1ZTogTWF5YmVCdWZmZXI7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBlbmNvZGVSZXF1ZXN0SW50b0J1ZmZlcihcbiAgYnVmZmVyOiBCdWZmZXIsXG4gIG9mZnNldDogbnVtYmVyLFxuICByZXF1ZXN0OiBFbmNvZGFibGVSZXF1ZXN0XG4pIHtcbiAgY29uc3Qga2V5ID0gYnVmZmVyaWZ5KHJlcXVlc3Qua2V5KTtcbiAgY29uc3QgZXh0cmFzID0gYnVmZmVyaWZ5KHJlcXVlc3QuZXh0cmFzKTtcbiAgY29uc3QgdmFsdWUgPSBidWZmZXJpZnkocmVxdWVzdC52YWx1ZSk7XG5cbiAgY29uc3QgYnVmVGFyZ2V0V3JpdGVPZmZzZXQgPSBvZmZzZXQgfHwgMDtcbiAgbGV0IHRvdGFsQnl0ZXNXcml0dGVuID0gMDtcbiAgZnVuY3Rpb24gY29weUludG9CdWZmZXIodG9Xcml0ZUJ1ZmZlcjogQnVmZmVyKSB7XG4gICAgY29uc3QgYnl0ZXNXcml0dGVuID0gdG9Xcml0ZUJ1ZmZlci5jb3B5KFxuICAgICAgYnVmZmVyLFxuICAgICAgYnVmVGFyZ2V0V3JpdGVPZmZzZXQgKyB0b3RhbEJ5dGVzV3JpdHRlblxuICAgICk7XG4gICAgdG90YWxCeXRlc1dyaXR0ZW4gKz0gYnl0ZXNXcml0dGVuO1xuICB9XG5cbiAgY29uc3QgcmVxdWVzdEhlYWRlcjogaGVhZGVyLkhlYWRlciA9IHtcbiAgICAuLi5yZXF1ZXN0LmhlYWRlcixcbiAgICBtYWdpYzogMHg4MCxcbiAgICBrZXlMZW5ndGg6IGtleS5sZW5ndGgsXG4gICAgZXh0cmFzTGVuZ3RoOiBleHRyYXMubGVuZ3RoLFxuICAgIHRvdGFsQm9keUxlbmd0aDoga2V5Lmxlbmd0aCArIHZhbHVlLmxlbmd0aCArIGV4dHJhcy5sZW5ndGgsXG4gIH07XG5cbiAgY29uc3QgaGVhZGVyQnVmZmVyID0gaGVhZGVyLnRvQnVmZmVyKHJlcXVlc3RIZWFkZXIpO1xuXG4gIGNvcHlJbnRvQnVmZmVyKGhlYWRlckJ1ZmZlcik7XG4gIGNvcHlJbnRvQnVmZmVyKGV4dHJhcyk7XG4gIGNvcHlJbnRvQnVmZmVyKGtleSk7XG4gIGNvcHlJbnRvQnVmZmVyKHZhbHVlKTtcblxuICByZXR1cm4gdG90YWxCeXRlc1dyaXR0ZW47XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBlbmNvZGVSZXF1ZXN0KHJlcXVlc3Q6IEVuY29kYWJsZVJlcXVlc3QpOiBCdWZmZXIge1xuICBjb25zdCBrZXkgPSBidWZmZXJpZnkocmVxdWVzdC5rZXkpO1xuICBjb25zdCBleHRyYXMgPSBidWZmZXJpZnkocmVxdWVzdC5leHRyYXMpO1xuICBjb25zdCB2YWx1ZSA9IGJ1ZmZlcmlmeShyZXF1ZXN0LnZhbHVlKTtcbiAgY29uc3QgYnVmU2l6ZSA9IDI0ICsga2V5Lmxlbmd0aCArIGV4dHJhcy5sZW5ndGggKyB2YWx1ZS5sZW5ndGg7XG4gIGNvbnN0IGJ1ZmZlciA9IEJ1ZmZlci5hbGxvYyhidWZTaXplKTtcbiAgZW5jb2RlUmVxdWVzdEludG9CdWZmZXIoYnVmZmVyLCAwLCB7XG4gICAgLi4ucmVxdWVzdCxcbiAgICBrZXksXG4gICAgZXh0cmFzLFxuICAgIHZhbHVlLFxuICB9KTtcbiAgcmV0dXJuIGJ1ZmZlcjtcbn1cblxuZXhwb3J0IGNvbnN0IGNvcHlJbnRvUmVxdWVzdEJ1ZmZlciA9IGZ1bmN0aW9uIChcbiAgb3Bjb2RlOiBPUCxcbiAga2V5OiBNYXliZUJ1ZmZlcixcbiAgZXh0cmFzOiBNYXliZUJ1ZmZlcixcbiAgdmFsdWU6IE1heWJlQnVmZmVyLFxuICBvcGFxdWU6IG51bWJlcixcbiAgYnVmOiBCdWZmZXIsXG4gIF9idWZUYXJnZXRXcml0ZU9mZnNldD86IG51bWJlclxuKSB7XG4gIHJldHVybiBlbmNvZGVSZXF1ZXN0SW50b0J1ZmZlcihidWYsIF9idWZUYXJnZXRXcml0ZU9mZnNldCB8fCAwLCB7XG4gICAgaGVhZGVyOiB7XG4gICAgICBvcGNvZGUsXG4gICAgICBvcGFxdWUsXG4gICAgfSxcbiAgICBrZXksXG4gICAgZXh0cmFzLFxuICAgIHZhbHVlLFxuICB9KTtcbn07XG5cbmV4cG9ydCBjb25zdCBtYWtlUmVxdWVzdEJ1ZmZlciA9IGZ1bmN0aW9uIChcbiAgb3Bjb2RlOiBPUCxcbiAga2V5OiBNYXliZUJ1ZmZlcixcbiAgZXh0cmFzOiBNYXliZUJ1ZmZlcixcbiAgdmFsdWU6IE1heWJlQnVmZmVyLFxuICBvcGFxdWU/OiBudW1iZXJcbikge1xuICByZXR1cm4gZW5jb2RlUmVxdWVzdCh7XG4gICAgZXh0cmFzLFxuICAgIGtleSxcbiAgICB2YWx1ZSxcbiAgICBoZWFkZXI6IHtcbiAgICAgIG9wY29kZSxcbiAgICAgIG9wYXF1ZTogb3BhcXVlIHx8IDAsXG4gICAgfSxcbiAgfSk7XG59O1xuXG5leHBvcnQgY29uc3QgbWFrZUFtb3VudEluaXRpYWxBbmRFeHBpcmF0aW9uID0gZnVuY3Rpb24gKFxuICBhbW91bnQ6IG51bWJlcixcbiAgYW1vdW50SWZFbXB0eTogbnVtYmVyLFxuICBleHBpcmF0aW9uOiBudW1iZXJcbikge1xuICBjb25zdCBidWYgPSBCdWZmZXIuYWxsb2MoMjApO1xuICBidWYud3JpdGVVSW50MzJCRSgwLCAwKTtcbiAgYnVmLndyaXRlVUludDMyQkUoYW1vdW50LCA0KTtcbiAgYnVmLndyaXRlVUludDMyQkUoMCwgOCk7XG4gIGJ1Zi53cml0ZVVJbnQzMkJFKGFtb3VudElmRW1wdHksIDEyKTtcbiAgYnVmLndyaXRlVUludDMyQkUoZXhwaXJhdGlvbiwgMTYpO1xuICByZXR1cm4gYnVmO1xufTtcblxuZXhwb3J0IGNvbnN0IG1ha2VFeHBpcmF0aW9uID0gZnVuY3Rpb24gKGV4cGlyYXRpb246IG51bWJlcikge1xuICBjb25zdCBidWYgPSBCdWZmZXIuYWxsb2MoNCk7XG4gIGJ1Zi53cml0ZVVJbnQzMkJFKGV4cGlyYXRpb24sIDApO1xuICByZXR1cm4gYnVmO1xufTtcblxuZXhwb3J0IGNvbnN0IGhhc2hDb2RlID0gZnVuY3Rpb24gKHN0cjogc3RyaW5nKSB7XG4gIGxldCByZXQsIGksIGxlbjtcbiAgZm9yIChyZXQgPSAwLCBpID0gMCwgbGVuID0gc3RyLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgcmV0ID0gKDMxICogcmV0ICsgc3RyLmNoYXJDb2RlQXQoaSkpIDw8IDA7XG4gIH1cbiAgcmV0dXJuIE1hdGguYWJzKHJldCk7XG59O1xuXG5leHBvcnQgaW50ZXJmYWNlIE1lc3NhZ2Uge1xuICBoZWFkZXI6IGhlYWRlci5IZWFkZXI7XG4gIGtleTogQnVmZmVyO1xuICB2YWw6IEJ1ZmZlcjtcbiAgZXh0cmFzOiBCdWZmZXI7XG59XG5cbmNvbnN0IEVSUk9SX1RPT19NQU5ZX09QRU5fQ09OTkVDVElPTlMgPSBcIkVSUk9SIFRvbyBtYW55IG9wZW4gY29ubmVjdGlvbnNcXHJcXG5cIjtcblxuZXhwb3J0IGNvbnN0IHBhcnNlTWVzc2FnZSA9IGZ1bmN0aW9uIChkYXRhQnVmOiBCdWZmZXIpOiBNZXNzYWdlIHwgZmFsc2Uge1xuICBpZiAoZGF0YUJ1Zi5sZW5ndGggPCAyNCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGlmIChkYXRhQnVmLmxlbmd0aCA9PT0gRVJST1JfVE9PX01BTllfT1BFTl9DT05ORUNUSU9OUy5sZW5ndGgpIHtcbiAgICBpZiAoZGF0YUJ1Zi50b1N0cmluZygpID09PSBFUlJPUl9UT09fTUFOWV9PUEVOX0NPTk5FQ1RJT05TKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJFUlJPUiBUb28gbWFueSBvcGVuIGNvbm5lY3Rpb25zXCIpO1xuICAgIH1cbiAgfVxuXG4gIGNvbnN0IHJlc3BvbnNlSGVhZGVyID0gaGVhZGVyLmZyb21CdWZmZXIoZGF0YUJ1Zik7XG5cbiAgaWYgKFxuICAgIGRhdGFCdWYubGVuZ3RoIDwgcmVzcG9uc2VIZWFkZXIudG90YWxCb2R5TGVuZ3RoICsgMjQgfHxcbiAgICByZXNwb25zZUhlYWRlci50b3RhbEJvZHlMZW5ndGggPFxuICAgICAgcmVzcG9uc2VIZWFkZXIua2V5TGVuZ3RoICsgcmVzcG9uc2VIZWFkZXIuZXh0cmFzTGVuZ3RoXG4gICkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGxldCBwb2ludGVyID0gMjQ7XG4gIGNvbnN0IGV4dHJhcyA9IGRhdGFCdWYuc2xpY2UocG9pbnRlciwgcG9pbnRlciArIHJlc3BvbnNlSGVhZGVyLmV4dHJhc0xlbmd0aCk7XG4gIHBvaW50ZXIgKz0gcmVzcG9uc2VIZWFkZXIuZXh0cmFzTGVuZ3RoO1xuICBjb25zdCBrZXkgPSBkYXRhQnVmLnNsaWNlKHBvaW50ZXIsIHBvaW50ZXIgKyByZXNwb25zZUhlYWRlci5rZXlMZW5ndGgpO1xuICBwb2ludGVyICs9IHJlc3BvbnNlSGVhZGVyLmtleUxlbmd0aDtcbiAgY29uc3QgdmFsID0gZGF0YUJ1Zi5zbGljZShwb2ludGVyLCAyNCArIHJlc3BvbnNlSGVhZGVyLnRvdGFsQm9keUxlbmd0aCk7XG5cbiAgcmV0dXJuIHsgaGVhZGVyOiByZXNwb25zZUhlYWRlciwga2V5OiBrZXksIGV4dHJhczogZXh0cmFzLCB2YWw6IHZhbCB9O1xufTtcblxuZXhwb3J0IGNvbnN0IHBhcnNlTWVzc2FnZXMgPSBmdW5jdGlvbiAoZGF0YUJ1ZjogQnVmZmVyKTogTWVzc2FnZVtdIHtcbiAgY29uc3QgbWVzc2FnZXMgPSBbXTtcblxuICBsZXQgbWVzc2FnZTogTWVzc2FnZTtcblxuICBkbyB7XG4gICAgbWVzc2FnZSA9IGV4cG9ydHMucGFyc2VNZXNzYWdlKGRhdGFCdWYpO1xuICAgIGlmIChtZXNzYWdlKSB7XG4gICAgICBtZXNzYWdlcy5wdXNoKG1lc3NhZ2UpO1xuICAgICAgY29uc3QgbWVzc2FnZUxlbmd0aCA9IG1lc3NhZ2UuaGVhZGVyLnRvdGFsQm9keUxlbmd0aCArIDI0O1xuICAgICAgZGF0YUJ1ZiA9IGRhdGFCdWYuc2xpY2UobWVzc2FnZUxlbmd0aCk7XG4gICAgfVxuICB9IHdoaWxlIChtZXNzYWdlKTtcblxuICByZXR1cm4gbWVzc2FnZXM7XG59O1xuXG5leHBvcnQgY29uc3QgbWVyZ2UgPSBmdW5jdGlvbiA8VD4ob3JpZ2luYWw6IGFueSwgZGVmbHQ6IFQpOiBUIHtcbiAgZm9yIChsZXQgYXR0clQgb2YgT2JqZWN0LmtleXMoZGVmbHQpKSB7XG4gICAgY29uc3QgYXR0cjoga2V5b2YgVCA9IGF0dHJUIGFzIGFueTtcbiAgICBjb25zdCBvcmlnaW5hbFZhbHVlID0gb3JpZ2luYWxbYXR0cl07XG5cbiAgICBpZiAob3JpZ2luYWxWYWx1ZSA9PT0gdW5kZWZpbmVkIHx8IG9yaWdpbmFsVmFsdWUgPT09IG51bGwpIHtcbiAgICAgIG9yaWdpbmFsW2F0dHJdID0gZGVmbHRbYXR0cl0gYXMgYW55O1xuICAgIH1cbiAgfVxuICByZXR1cm4gb3JpZ2luYWw7XG59O1xuXG4vLyB0aW1lc3RhbXAgcHJvdmlkZXMgYSBtb25vdG9uaWMgdGltZXN0YW1wIHdpdGggbWlsbGlzZWNvbmQgYWNjdXJhY3ksIHVzZWZ1bFxuLy8gZm9yIHRpbWVycy5cbmV4cG9ydCBjb25zdCB0aW1lc3RhbXAgPSBmdW5jdGlvbiAoKSB7XG4gIGNvbnN0IHRpbWVzID0gcHJvY2Vzcy5ocnRpbWUoKTtcbiAgcmV0dXJuIHRpbWVzWzBdICogMTAwMCArIE1hdGgucm91bmQodGltZXNbMV0gLyAxMDAwMDAwKTtcbn07XG5cbmlmICghQnVmZmVyLmNvbmNhdCkge1xuICBCdWZmZXIuY29uY2F0ID0gZnVuY3Rpb24gKGxpc3QsIGxlbmd0aCkge1xuICAgIGlmICghQXJyYXkuaXNBcnJheShsaXN0KSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiVXNhZ2U6IEJ1ZmZlci5jb25jYXQobGlzdCwgW2xlbmd0aF0pXCIpO1xuICAgIH1cblxuICAgIGlmIChsaXN0Lmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuIEJ1ZmZlci5hbGxvYygwKTtcbiAgICB9XG4gICAgaWYgKGxpc3QubGVuZ3RoID09PSAxKSB7XG4gICAgICByZXR1cm4gbGlzdFswXTtcbiAgICB9XG5cbiAgICBsZXQgaTogbnVtYmVyO1xuICAgIGxldCBidWY6IEJ1ZmZlcjtcblxuICAgIGlmICh0eXBlb2YgbGVuZ3RoICE9PSBcIm51bWJlclwiKSB7XG4gICAgICBsZW5ndGggPSAwO1xuICAgICAgZm9yIChpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgYnVmID0gbGlzdFtpXTtcbiAgICAgICAgbGVuZ3RoICs9IGJ1Zi5sZW5ndGg7XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgYnVmZmVyID0gQnVmZmVyLmFsbG9jKGxlbmd0aCk7XG4gICAgbGV0IHBvcyA9IDA7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICBidWYgPSBsaXN0W2ldO1xuICAgICAgYnVmLmNvcHkoYnVmZmVyLCBwb3MpO1xuICAgICAgcG9zICs9IGJ1Zi5sZW5ndGg7XG4gICAgfVxuICAgIHJldHVybiBidWZmZXI7XG4gIH07XG59XG4iXX0= \ No newline at end of file diff --git a/lotofconnstest.js b/lotofconnstest.js new file mode 100755 index 0000000..26c3eab --- /dev/null +++ b/lotofconnstest.js @@ -0,0 +1,56 @@ +#! node +const MemJS = require("."); + +async function nextTick() { + return new Promise((resolve) => setImmediate(resolve)); +} + +const clients = []; + +async function body() { + // local memcached is default 1024 max connections + for (let i = 0; i < 1025; i++) { + const client = MemJS.Client.create(undefined, {timeout: 1, connTimeout: 2, retries: 1}); + console.log("created", i); + + client.servers.forEach((server) => { + server.onConnect((sock) => { + console.log("connected", i); + + sock.once("close", (err) => { + console.log("closed", i, err); + }) + sock.once("error", (err) => { + console.log("error handler", i, err); + }) + }) + }) + + try { + await client.get("foo"); + console.log(i) + } catch (error) { + console.log("error", error, i); + } + + clients.push(client); + } + +} + +async function main() { + try { + await body(); + console.log("smoketest ok"); + } catch (error) { + console.error("fatal", error); + process.exit(1); + } finally { + clients.forEach((client) => { + client.servers.forEach((server) => server._socket?.removeAllListeners("close")); + client.quit() + }); + } +} + +main(); diff --git a/src/memjs/server.ts b/src/memjs/server.ts index b4c9184..03890ca 100644 --- a/src/memjs/server.ts +++ b/src/memjs/server.ts @@ -151,7 +151,14 @@ export class Server extends events.EventEmitter { return this.responseBuffer; } responseHandler(dataBuf: Buffer) { - let response = parseMessage(this.appendToBuffer(dataBuf)); + let response: Message | false; + try { + response = parseMessage(this.appendToBuffer(dataBuf)); + } catch (e) { + this.error(e as Error); + return; + } + let respLength: number; while (response) { if (response.header.opcode === 0x20) { @@ -218,6 +225,9 @@ export class Server extends events.EventEmitter { }); self._socket.on("close", function () { + if (Object.keys(self.errorCallbacks).length > 0) { + self.error(new Error("socket closed unexpectedly.")); + } self.connected = false; if (self.timeoutSet) { self._socket?.setTimeout(0); diff --git a/src/memjs/utils.ts b/src/memjs/utils.ts index 39e7a59..9f4cd3f 100644 --- a/src/memjs/utils.ts +++ b/src/memjs/utils.ts @@ -144,10 +144,19 @@ export interface Message { extras: Buffer; } +const ERROR_TOO_MANY_OPEN_CONNECTIONS = "ERROR Too many open connections\r\n"; + export const parseMessage = function (dataBuf: Buffer): Message | false { if (dataBuf.length < 24) { return false; } + + if (dataBuf.length === ERROR_TOO_MANY_OPEN_CONNECTIONS.length) { + if (dataBuf.toString() === ERROR_TOO_MANY_OPEN_CONNECTIONS) { + throw new Error("ERROR Too many open connections"); + } + } + const responseHeader = header.fromBuffer(dataBuf); if ( diff --git a/src/test/server_test.js b/src/test/server_test.js index 7ffabe6..d64377a 100644 --- a/src/test/server_test.js +++ b/src/test/server_test.js @@ -35,6 +35,20 @@ test('ResponseHandler with authentication error', function(t) { t.end(); }); +test('ResponseHandler with too many connections error', function(t) { + const server = new MemJS.Server('localhost', 11211); + + server.onError('test', function(err) { + t.equal('ERROR Too many open connections', err.message); + }); + + const responseBuf = Buffer.from('ERROR Too many open connections\r\n'); + + server.responseHandler(responseBuf); + + t.end(); +}); + test('Authenticate', function(t) { const expectedBuf = makeRequestBuffer(0x21, 'PLAIN', '', '\0user1\0password'); const dummySocket = { From cb1693c5fdf24b485de2e898de13dda94022dfd5 Mon Sep 17 00:00:00 2001 From: Ben Hughes Date: Tue, 3 Oct 2023 14:53:56 -0400 Subject: [PATCH 72/79] Comment error string --- lib/memjs/utils.d.ts.map | 2 +- lib/memjs/utils.js | 5 ++++- src/memjs/utils.ts | 3 +++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/memjs/utils.d.ts.map b/lib/memjs/utils.d.ts.map index 1394895..29bfad7 100644 --- a/lib/memjs/utils.d.ts.map +++ b/lib/memjs/utils.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/memjs/utils.ts"],"names":[],"mappings":";AAEA,OAAO,KAAK,MAAM,MAAM,UAAU,CAAC;AACnC,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AAEjC,oBAAY,WAAW,GAAG,MAAM,GAAG,MAAM,CAAC;AAE1C,eAAO,MAAM,SAAS,QAAkB,WAAW,WAElD,CAAC;AAEF,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,IAAI,CACV,MAAM,CAAC,MAAM,EACb,OAAO,GAAG,WAAW,GAAG,cAAc,GAAG,iBAAiB,CAC3D,CAAC;IACF,GAAG,EAAE,WAAW,CAAC;IACjB,MAAM,EAAE,WAAW,CAAC;IACpB,KAAK,EAAE,WAAW,CAAC;CACpB;AAED,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,gBAAgB,UAgC1B;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,gBAAgB,GAAG,MAAM,CAa/D;AAED,eAAO,MAAM,qBAAqB,WACxB,EAAE,OACL,WAAW,UACR,WAAW,SACZ,WAAW,UACV,MAAM,OACT,MAAM,uDAYZ,CAAC;AAEF,eAAO,MAAM,iBAAiB,WACpB,EAAE,OACL,WAAW,UACR,WAAW,SACZ,WAAW,wCAYnB,CAAC;AAEF,eAAO,MAAM,8BAA8B,WACjC,MAAM,iBACC,MAAM,cACT,MAAM,WASnB,CAAC;AAEF,eAAO,MAAM,cAAc,eAAyB,MAAM,WAIzD,CAAC;AAEF,eAAO,MAAM,QAAQ,QAAkB,MAAM,WAM5C,CAAC;AAEF,MAAM,WAAW,OAAO;IACtB,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;CAChB;AAID,eAAO,MAAM,YAAY,YAAsB,MAAM,KAAG,OAAO,GAAG,KA6BjE,CAAC;AAEF,eAAO,MAAM,aAAa,YAAsB,MAAM,KAAG,OAAO,EAe/D,CAAC;AAEF,eAAO,MAAM,KAAK,gBAA0B,GAAG,gBAU9C,CAAC;AAIF,eAAO,MAAM,SAAS,cAGrB,CAAC"} \ No newline at end of file +{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/memjs/utils.ts"],"names":[],"mappings":";AAEA,OAAO,KAAK,MAAM,MAAM,UAAU,CAAC;AACnC,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AAEjC,oBAAY,WAAW,GAAG,MAAM,GAAG,MAAM,CAAC;AAE1C,eAAO,MAAM,SAAS,QAAkB,WAAW,WAElD,CAAC;AAEF,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,IAAI,CACV,MAAM,CAAC,MAAM,EACb,OAAO,GAAG,WAAW,GAAG,cAAc,GAAG,iBAAiB,CAC3D,CAAC;IACF,GAAG,EAAE,WAAW,CAAC;IACjB,MAAM,EAAE,WAAW,CAAC;IACpB,KAAK,EAAE,WAAW,CAAC;CACpB;AAED,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,gBAAgB,UAgC1B;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,gBAAgB,GAAG,MAAM,CAa/D;AAED,eAAO,MAAM,qBAAqB,WACxB,EAAE,OACL,WAAW,UACR,WAAW,SACZ,WAAW,UACV,MAAM,OACT,MAAM,uDAYZ,CAAC;AAEF,eAAO,MAAM,iBAAiB,WACpB,EAAE,OACL,WAAW,UACR,WAAW,SACZ,WAAW,wCAYnB,CAAC;AAEF,eAAO,MAAM,8BAA8B,WACjC,MAAM,iBACC,MAAM,cACT,MAAM,WASnB,CAAC;AAEF,eAAO,MAAM,cAAc,eAAyB,MAAM,WAIzD,CAAC;AAEF,eAAO,MAAM,QAAQ,QAAkB,MAAM,WAM5C,CAAC;AAEF,MAAM,WAAW,OAAO;IACtB,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;CAChB;AAOD,eAAO,MAAM,YAAY,YAAsB,MAAM,KAAG,OAAO,GAAG,KA6BjE,CAAC;AAEF,eAAO,MAAM,aAAa,YAAsB,MAAM,KAAG,OAAO,EAe/D,CAAC;AAEF,eAAO,MAAM,KAAK,gBAA0B,GAAG,gBAU9C,CAAC;AAIF,eAAO,MAAM,SAAS,cAGrB,CAAC"} \ No newline at end of file diff --git a/lib/memjs/utils.js b/lib/memjs/utils.js index 3179851..10dddd7 100644 --- a/lib/memjs/utils.js +++ b/lib/memjs/utils.js @@ -114,6 +114,9 @@ const hashCode = function (str) { return Math.abs(ret); }; exports.hashCode = hashCode; +// Error message from memcached when it rejects a request for having too many +// open connections +// https://github.com/memcached/memcached/blob/efee763c93249358ea5b3b42c7fd4e57e2599c30/memcached.c#L3044 const ERROR_TOO_MANY_OPEN_CONNECTIONS = "ERROR Too many open connections\r\n"; const parseMessage = function (dataBuf) { if (dataBuf.length < 24) { @@ -201,4 +204,4 @@ if (!Buffer.concat) { return buffer; }; } -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbWVtanMvdXRpbHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLDRCQUE0Qjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUU1QixpREFBbUM7QUFLNUIsTUFBTSxTQUFTLEdBQUcsVUFBVSxHQUFnQjtJQUNqRCxPQUFPLE1BQU0sQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFVLENBQUMsQ0FBQztBQUM5RCxDQUFDLENBQUM7QUFGVyxRQUFBLFNBQVMsYUFFcEI7QUFZRixTQUFnQix1QkFBdUIsQ0FDckMsTUFBYyxFQUNkLE1BQWMsRUFDZCxPQUF5QjtJQUV6QixNQUFNLEdBQUcsR0FBRyxpQkFBUyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNuQyxNQUFNLE1BQU0sR0FBRyxpQkFBUyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUN6QyxNQUFNLEtBQUssR0FBRyxpQkFBUyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUV2QyxNQUFNLG9CQUFvQixHQUFHLE1BQU0sSUFBSSxDQUFDLENBQUM7SUFDekMsSUFBSSxpQkFBaUIsR0FBRyxDQUFDLENBQUM7SUFDMUIsU0FBUyxjQUFjLENBQUMsYUFBcUI7UUFDM0MsTUFBTSxZQUFZLEdBQUcsYUFBYSxDQUFDLElBQUksQ0FDckMsTUFBTSxFQUNOLG9CQUFvQixHQUFHLGlCQUFpQixDQUN6QyxDQUFDO1FBQ0YsaUJBQWlCLElBQUksWUFBWSxDQUFDO0lBQ3BDLENBQUM7SUFFRCxNQUFNLGFBQWEsR0FBa0I7UUFDbkMsR0FBRyxPQUFPLENBQUMsTUFBTTtRQUNqQixLQUFLLEVBQUUsSUFBSTtRQUNYLFNBQVMsRUFBRSxHQUFHLENBQUMsTUFBTTtRQUNyQixZQUFZLEVBQUUsTUFBTSxD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LE1BQU0sS0FBSyxDQUFDLEVBQUU7WUFDckIsT0FBTyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1NBQ3hCO1FBQ0QsSUFBSSxJQUFJLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRTtZQUNyQixPQUFPLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNoQjtRQUVELElBQUksQ0FBUyxDQUFDO1FBQ2QsSUFBSSxHQUFXLENBQUM7UUFFaEIsSUFBSSxPQUFPLE1BQU0sS0FBSyxRQUFRLEVBQUU7WUFDOUIsTUFBTSxHQUFHLENBQUMsQ0FBQztZQUNYLEtBQUssQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRTtnQkFDaEMsR0FBRyxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDZCxNQUFNLElBQUksR0FBRyxDQUFDLE1BQU0sQ0FBQzthQUN0QjtTQUNGO1FBRUQsTUFBTSxNQUFNLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUNwQyxJQUFJLEdBQUcsR0FBRyxDQUFDLENBQUM7UUFDWixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRTtZQUNwQyxHQUFHLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ2QsR0FBRyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUM7WUFDdEIsR0FBRyxJQUFJLEdBQUcsQ0FBQyxNQUFNLENBQUM7U0FDbkI7UUFDRCxPQUFPLE1BQU0sQ0FBQztJQUNoQixDQUFDLENBQUM7Q0FDSCIsInNvdXJjZXNDb250ZW50IjpbIi8vICMgTWVtSlMgdXRpbGl0eSBmdW5jdGlvbnNcblxuaW1wb3J0ICogYXMgaGVhZGVyIGZyb20gXCIuL2hlYWRlclwiO1xuaW1wb3J0IHsgT1AgfSBmcm9tIFwiLi9jb25zdGFudHNcIjtcblxuZXhwb3J0IHR5cGUgTWF5YmVCdWZmZXIgPSBzdHJpbmcgfCBCdWZmZXI7XG5cbmV4cG9ydCBjb25zdCBidWZmZXJpZnkgPSBmdW5jdGlvbiAodmFsOiBNYXliZUJ1ZmZlcikge1xuICByZXR1cm4gQnVmZmVyLmlzQnVmZmVyKHZhbCkgPyB2YWwgOiBCdWZmZXIuZnJvbSh2YWwgYXMgYW55KTtcbn07XG5cbmV4cG9ydCBpbnRlcmZhY2UgRW5jb2RhYmxlUmVxdWVzdCB7XG4gIGhlYWRlcjogT21pdDxcbiAgICBoZWFkZXIuSGVhZGVyLFxuICAgIFwibWFnaWNcIiB8IFwia2V5TGVuZ3RoXCIgfCBcImV4dHJhc0xlbmd0aFwiIHwgXCJ0b3RhbEJvZHlMZW5ndGhcIlxuICA+O1xuICBrZXk6IE1heWJlQnVmZmVyO1xuICBleHRyYXM6IE1heWJlQnVmZmVyO1xuICB2YWx1ZTogTWF5YmVCdWZmZXI7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBlbmNvZGVSZXF1ZXN0SW50b0J1ZmZlcihcbiAgYnVmZmVyOiBCdWZmZXIsXG4gIG9mZnNldDogbnVtYmVyLFxuICByZXF1ZXN0OiBFbmNvZGFibGVSZXF1ZXN0XG4pIHtcbiAgY29uc3Qga2V5ID0gYnVmZmVyaWZ5KHJlcXVlc3Qua2V5KTtcbiAgY29uc3QgZXh0cmFzID0gYnVmZmVyaWZ5KHJlcXVlc3QuZXh0cmFzKTtcbiAgY29uc3QgdmFsdWUgPSBidWZmZXJpZnkocmVxdWVzdC52YWx1ZSk7XG5cbiAgY29uc3QgYnVmVGFyZ2V0V3JpdGVPZmZzZXQgPSBvZmZzZXQgfHwgMDtcbiAgbGV0IHRvdGFsQnl0ZXNXcml0dGVuID0gMDtcbiAgZnVuY3Rpb24gY29weUludG9CdWZmZXIodG9Xcml0ZUJ1ZmZlcjogQnVmZmVyKSB7XG4gICAgY29uc3QgYnl0ZXNXcml0dGVuID0gdG9Xcml0ZUJ1ZmZlci5jb3B5KFxuICAgICAgYnVmZmVyLFxuICAgICAgYnVmVGFyZ2V0V3JpdGVPZmZzZXQgKyB0b3RhbEJ5dGVzV3JpdHRlblxuICAgICk7XG4gICAgdG90YWxCeXRlc1dyaXR0ZW4gKz0gYnl0ZXNXcml0dGVuO1xuICB9XG5cbiAgY29uc3QgcmVxdWVzdEhlYWRlcjogaGVhZGVyLkhlYWRlciA9IHtcbiAgICAuLi5yZXF1ZXN0LmhlYWRlcixcbiAgICBtYWdpYzogMHg4MCxcbiAgICBrZXlMZW5ndGg6IGtleS5sZW5ndGgsXG4gICAgZXh0cmFzTGVuZ3RoOiBleHRyYXMubGVuZ3RoLFxuICAgIHRvdGFsQm9keUxlbmd0aDoga2V5Lmxlbmd0aCArIHZhbHVlLmxlbmd0aCArIGV4dHJhcy5sZW5ndGgsXG4gIH07XG5cbiAgY29uc3QgaGVhZGVyQnVmZmVyID0gaGVhZGVyLnRvQnVmZmVyKHJlcXVlc3RIZWFkZXIpO1xuXG4gIGNvcHlJbnRvQnVmZmVyKGhlYWRlckJ1ZmZlcik7XG4gIGNvcHlJbnRvQnVmZmVyKGV4dHJhcyk7XG4gIGNvcHlJbnRvQnVmZmVyKGtleSk7XG4gIGNvcHlJbnRvQnVmZmVyKHZhbHVlKTtcblxuICByZXR1cm4gdG90YWxCeXRlc1dyaXR0ZW47XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBlbmNvZGVSZXF1ZXN0KHJlcXVlc3Q6IEVuY29kYWJsZVJlcXVlc3QpOiBCdWZmZXIge1xuICBjb25zdCBrZXkgPSBidWZmZXJpZnkocmVxdWVzdC5rZXkpO1xuICBjb25zdCBleHRyYXMgPSBidWZmZXJpZnkocmVxdWVzdC5leHRyYXMpO1xuICBjb25zdCB2YWx1ZSA9IGJ1ZmZlcmlmeShyZXF1ZXN0LnZhbHVlKTtcbiAgY29uc3QgYnVmU2l6ZSA9IDI0ICsga2V5Lmxlbmd0aCArIGV4dHJhcy5sZW5ndGggKyB2YWx1ZS5sZW5ndGg7XG4gIGNvbnN0IGJ1ZmZlciA9IEJ1ZmZlci5hbGxvYyhidWZTaXplKTtcbiAgZW5jb2RlUmVxdWVzdEludG9CdWZmZXIoYnVmZmVyLCAwLCB7XG4gICAgLi4ucmVxdWVzdCxcbiAgICBrZXksXG4gICAgZXh0cmFzLFxuICAgIHZhbHVlLFxuICB9KTtcbiAgcmV0dXJuIGJ1ZmZlcjtcbn1cblxuZXhwb3J0IGNvbnN0IGNvcHlJbnRvUmVxdWVzdEJ1ZmZlciA9IGZ1bmN0aW9uIChcbiAgb3Bjb2RlOiBPUCxcbiAga2V5OiBNYXliZUJ1ZmZlcixcbiAgZXh0cmFzOiBNYXliZUJ1ZmZlcixcbiAgdmFsdWU6IE1heWJlQnVmZmVyLFxuICBvcGFxdWU6IG51bWJlcixcbiAgYnVmOiBCdWZmZXIsXG4gIF9idWZUYXJnZXRXcml0ZU9mZnNldD86IG51bWJlclxuKSB7XG4gIHJldHVybiBlbmNvZGVSZXF1ZXN0SW50b0J1ZmZlcihidWYsIF9idWZUYXJnZXRXcml0ZU9mZnNldCB8fCAwLCB7XG4gICAgaGVhZGVyOiB7XG4gICAgICBvcGNvZGUsXG4gICAgICBvcGFxdWUsXG4gICAgfSxcbiAgICBrZXksXG4gICAgZXh0cmFzLFxuICAgIHZhbHVlLFxuICB9KTtcbn07XG5cbmV4cG9ydCBjb25zdCBtYWtlUmVxdWVzdEJ1ZmZlciA9IGZ1bmN0aW9uIChcbiAgb3Bjb2RlOiBPUCxcbiAga2V5OiBNYXliZUJ1ZmZlcixcbiAgZXh0cmFzOiBNYXliZUJ1ZmZlcixcbiAgdmFsdWU6IE1heWJlQnVmZmVyLFxuICBvcGFxdWU/OiBudW1iZXJcbikge1xuICByZXR1cm4gZW5jb2RlUmVxdWVzdCh7XG4gICAgZXh0cmFzLFxuICAgIGtleSxcbiAgICB2YWx1ZSxcbiAgICBoZWFkZXI6IHtcbiAgICAgIG9wY29kZSxcbiAgICAgIG9wYXF1ZTogb3BhcXVlIHx8IDAsXG4gICAgfSxcbiAgfSk7XG59O1xuXG5leHBvcnQgY29uc3QgbWFrZUFtb3VudEluaXRpYWxBbmRFeHBpcmF0aW9uID0gZnVuY3Rpb24gKFxuICBhbW91bnQ6IG51bWJlcixcbiAgYW1vdW50SWZFbXB0eTogbnVtYmVyLFxuICBleHBpcmF0aW9uOiBudW1iZXJcbikge1xuICBjb25zdCBidWYgPSBCdWZmZXIuYWxsb2MoMjApO1xuICBidWYud3JpdGVVSW50MzJCRSgwLCAwKTtcbiAgYnVmLndyaXRlVUludDMyQkUoYW1vdW50LCA0KTtcbiAgYnVmLndyaXRlVUludDMyQkUoMCwgOCk7XG4gIGJ1Zi53cml0ZVVJbnQzMkJFKGFtb3VudElmRW1wdHksIDEyKTtcbiAgYnVmLndyaXRlVUludDMyQkUoZXhwaXJhdGlvbiwgMTYpO1xuICByZXR1cm4gYnVmO1xufTtcblxuZXhwb3J0IGNvbnN0IG1ha2VFeHBpcmF0aW9uID0gZnVuY3Rpb24gKGV4cGlyYXRpb246IG51bWJlcikge1xuICBjb25zdCBidWYgPSBCdWZmZXIuYWxsb2MoNCk7XG4gIGJ1Zi53cml0ZVVJbnQzMkJFKGV4cGlyYXRpb24sIDApO1xuICByZXR1cm4gYnVmO1xufTtcblxuZXhwb3J0IGNvbnN0IGhhc2hDb2RlID0gZnVuY3Rpb24gKHN0cjogc3RyaW5nKSB7XG4gIGxldCByZXQsIGksIGxlbjtcbiAgZm9yIChyZXQgPSAwLCBpID0gMCwgbGVuID0gc3RyLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgcmV0ID0gKDMxICogcmV0ICsgc3RyLmNoYXJDb2RlQXQoaSkpIDw8IDA7XG4gIH1cbiAgcmV0dXJuIE1hdGguYWJzKHJldCk7XG59O1xuXG5leHBvcnQgaW50ZXJmYWNlIE1lc3NhZ2Uge1xuICBoZWFkZXI6IGhlYWRlci5IZWFkZXI7XG4gIGtleTogQnVmZmVyO1xuICB2YWw6IEJ1ZmZlcjtcbiAgZXh0cmFzOiBCdWZmZXI7XG59XG5cbmNvbnN0IEVSUk9SX1RPT19NQU5ZX09QRU5fQ09OTkVDVElPTlMgPSBcIkVSUk9SIFRvbyBtYW55IG9wZW4gY29ubmVjdGlvbnNcXHJcXG5cIjtcblxuZXhwb3J0IGNvbnN0IHBhcnNlTWVzc2FnZSA9IGZ1bmN0aW9uIChkYXRhQnVmOiBCdWZmZXIpOiBNZXNzYWdlIHwgZmFsc2Uge1xuICBpZiAoZGF0YUJ1Zi5sZW5ndGggPCAyNCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGlmIChkYXRhQnVmLmxlbmd0aCA9PT0gRVJST1JfVE9PX01BTllfT1BFTl9DT05ORUNUSU9OUy5sZW5ndGgpIHtcbiAgICBpZiAoZGF0YUJ1Zi50b1N0cmluZygpID09PSBFUlJPUl9UT09fTUFOWV9PUEVOX0NPTk5FQ1RJT05TKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJFUlJPUiBUb28gbWFueSBvcGVuIGNvbm5lY3Rpb25zXCIpO1xuICAgIH1cbiAgfVxuXG4gIGNvbnN0IHJlc3BvbnNlSGVhZGVyID0gaGVhZGVyLmZyb21CdWZmZXIoZGF0YUJ1Zik7XG5cbiAgaWYgKFxuICAgIGRhdGFCdWYubGVuZ3RoIDwgcmVzcG9uc2VIZWFkZXIudG90YWxCb2R5TGVuZ3RoICsgMjQgfHxcbiAgICByZXNwb25zZUhlYWRlci50b3RhbEJvZHlMZW5ndGggPFxuICAgICAgcmVzcG9uc2VIZWFkZXIua2V5TGVuZ3RoICsgcmVzcG9uc2VIZWFkZXIuZXh0cmFzTGVuZ3RoXG4gICkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGxldCBwb2ludGVyID0gMjQ7XG4gIGNvbnN0IGV4dHJhcyA9IGRhdGFCdWYuc2xpY2UocG9pbnRlciwgcG9pbnRlciArIHJlc3BvbnNlSGVhZGVyLmV4dHJhc0xlbmd0aCk7XG4gIHBvaW50ZXIgKz0gcmVzcG9uc2VIZWFkZXIuZXh0cmFzTGVuZ3RoO1xuICBjb25zdCBrZXkgPSBkYXRhQnVmLnNsaWNlKHBvaW50ZXIsIHBvaW50ZXIgKyByZXNwb25zZUhlYWRlci5rZXlMZW5ndGgpO1xuICBwb2ludGVyICs9IHJlc3BvbnNlSGVhZGVyLmtleUxlbmd0aDtcbiAgY29uc3QgdmFsID0gZGF0YUJ1Zi5zbGljZShwb2ludGVyLCAyNCArIHJlc3BvbnNlSGVhZGVyLnRvdGFsQm9keUxlbmd0aCk7XG5cbiAgcmV0dXJuIHsgaGVhZGVyOiByZXNwb25zZUhlYWRlciwga2V5OiBrZXksIGV4dHJhczogZXh0cmFzLCB2YWw6IHZhbCB9O1xufTtcblxuZXhwb3J0IGNvbnN0IHBhcnNlTWVzc2FnZXMgPSBmdW5jdGlvbiAoZGF0YUJ1ZjogQnVmZmVyKTogTWVzc2FnZVtdIHtcbiAgY29uc3QgbWVzc2FnZXMgPSBbXTtcblxuICBsZXQgbWVzc2FnZTogTWVzc2FnZTtcblxuICBkbyB7XG4gICAgbWVzc2FnZSA9IGV4cG9ydHMucGFyc2VNZXNzYWdlKGRhdGFCdWYpO1xuICAgIGlmIChtZXNzYWdlKSB7XG4gICAgICBtZXNzYWdlcy5wdXNoKG1lc3NhZ2UpO1xuICAgICAgY29uc3QgbWVzc2FnZUxlbmd0aCA9IG1lc3NhZ2UuaGVhZGVyLnRvdGFsQm9keUxlbmd0aCArIDI0O1xuICAgICAgZGF0YUJ1ZiA9IGRhdGFCdWYuc2xpY2UobWVzc2FnZUxlbmd0aCk7XG4gICAgfVxuICB9IHdoaWxlIChtZXNzYWdlKTtcblxuICByZXR1cm4gbWVzc2FnZXM7XG59O1xuXG5leHBvcnQgY29uc3QgbWVyZ2UgPSBmdW5jdGlvbiA8VD4ob3JpZ2luYWw6IGFueSwgZGVmbHQ6IFQpOiBUIHtcbiAgZm9yIChsZXQgYXR0clQgb2YgT2JqZWN0LmtleXMoZGVmbHQpKSB7XG4gICAgY29uc3QgYXR0cjoga2V5b2YgVCA9IGF0dHJUIGFzIGFueTtcbiAgICBjb25zdCBvcmlnaW5hbFZhbHVlID0gb3JpZ2luYWxbYXR0cl07XG5cbiAgICBpZiAob3JpZ2luYWxWYWx1ZSA9PT0gdW5kZWZpbmVkIHx8IG9yaWdpbmFsVmFsdWUgPT09IG51bGwpIHtcbiAgICAgIG9yaWdpbmFsW2F0dHJdID0gZGVmbHRbYXR0cl0gYXMgYW55O1xuICAgIH1cbiAgfVxuICByZXR1cm4gb3JpZ2luYWw7XG59O1xuXG4vLyB0aW1lc3RhbXAgcHJvdmlkZXMgYSBtb25vdG9uaWMgdGltZXN0YW1wIHdpdGggbWlsbGlzZWNvbmQgYWNjdXJhY3ksIHVzZWZ1bFxuLy8gZm9yIHRpbWVycy5cbmV4cG9ydCBjb25zdCB0aW1lc3RhbXAgPSBmdW5jdGlvbiAoKSB7XG4gIGNvbnN0IHRpbWVzID0gcHJvY2Vzcy5ocnRpbWUoKTtcbiAgcmV0dXJuIHRpbWVzWzBdICogMTAwMCArIE1hdGgucm91bmQodGltZXNbMV0gLyAxMDAwMDAwKTtcbn07XG5cbmlmICghQnVmZmVyLmNvbmNhdCkge1xuICBCdWZmZXIuY29uY2F0ID0gZnVuY3Rpb24gKGxpc3QsIGxlbmd0aCkge1xuICAgIGlmICghQXJyYXkuaXNBcnJheShsaXN0KSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiVXNhZ2U6IEJ1ZmZlci5jb25jYXQobGlzdCwgW2xlbmd0aF0pXCIpO1xuICAgIH1cblxuICAgIGlmIChsaXN0Lmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuIEJ1ZmZlci5hbGxvYygwKTtcbiAgICB9XG4gICAgaWYgKGxpc3QubGVuZ3RoID09PSAxKSB7XG4gICAgICByZXR1cm4gbGlzdFswXTtcbiAgICB9XG5cbiAgICBsZXQgaTogbnVtYmVyO1xuICAgIGxldCBidWY6IEJ1ZmZlcjtcblxuICAgIGlmICh0eXBlb2YgbGVuZ3RoICE9PSBcIm51bWJlclwiKSB7XG4gICAgICBsZW5ndGggPSAwO1xuICAgICAgZm9yIChpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgYnVmID0gbGlzdFtpXTtcbiAgICAgICAgbGVuZ3RoICs9IGJ1Zi5sZW5ndGg7XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgYnVmZmVyID0gQnVmZmVyLmFsbG9jKGxlbmd0aCk7XG4gICAgbGV0IHBvcyA9IDA7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICBidWYgPSBsaXN0W2ldO1xuICAgICAgYnVmLmNvcHkoYnVmZmVyLCBwb3MpO1xuICAgICAgcG9zICs9IGJ1Zi5sZW5ndGg7XG4gICAgfVxuICAgIHJldHVybiBidWZmZXI7XG4gIH07XG59XG4iXX0= \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbWVtanMvdXRpbHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLDRCQUE0Qjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUU1QixpREFBbUM7QUFLNUIsTUFBTSxTQUFTLEdBQUcsVUFBVSxHQUFnQjtJQUNqRCxPQUFPLE1BQU0sQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFVLENBQUMsQ0FBQztBQUM5RCxDQUFDLENBQUM7QUFGVyxRQUFBLFNBQVMsYUFFcEI7QUFZRixTQUFnQix1QkFBdUIsQ0FDckMsTUFBYyxFQUNkLE1BQWMsRUFDZCxPQUF5QjtJQUV6QixNQUFNLEdBQUcsR0FBRyxpQkFBUyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNuQyxNQUFNLE1BQU0sR0FBRyxpQkFBUyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUN6QyxNQUFNLEtBQUssR0FBRyxpQkFBUyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUV2QyxNQUFNLG9CQUFvQixHQUFHLE1BQU0sSUFBSSxDQUFDLENBQUM7SUFDekMsSUFBSSxpQkFBaUIsR0FBRyxDQUFDLENBQUM7SUFDMUIsU0FBUyxjQUFjLENBQUMsYUFBcUI7UUFDM0MsTUFBTSxZQUFZLEdBQUcsYUFBYSxDQUFDLElBQUksQ0FDckMsTUFBTSxFQUNOLG9CQUFvQixHQUFHLGlCQUFpQixDQUN6QyxDQUFDO1FBQ0YsaUJBQWlCLElBQUksWUFBWSxDQUFDO0lBQ3BDLENBQUM7SUFFRCxNQUFNLGFBQWEsR0FBa0I7UUFDbkMsR0FBRyxPQUFPLENBQUMsTUFBTTtRQUNqQixLQUFLLEVBQUUsSUFBSTtRQUNYLFNBQVMsRUFBRSxHQUFHLENBQUMsTUFBTTtRQUNyQixZQUFZLEVBQUUsTUFBTSxD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QXNDLENBQUMsQ0FBQztTQUN6RDtRQUVELElBQUksSUFBSSxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUU7WUFDckIsT0FBTyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1NBQ3hCO1FBQ0QsSUFBSSxJQUFJLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRTtZQUNyQixPQUFPLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNoQjtRQUVELElBQUksQ0FBUyxDQUFDO1FBQ2QsSUFBSSxHQUFXLENBQUM7UUFFaEIsSUFBSSxPQUFPLE1BQU0sS0FBSyxRQUFRLEVBQUU7WUFDOUIsTUFBTSxHQUFHLENBQUMsQ0FBQztZQUNYLEtBQUssQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRTtnQkFDaEMsR0FBRyxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDZCxNQUFNLElBQUksR0FBRyxDQUFDLE1BQU0sQ0FBQzthQUN0QjtTQUNGO1FBRUQsTUFBTSxNQUFNLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUNwQyxJQUFJLEdBQUcsR0FBRyxDQUFDLENBQUM7UUFDWixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRTtZQUNwQyxHQUFHLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ2QsR0FBRyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUM7WUFDdEIsR0FBRyxJQUFJLEdBQUcsQ0FBQyxNQUFNLENBQUM7U0FDbkI7UUFDRCxPQUFPLE1BQU0sQ0FBQztJQUNoQixDQUFDLENBQUM7Q0FDSCIsInNvdXJjZXNDb250ZW50IjpbIi8vICMgTWVtSlMgdXRpbGl0eSBmdW5jdGlvbnNcblxuaW1wb3J0ICogYXMgaGVhZGVyIGZyb20gXCIuL2hlYWRlclwiO1xuaW1wb3J0IHsgT1AgfSBmcm9tIFwiLi9jb25zdGFudHNcIjtcblxuZXhwb3J0IHR5cGUgTWF5YmVCdWZmZXIgPSBzdHJpbmcgfCBCdWZmZXI7XG5cbmV4cG9ydCBjb25zdCBidWZmZXJpZnkgPSBmdW5jdGlvbiAodmFsOiBNYXliZUJ1ZmZlcikge1xuICByZXR1cm4gQnVmZmVyLmlzQnVmZmVyKHZhbCkgPyB2YWwgOiBCdWZmZXIuZnJvbSh2YWwgYXMgYW55KTtcbn07XG5cbmV4cG9ydCBpbnRlcmZhY2UgRW5jb2RhYmxlUmVxdWVzdCB7XG4gIGhlYWRlcjogT21pdDxcbiAgICBoZWFkZXIuSGVhZGVyLFxuICAgIFwibWFnaWNcIiB8IFwia2V5TGVuZ3RoXCIgfCBcImV4dHJhc0xlbmd0aFwiIHwgXCJ0b3RhbEJvZHlMZW5ndGhcIlxuICA+O1xuICBrZXk6IE1heWJlQnVmZmVyO1xuICBleHRyYXM6IE1heWJlQnVmZmVyO1xuICB2YWx1ZTogTWF5YmVCdWZmZXI7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBlbmNvZGVSZXF1ZXN0SW50b0J1ZmZlcihcbiAgYnVmZmVyOiBCdWZmZXIsXG4gIG9mZnNldDogbnVtYmVyLFxuICByZXF1ZXN0OiBFbmNvZGFibGVSZXF1ZXN0XG4pIHtcbiAgY29uc3Qga2V5ID0gYnVmZmVyaWZ5KHJlcXVlc3Qua2V5KTtcbiAgY29uc3QgZXh0cmFzID0gYnVmZmVyaWZ5KHJlcXVlc3QuZXh0cmFzKTtcbiAgY29uc3QgdmFsdWUgPSBidWZmZXJpZnkocmVxdWVzdC52YWx1ZSk7XG5cbiAgY29uc3QgYnVmVGFyZ2V0V3JpdGVPZmZzZXQgPSBvZmZzZXQgfHwgMDtcbiAgbGV0IHRvdGFsQnl0ZXNXcml0dGVuID0gMDtcbiAgZnVuY3Rpb24gY29weUludG9CdWZmZXIodG9Xcml0ZUJ1ZmZlcjogQnVmZmVyKSB7XG4gICAgY29uc3QgYnl0ZXNXcml0dGVuID0gdG9Xcml0ZUJ1ZmZlci5jb3B5KFxuICAgICAgYnVmZmVyLFxuICAgICAgYnVmVGFyZ2V0V3JpdGVPZmZzZXQgKyB0b3RhbEJ5dGVzV3JpdHRlblxuICAgICk7XG4gICAgdG90YWxCeXRlc1dyaXR0ZW4gKz0gYnl0ZXNXcml0dGVuO1xuICB9XG5cbiAgY29uc3QgcmVxdWVzdEhlYWRlcjogaGVhZGVyLkhlYWRlciA9IHtcbiAgICAuLi5yZXF1ZXN0LmhlYWRlcixcbiAgICBtYWdpYzogMHg4MCxcbiAgICBrZXlMZW5ndGg6IGtleS5sZW5ndGgsXG4gICAgZXh0cmFzTGVuZ3RoOiBleHRyYXMubGVuZ3RoLFxuICAgIHRvdGFsQm9keUxlbmd0aDoga2V5Lmxlbmd0aCArIHZhbHVlLmxlbmd0aCArIGV4dHJhcy5sZW5ndGgsXG4gIH07XG5cbiAgY29uc3QgaGVhZGVyQnVmZmVyID0gaGVhZGVyLnRvQnVmZmVyKHJlcXVlc3RIZWFkZXIpO1xuXG4gIGNvcHlJbnRvQnVmZmVyKGhlYWRlckJ1ZmZlcik7XG4gIGNvcHlJbnRvQnVmZmVyKGV4dHJhcyk7XG4gIGNvcHlJbnRvQnVmZmVyKGtleSk7XG4gIGNvcHlJbnRvQnVmZmVyKHZhbHVlKTtcblxuICByZXR1cm4gdG90YWxCeXRlc1dyaXR0ZW47XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBlbmNvZGVSZXF1ZXN0KHJlcXVlc3Q6IEVuY29kYWJsZVJlcXVlc3QpOiBCdWZmZXIge1xuICBjb25zdCBrZXkgPSBidWZmZXJpZnkocmVxdWVzdC5rZXkpO1xuICBjb25zdCBleHRyYXMgPSBidWZmZXJpZnkocmVxdWVzdC5leHRyYXMpO1xuICBjb25zdCB2YWx1ZSA9IGJ1ZmZlcmlmeShyZXF1ZXN0LnZhbHVlKTtcbiAgY29uc3QgYnVmU2l6ZSA9IDI0ICsga2V5Lmxlbmd0aCArIGV4dHJhcy5sZW5ndGggKyB2YWx1ZS5sZW5ndGg7XG4gIGNvbnN0IGJ1ZmZlciA9IEJ1ZmZlci5hbGxvYyhidWZTaXplKTtcbiAgZW5jb2RlUmVxdWVzdEludG9CdWZmZXIoYnVmZmVyLCAwLCB7XG4gICAgLi4ucmVxdWVzdCxcbiAgICBrZXksXG4gICAgZXh0cmFzLFxuICAgIHZhbHVlLFxuICB9KTtcbiAgcmV0dXJuIGJ1ZmZlcjtcbn1cblxuZXhwb3J0IGNvbnN0IGNvcHlJbnRvUmVxdWVzdEJ1ZmZlciA9IGZ1bmN0aW9uIChcbiAgb3Bjb2RlOiBPUCxcbiAga2V5OiBNYXliZUJ1ZmZlcixcbiAgZXh0cmFzOiBNYXliZUJ1ZmZlcixcbiAgdmFsdWU6IE1heWJlQnVmZmVyLFxuICBvcGFxdWU6IG51bWJlcixcbiAgYnVmOiBCdWZmZXIsXG4gIF9idWZUYXJnZXRXcml0ZU9mZnNldD86IG51bWJlclxuKSB7XG4gIHJldHVybiBlbmNvZGVSZXF1ZXN0SW50b0J1ZmZlcihidWYsIF9idWZUYXJnZXRXcml0ZU9mZnNldCB8fCAwLCB7XG4gICAgaGVhZGVyOiB7XG4gICAgICBvcGNvZGUsXG4gICAgICBvcGFxdWUsXG4gICAgfSxcbiAgICBrZXksXG4gICAgZXh0cmFzLFxuICAgIHZhbHVlLFxuICB9KTtcbn07XG5cbmV4cG9ydCBjb25zdCBtYWtlUmVxdWVzdEJ1ZmZlciA9IGZ1bmN0aW9uIChcbiAgb3Bjb2RlOiBPUCxcbiAga2V5OiBNYXliZUJ1ZmZlcixcbiAgZXh0cmFzOiBNYXliZUJ1ZmZlcixcbiAgdmFsdWU6IE1heWJlQnVmZmVyLFxuICBvcGFxdWU/OiBudW1iZXJcbikge1xuICByZXR1cm4gZW5jb2RlUmVxdWVzdCh7XG4gICAgZXh0cmFzLFxuICAgIGtleSxcbiAgICB2YWx1ZSxcbiAgICBoZWFkZXI6IHtcbiAgICAgIG9wY29kZSxcbiAgICAgIG9wYXF1ZTogb3BhcXVlIHx8IDAsXG4gICAgfSxcbiAgfSk7XG59O1xuXG5leHBvcnQgY29uc3QgbWFrZUFtb3VudEluaXRpYWxBbmRFeHBpcmF0aW9uID0gZnVuY3Rpb24gKFxuICBhbW91bnQ6IG51bWJlcixcbiAgYW1vdW50SWZFbXB0eTogbnVtYmVyLFxuICBleHBpcmF0aW9uOiBudW1iZXJcbikge1xuICBjb25zdCBidWYgPSBCdWZmZXIuYWxsb2MoMjApO1xuICBidWYud3JpdGVVSW50MzJCRSgwLCAwKTtcbiAgYnVmLndyaXRlVUludDMyQkUoYW1vdW50LCA0KTtcbiAgYnVmLndyaXRlVUludDMyQkUoMCwgOCk7XG4gIGJ1Zi53cml0ZVVJbnQzMkJFKGFtb3VudElmRW1wdHksIDEyKTtcbiAgYnVmLndyaXRlVUludDMyQkUoZXhwaXJhdGlvbiwgMTYpO1xuICByZXR1cm4gYnVmO1xufTtcblxuZXhwb3J0IGNvbnN0IG1ha2VFeHBpcmF0aW9uID0gZnVuY3Rpb24gKGV4cGlyYXRpb246IG51bWJlcikge1xuICBjb25zdCBidWYgPSBCdWZmZXIuYWxsb2MoNCk7XG4gIGJ1Zi53cml0ZVVJbnQzMkJFKGV4cGlyYXRpb24sIDApO1xuICByZXR1cm4gYnVmO1xufTtcblxuZXhwb3J0IGNvbnN0IGhhc2hDb2RlID0gZnVuY3Rpb24gKHN0cjogc3RyaW5nKSB7XG4gIGxldCByZXQsIGksIGxlbjtcbiAgZm9yIChyZXQgPSAwLCBpID0gMCwgbGVuID0gc3RyLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgcmV0ID0gKDMxICogcmV0ICsgc3RyLmNoYXJDb2RlQXQoaSkpIDw8IDA7XG4gIH1cbiAgcmV0dXJuIE1hdGguYWJzKHJldCk7XG59O1xuXG5leHBvcnQgaW50ZXJmYWNlIE1lc3NhZ2Uge1xuICBoZWFkZXI6IGhlYWRlci5IZWFkZXI7XG4gIGtleTogQnVmZmVyO1xuICB2YWw6IEJ1ZmZlcjtcbiAgZXh0cmFzOiBCdWZmZXI7XG59XG5cbi8vIEVycm9yIG1lc3NhZ2UgZnJvbSBtZW1jYWNoZWQgd2hlbiBpdCByZWplY3RzIGEgcmVxdWVzdCBmb3IgaGF2aW5nIHRvbyBtYW55XG4vLyBvcGVuIGNvbm5lY3Rpb25zXG4vLyBodHRwczovL2dpdGh1Yi5jb20vbWVtY2FjaGVkL21lbWNhY2hlZC9ibG9iL2VmZWU3NjNjOTMyNDkzNThlYTViM2I0MmM3ZmQ0ZTU3ZTI1OTljMzAvbWVtY2FjaGVkLmMjTDMwNDRcbmNvbnN0IEVSUk9SX1RPT19NQU5ZX09QRU5fQ09OTkVDVElPTlMgPSBcIkVSUk9SIFRvbyBtYW55IG9wZW4gY29ubmVjdGlvbnNcXHJcXG5cIjtcblxuZXhwb3J0IGNvbnN0IHBhcnNlTWVzc2FnZSA9IGZ1bmN0aW9uIChkYXRhQnVmOiBCdWZmZXIpOiBNZXNzYWdlIHwgZmFsc2Uge1xuICBpZiAoZGF0YUJ1Zi5sZW5ndGggPCAyNCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGlmIChkYXRhQnVmLmxlbmd0aCA9PT0gRVJST1JfVE9PX01BTllfT1BFTl9DT05ORUNUSU9OUy5sZW5ndGgpIHtcbiAgICBpZiAoZGF0YUJ1Zi50b1N0cmluZygpID09PSBFUlJPUl9UT09fTUFOWV9PUEVOX0NPTk5FQ1RJT05TKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJFUlJPUiBUb28gbWFueSBvcGVuIGNvbm5lY3Rpb25zXCIpO1xuICAgIH1cbiAgfVxuXG4gIGNvbnN0IHJlc3BvbnNlSGVhZGVyID0gaGVhZGVyLmZyb21CdWZmZXIoZGF0YUJ1Zik7XG5cbiAgaWYgKFxuICAgIGRhdGFCdWYubGVuZ3RoIDwgcmVzcG9uc2VIZWFkZXIudG90YWxCb2R5TGVuZ3RoICsgMjQgfHxcbiAgICByZXNwb25zZUhlYWRlci50b3RhbEJvZHlMZW5ndGggPFxuICAgICAgcmVzcG9uc2VIZWFkZXIua2V5TGVuZ3RoICsgcmVzcG9uc2VIZWFkZXIuZXh0cmFzTGVuZ3RoXG4gICkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGxldCBwb2ludGVyID0gMjQ7XG4gIGNvbnN0IGV4dHJhcyA9IGRhdGFCdWYuc2xpY2UocG9pbnRlciwgcG9pbnRlciArIHJlc3BvbnNlSGVhZGVyLmV4dHJhc0xlbmd0aCk7XG4gIHBvaW50ZXIgKz0gcmVzcG9uc2VIZWFkZXIuZXh0cmFzTGVuZ3RoO1xuICBjb25zdCBrZXkgPSBkYXRhQnVmLnNsaWNlKHBvaW50ZXIsIHBvaW50ZXIgKyByZXNwb25zZUhlYWRlci5rZXlMZW5ndGgpO1xuICBwb2ludGVyICs9IHJlc3BvbnNlSGVhZGVyLmtleUxlbmd0aDtcbiAgY29uc3QgdmFsID0gZGF0YUJ1Zi5zbGljZShwb2ludGVyLCAyNCArIHJlc3BvbnNlSGVhZGVyLnRvdGFsQm9keUxlbmd0aCk7XG5cbiAgcmV0dXJuIHsgaGVhZGVyOiByZXNwb25zZUhlYWRlciwga2V5OiBrZXksIGV4dHJhczogZXh0cmFzLCB2YWw6IHZhbCB9O1xufTtcblxuZXhwb3J0IGNvbnN0IHBhcnNlTWVzc2FnZXMgPSBmdW5jdGlvbiAoZGF0YUJ1ZjogQnVmZmVyKTogTWVzc2FnZVtdIHtcbiAgY29uc3QgbWVzc2FnZXMgPSBbXTtcblxuICBsZXQgbWVzc2FnZTogTWVzc2FnZTtcblxuICBkbyB7XG4gICAgbWVzc2FnZSA9IGV4cG9ydHMucGFyc2VNZXNzYWdlKGRhdGFCdWYpO1xuICAgIGlmIChtZXNzYWdlKSB7XG4gICAgICBtZXNzYWdlcy5wdXNoKG1lc3NhZ2UpO1xuICAgICAgY29uc3QgbWVzc2FnZUxlbmd0aCA9IG1lc3NhZ2UuaGVhZGVyLnRvdGFsQm9keUxlbmd0aCArIDI0O1xuICAgICAgZGF0YUJ1ZiA9IGRhdGFCdWYuc2xpY2UobWVzc2FnZUxlbmd0aCk7XG4gICAgfVxuICB9IHdoaWxlIChtZXNzYWdlKTtcblxuICByZXR1cm4gbWVzc2FnZXM7XG59O1xuXG5leHBvcnQgY29uc3QgbWVyZ2UgPSBmdW5jdGlvbiA8VD4ob3JpZ2luYWw6IGFueSwgZGVmbHQ6IFQpOiBUIHtcbiAgZm9yIChsZXQgYXR0clQgb2YgT2JqZWN0LmtleXMoZGVmbHQpKSB7XG4gICAgY29uc3QgYXR0cjoga2V5b2YgVCA9IGF0dHJUIGFzIGFueTtcbiAgICBjb25zdCBvcmlnaW5hbFZhbHVlID0gb3JpZ2luYWxbYXR0cl07XG5cbiAgICBpZiAob3JpZ2luYWxWYWx1ZSA9PT0gdW5kZWZpbmVkIHx8IG9yaWdpbmFsVmFsdWUgPT09IG51bGwpIHtcbiAgICAgIG9yaWdpbmFsW2F0dHJdID0gZGVmbHRbYXR0cl0gYXMgYW55O1xuICAgIH1cbiAgfVxuICByZXR1cm4gb3JpZ2luYWw7XG59O1xuXG4vLyB0aW1lc3RhbXAgcHJvdmlkZXMgYSBtb25vdG9uaWMgdGltZXN0YW1wIHdpdGggbWlsbGlzZWNvbmQgYWNjdXJhY3ksIHVzZWZ1bFxuLy8gZm9yIHRpbWVycy5cbmV4cG9ydCBjb25zdCB0aW1lc3RhbXAgPSBmdW5jdGlvbiAoKSB7XG4gIGNvbnN0IHRpbWVzID0gcHJvY2Vzcy5ocnRpbWUoKTtcbiAgcmV0dXJuIHRpbWVzWzBdICogMTAwMCArIE1hdGgucm91bmQodGltZXNbMV0gLyAxMDAwMDAwKTtcbn07XG5cbmlmICghQnVmZmVyLmNvbmNhdCkge1xuICBCdWZmZXIuY29uY2F0ID0gZnVuY3Rpb24gKGxpc3QsIGxlbmd0aCkge1xuICAgIGlmICghQXJyYXkuaXNBcnJheShsaXN0KSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiVXNhZ2U6IEJ1ZmZlci5jb25jYXQobGlzdCwgW2xlbmd0aF0pXCIpO1xuICAgIH1cblxuICAgIGlmIChsaXN0Lmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuIEJ1ZmZlci5hbGxvYygwKTtcbiAgICB9XG4gICAgaWYgKGxpc3QubGVuZ3RoID09PSAxKSB7XG4gICAgICByZXR1cm4gbGlzdFswXTtcbiAgICB9XG5cbiAgICBsZXQgaTogbnVtYmVyO1xuICAgIGxldCBidWY6IEJ1ZmZlcjtcblxuICAgIGlmICh0eXBlb2YgbGVuZ3RoICE9PSBcIm51bWJlclwiKSB7XG4gICAgICBsZW5ndGggPSAwO1xuICAgICAgZm9yIChpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgYnVmID0gbGlzdFtpXTtcbiAgICAgICAgbGVuZ3RoICs9IGJ1Zi5sZW5ndGg7XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgYnVmZmVyID0gQnVmZmVyLmFsbG9jKGxlbmd0aCk7XG4gICAgbGV0IHBvcyA9IDA7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICBidWYgPSBsaXN0W2ldO1xuICAgICAgYnVmLmNvcHkoYnVmZmVyLCBwb3MpO1xuICAgICAgcG9zICs9IGJ1Zi5sZW5ndGg7XG4gICAgfVxuICAgIHJldHVybiBidWZmZXI7XG4gIH07XG59XG4iXX0= \ No newline at end of file diff --git a/src/memjs/utils.ts b/src/memjs/utils.ts index 9f4cd3f..bea061b 100644 --- a/src/memjs/utils.ts +++ b/src/memjs/utils.ts @@ -144,6 +144,9 @@ export interface Message { extras: Buffer; } +// Error message from memcached when it rejects a request for having too many +// open connections +// https://github.com/memcached/memcached/blob/efee763c93249358ea5b3b42c7fd4e57e2599c30/memcached.c#L3044 const ERROR_TOO_MANY_OPEN_CONNECTIONS = "ERROR Too many open connections\r\n"; export const parseMessage = function (dataBuf: Buffer): Message | false { From 99b24c4bca570982457f5a42021767d8be000ecf Mon Sep 17 00:00:00 2001 From: Ben Hughes Date: Tue, 3 Oct 2023 16:39:12 -0400 Subject: [PATCH 73/79] Reset responseBuffer on error, close, and new connections --- lib/memjs/server.d.ts.map | 2 +- lib/memjs/server.js | 5 ++++- src/memjs/server.ts | 3 +++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/memjs/server.d.ts.map b/lib/memjs/server.d.ts.map index 0c0c85e..31f9e76 100644 --- a/lib/memjs/server.d.ts.map +++ b/lib/memjs/server.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/memjs/server.ts"],"names":[],"mappings":";AAAA,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAKL,OAAO,EACR,MAAM,SAAS,CAAC;AAEjB,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,aAAK,GAAG,GAAG,MAAM,CAAC;AAElB,MAAM,WAAW,iBAAiB;IAChC,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,MAAM,WAAW,kBAAkB;IACjC,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACzB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;CACtB;AAED,qBAAa,MAAO,SAAQ,MAAM,CAAC,YAAY;IAC7C,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IAClC,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;IACpB,gBAAgB,EAAE,iBAAiB,EAAE,CAAC;IACtC,iBAAiB,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,kBAAkB,CAAA;KAAE,CAAC;IACzD,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,cAAc,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,CAAA;KAAE,CAAC;IACnD,OAAO,EAAE,aAAa,CAAC;IACvB,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAE7B,OAAO,EAAE,GAAG,CAAC,MAAM,GAAG,SAAS,CAAC;gBAG9B,IAAI,EAAE,MAAM,EAEZ,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,EACtB,QAAQ,CAAC,EAAE,MAAM,EACjB,QAAQ,CAAC,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC;IAoClC,SAAS,CAAC,IAAI,EAAE,iBAAiB;IAIjC,UAAU,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,kBAAkB;IAI7C,OAAO,CAAC,QAAQ,EAAE,OAAO;IAczB,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,eAAe;IAIvC,KAAK,CAAC,GAAG,EAAE,KAAK;IAgBhB,QAAQ;IAKR,QAAQ;IAMR,cAAc,CAAC,OAAO,EAAE,MAAM;IAO9B,eAAe,CAAC,OAAO,EAAE,MAAM;IAyB/B,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,iBAAiB;IAyFzC,KAAK,CAAC,IAAI,EAAE,MAAM;IAelB,SAAS,CAAC,IAAI,EAAE,MAAM;IAMtB,KAAK;IAML,QAAQ;IAIR,cAAc;CAGf"} \ No newline at end of file +{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/memjs/server.ts"],"names":[],"mappings":";AAAA,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAKL,OAAO,EACR,MAAM,SAAS,CAAC;AAEjB,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,aAAK,GAAG,GAAG,MAAM,CAAC;AAElB,MAAM,WAAW,iBAAiB;IAChC,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,MAAM,WAAW,kBAAkB;IACjC,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACzB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;CACtB;AAED,qBAAa,MAAO,SAAQ,MAAM,CAAC,YAAY;IAC7C,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IAClC,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;IACpB,gBAAgB,EAAE,iBAAiB,EAAE,CAAC;IACtC,iBAAiB,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,kBAAkB,CAAA;KAAE,CAAC;IACzD,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,cAAc,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,CAAA;KAAE,CAAC;IACnD,OAAO,EAAE,aAAa,CAAC;IACvB,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAE7B,OAAO,EAAE,GAAG,CAAC,MAAM,GAAG,SAAS,CAAC;gBAG9B,IAAI,EAAE,MAAM,EAEZ,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,EACtB,QAAQ,CAAC,EAAE,MAAM,EACjB,QAAQ,CAAC,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC;IAoClC,SAAS,CAAC,IAAI,EAAE,iBAAiB;IAIjC,UAAU,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,kBAAkB;IAI7C,OAAO,CAAC,QAAQ,EAAE,OAAO;IAczB,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,eAAe;IAIvC,KAAK,CAAC,GAAG,EAAE,KAAK;IAiBhB,QAAQ;IAKR,QAAQ;IAMR,cAAc,CAAC,OAAO,EAAE,MAAM;IAO9B,eAAe,CAAC,OAAO,EAAE,MAAM;IAyB/B,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,iBAAiB;IA2FzC,KAAK,CAAC,IAAI,EAAE,MAAM;IAelB,SAAS,CAAC,IAAI,EAAE,MAAM;IAMtB,KAAK;IAML,QAAQ;IAIR,cAAc;CAGf"} \ No newline at end of file diff --git a/lib/memjs/server.js b/lib/memjs/server.js index e8fcefe..5c23615 100644 --- a/lib/memjs/server.js +++ b/lib/memjs/server.js @@ -71,6 +71,7 @@ class Server extends events_1.default.EventEmitter { this.requestTimeouts = []; this.errorCallbacks = {}; this.timeoutSet = false; + this.responseBuffer = Buffer.from([]); if (this._socket) { this._socket.destroy(); delete this._socket; @@ -128,6 +129,7 @@ class Server extends events_1.default.EventEmitter { if (!self._socket) { // CASE 1: completely new socket self.connected = false; + self.responseBuffer = Buffer.from([]); self._socket = net_1.default.connect( /* TODO: allowing port to be string or undefined is used by the tests, but seems bad overall. */ typeof this.port === "string" @@ -171,6 +173,7 @@ class Server extends events_1.default.EventEmitter { self.error(new Error("socket closed unexpectedly.")); } self.connected = false; + self.responseBuffer = Buffer.from([]); if (self.timeoutSet) { (_a = self._socket) === null || _a === void 0 ? void 0 : _a.setTimeout(0); self.timeoutSet = false; @@ -259,4 +262,4 @@ const timeoutHandler = function (server, sock) { }); } }; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL21lbWpzL3NlcnZlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSw4Q0FBc0I7QUFDdEIsb0RBQTRCO0FBQzVCLG1DQU1pQjtBQTBCakIsTUFBYSxNQUFPLFNBQVEsZ0JBQU0sQ0FBQyxZQUFZO0lBZ0I3QyxZQUNFLElBQVk7SUFDWixnR0FBZ0c7SUFDaEcsSUFBc0IsRUFDdEIsUUFBaUIsRUFDakIsUUFBaUIsRUFDakIsT0FBZ0M7UUFFaEMsS0FBSyxFQUFFLENBQUM7UUFDUixJQUFJLENBQUMsY0FBYyxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDdEMsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUM7UUFDakIsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUM7UUFDakIsSUFBSSxDQUFDLFNBQVMsR0FBRyxLQUFLLENBQUM7UUFDdkIsSUFBSSxDQUFDLFVBQVUsR0FBRyxLQUFLLENBQUM7UUFDeEIsSUFBSSxDQUFDLGdCQUFnQixHQUFHLEVBQUUsQ0FBQztRQUMzQixJQUFJLENBQUMsaUJBQWlCLEdBQUcsRUFBRSxDQUFDO1FBQzVCLElBQUksQ0FBQyxlQUFlLEdBQUcsRUFBRSxDQUFDO1FBQzFCLElBQUksQ0FBQyxjQUFjLEdBQUcsRUFBRSxDQUFDO1FBQ3pCLElBQUksQ0FBQyxPQUFPLEdBQUcsYUFBSyxDQUFDLE9BQU8sSUFBSSxFQUFFLEVBQUU7WUFDbEMsT0FBTyxFQUFFLEdBQUc7WUFDWixTQUFTLEVBQUUsS0FBSztZQUNoQixjQUFjLEVBQUUsRUFBRTtTQUNuQixDQUFrQixDQUFDO1FBQ3BCLElBQ0UsSUFBSSxDQUFDLE9BQU8sQ0FBQyxXQUFXLEtBQUssU0FBUztZQUN0QyxJQUFJLENBQUMsT0FBTyxDQUFDLFdBQVcsS0FBSyxJQUFJLEVBQ2pDO1lBQ0EsSUFBSSxDQUFDLE9BQU8sQ0FBQyxXQUFX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LElBQUksQ0FBQztJQUNyQyxDQUFDO0NBQ0Y7QUExUUQsd0JBMFFDO0FBRUQsK0VBQStFO0FBQy9FLDZFQUE2RTtBQUM3RSxvQkFBb0I7QUFDcEIsTUFBTSxjQUFjLEdBQUcsVUFBVSxNQUFjLEVBQUUsSUFBZ0I7SUFDL0QsSUFBSSxNQUFNLENBQUMsZUFBZSxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUU7UUFDdkMsaUJBQWlCO1FBQ2pCLE1BQU0sQ0FBQyxVQUFVLEdBQUcsS0FBSyxDQUFDO1FBQzFCLE9BQU87S0FDUjtJQUVELHlEQUF5RDtJQUN6RCxNQUFNLEdBQUcsR0FBRyxpQkFBUyxFQUFFLENBQUM7SUFDeEIsTUFBTSxjQUFjLEdBQUcsTUFBTSxDQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUVqRCxJQUFJLGNBQWMsSUFBSSxHQUFHLEVBQUU7UUFDekIsb0JBQW9CO1FBQ3BCLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztRQUNYLE1BQU0sQ0FBQyxTQUFTLEdBQUcsS0FBSyxDQUFDO1FBQ3pCLE1BQU0sQ0FBQyxPQUFPLEdBQUcsU0FBUyxDQUFDO1FBQzNCLE1BQU0sQ0FBQyxVQUFVLEdBQUcsS0FBSyxDQUFDO1FBQzFCLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxLQUFLLENBQUMsdUNBQXVDLENBQUMsQ0FBQyxDQUFDO0tBQ2xFO1NBQU07UUFDTCw4QkFBOEI7UUFDOUIsTUFBTSxRQUFRLEdBQUcsY0FBYyxHQUFHLEdBQUcsQ0FBQztRQUN0QyxJQUFJLENBQUMsVUFBVSxDQUFDLFFBQVEsRUFBRTtZQUN4QixjQUFjLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQy9CLENBQUMsQ0FBQyxDQUFDO0tBQ0o7QUFDSCxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgbmV0IGZyb20gXCJuZXRcIjtcbmltcG9ydCBldmVudHMgZnJvbSBcImV2ZW50c1wiO1xuaW1wb3J0IHtcbiAgbWFrZVJlcXVlc3RCdWZmZXIsXG4gIHBhcnNlTWVzc2FnZSxcbiAgbWVyZ2UsXG4gIHRpbWVzdGFtcCxcbiAgTWVzc2FnZSxcbn0gZnJvbSBcIi4vdXRpbHNcIjtcblxuZXhwb3J0IGludGVyZmFjZSBTZXJ2ZXJPcHRpb25zIHtcbiAgdGltZW91dDogbnVtYmVyO1xuICBrZWVwQWxpdmU6IGJvb2xlYW47XG4gIGtlZXBBbGl2ZURlbGF5OiBudW1iZXI7XG4gIGNvbm50aW1lb3V0OiBudW1iZXI7XG4gIHVzZXJuYW1lPzogc3RyaW5nO1xuICBwYXNzd29yZD86IHN0cmluZztcbn1cblxudHlwZSBTZXEgPSBudW1iZXI7XG5cbmV4cG9ydCBpbnRlcmZhY2UgT25Db25uZWN0Q2FsbGJhY2sge1xuICAoc29ja2V0OiBuZXQuU29ja2V0KTogdm9pZDtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBPblJlc3BvbnNlQ2FsbGJhY2sge1xuICAobWVzc2FnZTogTWVzc2FnZSk6IHZvaWQ7XG4gIHF1aWV0PzogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBPbkVycm9yQ2FsbGJhY2sge1xuICAoZXJyb3I6IEVycm9yKTogdm9pZDtcbn1cblxuZXhwb3J0IGNsYXNzIFNlcnZlciBleHRlbmRzIGV2ZW50cy5FdmVudEVtaXR0ZXIge1xuICByZXNwb25zZUJ1ZmZlcjogQnVmZmVyO1xuICBob3N0OiBzdHJpbmc7XG4gIHBvcnQ6IHN0cmluZyB8IG51bWJlciB8IHVuZGVmaW5lZDtcbiAgY29ubmVjdGVkOiBib29sZWFuO1xuICB0aW1lb3V0U2V0OiBib29sZWFuO1xuICBjb25uZWN0Q2FsbGJhY2tzOiBPbkNvbm5lY3RDYWxsYmFja1tdO1xuICByZXNwb25zZUNhbGxiYWNrczogeyBbc2VxOiBzdHJpbmddOiBPblJlc3BvbnNlQ2FsbGJhY2sgfTtcbiAgcmVxdWVzdFRpbWVvdXRzOiBudW1iZXJbXTtcbiAgZXJyb3JDYWxsYmFja3M6IHsgW3NlcTogc3RyaW5nXTogT25FcnJvckNhbGxiYWNrIH07XG4gIG9wdGlvbnM6IFNlcnZlck9wdGlvbnM7XG4gIHVzZXJuYW1lOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gIHBhc3N3b3JkOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG5cbiAgX3NvY2tldDogbmV0LlNvY2tldCB8IHVuZGVmaW5lZDtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBob3N0OiBzdHJpbmcsXG4gICAgLyogVE9ETzogYWxsb3dpbmcgcG9ydCB0byBiZSBzdHJpbmcgb3IgdW5kZWZpbmVkIGlzIHVzZWQgYnkgdGhlIHRlc3RzLCBidXQgc2VlbXMgYmFkIG92ZXJhbGwuICovXG4gICAgcG9ydD86IHN0cmluZyB8IG51bWJlcixcbiAgICB1c2VybmFtZT86IHN0cmluZyxcbiAgICBwYXNzd29yZD86IHN0cmluZyxcbiAgICBvcHRpb25zPzogUGFydGlhbDxTZXJ2ZXJPcHRpb25zPlxuICApIHtcbiAgICBzdXBlcigpO1xuICAgIHRoaXMucmVzcG9uc2VCdWZmZXIgPSBCdWZmZXIuZnJvbShbXSk7XG4gICAgdGhpcy5ob3N0ID0gaG9zdDtcbiAgICB0aGlzLnBvcnQgPSBwb3J0O1xuICAgIHRoaXMuY29ubmVjdGVkID0gZmFsc2U7XG4gICAgdGhpcy50aW1lb3V0U2V0ID0gZmFsc2U7XG4gICAgdGhpcy5jb25uZWN0Q2FsbGJhY2tzID0gW107XG4gICAgdGhpcy5yZXNwb25zZUNhbGxiYWNrcyA9IHt9O1xuICAgIHRoaXMucmVxdWVzdFRpbWVvdXRzID0gW107XG4gICAgdGhpcy5lcnJvckNhbGxiYWNrcyA9IHt9O1xuICAgIHRoaXMub3B0aW9ucyA9IG1lcmdlKG9wdGlvbnMgfHwge30sIHtcbiAgICAgIHRpbWVvdXQ6IDAuNSxcbiAgICAgIGtlZXBBbGl2ZTogZmFsc2UsXG4gICAgICBrZWVwQWxpdmVEZWxheTogMzAsXG4gICAgfSkgYXMgU2VydmVyT3B0aW9ucztcbiAgICBpZiAoXG4gICAgICB0aGlzLm9wdGlvbnMuY29ubnRpbWVvdXQgPT09IHVuZGVmaW5lZCB8fFxuICAgICAgdGhpcy5vcHRpb25zLmNvbm50aW1lb3V0ID09PSBudWxsXG4gICAgKSB7XG4gICAgICB0aGlzLm9wdGlvbnMuY29ubnRpbWVvdXQgPSAyICogdGhpcy5vcHRpb25zLnRpbWVvdXQ7XG4gICAgfVxuICAgIHRoaXMudXNlcm5hbWUgPVxuICAgICAgdXNlcm5hbWUgfHxcbiAgICAgIHRoaXMub3B0aW9ucy51c2VybmFtZSB8fFxuICAgICAgcHJvY2Vzcy5lbnYuTUVNQ0FDSElFUl9VU0VSTkFNRSB8fFxuICAgICAgcHJvY2Vzcy5lbnYuTUVNQ0FDSEVfVVNFUk5BTUU7XG4gICAgdGhpcy5wYXNzd29yZCA9XG4gICAgICBwYXNzd29yZCB8fFxuICAgICAgdGhpcy5vcHRpb25zLnBhc3N3b3JkIHx8XG4gICAgICBwcm9jZXNzLmVudi5NRU1DQUNISUVSX1BBU1NXT1JEIHx8XG4gICAgICBwcm9jZXNzLmVudi5NRU1DQUNIRV9QQVNTV09SRDtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIG9uQ29ubmVjdChmdW5jOiBPbkNvbm5lY3RDYWxsYmFjaykge1xuICAgIHRoaXMuY29ubmVjdENhbGxiYWNrcy5wdXNoKGZ1bmMpO1xuICB9XG5cbiAgb25SZXNwb25zZShzZXE6IFNlcSwgZnVuYzogT25SZXNwb25zZUNhbGxiYWNrKSB7XG4gICAgdGhpcy5yZXNwb25zZUNhbGxiYWNrc1tzZXFdID0gZnVuYztcbiAgfVxuXG4gIHJlc3BvbmQocmVzcG9uc2U6IE1lc3NhZ2UpIHtcbiAgICBjb25zdCBjYWxsYmFjayA9IHRoaXMucmVzcG9uc2VDYWxsYmFja3NbcmVzcG9uc2UuaGVhZGVyLm9wYXF1ZV07XG4gICAgaWYgKCFjYWxsYmFjaykge1xuICAgICAgLy8gaW4gY2FzZSBvZiBhdXRoZW50aWNhdGlvbiwgbm8gY2FsbGJhY2sgaXMgcmVnaXN0ZXJlZFxuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjYWxsYmFjayhyZXNwb25zZSk7XG4gICAgaWYgKCFjYWxsYmFjay5xdWlldCB8fCByZXNwb25zZS5oZWFkZXIudG90YWxCb2R5TGVuZ3RoID09PSAwKSB7XG4gICAgICBkZWxldGUgdGhpcy5yZXNwb25zZUNhbGxiYWNrc1tyZXNwb25zZS5oZWFkZXIub3BhcXVlXTtcbiAgICAgIHRoaXMucmVxdWVzdFRpbWVvdXRzLnNoaWZ0KCk7XG4gICAgICBkZWxldGUgdGhpcy5lcnJvckNhbGxiYWNrc1tyZXNwb25zZS5oZWFkZXIub3BhcXVlXTtcbiAgICB9XG4gIH1cblxuICBvbkVycm9yKHNlcTogU2VxLCBmdW5jOiBPbkVycm9yQ2FsbGJhY2spIHtcbiAgICB0aGlzLmVycm9yQ2FsbGJhY2tzW3NlcV0gPSBmdW5jO1xuICB9XG5cbiAgZXJyb3IoZXJyOiBFcnJvcikge1xuICAgIGNvbnN0IGVycmNhbGxzID0gdGhpcy5lcnJvckNhbGxiYWNrcztcbiAgICB0aGlzLmNvbm5lY3RDYWxsYmFja3MgPSBbXTtcbiAgICB0aGlzLnJlc3BvbnNlQ2FsbGJhY2tzID0ge307XG4gICAgdGhpcy5yZXF1ZXN0VGltZW91dHMgPSBbXTtcbiAgICB0aGlzLmVycm9yQ2FsbGJhY2tzID0ge307XG4gICAgdGhpcy50aW1lb3V0U2V0ID0gZmFsc2U7XG4gICAgaWYgKHRoaXMuX3NvY2tldCkge1xuICAgICAgdGhpcy5fc29ja2V0LmRlc3Ryb3koKTtcbiAgICAgIGRlbGV0ZSB0aGlzLl9zb2NrZXQ7XG4gICAgfVxuICAgIGZvciAobGV0IGVycmNhbGwgb2YgT2JqZWN0LnZhbHVlcyhlcnJjYWxscykpIHtcbiAgICAgIGVycmNhbGwoZXJyKTtcbiAgICB9XG4gIH1cblxuICBsaXN0U2FzbCgpIHtcbiAgICBjb25zdCBidWYgPSBtYWtlUmVxdWVzdEJ1ZmZlcigweDIwLCBcIlwiLCBcIlwiLCBcIlwiKTtcbiAgICB0aGlzLndyaXRlU0FTTChidWYpO1xuICB9XG5cbiAgc2FzbEF1dGgoKSB7XG4gICAgY29uc3QgYXV0aFN0ciA9IFwiXFx4MDBcIiArIHRoaXMudXNlcm5hbWUgKyBcIlxceDAwXCIgKyB0aGlzLnBhc3N3b3JkO1xuICAgIGNvbnN0IGJ1ZiA9IG1ha2VSZXF1ZXN0QnVmZmVyKDB4MjEsIFwiUExBSU5cIiwgXCJcIiwgYXV0aFN0cik7XG4gICAgdGhpcy53cml0ZVNBU0woYnVmKTtcbiAgfVxuXG4gIGFwcGVuZFRvQnVmZmVyKGRhdGFCdWY6IEJ1ZmZlcikge1xuICAgIGNvbnN0IG9sZCA9IHRoaXMucmVzcG9uc2VCdWZmZXI7XG4gICAgdGhpcy5yZXNwb25zZUJ1ZmZlciA9IEJ1ZmZlci5hbGxvYyhvbGQubGVuZ3RoICsgZGF0YUJ1Zi5sZW5ndGgpO1xuICAgIG9sZC5jb3B5KHRoaXMucmVzcG9uc2VCdWZmZXIsIDApO1xuICAgIGRhdGFCdWYuY29weSh0aGlzLnJlc3BvbnNlQnVmZmVyLCBvbGQubGVuZ3RoKTtcbiAgICByZXR1cm4gdGhpcy5yZXNwb25zZUJ1ZmZlcjtcbiAgfVxuICByZXNwb25zZUhhbmRsZXIoZGF0YUJ1ZjogQnVmZmVyKSB7XG4gICAgbGV0IHJlc3BvbnNlOiBNZXNzYWdlIHwgZmFsc2U7XG4gICAgdHJ5IHtcbiAgICAgIHJlc3BvbnNlID0gcGFyc2VNZXNzYWdlKHRoaXMuYXBwZW5kVG9CdWZmZXIoZGF0YUJ1ZikpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHRoaXMuZXJyb3IoZSBhcyBFcnJvcik7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgbGV0IHJlc3BMZW5ndGg6IG51bWJlcjtcbiAgICB3aGlsZSAocmVzcG9uc2UpIHtcbiAgICAgIGlmIChyZXNwb25zZS5oZWFkZXIub3Bjb2RlID09PSAweDIwKSB7XG4gICAgICAgIHRoaXMuc2FzbEF1dGgoKTtcbiAgICAgIH0gZWxzZSBpZiAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cyA9PT0gKDB4MjAgYXMgYW55KSAvKiBUT0RPOiB3dGY/ICovKSB7XG4gICAgICAgIHRoaXMuZXJyb3IobmV3IEVycm9yKFwiTWVtY2FjaGVkIHNlcnZlciBhdXRoZW50aWNhdGlvbiBmYWlsZWQhXCIpKTtcbiAgICAgIH0gZWxzZSBpZiAocmVzcG9uc2UuaGVhZGVyLm9wY29kZSA9PT0gMHgyMSkge1xuICAgICAgICB0aGlzLmVtaXQoXCJhdXRoZW50aWNhdGVkXCIpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5yZXNwb25kKHJlc3BvbnNlKTtcbiAgICAgIH1cbiAgICAgIHJlc3BMZW5ndGggPSByZXNwb25zZS5oZWFkZXIudG90YWxCb2R5TGVuZ3RoICsgMjQ7XG4gICAgICB0aGlzLnJlc3BvbnNlQnVmZmVyID0gdGhpcy5yZXNwb25zZUJ1ZmZlci5zbGljZShyZXNwTGVuZ3RoKTtcbiAgICAgIHJlc3BvbnNlID0gcGFyc2VNZXNzYWdlKHRoaXMucmVzcG9uc2VCdWZmZXIpO1xuICAgIH1cbiAgfVxuICBzb2NrKHNhc2w6IGJvb2xlYW4sIGdvOiBPbkNvbm5lY3RDYWxsYmFjaykge1xuICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuXG4gICAgaWYgKCFzZWxmLl9zb2NrZXQpIHtcbiAgICAgIC8vIENBU0UgMTogY29tcGxldGVseSBuZXcgc29ja2V0XG4gICAgICBzZWxmLmNvbm5lY3RlZCA9IGZhbHNlO1xuICAgICAgc2VsZi5fc29ja2V0ID0gbmV0LmNvbm5lY3QoXG4gICAgICAgIC8qIFRPRE86IGFsbG93aW5nIHBvcnQgdG8gYmUgc3RyaW5nIG9yIHVuZGVmaW5lZCBpcyB1c2VkIGJ5IHRoZSB0ZXN0cywgYnV0IHNlZW1zIGJhZCBvdmVyYWxsLiAqL1xuICAgICAgICB0eXBlb2YgdGhpcy5wb3J0ID09PSBcInN0cmluZ1wiXG4gICAgICAgICAgPyBwYXJzZUludCh0aGlzLnBvcnQsIDEwKVxuICAgICAgICAgIDogdGhpcy5wb3J0IHx8IDExMjExLFxuICAgICAgICB0aGlzLmhvc3QsXG4gICAgICAgIGZ1bmN0aW9uICh0aGlzOiBuZXQuU29ja2V0KSB7XG4gICAgICAgICAgLy8gU0FTTCBhdXRoZW50aWNhdGlvbiBoYW5kbGVyXG4gICAgICAgICAgc2VsZi5vbmNlKFwiYXV0aGVudGljYXRlZFwiLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAoc2VsZi5fc29ja2V0KSB7XG4gICAgICAgICAgICAgIGNvbnN0IHNvY2tldCA9IHNlbGYuX3NvY2tldDtcbiAgICAgICAgICAgICAgc2VsZi5jb25uZWN0ZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAvLyBjYW5jZWwgY29ubmVjdGlvbiB0aW1lb3V0XG4gICAgICAgICAgICAgIHNlbGYuX3NvY2tldC5zZXRUaW1lb3V0KDApO1xuICAgICAgICAgICAgICBzZWxmLnRpbWVvdXRTZXQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgLy8gcnVuIGFjdHVhbCByZXF1ZXN0KHMpXG4gICAgICAgICAgICAgIGdvKHNlbGYuX3NvY2tldCk7XG4gICAgICAgICAgICAgIHNlbGYuY29ubmVjdENhbGxiYWNrcy5mb3JFYWNoKGZ1bmN0aW9uIChjYikge1xuICAgICAgICAgICAgICAgIGNiKHNvY2tldCk7XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICBzZWxmLmNvbm5lY3RDYWxsYmFja3MgPSBbXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIC8vIHNldHVwIHJlc3BvbnNlIGhhbmRsZXJcbiAgICAgICAgICB0aGlzLm9uKFwiZGF0YVwiLCBmdW5jdGlvbiAoZGF0YUJ1Zikge1xuICAgICAgICAgICAgc2VsZi5yZXNwb25zZUhhbmRsZXIoZGF0YUJ1Zik7XG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICAvLyBraWNrIG9mIFNBU0wgaWYgbmVlZGVkXG4gICAgICAgICAgaWYgKHNlbGYudXNlcm5hbWUgJiYgc2VsZi5wYXNzd29yZCkge1xuICAgICAgICAgICAgc2VsZi5saXN0U2FzbCgpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzZWxmLmVtaXQoXCJhdXRoZW50aWNhdGVkXCIpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgKTtcblxuICAgICAgLy8gc2V0dXAgZXJyb3IgaGFuZGxlclxuICAgICAgc2VsZi5fc29ja2V0Lm9uKFwiZXJyb3JcIiwgZnVuY3Rpb24gKGVycm9yKSB7XG4gICAgICAgIHNlbGYuZXJyb3IoZXJyb3IpO1xuICAgICAgfSk7XG5cbiAgICAgIHNlbGYuX3NvY2tldC5vbihcImNsb3NlXCIsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKE9iamVjdC5rZXlzKHNlbGYuZXJyb3JDYWxsYmFja3MpLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICBzZWxmLmVycm9yKG5ldyBFcnJvcihcInNvY2tldCBjbG9zZWQgdW5leHBlY3RlZGx5LlwiKSk7XG4gICAgICAgIH1cbiAgICAgICAgc2VsZi5jb25uZWN0ZWQgPSBmYWxzZTtcbiAgICAgICAgaWYgKHNlbGYudGltZW91dFNldCkge1xuICAgICAgICAgIHNlbGYuX3NvY2tldD8uc2V0VGltZW91dCgwKTtcbiAgICAgICAgICBzZWxmLnRpbWVvdXRTZXQgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBzZWxmLl9zb2NrZXQgPSB1bmRlZmluZWQ7XG4gICAgICB9KTtcblxuICAgICAgLy8gc2V0dXAgY29ubmVjdGlvbiB0aW1lb3V0IGhhbmRsZXJcbiAgICAgIHNlbGYudGltZW91dFNldCA9IHRydWU7XG4gICAgICBzZWxmLl9zb2NrZXQuc2V0VGltZW91dChcbiAgICAgICAgc2VsZi5vcHRpb25zLmNvbm50aW1lb3V0ICogMTAwMCxcbiAgICAgICAgZnVuY3Rpb24gKHRoaXM6IG5ldC5Tb2NrZXQpIHtcbiAgICAgICAgICBzZWxmLnRpbWVvdXRTZXQgPSBmYWxzZTtcbiAgICAgICAgICBpZiAoIXNlbGYuY29ubmVjdGVkKSB7XG4gICAgICAgICAgICB0aGlzLmVuZCgpO1xuICAgICAgICAgICAgc2VsZi5fc29ja2V0ID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgc2VsZi5lcnJvcihuZXcgRXJyb3IoXCJzb2NrZXQgdGltZWQgb3V0IGNvbm5lY3RpbmcgdG8gc2VydmVyLlwiKSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICApO1xuXG4gICAgICAvLyB1c2UgVENQIGtlZXAtYWxpdmVcbiAgICAgIHNlbGYuX3NvY2tldC5zZXRLZWVwQWxpdmUoXG4gICAgICAgIHNlbGYub3B0aW9ucy5rZWVwQWxpdmUsXG4gICAgICAgIHNlbGYub3B0aW9ucy5rZWVwQWxpdmVEZWxheSAqIDEwMDBcbiAgICAgICk7XG4gICAgfSBlbHNlIGlmICghc2VsZi5jb25uZWN0ZWQgJiYgIXNhc2wpIHtcbiAgICAgIC8vIENBU0UgMjogc29ja2V0IGV4aXN0cywgYnV0IHN0aWxsIGNvbm5lY3RpbmcgLyBhdXRoZW50aWNhdGluZ1xuICAgICAgc2VsZi5vbkNvbm5lY3QoZ28pO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBDQVNFIDM6IHNvY2tldCBleGlzdHMgYW5kIGNvbm5lY3RlZCAvIHJlYWR5IHRvIHVzZVxuICAgICAgZ28oc2VsZi5fc29ja2V0KTtcbiAgICB9XG4gIH1cblxuICB3cml0ZShibG9iOiBCdWZmZXIpIHtcbiAgICBjb25zdCBzZWxmID0gdGhpcztcbiAgICBjb25zdCBkZWFkbGluZSA9IE1hdGgucm91bmQoc2VsZi5vcHRpb25zLnRpbWVvdXQgKiAxMDAwKTtcbiAgICB0aGlzLnNvY2soZmFsc2UsIGZ1bmN0aW9uIChzKSB7XG4gICAgICBzLndyaXRlKGJsb2IpO1xuICAgICAgc2VsZi5yZXF1ZXN0VGltZW91dHMucHVzaCh0aW1lc3RhbXAoKSArIGRlYWRsaW5lKTtcbiAgICAgIGlmICghc2VsZi50aW1lb3V0U2V0KSB7XG4gICAgICAgIHNlbGYudGltZW91dFNldCA9IHRydWU7XG4gICAgICAgIHMuc2V0VGltZW91dChkZWFkbGluZSwgZnVuY3Rpb24gKHRoaXM6IG5ldC5Tb2NrZXQpIHtcbiAgICAgICAgICB0aW1lb3V0SGFuZGxlcihzZWxmLCB0aGlzKTtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICB3cml0ZVNBU0woYmxvYjogQnVmZmVyKSB7XG4gICAgdGhpcy5zb2NrKHRydWUsIGZ1bmN0aW9uIChzKSB7XG4gICAgICBzLndyaXRlKGJsb2IpO1xuICAgIH0pO1xuICB9XG5cbiAgY2xvc2UoKSB7XG4gICAgaWYgKHRoaXMuX3NvY2tldCkge1xuICAgICAgdGhpcy5fc29ja2V0LmVuZCgpO1xuICAgIH1cbiAgfVxuXG4gIHRvU3RyaW5nKCkge1xuICAgIHJldHVybiBcIjxTZXJ2ZXIgXCIgKyB0aGlzLmhvc3QgKyBcIjpcIiArIHRoaXMucG9ydCArIFwiPlwiO1xuICB9XG5cbiAgaG9zdHBvcnRTdHJpbmcoKSB7XG4gICAgcmV0dXJuIHRoaXMuaG9zdCArIFwiOlwiICsgdGhpcy5wb3J0O1xuICB9XG59XG5cbi8vIFdlIGhhbmRsZSB0cmFja2luZyB0aW1lb3V0cyB3aXRoIGFuIGFycmF5IG9mIGRlYWRsaW5lcyAocmVxdWVzdFRpbWVvdXRzKSwgYXNcbi8vIG5vZGUgZG9lc24ndCBsaWtlIHVzIHNldHRpbmcgdXAgbG90cyBvZiB0aW1lcnMsIGFuZCB1c2luZyBqdXN0IG9uZSBpcyBtb3JlXG4vLyBlZmZpY2llbnQgYW55d2F5LlxuY29uc3QgdGltZW91dEhhbmRsZXIgPSBmdW5jdGlvbiAoc2VydmVyOiBTZXJ2ZXIsIHNvY2s6IG5ldC5Tb2NrZXQpIHtcbiAgaWYgKHNlcnZlci5yZXF1ZXN0VGltZW91dHMubGVuZ3RoID09PSAwKSB7XG4gICAgLy8gbm90aGluZyBhY3RpdmVcbiAgICBzZXJ2ZXIudGltZW91dFNldCA9IGZhbHNlO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIC8vIHNvbWUgcmVxdWVzdHMgb3V0c3RhbmRpbmcsIGNoZWNrIGlmIGFueSBoYXZlIHRpbWVkLW91dFxuICBjb25zdCBub3cgPSB0aW1lc3RhbXAoKTtcbiAgY29uc3Qgc29vbmVzdFRpbWVvdXQgPSBzZXJ2ZXIucmVxdWVzdFRpbWVvdXRzWzBdO1xuXG4gIGlmIChzb29uZXN0VGltZW91dCA8PSBub3cpIHtcbiAgICAvLyB0aW1lb3V0IG9jY3VycmVkIVxuICAgIHNvY2suZW5kKCk7XG4gICAgc2VydmVyLmNvbm5lY3RlZCA9IGZhbHNlO1xuICAgIHNlcnZlci5fc29ja2V0ID0gdW5kZWZpbmVkO1xuICAgIHNlcnZlci50aW1lb3V0U2V0ID0gZmFsc2U7XG4gICAgc2VydmVyLmVycm9yKG5ldyBFcnJvcihcInNvY2tldCB0aW1lZCBvdXQgd2FpdGluZyBvbiByZXNwb25zZS5cIikpO1xuICB9IGVsc2Uge1xuICAgIC8vIG5vIHRpbWVvdXQhIFNldHVwIG5leHQgb25lLlxuICAgIGNvbnN0IGRlYWRsaW5lID0gc29vbmVzdFRpbWVvdXQgLSBub3c7XG4gICAgc29jay5zZXRUaW1lb3V0KGRlYWRsaW5lLCBmdW5jdGlvbiAoKSB7XG4gICAgICB0aW1lb3V0SGFuZGxlcihzZXJ2ZXIsIHNvY2spO1xuICAgIH0pO1xuICB9XG59O1xuIl19 \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL21lbWpzL3NlcnZlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSw4Q0FBc0I7QUFDdEIsb0RBQTRCO0FBQzVCLG1DQU1pQjtBQTBCakIsTUFBYSxNQUFPLFNBQVEsZ0JBQU0sQ0FBQyxZQUFZO0lBZ0I3QyxZQUNFLElBQVk7SUFDWixnR0FBZ0c7SUFDaEcsSUFBc0IsRUFDdEIsUUFBaUIsRUFDakIsUUFBaUIsRUFDakIsT0FBZ0M7UUFFaEMsS0FBSyxFQUFFLENBQUM7UUFDUixJQUFJLENBQUMsY0FBYyxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDdEMsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUM7UUFDakIsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUM7UUFDakIsSUFBSSxDQUFDLFNBQVMsR0FBRyxLQUFLLENBQUM7UUFDdkIsSUFBSSxDQUFDLFVBQVUsR0FBRyxLQUFLLENBQUM7UUFDeEIsSUFBSSxDQUFDLGdCQUFnQixHQUFHLEVBQUUsQ0FBQztRQUMzQixJQUFJLENBQUMsaUJBQWlCLEdBQUcsRUFBRSxDQUFDO1FBQzVCLElBQUksQ0FBQyxlQUFlLEdBQUcsRUFBRSxDQUFDO1FBQzFCLElBQUksQ0FBQyxjQUFjLEdBQUcsRUFBRSxDQUFDO1FBQ3pCLElBQUksQ0FBQyxPQUFPLEdBQUcsYUFBSyxDQUFDLE9BQU8sSUFBSSxFQUFFLEVBQUU7WUFDbEMsT0FBTyxFQUFFLEdBQUc7WUFDWixTQUFTLEVBQUUsS0FBSztZQUNoQixjQUFjLEVBQUUsRUFBRTtTQUNuQixDQUFrQixDQUFDO1FBQ3BCLElBQ0UsSUFBSSxDQUFDLE9BQU8sQ0FBQyxXQUFXLEtBQUssU0FBUztZQUN0QyxJQUFJLENBQUMsT0FBTyxDQUFDLFdBQVcsS0FBSyxJQUFJLEVBQ2pDO1lBQ0EsSUFBSSxDQUFDLE9BQU8sQ0FBQyxXQUFX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LENBQUMsQ0FBQztRQUMvQixDQUFDLENBQUMsQ0FBQztLQUNKO0FBQ0gsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IG5ldCBmcm9tIFwibmV0XCI7XG5pbXBvcnQgZXZlbnRzIGZyb20gXCJldmVudHNcIjtcbmltcG9ydCB7XG4gIG1ha2VSZXF1ZXN0QnVmZmVyLFxuICBwYXJzZU1lc3NhZ2UsXG4gIG1lcmdlLFxuICB0aW1lc3RhbXAsXG4gIE1lc3NhZ2UsXG59IGZyb20gXCIuL3V0aWxzXCI7XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2VydmVyT3B0aW9ucyB7XG4gIHRpbWVvdXQ6IG51bWJlcjtcbiAga2VlcEFsaXZlOiBib29sZWFuO1xuICBrZWVwQWxpdmVEZWxheTogbnVtYmVyO1xuICBjb25udGltZW91dDogbnVtYmVyO1xuICB1c2VybmFtZT86IHN0cmluZztcbiAgcGFzc3dvcmQ/OiBzdHJpbmc7XG59XG5cbnR5cGUgU2VxID0gbnVtYmVyO1xuXG5leHBvcnQgaW50ZXJmYWNlIE9uQ29ubmVjdENhbGxiYWNrIHtcbiAgKHNvY2tldDogbmV0LlNvY2tldCk6IHZvaWQ7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgT25SZXNwb25zZUNhbGxiYWNrIHtcbiAgKG1lc3NhZ2U6IE1lc3NhZ2UpOiB2b2lkO1xuICBxdWlldD86IGJvb2xlYW47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgT25FcnJvckNhbGxiYWNrIHtcbiAgKGVycm9yOiBFcnJvcik6IHZvaWQ7XG59XG5cbmV4cG9ydCBjbGFzcyBTZXJ2ZXIgZXh0ZW5kcyBldmVudHMuRXZlbnRFbWl0dGVyIHtcbiAgcmVzcG9uc2VCdWZmZXI6IEJ1ZmZlcjtcbiAgaG9zdDogc3RyaW5nO1xuICBwb3J0OiBzdHJpbmcgfCBudW1iZXIgfCB1bmRlZmluZWQ7XG4gIGNvbm5lY3RlZDogYm9vbGVhbjtcbiAgdGltZW91dFNldDogYm9vbGVhbjtcbiAgY29ubmVjdENhbGxiYWNrczogT25Db25uZWN0Q2FsbGJhY2tbXTtcbiAgcmVzcG9uc2VDYWxsYmFja3M6IHsgW3NlcTogc3RyaW5nXTogT25SZXNwb25zZUNhbGxiYWNrIH07XG4gIHJlcXVlc3RUaW1lb3V0czogbnVtYmVyW107XG4gIGVycm9yQ2FsbGJhY2tzOiB7IFtzZXE6IHN0cmluZ106IE9uRXJyb3JDYWxsYmFjayB9O1xuICBvcHRpb25zOiBTZXJ2ZXJPcHRpb25zO1xuICB1c2VybmFtZTogc3RyaW5nIHwgdW5kZWZpbmVkO1xuICBwYXNzd29yZDogc3RyaW5nIHwgdW5kZWZpbmVkO1xuXG4gIF9zb2NrZXQ6IG5ldC5Tb2NrZXQgfCB1bmRlZmluZWQ7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgaG9zdDogc3RyaW5nLFxuICAgIC8qIFRPRE86IGFsbG93aW5nIHBvcnQgdG8gYmUgc3RyaW5nIG9yIHVuZGVmaW5lZCBpcyB1c2VkIGJ5IHRoZSB0ZXN0cywgYnV0IHNlZW1zIGJhZCBvdmVyYWxsLiAqL1xuICAgIHBvcnQ/OiBzdHJpbmcgfCBudW1iZXIsXG4gICAgdXNlcm5hbWU/OiBzdHJpbmcsXG4gICAgcGFzc3dvcmQ/OiBzdHJpbmcsXG4gICAgb3B0aW9ucz86IFBhcnRpYWw8U2VydmVyT3B0aW9ucz5cbiAgKSB7XG4gICAgc3VwZXIoKTtcbiAgICB0aGlzLnJlc3BvbnNlQnVmZmVyID0gQnVmZmVyLmZyb20oW10pO1xuICAgIHRoaXMuaG9zdCA9IGhvc3Q7XG4gICAgdGhpcy5wb3J0ID0gcG9ydDtcbiAgICB0aGlzLmNvbm5lY3RlZCA9IGZhbHNlO1xuICAgIHRoaXMudGltZW91dFNldCA9IGZhbHNlO1xuICAgIHRoaXMuY29ubmVjdENhbGxiYWNrcyA9IFtdO1xuICAgIHRoaXMucmVzcG9uc2VDYWxsYmFja3MgPSB7fTtcbiAgICB0aGlzLnJlcXVlc3RUaW1lb3V0cyA9IFtdO1xuICAgIHRoaXMuZXJyb3JDYWxsYmFja3MgPSB7fTtcbiAgICB0aGlzLm9wdGlvbnMgPSBtZXJnZShvcHRpb25zIHx8IHt9LCB7XG4gICAgICB0aW1lb3V0OiAwLjUsXG4gICAgICBrZWVwQWxpdmU6IGZhbHNlLFxuICAgICAga2VlcEFsaXZlRGVsYXk6IDMwLFxuICAgIH0pIGFzIFNlcnZlck9wdGlvbnM7XG4gICAgaWYgKFxuICAgICAgdGhpcy5vcHRpb25zLmNvbm50aW1lb3V0ID09PSB1bmRlZmluZWQgfHxcbiAgICAgIHRoaXMub3B0aW9ucy5jb25udGltZW91dCA9PT0gbnVsbFxuICAgICkge1xuICAgICAgdGhpcy5vcHRpb25zLmNvbm50aW1lb3V0ID0gMiAqIHRoaXMub3B0aW9ucy50aW1lb3V0O1xuICAgIH1cbiAgICB0aGlzLnVzZXJuYW1lID1cbiAgICAgIHVzZXJuYW1lIHx8XG4gICAgICB0aGlzLm9wdGlvbnMudXNlcm5hbWUgfHxcbiAgICAgIHByb2Nlc3MuZW52Lk1FTUNBQ0hJRVJfVVNFUk5BTUUgfHxcbiAgICAgIHByb2Nlc3MuZW52Lk1FTUNBQ0hFX1VTRVJOQU1FO1xuICAgIHRoaXMucGFzc3dvcmQgPVxuICAgICAgcGFzc3dvcmQgfHxcbiAgICAgIHRoaXMub3B0aW9ucy5wYXNzd29yZCB8fFxuICAgICAgcHJvY2Vzcy5lbnYuTUVNQ0FDSElFUl9QQVNTV09SRCB8fFxuICAgICAgcHJvY2Vzcy5lbnYuTUVNQ0FDSEVfUEFTU1dPUkQ7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICBvbkNvbm5lY3QoZnVuYzogT25Db25uZWN0Q2FsbGJhY2spIHtcbiAgICB0aGlzLmNvbm5lY3RDYWxsYmFja3MucHVzaChmdW5jKTtcbiAgfVxuXG4gIG9uUmVzcG9uc2Uoc2VxOiBTZXEsIGZ1bmM6IE9uUmVzcG9uc2VDYWxsYmFjaykge1xuICAgIHRoaXMucmVzcG9uc2VDYWxsYmFja3Nbc2VxXSA9IGZ1bmM7XG4gIH1cblxuICByZXNwb25kKHJlc3BvbnNlOiBNZXNzYWdlKSB7XG4gICAgY29uc3QgY2FsbGJhY2sgPSB0aGlzLnJlc3BvbnNlQ2FsbGJhY2tzW3Jlc3BvbnNlLmhlYWRlci5vcGFxdWVdO1xuICAgIGlmICghY2FsbGJhY2spIHtcbiAgICAgIC8vIGluIGNhc2Ugb2YgYXV0aGVudGljYXRpb24sIG5vIGNhbGxiYWNrIGlzIHJlZ2lzdGVyZWRcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY2FsbGJhY2socmVzcG9uc2UpO1xuICAgIGlmICghY2FsbGJhY2sucXVpZXQgfHwgcmVzcG9uc2UuaGVhZGVyLnRvdGFsQm9keUxlbmd0aCA9PT0gMCkge1xuICAgICAgZGVsZXRlIHRoaXMucmVzcG9uc2VDYWxsYmFja3NbcmVzcG9uc2UuaGVhZGVyLm9wYXF1ZV07XG4gICAgICB0aGlzLnJlcXVlc3RUaW1lb3V0cy5zaGlmdCgpO1xuICAgICAgZGVsZXRlIHRoaXMuZXJyb3JDYWxsYmFja3NbcmVzcG9uc2UuaGVhZGVyLm9wYXF1ZV07XG4gICAgfVxuICB9XG5cbiAgb25FcnJvcihzZXE6IFNlcSwgZnVuYzogT25FcnJvckNhbGxiYWNrKSB7XG4gICAgdGhpcy5lcnJvckNhbGxiYWNrc1tzZXFdID0gZnVuYztcbiAgfVxuXG4gIGVycm9yKGVycjogRXJyb3IpIHtcbiAgICBjb25zdCBlcnJjYWxscyA9IHRoaXMuZXJyb3JDYWxsYmFja3M7XG4gICAgdGhpcy5jb25uZWN0Q2FsbGJhY2tzID0gW107XG4gICAgdGhpcy5yZXNwb25zZUNhbGxiYWNrcyA9IHt9O1xuICAgIHRoaXMucmVxdWVzdFRpbWVvdXRzID0gW107XG4gICAgdGhpcy5lcnJvckNhbGxiYWNrcyA9IHt9O1xuICAgIHRoaXMudGltZW91dFNldCA9IGZhbHNlO1xuICAgIHRoaXMucmVzcG9uc2VCdWZmZXIgPSBCdWZmZXIuZnJvbShbXSk7XG4gICAgaWYgKHRoaXMuX3NvY2tldCkge1xuICAgICAgdGhpcy5fc29ja2V0LmRlc3Ryb3koKTtcbiAgICAgIGRlbGV0ZSB0aGlzLl9zb2NrZXQ7XG4gICAgfVxuICAgIGZvciAobGV0IGVycmNhbGwgb2YgT2JqZWN0LnZhbHVlcyhlcnJjYWxscykpIHtcbiAgICAgIGVycmNhbGwoZXJyKTtcbiAgICB9XG4gIH1cblxuICBsaXN0U2FzbCgpIHtcbiAgICBjb25zdCBidWYgPSBtYWtlUmVxdWVzdEJ1ZmZlcigweDIwLCBcIlwiLCBcIlwiLCBcIlwiKTtcbiAgICB0aGlzLndyaXRlU0FTTChidWYpO1xuICB9XG5cbiAgc2FzbEF1dGgoKSB7XG4gICAgY29uc3QgYXV0aFN0ciA9IFwiXFx4MDBcIiArIHRoaXMudXNlcm5hbWUgKyBcIlxceDAwXCIgKyB0aGlzLnBhc3N3b3JkO1xuICAgIGNvbnN0IGJ1ZiA9IG1ha2VSZXF1ZXN0QnVmZmVyKDB4MjEsIFwiUExBSU5cIiwgXCJcIiwgYXV0aFN0cik7XG4gICAgdGhpcy53cml0ZVNBU0woYnVmKTtcbiAgfVxuXG4gIGFwcGVuZFRvQnVmZmVyKGRhdGFCdWY6IEJ1ZmZlcikge1xuICAgIGNvbnN0IG9sZCA9IHRoaXMucmVzcG9uc2VCdWZmZXI7XG4gICAgdGhpcy5yZXNwb25zZUJ1ZmZlciA9IEJ1ZmZlci5hbGxvYyhvbGQubGVuZ3RoICsgZGF0YUJ1Zi5sZW5ndGgpO1xuICAgIG9sZC5jb3B5KHRoaXMucmVzcG9uc2VCdWZmZXIsIDApO1xuICAgIGRhdGFCdWYuY29weSh0aGlzLnJlc3BvbnNlQnVmZmVyLCBvbGQubGVuZ3RoKTtcbiAgICByZXR1cm4gdGhpcy5yZXNwb25zZUJ1ZmZlcjtcbiAgfVxuICByZXNwb25zZUhhbmRsZXIoZGF0YUJ1ZjogQnVmZmVyKSB7XG4gICAgbGV0IHJlc3BvbnNlOiBNZXNzYWdlIHwgZmFsc2U7XG4gICAgdHJ5IHtcbiAgICAgIHJlc3BvbnNlID0gcGFyc2VNZXNzYWdlKHRoaXMuYXBwZW5kVG9CdWZmZXIoZGF0YUJ1ZikpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHRoaXMuZXJyb3IoZSBhcyBFcnJvcik7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgbGV0IHJlc3BMZW5ndGg6IG51bWJlcjtcbiAgICB3aGlsZSAocmVzcG9uc2UpIHtcbiAgICAgIGlmIChyZXNwb25zZS5oZWFkZXIub3Bjb2RlID09PSAweDIwKSB7XG4gICAgICAgIHRoaXMuc2FzbEF1dGgoKTtcbiAgICAgIH0gZWxzZSBpZiAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cyA9PT0gKDB4MjAgYXMgYW55KSAvKiBUT0RPOiB3dGY/ICovKSB7XG4gICAgICAgIHRoaXMuZXJyb3IobmV3IEVycm9yKFwiTWVtY2FjaGVkIHNlcnZlciBhdXRoZW50aWNhdGlvbiBmYWlsZWQhXCIpKTtcbiAgICAgIH0gZWxzZSBpZiAocmVzcG9uc2UuaGVhZGVyLm9wY29kZSA9PT0gMHgyMSkge1xuICAgICAgICB0aGlzLmVtaXQoXCJhdXRoZW50aWNhdGVkXCIpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5yZXNwb25kKHJlc3BvbnNlKTtcbiAgICAgIH1cbiAgICAgIHJlc3BMZW5ndGggPSByZXNwb25zZS5oZWFkZXIudG90YWxCb2R5TGVuZ3RoICsgMjQ7XG4gICAgICB0aGlzLnJlc3BvbnNlQnVmZmVyID0gdGhpcy5yZXNwb25zZUJ1ZmZlci5zbGljZShyZXNwTGVuZ3RoKTtcbiAgICAgIHJlc3BvbnNlID0gcGFyc2VNZXNzYWdlKHRoaXMucmVzcG9uc2VCdWZmZXIpO1xuICAgIH1cbiAgfVxuICBzb2NrKHNhc2w6IGJvb2xlYW4sIGdvOiBPbkNvbm5lY3RDYWxsYmFjaykge1xuICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuXG4gICAgaWYgKCFzZWxmLl9zb2NrZXQpIHtcbiAgICAgIC8vIENBU0UgMTogY29tcGxldGVseSBuZXcgc29ja2V0XG4gICAgICBzZWxmLmNvbm5lY3RlZCA9IGZhbHNlO1xuICAgICAgc2VsZi5yZXNwb25zZUJ1ZmZlciA9IEJ1ZmZlci5mcm9tKFtdKTtcbiAgICAgIHNlbGYuX3NvY2tldCA9IG5ldC5jb25uZWN0KFxuICAgICAgICAvKiBUT0RPOiBhbGxvd2luZyBwb3J0IHRvIGJlIHN0cmluZyBvciB1bmRlZmluZWQgaXMgdXNlZCBieSB0aGUgdGVzdHMsIGJ1dCBzZWVtcyBiYWQgb3ZlcmFsbC4gKi9cbiAgICAgICAgdHlwZW9mIHRoaXMucG9ydCA9PT0gXCJzdHJpbmdcIlxuICAgICAgICAgID8gcGFyc2VJbnQodGhpcy5wb3J0LCAxMClcbiAgICAgICAgICA6IHRoaXMucG9ydCB8fCAxMTIxMSxcbiAgICAgICAgdGhpcy5ob3N0LFxuICAgICAgICBmdW5jdGlvbiAodGhpczogbmV0LlNvY2tldCkge1xuICAgICAgICAgIC8vIFNBU0wgYXV0aGVudGljYXRpb24gaGFuZGxlclxuICAgICAgICAgIHNlbGYub25jZShcImF1dGhlbnRpY2F0ZWRcIiwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKHNlbGYuX3NvY2tldCkge1xuICAgICAgICAgICAgICBjb25zdCBzb2NrZXQgPSBzZWxmLl9zb2NrZXQ7XG4gICAgICAgICAgICAgIHNlbGYuY29ubmVjdGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgLy8gY2FuY2VsIGNvbm5lY3Rpb24gdGltZW91dFxuICAgICAgICAgICAgICBzZWxmLl9zb2NrZXQuc2V0VGltZW91dCgwKTtcbiAgICAgICAgICAgICAgc2VsZi50aW1lb3V0U2V0ID0gZmFsc2U7XG4gICAgICAgICAgICAgIC8vIHJ1biBhY3R1YWwgcmVxdWVzdChzKVxuICAgICAgICAgICAgICBnbyhzZWxmLl9zb2NrZXQpO1xuICAgICAgICAgICAgICBzZWxmLmNvbm5lY3RDYWxsYmFja3MuZm9yRWFjaChmdW5jdGlvbiAoY2IpIHtcbiAgICAgICAgICAgICAgICBjYihzb2NrZXQpO1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgc2VsZi5jb25uZWN0Q2FsbGJhY2tzID0gW107XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICAvLyBzZXR1cCByZXNwb25zZSBoYW5kbGVyXG4gICAgICAgICAgdGhpcy5vbihcImRhdGFcIiwgZnVuY3Rpb24gKGRhdGFCdWYpIHtcbiAgICAgICAgICAgIHNlbGYucmVzcG9uc2VIYW5kbGVyKGRhdGFCdWYpO1xuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgLy8ga2ljayBvZiBTQVNMIGlmIG5lZWRlZFxuICAgICAgICAgIGlmIChzZWxmLnVzZXJuYW1lICYmIHNlbGYucGFzc3dvcmQpIHtcbiAgICAgICAgICAgIHNlbGYubGlzdFNhc2woKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc2VsZi5lbWl0KFwiYXV0aGVudGljYXRlZFwiKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICk7XG5cbiAgICAgIC8vIHNldHVwIGVycm9yIGhhbmRsZXJcbiAgICAgIHNlbGYuX3NvY2tldC5vbihcImVycm9yXCIsIGZ1bmN0aW9uIChlcnJvcikge1xuICAgICAgICBzZWxmLmVycm9yKGVycm9yKTtcbiAgICAgIH0pO1xuXG4gICAgICBzZWxmLl9zb2NrZXQub24oXCJjbG9zZVwiLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmIChPYmplY3Qua2V5cyhzZWxmLmVycm9yQ2FsbGJhY2tzKS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgc2VsZi5lcnJvcihuZXcgRXJyb3IoXCJzb2NrZXQgY2xvc2VkIHVuZXhwZWN0ZWRseS5cIikpO1xuICAgICAgICB9XG4gICAgICAgIHNlbGYuY29ubmVjdGVkID0gZmFsc2U7XG4gICAgICAgIHNlbGYucmVzcG9uc2VCdWZmZXIgPSBCdWZmZXIuZnJvbShbXSk7XG4gICAgICAgIGlmIChzZWxmLnRpbWVvdXRTZXQpIHtcbiAgICAgICAgICBzZWxmLl9zb2NrZXQ/LnNldFRpbWVvdXQoMCk7XG4gICAgICAgICAgc2VsZi50aW1lb3V0U2V0ID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgc2VsZi5fc29ja2V0ID0gdW5kZWZpbmVkO1xuICAgICAgfSk7XG5cbiAgICAgIC8vIHNldHVwIGNvbm5lY3Rpb24gdGltZW91dCBoYW5kbGVyXG4gICAgICBzZWxmLnRpbWVvdXRTZXQgPSB0cnVlO1xuICAgICAgc2VsZi5fc29ja2V0LnNldFRpbWVvdXQoXG4gICAgICAgIHNlbGYub3B0aW9ucy5jb25udGltZW91dCAqIDEwMDAsXG4gICAgICAgIGZ1bmN0aW9uICh0aGlzOiBuZXQuU29ja2V0KSB7XG4gICAgICAgICAgc2VsZi50aW1lb3V0U2V0ID0gZmFsc2U7XG4gICAgICAgICAgaWYgKCFzZWxmLmNvbm5lY3RlZCkge1xuICAgICAgICAgICAgdGhpcy5lbmQoKTtcbiAgICAgICAgICAgIHNlbGYuX3NvY2tldCA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIHNlbGYuZXJyb3IobmV3IEVycm9yKFwic29ja2V0IHRpbWVkIG91dCBjb25uZWN0aW5nIHRvIHNlcnZlci5cIikpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgKTtcblxuICAgICAgLy8gdXNlIFRDUCBrZWVwLWFsaXZlXG4gICAgICBzZWxmLl9zb2NrZXQuc2V0S2VlcEFsaXZlKFxuICAgICAgICBzZWxmLm9wdGlvbnMua2VlcEFsaXZlLFxuICAgICAgICBzZWxmLm9wdGlvbnMua2VlcEFsaXZlRGVsYXkgKiAxMDAwXG4gICAgICApO1xuICAgIH0gZWxzZSBpZiAoIXNlbGYuY29ubmVjdGVkICYmICFzYXNsKSB7XG4gICAgICAvLyBDQVNFIDI6IHNvY2tldCBleGlzdHMsIGJ1dCBzdGlsbCBjb25uZWN0aW5nIC8gYXV0aGVudGljYXRpbmdcbiAgICAgIHNlbGYub25Db25uZWN0KGdvKTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gQ0FTRSAzOiBzb2NrZXQgZXhpc3RzIGFuZCBjb25uZWN0ZWQgLyByZWFkeSB0byB1c2VcbiAgICAgIGdvKHNlbGYuX3NvY2tldCk7XG4gICAgfVxuICB9XG5cbiAgd3JpdGUoYmxvYjogQnVmZmVyKSB7XG4gICAgY29uc3Qgc2VsZiA9IHRoaXM7XG4gICAgY29uc3QgZGVhZGxpbmUgPSBNYXRoLnJvdW5kKHNlbGYub3B0aW9ucy50aW1lb3V0ICogMTAwMCk7XG4gICAgdGhpcy5zb2NrKGZhbHNlLCBmdW5jdGlvbiAocykge1xuICAgICAgcy53cml0ZShibG9iKTtcbiAgICAgIHNlbGYucmVxdWVzdFRpbWVvdXRzLnB1c2godGltZXN0YW1wKCkgKyBkZWFkbGluZSk7XG4gICAgICBpZiAoIXNlbGYudGltZW91dFNldCkge1xuICAgICAgICBzZWxmLnRpbWVvdXRTZXQgPSB0cnVlO1xuICAgICAgICBzLnNldFRpbWVvdXQoZGVhZGxpbmUsIGZ1bmN0aW9uICh0aGlzOiBuZXQuU29ja2V0KSB7XG4gICAgICAgICAgdGltZW91dEhhbmRsZXIoc2VsZiwgdGhpcyk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgd3JpdGVTQVNMKGJsb2I6IEJ1ZmZlcikge1xuICAgIHRoaXMuc29jayh0cnVlLCBmdW5jdGlvbiAocykge1xuICAgICAgcy53cml0ZShibG9iKTtcbiAgICB9KTtcbiAgfVxuXG4gIGNsb3NlKCkge1xuICAgIGlmICh0aGlzLl9zb2NrZXQpIHtcbiAgICAgIHRoaXMuX3NvY2tldC5lbmQoKTtcbiAgICB9XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICByZXR1cm4gXCI8U2VydmVyIFwiICsgdGhpcy5ob3N0ICsgXCI6XCIgKyB0aGlzLnBvcnQgKyBcIj5cIjtcbiAgfVxuXG4gIGhvc3Rwb3J0U3RyaW5nKCkge1xuICAgIHJldHVybiB0aGlzLmhvc3QgKyBcIjpcIiArIHRoaXMucG9ydDtcbiAgfVxufVxuXG4vLyBXZSBoYW5kbGUgdHJhY2tpbmcgdGltZW91dHMgd2l0aCBhbiBhcnJheSBvZiBkZWFkbGluZXMgKHJlcXVlc3RUaW1lb3V0cyksIGFzXG4vLyBub2RlIGRvZXNuJ3QgbGlrZSB1cyBzZXR0aW5nIHVwIGxvdHMgb2YgdGltZXJzLCBhbmQgdXNpbmcganVzdCBvbmUgaXMgbW9yZVxuLy8gZWZmaWNpZW50IGFueXdheS5cbmNvbnN0IHRpbWVvdXRIYW5kbGVyID0gZnVuY3Rpb24gKHNlcnZlcjogU2VydmVyLCBzb2NrOiBuZXQuU29ja2V0KSB7XG4gIGlmIChzZXJ2ZXIucmVxdWVzdFRpbWVvdXRzLmxlbmd0aCA9PT0gMCkge1xuICAgIC8vIG5vdGhpbmcgYWN0aXZlXG4gICAgc2VydmVyLnRpbWVvdXRTZXQgPSBmYWxzZTtcbiAgICByZXR1cm47XG4gIH1cblxuICAvLyBzb21lIHJlcXVlc3RzIG91dHN0YW5kaW5nLCBjaGVjayBpZiBhbnkgaGF2ZSB0aW1lZC1vdXRcbiAgY29uc3Qgbm93ID0gdGltZXN0YW1wKCk7XG4gIGNvbnN0IHNvb25lc3RUaW1lb3V0ID0gc2VydmVyLnJlcXVlc3RUaW1lb3V0c1swXTtcblxuICBpZiAoc29vbmVzdFRpbWVvdXQgPD0gbm93KSB7XG4gICAgLy8gdGltZW91dCBvY2N1cnJlZCFcbiAgICBzb2NrLmVuZCgpO1xuICAgIHNlcnZlci5jb25uZWN0ZWQgPSBmYWxzZTtcbiAgICBzZXJ2ZXIuX3NvY2tldCA9IHVuZGVmaW5lZDtcbiAgICBzZXJ2ZXIudGltZW91dFNldCA9IGZhbHNlO1xuICAgIHNlcnZlci5lcnJvcihuZXcgRXJyb3IoXCJzb2NrZXQgdGltZWQgb3V0IHdhaXRpbmcgb24gcmVzcG9uc2UuXCIpKTtcbiAgfSBlbHNlIHtcbiAgICAvLyBubyB0aW1lb3V0ISBTZXR1cCBuZXh0IG9uZS5cbiAgICBjb25zdCBkZWFkbGluZSA9IHNvb25lc3RUaW1lb3V0IC0gbm93O1xuICAgIHNvY2suc2V0VGltZW91dChkZWFkbGluZSwgZnVuY3Rpb24gKCkge1xuICAgICAgdGltZW91dEhhbmRsZXIoc2VydmVyLCBzb2NrKTtcbiAgICB9KTtcbiAgfVxufTtcbiJdfQ== \ No newline at end of file diff --git a/src/memjs/server.ts b/src/memjs/server.ts index 03890ca..ed96313 100644 --- a/src/memjs/server.ts +++ b/src/memjs/server.ts @@ -123,6 +123,7 @@ export class Server extends events.EventEmitter { this.requestTimeouts = []; this.errorCallbacks = {}; this.timeoutSet = false; + this.responseBuffer = Buffer.from([]); if (this._socket) { this._socket.destroy(); delete this._socket; @@ -181,6 +182,7 @@ export class Server extends events.EventEmitter { if (!self._socket) { // CASE 1: completely new socket self.connected = false; + self.responseBuffer = Buffer.from([]); self._socket = net.connect( /* TODO: allowing port to be string or undefined is used by the tests, but seems bad overall. */ typeof this.port === "string" @@ -229,6 +231,7 @@ export class Server extends events.EventEmitter { self.error(new Error("socket closed unexpectedly.")); } self.connected = false; + self.responseBuffer = Buffer.from([]); if (self.timeoutSet) { self._socket?.setTimeout(0); self.timeoutSet = false; From 19c9bb320e0a4750576e5b0f604244857b115315 Mon Sep 17 00:00:00 2001 From: Leon Wei Date: Tue, 3 Oct 2023 16:13:17 -0700 Subject: [PATCH 74/79] bump version to clear circleCI cache --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index b664ffd..9534ba9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "memjs", - "version": "1.2.2", + "version": "1.2.3", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "memjs", - "version": "1.2.2", + "version": "1.2.3", "license": "MIT", "devDependencies": { "@types/node": "12.20.7", diff --git a/package.json b/package.json index c907101..4268835 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "author": "Amit Levy", "name": "memjs", "description": "A memcache client for node using the binary protocol and SASL authentication", - "version": "1.2.2", + "version": "1.2.3", "license": "MIT", "homepage": "http://github.com/memcachier/memjs", "keywords": [ From a8a1eca6f6f1a0681a10d2bd517b6d746085159b Mon Sep 17 00:00:00 2001 From: Ben Hughes Date: Wed, 15 Nov 2023 15:34:29 -0500 Subject: [PATCH 75/79] Add versionAllWithErrors --- src/memjs/memjs.ts | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/memjs/memjs.ts b/src/memjs/memjs.ts index cec6ebf..22c3873 100644 --- a/src/memjs/memjs.ts +++ b/src/memjs/memjs.ts @@ -989,6 +989,45 @@ class Client { return { values: values }; } + /** + * Retrieves the server version (often used as a status check) from all the + * servers in the backend pool. If any servers error, the error is returned + * with the results. + * + * Callback functions are called before/after we ping each memcached node to + * allow logging of incremental results and timeouts. + * + * @param callbacks + * @returns + */ + async versionAllWithErrors(callbacks?: { + beforePing?: (serverKey: string) => void; + afterPing?: (serverKey: string, error?: Error) => void; + }): Promise<{ + values: Record + }> { + const versionObjects = await Promise.all( + this.serverKeys.map(async (serverKey) => { + const server = this.serverKeyToServer(serverKey); + callbacks?.beforePing?.(serverKey); + try { + const response = await this._version(server); + callbacks?.afterPing?.(serverKey); + return { serverKey: serverKey, value: { version: response.value } }; + } catch (err) { + const error = err as Error; + callbacks?.afterPing?.(serverKey, error); + return { serverKey: serverKey, value: { error } }; + } + }) + ); + const values = versionObjects.reduce((accumulator, versionObject) => { + accumulator[versionObject.serverKey] = versionObject.value; + return accumulator; + }, {} as Record); + return { values: values }; + } + /** * Closes (abruptly) connections to all the servers. * @see this.quit From 4f93728b4c15ccd15ab8db015e176257887cceee Mon Sep 17 00:00:00 2001 From: Ben Hughes Date: Wed, 15 Nov 2023 16:56:55 -0500 Subject: [PATCH 76/79] add types --- lib/memjs/memjs.d.ts | 20 ++++++++++++++++++++ lib/memjs/memjs.d.ts.map | 2 +- lib/memjs/memjs.js | 35 ++++++++++++++++++++++++++++++++++- 3 files changed, 55 insertions(+), 2 deletions(-) diff --git a/lib/memjs/memjs.d.ts b/lib/memjs/memjs.d.ts index 90d55c3..9fd3540 100644 --- a/lib/memjs/memjs.d.ts +++ b/lib/memjs/memjs.d.ts @@ -292,6 +292,26 @@ declare class Client { }): Promise<{ values: Record; }>; + /** + * Retrieves the server version (often used as a status check) from all the + * servers in the backend pool. If any servers error, the error is returned + * with the results. + * + * Callback functions are called before/after we ping each memcached node to + * allow logging of incremental results and timeouts. + * + * @param callbacks + * @returns + */ + versionAllWithErrors(callbacks?: { + beforePing?: (serverKey: string) => void; + afterPing?: (serverKey: string, error?: Error) => void; + }): Promise<{ + values: Record; + }>; /** * Closes (abruptly) connections to all the servers. * @see this.quit diff --git a/lib/memjs/memjs.d.ts.map b/lib/memjs/memjs.d.ts.map index 699e889..b37bfd3 100644 --- a/lib/memjs/memjs.d.ts.map +++ b/lib/memjs/memjs.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"memjs.d.ts","sourceRoot":"","sources":["../../src/memjs/memjs.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"memjs.d.ts","sourceRoot":"","sources":["../../src/memjs/memjs.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/lib/memjs/memjs.js b/lib/memjs/memjs.js index bc8c588..f39e8cf 100644 --- a/lib/memjs/memjs.js +++ b/lib/memjs/memjs.js @@ -676,6 +676,39 @@ class Client { }, {}); return { values: values }; } + /** + * Retrieves the server version (often used as a status check) from all the + * servers in the backend pool. If any servers error, the error is returned + * with the results. + * + * Callback functions are called before/after we ping each memcached node to + * allow logging of incremental results and timeouts. + * + * @param callbacks + * @returns + */ + async versionAllWithErrors(callbacks) { + const versionObjects = await Promise.all(this.serverKeys.map(async (serverKey) => { + var _a, _b, _c; + const server = this.serverKeyToServer(serverKey); + (_a = callbacks === null || callbacks === void 0 ? void 0 : callbacks.beforePing) === null || _a === void 0 ? void 0 : _a.call(callbacks, serverKey); + try { + const response = await this._version(server); + (_b = callbacks === null || callbacks === void 0 ? void 0 : callbacks.afterPing) === null || _b === void 0 ? void 0 : _b.call(callbacks, serverKey); + return { serverKey: serverKey, value: { version: response.value } }; + } + catch (err) { + const error = err; + (_c = callbacks === null || callbacks === void 0 ? void 0 : callbacks.afterPing) === null || _c === void 0 ? void 0 : _c.call(callbacks, serverKey, error); + return { serverKey: serverKey, value: { error } }; + } + })); + const values = versionObjects.reduce((accumulator, versionObject) => { + accumulator[versionObject.serverKey] = versionObject.value; + return accumulator; + }, {}); + return { values: values }; + } /** * Closes (abruptly) connections to all the servers. * @see this.quit @@ -768,4 +801,4 @@ class Client { } } exports.Client = Client; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVtanMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbWVtanMvbWVtanMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLHdCQUF3Qjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUV4QixxQ0FLa0I7QUE0bENELHVGQTlsQ2YsZUFBTSxPQThsQ2U7QUEzbEN2Qix1REFBK0Q7QUFDL0QsbUNBU2lCO0FBQ2pCLHVEQUF5QztBQUN6QywyQ0FBNkM7QUFDN0MsK0NBQWlDO0FBOGtDUixzQkFBSztBQTdrQzlCLGlEQUFtQztBQTZrQ0gsd0JBQU07QUEza0N0QyxTQUFTLDhCQUE4QixDQUNyQyxPQUFpQixFQUNqQixHQUFXO0lBRVgsTUFBTSxLQUFLLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQztJQUM3QixNQUFNLEtBQUssR0FBRyxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxnQkFBUSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3BELE9BQU8sT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ3hCLENBQUM7QUFFRCwrQ0FBK0M7QUFDL0MsU0FBUyxTQUFTLENBQ2hCLE9BQTBFO0lBRTFFLE9BQU8sSUFBSSxPQUFPLENBQUMsVUFBVSxPQUFPLEVBQUUsTUFBTTtRQUMxQyxPQUFPLENBQUMsVUFBVSxHQUFHLEVBQUUsTUFBTTtZQUMzQixHQUFHLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3RDLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBd0VELE1BQU0sTUFBTTtJQVFWLDRFQUE0RTtJQUM1RSxtQ0FBbUM7SUFDbkMsWUFBWSxPQUFpQixFQUFFLE9BQTBDO1FBQ3ZFLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO1FBQ3ZCLElB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LEdBQUcsQ0FBQztJQUNsQixDQUFDO0lBRU8saUJBQWlCLENBQ3ZCLFdBQW1CLEVBQ25CLGNBQTBDO1FBRTFDLE1BQU0sWUFBWSxHQUFHLFNBQVMsV0FBVyxLQUFLLFNBQVMsQ0FBQyxzQkFBc0IsQ0FDNUUsY0FBYyxDQUNmLEVBQUUsQ0FBQztRQUNKLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUN0QyxPQUFPLElBQUksS0FBSyxDQUFDLFlBQVksQ0FBQyxDQUFDO0lBQ2pDLENBQUM7SUFFRDs7O09BR0c7SUFDSyxtQkFBbUIsQ0FDekIsV0FBbUIsRUFDbkIsY0FBMEMsRUFDMUMsUUFBa0U7UUFFbEUsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixDQUFDLFdBQVcsRUFBRSxjQUFjLENBQUMsQ0FBQztRQUNsRSxJQUFJLFFBQVEsRUFBRTtZQUNaLFFBQVEsQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLENBQUM7U0FDdkI7UUFDRCxPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7Q0FDRjtBQUVRLHdCQUFNIiwic291cmNlc0NvbnRlbnQiOlsiLy8gTWVtVFMgTWVtY2FjaGUgQ2xpZW50XG5cbmltcG9ydCB7XG4gIE9uRXJyb3JDYWxsYmFjayxcbiAgT25SZXNwb25zZUNhbGxiYWNrLFxuICBTZXJ2ZXIsXG4gIFNlcnZlck9wdGlvbnMsXG59IGZyb20gXCIuL3NlcnZlclwiO1xuaW1wb3J0IHsgbm9vcFNlcmlhbGl6ZXIsIFNlcmlhbGl6ZXIgfSBmcm9tIFwiLi9ub29wLXNlcmlhbGl6ZXJcIjtcbmltcG9ydCB7XG4gIG1ha2VSZXF1ZXN0QnVmZmVyLFxuICBjb3B5SW50b1JlcXVlc3RCdWZmZXIsXG4gIG1lcmdlLFxuICBtYWtlRXhwaXJhdGlvbixcbiAgbWFrZUFtb3VudEluaXRpYWxBbmRFeHBpcmF0aW9uLFxuICBoYXNoQ29kZSxcbiAgTWF5YmVCdWZmZXIsXG4gIE1lc3NhZ2UsXG59IGZyb20gXCIuL3V0aWxzXCI7XG5pbXBvcnQgKiBhcyBjb25zdGFudHMgZnJvbSBcIi4vY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBSZXNwb25zZVN0YXR1cyB9IGZyb20gXCIuL2NvbnN0YW50c1wiO1xuaW1wb3J0ICogYXMgVXRpbHMgZnJvbSBcIi4vdXRpbHNcIjtcbmltcG9ydCAqIGFzIEhlYWRlciBmcm9tIFwiLi9oZWFkZXJcIjtcblxuZnVuY3Rpb24gZGVmYXVsdEtleVRvU2VydmVySGFzaEZ1bmN0aW9uKFxuICBzZXJ2ZXJzOiBzdHJpbmdbXSxcbiAga2V5OiBzdHJpbmdcbik6IHN0cmluZyB7XG4gIGNvbnN0IHRvdGFsID0gc2VydmVycy5sZW5ndGg7XG4gIGNvbnN0IGluZGV4ID0gdG90YWwgPiAxID8gaGFzaENvZGUoa2V5KSAlIHRvdGFsIDogMDtcbiAgcmV0dXJuIHNlcnZlcnNbaW5kZXhdO1xufVxuXG4vLyBjb252ZXJ0cyBhIGNhbGwgaW50byBhIHByb21pc2UtcmV0dXJuaW5nIG9uZVxuZnVuY3Rpb24gcHJvbWlzaWZ5PFJlc3VsdD4oXG4gIGNvbW1hbmQ6IChjYWxsYmFjazogKGVycm9yOiBFcnJvciB8IG51bGwsIHJlc3VsdDogUmVzdWx0KSA9PiB2b2lkKSA9PiB2b2lkXG4pOiBQcm9taXNlPFJlc3VsdD4ge1xuICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuICAgIGNvbW1hbmQoZnVuY3Rpb24gKGVyciwgcmVzdWx0KSB7XG4gICAgICBlcnIgPyByZWplY3QoZXJyKSA6IHJlc29sdmUocmVzdWx0KTtcbiAgICB9KTtcbiAgfSk7XG59XG5cbnR5cGUgUmVzcG9uc2VPckVycm9yQ2FsbGJhY2sgPSAoXG4gIGVycm9yOiBFcnJvciB8IG51bGwsXG4gIHJlc3BvbnNlOiBNZXNzYWdlIHwgbnVsbFxuKSA9PiB2b2lkO1xuXG5pbnRlcmZhY2UgQmFzZUNsaWVudE9wdGlvbnMge1xuICByZXRyaWVzOiBudW1iZXI7XG4gIHJldHJ5X2RlbGF5OiBudW1iZXI7XG4gIGV4cGlyZXM6IG51bWJlcjtcbiAgbG9nZ2VyOiB7IGxvZzogdHlwZW9mIGNvbnNvbGUubG9nIH07XG4gIGtleVRvU2VydmVySGFzaEZ1bmN0aW9uOiB0eXBlb2YgZGVmYXVsdEtleVRvU2VydmVySGFzaEZ1bmN0aW9uO1xufVxuXG5pbnRlcmZhY2UgU2VyaWFsaXplclByb3A8VmFsdWUsIEV4dHJhcz4ge1xuICBzZXJpYWxpemVyOiBTZXJpYWxpemVyPFZhbHVlLCBFeHRyYXM+O1xufVxuXG4vKipcbiAqIFRoZSBjbGllbnQgaGFzIHBhcnRpYWwgc3VwcG9ydCBmb3Igc2VyaWFsaXppbmcgYW5kIGRlc2VyaWFsaXppbmcgdmFsdWVzIGZyb20gdGhlXG4gKiBCdWZmZXIgYnl0ZSBzdHJpbmdzIHdlIHJlY2VpdmUgZnJvbSB0aGUgd2lyZS4gVGhlIGRlZmF1bHQgc2VyaWFsaXplciBpcyBmb3IgTWF5YmVCdWZmZXIuXG4gKlxuICogSWYgVmFsdWUgYW5kIEV4dHJhcyBhcmUgb2YgdHlwZSBCdWZmZXIsIHRoZW4gcmV0dXJuIHR5cGUgV2hlbkJ1ZmZlci4gT3RoZXJ3aXNlLFxuICogcmV0dXJuIHR5cGUgTm90QnVmZmVyLlxuICovXG50eXBlIElmQnVmZmVyPFZhbHVlLCBFeHRyYXMsIFdoZW5WYWx1ZUFuZEV4dHJhc0FyZUJ1ZmZlcnMsIE5vdEJ1ZmZlcj4gPVxuICBWYWx1ZSBleHRlbmRzIEJ1ZmZlclxuICAgID8gRXh0cmFzIGV4dGVuZHMgQnVmZmVyXG4gICAgICA/IFdoZW5WYWx1ZUFuZEV4dHJhc0FyZUJ1ZmZlcnNcbiAgICAgIDogTm90QnVmZmVyXG4gICAgOiBOb3RCdWZmZXI7XG5cbmV4cG9ydCB0eXBlIEdpdmVuQ2xpZW50T3B0aW9uczxWYWx1ZSwgRXh0cmFzPiA9IFBhcnRpYWw8QmFzZUNsaWVudE9wdGlvbnM+ICZcbiAgSWZCdWZmZXI8XG4gICAgVmFsdWUsXG4gICAgRXh0cmFzLFxuICAgIFBhcnRpYWw8U2VyaWFsaXplclByb3A8VmFsdWUsIEV4dHJhcz4+LFxuICAgIFNlcmlhbGl6ZXJQcm9wPFZhbHVlLCBFeHRyYXM+XG4gID47XG5cbmV4cG9ydCB0eXBlIENBU1Rva2VuID0gQnVmZmVyO1xuXG5leHBvcnQgaW50ZXJmYWNlIEdldFJlc3VsdDxWYWx1ZSA9IE1heWJlQnVmZmVyLCBFeHRyYXMgPSBNYXliZUJ1ZmZlcj4ge1xuICB2YWx1ZTogVmFsdWU7XG4gIGV4dHJhczogRXh0cmFzO1xuICBjYXM6IENBU1Rva2VuIHwgdW5kZWZpbmVkO1xufVxuXG5leHBvcnQgdHlwZSBHZXRNdWx0aVJlc3VsdDxcbiAgS2V5cyBleHRlbmRzIHN0cmluZyA9IHN0cmluZyxcbiAgVmFsdWUgPSBNYXliZUJ1ZmZlcixcbiAgRXh0cmFzID0gTWF5YmVCdWZmZXJcbj4gPSB7XG4gIFtLIGluIEtleXNdPzogR2V0UmVzdWx0PFZhbHVlLCBFeHRyYXM+O1xufTtcblxuZXhwb3J0IGludGVyZmFjZSBHZXRNdWx0aUVycm9yPEtleXMgZXh0ZW5kcyBzdHJpbmcgPSBzdHJpbmc+IHtcbiAgZXJyb3I6IEVycm9yO1xuICBzZXJ2ZXJLZXk6IHN0cmluZztcbiAga2V5czogS2V5c1tdO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEdldE11bHRpV2l0aEVycm9yc1Jlc3VsdDxcbktleXMgZXh0ZW5kcyBzdHJpbmcgPSBzdHJpbmcsXG5WYWx1ZSA9IE1heWJlQnVmZmVyLFxuRXh0cmFzID0gTWF5YmVCdWZmZXJcbj4ge1xuICByZXN1bHQ6IEdldE11bHRpUmVzdWx0PEtleXMsIFZhbHVlLCBFeHRyYXM+O1xuICBlcnJvcnM6IEdldE11bHRpRXJyb3I8S2V5cz5bXTtcbn1cblxuY2xhc3MgQ2xpZW50PFZhbHVlID0gTWF5YmVCdWZmZXIsIEV4dHJhcyA9IE1heWJlQnVmZmVyPiB7XG4gIHNlcnZlcnM6IFNlcnZlcltdO1xuICBzZXE6IG51bWJlcjtcbiAgb3B0aW9uczogQmFzZUNsaWVudE9wdGlvbnMgJiBQYXJ0aWFsPFNlcmlhbGl6ZXJQcm9wPFZhbHVlLCBFeHRyYXM+PjtcbiAgc2VyaWFsaXplcjogU2VyaWFsaXplcjxWYWx1ZSwgRXh0cmFzPjtcbiAgc2VydmVyTWFwOiB7IFtob3N0cG9ydDogc3RyaW5nXTogU2VydmVyIH07XG4gIHNlcnZlcktleXM6IHN0cmluZ1tdO1xuXG4gIC8vIENsaWVudCBpbml0aWFsaXplciB0YWtlcyBhIGxpc3Qgb2YgYFNlcnZlcmBzIGFuZCBhbiBgb3B0aW9uc2AgZGljdGlvbmFyeS5cbiAgLy8gU2VlIGBDbGllbnQuY3JlYXRlYCBmb3IgZGV0YWlscy5cbiAgY29uc3RydWN0b3Ioc2VydmVyczogU2VydmVyW10sIG9wdGlvbnM6IEdpdmVuQ2xpZW50T3B0aW9uczxWYWx1ZSwgRXh0cmFzPikge1xuICAgIHRoaXMuc2VydmVycyA9IHNlcnZlcnM7XG4gICAgdGhpcy5zZXEgPSAwO1xuICAgIHRoaXMub3B0aW9ucyA9IG1lcmdlKG9wdGlvbnMgfHwge30sIHtcbiAgICAgIHJldHJpZXM6IDIsXG4gICAgICByZXRyeV9kZWxheTogMC4yLFxuICAgICAgZXhwaXJlczogMCxcbiAgICAgIGxvZ2dlcjogY29uc29sZSxcbiAgICAgIGtleVRvU2VydmVySGFzaEZ1bmN0aW9uOiBkZWZhdWx0S2V5VG9TZXJ2ZXJIYXNoRnVuY3Rpb24sXG4gICAgfSk7XG5cbiAgICB0aGlzLnNlcmlhbGl6ZXIgPSB0aGlzLm9wdGlvbnMuc2VyaWFsaXplciB8fCAobm9vcFNlcmlhbGl6ZXIgYXMgYW55KTtcblxuICAgIC8vIFN0b3JlIGEgbWFwcGluZyBmcm9tIGhvc3Rwb3J0IC0+IHNlcnZlciBzbyB3ZSBjYW4gcXVpY2tseSBnZXQgYSBzZXJ2ZXIgb2JqZWN0IGZyb20gdGhlIHNlcnZlcktleSByZXR1cm5lZCBieSB0aGUgaGFzaGluZyBmdW5jdGlvblxuICAgIGNvbnN0IHNlcnZlck1hcDogeyBbaG9zdHBvcnQ6IHN0cmluZ106IFNlcnZlciB9ID0ge307XG4gICAgdGhpcy5zZXJ2ZXJzLmZvckVhY2goZnVuY3Rpb24gKHNlcnZlcikge1xuICAgICAgc2VydmVyTWFwW3NlcnZlci5ob3N0cG9ydFN0cmluZygpXSA9IHNlcnZlcjtcbiAgICB9KTtcbiAgICB0aGlzLnNlcnZlck1hcCA9IHNlcnZlck1hcDtcblxuICAgIC8vIHN0b3JlIGEgbGlzdCBvZiBhbGwgb3VyIHNlcnZlcktleXMgc28gd2UgZG9uJ3QgbmVlZCB0byBjb25zdGFudGx5IHJlYWxsb2NhdGUgdGhpcyBhcnJheVxuICAgIHRoaXMuc2VydmVyS2V5cyA9IE9iamVjdC5rZXlzKHRoaXMuc2VydmVyTWFwKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgbmV3IGNsaWVudCBnaXZlbiBhbiBvcHRpb25hbCBjb25maWcgc3RyaW5nIGFuZCBvcHRpb25hbCBoYXNoIG9mXG4gICAqIG9wdGlvbnMuIFRoZSBjb25maWcgc3RyaW5nIHNob3VsZCBiZSBvZiB0aGUgZm9ybTpcbiAgICpcbiAgICogICAgIFwiW3VzZXI6cGFzc0Bdc2VydmVyMVs6MTEyMTFdLFt1c2VyOnBhc3NAXXNlcnZlcjJbOjExMjExXSwuLi5cIlxuICAgKlxuICAgKiBJZiB0aGUgYXJndW1lbnQgaXMgbm90IGdpdmVuLCBmYWxsYmFjayBvbiB0aGUgYE1FTUNBQ0hJRVJfU0VSVkVSU2AgZW52aXJvbm1lbnRcbiAgICogdmFyaWFibGUsIGBNRU1DQUNIRV9TRVJWRVJTYCBlbnZpcm9ubWVudCB2YXJpYWJsZSBvciBgXCJsb2NhbGhvc3Q6MTEyMTFcImAuXG4gICAqXG4gICAqIFRoZSBvcHRpb25zIGhhc2ggbWF5IGNvbnRhaW4gdGhlIG9wdGlvbnM6XG4gICAqXG4gICAqICogYHJldHJpZXNgIC0gdGhlIG51bWJlciBvZiB0aW1lcyB0byByZXRyeSBhbiBvcGVyYXRpb24gaW4gbGlldSBvZiBmYWlsdXJlc1xuICAgKiAoZGVmYXVsdCAyKVxuICAgKiAqIGBleHBpcmVzYCAtIHRoZSBkZWZhdWx0IGV4cGlyYXRpb24gaW4gc2Vjb25kcyB0byB1c2UgKGRlZmF1bHQgMCAtIG5ldmVyXG4gICAqIGV4cGlyZSkuIElmIGBleHBpcmVzYCBpcyBncmVhdGVyIHRoYW4gMzAgZGF5cyAoNjAgeCA2MCB4IDI0IHggMzApLCBpdCBpc1xuICAgKiB0cmVhdGVkIGFzIGEgVU5JWCB0aW1lIChudW1iZXIgb2Ygc2Vjb25kcyBzaW5jZSBKYW51YXJ5IDEsIDE5NzApLlxuICAgKiAqIGBsb2dnZXJgIC0gYSBsb2dnZXIgb2JqZWN0IHRoYXQgcmVzcG9uZHMgdG8gYGxvZyhzdHJpbmcpYCBtZXRob2QgY2FsbHMuXG4gICAqXG4gICAqICAgfn5+flxuICAgKiAgICAgbG9nKG1zZzFbLCBtc2cyWywgbXNnM1suLi5dXV0pXG4gICAqICAgfn5+flxuICAgKlxuICAgKiAgIERlZmF1bHRzIHRvIGBjb25zb2xlYC5cbiAgICogKiBgc2VyaWFsaXplcmAgLSB0aGUgb2JqZWN0IHdoaWNoIHdpbGwgKGRlKXNlcmlhbGl6ZSB0aGUgZGF0YS4gSXQgbmVlZHNcbiAgICogICB0d28gcHVibGljIG1ldGhvZHM6IHNlcmlhbGl6ZSBhbmQgZGVzZXJpYWxpemUuIEl0IGRlZmF1bHRzIHRvIHRoZVxuICAgKiAgIG5vb3BTZXJpYWxpemVyOlxuICAgKlxuICAgKiAgIH5+fn5cbiAgICogICBjb25zdCBub29wU2VyaWFsaXplciA9IHtcbiAgICogICAgIHNlcmlhbGl6ZTogZnVuY3Rpb24gKG9wY29kZSwgdmFsdWUsIGV4dHJhcykge1xuICAgKiAgICAgICByZXR1cm4geyB2YWx1ZTogdmFsdWUsIGV4dHJhczogZXh0cmFzIH07XG4gICAqICAgICB9LFxuICAgKiAgICAgZGVzZXJpYWxpemU6IGZ1bmN0aW9uIChvcGNvZGUsIHZhbHVlLCBleHRyYXMpIHtcbiAgICogICAgICAgcmV0dXJuIHsgdmFsdWU6IHZhbHVlLCBleHRyYXM6IGV4dHJhcyB9O1xuICAgKiAgICAgfVxuICAgKiAgIH07XG4gICAqICAgfn5+flxuICAgKlxuICAgKiBPciBvcHRpb25zIGZvciB0aGUgc2VydmVycyBpbmNsdWRpbmc6XG4gICAqICogYHVzZXJuYW1lYCBhbmQgYHBhc3N3b3JkYCBmb3IgZmFsbGJhY2sgU0FTTCBhdXRoZW50aWNhdGlvbiBjcmVkZW50aWFscy5cbiAgICogKiBgdGltZW91dGAgaW4gc2Vjb25kcyB0byBkZXRlcm1pbmUgZmFpbHVyZSBmb3Igb3BlcmF0aW9ucy4gRGVmYXVsdCBpcyAwLjVcbiAgICogICAgICAgICAgICAgc2Vjb25kcy5cbiAgICogKiAnY29ubnRpbWVvdXQnIGluIHNlY29uZHMgdG8gY29ubmVjdGlvbiBmYWlsdXJlLiBEZWZhdWx0IGlzIHR3aWNlIHRoZSB2YWx1ZVxuICAgKiAgICAgICAgICAgICAgICAgb2YgYHRpbWVvdXRgLlxuICAgKiAqIGBrZWVwQWxpdmVgIHdoZXRoZXIgdG8gZW5hYmxlIGtlZXAtYWxpdmUgZnVuY3Rpb25hbGl0eS4gRGVmYXVsdHMgdG8gZmFsc2UuXG4gICAqICogYGtlZXBBbGl2ZURlbGF5YCBpbiBzZWNvbmRzIHRvIHRoZSBpbml0aWFsIGRlbGF5IGJlZm9yZSB0aGUgZmlyc3Qga2VlcGFsaXZlXG4gICAqICAgICAgICAgICAgICAgICAgICBwcm9iZSBpcyBzZW50IG9uIGFuIGlkbGUgc29ja2V0LiBEZWZhdWx0cyBpcyAzMCBzZWNvbmRzLlxuICAgKiAqIGBrZXlUb1NlcnZlckhhc2hGdW5jdGlvbmAgYSBmdW5jdGlvbiB0byBtYXAga2V5cyB0byBzZXJ2ZXJzLCB3aXRoIHRoZSBzaWduYXR1cmVcbiAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgKHNlcnZlcktleXM6IHN0cmluZ1tdLCBrZXk6IHN0cmluZyk6IHN0cmluZ1xuICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICBOT1RFOiBpZiB5b3UgbmVlZCB0byBkbyBzb21lIGV4cGVuc2l2ZSBpbml0aWFsaXphdGlvbiwgKnBsZWFzZSogZG8gaXQgbGF6aWx5IHRoZSBmaXJzdCB0aW1lIHlvdSB0aGlzIGZ1bmN0aW9uIGlzIGNhbGxlZCB3aXRoIGFuIGFycmF5IG9mIHNlcnZlcktleXMsIG5vdCBvbiBldmVyeSBjYWxsXG4gICAqL1xuICBzdGF0aWMgY3JlYXRlPFZhbHVlLCBFeHRyYXM+KFxuICAgIHNlcnZlcnNTdHI6IHN0cmluZyB8IHVuZGVmaW5lZCxcbiAgICBvcHRpb25zOiBJZkJ1ZmZlcjxcbiAgICAgIFZhbHVlLFxuICAgICAgRXh0cmFzLFxuICAgICAgdW5kZWZpbmVkIHwgKFBhcnRpYWw8U2VydmVyT3B0aW9ucz4gJiBHaXZlbkNsaWVudE9wdGlvbnM8VmFsdWUsIEV4dHJhcz4pLFxuICAgICAgUGFydGlhbDxTZXJ2ZXJPcHRpb25zPiAmIEdpdmVuQ2xpZW50T3B0aW9uczxWYWx1ZSwgRXh0cmFzPlxuICAgID5cbiAgKTogQ2xpZW50PFZhbHVlLCBFeHRyYXM+IHtcbiAgICBzZXJ2ZXJzU3RyID1cbiAgICAgIHNlcnZlcnNTdHIgfHxcbiAgICAgIHByb2Nlc3MuZW52Lk1FTUNBQ0hJRVJfU0VSVkVSUyB8fFxuICAgICAgcHJvY2Vzcy5lbnYuTUVNQ0FDSEVfU0VSVkVSUyB8fFxuICAgICAgXCJsb2NhbGhvc3Q6MTEyMTFcIjtcbiAgICBjb25zdCBzZXJ2ZXJVcmlzID0gc2VydmVyc1N0ci5zcGxpdChcIixcIik7XG4gICAgY29uc3Qgc2VydmVycyA9IHNlcnZlclVyaXMubWFwKGZ1bmN0aW9uICh1cmkpIHtcbiAgICAgIGNvbnN0IHVyaVBhcnRzID0gdXJpLnNwbGl0KFwiQFwiKTtcbiAgICAgIGNvbnN0IGhvc3RQb3J0ID0gdXJpUGFydHNbdXJpUGFydHMubGVuZ3RoIC0gMV0uc3BsaXQoXCI6XCIpO1xuICAgICAgY29uc3QgdXNlclBhc3MgPSAodXJpUGFydHNbdXJpUGFydHMubGVuZ3RoIC0gMl0gfHwgXCJcIikuc3BsaXQoXCI6XCIpO1xuICAgICAgcmV0dXJuIG5ldyBTZXJ2ZXIoXG4gICAgICAgIGhvc3RQb3J0WzBdLFxuICAgICAgICBwYXJzZUludChob3N0UG9ydFsxXSB8fCBcIjExMjExXCIsIDEwKSxcbiAgICAgICAgdXNlclBhc3NbMF0sXG4gICAgICAgIHVzZXJQYXNzWzFdLFxuICAgICAgICBvcHRpb25zXG4gICAgICApO1xuICAgIH0pO1xuICAgIHJldHVybiBuZXcgQ2xpZW50KHNlcnZlcnMsIG9wdGlvbnMgYXMgYW55KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHaXZlbiBhIHNlcnZlcktleSBmcm9tbG9va3VwS2V5VG9TZXJ2ZXJLZXksIHJldHVybiB0aGUgY29ycmVzcG9uZGluZyBTZXJ2ZXIgaW5zdGFuY2VcbiAgICpcbiAgICogQHBhcmFtICB7c3RyaW5nfSBzZXJ2ZXJLZXlcbiAgICogQHJldHVybnMge1NlcnZlcn1cbiAgICovXG4gIHNlcnZlcktleVRvU2VydmVyKHNlcnZlcktleTogc3RyaW5nKTogU2VydmVyIHtcbiAgICByZXR1cm4gdGhpcy5zZXJ2ZXJNYXBbc2VydmVyS2V5XTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHaXZlbiBhIGtleSB0byBsb29rIHVwIGluIG1lbWNhY2hlLCByZXR1cm4gYSBzZXJ2ZXJLZXkgKGJhc2VkIG9uIHNvbWVcbiAgICogaGFzaGluZyBmdW5jdGlvbikgd2hpY2ggY2FuIGJlIHVzZWQgdG8gaW5kZXggdGhpcy5zZXJ2ZXJNYXBcbiAgICovXG4gIGxvb2t1cEtleVRvU2VydmVyS2V5KGtleTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5vcHRpb25zLmtleVRvU2VydmVySGFzaEZ1bmN0aW9uKHRoaXMuc2VydmVyS2V5cywga2V5KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXRyaWV2ZXMgdGhlIHZhbHVlIGF0IHRoZSBnaXZlbiBrZXkgaW4gbWVtY2FjaGUuXG4gICAqL1xuICBhc3luYyBnZXQoa2V5OiBzdHJpbmcpOiBQcm9taXNlPEdldFJlc3VsdDxWYWx1ZSwgRXh0cmFzPiB8IG51bGw+IHtcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoY29uc3RhbnRzLk9QX0dFVCwga2V5LCBcIlwiLCBcIlwiLCB0aGlzLnNlcSk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIGNvbnN0IGRlc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5kZXNlcmlhbGl6ZShcbiAgICAgICAgICByZXNwb25zZS5oZWFkZXIub3Bjb2RlLFxuICAgICAgICAgIHJlc3BvbnNlLnZhbCxcbiAgICAgICAgICByZXNwb25zZS5leHRyYXNcbiAgICAgICAgKTtcbiAgICAgICAgcmV0dXJuIHsgLi4uZGVzZXJpYWxpemVkLCBjYXM6IHJlc3BvbnNlLmhlYWRlci5jYXMgfTtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuS0VZX05PVF9GT1VORDpcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiR0VUXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBCdWlsZCBhIHBpcGVsaW5lZCBnZXQgbXVsdGkgcmVxdWVzdCBieSBzZW5kaW5nIG9uZSBHRVRLUSBmb3IgZWFjaCBrZXkgKHF1aWV0LCBtZWFuaW5nIGl0IHdvbid0IHJlc3BvbmQgaWYgdGhlIHZhbHVlIGlzIG1pc3NpbmcpIGZvbGxvd2VkIGJ5IGEgbm8tb3AgdG8gZm9yY2UgYSByZXNwb25zZSAoYW5kIHRvIGdpdmUgdXMgYSBzZW50aW5lbCByZXNwb25zZSB0aGF0IHRoZSBwaXBlbGluZSBpcyBkb25lKVxuICAgKlxuICAgKiBjZiBodHRwczovL2dpdGh1Yi5jb20vY291Y2hiYXNlL21lbWNhY2hlZC9ibG9iL21hc3Rlci9kb2NzL0JpbmFyeVByb3RvY29sLm1kIzB4MGQtZ2V0a3EtZ2V0LXdpdGgta2V5LXF1aWV0bHlcbiAgICovXG4gIF9idWlsZEdldE11bHRpUmVxdWVzdChrZXlzOiBzdHJpbmdbXSwgc2VxOiBudW1iZXIpOiBCdWZmZXIge1xuICAgIC8vIHN0YXJ0IGF0IDI0IGZvciB0aGUgbm8tb3AgY29tbWFuZCBhdCB0aGUgZW5kXG4gICAgbGV0IHJlcXVlc3RTaXplID0gMjQ7XG4gICAgZm9yIChjb25zdCBrZXlJZHggaW4ga2V5cykge1xuICAgICAgcmVxdWVzdFNpemUgKz0gQnVmZmVyLmJ5dGVMZW5ndGgoa2V5c1trZXlJZHhdLCBcInV0ZjhcIikgKyAyNDtcbiAgICB9XG5cbiAgICBjb25zdCByZXF1ZXN0ID0gQnVmZmVyLmFsbG9jKHJlcXVlc3RTaXplKTtcblxuICAgIGxldCBieXRlc1dyaXR0ZW4gPSAwO1xuICAgIGZvciAoY29uc3Qga2V5SWR4IGluIGtleXMpIHtcbiAgICAgIGNvbnN0IGtleSA9IGtleXNba2V5SWR4XTtcbiAgICAgIGJ5dGVzV3JpdHRlbiArPSBjb3B5SW50b1JlcXVlc3RCdWZmZXIoXG4gICAgICAgIGNvbnN0YW50cy5PUF9HRVRLUSxcbiAgICAgICAga2V5LFxuICAgICAgICBcIlwiLFxuICAgICAgICBcIlwiLFxuICAgICAgICBzZXEsXG4gICAgICAgIHJlcXVlc3QsXG4gICAgICAgIGJ5dGVzV3JpdHRlblxuICAgICAgKTtcbiAgICB9XG5cbiAgICBieXRlc1dyaXR0ZW4gKz0gY29weUludG9SZXF1ZXN0QnVmZmVyKFxuICAgICAgY29uc3RhbnRzLk9QX05PX09QLFxuICAgICAgXCJcIixcbiAgICAgIFwiXCIsXG4gICAgICBcIlwiLFxuICAgICAgc2VxLFxuICAgICAgcmVxdWVzdCxcbiAgICAgIGJ5dGVzV3JpdHRlblxuICAgICk7XG5cbiAgICByZXR1cm4gcmVxdWVzdDtcbiAgfVxuXG4gIC8qKiBFeGVjdXRpbmcgYSBwaXBlbGluZWQgKG11bHRpKSBnZXQgYWdhaW5zdCBhIHNpbmdsZSBzZXJ2ZXIuIFRoaXMgaXMgYSBwcml2YXRlIGltcGxlbWVudGF0aW9uIGRldGFpbCBvZiBnZXRNdWx0aS4gKi9cbiAgYXN5bmMgX2dldE11bHRpVG9TZXJ2ZXI8S2V5cyBleHRlbmRzIHN0cmluZz4oXG4gICAgc2VydjogU2VydmVyLFxuICAgIGtleXM6IEtleXNbXVxuICApOiBQcm9taXNlPEdldE11bHRpUmVzdWx0PEtleXMsIFZhbHVlLCBFeHRyYXM+PiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGNvbnN0IHJlc3BvbnNlTWFwOiBHZXRNdWx0aVJlc3VsdDxzdHJpbmcsIFZhbHVlLCBFeHRyYXM+ID0ge307XG5cbiAgICAgIGNvbnN0IGhhbmRsZTogT25SZXNwb25zZUNhbGxiYWNrID0gKHJlc3BvbnNlKSA9PiB7XG4gICAgICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgICAgIC8vIFdoZW4gd2UgZ2V0IHRoZSBuby1vcCByZXNwb25zZSwgd2UgYXJlIGRvbmUgd2l0aCB0aGlzIG9uZSBnZXRNdWx0aSBpbiB0aGUgcGVyLWJhY2tlbmQgZmFuLW91dFxuICAgICAgICAgICAgaWYgKHJlc3BvbnNlLmhlYWRlci5vcGNvZGUgPT09IGNvbnN0YW50cy5PUF9OT19PUCkge1xuICAgICAgICAgICAgICAvLyBUaGlzIGVuc3VyZXMgdGhlIGhhbmRsZXIgd2lsbCBiZSBkZWxldGVkIGZyb20gdGhlIHJlc3BvbnNlQ2FsbGJhY2tzIG1hcCBpbiBzZXJ2ZXIuanNcbiAgICAgICAgICAgICAgLy8gVGhpcyBpc24ndCB0ZWNobmljYWxseSBuZWVkZWQgaGVyZSBiZWNhdXNlIHRoZSBsb2dpYyBpbiBzZXJ2ZXIuanMgYWxzbyBjaGVja3MgaWYgdG90YWxCb2R5TGVuZ3RoID09PSAwLCBidXQgb3VyIHVuaXR0ZXN0cyBhcmVuJ3QgZ3JlYXQgYWJvdXQgc2V0dGluZyB0aGF0IGZpZWxkLCBhbmQgYWxzbyB0aGlzIG1ha2VzIGl0IG1vcmUgZXhwbGljaXRcbiAgICAgICAgICAgICAgaGFuZGxlLnF1aWV0ID0gZmFsc2U7XG4gICAgICAgICAgICAgIHJlc29sdmUocmVzcG9uc2VNYXApO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgICAgICAgcmVzcG9uc2UuaGVhZGVyLm9wY29kZSA9PT0gY29uc3RhbnRzLk9QX0dFVEsgfHxcbiAgICAgICAgICAgICAgcmVzcG9uc2UuaGVhZGVyLm9wY29kZSA9PT0gY29uc3RhbnRzLk9QX0dFVEtRXG4gICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgY29uc3QgZGVzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLmRlc2VyaWFsaXplKFxuICAgICAgICAgICAgICAgIHJlc3BvbnNlLmhlYWRlci5vcGNvZGUsXG4gICAgICAgICAgICAgICAgcmVzcG9uc2UudmFsLFxuICAgICAgICAgICAgICAgIHJlc3BvbnNlLmV4dHJhc1xuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICBjb25zdCBrZXkgPSByZXNwb25zZS5rZXkudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgaWYgKGtleS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVqZWN0KFxuICAgICAgICAgICAgICAgICAgbmV3IEVycm9yKFxuICAgICAgICAgICAgICAgICAgICBcIlJlY2lldmVkIGVtcHR5IGtleSBpbiBnZXRNdWx0aTogXCIgK1xuICAgICAgICAgICAgICAgICAgICAgIEpTT04uc3RyaW5naWZ5KHJlc3BvbnNlKVxuICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgcmVzcG9uc2VNYXBba2V5XSA9IHsgLi4uZGVzZXJpYWxpemVkLCBjYXM6IHJlc3BvbnNlLmhlYWRlci5jYXMgfTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHJldHVybiByZWplY3QoXG4gICAgICAgICAgICAgICAgbmV3IEVycm9yKFxuICAgICAgICAgICAgICAgICAgXCJSZWNpZXZlZCByZXNwb25zZSBpbiBnZXRNdWx0aSBmb3IgdW5rbm93biBvcGNvZGU6IFwiICtcbiAgICAgICAgICAgICAgICAgICAgSlNPTi5zdHJpbmdpZnkocmVzcG9uc2UpXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHJldHVybiByZWplY3QoXG4gICAgICAgICAgICAgIHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJHRVRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cylcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH07XG4gICAgICAvLyBUaGlzIHByZXZlbnRzIHRoZSBoYW5kbGVyIGZyb20gYmVpbmcgZGVsZXRlZFxuICAgICAgLy8gYWZ0ZXIgdGhlIGZpcnN0IHJlc3BvbnNlLiBMb2dpYyBpbiBzZXJ2ZXIuanMuXG4gICAgICBoYW5kbGUucXVpZXQgPSB0cnVlO1xuXG4gICAgICBjb25zdCBzZXEgPSB0aGlzLmluY3JTZXEoKTtcbiAgICAgIGNvbnN0IHJlcXVlc3QgPSB0aGlzLl9idWlsZEdldE11bHRpUmVxdWVzdChrZXlzLCBzZXEpO1xuICAgICAgc2Vydi5vblJlc3BvbnNlKHRoaXMuc2VxLCBoYW5kbGUpO1xuICAgICAgc2Vydi5vbkVycm9yKHRoaXMuc2VxLCByZWplY3QpO1xuICAgICAgc2Vydi53cml0ZShyZXF1ZXN0KTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXRyaWV2cyB0aGUgdmFsdWUgYXQgdGhlIGdpdmVuIGtleXMgaW4gbWVtY2FjaGVkLiBSZXR1cm5zIGEgbWFwIGZyb20gdGhlXG4gICAqIHJlcXVlc3RlZCBrZXlzIHRvIHJlc3VsdHMsIG9yIG51bGwgaWYgdGhlIGtleSB3YXMgbm90IGZvdW5kLlxuICAgKi9cbiAgYXN5bmMgZ2V0TXVsdGk8S2V5cyBleHRlbmRzIHN0cmluZz4oXG4gICAga2V5czogS2V5c1tdXG4gICk6IFByb21pc2U8R2V0TXVsdGlSZXN1bHQ8S2V5cywgVmFsdWUsIEV4dHJhcz4+IHtcbiAgICBjb25zdCBzZXJ2ZXJLZXl0b0xvb2t1cEtleXM6IHtcbiAgICAgIFtzZXJ2ZXJLZXk6IHN0cmluZ106IHN0cmluZ1tdO1xuICAgIH0gPSB7fTtcbiAgICBrZXlzLmZvckVhY2goKGxvb2t1cEtleSkgPT4ge1xuICAgICAgY29uc3Qgc2VydmVyS2V5ID0gdGhpcy5sb29rdXBLZXlUb1NlcnZlcktleShsb29rdXBLZXkpO1xuICAgICAgaWYgKCFzZXJ2ZXJLZXl0b0xvb2t1cEtleXNbc2VydmVyS2V5XSkge1xuICAgICAgICBzZXJ2ZXJLZXl0b0xvb2t1cEtleXNbc2VydmVyS2V5XSA9IFtdO1xuICAgICAgfVxuICAgICAgc2VydmVyS2V5dG9Mb29rdXBLZXlzW3NlcnZlcktleV0ucHVzaChsb29rdXBLZXkpO1xuICAgIH0pO1xuXG4gICAgY29uc3QgdXNlZFNlcnZlcktleXMgPSBPYmplY3Qua2V5cyhzZXJ2ZXJLZXl0b0xvb2t1cEtleXMpO1xuICAgIGNvbnN0IHJlc3VsdHMgPSBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIHVzZWRTZXJ2ZXJLZXlzLm1hcCgoc2VydmVyS2V5KSA9PiB7XG4gICAgICAgIGNvbnN0IHNlcnZlciA9IHRoaXMuc2VydmVyS2V5VG9TZXJ2ZXIoc2VydmVyS2V5KTtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2dldE11bHRpVG9TZXJ2ZXIoc2VydmVyLCBzZXJ2ZXJLZXl0b0xvb2t1cEtleXNbc2VydmVyS2V5XSk7XG4gICAgICB9KVxuICAgICk7XG5cbiAgICByZXR1cm4gT2JqZWN0LmFzc2lnbih7fSwgLi4ucmVzdWx0cyk7XG4gIH1cblxuICBhc3luYyBnZXRNdWx0aVdpdGhFcnJvcnM8S2V5cyBleHRlbmRzIHN0cmluZz4oXG4gICAga2V5czogS2V5c1tdXG4gICk6IFByb21pc2U8R2V0TXVsdGlXaXRoRXJyb3JzUmVzdWx0PEtleXMsIFZhbHVlLCBFeHRyYXM+PiB7XG4gICAgY29uc3Qgc2VydmVyS2V5dG9Mb29rdXBLZXlzOiB7XG4gICAgICBbc2VydmVyS2V5OiBzdHJpbmddOiBLZXlzW107XG4gICAgfSA9IHt9O1xuICAgIGtleXMuZm9yRWFjaCgobG9va3VwS2V5KSA9PiB7XG4gICAgICBjb25zdCBzZXJ2ZXJLZXkgPSB0aGlzLmxvb2t1cEtleVRvU2VydmVyS2V5KGxvb2t1cEtleSk7XG4gICAgICBpZiAoIXNlcnZlcktleXRvTG9va3VwS2V5c1tzZXJ2ZXJLZXldKSB7XG4gICAgICAgIHNlcnZlcktleXRvTG9va3VwS2V5c1tzZXJ2ZXJLZXldID0gW107XG4gICAgICB9XG4gICAgICBzZXJ2ZXJLZXl0b0xvb2t1cEtleXNbc2VydmVyS2V5XS5wdXNoKGxvb2t1cEtleSk7XG4gICAgfSk7XG5cbiAgICBjb25zdCB1c2VkU2VydmVyS2V5cyA9IE9iamVjdC5rZXlzKHNlcnZlcktleXRvTG9va3VwS2V5cyk7XG4gICAgY29uc3QgZXJyb3JzOiBHZXRNdWx0aUVycm9yPEtleXM+W10gPSBbXTtcbiAgICBjb25zdCByZXN1bHRzID0gYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICB1c2VkU2VydmVyS2V5cy5tYXAoYXN5bmMgKHNlcnZlcktleSkgPT4ge1xuICAgICAgICBjb25zdCBzZXJ2ZXIgPSB0aGlzLnNlcnZlcktleVRvU2VydmVyKHNlcnZlcktleSk7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgcmV0dXJuIGF3YWl0IHRoaXMuX2dldE11bHRpVG9TZXJ2ZXIoc2VydmVyLCBzZXJ2ZXJLZXl0b0xvb2t1cEtleXNbc2VydmVyS2V5XSk7XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgZXJyb3JzLnB1c2goe1xuICAgICAgICAgICAgZXJyb3I6IGVycm9yIGFzIEVycm9yLFxuICAgICAgICAgICAgc2VydmVyS2V5LFxuICAgICAgICAgICAga2V5czogc2VydmVyS2V5dG9Mb29rdXBLZXlzW3NlcnZlcktleV1cbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfSlcbiAgICApO1xuXG4gICAgcmV0dXJuIHsgcmVzdWx0OiBPYmplY3QuYXNzaWduKHt9LCAuLi5yZXN1bHRzKSwgZXJyb3JzIH07XG4gIH1cblxuICAvKipcbiAgICogU2V0cyBga2V5YCB0byBgdmFsdWVgLlxuICAgKi9cbiAgYXN5bmMgc2V0KFxuICAgIGtleTogc3RyaW5nLFxuICAgIHZhbHVlOiBWYWx1ZSxcbiAgICBvcHRpb25zPzogeyBleHBpcmVzPzogbnVtYmVyOyBjYXM/OiBDQVNUb2tlbiB9XG4gICk6IFByb21pc2U8Ym9vbGVhbiB8IG51bGw+IHtcbiAgICBjb25zdCBleHBpcmVzID0gb3B0aW9ucz8uZXhwaXJlcztcbiAgICBjb25zdCBjYXMgPSBvcHRpb25zPy5jYXM7XG5cbiAgICAvLyBUT0RPOiBzdXBwb3J0IGZsYWdzXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgZXhwaXJhdGlvbiA9IG1ha2VFeHBpcmF0aW9uKGV4cGlyZXMgfHwgdGhpcy5vcHRpb25zLmV4cGlyZXMpO1xuICAgIGNvbnN0IGV4dHJhcyA9IEJ1ZmZlci5jb25jYXQoW0J1ZmZlci5mcm9tKFwiMDAwMDAwMDBcIiwgXCJoZXhcIiksIGV4cGlyYXRpb25dKTtcbiAgICBjb25zdCBzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLnNlcmlhbGl6ZShcbiAgICAgIGNvbnN0YW50cy5PUF9TRVQsXG4gICAgICB2YWx1ZSxcbiAgICAgIGV4dHJhc1xuICAgICk7XG4gICAgY29uc3QgcmVxdWVzdCA9IFV0aWxzLmVuY29kZVJlcXVlc3Qoe1xuICAgICAgaGVhZGVyOiB7XG4gICAgICAgIG9wY29kZTogY29uc3RhbnRzLk9QX1NFVCxcbiAgICAgICAgb3BhcXVlOiB0aGlzLnNlcSxcbiAgICAgICAgY2FzLFxuICAgICAgfSxcbiAgICAgIGtleSxcbiAgICAgIHZhbHVlOiBzZXJpYWxpemVkLnZhbHVlLFxuICAgICAgZXh0cmFzOiBzZXJpYWxpemVkLmV4dHJhcyxcbiAgICB9KTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9FWElTVFM6XG4gICAgICAgIGlmIChjYXMpIHtcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIlNFVFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICAgICAgfVxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIlNFVFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQUREXG4gICAqXG4gICAqIEFkZHMgdGhlIGdpdmVuIF9rZXlfIGFuZCBfdmFsdWVfIHRvIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHNcbiAgICogaWYgdGhlIGtleSBpcyBub3QgYWxyZWFkeSBzZXQuXG4gICAqXG4gICAqIFRoZSBvcHRpb25zIGRpY3Rpb25hcnkgdGFrZXM6XG4gICAqICogX2V4cGlyZXNfOiBvdmVycmlkZXMgdGhlIGRlZmF1bHQgZXhwaXJhdGlvbiAoc2VlIGBDbGllbnQuY3JlYXRlYCkgZm9yIHRoaXNcbiAgICogICAgICAgICAgICAgIHBhcnRpY3VsYXIga2V5LXZhbHVlIHBhaXIuXG4gICAqL1xuICBhc3luYyBhZGQoXG4gICAga2V5OiBzdHJpbmcsXG4gICAgdmFsdWU6IFZhbHVlLFxuICAgIG9wdGlvbnM/OiB7IGV4cGlyZXM/OiBudW1iZXIgfVxuICApOiBQcm9taXNlPGJvb2xlYW4gfCBudWxsPiB7XG4gICAgLy8gVE9ETzogc3VwcG9ydCBmbGFncywgc3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgZXhwaXJhdGlvbiA9IG1ha2VFeHBpcmF0aW9uKG9wdGlvbnM/LmV4cGlyZXMgfHwgdGhpcy5vcHRpb25zLmV4cGlyZXMpO1xuICAgIGNvbnN0IGV4dHJhcyA9IEJ1ZmZlci5jb25jYXQoW0J1ZmZlci5mcm9tKFwiMDAwMDAwMDBcIiwgXCJoZXhcIiksIGV4cGlyYXRpb25dKTtcblxuICAgIGNvbnN0IG9wY29kZSA9IGNvbnN0YW50cy5PUF9BREQ7XG4gICAgY29uc3Qgc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5zZXJpYWxpemUob3Bjb2RlLCB2YWx1ZSwgZXh0cmFzKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICBvcGNvZGUsXG4gICAgICBrZXksXG4gICAgICBzZXJpYWxpemVkLmV4dHJhcyxcbiAgICAgIHNlcmlhbGl6ZWQudmFsdWUsXG4gICAgICB0aGlzLnNlcVxuICAgICk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfRVhJU1RTOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIkFERFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmVwbGFjZXMgdGhlIGdpdmVuIF9rZXlfIGFuZCBfdmFsdWVfIHRvIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHNcbiAgICogaWYgdGhlIGtleSBpcyBhbHJlYWR5IHByZXNlbnQuXG4gICAqL1xuICBhc3luYyByZXBsYWNlKFxuICAgIGtleTogc3RyaW5nLFxuICAgIHZhbHVlOiBWYWx1ZSxcbiAgICBvcHRpb25zPzogeyBleHBpcmVzPzogbnVtYmVyIH1cbiAgKTogUHJvbWlzZTxib29sZWFuIHwgbnVsbD4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgZmxhZ3MsIHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IGV4cGlyYXRpb24gPSBtYWtlRXhwaXJhdGlvbihvcHRpb25zPy5leHBpcmVzIHx8IHRoaXMub3B0aW9ucy5leHBpcmVzKTtcbiAgICBjb25zdCBleHRyYXMgPSBCdWZmZXIuY29uY2F0KFtCdWZmZXIuZnJvbShcIjAwMDAwMDAwXCIsIFwiaGV4XCIpLCBleHBpcmF0aW9uXSk7XG5cbiAgICBjb25zdCBvcGNvZGU6IGNvbnN0YW50cy5PUCA9IGNvbnN0YW50cy5PUF9SRVBMQUNFO1xuICAgIGNvbnN0IHNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuc2VyaWFsaXplKG9wY29kZSwgdmFsdWUsIGV4dHJhcyk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKFxuICAgICAgb3Bjb2RlLFxuICAgICAga2V5LFxuICAgICAgc2VyaWFsaXplZC5leHRyYXMsXG4gICAgICBzZXJpYWxpemVkLnZhbHVlLFxuICAgICAgdGhpcy5zZXFcbiAgICApO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuS0VZX05PVF9GT1VORDpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIlJFUExBQ0VcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIERlbGV0ZXMgdGhlIGdpdmVuIF9rZXlfIGZyb20gbWVtY2FjaGUuIFRoZSBvcGVyYXRpb24gb25seSBzdWNjZWVkc1xuICAgKiBpZiB0aGUga2V5IGlzIGFscmVhZHkgcHJlc2VudC5cbiAgICovXG4gIGFzeW5jIGRlbGV0ZShrZXk6IHN0cmluZyk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIC8vIFRPRE86IFN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcig0LCBrZXksIFwiXCIsIFwiXCIsIHRoaXMuc2VxKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcblxuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuS0VZX05PVF9GT1VORDpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIkRFTEVURVwiLCByZXNwb25zZT8uaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEluY3JlbWVudHMgdGhlIGdpdmVuIF9rZXlfIGluIG1lbWNhY2hlLlxuICAgKi9cbiAgYXN5bmMgaW5jcmVtZW50KFxuICAgIGtleTogc3RyaW5nLFxuICAgIGFtb3VudDogbnVtYmVyLFxuICAgIG9wdGlvbnM/OiB7IGluaXRpYWw/OiBudW1iZXI7IGV4cGlyZXM/OiBudW1iZXIgfVxuICApOiBQcm9taXNlPHsgdmFsdWU6IG51bWJlciB8IG51bGw7IHN1Y2Nlc3M6IGJvb2xlYW4gfCBudWxsIH0+IHtcbiAgICAvLyBUT0RPOiBzdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBpbml0aWFsID0gb3B0aW9ucz8uaW5pdGlhbCB8fCAwO1xuICAgIGNvbnN0IGV4cGlyZXMgPSBvcHRpb25zPy5leHBpcmVzIHx8IHRoaXMub3B0aW9ucy5leHBpcmVzO1xuICAgIGNvbnN0IGV4dHJhcyA9IG1ha2VBbW91bnRJbml0aWFsQW5kRXhwaXJhdGlvbihhbW91bnQsIGluaXRpYWwsIGV4cGlyZXMpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgIGNvbnN0YW50cy5PUF9JTkNSRU1FTlQsXG4gICAgICBrZXksXG4gICAgICBleHRyYXMsXG4gICAgICBcIlwiLFxuICAgICAgdGhpcy5zZXFcbiAgICApO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICBjb25zdCBidWZJbnQgPVxuICAgICAgICAgIChyZXNwb25zZS52YWwucmVhZFVJbnQzMkJFKDApIDw8IDgpICsgcmVzcG9uc2UudmFsLnJlYWRVSW50MzJCRSg0KTtcbiAgICAgICAgcmV0dXJuIHsgdmFsdWU6IGJ1ZkludCwgc3VjY2VzczogdHJ1ZSB9O1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIklOQ1JFTUVOVFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRGVjcmVtZW50cyB0aGUgZ2l2ZW4gYGtleWAgaW4gbWVtY2FjaGUuXG4gICAqL1xuICBhc3luYyBkZWNyZW1lbnQoXG4gICAga2V5OiBzdHJpbmcsXG4gICAgYW1vdW50OiBudW1iZXIsXG4gICAgb3B0aW9uczogeyBpbml0aWFsPzogbnVtYmVyOyBleHBpcmVzPzogbnVtYmVyIH1cbiAgKTogUHJvbWlzZTx7IHZhbHVlOiBudW1iZXIgfCBudWxsOyBzdWNjZXNzOiBib29sZWFuIHwgbnVsbCB9PiB7XG4gICAgLy8gVE9ETzogc3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgaW5pdGlhbCA9IG9wdGlvbnMuaW5pdGlhbCB8fCAwO1xuICAgIGNvbnN0IGV4cGlyZXMgPSBvcHRpb25zLmV4cGlyZXMgfHwgdGhpcy5vcHRpb25zLmV4cGlyZXM7XG4gICAgY29uc3QgZXh0cmFzID0gbWFrZUFtb3VudEluaXRpYWxBbmRFeHBpcmF0aW9uKGFtb3VudCwgaW5pdGlhbCwgZXhwaXJlcyk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKFxuICAgICAgY29uc3RhbnRzLk9QX0RFQ1JFTUVOVCxcbiAgICAgIGtleSxcbiAgICAgIGV4dHJhcyxcbiAgICAgIFwiXCIsXG4gICAgICB0aGlzLnNlcVxuICAgICk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIGNvbnN0IGJ1ZkludCA9XG4gICAgICAgICAgKHJlc3BvbnNlLnZhbC5yZWFkVUludDMyQkUoMCkgPDwgOCkgKyByZXNwb25zZS52YWwucmVhZFVJbnQzMkJFKDQpO1xuICAgICAgICByZXR1cm4geyB2YWx1ZTogYnVmSW50LCBzdWNjZXNzOiB0cnVlIH07XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiREVDUkVNRU5UXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBBcHBlbmQgdGhlIGdpdmVuIF92YWx1ZV8gdG8gdGhlIHZhbHVlIGFzc29jaWF0ZWQgd2l0aCB0aGUgZ2l2ZW4gX2tleV8gaW5cbiAgICogbWVtY2FjaGUuIFRoZSBvcGVyYXRpb24gb25seSBzdWNjZWVkcyBpZiB0aGUga2V5IGlzIGFscmVhZHkgcHJlc2VudC5cbiAgICovXG4gIGFzeW5jIGFwcGVuZChrZXk6IHN0cmluZywgdmFsdWU6IFZhbHVlKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgLy8gVE9ETzogc3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3Qgb3Bjb2RlOiBjb25zdGFudHMuT1AgPSBjb25zdGFudHMuT1BfQVBQRU5EO1xuICAgIGNvbnN0IHNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuc2VyaWFsaXplKG9wY29kZSwgdmFsdWUsIFwiXCIpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgIG9wY29kZSxcbiAgICAgIGtleSxcbiAgICAgIHNlcmlhbGl6ZWQuZXh0cmFzLFxuICAgICAgc2VyaWFsaXplZC52YWx1ZSxcbiAgICAgIHRoaXMuc2VxXG4gICAgKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJBUFBFTkRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFByZXBlbmQgdGhlIGdpdmVuIF92YWx1ZV8gdG8gdGhlIHZhbHVlIGFzc29jaWF0ZWQgd2l0aCB0aGUgZ2l2ZW4gX2tleV8gaW5cbiAgICogbWVtY2FjaGUuIFRoZSBvcGVyYXRpb24gb25seSBzdWNjZWVkcyBpZiB0aGUga2V5IGlzIGFscmVhZHkgcHJlc2VudC5cbiAgICovXG4gIGFzeW5jIHByZXBlbmQoa2V5OiBzdHJpbmcsIHZhbHVlOiBWYWx1ZSk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IG9wY29kZTogY29uc3RhbnRzLk9QID0gY29uc3RhbnRzLk9QX1BSRVBFTkQ7XG4gICAgY29uc3Qgc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5zZXJpYWxpemUob3Bjb2RlLCB2YWx1ZSwgXCJcIik7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKFxuICAgICAgb3Bjb2RlLFxuICAgICAga2V5LFxuICAgICAgc2VyaWFsaXplZC5leHRyYXMsXG4gICAgICBzZXJpYWxpemVkLnZhbHVlLFxuICAgICAgdGhpcy5zZXFcbiAgICApO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuS0VZX05PVF9GT1VORDpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIlBSRVBFTkRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFRvdWNoIHNldHMgYW4gZXhwaXJhdGlvbiB2YWx1ZSwgZ2l2ZW4gYnkgX2V4cGlyZXNfLCBvbiB0aGUgZ2l2ZW4gX2tleV8gaW5cbiAgICogbWVtY2FjaGUuIFRoZSBvcGVyYXRpb24gb25seSBzdWNjZWVkcyBpZiB0aGUga2V5IGlzIGFscmVhZHkgcHJlc2VudC5cbiAgICovXG4gIGFzeW5jIHRvdWNoKGtleTogc3RyaW5nLCBleHBpcmVzOiBudW1iZXIpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAvLyBUT0RPOiBzdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBleHRyYXMgPSBtYWtlRXhwaXJhdGlvbihleHBpcmVzIHx8IHRoaXMub3B0aW9ucy5leHBpcmVzKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoMHgxYywga2V5LCBleHRyYXMsIFwiXCIsIHRoaXMuc2VxKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJUT1VDSFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRkxVU0hcbiAgICpcbiAgICogRmx1c2hlcyB0aGUgY2FjaGUgb24gZWFjaCBjb25uZWN0ZWQgc2VydmVyLiBUaGUgY2FsbGJhY2sgc2lnbmF0dXJlIGlzOlxuICAgKlxuICAgKiAgICAgY2FsbGJhY2sobGFzdEVyciwgcmVzdWx0cylcbiAgICpcbiAgICogd2hlcmUgX2xhc3RFcnJfIGlzIHRoZSBsYXN0IGVycm9yIGVuY291bnRlcmVkIChvciBudWxsLCBpbiB0aGUgY29tbW9uIGNhc2VcbiAgICogb2Ygbm8gZXJyb3JzKS4gX3Jlc3VsdHNfIGlzIGEgZGljdGlvbmFyeSBtYXBwaW5nIGBcImhvc3RuYW1lOnBvcnRcImAgdG8gZWl0aGVyXG4gICAqIGB0cnVlYCAoaWYgdGhlIG9wZXJhdGlvbiB3YXMgc3VjY2Vzc2Z1bCksIG9yIGFuIGVycm9yLlxuICAgKiBAcGFyYW0gY2FsbGJhY2tcbiAgICovXG4gIGZsdXNoKCk6IFByb21pc2U8UmVjb3JkPHN0cmluZywgYm9vbGVhbiB8IEVycm9yPj47XG4gIGZsdXNoKFxuICAgIGNhbGxiYWNrOiAoXG4gICAgICBlcnI6IEVycm9yIHwgbnVsbCxcbiAgICAgIHJlc3VsdHM6IFJlY29yZDxzdHJpbmcsIGJvb2xlYW4gfCBFcnJvcj5cbiAgICApID0+IHZvaWRcbiAgKTogdm9pZDtcbiAgZmx1c2goXG4gICAgY2FsbGJhY2s/OiAoXG4gICAgICBlcnI6IEVycm9yIHwgbnVsbCxcbiAgICAgIHJlc3VsdHM6IFJlY29yZDxzdHJpbmcsIGJvb2xlYW4gfCBFcnJvcj5cbiAgICApID0+IHZvaWRcbiAgKSB7XG4gICAgaWYgKGNhbGxiYWNrID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybiBwcm9taXNpZnkoKGNhbGxiYWNrKSA9PiB7XG4gICAgICAgIHRoaXMuZmx1c2goZnVuY3Rpb24gKGVyciwgcmVzdWx0cykge1xuICAgICAgICAgIGNhbGxiYWNrKGVyciwgcmVzdWx0cyk7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfVxuICAgIC8vIFRPRE86IHN1cHBvcnQgZXhwaXJhdGlvblxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcigweDA4LCBcIlwiLCBcIlwiLCBcIlwiLCB0aGlzLnNlcSk7XG4gICAgbGV0IGNvdW50ID0gdGhpcy5zZXJ2ZXJzLmxlbmd0aDtcbiAgICBjb25zdCByZXN1bHQ6IFJlY29yZDxzdHJpbmcsIGJvb2xlYW4gfCBFcnJvcj4gPSB7fTtcbiAgICBsZXQgbGFzdEVycjogRXJyb3IgfCBudWxsID0gbnVsbDtcblxuICAgIGNvbnN0IGhhbmRsZUZsdXNoID0gZnVuY3Rpb24gKHNlcTogbnVtYmVyLCBzZXJ2OiBTZXJ2ZXIpIHtcbiAgICAgIHNlcnYub25SZXNwb25zZShzZXEsIGZ1bmN0aW9uICgvKiByZXNwb25zZSAqLykge1xuICAgICAgICBjb3VudCAtPSAxO1xuICAgICAgICByZXN1bHRbc2Vydi5ob3N0cG9ydFN0cmluZygpXSA9IHRydWU7XG4gICAgICAgIGlmIChjYWxsYmFjayAmJiBjb3VudCA9PT0gMCkge1xuICAgICAgICAgIGNhbGxiYWNrKGxhc3RFcnIsIHJlc3VsdCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgc2Vydi5vbkVycm9yKHNlcSwgZnVuY3Rpb24gKGVycikge1xuICAgICAgICBjb3VudCAtPSAxO1xuICAgICAgICBsYXN0RXJyID0gZXJyO1xuICAgICAgICByZXN1bHRbc2Vydi5ob3N0cG9ydFN0cmluZygpXSA9IGVycjtcbiAgICAgICAgaWYgKGNhbGxiYWNrICYmIGNvdW50ID09PSAwKSB7XG4gICAgICAgICAgY2FsbGJhY2sobGFzdEVyciwgcmVzdWx0KTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICBzZXJ2LndyaXRlKHJlcXVlc3QpO1xuICAgIH07XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuc2VydmVycy5sZW5ndGg7IGkrKykge1xuICAgICAgaGFuZGxlRmx1c2godGhpcy5zZXEsIHRoaXMuc2VydmVyc1tpXSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNUQVRTX1dJVEhfS0VZXG4gICAqXG4gICAqIFNlbmRzIGEgbWVtY2FjaGUgc3RhdHMgY29tbWFuZCB3aXRoIGEga2V5IHRvIGVhY2ggY29ubmVjdGVkIHNlcnZlci4gVGhlXG4gICAqIGNhbGxiYWNrIGlzIGludm9rZWQgKipPTkNFIFBFUiBTRVJWRVIqKiBhbmQgaGFzIHRoZSBzaWduYXR1cmU6XG4gICAqXG4gICAqICAgICBjYWxsYmFjayhlcnIsIHNlcnZlciwgc3RhdHMpXG4gICAqXG4gICAqIF9zZXJ2ZXJfIGlzIHRoZSBgXCJob3N0bmFtZTpwb3J0XCJgIG9mIHRoZSBzZXJ2ZXIsIGFuZCBfc3RhdHNfIGlzIGEgZGljdGlvbmFyeVxuICAgKiBtYXBwaW5nIHRoZSBzdGF0IG5hbWUgdG8gdGhlIHZhbHVlIG9mIHRoZSBzdGF0aXN0aWMgYXMgYSBzdHJpbmcuXG4gICAqIEBwYXJhbSBrZXlcbiAgICogQHBhcmFtIGNhbGxiYWNrXG4gICAqL1xuICBzdGF0c1dpdGhLZXkoXG4gICAga2V5OiBzdHJpbmcsXG4gICAgY2FsbGJhY2s/OiAoXG4gICAgICBlcnI6IEVycm9yIHwgbnVsbCxcbiAgICAgIHNlcnZlcjogc3RyaW5nLFxuICAgICAgc3RhdHM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gfCBudWxsXG4gICAgKSA9PiB2b2lkXG4gICk6IHZvaWQge1xuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcigweDEwLCBrZXksIFwiXCIsIFwiXCIsIHRoaXMuc2VxKTtcblxuICAgIGNvbnN0IGhhbmRsZVN0YXRzID0gKHNlcTogbnVtYmVyLCBzZXJ2OiBTZXJ2ZXIpID0+IHtcbiAgICAgIGNvbnN0IHJlc3VsdDogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHt9O1xuICAgICAgY29uc3QgaGFuZGxlOiBPblJlc3BvbnNlQ2FsbGJhY2sgPSAocmVzcG9uc2UpID0+IHtcbiAgICAgICAgLy8gZW5kIG9mIHN0YXQgcmVzcG9uc2VzXG4gICAgICAgIGlmIChyZXNwb25zZS5oZWFkZXIudG90YWxCb2R5TGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgICAgICBjYWxsYmFjayhudWxsLCBzZXJ2Lmhvc3Rwb3J0U3RyaW5nKCksIHJlc3VsdCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICAvLyBwcm9jZXNzIHNpbmdsZSBzdGF0IGxpbmUgcmVzcG9uc2VcbiAgICAgICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICAgICAgcmVzdWx0W3Jlc3BvbnNlLmtleS50b1N0cmluZygpXSA9IHJlc3BvbnNlLnZhbC50b1N0cmluZygpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIGNvbnN0IGVycm9yID0gdGhpcy5oYW5kbGVSZXNwb25zZUVycm9yKFxuICAgICAgICAgICAgICBgU1RBVFMgKCR7a2V5fSlgLFxuICAgICAgICAgICAgICByZXNwb25zZS5oZWFkZXIuc3RhdHVzLFxuICAgICAgICAgICAgICB1bmRlZmluZWRcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgY2FsbGJhY2soZXJyb3IsIHNlcnYuaG9zdHBvcnRTdHJpbmcoKSwgbnVsbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH07XG4gICAgICBoYW5kbGUucXVpZXQgPSB0cnVlO1xuXG4gICAgICBzZXJ2Lm9uUmVzcG9uc2Uoc2VxLCBoYW5kbGUpO1xuICAgICAgc2Vydi5vbkVycm9yKHNlcSwgZnVuY3Rpb24gKGVycikge1xuICAgICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgICBjYWxsYmFjayhlcnIsIHNlcnYuaG9zdHBvcnRTdHJpbmcoKSwgbnVsbCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgc2Vydi53cml0ZShyZXF1ZXN0KTtcbiAgICB9O1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnNlcnZlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGhhbmRsZVN0YXRzKHRoaXMuc2VxLCB0aGlzLnNlcnZlcnNbaV0pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTVEFUU1xuICAgKlxuICAgKiBGZXRjaGVzIG1lbWNhY2hlIHN0YXRzIGZyb20gZWFjaCBjb25uZWN0ZWQgc2VydmVyLiBUaGUgY2FsbGJhY2sgaXMgaW52b2tlZFxuICAgKiAqKk9OQ0UgUEVSIFNFUlZFUioqIGFuZCBoYXMgdGhlIHNpZ25hdHVyZTpcbiAgICpcbiAgICogICAgIGNhbGxiYWNrKGVyciwgc2VydmVyLCBzdGF0cylcbiAgICpcbiAgICogX3NlcnZlcl8gaXMgdGhlIGBcImhvc3RuYW1lOnBvcnRcImAgb2YgdGhlIHNlcnZlciwgYW5kIF9zdGF0c18gaXMgYVxuICAgKiBkaWN0aW9uYXJ5IG1hcHBpbmcgdGhlIHN0YXQgbmFtZSB0byB0aGUgdmFsdWUgb2YgdGhlIHN0YXRpc3RpYyBhcyBhIHN0cmluZy5cbiAgICogQHBhcmFtIGNhbGxiYWNrXG4gICAqL1xuICBzdGF0cyhcbiAgICBjYWxsYmFjaz86IChcbiAgICAgIGVycjogRXJyb3IgfCBudWxsLFxuICAgICAgc2VydmVyOiBzdHJpbmcsXG4gICAgICBzdGF0czogUmVjb3JkPHN0cmluZywgc3RyaW5nPiB8IG51bGxcbiAgICApID0+IHZvaWRcbiAgKTogdm9pZCB7XG4gICAgdGhpcy5zdGF0c1dpdGhLZXkoXCJcIiwgY2FsbGJhY2spO1xuICB9XG5cbiAgLyoqXG4gICAqIFJFU0VUX1NUQVRTXG4gICAqXG4gICAqIFJlc2V0IHRoZSBzdGF0aXN0aWNzIGVhY2ggc2VydmVyIGlzIGtlZXBpbmcgYmFjayB0byB6ZXJvLiBUaGlzIGRvZXNuJ3QgY2xlYXJcbiAgICogc3RhdHMgc3VjaCBhcyBpdGVtIGNvdW50LCBidXQgdGVtcG9yYXJ5IHN0YXRzIHN1Y2ggYXMgdG90YWwgbnVtYmVyIG9mXG4gICAqIGNvbm5lY3Rpb25zIG92ZXIgdGltZS5cbiAgICpcbiAgICogVGhlIGNhbGxiYWNrIGlzIGludm9rZWQgKipPTkNFIFBFUiBTRVJWRVIqKiBhbmQgaGFzIHRoZSBzaWduYXR1cmU6XG4gICAqXG4gICAqICAgICBjYWxsYmFjayhlcnIsIHNlcnZlcilcbiAgICpcbiAgICogX3NlcnZlcl8gaXMgdGhlIGBcImhvc3RuYW1lOnBvcnRcImAgb2YgdGhlIHNlcnZlci5cbiAgICogQHBhcmFtIGNhbGxiYWNrXG4gICAqL1xuICByZXNldFN0YXRzKFxuICAgIGNhbGxiYWNrPzogKFxuICAgICAgZXJyOiBFcnJvciB8IG51bGwsXG4gICAgICBzZXJ2ZXI6IHN0cmluZyxcbiAgICAgIHN0YXRzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+IHwgbnVsbFxuICAgICkgPT4gdm9pZFxuICApOiB2b2lkIHtcbiAgICB0aGlzLnN0YXRzV2l0aEtleShcInJlc2V0XCIsIGNhbGxiYWNrKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBRVUlUXG4gICAqXG4gICAqIENsb3NlcyB0aGUgY29ubmVjdGlvbiB0byBlYWNoIHNlcnZlciwgbm90aWZ5aW5nIHRoZW0gb2YgdGhpcyBpbnRlbnRpb24uIE5vdGVcbiAgICogdGhhdCBxdWl0IGNhbiByYWNlIGFnYWluc3QgYWxyZWFkeSBvdXRzdGFuZGluZyByZXF1ZXN0cyB3aGVuIHRob3NlIHJlcXVlc3RzXG4gICAqIGZhaWwgYW5kIGFyZSByZXRyaWVkLCBsZWFkaW5nIHRvIHRoZSBxdWl0IGNvbW1hbmQgd2lubmluZyBhbmQgY2xvc2luZyB0aGVcbiAgICogY29ubmVjdGlvbiBiZWZvcmUgdGhlIHJldHJpZXMgY29tcGxldGUuXG4gICAqL1xuICBxdWl0KCkge1xuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIC8vIFRPRE86IE5pY2VyIHBlcmhhcHMgdG8gZG8gUVVJVFEgKDB4MTcpIGJ1dCBuZWVkIGEgbmV3IGNhbGxiYWNrIGZvciB3aGVuXG4gICAgLy8gd3JpdGUgaXMgZG9uZS5cbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoMHgwNywgXCJcIiwgXCJcIiwgXCJcIiwgdGhpcy5zZXEpOyAvLyBRVUlUXG4gICAgbGV0IHNlcnY7XG5cbiAgICBjb25zdCBoYW5kbGVRdWl0ID0gZnVuY3Rpb24gKHNlcTogbnVtYmVyLCBzZXJ2OiBTZXJ2ZXIpIHtcbiAgICAgIHNlcnYub25SZXNwb25zZShzZXEsIGZ1bmN0aW9uICgvKiByZXNwb25zZSAqLykge1xuICAgICAgICBzZXJ2LmNsb3NlKCk7XG4gICAgICB9KTtcbiAgICAgIHNlcnYub25FcnJvcihzZXEsIGZ1bmN0aW9uICgvKiBlcnIgKi8pIHtcbiAgICAgICAgc2Vydi5jbG9zZSgpO1xuICAgICAgfSk7XG4gICAgICBzZXJ2LndyaXRlKHJlcXVlc3QpO1xuICAgIH07XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuc2VydmVycy5sZW5ndGg7IGkrKykge1xuICAgICAgc2VydiA9IHRoaXMuc2VydmVyc1tpXTtcbiAgICAgIGhhbmRsZVF1aXQodGhpcy5zZXEsIHNlcnYpO1xuICAgIH1cbiAgfVxuXG4gIF92ZXJzaW9uKHNlcnZlcjogU2VydmVyKTogUHJvbWlzZTx7IHZhbHVlOiBWYWx1ZSB8IG51bGwgfT4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICB0aGlzLmluY3JTZXEoKTtcbiAgICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgICAgY29uc3RhbnRzLk9QX1ZFUlNJT04sXG4gICAgICAgIFwiXCIsXG4gICAgICAgIFwiXCIsXG4gICAgICAgIFwiXCIsXG4gICAgICAgIHRoaXMuc2VxXG4gICAgICApO1xuICAgICAgdGhpcy5wZXJmb3JtT25TZXJ2ZXIoc2VydmVyLCByZXF1ZXN0LCB0aGlzLnNlcSwgKGVyciwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgIHJldHVybiByZWplY3QoZXJyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHN3aXRjaCAocmVzcG9uc2UhLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgICAgICAvKiBUT0RPOiB0aGlzIGlzIGJ1Z2dlZCwgd2Ugc2hvdWxkJ3QgdXNlIHRoZSBkZXNlcmlhbGl6ZXIgaGVyZSwgc2luY2UgdmVyc2lvbiBhbHdheXMgcmV0dXJucyBhIHZlcnNpb24gc3RyaW5nLlxuICAgICAgICAgICAgIFRoZSBkZXNlcmlhbGl6ZXIgc2hvdWxkIG9ubHkgYmUgdXNlZCBvbiB1c2VyIGtleSBkYXRhLiAqL1xuICAgICAgICAgICAgY29uc3QgZGVzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLmRlc2VyaWFsaXplKFxuICAgICAgICAgICAgICByZXNwb25zZSEuaGVhZGVyLm9wY29kZSxcbiAgICAgICAgICAgICAgcmVzcG9uc2UhLnZhbCxcbiAgICAgICAgICAgICAgcmVzcG9uc2UhLmV4dHJhc1xuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHJldHVybiByZXNvbHZlKHsgdmFsdWU6IGRlc2VyaWFsaXplZC52YWx1ZSB9KTtcbiAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgcmV0dXJuIHJlamVjdChcbiAgICAgICAgICAgICAgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIlZFUlNJT05cIiwgcmVzcG9uc2UhLmhlYWRlci5zdGF0dXMpXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXF1ZXN0IHRoZSBzZXJ2ZXIgdmVyc2lvbiBmcm9tIHRoZSBcImZpcnN0XCIgc2VydmVyIGluIHRoZSBiYWNrZW5kIHBvb2wuXG4gICAqIFRoZSBzZXJ2ZXIgcmVzcG9uZHMgd2l0aCBhIHBhY2tldCBjb250YWluaW5nIHRoZSB2ZXJzaW9uIHN0cmluZyBpbiB0aGUgYm9keSB3aXRoIHRoZSBmb2xsb3dpbmcgZm9ybWF0OiBcIngueS56XCJcbiAgICovXG4gIHZlcnNpb24oKTogUHJvbWlzZTx7IHZhbHVlOiBWYWx1ZSB8IG51bGwgfT4ge1xuICAgIGNvbnN0IHNlcnZlciA9IHRoaXMuc2VydmVyS2V5VG9TZXJ2ZXIodGhpcy5zZXJ2ZXJLZXlzWzBdKTtcbiAgICByZXR1cm4gdGhpcy5fdmVyc2lvbihzZXJ2ZXIpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHJpZXZlcyB0aGUgc2VydmVyIHZlcnNpb24gZnJvbSBhbGwgdGhlIHNlcnZlcnNcbiAgICogaW4gdGhlIGJhY2tlbmQgcG9vbCwgZXJyb3JzIGlmIGFueSBvbmUgb2YgdGhlbSBoYXMgYW5cbiAgICogZXJyb3JcbiAgICogXG4gICAqIENhbGxiYWNrcyBmdW5jdGlvbnMgYXJlIGNhbGxlZCBiZWZvcmUvYWZ0ZXIgd2UgcGluZyBtZW1jYWNoZWRcbiAgICogYW5kIHVzZWQgdG8gbG9nIHdoaWNoIGhvc3RzIGFyZSB0aW1pbmcgb3V0LlxuICAgKi9cbiAgYXN5bmMgdmVyc2lvbkFsbChjYWxsYmFja3M/OiB7XG4gICAgYmVmb3JlUGluZz86IChzZXJ2ZXJLZXk6IHN0cmluZykgPT4gdm9pZDtcbiAgICBhZnRlclBpbmc/OiAoc2VydmVyS2V5OiBzdHJpbmcpID0+IHZvaWQ7XG4gIH0pOiBQcm9taXNlPHtcbiAgICB2YWx1ZXM6IFJlY29yZDxzdHJpbmcsIFZhbHVlIHwgbnVsbD47XG4gIH0+IHtcbiAgICBjb25zdCB2ZXJzaW9uT2JqZWN0cyA9IGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgdGhpcy5zZXJ2ZXJLZXlzLm1hcCgoc2VydmVyS2V5KSA9PiB7XG4gICAgICAgIGNvbnN0IHNlcnZlciA9IHRoaXMuc2VydmVyS2V5VG9TZXJ2ZXIoc2VydmVyS2V5KTtcbiAgICAgICAgY2FsbGJhY2tzPy5iZWZvcmVQaW5nPy4oc2VydmVyS2V5KTtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3ZlcnNpb24oc2VydmVyKS50aGVuKChyZXNwb25zZSkgPT4ge1xuICAgICAgICAgIGNhbGxiYWNrcz8uYWZ0ZXJQaW5nPy4oc2VydmVyS2V5KTtcbiAgICAgICAgICByZXR1cm4geyBzZXJ2ZXJLZXk6IHNlcnZlcktleSwgdmFsdWU6IHJlc3BvbnNlLnZhbHVlIH07XG4gICAgICAgIH0pO1xuICAgICAgfSlcbiAgICApO1xuICAgIGNvbnN0IHZhbHVlcyA9IHZlcnNpb25PYmplY3RzLnJlZHVjZSgoYWNjdW11bGF0b3IsIHZlcnNpb25PYmplY3QpID0+IHtcbiAgICAgIGFjY3VtdWxhdG9yW3ZlcnNpb25PYmplY3Quc2VydmVyS2V5XSA9IHZlcnNpb25PYmplY3QudmFsdWU7XG4gICAgICByZXR1cm4gYWNjdW11bGF0b3I7XG4gICAgfSwge30gYXMgUmVjb3JkPHN0cmluZywgVmFsdWUgfCBudWxsPik7XG4gICAgcmV0dXJuIHsgdmFsdWVzOiB2YWx1ZXMgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDbG9zZXMgKGFicnVwdGx5KSBjb25uZWN0aW9ucyB0byBhbGwgdGhlIHNlcnZlcnMuXG4gICAqIEBzZWUgdGhpcy5xdWl0XG4gICAqL1xuICBjbG9zZSgpIHtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuc2VydmVycy5sZW5ndGg7IGkrKykge1xuICAgICAgdGhpcy5zZXJ2ZXJzW2ldLmNsb3NlKCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFBlcmZvcm0gYSBnZW5lcmljIHNpbmdsZSByZXNwb25zZSBvcGVyYXRpb24gKGdldCwgc2V0IGV0Yykgb24gb25lIHNlcnZlclxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IHRoZSBrZXkgdG8gaGFzaCB0byBnZXQgYSBzZXJ2ZXIgZnJvbSB0aGUgcG9vbFxuICAgKiBAcGFyYW0ge2J1ZmZlcn0gcmVxdWVzdCBhIGJ1ZmZlciBjb250YWluaW5nIHRoZSByZXF1ZXN0XG4gICAqIEBwYXJhbSB7bnVtYmVyfSBzZXEgdGhlIHNlcXVlbmNlIG51bWJlciBvZiB0aGUgb3BlcmF0aW9uLiBJdCBpcyB1c2VkIHRvIHBpbiB0aGUgY2FsbGJhY2tzXG4gICAgICAgICAgICAgICAgICAgICAgICAgdG8gYSBzcGVjaWZpYyBvcGVyYXRpb24gYW5kIHNob3VsZCBuZXZlciBjaGFuZ2UgZHVyaW5nIGEgYHBlcmZvcm1gLlxuICAgKiBAcGFyYW0ge251bWJlcj99IHJldHJpZXMgbnVtYmVyIG9mIHRpbWVzIHRvIHJldHJ5IHJlcXVlc3Qgb24gZmFpbHVyZVxuICAgKi9cbiAgcGVyZm9ybShcbiAgICBrZXk6IHN0cmluZyxcbiAgICByZXF1ZXN0OiBCdWZmZXIsXG4gICAgc2VxOiBudW1iZXIsXG4gICAgcmV0cmllcz86IG51bWJlclxuICApOiBQcm9taXNlPE1lc3NhZ2U+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgY29uc3Qgc2VydmVyS2V5ID0gdGhpcy5sb29rdXBLZXlUb1NlcnZlcktleShrZXkpO1xuICAgICAgY29uc3Qgc2VydmVyID0gdGhpcy5zZXJ2ZXJLZXlUb1NlcnZlcihzZXJ2ZXJLZXkpO1xuXG4gICAgICBpZiAoIXNlcnZlcikge1xuICAgICAgICByZXR1cm4gcmVqZWN0KG5ldyBFcnJvcihcIk5vIHNlcnZlcnMgYXZhaWxhYmxlXCIpKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5wZXJmb3JtT25TZXJ2ZXIoXG4gICAgICAgIHNlcnZlcixcbiAgICAgICAgcmVxdWVzdCxcbiAgICAgICAgc2VxLFxuICAgICAgICAoZXJyb3IsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICByZXR1cm4gcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmVzb2x2ZShyZXNwb25zZSEpO1xuICAgICAgICB9LFxuICAgICAgICByZXRyaWVzXG4gICAgICApO1xuICAgIH0pO1xuICB9XG5cbiAgcGVyZm9ybU9uU2VydmVyKFxuICAgIHNlcnZlcjogU2VydmVyLFxuICAgIHJlcXVlc3Q6IEJ1ZmZlcixcbiAgICBzZXE6IG51bWJlcixcbiAgICBjYWxsYmFjazogUmVzcG9uc2VPckVycm9yQ2FsbGJhY2ssXG4gICAgcmV0cmllczogbnVtYmVyID0gMFxuICApIHtcbiAgICBjb25zdCBfdGhpcyA9IHRoaXM7XG5cbiAgICByZXRyaWVzID0gcmV0cmllcyB8fCB0aGlzLm9wdGlvbnMucmV0cmllcztcbiAgICBjb25zdCBvcmlnUmV0cmllcyA9IHRoaXMub3B0aW9ucy5yZXRyaWVzO1xuICAgIGNvbnN0IGxvZ2dlciA9IHRoaXMub3B0aW9ucy5sb2dnZXI7XG4gICAgY29uc3QgcmV0cnlfZGVsYXkgPSB0aGlzLm9wdGlvbnMucmV0cnlfZGVsYXk7XG5cbiAgICBjb25zdCByZXNwb25zZUhhbmRsZXI6IE9uUmVzcG9uc2VDYWxsYmFjayA9IGZ1bmN0aW9uIChyZXNwb25zZSkge1xuICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgIGNhbGxiYWNrKG51bGwsIHJlc3BvbnNlKTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgY29uc3QgZXJyb3JIYW5kbGVyOiBPbkVycm9yQ2FsbGJhY2sgPSBmdW5jdGlvbiAoZXJyb3IpIHtcbiAgICAgIGlmICgtLXJldHJpZXMgPiAwKSB7XG4gICAgICAgIC8vIFdhaXQgZm9yIHJldHJ5X2RlbGF5XG4gICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgIF90aGlzLnBlcmZvcm1PblNlcnZlcihzZXJ2ZXIsIHJlcXVlc3QsIHNlcSwgY2FsbGJhY2ssIHJldHJpZXMpO1xuICAgICAgICB9LCAxMDAwICogcmV0cnlfZGVsYXkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbG9nZ2VyLmxvZyhcbiAgICAgICAgICBcIk1lbUpTOiBTZXJ2ZXIgPFwiICtcbiAgICAgICAgICAgIHNlcnZlci5ob3N0cG9ydFN0cmluZygpICtcbiAgICAgICAgICAgIFwiPiBmYWlsZWQgYWZ0ZXIgKFwiICtcbiAgICAgICAgICAgIG9yaWdSZXRyaWVzICtcbiAgICAgICAgICAgIFwiKSByZXRyaWVzIHdpdGggZXJyb3IgLSBcIiArXG4gICAgICAgICAgICBlcnJvci5tZXNzYWdlXG4gICAgICAgICk7XG4gICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgIGNhbGxiYWNrKGVycm9yLCBudWxsKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH07XG5cbiAgICBzZXJ2ZXIub25SZXNwb25zZShzZXEsIHJlc3BvbnNlSGFuZGxlcik7XG4gICAgc2VydmVyLm9uRXJyb3Ioc2VxLCBlcnJvckhhbmRsZXIpO1xuICAgIHNlcnZlci53cml0ZShyZXF1ZXN0KTtcbiAgfVxuXG4gIC8vIEluY3JlbWVudCB0aGUgc2VxIHZhbHVlXG4gIGluY3JTZXEoKSB7XG4gICAgdGhpcy5zZXErKztcblxuICAgIC8vIFdyYXAgYHRoaXMuc2VxYCB0byAzMi1iaXRzIHNpbmNlIHRoZSBmaWVsZCB3ZSBmaXQgaXQgaW50byBpcyBvbmx5IDMyLWJpdHMuXG4gICAgdGhpcy5zZXEgJj0gMHhmZmZmZmZmZjtcblxuICAgIHJldHVybiB0aGlzLnNlcTtcbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlQW5kTG9nRXJyb3IoXG4gICAgY29tbWFuZE5hbWU6IHN0cmluZyxcbiAgICByZXNwb25zZVN0YXR1czogUmVzcG9uc2VTdGF0dXMgfCB1bmRlZmluZWRcbiAgKTogRXJyb3Ige1xuICAgIGNvbnN0IGVycm9yTWVzc2FnZSA9IGBNZW1KUyAke2NvbW1hbmROYW1lfTogJHtjb25zdGFudHMucmVzcG9uc2VTdGF0dXNUb1N0cmluZyhcbiAgICAgIHJlc3BvbnNlU3RhdHVzXG4gICAgKX1gO1xuICAgIHRoaXMub3B0aW9ucy5sb2dnZXIubG9nKGVycm9yTWVzc2FnZSk7XG4gICAgcmV0dXJuIG5ldyBFcnJvcihlcnJvck1lc3NhZ2UpO1xuICB9XG5cbiAgLyoqXG4gICAqIExvZyBhbiBlcnJvciB0byB0aGUgbG9nZ2VyLCB0aGVuIHJldHVybiB0aGUgZXJyb3IuXG4gICAqIElmIGEgY2FsbGJhY2sgaXMgZ2l2ZW4sIGNhbGwgaXQgd2l0aCBjYWxsYmFjayhlcnJvciwgbnVsbCkuXG4gICAqL1xuICBwcml2YXRlIGhhbmRsZVJlc3BvbnNlRXJyb3IoXG4gICAgY29tbWFuZE5hbWU6IHN0cmluZyxcbiAgICByZXNwb25zZVN0YXR1czogUmVzcG9uc2VTdGF0dXMgfCB1bmRlZmluZWQsXG4gICAgY2FsbGJhY2s6IHVuZGVmaW5lZCB8ICgoZXJyb3I6IEVycm9yIHwgbnVsbCwgb3RoZXI6IG51bGwpID0+IHZvaWQpXG4gICk6IEVycm9yIHtcbiAgICBjb25zdCBlcnJvciA9IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoY29tbWFuZE5hbWUsIHJlc3BvbnNlU3RhdHVzKTtcbiAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgIGNhbGxiYWNrKGVycm9yLCBudWxsKTtcbiAgICB9XG4gICAgcmV0dXJuIGVycm9yO1xuICB9XG59XG5cbmV4cG9ydCB7IENsaWVudCwgU2VydmVyLCBVdGlscywgSGVhZGVyIH07XG4iXX0= \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVtanMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbWVtanMvbWVtanMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLHdCQUF3Qjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUV4QixxQ0FLa0I7QUFtb0NELHVGQXJvQ2YsZUFBTSxPQXFvQ2U7QUFsb0N2Qix1REFBK0Q7QUFDL0QsbUNBU2lCO0FBQ2pCLHVEQUF5QztBQUN6QywyQ0FBNkM7QUFDN0MsK0NBQWlDO0FBcW5DUixzQkFBSztBQXBuQzlCLGlEQUFtQztBQW9uQ0gsd0JBQU07QUFsbkN0QyxTQUFTLDhCQUE4QixDQUNyQyxPQUFpQixFQUNqQixHQUFXO0lBRVgsTUFBTSxLQUFLLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQztJQUM3QixNQUFNLEtBQUssR0FBRyxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxnQkFBUSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3BELE9BQU8sT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ3hCLENBQUM7QUFFRCwrQ0FBK0M7QUFDL0MsU0FBUyxTQUFTLENBQ2hCLE9BQTBFO0lBRTFFLE9BQU8sSUFBSSxPQUFPLENBQUMsVUFBVSxPQUFPLEVBQUUsTUFBTTtRQUMxQyxPQUFPLENBQUMsVUFBVSxHQUFHLEVBQUUsTUFBTTtZQUMzQixHQUFHLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3RDLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBd0VELE1BQU0sTUFBTTtJQVFWLDRFQUE0RTtJQUM1RSxtQ0FBbUM7SUFDbkMsWUFBWSxPQUFpQixFQUFFLE9BQTBDO1FBQ3ZFLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO1FBQ3ZCLElB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SUFFRCwwQkFBMEI7SUFDMUIsT0FBTztRQUNMLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztRQUVYLDZFQUE2RTtRQUM3RSxJQUFJLENBQUMsR0FBRyxJQUFJLFVBQVUsQ0FBQztRQUV2QixPQUFPLElBQUksQ0FBQyxHQUFHLENBQUM7SUFDbEIsQ0FBQztJQUVPLGlCQUFpQixDQUN2QixXQUFtQixFQUNuQixjQUEwQztRQUUxQyxNQUFNLFlBQVksR0FBRyxTQUFTLFdBQVcsS0FBSyxTQUFTLENBQUMsc0JBQXNCLENBQzVFLGNBQWMsQ0FDZixFQUFFLENBQUM7UUFDSixJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDdEMsT0FBTyxJQUFJLEtBQUssQ0FBQyxZQUFZLENBQUMsQ0FBQztJQUNqQyxDQUFDO0lBRUQ7OztPQUdHO0lBQ0ssbUJBQW1CLENBQ3pCLFdBQW1CLEVBQ25CLGNBQTBDLEVBQzFDLFFBQWtFO1FBRWxFLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxXQUFXLEVBQUUsY0FBYyxDQUFDLENBQUM7UUFDbEUsSUFBSSxRQUFRLEVBQUU7WUFDWixRQUFRLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxDQUFDO1NBQ3ZCO1FBQ0QsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0NBQ0Y7QUFFUSx3QkFBTSIsInNvdXJjZXNDb250ZW50IjpbIi8vIE1lbVRTIE1lbWNhY2hlIENsaWVudFxuXG5pbXBvcnQge1xuICBPbkVycm9yQ2FsbGJhY2ssXG4gIE9uUmVzcG9uc2VDYWxsYmFjayxcbiAgU2VydmVyLFxuICBTZXJ2ZXJPcHRpb25zLFxufSBmcm9tIFwiLi9zZXJ2ZXJcIjtcbmltcG9ydCB7IG5vb3BTZXJpYWxpemVyLCBTZXJpYWxpemVyIH0gZnJvbSBcIi4vbm9vcC1zZXJpYWxpemVyXCI7XG5pbXBvcnQge1xuICBtYWtlUmVxdWVzdEJ1ZmZlcixcbiAgY29weUludG9SZXF1ZXN0QnVmZmVyLFxuICBtZXJnZSxcbiAgbWFrZUV4cGlyYXRpb24sXG4gIG1ha2VBbW91bnRJbml0aWFsQW5kRXhwaXJhdGlvbixcbiAgaGFzaENvZGUsXG4gIE1heWJlQnVmZmVyLFxuICBNZXNzYWdlLFxufSBmcm9tIFwiLi91dGlsc1wiO1xuaW1wb3J0ICogYXMgY29uc3RhbnRzIGZyb20gXCIuL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgUmVzcG9uc2VTdGF0dXMgfSBmcm9tIFwiLi9jb25zdGFudHNcIjtcbmltcG9ydCAqIGFzIFV0aWxzIGZyb20gXCIuL3V0aWxzXCI7XG5pbXBvcnQgKiBhcyBIZWFkZXIgZnJvbSBcIi4vaGVhZGVyXCI7XG5cbmZ1bmN0aW9uIGRlZmF1bHRLZXlUb1NlcnZlckhhc2hGdW5jdGlvbihcbiAgc2VydmVyczogc3RyaW5nW10sXG4gIGtleTogc3RyaW5nXG4pOiBzdHJpbmcge1xuICBjb25zdCB0b3RhbCA9IHNlcnZlcnMubGVuZ3RoO1xuICBjb25zdCBpbmRleCA9IHRvdGFsID4gMSA/IGhhc2hDb2RlKGtleSkgJSB0b3RhbCA6IDA7XG4gIHJldHVybiBzZXJ2ZXJzW2luZGV4XTtcbn1cblxuLy8gY29udmVydHMgYSBjYWxsIGludG8gYSBwcm9taXNlLXJldHVybmluZyBvbmVcbmZ1bmN0aW9uIHByb21pc2lmeTxSZXN1bHQ+KFxuICBjb21tYW5kOiAoY2FsbGJhY2s6IChlcnJvcjogRXJyb3IgfCBudWxsLCByZXN1bHQ6IFJlc3VsdCkgPT4gdm9pZCkgPT4gdm9pZFxuKTogUHJvbWlzZTxSZXN1bHQ+IHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICBjb21tYW5kKGZ1bmN0aW9uIChlcnIsIHJlc3VsdCkge1xuICAgICAgZXJyID8gcmVqZWN0KGVycikgOiByZXNvbHZlKHJlc3VsdCk7XG4gICAgfSk7XG4gIH0pO1xufVxuXG50eXBlIFJlc3BvbnNlT3JFcnJvckNhbGxiYWNrID0gKFxuICBlcnJvcjogRXJyb3IgfCBudWxsLFxuICByZXNwb25zZTogTWVzc2FnZSB8IG51bGxcbikgPT4gdm9pZDtcblxuaW50ZXJmYWNlIEJhc2VDbGllbnRPcHRpb25zIHtcbiAgcmV0cmllczogbnVtYmVyO1xuICByZXRyeV9kZWxheTogbnVtYmVyO1xuICBleHBpcmVzOiBudW1iZXI7XG4gIGxvZ2dlcjogeyBsb2c6IHR5cGVvZiBjb25zb2xlLmxvZyB9O1xuICBrZXlUb1NlcnZlckhhc2hGdW5jdGlvbjogdHlwZW9mIGRlZmF1bHRLZXlUb1NlcnZlckhhc2hGdW5jdGlvbjtcbn1cblxuaW50ZXJmYWNlIFNlcmlhbGl6ZXJQcm9wPFZhbHVlLCBFeHRyYXM+IHtcbiAgc2VyaWFsaXplcjogU2VyaWFsaXplcjxWYWx1ZSwgRXh0cmFzPjtcbn1cblxuLyoqXG4gKiBUaGUgY2xpZW50IGhhcyBwYXJ0aWFsIHN1cHBvcnQgZm9yIHNlcmlhbGl6aW5nIGFuZCBkZXNlcmlhbGl6aW5nIHZhbHVlcyBmcm9tIHRoZVxuICogQnVmZmVyIGJ5dGUgc3RyaW5ncyB3ZSByZWNlaXZlIGZyb20gdGhlIHdpcmUuIFRoZSBkZWZhdWx0IHNlcmlhbGl6ZXIgaXMgZm9yIE1heWJlQnVmZmVyLlxuICpcbiAqIElmIFZhbHVlIGFuZCBFeHRyYXMgYXJlIG9mIHR5cGUgQnVmZmVyLCB0aGVuIHJldHVybiB0eXBlIFdoZW5CdWZmZXIuIE90aGVyd2lzZSxcbiAqIHJldHVybiB0eXBlIE5vdEJ1ZmZlci5cbiAqL1xudHlwZSBJZkJ1ZmZlcjxWYWx1ZSwgRXh0cmFzLCBXaGVuVmFsdWVBbmRFeHRyYXNBcmVCdWZmZXJzLCBOb3RCdWZmZXI+ID1cbiAgVmFsdWUgZXh0ZW5kcyBCdWZmZXJcbiAgICA/IEV4dHJhcyBleHRlbmRzIEJ1ZmZlclxuICAgICAgPyBXaGVuVmFsdWVBbmRFeHRyYXNBcmVCdWZmZXJzXG4gICAgICA6IE5vdEJ1ZmZlclxuICAgIDogTm90QnVmZmVyO1xuXG5leHBvcnQgdHlwZSBHaXZlbkNsaWVudE9wdGlvbnM8VmFsdWUsIEV4dHJhcz4gPSBQYXJ0aWFsPEJhc2VDbGllbnRPcHRpb25zPiAmXG4gIElmQnVmZmVyPFxuICAgIFZhbHVlLFxuICAgIEV4dHJhcyxcbiAgICBQYXJ0aWFsPFNlcmlhbGl6ZXJQcm9wPFZhbHVlLCBFeHRyYXM+PixcbiAgICBTZXJpYWxpemVyUHJvcDxWYWx1ZSwgRXh0cmFzPlxuICA+O1xuXG5leHBvcnQgdHlwZSBDQVNUb2tlbiA9IEJ1ZmZlcjtcblxuZXhwb3J0IGludGVyZmFjZSBHZXRSZXN1bHQ8VmFsdWUgPSBNYXliZUJ1ZmZlciwgRXh0cmFzID0gTWF5YmVCdWZmZXI+IHtcbiAgdmFsdWU6IFZhbHVlO1xuICBleHRyYXM6IEV4dHJhcztcbiAgY2FzOiBDQVNUb2tlbiB8IHVuZGVmaW5lZDtcbn1cblxuZXhwb3J0IHR5cGUgR2V0TXVsdGlSZXN1bHQ8XG4gIEtleXMgZXh0ZW5kcyBzdHJpbmcgPSBzdHJpbmcsXG4gIFZhbHVlID0gTWF5YmVCdWZmZXIsXG4gIEV4dHJhcyA9IE1heWJlQnVmZmVyXG4+ID0ge1xuICBbSyBpbiBLZXlzXT86IEdldFJlc3VsdDxWYWx1ZSwgRXh0cmFzPjtcbn07XG5cbmV4cG9ydCBpbnRlcmZhY2UgR2V0TXVsdGlFcnJvcjxLZXlzIGV4dGVuZHMgc3RyaW5nID0gc3RyaW5nPiB7XG4gIGVycm9yOiBFcnJvcjtcbiAgc2VydmVyS2V5OiBzdHJpbmc7XG4gIGtleXM6IEtleXNbXTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBHZXRNdWx0aVdpdGhFcnJvcnNSZXN1bHQ8XG5LZXlzIGV4dGVuZHMgc3RyaW5nID0gc3RyaW5nLFxuVmFsdWUgPSBNYXliZUJ1ZmZlcixcbkV4dHJhcyA9IE1heWJlQnVmZmVyXG4+IHtcbiAgcmVzdWx0OiBHZXRNdWx0aVJlc3VsdDxLZXlzLCBWYWx1ZSwgRXh0cmFzPjtcbiAgZXJyb3JzOiBHZXRNdWx0aUVycm9yPEtleXM+W107XG59XG5cbmNsYXNzIENsaWVudDxWYWx1ZSA9IE1heWJlQnVmZmVyLCBFeHRyYXMgPSBNYXliZUJ1ZmZlcj4ge1xuICBzZXJ2ZXJzOiBTZXJ2ZXJbXTtcbiAgc2VxOiBudW1iZXI7XG4gIG9wdGlvbnM6IEJhc2VDbGllbnRPcHRpb25zICYgUGFydGlhbDxTZXJpYWxpemVyUHJvcDxWYWx1ZSwgRXh0cmFzPj47XG4gIHNlcmlhbGl6ZXI6IFNlcmlhbGl6ZXI8VmFsdWUsIEV4dHJhcz47XG4gIHNlcnZlck1hcDogeyBbaG9zdHBvcnQ6IHN0cmluZ106IFNlcnZlciB9O1xuICBzZXJ2ZXJLZXlzOiBzdHJpbmdbXTtcblxuICAvLyBDbGllbnQgaW5pdGlhbGl6ZXIgdGFrZXMgYSBsaXN0IG9mIGBTZXJ2ZXJgcyBhbmQgYW4gYG9wdGlvbnNgIGRpY3Rpb25hcnkuXG4gIC8vIFNlZSBgQ2xpZW50LmNyZWF0ZWAgZm9yIGRldGFpbHMuXG4gIGNvbnN0cnVjdG9yKHNlcnZlcnM6IFNlcnZlcltdLCBvcHRpb25zOiBHaXZlbkNsaWVudE9wdGlvbnM8VmFsdWUsIEV4dHJhcz4pIHtcbiAgICB0aGlzLnNlcnZlcnMgPSBzZXJ2ZXJzO1xuICAgIHRoaXMuc2VxID0gMDtcbiAgICB0aGlzLm9wdGlvbnMgPSBtZXJnZShvcHRpb25zIHx8IHt9LCB7XG4gICAgICByZXRyaWVzOiAyLFxuICAgICAgcmV0cnlfZGVsYXk6IDAuMixcbiAgICAgIGV4cGlyZXM6IDAsXG4gICAgICBsb2dnZXI6IGNvbnNvbGUsXG4gICAgICBrZXlUb1NlcnZlckhhc2hGdW5jdGlvbjogZGVmYXVsdEtleVRvU2VydmVySGFzaEZ1bmN0aW9uLFxuICAgIH0pO1xuXG4gICAgdGhpcy5zZXJpYWxpemVyID0gdGhpcy5vcHRpb25zLnNlcmlhbGl6ZXIgfHwgKG5vb3BTZXJpYWxpemVyIGFzIGFueSk7XG5cbiAgICAvLyBTdG9yZSBhIG1hcHBpbmcgZnJvbSBob3N0cG9ydCAtPiBzZXJ2ZXIgc28gd2UgY2FuIHF1aWNrbHkgZ2V0IGEgc2VydmVyIG9iamVjdCBmcm9tIHRoZSBzZXJ2ZXJLZXkgcmV0dXJuZWQgYnkgdGhlIGhhc2hpbmcgZnVuY3Rpb25cbiAgICBjb25zdCBzZXJ2ZXJNYXA6IHsgW2hvc3Rwb3J0OiBzdHJpbmddOiBTZXJ2ZXIgfSA9IHt9O1xuICAgIHRoaXMuc2VydmVycy5mb3JFYWNoKGZ1bmN0aW9uIChzZXJ2ZXIpIHtcbiAgICAgIHNlcnZlck1hcFtzZXJ2ZXIuaG9zdHBvcnRTdHJpbmcoKV0gPSBzZXJ2ZXI7XG4gICAgfSk7XG4gICAgdGhpcy5zZXJ2ZXJNYXAgPSBzZXJ2ZXJNYXA7XG5cbiAgICAvLyBzdG9yZSBhIGxpc3Qgb2YgYWxsIG91ciBzZXJ2ZXJLZXlzIHNvIHdlIGRvbid0IG5lZWQgdG8gY29uc3RhbnRseSByZWFsbG9jYXRlIHRoaXMgYXJyYXlcbiAgICB0aGlzLnNlcnZlcktleXMgPSBPYmplY3Qua2V5cyh0aGlzLnNlcnZlck1hcCk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIG5ldyBjbGllbnQgZ2l2ZW4gYW4gb3B0aW9uYWwgY29uZmlnIHN0cmluZyBhbmQgb3B0aW9uYWwgaGFzaCBvZlxuICAgKiBvcHRpb25zLiBUaGUgY29uZmlnIHN0cmluZyBzaG91bGQgYmUgb2YgdGhlIGZvcm06XG4gICAqXG4gICAqICAgICBcIlt1c2VyOnBhc3NAXXNlcnZlcjFbOjExMjExXSxbdXNlcjpwYXNzQF1zZXJ2ZXIyWzoxMTIxMV0sLi4uXCJcbiAgICpcbiAgICogSWYgdGhlIGFyZ3VtZW50IGlzIG5vdCBnaXZlbiwgZmFsbGJhY2sgb24gdGhlIGBNRU1DQUNISUVSX1NFUlZFUlNgIGVudmlyb25tZW50XG4gICAqIHZhcmlhYmxlLCBgTUVNQ0FDSEVfU0VSVkVSU2AgZW52aXJvbm1lbnQgdmFyaWFibGUgb3IgYFwibG9jYWxob3N0OjExMjExXCJgLlxuICAgKlxuICAgKiBUaGUgb3B0aW9ucyBoYXNoIG1heSBjb250YWluIHRoZSBvcHRpb25zOlxuICAgKlxuICAgKiAqIGByZXRyaWVzYCAtIHRoZSBudW1iZXIgb2YgdGltZXMgdG8gcmV0cnkgYW4gb3BlcmF0aW9uIGluIGxpZXUgb2YgZmFpbHVyZXNcbiAgICogKGRlZmF1bHQgMilcbiAgICogKiBgZXhwaXJlc2AgLSB0aGUgZGVmYXVsdCBleHBpcmF0aW9uIGluIHNlY29uZHMgdG8gdXNlIChkZWZhdWx0IDAgLSBuZXZlclxuICAgKiBleHBpcmUpLiBJZiBgZXhwaXJlc2AgaXMgZ3JlYXRlciB0aGFuIDMwIGRheXMgKDYwIHggNjAgeCAyNCB4IDMwKSwgaXQgaXNcbiAgICogdHJlYXRlZCBhcyBhIFVOSVggdGltZSAobnVtYmVyIG9mIHNlY29uZHMgc2luY2UgSmFudWFyeSAxLCAxOTcwKS5cbiAgICogKiBgbG9nZ2VyYCAtIGEgbG9nZ2VyIG9iamVjdCB0aGF0IHJlc3BvbmRzIHRvIGBsb2coc3RyaW5nKWAgbWV0aG9kIGNhbGxzLlxuICAgKlxuICAgKiAgIH5+fn5cbiAgICogICAgIGxvZyhtc2cxWywgbXNnMlssIG1zZzNbLi4uXV1dKVxuICAgKiAgIH5+fn5cbiAgICpcbiAgICogICBEZWZhdWx0cyB0byBgY29uc29sZWAuXG4gICAqICogYHNlcmlhbGl6ZXJgIC0gdGhlIG9iamVjdCB3aGljaCB3aWxsIChkZSlzZXJpYWxpemUgdGhlIGRhdGEuIEl0IG5lZWRzXG4gICAqICAgdHdvIHB1YmxpYyBtZXRob2RzOiBzZXJpYWxpemUgYW5kIGRlc2VyaWFsaXplLiBJdCBkZWZhdWx0cyB0byB0aGVcbiAgICogICBub29wU2VyaWFsaXplcjpcbiAgICpcbiAgICogICB+fn5+XG4gICAqICAgY29uc3Qgbm9vcFNlcmlhbGl6ZXIgPSB7XG4gICAqICAgICBzZXJpYWxpemU6IGZ1bmN0aW9uIChvcGNvZGUsIHZhbHVlLCBleHRyYXMpIHtcbiAgICogICAgICAgcmV0dXJuIHsgdmFsdWU6IHZhbHVlLCBleHRyYXM6IGV4dHJhcyB9O1xuICAgKiAgICAgfSxcbiAgICogICAgIGRlc2VyaWFsaXplOiBmdW5jdGlvbiAob3Bjb2RlLCB2YWx1ZSwgZXh0cmFzKSB7XG4gICAqICAgICAgIHJldHVybiB7IHZhbHVlOiB2YWx1ZSwgZXh0cmFzOiBleHRyYXMgfTtcbiAgICogICAgIH1cbiAgICogICB9O1xuICAgKiAgIH5+fn5cbiAgICpcbiAgICogT3Igb3B0aW9ucyBmb3IgdGhlIHNlcnZlcnMgaW5jbHVkaW5nOlxuICAgKiAqIGB1c2VybmFtZWAgYW5kIGBwYXNzd29yZGAgZm9yIGZhbGxiYWNrIFNBU0wgYXV0aGVudGljYXRpb24gY3JlZGVudGlhbHMuXG4gICAqICogYHRpbWVvdXRgIGluIHNlY29uZHMgdG8gZGV0ZXJtaW5lIGZhaWx1cmUgZm9yIG9wZXJhdGlvbnMuIERlZmF1bHQgaXMgMC41XG4gICAqICAgICAgICAgICAgIHNlY29uZHMuXG4gICAqICogJ2Nvbm50aW1lb3V0JyBpbiBzZWNvbmRzIHRvIGNvbm5lY3Rpb24gZmFpbHVyZS4gRGVmYXVsdCBpcyB0d2ljZSB0aGUgdmFsdWVcbiAgICogICAgICAgICAgICAgICAgIG9mIGB0aW1lb3V0YC5cbiAgICogKiBga2VlcEFsaXZlYCB3aGV0aGVyIHRvIGVuYWJsZSBrZWVwLWFsaXZlIGZ1bmN0aW9uYWxpdHkuIERlZmF1bHRzIHRvIGZhbHNlLlxuICAgKiAqIGBrZWVwQWxpdmVEZWxheWAgaW4gc2Vjb25kcyB0byB0aGUgaW5pdGlhbCBkZWxheSBiZWZvcmUgdGhlIGZpcnN0IGtlZXBhbGl2ZVxuICAgKiAgICAgICAgICAgICAgICAgICAgcHJvYmUgaXMgc2VudCBvbiBhbiBpZGxlIHNvY2tldC4gRGVmYXVsdHMgaXMgMzAgc2Vjb25kcy5cbiAgICogKiBga2V5VG9TZXJ2ZXJIYXNoRnVuY3Rpb25gIGEgZnVuY3Rpb24gdG8gbWFwIGtleXMgdG8gc2VydmVycywgd2l0aCB0aGUgc2lnbmF0dXJlXG4gICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgIChzZXJ2ZXJLZXlzOiBzdHJpbmdbXSwga2V5OiBzdHJpbmcpOiBzdHJpbmdcbiAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgTk9URTogaWYgeW91IG5lZWQgdG8gZG8gc29tZSBleHBlbnNpdmUgaW5pdGlhbGl6YXRpb24sICpwbGVhc2UqIGRvIGl0IGxhemlseSB0aGUgZmlyc3QgdGltZSB5b3UgdGhpcyBmdW5jdGlvbiBpcyBjYWxsZWQgd2l0aCBhbiBhcnJheSBvZiBzZXJ2ZXJLZXlzLCBub3Qgb24gZXZlcnkgY2FsbFxuICAgKi9cbiAgc3RhdGljIGNyZWF0ZTxWYWx1ZSwgRXh0cmFzPihcbiAgICBzZXJ2ZXJzU3RyOiBzdHJpbmcgfCB1bmRlZmluZWQsXG4gICAgb3B0aW9uczogSWZCdWZmZXI8XG4gICAgICBWYWx1ZSxcbiAgICAgIEV4dHJhcyxcbiAgICAgIHVuZGVmaW5lZCB8IChQYXJ0aWFsPFNlcnZlck9wdGlvbnM+ICYgR2l2ZW5DbGllbnRPcHRpb25zPFZhbHVlLCBFeHRyYXM+KSxcbiAgICAgIFBhcnRpYWw8U2VydmVyT3B0aW9ucz4gJiBHaXZlbkNsaWVudE9wdGlvbnM8VmFsdWUsIEV4dHJhcz5cbiAgICA+XG4gICk6IENsaWVudDxWYWx1ZSwgRXh0cmFzPiB7XG4gICAgc2VydmVyc1N0ciA9XG4gICAgICBzZXJ2ZXJzU3RyIHx8XG4gICAgICBwcm9jZXNzLmVudi5NRU1DQUNISUVSX1NFUlZFUlMgfHxcbiAgICAgIHByb2Nlc3MuZW52Lk1FTUNBQ0hFX1NFUlZFUlMgfHxcbiAgICAgIFwibG9jYWxob3N0OjExMjExXCI7XG4gICAgY29uc3Qgc2VydmVyVXJpcyA9IHNlcnZlcnNTdHIuc3BsaXQoXCIsXCIpO1xuICAgIGNvbnN0IHNlcnZlcnMgPSBzZXJ2ZXJVcmlzLm1hcChmdW5jdGlvbiAodXJpKSB7XG4gICAgICBjb25zdCB1cmlQYXJ0cyA9IHVyaS5zcGxpdChcIkBcIik7XG4gICAgICBjb25zdCBob3N0UG9ydCA9IHVyaVBhcnRzW3VyaVBhcnRzLmxlbmd0aCAtIDFdLnNwbGl0KFwiOlwiKTtcbiAgICAgIGNvbnN0IHVzZXJQYXNzID0gKHVyaVBhcnRzW3VyaVBhcnRzLmxlbmd0aCAtIDJdIHx8IFwiXCIpLnNwbGl0KFwiOlwiKTtcbiAgICAgIHJldHVybiBuZXcgU2VydmVyKFxuICAgICAgICBob3N0UG9ydFswXSxcbiAgICAgICAgcGFyc2VJbnQoaG9zdFBvcnRbMV0gfHwgXCIxMTIxMVwiLCAxMCksXG4gICAgICAgIHVzZXJQYXNzWzBdLFxuICAgICAgICB1c2VyUGFzc1sxXSxcbiAgICAgICAgb3B0aW9uc1xuICAgICAgKTtcbiAgICB9KTtcbiAgICByZXR1cm4gbmV3IENsaWVudChzZXJ2ZXJzLCBvcHRpb25zIGFzIGFueSk7XG4gIH1cblxuICAvKipcbiAgICogR2l2ZW4gYSBzZXJ2ZXJLZXkgZnJvbWxvb2t1cEtleVRvU2VydmVyS2V5LCByZXR1cm4gdGhlIGNvcnJlc3BvbmRpbmcgU2VydmVyIGluc3RhbmNlXG4gICAqXG4gICAqIEBwYXJhbSAge3N0cmluZ30gc2VydmVyS2V5XG4gICAqIEByZXR1cm5zIHtTZXJ2ZXJ9XG4gICAqL1xuICBzZXJ2ZXJLZXlUb1NlcnZlcihzZXJ2ZXJLZXk6IHN0cmluZyk6IFNlcnZlciB7XG4gICAgcmV0dXJuIHRoaXMuc2VydmVyTWFwW3NlcnZlcktleV07XG4gIH1cblxuICAvKipcbiAgICogR2l2ZW4gYSBrZXkgdG8gbG9vayB1cCBpbiBtZW1jYWNoZSwgcmV0dXJuIGEgc2VydmVyS2V5IChiYXNlZCBvbiBzb21lXG4gICAqIGhhc2hpbmcgZnVuY3Rpb24pIHdoaWNoIGNhbiBiZSB1c2VkIHRvIGluZGV4IHRoaXMuc2VydmVyTWFwXG4gICAqL1xuICBsb29rdXBLZXlUb1NlcnZlcktleShrZXk6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMub3B0aW9ucy5rZXlUb1NlcnZlckhhc2hGdW5jdGlvbih0aGlzLnNlcnZlcktleXMsIGtleSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldmVzIHRoZSB2YWx1ZSBhdCB0aGUgZ2l2ZW4ga2V5IGluIG1lbWNhY2hlLlxuICAgKi9cbiAgYXN5bmMgZ2V0KGtleTogc3RyaW5nKTogUHJvbWlzZTxHZXRSZXN1bHQ8VmFsdWUsIEV4dHJhcz4gfCBudWxsPiB7XG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKGNvbnN0YW50cy5PUF9HRVQsIGtleSwgXCJcIiwgXCJcIiwgdGhpcy5zZXEpO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICBjb25zdCBkZXNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuZGVzZXJpYWxpemUoXG4gICAgICAgICAgcmVzcG9uc2UuaGVhZGVyLm9wY29kZSxcbiAgICAgICAgICByZXNwb25zZS52YWwsXG4gICAgICAgICAgcmVzcG9uc2UuZXh0cmFzXG4gICAgICAgICk7XG4gICAgICAgIHJldHVybiB7IC4uLmRlc2VyaWFsaXplZCwgY2FzOiByZXNwb25zZS5oZWFkZXIuY2FzIH07XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIkdFVFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKiogQnVpbGQgYSBwaXBlbGluZWQgZ2V0IG11bHRpIHJlcXVlc3QgYnkgc2VuZGluZyBvbmUgR0VUS1EgZm9yIGVhY2gga2V5IChxdWlldCwgbWVhbmluZyBpdCB3b24ndCByZXNwb25kIGlmIHRoZSB2YWx1ZSBpcyBtaXNzaW5nKSBmb2xsb3dlZCBieSBhIG5vLW9wIHRvIGZvcmNlIGEgcmVzcG9uc2UgKGFuZCB0byBnaXZlIHVzIGEgc2VudGluZWwgcmVzcG9uc2UgdGhhdCB0aGUgcGlwZWxpbmUgaXMgZG9uZSlcbiAgICpcbiAgICogY2YgaHR0cHM6Ly9naXRodWIuY29tL2NvdWNoYmFzZS9tZW1jYWNoZWQvYmxvYi9tYXN0ZXIvZG9jcy9CaW5hcnlQcm90b2NvbC5tZCMweDBkLWdldGtxLWdldC13aXRoLWtleS1xdWlldGx5XG4gICAqL1xuICBfYnVpbGRHZXRNdWx0aVJlcXVlc3Qoa2V5czogc3RyaW5nW10sIHNlcTogbnVtYmVyKTogQnVmZmVyIHtcbiAgICAvLyBzdGFydCBhdCAyNCBmb3IgdGhlIG5vLW9wIGNvbW1hbmQgYXQgdGhlIGVuZFxuICAgIGxldCByZXF1ZXN0U2l6ZSA9IDI0O1xuICAgIGZvciAoY29uc3Qga2V5SWR4IGluIGtleXMpIHtcbiAgICAgIHJlcXVlc3RTaXplICs9IEJ1ZmZlci5ieXRlTGVuZ3RoKGtleXNba2V5SWR4XSwgXCJ1dGY4XCIpICsgMjQ7XG4gICAgfVxuXG4gICAgY29uc3QgcmVxdWVzdCA9IEJ1ZmZlci5hbGxvYyhyZXF1ZXN0U2l6ZSk7XG5cbiAgICBsZXQgYnl0ZXNXcml0dGVuID0gMDtcbiAgICBmb3IgKGNvbnN0IGtleUlkeCBpbiBrZXlzKSB7XG4gICAgICBjb25zdCBrZXkgPSBrZXlzW2tleUlkeF07XG4gICAgICBieXRlc1dyaXR0ZW4gKz0gY29weUludG9SZXF1ZXN0QnVmZmVyKFxuICAgICAgICBjb25zdGFudHMuT1BfR0VUS1EsXG4gICAgICAgIGtleSxcbiAgICAgICAgXCJcIixcbiAgICAgICAgXCJcIixcbiAgICAgICAgc2VxLFxuICAgICAgICByZXF1ZXN0LFxuICAgICAgICBieXRlc1dyaXR0ZW5cbiAgICAgICk7XG4gICAgfVxuXG4gICAgYnl0ZXNXcml0dGVuICs9IGNvcHlJbnRvUmVxdWVzdEJ1ZmZlcihcbiAgICAgIGNvbnN0YW50cy5PUF9OT19PUCxcbiAgICAgIFwiXCIsXG4gICAgICBcIlwiLFxuICAgICAgXCJcIixcbiAgICAgIHNlcSxcbiAgICAgIHJlcXVlc3QsXG4gICAgICBieXRlc1dyaXR0ZW5cbiAgICApO1xuXG4gICAgcmV0dXJuIHJlcXVlc3Q7XG4gIH1cblxuICAvKiogRXhlY3V0aW5nIGEgcGlwZWxpbmVkIChtdWx0aSkgZ2V0IGFnYWluc3QgYSBzaW5nbGUgc2VydmVyLiBUaGlzIGlzIGEgcHJpdmF0ZSBpbXBsZW1lbnRhdGlvbiBkZXRhaWwgb2YgZ2V0TXVsdGkuICovXG4gIGFzeW5jIF9nZXRNdWx0aVRvU2VydmVyPEtleXMgZXh0ZW5kcyBzdHJpbmc+KFxuICAgIHNlcnY6IFNlcnZlcixcbiAgICBrZXlzOiBLZXlzW11cbiAgKTogUHJvbWlzZTxHZXRNdWx0aVJlc3VsdDxLZXlzLCBWYWx1ZSwgRXh0cmFzPj4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBjb25zdCByZXNwb25zZU1hcDogR2V0TXVsdGlSZXN1bHQ8c3RyaW5nLCBWYWx1ZSwgRXh0cmFzPiA9IHt9O1xuXG4gICAgICBjb25zdCBoYW5kbGU6IE9uUmVzcG9uc2VDYWxsYmFjayA9IChyZXNwb25zZSkgPT4ge1xuICAgICAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgICAgICAvLyBXaGVuIHdlIGdldCB0aGUgbm8tb3AgcmVzcG9uc2UsIHdlIGFyZSBkb25lIHdpdGggdGhpcyBvbmUgZ2V0TXVsdGkgaW4gdGhlIHBlci1iYWNrZW5kIGZhbi1vdXRcbiAgICAgICAgICAgIGlmIChyZXNwb25zZS5oZWFkZXIub3Bjb2RlID09PSBjb25zdGFudHMuT1BfTk9fT1ApIHtcbiAgICAgICAgICAgICAgLy8gVGhpcyBlbnN1cmVzIHRoZSBoYW5kbGVyIHdpbGwgYmUgZGVsZXRlZCBmcm9tIHRoZSByZXNwb25zZUNhbGxiYWNrcyBtYXAgaW4gc2VydmVyLmpzXG4gICAgICAgICAgICAgIC8vIFRoaXMgaXNuJ3QgdGVjaG5pY2FsbHkgbmVlZGVkIGhlcmUgYmVjYXVzZSB0aGUgbG9naWMgaW4gc2VydmVyLmpzIGFsc28gY2hlY2tzIGlmIHRvdGFsQm9keUxlbmd0aCA9PT0gMCwgYnV0IG91ciB1bml0dGVzdHMgYXJlbid0IGdyZWF0IGFib3V0IHNldHRpbmcgdGhhdCBmaWVsZCwgYW5kIGFsc28gdGhpcyBtYWtlcyBpdCBtb3JlIGV4cGxpY2l0XG4gICAgICAgICAgICAgIGhhbmRsZS5xdWlldCA9IGZhbHNlO1xuICAgICAgICAgICAgICByZXNvbHZlKHJlc3BvbnNlTWFwKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgICAgICAgIHJlc3BvbnNlLmhlYWRlci5vcGNvZGUgPT09IGNvbnN0YW50cy5PUF9HRVRLIHx8XG4gICAgICAgICAgICAgIHJlc3BvbnNlLmhlYWRlci5vcGNvZGUgPT09IGNvbnN0YW50cy5PUF9HRVRLUVxuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgIGNvbnN0IGRlc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5kZXNlcmlhbGl6ZShcbiAgICAgICAgICAgICAgICByZXNwb25zZS5oZWFkZXIub3Bjb2RlLFxuICAgICAgICAgICAgICAgIHJlc3BvbnNlLnZhbCxcbiAgICAgICAgICAgICAgICByZXNwb25zZS5leHRyYXNcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgY29uc3Qga2V5ID0gcmVzcG9uc2Uua2V5LnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgIGlmIChrZXkubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlamVjdChcbiAgICAgICAgICAgICAgICAgIG5ldyBFcnJvcihcbiAgICAgICAgICAgICAgICAgICAgXCJSZWNpZXZlZCBlbXB0eSBrZXkgaW4gZ2V0TXVsdGk6IFwiICtcbiAgICAgICAgICAgICAgICAgICAgICBKU09OLnN0cmluZ2lmeShyZXNwb25zZSlcbiAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIHJlc3BvbnNlTWFwW2tleV0gPSB7IC4uLmRlc2VyaWFsaXplZCwgY2FzOiByZXNwb25zZS5oZWFkZXIuY2FzIH07XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICByZXR1cm4gcmVqZWN0KFxuICAgICAgICAgICAgICAgIG5ldyBFcnJvcihcbiAgICAgICAgICAgICAgICAgIFwiUmVjaWV2ZWQgcmVzcG9uc2UgaW4gZ2V0TXVsdGkgZm9yIHVua25vd24gb3Bjb2RlOiBcIiArXG4gICAgICAgICAgICAgICAgICAgIEpTT04uc3RyaW5naWZ5KHJlc3BvbnNlKVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICByZXR1cm4gcmVqZWN0KFxuICAgICAgICAgICAgICB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiR0VUXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9O1xuICAgICAgLy8gVGhpcyBwcmV2ZW50cyB0aGUgaGFuZGxlciBmcm9tIGJlaW5nIGRlbGV0ZWRcbiAgICAgIC8vIGFmdGVyIHRoZSBmaXJzdCByZXNwb25zZS4gTG9naWMgaW4gc2VydmVyLmpzLlxuICAgICAgaGFuZGxlLnF1aWV0ID0gdHJ1ZTtcblxuICAgICAgY29uc3Qgc2VxID0gdGhpcy5pbmNyU2VxKCk7XG4gICAgICBjb25zdCByZXF1ZXN0ID0gdGhpcy5fYnVpbGRHZXRNdWx0aVJlcXVlc3Qoa2V5cywgc2VxKTtcbiAgICAgIHNlcnYub25SZXNwb25zZSh0aGlzLnNlcSwgaGFuZGxlKTtcbiAgICAgIHNlcnYub25FcnJvcih0aGlzLnNlcSwgcmVqZWN0KTtcbiAgICAgIHNlcnYud3JpdGUocmVxdWVzdCk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldnMgdGhlIHZhbHVlIGF0IHRoZSBnaXZlbiBrZXlzIGluIG1lbWNhY2hlZC4gUmV0dXJucyBhIG1hcCBmcm9tIHRoZVxuICAgKiByZXF1ZXN0ZWQga2V5cyB0byByZXN1bHRzLCBvciBudWxsIGlmIHRoZSBrZXkgd2FzIG5vdCBmb3VuZC5cbiAgICovXG4gIGFzeW5jIGdldE11bHRpPEtleXMgZXh0ZW5kcyBzdHJpbmc+KFxuICAgIGtleXM6IEtleXNbXVxuICApOiBQcm9taXNlPEdldE11bHRpUmVzdWx0PEtleXMsIFZhbHVlLCBFeHRyYXM+PiB7XG4gICAgY29uc3Qgc2VydmVyS2V5dG9Mb29rdXBLZXlzOiB7XG4gICAgICBbc2VydmVyS2V5OiBzdHJpbmddOiBzdHJpbmdbXTtcbiAgICB9ID0ge307XG4gICAga2V5cy5mb3JFYWNoKChsb29rdXBLZXkpID0+IHtcbiAgICAgIGNvbnN0IHNlcnZlcktleSA9IHRoaXMubG9va3VwS2V5VG9TZXJ2ZXJLZXkobG9va3VwS2V5KTtcbiAgICAgIGlmICghc2VydmVyS2V5dG9Mb29rdXBLZXlzW3NlcnZlcktleV0pIHtcbiAgICAgICAgc2VydmVyS2V5dG9Mb29rdXBLZXlzW3NlcnZlcktleV0gPSBbXTtcbiAgICAgIH1cbiAgICAgIHNlcnZlcktleXRvTG9va3VwS2V5c1tzZXJ2ZXJLZXldLnB1c2gobG9va3VwS2V5KTtcbiAgICB9KTtcblxuICAgIGNvbnN0IHVzZWRTZXJ2ZXJLZXlzID0gT2JqZWN0LmtleXMoc2VydmVyS2V5dG9Mb29rdXBLZXlzKTtcbiAgICBjb25zdCByZXN1bHRzID0gYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICB1c2VkU2VydmVyS2V5cy5tYXAoKHNlcnZlcktleSkgPT4ge1xuICAgICAgICBjb25zdCBzZXJ2ZXIgPSB0aGlzLnNlcnZlcktleVRvU2VydmVyKHNlcnZlcktleSk7XG4gICAgICAgIHJldHVybiB0aGlzLl9nZXRNdWx0aVRvU2VydmVyKHNlcnZlciwgc2VydmVyS2V5dG9Mb29rdXBLZXlzW3NlcnZlcktleV0pO1xuICAgICAgfSlcbiAgICApO1xuXG4gICAgcmV0dXJuIE9iamVjdC5hc3NpZ24oe30sIC4uLnJlc3VsdHMpO1xuICB9XG5cbiAgYXN5bmMgZ2V0TXVsdGlXaXRoRXJyb3JzPEtleXMgZXh0ZW5kcyBzdHJpbmc+KFxuICAgIGtleXM6IEtleXNbXVxuICApOiBQcm9taXNlPEdldE11bHRpV2l0aEVycm9yc1Jlc3VsdDxLZXlzLCBWYWx1ZSwgRXh0cmFzPj4ge1xuICAgIGNvbnN0IHNlcnZlcktleXRvTG9va3VwS2V5czoge1xuICAgICAgW3NlcnZlcktleTogc3RyaW5nXTogS2V5c1tdO1xuICAgIH0gPSB7fTtcbiAgICBrZXlzLmZvckVhY2goKGxvb2t1cEtleSkgPT4ge1xuICAgICAgY29uc3Qgc2VydmVyS2V5ID0gdGhpcy5sb29rdXBLZXlUb1NlcnZlcktleShsb29rdXBLZXkpO1xuICAgICAgaWYgKCFzZXJ2ZXJLZXl0b0xvb2t1cEtleXNbc2VydmVyS2V5XSkge1xuICAgICAgICBzZXJ2ZXJLZXl0b0xvb2t1cEtleXNbc2VydmVyS2V5XSA9IFtdO1xuICAgICAgfVxuICAgICAgc2VydmVyS2V5dG9Mb29rdXBLZXlzW3NlcnZlcktleV0ucHVzaChsb29rdXBLZXkpO1xuICAgIH0pO1xuXG4gICAgY29uc3QgdXNlZFNlcnZlcktleXMgPSBPYmplY3Qua2V5cyhzZXJ2ZXJLZXl0b0xvb2t1cEtleXMpO1xuICAgIGNvbnN0IGVycm9yczogR2V0TXVsdGlFcnJvcjxLZXlzPltdID0gW107XG4gICAgY29uc3QgcmVzdWx0cyA9IGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgdXNlZFNlcnZlcktleXMubWFwKGFzeW5jIChzZXJ2ZXJLZXkpID0+IHtcbiAgICAgICAgY29uc3Qgc2VydmVyID0gdGhpcy5zZXJ2ZXJLZXlUb1NlcnZlcihzZXJ2ZXJLZXkpO1xuICAgICAgICB0cnkge1xuICAgICAgICAgIHJldHVybiBhd2FpdCB0aGlzLl9nZXRNdWx0aVRvU2VydmVyKHNlcnZlciwgc2VydmVyS2V5dG9Mb29rdXBLZXlzW3NlcnZlcktleV0pO1xuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgIGVycm9ycy5wdXNoKHtcbiAgICAgICAgICAgIGVycm9yOiBlcnJvciBhcyBFcnJvcixcbiAgICAgICAgICAgIHNlcnZlcktleSxcbiAgICAgICAgICAgIGtleXM6IHNlcnZlcktleXRvTG9va3VwS2V5c1tzZXJ2ZXJLZXldXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH0pXG4gICAgKTtcblxuICAgIHJldHVybiB7IHJlc3VsdDogT2JqZWN0LmFzc2lnbih7fSwgLi4ucmVzdWx0cyksIGVycm9ycyB9O1xuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgYGtleWAgdG8gYHZhbHVlYC5cbiAgICovXG4gIGFzeW5jIHNldChcbiAgICBrZXk6IHN0cmluZyxcbiAgICB2YWx1ZTogVmFsdWUsXG4gICAgb3B0aW9ucz86IHsgZXhwaXJlcz86IG51bWJlcjsgY2FzPzogQ0FTVG9rZW4gfVxuICApOiBQcm9taXNlPGJvb2xlYW4gfCBudWxsPiB7XG4gICAgY29uc3QgZXhwaXJlcyA9IG9wdGlvbnM/LmV4cGlyZXM7XG4gICAgY29uc3QgY2FzID0gb3B0aW9ucz8uY2FzO1xuXG4gICAgLy8gVE9ETzogc3VwcG9ydCBmbGFnc1xuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IGV4cGlyYXRpb24gPSBtYWtlRXhwaXJhdGlvbihleHBpcmVzIHx8IHRoaXMub3B0aW9ucy5leHBpcmVzKTtcbiAgICBjb25zdCBleHRyYXMgPSBCdWZmZXIuY29uY2F0KFtCdWZmZXIuZnJvbShcIjAwMDAwMDAwXCIsIFwiaGV4XCIpLCBleHBpcmF0aW9uXSk7XG4gICAgY29uc3Qgc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5zZXJpYWxpemUoXG4gICAgICBjb25zdGFudHMuT1BfU0VULFxuICAgICAgdmFsdWUsXG4gICAgICBleHRyYXNcbiAgICApO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBVdGlscy5lbmNvZGVSZXF1ZXN0KHtcbiAgICAgIGhlYWRlcjoge1xuICAgICAgICBvcGNvZGU6IGNvbnN0YW50cy5PUF9TRVQsXG4gICAgICAgIG9wYXF1ZTogdGhpcy5zZXEsXG4gICAgICAgIGNhcyxcbiAgICAgIH0sXG4gICAgICBrZXksXG4gICAgICB2YWx1ZTogc2VyaWFsaXplZC52YWx1ZSxcbiAgICAgIGV4dHJhczogc2VyaWFsaXplZC5leHRyYXMsXG4gICAgfSk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfRVhJU1RTOlxuICAgICAgICBpZiAoY2FzKSB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJTRVRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgICAgIH1cbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJTRVRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEFERFxuICAgKlxuICAgKiBBZGRzIHRoZSBnaXZlbiBfa2V5XyBhbmQgX3ZhbHVlXyB0byBtZW1jYWNoZS4gVGhlIG9wZXJhdGlvbiBvbmx5IHN1Y2NlZWRzXG4gICAqIGlmIHRoZSBrZXkgaXMgbm90IGFscmVhZHkgc2V0LlxuICAgKlxuICAgKiBUaGUgb3B0aW9ucyBkaWN0aW9uYXJ5IHRha2VzOlxuICAgKiAqIF9leHBpcmVzXzogb3ZlcnJpZGVzIHRoZSBkZWZhdWx0IGV4cGlyYXRpb24gKHNlZSBgQ2xpZW50LmNyZWF0ZWApIGZvciB0aGlzXG4gICAqICAgICAgICAgICAgICBwYXJ0aWN1bGFyIGtleS12YWx1ZSBwYWlyLlxuICAgKi9cbiAgYXN5bmMgYWRkKFxuICAgIGtleTogc3RyaW5nLFxuICAgIHZhbHVlOiBWYWx1ZSxcbiAgICBvcHRpb25zPzogeyBleHBpcmVzPzogbnVtYmVyIH1cbiAgKTogUHJvbWlzZTxib29sZWFuIHwgbnVsbD4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgZmxhZ3MsIHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IGV4cGlyYXRpb24gPSBtYWtlRXhwaXJhdGlvbihvcHRpb25zPy5leHBpcmVzIHx8IHRoaXMub3B0aW9ucy5leHBpcmVzKTtcbiAgICBjb25zdCBleHRyYXMgPSBCdWZmZXIuY29uY2F0KFtCdWZmZXIuZnJvbShcIjAwMDAwMDAwXCIsIFwiaGV4XCIpLCBleHBpcmF0aW9uXSk7XG5cbiAgICBjb25zdCBvcGNvZGUgPSBjb25zdGFudHMuT1BfQUREO1xuICAgIGNvbnN0IHNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuc2VyaWFsaXplKG9wY29kZSwgdmFsdWUsIGV4dHJhcyk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKFxuICAgICAgb3Bjb2RlLFxuICAgICAga2V5LFxuICAgICAgc2VyaWFsaXplZC5leHRyYXMsXG4gICAgICBzZXJpYWxpemVkLnZhbHVlLFxuICAgICAgdGhpcy5zZXFcbiAgICApO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuS0VZX0VYSVNUUzpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJBRERcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlcGxhY2VzIHRoZSBnaXZlbiBfa2V5XyBhbmQgX3ZhbHVlXyB0byBtZW1jYWNoZS4gVGhlIG9wZXJhdGlvbiBvbmx5IHN1Y2NlZWRzXG4gICAqIGlmIHRoZSBrZXkgaXMgYWxyZWFkeSBwcmVzZW50LlxuICAgKi9cbiAgYXN5bmMgcmVwbGFjZShcbiAgICBrZXk6IHN0cmluZyxcbiAgICB2YWx1ZTogVmFsdWUsXG4gICAgb3B0aW9ucz86IHsgZXhwaXJlcz86IG51bWJlciB9XG4gICk6IFByb21pc2U8Ym9vbGVhbiB8IG51bGw+IHtcbiAgICAvLyBUT0RPOiBzdXBwb3J0IGZsYWdzLCBzdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBleHBpcmF0aW9uID0gbWFrZUV4cGlyYXRpb24ob3B0aW9ucz8uZXhwaXJlcyB8fCB0aGlzLm9wdGlvbnMuZXhwaXJlcyk7XG4gICAgY29uc3QgZXh0cmFzID0gQnVmZmVyLmNvbmNhdChbQnVmZmVyLmZyb20oXCIwMDAwMDAwMFwiLCBcImhleFwiKSwgZXhwaXJhdGlvbl0pO1xuXG4gICAgY29uc3Qgb3Bjb2RlOiBjb25zdGFudHMuT1AgPSBjb25zdGFudHMuT1BfUkVQTEFDRTtcbiAgICBjb25zdCBzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLnNlcmlhbGl6ZShvcGNvZGUsIHZhbHVlLCBleHRyYXMpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgIG9wY29kZSxcbiAgICAgIGtleSxcbiAgICAgIHNlcmlhbGl6ZWQuZXh0cmFzLFxuICAgICAgc2VyaWFsaXplZC52YWx1ZSxcbiAgICAgIHRoaXMuc2VxXG4gICAgKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJSRVBMQUNFXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBEZWxldGVzIHRoZSBnaXZlbiBfa2V5XyBmcm9tIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHNcbiAgICogaWYgdGhlIGtleSBpcyBhbHJlYWR5IHByZXNlbnQuXG4gICAqL1xuICBhc3luYyBkZWxldGUoa2V5OiBzdHJpbmcpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAvLyBUT0RPOiBTdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoNCwga2V5LCBcIlwiLCBcIlwiLCB0aGlzLnNlcSk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG5cbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJERUxFVEVcIiwgcmVzcG9uc2U/LmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBJbmNyZW1lbnRzIHRoZSBnaXZlbiBfa2V5XyBpbiBtZW1jYWNoZS5cbiAgICovXG4gIGFzeW5jIGluY3JlbWVudChcbiAgICBrZXk6IHN0cmluZyxcbiAgICBhbW91bnQ6IG51bWJlcixcbiAgICBvcHRpb25zPzogeyBpbml0aWFsPzogbnVtYmVyOyBleHBpcmVzPzogbnVtYmVyIH1cbiAgKTogUHJvbWlzZTx7IHZhbHVlOiBudW1iZXIgfCBudWxsOyBzdWNjZXNzOiBib29sZWFuIHwgbnVsbCB9PiB7XG4gICAgLy8gVE9ETzogc3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgaW5pdGlhbCA9IG9wdGlvbnM/LmluaXRpYWwgfHwgMDtcbiAgICBjb25zdCBleHBpcmVzID0gb3B0aW9ucz8uZXhwaXJlcyB8fCB0aGlzLm9wdGlvbnMuZXhwaXJlcztcbiAgICBjb25zdCBleHRyYXMgPSBtYWtlQW1vdW50SW5pdGlhbEFuZEV4cGlyYXRpb24oYW1vdW50LCBpbml0aWFsLCBleHBpcmVzKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICBjb25zdGFudHMuT1BfSU5DUkVNRU5ULFxuICAgICAga2V5LFxuICAgICAgZXh0cmFzLFxuICAgICAgXCJcIixcbiAgICAgIHRoaXMuc2VxXG4gICAgKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgY29uc3QgYnVmSW50ID1cbiAgICAgICAgICAocmVzcG9uc2UudmFsLnJlYWRVSW50MzJCRSgwKSA8PCA4KSArIHJlc3BvbnNlLnZhbC5yZWFkVUludDMyQkUoNCk7XG4gICAgICAgIHJldHVybiB7IHZhbHVlOiBidWZJbnQsIHN1Y2Nlc3M6IHRydWUgfTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJJTkNSRU1FTlRcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIERlY3JlbWVudHMgdGhlIGdpdmVuIGBrZXlgIGluIG1lbWNhY2hlLlxuICAgKi9cbiAgYXN5bmMgZGVjcmVtZW50KFxuICAgIGtleTogc3RyaW5nLFxuICAgIGFtb3VudDogbnVtYmVyLFxuICAgIG9wdGlvbnM6IHsgaW5pdGlhbD86IG51bWJlcjsgZXhwaXJlcz86IG51bWJlciB9XG4gICk6IFByb21pc2U8eyB2YWx1ZTogbnVtYmVyIHwgbnVsbDsgc3VjY2VzczogYm9vbGVhbiB8IG51bGwgfT4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IGluaXRpYWwgPSBvcHRpb25zLmluaXRpYWwgfHwgMDtcbiAgICBjb25zdCBleHBpcmVzID0gb3B0aW9ucy5leHBpcmVzIHx8IHRoaXMub3B0aW9ucy5leHBpcmVzO1xuICAgIGNvbnN0IGV4dHJhcyA9IG1ha2VBbW91bnRJbml0aWFsQW5kRXhwaXJhdGlvbihhbW91bnQsIGluaXRpYWwsIGV4cGlyZXMpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgIGNvbnN0YW50cy5PUF9ERUNSRU1FTlQsXG4gICAgICBrZXksXG4gICAgICBleHRyYXMsXG4gICAgICBcIlwiLFxuICAgICAgdGhpcy5zZXFcbiAgICApO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5wZXJmb3JtKGtleSwgcmVxdWVzdCwgdGhpcy5zZXEpO1xuICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICBjb25zdCBidWZJbnQgPVxuICAgICAgICAgIChyZXNwb25zZS52YWwucmVhZFVJbnQzMkJFKDApIDw8IDgpICsgcmVzcG9uc2UudmFsLnJlYWRVSW50MzJCRSg0KTtcbiAgICAgICAgcmV0dXJuIHsgdmFsdWU6IGJ1ZkludCwgc3VjY2VzczogdHJ1ZSB9O1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgdGhpcy5jcmVhdGVBbmRMb2dFcnJvcihcIkRFQ1JFTUVOVFwiLCByZXNwb25zZS5oZWFkZXIuc3RhdHVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQXBwZW5kIHRoZSBnaXZlbiBfdmFsdWVfIHRvIHRoZSB2YWx1ZSBhc3NvY2lhdGVkIHdpdGggdGhlIGdpdmVuIF9rZXlfIGluXG4gICAqIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHMgaWYgdGhlIGtleSBpcyBhbHJlYWR5IHByZXNlbnQuXG4gICAqL1xuICBhc3luYyBhcHBlbmQoa2V5OiBzdHJpbmcsIHZhbHVlOiBWYWx1ZSk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIC8vIFRPRE86IHN1cHBvcnQgdmVyc2lvbiAoQ0FTKVxuICAgIHRoaXMuaW5jclNlcSgpO1xuICAgIGNvbnN0IG9wY29kZTogY29uc3RhbnRzLk9QID0gY29uc3RhbnRzLk9QX0FQUEVORDtcbiAgICBjb25zdCBzZXJpYWxpemVkID0gdGhpcy5zZXJpYWxpemVyLnNlcmlhbGl6ZShvcGNvZGUsIHZhbHVlLCBcIlwiKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICBvcGNvZGUsXG4gICAgICBrZXksXG4gICAgICBzZXJpYWxpemVkLmV4dHJhcyxcbiAgICAgIHNlcmlhbGl6ZWQudmFsdWUsXG4gICAgICB0aGlzLnNlcVxuICAgICk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfTk9UX0ZPVU5EOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiQVBQRU5EXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBQcmVwZW5kIHRoZSBnaXZlbiBfdmFsdWVfIHRvIHRoZSB2YWx1ZSBhc3NvY2lhdGVkIHdpdGggdGhlIGdpdmVuIF9rZXlfIGluXG4gICAqIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHMgaWYgdGhlIGtleSBpcyBhbHJlYWR5IHByZXNlbnQuXG4gICAqL1xuICBhc3luYyBwcmVwZW5kKGtleTogc3RyaW5nLCB2YWx1ZTogVmFsdWUpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAvLyBUT0RPOiBzdXBwb3J0IHZlcnNpb24gKENBUylcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCBvcGNvZGU6IGNvbnN0YW50cy5PUCA9IGNvbnN0YW50cy5PUF9QUkVQRU5EO1xuICAgIGNvbnN0IHNlcmlhbGl6ZWQgPSB0aGlzLnNlcmlhbGl6ZXIuc2VyaWFsaXplKG9wY29kZSwgdmFsdWUsIFwiXCIpO1xuICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdEJ1ZmZlcihcbiAgICAgIG9wY29kZSxcbiAgICAgIGtleSxcbiAgICAgIHNlcmlhbGl6ZWQuZXh0cmFzLFxuICAgICAgc2VyaWFsaXplZC52YWx1ZSxcbiAgICAgIHRoaXMuc2VxXG4gICAgKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucGVyZm9ybShrZXksIHJlcXVlc3QsIHRoaXMuc2VxKTtcbiAgICBzd2l0Y2ggKHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpIHtcbiAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLktFWV9OT1RfRk9VTkQ6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJQUkVQRU5EXCIsIHJlc3BvbnNlLmhlYWRlci5zdGF0dXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBUb3VjaCBzZXRzIGFuIGV4cGlyYXRpb24gdmFsdWUsIGdpdmVuIGJ5IF9leHBpcmVzXywgb24gdGhlIGdpdmVuIF9rZXlfIGluXG4gICAqIG1lbWNhY2hlLiBUaGUgb3BlcmF0aW9uIG9ubHkgc3VjY2VlZHMgaWYgdGhlIGtleSBpcyBhbHJlYWR5IHByZXNlbnQuXG4gICAqL1xuICBhc3luYyB0b3VjaChrZXk6IHN0cmluZywgZXhwaXJlczogbnVtYmVyKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgLy8gVE9ETzogc3VwcG9ydCB2ZXJzaW9uIChDQVMpXG4gICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgY29uc3QgZXh0cmFzID0gbWFrZUV4cGlyYXRpb24oZXhwaXJlcyB8fCB0aGlzLm9wdGlvbnMuZXhwaXJlcyk7XG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKDB4MWMsIGtleSwgZXh0cmFzLCBcIlwiLCB0aGlzLnNlcSk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBlcmZvcm0oa2V5LCByZXF1ZXN0LCB0aGlzLnNlcSk7XG4gICAgc3dpdGNoIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICBjYXNlIFJlc3BvbnNlU3RhdHVzLlNVQ0NFU1M6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5LRVlfTk9UX0ZPVU5EOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKFwiVE9VQ0hcIiwgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEZMVVNIXG4gICAqXG4gICAqIEZsdXNoZXMgdGhlIGNhY2hlIG9uIGVhY2ggY29ubmVjdGVkIHNlcnZlci4gVGhlIGNhbGxiYWNrIHNpZ25hdHVyZSBpczpcbiAgICpcbiAgICogICAgIGNhbGxiYWNrKGxhc3RFcnIsIHJlc3VsdHMpXG4gICAqXG4gICAqIHdoZXJlIF9sYXN0RXJyXyBpcyB0aGUgbGFzdCBlcnJvciBlbmNvdW50ZXJlZCAob3IgbnVsbCwgaW4gdGhlIGNvbW1vbiBjYXNlXG4gICAqIG9mIG5vIGVycm9ycykuIF9yZXN1bHRzXyBpcyBhIGRpY3Rpb25hcnkgbWFwcGluZyBgXCJob3N0bmFtZTpwb3J0XCJgIHRvIGVpdGhlclxuICAgKiBgdHJ1ZWAgKGlmIHRoZSBvcGVyYXRpb24gd2FzIHN1Y2Nlc3NmdWwpLCBvciBhbiBlcnJvci5cbiAgICogQHBhcmFtIGNhbGxiYWNrXG4gICAqL1xuICBmbHVzaCgpOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIGJvb2xlYW4gfCBFcnJvcj4+O1xuICBmbHVzaChcbiAgICBjYWxsYmFjazogKFxuICAgICAgZXJyOiBFcnJvciB8IG51bGwsXG4gICAgICByZXN1bHRzOiBSZWNvcmQ8c3RyaW5nLCBib29sZWFuIHwgRXJyb3I+XG4gICAgKSA9PiB2b2lkXG4gICk6IHZvaWQ7XG4gIGZsdXNoKFxuICAgIGNhbGxiYWNrPzogKFxuICAgICAgZXJyOiBFcnJvciB8IG51bGwsXG4gICAgICByZXN1bHRzOiBSZWNvcmQ8c3RyaW5nLCBib29sZWFuIHwgRXJyb3I+XG4gICAgKSA9PiB2b2lkXG4gICkge1xuICAgIGlmIChjYWxsYmFjayA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm4gcHJvbWlzaWZ5KChjYWxsYmFjaykgPT4ge1xuICAgICAgICB0aGlzLmZsdXNoKGZ1bmN0aW9uIChlcnIsIHJlc3VsdHMpIHtcbiAgICAgICAgICBjYWxsYmFjayhlcnIsIHJlc3VsdHMpO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH1cbiAgICAvLyBUT0RPOiBzdXBwb3J0IGV4cGlyYXRpb25cbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoMHgwOCwgXCJcIiwgXCJcIiwgXCJcIiwgdGhpcy5zZXEpO1xuICAgIGxldCBjb3VudCA9IHRoaXMuc2VydmVycy5sZW5ndGg7XG4gICAgY29uc3QgcmVzdWx0OiBSZWNvcmQ8c3RyaW5nLCBib29sZWFuIHwgRXJyb3I+ID0ge307XG4gICAgbGV0IGxhc3RFcnI6IEVycm9yIHwgbnVsbCA9IG51bGw7XG5cbiAgICBjb25zdCBoYW5kbGVGbHVzaCA9IGZ1bmN0aW9uIChzZXE6IG51bWJlciwgc2VydjogU2VydmVyKSB7XG4gICAgICBzZXJ2Lm9uUmVzcG9uc2Uoc2VxLCBmdW5jdGlvbiAoLyogcmVzcG9uc2UgKi8pIHtcbiAgICAgICAgY291bnQgLT0gMTtcbiAgICAgICAgcmVzdWx0W3NlcnYuaG9zdHBvcnRTdHJpbmcoKV0gPSB0cnVlO1xuICAgICAgICBpZiAoY2FsbGJhY2sgJiYgY291bnQgPT09IDApIHtcbiAgICAgICAgICBjYWxsYmFjayhsYXN0RXJyLCByZXN1bHQpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHNlcnYub25FcnJvcihzZXEsIGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgICAgY291bnQgLT0gMTtcbiAgICAgICAgbGFzdEVyciA9IGVycjtcbiAgICAgICAgcmVzdWx0W3NlcnYuaG9zdHBvcnRTdHJpbmcoKV0gPSBlcnI7XG4gICAgICAgIGlmIChjYWxsYmFjayAmJiBjb3VudCA9PT0gMCkge1xuICAgICAgICAgIGNhbGxiYWNrKGxhc3RFcnIsIHJlc3VsdCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgc2Vydi53cml0ZShyZXF1ZXN0KTtcbiAgICB9O1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnNlcnZlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGhhbmRsZUZsdXNoKHRoaXMuc2VxLCB0aGlzLnNlcnZlcnNbaV0pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTVEFUU19XSVRIX0tFWVxuICAgKlxuICAgKiBTZW5kcyBhIG1lbWNhY2hlIHN0YXRzIGNvbW1hbmQgd2l0aCBhIGtleSB0byBlYWNoIGNvbm5lY3RlZCBzZXJ2ZXIuIFRoZVxuICAgKiBjYWxsYmFjayBpcyBpbnZva2VkICoqT05DRSBQRVIgU0VSVkVSKiogYW5kIGhhcyB0aGUgc2lnbmF0dXJlOlxuICAgKlxuICAgKiAgICAgY2FsbGJhY2soZXJyLCBzZXJ2ZXIsIHN0YXRzKVxuICAgKlxuICAgKiBfc2VydmVyXyBpcyB0aGUgYFwiaG9zdG5hbWU6cG9ydFwiYCBvZiB0aGUgc2VydmVyLCBhbmQgX3N0YXRzXyBpcyBhIGRpY3Rpb25hcnlcbiAgICogbWFwcGluZyB0aGUgc3RhdCBuYW1lIHRvIHRoZSB2YWx1ZSBvZiB0aGUgc3RhdGlzdGljIGFzIGEgc3RyaW5nLlxuICAgKiBAcGFyYW0ga2V5XG4gICAqIEBwYXJhbSBjYWxsYmFja1xuICAgKi9cbiAgc3RhdHNXaXRoS2V5KFxuICAgIGtleTogc3RyaW5nLFxuICAgIGNhbGxiYWNrPzogKFxuICAgICAgZXJyOiBFcnJvciB8IG51bGwsXG4gICAgICBzZXJ2ZXI6IHN0cmluZyxcbiAgICAgIHN0YXRzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+IHwgbnVsbFxuICAgICkgPT4gdm9pZFxuICApOiB2b2lkIHtcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoMHgxMCwga2V5LCBcIlwiLCBcIlwiLCB0aGlzLnNlcSk7XG5cbiAgICBjb25zdCBoYW5kbGVTdGF0cyA9IChzZXE6IG51bWJlciwgc2VydjogU2VydmVyKSA9PiB7XG4gICAgICBjb25zdCByZXN1bHQ6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcbiAgICAgIGNvbnN0IGhhbmRsZTogT25SZXNwb25zZUNhbGxiYWNrID0gKHJlc3BvbnNlKSA9PiB7XG4gICAgICAgIC8vIGVuZCBvZiBzdGF0IHJlc3BvbnNlc1xuICAgICAgICBpZiAocmVzcG9uc2UuaGVhZGVyLnRvdGFsQm9keUxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgICAgY2FsbGJhY2sobnVsbCwgc2Vydi5ob3N0cG9ydFN0cmluZygpLCByZXN1bHQpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgLy8gcHJvY2VzcyBzaW5nbGUgc3RhdCBsaW5lIHJlc3BvbnNlXG4gICAgICAgIHN3aXRjaCAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cykge1xuICAgICAgICAgIGNhc2UgUmVzcG9uc2VTdGF0dXMuU1VDQ0VTUzpcbiAgICAgICAgICAgIHJlc3VsdFtyZXNwb25zZS5rZXkudG9TdHJpbmcoKV0gPSByZXNwb25zZS52YWwudG9TdHJpbmcoKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICBjb25zdCBlcnJvciA9IHRoaXMuaGFuZGxlUmVzcG9uc2VFcnJvcihcbiAgICAgICAgICAgICAgYFNUQVRTICgke2tleX0pYCxcbiAgICAgICAgICAgICAgcmVzcG9uc2UuaGVhZGVyLnN0YXR1cyxcbiAgICAgICAgICAgICAgdW5kZWZpbmVkXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgICAgICAgIGNhbGxiYWNrKGVycm9yLCBzZXJ2Lmhvc3Rwb3J0U3RyaW5nKCksIG51bGwpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9O1xuICAgICAgaGFuZGxlLnF1aWV0ID0gdHJ1ZTtcblxuICAgICAgc2Vydi5vblJlc3BvbnNlKHNlcSwgaGFuZGxlKTtcbiAgICAgIHNlcnYub25FcnJvcihzZXEsIGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgICAgY2FsbGJhY2soZXJyLCBzZXJ2Lmhvc3Rwb3J0U3RyaW5nKCksIG51bGwpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHNlcnYud3JpdGUocmVxdWVzdCk7XG4gICAgfTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5zZXJ2ZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBoYW5kbGVTdGF0cyh0aGlzLnNlcSwgdGhpcy5zZXJ2ZXJzW2ldKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU1RBVFNcbiAgICpcbiAgICogRmV0Y2hlcyBtZW1jYWNoZSBzdGF0cyBmcm9tIGVhY2ggY29ubmVjdGVkIHNlcnZlci4gVGhlIGNhbGxiYWNrIGlzIGludm9rZWRcbiAgICogKipPTkNFIFBFUiBTRVJWRVIqKiBhbmQgaGFzIHRoZSBzaWduYXR1cmU6XG4gICAqXG4gICAqICAgICBjYWxsYmFjayhlcnIsIHNlcnZlciwgc3RhdHMpXG4gICAqXG4gICAqIF9zZXJ2ZXJfIGlzIHRoZSBgXCJob3N0bmFtZTpwb3J0XCJgIG9mIHRoZSBzZXJ2ZXIsIGFuZCBfc3RhdHNfIGlzIGFcbiAgICogZGljdGlvbmFyeSBtYXBwaW5nIHRoZSBzdGF0IG5hbWUgdG8gdGhlIHZhbHVlIG9mIHRoZSBzdGF0aXN0aWMgYXMgYSBzdHJpbmcuXG4gICAqIEBwYXJhbSBjYWxsYmFja1xuICAgKi9cbiAgc3RhdHMoXG4gICAgY2FsbGJhY2s/OiAoXG4gICAgICBlcnI6IEVycm9yIHwgbnVsbCxcbiAgICAgIHNlcnZlcjogc3RyaW5nLFxuICAgICAgc3RhdHM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gfCBudWxsXG4gICAgKSA9PiB2b2lkXG4gICk6IHZvaWQge1xuICAgIHRoaXMuc3RhdHNXaXRoS2V5KFwiXCIsIGNhbGxiYWNrKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSRVNFVF9TVEFUU1xuICAgKlxuICAgKiBSZXNldCB0aGUgc3RhdGlzdGljcyBlYWNoIHNlcnZlciBpcyBrZWVwaW5nIGJhY2sgdG8gemVyby4gVGhpcyBkb2Vzbid0IGNsZWFyXG4gICAqIHN0YXRzIHN1Y2ggYXMgaXRlbSBjb3VudCwgYnV0IHRlbXBvcmFyeSBzdGF0cyBzdWNoIGFzIHRvdGFsIG51bWJlciBvZlxuICAgKiBjb25uZWN0aW9ucyBvdmVyIHRpbWUuXG4gICAqXG4gICAqIFRoZSBjYWxsYmFjayBpcyBpbnZva2VkICoqT05DRSBQRVIgU0VSVkVSKiogYW5kIGhhcyB0aGUgc2lnbmF0dXJlOlxuICAgKlxuICAgKiAgICAgY2FsbGJhY2soZXJyLCBzZXJ2ZXIpXG4gICAqXG4gICAqIF9zZXJ2ZXJfIGlzIHRoZSBgXCJob3N0bmFtZTpwb3J0XCJgIG9mIHRoZSBzZXJ2ZXIuXG4gICAqIEBwYXJhbSBjYWxsYmFja1xuICAgKi9cbiAgcmVzZXRTdGF0cyhcbiAgICBjYWxsYmFjaz86IChcbiAgICAgIGVycjogRXJyb3IgfCBudWxsLFxuICAgICAgc2VydmVyOiBzdHJpbmcsXG4gICAgICBzdGF0czogUmVjb3JkPHN0cmluZywgc3RyaW5nPiB8IG51bGxcbiAgICApID0+IHZvaWRcbiAgKTogdm9pZCB7XG4gICAgdGhpcy5zdGF0c1dpdGhLZXkoXCJyZXNldFwiLCBjYWxsYmFjayk7XG4gIH1cblxuICAvKipcbiAgICogUVVJVFxuICAgKlxuICAgKiBDbG9zZXMgdGhlIGNvbm5lY3Rpb24gdG8gZWFjaCBzZXJ2ZXIsIG5vdGlmeWluZyB0aGVtIG9mIHRoaXMgaW50ZW50aW9uLiBOb3RlXG4gICAqIHRoYXQgcXVpdCBjYW4gcmFjZSBhZ2FpbnN0IGFscmVhZHkgb3V0c3RhbmRpbmcgcmVxdWVzdHMgd2hlbiB0aG9zZSByZXF1ZXN0c1xuICAgKiBmYWlsIGFuZCBhcmUgcmV0cmllZCwgbGVhZGluZyB0byB0aGUgcXVpdCBjb21tYW5kIHdpbm5pbmcgYW5kIGNsb3NpbmcgdGhlXG4gICAqIGNvbm5lY3Rpb24gYmVmb3JlIHRoZSByZXRyaWVzIGNvbXBsZXRlLlxuICAgKi9cbiAgcXVpdCgpIHtcbiAgICB0aGlzLmluY3JTZXEoKTtcbiAgICAvLyBUT0RPOiBOaWNlciBwZXJoYXBzIHRvIGRvIFFVSVRRICgweDE3KSBidXQgbmVlZCBhIG5ldyBjYWxsYmFjayBmb3Igd2hlblxuICAgIC8vIHdyaXRlIGlzIGRvbmUuXG4gICAgY29uc3QgcmVxdWVzdCA9IG1ha2VSZXF1ZXN0QnVmZmVyKDB4MDcsIFwiXCIsIFwiXCIsIFwiXCIsIHRoaXMuc2VxKTsgLy8gUVVJVFxuICAgIGxldCBzZXJ2O1xuXG4gICAgY29uc3QgaGFuZGxlUXVpdCA9IGZ1bmN0aW9uIChzZXE6IG51bWJlciwgc2VydjogU2VydmVyKSB7XG4gICAgICBzZXJ2Lm9uUmVzcG9uc2Uoc2VxLCBmdW5jdGlvbiAoLyogcmVzcG9uc2UgKi8pIHtcbiAgICAgICAgc2Vydi5jbG9zZSgpO1xuICAgICAgfSk7XG4gICAgICBzZXJ2Lm9uRXJyb3Ioc2VxLCBmdW5jdGlvbiAoLyogZXJyICovKSB7XG4gICAgICAgIHNlcnYuY2xvc2UoKTtcbiAgICAgIH0pO1xuICAgICAgc2Vydi53cml0ZShyZXF1ZXN0KTtcbiAgICB9O1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnNlcnZlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHNlcnYgPSB0aGlzLnNlcnZlcnNbaV07XG4gICAgICBoYW5kbGVRdWl0KHRoaXMuc2VxLCBzZXJ2KTtcbiAgICB9XG4gIH1cblxuICBfdmVyc2lvbihzZXJ2ZXI6IFNlcnZlcik6IFByb21pc2U8eyB2YWx1ZTogVmFsdWUgfCBudWxsIH0+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgdGhpcy5pbmNyU2VxKCk7XG4gICAgICBjb25zdCByZXF1ZXN0ID0gbWFrZVJlcXVlc3RCdWZmZXIoXG4gICAgICAgIGNvbnN0YW50cy5PUF9WRVJTSU9OLFxuICAgICAgICBcIlwiLFxuICAgICAgICBcIlwiLFxuICAgICAgICBcIlwiLFxuICAgICAgICB0aGlzLnNlcVxuICAgICAgKTtcbiAgICAgIHRoaXMucGVyZm9ybU9uU2VydmVyKHNlcnZlciwgcmVxdWVzdCwgdGhpcy5zZXEsIChlcnIsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICByZXR1cm4gcmVqZWN0KGVycik7XG4gICAgICAgIH1cblxuICAgICAgICBzd2l0Y2ggKHJlc3BvbnNlIS5oZWFkZXIuc3RhdHVzKSB7XG4gICAgICAgICAgY2FzZSBSZXNwb25zZVN0YXR1cy5TVUNDRVNTOlxuICAgICAgICAgICAgLyogVE9ETzogdGhpcyBpcyBidWdnZWQsIHdlIHNob3VsZCd0IHVzZSB0aGUgZGVzZXJpYWxpemVyIGhlcmUsIHNpbmNlIHZlcnNpb24gYWx3YXlzIHJldHVybnMgYSB2ZXJzaW9uIHN0cmluZy5cbiAgICAgICAgICAgICBUaGUgZGVzZXJpYWxpemVyIHNob3VsZCBvbmx5IGJlIHVzZWQgb24gdXNlciBrZXkgZGF0YS4gKi9cbiAgICAgICAgICAgIGNvbnN0IGRlc2VyaWFsaXplZCA9IHRoaXMuc2VyaWFsaXplci5kZXNlcmlhbGl6ZShcbiAgICAgICAgICAgICAgcmVzcG9uc2UhLmhlYWRlci5vcGNvZGUsXG4gICAgICAgICAgICAgIHJlc3BvbnNlIS52YWwsXG4gICAgICAgICAgICAgIHJlc3BvbnNlIS5leHRyYXNcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICByZXR1cm4gcmVzb2x2ZSh7IHZhbHVlOiBkZXNlcmlhbGl6ZWQudmFsdWUgfSk7XG4gICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHJldHVybiByZWplY3QoXG4gICAgICAgICAgICAgIHRoaXMuY3JlYXRlQW5kTG9nRXJyb3IoXCJWRVJTSU9OXCIsIHJlc3BvbnNlIS5oZWFkZXIuc3RhdHVzKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmVxdWVzdCB0aGUgc2VydmVyIHZlcnNpb24gZnJvbSB0aGUgXCJmaXJzdFwiIHNlcnZlciBpbiB0aGUgYmFja2VuZCBwb29sLlxuICAgKiBUaGUgc2VydmVyIHJlc3BvbmRzIHdpdGggYSBwYWNrZXQgY29udGFpbmluZyB0aGUgdmVyc2lvbiBzdHJpbmcgaW4gdGhlIGJvZHkgd2l0aCB0aGUgZm9sbG93aW5nIGZvcm1hdDogXCJ4LnkuelwiXG4gICAqL1xuICB2ZXJzaW9uKCk6IFByb21pc2U8eyB2YWx1ZTogVmFsdWUgfCBudWxsIH0+IHtcbiAgICBjb25zdCBzZXJ2ZXIgPSB0aGlzLnNlcnZlcktleVRvU2VydmVyKHRoaXMuc2VydmVyS2V5c1swXSk7XG4gICAgcmV0dXJuIHRoaXMuX3ZlcnNpb24oc2VydmVyKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXRyaWV2ZXMgdGhlIHNlcnZlciB2ZXJzaW9uIGZyb20gYWxsIHRoZSBzZXJ2ZXJzXG4gICAqIGluIHRoZSBiYWNrZW5kIHBvb2wsIGVycm9ycyBpZiBhbnkgb25lIG9mIHRoZW0gaGFzIGFuXG4gICAqIGVycm9yXG4gICAqIFxuICAgKiBDYWxsYmFja3MgZnVuY3Rpb25zIGFyZSBjYWxsZWQgYmVmb3JlL2FmdGVyIHdlIHBpbmcgbWVtY2FjaGVkXG4gICAqIGFuZCB1c2VkIHRvIGxvZyB3aGljaCBob3N0cyBhcmUgdGltaW5nIG91dC5cbiAgICovXG4gIGFzeW5jIHZlcnNpb25BbGwoY2FsbGJhY2tzPzoge1xuICAgIGJlZm9yZVBpbmc/OiAoc2VydmVyS2V5OiBzdHJpbmcpID0+IHZvaWQ7XG4gICAgYWZ0ZXJQaW5nPzogKHNlcnZlcktleTogc3RyaW5nKSA9PiB2b2lkO1xuICB9KTogUHJvbWlzZTx7XG4gICAgdmFsdWVzOiBSZWNvcmQ8c3RyaW5nLCBWYWx1ZSB8IG51bGw+O1xuICB9PiB7XG4gICAgY29uc3QgdmVyc2lvbk9iamVjdHMgPSBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIHRoaXMuc2VydmVyS2V5cy5tYXAoKHNlcnZlcktleSkgPT4ge1xuICAgICAgICBjb25zdCBzZXJ2ZXIgPSB0aGlzLnNlcnZlcktleVRvU2VydmVyKHNlcnZlcktleSk7XG4gICAgICAgIGNhbGxiYWNrcz8uYmVmb3JlUGluZz8uKHNlcnZlcktleSk7XG4gICAgICAgIHJldHVybiB0aGlzLl92ZXJzaW9uKHNlcnZlcikudGhlbigocmVzcG9uc2UpID0+IHtcbiAgICAgICAgICBjYWxsYmFja3M/LmFmdGVyUGluZz8uKHNlcnZlcktleSk7XG4gICAgICAgICAgcmV0dXJuIHsgc2VydmVyS2V5OiBzZXJ2ZXJLZXksIHZhbHVlOiByZXNwb25zZS52YWx1ZSB9O1xuICAgICAgICB9KTtcbiAgICAgIH0pXG4gICAgKTtcbiAgICBjb25zdCB2YWx1ZXMgPSB2ZXJzaW9uT2JqZWN0cy5yZWR1Y2UoKGFjY3VtdWxhdG9yLCB2ZXJzaW9uT2JqZWN0KSA9PiB7XG4gICAgICBhY2N1bXVsYXRvclt2ZXJzaW9uT2JqZWN0LnNlcnZlcktleV0gPSB2ZXJzaW9uT2JqZWN0LnZhbHVlO1xuICAgICAgcmV0dXJuIGFjY3VtdWxhdG9yO1xuICAgIH0sIHt9IGFzIFJlY29yZDxzdHJpbmcsIFZhbHVlIHwgbnVsbD4pO1xuICAgIHJldHVybiB7IHZhbHVlczogdmFsdWVzIH07XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldmVzIHRoZSBzZXJ2ZXIgdmVyc2lvbiAob2Z0ZW4gdXNlZCBhcyBhIHN0YXR1cyBjaGVjaykgZnJvbSBhbGwgdGhlXG4gICAqIHNlcnZlcnMgaW4gdGhlIGJhY2tlbmQgcG9vbC4gSWYgYW55IHNlcnZlcnMgZXJyb3IsIHRoZSBlcnJvciBpcyByZXR1cm5lZFxuICAgKiB3aXRoIHRoZSByZXN1bHRzLlxuICAgKlxuICAgKiBDYWxsYmFjayBmdW5jdGlvbnMgYXJlIGNhbGxlZCBiZWZvcmUvYWZ0ZXIgd2UgcGluZyBlYWNoIG1lbWNhY2hlZCBub2RlIHRvXG4gICAqIGFsbG93IGxvZ2dpbmcgb2YgaW5jcmVtZW50YWwgcmVzdWx0cyBhbmQgdGltZW91dHMuXG4gICAqXG4gICAqIEBwYXJhbSBjYWxsYmFja3NcbiAgICogQHJldHVybnMgXG4gICAqL1xuICBhc3luYyB2ZXJzaW9uQWxsV2l0aEVycm9ycyhjYWxsYmFja3M/OiB7XG4gICAgYmVmb3JlUGluZz86IChzZXJ2ZXJLZXk6IHN0cmluZykgPT4gdm9pZDtcbiAgICBhZnRlclBpbmc/OiAoc2VydmVyS2V5OiBzdHJpbmcsIGVycm9yPzogRXJyb3IpID0+IHZvaWQ7XG4gIH0pOiBQcm9taXNlPHtcbiAgICB2YWx1ZXM6IFJlY29yZDxzdHJpbmcsIHt2ZXJzaW9uPzogVmFsdWUgfCBudWxsLCBlcnJvcj86IEVycm9yfT5cbiAgfT4ge1xuICAgIGNvbnN0IHZlcnNpb25PYmplY3RzID0gYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICB0aGlzLnNlcnZlcktleXMubWFwKGFzeW5jIChzZXJ2ZXJLZXkpID0+IHtcbiAgICAgICAgY29uc3Qgc2VydmVyID0gdGhpcy5zZXJ2ZXJLZXlUb1NlcnZlcihzZXJ2ZXJLZXkpO1xuICAgICAgICBjYWxsYmFja3M/LmJlZm9yZVBpbmc/LihzZXJ2ZXJLZXkpO1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5fdmVyc2lvbihzZXJ2ZXIpO1xuICAgICAgICAgIGNhbGxiYWNrcz8uYWZ0ZXJQaW5nPy4oc2VydmVyS2V5KTtcbiAgICAgICAgICByZXR1cm4geyBzZXJ2ZXJLZXk6IHNlcnZlcktleSwgdmFsdWU6IHsgdmVyc2lvbjogcmVzcG9uc2UudmFsdWUgfSB9O1xuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICBjb25zdCBlcnJvciA9IGVyciBhcyBFcnJvcjtcbiAgICAgICAgICBjYWxsYmFja3M/LmFmdGVyUGluZz8uKHNlcnZlcktleSwgZXJyb3IpO1xuICAgICAgICAgIHJldHVybiB7IHNlcnZlcktleTogc2VydmVyS2V5LCB2YWx1ZTogeyBlcnJvciB9IH07XG4gICAgICAgIH1cbiAgICAgIH0pXG4gICAgKTtcbiAgICBjb25zdCB2YWx1ZXMgPSB2ZXJzaW9uT2JqZWN0cy5yZWR1Y2UoKGFjY3VtdWxhdG9yLCB2ZXJzaW9uT2JqZWN0KSA9PiB7XG4gICAgICBhY2N1bXVsYXRvclt2ZXJzaW9uT2JqZWN0LnNlcnZlcktleV0gPSB2ZXJzaW9uT2JqZWN0LnZhbHVlO1xuICAgICAgcmV0dXJuIGFjY3VtdWxhdG9yO1xuICAgIH0sIHt9IGFzIFJlY29yZDxzdHJpbmcsIHt2ZXJzaW9uPzogVmFsdWUgfCBudWxsLCBlcnJvcj86IEVycm9yfT4pO1xuICAgIHJldHVybiB7IHZhbHVlczogdmFsdWVzIH07XG4gIH1cblxuICAvKipcbiAgICogQ2xvc2VzIChhYnJ1cHRseSkgY29ubmVjdGlvbnMgdG8gYWxsIHRoZSBzZXJ2ZXJzLlxuICAgKiBAc2VlIHRoaXMucXVpdFxuICAgKi9cbiAgY2xvc2UoKSB7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnNlcnZlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHRoaXMuc2VydmVyc1tpXS5jbG9zZSgpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBQZXJmb3JtIGEgZ2VuZXJpYyBzaW5nbGUgcmVzcG9uc2Ugb3BlcmF0aW9uIChnZXQsIHNldCBldGMpIG9uIG9uZSBzZXJ2ZXJcbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IGtleSB0aGUga2V5IHRvIGhhc2ggdG8gZ2V0IGEgc2VydmVyIGZyb20gdGhlIHBvb2xcbiAgICogQHBhcmFtIHtidWZmZXJ9IHJlcXVlc3QgYSBidWZmZXIgY29udGFpbmluZyB0aGUgcmVxdWVzdFxuICAgKiBAcGFyYW0ge251bWJlcn0gc2VxIHRoZSBzZXF1ZW5jZSBudW1iZXIgb2YgdGhlIG9wZXJhdGlvbi4gSXQgaXMgdXNlZCB0byBwaW4gdGhlIGNhbGxiYWNrc1xuICAgICAgICAgICAgICAgICAgICAgICAgIHRvIGEgc3BlY2lmaWMgb3BlcmF0aW9uIGFuZCBzaG91bGQgbmV2ZXIgY2hhbmdlIGR1cmluZyBhIGBwZXJmb3JtYC5cbiAgICogQHBhcmFtIHtudW1iZXI/fSByZXRyaWVzIG51bWJlciBvZiB0aW1lcyB0byByZXRyeSByZXF1ZXN0IG9uIGZhaWx1cmVcbiAgICovXG4gIHBlcmZvcm0oXG4gICAga2V5OiBzdHJpbmcsXG4gICAgcmVxdWVzdDogQnVmZmVyLFxuICAgIHNlcTogbnVtYmVyLFxuICAgIHJldHJpZXM/OiBudW1iZXJcbiAgKTogUHJvbWlzZTxNZXNzYWdlPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGNvbnN0IHNlcnZlcktleSA9IHRoaXMubG9va3VwS2V5VG9TZXJ2ZXJLZXkoa2V5KTtcbiAgICAgIGNvbnN0IHNlcnZlciA9IHRoaXMuc2VydmVyS2V5VG9TZXJ2ZXIoc2VydmVyS2V5KTtcblxuICAgICAgaWYgKCFzZXJ2ZXIpIHtcbiAgICAgICAgcmV0dXJuIHJlamVjdChuZXcgRXJyb3IoXCJObyBzZXJ2ZXJzIGF2YWlsYWJsZVwiKSk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMucGVyZm9ybU9uU2VydmVyKFxuICAgICAgICBzZXJ2ZXIsXG4gICAgICAgIHJlcXVlc3QsXG4gICAgICAgIHNlcSxcbiAgICAgICAgKGVycm9yLCByZXNwb25zZSkgPT4ge1xuICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgcmV0dXJuIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJlc29sdmUocmVzcG9uc2UhKTtcbiAgICAgICAgfSxcbiAgICAgICAgcmV0cmllc1xuICAgICAgKTtcbiAgICB9KTtcbiAgfVxuXG4gIHBlcmZvcm1PblNlcnZlcihcbiAgICBzZXJ2ZXI6IFNlcnZlcixcbiAgICByZXF1ZXN0OiBCdWZmZXIsXG4gICAgc2VxOiBudW1iZXIsXG4gICAgY2FsbGJhY2s6IFJlc3BvbnNlT3JFcnJvckNhbGxiYWNrLFxuICAgIHJldHJpZXM6IG51bWJlciA9IDBcbiAgKSB7XG4gICAgY29uc3QgX3RoaXMgPSB0aGlzO1xuXG4gICAgcmV0cmllcyA9IHJldHJpZXMgfHwgdGhpcy5vcHRpb25zLnJldHJpZXM7XG4gICAgY29uc3Qgb3JpZ1JldHJpZXMgPSB0aGlzLm9wdGlvbnMucmV0cmllcztcbiAgICBjb25zdCBsb2dnZXIgPSB0aGlzLm9wdGlvbnMubG9nZ2VyO1xuICAgIGNvbnN0IHJldHJ5X2RlbGF5ID0gdGhpcy5vcHRpb25zLnJldHJ5X2RlbGF5O1xuXG4gICAgY29uc3QgcmVzcG9uc2VIYW5kbGVyOiBPblJlc3BvbnNlQ2FsbGJhY2sgPSBmdW5jdGlvbiAocmVzcG9uc2UpIHtcbiAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICBjYWxsYmFjayhudWxsLCByZXNwb25zZSk7XG4gICAgICB9XG4gICAgfTtcblxuICAgIGNvbnN0IGVycm9ySGFuZGxlcjogT25FcnJvckNhbGxiYWNrID0gZnVuY3Rpb24gKGVycm9yKSB7XG4gICAgICBpZiAoLS1yZXRyaWVzID4gMCkge1xuICAgICAgICAvLyBXYWl0IGZvciByZXRyeV9kZWxheVxuICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICBfdGhpcy5wZXJmb3JtT25TZXJ2ZXIoc2VydmVyLCByZXF1ZXN0LCBzZXEsIGNhbGxiYWNrLCByZXRyaWVzKTtcbiAgICAgICAgfSwgMTAwMCAqIHJldHJ5X2RlbGF5KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGxvZ2dlci5sb2coXG4gICAgICAgICAgXCJNZW1KUzogU2VydmVyIDxcIiArXG4gICAgICAgICAgICBzZXJ2ZXIuaG9zdHBvcnRTdHJpbmcoKSArXG4gICAgICAgICAgICBcIj4gZmFpbGVkIGFmdGVyIChcIiArXG4gICAgICAgICAgICBvcmlnUmV0cmllcyArXG4gICAgICAgICAgICBcIikgcmV0cmllcyB3aXRoIGVycm9yIC0gXCIgK1xuICAgICAgICAgICAgZXJyb3IubWVzc2FnZVxuICAgICAgICApO1xuICAgICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgICBjYWxsYmFjayhlcnJvciwgbnVsbCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9O1xuXG4gICAgc2VydmVyLm9uUmVzcG9uc2Uoc2VxLCByZXNwb25zZUhhbmRsZXIpO1xuICAgIHNlcnZlci5vbkVycm9yKHNlcSwgZXJyb3JIYW5kbGVyKTtcbiAgICBzZXJ2ZXIud3JpdGUocmVxdWVzdCk7XG4gIH1cblxuICAvLyBJbmNyZW1lbnQgdGhlIHNlcSB2YWx1ZVxuICBpbmNyU2VxKCkge1xuICAgIHRoaXMuc2VxKys7XG5cbiAgICAvLyBXcmFwIGB0aGlzLnNlcWAgdG8gMzItYml0cyBzaW5jZSB0aGUgZmllbGQgd2UgZml0IGl0IGludG8gaXMgb25seSAzMi1iaXRzLlxuICAgIHRoaXMuc2VxICY9IDB4ZmZmZmZmZmY7XG5cbiAgICByZXR1cm4gdGhpcy5zZXE7XG4gIH1cblxuICBwcml2YXRlIGNyZWF0ZUFuZExvZ0Vycm9yKFxuICAgIGNvbW1hbmROYW1lOiBzdHJpbmcsXG4gICAgcmVzcG9uc2VTdGF0dXM6IFJlc3BvbnNlU3RhdHVzIHwgdW5kZWZpbmVkXG4gICk6IEVycm9yIHtcbiAgICBjb25zdCBlcnJvck1lc3NhZ2UgPSBgTWVtSlMgJHtjb21tYW5kTmFtZX06ICR7Y29uc3RhbnRzLnJlc3BvbnNlU3RhdHVzVG9TdHJpbmcoXG4gICAgICByZXNwb25zZVN0YXR1c1xuICAgICl9YDtcbiAgICB0aGlzLm9wdGlvbnMubG9nZ2VyLmxvZyhlcnJvck1lc3NhZ2UpO1xuICAgIHJldHVybiBuZXcgRXJyb3IoZXJyb3JNZXNzYWdlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBMb2cgYW4gZXJyb3IgdG8gdGhlIGxvZ2dlciwgdGhlbiByZXR1cm4gdGhlIGVycm9yLlxuICAgKiBJZiBhIGNhbGxiYWNrIGlzIGdpdmVuLCBjYWxsIGl0IHdpdGggY2FsbGJhY2soZXJyb3IsIG51bGwpLlxuICAgKi9cbiAgcHJpdmF0ZSBoYW5kbGVSZXNwb25zZUVycm9yKFxuICAgIGNvbW1hbmROYW1lOiBzdHJpbmcsXG4gICAgcmVzcG9uc2VTdGF0dXM6IFJlc3BvbnNlU3RhdHVzIHwgdW5kZWZpbmVkLFxuICAgIGNhbGxiYWNrOiB1bmRlZmluZWQgfCAoKGVycm9yOiBFcnJvciB8IG51bGwsIG90aGVyOiBudWxsKSA9PiB2b2lkKVxuICApOiBFcnJvciB7XG4gICAgY29uc3QgZXJyb3IgPSB0aGlzLmNyZWF0ZUFuZExvZ0Vycm9yKGNvbW1hbmROYW1lLCByZXNwb25zZVN0YXR1cyk7XG4gICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICBjYWxsYmFjayhlcnJvciwgbnVsbCk7XG4gICAgfVxuICAgIHJldHVybiBlcnJvcjtcbiAgfVxufVxuXG5leHBvcnQgeyBDbGllbnQsIFNlcnZlciwgVXRpbHMsIEhlYWRlciB9O1xuIl19 \ No newline at end of file From aab777826c6efd7dd5cf66cc093483d8b6ec4d2d Mon Sep 17 00:00:00 2001 From: Ben Hughes Date: Thu, 16 Nov 2023 08:33:29 -0500 Subject: [PATCH 77/79] Add tests --- src/test/client_test.ts | 55 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/src/test/client_test.ts b/src/test/client_test.ts index 19a0d1c..2b57783 100644 --- a/src/test/client_test.ts +++ b/src/test/client_test.ts @@ -1747,3 +1747,58 @@ tap.only("VersionAllSomeFailed", function (t) { assertor(err); }); }); + +test("VersionAllWithErrorsSuccessful", function (t) { + const dummyServer1 = makeDummyVersionServer(t, "dummyServer1", "1.0.0"); + const dummyServer2 = makeDummyVersionServer(t, "dummyServer2", "2.0.0"); + const dummyServer3 = makeDummyVersionServer(t, "dummyServer3", "3.0.0"); + + const client = makeClient([dummyServer1, dummyServer2, dummyServer3]); + const assertor = function ( + val?: Record | null + ) { + t.deepEqual( + { + "dummyServer1:undefined": { version: "1.0.0" }, + "dummyServer2:undefined": { version: "2.0.0" }, + "dummyServer3:undefined": { version: "3.0.0" }, + }, + val + ); + }; + + return client.versionAllWithErrors().then(function (res) { + assertor(res.values); + }); +}); + +tap.only("VersionAllWithErrorsSomeFailed", function (t) { + const dummyServer1 = makeDummyVersionServer(t, "dummyServer1", "1.0.0"); + const dummyServer2 = makeDummyVersionServer(t, "dummyServer2", "2.0.0"); + dummyServer2.write = function () { + dummyServer2.error({ + name: "ErrorName", + message: "This is an expected error.", + }); + }; + const dummyServer3 = makeDummyVersionServer(t, "dummyServer3", "3.0.0"); + + const client = makeClient([dummyServer1, dummyServer2, dummyServer3]); + const assertor = function ( + val?: Record | null + ) { + t.deepEqual( + { + "dummyServer1:undefined": { version: "1.0.0" }, + "dummyServer2:undefined": { error: { name: "ErrorName", message: "This is an expected error." } }, + "dummyServer3:undefined": { version: "3.0.0" }, + }, + val + ); + }; + + + return client.versionAllWithErrors().then(function (res) { + assertor(res.values); + }); +}); From 02dabaa2e09e81613fb36d2f1581951e7b52a0cd Mon Sep 17 00:00:00 2001 From: Ben Hughes Date: Thu, 16 Nov 2023 11:29:00 -0500 Subject: [PATCH 78/79] bump version --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9534ba9..1963366 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "memjs", - "version": "1.2.3", + "version": "1.2.4", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "memjs", - "version": "1.2.3", + "version": "1.2.4", "license": "MIT", "devDependencies": { "@types/node": "12.20.7", diff --git a/package.json b/package.json index 4268835..a24179c 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "author": "Amit Levy", "name": "memjs", "description": "A memcache client for node using the binary protocol and SASL authentication", - "version": "1.2.3", + "version": "1.2.4", "license": "MIT", "homepage": "http://github.com/memcachier/memjs", "keywords": [ From 7a521a2ae9929c7ddbfda720deaf65e42be694fc Mon Sep 17 00:00:00 2001 From: Ben Hughes Date: Wed, 14 Feb 2024 13:45:10 -0500 Subject: [PATCH 79/79] Use sock.destroy() instead of end() on timeout, 1.2.4-NOTION.1 Unifies error handling/resetting state in error() --- lib/memjs/server.d.ts.map | 2 +- lib/memjs/server.js | 14 +++++++------- package-lock.json | 4 ++-- package.json | 2 +- src/memjs/server.ts | 12 ++++++------ 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/lib/memjs/server.d.ts.map b/lib/memjs/server.d.ts.map index 31f9e76..6128b8f 100644 --- a/lib/memjs/server.d.ts.map +++ b/lib/memjs/server.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/memjs/server.ts"],"names":[],"mappings":";AAAA,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAKL,OAAO,EACR,MAAM,SAAS,CAAC;AAEjB,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,aAAK,GAAG,GAAG,MAAM,CAAC;AAElB,MAAM,WAAW,iBAAiB;IAChC,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,MAAM,WAAW,kBAAkB;IACjC,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACzB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;CACtB;AAED,qBAAa,MAAO,SAAQ,MAAM,CAAC,YAAY;IAC7C,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IAClC,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;IACpB,gBAAgB,EAAE,iBAAiB,EAAE,CAAC;IACtC,iBAAiB,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,kBAAkB,CAAA;KAAE,CAAC;IACzD,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,cAAc,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,CAAA;KAAE,CAAC;IACnD,OAAO,EAAE,aAAa,CAAC;IACvB,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAE7B,OAAO,EAAE,GAAG,CAAC,MAAM,GAAG,SAAS,CAAC;gBAG9B,IAAI,EAAE,MAAM,EAEZ,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,EACtB,QAAQ,CAAC,EAAE,MAAM,EACjB,QAAQ,CAAC,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC;IAoClC,SAAS,CAAC,IAAI,EAAE,iBAAiB;IAIjC,UAAU,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,kBAAkB;IAI7C,OAAO,CAAC,QAAQ,EAAE,OAAO;IAczB,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,eAAe;IAIvC,KAAK,CAAC,GAAG,EAAE,KAAK;IAiBhB,QAAQ;IAKR,QAAQ;IAMR,cAAc,CAAC,OAAO,EAAE,MAAM;IAO9B,eAAe,CAAC,OAAO,EAAE,MAAM;IAyB/B,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,iBAAiB;IA2FzC,KAAK,CAAC,IAAI,EAAE,MAAM;IAelB,SAAS,CAAC,IAAI,EAAE,MAAM;IAMtB,KAAK;IAML,QAAQ;IAIR,cAAc;CAGf"} \ No newline at end of file +{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/memjs/server.ts"],"names":[],"mappings":";AAAA,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAKL,OAAO,EACR,MAAM,SAAS,CAAC;AAEjB,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,aAAK,GAAG,GAAG,MAAM,CAAC;AAElB,MAAM,WAAW,iBAAiB;IAChC,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,MAAM,WAAW,kBAAkB;IACjC,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACzB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;CACtB;AAED,qBAAa,MAAO,SAAQ,MAAM,CAAC,YAAY;IAC7C,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IAClC,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;IACpB,gBAAgB,EAAE,iBAAiB,EAAE,CAAC;IACtC,iBAAiB,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,kBAAkB,CAAA;KAAE,CAAC;IACzD,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,cAAc,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,CAAA;KAAE,CAAC;IACnD,OAAO,EAAE,aAAa,CAAC;IACvB,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAE7B,OAAO,EAAE,GAAG,CAAC,MAAM,GAAG,SAAS,CAAC;gBAG9B,IAAI,EAAE,MAAM,EAEZ,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,EACtB,QAAQ,CAAC,EAAE,MAAM,EACjB,QAAQ,CAAC,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC;IAoClC,SAAS,CAAC,IAAI,EAAE,iBAAiB;IAIjC,UAAU,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,kBAAkB;IAI7C,OAAO,CAAC,QAAQ,EAAE,OAAO;IAczB,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,eAAe;IAIvC,KAAK,CAAC,GAAG,EAAE,KAAK;IAmBhB,QAAQ;IAKR,QAAQ;IAMR,cAAc,CAAC,OAAO,EAAE,MAAM;IAO9B,eAAe,CAAC,OAAO,EAAE,MAAM;IAyB/B,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,iBAAiB;IA2FzC,KAAK,CAAC,IAAI,EAAE,MAAM;IAelB,SAAS,CAAC,IAAI,EAAE,MAAM;IAMtB,KAAK;IAQL,QAAQ;IAIR,cAAc;CAGf"} \ No newline at end of file diff --git a/lib/memjs/server.js b/lib/memjs/server.js index 5c23615..3663474 100644 --- a/lib/memjs/server.js +++ b/lib/memjs/server.js @@ -66,12 +66,14 @@ class Server extends events_1.default.EventEmitter { } error(err) { const errcalls = this.errorCallbacks; + // reset all states except host, port, options, username, password + this.responseBuffer = Buffer.from([]); + this.connected = false; + this.timeoutSet = false; this.connectCallbacks = []; this.responseCallbacks = {}; this.requestTimeouts = []; this.errorCallbacks = {}; - this.timeoutSet = false; - this.responseBuffer = Buffer.from([]); if (this._socket) { this._socket.destroy(); delete this._socket; @@ -223,6 +225,8 @@ class Server extends events_1.default.EventEmitter { } close() { if (this._socket) { + // TODO: this should probably be destroy() in at least some, if not all, + // cases. this._socket.end(); } } @@ -248,10 +252,6 @@ const timeoutHandler = function (server, sock) { const soonestTimeout = server.requestTimeouts[0]; if (soonestTimeout <= now) { // timeout occurred! - sock.end(); - server.connected = false; - server._socket = undefined; - server.timeoutSet = false; server.error(new Error("socket timed out waiting on response.")); } else { @@ -262,4 +262,4 @@ const timeoutHandler = function (server, sock) { }); } }; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL21lbWpzL3NlcnZlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSw4Q0FBc0I7QUFDdEIsb0RBQTRCO0FBQzVCLG1DQU1pQjtBQTBCakIsTUFBYSxNQUFPLFNBQVEsZ0JBQU0sQ0FBQyxZQUFZO0lBZ0I3QyxZQUNFLElBQVk7SUFDWixnR0FBZ0c7SUFDaEcsSUFBc0IsRUFDdEIsUUFBaUIsRUFDakIsUUFBaUIsRUFDakIsT0FBZ0M7UUFFaEMsS0FBSyxFQUFFLENBQUM7UUFDUixJQUFJLENBQUMsY0FBYyxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDdEMsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUM7UUFDakIsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUM7UUFDakIsSUFBSSxDQUFDLFNBQVMsR0FBRyxLQUFLLENBQUM7UUFDdkIsSUFBSSxDQUFDLFVBQVUsR0FBRyxLQUFLLENBQUM7UUFDeEIsSUFBSSxDQUFDLGdCQUFnQixHQUFHLEVBQUUsQ0FBQztRQUMzQixJQUFJLENBQUMsaUJBQWlCLEdBQUcsRUFBRSxDQUFDO1FBQzVCLElBQUksQ0FBQyxlQUFlLEdBQUcsRUFBRSxDQUFDO1FBQzFCLElBQUksQ0FBQyxjQUFjLEdBQUcsRUFBRSxDQUFDO1FBQ3pCLElBQUksQ0FBQyxPQUFPLEdBQUcsYUFBSyxDQUFDLE9BQU8sSUFBSSxFQUFFLEVBQUU7WUFDbEMsT0FBTyxFQUFFLEdBQUc7WUFDWixTQUFTLEVBQUUsS0FBSztZQUNoQixjQUFjLEVBQUUsRUFBRTtTQUNuQixDQUFrQixDQUFDO1FBQ3BCLElBQ0UsSUFBSSxDQUFDLE9BQU8sQ0FBQyxXQUFXLEtBQUssU0FBUztZQUN0QyxJQUFJLENBQUMsT0FBTyxDQUFDLFdBQVcsS0FBSyxJQUFJLEVBQ2pDO1lBQ0EsSUFBSSxDQUFDLE9BQU8sQ0FBQyxXQUFX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LENBQUMsQ0FBQztRQUMvQixDQUFDLENBQUMsQ0FBQztLQUNKO0FBQ0gsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IG5ldCBmcm9tIFwibmV0XCI7XG5pbXBvcnQgZXZlbnRzIGZyb20gXCJldmVudHNcIjtcbmltcG9ydCB7XG4gIG1ha2VSZXF1ZXN0QnVmZmVyLFxuICBwYXJzZU1lc3NhZ2UsXG4gIG1lcmdlLFxuICB0aW1lc3RhbXAsXG4gIE1lc3NhZ2UsXG59IGZyb20gXCIuL3V0aWxzXCI7XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2VydmVyT3B0aW9ucyB7XG4gIHRpbWVvdXQ6IG51bWJlcjtcbiAga2VlcEFsaXZlOiBib29sZWFuO1xuICBrZWVwQWxpdmVEZWxheTogbnVtYmVyO1xuICBjb25udGltZW91dDogbnVtYmVyO1xuICB1c2VybmFtZT86IHN0cmluZztcbiAgcGFzc3dvcmQ/OiBzdHJpbmc7XG59XG5cbnR5cGUgU2VxID0gbnVtYmVyO1xuXG5leHBvcnQgaW50ZXJmYWNlIE9uQ29ubmVjdENhbGxiYWNrIHtcbiAgKHNvY2tldDogbmV0LlNvY2tldCk6IHZvaWQ7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgT25SZXNwb25zZUNhbGxiYWNrIHtcbiAgKG1lc3NhZ2U6IE1lc3NhZ2UpOiB2b2lkO1xuICBxdWlldD86IGJvb2xlYW47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgT25FcnJvckNhbGxiYWNrIHtcbiAgKGVycm9yOiBFcnJvcik6IHZvaWQ7XG59XG5cbmV4cG9ydCBjbGFzcyBTZXJ2ZXIgZXh0ZW5kcyBldmVudHMuRXZlbnRFbWl0dGVyIHtcbiAgcmVzcG9uc2VCdWZmZXI6IEJ1ZmZlcjtcbiAgaG9zdDogc3RyaW5nO1xuICBwb3J0OiBzdHJpbmcgfCBudW1iZXIgfCB1bmRlZmluZWQ7XG4gIGNvbm5lY3RlZDogYm9vbGVhbjtcbiAgdGltZW91dFNldDogYm9vbGVhbjtcbiAgY29ubmVjdENhbGxiYWNrczogT25Db25uZWN0Q2FsbGJhY2tbXTtcbiAgcmVzcG9uc2VDYWxsYmFja3M6IHsgW3NlcTogc3RyaW5nXTogT25SZXNwb25zZUNhbGxiYWNrIH07XG4gIHJlcXVlc3RUaW1lb3V0czogbnVtYmVyW107XG4gIGVycm9yQ2FsbGJhY2tzOiB7IFtzZXE6IHN0cmluZ106IE9uRXJyb3JDYWxsYmFjayB9O1xuICBvcHRpb25zOiBTZXJ2ZXJPcHRpb25zO1xuICB1c2VybmFtZTogc3RyaW5nIHwgdW5kZWZpbmVkO1xuICBwYXNzd29yZDogc3RyaW5nIHwgdW5kZWZpbmVkO1xuXG4gIF9zb2NrZXQ6IG5ldC5Tb2NrZXQgfCB1bmRlZmluZWQ7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgaG9zdDogc3RyaW5nLFxuICAgIC8qIFRPRE86IGFsbG93aW5nIHBvcnQgdG8gYmUgc3RyaW5nIG9yIHVuZGVmaW5lZCBpcyB1c2VkIGJ5IHRoZSB0ZXN0cywgYnV0IHNlZW1zIGJhZCBvdmVyYWxsLiAqL1xuICAgIHBvcnQ/OiBzdHJpbmcgfCBudW1iZXIsXG4gICAgdXNlcm5hbWU/OiBzdHJpbmcsXG4gICAgcGFzc3dvcmQ/OiBzdHJpbmcsXG4gICAgb3B0aW9ucz86IFBhcnRpYWw8U2VydmVyT3B0aW9ucz5cbiAgKSB7XG4gICAgc3VwZXIoKTtcbiAgICB0aGlzLnJlc3BvbnNlQnVmZmVyID0gQnVmZmVyLmZyb20oW10pO1xuICAgIHRoaXMuaG9zdCA9IGhvc3Q7XG4gICAgdGhpcy5wb3J0ID0gcG9ydDtcbiAgICB0aGlzLmNvbm5lY3RlZCA9IGZhbHNlO1xuICAgIHRoaXMudGltZW91dFNldCA9IGZhbHNlO1xuICAgIHRoaXMuY29ubmVjdENhbGxiYWNrcyA9IFtdO1xuICAgIHRoaXMucmVzcG9uc2VDYWxsYmFja3MgPSB7fTtcbiAgICB0aGlzLnJlcXVlc3RUaW1lb3V0cyA9IFtdO1xuICAgIHRoaXMuZXJyb3JDYWxsYmFja3MgPSB7fTtcbiAgICB0aGlzLm9wdGlvbnMgPSBtZXJnZShvcHRpb25zIHx8IHt9LCB7XG4gICAgICB0aW1lb3V0OiAwLjUsXG4gICAgICBrZWVwQWxpdmU6IGZhbHNlLFxuICAgICAga2VlcEFsaXZlRGVsYXk6IDMwLFxuICAgIH0pIGFzIFNlcnZlck9wdGlvbnM7XG4gICAgaWYgKFxuICAgICAgdGhpcy5vcHRpb25zLmNvbm50aW1lb3V0ID09PSB1bmRlZmluZWQgfHxcbiAgICAgIHRoaXMub3B0aW9ucy5jb25udGltZW91dCA9PT0gbnVsbFxuICAgICkge1xuICAgICAgdGhpcy5vcHRpb25zLmNvbm50aW1lb3V0ID0gMiAqIHRoaXMub3B0aW9ucy50aW1lb3V0O1xuICAgIH1cbiAgICB0aGlzLnVzZXJuYW1lID1cbiAgICAgIHVzZXJuYW1lIHx8XG4gICAgICB0aGlzLm9wdGlvbnMudXNlcm5hbWUgfHxcbiAgICAgIHByb2Nlc3MuZW52Lk1FTUNBQ0hJRVJfVVNFUk5BTUUgfHxcbiAgICAgIHByb2Nlc3MuZW52Lk1FTUNBQ0hFX1VTRVJOQU1FO1xuICAgIHRoaXMucGFzc3dvcmQgPVxuICAgICAgcGFzc3dvcmQgfHxcbiAgICAgIHRoaXMub3B0aW9ucy5wYXNzd29yZCB8fFxuICAgICAgcHJvY2Vzcy5lbnYuTUVNQ0FDSElFUl9QQVNTV09SRCB8fFxuICAgICAgcHJvY2Vzcy5lbnYuTUVNQ0FDSEVfUEFTU1dPUkQ7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICBvbkNvbm5lY3QoZnVuYzogT25Db25uZWN0Q2FsbGJhY2spIHtcbiAgICB0aGlzLmNvbm5lY3RDYWxsYmFja3MucHVzaChmdW5jKTtcbiAgfVxuXG4gIG9uUmVzcG9uc2Uoc2VxOiBTZXEsIGZ1bmM6IE9uUmVzcG9uc2VDYWxsYmFjaykge1xuICAgIHRoaXMucmVzcG9uc2VDYWxsYmFja3Nbc2VxXSA9IGZ1bmM7XG4gIH1cblxuICByZXNwb25kKHJlc3BvbnNlOiBNZXNzYWdlKSB7XG4gICAgY29uc3QgY2FsbGJhY2sgPSB0aGlzLnJlc3BvbnNlQ2FsbGJhY2tzW3Jlc3BvbnNlLmhlYWRlci5vcGFxdWVdO1xuICAgIGlmICghY2FsbGJhY2spIHtcbiAgICAgIC8vIGluIGNhc2Ugb2YgYXV0aGVudGljYXRpb24sIG5vIGNhbGxiYWNrIGlzIHJlZ2lzdGVyZWRcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY2FsbGJhY2socmVzcG9uc2UpO1xuICAgIGlmICghY2FsbGJhY2sucXVpZXQgfHwgcmVzcG9uc2UuaGVhZGVyLnRvdGFsQm9keUxlbmd0aCA9PT0gMCkge1xuICAgICAgZGVsZXRlIHRoaXMucmVzcG9uc2VDYWxsYmFja3NbcmVzcG9uc2UuaGVhZGVyLm9wYXF1ZV07XG4gICAgICB0aGlzLnJlcXVlc3RUaW1lb3V0cy5zaGlmdCgpO1xuICAgICAgZGVsZXRlIHRoaXMuZXJyb3JDYWxsYmFja3NbcmVzcG9uc2UuaGVhZGVyLm9wYXF1ZV07XG4gICAgfVxuICB9XG5cbiAgb25FcnJvcihzZXE6IFNlcSwgZnVuYzogT25FcnJvckNhbGxiYWNrKSB7XG4gICAgdGhpcy5lcnJvckNhbGxiYWNrc1tzZXFdID0gZnVuYztcbiAgfVxuXG4gIGVycm9yKGVycjogRXJyb3IpIHtcbiAgICBjb25zdCBlcnJjYWxscyA9IHRoaXMuZXJyb3JDYWxsYmFja3M7XG4gICAgdGhpcy5jb25uZWN0Q2FsbGJhY2tzID0gW107XG4gICAgdGhpcy5yZXNwb25zZUNhbGxiYWNrcyA9IHt9O1xuICAgIHRoaXMucmVxdWVzdFRpbWVvdXRzID0gW107XG4gICAgdGhpcy5lcnJvckNhbGxiYWNrcyA9IHt9O1xuICAgIHRoaXMudGltZW91dFNldCA9IGZhbHNlO1xuICAgIHRoaXMucmVzcG9uc2VCdWZmZXIgPSBCdWZmZXIuZnJvbShbXSk7XG4gICAgaWYgKHRoaXMuX3NvY2tldCkge1xuICAgICAgdGhpcy5fc29ja2V0LmRlc3Ryb3koKTtcbiAgICAgIGRlbGV0ZSB0aGlzLl9zb2NrZXQ7XG4gICAgfVxuICAgIGZvciAobGV0IGVycmNhbGwgb2YgT2JqZWN0LnZhbHVlcyhlcnJjYWxscykpIHtcbiAgICAgIGVycmNhbGwoZXJyKTtcbiAgICB9XG4gIH1cblxuICBsaXN0U2FzbCgpIHtcbiAgICBjb25zdCBidWYgPSBtYWtlUmVxdWVzdEJ1ZmZlcigweDIwLCBcIlwiLCBcIlwiLCBcIlwiKTtcbiAgICB0aGlzLndyaXRlU0FTTChidWYpO1xuICB9XG5cbiAgc2FzbEF1dGgoKSB7XG4gICAgY29uc3QgYXV0aFN0ciA9IFwiXFx4MDBcIiArIHRoaXMudXNlcm5hbWUgKyBcIlxceDAwXCIgKyB0aGlzLnBhc3N3b3JkO1xuICAgIGNvbnN0IGJ1ZiA9IG1ha2VSZXF1ZXN0QnVmZmVyKDB4MjEsIFwiUExBSU5cIiwgXCJcIiwgYXV0aFN0cik7XG4gICAgdGhpcy53cml0ZVNBU0woYnVmKTtcbiAgfVxuXG4gIGFwcGVuZFRvQnVmZmVyKGRhdGFCdWY6IEJ1ZmZlcikge1xuICAgIGNvbnN0IG9sZCA9IHRoaXMucmVzcG9uc2VCdWZmZXI7XG4gICAgdGhpcy5yZXNwb25zZUJ1ZmZlciA9IEJ1ZmZlci5hbGxvYyhvbGQubGVuZ3RoICsgZGF0YUJ1Zi5sZW5ndGgpO1xuICAgIG9sZC5jb3B5KHRoaXMucmVzcG9uc2VCdWZmZXIsIDApO1xuICAgIGRhdGFCdWYuY29weSh0aGlzLnJlc3BvbnNlQnVmZmVyLCBvbGQubGVuZ3RoKTtcbiAgICByZXR1cm4gdGhpcy5yZXNwb25zZUJ1ZmZlcjtcbiAgfVxuICByZXNwb25zZUhhbmRsZXIoZGF0YUJ1ZjogQnVmZmVyKSB7XG4gICAgbGV0IHJlc3BvbnNlOiBNZXNzYWdlIHwgZmFsc2U7XG4gICAgdHJ5IHtcbiAgICAgIHJlc3BvbnNlID0gcGFyc2VNZXNzYWdlKHRoaXMuYXBwZW5kVG9CdWZmZXIoZGF0YUJ1ZikpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHRoaXMuZXJyb3IoZSBhcyBFcnJvcik7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgbGV0IHJlc3BMZW5ndGg6IG51bWJlcjtcbiAgICB3aGlsZSAocmVzcG9uc2UpIHtcbiAgICAgIGlmIChyZXNwb25zZS5oZWFkZXIub3Bjb2RlID09PSAweDIwKSB7XG4gICAgICAgIHRoaXMuc2FzbEF1dGgoKTtcbiAgICAgIH0gZWxzZSBpZiAocmVzcG9uc2UuaGVhZGVyLnN0YXR1cyA9PT0gKDB4MjAgYXMgYW55KSAvKiBUT0RPOiB3dGY/ICovKSB7XG4gICAgICAgIHRoaXMuZXJyb3IobmV3IEVycm9yKFwiTWVtY2FjaGVkIHNlcnZlciBhdXRoZW50aWNhdGlvbiBmYWlsZWQhXCIpKTtcbiAgICAgIH0gZWxzZSBpZiAocmVzcG9uc2UuaGVhZGVyLm9wY29kZSA9PT0gMHgyMSkge1xuICAgICAgICB0aGlzLmVtaXQoXCJhdXRoZW50aWNhdGVkXCIpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5yZXNwb25kKHJlc3BvbnNlKTtcbiAgICAgIH1cbiAgICAgIHJlc3BMZW5ndGggPSByZXNwb25zZS5oZWFkZXIudG90YWxCb2R5TGVuZ3RoICsgMjQ7XG4gICAgICB0aGlzLnJlc3BvbnNlQnVmZmVyID0gdGhpcy5yZXNwb25zZUJ1ZmZlci5zbGljZShyZXNwTGVuZ3RoKTtcbiAgICAgIHJlc3BvbnNlID0gcGFyc2VNZXNzYWdlKHRoaXMucmVzcG9uc2VCdWZmZXIpO1xuICAgIH1cbiAgfVxuICBzb2NrKHNhc2w6IGJvb2xlYW4sIGdvOiBPbkNvbm5lY3RDYWxsYmFjaykge1xuICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuXG4gICAgaWYgKCFzZWxmLl9zb2NrZXQpIHtcbiAgICAgIC8vIENBU0UgMTogY29tcGxldGVseSBuZXcgc29ja2V0XG4gICAgICBzZWxmLmNvbm5lY3RlZCA9IGZhbHNlO1xuICAgICAgc2VsZi5yZXNwb25zZUJ1ZmZlciA9IEJ1ZmZlci5mcm9tKFtdKTtcbiAgICAgIHNlbGYuX3NvY2tldCA9IG5ldC5jb25uZWN0KFxuICAgICAgICAvKiBUT0RPOiBhbGxvd2luZyBwb3J0IHRvIGJlIHN0cmluZyBvciB1bmRlZmluZWQgaXMgdXNlZCBieSB0aGUgdGVzdHMsIGJ1dCBzZWVtcyBiYWQgb3ZlcmFsbC4gKi9cbiAgICAgICAgdHlwZW9mIHRoaXMucG9ydCA9PT0gXCJzdHJpbmdcIlxuICAgICAgICAgID8gcGFyc2VJbnQodGhpcy5wb3J0LCAxMClcbiAgICAgICAgICA6IHRoaXMucG9ydCB8fCAxMTIxMSxcbiAgICAgICAgdGhpcy5ob3N0LFxuICAgICAgICBmdW5jdGlvbiAodGhpczogbmV0LlNvY2tldCkge1xuICAgICAgICAgIC8vIFNBU0wgYXV0aGVudGljYXRpb24gaGFuZGxlclxuICAgICAgICAgIHNlbGYub25jZShcImF1dGhlbnRpY2F0ZWRcIiwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKHNlbGYuX3NvY2tldCkge1xuICAgICAgICAgICAgICBjb25zdCBzb2NrZXQgPSBzZWxmLl9zb2NrZXQ7XG4gICAgICAgICAgICAgIHNlbGYuY29ubmVjdGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgLy8gY2FuY2VsIGNvbm5lY3Rpb24gdGltZW91dFxuICAgICAgICAgICAgICBzZWxmLl9zb2NrZXQuc2V0VGltZW91dCgwKTtcbiAgICAgICAgICAgICAgc2VsZi50aW1lb3V0U2V0ID0gZmFsc2U7XG4gICAgICAgICAgICAgIC8vIHJ1biBhY3R1YWwgcmVxdWVzdChzKVxuICAgICAgICAgICAgICBnbyhzZWxmLl9zb2NrZXQpO1xuICAgICAgICAgICAgICBzZWxmLmNvbm5lY3RDYWxsYmFja3MuZm9yRWFjaChmdW5jdGlvbiAoY2IpIHtcbiAgICAgICAgICAgICAgICBjYihzb2NrZXQpO1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgc2VsZi5jb25uZWN0Q2FsbGJhY2tzID0gW107XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICAvLyBzZXR1cCByZXNwb25zZSBoYW5kbGVyXG4gICAgICAgICAgdGhpcy5vbihcImRhdGFcIiwgZnVuY3Rpb24gKGRhdGFCdWYpIHtcbiAgICAgICAgICAgIHNlbGYucmVzcG9uc2VIYW5kbGVyKGRhdGFCdWYpO1xuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgLy8ga2ljayBvZiBTQVNMIGlmIG5lZWRlZFxuICAgICAgICAgIGlmIChzZWxmLnVzZXJuYW1lICYmIHNlbGYucGFzc3dvcmQpIHtcbiAgICAgICAgICAgIHNlbGYubGlzdFNhc2woKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc2VsZi5lbWl0KFwiYXV0aGVudGljYXRlZFwiKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICk7XG5cbiAgICAgIC8vIHNldHVwIGVycm9yIGhhbmRsZXJcbiAgICAgIHNlbGYuX3NvY2tldC5vbihcImVycm9yXCIsIGZ1bmN0aW9uIChlcnJvcikge1xuICAgICAgICBzZWxmLmVycm9yKGVycm9yKTtcbiAgICAgIH0pO1xuXG4gICAgICBzZWxmLl9zb2NrZXQub24oXCJjbG9zZVwiLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmIChPYmplY3Qua2V5cyhzZWxmLmVycm9yQ2FsbGJhY2tzKS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgc2VsZi5lcnJvcihuZXcgRXJyb3IoXCJzb2NrZXQgY2xvc2VkIHVuZXhwZWN0ZWRseS5cIikpO1xuICAgICAgICB9XG4gICAgICAgIHNlbGYuY29ubmVjdGVkID0gZmFsc2U7XG4gICAgICAgIHNlbGYucmVzcG9uc2VCdWZmZXIgPSBCdWZmZXIuZnJvbShbXSk7XG4gICAgICAgIGlmIChzZWxmLnRpbWVvdXRTZXQpIHtcbiAgICAgICAgICBzZWxmLl9zb2NrZXQ/LnNldFRpbWVvdXQoMCk7XG4gICAgICAgICAgc2VsZi50aW1lb3V0U2V0ID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgc2VsZi5fc29ja2V0ID0gdW5kZWZpbmVkO1xuICAgICAgfSk7XG5cbiAgICAgIC8vIHNldHVwIGNvbm5lY3Rpb24gdGltZW91dCBoYW5kbGVyXG4gICAgICBzZWxmLnRpbWVvdXRTZXQgPSB0cnVlO1xuICAgICAgc2VsZi5fc29ja2V0LnNldFRpbWVvdXQoXG4gICAgICAgIHNlbGYub3B0aW9ucy5jb25udGltZW91dCAqIDEwMDAsXG4gICAgICAgIGZ1bmN0aW9uICh0aGlzOiBuZXQuU29ja2V0KSB7XG4gICAgICAgICAgc2VsZi50aW1lb3V0U2V0ID0gZmFsc2U7XG4gICAgICAgICAgaWYgKCFzZWxmLmNvbm5lY3RlZCkge1xuICAgICAgICAgICAgdGhpcy5lbmQoKTtcbiAgICAgICAgICAgIHNlbGYuX3NvY2tldCA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIHNlbGYuZXJyb3IobmV3IEVycm9yKFwic29ja2V0IHRpbWVkIG91dCBjb25uZWN0aW5nIHRvIHNlcnZlci5cIikpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgKTtcblxuICAgICAgLy8gdXNlIFRDUCBrZWVwLWFsaXZlXG4gICAgICBzZWxmLl9zb2NrZXQuc2V0S2VlcEFsaXZlKFxuICAgICAgICBzZWxmLm9wdGlvbnMua2VlcEFsaXZlLFxuICAgICAgICBzZWxmLm9wdGlvbnMua2VlcEFsaXZlRGVsYXkgKiAxMDAwXG4gICAgICApO1xuICAgIH0gZWxzZSBpZiAoIXNlbGYuY29ubmVjdGVkICYmICFzYXNsKSB7XG4gICAgICAvLyBDQVNFIDI6IHNvY2tldCBleGlzdHMsIGJ1dCBzdGlsbCBjb25uZWN0aW5nIC8gYXV0aGVudGljYXRpbmdcbiAgICAgIHNlbGYub25Db25uZWN0KGdvKTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gQ0FTRSAzOiBzb2NrZXQgZXhpc3RzIGFuZCBjb25uZWN0ZWQgLyByZWFkeSB0byB1c2VcbiAgICAgIGdvKHNlbGYuX3NvY2tldCk7XG4gICAgfVxuICB9XG5cbiAgd3JpdGUoYmxvYjogQnVmZmVyKSB7XG4gICAgY29uc3Qgc2VsZiA9IHRoaXM7XG4gICAgY29uc3QgZGVhZGxpbmUgPSBNYXRoLnJvdW5kKHNlbGYub3B0aW9ucy50aW1lb3V0ICogMTAwMCk7XG4gICAgdGhpcy5zb2NrKGZhbHNlLCBmdW5jdGlvbiAocykge1xuICAgICAgcy53cml0ZShibG9iKTtcbiAgICAgIHNlbGYucmVxdWVzdFRpbWVvdXRzLnB1c2godGltZXN0YW1wKCkgKyBkZWFkbGluZSk7XG4gICAgICBpZiAoIXNlbGYudGltZW91dFNldCkge1xuICAgICAgICBzZWxmLnRpbWVvdXRTZXQgPSB0cnVlO1xuICAgICAgICBzLnNldFRpbWVvdXQoZGVhZGxpbmUsIGZ1bmN0aW9uICh0aGlzOiBuZXQuU29ja2V0KSB7XG4gICAgICAgICAgdGltZW91dEhhbmRsZXIoc2VsZiwgdGhpcyk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgd3JpdGVTQVNMKGJsb2I6IEJ1ZmZlcikge1xuICAgIHRoaXMuc29jayh0cnVlLCBmdW5jdGlvbiAocykge1xuICAgICAgcy53cml0ZShibG9iKTtcbiAgICB9KTtcbiAgfVxuXG4gIGNsb3NlKCkge1xuICAgIGlmICh0aGlzLl9zb2NrZXQpIHtcbiAgICAgIHRoaXMuX3NvY2tldC5lbmQoKTtcbiAgICB9XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICByZXR1cm4gXCI8U2VydmVyIFwiICsgdGhpcy5ob3N0ICsgXCI6XCIgKyB0aGlzLnBvcnQgKyBcIj5cIjtcbiAgfVxuXG4gIGhvc3Rwb3J0U3RyaW5nKCkge1xuICAgIHJldHVybiB0aGlzLmhvc3QgKyBcIjpcIiArIHRoaXMucG9ydDtcbiAgfVxufVxuXG4vLyBXZSBoYW5kbGUgdHJhY2tpbmcgdGltZW91dHMgd2l0aCBhbiBhcnJheSBvZiBkZWFkbGluZXMgKHJlcXVlc3RUaW1lb3V0cyksIGFzXG4vLyBub2RlIGRvZXNuJ3QgbGlrZSB1cyBzZXR0aW5nIHVwIGxvdHMgb2YgdGltZXJzLCBhbmQgdXNpbmcganVzdCBvbmUgaXMgbW9yZVxuLy8gZWZmaWNpZW50IGFueXdheS5cbmNvbnN0IHRpbWVvdXRIYW5kbGVyID0gZnVuY3Rpb24gKHNlcnZlcjogU2VydmVyLCBzb2NrOiBuZXQuU29ja2V0KSB7XG4gIGlmIChzZXJ2ZXIucmVxdWVzdFRpbWVvdXRzLmxlbmd0aCA9PT0gMCkge1xuICAgIC8vIG5vdGhpbmcgYWN0aXZlXG4gICAgc2VydmVyLnRpbWVvdXRTZXQgPSBmYWxzZTtcbiAgICByZXR1cm47XG4gIH1cblxuICAvLyBzb21lIHJlcXVlc3RzIG91dHN0YW5kaW5nLCBjaGVjayBpZiBhbnkgaGF2ZSB0aW1lZC1vdXRcbiAgY29uc3Qgbm93ID0gdGltZXN0YW1wKCk7XG4gIGNvbnN0IHNvb25lc3RUaW1lb3V0ID0gc2VydmVyLnJlcXVlc3RUaW1lb3V0c1swXTtcblxuICBpZiAoc29vbmVzdFRpbWVvdXQgPD0gbm93KSB7XG4gICAgLy8gdGltZW91dCBvY2N1cnJlZCFcbiAgICBzb2NrLmVuZCgpO1xuICAgIHNlcnZlci5jb25uZWN0ZWQgPSBmYWxzZTtcbiAgICBzZXJ2ZXIuX3NvY2tldCA9IHVuZGVmaW5lZDtcbiAgICBzZXJ2ZXIudGltZW91dFNldCA9IGZhbHNlO1xuICAgIHNlcnZlci5lcnJvcihuZXcgRXJyb3IoXCJzb2NrZXQgdGltZWQgb3V0IHdhaXRpbmcgb24gcmVzcG9uc2UuXCIpKTtcbiAgfSBlbHNlIHtcbiAgICAvLyBubyB0aW1lb3V0ISBTZXR1cCBuZXh0IG9uZS5cbiAgICBjb25zdCBkZWFkbGluZSA9IHNvb25lc3RUaW1lb3V0IC0gbm93O1xuICAgIHNvY2suc2V0VGltZW91dChkZWFkbGluZSwgZnVuY3Rpb24gKCkge1xuICAgICAgdGltZW91dEhhbmRsZXIoc2VydmVyLCBzb2NrKTtcbiAgICB9KTtcbiAgfVxufTtcbiJdfQ== \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL21lbWpzL3NlcnZlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSw4Q0FBc0I7QUFDdEIsb0RBQTRCO0FBQzVCLG1DQU1pQjtBQTBCakIsTUFBYSxNQUFPLFNBQVEsZ0JBQU0sQ0FBQyxZQUFZO0lBZ0I3QyxZQUNFLElBQVk7SUFDWixnR0FBZ0c7SUFDaEcsSUFBc0IsRUFDdEIsUUFBaUIsRUFDakIsUUFBaUIsRUFDakIsT0FBZ0M7UUFFaEMsS0FBSyxFQUFFLENBQUM7UUFDUixJQUFJLENBQUMsY0FBYyxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDdEMsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUM7UUFDakIsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUM7UUFDakIsSUFBSSxDQUFDLFNBQVMsR0FBRyxLQUFLLENBQUM7UUFDdkIsSUFBSSxDQUFDLFVBQVUsR0FBRyxLQUFLLENBQUM7UUFDeEIsSUFBSSxDQUFDLGdCQUFnQixHQUFHLEVBQUUsQ0FBQztRQUMzQixJQUFJLENBQUMsaUJBQWlCLEdBQUcsRUFBRSxDQUFDO1FBQzVCLElBQUksQ0FBQyxlQUFlLEdBQUcsRUFBRSxDQUFDO1FBQzFCLElBQUksQ0FBQyxjQUFjLEdBQUcsRUFBRSxDQUFDO1FBQ3pCLElBQUksQ0FBQyxPQUFPLEdBQUcsYUFBSyxDQUFDLE9BQU8sSUFBSSxFQUFFLEVBQUU7WUFDbEMsT0FBTyxFQUFFLEdBQUc7WUFDWixTQUFTLEVBQUUsS0FBSztZQUNoQixjQUFjLEVBQUUsRUFBRTtTQUNuQixDQUFrQixDQUFDO1FBQ3BCLElBQ0UsSUFBSSxDQUFDLE9BQU8sQ0FBQyxXQUFXLEtBQUssU0FBUztZQUN0QyxJQUFJLENBQUMsT0FBTyxDQUFDLFdBQVcsS0FBSyxJQUFJLEVBQ2pDO1lBQ0EsSUFBSSxDQUFDLE9BQU8sQ0FBQyxXQUFX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bnQiOlsiaW1wb3J0IG5ldCBmcm9tIFwibmV0XCI7XG5pbXBvcnQgZXZlbnRzIGZyb20gXCJldmVudHNcIjtcbmltcG9ydCB7XG4gIG1ha2VSZXF1ZXN0QnVmZmVyLFxuICBwYXJzZU1lc3NhZ2UsXG4gIG1lcmdlLFxuICB0aW1lc3RhbXAsXG4gIE1lc3NhZ2UsXG59IGZyb20gXCIuL3V0aWxzXCI7XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2VydmVyT3B0aW9ucyB7XG4gIHRpbWVvdXQ6IG51bWJlcjtcbiAga2VlcEFsaXZlOiBib29sZWFuO1xuICBrZWVwQWxpdmVEZWxheTogbnVtYmVyO1xuICBjb25udGltZW91dDogbnVtYmVyO1xuICB1c2VybmFtZT86IHN0cmluZztcbiAgcGFzc3dvcmQ/OiBzdHJpbmc7XG59XG5cbnR5cGUgU2VxID0gbnVtYmVyO1xuXG5leHBvcnQgaW50ZXJmYWNlIE9uQ29ubmVjdENhbGxiYWNrIHtcbiAgKHNvY2tldDogbmV0LlNvY2tldCk6IHZvaWQ7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgT25SZXNwb25zZUNhbGxiYWNrIHtcbiAgKG1lc3NhZ2U6IE1lc3NhZ2UpOiB2b2lkO1xuICBxdWlldD86IGJvb2xlYW47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgT25FcnJvckNhbGxiYWNrIHtcbiAgKGVycm9yOiBFcnJvcik6IHZvaWQ7XG59XG5cbmV4cG9ydCBjbGFzcyBTZXJ2ZXIgZXh0ZW5kcyBldmVudHMuRXZlbnRFbWl0dGVyIHtcbiAgcmVzcG9uc2VCdWZmZXI6IEJ1ZmZlcjtcbiAgaG9zdDogc3RyaW5nO1xuICBwb3J0OiBzdHJpbmcgfCBudW1iZXIgfCB1bmRlZmluZWQ7XG4gIGNvbm5lY3RlZDogYm9vbGVhbjtcbiAgdGltZW91dFNldDogYm9vbGVhbjtcbiAgY29ubmVjdENhbGxiYWNrczogT25Db25uZWN0Q2FsbGJhY2tbXTtcbiAgcmVzcG9uc2VDYWxsYmFja3M6IHsgW3NlcTogc3RyaW5nXTogT25SZXNwb25zZUNhbGxiYWNrIH07XG4gIHJlcXVlc3RUaW1lb3V0czogbnVtYmVyW107XG4gIGVycm9yQ2FsbGJhY2tzOiB7IFtzZXE6IHN0cmluZ106IE9uRXJyb3JDYWxsYmFjayB9O1xuICBvcHRpb25zOiBTZXJ2ZXJPcHRpb25zO1xuICB1c2VybmFtZTogc3RyaW5nIHwgdW5kZWZpbmVkO1xuICBwYXNzd29yZDogc3RyaW5nIHwgdW5kZWZpbmVkO1xuXG4gIF9zb2NrZXQ6IG5ldC5Tb2NrZXQgfCB1bmRlZmluZWQ7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgaG9zdDogc3RyaW5nLFxuICAgIC8qIFRPRE86IGFsbG93aW5nIHBvcnQgdG8gYmUgc3RyaW5nIG9yIHVuZGVmaW5lZCBpcyB1c2VkIGJ5IHRoZSB0ZXN0cywgYnV0IHNlZW1zIGJhZCBvdmVyYWxsLiAqL1xuICAgIHBvcnQ/OiBzdHJpbmcgfCBudW1iZXIsXG4gICAgdXNlcm5hbWU/OiBzdHJpbmcsXG4gICAgcGFzc3dvcmQ/OiBzdHJpbmcsXG4gICAgb3B0aW9ucz86IFBhcnRpYWw8U2VydmVyT3B0aW9ucz5cbiAgKSB7XG4gICAgc3VwZXIoKTtcbiAgICB0aGlzLnJlc3BvbnNlQnVmZmVyID0gQnVmZmVyLmZyb20oW10pO1xuICAgIHRoaXMuaG9zdCA9IGhvc3Q7XG4gICAgdGhpcy5wb3J0ID0gcG9ydDtcbiAgICB0aGlzLmNvbm5lY3RlZCA9IGZhbHNlO1xuICAgIHRoaXMudGltZW91dFNldCA9IGZhbHNlO1xuICAgIHRoaXMuY29ubmVjdENhbGxiYWNrcyA9IFtdO1xuICAgIHRoaXMucmVzcG9uc2VDYWxsYmFja3MgPSB7fTtcbiAgICB0aGlzLnJlcXVlc3RUaW1lb3V0cyA9IFtdO1xuICAgIHRoaXMuZXJyb3JDYWxsYmFja3MgPSB7fTtcbiAgICB0aGlzLm9wdGlvbnMgPSBtZXJnZShvcHRpb25zIHx8IHt9LCB7XG4gICAgICB0aW1lb3V0OiAwLjUsXG4gICAgICBrZWVwQWxpdmU6IGZhbHNlLFxuICAgICAga2VlcEFsaXZlRGVsYXk6IDMwLFxuICAgIH0pIGFzIFNlcnZlck9wdGlvbnM7XG4gICAgaWYgKFxuICAgICAgdGhpcy5vcHRpb25zLmNvbm50aW1lb3V0ID09PSB1bmRlZmluZWQgfHxcbiAgICAgIHRoaXMub3B0aW9ucy5jb25udGltZW91dCA9PT0gbnVsbFxuICAgICkge1xuICAgICAgdGhpcy5vcHRpb25zLmNvbm50aW1lb3V0ID0gMiAqIHRoaXMub3B0aW9ucy50aW1lb3V0O1xuICAgIH1cbiAgICB0aGlzLnVzZXJuYW1lID1cbiAgICAgIHVzZXJuYW1lIHx8XG4gICAgICB0aGlzLm9wdGlvbnMudXNlcm5hbWUgfHxcbiAgICAgIHByb2Nlc3MuZW52Lk1FTUNBQ0hJRVJfVVNFUk5BTUUgfHxcbiAgICAgIHByb2Nlc3MuZW52Lk1FTUNBQ0hFX1VTRVJOQU1FO1xuICAgIHRoaXMucGFzc3dvcmQgPVxuICAgICAgcGFzc3dvcmQgfHxcbiAgICAgIHRoaXMub3B0aW9ucy5wYXNzd29yZCB8fFxuICAgICAgcHJvY2Vzcy5lbnYuTUVNQ0FDSElFUl9QQVNTV09SRCB8fFxuICAgICAgcHJvY2Vzcy5lbnYuTUVNQ0FDSEVfUEFTU1dPUkQ7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICBvbkNvbm5lY3QoZnVuYzogT25Db25uZWN0Q2FsbGJhY2spIHtcbiAgICB0aGlzLmNvbm5lY3RDYWxsYmFja3MucHVzaChmdW5jKTtcbiAgfVxuXG4gIG9uUmVzcG9uc2Uoc2VxOiBTZXEsIGZ1bmM6IE9uUmVzcG9uc2VDYWxsYmFjaykge1xuICAgIHRoaXMucmVzcG9uc2VDYWxsYmFja3Nbc2VxXSA9IGZ1bmM7XG4gIH1cblxuICByZXNwb25kKHJlc3BvbnNlOiBNZXNzYWdlKSB7XG4gICAgY29uc3QgY2FsbGJhY2sgPSB0aGlzLnJlc3BvbnNlQ2FsbGJhY2tzW3Jlc3BvbnNlLmhlYWRlci5vcGFxdWVdO1xuICAgIGlmICghY2FsbGJhY2spIHtcbiAgICAgIC8vIGluIGNhc2Ugb2YgYXV0aGVudGljYXRpb24sIG5vIGNhbGxiYWNrIGlzIHJlZ2lzdGVyZWRcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY2FsbGJhY2socmVzcG9uc2UpO1xuICAgIGlmICghY2FsbGJhY2sucXVpZXQgfHwgcmVzcG9uc2UuaGVhZGVyLnRvdGFsQm9keUxlbmd0aCA9PT0gMCkge1xuICAgICAgZGVsZXRlIHRoaXMucmVzcG9uc2VDYWxsYmFja3NbcmVzcG9uc2UuaGVhZGVyLm9wYXF1ZV07XG4gICAgICB0aGlzLnJlcXVlc3RUaW1lb3V0cy5zaGlmdCgpO1xuICAgICAgZGVsZXRlIHRoaXMuZXJyb3JDYWxsYmFja3NbcmVzcG9uc2UuaGVhZGVyLm9wYXF1ZV07XG4gICAgfVxuICB9XG5cbiAgb25FcnJvcihzZXE6IFNlcSwgZnVuYzogT25FcnJvckNhbGxiYWNrKSB7XG4gICAgdGhpcy5lcnJvckNhbGxiYWNrc1tzZXFdID0gZnVuYztcbiAgfVxuXG4gIGVycm9yKGVycjogRXJyb3IpIHtcbiAgICBjb25zdCBlcnJjYWxscyA9IHRoaXMuZXJyb3JDYWxsYmFja3M7XG4gICAgLy8gcmVzZXQgYWxsIHN0YXRlcyBleGNlcHQgaG9zdCwgcG9ydCwgb3B0aW9ucywgdXNlcm5hbWUsIHBhc3N3b3JkXG4gICAgdGhpcy5yZXNwb25zZUJ1ZmZlciA9IEJ1ZmZlci5mcm9tKFtdKTtcbiAgICB0aGlzLmNvbm5lY3RlZCA9IGZhbHNlO1xuICAgIHRoaXMudGltZW91dFNldCA9IGZhbHNlO1xuICAgIHRoaXMuY29ubmVjdENhbGxiYWNrcyA9IFtdO1xuICAgIHRoaXMucmVzcG9uc2VDYWxsYmFja3MgPSB7fTtcbiAgICB0aGlzLnJlcXVlc3RUaW1lb3V0cyA9IFtdO1xuICAgIHRoaXMuZXJyb3JDYWxsYmFja3MgPSB7fTtcbiAgICBpZiAodGhpcy5fc29ja2V0KSB7XG4gICAgICB0aGlzLl9zb2NrZXQuZGVzdHJveSgpO1xuICAgICAgZGVsZXRlIHRoaXMuX3NvY2tldDtcbiAgICB9XG4gICAgZm9yIChsZXQgZXJyY2FsbCBvZiBPYmplY3QudmFsdWVzKGVycmNhbGxzKSkge1xuICAgICAgZXJyY2FsbChlcnIpO1xuICAgIH1cbiAgfVxuXG4gIGxpc3RTYXNsKCkge1xuICAgIGNvbnN0IGJ1ZiA9IG1ha2VSZXF1ZXN0QnVmZmVyKDB4MjAsIFwiXCIsIFwiXCIsIFwiXCIpO1xuICAgIHRoaXMud3JpdGVTQVNMKGJ1Zik7XG4gIH1cblxuICBzYXNsQXV0aCgpIHtcbiAgICBjb25zdCBhdXRoU3RyID0gXCJcXHgwMFwiICsgdGhpcy51c2VybmFtZSArIFwiXFx4MDBcIiArIHRoaXMucGFzc3dvcmQ7XG4gICAgY29uc3QgYnVmID0gbWFrZVJlcXVlc3RCdWZmZXIoMHgyMSwgXCJQTEFJTlwiLCBcIlwiLCBhdXRoU3RyKTtcbiAgICB0aGlzLndyaXRlU0FTTChidWYpO1xuICB9XG5cbiAgYXBwZW5kVG9CdWZmZXIoZGF0YUJ1ZjogQnVmZmVyKSB7XG4gICAgY29uc3Qgb2xkID0gdGhpcy5yZXNwb25zZUJ1ZmZlcjtcbiAgICB0aGlzLnJlc3BvbnNlQnVmZmVyID0gQnVmZmVyLmFsbG9jKG9sZC5sZW5ndGggKyBkYXRhQnVmLmxlbmd0aCk7XG4gICAgb2xkLmNvcHkodGhpcy5yZXNwb25zZUJ1ZmZlciwgMCk7XG4gICAgZGF0YUJ1Zi5jb3B5KHRoaXMucmVzcG9uc2VCdWZmZXIsIG9sZC5sZW5ndGgpO1xuICAgIHJldHVybiB0aGlzLnJlc3BvbnNlQnVmZmVyO1xuICB9XG4gIHJlc3BvbnNlSGFuZGxlcihkYXRhQnVmOiBCdWZmZXIpIHtcbiAgICBsZXQgcmVzcG9uc2U6IE1lc3NhZ2UgfCBmYWxzZTtcbiAgICB0cnkge1xuICAgICAgcmVzcG9uc2UgPSBwYXJzZU1lc3NhZ2UodGhpcy5hcHBlbmRUb0J1ZmZlcihkYXRhQnVmKSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgdGhpcy5lcnJvcihlIGFzIEVycm9yKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBsZXQgcmVzcExlbmd0aDogbnVtYmVyO1xuICAgIHdoaWxlIChyZXNwb25zZSkge1xuICAgICAgaWYgKHJlc3BvbnNlLmhlYWRlci5vcGNvZGUgPT09IDB4MjApIHtcbiAgICAgICAgdGhpcy5zYXNsQXV0aCgpO1xuICAgICAgfSBlbHNlIGlmIChyZXNwb25zZS5oZWFkZXIuc3RhdHVzID09PSAoMHgyMCBhcyBhbnkpIC8qIFRPRE86IHd0Zj8gKi8pIHtcbiAgICAgICAgdGhpcy5lcnJvcihuZXcgRXJyb3IoXCJNZW1jYWNoZWQgc2VydmVyIGF1dGhlbnRpY2F0aW9uIGZhaWxlZCFcIikpO1xuICAgICAgfSBlbHNlIGlmIChyZXNwb25zZS5oZWFkZXIub3Bjb2RlID09PSAweDIxKSB7XG4gICAgICAgIHRoaXMuZW1pdChcImF1dGhlbnRpY2F0ZWRcIik7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLnJlc3BvbmQocmVzcG9uc2UpO1xuICAgICAgfVxuICAgICAgcmVzcExlbmd0aCA9IHJlc3BvbnNlLmhlYWRlci50b3RhbEJvZHlMZW5ndGggKyAyNDtcbiAgICAgIHRoaXMucmVzcG9uc2VCdWZmZXIgPSB0aGlzLnJlc3BvbnNlQnVmZmVyLnNsaWNlKHJlc3BMZW5ndGgpO1xuICAgICAgcmVzcG9uc2UgPSBwYXJzZU1lc3NhZ2UodGhpcy5yZXNwb25zZUJ1ZmZlcik7XG4gICAgfVxuICB9XG4gIHNvY2soc2FzbDogYm9vbGVhbiwgZ286IE9uQ29ubmVjdENhbGxiYWNrKSB7XG4gICAgY29uc3Qgc2VsZiA9IHRoaXM7XG5cbiAgICBpZiAoIXNlbGYuX3NvY2tldCkge1xuICAgICAgLy8gQ0FTRSAxOiBjb21wbGV0ZWx5IG5ldyBzb2NrZXRcbiAgICAgIHNlbGYuY29ubmVjdGVkID0gZmFsc2U7XG4gICAgICBzZWxmLnJlc3BvbnNlQnVmZmVyID0gQnVmZmVyLmZyb20oW10pO1xuICAgICAgc2VsZi5fc29ja2V0ID0gbmV0LmNvbm5lY3QoXG4gICAgICAgIC8qIFRPRE86IGFsbG93aW5nIHBvcnQgdG8gYmUgc3RyaW5nIG9yIHVuZGVmaW5lZCBpcyB1c2VkIGJ5IHRoZSB0ZXN0cywgYnV0IHNlZW1zIGJhZCBvdmVyYWxsLiAqL1xuICAgICAgICB0eXBlb2YgdGhpcy5wb3J0ID09PSBcInN0cmluZ1wiXG4gICAgICAgICAgPyBwYXJzZUludCh0aGlzLnBvcnQsIDEwKVxuICAgICAgICAgIDogdGhpcy5wb3J0IHx8IDExMjExLFxuICAgICAgICB0aGlzLmhvc3QsXG4gICAgICAgIGZ1bmN0aW9uICh0aGlzOiBuZXQuU29ja2V0KSB7XG4gICAgICAgICAgLy8gU0FTTCBhdXRoZW50aWNhdGlvbiBoYW5kbGVyXG4gICAgICAgICAgc2VsZi5vbmNlKFwiYXV0aGVudGljYXRlZFwiLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAoc2VsZi5fc29ja2V0KSB7XG4gICAgICAgICAgICAgIGNvbnN0IHNvY2tldCA9IHNlbGYuX3NvY2tldDtcbiAgICAgICAgICAgICAgc2VsZi5jb25uZWN0ZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAvLyBjYW5jZWwgY29ubmVjdGlvbiB0aW1lb3V0XG4gICAgICAgICAgICAgIHNlbGYuX3NvY2tldC5zZXRUaW1lb3V0KDApO1xuICAgICAgICAgICAgICBzZWxmLnRpbWVvdXRTZXQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgLy8gcnVuIGFjdHVhbCByZXF1ZXN0KHMpXG4gICAgICAgICAgICAgIGdvKHNlbGYuX3NvY2tldCk7XG4gICAgICAgICAgICAgIHNlbGYuY29ubmVjdENhbGxiYWNrcy5mb3JFYWNoKGZ1bmN0aW9uIChjYikge1xuICAgICAgICAgICAgICAgIGNiKHNvY2tldCk7XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICBzZWxmLmNvbm5lY3RDYWxsYmFja3MgPSBbXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIC8vIHNldHVwIHJlc3BvbnNlIGhhbmRsZXJcbiAgICAgICAgICB0aGlzLm9uKFwiZGF0YVwiLCBmdW5jdGlvbiAoZGF0YUJ1Zikge1xuICAgICAgICAgICAgc2VsZi5yZXNwb25zZUhhbmRsZXIoZGF0YUJ1Zik7XG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICAvLyBraWNrIG9mIFNBU0wgaWYgbmVlZGVkXG4gICAgICAgICAgaWYgKHNlbGYudXNlcm5hbWUgJiYgc2VsZi5wYXNzd29yZCkge1xuICAgICAgICAgICAgc2VsZi5saXN0U2FzbCgpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzZWxmLmVtaXQoXCJhdXRoZW50aWNhdGVkXCIpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgKTtcblxuICAgICAgLy8gc2V0dXAgZXJyb3IgaGFuZGxlclxuICAgICAgc2VsZi5fc29ja2V0Lm9uKFwiZXJyb3JcIiwgZnVuY3Rpb24gKGVycm9yKSB7XG4gICAgICAgIHNlbGYuZXJyb3IoZXJyb3IpO1xuICAgICAgfSk7XG5cbiAgICAgIHNlbGYuX3NvY2tldC5vbihcImNsb3NlXCIsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKE9iamVjdC5rZXlzKHNlbGYuZXJyb3JDYWxsYmFja3MpLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICBzZWxmLmVycm9yKG5ldyBFcnJvcihcInNvY2tldCBjbG9zZWQgdW5leHBlY3RlZGx5LlwiKSk7XG4gICAgICAgIH1cbiAgICAgICAgc2VsZi5jb25uZWN0ZWQgPSBmYWxzZTtcbiAgICAgICAgc2VsZi5yZXNwb25zZUJ1ZmZlciA9IEJ1ZmZlci5mcm9tKFtdKTtcbiAgICAgICAgaWYgKHNlbGYudGltZW91dFNldCkge1xuICAgICAgICAgIHNlbGYuX3NvY2tldD8uc2V0VGltZW91dCgwKTtcbiAgICAgICAgICBzZWxmLnRpbWVvdXRTZXQgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBzZWxmLl9zb2NrZXQgPSB1bmRlZmluZWQ7XG4gICAgICB9KTtcblxuICAgICAgLy8gc2V0dXAgY29ubmVjdGlvbiB0aW1lb3V0IGhhbmRsZXJcbiAgICAgIHNlbGYudGltZW91dFNldCA9IHRydWU7XG4gICAgICBzZWxmLl9zb2NrZXQuc2V0VGltZW91dChcbiAgICAgICAgc2VsZi5vcHRpb25zLmNvbm50aW1lb3V0ICogMTAwMCxcbiAgICAgICAgZnVuY3Rpb24gKHRoaXM6IG5ldC5Tb2NrZXQpIHtcbiAgICAgICAgICBzZWxmLnRpbWVvdXRTZXQgPSBmYWxzZTtcbiAgICAgICAgICBpZiAoIXNlbGYuY29ubmVjdGVkKSB7XG4gICAgICAgICAgICB0aGlzLmVuZCgpO1xuICAgICAgICAgICAgc2VsZi5fc29ja2V0ID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgc2VsZi5lcnJvcihuZXcgRXJyb3IoXCJzb2NrZXQgdGltZWQgb3V0IGNvbm5lY3RpbmcgdG8gc2VydmVyLlwiKSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICApO1xuXG4gICAgICAvLyB1c2UgVENQIGtlZXAtYWxpdmVcbiAgICAgIHNlbGYuX3NvY2tldC5zZXRLZWVwQWxpdmUoXG4gICAgICAgIHNlbGYub3B0aW9ucy5rZWVwQWxpdmUsXG4gICAgICAgIHNlbGYub3B0aW9ucy5rZWVwQWxpdmVEZWxheSAqIDEwMDBcbiAgICAgICk7XG4gICAgfSBlbHNlIGlmICghc2VsZi5jb25uZWN0ZWQgJiYgIXNhc2wpIHtcbiAgICAgIC8vIENBU0UgMjogc29ja2V0IGV4aXN0cywgYnV0IHN0aWxsIGNvbm5lY3RpbmcgLyBhdXRoZW50aWNhdGluZ1xuICAgICAgc2VsZi5vbkNvbm5lY3QoZ28pO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBDQVNFIDM6IHNvY2tldCBleGlzdHMgYW5kIGNvbm5lY3RlZCAvIHJlYWR5IHRvIHVzZVxuICAgICAgZ28oc2VsZi5fc29ja2V0KTtcbiAgICB9XG4gIH1cblxuICB3cml0ZShibG9iOiBCdWZmZXIpIHtcbiAgICBjb25zdCBzZWxmID0gdGhpcztcbiAgICBjb25zdCBkZWFkbGluZSA9IE1hdGgucm91bmQoc2VsZi5vcHRpb25zLnRpbWVvdXQgKiAxMDAwKTtcbiAgICB0aGlzLnNvY2soZmFsc2UsIGZ1bmN0aW9uIChzKSB7XG4gICAgICBzLndyaXRlKGJsb2IpO1xuICAgICAgc2VsZi5yZXF1ZXN0VGltZW91dHMucHVzaCh0aW1lc3RhbXAoKSArIGRlYWRsaW5lKTtcbiAgICAgIGlmICghc2VsZi50aW1lb3V0U2V0KSB7XG4gICAgICAgIHNlbGYudGltZW91dFNldCA9IHRydWU7XG4gICAgICAgIHMuc2V0VGltZW91dChkZWFkbGluZSwgZnVuY3Rpb24gKHRoaXM6IG5ldC5Tb2NrZXQpIHtcbiAgICAgICAgICB0aW1lb3V0SGFuZGxlcihzZWxmLCB0aGlzKTtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICB3cml0ZVNBU0woYmxvYjogQnVmZmVyKSB7XG4gICAgdGhpcy5zb2NrKHRydWUsIGZ1bmN0aW9uIChzKSB7XG4gICAgICBzLndyaXRlKGJsb2IpO1xuICAgIH0pO1xuICB9XG5cbiAgY2xvc2UoKSB7XG4gICAgaWYgKHRoaXMuX3NvY2tldCkge1xuICAgICAgLy8gVE9ETzogdGhpcyBzaG91bGQgcHJvYmFibHkgYmUgZGVzdHJveSgpIGluIGF0IGxlYXN0IHNvbWUsIGlmIG5vdCBhbGwsXG4gICAgICAvLyBjYXNlcy5cbiAgICAgIHRoaXMuX3NvY2tldC5lbmQoKTtcbiAgICB9XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICByZXR1cm4gXCI8U2VydmVyIFwiICsgdGhpcy5ob3N0ICsgXCI6XCIgKyB0aGlzLnBvcnQgKyBcIj5cIjtcbiAgfVxuXG4gIGhvc3Rwb3J0U3RyaW5nKCkge1xuICAgIHJldHVybiB0aGlzLmhvc3QgKyBcIjpcIiArIHRoaXMucG9ydDtcbiAgfVxufVxuXG4vLyBXZSBoYW5kbGUgdHJhY2tpbmcgdGltZW91dHMgd2l0aCBhbiBhcnJheSBvZiBkZWFkbGluZXMgKHJlcXVlc3RUaW1lb3V0cyksIGFzXG4vLyBub2RlIGRvZXNuJ3QgbGlrZSB1cyBzZXR0aW5nIHVwIGxvdHMgb2YgdGltZXJzLCBhbmQgdXNpbmcganVzdCBvbmUgaXMgbW9yZVxuLy8gZWZmaWNpZW50IGFueXdheS5cbmNvbnN0IHRpbWVvdXRIYW5kbGVyID0gZnVuY3Rpb24gKHNlcnZlcjogU2VydmVyLCBzb2NrOiBuZXQuU29ja2V0KSB7XG4gIGlmIChzZXJ2ZXIucmVxdWVzdFRpbWVvdXRzLmxlbmd0aCA9PT0gMCkge1xuICAgIC8vIG5vdGhpbmcgYWN0aXZlXG4gICAgc2VydmVyLnRpbWVvdXRTZXQgPSBmYWxzZTtcbiAgICByZXR1cm47XG4gIH1cblxuICAvLyBzb21lIHJlcXVlc3RzIG91dHN0YW5kaW5nLCBjaGVjayBpZiBhbnkgaGF2ZSB0aW1lZC1vdXRcbiAgY29uc3Qgbm93ID0gdGltZXN0YW1wKCk7XG4gIGNvbnN0IHNvb25lc3RUaW1lb3V0ID0gc2VydmVyLnJlcXVlc3RUaW1lb3V0c1swXTtcblxuICBpZiAoc29vbmVzdFRpbWVvdXQgPD0gbm93KSB7XG4gICAgLy8gdGltZW91dCBvY2N1cnJlZCFcbiAgICBzZXJ2ZXIuZXJyb3IobmV3IEVycm9yKFwic29ja2V0IHRpbWVkIG91dCB3YWl0aW5nIG9uIHJlc3BvbnNlLlwiKSk7XG4gIH0gZWxzZSB7XG4gICAgLy8gbm8gdGltZW91dCEgU2V0dXAgbmV4dCBvbmUuXG4gICAgY29uc3QgZGVhZGxpbmUgPSBzb29uZXN0VGltZW91dCAtIG5vdztcbiAgICBzb2NrLnNldFRpbWVvdXQoZGVhZGxpbmUsIGZ1bmN0aW9uICgpIHtcbiAgICAgIHRpbWVvdXRIYW5kbGVyKHNlcnZlciwgc29jayk7XG4gICAgfSk7XG4gIH1cbn07XG4iXX0= \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 1963366..09423c3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "memjs", - "version": "1.2.4", + "version": "1.2.4-NOTION.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "memjs", - "version": "1.2.4", + "version": "1.2.4-NOTION.1", "license": "MIT", "devDependencies": { "@types/node": "12.20.7", diff --git a/package.json b/package.json index a24179c..007377f 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "author": "Amit Levy", "name": "memjs", "description": "A memcache client for node using the binary protocol and SASL authentication", - "version": "1.2.4", + "version": "1.2.4-NOTION.1", "license": "MIT", "homepage": "http://github.com/memcachier/memjs", "keywords": [ diff --git a/src/memjs/server.ts b/src/memjs/server.ts index ed96313..5f7b830 100644 --- a/src/memjs/server.ts +++ b/src/memjs/server.ts @@ -118,12 +118,14 @@ export class Server extends events.EventEmitter { error(err: Error) { const errcalls = this.errorCallbacks; + // reset all states except host, port, options, username, password + this.responseBuffer = Buffer.from([]); + this.connected = false; + this.timeoutSet = false; this.connectCallbacks = []; this.responseCallbacks = {}; this.requestTimeouts = []; this.errorCallbacks = {}; - this.timeoutSet = false; - this.responseBuffer = Buffer.from([]); if (this._socket) { this._socket.destroy(); delete this._socket; @@ -290,6 +292,8 @@ export class Server extends events.EventEmitter { close() { if (this._socket) { + // TODO: this should probably be destroy() in at least some, if not all, + // cases. this._socket.end(); } } @@ -319,10 +323,6 @@ const timeoutHandler = function (server: Server, sock: net.Socket) { if (soonestTimeout <= now) { // timeout occurred! - sock.end(); - server.connected = false; - server._socket = undefined; - server.timeoutSet = false; server.error(new Error("socket timed out waiting on response.")); } else { // no timeout! Setup next one.