| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -157,6 +157,8 @@ Create a new resolver. | |||
| 157 | 157 | default timeout. | |
| 158 | 158 | * `tries` {integer} The number of tries the resolver will try contacting | |
| 159 | 159 | each name server before giving up. **Default:** `4` | |
| 160 | + * `maxTimeout` {integer} The max retry timeout, in milliseconds. | ||
| 161 | + **Default:** `0`, disabled. | ||
| 160 | 162 | ||
| 161 | 163 | ### `resolver.cancel()` | |
| 162 | 164 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -25,6 +25,7 @@ const { | |||
| 25 | 25 | validateInt32, | |
| 26 | 26 | validateOneOf, | |
| 27 | 27 | validateString, | |
| 28 | + validateUint32, | ||
| 28 | 29 | } = require('internal/validators'); | |
| 29 | 30 | let binding; | |
| 30 | 31 | function lazyBinding() { | |
@@ -49,6 +50,12 @@ function validateTimeout(options) { | |||
| 49 | 50 | return timeout; | |
| 50 | 51 | } | |
| 51 | 52 | ||
| 53 | + function validateMaxTimeout(options) { | ||
| 54 | + const { maxTimeout = 0 } = { ...options }; | ||
| 55 | + validateUint32(maxTimeout, 'options.maxTimeout'); | ||
| 56 | + return maxTimeout; | ||
| 57 | + } | ||
| 58 | + | ||
| 52 | 59 | function validateTries(options) { | |
| 53 | 60 | const { tries = 4 } = { ...options }; | |
| 54 | 61 | validateInt32(tries, 'options.tries', 1); | |
@@ -67,17 +74,18 @@ class ResolverBase { | |||
| 67 | 74 | constructor(options = undefined) { | |
| 68 | 75 | const timeout = validateTimeout(options); | |
| 69 | 76 | const tries = validateTries(options); | |
| 77 | + const maxTimeout = validateMaxTimeout(options); | ||
| 70 | 78 | // If we are building snapshot, save the states of the resolver along | |
| 71 | 79 | // the way. | |
| 72 | 80 | if (isBuildingSnapshot()) { | |
| 73 | - this[kSnapshotStates] = { timeout, tries }; | ||
| 81 | + this[kSnapshotStates] = { timeout, tries, maxTimeout }; | ||
| 74 | 82 | } | |
| 75 | - this[kInitializeHandle](timeout, tries); | ||
| 83 | + this[kInitializeHandle](timeout, tries, maxTimeout); | ||
| 76 | 84 | } | |
| 77 | 85 | ||
| 78 | - [kInitializeHandle](timeout, tries) { | ||
| 86 | + [kInitializeHandle](timeout, tries, maxTimeout) { | ||
| 79 | 87 | const { ChannelWrap } = lazyBinding(); | |
| 80 | - this._handle = new ChannelWrap(timeout, tries); | ||
| 88 | + this._handle = new ChannelWrap(timeout, tries, maxTimeout); | ||
| 81 | 89 | } | |
| 82 | 90 | ||
| 83 | 91 | cancel() { | |
@@ -187,8 +195,8 @@ class ResolverBase { | |||
| 187 | 195 | } | |
| 188 | 196 | ||
| 189 | 197 | [kDeserializeResolver]() { | |
| 190 | - const { timeout, tries, localAddress, servers } = this[kSnapshotStates]; | ||
| 191 | - this[kInitializeHandle](timeout, tries); | ||
| 198 | + const { timeout, tries, maxTimeout, localAddress, servers } = this[kSnapshotStates]; | ||
| 199 | + this[kInitializeHandle](timeout, tries, maxTimeout); | ||
| 192 | 200 | if (localAddress) { | |
| 193 | 201 | const { ipv4, ipv6 } = localAddress; | |
| 194 | 202 | this._handle.setLocalAddress(ipv4, ipv6); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -787,14 +787,15 @@ Maybe<int> ParseSoaReply(Environment* env, | |||
| 787 | 787 | } | |
| 788 | 788 | } // anonymous namespace | |
| 789 | 789 | ||
| 790 | - ChannelWrap::ChannelWrap( | ||
| 791 | - Environment* env, | ||
| 792 | - Local<Object> object, | ||
| 793 | - int timeout, | ||
| 794 | - int tries) | ||
| 790 | + ChannelWrap::ChannelWrap(Environment* env, | ||
| 791 | + Local<Object> object, | ||
| 792 | + int timeout, | ||
| 793 | + int tries, | ||
| 794 | + int max_timeout) | ||
| 795 | 795 | : AsyncWrap(env, object, PROVIDER_DNSCHANNEL), | |
| 796 | 796 | timeout_(timeout), | |
| 797 | - tries_(tries) { | ||
| 797 | + tries_(tries), | ||
| 798 | + max_timeout_(max_timeout) { | ||
| 798 | 799 | MakeWeak(); | |
| 799 | 800 | ||
| 800 | 801 | Setup(); | |
@@ -808,13 +809,15 @@ void ChannelWrap::MemoryInfo(MemoryTracker* tracker) const { | |||
| 808 | 809 | ||
| 809 | 810 | void ChannelWrap::New(const FunctionCallbackInfo<Value>& args) { | |
| 810 | 811 | CHECK(args.IsConstructCall()); | |
| 811 | - CHECK_EQ(args.Length(), 2); | ||
| 812 | + CHECK_EQ(args.Length(), 3); | ||
| 812 | 813 | CHECK(args[0]->IsInt32()); | |
| 813 | 814 | CHECK(args[1]->IsInt32()); | |
| 815 | + CHECK(args[2]->IsInt32()); | ||
| 814 | 816 | const int timeout = args[0].As<Int32>()->Value(); | |
| 815 | 817 | const int tries = args[1].As<Int32>()->Value(); | |
| 818 | + const int max_timeout = args[2].As<Int32>()->Value(); | ||
| 816 | 819 | Environment* env = Environment::GetCurrent(args); | |
| 817 | - new ChannelWrap(env, args.This(), timeout, tries); | ||
| 820 | + new ChannelWrap(env, args.This(), timeout, tries, max_timeout); | ||
| 818 | 821 | } | |
| 819 | 822 | ||
| 820 | 823 | GetAddrInfoReqWrap::GetAddrInfoReqWrap(Environment* env, | |
@@ -879,9 +882,14 @@ void ChannelWrap::Setup() { | |||
| 879 | 882 | } | |
| 880 | 883 | ||
| 881 | 884 | /* We do the call to ares_init_option for caller. */ | |
| 882 | - const int optmask = ARES_OPT_FLAGS | ARES_OPT_TIMEOUTMS | | ||
| 883 | - ARES_OPT_SOCK_STATE_CB | ARES_OPT_TRIES | | ||
| 884 | - ARES_OPT_QUERY_CACHE; | ||
| 885 | + int optmask = ARES_OPT_FLAGS | ARES_OPT_TIMEOUTMS | ARES_OPT_SOCK_STATE_CB | | ||
| 886 | + ARES_OPT_TRIES | ARES_OPT_QUERY_CACHE; | ||
| 887 | + | ||
| 888 | + if (max_timeout_ > 0) { | ||
| 889 | + options.maxtimeout = max_timeout_; | ||
| 890 | + optmask |= ARES_OPT_MAXTIMEOUTMS; | ||
| 891 | + } | ||
| 892 | + | ||
| 885 | 893 | r = ares_init_options(&channel_, &options, optmask); | |
| 886 | 894 | ||
| 887 | 895 | if (r != ARES_SUCCESS) { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -151,11 +151,11 @@ struct NodeAresTask final : public MemoryRetainer { | |||
| 151 | 151 | ||
| 152 | 152 | class ChannelWrap final : public AsyncWrap { | |
| 153 | 153 | public: | |
| 154 | - ChannelWrap( | ||
| 155 | - Environment* env, | ||
| 156 | - v8::Local<v8::Object> object, | ||
| 157 | - int timeout, | ||
| 158 | - int tries); | ||
| 154 | + ChannelWrap(Environment* env, | ||
| 155 | + v8::Local<v8::Object> object, | ||
| 156 | + int timeout, | ||
| 157 | + int tries, | ||
| 158 | + int max_timeout); | ||
| 159 | 159 | ~ChannelWrap() override; | |
| 160 | 160 | ||
| 161 | 161 | static void New(const v8::FunctionCallbackInfo<v8::Value>& args); | |
@@ -190,6 +190,7 @@ class ChannelWrap final : public AsyncWrap { | |||
| 190 | 190 | bool library_inited_ = false; | |
| 191 | 191 | int timeout_; | |
| 192 | 192 | int tries_; | |
| 193 | + int max_timeout_; | ||
| 193 | 194 | int active_query_count_ = 0; | |
| 194 | 195 | NodeAresTask::List task_list_; | |
| 195 | 196 | }; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,77 @@ | |||
| 1 | + 'use strict'; | ||
| 2 | + const common = require('../common'); | ||
| 3 | + const dnstools = require('../common/dns'); | ||
| 4 | + const dns = require('dns'); | ||
| 5 | + const assert = require('assert'); | ||
| 6 | + const dgram = require('dgram'); | ||
| 7 | + | ||
| 8 | + [ | ||
| 9 | + -1, | ||
| 10 | + 1.1, | ||
| 11 | + NaN, | ||
| 12 | + undefined, | ||
| 13 | + {}, | ||
| 14 | + [], | ||
| 15 | + null, | ||
| 16 | + function() {}, | ||
| 17 | + Symbol(), | ||
| 18 | + true, | ||
| 19 | + Infinity, | ||
| 20 | + ].forEach((maxTimeout) => { | ||
| 21 | + try { | ||
| 22 | + new dns.Resolver({ maxTimeout }); | ||
| 23 | + } catch (e) { | ||
| 24 | + assert.ok(/ERR_OUT_OF_RANGE|ERR_INVALID_ARG_TYPE/i.test(e.code)); | ||
| 25 | + } | ||
| 26 | + }); | ||
| 27 | + | ||
| 28 | + const server = dgram.createSocket('udp4'); | ||
| 29 | + const nxdomain = 'nxdomain.org'; | ||
| 30 | + const domain = 'example.org'; | ||
| 31 | + const answers = [{ type: 'A', address: '1.2.3.4', ttl: 123, domain }]; | ||
| 32 | + | ||
| 33 | + server.on('message', common.mustCallAtLeast((msg, { address, port }) => { | ||
| 34 | + const parsed = dnstools.parseDNSPacket(msg); | ||
| 35 | + if (parsed.questions[0].domain === nxdomain) { | ||
| 36 | + return; | ||
| 37 | + } | ||
| 38 | + assert.strictEqual(parsed.questions[0].domain, domain); | ||
| 39 | + server.send(dnstools.writeDNSPacket({ | ||
| 40 | + id: parsed.id, | ||
| 41 | + questions: parsed.questions, | ||
| 42 | + answers: answers, | ||
| 43 | + }), port, address); | ||
| 44 | + }), 1); | ||
| 45 | + | ||
| 46 | + server.bind(0, common.mustCall(async () => { | ||
| 47 | + const address = server.address(); | ||
| 48 | + // Test if the Resolver works as before. | ||
| 49 | + const resolver = new dns.promises.Resolver({ timeout: 1000, tries: 1, maxTimeout: 1000 }); | ||
| 50 | + resolver.setServers([`127.0.0.1:${address.port}`]); | ||
| 51 | + const res = await resolver.resolveAny('example.org'); | ||
| 52 | + assert.strictEqual(res.length, 1); | ||
| 53 | + assert.strictEqual(res.length, answers.length); | ||
| 54 | + assert.strictEqual(res[0].address, answers[0].address); | ||
| 55 | + | ||
| 56 | + // Test that maxTimeout is effective. | ||
| 57 | + // Without maxTimeout, the timeout will keep increasing when retrying. | ||
| 58 | + const timeout1 = await timeout(address, { timeout: 500, tries: 3 }); | ||
| 59 | + // With maxTimeout, the timeout will always be 500 when retrying. | ||
| 60 | + const timeout2 = await timeout(address, { timeout: 500, tries: 3, maxTimeout: 500 }); | ||
| 61 | + console.log(`timeout1: ${timeout1}, timeout2: ${timeout2}`); | ||
| 62 | + assert.strictEqual(timeout1 !== undefined && timeout2 !== undefined, true); | ||
| 63 | + assert.strictEqual(timeout1 > timeout2, true); | ||
| 64 | + server.close(); | ||
| 65 | + })); | ||
| 66 | + | ||
| 67 | + async function timeout(address, options) { | ||
| 68 | + const start = Date.now(); | ||
| 69 | + const resolver = new dns.promises.Resolver(options); | ||
| 70 | + resolver.setServers([`127.0.0.1:${address.port}`]); | ||
| 71 | + try { | ||
| 72 | + await resolver.resolveAny(nxdomain); | ||
| 73 | + } catch (e) { | ||
| 74 | + assert.strictEqual(e.code, 'ETIMEOUT'); | ||
| 75 | + return Date.now() - start; | ||
| 76 | + } | ||
| 77 | + } | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments