From 33a25b29a4d654f5c2a5c74725862bccb2fcccfb Mon Sep 17 00:00:00 2001 From: Ouyang Yadong Date: Sun, 21 Oct 2018 15:59:38 +0800 Subject: net,dgram: add ipv6Only option for net and dgram For TCP servers, the dual-stack support is enable by default, i.e. binding host "::" will also make "0.0.0.0" bound. This commit add ipv6Only option in `net.Server.listen()` and `dgram.createSocket()` methods which allows to disable dual-stack support. Support for cluster module is also provided in this commit. Fixes: https://github.com/nodejs/node/issues/17664 PR-URL: https://github.com/nodejs/node/pull/23798 Reviewed-By: Ben Noordhuis Reviewed-By: James M Snell --- lib/net.js | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) (limited to 'lib/net.js') diff --git a/lib/net.js b/lib/net.js index 01cfed98e8..25767b2574 100644 --- a/lib/net.js +++ b/lib/net.js @@ -97,6 +97,10 @@ const { function noop() {} +function getFlags(ipv6Only) { + return ipv6Only === true ? TCPConstants.UV_TCP_IPV6ONLY : 0; +} + function createHandle(fd, is_server) { validateInt32(fd, 'fd', 0); const type = TTYWrap.guessHandleType(fd); @@ -798,7 +802,7 @@ function checkBindError(err, port, handle) { function internalConnect( - self, address, port, addressType, localAddress, localPort) { + self, address, port, addressType, localAddress, localPort, flags) { // TODO return promise from Socket.prototype.connect which // wraps _connectReq. @@ -812,7 +816,7 @@ function internalConnect( err = self._handle.bind(localAddress, localPort); } else { // addressType === 6 localAddress = localAddress || '::'; - err = self._handle.bind6(localAddress, localPort); + err = self._handle.bind6(localAddress, localPort, flags); } debug('binding to localAddress: %s and localPort: %d (addressType: %d)', localAddress, localPort, addressType); @@ -1148,7 +1152,7 @@ util.inherits(Server, EventEmitter); function toNumber(x) { return (x = Number(x)) >= 0 ? x : false; } // Returns handle if it can be created, or error code if it can't -function createServerHandle(address, port, addressType, fd) { +function createServerHandle(address, port, addressType, fd, flags) { var err = 0; // assign handle in listen, and clean up if bind or listen fails var handle; @@ -1187,14 +1191,14 @@ function createServerHandle(address, port, addressType, fd) { debug('bind to', address || 'any'); if (!address) { // Try binding to ipv6 first - err = handle.bind6('::', port); + err = handle.bind6('::', port, flags); if (err) { handle.close(); // Fallback to ipv4 return createServerHandle('0.0.0.0', port); } } else if (addressType === 6) { - err = handle.bind6(address, port); + err = handle.bind6(address, port, flags); } else { err = handle.bind(address, port); } @@ -1208,7 +1212,7 @@ function createServerHandle(address, port, addressType, fd) { return handle; } -function setupListenHandle(address, port, addressType, backlog, fd) { +function setupListenHandle(address, port, addressType, backlog, fd, flags) { debug('setupListenHandle', address, port, addressType, backlog, fd); // If there is not yet a handle, we need to create one and bind. @@ -1222,7 +1226,7 @@ function setupListenHandle(address, port, addressType, backlog, fd) { // Try to bind to the unspecified IPv6 address, see if IPv6 is available if (!address && typeof fd !== 'number') { - rval = createServerHandle('::', port, 6, fd); + rval = createServerHandle('::', port, 6, fd, flags); if (typeof rval === 'number') { rval = null; @@ -1235,7 +1239,7 @@ function setupListenHandle(address, port, addressType, backlog, fd) { } if (rval === null) - rval = createServerHandle(address, port, addressType, fd); + rval = createServerHandle(address, port, addressType, fd, flags); if (typeof rval === 'number') { var error = uvExceptionWithHostPort(rval, 'listen', address, port); @@ -1294,7 +1298,7 @@ function emitListeningNT(self) { function listenInCluster(server, address, port, addressType, - backlog, fd, exclusive) { + backlog, fd, exclusive, flags) { exclusive = !!exclusive; if (cluster === undefined) cluster = require('cluster'); @@ -1303,7 +1307,7 @@ function listenInCluster(server, address, port, addressType, // Will create a new handle // _listen2 sets up the listened handle, it is still named like this // to avoid breaking code that wraps this method - server._listen2(address, port, addressType, backlog, fd); + server._listen2(address, port, addressType, backlog, fd, flags); return; } @@ -1312,7 +1316,7 @@ function listenInCluster(server, address, port, addressType, port: port, addressType: addressType, fd: fd, - flags: 0 + flags, }; // Get the master's server handle, and listen on it @@ -1330,7 +1334,7 @@ function listenInCluster(server, address, port, addressType, server._handle = handle; // _listen2 sets up the listened handle, it is still named like this // to avoid breaking code that wraps this method - server._listen2(address, port, addressType, backlog, fd); + server._listen2(address, port, addressType, backlog, fd, flags); } } @@ -1353,6 +1357,7 @@ Server.prototype.listen = function(...args) { toNumber(args.length > 2 && args[2]); // (port, host, backlog) options = options._handle || options.handle || options; + const flags = getFlags(options.ipv6Only); // (handle[, backlog][, cb]) where handle is an object with a handle if (options instanceof TCP) { this._handle = options; @@ -1387,7 +1392,7 @@ Server.prototype.listen = function(...args) { // start TCP server listening on host:port if (options.host) { lookupAndListen(this, options.port | 0, options.host, backlog, - options.exclusive); + options.exclusive, flags); } else { // Undefined host, listens on unspecified address // Default addressType 4 will be used to search for master server listenInCluster(this, null, options.port | 0, 4, @@ -1434,7 +1439,7 @@ Server.prototype.listen = function(...args) { throw new ERR_INVALID_OPT_VALUE('options', util.inspect(options)); }; -function lookupAndListen(self, port, address, backlog, exclusive) { +function lookupAndListen(self, port, address, backlog, exclusive, flags) { if (dns === undefined) dns = require('dns'); dns.lookup(address, function doListen(err, ip, addressType) { if (err) { @@ -1442,7 +1447,7 @@ function lookupAndListen(self, port, address, backlog, exclusive) { } else { addressType = ip ? addressType : 4; listenInCluster(self, ip, port, addressType, - backlog, undefined, exclusive); + backlog, undefined, exclusive, flags); } }); } -- cgit v1.2.3