diff --git a/config.js b/config.js index 90ea0e8..e7160de 100755 --- a/config.js +++ b/config.js @@ -1,17 +1,23 @@ -module.exports = class config { +/** + * Config class for SCGO Server API + */ +module.exports = class config { constructor () { this._userOptions = { // Network interface over which the server is communicating. We set this and not the // IP-address, in case the server is using DHCP in a LAN and not a static address. 'iface': 'eth0', - // Steam Account to update the server with steamcmd. - 'steamAccount': ' ', // steam serverToken. To get one see https://steamcommunity.com/dev/managegameservers 'serverToken': '', // Well, the rcon password... 'rconPass': 'YourRconPass', - // Path to steamcmd, can stay like this if installed via package manager. - 'steamExe': 'steamcmd', + // https settings + 'useHttps': false, + 'httpsCertificate': '', + 'httpsPrivateKey': '', + // Optional.In case your CA is not trusted by default (e.g. letsencrypt), you can add + // the CA-Cert here. + 'httpsCa': '', // The folder, where your srcds_run is located 'csgoDir': '/home/csgo/csgo_ds', // anything you want your server command line to have additional to: @@ -24,17 +30,18 @@ // The screen Logfile where the console output of screen and the server will be logged. // New logs are appended, so you may need to delete or rotate this log periodically. 'screenLog': '/home/csgo/screen.log', + // Path to steamcmd, can stay like this if installed via package manager. + 'steamExe': 'steamcmd', + // Steam Account to update the server with steamcmd. + 'steamAccount': ' ', // Script to pass into steamcmd to update. // See https://steamcommunity.com/discussions/forum/1/492379159713970561/ for more info. 'updateScript': '/home/csgo/update_csgo.txt' }; - this.screenCommand = `${this._userOptions.screen} -L -Logfile ${this._userOptions.screenLog} -dmS ${this._userOptions.screenName}`; + this.screenCommand = `${this._userOptions.screen} -L -Logfile ${this._userOptions.screenLog} -dmS ${this._userOptions.screenName}`; this.csgoCommand = `${this._userOptions.csgoDir}/srcds_run`; this.csgoArgs = `-game csgo -console -usercon +sv_setsteamaccount ${this._userOptions.serverToken} ${this._userOptions.csgoOptionalArgs}`; - this.updateCommand = `${this._userOptions.steamExe}`; - this.updateArguments = [`+login ${this._userOptions.steamAccount}`, - `+runscript ${this._userOptions.updateScript}`]; } get rconPass () { @@ -48,4 +55,24 @@ get serverCommandline () { return `${this.screenCommand} ${this.csgoCommand} ${this.csgoArgs}`; } + get updateCommand () { + return this._userOptions.steamExe + } + get updateArguments () { + return [`+login ${this._userOptions.steamAccount}`, + `+runscript ${this._userOptions.updateScript}`]; + } + + get useHttps () { + return this._userOptions.useHttps; + } + get httpsCertificate () { + return this._userOptions.httpsCertificate; + } + get httpsPrivateKey () { + return this._userOptions.httpsPrivateKey; + } + get httpsCa () { + return this._userOptions.httpsCa; + } }; diff --git a/serverControl.js b/serverControl.js index b1bbedb..ef6cd01 100755 --- a/serverControl.js +++ b/serverControl.js @@ -16,9 +16,9 @@ const rcon = require('rcon-srcds'); const logReceiver = require('srcds-log-receiver'); -const http = require('http'); const webSocket = require('ws') const url = require('url'); +const fs = require('fs'); const events = require('events'); const pty = require('node-pty'); const { exec, spawn } = require('child_process'); @@ -36,10 +36,26 @@ var state = { 'serverRunning': false, 'serverRcon': undefined, 'authenticated': false, - 'authenticating': false + 'authenticating': false, + 'updating': false } var serverInfo = new si(); var cfg = new config(); +var http = undefined; +var httpOptions = {}; +// if configured for https, we fork here. +if (cfg.useHttps) { + http = require('https'); + httpOptions = { + key: fs.readFileSync(cfg.httpsPrivateKey), + cert: fs.readFileSync(cfg.httpsCertificate), + }; + if (cfg.httpsCa != '') { + httpOptions.ca = fs.readFileSync(cfg.httpsCa) + } +} else { + http = require('http'); +} // check for running Server on Startup exec('/bin/ps -a', (error, stdout, stderr) => { @@ -154,7 +170,7 @@ function executeRcon (message) { /** * Creates a http server to communicate with a webInteraface. */ -http.createServer((req, res) => { +http.createServer(httpOptions, (req, res) => { var myUrl = url.parse(req.url, true); // Process "control" messages. @@ -205,20 +221,27 @@ http.createServer((req, res) => { }); //Update Server - } else if (args.action == "update") { + } else if (args.action == "update" && !state.updating) { + let updateSuccess = false; + state.updating = true; console.log('Updating Server.'); let updateProcess = pty.spawn(cfg.updateCommand, cfg.updateArguments); updateProcess.on('data', (data) => { - if (data.indexOf("Update state (0x") != -1) { + console.log(data); + if (data.indexOf('Update state (0x') != -1) { let rex = /Update state \(0x\d+\) (.+), progress: (\d{1,2})\.\d{2}/; let matches = rex.exec(data); updateEmitter.emit('progress', matches[1], matches[2]); + } else if (data.indexOf('Success!') != -1) { + console.log('update succeeded'); + updateSuccess = true; } }); updateProcess.on('close', (code) => { res.writeHeader(200, {"Content-Type": "application/json"}); - res.write(`{ "success": true }`); + res.write(`{ "success": ${updateSuccess} }`); res.end(); + state.updating = false; }); // Send Status @@ -275,11 +298,16 @@ http.createServer((req, res) => { res.write('{ "error": true }'); res.end(); } + } else { + res.setHeader("Access-Control-Allow-Origin", "*"); + res.writeHeader(200, { 'Content-Type': 'text/plain' }); + res.write('command ignored'); } }).listen(8090); /*----------------- WebSockets Code -------------------*/ -const wss = new webSocket.Server({ port: 8091 }) +const wssServer = http.createServer(httpOptions); +const wss = new webSocket.Server({ server: wssServer }); /** * Websocket to send data updates to a webClient. @@ -329,6 +357,14 @@ wss.on('connection', (ws) => { }); }); +wssServer.listen(8091, () => { + if(cfg.useHttps) { + const ws = new webSocket(`wss://klosser.duckdns.org:${wssServer.address().port}`); + } else { + const ws = new webSocket(`ws://klosser.duckdns.org:${wssServer.address().port}`); + } +}); + /*----------------- log receiving code --------------------*/ // Since we only control locally installed servers and server logging is not working on // 'localhost', we use the ip-address of the interface configured.