Skip to content

Commit fe56de9

Browse files
committed
net: rework autoSelectFamily implementation
1 parent 6473e9c commit fe56de9

8 files changed

+65
-35
lines changed

lib/_tls_wrap.js

+4-2
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,9 +633,11 @@ TLSSocket.prototype._wrapHandle = function(wrap, handle) {
633633
return res;
634634
};
635635

636-
TLSSocket.prototype[kWrapConnectedHandle] = function(handle) {
636+
TLSSocket.prototype[kReinitializeHandle] = function reinitializeHandle(handle) {
637637
this._handle = this._wrapHandle(null, handle);
638638
this.ssl = this._handle;
639+
640+
net.Socket.prototype[kReinitializeHandle].call(this, this._handle);
639641
this._init();
640642

641643
if (this._tlsOptions.enableTrace) {

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

+22-13
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ let debug = require('internal/util/debuglog').debuglog('net', (fn) => {
4242
debug = fn;
4343
});
4444
const {
45-
kWrapConnectedHandle,
45+
kReinitializeHandle,
4646
isIP,
4747
isIPv4,
4848
isIPv6,
@@ -53,7 +53,8 @@ const assert = require('internal/assert');
5353
const {
5454
UV_EADDRINUSE,
5555
UV_EINVAL,
56-
UV_ENOTCONN
56+
UV_ENOTCONN,
57+
UV_ECANCELED
5758
} = internalBinding('uv');
5859

5960
const { Buffer } = require('buffer');
@@ -1064,17 +1065,18 @@ function internalConnect(
10641065
}
10651066

10661067

1067-
function internalConnectMultiple(context) {
1068+
function internalConnectMultiple(context, canceled) {
10681069
clearTimeout(context[kTimeout]);
10691070
const self = context.socket;
1070-
assert(self.connecting);
10711071

10721072
// All connections have been tried without success, destroy with error
1073-
if (context.current === context.addresses.length) {
1073+
if (canceled || context.current === context.addresses.length) {
10741074
self.destroy(aggregateErrors(context.errors));
10751075
return;
10761076
}
10771077

1078+
assert(self.connecting);
1079+
10781080
const { localPort, port, flags } = context;
10791081
const { address, family: addressType } = context.addresses[context.current++];
10801082
const handle = new TCP(TCPConstants.SOCKET);
@@ -1101,6 +1103,8 @@ function internalConnectMultiple(context) {
11011103
}
11021104
}
11031105

1106+
debug('connect/multiple: attempting to connect to %s:%d (addressType: %d)', address, port, addressType);
1107+
11041108
const req = new TCPConnectWrap();
11051109
req.oncomplete = FunctionPrototypeBind(afterConnectMultiple, undefined, context);
11061110
req.address = address;
@@ -1190,6 +1194,13 @@ Socket.prototype.connect = function(...args) {
11901194
return this;
11911195
};
11921196

1197+
Socket.prototype[kReinitializeHandle] = function reinitializeHandle(handle) {
1198+
this._handle = handle;
1199+
this._handle[owner_symbol] = this;
1200+
1201+
initSocketHandle(this);
1202+
}
1203+
11931204
function socketToDnsFamily(family) {
11941205
switch (family) {
11951206
case 'IPv4':
@@ -1337,6 +1348,8 @@ function lookupAndConnectMultiple(self, async_id_symbol, lookup, host, options,
13371348
if (!self.connecting) {
13381349
return;
13391350
} else if (err) {
1351+
self.emit('lookup', err, undefined, undefined, host);
1352+
13401353
// net.createConnection() creates a net.Socket object and immediately
13411354
// calls net.Socket.connect() on it (that's us). There are no event
13421355
// listeners registered yet so defer the error event to the next tick.
@@ -1529,7 +1542,7 @@ function afterConnectMultiple(context, status, handle, req, readable, writable)
15291542
ArrayPrototypePush(context.errors, ex);
15301543

15311544
// Try the next address
1532-
internalConnectMultiple(context);
1545+
internalConnectMultiple(context, status === UV_ECANCELED);
15331546
return;
15341547
}
15351548

@@ -1540,13 +1553,9 @@ function afterConnectMultiple(context, status, handle, req, readable, writable)
15401553
return;
15411554
}
15421555

1543-
// Perform initialization sequence on the handle, then move on with the regular callback
1544-
self._handle = handle;
1545-
initSocketHandle(self);
1546-
1547-
if (self[kWrapConnectedHandle]) {
1548-
self[kWrapConnectedHandle](handle);
1549-
initSocketHandle(self); // This is called again to initialize the TLSWrap
1556+
if(self[kReinitializeHandle]) {
1557+
self[kReinitializeHandle](handle);
1558+
handle = self._handle;
15501559
}
15511560

15521561
if (hasObserver('net')) {

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-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
}));

0 commit comments

Comments
 (0)