diff options
Diffstat (limited to 'lib/sockets.js')
| -rw-r--r-- | lib/sockets.js | 93 |
1 files changed, 41 insertions, 52 deletions
diff --git a/lib/sockets.js b/lib/sockets.js index c94c29a0..7f655570 100644 --- a/lib/sockets.js +++ b/lib/sockets.js @@ -1,49 +1,42 @@ -import store from "$lib/store"; -import config from "$config"; import app from "$app"; +import config from "$config"; +import store from "$lib/store"; import jwt from "jsonwebtoken"; import { v4 } from "uuid"; -import WebSocket from "ws"; -import { differenceInSeconds, subSeconds } from "date-fns"; -import fastifyWs from "@fastify/websocket"; import whitelist from "./whitelist"; import { l, err, warn } from "$lib/logging"; -import { g } from "$lib/redis"; +import { g } from "$lib/db"; +import { pick } from "$lib/utils"; const code = 1000; - -const wss = new WebSocket.Server({ clientTracking: false, noServer: true }); - -const pick = (O, ...K) => K.reduce((o, k) => ((o[k] = O[k]), o), {}); const all = {}; const subscriptions = []; const lastSeen = {}; +const users = {}; -export const emit = (uuid, type, data) => { - if (data.uuid !== undefined) data = pick(data, ...whitelist); - +export const emit = (uid, type, data) => { if (type === "payment" && data.amount > 0) { for (let i = subscriptions.length - 1; i >= 0; i--) { let s = subscriptions[i]; - if (s.invoice.id === data.invoice_id) { + if (s.hash === data.hash) { s.ws.send(JSON.stringify({ type, data })); } } } - if (!store.sockets[uuid]) return; - for (let id in store.sockets[uuid]) { - const ws = store.sockets[uuid][id]; + if (!store.sockets[uid]) return; + for (let id in store.sockets[uid]) { + const ws = store.sockets[uid][id]; ws.send(JSON.stringify({ type, data })); } }; export const broadcast = (type, data) => { const sent = []; - for (const uuid in store.sockets) { - for (const id in store.sockets[uuid]) { - const ws = store.sockets[uuid][id]; + for (const uid in store.sockets) { + for (const id in store.sockets[uid]) { + const ws = store.sockets[uid][id]; ws.send(JSON.stringify({ type, data })); sent.push(ws.id); } @@ -54,14 +47,10 @@ export const broadcast = (type, data) => { }); }; -function subtractSeconds(numOfSeconds, date = new Date()) { - date.setSeconds(date.getSeconds() - numOfSeconds); - return date; -} +export async function socketServer(app) { + let seconds = (n, d = new Date()) => d.setSeconds(d.getSeconds() - n) && d; -app.register(fastifyWs); -app.register(async function(app) { app.get("/ws", { websocket: true }, ({ socket: ws }, req) => { const id = v4(); ws.id = id; @@ -85,41 +74,42 @@ app.register(async function(app) { case "login": let token = data; - if (lastSeen[token] > subtractSeconds(5)) return; + 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: user_id } = jwt.decode(token); - if (!user_id) throw new Error("Invalid JWT token"); - let user = await g(`user:${user_id}`); + 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"); - user.haspin = !!user.pin; - if (!store.sockets[user_id]) store.sockets[user_id] = {}; - const existing = Object.keys(store.sockets[user_id]); + if (!store.sockets[uid]) store.sockets[uid] = {}; + const existing = Object.keys(store.sockets[uid]); if (existing.length > 4) { - const p = existing.find(sid => sid !== user_id); - store.sockets[user_id][p].send(JSON.stringify({ type: "logout" })); + const p = existing.find(sid => sid !== uid); + store.sockets[uid][p].send( + JSON.stringify({ type: "logout" }) + ); setTimeout(() => { - if (store.sockets[user_id][p]) - store.sockets[user_id][p].close(code, "too many sockets"); + if (store.sockets[uid][p]) + store.sockets[uid][p].close(code, "too many sockets"); }, 5000); } - store.sockets[user_id][id] = ws; - names[id] = user_id; + store.sockets[uid][id] = ws; + users[id] = uid; ws.user = user; ws.send( - JSON.stringify({ type: "login", data: pick(user, ...whitelist) }) + JSON.stringify({ type: "login", data: pick(user, whitelist) }) ); ws.send( JSON.stringify({ type: "version", data: config.clientVersion }) ); } catch (e) { - console.log(e) + console.log(e); err("caught socket error", e.message); if (e.message.includes("not found")) ws.send(JSON.stringify({ type: "logout" })); @@ -146,9 +136,9 @@ app.register(async function(app) { ws.on("close", function(code, reason) { try { - const uuid = names[id]; - if (store.sockets[uuid] && store.sockets[uuid][id]) { - delete store.sockets[uuid][id]; + const uid = users[id]; + if (store.sockets[uid] && store.sockets[uid][id]) { + delete store.sockets[uid][id]; } if (all[id]) delete all[id]; @@ -157,16 +147,15 @@ app.register(async function(app) { } }); }); -}); +} -const names = {}; -setInterval(() => { - for (const uuid in store.sockets) { - for (const id in store.sockets[uuid]) { - let ws = store.sockets[uuid][id]; +export let sendHeartbeat = () => { + for (const uid in store.sockets) { + for (const id in store.sockets[uid]) { + let ws = store.sockets[uid][id]; ws.beats++; - if (ws.beats > 10) ws.close(code, `${uuid} ${id} lost heartbeat`); + if (ws.beats > 10) ws.close(code, `${uid} ${id} lost heartbeat`); } } -}, 2000); +} |
