Skip to content

Commit

Permalink
Sockets: Go rewrite
Browse files Browse the repository at this point in the history
Work in progress. I haven't written documentation for the Go code or
confirmed whether this works as intended on Windows yet.

This turned into a pretty substantial refactor of the Node version of
sockets-related code to not only to make using Go child processes
possible, but to optimize it and make unit testing of it and any code
dependent on it possible to write entirely synchronously. sockets.js
and sockets-workers.js are now written in Typescript, though they won't
be able to be transpiled until after Config, Users, Dnsbl, and Monitor
work with it as well.

Fixes #2943
  • Loading branch information
Morfent committed Sep 19, 2017
1 parent 9ea8bac commit af3850d
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 62 deletions.
60 changes: 22 additions & 38 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 1 addition & 3 deletions package.json
Expand Up @@ -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"
}
}
44 changes: 43 additions & 1 deletion sockets-workers.js
Expand Up @@ -13,6 +13,8 @@
'use strict';

const cluster = require('cluster');
const fs = require('fs');
const path = require('path');

// IPC command tokens
const EVAL = '$';
Expand Down Expand Up @@ -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-]*\/?$/;
Expand Down Expand Up @@ -529,6 +570,7 @@ if (cluster.isWorker) {
process.once('disconnect', () => {
multiplexer.destroy();
app.close();
/** @type {?NodeJS.Server} */
if (appssl) appssl.close();
});

Expand Down
29 changes: 9 additions & 20 deletions sockets.js
Expand Up @@ -301,8 +301,6 @@ class GoWorker extends EventEmitter {
/** @type {boolean | void} */
this.exitedAfterDisconnect = undefined;

/** @type {string[]} */
this.obuf = [];
/** @type {string} */
this.ibuf = '';
/** @type {?Error} */
Expand Down Expand Up @@ -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);
}

Expand All @@ -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);
}

/**
Expand Down Expand Up @@ -419,6 +407,7 @@ class GoWorker extends EventEmitter {
// if it crashed.
if (this.error) throw this.error;
}

this.emit('exit', this, ...args);
});
});
Expand All @@ -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 {
Expand Down

0 comments on commit af3850d

Please sign in to comment.