const sleep = require('../libs/util.js').sleep; const EventEmitter = require('events'); const Message = require('./Message.js'); class Heartbeat extends EventEmitter { constructor(client) { super(); this.interval = config?.heartbeat || 10000; this.client = client; this.#listenForPingPong(); this.#sendPing(); } async #sendPing() { if (this.timeout !== undefined) { clearTimeout(this.timeout); } if (this.alive === false) { this.emit('timeout'); return; } else if (this.alive === undefined) { await sleep(this.interval); } this.alive = false; await new Message('ping', { server: Date.now() }).send(this.client); this.timeout = setTimeout(() => { this.#sendPing(); }, this.interval); } async #listenForPingPong() { eventparser.on('ping', () => { logger.debug(this.client.getTag() + ' handling event \'ping\', responding with \'pong\'...'); new Message('pong').send(this.client); }); eventparser.on('pong', (data) => { logger.debug(this.client.getTag() + ' handling event \'pong\'...'); const now = Date.now(); this.alive = true; this.emit('latency', { toClient: (data.client - data.server), fromClient: (now - data.client), roundtrip: (now - data.server) }); }); } destroy() { if (this.timeout !== undefined) { clearTimeout(this.timeout); } eventparser.removeAllListeners('ping'); eventparser.removeAllListeners('pong'); } } module.exports = Heartbeat;