@webex/plugin-meetings 3.0.0-beta.291 → 3.0.0-beta.293
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/breakouts/breakout.js +1 -1
- package/dist/breakouts/index.js +1 -1
- package/dist/common/errors/webex-errors.js +21 -1
- package/dist/common/errors/webex-errors.js.map +1 -1
- package/dist/config.js +1 -2
- package/dist/config.js.map +1 -1
- package/dist/interpretation/index.js +1 -1
- package/dist/interpretation/siLanguage.js +1 -1
- package/dist/meeting/index.js +357 -173
- package/dist/meeting/index.js.map +1 -1
- package/dist/meetings/index.js +0 -17
- package/dist/meetings/index.js.map +1 -1
- package/dist/reconnection-manager/index.js +2 -2
- package/dist/reconnection-manager/index.js.map +1 -1
- package/dist/roap/index.js +3 -2
- package/dist/roap/index.js.map +1 -1
- package/dist/roap/turnDiscovery.js +15 -16
- package/dist/roap/turnDiscovery.js.map +1 -1
- package/dist/types/common/errors/webex-errors.d.ts +12 -0
- package/dist/types/config.d.ts +0 -1
- package/dist/types/meeting/index.d.ts +42 -1
- package/dist/types/meetings/index.d.ts +0 -8
- package/dist/types/roap/index.d.ts +2 -1
- package/dist/types/roap/turnDiscovery.d.ts +3 -2
- package/dist/webinar/index.js +1 -1
- package/package.json +19 -19
- package/src/common/errors/webex-errors.ts +17 -0
- package/src/config.ts +0 -1
- package/src/meeting/index.ts +150 -9
- package/src/meetings/index.ts +0 -15
- package/src/reconnection-manager/index.ts +2 -2
- package/src/roap/index.ts +3 -2
- package/src/roap/turnDiscovery.ts +8 -12
- package/test/unit/spec/meeting/index.js +310 -45
- package/test/unit/spec/meetings/index.js +0 -28
- package/test/unit/spec/reconnection-manager/index.js +1 -0
- package/test/unit/spec/roap/index.ts +16 -22
- package/test/unit/spec/roap/turnDiscovery.ts +42 -31
package/src/meeting/index.ts
CHANGED
|
@@ -38,6 +38,7 @@ import {
|
|
|
38
38
|
UserInLobbyError,
|
|
39
39
|
NoMediaEstablishedYetError,
|
|
40
40
|
UserNotJoinedError,
|
|
41
|
+
AddMediaFailed,
|
|
41
42
|
} from '../common/errors/webex-errors';
|
|
42
43
|
import {StatsAnalyzer, EVENTS as StatsAnalyzerEvents} from '../statsAnalyzer';
|
|
43
44
|
import NetworkQualityMonitor from '../networkQualityMonitor';
|
|
@@ -569,6 +570,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
569
570
|
allowMediaInLobby: boolean;
|
|
570
571
|
turnDiscoverySkippedReason: string;
|
|
571
572
|
turnServerUsed: boolean;
|
|
573
|
+
private retriedWithTurnServer: boolean;
|
|
572
574
|
private sendSlotManager: SendSlotManager = new SendSlotManager(LoggerProxy);
|
|
573
575
|
private deferSDPAnswer?: Defer; // used for waiting for a response
|
|
574
576
|
private sdpResponseTimer?: ReturnType<typeof setTimeout>;
|
|
@@ -1304,6 +1306,15 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1304
1306
|
* @memberof Meeting
|
|
1305
1307
|
*/
|
|
1306
1308
|
this.turnServerUsed = false;
|
|
1309
|
+
|
|
1310
|
+
/**
|
|
1311
|
+
* Whether retry was done using TURN Discovery.
|
|
1312
|
+
* @instance
|
|
1313
|
+
* @type {boolean}
|
|
1314
|
+
* @private
|
|
1315
|
+
* @memberof Meeting
|
|
1316
|
+
*/
|
|
1317
|
+
this.retriedWithTurnServer = false;
|
|
1307
1318
|
}
|
|
1308
1319
|
|
|
1309
1320
|
/**
|
|
@@ -5708,8 +5719,8 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5708
5719
|
this.webex.internal.newMetrics.submitClientEvent({
|
|
5709
5720
|
name: 'client.ice.end',
|
|
5710
5721
|
payload: {
|
|
5711
|
-
canProceed:
|
|
5712
|
-
icePhase: 'JOIN_MEETING_FINAL',
|
|
5722
|
+
canProceed: !this.turnServerUsed, // If we haven't done turn tls retry yet we will proceed with join attempt
|
|
5723
|
+
icePhase: this.turnServerUsed ? 'JOIN_MEETING_FINAL' : 'JOIN_MEETING_RETRY',
|
|
5713
5724
|
errors: [
|
|
5714
5725
|
// @ts-ignore
|
|
5715
5726
|
this.webex.internal.newMetrics.callDiagnosticMetrics.getErrorPayloadForClientErrorCode({
|
|
@@ -5817,20 +5828,109 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5817
5828
|
}
|
|
5818
5829
|
|
|
5819
5830
|
/**
|
|
5820
|
-
*
|
|
5831
|
+
* Calls establishMediaConnection with isForced = true to force turn discovery to happen
|
|
5821
5832
|
*
|
|
5822
5833
|
* @private
|
|
5823
5834
|
* @param {RemoteMediaManagerConfiguration} [remoteMediaManagerConfig]
|
|
5824
5835
|
* @param {BundlePolicy} [bundlePolicy]
|
|
5825
5836
|
* @returns {Promise<void>}
|
|
5826
5837
|
*/
|
|
5827
|
-
private async
|
|
5838
|
+
private async retryEstablishMediaConnectionWithForcedTurnDiscovery(
|
|
5828
5839
|
remoteMediaManagerConfig?: RemoteMediaManagerConfiguration,
|
|
5829
5840
|
bundlePolicy?: BundlePolicy
|
|
5841
|
+
): Promise<void> {
|
|
5842
|
+
const LOG_HEADER =
|
|
5843
|
+
'Meeting:index#addMedia():retryEstablishMediaConnectionWithForcedTurnDiscovery -->';
|
|
5844
|
+
|
|
5845
|
+
try {
|
|
5846
|
+
await this.establishMediaConnection(remoteMediaManagerConfig, bundlePolicy, true);
|
|
5847
|
+
} catch (err) {
|
|
5848
|
+
LoggerProxy.logger.error(
|
|
5849
|
+
`${LOG_HEADER} retry with TURN-TLS failed, media connection unable to connect, `,
|
|
5850
|
+
err
|
|
5851
|
+
);
|
|
5852
|
+
|
|
5853
|
+
throw err;
|
|
5854
|
+
}
|
|
5855
|
+
}
|
|
5856
|
+
|
|
5857
|
+
/**
|
|
5858
|
+
* Does relevant clean up before retrying to establish media connection
|
|
5859
|
+
* and performs the retry with forced turn discovery
|
|
5860
|
+
*
|
|
5861
|
+
* @private
|
|
5862
|
+
* @param {RemoteMediaManagerConfiguration} [remoteMediaManagerConfig]
|
|
5863
|
+
* @param {BundlePolicy} [bundlePolicy]
|
|
5864
|
+
* @returns {Promise<void>}
|
|
5865
|
+
*/
|
|
5866
|
+
private async retryWithForcedTurnDiscovery(
|
|
5867
|
+
remoteMediaManagerConfig?: RemoteMediaManagerConfiguration,
|
|
5868
|
+
bundlePolicy?: BundlePolicy
|
|
5869
|
+
): Promise<void> {
|
|
5870
|
+
this.retriedWithTurnServer = true;
|
|
5871
|
+
|
|
5872
|
+
await this.cleanUpBeforeRetryWithTurnServer();
|
|
5873
|
+
|
|
5874
|
+
await this.retryEstablishMediaConnectionWithForcedTurnDiscovery(
|
|
5875
|
+
remoteMediaManagerConfig,
|
|
5876
|
+
bundlePolicy
|
|
5877
|
+
);
|
|
5878
|
+
}
|
|
5879
|
+
|
|
5880
|
+
/**
|
|
5881
|
+
* If waitForMediaConnectionConnected() fails when we haven't done turn discovery then we
|
|
5882
|
+
* attempt to establish a media connection again, but this time using turn discovery. If we
|
|
5883
|
+
* used turn discovery on the first pass we do not attempt connection again.
|
|
5884
|
+
*
|
|
5885
|
+
* @private
|
|
5886
|
+
* @param {Error} error
|
|
5887
|
+
* @param {RemoteMediaManagerConfiguration} [remoteMediaManagerConfig]
|
|
5888
|
+
* @param {BundlePolicy} [bundlePolicy]
|
|
5889
|
+
* @returns {Promise<void>}
|
|
5890
|
+
*/
|
|
5891
|
+
private async handleWaitForMediaConnectionConnectedError(
|
|
5892
|
+
error: Error,
|
|
5893
|
+
remoteMediaManagerConfig?: RemoteMediaManagerConfiguration,
|
|
5894
|
+
bundlePolicy?: BundlePolicy
|
|
5895
|
+
): Promise<void> {
|
|
5896
|
+
const LOG_HEADER = 'Meeting:index#addMedia():handleWaitForMediaConnectionConnectedError -->';
|
|
5897
|
+
|
|
5898
|
+
// @ts-ignore - config coming from registerPlugin
|
|
5899
|
+
if (!this.turnServerUsed) {
|
|
5900
|
+
LoggerProxy.logger.info(
|
|
5901
|
+
`${LOG_HEADER} error waiting for media to connect on UDP, TCP, retrying using TURN-TLS, `,
|
|
5902
|
+
error
|
|
5903
|
+
);
|
|
5904
|
+
|
|
5905
|
+
await this.retryWithForcedTurnDiscovery(remoteMediaManagerConfig, bundlePolicy);
|
|
5906
|
+
} else {
|
|
5907
|
+
LoggerProxy.logger.error(
|
|
5908
|
+
`${LOG_HEADER} error waiting for media to connect using UDP, TCP and TURN-TLS`,
|
|
5909
|
+
error
|
|
5910
|
+
);
|
|
5911
|
+
|
|
5912
|
+
throw new AddMediaFailed();
|
|
5913
|
+
}
|
|
5914
|
+
}
|
|
5915
|
+
|
|
5916
|
+
/**
|
|
5917
|
+
* Does TURN discovery, SDP offer/answer exhange, establishes ICE connection and DTLS handshake.
|
|
5918
|
+
*
|
|
5919
|
+
* @private
|
|
5920
|
+
* @param {RemoteMediaManagerConfiguration} [remoteMediaManagerConfig]
|
|
5921
|
+
* @param {BundlePolicy} [bundlePolicy]
|
|
5922
|
+
* @param {boolean} [isForced] - let isForced be true to do turn discovery regardless of reachability results
|
|
5923
|
+
* @returns {Promise<void>}
|
|
5924
|
+
*/
|
|
5925
|
+
private async establishMediaConnection(
|
|
5926
|
+
remoteMediaManagerConfig?: RemoteMediaManagerConfiguration,
|
|
5927
|
+
bundlePolicy?: BundlePolicy,
|
|
5928
|
+
isForced?: boolean
|
|
5830
5929
|
): Promise<void> {
|
|
5831
5930
|
const LOG_HEADER = 'Meeting:index#addMedia():establishMediaConnection -->';
|
|
5832
5931
|
// @ts-ignore
|
|
5833
5932
|
const cdl = this.webex.internal.newMetrics.callDiagnosticLatencies;
|
|
5933
|
+
const isRetry = this.retriedWithTurnServer;
|
|
5834
5934
|
|
|
5835
5935
|
try {
|
|
5836
5936
|
// @ts-ignore
|
|
@@ -5838,7 +5938,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5838
5938
|
name: 'internal.client.add-media.turn-discovery.start',
|
|
5839
5939
|
});
|
|
5840
5940
|
|
|
5841
|
-
const turnDiscoveryObject = await this.roap.doTurnDiscovery(this,
|
|
5941
|
+
const turnDiscoveryObject = await this.roap.doTurnDiscovery(this, isRetry, isForced);
|
|
5842
5942
|
|
|
5843
5943
|
this.turnDiscoverySkippedReason = turnDiscoveryObject?.turnDiscoverySkippedReason;
|
|
5844
5944
|
this.turnServerUsed = !this.turnDiscoverySkippedReason;
|
|
@@ -5853,6 +5953,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5853
5953
|
correlation_id: this.correlationId,
|
|
5854
5954
|
latency: cdl.getTurnDiscoveryTime(),
|
|
5855
5955
|
turnServerUsed: this.turnServerUsed,
|
|
5956
|
+
retriedWithTurnServer: this.retriedWithTurnServer,
|
|
5856
5957
|
});
|
|
5857
5958
|
}
|
|
5858
5959
|
|
|
@@ -5898,7 +5999,15 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5898
5999
|
throw error;
|
|
5899
6000
|
}
|
|
5900
6001
|
|
|
5901
|
-
|
|
6002
|
+
try {
|
|
6003
|
+
await this.waitForMediaConnectionConnected();
|
|
6004
|
+
} catch (error) {
|
|
6005
|
+
await this.handleWaitForMediaConnectionConnectedError(
|
|
6006
|
+
error,
|
|
6007
|
+
remoteMediaManagerConfig,
|
|
6008
|
+
bundlePolicy
|
|
6009
|
+
);
|
|
6010
|
+
}
|
|
5902
6011
|
}
|
|
5903
6012
|
|
|
5904
6013
|
/**
|
|
@@ -5907,7 +6016,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5907
6016
|
* @private
|
|
5908
6017
|
* @returns {Promise<void>}
|
|
5909
6018
|
*/
|
|
5910
|
-
private async cleanUpOnAddMediaFailure() {
|
|
6019
|
+
private async cleanUpOnAddMediaFailure(): Promise<void> {
|
|
5911
6020
|
if (this.statsAnalyzer) {
|
|
5912
6021
|
await this.statsAnalyzer.stopAnalyzer();
|
|
5913
6022
|
}
|
|
@@ -5924,6 +6033,36 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5924
6033
|
}
|
|
5925
6034
|
}
|
|
5926
6035
|
|
|
6036
|
+
/**
|
|
6037
|
+
* Sends stats report, closes peer connection and cleans up any media connection
|
|
6038
|
+
* related things before trying to establish media connection again with turn server
|
|
6039
|
+
*
|
|
6040
|
+
* @private
|
|
6041
|
+
* @returns {Promise<void>}
|
|
6042
|
+
*/
|
|
6043
|
+
private async cleanUpBeforeRetryWithTurnServer(): Promise<void> {
|
|
6044
|
+
// when media fails, we want to upload a webrtc dump to see whats going on
|
|
6045
|
+
// this function is async, but returns once the stats have been gathered
|
|
6046
|
+
await this.forceSendStatsReport({callFrom: 'cleanUpBeforeRetryWithTurnServer'});
|
|
6047
|
+
|
|
6048
|
+
if (this.mediaProperties.webrtcMediaConnection) {
|
|
6049
|
+
if (this.remoteMediaManager) {
|
|
6050
|
+
this.remoteMediaManager.stop();
|
|
6051
|
+
this.remoteMediaManager = null;
|
|
6052
|
+
}
|
|
6053
|
+
|
|
6054
|
+
Object.values(this.mediaRequestManagers).forEach((mediaRequestManager) =>
|
|
6055
|
+
mediaRequestManager.reset()
|
|
6056
|
+
);
|
|
6057
|
+
|
|
6058
|
+
this.receiveSlotManager.reset();
|
|
6059
|
+
this.mediaProperties.webrtcMediaConnection.close();
|
|
6060
|
+
this.sendSlotManager.reset();
|
|
6061
|
+
|
|
6062
|
+
this.mediaProperties.unsetPeerConnection();
|
|
6063
|
+
}
|
|
6064
|
+
}
|
|
6065
|
+
|
|
5927
6066
|
/**
|
|
5928
6067
|
* Creates a media connection to the server. Media connection is required for sending or receiving any audio/video.
|
|
5929
6068
|
*
|
|
@@ -5932,7 +6071,8 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5932
6071
|
* @public
|
|
5933
6072
|
* @memberof Meeting
|
|
5934
6073
|
*/
|
|
5935
|
-
async addMedia(options: AddMediaOptions = {}) {
|
|
6074
|
+
async addMedia(options: AddMediaOptions = {}): Promise<void> {
|
|
6075
|
+
this.retriedWithTurnServer = false;
|
|
5936
6076
|
const LOG_HEADER = 'Meeting:index#addMedia -->';
|
|
5937
6077
|
LoggerProxy.logger.info(`${LOG_HEADER} called with: ${JSON.stringify(options)}`);
|
|
5938
6078
|
|
|
@@ -6028,7 +6168,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
6028
6168
|
|
|
6029
6169
|
this.createStatsAnalyzer();
|
|
6030
6170
|
|
|
6031
|
-
await this.establishMediaConnection(remoteMediaManagerConfig, bundlePolicy);
|
|
6171
|
+
await this.establishMediaConnection(remoteMediaManagerConfig, bundlePolicy, false);
|
|
6032
6172
|
|
|
6033
6173
|
await Meeting.handleDeviceLogging();
|
|
6034
6174
|
|
|
@@ -6074,6 +6214,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
6074
6214
|
code: error.code,
|
|
6075
6215
|
turnDiscoverySkippedReason: this.turnDiscoverySkippedReason,
|
|
6076
6216
|
turnServerUsed: this.turnServerUsed,
|
|
6217
|
+
retriedWithTurnServer: this.retriedWithTurnServer,
|
|
6077
6218
|
isMultistream: this.isMultistream,
|
|
6078
6219
|
signalingState:
|
|
6079
6220
|
this.mediaProperties.webrtcMediaConnection?.multistreamConnection?.pc?.pc
|
package/src/meetings/index.ts
CHANGED
|
@@ -681,21 +681,6 @@ export default class Meetings extends WebexPlugin {
|
|
|
681
681
|
}
|
|
682
682
|
}
|
|
683
683
|
|
|
684
|
-
/**
|
|
685
|
-
* API to enable or disable TURN discovery
|
|
686
|
-
* @param {Boolean} enable
|
|
687
|
-
* @private
|
|
688
|
-
* @memberof Meetings
|
|
689
|
-
* @returns {undefined}
|
|
690
|
-
*/
|
|
691
|
-
private _toggleTurnDiscovery(enable: boolean) {
|
|
692
|
-
if (typeof enable !== 'boolean') {
|
|
693
|
-
return;
|
|
694
|
-
}
|
|
695
|
-
// @ts-ignore
|
|
696
|
-
this.config.experimental.enableTurnDiscovery = enable;
|
|
697
|
-
}
|
|
698
|
-
|
|
699
684
|
/**
|
|
700
685
|
* API to toggle starting adhoc meeting
|
|
701
686
|
* @param {Boolean} changeState
|
|
@@ -563,8 +563,8 @@ export default class ReconnectionManager {
|
|
|
563
563
|
'ReconnectionManager:index#reconnectMedia --> Begin reestablishment of media'
|
|
564
564
|
);
|
|
565
565
|
|
|
566
|
-
// do the TURN server discovery again since the TURN server might change
|
|
567
|
-
const turnServerResult = await this.meeting.roap.doTurnDiscovery(this.meeting, true);
|
|
566
|
+
// do the TURN server discovery again and ignore reachability results since the TURN server might change
|
|
567
|
+
const turnServerResult = await this.meeting.roap.doTurnDiscovery(this.meeting, true, true);
|
|
568
568
|
|
|
569
569
|
const iceServers = [];
|
|
570
570
|
|
package/src/roap/index.ts
CHANGED
|
@@ -222,9 +222,10 @@ export default class Roap extends StatelessWebexPlugin {
|
|
|
222
222
|
* @param {Meeting} meeting
|
|
223
223
|
* @param {Boolean} isReconnecting should be set to true if this is a new
|
|
224
224
|
* media connection just after a reconnection
|
|
225
|
+
* @param {Boolean} [isForced]
|
|
225
226
|
* @returns {Promise}
|
|
226
227
|
*/
|
|
227
|
-
doTurnDiscovery(meeting: Meeting, isReconnecting: boolean) {
|
|
228
|
-
return this.turnDiscovery.doTurnDiscovery(meeting, isReconnecting);
|
|
228
|
+
doTurnDiscovery(meeting: Meeting, isReconnecting: boolean, isForced?: boolean) {
|
|
229
|
+
return this.turnDiscovery.doTurnDiscovery(meeting, isReconnecting, isForced);
|
|
229
230
|
}
|
|
230
231
|
}
|
|
@@ -237,15 +237,6 @@ export default class TurnDiscovery {
|
|
|
237
237
|
return 'reachability';
|
|
238
238
|
}
|
|
239
239
|
|
|
240
|
-
// @ts-ignore - fix type
|
|
241
|
-
if (!meeting.config.experimental.enableTurnDiscovery) {
|
|
242
|
-
LoggerProxy.logger.info(
|
|
243
|
-
'Roap:turnDiscovery#getSkipReason --> TURN discovery disabled in config, skipping it'
|
|
244
|
-
);
|
|
245
|
-
|
|
246
|
-
return 'config';
|
|
247
|
-
}
|
|
248
|
-
|
|
249
240
|
return '';
|
|
250
241
|
}
|
|
251
242
|
|
|
@@ -274,12 +265,17 @@ export default class TurnDiscovery {
|
|
|
274
265
|
* so it works fine no matter if TURN discovery is done or not.
|
|
275
266
|
*
|
|
276
267
|
* @param {Meeting} meeting
|
|
277
|
-
* @param {Boolean} isReconnecting should be set to true if this is a new
|
|
268
|
+
* @param {Boolean} [isReconnecting] should be set to true if this is a new
|
|
278
269
|
* media connection just after a reconnection
|
|
270
|
+
* @param {Boolean} [isForced]
|
|
279
271
|
* @returns {Promise}
|
|
280
272
|
*/
|
|
281
|
-
async doTurnDiscovery(meeting: Meeting, isReconnecting?: boolean) {
|
|
282
|
-
|
|
273
|
+
async doTurnDiscovery(meeting: Meeting, isReconnecting?: boolean, isForced?: boolean) {
|
|
274
|
+
let turnDiscoverySkippedReason: string;
|
|
275
|
+
|
|
276
|
+
if (!isForced) {
|
|
277
|
+
turnDiscoverySkippedReason = await this.getSkipReason(meeting);
|
|
278
|
+
}
|
|
283
279
|
|
|
284
280
|
if (turnDiscoverySkippedReason) {
|
|
285
281
|
return {
|