node-gamedig/lib/DnsResolver.js
Tom 01794f6339
Add support for running using deno (#362)
* Add missing CRLF line ending

* Add support for running using deno

Prefix node imports with "node:" and gate a socket API that is not
implemented in [deno](https://deno.land) so that the library can be used
there. This should not break node and doesn't in my brief testing.
2023-10-10 12:25:57 +03:00

78 lines
2.3 KiB
JavaScript

import * as dns from 'node:dns'
import punycode from 'punycode/punycode.js'
import { promisify } from 'node:util'
const dnsLookupAsync = promisify(dns.lookup)
const dnsResolveAsync = promisify(dns.resolve)
export default class DnsResolver {
/**
* @param {Logger} logger
*/
constructor (logger) {
this.logger = logger
}
isIp (host) {
return !!host.match(/\d+\.\d+\.\d+\.\d+/)
}
/**
* Response port will only be present if srv record was involved.
* @param {string} host
* @param {number} ipFamily
* @param {string=} srvRecordPrefix
* @returns {Promise<{address:string, port:number=}>}
*/
async resolve (host, ipFamily, srvRecordPrefix) {
this.logger.debug('DNS Lookup: ' + host)
if (this.isIp(host)) {
this.logger.debug('Raw IP Address: ' + host)
return { address: host }
}
const asciiForm = punycode.toASCII(host)
if (asciiForm !== host) {
this.logger.debug('Encoded punycode: ' + host + ' -> ' + asciiForm)
host = asciiForm
}
if (srvRecordPrefix) {
this.logger.debug('SRV Resolve: ' + srvRecordPrefix + '.' + host)
let records
try {
records = await dnsResolveAsync(srvRecordPrefix + '.' + host, 'SRV')
if (records.length >= 1) {
this.logger.debug('Found SRV Records: ', records)
const record = records[0]
const srvPort = record.port
const srvHost = record.name
if (srvHost === host) {
throw new Error('Loop in DNS SRV records')
}
return {
port: srvPort,
...await this.resolve(srvHost, ipFamily, srvRecordPrefix)
}
}
this.logger.debug('No SRV Record')
} catch (e) {
this.logger.debug(e)
}
}
this.logger.debug('Standard Resolve: ' + host)
const dnsResult = await dnsLookupAsync(host, ipFamily)
// For some reason, this sometimes returns a string address rather than an object.
// I haven't been able to reproduce, but it's been reported on the issue tracker.
let address
if (typeof dnsResult === 'string') {
address = dnsResult
} else {
address = dnsResult.address
}
this.logger.debug('Found address: ' + address)
return { address }
}
}