diff --git a/lib/channel.js b/lib/channel.js index d1fada54..89e2baa6 100644 --- a/lib/channel.js +++ b/lib/channel.js @@ -897,7 +897,7 @@ Channel.prototype.userJoin = function(user, password) { user.saverank = true; user.rank = rank; } - user.socket.emit("rank", rank); + user.socket.emit("rank", user.rank); self.broadcastNewUser(user); }); } diff --git a/lib/database.js b/lib/database.js index 28768a87..eb7bb944 100644 --- a/lib/database.js +++ b/lib/database.js @@ -7,7 +7,6 @@ var Logger = require("./logger"); var cfg = {}; var pool = null; var global_ipbans = {}; -var users = null; module.exports.init = function (cfg) { cfg = cfg; @@ -31,8 +30,8 @@ module.exports.init = function (cfg) { }); global_ipbans = {}; - users = require("./database/accounts"); - users.init(); + module.exports.users = require("./database/accounts"); + module.exports.users.init(); }; module.exports.query = function (query, sub, callback) { diff --git a/lib/io/ioserver.js b/lib/io/ioserver.js new file mode 100644 index 00000000..acd71e72 --- /dev/null +++ b/lib/io/ioserver.js @@ -0,0 +1,133 @@ +var sio = require("socket.io"); +var parseCookie = require("cookie").parse; +var Logger = require("../logger"); +var db = require("../database"); +var User = require("../user"); +var Server = require("../server"); +var $util = require("../utilities"); + +var CONNECT_RATE = { + burst: 5, + sustained: 0.1 +}; + +// Keep track of rate limiting by IP +var ipThrottle = {}; +// Keep track of number of connections per IP +var ipCount = {}; + +/** + * Called before an incoming socket.io connection is accepted. + */ +function handleAuth(data, accept) { + data.user = false; + if (data.headers.cookie) { + data.cookie = parseCookie(data.headers.cookie); + var auth = data.cookie.auth; + db.users.verifyAuth(auth, function (err, user) { + if (!err) { + console.log('VERIFIED: ' + user.name + ' => ' + user.global_rank); + data.user = { + name: user.name, + global_rank: user.global_rank + }; + } else { + console.log('Auth fail: ' + err); + } + accept(null, true); + }); + } else { + accept(null, true); + } +} + +/** + * Called after a connection is accepted + */ +function handleConnection(sock) { + sock._ip = sock.handshake.address.address; + var ip = sock._ip; + var srv = Server.getServer(); + if (srv.torblocker && srv.torblocker.shouldBlockIP(ip)) { + sock.emit("kick", { + reason: "This server does not allow connections from Tor. "+ + "Please log in with your regular internet connection." + }); + Logger.syslog.log("Blocked Tor IP: " + ip); + sock.disconnect(true); + return; + } + + if (!(ip in ipThrottle)) { + ipThrottle[ip] = $util.newRateLimiter(); + } + + if (ipThrottle[ip].throttle(CONNECT_RATE)) { + Logger.syslog.log("WARN: IP throttled: " + ip); + sock.emit("kick", { + reason: "Your IP address is connecting too quickly. Please "+ + "wait 10 seconds before joining again." + }); + return; + } + + // Check for global ban on the IP + db.isGlobalIPBanned(ip, function (err, banned) { + if (banned) { + Logger.syslog.log("Disconnecting " + ip + " - global banned"); + sock.emit("kick", { reason: "Your IP is globally banned." }); + sock.disconnect(true); + } + }); + + sock.on("disconnect", function () { + ipCount[ip]--; + }); + + if (!(ip in ipCount)) { + ipCount[ip] = 0; + } + + ipCount[ip]++; + if (ipCount[ip] > srv.cfg["ip-connection-limit"]) { + sock.emit("kick", { + reason: "Too many connections from your IP address" + }); + sock.disconnect(true); + return; + } + + Logger.syslog.log("Accepted socket from " + ip); + var user = new User(sock); + if (sock.handshake.user) { + user.name = sock.handshake.user.name; + user.global_rank = sock.handshake.user.global_rank; + user.loggedIn = true; + } +} + +module.exports = { + init: function (srv) { + var ioport = srv.cfg["io-port"]; + var webport = srv.cfg["web-port"]; + var app; + if (ioport !== webport) { + app = require("express")().listen(ioport, srv.cfg["express-host"]); + srv.ioWeb = app; + } else { + app = srv.express; + } + + srv.io = sio.listen(app); + srv.io.set("log level", 1); + srv.io.set("authorization", handleAuth); + srv.io.on("connection", handleConnection); + + if (srv.cfg["enable-ssl"]) { + srv.ioSecure = sio.listen(srv.https); + srv.ioSecure.set("log level", 1); + srv.ioSecure.set("authorization", handleAuth); + srv.ioSecure.on("connection", handleConnection); + } + } +}; diff --git a/lib/server.js b/lib/server.js index bbca30da..95a0be93 100644 --- a/lib/server.js +++ b/lib/server.js @@ -56,8 +56,6 @@ var Server = function (cfg) { self.io = null; self.ioWeb = null; self.ioSecure = null; - self.ipCount = {}; - self.ipThrottle = {}; self.db = null; self.api = null; self.announcement = null; @@ -170,21 +168,19 @@ var Server = function (cfg) { self.https = https.createServer(opts, self.express) .listen(self.cfg["ssl-port"]); - self.ioSecure = require("socket.io").listen(self.https); - self.ioSecure.set("log level", 1); - self.ioSecure.on("connection", function (sock) { - self.handleSocketConnection(sock); - }); } self.http = self.express.listen(self.cfg["web-port"], self.cfg["express-host"]); + /* self.ioWeb = express().listen(self.cfg["io-port"], self.cfg["io-host"]); self.io = require("socket.io").listen(self.ioWeb); self.io.set("log level", 1); self.io.sockets.on("connection", function (sock) { self.handleSocketConnection(sock); }); + */ + require("./io/ioserver").init(self); // background tasks init ---------------------------------------------- require("./bgtask")(self); @@ -277,68 +273,6 @@ Server.prototype.logHTTP = function (req, status) { ].join(" ")); }; -const IP_THROTTLE = { - burst: 5, - sustained: 0.1 -}; - -Server.prototype.handleSocketConnection = function (socket) { - var self = this; - var ip = self.getSocketIP(socket); - socket._ip = ip; - - if (self.torblocker && self.torblocker.shouldBlockIP(ip)) { - socket.emit("kick", { - reason: "This server does not allow connections from Tor. "+ - "Please log in with your regular internet connection." - }); - Logger.syslog.log("Blocked Tor IP: " + ip); - socket.disconnect(true); - return; - } - - if (!(ip in self.ipThrottle)) { - self.ipThrottle[ip] = $util.newRateLimiter(); - } - - if (self.ipThrottle[ip].throttle(IP_THROTTLE)) { - Logger.syslog.log("WARN: IP throttled: " + ip); - socket.emit("kick", { - reason: "Your IP address is connecting too quickly. Please "+ - "wait 10 seconds before joining again." - }); - return; - } - - // Check for global ban on the IP - self.db.isGlobalIPBanned(ip, function (err, banned) { - if (banned) { - Logger.syslog.log("Disconnecting " + ip + " - global banned"); - socket.emit("kick", { reason: "Your IP is globally banned." }); - socket.disconnect(true); - } - }); - - socket.on("disconnect", function () { - self.ipCount[ip]--; - }); - - if (!(ip in self.ipCount)) - self.ipCount[ip] = 0; - - self.ipCount[ip]++; - if (self.ipCount[ip] > self.cfg["ip-connection-limit"]) { - socket.emit("kick", { - reason: "Too many connections from your IP address" - }); - socket.disconnect(true); - return; - } - - Logger.syslog.log("Accepted socket from " + ip); - new User(socket); -}; - Server.prototype.shutdown = function () { Logger.syslog.log("Unloading channels"); for (var i = 0; i < this.channels.length; i++) { diff --git a/lib/web/auth.js b/lib/web/auth.js index 40ac3123..b2fc7e1b 100644 --- a/lib/web/auth.js +++ b/lib/web/auth.js @@ -11,7 +11,7 @@ var webserver = require('./webserver'); var sendJade = require('./jade').sendJade; var Logger = require('../logger'); var $util = require('../utilities'); -var Server = require('../server'); +var db = require('../database'); /** * Processes a login request. Sets a cookie upon successful authentication @@ -27,7 +27,7 @@ function handleLogin(req, res) { password = password.substring(0, 100); - Server.getServer().db.users.verifyLogin(name, password, function (err, user) { + db.users.verifyLogin(name, password, function (err, user) { if (err) { if (err === 'Invalid username/password combination') { Logger.eventlog('Login failed (bad password): ' + name @@ -141,7 +141,7 @@ function handleRegister(req, res) { return; } - Server.getServer().db.users.register({ + db.users.register({ name: name, password: password, email: email, diff --git a/templates/channel.jade b/templates/channel.jade index 2fb1cd42..084c0951 100644 --- a/templates/channel.jade +++ b/templates/channel.jade @@ -3,6 +3,7 @@ html(lang="en") head include head +head() + link(href="//code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css", rel="stylesheet") body #wrap nav.navbar.navbar-inverse.navbar-fixed-top(role="navigation") @@ -170,6 +171,7 @@ html(lang="en") button.btn.btn-default(type="button", data-dismiss="modal") Close include footer +footer() + script(src="//code.jquery.com/ui/1.10.3/jquery-ui.js") script(src="/assets/js/iourl.js") //script(src="#{ioUrl}/socket.io/socket.io.js") //script(type="text/javascript"). diff --git a/www/assets/js/callbacks.js b/www/assets/js/callbacks.js index 4bd7f856..9ec52682 100644 --- a/www/assets/js/callbacks.js +++ b/www/assets/js/callbacks.js @@ -49,6 +49,7 @@ Callbacks = { if (CHANNEL.opts.password) { socket.emit("channelPassword", CHANNEL.opts.password); } + /* if(NAME && SESSION) { socket.emit("login", { name: NAME, @@ -61,6 +62,7 @@ Callbacks = { name: CLIENT.name }); } + */ $("
").addClass("server-msg-reconnect") .text("Connected") .appendTo($("#messagebuffer")); diff --git a/www/assets/js/ui.js b/www/assets/js/ui.js index 6f341ffe..1226954e 100644 --- a/www/assets/js/ui.js +++ b/www/assets/js/ui.js @@ -478,7 +478,7 @@ $(window).resize(function() { /* load channel */ var loc = document.location+""; -var m = loc.match(/\/old\/([a-zA-Z0-9-_]+)$/); +var m = loc.match(/\/r\/([a-zA-Z0-9-_]+)$/); if(m) { CHANNEL.name = m[1]; } diff --git a/www/css/cytube.css b/www/css/cytube.css index 492883a8..dbb0d445 100644 --- a/www/css/cytube.css +++ b/www/css/cytube.css @@ -124,10 +124,6 @@ margin-top: 5px; } -#logoutform { - display: none; -} - #drinkbar { margin-left: 0; background-color: #000000;