diff options
-rw-r--r-- | doc/api/dns.md | 8 | ||||
-rw-r--r-- | lib/dns.js | 4 | ||||
-rw-r--r-- | src/cares_wrap.cc | 8 | ||||
-rw-r--r-- | test/parallel/test-dns-channel-cancel.js | 29 |
4 files changed, 49 insertions, 0 deletions
diff --git a/doc/api/dns.md b/doc/api/dns.md index e9de95c118..5be30f2228 100644 --- a/doc/api/dns.md +++ b/doc/api/dns.md @@ -95,6 +95,14 @@ The following methods from the `dns` module are available: * [`resolver.resolveTxt()`][`dns.resolveTxt()`] * [`resolver.reverse()`][`dns.reverse()`] +### resolver.cancel() +<!-- YAML +added: REPLACEME +--> + +Cancel all outstanding DNS queries made by this resolver. The corresponding +callbacks will be called with an error with code `ECANCELLED`. + ## dns.getServers() <!-- YAML added: v0.11.3 diff --git a/lib/dns.js b/lib/dns.js index f79eb3bb14..90eaac3122 100644 --- a/lib/dns.js +++ b/lib/dns.js @@ -247,6 +247,10 @@ class Resolver { constructor() { this._handle = new ChannelWrap(); } + + cancel() { + this._handle.cancel(); + } } function resolver(bindingName) { diff --git a/src/cares_wrap.cc b/src/cares_wrap.cc index a75da1f410..327d947f3a 100644 --- a/src/cares_wrap.cc +++ b/src/cares_wrap.cc @@ -2131,6 +2131,13 @@ void SetServers(const FunctionCallbackInfo<Value>& args) { args.GetReturnValue().Set(err); } +void Cancel(const FunctionCallbackInfo<Value>& args) { + ChannelWrap* channel; + ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder()); + + ares_cancel(channel->cares_channel()); +} + void StrError(const FunctionCallbackInfo<Value>& args) { Environment* env = Environment::GetCurrent(args); @@ -2215,6 +2222,7 @@ void Initialize(Local<Object> target, env->SetProtoMethod(channel_wrap, "getServers", GetServers); env->SetProtoMethod(channel_wrap, "setServers", SetServers); + env->SetProtoMethod(channel_wrap, "cancel", Cancel); channel_wrap->SetClassName( FIXED_ONE_BYTE_STRING(env->isolate(), "ChannelWrap")); diff --git a/test/parallel/test-dns-channel-cancel.js b/test/parallel/test-dns-channel-cancel.js new file mode 100644 index 0000000000..797d61efb4 --- /dev/null +++ b/test/parallel/test-dns-channel-cancel.js @@ -0,0 +1,29 @@ +'use strict'; +const common = require('../common'); +const dnstools = require('../common/dns'); +const { Resolver } = require('dns'); +const assert = require('assert'); +const dgram = require('dgram'); + +const server = dgram.createSocket('udp4'); +const resolver = new Resolver(); + +server.bind(0, common.mustCall(() => { + resolver.setServers([`127.0.0.1:${server.address().port}`]); + resolver.resolve4('example.org', common.mustCall((err, res) => { + assert.strictEqual(err.code, 'ECANCELLED'); + assert.strictEqual(err.errno, 'ECANCELLED'); + assert.strictEqual(err.syscall, 'queryA'); + assert.strictEqual(err.hostname, 'example.org'); + server.close(); + })); +})); + +server.on('message', common.mustCall((msg, { address, port }) => { + const parsed = dnstools.parseDNSPacket(msg); + const domain = parsed.questions[0].domain; + assert.strictEqual(domain, 'example.org'); + + // Do not send a reply. + resolver.cancel(); +})); |