UNPKG

@viero/webrtc-sfu-client

Version:
409 lines (350 loc) 49.5 kB
"use strict"; /** * Copyright 2020 Viero, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ 'use-strict'; // eslint-disable-next-line no-unused-vars Object.defineProperty(exports, "__esModule", { value: true }); exports.VieroWebRTCSFUClient = void 0; var _webrtcAdapter = _interopRequireDefault(require("webrtc-adapter")); var _eventTargetShim = require("event-target-shim"); var _error = require("@viero/common/error"); var _webrtcSignalingCommon = require("@viero/webrtc-signaling-common"); var _webrtcCommon = require("@viero/webrtc-common"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } var DEFAULT_PEERCONNECTION_CONFIGURATION = { iceServers: [{ urls: 'stun:stun.l.google.com:19302' }] }; var mySocketId = self => { // eslint-disable-next-line no-underscore-dangle if (self.$.signaling && self.$.signaling._socket && self.$.signaling._socket.id) { // eslint-disable-next-line no-underscore-dangle return self.$.signaling._socket.id; } return null; }; var onConnectionStateChange = (self, peer, evt) => { var value = evt.currentTarget.connectionState; self.dispatchEvent(new CustomEvent(_webrtcCommon.VieroWebRTCCommon.EVENT.WEBRTC.STATE_DID_CHANGE, { detail: { direction: peer ? 'in' : 'out', id: peer ? peer.socketId : mySocketId(self), state: 'connectionState', value } })); if (value === 'disconnected') { if (peer) {// the peer's ipc disconnected // 1. we need to check whether signaling is still on // 2. if not, we must leave // 3. if it is, we need to ask the server to renegotiate } else {// our opc is disconnected // 1. we need to check whether signaling is still on // 2. if not, we must leave // 3. if it is, we need to renegotiate } } else if (value === 'failed') {// not sure how to handle this } }; var onICECandidate = (self, peer, evt) => { if (evt.candidate) { self.$.signaling.send(_objectSpread({ word: _webrtcCommon.VieroWebRTCCommon.WORD.CDT, data: JSON.parse(JSON.stringify(evt.candidate)) }, peer ? { on: peer.socketId } : {})); } }; var onICEConnectionStateChange = (self, peer, evt) => { self.dispatchEvent(new CustomEvent(_webrtcCommon.VieroWebRTCCommon.EVENT.WEBRTC.STATE_DID_CHANGE, { detail: { direction: peer ? 'in' : 'out', id: peer ? peer.socketId : mySocketId(self), state: 'iceConnectionState', value: evt.currentTarget.iceConnectionState } })); }; var onICEGatheringStateChange = (self, peer, evt) => { self.dispatchEvent(new CustomEvent(_webrtcCommon.VieroWebRTCCommon.EVENT.WEBRTC.STATE_DID_CHANGE, { detail: { direction: peer ? 'in' : 'out', id: peer ? peer.socketId : mySocketId(self), state: 'iceGatheringState', value: evt.currentTarget.iceGatheringState } })); }; var onNegotiationNeeded = (self, peer) => { var pc = peer ? peer.ipc : self.$.opc; pc.createOffer().then(offer => pc.setLocalDescription(offer)).then(() => self.$.signaling.send({ word: _webrtcCommon.VieroWebRTCCommon.WORD.SDP, data: JSON.parse(JSON.stringify(pc.localDescription)) })).catch(err => { var error = new _error.VieroError('/webrtc/sfu/client', 884761, { [_error.VieroError.KEY.ERROR]: err }); self.dispatchEvent(new CustomEvent(_webrtcCommon.VieroWebRTCCommon.EVENT.ERROR, { detail: { error } })); }); }; var onSignalingStateChange = (self, peer, evt) => { self.dispatchEvent(new CustomEvent(_webrtcCommon.VieroWebRTCCommon.EVENT.WEBRTC.STATE_DID_CHANGE, { detail: { direction: peer ? 'in' : 'out', id: peer ? peer.socketId : mySocketId(self), state: 'signalingState', value: evt.currentTarget.signalingState } })); }; var onTrack = (self, peer, evt) => { if (evt.streams && evt.streams.length) { // eslint-disable-next-line prefer-destructuring, no-param-reassign peer.stream = evt.streams[0]; peer.stream.addEventListener('removetrack', () => { setTimeout(() => { self.dispatchEvent(new CustomEvent(_webrtcCommon.VieroWebRTCCommon.EVENT.TRACK.DID_REMOVE, { detail: { peer } })); }, 0); }); self.dispatchEvent(new CustomEvent(_webrtcCommon.VieroWebRTCCommon.EVENT.TRACK.DID_ADD, { detail: { peer } })); } }; var stripPeer = peer => ({ socketId: peer.socketId, stream: peer.stream || new MediaStream([]) }); var addPeer = (self, socketId) => { var ipc = new RTCPeerConnection(self.$.peerConnectionConfiguration); var peer = { socketId, ipc, stream: new MediaStream([]) }; ipc.addEventListener('connectionstatechange', onConnectionStateChange.bind(null, self, peer)); ipc.addEventListener('icecandidate', onICECandidate.bind(null, self, peer)); ipc.addEventListener('iceconnectionstatechange', onICEConnectionStateChange.bind(null, self, peer)); ipc.addEventListener('icegatheringstatechange', onICEGatheringStateChange.bind(null, self, peer)); ipc.addEventListener('signalingstatechange', onSignalingStateChange.bind(null, self, peer)); ipc.addEventListener('track', onTrack.bind(null, self, peer)); // eslint-disable-next-line no-param-reassign self.$.peers[socketId] = peer; self.dispatchEvent(new CustomEvent(_webrtcCommon.VieroWebRTCCommon.EVENT.PEER.DID_ENTER, { detail: { peer: stripPeer(peer) } })); return peer; }; var removePeer = (self, peer) => { peer.ipc.close(); // eslint-disable-next-line no-param-reassign delete self.$.peers[peer.socketId]; self.dispatchEvent(new CustomEvent(_webrtcCommon.VieroWebRTCCommon.EVENT.PEER.DID_LEAVE, { detail: { peer: stripPeer(peer) } })); }; var onEnter = (self, evt) => { addPeer(self, evt.detail.socketId); }; var onLeave = (self, evt) => { var peer = self.$.peers[evt.detail.socketId]; if (!peer) return; removePeer(self, peer); }; var onMessage = (self, evt) => { var { payload } = evt.detail; switch (payload.word) { case _webrtcCommon.VieroWebRTCCommon.WORD.HELLO: { return payload.data.forEach(socketId => { addPeer(self, socketId); }); } case _webrtcCommon.VieroWebRTCCommon.WORD.SDP: { var sdp = new RTCSessionDescription(payload.data); var peer = self.$.peers[payload.on]; switch (sdp.type) { case 'offer': { // DONE // received an offer, answer it var { ipc } = peer; return ipc.setRemoteDescription(sdp).then(() => ipc.createAnswer()).then(answer => ipc.setLocalDescription(answer)).then(() => self.$.signaling.send({ word: _webrtcCommon.VieroWebRTCCommon.WORD.SDP, on: payload.on, data: JSON.parse(JSON.stringify(ipc.localDescription)) })).catch(err => { var error = new _error.VieroError('/webrtc/sfu/client', 352177, { [_error.VieroError.KEY.ERROR]: err }); self.dispatchEvent(new CustomEvent(_webrtcCommon.VieroWebRTCCommon.EVENT.ERROR, { detail: { error } })); }); } case 'answer': { // DONE // received an answer return self.$.opc.setRemoteDescription(sdp).catch(err => { var error = new _error.VieroError('/webrtc/sfu/client', 645167, { [_error.VieroError.KEY.ERROR]: err }); self.dispatchEvent(new CustomEvent(_webrtcCommon.VieroWebRTCCommon.EVENT.ERROR, { detail: { error } })); }); } default: { return Promise.resolve(); } } } case _webrtcCommon.VieroWebRTCCommon.WORD.CDT: { var cdt = new RTCIceCandidate(payload.data); return (payload.on ? self.$.peers[payload.on].ipc : self.$.opc).addIceCandidate(cdt).catch(err => { var error = new _error.VieroError('/webrtc/sfu/client', 518450, { [_error.VieroError.KEY.ERROR]: err, data: payload.data }); self.dispatchEvent(new CustomEvent(_webrtcCommon.VieroWebRTCCommon.EVENT.ERROR, { detail: { error } })); }); } default: { return Promise.resolve(); } } }; class VieroWebRTCSFUClient extends _eventTargetShim.EventTarget { constructor(peerConnectionConfiguration) { super(); this.$ = { peerConnectionConfiguration: peerConnectionConfiguration || DEFAULT_PEERCONNECTION_CONFIGURATION, onEnterProxy: onEnter.bind(null, this), onMessageProxy: onMessage.bind(null, this), onLeaveProxy: onLeave.bind(null, this), peers: [], stream: new MediaStream([]) }; } peer(socketId) { var peer = this.$.peers[socketId]; if (peer) { return stripPeer(peer); } return null; } peers() { return Object.values(this.$.peers).map(peer => stripPeer(peer)); } join(signaling) { this.leave(); return signaling.connect().then(() => { signaling.addEventListener(_webrtcSignalingCommon.VieroWebRTCSignalingCommon.SIGNAL.ENTER, this.$.onEnterProxy); signaling.addEventListener(_webrtcSignalingCommon.VieroWebRTCSignalingCommon.SIGNAL.MESSAGE, this.$.onMessageProxy); signaling.addEventListener(_webrtcSignalingCommon.VieroWebRTCSignalingCommon.SIGNAL.LEAVE, this.$.onLeaveProxy); var opc = new RTCPeerConnection(this.$.peerConnectionConfiguration); opc.addEventListener('connectionstatechange', onConnectionStateChange.bind(null, this, null)); opc.addEventListener('icecandidate', onICECandidate.bind(null, this, null)); opc.addEventListener('iceconnectionstatechange', onICEConnectionStateChange.bind(null, this, null)); opc.addEventListener('icegatheringstatechange', onICEGatheringStateChange.bind(null, this, null)); opc.addEventListener('signalingstatechange', onSignalingStateChange.bind(null, this, null)); this.$.signaling = signaling; this.$.opc = opc; }); } leave() { if (this.$.signaling) { this.$.signaling.removeEventListener(_webrtcSignalingCommon.VieroWebRTCSignalingCommon.SIGNAL.ENTER, this.$.onEnterProxy); this.$.signaling.removeEventListener(_webrtcSignalingCommon.VieroWebRTCSignalingCommon.SIGNAL.MESSAGE, this.$.onMessageProxy); this.$.signaling.removeEventListener(_webrtcSignalingCommon.VieroWebRTCSignalingCommon.SIGNAL.LEAVE, this.$.onLeaveProxy); this.$.signaling.disconnect(); delete this.$.signaling; } if (this.$.opc) { this.$.opc.close(); delete this.$.opc; } Object.values(this.$.peers).forEach(peer => { if (peer.stream) { peer.stream.getTracks().forEach(t => t.stop()); } peer.ipc.close(); delete this.$.peers[peer.socketId]; }); } setStreams() { var streams = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; // 1. collect all tracks var tracks = streams.reduce((acc, stream) => { acc.push(...stream.getTracks()); return acc; }, []); // 2. save existing stream as previous var previous = this.$.stream; // 3. set new stream this.$.stream = new MediaStream(tracks); // 4. remove tracks from opc if (this.$.opc) { var senders = this.$.opc.getSenders(); if (senders.length) { senders.forEach(sender => this.$.opc.removeTrack(sender)); } // 5. add tracks to output stream this.$.stream.getTracks().forEach(track => this.$.opc.addTrack(track, this.$.stream)); onNegotiationNeeded(this); } // 6. remove tracks from previous if (previous) { Array.from(previous.getTracks()).forEach(t => { t.stop(); previous.removeTrack(t); }); } return this.$.stream; } } exports.VieroWebRTCSFUClient = VieroWebRTCSFUClient; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9pbmRleC5qcyJdLCJuYW1lcyI6WyJERUZBVUxUX1BFRVJDT05ORUNUSU9OX0NPTkZJR1VSQVRJT04iLCJpY2VTZXJ2ZXJzIiwidXJscyIsIm15U29ja2V0SWQiLCJzZWxmIiwiJCIsInNpZ25hbGluZyIsIl9zb2NrZXQiLCJpZCIsIm9uQ29ubmVjdGlvblN0YXRlQ2hhbmdlIiwicGVlciIsImV2dCIsInZhbHVlIiwiY3VycmVudFRhcmdldCIsImNvbm5lY3Rpb25TdGF0ZSIsImRpc3BhdGNoRXZlbnQiLCJDdXN0b21FdmVudCIsIlZpZXJvV2ViUlRDQ29tbW9uIiwiRVZFTlQiLCJXRUJSVEMiLCJTVEFURV9ESURfQ0hBTkdFIiwiZGV0YWlsIiwiZGlyZWN0aW9uIiwic29ja2V0SWQiLCJzdGF0ZSIsIm9uSUNFQ2FuZGlkYXRlIiwiY2FuZGlkYXRlIiwic2VuZCIsIndvcmQiLCJXT1JEIiwiQ0RUIiwiZGF0YSIsIkpTT04iLCJwYXJzZSIsInN0cmluZ2lmeSIsIm9uIiwib25JQ0VDb25uZWN0aW9uU3RhdGVDaGFuZ2UiLCJpY2VDb25uZWN0aW9uU3RhdGUiLCJvbklDRUdhdGhlcmluZ1N0YXRlQ2hhbmdlIiwiaWNlR2F0aGVyaW5nU3RhdGUiLCJvbk5lZ290aWF0aW9uTmVlZGVkIiwicGMiLCJpcGMiLCJvcGMiLCJjcmVhdGVPZmZlciIsInRoZW4iLCJvZmZlciIsInNldExvY2FsRGVzY3JpcHRpb24iLCJTRFAiLCJsb2NhbERlc2NyaXB0aW9uIiwiY2F0Y2giLCJlcnIiLCJlcnJvciIsIlZpZXJvRXJyb3IiLCJLRVkiLCJFUlJPUiIsIm9uU2lnbmFsaW5nU3RhdGVDaGFuZ2UiLCJzaWduYWxpbmdTdGF0ZSIsIm9uVHJhY2siLCJzdHJlYW1zIiwibGVuZ3RoIiwic3RyZWFtIiwiYWRkRXZlbnRMaXN0ZW5lciIsInNldFRpbWVvdXQiLCJUUkFDSyIsIkRJRF9SRU1PVkUiLCJESURfQUREIiwic3RyaXBQZWVyIiwiTWVkaWFTdHJlYW0iLCJhZGRQZWVyIiwiUlRDUGVlckNvbm5lY3Rpb24iLCJwZWVyQ29ubmVjdGlvbkNvbmZpZ3VyYXRpb24iLCJiaW5kIiwicGVlcnMiLCJQRUVSIiwiRElEX0VOVEVSIiwicmVtb3ZlUGVlciIsImNsb3NlIiwiRElEX0xFQVZFIiwib25FbnRlciIsIm9uTGVhdmUiLCJvbk1lc3NhZ2UiLCJwYXlsb2FkIiwiSEVMTE8iLCJmb3JFYWNoIiwic2RwIiwiUlRDU2Vzc2lvbkRlc2NyaXB0aW9uIiwidHlwZSIsInNldFJlbW90ZURlc2NyaXB0aW9uIiwiY3JlYXRlQW5zd2VyIiwiYW5zd2VyIiwiUHJvbWlzZSIsInJlc29sdmUiLCJjZHQiLCJSVENJY2VDYW5kaWRhdGUiLCJhZGRJY2VDYW5kaWRhdGUiLCJWaWVyb1dlYlJUQ1NGVUNsaWVudCIsIkV2ZW50VGFyZ2V0IiwiY29uc3RydWN0b3IiLCJvbkVudGVyUHJveHkiLCJvbk1lc3NhZ2VQcm94eSIsIm9uTGVhdmVQcm94eSIsIk9iamVjdCIsInZhbHVlcyIsIm1hcCIsImpvaW4iLCJsZWF2ZSIsImNvbm5lY3QiLCJWaWVyb1dlYlJUQ1NpZ25hbGluZ0NvbW1vbiIsIlNJR05BTCIsIkVOVEVSIiwiTUVTU0FHRSIsIkxFQVZFIiwicmVtb3ZlRXZlbnRMaXN0ZW5lciIsImRpc2Nvbm5lY3QiLCJnZXRUcmFja3MiLCJ0Iiwic3RvcCIsInNldFN0cmVhbXMiLCJ0cmFja3MiLCJyZWR1Y2UiLCJhY2MiLCJwdXNoIiwicHJldmlvdXMiLCJzZW5kZXJzIiwiZ2V0U2VuZGVycyIsInNlbmRlciIsInJlbW92ZVRyYWNrIiwidHJhY2siLCJhZGRUcmFjayIsIkFycmF5IiwiZnJvbSJdLCJtYXBwaW5ncyI6Ijs7QUFBQTs7Ozs7Ozs7Ozs7Ozs7O0FBZ0JBLGEsQ0FFQTs7Ozs7OztBQUNBOztBQUNBOztBQUVBOztBQUNBOztBQUNBOzs7Ozs7Ozs7O0FBRUEsSUFBTUEsb0NBQW9DLEdBQUc7QUFDM0NDLEVBQUFBLFVBQVUsRUFBRSxDQUNWO0FBQUVDLElBQUFBLElBQUksRUFBRTtBQUFS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Q0FBTCxDQUFPd0QsTUFBZDtBQUNEOztBQWpHbUQiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvcHlyaWdodCAyMDIwIFZpZXJvLCBJbmMuXG4gKlxuICogUGVybWlzc2lvbiB0byB1c2UsIGNvcHksIG1vZGlmeSwgYW5kL29yIGRpc3RyaWJ1dGUgdGhpcyBzb2Z0d2FyZSBmb3IgYW55XG4gKiBwdXJwb3NlIHdpdGggb3Igd2l0aG91dCBmZWUgaXMgaGVyZWJ5IGdyYW50ZWQsIHByb3ZpZGVkIHRoYXQgdGhlIGFib3ZlXG4gKiBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIGFwcGVhciBpbiBhbGwgY29waWVzLlxuICpcbiAqIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIgQU5EIFRIRSBBVVRIT1IgRElTQ0xBSU1TIEFMTCBXQVJSQU5USUVTXG4gKiBXSVRIIFJFR0FSRCBUTyBUSElTIFNPRlRXQVJFIElOQ0xVRElORyBBTEwgSU1QTElFRCBXQVJSQU5USUVTIE9GXG4gKiBNRVJDSEFOVEFCSUxJVFkgQU5EIEZJVE5FU1MuIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBBVVRIT1IgQkUgTElBQkxFIEZPUlxuICogQU5ZIFNQRUNJQUwsIERJUkVDVCwgSU5ESVJFQ1QsIE9SIENPTlNFUVVFTlRJQUwgREFNQUdFUyBPUiBBTlkgREFNQUdFU1xuICogV0hBVFNPRVZFUiBSRVNVTFRJTkcgRlJPTSBMT1NTIE9GIFVTRSwgREFUQSBPUiBQUk9GSVRTLCBXSEVUSEVSIElOIEFOXG4gKiBBQ1RJT04gT0YgQ09OVFJBQ1QsIE5FR0xJR0VOQ0UgT1IgT1RIRVIgVE9SVElPVVMgQUNUSU9OLCBBUklTSU5HIE9VVCBPRlxuICogT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBVU0UgT1IgUEVSRk9STUFOQ0UgT0YgVEhJUyBTT0ZUV0FSRS5cbiAqL1xuXG4ndXNlLXN0cmljdCc7XG5cbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby11bnVzZWQtdmFyc1xuaW1wb3J0IGFkYXB0ZXIgZnJvbSAnd2VicnRjLWFkYXB0ZXInO1xuaW1wb3J0IHsgRXZlbnRUYXJnZXQgfSBmcm9tICdldmVudC10YXJnZXQtc2hpbSc7XG5cbmltcG9ydCB7IFZpZXJvRXJyb3IgfSBmcm9tICdAdmllcm8vY29tbW9uL2Vycm9yJztcbmltcG9ydCB7IFZpZXJvV2ViUlRDU2lnbmFsaW5nQ29tbW9uIH0gZnJvbSAnQHZpZXJvL3dlYnJ0Yy1zaWduYWxpbmctY29tbW9uJztcbmltcG9ydCB7IFZpZXJvV2ViUlRDQ29tbW9uIH0gZnJvbSAnQHZpZXJvL3dlYnJ0Yy1jb21tb24nO1xuXG5jb25zdCBERUZBVUxUX1BFRVJDT05ORUNUSU9OX0NPTkZJR1VSQVRJT04gPSB7XG4gIGljZVNlcnZlcnM6IFtcbiAgICB7IHVybHM6ICdzdHVuOnN0dW4ubC5nb29nbGUuY29tOjE5MzAyJyB9LFxuICBdLFxufTtcblxuY29uc3QgbXlTb2NrZXRJZCA9IChzZWxmKSA9PiB7XG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby11bmRlcnNjb3JlLWRhbmdsZVxuICBpZiAoc2VsZi4kLnNpZ25hbGluZyAmJiBzZWxmLiQuc2lnbmFsaW5nLl9zb2NrZXQgJiYgc2VsZi4kLnNpZ25hbGluZy5fc29ja2V0LmlkKSB7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXVuZGVyc2NvcmUtZGFuZ2xlXG4gICAgcmV0dXJuIHNlbGYuJC5zaWduYWxpbmcuX3NvY2tldC5pZDtcbiAgfVxuICByZXR1cm4gbnVsbDtcbn07XG5cbmNvbnN0IG9uQ29ubmVjdGlvblN0YXRlQ2hhbmdlID0gKHNlbGYsIHBlZXIsIGV2dCkgPT4ge1xuICBjb25zdCB2YWx1ZSA9IGV2dC5jdXJyZW50VGFyZ2V0LmNvbm5lY3Rpb25TdGF0ZTtcbiAgc2VsZi5kaXNwYXRjaEV2ZW50KG5ldyBDdXN0b21FdmVudChWaWVyb1dlYlJUQ0NvbW1vbi5FVkVOVC5XRUJSVEMuU1RBVEVfRElEX0NIQU5HRSwge1xuICAgIGRldGFpbDoge1xuICAgICAgZGlyZWN0aW9uOiBwZWVyID8gJ2luJyA6ICdvdXQnLFxuICAgICAgaWQ6IHBlZXIgPyBwZWVyLnNvY2tldElkIDogbXlTb2NrZXRJZChzZWxmKSxcbiAgICAgIHN0YXRlOiAnY29ubmVjdGlvblN0YXRlJyxcbiAgICAgIHZhbHVlLFxuICAgIH0sXG4gIH0pKTtcbiAgaWYgKHZhbHVlID09PSAnZGlzY29ubmVjdGVkJykge1xuICAgIGlmIChwZWVyKSB7XG4gICAgICAvLyB0aGUgcGVlcidzIGlwYyBkaXNjb25uZWN0ZWRcbiAgICAgIC8vIDEuIHdlIG5lZWQgdG8gY2hlY2sgd2hldGhlciBzaWduYWxpbmcgaXMgc3RpbGwgb25cbiAgICAgIC8vIDIuIGlmIG5vdCwgd2UgbXVzdCBsZWF2ZVxuICAgICAgLy8gMy4gaWYgaXQgaXMsIHdlIG5lZWQgdG8gYXNrIHRoZSBzZXJ2ZXIgdG8gcmVuZWdvdGlhdGVcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gb3VyIG9wYyBpcyBkaXNjb25uZWN0ZWRcbiAgICAgIC8vIDEuIHdlIG5lZWQgdG8gY2hlY2sgd2hldGhlciBzaWduYWxpbmcgaXMgc3RpbGwgb25cbiAgICAgIC8vIDIuIGlmIG5vdCwgd2UgbXVzdCBsZWF2ZVxuICAgICAgLy8gMy4gaWYgaXQgaXMsIHdlIG5lZWQgdG8gcmVuZWdvdGlhdGVcbiAgICB9XG4gIH0gZWxzZSBpZiAodmFsdWUgPT09ICdmYWlsZWQnKSB7XG4gICAgLy8gbm90IHN1cmUgaG93IHRvIGhhbmRsZSB0aGlzXG4gIH1cbn07XG5cbmNvbnN0IG9uSUNFQ2FuZGlkYXRlID0gKHNlbGYsIHBlZXIsIGV2dCkgPT4ge1xuICBpZiAoZXZ0LmNhbmRpZGF0ZSkge1xuICAgIHNlbGYuJC5zaWduYWxpbmcuc2VuZCh7XG4gICAgICB3b3JkOiBWaWVyb1dlYlJUQ0NvbW1vbi5XT1JELkNEVCxcbiAgICAgIGRhdGE6IEpTT04ucGFyc2UoSlNPTi5zdHJpbmdpZnkoZXZ0LmNhbmRpZGF0ZSkpLFxuICAgICAgLi4uKHBlZXIgPyB7IG9uOiBwZWVyLnNvY2tldElkIH0gOiB7fSksXG4gICAgfSk7XG4gIH1cbn07XG5cbmNvbnN0IG9uSUNFQ29ubmVjdGlvblN0YXRlQ2hhbmdlID0gKHNlbGYsIHBlZXIsIGV2dCkgPT4ge1xuICBzZWxmLmRpc3BhdGNoRXZlbnQobmV3IEN1c3RvbUV2ZW50KFZpZXJvV2ViUlRDQ29tbW9uLkVWRU5ULldFQlJUQy5TVEFURV9ESURfQ0hBTkdFLCB7XG4gICAgZGV0YWlsOiB7XG4gICAgICBkaXJlY3Rpb246IHBlZXIgPyAnaW4nIDogJ291dCcsXG4gICAgICBpZDogcGVlciA/IHBlZXIuc29ja2V0SWQgOiBteVNvY2tldElkKHNlbGYpLFxuICAgICAgc3RhdGU6ICdpY2VDb25uZWN0aW9uU3RhdGUnLFxuICAgICAgdmFsdWU6IGV2dC5jdXJyZW50VGFyZ2V0LmljZUNvbm5lY3Rpb25TdGF0ZSxcbiAgICB9LFxuICB9KSk7XG59O1xuXG5jb25zdCBvbklDRUdhdGhlcmluZ1N0YXRlQ2hhbmdlID0gKHNlbGYsIHBlZXIsIGV2dCkgPT4ge1xuICBzZWxmLmRpc3BhdGNoRXZlbnQobmV3IEN1c3RvbUV2ZW50KFZpZXJvV2ViUlRDQ29tbW9uLkVWRU5ULldFQlJUQy5TVEFURV9ESURfQ0hBTkdFLCB7XG4gICAgZGV0YWlsOiB7XG4gICAgICBkaXJlY3Rpb246IHBlZXIgPyAnaW4nIDogJ291dCcsXG4gICAgICBpZDogcGVlciA/IHBlZXIuc29ja2V0SWQgOiBteVNvY2tldElkKHNlbGYpLFxuICAgICAgc3RhdGU6ICdpY2VHYXRoZXJpbmdTdGF0ZScsXG4gICAgICB2YWx1ZTogZXZ0LmN1cnJlbnRUYXJnZXQuaWNlR2F0aGVyaW5nU3RhdGUsXG4gICAgfSxcbiAgfSkpO1xufTtcblxuY29uc3Qgb25OZWdvdGlhdGlvbk5lZWRlZCA9IChzZWxmLCBwZWVyKSA9PiB7XG4gIGNvbnN0IHBjID0gcGVlciA/IHBlZXIuaXBjIDogc2VsZi4kLm9wYztcbiAgcGMuY3JlYXRlT2ZmZXIoKVxuICAgIC50aGVuKChvZmZlcikgPT4gcGMuc2V0TG9jYWxEZXNjcmlwdGlvbihvZmZlcikpXG4gICAgLnRoZW4oKCkgPT4gc2VsZi4kLnNpZ25hbGluZy5zZW5kKHtcbiAgICAgIHdvcmQ6IFZpZXJvV2ViUlRDQ29tbW9uLldPUkQuU0RQLFxuICAgICAgZGF0YTogSlNPTi5wYXJzZShKU09OLnN0cmluZ2lmeShwYy5sb2NhbERlc2NyaXB0aW9uKSksXG4gICAgfSkpXG4gICAgLmNhdGNoKChlcnIpID0+IHtcbiAgICAgIGNvbnN0IGVycm9yID0gbmV3IFZpZXJvRXJyb3IoJy93ZWJydGMvc2Z1L2NsaWVudCcsIDg4NDc2MSwgeyBbVmllcm9FcnJvci5LRVkuRVJST1JdOiBlcnIgfSk7XG4gICAgICBzZWxmLmRpc3BhdGNoRXZlbnQobmV3IEN1c3RvbUV2ZW50KFZpZXJvV2ViUlRDQ29tbW9uLkVWRU5ULkVSUk9SLCB7IGRldGFpbDogeyBlcnJvciB9IH0pKTtcbiAgICB9KTtcbn07XG5cbmNvbnN0IG9uU2lnbmFsaW5nU3RhdGVDaGFuZ2UgPSAoc2VsZiwgcGVlciwgZXZ0KSA9PiB7XG4gIHNlbGYuZGlzcGF0Y2hFdmVudChuZXcgQ3VzdG9tRXZlbnQoVmllcm9XZWJSVENDb21tb24uRVZFTlQuV0VCUlRDLlNUQVRFX0RJRF9DSEFOR0UsIHtcbiAgICBkZXRhaWw6IHtcbiAgICAgIGRpcmVjdGlvbjogcGVlciA/ICdpbicgOiAnb3V0JyxcbiAgICAgIGlkOiBwZWVyID8gcGVlci5zb2NrZXRJZCA6IG15U29ja2V0SWQoc2VsZiksXG4gICAgICBzdGF0ZTogJ3NpZ25hbGluZ1N0YXRlJyxcbiAgICAgIHZhbHVlOiBldnQuY3VycmVudFRhcmdldC5zaWduYWxpbmdTdGF0ZSxcbiAgICB9LFxuICB9KSk7XG59O1xuXG5jb25zdCBvblRyYWNrID0gKHNlbGYsIHBlZXIsIGV2dCkgPT4ge1xuICBpZiAoZXZ0LnN0cmVhbXMgJiYgZXZ0LnN0cmVhbXMubGVuZ3RoKSB7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIHByZWZlci1kZXN0cnVjdHVyaW5nLCBuby1wYXJhbS1yZWFzc2lnblxuICAgIHBlZXIuc3RyZWFtID0gZXZ0LnN0cmVhbXNbMF07XG4gICAgcGVlci5zdHJlYW0uYWRkRXZlbnRMaXN0ZW5lcigncmVtb3ZldHJhY2snLCAoKSA9PiB7XG4gICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgc2VsZi5kaXNwYXRjaEV2ZW50KG5ldyBDdXN0b21FdmVudChWaWVyb1dlYlJUQ0NvbW1vbi5FVkVOVC5UUkFDSy5ESURfUkVNT1ZFLCB7IGRldGFpbDogeyBwZWVyIH0gfSkpO1xuICAgICAgfSwgMCk7XG4gICAgfSk7XG4gICAgc2VsZi5kaXNwYXRjaEV2ZW50KG5ldyBDdXN0b21FdmVudChWaWVyb1dlYlJUQ0NvbW1vbi5FVkVOVC5UUkFDSy5ESURfQURELCB7IGRldGFpbDogeyBwZWVyIH0gfSkpO1xuICB9XG59O1xuXG5jb25zdCBzdHJpcFBlZXIgPSAocGVlcikgPT4gKHsgc29ja2V0SWQ6IHBlZXIuc29ja2V0SWQsIHN0cmVhbTogcGVlci5zdHJlYW0gfHwgbmV3IE1lZGlhU3RyZWFtKFtdKSB9KTtcblxuY29uc3QgYWRkUGVlciA9IChzZWxmLCBzb2NrZXRJZCkgPT4ge1xuICBjb25zdCBpcGMgPSBuZXcgUlRDUGVlckNvbm5lY3Rpb24oc2VsZi4kLnBlZXJDb25uZWN0aW9uQ29uZmlndXJhdGlvbik7XG4gIGNvbnN0IHBlZXIgPSB7IHNvY2tldElkLCBpcGMsIHN0cmVhbTogbmV3IE1lZGlhU3RyZWFtKFtdKSB9O1xuXG4gIGlwYy5hZGRFdmVudExpc3RlbmVyKCdjb25uZWN0aW9uc3RhdGVjaGFuZ2UnLCBvbkNvbm5lY3Rpb25TdGF0ZUNoYW5nZS5iaW5kKG51bGwsIHNlbGYsIHBlZXIpKTtcbiAgaXBjLmFkZEV2ZW50TGlzdGVuZXIoJ2ljZWNhbmRpZGF0ZScsIG9uSUNFQ2FuZGlkYXRlLmJpbmQobnVsbCwgc2VsZiwgcGVlcikpO1xuICBpcGMuYWRkRXZlbnRMaXN0ZW5lcignaWNlY29ubmVjdGlvbnN0YXRlY2hhbmdlJywgb25JQ0VDb25uZWN0aW9uU3RhdGVDaGFuZ2UuYmluZChudWxsLCBzZWxmLCBwZWVyKSk7XG4gIGlwYy5hZGRFdmVudExpc3RlbmVyKCdpY2VnYXRoZXJpbmdzdGF0ZWNoYW5nZScsIG9uSUNFR2F0aGVyaW5nU3RhdGVDaGFuZ2UuYmluZChudWxsLCBzZWxmLCBwZWVyKSk7XG4gIGlwYy5hZGRFdmVudExpc3RlbmVyKCdzaWduYWxpbmdzdGF0ZWNoYW5nZScsIG9uU2lnbmFsaW5nU3RhdGVDaGFuZ2UuYmluZChudWxsLCBzZWxmLCBwZWVyKSk7XG4gIGlwYy5hZGRFdmVudExpc3RlbmVyKCd0cmFjaycsIG9uVHJhY2suYmluZChudWxsLCBzZWxmLCBwZWVyKSk7XG5cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXBhcmFtLXJlYXNzaWduXG4gIHNlbGYuJC5wZWVyc1tzb2NrZXRJZF0gPSBwZWVyO1xuICBzZWxmLmRpc3BhdGNoRXZlbnQobmV3IEN1c3RvbUV2ZW50KFZpZXJvV2ViUlRDQ29tbW9uLkVWRU5ULlBFRVIuRElEX0VOVEVSLCB7IGRldGFpbDogeyBwZWVyOiBzdHJpcFBlZXIocGVlcikgfSB9KSk7XG4gIHJldHVybiBwZWVyO1xufTtcblxuY29uc3QgcmVtb3ZlUGVlciA9IChzZWxmLCBwZWVyKSA9PiB7XG4gIHBlZXIuaXBjLmNsb3NlKCk7XG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1wYXJhbS1yZWFzc2lnblxuICBkZWxldGUgc2VsZi4kLnBlZXJzW3BlZXIuc29ja2V0SWRdO1xuICBzZWxmLmRpc3BhdGNoRXZlbnQobmV3IEN1c3RvbUV2ZW50KFZpZXJvV2ViUlRDQ29tbW9uLkVWRU5ULlBFRVIuRElEX0xFQVZFLCB7IGRldGFpbDogeyBwZWVyOiBzdHJpcFBlZXIocGVlcikgfSB9KSk7XG59O1xuXG5jb25zdCBvbkVudGVyID0gKHNlbGYsIGV2dCkgPT4ge1xuICBhZGRQZWVyKHNlbGYsIGV2dC5kZXRhaWwuc29ja2V0SWQpO1xufTtcblxuY29uc3Qgb25MZWF2ZSA9IChzZWxmLCBldnQpID0+IHtcbiAgY29uc3QgcGVlciA9IHNlbGYuJC5wZWVyc1tldnQuZGV0YWlsLnNvY2tldElkXTtcbiAgaWYgKCFwZWVyKSByZXR1cm47XG4gIHJlbW92ZVBlZXIoc2VsZiwgcGVlcik7XG59O1xuXG5jb25zdCBvbk1lc3NhZ2UgPSAoc2VsZiwgZXZ0KSA9PiB7XG4gIGNvbnN0IHsgcGF5bG9hZCB9ID0gZXZ0LmRldGFpbDtcbiAgc3dpdGNoIChwYXlsb2FkLndvcmQpIHtcbiAgICBjYXNlIFZpZXJvV2ViUlRDQ29tbW9uLldPUkQuSEVMTE86IHtcbiAgICAgIHJldHVybiBwYXlsb2FkLmRhdGEuZm9yRWFjaCgoc29ja2V0SWQpID0+IHtcbiAgICAgICAgYWRkUGVlcihzZWxmLCBzb2NrZXRJZCk7XG4gICAgICB9KTtcbiAgICB9XG4gICAgY2FzZSBWaWVyb1dlYlJUQ0NvbW1vbi5XT1JELlNEUDoge1xuICAgICAgY29uc3Qgc2RwID0gbmV3IFJUQ1Nlc3Npb25EZXNjcmlwdGlvbihwYXlsb2FkLmRhdGEpO1xuICAgICAgY29uc3QgcGVlciA9IHNlbGYuJC5wZWVyc1twYXlsb2FkLm9uXTtcbiAgICAgIHN3aXRjaCAoc2RwLnR5cGUpIHtcbiAgICAgICAgY2FzZSAnb2ZmZXInOiB7XG4gICAgICAgICAgLy8gRE9ORVxuICAgICAgICAgIC8vIHJlY2VpdmVkIGFuIG9mZmVyLCBhbnN3ZXIgaXRcbiAgICAgICAgICBjb25zdCB7IGlwYyB9ID0gcGVlcjtcbiAgICAgICAgICByZXR1cm4gaXBjLnNldFJlbW90ZURlc2NyaXB0aW9uKHNkcClcbiAgICAgICAgICAgIC50aGVuKCgpID0+IGlwYy5jcmVhdGVBbnN3ZXIoKSlcbiAgICAgICAgICAgIC50aGVuKChhbnN3ZXIpID0+IGlwYy5zZXRMb2NhbERlc2NyaXB0aW9uKGFuc3dlcikpXG4gICAgICAgICAgICAudGhlbigoKSA9PiBzZWxmLiQuc2lnbmFsaW5nLnNlbmQoe1xuICAgICAgICAgICAgICB3b3JkOiBWaWVyb1dlYlJUQ0NvbW1vbi5XT1JELlNEUCxcbiAgICAgICAgICAgICAgb246IHBheWxvYWQub24sXG4gICAgICAgICAgICAgIGRhdGE6IEpTT04ucGFyc2UoSlNPTi5zdHJpbmdpZnkoaXBjLmxvY2FsRGVzY3JpcHRpb24pKSxcbiAgICAgICAgICAgIH0pKVxuICAgICAgICAgICAgLmNhdGNoKChlcnIpID0+IHtcbiAgICAgICAgICAgICAgY29uc3QgZXJyb3IgPSBuZXcgVmllcm9FcnJvcignL3dlYnJ0Yy9zZnUvY2xpZW50JywgMzUyMTc3LCB7IFtWaWVyb0Vycm9yLktFWS5FUlJPUl06IGVyciB9KTtcbiAgICAgICAgICAgICAgc2VsZi5kaXNwYXRjaEV2ZW50KG5ldyBDdXN0b21FdmVudChWaWVyb1dlYlJUQ0NvbW1vbi5FVkVOVC5FUlJPUiwgeyBkZXRhaWw6IHsgZXJyb3IgfSB9KSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBjYXNlICdhbnN3ZXInOiB7XG4gICAgICAgICAgLy8gRE9ORVxuICAgICAgICAgIC8vIHJlY2VpdmVkIGFuIGFuc3dlclxuICAgICAgICAgIHJldHVybiBzZWxmLiQub3BjLnNldFJlbW90ZURlc2NyaXB0aW9uKHNkcClcbiAgICAgICAgICAgIC5jYXRjaCgoZXJyKSA9PiB7XG4gICAgICAgICAgICAgIGNvbnN0IGVycm9yID0gbmV3IFZpZXJvRXJyb3IoJy93ZWJydGMvc2Z1L2NsaWVudCcsIDY0NTE2NywgeyBbVmllcm9FcnJvci5LRVkuRVJST1JdOiBlcnIgfSk7XG4gICAgICAgICAgICAgIHNlbGYuZGlzcGF0Y2hFdmVudChuZXcgQ3VzdG9tRXZlbnQoVmllcm9XZWJSVENDb21tb24uRVZFTlQuRVJST1IsIHsgZGV0YWlsOiB7IGVycm9yIH0gfSkpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgZGVmYXVsdDoge1xuICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICBjYXNlIFZpZXJvV2ViUlRDQ29tbW9uLldPUkQuQ0RUOiB7XG4gICAgICBjb25zdCBjZHQgPSBuZXcgUlRDSWNlQ2FuZGlkYXRlKHBheWxvYWQuZGF0YSk7XG4gICAgICByZXR1cm4gKHBheWxvYWQub24gPyBzZWxmLiQucGVlcnNbcGF5bG9hZC5vbl0uaXBjIDogc2VsZi4kLm9wYykuYWRkSWNlQ2FuZGlkYXRlKGNkdClcbiAgICAgICAgLmNhdGNoKChlcnIpID0+IHtcbiAgICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBWaWVyb0Vycm9yKCcvd2VicnRjL3NmdS9jbGllbnQnLCA1MTg0NTAsIHtcbiAgICAgICAgICAgIFtWaWVyb0Vycm9yLktFWS5FUlJPUl06IGVyciwgZGF0YTogcGF5bG9hZC5kYXRhLFxuICAgICAgICAgIH0pO1xuICAgICAgICAgIHNlbGYuZGlzcGF0Y2hFdmVudChuZXcgQ3VzdG9tRXZlbnQoVmllcm9XZWJSVENDb21tb24uRVZFTlQuRVJST1IsIHsgZGV0YWlsOiB7IGVycm9yIH0gfSkpO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgZGVmYXVsdDoge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgIH1cbiAgfVxufTtcblxuZXhwb3J0IGNsYXNzIFZpZXJvV2ViUlRDU0ZVQ2xpZW50IGV4dGVuZHMgRXZlbnRUYXJnZXQge1xuICBjb25zdHJ1Y3RvcihwZWVyQ29ubmVjdGlvbkNvbmZpZ3VyYXRpb24pIHtcbiAgICBzdXBlcigpO1xuXG4gICAgdGhpcy4kID0ge1xuICAgICAgcGVlckNvbm5lY3Rpb25Db25maWd1cmF0aW9uOiBwZWVyQ29ubmVjdGlvbkNvbmZpZ3VyYXRpb24gfHwgREVGQVVMVF9QRUVSQ09OTkVDVElPTl9DT05GSUdVUkFUSU9OLFxuICAgICAgb25FbnRlclByb3h5OiBvbkVudGVyLmJpbmQobnVsbCwgdGhpcyksXG4gICAgICBvbk1lc3NhZ2VQcm94eTogb25NZXNzYWdlLmJpbmQobnVsbCwgdGhpcyksXG4gICAgICBvbkxlYXZlUHJveHk6IG9uTGVhdmUuYmluZChudWxsLCB0aGlzKSxcbiAgICAgIHBlZXJzOiBbXSxcbiAgICAgIHN0cmVhbTogbmV3IE1lZGlhU3RyZWFtKFtdKSxcbiAgICB9O1xuICB9XG5cbiAgcGVlcihzb2NrZXRJZCkge1xuICAgIGNvbnN0IHBlZXIgPSB0aGlzLiQucGVlcnNbc29ja2V0SWRdO1xuICAgIGlmIChwZWVyKSB7XG4gICAgICByZXR1cm4gc3RyaXBQZWVyKHBlZXIpO1xuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHBlZXJzKCkge1xuICAgIHJldHVybiBPYmplY3QudmFsdWVzKHRoaXMuJC5wZWVycykubWFwKChwZWVyKSA9PiBzdHJpcFBlZXIocGVlcikpO1xuICB9XG5cbiAgam9pbihzaWduYWxpbmcpIHtcbiAgICB0aGlzLmxlYXZlKCk7XG4gICAgcmV0dXJuIHNpZ25hbGluZy5jb25uZWN0KCkudGhlbigoKSA9PiB7XG4gICAgICBzaWduYWxpbmcuYWRkRXZlbnRMaXN0ZW5lcihWaWVyb1dlYlJUQ1NpZ25hbGluZ0NvbW1vbi5TSUdOQUwuRU5URVIsIHRoaXMuJC5vbkVudGVyUHJveHkpO1xuICAgICAgc2lnbmFsaW5nLmFkZEV2ZW50TGlzdGVuZXIoVmllcm9XZWJSVENTaWduYWxpbmdDb21tb24uU0lHTkFMLk1FU1NBR0UsIHRoaXMuJC5vbk1lc3NhZ2VQcm94eSk7XG4gICAgICBzaWduYWxpbmcuYWRkRXZlbnRMaXN0ZW5lcihWaWVyb1dlYlJUQ1NpZ25hbGluZ0NvbW1vbi5TSUdOQUwuTEVBVkUsIHRoaXMuJC5vbkxlYXZlUHJveHkpO1xuICAgICAgY29uc3Qgb3BjID0gbmV3IFJUQ1BlZXJDb25uZWN0aW9uKHRoaXMuJC5wZWVyQ29ubmVjdGlvbkNvbmZpZ3VyYXRpb24pO1xuICAgICAgb3BjLmFkZEV2ZW50TGlzdGVuZXIoJ2Nvbm5lY3Rpb25zdGF0ZWNoYW5nZScsIG9uQ29ubmVjdGlvblN0YXRlQ2hhbmdlLmJpbmQobnVsbCwgdGhpcywgbnVsbCkpO1xuICAgICAgb3BjLmFkZEV2ZW50TGlzdGVuZXIoJ2ljZWNhbmRpZGF0ZScsIG9uSUNFQ2FuZGlkYXRlLmJpbmQobnVsbCwgdGhpcywgbnVsbCkpO1xuICAgICAgb3BjLmFkZEV2ZW50TGlzdGVuZXIoJ2ljZWNvbm5lY3Rpb25zdGF0ZWNoYW5nZScsIG9uSUNFQ29ubmVjdGlvblN0YXRlQ2hhbmdlLmJpbmQobnVsbCwgdGhpcywgbnVsbCkpO1xuICAgICAgb3BjLmFkZEV2ZW50TGlzdGVuZXIoJ2ljZWdhdGhlcmluZ3N0YXRlY2hhbmdlJywgb25JQ0VHYXRoZXJpbmdTdGF0ZUNoYW5nZS5iaW5kKG51bGwsIHRoaXMsIG51bGwpKTtcbiAgICAgIG9wYy5hZGRFdmVudExpc3RlbmVyKCdzaWduYWxpbmdzdGF0ZWNoYW5nZScsIG9uU2lnbmFsaW5nU3RhdGVDaGFuZ2UuYmluZChudWxsLCB0aGlzLCBudWxsKSk7XG4gICAgICB0aGlzLiQuc2lnbmFsaW5nID0gc2lnbmFsaW5nO1xuICAgICAgdGhpcy4kLm9wYyA9IG9wYztcbiAgICB9KTtcbiAgfVxuXG4gIGxlYXZlKCkge1xuICAgIGlmICh0aGlzLiQuc2lnbmFsaW5nKSB7XG4gICAgICB0aGlzLiQuc2lnbmFsaW5nLnJlbW92ZUV2ZW50TGlzdGVuZXIoVmllcm9XZWJSVENTaWduYWxpbmdDb21tb24uU0lHTkFMLkVOVEVSLCB0aGlzLiQub25FbnRlclByb3h5KTtcbiAgICAgIHRoaXMuJC5zaWduYWxpbmcucmVtb3ZlRXZlbnRMaXN0ZW5lcihWaWVyb1dlYlJUQ1NpZ25hbGluZ0NvbW1vbi5TSUdOQUwuTUVTU0FHRSwgdGhpcy4kLm9uTWVzc2FnZVByb3h5KTtcbiAgICAgIHRoaXMuJC5zaWduYWxpbmcucmVtb3ZlRXZlbnRMaXN0ZW5lcihWaWVyb1dlYlJUQ1NpZ25hbGluZ0NvbW1vbi5TSUdOQUwuTEVBVkUsIHRoaXMuJC5vbkxlYXZlUHJveHkpO1xuICAgICAgdGhpcy4kLnNpZ25hbGluZy5kaXNjb25uZWN0KCk7XG4gICAgICBkZWxldGUgdGhpcy4kLnNpZ25hbGluZztcbiAgICB9XG4gICAgaWYgKHRoaXMuJC5vcGMpIHtcbiAgICAgIHRoaXMuJC5vcGMuY2xvc2UoKTtcbiAgICAgIGRlbGV0ZSB0aGlzLiQub3BjO1xuICAgIH1cbiAgICBPYmplY3QudmFsdWVzKHRoaXMuJC5wZWVycykuZm9yRWFjaCgocGVlcikgPT4ge1xuICAgICAgaWYgKHBlZXIuc3RyZWFtKSB7XG4gICAgICAgIHBlZXIuc3RyZWFtLmdldFRyYWNrcygpLmZvckVhY2goKHQpID0+IHQuc3RvcCgpKTtcbiAgICAgIH1cbiAgICAgIHBlZXIuaXBjLmNsb3NlKCk7XG4gICAgICBkZWxldGUgdGhpcy4kLnBlZXJzW3BlZXIuc29ja2V0SWRdO1xuICAgIH0pO1xuICB9XG5cbiAgc2V0U3RyZWFtcyhzdHJlYW1zID0gW10pIHtcbiAgICAvLyAxLiBjb2xsZWN0IGFsbCB0cmFja3NcbiAgICBjb25zdCB0cmFja3MgPSBzdHJlYW1zLnJlZHVjZSgoYWNjLCBzdHJlYW0pID0+IHtcbiAgICAgIGFjYy5wdXNoKC4uLnN0cmVhbS5nZXRUcmFja3MoKSk7XG4gICAgICByZXR1cm4gYWNjO1xuICAgIH0sIFtdKTtcblxuICAgIC8vIDIuIHNhdmUgZXhpc3Rpbmcgc3RyZWFtIGFzIHByZXZpb3VzXG4gICAgY29uc3QgcHJldmlvdXMgPSB0aGlzLiQuc3RyZWFtO1xuXG4gICAgLy8gMy4gc2V0IG5ldyBzdHJlYW1cbiAgICB0aGlzLiQuc3RyZWFtID0gbmV3IE1lZGlhU3RyZWFtKHRyYWNrcyk7XG5cbiAgICAvLyA0LiByZW1vdmUgdHJhY2tzIGZyb20gb3BjXG4gICAgaWYgKHRoaXMuJC5vcGMpIHtcbiAgICAgIGNvbnN0IHNlbmRlcnMgPSB0aGlzLiQub3BjLmdldFNlbmRlcnMoKTtcbiAgICAgIGlmIChzZW5kZXJzLmxlbmd0aCkge1xuICAgICAgICBzZW5kZXJzLmZvckVhY2goKHNlbmRlcikgPT4gdGhpcy4kLm9wYy5yZW1vdmVUcmFjayhzZW5kZXIpKTtcbiAgICAgIH1cblxuICAgICAgLy8gNS4gYWRkIHRyYWNrcyB0byBvdXRwdXQgc3RyZWFtXG4gICAgICB0aGlzLiQuc3RyZWFtLmdldFRyYWNrcygpLmZvckVhY2goKHRyYWNrKSA9PiB0aGlzLiQub3BjLmFkZFRyYWNrKHRyYWNrLCB0aGlzLiQuc3RyZWFtKSk7XG4gICAgICBvbk5lZ290aWF0aW9uTmVlZGVkKHRoaXMpO1xuICAgIH1cblxuICAgIC8vIDYuIHJlbW92ZSB0cmFja3MgZnJvbSBwcmV2aW91c1xuICAgIGlmIChwcmV2aW91cykge1xuICAgICAgQXJyYXkuZnJvbShwcmV2aW91cy5nZXRUcmFja3MoKSkuZm9yRWFjaCgodCkgPT4ge1xuICAgICAgICB0LnN0b3AoKTtcbiAgICAgICAgcHJldmlvdXMucmVtb3ZlVHJhY2sodCk7XG4gICAgICB9KTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuJC5zdHJlYW07XG4gIH1cbn1cbiJdfQ==