townsquare/server/index.js

89 lines
2.3 KiB
JavaScript
Raw Normal View History

2020-05-27 20:33:51 +00:00
const fs = require("fs");
const https = require("https");
const WebSocket = require("ws");
const server = https.createServer({
cert: fs.readFileSync("cert.pem"),
key: fs.readFileSync("key.pem")
});
const wss = new WebSocket.Server({
2020-06-04 19:44:25 +00:00
...(process.env.NODE_ENV === "development" ? { port: 8081 } : { server }),
2020-05-27 20:33:51 +00:00
verifyClient: info =>
!!info.origin.match(
/^https?:\/\/(bra1n\.github\.io|localhost|eddbra1nprivatetownsquare\.xyz)/i
)
2020-05-27 20:33:51 +00:00
});
2020-06-04 19:44:25 +00:00
function noop() {}
function heartbeat() {
this.latency = Math.round((new Date().getTime() - this.pingStart) / 2);
2020-06-04 19:44:25 +00:00
this.isAlive = true;
}
2020-05-27 20:33:51 +00:00
wss.on("connection", function connection(ws, req) {
ws.channel = req.url
.split("/")
.pop()
.toLocaleLowerCase();
if (ws.channel.match(/-host$/i)) {
ws.isHost = true;
ws.channel = ws.channel.substr(0, ws.channel.length - 5);
// check for another host on this channel
if (
Array.from(wss.clients).some(
client =>
client !== ws &&
client.readyState === WebSocket.OPEN &&
client.channel === ws.channel &&
client.isHost
)
) {
console.log(ws.channel, "duplicate host");
ws.close(1000, `The channel "${ws.channel}" already has a host`);
return;
}
}
2020-06-04 19:44:25 +00:00
ws.isAlive = true;
ws.pingStart = new Date().getTime();
ws.ping(noop);
2020-06-04 19:44:25 +00:00
ws.on("pong", heartbeat);
2020-05-27 20:33:51 +00:00
ws.on("message", function incoming(data) {
const isPing = data.match(/^\["ping/i);
if (!isPing) {
console.log(new Date(), wss.clients.size, ws.channel, data);
2020-05-30 20:01:42 +00:00
}
2020-05-27 20:33:51 +00:00
wss.clients.forEach(function each(client) {
if (
client !== ws &&
client.readyState === WebSocket.OPEN &&
client.channel === ws.channel
) {
// inject latency between both clients if ping message
if (isPing && client.latency && ws.latency) {
client.send(data.replace(/latency/, client.latency + ws.latency));
} else {
client.send(data);
}
2020-05-27 20:33:51 +00:00
}
});
});
});
2020-06-04 19:44:25 +00:00
const interval = setInterval(function ping() {
wss.clients.forEach(function each(ws) {
if (ws.isAlive === false) return ws.terminate();
ws.isAlive = false;
ws.pingStart = new Date().getTime();
2020-06-04 19:44:25 +00:00
ws.ping(noop);
});
}, 30000);
wss.on("close", function close() {
clearInterval(interval);
});
if (process.env.NODE_ENV !== "development") {
server.listen(8080);
}