cscg24-guacamole

CSCG 2024 Challenge 'Guacamole Mashup'
git clone https://git.sinitax.com/sinitax/cscg24-guacamole
Log | Files | Refs | sfeed.txt

Server.js (4573B)


      1const EventEmitter = require('events').EventEmitter;
      2const Ws = require('ws');
      3const DeepExtend = require('deep-extend');
      4
      5const ClientConnection = require('./ClientConnection.js');
      6
      7class Server extends EventEmitter {
      8
      9    constructor(wsOptions, guacdOptions, clientOptions, callbacks) {
     10        super();
     11
     12        this.LOGLEVEL = {
     13            QUIET: 0,
     14            ERRORS: 10,
     15            NORMAL: 20,
     16            VERBOSE: 30,
     17            DEBUG: 40,
     18        };
     19
     20        if (wsOptions.hasOwnProperty('server')) {
     21            this.wsOptions = wsOptions;
     22        } else {
     23            this.wsOptions = Object.assign({
     24                port: 8080
     25            }, wsOptions);
     26        }
     27
     28        this.guacdOptions = Object.assign({
     29            host: '127.0.0.1',
     30            port: 4822
     31        }, guacdOptions);
     32
     33        this.clientOptions = {};
     34        DeepExtend(this.clientOptions, {
     35            maxInactivityTime: 10000,
     36
     37            log: {
     38                level: this.LOGLEVEL.VERBOSE,
     39                stdLog: console.log,
     40                errorLog: console.error
     41            },
     42
     43            crypt: {
     44                cypher: 'AES-256-CBC',
     45            },
     46
     47            connectionDefaultSettings: {
     48                rdp: {
     49                    'args': 'connect',
     50                    'port': '3389',
     51                    'width': 1024,
     52                    'height': 768,
     53                    'dpi': 96,
     54                },
     55                vnc: {
     56                    'args': 'connect',
     57                    'port': '5900',
     58                    'width': 1024,
     59                    'height': 768,
     60                    'dpi': 96,
     61                },
     62                ssh: {
     63                    'args': 'connect',
     64                    'port': 22,
     65                    'width': 1024,
     66                    'height': 768,
     67                    'dpi': 96,
     68                },
     69                telnet: {
     70                    'args': 'connect',
     71                    'port': 23,
     72                    'width': 1024,
     73                    'height': 768,
     74                    'dpi': 96,
     75                }
     76            },
     77
     78            allowedUnencryptedConnectionSettings: {
     79                rdp: [
     80                    'width',
     81                    'height',
     82                    'dpi'
     83                ],
     84                vnc: [
     85                    'width',
     86                    'height',
     87                    'dpi'
     88                ],
     89                ssh: [
     90                    'color-scheme',
     91                    'font-name',
     92                    'font-size',
     93                    'width',
     94                    'height',
     95                    'dpi'
     96                ],
     97                telnet: [
     98                    'color-scheme',
     99                    'font-name',
    100                    'font-size',
    101                    'width',
    102                    'height',
    103                    'dpi'
    104                ]
    105            }
    106
    107        }, clientOptions);
    108
    109        // Backwards compatibility
    110        if (this.clientOptions.log.verbose !== 'undefined' && this.clientOptions.log.verbose === true) {
    111            this.clientOptions.log.level = this.LOGLEVEL.DEBUG;
    112        }
    113
    114        if (typeof this.clientOptions.log.level === 'string' && this.LOGLEVEL[this.clientOptions.log.level]) {
    115            this.clientOptions.log.level = this.LOGLEVEL[this.clientOptions.log.level];
    116        }
    117
    118        this.callbacks = Object.assign({
    119            processConnectionSettings: (settings, callback) => callback(undefined, settings)
    120        }, callbacks);
    121
    122        this.connectionsCount = 0;
    123        this.activeConnections = new Map();
    124
    125        if (this.clientOptions.log.level >= this.LOGLEVEL.NORMAL) {
    126            this.clientOptions.log.stdLog('Starting guacamole-lite websocket server');
    127        }
    128
    129        this.webSocketServer = new Ws.Server(this.wsOptions);
    130        this.webSocketServer.on('connection', this.newConnection.bind(this));
    131
    132        process.on('SIGTERM', this.close.bind(this));
    133        process.on('SIGINT', this.close.bind(this));
    134
    135    }
    136
    137    close() {
    138        if (this.clientOptions.log.level >= this.LOGLEVEL.NORMAL) {
    139            this.clientOptions.log.stdLog('Closing all connections and exiting...');
    140        }
    141
    142        this.webSocketServer.close(() => {
    143            this.activeConnections.forEach((activeConnection) => {
    144                activeConnection.close();
    145            });
    146        });
    147    }
    148
    149    newConnection(webSocketConnection) {
    150        this.connectionsCount++;
    151        this.activeConnections.set(this.connectionsCount, new ClientConnection(this, this.connectionsCount, webSocketConnection));
    152    }
    153}
    154
    155module.exports = Server;