From d20f0c161fe46c7db4cb5c3ac478260a7d3a9ec4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5var=20Aamb=C3=B8=20Fosstveit?= Date: Fri, 27 Mar 2020 01:36:11 +0100 Subject: [PATCH] Handle client reconnects better --- app/src/RoomClient.js | 29 +++++++++++ server/lib/Room.js | 115 ++++++++++++++++++++++++++++-------------- server/package.json | 4 +- server/server.js | 4 +- 4 files changed, 111 insertions(+), 41 deletions(-) diff --git a/app/src/RoomClient.js b/app/src/RoomClient.js index e133a30..204643d 100644 --- a/app/src/RoomClient.js +++ b/app/src/RoomClient.js @@ -1520,6 +1520,28 @@ export default class RoomClient }) })); + if (this._screenSharingProducer) + this._screenSharingProducer.close(); + + if (this._webcamProducer) + this._webcamProducer.close(); + + if (this._micProducer) + this._micProducer.close(); + + // Close mediasoup Transports. + if (this._sendTransport) + { + this._sendTransport.close(); + this._sendTransport = null; + } + + if (this._recvTransport) + { + this._recvTransport.close(); + this._recvTransport = null; + } + store.dispatch(roomActions.setRoomState('connecting')); }); @@ -1721,6 +1743,13 @@ export default class RoomClient break; } + + case 'roomBack': + { + await this._joinRoom({ joinVideo }); + + break; + } case 'lockRoom': { diff --git a/server/lib/Room.js b/server/lib/Room.js index f0ceb66..b6ee85b 100644 --- a/server/lib/Room.js +++ b/server/lib/Room.js @@ -2,6 +2,8 @@ const EventEmitter = require('events').EventEmitter; const axios = require('axios'); const Logger = require('./Logger'); const Lobby = require('./Lobby'); +const { v4: uuidv4 } = require('uuid'); +const jwt = require('jsonwebtoken'); const userRoles = require('../userRoles'); const config = require('../config/config'); @@ -46,6 +48,8 @@ class Room extends EventEmitter super(); this.setMaxListeners(Infinity); + this._uuid = uuidv4(); + // Room ID. this._roomId = roomId; @@ -120,9 +124,26 @@ class Room extends EventEmitter this.emit('close'); } - handlePeer(peer) + handlePeer({ peer, token }) { - logger.info('handlePeer() [peer:"%s", roles:"%s"]', peer.id, peer.roles); + logger.info('handlePeer() [peer:"%s", roles:"%s", token:"%s"]', peer.id, peer.roles, token); + + let verifiedPeer = false; + + if (token) + { + try + { + const decoded = jwt.verify(token, this._uuid); + + if (decoded.id === peer.id) + verifiedPeer = true; + } + catch (err) + { + logger.warn('handlePeer() | invalid token'); + } + } // Allow reconnections, remove old peer if (this._peers[peer.id]) @@ -134,8 +155,11 @@ class Room extends EventEmitter this._peers[peer.id].close(); } + // Returning user + if (verifiedPeer) + this._peerJoining(peer, true); // Always let ADMIN in, even if locked - if (peer.roles.includes(userRoles.ADMIN)) + else if (peer.roles.includes(userRoles.ADMIN)) this._peerJoining(peer); else if (this._locked) this._parkPeer(peer); @@ -332,7 +356,7 @@ class Room extends EventEmitter } } - async _peerJoining(peer) + async _peerJoining(peer, returning = false) { peer.socket.join(this._roomId); @@ -343,45 +367,58 @@ class Room extends EventEmitter this._handlePeer(peer); - let turnServers; - - if ('turnAPIURI' in config) + if (returning) { - try - { - const { data } = await axios.get( - config.turnAPIURI, - { - params : { - 'uri_schema' : 'turn', - 'transport' : 'tcp', - 'ip_ver' : 'ipv4', - 'servercount' : '2', - 'api_key' : config.turnAPIKey, - 'ip' : peer.socket.request.connection.remoteAddress - } - }); - - turnServers = [ { - urls : data.uris, - username : data.username, - credential : data.password - } ]; - } - catch (error) - { - if ('backupTurnServers' in config) - turnServers = config.backupTurnServers; - - logger.error('_peerJoining() | error on REST turn [error:"%o"]', error); - } + this._notification(peer.socket, 'roomBack'); } - else if ('backupTurnServers' in config) + else { - turnServers = config.backupTurnServers; - } + const token = jwt.sign({ id: peer.id }, this._uuid, { noTimestamp: true }); - this._notification(peer.socket, 'roomReady', { turnServers }); + peer.socket.handshake.session.token = token; + + peer.socket.handshake.session.save(); + + let turnServers; + + if ('turnAPIURI' in config) + { + try + { + const { data } = await axios.get( + config.turnAPIURI, + { + params : { + 'uri_schema' : 'turn', + 'transport' : 'tcp', + 'ip_ver' : 'ipv4', + 'servercount' : '2', + 'api_key' : config.turnAPIKey, + 'ip' : peer.socket.request.connection.remoteAddress + } + }); + + turnServers = [ { + urls : data.uris, + username : data.username, + credential : data.password + } ]; + } + catch (error) + { + if ('backupTurnServers' in config) + turnServers = config.backupTurnServers; + + logger.error('_peerJoining() | error on REST turn [error:"%o"]', error); + } + } + else if ('backupTurnServers' in config) + { + turnServers = config.backupTurnServers; + } + + this._notification(peer.socket, 'roomReady', { turnServers }); + } } _handlePeer(peer) diff --git a/server/package.json b/server/package.json index b05676d..ae1f3b9 100644 --- a/server/package.json +++ b/server/package.json @@ -25,6 +25,7 @@ "express-socket.io-session": "^1.3.5", "helmet": "^3.21.2", "ims-lti": "^3.0.2", + "jsonwebtoken": "^8.5.1", "mediasoup": "^3.5.5", "openid-client": "^3.7.3", "passport": "^0.4.0", @@ -32,6 +33,7 @@ "pidusage": "^2.0.17", "redis": "^2.8.0", "socket.io": "^2.3.0", - "spdy": "^4.0.1" + "spdy": "^4.0.1", + "uuid": "^7.0.2" } } diff --git a/server/server.js b/server/server.js index ebf951e..2e50a8c 100755 --- a/server/server.js +++ b/server/server.js @@ -467,6 +467,8 @@ async function runWebSocketServer() const room = await getOrCreateRoom({ roomId }); const peer = new Peer({ id: peerId, roomId, socket }); + const { token } = socket.handshake.session; + peers.set(peerId, peer); peer.on('close', () => peers.delete(peerId)); @@ -495,7 +497,7 @@ async function runWebSocketServer() } } - room.handlePeer(peer); + room.handlePeer({ peer, token }); }) .catch((error) => {