sync/lib/io/ioserver.js

142 lines
4.0 KiB
JavaScript

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 Config = require("../config");
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) {
data.user = {
name: user.name,
global_rank: user.global_rank
};
}
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] > Config.get("io.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;
user.emit("login");
user.socket.emit("login", {
success: true,
name: user.name,
guest: false
});
user.socket.emit("rank", user.global_rank);
Logger.syslog.log(ip + " logged in as " + user.name);
} else {
user.socket.emit("rank", -1);
}
}
module.exports = {
init: function (srv) {
var ioport = Config.get("io.port");
var webport = Config.get("http.port");
var app;
if (ioport !== webport) {
app = require("express")().listen(ioport, Config.get("http.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 (Config.get("https.enabled")) {
srv.ioSecure = sio.listen(srv.https);
srv.ioSecure.set("log level", 1);
srv.ioSecure.set("authorization", handleAuth);
srv.ioSecure.on("connection", handleConnection);
}
}
};