2013-07-19 20:27:21 +00:00
|
|
|
var path = require("path");
|
2013-04-17 18:42:29 +00:00
|
|
|
var express = require("express");
|
2013-07-15 22:57:33 +00:00
|
|
|
var Config = require("./config");
|
|
|
|
var Logger = require("./logger");
|
|
|
|
var Channel = require("./channel");
|
|
|
|
var User = require("./user");
|
2013-04-22 19:42:39 +00:00
|
|
|
|
2013-07-15 22:57:33 +00:00
|
|
|
const VERSION = "2.1.0";
|
2013-04-25 16:00:06 +00:00
|
|
|
|
2013-07-15 22:57:33 +00:00
|
|
|
function getIP(req) {
|
2013-07-06 17:00:02 +00:00
|
|
|
var raw = req.connection.remoteAddress;
|
2013-06-04 03:56:06 +00:00
|
|
|
var forward = req.header("x-forwarded-for");
|
2013-07-06 17:00:02 +00:00
|
|
|
if(Config.REVERSE_PROXY && forward) {
|
2013-07-15 22:57:33 +00:00
|
|
|
var ip = forward.split(",")[0];
|
|
|
|
Logger.syslog.log("REVPROXY " + raw + " => " + ip);
|
2013-07-06 17:00:02 +00:00
|
|
|
return ip;
|
2013-06-04 03:56:06 +00:00
|
|
|
}
|
2013-07-06 17:00:02 +00:00
|
|
|
return raw;
|
2013-06-04 03:56:06 +00:00
|
|
|
}
|
|
|
|
|
2013-06-26 14:57:56 +00:00
|
|
|
function getSocketIP(socket) {
|
2013-07-06 17:00:02 +00:00
|
|
|
var raw = socket.handshake.address.address;
|
|
|
|
if(Config.REVERSE_PROXY) {
|
|
|
|
if(typeof socket.handshake.headers["x-forwarded-for"] == "string") {
|
2013-07-15 22:57:33 +00:00
|
|
|
var ip = socket.handshake.headers["x-forwarded-for"]
|
|
|
|
.split(",")[0];
|
|
|
|
Logger.syslog.log("REVPROXY " + raw + " => " + ip);
|
2013-07-06 17:00:02 +00:00
|
|
|
return ip;
|
|
|
|
}
|
|
|
|
}
|
2013-07-15 22:57:33 +00:00
|
|
|
return raw;
|
2013-06-26 14:57:56 +00:00
|
|
|
}
|
|
|
|
|
2013-07-15 22:57:33 +00:00
|
|
|
var Server = {
|
|
|
|
channels: [],
|
|
|
|
channelLoaded: function (name) {
|
|
|
|
for(var i in this.channels) {
|
2013-07-16 16:12:00 +00:00
|
|
|
if(this.channels[i].name.toLowerCase() == name.toLowerCase())
|
2013-07-15 22:57:33 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
},
|
|
|
|
getChannel: function (name) {
|
|
|
|
for(var i in this.channels) {
|
2013-07-16 16:12:00 +00:00
|
|
|
if(this.channels[i].name.toLowerCase() == name.toLowerCase())
|
2013-07-15 22:57:33 +00:00
|
|
|
return this.channels[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
var c = new Channel(name, this);
|
|
|
|
this.channels.push(c);
|
|
|
|
return c;
|
|
|
|
},
|
|
|
|
unloadChannel: function(chan) {
|
|
|
|
if(chan.registered)
|
|
|
|
chan.saveDump();
|
|
|
|
chan.playlist.die();
|
|
|
|
for(var i in this.channels) {
|
2013-07-16 16:12:00 +00:00
|
|
|
if(this.channels[i].name.toLowerCase() == chan.name.toLowerCase()) {
|
2013-07-15 22:57:33 +00:00
|
|
|
this.channels.splice(i, 1);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2013-07-16 15:56:33 +00:00
|
|
|
//for(var i in chan)
|
|
|
|
// delete chan[i];
|
2013-07-15 22:57:33 +00:00
|
|
|
},
|
2013-07-16 18:57:34 +00:00
|
|
|
stats: null,
|
2013-07-15 22:57:33 +00:00
|
|
|
app: null,
|
|
|
|
io: null,
|
|
|
|
httpserv: null,
|
|
|
|
ioserv: null,
|
|
|
|
db: null,
|
|
|
|
ips: {},
|
2013-07-16 03:01:12 +00:00
|
|
|
acp: null,
|
2013-07-15 22:57:33 +00:00
|
|
|
init: function () {
|
|
|
|
this.app = express();
|
|
|
|
// channel path
|
|
|
|
this.app.get("/r/:channel(*)", function (req, res, next) {
|
|
|
|
var c = req.params.channel;
|
|
|
|
if(!c.match(/^[\w-_]+$/))
|
|
|
|
res.redirect("/" + c);
|
|
|
|
else
|
|
|
|
res.sendfile(__dirname + "/www/channel.html");
|
2013-04-28 06:06:58 +00:00
|
|
|
});
|
2013-03-28 23:51:08 +00:00
|
|
|
|
2013-07-15 22:57:33 +00:00
|
|
|
// api path
|
|
|
|
this.api = require("./api")(this);
|
|
|
|
this.app.get("/api/:apireq(*)", function (req, res, next) {
|
|
|
|
this.api.handle(req.url.substring(5), req, res);
|
2013-07-16 15:46:09 +00:00
|
|
|
}.bind(this));
|
2013-03-28 23:51:08 +00:00
|
|
|
|
2013-07-20 01:59:39 +00:00
|
|
|
this.app.get("/", function (req, res, next) {
|
|
|
|
res.sendfile(__dirname + "/www/index.html");
|
|
|
|
});
|
|
|
|
|
2013-07-15 22:57:33 +00:00
|
|
|
// default path
|
|
|
|
this.app.get("/:thing(*)", function (req, res, next) {
|
2013-07-20 16:02:08 +00:00
|
|
|
while(req.params.thing.indexOf("%25") != -1)
|
|
|
|
req.params.thing = decodeURIComponent(req.params.thing);
|
|
|
|
req.params.thing = decodeURIComponent(req.params.thing);
|
2013-07-19 20:27:21 +00:00
|
|
|
var root = __dirname + "/www/",
|
|
|
|
answer = path.resolve (__dirname + "/www/", req.params.thing);
|
|
|
|
if (answer.indexOf (root) != 0)
|
|
|
|
res.send (404);
|
|
|
|
else
|
|
|
|
res.sendfile(__dirname + "/www/" + req.params.thing);
|
2013-07-15 22:57:33 +00:00
|
|
|
});
|
2013-03-28 23:51:08 +00:00
|
|
|
|
2013-07-15 22:57:33 +00:00
|
|
|
// fallback
|
|
|
|
this.app.use(function (err, req, res, next) {
|
|
|
|
if(err.status == 404) {
|
|
|
|
res.send(404);
|
|
|
|
} else {
|
|
|
|
next(err);
|
|
|
|
}
|
|
|
|
});
|
2013-05-03 18:15:05 +00:00
|
|
|
|
2013-07-15 22:57:33 +00:00
|
|
|
// bind servers
|
|
|
|
this.httpserv = this.app.listen(Config.WEBSERVER_PORT);
|
|
|
|
this.ioserv = express().listen(Config.IO_PORT);
|
|
|
|
|
|
|
|
// init socket.io
|
|
|
|
this.io = require("socket.io").listen(this.ioserv);
|
|
|
|
this.io.set("log level", 1);
|
|
|
|
this.io.sockets.on("connection", function (socket) {
|
|
|
|
var ip = getSocketIP(socket);
|
|
|
|
socket._ip = ip;
|
|
|
|
if(this.db.checkGlobalBan(ip)) {
|
|
|
|
Logger.syslog.log("Disconnecting " + ip + " - gbanned");
|
|
|
|
socket.emit("kick", {
|
|
|
|
reason: "You're globally banned."
|
|
|
|
});
|
|
|
|
socket.disconnect(true);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
socket.on("disconnect", function () {
|
|
|
|
this.ips[ip]--;
|
2013-07-16 15:46:09 +00:00
|
|
|
}.bind(this));
|
2013-07-15 22:57:33 +00:00
|
|
|
|
|
|
|
if(!(ip in this.ips))
|
|
|
|
this.ips[ip] = 0;
|
|
|
|
this.ips[ip]++;
|
|
|
|
|
|
|
|
if(this.ips[ip] > Config.MAX_PER_IP) {
|
|
|
|
socket.emit("kick", {
|
|
|
|
reason: "Too many connections from your IP address"
|
|
|
|
});
|
|
|
|
socket.disconnect(true);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// finally a valid user
|
|
|
|
Logger.syslog.log("Accepted socket from /" + socket._ip);
|
|
|
|
new User(socket, this);
|
2013-07-16 03:01:12 +00:00
|
|
|
}.bind(this));
|
2013-07-14 02:19:47 +00:00
|
|
|
|
2013-07-15 22:57:33 +00:00
|
|
|
// init database
|
|
|
|
this.db = require("./database");
|
|
|
|
this.db.setup(Config);
|
|
|
|
this.db.init();
|
2013-07-16 03:01:12 +00:00
|
|
|
|
|
|
|
// init ACP
|
|
|
|
this.acp = require("./acp")(this);
|
2013-07-16 18:57:34 +00:00
|
|
|
|
|
|
|
// init stats
|
|
|
|
this.stats = require("./stats")(this);
|
2013-07-15 22:57:33 +00:00
|
|
|
},
|
|
|
|
shutdown: function () {
|
|
|
|
Logger.syslog.log("Unloading channels");
|
|
|
|
for(var i in this.channels) {
|
|
|
|
if(this.channels[i].registered)
|
|
|
|
this.channels[i].saveDump();
|
|
|
|
}
|
|
|
|
Logger.syslog.log("Goodbye");
|
|
|
|
process.exit(0);
|
|
|
|
}
|
|
|
|
};
|
2013-07-14 02:19:47 +00:00
|
|
|
|
2013-07-15 22:57:33 +00:00
|
|
|
Logger.syslog.log("Starting CyTube v" + VERSION);
|
|
|
|
Server.init();
|
2013-07-14 02:19:47 +00:00
|
|
|
|
2013-07-15 22:57:33 +00:00
|
|
|
if(!Config.DEBUG) {
|
|
|
|
process.on("uncaughtException", function (err) {
|
|
|
|
Logger.errlog.log("[SEVERE] Uncaught Exception: " + err);
|
|
|
|
Logger.errlog.log(err.stack);
|
|
|
|
});
|
2013-07-14 02:19:47 +00:00
|
|
|
|
2013-07-20 02:07:25 +00:00
|
|
|
process.on("SIGINT", Server.shutdown);
|
2013-05-03 18:15:05 +00:00
|
|
|
}
|