mirror of https://github.com/bra1n/townsquare.git
added stats to server and simple channel -> client map
This commit is contained in:
parent
e19b617df4
commit
805e16ad63
|
@ -10,17 +10,22 @@ const wss = new WebSocket.Server({
|
||||||
...(process.env.NODE_ENV === "development" ? { port: 8081 } : { server }),
|
...(process.env.NODE_ENV === "development" ? { port: 8081 } : { server }),
|
||||||
verifyClient: info =>
|
verifyClient: info =>
|
||||||
!!info.origin.match(
|
!!info.origin.match(
|
||||||
/^https?:\/\/(bra1n\.github\.io|localhost|eddbra1nprivatetownsquare\.xyz)/i
|
/^https?:\/\/([^.]+\.github\.io|localhost|live\.clocktower\.online|eddbra1nprivatetownsquare\.xyz)/i
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
function noop() {}
|
function noop() {}
|
||||||
|
|
||||||
|
// calculate latency on heartbeat
|
||||||
function heartbeat() {
|
function heartbeat() {
|
||||||
this.latency = Math.round((new Date().getTime() - this.pingStart) / 2);
|
this.latency = Math.round((new Date().getTime() - this.pingStart) / 2);
|
||||||
this.isAlive = true;
|
this.isAlive = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// map of channels currently in use
|
||||||
|
const channels = {};
|
||||||
|
|
||||||
|
// a new client connects
|
||||||
wss.on("connection", function connection(ws, req) {
|
wss.on("connection", function connection(ws, req) {
|
||||||
ws.channel = req.url
|
ws.channel = req.url
|
||||||
.split("/")
|
.split("/")
|
||||||
|
@ -31,12 +36,10 @@ wss.on("connection", function connection(ws, req) {
|
||||||
ws.channel = ws.channel.substr(0, ws.channel.length - 5);
|
ws.channel = ws.channel.substr(0, ws.channel.length - 5);
|
||||||
// check for another host on this channel
|
// check for another host on this channel
|
||||||
if (
|
if (
|
||||||
Array.from(wss.clients).some(
|
channels[ws.channel] &&
|
||||||
|
channels[ws.channel].some(
|
||||||
client =>
|
client =>
|
||||||
client !== ws &&
|
client !== ws && client.readyState === WebSocket.OPEN && client.isHost
|
||||||
client.readyState === WebSocket.OPEN &&
|
|
||||||
client.channel === ws.channel &&
|
|
||||||
client.isHost
|
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
console.log(ws.channel, "duplicate host");
|
console.log(ws.channel, "duplicate host");
|
||||||
|
@ -46,19 +49,30 @@ wss.on("connection", function connection(ws, req) {
|
||||||
}
|
}
|
||||||
ws.isAlive = true;
|
ws.isAlive = true;
|
||||||
ws.pingStart = new Date().getTime();
|
ws.pingStart = new Date().getTime();
|
||||||
|
// add channel to list
|
||||||
|
if (!channels[ws.channel]) {
|
||||||
|
channels[ws.channel] = [];
|
||||||
|
}
|
||||||
|
channels[ws.channel].push(ws);
|
||||||
|
// start ping pong
|
||||||
ws.ping(noop);
|
ws.ping(noop);
|
||||||
ws.on("pong", heartbeat);
|
ws.on("pong", heartbeat);
|
||||||
|
// remove client from channels on close
|
||||||
|
ws.on("close", () => {
|
||||||
|
const index = channels[ws.channel].indexOf(ws);
|
||||||
|
if (index >= 0) {
|
||||||
|
channels[ws.channel].splice(index, 1);
|
||||||
|
}
|
||||||
|
if (!channels[ws.channel].length) delete channels[ws.channel];
|
||||||
|
});
|
||||||
|
// handle message
|
||||||
ws.on("message", function incoming(data) {
|
ws.on("message", function incoming(data) {
|
||||||
const isPing = data.match(/^\["ping/i);
|
const isPing = data.match(/^\["ping/i);
|
||||||
if (!isPing) {
|
if (!isPing) {
|
||||||
console.log(new Date(), wss.clients.size, ws.channel, data);
|
console.log(new Date(), wss.clients.size, ws.channel, data);
|
||||||
}
|
}
|
||||||
wss.clients.forEach(function each(client) {
|
channels[ws.channel].forEach(function each(client) {
|
||||||
if (
|
if (client !== ws && client.readyState === WebSocket.OPEN) {
|
||||||
client !== ws &&
|
|
||||||
client.readyState === WebSocket.OPEN &&
|
|
||||||
client.channel === ws.channel
|
|
||||||
) {
|
|
||||||
// inject latency between both clients if ping message
|
// inject latency between both clients if ping message
|
||||||
if (isPing && client.latency && ws.latency) {
|
if (isPing && client.latency && ws.latency) {
|
||||||
client.send(data.replace(/latency/, client.latency + ws.latency));
|
client.send(data.replace(/latency/, client.latency + ws.latency));
|
||||||
|
@ -70,6 +84,7 @@ wss.on("connection", function connection(ws, req) {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// start ping interval timer
|
||||||
const interval = setInterval(function ping() {
|
const interval = setInterval(function ping() {
|
||||||
wss.clients.forEach(function each(ws) {
|
wss.clients.forEach(function each(ws) {
|
||||||
if (ws.isAlive === false) return ws.terminate();
|
if (ws.isAlive === false) return ws.terminate();
|
||||||
|
@ -77,12 +92,24 @@ const interval = setInterval(function ping() {
|
||||||
ws.pingStart = new Date().getTime();
|
ws.pingStart = new Date().getTime();
|
||||||
ws.ping(noop);
|
ws.ping(noop);
|
||||||
});
|
});
|
||||||
}, 30000);
|
}, 30000); // 30 second pings
|
||||||
|
|
||||||
|
// handle server shutdown
|
||||||
wss.on("close", function close() {
|
wss.on("close", function close() {
|
||||||
clearInterval(interval);
|
clearInterval(interval);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// prod mode with stats API
|
||||||
if (process.env.NODE_ENV !== "development") {
|
if (process.env.NODE_ENV !== "development") {
|
||||||
|
console.log("server starting");
|
||||||
server.listen(8080);
|
server.listen(8080);
|
||||||
|
server.on("request", (req, res) => {
|
||||||
|
res.writeHead(200);
|
||||||
|
res.end(
|
||||||
|
JSON.stringify({
|
||||||
|
players: wss.clients.size,
|
||||||
|
channels: Object.keys(channels).length
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue