add session counters and presence (brainlet-react presence is locked behind an experiment flag, just enable it with an override at the moment)
This commit is contained in:
parent
76f041e75e
commit
3a53d585ff
3 changed files with 61 additions and 13 deletions
|
@ -6,7 +6,7 @@ const werift = require("werift");
|
|||
const { experiments } = require("../../../experiments");
|
||||
const User = require("../../../models/User");
|
||||
const Channel = require("../../../models/Channel");
|
||||
const { parseMessage, opcodeSeparator, getOpcodeByName } = require("./messageparser");
|
||||
const { parseMessage, packet } = require("./messageparser");
|
||||
const { checkToken } = require("../../../common/auth/authfunctions");
|
||||
|
||||
const pingCheckDelay = 10000;
|
||||
|
@ -43,6 +43,7 @@ class GatewayServer extends EventEmitter {
|
|||
constructor({ server }) {
|
||||
super();
|
||||
this.wss = new websockets.Server({ server: server, path: "/gateway" });
|
||||
this.sessionCounters = {};
|
||||
|
||||
this.pingInterval = setInterval(() => {
|
||||
this.wss.clients.forEach((client) => {
|
||||
|
@ -61,7 +62,7 @@ class GatewayServer extends EventEmitter {
|
|||
|
||||
this.wss.on("connection", (ws) => {
|
||||
// Send HELLO message as soon as the client connects
|
||||
ws.send(this.packet("HELLO", {}));
|
||||
ws.send(packet("HELLO", {}));
|
||||
ws.session = {
|
||||
authenticated: false,
|
||||
user: null,
|
||||
|
@ -73,6 +74,21 @@ class GatewayServer extends EventEmitter {
|
|||
ws.alive = true;
|
||||
});
|
||||
ws.on("close", async () => {
|
||||
if (this.sessionCounters[ws.session.user._id] <= 1) {
|
||||
this.inChannel(ws.channels[0], (client) => {
|
||||
console.log(client.session);
|
||||
client.send(packet("EVENT_CHANNEL_MEMBERS", {
|
||||
[ws.session.user._id]: {
|
||||
_id: ws.session.user._id,
|
||||
username: ws.session.user.username,
|
||||
status: 0,
|
||||
status_text: "Now offline"
|
||||
}
|
||||
}));
|
||||
});
|
||||
}
|
||||
this.sessionCounters[ws.session.user._id]--;
|
||||
|
||||
if (ws.rtc) await ws.rtc.connection.close();
|
||||
});
|
||||
ws.on("message", async (data) => {
|
||||
|
@ -87,6 +103,12 @@ class GatewayServer extends EventEmitter {
|
|||
ws.session.user = user;
|
||||
ws.session.authenticated = true;
|
||||
|
||||
if (!this.sessionCounters[user._id]) this.sessionCounters[user._id] = 0;
|
||||
this.sessionCounters[user._id]++;
|
||||
if (this.sessionCounters[user._id] > 5) {
|
||||
return ws.close(4006, "Too many sessions.");
|
||||
}
|
||||
|
||||
// The user is now successfully authenticated, send the YOO_ACK packet
|
||||
// TODO: This is probably not efficient
|
||||
|
||||
|
@ -96,7 +118,30 @@ class GatewayServer extends EventEmitter {
|
|||
|
||||
ws.channels = channels.map(x => x._id);
|
||||
|
||||
ws.send(this.packet("YOO_ACK", { session_id: ws.session.sessionId, channels, user: { username: user.username, _id: user._id }, __global_experiments: experiments }));
|
||||
ws.send(packet("YOO_ACK", { session_id: ws.session.sessionId, channels, user: { username: user.username, _id: user._id }, __global_experiments: experiments }));
|
||||
|
||||
let presence = {};
|
||||
const channel = channels[0];
|
||||
|
||||
this.inChannel(channel._id, (client) => {
|
||||
presence[client.session.user._id] = {
|
||||
_id: client.session.user._id,
|
||||
username: client.session.user.username,
|
||||
status: 1,
|
||||
status_text: "Online"
|
||||
};
|
||||
if (client.session.sessionId !== ws.session.sessionId) client.send(packet("EVENT_CHANNEL_MEMBERS", {
|
||||
[ws.session.user._id]: {
|
||||
_id: ws.session.user._id,
|
||||
username: ws.session.user.username,
|
||||
status: 1,
|
||||
status_text: "Online"
|
||||
}
|
||||
}));
|
||||
});
|
||||
|
||||
ws.send(packet("EVENT_CHANNEL_MEMBERS", presence));
|
||||
|
||||
console.log(`gateway: user ${user.username}: handshake complete`);
|
||||
} catch (e) {
|
||||
console.log("gateway:", e);
|
||||
|
@ -116,7 +161,7 @@ class GatewayServer extends EventEmitter {
|
|||
// Check if the user is in that channel before broadcasting the message
|
||||
if (!ws.channels.includes(message.data.channel._id)) return ws.close(4008, "Not authorized to perform action.");
|
||||
|
||||
this.broadcast(message.data.channel._id, this.packet("EVENT_CREATE_MESSAGE", {
|
||||
this.broadcast(message.data.channel._id, packet("EVENT_CREATE_MESSAGE", {
|
||||
content: messageContent,
|
||||
channel: {
|
||||
_id: message.data.channel._id
|
||||
|
@ -133,7 +178,7 @@ class GatewayServer extends EventEmitter {
|
|||
case "ACTION_VOICE_REQUEST_SESSION": {
|
||||
if (!experiments.voiceSFUTesting) return;
|
||||
// just send ourselves as the voice server lol
|
||||
ws.send(this.packet("EVENT_VOICE_ASSIGN_SERVER", {
|
||||
ws.send(packet("EVENT_VOICE_ASSIGN_SERVER", {
|
||||
reportTo: "/gateway",
|
||||
channel: message.data.channel
|
||||
}));
|
||||
|
@ -168,7 +213,7 @@ class GatewayServer extends EventEmitter {
|
|||
});
|
||||
}
|
||||
|
||||
ws.send(this.packet("EVENT_VOICE_CONNECTION_ANSWER", {
|
||||
ws.send(packet("EVENT_VOICE_CONNECTION_ANSWER", {
|
||||
answer: await ws.rtc.answer(offer)
|
||||
}));
|
||||
|
||||
|
@ -225,9 +270,4 @@ GatewayServer.prototype.authMessage = function(ws) {
|
|||
return true;
|
||||
};
|
||||
|
||||
GatewayServer.prototype.packet = function(op, data) {
|
||||
if (typeof op === "string") op = getOpcodeByName(op);
|
||||
return `${op}${opcodeSeparator}${JSON.stringify(data)}`;
|
||||
};
|
||||
|
||||
module.exports = GatewayServer;
|
||||
|
|
|
@ -4,6 +4,9 @@ const opcodes = {
|
|||
2: { name: "YOO_ACK", data: "JSON" },
|
||||
3: { name: "ACTION_CREATE_MESSAGE", data: "JSON" },
|
||||
4: { name: "EVENT_CREATE_MESSAGE", data: "JSON" },
|
||||
5: { name: "ACTION_UPDATE_STATUS", data: "JSON" },
|
||||
6: { name: "EVENT_CHANNEL_MEMBERS", data: "JSON" },
|
||||
7: { name: "EVENT_CHANNEL_MEMBER_UPDATE", data: "JSON" },
|
||||
21: { name: "ACTION_VOICE_REQUEST_SESSION", data: "JSON" },
|
||||
22: { name: "EVENT_VOICE_ASSIGN_SERVER", data: "JSON" },
|
||||
23: { name: "ACTION_VOICE_CONNECTION_REQUEST", data: "JSON" },
|
||||
|
@ -45,4 +48,9 @@ const getOpcodeByName = (name) => {
|
|||
for (const [key, value] of Object.entries(opcodes)) if (value.name === name) return key;
|
||||
};
|
||||
|
||||
module.exports = { opcodes, parseMessage, opcodeSeparator, getOpcodeByName };
|
||||
const packet = (op, data) => {
|
||||
if (typeof op === "string") op = getOpcodeByName(op);
|
||||
return `${op}${opcodeSeparator}${JSON.stringify(data)}`;
|
||||
};
|
||||
|
||||
module.exports = { opcodes, parseMessage, opcodeSeparator, getOpcodeByName, packet };
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
module.exports = {
|
||||
experiments: {
|
||||
voiceSFUTesting: false,
|
||||
userListTest: true
|
||||
userListTest: false
|
||||
}
|
||||
};
|
||||
|
|
Reference in a new issue