Skip to content

Commit

Permalink
Merge pull request #486 from Temasys/2.x.x/development
Browse files Browse the repository at this point in the history
Release 2.7.0
  • Loading branch information
dinawee authored Oct 29, 2024
2 parents 6ddd400 + cb5a6f1 commit 68c070d
Show file tree
Hide file tree
Showing 10 changed files with 79 additions and 180 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -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).
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -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.",
Expand Down
34 changes: 0 additions & 34 deletions src/compatibility/ice-connection.js

This file was deleted.

2 changes: 0 additions & 2 deletions src/compatibility/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@
*/

import validateDependencies from './dependencies';
import getConnectionPortsAndProtocolByBrowser from './ice-connection';

export {
validateDependencies,
getConnectionPortsAndProtocolByBrowser,
};
12 changes: 1 addition & 11 deletions src/documentation/typedefs.js
Original file line number Diff line number Diff line change
Expand Up @@ -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.
* <blockquote>This overrides <code>enableTURNServer</code> value to <code>true</code> and
* <code>enableSTUNServer</code> value to <code>false</code>.
* @property {boolean} [TURNServerTransport] <blockquote class="info">
* 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.
Expand Down Expand Up @@ -160,14 +154,10 @@
* Note that the minimum timeout value is <code>5000</code>. If less, this value will be <code>5000</code>.
* Note that it is recommended to use <code>7000</code> 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 when <code>enableTURNServer</code> is enabled.
* @property {boolean} [forceTURNSSL=false] The flag if TURNS protocol should be used. Setting this flag to true sets <code>forceTURN</code> to true as well.
* <blockquote class="info">
* Note that currently Firefox does not support the TURNS protocol, and that if TURNS is required,
* TURN ICE servers using port <code>443</code> 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 <code>[iceServer]</code>.
* 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 <code>{ url: socketServer }</code>.
* Note that this is a debugging feature and is only used when instructed for debugging purposes.
Expand Down
187 changes: 67 additions & 120 deletions src/ice-connection/helpers/setIceServers.js
Original file line number Diff line number Diff line change
@@ -1,68 +1,43 @@
import { getConnectionPortsAndProtocolByBrowser } from '../../compatibility/index';
import { TAGS, TURN_TRANSPORT } from '../../constants';
import Skylink from '../../index';
import logger from '../../logger';
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}
Expand All @@ -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,
};
};

Expand Down
3 changes: 2 additions & 1 deletion src/messages.js
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down Expand Up @@ -452,4 +453,4 @@ const MESSAGES = {
},
};

export default MESSAGES;
export default MESSAGES;
10 changes: 6 additions & 4 deletions src/server-communication/api-server/api-helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
4 changes: 0 additions & 4 deletions src/server-communication/api-server/defaultOptions.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,13 @@ const defaultOptions = {
appKey: null,
roomServer: '//api.temasys.io',
enableDataChannel: true,
enableSTUNServer: true,
enableTURNServer: true,
socketServerPath: null,
enableStatsGathering: true,
audioFallback: true,
socketTimeout: 7000,
forceTURNSSL: false,
forceTURN: false,
forceSSL: true,
usePublicSTUN: false,
filterCandidatesType: {
host: false,
srflx: false,
Expand All @@ -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,
Expand Down
Loading

0 comments on commit 68c070d

Please sign in to comment.