-
Notifications
You must be signed in to change notification settings - Fork 29.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
dns: refactor dns to more modern JavaScript #5762
Changes from all commits
8d6c22e
f5c4f55
2784847
48fde13
bfe0f40
2d54ae9
85f9b87
457de39
4f124f7
6fe93ed
b3ced41
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,5 @@ | ||
'use strict'; | ||
|
||
const net = require('net'); | ||
const util = require('util'); | ||
|
||
const cares = process.binding('cares_wrap'); | ||
|
@@ -11,7 +10,7 @@ const GetAddrInfoReqWrap = cares.GetAddrInfoReqWrap; | |
const GetNameInfoReqWrap = cares.GetNameInfoReqWrap; | ||
const QueryReqWrap = cares.QueryReqWrap; | ||
|
||
const isIp = net.isIP; | ||
const isIp = cares.isIP; | ||
const isLegalPort = internalNet.isLegalPort; | ||
|
||
|
||
|
@@ -25,7 +24,7 @@ function errnoException(err, syscall, hostname) { | |
} | ||
var ex = null; | ||
if (typeof err === 'string') { // c-ares error code. | ||
ex = new Error(syscall + ' ' + err + (hostname ? ' ' + hostname : '')); | ||
ex = new Error(`${syscall} ${err} ${(hostname ? ' ' + hostname : '')}`); | ||
ex.code = err; | ||
ex.errno = err; | ||
ex.syscall = syscall; | ||
|
@@ -38,7 +37,6 @@ function errnoException(err, syscall, hostname) { | |
return ex; | ||
} | ||
|
||
|
||
// c-ares invokes a callback either synchronously or asynchronously, | ||
// but the dns API should always invoke a callback asynchronously. | ||
// | ||
|
@@ -66,8 +64,9 @@ function makeAsync(callback) { | |
} else { | ||
var args = new Array(arguments.length + 1); | ||
args[0] = callback; | ||
for (var i = 1, a = 0; a < arguments.length; ++i, ++a) | ||
for (var i = 1, a = 0; a < arguments.length; ++i, ++a) { | ||
args[i] = arguments[a]; | ||
} | ||
process.nextTick.apply(null, args); | ||
} | ||
}; | ||
|
@@ -76,8 +75,10 @@ function makeAsync(callback) { | |
|
||
function onlookup(err, addresses) { | ||
if (err) { | ||
return this.callback(errnoException(err, 'getaddrinfo', this.hostname)); | ||
this.callback(errnoException(err, 'getaddrinfo', this.hostname)); | ||
return; | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why change this? the |
||
|
||
if (this.family) { | ||
this.callback(null, addresses[0], this.family); | ||
} else { | ||
|
@@ -87,16 +88,18 @@ function onlookup(err, addresses) { | |
|
||
|
||
function onlookupall(err, addresses) { | ||
var results = []; | ||
if (err) { | ||
return this.callback(errnoException(err, 'getaddrinfo', this.hostname)); | ||
this.callback(errnoException(err, 'getaddrinfo', this.hostname)); | ||
return; | ||
} | ||
|
||
const results = new Array(addresses.length); | ||
|
||
for (var i = 0; i < addresses.length; i++) { | ||
results.push({ | ||
results[i] = { | ||
address: addresses[i], | ||
family: this.family || (addresses[i].indexOf(':') >= 0 ? 6 : 4) | ||
}); | ||
}; | ||
} | ||
|
||
this.callback(null, results); | ||
|
@@ -134,8 +137,10 @@ exports.lookup = function lookup(hostname, options, callback) { | |
family = options >>> 0; | ||
} | ||
|
||
if (family !== 0 && family !== 4 && family !== 6) | ||
throw new TypeError('Invalid argument: family must be 4 or 6'); | ||
if (family !== 0 && family !== 4 && family !== 6) { | ||
const msg = `Invalid argument: family must be 4 or 6, got ${family}`; | ||
throw new TypeError(msg); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks like the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks :) |
||
|
||
callback = makeAsync(callback); | ||
|
||
|
@@ -148,7 +153,7 @@ exports.lookup = function lookup(hostname, options, callback) { | |
return {}; | ||
} | ||
|
||
var matchedFamily = net.isIP(hostname); | ||
var matchedFamily = isIP(hostname); | ||
if (matchedFamily) { | ||
if (all) { | ||
callback(null, [{address: hostname, family: matchedFamily}]); | ||
|
@@ -176,25 +181,30 @@ exports.lookup = function lookup(hostname, options, callback) { | |
|
||
|
||
function onlookupservice(err, host, service) { | ||
if (err) | ||
return this.callback(errnoException(err, 'getnameinfo', this.host)); | ||
if (err) { | ||
this.callback(errnoException(err, 'getnameinfo', this.host)); | ||
return; | ||
} | ||
|
||
this.callback(null, host, service); | ||
} | ||
|
||
|
||
// lookupService(address, port, callback) | ||
exports.lookupService = function(host, port, callback) { | ||
if (arguments.length !== 3) | ||
throw new Error('Invalid arguments'); | ||
if (arguments.length !== 3) { | ||
throw new TypeError(`Expected 3 arguments, got ${arguments.length}`); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This isn't really a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well, the type of For example - when you call I don't feel very strongly about this - but the language and most APIs I know throw type errors in this case. |
||
} | ||
|
||
if (cares.isIP(host) === 0) | ||
if (isIP(host) === 0) { | ||
throw new TypeError('"host" argument needs to be a valid IP address'); | ||
} | ||
|
||
if (port == null || !isLegalPort(port)) | ||
if (port == null || !isLegalPort(port)) { | ||
throw new TypeError(`"port" should be >= 0 and < 65536, got "${port}"`); | ||
} | ||
|
||
port = +port; | ||
port = Number(port); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why this change? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well, unary I'm also not sure about the |
||
callback = makeAsync(callback); | ||
|
||
var req = new GetNameInfoReqWrap(); | ||
|
@@ -204,18 +214,21 @@ exports.lookupService = function(host, port, callback) { | |
req.oncomplete = onlookupservice; | ||
|
||
var err = cares.getnameinfo(req, host, port); | ||
if (err) throw errnoException(err, 'getnameinfo', host); | ||
if (err) { | ||
throw errnoException(err, 'getnameinfo', host); | ||
} | ||
|
||
callback.immediately = true; | ||
return req; | ||
}; | ||
|
||
|
||
function onresolve(err, result) { | ||
if (err) | ||
if (err) { | ||
this.callback(errnoException(err, this.bindingName, this.hostname)); | ||
else | ||
} else { | ||
this.callback(null, result); | ||
} | ||
} | ||
|
||
|
||
|
@@ -224,9 +237,10 @@ function resolver(bindingName) { | |
|
||
return function query(name, callback) { | ||
if (typeof name !== 'string') { | ||
throw new Error('"name" argument must be a string'); | ||
const msg = `"name" argument must be a string, got ${typeof name}`; | ||
throw new TypeError(msg); | ||
} else if (typeof callback !== 'function') { | ||
throw new Error('"callback" argument must be a function'); | ||
throw new TypeError('"callback" argument must be a function'); | ||
} | ||
|
||
callback = makeAsync(callback); | ||
|
@@ -236,14 +250,17 @@ function resolver(bindingName) { | |
req.hostname = name; | ||
req.oncomplete = onresolve; | ||
var err = binding(req, name); | ||
if (err) throw errnoException(err, bindingName); | ||
if (err) { | ||
throw errnoException(err, bindingName); | ||
} | ||
|
||
callback.immediately = true; | ||
return req; | ||
}; | ||
} | ||
|
||
|
||
var resolveMap = {}; | ||
var resolveMap = Object.create(null); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why this change? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good question, we're using this object for a map, I thought about converting it to an ES2015 map but wasn't 100% sure about the implications or performance. With your blessing I'll refactor this to a |
||
exports.resolve4 = resolveMap.A = resolver('queryA'); | ||
exports.resolve6 = resolveMap.AAAA = resolver('queryAaaa'); | ||
exports.resolveCname = resolveMap.CNAME = resolver('queryCname'); | ||
|
@@ -257,7 +274,7 @@ exports.resolveSoa = resolveMap.SOA = resolver('querySoa'); | |
exports.reverse = resolver('getHostByAddr'); | ||
|
||
|
||
exports.resolve = function(hostname, type_, callback_) { | ||
exports.resolve = (hostname, type_, callback_) => { | ||
var resolver, callback; | ||
if (typeof type_ === 'string') { | ||
resolver = resolveMap[type_]; | ||
|
@@ -272,56 +289,55 @@ exports.resolve = function(hostname, type_, callback_) { | |
if (typeof resolver === 'function') { | ||
return resolver(hostname, callback); | ||
} else { | ||
throw new Error('Unknown type "' + type_ + '"'); | ||
throw new Error(`Unknown type ${type_}`); | ||
} | ||
}; | ||
|
||
|
||
exports.getServers = function() { | ||
exports.getServers = () => { | ||
return cares.getServers(); | ||
}; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. exports.getServers = () => cares.getServers(); Are the curlys required by coding convention here? ::shrugs:: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think they're required in multi-line functions. I recall talking about it but I'm not sure what conclusion was reached and I'm fine with either - @thefourtheye ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I remember the discussion regarding the parens in arrow function parameters, but not sure about the body. I'll have to look. But I feel that having curly braces for even a single expression kinda beats the purpose of arrow functions. |
||
|
||
|
||
exports.setServers = function(servers) { | ||
// cache the original servers because in the event of an error setting the | ||
// servers cares won't have any servers available for resolution | ||
var orig = cares.getServers(); | ||
var originalServers = cares.getServers(); | ||
|
||
var newSet = []; | ||
const newSet = servers.map((serv) => { | ||
var ipVersion = isIp(serv); | ||
|
||
servers.forEach(function(serv) { | ||
var ver = isIp(serv); | ||
|
||
if (ver) | ||
return newSet.push([ver, serv]); | ||
|
||
var match = serv.match(/\[(.*)\](:\d+)?/); | ||
if (ipVersion !== 0) { | ||
return [ver, serv]; | ||
} | ||
const match = serv.match(/\[(.*)\](:\d+)?/); | ||
|
||
// we have an IPv6 in brackets | ||
if (match) { | ||
ver = isIp(match[1]); | ||
if (ver) | ||
return newSet.push([ver, match[1]]); | ||
ipVersion = isIp(match[1]); | ||
if (ipVersion !== 0) { | ||
return [ver, match[1]]; | ||
} | ||
} | ||
|
||
var s = serv.split(/:\d+$/)[0]; | ||
ver = isIp(s); | ||
ipVersion = isIp(s); | ||
|
||
if (ver) | ||
return newSet.push([ver, s]); | ||
if (ipVersion !== 0) { | ||
return [ver, s]; | ||
} | ||
|
||
throw new Error('IP address is not properly formatted: ' + serv); | ||
throw new Error(`IP address is not properly formatted: ${serv}`); | ||
}); | ||
|
||
var r = cares.setServers(newSet); | ||
const errorNumber = cares.setServers(newSet); | ||
|
||
if (r) { | ||
if (errorNumber !== 0) { | ||
// reset the servers to the old servers, because ares probably unset them | ||
cares.setServers(orig.join(',')); | ||
cares.setServers(originalServers.join(',')); | ||
|
||
var err = cares.strerror(r); | ||
throw new Error('c-ares failed to set servers: "' + err + | ||
'" [' + servers + ']'); | ||
throw new Error(`c-ares failed to set servers: ${err} [${servers}]`); | ||
} | ||
}; | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: not in love with the style changes