forked from hippoz/brainlet
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 { experiments } = require("../../../experiments");
|
||||||
const User = require("../../../models/User");
|
const User = require("../../../models/User");
|
||||||
const Channel = require("../../../models/Channel");
|
const Channel = require("../../../models/Channel");
|
||||||
const { parseMessage, opcodeSeparator, getOpcodeByName } = require("./messageparser");
|
const { parseMessage, packet } = require("./messageparser");
|
||||||
const { checkToken } = require("../../../common/auth/authfunctions");
|
const { checkToken } = require("../../../common/auth/authfunctions");
|
||||||
|
|
||||||
const pingCheckDelay = 10000;
|
const pingCheckDelay = 10000;
|
||||||
|
@ -43,6 +43,7 @@ class GatewayServer extends EventEmitter {
|
||||||
constructor({ server }) {
|
constructor({ server }) {
|
||||||
super();
|
super();
|
||||||
this.wss = new websockets.Server({ server: server, path: "/gateway" });
|
this.wss = new websockets.Server({ server: server, path: "/gateway" });
|
||||||
|
this.sessionCounters = {};
|
||||||
|
|
||||||
this.pingInterval = setInterval(() => {
|
this.pingInterval = setInterval(() => {
|
||||||
this.wss.clients.forEach((client) => {
|
this.wss.clients.forEach((client) => {
|
||||||
|
@ -61,7 +62,7 @@ class GatewayServer extends EventEmitter {
|
||||||
|
|
||||||
this.wss.on("connection", (ws) => {
|
this.wss.on("connection", (ws) => {
|
||||||
// Send HELLO message as soon as the client connects
|
// Send HELLO message as soon as the client connects
|
||||||
ws.send(this.packet("HELLO", {}));
|
ws.send(packet("HELLO", {}));
|
||||||
ws.session = {
|
ws.session = {
|
||||||
authenticated: false,
|
authenticated: false,
|
||||||
user: null,
|
user: null,
|
||||||
|
@ -73,6 +74,21 @@ class GatewayServer extends EventEmitter {
|
||||||
ws.alive = true;
|
ws.alive = true;
|
||||||
});
|
});
|
||||||
ws.on("close", async () => {
|
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();
|
if (ws.rtc) await ws.rtc.connection.close();
|
||||||
});
|
});
|
||||||
ws.on("message", async (data) => {
|
ws.on("message", async (data) => {
|
||||||
|
@ -87,6 +103,12 @@ class GatewayServer extends EventEmitter {
|
||||||
ws.session.user = user;
|
ws.session.user = user;
|
||||||
ws.session.authenticated = true;
|
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
|
// The user is now successfully authenticated, send the YOO_ACK packet
|
||||||
// TODO: This is probably not efficient
|
// TODO: This is probably not efficient
|
||||||
|
|
||||||
|
@ -96,7 +118,30 @@ class GatewayServer extends EventEmitter {
|
||||||
|
|
||||||
ws.channels = channels.map(x => x._id);
|
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`);
|
console.log(`gateway: user ${user.username}: handshake complete`);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log("gateway:", 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
|
// 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.");
|
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,
|
content: messageContent,
|
||||||
channel: {
|
channel: {
|
||||||
_id: message.data.channel._id
|
_id: message.data.channel._id
|
||||||
|
@ -133,7 +178,7 @@ class GatewayServer extends EventEmitter {
|
||||||
case "ACTION_VOICE_REQUEST_SESSION": {
|
case "ACTION_VOICE_REQUEST_SESSION": {
|
||||||
if (!experiments.voiceSFUTesting) return;
|
if (!experiments.voiceSFUTesting) return;
|
||||||
// just send ourselves as the voice server lol
|
// 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",
|
reportTo: "/gateway",
|
||||||
channel: message.data.channel
|
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)
|
answer: await ws.rtc.answer(offer)
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -225,9 +270,4 @@ GatewayServer.prototype.authMessage = function(ws) {
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
GatewayServer.prototype.packet = function(op, data) {
|
|
||||||
if (typeof op === "string") op = getOpcodeByName(op);
|
|
||||||
return `${op}${opcodeSeparator}${JSON.stringify(data)}`;
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = GatewayServer;
|
module.exports = GatewayServer;
|
||||||
|
|
|
@ -4,6 +4,9 @@ const opcodes = {
|
||||||
2: { name: "YOO_ACK", data: "JSON" },
|
2: { name: "YOO_ACK", data: "JSON" },
|
||||||
3: { name: "ACTION_CREATE_MESSAGE", data: "JSON" },
|
3: { name: "ACTION_CREATE_MESSAGE", data: "JSON" },
|
||||||
4: { name: "EVENT_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" },
|
21: { name: "ACTION_VOICE_REQUEST_SESSION", data: "JSON" },
|
||||||
22: { name: "EVENT_VOICE_ASSIGN_SERVER", data: "JSON" },
|
22: { name: "EVENT_VOICE_ASSIGN_SERVER", data: "JSON" },
|
||||||
23: { name: "ACTION_VOICE_CONNECTION_REQUEST", 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;
|
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 = {
|
module.exports = {
|
||||||
experiments: {
|
experiments: {
|
||||||
voiceSFUTesting: false,
|
voiceSFUTesting: false,
|
||||||
userListTest: true
|
userListTest: false
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue