aboutsummaryrefslogtreecommitdiffstats
path: root/lib/sockets.js
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2023-02-06 16:48:13 -0800
committerAdam Soltys <[email protected]>2023-02-06 16:48:13 -0800
commit9c667055c6367e1b2e239686e72f52995679a47e (patch)
tree0b1d4aee51ec2d4e92d08a9d1404ba4e2ecd462a /lib/sockets.js
parent15294844dbc8e73b4d1e92008a7eebc6b86b9ec5 (diff)
parent6f5602d112b68adb7452abf3047f20c32e7725b6 (diff)
downloadcoinos-server-9c667055c6367e1b2e239686e72f52995679a47e.tar.gz
coinos-server-9c667055c6367e1b2e239686e72f52995679a47e.zip
Merge branch 'master' into test
Diffstat (limited to 'lib/sockets.js')
-rw-r--r--lib/sockets.js148
1 files changed, 40 insertions, 108 deletions
diff --git a/lib/sockets.js b/lib/sockets.js
index 7498db62..234c647a 100644
--- a/lib/sockets.js
+++ b/lib/sockets.js
@@ -1,50 +1,41 @@
-import store from "./store";
import config from "$config";
-import app from "$app";
+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 { getUser } from "$lib/utils";
-import db from "$db";
+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 = (username, type, data) => {
- if (data.username !== 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[username]) return;
- for (let id in store.sockets[username]) {
- const ws = store.sockets[username][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 username in store.sockets) {
- for (const id in store.sockets[username]) {
- const ws = store.sockets[username][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);
}
@@ -55,14 +46,9 @@ 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;
@@ -86,75 +72,41 @@ 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}`);
- const username = jwt.decode(token).username;
- if (!username) throw new Error("Invalid JWT token");
- if (!store.sockets[username]) store.sockets[username] = {};
- const existing = Object.keys(store.sockets[username]);
+ 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 !== id);
- store.sockets[username][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[username][p])
- store.sockets[username][p].close(code, "too many sockets");
+ if (store.sockets[uid][p])
+ store.sockets[uid][p].close(code, "too many sockets");
}, 5000);
}
- store.sockets[username][id] = ws;
- names[id] = username;
-
- let user = await getUser(username);
-
- let { haspin } = user;
-
- if (user.locked) throw new Error("Account is locked");
- let payments = await user.getPayments({
- where: {
- account_id: user.account_id
- },
- order: [["id", "DESC"]],
- limit: 12,
- include: [
- {
- model: db.Account,
- as: "account"
- },
- {
- model: db.Payment,
- as: "fee_payment"
- }
- ]
- });
-
- let accounts = await user.getAccounts();
-
- let keys = await user.getKeys();
- user = user.get({ plain: true });
- user.accounts = accounts;
- user.keys = keys;
- user.payments = payments;
- user.haspin = haspin;
+ 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);
err("caught socket error", e.message);
- if (e.message.includes("locked")) {
- ws.send(JSON.stringify({ type: "locked" }));
- ws.send(JSON.stringify({ type: "logout" }));
- }
if (e.message.includes("not found"))
ws.send(JSON.stringify({ type: "logout" }));
setTimeout(
@@ -170,23 +122,6 @@ app.register(async function(app) {
case "lnurl":
store.sessions[data] = ws;
break;
- case "updateMemo":
- const payment = await db.Payment.findOne({
- where: {
- user_id: ws.user.id,
- id: data.id
- },
- include: {
- model: db.Account,
- as: "account"
- }
- });
- if (payment) {
- payment.memo = data.memo;
- await payment.save();
- emit(ws.user.username, "payment", payment);
- }
- break;
case "subscribe":
subscriptions.push({ invoice: data, ws });
break;
@@ -196,11 +131,10 @@ app.register(async function(app) {
});
ws.on("close", function(code, reason) {
- // console.log("closing socket", reason && reason.toString(), id);
try {
- const username = names[id];
- if (store.sockets[username] && store.sockets[username][id]) {
- delete store.sockets[username][id];
+ const uid = users[id];
+ if (store.sockets[uid] && store.sockets[uid][id]) {
+ delete store.sockets[uid][id];
}
if (all[id]) delete all[id];
@@ -209,16 +143,14 @@ app.register(async function(app) {
}
});
});
-});
-
-const names = {};
+}
-setInterval(() => {
- for (const username in store.sockets) {
- for (const id in store.sockets[username]) {
- let ws = store.sockets[username][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, `${username} ${id} lost heartbeat`);
+ if (ws.beats > 10) ws.close(code, `${uid} ${id} lost heartbeat`);
}
}
-}, 2000);
+};