103 lines
2.2 KiB
JavaScript
103 lines
2.2 KiB
JavaScript
'use strict'
|
|
|
|
const debug = require('debug')('detect-port')
|
|
const net = require('net')
|
|
const address = require('address')
|
|
|
|
module.exports = (port, host, callback) => {
|
|
if (typeof port === 'function') {
|
|
callback = port
|
|
port = null
|
|
} else if (typeof host === 'function') {
|
|
callback = host
|
|
host = null
|
|
}
|
|
port = parseInt(port) || 0
|
|
let maxPort = port + 10
|
|
if (maxPort > 65535) {
|
|
maxPort = 65535
|
|
}
|
|
debug('detect free port between [%s, %s)', port, maxPort)
|
|
if (typeof callback === 'function') {
|
|
return tryListen(host, port, maxPort, callback)
|
|
}
|
|
// promise
|
|
return new Promise((resolve, reject) => {
|
|
tryListen(host, port, maxPort, (error, realPort) => {
|
|
if (error) {
|
|
reject(error);
|
|
} else {
|
|
resolve(realPort);
|
|
}
|
|
})
|
|
})
|
|
}
|
|
|
|
function tryListen(host, port, maxPort, callback) {
|
|
function handleError() {
|
|
port++
|
|
if (port >= maxPort) {
|
|
debug(
|
|
'port: %s >= maxPort: %s, give up and use random port',
|
|
port,
|
|
maxPort
|
|
)
|
|
port = 0
|
|
maxPort = 0
|
|
}
|
|
tryListen(host, port, maxPort, callback)
|
|
}
|
|
|
|
// 1. check specified host (or null)
|
|
listen(port, host, (err, realPort) => {
|
|
// ignore random listening
|
|
if (port === 0) {
|
|
return callback(err, realPort)
|
|
}
|
|
|
|
if (err) {
|
|
return handleError(err)
|
|
}
|
|
|
|
// 2. check default host
|
|
listen(port, null, err => {
|
|
if (err) {
|
|
return handleError(err)
|
|
}
|
|
|
|
// 3. check localhost
|
|
listen(port, 'localhost', err => {
|
|
if (err) {
|
|
return handleError(err)
|
|
}
|
|
|
|
// 4. check current ip
|
|
listen(port, address.ip(), (err, realPort) => {
|
|
if (err) {
|
|
return handleError(err)
|
|
}
|
|
|
|
callback(null, realPort)
|
|
})
|
|
})
|
|
})
|
|
})
|
|
}
|
|
|
|
function listen(port, hostname, callback) {
|
|
const server = new net.Server()
|
|
|
|
server.on('error', err => {
|
|
debug('listen %s:%s error: %s', hostname, port, err)
|
|
server.close()
|
|
return callback(err)
|
|
})
|
|
|
|
server.listen(port, hostname, () => {
|
|
port = server.address().port
|
|
server.close()
|
|
debug('get free %s:%s', hostname, port)
|
|
return callback(null, port)
|
|
})
|
|
}
|