net: signal localAddress bind failure in connect
authorBrian Schroeder <bts@gmail.com>
Thu, 3 May 2012 20:27:06 +0000 (13:27 -0700)
committerBen Noordhuis <info@bnoordhuis.nl>
Fri, 4 May 2012 23:30:32 +0000 (01:30 +0200)
lib/net.js
test/simple/test-http-localaddress-bind-error.js [new file with mode: 0644]
test/simple/test-https-localaddress-bind-error.js [new file with mode: 0644]

index bbd0c1f..3acaf8a 100644 (file)
@@ -565,21 +565,26 @@ function connect(self, address, port, addressType, localAddress) {
 
   assert.ok(self._connecting);
 
+  if (localAddress) {
+    var r;
+    if (addressType == 6) {
+      r = self._handle.bind6(localAddress);
+    } else {
+      r = self._handle.bind(localAddress);
+    }
+
+    if (r) {
+      self._destroy(errnoException(errno, 'bind'));
+      return;
+    }
+  }
+
   var connectReq;
   if (addressType == 6) {
-    if (localAddress) {
-      self._handle.bind6(localAddress);
-    }
     connectReq = self._handle.connect6(address, port);
   } else if (addressType == 4) {
-    if (localAddress) {
-      self._handle.bind(localAddress);
-    }
     connectReq = self._handle.connect(address, port);
   } else {
-    if (localAddress) {
-      self._handle.bind(localAddress);
-    }
     connectReq = self._handle.connect(address, afterConnect);
   }
 
diff --git a/test/simple/test-http-localaddress-bind-error.js b/test/simple/test-http-localaddress-bind-error.js
new file mode 100644 (file)
index 0000000..0f9cdbb
--- /dev/null
@@ -0,0 +1,56 @@
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+var common = require('../common');
+var assert = require('assert');
+var http = require('http');
+
+var invalidLocalAddress = '1.2.3.4';
+var gotError = false;
+
+var server = http.createServer(function(req, res) {
+  console.log("Connect from: " + req.connection.remoteAddress);
+
+  req.on('end', function() {
+    res.writeHead(200, { 'Content-Type': 'text/plain' });
+    res.end('You are from: ' + req.connection.remoteAddress);
+  });
+});
+
+server.listen(common.PORT, "127.0.0.1", function() {
+  var req = http.request({
+    host: 'localhost',
+    port: common.PORT,
+    path: '/',
+    method: 'GET',
+    localAddress: invalidLocalAddress
+  }, function(res) {
+    assert.fail('unexpectedly got response from server');
+  }).on('error', function(e) {
+    console.log('client got error: ' + e.message);
+    gotError = true;
+    server.close();
+  }).end();
+});
+
+process.on('exit', function() {
+  assert.ok(gotError);
+});
diff --git a/test/simple/test-https-localaddress-bind-error.js b/test/simple/test-https-localaddress-bind-error.js
new file mode 100644 (file)
index 0000000..157df05
--- /dev/null
@@ -0,0 +1,62 @@
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+var common = require('../common');
+var assert = require('assert');
+var https = require('https');
+var fs = require('fs');
+
+var options = {
+  key: fs.readFileSync(common.fixturesDir + '/keys/agent1-key.pem'),
+  cert: fs.readFileSync(common.fixturesDir + '/keys/agent1-cert.pem')
+};
+
+var invalidLocalAddress = '1.2.3.4';
+var gotError = false;
+
+var server = https.createServer(options, function(req, res) {
+  console.log("Connect from: " + req.connection.remoteAddress);
+
+  req.on('end', function() {
+    res.writeHead(200, { 'Content-Type': 'text/plain' });
+    res.end('You are from: ' + req.connection.remoteAddress);
+  });
+});
+
+server.listen(common.PORT, "127.0.0.1", function() {
+  var req = https.request({
+    host: 'localhost',
+    port: common.PORT,
+    path: '/',
+    method: 'GET',
+    localAddress: invalidLocalAddress
+  }, function(res) {
+    assert.fail('unexpectedly got response from server');
+  }).on('error', function(e) {
+    console.log('client got error: ' + e.message);
+    gotError = true;
+    server.close();
+  }).end();
+});
+
+process.on('exit', function() {
+  assert.ok(gotError);
+});