UNPKG

@jsprismarine/client

Version:
174 lines (173 loc) • 21.7 kB
"use strict"; Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } }); const require_runtime = require("./_virtual/_rolldown/runtime.cjs.cjs"); const require_set_interval_async = require("./node_modules/.pnpm/set-interval-async@3.0.3/node_modules/set-interval-async/dist/dynamic/set-interval-async2.cjs.cjs"); let _jsprismarine_logger = require("@jsprismarine/logger"); let _jsprismarine_prismarine = require("@jsprismarine/prismarine"); let _jsprismarine_raknet = require("@jsprismarine/raknet"); let node_crypto = require("node:crypto"); node_crypto = require_runtime.__toESM(node_crypto, 1); let node_dgram = require("node:dgram"); node_dgram = require_runtime.__toESM(node_dgram, 1); let node_events = require("node:events"); //#region src/index.ts var getRandomInt = (min, max) => { min = Math.ceil(min); max = Math.floor(max); return Math.floor(Math.random() * (max - min + 1)) + min; }; var PROTOCOL = 10; var DEF_MTU_SIZE = 1455; var RAKNET_TICK_LENGTH = 1 / 100; var Client = class extends node_events.EventEmitter { clientGUID = node_crypto.default.randomBytes(8).readBigInt64BE(); logger = new _jsprismarine_logger.Logger(); address; targetAddress; connection = null; socket = node_dgram.default.createSocket({ type: "udp4" }); get closed() { return false; } connecting = false; connected = false; offlineHandled = false; loginHandled = false; constructor() { super(); this.address = new _jsprismarine_raknet.InetAddress("0.0.0.0", getRandomInt(46e3, 49999)); this.socket.bind(this.address.getPort(), this.address.getAddress()); } /** * Creates a packet listener on given address and port. * @param {string} address - The address to listen on. * @param {number} port - The port to listen on. * @returns {Promise<Client>} The client instance. * @public */ async connect(address = "0.0.0.0", port = 19132) { this.targetAddress = new _jsprismarine_raknet.InetAddress(address, port); this.socket.on("message", (buffer) => { this.handle(buffer); }); if (this.connection) throw new Error("Already connected/connecting to server."); this.logger.info("JSPrismarine client is now attempting to connect..."); const timer = (0, require_set_interval_async.import_set_interval_async.setIntervalAsync)(async () => { if (this.closed) { await (0, require_set_interval_async.import_clear_interval_async.clearIntervalAsync)(timer); return; } if (!this.connecting) { const pk = new _jsprismarine_raknet.Protocol.UnconnectedPing(); pk.timestamp = BigInt(Date.now()); pk.encode(); await this.sendBuffer(pk.getBuffer()); } if (this.connected && !this.loginHandled) { const pk = new _jsprismarine_prismarine.Protocol.Packets.LoginPacket(); pk.encode(); const sendPk = new _jsprismarine_raknet.Protocol.Frame(); sendPk.reliability = 0; sendPk.content = pk.getBuffer(); this.connection.sendFrame(sendPk, _jsprismarine_raknet.ConnectionPriority.NORMAL); this.loginHandled = true; } this.connection?.update(Date.now()); }, RAKNET_TICK_LENGTH * 1e3); return this; } /** * Handles the incoming buffer. * @param {Buffer} buffer - The buffer to handle. * @private * @internal */ async handle(buffer) { const header = buffer.readUInt8(); if (this.connection && this.offlineHandled) { this.connection.handle(buffer); return; } let buf; switch (header) { case _jsprismarine_raknet.MessageIdentifiers.UNCONNECTED_PONG: buf = this.handleUnconnectedPong(buffer); await this.sendBuffer(buf); break; case _jsprismarine_raknet.MessageIdentifiers.OPEN_CONNECTION_REPLY_1: buf = this.handleOpenConnectionReply1(buffer); await this.sendBuffer(buf); break; case _jsprismarine_raknet.MessageIdentifiers.OPEN_CONNECTION_REPLY_2: this.handleOpenConnectionReply2(buffer); break; default: this.logger.warn(`Unhandled offline packet ID: ${header}`, "Client/handle"); } } handleUnconnectedPong(buffer) { const decodedPacket = new _jsprismarine_raknet.Protocol.UnconnectedPong(buffer); decodedPacket.decode(); if (!decodedPacket.isValid()) throw new Error("Received an invalid offline message"); const packet = new _jsprismarine_raknet.Protocol.OpenConnectionRequest1(); packet.protocol = PROTOCOL; packet.mtuSize = DEF_MTU_SIZE; packet.encode(); return packet.getBuffer(); } handleOpenConnectionReply1(buffer) { const decodedPacket = new _jsprismarine_raknet.Protocol.OpenConnectionReply1(buffer); decodedPacket.decode(); if (!decodedPacket.isValid()) throw new Error("Received an invalid offline message"); const packet = new _jsprismarine_raknet.Protocol.OpenConnectionRequest2(); packet.serverAddress = this.targetAddress; packet.mtuSize = DEF_MTU_SIZE; packet.clientGUID = this.clientGUID; packet.encode(); this.connecting = true; this.connection = new _jsprismarine_raknet.RakNetSession(this, DEF_MTU_SIZE, { address: this.address.getAddress(), port: this.address.getPort(), family: "IPv4", size: 0 }, (0, node_crypto.randomBytes)(8).readBigInt64BE()); return packet.getBuffer(); } handleOpenConnectionReply2(buffer) { const decodedPacket = new _jsprismarine_raknet.Protocol.OpenConnectionReply2(buffer); decodedPacket.decode(); if (!decodedPacket.isValid()) throw new Error("Received an invalid offline message"); const packet = new _jsprismarine_raknet.Protocol.ConnectionRequest(); packet.clientGUID = this.clientGUID; packet.requestTimestamp = BigInt(Date.now()); packet.encode(); const sendPacket = new _jsprismarine_raknet.Protocol.Frame(); sendPacket.reliability = 0; sendPacket.content = packet.getBuffer(); this.connection?.sendFrame(sendPacket, _jsprismarine_raknet.ConnectionPriority.NORMAL); this.offlineHandled = true; this.connected = true; } /** * Sends the buffer to the server * * @param buffer */ async sendBuffer(buffer) { this.socket.send(buffer, 0, buffer.byteLength, this.targetAddress.getPort(), this.targetAddress.getAddress()); } getSocket() { return this.socket; } getAddress() { return this.address; } async removeConnection(_connection, _reason) { throw new Error("Method not implemented."); } }; //#endregion exports.default = Client; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguY2pzLmNqcyIsIm5hbWVzIjpbXSwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgTG9nZ2VyIH0gZnJvbSAnQGpzcHJpc21hcmluZS9sb2dnZXInO1xuaW1wb3J0IHsgUHJvdG9jb2wgYXMgSlNQUHJvdG9jb2wgfSBmcm9tICdAanNwcmlzbWFyaW5lL3ByaXNtYXJpbmUnO1xuaW1wb3J0IHsgQ29ubmVjdGlvblByaW9yaXR5LCBJbmV0QWRkcmVzcywgTWVzc2FnZUlkZW50aWZpZXJzLCBQcm90b2NvbCwgUmFrTmV0U2Vzc2lvbiB9IGZyb20gJ0Bqc3ByaXNtYXJpbmUvcmFrbmV0JztcbmltcG9ydCBDcnlwdG8sIHsgcmFuZG9tQnl0ZXMgfSBmcm9tICdub2RlOmNyeXB0byc7XG5pbXBvcnQgRGdyYW0sIHsgdHlwZSBTb2NrZXQgfSBmcm9tICdub2RlOmRncmFtJztcbmltcG9ydCB7IEV2ZW50RW1pdHRlciB9IGZyb20gJ25vZGU6ZXZlbnRzJztcbmltcG9ydCB7IGNsZWFySW50ZXJ2YWxBc3luYywgc2V0SW50ZXJ2YWxBc3luYyB9IGZyb20gJ3NldC1pbnRlcnZhbC1hc3luYy9keW5hbWljJztcblxuLy8gaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9hLzE1Mjc4MjAvMzE0MjU1M1xuY29uc3QgZ2V0UmFuZG9tSW50ID0gKG1pbjogbnVtYmVyLCBtYXg6IG51bWJlcikgPT4ge1xuICAgIG1pbiA9IE1hdGguY2VpbChtaW4pO1xuICAgIG1heCA9IE1hdGguZmxvb3IobWF4KTtcbiAgICByZXR1cm4gTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogKG1heCAtIG1pbiArIDEpKSArIG1pbjtcbn07XG5cbi8vIE1pbmVjcmFmdCByZWxhdGVkIHByb3RvY29sXG5jb25zdCBQUk9UT0NPTCA9IDEwO1xuXG4vLyBNYXggbmV0IHRyYW5zZmVyIHVuaXRcbmNvbnN0IERFRl9NVFVfU0laRSA9IDE0NTU7XG5cbi8vIFJha25ldCB0aWNrc1xuY29uc3QgUkFLTkVUX1RQUyA9IDEwMDtcbmNvbnN0IFJBS05FVF9USUNLX0xFTkdUSCA9IDEgLyBSQUtORVRfVFBTO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBDbGllbnQgZXh0ZW5kcyBFdmVudEVtaXR0ZXIge1xuICAgIHByaXZhdGUgY2xpZW50R1VJRCA9IENyeXB0by5yYW5kb21CeXRlcyg4KS5yZWFkQmlnSW50NjRCRSgpO1xuICAgIHByaXZhdGUgcmVhZG9ubHkgbG9nZ2VyID0gbmV3IExvZ2dlcigpO1xuICAgIHByaXZhdGUgcmVhZG9ubHkgYWRkcmVzczogSW5ldEFkZHJlc3M7XG4gICAgcHJpdmF0ZSB0YXJnZXRBZGRyZXNzITogSW5ldEFkZHJlc3M7XG4gICAgcHJpdmF0ZSBjb25uZWN0aW9uOiBSYWtOZXRTZXNzaW9uIHwgbnVsbCA9IG51bGw7XG4gICAgcHJpdmF0ZSByZWFkb25seSBzb2NrZXQgPSBEZ3JhbS5jcmVhdGVTb2NrZXQoeyB0eXBlOiAndWRwNCcgfSk7XG4gICAgcHJpdmF0ZSBnZXQgY2xvc2VkKCkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBjb25uZWN0aW5nID0gZmFsc2U7XG4gICAgcHJpdmF0ZSBjb25uZWN0ZWQgPSBmYWxzZTtcbiAgICBwcml2YXRlIG9mZmxpbmVIYW5kbGVkID0gZmFsc2U7XG4gICAgcHJpdmF0ZSBsb2dpbkhhbmRsZWQgPSBmYWxzZTtcblxuICAgIHB1YmxpYyBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgc3VwZXIoKTtcbiAgICAgICAgdGhpcy5hZGRyZXNzID0gbmV3IEluZXRBZGRyZXNzKCcwLjAuMC4wJywgZ2V0UmFuZG9tSW50KDQ2MDAwLCA0OTk5OSkpO1xuICAgICAgICB0aGlzLnNvY2tldC5iaW5kKHRoaXMuYWRkcmVzcy5nZXRQb3J0KCksIHRoaXMuYWRkcmVzcy5nZXRBZGRyZXNzKCkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBwYWNrZXQgbGlzdGVuZXIgb24gZ2l2ZW4gYWRkcmVzcyBhbmQgcG9ydC5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gYWRkcmVzcyAtIFRoZSBhZGRyZXNzIHRvIGxpc3RlbiBvbi5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gcG9ydCAtIFRoZSBwb3J0IHRvIGxpc3RlbiBvbi5cbiAgICAgKiBAcmV0dXJucyB7UHJvbWlzZTxDbGllbnQ+fSBUaGUgY2xpZW50IGluc3RhbmNlLlxuICAgICAqIEBwdWJsaWNcbiAgICAgKi9cbiAgICBwdWJsaWMgYXN5bmMgY29ubmVjdChhZGRyZXNzID0gJzAuMC4wLjAnLCBwb3J0ID0gMTkxMzIpOiBQcm9taXNlPENsaWVudD4ge1xuICAgICAgICB0aGlzLnRhcmdldEFkZHJlc3MgPSBuZXcgSW5ldEFkZHJlc3MoYWRkcmVzcywgcG9ydCk7XG5cbiAgICAgICAgdGhpcy5zb2NrZXQub24oJ21lc3NhZ2UnLCAoYnVmZmVyOiBCdWZmZXIpID0+IHtcbiAgICAgICAgICAgIHZvaWQgdGhpcy5oYW5kbGUoYnVmZmVyKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYgKHRoaXMuY29ubmVjdGlvbikgdGhyb3cgbmV3IEVycm9yKCdBbHJlYWR5IGNvbm5lY3RlZC9jb25uZWN0aW5nIHRvIHNlcnZlci4nKTtcblxuICAgICAgICB0aGlzLmxvZ2dlci5pbmZvKCdKU1ByaXNtYXJpbmUgY2xpZW50IGlzIG5vdyBhdHRlbXB0aW5nIHRvIGNvbm5lY3QuLi4nKTtcblxuICAgICAgICBjb25zdCB0aW1lciA9IHNldEludGVydmFsQXN5bmMoYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMuY2xvc2VkKSB7XG4gICAgICAgICAgICAgICAgYXdhaXQgY2xlYXJJbnRlcnZhbEFzeW5jKHRpbWVyKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFNlbmQgYSBjbGllbnQgcGFja2V0IHRvIHRoZSBzZXJ2ZXJcbiAgICAgICAgICAgIC8vIHNvIHRoZSBzZXJ2ZXIgZ29lcyBpbiB0YXJnZXQgbW9kZVxuICAgICAgICAgICAgLy8gYW5kIHRoZSBsb2dpbiBwcm9jZXNzIHN0YXJ0c1xuICAgICAgICAgICAgaWYgKCF0aGlzLmNvbm5lY3RpbmcpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBwayA9IG5ldyBQcm90b2NvbC5VbmNvbm5lY3RlZFBpbmcoKTtcbiAgICAgICAgICAgICAgICBway50aW1lc3RhbXAgPSBCaWdJbnQoRGF0ZS5ub3coKSk7XG4gICAgICAgICAgICAgICAgLy8gVE9ETzogY2FuIGJlIG9taXR0ZWQuLi4gcGsuID0gdGhpcy5jbGllbnRHVUlEO1xuICAgICAgICAgICAgICAgIHBrLmVuY29kZSgpO1xuICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMuc2VuZEJ1ZmZlcihway5nZXRCdWZmZXIoKSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0aGlzLmNvbm5lY3RlZCAmJiAhdGhpcy5sb2dpbkhhbmRsZWQpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBwayA9IG5ldyBKU1BQcm90b2NvbC5QYWNrZXRzLkxvZ2luUGFja2V0KCk7XG4gICAgICAgICAgICAgICAgcGsuZW5jb2RlKCk7XG5cbiAgICAgICAgICAgICAgICBjb25zdCBzZW5kUGsgPSBuZXcgUHJvdG9jb2wuRnJhbWUoKTtcbiAgICAgICAgICAgICAgICBzZW5kUGsucmVsaWFiaWxpdHkgPSAwO1xuICAgICAgICAgICAgICAgIHNlbmRQay5jb250ZW50ID0gcGsuZ2V0QnVmZmVyKCk7XG5cbiAgICAgICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24hLnNlbmRGcmFtZShzZW5kUGssIENvbm5lY3Rpb25Qcmlvcml0eS5OT1JNQUwpOyAvLyBQYWNrZXQgbmVlZHMgdG8gYmUgc3BsaXR0ZWRcbiAgICAgICAgICAgICAgICB0aGlzLmxvZ2luSGFuZGxlZCA9IHRydWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbj8udXBkYXRlKERhdGUubm93KCkpO1xuICAgICAgICB9LCBSQUtORVRfVElDS19MRU5HVEggKiAxMDAwKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSGFuZGxlcyB0aGUgaW5jb21pbmcgYnVmZmVyLlxuICAgICAqIEBwYXJhbSB7QnVmZmVyfSBidWZmZXIgLSBUaGUgYnVmZmVyIHRvIGhhbmRsZS5cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBpbnRlcm5hbFxuICAgICAqL1xuICAgIHByaXZhdGUgYXN5bmMgaGFuZGxlKGJ1ZmZlcjogQnVmZmVyKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGNvbnN0IGhlYWRlciA9IGJ1ZmZlci5yZWFkVUludDgoKTsgLy8gUmVhZCBwYWNrZXQgaGVhZGVyXG5cbiAgICAgICAgaWYgKHRoaXMuY29ubmVjdGlvbiAmJiB0aGlzLm9mZmxpbmVIYW5kbGVkKSB7XG4gICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24uaGFuZGxlKGJ1ZmZlcik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgYnVmO1xuICAgICAgICBzd2l0Y2ggKGhlYWRlcikge1xuICAgICAgICAgICAgY2FzZSBNZXNzYWdlSWRlbnRpZmllcnMuVU5DT05ORUNURURfUE9ORzpcbiAgICAgICAgICAgICAgICBidWYgPSB0aGlzLmhhbmRsZVVuY29ubmVjdGVkUG9uZyhidWZmZXIpO1xuICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMuc2VuZEJ1ZmZlcihidWYpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBNZXNzYWdlSWRlbnRpZmllcnMuT1BFTl9DT05ORUNUSU9OX1JFUExZXzE6XG4gICAgICAgICAgICAgICAgYnVmID0gdGhpcy5oYW5kbGVPcGVuQ29ubmVjdGlvblJlcGx5MShidWZmZXIpO1xuICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMuc2VuZEJ1ZmZlcihidWYpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBNZXNzYWdlSWRlbnRpZmllcnMuT1BFTl9DT05ORUNUSU9OX1JFUExZXzI6XG4gICAgICAgICAgICAgICAgdGhpcy5oYW5kbGVPcGVuQ29ubmVjdGlvblJlcGx5MihidWZmZXIpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICB0aGlzLmxvZ2dlci53YXJuKGBVbmhhbmRsZWQgb2ZmbGluZSBwYWNrZXQgSUQ6ICR7aGVhZGVyfWAsICdDbGllbnQvaGFuZGxlJyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwdWJsaWMgaGFuZGxlVW5jb25uZWN0ZWRQb25nKGJ1ZmZlcjogQnVmZmVyKTogQnVmZmVyIHtcbiAgICAgICAgLy8gRGVjb2RlIHNlcnZlciBwYWNrZXRcbiAgICAgICAgY29uc3QgZGVjb2RlZFBhY2tldCA9IG5ldyBQcm90b2NvbC5VbmNvbm5lY3RlZFBvbmcoYnVmZmVyKTtcbiAgICAgICAgZGVjb2RlZFBhY2tldC5kZWNvZGUoKTtcblxuICAgICAgICAvLyBDaGVjayBwYWNrZXQgdmFsaWRpdHlcbiAgICAgICAgLy8gVG8gcmVmYWN0b3JcbiAgICAgICAgaWYgKCFkZWNvZGVkUGFja2V0LmlzVmFsaWQoKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdSZWNlaXZlZCBhbiBpbnZhbGlkIG9mZmxpbmUgbWVzc2FnZScpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gRW5jb2RlIHJlc3BvbnNlXG4gICAgICAgIGNvbnN0IHBhY2tldCA9IG5ldyBQcm90b2NvbC5PcGVuQ29ubmVjdGlvblJlcXVlc3QxKCk7XG4gICAgICAgIHBhY2tldC5wcm90b2NvbCA9IFBST1RPQ09MO1xuICAgICAgICBwYWNrZXQubXR1U2l6ZSA9IERFRl9NVFVfU0laRTtcbiAgICAgICAgcGFja2V0LmVuY29kZSgpO1xuXG4gICAgICAgIC8vIFVwZGF0ZSBzZXNzaW9uIHN0YXR1c1xuICAgICAgICAvLyB0aGlzLnN0YXR1cyA9IENvbm5lY3Rpb25TdGF0dXMuVGFyZ2V0dGVkO1xuXG4gICAgICAgIHJldHVybiBwYWNrZXQuZ2V0QnVmZmVyKCk7XG4gICAgfVxuXG4gICAgcHVibGljIGhhbmRsZU9wZW5Db25uZWN0aW9uUmVwbHkxKGJ1ZmZlcjogQnVmZmVyKTogQnVmZmVyIHtcbiAgICAgICAgLy8gRGVjb2RlIHNlcnZlciBwYWNrZXRcbiAgICAgICAgY29uc3QgZGVjb2RlZFBhY2tldCA9IG5ldyBQcm90b2NvbC5PcGVuQ29ubmVjdGlvblJlcGx5MShidWZmZXIpO1xuICAgICAgICBkZWNvZGVkUGFja2V0LmRlY29kZSgpO1xuXG4gICAgICAgIC8vIENoZWNrIHBhY2tldCB2YWxpZGl0eVxuICAgICAgICAvLyBUbyByZWZhY3RvclxuICAgICAgICBpZiAoIWRlY29kZWRQYWNrZXQuaXNWYWxpZCgpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1JlY2VpdmVkIGFuIGludmFsaWQgb2ZmbGluZSBtZXNzYWdlJyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBFbmNvZGUgcmVzcG9uc2VcbiAgICAgICAgY29uc3QgcGFja2V0ID0gbmV3IFByb3RvY29sLk9wZW5Db25uZWN0aW9uUmVxdWVzdDIoKTtcbiAgICAgICAgcGFja2V0LnNlcnZlckFkZHJlc3MgPSB0aGlzLnRhcmdldEFkZHJlc3M7XG4gICAgICAgIHBhY2tldC5tdHVTaXplID0gREVGX01UVV9TSVpFO1xuICAgICAgICBwYWNrZXQuY2xpZW50R1VJRCA9IHRoaXMuY2xpZW50R1VJRDtcbiAgICAgICAgcGFja2V0LmVuY29kZSgpO1xuXG4gICAgICAgIC8vIFVwZGF0ZSBzZXNzaW9uIHN0YXR1c1xuICAgICAgICB0aGlzLmNvbm5lY3RpbmcgPSB0cnVlO1xuICAgICAgICAvLyBUaGlzLnN0YXR1cyA9IENvbm5lY3Rpb25TdGF0dXMuQ29ubmVjdGVkO1xuICAgICAgICB0aGlzLmNvbm5lY3Rpb24gPSBuZXcgUmFrTmV0U2Vzc2lvbihcbiAgICAgICAgICAgIHRoaXMgYXMgYW55LFxuICAgICAgICAgICAgREVGX01UVV9TSVpFLFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIGFkZHJlc3M6IHRoaXMuYWRkcmVzcy5nZXRBZGRyZXNzKCksXG4gICAgICAgICAgICAgICAgcG9ydDogdGhpcy5hZGRyZXNzLmdldFBvcnQoKSxcbiAgICAgICAgICAgICAgICBmYW1pbHk6ICdJUHY0JyxcbiAgICAgICAgICAgICAgICBzaXplOiAwXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcmFuZG9tQnl0ZXMoOCkucmVhZEJpZ0ludDY0QkUoKVxuICAgICAgICApO1xuXG4gICAgICAgIHJldHVybiBwYWNrZXQuZ2V0QnVmZmVyKCk7XG4gICAgfVxuXG4gICAgcHVibGljIGhhbmRsZU9wZW5Db25uZWN0aW9uUmVwbHkyKGJ1ZmZlcjogQnVmZmVyKTogdm9pZCB7XG4gICAgICAgIC8vIERlY29kZSBzZXJ2ZXIgcGFja2V0XG4gICAgICAgIGNvbnN0IGRlY29kZWRQYWNrZXQgPSBuZXcgUHJvdG9jb2wuT3BlbkNvbm5lY3Rpb25SZXBseTIoYnVmZmVyKTtcbiAgICAgICAgZGVjb2RlZFBhY2tldC5kZWNvZGUoKTtcblxuICAgICAgICAvLyBDaGVjayBwYWNrZXQgdmFsaWRpdHlcbiAgICAgICAgLy8gVG8gcmVmYWN0b3JcbiAgICAgICAgaWYgKCFkZWNvZGVkUGFja2V0LmlzVmFsaWQoKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdSZWNlaXZlZCBhbiBpbnZhbGlkIG9mZmxpbmUgbWVzc2FnZScpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gRW5jb2RlIHJlc3BvbnNlIChlbmNhcHN1bGF0ZWQpXG4gICAgICAgIGNvbnN0IHBhY2tldCA9IG5ldyBQcm90b2NvbC5Db25uZWN0aW9uUmVxdWVzdCgpO1xuICAgICAgICBwYWNrZXQuY2xpZW50R1VJRCA9IHRoaXMuY2xpZW50R1VJRDtcbiAgICAgICAgcGFja2V0LnJlcXVlc3RUaW1lc3RhbXAgPSBCaWdJbnQoRGF0ZS5ub3coKSk7XG4gICAgICAgIHBhY2tldC5lbmNvZGUoKTtcblxuICAgICAgICBjb25zdCBzZW5kUGFja2V0ID0gbmV3IFByb3RvY29sLkZyYW1lKCk7XG4gICAgICAgIHNlbmRQYWNrZXQucmVsaWFiaWxpdHkgPSAwO1xuICAgICAgICBzZW5kUGFja2V0LmNvbnRlbnQgPSBwYWNrZXQuZ2V0QnVmZmVyKCk7XG5cbiAgICAgICAgdGhpcy5jb25uZWN0aW9uPy5zZW5kRnJhbWUoc2VuZFBhY2tldCwgQ29ubmVjdGlvblByaW9yaXR5Lk5PUk1BTCk7XG5cbiAgICAgICAgdGhpcy5vZmZsaW5lSGFuZGxlZCA9IHRydWU7XG4gICAgICAgIHRoaXMuY29ubmVjdGVkID0gdHJ1ZTsgLy8gU2hvdWxkIGJlLi4uIHdlIGNhbid0IHJlbHkgb24gaXRcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZW5kcyB0aGUgYnVmZmVyIHRvIHRoZSBzZXJ2ZXJcbiAgICAgKlxuICAgICAqIEBwYXJhbSBidWZmZXJcbiAgICAgKi9cbiAgICBwdWJsaWMgYXN5bmMgc2VuZEJ1ZmZlcihidWZmZXI6IEJ1ZmZlcik6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICB0aGlzLnNvY2tldC5zZW5kKFxuICAgICAgICAgICAgYnVmZmVyIGFzIGFueSxcbiAgICAgICAgICAgIDAsXG4gICAgICAgICAgICBidWZmZXIuYnl0ZUxlbmd0aCxcbiAgICAgICAgICAgIHRoaXMudGFyZ2V0QWRkcmVzcy5nZXRQb3J0KCksXG4gICAgICAgICAgICB0aGlzLnRhcmdldEFkZHJlc3MuZ2V0QWRkcmVzcygpXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgcHVibGljIGdldFNvY2tldCgpOiBTb2NrZXQge1xuICAgICAgICByZXR1cm4gdGhpcy5zb2NrZXQ7XG4gICAgfVxuXG4gICAgcHVibGljIGdldEFkZHJlc3MoKTogSW5ldEFkZHJlc3Mge1xuICAgICAgICByZXR1cm4gdGhpcy5hZGRyZXNzO1xuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyByZW1vdmVDb25uZWN0aW9uKF9jb25uZWN0aW9uOiBSYWtOZXRTZXNzaW9uLCBfcmVhc29uPzogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignTWV0aG9kIG5vdCBpbXBsZW1lbnRlZC4nKTtcbiAgICB9XG59XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7QUFTQSxJQUFNLGdCQUFnQixLQUFhLFFBQWdCO0NBQy9DLE1BQU0sS0FBSyxLQUFLLEdBQUc7Q0FDbkIsTUFBTSxLQUFLLE1BQU0sR0FBRztDQUNwQixPQUFPLEtBQUssTUFBTSxLQUFLLE9BQU8sS0FBSyxNQUFNLE1BQU0sRUFBRSxJQUFJO0FBQ3pEO0FBR0EsSUFBTSxXQUFXO0FBR2pCLElBQU0sZUFBZTtBQUlyQixJQUFNLHFCQUFxQixJQUFJO0FBRS9CLElBQXFCLFNBQXJCLGNBQW9DLFlBQUEsYUFBYTtDQUM3QyxhQUFxQixZQUFBLFFBQU8sWUFBWSxDQUFDLEVBQUUsZUFBZTtDQUMxRCxTQUEwQixJQUFJLHFCQUFBLE9BQU87Q0FDckM7Q0FDQTtDQUNBLGFBQTJDO0NBQzNDLFNBQTBCLFdBQUEsUUFBTSxhQUFhLEVBQUUsTUFBTSxPQUFPLENBQUM7Q0FDN0QsSUFBWSxTQUFTO0VBQ2pCLE9BQU87Q0FDWDtDQUVBLGFBQXFCO0NBQ3JCLFlBQW9CO0NBQ3BCLGlCQUF5QjtDQUN6QixlQUF1QjtDQUV2QixjQUFxQjtFQUNqQixNQUFNO0VBQ04sS0FBSyxVQUFVLElBQUkscUJBQUEsWUFBWSxXQUFXLGFBQWEsTUFBTyxLQUFLLENBQUM7RUFDcEUsS0FBSyxPQUFPLEtBQUssS0FBSyxRQUFRLFFBQVEsR0FBRyxLQUFLLFFBQVEsV0FBVyxDQUFDO0NBQ3RFOzs7Ozs7OztDQVNBLE1BQWEsUUFBUSxVQUFVLFdBQVcsT0FBTyxPQUF3QjtFQUNyRSxLQUFLLGdCQUFnQixJQUFJLHFCQUFB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