Home Manual Reference Source

src/core/Config.js

import media from './util/Media';
import * as DataSync from './util/DataSync';
import * as Log from './util/Log';
import cache from './util/cache';

const _flattenServers = servers => {
	const _expand = servers.map(server => {
		const {username, credential, urls, url} = server;
		const uris = urls || url;
		if(typeof uris !== 'string' ) {
			return uris.map(uri => ({username, credential, urls: uri}));
		}
		return [server];
	});
	return [].concat(..._expand);
};

/**
 * The Reach configuration object
 * @class Config
 */
export default class Config {
	/**
	 * Create configuration
	 * @access protected
	 * @param obj
	 */
	constructor(obj) {
		/**
		 * The default media constraints. These can be overridden when subscribing to a stream.
		 * @type {MediaStreamConstraints}
		 */
		this.constraints = null;

		/**
		 * The id/element dom element that will hold the local video/audio element
		 * @type {string|Element}
		 */
		this.localStreamContainer = null;
		/**
		 * The id/element dom element that will hold the remote video/audio element
		 * @type {string|Element}
		 */
		this.remoteStreamContainer = null;

		/**
		 * The preferred video Codec. Takes a RegExp matching the codec name and sample rate.
		 * Predefined values can be found in {@link Codec/video}
		 * @type {RegExp}
		 * @example <caption>Prefer VP9</caption>
		 * var myReach = new Reach('https://io.datasync.orange.com/base/<my_namespace>', {
		 *  preferredVideoCodec: Reach.codecs.video.VP9
		 * });
		 */
		this.preferredVideoCodec = null;

		/**
		 * The preferred audio Codec. Takes a RegExp matching the codec name and sample rate.
		 * Predefined values can be found in {@link Codec/audio}
		 * @type {RegExp}
		 * @example <caption>Prefer opus</caption>
		 * var myReach = new Reach('https://io.datasync.orange.com/base/<my_namespace>', {
		 *  preferredAudioCodec: Reach.codecs.audio.OPUS
		 * });
		 */
		this.preferredAudioCodec = null;

		// Populate with default values
		this.reset();

		// Populate with data
		this.assign(obj);

		// Read ICE servers from server
		DataSync.get('_/ice').then(snapData => {
			if(snapData) {
				this.iceServers = snapData.val();
				Log.i('ICEServers', this.iceServers.length > 0 ? this.iceServers : 'None');
			}
		}, e => Log.d('ICEServers', e));

		// TODO #Feat: Add boolean prop to request permission on start, sdpEditor (for user defined SDP modifications)
	}

	/**
	 * Assign new conf values
	 * @access protected
	 * @param {object} obj the new conf values
	 */
	assign(obj) {
		Object.keys(obj || {}).forEach(key => {this[key] = obj[key];});
	}

	/**
	 * The log level (DEBUG, INFO, WARN, ERROR)
	 * @type {string}
	 */
	set logLevel(level) {
		cache.logLevel = level;
	}

	/**
	 * The log level (DEBUG, INFO, WARN, ERROR)
	 * @returns {string}
	 */
	get logLevel() {
		return cache.logLevel;
	}

	/**
	 * List of TURN/STUN servers to use for ICE. This list will be merged with the ICE servers declared in the namespace (**_/ice**).
	 * @type {ICEServer[]}
	 */
	set iceServers(servers) {
		Log.d('Config~set~iceServers', servers);
		if(servers) {
			if (!this._iceServers) {
				/**
				 * @ignore
				 */
				this._iceServers = [].concat(servers || []);
			} else {
				// flatten existing
				const _currentServers = _flattenServers(this._iceServers);
				// flatten new
				const _newServers = _flattenServers(servers);
				// Add only the missing servers
				_newServers.forEach(newServer => {
					if(!_currentServers.some(server =>
							server.urls === newServer.urls &&
							server.username === newServer.username &&
							server.credential === newServer.credential)) {
						_currentServers.push(newServer);
					}
				});
				// Re-group by username/credential
				this._iceServers = _currentServers.reduce((previous, current) => {
					const {username, credential, urls} = current;
					const idx = previous.findIndex(s => s.username === username && s.credential === credential);
					if(idx >= 0) {
						previous[idx].urls.push(urls);
					} else {
						previous.push({username, credential, urls: [urls]});
					}
					return previous;
				}, []);
			}
		}
	}

	/**
	 * List of TURN/STUN servers to use for ICE. This list will be merged with the ICE servers declared in the namespace (**_/ice**).
	 * @type {ICEServer[]}
	 */
	get iceServers() {
		return this._iceServers || [
			{
				username: 'admin',
				credential: 'webcom1234',
				urls: [
					'turns:turn1.webcom.orange.com:443',
					'turn:turn1.webcom.orange.com:443?transport=tcp',
					'turn:turn1.webcom.orange.com:3478?transport=tcp'
				]
			}
		];
	}

	/**
	 * Resets configuration to default values
	 * @protected
	 */
	reset () {
		this.assign({
			constraints: media.constraints(),
			logLevel: 'ERROR'
		});
	}
}