@webex/plugin-meetings 3.8.1-next.12 → 3.8.1-next.3

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.
@@ -231,14 +231,6 @@ export type AddMediaOptions = {
231
231
  remoteMediaManagerConfig?: RemoteMediaManagerConfiguration; // applies only to multistream meetings
232
232
  bundlePolicy?: BundlePolicy; // applies only to multistream meetings
233
233
  allowMediaInLobby?: boolean; // allows adding media when in the lobby
234
- additionalMediaOptions?: AdditionalMediaOptions; // allows adding additional options like send/receive audio/video
235
- };
236
-
237
- export type AdditionalMediaOptions = {
238
- sendVideo?: boolean; // if not specified, default value of videoEnabled is used
239
- receiveVideo?: boolean; // if not specified, default value of videoEnabled is used
240
- sendAudio?: boolean; // if not specified, default value of audioEnabled true is used
241
- receiveAudio?: boolean; // if not specified, default value of audioEnabled true is used
242
234
  };
243
235
 
244
236
  export type CallStateForMetrics = {
@@ -271,9 +263,8 @@ type FetchMeetingInfoParams = {
271
263
  };
272
264
 
273
265
  type MediaReachabilityMetrics = ReachabilityMetrics & {
274
- subnet_reachable: boolean;
275
- selected_cluster: string | null;
276
- selected_subnet: string | null;
266
+ isSubnetReachable: boolean;
267
+ selectedCluster: string | null;
277
268
  };
278
269
 
279
270
  /**
@@ -2766,9 +2757,7 @@ export default class Meeting extends StatelessWebexPlugin {
2766
2757
  LOCUSINFO.EVENTS.CONTROLS_MEETING_TRANSCRIPTION_SPOKEN_LANGUAGE_UPDATED,
2767
2758
  ({spokenLanguage}) => {
2768
2759
  if (spokenLanguage) {
2769
- if (this.transcription?.languageOptions) {
2770
- this.transcription.languageOptions.currentSpokenLanguage = spokenLanguage;
2771
- }
2760
+ this.transcription.languageOptions.currentSpokenLanguage = spokenLanguage;
2772
2761
  // @ts-ignore
2773
2762
  this.webex.internal.voicea.onSpokenLanguageUpdate(spokenLanguage);
2774
2763
 
@@ -7765,21 +7754,8 @@ export default class Meeting extends StatelessWebexPlugin {
7765
7754
  shareVideoEnabled = true,
7766
7755
  remoteMediaManagerConfig,
7767
7756
  bundlePolicy = 'max-bundle',
7768
- additionalMediaOptions = {},
7769
7757
  } = options;
7770
7758
 
7771
- const {
7772
- sendVideo: rawSendVideo,
7773
- receiveVideo: rawReceiveVideo,
7774
- sendAudio: rawSendAudio,
7775
- receiveAudio: rawReceiveAudio,
7776
- } = additionalMediaOptions;
7777
-
7778
- const sendVideo = videoEnabled && (rawSendVideo ?? true);
7779
- const receiveVideo = videoEnabled && (rawReceiveVideo ?? true);
7780
- const sendAudio = audioEnabled && (rawSendAudio ?? true);
7781
- const receiveAudio = audioEnabled && (rawReceiveAudio ?? true);
7782
-
7783
7759
  this.allowMediaInLobby = options?.allowMediaInLobby;
7784
7760
 
7785
7761
  // If the user is unjoined or guest waiting in lobby dont allow the user to addMedia
@@ -7815,11 +7791,11 @@ export default class Meeting extends StatelessWebexPlugin {
7815
7791
  // when audioEnabled/videoEnabled is true, we set sendAudio/sendVideo to true even before any streams are published
7816
7792
  // to avoid doing an extra SDP exchange when they are published for the first time
7817
7793
  this.mediaProperties.setMediaDirection({
7818
- sendAudio,
7819
- sendVideo,
7794
+ sendAudio: audioEnabled,
7795
+ sendVideo: videoEnabled,
7820
7796
  sendShare: false,
7821
- receiveAudio,
7822
- receiveVideo,
7797
+ receiveAudio: audioEnabled,
7798
+ receiveVideo: videoEnabled,
7823
7799
  receiveShare: shareAudioEnabled || shareVideoEnabled,
7824
7800
  });
7825
7801
 
@@ -9745,22 +9721,21 @@ export default class Meeting extends StatelessWebexPlugin {
9745
9721
  return total;
9746
9722
  }, 0);
9747
9723
 
9748
- const selectedSubnetFirstOctet = this.mediaServerIp?.split('.')[0];
9749
-
9750
9724
  let isSubnetReachable = null;
9751
- if (totalSuccessCases > 0 && selectedSubnetFirstOctet) {
9752
- isSubnetReachable =
9753
- // @ts-ignore
9754
- this.webex.meetings.reachability.isSubnetReachable(selectedSubnetFirstOctet);
9725
+ if (totalSuccessCases > 0) {
9726
+ // @ts-ignore
9727
+ isSubnetReachable = this.webex.meetings.reachability.isSubnetReachable(this.mediaServerIp);
9755
9728
  }
9756
9729
 
9757
- const selectedCluster = this.mediaConnections?.[0]?.mediaAgentCluster ?? null;
9730
+ let selectedCluster = null;
9731
+ if (this.mediaConnections && this.mediaConnections.length > 0) {
9732
+ selectedCluster = this.mediaConnections[0].mediaAgentCluster;
9733
+ }
9758
9734
 
9759
9735
  return {
9760
9736
  ...reachabilityMetrics,
9761
- subnet_reachable: isSubnetReachable,
9762
- selected_cluster: selectedCluster,
9763
- selected_subnet: selectedSubnetFirstOctet ? `${selectedSubnetFirstOctet}.X.X.X` : null,
9737
+ isSubnetReachable,
9738
+ selectedCluster,
9764
9739
  };
9765
9740
  }
9766
9741
  }
@@ -140,14 +140,22 @@ export default class Reachability extends EventsScope {
140
140
 
141
141
  /**
142
142
  * Checks if the given subnet is reachable
143
- * @param {string} selectedSubnetFirstOctet - selected subnet first octet, e.g. "10" for "10.X.X.X"
143
+ * @param {string} mediaServerIp - media server ip
144
144
  * @returns {boolean | null} true if reachable, false if not reachable, null if mediaServerIp is not provided
145
145
  * @public
146
146
  * @memberof Reachability
147
147
  */
148
- public isSubnetReachable(selectedSubnetFirstOctet: string): boolean | null {
148
+ public isSubnetReachable(mediaServerIp?: string): boolean | null {
149
+ if (!mediaServerIp) {
150
+ LoggerProxy.logger.error(`Reachability:index#isSubnetReachable --> mediaServerIp is null`);
151
+
152
+ return null;
153
+ }
154
+
155
+ const subnetFirstOctet = mediaServerIp.split('.')[0];
156
+
149
157
  LoggerProxy.logger.info(
150
- `Reachability:index#isSubnetReachable --> Looking for subnet: ${selectedSubnetFirstOctet}.X.X.X`
158
+ `Reachability:index#isSubnetReachable --> Looking for subnet: ${subnetFirstOctet}.X.X.X`
151
159
  );
152
160
 
153
161
  const matchingReachedClusters = Object.values(this.clusterReachability).reduce(
@@ -159,7 +167,7 @@ export default class Reachability extends EventsScope {
159
167
  const subnet = reachedSubnetsArray[i];
160
168
  const reachedSubnetFirstOctet = subnet.split('.')[0];
161
169
 
162
- if (selectedSubnetFirstOctet === reachedSubnetFirstOctet) {
170
+ if (subnetFirstOctet === reachedSubnetFirstOctet) {
163
171
  acc.add(cluster.name);
164
172
  }
165
173
 
@@ -178,7 +186,7 @@ export default class Reachability extends EventsScope {
178
186
  );
179
187
 
180
188
  LoggerProxy.logger.info(
181
- `Reachability:index#isSubnetReachable --> Found ${matchingReachedClusters.size} clusters that use the subnet ${selectedSubnetFirstOctet}.X.X.X`
189
+ `Reachability:index#isSubnetReachable --> Found ${matchingReachedClusters.size} clusters that use the subnet ${subnetFirstOctet}.X.X.X`
182
190
  );
183
191
 
184
192
  return matchingReachedClusters.size > 0;
@@ -137,113 +137,6 @@ describe('createMediaConnection', () => {
137
137
  );
138
138
  });
139
139
 
140
- it('should set direction to sendonly for both audio and video when only send flags are true', () => {
141
- const roapMediaConnectionConstructorStub = sinon
142
- .stub(InternalMediaCoreModule, 'RoapMediaConnection')
143
- .returns(fakeRoapMediaConnection);
144
-
145
- StaticConfig.set({bandwidth: {audio: 123, video: 456, startBitrate: 999}});
146
-
147
- const ENABLE_EXTMAP = false;
148
- const ENABLE_RTX = true;
149
-
150
- Media.createMediaConnection(false, 'sendonly-debug-id', 'meetingId', {
151
- mediaProperties: {
152
- mediaDirection: {
153
- sendAudio: true,
154
- receiveAudio: false,
155
- sendVideo: true,
156
- receiveVideo: false,
157
- sendShare: false,
158
- receiveShare: false,
159
- },
160
- audioStream: fakeAudioStream,
161
- videoStream: fakeVideoStream,
162
- shareVideoTrack: null,
163
- shareAudioTrack: null,
164
- },
165
- remoteQualityLevel: 'HIGH',
166
- enableRtx: ENABLE_RTX,
167
- enableExtmap: ENABLE_EXTMAP,
168
- turnServerInfo: undefined,
169
- iceCandidatesTimeout: undefined,
170
- });
171
-
172
- assert.calledWith(
173
- roapMediaConnectionConstructorStub,
174
- sinon.match.any,
175
- {
176
- localTracks: {
177
- audio: fakeTrack,
178
- video: fakeTrack,
179
- screenShareVideo: undefined,
180
- screenShareAudio: undefined,
181
- },
182
- direction: {
183
- audio: 'sendonly',
184
- video: 'sendonly',
185
- screenShareVideo: 'inactive',
186
- },
187
- remoteQualityLevel: 'HIGH',
188
- },
189
- 'sendonly-debug-id'
190
- );
191
- });
192
-
193
- it('should set direction to recvonly for both audio and video when only receive flags are true', () => {
194
- const roapMediaConnectionConstructorStub = sinon
195
- .stub(InternalMediaCoreModule, 'RoapMediaConnection')
196
- .returns(fakeRoapMediaConnection);
197
-
198
- StaticConfig.set({bandwidth: {audio: 123, video: 456, startBitrate: 999}});
199
-
200
- const ENABLE_EXTMAP = true;
201
- const ENABLE_RTX = false;
202
-
203
- Media.createMediaConnection(false, 'recvonly-debug-id', 'meetingId', {
204
- mediaProperties: {
205
- mediaDirection: {
206
- sendAudio: false,
207
- receiveAudio: true,
208
- sendVideo: false,
209
- receiveVideo: true,
210
- sendShare: false,
211
- receiveShare: false,
212
- },
213
- audioStream: fakeAudioStream,
214
- videoStream: fakeVideoStream,
215
- shareVideoTrack: null,
216
- shareAudioTrack: null,
217
- },
218
- remoteQualityLevel: 'HIGH',
219
- enableRtx: ENABLE_RTX,
220
- enableExtmap: ENABLE_EXTMAP,
221
- turnServerInfo: undefined,
222
- iceCandidatesTimeout: undefined,
223
- });
224
-
225
- assert.calledWith(
226
- roapMediaConnectionConstructorStub,
227
- sinon.match.any,
228
- {
229
- localTracks: {
230
- audio: fakeTrack,
231
- video: fakeTrack,
232
- screenShareVideo: undefined,
233
- screenShareAudio: undefined,
234
- },
235
- direction: {
236
- audio: 'recvonly',
237
- video: 'recvonly',
238
- screenShareVideo: 'inactive',
239
- },
240
- remoteQualityLevel: 'HIGH',
241
- },
242
- 'recvonly-debug-id'
243
- );
244
- });
245
-
246
-
247
140
  it('creates a MultistreamRoapMediaConnection when multistream is enabled', () => {
248
141
  const multistreamRoapMediaConnectionConstructorStub = sinon
249
142
  .stub(InternalMediaCoreModule, 'MultistreamRoapMediaConnection')
@@ -1208,76 +1208,8 @@ describe('plugin-meetings', () => {
1208
1208
  reason: 'joinWithMedia failure',
1209
1209
  });
1210
1210
  });
1211
-
1212
- it('should ignore sendVideo/receiveVideo when videoEnabled is false', async () => {
1213
- await meeting.joinWithMedia({
1214
- joinOptions,
1215
- mediaOptions: {
1216
- videoEnabled: false,
1217
- sendVideo: true,
1218
- receiveVideo: true,
1219
- allowMediaInLobby: true,
1220
- },
1221
- });
1222
-
1223
- assert.calledWithMatch(
1224
- meeting.addMediaInternal,
1225
- sinon.match.any,
1226
- sinon.match.any,
1227
- sinon.match.any,
1228
- sinon.match.has('videoEnabled', false)
1229
- .and(sinon.match.has('allowMediaInLobby', true))
1230
- );
1231
- });
1232
-
1233
- it('should ignore sendAudio/receiveAudio when audioEnabled is false', async () => {
1234
- await meeting.joinWithMedia({
1235
- joinOptions,
1236
- mediaOptions: {
1237
- audioEnabled: false,
1238
- sendAudio: true,
1239
- receiveAudio: false,
1240
- allowMediaInLobby: true,
1241
- },
1242
- });
1243
-
1244
- assert.calledWithMatch(
1245
- meeting.addMediaInternal,
1246
- sinon.match.any,
1247
- sinon.match.any,
1248
- sinon.match.any,
1249
- sinon.match.has('audioEnabled', false)
1250
- .and(sinon.match.has('allowMediaInLobby', true))
1251
- );
1252
- });
1253
-
1254
-
1255
- it('should use provided send/receive values when videoEnabled/audioEnabled are true or not set', async () => {
1256
- await meeting.joinWithMedia({
1257
- joinOptions,
1258
- mediaOptions: {
1259
- sendVideo: true,
1260
- receiveVideo: false,
1261
- sendAudio: false,
1262
- receiveAudio: true,
1263
- allowMediaInLobby: true,
1264
- },
1265
- });
1266
-
1267
- assert.calledWith(
1268
- meeting.addMediaInternal,
1269
- sinon.match.any,
1270
- sinon.match.any,
1271
- sinon.match.any,
1272
- sinon.match({
1273
- sendVideo: true,
1274
- receiveVideo: false,
1275
- sendAudio: false,
1276
- receiveAudio: true,
1277
- })
1278
- );
1279
- });
1280
1211
  });
1212
+
1281
1213
  describe('#isTranscriptionSupported', () => {
1282
1214
  it('should return false if the feature is not supported for the meeting', () => {
1283
1215
  meeting.locusInfo.controls = {transcribe: {caption: false}};
@@ -2295,9 +2227,8 @@ describe('plugin-meetings', () => {
2295
2227
  someReachabilityMetric1: 'some value1',
2296
2228
  someReachabilityMetric2: 'some value2',
2297
2229
  selectedCandidatePairChanges: 2,
2298
- subnet_reachable: null,
2299
- selected_cluster: null,
2300
- selected_subnet: null,
2230
+ isSubnetReachable: null,
2231
+ selectedCluster: null,
2301
2232
  numTransports: 1,
2302
2233
  iceCandidatesCount: 0,
2303
2234
  }
@@ -2344,9 +2275,8 @@ describe('plugin-meetings', () => {
2344
2275
  signalingState: 'unknown',
2345
2276
  connectionState: 'unknown',
2346
2277
  iceConnectionState: 'unknown',
2347
- subnet_reachable: null,
2348
- selected_cluster: null,
2349
- selected_subnet: null,
2278
+ isSubnetReachable: null,
2279
+ selectedCluster: null,
2350
2280
  })
2351
2281
  );
2352
2282
 
@@ -2412,9 +2342,8 @@ describe('plugin-meetings', () => {
2412
2342
  selectedCandidatePairChanges: 2,
2413
2343
  numTransports: 1,
2414
2344
  iceCandidatesCount: 0,
2415
- subnet_reachable: null,
2416
- selected_cluster: null,
2417
- selected_subnet: null,
2345
+ isSubnetReachable: null,
2346
+ selectedCluster: null,
2418
2347
  }
2419
2348
  );
2420
2349
  });
@@ -2472,9 +2401,8 @@ describe('plugin-meetings', () => {
2472
2401
  signalingState: 'have-local-offer',
2473
2402
  connectionState: 'connecting',
2474
2403
  iceConnectionState: 'checking',
2475
- subnet_reachable: null,
2476
- selected_cluster: null,
2477
- selected_subnet: null,
2404
+ isSubnetReachable: null,
2405
+ selectedCluster: null,
2478
2406
  })
2479
2407
  );
2480
2408
 
@@ -2532,9 +2460,8 @@ describe('plugin-meetings', () => {
2532
2460
  signalingState: 'have-local-offer',
2533
2461
  connectionState: 'connecting',
2534
2462
  iceConnectionState: 'checking',
2535
- subnet_reachable: null,
2536
- selected_cluster: null,
2537
- selected_subnet: null,
2463
+ isSubnetReachable: null,
2464
+ selectedCluster: null,
2538
2465
  })
2539
2466
  );
2540
2467
 
@@ -3056,9 +2983,8 @@ describe('plugin-meetings', () => {
3056
2983
  selectedCandidatePairChanges: 2,
3057
2984
  numTransports: 1,
3058
2985
  iceCandidatesCount: 0,
3059
- subnet_reachable: null,
3060
- selected_cluster: null,
3061
- selected_subnet: null,
2986
+ isSubnetReachable: null,
2987
+ selectedCluster: null,
3062
2988
  },
3063
2989
  ]);
3064
2990
 
@@ -3265,9 +3191,8 @@ describe('plugin-meetings', () => {
3265
3191
  retriedWithTurnServer: true,
3266
3192
  isJoinWithMediaRetry: false,
3267
3193
  iceCandidatesCount: 0,
3268
- subnet_reachable: null,
3269
- selected_cluster: null,
3270
- selected_subnet: null,
3194
+ isSubnetReachable: null,
3195
+ selectedCluster: null,
3271
3196
  },
3272
3197
  ]);
3273
3198
  meeting.roap.doTurnDiscovery;
@@ -3430,9 +3355,8 @@ describe('plugin-meetings', () => {
3430
3355
  iceCandidatesCount: 3,
3431
3356
  '701_error': 3,
3432
3357
  '701_turn_host_lookup_received_error': 1,
3433
- subnet_reachable: null,
3434
- selected_cluster: 'some.cluster',
3435
- selected_subnet: null,
3358
+ isSubnetReachable: null,
3359
+ selectedCluster: 'some.cluster',
3436
3360
  }
3437
3361
  );
3438
3362
 
@@ -3495,9 +3419,8 @@ describe('plugin-meetings', () => {
3495
3419
  iceConnectionState: 'unknown',
3496
3420
  selectedCandidatePairChanges: 2,
3497
3421
  numTransports: 1,
3498
- subnet_reachable: null,
3499
- selected_cluster: null,
3500
- selected_subnet: null,
3422
+ isSubnetReachable: null,
3423
+ selectedCluster: null,
3501
3424
  iceCandidatesCount: 0,
3502
3425
  }
3503
3426
  );
@@ -3559,9 +3482,8 @@ describe('plugin-meetings', () => {
3559
3482
  numTransports: 1,
3560
3483
  '701_error': 2,
3561
3484
  '701_turn_host_lookup_received_error': 1,
3562
- subnet_reachable: null,
3563
- selected_cluster: null,
3564
- selected_subnet: null,
3485
+ isSubnetReachable: null,
3486
+ selectedCluster: null,
3565
3487
  iceCandidatesCount: 0,
3566
3488
  }
3567
3489
  );
@@ -3569,7 +3491,7 @@ describe('plugin-meetings', () => {
3569
3491
  assert.isOk(errorThrown);
3570
3492
  });
3571
3493
 
3572
- it('should send subnet reachablity metrics if media connection success', async () => {
3494
+ it('should send valid isSubnetReachability if media connection success', async () => {
3573
3495
  meeting.roap.doTurnDiscovery = sinon.stub().returns({
3574
3496
  turnServerInfo: undefined,
3575
3497
  turnDiscoverySkippedReason: undefined,
@@ -3583,12 +3505,6 @@ describe('plugin-meetings', () => {
3583
3505
  stopReachability: sinon.stub(),
3584
3506
  isSubnetReachable: sinon.stub().returns(false),
3585
3507
  };
3586
- meeting.mediaServerIp = '1.2.3.4';
3587
- meeting.mediaConnections = [
3588
- {
3589
- mediaAgentCluster: 'some.cluster',
3590
- }
3591
- ]
3592
3508
 
3593
3509
  const forceRtcMetricsSend = sinon.stub().resolves();
3594
3510
  const closeMediaConnectionStub = sinon.stub();
@@ -3616,13 +3532,12 @@ describe('plugin-meetings', () => {
3616
3532
  isJoinWithMediaRetry: false,
3617
3533
  iceCandidatesCount: 0,
3618
3534
  reachability_public_udp_success: 5,
3619
- subnet_reachable: false,
3620
- selected_cluster: 'some.cluster',
3621
- selected_subnet: '1.X.X.X',
3535
+ isSubnetReachable: false,
3536
+ selectedCluster: null,
3622
3537
  });
3623
3538
  });
3624
3539
 
3625
- it('should send subnet reachablity metrics if media connection fails', async () => {
3540
+ it('should send valid isSubnetReachability if media connection fails', async () => {
3626
3541
  let errorThrown = undefined;
3627
3542
 
3628
3543
  meeting.roap.doTurnDiscovery = sinon.stub().returns({
@@ -3638,12 +3553,6 @@ describe('plugin-meetings', () => {
3638
3553
  stopReachability: sinon.stub(),
3639
3554
  isSubnetReachable: sinon.stub().returns(true),
3640
3555
  };
3641
- meeting.mediaServerIp = '1.2.3.4';
3642
- meeting.mediaConnections = [
3643
- {
3644
- mediaAgentCluster: 'some.cluster',
3645
- }
3646
- ]
3647
3556
 
3648
3557
  const forceRtcMetricsSend = sinon.stub().resolves();
3649
3558
  const closeMediaConnectionStub = sinon.stub();
@@ -3685,9 +3594,8 @@ describe('plugin-meetings', () => {
3685
3594
  selectedCandidatePairChanges: 2,
3686
3595
  numTransports: 1,
3687
3596
  reachability_public_udp_success: 5,
3688
- subnet_reachable: true,
3689
- selected_cluster: 'some.cluster',
3690
- selected_subnet: '1.X.X.X',
3597
+ isSubnetReachable: true,
3598
+ selectedCluster: null,
3691
3599
  iceCandidatesCount: 0,
3692
3600
  }
3693
3601
  );
@@ -2764,10 +2764,14 @@ describe('isSubnetReachable', () => {
2764
2764
  });
2765
2765
 
2766
2766
  it('returns true if the subnet is reachable', () => {
2767
- assert(reachability.isSubnetReachable('1'));
2767
+ assert(reachability.isSubnetReachable('1.2.3.4'));
2768
2768
  });
2769
2769
 
2770
2770
  it(`returns false if the subnet is unreachable`, () => {
2771
- assert(!reachability.isSubnetReachable('11'));
2771
+ assert(!reachability.isSubnetReachable('11.2.3.4'));
2772
+ });
2773
+
2774
+ it('returns null if the subnet is not provided', () => {
2775
+ assert.isNull(reachability.isSubnetReachable(undefined));
2772
2776
  });
2773
2777
  });