sync/src/server.js

280 lines
8.4 KiB
JavaScript
Raw Normal View History

2015-07-06 18:16:02 +00:00
const VERSION = require("../package.json").version;
2013-10-11 21:31:40 +00:00
var singleton = null;
2014-01-22 23:11:26 +00:00
var Config = require("./config");
2015-09-21 06:17:06 +00:00
var Promise = require("bluebird");
2015-10-02 05:02:59 +00:00
import * as ChannelStore from './channel-storage/channelstore';
2013-10-11 21:31:40 +00:00
module.exports = {
2014-01-22 23:11:26 +00:00
init: function () {
2013-10-11 21:31:40 +00:00
Logger.syslog.log("Starting CyTube v" + VERSION);
var chanlogpath = path.join(__dirname, "../chanlogs");
fs.exists(chanlogpath, function (exists) {
exists || fs.mkdir(chanlogpath);
});
var chandumppath = path.join(__dirname, "../chandump");
fs.exists(chandumppath, function (exists) {
exists || fs.mkdir(chandumppath);
});
var gdvttpath = path.join(__dirname, "../google-drive-subtitles");
fs.exists(gdvttpath, function (exists) {
exists || fs.mkdir(gdvttpath);
});
2014-01-22 23:11:26 +00:00
singleton = new Server();
2013-10-11 21:31:40 +00:00
return singleton;
},
getServer: function () {
return singleton;
}
};
2013-07-19 20:27:21 +00:00
var path = require("path");
2013-07-28 23:47:55 +00:00
var fs = require("fs");
2013-09-09 22:16:41 +00:00
var http = require("http");
var https = require("https");
2013-04-17 18:42:29 +00:00
var express = require("express");
2013-07-15 22:57:33 +00:00
var Logger = require("./logger");
2014-05-21 02:30:14 +00:00
var Channel = require("./channel/channel");
2013-07-15 22:57:33 +00:00
var User = require("./user");
2013-10-09 23:10:26 +00:00
var $util = require("./utilities");
2014-02-01 18:41:06 +00:00
var db = require("./database");
2014-05-21 02:30:14 +00:00
var Flags = require("./flags");
var sio = require("socket.io");
2015-10-27 05:56:53 +00:00
import LocalChannelIndex from './web/localchannelindex';
import IOConfiguration from './configuration/ioconfig';
import WebConfiguration from './configuration/webconfig';
2015-10-27 05:56:53 +00:00
import NullClusterClient from './io/cluster/nullclusterclient';
2016-01-29 03:51:59 +00:00
import { RedisClusterClient } from './io/cluster/redisclusterclient';
import { FrontendPool } from 'cytube-common/lib/redis/frontendpool';
2015-11-02 01:42:20 +00:00
import session from './session';
2014-01-22 23:11:26 +00:00
var Server = function () {
2013-10-09 23:10:26 +00:00
var self = this;
self.channels = [],
self.express = null;
self.db = null;
self.api = null;
self.announcement = null;
self.infogetter = null;
self.servers = {};
2013-10-09 23:10:26 +00:00
// database init ------------------------------------------------------
var Database = require("./database");
2013-12-12 22:28:30 +00:00
self.db = Database;
2014-01-22 23:11:26 +00:00
self.db.init();
2015-10-02 05:02:59 +00:00
ChannelStore.init();
2013-10-11 23:15:44 +00:00
2016-01-29 03:51:59 +00:00
// redis init
const redis = require('redis');
Promise.promisifyAll(redis.RedisClient.prototype);
Promise.promisifyAll(redis.Multi.prototype);
2013-10-11 23:15:44 +00:00
// webserver init -----------------------------------------------------
2015-10-27 05:56:53 +00:00
const ioConfig = IOConfiguration.fromOldConfig(Config);
const webConfig = WebConfiguration.fromOldConfig(Config);
2016-01-29 03:51:59 +00:00
const frontendPool = new FrontendPool(redis.createClient());
const clusterClient = new RedisClusterClient(frontendPool);
2015-10-27 05:56:53 +00:00
const channelIndex = new LocalChannelIndex();
2013-10-09 23:10:26 +00:00
self.express = express();
2015-10-27 05:56:53 +00:00
require("./web/webserver").init(self.express,
webConfig,
2015-10-27 05:56:53 +00:00
ioConfig,
clusterClient,
2015-11-02 01:42:20 +00:00
channelIndex,
session);
2013-10-09 23:10:26 +00:00
// http/https/sio server init -----------------------------------------
var key = "", cert = "", ca = undefined;
if (Config.get("https.enabled")) {
key = fs.readFileSync(path.resolve(__dirname, "..",
Config.get("https.keyfile")));
cert = fs.readFileSync(path.resolve(__dirname, "..",
Config.get("https.certfile")));
if (Config.get("https.cafile")) {
ca = fs.readFileSync(path.resolve(__dirname, "..",
Config.get("https.cafile")));
}
2013-10-09 23:10:26 +00:00
}
var opts = {
key: key,
cert: cert,
passphrase: Config.get("https.passphrase"),
ca: ca,
2015-03-06 22:29:21 +00:00
ciphers: Config.get("https.ciphers"),
2015-03-06 21:59:34 +00:00
honorCipherOrder: true
};
Config.get("listen").forEach(function (bind) {
var id = bind.ip + ":" + bind.port;
if (id in self.servers) {
Logger.syslog.log("[WARN] Ignoring duplicate listen address " + id);
return;
}
if (bind.https && Config.get("https.enabled")) {
self.servers[id] = https.createServer(opts, self.express)
.listen(bind.port, bind.ip);
2015-01-06 15:54:14 +00:00
self.servers[id].on("clientError", function (err, socket) {
try {
socket.destroy();
} catch (e) {
}
});
} else if (bind.http) {
self.servers[id] = self.express.listen(bind.port, bind.ip);
2015-01-06 15:54:14 +00:00
self.servers[id].on("clientError", function (err, socket) {
try {
socket.destroy();
} catch (e) {
}
});
}
});
2014-01-23 03:12:43 +00:00
require("./io/ioserver").init(self, webConfig);
2015-12-26 23:07:03 +00:00
const redisAdapter = require('socket.io-redis');
const IOBackend = require('./io/backend/iobackend');
const sioEmitter = require("socket.io").instance;
sioEmitter.adapter(redisAdapter());
const listenerConfig = {
getPort: function () {
return 3071;
},
getHost: function () {
return '127.0.0.1';
}
};
const backend = new IOBackend(listenerConfig, sioEmitter, redis.createClient());
2013-10-09 23:10:26 +00:00
// background tasks init ----------------------------------------------
require("./bgtask")(self);
// setuid
require("./setuid");
2013-10-09 23:10:26 +00:00
};
Server.prototype.getHTTPIP = function (req) {
2013-11-25 00:13:58 +00:00
var ip = req.ip;
if (ip === "127.0.0.1" || ip === "::1") {
var fwd = req.header("x-forwarded-for");
if (fwd && typeof fwd === "string") {
return fwd;
}
}
2013-11-25 00:13:58 +00:00
return ip;
2013-10-09 23:10:26 +00:00
};
2013-10-09 23:10:26 +00:00
Server.prototype.getSocketIP = function (socket) {
2013-07-06 17:00:02 +00:00
var raw = socket.handshake.address.address;
2013-11-25 00:13:58 +00:00
if (raw === "127.0.0.1" || raw === "::1") {
var fwd = socket.handshake.headers["x-forwarded-for"];
if (fwd && typeof fwd === "string") {
return fwd;
2013-07-06 17:00:02 +00:00
}
}
2013-07-15 22:57:33 +00:00
return raw;
2013-10-09 23:10:26 +00:00
};
2013-07-15 22:57:33 +00:00
2013-10-09 23:10:26 +00:00
Server.prototype.isChannelLoaded = function (name) {
name = name.toLowerCase();
for (var i = 0; i < this.channels.length; i++) {
if (this.channels[i].uniqueName == name)
2013-10-09 23:10:26 +00:00
return true;
}
return false;
};
2013-09-09 22:16:41 +00:00
2013-10-09 23:10:26 +00:00
Server.prototype.getChannel = function (name) {
2014-01-23 21:53:53 +00:00
var self = this;
2013-10-09 23:10:26 +00:00
var cname = name.toLowerCase();
2014-01-23 21:53:53 +00:00
for (var i = 0; i < self.channels.length; i++) {
if (self.channels[i].uniqueName === cname)
return self.channels[i];
2013-10-09 23:10:26 +00:00
}
2013-09-09 22:16:41 +00:00
2013-10-11 21:31:40 +00:00
var c = new Channel(name);
2014-01-23 21:53:53 +00:00
c.on("empty", function () {
self.unloadChannel(c);
});
self.channels.push(c);
2013-10-09 23:10:26 +00:00
return c;
};
2013-09-09 22:16:41 +00:00
2013-10-09 23:10:26 +00:00
Server.prototype.unloadChannel = function (chan) {
if (chan.dead) {
return;
}
2014-05-21 02:30:14 +00:00
chan.saveState();
2013-09-09 22:16:41 +00:00
2014-03-04 17:57:05 +00:00
chan.logger.log("[init] Channel shutting down");
2013-10-09 23:10:26 +00:00
chan.logger.close();
2014-05-21 02:30:14 +00:00
chan.notifyModules("unload", []);
Object.keys(chan.modules).forEach(function (k) {
chan.modules[k].dead = true;
});
2013-10-09 23:10:26 +00:00
for (var i = 0; i < this.channels.length; i++) {
2014-01-23 21:53:53 +00:00
if (this.channels[i].uniqueName === chan.uniqueName) {
2013-10-09 23:10:26 +00:00
this.channels.splice(i, 1);
i--;
}
}
2014-02-16 19:27:01 +00:00
Logger.syslog.log("Unloaded channel " + chan.name);
2013-10-09 23:10:26 +00:00
// Empty all outward references from the channel
var keys = Object.keys(chan);
for (var i in keys) {
delete chan[keys[i]];
}
chan.dead = true;
};
2014-05-24 06:09:36 +00:00
Server.prototype.packChannelList = function (publicOnly, isAdmin) {
2014-01-20 23:52:36 +00:00
var channels = this.channels.filter(function (c) {
if (!publicOnly) {
return true;
}
2014-05-21 02:30:14 +00:00
return c.modules.options && c.modules.options.get("show_public");
2014-01-20 23:52:36 +00:00
});
2014-05-24 05:40:35 +00:00
var self = this;
return channels.map(function (c) {
2014-05-24 06:09:36 +00:00
return c.packInfo(isAdmin);
2014-05-24 05:40:35 +00:00
});
2014-01-20 23:52:36 +00:00
};
2014-02-01 18:41:06 +00:00
Server.prototype.announce = function (data) {
if (data == null) {
this.announcement = null;
db.clearAnnouncement();
} else {
this.announcement = data;
db.setAnnouncement(data);
sio.instance.emit("announcement", data);
2014-02-01 18:41:06 +00:00
}
2013-10-09 23:10:26 +00:00
};
2013-10-09 23:10:26 +00:00
Server.prototype.shutdown = function () {
Logger.syslog.log("Unloading channels");
2015-09-21 06:17:06 +00:00
Promise.map(this.channels, channel => {
return channel.saveState().tap(() => {
Logger.syslog.log(`Saved /r/${channel.name}`);
}).catch(err => {
Logger.errlog.log(`Failed to save /r/${channel.name}: ${err.stack}`);
});
}).then(() => {
Logger.syslog.log("Goodbye");
process.exit(0);
}).catch(err => {
Logger.errlog.log(`Caught error while saving channels: ${err.stack}`);
process.exit(1);
2015-09-21 06:17:06 +00:00
});
2013-10-09 23:10:26 +00:00
};