diff options
-rw-r--r-- | doc/api/dns.md | 2 | ||||
-rw-r--r-- | lib/internal/dns/promises.js | 4 | ||||
-rw-r--r-- | lib/internal/dns/utils.js | 10 | ||||
-rw-r--r-- | src/cares_wrap.cc | 19 | ||||
-rw-r--r-- | src/cares_wrap.h | 7 |
5 files changed, 34 insertions, 8 deletions
diff --git a/doc/api/dns.md b/doc/api/dns.md index 45b2ff79e37..56f1522dd2f 100644 --- a/doc/api/dns.md +++ b/doc/api/dns.md @@ -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 diff --git a/lib/internal/dns/promises.js b/lib/internal/dns/promises.js index 035e7f354ef..e32b6a1dcd9 100644 --- a/lib/internal/dns/promises.js +++ b/lib/internal/dns/promises.js @@ -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); } } diff --git a/lib/internal/dns/utils.js b/lib/internal/dns/utils.js index 4f5cdf1104c..f15f8c7a779 100644 --- a/lib/internal/dns/utils.js +++ b/lib/internal/dns/utils.js @@ -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, diff --git a/src/cares_wrap.cc b/src/cares_wrap.cc index f4b069a28ea..9372aa6b7cc 100644 --- a/src/cares_wrap.cc +++ b/src/cares_wrap.cc @@ -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) { diff --git a/src/cares_wrap.h b/src/cares_wrap.h index 27322367556..649450315ed 100644 --- a/src/cares_wrap.h +++ b/src/cares_wrap.h @@ -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_; }; |