Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inconsistencies with IPv6 endpoint specification across platforms #7728

Closed
gireeshpunathil opened this issue Jul 14, 2016 · 7 comments
Closed
Labels
net Issues and PRs related to the net subsystem.

Comments

@gireeshpunathil
Copy link
Member

gireeshpunathil commented Jul 14, 2016

  • 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.

@gireeshpunathil
Copy link
Member Author

So the objective of this issue report is to see if it is possible for either:

  1. Node encapsulating these platform disparities
  2. Test cases accommodating these differences in test code

@gibfahn
Copy link
Member

gibfahn commented Jul 14, 2016

@gireeshpunathil So basically listening at unspecified (::) will default to the loopback address (localhost, which is ::1 on IPv6 or 127.0.0.1 on IPv4) on some platforms but not on others.

So node could either convert :: to localhost internally (so that listening on :: works everywhere), or we could convert all the tests to specify localhost, depending on whether that conversion should be expected.

@bnoordhuis
Copy link
Member

bnoordhuis commented Jul 14, 2016

So basically listening at unspecified (::) will default to the loopback address

@gibfahn Not quite. :: is the 'any' address. Listening on the any address makes the operating system accept incoming connections on all interfaces, including the loopback device.

Connecting to :: works on some platforms but not others and is a somewhat nonsensical thing to do. Tests that do that should be fixed to connect to the actual server address (i.e., server.address().address.)

EDIT: 'Nonsensical' is perhaps a poor choice of words. One way to think of it is as asking for a connection to any local address that is accepting connections on the selected port. That is meaningful and sensible but alas, not very portable.

@gireeshpunathil gireeshpunathil changed the title Incosistencies with IPv6 endpoint specification across platforms Inconsistencies with IPv6 endpoint specification across platforms Jul 14, 2016
@gibfahn
Copy link
Member

gibfahn commented Jul 14, 2016

@bnoordhuis Thanks a lot, I knew I was getting muddled somewhere. 😄

@mscdex mscdex added the net Issues and PRs related to the net subsystem. label Jul 14, 2016
@mhdawson
Copy link
Member

mhdawson commented Jan 3, 2017

@gireeshpunathil are we any close to the right answer on this ?

@gireeshpunathil
Copy link
Member Author

@mhdawson - this can be deemed resolved when two of the PRs:
test: Avoid usage of mixed IPV6 addresses (closed) and
test: avoid connecting to :: in test-net-timeout (open)
are resolved.
/cc @gibfahn

@gibfahn
Copy link
Member

gibfahn commented May 9, 2017

@gireeshpunathil those PRs have both landed, so I think this can be closed...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
net Issues and PRs related to the net subsystem.
Projects
None yet
Development

No branches or pull requests

5 participants