UNPKG

ivcbox-adapter

Version:
827 lines 36.7 kB
"use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); Object.defineProperty(exports, "__esModule", { value: true }); var log_1 = require("./services/log"); var common_1 = require("./services/common"); var AdapterJS = require("./libraries/AdapterJs.js"); var Base_1 = require("./Base"); var WebRtc = /** @class */ (function (_super) { __extends(WebRtc, _super); function WebRtc() { var _this = _super.call(this) || this; /* * Use for detecting if connection was closed because of lost connection */ // protected peerConnectionsDisabled: any[]; _this.VIDEO_RESOLUTION = { QQVGA: { width: 160, height: 120 /*, aspectRatio: '4:3'*/ }, HQVGA: { width: 240, height: 160 /*, aspectRatio: '3:2'*/ }, QVGA: { width: 320, height: 240 /*, aspectRatio: '4:3'*/ }, WQVGA: { width: 384, height: 240 /*, aspectRatio: '16:10'*/ }, HVGA: { width: 480, height: 320 /*, aspectRatio: '3:2'*/ }, VGA: { width: 640, height: 480 /*, aspectRatio: '4:3'*/ }, WVGA: { width: 768, height: 480 /*, aspectRatio: '16:10'*/ }, FWVGA: { width: 854, height: 480 /*, aspectRatio: '16:9'*/ }, SVGA: { width: 800, height: 600 /*, aspectRatio: '4:3'*/ }, DVGA: { width: 960, height: 640 /*, aspectRatio: '3:2'*/ }, WSVGA: { width: 1024, height: 576 /*, aspectRatio: '16:9'*/ }, HD: { width: 1280, height: 720 /*, aspectRatio: '16:9'*/ }, HDPLUS: { width: 1600, height: 900 /*, aspectRatio: '16:9'*/ }, FHD: { width: 1920, height: 1080 /*, aspectRatio: '16:9'*/ }, QHD: { width: 2560, height: 1440 /*, aspectRatio: '16:9'*/ }, WQXGAPLUS: { width: 3200, height: 1800 /*, aspectRatio: '16:9'*/ }, UHD: { width: 3840, height: 2160 /*, aspectRatio: '16:9'*/ }, UHDPLUS: { width: 5120, height: 2880 /*, aspectRatio: '16:9'*/ }, FUHD: { width: 7680, height: 4320 /*, aspectRatio: '16:9'*/ }, QUHD: { width: 15360, height: 8640 /*, aspectRatio: '16:9'*/ } }; _this.HANDSHAKE_PROGRESS = { OFFER: 'offer', ANSWER: 'answer', ERROR: 'error' }; _this.PEER_CONNECTION_STATE = { STABLE: 'stable', CLOSED: 'closed' }; _this.mediaOptions = { video: true, audio: true }; /** * Stores the stun and turn configs */ _this.peerConnectionConfig = {}; /** * @attribute localStream */ _this.localStream = null; /** * Stores the list of the Peer connections. */ _this.peerConnections = {}; /** * Stores the list of buffered ICE candidates that is received before */ _this.peerCandidatesQueue = []; _this.timestamp = { getUserMedia: null }; _this.peerConnectionsTimer = { disconnected: {}, failed: {} }; _this.peerConnectionsFailedCounter = 0; _this.peerConnectionsFailed = false; return _this; } WebRtc.prototype.init = function (options, callback) { var self = this; self.initialization(options, callback); self.addWebRtcWatchers(); }; WebRtc.prototype.initRtcConnection = function (payload) { var self = this; self.clearRtcConnections(); var requestObj = { roomHash: payload.roomHash, rtcType: payload.rtcType ? payload.rtcType : 0 }; self.stompClient.send('/app/ws/room/initRtcConnection', {}, JSON.stringify(requestObj)); }; WebRtc.prototype.closeRtcConnection = function (payload) { var self = this; self.clearRtcConnections(); var requestObj = { roomHash: payload.roomHash }; self.stompClient.send('/app/ws/room/closeRtcConnection', {}, JSON.stringify(requestObj)); }; WebRtc.prototype.leaveRtcConnection = function () { var self = this; if (self.localStream) { self.localStream.getTracks().forEach(function (track) { track.stop(); }); self.clearRtcConnections(); self.stompClient.send('/app/ws/room/leaveRtcConnection', {}, null); } }; WebRtc.prototype.getUserMedia = function (options, callback) { var self = this; if (typeof options === 'undefined' || typeof options !== 'object' || options === null) { options = { audio: true, video: true }; } self.mediaOptions = options; self.throttle(function () { if (typeof callback === 'function') { var mediaAccessSuccessFn = function (stream) { self.off('_mediaAccessError'); callback(null, stream); }; var mediaAccessErrorFn = function (error) { self.off('_mediaAccessSuccess'); callback(error, null); }; self.once('_mediaAccessSuccess', mediaAccessSuccessFn, function () { return true; }); self.once('_mediaAccessError', mediaAccessErrorFn, function (error) { log_1.default.error(['_mediaAccessError', error]); return true; }); } var settings = self.parseStreamSettings(options); var onSuccessCbFn = function (stream) { self.onStreamAccessSuccess(stream); self.trigger('_mediaAccessSuccess', stream); }; var onErrorCbFn = function (error) { self.onStreamAccessError(error); self.trigger('_mediaAccessError', error); }; try { AdapterJS.webRTCReady(function () { navigator.getUserMedia(settings.getUserMediaSettings, onSuccessCbFn, onErrorCbFn); }); } catch (error) { onErrorCbFn(error); } }, 'getUserMedia', 0); }; /** * Check device availability */ WebRtc.prototype.checkDevices = function (triggerName) { if (triggerName === void 0) { triggerName = 'mediaAccessError'; } var self = this; var MediaDevices = []; var hasMicrophone = false; var hasCamera = false; navigator.mediaDevices.enumerateDevices().then(function (devices) { devices.forEach(function (deviceObj) { var device = {}; for (var d in deviceObj) { if (deviceObj.hasOwnProperty(d)) { device[d] = deviceObj[d]; } } var skip = false; MediaDevices.forEach(function (d) { if (d.id === device.id && d.kind === device.kind) { skip = true; } }); if (skip) { return; } if (!device.id) { device.id = device.deviceId; } if (device.kind === 'audio' && device.kind === 'audioinput') { hasMicrophone = true; } if (device.kind === 'video' || device.kind === 'videoinput') { hasCamera = true; } MediaDevices.push(device); }); }).then(function () { self.trigger(triggerName, { error: 'no access', microphone: hasMicrophone, camera: hasCamera }); }).catch(function (error) { self.trigger(triggerName, { error: error }); }); }; WebRtc.prototype.addWebRtcWatchers = function () { var self = this; self.on('rtcConfigsSignal', function (data) { self.processConnectionConfig(data); }); self.on('newRtcConnectionSignal', function (data) { self.newRtcConnection(data); }); self.on('rtcDescriptionSignal', function (data) { self.processRtcDescription(data); }); self.on('rtcCandidatesSignal', function (data) { self.processIceCandidate(data); }); self.on('userLeftRtcSignal', function (data) { self.processRtcLeave(data); }); self.on('initConnectionResponse', function () { self.getConnectionConfig(); }); }; /** * Запрос на получение RTC конфигов */ WebRtc.prototype.getConnectionConfig = function () { var self = this; self.stompClient.send('/app/ws/rtcConfigs', {}, JSON.stringify({})); }; WebRtc.prototype.processConnectionConfig = function (connectionConfig) { var self = this; self.peerConnectionConfig = { iceServers: [ { urls: 'stun:' + connectionConfig.stunUrl }, { urls: 'turn:' + connectionConfig.turnUrl + '?transport=udp', credential: connectionConfig.turnCredential, username: connectionConfig.turnUsername }, { urls: 'turn:' + connectionConfig.turnUrl + '?transport=tcp', credential: connectionConfig.turnCredential, username: connectionConfig.turnUsername } ] }; }; WebRtc.prototype.newRtcConnection = function (payload) { var self = this; var targetMid = payload.fromUserId; if (!self.localStream) { return; } self.addPeer(targetMid, payload, function () { try { self.localStream.getTracks().forEach(function (track) { self.peerConnections[targetMid].addTrack(track, self.localStream); }); } catch (err) { self.peerConnections[targetMid].addStream(self.localStream); } self.peerConnections[targetMid].createOffer(function (description) { self.peerConnections[targetMid].setLocalDescription(description).then(function () { var requestObj = { roomHash: payload.roomHash, localDescription: description, toUserId: targetMid, type: 'offer' }; self.stompClient.send('/app/ws/room/rtcDescription', {}, JSON.stringify(requestObj)); }); }, function (error) { log_1.default.error(error); }, {}); }); }; WebRtc.prototype.processRtcDescription = function (payload) { var self = this; var targetMid = payload.fromUserId; if (payload.type === 'offer') { self.getUserMedia(self.mediaOptions, function (mediaError) { if (!mediaError) { self.addPeer(targetMid, payload, function () { var onSuccessCbFn = function () { self.processIceCandidatesFromQueue(targetMid); if (self.localStream) { try { self.localStream.getTracks().forEach(function (track) { self.peerConnections[targetMid].addTrack(track, self.localStream); }); } catch (err) { self.peerConnections[targetMid].addStream(self.localStream); } } self.peerConnections[targetMid].createAnswer(function (answer) { var localDescription = new RTCSessionDescription(answer); self.peerConnections[targetMid].setLocalDescription(localDescription).then(function () { if (self.peerConnections[targetMid].localDescription) { if (AdapterJS.webrtcDetectedBrowser === 'IE') { localDescription = { sdp: self.peerConnections[targetMid].localDescription.sdp, type: self.peerConnections[targetMid].localDescription.type }; } else { localDescription = self.peerConnections[targetMid].localDescription; } } var requestObj = { roomHash: payload.roomHash, localDescription: localDescription, toUserId: targetMid, type: 'answer' }; self.stompClient.send('/app/ws/room/rtcDescription', {}, JSON.stringify(requestObj)); }); }, function (error) { log_1.default.error(error); }); }; var onErrorCbFn = function (error) { self.trigger('handshakeProgress', self.HANDSHAKE_PROGRESS.ANSWER, targetMid, error); log_1.default.error([targetMid, null, 'Failed setting remote description: ', error]); }; self.peerConnections[targetMid].setRemoteDescription(new RTCSessionDescription(payload.localDescription), onSuccessCbFn, onErrorCbFn); }); } }); } else { var onSuccessCbFn = function () { self.processIceCandidatesFromQueue(targetMid); }; var onErrorCbFn = function (error) { self.trigger('handshakeProgress', self.HANDSHAKE_PROGRESS.OFFER, targetMid, error); log_1.default.error([targetMid, null, 'Failed setting remote description: ', error]); }; self.peerConnections[targetMid].setRemoteDescription(new RTCSessionDescription(payload.localDescription), onSuccessCbFn, onErrorCbFn); } }; /** * Обработка полученых с сервера кандидатов */ WebRtc.prototype.processIceCandidate = function (payload) { var self = this; var targetMid = payload.fromUserId; var iceCandidate = new RTCIceCandidate(payload.candidate); if (typeof self.peerConnections[targetMid] === 'undefined') { return; } if (self.peerConnections[targetMid].remoteDescrSet === true) { self.addIceCandidate(targetMid, iceCandidate); } else { if (typeof self.peerCandidatesQueue[targetMid] === 'undefined') { self.peerCandidatesQueue[targetMid] = []; } self.peerCandidatesQueue[targetMid].push(iceCandidate); } }; /** * Вывод кандидатов из хранилища и добавление */ WebRtc.prototype.processIceCandidatesFromQueue = function (targetMid) { var self = this; if (typeof self.peerConnections[targetMid] === 'undefined') { return; } self.peerConnections[targetMid].remoteDescrSet = true; if (typeof self.peerCandidatesQueue[targetMid] !== 'undefined') { while (self.peerCandidatesQueue[targetMid].length > 0) { var iceCandidate = self.peerCandidatesQueue[targetMid].shift(); self.addIceCandidate(targetMid, iceCandidate); } } }; /** * Adding candidate to peer connection */ WebRtc.prototype.addIceCandidate = function (targetMid, iceCandidate) { var self = this; if (typeof self.peerConnections[targetMid] === 'undefined') { return; } var onSuccessCbFn = function () { log_1.default.console([targetMid, 'RTCIceCandidate', 'Added ICE candidate successfully.']); }; var onErrorCbFn = function (error) { log_1.default.error([targetMid, 'RTCIceCandidate', 'Failed adding ICE candidate', error]); }; if (!(self.peerConnections[targetMid] && self.peerConnections[targetMid].remoteDescription && self.peerConnections[targetMid].signalingState !== self.PEER_CONNECTION_STATE.CLOSED && self.peerConnections[targetMid].remoteDescription.sdp && self.peerConnections[targetMid].remoteDescription.sdp .indexOf('\r\na=mid:' + iceCandidate.sdpMid + '\r\n') > -1)) { log_1.default.warn([ targetMid, 'RTCIceCandidate', 'Dropping ICE candidate as Peer connection does not exists or is closed' ]); return; } try { self.peerConnections[targetMid].addIceCandidate(iceCandidate, onSuccessCbFn, onErrorCbFn); } catch (error) { onErrorCbFn(error); } }; WebRtc.prototype.clearRtcConnections = function () { var self = this; for (var peerId in self.peerConnections) { if (self.peerConnections.hasOwnProperty(peerId)) { self.removePeer(+peerId, false); } } self.peerConnectionsFailedCounter = 0; }; WebRtc.prototype.processRtcLeave = function (payload) { var self = this; self.removePeer(payload.userId, false); var data = { userId: payload.userId, roomHash: payload.roomHash }; if (payload.isForced) { self.trigger('peerConnectionDisconnected', data); } else { self.trigger('userLeftRtc', data); } }; /** * Function that parses the <code>getUserMedia()</code> settings provided. */ WebRtc.prototype.parseStreamSettings = function (options) { var settings = { settings: { audio: null, video: null }, mutedSettings: { shouldAudioMuted: false, shouldVideoMuted: false }, getUserMediaSettings: { audio: null, video: null } }; if (options.audio) { // For Edge to work since they do not support the advanced constraints yet settings.settings.audio = { stereo: false, exactConstraints: !!options.useExactConstraints, echoCancellation: true }; settings.getUserMediaSettings.audio = { echoCancellation: true }; if (typeof options.audio === 'object') { if (typeof options.audio.stereo === 'boolean') { settings.settings.audio.stereo = options.audio.stereo; } if (typeof options.audio.useinbandfec === 'boolean') { settings.settings.audio.useinbandfec = options.audio.useinbandfec; } if (typeof options.audio.usedtx === 'boolean') { settings.settings.audio.usedtx = options.audio.usedtx; } if (typeof options.audio.maxplaybackrate === 'number' && options.audio.maxplaybackrate >= 8000 && options.audio.maxplaybackrate <= 48000) { settings.settings.audio.maxplaybackrate = options.audio.maxplaybackrate; } if (typeof options.audio.mute === 'boolean') { settings.mutedSettings.shouldAudioMuted = options.audio.mute; } // Not supported in Edge browser features. if (AdapterJS.webrtcDetectedBrowser !== 'edge') { if (typeof options.audio.echoCancellation === 'boolean') { settings.settings.audio.echoCancellation = options.audio.echoCancellation; settings.getUserMediaSettings.audio.echoCancellation = options.audio.echoCancellation; } if (Array.isArray(options.audio.optional)) { settings.settings.audio.optional = common_1.clone(options.audio.optional); settings.getUserMediaSettings.audio.optional = common_1.clone(options.audio.optional); } if (options.audio.deviceId && typeof options.audio.deviceId === 'string' && AdapterJS.webrtcDetectedBrowser !== 'firefox') { settings.settings.audio.deviceId = options.audio.deviceId; settings.getUserMediaSettings.audio.deviceId = options.useExactConstraints ? { exact: options.audio.deviceId } : { ideal: options.audio.deviceId }; } } } if (AdapterJS.webrtcDetectedBrowser === 'edge' || AdapterJS.webrtcDetectedBrowser === 'safari') { settings.getUserMediaSettings.audio = true; } } if (options.video) { // For Edge to work since they do not support the advanced constraints yet settings.settings.video = { resolution: common_1.clone(this.VIDEO_RESOLUTION.VGA), exactConstraints: !!options.useExactConstraints }; settings.getUserMediaSettings.video = {}; if (typeof options.video === 'object') { if (typeof options.video.mute === 'boolean') { settings.mutedSettings.shouldVideoMuted = options.video.mute; } if (Array.isArray(options.video.optional)) { settings.settings.video.optional = common_1.clone(options.video.optional); settings.getUserMediaSettings.video.optional = common_1.clone(options.video.optional); } if (options.video.deviceId && typeof options.video.deviceId === 'string' && AdapterJS.webrtcDetectedBrowser !== 'firefox') { settings.settings.video.deviceId = options.video.deviceId; settings.getUserMediaSettings.video.deviceId = options.useExactConstraints ? { exact: options.video.deviceId } : { ideal: options.video.deviceId }; } if (options.video.resolution && typeof options.video.resolution === 'object') { if ((options.video.resolution.width && typeof options.video.resolution.width === 'object') || typeof options.video.resolution.width === 'number') { settings.settings.video.resolution.width = options.video.resolution.width; } if ((options.video.resolution.height && typeof options.video.resolution.height === 'object') || typeof options.video.resolution.height === 'number') { settings.settings.video.resolution.height = options.video.resolution.height; } } settings.getUserMediaSettings.video.width = typeof settings.settings.video.resolution.width === 'object' ? settings.settings.video.resolution.width : (options.useExactConstraints ? { exact: settings.settings.video.resolution.width } : { max: settings.settings.video.resolution.width }); settings.getUserMediaSettings.video.height = typeof settings.settings.video.resolution.height === 'object' ? settings.settings.video.resolution.height : (options.useExactConstraints ? { exact: settings.settings.video.resolution.height } : { max: settings.settings.video.resolution.height }); } else { settings.getUserMediaSettings.video = { width: options.useExactConstraints ? { exact: settings.settings.video.resolution.width } : { max: settings.settings.video.resolution.width }, height: options.useExactConstraints ? { exact: settings.settings.video.resolution.height } : { max: settings.settings.video.resolution.height } }; } if (AdapterJS.webrtcDetectedBrowser === 'edge' || AdapterJS.webrtcDetectedBrowser === 'safari') { settings.settings.video = { exactConstraints: !!options.useExactConstraints }; settings.getUserMediaSettings.video = true; } } return settings; }; /** * Function that handles the native <code>navigator.getUserMedia()</code> API success callback result. */ WebRtc.prototype.onStreamAccessSuccess = function (stream) { var self = this; self.localStream = stream; self.trigger('mediaAccessSuccess', stream); }; /** * Function that handles the native <code>navigator.getUserMedia()</code> API failure callback result. */ WebRtc.prototype.onStreamAccessError = function (error) { var self = this; log_1.default.error(['mediaAccessError', error]); self.checkDevices(); }; /** * Function that starts the Peer connection session. * Remember to remove previous method of reconnection * (re-creating the Peer connection - destroy and create connection). */ WebRtc.prototype.addPeer = function (peerId, payload, callback) { var self = this; log_1.default.console('Adding peer'); self.peerConnections[peerId] = self.createPeerConnection(peerId, payload); if (!self.peerConnections[peerId]) { log_1.default.error('Failed creating the connection to peer. #' + peerId); return; } self.peerConnections[peerId].info = { type: payload.type === 'offer' ? 'answer' : 'offer', roomHash: payload.roomHash }; if (typeof callback === 'function') { callback(); } }; /** * Function that ends the Peer connection session. */ WebRtc.prototype.removePeer = function (peerId, trigger) { var self = this; // prevent connectionDisconnected trigger if (typeof (self.peerConnectionsTimer.disconnected[peerId]) !== 'undefined') { clearTimeout(self.peerConnectionsTimer.disconnected[peerId]); delete self.peerConnectionsTimer.disconnected[peerId]; } if (typeof (self.peerConnectionsTimer.failed[peerId]) !== 'undefined') { clearTimeout(self.peerConnectionsTimer.failed[peerId]); } if (!self.peerConnections[peerId]) { return; } // check if health timer exists if (self.peerConnections[peerId]) { if (self.peerConnections[peerId].signalingState !== self.PEER_CONNECTION_STATE.CLOSED) { self.peerConnections[peerId].close(); if (trigger) { self.trigger('peerConnectionClosed', { userId: peerId, roomHash: self.peerConnections[peerId].info.roomHash }); } } delete this.peerConnections[peerId]; if (self.peerCandidatesQueue[peerId]) { delete self.peerCandidatesQueue[peerId]; } } log_1.default.console([peerId, 'RTCPeerConnection', null, 'Successfully removed peer']); }; /** * Function that creates the Peer connection. */ WebRtc.prototype.createPeerConnection = function (targetMid, payload) { var self = this; var pc; var constraints = self.peerConnectionConfig; var optional = { optional: [ { DtlsSrtpKeyAgreement: true }, { googIPv6: true } ] }; try { log_1.default.debug([targetMid, 'RTCPeerConnection', null, 'Creating peer connection ->', { constraints: constraints, optional: optional }]); // @ts-ignore pc = new ((window.msRTCPeerConnection) ? window.msRTCPeerConnection : RTCPeerConnection)(constraints, optional); } catch (error) { log_1.default.error([targetMid, null, null, 'Failed creating peer connection:', error]); self.trigger('handshakeProgress', self.HANDSHAKE_PROGRESS.ERROR, targetMid, error); return null; } pc.localStream = null; pc.localStreamId = null; pc.remoteStream = null; pc.remoteStreamId = null; pc.remoteDescrSet = false; pc.onaddstream = function (evt) { if (!self.peerConnections[targetMid]) { return; } var stream = evt.stream; pc.remoteStream = stream; pc.remoteStreamId = pc.remoteStreamId || stream.id; self.onRemoteStreamAdded(targetMid, stream); }; pc.onicecandidate = function (event) { self.onIceCandidate(targetMid, event.candidate, payload.roomHash); }; pc.oniceconnectionstatechange = function () { var iceConnectionState = pc.iceConnectionState; self.trigger('iceConnectionState', iceConnectionState, targetMid); log_1.default.console(['oniceconnectionstatechange', null, iceConnectionState]); if (iceConnectionState !== 'closed') { self.peerConnectionsFailed = false; } switch (iceConnectionState) { case 'connected': self.onConnected(targetMid); break; case 'failed': self.onFailed(targetMid); break; case 'closed': self.onClosed(targetMid); break; case 'disconnected': self.onDisconnected(targetMid); break; } }; return pc; }; WebRtc.prototype.onConnected = function (targetMid) { var self = this; self.peerConnectionsFailedCounter = 0; if (self.peerConnectionsTimer.disconnected[targetMid]) { clearTimeout(self.peerConnectionsTimer.disconnected[targetMid]); } self.trigger('peerConnectionConnected', { userId: targetMid, roomHash: self.peerConnections[targetMid].info.roomHash }); }; WebRtc.prototype.onDisconnected = function (targetMid) { var self = this; self.peerConnectionsTimer.disconnected[targetMid] = setTimeout(function () { self.trigger('peerConnectionDisconnected', { userId: targetMid, roomHash: self.peerConnections[targetMid].info.roomHash }); }, 500); }; WebRtc.prototype.onClosed = function (targetMid) { var self = this; if (self.peerConnectionsFailed) { self.peerConnectionsFailed = false; } else { self.removePeer(targetMid, true); } }; WebRtc.prototype.onFailed = function (targetMid) { var self = this; if (!self.peerConnections[targetMid]) { self.onConnectionFailed(targetMid); } else { var connectionInfo = self.peerConnections[targetMid].info; var data = { userId: targetMid, roomHash: self.peerConnections[targetMid].info.roomHash }; self.removePeer(targetMid, false); if (self.peerConnectionsFailedCounter < 1) { self.trigger('peerConnectionDisconnected', data); if (connectionInfo && connectionInfo.type === 'offer') { self.newRtcConnection({ roomHash: connectionInfo.roomHash, fromUserId: targetMid }); self.peerConnectionsFailed = true; } else { self.peerConnectionsTimer.failed[targetMid] = setTimeout(function () { if (!self.peerConnections[targetMid]) { self.onConnectionFailed(targetMid); } }, 30000); } self.peerConnectionsFailedCounter++; } else { self.onConnectionFailed(targetMid); } } }; WebRtc.prototype.onConnectionFailed = function (targetMid) { var self = this; self.peerConnectionsFailedCounter = 0; self.trigger('peerConnectionFailed', { userId: targetMid, roomHash: self.peerConnections[targetMid].info.roomHash }); }; /** * Function that handles the <code>RTCPeerConnection.onaddstream</code> remote MediaStream received. */ WebRtc.prototype.onRemoteStreamAdded = function (targetMid, stream) { var self = this; self.trigger('incomingStream', stream); self.trigger('peerUpdated'); }; /** * Function that handles the Peer connection gathered ICE candidate to be sent. */ WebRtc.prototype.onIceCandidate = function (targetMid, candidate, roomHash) { var self = this; var pc = self.peerConnections[targetMid]; if (!pc) { log_1.default.error([targetMid, 'RTCIceCandidate', 'Peer connection does not exists']); return; } if (candidate && candidate.candidate) { var candidateType = candidate.candidate.split(' ')[7]; log_1.default.debug([targetMid, 'RTCIceCandidate', candidateType, 'Generated ICE candidate ->', candidate]); if (candidateType === 'endOfCandidates' || !(self.peerConnections[targetMid] && self.peerConnections[targetMid].localDescription && self.peerConnections[targetMid].localDescription.sdp && self.peerConnections[targetMid].localDescription.sdp.indexOf('\r\na=mid:' + candidate.sdpMid + '\r\n') > -1)) { log_1.default.warn([targetMid, 'RTCIceCandidate', candidateType, 'Dropping of sending ICE candidate ' + 'end-of-candidates signal or unused ICE candidates to prevent errors ->', candidate]); return; } if (candidate.candidate.indexOf('relay') >= 0) { var candidateObject = { candidate: candidate.candidate, sdpMLineIndex: candidate.sdpMLineIndex, sdpMid: candidate.sdpMid }; var requestObj = { roomHash: roomHash, toUserId: targetMid, candidate: candidateObject }; self.stompClient.send('/app/ws/room/rtcCandidates', {}, JSON.stringify(requestObj)); } } }; return WebRtc; }(Base_1.default)); exports.default = WebRtc; //# sourceMappingURL=WebRtc.js.map