![]() System : Linux absol.cf 5.4.0-198-generic #218-Ubuntu SMP Fri Sep 27 20:18:53 UTC 2024 x86_64 User : www-data ( 33) PHP Version : 7.4.33 Disable Function : pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare, Directory : /var/www/html/gadevoir/server/ |
Upload File : |
const Conversation = require("./Conversation"); const mediasoup = require('mediasoup'); const fs = require('fs'); const https = require('https'); const express = require('express'); const socketIO = require('socket.io'); var cors = require('cors'); const uuidv4 = require('uuid').v4; const User = require('./User'); function GDVServer(config) { this.config = config; /*** * * @type {User[]} */ this.userList = []; this._setupMediaSoup() .then(this._setupExpress.bind(this)) .then(this._setupWebServer.bind(this)) .then(this._setupSocketSever.bind(this)); } GDVServer.prototype._setupMediaSoup = function () { var server = this; return mediasoup.createWorker({ logLevel: this.config.mediasoup.worker.logLevel, logTags: this.config.mediasoup.worker.logTags, rtcMinPort: this.config.mediasoup.worker.rtcMinPort, rtcMaxPort: this.config.mediasoup.worker.rtcMaxPort }).then(function (worker) { worker.on('died', () => { console.error('mediasoup worker died, exiting in 2 seconds... [pid:%d]', worker.pid); setTimeout(() => process.exit(1), 2000); }); server.mediaSoupWorker = worker; }); }; GDVServer.prototype._setupExpress = function () { this.expressApp = express(); this.expressApp.use(cors()); this.expressApp.use(express.json()); this.expressApp.use(express.static(__dirname)); this.expressApp.use(this._expressRouteDefault.bind(this)); }; GDVServer.prototype._setupWebServer = function () { const config = this.config; const { sslKey, sslCrt } = config; if (!fs.existsSync(sslKey) || !fs.existsSync(sslCrt)) { console.error('SSL files are not found. check your config.js file'); process.exit(0); } const tls = { cert: fs.readFileSync(sslCrt), key: fs.readFileSync(sslKey), }; var webServer = https.createServer(tls, this.expressApp); this.webServer = webServer; this.webServer.on('error', (err) => { console.error('starting web server failed:', err.message); }); return new Promise((resolve) => { const { ip, port, host } = config; webServer.listen(port, () => { console.log('server is running'); console.log(`open https://${host}:${port} in your web browser`); resolve(); }); }) }; /*** * * @param {Error} error * @param {Request} req * @param {Response}res * @param {NextFunction} next * @private */ GDVServer.prototype._expressRouteDefault = function (error, req, res, next) { }; GDVServer.prototype._setupSocketSever = function () { var socketServer = socketIO(this.webServer, { serveClient: false, path: '/server', log: false, }); this.socketServer = socketServer; socketServer.on('connection', this._socketClient.bind(this)) }; GDVServer.prototype._socketClient = function (clientSk) { clientSk.on('login', this._socketLogin.bind(this, clientSk)); clientSk.on('disconnect', this._socketDisconnect.bind(this, clientSk)); clientSk.on('getContactList', this._socketGetContactList.bind(this, clientSk)); clientSk.on('callTo', this._socketCallTo.bind(this, clientSk)); clientSk.on('getRouterRtpCapabilities', this._socketGetRouterRtpCapabilities.bind(this, clientSk)); }; GDVServer.prototype._socketLogin = function (clientSk, userData, resolveCb) { var userName = userData.userName; var password = userData.password; var token = userData.token; if (!userName || (!password && !token)) { resolveCb({ error: "INVALID_LOGIN_PARAM" }); return; } var user = this.findUserByName(userName); var isNew = false; if (user) { if (user.online && user.socket.id !== clientSk.id) { resolveCb({ error: "LOGIN_IN_OTHER" }); return; } else if (user.password === password || user.token === token) { user.socket = clientSk; user.online = true; user.token = Array(32).fill(0).map(function () { return '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'[Math.random() * 62 >> 0] }).join(''); console.log("RELOGIN", user.name); } else { resolveCb({ error: "LOGIN_FAIL" }); return; } } else { isNew = true; user = new User({ online: true, id: clientSk.id, name: userName, password: password, socket: clientSk, token: Array(32).fill(0).map(function () { return '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'[Math.random() * 62 >> 0] }).join('') }); user.routerSync = this.mediaSoupWorker.createRouter({ mediaCodecs: this.config.mediasoup.router.mediaCodecs }) .then(function (router) { user.router = router; return router; }); this.userList.push(user); console.log("NEW_USER", user.name); } this.notifyOnlineToOther(user); resolveCb({ isNew: isNew, id: user.id, name: userName, token: user.token }); }; GDVServer.prototype._socketGetContactList = function (clientSk, data, resolveCb) { var user = this.findUserBySocketId(clientSk.id); if (user) resolveCb(this.getUserInfoList().filter(function (item) { return item.name !== user.name; })); else resolveCb({ error: "NO_LOGIN" }) }; GDVServer.prototype._socketCallTo = function (socketSk, data) { var server = this; var user = this.findUserBySocketId(socketSk.id); var destUser = this.findUserByName(data.userName); var destUserName = data.userName; var conversationId = data.conversationId; var timeout; if (user) { if (destUser) { if (destUser.online && destUser.socket) { timeout = setTimeout(function () { socketSk.emit("outcome_response", { error: "USER_NOT_RESPONSE", userName: destUserName }) }, 20000); function incomeResponseCb(data) { if (data.conversationId === conversationId) { clearTimeout(timeout); destUser.socket.off('income_response', incomeResponseCb); user.socket.off('outgoing_cancel', outgoingCancelCb); if (data.answer === "ACCEPT") { var conversation = new Conversation(server, { outgoingUser: user, incomeUser: destUser, conversationId: conversationId }); conversation.start(); } else { } socketSk.emit("outgoing_response", { answer: data.answer, userName: destUserName, conversationId: conversationId }); } } function outgoingCancelCb(data) { if (data.conversationId === conversationId) { clearTimeout(timeout); destUser.socket.off('income_response', incomeResponseCb); user.socket.off('outgoing_cancel', outgoingCancelCb); destUser.socket.emit('income_cancel', { conversationId: conversationId }); } } destUser.socket.on('income_response', incomeResponseCb); user.socket.on('outgoing_cancel', outgoingCancelCb); destUser.socket.emit('income', { userName: user.name, type: data.type, conversationId: conversationId }); } else { socketSk.emit('outgoing_response', { error: "USER_OFFLINE", userName: destUserName, conversationId: conversationId }); } } else { socketSk.emit("outgoing_response", { error: "USER_NOT_EXIST", userName: destUserName, conversationId: conversationId }); } } else socketSk.emit('outgoing_response', { error: "NOT_LOGIN", userName: destUserName, conversationId: conversationId }); }; GDVServer.prototype._socketGetRouterRtpCapabilities = function (clientSk, data, resolveCb) { var user = this.findUserBySocketId(clientSk.id); user.routerSync.then(function (router) { resolveCb(router.rtpCapabilities); }) }; GDVServer.prototype._socketDisconnect = function (clientSk) { var user = this.findUserBySocketId(clientSk.id); if (user) { user.online = false; user.socket = null; this.notifyOfflineToOther(user); console.log("OFFLINE", user.name); } }; GDVServer.prototype.createWebRtcTransport = function (user) { const { maxIncomingBitrate, initialAvailableOutgoingBitrate } = this.config.mediasoup.webRtcTransport; const res = {}; var server = this; return user.routerSync.then(function (router) { return router.createWebRtcTransport({ listenIps: server.config.mediasoup.webRtcTransport.listenIps, enableUdp: true, enableTcp: true, preferUdp: true, initialAvailableOutgoingBitrate, }).then(function (transport) { res.transport = transport; if (maxIncomingBitrate) { try { return transport.setMaxIncomingBitrate(maxIncomingBitrate); } catch (error) { } } }).then(function () { res.params = { id: res.transport.id, iceParameters: res.transport.iceParameters, iceCandidates: res.transport.iceCandidates, dtlsParameters: res.transport.dtlsParameters } return res; }); }); }; GDVServer.prototype.findUserByName = function (name) { return this.userList.find(function (item) { return item.name === name; }); }; GDVServer.prototype.findUserById = function (id) { return this.userList.find(function (item) { return item.id = id; }); }; GDVServer.prototype.findUserBySocketId = function (socketId) { return this.userList.find(function (item) { return item.socket && item.socket.id === socketId; }); }; GDVServer.prototype.notifyOnlineToOther = function (user) { var userInfo = user.toPublicInfo(); this.userList.forEach(function (item) { if (item.id === user.id) return; if (item.online && item.socket) { item.socket.emit('other_online', userInfo) } }); }; GDVServer.prototype.notifyOfflineToOther = function (user) { this.userList.forEach(function (item) { var userInfo = user.toPublicInfo(); if (item.id === user.id) return; if (item.online && item.socket) { item.socket.emit('other_offline', userInfo); } }); }; GDVServer.prototype.getUserInfoList = function () { return this.userList.map(function (item) { return item.toPublicInfo(); }) } module.exports = GDVServer;