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;