Skip to content

Commit

Permalink
dns: add "tries" option to Resolve options
Browse files Browse the repository at this point in the history
PR-URL: #39610
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Michaël Zasso <targos@protonmail.com>
  • Loading branch information
oluan authored and targos committed Sep 4, 2021
1 parent a62d4d6 commit d8d9a96
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 8 deletions.
2 changes: 2 additions & 0 deletions doc/api/dns.md
Expand Up @@ -108,6 +108,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, `4` by default.

### `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 @@ -211,6 +218,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 @@ -147,7 +147,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);
Expand Down Expand Up @@ -181,6 +185,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

0 comments on commit d8d9a96

Please sign in to comment.