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鈥檒l 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
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions doc/api/dns.md
Expand Up @@ -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.
Expand All @@ -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
Expand Down
4 changes: 3 additions & 1 deletion lib/internal/dns/promises.js
Expand Up @@ -12,6 +12,7 @@ const {
Resolver: CallbackResolver,
validateHints,
validateTimeout,
validateTries,
emitInvalidHostnameWarning,
getDefaultVerbatim,
} = require('internal/dns/utils');
Expand Down Expand Up @@ -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);
}
}

Expand Down
10 changes: 9 additions & 1 deletion lib/internal/dns/utils.js
Expand Up @@ -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() {
Expand Down Expand Up @@ -209,6 +216,7 @@ module.exports = {
setDefaultResolver,
validateHints,
validateTimeout,
validateTries,
Resolver,
emitInvalidHostnameWarning,
getDefaultVerbatim,
Expand Down
19 changes: 14 additions & 5 deletions src/cares_wrap.cc
Expand Up @@ -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();
Expand All @@ -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(
Expand Down Expand Up @@ -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_) {
Expand All @@ -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) {
Expand Down
7 changes: 6 additions & 1 deletion src/cares_wrap.h
Expand Up @@ -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);
oluan marked this conversation as resolved.
Show resolved Hide resolved
~ChannelWrap() override;

static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
Expand Down Expand Up @@ -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_;
};
Expand Down