@webex/plugin-meetings 2.60.0-next.1 → 2.60.0-next.2

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.
Files changed (55) hide show
  1. package/dist/breakouts/breakout.js +1 -1
  2. package/dist/breakouts/index.js +1 -1
  3. package/dist/constants.js +1 -1
  4. package/dist/constants.js.map +1 -1
  5. package/dist/controls-options-manager/enums.js +2 -1
  6. package/dist/controls-options-manager/enums.js.map +1 -1
  7. package/dist/interpretation/index.js +1 -1
  8. package/dist/interpretation/siLanguage.js +1 -1
  9. package/dist/meeting/in-meeting-actions.js +2 -0
  10. package/dist/meeting/in-meeting-actions.js.map +1 -1
  11. package/dist/meeting/index.js +155 -103
  12. package/dist/meeting/index.js.map +1 -1
  13. package/dist/meeting-info/meeting-info-v2.js +3 -0
  14. package/dist/meeting-info/meeting-info-v2.js.map +1 -1
  15. package/dist/meeting-info/utilv2.js +14 -29
  16. package/dist/meeting-info/utilv2.js.map +1 -1
  17. package/dist/meetings/collection.js +17 -0
  18. package/dist/meetings/collection.js.map +1 -1
  19. package/dist/meetings/index.js +13 -0
  20. package/dist/meetings/index.js.map +1 -1
  21. package/dist/metrics/constants.js +1 -0
  22. package/dist/metrics/constants.js.map +1 -1
  23. package/dist/reconnection-manager/index.js +26 -26
  24. package/dist/reconnection-manager/index.js.map +1 -1
  25. package/dist/rtcMetrics/index.js +25 -0
  26. package/dist/rtcMetrics/index.js.map +1 -1
  27. package/dist/statsAnalyzer/index.js +21 -1
  28. package/dist/statsAnalyzer/index.js.map +1 -1
  29. package/dist/statsAnalyzer/mqaUtil.js +16 -16
  30. package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
  31. package/dist/webinar/index.js +1 -1
  32. package/package.json +21 -22
  33. package/src/constants.ts +10 -4
  34. package/src/controls-options-manager/enums.ts +2 -0
  35. package/src/meeting/in-meeting-actions.ts +4 -0
  36. package/src/meeting/index.ts +140 -92
  37. package/src/meeting-info/meeting-info-v2.ts +4 -0
  38. package/src/meeting-info/utilv2.ts +6 -19
  39. package/src/meetings/collection.ts +13 -0
  40. package/src/meetings/index.ts +11 -0
  41. package/src/metrics/constants.ts +1 -0
  42. package/src/reconnection-manager/index.ts +62 -66
  43. package/src/rtcMetrics/index.ts +24 -0
  44. package/src/statsAnalyzer/index.ts +30 -1
  45. package/src/statsAnalyzer/mqaUtil.ts +17 -14
  46. package/test/unit/spec/meeting/in-meeting-actions.ts +2 -0
  47. package/test/unit/spec/meeting/index.js +1058 -158
  48. package/test/unit/spec/meeting/muteState.js +2 -1
  49. package/test/unit/spec/meeting-info/meetinginfov2.js +28 -0
  50. package/test/unit/spec/meetings/collection.js +12 -0
  51. package/test/unit/spec/meetings/index.js +306 -118
  52. package/test/unit/spec/member/util.js +0 -31
  53. package/test/unit/spec/reconnection-manager/index.js +25 -10
  54. package/test/unit/spec/rtcMetrics/index.ts +20 -0
  55. package/test/unit/spec/stats-analyzer/index.js +12 -2
@@ -1,3 +1,5 @@
1
+ /* eslint-disable class-methods-use-this */
2
+ import {CallDiagnosticUtils} from '@webex/internal-plugin-metrics';
1
3
  import RTC_METRICS from './constants';
2
4
 
3
5
  /**
@@ -55,6 +57,9 @@ export default class RtcMetrics {
55
57
  */
56
58
  addMetrics(data) {
57
59
  if (data.payload.length) {
60
+ if (data.name === 'stats-report') {
61
+ data.payload = data.payload.map(this.anonymizeIp);
62
+ }
58
63
  this.metricsQueue.push(data);
59
64
  }
60
65
  }
@@ -69,6 +74,25 @@ export default class RtcMetrics {
69
74
  clearInterval(this.intervalId);
70
75
  }
71
76
 
77
+ /**
78
+ * Anonymize IP addresses.
79
+ *
80
+ * @param {array} stats - An RTCStatsReport organized into an array of strings.
81
+ * @returns {string}
82
+ */
83
+ anonymizeIp(stats: string): string {
84
+ const data = JSON.parse(stats);
85
+ // on local and remote candidates, anonymize the last 4 bits.
86
+ if (data.type === 'local-candidate' || data.type === 'remote-candidate') {
87
+ data.ip = CallDiagnosticUtils.anonymizeIPAddress(data.ip) || undefined;
88
+ data.address = CallDiagnosticUtils.anonymizeIPAddress(data.address) || undefined;
89
+ data.relatedAddress =
90
+ CallDiagnosticUtils.anonymizeIPAddress(data.relatedAddress) || undefined;
91
+ }
92
+
93
+ return JSON.stringify(data);
94
+ }
95
+
72
96
  /**
73
97
  * Send metrics to the metrics service.
74
98
  *
@@ -103,7 +103,7 @@ export class StatsAnalyzer extends EventsScope {
103
103
  this.networkQualityMonitor = networkQualityMonitor;
104
104
  this.correlationId = config.correlationId;
105
105
  this.mqaSentCount = -1;
106
- this.lastMqaDataSent = {};
106
+ this.lastMqaDataSent = {resolutions: {}};
107
107
  this.lastEmittedStartStopEvent = {};
108
108
  this.receiveSlotCallback = receiveSlotCallback;
109
109
  this.successfulCandidatePair = {};
@@ -152,6 +152,21 @@ export class StatsAnalyzer extends EventsScope {
152
152
  const newMqa = cloneDeep(emptyMqaInterval);
153
153
 
154
154
  Object.keys(this.statsResults).forEach((mediaType) => {
155
+ if (!this.lastMqaDataSent[mediaType]) {
156
+ this.lastMqaDataSent[mediaType] = {};
157
+ this.lastMqaDataSent.resolutions[mediaType] = {};
158
+ }
159
+
160
+ if (!this.lastMqaDataSent[mediaType].send && mediaType.includes('-send')) {
161
+ this.lastMqaDataSent[mediaType].send = {};
162
+ this.lastMqaDataSent.resolutions[mediaType].send = {};
163
+ }
164
+
165
+ if (!this.lastMqaDataSent[mediaType].recv && mediaType.includes('-recv')) {
166
+ this.lastMqaDataSent[mediaType].recv = {};
167
+ this.lastMqaDataSent.resolutions[mediaType].recv = {};
168
+ }
169
+
155
170
  if (mediaType.includes('audio-send') || mediaType.includes('audio-share-send')) {
156
171
  const audioSender = cloneDeep(emptyAudioTransmit);
157
172
 
@@ -162,6 +177,8 @@ export class StatsAnalyzer extends EventsScope {
162
177
  mediaType,
163
178
  });
164
179
  newMqa.audioTransmit.push(audioSender);
180
+
181
+ this.lastMqaDataSent[mediaType].send = cloneDeep(this.statsResults[mediaType].send);
165
182
  } else if (mediaType.includes('audio-recv') || mediaType.includes('audio-share-recv')) {
166
183
  const audioReceiver = cloneDeep(emptyAudioReceive);
167
184
 
@@ -172,6 +189,8 @@ export class StatsAnalyzer extends EventsScope {
172
189
  mediaType,
173
190
  });
174
191
  newMqa.audioReceive.push(audioReceiver);
192
+
193
+ this.lastMqaDataSent[mediaType].recv = cloneDeep(this.statsResults[mediaType].recv);
175
194
  } else if (mediaType.includes('video-send') || mediaType.includes('video-share-send')) {
176
195
  const videoSender = cloneDeep(emptyVideoTransmit);
177
196
 
@@ -182,6 +201,11 @@ export class StatsAnalyzer extends EventsScope {
182
201
  mediaType,
183
202
  });
184
203
  newMqa.videoTransmit.push(videoSender);
204
+
205
+ this.lastMqaDataSent[mediaType].send = cloneDeep(this.statsResults[mediaType].send);
206
+ this.lastMqaDataSent.resolutions[mediaType].send = cloneDeep(
207
+ this.statsResults.resolutions[mediaType].send
208
+ );
185
209
  } else if (mediaType.includes('video-recv') || mediaType.includes('video-share-recv')) {
186
210
  const videoReceiver = cloneDeep(emptyVideoReceive);
187
211
 
@@ -192,6 +216,11 @@ export class StatsAnalyzer extends EventsScope {
192
216
  mediaType,
193
217
  });
194
218
  newMqa.videoReceive.push(videoReceiver);
219
+
220
+ this.lastMqaDataSent[mediaType].recv = cloneDeep(this.statsResults[mediaType].recv);
221
+ this.lastMqaDataSent.resolutions[mediaType].recv = cloneDeep(
222
+ this.statsResults.resolutions[mediaType].recv
223
+ );
195
224
  }
196
225
  });
197
226
 
@@ -134,9 +134,12 @@ export const getVideoReceiverMqa = ({videoReceiver, statsResults, lastMqaDataSen
134
134
  const lastPacketsReceived = lastMqaDataSent[mediaType]?.[sendrecvType].totalPacketsReceived || 0;
135
135
  const lastPacketsLost = lastMqaDataSent[mediaType]?.[sendrecvType].totalPacketsLost || 0;
136
136
  const lastBytesReceived = lastMqaDataSent[mediaType]?.[sendrecvType].totalBytesReceived || 0;
137
- const lastFramesReceived = lastMqaDataSent[mediaType]?.[sendrecvType].framesReceived || 0;
138
- const lastFramesDecoded = lastMqaDataSent[mediaType]?.[sendrecvType].framesDecoded || 0;
139
- const lastFramesDropped = lastMqaDataSent[mediaType]?.[sendrecvType].framesDropped || 0;
137
+ const lastFramesReceived =
138
+ lastMqaDataSent.resolutions[mediaType]?.[sendrecvType].framesReceived || 0;
139
+ const lastFramesDecoded =
140
+ lastMqaDataSent.resolutions[mediaType]?.[sendrecvType].framesDecoded || 0;
141
+ const lastFramesDropped =
142
+ lastMqaDataSent.resolutions[mediaType]?.[sendrecvType].framesDropped || 0;
140
143
  const lastKeyFramesDecoded = lastMqaDataSent[mediaType]?.[sendrecvType].keyFramesDecoded || 0;
141
144
  const lastPliCount = lastMqaDataSent[mediaType]?.[sendrecvType].totalPliCount || 0;
142
145
 
@@ -190,12 +193,12 @@ export const getVideoReceiverMqa = ({videoReceiver, statsResults, lastMqaDataSen
190
193
  const totalFrameDecodedInaMin =
191
194
  statsResults.resolutions[mediaType][sendrecvType].framesDecoded - lastFramesDecoded;
192
195
 
193
- videoReceiver.streams[0].common.receivedFrameRate = totalFrameReceivedInaMin
194
- ? (totalFrameReceivedInaMin * 100) / 60
195
- : 0;
196
- videoReceiver.streams[0].common.renderedFrameRate = totalFrameDecodedInaMin
197
- ? (totalFrameDecodedInaMin * 100) / 60
198
- : 0;
196
+ videoReceiver.streams[0].common.receivedFrameRate = Math.round(
197
+ totalFrameReceivedInaMin ? totalFrameReceivedInaMin / 60 : 0
198
+ );
199
+ videoReceiver.streams[0].common.renderedFrameRate = Math.round(
200
+ totalFrameDecodedInaMin ? totalFrameDecodedInaMin / 60 : 0
201
+ );
199
202
 
200
203
  videoReceiver.streams[0].common.framesDropped =
201
204
  statsResults.resolutions[mediaType][sendrecvType].framesDropped - lastFramesDropped;
@@ -220,9 +223,9 @@ export const getVideoSenderMqa = ({videoSender, statsResults, lastMqaDataSent, m
220
223
  lastMqaDataSent[mediaType]?.[sendrecvType].totalPacketsLostOnReceiver || 0;
221
224
  const lastBytesSent = lastMqaDataSent[mediaType]?.[sendrecvType].totalBytesSent || 0;
222
225
  const lastKeyFramesEncoded =
223
- lastMqaDataSent[mediaType]?.[sendrecvType].totalKeyFramesEncoded || 0;
226
+ lastMqaDataSent.resolutions[mediaType]?.[sendrecvType].totalKeyFramesEncoded || 0;
224
227
  const lastFirCount = lastMqaDataSent[mediaType]?.[sendrecvType].totalFirCount || 0;
225
- const lastFramesSent = lastMqaDataSent[mediaType]?.[sendrecvType].framesSent || 0;
228
+ const lastFramesSent = lastMqaDataSent.resolutions[mediaType]?.[sendrecvType].framesSent || 0;
226
229
  const {csi} = statsResults[mediaType];
227
230
  if (csi && !videoSender.streams[0].common.csi.includes(csi)) {
228
231
  videoSender.streams[0].common.csi.push(csi);
@@ -280,9 +283,9 @@ export const getVideoSenderMqa = ({videoSender, statsResults, lastMqaDataSent, m
280
283
  const totalFrameSentInaMin =
281
284
  statsResults.resolutions[mediaType][sendrecvType].framesSent - (lastFramesSent || 0);
282
285
 
283
- videoSender.streams[0].common.transmittedFrameRate = totalFrameSentInaMin
284
- ? (totalFrameSentInaMin * 100) / 60
285
- : 0;
286
+ videoSender.streams[0].common.transmittedFrameRate = Math.round(
287
+ totalFrameSentInaMin ? totalFrameSentInaMin / 60 : 0
288
+ );
286
289
  videoSender.streams[0].transmittedHeight =
287
290
  statsResults.resolutions[mediaType][sendrecvType].height || 0;
288
291
  videoSender.streams[0].transmittedWidth =
@@ -67,6 +67,7 @@ describe('plugin-meetings', () => {
67
67
  canShareDesktop: null,
68
68
  canShareContent: null,
69
69
  canTransferFile: null,
70
+ canChat: null,
70
71
  canDoVideo: null,
71
72
  canAnnotate: null,
72
73
  canUseVoip: null,
@@ -145,6 +146,7 @@ describe('plugin-meetings', () => {
145
146
  'canShareDesktop',
146
147
  'canShareContent',
147
148
  'canTransferFile',
149
+ 'canChat',
148
150
  'canDoVideo',
149
151
  'canAnnotate',
150
152
  'canUseVoip',