From d404f11e5df3c982ed91e4cddd2fbc9de6870262 Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Thu, 13 Apr 2023 13:42:19 -0700 Subject: socket tracking --- lib/sockets.js | 66 ++++++++++++++++++++++++++-------------------------------- 1 file changed, 29 insertions(+), 37 deletions(-) diff --git a/lib/sockets.js b/lib/sockets.js index ba763fdc..e5f2638b 100644 --- a/lib/sockets.js +++ b/lib/sockets.js @@ -41,17 +41,36 @@ export const broadcast = (type, data) => { } } - Object.values(all).map((ws) => { + Object.values(all).map(ws => { if (!sent.includes(ws.id)) ws.send(JSON.stringify({ type, data })); }); }; +let track = async (ws, token) => { + let { id } = ws; + let { id: uid } = jwt.decode(token); + if (!uid) throw new Error("Invalid JWT token"); + let user = await g(`user:${uid}`); + if (!user) throw new Error("User not found"); + + if (!store.sockets[uid]) store.sockets[uid] = {}; + if (store.sockets[uid][id]) return; + const existing = Object.keys(store.sockets[uid]); + if (existing.length > 4) { + const p = existing.find(sid => sid !== uid); + store.sockets[uid][p].close(code, "too many sockets"); + } + store.sockets[uid][id] = ws; + users[id] = uid; + ws.user = user; +}; + export async function socketServer(app) { let seconds = (n, d = new Date()) => d.setSeconds(d.getSeconds() - n) && d; app.get("/ws", { websocket: true }, (connection, req) => { let { socket: ws } = connection; - connection.on("error", (e) => err(e.message)); + connection.on("error", e => err(e.message)); const id = v4(); ws.id = id; @@ -59,7 +78,7 @@ export async function socketServer(app) { ws.send(JSON.stringify({ type: "connected", data: id })); all[id] = ws; - ws.on("message", async (message) => { + ws.on("message", async message => { let type, data; try { ({ type, data } = JSON.parse(message)); @@ -70,43 +89,16 @@ export async function socketServer(app) { switch (type) { case "heartbeat": ws.beats = 0; + if (data) await track(ws, data); ws.send(JSON.stringify({ type: "id", data: ws.id })); break; case "login": - let token = data; - if (lastSeen[token] > seconds(5)) return; - lastSeen[token] = new Date(); - try { - if (!token || token === "null" || !jwt.decode(token)) - return ws.close(code, `bad token ${token}`); - - let { id: uid } = jwt.decode(token); - if (!uid) throw new Error("Invalid JWT token"); - let user = await g(`user:${uid}`); - if (!user) throw new Error("User not found"); - - if (!store.sockets[uid]) store.sockets[uid] = {}; - const existing = Object.keys(store.sockets[uid]); - if (existing.length > 4) { - const p = existing.find((sid) => sid !== uid); - store.sockets[uid][p].send(JSON.stringify({ type: "logout" })); - setTimeout(() => { - if (store.sockets[uid][p]) - store.sockets[uid][p].close(code, "too many sockets"); - }, 5000); - } - store.sockets[uid][id] = ws; - users[id] = uid; - - ws.user = user; - ws.send( - JSON.stringify({ type: "login", data: pick(user, whitelist) }) - ); - ws.send( - JSON.stringify({ type: "version", data: config.clientVersion }) - ); + if (!data || data === "null" || !jwt.decode(data)) + return ws.close(code, `bad token ${data}`); + + await track(ws, data); } catch (e) { // console.log(e); // err("caught socket error", e.message); @@ -133,9 +125,9 @@ export async function socketServer(app) { } }); - ws.on("error", (e) => err(e.message)); + ws.on("error", e => err(e.message)); - ws.on("close", function (code, reason) { + ws.on("close", function(code, reason) { try { const uid = users[id]; if (store.sockets[uid] && store.sockets[uid][id]) { -- cgit v1.2.3