@webex/plugin-meetings 2.34.0 → 2.35.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/constants.js +4 -4
- package/dist/constants.js.map +1 -1
- package/dist/media/properties.js +139 -0
- package/dist/media/properties.js.map +1 -1
- package/dist/meeting/index.js +96 -102
- package/dist/meeting/index.js.map +1 -1
- package/package.json +22 -18
- package/src/constants.ts +8 -8
- package/src/media/properties.js +97 -0
- package/src/meeting/index.js +99 -110
- package/test/unit/spec/media/properties.ts +305 -0
- package/test/unit/spec/meeting/index.js +38 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webex/plugin-meetings",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.35.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"license": "Cisco EULA (https://www.cisco.com/c/en/us/products/end-user-license-agreement.html)",
|
|
6
6
|
"contributors": [
|
|
@@ -13,7 +13,11 @@
|
|
|
13
13
|
],
|
|
14
14
|
"main": "dist/index.js",
|
|
15
15
|
"devMain": "src/index.js",
|
|
16
|
-
"repository":
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "https://github.com/webex/webex-js-sdk.git",
|
|
19
|
+
"directory": "packages/@webex/plugin-meetings"
|
|
20
|
+
},
|
|
17
21
|
"engines": {
|
|
18
22
|
"node": ">=14"
|
|
19
23
|
},
|
|
@@ -24,30 +28,30 @@
|
|
|
24
28
|
]
|
|
25
29
|
},
|
|
26
30
|
"devDependencies": {
|
|
27
|
-
"@webex/plugin-meetings": "2.
|
|
28
|
-
"@webex/test-helper-chai": "2.
|
|
29
|
-
"@webex/test-helper-mocha": "2.
|
|
30
|
-
"@webex/test-helper-mock-webex": "2.
|
|
31
|
-
"@webex/test-helper-retry": "2.
|
|
32
|
-
"@webex/test-helper-test-users": "2.
|
|
31
|
+
"@webex/plugin-meetings": "2.35.1",
|
|
32
|
+
"@webex/test-helper-chai": "2.35.1",
|
|
33
|
+
"@webex/test-helper-mocha": "2.35.1",
|
|
34
|
+
"@webex/test-helper-mock-webex": "2.35.1",
|
|
35
|
+
"@webex/test-helper-retry": "2.35.1",
|
|
36
|
+
"@webex/test-helper-test-users": "2.35.1",
|
|
33
37
|
"chai": "^4.3.4",
|
|
34
38
|
"chai-as-promised": "^7.1.1",
|
|
35
39
|
"jsdom-global": "3.0.2",
|
|
36
40
|
"sinon": "^9.2.4"
|
|
37
41
|
},
|
|
38
42
|
"dependencies": {
|
|
39
|
-
"@webex/common": "2.
|
|
43
|
+
"@webex/common": "2.35.1",
|
|
40
44
|
"@webex/internal-media-core": "^0.0.7-beta",
|
|
41
|
-
"@webex/internal-plugin-conversation": "2.
|
|
42
|
-
"@webex/internal-plugin-device": "2.
|
|
43
|
-
"@webex/internal-plugin-mercury": "2.
|
|
44
|
-
"@webex/internal-plugin-metrics": "2.
|
|
45
|
-
"@webex/internal-plugin-support": "2.
|
|
46
|
-
"@webex/internal-plugin-user": "2.
|
|
47
|
-
"@webex/plugin-people": "2.
|
|
48
|
-
"@webex/plugin-rooms": "2.
|
|
45
|
+
"@webex/internal-plugin-conversation": "2.35.1",
|
|
46
|
+
"@webex/internal-plugin-device": "2.35.1",
|
|
47
|
+
"@webex/internal-plugin-mercury": "2.35.1",
|
|
48
|
+
"@webex/internal-plugin-metrics": "2.35.1",
|
|
49
|
+
"@webex/internal-plugin-support": "2.35.1",
|
|
50
|
+
"@webex/internal-plugin-user": "2.35.1",
|
|
51
|
+
"@webex/plugin-people": "2.35.1",
|
|
52
|
+
"@webex/plugin-rooms": "2.35.1",
|
|
49
53
|
"@webex/ts-sdp": "^1.0.1",
|
|
50
|
-
"@webex/webex-core": "2.
|
|
54
|
+
"@webex/webex-core": "2.35.1",
|
|
51
55
|
"bowser": "^2.11.0",
|
|
52
56
|
"btoa": "^1.2.1",
|
|
53
57
|
"dotenv": "^4.0.0",
|
package/src/constants.ts
CHANGED
|
@@ -972,7 +972,7 @@ export const QUALITY_LEVELS = {
|
|
|
972
972
|
};
|
|
973
973
|
|
|
974
974
|
|
|
975
|
-
export const
|
|
975
|
+
export const AVAILABLE_RESOLUTIONS = {
|
|
976
976
|
'360p': {
|
|
977
977
|
video: {
|
|
978
978
|
width: {
|
|
@@ -1024,13 +1024,13 @@ export const AVALIABLE_RESOLUTIONS = {
|
|
|
1024
1024
|
};
|
|
1025
1025
|
|
|
1026
1026
|
export const VIDEO_RESOLUTIONS = {
|
|
1027
|
-
[QUALITY_LEVELS.LOW]:
|
|
1028
|
-
[QUALITY_LEVELS.MEDIUM]:
|
|
1029
|
-
[QUALITY_LEVELS.HIGH]:
|
|
1030
|
-
[QUALITY_LEVELS['360p']]:
|
|
1031
|
-
[QUALITY_LEVELS['480p']]:
|
|
1032
|
-
[QUALITY_LEVELS['720p']]:
|
|
1033
|
-
[QUALITY_LEVELS['1080p']]:
|
|
1027
|
+
[QUALITY_LEVELS.LOW]: AVAILABLE_RESOLUTIONS['480p'],
|
|
1028
|
+
[QUALITY_LEVELS.MEDIUM]: AVAILABLE_RESOLUTIONS['720p'],
|
|
1029
|
+
[QUALITY_LEVELS.HIGH]: AVAILABLE_RESOLUTIONS['1080p'],
|
|
1030
|
+
[QUALITY_LEVELS['360p']]: AVAILABLE_RESOLUTIONS['360p'],
|
|
1031
|
+
[QUALITY_LEVELS['480p']]: AVAILABLE_RESOLUTIONS['480p'],
|
|
1032
|
+
[QUALITY_LEVELS['720p']]: AVAILABLE_RESOLUTIONS['720p'],
|
|
1033
|
+
[QUALITY_LEVELS['1080p']]: AVAILABLE_RESOLUTIONS['1080p'],
|
|
1034
1034
|
};
|
|
1035
1035
|
|
|
1036
1036
|
/**
|
package/src/media/properties.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
|
+
ICE_STATE,
|
|
2
3
|
MEETINGS,
|
|
4
|
+
PC_BAIL_TIMEOUT,
|
|
3
5
|
QUALITY_LEVELS
|
|
4
6
|
} from '../constants';
|
|
5
7
|
import LoggerProxy from '../common/logs/logger-proxy';
|
|
@@ -195,4 +197,99 @@ export default class MediaProperties {
|
|
|
195
197
|
this.unsetLocalVideoTrack();
|
|
196
198
|
this.unsetRemoteMedia();
|
|
197
199
|
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Waits until ice connection is established
|
|
203
|
+
*
|
|
204
|
+
* @returns {Promise<void>}
|
|
205
|
+
*/
|
|
206
|
+
waitForIceConnectedState() {
|
|
207
|
+
const isIceConnected = () => (
|
|
208
|
+
this.peerConnection.iceConnectionState === ICE_STATE.CONNECTED ||
|
|
209
|
+
this.peerConnection.iceConnectionState === ICE_STATE.COMPLETED
|
|
210
|
+
);
|
|
211
|
+
|
|
212
|
+
if (isIceConnected()) {
|
|
213
|
+
return Promise.resolve();
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
return new Promise((resolve, reject) => {
|
|
217
|
+
let timer;
|
|
218
|
+
|
|
219
|
+
const iceListener = () => {
|
|
220
|
+
LoggerProxy.logger.log(`Media:properties#waitForIceConnectedState --> ice state: ${this.peerConnection.iceConnectionState}, conn state: ${this.peerConnection.connectionState}`);
|
|
221
|
+
|
|
222
|
+
if (isIceConnected()) {
|
|
223
|
+
clearTimeout(timer);
|
|
224
|
+
this.peerConnection.removeEventListener('iceconnectionstatechange', iceListener);
|
|
225
|
+
resolve();
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
timer = setTimeout(() => {
|
|
230
|
+
this.peerConnection.removeEventListener('iceconnectionstatechange', iceListener);
|
|
231
|
+
reject();
|
|
232
|
+
}, PC_BAIL_TIMEOUT);
|
|
233
|
+
|
|
234
|
+
this.peerConnection.addEventListener('iceconnectionstatechange', iceListener);
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Returns the type of a connection that has been established
|
|
240
|
+
*
|
|
241
|
+
* @returns {Promise<'UDP' | 'TCP' | 'TURN-TLS' | 'TURN-TCP' | 'TURN-UDP' | 'unknown'>}
|
|
242
|
+
*/
|
|
243
|
+
async getCurrentConnectionType() {
|
|
244
|
+
// we can only get the connection type after ICE connection has been established
|
|
245
|
+
await this.waitForIceConnectedState();
|
|
246
|
+
|
|
247
|
+
const allStatsReports = [];
|
|
248
|
+
|
|
249
|
+
try {
|
|
250
|
+
// eslint-disable-next-line no-await-in-loop
|
|
251
|
+
const statsResult = await this.peerConnection.getStats();
|
|
252
|
+
|
|
253
|
+
statsResult.forEach((report) => allStatsReports.push(report));
|
|
254
|
+
}
|
|
255
|
+
catch (error) {
|
|
256
|
+
LoggerProxy.logger.warn(`Media:properties#getCurrentConnectionType --> getStats() failed: ${error}`);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
const successfulCandidatePairs = allStatsReports.filter(
|
|
260
|
+
(report) => report.type === 'candidate-pair' && report.state?.toLowerCase() === 'succeeded'
|
|
261
|
+
);
|
|
262
|
+
|
|
263
|
+
let foundConnectionType = 'unknown';
|
|
264
|
+
|
|
265
|
+
// all of the successful pairs should have the same connection type, so just return the type for the first one
|
|
266
|
+
successfulCandidatePairs.some((pair) => {
|
|
267
|
+
const localCandidate = allStatsReports.find((report) => report.type === 'local-candidate' && report.id === pair.localCandidateId);
|
|
268
|
+
|
|
269
|
+
if (localCandidate === undefined) {
|
|
270
|
+
LoggerProxy.logger.warn(`Media:properties#getCurrentConnectionType --> failed to find local candidate "${pair.localCandidateId}" in getStats() results`);
|
|
271
|
+
|
|
272
|
+
return false;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
let connectionType;
|
|
276
|
+
|
|
277
|
+
if (localCandidate.relayProtocol) {
|
|
278
|
+
connectionType = `TURN-${localCandidate.relayProtocol.toUpperCase()}`;
|
|
279
|
+
}
|
|
280
|
+
else {
|
|
281
|
+
connectionType = localCandidate.protocol?.toUpperCase(); // it will be UDP or TCP
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
if (connectionType) {
|
|
285
|
+
foundConnectionType = connectionType;
|
|
286
|
+
|
|
287
|
+
return true;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
return false;
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
return foundConnectionType;
|
|
294
|
+
}
|
|
198
295
|
}
|
package/src/meeting/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import uuid from 'uuid';
|
|
2
|
-
import {cloneDeep, isEqual, pick} from 'lodash';
|
|
2
|
+
import {cloneDeep, isEqual, pick, isString} from 'lodash';
|
|
3
3
|
import {StatelessWebexPlugin} from '@webex/webex-core';
|
|
4
4
|
import {Media as WebRTCMedia} from '@webex/internal-media-core';
|
|
5
5
|
|
|
@@ -36,7 +36,6 @@ import {
|
|
|
36
36
|
_INCOMING_,
|
|
37
37
|
_JOIN_,
|
|
38
38
|
AUDIO,
|
|
39
|
-
CONNECTION_STATE,
|
|
40
39
|
CONTENT,
|
|
41
40
|
ENDED,
|
|
42
41
|
EVENT_TRIGGERS,
|
|
@@ -58,7 +57,6 @@ import {
|
|
|
58
57
|
ONLINE,
|
|
59
58
|
OFFLINE,
|
|
60
59
|
PASSWORD_STATUS,
|
|
61
|
-
PC_BAIL_TIMEOUT,
|
|
62
60
|
PSTN_STATUS,
|
|
63
61
|
QUALITY_LEVELS,
|
|
64
62
|
RECORDING_STATE,
|
|
@@ -2746,7 +2744,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2746
2744
|
const {localQualityLevel} = this.mediaProperties;
|
|
2747
2745
|
|
|
2748
2746
|
if (Number(localQualityLevel.slice(0, -1)) > height) {
|
|
2749
|
-
LoggerProxy.logger.
|
|
2747
|
+
LoggerProxy.logger.warn(`Meeting:index#setLocalVideoTrack --> Local video quality of ${localQualityLevel} not supported,
|
|
2750
2748
|
downscaling to highest possible resolution of ${height}p`);
|
|
2751
2749
|
|
|
2752
2750
|
this.mediaProperties.setLocalQualityLevel(`${height}p`);
|
|
@@ -4014,6 +4012,16 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4014
4012
|
LoggerProxy.logger.warn('Meeting:index#getMediaStreams --> Please use `meeting.shareScreen()` to manually start the screen share after successfully joining the meeting');
|
|
4015
4013
|
}
|
|
4016
4014
|
|
|
4015
|
+
if (audioVideo && isString(audioVideo)) {
|
|
4016
|
+
if (Object.keys(VIDEO_RESOLUTIONS).includes(audioVideo)) {
|
|
4017
|
+
this.mediaProperties.setLocalQualityLevel(audioVideo);
|
|
4018
|
+
audioVideo = {video: VIDEO_RESOLUTIONS[audioVideo].video};
|
|
4019
|
+
}
|
|
4020
|
+
else {
|
|
4021
|
+
throw new ParameterError(`${audioVideo} not supported. Either pass level from pre-defined resolutions or pass complete audioVideo object`);
|
|
4022
|
+
}
|
|
4023
|
+
}
|
|
4024
|
+
|
|
4017
4025
|
if (!audioVideo.video) {
|
|
4018
4026
|
audioVideo = {...audioVideo, video: {...audioVideo.video, ...VIDEO_RESOLUTIONS[this.mediaProperties.localQualityLevel].video}};
|
|
4019
4027
|
}
|
|
@@ -4246,129 +4254,110 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4246
4254
|
enableRtx: this.config.enableRtx,
|
|
4247
4255
|
enableExtmap: this.config.enableExtmap,
|
|
4248
4256
|
setStartLocalSDPGenRemoteSDPRecvDelay: this.setStartLocalSDPGenRemoteSDPRecvDelay.bind(this)
|
|
4249
|
-
})
|
|
4250
|
-
|
|
4251
|
-
|
|
4257
|
+
}))
|
|
4258
|
+
.then((peerConnection) => this.getDevices().then((devices) => {
|
|
4259
|
+
MeetingUtil.handleDeviceLogging(devices);
|
|
4252
4260
|
|
|
4253
|
-
|
|
4254
|
-
|
|
4255
|
-
|
|
4256
|
-
|
|
4257
|
-
|
|
4261
|
+
return peerConnection;
|
|
4262
|
+
}))
|
|
4263
|
+
.then((peerConnection) => {
|
|
4264
|
+
this.handleMediaLogging(this.mediaProperties);
|
|
4265
|
+
LoggerProxy.logger.info(`${LOG_HEADER} PeerConnection Received from attachMedia `);
|
|
4266
|
+
|
|
4267
|
+
this.setRemoteStream(peerConnection);
|
|
4268
|
+
if (this.config.stats.enableStatsAnalyzer) {
|
|
4269
|
+
// TODO: ** Dont re create StatsAnalyzer on reconnect or rejoin
|
|
4270
|
+
this.networkQualityMonitor = new NetworkQualityMonitor(this.config.stats);
|
|
4271
|
+
this.statsAnalyzer = new StatsAnalyzer(this.config.stats, this.networkQualityMonitor);
|
|
4272
|
+
this.setupStatsAnalyzerEventHandlers();
|
|
4273
|
+
this.networkQualityMonitor.on(EVENT_TRIGGERS.NETWORK_QUALITY, this.sendNetworkQualityEvent.bind(this));
|
|
4274
|
+
}
|
|
4275
|
+
})
|
|
4276
|
+
.catch((error) => {
|
|
4277
|
+
LoggerProxy.logger.error(`${LOG_HEADER} Error adding media , setting up peerconnection, `, error);
|
|
4258
4278
|
|
|
4259
|
-
|
|
4260
|
-
|
|
4261
|
-
|
|
4262
|
-
|
|
4263
|
-
|
|
4264
|
-
|
|
4265
|
-
|
|
4279
|
+
Metrics.sendBehavioralMetric(
|
|
4280
|
+
BEHAVIORAL_METRICS.ADD_MEDIA_FAILURE,
|
|
4281
|
+
{
|
|
4282
|
+
correlation_id: this.correlationId,
|
|
4283
|
+
locus_id: this.locusUrl.split('/').pop(),
|
|
4284
|
+
reason: error.message,
|
|
4285
|
+
stack: error.stack,
|
|
4286
|
+
turnDiscoverySkippedReason,
|
|
4287
|
+
turnServerUsed
|
|
4266
4288
|
}
|
|
4267
|
-
|
|
4268
|
-
.catch((error) => {
|
|
4269
|
-
LoggerProxy.logger.error(`${LOG_HEADER} Error adding media , setting up peerconnection, `, error);
|
|
4270
|
-
|
|
4271
|
-
Metrics.sendBehavioralMetric(
|
|
4272
|
-
BEHAVIORAL_METRICS.ADD_MEDIA_FAILURE,
|
|
4273
|
-
{
|
|
4274
|
-
correlation_id: this.correlationId,
|
|
4275
|
-
locus_id: this.locusUrl.split('/').pop(),
|
|
4276
|
-
reason: error.message,
|
|
4277
|
-
stack: error.stack,
|
|
4278
|
-
turnDiscoverySkippedReason,
|
|
4279
|
-
turnServerUsed
|
|
4280
|
-
}
|
|
4281
|
-
);
|
|
4289
|
+
);
|
|
4282
4290
|
|
|
4283
|
-
|
|
4284
|
-
|
|
4285
|
-
|
|
4286
|
-
|
|
4291
|
+
throw error;
|
|
4292
|
+
})
|
|
4293
|
+
.then(() => new Promise((resolve, reject) => {
|
|
4294
|
+
let timerCount = 0;
|
|
4287
4295
|
|
|
4288
|
-
|
|
4289
|
-
|
|
4290
|
-
|
|
4296
|
+
// eslint-disable-next-line func-names
|
|
4297
|
+
// eslint-disable-next-line prefer-arrow-callback
|
|
4298
|
+
if (this.type === _CALL_) {
|
|
4299
|
+
resolve();
|
|
4300
|
+
}
|
|
4301
|
+
const joiningTimer = setInterval(() => {
|
|
4302
|
+
timerCount += 1;
|
|
4303
|
+
if (this.meetingState === FULL_STATE.ACTIVE) {
|
|
4304
|
+
clearInterval(joiningTimer);
|
|
4291
4305
|
resolve();
|
|
4292
4306
|
}
|
|
4293
|
-
const joiningTimer = setInterval(() => {
|
|
4294
|
-
timerCount += 1;
|
|
4295
|
-
if (this.meetingState === FULL_STATE.ACTIVE) {
|
|
4296
|
-
clearInterval(joiningTimer);
|
|
4297
|
-
resolve();
|
|
4298
|
-
}
|
|
4299
4307
|
|
|
4300
|
-
|
|
4301
|
-
|
|
4302
|
-
|
|
4303
|
-
|
|
4304
|
-
|
|
4308
|
+
if (timerCount === 4) {
|
|
4309
|
+
clearInterval(joiningTimer);
|
|
4310
|
+
reject(new Error('Meeting is still not active '));
|
|
4311
|
+
}
|
|
4312
|
+
}, 1000);
|
|
4313
|
+
}))
|
|
4314
|
+
.then(() =>
|
|
4315
|
+
logRequest(this.roap
|
|
4316
|
+
.sendRoapMediaRequest({
|
|
4317
|
+
sdp: this.mediaProperties.peerConnection.sdp,
|
|
4318
|
+
roapSeq: this.roapSeq,
|
|
4319
|
+
meeting: this // or can pass meeting ID
|
|
4320
|
+
}), {
|
|
4321
|
+
header: `${LOG_HEADER} Send Roap Media Request.`,
|
|
4322
|
+
success: `${LOG_HEADER} Successfully send roap media request`,
|
|
4323
|
+
failure: `${LOG_HEADER} Error joining the call on send roap media request, `
|
|
4305
4324
|
}))
|
|
4306
|
-
|
|
4307
|
-
|
|
4308
|
-
|
|
4309
|
-
|
|
4310
|
-
|
|
4311
|
-
|
|
4312
|
-
|
|
4313
|
-
|
|
4314
|
-
success: `${LOG_HEADER} Successfully send roap media request`,
|
|
4315
|
-
failure: `${LOG_HEADER} Error joining the call on send roap media request, `
|
|
4316
|
-
}))
|
|
4317
|
-
.then(() => {
|
|
4318
|
-
const {peerConnection} = this.mediaProperties;
|
|
4319
|
-
|
|
4320
|
-
return new Promise((resolve, reject) => {
|
|
4321
|
-
if (peerConnection.connectionState === CONNECTION_STATE.CONNECTED) {
|
|
4322
|
-
LoggerProxy.logger.info(`${LOG_HEADER} PeerConnection CONNECTED`);
|
|
4323
|
-
|
|
4324
|
-
resolve(peerConnection);
|
|
4325
|
-
|
|
4326
|
-
return;
|
|
4327
|
-
}
|
|
4328
|
-
// Check if Peer Connection is STABLE (connected)
|
|
4329
|
-
const stabilityTimeout = setTimeout(() => {
|
|
4330
|
-
if (peerConnection.connectionState !== CONNECTION_STATE.CONNECTED) {
|
|
4331
|
-
// TODO: Fix this after the error code pr goes in
|
|
4332
|
-
reject(createMeetingsError(30202, 'Meeting connection failed'));
|
|
4333
|
-
}
|
|
4334
|
-
else {
|
|
4335
|
-
LoggerProxy.logger.info(`${LOG_HEADER} PeerConnection CONNECTED`);
|
|
4336
|
-
resolve(peerConnection);
|
|
4337
|
-
}
|
|
4338
|
-
}, PC_BAIL_TIMEOUT);
|
|
4339
|
-
|
|
4340
|
-
this.once(EVENT_TRIGGERS.MEDIA_READY, () => {
|
|
4341
|
-
LoggerProxy.logger.info(`${LOG_HEADER} PeerConnection CONNECTED, clearing stability timer.`);
|
|
4342
|
-
clearTimeout(stabilityTimeout);
|
|
4343
|
-
resolve(peerConnection);
|
|
4344
|
-
});
|
|
4345
|
-
});
|
|
4346
|
-
})
|
|
4347
|
-
.then(() => {
|
|
4348
|
-
if (mediaSettings && mediaSettings.sendShare && localShare) {
|
|
4349
|
-
if (this.state === MEETING_STATE.STATES.JOINED) {
|
|
4350
|
-
return this.share();
|
|
4351
|
-
}
|
|
4325
|
+
.then(
|
|
4326
|
+
() => this.mediaProperties.waitForIceConnectedState()
|
|
4327
|
+
.catch(() => {
|
|
4328
|
+
throw createMeetingsError(30202, 'Meeting connection failed');
|
|
4329
|
+
})
|
|
4330
|
+
)
|
|
4331
|
+
.then(() => {
|
|
4332
|
+
LoggerProxy.logger.info(`${LOG_HEADER} PeerConnection CONNECTED`);
|
|
4352
4333
|
|
|
4353
|
-
|
|
4354
|
-
|
|
4334
|
+
if (mediaSettings && mediaSettings.sendShare && localShare) {
|
|
4335
|
+
if (this.state === MEETING_STATE.STATES.JOINED) {
|
|
4336
|
+
return this.share();
|
|
4355
4337
|
}
|
|
4356
4338
|
|
|
4357
|
-
|
|
4358
|
-
|
|
4359
|
-
|
|
4360
|
-
correlation_id: this.correlationId,
|
|
4361
|
-
locus_id: this.locusUrl.split('/').pop()
|
|
4362
|
-
}
|
|
4363
|
-
);
|
|
4339
|
+
// When the self state changes to JOINED then request the floor
|
|
4340
|
+
this.floorGrantPending = true;
|
|
4341
|
+
}
|
|
4364
4342
|
|
|
4365
|
-
|
|
4366
|
-
|
|
4343
|
+
return {};
|
|
4344
|
+
})
|
|
4345
|
+
.then(() => this.mediaProperties.getCurrentConnectionType())
|
|
4346
|
+
.then((connectionType) => {
|
|
4347
|
+
Metrics.sendBehavioralMetric(
|
|
4348
|
+
BEHAVIORAL_METRICS.ADD_MEDIA_SUCCESS,
|
|
4349
|
+
{
|
|
4350
|
+
correlation_id: this.correlationId,
|
|
4351
|
+
locus_id: this.locusUrl.split('/').pop(),
|
|
4352
|
+
connectionType
|
|
4353
|
+
}
|
|
4354
|
+
);
|
|
4355
|
+
})
|
|
4367
4356
|
.catch((error) => {
|
|
4368
4357
|
// Clean up stats analyzer, peer connection, and turn off listeners
|
|
4369
4358
|
const stopStatsAnalyzer = (this.statsAnalyzer) ? this.statsAnalyzer.stopAnalyzer() : Promise.resolve();
|
|
4370
4359
|
|
|
4371
|
-
stopStatsAnalyzer
|
|
4360
|
+
return stopStatsAnalyzer
|
|
4372
4361
|
.then(() => {
|
|
4373
4362
|
this.statsAnalyzer = null;
|
|
4374
4363
|
|