backend/gateway: add session count limit per user id
This commit is contained in:
parent
bf5e4f554e
commit
e329c64eb7
2 changed files with 27 additions and 1 deletions
|
@ -15,4 +15,5 @@ export const gatewayErrors = {
|
||||||
FLOODING: { code: 4005, message: "Flooding (exceeded maximum messages per batch)" },
|
FLOODING: { code: 4005, message: "Flooding (exceeded maximum messages per batch)" },
|
||||||
ALREADY_AUTHENTICATED: { code: 4006, message: "Already authenticated" },
|
ALREADY_AUTHENTICATED: { code: 4006, message: "Already authenticated" },
|
||||||
PAYLOAD_TOO_LARGE: { code: 4007, message: "Payload too large" },
|
PAYLOAD_TOO_LARGE: { code: 4007, message: "Payload too large" },
|
||||||
|
TOO_MANY_SESSIONS: { code: 4008, message: "Too many sessions" },
|
||||||
};
|
};
|
||||||
|
|
|
@ -10,10 +10,14 @@ import { GatewayPayloadType } from "./gatewaypayloadtype";
|
||||||
const GATEWAY_BATCH_INTERVAL = 50000;
|
const GATEWAY_BATCH_INTERVAL = 50000;
|
||||||
const GATEWAY_PING_INTERVAL = 40000;
|
const GATEWAY_PING_INTERVAL = 40000;
|
||||||
const MAX_CLIENT_MESSAGES_PER_BATCH = 6; // TODO: how well does this work for weak connections?
|
const MAX_CLIENT_MESSAGES_PER_BATCH = 6; // TODO: how well does this work for weak connections?
|
||||||
|
const MAX_GATEWAY_SESSIONS_PER_USER = 5;
|
||||||
|
|
||||||
// mapping between a dispatch id and a websocket client
|
// mapping between a dispatch id and a websocket client
|
||||||
const dispatchChannels = new Map<string, Set<WebSocket>>();
|
const dispatchChannels = new Map<string, Set<WebSocket>>();
|
||||||
|
|
||||||
|
// mapping between a user id and the websocket sessions it has
|
||||||
|
const sessionsByUserId = new Map<number, Set<WebSocket>>();
|
||||||
|
|
||||||
function clientSubscribe(ws: WebSocket, dispatchChannel: string) {
|
function clientSubscribe(ws: WebSocket, dispatchChannel: string) {
|
||||||
ws.state.dispatchChannels.add(dispatchChannel);
|
ws.state.dispatchChannels.add(dispatchChannel);
|
||||||
if (!dispatchChannels.get(dispatchChannel)) {
|
if (!dispatchChannels.get(dispatchChannel)) {
|
||||||
|
@ -159,6 +163,15 @@ export default function(server: Server) {
|
||||||
|
|
||||||
ws.on("close", () => {
|
ws.on("close", () => {
|
||||||
clientUnsubscribeAll(ws);
|
clientUnsubscribeAll(ws);
|
||||||
|
if (ws.state.user && ws.state.user.id) {
|
||||||
|
const sessions = sessionsByUserId.get(ws.state.user.id);
|
||||||
|
if (sessions) {
|
||||||
|
sessions.delete(ws);
|
||||||
|
if (sessions.size < 1) {
|
||||||
|
sessionsByUserId.delete(ws.state.user.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
ws.on("message", async (rawData, isBinary) => {
|
ws.on("message", async (rawData, isBinary) => {
|
||||||
|
@ -195,7 +208,19 @@ export default function(server: Server) {
|
||||||
if (!user) {
|
if (!user) {
|
||||||
return closeWithError(ws, gatewayErrors.BAD_AUTH);
|
return closeWithError(ws, gatewayErrors.BAD_AUTH);
|
||||||
}
|
}
|
||||||
// each user should have their own list of channels that they join
|
|
||||||
|
let sessions = sessionsByUserId.get(user.id);
|
||||||
|
if (sessions) {
|
||||||
|
if ((sessions.size + 1) > MAX_GATEWAY_SESSIONS_PER_USER) {
|
||||||
|
return closeWithError(ws, gatewayErrors.TOO_MANY_SESSIONS);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sessions = new Set();
|
||||||
|
sessionsByUserId.set(user.id, sessions);
|
||||||
|
}
|
||||||
|
sessions.add(ws);
|
||||||
|
|
||||||
|
// TODO: each user should have their own list of channels that they join
|
||||||
const channels = await query("SELECT id, name, owner_id FROM channels");
|
const channels = await query("SELECT id, name, owner_id FROM channels");
|
||||||
|
|
||||||
clientSubscribe(ws, "*");
|
clientSubscribe(ws, "*");
|
||||||
|
|
Loading…
Reference in a new issue