fix: add timeout to SRV record lookup

The `dns.promises.resolveSrv` function used for SRV record lookups
does not have a user-configurable timeout. This could cause the entire
`pingJava` operation to hang for an extended period if the target's
DNS server unresponsive.

To make the SRV lookup more robust and respect the user-provided
timeout, this commit switches to using the `dns.promises.Resolver`
class.
This commit is contained in:
2025-06-25 01:09:07 +03:00
parent 2bd5d9c9bf
commit 23299a9a07

View File

@ -6,7 +6,7 @@
"use strict";
import net from "node:net";
import dns from "node:dns/promises";
import { Resolver } from "node:dns/promises";
import createDebug from "debug";
import * as varint from "./varint.js";
@ -148,22 +148,27 @@ export async function pingJava(host, options = {}) {
let targetPort = fallbackPort;
try {
debug("attempting SRV lookup for _minecraft._tcp.%s", host);
const srvRecords = await dns.resolveSrv(`_minecraft._tcp.${host}`);
debug(
"attempting SRV lookup for _minecraft._tcp.%s with %dms timeout",
host,
timeout
);
const resolver = new Resolver({ timeout, tries: 3 });
const srvRecords = await resolver.resolveSrv(`_minecraft._tcp.${host}`);
if (srvRecords.length > 0) {
targetHost = srvRecords[0].name;
targetPort = srvRecords[0].port;
debug("SRV lookup successful, new target: %s:%d", targetHost, targetPort);
}
} catch (err) {
// Common errors like ENODATA or ENOTFOUND are expected when a server
// does not have an SRV record, so we ignore them and proceed
// Common errors like ENODATA, ENOTFOUND, or a DNS timeout (ETIMEOUT) are expected
// when a server does not have an SRV record, so we ignore them and proceed.
const nonFatalDnsCodes = ["ENODATA", "ENOTFOUND", "ETIMEOUT"];
if (
err instanceof Error &&
"code" in err &&
(err.code === "ENODATA" || err.code === "ENOTFOUND")
nonFatalDnsCodes.includes(err.code)
) {
// Non fatal DNS error, log it and continue
debug("SRV lookup for %s failed (%s), using fallback.", host, err.code);
} else {
// Re-throw anything else to fail the operation