Last active
April 18, 2016 22:00
-
-
Save eplawless/51afd77bc6e8631f6b5cb117208d5fe0 to your computer and use it in GitHub Desktop.
Implementation of "get next available TCP port"
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var net = require('net'); | |
var os = require('os'); | |
function getLocalHosts() { | |
var hosts = ['0.0.0.0', '::']; | |
var interfaces = os.networkInterfaces(); | |
Object.keys(interfaces).forEach(function(interfaceName) { | |
var interface = interfaces[interfaceName]; | |
interface.forEach(function(info) { | |
var address = info.address; | |
// append the interface name onto link-local IPv6 addresses | |
// http://stackoverflow.com/a/34275391 | |
if (address.indexOf('fe80:') === 0) { | |
address += '%' + interfaceName; | |
} | |
hosts.push(address); | |
}); | |
}); | |
return hosts; | |
} | |
function createServer(port, host) { | |
return new Promise(function(resolve, reject) { | |
var server = net.createServer(); | |
server.listen(port, host, function() { | |
server.once('close', function() { | |
resolve(true); | |
}); | |
server.close(); | |
}); | |
server.on('error', reject); | |
}); | |
} | |
function _getNextAvailableTcpPort(port, hosts, callback) { | |
if (port < 1 || port > 65535) { | |
callback(new RangeError('expected port to be from 1 to 65535, got ' + port)); | |
return; | |
} | |
var servers = hosts.reduce(function(lastServer, host) { | |
return lastServer | |
? lastServer.then(function() { return createServer(port, host); }) | |
: createServer(port, host); | |
}, null); | |
servers.then(function() { | |
callback(null, port); | |
}, function(error) { | |
_getNextAvailableTcpPort(port + 1, hosts, callback); | |
}); | |
} | |
function getNextAvailableTcpPort(port, callback) { | |
if (typeof callback !== 'function') { | |
throw new TypeError('expected callback to be a function, got ' + typeof callback); | |
} | |
if (typeof port !== 'number') { | |
callback(new TypeError('expected port to be a number, got ' + typeof port)); | |
return; | |
} | |
var hosts = getLocalHosts(); | |
return _getNextAvailableTcpPort(port, hosts, callback); | |
} | |
module.exports = getNextAvailableTcpPort; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment