Skip to content

Commit

Permalink
dns: add channel.cancel()
Browse files Browse the repository at this point in the history
This can be used to implement custom timeouts.

Fixes: #7231
PR-URL: #14518
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Tobias Nießen <tniessen@tnie.de>
  • Loading branch information
addaleax committed Aug 1, 2017
1 parent 6e05970 commit 732658e
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 0 deletions.
8 changes: 8 additions & 0 deletions doc/api/dns.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions lib/dns.js
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,10 @@ class Resolver {
constructor() {
this._handle = new ChannelWrap();
}

cancel() {
this._handle.cancel();
}
}

function resolver(bindingName) {
Expand Down
8 changes: 8 additions & 0 deletions src/cares_wrap.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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"));
Expand Down
29 changes: 29 additions & 0 deletions test/parallel/test-dns-channel-cancel.js
Original file line number Diff line number Diff line change
@@ -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();
}));

0 comments on commit 732658e

Please sign in to comment.