Skip to content
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: add "tries" option to Resolve options #39610

Closed
wants to merge 3 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions doc/api/dns.md
Original file line number Diff line number Diff line change
@@ -97,6 +97,9 @@ The following methods from the `dns` module are available:
<!-- YAML
added: v8.3.0
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/39610
description: The `options` object now accepts a `tries` option.
- version: v12.18.3
pr-url: https://github.com/nodejs/node/pull/33472
description: The constructor now accepts an `options` object.
@@ -108,6 +111,8 @@ Create a new resolver.
* `options` {Object}
* `timeout` {integer} Query timeout in milliseconds, or `-1` to use the
default timeout.
* `tries` {integer} The number of tries the resolver will try contacting
each name server before giving up. **Default:** `4`

### `resolver.cancel()`
<!-- YAML
4 changes: 3 additions & 1 deletion lib/internal/dns/promises.js
Original file line number Diff line number Diff line change
@@ -12,6 +12,7 @@ const {
Resolver: CallbackResolver,
validateHints,
validateTimeout,
validateTries,
emitInvalidHostnameWarning,
getDefaultVerbatim,
} = require('internal/dns/utils');
@@ -216,7 +217,8 @@ const resolveMap = ObjectCreate(null);
class Resolver {
constructor(options = undefined) {
const timeout = validateTimeout(options);
this._handle = new ChannelWrap(timeout);
const tries = validateTries(options);
this._handle = new ChannelWrap(timeout, tries);
}
}

10 changes: 9 additions & 1 deletion lib/internal/dns/utils.js
Original file line number Diff line number Diff line change
@@ -43,11 +43,18 @@ function validateTimeout(options) {
return timeout;
}

function validateTries(options) {
const { tries = 4 } = { ...options };
validateInt32(tries, 'options.tries', 1, 2 ** 31 - 1);
return tries;
}

// Resolver instances correspond 1:1 to c-ares channels.
class Resolver {
constructor(options = undefined) {
const timeout = validateTimeout(options);
this._handle = new ChannelWrap(timeout);
const tries = validateTries(options);
this._handle = new ChannelWrap(timeout, tries);
}

cancel() {
@@ -209,6 +216,7 @@ module.exports = {
setDefaultResolver,
validateHints,
validateTimeout,
validateTries,
Resolver,
emitInvalidHostnameWarning,
getDefaultVerbatim,
19 changes: 14 additions & 5 deletions src/cares_wrap.cc
Original file line number Diff line number Diff line change
@@ -631,9 +631,14 @@ int ParseSoaReply(
}
} // anonymous namespace

ChannelWrap::ChannelWrap(Environment* env, Local<Object> object, int timeout)
ChannelWrap::ChannelWrap(
Environment* env,
Local<Object> object,
int timeout,
int tries)
: AsyncWrap(env, object, PROVIDER_DNSCHANNEL),
timeout_(timeout) {
timeout_(timeout),
tries_(tries) {
MakeWeak();

Setup();
@@ -647,11 +652,13 @@ void ChannelWrap::MemoryInfo(MemoryTracker* tracker) const {

void ChannelWrap::New(const FunctionCallbackInfo<Value>& args) {
CHECK(args.IsConstructCall());
CHECK_EQ(args.Length(), 1);
CHECK_EQ(args.Length(), 2);
CHECK(args[0]->IsInt32());
CHECK(args[1]->IsInt32());
const int timeout = args[0].As<Int32>()->Value();
const int tries = args[1].As<Int32>()->Value();
Environment* env = Environment::GetCurrent(args);
new ChannelWrap(env, args.This(), timeout);
new ChannelWrap(env, args.This(), timeout, tries);
}

GetAddrInfoReqWrap::GetAddrInfoReqWrap(
@@ -704,6 +711,7 @@ void ChannelWrap::Setup() {
options.sock_state_cb = ares_sockstate_cb;
options.sock_state_cb_data = this;
options.timeout = timeout_;
options.tries = tries_;

int r;
if (!library_inited_) {
@@ -717,7 +725,8 @@ void ChannelWrap::Setup() {

/* We do the call to ares_init_option for caller. */
const int optmask =
ARES_OPT_FLAGS | ARES_OPT_TIMEOUTMS | ARES_OPT_SOCK_STATE_CB;
ARES_OPT_FLAGS | ARES_OPT_TIMEOUTMS |
ARES_OPT_SOCK_STATE_CB | ARES_OPT_TRIES;
r = ares_init_options(&channel_, &options, optmask);

if (r != ARES_SUCCESS) {
7 changes: 6 additions & 1 deletion src/cares_wrap.h
Original file line number Diff line number Diff line change
@@ -155,7 +155,11 @@ struct NodeAresTask final : public MemoryRetainer {

class ChannelWrap final : public AsyncWrap {
public:
ChannelWrap(Environment* env, v8::Local<v8::Object> object, int timeout);
ChannelWrap(
Environment* env,
v8::Local<v8::Object> object,
int timeout,
int tries);
~ChannelWrap() override;

static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
@@ -189,6 +193,7 @@ class ChannelWrap final : public AsyncWrap {
bool is_servers_default_ = true;
bool library_inited_ = false;
int timeout_;
int tries_;
int active_query_count_ = 0;
NodeAresTask::List task_list_;
};