From 4f3a962f7fe3636094c4b5062ca6236e3448453f Mon Sep 17 00:00:00 2001 From: Aziz Khoury Date: Fri, 15 Apr 2016 16:42:22 -0400 Subject: [PATCH] what did i do? --- src/socket.io/index.js | 336 ++++++++++++++++++++--------------------- 1 file changed, 160 insertions(+), 176 deletions(-) diff --git a/src/socket.io/index.js b/src/socket.io/index.js index 4092b576bf..809f21ea11 100644 --- a/src/socket.io/index.js +++ b/src/socket.io/index.js @@ -8,227 +8,211 @@ var cookieParser = require('cookie-parser')(nconf.get('secret')); var winston = require('winston'); var db = require('../database'); -var user = require('../user'); var logger = require('../logger'); var ratelimit = require('../middleware/ratelimit'); -var cls = require('../middleware/cls'); -var io; +var Sockets = {}; +var Namespaces = {}; -(function(Sockets) { - var Namespaces = {}; +var io; - Sockets.init = function(server) { - requireModules(); +Sockets.init = function(server) { + requireModules(); - io = new SocketIO({ - path: nconf.get('relative_path') + '/socket.io' - }); + io = new SocketIO({ + path: nconf.get('relative_path') + '/socket.io' + }); - addRedisAdapter(io); + addRedisAdapter(io); - io.use(socketioWildcard); - io.use(authorize); + io.use(socketioWildcard); + io.use(authorize); - io.on('connection', onConnection); + io.on('connection', onConnection); - io.on('disconnect', function(data) { - onDisconnect(io, data); - }); + io.listen(server, { + transports: nconf.get('socket.io:transports') + }); - io.listen(server, { - transports: nconf.get('socket.io:transports') - }); + Sockets.server = io; +}; - Sockets.server = io; - }; +function onConnection(socket) { + socket.ip = socket.request.headers['x-forwarded-for'] || socket.request.connection.remoteAddress; - function onConnection(socket) { - socket.ip = socket.request.headers['x-forwarded-for'] || socket.request.connection.remoteAddress; + logger.io_one(socket, socket.uid); - logger.io_one(socket, socket.uid); + onConnect(socket); - cls.socket(socket, null, 'connection', function () { - onConnect(socket); - }); + socket.on('*', function(payload) { + onMessage(socket, payload); + }); +} - socket.on('*', function(payload) { - cls.socket(socket, payload, null, function() { - onMessage(socket, payload); - }); - }); +function onConnect(socket) { + if (socket.uid) { + socket.join('uid_' + socket.uid); + socket.join('online_users'); + } else { + socket.join('online_guests'); } +} - function onConnect(socket) { - if (socket.uid) { - socket.join('uid_' + socket.uid); - socket.join('online_users'); - } else { - socket.join('online_guests'); - } + +function onMessage(socket, payload) { + if (!payload.data.length) { + return winston.warn('[socket.io] Empty payload'); } - function onDisconnect(socket) { - cls.socket(socket, null, 'disconnect', function() {}); + var eventName = payload.data[0]; + var params = payload.data[1]; + var callback = typeof payload.data[payload.data.length - 1] === 'function' ? payload.data[payload.data.length - 1] : function() {}; + + if (!eventName) { + return winston.warn('[socket.io] Empty method name'); } + var parts = eventName.toString().split('.'); + var namespace = parts[0]; + var methodToCall = parts.reduce(function(prev, cur) { + if (prev !== null && prev[cur]) { + return prev[cur]; + } else { + return null; + } + }, Namespaces); - function onMessage(socket, payload) { - if (!payload.data.length) { - return winston.warn('[socket.io] Empty payload'); + if(!methodToCall) { + if (process.env.NODE_ENV === 'development') { + winston.warn('[socket.io] Unrecognized message: ' + eventName); } + return; + } - var eventName = payload.data[0]; - var params = payload.data[1]; - var callback = typeof payload.data[payload.data.length - 1] === 'function' ? payload.data[payload.data.length - 1] : function() {}; + socket.previousEvents = socket.previousEvents || []; + socket.previousEvents.push(eventName); + if (socket.previousEvents.length > 20) { + socket.previousEvents.shift(); + } - if (!eventName) { - return winston.warn('[socket.io] Empty method name'); - } + if (!eventName.startsWith('admin.') && ratelimit.isFlooding(socket)) { + winston.warn('[socket.io] Too many emits! Disconnecting uid : ' + socket.uid + '. Events : ' + socket.previousEvents); + return socket.disconnect(); + } - var parts = eventName.toString().split('.'); - var namespace = parts[0]; - var methodToCall = parts.reduce(function(prev, cur) { - if (prev !== null && prev[cur]) { - return prev[cur]; + async.waterfall([ + function (next) { + validateSession(socket, next); + }, + function (next) { + if (Namespaces[namespace].before) { + Namespaces[namespace].before(socket, eventName, params, next); } else { - return null; - } - }, Namespaces); - - if(!methodToCall) { - if (process.env.NODE_ENV === 'development') { - winston.warn('[socket.io] Unrecognized message: ' + eventName); + next(); } - return; - } - - socket.previousEvents = socket.previousEvents || []; - socket.previousEvents.push(eventName); - if (socket.previousEvents.length > 20) { - socket.previousEvents.shift(); + }, + function (next) { + methodToCall(socket, params, next); } - - if (!eventName.startsWith('admin.') && ratelimit.isFlooding(socket)) { - winston.warn('[socket.io] Too many emits! Disconnecting uid : ' + socket.uid + '. Events : ' + socket.previousEvents); - return socket.disconnect(); + ], function(err, result) { + callback(err ? {message: err.message} : null, result); + }); +} + +function requireModules() { + var modules = ['admin', 'categories', 'groups', 'meta', 'modules', + 'notifications', 'plugins', 'posts', 'topics', 'user', 'blacklist' + ]; + + modules.forEach(function(module) { + Namespaces[module] = require('./' + module); + }); +} + +function validateSession(socket, callback) { + var req = socket.request; + if (!req.signedCookies || !req.signedCookies['express.sid']) { + return callback(new Error('[[error:invalid-session]]')); + } + db.sessionStore.get(req.signedCookies['express.sid'], function(err, sessionData) { + if (err || !sessionData) { + return callback(err || new Error('[[error:invalid-session]]')); } - async.waterfall([ - function (next) { - validateSession(socket, next); - }, - function (next) { - if (Namespaces[namespace].before) { - Namespaces[namespace].before(socket, eventName, params, next); - } else { - next(); - } - }, - function (next) { - methodToCall(socket, params, next); - } - ], function(err, result) { - callback(err ? {message: err.message} : null, result); - }); - } + callback(); + }); +} - function requireModules() { - var modules = ['admin', 'categories', 'groups', 'meta', 'modules', - 'notifications', 'plugins', 'posts', 'topics', 'user', 'blacklist' - ]; +function authorize(socket, callback) { + var request = socket.request; - modules.forEach(function(module) { - Namespaces[module] = require('./' + module); - }); + if (!request) { + return callback(new Error('[[error:not-authorized]]')); } - function validateSession(socket, callback) { - var req = socket.request; - if (!req.signedCookies || !req.signedCookies['express.sid']) { - return callback(new Error('[[error:invalid-session]]')); + async.waterfall([ + function(next) { + cookieParser(request, {}, next); + }, + function(next) { + db.sessionStore.get(request.signedCookies['express.sid'], function(err, sessionData) { + if (err) { + return next(err); + } + if (sessionData && sessionData.passport && sessionData.passport.user) { + request.session = sessionData; + socket.uid = parseInt(sessionData.passport.user, 10); + } else { + socket.uid = 0; + } + next(); + }); } - db.sessionStore.get(req.signedCookies['express.sid'], function(err, sessionData) { - if (err || !sessionData) { - return callback(err || new Error('[[error:invalid-session]]')); - } - - callback(); - }); + ], callback); +} + +function addRedisAdapter(io) { + if (nconf.get('redis')) { + var redisAdapter = require('socket.io-redis'); + var redis = require('../database/redis'); + var pub = redis.connect({return_buffers: true}); + var sub = redis.connect({return_buffers: true}); + + io.adapter(redisAdapter({pubClient: pub, subClient: sub})); + } else if (nconf.get('isCluster') === 'true') { + winston.warn('[socket.io] Clustering detected, you are advised to configure Redis as a websocket store.'); } +} - function authorize(socket, callback) { - var request = socket.request; +Sockets.in = function(room) { + return io.in(room); +}; - if (!request) { - return callback(new Error('[[error:not-authorized]]')); - } - - async.waterfall([ - function(next) { - cookieParser(request, {}, next); - }, - function(next) { - db.sessionStore.get(request.signedCookies['express.sid'], function(err, sessionData) { - if (err) { - return next(err); - } - if (sessionData && sessionData.passport && sessionData.passport.user) { - request.session = sessionData; - socket.uid = parseInt(sessionData.passport.user, 10); - } else { - socket.uid = 0; - } - next(); - }); - } - ], callback); +Sockets.getUserSocketCount = function(uid) { + if (!io) { + return 0; } - function addRedisAdapter(io) { - if (nconf.get('redis')) { - var redisAdapter = require('socket.io-redis'); - var redis = require('../database/redis'); - var pub = redis.connect({return_buffers: true}); - var sub = redis.connect({return_buffers: true}); - - io.adapter(redisAdapter({pubClient: pub, subClient: sub})); - } else if (nconf.get('isCluster') === 'true') { - winston.warn('[socket.io] Clustering detected, you are advised to configure Redis as a websocket store.'); - } - } + var room = io.sockets.adapter.rooms['uid_' + uid]; + return room ? room.length : 0; +}; - Sockets.in = function(room) { - return io.in(room); - }; - Sockets.getUserSocketCount = function(uid) { - if (!io) { - return 0; - } +Sockets.reqFromSocket = function(socket) { + var headers = socket.request.headers; + var host = headers.host; + var referer = headers.referer || ''; - var room = io.sockets.adapter.rooms['uid_' + uid]; - return room ? room.length : 0; + return { + ip: headers['x-forwarded-for'] || socket.ip, + host: host, + protocol: socket.request.connection.encrypted ? 'https' : 'http', + secure: !!socket.request.connection.encrypted, + url: referer, + path: referer.substr(referer.indexOf(host) + host.length), + headers: headers }; +}; - Sockets.reqFromSocket = function(socket, payload, event) { - var headers = socket.request.headers; - var host = headers.host; - var referer = headers.referer || ''; - - return { - ip: headers['x-forwarded-for'] || socket.ip, - host: host, - uid: socket.uid, - protocol: socket.request.connection.encrypted ? 'https' : 'http', - secure: !!socket.request.connection.encrypted, - url: referer, - body: {event: event || ((payload || {}).data || [])[0], payload: payload}, - path: referer.substr(referer.indexOf(host) + host.length), - headers: headers, - _socket: socket - }; - }; - -})(exports); \ No newline at end of file +module.exports = Sockets; \ No newline at end of file