@webex/plugin-meetings 3.8.0-next.7 → 3.8.0-next.71
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 +4 -1
- 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 +32 -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 +14 -16
- 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 +6 -0
- package/dist/meeting/brbState.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 +541 -302
- 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 +114 -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 +330 -353
- 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 +2 -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 +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 +16 -0
- package/dist/types/meeting/index.d.ts +32 -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 +48 -0
- package/dist/types/member/index.d.ts +1 -0
- package/dist/types/member/util.d.ts +159 -1
- 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 +24 -23
- package/src/common/errors/webex-errors.ts +8 -1
- package/src/config.ts +2 -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 +38 -12
- package/src/locus-info/selfUtils.ts +496 -442
- package/src/media/index.ts +20 -21
- package/src/media/properties.ts +96 -0
- package/src/meeting/brbState.ts +7 -0
- package/src/meeting/in-meeting-actions.ts +32 -0
- package/src/meeting/index.ts +346 -93
- 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 +128 -1
- package/src/meetings/util.ts +18 -0
- package/src/member/index.ts +13 -2
- package/src/member/util.ts +351 -348
- 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 +141 -73
- package/test/unit/spec/locus-info/selfUtils.js +98 -24
- package/test/unit/spec/media/index.ts +98 -16
- package/test/unit/spec/media/properties.ts +130 -0
- package/test/unit/spec/meeting/brbState.ts +19 -0
- package/test/unit/spec/meeting/in-meeting-actions.ts +19 -4
- package/test/unit/spec/meeting/index.js +524 -35
- 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 +133 -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';
|
@@ -265,6 +262,8 @@ type FetchMeetingInfoParams = {
|
|
265
262
|
sendCAevents?: boolean;
|
266
263
|
};
|
267
264
|
|
265
|
+
type MediaReachabilityMetrics = ReachabilityMetrics & {isSubnetReachable: boolean};
|
266
|
+
|
268
267
|
/**
|
269
268
|
* MediaDirection
|
270
269
|
* @typedef {Object} MediaDirection
|
@@ -650,6 +649,13 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
650
649
|
allowMediaInLobby: boolean;
|
651
650
|
localShareInstanceId: string;
|
652
651
|
remoteShareInstanceId: string;
|
652
|
+
shareCAEventSentStatus: {
|
653
|
+
transmitStart: boolean;
|
654
|
+
transmitStop: boolean;
|
655
|
+
receiveStart: boolean;
|
656
|
+
receiveStop: boolean;
|
657
|
+
};
|
658
|
+
|
653
659
|
turnDiscoverySkippedReason: TurnDiscoverySkipReason;
|
654
660
|
turnServerUsed: boolean;
|
655
661
|
areVoiceaEventsSetup = false;
|
@@ -718,6 +724,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
718
724
|
private rtcMetrics?: RtcMetrics;
|
719
725
|
private uploadLogsTimer?: ReturnType<typeof setTimeout>;
|
720
726
|
private logUploadIntervalIndex: number;
|
727
|
+
private mediaServerIp: string;
|
721
728
|
|
722
729
|
/**
|
723
730
|
* @param {Object} attrs
|
@@ -1422,6 +1429,19 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
1422
1429
|
*/
|
1423
1430
|
this.remoteShareInstanceId = null;
|
1424
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
|
+
|
1425
1445
|
/**
|
1426
1446
|
* The class that helps to control recording functions: start, stop, pause, resume, etc
|
1427
1447
|
* @instance
|
@@ -1581,6 +1601,19 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
1581
1601
|
* @memberof Meeting
|
1582
1602
|
*/
|
1583
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;
|
1584
1617
|
}
|
1585
1618
|
|
1586
1619
|
/**
|
@@ -1686,6 +1719,33 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
1686
1719
|
return this.#isoLocalClientMeetingJoinTime;
|
1687
1720
|
}
|
1688
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
|
+
|
1689
1749
|
/**
|
1690
1750
|
* Set meeting info and trigger `MEETING_INFO_AVAILABLE` event
|
1691
1751
|
* @param {any} info
|
@@ -2827,6 +2887,24 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
2827
2887
|
{state}
|
2828
2888
|
);
|
2829
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
|
+
});
|
2830
2908
|
}
|
2831
2909
|
|
2832
2910
|
/**
|
@@ -2999,6 +3077,8 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
2999
3077
|
case SHARE_STATUS.REMOTE_SHARE_ACTIVE: {
|
3000
3078
|
const sendStartedSharingRemote = () => {
|
3001
3079
|
this.remoteShareInstanceId = contentShare.shareInstanceId;
|
3080
|
+
this.shareCAEventSentStatus.receiveStart = false;
|
3081
|
+
this.shareCAEventSentStatus.receiveStop = false;
|
3002
3082
|
|
3003
3083
|
Trigger.trigger(
|
3004
3084
|
this,
|
@@ -3052,6 +3132,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
3052
3132
|
},
|
3053
3133
|
options: {meetingId: this.id},
|
3054
3134
|
});
|
3135
|
+
|
3055
3136
|
break;
|
3056
3137
|
|
3057
3138
|
case SHARE_STATUS.WHITEBOARD_SHARE_ACTIVE:
|
@@ -3092,6 +3173,8 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
3092
3173
|
// if we got here, then some remote participant has stolen
|
3093
3174
|
// the presentation from another remote participant
|
3094
3175
|
this.remoteShareInstanceId = contentShare.shareInstanceId;
|
3176
|
+
this.shareCAEventSentStatus.receiveStart = false;
|
3177
|
+
this.shareCAEventSentStatus.receiveStop = false;
|
3095
3178
|
|
3096
3179
|
Trigger.trigger(
|
3097
3180
|
this,
|
@@ -3775,7 +3858,13 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
3775
3858
|
return Promise.reject(error);
|
3776
3859
|
}
|
3777
3860
|
|
3778
|
-
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
|
+
});
|
3779
3868
|
}
|
3780
3869
|
|
3781
3870
|
/**
|
@@ -3967,7 +4056,10 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
3967
4056
|
canAdmitParticipant: MeetingUtil.canAdmitParticipant(this.userDisplayHints),
|
3968
4057
|
canLock: MeetingUtil.canUserLock(this.userDisplayHints),
|
3969
4058
|
canUnlock: MeetingUtil.canUserUnlock(this.userDisplayHints),
|
3970
|
-
canShareWhiteBoard: MeetingUtil.canShareWhiteBoard(
|
4059
|
+
canShareWhiteBoard: MeetingUtil.canShareWhiteBoard(
|
4060
|
+
this.userDisplayHints,
|
4061
|
+
this.selfUserPolicies
|
4062
|
+
),
|
3971
4063
|
canSetDisallowUnmute: ControlsOptionsUtil.canSetDisallowUnmute(this.userDisplayHints),
|
3972
4064
|
canUnsetDisallowUnmute: ControlsOptionsUtil.canUnsetDisallowUnmute(this.userDisplayHints),
|
3973
4065
|
canSetMuteOnEntry: ControlsOptionsUtil.canSetMuteOnEntry(this.userDisplayHints),
|
@@ -4016,6 +4108,9 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
4016
4108
|
this.inMeetingActions.canSendReactions,
|
4017
4109
|
this.userDisplayHints
|
4018
4110
|
),
|
4111
|
+
requiresPostMeetingDataConsentPrompt: MeetingUtil.requiresPostMeetingDataConsentPrompt(
|
4112
|
+
this.userDisplayHints
|
4113
|
+
),
|
4019
4114
|
canManageBreakout: MeetingUtil.canManageBreakout(this.userDisplayHints),
|
4020
4115
|
canStartBreakout: MeetingUtil.canStartBreakout(this.userDisplayHints),
|
4021
4116
|
canBroadcastMessageToBreakout: MeetingUtil.canBroadcastMessageToBreakout(
|
@@ -4031,6 +4126,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
4031
4126
|
this.userDisplayHints
|
4032
4127
|
),
|
4033
4128
|
canUserRenameOthers: MeetingUtil.canUserRenameOthers(this.userDisplayHints),
|
4129
|
+
canMoveToLobby: MeetingUtil.canMoveToLobby(this.userDisplayHints),
|
4034
4130
|
canMuteAll: ControlsOptionsUtil.hasHints({
|
4035
4131
|
requiredHints: [DISPLAY_HINTS.MUTE_ALL],
|
4036
4132
|
displayHints: this.userDisplayHints,
|
@@ -4165,6 +4261,14 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
4165
4261
|
requiredPolicies: [SELF_POLICY.SUPPORT_FILE_TRANSFER],
|
4166
4262
|
policies: this.selfUserPolicies,
|
4167
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
|
+
}),
|
4168
4272
|
canChat: ControlsOptionsUtil.hasPolicies({
|
4169
4273
|
requiredPolicies: [SELF_POLICY.SUPPORT_CHAT],
|
4170
4274
|
policies: this.selfUserPolicies,
|
@@ -4211,6 +4315,22 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
4211
4315
|
requiredPolicies: [SELF_POLICY.SUPPORT_ANNOTATION],
|
4212
4316
|
policies: this.selfUserPolicies,
|
4213
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
|
+
}),
|
4214
4334
|
}) || changed;
|
4215
4335
|
}
|
4216
4336
|
if (changed) {
|
@@ -5718,8 +5838,6 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
5718
5838
|
// @ts-ignore
|
5719
5839
|
this.webex.internal.device.meetingStarted();
|
5720
5840
|
|
5721
|
-
this.#isoLocalClientMeetingJoinTime = new Date().toISOString();
|
5722
|
-
|
5723
5841
|
LoggerProxy.logger.log('Meeting:index#join --> Success');
|
5724
5842
|
|
5725
5843
|
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.JOIN_SUCCESS, {
|
@@ -6180,10 +6298,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
6180
6298
|
},
|
6181
6299
|
options: {meetingId: this.id, rawError: error},
|
6182
6300
|
});
|
6183
|
-
} else if (
|
6184
|
-
error instanceof Errors.SdpOfferHandlingError ||
|
6185
|
-
error instanceof Errors.SdpAnswerHandlingError
|
6186
|
-
) {
|
6301
|
+
} else if (error instanceof Errors.SdpOfferHandlingError) {
|
6187
6302
|
sendBehavioralMetric(BEHAVIORAL_METRICS.PEERCONNECTION_FAILURE, error, this.correlationId);
|
6188
6303
|
|
6189
6304
|
// @ts-ignore
|
@@ -6194,6 +6309,24 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
6194
6309
|
},
|
6195
6310
|
options: {meetingId: this.id, rawError: error},
|
6196
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
|
+
}
|
6197
6330
|
} else if (error instanceof Errors.SdpError) {
|
6198
6331
|
// this covers also the case of Errors.IceGatheringError which extends Errors.SdpError
|
6199
6332
|
sendBehavioralMetric(BEHAVIORAL_METRICS.INVALID_ICE_CANDIDATE, error, this.correlationId);
|
@@ -6221,6 +6354,11 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
6221
6354
|
? MeetingsUtil.getMediaServer(roapMessage.sdp)
|
6222
6355
|
: undefined;
|
6223
6356
|
|
6357
|
+
const mediaServerIp =
|
6358
|
+
roapMessage.messageType === 'ANSWER'
|
6359
|
+
? MeetingsUtil.getMediaServerIp(roapMessage.sdp)
|
6360
|
+
: undefined;
|
6361
|
+
|
6224
6362
|
if (this.isMultistream && mediaServer && mediaServer !== 'homer') {
|
6225
6363
|
throw new MultistreamNotSupportedError(
|
6226
6364
|
`Client asked for multistream backend (Homer), but got ${mediaServer} instead`
|
@@ -6231,6 +6369,10 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
6231
6369
|
if (mediaServer) {
|
6232
6370
|
this.mediaProperties.webrtcMediaConnection.mediaServer = mediaServer;
|
6233
6371
|
}
|
6372
|
+
|
6373
|
+
if (this.isMultistream && mediaServerIp) {
|
6374
|
+
this.mediaServerIp = mediaServerIp;
|
6375
|
+
}
|
6234
6376
|
};
|
6235
6377
|
|
6236
6378
|
/**
|
@@ -6688,20 +6830,20 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
6688
6830
|
* @memberof Meetings
|
6689
6831
|
*/
|
6690
6832
|
setupStatsAnalyzerEventHandlers = () => {
|
6691
|
-
this.statsAnalyzer.on(StatsAnalyzerEventNames.MEDIA_QUALITY, (
|
6692
|
-
//
|
6693
|
-
|
6694
|
-
|
6695
|
-
|
6696
|
-
|
6697
|
-
|
6698
|
-
|
6699
|
-
|
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
|
+
}
|
6700
6843
|
|
6844
|
+
// Count members that are in the meeting.
|
6701
6845
|
const {members} = this.getMembers().membersCollection;
|
6702
|
-
|
6703
|
-
// Count members that are in the meeting
|
6704
|
-
options.data.intervalMetadata.meetingUserCount = Object.values(members).filter(
|
6846
|
+
event.data.intervalMetadata.meetingUserCount = Object.values(members).filter(
|
6705
6847
|
(member: Member) => member.isInMeeting
|
6706
6848
|
).length;
|
6707
6849
|
|
@@ -6710,10 +6852,10 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
6710
6852
|
name: 'client.mediaquality.event',
|
6711
6853
|
options: {
|
6712
6854
|
meetingId: this.id,
|
6713
|
-
networkType:
|
6855
|
+
networkType: this.statsAnalyzer.getNetworkType(),
|
6714
6856
|
},
|
6715
6857
|
payload: {
|
6716
|
-
intervals: [
|
6858
|
+
intervals: [event.data],
|
6717
6859
|
},
|
6718
6860
|
});
|
6719
6861
|
});
|
@@ -6728,30 +6870,42 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
6728
6870
|
EVENT_TRIGGERS.MEETING_MEDIA_LOCAL_STARTED,
|
6729
6871
|
data
|
6730
6872
|
);
|
6731
|
-
|
6732
|
-
|
6733
|
-
|
6734
|
-
|
6735
|
-
|
6736
|
-
|
6737
|
-
|
6738
|
-
|
6739
|
-
|
6740
|
-
|
6741
|
-
|
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
|
+
}
|
6742
6890
|
});
|
6743
6891
|
this.statsAnalyzer.on(StatsAnalyzerEventNames.LOCAL_MEDIA_STOPPED, (data) => {
|
6744
|
-
|
6745
|
-
|
6746
|
-
|
6747
|
-
|
6748
|
-
|
6749
|
-
|
6750
|
-
|
6751
|
-
|
6752
|
-
|
6753
|
-
|
6754
|
-
|
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
|
+
}
|
6755
6909
|
});
|
6756
6910
|
this.statsAnalyzer.on(StatsAnalyzerEventNames.REMOTE_MEDIA_STARTED, (data) => {
|
6757
6911
|
Trigger.trigger(
|
@@ -6763,57 +6917,65 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
6763
6917
|
EVENT_TRIGGERS.MEETING_MEDIA_REMOTE_STARTED,
|
6764
6918
|
data
|
6765
6919
|
);
|
6766
|
-
|
6767
|
-
this.webex.internal.newMetrics.submitClientEvent({
|
6768
|
-
name: 'client.media.rx.start',
|
6769
|
-
payload: {
|
6770
|
-
mediaType: data.mediaType,
|
6771
|
-
shareInstanceId: data.mediaType === 'share' ? this.remoteShareInstanceId : undefined,
|
6772
|
-
},
|
6773
|
-
options: {
|
6774
|
-
meetingId: this.id,
|
6775
|
-
},
|
6776
|
-
});
|
6777
|
-
|
6778
|
-
if (data.mediaType === 'share') {
|
6920
|
+
if (data.mediaType !== 'share' || !this.shareCAEventSentStatus.receiveStart) {
|
6779
6921
|
// @ts-ignore
|
6780
6922
|
this.webex.internal.newMetrics.submitClientEvent({
|
6781
|
-
name: 'client.media.
|
6923
|
+
name: 'client.media.rx.start',
|
6782
6924
|
payload: {
|
6783
|
-
mediaType:
|
6784
|
-
shareInstanceId: this.remoteShareInstanceId,
|
6925
|
+
mediaType: data.mediaType,
|
6926
|
+
shareInstanceId: data.mediaType === 'share' ? this.remoteShareInstanceId : undefined,
|
6785
6927
|
},
|
6786
6928
|
options: {
|
6787
6929
|
meetingId: this.id,
|
6788
6930
|
},
|
6789
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
|
+
}
|
6790
6948
|
}
|
6791
6949
|
});
|
6792
6950
|
this.statsAnalyzer.on(StatsAnalyzerEventNames.REMOTE_MEDIA_STOPPED, (data) => {
|
6793
|
-
|
6794
|
-
this.webex.internal.newMetrics.submitClientEvent({
|
6795
|
-
name: 'client.media.rx.stop',
|
6796
|
-
payload: {
|
6797
|
-
mediaType: data.mediaType,
|
6798
|
-
shareInstanceId: data.mediaType === 'share' ? this.remoteShareInstanceId : undefined,
|
6799
|
-
},
|
6800
|
-
options: {
|
6801
|
-
meetingId: this.id,
|
6802
|
-
},
|
6803
|
-
});
|
6804
|
-
|
6805
|
-
if (data.mediaType === 'share') {
|
6951
|
+
if (data.mediaType !== 'share' || !this.shareCAEventSentStatus.receiveStop) {
|
6806
6952
|
// @ts-ignore
|
6807
6953
|
this.webex.internal.newMetrics.submitClientEvent({
|
6808
|
-
name: 'client.media.
|
6954
|
+
name: 'client.media.rx.stop',
|
6809
6955
|
payload: {
|
6810
|
-
mediaType:
|
6811
|
-
shareInstanceId: this.remoteShareInstanceId,
|
6956
|
+
mediaType: data.mediaType,
|
6957
|
+
shareInstanceId: data.mediaType === 'share' ? this.remoteShareInstanceId : undefined,
|
6812
6958
|
},
|
6813
6959
|
options: {
|
6814
6960
|
meetingId: this.id,
|
6815
6961
|
},
|
6816
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
|
+
}
|
6817
6979
|
}
|
6818
6980
|
});
|
6819
6981
|
};
|
@@ -6830,7 +6992,10 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
6830
6992
|
* @param {AddMediaOptions} [options] Options for enabling/disabling audio/video
|
6831
6993
|
* @returns {RoapMediaConnection | MultistreamRoapMediaConnection}
|
6832
6994
|
*/
|
6833
|
-
private async createMediaConnection(
|
6995
|
+
private async createMediaConnection(
|
6996
|
+
turnServerInfo?: TurnServerInfo,
|
6997
|
+
bundlePolicy?: BundlePolicy
|
6998
|
+
) {
|
6834
6999
|
this.rtcMetrics = this.isMultistream
|
6835
7000
|
? // @ts-ignore
|
6836
7001
|
new RtcMetrics(this.webex, {meetingId: this.id}, this.correlationId)
|
@@ -6855,6 +7020,11 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
6855
7020
|
bundlePolicy,
|
6856
7021
|
// @ts-ignore - config coming from registerPlugin
|
6857
7022
|
iceCandidatesTimeout: this.config.iceCandidatesGatheringTimeout,
|
7023
|
+
// @ts-ignore - config coming from registerPlugin
|
7024
|
+
disableAudioMainDtx: this.config.experimental.disableAudioMainDtx,
|
7025
|
+
stopIceGatheringAfterFirstRelayCandidate:
|
7026
|
+
// @ts-ignore - config coming from registerPlugin
|
7027
|
+
this.config.stopIceGatheringAfterFirstRelayCandidate,
|
6858
7028
|
}
|
6859
7029
|
);
|
6860
7030
|
|
@@ -7005,12 +7175,18 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
7005
7175
|
},
|
7006
7176
|
options: {
|
7007
7177
|
meetingId: this.id,
|
7178
|
+
rawError: error,
|
7008
7179
|
},
|
7009
7180
|
});
|
7010
7181
|
}
|
7011
|
-
|
7182
|
+
|
7183
|
+
const timedOutError = new Error(
|
7012
7184
|
`Timed out waiting for media connection to be connected, correlationId=${this.correlationId}`
|
7013
7185
|
);
|
7186
|
+
|
7187
|
+
timedOutError.cause = error;
|
7188
|
+
|
7189
|
+
throw timedOutError;
|
7014
7190
|
}
|
7015
7191
|
}
|
7016
7192
|
|
@@ -7031,6 +7207,12 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
7031
7207
|
networkQualityMonitor: this.networkQualityMonitor,
|
7032
7208
|
isMultistream: this.isMultistream,
|
7033
7209
|
});
|
7210
|
+
this.shareCAEventSentStatus = {
|
7211
|
+
transmitStart: false,
|
7212
|
+
transmitStop: false,
|
7213
|
+
receiveStart: false,
|
7214
|
+
receiveStop: false,
|
7215
|
+
};
|
7034
7216
|
this.setupStatsAnalyzerEventHandlers();
|
7035
7217
|
this.networkQualityMonitor.on(
|
7036
7218
|
NetworkQualityEventNames.NETWORK_QUALITY,
|
@@ -7065,6 +7247,9 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
7065
7247
|
ROAP_OFFER_ANSWER_EXCHANGE_TIMEOUT / 1000
|
7066
7248
|
} seconds`
|
7067
7249
|
);
|
7250
|
+
|
7251
|
+
const error = new Error('Timed out waiting for REMOTE SDP ANSWER');
|
7252
|
+
|
7068
7253
|
// @ts-ignore
|
7069
7254
|
this.webex.internal.newMetrics.submitClientEvent({
|
7070
7255
|
name: 'client.media-engine.remote-sdp-received',
|
@@ -7077,10 +7262,10 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
7077
7262
|
}),
|
7078
7263
|
],
|
7079
7264
|
},
|
7080
|
-
options: {meetingId: this.id, rawError:
|
7265
|
+
options: {meetingId: this.id, rawError: error},
|
7081
7266
|
});
|
7082
7267
|
|
7083
|
-
deferSDPAnswer.reject(
|
7268
|
+
deferSDPAnswer.reject(error);
|
7084
7269
|
}, ROAP_OFFER_ANSWER_EXCHANGE_TIMEOUT);
|
7085
7270
|
|
7086
7271
|
LoggerProxy.logger.info(`${LOG_HEADER} waiting for REMOTE SDP ANSWER...`);
|
@@ -7185,7 +7370,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
7185
7370
|
error
|
7186
7371
|
);
|
7187
7372
|
|
7188
|
-
throw new AddMediaFailed();
|
7373
|
+
throw new AddMediaFailed(error);
|
7189
7374
|
}
|
7190
7375
|
}
|
7191
7376
|
|
@@ -7598,28 +7783,33 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
7598
7783
|
await this.enqueueScreenShareFloorRequest();
|
7599
7784
|
}
|
7600
7785
|
|
7601
|
-
const {connectionType, selectedCandidatePairChanges, numTransports} =
|
7786
|
+
const {connectionType, ipVersion, selectedCandidatePairChanges, numTransports} =
|
7602
7787
|
await this.mediaProperties.getCurrentConnectionInfo();
|
7603
|
-
|
7604
|
-
const reachabilityStats = await this.webex.meetings.reachability.getReachabilityMetrics();
|
7788
|
+
|
7605
7789
|
const iceCandidateErrors = Object.fromEntries(this.iceCandidateErrors);
|
7606
7790
|
|
7791
|
+
const reachabilityMetrics = await this.getMediaReachabilityMetricFields();
|
7792
|
+
|
7607
7793
|
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.ADD_MEDIA_SUCCESS, {
|
7608
7794
|
correlation_id: this.correlationId,
|
7609
7795
|
locus_id: this.locusUrl.split('/').pop(),
|
7610
7796
|
connectionType,
|
7797
|
+
ipVersion,
|
7611
7798
|
selectedCandidatePairChanges,
|
7612
7799
|
numTransports,
|
7613
7800
|
isMultistream: this.isMultistream,
|
7614
7801
|
retriedWithTurnServer: this.addMediaData.retriedWithTurnServer,
|
7615
7802
|
isJoinWithMediaRetry: this.joinWithMediaRetryInfo.isRetry,
|
7616
|
-
...
|
7803
|
+
...reachabilityMetrics,
|
7617
7804
|
...iceCandidateErrors,
|
7618
7805
|
iceCandidatesCount: this.iceCandidatesCount,
|
7619
7806
|
});
|
7620
7807
|
// @ts-ignore
|
7621
7808
|
this.webex.internal.newMetrics.submitClientEvent({
|
7622
7809
|
name: 'client.media-engine.ready',
|
7810
|
+
payload: {
|
7811
|
+
ipVersion,
|
7812
|
+
},
|
7623
7813
|
options: {
|
7624
7814
|
meetingId: this.id,
|
7625
7815
|
},
|
@@ -7635,7 +7825,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
7635
7825
|
LoggerProxy.logger.error(`${LOG_HEADER} failed to establish media connection: `, error);
|
7636
7826
|
|
7637
7827
|
// @ts-ignore
|
7638
|
-
const reachabilityMetrics = await this.
|
7828
|
+
const reachabilityMetrics = await this.getMediaReachabilityMetricFields();
|
7639
7829
|
|
7640
7830
|
const {selectedCandidatePairChanges, numTransports} =
|
7641
7831
|
await this.mediaProperties.getCurrentConnectionInfo();
|
@@ -8715,6 +8905,9 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
8715
8905
|
LoggerProxy.logger.log(
|
8716
8906
|
`Meeting:index#handleShareVideoStreamMuteStateChange --> Share video stream mute state changed to muted ${muted}`
|
8717
8907
|
);
|
8908
|
+
|
8909
|
+
const shareVideoStreamSettings = this.mediaProperties?.shareVideoStream?.getSettings();
|
8910
|
+
|
8718
8911
|
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.MEETING_SHARE_VIDEO_MUTE_STATE_CHANGE, {
|
8719
8912
|
correlationId: this.correlationId,
|
8720
8913
|
muted,
|
@@ -8723,8 +8916,9 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
8723
8916
|
// SDK to TypeScript 5, which may affect other packages, use bracket notation for now, since
|
8724
8917
|
// all we're doing here is adding metrics.
|
8725
8918
|
// eslint-disable-next-line dot-notation
|
8726
|
-
displaySurface:
|
8919
|
+
displaySurface: shareVideoStreamSettings?.['displaySurface'],
|
8727
8920
|
isMultistream: this.isMultistream,
|
8921
|
+
frameRate: shareVideoStreamSettings?.frameRate,
|
8728
8922
|
});
|
8729
8923
|
};
|
8730
8924
|
|
@@ -9051,6 +9245,23 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
9051
9245
|
});
|
9052
9246
|
}
|
9053
9247
|
|
9248
|
+
/**
|
9249
|
+
* Method to set post meeting data consent.
|
9250
|
+
*
|
9251
|
+
* @param {boolean} accept - whether consent accepted or declined
|
9252
|
+
* @returns {Promise}
|
9253
|
+
* @public
|
9254
|
+
* @memberof Meeting
|
9255
|
+
*/
|
9256
|
+
public setPostMeetingDataConsent(accept: boolean) {
|
9257
|
+
return this.meetingRequest.setPostMeetingDataConsent({
|
9258
|
+
postMeetingDataConsent: accept,
|
9259
|
+
locusUrl: this.locusUrl,
|
9260
|
+
deviceUrl: this.deviceUrl,
|
9261
|
+
selfId: this.members.selfId,
|
9262
|
+
});
|
9263
|
+
}
|
9264
|
+
|
9054
9265
|
/**
|
9055
9266
|
* Throws if we don't have a media connection created
|
9056
9267
|
*
|
@@ -9291,6 +9502,8 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
9291
9502
|
|
9292
9503
|
if (floorRequestNeeded) {
|
9293
9504
|
this.localShareInstanceId = uuid.v4();
|
9505
|
+
this.shareCAEventSentStatus.transmitStart = false;
|
9506
|
+
this.shareCAEventSentStatus.transmitStop = false;
|
9294
9507
|
|
9295
9508
|
// @ts-ignore
|
9296
9509
|
this.webex.internal.newMetrics.submitClientEvent({
|
@@ -9418,4 +9631,44 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
9418
9631
|
|
9419
9632
|
return Promise.resolve();
|
9420
9633
|
}
|
9634
|
+
|
9635
|
+
/**
|
9636
|
+
* Gets the media reachability metrics
|
9637
|
+
*
|
9638
|
+
* @returns {Promise<MediaReachabilityMetrics>}
|
9639
|
+
*/
|
9640
|
+
private async getMediaReachabilityMetricFields(): Promise<MediaReachabilityMetrics> {
|
9641
|
+
const reachabilityMetrics: ReachabilityMetrics =
|
9642
|
+
// @ts-ignore
|
9643
|
+
await this.webex.meetings.reachability.getReachabilityMetrics();
|
9644
|
+
|
9645
|
+
const successKeys: Array<keyof ReachabilityMetrics> = [
|
9646
|
+
'reachability_public_udp_success',
|
9647
|
+
'reachability_public_tcp_success',
|
9648
|
+
'reachability_public_xtls_success',
|
9649
|
+
'reachability_vmn_udp_success',
|
9650
|
+
'reachability_vmn_tcp_success',
|
9651
|
+
'reachability_vmn_xtls_success',
|
9652
|
+
];
|
9653
|
+
|
9654
|
+
const totalSuccessCases = successKeys.reduce((total, key) => {
|
9655
|
+
const value = reachabilityMetrics[key];
|
9656
|
+
if (typeof value === 'number') {
|
9657
|
+
return total + value;
|
9658
|
+
}
|
9659
|
+
|
9660
|
+
return total;
|
9661
|
+
}, 0);
|
9662
|
+
|
9663
|
+
let isSubnetReachable = null;
|
9664
|
+
if (totalSuccessCases > 0) {
|
9665
|
+
// @ts-ignore
|
9666
|
+
isSubnetReachable = this.webex.meetings.reachability.isSubnetReachable(this.mediaServerIp);
|
9667
|
+
}
|
9668
|
+
|
9669
|
+
return {
|
9670
|
+
...reachabilityMetrics,
|
9671
|
+
isSubnetReachable,
|
9672
|
+
};
|
9673
|
+
}
|
9421
9674
|
}
|