| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -135,7 +135,6 @@ let autoSelectFamilyDefault = getOptionValue('--enable-network-family-autoselect | |||
| 135 | 135 | ||
| 136 | 136 | const { clearTimeout, setTimeout } = require('timers'); | |
| 137 | 137 | const { kTimeout } = require('internal/timers'); | |
| 138 | - const kTimeoutTriggered = Symbol('kTimeoutTriggered'); | ||
| 139 | 138 | ||
| 140 | 139 | const DEFAULT_IPV4_ADDR = '0.0.0.0'; | |
| 141 | 140 | const DEFAULT_IPV6_ADDR = '::'; | |
@@ -1093,9 +1092,11 @@ function internalConnectMultiple(context) { | |||
| 1093 | 1092 | return; | |
| 1094 | 1093 | } | |
| 1095 | 1094 | ||
| 1095 | + | ||
| 1096 | + const current = context.current++; | ||
| 1097 | + const handle = current === 0 ? self._handle : new TCP(TCPConstants.SOCKET); | ||
| 1096 | 1098 | const { localPort, port, flags } = context; | |
| 1097 | - const { address, family: addressType } = context.addresses[context.current++]; | ||
| 1098 | - const handle = new TCP(TCPConstants.SOCKET); | ||
| 1099 | + const { address, family: addressType } = context.addresses[current]; | ||
| 1099 | 1100 | let localAddress; | |
| 1100 | 1101 | let err; | |
| 1101 | 1102 | ||
@@ -1120,7 +1121,7 @@ function internalConnectMultiple(context) { | |||
| 1120 | 1121 | } | |
| 1121 | 1122 | ||
| 1122 | 1123 | const req = new TCPConnectWrap(); | |
| 1123 | - req.oncomplete = FunctionPrototypeBind(afterConnectMultiple, undefined, context); | ||
| 1124 | + req.oncomplete = FunctionPrototypeBind(afterConnectMultiple, undefined, context, current); | ||
| 1124 | 1125 | req.address = address; | |
| 1125 | 1126 | req.port = port; | |
| 1126 | 1127 | req.localAddress = localAddress; | |
@@ -1147,8 +1148,12 @@ function internalConnectMultiple(context) { | |||
| 1147 | 1148 | return; | |
| 1148 | 1149 | } | |
| 1149 | 1150 | ||
| 1150 | - // If the attempt has not returned an error, start the connection timer | ||
| 1151 | - context[kTimeout] = setTimeout(internalConnectMultipleTimeout, context.timeout, context, req); | ||
| 1151 | + if (current < context.addresses.length - 1) { | ||
| 1152 | + debug('connect/multiple: setting the attempt timeout to %d ms', context.timeout); | ||
| 1153 | + | ||
| 1154 | + // If the attempt has not returned an error, start the connection timer | ||
| 1155 | + context[kTimeout] = setTimeout(internalConnectMultipleTimeout, context.timeout, context, req, handle); | ||
| 1156 | + } | ||
| 1152 | 1157 | } | |
| 1153 | 1158 | ||
| 1154 | 1159 | Socket.prototype.connect = function(...args) { | |
@@ -1419,7 +1424,6 @@ function lookupAndConnectMultiple(self, async_id_symbol, lookup, host, options, | |||
| 1419 | 1424 | localPort, | |
| 1420 | 1425 | timeout, | |
| 1421 | 1426 | [kTimeout]: null, | |
| 1422 | - [kTimeoutTriggered]: false, | ||
| 1423 | 1427 | errors: [], | |
| 1424 | 1428 | }; | |
| 1425 | 1429 | ||
@@ -1522,12 +1526,20 @@ function afterConnect(status, handle, req, readable, writable) { | |||
| 1522 | 1526 | } | |
| 1523 | 1527 | } | |
| 1524 | 1528 | ||
| 1525 | - function afterConnectMultiple(context, status, handle, req, readable, writable) { | ||
| 1526 | - const self = context.socket; | ||
| 1527 | - | ||
| 1529 | + function afterConnectMultiple(context, current, status, handle, req, readable, writable) { | ||
| 1528 | 1530 | // Make sure another connection is not spawned | |
| 1529 | 1531 | clearTimeout(context[kTimeout]); | |
| 1530 | 1532 | ||
| 1533 | + // One of the connection has completed and correctly dispatched but after timeout, ignore this one | ||
| 1534 | + if (status === 0 && current !== context.current - 1) { | ||
| 1535 | + debug('connect/multiple: ignoring successful but timedout connection to %s:%s', req.address, req.port); | ||
| 1536 | + handle.close(); | ||
| 1537 | + return; | ||
| 1538 | + } | ||
| 1539 | + | ||
| 1540 | + const self = context.socket; | ||
| 1541 | + | ||
| 1542 | + | ||
| 1531 | 1543 | // Some error occurred, add to the list of exceptions | |
| 1532 | 1544 | if (status !== 0) { | |
| 1533 | 1545 | let details; | |
@@ -1552,7 +1564,7 @@ function afterConnectMultiple(context, status, handle, req, readable, writable) | |||
| 1552 | 1564 | } | |
| 1553 | 1565 | ||
| 1554 | 1566 | // One of the connection has completed and correctly dispatched but after timeout, ignore this one | |
| 1555 | - if (context[kTimeoutTriggered]) { | ||
| 1567 | + if (status === 0 && current !== context.current - 1) { | ||
| 1556 | 1568 | debug('connect/multiple: ignoring successful but timedout connection to %s:%s', req.address, req.port); | |
| 1557 | 1569 | handle.close(); | |
| 1558 | 1570 | return; | |
@@ -1578,8 +1590,10 @@ function afterConnectMultiple(context, status, handle, req, readable, writable) | |||
| 1578 | 1590 | afterConnect(status, handle, req, readable, writable); | |
| 1579 | 1591 | } | |
| 1580 | 1592 | ||
| 1581 | - function internalConnectMultipleTimeout(context, req) { | ||
| 1582 | - context[kTimeoutTriggered] = true; | ||
| 1593 | + function internalConnectMultipleTimeout(context, req, handle) { | ||
| 1594 | + debug('connect/multiple: connection to %s:%s timed out', req.address, req.port); | ||
| 1595 | + req.oncomplete = undefined; | ||
| 1596 | + handle.close(); | ||
| 1583 | 1597 | internalConnectMultiple(context); | |
| 1584 | 1598 | } | |
| 1585 | 1599 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -36,7 +36,15 @@ function _lookup(resolver, hostname, options, cb) { | |||
| 36 | 36 | }); | |
| 37 | 37 | } | |
| 38 | 38 | ||
| 39 | - function createDnsServer(ipv6Addr, ipv4Addr, cb) { | ||
| 39 | + function createDnsServer(ipv6Addrs, ipv4Addrs, cb) { | ||
| 40 | + if (!Array.isArray(ipv6Addrs)) { | ||
| 41 | + ipv6Addrs = [ipv6Addrs]; | ||
| 42 | + } | ||
| 43 | + | ||
| 44 | + if (!Array.isArray(ipv4Addrs)) { | ||
| 45 | + ipv4Addrs = [ipv4Addrs]; | ||
| 46 | + } | ||
| 47 | + | ||
| 40 | 48 | // Create a DNS server which replies with a AAAA and a A record for the same host | |
| 41 | 49 | const socket = dgram.createSocket('udp4'); | |
| 42 | 50 | ||
@@ -49,8 +57,8 @@ function createDnsServer(ipv6Addr, ipv4Addr, cb) { | |||
| 49 | 57 | id: parsed.id, | |
| 50 | 58 | questions: parsed.questions, | |
| 51 | 59 | answers: [ | |
| 52 | - { type: 'AAAA', address: ipv6Addr, ttl: 123, domain: 'example.org' }, | ||
| 53 | - { type: 'A', address: ipv4Addr, ttl: 123, domain: 'example.org' }, | ||
| 60 | + ...ipv6Addrs.map((address) => ({ type: 'AAAA', address, ttl: 123, domain: 'example.org' })), | ||
| 61 | + ...ipv4Addrs.map((address) => ({ type: 'A', address, ttl: 123, domain: 'example.org' })), | ||
| 54 | 62 | ] | |
| 55 | 63 | }), port, address); | |
| 56 | 64 | })); | |
@@ -106,6 +114,56 @@ function createDnsServer(ipv6Addr, ipv4Addr, cb) { | |||
| 106 | 114 | })); | |
| 107 | 115 | } | |
| 108 | 116 | ||
| 117 | + // Test that only the last successful connection is established. | ||
| 118 | + { | ||
| 119 | + createDnsServer( | ||
| 120 | + '::1', | ||
| 121 | + ['104.20.22.46', '104.20.23.46', '127.0.0.1'], | ||
| 122 | + common.mustCall(function({ dnsServer, lookup }) { | ||
| 123 | + const ipv4Server = createServer((socket) => { | ||
| 124 | + socket.on('data', common.mustCall(() => { | ||
| 125 | + socket.write('response-ipv4'); | ||
| 126 | + socket.end(); | ||
| 127 | + })); | ||
| 128 | + }); | ||
| 129 | + | ||
| 130 | + ipv4Server.listen(0, '127.0.0.1', common.mustCall(() => { | ||
| 131 | + const port = ipv4Server.address().port; | ||
| 132 | + | ||
| 133 | + const connection = createConnection({ | ||
| 134 | + host: 'example.org', | ||
| 135 | + port: port, | ||
| 136 | + lookup, | ||
| 137 | + autoSelectFamily: true, | ||
| 138 | + autoSelectFamilyAttemptTimeout, | ||
| 139 | + }); | ||
| 140 | + | ||
| 141 | + let response = ''; | ||
| 142 | + connection.setEncoding('utf-8'); | ||
| 143 | + | ||
| 144 | + connection.on('ready', common.mustCall(() => { | ||
| 145 | + assert.deepStrictEqual( | ||
| 146 | + connection.autoSelectFamilyAttemptedAddresses, | ||
| 147 | + [`::1:${port}`, `104.20.22.46:${port}`, `104.20.23.46:${port}`, `127.0.0.1:${port}`] | ||
| 148 | + ); | ||
| 149 | + })); | ||
| 150 | + | ||
| 151 | + connection.on('data', (chunk) => { | ||
| 152 | + response += chunk; | ||
| 153 | + }); | ||
| 154 | + | ||
| 155 | + connection.on('end', common.mustCall(() => { | ||
| 156 | + assert.strictEqual(response, 'response-ipv4'); | ||
| 157 | + ipv4Server.close(); | ||
| 158 | + dnsServer.close(); | ||
| 159 | + })); | ||
| 160 | + | ||
| 161 | + connection.write('request'); | ||
| 162 | + })); | ||
| 163 | + }) | ||
| 164 | + ); | ||
| 165 | + } | ||
| 166 | + | ||
| 109 | 167 | // Test that IPV4 is NOT reached if IPV6 is reachable | |
| 110 | 168 | if (common.hasIPv6) { | |
| 111 | 169 | createDnsServer('::1', '127.0.0.1', common.mustCall(function({ dnsServer, lookup }) { | |
| Back | FazBrowse Home | New Git URL |
0 commit comments