ivcbox-adapter
Version:
827 lines • 36.7 kB
JavaScript
;
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