UNPKG

@jsprismarine/client

Version:
186 lines (183 loc) • 24.2 kB
import { Logger } from '@jsprismarine/logger'; import { Protocol as Protocol$1 } from '@jsprismarine/prismarine'; import { InetAddress, Protocol, ConnectionPriority, MessageIdentifiers, RakNetSession } from '@jsprismarine/raknet'; import Crypto, { randomBytes } from 'node:crypto'; import Dgram from 'node:dgram'; import { EventEmitter } from 'node:events'; import { c as clearIntervalAsyncExports } from './_virtual/clear-interval-async.es.js'; import { s as setIntervalAsyncExports } from './_virtual/set-interval-async.es.js'; const getRandomInt = (min, max) => { min = Math.ceil(min); max = Math.floor(max); return Math.floor(Math.random() * (max - min + 1)) + min; }; const PROTOCOL = 10; const DEF_MTU_SIZE = 1455; const RAKNET_TPS = 100; const RAKNET_TICK_LENGTH = 1 / RAKNET_TPS; class Client extends EventEmitter { clientGUID = Crypto.randomBytes(8).readBigInt64BE(); logger = new Logger(); address; targetAddress; connection = null; socket = Dgram.createSocket({ type: "udp4" }); get closed() { return false; } connecting = false; connected = false; offlineHandled = false; loginHandled = false; constructor() { super(); this.address = new 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 InetAddress(address, port); this.socket.on("message", (buffer) => { void 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 = setIntervalAsyncExports.setIntervalAsync(async () => { if (this.closed) { await clearIntervalAsyncExports.clearIntervalAsync(timer); return; } if (!this.connecting) { const pk = new Protocol.UnconnectedPing(); pk.timestamp = BigInt(Date.now()); pk.encode(); await this.sendBuffer(pk.getBuffer()); } if (this.connected && !this.loginHandled) { const pk = new Protocol$1.Packets.LoginPacket(); pk.encode(); const sendPk = new Protocol.Frame(); sendPk.reliability = 0; sendPk.content = pk.getBuffer(); this.connection.sendFrame(sendPk, 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 MessageIdentifiers.UNCONNECTED_PONG: buf = this.handleUnconnectedPong(buffer); await this.sendBuffer(buf); break; case MessageIdentifiers.OPEN_CONNECTION_REPLY_1: buf = this.handleOpenConnectionReply1(buffer); await this.sendBuffer(buf); break; case 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 Protocol.UnconnectedPong(buffer); decodedPacket.decode(); if (!decodedPacket.isValid()) { throw new Error("Received an invalid offline message"); } const packet = new Protocol.OpenConnectionRequest1(); packet.protocol = PROTOCOL; packet.mtuSize = DEF_MTU_SIZE; packet.encode(); return packet.getBuffer(); } handleOpenConnectionReply1(buffer) { const decodedPacket = new Protocol.OpenConnectionReply1(buffer); decodedPacket.decode(); if (!decodedPacket.isValid()) { throw new Error("Received an invalid offline message"); } const packet = new Protocol.OpenConnectionRequest2(); packet.serverAddress = this.targetAddress; packet.mtuSize = DEF_MTU_SIZE; packet.clientGUID = this.clientGUID; packet.encode(); this.connecting = true; this.connection = new RakNetSession( this, DEF_MTU_SIZE, { address: this.address.getAddress(), port: this.address.getPort(), family: "IPv4", size: 0 }, randomBytes(8).readBigInt64BE() ); return packet.getBuffer(); } handleOpenConnectionReply2(buffer) { const decodedPacket = new Protocol.OpenConnectionReply2(buffer); decodedPacket.decode(); if (!decodedPacket.isValid()) { throw new Error("Received an invalid offline message"); } const packet = new Protocol.ConnectionRequest(); packet.clientGUID = this.clientGUID; packet.requestTimestamp = BigInt(Date.now()); packet.encode(); const sendPacket = new Protocol.Frame(); sendPacket.reliability = 0; sendPacket.content = packet.getBuffer(); this.connection?.sendFrame(sendPacket, 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."); } } export { Client as default }; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguZXMuanMiLCJzb3VyY2VzIjpbIi4uL3NyYy9pbmRleC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBMb2dnZXIgfSBmcm9tICdAanNwcmlzbWFyaW5lL2xvZ2dlcic7XG5pbXBvcnQgeyBQcm90b2NvbCBhcyBKU1BQcm90b2NvbCB9IGZyb20gJ0Bqc3ByaXNtYXJpbmUvcHJpc21hcmluZSc7XG5pbXBvcnQgeyBDb25uZWN0aW9uUHJpb3JpdHksIEluZXRBZGRyZXNzLCBNZXNzYWdlSWRlbnRpZmllcnMsIFByb3RvY29sLCBSYWtOZXRTZXNzaW9uIH0gZnJvbSAnQGpzcHJpc21hcmluZS9yYWtuZXQnO1xuaW1wb3J0IENyeXB0bywgeyByYW5kb21CeXRlcyB9IGZyb20gJ25vZGU6Y3J5cHRvJztcbmltcG9ydCBEZ3JhbSwgeyB0eXBlIFNvY2tldCB9IGZyb20gJ25vZGU6ZGdyYW0nO1xuaW1wb3J0IHsgRXZlbnRFbWl0dGVyIH0gZnJvbSAnbm9kZTpldmVudHMnO1xuaW1wb3J0IHsgY2xlYXJJbnRlcnZhbEFzeW5jLCBzZXRJbnRlcnZhbEFzeW5jIH0gZnJvbSAnc2V0LWludGVydmFsLWFzeW5jL2R5bmFtaWMnO1xuXG4vLyBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL2EvMTUyNzgyMC8zMTQyNTUzXG5jb25zdCBnZXRSYW5kb21JbnQgPSAobWluOiBudW1iZXIsIG1heDogbnVtYmVyKSA9PiB7XG4gICAgbWluID0gTWF0aC5jZWlsKG1pbik7XG4gICAgbWF4ID0gTWF0aC5mbG9vcihtYXgpO1xuICAgIHJldHVybiBNYXRoLmZsb29yKE1hdGgucmFuZG9tKCkgKiAobWF4IC0gbWluICsgMSkpICsgbWluO1xufTtcblxuLy8gTWluZWNyYWZ0IHJlbGF0ZWQgcHJvdG9jb2xcbmNvbnN0IFBST1RPQ09MID0gMTA7XG5cbi8vIE1heCBuZXQgdHJhbnNmZXIgdW5pdFxuY29uc3QgREVGX01UVV9TSVpFID0gMTQ1NTtcblxuLy8gUmFrbmV0IHRpY2tzXG5jb25zdCBSQUtORVRfVFBTID0gMTAwO1xuY29uc3QgUkFLTkVUX1RJQ0tfTEVOR1RIID0gMSAvIFJBS05FVF9UUFM7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIENsaWVudCBleHRlbmRzIEV2ZW50RW1pdHRlciB7XG4gICAgcHJpdmF0ZSBjbGllbnRHVUlEID0gQ3J5cHRvLnJhbmRvbUJ5dGVzKDgpLnJlYWRCaWdJbnQ2NEJFKCk7XG4gICAgcHJpdmF0ZSByZWFkb25seSBsb2dnZXIgPSBuZXcgTG9nZ2VyKCk7XG4gICAgcHJpdmF0ZSByZWFkb25seSBhZGRyZXNzOiBJbmV0QWRkcmVzcztcbiAgICBwcml2YXRlIHRhcmdldEFkZHJlc3MhOiBJbmV0QWRkcmVzcztcbiAgICBwcml2YXRlIGNvbm5lY3Rpb246IFJha05ldFNlc3Npb24gfCBudWxsID0gbnVsbDtcbiAgICBwcml2YXRlIHJlYWRvbmx5IHNvY2tldCA9IERncmFtLmNyZWF0ZVNvY2tldCh7IHR5cGU6ICd1ZHA0JyB9KTtcbiAgICBwcml2YXRlIGdldCBjbG9zZWQoKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGNvbm5lY3RpbmcgPSBmYWxzZTtcbiAgICBwcml2YXRlIGNvbm5lY3RlZCA9IGZhbHNlO1xuICAgIHByaXZhdGUgb2ZmbGluZUhhbmRsZWQgPSBmYWxzZTtcbiAgICBwcml2YXRlIGxvZ2luSGFuZGxlZCA9IGZhbHNlO1xuXG4gICAgcHVibGljIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICBzdXBlcigpO1xuICAgICAgICB0aGlzLmFkZHJlc3MgPSBuZXcgSW5ldEFkZHJlc3MoJzAuMC4wLjAnLCBnZXRSYW5kb21JbnQoNDYwMDAsIDQ5OTk5KSk7XG4gICAgICAgIHRoaXMuc29ja2V0LmJpbmQodGhpcy5hZGRyZXNzLmdldFBvcnQoKSwgdGhpcy5hZGRyZXNzLmdldEFkZHJlc3MoKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIHBhY2tldCBsaXN0ZW5lciBvbiBnaXZlbiBhZGRyZXNzIGFuZCBwb3J0LlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBhZGRyZXNzIC0gVGhlIGFkZHJlc3MgdG8gbGlzdGVuIG9uLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBwb3J0IC0gVGhlIHBvcnQgdG8gbGlzdGVuIG9uLlxuICAgICAqIEByZXR1cm5zIHtQcm9taXNlPENsaWVudD59IFRoZSBjbGllbnQgaW5zdGFuY2UuXG4gICAgICogQHB1YmxpY1xuICAgICAqL1xuICAgIHB1YmxpYyBhc3luYyBjb25uZWN0KGFkZHJlc3MgPSAnMC4wLjAuMCcsIHBvcnQgPSAxOTEzMik6IFByb21pc2U8Q2xpZW50PiB7XG4gICAgICAgIHRoaXMudGFyZ2V0QWRkcmVzcyA9IG5ldyBJbmV0QWRkcmVzcyhhZGRyZXNzLCBwb3J0KTtcblxuICAgICAgICB0aGlzLnNvY2tldC5vbignbWVzc2FnZScsIChidWZmZXI6IEJ1ZmZlcikgPT4ge1xuICAgICAgICAgICAgdm9pZCB0aGlzLmhhbmRsZShidWZmZXIpO1xuICAgICAgICB9KTtcblxuICAgICAgICBpZiAodGhpcy5jb25uZWN0aW9uKSB0aHJvdyBuZXcgRXJyb3IoJ0FscmVhZHkgY29ubmVjdGVkL2Nvbm5lY3RpbmcgdG8gc2VydmVyLicpO1xuXG4gICAgICAgIHRoaXMubG9nZ2VyLmluZm8oJ0pTUHJpc21hcmluZSBjbGllbnQgaXMgbm93IGF0dGVtcHRpbmcgdG8gY29ubmVjdC4uLicpO1xuXG4gICAgICAgIGNvbnN0IHRpbWVyID0gc2V0SW50ZXJ2YWxBc3luYyhhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICBpZiAodGhpcy5jbG9zZWQpIHtcbiAgICAgICAgICAgICAgICBhd2FpdCBjbGVhckludGVydmFsQXN5bmModGltZXIpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gU2VuZCBhIGNsaWVudCBwYWNrZXQgdG8gdGhlIHNlcnZlclxuICAgICAgICAgICAgLy8gc28gdGhlIHNlcnZlciBnb2VzIGluIHRhcmdldCBtb2RlXG4gICAgICAgICAgICAvLyBhbmQgdGhlIGxvZ2luIHByb2Nlc3Mgc3RhcnRzXG4gICAgICAgICAgICBpZiAoIXRoaXMuY29ubmVjdGluZykge1xuICAgICAgICAgICAgICAgIGNvbnN0IHBrID0gbmV3IFByb3RvY29sLlVuY29ubmVjdGVkUGluZygpO1xuICAgICAgICAgICAgICAgIHBrLnRpbWVzdGFtcCA9IEJpZ0ludChEYXRlLm5vdygpKTtcbiAgICAgICAgICAgICAgICAvLyBUT0RPOiBjYW4gYmUgb21pdHRlZC4uLiBway4gPSB0aGlzLmNsaWVudEdVSUQ7XG4gICAgICAgICAgICAgICAgcGsuZW5jb2RlKCk7XG4gICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5zZW5kQnVmZmVyKHBrLmdldEJ1ZmZlcigpKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHRoaXMuY29ubmVjdGVkICYmICF0aGlzLmxvZ2luSGFuZGxlZCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHBrID0gbmV3IEpTUFByb3RvY29sLlBhY2tldHMuTG9naW5QYWNrZXQoKTtcbiAgICAgICAgICAgICAgICBway5lbmNvZGUoKTtcblxuICAgICAgICAgICAgICAgIGNvbnN0IHNlbmRQayA9IG5ldyBQcm90b2NvbC5GcmFtZSgpO1xuICAgICAgICAgICAgICAgIHNlbmRQay5yZWxpYWJpbGl0eSA9IDA7XG4gICAgICAgICAgICAgICAgc2VuZFBrLmNvbnRlbnQgPSBway5nZXRCdWZmZXIoKTtcblxuICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbiEuc2VuZEZyYW1lKHNlbmRQaywgQ29ubmVjdGlvblByaW9yaXR5Lk5PUk1BTCk7IC8vIFBhY2tldCBuZWVkcyB0byBiZSBzcGxpdHRlZFxuICAgICAgICAgICAgICAgIHRoaXMubG9naW5IYW5kbGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uPy51cGRhdGUoRGF0ZS5ub3coKSk7XG4gICAgICAgIH0sIFJBS05FVF9USUNLX0xFTkdUSCAqIDEwMDApO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBIYW5kbGVzIHRoZSBpbmNvbWluZyBidWZmZXIuXG4gICAgICogQHBhcmFtIHtCdWZmZXJ9IGJ1ZmZlciAtIFRoZSBidWZmZXIgdG8gaGFuZGxlLlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQGludGVybmFsXG4gICAgICovXG4gICAgcHJpdmF0ZSBhc3luYyBoYW5kbGUoYnVmZmVyOiBCdWZmZXIpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgY29uc3QgaGVhZGVyID0gYnVmZmVyLnJlYWRVSW50OCgpOyAvLyBSZWFkIHBhY2tldCBoZWFkZXJcblxuICAgICAgICBpZiAodGhpcy5jb25uZWN0aW9uICYmIHRoaXMub2ZmbGluZUhhbmRsZWQpIHtcbiAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5oYW5kbGUoYnVmZmVyKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBidWY7XG4gICAgICAgIHN3aXRjaCAoaGVhZGVyKSB7XG4gICAgICAgICAgICBjYXNlIE1lc3NhZ2VJZGVudGlmaWVycy5VTkNPTk5FQ1RFRF9QT05HOlxuICAgICAgICAgICAgICAgIGJ1ZiA9IHRoaXMuaGFuZGxlVW5jb25uZWN0ZWRQb25nKGJ1ZmZlcik7XG4gICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5zZW5kQnVmZmVyKGJ1Zik7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIE1lc3NhZ2VJZGVudGlmaWVycy5PUEVOX0NPTk5FQ1RJT05fUkVQTFlfMTpcbiAgICAgICAgICAgICAgICBidWYgPSB0aGlzLmhhbmRsZU9wZW5Db25uZWN0aW9uUmVwbHkxKGJ1ZmZlcik7XG4gICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5zZW5kQnVmZmVyKGJ1Zik7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIE1lc3NhZ2VJZGVudGlmaWVycy5PUEVOX0NPTk5FQ1RJT05fUkVQTFlfMjpcbiAgICAgICAgICAgICAgICB0aGlzLmhhbmRsZU9wZW5Db25uZWN0aW9uUmVwbHkyKGJ1ZmZlcik7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIHRoaXMubG9nZ2VyLndhcm4oYFVuaGFuZGxlZCBvZmZsaW5lIHBhY2tldCBJRDogJHtoZWFkZXJ9YCwgJ0NsaWVudC9oYW5kbGUnKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHB1YmxpYyBoYW5kbGVVbmNvbm5lY3RlZFBvbmcoYnVmZmVyOiBCdWZmZXIpOiBCdWZmZXIge1xuICAgICAgICAvLyBEZWNvZGUgc2VydmVyIHBhY2tldFxuICAgICAgICBjb25zdCBkZWNvZGVkUGFja2V0ID0gbmV3IFByb3RvY29sLlVuY29ubmVjdGVkUG9uZyhidWZmZXIpO1xuICAgICAgICBkZWNvZGVkUGFja2V0LmRlY29kZSgpO1xuXG4gICAgICAgIC8vIENoZWNrIHBhY2tldCB2YWxpZGl0eVxuICAgICAgICAvLyBUbyByZWZhY3RvclxuICAgICAgICBpZiAoIWRlY29kZWRQYWNrZXQuaXNWYWxpZCgpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1JlY2VpdmVkIGFuIGludmFsaWQgb2ZmbGluZSBtZXNzYWdlJyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBFbmNvZGUgcmVzcG9uc2VcbiAgICAgICAgY29uc3QgcGFja2V0ID0gbmV3IFByb3RvY29sLk9wZW5Db25uZWN0aW9uUmVxdWVzdDEoKTtcbiAgICAgICAgcGFja2V0LnByb3RvY29sID0gUFJPVE9DT0w7XG4gICAgICAgIHBhY2tldC5tdHVTaXplID0gREVGX01UVV9TSVpFO1xuICAgICAgICBwYWNrZXQuZW5jb2RlKCk7XG5cbiAgICAgICAgLy8gVXBkYXRlIHNlc3Npb24gc3RhdHVzXG4gICAgICAgIC8vIHRoaXMuc3RhdHVzID0gQ29ubmVjdGlvblN0YXR1cy5UYXJnZXR0ZWQ7XG5cbiAgICAgICAgcmV0dXJuIHBhY2tldC5nZXRCdWZmZXIoKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgaGFuZGxlT3BlbkNvbm5lY3Rpb25SZXBseTEoYnVmZmVyOiBCdWZmZXIpOiBCdWZmZXIge1xuICAgICAgICAvLyBEZWNvZGUgc2VydmVyIHBhY2tldFxuICAgICAgICBjb25zdCBkZWNvZGVkUGFja2V0ID0gbmV3IFByb3RvY29sLk9wZW5Db25uZWN0aW9uUmVwbHkxKGJ1ZmZlcik7XG4gICAgICAgIGRlY29kZWRQYWNrZXQuZGVjb2RlKCk7XG5cbiAgICAgICAgLy8gQ2hlY2sgcGFja2V0IHZhbGlkaXR5XG4gICAgICAgIC8vIFRvIHJlZmFjdG9yXG4gICAgICAgIGlmICghZGVjb2RlZFBhY2tldC5pc1ZhbGlkKCkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignUmVjZWl2ZWQgYW4gaW52YWxpZCBvZmZsaW5lIG1lc3NhZ2UnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEVuY29kZSByZXNwb25zZVxuICAgICAgICBjb25zdCBwYWNrZXQgPSBuZXcgUHJvdG9jb2wuT3BlbkNvbm5lY3Rpb25SZXF1ZXN0MigpO1xuICAgICAgICBwYWNrZXQuc2VydmVyQWRkcmVzcyA9IHRoaXMudGFyZ2V0QWRkcmVzcztcbiAgICAgICAgcGFja2V0Lm10dVNpemUgPSBERUZfTVRVX1NJWkU7XG4gICAgICAgIHBhY2tldC5jbGllbnRHVUlEID0gdGhpcy5jbGllbnRHVUlEO1xuICAgICAgICBwYWNrZXQuZW5jb2RlKCk7XG5cbiAgICAgICAgLy8gVXBkYXRlIHNlc3Npb24gc3RhdHVzXG4gICAgICAgIHRoaXMuY29ubmVjdGluZyA9IHRydWU7XG4gICAgICAgIC8vIFRoaXMuc3RhdHVzID0gQ29ubmVjdGlvblN0YXR1cy5Db25uZWN0ZWQ7XG4gICAgICAgIHRoaXMuY29ubmVjdGlvbiA9IG5ldyBSYWtOZXRTZXNzaW9uKFxuICAgICAgICAgICAgdGhpcyBhcyBhbnksXG4gICAgICAgICAgICBERUZfTVRVX1NJWkUsXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgYWRkcmVzczogdGhpcy5hZGRyZXNzLmdldEFkZHJlc3MoKSxcbiAgICAgICAgICAgICAgICBwb3J0OiB0aGlzLmFkZHJlc3MuZ2V0UG9ydCgpLFxuICAgICAgICAgICAgICAgIGZhbWlseTogJ0lQdjQnLFxuICAgICAgICAgICAgICAgIHNpemU6IDBcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICByYW5kb21CeXRlcyg4KS5yZWFkQmlnSW50NjRCRSgpXG4gICAgICAgICk7XG5cbiAgICAgICAgcmV0dXJuIHBhY2tldC5nZXRCdWZmZXIoKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgaGFuZGxlT3BlbkNvbm5lY3Rpb25SZXBseTIoYnVmZmVyOiBCdWZmZXIpOiB2b2lkIHtcbiAgICAgICAgLy8gRGVjb2RlIHNlcnZlciBwYWNrZXRcbiAgICAgICAgY29uc3QgZGVjb2RlZFBhY2tldCA9IG5ldyBQcm90b2NvbC5PcGVuQ29ubmVjdGlvblJlcGx5MihidWZmZXIpO1xuICAgICAgICBkZWNvZGVkUGFja2V0LmRlY29kZSgpO1xuXG4gICAgICAgIC8vIENoZWNrIHBhY2tldCB2YWxpZGl0eVxuICAgICAgICAvLyBUbyByZWZhY3RvclxuICAgICAgICBpZiAoIWRlY29kZWRQYWNrZXQuaXNWYWxpZCgpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1JlY2VpdmVkIGFuIGludmFsaWQgb2ZmbGluZSBtZXNzYWdlJyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBFbmNvZGUgcmVzcG9uc2UgKGVuY2Fwc3VsYXRlZClcbiAgICAgICAgY29uc3QgcGFja2V0ID0gbmV3IFByb3RvY29sLkNvbm5lY3Rpb25SZXF1ZXN0KCk7XG4gICAgICAgIHBhY2tldC5jbGllbnRHVUlEID0gdGhpcy5jbGllbnRHVUlEO1xuICAgICAgICBwYWNrZXQucmVxdWVzdFRpbWVzdGFtcCA9IEJpZ0ludChEYXRlLm5vdygpKTtcbiAgICAgICAgcGFja2V0LmVuY29kZSgpO1xuXG4gICAgICAgIGNvbnN0IHNlbmRQYWNrZXQgPSBuZXcgUHJvdG9jb2wuRnJhbWUoKTtcbiAgICAgICAgc2VuZFBhY2tldC5yZWxpYWJpbGl0eSA9IDA7XG4gICAgICAgIHNlbmRQYWNrZXQuY29udGVudCA9IHBhY2tldC5nZXRCdWZmZXIoKTtcblxuICAgICAgICB0aGlzLmNvbm5lY3Rpb24/LnNlbmRGcmFtZShzZW5kUGFja2V0LCBDb25uZWN0aW9uUHJpb3JpdHkuTk9STUFMKTtcblxuICAgICAgICB0aGlzLm9mZmxpbmVIYW5kbGVkID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5jb25uZWN0ZWQgPSB0cnVlOyAvLyBTaG91bGQgYmUuLi4gd2UgY2FuJ3QgcmVseSBvbiBpdFxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNlbmRzIHRoZSBidWZmZXIgdG8gdGhlIHNlcnZlclxuICAgICAqXG4gICAgICogQHBhcmFtIGJ1ZmZlclxuICAgICAqL1xuICAgIHB1YmxpYyBhc3luYyBzZW5kQnVmZmVyKGJ1ZmZlcjogQnVmZmVyKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHRoaXMuc29ja2V0LnNlbmQoXG4gICAgICAgICAgICBidWZmZXIgYXMgYW55LFxuICAgICAgICAgICAgMCxcbiAgICAgICAgICAgIGJ1ZmZlci5ieXRlTGVuZ3RoLFxuICAgICAgICAgICAgdGhpcy50YXJnZXRBZGRyZXNzLmdldFBvcnQoKSxcbiAgICAgICAgICAgIHRoaXMudGFyZ2V0QWRkcmVzcy5nZXRBZGRyZXNzKClcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0U29ja2V0KCk6IFNvY2tldCB7XG4gICAgICAgIHJldHVybiB0aGlzLnNvY2tldDtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0QWRkcmVzcygpOiBJbmV0QWRkcmVzcyB7XG4gICAgICAgIHJldHVybiB0aGlzLmFkZHJlc3M7XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIHJlbW92ZUNvbm5lY3Rpb24oX2Nvbm5lY3Rpb246IFJha05ldFNlc3Npb24sIF9yZWFzb24/OiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdNZXRob2Qgbm90IGltcGxlbWVudGVkLicpO1xuICAgIH1cbn1cbiJdLCJuYW1lcyI6WyJzZXRJbnRlcnZhbEFzeW5jIiwiY2xlYXJJbnRlcnZhbEFzeW5jIiwiSlNQUHJvdG9jb2wiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7OztBQVNBLE1BQU0sWUFBQSxHQUFlLENBQUMsR0FBQSxFQUFhLEdBQWdCLEtBQUE7QUFDL0MsRUFBTSxHQUFBLEdBQUEsSUFBQSxDQUFLLEtBQUssR0FBRyxDQUFBO0FBQ25CLEVBQU0sR0FBQSxHQUFBLElBQUEsQ0FBSyxNQUFNLEdBQUcsQ0FBQTtBQUNwQixFQUFPLE9BQUEsSUFBQSxDQUFLLE1BQU0sSUFBSyxDQUFBLE1BQUEsTUFBWSxHQUFNLEdBQUEsR0FBQSxHQUFNLEVBQUUsQ0FBSSxHQUFBLEdBQUE7QUFDekQsQ0FBQTtBQUdBLE1BQU0sUUFBVyxHQUFBLEVBQUE7QUFHakIsTUFBTSxZQUFlLEdBQUEsSUFBQTtBQUdyQixNQUFNLFVBQWEsR0FBQSxHQUFBO0FBQ25CLE1BQU0scUJBQXFCLENBQUksR0FBQSxVQUFBO0FBRS9CLE1BQXFCLGVBQWUsWUFBYSxDQUFBO0FBQUEsRUFDckMsVUFBYSxHQUFBLE1BQUEsQ0FBTyxXQUFZLENBQUEsQ0FBQyxFQUFFLGNBQWUsRUFBQTtBQUFBLEVBQ3pDLE1BQUEsR0FBUyxJQUFJLE1BQU8sRUFBQTtBQUFBLEVBQ3BCLE9BQUE7QUFBQSxFQUNULGFBQUE7QUFBQSxFQUNBLFVBQW1DLEdBQUEsSUFBQTtBQUFBLEVBQzFCLFNBQVMsS0FBTSxDQUFBLFlBQUEsQ0FBYSxFQUFFLElBQUEsRUFBTSxRQUFRLENBQUE7QUFBQSxFQUM3RCxJQUFZLE1BQVMsR0FBQTtBQUNq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