aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/api/dns.md8
-rw-r--r--lib/dns.js4
-rw-r--r--src/cares_wrap.cc8
-rw-r--r--test/parallel/test-dns-channel-cancel.js29
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();
+}));