@webex/plugin-meetings 3.8.0-next.6 → 3.8.0-next.61
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/dist/breakouts/breakout.js +1 -1
- package/dist/breakouts/index.js +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 +1 -0
- package/dist/config.js.map +1 -1
- package/dist/constants.js +17 -121
- package/dist/constants.js.map +1 -1
- package/dist/controls-options-manager/enums.js +2 -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 +52 -0
- package/dist/controls-options-manager/util.js.map +1 -1
- package/dist/interpretation/index.js +1 -1
- package/dist/interpretation/siLanguage.js +1 -1
- package/dist/locus-info/controlsUtils.js +28 -10
- package/dist/locus-info/controlsUtils.js.map +1 -1
- package/dist/locus-info/index.js +20 -1
- package/dist/locus-info/index.js.map +1 -1
- package/dist/locus-info/selfUtils.js +405 -418
- package/dist/locus-info/selfUtils.js.map +1 -1
- package/dist/media/index.js +8 -16
- package/dist/media/index.js.map +1 -1
- package/dist/meeting/in-meeting-actions.js +17 -1
- package/dist/meeting/in-meeting-actions.js.map +1 -1
- package/dist/meeting/index.js +556 -288
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/locusMediaRequest.js +0 -17
- package/dist/meeting/locusMediaRequest.js.map +1 -1
- package/dist/meeting/muteState.js +0 -2
- 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 +359 -60
- package/dist/meeting-info/meeting-info-v2.js.map +1 -1
- package/dist/meetings/index.js +91 -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 +10 -0
- package/dist/member/index.js.map +1 -1
- package/dist/member/util.js +3 -0
- package/dist/member/util.js.map +1 -1
- package/dist/members/index.js +23 -0
- package/dist/members/index.js.map +1 -1
- package/dist/members/request.js +21 -0
- package/dist/members/request.js.map +1 -1
- package/dist/members/util.js +15 -0
- package/dist/members/util.js.map +1 -1
- package/dist/metrics/constants.js +9 -0
- package/dist/metrics/constants.js.map +1 -1
- package/dist/reachability/clusterReachability.js +63 -27
- package/dist/reachability/clusterReachability.js.map +1 -1
- package/dist/reachability/index.js +112 -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 +1 -0
- package/dist/types/constants.d.ts +12 -85
- package/dist/types/controls-options-manager/enums.d.ts +3 -1
- package/dist/types/controls-options-manager/types.d.ts +7 -1
- package/dist/types/locus-info/index.d.ts +1 -0
- package/dist/types/locus-info/selfUtils.d.ts +247 -1
- package/dist/types/meeting/in-meeting-actions.d.ts +16 -0
- package/dist/types/meeting/index.d.ts +54 -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 +80 -0
- package/dist/types/meetings/index.d.ts +38 -0
- package/dist/types/member/index.d.ts +1 -0
- package/dist/types/members/index.d.ts +8 -0
- package/dist/types/members/request.d.ts +19 -0
- package/dist/types/members/util.d.ts +13 -0
- package/dist/types/metrics/constants.d.ts +9 -0
- 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 +1 -1
- package/package.json +23 -23
- package/src/common/errors/webex-errors.ts +8 -1
- package/src/config.ts +1 -0
- package/src/constants.ts +19 -90
- package/src/controls-options-manager/enums.ts +2 -0
- package/src/controls-options-manager/types.ts +11 -1
- package/src/controls-options-manager/util.ts +62 -0
- package/src/locus-info/controlsUtils.ts +44 -14
- package/src/locus-info/index.ts +23 -1
- package/src/locus-info/selfUtils.ts +451 -447
- package/src/media/index.ts +11 -21
- package/src/meeting/in-meeting-actions.ts +32 -0
- package/src/meeting/index.ts +372 -92
- package/src/meeting/locusMediaRequest.ts +0 -18
- package/src/meeting/muteState.ts +0 -2
- 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 +247 -6
- package/src/meetings/index.ts +107 -1
- package/src/meetings/util.ts +18 -0
- package/src/member/index.ts +11 -0
- package/src/member/util.ts +3 -0
- package/src/members/index.ts +25 -0
- package/src/members/request.ts +26 -0
- package/src/members/util.ts +16 -0
- package/src/metrics/constants.ts +9 -0
- package/src/reachability/clusterReachability.ts +73 -26
- package/src/reachability/index.ts +70 -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/test/unit/spec/controls-options-manager/util.js +120 -0
- package/test/unit/spec/locus-info/controlsUtils.js +103 -9
- package/test/unit/spec/locus-info/index.js +28 -0
- package/test/unit/spec/media/index.ts +36 -16
- package/test/unit/spec/meeting/in-meeting-actions.ts +19 -4
- package/test/unit/spec/meeting/index.js +528 -34
- package/test/unit/spec/meeting/locusMediaRequest.ts +0 -30
- package/test/unit/spec/meeting/muteState.js +0 -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 +443 -114
- package/test/unit/spec/meetings/index.js +120 -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 +103 -26
- package/test/unit/spec/members/request.js +45 -22
- package/test/unit/spec/members/utils.js +33 -0
- package/test/unit/spec/reachability/clusterReachability.ts +88 -56
- package/test/unit/spec/reachability/index.ts +101 -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/src/meeting/index.ts
CHANGED
@@ -60,11 +60,8 @@ import {
|
|
60
60
|
import LoggerProxy from '../common/logs/logger-proxy';
|
61
61
|
import EventsUtil from '../common/events/util';
|
62
62
|
import Trigger from '../common/events/trigger-proxy';
|
63
|
-
import Roap, {
|
64
|
-
|
65
|
-
type TurnServerInfo,
|
66
|
-
type TurnDiscoverySkipReason,
|
67
|
-
} from '../roap/index';
|
63
|
+
import Roap, {type TurnDiscoveryResult, type TurnDiscoverySkipReason} from '../roap/index';
|
64
|
+
import {type TurnServerInfo} from '../roap/types';
|
68
65
|
import Media, {type BundlePolicy} from '../media';
|
69
66
|
import MediaProperties from '../media/properties';
|
70
67
|
import MeetingStateMachine from './state';
|
@@ -103,7 +100,6 @@ import {
|
|
103
100
|
MEETING_STATE_MACHINE,
|
104
101
|
MEETING_STATE,
|
105
102
|
MEETINGS,
|
106
|
-
MQA_STATS,
|
107
103
|
NETWORK_STATUS,
|
108
104
|
ONLINE,
|
109
105
|
OFFLINE,
|
@@ -167,6 +163,7 @@ import Member from '../member';
|
|
167
163
|
import {BrbState, createBrbState} from './brbState';
|
168
164
|
import MultistreamNotSupportedError from '../common/errors/multistream-not-supported-error';
|
169
165
|
import JoinForbiddenError from '../common/errors/join-forbidden-error';
|
166
|
+
import {ReachabilityMetrics} from '../reachability/reachability.types';
|
170
167
|
|
171
168
|
// default callback so we don't call an undefined function, but in practice it should never be used
|
172
169
|
const DEFAULT_ICE_PHASE_CALLBACK = () => 'JOIN_MEETING_FINAL';
|
@@ -241,6 +238,8 @@ export type CallStateForMetrics = {
|
|
241
238
|
sessionCorrelationId?: string;
|
242
239
|
joinTrigger?: string;
|
243
240
|
loginType?: string;
|
241
|
+
userNameInput?: string;
|
242
|
+
emailInput?: string;
|
244
243
|
};
|
245
244
|
|
246
245
|
export const MEDIA_UPDATE_TYPE = {
|
@@ -263,6 +262,8 @@ type FetchMeetingInfoParams = {
|
|
263
262
|
sendCAevents?: boolean;
|
264
263
|
};
|
265
264
|
|
265
|
+
type MediaReachabilityMetrics = ReachabilityMetrics & {isSubnetReachable: boolean};
|
266
|
+
|
266
267
|
/**
|
267
268
|
* MediaDirection
|
268
269
|
* @typedef {Object} MediaDirection
|
@@ -648,6 +649,13 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
648
649
|
allowMediaInLobby: boolean;
|
649
650
|
localShareInstanceId: string;
|
650
651
|
remoteShareInstanceId: string;
|
652
|
+
shareCAEventSentStatus: {
|
653
|
+
transmitStart: boolean;
|
654
|
+
transmitStop: boolean;
|
655
|
+
receiveStart: boolean;
|
656
|
+
receiveStop: boolean;
|
657
|
+
};
|
658
|
+
|
651
659
|
turnDiscoverySkippedReason: TurnDiscoverySkipReason;
|
652
660
|
turnServerUsed: boolean;
|
653
661
|
areVoiceaEventsSetup = false;
|
@@ -716,6 +724,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
716
724
|
private rtcMetrics?: RtcMetrics;
|
717
725
|
private uploadLogsTimer?: ReturnType<typeof setTimeout>;
|
718
726
|
private logUploadIntervalIndex: number;
|
727
|
+
private mediaServerIp: string;
|
719
728
|
|
720
729
|
/**
|
721
730
|
* @param {Object} attrs
|
@@ -1420,6 +1429,19 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
1420
1429
|
*/
|
1421
1430
|
this.remoteShareInstanceId = null;
|
1422
1431
|
|
1432
|
+
/**
|
1433
|
+
* Status used for ensuring we do not oversend metrics
|
1434
|
+
* @instance
|
1435
|
+
* @private
|
1436
|
+
* @memberof Meeting
|
1437
|
+
*/
|
1438
|
+
this.shareCAEventSentStatus = {
|
1439
|
+
transmitStart: false,
|
1440
|
+
transmitStop: false,
|
1441
|
+
receiveStart: false,
|
1442
|
+
receiveStop: false,
|
1443
|
+
};
|
1444
|
+
|
1423
1445
|
/**
|
1424
1446
|
* The class that helps to control recording functions: start, stop, pause, resume, etc
|
1425
1447
|
* @instance
|
@@ -1579,6 +1601,19 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
1579
1601
|
* @memberof Meeting
|
1580
1602
|
*/
|
1581
1603
|
this.#isoLocalClientMeetingJoinTime = undefined;
|
1604
|
+
|
1605
|
+
// We clear the error cache of CA events on every new meeting instance
|
1606
|
+
// @ts-ignore - Fix type
|
1607
|
+
this.webex.internal.newMetrics.callDiagnosticMetrics.clearErrorCache();
|
1608
|
+
|
1609
|
+
/**
|
1610
|
+
* IP Address of the remote media server
|
1611
|
+
* @instance
|
1612
|
+
* @type {string}
|
1613
|
+
* @private
|
1614
|
+
* @memberof Meeting
|
1615
|
+
*/
|
1616
|
+
this.mediaServerIp = undefined;
|
1582
1617
|
}
|
1583
1618
|
|
1584
1619
|
/**
|
@@ -1627,6 +1662,38 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
1627
1662
|
this.callStateForMetrics.correlationId = correlationId;
|
1628
1663
|
}
|
1629
1664
|
|
1665
|
+
/**
|
1666
|
+
* Getter - Returns callStateForMetrics.userNameInput
|
1667
|
+
* @returns {string}
|
1668
|
+
*/
|
1669
|
+
get userNameInput() {
|
1670
|
+
return this.callStateForMetrics?.userNameInput;
|
1671
|
+
}
|
1672
|
+
|
1673
|
+
/**
|
1674
|
+
* Setter - sets callStateForMetrics.userNameInput
|
1675
|
+
* @param {string} userNameInput
|
1676
|
+
*/
|
1677
|
+
set userNameInput(userNameInput: string) {
|
1678
|
+
this.callStateForMetrics.userNameInput = userNameInput;
|
1679
|
+
}
|
1680
|
+
|
1681
|
+
/**
|
1682
|
+
* Getter - Returns callStateForMetrics.emailInput
|
1683
|
+
* @returns {string}
|
1684
|
+
*/
|
1685
|
+
get emailInput() {
|
1686
|
+
return this.callStateForMetrics?.emailInput;
|
1687
|
+
}
|
1688
|
+
|
1689
|
+
/**
|
1690
|
+
* Setter - sets callStateForMetrics.emailInput
|
1691
|
+
* @param {string} emailInput
|
1692
|
+
*/
|
1693
|
+
set emailInput(emailInput: string) {
|
1694
|
+
this.callStateForMetrics.emailInput = emailInput;
|
1695
|
+
}
|
1696
|
+
|
1630
1697
|
/**
|
1631
1698
|
* Getter - Returns callStateForMetrics.sessionCorrelationId
|
1632
1699
|
* @returns {string}
|
@@ -1652,6 +1719,33 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
1652
1719
|
return this.#isoLocalClientMeetingJoinTime;
|
1653
1720
|
}
|
1654
1721
|
|
1722
|
+
/**
|
1723
|
+
* Setter - sets isoLocalClientMeetingJoinTime
|
1724
|
+
* This will be set once on meeting join, and not updated again
|
1725
|
+
* this will always produce an ISO string
|
1726
|
+
* If the iso string is invalid, it will fallback to the current system time
|
1727
|
+
* @param {string | undefined} time
|
1728
|
+
*/
|
1729
|
+
set isoLocalClientMeetingJoinTime(time: string | undefined) {
|
1730
|
+
const fallback = new Date().toISOString();
|
1731
|
+
if (!time) {
|
1732
|
+
this.#isoLocalClientMeetingJoinTime = fallback;
|
1733
|
+
} else {
|
1734
|
+
const date = new Date(time);
|
1735
|
+
|
1736
|
+
// Check if the date is valid
|
1737
|
+
if (Number.isNaN(date.getTime())) {
|
1738
|
+
LoggerProxy.logger.info(
|
1739
|
+
// @ts-ignore
|
1740
|
+
`Meeting:index#isoLocalClientMeetingJoinTime --> Invalid date provided: ${time}. Falling back to system clock.`
|
1741
|
+
);
|
1742
|
+
this.#isoLocalClientMeetingJoinTime = fallback;
|
1743
|
+
} else {
|
1744
|
+
this.#isoLocalClientMeetingJoinTime = date.toISOString();
|
1745
|
+
}
|
1746
|
+
}
|
1747
|
+
}
|
1748
|
+
|
1655
1749
|
/**
|
1656
1750
|
* Set meeting info and trigger `MEETING_INFO_AVAILABLE` event
|
1657
1751
|
* @param {any} info
|
@@ -2793,6 +2887,24 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
2793
2887
|
{state}
|
2794
2888
|
);
|
2795
2889
|
});
|
2890
|
+
|
2891
|
+
this.locusInfo.on(LOCUSINFO.EVENTS.CONTROLS_ANNOTATION_CHANGED, ({state}) => {
|
2892
|
+
Trigger.trigger(
|
2893
|
+
this,
|
2894
|
+
{file: 'meeting/index', function: 'setupLocusControlsListener'},
|
2895
|
+
EVENT_TRIGGERS.MEETING_CONTROLS_ANNOTATION_UPDATED,
|
2896
|
+
{state}
|
2897
|
+
);
|
2898
|
+
});
|
2899
|
+
|
2900
|
+
this.locusInfo.on(LOCUSINFO.EVENTS.CONTROLS_REMOTE_DESKTOP_CONTROL_CHANGED, ({state}) => {
|
2901
|
+
Trigger.trigger(
|
2902
|
+
this,
|
2903
|
+
{file: 'meeting/index', function: 'setupLocusControlsListener'},
|
2904
|
+
EVENT_TRIGGERS.MEETING_CONTROLS_REMOTE_DESKTOP_CONTROL_UPDATED,
|
2905
|
+
{state}
|
2906
|
+
);
|
2907
|
+
});
|
2796
2908
|
}
|
2797
2909
|
|
2798
2910
|
/**
|
@@ -2965,6 +3077,8 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
2965
3077
|
case SHARE_STATUS.REMOTE_SHARE_ACTIVE: {
|
2966
3078
|
const sendStartedSharingRemote = () => {
|
2967
3079
|
this.remoteShareInstanceId = contentShare.shareInstanceId;
|
3080
|
+
this.shareCAEventSentStatus.receiveStart = false;
|
3081
|
+
this.shareCAEventSentStatus.receiveStop = false;
|
2968
3082
|
|
2969
3083
|
Trigger.trigger(
|
2970
3084
|
this,
|
@@ -3018,6 +3132,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
3018
3132
|
},
|
3019
3133
|
options: {meetingId: this.id},
|
3020
3134
|
});
|
3135
|
+
|
3021
3136
|
break;
|
3022
3137
|
|
3023
3138
|
case SHARE_STATUS.WHITEBOARD_SHARE_ACTIVE:
|
@@ -3058,6 +3173,8 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
3058
3173
|
// if we got here, then some remote participant has stolen
|
3059
3174
|
// the presentation from another remote participant
|
3060
3175
|
this.remoteShareInstanceId = contentShare.shareInstanceId;
|
3176
|
+
this.shareCAEventSentStatus.receiveStart = false;
|
3177
|
+
this.shareCAEventSentStatus.receiveStop = false;
|
3061
3178
|
|
3062
3179
|
Trigger.trigger(
|
3063
3180
|
this,
|
@@ -3741,7 +3858,13 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
3741
3858
|
return Promise.reject(error);
|
3742
3859
|
}
|
3743
3860
|
|
3744
|
-
return this.brbState.enable(enabled, this.sendSlotManager)
|
3861
|
+
return this.brbState.enable(enabled, this.sendSlotManager).then(() => {
|
3862
|
+
if (this.audio && enabled) {
|
3863
|
+
// locus mutes the participant with brb enabled request,
|
3864
|
+
// so we need to explicitly update remote mute for correct logic flow
|
3865
|
+
this.audio.handleServerRemoteMuteUpdate(this, enabled);
|
3866
|
+
}
|
3867
|
+
});
|
3745
3868
|
}
|
3746
3869
|
|
3747
3870
|
/**
|
@@ -3933,7 +4056,10 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
3933
4056
|
canAdmitParticipant: MeetingUtil.canAdmitParticipant(this.userDisplayHints),
|
3934
4057
|
canLock: MeetingUtil.canUserLock(this.userDisplayHints),
|
3935
4058
|
canUnlock: MeetingUtil.canUserUnlock(this.userDisplayHints),
|
3936
|
-
canShareWhiteBoard: MeetingUtil.canShareWhiteBoard(
|
4059
|
+
canShareWhiteBoard: MeetingUtil.canShareWhiteBoard(
|
4060
|
+
this.userDisplayHints,
|
4061
|
+
this.selfUserPolicies
|
4062
|
+
),
|
3937
4063
|
canSetDisallowUnmute: ControlsOptionsUtil.canSetDisallowUnmute(this.userDisplayHints),
|
3938
4064
|
canUnsetDisallowUnmute: ControlsOptionsUtil.canUnsetDisallowUnmute(this.userDisplayHints),
|
3939
4065
|
canSetMuteOnEntry: ControlsOptionsUtil.canSetMuteOnEntry(this.userDisplayHints),
|
@@ -3982,6 +4108,9 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
3982
4108
|
this.inMeetingActions.canSendReactions,
|
3983
4109
|
this.userDisplayHints
|
3984
4110
|
),
|
4111
|
+
requiresPostMeetingDataConsentPrompt: MeetingUtil.requiresPostMeetingDataConsentPrompt(
|
4112
|
+
this.userDisplayHints
|
4113
|
+
),
|
3985
4114
|
canManageBreakout: MeetingUtil.canManageBreakout(this.userDisplayHints),
|
3986
4115
|
canStartBreakout: MeetingUtil.canStartBreakout(this.userDisplayHints),
|
3987
4116
|
canBroadcastMessageToBreakout: MeetingUtil.canBroadcastMessageToBreakout(
|
@@ -3997,6 +4126,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
3997
4126
|
this.userDisplayHints
|
3998
4127
|
),
|
3999
4128
|
canUserRenameOthers: MeetingUtil.canUserRenameOthers(this.userDisplayHints),
|
4129
|
+
canMoveToLobby: MeetingUtil.canMoveToLobby(this.userDisplayHints),
|
4000
4130
|
canMuteAll: ControlsOptionsUtil.hasHints({
|
4001
4131
|
requiredHints: [DISPLAY_HINTS.MUTE_ALL],
|
4002
4132
|
displayHints: this.userDisplayHints,
|
@@ -4131,6 +4261,14 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
4131
4261
|
requiredPolicies: [SELF_POLICY.SUPPORT_FILE_TRANSFER],
|
4132
4262
|
policies: this.selfUserPolicies,
|
4133
4263
|
}),
|
4264
|
+
canRealtimeCloseCaption: ControlsOptionsUtil.hasPolicies({
|
4265
|
+
requiredPolicies: [SELF_POLICY.SUPPORT_REALTIME_CLOSE_CAPTION],
|
4266
|
+
policies: this.selfUserPolicies,
|
4267
|
+
}),
|
4268
|
+
canRealtimeCloseCaptionManual: ControlsOptionsUtil.hasPolicies({
|
4269
|
+
requiredPolicies: [SELF_POLICY.SUPPORT_REALTIME_CLOSE_CAPTION_MANUAL],
|
4270
|
+
policies: this.selfUserPolicies,
|
4271
|
+
}),
|
4134
4272
|
canChat: ControlsOptionsUtil.hasPolicies({
|
4135
4273
|
requiredPolicies: [SELF_POLICY.SUPPORT_CHAT],
|
4136
4274
|
policies: this.selfUserPolicies,
|
@@ -4177,6 +4315,22 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
4177
4315
|
requiredPolicies: [SELF_POLICY.SUPPORT_ANNOTATION],
|
4178
4316
|
policies: this.selfUserPolicies,
|
4179
4317
|
}),
|
4318
|
+
canEnableAnnotation: ControlsOptionsUtil.hasHints({
|
4319
|
+
requiredHints: [DISPLAY_HINTS.ENABLE_ANNOTATION_MEETING_OPTION],
|
4320
|
+
displayHints: this.userDisplayHints,
|
4321
|
+
}),
|
4322
|
+
canDisableAnnotation: ControlsOptionsUtil.hasHints({
|
4323
|
+
requiredHints: [DISPLAY_HINTS.DISABLE_ANNOTATION_MEETING_OPTION],
|
4324
|
+
displayHints: this.userDisplayHints,
|
4325
|
+
}),
|
4326
|
+
canEnableRemoteDesktopControl: ControlsOptionsUtil.hasHints({
|
4327
|
+
requiredHints: [DISPLAY_HINTS.ENABLE_RDC_MEETING_OPTION],
|
4328
|
+
displayHints: this.userDisplayHints,
|
4329
|
+
}),
|
4330
|
+
canDisableRemoteDesktopControl: ControlsOptionsUtil.hasHints({
|
4331
|
+
requiredHints: [DISPLAY_HINTS.DISABLE_RDC_MEETING_OPTION],
|
4332
|
+
displayHints: this.userDisplayHints,
|
4333
|
+
}),
|
4180
4334
|
}) || changed;
|
4181
4335
|
}
|
4182
4336
|
if (changed) {
|
@@ -5684,8 +5838,6 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
5684
5838
|
// @ts-ignore
|
5685
5839
|
this.webex.internal.device.meetingStarted();
|
5686
5840
|
|
5687
|
-
this.#isoLocalClientMeetingJoinTime = new Date().toISOString();
|
5688
|
-
|
5689
5841
|
LoggerProxy.logger.log('Meeting:index#join --> Success');
|
5690
5842
|
|
5691
5843
|
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.JOIN_SUCCESS, {
|
@@ -6146,10 +6298,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
6146
6298
|
},
|
6147
6299
|
options: {meetingId: this.id, rawError: error},
|
6148
6300
|
});
|
6149
|
-
} else if (
|
6150
|
-
error instanceof Errors.SdpOfferHandlingError ||
|
6151
|
-
error instanceof Errors.SdpAnswerHandlingError
|
6152
|
-
) {
|
6301
|
+
} else if (error instanceof Errors.SdpOfferHandlingError) {
|
6153
6302
|
sendBehavioralMetric(BEHAVIORAL_METRICS.PEERCONNECTION_FAILURE, error, this.correlationId);
|
6154
6303
|
|
6155
6304
|
// @ts-ignore
|
@@ -6160,6 +6309,24 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
6160
6309
|
},
|
6161
6310
|
options: {meetingId: this.id, rawError: error},
|
6162
6311
|
});
|
6312
|
+
} else if (error instanceof Errors.SdpAnswerHandlingError) {
|
6313
|
+
sendBehavioralMetric(BEHAVIORAL_METRICS.PEERCONNECTION_FAILURE, error, this.correlationId);
|
6314
|
+
|
6315
|
+
// @ts-ignore
|
6316
|
+
this.webex.internal.newMetrics.submitClientEvent({
|
6317
|
+
name: 'client.media-engine.remote-sdp-received',
|
6318
|
+
payload: {
|
6319
|
+
canProceed: false,
|
6320
|
+
},
|
6321
|
+
options: {meetingId: this.id, rawError: error},
|
6322
|
+
});
|
6323
|
+
|
6324
|
+
if (this.deferSDPAnswer) {
|
6325
|
+
clearTimeout(this.sdpResponseTimer);
|
6326
|
+
this.sdpResponseTimer = undefined;
|
6327
|
+
|
6328
|
+
this.deferSDPAnswer.reject();
|
6329
|
+
}
|
6163
6330
|
} else if (error instanceof Errors.SdpError) {
|
6164
6331
|
// this covers also the case of Errors.IceGatheringError which extends Errors.SdpError
|
6165
6332
|
sendBehavioralMetric(BEHAVIORAL_METRICS.INVALID_ICE_CANDIDATE, error, this.correlationId);
|
@@ -6187,6 +6354,11 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
6187
6354
|
? MeetingsUtil.getMediaServer(roapMessage.sdp)
|
6188
6355
|
: undefined;
|
6189
6356
|
|
6357
|
+
const mediaServerIp =
|
6358
|
+
roapMessage.messageType === 'ANSWER'
|
6359
|
+
? MeetingsUtil.getMediaServerIp(roapMessage.sdp)
|
6360
|
+
: undefined;
|
6361
|
+
|
6190
6362
|
if (this.isMultistream && mediaServer && mediaServer !== 'homer') {
|
6191
6363
|
throw new MultistreamNotSupportedError(
|
6192
6364
|
`Client asked for multistream backend (Homer), but got ${mediaServer} instead`
|
@@ -6197,6 +6369,10 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
6197
6369
|
if (mediaServer) {
|
6198
6370
|
this.mediaProperties.webrtcMediaConnection.mediaServer = mediaServer;
|
6199
6371
|
}
|
6372
|
+
|
6373
|
+
if (this.isMultistream && mediaServerIp) {
|
6374
|
+
this.mediaServerIp = mediaServerIp;
|
6375
|
+
}
|
6200
6376
|
};
|
6201
6377
|
|
6202
6378
|
/**
|
@@ -6654,20 +6830,20 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
6654
6830
|
* @memberof Meetings
|
6655
6831
|
*/
|
6656
6832
|
setupStatsAnalyzerEventHandlers = () => {
|
6657
|
-
this.statsAnalyzer.on(StatsAnalyzerEventNames.MEDIA_QUALITY, (
|
6658
|
-
//
|
6659
|
-
|
6660
|
-
|
6661
|
-
|
6662
|
-
|
6663
|
-
|
6664
|
-
|
6665
|
-
|
6833
|
+
this.statsAnalyzer.on(StatsAnalyzerEventNames.MEDIA_QUALITY, (event) => {
|
6834
|
+
// Add IP address from geoHintInfo if missing.
|
6835
|
+
if (event.data.intervalMetadata.maskedPeerReflexiveIP === '0.0.0.0') {
|
6836
|
+
// @ts-ignore fix type
|
6837
|
+
const clientAddressFromGeoHint = this.webex.meetings.geoHintInfo?.clientAddress;
|
6838
|
+
if (clientAddressFromGeoHint) {
|
6839
|
+
event.data.intervalMetadata.maskedPeerReflexiveIP =
|
6840
|
+
CallDiagnosticUtils.anonymizeIPAddress(clientAddressFromGeoHint);
|
6841
|
+
}
|
6842
|
+
}
|
6666
6843
|
|
6844
|
+
// Count members that are in the meeting.
|
6667
6845
|
const {members} = this.getMembers().membersCollection;
|
6668
|
-
|
6669
|
-
// Count members that are in the meeting
|
6670
|
-
options.data.intervalMetadata.meetingUserCount = Object.values(members).filter(
|
6846
|
+
event.data.intervalMetadata.meetingUserCount = Object.values(members).filter(
|
6671
6847
|
(member: Member) => member.isInMeeting
|
6672
6848
|
).length;
|
6673
6849
|
|
@@ -6676,10 +6852,10 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
6676
6852
|
name: 'client.mediaquality.event',
|
6677
6853
|
options: {
|
6678
6854
|
meetingId: this.id,
|
6679
|
-
networkType:
|
6855
|
+
networkType: this.statsAnalyzer.getNetworkType(),
|
6680
6856
|
},
|
6681
6857
|
payload: {
|
6682
|
-
intervals: [
|
6858
|
+
intervals: [event.data],
|
6683
6859
|
},
|
6684
6860
|
});
|
6685
6861
|
});
|
@@ -6694,30 +6870,42 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
6694
6870
|
EVENT_TRIGGERS.MEETING_MEDIA_LOCAL_STARTED,
|
6695
6871
|
data
|
6696
6872
|
);
|
6697
|
-
|
6698
|
-
|
6699
|
-
|
6700
|
-
|
6701
|
-
|
6702
|
-
|
6703
|
-
|
6704
|
-
|
6705
|
-
|
6706
|
-
|
6707
|
-
|
6873
|
+
if (data.mediaType !== 'share' || !this.shareCAEventSentStatus.transmitStart) {
|
6874
|
+
// @ts-ignore
|
6875
|
+
this.webex.internal.newMetrics.submitClientEvent({
|
6876
|
+
name: 'client.media.tx.start',
|
6877
|
+
payload: {
|
6878
|
+
mediaType: data.mediaType,
|
6879
|
+
shareInstanceId: data.mediaType === 'share' ? this.localShareInstanceId : undefined,
|
6880
|
+
},
|
6881
|
+
options: {
|
6882
|
+
meetingId: this.id,
|
6883
|
+
},
|
6884
|
+
});
|
6885
|
+
|
6886
|
+
if (data.mediaType === 'share') {
|
6887
|
+
this.shareCAEventSentStatus.transmitStart = true;
|
6888
|
+
}
|
6889
|
+
}
|
6708
6890
|
});
|
6709
6891
|
this.statsAnalyzer.on(StatsAnalyzerEventNames.LOCAL_MEDIA_STOPPED, (data) => {
|
6710
|
-
|
6711
|
-
|
6712
|
-
|
6713
|
-
|
6714
|
-
|
6715
|
-
|
6716
|
-
|
6717
|
-
|
6718
|
-
|
6719
|
-
|
6720
|
-
|
6892
|
+
if (data.mediaType !== 'share' || !this.shareCAEventSentStatus.transmitStop) {
|
6893
|
+
// @ts-ignore
|
6894
|
+
this.webex.internal.newMetrics.submitClientEvent({
|
6895
|
+
name: 'client.media.tx.stop',
|
6896
|
+
payload: {
|
6897
|
+
mediaType: data.mediaType,
|
6898
|
+
shareInstanceId: data.mediaType === 'share' ? this.localShareInstanceId : undefined,
|
6899
|
+
},
|
6900
|
+
options: {
|
6901
|
+
meetingId: this.id,
|
6902
|
+
},
|
6903
|
+
});
|
6904
|
+
|
6905
|
+
if (data.mediaType === 'share') {
|
6906
|
+
this.shareCAEventSentStatus.transmitStop = true;
|
6907
|
+
}
|
6908
|
+
}
|
6721
6909
|
});
|
6722
6910
|
this.statsAnalyzer.on(StatsAnalyzerEventNames.REMOTE_MEDIA_STARTED, (data) => {
|
6723
6911
|
Trigger.trigger(
|
@@ -6729,57 +6917,65 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
6729
6917
|
EVENT_TRIGGERS.MEETING_MEDIA_REMOTE_STARTED,
|
6730
6918
|
data
|
6731
6919
|
);
|
6732
|
-
|
6733
|
-
this.webex.internal.newMetrics.submitClientEvent({
|
6734
|
-
name: 'client.media.rx.start',
|
6735
|
-
payload: {
|
6736
|
-
mediaType: data.mediaType,
|
6737
|
-
shareInstanceId: data.mediaType === 'share' ? this.remoteShareInstanceId : undefined,
|
6738
|
-
},
|
6739
|
-
options: {
|
6740
|
-
meetingId: this.id,
|
6741
|
-
},
|
6742
|
-
});
|
6743
|
-
|
6744
|
-
if (data.mediaType === 'share') {
|
6920
|
+
if (data.mediaType !== 'share' || !this.shareCAEventSentStatus.receiveStart) {
|
6745
6921
|
// @ts-ignore
|
6746
6922
|
this.webex.internal.newMetrics.submitClientEvent({
|
6747
|
-
name: 'client.media.
|
6923
|
+
name: 'client.media.rx.start',
|
6748
6924
|
payload: {
|
6749
|
-
mediaType:
|
6750
|
-
shareInstanceId: this.remoteShareInstanceId,
|
6925
|
+
mediaType: data.mediaType,
|
6926
|
+
shareInstanceId: data.mediaType === 'share' ? this.remoteShareInstanceId : undefined,
|
6751
6927
|
},
|
6752
6928
|
options: {
|
6753
6929
|
meetingId: this.id,
|
6754
6930
|
},
|
6755
6931
|
});
|
6932
|
+
|
6933
|
+
if (data.mediaType === 'share') {
|
6934
|
+
// @ts-ignore
|
6935
|
+
this.webex.internal.newMetrics.submitClientEvent({
|
6936
|
+
name: 'client.media.render.start',
|
6937
|
+
payload: {
|
6938
|
+
mediaType: 'share',
|
6939
|
+
shareInstanceId: this.remoteShareInstanceId,
|
6940
|
+
},
|
6941
|
+
options: {
|
6942
|
+
meetingId: this.id,
|
6943
|
+
},
|
6944
|
+
});
|
6945
|
+
|
6946
|
+
this.shareCAEventSentStatus.receiveStart = true;
|
6947
|
+
}
|
6756
6948
|
}
|
6757
6949
|
});
|
6758
6950
|
this.statsAnalyzer.on(StatsAnalyzerEventNames.REMOTE_MEDIA_STOPPED, (data) => {
|
6759
|
-
|
6760
|
-
this.webex.internal.newMetrics.submitClientEvent({
|
6761
|
-
name: 'client.media.rx.stop',
|
6762
|
-
payload: {
|
6763
|
-
mediaType: data.mediaType,
|
6764
|
-
shareInstanceId: data.mediaType === 'share' ? this.remoteShareInstanceId : undefined,
|
6765
|
-
},
|
6766
|
-
options: {
|
6767
|
-
meetingId: this.id,
|
6768
|
-
},
|
6769
|
-
});
|
6770
|
-
|
6771
|
-
if (data.mediaType === 'share') {
|
6951
|
+
if (data.mediaType !== 'share' || !this.shareCAEventSentStatus.receiveStop) {
|
6772
6952
|
// @ts-ignore
|
6773
6953
|
this.webex.internal.newMetrics.submitClientEvent({
|
6774
|
-
name: 'client.media.
|
6954
|
+
name: 'client.media.rx.stop',
|
6775
6955
|
payload: {
|
6776
|
-
mediaType:
|
6777
|
-
shareInstanceId: this.remoteShareInstanceId,
|
6956
|
+
mediaType: data.mediaType,
|
6957
|
+
shareInstanceId: data.mediaType === 'share' ? this.remoteShareInstanceId : undefined,
|
6778
6958
|
},
|
6779
6959
|
options: {
|
6780
6960
|
meetingId: this.id,
|
6781
6961
|
},
|
6782
6962
|
});
|
6963
|
+
|
6964
|
+
if (data.mediaType === 'share') {
|
6965
|
+
// @ts-ignore
|
6966
|
+
this.webex.internal.newMetrics.submitClientEvent({
|
6967
|
+
name: 'client.media.render.stop',
|
6968
|
+
payload: {
|
6969
|
+
mediaType: 'share',
|
6970
|
+
shareInstanceId: this.remoteShareInstanceId,
|
6971
|
+
},
|
6972
|
+
options: {
|
6973
|
+
meetingId: this.id,
|
6974
|
+
},
|
6975
|
+
});
|
6976
|
+
|
6977
|
+
this.shareCAEventSentStatus.receiveStop = true;
|
6978
|
+
}
|
6783
6979
|
}
|
6784
6980
|
});
|
6785
6981
|
};
|
@@ -6796,7 +6992,10 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
6796
6992
|
* @param {AddMediaOptions} [options] Options for enabling/disabling audio/video
|
6797
6993
|
* @returns {RoapMediaConnection | MultistreamRoapMediaConnection}
|
6798
6994
|
*/
|
6799
|
-
private async createMediaConnection(
|
6995
|
+
private async createMediaConnection(
|
6996
|
+
turnServerInfo?: TurnServerInfo,
|
6997
|
+
bundlePolicy?: BundlePolicy
|
6998
|
+
) {
|
6800
6999
|
this.rtcMetrics = this.isMultistream
|
6801
7000
|
? // @ts-ignore
|
6802
7001
|
new RtcMetrics(this.webex, {meetingId: this.id}, this.correlationId)
|
@@ -6821,6 +7020,8 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
6821
7020
|
bundlePolicy,
|
6822
7021
|
// @ts-ignore - config coming from registerPlugin
|
6823
7022
|
iceCandidatesTimeout: this.config.iceCandidatesGatheringTimeout,
|
7023
|
+
// @ts-ignore - config coming from registerPlugin
|
7024
|
+
disableAudioMainDtx: this.config.experimental.disableAudioMainDtx,
|
6824
7025
|
}
|
6825
7026
|
);
|
6826
7027
|
|
@@ -6971,12 +7172,18 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
6971
7172
|
},
|
6972
7173
|
options: {
|
6973
7174
|
meetingId: this.id,
|
7175
|
+
rawError: error,
|
6974
7176
|
},
|
6975
7177
|
});
|
6976
7178
|
}
|
6977
|
-
|
7179
|
+
|
7180
|
+
const timedOutError = new Error(
|
6978
7181
|
`Timed out waiting for media connection to be connected, correlationId=${this.correlationId}`
|
6979
7182
|
);
|
7183
|
+
|
7184
|
+
timedOutError.cause = error;
|
7185
|
+
|
7186
|
+
throw timedOutError;
|
6980
7187
|
}
|
6981
7188
|
}
|
6982
7189
|
|
@@ -6997,6 +7204,12 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
6997
7204
|
networkQualityMonitor: this.networkQualityMonitor,
|
6998
7205
|
isMultistream: this.isMultistream,
|
6999
7206
|
});
|
7207
|
+
this.shareCAEventSentStatus = {
|
7208
|
+
transmitStart: false,
|
7209
|
+
transmitStop: false,
|
7210
|
+
receiveStart: false,
|
7211
|
+
receiveStop: false,
|
7212
|
+
};
|
7000
7213
|
this.setupStatsAnalyzerEventHandlers();
|
7001
7214
|
this.networkQualityMonitor.on(
|
7002
7215
|
NetworkQualityEventNames.NETWORK_QUALITY,
|
@@ -7031,6 +7244,9 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
7031
7244
|
ROAP_OFFER_ANSWER_EXCHANGE_TIMEOUT / 1000
|
7032
7245
|
} seconds`
|
7033
7246
|
);
|
7247
|
+
|
7248
|
+
const error = new Error('Timed out waiting for REMOTE SDP ANSWER');
|
7249
|
+
|
7034
7250
|
// @ts-ignore
|
7035
7251
|
this.webex.internal.newMetrics.submitClientEvent({
|
7036
7252
|
name: 'client.media-engine.remote-sdp-received',
|
@@ -7043,10 +7259,10 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
7043
7259
|
}),
|
7044
7260
|
],
|
7045
7261
|
},
|
7046
|
-
options: {meetingId: this.id, rawError:
|
7262
|
+
options: {meetingId: this.id, rawError: error},
|
7047
7263
|
});
|
7048
7264
|
|
7049
|
-
deferSDPAnswer.reject(
|
7265
|
+
deferSDPAnswer.reject(error);
|
7050
7266
|
}, ROAP_OFFER_ANSWER_EXCHANGE_TIMEOUT);
|
7051
7267
|
|
7052
7268
|
LoggerProxy.logger.info(`${LOG_HEADER} waiting for REMOTE SDP ANSWER...`);
|
@@ -7151,7 +7367,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
7151
7367
|
error
|
7152
7368
|
);
|
7153
7369
|
|
7154
|
-
throw new AddMediaFailed();
|
7370
|
+
throw new AddMediaFailed(error);
|
7155
7371
|
}
|
7156
7372
|
}
|
7157
7373
|
|
@@ -7566,10 +7782,11 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
7566
7782
|
|
7567
7783
|
const {connectionType, selectedCandidatePairChanges, numTransports} =
|
7568
7784
|
await this.mediaProperties.getCurrentConnectionInfo();
|
7569
|
-
|
7570
|
-
const reachabilityStats = await this.webex.meetings.reachability.getReachabilityMetrics();
|
7785
|
+
|
7571
7786
|
const iceCandidateErrors = Object.fromEntries(this.iceCandidateErrors);
|
7572
7787
|
|
7788
|
+
const reachabilityMetrics = await this.getMediaReachabilityMetricFields();
|
7789
|
+
|
7573
7790
|
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.ADD_MEDIA_SUCCESS, {
|
7574
7791
|
correlation_id: this.correlationId,
|
7575
7792
|
locus_id: this.locusUrl.split('/').pop(),
|
@@ -7579,7 +7796,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
7579
7796
|
isMultistream: this.isMultistream,
|
7580
7797
|
retriedWithTurnServer: this.addMediaData.retriedWithTurnServer,
|
7581
7798
|
isJoinWithMediaRetry: this.joinWithMediaRetryInfo.isRetry,
|
7582
|
-
...
|
7799
|
+
...reachabilityMetrics,
|
7583
7800
|
...iceCandidateErrors,
|
7584
7801
|
iceCandidatesCount: this.iceCandidatesCount,
|
7585
7802
|
});
|
@@ -7601,7 +7818,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
7601
7818
|
LoggerProxy.logger.error(`${LOG_HEADER} failed to establish media connection: `, error);
|
7602
7819
|
|
7603
7820
|
// @ts-ignore
|
7604
|
-
const reachabilityMetrics = await this.
|
7821
|
+
const reachabilityMetrics = await this.getMediaReachabilityMetricFields();
|
7605
7822
|
|
7606
7823
|
const {selectedCandidatePairChanges, numTransports} =
|
7607
7824
|
await this.mediaProperties.getCurrentConnectionInfo();
|
@@ -8681,6 +8898,9 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
8681
8898
|
LoggerProxy.logger.log(
|
8682
8899
|
`Meeting:index#handleShareVideoStreamMuteStateChange --> Share video stream mute state changed to muted ${muted}`
|
8683
8900
|
);
|
8901
|
+
|
8902
|
+
const shareVideoStreamSettings = this.mediaProperties?.shareVideoStream?.getSettings();
|
8903
|
+
|
8684
8904
|
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.MEETING_SHARE_VIDEO_MUTE_STATE_CHANGE, {
|
8685
8905
|
correlationId: this.correlationId,
|
8686
8906
|
muted,
|
@@ -8689,8 +8909,9 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
8689
8909
|
// SDK to TypeScript 5, which may affect other packages, use bracket notation for now, since
|
8690
8910
|
// all we're doing here is adding metrics.
|
8691
8911
|
// eslint-disable-next-line dot-notation
|
8692
|
-
displaySurface:
|
8912
|
+
displaySurface: shareVideoStreamSettings?.['displaySurface'],
|
8693
8913
|
isMultistream: this.isMultistream,
|
8914
|
+
frameRate: shareVideoStreamSettings?.frameRate,
|
8694
8915
|
});
|
8695
8916
|
};
|
8696
8917
|
|
@@ -9017,6 +9238,23 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
9017
9238
|
});
|
9018
9239
|
}
|
9019
9240
|
|
9241
|
+
/**
|
9242
|
+
* Method to set post meeting data consent.
|
9243
|
+
*
|
9244
|
+
* @param {boolean} accept - whether consent accepted or declined
|
9245
|
+
* @returns {Promise}
|
9246
|
+
* @public
|
9247
|
+
* @memberof Meeting
|
9248
|
+
*/
|
9249
|
+
public setPostMeetingDataConsent(accept: boolean) {
|
9250
|
+
return this.meetingRequest.setPostMeetingDataConsent({
|
9251
|
+
postMeetingDataConsent: accept,
|
9252
|
+
locusUrl: this.locusUrl,
|
9253
|
+
deviceUrl: this.deviceUrl,
|
9254
|
+
selfId: this.members.selfId,
|
9255
|
+
});
|
9256
|
+
}
|
9257
|
+
|
9020
9258
|
/**
|
9021
9259
|
* Throws if we don't have a media connection created
|
9022
9260
|
*
|
@@ -9257,6 +9495,8 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
9257
9495
|
|
9258
9496
|
if (floorRequestNeeded) {
|
9259
9497
|
this.localShareInstanceId = uuid.v4();
|
9498
|
+
this.shareCAEventSentStatus.transmitStart = false;
|
9499
|
+
this.shareCAEventSentStatus.transmitStop = false;
|
9260
9500
|
|
9261
9501
|
// @ts-ignore
|
9262
9502
|
this.webex.internal.newMetrics.submitClientEvent({
|
@@ -9384,4 +9624,44 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
9384
9624
|
|
9385
9625
|
return Promise.resolve();
|
9386
9626
|
}
|
9627
|
+
|
9628
|
+
/**
|
9629
|
+
* Gets the media reachability metrics
|
9630
|
+
*
|
9631
|
+
* @returns {Promise<MediaReachabilityMetrics>}
|
9632
|
+
*/
|
9633
|
+
private async getMediaReachabilityMetricFields(): Promise<MediaReachabilityMetrics> {
|
9634
|
+
const reachabilityMetrics: ReachabilityMetrics =
|
9635
|
+
// @ts-ignore
|
9636
|
+
await this.webex.meetings.reachability.getReachabilityMetrics();
|
9637
|
+
|
9638
|
+
const successKeys: Array<keyof ReachabilityMetrics> = [
|
9639
|
+
'reachability_public_udp_success',
|
9640
|
+
'reachability_public_tcp_success',
|
9641
|
+
'reachability_public_xtls_success',
|
9642
|
+
'reachability_vmn_udp_success',
|
9643
|
+
'reachability_vmn_tcp_success',
|
9644
|
+
'reachability_vmn_xtls_success',
|
9645
|
+
];
|
9646
|
+
|
9647
|
+
const totalSuccessCases = successKeys.reduce((total, key) => {
|
9648
|
+
const value = reachabilityMetrics[key];
|
9649
|
+
if (typeof value === 'number') {
|
9650
|
+
return total + value;
|
9651
|
+
}
|
9652
|
+
|
9653
|
+
return total;
|
9654
|
+
}, 0);
|
9655
|
+
|
9656
|
+
let isSubnetReachable = null;
|
9657
|
+
if (totalSuccessCases > 0) {
|
9658
|
+
// @ts-ignore
|
9659
|
+
isSubnetReachable = this.webex.meetings.reachability.isSubnetReachable(this.mediaServerIp);
|
9660
|
+
}
|
9661
|
+
|
9662
|
+
return {
|
9663
|
+
...reachabilityMetrics,
|
9664
|
+
isSubnetReachable,
|
9665
|
+
};
|
9666
|
+
}
|
9387
9667
|
}
|