@webex/plugin-meetings 3.8.0-next.55 → 3.8.0-next.56

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.
@@ -1976,5 +1976,11 @@ export default class Meeting extends StatelessWebexPlugin {
1976
1976
  * @returns {Promise<void>}
1977
1977
  */
1978
1978
  checkAndRefreshPermissionToken(threshold: number, reason: string): Promise<void>;
1979
+ /**
1980
+ * Gets the media reachability metrics
1981
+ *
1982
+ * @returns {Promise<MediaReachabilityMetrics>}
1983
+ */
1984
+ private getMediaReachabilityMetricFields;
1979
1985
  }
1980
1986
  export {};
@@ -458,7 +458,7 @@ var Webinar = _webexCore.WebexPlugin.extend({
458
458
  }, _callee7);
459
459
  }))();
460
460
  },
461
- version: "3.8.0-next.55"
461
+ version: "3.8.0-next.56"
462
462
  });
463
463
  var _default = exports.default = Webinar;
464
464
  //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -43,7 +43,7 @@
43
43
  "@webex/eslint-config-legacy": "0.0.0",
44
44
  "@webex/jest-config-legacy": "0.0.0",
45
45
  "@webex/legacy-tools": "0.0.0",
46
- "@webex/plugin-meetings": "3.8.0-next.55",
46
+ "@webex/plugin-meetings": "3.8.0-next.56",
47
47
  "@webex/plugin-rooms": "3.8.0-next.21",
48
48
  "@webex/test-helper-chai": "3.8.0-next.17",
49
49
  "@webex/test-helper-mocha": "3.8.0-next.17",
@@ -71,7 +71,7 @@
71
71
  "@webex/internal-plugin-metrics": "3.8.0-next.17",
72
72
  "@webex/internal-plugin-support": "3.8.0-next.21",
73
73
  "@webex/internal-plugin-user": "3.8.0-next.17",
74
- "@webex/internal-plugin-voicea": "3.8.0-next.55",
74
+ "@webex/internal-plugin-voicea": "3.8.0-next.56",
75
75
  "@webex/media-helpers": "3.8.0-next.19",
76
76
  "@webex/plugin-people": "3.8.0-next.19",
77
77
  "@webex/plugin-rooms": "3.8.0-next.21",
@@ -92,5 +92,5 @@
92
92
  "//": [
93
93
  "TODO: upgrade jwt-decode when moving to node 18"
94
94
  ],
95
- "version": "3.8.0-next.55"
95
+ "version": "3.8.0-next.56"
96
96
  }
@@ -164,6 +164,7 @@ import Member from '../member';
164
164
  import {BrbState, createBrbState} from './brbState';
165
165
  import MultistreamNotSupportedError from '../common/errors/multistream-not-supported-error';
166
166
  import JoinForbiddenError from '../common/errors/join-forbidden-error';
167
+ import {ReachabilityMetrics} from '../reachability/reachability.types';
167
168
 
168
169
  // default callback so we don't call an undefined function, but in practice it should never be used
169
170
  const DEFAULT_ICE_PHASE_CALLBACK = () => 'JOIN_MEETING_FINAL';
@@ -262,6 +263,8 @@ type FetchMeetingInfoParams = {
262
263
  sendCAevents?: boolean;
263
264
  };
264
265
 
266
+ type MediaReachabilityMetrics = ReachabilityMetrics & {isSubnetReachable: boolean};
267
+
265
268
  /**
266
269
  * MediaDirection
267
270
  * @typedef {Object} MediaDirection
@@ -7769,14 +7772,10 @@ export default class Meeting extends StatelessWebexPlugin {
7769
7772
 
7770
7773
  const {connectionType, selectedCandidatePairChanges, numTransports} =
7771
7774
  await this.mediaProperties.getCurrentConnectionInfo();
7772
- // @ts-ignore
7773
- const reachabilityStats = await this.webex.meetings.reachability.getReachabilityMetrics();
7775
+
7774
7776
  const iceCandidateErrors = Object.fromEntries(this.iceCandidateErrors);
7775
7777
 
7776
- // @ts-ignore
7777
- const isSubnetReachable = this.webex.meetings.reachability.isSubnetReachable(
7778
- this.mediaServerIp
7779
- );
7778
+ const reachabilityMetrics = await this.getMediaReachabilityMetricFields();
7780
7779
 
7781
7780
  Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.ADD_MEDIA_SUCCESS, {
7782
7781
  correlation_id: this.correlationId,
@@ -7787,8 +7786,7 @@ export default class Meeting extends StatelessWebexPlugin {
7787
7786
  isMultistream: this.isMultistream,
7788
7787
  retriedWithTurnServer: this.addMediaData.retriedWithTurnServer,
7789
7788
  isJoinWithMediaRetry: this.joinWithMediaRetryInfo.isRetry,
7790
- isSubnetReachable,
7791
- ...reachabilityStats,
7789
+ ...reachabilityMetrics,
7792
7790
  ...iceCandidateErrors,
7793
7791
  iceCandidatesCount: this.iceCandidatesCount,
7794
7792
  });
@@ -7810,18 +7808,13 @@ export default class Meeting extends StatelessWebexPlugin {
7810
7808
  LoggerProxy.logger.error(`${LOG_HEADER} failed to establish media connection: `, error);
7811
7809
 
7812
7810
  // @ts-ignore
7813
- const reachabilityMetrics = await this.webex.meetings.reachability.getReachabilityMetrics();
7811
+ const reachabilityMetrics = await this.getMediaReachabilityMetricFields();
7814
7812
 
7815
7813
  const {selectedCandidatePairChanges, numTransports} =
7816
7814
  await this.mediaProperties.getCurrentConnectionInfo();
7817
7815
 
7818
7816
  const iceCandidateErrors = Object.fromEntries(this.iceCandidateErrors);
7819
7817
 
7820
- // @ts-ignore
7821
- const isSubnetReachable = this.webex.meetings.reachability.isSubnetReachable(
7822
- this.mediaServerIp
7823
- );
7824
-
7825
7818
  Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.ADD_MEDIA_FAILURE, {
7826
7819
  correlation_id: this.correlationId,
7827
7820
  locus_id: this.locusUrl.split('/').pop(),
@@ -7851,7 +7844,6 @@ export default class Meeting extends StatelessWebexPlugin {
7851
7844
  this.mediaProperties.webrtcMediaConnection?.mediaConnection?.pc?.iceConnectionState ||
7852
7845
  'unknown',
7853
7846
  ...reachabilityMetrics,
7854
- isSubnetReachable,
7855
7847
  ...iceCandidateErrors,
7856
7848
  iceCandidatesCount: this.iceCandidatesCount,
7857
7849
  });
@@ -9622,4 +9614,44 @@ export default class Meeting extends StatelessWebexPlugin {
9622
9614
 
9623
9615
  return Promise.resolve();
9624
9616
  }
9617
+
9618
+ /**
9619
+ * Gets the media reachability metrics
9620
+ *
9621
+ * @returns {Promise<MediaReachabilityMetrics>}
9622
+ */
9623
+ private async getMediaReachabilityMetricFields(): Promise<MediaReachabilityMetrics> {
9624
+ const reachabilityMetrics: ReachabilityMetrics =
9625
+ // @ts-ignore
9626
+ await this.webex.meetings.reachability.getReachabilityMetrics();
9627
+
9628
+ const successKeys: Array<keyof ReachabilityMetrics> = [
9629
+ 'reachability_public_udp_success',
9630
+ 'reachability_public_tcp_success',
9631
+ 'reachability_public_xtls_success',
9632
+ 'reachability_vmn_udp_success',
9633
+ 'reachability_vmn_tcp_success',
9634
+ 'reachability_vmn_xtls_success',
9635
+ ];
9636
+
9637
+ const totalSuccessCases = successKeys.reduce((total, key) => {
9638
+ const value = reachabilityMetrics[key];
9639
+ if (typeof value === 'number') {
9640
+ return total + value;
9641
+ }
9642
+
9643
+ return total;
9644
+ }, 0);
9645
+
9646
+ let isSubnetReachable = null;
9647
+ if (totalSuccessCases > 0) {
9648
+ // @ts-ignore
9649
+ isSubnetReachable = this.webex.meetings.reachability.isSubnetReachable(this.mediaServerIp);
9650
+ }
9651
+
9652
+ return {
9653
+ ...reachabilityMetrics,
9654
+ isSubnetReachable,
9655
+ };
9656
+ }
9625
9657
  }
@@ -2166,7 +2166,7 @@ describe('plugin-meetings', () => {
2166
2166
  someReachabilityMetric1: 'some value1',
2167
2167
  someReachabilityMetric2: 'some value2',
2168
2168
  selectedCandidatePairChanges: 2,
2169
- isSubnetReachable: false,
2169
+ isSubnetReachable: null,
2170
2170
  numTransports: 1,
2171
2171
  iceCandidatesCount: 0,
2172
2172
  }
@@ -2213,7 +2213,7 @@ describe('plugin-meetings', () => {
2213
2213
  signalingState: 'unknown',
2214
2214
  connectionState: 'unknown',
2215
2215
  iceConnectionState: 'unknown',
2216
- isSubnetReachable: true,
2216
+ isSubnetReachable: null,
2217
2217
  })
2218
2218
  );
2219
2219
 
@@ -2279,7 +2279,7 @@ describe('plugin-meetings', () => {
2279
2279
  selectedCandidatePairChanges: 2,
2280
2280
  numTransports: 1,
2281
2281
  iceCandidatesCount: 0,
2282
- isSubnetReachable: true,
2282
+ isSubnetReachable: null,
2283
2283
  }
2284
2284
  );
2285
2285
  });
@@ -2337,7 +2337,7 @@ describe('plugin-meetings', () => {
2337
2337
  signalingState: 'have-local-offer',
2338
2338
  connectionState: 'connecting',
2339
2339
  iceConnectionState: 'checking',
2340
- isSubnetReachable: true,
2340
+ isSubnetReachable: null,
2341
2341
  })
2342
2342
  );
2343
2343
 
@@ -2395,7 +2395,7 @@ describe('plugin-meetings', () => {
2395
2395
  signalingState: 'have-local-offer',
2396
2396
  connectionState: 'connecting',
2397
2397
  iceConnectionState: 'checking',
2398
- isSubnetReachable: true,
2398
+ isSubnetReachable: null,
2399
2399
  })
2400
2400
  );
2401
2401
 
@@ -2731,7 +2731,7 @@ describe('plugin-meetings', () => {
2731
2731
  sinon.stub().returns(FAKE_ERROR));
2732
2732
  webex.meetings.reachability = {
2733
2733
  isWebexMediaBackendUnreachable: sinon.stub().resolves(false),
2734
- getReachabilityMetrics: sinon.stub().resolves(),
2734
+ getReachabilityMetrics: sinon.stub().resolves({}),
2735
2735
  stopReachability: sinon.stub(),
2736
2736
  isSubnetReachable: sinon.stub().returns(true),
2737
2737
  };
@@ -2917,7 +2917,7 @@ describe('plugin-meetings', () => {
2917
2917
  selectedCandidatePairChanges: 2,
2918
2918
  numTransports: 1,
2919
2919
  iceCandidatesCount: 0,
2920
- isSubnetReachable: true,
2920
+ isSubnetReachable: null,
2921
2921
  },
2922
2922
  ]);
2923
2923
 
@@ -3120,7 +3120,7 @@ describe('plugin-meetings', () => {
3120
3120
  retriedWithTurnServer: true,
3121
3121
  isJoinWithMediaRetry: false,
3122
3122
  iceCandidatesCount: 0,
3123
- isSubnetReachable: true,
3123
+ isSubnetReachable: null,
3124
3124
  },
3125
3125
  ]);
3126
3126
  meeting.roap.doTurnDiscovery;
@@ -3277,7 +3277,7 @@ describe('plugin-meetings', () => {
3277
3277
  iceCandidatesCount: 3,
3278
3278
  '701_error': 3,
3279
3279
  '701_turn_host_lookup_received_error': 1,
3280
- isSubnetReachable: true,
3280
+ isSubnetReachable: null,
3281
3281
  }
3282
3282
  );
3283
3283
 
@@ -3340,7 +3340,7 @@ describe('plugin-meetings', () => {
3340
3340
  iceConnectionState: 'unknown',
3341
3341
  selectedCandidatePairChanges: 2,
3342
3342
  numTransports: 1,
3343
- isSubnetReachable: true,
3343
+ isSubnetReachable: null,
3344
3344
  iceCandidatesCount: 0,
3345
3345
  }
3346
3346
  );
@@ -3402,6 +3402,120 @@ describe('plugin-meetings', () => {
3402
3402
  numTransports: 1,
3403
3403
  '701_error': 2,
3404
3404
  '701_turn_host_lookup_received_error': 1,
3405
+ isSubnetReachable: null,
3406
+ iceCandidatesCount: 0,
3407
+ }
3408
+ );
3409
+
3410
+ assert.isOk(errorThrown);
3411
+ });
3412
+
3413
+ it('should send valid isSubnetReachability if media connection success', async () => {
3414
+ meeting.roap.doTurnDiscovery = sinon.stub().returns({
3415
+ turnServerInfo: undefined,
3416
+ turnDiscoverySkippedReason: undefined,
3417
+ });
3418
+ meeting.meetingState = 'ACTIVE';
3419
+ meeting.mediaProperties.waitForMediaConnectionConnected.resolves();
3420
+ meeting.webex.meetings.reachability = {
3421
+ getReachabilityMetrics: sinon.stub().resolves({
3422
+ reachability_public_udp_success: 5,
3423
+ }),
3424
+ stopReachability: sinon.stub(),
3425
+ isSubnetReachable: sinon.stub().returns(false),
3426
+ };
3427
+
3428
+ const forceRtcMetricsSend = sinon.stub().resolves();
3429
+ const closeMediaConnectionStub = sinon.stub();
3430
+ Media.createMediaConnection = sinon.stub().returns({
3431
+ close: closeMediaConnectionStub,
3432
+ forceRtcMetricsSend,
3433
+ getConnectionState: sinon.stub().returns(ConnectionState.Connected),
3434
+ initiateOffer: sinon.stub().resolves({}),
3435
+ on: sinon.stub(),
3436
+ });
3437
+
3438
+ await meeting
3439
+ .addMedia({
3440
+ mediaSettings: {},
3441
+ });
3442
+
3443
+ assert.calledWith(
3444
+ Metrics.sendBehavioralMetric,
3445
+ BEHAVIORAL_METRICS.ADD_MEDIA_SUCCESS,
3446
+ {
3447
+ correlation_id: meeting.correlationId,
3448
+ locus_id: meeting.locusUrl.split('/').pop(),
3449
+ connectionType: 'udp',
3450
+ selectedCandidatePairChanges: 2,
3451
+ numTransports: 1,
3452
+ isMultistream: false,
3453
+ retriedWithTurnServer: false,
3454
+ isJoinWithMediaRetry: false,
3455
+ iceCandidatesCount: 0,
3456
+ reachability_public_udp_success: 5,
3457
+ isSubnetReachable: false,
3458
+ }
3459
+ );
3460
+ });
3461
+
3462
+ it('should send valid isSubnetReachability if media connection fails', async () => {
3463
+ let errorThrown = undefined;
3464
+
3465
+ meeting.roap.doTurnDiscovery = sinon.stub().returns({
3466
+ turnServerInfo: undefined,
3467
+ turnDiscoverySkippedReason: undefined,
3468
+ });
3469
+ meeting.meetingState = 'ACTIVE';
3470
+ meeting.mediaProperties.waitForMediaConnectionConnected.rejects({iceConnected: false});
3471
+ meeting.webex.meetings.reachability = {
3472
+ getReachabilityMetrics: sinon.stub().resolves({
3473
+ reachability_public_udp_success: 5,
3474
+ }),
3475
+ stopReachability: sinon.stub(),
3476
+ isSubnetReachable: sinon.stub().returns(true),
3477
+ };
3478
+
3479
+ const forceRtcMetricsSend = sinon.stub().resolves();
3480
+ const closeMediaConnectionStub = sinon.stub();
3481
+ Media.createMediaConnection = sinon.stub().returns({
3482
+ close: closeMediaConnectionStub,
3483
+ forceRtcMetricsSend,
3484
+ getConnectionState: sinon.stub().returns(ConnectionState.Connected),
3485
+ initiateOffer: sinon.stub().resolves({}),
3486
+ on: sinon.stub(),
3487
+ });
3488
+
3489
+ await meeting
3490
+ .addMedia({
3491
+ mediaSettings: {},
3492
+ })
3493
+ .catch((err) => {
3494
+ errorThrown = err;
3495
+ assert.instanceOf(err, AddMediaFailed);
3496
+ });
3497
+
3498
+ // Check that the only metric sent is ADD_MEDIA_FAILURE
3499
+ assert.calledOnceWithExactly(
3500
+ Metrics.sendBehavioralMetric,
3501
+ BEHAVIORAL_METRICS.ADD_MEDIA_FAILURE,
3502
+ {
3503
+ correlation_id: meeting.correlationId,
3504
+ locus_id: meeting.locusUrl.split('/').pop(),
3505
+ reason: errorThrown.message,
3506
+ stack: errorThrown.stack,
3507
+ code: errorThrown.code,
3508
+ turnDiscoverySkippedReason: undefined,
3509
+ turnServerUsed: true,
3510
+ retriedWithTurnServer: false,
3511
+ isMultistream: false,
3512
+ isJoinWithMediaRetry: false,
3513
+ signalingState: 'unknown',
3514
+ connectionState: 'unknown',
3515
+ iceConnectionState: 'unknown',
3516
+ selectedCandidatePairChanges: 2,
3517
+ numTransports: 1,
3518
+ reachability_public_udp_success: 5,
3405
3519
  isSubnetReachable: true,
3406
3520
  iceCandidatesCount: 0,
3407
3521
  }