93 lines
3.5 KiB
JavaScript
93 lines
3.5 KiB
JavaScript
"use strict";
|
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
};
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const events_1 = __importDefault(require("events"));
|
|
const url_1 = __importDefault(require("url"));
|
|
const ws_1 = __importDefault(require("ws"));
|
|
const enums_1 = require("../../enums");
|
|
const client_1 = require("../../models/client");
|
|
const WS_PATH = 'peerjs';
|
|
class WebSocketServer extends events_1.default {
|
|
constructor({ server, realm, config }) {
|
|
super();
|
|
this.setMaxListeners(0);
|
|
this.realm = realm;
|
|
this.config = config;
|
|
const path = this.config.path;
|
|
this.path = `${path}${path.endsWith('/') ? "" : "/"}${WS_PATH}`;
|
|
this.socketServer = new ws_1.default.Server({ path: this.path, server });
|
|
this.socketServer.on("connection", (socket, req) => this._onSocketConnection(socket, req));
|
|
this.socketServer.on("error", (error) => this._onSocketError(error));
|
|
}
|
|
_onSocketConnection(socket, req) {
|
|
const { query = {} } = url_1.default.parse(req.url, true);
|
|
const { id, token, key } = query;
|
|
if (!id || !token || !key) {
|
|
return this._sendErrorAndClose(socket, enums_1.Errors.INVALID_WS_PARAMETERS);
|
|
}
|
|
if (key !== this.config.key) {
|
|
return this._sendErrorAndClose(socket, enums_1.Errors.INVALID_KEY);
|
|
}
|
|
const client = this.realm.getClientById(id);
|
|
if (client) {
|
|
if (token !== client.getToken()) {
|
|
// ID-taken, invalid token
|
|
socket.send(JSON.stringify({
|
|
type: enums_1.MessageType.ID_TAKEN,
|
|
payload: { msg: "ID is taken" }
|
|
}));
|
|
return socket.close();
|
|
}
|
|
return this._configureWS(socket, client);
|
|
}
|
|
this._registerClient({ socket, id, token });
|
|
}
|
|
_onSocketError(error) {
|
|
// handle error
|
|
this.emit("error", error);
|
|
}
|
|
_registerClient({ socket, id, token }) {
|
|
// Check concurrent limit
|
|
const clientsCount = this.realm.getClientsIds().length;
|
|
if (clientsCount >= this.config.concurrent_limit) {
|
|
return this._sendErrorAndClose(socket, enums_1.Errors.CONNECTION_LIMIT_EXCEED);
|
|
}
|
|
const newClient = new client_1.Client({ id, token });
|
|
this.realm.setClient(newClient, id);
|
|
socket.send(JSON.stringify({ type: enums_1.MessageType.OPEN }));
|
|
this._configureWS(socket, newClient);
|
|
}
|
|
_configureWS(socket, client) {
|
|
client.setSocket(socket);
|
|
// Cleanup after a socket closes.
|
|
socket.on("close", () => {
|
|
if (client.getSocket() === socket) {
|
|
this.realm.removeClientById(client.getId());
|
|
this.emit("close", client);
|
|
}
|
|
});
|
|
// Handle messages from peers.
|
|
socket.on("message", (data) => {
|
|
try {
|
|
const message = JSON.parse(data);
|
|
message.src = client.getId();
|
|
this.emit("message", client, message);
|
|
}
|
|
catch (e) {
|
|
this.emit("error", e);
|
|
}
|
|
});
|
|
this.emit("connection", client);
|
|
}
|
|
_sendErrorAndClose(socket, msg) {
|
|
socket.send(JSON.stringify({
|
|
type: enums_1.MessageType.ERROR,
|
|
payload: { msg }
|
|
}));
|
|
socket.close();
|
|
}
|
|
}
|
|
exports.WebSocketServer = WebSocketServer;
|