Skip to content

Commit 267439f

Browse files
ShogunPandaruyadorno
authored andcommittedAug 17, 2023
net: rework autoSelectFamily implementation
PR-URL: #46587 Backport-PR-URL: #49183 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
1 parent 0beb5ab commit 267439f

16 files changed

+247
-128
lines changed
 

‎doc/api/net.md

+43-21
Original file line numberDiff line numberDiff line change
@@ -935,7 +935,7 @@ For TCP connections, available `options` are:
935935
* `autoSelectFamilyAttemptTimeout` {number}: The amount of time in milliseconds to wait
936936
for a connection attempt to finish before trying the next address when using the `autoSelectFamily` option.
937937
If set to a positive integer less than `10`, then the value `10` will be used instead.
938-
**Default:** `250`.
938+
**Default:** initially `250`, but it can be changed at runtime using [`net.setDefaultAutoSelectFamilyAttemptTimeout(value)`][]
939939

940940
For [IPC][] connections, available `options` are:
941941

@@ -1520,26 +1520,6 @@ immediately initiates connection with
15201520
[`socket.connect(port[, host][, connectListener])`][`socket.connect(port)`],
15211521
then returns the `net.Socket` that starts the connection.
15221522

1523-
## `net.setDefaultAutoSelectFamily(value)`
1524-
1525-
<!-- YAML
1526-
added: REPLACEME
1527-
-->
1528-
1529-
Sets the default value of the `autoSelectFamily` option of [`socket.connect(options)`][].
1530-
1531-
* `value` {boolean} The new default value. The initial default value is `false`.
1532-
1533-
## `net.getDefaultAutoSelectFamily()`
1534-
1535-
<!-- YAML
1536-
added: REPLACEME
1537-
-->
1538-
1539-
Gets the current default value of the `autoSelectFamily` option of [`socket.connect(options)`][].
1540-
1541-
* Returns: {boolean} The current default value of the `autoSelectFamily` option.
1542-
15431523
## `net.createServer([options][, connectionListener])`
15441524

15451525
<!-- YAML
@@ -1640,6 +1620,47 @@ Use `nc` to connect to a Unix domain socket server:
16401620
$ nc -U /tmp/echo.sock
16411621
```
16421622

1623+
## `net.getDefaultAutoSelectFamily()`
1624+
1625+
<!-- YAML
1626+
added: v19.4.0
1627+
-->
1628+
1629+
Gets the current default value of the `autoSelectFamily` option of [`socket.connect(options)`][].
1630+
1631+
* Returns: {boolean} The current default value of the `autoSelectFamily` option.
1632+
1633+
## `net.setDefaultAutoSelectFamily(value)`
1634+
1635+
<!-- YAML
1636+
added: v19.4.0
1637+
-->
1638+
1639+
Sets the default value of the `autoSelectFamily` option of [`socket.connect(options)`][].
1640+
1641+
* `value` {boolean} The new default value. The initial default value is `false`.
1642+
1643+
## `net.getDefaultAutoSelectFamilyAttemptTimeout()`
1644+
1645+
<!-- YAML
1646+
added: REPLACEME
1647+
-->
1648+
1649+
Gets the current default value of the `autoSelectFamilyAttemptTimeout` option of [`socket.connect(options)`][].
1650+
1651+
* Returns: {number} The current default value of the `autoSelectFamilyAttemptTimeout` option.
1652+
1653+
## `net.setDefaultAutoSelectFamilyAttemptTimeout(value)`
1654+
1655+
<!-- YAML
1656+
added: REPLACEME
1657+
-->
1658+
1659+
Sets the default value of the `autoSelectFamilyAttemptTimeout` option of [`socket.connect(options)`][].
1660+
1661+
* `value` {number} The new default value, which must be a positive number. If the number is less than `10`,
1662+
the value `10` is used insted The initial default value is `250`.
1663+
16431664
## `net.isIP(input)`
16441665

16451666
<!-- YAML
@@ -1725,6 +1746,7 @@ net.isIPv6('fhqwhgads'); // returns false
17251746
[`net.createConnection(port, host)`]: #netcreateconnectionport-host-connectlistener
17261747
[`net.createServer()`]: #netcreateserveroptions-connectionlistener
17271748
[`net.setDefaultAutoSelectFamily(value)`]: #netsetdefaultautoselectfamilyvalue
1749+
[`net.setDefaultAutoSelectFamilyAttemptTimeout(value)`]: #netsetdefaultautoselectfamilyattempttimeoutvalue
17281750
[`new net.Socket(options)`]: #new-netsocketoptions
17291751
[`readable.setEncoding()`]: stream.md#readablesetencodingencoding
17301752
[`server.close()`]: #serverclosecallback

‎lib/_tls_wrap.js

+44-26
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ const EE = require('events');
5454
const net = require('net');
5555
const tls = require('tls');
5656
const common = require('_tls_common');
57-
const { kWrapConnectedHandle } = require('internal/net');
57+
const { kReinitializeHandle } = require('internal/net');
5858
const JSStreamSocket = require('internal/js_stream_socket');
5959
const { Buffer } = require('buffer');
6060
let debug = require('internal/util/debuglog').debuglog('tls', (fn) => {
@@ -633,14 +633,27 @@ TLSSocket.prototype._wrapHandle = function(wrap, handle) {
633633
return res;
634634
};
635635

636-
TLSSocket.prototype[kWrapConnectedHandle] = function(handle) {
637-
this._handle = this._wrapHandle(null, handle);
636+
TLSSocket.prototype[kReinitializeHandle] = function reinitializeHandle(handle) {
637+
const originalServername = this._handle.getServername();
638+
const originalSession = this._handle.getSession();
639+
640+
this.handle = this._wrapHandle(null, handle);
638641
this.ssl = this._handle;
642+
643+
net.Socket.prototype[kReinitializeHandle].call(this, this.handle);
639644
this._init();
640645

641646
if (this._tlsOptions.enableTrace) {
642647
this._handle.enableTrace();
643648
}
649+
650+
if (originalSession) {
651+
this.setSession(originalSession);
652+
}
653+
654+
if (originalServername) {
655+
this.setServername(originalServername);
656+
}
644657
};
645658

646659
// This eliminates a cyclic reference to TLSWrap
@@ -679,6 +692,30 @@ TLSSocket.prototype._destroySSL = function _destroySSL() {
679692
this[kIsVerified] = false;
680693
};
681694

695+
function keylogNewListener(event) {
696+
if (event !== 'keylog')
697+
return;
698+
699+
// Guard against enableKeylogCallback after destroy
700+
if (!this._handle) return;
701+
this._handle.enableKeylogCallback();
702+
703+
// Remove this listener since it's no longer needed.
704+
this.removeListener('newListener', keylogNewListener);
705+
}
706+
707+
function newListener(event) {
708+
if (event !== 'session')
709+
return;
710+
711+
// Guard against enableSessionCallbacks after destroy
712+
if (!this._handle) return;
713+
this._handle.enableSessionCallbacks();
714+
715+
// Remove this listener since it's no longer needed.
716+
this.removeListener('newListener', newListener);
717+
}
718+
682719
// Constructor guts, arbitrarily factored out.
683720
let warnOnTlsKeylog = true;
684721
let warnOnTlsKeylogError = true;
@@ -704,18 +741,9 @@ TLSSocket.prototype._init = function(socket, wrap) {
704741

705742
// Only call .onkeylog if there is a keylog listener.
706743
ssl.onkeylog = onkeylog;
707-
this.on('newListener', keylogNewListener);
708744

709-
function keylogNewListener(event) {
710-
if (event !== 'keylog')
711-
return;
712-
713-
// Guard against enableKeylogCallback after destroy
714-
if (!this._handle) return;
715-
this._handle.enableKeylogCallback();
716-
717-
// Remove this listener since it's no longer needed.
718-
this.removeListener('newListener', keylogNewListener);
745+
if (this.listenerCount('newListener', keylogNewListener) === 0) {
746+
this.on('newListener', keylogNewListener);
719747
}
720748

721749
if (options.isServer) {
@@ -750,18 +778,8 @@ TLSSocket.prototype._init = function(socket, wrap) {
750778
ssl.onnewsession = onnewsessionclient;
751779

752780
// Only call .onnewsession if there is a session listener.
753-
this.on('newListener', newListener);
754-
755-
function newListener(event) {
756-
if (event !== 'session')
757-
return;
758-
759-
// Guard against enableSessionCallbacks after destroy
760-
if (!this._handle) return;
761-
this._handle.enableSessionCallbacks();
762-
763-
// Remove this listener since it's no longer needed.
764-
this.removeListener('newListener', newListener);
781+
if (this.listenerCount('newListener', newListener) === 0) {
782+
this.on('newListener', newListener);
765783
}
766784
}
767785

‎lib/internal/net.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ function makeSyncWrite(fd) {
6767
}
6868

6969
module.exports = {
70-
kWrapConnectedHandle: Symbol('wrapConnectedHandle'),
70+
kReinitializeHandle: Symbol('reinitializeHandle'),
7171
isIP,
7272
isIPv4,
7373
isIPv6,

‎lib/net.js

+61-26
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ let debug = require('internal/util/debuglog').debuglog('net', (fn) => {
4343
debug = fn;
4444
});
4545
const {
46-
kWrapConnectedHandle,
46+
kReinitializeHandle,
4747
isIP,
4848
isIPv4,
4949
isIPv6,
@@ -55,6 +55,7 @@ const {
5555
UV_EADDRINUSE,
5656
UV_EINVAL,
5757
UV_ENOTCONN,
58+
UV_ECANCELED,
5859
} = internalBinding('uv');
5960

6061
const { Buffer } = require('buffer');
@@ -132,6 +133,7 @@ let dns;
132133
let BlockList;
133134
let SocketAddress;
134135
let autoSelectFamilyDefault = getOptionValue('--enable-network-family-autoselection');
136+
let autoSelectFamilyAttemptTimeoutDefault = 250;
135137

136138
const { clearTimeout, setTimeout } = require('timers');
137139
const { kTimeout } = require('internal/timers');
@@ -254,6 +256,20 @@ function setDefaultAutoSelectFamily(value) {
254256
autoSelectFamilyDefault = value;
255257
}
256258

259+
function getDefaultAutoSelectFamilyAttemptTimeout() {
260+
return autoSelectFamilyAttemptTimeoutDefault;
261+
}
262+
263+
function setDefaultAutoSelectFamilyAttemptTimeout(value) {
264+
validateInt32(value, 'value', 1);
265+
266+
if (value < 1) {
267+
value = 10;
268+
}
269+
270+
autoSelectFamilyAttemptTimeoutDefault = value;
271+
}
272+
257273
// Returns an array [options, cb], where options is an object,
258274
// cb is either a function or null.
259275
// Used to normalize arguments of Socket.prototype.connect() and
@@ -694,7 +710,11 @@ function tryReadStart(socket) {
694710

695711
// Just call handle.readStart until we have enough in the buffer
696712
Socket.prototype._read = function(n) {
697-
debug('_read');
713+
debug(
714+
'_read - n', n,
715+
'isConnecting?', !!this.connecting,
716+
'hasHandle?', !!this._handle,
717+
);
698718

699719
if (this.connecting || !this._handle) {
700720
debug('_read wait for connection');
@@ -1034,7 +1054,7 @@ function internalConnect(
10341054
localAddress = localAddress || DEFAULT_IPV6_ADDR;
10351055
err = self._handle.bind6(localAddress, localPort, flags);
10361056
}
1037-
debug('binding to localAddress: %s and localPort: %d (addressType: %d)',
1057+
debug('connect: binding to localAddress: %s and localPort: %d (addressType: %d)',
10381058
localAddress, localPort, addressType);
10391059

10401060
err = checkBindError(err, localPort, self._handle);
@@ -1045,6 +1065,8 @@ function internalConnect(
10451065
}
10461066
}
10471067

1068+
debug('connect: attempting to connect to %s:%d (addressType: %d)', address, port, addressType);
1069+
10481070
if (addressType === 6 || addressType === 4) {
10491071
const req = new TCPConnectWrap();
10501072
req.oncomplete = afterConnect;
@@ -1081,17 +1103,17 @@ function internalConnect(
10811103
}
10821104

10831105

1084-
function internalConnectMultiple(context) {
1106+
function internalConnectMultiple(context, canceled) {
10851107
clearTimeout(context[kTimeout]);
10861108
const self = context.socket;
1087-
assert(self.connecting);
10881109

10891110
// All connections have been tried without success, destroy with error
1090-
if (context.current === context.addresses.length) {
1111+
if (canceled || context.current === context.addresses.length) {
10911112
self.destroy(aggregateErrors(context.errors));
10921113
return;
10931114
}
10941115

1116+
assert(self.connecting);
10951117

10961118
const current = context.current++;
10971119
const handle = current === 0 ? self._handle : new TCP(TCPConstants.SOCKET);
@@ -1120,6 +1142,8 @@ function internalConnectMultiple(context) {
11201142
}
11211143
}
11221144

1145+
debug('connect/multiple: attempting to connect to %s:%d (addressType: %d)', address, port, addressType);
1146+
11231147
const req = new TCPConnectWrap();
11241148
req.oncomplete = FunctionPrototypeBind(afterConnectMultiple, undefined, context, current);
11251149
req.address = address;
@@ -1213,6 +1237,15 @@ Socket.prototype.connect = function(...args) {
12131237
return this;
12141238
};
12151239

1240+
Socket.prototype[kReinitializeHandle] = function reinitializeHandle(handle) {
1241+
this._handle?.close();
1242+
1243+
this._handle = handle;
1244+
this._handle[owner_symbol] = this;
1245+
1246+
initSocketHandle(this);
1247+
};
1248+
12161249
function socketToDnsFamily(family) {
12171250
switch (family) {
12181251
case 'IPv4':
@@ -1260,7 +1293,7 @@ function lookupAndConnect(self, options) {
12601293
autoSelectFamilyAttemptTimeout = 10;
12611294
}
12621295
} else {
1263-
autoSelectFamilyAttemptTimeout = 250;
1296+
autoSelectFamilyAttemptTimeout = autoSelectFamilyAttemptTimeoutDefault;
12641297
}
12651298

12661299
// If host is an IP, skip performing a lookup
@@ -1302,17 +1335,19 @@ function lookupAndConnect(self, options) {
13021335
debug('connect: autodetecting');
13031336

13041337
dnsopts.all = true;
1305-
lookupAndConnectMultiple(
1306-
self,
1307-
async_id_symbol,
1308-
lookup,
1309-
host,
1310-
options,
1311-
dnsopts,
1312-
port,
1313-
localPort,
1314-
autoSelectFamilyAttemptTimeout,
1315-
);
1338+
defaultTriggerAsyncIdScope(self[async_id_symbol], function() {
1339+
lookupAndConnectMultiple(
1340+
self,
1341+
async_id_symbol,
1342+
lookup,
1343+
host,
1344+
options,
1345+
dnsopts,
1346+
port,
1347+
localPort,
1348+
autoSelectFamilyAttemptTimeout,
1349+
);
1350+
});
13161351

13171352
return;
13181353
}
@@ -1360,6 +1395,8 @@ function lookupAndConnectMultiple(self, async_id_symbol, lookup, host, options,
13601395
if (!self.connecting) {
13611396
return;
13621397
} else if (err) {
1398+
self.emit('lookup', err, undefined, undefined, host);
1399+
13631400
// net.createConnection() creates a net.Socket object and immediately
13641401
// calls net.Socket.connect() on it (that's us). There are no event
13651402
// listeners registered yet so defer the error event to the next tick.
@@ -1559,7 +1596,7 @@ function afterConnectMultiple(context, current, status, handle, req, readable, w
15591596
ArrayPrototypePush(context.errors, ex);
15601597

15611598
// Try the next address
1562-
internalConnectMultiple(context);
1599+
internalConnectMultiple(context, status === UV_ECANCELED);
15631600
return;
15641601
}
15651602

@@ -1570,13 +1607,9 @@ function afterConnectMultiple(context, current, status, handle, req, readable, w
15701607
return;
15711608
}
15721609

1573-
// Perform initialization sequence on the handle, then move on with the regular callback
1574-
self._handle = handle;
1575-
initSocketHandle(self);
1576-
1577-
if (self[kWrapConnectedHandle]) {
1578-
self[kWrapConnectedHandle](handle);
1579-
initSocketHandle(self); // This is called again to initialize the TLSWrap
1610+
if (context.current > 1 && self[kReinitializeHandle]) {
1611+
self[kReinitializeHandle](handle);
1612+
handle = self._handle;
15801613
}
15811614

15821615
if (hasObserver('net')) {
@@ -2295,4 +2328,6 @@ module.exports = {
22952328
Stream: Socket, // Legacy naming
22962329
getDefaultAutoSelectFamily,
22972330
setDefaultAutoSelectFamily,
2331+
getDefaultAutoSelectFamilyAttemptTimeout,
2332+
setDefaultAutoSelectFamilyAttemptTimeout,
22982333
};

‎test/parallel/test-http-autoselectfamily.js

+3-7
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,12 @@ const assert = require('assert');
77
const dgram = require('dgram');
88
const { Resolver } = require('dns');
99
const { request, createServer } = require('http');
10+
const { setDefaultAutoSelectFamilyAttemptTimeout } = require('net');
1011

1112
// Test that happy eyeballs algorithm is properly implemented when using HTTP.
1213

13-
let autoSelectFamilyAttemptTimeout = common.platformTimeout(250);
14-
if (common.isWindows) {
15-
// Some of the windows machines in the CI need more time to establish connection
16-
autoSelectFamilyAttemptTimeout = common.platformTimeout(1500);
17-
}
14+
// Some of the windows machines in the CI need more time to establish connection
15+
setDefaultAutoSelectFamilyAttemptTimeout(common.platformTimeout(common.isWindows ? 1500 : 250));
1816

1917
function _lookup(resolver, hostname, options, cb) {
2018
resolver.resolve(hostname, 'ANY', (err, replies) => {
@@ -77,7 +75,6 @@ function createDnsServer(ipv6Addr, ipv4Addr, cb) {
7775
{
7876
lookup,
7977
autoSelectFamily: true,
80-
autoSelectFamilyAttemptTimeout
8178
},
8279
(res) => {
8380
assert.strictEqual(res.statusCode, 200);
@@ -122,7 +119,6 @@ if (common.hasIPv6) {
122119
{
123120
lookup,
124121
autoSelectFamily: true,
125-
autoSelectFamilyAttemptTimeout,
126122
},
127123
(res) => {
128124
assert.strictEqual(res.statusCode, 200);

‎test/parallel/test-http2-ping-settings-heapdump.js

+9-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,14 @@ const v8 = require('v8');
1111
// after it is destroyed, either because they are detached from it or have been
1212
// destroyed themselves.
1313

14+
// We use an higher autoSelectFamilyAttemptTimeout in this test as the v8.getHeapSnapshot().resume()
15+
// will slow the connection flow and we don't want the second connection attempt to start.
16+
let autoSelectFamilyAttemptTimeout = common.platformTimeout(1000);
17+
if (common.isWindows) {
18+
// Some of the windows machines in the CI need more time to establish connection
19+
autoSelectFamilyAttemptTimeout = common.platformTimeout(10000);
20+
}
21+
1422
for (const variant of ['ping', 'settings']) {
1523
const server = http2.createServer();
1624
server.on('session', common.mustCall((session) => {
@@ -30,7 +38,7 @@ for (const variant of ['ping', 'settings']) {
3038
}));
3139

3240
server.listen(0, common.mustCall(() => {
33-
const client = http2.connect(`http://localhost:${server.address().port}`,
41+
const client = http2.connect(`http://localhost:${server.address().port}`, { autoSelectFamilyAttemptTimeout },
3442
common.mustCall());
3543
client.on('error', (err) => {
3644
// We destroy the session so it's possible to get ECONNRESET here.

‎test/parallel/test-https-autoselectfamily.js

+3-9
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ const assert = require('assert');
1313
const dgram = require('dgram');
1414
const { Resolver } = require('dns');
1515
const { request, createServer } = require('https');
16+
const { setDefaultAutoSelectFamilyAttemptTimeout } = require('net');
1617

1718
if (!common.hasCrypto)
1819
common.skip('missing crypto');
@@ -24,11 +25,8 @@ const options = {
2425

2526
// Test that happy eyeballs algorithm is properly implemented when using HTTP.
2627

27-
let autoSelectFamilyAttemptTimeout = common.platformTimeout(250);
28-
if (common.isWindows) {
29-
// Some of the windows machines in the CI need more time to establish connection
30-
autoSelectFamilyAttemptTimeout = common.platformTimeout(1500);
31-
}
28+
// Some of the windows machines in the CI need more time to establish connection
29+
setDefaultAutoSelectFamilyAttemptTimeout(common.platformTimeout(common.isWindows ? 1500 : 250));
3230

3331
function _lookup(resolver, hostname, options, cb) {
3432
resolver.resolve(hostname, 'ANY', (err, replies) => {
@@ -93,8 +91,6 @@ function createDnsServer(ipv6Addr, ipv4Addr, cb) {
9391
lookup,
9492
rejectUnauthorized: false,
9593
autoSelectFamily: true,
96-
autoSelectFamilyAttemptTimeout,
97-
servername: 'example.org',
9894
},
9995
(res) => {
10096
assert.strictEqual(res.statusCode, 200);
@@ -142,8 +138,6 @@ if (common.hasIPv6) {
142138
lookup,
143139
rejectUnauthorized: false,
144140
autoSelectFamily: true,
145-
autoSelectFamilyAttemptTimeout,
146-
servername: 'example.org',
147141
},
148142
(res) => {
149143
assert.strictEqual(res.statusCode, 200);

‎test/parallel/test-net-autoselectfamily-commandline-option.js

+3-7
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,12 @@ const { parseDNSPacket, writeDNSPacket } = require('../common/dns');
88
const assert = require('assert');
99
const dgram = require('dgram');
1010
const { Resolver } = require('dns');
11-
const { createConnection, createServer } = require('net');
11+
const { createConnection, createServer, setDefaultAutoSelectFamilyAttemptTimeout } = require('net');
1212

1313
// Test that happy eyeballs algorithm can be enable from command line.
1414

15-
let autoSelectFamilyAttemptTimeout = common.platformTimeout(250);
16-
if (common.isWindows) {
17-
// Some of the windows machines in the CI need more time to establish connection
18-
autoSelectFamilyAttemptTimeout = common.platformTimeout(1500);
19-
}
15+
// Some of the windows machines in the CI need more time to establish connection
16+
setDefaultAutoSelectFamilyAttemptTimeout(common.platformTimeout(common.isWindows ? 1500 : 250));
2017

2118
function _lookup(resolver, hostname, options, cb) {
2219
resolver.resolve(hostname, 'ANY', (err, replies) => {
@@ -82,7 +79,6 @@ function createDnsServer(ipv6Addr, ipv4Addr, cb) {
8279
host: 'example.org',
8380
port: port,
8481
lookup,
85-
autoSelectFamilyAttemptTimeout,
8682
});
8783

8884
let response = '';

‎test/parallel/test-net-autoselectfamily-ipv4first.js

+3-7
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,12 @@ const { parseDNSPacket, writeDNSPacket } = require('../common/dns');
66
const assert = require('assert');
77
const dgram = require('dgram');
88
const { Resolver } = require('dns');
9-
const { createConnection, createServer } = require('net');
9+
const { createConnection, createServer, setDefaultAutoSelectFamilyAttemptTimeout } = require('net');
1010

1111
// Test that happy eyeballs algorithm is properly implemented when a A record is returned first.
1212

13-
let autoSelectFamilyAttemptTimeout = common.platformTimeout(250);
14-
if (common.isWindows) {
15-
// Some of the windows machines in the CI need more time to establish connection
16-
autoSelectFamilyAttemptTimeout = common.platformTimeout(1500);
17-
}
13+
// Some of the windows machines in the CI need more time to establish connection
14+
setDefaultAutoSelectFamilyAttemptTimeout(common.platformTimeout(common.isWindows ? 1500 : 250));
1815

1916
function _lookup(resolver, hostname, options, cb) {
2017
resolver.resolve(hostname, 'ANY', (err, replies) => {
@@ -88,7 +85,6 @@ if (common.hasIPv6) {
8885
port,
8986
lookup,
9087
autoSelectFamily: true,
91-
autoSelectFamilyAttemptTimeout
9288
});
9389

9490
let response = '';

‎test/parallel/test-net-autoselectfamily.js

+5-5
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@ const { createConnection, createServer } = require('net');
1010

1111
// Test that happy eyeballs algorithm is properly implemented.
1212

13-
let autoSelectFamilyAttemptTimeout = common.platformTimeout(250);
14-
if (common.isWindows) {
15-
// Some of the windows machines in the CI need more time to establish connection
16-
autoSelectFamilyAttemptTimeout = common.platformTimeout(1500);
17-
}
13+
// Purposely not using setDefaultAutoSelectFamilyAttemptTimeout here to test the
14+
// parameter is correctly used in options.
15+
//
16+
// Some of the windows machines in the CI need more time to establish connection
17+
const autoSelectFamilyAttemptTimeout = common.platformTimeout(common.isWindows ? 1500 : 250);
1818

1919
function _lookup(resolver, hostname, options, cb) {
2020
resolver.resolve(hostname, 'ANY', (err, replies) => {

‎test/parallel/test-net-dns-custom-lookup.js

+16-3
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,22 @@ function check(addressType, cb) {
2626

2727
function lookup(host, dnsopts, cb) {
2828
dnsopts.family = addressType;
29+
2930
if (addressType === 4) {
3031
process.nextTick(function() {
31-
cb(null, common.localhostIPv4, 4);
32+
if (dnsopts.all) {
33+
cb(null, [{ address: common.localhostIPv4, family: 4 }]);
34+
} else {
35+
cb(null, common.localhostIPv4, 4);
36+
}
3237
});
3338
} else {
3439
process.nextTick(function() {
35-
cb(null, '::1', 6);
40+
if (dnsopts.all) {
41+
cb(null, [{ address: '::1', family: 6 }]);
42+
} else {
43+
cb(null, '::1', 6);
44+
}
3645
});
3746
}
3847
}
@@ -48,7 +57,11 @@ check(4, function() {
4857
host: 'localhost',
4958
port: 80,
5059
lookup(host, dnsopts, cb) {
51-
cb(null, undefined, 4);
60+
if (dnsopts.all) {
61+
cb(null, [{ address: undefined, family: 4 }]);
62+
} else {
63+
cb(null, undefined, 4);
64+
}
5265
}
5366
}).on('error', common.expectsError({ code: 'ERR_INVALID_IP_ADDRESS' }));
5467
}

‎test/parallel/test-net-dns-lookup.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,10 @@ const server = net.createServer(function(client) {
3131

3232
server.listen(0, common.mustCall(function() {
3333
net.connect(this.address().port, 'localhost')
34-
.on('lookup', common.mustCall(function(err, ip, type, host) {
34+
.on('lookup', common.mustCallAtLeast(function(err, ip, type, host) {
3535
assert.strictEqual(err, null);
3636
assert.match(ip, /^(127\.0\.0\.1|::1)$/);
3737
assert.match(type.toString(), /^(4|6)$/);
3838
assert.strictEqual(host, 'localhost');
39-
}));
39+
}, 1));
4040
}));

‎test/parallel/test-net-options-lookup.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,11 @@ function connectDoesNotThrow(input) {
3636
{
3737
// Verify that an error is emitted when an invalid address family is returned.
3838
const s = connectDoesNotThrow((host, options, cb) => {
39-
cb(null, '127.0.0.1', 100);
39+
if (options.all) {
40+
cb(null, [{ address: '127.0.0.1', family: 100 }]);
41+
} else {
42+
cb(null, '127.0.0.1', 100);
43+
}
4044
});
4145

4246
s.on('error', common.expectsError({

‎test/parallel/test-net-server-reset.js

+6-12
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,11 @@ server.on('close', common.mustCall());
2020

2121
assert.strictEqual(server, server.listen(0, () => {
2222
net.createConnection(server.address().port)
23-
.on('error', common.mustCall(
24-
common.expectsError({
25-
code: 'ECONNRESET',
26-
name: 'Error'
27-
}))
28-
);
23+
.on('error', common.mustCall((error) => {
24+
assert.strictEqual(error.code, 'ECONNRESET');
25+
}));
2926
net.createConnection(server.address().port)
30-
.on('error', common.mustCall(
31-
common.expectsError({
32-
code: 'ECONNRESET',
33-
name: 'Error'
34-
}))
35-
);
27+
.on('error', common.mustCall((error) => {
28+
assert.strictEqual(error.code, 'ECONNRESET');
29+
}));
3630
}));

‎test/parallel/test-net-socket-connect-invalid-autoselectfamilyattempttimeout.js

+6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
'use strict';
2+
23
require('../common');
4+
35
const assert = require('assert');
46
const net = require('net');
57

@@ -11,4 +13,8 @@ for (const autoSelectFamilyAttemptTimeout of [-10, 0]) {
1113
autoSelectFamilyAttemptTimeout,
1214
});
1315
}, { code: 'ERR_OUT_OF_RANGE' });
16+
17+
assert.throws(() => {
18+
net.setDefaultAutoSelectFamilyAttemptTimeout(autoSelectFamilyAttemptTimeout);
19+
}, { code: 'ERR_OUT_OF_RANGE' });
1420
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
5+
if (!common.hasCrypto) {
6+
common.skip('missing crypto');
7+
}
8+
9+
const { setDefaultAutoSelectFamilyAttemptTimeout } = require('net');
10+
const { connect } = require('tls');
11+
12+
// Some of the windows machines in the CI need more time to establish connection
13+
setDefaultAutoSelectFamilyAttemptTimeout(common.platformTimeout(common.isWindows ? 1500 : 250));
14+
15+
// Test that TLS connecting works without autoSelectFamily
16+
{
17+
const socket = connect({
18+
host: 'google.com',
19+
port: 443,
20+
servername: 'google.com',
21+
autoSelectFamily: false,
22+
});
23+
24+
socket.on('secureConnect', common.mustCall(() => socket.end()));
25+
}
26+
27+
// Test that TLS connecting works with autoSelectFamily
28+
{
29+
const socket = connect({
30+
host: 'google.com',
31+
port: 443,
32+
servername: 'google.com',
33+
autoSelectFamily: true,
34+
});
35+
36+
socket.on('secureConnect', common.mustCall(() => socket.end()));
37+
}

0 commit comments

Comments
 (0)
Please sign in to comment.