Make uws listener configurable

This commit is contained in:
Calvin Montgomery 2018-07-11 21:24:39 -07:00
parent 2340da1cb5
commit 3322e5404f
7 changed files with 95 additions and 21 deletions

View File

@ -6,11 +6,47 @@ export default class IOConfiguration {
getSocketEndpoints() {
return this.config.endpoints.slice();
}
getUWSEndpoints() {
return this.config.uwsEndpoints.slice();
}
}
function getUWSEndpoints(oldConfig) {
const uwsEndpoints = oldConfig.get('listen').filter(it => it.uws)
.map(it => {
let domain;
if (it.https) {
domain = oldConfig.get('https.domain')
.replace(/^https/, 'wss');
} else {
domain = oldConfig.get('io.domain')
.replace(/^http/, 'ws');
}
return {
secure: !!it.https,
url: `${domain}:${it.port}`
};
});
uwsEndpoints.sort((a, b) => {
if (a.secure && !b.secure) {
return -1;
} else if (b.secure && !a.secure) {
return 1;
} else {
return 0;
}
});
return uwsEndpoints;
}
IOConfiguration.fromOldConfig = function (oldConfig) {
const config = {
endpoints: []
endpoints: [],
uwsEndpoints: getUWSEndpoints(oldConfig)
};
if (oldConfig.get('io.ipv4-ssl')) {

View File

@ -7,8 +7,10 @@ export default class NullClusterClient {
getSocketConfig(_channel) {
const servers = this.ioConfig.getSocketEndpoints();
const uwsServers = this.ioConfig.getUWSEndpoints();
return Promise.resolve({
servers: servers
servers: servers,
uwsServers: uwsServers
});
}
}

View File

@ -278,18 +278,20 @@ class IOServer {
uws.use(this.cookieParsingMiddleware.bind(this));
uws.use(this.ipSessionCookieMiddleware.bind(this));
uws.use(this.authUserMiddleware.bind(this));
uws.use(this.metricsEmittingMiddleware.bind(this));
uws.on('connection', this.handleConnection.bind(this));
}
bindTo(servers) {
bindTo(sioServers, uwsServers) {
if (!this.io) {
throw new Error('Cannot bind: socket.io has not been initialized yet');
}
servers.forEach(server => {
sioServers.forEach(server => {
this.io.attach(server);
});
uwsServers.forEach(server => {
this.uws.attach(server);
});
}
}
@ -425,12 +427,19 @@ module.exports = {
const uniqueListenAddresses = new Set();
const servers = [];
const uwsServers = [];
Config.get("listen").forEach(function (bind) {
if (!bind.io) {
if (bind.io && bind.uws) {
throw new Error(
'Cannot bind both socket.io and uws to the same listener'
);
} else if (!bind.io && !bind.uws) {
return;
}
const serverList = bind.io ? servers : uwsServers;
const id = bind.ip + ":" + bind.port;
if (uniqueListenAddresses.has(id)) {
LOGGER.warn("Ignoring duplicate listen address %s", id);
@ -438,16 +447,16 @@ module.exports = {
}
if (srv.servers.hasOwnProperty(id)) {
servers.push(srv.servers[id]);
serverList.push(srv.servers[id]);
} else {
const server = http.createServer().listen(bind.port, bind.ip);
servers.push(server);
serverList.push(server);
}
uniqueListenAddresses.add(id);
});
ioServer.bindTo(servers);
ioServer.bindTo(servers, uwsServers);
},
IOServer: IOServer,

View File

@ -165,18 +165,26 @@ class UWSServer extends EventEmitter {
constructor() {
super();
this._server = new uws.Server({ port: 3000, host: '127.0.0.1' });
this._servers = [];
this._middleware = [];
this._server.on('connection', socket => this._onConnection(socket));
this._server.on('listening', () => this.emit('listening'));
this._server.on('error', e => this.emit('error', e));
}
use(cb) {
this._middleware.push(cb);
}
attach(server) {
const uwsServer = new uws.Server({
server,
perMessageDeflate: false
});
this._servers.push(uwsServer);
uwsServer.on('connection', socket => this._onConnection(socket));
server.on('listening', () => this.emit('listening'));
uwsServer.on('error', e => this.emit('error', e));
}
_onConnection(uwsSocket) {
const socket = new UWSWrapper(uwsSocket);
@ -212,7 +220,7 @@ class UWSServer extends EventEmitter {
}
shutdown() {
this._server.close();
this._servers.forEach(sv => sv.close());
}
}

View File

@ -3,14 +3,20 @@ const assert = require('assert');
const { UWSServer } = require('../../lib/io/uws');
const inRoom = require('../../lib/io/uws')['in'];
const WebSocket = require('uws');
const http = require('http');
describe('UWSServer', () => {
const endpoint = 'ws://127.0.0.1:3000';
let httpServer;
let server;
let socket;
beforeEach(done => {
httpServer = http.createServer();
httpServer.listen(3000);
server = new UWSServer();
server.attach(httpServer);
server.on('error', e => { throw e; });
server.once('listening', done);
});
@ -38,6 +44,8 @@ describe('UWSServer', () => {
socket = null;
if (server) server.shutdown();
server = null;
if (httpServer) httpServer.close();
httpServer = null;
});
it('accepts a connection immediately if there is no middleware', done => {

View File

@ -1221,7 +1221,19 @@ function ioServerConnect(socketConfig) {
var USING_LETS_ENCRYPT = false;
function initSocket(socketConfig) {
if (socketConfig.uwsServers && socketConfig.uwsServers.length > 0) {
initWS(socketConfig.uwsServers);
} else {
initSocketIO(socketConfig);
}
setupCallbacks();
}
function initSocketIO(socketConfig) {
console.log('Using socket.io');
function genericConnectionError() {
var message = "The socket.io library could not be loaded from <code>" +
source + "</code>. Ensure that it is not being blocked " +
@ -1295,16 +1307,16 @@ function checkLetsEncrypt(socketConfig, nonLetsEncryptError) {
});
}
function initWS() {
window.socket = new WSShim('ws://localhost:3000/');
setupCallbacks();
function initWS(servers) {
console.log('Using WSShim');
console.log("Connecting to " + JSON.stringify(servers[0]));
window.socket = new WSShim(servers[0].url);
}
(function () {
$.getJSON("/socketconfig/" + CHANNEL.name + ".json")
.done(function (socketConfig) {
//initSocketIO(socketConfig);
initWS();
initSocket(socketConfig);
}).fail(function () {
makeAlert("Error", "Failed to retrieve socket.io configuration. " +
"Please try again in a few minutes.",

View File

@ -113,7 +113,6 @@
WSShim.prototype._onmessage = function _onmessage(message) {
try {
var parsed = JSON.parse(message.data);
console.log(parsed);
var type = parsed.type;
var frame = parsed.frame;
var payload = parsed.payload;