forked from hippoz/brainlet
bump package versions and clean gateway code
This commit is contained in:
parent
680aab399b
commit
0345e0d0a3
5 changed files with 844 additions and 1030 deletions
|
@ -10,6 +10,16 @@ const Channel = require("../../../models/Channel");
|
|||
const { parseMessage, packet } = require("./messageparser");
|
||||
const { checkToken } = require("../../../common/auth/authfunctions");
|
||||
|
||||
const wsCloseCodes = {
|
||||
PAYLOAD_ERROR: [4001, "Error while handling payload"],
|
||||
NOT_AUTHENTICATED: [4002, "Not authenticated"],
|
||||
SERVER_DENIED_CONNECTION: [4003, "Server denied connection"],
|
||||
AUTHENTICATION_ERROR: [4004, "Authentication error"],
|
||||
TOO_MANY_SESSIONS: [4005, "Too many sessions"],
|
||||
NOT_AUTHORIZED: [4006, "Not authorized"],
|
||||
FLOODING: [4007, "Flooding"],
|
||||
};
|
||||
const closeConnectionWithCode = (ws, code) => ws.close(code[0], code[1]);
|
||||
const pingCheckDelay = 10000;
|
||||
|
||||
class GatewayRTCConnection {
|
||||
|
@ -18,7 +28,7 @@ class GatewayRTCConnection {
|
|||
this.server = server;
|
||||
|
||||
this.connection = new werift.RTCPeerConnection();
|
||||
this.connection.onnegotiationneeded.subscribe(() => this.renegotiate);
|
||||
this.connection.onnegotiationneeded.subscribe(() => this.renegotiate); // TODO: what
|
||||
}
|
||||
|
||||
async answer(offer) {
|
||||
|
@ -62,8 +72,7 @@ class GatewayServer extends EventEmitter {
|
|||
});
|
||||
|
||||
this.wss.on("connection", (ws) => {
|
||||
if (!policies.allowGatewayConnection) return ws.close(4007, "Disallowed by policy.");
|
||||
// Send HELLO message as soon as the client connects
|
||||
if (!policies.allowGatewayConnection) return closeConnectionWithCode(ws, wsCloseCodes.SERVER_DENIED_CONNECTION);
|
||||
ws.send(packet("HELLO", {}));
|
||||
ws.session = {
|
||||
authenticated: false,
|
||||
|
@ -75,8 +84,9 @@ class GatewayServer extends EventEmitter {
|
|||
ws.on("pong", () => {
|
||||
ws.alive = true;
|
||||
});
|
||||
ws.on("close", async () => {
|
||||
if (ws.session.user) {
|
||||
ws.on("close", async (code, data) => {
|
||||
console.log(code, data.toString());
|
||||
if (ws.session.user && ws.channels) {
|
||||
if (this.sessionCounters[ws.session.user._id] <= 1) {
|
||||
this.inChannel(ws.channels[0], (client) => {
|
||||
console.log(client.session);
|
||||
|
@ -95,23 +105,22 @@ class GatewayServer extends EventEmitter {
|
|||
|
||||
if (ws.rtc && ws.rtc.connection) await ws.rtc.connection.close();
|
||||
});
|
||||
ws.on("message", async (data) => {
|
||||
ws.on("message", async (data, isBinary) => {
|
||||
try {
|
||||
const message = parseMessage(data);
|
||||
if (isBinary) return closeConnectionWithCode(wsCloseCodes.PAYLOAD_ERROR);
|
||||
const message = parseMessage(data.toString());
|
||||
switch (message.opcodeType) {
|
||||
case "YOO": {
|
||||
// The client has responded to our HELLO with a YOO packet
|
||||
try {
|
||||
const user = await checkToken(message.data.token);
|
||||
if (!user) return ws.close(4006, "Authentication failed.");
|
||||
if (!user) return closeConnectionWithCode(ws, wsCloseCodes.AUTHENTICATION_ERROR);
|
||||
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.");
|
||||
}
|
||||
if (this.sessionCounters[user._id] > policies.perUserMaxGatewayConnections) return closeConnectionWithCode(ws, wsCloseCodes.TOO_MANY_SESSIONS);
|
||||
|
||||
// The user is now successfully authenticated, send the YOO_ACK packet
|
||||
// TODO: This is probably not efficient
|
||||
|
@ -151,7 +160,7 @@ class GatewayServer extends EventEmitter {
|
|||
console.log(`gateway: user ${user.username}: handshake complete`);
|
||||
} catch (e) {
|
||||
console.log("gateway:", e);
|
||||
return ws.close(4006, "Authentication failed.");
|
||||
return closeConnectionWithCode(ws, wsCloseCodes.AUTHENTICATION_ERROR);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -165,7 +174,7 @@ class GatewayServer extends EventEmitter {
|
|||
if (message.data.channel._id.length !== 24) throw new Error("msg: payload has invalid id"); // MONGODB ONLY!!
|
||||
|
||||
// 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 closeConnectionWithCode(ws, wsCloseCodes.NOT_AUTHORIZED);
|
||||
|
||||
this.broadcast(message.data.channel._id, packet("EVENT_CREATE_MESSAGE", {
|
||||
content: messageContent,
|
||||
|
@ -241,7 +250,7 @@ class GatewayServer extends EventEmitter {
|
|||
}
|
||||
} catch(e) {
|
||||
console.error("gateway:", e);
|
||||
return ws.close(4000, "Error while handling payload.");
|
||||
return closeConnectionWithCode(ws, wsCloseCodes.PAYLOAD_ERROR);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -270,7 +279,7 @@ GatewayServer.prototype.clientRTCReady = function(ws) {
|
|||
|
||||
GatewayServer.prototype.authMessage = function(ws) {
|
||||
if (!this.clientReady(ws)) {
|
||||
ws.close(4007, "Not authenticated.");
|
||||
closeConnectionWithCode(ws, wsCloseCodes.NOT_AUTHENTICATED);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
// This is "inspired" by rate-limiter-flexible
|
||||
|
||||
class RateLimiter {
|
||||
constructor({ points=5, time=1000, minPoints=0 }) {
|
||||
this.points = points;
|
||||
this.minPoints = minPoints;
|
||||
this.time = time;
|
||||
|
||||
this._flooding = {};
|
||||
}
|
||||
}
|
||||
|
||||
RateLimiter.prototype.consume = function(discriminator) {
|
||||
if (!this._flooding[discriminator]) this._flooding[discriminator] = { points: this.points, lastReset: Date.now() };
|
||||
|
||||
if (Math.abs(new Date() - this._flooding[discriminator].lastReset) >= this.time) {
|
||||
this._flooding[discriminator] = { points: this.points, lastReset: Date.now() };
|
||||
}
|
||||
|
||||
this._flooding[discriminator].points--;
|
||||
|
||||
if (this._flooding[discriminator].points <= this.minPoints) {
|
||||
this._flooding[discriminator].flooding = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this._flooding[discriminator].flooding === true) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
module.exports = RateLimiter;
|
|
@ -19,6 +19,7 @@ module.exports = {
|
|||
allowAccountCreation: true,
|
||||
allowLogin: true,
|
||||
allowGatewayConnection: true,
|
||||
perUserMaxGatewayConnections: 4,
|
||||
},
|
||||
/*
|
||||
--- Adding a special code requirement for account creation
|
||||
|
|
1783
brainlet/package-lock.json
generated
1783
brainlet/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -18,12 +18,10 @@
|
|||
"express-rate-limit": "^5.1.3",
|
||||
"express-validator": "^6.6.1",
|
||||
"jsonwebtoken": "^8.5.1",
|
||||
"mongoose": "^5.10.0",
|
||||
"semver": "^5.7.1",
|
||||
"socket.io": "^3.0.1",
|
||||
"mongoose": "^6.0.4",
|
||||
"uuid": "^8.3.1",
|
||||
"werift": "^0.9.13",
|
||||
"ws": "^7.4.3"
|
||||
"ws": "^8.2.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "^7.21.0"
|
||||
|
|
Loading…
Reference in a new issue