Skip to content

Commit

Permalink
dns: implement {ttl: true} for dns.resolve4()
Browse files Browse the repository at this point in the history
Add an option to retrieve the Time-To-Live of the A record.

PR-URL: nodejs/node#9296
Refs: nodejs/node#5893
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Roman Reiss <[email protected]>
  • Loading branch information
bnoordhuis authored and andrew749 committed Jul 19, 2017
1 parent 0497a10 commit d6020c4
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 19 deletions.
9 changes: 8 additions & 1 deletion doc/api/dns.md
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ corresponding lookup methods.
On error, `err` is an [`Error`][] object, where `err.code` is
one of the error codes listed [here](#dns_error_codes).

## dns.resolve4(hostname, callback)
## dns.resolve4(hostname[, options], callback)
<!-- YAML
added: v0.1.16
-->
Expand All @@ -205,6 +205,13 @@ Uses the DNS protocol to resolve a IPv4 addresses (`A` records) for the
will contain an array of IPv4 addresses (e.g.
`['74.125.79.104', '74.125.79.105', '74.125.79.106']`).

* `hostname` {String} Hostname to resolve.
* `options` {Object}
* `ttl` {Boolean} Retrieve the Time-To-Live value (TTL) of each record.
The callback receives an array of `{ address: '1.2.3.4', ttl: 60 }` objects
rather than an array of strings. The TTL is expressed in seconds.
* `callback` {Function} An `(err, result)` callback function.

## dns.resolve6(hostname, callback)
<!-- YAML
added: v0.1.16
Expand Down
14 changes: 12 additions & 2 deletions lib/dns.js
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,10 @@ exports.lookupService = function(host, port, callback) {
};


function onresolve(err, result) {
function onresolve(err, result, ttls) {
if (ttls && this.ttl)
result = result.map((address, index) => ({ address, ttl: ttls[index] }));

if (err)
this.callback(errnoException(err, this.bindingName, this.hostname));
else
Expand All @@ -222,7 +225,13 @@ function onresolve(err, result) {
function resolver(bindingName) {
var binding = cares[bindingName];

return function query(name, callback) {
return function query(name, /* options, */ callback) {
var options;
if (arguments.length > 2) {
options = callback;
callback = arguments[2];
}

if (typeof name !== 'string') {
throw new Error('"name" argument must be a string');
} else if (typeof callback !== 'function') {
Expand All @@ -235,6 +244,7 @@ function resolver(bindingName) {
req.callback = callback;
req.hostname = name;
req.oncomplete = onresolve;
req.ttl = !!(options && options.ttl);
var err = binding(req, name);
if (err) throw errnoException(err, bindingName);
callback.immediately = true;
Expand Down
33 changes: 17 additions & 16 deletions src/cares_wrap.cc
Original file line number Diff line number Diff line change
Expand Up @@ -337,25 +337,17 @@ class QueryWrap : public AsyncWrap {
delete wrap;
}

void CallOnComplete(Local<Value> answer) {
HandleScope handle_scope(env()->isolate());
Context::Scope context_scope(env()->context());
Local<Value> argv[] = {
Integer::New(env()->isolate(), 0),
answer
};
MakeCallback(env()->oncomplete_string(), arraysize(argv), argv);
}

void CallOnComplete(Local<Value> answer, Local<Value> family) {
void CallOnComplete(Local<Value> answer,
Local<Value> extra = Local<Value>()) {
HandleScope handle_scope(env()->isolate());
Context::Scope context_scope(env()->context());
Local<Value> argv[] = {
Integer::New(env()->isolate(), 0),
answer,
family
extra
};
MakeCallback(env()->oncomplete_string(), arraysize(argv), argv);
const int argc = arraysize(argv) - extra.IsEmpty();
MakeCallback(env()->oncomplete_string(), argc, argv);
}

void ParseError(int status) {
Expand Down Expand Up @@ -401,18 +393,27 @@ class QueryAWrap: public QueryWrap {
HandleScope handle_scope(env()->isolate());
Context::Scope context_scope(env()->context());

struct hostent* host;
hostent* host;
ares_addrttl addrttls[256];
int naddrttls = arraysize(addrttls);

int status = ares_parse_a_reply(buf, len, &host, nullptr, nullptr);
int status = ares_parse_a_reply(buf, len, &host, addrttls, &naddrttls);
if (status != ARES_SUCCESS) {
ParseError(status);
return;
}

Local<Array> addresses = HostentToAddresses(env(), host);
Local<Array> ttls = Array::New(env()->isolate(), naddrttls);

auto context = env()->context();
for (int i = 0; i < naddrttls; i += 1) {
auto value = Integer::New(env()->isolate(), addrttls[i].ttl);
ttls->Set(context, i, value).FromJust();
}
ares_free_hostent(host);

this->CallOnComplete(addresses);
CallOnComplete(addresses, ttls);
}
};

Expand Down
20 changes: 20 additions & 0 deletions test/internet/test-dns.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,26 @@ TEST(function test_reverse_bogus(done) {
done();
});

TEST(function test_resolve4_ttl(done) {
const req = dns.resolve4('google.com', { ttl: true }, function(err, result) {
assert.ifError(err);
assert.ok(result.length > 0);

for (let i = 0; i < result.length; i++) {
const item = result[i];
assert.ok(item);
assert.strictEqual(typeof item, 'object');
assert.strictEqual(typeof item.ttl, 'number');
assert.strictEqual(typeof item.address, 'string');
assert.ok(item.ttl > 0);
assert.ok(isIPv4(item.address));
}

done();
});

checkWrap(req);
});

TEST(function test_resolveMx(done) {
const req = dns.resolveMx('gmail.com', function(err, result) {
Expand Down

0 comments on commit d6020c4

Please sign in to comment.