net: Ensure consistent binding to IPV6 if address is absent
authorRaymond Feng <raymond@strongloop.com>
Tue, 27 May 2014 22:26:13 +0000 (15:26 -0700)
committerFedor Indutny <fedor@indutny.com>
Wed, 28 May 2014 22:05:19 +0000 (02:05 +0400)
See https://github.com/joyent/node/issues/7675
net.server.listen() behaves inconsistently depending on whether the port
number is provided.

1. port === 0 && host == '' (i.e. false-y), node creates an AF_INET
socket but does not call bind().

2. port > 0 && host == '', node creates an AF_INET6 socket and calls
bind().

The fix makes 1 consistent with 2.

Signed-off-by: Fedor Indutny <fedor@indutny.com>
lib/net.js
test/simple/test-net-server-address.js

index 3b4f7da07865f783c4dd5cba5ce5c1c5e6d619b1..1af61f3bd919e89eb11580fcdbf12749c086dc3a 100644 (file)
@@ -1051,6 +1051,7 @@ var createServerHandle = exports._createServerHandle =
   // assign handle in listen, and clean up if bind or listen fails
   var handle;
 
+  var isTCP = false;
   if (util.isNumber(fd) && fd >= 0) {
     try {
       handle = createHandle(fd);
@@ -1074,9 +1075,10 @@ var createServerHandle = exports._createServerHandle =
     }
   } else {
     handle = createTCP();
+    isTCP = true;
   }
 
-  if (address || port) {
+  if (address || port || isTCP) {
     debug('bind to ' + (address || 'anycast'));
     if (!address) {
       // Try binding to ipv6 first
index a9f92c448be24766f9d13e0bb9d29becabb3a286..671305f6621ee715613b2976a099534cbd340ee5 100644 (file)
@@ -56,3 +56,65 @@ server_ipv6.listen(common.PORT, localhost_ipv6, function() {
   assert.strictEqual(address_ipv6.family, family_ipv6);
   server_ipv6.close();
 });
+
+// Test without hostname or ip
+var anycast_ipv6 = '::';
+var server1 = net.createServer();
+
+server1.on('error', function(e) {
+  console.log('Error on ip socket: ' + e.toString());
+});
+
+// Specify the port number
+server1.listen(common.PORT, function() {
+  var address = server1.address();
+  assert.strictEqual(address.address, anycast_ipv6);
+  assert.strictEqual(address.port, common.PORT);
+  assert.strictEqual(address.family, family_ipv6);
+  server1.close();
+});
+
+// Test without hostname or port
+var server2 = net.createServer();
+
+server2.on('error', function (e) {
+  console.log('Error on ip socket: ' + e.toString());
+});
+
+// Don't specify the port number
+server2.listen(function () {
+  var address = server2.address();
+  assert.strictEqual(address.address, anycast_ipv6);
+  assert.strictEqual(address.family, family_ipv6);
+  server2.close();
+});
+
+// Test without hostname, but with a false-y port
+var server3 = net.createServer();
+
+server3.on('error', function (e) {
+  console.log('Error on ip socket: ' + e.toString());
+});
+
+// Specify a false-y port number
+server3.listen(0, function () {
+  var address = server3.address();
+  assert.strictEqual(address.address, anycast_ipv6);
+  assert.strictEqual(address.family, family_ipv6);
+  server3.close();
+});
+
+// Test without hostname, but with port -1
+var server4 = net.createServer();
+
+server4.on('error', function (e) {
+  console.log('Error on ip socket: ' + e.toString());
+});
+
+// Specify -1 as port number
+server4.listen(-1, function () {
+  var address = server4.address();
+  assert.strictEqual(address.address, anycast_ipv6);
+  assert.strictEqual(address.family, family_ipv6);
+  server4.close();
+});