@webex/plugin-meetings 3.6.0-next.9 → 3.7.0-ipv6-multi-turn-urls.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/dist/breakouts/breakout.js +1 -1
- package/dist/breakouts/index.js +1 -1
- package/dist/common/errors/{webinar-registration-error.js → join-webinar-error.js} +12 -12
- package/dist/common/errors/join-webinar-error.js.map +1 -0
- package/dist/config.js +3 -1
- package/dist/config.js.map +1 -1
- package/dist/constants.js +50 -7
- package/dist/constants.js.map +1 -1
- package/dist/controls-options-manager/enums.js +1 -0
- package/dist/controls-options-manager/enums.js.map +1 -1
- package/dist/controls-options-manager/index.js +10 -3
- package/dist/controls-options-manager/index.js.map +1 -1
- package/dist/controls-options-manager/types.js.map +1 -1
- package/dist/controls-options-manager/util.js +12 -0
- package/dist/controls-options-manager/util.js.map +1 -1
- package/dist/index.js +7 -7
- package/dist/index.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 -4
- package/dist/locus-info/controlsUtils.js.map +1 -1
- package/dist/locus-info/fullState.js +2 -1
- package/dist/locus-info/fullState.js.map +1 -1
- package/dist/locus-info/index.js +61 -3
- package/dist/locus-info/index.js.map +1 -1
- package/dist/media/index.js +29 -1
- package/dist/media/index.js.map +1 -1
- package/dist/meeting/in-meeting-actions.js +29 -1
- package/dist/meeting/in-meeting-actions.js.map +1 -1
- package/dist/meeting/index.js +692 -472
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/locusMediaRequest.js +2 -6
- package/dist/meeting/locusMediaRequest.js.map +1 -1
- package/dist/meeting/request.js +21 -29
- package/dist/meeting/request.js.map +1 -1
- package/dist/meeting/util.js +95 -59
- package/dist/meeting/util.js.map +1 -1
- package/dist/meeting-info/meeting-info-v2.js +29 -17
- package/dist/meeting-info/meeting-info-v2.js.map +1 -1
- package/dist/meetings/index.js +8 -3
- package/dist/meetings/index.js.map +1 -1
- package/dist/members/index.js +3 -2
- package/dist/members/index.js.map +1 -1
- package/dist/members/util.js +13 -7
- package/dist/members/util.js.map +1 -1
- package/dist/metrics/constants.js +3 -1
- package/dist/metrics/constants.js.map +1 -1
- package/dist/multistream/remoteMedia.js +30 -15
- package/dist/multistream/remoteMedia.js.map +1 -1
- package/dist/reachability/clusterReachability.js +12 -15
- package/dist/reachability/clusterReachability.js.map +1 -1
- package/dist/reachability/index.js +433 -136
- package/dist/reachability/index.js.map +1 -1
- package/dist/reachability/reachability.types.js +7 -0
- package/dist/reachability/reachability.types.js.map +1 -0
- package/dist/reachability/request.js +23 -9
- package/dist/reachability/request.js.map +1 -1
- package/dist/recording-controller/enums.js +8 -4
- package/dist/recording-controller/enums.js.map +1 -1
- package/dist/recording-controller/index.js +18 -9
- package/dist/recording-controller/index.js.map +1 -1
- package/dist/recording-controller/util.js +13 -9
- package/dist/recording-controller/util.js.map +1 -1
- package/dist/roap/index.js +5 -7
- package/dist/roap/index.js.map +1 -1
- package/dist/roap/request.js +45 -79
- package/dist/roap/request.js.map +1 -1
- package/dist/roap/turnDiscovery.js +3 -6
- package/dist/roap/turnDiscovery.js.map +1 -1
- package/dist/types/common/errors/{webinar-registration-error.d.ts → join-webinar-error.d.ts} +2 -2
- package/dist/types/config.d.ts +2 -0
- package/dist/types/constants.d.ts +38 -1
- package/dist/types/controls-options-manager/enums.d.ts +2 -1
- package/dist/types/controls-options-manager/index.d.ts +2 -1
- package/dist/types/controls-options-manager/types.d.ts +2 -0
- package/dist/types/index.d.ts +2 -2
- package/dist/types/locus-info/index.d.ts +9 -0
- package/dist/types/meeting/in-meeting-actions.d.ts +28 -0
- package/dist/types/meeting/index.d.ts +34 -3
- package/dist/types/meeting/locusMediaRequest.d.ts +2 -3
- package/dist/types/meeting/request.d.ts +2 -2
- package/dist/types/meeting/util.d.ts +2 -2
- package/dist/types/meeting-info/meeting-info-v2.d.ts +4 -4
- package/dist/types/meetings/index.d.ts +4 -1
- package/dist/types/members/index.d.ts +2 -1
- package/dist/types/members/util.d.ts +5 -1
- package/dist/types/metrics/constants.d.ts +3 -1
- package/dist/types/reachability/clusterReachability.d.ts +1 -10
- package/dist/types/reachability/index.d.ts +74 -35
- package/dist/types/reachability/reachability.types.d.ts +64 -0
- package/dist/types/reachability/request.d.ts +5 -1
- package/dist/types/recording-controller/enums.d.ts +5 -2
- package/dist/types/recording-controller/index.d.ts +1 -0
- package/dist/types/recording-controller/util.d.ts +2 -1
- package/dist/types/roap/request.d.ts +1 -13
- package/dist/webinar/index.js +382 -19
- package/dist/webinar/index.js.map +1 -1
- package/package.json +22 -22
- package/src/common/errors/join-webinar-error.ts +24 -0
- package/src/config.ts +2 -0
- package/src/constants.ts +49 -3
- package/src/controls-options-manager/enums.ts +1 -0
- package/src/controls-options-manager/index.ts +19 -2
- package/src/controls-options-manager/types.ts +2 -0
- package/src/controls-options-manager/util.ts +12 -0
- package/src/index.ts +2 -2
- package/src/locus-info/controlsUtils.ts +46 -2
- package/src/locus-info/fullState.ts +1 -0
- package/src/locus-info/index.ts +60 -0
- package/src/media/index.ts +15 -0
- package/src/meeting/in-meeting-actions.ts +58 -0
- package/src/meeting/index.ts +232 -25
- package/src/meeting/locusMediaRequest.ts +4 -8
- package/src/meeting/request.ts +4 -11
- package/src/meeting/util.ts +25 -4
- package/src/meeting-info/meeting-info-v2.ts +23 -11
- package/src/meetings/index.ts +54 -41
- package/src/members/index.ts +4 -2
- package/src/members/util.ts +4 -1
- package/src/metrics/constants.ts +3 -1
- package/src/multistream/remoteMedia.ts +28 -15
- package/src/reachability/clusterReachability.ts +5 -15
- package/src/reachability/index.ts +285 -77
- package/src/reachability/reachability.types.ts +85 -0
- package/src/reachability/request.ts +55 -30
- package/src/recording-controller/enums.ts +5 -2
- package/src/recording-controller/index.ts +17 -4
- package/src/recording-controller/util.ts +20 -5
- package/src/roap/index.ts +4 -5
- package/src/roap/request.ts +30 -44
- package/src/roap/turnDiscovery.ts +2 -4
- package/src/webinar/index.ts +223 -17
- package/test/unit/spec/controls-options-manager/index.js +56 -32
- package/test/unit/spec/controls-options-manager/util.js +44 -0
- package/test/unit/spec/locus-info/controlsUtils.js +80 -4
- package/test/unit/spec/locus-info/index.js +59 -2
- package/test/unit/spec/meeting/in-meeting-actions.ts +31 -1
- package/test/unit/spec/meeting/index.js +369 -103
- package/test/unit/spec/meeting/locusMediaRequest.ts +18 -11
- package/test/unit/spec/meeting/request.js +3 -26
- package/test/unit/spec/meeting/utils.js +55 -13
- package/test/unit/spec/meeting-info/meetinginfov2.js +9 -4
- package/test/unit/spec/meetings/index.js +25 -6
- package/test/unit/spec/members/index.js +25 -2
- package/test/unit/spec/members/request.js +37 -3
- package/test/unit/spec/members/utils.js +110 -1
- package/test/unit/spec/multistream/remoteMedia.ts +11 -7
- package/test/unit/spec/reachability/clusterReachability.ts +7 -0
- package/test/unit/spec/reachability/index.ts +265 -1
- package/test/unit/spec/reachability/request.js +56 -15
- package/test/unit/spec/recording-controller/index.js +61 -5
- package/test/unit/spec/recording-controller/util.js +39 -3
- package/test/unit/spec/roap/index.ts +1 -1
- package/test/unit/spec/roap/request.ts +51 -109
- package/test/unit/spec/roap/turnDiscovery.ts +202 -147
- package/test/unit/spec/webinar/index.ts +443 -14
- package/dist/common/errors/webinar-registration-error.js.map +0 -1
- package/src/common/errors/webinar-registration-error.ts +0 -27
package/src/meeting/index.ts
CHANGED
|
@@ -5,6 +5,7 @@ import jwtDecode from 'jwt-decode';
|
|
|
5
5
|
import {StatelessWebexPlugin} from '@webex/webex-core';
|
|
6
6
|
// @ts-ignore - Types not available for @webex/common
|
|
7
7
|
import {Defer} from '@webex/common';
|
|
8
|
+
import {safeSetTimeout, safeSetInterval} from '@webex/common-timers';
|
|
8
9
|
import {
|
|
9
10
|
ClientEvent,
|
|
10
11
|
ClientEventLeaveReason,
|
|
@@ -121,6 +122,8 @@ import {
|
|
|
121
122
|
MEETING_PERMISSION_TOKEN_REFRESH_REASON,
|
|
122
123
|
ROAP_OFFER_ANSWER_EXCHANGE_TIMEOUT,
|
|
123
124
|
NAMED_MEDIA_GROUP_TYPE_AUDIO,
|
|
125
|
+
WEBINAR_ERROR_WEBCAST,
|
|
126
|
+
WEBINAR_ERROR_REGISTRATIONID,
|
|
124
127
|
} from '../constants';
|
|
125
128
|
import BEHAVIORAL_METRICS from '../metrics/constants';
|
|
126
129
|
import ParameterError from '../common/errors/parameter';
|
|
@@ -128,7 +131,7 @@ import {
|
|
|
128
131
|
MeetingInfoV2PasswordError,
|
|
129
132
|
MeetingInfoV2CaptchaError,
|
|
130
133
|
MeetingInfoV2PolicyError,
|
|
131
|
-
|
|
134
|
+
MeetingInfoV2JoinWebinarError,
|
|
132
135
|
} from '../meeting-info/meeting-info-v2';
|
|
133
136
|
import {CSI, ReceiveSlotManager} from '../multistream/receiveSlotManager';
|
|
134
137
|
import SendSlotManager from '../multistream/sendSlotManager';
|
|
@@ -157,7 +160,7 @@ import ControlsOptionsManager from '../controls-options-manager';
|
|
|
157
160
|
import PermissionError from '../common/errors/permission';
|
|
158
161
|
import {LocusMediaRequest} from './locusMediaRequest';
|
|
159
162
|
import {ConnectionStateHandler, ConnectionStateEvent} from './connectionStateHandler';
|
|
160
|
-
import
|
|
163
|
+
import JoinWebinarError from '../common/errors/join-webinar-error';
|
|
161
164
|
|
|
162
165
|
// default callback so we don't call an undefined function, but in practice it should never be used
|
|
163
166
|
const DEFAULT_ICE_PHASE_CALLBACK = () => 'JOIN_MEETING_FINAL';
|
|
@@ -702,6 +705,8 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
702
705
|
private iceCandidateErrors: Map<string, number>;
|
|
703
706
|
private iceCandidatesCount: number;
|
|
704
707
|
private rtcMetrics?: RtcMetrics;
|
|
708
|
+
private uploadLogsTimer?: ReturnType<typeof setTimeout>;
|
|
709
|
+
private logUploadIntervalIndex: number;
|
|
705
710
|
|
|
706
711
|
/**
|
|
707
712
|
* @param {Object} attrs
|
|
@@ -770,6 +775,8 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
770
775
|
);
|
|
771
776
|
this.callStateForMetrics.correlationId = this.id;
|
|
772
777
|
}
|
|
778
|
+
this.logUploadIntervalIndex = 0;
|
|
779
|
+
|
|
773
780
|
/**
|
|
774
781
|
* @instance
|
|
775
782
|
* @type {String}
|
|
@@ -1762,15 +1769,20 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1762
1769
|
this.meetingInfo = err.meetingInfo;
|
|
1763
1770
|
}
|
|
1764
1771
|
throw new PermissionError();
|
|
1765
|
-
} else if (err instanceof
|
|
1772
|
+
} else if (err instanceof MeetingInfoV2JoinWebinarError) {
|
|
1766
1773
|
this.meetingInfoFailureReason = MEETING_INFO_FAILURE_REASON.WEBINAR_REGISTRATION;
|
|
1774
|
+
if (WEBINAR_ERROR_WEBCAST.includes(err.wbxAppApiCode)) {
|
|
1775
|
+
this.meetingInfoFailureReason = MEETING_INFO_FAILURE_REASON.NEED_JOIN_WITH_WEBCAST;
|
|
1776
|
+
} else if (WEBINAR_ERROR_REGISTRATIONID.includes(err.wbxAppApiCode)) {
|
|
1777
|
+
this.meetingInfoFailureReason = MEETING_INFO_FAILURE_REASON.WEBINAR_NEED_REGISTRATIONID;
|
|
1778
|
+
}
|
|
1767
1779
|
this.meetingInfoFailureCode = err.wbxAppApiCode;
|
|
1768
1780
|
|
|
1769
1781
|
if (err.meetingInfo) {
|
|
1770
1782
|
this.meetingInfo = err.meetingInfo;
|
|
1771
1783
|
}
|
|
1772
1784
|
|
|
1773
|
-
throw new
|
|
1785
|
+
throw new JoinWebinarError();
|
|
1774
1786
|
} else if (err instanceof MeetingInfoV2PasswordError) {
|
|
1775
1787
|
LoggerProxy.logger.info(
|
|
1776
1788
|
// @ts-ignore
|
|
@@ -2014,6 +2026,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2014
2026
|
this.setUpLocusInfoSelfListener();
|
|
2015
2027
|
this.setUpLocusInfoMeetingListener();
|
|
2016
2028
|
this.setUpLocusServicesListener();
|
|
2029
|
+
this.setUpLocusResourcesListener();
|
|
2017
2030
|
// members update listeners
|
|
2018
2031
|
this.setUpLocusFullStateListener();
|
|
2019
2032
|
this.setUpLocusUrlListener();
|
|
@@ -2635,6 +2648,43 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2635
2648
|
);
|
|
2636
2649
|
});
|
|
2637
2650
|
|
|
2651
|
+
this.locusInfo.on(LOCUSINFO.EVENTS.CONTROLS_WEBCAST_CHANGED, ({state}) => {
|
|
2652
|
+
Trigger.trigger(
|
|
2653
|
+
this,
|
|
2654
|
+
{file: 'meeting/index', function: 'setupLocusControlsListener'},
|
|
2655
|
+
EVENT_TRIGGERS.MEETING_CONTROLS_WEBCAST_UPDATED,
|
|
2656
|
+
{state}
|
|
2657
|
+
);
|
|
2658
|
+
});
|
|
2659
|
+
|
|
2660
|
+
this.locusInfo.on(LOCUSINFO.EVENTS.CONTROLS_MEETING_FULL_CHANGED, ({state}) => {
|
|
2661
|
+
Trigger.trigger(
|
|
2662
|
+
this,
|
|
2663
|
+
{file: 'meeting/index', function: 'setupLocusControlsListener'},
|
|
2664
|
+
EVENT_TRIGGERS.MEETING_CONTROLS_MEETING_FULL_UPDATED,
|
|
2665
|
+
{state}
|
|
2666
|
+
);
|
|
2667
|
+
});
|
|
2668
|
+
|
|
2669
|
+
this.locusInfo.on(LOCUSINFO.EVENTS.CONTROLS_PRACTICE_SESSION_STATUS_UPDATED, ({state}) => {
|
|
2670
|
+
this.webinar.updatePracticeSessionStatus(state);
|
|
2671
|
+
Trigger.trigger(
|
|
2672
|
+
this,
|
|
2673
|
+
{file: 'meeting/index', function: 'setupLocusControlsListener'},
|
|
2674
|
+
EVENT_TRIGGERS.MEETING_CONTROLS_PRACTICE_SESSION_STATUS_UPDATED,
|
|
2675
|
+
{state}
|
|
2676
|
+
);
|
|
2677
|
+
});
|
|
2678
|
+
|
|
2679
|
+
this.locusInfo.on(LOCUSINFO.EVENTS.CONTROLS_STAGE_VIEW_UPDATED, ({state}) => {
|
|
2680
|
+
Trigger.trigger(
|
|
2681
|
+
this,
|
|
2682
|
+
{file: 'meeting/index', function: 'setupLocusControlsListener'},
|
|
2683
|
+
EVENT_TRIGGERS.MEETING_CONTROLS_STAGE_VIEW_UPDATED,
|
|
2684
|
+
{state}
|
|
2685
|
+
);
|
|
2686
|
+
});
|
|
2687
|
+
|
|
2638
2688
|
this.locusInfo.on(LOCUSINFO.EVENTS.CONTROLS_VIDEO_CHANGED, ({state}) => {
|
|
2639
2689
|
Trigger.trigger(
|
|
2640
2690
|
this,
|
|
@@ -2996,10 +3046,20 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2996
3046
|
this.breakouts.breakoutServiceUrlUpdate(payload?.services?.breakout?.url);
|
|
2997
3047
|
this.annotation.approvalUrlUpdate(payload?.services?.approval?.url);
|
|
2998
3048
|
this.simultaneousInterpretation.approvalUrlUpdate(payload?.services?.approval?.url);
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
|
|
3049
|
+
});
|
|
3050
|
+
}
|
|
3051
|
+
|
|
3052
|
+
/**
|
|
3053
|
+
* Set up the locus info resources link listener
|
|
3054
|
+
* update the locusInfo for webcast instance url
|
|
3055
|
+
* @param {Object} payload - The event payload
|
|
3056
|
+
* @returns {undefined}
|
|
3057
|
+
* @private
|
|
3058
|
+
* @memberof Meeting
|
|
3059
|
+
*/
|
|
3060
|
+
private setUpLocusResourcesListener() {
|
|
3061
|
+
this.locusInfo.on(LOCUSINFO.EVENTS.LINKS_RESOURCES, (payload) => {
|
|
3062
|
+
this.webinar.updateWebcastUrl(payload);
|
|
3003
3063
|
});
|
|
3004
3064
|
}
|
|
3005
3065
|
|
|
@@ -3202,6 +3262,9 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3202
3262
|
options: {meetingId: this.id},
|
|
3203
3263
|
});
|
|
3204
3264
|
}
|
|
3265
|
+
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.GUEST_ENTERED_LOBBY, {
|
|
3266
|
+
correlation_id: this.correlationId,
|
|
3267
|
+
});
|
|
3205
3268
|
this.updateLLMConnection();
|
|
3206
3269
|
});
|
|
3207
3270
|
this.locusInfo.on(LOCUSINFO.EVENTS.SELF_ADMITTED_GUEST, async (payload) => {
|
|
@@ -3225,6 +3288,9 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3225
3288
|
name: 'client.lobby.exited',
|
|
3226
3289
|
options: {meetingId: this.id},
|
|
3227
3290
|
});
|
|
3291
|
+
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.GUEST_EXITED_LOBBY, {
|
|
3292
|
+
correlation_id: this.correlationId,
|
|
3293
|
+
});
|
|
3228
3294
|
}
|
|
3229
3295
|
this.rtcMetrics?.sendNextMetrics();
|
|
3230
3296
|
this.updateLLMConnection();
|
|
@@ -3311,7 +3377,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3311
3377
|
this.simultaneousInterpretation.updateCanManageInterpreters(
|
|
3312
3378
|
payload.newRoles?.includes(SELF_ROLES.MODERATOR)
|
|
3313
3379
|
);
|
|
3314
|
-
this.webinar.
|
|
3380
|
+
this.webinar.updateRoleChanged(payload);
|
|
3315
3381
|
Trigger.trigger(
|
|
3316
3382
|
this,
|
|
3317
3383
|
{
|
|
@@ -3458,6 +3524,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3458
3524
|
emailAddress: string;
|
|
3459
3525
|
email: string;
|
|
3460
3526
|
phoneNumber: string;
|
|
3527
|
+
roles: Array<string>;
|
|
3461
3528
|
},
|
|
3462
3529
|
alertIfActive = true
|
|
3463
3530
|
) {
|
|
@@ -3714,6 +3781,10 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3714
3781
|
this.userDisplayHints,
|
|
3715
3782
|
this.selfUserPolicies
|
|
3716
3783
|
),
|
|
3784
|
+
isPremiseRecordingEnabled: RecordingUtil.isPremiseRecordingEnabled(
|
|
3785
|
+
this.userDisplayHints,
|
|
3786
|
+
this.selfUserPolicies
|
|
3787
|
+
),
|
|
3717
3788
|
canRaiseHand: MeetingUtil.canUserRaiseHand(this.userDisplayHints),
|
|
3718
3789
|
canLowerAllHands: MeetingUtil.canUserLowerAllHands(this.userDisplayHints),
|
|
3719
3790
|
canLowerSomeoneElsesHand: MeetingUtil.canUserLowerSomeoneElsesHand(this.userDisplayHints),
|
|
@@ -3805,6 +3876,22 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3805
3876
|
requiredHints: [DISPLAY_HINTS.DISABLE_VIEW_THE_PARTICIPANT_LIST],
|
|
3806
3877
|
displayHints: this.userDisplayHints,
|
|
3807
3878
|
}),
|
|
3879
|
+
canEnableViewTheParticipantsListPanelist: ControlsOptionsUtil.hasHints({
|
|
3880
|
+
requiredHints: [DISPLAY_HINTS.ENABLE_VIEW_THE_PARTICIPANT_LIST_PANELIST],
|
|
3881
|
+
displayHints: this.userDisplayHints,
|
|
3882
|
+
}),
|
|
3883
|
+
canDisableViewTheParticipantsListPanelist: ControlsOptionsUtil.hasHints({
|
|
3884
|
+
requiredHints: [DISPLAY_HINTS.DISABLE_VIEW_THE_PARTICIPANT_LIST_PANELIST],
|
|
3885
|
+
displayHints: this.userDisplayHints,
|
|
3886
|
+
}),
|
|
3887
|
+
canEnableShowAttendeeCount: ControlsOptionsUtil.hasHints({
|
|
3888
|
+
requiredHints: [DISPLAY_HINTS.ENABLE_SHOW_ATTENDEE_COUNT],
|
|
3889
|
+
displayHints: this.userDisplayHints,
|
|
3890
|
+
}),
|
|
3891
|
+
canDisableShowAttendeeCount: ControlsOptionsUtil.hasHints({
|
|
3892
|
+
requiredHints: [DISPLAY_HINTS.DISABLE_SHOW_ATTENDEE_COUNT],
|
|
3893
|
+
displayHints: this.userDisplayHints,
|
|
3894
|
+
}),
|
|
3808
3895
|
canEnableRaiseHand: ControlsOptionsUtil.hasHints({
|
|
3809
3896
|
requiredHints: [DISPLAY_HINTS.ENABLE_RAISE_HAND],
|
|
3810
3897
|
displayHints: this.userDisplayHints,
|
|
@@ -3821,6 +3908,42 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3821
3908
|
requiredHints: [DISPLAY_HINTS.DISABLE_VIDEO],
|
|
3822
3909
|
displayHints: this.userDisplayHints,
|
|
3823
3910
|
}),
|
|
3911
|
+
canStartWebcast: ControlsOptionsUtil.hasHints({
|
|
3912
|
+
requiredHints: [DISPLAY_HINTS.WEBCAST_CONTROL_START],
|
|
3913
|
+
displayHints: this.userDisplayHints,
|
|
3914
|
+
}),
|
|
3915
|
+
canStopWebcast: ControlsOptionsUtil.hasHints({
|
|
3916
|
+
requiredHints: [DISPLAY_HINTS.WEBCAST_CONTROL_STOP],
|
|
3917
|
+
displayHints: this.userDisplayHints,
|
|
3918
|
+
}),
|
|
3919
|
+
canShowStageView: ControlsOptionsUtil.hasHints({
|
|
3920
|
+
requiredHints: [DISPLAY_HINTS.STAGE_VIEW_ACTIVE],
|
|
3921
|
+
displayHints: this.userDisplayHints,
|
|
3922
|
+
}),
|
|
3923
|
+
canEnableStageView: ControlsOptionsUtil.hasHints({
|
|
3924
|
+
requiredHints: [DISPLAY_HINTS.ENABLE_STAGE_VIEW],
|
|
3925
|
+
displayHints: this.userDisplayHints,
|
|
3926
|
+
}),
|
|
3927
|
+
canDisableStageView: ControlsOptionsUtil.hasHints({
|
|
3928
|
+
requiredHints: [DISPLAY_HINTS.DISABLE_STAGE_VIEW],
|
|
3929
|
+
displayHints: this.userDisplayHints,
|
|
3930
|
+
}),
|
|
3931
|
+
isPracticeSessionOn: ControlsOptionsUtil.hasHints({
|
|
3932
|
+
requiredHints: [DISPLAY_HINTS.PRACTICE_SESSION_ON],
|
|
3933
|
+
displayHints: this.userDisplayHints,
|
|
3934
|
+
}),
|
|
3935
|
+
isPracticeSessionOff: ControlsOptionsUtil.hasHints({
|
|
3936
|
+
requiredHints: [DISPLAY_HINTS.PRACTICE_SESSION_OFF],
|
|
3937
|
+
displayHints: this.userDisplayHints,
|
|
3938
|
+
}),
|
|
3939
|
+
canStartPracticeSession: ControlsOptionsUtil.hasHints({
|
|
3940
|
+
requiredHints: [DISPLAY_HINTS.SHOW_PRACTICE_SESSION_START],
|
|
3941
|
+
displayHints: this.userDisplayHints,
|
|
3942
|
+
}),
|
|
3943
|
+
canStopPracticeSession: ControlsOptionsUtil.hasHints({
|
|
3944
|
+
requiredHints: [DISPLAY_HINTS.SHOW_PRACTICE_SESSION_STOP],
|
|
3945
|
+
displayHints: this.userDisplayHints,
|
|
3946
|
+
}),
|
|
3824
3947
|
canShareFile:
|
|
3825
3948
|
(ControlsOptionsUtil.hasHints({
|
|
3826
3949
|
requiredHints: [DISPLAY_HINTS.SHARE_FILE],
|
|
@@ -3977,6 +4100,66 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3977
4100
|
Trigger.trigger(this, options, EVENTS.REQUEST_UPLOAD_LOGS, this);
|
|
3978
4101
|
}
|
|
3979
4102
|
|
|
4103
|
+
/**
|
|
4104
|
+
* sets the timer for periodic log upload
|
|
4105
|
+
* @returns {void}
|
|
4106
|
+
*/
|
|
4107
|
+
private setLogUploadTimer() {
|
|
4108
|
+
// start with short timeouts and increase them later on so in case users have very long multi-hour meetings we don't get too fragmented logs
|
|
4109
|
+
const LOG_UPLOAD_INTERVALS = [0.1, 15, 30, 60]; // in minutes
|
|
4110
|
+
|
|
4111
|
+
const delay =
|
|
4112
|
+
1000 *
|
|
4113
|
+
60 *
|
|
4114
|
+
// @ts-ignore - config coming from registerPlugin
|
|
4115
|
+
this.config.logUploadIntervalMultiplicationFactor *
|
|
4116
|
+
LOG_UPLOAD_INTERVALS[this.logUploadIntervalIndex];
|
|
4117
|
+
|
|
4118
|
+
if (this.logUploadIntervalIndex < LOG_UPLOAD_INTERVALS.length - 1) {
|
|
4119
|
+
this.logUploadIntervalIndex += 1;
|
|
4120
|
+
}
|
|
4121
|
+
|
|
4122
|
+
this.uploadLogsTimer = safeSetTimeout(() => {
|
|
4123
|
+
this.uploadLogsTimer = undefined;
|
|
4124
|
+
|
|
4125
|
+
this.uploadLogs();
|
|
4126
|
+
|
|
4127
|
+
// just as an extra precaution, to avoid uploading logs forever in case something goes wrong
|
|
4128
|
+
// and the page remains opened, we stop it if there is no media connection
|
|
4129
|
+
if (!this.mediaProperties.webrtcMediaConnection) {
|
|
4130
|
+
return;
|
|
4131
|
+
}
|
|
4132
|
+
|
|
4133
|
+
this.setLogUploadTimer();
|
|
4134
|
+
}, delay);
|
|
4135
|
+
}
|
|
4136
|
+
|
|
4137
|
+
/**
|
|
4138
|
+
* Starts a periodic upload of logs
|
|
4139
|
+
*
|
|
4140
|
+
* @returns {undefined}
|
|
4141
|
+
*/
|
|
4142
|
+
public startPeriodicLogUpload() {
|
|
4143
|
+
// @ts-ignore - config coming from registerPlugin
|
|
4144
|
+
if (this.config.logUploadIntervalMultiplicationFactor && !this.uploadLogsTimer) {
|
|
4145
|
+
this.logUploadIntervalIndex = 0;
|
|
4146
|
+
|
|
4147
|
+
this.setLogUploadTimer();
|
|
4148
|
+
}
|
|
4149
|
+
}
|
|
4150
|
+
|
|
4151
|
+
/**
|
|
4152
|
+
* Stops the periodic upload of logs
|
|
4153
|
+
*
|
|
4154
|
+
* @returns {undefined}
|
|
4155
|
+
*/
|
|
4156
|
+
public stopPeriodicLogUpload() {
|
|
4157
|
+
if (this.uploadLogsTimer) {
|
|
4158
|
+
clearTimeout(this.uploadLogsTimer);
|
|
4159
|
+
this.uploadLogsTimer = undefined;
|
|
4160
|
+
}
|
|
4161
|
+
}
|
|
4162
|
+
|
|
3980
4163
|
/**
|
|
3981
4164
|
* Removes remote audio, video and share streams from class instance's mediaProperties
|
|
3982
4165
|
* @returns {undefined}
|
|
@@ -4688,8 +4871,6 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4688
4871
|
if (!joinResponse) {
|
|
4689
4872
|
// This is the 1st attempt or a retry after join request failed -> we need to do a join with TURN discovery
|
|
4690
4873
|
|
|
4691
|
-
// @ts-ignore
|
|
4692
|
-
joinOptions.reachability = await this.webex.meetings.reachability.getReachabilityResults();
|
|
4693
4874
|
const turnDiscoveryRequest = await this.roap.generateTurnDiscoveryRequestMessage(
|
|
4694
4875
|
this,
|
|
4695
4876
|
true
|
|
@@ -4821,6 +5002,8 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4821
5002
|
);
|
|
4822
5003
|
}
|
|
4823
5004
|
|
|
5005
|
+
this.cleanUpBeforeReconnection();
|
|
5006
|
+
|
|
4824
5007
|
return this.reconnectionManager
|
|
4825
5008
|
.reconnect(options, async () => {
|
|
4826
5009
|
await this.waitForRemoteSDPAnswer();
|
|
@@ -5198,16 +5381,19 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5198
5381
|
this.meetingFiniteStateMachine.reset();
|
|
5199
5382
|
}
|
|
5200
5383
|
|
|
5201
|
-
//
|
|
5202
|
-
|
|
5203
|
-
|
|
5204
|
-
|
|
5205
|
-
|
|
5206
|
-
|
|
5207
|
-
|
|
5208
|
-
|
|
5209
|
-
|
|
5210
|
-
|
|
5384
|
+
// send client.call.initiated unless told not to
|
|
5385
|
+
if (options.sendCallInitiated !== false) {
|
|
5386
|
+
// @ts-ignore
|
|
5387
|
+
this.webex.internal.newMetrics.submitClientEvent({
|
|
5388
|
+
name: 'client.call.initiated',
|
|
5389
|
+
payload: {
|
|
5390
|
+
trigger: this.callStateForMetrics.joinTrigger || 'user-interaction',
|
|
5391
|
+
isRoapCallEnabled: true,
|
|
5392
|
+
pstnAudioType: options?.pstnAudioType,
|
|
5393
|
+
},
|
|
5394
|
+
options: {meetingId: this.id},
|
|
5395
|
+
});
|
|
5396
|
+
}
|
|
5211
5397
|
|
|
5212
5398
|
LoggerProxy.logger.log('Meeting:index#join --> Joining a meeting');
|
|
5213
5399
|
|
|
@@ -6238,7 +6424,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
6238
6424
|
this.mediaProperties.webrtcMediaConnection.on(
|
|
6239
6425
|
MediaConnectionEventNames.ICE_CANDIDATE,
|
|
6240
6426
|
(event) => {
|
|
6241
|
-
if (event.candidate) {
|
|
6427
|
+
if (event.candidate && event.candidate.candidate && event.candidate.candidate.length > 0) {
|
|
6242
6428
|
this.iceCandidatesCount += 1;
|
|
6243
6429
|
}
|
|
6244
6430
|
}
|
|
@@ -6949,6 +7135,23 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
6949
7135
|
}
|
|
6950
7136
|
}
|
|
6951
7137
|
|
|
7138
|
+
private async cleanUpBeforeReconnection(): Promise<void> {
|
|
7139
|
+
try {
|
|
7140
|
+
// when media fails, we want to upload a webrtc dump to see whats going on
|
|
7141
|
+
// this function is async, but returns once the stats have been gathered
|
|
7142
|
+
await this.forceSendStatsReport({callFrom: 'cleanUpBeforeReconnection'});
|
|
7143
|
+
|
|
7144
|
+
if (this.statsAnalyzer) {
|
|
7145
|
+
await this.statsAnalyzer.stopAnalyzer();
|
|
7146
|
+
}
|
|
7147
|
+
} catch (error) {
|
|
7148
|
+
LoggerProxy.logger.error(
|
|
7149
|
+
'Meeting:index#cleanUpBeforeReconnection --> Error during cleanup: ',
|
|
7150
|
+
error
|
|
7151
|
+
);
|
|
7152
|
+
}
|
|
7153
|
+
}
|
|
7154
|
+
|
|
6952
7155
|
/**
|
|
6953
7156
|
* Creates an instance of LocusMediaRequest for this meeting - it is needed for doing any calls
|
|
6954
7157
|
* to Locus /media API (these are used for sending Roap messages and updating audio/video mute status).
|
|
@@ -7040,7 +7243,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
7040
7243
|
shareAudioEnabled = true,
|
|
7041
7244
|
shareVideoEnabled = true,
|
|
7042
7245
|
remoteMediaManagerConfig,
|
|
7043
|
-
bundlePolicy,
|
|
7246
|
+
bundlePolicy = 'max-bundle',
|
|
7044
7247
|
} = options;
|
|
7045
7248
|
|
|
7046
7249
|
this.allowMediaInLobby = options?.allowMediaInLobby;
|
|
@@ -7145,6 +7348,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
7145
7348
|
|
|
7146
7349
|
// We can log ReceiveSlot SSRCs only after the SDP exchange, so doing it here:
|
|
7147
7350
|
this.remoteMediaManager?.logAllReceiveSlots();
|
|
7351
|
+
this.startPeriodicLogUpload();
|
|
7148
7352
|
} catch (error) {
|
|
7149
7353
|
LoggerProxy.logger.error(`${LOG_HEADER} failed to establish media connection: `, error);
|
|
7150
7354
|
|
|
@@ -7927,18 +8131,21 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
7927
8131
|
* @param {boolean} mutedEnabled
|
|
7928
8132
|
* @param {boolean} disallowUnmuteEnabled
|
|
7929
8133
|
* @param {boolean} muteOnEntryEnabled
|
|
8134
|
+
* @param {array} roles
|
|
7930
8135
|
* @public
|
|
7931
8136
|
* @memberof Meeting
|
|
7932
8137
|
*/
|
|
7933
8138
|
public setMuteAll(
|
|
7934
8139
|
mutedEnabled: boolean,
|
|
7935
8140
|
disallowUnmuteEnabled: boolean,
|
|
7936
|
-
muteOnEntryEnabled: boolean
|
|
8141
|
+
muteOnEntryEnabled: boolean,
|
|
8142
|
+
roles: Array<string>
|
|
7937
8143
|
) {
|
|
7938
8144
|
return this.controlsOptionsManager.setMuteAll(
|
|
7939
8145
|
mutedEnabled,
|
|
7940
8146
|
disallowUnmuteEnabled,
|
|
7941
|
-
muteOnEntryEnabled
|
|
8147
|
+
muteOnEntryEnabled,
|
|
8148
|
+
roles
|
|
7942
8149
|
);
|
|
7943
8150
|
}
|
|
7944
8151
|
|
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
import {defer} from 'lodash';
|
|
3
3
|
import {Defer} from '@webex/common';
|
|
4
4
|
import {WebexPlugin} from '@webex/webex-core';
|
|
5
|
-
import {MEDIA, HTTP_VERBS, ROAP
|
|
5
|
+
import {MEDIA, HTTP_VERBS, ROAP} from '../constants';
|
|
6
6
|
import LoggerProxy from '../common/logs/logger-proxy';
|
|
7
|
+
import {ClientMediaPreferences} from '../reachability/reachability.types';
|
|
7
8
|
|
|
8
9
|
export type MediaRequestType = 'RoapMessage' | 'LocalMute';
|
|
9
10
|
export type RequestResult = any;
|
|
@@ -14,9 +15,8 @@ export type RoapRequest = {
|
|
|
14
15
|
mediaId: string;
|
|
15
16
|
roapMessage: any;
|
|
16
17
|
reachability: any;
|
|
18
|
+
clientMediaPreferences: ClientMediaPreferences;
|
|
17
19
|
sequence?: any;
|
|
18
|
-
joinCookie: any; // any, because this is opaque to the client, we pass whatever object we got from one backend component (Orpheus) to the other (Locus)
|
|
19
|
-
ipVersion?: IP_VERSION;
|
|
20
20
|
};
|
|
21
21
|
|
|
22
22
|
export type LocalMuteRequest = {
|
|
@@ -202,10 +202,6 @@ export class LocusMediaRequest extends WebexPlugin {
|
|
|
202
202
|
const body: any = {
|
|
203
203
|
device: this.config.device,
|
|
204
204
|
correlationId: this.config.correlationId,
|
|
205
|
-
clientMediaPreferences: {
|
|
206
|
-
preferTranscoding: this.config.preferTranscoding,
|
|
207
|
-
ipver: request.type === 'RoapMessage' ? request.ipVersion : undefined,
|
|
208
|
-
},
|
|
209
205
|
};
|
|
210
206
|
|
|
211
207
|
const localMedias: any = {
|
|
@@ -223,7 +219,7 @@ export class LocusMediaRequest extends WebexPlugin {
|
|
|
223
219
|
case 'RoapMessage':
|
|
224
220
|
localMedias.roapMessage = request.roapMessage;
|
|
225
221
|
localMedias.reachability = request.reachability;
|
|
226
|
-
body.clientMediaPreferences
|
|
222
|
+
body.clientMediaPreferences = request.clientMediaPreferences;
|
|
227
223
|
|
|
228
224
|
// @ts-ignore
|
|
229
225
|
this.webex.internal.newMetrics.submitClientEvent({
|
package/src/meeting/request.ts
CHANGED
|
@@ -26,11 +26,11 @@ import {
|
|
|
26
26
|
SEND_DTMF_ENDPOINT,
|
|
27
27
|
_SLIDES_,
|
|
28
28
|
ANNOTATION,
|
|
29
|
-
IP_VERSION,
|
|
30
29
|
} from '../constants';
|
|
31
30
|
import {SendReactionOptions, ToggleReactionsOptions} from './request.type';
|
|
32
31
|
import MeetingUtil from './util';
|
|
33
32
|
import {AnnotationInfo} from '../annotation/annotation.types';
|
|
33
|
+
import {ClientMediaPreferences} from '../reachability/reachability.types';
|
|
34
34
|
|
|
35
35
|
/**
|
|
36
36
|
* @class MeetingRequest
|
|
@@ -128,8 +128,8 @@ export default class MeetingRequest extends StatelessWebexPlugin {
|
|
|
128
128
|
locale?: string;
|
|
129
129
|
deviceCapabilities?: Array<string>;
|
|
130
130
|
liveAnnotationSupported: boolean;
|
|
131
|
-
ipVersion?: IP_VERSION;
|
|
132
131
|
alias?: string;
|
|
132
|
+
clientMediaPreferences: ClientMediaPreferences;
|
|
133
133
|
}) {
|
|
134
134
|
const {
|
|
135
135
|
asResourceOccupant,
|
|
@@ -147,12 +147,11 @@ export default class MeetingRequest extends StatelessWebexPlugin {
|
|
|
147
147
|
moveToResource,
|
|
148
148
|
roapMessage,
|
|
149
149
|
reachability,
|
|
150
|
-
preferTranscoding,
|
|
151
150
|
breakoutsSupported,
|
|
152
151
|
locale,
|
|
153
152
|
deviceCapabilities = [],
|
|
154
153
|
liveAnnotationSupported,
|
|
155
|
-
|
|
154
|
+
clientMediaPreferences,
|
|
156
155
|
alias,
|
|
157
156
|
} = options;
|
|
158
157
|
|
|
@@ -160,8 +159,6 @@ export default class MeetingRequest extends StatelessWebexPlugin {
|
|
|
160
159
|
|
|
161
160
|
let url = '';
|
|
162
161
|
|
|
163
|
-
const joinCookie = await this.getJoinCookie();
|
|
164
|
-
|
|
165
162
|
const body: any = {
|
|
166
163
|
asResourceOccupant,
|
|
167
164
|
device: {
|
|
@@ -176,11 +173,7 @@ export default class MeetingRequest extends StatelessWebexPlugin {
|
|
|
176
173
|
allowMultiDevice: true,
|
|
177
174
|
ensureConversation: ensureConversation || false,
|
|
178
175
|
supportsNativeLobby: 1,
|
|
179
|
-
clientMediaPreferences
|
|
180
|
-
preferTranscoding: preferTranscoding ?? true,
|
|
181
|
-
joinCookie,
|
|
182
|
-
ipver: ipVersion,
|
|
183
|
-
},
|
|
176
|
+
clientMediaPreferences,
|
|
184
177
|
};
|
|
185
178
|
|
|
186
179
|
if (alias) {
|
package/src/meeting/util.ts
CHANGED
|
@@ -115,7 +115,7 @@ const MeetingUtil = {
|
|
|
115
115
|
return IP_VERSION.unknown;
|
|
116
116
|
},
|
|
117
117
|
|
|
118
|
-
joinMeeting: (meeting, options) => {
|
|
118
|
+
joinMeeting: async (meeting, options) => {
|
|
119
119
|
if (!meeting) {
|
|
120
120
|
return Promise.reject(new ParameterError('You need a meeting object.'));
|
|
121
121
|
}
|
|
@@ -127,6 +127,27 @@ const MeetingUtil = {
|
|
|
127
127
|
options: {meetingId: meeting.id},
|
|
128
128
|
});
|
|
129
129
|
|
|
130
|
+
let reachability;
|
|
131
|
+
let clientMediaPreferences = {
|
|
132
|
+
// bare minimum fallback value that should allow us to join
|
|
133
|
+
ipver: IP_VERSION.unknown,
|
|
134
|
+
joinCookie: undefined,
|
|
135
|
+
preferTranscoding: !meeting.isMultistream,
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
try {
|
|
139
|
+
clientMediaPreferences = await webex.meetings.reachability.getClientMediaPreferences(
|
|
140
|
+
meeting.isMultistream,
|
|
141
|
+
MeetingUtil.getIpVersion(webex)
|
|
142
|
+
);
|
|
143
|
+
reachability = await webex.meetings.reachability.getReachabilityReportToAttachToRoap();
|
|
144
|
+
} catch (e) {
|
|
145
|
+
LoggerProxy.logger.error(
|
|
146
|
+
'Meeting:util#joinMeeting --> Error getting reachability or clientMediaPreferences:',
|
|
147
|
+
e
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
|
|
130
151
|
// eslint-disable-next-line no-warning-comments
|
|
131
152
|
// TODO: check if the meeting is in JOINING state
|
|
132
153
|
// if Joining state termintate the request as user might click multiple times
|
|
@@ -138,20 +159,19 @@ const MeetingUtil = {
|
|
|
138
159
|
locusUrl: meeting.locusUrl,
|
|
139
160
|
locusClusterUrl: meeting.meetingInfo?.locusClusterUrl,
|
|
140
161
|
correlationId: meeting.correlationId,
|
|
141
|
-
reachability
|
|
162
|
+
reachability,
|
|
142
163
|
roapMessage: options.roapMessage,
|
|
143
164
|
permissionToken: meeting.permissionToken,
|
|
144
165
|
resourceId: options.resourceId || null,
|
|
145
166
|
moderator: options.moderator,
|
|
146
167
|
pin: options.pin,
|
|
147
168
|
moveToResource: options.moveToResource,
|
|
148
|
-
preferTranscoding: !meeting.isMultistream,
|
|
149
169
|
asResourceOccupant: options.asResourceOccupant,
|
|
150
170
|
breakoutsSupported: options.breakoutsSupported,
|
|
151
171
|
locale: options.locale,
|
|
152
172
|
deviceCapabilities: options.deviceCapabilities,
|
|
153
173
|
liveAnnotationSupported: options.liveAnnotationSupported,
|
|
154
|
-
|
|
174
|
+
clientMediaPreferences,
|
|
155
175
|
})
|
|
156
176
|
.then((res) => {
|
|
157
177
|
const parsed = MeetingUtil.parseLocusJoin(res);
|
|
@@ -177,6 +197,7 @@ const MeetingUtil = {
|
|
|
177
197
|
|
|
178
198
|
cleanUp: (meeting) => {
|
|
179
199
|
meeting.getWebexObject().internal.device.meetingEnded();
|
|
200
|
+
meeting.stopPeriodicLogUpload();
|
|
180
201
|
|
|
181
202
|
meeting.breakouts.cleanUp();
|
|
182
203
|
meeting.simultaneousInterpretation.cleanUp();
|