| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 24e334b commit 55321ba
22 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -462,14 +462,20 @@ added: v6.0.0 | |||
| 462 | 462 | Enable FIPS-compliant crypto at startup. (Requires Node.js to be built | |
| 463 | 463 | against FIPS-compatible OpenSSL.) | |
| 464 | 464 | ||
| 465 | - ### `--enable-network-family-autoselection` | ||
| 465 | + ### `--no-network-family-autoselection` | ||
| 466 | 466 | ||
| 467 | 467 | <!-- YAML | |
| 468 | 468 | added: v19.4.0 | |
| 469 | + changes: | ||
| 470 | + - version: REPLACEME | ||
| 471 | + pr-url: https://github.com/nodejs/node/pull/46790 | ||
| 472 | + description: The flag was renamed from `--no-enable-network-family-autoselection` | ||
| 473 | + to `--no-network-family-autoselection`. The old name can still work as | ||
| 474 | + an alias. | ||
| 469 | 475 | --> | |
| 470 | 476 | ||
| 471 | - Enables the family autoselection algorithm unless connection options explicitly | ||
| 472 | - disables it. | ||
| 477 | + Disables the family autoselection algorithm unless connection options explicitly | ||
| 478 | + enables it. | ||
| 473 | 479 | ||
| 474 | 480 | ### `--enable-source-maps` | |
| 475 | 481 | ||
@@ -2125,6 +2131,7 @@ Node.js options that are allowed are: | |||
| 2125 | 2131 | * `--no-extra-info-on-fatal-exception` | |
| 2126 | 2132 | * `--no-force-async-hooks-checks` | |
| 2127 | 2133 | * `--no-global-search-paths` | |
| 2134 | + * `--no-network-family-autoselection` | ||
| 2128 | 2135 | * `--no-warnings` | |
| 2129 | 2136 | * `--node-memory-debug` | |
| 2130 | 2137 | * `--openssl-config` | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -2593,6 +2593,13 @@ An attempt was made to operate on an already closed socket. | |||
| 2593 | 2593 | When calling [`net.Socket.write()`][] on a connecting socket and the socket was | |
| 2594 | 2594 | closed before the connection was established. | |
| 2595 | 2595 | ||
| 2596 | + <a id="ERR_SOCKET_CONNECTION_TIMEOUT"></a> | ||
| 2597 | + | ||
| 2598 | + ### `ERR_SOCKET_CONNECTION_TIMEOUT` | ||
| 2599 | + | ||
| 2600 | + The socket was unable to connect to any address returned by the DNS within the | ||
| 2601 | + allowed timeout when using the family autoselection algorithm. | ||
| 2602 | + | ||
| 2596 | 2603 | <a id="ERR_SOCKET_DGRAM_IS_CONNECTED"></a> | |
| 2597 | 2604 | ||
| 2598 | 2605 | ### `ERR_SOCKET_DGRAM_IS_CONNECTED` | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -870,6 +870,12 @@ behavior. | |||
| 870 | 870 | <!-- YAML | |
| 871 | 871 | added: v0.1.90 | |
| 872 | 872 | changes: | |
| 873 | + - version: REPLACEME | ||
| 874 | + pr-url: https://github.com/nodejs/node/pull/46790 | ||
| 875 | + description: The default value for the autoSelectFamily option is now true. | ||
| 876 | + The `--enable-network-family-autoselection` CLI flag has been renamed | ||
| 877 | + to `--network-family-autoselection`. The old name is now an | ||
| 878 | + alias but it is discouraged. | ||
| 873 | 879 | - version: v19.4.0 | |
| 874 | 880 | pr-url: https://github.com/nodejs/node/pull/45777 | |
| 875 | 881 | description: The default value for autoSelectFamily option can be changed | |
@@ -936,12 +942,12 @@ For TCP connections, available `options` are: | |||
| 936 | 942 | option before timing out and trying the next address. | |
| 937 | 943 | Ignored if the `family` option is not `0` or if `localAddress` is set. | |
| 938 | 944 | Connection errors are not emitted if at least one connection succeeds. | |
| 939 | - **Default:** initially `false`, but it can be changed at runtime using [`net.setDefaultAutoSelectFamily(value)`][] | ||
| 940 | - or via the command line option `--enable-network-family-autoselection`. | ||
| 945 | + If all connections attempts fails, a single `AggregateError` with all failed attempts is emitted. | ||
| 946 | + **Default:** [`net.getDefaultAutoSelectFamily()`][] | ||
| 941 | 947 | * `autoSelectFamilyAttemptTimeout` {number}: The amount of time in milliseconds to wait | |
| 942 | 948 | for a connection attempt to finish before trying the next address when using the `autoSelectFamily` option. | |
| 943 | 949 | If set to a positive integer less than `10`, then the value `10` will be used instead. | |
| 944 | - **Default:** initially `250`, but it can be changed at runtime using [`net.setDefaultAutoSelectFamilyAttemptTimeout(value)`][] | ||
| 950 | + **Default:** [`net.getDefaultAutoSelectFamilyAttemptTimeout()`][] | ||
| 945 | 951 | ||
| 946 | 952 | For [IPC][] connections, available `options` are: | |
| 947 | 953 | ||
@@ -1629,6 +1635,8 @@ added: v19.4.0 | |||
| 1629 | 1635 | --> | |
| 1630 | 1636 | ||
| 1631 | 1637 | Gets the current default value of the `autoSelectFamily` option of [`socket.connect(options)`][]. | |
| 1638 | + The initial default value is `true`, unless the command line option | ||
| 1639 | + `--no-network-family-autoselection` is provided. | ||
| 1632 | 1640 | ||
| 1633 | 1641 | * Returns: {boolean} The current default value of the `autoSelectFamily` option. | |
| 1634 | 1642 | ||
@@ -1649,6 +1657,7 @@ added: v19.8.0 | |||
| 1649 | 1657 | --> | |
| 1650 | 1658 | ||
| 1651 | 1659 | Gets the current default value of the `autoSelectFamilyAttemptTimeout` option of [`socket.connect(options)`][]. | |
| 1660 | + The initial default value is `250`. | ||
| 1652 | 1661 | ||
| 1653 | 1662 | * Returns: {number} The current default value of the `autoSelectFamilyAttemptTimeout` option. | |
| 1654 | 1663 | ||
@@ -1747,8 +1756,8 @@ net.isIPv6('fhqwhgads'); // returns false | |||
| 1747 | 1756 | [`net.createConnection(path)`]: #netcreateconnectionpath-connectlistener | |
| 1748 | 1757 | [`net.createConnection(port, host)`]: #netcreateconnectionport-host-connectlistener | |
| 1749 | 1758 | [`net.createServer()`]: #netcreateserveroptions-connectionlistener | |
| 1750 | - [`net.setDefaultAutoSelectFamily(value)`]: #netsetdefaultautoselectfamilyvalue | ||
| 1751 | - [`net.setDefaultAutoSelectFamilyAttemptTimeout(value)`]: #netsetdefaultautoselectfamilyattempttimeoutvalue | ||
| 1759 | + [`net.getDefaultAutoSelectFamily()`]: #netgetdefaultautoselectfamily | ||
| 1760 | + [`net.getDefaultAutoSelectFamilyAttemptTimeout()`]: #netgetdefaultautoselectfamilyattempttimeout | ||
| 1752 | 1761 | [`new net.Socket(options)`]: #new-netsocketoptions | |
| 1753 | 1762 | [`readable.setEncoding()`]: stream.md#readablesetencodingencoding | |
| 1754 | 1763 | [`server.close()`]: #serverclosecallback | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1567,6 +1567,8 @@ E('ERR_SOCKET_CLOSED', 'Socket is closed', Error); | |||
| 1567 | 1567 | E('ERR_SOCKET_CLOSED_BEFORE_CONNECTION', | |
| 1568 | 1568 | 'Socket closed before the connection was established', | |
| 1569 | 1569 | Error); | |
| 1570 | + E('ERR_SOCKET_CONNECTION_TIMEOUT', | ||
| 1571 | + 'Socket connection timeout', Error); | ||
| 1570 | 1572 | E('ERR_SOCKET_DGRAM_IS_CONNECTED', 'Already connected', Error); | |
| 1571 | 1573 | E('ERR_SOCKET_DGRAM_NOT_CONNECTED', 'Not connected', Error); | |
| 1572 | 1574 | E('ERR_SOCKET_DGRAM_NOT_RUNNING', 'Not running', Error); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -67,7 +67,7 @@ function makeSyncWrite(fd) { | |||
| 67 | 67 | } | |
| 68 | 68 | ||
| 69 | 69 | module.exports = { | |
| 70 | - kReinitializeHandle: Symbol('reinitializeHandle'), | ||
| 70 | + kReinitializeHandle: Symbol('kReinitializeHandle'), | ||
| 71 | 71 | isIP, | |
| 72 | 72 | isIPv4, | |
| 73 | 73 | isIPv6, | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -23,6 +23,7 @@ | |||
| 23 | 23 | ||
| 24 | 24 | const { | |
| 25 | 25 | ArrayIsArray, | |
| 26 | + ArrayPrototypeIncludes, | ||
| 26 | 27 | ArrayPrototypeIndexOf, | |
| 27 | 28 | ArrayPrototypePush, | |
| 28 | 29 | Boolean, | |
@@ -97,6 +98,7 @@ const { | |||
| 97 | 98 | ERR_INVALID_HANDLE_TYPE, | |
| 98 | 99 | ERR_SERVER_ALREADY_LISTEN, | |
| 99 | 100 | ERR_SERVER_NOT_RUNNING, | |
| 101 | + ERR_SOCKET_CONNECTION_TIMEOUT, | ||
| 100 | 102 | ERR_SOCKET_CLOSED, | |
| 101 | 103 | ERR_SOCKET_CLOSED_BEFORE_CONNECTION, | |
| 102 | 104 | ERR_MISSING_ARGS, | |
@@ -127,7 +129,7 @@ let cluster; | |||
| 127 | 129 | let dns; | |
| 128 | 130 | let BlockList; | |
| 129 | 131 | let SocketAddress; | |
| 130 | - let autoSelectFamilyDefault = getOptionValue('--enable-network-family-autoselection'); | ||
| 132 | + let autoSelectFamilyDefault = getOptionValue('--network-family-autoselection'); | ||
| 131 | 133 | let autoSelectFamilyAttemptTimeoutDefault = 250; | |
| 132 | 134 | ||
| 133 | 135 | const { clearTimeout, setTimeout } = require('timers'); | |
@@ -1092,6 +1094,11 @@ function internalConnectMultiple(context, canceled) { | |||
| 1092 | 1094 | ||
| 1093 | 1095 | // All connections have been tried without success, destroy with error | |
| 1094 | 1096 | if (canceled || context.current === context.addresses.length) { | |
| 1097 | + if (context.errors.length === 0) { | ||
| 1098 | + self.destroy(new ERR_SOCKET_CONNECTION_TIMEOUT()); | ||
| 1099 | + return; | ||
| 1100 | + } | ||
| 1101 | + | ||
| 1095 | 1102 | self.destroy(aggregateErrors(context.errors)); | |
| 1096 | 1103 | return; | |
| 1097 | 1104 | } | |
@@ -1322,6 +1329,7 @@ function lookupAndConnect(self, options) { | |||
| 1322 | 1329 | options, | |
| 1323 | 1330 | dnsopts, | |
| 1324 | 1331 | port, | |
| 1332 | + localAddress, | ||
| 1325 | 1333 | localPort, | |
| 1326 | 1334 | autoSelectFamilyAttemptTimeout, | |
| 1327 | 1335 | ); | |
@@ -1364,7 +1372,9 @@ function lookupAndConnect(self, options) { | |||
| 1364 | 1372 | }); | |
| 1365 | 1373 | } | |
| 1366 | 1374 | ||
| 1367 | - function lookupAndConnectMultiple(self, async_id_symbol, lookup, host, options, dnsopts, port, localPort, timeout) { | ||
| 1375 | + function lookupAndConnectMultiple( | ||
| 1376 | + self, async_id_symbol, lookup, host, options, dnsopts, port, localAddress, localPort, timeout, | ||
| 1377 | + ) { | ||
| 1368 | 1378 | defaultTriggerAsyncIdScope(self[async_id_symbol], function emitLookup() { | |
| 1369 | 1379 | lookup(host, dnsopts, function emitLookup(err, addresses) { | |
| 1370 | 1380 | // It's possible we were destroyed while looking this up. | |
@@ -1385,6 +1395,7 @@ function lookupAndConnectMultiple(self, async_id_symbol, lookup, host, options, | |||
| 1385 | 1395 | // Filter addresses by only keeping the one which are either IPv4 or IPV6. | |
| 1386 | 1396 | // The first valid address determines which group has preference on the | |
| 1387 | 1397 | // alternate family sorting which happens later. | |
| 1398 | + const validAddresses = [[], []]; | ||
| 1388 | 1399 | const validIps = [[], []]; | |
| 1389 | 1400 | let destinations; | |
| 1390 | 1401 | for (let i = 0, l = addresses.length; i < l; i++) { | |
@@ -1397,12 +1408,19 @@ function lookupAndConnectMultiple(self, async_id_symbol, lookup, host, options, | |||
| 1397 | 1408 | destinations = addressType === 6 ? { 6: 0, 4: 1 } : { 4: 0, 6: 1 }; | |
| 1398 | 1409 | } | |
| 1399 | 1410 | ||
| 1400 | - ArrayPrototypePush(validIps[destinations[addressType]], address); | ||
| 1411 | + const destination = destinations[addressType]; | ||
| 1412 | + | ||
| 1413 | + // Only try an address once | ||
| 1414 | + if (!ArrayPrototypeIncludes(validIps[destination], ip)) { | ||
| 1415 | + ArrayPrototypePush(validAddresses[destination], address); | ||
| 1416 | + ArrayPrototypePush(validIps[destination], ip); | ||
| 1417 | + } | ||
| 1401 | 1418 | } | |
| 1402 | 1419 | } | |
| 1403 | 1420 | ||
| 1421 | + | ||
| 1404 | 1422 | // When no AAAA or A records are available, fail on the first one | |
| 1405 | - if (!validIps[0].length && !validIps[1].length) { | ||
| 1423 | + if (!validAddresses[0].length && !validAddresses[1].length) { | ||
| 1406 | 1424 | const { address: firstIp, family: firstAddressType } = addresses[0]; | |
| 1407 | 1425 | ||
| 1408 | 1426 | if (!isIP(firstIp)) { | |
@@ -1420,16 +1438,36 @@ function lookupAndConnectMultiple(self, async_id_symbol, lookup, host, options, | |||
| 1420 | 1438 | ||
| 1421 | 1439 | // Sort addresses alternating families | |
| 1422 | 1440 | const toAttempt = []; | |
| 1423 | - for (let i = 0, l = MathMax(validIps[0].length, validIps[1].length); i < l; i++) { | ||
| 1424 | - if (i in validIps[0]) { | ||
| 1425 | - ArrayPrototypePush(toAttempt, validIps[0][i]); | ||
| 1441 | + for (let i = 0, l = MathMax(validAddresses[0].length, validAddresses[1].length); i < l; i++) { | ||
| 1442 | + if (i in validAddresses[0]) { | ||
| 1443 | + ArrayPrototypePush(toAttempt, validAddresses[0][i]); | ||
| 1426 | 1444 | } | |
| 1427 | - if (i in validIps[1]) { | ||
| 1428 | - ArrayPrototypePush(toAttempt, validIps[1][i]); | ||
| 1445 | + if (i in validAddresses[1]) { | ||
| 1446 | + ArrayPrototypePush(toAttempt, validAddresses[1][i]); | ||
| 1429 | 1447 | } | |
| 1430 | 1448 | } | |
| 1431 | 1449 | ||
| 1450 | + if (toAttempt.length === 1) { | ||
| 1451 | + debug('connect/multiple: only one address found, switching back to single connection'); | ||
| 1452 | + const { address: ip, family: addressType } = toAttempt[0]; | ||
| 1453 | + | ||
| 1454 | + self._unrefTimer(); | ||
| 1455 | + defaultTriggerAsyncIdScope( | ||
| 1456 | + self[async_id_symbol], | ||
| 1457 | + internalConnect, | ||
| 1458 | + self, | ||
| 1459 | + ip, | ||
| 1460 | + port, | ||
| 1461 | + addressType, | ||
| 1462 | + localAddress, | ||
| 1463 | + localPort, | ||
| 1464 | + ); | ||
| 1465 | + | ||
| 1466 | + return; | ||
| 1467 | + } | ||
| 1468 | + | ||
| 1432 | 1469 | self.autoSelectFamilyAttemptedAddresses = []; | |
| 1470 | + debug('connect/multiple: will try the following addresses', toAttempt); | ||
| 1433 | 1471 | ||
| 1434 | 1472 | const context = { | |
| 1435 | 1473 | socket: self, | |
@@ -1543,6 +1581,13 @@ function afterConnect(status, handle, req, readable, writable) { | |||
| 1543 | 1581 | } | |
| 1544 | 1582 | ||
| 1545 | 1583 | function afterConnectMultiple(context, status, handle, req, readable, writable) { | |
| 1584 | + // One of the connection has completed and correctly dispatched but after timeout, ignore this one | ||
| 1585 | + if (context[kTimeoutTriggered]) { | ||
| 1586 | + debug('connect/multiple: ignoring successful but timedout connection to %s:%s', req.address, req.port); | ||
| 1587 | + handle.close(); | ||
| 1588 | + return; | ||
| 1589 | + } | ||
| 1590 | + | ||
| 1546 | 1591 | const self = context.socket; | |
| 1547 | 1592 | ||
| 1548 | 1593 | // Make sure another connection is not spawned | |
@@ -1571,13 +1616,6 @@ function afterConnectMultiple(context, status, handle, req, readable, writable) | |||
| 1571 | 1616 | return; | |
| 1572 | 1617 | } | |
| 1573 | 1618 | ||
| 1574 | - // One of the connection has completed and correctly dispatched but after timeout, ignore this one | ||
| 1575 | - if (context[kTimeoutTriggered]) { | ||
| 1576 | - debug('connect/multiple: ignoring successful but timedout connection to %s:%s', req.address, req.port); | ||
| 1577 | - handle.close(); | ||
| 1578 | - return; | ||
| 1579 | - } | ||
| 1580 | - | ||
| 1581 | 1619 | if (context.current > 1 && self[kReinitializeHandle]) { | |
| 1582 | 1620 | self[kReinitializeHandle](handle); | |
| 1583 | 1621 | handle = self._handle; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -358,10 +358,13 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() { | |||
| 358 | 358 | "returned)", | |
| 359 | 359 | &EnvironmentOptions::dns_result_order, | |
| 360 | 360 | kAllowedInEnvvar); | |
| 361 | - AddOption("--enable-network-family-autoselection", | ||
| 362 | - "Enable network address family autodetection algorithm", | ||
| 363 | - &EnvironmentOptions::enable_network_family_autoselection, | ||
| 364 | - kAllowedInEnvvar); | ||
| 361 | + AddOption("--network-family-autoselection", | ||
| 362 | + "Disable network address family autodetection algorithm", | ||
| 363 | + &EnvironmentOptions::network_family_autoselection, | ||
| 364 | + kAllowedInEnvvar, | ||
| 365 | + true); | ||
| 366 | + AddAlias("--enable-network-family-autoselection", | ||
| 367 | + "--network-family-autoselection"); | ||
| 365 | 368 | AddOption("--enable-source-maps", | |
| 366 | 369 | "Source Map V3 support for stack traces", | |
| 367 | 370 | &EnvironmentOptions::enable_source_maps, | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -132,7 +132,7 @@ class EnvironmentOptions : public Options { | |||
| 132 | 132 | bool frozen_intrinsics = false; | |
| 133 | 133 | int64_t heap_snapshot_near_heap_limit = 0; | |
| 134 | 134 | std::string heap_snapshot_signal; | |
| 135 | - bool enable_network_family_autoselection = false; | ||
| 135 | + bool network_family_autoselection = true; | ||
| 136 | 136 | uint64_t max_http_header_size = 16 * 1024; | |
| 137 | 137 | bool deprecation = true; | |
| 138 | 138 | bool force_async_hooks_checks = true; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -26,6 +26,7 @@ const process = global.process; // Some tests tamper with the process global. | |||
| 26 | 26 | const assert = require('assert'); | |
| 27 | 27 | const { exec, execSync, spawn, spawnSync } = require('child_process'); | |
| 28 | 28 | const fs = require('fs'); | |
| 29 | + const net = require('net'); | ||
| 29 | 30 | // Do not require 'os' until needed so that test-os-checked-function can | |
| 30 | 31 | // monkey patch it. If 'os' is required here, that test will fail. | |
| 31 | 32 | const path = require('path'); | |
@@ -137,6 +138,14 @@ const isPi = (() => { | |||
| 137 | 138 | ||
| 138 | 139 | const isDumbTerminal = process.env.TERM === 'dumb'; | |
| 139 | 140 | ||
| 141 | + // When using high concurrency or in the CI we need much more time for each connection attempt | ||
| 142 | + const defaultAutoSelectFamilyAttemptTimeout = platformTimeout(2500); | ||
| 143 | + // Since this is also used by tools outside of the test suite, | ||
| 144 | + // make sure setDefaultAutoSelectFamilyAttemptTimeout | ||
| 145 | + if (typeof net.setDefaultAutoSelectFamilyAttemptTimeout === 'function') { | ||
| 146 | + net.setDefaultAutoSelectFamilyAttemptTimeout(platformTimeout(defaultAutoSelectFamilyAttemptTimeout)); | ||
| 147 | + } | ||
| 148 | + | ||
| 140 | 149 | const buildType = process.config.target_defaults ? | |
| 141 | 150 | process.config.target_defaults.default_configuration : | |
| 142 | 151 | 'Release'; | |
@@ -886,6 +895,7 @@ const common = { | |||
| 886 | 895 | canCreateSymLink, | |
| 887 | 896 | childShouldThrowAndAbort, | |
| 888 | 897 | createZeroFilledFile, | |
| 898 | + defaultAutoSelectFamilyAttemptTimeout, | ||
| 889 | 899 | expectsError, | |
| 890 | 900 | expectWarning, | |
| 891 | 901 | gcUntil, | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -7,12 +7,8 @@ if (!common.hasCrypto) { | |||
| 7 | 7 | common.skip('missing crypto'); | |
| 8 | 8 | } | |
| 9 | 9 | ||
| 10 | - const { setDefaultAutoSelectFamilyAttemptTimeout } = require('net'); | ||
| 11 | 10 | const { connect } = require('tls'); | |
| 12 | 11 | ||
| 13 | - // Some of the windows machines in the CI need more time to establish connection | ||
| 14 | - setDefaultAutoSelectFamilyAttemptTimeout(common.platformTimeout(common.isWindows ? 1500 : 250)); | ||
| 15 | - | ||
| 16 | 12 | // Test that TLS connecting works without autoSelectFamily | |
| 17 | 13 | { | |
| 18 | 14 | const socket = connect({ | |
| Back | FazBrowse Home | New Git URL |
0 commit comments