node-gamedig/lib/GlobalUdpSocket.js

70 lines
1.9 KiB
JavaScript

import { createSocket } from 'node:dgram'
import { debugDump } from './HexUtil.js'
import { promisify } from 'node:util'
import Logger from './Logger.js'
export default class GlobalUdpSocket {
constructor ({ port }) {
this.socket = null
this.callbacks = new Set()
this.debuggingCallbacks = new Set()
this.logger = new Logger()
this.port = port
}
async _getSocket () {
if (!this.socket) {
const udpSocket = createSocket({
type: 'udp4',
reuseAddr: true
})
udpSocket.unref()
udpSocket.on('message', (buffer, rinfo) => {
const fromAddress = rinfo.address
const fromPort = rinfo.port
this.logger.debug(log => {
log(fromAddress + ':' + fromPort + ' <--UDP(' + this.port + ')')
log(debugDump(buffer))
})
for (const callback of this.callbacks) {
callback(fromAddress, fromPort, buffer)
}
})
udpSocket.on('error', e => {
this.logger.debug('UDP ERROR:', e)
})
await promisify(udpSocket.bind).bind(udpSocket)(this.port)
this.port = udpSocket.address().port
this.socket = udpSocket
}
return this.socket
}
async send (buffer, address, port, debug) {
const socket = await this._getSocket()
if (debug) {
this.logger._print(log => {
log(address + ':' + port + ' UDP(' + this.port + ')-->')
log(debugDump(buffer))
})
}
await promisify(socket.send).bind(socket)(buffer, 0, buffer.length, port, address)
}
addCallback (callback, debug) {
this.callbacks.add(callback)
if (debug) {
this.debuggingCallbacks.add(callback)
this.logger.debugEnabled = true
}
}
removeCallback (callback) {
this.callbacks.delete(callback)
this.debuggingCallbacks.delete(callback)
this.logger.debugEnabled = this.debuggingCallbacks.size > 0
}
}