123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114 |
- '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
- let ip;
- try {
- ip = address.ip();
- } catch (err) {
- // Skip the `ip` check if `address.ip()` fails
- return callback(null, realPort);
- }
- listen(port, 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();
- if (err.code === 'ENOTFOUND') {
- debug('ignore dns ENOTFOUND error, get free %s:%s', hostname, port);
- return callback(null, port);
- }
- return callback(err);
- });
- server.listen(port, hostname, () => {
- port = server.address().port;
- server.close();
- debug('get free %s:%s', hostname, port);
- return callback(null, port);
- });
- }
|