diff --git a/README.md b/README.md index 7448fd45f..9c3a2ce22 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# SKYLINK WEB SDK 2.6.3 +# SKYLINK WEB SDK 2.7.0 > Temasys SkylinkJS Web SDK is an open-source client-side library for your web-browser that enables any website to easily leverage the capabilities of WebRTC and its direct data streaming powers between peers for audio/video conferencing. You'll need a Temasys Account, and an App key to use this. [Register here to get your App key](https://console.temasys.io). @@ -34,7 +34,7 @@ You'll need a Temasys Account, and an App key to use this. [Register here to get - We recommend that you always use the latest versions of the Temasys SkylinkJS Web SDK as WebRTC is still evolving and we adapt to changes very frequently. - It is advised to not attach any event handlers to the WebRTC APIs as doing so may override the handlers set in SkylinkJS and result in unexpected behaviour. -[Latest version: 2.6.3](https://github.com/Temasys/SkylinkJS/releases/tag/2.6.3) +[Latest version: 2.7.0](https://github.com/Temasys/SkylinkJS/releases/tag/2.7.0) ## How to build your own Temasys SkylinkJS Web SDK diff --git a/package.json b/package.json index 2902b456f..48756d3b9 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "skylinkjs", "description": "Temasys Web SDK is an open-source client-side library for your web-browser that enables any website to easily leverage the capabilities of WebRTC and its direct data streaming powers between peers for audio/video conferencing or file transfer.", - "version": "2.6.3", + "version": "2.7.0", "homepage": "https://temasys.io/", "author": { "name": "Temasys Communications Pte. Ltd.", diff --git a/src/compatibility/ice-connection.js b/src/compatibility/ice-connection.js deleted file mode 100644 index c38225f22..000000000 --- a/src/compatibility/ice-connection.js +++ /dev/null @@ -1,34 +0,0 @@ -import { isAgent } from '../utils/helpers'; -import { BROWSER_AGENT } from '../constants'; - -/** - * @description Gets TCP and UDP ports based on the browser - * @param {Object} params - * @param {boolean} params.forceTURNSSL - * @param {boolean} params.enableTURNServer - * @param {enum} params.CONSTANTS - * @memberOf module:Compatibility - * @return {{tcp: Array, udp: Array, both: Array, iceServerProtocol: string}} - */ -const getConnectionPortsAndProtocolByBrowser = (params) => { - const { forceTURNSSL, serverConfig } = params; - const connectionConfig = { - tcp: serverConfig.iceServerPorts.tcp, - udp: serverConfig.iceServerPorts.udp, - both: serverConfig.iceServerPorts.both, - iceServerProtocol: serverConfig.iceServerProtocol, - iceServerPorts: serverConfig.iceServerPorts, - }; - - if (forceTURNSSL) { - connectionConfig.iceServerPorts.udp = []; - connectionConfig.iceServerProtocol = 'turns'; - } else if (isAgent(BROWSER_AGENT.FIREFOX)) { // default configs are specific to Chrome - connectionConfig.udp = [3478]; - connectionConfig.both = []; - } - - return connectionConfig; -}; - -export default getConnectionPortsAndProtocolByBrowser; diff --git a/src/compatibility/index.js b/src/compatibility/index.js index 0bc32206c..574f5b61e 100644 --- a/src/compatibility/index.js +++ b/src/compatibility/index.js @@ -5,9 +5,7 @@ */ import validateDependencies from './dependencies'; -import getConnectionPortsAndProtocolByBrowser from './ice-connection'; export { validateDependencies, - getConnectionPortsAndProtocolByBrowser, }; diff --git a/src/documentation/typedefs.js b/src/documentation/typedefs.js index a49015b53..fec10b6e8 100644 --- a/src/documentation/typedefs.js +++ b/src/documentation/typedefs.js @@ -103,14 +103,8 @@ * To enable the configuration of this option, you need to enable the "Collect Quality Statistics" option on the Temasys console Website under * App key settings section. * @property {boolean} [enableDataChannel=true] The flag if Datachannel connections should be enabled. - * @property {boolean} [enableTURNServer=true] The flag if TURN ICE servers should - * be used when constructing Peer connections to allow TURN connections when required and enabled for the App Key. - * @property {boolean} [enableSTUNServer=true] The flag if STUN ICE servers should - * be used when constructing Peer connections to allow TURN connections when required. * @property {boolean} [forceTURN=false] The flag if Peer connections should enforce * connections over the TURN server. - *
This overridesenableTURNServer
value totrue
and - *enableSTUNServer
value tofalse
. * @property {boolean} [TURNServerTransport]* Note that configuring the protocol may not necessarily result in the desired network transports protocol * used in the actual TURN network traffic as it depends which protocol the browser selects and connects with. @@ -160,14 +154,10 @@ * Note that the minimum timeout value is5000
. If less, this value will be5000
. * Note that it is recommended to use7000
as the lowest timeout value if Peers are connecting * using Polling transports to prevent connection errors. - * @property {boolean} [forceTURNSSL=false] The flag if TURNS protocol should be used whenenableTURNServer
is enabled. + * @property {boolean} [forceTURNSSL=false] The flag if TURNS protocol should be used. Setting this flag to true setsforceTURN
to true as well. ** Note that currently Firefox does not support the TURNS protocol, and that if TURNS is required, * TURN ICE servers using port443
will be used instead. - * @property {String|Array} [iceServer] The ICE servers for debugging purposes to use. - * - When defined as string, the value is considered as[iceServer]
. - * Note that this is a debugging feature and is only used when instructed for debugging purposes. - * @property {String} [iceServer.#index] The ICE server url for debugging purposes to use. * @property {String|JSON} [socketServer] The Signaling server for debugging purposes to use. * - When defined as string, the value is considered as{ url: socketServer }
. * Note that this is a debugging feature and is only used when instructed for debugging purposes. diff --git a/src/ice-connection/helpers/setIceServers.js b/src/ice-connection/helpers/setIceServers.js index 50eb72b36..2ca5ee36e 100644 --- a/src/ice-connection/helpers/setIceServers.js +++ b/src/ice-connection/helpers/setIceServers.js @@ -1,4 +1,3 @@ -import { getConnectionPortsAndProtocolByBrowser } from '../../compatibility/index'; import { TAGS, TURN_TRANSPORT } from '../../constants'; import Skylink from '../../index'; import logger from '../../logger'; @@ -6,63 +5,39 @@ import MESSAGES from '../../messages'; import { isEmptyArray } from '../../utils/helpers'; const defaultIceServerPorts = { - udp: [3478, 19302, 19303, 19304], - tcp: [80, 443], - both: [19305, 19306, 19307, 19308], + udp: [3478, 53], + tcp: [80, 3478], + ssl: [443, 5349], }; const CONSTANTS = { STUN: 'stun', TURN: 'turn', - TEMASYS: 'temasys', - DEFAULT_TURN_SERVER: 'turn.temasys.io', + TURNS: 'turns', TCP: 'TCP', UDP: 'UDP', }; -const userIceServer = (iceServer, serverConfig) => { - const { urls } = iceServer; - return [{ - urls, - username: serverConfig.iceServers[1].username || null, - credential: serverConfig.iceServers[1].credential || null, - }]; -}; +const getServers = (protocol, servers) => { + const _servers = servers.filter((s) => { + const parts = s.url.split(':'); + const iceServerProtocol = parts[0]; + return iceServerProtocol === protocol; + }).map((s) => { + const parts = s.url.split(':'); + const urlParts = (parts[1] || '').split('@'); + + const iceServerProtocol = parts[0]; + const iceServerName = (urlParts[1] || urlParts[0]).split('?')[0]; + const username = urlParts.length === 2 ? urlParts[0] : ''; + const credential = s.credential || ''; + + return { credential, iceServerName, username, iceServerProtocol }; + }); -const getConnectionPortsByTurnTransport = (params) => { - const { - TURNServerTransport, - forceTURNSSL, - udp, - tcp, - both, - } = params; - const ports = { - udp: [], - tcp: [], - both: [], - }; - if (TURNServerTransport === TURN_TRANSPORT.UDP && !forceTURNSSL) { - ports.udp = udp.concat(both); - ports.tcp = []; - ports.both = []; - } else if (TURNServerTransport === TURN_TRANSPORT.TCP) { - ports.tcp = tcp.concat(both); - ports.udp = []; - ports.both = []; - } else if (TURNServerTransport === TURN_TRANSPORT.NONE) { - ports.tcp = []; - ports.udp = []; - } else { - ports.tcp = tcp; - ports.udp = udp; - ports.both = both; - } - return ports; + return _servers; }; -const getIceServerPorts = () => defaultIceServerPorts; - /** * @param {String} roomKey - The room id * @param {RTCIceServer[]} servers - The list of IceServers passed | {@link https://developer.mozilla.org/en-US/docs/Web/API/RTCIceServer} @@ -73,104 +48,76 @@ const getIceServerPorts = () => defaultIceServerPorts; const setIceServers = (roomKey, servers) => { const initOptions = Skylink.getInitOptions(); const state = Skylink.getSkylinkState(roomKey); - const serverConfig = { - iceServerName: null, - iceServerPorts: getIceServerPorts(), - iceServerProtocol: CONSTANTS.STUN, - iceServers: [{ urls: [] }, { urls: [] }], - }; const { - iceServer, - enableTURNServer, + forceTURN, forceTURNSSL, TURNServerTransport, - enableSTUNServer, - usePublicSTUN, } = initOptions; - servers.forEach((server) => { - if (server.url.indexOf(`${CONSTANTS.STUN}:`) === 0) { - if (server.url.indexOf(`${CONSTANTS.TEMASYS}`) > 0) { - // server[?transport=xxx] - serverConfig.iceServerName = (server.url.split(':')[1] || '').split('?')[0] || null; - } else { - serverConfig.iceServers[0].urls.push(server.url); - } - } else if (server.url.indexOf('turn:') === 0 && server.url.indexOf('@') > 0 && server.credential && !(serverConfig.iceServers[1].username || serverConfig.iceServers[1].credential)) { - /* eslint-disable prefer-destructuring */ - const parts = server.url.split(':'); - const urlParts = (parts[1] || '').split('@'); - serverConfig.iceServerName = (urlParts[1] || '').split('?')[0]; - serverConfig.iceServers[1].username = urlParts[0]; - serverConfig.iceServers[1].credential = server.credential; - serverConfig.iceServerProtocol = CONSTANTS.TURN; - } - }); - - if (iceServer) { - return { iceServers: userIceServer(iceServer, serverConfig) }; - } + const stunServers = getServers(CONSTANTS.STUN, servers); + const turnServers = getServers(CONSTANTS.TURN, servers); + const turnsServers = getServers(CONSTANTS.TURNS, servers); - serverConfig.iceServerName = serverConfig.iceServerName || CONSTANTS.DEFAULT_TURN_SERVER; + const iceServers = []; - if (serverConfig.iceServerProtocol === CONSTANTS.TURN && !enableTURNServer && !forceTURNSSL) { - serverConfig.iceServerProtocol = CONSTANTS.STUN; - } else { - const connectionPortsAndProtocolByBrowser = getConnectionPortsAndProtocolByBrowser({ - forceTURNSSL, - enableTURNServer, - CONSTANTS, - serverConfig, + if (!forceTURN && !forceTURNSSL) { + stunServers.forEach((s) => { + const urls = []; + defaultIceServerPorts.udp.forEach((portNo) => { + urls.push(`${s.iceServerProtocol}:${s.iceServerName}:${portNo}`); + }); + iceServers.push({ urls, credential: s.credential, username: s.username }); }); - serverConfig.iceServerPorts.tcp = connectionPortsAndProtocolByBrowser.tcp; - serverConfig.iceServerPorts.udp = connectionPortsAndProtocolByBrowser.udp; - serverConfig.iceServerPorts.both = connectionPortsAndProtocolByBrowser.both; - serverConfig.iceServerProtocol = connectionPortsAndProtocolByBrowser.iceServerProtocol; } - const connectionPortsByTurnTransport = getConnectionPortsByTurnTransport({ - forceTURNSSL, - TURNServerTransport, - udp: serverConfig.iceServerPorts.udp, - tcp: serverConfig.iceServerPorts.tcp, - both: serverConfig.iceServerPorts.both, - }); + if (!forceTURNSSL) { + turnServers.forEach((s) => { + const urls = []; + if (TURNServerTransport !== TURN_TRANSPORT.TCP) { + defaultIceServerPorts.udp.forEach((portNo) => { + urls.push(`${s.iceServerProtocol}:${s.iceServerName}:${portNo}`); + if (TURNServerTransport !== TURN_TRANSPORT.NONE) { + urls.push(`${s.iceServerProtocol}:${s.iceServerName}:${portNo}?transport=udp`); + } + }); + } - serverConfig.iceServerPorts.tcp = connectionPortsByTurnTransport.tcp; - serverConfig.iceServerPorts.udp = connectionPortsByTurnTransport.udp; - serverConfig.iceServerPorts.both = connectionPortsByTurnTransport.both; + if (TURNServerTransport !== TURN_TRANSPORT.UDP) { + defaultIceServerPorts.tcp.forEach((portNo) => { + if (urls.indexOf(`${s.iceServerProtocol}:${s.iceServerName}:${portNo}`) === -1) { + urls.push(`${s.iceServerProtocol}:${s.iceServerName}:${portNo}`); + } - if (serverConfig.iceServerProtocol === CONSTANTS.STUN) { - serverConfig.iceServerPorts.tcp = []; - } + if (TURNServerTransport !== TURN_TRANSPORT.NONE) { + urls.push(`${s.iceServerProtocol}:${s.iceServerName}:${portNo}?transport=tcp`); + } + }); + } - if (serverConfig.iceServerProtocol === CONSTANTS.STUN && !enableSTUNServer && !state.hasMCU) { - serverConfig.iceServers = []; - } else { - serverConfig.iceServerPorts.tcp.forEach((tcpPort) => { - serverConfig.iceServers[1].urls.push(`${serverConfig.iceServerProtocol}:${serverConfig.iceServerName}:${tcpPort}?transport=tcp`); + iceServers.push({ urls, credential: s.credential, username: s.username }); }); + } - serverConfig.iceServerPorts.udp.forEach((udpPort) => { - serverConfig.iceServers[1].urls.push(`${serverConfig.iceServerProtocol}:${serverConfig.iceServerName}:${udpPort}?transport=udp`); - }); + if (TURNServerTransport !== TURN_TRANSPORT.NONE && TURNServerTransport !== TURN_TRANSPORT.UDP) { + turnsServers.forEach((s) => { + const urls = []; + defaultIceServerPorts.ssl.forEach((portNo) => { + urls.push(`${s.iceServerProtocol}:${s.iceServerName}:${portNo}?transport=tcp`); + }); - serverConfig.iceServerPorts.both.forEach((bothPort) => { - serverConfig.iceServers[1].urls.push(`${serverConfig.iceServerProtocol}:${serverConfig.iceServerName}:${bothPort}`); + iceServers.push({ urls, credential: s.credential, username: s.username }); }); - - if (!usePublicSTUN) { - serverConfig.iceServers.splice(0, 1); - } } - if (isEmptyArray(serverConfig.iceServers) && initOptions.forceTURN && !state.hasMCU) { + if (isEmptyArray(iceServers) && initOptions.forceTURN && !state.hasMCU) { logger.log.WARN([null, TAGS.PEER_CONNECTION, null, MESSAGES.ICE_CONNECTION.TURN_NOT_ENABLED]); + } else if (isEmptyArray(iceServers)) { + logger.log.WARN([null, TAGS.PEER_CONNECTION, null, MESSAGES.ICE_CONNECTION.NO_ICE_SERVERS]); } return { - iceServers: serverConfig.iceServers, + iceServers, }; }; diff --git a/src/messages.js b/src/messages.js index 878c3f368..f5e377838 100644 --- a/src/messages.js +++ b/src/messages.js @@ -108,6 +108,7 @@ const MESSAGES = { DROP_EOC: 'Dropping of sending ICE candidate end-of-candidates signal or unused ICE candidates ->', STATE_CHANGE: 'Ice connection state changed ->', TURN_NOT_ENABLED: 'TURN is not enabled but forceTURN init options is enforced', + NO_ICE_SERVERS: 'No ICE servers. Check init options', }, ICE_CANDIDATE: { DROPPING_CANDIDATE: 'Dropping ICE candidate', @@ -452,4 +453,4 @@ const MESSAGES = { }, }; -export default MESSAGES; \ No newline at end of file +export default MESSAGES; diff --git a/src/server-communication/api-server/api-helpers.js b/src/server-communication/api-server/api-helpers.js index 41737d4bb..f9fc66b13 100644 --- a/src/server-communication/api-server/api-helpers.js +++ b/src/server-communication/api-server/api-helpers.js @@ -86,10 +86,12 @@ export const validateAPIResponse = (response) => { export const parseAndMutateOptions = (options) => { const updatedOptions = options; - // Force TURN connections should enforce settings. - if (updatedOptions.forceTURN === true) { - updatedOptions.enableTURNServer = true; - updatedOptions.enableSTUNServer = false; + // Force TURN and TURNSSL connections should enforce settings. + if (updatedOptions.forceTURNSSL) { + updatedOptions.forceTURN = updatedOptions.forceTURNSSL; + } + + if (updatedOptions.forceTURN === true || updatedOptions.forceTURNSSL === true) { updatedOptions.filterCandidatesType.host = true; updatedOptions.filterCandidatesType.srflx = true; updatedOptions.filterCandidatesType.relay = false; diff --git a/src/server-communication/api-server/defaultOptions.js b/src/server-communication/api-server/defaultOptions.js index 0e144c49b..ef168874f 100644 --- a/src/server-communication/api-server/defaultOptions.js +++ b/src/server-communication/api-server/defaultOptions.js @@ -24,8 +24,6 @@ const defaultOptions = { appKey: null, roomServer: '//api.temasys.io', enableDataChannel: true, - enableSTUNServer: true, - enableTURNServer: true, socketServerPath: null, enableStatsGathering: true, audioFallback: true, @@ -33,7 +31,6 @@ const defaultOptions = { forceTURNSSL: false, forceTURN: false, forceSSL: true, - usePublicSTUN: false, filterCandidatesType: { host: false, srflx: false, @@ -44,7 +41,6 @@ const defaultOptions = { enableSimultaneousTransfers: true, TURNServerTransport: TURN_TRANSPORT.ANY, credentials: null, - iceServer: null, socketServer: null, audioCodec: AUDIO_CODEC.AUTO, videoCodec: VIDEO_CODEC.AUTO, diff --git a/src/server-communication/api-server/index.js b/src/server-communication/api-server/index.js index 79643d726..5bffe5df9 100644 --- a/src/server-communication/api-server/index.js +++ b/src/server-communication/api-server/index.js @@ -80,7 +80,6 @@ class SkylinkAPIServer { throw new Error(webrtcReady.message); } }); - initOptions = parseAndMutateOptions(initOptions); return initOptions; }