diff --git a/app/public/config/config.example.js b/app/public/config/config.example.js index 6d78565..87ee428 100644 --- a/app/public/config/config.example.js +++ b/app/public/config/config.example.js @@ -5,15 +5,7 @@ var config = developmentPort : 3443, productionPort : 443, multipartyServer : 'letsmeet.no', - turnServers : [ - { - urls : [ - 'turn:turn.example.com:443?transport=tcp' - ], - username : 'example', - credential : 'example' - } - ], + /** * If defaultResolution is set, it will override user settings when joining: * low ~ 320x240 @@ -35,8 +27,8 @@ var config = { scaleResolutionDownBy: 1 } ], // Socket.io request timeout - requestTimeout : 10000, - transportOptions : + requestTimeout : 10000, + transportOptions : { tcp : true }, diff --git a/app/src/RoomClient.js b/app/src/RoomClient.js index 6baff6d..070992e 100644 --- a/app/src/RoomClient.js +++ b/app/src/RoomClient.js @@ -26,8 +26,7 @@ let ScreenShare; let Spotlights; -let turnServers, - requestTimeout, +let requestTimeout, transportOptions, lastN, mobileLastN, @@ -36,7 +35,6 @@ let turnServers, if (process.env.NODE_ENV !== 'test') { ({ - turnServers, requestTimeout, transportOptions, lastN, @@ -50,8 +48,7 @@ const logger = new Logger('RoomClient'); const ROOM_OPTIONS = { requestTimeout : requestTimeout, - transportOptions : transportOptions, - turnServers : turnServers + transportOptions : transportOptions }; const VIDEO_CONSTRAINS = @@ -1393,27 +1390,6 @@ export default class RoomClient this._signalingUrl = getSignalingUrl(this._peerId, roomId); - this._torrentSupport = WebTorrent.WEBRTC_SUPPORT; - - this._webTorrent = this._torrentSupport && new WebTorrent({ - tracker : { - rtcConfig : { - iceServers : ROOM_OPTIONS.turnServers - } - } - }); - - this._webTorrent.on('error', (error) => - { - logger.error('Filesharing [error:"%o"]', error); - - store.dispatch(requestActions.notify( - { - type : 'error', - text : intl.formatMessage({ id: 'filesharing.error', defaultMessage: 'There was a filesharing error' }) - })); - }); - this._screenSharing = ScreenShare.create(this._device); this._signalingSocket = io(this._signalingUrl); @@ -1645,6 +1621,10 @@ export default class RoomClient case 'roomReady': { + const { turnServers } = notification.data; + + this._turnServers = turnServers; + store.dispatch(roomActions.toggleJoined()); store.dispatch(roomActions.setInLobby(false)); @@ -2062,6 +2042,27 @@ export default class RoomClient try { + this._torrentSupport = WebTorrent.WEBRTC_SUPPORT; + + this._webTorrent = this._torrentSupport && new WebTorrent({ + tracker : { + rtcConfig : { + iceServers : this._turnServers + } + } + }); + + this._webTorrent.on('error', (error) => + { + logger.error('Filesharing [error:"%o"]', error); + + store.dispatch(requestActions.notify( + { + type : 'error', + text : intl.formatMessage({ id: 'filesharing.error', defaultMessage: 'There was a filesharing error' }) + })); + }); + this._mediasoupDevice = new mediasoupClient.Device(); const routerRtpCapabilities = @@ -2092,7 +2093,7 @@ export default class RoomClient iceParameters, iceCandidates, dtlsParameters, - iceServers : ROOM_OPTIONS.turnServers, + iceServers : this._turnServers, proprietaryConstraints : PC_PROPRIETARY_CONSTRAINTS }); @@ -2154,7 +2155,7 @@ export default class RoomClient iceParameters, iceCandidates, dtlsParameters, - iceServers : ROOM_OPTIONS.turnServers + iceServers : this._turnServers }); this._recvTransport.on( diff --git a/server/config/config.example.js b/server/config/config.example.js index 740a9ae..e0b78e4 100644 --- a/server/config/config.example.js +++ b/server/config/config.example.js @@ -32,6 +32,19 @@ module.exports = } }, */ + // URI and key for requesting geoip-based TURN server closest to the client + turnAPIKey : 'examplekey', + turnAPIURI : 'https://example.com/api/turn', + // Backup turnservers if REST fails or is not configured + backupTurnServers : [ + { + urls : [ + 'turn:turn.example.com:443?transport=tcp' + ], + username : 'example', + credential : 'example' + } + ], redisOptions : {}, // session cookie secret cookieSecret : 'T0P-S3cR3t_cook!e', diff --git a/server/lib/Room.js b/server/lib/Room.js index f25f31d..5d86f11 100644 --- a/server/lib/Room.js +++ b/server/lib/Room.js @@ -1,4 +1,5 @@ const EventEmitter = require('events').EventEmitter; +const axios = require('axios'); const Logger = require('./Logger'); const Lobby = require('./Lobby'); const config = require('../config/config'); @@ -319,7 +320,7 @@ class Room extends EventEmitter } } - _peerJoining(peer) + async _peerJoining(peer) { peer.socket.join(this._roomId); @@ -333,7 +334,46 @@ class Room extends EventEmitter this._peers[peer.id] = peer; this._handlePeer(peer); - this._notification(peer.socket, 'roomReady'); + + 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 cc4e236..b05676d 100644 --- a/server/package.json +++ b/server/package.json @@ -12,6 +12,7 @@ }, "dependencies": { "awaitqueue": "^1.0.0", + "axios": "^0.19.2", "base-64": "^0.1.0", "body-parser": "^1.19.0", "colors": "^1.4.0",