diff --git a/config-default.json b/config-default.json index f9e426c..d577145 100644 --- a/config-default.json +++ b/config-default.json @@ -9,7 +9,7 @@ "logDirectory": "" }, - "port": 3000, + "port": "auto", "deamon": false, "parallelQueueProcessing": 1, "cleanupTasksAfter": 2880, diff --git a/config.js b/config.js index 601b4bb..de014b6 100644 --- a/config.js +++ b/config.js @@ -29,7 +29,7 @@ Usage: node index.js [options] Options: --config Path to the configuration file (default: config-default.json) - -p, --port Port to bind the server to (default: 3000) + -p, --port Port to bind the server to, or "auto" to automatically find an available port (default: 3000) --odm_path Path to OpenDroneMap's code (default: /code) --log_level Set log level verbosity (default: info) -d, --daemon Set process to run as a deamon @@ -114,7 +114,7 @@ config.logger.maxFileSize = fromConfigFile("logger.maxFileSize", 1024 * 1024 * 1 config.logger.maxFiles = fromConfigFile("logger.maxFiles", 10); // Max number of log files kept config.logger.logDirectory = fromConfigFile("logger.logDirectory", ''); // Set this to a full path to a directory - if not set logs will be written to the application directory. -config.port = parseInt(argv.port || argv.p || fromConfigFile("port", process.env.PORT || 3000)); +config.port = (argv.port || argv.p || fromConfigFile("port", process.env.PORT || "auto")); config.deamon = argv.deamonize || argv.daemon || argv.d || fromConfigFile("daemon", false); config.parallelQueueProcessing = parseInt(argv.parallel_queue_processing || argv.q || fromConfigFile("parallelQueueProcessing", 1)); config.cleanupTasksAfter = parseInt(argv.cleanup_tasks_after || fromConfigFile("cleanupTasksAfter", 2880)); diff --git a/index.js b/index.js index f15ef78..9f74a53 100644 --- a/index.js +++ b/index.js @@ -918,10 +918,29 @@ let commands = [ taskManager = TaskManager.singleton(); }, cb => { - server = app.listen(config.port, err => { - if (!err) logger.info('Server has started on port ' + String(config.port)); - cb(err); - }); + const startServer = (port, cb) => { + server = app.listen(parseInt(port), (err) => { + if (!err) logger.info('Server has started on port ' + String(port)); + cb(err); + }); + server.on("error", cb); + }; + + const tryStartServer = (port, cb) => { + startServer(port, (err) => { + if (err && err.code === 'EADDRINUSE' && port < 5000){ + tryStartServer(port + 1, cb); + }else cb(err); + }); + }; + + if (Number.isInteger(parseInt(config.port))){ + startServer(config.port, cb); + }else if (config.port === "auto"){ + tryStartServer(3000, cb); + }else{ + cb(new Error(`Invalid port: ${config.port}`)); + } } ]; @@ -934,7 +953,7 @@ if (config.powercycle) { async.series(commands, err => { if (err) { - logger.error("Error during startup: " + err.message); + logger.error(err.message); process.exit(1); } }); diff --git a/libs/ProgressReceiver.js b/libs/ProgressReceiver.js index aa33467..a49455b 100644 --- a/libs/ProgressReceiver.js +++ b/libs/ProgressReceiver.js @@ -21,7 +21,7 @@ const dgram = require('dgram'); module.exports = class ProgressReceiver{ constructor(){ - const server = dgram.createSocket('udp4'); + const server = dgram.createSocket({type: 'udp4', reuseAddr: true}); this.callbacks = []; server.on('error', (err) => {