UNPKG

webcom-reach

Version:
143 lines (125 loc) 4.2 kB
import PeerConnection from './PeerConnection'; import cache from '../util/cache'; import * as Log from '../util/Log'; import * as DataSync from '../util/DataSync'; const getShortStackId = (id1, id2) => ( id1.localeCompare(id2, 'en-us') > 0 ? `${id1}-${id2}` : `${id2}-${id1}` ); /* eslint-disable no-bitwise */ const hashCode = str => ( str .split('') .reduce((prevHash, currVal) => (((prevHash << 5) - prevHash) + currVal.charCodeAt(0)) | 0, 0) ); /* eslint-enable no-bitwise */ const getStackId = (deviceId1, deviceId2) => { const shortstackId = getShortStackId(deviceId1, deviceId2); const hash = `${hashCode(shortstackId)}`; const length = hash.length; // eslint-disable-line const id1 = hash.substring(length - 3, length); const id2 = hash.substring(length - 6, length - 3); return `${id1}/${id2}/${shortstackId}`; }; /** * @access protected */ export default class PeerConnectionManager { /** * Constructor * @access protected */ constructor() { /** * WebRTC stacks * @type {{*: {*: PeerConnection}}} */ this.stacks = {}; } /** * Get a PeerConnection object for a specific stream * @param {Local|Remote} stream * @param {Remote|{to: string, device:string}} remote * @param {boolean} publish * @return {*} */ getPeerConnection(stream, remote, publish) { if (!cache.user) { return Promise.reject( new Error('Only an authenticated user can get a PeerConnection\'s object.') ); } const stackId = getStackId(remote.device, cache.device); if (this.stacks[stackId] && this.stacks[stackId][stream.uid]) { return Promise.resolve(this.stacks[stackId][stream.uid]); } if (!this.stacks[stackId]) { this.stacks[stackId] = {}; } const userId = cache.user.uid.split('/'); const shortUserId = userId[2]; let shortRemoteTo; let shortRemoteFrom; if (remote.to) { const remoteTo = remote.to.split('/'); shortRemoteTo = remoteTo[2]; // eslint-disable-line prefer-destructuring } else { const remoteFrom = remote.from.split('/'); shortRemoteFrom = remoteFrom[2]; // eslint-disable-line prefer-destructuring } const users = {}; // users[cache.user.uid] = true; users[shortUserId] = true; // users[remote.from || remote.to] = true; users[shortRemoteFrom || shortRemoteTo] = true; return DataSync.update(`_/webrtc/${stackId}`, users) .then(() => new PeerConnection(stackId, stream.uid, remote, publish)) .then((pc) => { Log.d('PeerConnectionManager~getPeerConnection', { stackId, streamId: stream.uid, pc }); this.stacks[stackId][stream.uid] = pc; return pc; }) .catch(Log.r('PeerConnectionManager~getPeerConnection')); } /** * Create offer for a stream to a subscriber * @param {Local} localStream * @param {object} subscriber * @param {array} errorCallbacks * @return {Promise.<PeerConnection>} */ offer(localStream, subscriber, errorCallbacks) { Log.d('PeerConnectionManager~offer', { localStream, subscriber }); return this.getPeerConnection(localStream, subscriber, true) .then(pc => pc.offer(localStream.media, errorCallbacks)); } /** * Answer to the offer from the publisher * @param {Remote} remoteStream * @param {Element} htmlElement * @param {array} errorCallbacks * @return {*|Promise.<PeerConnection>} */ answer(remoteStream, htmlElement, errorCallbacks = []) { Log.d('PeerConnectionManager~answer', { remoteStream, htmlElement }); return this.getPeerConnection(remoteStream, remoteStream, false) .then(pc => pc.answer(htmlElement, errorCallbacks)); } /** * Close a PeerConnection * @param streamId * @param remoteDevice * @return {*} */ close(streamId, remoteDevice) { const stackId = getStackId(remoteDevice, cache.device); const pc = this.stacks[stackId] ? this.stacks[stackId][streamId] : null; if (pc) { pc.close(); DataSync.remove(`_/webrtc/${stackId}`); this.stacks[stackId][streamId] = null; delete this.stacks[stackId][streamId]; return pc; } return false; } }