uyem
Version:
WebRTC client-server SFU application
235 lines • 8.16 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
/******************************************************************************************
* Repository: https://github.com/kolserdav/werift-sfu-react.git
* File name: ws.ts
* Author: Sergey Kolmiller
* Email: <uyem.ru@gmail.com>
* License: MIT
* License text: See in LICENSE file
* Copyright: kolserdav, All rights reserved (c)
* Create Date: Wed Aug 24 2022 14:14:09 GMT+0700 (Krasnoyarsk Standard Time)
******************************************************************************************/
const ws_1 = require("ws");
const http_1 = require("http");
const interfaces_1 = require("../types/interfaces");
const lib_1 = require("../utils/lib");
const db_1 = __importDefault(require("./db"));
const http_2 = __importDefault(require("./http"));
const constants_1 = require("../utils/constants");
const server = (0, http_1.createServer)();
class WS extends db_1.default {
connection;
sockets = {};
delimiter = '_';
users = {};
rooms = {};
http;
WebSocket = ws_1.WebSocket;
constructor(connectionArgs) {
const { cloudPath, prisma } = connectionArgs;
super({ prisma });
this.http = new http_2.default({ prisma, cloudPath });
const _connectionArgs = { ...connectionArgs };
_connectionArgs.server = server;
delete _connectionArgs.port;
this.connection = this.createConnection(_connectionArgs);
server.listen(connectionArgs.port);
server.on('request', async (req, res) => {
// CORS
const headers = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'OPTIONS, POST, GET',
'Access-Control-Max-Age': 2592000,
};
if (req.method === 'OPTIONS') {
res.writeHead(204, headers);
res.end();
return;
}
if (['GET', 'POST'].indexOf(req.method || 'GET') > -1) {
Object.keys(headers).forEach((key) => {
res.setHeader(key, headers[key]);
});
}
const { url: _url } = req;
if (!_url) {
res.writeHead(400);
res.end();
return;
}
// Check token
const queryString = _url.match(/\?.*$/);
if (!queryString) {
res.writeHead(422);
res.end();
return;
}
const qS = queryString[0];
const url = _url.replace(qS, '');
const { [interfaces_1.TOKEN_QUERY_NAME]: token } = (0, lib_1.parseQueryString)(qS);
const { errorCode, unitId } = await this.checkTokenCb({ token });
const isDefaultAuth = (0, lib_1.checkDefaultAuth)({ unitId });
if (errorCode !== 0 && !isDefaultAuth) {
res.writeHead(403);
res.end();
return;
}
const isVideos = constants_1.VIDEO_REGEX.test(url || '');
const isTmp = constants_1.TMP_REGEX.test(url || '');
if (isVideos) {
await this.http.getVideoHandler({
isDefaultAuth,
res,
req,
unitId,
url,
});
}
else if (isTmp) {
await this.http.getTmpHandler({
isDefaultAuth,
res,
req,
unitId,
url,
});
}
else {
res.writeHead(501);
res.end();
}
});
}
async setSocket({ id: _id, ws, connId, isRoom, userName, locale, }) {
if ((0, lib_1.checkDefaultAuth)({ unitId: _id.toString() })) {
return;
}
const oldSock = Object.keys(this.sockets).find((item) => {
const sock = item.split(this.delimiter);
return sock[0] === _id.toString();
});
if (oldSock) {
if (this.sockets[oldSock]) {
delete this.sockets[oldSock];
}
}
this.sockets[this.getSocketId(_id.toString(), connId)] = ws;
const id = _id.toString();
if (!isRoom) {
const u = await this.unitFindFirst({
where: {
id,
},
});
if (u) {
await this.unitUpdate({
where: {
id,
},
data: {
name: userName,
updated: new Date(),
},
});
}
else {
await this.unitCreate({
data: {
id,
name: userName,
},
});
}
this.users[id] = {
connId,
name: userName,
locale,
};
}
else {
this.rooms[id] = connId;
}
}
getSocketId(id, connId) {
return `${id}${this.delimiter}${connId}`;
}
findSocketId(id) {
return Object.keys(this.sockets).find((item) => item.split(this.delimiter)[0] === id) || null;
}
createConnection = (args) => {
this.connection = new ws_1.WebSocketServer(args);
return this.connection;
};
// eslint-disable-next-line class-methods-use-this
parseMessage = (message) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let data;
try {
data = JSON.parse(message);
}
catch (err) {
(0, lib_1.log)('error', 'parseMessage', err);
return null;
}
return data;
};
// eslint-disable-next-line class-methods-use-this
getMessage = (type, data) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const res = data;
return res;
};
getLocale({ userId }) {
return (0, lib_1.getLocale)(this.users[userId].locale).server;
}
sendMessage = (args, second, cb) => new Promise((resolve) => {
setTimeout(() => {
let res = '';
try {
res = JSON.stringify(args);
}
catch (e) {
(0, lib_1.log)('error', 'sendMessage', e);
resolve(1);
}
const { id } = args;
(0, lib_1.log)('log', 'Send message', {
id,
data: args.data,
type: args.type,
u: this.users[id],
s: Object.keys(this.sockets[this.getSocketId(id, this.users[id]?.connId)] || {}).length,
r: this.rooms[id],
ss: Object.keys(this.sockets[this.getSocketId(id, this.rooms[id])] || {}).length,
});
let key = '';
if (this.users[id]?.connId && this.sockets[this.getSocketId(id, this.users[id]?.connId)]) {
key = this.getSocketId(id, this.users[id].connId);
}
else if (this.rooms[id] && this.sockets[this.getSocketId(id, this.rooms[id])]) {
key = this.getSocketId(id, this.rooms[id]);
}
if (this.sockets[key]) {
this.sockets[key].send(res, cb);
}
else if (!second) {
setTimeout(() => {
this.sendMessage(args, true, cb);
}, 3000);
}
else {
(0, lib_1.log)('warn', 'Send message without conected socket', {
args,
});
resolve(1);
}
resolve(0);
}, 0);
});
}
exports.default = WS;
//# sourceMappingURL=ws.js.map