mirror of
https://github.com/nodejs/node.git
synced 2024-12-01 16:10:02 +01:00
c88d9577bb
* alphabetize contenst of `resolverKeys` array * less line-wrapping for increased code clarity PR-URL: https://github.com/nodejs/node/pull/27006 Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
165 lines
3.8 KiB
JavaScript
165 lines
3.8 KiB
JavaScript
'use strict';
|
|
const errors = require('internal/errors');
|
|
const { isIP } = require('internal/net');
|
|
const {
|
|
ChannelWrap,
|
|
strerror,
|
|
AI_ADDRCONFIG,
|
|
AI_V4MAPPED
|
|
} = internalBinding('cares_wrap');
|
|
const IANA_DNS_PORT = 53;
|
|
const IPv6RE = /^\[([^[\]]*)\]/;
|
|
const addrSplitRE = /(^.+?)(?::(\d+))?$/;
|
|
const {
|
|
ERR_DNS_SET_SERVERS_FAILED,
|
|
ERR_INVALID_ARG_TYPE,
|
|
ERR_INVALID_IP_ADDRESS,
|
|
ERR_INVALID_OPT_VALUE
|
|
} = errors.codes;
|
|
|
|
// Resolver instances correspond 1:1 to c-ares channels.
|
|
class Resolver {
|
|
constructor() {
|
|
this._handle = new ChannelWrap();
|
|
}
|
|
|
|
cancel() {
|
|
this._handle.cancel();
|
|
}
|
|
|
|
getServers() {
|
|
return this._handle.getServers().map((val) => {
|
|
if (!val[1] || val[1] === IANA_DNS_PORT)
|
|
return val[0];
|
|
|
|
const host = isIP(val[0]) === 6 ? `[${val[0]}]` : val[0];
|
|
return `${host}:${val[1]}`;
|
|
});
|
|
}
|
|
|
|
setServers(servers) {
|
|
if (!Array.isArray(servers)) {
|
|
throw new ERR_INVALID_ARG_TYPE('servers', 'Array', servers);
|
|
}
|
|
|
|
// Cache the original servers because in the event of an error while
|
|
// setting the servers, c-ares won't have any servers available for
|
|
// resolution.
|
|
const orig = this._handle.getServers();
|
|
const newSet = [];
|
|
|
|
servers.forEach((serv, index) => {
|
|
if (typeof serv !== 'string') {
|
|
throw new ERR_INVALID_ARG_TYPE(`servers[${index}]`, 'string', serv);
|
|
}
|
|
var ipVersion = isIP(serv);
|
|
|
|
if (ipVersion !== 0)
|
|
return newSet.push([ipVersion, serv, IANA_DNS_PORT]);
|
|
|
|
const match = serv.match(IPv6RE);
|
|
|
|
// Check for an IPv6 in brackets.
|
|
if (match) {
|
|
ipVersion = isIP(match[1]);
|
|
|
|
if (ipVersion !== 0) {
|
|
const port =
|
|
parseInt(serv.replace(addrSplitRE, '$2')) || IANA_DNS_PORT;
|
|
return newSet.push([ipVersion, match[1], port]);
|
|
}
|
|
}
|
|
|
|
// addr::port
|
|
const addrSplitMatch = serv.match(addrSplitRE);
|
|
|
|
if (addrSplitMatch) {
|
|
const hostIP = addrSplitMatch[1];
|
|
const port = addrSplitMatch[2] || IANA_DNS_PORT;
|
|
|
|
ipVersion = isIP(hostIP);
|
|
|
|
if (ipVersion !== 0) {
|
|
return newSet.push([ipVersion, hostIP, parseInt(port)]);
|
|
}
|
|
}
|
|
|
|
throw new ERR_INVALID_IP_ADDRESS(serv);
|
|
});
|
|
|
|
const errorNumber = this._handle.setServers(newSet);
|
|
|
|
if (errorNumber !== 0) {
|
|
// Reset the servers to the old servers, because ares probably unset them.
|
|
this._handle.setServers(orig.join(','));
|
|
const err = strerror(errorNumber);
|
|
throw new ERR_DNS_SET_SERVERS_FAILED(err, servers);
|
|
}
|
|
}
|
|
}
|
|
|
|
let defaultResolver = new Resolver();
|
|
const resolverKeys = [
|
|
'getServers',
|
|
'resolve',
|
|
'resolve4',
|
|
'resolve6',
|
|
'resolveAny',
|
|
'resolveCname',
|
|
'resolveMx',
|
|
'resolveNaptr',
|
|
'resolveNs',
|
|
'resolvePtr',
|
|
'resolveSoa',
|
|
'resolveSrv',
|
|
'resolveTxt',
|
|
'reverse',
|
|
];
|
|
|
|
function getDefaultResolver() {
|
|
return defaultResolver;
|
|
}
|
|
|
|
function setDefaultResolver(resolver) {
|
|
defaultResolver = resolver;
|
|
}
|
|
|
|
function bindDefaultResolver(target, source) {
|
|
resolverKeys.forEach((key) => {
|
|
target[key] = source[key].bind(defaultResolver);
|
|
});
|
|
}
|
|
|
|
function validateHints(hints) {
|
|
if (hints !== 0 &&
|
|
hints !== AI_ADDRCONFIG &&
|
|
hints !== AI_V4MAPPED &&
|
|
hints !== (AI_ADDRCONFIG | AI_V4MAPPED)) {
|
|
throw new ERR_INVALID_OPT_VALUE('hints', hints);
|
|
}
|
|
}
|
|
|
|
let invalidHostnameWarningEmitted = false;
|
|
|
|
function emitInvalidHostnameWarning(hostname) {
|
|
if (invalidHostnameWarningEmitted) {
|
|
return;
|
|
}
|
|
invalidHostnameWarningEmitted = true;
|
|
process.emitWarning(
|
|
`The provided hostname "${hostname}" is not a valid ` +
|
|
'hostname, and is supported in the dns module solely for compatibility.',
|
|
'DeprecationWarning',
|
|
'DEP0118'
|
|
);
|
|
}
|
|
|
|
module.exports = {
|
|
bindDefaultResolver,
|
|
getDefaultResolver,
|
|
setDefaultResolver,
|
|
validateHints,
|
|
Resolver,
|
|
emitInvalidHostnameWarning,
|
|
};
|