@webex/plugin-meetings 2.59.1 → 2.59.3-next.1
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/.eslintrc.js +6 -6
- package/LICENSE +1 -1
- package/README.md +1204 -1204
- package/UPGRADING.md +287 -287
- package/babel.config.js +3 -3
- package/browsers.js +108 -108
- package/dist/common/browser-detection.d.ts +9 -9
- package/dist/common/browser-detection.js.map +1 -1
- package/dist/common/collection.d.ts +48 -48
- package/dist/common/collection.js +43 -43
- package/dist/common/collection.js.map +1 -1
- package/dist/common/config.d.ts +2 -2
- package/dist/common/config.js.map +1 -1
- package/dist/common/errors/captcha-error.d.ts +15 -15
- package/dist/common/errors/captcha-error.js +7 -7
- package/dist/common/errors/captcha-error.js.map +1 -1
- package/dist/common/errors/intent-to-join.d.ts +16 -16
- package/dist/common/errors/intent-to-join.js +7 -7
- package/dist/common/errors/intent-to-join.js.map +1 -1
- package/dist/common/errors/join-meeting.d.ts +17 -17
- package/dist/common/errors/join-meeting.js +8 -8
- package/dist/common/errors/join-meeting.js.map +1 -1
- package/dist/common/errors/media.d.ts +15 -15
- package/dist/common/errors/media.js +7 -7
- package/dist/common/errors/media.js.map +1 -1
- package/dist/common/errors/parameter.d.ts +15 -15
- package/dist/common/errors/parameter.js +7 -7
- package/dist/common/errors/parameter.js.map +1 -1
- package/dist/common/errors/password-error.d.ts +15 -15
- package/dist/common/errors/password-error.js +7 -7
- package/dist/common/errors/password-error.js.map +1 -1
- package/dist/common/errors/permission.d.ts +14 -14
- package/dist/common/errors/permission.js +6 -6
- package/dist/common/errors/permission.js.map +1 -1
- package/dist/common/errors/reconnection-in-progress.d.ts +9 -9
- package/dist/common/errors/reconnection-in-progress.js +6 -6
- package/dist/common/errors/reconnection-in-progress.js.map +1 -1
- package/dist/common/errors/reconnection.d.ts +15 -15
- package/dist/common/errors/reconnection.js +7 -7
- package/dist/common/errors/reconnection.js.map +1 -1
- package/dist/common/errors/stats.d.ts +15 -15
- package/dist/common/errors/stats.js +7 -7
- package/dist/common/errors/stats.js.map +1 -1
- package/dist/common/errors/webex-errors.d.ts +81 -81
- package/dist/common/errors/webex-errors.js +42 -42
- package/dist/common/errors/webex-errors.js.map +1 -1
- package/dist/common/errors/webex-meetings-error.d.ts +20 -20
- package/dist/common/errors/webex-meetings-error.js +12 -12
- package/dist/common/errors/webex-meetings-error.js.map +1 -1
- package/dist/common/events/events-scope.d.ts +17 -17
- package/dist/common/events/events-scope.js +10 -10
- package/dist/common/events/events-scope.js.map +1 -1
- package/dist/common/events/events.d.ts +12 -12
- package/dist/common/events/events.js +4 -4
- package/dist/common/events/events.js.map +1 -1
- package/dist/common/events/trigger-proxy.d.ts +2 -2
- package/dist/common/events/trigger-proxy.js.map +1 -1
- package/dist/common/events/util.d.ts +2 -2
- package/dist/common/events/util.js.map +1 -1
- package/dist/common/logs/logger-config.d.ts +2 -2
- package/dist/common/logs/logger-config.js.map +1 -1
- package/dist/common/logs/logger-proxy.d.ts +2 -2
- package/dist/common/logs/logger-proxy.js.map +1 -1
- package/dist/common/logs/request.d.ts +34 -34
- package/dist/common/logs/request.js +18 -18
- package/dist/common/logs/request.js.map +1 -1
- package/dist/common/queue.d.ts +32 -32
- package/dist/common/queue.js +18 -18
- package/dist/common/queue.js.map +1 -1
- package/dist/config.d.ts +73 -73
- package/dist/config.js.map +1 -1
- package/dist/constants.d.ts +924 -924
- package/dist/constants.js +9 -9
- package/dist/constants.js.map +1 -1
- package/dist/controls-options-manager/constants.d.ts +4 -4
- package/dist/controls-options-manager/constants.js.map +1 -1
- package/dist/controls-options-manager/enums.d.ts +5 -5
- package/dist/controls-options-manager/enums.js.map +1 -1
- package/dist/controls-options-manager/index.d.ts +120 -120
- package/dist/controls-options-manager/index.js +81 -81
- package/dist/controls-options-manager/index.js.map +1 -1
- package/dist/controls-options-manager/util.d.ts +7 -7
- package/dist/controls-options-manager/util.js.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.js.map +1 -1
- package/dist/locus-info/controlsUtils.d.ts +2 -2
- package/dist/locus-info/controlsUtils.js +21 -21
- package/dist/locus-info/controlsUtils.js.map +1 -1
- package/dist/locus-info/embeddedAppsUtils.d.ts +2 -2
- package/dist/locus-info/embeddedAppsUtils.js +14 -14
- package/dist/locus-info/embeddedAppsUtils.js.map +1 -1
- package/dist/locus-info/fullState.d.ts +2 -2
- package/dist/locus-info/fullState.js.map +1 -1
- package/dist/locus-info/hostUtils.d.ts +2 -2
- package/dist/locus-info/hostUtils.js +19 -19
- package/dist/locus-info/hostUtils.js.map +1 -1
- package/dist/locus-info/index.d.ts +269 -269
- package/dist/locus-info/index.js +180 -180
- package/dist/locus-info/index.js.map +1 -1
- package/dist/locus-info/infoUtils.d.ts +2 -2
- package/dist/locus-info/infoUtils.js.map +1 -1
- package/dist/locus-info/mediaSharesUtils.d.ts +2 -2
- package/dist/locus-info/mediaSharesUtils.js +50 -50
- package/dist/locus-info/mediaSharesUtils.js.map +1 -1
- package/dist/locus-info/parser.d.ts +212 -212
- package/dist/locus-info/parser.js +136 -136
- package/dist/locus-info/parser.js.map +1 -1
- package/dist/locus-info/selfUtils.d.ts +2 -2
- package/dist/locus-info/selfUtils.js +52 -52
- package/dist/locus-info/selfUtils.js.map +1 -1
- package/dist/media/index.d.ts +32 -32
- package/dist/media/index.js +145 -145
- package/dist/media/index.js.map +1 -1
- package/dist/media/properties.d.ts +108 -108
- package/dist/media/properties.js +49 -49
- package/dist/media/properties.js.map +1 -1
- package/dist/media/util.d.ts +2 -2
- package/dist/media/util.js.map +1 -1
- package/dist/mediaQualityMetrics/config.d.ts +233 -233
- package/dist/mediaQualityMetrics/config.js.map +1 -1
- package/dist/meeting/effectsState.d.ts +42 -42
- package/dist/meeting/effectsState.js +24 -24
- package/dist/meeting/effectsState.js.map +1 -1
- package/dist/meeting/in-meeting-actions.d.ts +79 -79
- package/dist/meeting/in-meeting-actions.js +11 -11
- package/dist/meeting/in-meeting-actions.js.map +1 -1
- package/dist/meeting/index.d.ts +1621 -1621
- package/dist/meeting/index.js +1502 -1505
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/muteState.d.ts +116 -116
- package/dist/meeting/muteState.js +85 -85
- package/dist/meeting/muteState.js.map +1 -1
- package/dist/meeting/request.d.ts +255 -255
- package/dist/meeting/request.js +141 -141
- package/dist/meeting/request.js.map +1 -1
- package/dist/meeting/state.d.ts +9 -9
- package/dist/meeting/state.js +30 -30
- package/dist/meeting/state.js.map +1 -1
- package/dist/meeting/util.d.ts +2 -2
- package/dist/meeting/util.js.map +1 -1
- package/dist/meeting-info/collection.d.ts +20 -20
- package/dist/meeting-info/collection.js +11 -11
- package/dist/meeting-info/collection.js.map +1 -1
- package/dist/meeting-info/index.d.ts +57 -57
- package/dist/meeting-info/index.js +50 -50
- package/dist/meeting-info/index.js.map +1 -1
- package/dist/meeting-info/meeting-info-v2.d.ts +93 -93
- package/dist/meeting-info/meeting-info-v2.js +52 -52
- package/dist/meeting-info/meeting-info-v2.js.map +1 -1
- package/dist/meeting-info/request.d.ts +22 -22
- package/dist/meeting-info/request.js +14 -14
- package/dist/meeting-info/request.js.map +1 -1
- package/dist/meeting-info/util.d.ts +2 -2
- package/dist/meeting-info/util.js +9 -9
- package/dist/meeting-info/util.js.map +1 -1
- package/dist/meeting-info/utilv2.d.ts +2 -2
- package/dist/meeting-info/utilv2.js +20 -20
- package/dist/meeting-info/utilv2.js.map +1 -1
- package/dist/meetings/collection.d.ts +23 -23
- package/dist/meetings/collection.js +14 -14
- package/dist/meetings/collection.js.map +1 -1
- package/dist/meetings/index.d.ts +296 -296
- package/dist/meetings/index.js +259 -259
- package/dist/meetings/index.js.map +1 -1
- package/dist/meetings/request.d.ts +27 -27
- package/dist/meetings/request.js +15 -15
- package/dist/meetings/request.js.map +1 -1
- package/dist/meetings/util.d.ts +18 -18
- package/dist/meetings/util.js +29 -29
- package/dist/meetings/util.js.map +1 -1
- package/dist/member/index.d.ts +147 -147
- package/dist/member/index.js +214 -214
- package/dist/member/index.js.map +1 -1
- package/dist/member/member.types.d.ts +11 -11
- package/dist/member/member.types.js.map +1 -1
- package/dist/member/util.d.ts +2 -2
- package/dist/member/util.js +60 -60
- package/dist/member/util.js.map +1 -1
- package/dist/members/collection.d.ts +24 -24
- package/dist/members/collection.js +11 -11
- package/dist/members/collection.js.map +1 -1
- package/dist/members/index.d.ts +298 -298
- package/dist/members/index.js +275 -275
- package/dist/members/index.js.map +1 -1
- package/dist/members/request.d.ts +50 -50
- package/dist/members/request.js +27 -27
- package/dist/members/request.js.map +1 -1
- package/dist/members/util.d.ts +2 -2
- package/dist/members/util.js +21 -21
- package/dist/members/util.js.map +1 -1
- package/dist/metrics/config.d.ts +169 -169
- package/dist/metrics/config.js.map +1 -1
- package/dist/metrics/constants.d.ts +57 -57
- package/dist/metrics/constants.js.map +1 -1
- package/dist/metrics/index.d.ts +152 -152
- package/dist/metrics/index.js +90 -90
- package/dist/metrics/index.js.map +1 -1
- package/dist/networkQualityMonitor/index.d.ts +70 -70
- package/dist/networkQualityMonitor/index.js +65 -65
- package/dist/networkQualityMonitor/index.js.map +1 -1
- package/dist/peer-connection-manager/index.d.ts +6 -6
- package/dist/peer-connection-manager/index.js +87 -87
- package/dist/peer-connection-manager/index.js.map +1 -1
- package/dist/peer-connection-manager/util.d.ts +6 -6
- package/dist/peer-connection-manager/util.js +9 -9
- package/dist/peer-connection-manager/util.js.map +1 -1
- package/dist/personal-meeting-room/index.d.ts +47 -47
- package/dist/personal-meeting-room/index.js +67 -67
- package/dist/personal-meeting-room/index.js.map +1 -1
- package/dist/personal-meeting-room/request.d.ts +14 -14
- package/dist/personal-meeting-room/request.js +7 -7
- package/dist/personal-meeting-room/request.js.map +1 -1
- package/dist/personal-meeting-room/util.d.ts +2 -2
- package/dist/personal-meeting-room/util.js.map +1 -1
- package/dist/reachability/index.d.ts +139 -139
- package/dist/reachability/index.js +110 -110
- package/dist/reachability/index.js.map +1 -1
- package/dist/reachability/request.d.ts +35 -35
- package/dist/reachability/request.js +15 -15
- package/dist/reachability/request.js.map +1 -1
- package/dist/reactions/reactions.d.ts +4 -4
- package/dist/reactions/reactions.js.map +1 -1
- package/dist/reactions/reactions.type.d.ts +32 -32
- package/dist/reactions/reactions.type.js.map +1 -1
- package/dist/reconnection-manager/index.d.ts +112 -112
- package/dist/reconnection-manager/index.js +112 -112
- package/dist/reconnection-manager/index.js.map +1 -1
- package/dist/recording-controller/enums.d.ts +7 -7
- package/dist/recording-controller/enums.js.map +1 -1
- package/dist/recording-controller/index.d.ts +193 -193
- package/dist/recording-controller/index.js +127 -127
- package/dist/recording-controller/index.js.map +1 -1
- package/dist/recording-controller/util.d.ts +13 -13
- package/dist/recording-controller/util.js.map +1 -1
- package/dist/roap/collection.d.ts +10 -10
- package/dist/roap/collection.js.map +1 -1
- package/dist/roap/handler.d.ts +47 -47
- package/dist/roap/handler.js +27 -27
- package/dist/roap/handler.js.map +1 -1
- package/dist/roap/index.d.ts +116 -116
- package/dist/roap/index.js +111 -111
- package/dist/roap/index.js.map +1 -1
- package/dist/roap/request.d.ts +35 -35
- package/dist/roap/request.js +17 -17
- package/dist/roap/request.js.map +1 -1
- package/dist/roap/state.d.ts +9 -9
- package/dist/roap/state.js +14 -14
- package/dist/roap/state.js.map +1 -1
- package/dist/roap/turnDiscovery.d.ts +67 -67
- package/dist/roap/turnDiscovery.js +46 -46
- package/dist/roap/turnDiscovery.js.map +1 -1
- package/dist/roap/util.d.ts +2 -2
- package/dist/roap/util.js.map +1 -1
- package/dist/statsAnalyzer/global.d.ts +126 -126
- package/dist/statsAnalyzer/global.js.map +1 -1
- package/dist/statsAnalyzer/index.d.ts +190 -190
- package/dist/statsAnalyzer/index.js +128 -128
- package/dist/statsAnalyzer/index.js.map +1 -1
- package/dist/statsAnalyzer/mqaUtil.d.ts +22 -22
- package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
- package/dist/transcription/index.d.ts +64 -64
- package/dist/transcription/index.js +42 -42
- package/dist/transcription/index.js.map +1 -1
- package/internal-README.md +172 -172
- package/jest.config.js +3 -3
- package/package.json +22 -21
- package/process +1 -1
- package/src/common/browser-detection.ts +39 -39
- package/src/common/collection.ts +94 -94
- package/src/common/config.ts +9 -9
- package/src/common/errors/captcha-error.ts +25 -25
- package/src/common/errors/intent-to-join.ts +27 -27
- package/src/common/errors/join-meeting.ts +32 -32
- package/src/common/errors/media.ts +25 -25
- package/src/common/errors/parameter.ts +33 -33
- package/src/common/errors/password-error.ts +25 -25
- package/src/common/errors/permission.ts +24 -24
- package/src/common/errors/reconnection-in-progress.ts +8 -8
- package/src/common/errors/reconnection.ts +25 -25
- package/src/common/errors/stats.ts +25 -25
- package/src/common/errors/webex-errors.ts +140 -140
- package/src/common/errors/webex-meetings-error.ts +35 -35
- package/src/common/events/events-scope.ts +30 -30
- package/src/common/events/events.ts +25 -25
- package/src/common/events/trigger-proxy.ts +25 -25
- package/src/common/events/util.ts +39 -39
- package/src/common/logs/logger-config.ts +8 -8
- package/src/common/logs/logger-proxy.ts +44 -44
- package/src/common/logs/request.ts +65 -65
- package/src/common/queue.ts +50 -50
- package/src/config.ts +96 -96
- package/src/constants.ts +1121 -1121
- package/src/controls-options-manager/constants.ts +5 -5
- package/src/controls-options-manager/enums.ts +6 -6
- package/src/controls-options-manager/index.ts +183 -183
- package/src/controls-options-manager/util.ts +20 -20
- package/src/index.js +15 -15
- package/src/locus-info/controlsUtils.ts +112 -112
- package/src/locus-info/embeddedAppsUtils.ts +57 -57
- package/src/locus-info/fullState.ts +69 -69
- package/src/locus-info/hostUtils.ts +60 -60
- package/src/locus-info/index.ts +1303 -1303
- package/src/locus-info/infoUtils.ts +101 -101
- package/src/locus-info/mediaSharesUtils.ts +173 -173
- package/src/locus-info/parser.ts +680 -680
- package/src/locus-info/selfUtils.ts +428 -428
- package/src/media/index.ts +675 -675
- package/src/media/properties.ts +313 -313
- package/src/media/util.ts +37 -37
- package/src/mediaQualityMetrics/config.ts +382 -382
- package/src/meeting/effectsState.ts +209 -209
- package/src/meeting/in-meeting-actions.ts +153 -153
- package/src/meeting/index.ts +6537 -6543
- package/src/meeting/muteState.ts +365 -365
- package/src/meeting/request.ts +810 -810
- package/src/meeting/state.ts +194 -194
- package/src/meeting/util.ts +530 -530
- package/src/meeting-info/collection.ts +41 -41
- package/src/meeting-info/index.ts +137 -137
- package/src/meeting-info/meeting-info-v2.ts +273 -273
- package/src/meeting-info/request.ts +46 -46
- package/src/meeting-info/util.ts +314 -314
- package/src/meeting-info/utilv2.ts +324 -324
- package/src/meetings/collection.ts +43 -43
- package/src/meetings/index.ts +1128 -1128
- package/src/meetings/request.ts +81 -81
- package/src/meetings/util.ts +181 -181
- package/src/member/index.ts +446 -446
- package/src/member/member.types.ts +13 -13
- package/src/member/util.ts +286 -286
- package/src/members/collection.ts +40 -40
- package/src/members/index.ts +900 -900
- package/src/members/request.ts +175 -175
- package/src/members/util.ts +260 -260
- package/src/metrics/config.ts +485 -485
- package/src/metrics/constants.ts +61 -61
- package/src/metrics/index.ts +543 -543
- package/src/networkQualityMonitor/index.ts +211 -211
- package/src/peer-connection-manager/index.ts +847 -847
- package/src/peer-connection-manager/util.ts +119 -119
- package/src/personal-meeting-room/index.ts +157 -157
- package/src/personal-meeting-room/request.ts +48 -48
- package/src/personal-meeting-room/util.ts +49 -49
- package/src/reachability/index.ts +478 -478
- package/src/reachability/request.ts +81 -81
- package/src/reactions/reactions.ts +104 -104
- package/src/reactions/reactions.type.ts +36 -36
- package/src/reconnection-manager/index.ts +622 -622
- package/src/recording-controller/enums.ts +8 -8
- package/src/recording-controller/index.ts +315 -315
- package/src/recording-controller/util.ts +58 -58
- package/src/roap/collection.ts +62 -62
- package/src/roap/handler.ts +294 -294
- package/src/roap/index.ts +413 -413
- package/src/roap/request.ts +229 -229
- package/src/roap/state.ts +156 -156
- package/src/roap/turnDiscovery.ts +283 -283
- package/src/roap/util.ts +100 -100
- package/src/statsAnalyzer/global.ts +128 -128
- package/src/statsAnalyzer/index.ts +1266 -1266
- package/src/statsAnalyzer/mqaUtil.ts +290 -290
- package/src/transcription/index.ts +154 -154
- package/test/integration/spec/journey.js +941 -941
- package/test/integration/spec/space-meeting.js +457 -457
- package/test/integration/spec/transcription.js +55 -55
- package/test/unit/spec/common/browser-detection.js +119 -119
- package/test/unit/spec/common/queue.js +69 -69
- package/test/unit/spec/controls-options-manager/index.js +123 -123
- package/test/unit/spec/controls-options-manager/util.js +65 -65
- package/test/unit/spec/fixture/locus.js +406 -406
- package/test/unit/spec/locus-info/controlsUtils.js +82 -82
- package/test/unit/spec/locus-info/embeddedAppsUtils.js +104 -104
- package/test/unit/spec/locus-info/index.js +1272 -1272
- package/test/unit/spec/locus-info/infoUtils.js +138 -138
- package/test/unit/spec/locus-info/lib/BasicSeqCmp.json +975 -975
- package/test/unit/spec/locus-info/lib/SeqCmp.json +522 -522
- package/test/unit/spec/locus-info/lib/selfConstant.js +286 -286
- package/test/unit/spec/locus-info/parser.js +298 -298
- package/test/unit/spec/locus-info/selfUtils.js +185 -185
- package/test/unit/spec/media/properties.ts +305 -305
- package/test/unit/spec/meeting/effectsState.js +281 -281
- package/test/unit/spec/meeting/in-meeting-actions.ts +90 -90
- package/test/unit/spec/meeting/index.js +5227 -5227
- package/test/unit/spec/meeting/muteState.js +430 -430
- package/test/unit/spec/meeting/request.js +317 -317
- package/test/unit/spec/meeting/utils.js +319 -319
- package/test/unit/spec/meeting-info/meetinginfov2.js +376 -376
- package/test/unit/spec/meeting-info/request.js +64 -64
- package/test/unit/spec/meeting-info/util.js +37 -37
- package/test/unit/spec/meeting-info/utilv2.js +330 -330
- package/test/unit/spec/meetings/collection.js +52 -52
- package/test/unit/spec/meetings/index.js +1375 -1375
- package/test/unit/spec/meetings/utils.js +66 -66
- package/test/unit/spec/member/index.js +47 -47
- package/test/unit/spec/member/util.js +80 -80
- package/test/unit/spec/members/index.js +364 -364
- package/test/unit/spec/members/request.js +200 -200
- package/test/unit/spec/members/utils.js +42 -42
- package/test/unit/spec/metrics/index.js +111 -111
- package/test/unit/spec/networkQualityMonitor/index.js +99 -99
- package/test/unit/spec/peerconnection-manager/index.js +218 -218
- package/test/unit/spec/peerconnection-manager/utils.js +49 -49
- package/test/unit/spec/peerconnection-manager/utils.test-fixtures.ts +388 -388
- package/test/unit/spec/personal-meeting-room/personal-meeting-room.js +29 -29
- package/test/unit/spec/reachability/index.ts +50 -50
- package/test/unit/spec/reconnection-manager/index.js +206 -206
- package/test/unit/spec/recording-controller/index.js +230 -230
- package/test/unit/spec/recording-controller/util.js +101 -101
- package/test/unit/spec/roap/index.ts +128 -128
- package/test/unit/spec/roap/turnDiscovery.ts +372 -372
- package/test/unit/spec/roap/util.js +30 -30
- package/test/unit/spec/stats-analyzer/index.js +287 -287
- package/test/utils/cmr.js +104 -104
- package/test/utils/testUtils.js +287 -287
- package/test/utils/webex-config.js +77 -77
- package/test/utils/webex-test-users.js +82 -82
- package/tsconfig.json +5 -5
|
@@ -1,372 +1,372 @@
|
|
|
1
|
-
import sinon from 'sinon';
|
|
2
|
-
import {assert} from '@webex/test-helper-chai';
|
|
3
|
-
import TurnDiscovery from '@webex/plugin-meetings/src/roap/turnDiscovery';
|
|
4
|
-
|
|
5
|
-
import Metrics from '@webex/plugin-meetings/src/metrics';
|
|
6
|
-
import BEHAVIORAL_METRICS from '@webex/plugin-meetings/src/metrics/constants';
|
|
7
|
-
import RoapRequest from '@webex/plugin-meetings/src/roap/request';
|
|
8
|
-
|
|
9
|
-
import testUtils from '../../../utils/testUtils';
|
|
10
|
-
|
|
11
|
-
describe('TurnDiscovery', () => {
|
|
12
|
-
let clock;
|
|
13
|
-
let mockRoapRequest: RoapRequest;
|
|
14
|
-
let testMeeting: any;
|
|
15
|
-
|
|
16
|
-
const FAKE_TURN_URL = 'turns:fakeTurnServer.com:443?transport=tcp';
|
|
17
|
-
const FAKE_TURN_USERNAME = 'someUsernameFromServer';
|
|
18
|
-
const FAKE_TURN_PASSWORD = 'fakePasswordFromServer';
|
|
19
|
-
const FAKE_LOCUS_ID = '09493311-f5d5-3e58-b491-009cc628162e';
|
|
20
|
-
const FAKE_MEDIA_CONNECTIONS_FROM_LOCUS = [{mediaId: '464ff97f-4bda-466a-ad06-3a22184a2274'}];
|
|
21
|
-
|
|
22
|
-
beforeEach(() => {
|
|
23
|
-
clock = sinon.useFakeTimers();
|
|
24
|
-
|
|
25
|
-
sinon.stub(Metrics, 'sendBehavioralMetric');
|
|
26
|
-
|
|
27
|
-
mockRoapRequest = {
|
|
28
|
-
sendRoap: sinon.fake.resolves({mediaConnections: FAKE_MEDIA_CONNECTIONS_FROM_LOCUS}),
|
|
29
|
-
} as unknown as RoapRequest;
|
|
30
|
-
|
|
31
|
-
testMeeting = {
|
|
32
|
-
id: 'fake meeting id',
|
|
33
|
-
config: {
|
|
34
|
-
experimental: {
|
|
35
|
-
enableTurnDiscovery: true,
|
|
36
|
-
},
|
|
37
|
-
},
|
|
38
|
-
correlationId: 'fake correlation id',
|
|
39
|
-
selfUrl: 'fake self url',
|
|
40
|
-
mediaId: 'fake media id',
|
|
41
|
-
locusUrl: `https://locus-a.wbx2.com/locus/api/v1/loci/${FAKE_LOCUS_ID}`,
|
|
42
|
-
roapSeq: -1,
|
|
43
|
-
audio:{
|
|
44
|
-
isLocallyMuted: () => true,
|
|
45
|
-
},
|
|
46
|
-
video:{
|
|
47
|
-
isLocallyMuted: () => false,
|
|
48
|
-
},
|
|
49
|
-
setRoapSeq: sinon.fake((newSeq) => {
|
|
50
|
-
testMeeting.roapSeq = newSeq;
|
|
51
|
-
}),
|
|
52
|
-
updateMediaConnections: sinon.stub(),
|
|
53
|
-
webex: {meetings: {reachability: {isAnyClusterReachable: () => false}}},
|
|
54
|
-
};
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
afterEach(() => {
|
|
58
|
-
clock.restore();
|
|
59
|
-
sinon.restore();
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
const checkRoapMessageSent = async (
|
|
63
|
-
messageType,
|
|
64
|
-
expectedSeq,
|
|
65
|
-
expectedMediaId = testMeeting.mediaId
|
|
66
|
-
) => {
|
|
67
|
-
await testUtils.flushPromises();
|
|
68
|
-
|
|
69
|
-
assert.calledOnce(mockRoapRequest.sendRoap);
|
|
70
|
-
assert.calledWith(mockRoapRequest.sendRoap, {
|
|
71
|
-
roapMessage: {
|
|
72
|
-
messageType,
|
|
73
|
-
version: '2',
|
|
74
|
-
seq: expectedSeq,
|
|
75
|
-
},
|
|
76
|
-
correlationId: testMeeting.correlationId,
|
|
77
|
-
locusSelfUrl: testMeeting.selfUrl,
|
|
78
|
-
mediaId: expectedMediaId,
|
|
79
|
-
audioMuted: testMeeting.audio?.isLocallyMuted(),
|
|
80
|
-
videoMuted: testMeeting.video?.isLocallyMuted(),
|
|
81
|
-
meetingId: testMeeting.id,
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
if (messageType === 'TURN_DISCOVERY_REQUEST') {
|
|
85
|
-
// check also that we've applied the media connections from the response
|
|
86
|
-
assert.calledOnce(testMeeting.updateMediaConnections);
|
|
87
|
-
assert.calledWith(testMeeting.updateMediaConnections, FAKE_MEDIA_CONNECTIONS_FROM_LOCUS);
|
|
88
|
-
}
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
const checkFailureMetricsSent = () => {
|
|
92
|
-
assert.calledOnce(Metrics.sendBehavioralMetric);
|
|
93
|
-
assert.calledWith(
|
|
94
|
-
Metrics.sendBehavioralMetric,
|
|
95
|
-
BEHAVIORAL_METRICS.TURN_DISCOVERY_FAILURE,
|
|
96
|
-
sinon.match({
|
|
97
|
-
correlation_id: testMeeting.correlationId,
|
|
98
|
-
locus_id: FAKE_LOCUS_ID,
|
|
99
|
-
})
|
|
100
|
-
);
|
|
101
|
-
};
|
|
102
|
-
|
|
103
|
-
describe('doTurnDiscovery', () => {
|
|
104
|
-
it('sends TURN_DISCOVERY_REQUEST, waits for response and sends OK', async () => {
|
|
105
|
-
const td = new TurnDiscovery(mockRoapRequest);
|
|
106
|
-
|
|
107
|
-
const result = td.doTurnDiscovery(testMeeting, false);
|
|
108
|
-
|
|
109
|
-
// check that TURN_DISCOVERY_REQUEST was sent
|
|
110
|
-
await checkRoapMessageSent('TURN_DISCOVERY_REQUEST', 0);
|
|
111
|
-
// @ts-ignore
|
|
112
|
-
mockRoapRequest.sendRoap.resetHistory();
|
|
113
|
-
|
|
114
|
-
// simulate the response
|
|
115
|
-
td.handleTurnDiscoveryResponse({
|
|
116
|
-
headers: [
|
|
117
|
-
`x-cisco-turn-url=${FAKE_TURN_URL}`,
|
|
118
|
-
`x-cisco-turn-username=${FAKE_TURN_USERNAME}`,
|
|
119
|
-
`x-cisco-turn-password=${FAKE_TURN_PASSWORD}`,
|
|
120
|
-
],
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
await testUtils.flushPromises();
|
|
124
|
-
|
|
125
|
-
// check that we've sent OK
|
|
126
|
-
await checkRoapMessageSent('OK', 0);
|
|
127
|
-
|
|
128
|
-
const {turnServerInfo, turnDiscoverySkippedReason} = await result;
|
|
129
|
-
|
|
130
|
-
assert.deepEqual(turnServerInfo, {
|
|
131
|
-
url: FAKE_TURN_URL,
|
|
132
|
-
username: FAKE_TURN_USERNAME,
|
|
133
|
-
password: FAKE_TURN_PASSWORD,
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
assert.isUndefined(turnDiscoverySkippedReason);
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
it('sends TURN_DISCOVERY_REQUEST with empty mediaId when isReconnecting is true', async () => {
|
|
140
|
-
const td = new TurnDiscovery(mockRoapRequest);
|
|
141
|
-
|
|
142
|
-
const result = td.doTurnDiscovery(testMeeting, true);
|
|
143
|
-
|
|
144
|
-
// check that TURN_DISCOVERY_REQUEST was sent with empty mediaId
|
|
145
|
-
await checkRoapMessageSent('TURN_DISCOVERY_REQUEST', 0, '');
|
|
146
|
-
|
|
147
|
-
// the main part of the test is complete now, checking the remaining part of the flow just for completeness
|
|
148
|
-
// @ts-ignore
|
|
149
|
-
mockRoapRequest.sendRoap.resetHistory();
|
|
150
|
-
|
|
151
|
-
// simulate the response
|
|
152
|
-
td.handleTurnDiscoveryResponse({
|
|
153
|
-
headers: [
|
|
154
|
-
`x-cisco-turn-url=${FAKE_TURN_URL}`,
|
|
155
|
-
`x-cisco-turn-username=${FAKE_TURN_USERNAME}`,
|
|
156
|
-
`x-cisco-turn-password=${FAKE_TURN_PASSWORD}`,
|
|
157
|
-
],
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
await testUtils.flushPromises();
|
|
161
|
-
|
|
162
|
-
// check that we've sent OK
|
|
163
|
-
await checkRoapMessageSent('OK', 0);
|
|
164
|
-
|
|
165
|
-
const {turnServerInfo, turnDiscoverySkippedReason} = await result;
|
|
166
|
-
|
|
167
|
-
assert.deepEqual(turnServerInfo, {
|
|
168
|
-
url: FAKE_TURN_URL,
|
|
169
|
-
username: FAKE_TURN_USERNAME,
|
|
170
|
-
password: FAKE_TURN_PASSWORD,
|
|
171
|
-
});
|
|
172
|
-
assert.isUndefined(turnDiscoverySkippedReason);
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
it('ignores any extra, unexpected headers in the response', async () => {
|
|
176
|
-
const td = new TurnDiscovery(mockRoapRequest);
|
|
177
|
-
const result = td.doTurnDiscovery(testMeeting, false);
|
|
178
|
-
|
|
179
|
-
// check that TURN_DISCOVERY_REQUEST was sent
|
|
180
|
-
await checkRoapMessageSent('TURN_DISCOVERY_REQUEST', 0);
|
|
181
|
-
// @ts-ignore
|
|
182
|
-
mockRoapRequest.sendRoap.resetHistory();
|
|
183
|
-
|
|
184
|
-
// simulate the response with some extra headers
|
|
185
|
-
td.handleTurnDiscoveryResponse({
|
|
186
|
-
headers: [
|
|
187
|
-
'x-cisco-turn-unexpected-header=xxx',
|
|
188
|
-
`x-cisco-turn-url=${FAKE_TURN_URL}`,
|
|
189
|
-
'x-cisco-some-other-header',
|
|
190
|
-
`x-cisco-turn-username=${FAKE_TURN_USERNAME}`,
|
|
191
|
-
`x-cisco-turn-password=${FAKE_TURN_PASSWORD}`,
|
|
192
|
-
'another-header-at-the-end=12345',
|
|
193
|
-
],
|
|
194
|
-
});
|
|
195
|
-
|
|
196
|
-
await testUtils.flushPromises();
|
|
197
|
-
|
|
198
|
-
// check that we've sent OK and still parsed the headers we care about
|
|
199
|
-
await checkRoapMessageSent('OK', 0);
|
|
200
|
-
|
|
201
|
-
const {turnServerInfo, turnDiscoverySkippedReason} = await result;
|
|
202
|
-
assert.deepEqual(turnServerInfo, {
|
|
203
|
-
url: FAKE_TURN_URL,
|
|
204
|
-
username: FAKE_TURN_USERNAME,
|
|
205
|
-
password: FAKE_TURN_PASSWORD,
|
|
206
|
-
});
|
|
207
|
-
assert.isUndefined(turnDiscoverySkippedReason);
|
|
208
|
-
});
|
|
209
|
-
|
|
210
|
-
it('resolves with undefined if turn discovery feature is disabled in config', async () => {
|
|
211
|
-
const prevConfigValue = testMeeting.config.experimental.enableTurnDiscovery;
|
|
212
|
-
|
|
213
|
-
testMeeting.config.experimental.enableTurnDiscovery = false;
|
|
214
|
-
// @ts-ignore
|
|
215
|
-
const result = await new TurnDiscovery(mockRoapRequest).doTurnDiscovery(testMeeting);
|
|
216
|
-
|
|
217
|
-
const {turnServerInfo, turnDiscoverySkippedReason} = result;
|
|
218
|
-
|
|
219
|
-
assert.isUndefined(turnServerInfo);
|
|
220
|
-
assert.equal(turnDiscoverySkippedReason, 'config');
|
|
221
|
-
assert.notCalled(mockRoapRequest.sendRoap);
|
|
222
|
-
assert.notCalled(Metrics.sendBehavioralMetric);
|
|
223
|
-
|
|
224
|
-
// restore previous config
|
|
225
|
-
testMeeting.config.experimental.enableTurnDiscovery = prevConfigValue;
|
|
226
|
-
});
|
|
227
|
-
|
|
228
|
-
it('resolves with undefined if sending the request fails', async () => {
|
|
229
|
-
const td = new TurnDiscovery(mockRoapRequest);
|
|
230
|
-
|
|
231
|
-
mockRoapRequest.sendRoap = sinon.fake.rejects(new Error('fake error'));
|
|
232
|
-
|
|
233
|
-
const result = await td.doTurnDiscovery(testMeeting, false);
|
|
234
|
-
|
|
235
|
-
const {turnServerInfo, turnDiscoverySkippedReason} = result;
|
|
236
|
-
|
|
237
|
-
assert.isUndefined(turnServerInfo);
|
|
238
|
-
assert.isUndefined(turnDiscoverySkippedReason);
|
|
239
|
-
checkFailureMetricsSent();
|
|
240
|
-
});
|
|
241
|
-
|
|
242
|
-
it('resolves with undefined when cluster is reachable', async () => {
|
|
243
|
-
const prev = testMeeting.webex.meetings.reachability.isAnyClusterReachable;
|
|
244
|
-
testMeeting.webex.meetings.reachability.isAnyClusterReachable = () => true;
|
|
245
|
-
const result = await new TurnDiscovery(mockRoapRequest).doTurnDiscovery(testMeeting);
|
|
246
|
-
|
|
247
|
-
const {turnServerInfo, turnDiscoverySkippedReason} = result;
|
|
248
|
-
|
|
249
|
-
assert.isUndefined(turnServerInfo);
|
|
250
|
-
assert.equal(turnDiscoverySkippedReason, 'reachability');
|
|
251
|
-
assert.notCalled(mockRoapRequest.sendRoap);
|
|
252
|
-
assert.notCalled(Metrics.sendBehavioralMetric);
|
|
253
|
-
testMeeting.webex.meetings.reachability.isAnyClusterReachable = prev;
|
|
254
|
-
});
|
|
255
|
-
|
|
256
|
-
it("resolves with undefined if we don't get a response within 10s", async () => {
|
|
257
|
-
const td = new TurnDiscovery(mockRoapRequest);
|
|
258
|
-
|
|
259
|
-
const promise = td.doTurnDiscovery(testMeeting, false);
|
|
260
|
-
|
|
261
|
-
await clock.tickAsync(10 * 1000);
|
|
262
|
-
await testUtils.flushPromises();
|
|
263
|
-
|
|
264
|
-
const {turnServerInfo, turnDiscoverySkippedReason} = await promise;
|
|
265
|
-
|
|
266
|
-
assert.isUndefined(turnServerInfo);
|
|
267
|
-
assert.isUndefined(turnDiscoverySkippedReason);
|
|
268
|
-
checkFailureMetricsSent();
|
|
269
|
-
});
|
|
270
|
-
|
|
271
|
-
it('resolves with undefined if the response does not have all the headers we expect', async () => {
|
|
272
|
-
const td = new TurnDiscovery(mockRoapRequest);
|
|
273
|
-
const turnDiscoveryPromise = td.doTurnDiscovery(testMeeting, false);
|
|
274
|
-
|
|
275
|
-
// simulate the response without the password
|
|
276
|
-
td.handleTurnDiscoveryResponse({
|
|
277
|
-
headers: [
|
|
278
|
-
`x-cisco-turn-url=${FAKE_TURN_URL}`,
|
|
279
|
-
`x-cisco-turn-username=${FAKE_TURN_USERNAME}`,
|
|
280
|
-
],
|
|
281
|
-
});
|
|
282
|
-
await testUtils.flushPromises();
|
|
283
|
-
const {turnServerInfo, turnDiscoverySkippedReason} = await turnDiscoveryPromise;
|
|
284
|
-
|
|
285
|
-
assert.isUndefined(turnServerInfo);
|
|
286
|
-
assert.isUndefined(turnDiscoverySkippedReason);
|
|
287
|
-
checkFailureMetricsSent();
|
|
288
|
-
});
|
|
289
|
-
|
|
290
|
-
it('resolves with undefined if the response does not have any headers', async () => {
|
|
291
|
-
const td = new TurnDiscovery(mockRoapRequest);
|
|
292
|
-
const turnDiscoveryPromise = td.doTurnDiscovery(testMeeting, false);
|
|
293
|
-
|
|
294
|
-
// simulate the response without the headers
|
|
295
|
-
td.handleTurnDiscoveryResponse({});
|
|
296
|
-
|
|
297
|
-
await testUtils.flushPromises();
|
|
298
|
-
const {turnServerInfo, turnDiscoverySkippedReason} = await turnDiscoveryPromise;
|
|
299
|
-
|
|
300
|
-
assert.isUndefined(turnServerInfo);
|
|
301
|
-
assert.isUndefined(turnDiscoverySkippedReason);
|
|
302
|
-
checkFailureMetricsSent();
|
|
303
|
-
});
|
|
304
|
-
|
|
305
|
-
it('resolves with undefined if the response has empty headers array', async () => {
|
|
306
|
-
const td = new TurnDiscovery(mockRoapRequest);
|
|
307
|
-
const turnDiscoveryPromise = td.doTurnDiscovery(testMeeting, false);
|
|
308
|
-
|
|
309
|
-
// simulate the response without the headers
|
|
310
|
-
td.handleTurnDiscoveryResponse({headers: []});
|
|
311
|
-
|
|
312
|
-
await testUtils.flushPromises();
|
|
313
|
-
const {turnServerInfo, turnDiscoverySkippedReason} = await turnDiscoveryPromise;
|
|
314
|
-
|
|
315
|
-
assert.isUndefined(turnServerInfo);
|
|
316
|
-
assert.isUndefined(turnDiscoverySkippedReason);
|
|
317
|
-
checkFailureMetricsSent();
|
|
318
|
-
});
|
|
319
|
-
|
|
320
|
-
it('resolves with undefined if failed to send OK', async () => {
|
|
321
|
-
const td = new TurnDiscovery(mockRoapRequest);
|
|
322
|
-
|
|
323
|
-
const turnDiscoveryPromise = td.doTurnDiscovery(testMeeting, false);
|
|
324
|
-
|
|
325
|
-
// check that TURN_DISCOVERY_REQUEST was sent
|
|
326
|
-
await checkRoapMessageSent('TURN_DISCOVERY_REQUEST', 0);
|
|
327
|
-
// @ts-ignore
|
|
328
|
-
mockRoapRequest.sendRoap.resetHistory();
|
|
329
|
-
|
|
330
|
-
// setup the mock so that sending of OK fails
|
|
331
|
-
mockRoapRequest.sendRoap = sinon.fake.rejects(new Error('fake error'));
|
|
332
|
-
|
|
333
|
-
// simulate the response
|
|
334
|
-
td.handleTurnDiscoveryResponse({
|
|
335
|
-
headers: [
|
|
336
|
-
`x-cisco-turn-url=${FAKE_TURN_URL}`,
|
|
337
|
-
`x-cisco-turn-username=${FAKE_TURN_USERNAME}`,
|
|
338
|
-
`x-cisco-turn-password=${FAKE_TURN_PASSWORD}`,
|
|
339
|
-
],
|
|
340
|
-
});
|
|
341
|
-
|
|
342
|
-
await testUtils.flushPromises();
|
|
343
|
-
|
|
344
|
-
// check that we've sent OK
|
|
345
|
-
await checkRoapMessageSent('OK', 0);
|
|
346
|
-
|
|
347
|
-
const {turnServerInfo, turnDiscoverySkippedReason} = await turnDiscoveryPromise;
|
|
348
|
-
|
|
349
|
-
assert.isUndefined(turnServerInfo);
|
|
350
|
-
assert.isUndefined(turnDiscoverySkippedReason);
|
|
351
|
-
checkFailureMetricsSent();
|
|
352
|
-
});
|
|
353
|
-
});
|
|
354
|
-
|
|
355
|
-
describe('handleTurnDiscoveryResponse', () => {
|
|
356
|
-
it("doesn't do anything if turn discovery was not started", () => {
|
|
357
|
-
const td = new TurnDiscovery(mockRoapRequest);
|
|
358
|
-
|
|
359
|
-
// there is not much we can check, but we mainly want to make
|
|
360
|
-
// sure that it doesn't crash
|
|
361
|
-
td.handleTurnDiscoveryResponse({
|
|
362
|
-
headers: [
|
|
363
|
-
`x-cisco-turn-url=${FAKE_TURN_URL}`,
|
|
364
|
-
`x-cisco-turn-username=${FAKE_TURN_USERNAME}`,
|
|
365
|
-
`x-cisco-turn-password=${FAKE_TURN_PASSWORD}`,
|
|
366
|
-
],
|
|
367
|
-
});
|
|
368
|
-
|
|
369
|
-
assert.notCalled(mockRoapRequest.sendRoap);
|
|
370
|
-
});
|
|
371
|
-
});
|
|
372
|
-
});
|
|
1
|
+
import sinon from 'sinon';
|
|
2
|
+
import {assert} from '@webex/test-helper-chai';
|
|
3
|
+
import TurnDiscovery from '@webex/plugin-meetings/src/roap/turnDiscovery';
|
|
4
|
+
|
|
5
|
+
import Metrics from '@webex/plugin-meetings/src/metrics';
|
|
6
|
+
import BEHAVIORAL_METRICS from '@webex/plugin-meetings/src/metrics/constants';
|
|
7
|
+
import RoapRequest from '@webex/plugin-meetings/src/roap/request';
|
|
8
|
+
|
|
9
|
+
import testUtils from '../../../utils/testUtils';
|
|
10
|
+
|
|
11
|
+
describe('TurnDiscovery', () => {
|
|
12
|
+
let clock;
|
|
13
|
+
let mockRoapRequest: RoapRequest;
|
|
14
|
+
let testMeeting: any;
|
|
15
|
+
|
|
16
|
+
const FAKE_TURN_URL = 'turns:fakeTurnServer.com:443?transport=tcp';
|
|
17
|
+
const FAKE_TURN_USERNAME = 'someUsernameFromServer';
|
|
18
|
+
const FAKE_TURN_PASSWORD = 'fakePasswordFromServer';
|
|
19
|
+
const FAKE_LOCUS_ID = '09493311-f5d5-3e58-b491-009cc628162e';
|
|
20
|
+
const FAKE_MEDIA_CONNECTIONS_FROM_LOCUS = [{mediaId: '464ff97f-4bda-466a-ad06-3a22184a2274'}];
|
|
21
|
+
|
|
22
|
+
beforeEach(() => {
|
|
23
|
+
clock = sinon.useFakeTimers();
|
|
24
|
+
|
|
25
|
+
sinon.stub(Metrics, 'sendBehavioralMetric');
|
|
26
|
+
|
|
27
|
+
mockRoapRequest = {
|
|
28
|
+
sendRoap: sinon.fake.resolves({mediaConnections: FAKE_MEDIA_CONNECTIONS_FROM_LOCUS}),
|
|
29
|
+
} as unknown as RoapRequest;
|
|
30
|
+
|
|
31
|
+
testMeeting = {
|
|
32
|
+
id: 'fake meeting id',
|
|
33
|
+
config: {
|
|
34
|
+
experimental: {
|
|
35
|
+
enableTurnDiscovery: true,
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
correlationId: 'fake correlation id',
|
|
39
|
+
selfUrl: 'fake self url',
|
|
40
|
+
mediaId: 'fake media id',
|
|
41
|
+
locusUrl: `https://locus-a.wbx2.com/locus/api/v1/loci/${FAKE_LOCUS_ID}`,
|
|
42
|
+
roapSeq: -1,
|
|
43
|
+
audio:{
|
|
44
|
+
isLocallyMuted: () => true,
|
|
45
|
+
},
|
|
46
|
+
video:{
|
|
47
|
+
isLocallyMuted: () => false,
|
|
48
|
+
},
|
|
49
|
+
setRoapSeq: sinon.fake((newSeq) => {
|
|
50
|
+
testMeeting.roapSeq = newSeq;
|
|
51
|
+
}),
|
|
52
|
+
updateMediaConnections: sinon.stub(),
|
|
53
|
+
webex: {meetings: {reachability: {isAnyClusterReachable: () => false}}},
|
|
54
|
+
};
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
afterEach(() => {
|
|
58
|
+
clock.restore();
|
|
59
|
+
sinon.restore();
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
const checkRoapMessageSent = async (
|
|
63
|
+
messageType,
|
|
64
|
+
expectedSeq,
|
|
65
|
+
expectedMediaId = testMeeting.mediaId
|
|
66
|
+
) => {
|
|
67
|
+
await testUtils.flushPromises();
|
|
68
|
+
|
|
69
|
+
assert.calledOnce(mockRoapRequest.sendRoap);
|
|
70
|
+
assert.calledWith(mockRoapRequest.sendRoap, {
|
|
71
|
+
roapMessage: {
|
|
72
|
+
messageType,
|
|
73
|
+
version: '2',
|
|
74
|
+
seq: expectedSeq,
|
|
75
|
+
},
|
|
76
|
+
correlationId: testMeeting.correlationId,
|
|
77
|
+
locusSelfUrl: testMeeting.selfUrl,
|
|
78
|
+
mediaId: expectedMediaId,
|
|
79
|
+
audioMuted: testMeeting.audio?.isLocallyMuted(),
|
|
80
|
+
videoMuted: testMeeting.video?.isLocallyMuted(),
|
|
81
|
+
meetingId: testMeeting.id,
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
if (messageType === 'TURN_DISCOVERY_REQUEST') {
|
|
85
|
+
// check also that we've applied the media connections from the response
|
|
86
|
+
assert.calledOnce(testMeeting.updateMediaConnections);
|
|
87
|
+
assert.calledWith(testMeeting.updateMediaConnections, FAKE_MEDIA_CONNECTIONS_FROM_LOCUS);
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
const checkFailureMetricsSent = () => {
|
|
92
|
+
assert.calledOnce(Metrics.sendBehavioralMetric);
|
|
93
|
+
assert.calledWith(
|
|
94
|
+
Metrics.sendBehavioralMetric,
|
|
95
|
+
BEHAVIORAL_METRICS.TURN_DISCOVERY_FAILURE,
|
|
96
|
+
sinon.match({
|
|
97
|
+
correlation_id: testMeeting.correlationId,
|
|
98
|
+
locus_id: FAKE_LOCUS_ID,
|
|
99
|
+
})
|
|
100
|
+
);
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
describe('doTurnDiscovery', () => {
|
|
104
|
+
it('sends TURN_DISCOVERY_REQUEST, waits for response and sends OK', async () => {
|
|
105
|
+
const td = new TurnDiscovery(mockRoapRequest);
|
|
106
|
+
|
|
107
|
+
const result = td.doTurnDiscovery(testMeeting, false);
|
|
108
|
+
|
|
109
|
+
// check that TURN_DISCOVERY_REQUEST was sent
|
|
110
|
+
await checkRoapMessageSent('TURN_DISCOVERY_REQUEST', 0);
|
|
111
|
+
// @ts-ignore
|
|
112
|
+
mockRoapRequest.sendRoap.resetHistory();
|
|
113
|
+
|
|
114
|
+
// simulate the response
|
|
115
|
+
td.handleTurnDiscoveryResponse({
|
|
116
|
+
headers: [
|
|
117
|
+
`x-cisco-turn-url=${FAKE_TURN_URL}`,
|
|
118
|
+
`x-cisco-turn-username=${FAKE_TURN_USERNAME}`,
|
|
119
|
+
`x-cisco-turn-password=${FAKE_TURN_PASSWORD}`,
|
|
120
|
+
],
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
await testUtils.flushPromises();
|
|
124
|
+
|
|
125
|
+
// check that we've sent OK
|
|
126
|
+
await checkRoapMessageSent('OK', 0);
|
|
127
|
+
|
|
128
|
+
const {turnServerInfo, turnDiscoverySkippedReason} = await result;
|
|
129
|
+
|
|
130
|
+
assert.deepEqual(turnServerInfo, {
|
|
131
|
+
url: FAKE_TURN_URL,
|
|
132
|
+
username: FAKE_TURN_USERNAME,
|
|
133
|
+
password: FAKE_TURN_PASSWORD,
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
assert.isUndefined(turnDiscoverySkippedReason);
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it('sends TURN_DISCOVERY_REQUEST with empty mediaId when isReconnecting is true', async () => {
|
|
140
|
+
const td = new TurnDiscovery(mockRoapRequest);
|
|
141
|
+
|
|
142
|
+
const result = td.doTurnDiscovery(testMeeting, true);
|
|
143
|
+
|
|
144
|
+
// check that TURN_DISCOVERY_REQUEST was sent with empty mediaId
|
|
145
|
+
await checkRoapMessageSent('TURN_DISCOVERY_REQUEST', 0, '');
|
|
146
|
+
|
|
147
|
+
// the main part of the test is complete now, checking the remaining part of the flow just for completeness
|
|
148
|
+
// @ts-ignore
|
|
149
|
+
mockRoapRequest.sendRoap.resetHistory();
|
|
150
|
+
|
|
151
|
+
// simulate the response
|
|
152
|
+
td.handleTurnDiscoveryResponse({
|
|
153
|
+
headers: [
|
|
154
|
+
`x-cisco-turn-url=${FAKE_TURN_URL}`,
|
|
155
|
+
`x-cisco-turn-username=${FAKE_TURN_USERNAME}`,
|
|
156
|
+
`x-cisco-turn-password=${FAKE_TURN_PASSWORD}`,
|
|
157
|
+
],
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
await testUtils.flushPromises();
|
|
161
|
+
|
|
162
|
+
// check that we've sent OK
|
|
163
|
+
await checkRoapMessageSent('OK', 0);
|
|
164
|
+
|
|
165
|
+
const {turnServerInfo, turnDiscoverySkippedReason} = await result;
|
|
166
|
+
|
|
167
|
+
assert.deepEqual(turnServerInfo, {
|
|
168
|
+
url: FAKE_TURN_URL,
|
|
169
|
+
username: FAKE_TURN_USERNAME,
|
|
170
|
+
password: FAKE_TURN_PASSWORD,
|
|
171
|
+
});
|
|
172
|
+
assert.isUndefined(turnDiscoverySkippedReason);
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
it('ignores any extra, unexpected headers in the response', async () => {
|
|
176
|
+
const td = new TurnDiscovery(mockRoapRequest);
|
|
177
|
+
const result = td.doTurnDiscovery(testMeeting, false);
|
|
178
|
+
|
|
179
|
+
// check that TURN_DISCOVERY_REQUEST was sent
|
|
180
|
+
await checkRoapMessageSent('TURN_DISCOVERY_REQUEST', 0);
|
|
181
|
+
// @ts-ignore
|
|
182
|
+
mockRoapRequest.sendRoap.resetHistory();
|
|
183
|
+
|
|
184
|
+
// simulate the response with some extra headers
|
|
185
|
+
td.handleTurnDiscoveryResponse({
|
|
186
|
+
headers: [
|
|
187
|
+
'x-cisco-turn-unexpected-header=xxx',
|
|
188
|
+
`x-cisco-turn-url=${FAKE_TURN_URL}`,
|
|
189
|
+
'x-cisco-some-other-header',
|
|
190
|
+
`x-cisco-turn-username=${FAKE_TURN_USERNAME}`,
|
|
191
|
+
`x-cisco-turn-password=${FAKE_TURN_PASSWORD}`,
|
|
192
|
+
'another-header-at-the-end=12345',
|
|
193
|
+
],
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
await testUtils.flushPromises();
|
|
197
|
+
|
|
198
|
+
// check that we've sent OK and still parsed the headers we care about
|
|
199
|
+
await checkRoapMessageSent('OK', 0);
|
|
200
|
+
|
|
201
|
+
const {turnServerInfo, turnDiscoverySkippedReason} = await result;
|
|
202
|
+
assert.deepEqual(turnServerInfo, {
|
|
203
|
+
url: FAKE_TURN_URL,
|
|
204
|
+
username: FAKE_TURN_USERNAME,
|
|
205
|
+
password: FAKE_TURN_PASSWORD,
|
|
206
|
+
});
|
|
207
|
+
assert.isUndefined(turnDiscoverySkippedReason);
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
it('resolves with undefined if turn discovery feature is disabled in config', async () => {
|
|
211
|
+
const prevConfigValue = testMeeting.config.experimental.enableTurnDiscovery;
|
|
212
|
+
|
|
213
|
+
testMeeting.config.experimental.enableTurnDiscovery = false;
|
|
214
|
+
// @ts-ignore
|
|
215
|
+
const result = await new TurnDiscovery(mockRoapRequest).doTurnDiscovery(testMeeting);
|
|
216
|
+
|
|
217
|
+
const {turnServerInfo, turnDiscoverySkippedReason} = result;
|
|
218
|
+
|
|
219
|
+
assert.isUndefined(turnServerInfo);
|
|
220
|
+
assert.equal(turnDiscoverySkippedReason, 'config');
|
|
221
|
+
assert.notCalled(mockRoapRequest.sendRoap);
|
|
222
|
+
assert.notCalled(Metrics.sendBehavioralMetric);
|
|
223
|
+
|
|
224
|
+
// restore previous config
|
|
225
|
+
testMeeting.config.experimental.enableTurnDiscovery = prevConfigValue;
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
it('resolves with undefined if sending the request fails', async () => {
|
|
229
|
+
const td = new TurnDiscovery(mockRoapRequest);
|
|
230
|
+
|
|
231
|
+
mockRoapRequest.sendRoap = sinon.fake.rejects(new Error('fake error'));
|
|
232
|
+
|
|
233
|
+
const result = await td.doTurnDiscovery(testMeeting, false);
|
|
234
|
+
|
|
235
|
+
const {turnServerInfo, turnDiscoverySkippedReason} = result;
|
|
236
|
+
|
|
237
|
+
assert.isUndefined(turnServerInfo);
|
|
238
|
+
assert.isUndefined(turnDiscoverySkippedReason);
|
|
239
|
+
checkFailureMetricsSent();
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
it('resolves with undefined when cluster is reachable', async () => {
|
|
243
|
+
const prev = testMeeting.webex.meetings.reachability.isAnyClusterReachable;
|
|
244
|
+
testMeeting.webex.meetings.reachability.isAnyClusterReachable = () => true;
|
|
245
|
+
const result = await new TurnDiscovery(mockRoapRequest).doTurnDiscovery(testMeeting);
|
|
246
|
+
|
|
247
|
+
const {turnServerInfo, turnDiscoverySkippedReason} = result;
|
|
248
|
+
|
|
249
|
+
assert.isUndefined(turnServerInfo);
|
|
250
|
+
assert.equal(turnDiscoverySkippedReason, 'reachability');
|
|
251
|
+
assert.notCalled(mockRoapRequest.sendRoap);
|
|
252
|
+
assert.notCalled(Metrics.sendBehavioralMetric);
|
|
253
|
+
testMeeting.webex.meetings.reachability.isAnyClusterReachable = prev;
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
it("resolves with undefined if we don't get a response within 10s", async () => {
|
|
257
|
+
const td = new TurnDiscovery(mockRoapRequest);
|
|
258
|
+
|
|
259
|
+
const promise = td.doTurnDiscovery(testMeeting, false);
|
|
260
|
+
|
|
261
|
+
await clock.tickAsync(10 * 1000);
|
|
262
|
+
await testUtils.flushPromises();
|
|
263
|
+
|
|
264
|
+
const {turnServerInfo, turnDiscoverySkippedReason} = await promise;
|
|
265
|
+
|
|
266
|
+
assert.isUndefined(turnServerInfo);
|
|
267
|
+
assert.isUndefined(turnDiscoverySkippedReason);
|
|
268
|
+
checkFailureMetricsSent();
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
it('resolves with undefined if the response does not have all the headers we expect', async () => {
|
|
272
|
+
const td = new TurnDiscovery(mockRoapRequest);
|
|
273
|
+
const turnDiscoveryPromise = td.doTurnDiscovery(testMeeting, false);
|
|
274
|
+
|
|
275
|
+
// simulate the response without the password
|
|
276
|
+
td.handleTurnDiscoveryResponse({
|
|
277
|
+
headers: [
|
|
278
|
+
`x-cisco-turn-url=${FAKE_TURN_URL}`,
|
|
279
|
+
`x-cisco-turn-username=${FAKE_TURN_USERNAME}`,
|
|
280
|
+
],
|
|
281
|
+
});
|
|
282
|
+
await testUtils.flushPromises();
|
|
283
|
+
const {turnServerInfo, turnDiscoverySkippedReason} = await turnDiscoveryPromise;
|
|
284
|
+
|
|
285
|
+
assert.isUndefined(turnServerInfo);
|
|
286
|
+
assert.isUndefined(turnDiscoverySkippedReason);
|
|
287
|
+
checkFailureMetricsSent();
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
it('resolves with undefined if the response does not have any headers', async () => {
|
|
291
|
+
const td = new TurnDiscovery(mockRoapRequest);
|
|
292
|
+
const turnDiscoveryPromise = td.doTurnDiscovery(testMeeting, false);
|
|
293
|
+
|
|
294
|
+
// simulate the response without the headers
|
|
295
|
+
td.handleTurnDiscoveryResponse({});
|
|
296
|
+
|
|
297
|
+
await testUtils.flushPromises();
|
|
298
|
+
const {turnServerInfo, turnDiscoverySkippedReason} = await turnDiscoveryPromise;
|
|
299
|
+
|
|
300
|
+
assert.isUndefined(turnServerInfo);
|
|
301
|
+
assert.isUndefined(turnDiscoverySkippedReason);
|
|
302
|
+
checkFailureMetricsSent();
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
it('resolves with undefined if the response has empty headers array', async () => {
|
|
306
|
+
const td = new TurnDiscovery(mockRoapRequest);
|
|
307
|
+
const turnDiscoveryPromise = td.doTurnDiscovery(testMeeting, false);
|
|
308
|
+
|
|
309
|
+
// simulate the response without the headers
|
|
310
|
+
td.handleTurnDiscoveryResponse({headers: []});
|
|
311
|
+
|
|
312
|
+
await testUtils.flushPromises();
|
|
313
|
+
const {turnServerInfo, turnDiscoverySkippedReason} = await turnDiscoveryPromise;
|
|
314
|
+
|
|
315
|
+
assert.isUndefined(turnServerInfo);
|
|
316
|
+
assert.isUndefined(turnDiscoverySkippedReason);
|
|
317
|
+
checkFailureMetricsSent();
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
it('resolves with undefined if failed to send OK', async () => {
|
|
321
|
+
const td = new TurnDiscovery(mockRoapRequest);
|
|
322
|
+
|
|
323
|
+
const turnDiscoveryPromise = td.doTurnDiscovery(testMeeting, false);
|
|
324
|
+
|
|
325
|
+
// check that TURN_DISCOVERY_REQUEST was sent
|
|
326
|
+
await checkRoapMessageSent('TURN_DISCOVERY_REQUEST', 0);
|
|
327
|
+
// @ts-ignore
|
|
328
|
+
mockRoapRequest.sendRoap.resetHistory();
|
|
329
|
+
|
|
330
|
+
// setup the mock so that sending of OK fails
|
|
331
|
+
mockRoapRequest.sendRoap = sinon.fake.rejects(new Error('fake error'));
|
|
332
|
+
|
|
333
|
+
// simulate the response
|
|
334
|
+
td.handleTurnDiscoveryResponse({
|
|
335
|
+
headers: [
|
|
336
|
+
`x-cisco-turn-url=${FAKE_TURN_URL}`,
|
|
337
|
+
`x-cisco-turn-username=${FAKE_TURN_USERNAME}`,
|
|
338
|
+
`x-cisco-turn-password=${FAKE_TURN_PASSWORD}`,
|
|
339
|
+
],
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
await testUtils.flushPromises();
|
|
343
|
+
|
|
344
|
+
// check that we've sent OK
|
|
345
|
+
await checkRoapMessageSent('OK', 0);
|
|
346
|
+
|
|
347
|
+
const {turnServerInfo, turnDiscoverySkippedReason} = await turnDiscoveryPromise;
|
|
348
|
+
|
|
349
|
+
assert.isUndefined(turnServerInfo);
|
|
350
|
+
assert.isUndefined(turnDiscoverySkippedReason);
|
|
351
|
+
checkFailureMetricsSent();
|
|
352
|
+
});
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
describe('handleTurnDiscoveryResponse', () => {
|
|
356
|
+
it("doesn't do anything if turn discovery was not started", () => {
|
|
357
|
+
const td = new TurnDiscovery(mockRoapRequest);
|
|
358
|
+
|
|
359
|
+
// there is not much we can check, but we mainly want to make
|
|
360
|
+
// sure that it doesn't crash
|
|
361
|
+
td.handleTurnDiscoveryResponse({
|
|
362
|
+
headers: [
|
|
363
|
+
`x-cisco-turn-url=${FAKE_TURN_URL}`,
|
|
364
|
+
`x-cisco-turn-username=${FAKE_TURN_USERNAME}`,
|
|
365
|
+
`x-cisco-turn-password=${FAKE_TURN_PASSWORD}`,
|
|
366
|
+
],
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
assert.notCalled(mockRoapRequest.sendRoap);
|
|
370
|
+
});
|
|
371
|
+
});
|
|
372
|
+
});
|