@webex/plugin-meetings 3.8.0 → 3.8.1-next.10
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 +26 -13
- package/dist/breakouts/breakout.js +1 -1
- package/dist/breakouts/index.js +70 -6
- package/dist/breakouts/index.js.map +1 -1
- package/dist/common/errors/webex-errors.js +12 -2
- package/dist/common/errors/webex-errors.js.map +1 -1
- package/dist/config.js +5 -1
- package/dist/config.js.map +1 -1
- package/dist/constants.js +28 -123
- package/dist/constants.js.map +1 -1
- package/dist/controls-options-manager/enums.js +3 -0
- package/dist/controls-options-manager/enums.js.map +1 -1
- package/dist/controls-options-manager/types.js.map +1 -1
- package/dist/controls-options-manager/util.js +78 -0
- package/dist/controls-options-manager/util.js.map +1 -1
- package/dist/interpretation/index.js +4 -4
- package/dist/interpretation/index.js.map +1 -1
- package/dist/interpretation/siLanguage.js +1 -1
- package/dist/locus-info/controlsUtils.js +37 -11
- package/dist/locus-info/controlsUtils.js.map +1 -1
- package/dist/locus-info/index.js +92 -12
- package/dist/locus-info/index.js.map +1 -1
- package/dist/locus-info/selfUtils.js +432 -418
- package/dist/locus-info/selfUtils.js.map +1 -1
- package/dist/media/index.js +17 -17
- package/dist/media/index.js.map +1 -1
- package/dist/media/properties.js +94 -6
- package/dist/media/properties.js.map +1 -1
- package/dist/meeting/brbState.js +9 -2
- package/dist/meeting/brbState.js.map +1 -1
- package/dist/meeting/in-meeting-actions.js +21 -1
- package/dist/meeting/in-meeting-actions.js.map +1 -1
- package/dist/meeting/index.js +678 -344
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/locusMediaRequest.js +21 -22
- package/dist/meeting/locusMediaRequest.js.map +1 -1
- package/dist/meeting/muteState.js +4 -4
- package/dist/meeting/muteState.js.map +1 -1
- package/dist/meeting/request.js +30 -0
- package/dist/meeting/request.js.map +1 -1
- package/dist/meeting/request.type.js.map +1 -1
- package/dist/meeting/util.js +13 -2
- package/dist/meeting/util.js.map +1 -1
- package/dist/meeting-info/meeting-info-v2.js +373 -68
- package/dist/meeting-info/meeting-info-v2.js.map +1 -1
- package/dist/meeting-info/utilv2.js +5 -1
- package/dist/meeting-info/utilv2.js.map +1 -1
- package/dist/meetings/index.js +136 -1
- package/dist/meetings/index.js.map +1 -1
- package/dist/meetings/util.js +14 -0
- package/dist/meetings/util.js.map +1 -1
- package/dist/member/index.js +55 -9
- package/dist/member/index.js.map +1 -1
- package/dist/member/types.js +3 -0
- package/dist/member/types.js.map +1 -1
- package/dist/member/util.js +335 -353
- package/dist/member/util.js.map +1 -1
- package/dist/members/collection.js.map +1 -1
- package/dist/members/index.js +137 -29
- package/dist/members/index.js.map +1 -1
- package/dist/members/request.js +38 -0
- package/dist/members/request.js.map +1 -1
- package/dist/members/util.js +36 -1
- package/dist/members/util.js.map +1 -1
- package/dist/metrics/constants.js +10 -0
- package/dist/metrics/constants.js.map +1 -1
- package/dist/multistream/remoteMediaManager.js +40 -8
- package/dist/multistream/remoteMediaManager.js.map +1 -1
- package/dist/reachability/clusterReachability.js +63 -27
- package/dist/reachability/clusterReachability.js.map +1 -1
- package/dist/reachability/index.js +107 -47
- package/dist/reachability/index.js.map +1 -1
- package/dist/reachability/reachability.types.js +14 -0
- package/dist/reachability/reachability.types.js.map +1 -1
- package/dist/reachability/request.js +19 -3
- package/dist/reachability/request.js.map +1 -1
- package/dist/reconnection-manager/index.js +2 -2
- package/dist/reconnection-manager/index.js.map +1 -1
- package/dist/recording-controller/util.js +5 -5
- package/dist/recording-controller/util.js.map +1 -1
- package/dist/roap/index.js.map +1 -1
- package/dist/roap/turnDiscovery.js +45 -27
- package/dist/roap/turnDiscovery.js.map +1 -1
- package/dist/roap/types.js +17 -0
- package/dist/roap/types.js.map +1 -0
- package/dist/types/common/errors/webex-errors.d.ts +7 -1
- package/dist/types/config.d.ts +3 -0
- package/dist/types/constants.d.ts +20 -85
- package/dist/types/controls-options-manager/enums.d.ts +4 -1
- package/dist/types/controls-options-manager/types.d.ts +10 -1
- package/dist/types/locus-info/index.d.ts +3 -3
- package/dist/types/locus-info/selfUtils.d.ts +216 -1
- package/dist/types/media/properties.d.ts +15 -0
- package/dist/types/meeting/in-meeting-actions.d.ts +20 -0
- package/dist/types/meeting/index.d.ts +65 -1
- package/dist/types/meeting/muteState.d.ts +0 -1
- package/dist/types/meeting/request.d.ts +12 -1
- package/dist/types/meeting/request.type.d.ts +6 -0
- package/dist/types/meeting/util.d.ts +3 -1
- package/dist/types/meeting-info/meeting-info-v2.d.ts +82 -1
- package/dist/types/meetings/index.d.ts +57 -0
- package/dist/types/member/index.d.ts +21 -6
- package/dist/types/member/types.d.ts +73 -14
- package/dist/types/member/util.d.ts +156 -1
- package/dist/types/members/collection.d.ts +6 -5
- package/dist/types/members/index.d.ts +32 -43
- package/dist/types/members/request.d.ts +26 -0
- package/dist/types/members/util.d.ts +27 -0
- package/dist/types/metrics/constants.d.ts +10 -0
- package/dist/types/multistream/remoteMediaManager.d.ts +10 -1
- package/dist/types/reachability/clusterReachability.d.ts +15 -7
- package/dist/types/reachability/index.d.ts +10 -1
- package/dist/types/reachability/reachability.types.d.ts +5 -0
- package/dist/types/roap/index.d.ts +3 -2
- package/dist/types/roap/turnDiscovery.d.ts +5 -17
- package/dist/types/roap/types.d.ts +16 -0
- package/dist/webinar/index.js +2 -2
- package/dist/webinar/index.js.map +1 -1
- package/package.json +24 -23
- package/src/breakouts/index.ts +69 -0
- package/src/common/errors/webex-errors.ts +8 -1
- package/src/config.ts +3 -0
- package/src/constants.ts +30 -90
- package/src/controls-options-manager/enums.ts +3 -0
- package/src/controls-options-manager/types.ts +16 -1
- package/src/controls-options-manager/util.ts +93 -0
- package/src/interpretation/index.ts +3 -3
- package/src/locus-info/controlsUtils.ts +59 -14
- package/src/locus-info/index.ts +97 -13
- package/src/locus-info/selfUtils.ts +496 -442
- package/src/media/index.ts +23 -21
- package/src/media/properties.ts +96 -0
- package/src/meeting/brbState.ts +11 -2
- package/src/meeting/in-meeting-actions.ts +40 -0
- package/src/meeting/index.ts +470 -105
- package/src/meeting/locusMediaRequest.ts +27 -22
- package/src/meeting/muteState.ts +4 -4
- package/src/meeting/request.ts +36 -1
- package/src/meeting/request.type.ts +7 -0
- package/src/meeting/util.ts +11 -2
- package/src/meeting-info/meeting-info-v2.ts +254 -8
- package/src/meeting-info/utilv2.ts +5 -0
- package/src/meetings/index.ts +148 -1
- package/src/meetings/util.ts +18 -0
- package/src/member/index.ts +68 -22
- package/src/member/types.ts +82 -16
- package/src/member/util.ts +357 -350
- package/src/members/collection.ts +4 -3
- package/src/members/index.ts +137 -18
- package/src/members/request.ts +44 -0
- package/src/members/util.ts +43 -1
- package/src/metrics/constants.ts +10 -0
- package/src/multistream/remoteMediaManager.ts +32 -10
- package/src/reachability/clusterReachability.ts +73 -26
- package/src/reachability/index.ts +62 -1
- package/src/reachability/reachability.types.ts +6 -0
- package/src/reachability/request.ts +7 -0
- package/src/reconnection-manager/index.ts +2 -2
- package/src/recording-controller/util.ts +17 -13
- package/src/roap/index.ts +3 -7
- package/src/roap/turnDiscovery.ts +34 -39
- package/src/roap/types.ts +23 -0
- package/src/webinar/index.ts +1 -1
- package/test/unit/spec/breakouts/index.ts +167 -95
- package/test/unit/spec/controls-options-manager/util.js +178 -0
- package/test/unit/spec/interpretation/index.ts +39 -1
- package/test/unit/spec/locus-info/controlsUtils.js +155 -9
- package/test/unit/spec/locus-info/index.js +209 -73
- package/test/unit/spec/locus-info/selfUtils.js +98 -24
- package/test/unit/spec/media/index.ts +150 -18
- package/test/unit/spec/media/properties.ts +130 -0
- package/test/unit/spec/meeting/brbState.ts +40 -2
- package/test/unit/spec/meeting/in-meeting-actions.ts +23 -4
- package/test/unit/spec/meeting/index.js +804 -139
- package/test/unit/spec/meeting/locusMediaRequest.ts +95 -87
- package/test/unit/spec/meeting/muteState.js +73 -2
- package/test/unit/spec/meeting/request.js +32 -1
- package/test/unit/spec/meeting/utils.js +119 -18
- package/test/unit/spec/meeting-info/meetinginfov2.js +484 -114
- package/test/unit/spec/meeting-info/utilv2.js +19 -0
- package/test/unit/spec/meetings/index.js +146 -2
- package/test/unit/spec/member/index.js +7 -0
- package/test/unit/spec/member/util.js +24 -0
- package/test/unit/spec/members/index.js +304 -78
- package/test/unit/spec/members/request.js +68 -22
- package/test/unit/spec/members/utils.js +75 -0
- package/test/unit/spec/multistream/remoteMediaManager.ts +397 -118
- package/test/unit/spec/reachability/clusterReachability.ts +88 -56
- package/test/unit/spec/reachability/index.ts +97 -0
- package/test/unit/spec/reachability/request.js +47 -2
- package/test/unit/spec/reconnection-manager/index.js +4 -4
- package/test/unit/spec/roap/turnDiscovery.ts +110 -28
- package/test/unit/spec/webinar/index.ts +5 -0
- package/dist/annotation/annotation.types.d.ts +0 -42
- package/dist/annotation/constants.d.ts +0 -31
- package/dist/annotation/index.d.ts +0 -117
- package/dist/breakouts/breakout.d.ts +0 -8
- package/dist/breakouts/collection.d.ts +0 -5
- package/dist/breakouts/edit-lock-error.d.ts +0 -15
- package/dist/breakouts/events.d.ts +0 -8
- package/dist/breakouts/index.d.ts +0 -5
- package/dist/breakouts/request.d.ts +0 -22
- package/dist/breakouts/utils.d.ts +0 -15
- package/dist/common/browser-detection.d.ts +0 -9
- package/dist/common/collection.d.ts +0 -48
- package/dist/common/config.d.ts +0 -2
- package/dist/common/errors/captcha-error.d.ts +0 -15
- package/dist/common/errors/intent-to-join.d.ts +0 -16
- package/dist/common/errors/join-meeting.d.ts +0 -17
- package/dist/common/errors/media.d.ts +0 -15
- package/dist/common/errors/no-meeting-info.d.ts +0 -14
- package/dist/common/errors/parameter.d.ts +0 -15
- package/dist/common/errors/password-error.d.ts +0 -15
- package/dist/common/errors/permission.d.ts +0 -14
- package/dist/common/errors/reclaim-host-role-error.js +0 -149
- package/dist/common/errors/reclaim-host-role-error.js.map +0 -1
- package/dist/common/errors/reclaim-host-role-errors.d.ts +0 -60
- package/dist/common/errors/reconnection-in-progress.d.ts +0 -9
- package/dist/common/errors/reconnection-in-progress.js +0 -33
- package/dist/common/errors/reconnection-in-progress.js.map +0 -1
- package/dist/common/errors/reconnection.d.ts +0 -15
- package/dist/common/errors/stats.d.ts +0 -15
- package/dist/common/errors/webex-errors.d.ts +0 -93
- package/dist/common/errors/webex-meetings-error.d.ts +0 -20
- package/dist/common/events/events-scope.d.ts +0 -17
- package/dist/common/events/events.d.ts +0 -12
- package/dist/common/events/trigger-proxy.d.ts +0 -2
- package/dist/common/events/util.d.ts +0 -2
- package/dist/common/logs/logger-config.d.ts +0 -2
- package/dist/common/logs/logger-proxy.d.ts +0 -2
- package/dist/common/logs/request.d.ts +0 -36
- package/dist/common/queue.d.ts +0 -34
- package/dist/config.d.ts +0 -72
- package/dist/constants.d.ts +0 -1088
- package/dist/controls-options-manager/constants.d.ts +0 -4
- package/dist/controls-options-manager/enums.d.ts +0 -15
- package/dist/controls-options-manager/index.d.ts +0 -136
- package/dist/controls-options-manager/types.d.ts +0 -43
- package/dist/controls-options-manager/util.d.ts +0 -1
- package/dist/index.d.ts +0 -7
- package/dist/interceptors/index.d.ts +0 -2
- package/dist/interceptors/locusRetry.d.ts +0 -27
- package/dist/interpretation/collection.d.ts +0 -5
- package/dist/interpretation/index.d.ts +0 -5
- package/dist/interpretation/siLanguage.d.ts +0 -5
- package/dist/locus-info/controlsUtils.d.ts +0 -2
- package/dist/locus-info/embeddedAppsUtils.d.ts +0 -2
- package/dist/locus-info/fullState.d.ts +0 -2
- package/dist/locus-info/hostUtils.d.ts +0 -2
- package/dist/locus-info/index.d.ts +0 -322
- package/dist/locus-info/infoUtils.d.ts +0 -2
- package/dist/locus-info/mediaSharesUtils.d.ts +0 -2
- package/dist/locus-info/parser.d.ts +0 -272
- package/dist/locus-info/selfUtils.d.ts +0 -2
- package/dist/media/index.d.ts +0 -34
- package/dist/media/properties.d.ts +0 -93
- package/dist/media/util.d.ts +0 -2
- package/dist/mediaQualityMetrics/config.d.ts +0 -241
- package/dist/mediaQualityMetrics/config.js +0 -502
- package/dist/mediaQualityMetrics/config.js.map +0 -1
- package/dist/meeting/effectsState.js +0 -260
- package/dist/meeting/effectsState.js.map +0 -1
- package/dist/meeting/in-meeting-actions.d.ts +0 -167
- package/dist/meeting/index.d.ts +0 -1825
- package/dist/meeting/locusMediaRequest.d.ts +0 -74
- package/dist/meeting/muteState.d.ts +0 -178
- package/dist/meeting/request.d.ts +0 -295
- package/dist/meeting/request.type.d.ts +0 -11
- package/dist/meeting/state.d.ts +0 -9
- package/dist/meeting/util.d.ts +0 -119
- package/dist/meeting/voicea-meeting.d.ts +0 -16
- package/dist/meeting-info/collection.d.ts +0 -20
- package/dist/meeting-info/index.d.ts +0 -69
- package/dist/meeting-info/meeting-info-v2.d.ts +0 -123
- package/dist/meeting-info/request.d.ts +0 -22
- package/dist/meeting-info/util.d.ts +0 -2
- package/dist/meeting-info/utilv2.d.ts +0 -2
- package/dist/meetings/collection.d.ts +0 -40
- package/dist/meetings/index.d.ts +0 -390
- package/dist/meetings/meetings.types.d.ts +0 -4
- package/dist/meetings/request.d.ts +0 -27
- package/dist/meetings/util.d.ts +0 -18
- package/dist/member/index.d.ts +0 -160
- package/dist/member/member.types.js +0 -17
- package/dist/member/member.types.js.map +0 -1
- package/dist/member/types.d.ts +0 -32
- package/dist/member/util.d.ts +0 -2
- package/dist/members/collection.d.ts +0 -29
- package/dist/members/index.d.ts +0 -353
- package/dist/members/request.d.ts +0 -114
- package/dist/members/types.d.ts +0 -25
- package/dist/members/util.d.ts +0 -215
- package/dist/metrics/config.js +0 -276
- package/dist/metrics/config.js.map +0 -1
- package/dist/metrics/constants.d.ts +0 -70
- package/dist/metrics/index.d.ts +0 -45
- package/dist/multistream/mediaRequestManager.d.ts +0 -119
- package/dist/multistream/receiveSlot.d.ts +0 -68
- package/dist/multistream/receiveSlotManager.d.ts +0 -56
- package/dist/multistream/remoteMedia.d.ts +0 -72
- package/dist/multistream/remoteMediaGroup.d.ts +0 -49
- package/dist/multistream/remoteMediaManager.d.ts +0 -300
- package/dist/multistream/sendSlotManager.d.ts +0 -69
- package/dist/networkQualityMonitor/index.d.ts +0 -70
- package/dist/networkQualityMonitor/index.js +0 -221
- package/dist/networkQualityMonitor/index.js.map +0 -1
- package/dist/peer-connection-manager/index.js +0 -671
- package/dist/peer-connection-manager/index.js.map +0 -1
- package/dist/peer-connection-manager/util.js +0 -109
- package/dist/peer-connection-manager/util.js.map +0 -1
- package/dist/personal-meeting-room/index.d.ts +0 -47
- package/dist/personal-meeting-room/request.d.ts +0 -14
- package/dist/personal-meeting-room/util.d.ts +0 -2
- package/dist/reachability/clusterReachability.d.ts +0 -109
- package/dist/reachability/index.d.ts +0 -105
- package/dist/reachability/request.d.ts +0 -39
- package/dist/reachability/util.d.ts +0 -8
- package/dist/reactions/constants.d.ts +0 -3
- package/dist/reactions/reactions.d.ts +0 -4
- package/dist/reactions/reactions.type.d.ts +0 -52
- package/dist/reconnection-manager/index.d.ts +0 -136
- package/dist/recording-controller/enums.d.ts +0 -7
- package/dist/recording-controller/index.d.ts +0 -207
- package/dist/recording-controller/util.d.ts +0 -14
- package/dist/roap/collection.js +0 -62
- package/dist/roap/collection.js.map +0 -1
- package/dist/roap/handler.js +0 -275
- package/dist/roap/handler.js.map +0 -1
- package/dist/roap/index.d.ts +0 -86
- package/dist/roap/request.d.ts +0 -39
- package/dist/roap/state.js +0 -126
- package/dist/roap/state.js.map +0 -1
- package/dist/roap/turnDiscovery.d.ts +0 -155
- package/dist/roap/util.js +0 -75
- package/dist/roap/util.js.map +0 -1
- package/dist/rtcMetrics/constants.d.ts +0 -4
- package/dist/rtcMetrics/constants.js +0 -11
- package/dist/rtcMetrics/constants.js.map +0 -1
- package/dist/rtcMetrics/index.d.ts +0 -61
- package/dist/rtcMetrics/index.js +0 -197
- package/dist/rtcMetrics/index.js.map +0 -1
- package/dist/statsAnalyzer/global.d.ts +0 -36
- package/dist/statsAnalyzer/global.js +0 -126
- package/dist/statsAnalyzer/global.js.map +0 -1
- package/dist/statsAnalyzer/index.d.ts +0 -217
- package/dist/statsAnalyzer/index.js +0 -1013
- package/dist/statsAnalyzer/index.js.map +0 -1
- package/dist/statsAnalyzer/mqaUtil.d.ts +0 -48
- package/dist/statsAnalyzer/mqaUtil.js +0 -179
- package/dist/statsAnalyzer/mqaUtil.js.map +0 -1
- package/dist/transcription/index.d.ts +0 -64
- package/dist/types/common/errors/reconnection-in-progress.d.ts +0 -9
- package/dist/types/mediaQualityMetrics/config.d.ts +0 -241
- package/dist/types/networkQualityMonitor/index.d.ts +0 -70
- package/dist/types/rtcMetrics/constants.d.ts +0 -4
- package/dist/types/rtcMetrics/index.d.ts +0 -71
- package/dist/types/statsAnalyzer/global.d.ts +0 -36
- package/dist/types/statsAnalyzer/index.d.ts +0 -217
- package/dist/types/statsAnalyzer/mqaUtil.d.ts +0 -48
- package/dist/webinar/collection.d.ts +0 -16
- package/dist/webinar/index.d.ts +0 -5
@@ -1,10 +1,11 @@
|
|
1
1
|
import {MEETINGS} from '../constants';
|
2
|
+
import Member from '../member';
|
2
3
|
|
3
4
|
/**
|
4
5
|
* @class MembersCollection
|
5
6
|
*/
|
6
7
|
export default class MembersCollection {
|
7
|
-
members:
|
8
|
+
members: Record<string, Member>;
|
8
9
|
namespace = MEETINGS;
|
9
10
|
/**
|
10
11
|
* @param {Object} locus
|
@@ -14,11 +15,11 @@ export default class MembersCollection {
|
|
14
15
|
this.members = {};
|
15
16
|
}
|
16
17
|
|
17
|
-
set(id, member) {
|
18
|
+
set(id: string, member: Member) {
|
18
19
|
this.members[id] = member;
|
19
20
|
}
|
20
21
|
|
21
|
-
setAll(members) {
|
22
|
+
setAll(members: Record<string, Member>) {
|
22
23
|
this.members = members;
|
23
24
|
}
|
24
25
|
|
package/src/members/index.ts
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
/*!
|
2
2
|
* Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
|
3
3
|
*/
|
4
|
-
import {isEmpty} from 'lodash';
|
4
|
+
import {get, isEmpty, set} from 'lodash';
|
5
5
|
// @ts-ignore
|
6
6
|
import {StatelessWebexPlugin} from '@webex/webex-core';
|
7
7
|
|
@@ -73,6 +73,7 @@ import {ServerRoleShape} from './types';
|
|
73
73
|
* @memberof Members
|
74
74
|
*/
|
75
75
|
|
76
|
+
type UpdatedMembers = {added: Array<Member>; updated: Array<Member>};
|
76
77
|
/**
|
77
78
|
* @class Members
|
78
79
|
*/
|
@@ -81,7 +82,7 @@ export default class Members extends StatelessWebexPlugin {
|
|
81
82
|
locusUrl: any;
|
82
83
|
mediaShareContentId: any;
|
83
84
|
mediaShareWhiteboardId: any;
|
84
|
-
membersCollection:
|
85
|
+
membersCollection: MembersCollection;
|
85
86
|
membersRequest: any;
|
86
87
|
receiveSlotManager: ReceiveSlotManager;
|
87
88
|
mediaRequestManagers: {
|
@@ -321,6 +322,63 @@ export default class Members extends StatelessWebexPlugin {
|
|
321
322
|
);
|
322
323
|
}
|
323
324
|
|
325
|
+
/**
|
326
|
+
* Updates properties on members that rely on information from other members.
|
327
|
+
* This function MUST be called only after the membersCollection has been fully updated
|
328
|
+
* @param {UpdatedMembers} membersUpdate
|
329
|
+
* @returns {Object} membersCollection
|
330
|
+
* @private
|
331
|
+
* @memberof Members
|
332
|
+
*/
|
333
|
+
private updateRelationsBetweenMembers(membersUpdate: UpdatedMembers) {
|
334
|
+
const updatePairedMembers = (membersList: Member[]) => {
|
335
|
+
membersList.forEach((member) => {
|
336
|
+
if (!member.pairedWith.participantUrl) {
|
337
|
+
// if we don't have a participantUrl set, it may be that we had it in the past and not anymore, so cleanup the rest of the data
|
338
|
+
if (member.pairedWith.memberId) {
|
339
|
+
const pairedMember = this.membersCollection.get(member.pairedWith.memberId);
|
340
|
+
|
341
|
+
if (pairedMember) {
|
342
|
+
// remove member from pairedMember's associatedUsers array
|
343
|
+
pairedMember.associatedUsers.delete(member.id);
|
344
|
+
|
345
|
+
if (pairedMember.associatedUser === member.id) {
|
346
|
+
pairedMember.associatedUser = null;
|
347
|
+
}
|
348
|
+
|
349
|
+
// reset all the props that we set on pairedMember
|
350
|
+
pairedMember.isPairedWithSelf = false;
|
351
|
+
pairedMember.isHost = false;
|
352
|
+
}
|
353
|
+
}
|
354
|
+
member.pairedWith.memberId = undefined;
|
355
|
+
} else if (member.pairedWith.memberId === undefined) {
|
356
|
+
// we have participantUrl set but not memberId, so find the member and set it
|
357
|
+
const pairedMember = Object.values(this.membersCollection.getAll()).find(
|
358
|
+
(m) => m.participant?.url === member.pairedWith.participantUrl
|
359
|
+
);
|
360
|
+
|
361
|
+
if (pairedMember) {
|
362
|
+
member.pairedWith.memberId = pairedMember.id;
|
363
|
+
pairedMember.associatedUsers.add(member.id);
|
364
|
+
|
365
|
+
if (pairedMember.associatedUsers.size === 1) {
|
366
|
+
// associatedUser is deprecated, because it's broken - device can have multiple associated users,
|
367
|
+
// so for backwards compatibility we set it to the first associated user
|
368
|
+
pairedMember.associatedUser = member.id;
|
369
|
+
}
|
370
|
+
|
371
|
+
pairedMember.isPairedWithSelf = member.isSelf;
|
372
|
+
pairedMember.isHost = member.isHost;
|
373
|
+
}
|
374
|
+
}
|
375
|
+
});
|
376
|
+
};
|
377
|
+
|
378
|
+
updatePairedMembers(membersUpdate.updated);
|
379
|
+
updatePairedMembers(membersUpdate.added);
|
380
|
+
}
|
381
|
+
|
324
382
|
/**
|
325
383
|
* when new participant updates come in, both delta and full participants, update them in members collection
|
326
384
|
* delta object in the event will have {updated, added} and full will be the full membersCollection
|
@@ -338,6 +396,8 @@ export default class Members extends StatelessWebexPlugin {
|
|
338
396
|
const delta = this.handleLocusInfoUpdatedParticipants(payload);
|
339
397
|
const full = this.handleMembersUpdate(delta); // SDK should propagate the full list for both delta and non delta updates
|
340
398
|
|
399
|
+
this.updateRelationsBetweenMembers(delta);
|
400
|
+
|
341
401
|
this.receiveSlotManager?.updateMemberIds();
|
342
402
|
|
343
403
|
Trigger.trigger(
|
@@ -478,20 +538,14 @@ export default class Members extends StatelessWebexPlugin {
|
|
478
538
|
|
479
539
|
/**
|
480
540
|
* sets values in the members collection for updated and added properties from delta
|
481
|
-
* @param {
|
541
|
+
* @param {UpdatedMembers} membersUpdate
|
482
542
|
* @returns {Object} membersCollection
|
483
543
|
* @private
|
484
544
|
* @memberof Members
|
485
545
|
*/
|
486
|
-
private handleMembersUpdate(membersUpdate:
|
487
|
-
|
488
|
-
|
489
|
-
this.constructMembers(membersUpdate.updated);
|
490
|
-
}
|
491
|
-
if (membersUpdate.added) {
|
492
|
-
this.constructMembers(membersUpdate.added);
|
493
|
-
}
|
494
|
-
}
|
546
|
+
private handleMembersUpdate(membersUpdate: UpdatedMembers) {
|
547
|
+
this.constructMembers(membersUpdate.updated, true);
|
548
|
+
this.constructMembers(membersUpdate.added, false);
|
495
549
|
|
496
550
|
return this.membersCollection.getAll();
|
497
551
|
}
|
@@ -499,12 +553,30 @@ export default class Members extends StatelessWebexPlugin {
|
|
499
553
|
/**
|
500
554
|
* set members to the member collection from each updated/added lists as passed in
|
501
555
|
* @param {Array} list
|
556
|
+
* @param {boolean} isUpdate
|
502
557
|
* @returns {undefined}
|
503
558
|
* @private
|
504
559
|
* @memberof Members
|
505
560
|
*/
|
506
|
-
private constructMembers(list: Array<any
|
561
|
+
private constructMembers(list: Array<any>, isUpdate: boolean) {
|
507
562
|
list.forEach((member) => {
|
563
|
+
if (isUpdate) {
|
564
|
+
// some member props are generated by SDK and need to be preserved on update,
|
565
|
+
// because they depend on relationships with other members so they need to be handled
|
566
|
+
// at the end, once all members are updated - this is done in updateRelationsBetweenMembers()
|
567
|
+
const propsToKeepOnUpdate = ['pairedWith.memberId'];
|
568
|
+
|
569
|
+
const existingMember = this.membersCollection.get(member.id);
|
570
|
+
if (existingMember) {
|
571
|
+
propsToKeepOnUpdate.forEach((prop) => {
|
572
|
+
const existingValue = get(existingMember, prop);
|
573
|
+
|
574
|
+
if (existingValue !== undefined) {
|
575
|
+
set(member, prop, existingValue);
|
576
|
+
}
|
577
|
+
});
|
578
|
+
}
|
579
|
+
}
|
508
580
|
this.membersCollection.set(member.id, member);
|
509
581
|
});
|
510
582
|
}
|
@@ -512,11 +584,11 @@ export default class Members extends StatelessWebexPlugin {
|
|
512
584
|
/**
|
513
585
|
* Internal update the participants value
|
514
586
|
* @param {Object} payload
|
515
|
-
* @returns {
|
587
|
+
* @returns {UpdatedMembers}
|
516
588
|
* @private
|
517
589
|
* @memberof Members
|
518
590
|
*/
|
519
|
-
private handleLocusInfoUpdatedParticipants(payload: any) {
|
591
|
+
private handleLocusInfoUpdatedParticipants(payload: any): UpdatedMembers {
|
520
592
|
this.hostId = payload.hostId || this.hostId;
|
521
593
|
this.selfId = payload.selfId || this.selfId;
|
522
594
|
this.recordingId = payload.recordingId;
|
@@ -681,12 +753,12 @@ export default class Members extends StatelessWebexPlugin {
|
|
681
753
|
* Removed/left members will end up in updates
|
682
754
|
* Each array contains only members
|
683
755
|
* @param {Array} participants the locus participants
|
684
|
-
* @returns {
|
756
|
+
* @returns {UpdatedMembers} {added: {Array}, updated: {Array}}
|
685
757
|
* @private
|
686
758
|
* @memberof Members
|
687
759
|
*/
|
688
|
-
private update(participants: Array<any>) {
|
689
|
-
const membersUpdate = {added: [], updated: []};
|
760
|
+
private update(participants: Array<any>): UpdatedMembers {
|
761
|
+
const membersUpdate: UpdatedMembers = {added: [], updated: []};
|
690
762
|
|
691
763
|
if (participants) {
|
692
764
|
participants.forEach((participant) => {
|
@@ -773,6 +845,28 @@ export default class Members extends StatelessWebexPlugin {
|
|
773
845
|
return this.membersRequest.cancelPhoneInvite(options);
|
774
846
|
}
|
775
847
|
|
848
|
+
/**
|
849
|
+
* Cancels an SIP call to the associated meeting
|
850
|
+
* @param {String} invitee
|
851
|
+
* @returns {Promise}
|
852
|
+
* @memberof Members
|
853
|
+
*/
|
854
|
+
cancelSIPInvite(invitee: any) {
|
855
|
+
if (!this.locusUrl) {
|
856
|
+
return Promise.reject(
|
857
|
+
new ParameterError('The associated locus url for this meeting object must be defined.')
|
858
|
+
);
|
859
|
+
}
|
860
|
+
if (!invitee?.memberId) {
|
861
|
+
return Promise.reject(
|
862
|
+
new ParameterError('The invitee must be defined with a memberId property.')
|
863
|
+
);
|
864
|
+
}
|
865
|
+
const options = MembersUtil.cancelSIPInviteOptions(invitee, this.locusUrl);
|
866
|
+
|
867
|
+
return this.membersRequest.cancelSIPInvite(options);
|
868
|
+
}
|
869
|
+
|
776
870
|
/**
|
777
871
|
* Admits waiting members (invited guests to meeting)
|
778
872
|
* @param {Array} memberIds
|
@@ -886,6 +980,31 @@ export default class Members extends StatelessWebexPlugin {
|
|
886
980
|
});
|
887
981
|
}
|
888
982
|
|
983
|
+
/**
|
984
|
+
* Moves a meeting member into the lobby.
|
985
|
+
* @param {String} memberId -- The ID of the member to move.
|
986
|
+
* @returns {Promise} -- Resolves with the lobby‐move response.
|
987
|
+
* @public
|
988
|
+
* @memberof Members
|
989
|
+
*/
|
990
|
+
public moveToLobby(memberId: string) {
|
991
|
+
if (!this.locusUrl) {
|
992
|
+
return Promise.reject(
|
993
|
+
new ParameterError(
|
994
|
+
'The associated locus url for this meetings members object must be defined.'
|
995
|
+
)
|
996
|
+
);
|
997
|
+
}
|
998
|
+
if (!memberId) {
|
999
|
+
return Promise.reject(
|
1000
|
+
new ParameterError('The member id must be defined to move the member to lobby.')
|
1001
|
+
);
|
1002
|
+
}
|
1003
|
+
const body = MembersUtil.getMoveMemberToLobbyRequestBody(memberId);
|
1004
|
+
|
1005
|
+
return this.membersRequest.moveToLobbyMember({locusUrl: this.locusUrl, memberId}, body);
|
1006
|
+
}
|
1007
|
+
|
889
1008
|
/**
|
890
1009
|
* Raise or lower the hand of a member in a meeting
|
891
1010
|
* @param {String} memberId
|
package/src/members/request.ts
CHANGED
@@ -129,6 +129,32 @@ export default class MembersRequest extends StatelessWebexPlugin {
|
|
129
129
|
return this.locusDeltaRequest(requestParams);
|
130
130
|
}
|
131
131
|
|
132
|
+
/**
|
133
|
+
* Sends a request to move a meeting member into the lobby.
|
134
|
+
* *
|
135
|
+
* @param {Object} options - Request options.
|
136
|
+
* @param {string} options.locusUrl - The locus URL for the meeting.
|
137
|
+
* @param {string} options.memberId - The ID of the member to move.
|
138
|
+
* @param {Object} body - The request payload.
|
139
|
+
* @param {Object} body.moveToLobby - Container for move‐to‐lobby data.
|
140
|
+
* @param {string[]} body.moveToLobby.participantIds - Array of participant IDs to move.
|
141
|
+
* @returns {Promise} - Resolves with the locus‐delta response.
|
142
|
+
*/
|
143
|
+
moveToLobbyMember(
|
144
|
+
options: {locusUrl: string; memberId: string},
|
145
|
+
body: {moveToLobby: {participantIds: string[]}}
|
146
|
+
) {
|
147
|
+
if (!options || !options.locusUrl || !options.memberId) {
|
148
|
+
throw new ParameterError(
|
149
|
+
'memberId must be defined, and the associated locus url for this meeting object must be defined.'
|
150
|
+
);
|
151
|
+
}
|
152
|
+
|
153
|
+
const requestParams = MembersUtil.getMoveMemberToLobbyRequestParams(options, body);
|
154
|
+
|
155
|
+
return this.locusDeltaRequest(requestParams);
|
156
|
+
}
|
157
|
+
|
132
158
|
/**
|
133
159
|
* Sends a request to raise or lower a member's hand
|
134
160
|
* @param {Object} options
|
@@ -252,4 +278,22 @@ export default class MembersRequest extends StatelessWebexPlugin {
|
|
252
278
|
|
253
279
|
return this.locusDeltaRequest(requestParams);
|
254
280
|
}
|
281
|
+
|
282
|
+
/**
|
283
|
+
* @param {Object} options with format of {invitee: object, locusUrl: string}
|
284
|
+
* @returns {Promise}
|
285
|
+
* @throws {Error} if the options are not valid and complete, must have invitee with memberId AND locusUrl
|
286
|
+
* @memberof MembersRequest
|
287
|
+
*/
|
288
|
+
cancelSIPInvite(options: any) {
|
289
|
+
if (!options?.invitee?.memberId || !options?.locusUrl) {
|
290
|
+
throw new ParameterError(
|
291
|
+
'invitee must be passed and the associated locus url for this meeting object must be defined.'
|
292
|
+
);
|
293
|
+
}
|
294
|
+
|
295
|
+
const requestParams = MembersUtil.generateCancelSIPInviteRequestParams(options);
|
296
|
+
|
297
|
+
return this.locusDeltaRequest(requestParams);
|
298
|
+
}
|
255
299
|
}
|
package/src/members/util.ts
CHANGED
@@ -110,7 +110,10 @@ const MembersUtil = {
|
|
110
110
|
return !DIALER_REGEX.E164_FORMAT.test(invitee.phoneNumber);
|
111
111
|
}
|
112
112
|
|
113
|
-
return !
|
113
|
+
return !(
|
114
|
+
VALID_EMAIL_ADDRESS.test(invitee.email || invitee.emailAddress) ||
|
115
|
+
DIALER_REGEX.SIP_ADDRESS.test(invitee.email || invitee.emailAddress)
|
116
|
+
);
|
114
117
|
},
|
115
118
|
|
116
119
|
getRemoveMemberRequestParams: (options) => {
|
@@ -203,6 +206,22 @@ const MembersUtil = {
|
|
203
206
|
};
|
204
207
|
},
|
205
208
|
|
209
|
+
getMoveMemberToLobbyRequestBody: (memberId: string) => ({
|
210
|
+
moveToLobby: {
|
211
|
+
participantIds: [memberId],
|
212
|
+
},
|
213
|
+
}),
|
214
|
+
|
215
|
+
getMoveMemberToLobbyRequestParams: (options: {memberId: string; locusUrl: string}, body) => {
|
216
|
+
const uri = `${options.locusUrl}/${PARTICIPANT}/${options.memberId}/${CONTROLS}`;
|
217
|
+
|
218
|
+
return {
|
219
|
+
method: HTTP_VERBS.PATCH,
|
220
|
+
uri,
|
221
|
+
body,
|
222
|
+
};
|
223
|
+
},
|
224
|
+
|
206
225
|
/**
|
207
226
|
* @param {ServerRoleShape} role
|
208
227
|
* @returns {ServerRoleShape} the role shape to be added to the body
|
@@ -351,6 +370,29 @@ const MembersUtil = {
|
|
351
370
|
|
352
371
|
return requestParams;
|
353
372
|
},
|
373
|
+
|
374
|
+
cancelSIPInviteOptions: (invitee, locusUrl) => ({
|
375
|
+
invitee,
|
376
|
+
locusUrl,
|
377
|
+
}),
|
378
|
+
|
379
|
+
generateCancelSIPInviteRequestParams: (options) => {
|
380
|
+
const body = {
|
381
|
+
actionType: _REMOVE_,
|
382
|
+
invitees: [
|
383
|
+
{
|
384
|
+
address: options.invitee.memberId,
|
385
|
+
},
|
386
|
+
],
|
387
|
+
};
|
388
|
+
const requestParams = {
|
389
|
+
method: HTTP_VERBS.PUT,
|
390
|
+
uri: options.locusUrl,
|
391
|
+
body,
|
392
|
+
};
|
393
|
+
|
394
|
+
return requestParams;
|
395
|
+
},
|
354
396
|
};
|
355
397
|
|
356
398
|
export default MembersUtil;
|
package/src/metrics/constants.ts
CHANGED
@@ -48,10 +48,19 @@ const BEHAVIORAL_METRICS = {
|
|
48
48
|
UPLOAD_LOGS_FAILURE: 'js_sdk_upload_logs_failure',
|
49
49
|
UPLOAD_LOGS_SUCCESS: 'js_sdk_upload_logs_success',
|
50
50
|
RECEIVE_TRANSCRIPTION_FAILURE: 'js_sdk_receive_transcription_failure',
|
51
|
+
MEETING_IS_IN_PROGRESS_ERROR: 'js_sdk_meeting_is_in_progress_error',
|
52
|
+
STATIC_MEETING_LINK_ALREADY_EXISTS_ERROR: 'js_sdk_static_meeting_link_already_exists_error',
|
51
53
|
FETCH_MEETING_INFO_V1_SUCCESS: 'js_sdk_fetch_meeting_info_v1_success',
|
52
54
|
FETCH_MEETING_INFO_V1_FAILURE: 'js_sdk_fetch_meeting_info_v1_failure',
|
55
|
+
ENABLE_STATIC_METTING_LINK_SUCCESS: 'js_sdk_enable_static_meeting_link_success',
|
56
|
+
ENABLE_STATIC_METTING_LINK_FAILURE: 'js_sdk_enable_static_meeting_link_failure',
|
57
|
+
DISABLE_STATIC_MEETING_LINK_SUCCESS: 'js_sdk_disable_static_meeting_link_success',
|
58
|
+
DISABLE_STATIC_MEETING_LINK_FAILURE: 'js_sdk_disable_static_meeting_link_failure',
|
53
59
|
ADHOC_MEETING_SUCCESS: 'js_sdk_adhoc_meeting_success',
|
54
60
|
ADHOC_MEETING_FAILURE: 'js_sdk_adhoc_meeting_failure',
|
61
|
+
FETCH_STATIC_MEETING_LINK_SUCCESS: 'js_sdk_fetch_static_meeting_link_success',
|
62
|
+
FETCH_STATIC_MEETING_LINK_FAILURE: 'js_sdk_fetch_static_meeting_link_failure',
|
63
|
+
MEETING_LINK_DOES_NOT_EXIST_ERROR: 'js_sdk_meeting_link_does_not_exist_error',
|
55
64
|
VERIFY_PASSWORD_SUCCESS: 'js_sdk_verify_password_success',
|
56
65
|
VERIFY_PASSWORD_ERROR: 'js_sdk_verify_password_error',
|
57
66
|
VERIFY_CAPTCHA_ERROR: 'js_sdk_verify_captcha_error',
|
@@ -63,6 +72,7 @@ const BEHAVIORAL_METRICS = {
|
|
63
72
|
MEETING_INFO_POLICY_ERROR: 'js_sdk_meeting_info_policy_error',
|
64
73
|
LOCUS_DELTA_SYNC_FAILED: 'js_sdk_locus_delta_sync_failed',
|
65
74
|
LOCUS_DELTA_OUT_OF_ORDER: 'js_sdk_locus_delta_ooo',
|
75
|
+
LOCUS_SYNC_HANDLING_FAILED: 'js_sdk_locus_sync_handling_failed',
|
66
76
|
PERMISSION_TOKEN_REFRESH: 'js_sdk_permission_token_refresh',
|
67
77
|
PERMISSION_TOKEN_REFRESH_ERROR: 'js_sdk_permission_token_refresh_error',
|
68
78
|
TURN_DISCOVERY_LATENCY: 'js_sdk_turn_discovery_latency',
|
@@ -1054,22 +1054,44 @@ export class RemoteMediaManager extends EventsScope {
|
|
1054
1054
|
);
|
1055
1055
|
}
|
1056
1056
|
|
1057
|
+
/**
|
1058
|
+
* Set multiple remote video CSIs at once
|
1059
|
+
* @param remoteMediaCsis The remote medias and CSIs to set them to
|
1060
|
+
* @returns {void}
|
1061
|
+
*/
|
1062
|
+
public setRemoteVideoCsis(remoteMediaCsis: {remoteMedia: RemoteMedia; csi?: CSI | null}[]) {
|
1063
|
+
if (!remoteMediaCsis.length) {
|
1064
|
+
return;
|
1065
|
+
}
|
1066
|
+
|
1067
|
+
// Check all remote medias are known
|
1068
|
+
remoteMediaCsis.forEach(({remoteMedia}) => {
|
1069
|
+
if (!Object.values(this.media.video.memberPanes).includes(remoteMedia)) {
|
1070
|
+
throw new Error(`remoteMedia ${remoteMedia.id} not found`);
|
1071
|
+
}
|
1072
|
+
});
|
1073
|
+
|
1074
|
+
// Set remote video CSIs
|
1075
|
+
remoteMediaCsis.forEach(({remoteMedia, csi}) => {
|
1076
|
+
if (csi) {
|
1077
|
+
remoteMedia.sendMediaRequest(csi, false);
|
1078
|
+
} else {
|
1079
|
+
remoteMedia.cancelMediaRequest(false);
|
1080
|
+
}
|
1081
|
+
});
|
1082
|
+
|
1083
|
+
// Commit the changes
|
1084
|
+
this.mediaRequestManagers.video.commit();
|
1085
|
+
}
|
1086
|
+
|
1057
1087
|
/**
|
1058
1088
|
* Sets a new CSI on a given remote media object
|
1059
1089
|
*
|
1060
1090
|
* @param {RemoteMedia} remoteMedia remote Media object to modify
|
1061
1091
|
* @param {CSI} csi new CSI value, can be null if we want to stop receiving media
|
1062
1092
|
*/
|
1063
|
-
public setRemoteVideoCsi(remoteMedia: RemoteMedia, csi
|
1064
|
-
|
1065
|
-
throw new Error('remoteMedia not found');
|
1066
|
-
}
|
1067
|
-
|
1068
|
-
if (csi) {
|
1069
|
-
remoteMedia.sendMediaRequest(csi, true);
|
1070
|
-
} else {
|
1071
|
-
remoteMedia.cancelMediaRequest(true);
|
1072
|
-
}
|
1093
|
+
public setRemoteVideoCsi(remoteMedia: RemoteMedia, csi?: CSI | null) {
|
1094
|
+
this.setRemoteVideoCsis([{remoteMedia, csi}]);
|
1073
1095
|
}
|
1074
1096
|
|
1075
1097
|
/**
|
@@ -6,7 +6,7 @@ import {convertStunUrlToTurn, convertStunUrlToTurnTls} from './util';
|
|
6
6
|
import EventsScope from '../common/events/events-scope';
|
7
7
|
|
8
8
|
import {CONNECTION_STATE, Enum, ICE_GATHERING_STATE} from '../constants';
|
9
|
-
import {ClusterReachabilityResult} from './reachability.types';
|
9
|
+
import {ClusterReachabilityResult, NatType} from './reachability.types';
|
10
10
|
|
11
11
|
// data for the Events.resultReady event
|
12
12
|
export type ResultEventData = {
|
@@ -22,9 +22,14 @@ export type ClientMediaIpsUpdatedEventData = {
|
|
22
22
|
clientMediaIPs: string[];
|
23
23
|
};
|
24
24
|
|
25
|
+
export type NatTypeUpdatedEventData = {
|
26
|
+
natType: NatType;
|
27
|
+
};
|
28
|
+
|
25
29
|
export const Events = {
|
26
30
|
resultReady: 'resultReady', // emitted when a cluster is reached successfully using specific protocol
|
27
31
|
clientMediaIpsUpdated: 'clientMediaIpsUpdated', // emitted when more public IPs are found after resultReady was already sent for a given protocol
|
32
|
+
natTypeUpdated: 'natTypeUpdated', // emitted when NAT type is determined
|
28
33
|
} as const;
|
29
34
|
|
30
35
|
export type Events = Enum<typeof Events>;
|
@@ -41,8 +46,10 @@ export class ClusterReachability extends EventsScope {
|
|
41
46
|
private pc?: RTCPeerConnection;
|
42
47
|
private defer: Defer; // this defer is resolved once reachability checks for this cluster are completed
|
43
48
|
private startTimestamp: number;
|
49
|
+
private srflxIceCandidates: RTCIceCandidate[] = [];
|
44
50
|
public readonly isVideoMesh: boolean;
|
45
51
|
public readonly name;
|
52
|
+
public readonly reachedSubnets: Set<string> = new Set();
|
46
53
|
|
47
54
|
/**
|
48
55
|
* Constructor for ClusterReachability
|
@@ -228,27 +235,13 @@ export class ClusterReachability extends EventsScope {
|
|
228
235
|
*/
|
229
236
|
private registerIceGatheringStateChangeListener() {
|
230
237
|
this.pc.onicegatheringstatechange = () => {
|
231
|
-
|
232
|
-
|
233
|
-
if (this.pc.iceConnectionState === COMPLETE) {
|
238
|
+
if (this.pc.iceGatheringState === ICE_GATHERING_STATE.COMPLETE) {
|
234
239
|
this.closePeerConnection();
|
235
240
|
this.finishReachabilityCheck();
|
236
241
|
}
|
237
242
|
};
|
238
243
|
}
|
239
244
|
|
240
|
-
/**
|
241
|
-
* Checks if we have the results for all the protocols (UDP and TCP)
|
242
|
-
*
|
243
|
-
* @returns {boolean} true if we have all results, false otherwise
|
244
|
-
*/
|
245
|
-
private haveWeGotAllResults(): boolean {
|
246
|
-
return ['udp', 'tcp', 'xtls'].every(
|
247
|
-
(protocol) =>
|
248
|
-
this.result[protocol].result === 'reachable' || this.result[protocol].result === 'untested'
|
249
|
-
);
|
250
|
-
}
|
251
|
-
|
252
245
|
/**
|
253
246
|
* Saves the latency in the result for the given protocol and marks it as reachable,
|
254
247
|
* emits the "resultReady" event if this is the first result for that protocol,
|
@@ -258,9 +251,15 @@ export class ClusterReachability extends EventsScope {
|
|
258
251
|
* @param {string} protocol
|
259
252
|
* @param {number} latency
|
260
253
|
* @param {string|null} [publicIp]
|
254
|
+
* @param {string|null} [serverIp]
|
261
255
|
* @returns {void}
|
262
256
|
*/
|
263
|
-
private saveResult(
|
257
|
+
private saveResult(
|
258
|
+
protocol: 'udp' | 'tcp' | 'xtls',
|
259
|
+
latency: number,
|
260
|
+
publicIp?: string | null,
|
261
|
+
serverIp?: string | null
|
262
|
+
) {
|
264
263
|
const result = this.result[protocol];
|
265
264
|
|
266
265
|
if (result.latencyInMilliseconds === undefined) {
|
@@ -288,6 +287,48 @@ export class ClusterReachability extends EventsScope {
|
|
288
287
|
} else {
|
289
288
|
this.addPublicIP(protocol, publicIp);
|
290
289
|
}
|
290
|
+
|
291
|
+
if (serverIp) {
|
292
|
+
this.reachedSubnets.add(serverIp);
|
293
|
+
}
|
294
|
+
}
|
295
|
+
|
296
|
+
/**
|
297
|
+
* Determines NAT Type.
|
298
|
+
*
|
299
|
+
* @param {RTCIceCandidate} candidate
|
300
|
+
* @returns {void}
|
301
|
+
*/
|
302
|
+
private determineNatType(candidate: RTCIceCandidate) {
|
303
|
+
this.srflxIceCandidates.push(candidate);
|
304
|
+
|
305
|
+
if (this.srflxIceCandidates.length > 1) {
|
306
|
+
const portsFound: Record<string, Set<number>> = {};
|
307
|
+
|
308
|
+
this.srflxIceCandidates.forEach((c) => {
|
309
|
+
const key = `${c.address}:${c.relatedPort}`;
|
310
|
+
if (!portsFound[key]) {
|
311
|
+
portsFound[key] = new Set();
|
312
|
+
}
|
313
|
+
portsFound[key].add(c.port);
|
314
|
+
});
|
315
|
+
|
316
|
+
Object.entries(portsFound).forEach(([, ports]) => {
|
317
|
+
if (ports.size > 1) {
|
318
|
+
// Found candidates with the same address and relatedPort, but different ports
|
319
|
+
this.emit(
|
320
|
+
{
|
321
|
+
file: 'clusterReachability',
|
322
|
+
function: 'determineNatType',
|
323
|
+
},
|
324
|
+
Events.natTypeUpdated,
|
325
|
+
{
|
326
|
+
natType: NatType.SymmetricNat,
|
327
|
+
}
|
328
|
+
);
|
329
|
+
}
|
330
|
+
});
|
331
|
+
}
|
291
332
|
}
|
292
333
|
|
293
334
|
/**
|
@@ -307,19 +348,25 @@ export class ClusterReachability extends EventsScope {
|
|
307
348
|
|
308
349
|
if (e.candidate) {
|
309
350
|
if (e.candidate.type === CANDIDATE_TYPES.SERVER_REFLEXIVE) {
|
310
|
-
|
351
|
+
let serverIp = null;
|
352
|
+
if ('url' in e.candidate) {
|
353
|
+
const stunServerUrlRegex = /stun:([\d.]+):\d+/;
|
354
|
+
|
355
|
+
const match = (e.candidate as any).url.match(stunServerUrlRegex);
|
356
|
+
if (match) {
|
357
|
+
// eslint-disable-next-line prefer-destructuring
|
358
|
+
serverIp = match[1];
|
359
|
+
}
|
360
|
+
}
|
361
|
+
|
362
|
+
this.saveResult('udp', latencyInMilliseconds, e.candidate.address, serverIp);
|
363
|
+
|
364
|
+
this.determineNatType(e.candidate);
|
311
365
|
}
|
312
366
|
|
313
367
|
if (e.candidate.type === CANDIDATE_TYPES.RELAY) {
|
314
368
|
const protocol = e.candidate.port === TURN_TLS_PORT ? 'xtls' : 'tcp';
|
315
|
-
this.saveResult(protocol, latencyInMilliseconds);
|
316
|
-
// we don't add public IP for TCP, because in the case of relay candidates
|
317
|
-
// e.candidate.address is the TURN server address, not the client's public IP
|
318
|
-
}
|
319
|
-
|
320
|
-
if (this.haveWeGotAllResults()) {
|
321
|
-
this.closePeerConnection();
|
322
|
-
this.finishReachabilityCheck();
|
369
|
+
this.saveResult(protocol, latencyInMilliseconds, null, e.candidate.address);
|
323
370
|
}
|
324
371
|
}
|
325
372
|
};
|