@webex/plugin-meetings 3.0.0-beta.39 → 3.0.0-beta.391
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/README.md +58 -8
- package/dist/annotation/annotation.types.js +7 -0
- package/dist/annotation/annotation.types.js.map +1 -0
- package/dist/annotation/constants.js +49 -0
- package/dist/annotation/constants.js.map +1 -0
- package/dist/annotation/index.js +342 -0
- package/dist/annotation/index.js.map +1 -0
- package/dist/breakouts/breakout.js +94 -15
- package/dist/breakouts/breakout.js.map +1 -1
- package/dist/breakouts/events.js +45 -0
- package/dist/breakouts/events.js.map +1 -0
- package/dist/breakouts/index.js +671 -81
- package/dist/breakouts/index.js.map +1 -1
- package/dist/breakouts/utils.js +45 -1
- package/dist/breakouts/utils.js.map +1 -1
- package/dist/common/errors/no-meeting-info.js +51 -0
- package/dist/common/errors/no-meeting-info.js.map +1 -0
- package/dist/common/errors/reclaim-host-role-errors.js +158 -0
- package/dist/common/errors/reclaim-host-role-errors.js.map +1 -0
- package/dist/common/errors/webex-errors.js +48 -7
- package/dist/common/errors/webex-errors.js.map +1 -1
- package/dist/common/logs/logger-proxy.js +1 -1
- package/dist/common/logs/logger-proxy.js.map +1 -1
- package/dist/common/logs/request.js +5 -1
- package/dist/common/logs/request.js.map +1 -1
- package/dist/common/queue.js +24 -9
- package/dist/common/queue.js.map +1 -1
- package/dist/config.js +5 -10
- package/dist/config.js.map +1 -1
- package/dist/constants.js +242 -33
- package/dist/constants.js.map +1 -1
- package/dist/controls-options-manager/enums.js +14 -2
- package/dist/controls-options-manager/enums.js.map +1 -1
- package/dist/controls-options-manager/index.js +109 -15
- package/dist/controls-options-manager/index.js.map +1 -1
- package/dist/controls-options-manager/types.js +7 -0
- package/dist/controls-options-manager/types.js.map +1 -0
- package/dist/controls-options-manager/util.js +309 -18
- package/dist/controls-options-manager/util.js.map +1 -1
- package/dist/index.js +110 -2
- package/dist/index.js.map +1 -1
- package/dist/interceptors/index.js +15 -0
- package/dist/interceptors/index.js.map +1 -0
- package/dist/interceptors/locusRetry.js +93 -0
- package/dist/interceptors/locusRetry.js.map +1 -0
- package/dist/interpretation/collection.js +23 -0
- package/dist/interpretation/collection.js.map +1 -0
- package/dist/interpretation/index.js +380 -0
- package/dist/interpretation/index.js.map +1 -0
- package/dist/interpretation/siLanguage.js +25 -0
- package/dist/interpretation/siLanguage.js.map +1 -0
- package/dist/locus-info/controlsUtils.js +91 -2
- package/dist/locus-info/controlsUtils.js.map +1 -1
- package/dist/locus-info/index.js +386 -62
- package/dist/locus-info/index.js.map +1 -1
- package/dist/locus-info/infoUtils.js +7 -1
- package/dist/locus-info/infoUtils.js.map +1 -1
- package/dist/locus-info/mediaSharesUtils.js +71 -1
- package/dist/locus-info/mediaSharesUtils.js.map +1 -1
- package/dist/locus-info/parser.js +249 -72
- package/dist/locus-info/parser.js.map +1 -1
- package/dist/locus-info/selfUtils.js +89 -14
- package/dist/locus-info/selfUtils.js.map +1 -1
- package/dist/media/index.js +65 -102
- package/dist/media/index.js.map +1 -1
- package/dist/media/properties.js +73 -124
- package/dist/media/properties.js.map +1 -1
- package/dist/mediaQualityMetrics/config.js +135 -330
- package/dist/mediaQualityMetrics/config.js.map +1 -1
- package/dist/meeting/in-meeting-actions.js +86 -2
- package/dist/meeting/in-meeting-actions.js.map +1 -1
- package/dist/meeting/index.js +4075 -2827
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/locusMediaRequest.js +292 -0
- package/dist/meeting/locusMediaRequest.js.map +1 -0
- package/dist/meeting/muteState.js +224 -136
- package/dist/meeting/muteState.js.map +1 -1
- package/dist/meeting/request.js +177 -152
- package/dist/meeting/request.js.map +1 -1
- package/dist/meeting/util.js +672 -417
- package/dist/meeting/util.js.map +1 -1
- package/dist/meeting-info/index.js +73 -7
- package/dist/meeting-info/index.js.map +1 -1
- package/dist/meeting-info/meeting-info-v2.js +192 -51
- package/dist/meeting-info/meeting-info-v2.js.map +1 -1
- package/dist/meeting-info/util.js +1 -1
- package/dist/meeting-info/util.js.map +1 -1
- package/dist/meeting-info/utilv2.js +36 -36
- package/dist/meeting-info/utilv2.js.map +1 -1
- package/dist/meetings/collection.js +39 -0
- package/dist/meetings/collection.js.map +1 -1
- package/dist/meetings/index.js +484 -119
- package/dist/meetings/index.js.map +1 -1
- package/dist/meetings/meetings.types.js +7 -0
- package/dist/meetings/meetings.types.js.map +1 -0
- package/dist/meetings/request.js +2 -0
- package/dist/meetings/request.js.map +1 -1
- package/dist/meetings/util.js +73 -7
- package/dist/meetings/util.js.map +1 -1
- package/dist/member/index.js +58 -0
- package/dist/member/index.js.map +1 -1
- package/dist/member/types.js +25 -0
- package/dist/member/types.js.map +1 -0
- package/dist/member/util.js +132 -25
- package/dist/member/util.js.map +1 -1
- package/dist/members/collection.js +10 -0
- package/dist/members/collection.js.map +1 -1
- package/dist/members/index.js +102 -6
- package/dist/members/index.js.map +1 -1
- package/dist/members/request.js +106 -38
- package/dist/members/request.js.map +1 -1
- package/dist/members/types.js +15 -0
- package/dist/members/types.js.map +1 -0
- package/dist/members/util.js +326 -232
- package/dist/members/util.js.map +1 -1
- package/dist/metrics/constants.js +18 -1
- package/dist/metrics/constants.js.map +1 -1
- package/dist/metrics/index.js +1 -446
- package/dist/metrics/index.js.map +1 -1
- package/dist/multistream/mediaRequestManager.js +223 -32
- package/dist/multistream/mediaRequestManager.js.map +1 -1
- package/dist/multistream/receiveSlot.js +10 -0
- package/dist/multistream/receiveSlot.js.map +1 -1
- package/dist/multistream/receiveSlotManager.js +39 -36
- package/dist/multistream/receiveSlotManager.js.map +1 -1
- package/dist/multistream/remoteMedia.js +3 -1
- package/dist/multistream/remoteMedia.js.map +1 -1
- package/dist/multistream/remoteMediaGroup.js +76 -5
- package/dist/multistream/remoteMediaGroup.js.map +1 -1
- package/dist/multistream/remoteMediaManager.js +366 -104
- package/dist/multistream/remoteMediaManager.js.map +1 -1
- package/dist/multistream/sendSlotManager.js +255 -0
- package/dist/multistream/sendSlotManager.js.map +1 -0
- package/dist/reachability/clusterReachability.js +356 -0
- package/dist/reachability/clusterReachability.js.map +1 -0
- package/dist/reachability/index.js +263 -390
- package/dist/reachability/index.js.map +1 -1
- package/dist/reachability/request.js +6 -4
- package/dist/reachability/request.js.map +1 -1
- package/dist/reachability/util.js +29 -0
- package/dist/reachability/util.js.map +1 -0
- package/dist/reconnection-manager/index.js +266 -202
- package/dist/reconnection-manager/index.js.map +1 -1
- package/dist/recording-controller/index.js +21 -2
- package/dist/recording-controller/index.js.map +1 -1
- package/dist/recording-controller/util.js +9 -8
- package/dist/recording-controller/util.js.map +1 -1
- package/dist/roap/index.js +51 -28
- package/dist/roap/index.js.map +1 -1
- package/dist/roap/request.js +48 -64
- package/dist/roap/request.js.map +1 -1
- package/dist/roap/turnDiscovery.js +220 -70
- package/dist/roap/turnDiscovery.js.map +1 -1
- package/dist/rtcMetrics/constants.js +12 -0
- package/dist/rtcMetrics/constants.js.map +1 -0
- package/dist/rtcMetrics/index.js +179 -0
- package/dist/rtcMetrics/index.js.map +1 -0
- package/dist/statsAnalyzer/index.js +357 -295
- package/dist/statsAnalyzer/index.js.map +1 -1
- package/dist/statsAnalyzer/mqaUtil.js +296 -156
- package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
- package/dist/types/annotation/annotation.types.d.ts +42 -0
- package/dist/types/annotation/constants.d.ts +31 -0
- package/dist/types/annotation/index.d.ts +117 -0
- package/dist/types/breakouts/events.d.ts +8 -0
- package/dist/types/breakouts/utils.d.ts +14 -0
- package/dist/types/common/errors/no-meeting-info.d.ts +14 -0
- package/dist/types/common/errors/reclaim-host-role-errors.d.ts +60 -0
- package/dist/types/common/errors/webex-errors.d.ts +25 -1
- package/dist/types/common/logs/request.d.ts +2 -0
- package/dist/types/common/queue.d.ts +9 -7
- package/dist/types/config.d.ts +2 -7
- package/dist/types/constants.d.ts +203 -31
- package/dist/types/controls-options-manager/enums.d.ts +11 -1
- package/dist/types/controls-options-manager/index.d.ts +17 -1
- package/dist/types/controls-options-manager/types.d.ts +43 -0
- package/dist/types/controls-options-manager/util.d.ts +1 -7
- package/dist/types/index.d.ts +6 -5
- package/dist/types/interceptors/index.d.ts +2 -0
- package/dist/types/interceptors/locusRetry.d.ts +27 -0
- package/dist/types/interpretation/collection.d.ts +5 -0
- package/dist/types/interpretation/index.d.ts +5 -0
- package/dist/types/interpretation/siLanguage.d.ts +5 -0
- package/dist/types/locus-info/index.d.ts +57 -4
- package/dist/types/locus-info/parser.d.ts +66 -6
- package/dist/types/media/index.d.ts +2 -0
- package/dist/types/media/properties.d.ts +34 -49
- package/dist/types/mediaQualityMetrics/config.d.ts +99 -223
- package/dist/types/meeting/in-meeting-actions.d.ts +86 -2
- package/dist/types/meeting/index.d.ts +567 -496
- package/dist/types/meeting/locusMediaRequest.d.ts +74 -0
- package/dist/types/meeting/muteState.d.ts +93 -25
- package/dist/types/meeting/request.d.ts +64 -43
- package/dist/types/meeting/util.d.ts +117 -1
- package/dist/types/meeting-info/index.d.ts +13 -1
- package/dist/types/meeting-info/meeting-info-v2.d.ts +31 -1
- package/dist/types/meetings/collection.d.ts +17 -0
- package/dist/types/meetings/index.d.ts +113 -21
- package/dist/types/meetings/meetings.types.d.ts +4 -0
- package/dist/types/member/index.d.ts +14 -0
- package/dist/types/member/types.d.ts +32 -0
- package/dist/types/members/collection.d.ts +5 -0
- package/dist/types/members/index.d.ts +35 -2
- package/dist/types/members/request.d.ts +73 -9
- package/dist/types/members/types.d.ts +25 -0
- package/dist/types/members/util.d.ts +214 -1
- package/dist/types/metrics/constants.d.ts +17 -0
- package/dist/types/metrics/index.d.ts +4 -111
- package/dist/types/multistream/mediaRequestManager.d.ts +72 -3
- package/dist/types/multistream/receiveSlot.d.ts +7 -3
- package/dist/types/multistream/receiveSlotManager.d.ts +14 -4
- package/dist/types/multistream/remoteMedia.d.ts +3 -31
- package/dist/types/multistream/remoteMediaGroup.d.ts +2 -9
- package/dist/types/multistream/remoteMediaManager.d.ts +62 -2
- package/dist/types/multistream/sendSlotManager.d.ts +70 -0
- package/dist/types/reachability/clusterReachability.d.ts +109 -0
- package/dist/types/reachability/index.d.ts +60 -95
- package/dist/types/reachability/request.d.ts +3 -1
- package/dist/types/reachability/util.d.ts +8 -0
- package/dist/types/reconnection-manager/index.d.ts +19 -0
- package/dist/types/recording-controller/index.d.ts +15 -1
- package/dist/types/recording-controller/util.d.ts +5 -4
- package/dist/types/roap/index.d.ts +2 -1
- package/dist/types/roap/request.d.ts +9 -8
- package/dist/types/roap/turnDiscovery.d.ts +39 -5
- package/dist/types/rtcMetrics/constants.d.ts +4 -0
- package/dist/types/rtcMetrics/index.d.ts +61 -0
- package/dist/types/statsAnalyzer/index.d.ts +34 -12
- package/dist/types/statsAnalyzer/mqaUtil.d.ts +28 -4
- package/dist/types/webinar/collection.d.ts +16 -0
- package/dist/types/webinar/index.d.ts +5 -0
- package/dist/webinar/collection.js +44 -0
- package/dist/webinar/collection.js.map +1 -0
- package/dist/webinar/index.js +69 -0
- package/dist/webinar/index.js.map +1 -0
- package/package.json +22 -19
- package/src/annotation/annotation.types.ts +50 -0
- package/src/annotation/constants.ts +36 -0
- package/src/annotation/index.ts +328 -0
- package/src/breakouts/README.md +35 -11
- package/src/breakouts/breakout.ts +67 -9
- package/src/breakouts/events.ts +56 -0
- package/src/breakouts/index.ts +558 -59
- package/src/breakouts/utils.ts +42 -0
- package/src/common/errors/no-meeting-info.ts +24 -0
- package/src/common/errors/reclaim-host-role-errors.ts +134 -0
- package/src/common/errors/webex-errors.ts +44 -2
- package/src/common/logs/logger-proxy.ts +1 -1
- package/src/common/logs/request.ts +5 -1
- package/src/common/queue.ts +22 -8
- package/src/config.ts +4 -9
- package/src/constants.ts +229 -21
- package/src/controls-options-manager/enums.ts +12 -0
- package/src/controls-options-manager/index.ts +116 -21
- package/src/controls-options-manager/types.ts +59 -0
- package/src/controls-options-manager/util.ts +294 -14
- package/src/index.ts +44 -0
- package/src/interceptors/index.ts +3 -0
- package/src/interceptors/locusRetry.ts +67 -0
- package/src/interpretation/README.md +60 -0
- package/src/interpretation/collection.ts +19 -0
- package/src/interpretation/index.ts +349 -0
- package/src/interpretation/siLanguage.ts +18 -0
- package/src/locus-info/controlsUtils.ts +108 -0
- package/src/locus-info/index.ts +417 -59
- package/src/locus-info/infoUtils.ts +10 -2
- package/src/locus-info/mediaSharesUtils.ts +80 -0
- package/src/locus-info/parser.ts +258 -47
- package/src/locus-info/selfUtils.ts +81 -5
- package/src/media/index.ts +100 -108
- package/src/media/properties.ts +88 -117
- package/src/mediaQualityMetrics/config.ts +103 -238
- package/src/meeting/in-meeting-actions.ts +171 -3
- package/src/meeting/index.ts +3411 -2435
- package/src/meeting/locusMediaRequest.ts +313 -0
- package/src/meeting/muteState.ts +223 -136
- package/src/meeting/request.ts +155 -120
- package/src/meeting/util.ts +685 -395
- package/src/meeting-info/index.ts +81 -8
- package/src/meeting-info/meeting-info-v2.ts +170 -14
- package/src/meeting-info/util.ts +1 -1
- package/src/meeting-info/utilv2.ts +23 -23
- package/src/meetings/collection.ts +33 -0
- package/src/meetings/index.ts +507 -127
- package/src/meetings/meetings.types.ts +12 -0
- package/src/meetings/request.ts +2 -0
- package/src/meetings/util.ts +81 -12
- package/src/member/index.ts +58 -0
- package/src/member/types.ts +38 -0
- package/src/member/util.ts +141 -25
- package/src/members/collection.ts +8 -0
- package/src/members/index.ts +134 -8
- package/src/members/request.ts +97 -17
- package/src/members/types.ts +29 -0
- package/src/members/util.ts +333 -240
- package/src/metrics/constants.ts +17 -0
- package/src/metrics/index.ts +1 -469
- package/src/multistream/mediaRequestManager.ts +271 -56
- package/src/multistream/receiveSlot.ts +11 -4
- package/src/multistream/receiveSlotManager.ts +34 -24
- package/src/multistream/remoteMedia.ts +5 -3
- package/src/multistream/remoteMediaGroup.ts +78 -0
- package/src/multistream/remoteMediaManager.ts +248 -44
- package/src/multistream/sendSlotManager.ts +199 -0
- package/src/reachability/clusterReachability.ts +320 -0
- package/src/reachability/index.ts +229 -346
- package/src/reachability/request.ts +8 -4
- package/src/reachability/util.ts +24 -0
- package/src/reconnection-manager/index.ts +128 -97
- package/src/recording-controller/index.ts +20 -3
- package/src/recording-controller/util.ts +26 -9
- package/src/roap/index.ts +52 -23
- package/src/roap/request.ts +48 -67
- package/src/roap/turnDiscovery.ts +147 -49
- package/src/rtcMetrics/constants.ts +3 -0
- package/src/rtcMetrics/index.ts +166 -0
- package/src/statsAnalyzer/index.ts +457 -416
- package/src/statsAnalyzer/mqaUtil.ts +317 -170
- package/src/webinar/collection.ts +31 -0
- package/src/webinar/index.ts +62 -0
- package/test/integration/spec/converged-space-meetings.js +60 -3
- package/test/integration/spec/journey.js +320 -261
- package/test/integration/spec/space-meeting.js +76 -3
- package/test/unit/spec/annotation/index.ts +418 -0
- package/test/unit/spec/breakouts/breakout.ts +118 -28
- package/test/unit/spec/breakouts/events.ts +89 -0
- package/test/unit/spec/breakouts/index.ts +1349 -114
- package/test/unit/spec/breakouts/utils.js +52 -1
- package/test/unit/spec/common/queue.js +31 -2
- package/test/unit/spec/controls-options-manager/index.js +163 -0
- package/test/unit/spec/controls-options-manager/util.js +576 -60
- package/test/unit/spec/fixture/locus.js +1 -0
- package/test/unit/spec/interceptors/locusRetry.ts +131 -0
- package/test/unit/spec/interpretation/collection.ts +15 -0
- package/test/unit/spec/interpretation/index.ts +625 -0
- package/test/unit/spec/interpretation/siLanguage.ts +28 -0
- package/test/unit/spec/locus-info/controlsUtils.js +316 -43
- package/test/unit/spec/locus-info/index.js +1363 -37
- package/test/unit/spec/locus-info/infoUtils.js +37 -15
- package/test/unit/spec/locus-info/lib/SeqCmp.json +16 -0
- package/test/unit/spec/locus-info/mediaSharesUtils.ts +41 -0
- package/test/unit/spec/locus-info/parser.js +116 -35
- package/test/unit/spec/locus-info/selfConstant.js +27 -4
- package/test/unit/spec/locus-info/selfUtils.js +208 -17
- package/test/unit/spec/media/index.ts +173 -81
- package/test/unit/spec/media/properties.ts +2 -2
- package/test/unit/spec/meeting/in-meeting-actions.ts +85 -3
- package/test/unit/spec/meeting/index.js +6821 -2172
- package/test/unit/spec/meeting/locusMediaRequest.ts +442 -0
- package/test/unit/spec/meeting/muteState.js +402 -212
- package/test/unit/spec/meeting/request.js +473 -54
- package/test/unit/spec/meeting/utils.js +773 -67
- package/test/unit/spec/meeting-info/index.js +300 -0
- package/test/unit/spec/meeting-info/meetinginfov2.js +526 -5
- package/test/unit/spec/meeting-info/utilv2.js +21 -0
- package/test/unit/spec/meetings/collection.js +26 -0
- package/test/unit/spec/meetings/index.js +1415 -213
- package/test/unit/spec/meetings/utils.js +229 -2
- package/test/unit/spec/member/index.js +61 -6
- package/test/unit/spec/member/util.js +510 -34
- package/test/unit/spec/members/index.js +432 -1
- package/test/unit/spec/members/request.js +206 -27
- package/test/unit/spec/members/utils.js +210 -0
- package/test/unit/spec/metrics/index.js +1 -50
- package/test/unit/spec/multistream/mediaRequestManager.ts +781 -114
- package/test/unit/spec/multistream/receiveSlot.ts +9 -1
- package/test/unit/spec/multistream/receiveSlotManager.ts +32 -30
- package/test/unit/spec/multistream/remoteMedia.ts +2 -0
- package/test/unit/spec/multistream/remoteMediaGroup.ts +345 -0
- package/test/unit/spec/multistream/remoteMediaManager.ts +525 -0
- package/test/unit/spec/multistream/sendSlotManager.ts +274 -0
- package/test/unit/spec/reachability/clusterReachability.ts +279 -0
- package/test/unit/spec/reachability/index.ts +551 -14
- package/test/unit/spec/reachability/request.js +3 -1
- package/test/unit/spec/reachability/util.ts +40 -0
- package/test/unit/spec/reconnection-manager/index.js +171 -11
- package/test/unit/spec/recording-controller/index.js +294 -218
- package/test/unit/spec/recording-controller/util.js +223 -96
- package/test/unit/spec/roap/index.ts +180 -83
- package/test/unit/spec/roap/request.ts +100 -62
- package/test/unit/spec/roap/turnDiscovery.ts +388 -96
- package/test/unit/spec/rtcMetrics/index.ts +122 -0
- package/test/unit/spec/stats-analyzer/index.js +1252 -12
- package/test/unit/spec/webinar/collection.ts +13 -0
- package/test/unit/spec/webinar/index.ts +60 -0
- package/test/utils/integrationTestUtils.js +46 -0
- package/test/utils/testUtils.js +0 -57
- package/test/utils/webex-test-users.js +12 -4
- package/dist/metrics/config.js +0 -289
- package/dist/metrics/config.js.map +0 -1
- package/dist/types/metrics/config.d.ts +0 -169
- package/src/index.js +0 -18
- package/src/metrics/config.ts +0 -485
package/src/roap/request.ts
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
/* global window */
|
|
2
1
|
// @ts-ignore
|
|
3
2
|
import {StatelessWebexPlugin} from '@webex/webex-core';
|
|
4
3
|
|
|
5
4
|
import LoggerProxy from '../common/logs/logger-proxy';
|
|
6
|
-
import {
|
|
7
|
-
import
|
|
8
|
-
import {eventType} from '../metrics/config';
|
|
5
|
+
import {IP_VERSION, REACHABILITY} from '../constants';
|
|
6
|
+
import {LocusMediaRequest} from '../meeting/locusMediaRequest';
|
|
9
7
|
|
|
10
8
|
/**
|
|
11
9
|
* @class RoapRequest
|
|
@@ -20,23 +18,10 @@ export default class RoapRequest extends StatelessWebexPlugin {
|
|
|
20
18
|
let joinCookie;
|
|
21
19
|
|
|
22
20
|
// @ts-ignore
|
|
23
|
-
const
|
|
24
|
-
.get(REACHABILITY.namespace, REACHABILITY.localStorageResult)
|
|
25
|
-
.catch(() => {});
|
|
26
|
-
|
|
27
|
-
if (reachabilityData) {
|
|
28
|
-
try {
|
|
29
|
-
const reachabilityResult = JSON.parse(reachabilityData);
|
|
21
|
+
const reachabilityResult = await this.webex.meetings.reachability.getReachabilityResults();
|
|
30
22
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
localSdp.reachability = reachabilityResult;
|
|
34
|
-
}
|
|
35
|
-
} catch (e) {
|
|
36
|
-
LoggerProxy.logger.error(
|
|
37
|
-
`Roap:request#attachReachabilityData --> Error in parsing reachability data: ${e}`
|
|
38
|
-
);
|
|
39
|
-
}
|
|
23
|
+
if (reachabilityResult && Object.keys(reachabilityResult).length) {
|
|
24
|
+
localSdp.reachability = reachabilityResult;
|
|
40
25
|
}
|
|
41
26
|
|
|
42
27
|
// @ts-ignore
|
|
@@ -64,72 +49,65 @@ export default class RoapRequest extends StatelessWebexPlugin {
|
|
|
64
49
|
* @param {String} options.locusSelfUrl
|
|
65
50
|
* @param {String} options.mediaId
|
|
66
51
|
* @param {String} options.correlationId
|
|
67
|
-
* @param {Boolean} options.audioMuted
|
|
68
|
-
* @param {Boolean} options.videoMuted
|
|
69
52
|
* @param {String} options.meetingId
|
|
70
|
-
* @param {
|
|
53
|
+
* @param {IP_VERSION} options.ipVersion only required for offers
|
|
71
54
|
* @returns {Promise} returns the response/failure of the request
|
|
72
55
|
*/
|
|
73
56
|
async sendRoap(options: {
|
|
74
57
|
roapMessage: any;
|
|
75
58
|
locusSelfUrl: string;
|
|
76
59
|
mediaId: string;
|
|
77
|
-
correlationId: string;
|
|
78
|
-
audioMuted: boolean;
|
|
79
|
-
videoMuted: boolean;
|
|
80
60
|
meetingId: string;
|
|
81
|
-
|
|
61
|
+
ipVersion?: IP_VERSION;
|
|
62
|
+
locusMediaRequest?: LocusMediaRequest;
|
|
82
63
|
}) {
|
|
83
|
-
const {roapMessage, locusSelfUrl, mediaId,
|
|
64
|
+
const {roapMessage, locusSelfUrl, mediaId, meetingId, locusMediaRequest, ipVersion} = options;
|
|
84
65
|
|
|
85
66
|
if (!mediaId) {
|
|
86
|
-
LoggerProxy.logger.info('Roap:request#sendRoap -->
|
|
67
|
+
LoggerProxy.logger.info('Roap:request#sendRoap --> sending empty mediaID');
|
|
87
68
|
}
|
|
88
69
|
|
|
70
|
+
if (!locusMediaRequest) {
|
|
71
|
+
LoggerProxy.logger.warn(
|
|
72
|
+
'Roap:request#sendRoap --> locusMediaRequest unavailable, not sending roap'
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
return Promise.reject(new Error('sendRoap called when locusMediaRequest is undefined'));
|
|
76
|
+
}
|
|
89
77
|
const {localSdp: localSdpWithReachabilityData, joinCookie} = await this.attachReachabilityData({
|
|
90
78
|
roapMessage,
|
|
91
|
-
// eslint-disable-next-line no-warning-comments
|
|
92
|
-
// TODO: check whats the need for video and audiomute
|
|
93
|
-
audioMuted: !!options.audioMuted,
|
|
94
|
-
videoMuted: !!options.videoMuted,
|
|
95
79
|
});
|
|
96
80
|
|
|
97
|
-
const mediaUrl = `${locusSelfUrl}/${MEDIA}`;
|
|
98
|
-
// @ts-ignore
|
|
99
|
-
const deviceUrl = this.webex.internal.device.url;
|
|
100
|
-
|
|
101
81
|
LoggerProxy.logger.info(
|
|
102
|
-
`Roap:request#sendRoap --> ${
|
|
82
|
+
`Roap:request#sendRoap --> ${locusSelfUrl} \n ${roapMessage.messageType} \n seq:${roapMessage.seq}`
|
|
103
83
|
);
|
|
104
84
|
|
|
105
|
-
Metrics.postEvent({event: eventType.MEDIA_REQUEST, meetingId});
|
|
106
|
-
|
|
107
85
|
// @ts-ignore
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
device: {
|
|
113
|
-
url: deviceUrl,
|
|
114
|
-
// @ts-ignore
|
|
115
|
-
deviceType: this.config.meetings.deviceType,
|
|
116
|
-
},
|
|
117
|
-
correlationId,
|
|
118
|
-
localMedias: [
|
|
119
|
-
{
|
|
120
|
-
localSdp: JSON.stringify(localSdpWithReachabilityData),
|
|
121
|
-
mediaId: options.mediaId,
|
|
122
|
-
},
|
|
123
|
-
],
|
|
124
|
-
clientMediaPreferences: {
|
|
125
|
-
preferTranscoding: options.preferTranscoding ?? true,
|
|
126
|
-
joinCookie,
|
|
127
|
-
},
|
|
86
|
+
this.webex.internal.newMetrics.submitClientEvent({
|
|
87
|
+
name: 'client.locus.media.request',
|
|
88
|
+
options: {
|
|
89
|
+
meetingId,
|
|
128
90
|
},
|
|
129
|
-
})
|
|
130
|
-
.then((res) => {
|
|
131
|
-
Metrics.postEvent({event: eventType.MEDIA_RESPONSE, meetingId});
|
|
91
|
+
});
|
|
132
92
|
|
|
93
|
+
return locusMediaRequest
|
|
94
|
+
.send({
|
|
95
|
+
type: 'RoapMessage',
|
|
96
|
+
selfUrl: locusSelfUrl,
|
|
97
|
+
joinCookie,
|
|
98
|
+
mediaId,
|
|
99
|
+
roapMessage,
|
|
100
|
+
reachability: localSdpWithReachabilityData.reachability,
|
|
101
|
+
ipVersion,
|
|
102
|
+
})
|
|
103
|
+
.then((res) => {
|
|
104
|
+
// @ts-ignore
|
|
105
|
+
this.webex.internal.newMetrics.submitClientEvent({
|
|
106
|
+
name: 'client.locus.media.response',
|
|
107
|
+
options: {
|
|
108
|
+
meetingId,
|
|
109
|
+
},
|
|
110
|
+
});
|
|
133
111
|
// always it will be the first mediaConnection Object
|
|
134
112
|
const mediaConnections =
|
|
135
113
|
res.body.mediaConnections &&
|
|
@@ -153,10 +131,13 @@ export default class RoapRequest extends StatelessWebexPlugin {
|
|
|
153
131
|
};
|
|
154
132
|
})
|
|
155
133
|
.catch((err) => {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
134
|
+
// @ts-ignore
|
|
135
|
+
this.webex.internal.newMetrics.submitClientEvent({
|
|
136
|
+
name: 'client.locus.media.response',
|
|
137
|
+
options: {
|
|
138
|
+
meetingId,
|
|
139
|
+
rawError: err,
|
|
140
|
+
},
|
|
160
141
|
});
|
|
161
142
|
LoggerProxy.logger.error(`Roap:request#sendRoap --> Error:${JSON.stringify(err, null, 2)}`);
|
|
162
143
|
LoggerProxy.logger.error(
|
|
@@ -8,6 +8,7 @@ import {ROAP} from '../constants';
|
|
|
8
8
|
|
|
9
9
|
import RoapRequest from './request';
|
|
10
10
|
import Meeting from '../meeting';
|
|
11
|
+
import MeetingUtil from '../meeting/util';
|
|
11
12
|
|
|
12
13
|
const TURN_DISCOVERY_TIMEOUT = 10; // in seconds
|
|
13
14
|
|
|
@@ -55,7 +56,7 @@ export default class TurnDiscovery {
|
|
|
55
56
|
* @private
|
|
56
57
|
* @memberof Roap
|
|
57
58
|
*/
|
|
58
|
-
private waitForTurnDiscoveryResponse() {
|
|
59
|
+
private waitForTurnDiscoveryResponse(): Promise<{isOkRequired: boolean}> {
|
|
59
60
|
if (!this.defer) {
|
|
60
61
|
LoggerProxy.logger.warn(
|
|
61
62
|
'Roap:turnDiscovery#waitForTurnDiscoveryResponse --> TURN discovery is not in progress'
|
|
@@ -87,22 +88,32 @@ export default class TurnDiscovery {
|
|
|
87
88
|
* handles TURN_DISCOVERY_RESPONSE roap message
|
|
88
89
|
*
|
|
89
90
|
* @param {Object} roapMessage
|
|
91
|
+
* @param {string} from string to indicate how we got the response (used just for logging)
|
|
90
92
|
* @returns {void}
|
|
91
93
|
* @public
|
|
92
94
|
* @memberof Roap
|
|
93
95
|
*/
|
|
94
|
-
public handleTurnDiscoveryResponse(roapMessage:
|
|
95
|
-
// @ts-ignore - Fix missing type
|
|
96
|
+
public handleTurnDiscoveryResponse(roapMessage: any, from: string) {
|
|
96
97
|
const {headers} = roapMessage;
|
|
97
98
|
|
|
98
99
|
if (!this.defer) {
|
|
99
100
|
LoggerProxy.logger.warn(
|
|
100
|
-
|
|
101
|
+
`Roap:turnDiscovery#handleTurnDiscoveryResponse --> unexpected TURN discovery response ${from}`
|
|
101
102
|
);
|
|
102
103
|
|
|
103
104
|
return;
|
|
104
105
|
}
|
|
105
106
|
|
|
107
|
+
if (roapMessage.messageType !== ROAP.ROAP_TYPES.TURN_DISCOVERY_RESPONSE) {
|
|
108
|
+
this.defer.reject(
|
|
109
|
+
new Error(
|
|
110
|
+
`TURN_DISCOVERY_RESPONSE ${from} has unexpected messageType: ${JSON.stringify(
|
|
111
|
+
roapMessage
|
|
112
|
+
)}`
|
|
113
|
+
)
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
|
|
106
117
|
const expectedHeaders = [
|
|
107
118
|
{headerName: 'x-cisco-turn-url', field: 'url'},
|
|
108
119
|
{headerName: 'x-cisco-turn-username', field: 'username'},
|
|
@@ -128,21 +139,39 @@ export default class TurnDiscovery {
|
|
|
128
139
|
|
|
129
140
|
if (foundHeaders !== expectedHeaders.length) {
|
|
130
141
|
LoggerProxy.logger.warn(
|
|
131
|
-
`Roap:turnDiscovery#handleTurnDiscoveryResponse --> missing some headers, received: ${JSON.stringify(
|
|
142
|
+
`Roap:turnDiscovery#handleTurnDiscoveryResponse --> missing some headers, received ${from}: ${JSON.stringify(
|
|
132
143
|
headers
|
|
133
144
|
)}`
|
|
134
145
|
);
|
|
135
146
|
this.defer.reject(
|
|
136
|
-
new Error(
|
|
147
|
+
new Error(
|
|
148
|
+
`TURN_DISCOVERY_RESPONSE ${from} missing some headers: ${JSON.stringify(headers)}`
|
|
149
|
+
)
|
|
137
150
|
);
|
|
138
151
|
} else {
|
|
139
152
|
LoggerProxy.logger.info(
|
|
140
|
-
`Roap:turnDiscovery#handleTurnDiscoveryResponse --> received a valid response, url=${this.turnInfo.url}`
|
|
153
|
+
`Roap:turnDiscovery#handleTurnDiscoveryResponse --> received a valid response ${from}, url=${this.turnInfo.url}`
|
|
141
154
|
);
|
|
142
|
-
|
|
155
|
+
|
|
156
|
+
this.defer.resolve({isOkRequired: !headers?.includes('noOkInTransaction')});
|
|
143
157
|
}
|
|
144
158
|
}
|
|
145
159
|
|
|
160
|
+
/**
|
|
161
|
+
* handles TURN_DISCOVERY_RESPONSE roap message that came in http response
|
|
162
|
+
*
|
|
163
|
+
* @param {Object} roapMessage
|
|
164
|
+
* @returns {Promise}
|
|
165
|
+
* @memberof Roap
|
|
166
|
+
*/
|
|
167
|
+
private async handleTurnDiscoveryResponseInHttpResponse(
|
|
168
|
+
roapMessage: object
|
|
169
|
+
): Promise<{isOkRequired: boolean}> {
|
|
170
|
+
this.handleTurnDiscoveryResponse(roapMessage, 'in http response');
|
|
171
|
+
|
|
172
|
+
return this.defer.promise;
|
|
173
|
+
}
|
|
174
|
+
|
|
146
175
|
/**
|
|
147
176
|
* sends the TURN_DISCOVERY_REQUEST roap request
|
|
148
177
|
*
|
|
@@ -167,6 +196,7 @@ export default class TurnDiscovery {
|
|
|
167
196
|
messageType: ROAP.ROAP_TYPES.TURN_DISCOVERY_REQUEST,
|
|
168
197
|
version: ROAP.ROAP_VERSION,
|
|
169
198
|
seq: TURN_DISCOVERY_SEQ,
|
|
199
|
+
headers: ['includeAnswerInHttpResponse', 'noOkInTransaction'],
|
|
170
200
|
};
|
|
171
201
|
|
|
172
202
|
LoggerProxy.logger.info(
|
|
@@ -176,20 +206,50 @@ export default class TurnDiscovery {
|
|
|
176
206
|
return this.roapRequest
|
|
177
207
|
.sendRoap({
|
|
178
208
|
roapMessage,
|
|
179
|
-
correlationId: meeting.correlationId,
|
|
180
209
|
// @ts-ignore - Fix missing type
|
|
181
210
|
locusSelfUrl: meeting.selfUrl,
|
|
182
211
|
// @ts-ignore - Fix missing type
|
|
183
212
|
mediaId: isReconnecting ? '' : meeting.mediaId,
|
|
184
|
-
audioMuted: meeting.audio?.isLocallyMuted(),
|
|
185
|
-
videoMuted: meeting.video?.isLocallyMuted(),
|
|
186
213
|
meetingId: meeting.id,
|
|
187
|
-
|
|
214
|
+
locusMediaRequest: meeting.locusMediaRequest,
|
|
215
|
+
// @ts-ignore - because of meeting.webex
|
|
216
|
+
ipVersion: MeetingUtil.getIpVersion(meeting.webex),
|
|
188
217
|
})
|
|
189
|
-
.then((
|
|
218
|
+
.then((response) => {
|
|
219
|
+
const {mediaConnections} = response;
|
|
220
|
+
|
|
221
|
+
let turnDiscoveryResponse;
|
|
222
|
+
|
|
190
223
|
if (mediaConnections) {
|
|
191
224
|
meeting.updateMediaConnections(mediaConnections);
|
|
225
|
+
|
|
226
|
+
if (mediaConnections[0]?.remoteSdp) {
|
|
227
|
+
const remoteSdp = JSON.parse(mediaConnections[0].remoteSdp);
|
|
228
|
+
|
|
229
|
+
if (remoteSdp.roapMessage) {
|
|
230
|
+
// yes, it's misleading that remoteSdp actually contains a TURN discovery response, but that's how the backend works...
|
|
231
|
+
const {seq, messageType, errorType, errorCause, headers} = remoteSdp.roapMessage;
|
|
232
|
+
|
|
233
|
+
turnDiscoveryResponse = {
|
|
234
|
+
seq,
|
|
235
|
+
messageType,
|
|
236
|
+
errorType,
|
|
237
|
+
errorCause,
|
|
238
|
+
headers,
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
}
|
|
192
242
|
}
|
|
243
|
+
|
|
244
|
+
if (!turnDiscoveryResponse) {
|
|
245
|
+
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.ROAP_HTTP_RESPONSE_MISSING, {
|
|
246
|
+
correlationId: meeting.correlationId,
|
|
247
|
+
messageType: 'TURN_DISCOVERY_RESPONSE',
|
|
248
|
+
isMultistream: meeting.isMultistream,
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
return turnDiscoveryResponse;
|
|
193
253
|
});
|
|
194
254
|
}
|
|
195
255
|
|
|
@@ -213,14 +273,45 @@ export default class TurnDiscovery {
|
|
|
213
273
|
locusSelfUrl: meeting.selfUrl,
|
|
214
274
|
// @ts-ignore - fix type
|
|
215
275
|
mediaId: meeting.mediaId,
|
|
216
|
-
correlationId: meeting.correlationId,
|
|
217
|
-
audioMuted: meeting.audio?.isLocallyMuted(),
|
|
218
|
-
videoMuted: meeting.video?.isLocallyMuted(),
|
|
219
276
|
meetingId: meeting.id,
|
|
220
|
-
|
|
277
|
+
locusMediaRequest: meeting.locusMediaRequest,
|
|
221
278
|
});
|
|
222
279
|
}
|
|
223
280
|
|
|
281
|
+
/**
|
|
282
|
+
* Gets the reason why reachability is skipped.
|
|
283
|
+
*
|
|
284
|
+
* @param {Meeting} meeting
|
|
285
|
+
* @returns {Promise<string>} Promise with empty string if reachability is not skipped or a reason if it is skipped
|
|
286
|
+
*/
|
|
287
|
+
private async getSkipReason(meeting: Meeting): Promise<string> {
|
|
288
|
+
const isAnyPublicClusterReachable =
|
|
289
|
+
// @ts-ignore - fix type
|
|
290
|
+
await meeting.webex.meetings.reachability.isAnyPublicClusterReachable();
|
|
291
|
+
|
|
292
|
+
if (isAnyPublicClusterReachable) {
|
|
293
|
+
LoggerProxy.logger.info(
|
|
294
|
+
'Roap:turnDiscovery#getSkipReason --> reachability has not failed, skipping TURN discovery'
|
|
295
|
+
);
|
|
296
|
+
|
|
297
|
+
return 'reachability';
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
return '';
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Checks if TURN discovery is skipped.
|
|
305
|
+
*
|
|
306
|
+
* @param {Meeting} meeting
|
|
307
|
+
* @returns {Boolean} true if TURN discovery is being skipped, false if it is being done
|
|
308
|
+
*/
|
|
309
|
+
async isSkipped(meeting) {
|
|
310
|
+
const skipReason = await this.getSkipReason(meeting);
|
|
311
|
+
|
|
312
|
+
return !!skipReason;
|
|
313
|
+
}
|
|
314
|
+
|
|
224
315
|
/**
|
|
225
316
|
* Retrieves TURN server information from the backend by doing
|
|
226
317
|
* a roap message exchange:
|
|
@@ -234,58 +325,65 @@ export default class TurnDiscovery {
|
|
|
234
325
|
* so it works fine no matter if TURN discovery is done or not.
|
|
235
326
|
*
|
|
236
327
|
* @param {Meeting} meeting
|
|
237
|
-
* @param {Boolean} isReconnecting should be set to true if this is a new
|
|
328
|
+
* @param {Boolean} [isReconnecting] should be set to true if this is a new
|
|
238
329
|
* media connection just after a reconnection
|
|
330
|
+
* @param {Boolean} [isForced]
|
|
239
331
|
* @returns {Promise}
|
|
240
332
|
*/
|
|
241
|
-
async doTurnDiscovery(meeting: Meeting, isReconnecting?: boolean) {
|
|
242
|
-
|
|
243
|
-
const isAnyClusterReachable = await meeting.webex.meetings.reachability.isAnyClusterReachable();
|
|
333
|
+
async doTurnDiscovery(meeting: Meeting, isReconnecting?: boolean, isForced?: boolean) {
|
|
334
|
+
let turnDiscoverySkippedReason: string;
|
|
244
335
|
|
|
245
|
-
if (
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
);
|
|
336
|
+
if (!isForced) {
|
|
337
|
+
turnDiscoverySkippedReason = await this.getSkipReason(meeting);
|
|
338
|
+
}
|
|
249
339
|
|
|
340
|
+
if (turnDiscoverySkippedReason) {
|
|
250
341
|
return {
|
|
251
342
|
turnServerInfo: undefined,
|
|
252
|
-
turnDiscoverySkippedReason
|
|
343
|
+
turnDiscoverySkippedReason,
|
|
253
344
|
};
|
|
254
345
|
}
|
|
255
346
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
LoggerProxy.logger.info(
|
|
259
|
-
'Roap:turnDiscovery#doTurnDiscovery --> TURN discovery disabled in config, skipping it'
|
|
260
|
-
);
|
|
347
|
+
try {
|
|
348
|
+
const httpResponse = await this.sendRoapTurnDiscoveryRequest(meeting, isReconnecting);
|
|
261
349
|
|
|
262
|
-
|
|
263
|
-
|
|
350
|
+
// if we haven't got the response over http, we need to wait for it to come over the websocket via Mercury
|
|
351
|
+
const {isOkRequired} = httpResponse
|
|
352
|
+
? await this.handleTurnDiscoveryResponseInHttpResponse(httpResponse)
|
|
353
|
+
: await this.waitForTurnDiscoveryResponse();
|
|
264
354
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
.then(() => this.sendRoapOK(meeting))
|
|
268
|
-
.then(() => {
|
|
269
|
-
this.defer = undefined;
|
|
355
|
+
if (isOkRequired) {
|
|
356
|
+
await this.sendRoapOK(meeting);
|
|
270
357
|
|
|
271
|
-
LoggerProxy.logger.info('Roap:turnDiscovery#doTurnDiscovery --> TURN discovery completed');
|
|
272
|
-
|
|
273
|
-
return {turnServerInfo: this.turnInfo, turnDiscoverySkippedReason: undefined};
|
|
274
|
-
})
|
|
275
|
-
.catch((e) => {
|
|
276
|
-
// we catch any errors and resolve with no turn information so that the normal call join flow can continue without TURN
|
|
277
358
|
LoggerProxy.logger.info(
|
|
278
|
-
|
|
359
|
+
'Roap:turnDiscovery#doTurnDiscovery --> TURN discovery response requires OK'
|
|
279
360
|
);
|
|
280
361
|
|
|
281
|
-
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.
|
|
362
|
+
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.TURN_DISCOVERY_REQUIRES_OK, {
|
|
282
363
|
correlation_id: meeting.correlationId,
|
|
283
364
|
locus_id: meeting.locusUrl.split('/').pop(),
|
|
284
|
-
reason: e.message,
|
|
285
|
-
stack: e.stack,
|
|
286
365
|
});
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
this.defer = undefined;
|
|
287
369
|
|
|
288
|
-
|
|
370
|
+
LoggerProxy.logger.info('Roap:turnDiscovery#doTurnDiscovery --> TURN discovery completed');
|
|
371
|
+
|
|
372
|
+
return {turnServerInfo: this.turnInfo, turnDiscoverySkippedReason: undefined};
|
|
373
|
+
} catch (e) {
|
|
374
|
+
// we catch any errors and resolve with no turn information so that the normal call join flow can continue without TURN
|
|
375
|
+
LoggerProxy.logger.info(
|
|
376
|
+
`Roap:turnDiscovery#doTurnDiscovery --> TURN discovery failed, continuing without TURN: ${e}`
|
|
377
|
+
);
|
|
378
|
+
|
|
379
|
+
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.TURN_DISCOVERY_FAILURE, {
|
|
380
|
+
correlation_id: meeting.correlationId,
|
|
381
|
+
locus_id: meeting.locusUrl.split('/').pop(),
|
|
382
|
+
reason: e.message,
|
|
383
|
+
stack: e.stack,
|
|
289
384
|
});
|
|
385
|
+
|
|
386
|
+
return {turnServerInfo: undefined, turnDiscoverySkippedReason: undefined};
|
|
387
|
+
}
|
|
290
388
|
}
|
|
291
389
|
}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/* eslint-disable class-methods-use-this */
|
|
2
|
+
import {CallDiagnosticUtils} from '@webex/internal-plugin-metrics';
|
|
3
|
+
import uuid from 'uuid';
|
|
4
|
+
import RTC_METRICS from './constants';
|
|
5
|
+
|
|
6
|
+
const parseJsonPayload = (payload: any[]): any | null => {
|
|
7
|
+
try {
|
|
8
|
+
if (payload && payload[0]) {
|
|
9
|
+
return JSON.parse(payload[0]);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
return null;
|
|
13
|
+
} catch (_) {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Rtc Metrics
|
|
20
|
+
*/
|
|
21
|
+
export default class RtcMetrics {
|
|
22
|
+
/**
|
|
23
|
+
* Array of MetricData items to be sent to the metrics service.
|
|
24
|
+
*/
|
|
25
|
+
metricsQueue = [];
|
|
26
|
+
|
|
27
|
+
intervalId: number;
|
|
28
|
+
|
|
29
|
+
webex: any;
|
|
30
|
+
|
|
31
|
+
meetingId: string;
|
|
32
|
+
|
|
33
|
+
correlationId: string;
|
|
34
|
+
|
|
35
|
+
connectionId: string;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Initialize the interval.
|
|
39
|
+
*
|
|
40
|
+
* @param {object} webex - The main `webex` object.
|
|
41
|
+
* @param {string} meetingId - The meeting id.
|
|
42
|
+
* @param {string} correlationId - The correlation id.
|
|
43
|
+
*/
|
|
44
|
+
constructor(webex, meetingId, correlationId) {
|
|
45
|
+
// `window` is used to prevent typescript from returning a NodeJS.Timer.
|
|
46
|
+
this.intervalId = window.setInterval(this.sendMetricsInQueue.bind(this), 30 * 1000);
|
|
47
|
+
this.meetingId = meetingId;
|
|
48
|
+
this.webex = webex;
|
|
49
|
+
this.correlationId = correlationId;
|
|
50
|
+
this.setNewConnectionId();
|
|
51
|
+
// Send the first set of metrics at 5 seconds in the case of a user leaving the call shortly after joining.
|
|
52
|
+
setTimeout(this.sendMetricsInQueue.bind(this), 5 * 1000);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Check to see if the metrics queue has any items.
|
|
57
|
+
*
|
|
58
|
+
* @returns {void}
|
|
59
|
+
*/
|
|
60
|
+
public sendMetricsInQueue() {
|
|
61
|
+
if (this.metricsQueue.length) {
|
|
62
|
+
this.sendMetrics();
|
|
63
|
+
this.metricsQueue = [];
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Add metrics items to the metrics queue.
|
|
69
|
+
*
|
|
70
|
+
* @param {object} data - An object with a payload array of metrics items.
|
|
71
|
+
*
|
|
72
|
+
* @returns {void}
|
|
73
|
+
*/
|
|
74
|
+
addMetrics(data) {
|
|
75
|
+
if (data.payload.length) {
|
|
76
|
+
if (data.name === 'stats-report') {
|
|
77
|
+
data.payload = data.payload.map(this.anonymizeIp);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
this.metricsQueue.push(data);
|
|
81
|
+
|
|
82
|
+
try {
|
|
83
|
+
// If a connection fails, send the rest of the metrics in queue and get a new connection id.
|
|
84
|
+
const parsedPayload = parseJsonPayload(data.payload);
|
|
85
|
+
if (
|
|
86
|
+
data.name === 'onconnectionstatechange' &&
|
|
87
|
+
parsedPayload &&
|
|
88
|
+
parsedPayload.value === 'failed'
|
|
89
|
+
) {
|
|
90
|
+
this.sendMetricsInQueue();
|
|
91
|
+
this.setNewConnectionId();
|
|
92
|
+
}
|
|
93
|
+
} catch (e) {
|
|
94
|
+
console.error(e);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Clear the metrics interval.
|
|
101
|
+
*
|
|
102
|
+
* @returns {void}
|
|
103
|
+
*/
|
|
104
|
+
closeMetrics() {
|
|
105
|
+
this.sendMetricsInQueue();
|
|
106
|
+
clearInterval(this.intervalId);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Anonymize IP addresses.
|
|
111
|
+
*
|
|
112
|
+
* @param {array} stats - An RTCStatsReport organized into an array of strings.
|
|
113
|
+
* @returns {string}
|
|
114
|
+
*/
|
|
115
|
+
anonymizeIp(stats: string): string {
|
|
116
|
+
const data = JSON.parse(stats);
|
|
117
|
+
// on local and remote candidates, anonymize the last 4 bits.
|
|
118
|
+
if (data.type === 'local-candidate' || data.type === 'remote-candidate') {
|
|
119
|
+
data.ip = CallDiagnosticUtils.anonymizeIPAddress(data.ip) || undefined;
|
|
120
|
+
data.address = CallDiagnosticUtils.anonymizeIPAddress(data.address) || undefined;
|
|
121
|
+
data.relatedAddress =
|
|
122
|
+
CallDiagnosticUtils.anonymizeIPAddress(data.relatedAddress) || undefined;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return JSON.stringify(data);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Set a new connection id.
|
|
130
|
+
*
|
|
131
|
+
* @returns {void}
|
|
132
|
+
*/
|
|
133
|
+
private setNewConnectionId() {
|
|
134
|
+
this.connectionId = uuid.v4();
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Send metrics to the metrics service.
|
|
139
|
+
*
|
|
140
|
+
* @returns {void}
|
|
141
|
+
*/
|
|
142
|
+
private sendMetrics() {
|
|
143
|
+
this.webex.request({
|
|
144
|
+
method: 'POST',
|
|
145
|
+
service: 'unifiedTelemetry',
|
|
146
|
+
resource: 'metric/v2',
|
|
147
|
+
headers: {
|
|
148
|
+
type: 'webrtcMedia',
|
|
149
|
+
appId: RTC_METRICS.APP_ID,
|
|
150
|
+
},
|
|
151
|
+
body: {
|
|
152
|
+
metrics: [
|
|
153
|
+
{
|
|
154
|
+
type: 'webrtc',
|
|
155
|
+
version: '1.1.0',
|
|
156
|
+
userId: this.webex.internal.device.userId,
|
|
157
|
+
meetingId: this.meetingId,
|
|
158
|
+
correlationId: this.correlationId,
|
|
159
|
+
connectionId: this.connectionId,
|
|
160
|
+
data: this.metricsQueue,
|
|
161
|
+
},
|
|
162
|
+
],
|
|
163
|
+
},
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
}
|