diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8d87b1d --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +node_modules/* diff --git a/bin/classes/IsJsonString.js b/bin/classes/IsJsonString.js new file mode 100644 index 0000000..d0e6885 --- /dev/null +++ b/bin/classes/IsJsonString.js @@ -0,0 +1,9 @@ +function IsJsonString(str) { + try { + JSON.parse(str); + } catch (e) { + return false; + } + return true; +} +module.exports = IsJsonString; \ No newline at end of file diff --git a/bin/classes/decrypt.js b/bin/classes/decrypt.js new file mode 100644 index 0000000..658b7a8 --- /dev/null +++ b/bin/classes/decrypt.js @@ -0,0 +1,18 @@ +module.exports = { + /** + * @param {String} content Zu entschlüsselnde Nachricht + */ + 'decrypt': function (content,passcode) { + var result = []; var str = ''; + var codesArr = JSON.parse(content);var passLen = passcode.length ; + for(var i = 0 ; i < codesArr.length ; i++) { + var passOffset = i%passLen ; + var calAscii = (codesArr[i]-passcode.charCodeAt(passOffset)); + result.push(calAscii) ; + } + for(var i = 0 ; i < result.length ; i++) { + var ch = String.fromCharCode(result[i]); str += ch ; + } + return str ; + } +} \ No newline at end of file diff --git a/bin/classes/events/listener.js b/bin/classes/events/listener.js new file mode 100644 index 0000000..31a7f85 --- /dev/null +++ b/bin/classes/events/listener.js @@ -0,0 +1,11 @@ +/** + * @param {array} events Die Events die Ausgeführt werden + */ +function listener(events, event){ + events.forEach(e => { + if(event === e.name) { + e.function(); + } + }) +} +module.exports = listener; \ No newline at end of file diff --git a/bin/classes/websocket.js b/bin/classes/websocket.js new file mode 100644 index 0000000..37a6fe4 --- /dev/null +++ b/bin/classes/websocket.js @@ -0,0 +1,27 @@ +function socket(WebSocket, config) { +// Websocket +const wss = new WebSocket.Server({ + port: config.websocket, + perMessageDeflate: { + zlibDeflateOptions: { + // See zlib defaults. + chunkSize: 1024, + memLevel: 7, + level: 3 + }, + zlibInflateOptions: { + chunkSize: 10 * 1024 + }, + // Other options settable: + clientNoContextTakeover: true, // Defaults to negotiated value. + serverNoContextTakeover: true, // Defaults to negotiated value. + serverMaxWindowBits: 10, // Defaults to negotiated value. + // Below options specified as default values. + concurrencyLimit: 10, // Limits zlib concurrency for perf. + threshold: 1024 // Size (in bytes) below which messages + // should not be compressed. + } +}); +return wss; +} +module.exports = socket; \ No newline at end of file diff --git a/bin/config/server.json b/bin/config/server.json new file mode 100644 index 0000000..07c60be --- /dev/null +++ b/bin/config/server.json @@ -0,0 +1,5 @@ +{ + "maintance":"true", + "websocket": "8080", + "tcpserver":"1337" +} \ No newline at end of file diff --git a/bin/config/sql.json b/bin/config/sql.json new file mode 100644 index 0000000..a0ea70b --- /dev/null +++ b/bin/config/sql.json @@ -0,0 +1,6 @@ +{ + "name": "", + "pw": "", + "host": "", + "user": "" + } \ No newline at end of file diff --git a/index.js b/index.js new file mode 100644 index 0000000..adb6e4d --- /dev/null +++ b/index.js @@ -0,0 +1,199 @@ +const WebSocket = require('ws'); // Websocket Frame +const sql = require('mysql'); // SQL frame +const db = require('./bin/config/sql.json'); // SQL Config +const net = require('net'); // TCP Connection +const readline = require('readline'); // Console Input +const colors = require('colors'); // Console Colours +let config = require('./bin/config/server.json'); // Server Config + +// Socket +let socket = require('./bin/classes/websocket'); // Requires Websocket Object +let wss = socket(WebSocket, config); // Asignes Websocket +//Classes +let crypt = require('./bin/classes/decrypt'); // Cryption Class +let IsJsonString = require('./bin/classes/IsJsonString'); // JSON Validator +let listener = require('./bin/classes/events/listener'); // Event Listener + +// Events +let tcp_login = require('./bin/classes/events/tcp/login'); // TCP Login Event +let ws_login = require('./bin/classes/events/ws/login'); // WSS Login Event +let ws_logout = require('./bin/classes/events/ws/logout'); // WSS Logout Event + +// Database Definition +var db_con = sql.createConnection({ + host : db.host, + user : db.user, + password : db.pw, + database : db.name +}); + +// Console Input +const rl = readline.createInterface({input: process.stdin, output: process.stdout}); + +wss.on('connection', (ws) => { + ws.on('message', function incoming(data) { + if(IsJsonString(data)){ + let payload = JSON.parse(data); + //console.log('WSS: ' + payload['event']); + let events = [ + {name:'login', function() {ws_login(payload, db_con, ws, crypt)}}, + {name:'logout', function() {ws_logout(payload, db_con, ws)}}, + ]; + listener(events,payload.event); + /** + * logout: + * Removes Session Key + * and sends packet to redirect from the user area + * ends connection + * register: + * User Folder Structure: + * Usersroot(named like the user) I--> space (where files get stored) + * I--> meta (Where user infos get stored) + * Ends Connection + * Database Oriented Data Management + * getData + * Sends Requested data + * + * Ends Connection + * writeData + * Wrights Data to the Database + * Check if user id is given + * Ends Connection + * Physical Data management + * updload + * Takes Uploaded Data and places it in the Users Space + * Ends Connection + * download + * Serves Requested Files from the Users Space + * Ends Connection + */ + } + }); +}); + +let server = net.createServer((socket) => { + socket.on('data', (data) => { + if(IsJsonString(data)){ + let payload = JSON.parse(data); + console.log('TCP: ' + payload['event']); + if(IsJsonString(data)){ + let payload = JSON.parse(data); + let events = [ + {name:'login', function() { tcp_login(payload, db_con, socket, crypt) } }, + {name:'test', function() { console.log('test 1111') } }, + ]; + listener(events,payload.event); + } + } + }); +}); + +// ======================================================================== +// * The Console Input * +// ======================================================================== +rl.on('line', (input) => { + //TODO: change all Console output to following Format console.log(colors.grey(`test ${colors.yellow("text")}`)); + let messageArray = input.split(" "); + let cmd = messageArray[0]; + let args = messageArray.slice(0); + + console.log(args); + switch(args[0].toLowerCase()){ + case 'help': + console.log(colors.grey('=================================== ') + colors.yellow('Help') + colors.grey(' ===================================')); + console.log(colors.yellow('Help:') + colors.grey(' Shows a list of all avaiable Comamnds.')); + console.log(colors.yellow('Shutdown:') + colors.grey(' shuts down the Server.')); + console.log(colors.grey('============================================================================')); + break; + case 'shutdown': + rl.question(colors.grey('Are you sure you want to shut down the Server?')+'\n'+colors.yellow('(Yes, y) = Yes, (No, n) = No: '), (reply) => { + let answer = reply.toLowerCase(); + //Askes if the Server should be shutdown + if(answer === 'yes' || answer === 'y'){ + process.exit(0); + }else if(answer === 'no' || answer === 'n'){ + return; + }else{ + return; + } + }); + break; + case 'maintance': + let config = file.import('./bin/config/server.json'); + switch(args[1]){ + default: + console.log(colors.grey(`Please Enter a Parameter you can use <${colors.yellow("enable")}, ${colors.yellow("disable")}, ${colors.yellow("current")}>`)); + break; + case 'disable': + rl.question(colors.grey('Are you sure you want disable Maintance Mode?')+'\n'+colors.yellow('(Yes, y) = Yes, (No, n) = No: '), (reply) => { + let answer = reply.toLowerCase(); + //Askes if the Server should be shutdown + if(answer === 'yes' || answer === 'y'){ + config.maintance = 'true'; + console.log(colors.green('Maintance Mode disabled')); + file.save('./bin/config/server.json', config); + }else if(answer === 'no' || answer === 'n'){ + return; + }else{ + return; + } + file.save('./bin/config/server.json', config); + }); + break; + case 'enable': + rl.question(colors.grey('Are you sure you want disable Maintance Mode?')+'\n'+colors.yellow('(Yes, y) = Yes, (No, n) = No: '), (reply) => { + let answer = reply.toLowerCase(); + //Askes if the Server should be shutdown + if(answer === 'yes' || answer === 'y'){ + config.maintance = 'false'; + console.log(colors.green('Maintance Mode disabled')); + file.save('./bin/config/server.json', config); + }else if(answer === 'no' || answer === 'n'){ + return; + }else{ + return; + } + file.save('./bin/config/server.json', config); + }); + break; + case 'current': + if(config.maintance == 'true'){ + console.log(colors.grey('Maintance Mode is ')+colors.yellow('Activated')); + }else{ + console.log(colors.grey('Maintance Mode is ')+colors.yellow('Deactivated')); + } + break; + } + break; + default: + console.log(colors.grey('Invalid Command.. Type ')+colors.yellow('Help')+colors.grey(', to get a list of avaiable Comamnds.')); + break; + } +}); + +// ========================================= +// * Starts Services with all needed ports * +// ========================================= +//Gets core-node Connections +server.listen(1337, '127.0.0.1', () => { + console.log(colors.grey('TCP Server online on Port: ') + colors.yellow(config.tcpserver)); + console.log(colors.grey('WSS Server online on Port: ') + colors.yellow(config.websocket)); +}); + +// ================================== +// * Checks if the Port is avaiable * +// * If Yes Run else Restart * +// ================================== +server.on('error', (e) => { + if (e.code === 'EADDRINUSE') { + console.log('Address in use, retrying...'); + setTimeout(() => { + + server.close(); + // Gets Server Connections + server.listen(config.tcpserver, '127.0.0.1', () => { + console.log('Server online on Port:' + config.tcpserver); + }); + }, 1000); + } +}); \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..86b8398 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,148 @@ +{ + "name": "server", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" + }, + "bignumber.js": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-7.2.1.tgz", + "integrity": "sha512-S4XzBk5sMB+Rcb/LNcpzXr57VRTxgAvaAEDAl1AwRx27j00hT84O6OkteE7u8UB3NuaaygCRrEpqox4uDOrbdQ==" + }, + "colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "fs": { + "version": "0.0.1-security", + "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz", + "integrity": "sha1-invTcYa23d84E/I4WLV+yq9eQdQ=" + }, + "http": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/http/-/http-0.0.0.tgz", + "integrity": "sha1-huYybSnF0Dnen6xYSkVon5KfT3I=" + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "mysql": { + "version": "2.17.1", + "resolved": "https://registry.npmjs.org/mysql/-/mysql-2.17.1.tgz", + "integrity": "sha512-7vMqHQ673SAk5C8fOzTG2LpPcf3bNt0oL3sFpxPEEFp1mdlDcrLK0On7z8ZYKaaHrHwNcQ/MTUz7/oobZ2OyyA==", + "requires": { + "bignumber.js": "7.2.1", + "readable-stream": "2.3.6", + "safe-buffer": "5.1.2", + "sqlstring": "2.3.1" + } + }, + "net": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/net/-/net-1.0.2.tgz", + "integrity": "sha1-0XV+yaf7I3HYPPR1XOPifhCCk4g=" + }, + "path": { + "version": "0.12.7", + "resolved": "https://registry.npmjs.org/path/-/path-0.12.7.tgz", + "integrity": "sha1-1NwqUGxM4hl+tIHr/NWzbAFAsQ8=", + "requires": { + "process": "^0.11.1", + "util": "^0.10.3" + } + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=" + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "readline": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/readline/-/readline-1.3.0.tgz", + "integrity": "sha1-xYDXfvLPyHUrEySYBg3JeTp6wBw=" + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "sqlstring": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz", + "integrity": "sha1-R1OT/56RR5rqYtyvDKPRSYOn+0A=" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "util": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", + "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", + "requires": { + "inherits": "2.0.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + } + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "ws": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.1.2.tgz", + "integrity": "sha512-gftXq3XI81cJCgkUiAVixA0raD9IVmXqsylCrjRygw4+UOOGzPoxnQ6r/CnVL9i+mDncJo94tSkyrtuuQVBmrg==", + "requires": { + "async-limiter": "^1.0.0" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..7263aaf --- /dev/null +++ b/package.json @@ -0,0 +1,21 @@ +{ + "name": "server", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", + "dependencies": { + "colors": "^1.3.3", + "fs": "0.0.1-security", + "net": "^1.0.2", + "path": "^0.12.7", + "readline": "^1.3.0", + "http": "0.0.0", + "mysql": "^2.17.1", + "ws": "^7.1.2" + } +} diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..8a1392b --- /dev/null +++ b/readme.md @@ -0,0 +1,5 @@ +# What does this Framework aim? +Simply dealing with as the description says "nearly" all kind of software which means it deals with a few much used socket protocols +Since it also handles web socket request it can be used as real coss side server + +# Documentation may folow later