Browse Source

net: add localPort to connect options

Expose localPort for binding to a specific port for outbound
connections.

If localAddress is not specified '0.0.0.0' is used for ip4 and '::'
for ip6 connections.

Fixes #7092
v0.11.12-release
Timothy J Fontaine 11 years ago
committed by Fedor Indutny
parent
commit
59baab2776
  1. 2
      doc/api/net.markdown
  2. 50
      lib/net.js
  3. 61
      test/simple/test-net-localerror.js
  4. 41
      test/simple/test-net-localport.js

2
doc/api/net.markdown

@ -64,6 +64,8 @@ For TCP sockets, `options` argument should be an object which specifies:
- `localAddress`: Local interface to bind to for network connections. - `localAddress`: Local interface to bind to for network connections.
- `localPort`: Local port to bind to for network connections.
- `family` : Version of IP stack. Defaults to `4`. - `family` : Version of IP stack. Defaults to `4`.
For local domain sockets, `options` argument should be an object which For local domain sockets, `options` argument should be an object which

50
lib/net.js

@ -776,20 +776,51 @@ function afterWrite(status, handle, req, err) {
} }
function connect(self, address, port, addressType, localAddress) { function connect(self, address, port, addressType, localAddress, localPort) {
// TODO return promise from Socket.prototype.connect which // TODO return promise from Socket.prototype.connect which
// wraps _connectReq. // wraps _connectReq.
assert.ok(self._connecting); assert.ok(self._connecting);
var err; var err;
if (localAddress) { if (localAddress || localPort) {
if (addressType === 6) { if (localAddress && !exports.isIP(localAddress))
err = self._handle.bind6(localAddress); err = new TypeError(
} else { 'localAddress should be a valid IP: ' + localAddress);
err = self._handle.bind(localAddress);
if (localPort && !util.isNumber(localPort))
err = new TypeError('localPort should be a number: ' + localPort);
var bind;
switch (addressType) {
case 4:
if (!localAddress)
localAddress = '0.0.0.0';
bind = self._handle.bind;
break;
case 6:
if (!localAddress)
localAddress = '::';
bind = self._handle.bind6;
break;
default:
err = new TypeError('Invalid addressType: ' + addressType);
break;
} }
if (err) {
self._destroy(err);
return;
}
debug('binding to localAddress: %s and localPort: %d',
localAddress,
localPort);
bind = bind.bind(self._handle);
err = bind(localAddress, localPort);
if (err) { if (err) {
self._destroy(errnoException(err, 'bind')); self._destroy(errnoException(err, 'bind'));
return; return;
@ -897,7 +928,12 @@ Socket.prototype.connect = function(options, cb) {
// expects remoteAddress to have a meaningful value // expects remoteAddress to have a meaningful value
ip = ip || (addressType === 4 ? '127.0.0.1' : '0:0:0:0:0:0:0:1'); ip = ip || (addressType === 4 ? '127.0.0.1' : '0:0:0:0:0:0:0:1');
connect(self, ip, options.port, addressType, options.localAddress); connect(self,
ip,
options.port,
addressType,
options.localAddress,
options.localPort);
} }
}); });
} }

61
test/simple/test-net-localerror.js

@ -0,0 +1,61 @@
// 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 net = require('net');
var server = net.createServer(function(socket) {
assert.ok(false, 'no clients should connect');
}).listen(common.PORT).on('listening', function() {
server.unref();
function test1(next) {
connect({
host: '127.0.0.1',
port: common.PORT,
localPort: 'foobar',
},
'localPort should be a number: foobar',
next);
}
function test2(next) {
connect({
host: '127.0.0.1',
port: common.PORT,
localAddress: 'foobar',
},
'localAddress should be a valid IP: foobar',
next)
}
test1(test2);
})
function connect(opts, msg, cb) {
var client = net.connect(opts).on('connect', function() {
assert.ok(false, 'we should never connect');
}).on('error', function(err) {
assert.strictEqual(err.message, msg);
if (cb) cb();
});
}

41
test/simple/test-net-localport.js

@ -0,0 +1,41 @@
// 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 net = require('net');
var server = net.createServer(function(socket) {
console.log(socket.remotePort);
assert.strictEqual(socket.remotePort, common.PORT + 1);
socket.end();
socket.on('close', function() {
server.close();
});
}).listen(common.PORT).on('listening', function() {
var client = net.connect({
host: '127.0.0.1',
port: common.PORT,
localPort: common.PORT + 1,
}).on('connect', function() {
assert.strictEqual(client.localPort, common.PORT + 1);
});
})
Loading…
Cancel
Save