diff --git a/package-lock.json b/package-lock.json index fb3a278ada8af..cd867c4ac88f2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,16 +17,20 @@ "dev": true }, "@types/node": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-8.0.1.tgz", - "integrity": "sha512-bys2VRs6H7HP8S26aHgPWSiSX7q81TToe5HSSvl5bQjoSElQ2SwbGw2p6/DSDb7Vr0oKhewFao9ZuTn8DSag9Q==", + "version": "8.0.28", + "resolved": "https://registry.npmjs.org/@types/node/-/node-8.0.28.tgz", + "integrity": "sha512-HupkFXEv3O3KSzcr3Ylfajg0kaerBg1DyaZzRBBQfrU3NN1mTBRE7sCveqHwXLS5Yrjvww8qFzkzYQQakG9FuQ==", "dev": true }, "@types/node-static": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/@types/node-static/-/node-static-0.7.0.tgz", "integrity": "sha512-4SImtzapcVt+rQEAKVtbT0eh2D895DKnyrRkDgcSpw+LNnol9zlJPcU6yDvjWrEV/6nBSPQqzY0AP69v5v2iEQ==", - "dev": true + "dev": true, + "requires": { + "@types/mime": "1.3.1", + "@types/node": "8.0.28" + } }, "@types/nodemailer": { "version": "1.3.33", @@ -34,27 +38,27 @@ "integrity": "sha512-PONEJf/LwNcqgU/GpMIAquSBFdq+kCdpYI9TdoeGcTfLCsXzWunKzv4bUQs8zfKGz97CLymgoL0fMLYpOu+/1A==", "dev": true, "requires": { - "@types/node": "8.0.1", - "@types/nodemailer-direct-transport": "1.0.29", - "@types/nodemailer-smtp-transport": "2.7.2" + "@types/node": "8.0.28", + "@types/nodemailer-direct-transport": "1.0.30", + "@types/nodemailer-smtp-transport": "2.7.3" } }, "@types/nodemailer-direct-transport": { - "version": "1.0.29", - "resolved": "https://registry.npmjs.org/@types/nodemailer-direct-transport/-/nodemailer-direct-transport-1.0.29.tgz", - "integrity": "sha1-Ake7RzT4u/k5gkGxa0ECLhMD3fE=", + "version": "1.0.30", + "resolved": "https://registry.npmjs.org/@types/nodemailer-direct-transport/-/nodemailer-direct-transport-1.0.30.tgz", + "integrity": "sha512-gH49BNkXM8EZb/UgI4hUwWwTW3izRx5L+0VyohKkbVijvfUIhn7RALSpBjCUyXzEj0XZSNmQMFVc97Lj0z8UIw==", "dev": true, "requires": { "@types/nodemailer": "1.3.33" } }, "@types/nodemailer-smtp-transport": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/@types/nodemailer-smtp-transport/-/nodemailer-smtp-transport-2.7.2.tgz", - "integrity": "sha512-sFeTdk87Xk4ADTs7HY32Thr/sD06HJHPbmjuCOGtqVhSnMeVPf3OQAU3d4oW9bhccRLpjCWUds00CrbuU/iLzw==", + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/@types/nodemailer-smtp-transport/-/nodemailer-smtp-transport-2.7.3.tgz", + "integrity": "sha512-HxKPBErWelYVIWiKkUl06IaG4ojEMDtH6cAlojKgjsqwF8UQun4QeahYCWLCkA8/vKOX0G6VV1Vu2Z4x4ovqLQ==", "dev": true, "requires": { - "@types/node": "8.0.1", + "@types/node": "8.0.28", "@types/nodemailer": "1.3.33" } }, @@ -68,13 +72,10 @@ "version": "0.3.31", "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.31.tgz", "integrity": "sha512-6d+6cH187jHWoUP07fzDQkC1fATu7TXMNJaCKwMwpcjkRvAK4T7bDw8sukL3rE8A/ZEPmo94YghsgCkI2/V8kw==", - "dev": true - }, - "acorn": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.0.3.tgz", - "integrity": "sha1-xGDfCEkUY/AozLguqzcwvwEIez0=", - "dev": true + "dev": true, + "requires": { + "@types/node": "8.0.28" + } }, "acorn-jsx": { "version": "3.0.1", @@ -1371,23 +1372,6 @@ "safe-buffer": "5.0.1" } }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" - } - }, - "string_decoder": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.2.tgz", - "integrity": "sha1-sp4fThEl+pehA4K4pTNze3SR4Xk=", - "dev": true - }, "strip-ansi": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", diff --git a/package.json b/package.json index 0035ab4a9fd63..8b53145887ce3 100644 --- a/package.json +++ b/package.json @@ -48,15 +48,13 @@ "license": "MIT", "devDependencies": { "@types/cloud-env": "^0.2.0", - "@types/node": "^8.0.1", + "@types/node": "^8.0.28", "@types/node-static": "^0.7.0", "@types/nodemailer": "^1.3.33", "@types/ofe": "^0.5.0", "@types/sockjs": "^0.3.31", "eslint": "^4.0.0", "mocha": "^3.0.0", - "@types/node": "^8.0.1", - "@types/nodemailer": "^1.3.33", "typescript": "^2.5.0-dev.20170622" } } diff --git a/sockets-workers.js b/sockets-workers.js index 93b1174b21734..952d34a6b8a92 100644 --- a/sockets-workers.js +++ b/sockets-workers.js @@ -13,6 +13,8 @@ 'use strict'; const cluster = require('cluster'); +const fs = require('fs'); +const path = require('path'); // IPC command tokens const EVAL = '$'; @@ -461,7 +463,46 @@ if (cluster.isWorker) { }); let app = require('http').createServer(); - let appssl = Config.ssl ? require('https').createServer(Config.ssl.options) : null; + /** @type {?NodeJS.Server} */ + let appssl = null; + if (Config.ssl) { + let key; + try { + key = path.resolve(__dirname, Config.ssl.options.key); + if (!fs.lstatSync(key).isFile()) throw new Error(); + try { + key = fs.readFileSync(key); + } catch (e) { + require('./crashlogger')(new Error(`Failed to read the configured SSL private key PEM file:\n${e.stack}`), `Socket process ${cluster.worker.id} (${process.pid})`, true); + } + } catch (e) { + console.warn('SSL private key config values will not support HTTPS server option values in the future. Please set it to use the absolute path of its PEM file.'); + key = Config.ssl.options.key; + } + + let cert; + try { + cert = path.resolve(__dirname, Config.ssl.options.cert); + if (!fs.lstatSync(cert).isFile()) throw new Error(); + try { + cert = fs.readFileSync(cert); + } catch (e) { + require('./crashlogger')(new Error(`Failed to read the configured SSL certificate PEM file:\n${e.stack}`), `Socket process ${cluster.worker.id} (${process.pid})`, true); + } + } catch (e) { + console.warn('SSL certificate config values will not support HTTPS server option values in the future. Please set it to use the absolute path of its PEM file.'); + cert = Config.ssl.options.cert; + } + + if (key && cert) { + try { + // In case there are additional SSL config settings besides the key and cert... + appssl = require('https').createServer(Object.assign({}, Config.ssl.options, {key, cert})); + } catch (e) { + require('./crashlogger')(new Error(`The SSL settings are misconfigured:\n${e.stack}`), `Socket process ${cluster.worker.id} (${process.pid})`, true); + } + } + } const StaticServer = require('node-static').Server; const roomidRegex = /^\/[A-Za-z0-9][A-Za-z0-9-]*\/?$/; @@ -529,6 +570,7 @@ if (cluster.isWorker) { process.once('disconnect', () => { multiplexer.destroy(); app.close(); + /** @type {?NodeJS.Server} */ if (appssl) appssl.close(); }); diff --git a/sockets.js b/sockets.js index 3bd473c28b719..4bd3e272173b2 100644 --- a/sockets.js +++ b/sockets.js @@ -301,8 +301,6 @@ class GoWorker extends EventEmitter { /** @type {boolean | void} */ this.exitedAfterDisconnect = undefined; - /** @type {string[]} */ - this.obuf = []; /** @type {string} */ this.ibuf = ''; /** @type {?Error} */ @@ -351,17 +349,7 @@ class GoWorker extends EventEmitter { * @return {boolean} */ send(message) { - if (!this.isConnected()) { - this.obuf.push(message); - return false; - } - - if (this.obuf.length) { - this.obuf.splice(0).forEach(msg => { - this.connection.write(JSON.stringify(msg) + DELIM); - }); - } - + if (!this.isConnected()) return false; return this.connection.write(JSON.stringify(message) + DELIM); } @@ -380,7 +368,7 @@ class GoWorker extends EventEmitter { * @return {boolean} */ isDead() { - return this.connection && !this.connection.destroyed; + return this.process && (this.process.exitCode !== null || this.process.statusCode !== null); } /** @@ -419,6 +407,7 @@ class GoWorker extends EventEmitter { // if it crashed. if (this.error) throw this.error; } + this.emit('exit', this, ...args); }); }); @@ -441,16 +430,16 @@ class GoWorker extends EventEmitter { this.connection.on('data', /** @param {string} data */ data => { let idx = data.lastIndexOf(DELIM); if (idx < 0) { - // Very long message... this.ibuf += data; return; } - // Because of how Node handles TCP connections, we can - // receive any number of messages, and they may not - // be guaranteed to be complete. - let messages = this.ibuf; - this.ibuf = ''; + let messages = ''; + if (this.ibuf) { + messages += this.ibuf.slice(0); + this.ibuf = ''; + } + if (idx === data.length - 1) { messages += data.slice(0, -1); } else {