2020-12-08 03:20:59 -05:00
|
|
|
'use strict';
|
|
|
|
|
2020-11-23 13:24:19 -05:00
|
|
|
const express = require('../express');
|
2020-10-06 19:44:34 -04:00
|
|
|
const proxyaddr = require('proxy-addr');
|
2020-11-23 13:24:19 -05:00
|
|
|
const settings = require('../../utils/Settings');
|
|
|
|
const socketio = require('socket.io');
|
|
|
|
const socketIORouter = require('../../handler/SocketIORouter');
|
2020-12-08 03:20:59 -05:00
|
|
|
const hooks = require('../../../static/js/pluginfw/hooks');
|
2020-11-23 13:24:19 -05:00
|
|
|
const padMessageHandler = require('../../handler/PadMessageHandler');
|
2020-12-07 15:48:28 -05:00
|
|
|
const util = require('util');
|
|
|
|
|
|
|
|
let io;
|
|
|
|
|
|
|
|
exports.expressCloseServer = async () => {
|
|
|
|
// According to the socket.io documentation every client is always in the default namespace (and
|
|
|
|
// may also be in other namespaces).
|
|
|
|
const ns = io.sockets; // The Namespace object for the default namespace.
|
|
|
|
// Disconnect all socket.io clients. This probably isn't necessary; closing the socket.io Engine
|
|
|
|
// (see below) probably gracefully disconnects all clients. But that is not documented, and this
|
|
|
|
// doesn't seem to hurt, so hedge against surprising and undocumented socket.io behavior.
|
|
|
|
for (const id of await util.promisify(ns.clients.bind(ns))()) {
|
|
|
|
ns.connected[id].disconnect(true);
|
|
|
|
}
|
|
|
|
// Don't call io.close() because that closes the underlying HTTP server, which is already done
|
|
|
|
// elsewhere. (Closing an HTTP server twice throws an exception.) The `engine` property of
|
|
|
|
// socket.io Server objects is undocumented, but I don't see any other way to shut down socket.io
|
|
|
|
// without also closing the HTTP server.
|
|
|
|
io.engine.close();
|
|
|
|
};
|
2012-02-25 16:44:37 +01:00
|
|
|
|
2020-12-08 03:20:59 -05:00
|
|
|
exports.expressCreateServer = (hookName, args, cb) => {
|
2020-11-23 13:24:19 -05:00
|
|
|
// init socket.io and redirect all requests to the MessageHandler
|
2014-11-25 22:38:22 +01:00
|
|
|
// there shouldn't be a browser that isn't compatible to all
|
|
|
|
// transports in this list at once
|
|
|
|
// e.g. XHR is disabled in IE by default, so in IE it should use jsonp-polling
|
2020-12-07 15:48:28 -05:00
|
|
|
io = socketio({
|
2020-11-23 13:24:19 -05:00
|
|
|
transports: settings.socketTransportProtocols,
|
2019-12-07 04:20:12 +01:00
|
|
|
}).listen(args.server, {
|
|
|
|
/*
|
|
|
|
* Do not set the "io" cookie.
|
|
|
|
*
|
|
|
|
* The "io" cookie is created by socket.io, and its purpose is to offer an
|
|
|
|
* handle to perform load balancing with session stickiness when the library
|
|
|
|
* falls back to long polling or below.
|
|
|
|
*
|
|
|
|
* In Etherpad's case, if an operator needs to load balance, he can use the
|
|
|
|
* "express_sid" cookie, and thus "io" is of no use.
|
|
|
|
*
|
|
|
|
* Moreover, socket.io API does not offer a way of setting the "secure" flag
|
|
|
|
* on it, and thus is a liability.
|
|
|
|
*
|
|
|
|
* Let's simply nuke "io".
|
|
|
|
*
|
|
|
|
* references:
|
|
|
|
* https://socket.io/docs/using-multiple-nodes/#Sticky-load-balancing
|
|
|
|
* https://github.com/socketio/socket.io/issues/2276#issuecomment-147184662 (not totally true, actually, see above)
|
|
|
|
*/
|
|
|
|
cookie: false,
|
|
|
|
});
|
2012-02-25 16:44:37 +01:00
|
|
|
|
2020-10-03 18:00:04 -04:00
|
|
|
io.use((socket, next) => {
|
2020-09-23 17:13:07 -04:00
|
|
|
const req = socket.request;
|
2020-10-06 19:44:34 -04:00
|
|
|
// Express sets req.ip but socket.io does not. Replicate Express's behavior here.
|
|
|
|
if (req.ip == null) {
|
|
|
|
if (settings.trustProxy) {
|
|
|
|
req.ip = proxyaddr(req, args.app.get('trust proxy fn'));
|
|
|
|
} else {
|
|
|
|
req.ip = socket.handshake.address;
|
|
|
|
}
|
|
|
|
}
|
2020-09-23 17:13:07 -04:00
|
|
|
if (!req.headers.cookie) {
|
2020-09-14 00:39:10 -04:00
|
|
|
// socketio.js-client on node.js doesn't support cookies (see https://git.io/JU8u9), so the
|
|
|
|
// token and express_sid cookies have to be passed via a query parameter for unit tests.
|
2020-09-23 17:13:07 -04:00
|
|
|
req.headers.cookie = socket.handshake.query.cookie;
|
2020-09-14 00:39:10 -04:00
|
|
|
}
|
2020-10-03 18:00:04 -04:00
|
|
|
// See: https://socket.io/docs/faq/#Usage-with-express-session
|
2020-10-03 18:10:00 -04:00
|
|
|
express.sessionMiddleware(req, {}, next);
|
2012-04-19 14:25:12 +02:00
|
|
|
});
|
|
|
|
|
2014-11-04 19:11:06 +00:00
|
|
|
// var socketIOLogger = log4js.getLogger("socket.io");
|
|
|
|
// Debug logging now has to be set at an environment level, this is stupid.
|
|
|
|
// https://github.com/Automattic/socket.io/wiki/Migrating-to-1.0
|
|
|
|
// This debug logging environment is set in Settings.js
|
2012-02-25 16:44:37 +01:00
|
|
|
|
2020-11-23 13:24:19 -05:00
|
|
|
// minify socket.io javascript
|
2014-11-04 23:25:18 +00:00
|
|
|
// Due to a shitty decision by the SocketIO team minification is
|
|
|
|
// no longer available, details available at:
|
|
|
|
// http://stackoverflow.com/questions/23981741/minify-socket-io-socket-io-js-with-1-0
|
|
|
|
// if(settings.minify) io.enable('browser client minification');
|
2019-04-16 00:34:29 +02:00
|
|
|
|
2021-02-03 00:30:07 +01:00
|
|
|
// Initialize the Socket.IO Router
|
2012-02-25 16:44:37 +01:00
|
|
|
socketIORouter.setSocketIO(io);
|
2020-11-23 13:24:19 -05:00
|
|
|
socketIORouter.addComponent('pad', padMessageHandler);
|
2012-02-25 16:44:37 +01:00
|
|
|
|
2020-11-23 13:24:19 -05:00
|
|
|
hooks.callAll('socketio', {app: args.app, io, server: args.server});
|
2020-10-10 22:51:26 -04:00
|
|
|
|
|
|
|
return cb();
|
2020-11-23 13:24:19 -05:00
|
|
|
};
|