@webex/plugin-meetings 3.12.0-next.9 → 3.12.0-next.91
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/AGENTS.md +9 -0
- package/dist/aiEnableRequest/index.js +15 -2
- package/dist/aiEnableRequest/index.js.map +1 -1
- package/dist/breakouts/breakout.js +8 -3
- package/dist/breakouts/breakout.js.map +1 -1
- package/dist/breakouts/index.js +26 -2
- package/dist/breakouts/index.js.map +1 -1
- package/dist/config.js +2 -2
- package/dist/config.js.map +1 -1
- package/dist/constants.js +35 -9
- package/dist/constants.js.map +1 -1
- package/dist/controls-options-manager/constants.js +11 -1
- package/dist/controls-options-manager/constants.js.map +1 -1
- package/dist/controls-options-manager/index.js +67 -29
- package/dist/controls-options-manager/index.js.map +1 -1
- package/dist/controls-options-manager/util.js +91 -0
- package/dist/controls-options-manager/util.js.map +1 -1
- package/dist/hashTree/constants.js +13 -1
- package/dist/hashTree/constants.js.map +1 -1
- package/dist/hashTree/hashTreeParser.js +880 -382
- package/dist/hashTree/hashTreeParser.js.map +1 -1
- package/dist/hashTree/utils.js +42 -0
- package/dist/hashTree/utils.js.map +1 -1
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/interceptors/dataChannelAuthToken.js +75 -15
- package/dist/interceptors/dataChannelAuthToken.js.map +1 -1
- package/dist/interceptors/locusRetry.js +23 -8
- package/dist/interceptors/locusRetry.js.map +1 -1
- package/dist/interpretation/index.js +10 -1
- package/dist/interpretation/index.js.map +1 -1
- package/dist/interpretation/interpretation.types.js +7 -0
- package/dist/interpretation/interpretation.types.js.map +1 -0
- package/dist/interpretation/siLanguage.js +1 -1
- package/dist/locus-info/controlsUtils.js +4 -1
- package/dist/locus-info/controlsUtils.js.map +1 -1
- package/dist/locus-info/index.js +303 -88
- package/dist/locus-info/index.js.map +1 -1
- package/dist/locus-info/infoUtils.js +36 -5
- package/dist/locus-info/infoUtils.js.map +1 -1
- package/dist/locus-info/types.js +19 -0
- package/dist/locus-info/types.js.map +1 -1
- package/dist/media/index.js +3 -1
- package/dist/media/index.js.map +1 -1
- package/dist/media/properties.js +1 -0
- package/dist/media/properties.js.map +1 -1
- package/dist/meeting/in-meeting-actions.js +5 -1
- package/dist/meeting/in-meeting-actions.js.map +1 -1
- package/dist/meeting/index.js +1233 -793
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/locusMediaRequest.js +229 -82
- package/dist/meeting/locusMediaRequest.js.map +1 -1
- package/dist/meeting/muteState.js +10 -1
- package/dist/meeting/muteState.js.map +1 -1
- package/dist/meeting/request.js +5 -2
- package/dist/meeting/request.js.map +1 -1
- package/dist/meeting/util.js +35 -2
- package/dist/meeting/util.js.map +1 -1
- package/dist/meeting-info/meeting-info-v2.js +2 -2
- package/dist/meeting-info/meeting-info-v2.js.map +1 -1
- package/dist/meetings/index.js +231 -118
- package/dist/meetings/index.js.map +1 -1
- package/dist/meetings/meetings.types.js +6 -1
- package/dist/meetings/meetings.types.js.map +1 -1
- package/dist/meetings/request.js +39 -0
- package/dist/meetings/request.js.map +1 -1
- package/dist/meetings/util.js +79 -5
- package/dist/meetings/util.js.map +1 -1
- package/dist/member/index.js +10 -0
- package/dist/member/index.js.map +1 -1
- package/dist/member/types.js.map +1 -1
- package/dist/member/util.js +30 -0
- package/dist/member/util.js.map +1 -1
- package/dist/members/index.js +101 -43
- package/dist/members/index.js.map +1 -1
- package/dist/members/util.js +8 -1
- package/dist/members/util.js.map +1 -1
- package/dist/metrics/constants.js +5 -1
- package/dist/metrics/constants.js.map +1 -1
- package/dist/multistream/codec/constants.js +63 -0
- package/dist/multistream/codec/constants.js.map +1 -0
- package/dist/multistream/mediaRequestManager.js +62 -15
- package/dist/multistream/mediaRequestManager.js.map +1 -1
- package/dist/multistream/receiveSlot.js +9 -0
- package/dist/multistream/receiveSlot.js.map +1 -1
- package/dist/reachability/index.js +10 -13
- package/dist/reachability/index.js.map +1 -1
- package/dist/reachability/reachability.types.js +2 -0
- package/dist/reachability/reachability.types.js.map +1 -1
- package/dist/reachability/util.js +45 -0
- package/dist/reachability/util.js.map +1 -1
- package/dist/reactions/reactions.type.js.map +1 -1
- package/dist/recording-controller/index.js +1 -3
- package/dist/recording-controller/index.js.map +1 -1
- package/dist/types/config.d.ts +2 -2
- package/dist/types/constants.d.ts +12 -1
- package/dist/types/controls-options-manager/constants.d.ts +6 -1
- package/dist/types/controls-options-manager/index.d.ts +16 -0
- package/dist/types/hashTree/constants.d.ts +2 -0
- package/dist/types/hashTree/hashTreeParser.d.ts +146 -17
- package/dist/types/hashTree/utils.d.ts +18 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/interceptors/locusRetry.d.ts +4 -4
- package/dist/types/interpretation/interpretation.types.d.ts +10 -0
- package/dist/types/locus-info/index.d.ts +50 -6
- package/dist/types/locus-info/infoUtils.d.ts +8 -0
- package/dist/types/locus-info/types.d.ts +21 -1
- package/dist/types/media/properties.d.ts +1 -0
- package/dist/types/meeting/in-meeting-actions.d.ts +4 -0
- package/dist/types/meeting/index.d.ts +94 -7
- package/dist/types/meeting/locusMediaRequest.d.ts +12 -0
- package/dist/types/meeting/request.d.ts +1 -0
- package/dist/types/meeting/util.d.ts +9 -0
- package/dist/types/meetings/index.d.ts +30 -18
- package/dist/types/meetings/meetings.types.d.ts +15 -0
- package/dist/types/meetings/request.d.ts +14 -0
- package/dist/types/member/index.d.ts +1 -0
- package/dist/types/member/types.d.ts +1 -0
- package/dist/types/member/util.d.ts +9 -0
- package/dist/types/members/index.d.ts +15 -2
- package/dist/types/members/util.d.ts +1 -5
- package/dist/types/metrics/constants.d.ts +4 -0
- package/dist/types/multistream/codec/constants.d.ts +7 -0
- package/dist/types/multistream/mediaRequestManager.d.ts +22 -5
- package/dist/types/reachability/index.d.ts +1 -1
- package/dist/types/reachability/reachability.types.d.ts +7 -0
- package/dist/types/reachability/util.d.ts +17 -0
- package/dist/types/reactions/reactions.type.d.ts +3 -0
- package/dist/webinar/index.js +305 -159
- package/dist/webinar/index.js.map +1 -1
- package/package.json +22 -22
- package/src/aiEnableRequest/index.ts +16 -0
- package/src/breakouts/breakout.ts +3 -1
- package/src/breakouts/index.ts +31 -0
- package/src/config.ts +2 -2
- package/src/constants.ts +20 -3
- package/src/controls-options-manager/constants.ts +14 -1
- package/src/controls-options-manager/index.ts +87 -28
- package/src/controls-options-manager/util.ts +81 -1
- package/src/hashTree/constants.ts +16 -0
- package/src/hashTree/hashTreeParser.ts +580 -196
- package/src/hashTree/utils.ts +36 -0
- package/src/index.ts +6 -0
- package/src/interceptors/dataChannelAuthToken.ts +88 -12
- package/src/interceptors/locusRetry.ts +25 -4
- package/src/interpretation/index.ts +27 -9
- package/src/interpretation/interpretation.types.ts +11 -0
- package/src/locus-info/controlsUtils.ts +3 -1
- package/src/locus-info/index.ts +304 -100
- package/src/locus-info/infoUtils.ts +41 -6
- package/src/locus-info/types.ts +25 -1
- package/src/media/index.ts +3 -0
- package/src/media/properties.ts +1 -0
- package/src/meeting/in-meeting-actions.ts +8 -0
- package/src/meeting/index.ts +494 -67
- package/src/meeting/locusMediaRequest.ts +106 -6
- package/src/meeting/muteState.ts +10 -1
- package/src/meeting/request.ts +11 -0
- package/src/meeting/util.ts +47 -5
- package/src/meeting-info/meeting-info-v2.ts +4 -2
- package/src/meetings/index.ts +133 -78
- package/src/meetings/meetings.types.ts +19 -0
- package/src/meetings/request.ts +43 -0
- package/src/meetings/util.ts +97 -1
- package/src/member/index.ts +10 -0
- package/src/member/types.ts +1 -0
- package/src/member/util.ts +29 -0
- package/src/members/index.ts +70 -7
- package/src/members/util.ts +12 -4
- package/src/metrics/constants.ts +4 -0
- package/src/multistream/codec/constants.ts +58 -0
- package/src/multistream/mediaRequestManager.ts +119 -28
- package/src/multistream/receiveSlot.ts +18 -0
- package/src/reachability/index.ts +19 -15
- package/src/reachability/reachability.types.ts +11 -0
- package/src/reachability/util.ts +36 -0
- package/src/reactions/reactions.type.ts +3 -0
- package/src/recording-controller/index.ts +1 -2
- package/src/webinar/index.ts +214 -36
- package/test/unit/spec/aiEnableRequest/index.ts +86 -0
- package/test/unit/spec/breakouts/breakout.ts +9 -3
- package/test/unit/spec/breakouts/index.ts +49 -0
- package/test/unit/spec/controls-options-manager/index.js +244 -29
- package/test/unit/spec/controls-options-manager/util.js +165 -0
- package/test/unit/spec/hashTree/hashTreeParser.ts +1838 -180
- package/test/unit/spec/hashTree/utils.ts +125 -1
- package/test/unit/spec/interceptors/dataChannelAuthToken.ts +196 -0
- package/test/unit/spec/interceptors/locusRetry.ts +205 -4
- package/test/unit/spec/interpretation/index.ts +26 -4
- package/test/unit/spec/locus-info/controlsUtils.js +172 -57
- package/test/unit/spec/locus-info/index.js +499 -81
- package/test/unit/spec/locus-info/infoUtils.js +184 -1
- package/test/unit/spec/media/index.ts +31 -0
- package/test/unit/spec/meeting/in-meeting-actions.ts +4 -0
- package/test/unit/spec/meeting/index.js +1615 -42
- package/test/unit/spec/meeting/locusMediaRequest.ts +302 -4
- package/test/unit/spec/meeting/muteState.js +81 -0
- package/test/unit/spec/meeting/request.js +12 -0
- package/test/unit/spec/meeting/utils.js +157 -1
- package/test/unit/spec/meeting-info/meetinginfov2.js +19 -10
- package/test/unit/spec/meetings/index.js +363 -36
- package/test/unit/spec/meetings/request.js +141 -0
- package/test/unit/spec/meetings/utils.js +189 -0
- package/test/unit/spec/member/index.js +7 -0
- package/test/unit/spec/member/util.js +89 -0
- package/test/unit/spec/members/index.js +216 -0
- package/test/unit/spec/members/request.js +37 -1
- package/test/unit/spec/members/utils.js +63 -0
- package/test/unit/spec/multistream/mediaRequestManager.ts +501 -37
- package/test/unit/spec/reachability/index.ts +59 -46
- package/test/unit/spec/reachability/util.ts +31 -0
- package/test/unit/spec/recording-controller/index.js +9 -8
- package/test/unit/spec/webinar/index.ts +329 -28
package/src/member/util.ts
CHANGED
|
@@ -140,6 +140,9 @@ const MemberUtil = {
|
|
|
140
140
|
isPresenterAssignmentProhibited: (participant: Participant) =>
|
|
141
141
|
participant && participant.presenterAssignmentNotAllowed,
|
|
142
142
|
|
|
143
|
+
isAttendeeAssignmentProhibited: (participant: Participant) =>
|
|
144
|
+
!!(participant && participant.attendeeAssignmentNotAllowed),
|
|
145
|
+
|
|
143
146
|
/**
|
|
144
147
|
* checks to see if the participant id is the same as the passed id
|
|
145
148
|
* there are multiple ids that can be used
|
|
@@ -436,5 +439,31 @@ const MemberUtil = {
|
|
|
436
439
|
|
|
437
440
|
return participantUrl;
|
|
438
441
|
},
|
|
442
|
+
|
|
443
|
+
/**
|
|
444
|
+
* Collects all CSIs reported for a participant across all their devices,
|
|
445
|
+
* looking at both the top-level `csis` array and any `mediaSessions[].csi` values.
|
|
446
|
+
*
|
|
447
|
+
* @param {Object} participant - The locus participant object.
|
|
448
|
+
* @returns {Array<number>} unique CSIs for this participant
|
|
449
|
+
*/
|
|
450
|
+
extractCsis: (participant: Participant): number[] => {
|
|
451
|
+
const csis = new Set<number>();
|
|
452
|
+
|
|
453
|
+
participant?.devices?.forEach((device: any) => {
|
|
454
|
+
device?.csis?.forEach((csi: number) => {
|
|
455
|
+
if (typeof csi === 'number') {
|
|
456
|
+
csis.add(csi);
|
|
457
|
+
}
|
|
458
|
+
});
|
|
459
|
+
device?.mediaSessions?.forEach((mediaSession: any) => {
|
|
460
|
+
if (typeof mediaSession?.csi === 'number') {
|
|
461
|
+
csis.add(mediaSession.csi);
|
|
462
|
+
}
|
|
463
|
+
});
|
|
464
|
+
});
|
|
465
|
+
|
|
466
|
+
return Array.from(csis);
|
|
467
|
+
},
|
|
439
468
|
};
|
|
440
469
|
export default MemberUtil;
|
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 {get, isEmpty, set} from 'lodash';
|
|
4
|
+
import {get, isEmpty, isEqual, set} from 'lodash';
|
|
5
5
|
// @ts-ignore
|
|
6
6
|
import {StatelessWebexPlugin} from '@webex/webex-core';
|
|
7
7
|
|
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
} from '../constants';
|
|
16
16
|
import Trigger from '../common/events/trigger-proxy';
|
|
17
17
|
import Member from '../member';
|
|
18
|
+
import MemberUtil from '../member/util';
|
|
18
19
|
import LoggerProxy from '../common/logs/logger-proxy';
|
|
19
20
|
import ParameterError from '../common/errors/parameter';
|
|
20
21
|
import {
|
|
@@ -99,6 +100,15 @@ export default class Members extends StatelessWebexPlugin {
|
|
|
99
100
|
selfId: any;
|
|
100
101
|
type: any;
|
|
101
102
|
|
|
103
|
+
/**
|
|
104
|
+
* Map of CSI -> memberId that previously used the CSI in a Locus update.
|
|
105
|
+
* Keyed by CSI so findMemberByCsi can resolve it in O(1).
|
|
106
|
+
* Kept here (rather than on each Member) so it survives members being removed
|
|
107
|
+
* and re-added (e.g. when entering/leaving a breakout session).
|
|
108
|
+
* @private
|
|
109
|
+
*/
|
|
110
|
+
private memberIdByHistoryCsi: Map<number, string> = new Map();
|
|
111
|
+
|
|
102
112
|
namespace = MEETINGS;
|
|
103
113
|
|
|
104
114
|
/**
|
|
@@ -315,6 +325,14 @@ export default class Members extends StatelessWebexPlugin {
|
|
|
315
325
|
* @memberof Members
|
|
316
326
|
*/
|
|
317
327
|
clearMembers() {
|
|
328
|
+
// capture CSIs of all current members before reset so findMemberByCsi can
|
|
329
|
+
// still resolve them if a member is later re-added (e.g. when leaving a
|
|
330
|
+
// breakout session)
|
|
331
|
+
Object.values(this.membersCollection.getAll()).forEach((member) => {
|
|
332
|
+
MemberUtil.extractCsis(member.participant).forEach((csi) =>
|
|
333
|
+
this.memberIdByHistoryCsi.set(csi, member.id)
|
|
334
|
+
);
|
|
335
|
+
});
|
|
318
336
|
this.membersCollection.reset();
|
|
319
337
|
Trigger.trigger(
|
|
320
338
|
this,
|
|
@@ -569,6 +587,15 @@ export default class Members extends StatelessWebexPlugin {
|
|
|
569
587
|
*/
|
|
570
588
|
private removeMembers(removedMembers: Array<string>) {
|
|
571
589
|
removedMembers.forEach((memberId) => {
|
|
590
|
+
// capture CSIs before removal so findMemberByCsi can still resolve them
|
|
591
|
+
// if the member is later re-added (e.g. when leaving a breakout session)
|
|
592
|
+
// with a participant payload that no longer contains the original CSIs
|
|
593
|
+
const existingMember = this.membersCollection.get(memberId);
|
|
594
|
+
if (existingMember) {
|
|
595
|
+
MemberUtil.extractCsis(existingMember.participant).forEach((csi) =>
|
|
596
|
+
this.memberIdByHistoryCsi.set(csi, memberId)
|
|
597
|
+
);
|
|
598
|
+
}
|
|
572
599
|
this.membersCollection.remove(memberId);
|
|
573
600
|
});
|
|
574
601
|
}
|
|
@@ -598,6 +625,19 @@ export default class Members extends StatelessWebexPlugin {
|
|
|
598
625
|
set(member, prop, existingValue);
|
|
599
626
|
}
|
|
600
627
|
});
|
|
628
|
+
|
|
629
|
+
// remember CSIs the member used previously so findMemberByCsi can still
|
|
630
|
+
// resolve a CSI even after participant.devices[].csis no longer contains it.
|
|
631
|
+
// Skip re-extracting when devices haven't changed - existing history already covers them.
|
|
632
|
+
const devicesUnchanged = isEqual(
|
|
633
|
+
existingMember.participant?.devices,
|
|
634
|
+
member.participant?.devices
|
|
635
|
+
);
|
|
636
|
+
if (!devicesUnchanged) {
|
|
637
|
+
MemberUtil.extractCsis(existingMember.participant).forEach((csi) =>
|
|
638
|
+
this.memberIdByHistoryCsi.set(csi, member.id)
|
|
639
|
+
);
|
|
640
|
+
}
|
|
601
641
|
}
|
|
602
642
|
}
|
|
603
643
|
this.membersCollection.set(member.id, member);
|
|
@@ -1096,12 +1136,16 @@ export default class Members extends StatelessWebexPlugin {
|
|
|
1096
1136
|
* Transfers the host to another member
|
|
1097
1137
|
* @param {String} memberId
|
|
1098
1138
|
* @param {boolean} [moderator] default true
|
|
1139
|
+
* @param {String} [breakoutLocusUrl] when provided, the request is sent against this locus url
|
|
1140
|
+
* (i.e. the breakout session's locus) instead of the main session's locus url
|
|
1099
1141
|
* @returns {Promise}
|
|
1100
1142
|
* @public
|
|
1101
1143
|
* @memberof Members
|
|
1102
1144
|
*/
|
|
1103
|
-
public transferHostToMember(memberId: string, moderator = true) {
|
|
1104
|
-
|
|
1145
|
+
public transferHostToMember(memberId: string, moderator = true, breakoutLocusUrl = '') {
|
|
1146
|
+
const locusUrl = breakoutLocusUrl || this.locusUrl;
|
|
1147
|
+
|
|
1148
|
+
if (!locusUrl) {
|
|
1105
1149
|
return Promise.reject(
|
|
1106
1150
|
new ParameterError(
|
|
1107
1151
|
'The associated locus url for this meetings members object must be defined.'
|
|
@@ -1113,11 +1157,14 @@ export default class Members extends StatelessWebexPlugin {
|
|
|
1113
1157
|
new ParameterError('The member id must be defined to transfer host to the member.')
|
|
1114
1158
|
);
|
|
1115
1159
|
}
|
|
1116
|
-
const options = MembersUtil.generateTransferHostMemberOptions(
|
|
1160
|
+
const options: Record<string, any> = MembersUtil.generateTransferHostMemberOptions(
|
|
1117
1161
|
memberId,
|
|
1118
1162
|
moderator,
|
|
1119
|
-
|
|
1163
|
+
locusUrl
|
|
1120
1164
|
);
|
|
1165
|
+
if (breakoutLocusUrl && breakoutLocusUrl !== this.locusUrl) {
|
|
1166
|
+
options.authorizingLocusUrl = this.locusUrl;
|
|
1167
|
+
}
|
|
1121
1168
|
|
|
1122
1169
|
return this.membersRequest.transferHostToMember(options);
|
|
1123
1170
|
}
|
|
@@ -1161,18 +1208,34 @@ export default class Members extends StatelessWebexPlugin {
|
|
|
1161
1208
|
);
|
|
1162
1209
|
}
|
|
1163
1210
|
|
|
1164
|
-
/** Finds a member that has any device with a csi matching provided value
|
|
1211
|
+
/** Finds a member that has any device with a csi matching provided value.
|
|
1212
|
+
* Falls back to the `memberIdByHistoryCsi` map so that a CSI a member used in
|
|
1213
|
+
* a previous Locus update can still be resolved even if it is no longer
|
|
1214
|
+
* present in `participant.devices[].csis`.
|
|
1165
1215
|
*
|
|
1166
1216
|
* @param {number} csi
|
|
1167
1217
|
* @returns {Member}
|
|
1168
1218
|
*/
|
|
1169
1219
|
findMemberByCsi(csi) {
|
|
1170
|
-
|
|
1220
|
+
const members = Object.values(this.membersCollection.getAll());
|
|
1221
|
+
|
|
1222
|
+
const currentMatch = members.find((member) =>
|
|
1171
1223
|
// @ts-ignore
|
|
1172
1224
|
member.participant?.devices?.find((device) =>
|
|
1173
1225
|
device.csis?.find((memberCsi) => memberCsi === csi)
|
|
1174
1226
|
)
|
|
1175
1227
|
);
|
|
1228
|
+
|
|
1229
|
+
if (currentMatch) {
|
|
1230
|
+
return currentMatch;
|
|
1231
|
+
}
|
|
1232
|
+
|
|
1233
|
+
const historyMemberId = this.memberIdByHistoryCsi.get(csi);
|
|
1234
|
+
if (historyMemberId) {
|
|
1235
|
+
return this.membersCollection.get(historyMemberId);
|
|
1236
|
+
}
|
|
1237
|
+
|
|
1238
|
+
return undefined;
|
|
1176
1239
|
}
|
|
1177
1240
|
|
|
1178
1241
|
/**
|
package/src/members/util.ts
CHANGED
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
ALIAS,
|
|
14
14
|
} from '../constants';
|
|
15
15
|
|
|
16
|
-
import {RoleAssignmentOptions, RoleAssignmentRequest, ServerRoleShape} from './types';
|
|
16
|
+
import {RoleAssignmentOptions, RoleAssignmentRequest, ServerRoleShape, ServerRoles} from './types';
|
|
17
17
|
import {Invitee} from '../meeting/type';
|
|
18
18
|
|
|
19
19
|
const MembersUtil = {
|
|
@@ -330,12 +330,20 @@ const MembersUtil = {
|
|
|
330
330
|
};
|
|
331
331
|
},
|
|
332
332
|
|
|
333
|
-
getTransferHostToMemberRequestParams: (options) => {
|
|
334
|
-
const body = {
|
|
333
|
+
getTransferHostToMemberRequestParams: (options: any) => {
|
|
334
|
+
const body: Record<string, any> = {
|
|
335
335
|
role: {
|
|
336
|
-
|
|
336
|
+
roles: [
|
|
337
|
+
{
|
|
338
|
+
hasRole: true,
|
|
339
|
+
type: ServerRoles.Moderator,
|
|
340
|
+
},
|
|
341
|
+
],
|
|
337
342
|
},
|
|
338
343
|
};
|
|
344
|
+
if (options.authorizingLocusUrl) {
|
|
345
|
+
body.authorizingLocusUrl = options.authorizingLocusUrl;
|
|
346
|
+
}
|
|
339
347
|
const uri = `${options.locusUrl}/${PARTICIPANT}/${options.memberId}/${CONTROLS}`;
|
|
340
348
|
|
|
341
349
|
return {
|
package/src/metrics/constants.ts
CHANGED
|
@@ -11,6 +11,7 @@ const BEHAVIORAL_METRICS = {
|
|
|
11
11
|
ADD_MEDIA_SUCCESS: 'js_sdk_add_media_success',
|
|
12
12
|
ADD_MEDIA_FAILURE: 'js_sdk_add_media_failures',
|
|
13
13
|
ADD_MEDIA_RETRY: 'js_sdk_add_media_retry',
|
|
14
|
+
LOCUS_MEDIA_REQUEST_RETRY: 'js_sdk_locus_media_request_retry',
|
|
14
15
|
ROAP_MERCURY_EVENT_RECEIVED: 'js_sdk_roap_mercury_received',
|
|
15
16
|
CONNECTION_SUCCESS: 'js_sdk_connection_success',
|
|
16
17
|
CONNECTION_FAILURE: 'js_sdk_connection_failures',
|
|
@@ -96,6 +97,9 @@ const BEHAVIORAL_METRICS = {
|
|
|
96
97
|
SET_CUSTOM_CODEC_PARAMETERS_USED: 'js_sdk_set_custom_codec_parameters_used',
|
|
97
98
|
MARK_CUSTOM_CODEC_PARAMETERS_FOR_DELETION_USED:
|
|
98
99
|
'js_sdk_mark_custom_codec_parameters_for_deletion_used',
|
|
100
|
+
HASH_TREE_SYNC_FAILURE: 'js_sdk_hash_tree_sync_failure',
|
|
101
|
+
HASH_TREE_HEARTBEAT_WATCHDOG_EXPIRED: 'js_sdk_hash_tree_heartbeat_watchdog_expired',
|
|
102
|
+
HASH_TREE_EMPTY_LOCUS_STATE_ELEMENTS: 'js_sdk_hash_tree_empty_locus_state_elements',
|
|
99
103
|
};
|
|
100
104
|
|
|
101
105
|
export {BEHAVIORAL_METRICS as default};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import {AV1EncodingParams, SupportedResolution} from '@webex/internal-media-core';
|
|
2
|
+
|
|
3
|
+
export const AV1_CODEC_PARAMETERS: Record<SupportedResolution, AV1EncodingParams> = {
|
|
4
|
+
'90p': {
|
|
5
|
+
levelIdx: 0,
|
|
6
|
+
tier: 0,
|
|
7
|
+
maxWidth: 160,
|
|
8
|
+
maxHeight: 90,
|
|
9
|
+
maxPicSize: 147_456,
|
|
10
|
+
maxDecodeRate: 5_529_600,
|
|
11
|
+
},
|
|
12
|
+
'180p': {
|
|
13
|
+
levelIdx: 0,
|
|
14
|
+
tier: 0,
|
|
15
|
+
maxWidth: 320,
|
|
16
|
+
maxHeight: 180,
|
|
17
|
+
maxPicSize: 147_456,
|
|
18
|
+
maxDecodeRate: 5_529_600,
|
|
19
|
+
},
|
|
20
|
+
'360p': {
|
|
21
|
+
levelIdx: 1,
|
|
22
|
+
tier: 0,
|
|
23
|
+
maxWidth: 640,
|
|
24
|
+
maxHeight: 360,
|
|
25
|
+
maxPicSize: 278_784,
|
|
26
|
+
maxDecodeRate: 10_454_400,
|
|
27
|
+
},
|
|
28
|
+
'540p': {
|
|
29
|
+
levelIdx: 4,
|
|
30
|
+
tier: 0,
|
|
31
|
+
maxWidth: 960,
|
|
32
|
+
maxHeight: 540,
|
|
33
|
+
maxPicSize: 665_856,
|
|
34
|
+
maxDecodeRate: 24_969_600,
|
|
35
|
+
},
|
|
36
|
+
'720p': {
|
|
37
|
+
levelIdx: 5,
|
|
38
|
+
tier: 0,
|
|
39
|
+
maxWidth: 1280,
|
|
40
|
+
maxHeight: 720,
|
|
41
|
+
maxPicSize: 1_065_024,
|
|
42
|
+
maxDecodeRate: 39_938_400,
|
|
43
|
+
},
|
|
44
|
+
'1080p': {
|
|
45
|
+
levelIdx: 8,
|
|
46
|
+
tier: 0,
|
|
47
|
+
maxWidth: 1920,
|
|
48
|
+
maxHeight: 1080,
|
|
49
|
+
maxPicSize: 2_359_296,
|
|
50
|
+
maxDecodeRate: 77_856_768,
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export const H264_CODEC_PARAMETERS = {
|
|
55
|
+
maxFs: 8192,
|
|
56
|
+
maxFps: 3000,
|
|
57
|
+
maxMbps: 245760,
|
|
58
|
+
};
|
|
@@ -9,6 +9,11 @@ import {
|
|
|
9
9
|
getRecommendedMaxBitrateForFrameSize,
|
|
10
10
|
RecommendedOpusBitrates,
|
|
11
11
|
NamedMediaGroup,
|
|
12
|
+
AV1Codec,
|
|
13
|
+
SupportedResolution,
|
|
14
|
+
AV1EncodingParams,
|
|
15
|
+
MediaType,
|
|
16
|
+
MediaCodecMimeType,
|
|
12
17
|
} from '@webex/internal-media-core';
|
|
13
18
|
import {cloneDeepWith, debounce} from 'lodash';
|
|
14
19
|
|
|
@@ -16,6 +21,7 @@ import LoggerProxy from '../common/logs/logger-proxy';
|
|
|
16
21
|
|
|
17
22
|
import {ReceiveSlot, ReceiveSlotEvents} from './receiveSlot';
|
|
18
23
|
import {MAX_FS_VALUES} from './remoteMedia';
|
|
24
|
+
import {AV1_CODEC_PARAMETERS, H264_CODEC_PARAMETERS} from './codec/constants';
|
|
19
25
|
|
|
20
26
|
export interface ActiveSpeakerPolicyInfo {
|
|
21
27
|
policy: 'active-speaker';
|
|
@@ -54,34 +60,49 @@ export interface MediaRequest {
|
|
|
54
60
|
|
|
55
61
|
export type MediaRequestId = string;
|
|
56
62
|
|
|
57
|
-
const CODEC_DEFAULTS = {
|
|
58
|
-
h264: {
|
|
59
|
-
maxFs: 8192,
|
|
60
|
-
maxFps: 3000,
|
|
61
|
-
maxMbps: 245760,
|
|
62
|
-
},
|
|
63
|
-
};
|
|
64
|
-
|
|
65
63
|
const DEBOUNCED_SOURCE_UPDATE_TIME = 1000;
|
|
66
64
|
|
|
65
|
+
const RESOLUTION_BUCKETS: Array<[SupportedResolution, number]> = [
|
|
66
|
+
['90p', MAX_FS_VALUES['90p']],
|
|
67
|
+
['180p', MAX_FS_VALUES['180p']],
|
|
68
|
+
['360p', MAX_FS_VALUES['360p']],
|
|
69
|
+
['540p', MAX_FS_VALUES['540p']],
|
|
70
|
+
['720p', MAX_FS_VALUES['720p']],
|
|
71
|
+
];
|
|
72
|
+
|
|
67
73
|
type DegradationPreferences = {
|
|
68
74
|
maxMacroblocksLimit: number;
|
|
69
75
|
};
|
|
70
76
|
|
|
71
77
|
type SendMediaRequestsCallback = (streamRequests: StreamRequest[]) => void;
|
|
78
|
+
type GetIngressPayloadTypeCallback = (
|
|
79
|
+
mediaType: MediaType,
|
|
80
|
+
codecMimeType: MediaCodecMimeType
|
|
81
|
+
) => number | undefined;
|
|
72
82
|
type Kind = 'audio' | 'video';
|
|
73
83
|
|
|
74
|
-
type
|
|
84
|
+
type AudioMediaRequestManagerOptions = {
|
|
75
85
|
degradationPreferences: DegradationPreferences;
|
|
76
|
-
kind:
|
|
86
|
+
kind: 'audio';
|
|
77
87
|
trimRequestsToNumOfSources: boolean; // if enabled, AS speaker requests will be trimmed based on the calls to setNumCurrentSources()
|
|
78
88
|
};
|
|
79
89
|
|
|
90
|
+
type VideoMediaRequestManagerOptions = {
|
|
91
|
+
degradationPreferences: DegradationPreferences;
|
|
92
|
+
kind: 'video';
|
|
93
|
+
trimRequestsToNumOfSources: boolean;
|
|
94
|
+
enableAv1?: boolean;
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
type Options = AudioMediaRequestManagerOptions | VideoMediaRequestManagerOptions;
|
|
98
|
+
|
|
80
99
|
type ClientRequestsMap = {[key: MediaRequestId]: MediaRequest};
|
|
81
100
|
|
|
82
101
|
export class MediaRequestManager {
|
|
83
102
|
private sendMediaRequestsCallback: SendMediaRequestsCallback;
|
|
84
103
|
|
|
104
|
+
private getIngressPayloadTypeCallback: GetIngressPayloadTypeCallback;
|
|
105
|
+
|
|
85
106
|
private kind: Kind;
|
|
86
107
|
|
|
87
108
|
private counter: number;
|
|
@@ -95,11 +116,17 @@ export class MediaRequestManager {
|
|
|
95
116
|
private debouncedSourceUpdateListener: () => void;
|
|
96
117
|
|
|
97
118
|
private trimRequestsToNumOfSources: boolean;
|
|
119
|
+
private enableAv1: boolean;
|
|
98
120
|
private numTotalSources: number;
|
|
99
121
|
private numLiveSources: number;
|
|
100
122
|
|
|
101
|
-
constructor(
|
|
123
|
+
constructor(
|
|
124
|
+
sendMediaRequestsCallback: SendMediaRequestsCallback,
|
|
125
|
+
getIngressPayloadTypeCallback: GetIngressPayloadTypeCallback,
|
|
126
|
+
options: Options
|
|
127
|
+
) {
|
|
102
128
|
this.sendMediaRequestsCallback = sendMediaRequestsCallback;
|
|
129
|
+
this.getIngressPayloadTypeCallback = getIngressPayloadTypeCallback;
|
|
103
130
|
this.counter = 0;
|
|
104
131
|
this.numLiveSources = 0;
|
|
105
132
|
this.numTotalSources = 0;
|
|
@@ -107,6 +134,7 @@ export class MediaRequestManager {
|
|
|
107
134
|
this.degradationPreferences = options.degradationPreferences;
|
|
108
135
|
this.kind = options.kind;
|
|
109
136
|
this.trimRequestsToNumOfSources = options.trimRequestsToNumOfSources;
|
|
137
|
+
this.enableAv1 = options.kind === 'video' && !!options.enableAv1;
|
|
110
138
|
this.sourceUpdateListener = this.commit.bind(this);
|
|
111
139
|
this.debouncedSourceUpdateListener = debounce(
|
|
112
140
|
this.sourceUpdateListener,
|
|
@@ -135,8 +163,8 @@ export class MediaRequestManager {
|
|
|
135
163
|
Object.values(clientRequests).forEach((mr) => {
|
|
136
164
|
if (mr.codecInfo) {
|
|
137
165
|
mr.codecInfo.maxFs = Math.min(
|
|
138
|
-
mr.preferredMaxFs ||
|
|
139
|
-
mr.codecInfo.maxFs ||
|
|
166
|
+
mr.preferredMaxFs || H264_CODEC_PARAMETERS.maxFs,
|
|
167
|
+
mr.codecInfo.maxFs || H264_CODEC_PARAMETERS.maxFs,
|
|
140
168
|
maxFsLimits[i]
|
|
141
169
|
);
|
|
142
170
|
// we only consider sources with "live" state
|
|
@@ -176,7 +204,7 @@ export class MediaRequestManager {
|
|
|
176
204
|
}
|
|
177
205
|
|
|
178
206
|
return getRecommendedMaxBitrateForFrameSize(
|
|
179
|
-
mediaRequest.codecInfo.maxFs ||
|
|
207
|
+
mediaRequest.codecInfo.maxFs || H264_CODEC_PARAMETERS.maxFs
|
|
180
208
|
);
|
|
181
209
|
}
|
|
182
210
|
|
|
@@ -192,12 +220,80 @@ export class MediaRequestManager {
|
|
|
192
220
|
// eslint-disable-next-line class-methods-use-this
|
|
193
221
|
private getH264MaxMbps(mediaRequest: MediaRequest): number {
|
|
194
222
|
// fallback for maxFps (not needed for maxFs, since there is a fallback already in getDegradedClientRequests)
|
|
195
|
-
const maxFps = mediaRequest.codecInfo.maxFps ||
|
|
223
|
+
const maxFps = mediaRequest.codecInfo.maxFps || H264_CODEC_PARAMETERS.maxFps;
|
|
196
224
|
|
|
197
225
|
// divided by 100 since maxFps is 3000 (for 30 frames per seconds)
|
|
198
226
|
return (mediaRequest.codecInfo.maxFs * maxFps) / 100;
|
|
199
227
|
}
|
|
200
228
|
|
|
229
|
+
/**
|
|
230
|
+
* Returns the AV1 encoding parameters for a media request
|
|
231
|
+
* @param mediaRequest - The media request to get the AV1 encoding parameters for
|
|
232
|
+
* @returns {AV1EncodingParams} The AV1 encoding parameters
|
|
233
|
+
*/
|
|
234
|
+
// eslint-disable-next-line class-methods-use-this
|
|
235
|
+
private getAv1EncodingParams(mediaRequest: MediaRequest): AV1EncodingParams {
|
|
236
|
+
const frameSize = mediaRequest.codecInfo.maxFs || H264_CODEC_PARAMETERS.maxFs;
|
|
237
|
+
const resolution = RESOLUTION_BUCKETS.find(([, maxFs]) => frameSize <= maxFs)?.[0] ?? '1080p';
|
|
238
|
+
|
|
239
|
+
return AV1_CODEC_PARAMETERS[resolution];
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
private buildH264CodecInfo(mr: MediaRequest): WcmeCodecInfo | undefined {
|
|
243
|
+
if (!mr.codecInfo) {
|
|
244
|
+
return undefined;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
const h264PayloadType = this.getIngressPayloadTypeCallback(
|
|
248
|
+
mr.receiveSlots[0].mediaType,
|
|
249
|
+
MediaCodecMimeType.H264
|
|
250
|
+
);
|
|
251
|
+
|
|
252
|
+
if (h264PayloadType === undefined) {
|
|
253
|
+
return undefined;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
return WcmeCodecInfo.fromH264(
|
|
257
|
+
h264PayloadType,
|
|
258
|
+
new H264Codec(
|
|
259
|
+
mr.codecInfo.maxFs,
|
|
260
|
+
mr.codecInfo.maxFps || H264_CODEC_PARAMETERS.maxFps,
|
|
261
|
+
this.getH264MaxMbps(mr),
|
|
262
|
+
mr.codecInfo.maxWidth,
|
|
263
|
+
mr.codecInfo.maxHeight
|
|
264
|
+
)
|
|
265
|
+
);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
private buildAv1CodecInfo(mr: MediaRequest): WcmeCodecInfo | undefined {
|
|
269
|
+
if (!this.enableAv1 || !mr.codecInfo) {
|
|
270
|
+
return undefined;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
const av1PayloadType = this.getIngressPayloadTypeCallback(
|
|
274
|
+
mr.receiveSlots[0].mediaType,
|
|
275
|
+
MediaCodecMimeType.AV1
|
|
276
|
+
);
|
|
277
|
+
|
|
278
|
+
if (av1PayloadType === undefined) {
|
|
279
|
+
return undefined;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
const av1EncodingParams = this.getAv1EncodingParams(mr);
|
|
283
|
+
|
|
284
|
+
return WcmeCodecInfo.fromAv1(
|
|
285
|
+
av1PayloadType,
|
|
286
|
+
new AV1Codec(
|
|
287
|
+
av1EncodingParams.levelIdx,
|
|
288
|
+
av1EncodingParams.tier,
|
|
289
|
+
mr.codecInfo.maxWidth || av1EncodingParams.maxWidth,
|
|
290
|
+
mr.codecInfo.maxHeight || av1EncodingParams.maxHeight,
|
|
291
|
+
av1EncodingParams.maxPicSize,
|
|
292
|
+
av1EncodingParams.maxDecodeRate
|
|
293
|
+
)
|
|
294
|
+
);
|
|
295
|
+
}
|
|
296
|
+
|
|
201
297
|
/** Modifies the passed in clientRequests and makes sure that in total they don't ask
|
|
202
298
|
* for more streams than there are available.
|
|
203
299
|
*
|
|
@@ -298,6 +394,12 @@ export class MediaRequestManager {
|
|
|
298
394
|
// map all the client media requests to wcme stream requests
|
|
299
395
|
Object.values(clientRequests).forEach((mr) => {
|
|
300
396
|
if (mr.receiveSlots.length > 0) {
|
|
397
|
+
const codecInfos: WcmeCodecInfo[] = mr.codecInfo
|
|
398
|
+
? [this.buildH264CodecInfo(mr), this.buildAv1CodecInfo(mr)].filter(
|
|
399
|
+
(info): info is WcmeCodecInfo => info !== undefined
|
|
400
|
+
)
|
|
401
|
+
: [];
|
|
402
|
+
|
|
301
403
|
streamRequests.push(
|
|
302
404
|
new StreamRequest(
|
|
303
405
|
mr.policyInfo.policy === 'active-speaker'
|
|
@@ -314,25 +416,14 @@ export class MediaRequestManager {
|
|
|
314
416
|
: new ReceiverSelectedInfo(mr.policyInfo.csi),
|
|
315
417
|
mr.receiveSlots.map((receiveSlot) => receiveSlot.wcmeReceiveSlot),
|
|
316
418
|
this.getMaxPayloadBitsPerSecond(mr),
|
|
317
|
-
|
|
318
|
-
WcmeCodecInfo.fromH264(
|
|
319
|
-
0x80,
|
|
320
|
-
new H264Codec(
|
|
321
|
-
mr.codecInfo.maxFs,
|
|
322
|
-
mr.codecInfo.maxFps || CODEC_DEFAULTS.h264.maxFps,
|
|
323
|
-
this.getH264MaxMbps(mr),
|
|
324
|
-
mr.codecInfo.maxWidth,
|
|
325
|
-
mr.codecInfo.maxHeight
|
|
326
|
-
)
|
|
327
|
-
),
|
|
328
|
-
]
|
|
419
|
+
codecInfos
|
|
329
420
|
)
|
|
330
421
|
);
|
|
331
422
|
}
|
|
332
423
|
});
|
|
333
424
|
|
|
334
425
|
this.sendMediaRequestsCallback(streamRequests);
|
|
335
|
-
LoggerProxy.logger.info(`multistream:sendRequests --> media requests sent
|
|
426
|
+
LoggerProxy.logger.info(`multistream:sendRequests --> media requests sent.`);
|
|
336
427
|
}
|
|
337
428
|
|
|
338
429
|
public addRequest(mediaRequest: MediaRequest, commit = true): MediaRequestId {
|
|
@@ -134,6 +134,24 @@ export class ReceiveSlot extends EventsScope {
|
|
|
134
134
|
});
|
|
135
135
|
}
|
|
136
136
|
);
|
|
137
|
+
|
|
138
|
+
this.mcReceiveSlot.on(WcmeReceiveSlotEvents.MediaStarted, () => {
|
|
139
|
+
LoggerProxy.logger.log(
|
|
140
|
+
`ReceiveSlot#setupEventListeners --> media started on receive slot ${this.id}, mediaType=${this.mediaType}`
|
|
141
|
+
);
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
this.mcReceiveSlot.on(WcmeReceiveSlotEvents.MediaStopped, () => {
|
|
145
|
+
LoggerProxy.logger.log(
|
|
146
|
+
`ReceiveSlot#setupEventListeners --> media stopped on receive slot ${this.id}, mediaType=${this.mediaType}`
|
|
147
|
+
);
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
this.mcReceiveSlot.on(WcmeReceiveSlotEvents.MediaEnded, () => {
|
|
151
|
+
LoggerProxy.logger.log(
|
|
152
|
+
`ReceiveSlot#setupEventListeners --> media ended on receive slot ${this.id}, mediaType=${this.mediaType}`
|
|
153
|
+
);
|
|
154
|
+
});
|
|
137
155
|
}
|
|
138
156
|
|
|
139
157
|
/** Tries to find the member id for this receive slot if it hasn't got one */
|
|
@@ -33,6 +33,7 @@ import {
|
|
|
33
33
|
NatTypeUpdatedEventData,
|
|
34
34
|
ResultEventData,
|
|
35
35
|
} from './clusterReachability';
|
|
36
|
+
import {isReachabilityEnabled, resolveReachabilityProtocols} from './util';
|
|
36
37
|
import EventsScope from '../common/events/events-scope';
|
|
37
38
|
import BEHAVIORAL_METRICS from '../metrics/constants';
|
|
38
39
|
import Metrics from '../metrics';
|
|
@@ -194,7 +195,7 @@ export default class Reachability extends EventsScope {
|
|
|
194
195
|
*/
|
|
195
196
|
public async gatherReachability(trigger: string): Promise<ReachabilityResults> {
|
|
196
197
|
// @ts-ignore
|
|
197
|
-
if (!this.webex.config.meetings.enableReachabilityChecks) {
|
|
198
|
+
if (!isReachabilityEnabled(this.webex.config.meetings.enableReachabilityChecks)) {
|
|
198
199
|
throw new Error('enableReachabilityChecks is disabled in config');
|
|
199
200
|
}
|
|
200
201
|
|
|
@@ -515,7 +516,7 @@ export default class Reachability extends EventsScope {
|
|
|
515
516
|
* Returns true only if ALL protocols (UDP, TCP and TLS) have been tested and none
|
|
516
517
|
* of the media clusters where reachable with any of the protocols. This is done
|
|
517
518
|
* irrespective of the config, so for example:
|
|
518
|
-
* if config.meetings.
|
|
519
|
+
* if config.meetings.enableReachabilityChecks disables TLS,
|
|
519
520
|
* it will return false, because TLS reachability won't be tested,
|
|
520
521
|
* so we can't say for sure that media backend is unreachable over TLS.
|
|
521
522
|
*
|
|
@@ -888,14 +889,21 @@ export default class Reachability extends EventsScope {
|
|
|
888
889
|
|
|
889
890
|
this.startTime = performance.now();
|
|
890
891
|
|
|
892
|
+
const protocols = resolveReachabilityProtocols(
|
|
893
|
+
// @ts-ignore
|
|
894
|
+
this.webex.config.meetings.enableReachabilityChecks
|
|
895
|
+
);
|
|
896
|
+
|
|
897
|
+
const enabledProtocols = [
|
|
898
|
+
protocols.udp && 'UDP',
|
|
899
|
+
protocols.tcp && 'TCP',
|
|
900
|
+
protocols.tls && 'TLS',
|
|
901
|
+
].filter(Boolean);
|
|
902
|
+
|
|
891
903
|
LoggerProxy.logger.log(
|
|
892
|
-
`Reachability:index#performReachabilityChecks --> doing
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
}${
|
|
896
|
-
// @ts-ignore
|
|
897
|
-
this.webex.config.meetings.experimental.enableTlsReachability ? ',TLS' : ''
|
|
898
|
-
} reachability checks`
|
|
904
|
+
`Reachability:index#performReachabilityChecks --> doing ${enabledProtocols.join(
|
|
905
|
+
','
|
|
906
|
+
)} reachability checks`
|
|
899
907
|
);
|
|
900
908
|
|
|
901
909
|
this.resetResultCounters();
|
|
@@ -905,18 +913,14 @@ export default class Reachability extends EventsScope {
|
|
|
905
913
|
const cluster = clusterList[key];
|
|
906
914
|
|
|
907
915
|
// Linus doesn't support TCP reachability checks on video mesh nodes
|
|
908
|
-
const includeTcpReachability =
|
|
909
|
-
// @ts-ignore
|
|
910
|
-
this.webex.config.meetings.experimental.enableTcpReachability && !cluster.isVideoMesh;
|
|
916
|
+
const includeTcpReachability = protocols.tcp && !cluster.isVideoMesh;
|
|
911
917
|
|
|
912
918
|
if (!includeTcpReachability) {
|
|
913
919
|
cluster.tcp = [];
|
|
914
920
|
}
|
|
915
921
|
|
|
916
922
|
// Linus doesn't support xTLS reachability checks on video mesh nodes
|
|
917
|
-
const includeTlsReachability =
|
|
918
|
-
// @ts-ignore
|
|
919
|
-
this.webex.config.meetings.experimental.enableTlsReachability && !cluster.isVideoMesh;
|
|
923
|
+
const includeTlsReachability = protocols.tls && !cluster.isVideoMesh;
|
|
920
924
|
|
|
921
925
|
if (!includeTlsReachability) {
|
|
922
926
|
cluster.xtls = [];
|
|
@@ -2,6 +2,17 @@ import {IP_VERSION, Enum} from '../constants';
|
|
|
2
2
|
|
|
3
3
|
export type Protocol = 'udp' | 'tcp' | 'xtls';
|
|
4
4
|
|
|
5
|
+
// Per-protocol reachability flags, fully resolved.
|
|
6
|
+
export type ResolvedReachabilityProtocols = {
|
|
7
|
+
udp: boolean;
|
|
8
|
+
tcp: boolean;
|
|
9
|
+
tls: boolean;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export type ReachabilityProtocolConfig = Partial<Omit<ResolvedReachabilityProtocols, 'udp'>>;
|
|
13
|
+
|
|
14
|
+
export type EnableReachabilityChecksConfig = boolean | ReachabilityProtocolConfig;
|
|
15
|
+
|
|
5
16
|
/**
|
|
6
17
|
* Events emitted by ReachabilityPeerConnection
|
|
7
18
|
*/
|