@webex/plugin-meetings 3.7.0-wxcc.1 → 3.8.0
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/annotation/annotation.types.d.ts +42 -0
- package/dist/annotation/constants.d.ts +31 -0
- package/dist/annotation/index.d.ts +117 -0
- package/dist/breakouts/breakout.d.ts +8 -0
- package/dist/breakouts/breakout.js +1 -1
- package/dist/breakouts/collection.d.ts +5 -0
- package/dist/breakouts/edit-lock-error.d.ts +15 -0
- package/dist/breakouts/events.d.ts +8 -0
- package/dist/breakouts/index.d.ts +5 -0
- package/dist/breakouts/index.js +1 -1
- package/dist/breakouts/request.d.ts +22 -0
- package/dist/breakouts/utils.d.ts +15 -0
- package/dist/common/browser-detection.d.ts +9 -0
- package/dist/common/collection.d.ts +48 -0
- package/dist/common/config.d.ts +2 -0
- package/dist/common/errors/captcha-error.d.ts +15 -0
- package/dist/common/errors/intent-to-join.d.ts +16 -0
- package/dist/common/errors/join-meeting.d.ts +17 -0
- package/dist/common/errors/media.d.ts +15 -0
- package/dist/common/errors/no-meeting-info.d.ts +14 -0
- package/dist/common/errors/parameter.d.ts +15 -0
- package/dist/common/errors/password-error.d.ts +15 -0
- package/dist/common/errors/permission.d.ts +14 -0
- package/dist/common/errors/reclaim-host-role-error.js +149 -0
- package/dist/common/errors/reclaim-host-role-error.js.map +1 -0
- package/dist/common/errors/reclaim-host-role-errors.d.ts +60 -0
- package/dist/common/errors/reconnection-in-progress.d.ts +9 -0
- package/dist/common/errors/reconnection-in-progress.js +33 -0
- package/dist/common/errors/reconnection-in-progress.js.map +1 -0
- package/dist/common/errors/reconnection.d.ts +15 -0
- package/dist/common/errors/stats.d.ts +15 -0
- package/dist/common/errors/webex-errors.d.ts +93 -0
- package/dist/common/errors/webex-meetings-error.d.ts +20 -0
- package/dist/common/events/events-scope.d.ts +17 -0
- package/dist/common/events/events.d.ts +12 -0
- package/dist/common/events/trigger-proxy.d.ts +2 -0
- package/dist/common/events/util.d.ts +2 -0
- package/dist/common/logs/logger-config.d.ts +2 -0
- package/dist/common/logs/logger-proxy.d.ts +2 -0
- package/dist/common/logs/request.d.ts +36 -0
- package/dist/common/queue.d.ts +34 -0
- package/dist/config.d.ts +72 -0
- package/dist/constants.d.ts +1088 -0
- package/dist/constants.js +15 -3
- package/dist/constants.js.map +1 -1
- package/dist/controls-options-manager/constants.d.ts +4 -0
- package/dist/controls-options-manager/enums.d.ts +15 -0
- package/dist/controls-options-manager/index.d.ts +136 -0
- package/dist/controls-options-manager/types.d.ts +43 -0
- package/dist/controls-options-manager/util.d.ts +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/interceptors/index.d.ts +2 -0
- package/dist/interceptors/locusRetry.d.ts +27 -0
- package/dist/interpretation/collection.d.ts +5 -0
- package/dist/interpretation/index.d.ts +5 -0
- package/dist/interpretation/index.js +1 -1
- package/dist/interpretation/siLanguage.d.ts +5 -0
- package/dist/interpretation/siLanguage.js +1 -1
- package/dist/locus-info/controlsUtils.d.ts +2 -0
- package/dist/locus-info/embeddedAppsUtils.d.ts +2 -0
- package/dist/locus-info/fullState.d.ts +2 -0
- package/dist/locus-info/hostUtils.d.ts +2 -0
- package/dist/locus-info/index.d.ts +322 -0
- package/dist/locus-info/infoUtils.d.ts +2 -0
- package/dist/locus-info/mediaSharesUtils.d.ts +2 -0
- package/dist/locus-info/parser.d.ts +272 -0
- package/dist/locus-info/selfUtils.d.ts +2 -0
- package/dist/locus-info/selfUtils.js +5 -0
- package/dist/locus-info/selfUtils.js.map +1 -1
- package/dist/media/MediaConnectionAwaiter.js +1 -0
- package/dist/media/MediaConnectionAwaiter.js.map +1 -1
- package/dist/media/index.d.ts +34 -0
- package/dist/media/properties.d.ts +93 -0
- package/dist/media/properties.js +30 -16
- package/dist/media/properties.js.map +1 -1
- package/dist/media/util.d.ts +2 -0
- package/dist/mediaQualityMetrics/config.d.ts +241 -0
- package/dist/mediaQualityMetrics/config.js +502 -0
- package/dist/mediaQualityMetrics/config.js.map +1 -0
- package/dist/meeting/brbState.js +167 -0
- package/dist/meeting/brbState.js.map +1 -0
- package/dist/meeting/effectsState.js +260 -0
- package/dist/meeting/effectsState.js.map +1 -0
- package/dist/meeting/in-meeting-actions.d.ts +167 -0
- package/dist/meeting/index.d.ts +1825 -0
- package/dist/meeting/index.js +363 -295
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/locusMediaRequest.d.ts +74 -0
- package/dist/meeting/muteState.d.ts +178 -0
- package/dist/meeting/muteState.js +1 -6
- package/dist/meeting/muteState.js.map +1 -1
- package/dist/meeting/request.d.ts +295 -0
- package/dist/meeting/request.type.d.ts +11 -0
- package/dist/meeting/state.d.ts +9 -0
- package/dist/meeting/util.d.ts +119 -0
- package/dist/meeting/voicea-meeting.d.ts +16 -0
- package/dist/meeting-info/collection.d.ts +20 -0
- package/dist/meeting-info/index.d.ts +69 -0
- package/dist/meeting-info/meeting-info-v2.d.ts +123 -0
- package/dist/meeting-info/meeting-info-v2.js +19 -12
- package/dist/meeting-info/meeting-info-v2.js.map +1 -1
- package/dist/meeting-info/request.d.ts +22 -0
- package/dist/meeting-info/util.d.ts +2 -0
- package/dist/meeting-info/utilv2.d.ts +2 -0
- package/dist/meeting-info/utilv2.js +5 -1
- package/dist/meeting-info/utilv2.js.map +1 -1
- package/dist/meetings/collection.d.ts +40 -0
- package/dist/meetings/index.d.ts +390 -0
- package/dist/meetings/meetings.types.d.ts +4 -0
- package/dist/meetings/request.d.ts +27 -0
- package/dist/meetings/util.d.ts +18 -0
- package/dist/member/index.d.ts +160 -0
- package/dist/member/member.types.js +17 -0
- package/dist/member/member.types.js.map +1 -0
- package/dist/member/types.d.ts +32 -0
- package/dist/member/util.d.ts +2 -0
- package/dist/members/collection.d.ts +29 -0
- package/dist/members/index.d.ts +353 -0
- package/dist/members/request.d.ts +114 -0
- package/dist/members/types.d.ts +25 -0
- package/dist/members/util.d.ts +215 -0
- package/dist/metrics/config.js +276 -0
- package/dist/metrics/config.js.map +1 -0
- package/dist/metrics/constants.d.ts +70 -0
- package/dist/metrics/constants.js +2 -0
- package/dist/metrics/constants.js.map +1 -1
- package/dist/metrics/index.d.ts +45 -0
- package/dist/multistream/mediaRequestManager.d.ts +119 -0
- package/dist/multistream/receiveSlot.d.ts +68 -0
- package/dist/multistream/receiveSlotManager.d.ts +56 -0
- package/dist/multistream/remoteMedia.d.ts +72 -0
- package/dist/multistream/remoteMediaGroup.d.ts +49 -0
- package/dist/multistream/remoteMediaManager.d.ts +300 -0
- package/dist/multistream/sendSlotManager.d.ts +69 -0
- package/dist/networkQualityMonitor/index.d.ts +70 -0
- package/dist/networkQualityMonitor/index.js +221 -0
- package/dist/networkQualityMonitor/index.js.map +1 -0
- package/dist/peer-connection-manager/index.js +671 -0
- package/dist/peer-connection-manager/index.js.map +1 -0
- package/dist/peer-connection-manager/util.js +109 -0
- package/dist/peer-connection-manager/util.js.map +1 -0
- package/dist/personal-meeting-room/index.d.ts +47 -0
- package/dist/personal-meeting-room/request.d.ts +14 -0
- package/dist/personal-meeting-room/util.d.ts +2 -0
- package/dist/reachability/clusterReachability.d.ts +109 -0
- package/dist/reachability/index.d.ts +105 -0
- package/dist/reachability/index.js +31 -3
- package/dist/reachability/index.js.map +1 -1
- package/dist/reachability/request.d.ts +39 -0
- package/dist/reachability/util.d.ts +8 -0
- package/dist/reactions/constants.d.ts +3 -0
- package/dist/reactions/reactions.d.ts +4 -0
- package/dist/reactions/reactions.type.d.ts +52 -0
- package/dist/reconnection-manager/index.d.ts +136 -0
- package/dist/recording-controller/enums.d.ts +7 -0
- package/dist/recording-controller/index.d.ts +207 -0
- package/dist/recording-controller/util.d.ts +14 -0
- package/dist/roap/collection.js +62 -0
- package/dist/roap/collection.js.map +1 -0
- package/dist/roap/handler.js +275 -0
- package/dist/roap/handler.js.map +1 -0
- package/dist/roap/index.d.ts +86 -0
- package/dist/roap/request.d.ts +39 -0
- package/dist/roap/state.js +126 -0
- package/dist/roap/state.js.map +1 -0
- package/dist/roap/turnDiscovery.d.ts +155 -0
- package/dist/roap/util.js +75 -0
- package/dist/roap/util.js.map +1 -0
- package/dist/rtcMetrics/constants.d.ts +4 -0
- package/dist/rtcMetrics/constants.js +11 -0
- package/dist/rtcMetrics/constants.js.map +1 -0
- package/dist/rtcMetrics/index.d.ts +61 -0
- package/dist/rtcMetrics/index.js +197 -0
- package/dist/rtcMetrics/index.js.map +1 -0
- package/dist/statsAnalyzer/global.d.ts +36 -0
- package/dist/statsAnalyzer/global.js +126 -0
- package/dist/statsAnalyzer/global.js.map +1 -0
- package/dist/statsAnalyzer/index.d.ts +217 -0
- package/dist/statsAnalyzer/index.js +1013 -0
- package/dist/statsAnalyzer/index.js.map +1 -0
- package/dist/statsAnalyzer/mqaUtil.d.ts +48 -0
- package/dist/statsAnalyzer/mqaUtil.js +179 -0
- package/dist/statsAnalyzer/mqaUtil.js.map +1 -0
- package/dist/transcription/index.d.ts +64 -0
- package/dist/types/common/errors/reconnection-in-progress.d.ts +9 -0
- package/dist/types/constants.d.ts +9 -2
- package/dist/types/mediaQualityMetrics/config.d.ts +241 -0
- package/dist/types/meeting/brbState.d.ts +54 -0
- package/dist/types/meeting/index.d.ts +23 -0
- package/dist/types/meeting-info/meeting-info-v2.d.ts +3 -1
- package/dist/types/metrics/constants.d.ts +2 -0
- package/dist/types/networkQualityMonitor/index.d.ts +70 -0
- package/dist/types/reachability/index.d.ts +9 -1
- package/dist/types/rtcMetrics/constants.d.ts +4 -0
- package/dist/types/rtcMetrics/index.d.ts +71 -0
- package/dist/types/statsAnalyzer/global.d.ts +36 -0
- package/dist/types/statsAnalyzer/index.d.ts +217 -0
- package/dist/types/statsAnalyzer/mqaUtil.d.ts +48 -0
- package/dist/webinar/collection.d.ts +16 -0
- package/dist/webinar/index.d.ts +5 -0
- package/dist/webinar/index.js +1 -1
- package/package.json +23 -23
- package/src/constants.ts +10 -2
- package/src/locus-info/selfUtils.ts +5 -0
- package/src/media/MediaConnectionAwaiter.ts +2 -0
- package/src/media/properties.ts +34 -13
- package/src/meeting/brbState.ts +169 -0
- package/src/meeting/index.ts +112 -26
- package/src/meeting/muteState.ts +1 -6
- package/src/meeting-info/meeting-info-v2.ts +9 -1
- package/src/meeting-info/utilv2.ts +14 -2
- package/src/metrics/constants.ts +2 -0
- package/src/reachability/index.ts +29 -1
- package/test/unit/spec/locus-info/selfUtils.js +10 -0
- package/test/unit/spec/media/properties.ts +15 -0
- package/test/unit/spec/meeting/brbState.ts +114 -0
- package/test/unit/spec/meeting/index.js +92 -30
- package/test/unit/spec/meeting/muteState.js +0 -24
- package/test/unit/spec/meeting-info/utilv2.js +9 -0
- package/test/unit/spec/reachability/index.ts +120 -10
package/src/meeting/index.ts
CHANGED
@@ -122,8 +122,9 @@ import {
|
|
122
122
|
ROAP_OFFER_ANSWER_EXCHANGE_TIMEOUT,
|
123
123
|
NAMED_MEDIA_GROUP_TYPE_AUDIO,
|
124
124
|
WEBINAR_ERROR_WEBCAST,
|
125
|
-
|
125
|
+
WEBINAR_ERROR_REGISTRATION_ID,
|
126
126
|
JOIN_BEFORE_HOST,
|
127
|
+
REGISTRATION_ID_STATUS,
|
127
128
|
} from '../constants';
|
128
129
|
import BEHAVIORAL_METRICS from '../metrics/constants';
|
129
130
|
import ParameterError from '../common/errors/parameter';
|
@@ -163,6 +164,7 @@ import {LocusMediaRequest} from './locusMediaRequest';
|
|
163
164
|
import {ConnectionStateHandler, ConnectionStateEvent} from './connectionStateHandler';
|
164
165
|
import JoinWebinarError from '../common/errors/join-webinar-error';
|
165
166
|
import Member from '../member';
|
167
|
+
import {BrbState, createBrbState} from './brbState';
|
166
168
|
import MultistreamNotSupportedError from '../common/errors/multistream-not-supported-error';
|
167
169
|
import JoinForbiddenError from '../common/errors/join-forbidden-error';
|
168
170
|
|
@@ -255,6 +257,7 @@ export enum ScreenShareFloorStatus {
|
|
255
257
|
|
256
258
|
type FetchMeetingInfoParams = {
|
257
259
|
password?: string;
|
260
|
+
registrationId?: string;
|
258
261
|
captchaCode?: string;
|
259
262
|
extraParams?: Record<string, any>;
|
260
263
|
sendCAevents?: boolean;
|
@@ -649,6 +652,8 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
649
652
|
turnServerUsed: boolean;
|
650
653
|
areVoiceaEventsSetup = false;
|
651
654
|
isMoveToInProgress = false;
|
655
|
+
registrationIdStatus: string;
|
656
|
+
brbState: BrbState;
|
652
657
|
|
653
658
|
voiceaListenerCallbacks: object = {
|
654
659
|
[VOICEAEVENTS.VOICEA_ANNOUNCEMENT]: (payload: Transcription['languageOptions']) => {
|
@@ -1345,6 +1350,16 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
1345
1350
|
*/
|
1346
1351
|
this.passwordStatus = PASSWORD_STATUS.UNKNOWN;
|
1347
1352
|
|
1353
|
+
/**
|
1354
|
+
* registrationId status. If it's REGISTRATIONID_STATUS.REQUIRED then verifyRegistrationId() needs to be called
|
1355
|
+
* with the correct registrationId before calling join()
|
1356
|
+
* @instance
|
1357
|
+
* @type {REGISTRATION_ID_STATUS}
|
1358
|
+
* @public
|
1359
|
+
* @memberof Meeting
|
1360
|
+
*/
|
1361
|
+
this.registrationIdStatus = REGISTRATION_ID_STATUS.UNKNOWN;
|
1362
|
+
|
1348
1363
|
/**
|
1349
1364
|
* Information about required captcha. If null, then no captcha is required. status. If it's PASSWORD_STATUS.REQUIRED then verifyPassword() needs to be called
|
1350
1365
|
* with the correct password before calling join()
|
@@ -1657,6 +1672,15 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
1657
1672
|
this.passwordStatus = PASSWORD_STATUS.NOT_REQUIRED;
|
1658
1673
|
}
|
1659
1674
|
|
1675
|
+
if (
|
1676
|
+
this.registrationIdStatus === REGISTRATION_ID_STATUS.REQUIRED ||
|
1677
|
+
this.registrationIdStatus === REGISTRATION_ID_STATUS.VERIFIED
|
1678
|
+
) {
|
1679
|
+
this.registrationIdStatus = REGISTRATION_ID_STATUS.VERIFIED;
|
1680
|
+
} else {
|
1681
|
+
this.registrationIdStatus = REGISTRATION_ID_STATUS.NOT_REQUIRED;
|
1682
|
+
}
|
1683
|
+
|
1660
1684
|
Trigger.trigger(
|
1661
1685
|
this,
|
1662
1686
|
{
|
@@ -1700,7 +1724,12 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
1700
1724
|
* @private
|
1701
1725
|
*/
|
1702
1726
|
private prepForFetchMeetingInfo(
|
1703
|
-
{
|
1727
|
+
{
|
1728
|
+
password = null,
|
1729
|
+
registrationId = null,
|
1730
|
+
captchaCode = null,
|
1731
|
+
extraParams = {},
|
1732
|
+
}: FetchMeetingInfoParams,
|
1704
1733
|
caller: string
|
1705
1734
|
): Promise<void> {
|
1706
1735
|
// when fetch meeting info is called directly by the client, we want to clear out the random timer for sdk to do it
|
@@ -1740,6 +1769,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
1740
1769
|
captchaCode = null,
|
1741
1770
|
extraParams = {},
|
1742
1771
|
sendCAevents = false,
|
1772
|
+
registrationId = null,
|
1743
1773
|
}): Promise<void> {
|
1744
1774
|
try {
|
1745
1775
|
const captchaInfo = captchaCode
|
@@ -1755,7 +1785,8 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
1755
1785
|
this.config.installedOrgID,
|
1756
1786
|
this.locusId,
|
1757
1787
|
extraParams,
|
1758
|
-
{meetingId: this.id, sendCAevents}
|
1788
|
+
{meetingId: this.id, sendCAevents},
|
1789
|
+
registrationId
|
1759
1790
|
);
|
1760
1791
|
|
1761
1792
|
this.parseMeetingInfo(info?.body, this.destination, info?.errors);
|
@@ -1777,14 +1808,15 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
1777
1808
|
this.meetingInfoFailureReason = MEETING_INFO_FAILURE_REASON.WEBINAR_REGISTRATION;
|
1778
1809
|
if (WEBINAR_ERROR_WEBCAST.includes(err.wbxAppApiCode)) {
|
1779
1810
|
this.meetingInfoFailureReason = MEETING_INFO_FAILURE_REASON.NEED_JOIN_WITH_WEBCAST;
|
1780
|
-
} else if (
|
1781
|
-
this.meetingInfoFailureReason = MEETING_INFO_FAILURE_REASON.
|
1811
|
+
} else if (WEBINAR_ERROR_REGISTRATION_ID.includes(err.wbxAppApiCode)) {
|
1812
|
+
this.meetingInfoFailureReason = MEETING_INFO_FAILURE_REASON.WEBINAR_NEED_REGISTRATION_ID;
|
1782
1813
|
}
|
1783
1814
|
this.meetingInfoFailureCode = err.wbxAppApiCode;
|
1784
1815
|
|
1785
1816
|
if (err.meetingInfo) {
|
1786
1817
|
this.meetingInfo = err.meetingInfo;
|
1787
1818
|
}
|
1819
|
+
this.requiredCaptcha = null;
|
1788
1820
|
|
1789
1821
|
throw new JoinWebinarError();
|
1790
1822
|
} else if (err instanceof MeetingInfoV2JoinForbiddenError) {
|
@@ -1829,9 +1861,13 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
1829
1861
|
`Meeting:index#fetchMeetingInfo --> Info Unable to fetch meeting info for ${this.destination} - captcha required (code=${err?.body?.code}).`
|
1830
1862
|
);
|
1831
1863
|
|
1832
|
-
|
1833
|
-
|
1834
|
-
|
1864
|
+
if (this.requiredCaptcha) {
|
1865
|
+
this.meetingInfoFailureReason = MEETING_INFO_FAILURE_REASON.WRONG_CAPTCHA;
|
1866
|
+
} else if (err.isRegistrationIdRequired) {
|
1867
|
+
this.meetingInfoFailureReason = MEETING_INFO_FAILURE_REASON.WRONG_REGISTRATION_ID;
|
1868
|
+
} else {
|
1869
|
+
this.meetingInfoFailureReason = MEETING_INFO_FAILURE_REASON.WRONG_PASSWORD;
|
1870
|
+
}
|
1835
1871
|
|
1836
1872
|
this.meetingInfoFailureCode = err.wbxAppApiCode;
|
1837
1873
|
|
@@ -1839,6 +1875,10 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
1839
1875
|
this.passwordStatus = PASSWORD_STATUS.REQUIRED;
|
1840
1876
|
}
|
1841
1877
|
|
1878
|
+
if (err.isRegistrationIdRequired) {
|
1879
|
+
this.registrationIdStatus = REGISTRATION_ID_STATUS.REQUIRED;
|
1880
|
+
}
|
1881
|
+
|
1842
1882
|
this.requiredCaptcha = err.captchaInfo;
|
1843
1883
|
throw new CaptchaError();
|
1844
1884
|
} else {
|
@@ -1979,6 +2019,48 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
1979
2019
|
});
|
1980
2020
|
}
|
1981
2021
|
|
2022
|
+
/**
|
2023
|
+
* Checks if the supplied registrationId is correct. It returns a promise with information whether the
|
2024
|
+
* registrationId and captcha code were correct or not.
|
2025
|
+
* @param {String | undefined} registrationId - can be undefined if only captcha was required
|
2026
|
+
* @param {String | undefined} captchaCode - can be undefined if captcha was not required by the server
|
2027
|
+
* @param {Boolean} sendCAevents - whether Call Analyzer events should be sent when fetching meeting information
|
2028
|
+
* @public
|
2029
|
+
* @memberof Meeting
|
2030
|
+
* @returns {Promise<{isRegistrationIdValid: boolean, requiredCaptcha: boolean, failureReason: MEETING_INFO_FAILURE_REASON}>}
|
2031
|
+
*/
|
2032
|
+
public verifyRegistrationId(registrationId: string, captchaCode: string, sendCAevents = false) {
|
2033
|
+
return this.fetchMeetingInfo({
|
2034
|
+
registrationId,
|
2035
|
+
captchaCode,
|
2036
|
+
sendCAevents,
|
2037
|
+
})
|
2038
|
+
.then(() => {
|
2039
|
+
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.VERIFY_REGISTRATION_ID_SUCCESS);
|
2040
|
+
|
2041
|
+
return {
|
2042
|
+
isRegistrationIdValid: true,
|
2043
|
+
requiredCaptcha: null,
|
2044
|
+
failureReason: MEETING_INFO_FAILURE_REASON.NONE,
|
2045
|
+
};
|
2046
|
+
})
|
2047
|
+
.catch((error) => {
|
2048
|
+
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.VERIFY_REGISTRATION_ID_ERROR);
|
2049
|
+
|
2050
|
+
if (error instanceof JoinWebinarError || error instanceof CaptchaError) {
|
2051
|
+
return {
|
2052
|
+
isRegistrationIdValid: this.registrationIdStatus === REGISTRATION_ID_STATUS.VERIFIED,
|
2053
|
+
requiredCaptcha: this.requiredCaptcha,
|
2054
|
+
failureReason:
|
2055
|
+
error instanceof JoinWebinarError
|
2056
|
+
? MEETING_INFO_FAILURE_REASON.WRONG_REGISTRATION_ID
|
2057
|
+
: this.meetingInfoFailureReason,
|
2058
|
+
};
|
2059
|
+
}
|
2060
|
+
throw error;
|
2061
|
+
});
|
2062
|
+
}
|
2063
|
+
|
1982
2064
|
/**
|
1983
2065
|
* Refreshes the captcha. As a result the meeting will have new captcha id, image and audio.
|
1984
2066
|
* If the refresh operation fails, meeting remains with the old captcha properties.
|
@@ -3349,6 +3431,10 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
3349
3431
|
// The second on is if the audio is muted, we need to tell the statsAnalyzer when
|
3350
3432
|
// the audio is muted or the user is not willing to send media
|
3351
3433
|
this.locusInfo.on(LOCUSINFO.EVENTS.MEDIA_STATUS_CHANGE, (status) => {
|
3434
|
+
LoggerProxy.logger.info(
|
3435
|
+
'Meeting:index#setUpLocusInfoSelfListener --> MEDIA_STATUS_CHANGE received, processing...'
|
3436
|
+
);
|
3437
|
+
|
3352
3438
|
if (this.statsAnalyzer) {
|
3353
3439
|
this.statsAnalyzer.updateMediaStatus({
|
3354
3440
|
actual: status,
|
@@ -3362,6 +3448,10 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
3362
3448
|
receiveShare: this.mediaProperties.mediaDirection?.receiveShare,
|
3363
3449
|
},
|
3364
3450
|
});
|
3451
|
+
} else {
|
3452
|
+
LoggerProxy.logger.warn(
|
3453
|
+
'Meeting:index#setUpLocusInfoSelfListener --> MEDIA_STATUS_CHANGE, statsAnalyzer is not available.'
|
3454
|
+
);
|
3365
3455
|
}
|
3366
3456
|
});
|
3367
3457
|
|
@@ -3407,6 +3497,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
3407
3497
|
});
|
3408
3498
|
|
3409
3499
|
this.locusInfo.on(LOCUSINFO.EVENTS.SELF_MEETING_BRB_CHANGED, (payload) => {
|
3500
|
+
this.brbState?.handleServerBrbUpdate(payload?.brb?.enabled);
|
3410
3501
|
Trigger.trigger(
|
3411
3502
|
this,
|
3412
3503
|
{
|
@@ -3650,22 +3741,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
3650
3741
|
return Promise.reject(error);
|
3651
3742
|
}
|
3652
3743
|
|
3653
|
-
|
3654
|
-
return this.meetingRequest
|
3655
|
-
.setBrb({
|
3656
|
-
enabled,
|
3657
|
-
locusUrl: this.locusUrl,
|
3658
|
-
deviceUrl: this.deviceUrl,
|
3659
|
-
selfId: this.selfId,
|
3660
|
-
})
|
3661
|
-
.then(() => {
|
3662
|
-
this.sendSlotManager.setSourceStateOverride(MediaType.VideoMain, enabled ? 'away' : null);
|
3663
|
-
})
|
3664
|
-
.catch((error) => {
|
3665
|
-
LoggerProxy.logger.error('Meeting:index#beRightBack --> Error ', error);
|
3666
|
-
|
3667
|
-
return Promise.reject(error);
|
3668
|
-
});
|
3744
|
+
return this.brbState.enable(enabled, this.sendSlotManager);
|
3669
3745
|
}
|
3670
3746
|
|
3671
3747
|
/**
|
@@ -6099,9 +6175,12 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
6099
6175
|
* @returns {undefined}
|
6100
6176
|
*/
|
6101
6177
|
public roapMessageReceived = (roapMessage: RoapMessage) => {
|
6102
|
-
const mediaServer =
|
6178
|
+
const mediaServer =
|
6179
|
+
roapMessage.messageType === 'ANSWER'
|
6180
|
+
? MeetingsUtil.getMediaServer(roapMessage.sdp)
|
6181
|
+
: undefined;
|
6103
6182
|
|
6104
|
-
if (this.isMultistream && mediaServer !== 'homer') {
|
6183
|
+
if (this.isMultistream && mediaServer && mediaServer !== 'homer') {
|
6105
6184
|
throw new MultistreamNotSupportedError(
|
6106
6185
|
`Client asked for multistream backend (Homer), but got ${mediaServer} instead`
|
6107
6186
|
);
|
@@ -6716,6 +6795,9 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
6716
6795
|
new RtcMetrics(this.webex, {meetingId: this.id}, this.correlationId)
|
6717
6796
|
: undefined;
|
6718
6797
|
|
6798
|
+
// ongoing reachability checks slow down new media connections especially on Firefox, so we stop them
|
6799
|
+
this.getWebexObject().meetings.reachability.stopReachability();
|
6800
|
+
|
6719
6801
|
const mc = Media.createMediaConnection(
|
6720
6802
|
this.isMultistream,
|
6721
6803
|
this.getMediaConnectionDebugId(),
|
@@ -7432,6 +7514,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
7432
7514
|
|
7433
7515
|
this.audio = createMuteState(AUDIO, this, audioEnabled);
|
7434
7516
|
this.video = createMuteState(VIDEO, this, videoEnabled);
|
7517
|
+
this.brbState = createBrbState(this, false);
|
7435
7518
|
|
7436
7519
|
try {
|
7437
7520
|
await this.setUpLocalStreamReferences(localStreams);
|
@@ -7467,6 +7550,9 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
7467
7550
|
throw error;
|
7468
7551
|
}
|
7469
7552
|
}
|
7553
|
+
|
7554
|
+
LoggerProxy.logger.info(`${LOG_HEADER} media connected, finalizing...`);
|
7555
|
+
|
7470
7556
|
if (this.mediaProperties.hasLocalShareStream()) {
|
7471
7557
|
await this.enqueueScreenShareFloorRequest();
|
7472
7558
|
}
|
package/src/meeting/muteState.ts
CHANGED
@@ -379,12 +379,7 @@ export class MuteState {
|
|
379
379
|
}
|
380
380
|
if (muted !== undefined) {
|
381
381
|
this.state.server.remoteMute = muted;
|
382
|
-
|
383
|
-
// We never want to unmute the local stream from a server remote mute update.
|
384
|
-
// Moderated unmute is handled by a different function.
|
385
|
-
if (muted) {
|
386
|
-
this.muteLocalStream(meeting, muted, 'remotelyMuted');
|
387
|
-
}
|
382
|
+
this.muteLocalStream(meeting, muted, 'remotelyMuted');
|
388
383
|
}
|
389
384
|
}
|
390
385
|
|
@@ -17,6 +17,8 @@ const CAPTCHA_ERROR_DEFAULT_MESSAGE =
|
|
17
17
|
const ADHOC_MEETING_DEFAULT_ERROR =
|
18
18
|
'Failed starting the adhoc meeting, Please contact support team ';
|
19
19
|
const CAPTCHA_ERROR_REQUIRES_PASSWORD_CODES = [423005, 423006];
|
20
|
+
const CAPTCHA_ERROR_REQUIRES_REGISTRATION_ID_CODES = [423007];
|
21
|
+
|
20
22
|
const POLICY_ERROR_CODES = [403049, 403104, 403103, 403048, 403102, 403101];
|
21
23
|
const JOIN_FORBIDDEN_CODES = [403003];
|
22
24
|
/**
|
@@ -113,6 +115,7 @@ export class MeetingInfoV2PolicyError extends Error {
|
|
113
115
|
export class MeetingInfoV2CaptchaError extends Error {
|
114
116
|
captchaInfo: any;
|
115
117
|
isPasswordRequired: any;
|
118
|
+
isRegistrationIdRequired: any;
|
116
119
|
sdkMessage: any;
|
117
120
|
wbxAppApiCode: any;
|
118
121
|
body: any;
|
@@ -134,6 +137,8 @@ export class MeetingInfoV2CaptchaError extends Error {
|
|
134
137
|
this.stack = new Error().stack;
|
135
138
|
this.wbxAppApiCode = wbxAppApiErrorCode;
|
136
139
|
this.isPasswordRequired = CAPTCHA_ERROR_REQUIRES_PASSWORD_CODES.includes(wbxAppApiErrorCode);
|
140
|
+
this.isRegistrationIdRequired =
|
141
|
+
CAPTCHA_ERROR_REQUIRES_REGISTRATION_ID_CODES.includes(wbxAppApiErrorCode);
|
137
142
|
this.captchaInfo = captchaInfo;
|
138
143
|
}
|
139
144
|
}
|
@@ -370,6 +375,7 @@ export default class MeetingInfoV2 {
|
|
370
375
|
* @param {String} locusId
|
371
376
|
* @param {Object} extraParams
|
372
377
|
* @param {Object} options
|
378
|
+
* @param {String} registrationId
|
373
379
|
* @returns {Promise} returns a meeting info object
|
374
380
|
* @public
|
375
381
|
* @memberof MeetingInfo
|
@@ -385,7 +391,8 @@ export default class MeetingInfoV2 {
|
|
385
391
|
installedOrgID = null,
|
386
392
|
locusId = null,
|
387
393
|
extraParams: object = {},
|
388
|
-
options: {meetingId?: string; sendCAevents?: boolean} = {}
|
394
|
+
options: {meetingId?: string; sendCAevents?: boolean} = {},
|
395
|
+
registrationId: string = null
|
389
396
|
) {
|
390
397
|
const {meetingId, sendCAevents} = options;
|
391
398
|
|
@@ -410,6 +417,7 @@ export default class MeetingInfoV2 {
|
|
410
417
|
installedOrgID,
|
411
418
|
locusId,
|
412
419
|
extraParams,
|
420
|
+
registrationId,
|
413
421
|
});
|
414
422
|
|
415
423
|
// If the body only contains the default properties, we don't have enough to
|
@@ -228,8 +228,16 @@ export default class MeetingInfoUtil {
|
|
228
228
|
* @returns {Object} returns an object with {resource, method}
|
229
229
|
*/
|
230
230
|
static getRequestBody(options: {type: DESTINATION_TYPE; destination: object} | any) {
|
231
|
-
const {
|
232
|
-
|
231
|
+
const {
|
232
|
+
type,
|
233
|
+
destination,
|
234
|
+
password,
|
235
|
+
captchaInfo,
|
236
|
+
installedOrgID,
|
237
|
+
locusId,
|
238
|
+
extraParams,
|
239
|
+
registrationId,
|
240
|
+
} = options;
|
233
241
|
const body: any = {
|
234
242
|
...DEFAULT_MEETING_INFO_REQUEST_BODY,
|
235
243
|
...extraParams,
|
@@ -271,6 +279,10 @@ export default class MeetingInfoUtil {
|
|
271
279
|
body.password = password;
|
272
280
|
}
|
273
281
|
|
282
|
+
if (registrationId) {
|
283
|
+
body.registrationId = registrationId;
|
284
|
+
}
|
285
|
+
|
274
286
|
if (captchaInfo) {
|
275
287
|
body.captchaID = captchaInfo.id;
|
276
288
|
body.captchaVerifyCode = captchaInfo.code;
|
package/src/metrics/constants.ts
CHANGED
@@ -73,6 +73,8 @@ const BEHAVIORAL_METRICS = {
|
|
73
73
|
JOIN_WEBINAR_ERROR: 'js_sdk_join_webinar_error',
|
74
74
|
GUEST_ENTERED_LOBBY: 'js_sdk_guest_entered_lobby',
|
75
75
|
GUEST_EXITED_LOBBY: 'js_sdk_guest_exited_lobby',
|
76
|
+
VERIFY_REGISTRATION_ID_SUCCESS: 'js_sdk_verify_registrationId_success',
|
77
|
+
VERIFY_REGISTRATION_ID_ERROR: 'js_sdk_verify_registrationId_error',
|
76
78
|
JOIN_FORBIDDEN_ERROR: 'js_sdk_join_forbidden_error',
|
77
79
|
};
|
78
80
|
|
@@ -259,6 +259,32 @@ export default class Reachability extends EventsScope {
|
|
259
259
|
}
|
260
260
|
}
|
261
261
|
|
262
|
+
/**
|
263
|
+
* Stops all reachability checks that are in progress
|
264
|
+
* @public
|
265
|
+
* @memberof Reachability
|
266
|
+
* @returns {void}
|
267
|
+
*/
|
268
|
+
public stopReachability() {
|
269
|
+
// overallTimer is always there only if there is reachability in progress
|
270
|
+
if (this.overallTimer) {
|
271
|
+
LoggerProxy.logger.log(
|
272
|
+
'Reachability:index#stopReachability --> stopping reachability checks'
|
273
|
+
);
|
274
|
+
this.abortCurrentChecks();
|
275
|
+
this.emit(
|
276
|
+
{
|
277
|
+
file: 'reachability',
|
278
|
+
function: 'stopReachability',
|
279
|
+
},
|
280
|
+
'reachability:stopped',
|
281
|
+
{}
|
282
|
+
);
|
283
|
+
this.sendMetric(true);
|
284
|
+
this.resolveReachabilityPromise();
|
285
|
+
}
|
286
|
+
}
|
287
|
+
|
262
288
|
/**
|
263
289
|
* Returns statistics about last reachability results. The returned value is an object
|
264
290
|
* with a flat list of properties so that it can be easily sent with metrics
|
@@ -637,9 +663,10 @@ export default class Reachability extends EventsScope {
|
|
637
663
|
/**
|
638
664
|
* Sends a metric with all the statistics about how long reachability took
|
639
665
|
*
|
666
|
+
* @param {boolean} aborted true if the reachability checks were aborted
|
640
667
|
* @returns {void}
|
641
668
|
*/
|
642
|
-
protected async sendMetric() {
|
669
|
+
protected async sendMetric(aborted = false) {
|
643
670
|
const results = [];
|
644
671
|
|
645
672
|
Object.values(this.clusterReachability).forEach((clusterReachability) => {
|
@@ -650,6 +677,7 @@ export default class Reachability extends EventsScope {
|
|
650
677
|
});
|
651
678
|
|
652
679
|
const stats = {
|
680
|
+
aborted,
|
653
681
|
vmn: {
|
654
682
|
udp: this.getStatistics(results, 'udp', true),
|
655
683
|
},
|
@@ -450,6 +450,16 @@ describe('plugin-meetings', () => {
|
|
450
450
|
assert.equal(SelfUtils.mutedByOthersChanged(null, {remoteMuted: true}), true);
|
451
451
|
});
|
452
452
|
|
453
|
+
it('should return false when selfIdentity and modifiedBy are the same', function () {
|
454
|
+
assert.equal(
|
455
|
+
SelfUtils.mutedByOthersChanged(
|
456
|
+
{remoteMuted: false},
|
457
|
+
{remoteMuted: true, selfIdentity: 'user1', modifiedBy: 'user1'}
|
458
|
+
),
|
459
|
+
false
|
460
|
+
);
|
461
|
+
});
|
462
|
+
|
453
463
|
it('should return true when remoteMuted values are different', function () {
|
454
464
|
assert.equal(
|
455
465
|
SelfUtils.mutedByOthersChanged(
|
@@ -66,6 +66,21 @@ describe('MediaProperties', () => {
|
|
66
66
|
assert.equal(numTransports, 0);
|
67
67
|
});
|
68
68
|
|
69
|
+
it('handles time out in the case when getStats() is not resolving', async () => {
|
70
|
+
// Promise that never resolves
|
71
|
+
mockMC.getStats = new Promise(() => {});
|
72
|
+
|
73
|
+
const promise = mediaProperties.getCurrentConnectionInfo();
|
74
|
+
|
75
|
+
await clock.tickAsync(1000);
|
76
|
+
|
77
|
+
const {connectionType, selectedCandidatePairChanges, numTransports} = await promise;
|
78
|
+
|
79
|
+
assert.equal(connectionType, 'unknown');
|
80
|
+
assert.equal(selectedCandidatePairChanges, -1);
|
81
|
+
assert.equal(numTransports, 0);
|
82
|
+
});
|
83
|
+
|
69
84
|
describe('selectedCandidatePairChanges and numTransports', () => {
|
70
85
|
it('returns correct values when getStats() returns no transport stats at all', async () => {
|
71
86
|
mockMC.getStats.resolves([{type: 'something', id: '1234'}]);
|
@@ -0,0 +1,114 @@
|
|
1
|
+
import sinon from 'sinon';
|
2
|
+
import {assert} from '@webex/test-helper-chai';
|
3
|
+
|
4
|
+
import testUtils from '../../../utils/testUtils';
|
5
|
+
import {BrbState, createBrbState} from '@webex/plugin-meetings/src/meeting/brbState';
|
6
|
+
|
7
|
+
describe('plugin-meetings', () => {
|
8
|
+
let meeting: any;
|
9
|
+
let brbState: BrbState;
|
10
|
+
|
11
|
+
beforeEach(async () => {
|
12
|
+
meeting = {
|
13
|
+
isMultistream: true,
|
14
|
+
locusUrl: 'locus url',
|
15
|
+
deviceUrl: 'device url',
|
16
|
+
selfId: 'self id',
|
17
|
+
mediaProperties: {
|
18
|
+
webrtcMediaConnection: true,
|
19
|
+
},
|
20
|
+
sendSlotManager: {
|
21
|
+
setSourceStateOverride: sinon.stub(),
|
22
|
+
},
|
23
|
+
meetingRequest: {
|
24
|
+
setBrb: sinon.stub().resolves(),
|
25
|
+
},
|
26
|
+
};
|
27
|
+
|
28
|
+
brbState = new BrbState(meeting, false);
|
29
|
+
await testUtils.flushPromises();
|
30
|
+
});
|
31
|
+
|
32
|
+
describe('brbState library', () => {
|
33
|
+
it('takes into account current status when instantiated', async () => {
|
34
|
+
// create a new BrbState instance
|
35
|
+
brbState = createBrbState(meeting, true);
|
36
|
+
await testUtils.flushPromises();
|
37
|
+
|
38
|
+
assert.isTrue(brbState.state.client.enabled);
|
39
|
+
|
40
|
+
// now check the opposite case
|
41
|
+
brbState = createBrbState(meeting, false);
|
42
|
+
await testUtils.flushPromises();
|
43
|
+
|
44
|
+
assert.isFalse(brbState.state.client.enabled);
|
45
|
+
});
|
46
|
+
|
47
|
+
it('can be enabled', async () => {
|
48
|
+
brbState.enable(true, meeting.sendSlotManager);
|
49
|
+
brbState.handleServerBrbUpdate(true);
|
50
|
+
await testUtils.flushPromises();
|
51
|
+
|
52
|
+
assert.isTrue(brbState.state.client.enabled);
|
53
|
+
assert.isTrue(brbState.state.server.enabled);
|
54
|
+
});
|
55
|
+
|
56
|
+
it('can be disabled', async () => {
|
57
|
+
brbState.enable(false, meeting.sendSlotManager);
|
58
|
+
brbState.handleServerBrbUpdate(false);
|
59
|
+
await testUtils.flushPromises();
|
60
|
+
|
61
|
+
assert.isFalse(brbState.state.client.enabled);
|
62
|
+
assert.isFalse(brbState.state.server.enabled);
|
63
|
+
});
|
64
|
+
|
65
|
+
it('does not send local brb state to server if it is not a multistream meeting', async () => {
|
66
|
+
meeting.isMultistream = false;
|
67
|
+
brbState.enable(true, meeting.sendSlotManager);
|
68
|
+
brbState.handleServerBrbUpdate(true);
|
69
|
+
await testUtils.flushPromises();
|
70
|
+
|
71
|
+
assert.isTrue(meeting.meetingRequest.setBrb.notCalled);
|
72
|
+
});
|
73
|
+
|
74
|
+
it('does not send local brb state to server if webrtc media connection is not defined', async () => {
|
75
|
+
meeting.mediaProperties.webrtcMediaConnection = undefined;
|
76
|
+
brbState.enable(true, meeting.sendSlotManager);
|
77
|
+
brbState.handleServerBrbUpdate(true);
|
78
|
+
await testUtils.flushPromises();
|
79
|
+
|
80
|
+
assert.isTrue(meeting.meetingRequest.setBrb.notCalled);
|
81
|
+
});
|
82
|
+
|
83
|
+
it('does not send request twice when in progress', async () => {
|
84
|
+
brbState.state.syncToServerInProgress = true;
|
85
|
+
brbState.enable(true, meeting.sendSlotManager);
|
86
|
+
await testUtils.flushPromises();
|
87
|
+
|
88
|
+
assert.isTrue(meeting.meetingRequest.setBrb.notCalled);
|
89
|
+
});
|
90
|
+
|
91
|
+
it('syncs with server when client state does not match server state', async () => {
|
92
|
+
brbState.enable(true, meeting.sendSlotManager);
|
93
|
+
brbState.handleServerBrbUpdate(true);
|
94
|
+
await testUtils.flushPromises();
|
95
|
+
|
96
|
+
assert.isTrue(meeting.meetingRequest.setBrb.calledOnce);
|
97
|
+
});
|
98
|
+
|
99
|
+
it('sets source state override when client state does not match server state', async () => {
|
100
|
+
brbState.enable(true, meeting.sendSlotManager);
|
101
|
+
brbState.handleServerBrbUpdate(true);
|
102
|
+
await testUtils.flushPromises();
|
103
|
+
|
104
|
+
assert.isTrue(meeting.sendSlotManager.setSourceStateOverride.calledOnce);
|
105
|
+
});
|
106
|
+
|
107
|
+
it('handles server update', async () => {
|
108
|
+
brbState.handleServerBrbUpdate(true);
|
109
|
+
await testUtils.flushPromises();
|
110
|
+
|
111
|
+
assert.isTrue(brbState.state.server.enabled);
|
112
|
+
});
|
113
|
+
});
|
114
|
+
});
|