@webex/plugin-meetings 3.8.0-next.8 → 3.8.0-next.81
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 +70 -6
- package/dist/breakouts/index.js.map +1 -1
- package/dist/common/errors/webex-errors.js +12 -2
- package/dist/common/errors/webex-errors.js.map +1 -1
- package/dist/config.js +5 -1
- package/dist/config.js.map +1 -1
- package/dist/constants.js +20 -123
- 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 +62 -12
- package/dist/locus-info/index.js.map +1 -1
- package/dist/locus-info/selfUtils.js +432 -418
- package/dist/locus-info/selfUtils.js.map +1 -1
- package/dist/media/index.js +17 -17
- package/dist/media/index.js.map +1 -1
- package/dist/media/properties.js +94 -6
- package/dist/media/properties.js.map +1 -1
- package/dist/meeting/brbState.js +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 +570 -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 +373 -68
- package/dist/meeting-info/meeting-info-v2.js.map +1 -1
- package/dist/meeting-info/utilv2.js +5 -1
- package/dist/meeting-info/utilv2.js.map +1 -1
- package/dist/meetings/index.js +136 -1
- package/dist/meetings/index.js.map +1 -1
- package/dist/meetings/util.js +14 -0
- package/dist/meetings/util.js.map +1 -1
- package/dist/member/index.js +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 +42 -0
- package/dist/members/index.js.map +1 -1
- package/dist/members/request.js +38 -0
- package/dist/members/request.js.map +1 -1
- package/dist/members/util.js +36 -1
- package/dist/members/util.js.map +1 -1
- package/dist/metrics/constants.js +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/roap/index.js.map +1 -1
- package/dist/roap/turnDiscovery.js +45 -27
- package/dist/roap/turnDiscovery.js.map +1 -1
- package/dist/roap/types.js +17 -0
- package/dist/roap/types.js.map +1 -0
- package/dist/types/common/errors/webex-errors.d.ts +7 -1
- package/dist/types/config.d.ts +3 -0
- package/dist/types/constants.d.ts +13 -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 +43 -1
- package/dist/types/meeting/muteState.d.ts +0 -1
- package/dist/types/meeting/request.d.ts +12 -1
- package/dist/types/meeting/request.type.d.ts +6 -0
- package/dist/types/meeting/util.d.ts +3 -1
- package/dist/types/meeting-info/meeting-info-v2.d.ts +82 -1
- package/dist/types/meetings/index.d.ts +57 -0
- package/dist/types/member/index.d.ts +1 -0
- package/dist/types/member/util.d.ts +159 -1
- package/dist/types/members/index.d.ts +15 -0
- package/dist/types/members/request.d.ts +26 -0
- package/dist/types/members/util.d.ts +27 -0
- package/dist/types/metrics/constants.d.ts +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/breakouts/index.ts +69 -0
- package/src/common/errors/webex-errors.ts +8 -1
- package/src/config.ts +3 -0
- package/src/constants.ts +20 -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 +56 -13
- package/src/locus-info/selfUtils.ts +496 -442
- package/src/media/index.ts +23 -21
- package/src/media/properties.ts +96 -0
- package/src/meeting/brbState.ts +7 -0
- package/src/meeting/in-meeting-actions.ts +32 -0
- package/src/meeting/index.ts +382 -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 +254 -8
- package/src/meeting-info/utilv2.ts +5 -0
- package/src/meetings/index.ts +148 -1
- package/src/meetings/util.ts +18 -0
- package/src/member/index.ts +13 -2
- package/src/member/util.ts +351 -348
- package/src/members/index.ts +47 -0
- package/src/members/request.ts +44 -0
- package/src/members/util.ts +43 -1
- 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/roap/index.ts +3 -7
- package/src/roap/turnDiscovery.ts +34 -39
- package/src/roap/types.ts +23 -0
- package/test/unit/spec/breakouts/index.ts +167 -95
- 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 +167 -73
- package/test/unit/spec/locus-info/selfUtils.js +98 -24
- package/test/unit/spec/media/index.ts +150 -18
- package/test/unit/spec/media/properties.ts +130 -0
- package/test/unit/spec/meeting/brbState.ts +19 -0
- package/test/unit/spec/meeting/in-meeting-actions.ts +19 -4
- package/test/unit/spec/meeting/index.js +557 -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 +484 -114
- package/test/unit/spec/meeting-info/utilv2.js +19 -0
- package/test/unit/spec/meetings/index.js +146 -2
- package/test/unit/spec/member/index.js +7 -0
- package/test/unit/spec/member/util.js +24 -0
- package/test/unit/spec/members/index.js +140 -26
- package/test/unit/spec/members/request.js +68 -22
- package/test/unit/spec/members/utils.js +75 -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,11 @@ type FetchMeetingInfoParams = {
|
|
265
262
|
sendCAevents?: boolean;
|
266
263
|
};
|
267
264
|
|
265
|
+
type MediaReachabilityMetrics = ReachabilityMetrics & {
|
266
|
+
isSubnetReachable: boolean;
|
267
|
+
selectedCluster: string | null;
|
268
|
+
};
|
269
|
+
|
268
270
|
/**
|
269
271
|
* MediaDirection
|
270
272
|
* @typedef {Object} MediaDirection
|
@@ -650,6 +652,13 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
650
652
|
allowMediaInLobby: boolean;
|
651
653
|
localShareInstanceId: string;
|
652
654
|
remoteShareInstanceId: string;
|
655
|
+
shareCAEventSentStatus: {
|
656
|
+
transmitStart: boolean;
|
657
|
+
transmitStop: boolean;
|
658
|
+
receiveStart: boolean;
|
659
|
+
receiveStop: boolean;
|
660
|
+
};
|
661
|
+
|
653
662
|
turnDiscoverySkippedReason: TurnDiscoverySkipReason;
|
654
663
|
turnServerUsed: boolean;
|
655
664
|
areVoiceaEventsSetup = false;
|
@@ -718,6 +727,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
718
727
|
private rtcMetrics?: RtcMetrics;
|
719
728
|
private uploadLogsTimer?: ReturnType<typeof setTimeout>;
|
720
729
|
private logUploadIntervalIndex: number;
|
730
|
+
private mediaServerIp: string;
|
721
731
|
|
722
732
|
/**
|
723
733
|
* @param {Object} attrs
|
@@ -1422,6 +1432,19 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
1422
1432
|
*/
|
1423
1433
|
this.remoteShareInstanceId = null;
|
1424
1434
|
|
1435
|
+
/**
|
1436
|
+
* Status used for ensuring we do not oversend metrics
|
1437
|
+
* @instance
|
1438
|
+
* @private
|
1439
|
+
* @memberof Meeting
|
1440
|
+
*/
|
1441
|
+
this.shareCAEventSentStatus = {
|
1442
|
+
transmitStart: false,
|
1443
|
+
transmitStop: false,
|
1444
|
+
receiveStart: false,
|
1445
|
+
receiveStop: false,
|
1446
|
+
};
|
1447
|
+
|
1425
1448
|
/**
|
1426
1449
|
* The class that helps to control recording functions: start, stop, pause, resume, etc
|
1427
1450
|
* @instance
|
@@ -1581,6 +1604,19 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
1581
1604
|
* @memberof Meeting
|
1582
1605
|
*/
|
1583
1606
|
this.#isoLocalClientMeetingJoinTime = undefined;
|
1607
|
+
|
1608
|
+
// We clear the error cache of CA events on every new meeting instance
|
1609
|
+
// @ts-ignore - Fix type
|
1610
|
+
this.webex.internal.newMetrics.callDiagnosticMetrics.clearErrorCache();
|
1611
|
+
|
1612
|
+
/**
|
1613
|
+
* IP Address of the remote media server
|
1614
|
+
* @instance
|
1615
|
+
* @type {string}
|
1616
|
+
* @private
|
1617
|
+
* @memberof Meeting
|
1618
|
+
*/
|
1619
|
+
this.mediaServerIp = undefined;
|
1584
1620
|
}
|
1585
1621
|
|
1586
1622
|
/**
|
@@ -1686,6 +1722,33 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
1686
1722
|
return this.#isoLocalClientMeetingJoinTime;
|
1687
1723
|
}
|
1688
1724
|
|
1725
|
+
/**
|
1726
|
+
* Setter - sets isoLocalClientMeetingJoinTime
|
1727
|
+
* This will be set once on meeting join, and not updated again
|
1728
|
+
* this will always produce an ISO string
|
1729
|
+
* If the iso string is invalid, it will fallback to the current system time
|
1730
|
+
* @param {string | undefined} time
|
1731
|
+
*/
|
1732
|
+
set isoLocalClientMeetingJoinTime(time: string | undefined) {
|
1733
|
+
const fallback = new Date().toISOString();
|
1734
|
+
if (!time) {
|
1735
|
+
this.#isoLocalClientMeetingJoinTime = fallback;
|
1736
|
+
} else {
|
1737
|
+
const date = new Date(time);
|
1738
|
+
|
1739
|
+
// Check if the date is valid
|
1740
|
+
if (Number.isNaN(date.getTime())) {
|
1741
|
+
LoggerProxy.logger.info(
|
1742
|
+
// @ts-ignore
|
1743
|
+
`Meeting:index#isoLocalClientMeetingJoinTime --> Invalid date provided: ${time}. Falling back to system clock.`
|
1744
|
+
);
|
1745
|
+
this.#isoLocalClientMeetingJoinTime = fallback;
|
1746
|
+
} else {
|
1747
|
+
this.#isoLocalClientMeetingJoinTime = date.toISOString();
|
1748
|
+
}
|
1749
|
+
}
|
1750
|
+
}
|
1751
|
+
|
1689
1752
|
/**
|
1690
1753
|
* Set meeting info and trigger `MEETING_INFO_AVAILABLE` event
|
1691
1754
|
* @param {any} info
|
@@ -2577,6 +2640,19 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
2577
2640
|
this.locusInfo.on(EVENTS.LOCUS_INFO_UPDATE_PARTICIPANTS, (payload) => {
|
2578
2641
|
this.members.locusParticipantsUpdate(payload);
|
2579
2642
|
});
|
2643
|
+
this.locusInfo.on(LOCUSINFO.EVENTS.PARTICIPANT_REASON_CHANGED, (payload) => {
|
2644
|
+
Trigger.trigger(
|
2645
|
+
this,
|
2646
|
+
{
|
2647
|
+
file: 'meeting/index',
|
2648
|
+
function: 'setUpLocusParticipantsListener',
|
2649
|
+
},
|
2650
|
+
EVENT_TRIGGERS.MEETING_PARTICIPANT_REASON_CHANGED,
|
2651
|
+
{
|
2652
|
+
payload,
|
2653
|
+
}
|
2654
|
+
);
|
2655
|
+
});
|
2580
2656
|
}
|
2581
2657
|
|
2582
2658
|
/**
|
@@ -2827,6 +2903,24 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
2827
2903
|
{state}
|
2828
2904
|
);
|
2829
2905
|
});
|
2906
|
+
|
2907
|
+
this.locusInfo.on(LOCUSINFO.EVENTS.CONTROLS_ANNOTATION_CHANGED, ({state}) => {
|
2908
|
+
Trigger.trigger(
|
2909
|
+
this,
|
2910
|
+
{file: 'meeting/index', function: 'setupLocusControlsListener'},
|
2911
|
+
EVENT_TRIGGERS.MEETING_CONTROLS_ANNOTATION_UPDATED,
|
2912
|
+
{state}
|
2913
|
+
);
|
2914
|
+
});
|
2915
|
+
|
2916
|
+
this.locusInfo.on(LOCUSINFO.EVENTS.CONTROLS_REMOTE_DESKTOP_CONTROL_CHANGED, ({state}) => {
|
2917
|
+
Trigger.trigger(
|
2918
|
+
this,
|
2919
|
+
{file: 'meeting/index', function: 'setupLocusControlsListener'},
|
2920
|
+
EVENT_TRIGGERS.MEETING_CONTROLS_REMOTE_DESKTOP_CONTROL_UPDATED,
|
2921
|
+
{state}
|
2922
|
+
);
|
2923
|
+
});
|
2830
2924
|
}
|
2831
2925
|
|
2832
2926
|
/**
|
@@ -2999,6 +3093,8 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
2999
3093
|
case SHARE_STATUS.REMOTE_SHARE_ACTIVE: {
|
3000
3094
|
const sendStartedSharingRemote = () => {
|
3001
3095
|
this.remoteShareInstanceId = contentShare.shareInstanceId;
|
3096
|
+
this.shareCAEventSentStatus.receiveStart = false;
|
3097
|
+
this.shareCAEventSentStatus.receiveStop = false;
|
3002
3098
|
|
3003
3099
|
Trigger.trigger(
|
3004
3100
|
this,
|
@@ -3052,6 +3148,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
3052
3148
|
},
|
3053
3149
|
options: {meetingId: this.id},
|
3054
3150
|
});
|
3151
|
+
|
3055
3152
|
break;
|
3056
3153
|
|
3057
3154
|
case SHARE_STATUS.WHITEBOARD_SHARE_ACTIVE:
|
@@ -3092,6 +3189,8 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
3092
3189
|
// if we got here, then some remote participant has stolen
|
3093
3190
|
// the presentation from another remote participant
|
3094
3191
|
this.remoteShareInstanceId = contentShare.shareInstanceId;
|
3192
|
+
this.shareCAEventSentStatus.receiveStart = false;
|
3193
|
+
this.shareCAEventSentStatus.receiveStop = false;
|
3095
3194
|
|
3096
3195
|
Trigger.trigger(
|
3097
3196
|
this,
|
@@ -3720,6 +3819,18 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
3720
3819
|
return this.members.cancelPhoneInvite(invitee);
|
3721
3820
|
}
|
3722
3821
|
|
3822
|
+
/**
|
3823
|
+
* Cancel an SIP call invitation made during a meeting
|
3824
|
+
* @param {Object} invitee
|
3825
|
+
* @param {String} invitee.memberId
|
3826
|
+
* @returns {Promise} see #members.cancelSIPInvite
|
3827
|
+
* @public
|
3828
|
+
* @memberof Meeting
|
3829
|
+
*/
|
3830
|
+
public cancelSIPInvite(invitee: {memberId: string}) {
|
3831
|
+
return this.members.cancelSIPInvite(invitee);
|
3832
|
+
}
|
3833
|
+
|
3723
3834
|
/**
|
3724
3835
|
* Admit the guest(s) to the call once they are waiting.
|
3725
3836
|
* If the host/cohost is in a breakout session, the locus url
|
@@ -3775,7 +3886,13 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
3775
3886
|
return Promise.reject(error);
|
3776
3887
|
}
|
3777
3888
|
|
3778
|
-
return this.brbState.enable(enabled, this.sendSlotManager)
|
3889
|
+
return this.brbState.enable(enabled, this.sendSlotManager).then(() => {
|
3890
|
+
if (this.audio && enabled) {
|
3891
|
+
// locus mutes the participant with brb enabled request,
|
3892
|
+
// so we need to explicitly update remote mute for correct logic flow
|
3893
|
+
this.audio.handleServerRemoteMuteUpdate(this, enabled);
|
3894
|
+
}
|
3895
|
+
});
|
3779
3896
|
}
|
3780
3897
|
|
3781
3898
|
/**
|
@@ -3967,7 +4084,10 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
3967
4084
|
canAdmitParticipant: MeetingUtil.canAdmitParticipant(this.userDisplayHints),
|
3968
4085
|
canLock: MeetingUtil.canUserLock(this.userDisplayHints),
|
3969
4086
|
canUnlock: MeetingUtil.canUserUnlock(this.userDisplayHints),
|
3970
|
-
canShareWhiteBoard: MeetingUtil.canShareWhiteBoard(
|
4087
|
+
canShareWhiteBoard: MeetingUtil.canShareWhiteBoard(
|
4088
|
+
this.userDisplayHints,
|
4089
|
+
this.selfUserPolicies
|
4090
|
+
),
|
3971
4091
|
canSetDisallowUnmute: ControlsOptionsUtil.canSetDisallowUnmute(this.userDisplayHints),
|
3972
4092
|
canUnsetDisallowUnmute: ControlsOptionsUtil.canUnsetDisallowUnmute(this.userDisplayHints),
|
3973
4093
|
canSetMuteOnEntry: ControlsOptionsUtil.canSetMuteOnEntry(this.userDisplayHints),
|
@@ -4016,6 +4136,9 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
4016
4136
|
this.inMeetingActions.canSendReactions,
|
4017
4137
|
this.userDisplayHints
|
4018
4138
|
),
|
4139
|
+
requiresPostMeetingDataConsentPrompt: MeetingUtil.requiresPostMeetingDataConsentPrompt(
|
4140
|
+
this.userDisplayHints
|
4141
|
+
),
|
4019
4142
|
canManageBreakout: MeetingUtil.canManageBreakout(this.userDisplayHints),
|
4020
4143
|
canStartBreakout: MeetingUtil.canStartBreakout(this.userDisplayHints),
|
4021
4144
|
canBroadcastMessageToBreakout: MeetingUtil.canBroadcastMessageToBreakout(
|
@@ -4031,6 +4154,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
4031
4154
|
this.userDisplayHints
|
4032
4155
|
),
|
4033
4156
|
canUserRenameOthers: MeetingUtil.canUserRenameOthers(this.userDisplayHints),
|
4157
|
+
canMoveToLobby: MeetingUtil.canMoveToLobby(this.userDisplayHints),
|
4034
4158
|
canMuteAll: ControlsOptionsUtil.hasHints({
|
4035
4159
|
requiredHints: [DISPLAY_HINTS.MUTE_ALL],
|
4036
4160
|
displayHints: this.userDisplayHints,
|
@@ -4165,6 +4289,14 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
4165
4289
|
requiredPolicies: [SELF_POLICY.SUPPORT_FILE_TRANSFER],
|
4166
4290
|
policies: this.selfUserPolicies,
|
4167
4291
|
}),
|
4292
|
+
canRealtimeCloseCaption: ControlsOptionsUtil.hasPolicies({
|
4293
|
+
requiredPolicies: [SELF_POLICY.SUPPORT_REALTIME_CLOSE_CAPTION],
|
4294
|
+
policies: this.selfUserPolicies,
|
4295
|
+
}),
|
4296
|
+
canRealtimeCloseCaptionManual: ControlsOptionsUtil.hasPolicies({
|
4297
|
+
requiredPolicies: [SELF_POLICY.SUPPORT_REALTIME_CLOSE_CAPTION_MANUAL],
|
4298
|
+
policies: this.selfUserPolicies,
|
4299
|
+
}),
|
4168
4300
|
canChat: ControlsOptionsUtil.hasPolicies({
|
4169
4301
|
requiredPolicies: [SELF_POLICY.SUPPORT_CHAT],
|
4170
4302
|
policies: this.selfUserPolicies,
|
@@ -4211,6 +4343,22 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
4211
4343
|
requiredPolicies: [SELF_POLICY.SUPPORT_ANNOTATION],
|
4212
4344
|
policies: this.selfUserPolicies,
|
4213
4345
|
}),
|
4346
|
+
canEnableAnnotation: ControlsOptionsUtil.hasHints({
|
4347
|
+
requiredHints: [DISPLAY_HINTS.ENABLE_ANNOTATION_MEETING_OPTION],
|
4348
|
+
displayHints: this.userDisplayHints,
|
4349
|
+
}),
|
4350
|
+
canDisableAnnotation: ControlsOptionsUtil.hasHints({
|
4351
|
+
requiredHints: [DISPLAY_HINTS.DISABLE_ANNOTATION_MEETING_OPTION],
|
4352
|
+
displayHints: this.userDisplayHints,
|
4353
|
+
}),
|
4354
|
+
canEnableRemoteDesktopControl: ControlsOptionsUtil.hasHints({
|
4355
|
+
requiredHints: [DISPLAY_HINTS.ENABLE_RDC_MEETING_OPTION],
|
4356
|
+
displayHints: this.userDisplayHints,
|
4357
|
+
}),
|
4358
|
+
canDisableRemoteDesktopControl: ControlsOptionsUtil.hasHints({
|
4359
|
+
requiredHints: [DISPLAY_HINTS.DISABLE_RDC_MEETING_OPTION],
|
4360
|
+
displayHints: this.userDisplayHints,
|
4361
|
+
}),
|
4214
4362
|
}) || changed;
|
4215
4363
|
}
|
4216
4364
|
if (changed) {
|
@@ -5718,8 +5866,6 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
5718
5866
|
// @ts-ignore
|
5719
5867
|
this.webex.internal.device.meetingStarted();
|
5720
5868
|
|
5721
|
-
this.#isoLocalClientMeetingJoinTime = new Date().toISOString();
|
5722
|
-
|
5723
5869
|
LoggerProxy.logger.log('Meeting:index#join --> Success');
|
5724
5870
|
|
5725
5871
|
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.JOIN_SUCCESS, {
|
@@ -6180,10 +6326,18 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
6180
6326
|
},
|
6181
6327
|
options: {meetingId: this.id, rawError: error},
|
6182
6328
|
});
|
6183
|
-
} else if (
|
6184
|
-
error
|
6185
|
-
|
6186
|
-
|
6329
|
+
} else if (error instanceof Errors.SdpOfferHandlingError) {
|
6330
|
+
sendBehavioralMetric(BEHAVIORAL_METRICS.PEERCONNECTION_FAILURE, error, this.correlationId);
|
6331
|
+
|
6332
|
+
// @ts-ignore
|
6333
|
+
this.webex.internal.newMetrics.submitClientEvent({
|
6334
|
+
name: 'client.media-engine.remote-sdp-received',
|
6335
|
+
payload: {
|
6336
|
+
canProceed: false,
|
6337
|
+
},
|
6338
|
+
options: {meetingId: this.id, rawError: error},
|
6339
|
+
});
|
6340
|
+
} else if (error instanceof Errors.SdpAnswerHandlingError) {
|
6187
6341
|
sendBehavioralMetric(BEHAVIORAL_METRICS.PEERCONNECTION_FAILURE, error, this.correlationId);
|
6188
6342
|
|
6189
6343
|
// @ts-ignore
|
@@ -6194,6 +6348,13 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
6194
6348
|
},
|
6195
6349
|
options: {meetingId: this.id, rawError: error},
|
6196
6350
|
});
|
6351
|
+
|
6352
|
+
if (this.deferSDPAnswer) {
|
6353
|
+
clearTimeout(this.sdpResponseTimer);
|
6354
|
+
this.sdpResponseTimer = undefined;
|
6355
|
+
|
6356
|
+
this.deferSDPAnswer.reject();
|
6357
|
+
}
|
6197
6358
|
} else if (error instanceof Errors.SdpError) {
|
6198
6359
|
// this covers also the case of Errors.IceGatheringError which extends Errors.SdpError
|
6199
6360
|
sendBehavioralMetric(BEHAVIORAL_METRICS.INVALID_ICE_CANDIDATE, error, this.correlationId);
|
@@ -6221,6 +6382,11 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
6221
6382
|
? MeetingsUtil.getMediaServer(roapMessage.sdp)
|
6222
6383
|
: undefined;
|
6223
6384
|
|
6385
|
+
const mediaServerIp =
|
6386
|
+
roapMessage.messageType === 'ANSWER'
|
6387
|
+
? MeetingsUtil.getMediaServerIp(roapMessage.sdp)
|
6388
|
+
: undefined;
|
6389
|
+
|
6224
6390
|
if (this.isMultistream && mediaServer && mediaServer !== 'homer') {
|
6225
6391
|
throw new MultistreamNotSupportedError(
|
6226
6392
|
`Client asked for multistream backend (Homer), but got ${mediaServer} instead`
|
@@ -6231,6 +6397,10 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
6231
6397
|
if (mediaServer) {
|
6232
6398
|
this.mediaProperties.webrtcMediaConnection.mediaServer = mediaServer;
|
6233
6399
|
}
|
6400
|
+
|
6401
|
+
if (this.isMultistream && mediaServerIp) {
|
6402
|
+
this.mediaServerIp = mediaServerIp;
|
6403
|
+
}
|
6234
6404
|
};
|
6235
6405
|
|
6236
6406
|
/**
|
@@ -6688,20 +6858,20 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
6688
6858
|
* @memberof Meetings
|
6689
6859
|
*/
|
6690
6860
|
setupStatsAnalyzerEventHandlers = () => {
|
6691
|
-
this.statsAnalyzer.on(StatsAnalyzerEventNames.MEDIA_QUALITY, (
|
6692
|
-
//
|
6693
|
-
|
6694
|
-
|
6695
|
-
|
6696
|
-
|
6697
|
-
|
6698
|
-
|
6699
|
-
|
6861
|
+
this.statsAnalyzer.on(StatsAnalyzerEventNames.MEDIA_QUALITY, (event) => {
|
6862
|
+
// Add IP address from geoHintInfo if missing.
|
6863
|
+
if (event.data.intervalMetadata.maskedPeerReflexiveIP === '0.0.0.0') {
|
6864
|
+
// @ts-ignore fix type
|
6865
|
+
const clientAddressFromGeoHint = this.webex.meetings.geoHintInfo?.clientAddress;
|
6866
|
+
if (clientAddressFromGeoHint) {
|
6867
|
+
event.data.intervalMetadata.maskedPeerReflexiveIP =
|
6868
|
+
CallDiagnosticUtils.anonymizeIPAddress(clientAddressFromGeoHint);
|
6869
|
+
}
|
6870
|
+
}
|
6700
6871
|
|
6872
|
+
// Count members that are in the meeting.
|
6701
6873
|
const {members} = this.getMembers().membersCollection;
|
6702
|
-
|
6703
|
-
// Count members that are in the meeting
|
6704
|
-
options.data.intervalMetadata.meetingUserCount = Object.values(members).filter(
|
6874
|
+
event.data.intervalMetadata.meetingUserCount = Object.values(members).filter(
|
6705
6875
|
(member: Member) => member.isInMeeting
|
6706
6876
|
).length;
|
6707
6877
|
|
@@ -6710,10 +6880,10 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
6710
6880
|
name: 'client.mediaquality.event',
|
6711
6881
|
options: {
|
6712
6882
|
meetingId: this.id,
|
6713
|
-
networkType:
|
6883
|
+
networkType: this.statsAnalyzer.getNetworkType(),
|
6714
6884
|
},
|
6715
6885
|
payload: {
|
6716
|
-
intervals: [
|
6886
|
+
intervals: [event.data],
|
6717
6887
|
},
|
6718
6888
|
});
|
6719
6889
|
});
|
@@ -6728,30 +6898,42 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
6728
6898
|
EVENT_TRIGGERS.MEETING_MEDIA_LOCAL_STARTED,
|
6729
6899
|
data
|
6730
6900
|
);
|
6731
|
-
|
6732
|
-
|
6733
|
-
|
6734
|
-
|
6735
|
-
|
6736
|
-
|
6737
|
-
|
6738
|
-
|
6739
|
-
|
6740
|
-
|
6741
|
-
|
6901
|
+
if (data.mediaType !== 'share' || !this.shareCAEventSentStatus.transmitStart) {
|
6902
|
+
// @ts-ignore
|
6903
|
+
this.webex.internal.newMetrics.submitClientEvent({
|
6904
|
+
name: 'client.media.tx.start',
|
6905
|
+
payload: {
|
6906
|
+
mediaType: data.mediaType,
|
6907
|
+
shareInstanceId: data.mediaType === 'share' ? this.localShareInstanceId : undefined,
|
6908
|
+
},
|
6909
|
+
options: {
|
6910
|
+
meetingId: this.id,
|
6911
|
+
},
|
6912
|
+
});
|
6913
|
+
|
6914
|
+
if (data.mediaType === 'share') {
|
6915
|
+
this.shareCAEventSentStatus.transmitStart = true;
|
6916
|
+
}
|
6917
|
+
}
|
6742
6918
|
});
|
6743
6919
|
this.statsAnalyzer.on(StatsAnalyzerEventNames.LOCAL_MEDIA_STOPPED, (data) => {
|
6744
|
-
|
6745
|
-
|
6746
|
-
|
6747
|
-
|
6748
|
-
|
6749
|
-
|
6750
|
-
|
6751
|
-
|
6752
|
-
|
6753
|
-
|
6754
|
-
|
6920
|
+
if (data.mediaType !== 'share' || !this.shareCAEventSentStatus.transmitStop) {
|
6921
|
+
// @ts-ignore
|
6922
|
+
this.webex.internal.newMetrics.submitClientEvent({
|
6923
|
+
name: 'client.media.tx.stop',
|
6924
|
+
payload: {
|
6925
|
+
mediaType: data.mediaType,
|
6926
|
+
shareInstanceId: data.mediaType === 'share' ? this.localShareInstanceId : undefined,
|
6927
|
+
},
|
6928
|
+
options: {
|
6929
|
+
meetingId: this.id,
|
6930
|
+
},
|
6931
|
+
});
|
6932
|
+
|
6933
|
+
if (data.mediaType === 'share') {
|
6934
|
+
this.shareCAEventSentStatus.transmitStop = true;
|
6935
|
+
}
|
6936
|
+
}
|
6755
6937
|
});
|
6756
6938
|
this.statsAnalyzer.on(StatsAnalyzerEventNames.REMOTE_MEDIA_STARTED, (data) => {
|
6757
6939
|
Trigger.trigger(
|
@@ -6763,57 +6945,65 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
6763
6945
|
EVENT_TRIGGERS.MEETING_MEDIA_REMOTE_STARTED,
|
6764
6946
|
data
|
6765
6947
|
);
|
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') {
|
6948
|
+
if (data.mediaType !== 'share' || !this.shareCAEventSentStatus.receiveStart) {
|
6779
6949
|
// @ts-ignore
|
6780
6950
|
this.webex.internal.newMetrics.submitClientEvent({
|
6781
|
-
name: 'client.media.
|
6951
|
+
name: 'client.media.rx.start',
|
6782
6952
|
payload: {
|
6783
|
-
mediaType:
|
6784
|
-
shareInstanceId: this.remoteShareInstanceId,
|
6953
|
+
mediaType: data.mediaType,
|
6954
|
+
shareInstanceId: data.mediaType === 'share' ? this.remoteShareInstanceId : undefined,
|
6785
6955
|
},
|
6786
6956
|
options: {
|
6787
6957
|
meetingId: this.id,
|
6788
6958
|
},
|
6789
6959
|
});
|
6960
|
+
|
6961
|
+
if (data.mediaType === 'share') {
|
6962
|
+
// @ts-ignore
|
6963
|
+
this.webex.internal.newMetrics.submitClientEvent({
|
6964
|
+
name: 'client.media.render.start',
|
6965
|
+
payload: {
|
6966
|
+
mediaType: 'share',
|
6967
|
+
shareInstanceId: this.remoteShareInstanceId,
|
6968
|
+
},
|
6969
|
+
options: {
|
6970
|
+
meetingId: this.id,
|
6971
|
+
},
|
6972
|
+
});
|
6973
|
+
|
6974
|
+
this.shareCAEventSentStatus.receiveStart = true;
|
6975
|
+
}
|
6790
6976
|
}
|
6791
6977
|
});
|
6792
6978
|
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') {
|
6979
|
+
if (data.mediaType !== 'share' || !this.shareCAEventSentStatus.receiveStop) {
|
6806
6980
|
// @ts-ignore
|
6807
6981
|
this.webex.internal.newMetrics.submitClientEvent({
|
6808
|
-
name: 'client.media.
|
6982
|
+
name: 'client.media.rx.stop',
|
6809
6983
|
payload: {
|
6810
|
-
mediaType:
|
6811
|
-
shareInstanceId: this.remoteShareInstanceId,
|
6984
|
+
mediaType: data.mediaType,
|
6985
|
+
shareInstanceId: data.mediaType === 'share' ? this.remoteShareInstanceId : undefined,
|
6812
6986
|
},
|
6813
6987
|
options: {
|
6814
6988
|
meetingId: this.id,
|
6815
6989
|
},
|
6816
6990
|
});
|
6991
|
+
|
6992
|
+
if (data.mediaType === 'share') {
|
6993
|
+
// @ts-ignore
|
6994
|
+
this.webex.internal.newMetrics.submitClientEvent({
|
6995
|
+
name: 'client.media.render.stop',
|
6996
|
+
payload: {
|
6997
|
+
mediaType: 'share',
|
6998
|
+
shareInstanceId: this.remoteShareInstanceId,
|
6999
|
+
},
|
7000
|
+
options: {
|
7001
|
+
meetingId: this.id,
|
7002
|
+
},
|
7003
|
+
});
|
7004
|
+
|
7005
|
+
this.shareCAEventSentStatus.receiveStop = true;
|
7006
|
+
}
|
6817
7007
|
}
|
6818
7008
|
});
|
6819
7009
|
};
|
@@ -6830,7 +7020,10 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
6830
7020
|
* @param {AddMediaOptions} [options] Options for enabling/disabling audio/video
|
6831
7021
|
* @returns {RoapMediaConnection | MultistreamRoapMediaConnection}
|
6832
7022
|
*/
|
6833
|
-
private async createMediaConnection(
|
7023
|
+
private async createMediaConnection(
|
7024
|
+
turnServerInfo?: TurnServerInfo,
|
7025
|
+
bundlePolicy?: BundlePolicy
|
7026
|
+
) {
|
6834
7027
|
this.rtcMetrics = this.isMultistream
|
6835
7028
|
? // @ts-ignore
|
6836
7029
|
new RtcMetrics(this.webex, {meetingId: this.id}, this.correlationId)
|
@@ -6855,6 +7048,13 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
6855
7048
|
bundlePolicy,
|
6856
7049
|
// @ts-ignore - config coming from registerPlugin
|
6857
7050
|
iceCandidatesTimeout: this.config.iceCandidatesGatheringTimeout,
|
7051
|
+
// @ts-ignore - config coming from registerPlugin
|
7052
|
+
disableAudioMainDtx: this.config.experimental.disableAudioMainDtx,
|
7053
|
+
// @ts-ignore - config coming from registerPlugin
|
7054
|
+
enableAudioTwcc: this.config.enableAudioTwccForMultistream,
|
7055
|
+
stopIceGatheringAfterFirstRelayCandidate:
|
7056
|
+
// @ts-ignore - config coming from registerPlugin
|
7057
|
+
this.config.stopIceGatheringAfterFirstRelayCandidate,
|
6858
7058
|
}
|
6859
7059
|
);
|
6860
7060
|
|
@@ -7005,12 +7205,18 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
7005
7205
|
},
|
7006
7206
|
options: {
|
7007
7207
|
meetingId: this.id,
|
7208
|
+
rawError: error,
|
7008
7209
|
},
|
7009
7210
|
});
|
7010
7211
|
}
|
7011
|
-
|
7212
|
+
|
7213
|
+
const timedOutError = new Error(
|
7012
7214
|
`Timed out waiting for media connection to be connected, correlationId=${this.correlationId}`
|
7013
7215
|
);
|
7216
|
+
|
7217
|
+
timedOutError.cause = error;
|
7218
|
+
|
7219
|
+
throw timedOutError;
|
7014
7220
|
}
|
7015
7221
|
}
|
7016
7222
|
|
@@ -7031,6 +7237,12 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
7031
7237
|
networkQualityMonitor: this.networkQualityMonitor,
|
7032
7238
|
isMultistream: this.isMultistream,
|
7033
7239
|
});
|
7240
|
+
this.shareCAEventSentStatus = {
|
7241
|
+
transmitStart: false,
|
7242
|
+
transmitStop: false,
|
7243
|
+
receiveStart: false,
|
7244
|
+
receiveStop: false,
|
7245
|
+
};
|
7034
7246
|
this.setupStatsAnalyzerEventHandlers();
|
7035
7247
|
this.networkQualityMonitor.on(
|
7036
7248
|
NetworkQualityEventNames.NETWORK_QUALITY,
|
@@ -7065,6 +7277,9 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
7065
7277
|
ROAP_OFFER_ANSWER_EXCHANGE_TIMEOUT / 1000
|
7066
7278
|
} seconds`
|
7067
7279
|
);
|
7280
|
+
|
7281
|
+
const error = new Error('Timed out waiting for REMOTE SDP ANSWER');
|
7282
|
+
|
7068
7283
|
// @ts-ignore
|
7069
7284
|
this.webex.internal.newMetrics.submitClientEvent({
|
7070
7285
|
name: 'client.media-engine.remote-sdp-received',
|
@@ -7077,10 +7292,10 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
7077
7292
|
}),
|
7078
7293
|
],
|
7079
7294
|
},
|
7080
|
-
options: {meetingId: this.id, rawError:
|
7295
|
+
options: {meetingId: this.id, rawError: error},
|
7081
7296
|
});
|
7082
7297
|
|
7083
|
-
deferSDPAnswer.reject(
|
7298
|
+
deferSDPAnswer.reject(error);
|
7084
7299
|
}, ROAP_OFFER_ANSWER_EXCHANGE_TIMEOUT);
|
7085
7300
|
|
7086
7301
|
LoggerProxy.logger.info(`${LOG_HEADER} waiting for REMOTE SDP ANSWER...`);
|
@@ -7185,7 +7400,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
7185
7400
|
error
|
7186
7401
|
);
|
7187
7402
|
|
7188
|
-
throw new AddMediaFailed();
|
7403
|
+
throw new AddMediaFailed(error);
|
7189
7404
|
}
|
7190
7405
|
}
|
7191
7406
|
|
@@ -7598,28 +7813,33 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
7598
7813
|
await this.enqueueScreenShareFloorRequest();
|
7599
7814
|
}
|
7600
7815
|
|
7601
|
-
const {connectionType, selectedCandidatePairChanges, numTransports} =
|
7816
|
+
const {connectionType, ipVersion, selectedCandidatePairChanges, numTransports} =
|
7602
7817
|
await this.mediaProperties.getCurrentConnectionInfo();
|
7603
|
-
|
7604
|
-
const reachabilityStats = await this.webex.meetings.reachability.getReachabilityMetrics();
|
7818
|
+
|
7605
7819
|
const iceCandidateErrors = Object.fromEntries(this.iceCandidateErrors);
|
7606
7820
|
|
7821
|
+
const reachabilityMetrics = await this.getMediaReachabilityMetricFields();
|
7822
|
+
|
7607
7823
|
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.ADD_MEDIA_SUCCESS, {
|
7608
7824
|
correlation_id: this.correlationId,
|
7609
7825
|
locus_id: this.locusUrl.split('/').pop(),
|
7610
7826
|
connectionType,
|
7827
|
+
ipVersion,
|
7611
7828
|
selectedCandidatePairChanges,
|
7612
7829
|
numTransports,
|
7613
7830
|
isMultistream: this.isMultistream,
|
7614
7831
|
retriedWithTurnServer: this.addMediaData.retriedWithTurnServer,
|
7615
7832
|
isJoinWithMediaRetry: this.joinWithMediaRetryInfo.isRetry,
|
7616
|
-
...
|
7833
|
+
...reachabilityMetrics,
|
7617
7834
|
...iceCandidateErrors,
|
7618
7835
|
iceCandidatesCount: this.iceCandidatesCount,
|
7619
7836
|
});
|
7620
7837
|
// @ts-ignore
|
7621
7838
|
this.webex.internal.newMetrics.submitClientEvent({
|
7622
7839
|
name: 'client.media-engine.ready',
|
7840
|
+
payload: {
|
7841
|
+
ipVersion,
|
7842
|
+
},
|
7623
7843
|
options: {
|
7624
7844
|
meetingId: this.id,
|
7625
7845
|
},
|
@@ -7635,7 +7855,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
7635
7855
|
LoggerProxy.logger.error(`${LOG_HEADER} failed to establish media connection: `, error);
|
7636
7856
|
|
7637
7857
|
// @ts-ignore
|
7638
|
-
const reachabilityMetrics = await this.
|
7858
|
+
const reachabilityMetrics = await this.getMediaReachabilityMetricFields();
|
7639
7859
|
|
7640
7860
|
const {selectedCandidatePairChanges, numTransports} =
|
7641
7861
|
await this.mediaProperties.getCurrentConnectionInfo();
|
@@ -8715,6 +8935,9 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
8715
8935
|
LoggerProxy.logger.log(
|
8716
8936
|
`Meeting:index#handleShareVideoStreamMuteStateChange --> Share video stream mute state changed to muted ${muted}`
|
8717
8937
|
);
|
8938
|
+
|
8939
|
+
const shareVideoStreamSettings = this.mediaProperties?.shareVideoStream?.getSettings();
|
8940
|
+
|
8718
8941
|
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.MEETING_SHARE_VIDEO_MUTE_STATE_CHANGE, {
|
8719
8942
|
correlationId: this.correlationId,
|
8720
8943
|
muted,
|
@@ -8723,8 +8946,9 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
8723
8946
|
// SDK to TypeScript 5, which may affect other packages, use bracket notation for now, since
|
8724
8947
|
// all we're doing here is adding metrics.
|
8725
8948
|
// eslint-disable-next-line dot-notation
|
8726
|
-
displaySurface:
|
8949
|
+
displaySurface: shareVideoStreamSettings?.['displaySurface'],
|
8727
8950
|
isMultistream: this.isMultistream,
|
8951
|
+
frameRate: shareVideoStreamSettings?.frameRate,
|
8728
8952
|
});
|
8729
8953
|
};
|
8730
8954
|
|
@@ -9051,6 +9275,23 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
9051
9275
|
});
|
9052
9276
|
}
|
9053
9277
|
|
9278
|
+
/**
|
9279
|
+
* Method to set post meeting data consent.
|
9280
|
+
*
|
9281
|
+
* @param {boolean} accept - whether consent accepted or declined
|
9282
|
+
* @returns {Promise}
|
9283
|
+
* @public
|
9284
|
+
* @memberof Meeting
|
9285
|
+
*/
|
9286
|
+
public setPostMeetingDataConsent(accept: boolean) {
|
9287
|
+
return this.meetingRequest.setPostMeetingDataConsent({
|
9288
|
+
postMeetingDataConsent: accept,
|
9289
|
+
locusUrl: this.locusUrl,
|
9290
|
+
deviceUrl: this.deviceUrl,
|
9291
|
+
selfId: this.members.selfId,
|
9292
|
+
});
|
9293
|
+
}
|
9294
|
+
|
9054
9295
|
/**
|
9055
9296
|
* Throws if we don't have a media connection created
|
9056
9297
|
*
|
@@ -9291,6 +9532,8 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
9291
9532
|
|
9292
9533
|
if (floorRequestNeeded) {
|
9293
9534
|
this.localShareInstanceId = uuid.v4();
|
9535
|
+
this.shareCAEventSentStatus.transmitStart = false;
|
9536
|
+
this.shareCAEventSentStatus.transmitStop = false;
|
9294
9537
|
|
9295
9538
|
// @ts-ignore
|
9296
9539
|
this.webex.internal.newMetrics.submitClientEvent({
|
@@ -9418,4 +9661,50 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
9418
9661
|
|
9419
9662
|
return Promise.resolve();
|
9420
9663
|
}
|
9664
|
+
|
9665
|
+
/**
|
9666
|
+
* Gets the media reachability metrics
|
9667
|
+
*
|
9668
|
+
* @returns {Promise<MediaReachabilityMetrics>}
|
9669
|
+
*/
|
9670
|
+
private async getMediaReachabilityMetricFields(): Promise<MediaReachabilityMetrics> {
|
9671
|
+
const reachabilityMetrics: ReachabilityMetrics =
|
9672
|
+
// @ts-ignore
|
9673
|
+
await this.webex.meetings.reachability.getReachabilityMetrics();
|
9674
|
+
|
9675
|
+
const successKeys: Array<keyof ReachabilityMetrics> = [
|
9676
|
+
'reachability_public_udp_success',
|
9677
|
+
'reachability_public_tcp_success',
|
9678
|
+
'reachability_public_xtls_success',
|
9679
|
+
'reachability_vmn_udp_success',
|
9680
|
+
'reachability_vmn_tcp_success',
|
9681
|
+
'reachability_vmn_xtls_success',
|
9682
|
+
];
|
9683
|
+
|
9684
|
+
const totalSuccessCases = successKeys.reduce((total, key) => {
|
9685
|
+
const value = reachabilityMetrics[key];
|
9686
|
+
if (typeof value === 'number') {
|
9687
|
+
return total + value;
|
9688
|
+
}
|
9689
|
+
|
9690
|
+
return total;
|
9691
|
+
}, 0);
|
9692
|
+
|
9693
|
+
let isSubnetReachable = null;
|
9694
|
+
if (totalSuccessCases > 0) {
|
9695
|
+
// @ts-ignore
|
9696
|
+
isSubnetReachable = this.webex.meetings.reachability.isSubnetReachable(this.mediaServerIp);
|
9697
|
+
}
|
9698
|
+
|
9699
|
+
let selectedCluster = null;
|
9700
|
+
if (this.mediaConnections && this.mediaConnections.length > 0) {
|
9701
|
+
selectedCluster = this.mediaConnections[0].mediaAgentCluster;
|
9702
|
+
}
|
9703
|
+
|
9704
|
+
return {
|
9705
|
+
...reachabilityMetrics,
|
9706
|
+
isSubnetReachable,
|
9707
|
+
selectedCluster,
|
9708
|
+
};
|
9709
|
+
}
|
9421
9710
|
}
|