dns: support max timeout · nodejs/node@c52aaac
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+}