Description
- Version: master
- Platform: AIX, Windows
- Subsystem: cluster, test
I have been debuging some of the test failures in AIX and Windows with respect to client-server connectivity on ipv6 addresses. Here is the summary:
Code:
var net = require('net');
var server = net.createServer(function() {
});
server.listen(0, process.argv[2], function(a, b) {
console.log(server.address());
net.connect(server.address().port, process.argv[3], function() {
console.log('connected');
process.exit(0);
});
});
Linux and Mac:
# ./node i.js // no hostname for listen, and connect. Default is unspecified address [expected]
{ address: '::', family: 'IPv6', port: 48168 }
connected
# ./node i.js :: // unspecified address for listen, no hostname for connect. Default is unspecified address [expected]
{ address: '::', family: 'IPv6', port: 46366 }
connected
# ./node i.js ::1 // loopback address for listen, no hostname for connect. Server listens at loopback [expected]
{ address: '::1', family: 'IPv6', port: 57099 }
connected
# ./node i.js :: :: // unspecified address for listen and connect. Default is unspecified address [expected]
{ address: '::', family: 'IPv6', port: 48019 }
connected
# ./node i.js ::1 :: // Loopback for listen, unspecified for connect. [Unexpected, but good]
{ address: '::1', family: 'IPv6', port: 52945 }
connected
# ./node i.js ::1 ::1 // Loopback for both listen and connect. Good and expected.
{ address: '::1', family: 'IPv6', port: 58486 }
connected
# ./node i.js :: ::1 // Unspecified for listen and loopback for connect. Good and expected.
{ address: '::', family: 'IPv6', port: 36496 }
connected
Bottom line of Linux and Mac story is that the unspecified and loopback addresses are interchangeably used, and every combination works.
Windows
>node s.js
{ address: '::', family: 'IPv6', port: 53401 }
connected
>node s.js ::
{ address: '::', family: 'IPv6', port: 53403 }
connected
>node s.js ::1
{ address: '::1', family: 'IPv6', port: 53405 }
events.js:160
throw er; // Unhandled 'error' event
^
Error: connect ECONNREFUSED 127.0.0.1:53405
at Object.exports._errnoException (util.js:1008:11)
at exports._exceptionWithHostPort (util.js:1031:20)
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1080:14)
>node s.js :: ::
{ address: '::', family: 'IPv6', port: 53408 }
events.js:160
throw er; // Unhandled 'error' event
^
Error: connect EADDRNOTAVAIL :::53408
at Object.exports._errnoException (util.js:1008:11)
at exports._exceptionWithHostPort (util.js:1031:20)
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1080:14)
>node s.js ::1 ::
{ address: '::1', family: 'IPv6', port: 53410 }
events.js:160
throw er; // Unhandled 'error' event
^
Error: connect EADDRNOTAVAIL :::53410
at Object.exports._errnoException (util.js:1008:11)
at exports._exceptionWithHostPort (util.js:1031:20)
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1080:14)
>node s.js :: ::1
{ address: '::', family: 'IPv6', port: 53413 }
connected
>node s.js ::1 ::1
{ address: '::1', family: 'IPv6', port: 53415 }
connected
Bottom line of Windows story is that the unspecified and loopback addresses are strictly disjoint.
AIX
# ./node i.js
{ address: '::', family: 'IPv6', port: 50538 }
connected
# ./node i.js ::
{ address: '::', family: 'IPv6', port: 50540 }
connected
# ./node i.js ::1
{ address: '::1', family: 'IPv6', port: 50542 }
events.js:160
throw er; // Unhandled 'error' event
^
Error: connect ECONNREFUSED 127.0.0.1:50542
at Object.exports._errnoException (util.js:1007:11)
at exports._exceptionWithHostPort (util.js:1030:20)
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1081:14)
# ./node i.js :: ::
{ address: '::', family: 'IPv6', port: 50544 }
connected
# ./node i.js ::1 ::
{ address: '::1', family: 'IPv6', port: 50546 }
events.js:160
throw er; // Unhandled 'error' event
^
Error: connect ECONNREFUSED :::50546
at Object.exports._errnoException (util.js:1007:11)
at exports._exceptionWithHostPort (util.js:1030:20)
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1081:14)
# ./node i.js :: ::1
{ address: '::', family: 'IPv6', port: 50548 }
connected
# ./node i.js ::1 ::1
{ address: '::1', family: 'IPv6', port: 50550 }
connected
#
Bottom line of AIX story is thar socket listening at unspecified (any address) is able to get connected from a client specifying loopback address, but vice versa is false.
This behavior is in alignment with the IPv4 behavior with 0.0.0.0 and 127.0.0.1 respectively, in these platforms.
The impact of this bejavior difference is that few test cases fail in some platforms (gc/test-net-timeout.js in windows #7291 and parallel/test-cluster-disconnect-handles in AIX #7563 etc.) but these may be just indications of future larger problems in real applications.
Among all these deviations and in the absence of a clear specification about the connectivity, my inference is that the AIX behavior seem correct, but would like to hear from others.