diff --git a/.travis.yml b/.travis.yml index 31d07777..f7059a13 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,8 @@ before_install: - curl -o factorio.tar.gz -L https://www.factorio.com/get-download/latest/headless/linux64 - tar -xf factorio.tar.gz - npm install -g codecov + # Needed for lib/manager/configManager + - echo {} > config.json script: - npm run-script ci-cover - codecov -f coverage/lcov.info diff --git a/CHANGELOG.md b/CHANGELOG.md index a0dfdd58..64085b0a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ Version 2.0.0 - Fixed sslCert and sslPrivKey entries being ignored in the config. - Changed ssl key creation to be done at startup instead of on npm install. - Added error handling during master startup. +- Factorio game and rcon port now defaults to a random port above 49151. ### Breaking Changes diff --git a/client.js b/client.js index 53d22417..d237a28c 100644 --- a/client.js +++ b/client.js @@ -90,6 +90,21 @@ function messageInterface(command, callback) { }); } +/** + * Give a random dynamic port + * + * Returns a random port number in the Dynamic Ports range as defined by + * RFC 6335. + * + * @return {number} a number in the range 49152 to 65535. + */ +function randomDynamicPort() { + const start = 49152; + const end = 65535 + 1; + + return Math.floor(Math.random() * (end - start) + start) +} + function printUsage() { console.error("Usage: "); console.error("node client.js start [instance name]"); @@ -264,8 +279,8 @@ write-data=${ path.resolve(config.instanceDirectory, instance) }\r\n // this line is probably not needed anymore but Im not gonna remove it fs.copySync('sharedMods', path.join(instancedirectory, "mods")); let instconf = { - "factorioPort": args.port || process.env.FACTORIOPORT || Math.floor(Math.random() * 65535), - "clientPort": args["rcon-port"] || process.env.RCONPORT || Math.floor(Math.random() * 65535), + "factorioPort": args.port || process.env.FACTORIOPORT || randomDynamicPort(), + "clientPort": args["rcon-port"] || process.env.RCONPORT || randomDynamicPort(), "__comment_clientPassword": "This is the rcon password. Its also used for making an instanceID. Make sure its unique and not blank.", "clientPassword": args["rcon-password"] || Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 8), "info": {} @@ -802,6 +817,11 @@ function hashMods(instanceName, callback) { }); } +module.exports = { + + // For testing only + _randomDynamicPort: randomDynamicPort, +}; if (module === require.main) { console.warn(` diff --git a/client.spec.js b/client.spec.js new file mode 100644 index 00000000..5fd9e9ff --- /dev/null +++ b/client.spec.js @@ -0,0 +1,23 @@ +const assert = require('assert').strict; + +const client = require("./client"); + +describe("Client testing", function() { + describe("randomDynamicPort()", function() { + it("should return a port number", function() { + let port = client._randomDynamicPort() + assert.equal(typeof port, "number"); + assert(Number.isInteger(port)); + assert(0 <= port && port < 2**16); + }); + + it("should return a port number in the dynamic range", function() { + function validate(port) { + return 49152 <= port && port <= 65535; + } + for (let i=0; i < 20; i++) { + assert(validate(client._randomDynamicPort())); + } + }); + }); +});