{"version":3,"file":"lib-meet.min.js","mappings":"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","sources":["webpack://JitsiMeetJS/webpack/universalModuleDefinition","webpack://JitsiMeetJS/./node_modules/lodash-es/_listCacheClear.js","webpack://JitsiMeetJS/./node_modules/lodash-es/eq.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_assocIndexOf.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_listCacheDelete.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_ListCache.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_listCacheGet.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_listCacheHas.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_listCacheSet.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_freeGlobal.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_root.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_Symbol.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_getRawTag.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_objectToString.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_baseGetTag.js","webpack://JitsiMeetJS/./node_modules/lodash-es/isObject.js","webpack://JitsiMeetJS/./node_modules/lodash-es/isFunction.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_coreJsData.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_isMasked.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_toSource.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_baseIsNative.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_getNative.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_getValue.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_Map.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_nativeCreate.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_hashGet.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_hashHas.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_Hash.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_hashClear.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_hashDelete.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_hashSet.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_getMapData.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_isKeyable.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_MapCache.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_mapCacheClear.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_mapCacheDelete.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_mapCacheGet.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_mapCacheHas.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_mapCacheSet.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_Stack.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_stackClear.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_stackDelete.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_stackGet.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_stackHas.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_stackSet.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_defineProperty.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_baseAssignValue.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_assignMergeValue.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_baseFor.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_createBaseFor.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_cloneBuffer.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_Uint8Array.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_cloneArrayBuffer.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_cloneTypedArray.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_copyArray.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_baseCreate.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_overArg.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_getPrototype.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_isPrototype.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_initCloneObject.js","webpack://JitsiMeetJS/./node_modules/lodash-es/isObjectLike.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_baseIsArguments.js","webpack://JitsiMeetJS/./node_modules/lodash-es/isArguments.js","webpack://JitsiMeetJS/./node_modules/lodash-es/isArray.js","webpack://JitsiMeetJS/./node_modules/lodash-es/isLength.js","webpack://JitsiMeetJS/./node_modules/lodash-es/isArrayLike.js","webpack://JitsiMeetJS/./node_modules/lodash-es/isBuffer.js","webpack://JitsiMeetJS/./node_modules/lodash-es/stubFalse.js","webpack://JitsiMeetJS/./node_modules/lodash-es/isPlainObject.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_baseIsTypedArray.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_baseUnary.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_nodeUtil.js","webpack://JitsiMeetJS/./node_modules/lodash-es/isTypedArray.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_safeGet.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_assignValue.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_copyObject.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_isIndex.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_arrayLikeKeys.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_baseTimes.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_baseKeysIn.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_nativeKeysIn.js","webpack://JitsiMeetJS/./node_modules/lodash-es/keysIn.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_baseMergeDeep.js","webpack://JitsiMeetJS/./node_modules/lodash-es/isArrayLikeObject.js","webpack://JitsiMeetJS/./node_modules/lodash-es/toPlainObject.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_baseMerge.js","webpack://JitsiMeetJS/./node_modules/lodash-es/identity.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_overRest.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_baseSetToString.js","webpack://JitsiMeetJS/./node_modules/lodash-es/constant.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_shortOut.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_setToString.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_baseRest.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_apply.js","webpack://JitsiMeetJS/./node_modules/lodash-es/merge.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_createAssigner.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_isIterateeCall.js","webpack://JitsiMeetJS/./JitsiAudioTranslationErrors.ts","webpack://JitsiMeetJS/./JitsiConferenceErrors.ts","webpack://JitsiMeetJS/./JitsiConferenceEvents.ts","webpack://JitsiMeetJS/./node_modules/lodash-es/_SetCache.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_setCacheAdd.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_setCacheHas.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_arraySome.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_equalArrays.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_cacheHas.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_mapToArray.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_setToArray.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_equalByTag.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_arrayPush.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_baseGetAllKeys.js","webpack://JitsiMeetJS/./node_modules/lodash-es/stubArray.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_getSymbols.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_arrayFilter.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_nativeKeys.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_baseKeys.js","webpack://JitsiMeetJS/./node_modules/lodash-es/keys.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_getAllKeys.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_equalObjects.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_DataView.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_Promise.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_Set.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_WeakMap.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_getTag.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_baseIsEqualDeep.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_baseIsEqual.js","webpack://JitsiMeetJS/./node_modules/lodash-es/isEqual.js","webpack://JitsiMeetJS/./JitsiTrackEvents.ts","webpack://JitsiMeetJS/./node_modules/@jitsi/rtcstats/node_modules/@jitsi/js-utils/dist/browser-detection/constants.js","webpack://JitsiMeetJS/./node_modules/@jitsi/rtcstats/node_modules/@jitsi/js-utils/dist/browser-detection/BrowserDetection.js","webpack://JitsiMeetJS/./node_modules/@jitsi/rtcstats/events.js","webpack://JitsiMeetJS/./node_modules/@jitsi/rtcstats/rtcstats.js","webpack://JitsiMeetJS/./node_modules/@jitsi/rtcstats/node_modules/uuid/dist/esm-browser/rng.js","webpack://JitsiMeetJS/./node_modules/@jitsi/rtcstats/node_modules/uuid/dist/esm-browser/regex.js","webpack://JitsiMeetJS/./node_modules/@jitsi/rtcstats/node_modules/uuid/dist/esm-browser/stringify.js","webpack://JitsiMeetJS/./node_modules/@jitsi/rtcstats/node_modules/uuid/dist/esm-browser/validate.js","webpack://JitsiMeetJS/./node_modules/@jitsi/rtcstats/node_modules/uuid/dist/esm-browser/v4.js","webpack://JitsiMeetJS/./node_modules/@jitsi/rtcstats/constants.js","webpack://JitsiMeetJS/./node_modules/@jitsi/js-utils/dist/browser-detection/constants.js","webpack://JitsiMeetJS/./node_modules/@jitsi/rtcstats/obfuscator.js","webpack://JitsiMeetJS/./node_modules/@jitsi/js-utils/dist/browser-detection/BrowserDetection.js","webpack://JitsiMeetJS/./node_modules/@jitsi/js-utils/dist/jitsi-local-storage/index.js","webpack://JitsiMeetJS/./node_modules/@jitsi/js-utils/dist/transport/constants.js","webpack://JitsiMeetJS/./node_modules/@jitsi/js-utils/dist/json.js","webpack://JitsiMeetJS/./node_modules/@jitsi/js-utils/dist/transport/PostMessageTransportBackend.js","webpack://JitsiMeetJS/./node_modules/uuid/dist/rng.js","webpack://JitsiMeetJS/./node_modules/uuid/dist/stringify.js","webpack://JitsiMeetJS/./node_modules/uuid/dist/v4.js","webpack://JitsiMeetJS/./modules/util/RandomUtil.ts","webpack://JitsiMeetJS/./modules/util/UsernameGenerator.ts","webpack://JitsiMeetJS/./modules/settings/Settings.ts","webpack://JitsiMeetJS/./modules/util/EventEmitter.ts","webpack://JitsiMeetJS/./modules/RTCStats/RTCStatsEvents.ts","webpack://JitsiMeetJS/./modules/RTCStats/DefaulLogStorage.ts","webpack://JitsiMeetJS/./modules/RTCStats/RTCStats.ts","webpack://JitsiMeetJS/./node_modules/@jitsi/rtcstats/trace-ws.js","webpack://JitsiMeetJS/./service/statistics/AnalyticsEvents.ts","webpack://JitsiMeetJS/./service/statistics/Events.ts","webpack://JitsiMeetJS/./modules/browser/index.js","webpack://JitsiMeetJS/./modules/browser/BrowserCapabilities.ts","webpack://JitsiMeetJS/./modules/watchRTC/WatchRTC.ts","webpack://JitsiMeetJS/./modules/watchRTC/functions.ts","webpack://JitsiMeetJS/./modules/statistics/AnalyticsAdapter.ts","webpack://JitsiMeetJS/./modules/statistics/LocalStatsCollector.ts","webpack://JitsiMeetJS/./service/RTC/MediaType.ts","webpack://JitsiMeetJS/./service/RTC/RTCEvents.ts","webpack://JitsiMeetJS/./modules/flags/FeatureFlags.ts","webpack://JitsiMeetJS/./modules/util/MathUtil.ts","webpack://JitsiMeetJS/./modules/statistics/RTPStatsCollector.js","webpack://JitsiMeetJS/./modules/statistics/statistics.ts","webpack://JitsiMeetJS/./service/statistics/constants.ts","webpack://JitsiMeetJS/./modules/util/EventEmitterForwarder.ts","webpack://JitsiMeetJS/./service/authentication/AuthenticationEvents.ts","webpack://JitsiMeetJS/./service/xmpp/XMPPEvents.ts","webpack://JitsiMeetJS/./JitsiConferenceEventManager.ts","webpack://JitsiMeetJS/./modules/statistics/constants.ts","webpack://JitsiMeetJS/./JitsiConnectionEvents.ts","webpack://JitsiMeetJS/./JitsiParticipant.ts","webpack://JitsiMeetJS/./JitsiTrackErrors.ts","webpack://JitsiMeetJS/./JitsiTrackError.ts","webpack://JitsiMeetJS/./node_modules/lodash-es/_arrayEach.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_getSymbolsIn.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_getAllKeysIn.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_initCloneArray.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_cloneRegExp.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_cloneSymbol.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_initCloneByTag.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_cloneDataView.js","webpack://JitsiMeetJS/./node_modules/lodash-es/isMap.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_baseIsMap.js","webpack://JitsiMeetJS/./node_modules/lodash-es/isSet.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_baseIsSet.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_baseClone.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_copySymbolsIn.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_baseAssignIn.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_copySymbols.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_baseAssign.js","webpack://JitsiMeetJS/./node_modules/lodash-es/cloneDeep.js","webpack://JitsiMeetJS/./service/RTC/VideoType.ts","webpack://JitsiMeetJS/./modules/util/Listenable.ts","webpack://JitsiMeetJS/./modules/RTC/BridgeChannel.ts","webpack://JitsiMeetJS/./service/RTC/CameraFacingMode.ts","webpack://JitsiMeetJS/./node_modules/webrtc-adapter/src/js/utils.js","webpack://JitsiMeetJS/./node_modules/webrtc-adapter/src/js/chrome/getusermedia.js","webpack://JitsiMeetJS/./node_modules/webrtc-adapter/src/js/chrome/getdisplaymedia.js","webpack://JitsiMeetJS/./node_modules/webrtc-adapter/src/js/chrome/chrome_shim.js","webpack://JitsiMeetJS/./node_modules/webrtc-adapter/src/js/firefox/getusermedia.js","webpack://JitsiMeetJS/./node_modules/webrtc-adapter/src/js/firefox/getdisplaymedia.js","webpack://JitsiMeetJS/./node_modules/webrtc-adapter/src/js/firefox/firefox_shim.js","webpack://JitsiMeetJS/./node_modules/webrtc-adapter/src/js/safari/safari_shim.js","webpack://JitsiMeetJS/./node_modules/webrtc-adapter/src/js/common_shim.js","webpack://JitsiMeetJS/./node_modules/webrtc-adapter/src/js/adapter_factory.js","webpack://JitsiMeetJS/./node_modules/webrtc-adapter/src/js/adapter_core.js","webpack://JitsiMeetJS/./service/RTC/Resolutions.ts","webpack://JitsiMeetJS/./modules/RTC/ScreenObtainer.ts","webpack://JitsiMeetJS/./modules/RTC/RTCUtils.js","webpack://JitsiMeetJS/./modules/RTC/JitsiTrack.ts","webpack://JitsiMeetJS/./modules/RTC/JitsiLocalTrack.ts","webpack://JitsiMeetJS/./service/RTC/CodecMimeType.ts","webpack://JitsiMeetJS/./service/RTC/MediaDirection.ts","webpack://JitsiMeetJS/./service/RTC/SignalingEvents.ts","webpack://JitsiMeetJS/./service/RTC/SignalingLayer.ts","webpack://JitsiMeetJS/./service/RTC/StandardVideoQualitySettings.ts","webpack://JitsiMeetJS/./modules/sdp/SdpTransformUtil.ts","webpack://JitsiMeetJS/./modules/sdp/LocalSdpMunger.ts","webpack://JitsiMeetJS/./modules/sdp/SDPUtil.ts","webpack://JitsiMeetJS/./modules/sdp/RtxModifier.js","webpack://JitsiMeetJS/./service/xmpp/XMPPExtensioProtocols.ts","webpack://JitsiMeetJS/./modules/util/XMLUtils.ts","webpack://JitsiMeetJS/./modules/sdp/SDP.ts","webpack://JitsiMeetJS/./modules/sdp/SdpSimulcast.ts","webpack://JitsiMeetJS/./modules/connectivity/TrackStreamingStatus.ts","webpack://JitsiMeetJS/./modules/RTC/JitsiRemoteTrack.ts","webpack://JitsiMeetJS/./service/RTC/VideoEncoderScalabilityMode.ts","webpack://JitsiMeetJS/./modules/RTC/TPCUtils.ts","webpack://JitsiMeetJS/./modules/RTC/TraceablePeerConnection.ts","webpack://JitsiMeetJS/./modules/RTC/RTC.js","webpack://JitsiMeetJS/./service/connectivity/ConnectionQualityEvents.ts","webpack://JitsiMeetJS/./modules/connectivity/ConnectionQuality.ts","webpack://JitsiMeetJS/./modules/connectivity/IceFailedHandling.ts","webpack://JitsiMeetJS/./modules/detection/DetectionEvents.ts","webpack://JitsiMeetJS/./modules/detection/NoAudioSignalDetection.ts","webpack://JitsiMeetJS/./modules/detection/P2PDominantSpeakerDetection.ts","webpack://JitsiMeetJS/./modules/webaudio/WebAudioUtils.ts","webpack://JitsiMeetJS/./modules/detection/TrackVADEmitter.ts","webpack://JitsiMeetJS/./modules/detection/VADAudioAnalyser.ts","webpack://JitsiMeetJS/./modules/detection/VADNoiseDetection.ts","webpack://JitsiMeetJS/./modules/detection/VADTalkMutedDetection.ts","webpack://JitsiMeetJS/./node_modules/jwt-decode/build/esm/index.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_baseToString.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_arrayMap.js","webpack://JitsiMeetJS/./node_modules/lodash-es/isSymbol.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_unescapeHtmlChar.js","webpack://JitsiMeetJS/./node_modules/lodash-es/_basePropertyOf.js","webpack://JitsiMeetJS/./node_modules/lodash-es/unescape.js","webpack://JitsiMeetJS/./node_modules/lodash-es/toString.js","webpack://JitsiMeetJS/./JitsiConnectionErrors.ts","webpack://JitsiMeetJS/./modules/xmpp/sha1.ts","webpack://JitsiMeetJS/./modules/xmpp/Caps.ts","webpack://JitsiMeetJS/./modules/xmpp/FileSharing.ts","webpack://JitsiMeetJS/./service/connectivity/Constants.ts","webpack://JitsiMeetJS/./modules/connectivity/NetworkInfo.ts","webpack://JitsiMeetJS/./modules/util/Retry.ts","webpack://JitsiMeetJS/./modules/xmpp/ResumeTask.ts","webpack://JitsiMeetJS/./modules/xmpp/StropheLastSuccess.ts","webpack://JitsiMeetJS/./modules/xmpp/strophe.stream-management.ts","webpack://JitsiMeetJS/./modules/xmpp/ConnectionPlugin.ts","webpack://JitsiMeetJS/./modules/xmpp/strophe.ping.ts","webpack://JitsiMeetJS/./modules/xmpp/XmppConnection.ts","webpack://JitsiMeetJS/./modules/xmpp/StropheErrorHandler.ts","webpack://JitsiMeetJS/./modules/xmpp/moderator.js","webpack://JitsiMeetJS/./modules/xmpp/strophe.disco.js","webpack://JitsiMeetJS/./JitsiTranscriptionStatus.ts","webpack://JitsiMeetJS/./modules/xmpp/AVModeration.ts","webpack://JitsiMeetJS/./modules/xmpp/BreakoutRooms.js","webpack://JitsiMeetJS/src/utils.ts","webpack://JitsiMeetJS/src/_arx.ts","webpack://JitsiMeetJS/src/_poly1305.ts","webpack://JitsiMeetJS/src/chacha.ts","webpack://JitsiMeetJS/./node_modules/@hexagon/base64/dist/base64.js","webpack://JitsiMeetJS/src/_u64.ts","webpack://JitsiMeetJS/src/sha3.ts","webpack://JitsiMeetJS/../src/abstract/fft.ts","webpack://JitsiMeetJS/src/_crystals.ts","webpack://JitsiMeetJS/src/ml-kem.ts","webpack://JitsiMeetJS/./modules/e2ee-internxt/Utils.ts","webpack://JitsiMeetJS/./modules/xmpp/ChetRoomCrypto.ts","webpack://JitsiMeetJS/./modules/xmpp/Lobby.js","webpack://JitsiMeetJS/./modules/xmpp/Polls.ts","webpack://JitsiMeetJS/./modules/xmpp/RoomMetadata.ts","webpack://JitsiMeetJS/./modules/xmpp/ChatRoom.ts","webpack://JitsiMeetJS/./node_modules/emoji-regex/index.mjs","webpack://JitsiMeetJS/./modules/xmpp/strophe.emuc.ts","webpack://JitsiMeetJS/./modules/xmpp/JingleHelperFunctions.ts","webpack://JitsiMeetJS/./service/RTC/IceRestartReason.ts","webpack://JitsiMeetJS/./modules/RTC/RemoteAudioWedgeDetector.ts","webpack://JitsiMeetJS/./modules/sdp/SDPDiffer.ts","webpack://JitsiMeetJS/./node_modules/async-es/internal/onlyOnce.js","webpack://JitsiMeetJS/./node_modules/async-es/internal/setImmediate.js","webpack://JitsiMeetJS/./node_modules/async-es/internal/DoublyLinkedList.js","webpack://JitsiMeetJS/./node_modules/async-es/asyncify.js","webpack://JitsiMeetJS/./node_modules/async-es/internal/wrapAsync.js","webpack://JitsiMeetJS/./node_modules/async-es/internal/initialParams.js","webpack://JitsiMeetJS/./node_modules/async-es/internal/queue.js","webpack://JitsiMeetJS/./modules/util/AsyncQueue.ts","webpack://JitsiMeetJS/./node_modules/async-es/queue.js","webpack://JitsiMeetJS/./modules/util/OTel.ts","webpack://JitsiMeetJS/./modules/xmpp/JingleSessionState.ts","webpack://JitsiMeetJS/./modules/xmpp/JingleSession.ts","webpack://JitsiMeetJS/./modules/xmpp/MediaSessionEvents.ts","webpack://JitsiMeetJS/./modules/xmpp/JingleSessionPC.ts","webpack://JitsiMeetJS/./modules/xmpp/strophe.jingle.js","webpack://JitsiMeetJS/./modules/xmpp/strophe.logger.ts","webpack://JitsiMeetJS/./modules/xmpp/strophe.rayo.ts","webpack://JitsiMeetJS/./modules/xmpp/strophe.util.ts","webpack://JitsiMeetJS/./modules/xmpp/xmpp.ts","webpack://JitsiMeetJS/src/_md.ts","webpack://JitsiMeetJS/src/_blake.ts","webpack://JitsiMeetJS/src/blake2.ts","webpack://JitsiMeetJS/src/blake3.ts","webpack://JitsiMeetJS/./modules/e2ee-internxt/Types.ts","webpack://JitsiMeetJS/./modules/e2ee-internxt/CryptoUtils.ts","webpack://JitsiMeetJS/./modules/e2ee-internxt/E2EEContext.ts","webpack://JitsiMeetJS/./modules/e2ee-internxt/SessionData.ts","webpack://JitsiMeetJS/./modules/e2ee-internxt/OlmAdapter.ts","webpack://JitsiMeetJS/./modules/e2ee-internxt/SAS.ts","webpack://JitsiMeetJS/./modules/e2ee-internxt/ManagedKeyHandler.ts","webpack://JitsiMeetJS/./modules/e2ee-internxt/E2EEncryption.ts","webpack://JitsiMeetJS/./service/e2eping/E2ePingEvents.ts","webpack://JitsiMeetJS/./modules/e2eping/e2eping.ts","webpack://JitsiMeetJS/./modules/litemode/LiteModeContext.ts","webpack://JitsiMeetJS/./modules/qualitycontrol/CodecSelection.ts","webpack://JitsiMeetJS/./service/RTC/ReceiverAudioSubscription.ts","webpack://JitsiMeetJS/./modules/qualitycontrol/ReceiveAudioController.ts","webpack://JitsiMeetJS/./modules/qualitycontrol/ReceiveVideoController.ts","webpack://JitsiMeetJS/./modules/qualitycontrol/SendVideoController.ts","webpack://JitsiMeetJS/./modules/qualitycontrol/QualityController.ts","webpack://JitsiMeetJS/./modules/recording/JibriSession.ts","webpack://JitsiMeetJS/./modules/recording/recordingXMLUtils.ts","webpack://JitsiMeetJS/./modules/recording/RecordingManager.ts","webpack://JitsiMeetJS/./modules/statistics/AvgRTPStatsReporter.ts","webpack://JitsiMeetJS/./modules/statistics/SpeakerStats.ts","webpack://JitsiMeetJS/./modules/statistics/SpeakerStatsCollector.ts","webpack://JitsiMeetJS/./modules/version/ComponentsVersions.ts","webpack://JitsiMeetJS/./modules/videosipgw/VideoSIPGWConstants.ts","webpack://JitsiMeetJS/./modules/videosipgw/JitsiVideoSIPGWSession.ts","webpack://JitsiMeetJS/./modules/videosipgw/VideoSIPGW.ts","webpack://JitsiMeetJS/./modules/xmpp/SignalingLayerImpl.ts","webpack://JitsiMeetJS/./service/RTC/BridgeVideoType.ts","webpack://JitsiMeetJS/./JitsiConference.ts","webpack://JitsiMeetJS/./JitsiConnection.ts","webpack://JitsiMeetJS/./JitsiMediaDevicesEvents.ts","webpack://JitsiMeetJS/./JitsiMediaDevices.ts","webpack://JitsiMeetJS/./modules/detection/ActiveDeviceDetector.ts","webpack://JitsiMeetJS/./modules/proxyconnection/CustomSignalingLayer.ts","webpack://JitsiMeetJS/./modules/proxyconnection/constants.ts","webpack://JitsiMeetJS/./modules/proxyconnection/ProxyConnectionPC.js","webpack://JitsiMeetJS/./modules/proxyconnection/ProxyConnectionService.js","webpack://JitsiMeetJS/./node_modules/@jitsi/precall-test/src/utility/parsedIceCandidate.js","webpack://JitsiMeetJS/./node_modules/@jitsi/precall-test/src/utility/stats/detectbrowser.js","webpack://JitsiMeetJS/./node_modules/@jitsi/precall-test/src/utility/stats/statsadapter.js","webpack://JitsiMeetJS/./node_modules/@jitsi/precall-test/src/utility/stats/getstatshandler.js","webpack://JitsiMeetJS/./node_modules/@jitsi/precall-test/src/turnConnection.js","webpack://JitsiMeetJS/./node_modules/@jitsi/precall-test/src/utility/timestamps.js","webpack://JitsiMeetJS/./node_modules/@jitsi/precall-test/src/tests/turnTest.js","webpack://JitsiMeetJS/./node_modules/@jitsi/precall-test/src/tests/rttTest.js","webpack://JitsiMeetJS/./node_modules/@jitsi/precall-test/src/utility/messageMaker.js","webpack://JitsiMeetJS/./node_modules/@jitsi/precall-test/src/tests/throughputTest.js","webpack://JitsiMeetJS/./node_modules/@jitsi/precall-test/src/tests/lossTest.js","webpack://JitsiMeetJS/./node_modules/@jitsi/precall-test/src/utility/resultsHandler.js","webpack://JitsiMeetJS/./node_modules/@jitsi/precall-test/src/utility/onlineCheck.js","webpack://JitsiMeetJS/./node_modules/@jitsi/precall-test/src/main.js","webpack://JitsiMeetJS/./modules/util/Deferred.ts","webpack://JitsiMeetJS/./modules/util/ScriptUtil.ts","webpack://JitsiMeetJS/./modules/webaudio/AudioMixer.ts","webpack://JitsiMeetJS/./version.ts","webpack://JitsiMeetJS/./JitsiMeetJS.ts","webpack://JitsiMeetJS/./modules/recording/recordingConstants.ts","webpack://JitsiMeetJS/./modules/statistics/PreCallTest.ts","webpack://JitsiMeetJS/./index.js","webpack://JitsiMeetJS/./node_modules/@hapi/bourne/lib/index.js","webpack://JitsiMeetJS/./node_modules/@jitsi/logger/lib/LogCollector.js","webpack://JitsiMeetJS/./node_modules/@jitsi/logger/lib/Logger.js","webpack://JitsiMeetJS/./node_modules/@jitsi/logger/lib/index.js","webpack://JitsiMeetJS/./node_modules/@jitsi/rtcstats/node_modules/@jitsi/logger/lib/LogCollector.js","webpack://JitsiMeetJS/./node_modules/@jitsi/rtcstats/node_modules/@jitsi/logger/lib/Logger.js","webpack://JitsiMeetJS/./node_modules/@jitsi/rtcstats/node_modules/@jitsi/logger/lib/index.js","webpack://JitsiMeetJS/watchRTC/webpack/universalModuleDefinition","webpack://JitsiMeetJS/watchRTC/src/index.ts","webpack://JitsiMeetJS/watchRTC/src/sdk.ts","webpack://JitsiMeetJS/watchRTC/src/stats.ts","webpack://JitsiMeetJS/watchRTC/src/types.ts","webpack://JitsiMeetJS/watchRTC/src/utils.ts","webpack://JitsiMeetJS/watchRTC/src/version.ts","webpack://JitsiMeetJS/watchRTC/src/watchrtchttp.ts","webpack://JitsiMeetJS/watchRTC/src/watchrtcsocket.ts","webpack://JitsiMeetJS/watchRTC/src/detect-gpu.js","webpack://JitsiMeetJS/watchRTC/Users/yurapostevka/Documents/apps/testrtc/watchrtc-sdk/src/gpu-benchmarks|sync|/^\\.\\/.*$/","webpack://JitsiMeetJS/watchRTC/src/lz-string.js","webpack://JitsiMeetJS/watchRTC/webpack/bootstrap","webpack://JitsiMeetJS/watchRTC/webpack/startup","webpack://JitsiMeetJS/watchRTC/webpack/runtime/global","webpack://JitsiMeetJS/watchRTC/webpack/runtime/hasOwnProperty shorthand","webpack://JitsiMeetJS/./node_modules/current-executing-script/dist/currentExecutingScript.js","webpack://JitsiMeetJS/./node_modules/events/events.js","webpack://JitsiMeetJS/./node_modules/js-md5/src/md5.js","webpack://JitsiMeetJS/../../common/lib/backend-impl.ts","webpack://JitsiMeetJS/../../common/lib/version.ts","webpack://JitsiMeetJS/../../common/lib/env-impl.ts","webpack://JitsiMeetJS/../../common/lib/env.ts","webpack://JitsiMeetJS/../../common/lib/tensor-conversion-impl.ts","webpack://JitsiMeetJS/../../common/lib/tensor-factory-impl.ts","webpack://JitsiMeetJS/../../common/lib/tensor-impl-type-mapping.ts","webpack://JitsiMeetJS/../../common/lib/tensor-utils-impl.ts","webpack://JitsiMeetJS/../../common/lib/tensor-impl.ts","webpack://JitsiMeetJS/../../common/lib/tensor.ts","webpack://JitsiMeetJS/../../common/lib/trace.ts","webpack://JitsiMeetJS/../../common/lib/inference-session-impl.ts","webpack://JitsiMeetJS/../../common/lib/inference-session.ts","webpack://JitsiMeetJS/../../common/lib/backend.ts","webpack://JitsiMeetJS/../../common/lib/tensor-conversion.ts","webpack://JitsiMeetJS/../../common/lib/tensor-factory.ts","webpack://JitsiMeetJS/../../common/lib/onnx-model.ts","webpack://JitsiMeetJS/../../common/lib/onnx-value.ts","webpack://JitsiMeetJS/../../common/lib/index.ts","webpack://JitsiMeetJS/../lib/wasm/wasm-utils-env.ts","webpack://JitsiMeetJS/../lib/wasm/proxy-worker/main.ts","webpack://JitsiMeetJS/../lib/wasm/wasm-utils-import.ts","webpack://JitsiMeetJS/../lib/wasm/wasm-factory.ts","webpack://JitsiMeetJS/../lib/wasm/wasm-utils.ts","webpack://JitsiMeetJS/../lib/wasm/run-options.ts","webpack://JitsiMeetJS/../lib/wasm/session-options.ts","webpack://JitsiMeetJS/../lib/wasm/wasm-common.ts","webpack://JitsiMeetJS/../lib/wasm/wasm-utils-load-file.ts","webpack://JitsiMeetJS/../lib/wasm/wasm-core-impl.ts","webpack://JitsiMeetJS/../lib/wasm/proxy-wrapper.ts","webpack://JitsiMeetJS/../lib/wasm/session-handler-inference.ts","webpack://JitsiMeetJS/../lib/backend-wasm.ts","webpack://JitsiMeetJS/../lib/index.ts","webpack://JitsiMeetJS/../lib/version.ts","webpack://JitsiMeetJS/./node_modules/sdp-transform/lib/grammar.js","webpack://JitsiMeetJS/./node_modules/sdp-transform/lib/index.js","webpack://JitsiMeetJS/./node_modules/sdp-transform/lib/parser.js","webpack://JitsiMeetJS/./node_modules/sdp-transform/lib/writer.js","webpack://JitsiMeetJS/./node_modules/sdp/sdp.js","webpack://JitsiMeetJS/./node_modules/strophe.js/dist/strophe.umd.js","webpack://JitsiMeetJS/./node_modules/ua-parser-js/src/ua-parser.js","webpack://JitsiMeetJS/./node_modules/vodozemac-wasm/javascript/pkg/vodozemac.js","webpack://JitsiMeetJS/./node_modules/onnxruntime-web/dist/ sync","webpack://JitsiMeetJS/webpack/bootstrap","webpack://JitsiMeetJS/webpack/runtime/amd options","webpack://JitsiMeetJS/webpack/runtime/compat get default export","webpack://JitsiMeetJS/webpack/runtime/define property getters","webpack://JitsiMeetJS/webpack/runtime/global","webpack://JitsiMeetJS/webpack/runtime/harmony module decorator","webpack://JitsiMeetJS/webpack/runtime/hasOwnProperty shorthand","webpack://JitsiMeetJS/webpack/runtime/make namespace object","webpack://JitsiMeetJS/webpack/runtime/publicPath","webpack://JitsiMeetJS/webpack/runtime/jsonp chunk loading","webpack://JitsiMeetJS/webpack/startup"],"sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"JitsiMeetJS\"] = factory();\n\telse\n\t\troot[\"JitsiMeetJS\"] = factory();\n})(self, () => {\nreturn ","/**\n * Removes all key-value entries from the list cache.\n *\n * @private\n * @name clear\n * @memberOf ListCache\n */\nfunction listCacheClear() {\n  this.__data__ = [];\n  this.size = 0;\n}\n\nexport default listCacheClear;\n","/**\n * Performs a\n * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n * comparison between two values to determine if they are equivalent.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @returns {boolean} Returns `true` if the values are equivalent, else `false`.\n * @example\n *\n * var object = { 'a': 1 };\n * var other = { 'a': 1 };\n *\n * _.eq(object, object);\n * // => true\n *\n * _.eq(object, other);\n * // => false\n *\n * _.eq('a', 'a');\n * // => true\n *\n * _.eq('a', Object('a'));\n * // => false\n *\n * _.eq(NaN, NaN);\n * // => true\n */\nfunction eq(value, other) {\n  return value === other || (value !== value && other !== other);\n}\n\nexport default eq;\n","import eq from './eq.js';\n\n/**\n * Gets the index at which the `key` is found in `array` of key-value pairs.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {*} key The key to search for.\n * @returns {number} Returns the index of the matched value, else `-1`.\n */\nfunction assocIndexOf(array, key) {\n  var length = array.length;\n  while (length--) {\n    if (eq(array[length][0], key)) {\n      return length;\n    }\n  }\n  return -1;\n}\n\nexport default assocIndexOf;\n","import assocIndexOf from './_assocIndexOf.js';\n\n/** Used for built-in method references. */\nvar arrayProto = Array.prototype;\n\n/** Built-in value references. */\nvar splice = arrayProto.splice;\n\n/**\n * Removes `key` and its value from the list cache.\n *\n * @private\n * @name delete\n * @memberOf ListCache\n * @param {string} key The key of the value to remove.\n * @returns {boolean} Returns `true` if the entry was removed, else `false`.\n */\nfunction listCacheDelete(key) {\n  var data = this.__data__,\n      index = assocIndexOf(data, key);\n\n  if (index < 0) {\n    return false;\n  }\n  var lastIndex = data.length - 1;\n  if (index == lastIndex) {\n    data.pop();\n  } else {\n    splice.call(data, index, 1);\n  }\n  --this.size;\n  return true;\n}\n\nexport default listCacheDelete;\n","import listCacheClear from './_listCacheClear.js';\nimport listCacheDelete from './_listCacheDelete.js';\nimport listCacheGet from './_listCacheGet.js';\nimport listCacheHas from './_listCacheHas.js';\nimport listCacheSet from './_listCacheSet.js';\n\n/**\n * Creates an list cache object.\n *\n * @private\n * @constructor\n * @param {Array} [entries] The key-value pairs to cache.\n */\nfunction ListCache(entries) {\n  var index = -1,\n      length = entries == null ? 0 : entries.length;\n\n  this.clear();\n  while (++index < length) {\n    var entry = entries[index];\n    this.set(entry[0], entry[1]);\n  }\n}\n\n// Add methods to `ListCache`.\nListCache.prototype.clear = listCacheClear;\nListCache.prototype['delete'] = listCacheDelete;\nListCache.prototype.get = listCacheGet;\nListCache.prototype.has = listCacheHas;\nListCache.prototype.set = listCacheSet;\n\nexport default ListCache;\n","import assocIndexOf from './_assocIndexOf.js';\n\n/**\n * Gets the list cache value for `key`.\n *\n * @private\n * @name get\n * @memberOf ListCache\n * @param {string} key The key of the value to get.\n * @returns {*} Returns the entry value.\n */\nfunction listCacheGet(key) {\n  var data = this.__data__,\n      index = assocIndexOf(data, key);\n\n  return index < 0 ? undefined : data[index][1];\n}\n\nexport default listCacheGet;\n","import assocIndexOf from './_assocIndexOf.js';\n\n/**\n * Checks if a list cache value for `key` exists.\n *\n * @private\n * @name has\n * @memberOf ListCache\n * @param {string} key The key of the entry to check.\n * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.\n */\nfunction listCacheHas(key) {\n  return assocIndexOf(this.__data__, key) > -1;\n}\n\nexport default listCacheHas;\n","import assocIndexOf from './_assocIndexOf.js';\n\n/**\n * Sets the list cache `key` to `value`.\n *\n * @private\n * @name set\n * @memberOf ListCache\n * @param {string} key The key of the value to set.\n * @param {*} value The value to set.\n * @returns {Object} Returns the list cache instance.\n */\nfunction listCacheSet(key, value) {\n  var data = this.__data__,\n      index = assocIndexOf(data, key);\n\n  if (index < 0) {\n    ++this.size;\n    data.push([key, value]);\n  } else {\n    data[index][1] = value;\n  }\n  return this;\n}\n\nexport default listCacheSet;\n","/** Detect free variable `global` from Node.js. */\nvar freeGlobal = typeof global == 'object' && global && global.Object === Object && global;\n\nexport default freeGlobal;\n","import freeGlobal from './_freeGlobal.js';\n\n/** Detect free variable `self`. */\nvar freeSelf = typeof self == 'object' && self && self.Object === Object && self;\n\n/** Used as a reference to the global object. */\nvar root = freeGlobal || freeSelf || Function('return this')();\n\nexport default root;\n","import root from './_root.js';\n\n/** Built-in value references. */\nvar Symbol = root.Symbol;\n\nexport default Symbol;\n","import Symbol from './_Symbol.js';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Used to resolve the\n * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar nativeObjectToString = objectProto.toString;\n\n/** Built-in value references. */\nvar symToStringTag = Symbol ? Symbol.toStringTag : undefined;\n\n/**\n * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.\n *\n * @private\n * @param {*} value The value to query.\n * @returns {string} Returns the raw `toStringTag`.\n */\nfunction getRawTag(value) {\n  var isOwn = hasOwnProperty.call(value, symToStringTag),\n      tag = value[symToStringTag];\n\n  try {\n    value[symToStringTag] = undefined;\n    var unmasked = true;\n  } catch (e) {}\n\n  var result = nativeObjectToString.call(value);\n  if (unmasked) {\n    if (isOwn) {\n      value[symToStringTag] = tag;\n    } else {\n      delete value[symToStringTag];\n    }\n  }\n  return result;\n}\n\nexport default getRawTag;\n","/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/**\n * Used to resolve the\n * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar nativeObjectToString = objectProto.toString;\n\n/**\n * Converts `value` to a string using `Object.prototype.toString`.\n *\n * @private\n * @param {*} value The value to convert.\n * @returns {string} Returns the converted string.\n */\nfunction objectToString(value) {\n  return nativeObjectToString.call(value);\n}\n\nexport default objectToString;\n","import Symbol from './_Symbol.js';\nimport getRawTag from './_getRawTag.js';\nimport objectToString from './_objectToString.js';\n\n/** `Object#toString` result references. */\nvar nullTag = '[object Null]',\n    undefinedTag = '[object Undefined]';\n\n/** Built-in value references. */\nvar symToStringTag = Symbol ? Symbol.toStringTag : undefined;\n\n/**\n * The base implementation of `getTag` without fallbacks for buggy environments.\n *\n * @private\n * @param {*} value The value to query.\n * @returns {string} Returns the `toStringTag`.\n */\nfunction baseGetTag(value) {\n  if (value == null) {\n    return value === undefined ? undefinedTag : nullTag;\n  }\n  return (symToStringTag && symToStringTag in Object(value))\n    ? getRawTag(value)\n    : objectToString(value);\n}\n\nexport default baseGetTag;\n","/**\n * Checks if `value` is the\n * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)\n * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an object, else `false`.\n * @example\n *\n * _.isObject({});\n * // => true\n *\n * _.isObject([1, 2, 3]);\n * // => true\n *\n * _.isObject(_.noop);\n * // => true\n *\n * _.isObject(null);\n * // => false\n */\nfunction isObject(value) {\n  var type = typeof value;\n  return value != null && (type == 'object' || type == 'function');\n}\n\nexport default isObject;\n","import baseGetTag from './_baseGetTag.js';\nimport isObject from './isObject.js';\n\n/** `Object#toString` result references. */\nvar asyncTag = '[object AsyncFunction]',\n    funcTag = '[object Function]',\n    genTag = '[object GeneratorFunction]',\n    proxyTag = '[object Proxy]';\n\n/**\n * Checks if `value` is classified as a `Function` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a function, else `false`.\n * @example\n *\n * _.isFunction(_);\n * // => true\n *\n * _.isFunction(/abc/);\n * // => false\n */\nfunction isFunction(value) {\n  if (!isObject(value)) {\n    return false;\n  }\n  // The use of `Object#toString` avoids issues with the `typeof` operator\n  // in Safari 9 which returns 'object' for typed arrays and other constructors.\n  var tag = baseGetTag(value);\n  return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag;\n}\n\nexport default isFunction;\n","import root from './_root.js';\n\n/** Used to detect overreaching core-js shims. */\nvar coreJsData = root['__core-js_shared__'];\n\nexport default coreJsData;\n","import coreJsData from './_coreJsData.js';\n\n/** Used to detect methods masquerading as native. */\nvar maskSrcKey = (function() {\n  var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || '');\n  return uid ? ('Symbol(src)_1.' + uid) : '';\n}());\n\n/**\n * Checks if `func` has its source masked.\n *\n * @private\n * @param {Function} func The function to check.\n * @returns {boolean} Returns `true` if `func` is masked, else `false`.\n */\nfunction isMasked(func) {\n  return !!maskSrcKey && (maskSrcKey in func);\n}\n\nexport default isMasked;\n","/** Used for built-in method references. */\nvar funcProto = Function.prototype;\n\n/** Used to resolve the decompiled source of functions. */\nvar funcToString = funcProto.toString;\n\n/**\n * Converts `func` to its source code.\n *\n * @private\n * @param {Function} func The function to convert.\n * @returns {string} Returns the source code.\n */\nfunction toSource(func) {\n  if (func != null) {\n    try {\n      return funcToString.call(func);\n    } catch (e) {}\n    try {\n      return (func + '');\n    } catch (e) {}\n  }\n  return '';\n}\n\nexport default toSource;\n","import isFunction from './isFunction.js';\nimport isMasked from './_isMasked.js';\nimport isObject from './isObject.js';\nimport toSource from './_toSource.js';\n\n/**\n * Used to match `RegExp`\n * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).\n */\nvar reRegExpChar = /[\\\\^$.*+?()[\\]{}|]/g;\n\n/** Used to detect host constructors (Safari). */\nvar reIsHostCtor = /^\\[object .+?Constructor\\]$/;\n\n/** Used for built-in method references. */\nvar funcProto = Function.prototype,\n    objectProto = Object.prototype;\n\n/** Used to resolve the decompiled source of functions. */\nvar funcToString = funcProto.toString;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/** Used to detect if a method is native. */\nvar reIsNative = RegExp('^' +\n  funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\\\$&')\n  .replace(/hasOwnProperty|(function).*?(?=\\\\\\()| for .+?(?=\\\\\\])/g, '$1.*?') + '$'\n);\n\n/**\n * The base implementation of `_.isNative` without bad shim checks.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a native function,\n *  else `false`.\n */\nfunction baseIsNative(value) {\n  if (!isObject(value) || isMasked(value)) {\n    return false;\n  }\n  var pattern = isFunction(value) ? reIsNative : reIsHostCtor;\n  return pattern.test(toSource(value));\n}\n\nexport default baseIsNative;\n","import baseIsNative from './_baseIsNative.js';\nimport getValue from './_getValue.js';\n\n/**\n * Gets the native function at `key` of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @param {string} key The key of the method to get.\n * @returns {*} Returns the function if it's native, else `undefined`.\n */\nfunction getNative(object, key) {\n  var value = getValue(object, key);\n  return baseIsNative(value) ? value : undefined;\n}\n\nexport default getNative;\n","/**\n * Gets the value at `key` of `object`.\n *\n * @private\n * @param {Object} [object] The object to query.\n * @param {string} key The key of the property to get.\n * @returns {*} Returns the property value.\n */\nfunction getValue(object, key) {\n  return object == null ? undefined : object[key];\n}\n\nexport default getValue;\n","import getNative from './_getNative.js';\nimport root from './_root.js';\n\n/* Built-in method references that are verified to be native. */\nvar Map = getNative(root, 'Map');\n\nexport default Map;\n","import getNative from './_getNative.js';\n\n/* Built-in method references that are verified to be native. */\nvar nativeCreate = getNative(Object, 'create');\n\nexport default nativeCreate;\n","import nativeCreate from './_nativeCreate.js';\n\n/** Used to stand-in for `undefined` hash values. */\nvar HASH_UNDEFINED = '__lodash_hash_undefined__';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Gets the hash value for `key`.\n *\n * @private\n * @name get\n * @memberOf Hash\n * @param {string} key The key of the value to get.\n * @returns {*} Returns the entry value.\n */\nfunction hashGet(key) {\n  var data = this.__data__;\n  if (nativeCreate) {\n    var result = data[key];\n    return result === HASH_UNDEFINED ? undefined : result;\n  }\n  return hasOwnProperty.call(data, key) ? data[key] : undefined;\n}\n\nexport default hashGet;\n","import nativeCreate from './_nativeCreate.js';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Checks if a hash value for `key` exists.\n *\n * @private\n * @name has\n * @memberOf Hash\n * @param {string} key The key of the entry to check.\n * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.\n */\nfunction hashHas(key) {\n  var data = this.__data__;\n  return nativeCreate ? (data[key] !== undefined) : hasOwnProperty.call(data, key);\n}\n\nexport default hashHas;\n","import hashClear from './_hashClear.js';\nimport hashDelete from './_hashDelete.js';\nimport hashGet from './_hashGet.js';\nimport hashHas from './_hashHas.js';\nimport hashSet from './_hashSet.js';\n\n/**\n * Creates a hash object.\n *\n * @private\n * @constructor\n * @param {Array} [entries] The key-value pairs to cache.\n */\nfunction Hash(entries) {\n  var index = -1,\n      length = entries == null ? 0 : entries.length;\n\n  this.clear();\n  while (++index < length) {\n    var entry = entries[index];\n    this.set(entry[0], entry[1]);\n  }\n}\n\n// Add methods to `Hash`.\nHash.prototype.clear = hashClear;\nHash.prototype['delete'] = hashDelete;\nHash.prototype.get = hashGet;\nHash.prototype.has = hashHas;\nHash.prototype.set = hashSet;\n\nexport default Hash;\n","import nativeCreate from './_nativeCreate.js';\n\n/**\n * Removes all key-value entries from the hash.\n *\n * @private\n * @name clear\n * @memberOf Hash\n */\nfunction hashClear() {\n  this.__data__ = nativeCreate ? nativeCreate(null) : {};\n  this.size = 0;\n}\n\nexport default hashClear;\n","/**\n * Removes `key` and its value from the hash.\n *\n * @private\n * @name delete\n * @memberOf Hash\n * @param {Object} hash The hash to modify.\n * @param {string} key The key of the value to remove.\n * @returns {boolean} Returns `true` if the entry was removed, else `false`.\n */\nfunction hashDelete(key) {\n  var result = this.has(key) && delete this.__data__[key];\n  this.size -= result ? 1 : 0;\n  return result;\n}\n\nexport default hashDelete;\n","import nativeCreate from './_nativeCreate.js';\n\n/** Used to stand-in for `undefined` hash values. */\nvar HASH_UNDEFINED = '__lodash_hash_undefined__';\n\n/**\n * Sets the hash `key` to `value`.\n *\n * @private\n * @name set\n * @memberOf Hash\n * @param {string} key The key of the value to set.\n * @param {*} value The value to set.\n * @returns {Object} Returns the hash instance.\n */\nfunction hashSet(key, value) {\n  var data = this.__data__;\n  this.size += this.has(key) ? 0 : 1;\n  data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value;\n  return this;\n}\n\nexport default hashSet;\n","import isKeyable from './_isKeyable.js';\n\n/**\n * Gets the data for `map`.\n *\n * @private\n * @param {Object} map The map to query.\n * @param {string} key The reference key.\n * @returns {*} Returns the map data.\n */\nfunction getMapData(map, key) {\n  var data = map.__data__;\n  return isKeyable(key)\n    ? data[typeof key == 'string' ? 'string' : 'hash']\n    : data.map;\n}\n\nexport default getMapData;\n","/**\n * Checks if `value` is suitable for use as unique object key.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is suitable, else `false`.\n */\nfunction isKeyable(value) {\n  var type = typeof value;\n  return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean')\n    ? (value !== '__proto__')\n    : (value === null);\n}\n\nexport default isKeyable;\n","import mapCacheClear from './_mapCacheClear.js';\nimport mapCacheDelete from './_mapCacheDelete.js';\nimport mapCacheGet from './_mapCacheGet.js';\nimport mapCacheHas from './_mapCacheHas.js';\nimport mapCacheSet from './_mapCacheSet.js';\n\n/**\n * Creates a map cache object to store key-value pairs.\n *\n * @private\n * @constructor\n * @param {Array} [entries] The key-value pairs to cache.\n */\nfunction MapCache(entries) {\n  var index = -1,\n      length = entries == null ? 0 : entries.length;\n\n  this.clear();\n  while (++index < length) {\n    var entry = entries[index];\n    this.set(entry[0], entry[1]);\n  }\n}\n\n// Add methods to `MapCache`.\nMapCache.prototype.clear = mapCacheClear;\nMapCache.prototype['delete'] = mapCacheDelete;\nMapCache.prototype.get = mapCacheGet;\nMapCache.prototype.has = mapCacheHas;\nMapCache.prototype.set = mapCacheSet;\n\nexport default MapCache;\n","import Hash from './_Hash.js';\nimport ListCache from './_ListCache.js';\nimport Map from './_Map.js';\n\n/**\n * Removes all key-value entries from the map.\n *\n * @private\n * @name clear\n * @memberOf MapCache\n */\nfunction mapCacheClear() {\n  this.size = 0;\n  this.__data__ = {\n    'hash': new Hash,\n    'map': new (Map || ListCache),\n    'string': new Hash\n  };\n}\n\nexport default mapCacheClear;\n","import getMapData from './_getMapData.js';\n\n/**\n * Removes `key` and its value from the map.\n *\n * @private\n * @name delete\n * @memberOf MapCache\n * @param {string} key The key of the value to remove.\n * @returns {boolean} Returns `true` if the entry was removed, else `false`.\n */\nfunction mapCacheDelete(key) {\n  var result = getMapData(this, key)['delete'](key);\n  this.size -= result ? 1 : 0;\n  return result;\n}\n\nexport default mapCacheDelete;\n","import getMapData from './_getMapData.js';\n\n/**\n * Gets the map value for `key`.\n *\n * @private\n * @name get\n * @memberOf MapCache\n * @param {string} key The key of the value to get.\n * @returns {*} Returns the entry value.\n */\nfunction mapCacheGet(key) {\n  return getMapData(this, key).get(key);\n}\n\nexport default mapCacheGet;\n","import getMapData from './_getMapData.js';\n\n/**\n * Checks if a map value for `key` exists.\n *\n * @private\n * @name has\n * @memberOf MapCache\n * @param {string} key The key of the entry to check.\n * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.\n */\nfunction mapCacheHas(key) {\n  return getMapData(this, key).has(key);\n}\n\nexport default mapCacheHas;\n","import getMapData from './_getMapData.js';\n\n/**\n * Sets the map `key` to `value`.\n *\n * @private\n * @name set\n * @memberOf MapCache\n * @param {string} key The key of the value to set.\n * @param {*} value The value to set.\n * @returns {Object} Returns the map cache instance.\n */\nfunction mapCacheSet(key, value) {\n  var data = getMapData(this, key),\n      size = data.size;\n\n  data.set(key, value);\n  this.size += data.size == size ? 0 : 1;\n  return this;\n}\n\nexport default mapCacheSet;\n","import ListCache from './_ListCache.js';\nimport stackClear from './_stackClear.js';\nimport stackDelete from './_stackDelete.js';\nimport stackGet from './_stackGet.js';\nimport stackHas from './_stackHas.js';\nimport stackSet from './_stackSet.js';\n\n/**\n * Creates a stack cache object to store key-value pairs.\n *\n * @private\n * @constructor\n * @param {Array} [entries] The key-value pairs to cache.\n */\nfunction Stack(entries) {\n  var data = this.__data__ = new ListCache(entries);\n  this.size = data.size;\n}\n\n// Add methods to `Stack`.\nStack.prototype.clear = stackClear;\nStack.prototype['delete'] = stackDelete;\nStack.prototype.get = stackGet;\nStack.prototype.has = stackHas;\nStack.prototype.set = stackSet;\n\nexport default Stack;\n","import ListCache from './_ListCache.js';\n\n/**\n * Removes all key-value entries from the stack.\n *\n * @private\n * @name clear\n * @memberOf Stack\n */\nfunction stackClear() {\n  this.__data__ = new ListCache;\n  this.size = 0;\n}\n\nexport default stackClear;\n","/**\n * Removes `key` and its value from the stack.\n *\n * @private\n * @name delete\n * @memberOf Stack\n * @param {string} key The key of the value to remove.\n * @returns {boolean} Returns `true` if the entry was removed, else `false`.\n */\nfunction stackDelete(key) {\n  var data = this.__data__,\n      result = data['delete'](key);\n\n  this.size = data.size;\n  return result;\n}\n\nexport default stackDelete;\n","/**\n * Gets the stack value for `key`.\n *\n * @private\n * @name get\n * @memberOf Stack\n * @param {string} key The key of the value to get.\n * @returns {*} Returns the entry value.\n */\nfunction stackGet(key) {\n  return this.__data__.get(key);\n}\n\nexport default stackGet;\n","/**\n * Checks if a stack value for `key` exists.\n *\n * @private\n * @name has\n * @memberOf Stack\n * @param {string} key The key of the entry to check.\n * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.\n */\nfunction stackHas(key) {\n  return this.__data__.has(key);\n}\n\nexport default stackHas;\n","import ListCache from './_ListCache.js';\nimport Map from './_Map.js';\nimport MapCache from './_MapCache.js';\n\n/** Used as the size to enable large array optimizations. */\nvar LARGE_ARRAY_SIZE = 200;\n\n/**\n * Sets the stack `key` to `value`.\n *\n * @private\n * @name set\n * @memberOf Stack\n * @param {string} key The key of the value to set.\n * @param {*} value The value to set.\n * @returns {Object} Returns the stack cache instance.\n */\nfunction stackSet(key, value) {\n  var data = this.__data__;\n  if (data instanceof ListCache) {\n    var pairs = data.__data__;\n    if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) {\n      pairs.push([key, value]);\n      this.size = ++data.size;\n      return this;\n    }\n    data = this.__data__ = new MapCache(pairs);\n  }\n  data.set(key, value);\n  this.size = data.size;\n  return this;\n}\n\nexport default stackSet;\n","import getNative from './_getNative.js';\n\nvar defineProperty = (function() {\n  try {\n    var func = getNative(Object, 'defineProperty');\n    func({}, '', {});\n    return func;\n  } catch (e) {}\n}());\n\nexport default defineProperty;\n","import defineProperty from './_defineProperty.js';\n\n/**\n * The base implementation of `assignValue` and `assignMergeValue` without\n * value checks.\n *\n * @private\n * @param {Object} object The object to modify.\n * @param {string} key The key of the property to assign.\n * @param {*} value The value to assign.\n */\nfunction baseAssignValue(object, key, value) {\n  if (key == '__proto__' && defineProperty) {\n    defineProperty(object, key, {\n      'configurable': true,\n      'enumerable': true,\n      'value': value,\n      'writable': true\n    });\n  } else {\n    object[key] = value;\n  }\n}\n\nexport default baseAssignValue;\n","import baseAssignValue from './_baseAssignValue.js';\nimport eq from './eq.js';\n\n/**\n * This function is like `assignValue` except that it doesn't assign\n * `undefined` values.\n *\n * @private\n * @param {Object} object The object to modify.\n * @param {string} key The key of the property to assign.\n * @param {*} value The value to assign.\n */\nfunction assignMergeValue(object, key, value) {\n  if ((value !== undefined && !eq(object[key], value)) ||\n      (value === undefined && !(key in object))) {\n    baseAssignValue(object, key, value);\n  }\n}\n\nexport default assignMergeValue;\n","import createBaseFor from './_createBaseFor.js';\n\n/**\n * The base implementation of `baseForOwn` which iterates over `object`\n * properties returned by `keysFunc` and invokes `iteratee` for each property.\n * Iteratee functions may exit iteration early by explicitly returning `false`.\n *\n * @private\n * @param {Object} object The object to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @param {Function} keysFunc The function to get the keys of `object`.\n * @returns {Object} Returns `object`.\n */\nvar baseFor = createBaseFor();\n\nexport default baseFor;\n","/**\n * Creates a base function for methods like `_.forIn` and `_.forOwn`.\n *\n * @private\n * @param {boolean} [fromRight] Specify iterating from right to left.\n * @returns {Function} Returns the new base function.\n */\nfunction createBaseFor(fromRight) {\n  return function(object, iteratee, keysFunc) {\n    var index = -1,\n        iterable = Object(object),\n        props = keysFunc(object),\n        length = props.length;\n\n    while (length--) {\n      var key = props[fromRight ? length : ++index];\n      if (iteratee(iterable[key], key, iterable) === false) {\n        break;\n      }\n    }\n    return object;\n  };\n}\n\nexport default createBaseFor;\n","import root from './_root.js';\n\n/** Detect free variable `exports`. */\nvar freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;\n\n/** Detect free variable `module`. */\nvar freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;\n\n/** Detect the popular CommonJS extension `module.exports`. */\nvar moduleExports = freeModule && freeModule.exports === freeExports;\n\n/** Built-in value references. */\nvar Buffer = moduleExports ? root.Buffer : undefined,\n    allocUnsafe = Buffer ? Buffer.allocUnsafe : undefined;\n\n/**\n * Creates a clone of  `buffer`.\n *\n * @private\n * @param {Buffer} buffer The buffer to clone.\n * @param {boolean} [isDeep] Specify a deep clone.\n * @returns {Buffer} Returns the cloned buffer.\n */\nfunction cloneBuffer(buffer, isDeep) {\n  if (isDeep) {\n    return buffer.slice();\n  }\n  var length = buffer.length,\n      result = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length);\n\n  buffer.copy(result);\n  return result;\n}\n\nexport default cloneBuffer;\n","import root from './_root.js';\n\n/** Built-in value references. */\nvar Uint8Array = root.Uint8Array;\n\nexport default Uint8Array;\n","import Uint8Array from './_Uint8Array.js';\n\n/**\n * Creates a clone of `arrayBuffer`.\n *\n * @private\n * @param {ArrayBuffer} arrayBuffer The array buffer to clone.\n * @returns {ArrayBuffer} Returns the cloned array buffer.\n */\nfunction cloneArrayBuffer(arrayBuffer) {\n  var result = new arrayBuffer.constructor(arrayBuffer.byteLength);\n  new Uint8Array(result).set(new Uint8Array(arrayBuffer));\n  return result;\n}\n\nexport default cloneArrayBuffer;\n","import cloneArrayBuffer from './_cloneArrayBuffer.js';\n\n/**\n * Creates a clone of `typedArray`.\n *\n * @private\n * @param {Object} typedArray The typed array to clone.\n * @param {boolean} [isDeep] Specify a deep clone.\n * @returns {Object} Returns the cloned typed array.\n */\nfunction cloneTypedArray(typedArray, isDeep) {\n  var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer;\n  return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length);\n}\n\nexport default cloneTypedArray;\n","/**\n * Copies the values of `source` to `array`.\n *\n * @private\n * @param {Array} source The array to copy values from.\n * @param {Array} [array=[]] The array to copy values to.\n * @returns {Array} Returns `array`.\n */\nfunction copyArray(source, array) {\n  var index = -1,\n      length = source.length;\n\n  array || (array = Array(length));\n  while (++index < length) {\n    array[index] = source[index];\n  }\n  return array;\n}\n\nexport default copyArray;\n","import isObject from './isObject.js';\n\n/** Built-in value references. */\nvar objectCreate = Object.create;\n\n/**\n * The base implementation of `_.create` without support for assigning\n * properties to the created object.\n *\n * @private\n * @param {Object} proto The object to inherit from.\n * @returns {Object} Returns the new object.\n */\nvar baseCreate = (function() {\n  function object() {}\n  return function(proto) {\n    if (!isObject(proto)) {\n      return {};\n    }\n    if (objectCreate) {\n      return objectCreate(proto);\n    }\n    object.prototype = proto;\n    var result = new object;\n    object.prototype = undefined;\n    return result;\n  };\n}());\n\nexport default baseCreate;\n","/**\n * Creates a unary function that invokes `func` with its argument transformed.\n *\n * @private\n * @param {Function} func The function to wrap.\n * @param {Function} transform The argument transform.\n * @returns {Function} Returns the new function.\n */\nfunction overArg(func, transform) {\n  return function(arg) {\n    return func(transform(arg));\n  };\n}\n\nexport default overArg;\n","import overArg from './_overArg.js';\n\n/** Built-in value references. */\nvar getPrototype = overArg(Object.getPrototypeOf, Object);\n\nexport default getPrototype;\n","/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/**\n * Checks if `value` is likely a prototype object.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a prototype, else `false`.\n */\nfunction isPrototype(value) {\n  var Ctor = value && value.constructor,\n      proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto;\n\n  return value === proto;\n}\n\nexport default isPrototype;\n","import baseCreate from './_baseCreate.js';\nimport getPrototype from './_getPrototype.js';\nimport isPrototype from './_isPrototype.js';\n\n/**\n * Initializes an object clone.\n *\n * @private\n * @param {Object} object The object to clone.\n * @returns {Object} Returns the initialized clone.\n */\nfunction initCloneObject(object) {\n  return (typeof object.constructor == 'function' && !isPrototype(object))\n    ? baseCreate(getPrototype(object))\n    : {};\n}\n\nexport default initCloneObject;\n","/**\n * Checks if `value` is object-like. A value is object-like if it's not `null`\n * and has a `typeof` result of \"object\".\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is object-like, else `false`.\n * @example\n *\n * _.isObjectLike({});\n * // => true\n *\n * _.isObjectLike([1, 2, 3]);\n * // => true\n *\n * _.isObjectLike(_.noop);\n * // => false\n *\n * _.isObjectLike(null);\n * // => false\n */\nfunction isObjectLike(value) {\n  return value != null && typeof value == 'object';\n}\n\nexport default isObjectLike;\n","import baseGetTag from './_baseGetTag.js';\nimport isObjectLike from './isObjectLike.js';\n\n/** `Object#toString` result references. */\nvar argsTag = '[object Arguments]';\n\n/**\n * The base implementation of `_.isArguments`.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an `arguments` object,\n */\nfunction baseIsArguments(value) {\n  return isObjectLike(value) && baseGetTag(value) == argsTag;\n}\n\nexport default baseIsArguments;\n","import baseIsArguments from './_baseIsArguments.js';\nimport isObjectLike from './isObjectLike.js';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/** Built-in value references. */\nvar propertyIsEnumerable = objectProto.propertyIsEnumerable;\n\n/**\n * Checks if `value` is likely an `arguments` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an `arguments` object,\n *  else `false`.\n * @example\n *\n * _.isArguments(function() { return arguments; }());\n * // => true\n *\n * _.isArguments([1, 2, 3]);\n * // => false\n */\nvar isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) {\n  return isObjectLike(value) && hasOwnProperty.call(value, 'callee') &&\n    !propertyIsEnumerable.call(value, 'callee');\n};\n\nexport default isArguments;\n","/**\n * Checks if `value` is classified as an `Array` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an array, else `false`.\n * @example\n *\n * _.isArray([1, 2, 3]);\n * // => true\n *\n * _.isArray(document.body.children);\n * // => false\n *\n * _.isArray('abc');\n * // => false\n *\n * _.isArray(_.noop);\n * // => false\n */\nvar isArray = Array.isArray;\n\nexport default isArray;\n","/** Used as references for various `Number` constants. */\nvar MAX_SAFE_INTEGER = 9007199254740991;\n\n/**\n * Checks if `value` is a valid array-like length.\n *\n * **Note:** This method is loosely based on\n * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.\n * @example\n *\n * _.isLength(3);\n * // => true\n *\n * _.isLength(Number.MIN_VALUE);\n * // => false\n *\n * _.isLength(Infinity);\n * // => false\n *\n * _.isLength('3');\n * // => false\n */\nfunction isLength(value) {\n  return typeof value == 'number' &&\n    value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;\n}\n\nexport default isLength;\n","import isFunction from './isFunction.js';\nimport isLength from './isLength.js';\n\n/**\n * Checks if `value` is array-like. A value is considered array-like if it's\n * not a function and has a `value.length` that's an integer greater than or\n * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is array-like, else `false`.\n * @example\n *\n * _.isArrayLike([1, 2, 3]);\n * // => true\n *\n * _.isArrayLike(document.body.children);\n * // => true\n *\n * _.isArrayLike('abc');\n * // => true\n *\n * _.isArrayLike(_.noop);\n * // => false\n */\nfunction isArrayLike(value) {\n  return value != null && isLength(value.length) && !isFunction(value);\n}\n\nexport default isArrayLike;\n","import root from './_root.js';\nimport stubFalse from './stubFalse.js';\n\n/** Detect free variable `exports`. */\nvar freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;\n\n/** Detect free variable `module`. */\nvar freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;\n\n/** Detect the popular CommonJS extension `module.exports`. */\nvar moduleExports = freeModule && freeModule.exports === freeExports;\n\n/** Built-in value references. */\nvar Buffer = moduleExports ? root.Buffer : undefined;\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined;\n\n/**\n * Checks if `value` is a buffer.\n *\n * @static\n * @memberOf _\n * @since 4.3.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a buffer, else `false`.\n * @example\n *\n * _.isBuffer(new Buffer(2));\n * // => true\n *\n * _.isBuffer(new Uint8Array(2));\n * // => false\n */\nvar isBuffer = nativeIsBuffer || stubFalse;\n\nexport default isBuffer;\n","/**\n * This method returns `false`.\n *\n * @static\n * @memberOf _\n * @since 4.13.0\n * @category Util\n * @returns {boolean} Returns `false`.\n * @example\n *\n * _.times(2, _.stubFalse);\n * // => [false, false]\n */\nfunction stubFalse() {\n  return false;\n}\n\nexport default stubFalse;\n","import baseGetTag from './_baseGetTag.js';\nimport getPrototype from './_getPrototype.js';\nimport isObjectLike from './isObjectLike.js';\n\n/** `Object#toString` result references. */\nvar objectTag = '[object Object]';\n\n/** Used for built-in method references. */\nvar funcProto = Function.prototype,\n    objectProto = Object.prototype;\n\n/** Used to resolve the decompiled source of functions. */\nvar funcToString = funcProto.toString;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/** Used to infer the `Object` constructor. */\nvar objectCtorString = funcToString.call(Object);\n\n/**\n * Checks if `value` is a plain object, that is, an object created by the\n * `Object` constructor or one with a `[[Prototype]]` of `null`.\n *\n * @static\n * @memberOf _\n * @since 0.8.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.\n * @example\n *\n * function Foo() {\n *   this.a = 1;\n * }\n *\n * _.isPlainObject(new Foo);\n * // => false\n *\n * _.isPlainObject([1, 2, 3]);\n * // => false\n *\n * _.isPlainObject({ 'x': 0, 'y': 0 });\n * // => true\n *\n * _.isPlainObject(Object.create(null));\n * // => true\n */\nfunction isPlainObject(value) {\n  if (!isObjectLike(value) || baseGetTag(value) != objectTag) {\n    return false;\n  }\n  var proto = getPrototype(value);\n  if (proto === null) {\n    return true;\n  }\n  var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor;\n  return typeof Ctor == 'function' && Ctor instanceof Ctor &&\n    funcToString.call(Ctor) == objectCtorString;\n}\n\nexport default isPlainObject;\n","import baseGetTag from './_baseGetTag.js';\nimport isLength from './isLength.js';\nimport isObjectLike from './isObjectLike.js';\n\n/** `Object#toString` result references. */\nvar argsTag = '[object Arguments]',\n    arrayTag = '[object Array]',\n    boolTag = '[object Boolean]',\n    dateTag = '[object Date]',\n    errorTag = '[object Error]',\n    funcTag = '[object Function]',\n    mapTag = '[object Map]',\n    numberTag = '[object Number]',\n    objectTag = '[object Object]',\n    regexpTag = '[object RegExp]',\n    setTag = '[object Set]',\n    stringTag = '[object String]',\n    weakMapTag = '[object WeakMap]';\n\nvar arrayBufferTag = '[object ArrayBuffer]',\n    dataViewTag = '[object DataView]',\n    float32Tag = '[object Float32Array]',\n    float64Tag = '[object Float64Array]',\n    int8Tag = '[object Int8Array]',\n    int16Tag = '[object Int16Array]',\n    int32Tag = '[object Int32Array]',\n    uint8Tag = '[object Uint8Array]',\n    uint8ClampedTag = '[object Uint8ClampedArray]',\n    uint16Tag = '[object Uint16Array]',\n    uint32Tag = '[object Uint32Array]';\n\n/** Used to identify `toStringTag` values of typed arrays. */\nvar typedArrayTags = {};\ntypedArrayTags[float32Tag] = typedArrayTags[float64Tag] =\ntypedArrayTags[int8Tag] = typedArrayTags[int16Tag] =\ntypedArrayTags[int32Tag] = typedArrayTags[uint8Tag] =\ntypedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] =\ntypedArrayTags[uint32Tag] = true;\ntypedArrayTags[argsTag] = typedArrayTags[arrayTag] =\ntypedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =\ntypedArrayTags[dataViewTag] = typedArrayTags[dateTag] =\ntypedArrayTags[errorTag] = typedArrayTags[funcTag] =\ntypedArrayTags[mapTag] = typedArrayTags[numberTag] =\ntypedArrayTags[objectTag] = typedArrayTags[regexpTag] =\ntypedArrayTags[setTag] = typedArrayTags[stringTag] =\ntypedArrayTags[weakMapTag] = false;\n\n/**\n * The base implementation of `_.isTypedArray` without Node.js optimizations.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.\n */\nfunction baseIsTypedArray(value) {\n  return isObjectLike(value) &&\n    isLength(value.length) && !!typedArrayTags[baseGetTag(value)];\n}\n\nexport default baseIsTypedArray;\n","/**\n * The base implementation of `_.unary` without support for storing metadata.\n *\n * @private\n * @param {Function} func The function to cap arguments for.\n * @returns {Function} Returns the new capped function.\n */\nfunction baseUnary(func) {\n  return function(value) {\n    return func(value);\n  };\n}\n\nexport default baseUnary;\n","import freeGlobal from './_freeGlobal.js';\n\n/** Detect free variable `exports`. */\nvar freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;\n\n/** Detect free variable `module`. */\nvar freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;\n\n/** Detect the popular CommonJS extension `module.exports`. */\nvar moduleExports = freeModule && freeModule.exports === freeExports;\n\n/** Detect free variable `process` from Node.js. */\nvar freeProcess = moduleExports && freeGlobal.process;\n\n/** Used to access faster Node.js helpers. */\nvar nodeUtil = (function() {\n  try {\n    // Use `util.types` for Node.js 10+.\n    var types = freeModule && freeModule.require && freeModule.require('util').types;\n\n    if (types) {\n      return types;\n    }\n\n    // Legacy `process.binding('util')` for Node.js < 10.\n    return freeProcess && freeProcess.binding && freeProcess.binding('util');\n  } catch (e) {}\n}());\n\nexport default nodeUtil;\n","import baseIsTypedArray from './_baseIsTypedArray.js';\nimport baseUnary from './_baseUnary.js';\nimport nodeUtil from './_nodeUtil.js';\n\n/* Node.js helper references. */\nvar nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray;\n\n/**\n * Checks if `value` is classified as a typed array.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.\n * @example\n *\n * _.isTypedArray(new Uint8Array);\n * // => true\n *\n * _.isTypedArray([]);\n * // => false\n */\nvar isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray;\n\nexport default isTypedArray;\n","/**\n * Gets the value at `key`, unless `key` is \"__proto__\" or \"constructor\".\n *\n * @private\n * @param {Object} object The object to query.\n * @param {string} key The key of the property to get.\n * @returns {*} Returns the property value.\n */\nfunction safeGet(object, key) {\n  if (key === 'constructor' && typeof object[key] === 'function') {\n    return;\n  }\n\n  if (key == '__proto__') {\n    return;\n  }\n\n  return object[key];\n}\n\nexport default safeGet;\n","import baseAssignValue from './_baseAssignValue.js';\nimport eq from './eq.js';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Assigns `value` to `key` of `object` if the existing value is not equivalent\n * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n * for equality comparisons.\n *\n * @private\n * @param {Object} object The object to modify.\n * @param {string} key The key of the property to assign.\n * @param {*} value The value to assign.\n */\nfunction assignValue(object, key, value) {\n  var objValue = object[key];\n  if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) ||\n      (value === undefined && !(key in object))) {\n    baseAssignValue(object, key, value);\n  }\n}\n\nexport default assignValue;\n","import assignValue from './_assignValue.js';\nimport baseAssignValue from './_baseAssignValue.js';\n\n/**\n * Copies properties of `source` to `object`.\n *\n * @private\n * @param {Object} source The object to copy properties from.\n * @param {Array} props The property identifiers to copy.\n * @param {Object} [object={}] The object to copy properties to.\n * @param {Function} [customizer] The function to customize copied values.\n * @returns {Object} Returns `object`.\n */\nfunction copyObject(source, props, object, customizer) {\n  var isNew = !object;\n  object || (object = {});\n\n  var index = -1,\n      length = props.length;\n\n  while (++index < length) {\n    var key = props[index];\n\n    var newValue = customizer\n      ? customizer(object[key], source[key], key, object, source)\n      : undefined;\n\n    if (newValue === undefined) {\n      newValue = source[key];\n    }\n    if (isNew) {\n      baseAssignValue(object, key, newValue);\n    } else {\n      assignValue(object, key, newValue);\n    }\n  }\n  return object;\n}\n\nexport default copyObject;\n","/** Used as references for various `Number` constants. */\nvar MAX_SAFE_INTEGER = 9007199254740991;\n\n/** Used to detect unsigned integer values. */\nvar reIsUint = /^(?:0|[1-9]\\d*)$/;\n\n/**\n * Checks if `value` is a valid array-like index.\n *\n * @private\n * @param {*} value The value to check.\n * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.\n * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.\n */\nfunction isIndex(value, length) {\n  var type = typeof value;\n  length = length == null ? MAX_SAFE_INTEGER : length;\n\n  return !!length &&\n    (type == 'number' ||\n      (type != 'symbol' && reIsUint.test(value))) &&\n        (value > -1 && value % 1 == 0 && value < length);\n}\n\nexport default isIndex;\n","import baseTimes from './_baseTimes.js';\nimport isArguments from './isArguments.js';\nimport isArray from './isArray.js';\nimport isBuffer from './isBuffer.js';\nimport isIndex from './_isIndex.js';\nimport isTypedArray from './isTypedArray.js';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Creates an array of the enumerable property names of the array-like `value`.\n *\n * @private\n * @param {*} value The value to query.\n * @param {boolean} inherited Specify returning inherited property names.\n * @returns {Array} Returns the array of property names.\n */\nfunction arrayLikeKeys(value, inherited) {\n  var isArr = isArray(value),\n      isArg = !isArr && isArguments(value),\n      isBuff = !isArr && !isArg && isBuffer(value),\n      isType = !isArr && !isArg && !isBuff && isTypedArray(value),\n      skipIndexes = isArr || isArg || isBuff || isType,\n      result = skipIndexes ? baseTimes(value.length, String) : [],\n      length = result.length;\n\n  for (var key in value) {\n    if ((inherited || hasOwnProperty.call(value, key)) &&\n        !(skipIndexes && (\n           // Safari 9 has enumerable `arguments.length` in strict mode.\n           key == 'length' ||\n           // Node.js 0.10 has enumerable non-index properties on buffers.\n           (isBuff && (key == 'offset' || key == 'parent')) ||\n           // PhantomJS 2 has enumerable non-index properties on typed arrays.\n           (isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) ||\n           // Skip index properties.\n           isIndex(key, length)\n        ))) {\n      result.push(key);\n    }\n  }\n  return result;\n}\n\nexport default arrayLikeKeys;\n","/**\n * The base implementation of `_.times` without support for iteratee shorthands\n * or max array length checks.\n *\n * @private\n * @param {number} n The number of times to invoke `iteratee`.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns the array of results.\n */\nfunction baseTimes(n, iteratee) {\n  var index = -1,\n      result = Array(n);\n\n  while (++index < n) {\n    result[index] = iteratee(index);\n  }\n  return result;\n}\n\nexport default baseTimes;\n","import isObject from './isObject.js';\nimport isPrototype from './_isPrototype.js';\nimport nativeKeysIn from './_nativeKeysIn.js';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n */\nfunction baseKeysIn(object) {\n  if (!isObject(object)) {\n    return nativeKeysIn(object);\n  }\n  var isProto = isPrototype(object),\n      result = [];\n\n  for (var key in object) {\n    if (!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) {\n      result.push(key);\n    }\n  }\n  return result;\n}\n\nexport default baseKeysIn;\n","/**\n * This function is like\n * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)\n * except that it includes inherited enumerable properties.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n */\nfunction nativeKeysIn(object) {\n  var result = [];\n  if (object != null) {\n    for (var key in Object(object)) {\n      result.push(key);\n    }\n  }\n  return result;\n}\n\nexport default nativeKeysIn;\n","import arrayLikeKeys from './_arrayLikeKeys.js';\nimport baseKeysIn from './_baseKeysIn.js';\nimport isArrayLike from './isArrayLike.js';\n\n/**\n * Creates an array of the own and inherited enumerable property names of `object`.\n *\n * **Note:** Non-object values are coerced to objects.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Object\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n * @example\n *\n * function Foo() {\n *   this.a = 1;\n *   this.b = 2;\n * }\n *\n * Foo.prototype.c = 3;\n *\n * _.keysIn(new Foo);\n * // => ['a', 'b', 'c'] (iteration order is not guaranteed)\n */\nfunction keysIn(object) {\n  return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object);\n}\n\nexport default keysIn;\n","import assignMergeValue from './_assignMergeValue.js';\nimport cloneBuffer from './_cloneBuffer.js';\nimport cloneTypedArray from './_cloneTypedArray.js';\nimport copyArray from './_copyArray.js';\nimport initCloneObject from './_initCloneObject.js';\nimport isArguments from './isArguments.js';\nimport isArray from './isArray.js';\nimport isArrayLikeObject from './isArrayLikeObject.js';\nimport isBuffer from './isBuffer.js';\nimport isFunction from './isFunction.js';\nimport isObject from './isObject.js';\nimport isPlainObject from './isPlainObject.js';\nimport isTypedArray from './isTypedArray.js';\nimport safeGet from './_safeGet.js';\nimport toPlainObject from './toPlainObject.js';\n\n/**\n * A specialized version of `baseMerge` for arrays and objects which performs\n * deep merges and tracks traversed objects enabling objects with circular\n * references to be merged.\n *\n * @private\n * @param {Object} object The destination object.\n * @param {Object} source The source object.\n * @param {string} key The key of the value to merge.\n * @param {number} srcIndex The index of `source`.\n * @param {Function} mergeFunc The function to merge values.\n * @param {Function} [customizer] The function to customize assigned values.\n * @param {Object} [stack] Tracks traversed source values and their merged\n *  counterparts.\n */\nfunction baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) {\n  var objValue = safeGet(object, key),\n      srcValue = safeGet(source, key),\n      stacked = stack.get(srcValue);\n\n  if (stacked) {\n    assignMergeValue(object, key, stacked);\n    return;\n  }\n  var newValue = customizer\n    ? customizer(objValue, srcValue, (key + ''), object, source, stack)\n    : undefined;\n\n  var isCommon = newValue === undefined;\n\n  if (isCommon) {\n    var isArr = isArray(srcValue),\n        isBuff = !isArr && isBuffer(srcValue),\n        isTyped = !isArr && !isBuff && isTypedArray(srcValue);\n\n    newValue = srcValue;\n    if (isArr || isBuff || isTyped) {\n      if (isArray(objValue)) {\n        newValue = objValue;\n      }\n      else if (isArrayLikeObject(objValue)) {\n        newValue = copyArray(objValue);\n      }\n      else if (isBuff) {\n        isCommon = false;\n        newValue = cloneBuffer(srcValue, true);\n      }\n      else if (isTyped) {\n        isCommon = false;\n        newValue = cloneTypedArray(srcValue, true);\n      }\n      else {\n        newValue = [];\n      }\n    }\n    else if (isPlainObject(srcValue) || isArguments(srcValue)) {\n      newValue = objValue;\n      if (isArguments(objValue)) {\n        newValue = toPlainObject(objValue);\n      }\n      else if (!isObject(objValue) || isFunction(objValue)) {\n        newValue = initCloneObject(srcValue);\n      }\n    }\n    else {\n      isCommon = false;\n    }\n  }\n  if (isCommon) {\n    // Recursively merge objects and arrays (susceptible to call stack limits).\n    stack.set(srcValue, newValue);\n    mergeFunc(newValue, srcValue, srcIndex, customizer, stack);\n    stack['delete'](srcValue);\n  }\n  assignMergeValue(object, key, newValue);\n}\n\nexport default baseMergeDeep;\n","import isArrayLike from './isArrayLike.js';\nimport isObjectLike from './isObjectLike.js';\n\n/**\n * This method is like `_.isArrayLike` except that it also checks if `value`\n * is an object.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an array-like object,\n *  else `false`.\n * @example\n *\n * _.isArrayLikeObject([1, 2, 3]);\n * // => true\n *\n * _.isArrayLikeObject(document.body.children);\n * // => true\n *\n * _.isArrayLikeObject('abc');\n * // => false\n *\n * _.isArrayLikeObject(_.noop);\n * // => false\n */\nfunction isArrayLikeObject(value) {\n  return isObjectLike(value) && isArrayLike(value);\n}\n\nexport default isArrayLikeObject;\n","import copyObject from './_copyObject.js';\nimport keysIn from './keysIn.js';\n\n/**\n * Converts `value` to a plain object flattening inherited enumerable string\n * keyed properties of `value` to own properties of the plain object.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Lang\n * @param {*} value The value to convert.\n * @returns {Object} Returns the converted plain object.\n * @example\n *\n * function Foo() {\n *   this.b = 2;\n * }\n *\n * Foo.prototype.c = 3;\n *\n * _.assign({ 'a': 1 }, new Foo);\n * // => { 'a': 1, 'b': 2 }\n *\n * _.assign({ 'a': 1 }, _.toPlainObject(new Foo));\n * // => { 'a': 1, 'b': 2, 'c': 3 }\n */\nfunction toPlainObject(value) {\n  return copyObject(value, keysIn(value));\n}\n\nexport default toPlainObject;\n","import Stack from './_Stack.js';\nimport assignMergeValue from './_assignMergeValue.js';\nimport baseFor from './_baseFor.js';\nimport baseMergeDeep from './_baseMergeDeep.js';\nimport isObject from './isObject.js';\nimport keysIn from './keysIn.js';\nimport safeGet from './_safeGet.js';\n\n/**\n * The base implementation of `_.merge` without support for multiple sources.\n *\n * @private\n * @param {Object} object The destination object.\n * @param {Object} source The source object.\n * @param {number} srcIndex The index of `source`.\n * @param {Function} [customizer] The function to customize merged values.\n * @param {Object} [stack] Tracks traversed source values and their merged\n *  counterparts.\n */\nfunction baseMerge(object, source, srcIndex, customizer, stack) {\n  if (object === source) {\n    return;\n  }\n  baseFor(source, function(srcValue, key) {\n    stack || (stack = new Stack);\n    if (isObject(srcValue)) {\n      baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack);\n    }\n    else {\n      var newValue = customizer\n        ? customizer(safeGet(object, key), srcValue, (key + ''), object, source, stack)\n        : undefined;\n\n      if (newValue === undefined) {\n        newValue = srcValue;\n      }\n      assignMergeValue(object, key, newValue);\n    }\n  }, keysIn);\n}\n\nexport default baseMerge;\n","/**\n * This method returns the first argument it receives.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Util\n * @param {*} value Any value.\n * @returns {*} Returns `value`.\n * @example\n *\n * var object = { 'a': 1 };\n *\n * console.log(_.identity(object) === object);\n * // => true\n */\nfunction identity(value) {\n  return value;\n}\n\nexport default identity;\n","import apply from './_apply.js';\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeMax = Math.max;\n\n/**\n * A specialized version of `baseRest` which transforms the rest array.\n *\n * @private\n * @param {Function} func The function to apply a rest parameter to.\n * @param {number} [start=func.length-1] The start position of the rest parameter.\n * @param {Function} transform The rest array transform.\n * @returns {Function} Returns the new function.\n */\nfunction overRest(func, start, transform) {\n  start = nativeMax(start === undefined ? (func.length - 1) : start, 0);\n  return function() {\n    var args = arguments,\n        index = -1,\n        length = nativeMax(args.length - start, 0),\n        array = Array(length);\n\n    while (++index < length) {\n      array[index] = args[start + index];\n    }\n    index = -1;\n    var otherArgs = Array(start + 1);\n    while (++index < start) {\n      otherArgs[index] = args[index];\n    }\n    otherArgs[start] = transform(array);\n    return apply(func, this, otherArgs);\n  };\n}\n\nexport default overRest;\n","import constant from './constant.js';\nimport defineProperty from './_defineProperty.js';\nimport identity from './identity.js';\n\n/**\n * The base implementation of `setToString` without support for hot loop shorting.\n *\n * @private\n * @param {Function} func The function to modify.\n * @param {Function} string The `toString` result.\n * @returns {Function} Returns `func`.\n */\nvar baseSetToString = !defineProperty ? identity : function(func, string) {\n  return defineProperty(func, 'toString', {\n    'configurable': true,\n    'enumerable': false,\n    'value': constant(string),\n    'writable': true\n  });\n};\n\nexport default baseSetToString;\n","/**\n * Creates a function that returns `value`.\n *\n * @static\n * @memberOf _\n * @since 2.4.0\n * @category Util\n * @param {*} value The value to return from the new function.\n * @returns {Function} Returns the new constant function.\n * @example\n *\n * var objects = _.times(2, _.constant({ 'a': 1 }));\n *\n * console.log(objects);\n * // => [{ 'a': 1 }, { 'a': 1 }]\n *\n * console.log(objects[0] === objects[1]);\n * // => true\n */\nfunction constant(value) {\n  return function() {\n    return value;\n  };\n}\n\nexport default constant;\n","/** Used to detect hot functions by number of calls within a span of milliseconds. */\nvar HOT_COUNT = 800,\n    HOT_SPAN = 16;\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeNow = Date.now;\n\n/**\n * Creates a function that'll short out and invoke `identity` instead\n * of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN`\n * milliseconds.\n *\n * @private\n * @param {Function} func The function to restrict.\n * @returns {Function} Returns the new shortable function.\n */\nfunction shortOut(func) {\n  var count = 0,\n      lastCalled = 0;\n\n  return function() {\n    var stamp = nativeNow(),\n        remaining = HOT_SPAN - (stamp - lastCalled);\n\n    lastCalled = stamp;\n    if (remaining > 0) {\n      if (++count >= HOT_COUNT) {\n        return arguments[0];\n      }\n    } else {\n      count = 0;\n    }\n    return func.apply(undefined, arguments);\n  };\n}\n\nexport default shortOut;\n","import baseSetToString from './_baseSetToString.js';\nimport shortOut from './_shortOut.js';\n\n/**\n * Sets the `toString` method of `func` to return `string`.\n *\n * @private\n * @param {Function} func The function to modify.\n * @param {Function} string The `toString` result.\n * @returns {Function} Returns `func`.\n */\nvar setToString = shortOut(baseSetToString);\n\nexport default setToString;\n","import identity from './identity.js';\nimport overRest from './_overRest.js';\nimport setToString from './_setToString.js';\n\n/**\n * The base implementation of `_.rest` which doesn't validate or coerce arguments.\n *\n * @private\n * @param {Function} func The function to apply a rest parameter to.\n * @param {number} [start=func.length-1] The start position of the rest parameter.\n * @returns {Function} Returns the new function.\n */\nfunction baseRest(func, start) {\n  return setToString(overRest(func, start, identity), func + '');\n}\n\nexport default baseRest;\n","/**\n * A faster alternative to `Function#apply`, this function invokes `func`\n * with the `this` binding of `thisArg` and the arguments of `args`.\n *\n * @private\n * @param {Function} func The function to invoke.\n * @param {*} thisArg The `this` binding of `func`.\n * @param {Array} args The arguments to invoke `func` with.\n * @returns {*} Returns the result of `func`.\n */\nfunction apply(func, thisArg, args) {\n  switch (args.length) {\n    case 0: return func.call(thisArg);\n    case 1: return func.call(thisArg, args[0]);\n    case 2: return func.call(thisArg, args[0], args[1]);\n    case 3: return func.call(thisArg, args[0], args[1], args[2]);\n  }\n  return func.apply(thisArg, args);\n}\n\nexport default apply;\n","import baseMerge from './_baseMerge.js';\nimport createAssigner from './_createAssigner.js';\n\n/**\n * This method is like `_.assign` except that it recursively merges own and\n * inherited enumerable string keyed properties of source objects into the\n * destination object. Source properties that resolve to `undefined` are\n * skipped if a destination value exists. Array and plain object properties\n * are merged recursively. Other objects and value types are overridden by\n * assignment. Source objects are applied from left to right. Subsequent\n * sources overwrite property assignments of previous sources.\n *\n * **Note:** This method mutates `object`.\n *\n * @static\n * @memberOf _\n * @since 0.5.0\n * @category Object\n * @param {Object} object The destination object.\n * @param {...Object} [sources] The source objects.\n * @returns {Object} Returns `object`.\n * @example\n *\n * var object = {\n *   'a': [{ 'b': 2 }, { 'd': 4 }]\n * };\n *\n * var other = {\n *   'a': [{ 'c': 3 }, { 'e': 5 }]\n * };\n *\n * _.merge(object, other);\n * // => { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] }\n */\nvar merge = createAssigner(function(object, source, srcIndex) {\n  baseMerge(object, source, srcIndex);\n});\n\nexport default merge;\n","import baseRest from './_baseRest.js';\nimport isIterateeCall from './_isIterateeCall.js';\n\n/**\n * Creates a function like `_.assign`.\n *\n * @private\n * @param {Function} assigner The function to assign values.\n * @returns {Function} Returns the new assigner function.\n */\nfunction createAssigner(assigner) {\n  return baseRest(function(object, sources) {\n    var index = -1,\n        length = sources.length,\n        customizer = length > 1 ? sources[length - 1] : undefined,\n        guard = length > 2 ? sources[2] : undefined;\n\n    customizer = (assigner.length > 3 && typeof customizer == 'function')\n      ? (length--, customizer)\n      : undefined;\n\n    if (guard && isIterateeCall(sources[0], sources[1], guard)) {\n      customizer = length < 3 ? undefined : customizer;\n      length = 1;\n    }\n    object = Object(object);\n    while (++index < length) {\n      var source = sources[index];\n      if (source) {\n        assigner(object, source, index, customizer);\n      }\n    }\n    return object;\n  });\n}\n\nexport default createAssigner;\n","import eq from './eq.js';\nimport isArrayLike from './isArrayLike.js';\nimport isIndex from './_isIndex.js';\nimport isObject from './isObject.js';\n\n/**\n * Checks if the given arguments are from an iteratee call.\n *\n * @private\n * @param {*} value The potential iteratee value argument.\n * @param {*} index The potential iteratee index or key argument.\n * @param {*} object The potential iteratee object argument.\n * @returns {boolean} Returns `true` if the arguments are from an iteratee call,\n *  else `false`.\n */\nfunction isIterateeCall(value, index, object) {\n  if (!isObject(object)) {\n    return false;\n  }\n  var type = typeof index;\n  if (type == 'number'\n        ? (isArrayLike(object) && isIndex(index, object.length))\n        : (type == 'string' && index in object)\n      ) {\n    return eq(object[index], value);\n  }\n  return false;\n}\n\nexport default isIterateeCall;\n","/**\n * The error conditions returned by the audio-translation component when it rejects a translation request.\n * The string values are the XMPP error conditions the component replies with.\n */\nexport enum JitsiAudioTranslationErrors {\n\n    /**\n     * The translation request was malformed. Indicates a client bug rather than a user-actionable problem.\n     */\n    BAD_REQUEST = 'bad-request',\n\n    /**\n     * The local participant is not permitted to use audio translation.\n     */\n    FORBIDDEN = 'forbidden',\n\n    /**\n     * The target speaker is no longer present in the conference.\n     */\n    SPEAKER_UNAVAILABLE = 'item-not-found',\n\n    /**\n     * The per-receiver translation subscription limit was reached.\n     */\n    SUBSCRIPTION_LIMIT_REACHED = 'policy-violation',\n\n    /**\n     * An unrecognized error condition was returned by the component.\n     */\n    UNKNOWN = 'unknown'\n}\n","/**\n * The errors for the conference.\n */\n\nexport enum JitsiConferenceErrors {\n\n    /**\n     * Indicates that client must be authenticated to create the conference.\n     */\n    AUTHENTICATION_REQUIRED = 'conference.authenticationRequired',\n\n    /**\n     * Indicates that chat error occurred.\n     */\n    CHAT_ERROR = 'conference.chatError',\n\n    /**\n     * Indicates that a connection error is due to denied access to the room,\n     * occurred after joining a lobby room and access is denied by the room moderators.\n     */\n    CONFERENCE_ACCESS_DENIED = 'conference.connectionError.accessDenied',\n\n    /**\n     * Indicates that conference has been destroyed.\n     */\n    CONFERENCE_DESTROYED = 'conference.destroyed',\n\n    /**\n     * Indicates that max users limit has been reached.\n     */\n    CONFERENCE_MAX_USERS = 'conference.max_users',\n\n    /**\n     * Indicates that a connection error occurred when trying to join a conference.\n     */\n    CONNECTION_ERROR = 'conference.connectionError',\n\n    /**\n     * Indicates that the display name is required when joining the room.\n     * There are cases like lobby room where display name is required.\n     * @param {boolean|null} lobby whether the error is because lobby is enabled.\n     */\n    DISPLAY_NAME_REQUIRED = 'conference.display_name_required',\n\n    /**\n     * Indicates that focus error happened.\n     */\n    FOCUS_DISCONNECTED = 'conference.focusDisconnected',\n\n    /**\n     * Indicates that focus left the conference.\n     */\n    FOCUS_LEFT = 'conference.focusLeft',\n\n    /**\n     * Indicates that graceful shutdown happened.\n     */\n    GRACEFUL_SHUTDOWN = 'conference.gracefulShutdown',\n\n    /**\n     * Indicates that the media connection has failed.\n     */\n    ICE_FAILED = 'conference.iceFailed',\n\n    /**\n     * Indicates that the versions of the server side components are incompatible\n     * with the client side.\n     */\n    INCOMPATIBLE_SERVER_VERSIONS = 'conference.incompatible_server_versions',\n\n    /**\n     * Indicates that a connection error is due to not allowed,\n     * occurred when trying to join a conference, only approved members are allowed to join.\n     */\n    MEMBERS_ONLY_ERROR = 'conference.connectionError.membersOnly',\n\n    /**\n     * Indicates that a connection error is due to not allowed,\n     * occurred when trying to join a conference.\n     */\n    NOT_ALLOWED_ERROR = 'conference.connectionError.notAllowed',\n\n    /**\n     * Indicates that offer/answer had failed.\n     */\n    OFFER_ANSWER_FAILED = 'conference.offerAnswerFailed',\n\n    /**\n     * Indicates that password cannot be set for this conference.\n     */\n    PASSWORD_NOT_SUPPORTED = 'conference.passwordNotSupported',\n\n    /**\n     * Indicates that a password is required in order to join the conference.\n     */\n    PASSWORD_REQUIRED = 'conference.passwordRequired',\n\n    /**\n     * Indicates that reservation system returned error.\n     */\n    RESERVATION_ERROR = 'conference.reservationError',\n\n    /**\n     * Indicates that a settings error occurred.\n     */\n    SETTINGS_ERROR = 'conference.settingsError',\n\n    /**\n     * Indicates that there is no available videobridge.\n     */\n    VIDEOBRIDGE_NOT_AVAILABLE = 'conference.videobridgeNotAvailable'\n}\n\n/**\n * Types that are passed for NOT_ALLOWED_ERROR.\n */\nexport enum AUTH_ERROR_TYPES {\n    GENERAL = 'general',\n    NO_MAIN_PARTICIPANTS = 'no-main-participants',\n    NO_VISITORS_LOBBY = 'no-visitors-lobby',\n    PROMOTION_NOT_ALLOWED = 'promotion-not-allowed',\n    ROOM_CREATION_RESTRICTION = 'room-creation-restriction',\n    ROOM_UNAUTHENTICATED_ACCESS_DISABLED = 'authentication-required'\n}\n\n// exported for backward compatibility\nexport const AUTHENTICATION_REQUIRED = JitsiConferenceErrors.AUTHENTICATION_REQUIRED;\nexport const CHAT_ERROR = JitsiConferenceErrors.CHAT_ERROR;\nexport const SETTINGS_ERROR = JitsiConferenceErrors.SETTINGS_ERROR;\nexport const CONFERENCE_DESTROYED = JitsiConferenceErrors.CONFERENCE_DESTROYED;\nexport const CONFERENCE_MAX_USERS = JitsiConferenceErrors.CONFERENCE_MAX_USERS;\nexport const CONNECTION_ERROR = JitsiConferenceErrors.CONNECTION_ERROR;\nexport const NOT_ALLOWED_ERROR = JitsiConferenceErrors.NOT_ALLOWED_ERROR;\nexport const MEMBERS_ONLY_ERROR = JitsiConferenceErrors.MEMBERS_ONLY_ERROR;\nexport const CONFERENCE_ACCESS_DENIED = JitsiConferenceErrors.CONFERENCE_ACCESS_DENIED;\nexport const DISPLAY_NAME_REQUIRED = JitsiConferenceErrors.DISPLAY_NAME_REQUIRED;\nexport const FOCUS_DISCONNECTED = JitsiConferenceErrors.FOCUS_DISCONNECTED;\nexport const FOCUS_LEFT = JitsiConferenceErrors.FOCUS_LEFT;\nexport const GRACEFUL_SHUTDOWN = JitsiConferenceErrors.GRACEFUL_SHUTDOWN;\nexport const ICE_FAILED = JitsiConferenceErrors.ICE_FAILED;\nexport const INCOMPATIBLE_SERVER_VERSIONS = JitsiConferenceErrors.INCOMPATIBLE_SERVER_VERSIONS;\nexport const OFFER_ANSWER_FAILED = JitsiConferenceErrors.OFFER_ANSWER_FAILED;\nexport const PASSWORD_NOT_SUPPORTED = JitsiConferenceErrors.PASSWORD_NOT_SUPPORTED;\nexport const PASSWORD_REQUIRED = JitsiConferenceErrors.PASSWORD_REQUIRED;\nexport const RESERVATION_ERROR = JitsiConferenceErrors.RESERVATION_ERROR;\nexport const VIDEOBRIDGE_NOT_AVAILABLE = JitsiConferenceErrors.VIDEOBRIDGE_NOT_AVAILABLE;\n","export enum JitsiConferenceEvents {\n\n    /**\n     * Event indicates that the current conference audio input switched between audio\n     * input states,i.e. with or without audio input.\n     */\n    AUDIO_INPUT_STATE_CHANGE = 'conference.audio_input_state_changed',\n\n    /**\n     * Event fired when the audio-translation component rejects a translation request (e.g. subscription limit\n     * reached, target speaker not in the room). The payload carries the affected endpoint ids and the error\n     * condition so the UI can notify the user and revert the optimistic language selection.\n     */\n    AUDIO_TRANSLATION_FAILED = 'conference.audio_translation_failed',\n\n    /**\n     * Event fired when the set of remote participants translating the local participant's audio changes. The\n     * audio-translation component pushes this per-sender (only to the participant being translated), so the\n     * payload is the array of endpoint ids currently listening to a translation of the local participant.\n     */\n    AUDIO_TRANSLATION_LISTENERS_CHANGED = 'conference.audio_translation_listeners_changed',\n\n    /**\n     * Event indicates that the permission for unmuting audio has changed based on the number of audio senders in the\n     * call and the audio sender limit configured in Jicofo.\n     */\n    AUDIO_UNMUTE_PERMISSIONS_CHANGED = 'conference.audio_unmute_permissions_changed',\n\n    /**\n     * Indicates that authentication status changed.\n     */\n    AUTH_STATUS_CHANGED = 'conference.auth_status_changed',\n\n    /**\n     * The local participant was approved to be able to unmute.\n     * @param {options} event - {\n     *     {MediaType} mediaType\n     * }.\n     */\n    AV_MODERATION_APPROVED = 'conference.av_moderation.approved',\n\n    /**\n     * AV Moderation was enabled/disabled. The actor is the participant that is currently in the meeting,\n     * or undefined if that participant has left the meeting.\n     *\n     * @param {options} event - {\n     *     {boolean} enabled,\n     *     {MediaType} mediaType,\n     *     {JitsiParticipant} actor\n     * }.\n     */\n    AV_MODERATION_CHANGED = 'conference.av_moderation.changed',\n\n    /**\n     * AV Moderation, report for user being approved to unmute.\n     * @param {options} event - {\n     *     {JitsiParticipant} participant,\n     *     {MediaType} mediaType\n     * }.\n     */\n    AV_MODERATION_PARTICIPANT_APPROVED = 'conference.av_moderation.participant.approved',\n\n    /**\n     * AV Moderation, report for user being blocked to unmute.\n     * @param {options} event - {\n     *     {JitsiParticipant} participant,\n     *     {MediaType} mediaType\n     * }.\n     */\n    AV_MODERATION_PARTICIPANT_REJECTED = 'conference.av_moderation.participant.rejected',\n\n    /**\n     * The local participant was blocked to be able to unmute.\n     * @param {options} event - {\n     *     {MediaType} mediaType\n     * }.\n     */\n    AV_MODERATION_REJECTED = 'conference.av_moderation.rejected',\n\n    /**\n     * Fired just before the statistics module is disposed and it's the last chance\n     * to submit some logs to the statistics service before it's disconnected.\n     */\n    BEFORE_STATISTICS_DISPOSED = 'conference.beforeStatisticsDisposed',\n\n    /**\n     * Event indicates that the bot participant type changed.\n     */\n    BOT_TYPE_CHANGED = 'conference.bot_type_changed',\n\n    /**\n     * Event fired when a participant is requested to join a given (breakout) room.\n     */\n    BREAKOUT_ROOMS_MOVE_TO_ROOM = 'conference.breakout-rooms.move-to-room',\n\n    /**\n     * Event fired when the breakout rooms data was updated.\n     */\n    BREAKOUT_ROOMS_UPDATED = 'conference.breakout-rooms.updated',\n\n    /**\n     * Event fired when the bandwidth estimation stats are received from the bridge.\n     */\n    BRIDGE_BWE_STATS_RECEIVED = 'conference.bridgeBweStatsReceived',\n\n    /**\n     * UTC conference timestamp when first participant joined.\n     */\n    CONFERENCE_CREATED_TIMESTAMP = 'conference.createdTimestamp',\n\n    /**\n     * Indicates that an error occurred.\n     */\n    CONFERENCE_ERROR = 'conference.error',\n\n    /**\n     * Indicates that conference failed.\n     */\n    CONFERENCE_FAILED = 'conference.failed',\n\n    /**\n     * Indicates that conference has been joined. The event does NOT provide any\n     * parameters to its listeners.\n     */\n    CONFERENCE_JOINED = 'conference.joined',\n\n    /**\n     * Indicates that conference is in progress of joining.\n     */\n    CONFERENCE_JOIN_IN_PROGRESS = 'conference.join_in_progress',\n\n    /**\n     * Indicates that conference has been left.\n     */\n    CONFERENCE_LEFT = 'conference.left',\n\n    /**\n     * Indicates that the conference unique identifier has been set.\n     */\n    CONFERENCE_UNIQUE_ID_SET = 'conference.unique_id_set',\n\n    /**\n     * Indicates that the aggregate set of codecs supported by the visitors has changed.\n     */\n    CONFERENCE_VISITOR_CODECS_CHANGED = 'conference.visitor_codecs_changed',\n\n    /**\n     * Indicates that the connection to the conference has been established\n     * XXX This is currently fired when the *ICE* connection enters 'connected'\n     * state for the first time.\n     */\n    CONNECTION_ESTABLISHED = 'conference.connectionEstablished',\n\n    /**\n     * Indicates that the connection to the conference has been interrupted for some\n     * reason.\n     * XXX This is currently fired when the *ICE* connection is interrupted.\n     */\n    CONNECTION_INTERRUPTED = 'conference.connectionInterrupted',\n\n    /**\n     * Indicates that the connection to the conference has been restored.\n     * XXX This is currently fired when the *ICE* connection is restored.\n     */\n    CONNECTION_RESTORED = 'conference.connectionRestored',\n\n    /**\n     * A connection to the video bridge's data channel has been closed.\n     * This event is only emitted in\n     */\n    DATA_CHANNEL_CLOSED = 'conference.dataChannelClosed',\n\n    /**\n     * A connection to the video bridge's data channel has been established.\n     */\n    DATA_CHANNEL_OPENED = 'conference.dataChannelOpened',\n\n    /**\n     * A user has changed it display name\n     */\n    DISPLAY_NAME_CHANGED = 'conference.displayNameChanged',\n\n    /**\n     * The dominant speaker was changed.\n     */\n    DOMINANT_SPEAKER_CHANGED = 'conference.dominantSpeaker',\n\n    /**\n     * Indicates that DTMF support changed.\n     */\n    DTMF_SUPPORT_CHANGED = 'conference.dtmfSupportChanged',\n\n    E2EE_CHAT_KEY_RECEIVED = 'conference.e2ee.chat_key_received',\n    E2EE_CRYPTO_FAILED = 'conference.e2ee.crypto_failed',\n    E2EE_KEY_SYNC_AFTER_TIMEOUT = 'conference.e2ee.key_sync_after_timeout',\n    E2EE_KEY_SYNC_FAILED = 'conference.e2ee.key_sync_failed',\n    E2EE_SAS_AVAILABLE = 'conference.e2ee.sas.available',\n\n    /**\n     * Indicates that the encode time stats for the local video sources has been received.\n     */\n    ENCODE_TIME_STATS_RECEIVED = 'conference.encode_time_stats_received',\n\n    /**\n     * Indicates that a message from another participant is received on data\n     * channel.\n     */\n    ENDPOINT_MESSAGE_RECEIVED = 'conference.endpoint_message_received',\n\n    /**\n     * Indicates that a message for the remote endpoint statistics has been received on the bridge channel.\n     */\n    ENDPOINT_STATS_RECEIVED = 'conference.endpoint_stats_received',\n\n    /**\n     * Event emitted when a list file is received in the conference. This event is fired when a participant joins\n     * and the file list is sent to them.\n     * @param {Map<String, IFileMetadata>} files - The map of files received in the conference with key the file ID.\n     */\n    FILE_SHARING_FILES_RECEIVED = 'conference.file_sharing.files_received',\n\n    /**\n     * Event emitted when a file is added to the conference.\n     * @param {IFileMetadata} file - The file object containing metadata about the file.\n     */\n    FILE_SHARING_FILE_ADDED = 'conference.file_sharing.file_added',\n\n    /**\n     * Event emitted when a file is removed from the conference.\n     * @param {String} fileId - The ID of the file that was removed.\n     */\n    FILE_SHARING_FILE_REMOVED = 'conference.file_sharing.file_removed',\n\n    /**\n     * The forwarded sources set is changed.\n     *\n     * @param {Array<string>} leavingForwardedSources the sourceNames of all the tracks which are leaving forwarded\n     * sources\n     * @param {Array<string>} enteringForwardedSources the sourceNames of all the tracks which are entering forwarded\n     * sources\n     */\n    FORWARDED_SOURCES_CHANGED = 'conference.forwardedSourcesChanged',\n\n    /**\n     * Indicates that inbound video stats have been received for remote video streams that are receiving\n     * media bytes but decoding no frames. Fired when at least one such stream exists, and once more with an\n     * empty map when all previously-failing streams have recovered (all-clear signal).\n     *\n     * @param {TraceablePeerConnection} tpc - The peer connection.\n     * @param {Map<number, { bitrateDownload: number, fps: number, participantId: string }>} stats - Stats per SSRC.\n     */\n    INBOUND_VIDEO_STATS_RECEIVED = 'conference.inbound_video_stats_received',\n\n    /**\n     * You are kicked from the conference.\n     * @param {JitsiParticipant} the participant that initiated the kick.\n     */\n    KICKED = 'conference.kicked',\n\n    /**\n     * The Last N set is changed.\n     *\n     * @param {Array<string>|null} leavingEndpointIds the ids of all the endpoints\n     * which are leaving Last N\n     * @param {Array<string>|null} enteringEndpointIds the ids of all the endpoints\n     * which are entering Last N\n     */\n    LAST_N_ENDPOINTS_CHANGED = 'conference.lastNEndpointsChanged',\n\n    /**\n     * A new user joined the lobby room.\n     */\n    LOBBY_USER_JOINED = 'conference.lobby.userJoined',\n\n    /**\n     * A user left the lobby room.\n     */\n    LOBBY_USER_LEFT = 'conference.lobby.userLeft',\n\n    /**\n     * A user from the lobby room has been update.\n     */\n    LOBBY_USER_UPDATED = 'conference.lobby.userUpdated',\n\n    /**\n     * Indicates that the room has been locked or unlocked.\n     */\n    LOCK_STATE_CHANGED = 'conference.lock_state_changed',\n\n    /**\n     * Indicates that the conference had changed to members only enabled/disabled.\n     * The first argument of this event is a <tt>boolean</tt> which when set to\n     * <tt>true</tt> means that the conference is running in members only mode.\n     * You may need to use Lobby if supported to ask for permissions to enter the conference.\n     */\n    MEMBERS_ONLY_CHANGED = 'conference.membersOnlyChanged',\n\n    /**\n     * Event fired when a chat message is moderated.\n     */\n    MESSAGE_MODERATED = 'conference.message_moderated',\n\n    /**\n     * New text message was received.\n     */\n    MESSAGE_RECEIVED = 'conference.messageReceived',\n\n    /**\n     * Event indicates that a message was retracted\n    */\n    MESSAGE_RETRACTED = 'conference.messageRetracted',\n\n    /**\n     * Event fired when the conference metadata is updated.\n     */\n    METADATA_UPDATED = 'conference.metadata.updated',\n\n    /**\n     * Event indicates that the current microphone used by the conference is noisy.\n     */\n    NOISY_MIC = 'conference.noisy_mic',\n\n    /**\n     * Indicates that a message from the local user or from the Prosody backend\n     * was received on the data channel.\n     */\n    NON_PARTICIPANT_MESSAGE_RECEIVED = 'conference.non_participant_message_received',\n\n    /**\n     * Event indicates that the current selected input device has no signal\n     */\n    NO_AUDIO_INPUT = 'conference.no_audio_input',\n\n    /**\n     * Indicates that the conference has switched between JVB and P2P connections.\n     * The first argument of this event is a <tt>boolean</tt> which when set to\n     * <tt>true</tt> means that the conference is running on the P2P connection.\n     */\n    P2P_STATUS = 'conference.p2pStatus',\n\n    /**\n     * Indicates that the features of the participant has been changed.\n     * TODO: there is a spelling mistake in this event name and associated constants\n     */\n    PARTCIPANT_FEATURES_CHANGED = 'conference.partcipant_features_changed',\n\n    /**\n     * Participant was kicked from the conference.\n     * @param {JitsiParticipant} the participant that initiated the kick.\n     * @param {JitsiParticipant} the participant that was kicked.\n     */\n    PARTICIPANT_KICKED = 'conference.participant_kicked',\n\n    /**\n     * Indicates that a value of a specific property of a specific participant\n     * has changed.\n     */\n    PARTICIPANT_PROPERTY_CHANGED = 'conference.participant_property_changed',\n\n    /**\n     * Indicates the state of sources attached to a given remote participant has changed.\n     */\n    PARTICIPANT_SOURCE_UPDATED = 'conference.participant_source_updated',\n\n    /**\n     * Indicates that the permissions for the local participant were updated.\n     */\n    PERMISSIONS_RECEIVED = 'conference.permissions_received',\n\n    /**\n     * Indicates that phone number changed.\n     */\n    PHONE_NUMBER_CHANGED = 'conference.phoneNumberChanged',\n\n    /**\n     * An answer for a pool was received.\n     */\n    POLL_ANSWER_RECEIVED = 'conference.pollAnswerReceived',\n\n    /**\n     * A new poll was received or a poll is loaded from the history.\n     */\n    POLL_RECEIVED = 'conference.pollReceived',\n\n    /**\n     * New private text message was received.\n     */\n    PRIVATE_MESSAGE_RECEIVED = 'conference.privateMessageReceived',\n\n    /**\n     * The conference properties changed.\n     */\n    PROPERTIES_CHANGED = 'conference.propertiesChanged',\n\n    /**\n     * New reaction was received.\n     */\n    REACTION_RECEIVED = 'conference.reactionReceived',\n\n    /**\n     * Indicates that recording state changed.\n     */\n    RECORDER_STATE_CHANGED = 'conference.recorderStateChanged',\n\n    /**\n     * Indicates that the region of the media server (jitsi-videobridge) that we\n     * are connected to changed (or was initially set).\n     */\n    SERVER_REGION_CHANGED = 'conference.server_region_changed',\n\n    /**\n     * Indicates a user has joined without audio\n     */\n    SILENT_STATUS_CHANGED = 'conference.silentStatusChanged',\n\n    /**\n     * Indicates that start muted settings changed.\n     */\n    START_MUTED_POLICY_CHANGED = 'conference.start_muted_policy_changed',\n\n    /**\n     * Indicates that subject of the conference has changed.\n     */\n    SUBJECT_CHANGED = 'conference.subjectChanged',\n\n    /**\n     * Indicates that DTMF support changed.\n     */\n    SUSPEND_DETECTED = 'conference.suspendDetected',\n\n    /**\n     * Event indicates that local user is talking while he muted himself\n     */\n    TALK_WHILE_MUTED = 'conference.talk_while_muted',\n\n    /**\n     * A new media track was added to the conference. The event provides the\n     * following parameters to its listeners:\n     *\n     * @param {JitsiTrack} track the added JitsiTrack\n     */\n    TRACK_ADDED = 'conference.trackAdded',\n\n    /**\n     * Audio levels of a media track ( attached to the conference) was changed.\n     */\n    TRACK_AUDIO_LEVEL_CHANGED = 'conference.audioLevelsChanged',\n\n    /**\n     * A media track ( attached to the conference) mute status was changed.\n     * @param {JitsiParticipant|null} the participant that initiated the mute\n     * if it is a remote mute.\n     */\n    TRACK_MUTE_CHANGED = 'conference.trackMuteChanged',\n\n    /**\n     * The media track was removed from the conference. The event provides the\n     * following parameters to its listeners:\n     *\n     * @param {JitsiTrack} track the removed JitsiTrack\n     */\n    TRACK_REMOVED = 'conference.trackRemoved',\n\n    /**\n     * The source-add for unmuting of a media track was rejected by Jicofo.\n     *\n     */\n    TRACK_UNMUTE_REJECTED = 'conference.trackUnmuteRejected',\n\n    /**\n     * Notifies for transcription status changes. The event provides the\n     * following parameters to its listeners:\n     *\n     * @param {String} status - The new status.\n     */\n    TRANSCRIPTION_STATUS_CHANGED = 'conference.transcriptionStatusChanged',\n\n    /**\n     * Indicates that a translated audio source started or stopped being forwarded to the local endpoint. The\n     * listener receives { sourceName, sending, timestamp }; timestamp is an RTP timestamp (48 kHz, wraps at\n     * 2^32) — not epoch ms.\n     */\n    TRANSLATED_SOURCE_SENDING_CHANGED = 'conference.translatedSourceSendingChanged',\n\n    /**\n     * A new user joined the conference.\n     */\n    USER_JOINED = 'conference.userJoined',\n\n    /**\n     * A user has left the conference.\n     */\n    USER_LEFT = 'conference.userLeft',\n\n    /**\n     * User role changed.\n     */\n    USER_ROLE_CHANGED = 'conference.roleChanged',\n\n    /**\n     * User status changed.\n     */\n    USER_STATUS_CHANGED = 'conference.statusChanged',\n\n    /**\n     * Indicates that the video codec of the local video track has changed.\n     */\n    VIDEO_CODEC_CHANGED = 'conference.videoCodecChanged',\n\n    /**\n     * Indicates that video SIP GW state changed.\n     * @param {VideoSIPGWConstants} status.\n     */\n    VIDEO_SIP_GW_AVAILABILITY_CHANGED = 'conference.videoSIPGWAvailabilityChanged',\n\n    /**\n     * Indicates that video SIP GW Session state changed.\n     * @param {options} event - {\n     *     {string} address,\n     *     {VideoSIPGWConstants} oldState,\n     *     {VideoSIPGWConstants} newState,\n     *     {string} displayName\n     * }.\n     */\n    VIDEO_SIP_GW_SESSION_STATE_CHANGED = 'conference.videoSIPGWSessionStateChanged',\n\n    /**\n     * Event indicates that the permission for unmuting video has changed based on the number of video senders in the\n     * call and the video sender limit configured in Jicofo.\n     */\n    VIDEO_UNMUTE_PERMISSIONS_CHANGED = 'conference.video_unmute_permissions_changed',\n\n    /**\n     * Event indicating we have received a message from the visitors component.\n     */\n    VISITORS_MESSAGE = 'conference.visitors_message',\n\n    /**\n     * Event indicating that our request for promotion was rejected.\n     */\n    VISITORS_REJECTION = 'conference.visitors_rejection',\n\n    /**\n     * Indicates that the conference has support for visitors.\n     */\n    VISITORS_SUPPORTED_CHANGED = 'conference.visitorsSupported',\n\n    /**\n     * An event(library-private) fired when the conference switches the currently active media session.\n     * @private\n     */\n    _MEDIA_SESSION_ACTIVE_CHANGED = 'conference.media_session.active_changed',\n\n    /**\n     * An event(library-private) fired when a new media session is added to the conference.\n     * @private\n     */\n    _MEDIA_SESSION_STARTED = 'conference.media_session.started'\n}\n","import MapCache from './_MapCache.js';\nimport setCacheAdd from './_setCacheAdd.js';\nimport setCacheHas from './_setCacheHas.js';\n\n/**\n *\n * Creates an array cache object to store unique values.\n *\n * @private\n * @constructor\n * @param {Array} [values] The values to cache.\n */\nfunction SetCache(values) {\n  var index = -1,\n      length = values == null ? 0 : values.length;\n\n  this.__data__ = new MapCache;\n  while (++index < length) {\n    this.add(values[index]);\n  }\n}\n\n// Add methods to `SetCache`.\nSetCache.prototype.add = SetCache.prototype.push = setCacheAdd;\nSetCache.prototype.has = setCacheHas;\n\nexport default SetCache;\n","/** Used to stand-in for `undefined` hash values. */\nvar HASH_UNDEFINED = '__lodash_hash_undefined__';\n\n/**\n * Adds `value` to the array cache.\n *\n * @private\n * @name add\n * @memberOf SetCache\n * @alias push\n * @param {*} value The value to cache.\n * @returns {Object} Returns the cache instance.\n */\nfunction setCacheAdd(value) {\n  this.__data__.set(value, HASH_UNDEFINED);\n  return this;\n}\n\nexport default setCacheAdd;\n","/**\n * Checks if `value` is in the array cache.\n *\n * @private\n * @name has\n * @memberOf SetCache\n * @param {*} value The value to search for.\n * @returns {boolean} Returns `true` if `value` is found, else `false`.\n */\nfunction setCacheHas(value) {\n  return this.__data__.has(value);\n}\n\nexport default setCacheHas;\n","/**\n * A specialized version of `_.some` for arrays without support for iteratee\n * shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} predicate The function invoked per iteration.\n * @returns {boolean} Returns `true` if any element passes the predicate check,\n *  else `false`.\n */\nfunction arraySome(array, predicate) {\n  var index = -1,\n      length = array == null ? 0 : array.length;\n\n  while (++index < length) {\n    if (predicate(array[index], index, array)) {\n      return true;\n    }\n  }\n  return false;\n}\n\nexport default arraySome;\n","import SetCache from './_SetCache.js';\nimport arraySome from './_arraySome.js';\nimport cacheHas from './_cacheHas.js';\n\n/** Used to compose bitmasks for value comparisons. */\nvar COMPARE_PARTIAL_FLAG = 1,\n    COMPARE_UNORDERED_FLAG = 2;\n\n/**\n * A specialized version of `baseIsEqualDeep` for arrays with support for\n * partial deep comparisons.\n *\n * @private\n * @param {Array} array The array to compare.\n * @param {Array} other The other array to compare.\n * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.\n * @param {Function} customizer The function to customize comparisons.\n * @param {Function} equalFunc The function to determine equivalents of values.\n * @param {Object} stack Tracks traversed `array` and `other` objects.\n * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`.\n */\nfunction equalArrays(array, other, bitmask, customizer, equalFunc, stack) {\n  var isPartial = bitmask & COMPARE_PARTIAL_FLAG,\n      arrLength = array.length,\n      othLength = other.length;\n\n  if (arrLength != othLength && !(isPartial && othLength > arrLength)) {\n    return false;\n  }\n  // Check that cyclic values are equal.\n  var arrStacked = stack.get(array);\n  var othStacked = stack.get(other);\n  if (arrStacked && othStacked) {\n    return arrStacked == other && othStacked == array;\n  }\n  var index = -1,\n      result = true,\n      seen = (bitmask & COMPARE_UNORDERED_FLAG) ? new SetCache : undefined;\n\n  stack.set(array, other);\n  stack.set(other, array);\n\n  // Ignore non-index properties.\n  while (++index < arrLength) {\n    var arrValue = array[index],\n        othValue = other[index];\n\n    if (customizer) {\n      var compared = isPartial\n        ? customizer(othValue, arrValue, index, other, array, stack)\n        : customizer(arrValue, othValue, index, array, other, stack);\n    }\n    if (compared !== undefined) {\n      if (compared) {\n        continue;\n      }\n      result = false;\n      break;\n    }\n    // Recursively compare arrays (susceptible to call stack limits).\n    if (seen) {\n      if (!arraySome(other, function(othValue, othIndex) {\n            if (!cacheHas(seen, othIndex) &&\n                (arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) {\n              return seen.push(othIndex);\n            }\n          })) {\n        result = false;\n        break;\n      }\n    } else if (!(\n          arrValue === othValue ||\n            equalFunc(arrValue, othValue, bitmask, customizer, stack)\n        )) {\n      result = false;\n      break;\n    }\n  }\n  stack['delete'](array);\n  stack['delete'](other);\n  return result;\n}\n\nexport default equalArrays;\n","/**\n * Checks if a `cache` value for `key` exists.\n *\n * @private\n * @param {Object} cache The cache to query.\n * @param {string} key The key of the entry to check.\n * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.\n */\nfunction cacheHas(cache, key) {\n  return cache.has(key);\n}\n\nexport default cacheHas;\n","/**\n * Converts `map` to its key-value pairs.\n *\n * @private\n * @param {Object} map The map to convert.\n * @returns {Array} Returns the key-value pairs.\n */\nfunction mapToArray(map) {\n  var index = -1,\n      result = Array(map.size);\n\n  map.forEach(function(value, key) {\n    result[++index] = [key, value];\n  });\n  return result;\n}\n\nexport default mapToArray;\n","/**\n * Converts `set` to an array of its values.\n *\n * @private\n * @param {Object} set The set to convert.\n * @returns {Array} Returns the values.\n */\nfunction setToArray(set) {\n  var index = -1,\n      result = Array(set.size);\n\n  set.forEach(function(value) {\n    result[++index] = value;\n  });\n  return result;\n}\n\nexport default setToArray;\n","import Symbol from './_Symbol.js';\nimport Uint8Array from './_Uint8Array.js';\nimport eq from './eq.js';\nimport equalArrays from './_equalArrays.js';\nimport mapToArray from './_mapToArray.js';\nimport setToArray from './_setToArray.js';\n\n/** Used to compose bitmasks for value comparisons. */\nvar COMPARE_PARTIAL_FLAG = 1,\n    COMPARE_UNORDERED_FLAG = 2;\n\n/** `Object#toString` result references. */\nvar boolTag = '[object Boolean]',\n    dateTag = '[object Date]',\n    errorTag = '[object Error]',\n    mapTag = '[object Map]',\n    numberTag = '[object Number]',\n    regexpTag = '[object RegExp]',\n    setTag = '[object Set]',\n    stringTag = '[object String]',\n    symbolTag = '[object Symbol]';\n\nvar arrayBufferTag = '[object ArrayBuffer]',\n    dataViewTag = '[object DataView]';\n\n/** Used to convert symbols to primitives and strings. */\nvar symbolProto = Symbol ? Symbol.prototype : undefined,\n    symbolValueOf = symbolProto ? symbolProto.valueOf : undefined;\n\n/**\n * A specialized version of `baseIsEqualDeep` for comparing objects of\n * the same `toStringTag`.\n *\n * **Note:** This function only supports comparing values with tags of\n * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.\n *\n * @private\n * @param {Object} object The object to compare.\n * @param {Object} other The other object to compare.\n * @param {string} tag The `toStringTag` of the objects to compare.\n * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.\n * @param {Function} customizer The function to customize comparisons.\n * @param {Function} equalFunc The function to determine equivalents of values.\n * @param {Object} stack Tracks traversed `object` and `other` objects.\n * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.\n */\nfunction equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) {\n  switch (tag) {\n    case dataViewTag:\n      if ((object.byteLength != other.byteLength) ||\n          (object.byteOffset != other.byteOffset)) {\n        return false;\n      }\n      object = object.buffer;\n      other = other.buffer;\n\n    case arrayBufferTag:\n      if ((object.byteLength != other.byteLength) ||\n          !equalFunc(new Uint8Array(object), new Uint8Array(other))) {\n        return false;\n      }\n      return true;\n\n    case boolTag:\n    case dateTag:\n    case numberTag:\n      // Coerce booleans to `1` or `0` and dates to milliseconds.\n      // Invalid dates are coerced to `NaN`.\n      return eq(+object, +other);\n\n    case errorTag:\n      return object.name == other.name && object.message == other.message;\n\n    case regexpTag:\n    case stringTag:\n      // Coerce regexes to strings and treat strings, primitives and objects,\n      // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring\n      // for more details.\n      return object == (other + '');\n\n    case mapTag:\n      var convert = mapToArray;\n\n    case setTag:\n      var isPartial = bitmask & COMPARE_PARTIAL_FLAG;\n      convert || (convert = setToArray);\n\n      if (object.size != other.size && !isPartial) {\n        return false;\n      }\n      // Assume cyclic values are equal.\n      var stacked = stack.get(object);\n      if (stacked) {\n        return stacked == other;\n      }\n      bitmask |= COMPARE_UNORDERED_FLAG;\n\n      // Recursively compare objects (susceptible to call stack limits).\n      stack.set(object, other);\n      var result = equalArrays(convert(object), convert(other), bitmask, customizer, equalFunc, stack);\n      stack['delete'](object);\n      return result;\n\n    case symbolTag:\n      if (symbolValueOf) {\n        return symbolValueOf.call(object) == symbolValueOf.call(other);\n      }\n  }\n  return false;\n}\n\nexport default equalByTag;\n","/**\n * Appends the elements of `values` to `array`.\n *\n * @private\n * @param {Array} array The array to modify.\n * @param {Array} values The values to append.\n * @returns {Array} Returns `array`.\n */\nfunction arrayPush(array, values) {\n  var index = -1,\n      length = values.length,\n      offset = array.length;\n\n  while (++index < length) {\n    array[offset + index] = values[index];\n  }\n  return array;\n}\n\nexport default arrayPush;\n","import arrayPush from './_arrayPush.js';\nimport isArray from './isArray.js';\n\n/**\n * The base implementation of `getAllKeys` and `getAllKeysIn` which uses\n * `keysFunc` and `symbolsFunc` to get the enumerable property names and\n * symbols of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @param {Function} keysFunc The function to get the keys of `object`.\n * @param {Function} symbolsFunc The function to get the symbols of `object`.\n * @returns {Array} Returns the array of property names and symbols.\n */\nfunction baseGetAllKeys(object, keysFunc, symbolsFunc) {\n  var result = keysFunc(object);\n  return isArray(object) ? result : arrayPush(result, symbolsFunc(object));\n}\n\nexport default baseGetAllKeys;\n","/**\n * This method returns a new empty array.\n *\n * @static\n * @memberOf _\n * @since 4.13.0\n * @category Util\n * @returns {Array} Returns the new empty array.\n * @example\n *\n * var arrays = _.times(2, _.stubArray);\n *\n * console.log(arrays);\n * // => [[], []]\n *\n * console.log(arrays[0] === arrays[1]);\n * // => false\n */\nfunction stubArray() {\n  return [];\n}\n\nexport default stubArray;\n","import arrayFilter from './_arrayFilter.js';\nimport stubArray from './stubArray.js';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Built-in value references. */\nvar propertyIsEnumerable = objectProto.propertyIsEnumerable;\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeGetSymbols = Object.getOwnPropertySymbols;\n\n/**\n * Creates an array of the own enumerable symbols of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of symbols.\n */\nvar getSymbols = !nativeGetSymbols ? stubArray : function(object) {\n  if (object == null) {\n    return [];\n  }\n  object = Object(object);\n  return arrayFilter(nativeGetSymbols(object), function(symbol) {\n    return propertyIsEnumerable.call(object, symbol);\n  });\n};\n\nexport default getSymbols;\n","/**\n * A specialized version of `_.filter` for arrays without support for\n * iteratee shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} predicate The function invoked per iteration.\n * @returns {Array} Returns the new filtered array.\n */\nfunction arrayFilter(array, predicate) {\n  var index = -1,\n      length = array == null ? 0 : array.length,\n      resIndex = 0,\n      result = [];\n\n  while (++index < length) {\n    var value = array[index];\n    if (predicate(value, index, array)) {\n      result[resIndex++] = value;\n    }\n  }\n  return result;\n}\n\nexport default arrayFilter;\n","import overArg from './_overArg.js';\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeKeys = overArg(Object.keys, Object);\n\nexport default nativeKeys;\n","import isPrototype from './_isPrototype.js';\nimport nativeKeys from './_nativeKeys.js';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * The base implementation of `_.keys` which doesn't treat sparse arrays as dense.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n */\nfunction baseKeys(object) {\n  if (!isPrototype(object)) {\n    return nativeKeys(object);\n  }\n  var result = [];\n  for (var key in Object(object)) {\n    if (hasOwnProperty.call(object, key) && key != 'constructor') {\n      result.push(key);\n    }\n  }\n  return result;\n}\n\nexport default baseKeys;\n","import arrayLikeKeys from './_arrayLikeKeys.js';\nimport baseKeys from './_baseKeys.js';\nimport isArrayLike from './isArrayLike.js';\n\n/**\n * Creates an array of the own enumerable property names of `object`.\n *\n * **Note:** Non-object values are coerced to objects. See the\n * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)\n * for more details.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Object\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n * @example\n *\n * function Foo() {\n *   this.a = 1;\n *   this.b = 2;\n * }\n *\n * Foo.prototype.c = 3;\n *\n * _.keys(new Foo);\n * // => ['a', 'b'] (iteration order is not guaranteed)\n *\n * _.keys('hi');\n * // => ['0', '1']\n */\nfunction keys(object) {\n  return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);\n}\n\nexport default keys;\n","import baseGetAllKeys from './_baseGetAllKeys.js';\nimport getSymbols from './_getSymbols.js';\nimport keys from './keys.js';\n\n/**\n * Creates an array of own enumerable property names and symbols of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names and symbols.\n */\nfunction getAllKeys(object) {\n  return baseGetAllKeys(object, keys, getSymbols);\n}\n\nexport default getAllKeys;\n","import getAllKeys from './_getAllKeys.js';\n\n/** Used to compose bitmasks for value comparisons. */\nvar COMPARE_PARTIAL_FLAG = 1;\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * A specialized version of `baseIsEqualDeep` for objects with support for\n * partial deep comparisons.\n *\n * @private\n * @param {Object} object The object to compare.\n * @param {Object} other The other object to compare.\n * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.\n * @param {Function} customizer The function to customize comparisons.\n * @param {Function} equalFunc The function to determine equivalents of values.\n * @param {Object} stack Tracks traversed `object` and `other` objects.\n * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.\n */\nfunction equalObjects(object, other, bitmask, customizer, equalFunc, stack) {\n  var isPartial = bitmask & COMPARE_PARTIAL_FLAG,\n      objProps = getAllKeys(object),\n      objLength = objProps.length,\n      othProps = getAllKeys(other),\n      othLength = othProps.length;\n\n  if (objLength != othLength && !isPartial) {\n    return false;\n  }\n  var index = objLength;\n  while (index--) {\n    var key = objProps[index];\n    if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) {\n      return false;\n    }\n  }\n  // Check that cyclic values are equal.\n  var objStacked = stack.get(object);\n  var othStacked = stack.get(other);\n  if (objStacked && othStacked) {\n    return objStacked == other && othStacked == object;\n  }\n  var result = true;\n  stack.set(object, other);\n  stack.set(other, object);\n\n  var skipCtor = isPartial;\n  while (++index < objLength) {\n    key = objProps[index];\n    var objValue = object[key],\n        othValue = other[key];\n\n    if (customizer) {\n      var compared = isPartial\n        ? customizer(othValue, objValue, key, other, object, stack)\n        : customizer(objValue, othValue, key, object, other, stack);\n    }\n    // Recursively compare objects (susceptible to call stack limits).\n    if (!(compared === undefined\n          ? (objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack))\n          : compared\n        )) {\n      result = false;\n      break;\n    }\n    skipCtor || (skipCtor = key == 'constructor');\n  }\n  if (result && !skipCtor) {\n    var objCtor = object.constructor,\n        othCtor = other.constructor;\n\n    // Non `Object` object instances with different constructors are not equal.\n    if (objCtor != othCtor &&\n        ('constructor' in object && 'constructor' in other) &&\n        !(typeof objCtor == 'function' && objCtor instanceof objCtor &&\n          typeof othCtor == 'function' && othCtor instanceof othCtor)) {\n      result = false;\n    }\n  }\n  stack['delete'](object);\n  stack['delete'](other);\n  return result;\n}\n\nexport default equalObjects;\n","import getNative from './_getNative.js';\nimport root from './_root.js';\n\n/* Built-in method references that are verified to be native. */\nvar DataView = getNative(root, 'DataView');\n\nexport default DataView;\n","import getNative from './_getNative.js';\nimport root from './_root.js';\n\n/* Built-in method references that are verified to be native. */\nvar Promise = getNative(root, 'Promise');\n\nexport default Promise;\n","import getNative from './_getNative.js';\nimport root from './_root.js';\n\n/* Built-in method references that are verified to be native. */\nvar Set = getNative(root, 'Set');\n\nexport default Set;\n","import getNative from './_getNative.js';\nimport root from './_root.js';\n\n/* Built-in method references that are verified to be native. */\nvar WeakMap = getNative(root, 'WeakMap');\n\nexport default WeakMap;\n","import DataView from './_DataView.js';\nimport Map from './_Map.js';\nimport Promise from './_Promise.js';\nimport Set from './_Set.js';\nimport WeakMap from './_WeakMap.js';\nimport baseGetTag from './_baseGetTag.js';\nimport toSource from './_toSource.js';\n\n/** `Object#toString` result references. */\nvar mapTag = '[object Map]',\n    objectTag = '[object Object]',\n    promiseTag = '[object Promise]',\n    setTag = '[object Set]',\n    weakMapTag = '[object WeakMap]';\n\nvar dataViewTag = '[object DataView]';\n\n/** Used to detect maps, sets, and weakmaps. */\nvar dataViewCtorString = toSource(DataView),\n    mapCtorString = toSource(Map),\n    promiseCtorString = toSource(Promise),\n    setCtorString = toSource(Set),\n    weakMapCtorString = toSource(WeakMap);\n\n/**\n * Gets the `toStringTag` of `value`.\n *\n * @private\n * @param {*} value The value to query.\n * @returns {string} Returns the `toStringTag`.\n */\nvar getTag = baseGetTag;\n\n// Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6.\nif ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) ||\n    (Map && getTag(new Map) != mapTag) ||\n    (Promise && getTag(Promise.resolve()) != promiseTag) ||\n    (Set && getTag(new Set) != setTag) ||\n    (WeakMap && getTag(new WeakMap) != weakMapTag)) {\n  getTag = function(value) {\n    var result = baseGetTag(value),\n        Ctor = result == objectTag ? value.constructor : undefined,\n        ctorString = Ctor ? toSource(Ctor) : '';\n\n    if (ctorString) {\n      switch (ctorString) {\n        case dataViewCtorString: return dataViewTag;\n        case mapCtorString: return mapTag;\n        case promiseCtorString: return promiseTag;\n        case setCtorString: return setTag;\n        case weakMapCtorString: return weakMapTag;\n      }\n    }\n    return result;\n  };\n}\n\nexport default getTag;\n","import Stack from './_Stack.js';\nimport equalArrays from './_equalArrays.js';\nimport equalByTag from './_equalByTag.js';\nimport equalObjects from './_equalObjects.js';\nimport getTag from './_getTag.js';\nimport isArray from './isArray.js';\nimport isBuffer from './isBuffer.js';\nimport isTypedArray from './isTypedArray.js';\n\n/** Used to compose bitmasks for value comparisons. */\nvar COMPARE_PARTIAL_FLAG = 1;\n\n/** `Object#toString` result references. */\nvar argsTag = '[object Arguments]',\n    arrayTag = '[object Array]',\n    objectTag = '[object Object]';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * A specialized version of `baseIsEqual` for arrays and objects which performs\n * deep comparisons and tracks traversed objects enabling objects with circular\n * references to be compared.\n *\n * @private\n * @param {Object} object The object to compare.\n * @param {Object} other The other object to compare.\n * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.\n * @param {Function} customizer The function to customize comparisons.\n * @param {Function} equalFunc The function to determine equivalents of values.\n * @param {Object} [stack] Tracks traversed `object` and `other` objects.\n * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.\n */\nfunction baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) {\n  var objIsArr = isArray(object),\n      othIsArr = isArray(other),\n      objTag = objIsArr ? arrayTag : getTag(object),\n      othTag = othIsArr ? arrayTag : getTag(other);\n\n  objTag = objTag == argsTag ? objectTag : objTag;\n  othTag = othTag == argsTag ? objectTag : othTag;\n\n  var objIsObj = objTag == objectTag,\n      othIsObj = othTag == objectTag,\n      isSameTag = objTag == othTag;\n\n  if (isSameTag && isBuffer(object)) {\n    if (!isBuffer(other)) {\n      return false;\n    }\n    objIsArr = true;\n    objIsObj = false;\n  }\n  if (isSameTag && !objIsObj) {\n    stack || (stack = new Stack);\n    return (objIsArr || isTypedArray(object))\n      ? equalArrays(object, other, bitmask, customizer, equalFunc, stack)\n      : equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack);\n  }\n  if (!(bitmask & COMPARE_PARTIAL_FLAG)) {\n    var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'),\n        othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');\n\n    if (objIsWrapped || othIsWrapped) {\n      var objUnwrapped = objIsWrapped ? object.value() : object,\n          othUnwrapped = othIsWrapped ? other.value() : other;\n\n      stack || (stack = new Stack);\n      return equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack);\n    }\n  }\n  if (!isSameTag) {\n    return false;\n  }\n  stack || (stack = new Stack);\n  return equalObjects(object, other, bitmask, customizer, equalFunc, stack);\n}\n\nexport default baseIsEqualDeep;\n","import baseIsEqualDeep from './_baseIsEqualDeep.js';\nimport isObjectLike from './isObjectLike.js';\n\n/**\n * The base implementation of `_.isEqual` which supports partial comparisons\n * and tracks traversed objects.\n *\n * @private\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @param {boolean} bitmask The bitmask flags.\n *  1 - Unordered comparison\n *  2 - Partial comparison\n * @param {Function} [customizer] The function to customize comparisons.\n * @param {Object} [stack] Tracks traversed `value` and `other` objects.\n * @returns {boolean} Returns `true` if the values are equivalent, else `false`.\n */\nfunction baseIsEqual(value, other, bitmask, customizer, stack) {\n  if (value === other) {\n    return true;\n  }\n  if (value == null || other == null || (!isObjectLike(value) && !isObjectLike(other))) {\n    return value !== value && other !== other;\n  }\n  return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack);\n}\n\nexport default baseIsEqual;\n","import baseIsEqual from './_baseIsEqual.js';\n\n/**\n * Performs a deep comparison between two values to determine if they are\n * equivalent.\n *\n * **Note:** This method supports comparing arrays, array buffers, booleans,\n * date objects, error objects, maps, numbers, `Object` objects, regexes,\n * sets, strings, symbols, and typed arrays. `Object` objects are compared\n * by their own, not inherited, enumerable properties. Functions and DOM\n * nodes are compared by strict equality, i.e. `===`.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @returns {boolean} Returns `true` if the values are equivalent, else `false`.\n * @example\n *\n * var object = { 'a': 1 };\n * var other = { 'a': 1 };\n *\n * _.isEqual(object, other);\n * // => true\n *\n * object === other;\n * // => false\n */\nfunction isEqual(value, other) {\n  return baseIsEqual(value, other);\n}\n\nexport default isEqual;\n","export enum JitsiTrackEvents {\n\n    /**\n     * The media track was removed to the conference.\n     */\n    LOCAL_TRACK_STOPPED = 'track.stopped',\n\n    /**\n     * Indicates that the local audio track is not receiving any audio input from\n     * the microphone that is currently selected.\n     */\n    NO_AUDIO_INPUT = 'track.no_audio_input',\n\n    /**\n     * Indicates that the track is not receiving any data even though we expect it\n     * to receive data (i.e. the stream is not stopped).\n     */\n    NO_DATA_FROM_SOURCE = 'track.no_data_from_source',\n\n    /**\n     * Audio levels of a this track was changed.\n     * The first argument is a number with audio level value in range [0, 1].\n     * The second argument is a <tt>TraceablePeerConnection</tt> which is the peer\n     * connection which measured the audio level (one audio track can be added\n     * to multiple peer connection at the same time). This argument is optional for\n     * local tracks for which we can measure audio level without the peer\n     * connection (the value will be <tt>undefined</tt>).\n     *\n     * NOTE The second argument should be treated as library internal and can be\n     * removed at any time.\n     */\n    TRACK_AUDIO_LEVEL_CHANGED = 'track.audioLevelsChanged',\n\n    /**\n     * The audio output of the track was changed.\n     */\n    TRACK_AUDIO_OUTPUT_CHANGED = 'track.audioOutputChanged',\n\n    /**\n     * A media track mute status was changed.\n     */\n    TRACK_MUTE_CHANGED = 'track.trackMuteChanged',\n\n    /**\n     * Indicates that a new owner has been assigned to a remote track when SSRC rewriting is enabled.\n     */\n    TRACK_OWNER_SET = 'track.owner_set',\n\n    /**\n     * Event fired whenever video track's streaming changes.\n     * First argument is the sourceName of the track and the second is a string indicating if the connection is\n     * currently\n     * - active - the connection is active.\n     * - inactive - the connection is inactive, was intentionally interrupted by the bridge because of low BWE or\n     *   because of the endpoint falling out of last N.\n     * - interrupted - a network problem occurred.\n     * - restoring - the connection was inactive and is restoring now.\n     *\n     * The current status value can be obtained by calling JitsiRemoteTrack.getTrackStreamingStatus().\n     */\n    TRACK_STREAMING_STATUS_CHANGED = 'track.streaming_status_changed',\n\n    /**\n     * The video type(\"camera\" or \"desktop\") of the track was changed.\n     */\n    TRACK_VIDEOTYPE_CHANGED = 'track.videoTypeChanged'\n}\n","export var Browser;\n(function (Browser) {\n    Browser[\"CHROME\"] = \"chrome\";\n    Browser[\"ELECTRON\"] = \"electron\";\n    Browser[\"FIREFOX\"] = \"firefox\";\n    Browser[\"REACT_NATIVE\"] = \"react-native\";\n    Browser[\"SAFARI\"] = \"safari\";\n    Browser[\"WEBKIT_BROWSER\"] = \"webkit-browser\";\n})(Browser || (Browser = {}));\n/**\n * Maps the names of the browsers from ua-parser to the internal names defined in\n * ./browsers.js\n */\nexport const PARSER_TO_JITSI_NAME = {\n    'Chrome': Browser.CHROME,\n    'Firefox': Browser.FIREFOX,\n    'Safari': Browser.SAFARI,\n    'Electron': Browser.ELECTRON\n};\nexport var Engine;\n(function (Engine) {\n    Engine[\"BLINK\"] = \"blink\";\n    Engine[\"GECKO\"] = \"gecko\";\n    Engine[\"WEBKIT\"] = \"webkit\";\n})(Engine || (Engine = {}));\nexport const ENGINES = {\n    'Blink': Engine.BLINK,\n    'WebKit': Engine.WEBKIT,\n    'Gecko': Engine.GECKO\n};\n","import { UAParser } from 'ua-parser-js';\nimport { Browser, ENGINES, Engine, PARSER_TO_JITSI_NAME, } from './constants';\n/**\n * Detects React Native environment.\n * @returns {Object|undefined} - The name (REACT_NATIVE) and version.\n */\nfunction _detectReactNative() {\n    const match = navigator.userAgent.match(/\\b(react[ \\t_-]*native)(?:\\/(\\S+))?/i);\n    let version;\n    // If we're remote debugging a React Native app, it may be treated as Chrome. Check navigator.product as well and\n    // always return some version even if we can't get the real one.\n    if (match || navigator.product === 'ReactNative') {\n        let name = Browser.REACT_NATIVE;\n        version = 'unknown';\n        if (match && match.length > 2) {\n            name = match[1];\n            version = match[2];\n        }\n        return {\n            name,\n            version\n        };\n    }\n}\n/**\n * Returns the Jitsi recognized name for the browser\n *\n * @param {Object} [browserInfo] - Information about the browser.\n * @param {string} browserInfo.name - The name of the browser.\n * @param {string} browserInfo.version - The version of the browser.\n * @param {string} browserInfo.engine - The engine of the browser.\n * @param {string} browserInfo.engineVersion - The version of the engine of the browser.\n * @param {string} browserInfo.os - The os of the browser.\n * @param {string} browserInfo.osVersion - The os version of the browser.\n * @returns\n */\nfunction _getJitsiBrowserInfo(browserInfo) {\n    const { engine, engineVersion, name, version } = browserInfo;\n    return {\n        name: PARSER_TO_JITSI_NAME[name],\n        version,\n        engine: engine ? ENGINES[engine] : undefined,\n        engineVersion: engineVersion\n    };\n}\n/**\n * Returns information about the current browser.\n * @param {Object} - The parser instance.\n * @returns {Object} - The name and version of the browser.\n */\nfunction _detect(parser) {\n    const reactNativeInfo = _detectReactNative();\n    if (reactNativeInfo) {\n        return reactNativeInfo;\n    }\n    const { name, version } = parser.getBrowser();\n    const { name: engine, version: engineVersion } = parser.getEngine();\n    return _getJitsiBrowserInfo({\n        name,\n        version,\n        engine,\n        engineVersion\n    });\n}\n/**\n * Implements browser detection.\n */\nexport default class BrowserDetection {\n    /**\n     * Creates new BrowserDetection instance.\n     *\n     * @param {Object} [browserInfo] - Information about the browser.\n     * @param {string} browserInfo.name - The name of the browser.\n     * @param {string} browserInfo.version - The version of the browser.\n     * @param {string} browserInfo.engine - The engine of the browser.\n     * @param {string} browserInfo.engineVersion - The version of the engine of the browser.\n     * @param {string} browserInfo.os - The os of the browser.\n     * @param {string} browserInfo.osVersion - The os version of the browser.\n     */\n    constructor(browserInfo) {\n        this._parser = new UAParser(navigator.userAgent);\n        const { name, version, engine, engineVersion } = browserInfo ? _getJitsiBrowserInfo(browserInfo) : _detect(this._parser);\n        this._name = name;\n        this._version = version;\n        this._engine = engine;\n        this._engineVersion = engineVersion;\n    }\n    /**\n     * Checks if current browser is Chrome.\n     * @returns {boolean}\n     */\n    isChrome() {\n        // for backward compatibility returns true for all Chromium browsers\n        return this._name === Browser.CHROME || this._engine === Engine.BLINK;\n    }\n    /**\n     * Checks if current browser is Firefox.\n     * @returns {boolean}\n     */\n    isFirefox() {\n        return this._engine === Engine.GECKO;\n    }\n    /**\n     * Checks if current browser is Safari.\n     * @returns {boolean}\n     */\n    isSafari() {\n        return this._name === Browser.SAFARI;\n    }\n    /**\n     * Checks if current environment is Electron.\n     * @returns {boolean}\n     */\n    isElectron() {\n        return this._name === Browser.ELECTRON;\n    }\n    /**\n     * Checks if current environment is React Native.\n     * @returns {boolean}\n     */\n    isReactNative() {\n        return this._name === Browser.REACT_NATIVE;\n    }\n    /**\n     * Checks if current browser is based on chromium.\n     * @returns {boolean}\n     */\n    isChromiumBased() {\n        return this._engine === Engine.BLINK;\n    }\n    /**\n     * Checks if current browser is based on webkit.\n     * @returns {boolean}\n     */\n    isWebKitBased() {\n        return this._engine === Engine.WEBKIT;\n    }\n    /**\n     * Gets current browser name.\n     * @returns {string}\n     */\n    getName() {\n        if (this._name) {\n            return this._name;\n        }\n        return this._parser.getBrowser().name;\n    }\n    /**\n     * Returns the version of the current browser.\n     * @returns {string}\n     */\n    getVersion() {\n        if (this._version) {\n            return this._version;\n        }\n        return this._parser.getBrowser().version;\n    }\n    /**\n     * Gets current engine name of the browser.\n     * @returns {string}\n     */\n    getEngine() {\n        return this._engine;\n    }\n    /**\n     * Returns the engine version of the current browser.\n     * @returns the engine version\n     */\n    getEngineVersion() {\n        return this._engineVersion;\n    }\n    /**\n     * Returns the operating system.\n     */\n    getOS() {\n        return this._parser.getOS().name;\n    }\n    /**\n     * Return the os version.\n     */\n    getOSVersion() {\n        return this._parser.getOS().version;\n    }\n    /**\n     * Compares the passed version with the current browser version.\n     *\n     * @param {number} version - The version to compare with.\n     * @returns {boolean} - Returns true if the current version is greater than the passed version and false otherwise.\n     */\n    isVersionGreaterThan(version) {\n        if (this._version) {\n            return parseInt(this._version, 10) > version;\n        }\n        return false;\n    }\n    /**\n     * Compares the passed version with the current browser version.\n     *\n     * @param {number} version - The version to compare with.\n     * @returns {boolean} - Returns true if the current version is lower than the passed version and false otherwise.\n     */\n    isVersionLessThan(version) {\n        if (this._version) {\n            return parseInt(this._version, 10) < version;\n        }\n        return false;\n    }\n    /**\n     * Compares the passed version with the current browser version.\n     *\n     * @param {number} version - The version to compare with.\n     * @returns {boolean} - Returns true if the current version is equal to the passed version and false otherwise.\n     */\n    isVersionEqualTo(version) {\n        if (this._version) {\n            return parseInt(this._version, 10) === version;\n        }\n        return false;\n    }\n    /**\n     * Compares the passed version with the current engine version.\n     *\n     * @param {number} version - The version to compare with.\n     * @returns {boolean} - Returns true if the current version is greater than the passed version and false otherwise.\n     */\n    isEngineVersionGreaterThan(version) {\n        if (this._engineVersion) {\n            return parseInt(this._engineVersion, 10) > version;\n        }\n        return false;\n    }\n    /**\n     * Compares the passed version with the current engine version.\n     *\n     * @param {number} version - The version to compare with.\n     * @returns {boolean} - Returns true if the current version is lower than the passed version and false otherwise.\n     */\n    isEngineVersionLessThan(version) {\n        if (this._engineVersion) {\n            return parseInt(this._engineVersion, 10) < version;\n        }\n        return false;\n    }\n    /**\n     * Compares the passed version with the current engine version.\n     *\n     * @param {number} version - The version to compare with.\n     * @returns {boolean} - Returns true if the current version is equal to the passed version and false otherwise.\n     */\n    isEngineVersionEqualTo(version) {\n        if (this._engineVersion) {\n            return parseInt(this._engineVersion, 10) === version;\n        }\n        return false;\n    }\n}\n","\nexport const PC_STATE_CONNECTED = 'connected';\n\nexport const PC_STATE_DISCONNECTED = 'disconnected';\n\nexport const PC_STATE_FAILED = 'failed';\n\nexport const PC_CON_STATE_CHANGE = 'connectionstatechange';\n\nexport const PC_ICE_CON_STATE_CHANGE = 'iceconnectionstatechange';\n","/* eslint-disable prefer-rest-params */\n/* eslint-disable no-param-reassign */\nimport { BrowserDetection } from '@jitsi/js-utils/browser-detection';\nimport { getLogger } from '@jitsi/logger';\n\nconst logger = getLogger('rtctstats');\n\nimport { PC_CON_STATE_CHANGE, PC_ICE_CON_STATE_CHANGE } from './events';\n\n/**\n * transforms a maplike to an object. Mostly for getStats + JSON.parse(JSON.stringify())\n * @param {*} m\n */\nfunction map2obj(m) {\n    if (!m.entries) {\n        return m;\n    }\n    const o = {};\n\n    m.forEach((v, k) => {\n        o[k] = v;\n    });\n\n    return o;\n}\n\n/**\n *\n * @param {*} pc\n * @param {*} response\n */\nfunction mangleChromeStats(pc, response) {\n    const standardReport = {};\n    const reports = response.result();\n\n    reports.forEach(report => {\n        const standardStats = {\n            id: report.id,\n            timestamp: report.timestamp.getTime(),\n            type: report.type\n        };\n\n        report.names().forEach(name => {\n            standardStats[name] = report.stat(name);\n        });\n        standardReport[standardStats.id] = standardStats;\n    });\n\n    return standardReport;\n}\n\n/**\n * Apply a delta compression to the stats report. Reduces size by ~90%.\n * To reduce further, report keys could be compressed.\n * @param {*} oldStats\n * @param {*} newStats\n */\nfunction deltaCompression(oldStats, newStatsArg) {\n    const newStats = JSON.parse(JSON.stringify(newStatsArg));\n\n    // Go through each report of the newly fetches stats entry and compare it with the previous one (old)\n    // If a field value (e.g. ssrc.id) from the new report matches the corresponding one from the old report\n    // delete it.\n    // The new stats entry will be returned thus any reports from the old stats entry that are no longer found\n    // in the new one will me considered as removed.\n    // stats entries are expected to have the following format:\n    // {reportName1: {\n    //    key1: value,\n    //    key2: value2\n    // },\n    // reportName2: {\n    //    key1: value,\n    //    key2, value2,\n    // }}\n\n    Object.keys(newStats).forEach(id => {\n        const report = newStats[id];\n\n        delete report.id;\n        if (!oldStats[id]) {\n            return;\n        }\n        Object.keys(report).forEach(name => {\n            if (report[name] === oldStats[id][name]) {\n                delete newStats[id][name];\n            }\n        });\n    });\n\n    // TODO Snippet bellow adds the last timestamp as a stats level fields, probably used in feature extraction on the\n    // rtcstats-server side, most likely not used anymore, verify if this can be removed.\n    let timestamp = -Infinity;\n\n    Object.keys(newStats).forEach(id => {\n        const report = newStats[id];\n\n        if (report.timestamp > timestamp) {\n            timestamp = report.timestamp;\n        }\n    });\n    Object.keys(newStats).forEach(id => {\n        const report = newStats[id];\n\n        if (report.timestamp === timestamp) {\n            report.timestamp = 0;\n        }\n    });\n    newStats.timestamp = timestamp;\n\n    return newStats;\n}\n\n/**\n *\n * @param {*} stream\n */\nfunction dumpStream(stream) {\n    return {\n        id: stream.id,\n        tracks: stream.getTracks().map(track => {\n            return {\n                id: track.id, // unique identifier (GUID) for the track\n                kind: track.kind, // `audio` or `video`\n                label: track.label, // identified the track source\n                enabled: track.enabled, // application can control it\n                muted: track.muted, // application cannot control it (read-only)\n                readyState: track.readyState // `live` or `ended`\n            };\n        })\n    };\n}\n\n/**\n *\n * @param {*} trace\n * @param {*} getStatsInterval\n * @param {*} prefixesToWrap\n * @param {*} connectionFilter\n */\nexport default function(\n        { statsEntry: sendStatsEntry },\n        { connectionFilter,\n            pollInterval,\n            useLegacy,\n            sendSdp = false,\n            prefixesToWrap = [ '' ],\n            eventCallback }\n) {\n    let peerconnectioncounter = 0;\n\n    const browserDetection = new BrowserDetection();\n    const isFirefox = browserDetection.isFirefox();\n    const isChromiumBased = browserDetection.isChromiumBased();\n    const isWebKitBased = browserDetection.isWebKitBased();\n    const isReactNative = browserDetection.isReactNative();\n\n    // Only initialize rtcstats if it's run in a supported browser\n    if (!(isFirefox || isChromiumBased || isWebKitBased || isReactNative)) {\n        logger.warn('RTCStats unsupported browser.');\n\n        return;\n    }\n\n    prefixesToWrap.forEach(prefix => {\n        if (!window[`${prefix}RTCPeerConnection`]) {\n            return;\n        }\n\n        const OrigPeerConnection = window[`${prefix}RTCPeerConnection`];\n        const peerconnection = function(config, constraints = {}) {\n            // We want to make sure that any potential errors that occur at this point, caused by rtcstats logic,\n            // does not affect the normal flow of any application that might integrate it.\n            const origConfig = { ...config };\n            const { optional = [] } = constraints;\n            let isP2P = false;\n\n            try {\n                // Verify if the connection is configured as P2P\n                optional.some(option => option.rtcStatsSFUP2P === true) && (isP2P = true);\n\n                const pc = new OrigPeerConnection(config, constraints);\n\n                // In case the client wants to skip some rtcstats connections, a filter function can be provided which\n                // will return the original PC object without any strings attached.\n                if (connectionFilter && connectionFilter(config)) {\n                    return pc;\n                }\n\n                const id = `PC_${peerconnectioncounter++}`;\n\n                pc.__rtcStatsId = id;\n\n                if (!config) {\n                    config = { nullConfig: true };\n                }\n\n                config = JSON.parse(JSON.stringify(config)); // deepcopy\n                // don't log credentials\n                ((config && config.iceServers) || []).forEach(server => {\n                    delete server.credential;\n                });\n\n                if (isFirefox) {\n                    config.browserType = 'moz';\n                } else {\n                    config.browserType = 'webkit';\n                }\n\n                sendStatsEntry('create', id, config);\n\n                pc.__dtlsTransport = null;\n\n                // TODO: do we want to log constraints here? They are chrome-proprietary.\n                // eslint-disable-next-line max-len\n                // http://stackoverflow.com/questions/31003928/what-do-each-of-these-experimental-goog-rtcpeerconnectionconstraints-do\n                sendStatsEntry('constraints', id, constraints);\n\n                pc.addEventListener('icecandidate', e => {\n                    sendStatsEntry('onicecandidate', id, e.candidate);\n                });\n                pc.addEventListener('addstream', e => {\n                    sendStatsEntry(\n                        'onaddstream',\n                        id,\n                        `${e.stream.id} ${e.stream.getTracks().map(t => `${t.kind}:${t.id}`)}`\n                    );\n                });\n                pc.addEventListener('track', e => {\n                    sendStatsEntry(\n                        'ontrack',\n                        id,\n                        `${e.track.kind}:${e.track.id} ${e.streams.map(stream => `stream:${stream.id}`)}`\n                    );\n                });\n                pc.addEventListener('removestream', e => {\n                    sendStatsEntry(\n                        'onremovestream',\n                        id,\n                        `${e.stream.id} ${e.stream.getTracks().map(t => `${t.kind}:${t.id}`)}`\n                    );\n                });\n                pc.addEventListener('signalingstatechange', () => {\n                    sendStatsEntry('onsignalingstatechange', id, pc.signalingState);\n                });\n                pc.addEventListener('iceconnectionstatechange', () => {\n                    const { iceConnectionState } = pc;\n\n                    sendStatsEntry('oniceconnectionstatechange', id, iceConnectionState);\n                    eventCallback?.({\n                        type: PC_ICE_CON_STATE_CHANGE,\n                        body: {\n                            pcId: id,\n                            isP2P,\n                            state: iceConnectionState\n                        }\n                    });\n                });\n                pc.addEventListener('icegatheringstatechange', () => {\n                    sendStatsEntry('onicegatheringstatechange', id, pc.iceGatheringState);\n                });\n                pc.addEventListener('connectionstatechange', () => {\n                    const { connectionState } = pc;\n\n                    sendStatsEntry('onconnectionstatechange', id, pc.connectionState);\n                    eventCallback?.({\n                        type: PC_CON_STATE_CHANGE,\n                        body: {\n                            pcId: id,\n                            isP2P,\n                            state: connectionState\n                        }\n                    });\n                });\n                pc.addEventListener('negotiationneeded', () => {\n                    sendStatsEntry('onnegotiationneeded', id, undefined);\n                });\n                pc.addEventListener('datachannel', event => {\n                    sendStatsEntry('ondatachannel', id, [ event.channel.id, event.channel.label ]);\n                });\n\n                let prev = {};\n\n                const getStats = function() {\n                    if (isFirefox || isWebKitBased || isReactNative || ((isChromiumBased && !useLegacy))) {\n                        pc.getStats(null).then(res => {\n                            const now = map2obj(res);\n                            const base = JSON.parse(JSON.stringify(now)); // our new prev\n\n                            sendStatsEntry('getstats', id, deltaCompression(prev, now));\n                            prev = base;\n                        });\n                    } else if (isChromiumBased) {\n                        // for chromium based env we have the option of using the chrome getstats api via the\n                        // useLegacy flag.\n                        pc.getStats(res => {\n                            const now = mangleChromeStats(pc, res);\n                            const base = JSON.parse(JSON.stringify(now)); // our new prev\n\n                            sendStatsEntry('getstats', id, deltaCompression(prev, now));\n                            prev = base;\n                        });\n                    }\n\n                    // If the current env doesn't support any getstats call do nothing.\n                };\n\n                // TODO: do we want one big interval and all peerconnections\n                //    queried in that or one setInterval per PC?\n                //    we have to collect results anyway so...\n                if (pollInterval) {\n                    const interval = window.setInterval(() => {\n                        if (pc.signalingState === 'closed' || pc.iceConnectionState === 'closed') {\n                            window.clearInterval(interval);\n\n                            return;\n                        }\n                        getStats();\n                    }, pollInterval);\n                }\n\n                pc.addEventListener('connectionstatechange', () => {\n                    if ([ 'connected', 'failed' ].includes(pc.connectionState)) {\n                        getStats();\n                    }\n                });\n\n                return pc;\n            } catch (error) {\n                // If something went wrong, return a normal PeerConnection\n                console.error('RTCStats PeerConnection bind failed: ', error);\n\n                return new OrigPeerConnection(origConfig, constraints);\n            }\n        };\n\n        [ 'createDataChannel', 'close' ].forEach(method => {\n            const nativeMethod = OrigPeerConnection.prototype[method];\n\n            if (nativeMethod) {\n                OrigPeerConnection.prototype[method] = function() {\n                    try {\n                        sendStatsEntry(method, this.__rtcStatsId, arguments);\n                    } catch (error) {\n                        console.error(`RTCStats ${method} bind failed: `, error);\n                    }\n\n                    return nativeMethod.apply(this, arguments);\n                };\n            }\n        });\n\n        [ 'addStream', 'removeStream' ].forEach(method => {\n            const nativeMethod = OrigPeerConnection.prototype[method];\n\n            if (nativeMethod) {\n                OrigPeerConnection.prototype[method] = function() {\n                    try {\n                        const stream = arguments[0];\n                        const streamInfo = stream\n                            .getTracks()\n                            .map(t => `${t.kind}:${t.id}`)\n                            .join(',');\n\n                        sendStatsEntry(method, this.__rtcStatsId, `${stream.id} ${streamInfo}`);\n                    } catch (error) {\n                        console.error(`RTCStats ${method} bind failed: `, error);\n                    }\n\n                    return nativeMethod.apply(this, arguments);\n                };\n            }\n        });\n\n        [ 'addTrack' ].forEach(method => {\n            const nativeMethod = OrigPeerConnection.prototype[method];\n\n            if (nativeMethod) {\n                OrigPeerConnection.prototype[method] = function() {\n                    try {\n                        const track = arguments[0];\n                        const streams = [].slice.call(arguments, 1);\n\n                        sendStatsEntry(\n                            method,\n                            this.__rtcStatsId,\n                            `${track.kind}:${track.id} ${streams.map(s => `stream:${s.id}`).join(';') || '-'}`\n                        );\n                    } catch (error) {\n                        console.error(`RTCStats ${method} bind failed: `, error);\n                    }\n\n                    return nativeMethod.apply(this, arguments);\n                };\n            }\n        });\n\n        [ 'removeTrack' ].forEach(method => {\n            const nativeMethod = OrigPeerConnection.prototype[method];\n\n            if (nativeMethod) {\n                OrigPeerConnection.prototype[method] = function() {\n                    try {\n                        const track = arguments[0].track;\n\n                        sendStatsEntry(method, this.__rtcStatsId, track ? `${track.kind}:${track.id}` : 'null');\n                    } catch (error) {\n                        console.error(`RTCStats ${method} bind failed: `, error);\n                    }\n\n                    return nativeMethod.apply(this, arguments);\n                };\n            }\n        });\n\n        [ 'addTransceiver' ].forEach(method => {\n            const nativeMethod = OrigPeerConnection.prototype[method];\n\n            if (nativeMethod) {\n                OrigPeerConnection.prototype[method] = function() {\n                    try {\n                        const trackOrKind = arguments[0];\n                        let opts;\n\n                        if (typeof trackOrKind === 'string') {\n\n                            opts = trackOrKind;\n                        } else {\n                            opts = `${trackOrKind.kind}:${trackOrKind.id}`;\n                        }\n                        if (arguments.length === 2 && typeof arguments[1] === 'object') {\n                            opts += ` ${JSON.stringify(arguments[1])}`;\n                        }\n\n                        sendStatsEntry(method, this.__rtcStatsId, opts);\n                    } catch (error) {\n                        console.error(`RTCStats ${method} bind failed: `, error);\n                    }\n\n                    return nativeMethod.apply(this, arguments);\n                };\n            }\n        });\n\n        [ 'createOffer', 'createAnswer' ].forEach(method => {\n            const nativeMethod = OrigPeerConnection.prototype[method];\n\n            if (nativeMethod) {\n                OrigPeerConnection.prototype[method] = function() {\n                    // The logic here extracts the arguments and establishes if the API\n                    // is callback or Promise based.\n                    const rtcStatsId = this.__rtcStatsId;\n                    const args = arguments;\n                    let opts;\n\n                    if (arguments.length === 1 && typeof arguments[0] === 'object') {\n                        opts = arguments[0];\n                    } else if (arguments.length === 3 && typeof arguments[2] === 'object') {\n                        opts = arguments[2];\n                    }\n\n                    // We can only put a \"barrier\" at this point because the above logic is\n                    // necessary in all cases, if something fails there we can't just bypass it.\n                    try {\n                        sendStatsEntry(method, this.__rtcStatsId, opts);\n                    } catch (error) {\n                        console.error(`RTCStats ${method} bind failed: `, error);\n                    }\n\n                    return nativeMethod.apply(this, opts ? [ opts ] : undefined).then(\n                        description => {\n                            try {\n\n                                const data = sendSdp ? description : '';\n\n                                sendStatsEntry(`${method}OnSuccess`, rtcStatsId, data);\n                            } catch (error) {\n                                console.error(`RTCStats ${method} promise success bind failed: `, error);\n                            }\n\n                            // We can't safely bypass this part of logic because it's necessary for Proxying this\n                            // request. It determines weather the call is callback or promise based.\n                            if (args.length > 0 && typeof args[0] === 'function') {\n                                args[0].apply(null, [ description ]);\n\n                                return undefined;\n                            }\n\n                            return description;\n                        },\n                        err => {\n                            try {\n                                sendStatsEntry(`${method}OnFailure`, rtcStatsId, err.toString());\n                            } catch (error) {\n                                console.error(`RTCStats ${method} promise failure bind failed: `, error);\n                            }\n\n                            // We can't safely bypass this part of logic because it's necessary for\n                            // Proxying this request. It determines weather the call is callback or promise based.\n                            if (args.length > 1 && typeof args[1] === 'function') {\n                                args[1].apply(null, [ err ]);\n\n                                return;\n                            }\n                            throw err;\n                        }\n                    );\n                };\n            }\n        });\n\n        [ 'setLocalDescription', 'setRemoteDescription', 'addIceCandidate' ].forEach(method => {\n            const nativeMethod = OrigPeerConnection.prototype[method];\n\n            if (nativeMethod) {\n                OrigPeerConnection.prototype[method] = function() {\n                    const rtcStatsId = this.__rtcStatsId;\n                    const args = arguments;\n\n                    try {\n                        const data = sendSdp ? args[0] : '';\n\n                        sendStatsEntry(method, this.__rtcStatsId, data);\n                    } catch (error) {\n                        console.error(`RTCStats ${method} bind failed: `, error);\n                    }\n\n                    return nativeMethod.apply(this, [ args[0] ]).then(\n                        () => {\n                            try {\n                                sendStatsEntry(`${method}OnSuccess`, rtcStatsId, undefined);\n                            } catch (error) {\n                                console.error(`RTCStats ${method} promise success bind failed: `, error);\n                            }\n\n                            if (!this.__dtlsTransport && method.endsWith('Description') && !isReactNative) {\n                                this.getSenders().forEach(sender => {\n                                    if (!this.__dtlsTransport && sender.transport) {\n                                        this.__dtlsTransport = sender.transport;\n\n                                        sender.transport.addEventListener('error', error => {\n                                            sendStatsEntry('ondtlserror', rtcStatsId, error);\n                                        });\n\n                                        sender.transport.addEventListener('statechange', () => {\n                                            const newstate = sender.transport.state;\n\n                                            sendStatsEntry('ondtlsstatechange', rtcStatsId, newstate);\n                                        });\n                                    }\n                                });\n                            }\n\n                            // We can't safely bypass this part of logic because it's necessary for\n                            // Proxying this request. It determines weather the call is callback or promise based.\n                            if (args.length >= 2 && typeof args[1] === 'function') {\n                                args[1].apply(null, []);\n\n                                return undefined;\n                            }\n\n                            return undefined;\n                        },\n                        err => {\n                            try {\n                                sendStatsEntry(`${method}OnFailure`, rtcStatsId, err.toString());\n                            } catch (error) {\n                                console.error(`RTCStats ${method} promise failure bind failed: `, error);\n                            }\n\n                            // We can't safely bypass this part of logic because it's necessary for\n                            // Proxying this request. It determines weather the call is callback or promise based\n                            if (args.length >= 3 && typeof args[2] === 'function') {\n                                args[2].apply(null, [ err ]);\n\n                                return undefined;\n                            }\n                            throw err;\n                        }\n                    );\n                };\n            }\n        });\n\n        // wrap static methods. Currently just generateCertificate.\n        if (OrigPeerConnection.generateCertificate) {\n            Object.defineProperty(peerconnection, 'generateCertificate', {\n                get() {\n                    return arguments.length\n                        ? OrigPeerConnection.generateCertificate.apply(null, arguments)\n                        : OrigPeerConnection.generateCertificate;\n                }\n            });\n        }\n        window[`${prefix}RTCPeerConnection`] = peerconnection;\n        window[`${prefix}RTCPeerConnection`].prototype = OrigPeerConnection.prototype;\n    });\n\n    // getUserMedia wrappers\n    prefixesToWrap.forEach(prefix => {\n        const name = prefix + (prefix.length ? 'GetUserMedia' : 'getUserMedia');\n\n        if (!navigator[name]) {\n            return;\n        }\n        const origGetUserMedia = navigator[name].bind(navigator);\n        const gum = function() {\n            try {\n                sendStatsEntry('getUserMedia', null, arguments[0]);\n            } catch (error) {\n                console.error('RTCStats getUserMedia bind failed: ', error);\n            }\n\n            const cb = arguments[1];\n            const eb = arguments[2];\n\n            origGetUserMedia(\n                arguments[0],\n                stream => {\n                    try {\n                        sendStatsEntry('getUserMediaOnSuccess', null, dumpStream(stream));\n                    } catch (error) {\n                        console.error('RTCStats getUserMediaOnSuccess bind failed: ', error);\n                    }\n\n                    // we log the stream id, track ids and tracks readystate since that is ended GUM fails\n                    // to acquire the cam (in chrome)\n                    if (cb) {\n                        cb(stream);\n                    }\n                },\n                err => {\n                    try {\n                        sendStatsEntry('getUserMediaOnFailure', null, err.name);\n                    } catch (error) {\n                        console.error('RTCStats getUserMediaOnFailure bind failed: ', error);\n                    }\n\n                    if (eb) {\n                        eb(err);\n                    }\n                }\n            );\n        };\n\n        navigator[name] = gum.bind(navigator);\n    });\n\n    if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {\n        const origGetUserMedia = navigator.mediaDevices.getUserMedia.bind(navigator.mediaDevices);\n        const gum = function() {\n            try {\n                sendStatsEntry('navigator.mediaDevices.getUserMedia', null, arguments[0]);\n            } catch (error) {\n                console.error('RTCStats navigator.mediaDevices.getUserMedia bind failed: ', error);\n            }\n\n            return origGetUserMedia.apply(navigator.mediaDevices, arguments).then(\n                stream => {\n                    try {\n                        sendStatsEntry('navigator.mediaDevices.getUserMediaOnSuccess', null, dumpStream(stream));\n                    } catch (error) {\n                        console.error('RTCStats navigator.mediaDevices.getUserMediaOnSuccess bind failed: ', error);\n                    }\n\n                    return stream;\n                },\n                err => {\n                    try {\n                        sendStatsEntry('navigator.mediaDevices.getUserMediaOnFailure', null, err.name);\n                    } catch (error) {\n                        console.error('RTCStats navigator.mediaDevices.getUserMediaOnFailure bind failed: ', error);\n                    }\n\n                    return Promise.reject(err);\n                }\n            );\n        };\n\n        navigator.mediaDevices.getUserMedia = gum.bind(navigator.mediaDevices);\n    }\n\n    // getDisplayMedia\n    if (navigator.mediaDevices && navigator.mediaDevices.getDisplayMedia) {\n        const origGetDisplayMedia = navigator.mediaDevices.getDisplayMedia.bind(navigator.mediaDevices);\n        const gdm = function() {\n            try {\n                sendStatsEntry('navigator.mediaDevices.getDisplayMedia', null, arguments[0]);\n            } catch (error) {\n                console.error('RTCStats navigator.mediaDevices.getDisplayMedia bind failed: ', error);\n            }\n\n            return origGetDisplayMedia.apply(navigator.mediaDevices, arguments).then(\n                stream => {\n                    try {\n                        sendStatsEntry('navigator.mediaDevices.getDisplayMediaOnSuccess', null, dumpStream(stream));\n                    } catch (error) {\n                        console.error('RTCStats navigator.mediaDevices.getDisplayMediaOnSuccess bind failed: ', error);\n                    }\n\n                    return stream;\n                },\n                err => {\n                    try {\n                        sendStatsEntry('navigator.mediaDevices.getDisplayMediaOnFailure', null, err.name);\n                    } catch (error) {\n                        console.error('RTCStats navigator.mediaDevices.getDisplayMediaOnFailure bind failed: ', error);\n                    }\n\n                    return Promise.reject(err);\n                }\n            );\n        };\n\n        navigator.mediaDevices.getDisplayMedia = gdm.bind(navigator.mediaDevices);\n    }\n}\n","// Unique ID creation requires a high quality random # generator. In the browser we therefore\n// require the crypto API and do not support built-in fallback to lower quality random number\n// generators (like Math.random()).\nvar getRandomValues;\nvar rnds8 = new Uint8Array(16);\nexport default function rng() {\n  // lazy load so that environments that need to polyfill have a chance to do so\n  if (!getRandomValues) {\n    // getRandomValues needs to be invoked in a context where \"this\" is a Crypto implementation. Also,\n    // find the complete implementation of crypto (msCrypto) on IE11.\n    getRandomValues = typeof crypto !== 'undefined' && crypto.getRandomValues && crypto.getRandomValues.bind(crypto) || typeof msCrypto !== 'undefined' && typeof msCrypto.getRandomValues === 'function' && msCrypto.getRandomValues.bind(msCrypto);\n\n    if (!getRandomValues) {\n      throw new Error('crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported');\n    }\n  }\n\n  return getRandomValues(rnds8);\n}","export default /^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i;","import validate from './validate.js';\n/**\n * Convert array of 16 byte values to UUID string format of the form:\n * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX\n */\n\nvar byteToHex = [];\n\nfor (var i = 0; i < 256; ++i) {\n  byteToHex.push((i + 0x100).toString(16).substr(1));\n}\n\nfunction stringify(arr) {\n  var offset = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;\n  // Note: Be careful editing this code!  It's been tuned for performance\n  // and works in ways you may not expect. See https://github.com/uuidjs/uuid/pull/434\n  var uuid = (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + '-' + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + '-' + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + '-' + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + '-' + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase(); // Consistency check for valid UUID.  If this throws, it's likely due to one\n  // of the following:\n  // - One or more input array values don't map to a hex octet (leading to\n  // \"undefined\" in the uuid)\n  // - Invalid input values for the RFC `version` or `variant` fields\n\n  if (!validate(uuid)) {\n    throw TypeError('Stringified UUID is invalid');\n  }\n\n  return uuid;\n}\n\nexport default stringify;","import REGEX from './regex.js';\n\nfunction validate(uuid) {\n  return typeof uuid === 'string' && REGEX.test(uuid);\n}\n\nexport default validate;","import rng from './rng.js';\nimport stringify from './stringify.js';\n\nfunction v4(options, buf, offset) {\n  options = options || {};\n  var rnds = options.random || (options.rng || rng)(); // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`\n\n  rnds[6] = rnds[6] & 0x0f | 0x40;\n  rnds[8] = rnds[8] & 0x3f | 0x80; // Copy bytes to buffer, if provided\n\n  if (buf) {\n    offset = offset || 0;\n\n    for (var i = 0; i < 16; ++i) {\n      buf[offset + i] = rnds[i];\n    }\n\n    return buf;\n  }\n\n  return stringify(rnds);\n}\n\nexport default v4;","export const PROTOCOL_ITERATION = '3.1';\n\n// the maximum number of ms allowed for the client to try reconnect\nexport const MAX_RECONNECT_TIME = 600000;\nexport const messageTypes = {\n    SequenceNumber: 'sn'\n};\nexport const CONFERENCE_LEAVE_CODE = 3001;\nexport const DUMP_ERROR_CODE = 3002;\nexport const CUSTOM_ERROR_CODES = [ CONFERENCE_LEAVE_CODE, DUMP_ERROR_CODE ];\n\n// The limit chosen for the buffer so that memory overflows do not happen.\nexport const BUFFER_LIMIT = 1000;\n","export var Browser;\n(function (Browser) {\n    Browser[\"CHROME\"] = \"chrome\";\n    Browser[\"ELECTRON\"] = \"electron\";\n    Browser[\"FIREFOX\"] = \"firefox\";\n    Browser[\"REACT_NATIVE\"] = \"react-native\";\n    Browser[\"SAFARI\"] = \"safari\";\n    Browser[\"WEBKIT_BROWSER\"] = \"webkit-browser\";\n})(Browser || (Browser = {}));\n/**\n * Maps the names of the browsers from ua-parser to the internal names defined in\n * ./browsers.js\n */\nexport const PARSER_TO_JITSI_NAME = {\n    'Chrome': Browser.CHROME,\n    'Firefox': Browser.FIREFOX,\n    'Safari': Browser.SAFARI,\n    'Electron': Browser.ELECTRON\n};\nexport var Engine;\n(function (Engine) {\n    Engine[\"BLINK\"] = \"blink\";\n    Engine[\"GECKO\"] = \"gecko\";\n    Engine[\"WEBKIT\"] = \"webkit\";\n})(Engine || (Engine = {}));\nexport const ENGINES = {\n    'Blink': Engine.BLINK,\n    'WebKit': Engine.WEBKIT,\n    'Gecko': Engine.GECKO\n};\n","// obfuscate ip addresses which should not be stored long-term.\n\nimport SDPUtils from 'sdp';\n\n/**\n * obfuscate ip, keeping address family intact.\n * @param {*} ip\n */\nfunction maskIP(ip) {\n    if (ip.indexOf('[') === 0 || ip.indexOf(':') !== -1) {\n        // IPv6\n        // obfuscate last five bits like Chrome does.\n        return `${ip.split(':').slice(0, 3)\n            .join(':')}:x:x:x:x:x`;\n    }\n\n    const parts = ip.split('.');\n\n    if (parts.length === 4) {\n        parts[3] = 'x';\n\n        return parts.join('.');\n    }\n\n    return ip;\n}\n\n/**\n * Returns a simple IP mask.\n *\n * @returns masked IP.\n */\nfunction obfuscateIP(ip) {\n    if (ip.indexOf('[') === 0 || ip.indexOf(':') !== -1) {\n\n        return 'x:x:x:x:x:x:x:x';\n    }\n\n    return 'x.x.x.x';\n}\n\n/**\n * obfuscate the ip in ice candidates. Does NOT obfuscate the ip of the TURN server to allow\n * selecting/grouping sessions by TURN server.\n * @param {*} candidate\n */\nfunction obfuscateCandidate(candidate) {\n    const cand = SDPUtils.parseCandidate(candidate);\n\n    if (!(cand.type === 'relay' || cand.protocol === 'ssltcp')) {\n        cand.ip = obfuscateIP(cand.ip);\n        cand.address = obfuscateIP(cand.address);\n    }\n    if (cand.relatedAddress) {\n        cand.relatedAddress = obfuscateIP(cand.relatedAddress);\n    }\n\n    return SDPUtils.writeCandidate(cand);\n}\n\n/**\n *\n * @param {*} sdp\n */\nfunction obfuscateSDP(sdp) {\n    const lines = SDPUtils.splitLines(sdp);\n\n    return `${lines\n        .map(line => {\n            // obfuscate a=candidate, c= and a=rtcp\n            if (line.indexOf('a=candidate:') === 0) {\n                return `a=${obfuscateCandidate(line)}`;\n            } else if (line.indexOf('c=') === 0) {\n                return 'c=IN IP4 0.0.0.0';\n            } else if (line.indexOf('a=rtcp:') === 0) {\n                return 'a=rtcp:9 IN IP4 0.0.0.0';\n            }\n\n            return line;\n        })\n        .join('\\r\\n')\n        .trim()}\\r\\n`;\n}\n\n/**\n *\n * @param {*} stats\n */\nfunction obfuscateStats(stats) {\n    Object.keys(stats).forEach(id => {\n        const report = stats[id];\n\n        // TODO Safari and Firefox seem to be sending empty statistic files\n        if (!report) {\n            return;\n        }\n\n        // obfuscate different variants of how the ip is contained in different stats / versions.\n        [ 'ipAddress', 'ip', 'address' ].forEach(address => {\n            if (report[address] && report.candidateType !== 'relay') {\n                report[address] = obfuscateIP(report[address]);\n            }\n        });\n        [ 'googLocalAddress', 'googRemoteAddress' ].forEach(name => {\n            // contains both address and port\n            let port;\n            let ip;\n            let splitBy;\n\n            // These fields also have the port, separate it first and the obfuscate.\n            if (report[name]) {\n                // IPv6 has the following format [1fff:0:a88:85a3::ac1f]:8001\n                // IPv5 has the following format 127.0.0.1:8001\n                if (report[name][0] === '[') {\n                    splitBy = ']:';\n                } else {\n                    splitBy = ':';\n                }\n\n                [ ip, port ] = report[name].split(splitBy);\n\n                report[name] = `${obfuscateIP(ip)}:${port}`;\n            }\n        });\n    });\n}\n\n/**\n * Obfuscates the ip addresses from webrtc statistics.\n * NOTE. The statistics spec is subject to change, consider evaluating which statistics contain IP addresses\n * before usage.\n *\n * @param {*} data\n */\nexport default function(data) {\n    switch (data[0]) {\n    case 'addIceCandidate':\n    case 'onicecandidate':\n        if (data[2] && data[2].candidate) {\n\n            const jsonRepr = data[2];\n\n            jsonRepr.candidate = obfuscateCandidate(jsonRepr.candidate);\n            data[2] = jsonRepr;\n        }\n        break;\n    case 'setLocalDescription':\n    case 'setRemoteDescription':\n    case 'createOfferOnSuccess':\n    case 'createAnswerOnSuccess':\n        if (data[2] && data[2].sdp) {\n            data[2].sdp = obfuscateSDP(data[2].sdp);\n        }\n        break;\n    case 'getStats':\n    case 'getstats':\n        if (data[2]) {\n            obfuscateStats(data[2]);\n        }\n        break;\n    default:\n        break;\n    }\n}\n","import { UAParser } from 'ua-parser-js';\nimport { Browser, ENGINES, Engine, PARSER_TO_JITSI_NAME, } from './constants';\n/**\n * Detects React Native environment.\n * @returns {Object|undefined} - The name (REACT_NATIVE) and version.\n */\nfunction _detectReactNative() {\n    const match = navigator.userAgent.match(/\\b(react[ \\t_-]*native)(?:\\/(\\S+))?/i);\n    let version;\n    // If we're remote debugging a React Native app, it may be treated as Chrome. Check navigator.product as well and\n    // always return some version even if we can't get the real one.\n    if (match || navigator.product === 'ReactNative') {\n        let name = Browser.REACT_NATIVE;\n        version = 'unknown';\n        if (match && match.length > 2) {\n            name = match[1];\n            version = match[2];\n        }\n        return {\n            name,\n            version\n        };\n    }\n}\n/**\n * Returns the Jitsi recognized name for the browser\n *\n * @param {Object} [browserInfo] - Information about the browser.\n * @param {string} browserInfo.name - The name of the browser.\n * @param {string} browserInfo.version - The version of the browser.\n * @param {string} browserInfo.engine - The engine of the browser.\n * @param {string} browserInfo.engineVersion - The version of the engine of the browser.\n * @param {string} browserInfo.os - The os of the browser.\n * @param {string} browserInfo.osVersion - The os version of the browser.\n * @returns\n */\nfunction _getJitsiBrowserInfo(browserInfo) {\n    const { engine, engineVersion, name, version } = browserInfo;\n    return {\n        name: PARSER_TO_JITSI_NAME[name],\n        version,\n        engine: engine ? ENGINES[engine] : undefined,\n        engineVersion: engineVersion\n    };\n}\n/**\n * Returns information about the current browser.\n * @param {Object} - The parser instance.\n * @returns {Object} - The name and version of the browser.\n */\nfunction _detect(parser) {\n    const reactNativeInfo = _detectReactNative();\n    if (reactNativeInfo) {\n        return reactNativeInfo;\n    }\n    const { name, version } = parser.getBrowser();\n    const { name: engine, version: engineVersion } = parser.getEngine();\n    return _getJitsiBrowserInfo({\n        name,\n        version,\n        engine,\n        engineVersion\n    });\n}\n/**\n * Implements browser detection.\n */\nexport default class BrowserDetection {\n    /**\n     * Creates new BrowserDetection instance.\n     *\n     * @param {Object} [browserInfo] - Information about the browser.\n     * @param {string} browserInfo.name - The name of the browser.\n     * @param {string} browserInfo.version - The version of the browser.\n     * @param {string} browserInfo.engine - The engine of the browser.\n     * @param {string} browserInfo.engineVersion - The version of the engine of the browser.\n     * @param {string} browserInfo.os - The os of the browser.\n     * @param {string} browserInfo.osVersion - The os version of the browser.\n     */\n    constructor(browserInfo) {\n        this._parser = new UAParser(navigator.userAgent);\n        const { name, version, engine, engineVersion } = browserInfo ? _getJitsiBrowserInfo(browserInfo) : _detect(this._parser);\n        this._name = name;\n        this._version = version;\n        this._engine = engine;\n        this._engineVersion = engineVersion;\n    }\n    /**\n     * Checks if current browser is Chrome.\n     * @returns {boolean}\n     */\n    isChrome() {\n        // for backward compatibility returns true for all Chromium browsers\n        return this._name === Browser.CHROME || this._engine === Engine.BLINK;\n    }\n    /**\n     * Checks if current browser is Firefox.\n     * @returns {boolean}\n     */\n    isFirefox() {\n        return this._engine === Engine.GECKO;\n    }\n    /**\n     * Checks if current browser is Safari.\n     * @returns {boolean}\n     */\n    isSafari() {\n        return this._name === Browser.SAFARI;\n    }\n    /**\n     * Checks if current environment is Electron.\n     * @returns {boolean}\n     */\n    isElectron() {\n        return this._name === Browser.ELECTRON;\n    }\n    /**\n     * Checks if current environment is React Native.\n     * @returns {boolean}\n     */\n    isReactNative() {\n        return this._name === Browser.REACT_NATIVE;\n    }\n    /**\n     * Checks if current browser is based on chromium.\n     * @returns {boolean}\n     */\n    isChromiumBased() {\n        return this._engine === Engine.BLINK;\n    }\n    /**\n     * Checks if current browser is based on webkit.\n     * @returns {boolean}\n     */\n    isWebKitBased() {\n        return this._engine === Engine.WEBKIT;\n    }\n    /**\n     * Gets current browser name.\n     * @returns {string}\n     */\n    getName() {\n        if (this._name) {\n            return this._name;\n        }\n        return this._parser.getBrowser().name;\n    }\n    /**\n     * Returns the version of the current browser.\n     * @returns {string}\n     */\n    getVersion() {\n        if (this._version) {\n            return this._version;\n        }\n        return this._parser.getBrowser().version;\n    }\n    /**\n     * Gets current engine name of the browser.\n     * @returns {string}\n     */\n    getEngine() {\n        return this._engine;\n    }\n    /**\n     * Returns the engine version of the current browser.\n     * @returns the engine version\n     */\n    getEngineVersion() {\n        return this._engineVersion;\n    }\n    /**\n     * Returns the operating system.\n     */\n    getOS() {\n        return this._parser.getOS().name;\n    }\n    /**\n     * Return the os version.\n     */\n    getOSVersion() {\n        return this._parser.getOS().version;\n    }\n    /**\n     * Compares the passed version with the current browser version.\n     *\n     * @param {number} version - The version to compare with.\n     * @returns {boolean} - Returns true if the current version is greater than the passed version and false otherwise.\n     */\n    isVersionGreaterThan(version) {\n        if (this._version) {\n            return parseInt(this._version, 10) > version;\n        }\n        return false;\n    }\n    /**\n     * Compares the passed version with the current browser version.\n     *\n     * @param {number} version - The version to compare with.\n     * @returns {boolean} - Returns true if the current version is lower than the passed version and false otherwise.\n     */\n    isVersionLessThan(version) {\n        if (this._version) {\n            return parseInt(this._version, 10) < version;\n        }\n        return false;\n    }\n    /**\n     * Compares the passed version with the current browser version.\n     *\n     * @param {number} version - The version to compare with.\n     * @returns {boolean} - Returns true if the current version is equal to the passed version and false otherwise.\n     */\n    isVersionEqualTo(version) {\n        if (this._version) {\n            return parseInt(this._version, 10) === version;\n        }\n        return false;\n    }\n    /**\n     * Compares the passed version with the current engine version.\n     *\n     * @param {number} version - The version to compare with.\n     * @returns {boolean} - Returns true if the current version is greater than the passed version and false otherwise.\n     */\n    isEngineVersionGreaterThan(version) {\n        if (this._engineVersion) {\n            return parseInt(this._engineVersion, 10) > version;\n        }\n        return false;\n    }\n    /**\n     * Compares the passed version with the current engine version.\n     *\n     * @param {number} version - The version to compare with.\n     * @returns {boolean} - Returns true if the current version is lower than the passed version and false otherwise.\n     */\n    isEngineVersionLessThan(version) {\n        if (this._engineVersion) {\n            return parseInt(this._engineVersion, 10) < version;\n        }\n        return false;\n    }\n    /**\n     * Compares the passed version with the current engine version.\n     *\n     * @param {number} version - The version to compare with.\n     * @returns {boolean} - Returns true if the current version is equal to the passed version and false otherwise.\n     */\n    isEngineVersionEqualTo(version) {\n        if (this._engineVersion) {\n            return parseInt(this._engineVersion, 10) === version;\n        }\n        return false;\n    }\n}\n","// NOTE: The 'events' module is a devDependency (not a runtime dependency).\n// Consumers of this package are expected to provide 'events' via their bundler (e.g., webpack) or\n// environment (e.g., nodeJS). For tests only, we include 'events' in devDependencies.\nimport EventEmitter from 'events';\n/**\n * Dummy implementation of Storage interface.\n */\nclass DummyLocalStorage extends EventEmitter {\n    constructor() {\n        super(...arguments);\n        /**\n         * The object used for storage.\n         */\n        this._storage = {};\n    }\n    /**\n     * Empties all keys out of the storage.\n     *\n     * @returns {void}\n     */\n    clear() {\n        this._storage = {};\n    }\n    /**\n     * Returns the number of data items stored in the Storage object.\n     *\n     * @returns {number} The number of data items stored in the Storage object.\n     */\n    get length() {\n        return Object.keys(this._storage).length;\n    }\n    /**\n     * Will return that key's value associated to the passed key name.\n     *\n     * @param {string} keyName - The key name.\n     * @returns {string | null} The key value.\n     */\n    getItem(keyName) {\n        var _a;\n        return (_a = this._storage[keyName]) !== null && _a !== void 0 ? _a : null;\n    }\n    /**\n     * When passed a key name and value, will add that key to the storage,\n     * or update that key's value if it already exists.\n     *\n     * @param {string} keyName - The key name.\n     * @param {string} keyValue - The key value.\n     * @returns {void}\n     */\n    setItem(keyName, keyValue) {\n        this._storage[keyName] = keyValue;\n    }\n    /**\n     * When passed a key name, will remove that key from the storage.\n     *\n     * @param {string} keyName - The key name.\n     * @returns {void}\n     */\n    removeItem(keyName) {\n        delete this._storage[keyName];\n    }\n    /**\n     * When passed a number n, this method will return the name of the nth key in the storage.\n     *\n     * @param {number} n - The index of the key.\n     * @returns {string | null} The nth key name, or null if index is out of bounds.\n     */\n    key(n) {\n        const keys = Object.keys(this._storage);\n        if (keys.length <= n) {\n            return null;\n        }\n        return keys[n];\n    }\n    /**\n     * Serializes the content of the storage.\n     *\n     * @param {string[]} [ignore=[]] - Array with keys from the local storage to be ignored.\n     * @returns {string} The serialized content.\n     */\n    serialize(ignore = []) {\n        if (ignore.length === 0) {\n            return JSON.stringify(this._storage);\n        }\n        const storageCopy = { ...this._storage };\n        ignore.forEach(key => {\n            delete storageCopy[key];\n        });\n        return JSON.stringify(storageCopy);\n    }\n}\n/**\n * Wrapper class for browser's local storage object.\n */\nexport class JitsiLocalStorage extends EventEmitter {\n    /**\n     * Creates a new JitsiLocalStorage instance.\n     */\n    constructor() {\n        super();\n        /**\n         * Whether window.localStorage is disabled.\n         */\n        this._localStorageDisabled = false;\n        let storage;\n        try {\n            storage = window.localStorage;\n            this._localStorageDisabled = false;\n        }\n        catch (ignore) {\n            // localStorage throws an exception.\n        }\n        if (!storage) { // Handles the case when window.localStorage is undefined or throws an exception.\n            console.warn('Local storage is disabled.');\n            storage = new DummyLocalStorage();\n            this._localStorageDisabled = true;\n        }\n        this._storage = storage;\n    }\n    /**\n     * Returns true if window.localStorage is disabled and false otherwise.\n     *\n     * @returns {boolean} True if window.localStorage is disabled and false otherwise.\n     */\n    isLocalStorageDisabled() {\n        return this._localStorageDisabled;\n    }\n    /**\n     * Switch between window.localStorage and DummyLocalStorage.\n     *\n     * @param {boolean} value - Whether to disable localStorage.\n     * @returns {void}\n     */\n    setLocalStorageDisabled(value) {\n        this._localStorageDisabled = value;\n        try {\n            this._storage = value ? new DummyLocalStorage() : window.localStorage;\n        }\n        catch (ignore) {\n            // localStorage throws an exception.\n        }\n        if (!this._storage) {\n            this._storage = new DummyLocalStorage();\n        }\n    }\n    /**\n     * Empties all keys out of the storage.\n     *\n     * @returns {void}\n     */\n    clear() {\n        this._storage.clear();\n        this.emit('changed');\n    }\n    /**\n     * Returns the number of data items stored in the Storage object.\n     *\n     * @returns {number} The number of data items stored in the Storage object.\n     */\n    get length() {\n        return this._storage.length;\n    }\n    /**\n     * Returns that passed key's value.\n     *\n     * @param {string} keyName - The name of the key you want to retrieve the value of.\n     * @returns {string | null} The value of the key. If the key does not exist, null is returned.\n     */\n    getItem(keyName) {\n        return this._storage.getItem(keyName);\n    }\n    /**\n     * Adds a key to the storage, or update key's value if it already exists.\n     *\n     * @param {string} keyName - The name of the key you want to create/update.\n     * @param {string} keyValue - The value you want to give the key you are creating/updating.\n     * @param {boolean} [dontEmitChangedEvent=false] - If true a changed event won't be emitted.\n     * @returns {void}\n     */\n    setItem(keyName, keyValue, dontEmitChangedEvent = false) {\n        this._storage.setItem(keyName, keyValue);\n        if (!dontEmitChangedEvent) {\n            this.emit('changed');\n        }\n    }\n    /**\n     * Remove a key from the storage.\n     *\n     * @param {string} keyName - The name of the key you want to remove.\n     * @returns {void}\n     */\n    removeItem(keyName) {\n        this._storage.removeItem(keyName);\n        this.emit('changed');\n    }\n    /**\n     * Returns the name of the nth key in the list, or null if n is greater\n     * than or equal to the number of key/value pairs in the object.\n     *\n     * @param {number} i - The index of the key in the list.\n     * @returns {string | null} The name of the nth key, or null if out of bounds.\n     */\n    key(i) {\n        return this._storage.key(i);\n    }\n    /**\n     * Serializes the content of the storage.\n     *\n     * @param {string[]} [ignore=[]] - Array with keys from the local storage to be ignored.\n     * @returns {string} The serialized content.\n     */\n    serialize(ignore = []) {\n        if (this.isLocalStorageDisabled()) {\n            return this._storage.serialize(ignore);\n        }\n        const length = this._storage.length;\n        const localStorageContent = {};\n        for (let i = 0; i < length; i++) {\n            const key = this._storage.key(i);\n            if (key && !ignore.includes(key)) {\n                localStorageContent[key] = this._storage.getItem(key);\n            }\n        }\n        return JSON.stringify(localStorageContent);\n    }\n}\nexport const jitsiLocalStorage = new JitsiLocalStorage();\n","/**\n * Message types for transport communication.\n *\n * @enum {string}\n */\nexport var MessageType;\n(function (MessageType) {\n    /**\n     * The message type for events.\n     *\n     * @type {string}\n     */\n    MessageType[\"EVENT\"] = \"event\";\n    /**\n     * The message type for requests.\n     *\n     * @type {string}\n     */\n    MessageType[\"REQUEST\"] = \"request\";\n    /**\n     * The message type for responses.\n     *\n     * @type {string}\n     */\n    MessageType[\"RESPONSE\"] = \"response\";\n})(MessageType || (MessageType = {}));\n","import { parse as BourneParse } from '@hapi/bourne';\n/**\n * Safely parse JSON payloads.\n *\n * @param {string} data - The payload to be parsed.\n * @returns The parsed object.\n */\nexport function safeJsonParse(data) {\n    return BourneParse(data);\n}\n","import Postis from './postis';\n/**\n * The default options for postis.\n *\n * @type {Object}\n */\nconst DEFAULT_POSTIS_OPTIONS = {\n    window: window.opener || window.parent\n};\n/**\n * The postis method used for all messages.\n *\n * @type {string}\n */\nconst POSTIS_METHOD_NAME = 'message';\n/**\n * Implements message transport using the postMessage API.\n */\nexport default class PostMessageITransportBackend {\n    /**\n     * Creates new PostMessageITransportBackend instance.\n     *\n     * @param {Object} options - Optional parameters for configuration of the\n     * transport.\n     */\n    constructor({ postisOptions } = {}) {\n        this.postis = new Postis({\n            ...DEFAULT_POSTIS_OPTIONS,\n            ...postisOptions\n        });\n        this._receiveCallback = () => {\n            // Do nothing until a callback is set by the consumer of\n            // PostMessageITransportBackend via setReceiveCallback.\n        };\n        this.postis.listen(POSTIS_METHOD_NAME, (message) => this._receiveCallback(message));\n    }\n    /**\n     * Disposes the allocated resources.\n     *\n     * @returns {void}\n     */\n    dispose() {\n        this.postis.destroy();\n    }\n    /**\n     * Sends the passed message.\n     *\n     * @param {Object} message - The message to be sent.\n     * @returns {void}\n     */\n    send(message) {\n        this.postis.send({\n            method: POSTIS_METHOD_NAME,\n            params: message\n        });\n    }\n    /**\n     * Sets the callback for receiving data.\n     *\n     * @param {Function} callback - The new callback.\n     * @returns {void}\n     */\n    setReceiveCallback(callback) {\n        this._receiveCallback = callback;\n    }\n}\n","const rnds8 = new Uint8Array(16);\nexport default function rng() {\n    return crypto.getRandomValues(rnds8);\n}\n","import validate from './validate.js';\nconst byteToHex = [];\nfor (let i = 0; i < 256; ++i) {\n    byteToHex.push((i + 0x100).toString(16).slice(1));\n}\nexport function unsafeStringify(arr, offset = 0) {\n    return (byteToHex[arr[offset + 0]] +\n        byteToHex[arr[offset + 1]] +\n        byteToHex[arr[offset + 2]] +\n        byteToHex[arr[offset + 3]] +\n        '-' +\n        byteToHex[arr[offset + 4]] +\n        byteToHex[arr[offset + 5]] +\n        '-' +\n        byteToHex[arr[offset + 6]] +\n        byteToHex[arr[offset + 7]] +\n        '-' +\n        byteToHex[arr[offset + 8]] +\n        byteToHex[arr[offset + 9]] +\n        '-' +\n        byteToHex[arr[offset + 10]] +\n        byteToHex[arr[offset + 11]] +\n        byteToHex[arr[offset + 12]] +\n        byteToHex[arr[offset + 13]] +\n        byteToHex[arr[offset + 14]] +\n        byteToHex[arr[offset + 15]]).toLowerCase();\n}\nfunction stringify(arr, offset = 0) {\n    const uuid = unsafeStringify(arr, offset);\n    if (!validate(uuid)) {\n        throw TypeError('Stringified UUID is invalid');\n    }\n    return uuid;\n}\nexport default stringify;\n","import rng from './rng.js';\nimport { unsafeStringify } from './stringify.js';\nfunction v4(options, buf, offset) {\n    if (!buf && !options && crypto.randomUUID) {\n        return crypto.randomUUID();\n    }\n    return _v4(options, buf, offset);\n}\nfunction _v4(options, buf, offset) {\n    options = options || {};\n    const rnds = options.random ?? options.rng?.() ?? rng();\n    if (rnds.length < 16) {\n        throw new Error('Random bytes length must be >= 16');\n    }\n    rnds[6] = (rnds[6] & 0x0f) | 0x40;\n    rnds[8] = (rnds[8] & 0x3f) | 0x80;\n    if (buf) {\n        offset = offset || 0;\n        if (offset < 0 || offset + 16 > buf.length) {\n            throw new RangeError(`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`);\n        }\n        for (let i = 0; i < 16; ++i) {\n            buf[offset + i] = rnds[i];\n        }\n        return buf;\n    }\n    return unsafeStringify(rnds);\n}\nexport default v4;\n","/**\n * @const\n */\nconst ALPHANUM\n    = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';\n\n/**\n * Hexadecimal digits.\n * @const\n */\nconst HEX_DIGITS = '0123456789abcdef';\n\n/**\n * Generates random int within the range [min, max]\n * @param min the minimum value for the generated number\n * @param max the maximum value for the generated number\n * @returns random int number\n */\nexport function randomInt(min: number, max: number): number {\n    return Math.floor(Math.random() * (max - min + 1)) + min;\n}\n\n/**\n * Get random element from array or string.\n * @param {Array|string} arr source\n * @returns array element or string character\n */\nexport function randomElement<T>(arr: T[] | string): T | string {\n    return arr[randomInt(0, arr.length - 1)];\n}\n\n/**\n * Generate random alphanumeric string.\n * @param {number} length expected string length\n * @returns {string} random string of specified length\n */\nexport function randomAlphanumStr(length: number): string {\n    let result = '';\n\n    for (let i = 0; i < length; i += 1) {\n        result += randomElement(ALPHANUM);\n    }\n\n    return result;\n}\n\n/**\n * Exported interface.\n */\nconst RandomUtil = {\n    /**\n     * Returns a random hex digit.\n     * @returns {*}\n     */\n    randomAlphanumStr,\n    randomElement,\n    randomHexDigit(): string {\n        return randomElement(HEX_DIGITS) as string;\n    },\n\n    /**\n     * Returns a random string of hex digits with length 'len'.\n     * @param len the length.\n     */\n    randomHexString(len: number): string {\n        let ret = '';\n\n        while (len--) { // eslint-disable-line no-param-reassign\n            ret += this.randomHexDigit();\n        }\n\n        return ret;\n    },\n    randomInt\n};\n\nexport default RandomUtil;\n","import { randomAlphanumStr, randomElement } from './RandomUtil';\n\n/**\n * from faker.js - Copyright (c) 2014-2015 Matthew Bergman & Marak Squires\n * MIT License\n * http://github.com/marak/faker.js/\n *\n * @const\n */\nconst names: string[] = [\n    'Aaliyah', 'Aaron', 'Abagail', 'Abbey', 'Abbie', 'Abbigail', 'Abby',\n    'Abdiel', 'Abdul', 'Abdullah', 'Abe', 'Abel', 'Abelardo', 'Abigail',\n    'Abigale', 'Abigayle', 'Abner', 'Abraham', 'Ada', 'Adah', 'Adalberto',\n    'Adaline', 'Adam', 'Adan', 'Addie', 'Addison', 'Adela', 'Adelbert', 'Adele',\n    'Adelia', 'Adeline', 'Adell', 'Adella', 'Adelle', 'Aditya', 'Adolf',\n    'Adolfo', 'Adolph', 'Adolphus', 'Adonis', 'Adrain', 'Adrian', 'Adriana',\n    'Adrianna', 'Adriel', 'Adrien', 'Adrienne', 'Afton', 'Aglae', 'Agnes',\n    'Agustin', 'Agustina', 'Ahmad', 'Ahmed', 'Aida', 'Aidan', 'Aiden', 'Aileen',\n    'Aisha', 'Aiyana', 'Akeem', 'Al', 'Alaina', 'Alan', 'Alana', 'Alanis',\n    'Alanna', 'Alayna', 'Alba', 'Albert', 'Alberta', 'Albertha', 'Alberto',\n    'Albin', 'Albina', 'Alda', 'Alden', 'Alec', 'Aleen', 'Alejandra',\n    'Alejandrin', 'Alek', 'Alena', 'Alene', 'Alessandra', 'Alessandro',\n    'Alessia', 'Aletha', 'Alex', 'Alexa', 'Alexander', 'Alexandra', 'Alexandre',\n    'Alexandrea', 'Alexandria', 'Alexandrine', 'Alexandro', 'Alexane',\n    'Alexanne', 'Alexie', 'Alexis', 'Alexys', 'Alexzander', 'Alf', 'Alfonso',\n    'Alfonzo', 'Alford', 'Alfred', 'Alfreda', 'Alfredo', 'Ali', 'Alia', 'Alice',\n    'Alicia', 'Alisa', 'Alisha', 'Alison', 'Alivia', 'Aliya', 'Aliyah', 'Aliza',\n    'Alize', 'Allan', 'Allen', 'Allene', 'Allie', 'Allison', 'Ally', 'Alphonso',\n    'Alta', 'Althea', 'Alva', 'Alvah', 'Alvena', 'Alvera', 'Alverta', 'Alvina',\n    'Alvis', 'Alyce', 'Alycia', 'Alysa', 'Alysha', 'Alyson', 'Alysson',\n    'Amalia', 'Amanda', 'Amani', 'Amara', 'Amari', 'Amaya', 'Amber', 'Ambrose',\n    'Amelia', 'Amelie', 'Amely', 'America', 'Americo', 'Amie', 'Amina', 'Amir',\n    'Amira', 'Amiya', 'Amos', 'Amparo', 'Amy', 'Amya', 'Ana', 'Anabel',\n    'Anabelle', 'Anahi', 'Anais', 'Anastacio', 'Anastasia', 'Anderson', 'Andre',\n    'Andreane', 'Andreanne', 'Andres', 'Andrew', 'Andy', 'Angel', 'Angela',\n    'Angelica', 'Angelina', 'Angeline', 'Angelita', 'Angelo', 'Angie', 'Angus',\n    'Anibal', 'Anika', 'Anissa', 'Anita', 'Aniya', 'Aniyah', 'Anjali', 'Anna',\n    'Annabel', 'Annabell', 'Annabelle', 'Annalise', 'Annamae', 'Annamarie',\n    'Anne', 'Annetta', 'Annette', 'Annie', 'Ansel', 'Ansley', 'Anthony',\n    'Antoinette', 'Antone', 'Antonetta', 'Antonette', 'Antonia', 'Antonietta',\n    'Antonina', 'Antonio', 'Antwan', 'Antwon', 'Anya', 'April', 'Ara',\n    'Araceli', 'Aracely', 'Arch', 'Archibald', 'Ardella', 'Arden', 'Ardith',\n    'Arely', 'Ari', 'Ariane', 'Arianna', 'Aric', 'Ariel', 'Arielle', 'Arjun',\n    'Arlene', 'Arlie', 'Arlo', 'Armand', 'Armando', 'Armani', 'Arnaldo', 'Arne',\n    'Arno', 'Arnold', 'Arnoldo', 'Arnulfo', 'Aron', 'Art', 'Arthur', 'Arturo',\n    'Arvel', 'Arvid', 'Arvilla', 'Aryanna', 'Asa', 'Asha', 'Ashlee', 'Ashleigh',\n    'Ashley', 'Ashly', 'Ashlynn', 'Ashton', 'Ashtyn', 'Asia', 'Assunta',\n    'Astrid', 'Athena', 'Aubree', 'Aubrey', 'Audie', 'Audra', 'Audreanne',\n    'Audrey', 'August', 'Augusta', 'Augustine', 'Augustus', 'Aurelia',\n    'Aurelie', 'Aurelio', 'Aurore', 'Austen', 'Austin', 'Austyn', 'Autumn',\n    'Ava', 'Avery', 'Avis', 'Axel', 'Ayana', 'Ayden', 'Ayla', 'Aylin', 'Baby',\n    'Bailee', 'Bailey', 'Barbara', 'Barney', 'Baron', 'Barrett', 'Barry',\n    'Bart', 'Bartholome', 'Barton', 'Baylee', 'Beatrice', 'Beau', 'Beaulah',\n    'Bell', 'Bella', 'Belle', 'Ben', 'Benedict', 'Benjamin', 'Bennett',\n    'Bennie', 'Benny', 'Benton', 'Berenice', 'Bernadette', 'Bernadine',\n    'Bernard', 'Bernardo', 'Berneice', 'Bernhard', 'Bernice', 'Bernie',\n    'Berniece', 'Bernita', 'Berry', 'Bert', 'Berta', 'Bertha', 'Bertram',\n    'Bertrand', 'Beryl', 'Bessie', 'Beth', 'Bethany', 'Bethel', 'Betsy',\n    'Bette', 'Bettie', 'Betty', 'Bettye', 'Beulah', 'Beverly', 'Bianka', 'Bill',\n    'Billie', 'Billy', 'Birdie', 'Blair', 'Blaise', 'Blake', 'Blanca',\n    'Blanche', 'Blaze', 'Bo', 'Bobbie', 'Bobby', 'Bonita', 'Bonnie', 'Boris',\n    'Boyd', 'Brad', 'Braden', 'Bradford', 'Bradley', 'Bradly', 'Brady',\n    'Braeden', 'Brain', 'Brandi', 'Brando', 'Brandon', 'Brandt', 'Brandy',\n    'Brandyn', 'Brannon', 'Branson', 'Brant', 'Braulio', 'Braxton', 'Brayan',\n    'Breana', 'Breanna', 'Breanne', 'Brenda', 'Brendan', 'Brenden', 'Brendon',\n    'Brenna', 'Brennan', 'Brennon', 'Brent', 'Bret', 'Brett', 'Bria', 'Brian',\n    'Briana', 'Brianne', 'Brice', 'Bridget', 'Bridgette', 'Bridie', 'Brielle',\n    'Brigitte', 'Brionna', 'Brisa', 'Britney', 'Brittany', 'Brock', 'Broderick',\n    'Brody', 'Brook', 'Brooke', 'Brooklyn', 'Brooks', 'Brown', 'Bruce',\n    'Bryana', 'Bryce', 'Brycen', 'Bryon', 'Buck', 'Bud', 'Buddy', 'Buford',\n    'Bulah', 'Burdette', 'Burley', 'Burnice', 'Buster', 'Cade', 'Caden',\n    'Caesar', 'Caitlyn', 'Cale', 'Caleb', 'Caleigh', 'Cali', 'Calista',\n    'Callie', 'Camden', 'Cameron', 'Camila', 'Camilla', 'Camille', 'Camren',\n    'Camron', 'Camryn', 'Camylle', 'Candace', 'Candelario', 'Candice',\n    'Candida', 'Candido', 'Cara', 'Carey', 'Carissa', 'Carlee', 'Carleton',\n    'Carley', 'Carli', 'Carlie', 'Carlo', 'Carlos', 'Carlotta', 'Carmel',\n    'Carmela', 'Carmella', 'Carmelo', 'Carmen', 'Carmine', 'Carol', 'Carolanne',\n    'Carole', 'Carolina', 'Caroline', 'Carolyn', 'Carolyne', 'Carrie',\n    'Carroll', 'Carson', 'Carter', 'Cary', 'Casandra', 'Casey', 'Casimer',\n    'Casimir', 'Casper', 'Cassandra', 'Cassandre', 'Cassidy', 'Cassie',\n    'Catalina', 'Caterina', 'Catharine', 'Catherine', 'Cathrine', 'Cathryn',\n    'Cathy', 'Cayla', 'Ceasar', 'Cecelia', 'Cecil', 'Cecile', 'Cecilia',\n    'Cedrick', 'Celestine', 'Celestino', 'Celia', 'Celine', 'Cesar', 'Chad',\n    'Chadd', 'Chadrick', 'Chaim', 'Chance', 'Chandler', 'Chanel', 'Chanelle',\n    'Charity', 'Charlene', 'Charles', 'Charley', 'Charlie', 'Charlotte',\n    'Chase', 'Chasity', 'Chauncey', 'Chaya', 'Chaz', 'Chelsea', 'Chelsey',\n    'Chelsie', 'Chesley', 'Chester', 'Chet', 'Cheyanne', 'Cheyenne', 'Chloe',\n    'Chris', 'Christ', 'Christa', 'Christelle', 'Christian', 'Christiana',\n    'Christina', 'Christine', 'Christop', 'Christophe', 'Christopher',\n    'Christy', 'Chyna', 'Ciara', 'Cicero', 'Cielo', 'Cierra', 'Cindy',\n    'Citlalli', 'Clair', 'Claire', 'Clara', 'Clarabelle', 'Clare', 'Clarissa',\n    'Clark', 'Claud', 'Claude', 'Claudia', 'Claudie', 'Claudine', 'Clay',\n    'Clemens', 'Clement', 'Clementina', 'Clementine', 'Clemmie', 'Cleo',\n    'Cleora', 'Cleta', 'Cletus', 'Cleve', 'Cleveland', 'Clifford', 'Clifton',\n    'Clint', 'Clinton', 'Clotilde', 'Clovis', 'Cloyd', 'Clyde', 'Coby', 'Cody',\n    'Colby', 'Cole', 'Coleman', 'Colin', 'Colleen', 'Collin', 'Colt', 'Colten',\n    'Colton', 'Columbus', 'Concepcion', 'Conner', 'Connie', 'Connor', 'Conor',\n    'Conrad', 'Constance', 'Constantin', 'Consuelo', 'Cooper', 'Cora',\n    'Coralie', 'Corbin', 'Cordelia', 'Cordell', 'Cordia', 'Cordie', 'Corene',\n    'Corine', 'Cornelius', 'Cornell', 'Corrine', 'Cortez', 'Cortney', 'Cory',\n    'Coty', 'Courtney', 'Coy', 'Craig', 'Crawford', 'Creola', 'Cristal',\n    'Cristian', 'Cristina', 'Cristobal', 'Cristopher', 'Cruz', 'Crystal',\n    'Crystel', 'Cullen', 'Curt', 'Curtis', 'Cydney', 'Cynthia', 'Cyril',\n    'Cyrus', 'Dagmar', 'Dahlia', 'Daija', 'Daisha', 'Daisy', 'Dakota', 'Dale',\n    'Dallas', 'Dallin', 'Dalton', 'Damaris', 'Dameon', 'Damian', 'Damien',\n    'Damion', 'Damon', 'Dan', 'Dana', 'Dandre', 'Dane', 'D\\'angelo', 'Dangelo',\n    'Danial', 'Daniela', 'Daniella', 'Danielle', 'Danika', 'Dannie', 'Danny',\n    'Dante', 'Danyka', 'Daphne', 'Daphnee', 'Daphney', 'Darby', 'Daren',\n    'Darian', 'Dariana', 'Darien', 'Dario', 'Darion', 'Darius', 'Darlene',\n    'Daron', 'Darrel', 'Darrell', 'Darren', 'Darrick', 'Darrin', 'Darrion',\n    'Darron', 'Darryl', 'Darwin', 'Daryl', 'Dashawn', 'Dasia', 'Dave', 'David',\n    'Davin', 'Davion', 'Davon', 'Davonte', 'Dawn', 'Dawson', 'Dax', 'Dayana',\n    'Dayna', 'Dayne', 'Dayton', 'Dean', 'Deangelo', 'Deanna', 'Deborah',\n    'Declan', 'Dedric', 'Dedrick', 'Dee', 'Deion', 'Deja', 'Dejah', 'Dejon',\n    'Dejuan', 'Delaney', 'Delbert', 'Delfina', 'Delia', 'Delilah', 'Dell',\n    'Della', 'Delmer', 'Delores', 'Delpha', 'Delphia', 'Delphine', 'Delta',\n    'Demarco', 'Demarcus', 'Demario', 'Demetris', 'Demetrius', 'Demond', 'Dena',\n    'Denis', 'Dennis', 'Deon', 'Deondre', 'Deontae', 'Deonte', 'Dereck',\n    'Derek', 'Derick', 'Deron', 'Derrick', 'Deshaun', 'Deshawn', 'Desiree',\n    'Desmond', 'Dessie', 'Destany', 'Destin', 'Destinee', 'Destiney', 'Destini',\n    'Destiny', 'Devan', 'Devante', 'Deven', 'Devin', 'Devon', 'Devonte',\n    'Devyn', 'Dewayne', 'Dewitt', 'Dexter', 'Diamond', 'Diana', 'Dianna',\n    'Diego', 'Dillan', 'Dillon', 'Dimitri', 'Dina', 'Dino', 'Dion', 'Dixie',\n    'Dock', 'Dolly', 'Dolores', 'Domenic', 'Domenica', 'Domenick', 'Domenico',\n    'Domingo', 'Dominic', 'Dominique', 'Don', 'Donald', 'Donato', 'Donavon',\n    'Donna', 'Donnell', 'Donnie', 'Donny', 'Dora', 'Dorcas', 'Dorian', 'Doris',\n    'Dorothea', 'Dorothy', 'Dorris', 'Dortha', 'Dorthy', 'Doug', 'Douglas',\n    'Dovie', 'Doyle', 'Drake', 'Drew', 'Duane', 'Dudley', 'Dulce', 'Duncan',\n    'Durward', 'Dustin', 'Dusty', 'Dwight', 'Dylan', 'Earl', 'Earlene',\n    'Earline', 'Earnest', 'Earnestine', 'Easter', 'Easton', 'Ebba', 'Ebony',\n    'Ed', 'Eda', 'Edd', 'Eddie', 'Eden', 'Edgar', 'Edgardo', 'Edison', 'Edmond',\n    'Edmund', 'Edna', 'Eduardo', 'Edward', 'Edwardo', 'Edwin', 'Edwina',\n    'Edyth', 'Edythe', 'Effie', 'Efrain', 'Efren', 'Eileen', 'Einar', 'Eino',\n    'Eladio', 'Elaina', 'Elbert', 'Elda', 'Eldon', 'Eldora', 'Eldred',\n    'Eldridge', 'Eleanora', 'Eleanore', 'Eleazar', 'Electa', 'Elena', 'Elenor',\n    'Elenora', 'Eleonore', 'Elfrieda', 'Eli', 'Elian', 'Eliane', 'Elias',\n    'Eliezer', 'Elijah', 'Elinor', 'Elinore', 'Elisa', 'Elisabeth', 'Elise',\n    'Eliseo', 'Elisha', 'Elissa', 'Eliza', 'Elizabeth', 'Ella', 'Ellen',\n    'Ellie', 'Elliot', 'Elliott', 'Ellis', 'Ellsworth', 'Elmer', 'Elmira',\n    'Elmo', 'Elmore', 'Elna', 'Elnora', 'Elody', 'Eloisa', 'Eloise', 'Elouise',\n    'Eloy', 'Elroy', 'Elsa', 'Else', 'Elsie', 'Elta', 'Elton', 'Elva', 'Elvera',\n    'Elvie', 'Elvis', 'Elwin', 'Elwyn', 'Elyse', 'Elyssa', 'Elza', 'Emanuel',\n    'Emelia', 'Emelie', 'Emely', 'Emerald', 'Emerson', 'Emery', 'Emie', 'Emil',\n    'Emile', 'Emilia', 'Emiliano', 'Emilie', 'Emilio', 'Emily', 'Emma',\n    'Emmalee', 'Emmanuel', 'Emmanuelle', 'Emmet', 'Emmett', 'Emmie', 'Emmitt',\n    'Emmy', 'Emory', 'Ena', 'Enid', 'Enoch', 'Enola', 'Enos', 'Enrico',\n    'Enrique', 'Ephraim', 'Era', 'Eriberto', 'Eric', 'Erica', 'Erich', 'Erick',\n    'Ericka', 'Erik', 'Erika', 'Erin', 'Erling', 'Erna', 'Ernest', 'Ernestina',\n    'Ernestine', 'Ernesto', 'Ernie', 'Ervin', 'Erwin', 'Eryn', 'Esmeralda',\n    'Esperanza', 'Esta', 'Esteban', 'Estefania', 'Estel', 'Estell', 'Estella',\n    'Estelle', 'Estevan', 'Esther', 'Estrella', 'Etha', 'Ethan', 'Ethel',\n    'Ethelyn', 'Ethyl', 'Ettie', 'Eudora', 'Eugene', 'Eugenia', 'Eula', 'Eulah',\n    'Eulalia', 'Euna', 'Eunice', 'Eusebio', 'Eva', 'Evalyn', 'Evan',\n    'Evangeline', 'Evans', 'Eve', 'Eveline', 'Evelyn', 'Everardo', 'Everett',\n    'Everette', 'Evert', 'Evie', 'Ewald', 'Ewell', 'Ezekiel', 'Ezequiel',\n    'Ezra', 'Fabian', 'Fabiola', 'Fae', 'Fannie', 'Fanny', 'Fatima', 'Faustino',\n    'Fausto', 'Favian', 'Fay', 'Faye', 'Federico', 'Felicia', 'Felicita',\n    'Felicity', 'Felipa', 'Felipe', 'Felix', 'Felton', 'Fermin', 'Fern',\n    'Fernando', 'Ferne', 'Fidel', 'Filiberto', 'Filomena', 'Finn', 'Fiona',\n    'Flavie', 'Flavio', 'Fleta', 'Fletcher', 'Flo', 'Florence', 'Florencio',\n    'Florian', 'Florida', 'Florine', 'Flossie', 'Floy', 'Floyd', 'Ford',\n    'Forest', 'Forrest', 'Foster', 'Frances', 'Francesca', 'Francesco',\n    'Francis', 'Francisca', 'Francisco', 'Franco', 'Frank', 'Frankie', 'Franz',\n    'Fred', 'Freda', 'Freddie', 'Freddy', 'Frederic', 'Frederick', 'Frederik',\n    'Frederique', 'Fredrick', 'Fredy', 'Freeda', 'Freeman', 'Freida', 'Frida',\n    'Frieda', 'Friedrich', 'Fritz', 'Furman', 'Gabe', 'Gabriel', 'Gabriella',\n    'Gabrielle', 'Gaetano', 'Gage', 'Gail', 'Gardner', 'Garett', 'Garfield',\n    'Garland', 'Garnet', 'Garnett', 'Garret', 'Garrett', 'Garrick', 'Garrison',\n    'Garry', 'Garth', 'Gaston', 'Gavin', 'Gay', 'Gayle', 'Gaylord', 'Gene',\n    'General', 'Genesis', 'Genevieve', 'Gennaro', 'Genoveva', 'Geo', 'Geoffrey',\n    'George', 'Georgette', 'Georgiana', 'Georgianna', 'Geovanni', 'Geovanny',\n    'Geovany', 'Gerald', 'Geraldine', 'Gerard', 'Gerardo', 'Gerda', 'Gerhard',\n    'Germaine', 'German', 'Gerry', 'Gerson', 'Gertrude', 'Gia', 'Gianni',\n    'Gideon', 'Gilbert', 'Gilberto', 'Gilda', 'Giles', 'Gillian', 'Gina',\n    'Gino', 'Giovani', 'Giovanna', 'Giovanni', 'Giovanny', 'Gisselle',\n    'Giuseppe', 'Gladyce', 'Gladys', 'Glen', 'Glenda', 'Glenna', 'Glennie',\n    'Gloria', 'Godfrey', 'Golda', 'Golden', 'Gonzalo', 'Gordon', 'Grace',\n    'Gracie', 'Graciela', 'Grady', 'Graham', 'Grant', 'Granville', 'Grayce',\n    'Grayson', 'Green', 'Greg', 'Gregg', 'Gregoria', 'Gregorio', 'Gregory',\n    'Greta', 'Gretchen', 'Greyson', 'Griffin', 'Grover', 'Guadalupe', 'Gudrun',\n    'Guido', 'Guillermo', 'Guiseppe', 'Gunnar', 'Gunner', 'Gus', 'Gussie',\n    'Gust', 'Gustave', 'Guy', 'Gwen', 'Gwendolyn', 'Hadley', 'Hailee', 'Hailey',\n    'Hailie', 'Hal', 'Haleigh', 'Haley', 'Halie', 'Halle', 'Hallie', 'Hank',\n    'Hanna', 'Hannah', 'Hans', 'Hardy', 'Harley', 'Harmon', 'Harmony', 'Harold',\n    'Harrison', 'Harry', 'Harvey', 'Haskell', 'Hassan', 'Hassie', 'Hattie',\n    'Haven', 'Hayden', 'Haylee', 'Hayley', 'Haylie', 'Hazel', 'Hazle', 'Heath',\n    'Heather', 'Heaven', 'Heber', 'Hector', 'Heidi', 'Helen', 'Helena',\n    'Helene', 'Helga', 'Hellen', 'Helmer', 'Heloise', 'Henderson', 'Henri',\n    'Henriette', 'Henry', 'Herbert', 'Herman', 'Hermann', 'Hermina', 'Herminia',\n    'Herminio', 'Hershel', 'Herta', 'Hertha', 'Hester', 'Hettie', 'Hilario',\n    'Hilbert', 'Hilda', 'Hildegard', 'Hillard', 'Hillary', 'Hilma', 'Hilton',\n    'Hipolito', 'Hiram', 'Hobart', 'Holden', 'Hollie', 'Hollis', 'Holly',\n    'Hope', 'Horace', 'Horacio', 'Hortense', 'Hosea', 'Houston', 'Howard',\n    'Howell', 'Hoyt', 'Hubert', 'Hudson', 'Hugh', 'Hulda', 'Humberto', 'Hunter',\n    'Hyman', 'Ian', 'Ibrahim', 'Icie', 'Ida', 'Idell', 'Idella', 'Ignacio',\n    'Ignatius', 'Ike', 'Ila', 'Ilene', 'Iliana', 'Ima', 'Imani', 'Imelda',\n    'Immanuel', 'Imogene', 'Ines', 'Irma', 'Irving', 'Irwin', 'Isaac', 'Isabel',\n    'Isabell', 'Isabella', 'Isabelle', 'Isac', 'Isadore', 'Isai', 'Isaiah',\n    'Isaias', 'Isidro', 'Ismael', 'Isobel', 'Isom', 'Israel', 'Issac', 'Itzel',\n    'Iva', 'Ivah', 'Ivory', 'Ivy', 'Izabella', 'Izaiah', 'Jabari', 'Jace',\n    'Jacey', 'Jacinthe', 'Jacinto', 'Jack', 'Jackeline', 'Jackie', 'Jacklyn',\n    'Jackson', 'Jacky', 'Jaclyn', 'Jacquelyn', 'Jacques', 'Jacynthe', 'Jada',\n    'Jade', 'Jaden', 'Jadon', 'Jadyn', 'Jaeden', 'Jaida', 'Jaiden', 'Jailyn',\n    'Jaime', 'Jairo', 'Jakayla', 'Jake', 'Jakob', 'Jaleel', 'Jalen', 'Jalon',\n    'Jalyn', 'Jamaal', 'Jamal', 'Jamar', 'Jamarcus', 'Jamel', 'Jameson',\n    'Jamey', 'Jamie', 'Jamil', 'Jamir', 'Jamison', 'Jammie', 'Jan', 'Jana',\n    'Janae', 'Jane', 'Janelle', 'Janessa', 'Janet', 'Janice', 'Janick', 'Janie',\n    'Janis', 'Janiya', 'Jannie', 'Jany', 'Jaquan', 'Jaquelin', 'Jaqueline',\n    'Jared', 'Jaren', 'Jarod', 'Jaron', 'Jarred', 'Jarrell', 'Jarret',\n    'Jarrett', 'Jarrod', 'Jarvis', 'Jasen', 'Jasmin', 'Jason', 'Jasper',\n    'Jaunita', 'Javier', 'Javon', 'Javonte', 'Jay', 'Jayce', 'Jaycee', 'Jayda',\n    'Jayde', 'Jayden', 'Jaydon', 'Jaylan', 'Jaylen', 'Jaylin', 'Jaylon',\n    'Jayme', 'Jayne', 'Jayson', 'Jazlyn', 'Jazmin', 'Jazmyn', 'Jazmyne', 'Jean',\n    'Jeanette', 'Jeanie', 'Jeanne', 'Jed', 'Jedediah', 'Jedidiah', 'Jeff',\n    'Jefferey', 'Jeffery', 'Jeffrey', 'Jeffry', 'Jena', 'Jenifer', 'Jennie',\n    'Jennifer', 'Jennings', 'Jennyfer', 'Jensen', 'Jerad', 'Jerald', 'Jeramie',\n    'Jeramy', 'Jerel', 'Jeremie', 'Jeremy', 'Jermain', 'Jermaine', 'Jermey',\n    'Jerod', 'Jerome', 'Jeromy', 'Jerrell', 'Jerrod', 'Jerrold', 'Jerry',\n    'Jess', 'Jesse', 'Jessica', 'Jessie', 'Jessika', 'Jessy', 'Jessyca',\n    'Jesus', 'Jett', 'Jettie', 'Jevon', 'Jewel', 'Jewell', 'Jillian', 'Jimmie',\n    'Jimmy', 'Jo', 'Joan', 'Joana', 'Joanie', 'Joanne', 'Joannie', 'Joanny',\n    'Joany', 'Joaquin', 'Jocelyn', 'Jodie', 'Jody', 'Joe', 'Joel', 'Joelle',\n    'Joesph', 'Joey', 'Johan', 'Johann', 'Johanna', 'Johathan', 'John',\n    'Johnathan', 'Johnathon', 'Johnnie', 'Johnny', 'Johnpaul', 'Johnson',\n    'Jolie', 'Jon', 'Jonas', 'Jonatan', 'Jonathan', 'Jonathon', 'Jordan',\n    'Jordane', 'Jordi', 'Jordon', 'Jordy', 'Jordyn', 'Jorge', 'Jose', 'Josefa',\n    'Josefina', 'Joseph', 'Josephine', 'Josh', 'Joshua', 'Joshuah', 'Josiah',\n    'Josiane', 'Josianne', 'Josie', 'Josue', 'Jovan', 'Jovani', 'Jovanny',\n    'Jovany', 'Joy', 'Joyce', 'Juana', 'Juanita', 'Judah', 'Judd', 'Jude',\n    'Judge', 'Judson', 'Judy', 'Jules', 'Julia', 'Julian', 'Juliana',\n    'Julianne', 'Julie', 'Julien', 'Juliet', 'Julio', 'Julius', 'June',\n    'Junior', 'Junius', 'Justen', 'Justice', 'Justina', 'Justine', 'Juston',\n    'Justus', 'Justyn', 'Juvenal', 'Juwan', 'Kacey', 'Kaci', 'Kacie', 'Kade',\n    'Kaden', 'Kadin', 'Kaela', 'Kaelyn', 'Kaia', 'Kailee', 'Kailey', 'Kailyn',\n    'Kaitlin', 'Kaitlyn', 'Kale', 'Kaleb', 'Kaleigh', 'Kaley', 'Kali', 'Kallie',\n    'Kameron', 'Kamille', 'Kamren', 'Kamron', 'Kamryn', 'Kane', 'Kara',\n    'Kareem', 'Karelle', 'Karen', 'Kari', 'Kariane', 'Karianne', 'Karina',\n    'Karine', 'Karl', 'Karlee', 'Karley', 'Karli', 'Karlie', 'Karolann',\n    'Karson', 'Kasandra', 'Kasey', 'Kassandra', 'Katarina', 'Katelin',\n    'Katelyn', 'Katelynn', 'Katharina', 'Katherine', 'Katheryn', 'Kathleen',\n    'Kathlyn', 'Kathryn', 'Kathryne', 'Katlyn', 'Katlynn', 'Katrina', 'Katrine',\n    'Kattie', 'Kavon', 'Kay', 'Kaya', 'Kaycee', 'Kayden', 'Kayla', 'Kaylah',\n    'Kaylee', 'Kayleigh', 'Kayley', 'Kayli', 'Kaylie', 'Kaylin', 'Keagan',\n    'Keanu', 'Keara', 'Keaton', 'Keegan', 'Keeley', 'Keely', 'Keenan', 'Keira',\n    'Keith', 'Kellen', 'Kelley', 'Kelli', 'Kellie', 'Kelly', 'Kelsi', 'Kelsie',\n    'Kelton', 'Kelvin', 'Ken', 'Kendall', 'Kendra', 'Kendrick', 'Kenna',\n    'Kennedi', 'Kennedy', 'Kenneth', 'Kennith', 'Kenny', 'Kenton', 'Kenya',\n    'Kenyatta', 'Kenyon', 'Keon', 'Keshaun', 'Keshawn', 'Keven', 'Kevin',\n    'Kevon', 'Keyon', 'Keyshawn', 'Khalid', 'Khalil', 'Kian', 'Kiana', 'Kianna',\n    'Kiara', 'Kiarra', 'Kiel', 'Kiera', 'Kieran', 'Kiley', 'Kim', 'Kimberly',\n    'King', 'Kip', 'Kira', 'Kirk', 'Kirsten', 'Kirstin', 'Kitty', 'Kobe',\n    'Koby', 'Kody', 'Kolby', 'Kole', 'Korbin', 'Korey', 'Kory', 'Kraig', 'Kris',\n    'Krista', 'Kristian', 'Kristin', 'Kristina', 'Kristofer', 'Kristoffer',\n    'Kristopher', 'Kristy', 'Krystal', 'Krystel', 'Krystina', 'Kurt', 'Kurtis',\n    'Kyla', 'Kyle', 'Kylee', 'Kyleigh', 'Kyler', 'Kylie', 'Kyra', 'Lacey',\n    'Lacy', 'Ladarius', 'Lafayette', 'Laila', 'Laisha', 'Lamar', 'Lambert',\n    'Lamont', 'Lance', 'Landen', 'Lane', 'Laney', 'Larissa', 'Laron', 'Larry',\n    'Larue', 'Laura', 'Laurel', 'Lauren', 'Laurence', 'Lauretta', 'Lauriane',\n    'Laurianne', 'Laurie', 'Laurine', 'Laury', 'Lauryn', 'Lavada', 'Lavern',\n    'Laverna', 'Laverne', 'Lavina', 'Lavinia', 'Lavon', 'Lavonne', 'Lawrence',\n    'Lawson', 'Layla', 'Layne', 'Lazaro', 'Lea', 'Leann', 'Leanna', 'Leanne',\n    'Leatha', 'Leda', 'Lee', 'Leif', 'Leila', 'Leilani', 'Lela', 'Lelah',\n    'Leland', 'Lelia', 'Lempi', 'Lemuel', 'Lenna', 'Lennie', 'Lenny', 'Lenora',\n    'Lenore', 'Leo', 'Leola', 'Leon', 'Leonard', 'Leonardo', 'Leone', 'Leonel',\n    'Leonie', 'Leonor', 'Leonora', 'Leopold', 'Leopoldo', 'Leora', 'Lera',\n    'Lesley', 'Leslie', 'Lesly', 'Lessie', 'Lester', 'Leta', 'Letha', 'Letitia',\n    'Levi', 'Lew', 'Lewis', 'Lexi', 'Lexie', 'Lexus', 'Lia', 'Liam', 'Liana',\n    'Libbie', 'Libby', 'Lila', 'Lilian', 'Liliana', 'Liliane', 'Lilla',\n    'Lillian', 'Lilliana', 'Lillie', 'Lilly', 'Lily', 'Lilyan', 'Lina',\n    'Lincoln', 'Linda', 'Lindsay', 'Lindsey', 'Linnea', 'Linnie', 'Linwood',\n    'Lionel', 'Lisa', 'Lisandro', 'Lisette', 'Litzy', 'Liza', 'Lizeth',\n    'Lizzie', 'Llewellyn', 'Lloyd', 'Logan', 'Lois', 'Lola', 'Lolita', 'Loma',\n    'Lon', 'London', 'Lonie', 'Lonnie', 'Lonny', 'Lonzo', 'Lora', 'Loraine',\n    'Loren', 'Lorena', 'Lorenz', 'Lorenza', 'Lorenzo', 'Lori', 'Lorine',\n    'Lorna', 'Lottie', 'Lou', 'Louie', 'Louisa', 'Lourdes', 'Louvenia',\n    'Lowell', 'Loy', 'Loyal', 'Loyce', 'Lucas', 'Luciano', 'Lucie', 'Lucienne',\n    'Lucile', 'Lucinda', 'Lucio', 'Lucious', 'Lucius', 'Lucy', 'Ludie',\n    'Ludwig', 'Lue', 'Luella', 'Luigi', 'Luis', 'Luisa', 'Lukas', 'Lula',\n    'Lulu', 'Luna', 'Lupe', 'Lura', 'Lurline', 'Luther', 'Luz', 'Lyda', 'Lydia',\n    'Lyla', 'Lynn', 'Lyric', 'Lysanne', 'Mabel', 'Mabelle', 'Mable', 'Mac',\n    'Macey', 'Maci', 'Macie', 'Mack', 'Mackenzie', 'Macy', 'Madaline',\n    'Madalyn', 'Maddison', 'Madeline', 'Madelyn', 'Madelynn', 'Madge', 'Madie',\n    'Madilyn', 'Madisen', 'Madison', 'Madisyn', 'Madonna', 'Madyson', 'Mae',\n    'Maegan', 'Maeve', 'Mafalda', 'Magali', 'Magdalen', 'Magdalena', 'Maggie',\n    'Magnolia', 'Magnus', 'Maia', 'Maida', 'Maiya', 'Major', 'Makayla',\n    'Makenna', 'Makenzie', 'Malachi', 'Malcolm', 'Malika', 'Malinda', 'Mallie',\n    'Mallory', 'Malvina', 'Mandy', 'Manley', 'Manuel', 'Manuela', 'Mara',\n    'Marc', 'Marcel', 'Marcelina', 'Marcelino', 'Marcella', 'Marcelle',\n    'Marcellus', 'Marcelo', 'Marcia', 'Marco', 'Marcos', 'Marcus', 'Margaret',\n    'Margarete', 'Margarett', 'Margaretta', 'Margarette', 'Margarita', 'Marge',\n    'Margie', 'Margot', 'Margret', 'Marguerite', 'Maria', 'Mariah', 'Mariam',\n    'Marian', 'Mariana', 'Mariane', 'Marianna', 'Marianne', 'Mariano',\n    'Maribel', 'Marie', 'Mariela', 'Marielle', 'Marietta', 'Marilie', 'Marilou',\n    'Marilyne', 'Marina', 'Mario', 'Marion', 'Marisa', 'Marisol', 'Maritza',\n    'Marjolaine', 'Marjorie', 'Marjory', 'Mark', 'Markus', 'Marlee', 'Marlen',\n    'Marlene', 'Marley', 'Marlin', 'Marlon', 'Marques', 'Marquis', 'Marquise',\n    'Marshall', 'Marta', 'Martin', 'Martina', 'Martine', 'Marty', 'Marvin',\n    'Mary', 'Maryam', 'Maryjane', 'Maryse', 'Mason', 'Mateo', 'Mathew',\n    'Mathias', 'Mathilde', 'Matilda', 'Matilde', 'Matt', 'Matteo', 'Mattie',\n    'Maud', 'Maude', 'Maudie', 'Maureen', 'Maurice', 'Mauricio', 'Maurine',\n    'Maverick', 'Mavis', 'Max', 'Maxie', 'Maxime', 'Maximilian', 'Maximillia',\n    'Maximillian', 'Maximo', 'Maximus', 'Maxine', 'Maxwell', 'May', 'Maya',\n    'Maybell', 'Maybelle', 'Maye', 'Maymie', 'Maynard', 'Mayra', 'Mazie',\n    'Mckayla', 'Mckenna', 'Mckenzie', 'Meagan', 'Meaghan', 'Meda', 'Megane',\n    'Meggie', 'Meghan', 'Mekhi', 'Melany', 'Melba', 'Melisa', 'Melissa',\n    'Mellie', 'Melody', 'Melvin', 'Melvina', 'Melyna', 'Melyssa', 'Mercedes',\n    'Meredith', 'Merl', 'Merle', 'Merlin', 'Merritt', 'Mertie', 'Mervin',\n    'Meta', 'Mia', 'Micaela', 'Micah', 'Michael', 'Michaela', 'Michale',\n    'Micheal', 'Michel', 'Michele', 'Michelle', 'Miguel', 'Mikayla', 'Mike',\n    'Mikel', 'Milan', 'Miles', 'Milford', 'Miller', 'Millie', 'Milo', 'Milton',\n    'Mina', 'Minerva', 'Minnie', 'Miracle', 'Mireille', 'Mireya', 'Misael',\n    'Missouri', 'Misty', 'Mitchel', 'Mitchell', 'Mittie', 'Modesta', 'Modesto',\n    'Mohamed', 'Mohammad', 'Mohammed', 'Moises', 'Mollie', 'Molly', 'Mona',\n    'Monica', 'Monique', 'Monroe', 'Monserrat', 'Monserrate', 'Montana',\n    'Monte', 'Monty', 'Morgan', 'Moriah', 'Morris', 'Mortimer', 'Morton',\n    'Mose', 'Moses', 'Moshe', 'Mossie', 'Mozell', 'Mozelle', 'Muhammad',\n    'Muriel', 'Murl', 'Murphy', 'Murray', 'Mustafa', 'Mya', 'Myah', 'Mylene',\n    'Myles', 'Myra', 'Myriam', 'Myrl', 'Myrna', 'Myron', 'Myrtice', 'Myrtie',\n    'Myrtis', 'Myrtle', 'Nadia', 'Nakia', 'Name', 'Nannie', 'Naomi', 'Naomie',\n    'Napoleon', 'Narciso', 'Nash', 'Nasir', 'Nat', 'Natalia', 'Natalie',\n    'Natasha', 'Nathan', 'Nathanael', 'Nathanial', 'Nathaniel', 'Nathen',\n    'Nayeli', 'Neal', 'Ned', 'Nedra', 'Neha', 'Neil', 'Nelda', 'Nella', 'Nelle',\n    'Nellie', 'Nels', 'Nelson', 'Neoma', 'Nestor', 'Nettie', 'Neva', 'Newell',\n    'Newton', 'Nia', 'Nicholas', 'Nicholaus', 'Nichole', 'Nick', 'Nicklaus',\n    'Nickolas', 'Nico', 'Nicola', 'Nicolas', 'Nicole', 'Nicolette', 'Nigel',\n    'Nikita', 'Nikki', 'Nikko', 'Niko', 'Nikolas', 'Nils', 'Nina', 'Noah',\n    'Noble', 'Noe', 'Noel', 'Noelia', 'Noemi', 'Noemie', 'Noemy', 'Nola',\n    'Nolan', 'Nona', 'Nora', 'Norbert', 'Norberto', 'Norene', 'Norma', 'Norris',\n    'Norval', 'Norwood', 'Nova', 'Novella', 'Nya', 'Nyah', 'Nyasia', 'Obie',\n    'Oceane', 'Ocie', 'Octavia', 'Oda', 'Odell', 'Odessa', 'Odie', 'Ofelia',\n    'Okey', 'Ola', 'Olaf', 'Ole', 'Olen', 'Oleta', 'Olga', 'Olin', 'Oliver',\n    'Ollie', 'Oma', 'Omari', 'Omer', 'Ona', 'Onie', 'Opal', 'Ophelia', 'Ora',\n    'Oral', 'Oran', 'Oren', 'Orie', 'Orin', 'Orion', 'Orland', 'Orlando',\n    'Orlo', 'Orpha', 'Orrin', 'Orval', 'Orville', 'Osbaldo', 'Osborne', 'Oscar',\n    'Osvaldo', 'Oswald', 'Oswaldo', 'Otha', 'Otho', 'Otilia', 'Otis', 'Ottilie',\n    'Ottis', 'Otto', 'Ova', 'Owen', 'Ozella', 'Pablo', 'Paige', 'Palma',\n    'Pamela', 'Pansy', 'Paolo', 'Paris', 'Parker', 'Pascale', 'Pasquale', 'Pat',\n    'Patience', 'Patricia', 'Patrick', 'Patsy', 'Pattie', 'Paul', 'Paula',\n    'Pauline', 'Paxton', 'Payton', 'Pearl', 'Pearlie', 'Pearline', 'Pedro',\n    'Peggie', 'Penelope', 'Percival', 'Percy', 'Perry', 'Pete', 'Peter',\n    'Petra', 'Peyton', 'Philip', 'Phoebe', 'Phyllis', 'Pierce', 'Pierre',\n    'Pietro', 'Pink', 'Pinkie', 'Piper', 'Polly', 'Porter', 'Precious',\n    'Presley', 'Preston', 'Price', 'Prince', 'Princess', 'Priscilla',\n    'Providenci', 'Prudence', 'Queen', 'Queenie', 'Quentin', 'Quincy', 'Quinn',\n    'Quinten', 'Quinton', 'Rachael', 'Rachel', 'Rachelle', 'Rae', 'Raegan',\n    'Rafael', 'Rafaela', 'Raheem', 'Rahsaan', 'Rahul', 'Raina', 'Raleigh',\n    'Ralph', 'Ramiro', 'Ramon', 'Ramona', 'Randal', 'Randall', 'Randi', 'Randy',\n    'Ransom', 'Raoul', 'Raphael', 'Raphaelle', 'Raquel', 'Rashad', 'Rashawn',\n    'Rasheed', 'Raul', 'Raven', 'Ray', 'Raymond', 'Raymundo', 'Reagan',\n    'Reanna', 'Reba', 'Rebeca', 'Rebecca', 'Rebeka', 'Rebekah', 'Reece', 'Reed',\n    'Reese', 'Regan', 'Reggie', 'Reginald', 'Reid', 'Reilly', 'Reina',\n    'Reinhold', 'Remington', 'Rene', 'Renee', 'Ressie', 'Reta', 'Retha',\n    'Retta', 'Reuben', 'Reva', 'Rex', 'Rey', 'Reyes', 'Reymundo', 'Reyna',\n    'Reynold', 'Rhea', 'Rhett', 'Rhianna', 'Rhiannon', 'Rhoda', 'Ricardo',\n    'Richard', 'Richie', 'Richmond', 'Rick', 'Rickey', 'Rickie', 'Ricky',\n    'Rico', 'Rigoberto', 'Riley', 'Rita', 'River', 'Robb', 'Robbie', 'Robert',\n    'Roberta', 'Roberto', 'Robin', 'Robyn', 'Rocio', 'Rocky', 'Rod', 'Roderick',\n    'Rodger', 'Rodolfo', 'Rodrick', 'Rodrigo', 'Roel', 'Rogelio', 'Roger',\n    'Rogers', 'Rolando', 'Rollin', 'Roma', 'Romaine', 'Roman', 'Ron', 'Ronaldo',\n    'Ronny', 'Roosevelt', 'Rory', 'Rosa', 'Rosalee', 'Rosalia', 'Rosalind',\n    'Rosalinda', 'Rosalyn', 'Rosamond', 'Rosanna', 'Rosario', 'Roscoe', 'Rose',\n    'Rosella', 'Roselyn', 'Rosemarie', 'Rosemary', 'Rosendo', 'Rosetta',\n    'Rosie', 'Rosina', 'Roslyn', 'Ross', 'Rossie', 'Rowan', 'Rowena', 'Rowland',\n    'Roxane', 'Roxanne', 'Roy', 'Royal', 'Royce', 'Rozella', 'Ruben', 'Rubie',\n    'Ruby', 'Rubye', 'Rudolph', 'Rudy', 'Rupert', 'Russ', 'Russel', 'Russell',\n    'Rusty', 'Ruth', 'Ruthe', 'Ruthie', 'Ryan', 'Ryann', 'Ryder', 'Rylan',\n    'Rylee', 'Ryleigh', 'Ryley', 'Sabina', 'Sabrina', 'Sabryna', 'Sadie',\n    'Sadye', 'Sage', 'Saige', 'Sallie', 'Sally', 'Salma', 'Salvador',\n    'Salvatore', 'Sam', 'Samanta', 'Samantha', 'Samara', 'Samir', 'Sammie',\n    'Sammy', 'Samson', 'Sandra', 'Sandrine', 'Sandy', 'Sanford', 'Santa',\n    'Santiago', 'Santina', 'Santino', 'Santos', 'Sarah', 'Sarai', 'Sarina',\n    'Sasha', 'Saul', 'Savanah', 'Savanna', 'Savannah', 'Savion', 'Scarlett',\n    'Schuyler', 'Scot', 'Scottie', 'Scotty', 'Seamus', 'Sean', 'Sebastian',\n    'Sedrick', 'Selena', 'Selina', 'Selmer', 'Serena', 'Serenity', 'Seth',\n    'Shad', 'Shaina', 'Shakira', 'Shana', 'Shane', 'Shanel', 'Shanelle',\n    'Shania', 'Shanie', 'Shaniya', 'Shanna', 'Shannon', 'Shanny', 'Shanon',\n    'Shany', 'Sharon', 'Shaun', 'Shawn', 'Shawna', 'Shaylee', 'Shayna',\n    'Shayne', 'Shea', 'Sheila', 'Sheldon', 'Shemar', 'Sheridan', 'Sherman',\n    'Sherwood', 'Shirley', 'Shyann', 'Shyanne', 'Sibyl', 'Sid', 'Sidney',\n    'Sienna', 'Sierra', 'Sigmund', 'Sigrid', 'Sigurd', 'Silas', 'Sim', 'Simeon',\n    'Simone', 'Sincere', 'Sister', 'Skye', 'Skyla', 'Skylar', 'Sofia',\n    'Soledad', 'Solon', 'Sonia', 'Sonny', 'Sonya', 'Sophia', 'Sophie',\n    'Spencer', 'Stacey', 'Stacy', 'Stan', 'Stanford', 'Stanley', 'Stanton',\n    'Stefan', 'Stefanie', 'Stella', 'Stephan', 'Stephania', 'Stephanie',\n    'Stephany', 'Stephen', 'Stephon', 'Sterling', 'Steve', 'Stevie', 'Stewart',\n    'Stone', 'Stuart', 'Summer', 'Sunny', 'Susan', 'Susana', 'Susanna', 'Susie',\n    'Suzanne', 'Sven', 'Syble', 'Sydnee', 'Sydney', 'Sydni', 'Sydnie', 'Sylvan',\n    'Sylvester', 'Sylvia', 'Tabitha', 'Tad', 'Talia', 'Talon', 'Tamara',\n    'Tamia', 'Tania', 'Tanner', 'Tanya', 'Tara', 'Taryn', 'Tate', 'Tatum',\n    'Tatyana', 'Taurean', 'Tavares', 'Taya', 'Taylor', 'Teagan', 'Ted', 'Telly',\n    'Terence', 'Teresa', 'Terrance', 'Terrell', 'Terrence', 'Terrill', 'Terry',\n    'Tess', 'Tessie', 'Tevin', 'Thad', 'Thaddeus', 'Thalia', 'Thea', 'Thelma',\n    'Theo', 'Theodora', 'Theodore', 'Theresa', 'Therese', 'Theresia', 'Theron',\n    'Thomas', 'Thora', 'Thurman', 'Tia', 'Tiana', 'Tianna', 'Tiara', 'Tierra',\n    'Tiffany', 'Tillman', 'Timmothy', 'Timmy', 'Timothy', 'Tina', 'Tito',\n    'Titus', 'Tobin', 'Toby', 'Tod', 'Tom', 'Tomas', 'Tomasa', 'Tommie',\n    'Toney', 'Toni', 'Tony', 'Torey', 'Torrance', 'Torrey', 'Toy', 'Trace',\n    'Tracey', 'Tracy', 'Travis', 'Travon', 'Tre', 'Tremaine', 'Tremayne',\n    'Trent', 'Trenton', 'Tressa', 'Tressie', 'Treva', 'Trever', 'Trevion',\n    'Trevor', 'Trey', 'Trinity', 'Trisha', 'Tristian', 'Tristin', 'Triston',\n    'Troy', 'Trudie', 'Trycia', 'Trystan', 'Turner', 'Twila', 'Tyler', 'Tyra',\n    'Tyree', 'Tyreek', 'Tyrel', 'Tyrell', 'Tyrese', 'Tyrique', 'Tyshawn',\n    'Tyson', 'Ubaldo', 'Ulices', 'Ulises', 'Una', 'Unique', 'Urban', 'Uriah',\n    'Uriel', 'Ursula', 'Vada', 'Valentin', 'Valentina', 'Valentine', 'Valerie',\n    'Vallie', 'Van', 'Vance', 'Vanessa', 'Vaughn', 'Veda', 'Velda', 'Vella',\n    'Velma', 'Velva', 'Vena', 'Verda', 'Verdie', 'Vergie', 'Verla', 'Verlie',\n    'Vern', 'Verna', 'Verner', 'Vernice', 'Vernie', 'Vernon', 'Verona',\n    'Veronica', 'Vesta', 'Vicenta', 'Vicente', 'Vickie', 'Vicky', 'Victor',\n    'Victoria', 'Vida', 'Vidal', 'Vilma', 'Vince', 'Vincent', 'Vincenza',\n    'Vincenzo', 'Vinnie', 'Viola', 'Violet', 'Violette', 'Virgie', 'Virgil',\n    'Virginia', 'Virginie', 'Vita', 'Vito', 'Viva', 'Vivian', 'Viviane',\n    'Vivianne', 'Vivien', 'Vivienne', 'Vladimir', 'Wade', 'Waino', 'Waldo',\n    'Walker', 'Wallace', 'Walter', 'Walton', 'Wanda', 'Ward', 'Warren',\n    'Watson', 'Wava', 'Waylon', 'Wayne', 'Webster', 'Weldon', 'Wellington',\n    'Wendell', 'Wendy', 'Werner', 'Westley', 'Weston', 'Whitney', 'Wilber',\n    'Wilbert', 'Wilburn', 'Wiley', 'Wilford', 'Wilfred', 'Wilfredo', 'Wilfrid',\n    'Wilhelm', 'Wilhelmine', 'Will', 'Willa', 'Willard', 'William', 'Willie',\n    'Willis', 'Willow', 'Willy', 'Wilma', 'Wilmer', 'Wilson', 'Wilton',\n    'Winfield', 'Winifred', 'Winnifred', 'Winona', 'Winston', 'Woodrow',\n    'Wyatt', 'Wyman', 'Xander', 'Xavier', 'Xzavier', 'Yadira', 'Yasmeen',\n    'Yasmin', 'Yasmine', 'Yazmin', 'Yesenia', 'Yessenia', 'Yolanda', 'Yoshiko',\n    'Yvette', 'Yvonne', 'Zachariah', 'Zachary', 'Zachery', 'Zack', 'Zackary',\n    'Zackery', 'Zakary', 'Zander', 'Zane', 'Zaria', 'Zechariah', 'Zelda',\n    'Zella', 'Zelma', 'Zena', 'Zetta', 'Zion', 'Zita', 'Zoe', 'Zoey', 'Zoie',\n    'Zoila', 'Zola', 'Zora', 'Zula'\n];\n\n/**\n * Generate random username.\n * @returns {string} random username\n */\nfunction generateUsername(): string {\n    const name = randomElement(names);\n    const suffix = randomAlphanumStr(3);\n\n    return `${name}-${suffix}`;\n}\n\nexport { generateUsername };\n","import { jitsiLocalStorage } from '@jitsi/js-utils';\nimport { getLogger } from '@jitsi/logger';\nimport { v4 as uuidv4 } from 'uuid';\n\nimport { generateUsername } from '../util/UsernameGenerator';\n\nconst logger = getLogger('settings:Settings');\n\nlet _callStatsUserName: Nullable<string> = null;\n\nlet _machineId: Nullable<string> = null;\n\n/**\n *\n */\nexport interface ISettings {\n    _storage: Storage;\n    readonly callStatsUserName: string;\n    init: (externalStorage?: Storage) => void;\n    readonly machineId: string;\n    sessionId: string;\n}\n\nconst Settings: ISettings = {\n    /**\n     * The storage used to store the settings.\n     */\n    _storage: jitsiLocalStorage,\n\n    /**\n     * Returns the ID to use for the purposes of stats, saved in localstorage as \"callStatsUserName\".\n     * @returns {string} fake username for callstats\n     */\n    get callStatsUserName(): string {\n        if (!_callStatsUserName) {\n            _callStatsUserName = this._storage.getItem('callStatsUserName');\n            if (!_callStatsUserName) {\n                _callStatsUserName = _generateStatsId();\n                this._storage.setItem('callStatsUserName', _callStatsUserName);\n            }\n        }\n\n        return _callStatsUserName;\n    },\n\n    /**\n     * Initializes the Settings class.\n     *\n     * @param {Storage|undefined} externalStorage - Object that implements the Storage interface. This object will be\n     * used for storing data instead of jitsiLocalStorage if specified.\n     */\n    init(externalStorage?: Storage): void {\n        this._storage = externalStorage || jitsiLocalStorage;\n    },\n\n    /**\n     * Returns current machine id.\n     * @returns {string} machine id\n     */\n    get machineId(): string {\n        if (!_machineId) {\n            const amDid = this._storage.getItem('billingId');\n\n            _machineId = amDid || this._storage.getItem('jitsiMeetId');\n\n            if (amDid) {\n                this._storage.setItem('jitsiMeetId', amDid);\n            } else if (!_machineId) {\n                _machineId = generateJitsiMeetId();\n                this._storage.setItem('jitsiMeetId', _machineId);\n            }\n        }\n\n        return _machineId!;\n    },\n\n    /**\n     * Returns current session id.\n     * @returns {string} current session id\n     */\n    get sessionId(): string {\n        // We may update sessionId in localStorage from another JitsiConference\n        // instance and that's why we should always re-read it.\n        return this._storage.getItem('sessionId') || '';\n    },\n\n    /**\n     * Save current session id.\n     * @param {string} sessionId session id\n     */\n    set sessionId(sessionId: string) {\n        if (sessionId) {\n            this._storage.setItem('sessionId', sessionId);\n        } else {\n            this._storage.removeItem('sessionId');\n        }\n    }\n};\n\n/**\n * Generate a random ID to be used for statistics.\n * @returns {string} the random ID\n */\nfunction _generateStatsId() {\n    const username = generateUsername();\n\n    logger.info('generated stats id', username);\n\n    return username;\n}\n\n/**\n * Generate unique id.\n * @returns {string} random unique id\n */\nfunction generateJitsiMeetId(): string {\n    const jitsiMeetId = uuidv4().replaceAll('-', '');\n\n    logger.info('generated id', jitsiMeetId);\n\n    return jitsiMeetId;\n}\n\nexport default Settings;\n","import { EventEmitter as NodeEventEmitter } from 'events';\n\nexport type EventListener = (...args: any[]) => void;\n\n/**\n * The class creates our own EventEmitter instance\n */\nexport default class EventEmitter extends NodeEventEmitter {\n    public addEventListener: typeof NodeEventEmitter.prototype.addListener;\n    public removeEventListener: typeof NodeEventEmitter.prototype.removeListener;\n\n    /**\n     * Creates new instance.\n     * @constructor\n     */\n    constructor() {\n        super();\n\n        // aliases for addListener/removeListener\n        this.addEventListener = this.addListener;\n        this.removeEventListener = this.removeListener;\n    }\n}\n","/**\n * Events emitted by the RTCStats module.\n */\nexport enum RTCStatsEvents {\n    /**\n     * Event that indicates that the microphone has been muted or unmuted.\n     *\n     * @param {boolean} muted - Whether microphone was muted.\n     */\n    AUDIO_MUTE_CHANGED_EVENT = 'audioMutedChanged',\n\n    /**\n     * Event that indicates that the video codec on the sender has changed.\n     *\n     * @param {object} data - The data.\n     * @param {CodecMimeType} data.camera - The codec used for camera source.\n     * @param {CodecMimeType} data.screenshare - The codec used for screenshare.\n     */\n    CODEC_CHANGED_EVENT = 'codecChanged',\n\n    /**\n     * Event that indicates that the conference start timestamp has been received from MUC.\n     */\n    CONFERENCE_START_TIMESTAMP_EVENT = 'conferenceStartTimestamp',\n\n    /**\n     * Event that indicates that the current user has become the dominant speaker for the conference.\n     */\n    DOMINANT_SPEAKER_CHANGED_EVENT = 'dominantSpeakerChanged',\n\n    /**\n     * Event that indicates that the encode resolution is being restricted by CPU.\n     *\n     * @param {boolean} restricted - Whether CPU restriction was detected or removed.\n     */\n    ENCODER_CPU_RESTRICTED_EVENT = 'cpuRestricted',\n\n    /**\n     * Event that indicates that a getUserMedia call has failed.\n     *\n     * @param {object} data - The data.\n     * @param {string} data.name - The error name (e.g. 'NotAllowedError', 'NotFoundError', 'OverconstrainedError').\n     * @param {string} data.message - The error message.\n     * @param {string} [data.constraint] - The failed constraint name, when applicable (OverconstrainedError).\n     * @param {Array<string>} data.devices - The media types that were requested (e.g. ['audio', 'video', 'desktop']).\n     */\n    GET_USER_MEDIA_ERROR_EVENT = 'getUserMediaError',\n\n    /**\n     * Event that indicates that an in-place ICE restart completed successfully, i.e. the renegotiation completed\n     * and the new local transport was signalled.\n     */\n    ICE_RESTART_APPLIED_EVENT = 'iceRestartApplied',\n\n    /**\n     * Event that indicates that an in-place ICE restart was requested.\n     */\n    ICE_RESTART_REQUESTED_EVENT = 'iceRestartRequested',\n\n    /**\n     * Event that indicates that the JVB media session is restarted because of ICE failure.\n     */\n    JVB_ICE_RESTARTED_EVENT = 'jvbIceRestarted',\n\n    /**\n     * Event for logging.\n     */\n    LOG_EVENT = 'logs',\n\n    /**\n     * Event that indicates that a remote video source's media stream has been interrupted.\n     */\n    REMOTE_SOURCE_INTERRUPTED_EVENT = 'remoteSourceInterrupted',\n\n    /**\n     * Event that indicates that a remote video source is suspended by the JVB because of BWE issues.\n     */\n    REMOTE_SOURCE_SUSPENDED_EVENT = 'remoteSourceSuspended',\n\n    /**\n     * Event that indicates a change in the decoding state of a remote video stream that is receiving media bytes.\n     *\n     * @param {object} data - The event data.\n     * @param {boolean} data.stopped - True when frame decoding has stopped while bytes are still received,\n     * false when decoding resumes.\n     * @param {string} data.participantId - The participant whose video stream is affected.\n     * @param {number} data.ssrc - The SSRC of the affected stream.\n     */\n    REMOTE_VIDEO_DECODING_EVENT = 'remoteVideoDecoding',\n\n    /**\n     * Event emitted when any PeerConnection event is triggered.\n     *\n     * @param {object} event - The PeerConnection event.\n     * @param {string} event.type - The event type.\n     * @param {object} event.body - Event body.\n     * @param {string} event.body.isP2P - PeerConnection type.\n     * @param {string} event.body.state - PeerConnection state change which triggered the event.\n     */\n    RTC_STATS_PC_EVENT = 'rtstats_pc_event',\n\n    /**\n     * Event emitted when the websocket connection to the rtcstats server is disconnected.\n     */\n    RTC_STATS_WC_DISCONNECTED = 'rtcstats_ws_disconnected',\n\n    /**\n     * Event that indicates that the screenshare has started or stopped.\n     *\n     * @param {object} data - The data.\n     * @param {boolean} data.muted - Whether screenshare was toggled off or on.\n     */\n    SCREENSHARE_MUTE_CHANGED_EVENT = 'screenshareToggled',\n\n    /**\n     * Event that indicates that the strophe connection has disconnected.\n     */\n    STROPHE_DISCONNECTED_EVENT = 'stropheDisconnected',\n\n    /**\n     * Event that indicates that a strophe error has occurred.\n     *\n     * @param {object} data - The data.\n     */\n    STROPHE_ERROR_EVENT = 'strophe.error',\n\n    /**\n     * Event that indicates that the strophe connection has been re-established.\n     */\n    STROPHE_RECONNECTED_EVENT = 'stropheReconnected',\n\n    /**\n     * Event that indicates that the camera has been muted or unmuted.\n     *\n     * @param {boolean} muted - Whether camera was muted.\n     */\n    VIDEO_MUTE_CHANGED_EVENT = 'videoMutedChanged'\n}\n","import RTCStats from './RTCStats';\nimport { RTCStatsEvents } from './RTCStatsEvents';\n\n/**\n * The default log storage implementation.\n */\nexport default class DefaultLogStorage {\n    private rtcStats: any;\n\n    /**\n     * Creates new instance of <tt>DefaultLogStorage</tt>.\n     * @param rtcStats - The RTCStats instance.\n     */\n    constructor(rtcStats: any) {\n        this.rtcStats = rtcStats;\n    }\n\n\n    /**\n     * The DefaultLogStorage is ready when the RTCStats is ready.\n     *\n     * @returns {boolean} <tt>true</tt> when this storage is ready or\n     * <tt>false</tt> otherwise.\n     */\n    isReady() {\n        return this.rtcStats.isTraceAvailable();\n    }\n\n    /**\n     * Called by the <tt>LogCollector</tt> to store a series of log lines into\n     * batch.\n     *\n     * @param {Array<string|Object>} logEntries - An array containing strings\n     * representing log lines or aggregated lines objects.\n     * @returns {void}\n     */\n    storeLogs(logEntries: Array<string | any>) {\n        RTCStats.sendStatsEntry(RTCStatsEvents.LOG_EVENT, null, logEntries);\n    }\n}\n","import Logger, { getLogger } from '@jitsi/logger';\nimport rtcstatsInit from '@jitsi/rtcstats/rtcstats';\nimport traceInit from '@jitsi/rtcstats/trace-ws';\n\nimport JitsiConference from '../../JitsiConference';\nimport { JitsiConferenceEvents } from '../../JitsiConferenceEvents';\nimport JitsiConnection from '../../JitsiConnection';\nimport Settings from '../settings/Settings';\nimport EventEmitter from '../util/EventEmitter';\n\nimport DefaultLogStorage from './DefaulLogStorage';\nimport { RTCStatsEvents } from './RTCStatsEvents';\nimport { ITraceOptions } from './interfaces';\n\nconst logger = getLogger('analytics:RTCStats');\n\n/**\n * Cap on stats entries buffered while the trace module is not connected. Bounds memory when a client\n * never connects the trace (e.g. rtcstats disabled); pre-connect entries are rare so this is ample.\n */\nconst MAX_PENDING_STATS_ENTRIES = 100;\n\n/** A stats entry buffered while the trace was disconnected, replayed once it connects. */\ninterface IPendingStatsEntry {\n    data: Optional<any>;\n    pcId: Optional<string>;\n    statsType: RTCStatsEvents;\n}\n\n/**\n * RTCStats Singleton that is initialized only once for the lifetime of the app, subsequent calls to init will be\n * ignored. Config and conference changes are handled by the start method.\n * RTCStats \"proxies\" WebRTC functions such as GUM and RTCPeerConnection by rewriting the global objects.\n * The proxies will then send data to the rtcstats server via the trace object.\n * The initialization procedure must be called once after lib-jitsi-meet is loaded.\n */\nclass RTCStats {\n    private _defaultLogCollector: any = null;\n    private _initialized: boolean = false;\n    private _pendingStatsEntries: IPendingStatsEntry[] = [];\n    private _startedWithNewConnection: boolean = true;\n    private _trace: any = null;\n    public events: EventEmitter = new EventEmitter();\n\n    isTraceAvailable(): boolean {\n        return this._trace !== null;\n    }\n\n    /**\n     * A JitsiConnection instance is created before the conference is joined, so even though\n     * we don't have any conference specific data yet, we can initialize the trace module and\n     * send any logs that might of otherwise be missed in case an error occurs between the connection\n     * and conference initialization.\n     *\n     * @param connection - The JitsiConnection instance.\n     * @returns {void}\n     */\n    startWithConnection(connection: JitsiConnection): void {\n        const { options } = connection;\n        const name = options?.name ?? '';\n        const {\n            analytics: {\n                rtcstatsEndpoint: endpoint = '',\n                rtcstatsEnabled = false,\n                rtcstatsPollInterval: pollInterval = 10000,\n                rtcstatsSendSdp: sendSdp = false\n            } = {},\n        } = options;\n\n        // Even though we have options being passed to init we need to recheck it as some client (react-native)\n        // don't always re-initialize the module and could create multiple connections with different options.\n        if (!rtcstatsEnabled) return;\n\n        // If rtcstats already initialized, do nothing.\n        // Calling rtcsatsInit multiple times will cause the global objects to be rewritten multiple times,\n        // with unforeseen consequences.\n        if (!this._initialized) {\n            rtcstatsInit(\n                { statsEntry: this.sendStatsEntry.bind(this) },\n                { eventCallback: event => this.events.emit(RTCStatsEvents.RTC_STATS_PC_EVENT, event),\n                    pollInterval,\n                    sendSdp,\n                    useLegacy: false }\n            );\n            this._initialized = true;\n        }\n\n        const traceOptions: ITraceOptions = {\n            endpoint,\n            isBreakoutRoom: false,\n            meetingFqn: name\n        };\n\n        // Can't be a breakout room.\n        this._connectTrace(traceOptions);\n\n        this._defaultLogCollector?.flush();\n\n        this.sendIdentity({\n            confName: name,\n            ...options\n        });\n\n        // This module is tightly tied with the ljm JitsiConnection and JitsiConference flows, technically\n        // the connection isn't associated with a conference, but we still need to have some association for\n        // data that is logged before the conference is joined.\n        // In short the flow is as follows:\n        // 1. Connection is created.\n        // 2. The trace module is initialized and connected to the rtcstats server, so data starts being sent.\n        // 3. Conference is created.\n        // 4. If the trace wasn't already initialized from the connection creation, it will be initialized again.\n        // this will take care of the cases where the connection is created and then multiple conferences are\n        // sequentially joined and left, such as breakout rooms.\n        this._startedWithNewConnection = true;\n    }\n\n    /**\n     * When a conference is about to start, we need to reset the trace module, and initialize it with the\n     * new conference's config. On a normal conference flow this wouldn't be necessary, as the whole page is\n     * reloaded, but in the case of breakout rooms or react native the js context doesn't reload, hence the\n     * RTCStats singleton and its config persists between conferences.\n     *\n     * @param conference - JitsiConference instance that's about to start.\n     * @returns {void}\n     */\n    attachToConference(conference: JitsiConference): void {\n        const {\n            options: {\n                config: confConfig = {},\n                name: confName = ''\n            } = {},\n            _statsCurrentId: displayName = ''\n        } = conference;\n\n        const {\n            analytics: {\n                rtcstatsEnabled = false,\n                rtcstatsEndpoint: endpoint = ''\n            } = {}\n        } = confConfig;\n\n        // The statisticsId, statisticsDisplayName and _statsCurrentId (renamed to displayName) fields\n        // that are sent through options might be a bit confusing. Depending on the context, they could\n        // be intermixed inside ljm, for instance _statsCurrentId might refer to the email field which is stored\n        // in statisticsId or it could have the same value as callStatsUserName.\n        // The following is the mapping between the fields, and a short explanation of each:\n        // statisticsId -> email, this is only send by jitsi-meet if enableEmailInStats option is set.\n        // statisticsDisplayName -> nick, this is only send by jitsi-meet if enableDisplayNameInStats option is set.\n        // localId, this is the unique id that is used to track users throughout stats.\n        const localId = Settings?.callStatsUserName ?? '';\n\n        // The new conference config might have rtcstats disabled, so we need to check again.\n        if (!rtcstatsEnabled) {\n            return;\n        }\n\n        // If rtcstats proxy module is not initialized, do nothing.\n        if (!this._initialized) {\n            logger.error('Calling attachToConference before RTCStats proxy module is initialized.');\n\n            return;\n        }\n\n        // When the conference is joined, we need to initialize the trace module with the new conference's config.\n        // The trace module will then connect to the rtcstats server and send the identity data.\n        conference.once(JitsiConferenceEvents.CONFERENCE_JOINED, () => {\n            const isBreakoutRoom = Boolean(conference.getBreakoutRooms()?.isBreakoutRoom());\n            const endpointId = conference.myUserId();\n            const meetingUniqueId = conference.getMeetingUniqueId();\n\n            // Connect to the rtcstats server instance. Stats (data obtained from getstats) won't be send until the\n            // connect successfully initializes, however calls to GUM are recorded in an internal buffer even if not\n            // connected and sent once it is established.\n            if (!this._startedWithNewConnection) {\n                const traceOptions = {\n                    endpoint,\n                    isBreakoutRoom,\n                    meetingFqn: confName\n                };\n\n                this._connectTrace(traceOptions);\n\n                // In cases where the conference was left but the connection was not closed,\n                // logs could get cached, so we flush them as soon as we get a chance after the\n                // conference is joined.\n                this._defaultLogCollector?.flush();\n            }\n\n            const identityData = {\n                ...confConfig,\n                confName,\n                displayName,\n                endpointId,\n                isBreakoutRoom,\n                localId,\n                meetingUniqueId\n            };\n\n            this.sendIdentity(identityData);\n            // Reset the flag, so that the next conference that is joined will have the trace module initialized, such as a breakout room.\n            this._startedWithNewConnection = false;\n        });\n\n        // Note, this will only be called for normal rooms, not breakout rooms.\n        conference.once(JitsiConferenceEvents.CONFERENCE_UNIQUE_ID_SET, meetingUniqueId => {\n            this.sendIdentity({ meetingUniqueId });\n        });\n\n        conference.once(JitsiConferenceEvents.CONFERENCE_LEFT, () => {\n            this.reset();\n        });\n\n        conference.once(JitsiConferenceEvents.CONFERENCE_CREATED_TIMESTAMP, (timestamp: number) => {\n            this.sendStatsEntry(RTCStatsEvents.CONFERENCE_START_TIMESTAMP_EVENT, null, timestamp);\n        });\n\n        conference.once(\n            JitsiConferenceEvents.BEFORE_STATISTICS_DISPOSED,\n            () => this._defaultLogCollector?.flush()\n        );\n    }\n\n    /**\n     * Reset and connects the trace module to the s server.\n     *\n     * @param traceOptions - Options for the trace module.\n     * @returns {void}\n     */\n    _connectTrace(traceOptions: ITraceOptions): void {\n\n        const traceOptionsComplete = {\n            ...traceOptions,\n            onCloseCallback: event => this.events.emit(RTCStatsEvents.RTC_STATS_WC_DISCONNECTED, event),\n            useLegacy: false\n        };\n\n        const { isBreakoutRoom } = traceOptionsComplete;\n\n        this.reset();\n        this._trace = traceInit(traceOptionsComplete);\n        this._trace.connect(isBreakoutRoom);\n\n        // Replay entries buffered while the trace was down so pre-join events aren't dropped.\n        this._flushPendingStatsEntries();\n    }\n\n    /**\n     * Replays the stats entries that sendStatsEntry buffered while the trace was not connected, in the\n     * order they occurred. Called right after the trace connects.\n     *\n     * @returns {void}\n     */\n    _flushPendingStatsEntries(): void {\n        if (!this._trace || this._pendingStatsEntries.length === 0) {\n            return;\n        }\n\n        const pending = this._pendingStatsEntries;\n\n        this._pendingStatsEntries = [];\n        for (const entry of pending) {\n            this._trace.statsEntry(entry.statsType, entry.pcId, entry.data);\n        }\n    }\n\n    /**\n     * Sends the identity data to the rtcstats server.\n     *\n     * @param identityData - Identity data to send.\n     * @returns {void}\n     */\n    sendIdentity(identityData: any): void {\n        this._trace?.identity('identity', null, identityData);\n    }\n\n    /**\n     * Resets the trace module by closing the websocket and deleting the object.\n     * After reset, the rtcstats proxy module that tries to send data via `sendStatsEntry`, will no longer\n     * send any data, until the trace module is initialized again. This comes in handy on react-native\n     * where ljm doesn't get reloaded, so we need to switch the trace module between conferences.\n     *\n     * @returns {void}\n     */\n    reset(): void {\n        // If a trace is connected, flush the remaining logs before closing the connection,\n        // if the trace is not present and we flush the logs will be lost,\n        this._trace && this._defaultLogCollector?.flush();\n        this._trace?.close();\n        this._trace = null;\n    }\n\n    /**\n     * Sends a stats entry to the rtcstats server. This is called by the rtcstats proxy module,\n     * or any other app that wants to send custom stats.\n     *\n     * @param entry - Stats entry to send.\n     * @returns {void}\n     */\n    sendStatsEntry(statsType: RTCStatsEvents, pcId?: Optional<string>, data?: Optional<any>): void {\n        if (this._trace) {\n            this._trace.statsEntry(statsType, pcId, data);\n\n            return;\n        }\n\n        // Not connected yet (e.g. a pre-join getUserMedia failure): buffer and replay on connect rather\n        // than drop, mirroring how logs are retained via the log collector. Cap so a client that never\n        // connects can't grow this unbounded, keeping the earliest entries which carry the root cause.\n        if (this._pendingStatsEntries.length < MAX_PENDING_STATS_ENTRIES) {\n            this._pendingStatsEntries.push({ data, pcId, statsType });\n        }\n    }\n\n    /**\n     * Creates a new log collector with the default log storage.\n     */\n    getDefaultLogCollector(maxEntryLength: number = 10000): void {\n        if (!this._defaultLogCollector) {\n            // If undefined is passed  as maxEntryLength LogCollector will default to 10000 bytes\n            this._defaultLogCollector = new Logger.LogCollector(new DefaultLogStorage(this), { maxEntryLength });\n            this._defaultLogCollector.start();\n        }\n\n        return this._defaultLogCollector;\n    }\n}\n\nexport default new RTCStats();\n","/* eslint-disable prefer-rest-params */\nimport { v4 as uuidv4 } from 'uuid';\n\nimport {\n    PROTOCOL_ITERATION,\n    MAX_RECONNECT_TIME,\n    messageTypes,\n    CONFERENCE_LEAVE_CODE,\n    BUFFER_LIMIT,\n    CUSTOM_ERROR_CODES,\n    DUMP_ERROR_CODE\n} from './constants';\nimport obfuscator from './obfuscator';\n\n/**\n * Function that returns the timeout time for the reconnect based on number of attempts.\n *\n * @param {*} reconnectAttempts\n * @returns\n */\nfunction getTimeout(reconnectAttempts) {\n    return ((2 ** reconnectAttempts) * 1000) + Math.floor(Math.random() * 10000);\n}\n\n/**\n *\n * @param {*} endpoint\n * @param {*} onCloseCallback\n * @param {*} pingInterval\n */\nexport default function({ endpoint, meetingFqn, onCloseCallback, useLegacy, obfuscate = true, pingInterval = 30000 }) {\n    // Parent stats session id, used when breakout rooms occur to keep track of the initial stats session id.\n    let parentStatsSessionId;\n\n    // Buffer for storing stats if there is no connection to the server.\n    let buffer = [];\n    let statsSessionId = uuidv4();\n    let connection;\n    let keepAliveInterval;\n\n    // the number of ms spent trying to reconnect to the server.\n    let reconnectSpentTime = 0;\n\n    // the number of reconnect attempts made since the last successful connection.\n    let reconnectAttempts = 0;\n\n    // flag indicating if data can be sent to the server.\n    let canSendMessage = false;\n\n    // The sequence number of the last stat.\n    let sequenceNumber = 1;\n\n    // Timeout time for the reconnect protocol.\n    let reconnectTimeout;\n\n    // We maintain support for legacy chrome rtcstats just in case we need some critical statistic\n    // only obtainable from that format, ideally we'd remove this in the future.\n    const protocolVersion = useLegacy ? `${PROTOCOL_ITERATION}_LEGACY` : `${PROTOCOL_ITERATION}_STANDARD`;\n\n    // Function setting the timestamp and the sequence number of the entry.\n    const setTransportParams = data => {\n        data.push(new Date().getTime());\n        data.push(sequenceNumber++);\n    };\n\n    // Function sending the message to the server if there is a connection.\n    const sendMessage = msg => {\n        // It creates a copy of the message so that the message from the buffer have the data attribute unstringified\n        const copyMsg = Object.assign({}, msg);\n\n        if (copyMsg.type !== 'identity' && copyMsg.data) {\n            copyMsg.data = JSON.stringify(copyMsg.data);\n        }\n        if (connection && (connection.readyState === WebSocket.OPEN) && canSendMessage) {\n            connection.send(JSON.stringify(copyMsg));\n        }\n    };\n\n    const trace = function(msg) {\n        sendMessage(msg);\n        if (buffer.length < BUFFER_LIMIT && msg.data) {\n            buffer.push(msg);\n        }\n    };\n\n    trace.isConnected = function() {\n        if (!connection) {\n            return false;\n        }\n        const { readyState } = connection;\n\n        return readyState === WebSocket.OPEN;\n    };\n\n    trace.isClosed = function() {\n        if (!connection) {\n            return true;\n        }\n\n        const { readyState } = connection;\n\n        return readyState === WebSocket.CLOSED;\n    };\n\n    trace.identity = function(...data) {\n        setTransportParams(data);\n\n        if (parentStatsSessionId) {\n            data[2].parentStatsSessionId = parentStatsSessionId;\n        }\n\n        const identityMsg = {\n            statsSessionId,\n            type: 'identity',\n            data\n        };\n\n        trace(identityMsg);\n    };\n\n    trace.statsEntry = function(...data) {\n        let myData = data;\n\n        if (obfuscate) {\n            switch (data[0]) {\n            case 'addIceCandidate':\n            case 'onicecandidate':\n            case 'setLocalDescription':\n            case 'setRemoteDescription':\n                // These functions need to original values to work with\n                // so we need a deep copy to do the obfuscation on.\n                myData = JSON.parse(JSON.stringify(myData));\n                break;\n            default:\n                break;\n            }\n\n            // Obfuscate the ips is required.\n            obfuscator(myData);\n        }\n        setTransportParams(myData);\n\n        const statsEntryMsg = {\n            statsSessionId,\n            type: 'stats-entry',\n            data: myData\n        };\n\n        trace(statsEntryMsg);\n    };\n\n    trace.keepAlive = function() {\n\n        const keepaliveMsg = {\n            statsSessionId,\n            type: 'keepalive'\n        };\n\n        trace(keepaliveMsg);\n    };\n\n    trace.close = function() {\n        connection && connection.close(CONFERENCE_LEAVE_CODE);\n    };\n\n    trace.connect = function(isBreakoutRoom, isReconnect = false) {\n        if (isBreakoutRoom && !parentStatsSessionId) {\n            parentStatsSessionId = statsSessionId;\n        }\n        if (parentStatsSessionId) {\n            statsSessionId = uuidv4();\n            buffer.forEach(entry => {\n                entry.statsSessionId = statsSessionId;\n            });\n        }\n        if (connection) {\n            connection.close();\n        }\n\n        connection = new WebSocket(\n            `${endpoint}/${meetingFqn}?statsSessionId=${statsSessionId}&isReconnect=${isReconnect}`,\n            protocolVersion,\n            { headers: { 'User-Agent': navigator.userAgent } }\n        );\n\n        connection.onclose = function(closeEvent) {\n            keepAliveInterval && clearInterval(keepAliveInterval);\n            canSendMessage && (canSendMessage = false);\n\n            onCloseCallback({ code: closeEvent.code,\n                reason: closeEvent.reason });\n\n            // Do not try to reconnect if connection was closed intentionally.\n            if (CUSTOM_ERROR_CODES.includes(closeEvent.code)) {\n                return;\n            }\n\n            if (reconnectSpentTime < MAX_RECONNECT_TIME) {\n                const reconnectTimeoutTimeCandidate = getTimeout(reconnectAttempts);\n                const reconnectTimeoutTime = reconnectSpentTime + reconnectTimeoutTimeCandidate < MAX_RECONNECT_TIME\n                    ? reconnectTimeoutTimeCandidate\n                    : MAX_RECONNECT_TIME - reconnectSpentTime;\n\n                reconnectAttempts++;\n                reconnectSpentTime += reconnectTimeoutTime;\n                reconnectTimeout = setTimeout(() => trace.connect(isBreakoutRoom, true), reconnectTimeoutTime);\n            }\n        };\n\n        connection.onopen = function() {\n            keepAliveInterval = setInterval(trace.keepAlive, pingInterval);\n        };\n\n        connection.onmessage = async function(msg) {\n            const { type, body } = JSON.parse(msg.data);\n\n            // if the server sends back the last sequence number that it has been received.\n            if (type === messageTypes.SequenceNumber) {\n                const { value, state } = body;\n\n                // if there are entries in the buffer\n                if (buffer.length) {\n                    const firstSN = buffer[0].data[4];\n                    const lastSN = buffer[buffer.length - 1].data[4];\n\n                    // messages would not be in order, some messages might be missing\n                    if (value < firstSN - 1 && value > lastSN) {\n                        connection && connection.close(DUMP_ERROR_CODE);\n\n                        return;\n                    }\n\n                    const lastReceivedSNIndex = buffer.findIndex(statsEntry => statsEntry.data[4] === value);\n\n                    buffer = buffer.slice(lastReceivedSNIndex + 1);\n                }\n\n                // this happens when the connection is established\n                if (state === 'initial') {\n                    reconnectTimeout && clearTimeout(reconnectTimeout);\n                    reconnectSpentTime = 0;\n                    reconnectAttempts = 0;\n                    canSendMessage = true;\n                    for (let i = 0; i < buffer.length; i++) {\n                        sendMessage(buffer[i]);\n                    }\n                }\n            }\n        };\n    };\n\n    return trace;\n}\n","/**\n * This class exports constants and factory methods related to the analytics\n * API provided by AnalyticsAdapter. In order for entries in a database to be\n * somewhat easily traceable back to the code which produced them, events sent\n * through analytics should be defined here.\n *\n * Since the AnalyticsAdapter API can be used in different ways, for some events\n * it is more convenient to just define the event name as a constant. For other\n * events a factory function is easier.\n *\n * A general approach for adding a new event:\n * 1. Determine the event type: track, UI, page, or operational. If in doubt use\n * operational.\n * 2. Determine whether the event is related to other existing events, and\n * which fields are desired to be set: name, action, actionSubject, source.\n * 3. If the name is sufficient (the other fields are not important), use a\n * constant. Otherwise use a factory function.\n *\n * Note that the AnalyticsAdapter uses the events passed to its functions for\n * its own purposes, and might modify them. Because of this, factory functions\n * should create new objects.\n *\n */\n\nexport enum AnalyticsEvents {\n\n    /**\n     * The \"action\" value for Jingle events which indicates that an in-place ICE restart was requested.\n     */\n    ACTION_JINGLE_ICE_RESTART_REQUESTED = 'ice-restart.requested',\n\n    /**\n     * The \"action\" value for Jingle events which indicates that an in-place ICE restart completed successfully,\n     * i.e. the renegotiation completed and the new local transport was signalled.\n     */\n    ACTION_JINGLE_ICE_RESTART_SUCCESS = 'ice-restart.success',\n\n    /**\n     * The \"action\" value for Jingle events which indicates that the Jingle session\n     * was restarted (TODO: verify/fix the documentation)\n     */\n    ACTION_JINGLE_RESTART = 'restart',\n\n    /**\n     * The \"action\" value for Jingle events which indicates that a session-accept\n     * timed out (TODO: verify/fix the documentation)\n     */\n    ACTION_JINGLE_SA_TIMEOUT = 'session-accept.timeout',\n\n    /**\n     * The \"action\" value for Jingle events which indicates that a session-initiate\n     * was received.\n     */\n    ACTION_JINGLE_SI_RECEIVED = 'session-initiate.received',\n\n    /**\n     * The \"action\" value for Jingle events which indicates that a session-initiate\n     * not arrived within a timeout (the value is specified in\n     * the {@link JingleSessionPC}.\n     */\n    ACTION_JINGLE_SI_TIMEOUT = 'session-initiate.timeout',\n\n    /**\n     * A constant for the \"terminate\" action for Jingle events. TODO: verify/fix\n     * the documentation)\n     */\n    ACTION_JINGLE_TERMINATE = 'terminate',\n\n    /**\n     * The \"action\" value for JVB events which indicates that the ICE connection has failed after 3 restart attempts\n     */\n    ACTION_JVB_ICE_FAILED = 'jvb.ice.failed',\n\n    /**\n     * The \"action\" value for P2P events which indicates that P2P session initiate message has been rejected by the\n     * client because the mandatory requirements were not met.\n     */\n    ACTION_P2P_DECLINED = 'decline',\n\n    /**\n     * The \"action\" value for P2P events which indicates that a connection was\n     * established (TODO: verify/fix the documentation)\n     */\n    ACTION_P2P_ESTABLISHED = 'established',\n\n    /**\n     * The \"action\" value for P2P events which indicates that something failed.\n     */\n    ACTION_P2P_FAILED = 'failed',\n\n    /**\n     * The \"action\" value for P2P events which indicates that a switch to\n     * jitsi-videobridge happened.\n     */\n    ACTION_P2P_SWITCH_TO_JVB = 'switch.to.jvb',\n\n    /**\n     * The name of an event which indicates an available device. We send one such\n     * event per available device once when the available devices are first known,\n     * and every time that they change\n     *\n     * Properties:\n     *      audio_input_device_count: the number of audio input devices available at\n     *          the time the event was sent.\n     *      audio_output_device_count: the number of audio output devices available\n     *          at the time the event was sent.\n     *      video_input_device_count: the number of video input devices available at\n     *          the time the event was sent.\n     *      video_output_device_count: the number of video output devices available\n     *          at the time the event was sent.\n     *      device_id: an identifier of the device described in this event.\n     *      device_group_id:\n     *      device_kind: one of 'audioinput', 'audiooutput', 'videoinput' or\n     *          'videooutput'.\n     *      device_label: a string which describes the device.\n     */\n    AVAILABLE_DEVICE = 'available.device',\n\n    /**\n     * This appears to be fired only in certain cases when the XMPP connection\n     * disconnects (and it was intentional?). It is currently never observed to\n     * fire in production.\n     *\n     * TODO: document\n     *\n     * Properties:\n     *      message: an error message\n     */\n    CONNECTION_DISCONNECTED = 'connection.disconnected',\n\n    /**\n     * Indicates that the user of the application provided feedback in terms of a\n     * rating (an integer from 1 to 5) and an optional comment.\n     * Properties:\n     *      value: the user's rating (an integer from 1 to 5)\n     *      comment: the user's comment\n     */\n    FEEDBACK = 'feedback',\n\n    /**\n     * Indicates the duration of a particular phase of the ICE connectivity\n     * establishment.\n     *\n     * Properties:\n     *      phase: the ICE phase (e.g. 'gathering', 'checking', 'establishment')\n     *      value: the duration in milliseconds.\n     *      p2p: whether the associated ICE connection is p2p or towards a\n     *          jitsi-videobridge\n     *      initiator: whether the local Jingle peer is the initiator or responder\n     *          in the Jingle session. XXX we probably actually care about the ICE\n     *          role (controlling vs controlled), and we assume that this correlates\n     *          with the Jingle initiator.\n     */\n    ICE_DURATION = 'ice.duration',\n\n    /**\n     * Indicates the difference in milliseconds between the ICE establishment time\n     * for the P2P and JVB connections (e.g. a value of 10 would indicate that the\n     * P2P connection took 10ms more than JVB connection to establish).\n     *\n     * Properties:\n     *      value: the difference in establishment durations in milliseconds.\n     *\n     */\n    ICE_ESTABLISHMENT_DURATION_DIFF = 'ice.establishment.duration.diff',\n\n    /**\n     * Indicates that the ICE state has changed.\n     *\n     * Properties:\n     *      state: the ICE state which was entered (e.g. 'checking', 'connected',\n     *          'completed', etc).\n     *      value: the time in milliseconds (as reported by\n     *          window.performance.now()) that the state change occurred.\n     *      p2p: whether the associated ICE connection is p2p or towards a\n     *          jitsi-videobridge\n     *      signalingState: The signaling state of the associated PeerConnection\n     *      reconnect: whether the associated Jingle session is in the process of\n     *          reconnecting (or is it ICE? TODO: verify/fix the documentation)\n     */\n    ICE_STATE_CHANGED = 'ice.state.changed',\n\n    /**\n     * Indicates that no bytes have been sent for the track.\n     *\n     * Properties:\n     *      mediaType: the media type of the local track ('audio' or 'video').\n     */\n    NO_BYTES_SENT = 'track.no-bytes-sent',\n\n    /**\n     * Indicates a change in the decoding state of a remote video stream that is receiving media bytes.\n     * Fired after the condition persists for at least 3 consecutive stats polling cycles (~30 seconds),\n     * and again when the condition resolves.\n     *\n     * Properties:\n     *      stopped: true when frame decoding has stopped while bytes are still received,\n     *               false when decoding resumes.\n     *      participantId: the ID of the participant whose video stream is affected.\n     *      ssrc: the SSRC of the affected stream.\n     */\n    REMOTE_VIDEO_DECODING = 'remote.video.decoding',\n\n    /**\n     * Indicates that a track was unmuted (?).\n     *\n     * Properties:\n     *      mediaType: the media type of the local track ('audio' or 'video').\n     *      trackType: the type of the track ('local' or 'remote').\n     *      value: TODO: document\n     */\n    TRACK_UNMUTED = 'track.unmuted',\n\n    /**\n     * The constant which identifies an event of type \"operational\".\n     */\n    TYPE_OPERATIONAL = 'operational',\n\n    /**\n     * The constant which identifies an event of type \"page\".\n     */\n    TYPE_PAGE = 'page',\n\n    /**\n     * The constant which identifies an event of type \"track\".\n     */\n    TYPE_TRACK = 'track',\n\n    /**\n     * The constant which identifies an event of type \"ui\".\n     */\n    TYPE_UI = 'ui',\n\n    /**\n     * Indicates that the video codec changed for a local track.\n     *\n     * Properties:\n     *      value: the video codec mimeType.\n     *      videoType: the videoType of local track, whether its 'camera' or 'desktop'.\n     */\n    VIDEO_CODEC_CHANGED = 'quality.video-codec-changed',\n}\n\n/**\n * Creates an operational event which indicates that we have received a\n * \"bridge down\" event from jicofo.\n */\nexport const createBridgeDownEvent = () => {\n    return {\n        action: 'bridge.down',\n        actionSubject: 'bridge.down',\n        type: AnalyticsEvents.TYPE_OPERATIONAL\n    };\n};\n\n/**\n * Creates an event which indicates that the XMPP connection failed\n * @param errorType TODO\n * @param errorMessage TODO\n * @param detail connection failed details.\n */\nexport const createConnectionFailedEvent = (errorType: unknown, errorMessage: unknown, details: object) => {\n    return {\n        action: 'connection.failed',\n        attributes: {\n            'error_message': errorMessage,\n            'error_type': errorType,\n            ...details\n        },\n        type: AnalyticsEvents.TYPE_OPERATIONAL\n    };\n};\n\n/**\n * Creates a conference event.\n *\n * @param action - The action of the event.\n * @param attributes - The attributes to be added to the event.\n */\nexport const createConferenceEvent = (action: string, attributes: object) => {\n    return {\n        action,\n        attributes,\n        source: 'conference',\n        type: AnalyticsEvents.TYPE_OPERATIONAL\n    };\n};\n\n/**\n * Creates an operational event which indicates that a particular connection\n * stage was reached (i.e. the XMPP connection transitioned to the \"connected\"\n * state).\n *\n * @param stage the stage which was reached\n * @param attributes additional attributes for the event. This should be an\n * object with a \"value\" property indicating a timestamp in milliseconds\n * relative to the beginning of the document's lifetime.\n *\n */\nexport const createConnectionStageReachedEvent = (stage: unknown, attributes: object) => {\n    return {\n        action: 'connection.stage.reached',\n        actionSubject: stage,\n        attributes,\n        source: 'connection.stage.reached',\n        type: AnalyticsEvents.TYPE_OPERATIONAL\n    };\n};\n\n/**\n * Creates an operational event for the end-to-end round trip time to a\n * specific remote participant.\n * @param participantId the ID of the remote participant.\n * @param region the region of the remote participant\n * @param rtt the rtt\n */\nexport const createE2eRttEvent = (participantId: unknown, region: unknown, rtt: unknown) => {\n    return {\n        attributes: {\n            'participant_id': participantId,\n            region,\n            rtt\n        },\n        name: 'e2e_rtt',\n        type: AnalyticsEvents.TYPE_OPERATIONAL\n    };\n};\n\n/**\n * Creates an event which indicates that the focus has left the MUC.\n */\nexport const createFocusLeftEvent = () => {\n    return {\n        action: 'focus.left',\n        actionSubject: 'focus.left',\n        type: AnalyticsEvents.TYPE_OPERATIONAL\n    };\n};\n\n/**\n * Creates an event related to a getUserMedia call.\n *\n * @param action the type of the result that the event represents: 'error',\n * 'success', 'warning', etc.\n * @param attributes the attributes to attach to the event.\n */\nexport const createGetUserMediaEvent = (action: 'error' | 'success' | 'warning' | string, attributes: object = {}) => {\n    return {\n        action,\n        attributes,\n        source: 'get.user.media',\n        type: AnalyticsEvents.TYPE_OPERATIONAL\n    };\n};\n\n/**\n * Creates an event which indicates that the JVB ICE connection has failed event after 3 retries.\n *\n * @param action - The action type of the event.\n * @param attributes - The attributes to be added to the event.\n * @returns - The event object.\n */\nexport const createJvbIceFailedEvent = (action: unknown, attributes: object = {}) => {\n    return {\n        action,\n        attributes,\n        type: AnalyticsEvents.TYPE_OPERATIONAL\n    };\n};\n\n/**\n * Creates an event related to remote participant connection status changes.\n *\n * @param attributes the attributes to attach to the event.\n */\nexport const createParticipantConnectionStatusEvent = (attributes: object = {}) => {\n    return {\n        action: 'duration',\n        attributes,\n        source: 'peer.conn.status',\n        type: AnalyticsEvents.TYPE_OPERATIONAL\n    };\n};\n\n/**\n * Creates an event related to remote track streaming status changes.\n *\n * @param attributes the attributes to attach to the event.\n */\nexport const createTrackStreamingStatusEvent = (attributes: object = {}) => {\n    return {\n        action: 'duration',\n        attributes,\n        source: 'track.streaming.status',\n        type: AnalyticsEvents.TYPE_OPERATIONAL\n    };\n};\n\n/**\n * Creates an event for a Jingle-related event.\n * @param action the action of the event\n * @param attributes attributes to add to the event.\n */\nexport const createJingleEvent = (action: unknown, attributes: object = {}) => {\n    return {\n        action,\n        attributes,\n        source: 'jingle',\n        type: AnalyticsEvents.TYPE_OPERATIONAL\n    };\n};\n\n/**\n * Creates an event which indicates that a local track was not able to read\n * data from its source (a camera or a microphone).\n *\n * @param mediaType the media type of the local track ('audio' or\n * 'video').\n */\nexport const createNoDataFromSourceEvent = (mediaType: 'audio' | 'video' | string, value: unknown) => {\n    return {\n        action: 'track.no.data.from.source',\n        attributes: {\n            'media_type': mediaType,\n            value\n        },\n        type: AnalyticsEvents.TYPE_OPERATIONAL\n    };\n};\n\n/**\n * Creates an event for a p2p-related event.\n * @param action the action of the event\n * @param attributes attributes to add to the event.\n */\nexport const createP2PEvent = (action: unknown, attributes: object = {}) => {\n    return {\n        action,\n        attributes,\n        source: 'p2p',\n        type: AnalyticsEvents.TYPE_OPERATIONAL\n    };\n};\n\n/**\n * Indicates that we received a remote command to mute.\n */\nexport const createRemotelyMutedEvent = (mediaType: unknown) => {\n    return {\n        action: 'remotely.muted',\n        mediaType,\n        type: AnalyticsEvents.TYPE_OPERATIONAL\n    };\n};\n\n/**\n * Creates an event which contains RTP statistics such as RTT and packet loss.\n *\n * All average RTP stats are currently reported under 1 event name, but with\n * different properties that allows to distinguish between a P2P call, a\n * call relayed through TURN or the JVB, and multiparty vs 1:1.\n *\n * The structure of the event is:\n *\n * {\n *      p2p: true,\n *      conferenceSize: 2,\n *      localCandidateType: \"relay\",\n *      remoteCandidateType: \"relay\",\n *      transportType: \"udp\",\n *\n *      // Average RTT of 200ms\n *      \"rtt.avg\": 200,\n *      \"rtt.samples\": \"[100, 200, 300]\",\n *\n *      // Average packet loss of 10%\n *      \"packet.loss.avg\": 10,\n *      \"packet.loss.samples\": '[5, 10, 15]'\n *\n *      // Difference in milliseconds in the end-to-end RTT between p2p and jvb.\n *      // The e2e RTT through jvb is 15ms shorter:\n *      \"rtt.diff\": 15,\n *\n *      // End-to-end RTT through JVB is ms.\n *      \"end2end.rtt.avg\" = 100\n * }\n *\n * Note that the value of the \"samples\" properties are (JSON encoded) strings,\n * and not JSON arrays, as events' attributes can not be nested. The samples are\n * currently included for debug purposes only and can be removed anytime soon\n * from the structure.\n *\n * Also note that not all of values are present in each event, as values are\n * obtained and calculated as part of different process/event pipe. For example\n * {@link ConnectionAvgStats} instances are doing the reports for each\n * {@link TraceablePeerConnection} and work independently from the main stats\n * pipe.\n */\nexport const createRtpStatsEvent = (attributes: object) => {\n    return {\n        action: 'rtp.stats',\n        attributes,\n        type: AnalyticsEvents.TYPE_OPERATIONAL\n    };\n};\n\n/**\n * Creates an event which contains the round trip time (RTT) to a set of\n * regions.\n *\n * @param attributes\n */\nexport const createRttByRegionEvent = (attributes: object) => {\n    return {\n        action: 'rtt.by.region',\n        attributes,\n        type: AnalyticsEvents.TYPE_OPERATIONAL\n    };\n};\n\n/**\n * Creates an event which contains the local and remote ICE candidate types\n * for the transport that is currently selected.\n *\n * @param attributes\n */\nexport const createTransportStatsEvent = (attributes: object) => {\n    return {\n        action: 'transport.stats',\n        attributes,\n        type: AnalyticsEvents.TYPE_OPERATIONAL\n    };\n};\n\n/**\n * Creates an event which contains information about the audio output problem (the user id of the affected participant,\n * the local audio levels and the remote audio levels that triggered the event).\n *\n * @param userID - The user id of the affected participant.\n * @param localAudioLevels - The local audio levels.\n * @param remoteAudioLevels - The audio levels received from the participant.\n */\nexport const createAudioOutputProblemEvent\n    = (userID: string, localAudioLevels: unknown, remoteAudioLevels: unknown) => {\n        return {\n            action: 'audio.output.problem',\n            attributes: {\n                localAudioLevels,\n                remoteAudioLevels,\n                userID\n            },\n            type: AnalyticsEvents.TYPE_OPERATIONAL\n        };\n    };\n\n/**\n * Creates an event indicating that the remote audio wedge watchdog detected a mapped, unmuted remote audio source\n * that received no inbound RTP for the detection window and triggered a source recycle to recover it. Used to measure\n * the residual wedge rate in the field (see the Chrome/WebRTC audio-demux wedge).\n *\n * @param attributes - The attributes to add to the event. Currently used fields:\n *      sourceName: the source name of the wedged remote audio source.\n *      ssrc: the SSRC of the wedged remote audio source.\n */\nexport const createAudioWedgeRecoveryEvent = (attributes: object) => {\n    return {\n        action: 'audio.wedge.recovery',\n        attributes,\n        type: AnalyticsEvents.TYPE_OPERATIONAL\n    };\n};\n\n/**\n * Creates an event which contains an information related to the bridge channel close event.\n *\n * @param code - A code from {@link https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent}\n * @param reason - A string which describes the reason for closing the bridge channel.\n */\nexport const createBridgeChannelClosedEvent = (code: string, reason: string) => {\n    return {\n        action: 'bridge-channel.error',\n        attributes: {\n            code,\n            reason\n        },\n        type: AnalyticsEvents.TYPE_OPERATIONAL\n    };\n};\n\n/**\n * Creates an event which indicates the Time To First Media (TTFM).\n * It is measured in milliseconds relative to the beginning of the document's\n * lifetime (i.e. the origin used by window.performance.now()), and it excludes\n * the following:\n * 1. The delay due to getUserMedia()\n * 2. The period between the MUC being joined and the reception of the Jingle\n * session-initiate from jicofo. This is because jicofo will not start a Jingle\n * session until there are at least 2 participants in the room.\n *\n * @param attributes the attributes to add to the event. Currently used fields:\n *      mediaType: the media type of the local track ('audio' or 'video').\n *      muted: whether the track has ever been muted (?)\n *      value: the TTMF in milliseconds.\n */\nexport const createTtfmEvent = (attributes: object) => createConnectionStageReachedEvent('ttfm', attributes);\n","export enum StatisticsEvents {\n\n    /**\n     * Notifies about audio level in RTP statistics by SSRC.\n     *\n     * @param ssrc - The synchronization source identifier (SSRC) of the\n     * endpoint/participant whose audio level is being reported.\n     * @param {number} audioLevel - The audio level of <tt>ssrc</tt> according to\n     * RTP statistics.\n     * @param {boolean} isLocal - <tt>true</tt> if <tt>ssrc</tt> identifies the\n     * local endpoint/participant; otherwise, <tt>false</tt>.\n     */\n    AUDIO_LEVEL = 'statistics.audioLevel',\n\n    /**\n     * An event fired just before the statistics module gets disposes and it's\n     * the last chance to submit logs.\n     */\n    BEFORE_DISPOSED = 'statistics.before_disposed',\n\n    /**\n     * An event carrying all statistics by ssrc.\n     */\n    BYTE_SENT_STATS = 'statistics.byte_sent_stats',\n\n    /**\n     * An event carrying connection statistics.\n     *\n     * @param {object} connectionStats - The connection statistics carried by the\n     * event such as <tt>bandwidth</tt>, <tt>bitrate</tt>, <tt>packetLoss</tt>,\n     * <tt>resolution</tt>, and <tt>transport</tt>.\n     */\n    CONNECTION_STATS = 'statistics.connectionstats',\n\n    /**\n     * An event carrying the encode time stats for all the local video sources.\n     */\n    ENCODE_TIME_STATS = 'statistics.encode_time_stats',\n\n    /**\n     * An event carrying per-SSRC inbound video stats for remote video streams that are receiving bytes but\n     * decoding no frames. Fired in two situations:\n     *   1. When at least one such stream exists (stats map is non-empty).\n     *   2. Once more with an empty map when the set of failing streams transitions from non-empty to empty,\n     *      giving consumers the opportunity to fire resolution events and clean up state.\n     * No event is emitted while all remote streams are healthy.\n     *\n     * @param {TraceablePeerConnection} tpc - The peer connection.\n     * @param {Map<number, { bitrateDownload: number, fps: number, participantId: string }>} stats - Stats per SSRC.\n     */\n    INBOUND_VIDEO_STATS = 'statistics.inbound_video_stats',\n}\n","import BrowserCapabilities from './BrowserCapabilities';\n\nexport default new BrowserCapabilities();\n","import { BrowserDetection } from '@jitsi/js-utils/browser-detection';\n\n/* Minimum required Chrome / Chromium version. This applies also to derivatives. */\nconst MIN_REQUIRED_CHROME_VERSION = 72;\nconst MIN_REQUIRED_FIREFOX_VERSION = 91;\nconst MIN_REQUIRED_SAFARI_VERSION = 14;\nconst MIN_REQUIRED_IOS_VERSION = 14;\n\n// Starting with iPadOS 13 the actual Safari / iPadOS version is concealed from the UA string and\n// the system pretends to be macOS 10.15.7. Yeah, you read that right.\nconst FROZEN_MACOS_VERSION = '10.15.7';\n\n// TODO: Move this code to js-utils.\n\n// NOTE: Now we are extending BrowserDetection in order to preserve\n// RTCBrowserType interface but maybe it worth exporting BrowserCapabilities\n// and BrowserDetection as separate objects in future.\n\n/**\n * Implements browser capabilities for lib-jitsi-meet.\n */\nexport default class BrowserCapabilities extends BrowserDetection {\n    /**\n     * Returns the version of an ios browser.\n     *\n     * @returns {Number}\n     */\n    _getIOSVersion(): number {\n        if (this.isWebKitBased()) {\n            return Number.parseInt(this.getOSVersion(), 10);\n        }\n\n        return -1;\n    }\n\n    /**\n     * Returns the version of a Safari browser.\n     *\n     * @returns {Number}\n     */\n    _getSafariVersion(): number {\n        if (this.isSafari()) {\n            return Number.parseInt(this.getVersion(), 10);\n        }\n\n        return -1;\n    }\n\n    /**\n     * Checks whether the browser honors <tt>RTCRtpEncodingParameters.active = false</tt> for audio senders. Firefox\n     * versions <= 153 ignore this flag and keep transmitting audio even when the encoding is deactivated, which is\n     * why the transceiver-direction workaround exists in {@link TraceablePeerConnection.getTransceiverDirection} and\n     * {@link TraceablePeerConnection.getMediaTransferDirection}. The fix is tracked in\n     * https://bugzilla.mozilla.org/show_bug.cgi?id=1813848 and ships in Firefox 154.\n     *\n     * @returns {boolean} <tt>true</tt> when the browser honors the flag (all non-Firefox browsers, and Firefox\n     * 154+), <tt>false</tt> when the workaround is required.\n     */\n    supportsRTCRtpEncodingParametersActiveForAudio(): boolean {\n        return !(this.isFirefox() && this.isVersionLessThan(154));\n    }\n\n    /**\n     * Tells whether or not the <tt>MediaStream/tt> is removed from the <tt>PeerConnection</tt> and disposed on video\n     * mute (in order to turn off the camera device). This is needed on Firefox because of the following bug\n     * https://bugzilla.mozilla.org/show_bug.cgi?id=1735951\n     *\n     * @return {boolean} <tt>true</tt> if the current browser supports this strategy or <tt>false</tt> otherwise.\n     */\n    doesVideoMuteByStreamRemove(): boolean {\n        return this.isChromiumBased() || this.isWebKitBased() || this.isFirefox();\n    }\n\n    /**\n     * Checks if the client is running on an Android browser.\n     *\n     * @returns {boolean}\n     */\n    isAndroidBrowser(): boolean {\n        return !this.isReactNative() && this.getOS() === 'Android';\n    }\n\n    /**\n     * Checks if the current platform is iOS.\n     *\n     * @returns {boolean}\n     */\n    isIosBrowser(): boolean {\n        return !this.isReactNative() && this.getOS() === 'iOS';\n    }\n\n    /**\n     * Checks if the client is running on a mobile device.\n     *\n     * @returns {boolean}\n     */\n    isMobileDevice(): boolean {\n        return this.isAndroidBrowser() || this.isIosBrowser() || this.isReactNative();\n    }\n\n    /**\n     * Checks whether current running context is a Trusted Web Application.\n     *\n     * @returns {boolean} Whether the current context is a TWA.\n     */\n    isTwa(): boolean {\n        return 'matchMedia' in window && window.matchMedia('(display-mode:standalone)').matches;\n    }\n\n    /**\n     * Checks if the current browser is supported.\n     *\n     * @returns {boolean} true if the browser is supported, false otherwise.\n     */\n    isSupported(): boolean {\n        // First check for WebRTC APIs because some \"security\" extensions are dumb.\n        if (typeof RTCPeerConnection === 'undefined'\n                || !navigator?.mediaDevices?.enumerateDevices || !navigator?.mediaDevices?.getUserMedia) {\n            return false;\n        }\n\n        if (this.isSafari() && this._getSafariVersion() < MIN_REQUIRED_SAFARI_VERSION) {\n            return false;\n        }\n\n        return (this.isChromiumBased() && this.isEngineVersionGreaterThan(MIN_REQUIRED_CHROME_VERSION - 1))\n            || (this.isFirefox() && this.isVersionGreaterThan(MIN_REQUIRED_FIREFOX_VERSION - 1))\n            || this.isReactNative()\n            || this.isWebKitBased();\n    }\n\n    /**\n     * Returns whether the browser is supported for Android.\n     *\n     * @returns {boolean} true if the browser is supported for Android devices.\n     */\n    isSupportedAndroidBrowser(): boolean {\n        return this.isChromiumBased() || this.isFirefox();\n    }\n\n    /**\n     * Returns whether the browser is supported for iOS.\n     *\n     * @returns {boolean} true if the browser is supported for iOS devices.\n     */\n    isSupportedIOSBrowser(): boolean {\n        // After iPadOS 13 we have no way to know the Safari or iPadOS version, so YOLO.\n        if (!this.isSafari() && this.isWebKitBased() && this.getOSVersion() === FROZEN_MACOS_VERSION) {\n            return true;\n        }\n\n        return this._getSafariVersion() >= MIN_REQUIRED_IOS_VERSION\n                || this._getIOSVersion() >= MIN_REQUIRED_IOS_VERSION;\n    }\n\n    /**\n     * Returns whether or not the current environment needs a user interaction\n     * with the page before any unmute can occur.\n     *\n     * @returns {boolean}\n     */\n    isUserInteractionRequiredForUnmute(): boolean {\n        return this.isFirefox() && this.isVersionLessThan(68);\n    }\n\n    /**\n     * Checks if the current browser triggers 'onmute'/'onunmute' events when\n     * user's connection is interrupted and the video stops playback.\n     *\n     * Chrome M144+ regression: mute/unmute events no longer fire for video tracks\n     * when frames stop flowing. See: https://issues.chromium.org/issues/489023910\n     *\n     * @returns {boolean} 'true' if the event is supported or 'false' otherwise.\n     */\n    supportsVideoMuteOnConnInterrupted(): boolean {\n        return (this.isChromiumBased() && this.isVersionLessThan(144))\n            || this.isReactNative();\n    }\n\n    /**\n     * Checks if the current browser reports upload and download bandwidth statistics.\n     *\n     * @return {boolean}\n     */\n    supportsBandwidthStatistics(): boolean {\n        // FIXME bandwidth stats are currently not implemented for FF on our\n        // side, but not sure if not possible ?\n        return !this.isFirefox() && !this.isWebKitBased();\n    }\n\n    /**\n     * Checks if the current browser supports setting codec preferences on the transceiver.\n     *\n     * @returns {boolean}\n     */\n    supportsCodecPreferences(): boolean {\n        return Boolean('setCodecPreferences' in window.RTCRtpTransceiver?.prototype\n            && typeof window.RTCRtpReceiver?.getCapabilities !== 'undefined')\n\n            // this is not working on Safari because of the following bug\n            // https://bugs.webkit.org/show_bug.cgi?id=215567\n            && !this.isWebKitBased()\n\n            // Calling this API on Firefox is causing freezes when the local endpoint is the answerer.\n            // https://bugzilla.mozilla.org/show_bug.cgi?id=1917800\n            && !this.isFirefox();\n    }\n\n    /**\n     * Checks if the browser supports the new codec selection API, i.e., checks if dictionary member\n     * RTCRtpEncodingParameters.codec as defined in\n     * https://w3c.github.io/webrtc-extensions/#dom-rtcrtpencodingparameters-codec is supported by the browser. It\n     * allows the application to change the current codec used by each RTCRtpSender without a renegotiation.\n     *\n     * @returns {boolean}\n     */\n    supportsCodecSelectionAPI(): boolean {\n        return this.isChromiumBased() && this.isEngineVersionGreaterThan(125);\n    }\n\n    /**\n     * Returns true if the browser supports Dependency Descriptor header extension.\n     *\n     * @returns {boolean}\n     */\n    supportsDDExtHeaders(): boolean {\n        return !(this.isFirefox() && this.isVersionLessThan(136));\n    }\n\n    /**\n     * Checks if the current browser support the device change event.\n     * @return {boolean}\n     */\n    supportsDeviceChangeEvent(): boolean {\n        return typeof navigator.mediaDevices?.ondevicechange !== 'undefined'\n            && typeof navigator.mediaDevices?.addEventListener !== 'undefined';\n    }\n\n    /**\n     * Checks if the current browser supports audio level stats on the receivers.\n     *\n     * @return {boolean}\n     */\n    supportsReceiverStats(): boolean {\n        return typeof window.RTCRtpReceiver !== 'undefined'\n            && Object.keys(RTCRtpReceiver.prototype).indexOf('getSynchronizationSources') > -1;\n    }\n\n    /**\n     * Checks if the current browser reports round trip time statistics for the ICE candidate pair.\n     *\n     * @return {boolean}\n     */\n    supportsRTTStatistics(): boolean {\n        // Firefox does not seem to report RTT for ICE candidate pair:\n        // eslint-disable-next-line max-len\n        // https://www.w3.org/TR/webrtc-stats/#dom-rtcicecandidatepairstats-currentroundtriptime\n        // It does report mozRTT for RTP streams, but at the time of this\n        // writing it's value does not make sense most of the time\n        // (is reported as 1):\n        // https://bugzilla.mozilla.org/show_bug.cgi?id=1241066\n        // For Chrome and others we rely on 'googRtt'.\n        return !this.isFirefox();\n    }\n\n    /**\n     * Returns true on Firefox 110+, where RTCRtpTransceiverInit.sendEncodings is honored.\n     *\n     * @returns {boolean}\n     */\n    supportsEncodingsConfig(): boolean {\n        return this.isFirefox() && this.isVersionGreaterThan(109);\n    }\n\n    /**\n     * Returns true if the browser supports the new Scalability Mode API for VP9/AV1 simulcast and full SVC. H.264\n     * simulcast will also be supported by the jvb for this version because the bridge is able to read the Dependency\n     * Descriptor RTP header extension to extract layers information for H.264 as well.\n     *\n     * @returns {boolean}\n     */\n    supportsScalabilityModeAPI(): boolean {\n        return this.isChromiumBased() && this.isEngineVersionGreaterThan(112);\n    }\n\n    /**\n     * Returns true if the browser supports track based statistics for the local video track. Otherwise,\n     * track resolution and framerate will be calculated based on the 'outbound-rtp' statistics.\n     *\n     * @returns {boolean}\n     */\n    supportsTrackBasedStats(): boolean {\n        return this.isChromiumBased() && this.isEngineVersionLessThan(112);\n    }\n\n    /**\n     * Returns true if VP9 is supported by the client on the browser.\n     *\n     * Disabled on WebKit-based browsers (Safari/iOS). Firefox is supported on version 151+ (see:\n     * https://bugzilla.mozilla.org/show_bug.cgi?id=1633876).\n     * @returns {boolean}\n     */\n    supportsVP9(): boolean {\n        return !this.isWebKitBased() && !(this.isFirefox() && this.isVersionLessThan(151));\n    }\n\n    /**\n     * Returns true if SVC is supported.\n     *\n     * @returns {boolean}\n     */\n    supportsSVC(): boolean {\n        return !this.isFirefox();\n    }\n\n    /**\n     * Checks if the browser uses SDP munging for turning on simulcast.\n     *\n     * @returns {boolean}\n     */\n    usesSdpMungingForSimulcast(): boolean {\n        return this.isChromiumBased() || this.isReactNative() || this.isWebKitBased();\n    }\n\n    /**\n     * Checks if the browser uses RIDs/MIDs for siganling the simulcast streams\n     * to the bridge instead of the ssrcs.\n     *\n     * @returns {boolean}\n     */\n    usesRidsForSimulcast(): boolean {\n        return false;\n    }\n\n    /**\n     * Checks if the browser supports getDisplayMedia.\n     *\n     * @returns {boolean} {@code true} if the browser supports getDisplayMedia.\n     */\n    supportsGetDisplayMedia(): boolean {\n        // @ts-ignore\n        return typeof navigator.getDisplayMedia !== 'undefined'\n            || (typeof navigator.mediaDevices?.getDisplayMedia !== 'undefined');\n    }\n\n    /**\n     * Checks if the browser supports WebRTC Encoded Transform, an alternative\n     * to insertable streams.\n     *\n     * NOTE: At the time of this writing the only browser supporting this is\n     * Safari / WebKit, behind a flag.\n     *\n     * @returns {boolean} {@code true} if the browser supports it.\n     */\n    supportsEncodedTransform(): boolean {\n        return Boolean(window.RTCRtpScriptTransform);\n    }\n\n    /**\n     * Checks if the browser supports insertable streams, needed for E2EE.\n     *\n     * @returns {boolean} {@code true} if the browser supports insertable streams.\n     */\n    supportsInsertableStreams(): boolean {\n        // @ts-ignore\n        if (!window.RTCRtpSender?.prototype.createEncodedStreams) {\n            return false;\n        }\n\n        // Feature-detect transferable streams which we need to operate in a worker.\n        // See https://groups.google.com/a/chromium.org/g/blink-dev/c/1LStSgBt6AM/m/hj0odB8pCAAJ\n        const stream = new ReadableStream();\n\n        try {\n            window.postMessage(stream, '*', [ stream ]);\n\n            return true;\n        } catch {\n            return false;\n        }\n    }\n\n    /**\n     * Whether the browser supports the RED format for audio.\n     *\n     * @returns {boolean} {@code true} if the browser supports RED.\n     */\n    supportsAudioRed(): boolean {\n        return Boolean(window.RTCRtpSender?.getCapabilities('audio')?.codecs.some(codec => codec.mimeType === 'audio/red')\n            && window.RTCRtpReceiver?.getCapabilities('audio')?.codecs.some(codec => codec.mimeType === 'audio/red'));\n    }\n\n    /**\n     * Checks if the browser supports voice activity detection via the @type {VADAudioAnalyser} service.\n     *\n     * @returns {boolean}\n     */\n    supportsVADDetection(): boolean {\n        return this.isChromiumBased();\n    }\n\n    /**\n     * Check if the browser supports the RTP RTX feature (and it is usable).\n     *\n     * @returns {boolean}\n     */\n    supportsRTX(): boolean {\n        // Disable RTX on Firefox up to 96 because we prefer simulcast over RTX\n        // see https://bugzilla.mozilla.org/show_bug.cgi?id=1738504\n        return !(this.isFirefox() && this.isVersionLessThan(96));\n    }\n}\n","\nimport Logger from '@jitsi/logger';\nimport watchRTC from '@testrtc/watchrtc-sdk';\n\nimport browser from '../browser';\n\nimport { isAnalyticsEnabled, isWatchRTCEnabled } from './functions';\nimport { IWatchRTCConfiguration } from './interfaces';\n\nconst logger = Logger.getLogger('analytics:WatchRTC');\n\n/**\n * Class that controls the watchRTC flow, because it overwrites and proxies global function it should only be\n * initialized once.\n */\nclass WatchRTCHandler {\n    options?: IWatchRTCConfiguration;\n\n    /**\n     * Initialize watchRTC, it overwrites GUM and PeerConnection global functions and adds a proxy over them\n     * used to capture stats.\n     *\n     * @param {Object} options - Init options.\n     * @returns {void}\n     */\n    init(options: any): void {\n        if (isWatchRTCEnabled(options)) {\n\n            // @ts-ignore\n            if (browser.isReactNative()) {\n                logger.warn('Cannot initialize WatchRTC in a react native environment!');\n\n                return;\n            }\n\n            if (!isAnalyticsEnabled(options)) {\n                logger.error('Cannot initialize WatchRTC when analytics or third party requests are disabled.');\n\n                return;\n            }\n\n            try {\n                if (options?.watchRTCConfigParams?.rtcApiKey) {\n                    watchRTC.init({\n                        rtcApiKey: options.watchRTCConfigParams.rtcApiKey,\n                    });\n                    this.options = options.watchRTCConfigParams;\n                    logger.info('WatchRTC initialized.');\n                } else {\n                    logger.error('WatchRTC is enabled but missing API key.');\n                }\n            } catch (error) {\n                logger.error('Failed to initialize WatchRTC: ', error);\n            }\n        }\n    }\n\n    /**\n     * Begin watchRTC session considering roomName and userName if already not available\n     *\n     * @param {string} roomName - The room name we are currently in.\n     * @param {string} userName - The user name. This value is obtained from\n     * JitsiConference.prototype.myUserId\n     * @returns {void}\n     */\n    start(roomName: string, userName: string): void {\n        try {\n            if (this.options) {\n                this.options.rtcRoomId = this.options.rtcRoomId ? this.options.rtcRoomId : roomName;\n                this.options.rtcPeerId = this.options.rtcPeerId ? this.options.rtcPeerId : userName;\n                watchRTC.setConfig(this.options);\n                logger.info('WatchRTC setConfig.');\n            }\n        } catch (error) {\n            logger.error('Failed to start WatchRTC session: ', error);\n        }\n    }\n}\n\nexport default new WatchRTCHandler();\n","/**\n * Checks whether analytics is enabled or not.\n *\n * @param {Object} options - Init options.\n * @returns {boolean}\n */\nexport function isAnalyticsEnabled(options): boolean {\n    const { analytics, disableThirdPartyRequests } = options;\n\n    return !(analytics?.disabled || disableThirdPartyRequests);\n}\n\n/**\n * Checks whether rtcstats is enabled or not.\n *\n * @param {Object} options - Init options.\n * @returns {boolean}\n */\nexport function isRtcstatsEnabled(options): boolean {\n    const { analytics } = options;\n\n    return analytics?.rtcstatsEnabled ?? false;\n}\n\n/**\n * Checks whether watchrtc is enabled or not.\n *\n * @param {Object} options - Init options.\n * @returns {boolean}\n */\nexport function isWatchRTCEnabled(options): boolean {\n    const { analytics } = options;\n\n    return analytics?.watchRTCEnabled ?? false;\n}\n","import { getLogger } from '@jitsi/logger';\n\nimport { AnalyticsEvents } from '../../service/statistics/AnalyticsEvents';\nimport browser from '../browser';\n\nconst MAX_CACHE_SIZE = 100;\n\nconst logger = getLogger('stats:AnalyticsAdapter');\n\n/**\n * Type for analytics event objects.\n */\nexport interface IAnalyticsEvent {\n    action?: string;\n    actionSubject?: string;\n    actionSubjectId?: string;\n    attributes?: Record<string, unknown>;\n    categories?: string[];\n    containerId?: string;\n    containerType?: string;\n    name?: string;\n    objectId?: string;\n    objectType?: string;\n    source?: string;\n    tags?: string[];\n    type: string;\n}\n\n/**\n * Type for analytics handler objects.\n */\nexport interface IAnalyticsHandler {\n    dispose?: () => void;\n    sendEvent: (event: IAnalyticsEvent) => void;\n    setUserProperties: (properties: Record<string, unknown>) => void;\n}\n\n/**\n * This class provides an API to lib-jitsi-meet and its users for sending\n * analytics events. It serves as a bridge to different backend implementations\n * (\"analytics handlers\") and a cache for events attempted to be sent before\n * the analytics handlers were enabled.\n *\n * The API is designed to be an easy replacement for the previous version of\n * this adapter, and is meant to be extended with more convenience methods.\n *\n *\n * The API calls are translated to objects with the following structure, which\n * are then passed to the sendEvent(event) function of the underlying handlers:\n *\n * {\n *    type,\n *\n *    action,\n *    actionSubject,\n *    actionSubjectId,\n *    attributes,\n *    categories,\n *    containerId,\n *    containerType,\n *    name,\n *    objectId,\n *    objectType,\n *    source,\n *    tags\n * }\n *\n * The 'type' is one of 'operational', 'page', 'track' or 'ui', and some of the\n * other properties are considered required according to the type.\n *\n * For events with type 'page', the required properties are: name.\n *\n * For events with type 'operational' and 'ui', the required properties are:\n * action, actionSubject, source\n *\n * For events with type 'page', the required properties are:\n * action, actionSubject, source, containerType, containerId, objectType,\n * objectId\n */\nclass AnalyticsAdapter {\n    /**\n     * Whether this AnalyticsAdapter has been disposed of or not. Once this\n     * is set to true, the AnalyticsAdapter is disabled and does not accept\n     * any more events, and it can not be re-enabled.\n     * @type {boolean}\n     */\n    private disposed: boolean;\n\n    /**\n     * The set of handlers to which events will be sent.\n     * @type {Set<AnalyticsHandler>}\n     */\n    private analyticsHandlers: Set<IAnalyticsHandler>;\n\n    /**\n     * The cache of events which are not sent yet. The cache is enabled\n     * while this field is truthy, and disabled otherwise.\n     * @type {AnalyticsEvent[] | null}\n     */\n    private cache: IAnalyticsEvent[] | null;\n\n    /**\n     * Map of properties that will be added to every event. Note that the\n     * keys will be prefixed with \"permanent.\".\n     */\n    private permanentProperties: Record<string, unknown>;\n\n    /**\n     * The name of the conference that this AnalyticsAdapter is associated\n     * with.\n     * @type {string}\n     */\n    private conferenceName: string;\n\n    /**\n     * Creates new AnalyticsAdapter instance.\n     */\n    constructor() {\n        this.reset();\n    }\n\n    /**\n     * Saves an event to the cache, if the cache is enabled.\n     * @param event the event to save.\n     * @returns {boolean} true if the event was saved, and false otherwise (i.e.\n     * if the cache was disabled).\n     * @private\n     */\n    private _maybeCacheEvent(event: IAnalyticsEvent): boolean {\n        if (this.cache) {\n            this.cache.push(event);\n\n            // We limit the size of the cache, in case the user fails to ever\n            // set the analytics handlers.\n            if (this.cache.length > MAX_CACHE_SIZE) {\n                this.cache.splice(0, 1);\n            }\n\n            return true;\n        }\n\n        return false;\n\n    }\n\n    /**\n     *\n     * @param event\n     * @private\n     */\n    private _sendEvent(event: IAnalyticsEvent): void {\n        if (this._maybeCacheEvent(event)) {\n            // The event was consumed by the cache.\n        } else {\n            this.analyticsHandlers.forEach(handler => {\n                try {\n                    handler.sendEvent(event);\n                } catch (e) {\n                    logger.warn(`Error sending analytics event: ${e}`);\n                }\n            });\n        }\n    }\n\n\n    /**\n     * Set the user properties to the analytics handlers.\n     *\n     * @returns {void}\n     */\n    private _setUserProperties(): void {\n        this.analyticsHandlers.forEach(handler => {\n            try {\n                handler.setUserProperties(this.permanentProperties);\n            } catch (error) {\n                logger.warn('Error in setUserProperties method of one of the '\n                    + `analytics handlers: ${error}`);\n            }\n        });\n    }\n\n    /**\n     * Checks whether an event has all of the required fields set, and tries\n     * to fill in some of the missing fields with reasonable default values.\n     * Returns true if after this operation the event has all of the required\n     * fields set, and false otherwise (if some of the required fields were not\n     * set and the attempt to fill them in with a default failed).\n     *\n     * @param event the event object.\n     * @return {boolean} true if the event (after the call to this function)\n     * contains all of the required fields, and false otherwise.\n     * @private\n     */\n    private _verifyRequiredFields(event: IAnalyticsEvent | null): boolean {\n        if (!event) {\n            return false;\n        }\n\n        if (!event.type) {\n            event.type = AnalyticsEvents.TYPE_OPERATIONAL;\n        }\n\n        const type = event.type;\n\n        if (type !== AnalyticsEvents.TYPE_OPERATIONAL && type !== AnalyticsEvents.TYPE_PAGE\n                && type !== AnalyticsEvents.TYPE_UI && type !== AnalyticsEvents.TYPE_TRACK) {\n            logger.error(`Unknown event type: ${type}`);\n\n            return false;\n        }\n\n        if (type === AnalyticsEvents.TYPE_PAGE) {\n            return Boolean(event.name);\n        }\n\n        // Try to set some reasonable default values in case some of the\n        // parameters required by the handler API are missing.\n        event.action = event.action || event.name || event.actionSubject;\n        event.actionSubject = event.actionSubject || event.name || event.action;\n        event.source = event.source || event.name || event.action\n            || event.actionSubject;\n\n        if (!event.action || !event.actionSubject || !event.source) {\n            logger.error(\n                'Required field missing (action, actionSubject or source)');\n\n            return false;\n        }\n\n        // Track events have additional required fields.\n        if (type === AnalyticsEvents.TYPE_TRACK) {\n            event.objectType = event.objectType || 'generic-object-type';\n            event.containerType = event.containerType || 'conference';\n            if (event.containerType === 'conference' && !event.containerId) {\n                event.containerId = this.conferenceName;\n            }\n\n\n            if (!event.objectType || !event.objectId\n                || !event.containerType || !event.containerId) {\n                logger.error(\n                    'Required field missing (containerId, containerType, '\n                        + 'objectId or objectType)');\n\n                return false;\n            }\n        }\n\n        return true;\n    }\n\n\n    /**\n     * Adds a set of permanent properties to this this AnalyticsAdapter.\n     * Permanent properties will be added as \"attributes\" to events sent to\n     * the underlying \"analytics handlers\", and their keys will be prefixed\n     * by \"permanent_\", i.e. adding a permanent property {key: \"value\"} will\n     * result in {\"permanent_key\": \"value\"} object to be added to the\n     * \"attributes\" field of events.\n     *\n     * @param {Record<string, unknown>} properties the properties to add\n     */\n    public addPermanentProperties(properties: Record<string, unknown>): void {\n        this.permanentProperties = {\n            ...this.permanentProperties,\n            ...properties\n        };\n\n        this._setUserProperties();\n    }\n\n    /**\n         * Dispose analytics. Clears all handlers.\n         */\n    public dispose(): void {\n        logger.debug('Disposing of analytics adapter.');\n\n        if (this.analyticsHandlers && this.analyticsHandlers.size > 0) {\n            this.analyticsHandlers.forEach(handler => {\n                if (typeof handler.dispose === 'function') {\n                    handler.dispose();\n                }\n            });\n        }\n\n        this.setAnalyticsHandlers([]);\n        this.disposed = true;\n    }\n\n    /**\n     * Reset the state to the initial one.\n     *\n     * @returns {void}\n     */\n    public reset(): void {\n        this.disposed = false;\n        this.analyticsHandlers = new Set();\n        this.cache = [];\n        this.permanentProperties = {};\n        this.conferenceName = '';\n        this.addPermanentProperties({\n            'browser_name': browser.getName(),\n            'user_agent': navigator.userAgent\n        });\n    }\n\n    /**\n     * Sends an event with a given name and given properties. The first\n     * parameter is either a string or an object. If it is a string, it is used\n     * as the event name and the second parameter is used at the attributes to\n     * attach to the event. If it is an object, it represents the whole event,\n     * including any desired attributes, and the second parameter is ignored.\n     *\n     * @param {String|IAnalyticsEvent} eventName either a string to be used as the name\n     * of the event, or an event object. If an event object is passed, the\n     * properties parameters is ignored.\n     * @param {Record<string, unknown>} properties the properties/attributes to attach to the\n     * event, if eventName is a string.\n     */\n    public sendEvent(eventName: string | IAnalyticsEvent, properties: Record<string, unknown> = {}): void {\n        if (this.disposed) {\n            return;\n        }\n\n        let event: IAnalyticsEvent | null = null;\n\n        if (typeof eventName === 'string') {\n            event = {\n                action: eventName,\n                actionSubject: eventName,\n                attributes: properties,\n                source: eventName,\n                type: AnalyticsEvents.TYPE_OPERATIONAL\n            };\n        } else if (typeof eventName === 'object') {\n            event = eventName;\n        }\n\n        if (!this._verifyRequiredFields(event)) {\n            logger.error(\n                `Dropping a mis-formatted event: ${JSON.stringify(event)}`);\n\n            return;\n        }\n\n        this._sendEvent(event);\n    }\n\n    /**\n         * Sets the handlers that are going to be used to send analytics. Sends any\n         * cached events.\n         * @param {IAnalyticsHandler[]} handlers the handlers\n         */\n    public setAnalyticsHandlers(handlers: IAnalyticsHandler[]): void {\n        if (this.disposed) {\n            return;\n        }\n\n        this.analyticsHandlers = new Set(handlers);\n\n        this._setUserProperties();\n\n        // Note that we disable the cache even if the set of handlers is empty.\n        const cache = this.cache;\n\n        this.cache = null;\n        if (cache) {\n            cache.forEach(event => this._sendEvent(event));\n        }\n    }\n\n\n    /**\n     * Sets the name of the conference that this AnalyticsAdapter is associated\n     * with.\n     * @param name the name to set.\n     */\n    public setConferenceName(name: string): void {\n        this.conferenceName = name;\n        this.addPermanentProperties({ 'conference_name': name });\n    }\n\n}\n\nexport default new AnalyticsAdapter();\n","import { getLogger } from '@jitsi/logger';\n\nconst logger = getLogger('stats:LocalStatsCollector');\n/**\n * Size of the webaudio analyzer buffer.\n * @type {number}\n */\nconst WEBAUDIO_ANALYZER_FFT_SIZE: number = 2048;\n\n/**\n * Value of the webaudio analyzer smoothing time parameter.\n * @type {number}\n */\nconst WEBAUDIO_ANALYZER_SMOOTING_TIME: number = 0.8;\n\n/**\n * The audio context.\n * @type {AudioContext}\n */\nlet context: Nullable<AudioContext> = null;\n\n/**\n * Converts time domain data array to audio level.\n * @param samples the time domain data array.\n * @returns {number} the audio level\n */\nfunction timeDomainDataToAudioLevel(samples: Uint8Array): number {\n    let maxVolume = 0;\n    const length = samples.length;\n\n    for (let i = 0; i < length; i++) {\n        if (maxVolume < samples[i]) {\n            maxVolume = samples[i];\n        }\n    }\n\n    return Number.parseFloat(((maxVolume - 127) / 128).toFixed(3));\n}\n\n/**\n * Animates audio level change\n * @param newLevel the new audio level\n * @param lastLevel the last audio level\n * @returns {Number} the audio level to be set\n */\nfunction animateLevel(newLevel: number, lastLevel: number): number {\n    let value = 0;\n    const diff = lastLevel - newLevel;\n\n    if (diff > 0.2) {\n        value = lastLevel - 0.2;\n    } else if (diff < -0.4) {\n        value = lastLevel + 0.4;\n    } else {\n        value = newLevel;\n    }\n\n    return Number.parseFloat(value.toFixed(3));\n}\n\n/**\n * Provides statistics for the local stream.\n */\nexport default class LocalStatsCollector {\n    stream: MediaStream;\n    intervalId: Nullable<Timeout>;\n    intervalMilis: number;\n    audioLevel: number;\n    callback: (audioLevel: number) => void;\n    source: Nullable<MediaStreamAudioSourceNode>;\n    analyser: Nullable<AnalyserNode>;\n\n    /**\n     * Creates a new instance of LocalStatsCollector.\n     *\n     * @param {MediaStream} stream - the local stream\n     * @param {number} interval - stats refresh interval given in ms.\n     * @param {Function} callback - function that receives the audio levels.\n     * @constructor\n     */\n    constructor(\n            stream: MediaStream,\n            interval: number,\n            callback: (audioLevel: number) => void\n    ) {\n        this.stream = stream;\n        this.intervalId = null;\n        this.intervalMilis = interval;\n        this.audioLevel = 0;\n        this.callback = callback;\n        this.source = null;\n        this.analyser = null;\n    }\n\n    /**\n     * Starts the collecting the statistics.\n     */\n    start(): void {\n        if (!LocalStatsCollector.isLocalStatsSupported()) {\n            return;\n        }\n\n        context!.resume();\n        this.analyser = context!.createAnalyser();\n\n        this.analyser.smoothingTimeConstant = WEBAUDIO_ANALYZER_SMOOTING_TIME;\n        this.analyser.fftSize = WEBAUDIO_ANALYZER_FFT_SIZE;\n\n        this.source = context!.createMediaStreamSource(this.stream);\n\n        this.source.connect(this.analyser);\n\n        this.intervalId = setInterval(\n            () => {\n                const array = new Uint8Array(this.analyser!.frequencyBinCount);\n\n                this.analyser!.getByteTimeDomainData(array);\n                const audioLevel = timeDomainDataToAudioLevel(array);\n\n                // Set the audio levels always as NoAudioSignalDetection now\n                // uses audio levels from LocalStatsCollector and waits for\n                // atleast 4 secs for a no audio signal before displaying the\n                // notification on the UI.\n                this.audioLevel = animateLevel(audioLevel, this.audioLevel);\n                this.callback(this.audioLevel);\n            },\n            this.intervalMilis\n        );\n    }\n\n    /**\n     * Stops collecting the statistics.\n     */\n    stop(): void {\n        if (this.intervalId) {\n            clearInterval(this.intervalId);\n            this.intervalId = null;\n        }\n\n        this.analyser?.disconnect();\n        this.analyser = null;\n        this.source?.disconnect();\n        this.source = null;\n    }\n\n    /**\n     * Initialize collector.\n     */\n    static init(): void {\n        LocalStatsCollector.connectAudioContext();\n    }\n\n    /**\n     * Checks if the environment has the necessary conditions to support\n     * collecting stats from local streams.\n     *\n     * @returns {boolean}\n     */\n    static isLocalStatsSupported(): boolean {\n        return Boolean(window?.AudioContext);\n    }\n\n    /**\n     * Disconnects the audio context.\n     */\n    static async disconnectAudioContext(): Promise<void> {\n        if (context) {\n            logger.info('Disconnecting audio context');\n            await context.close();\n            context = null;\n        }\n    }\n\n    /**\n     * Connects the audio context.\n     */\n    static connectAudioContext(): void {\n        if (!LocalStatsCollector.isLocalStatsSupported()) {\n            return;\n        }\n\n        logger.info('Connecting audio context');\n        context = new AudioContext();\n\n        context.suspend();\n    }\n}\n","export enum MediaType {\n\n    /**\n     * The application type (data over bridge channel).\n     */\n    APPLICATION = 'application',\n\n    /**\n     * The audio type.\n     */\n    AUDIO = 'audio',\n\n    /**\n     * The desktop video type.\n     */\n    DESKTOP = 'desktop',\n\n    /**\n     * The video type.\n     */\n    VIDEO = 'video'\n}\n","export enum RTCEvents {\n    /**\n     * Designates an event indicating that the audio output device has changed.\n     */\n    AUDIO_OUTPUT_DEVICE_CHANGED = 'rtc.audio_output_device_changed',\n\n    /**\n     * Designates an event indicating that some audio SSRCs that have already been signaled will now map to new remote\n     * sources.\n     */\n    AUDIO_SSRCS_REMAPPED = 'rtc.audio_ssrcs_remapped',\n\n    /**\n     * Designates an event indicating that the bridge bandwidth estimation stats have been received.\n     */\n    BRIDGE_BWE_STATS_RECEIVED = 'rtc.bridge_bwe_stats_received',\n\n    /**\n     * Indicates that the data channel has been closed.\n     */\n    DATA_CHANNEL_CLOSED = 'rtc.data_channel_closed',\n\n    /**\n     * Indicates that the data channel has been opened.\n     */\n    DATA_CHANNEL_OPEN = 'rtc.data_channel_open',\n\n    /**\n     * Indicates that the list with available devices is now available.\n     */\n    DEVICE_LIST_AVAILABLE = 'rtc.device_list_available',\n\n    /**\n     * Indicates that the list with available devices has changed.\n     */\n    DEVICE_LIST_CHANGED = 'rtc.device_list_changed',\n\n    /**\n     * Indicates that the list with available devices will change.\n     */\n    DEVICE_LIST_WILL_CHANGE = 'rtc.device_list_will_change',\n\n    /**\n     * Indicates that the dominant speaker has changed.\n     */\n    DOMINANT_SPEAKER_CHANGED = 'rtc.dominant_speaker_changed',\n\n    /**\n     * Indicates that the connection status of the endpoint has changed.\n     */\n    ENDPOINT_CONN_STATUS_CHANGED = 'rtc.endpoint_conn_status_changed',\n\n    /**\n     * Indicates that a message from another participant is received on data channel.\n     */\n    ENDPOINT_MESSAGE_RECEIVED = 'rtc.endpoint_message_received',\n\n    /**\n     * Indicates that the remote endpoint stats have been received on data channel.\n     */\n    ENDPOINT_STATS_RECEIVED = 'rtc.endpoint_stats_received',\n\n    /**\n     * Indicates that the list of sources currently being forwarded by the bridge has changed.\n     */\n    FORWARDED_SOURCES_CHANGED = 'rtc.forwarded_sources_changed',\n\n    /**\n     * Per-poll inbound audio stats emitted by the {@code StatsCollector} on each stats cycle. The payload is the\n     * source {@code TraceablePeerConnection} and a {@code Map<ssrc, packetsReceived>} of the cumulative received\n     * packet count for every inbound audio SSRC. Consumed by {@link RemoteAudioWedgeDetector} so it can piggyback on\n     * the existing stats poll instead of running its own {@code getStats()} loop.\n     */\n    INBOUND_AUDIO_STATS = 'rtc.inbound_audio_stats',\n\n    /**\n     * Event emitted when {@link RTC.setLastN} method is called to update with the new value set.\n     * The first argument is the value passed to {@link RTC.setLastN}.\n     */\n    LASTN_VALUE_CHANGED = 'rtc.lastn_value_changed',\n\n    /**\n     * The max enabled resolution of a local video track was changed.\n     */\n    LOCAL_TRACK_MAX_ENABLED_RESOLUTION_CHANGED = 'rtc.local_track_max_enabled_resolution_changed',\n\n    /**\n     * Designates an event indicating that the local ICE username fragment of\n     * the jingle session has changed.\n     * The first argument of the vent is <tt>TraceablePeerConnection</tt> which\n     * is the source of the event.\n     * The second argument is the actual \"ufrag\" string.\n     */\n    LOCAL_UFRAG_CHANGED = 'rtc.local_ufrag_changed',\n\n    /**\n     * Event emitted when the user granted/blocked a permission for the camera / mic.\n     * Used to keep track of the granted permissions on browsers which don't\n     * support the Permissions API.\n     */\n    PERMISSIONS_CHANGED = 'rtc.permissions_changed',\n\n    /**\n     * Event fired when we remote track is added to the conference.\n     * 1st event argument is the added <tt>JitsiRemoteTrack</tt> instance.\n     **/\n    REMOTE_TRACK_ADDED = 'rtc.remote_track_added',\n\n    // FIXME get rid of this event in favour of NO_DATA_FROM_SOURCE event\n    // (currently implemented for local tracks only)\n    REMOTE_TRACK_MUTE = 'rtc.remote_track_mute',\n\n    /**\n     * Indicates that the remote track has been removed from the conference.\n     * 1st event argument is the removed {@link JitsiRemoteTrack} instance.\n     */\n    REMOTE_TRACK_REMOVED = 'rtc.remote_track_removed',\n\n    // FIXME get rid of this event in favour of NO_DATA_FROM_SOURCE event\n    // (currently implemented for local tracks only)\n    REMOTE_TRACK_UNMUTE = 'rtc.remote_track_unmute',\n\n    /**\n     * Designates an event indicating that the local ICE username fragment of the jingle session has changed.\n     * The first argument of the vent is <tt>TraceablePeerConnection</tt> which is the source of the event.\n     * The second argument is the actual \"ufrag\" string.\n     */\n    REMOTE_UFRAG_CHANGED = 'rtc.remote_ufrag_changed',\n\n    /**\n     * Indicates that sender constraints requested by the bridge for this endpoint have changed.\n     */\n    SENDER_VIDEO_CONSTRAINTS_CHANGED = 'rtc.sender_video_constraints_changed',\n\n    /**\n     * Indicates that a translated audio source started or stopped being sent (forwarded) to this endpoint by\n     * the bridge. The payload is { sourceName, sending, timestamp }; timestamp is an RTP timestamp (48 kHz,\n     * arbitrary origin, wraps at 2^32) — not epoch milliseconds.\n     */\n    TRANSLATED_SOURCE_SENDING_CHANGED = 'rtc.translated_source_sending_changed',\n\n    /**\n     * Designates an event indicating that some video SSRCs that have already been signaled will now map to new remote\n     * sources.\n     */\n    VIDEO_SSRCS_REMAPPED = 'rtc.video_ssrcs_remapped'\n}\n","import browser from '../browser';\n\n/**\n * A global module for accessing information about different feature flags state.\n */\nclass FeatureFlags {\n    private _runInLiteMode: boolean;\n    private _ssrcRewriting: boolean;\n    private _rtpMidDemux: boolean;\n\n    /**\n     * Configures the module.\n     *\n     * @param {object} flags - The feature flags.\n     * @param {Optional<boolean>} flags.runInLiteMode - Enables lite mode for testing to disable media decoding.\n     * @param {Optional<boolean>} flags.ssrcRewritingEnabled - Use SSRC rewriting.\n     * @param {Optional<boolean>} flags.rtpMidDemuxEnabled - Allow the bridge to demux forwarded media by the RTP\n     * sdes:mid header extension (requires SSRC rewriting).\n     */\n    init(flags: {\n        rtpMidDemuxEnabled?: Optional<boolean>;\n        runInLiteMode?: Optional<boolean>;\n        ssrcRewritingEnabled?: Optional<boolean>;\n    }) {\n        this._runInLiteMode = Boolean(flags.runInLiteMode);\n        this._ssrcRewriting = Boolean(flags.ssrcRewritingEnabled);\n        this._rtpMidDemux = Boolean(flags.rtpMidDemuxEnabled);\n    }\n\n    /**\n     * Checks if the client supports demuxing media forwarded by the bridge using the RTP sdes:mid header extension.\n     * Requires SSRC rewriting, since the per-slot mids are signaled in the bridge's source-map messages. Limited to\n     * Chromium-based browsers: Chrome routes each forwarded source to its own m-line by mid -- remote audio to the\n     * bridge's \"a0\" m-line and remote video to \"v0\" (verified via inbound-rtp). Firefox mid-demuxes video correctly but\n     * does NOT for audio: it folds the remote audio onto its own sendrecv audio m-line (mid 0) instead of the bridge's\n     * recvonly \"a0\" m-line, leaving \"a0\" orphaned. That orphan m-line's join-time SSRC reconciliation intermittently\n     * stalls audio reception past acceptable limits (manifests as the torture suite's \"no media in 15s\", audio-only,\n     * Firefox-only, under mid demux; absent when mid demux is off and there is no \"a0\" m-line). So Firefox keeps\n     * SSRC-only demuxing and the {@code TPCUtils._stripSdesMid} workaround.\n     *\n     * Further limited to Chromium 148 and later: mid demux is a workaround for the audio-demux wedge, and that\n     * regression was introduced in Chromium 148. Earlier Chromium versions do not have the bug, so there is nothing to\n     * work around there.\n     *\n     * @returns {boolean}\n     */\n    isRtpMidDemuxSupported(): boolean {\n        return this._rtpMidDemux\n            && this._ssrcRewriting\n            && browser.isChromiumBased()\n            && browser.isEngineVersionGreaterThan(147);\n    }\n\n    /**\n     * Checks if the run in lite mode is enabled.\n     * This will cause any media to be received and not decoded. (Insertable streams are used to discard\n     * all media before it is decoded). This can be used for various test scenarios.\n     *\n     * @returns {boolean}\n     */\n    isRunInLiteModeEnabled(): boolean {\n        return this._runInLiteMode && browser.supportsInsertableStreams();\n    }\n\n    /**\n     * Checks if the clients supports re-writing of the SSRCs on the media streams by the bridge.\n     * @returns {boolean}\n     */\n    isSsrcRewritingSupported(): boolean {\n        return this._ssrcRewriting;\n    }\n}\n\nexport default new FeatureFlags();\n","/**\n * The method will increase the given number by 1. If the given counter is equal\n * or greater to {@link Number.MAX_SAFE_INTEGER} then it will be rolled back to\n * 1.\n * @param {number} number - An integer counter value to be incremented.\n * @return {number} the next counter value increased by 1 (see the description\n * above for exception).\n */\nexport function safeCounterIncrement(number: number): number {\n    let nextValue = number;\n\n    if (number >= Number.MAX_SAFE_INTEGER) {\n        nextValue = 0;\n    }\n\n    return nextValue + 1;\n}\n\n/**\n * Calculates the average value of an Array of numbers.\n *\n * @param {Float32Array} valueArray - Array of numbers.\n * @returns {number} - Number array average.\n */\nexport function calculateAverage(valueArray: Float32Array): number {\n    return valueArray.length > 0 ? valueArray.reduce((a, b) => a + b) / valueArray.length : 0;\n}\n\n/**\n * Calculates a unique hash for a given string similar to Java's\n * implementation of String.hashCode()\n *\n * @param {string} string - String whose hash has to be calculated.\n * @returns {number} - Unique hash code calculated.\n */\nexport function hashString(string: string): number {\n    let hash = 0;\n\n    for (let i = 0; i < string.length; i++) {\n        hash += Math.pow(string.charCodeAt(i) * 31, string.length - i);\n\n        /* eslint-disable no-bitwise */\n        hash = hash & hash; // Convert to 32bit integer\n    }\n\n    return Math.abs(hash);\n}\n\n/**\n * Returns only the positive values from an array of numbers.\n *\n * @param {Float32Array} valueArray - Array of vad scores.\n * @returns {number[]} - Array of positive numbers.\n */\nexport function filterPositiveValues(valueArray: Float32Array): number[] {\n    return Array.from(valueArray).filter(value => value >= 0);\n}\n\n/**\n * This class calculates a simple running average that continually changes\n * as more data points are collected and added.\n */\nexport class RunningAverage {\n    private average: number;\n    private n: number;\n\n    /**\n     * Creates an instance of the running average calculator.\n     */\n    constructor() {\n        this.average = 0;\n        this.n = 0;\n    }\n\n    /**\n     * Adds a new data point to the existing set of values and recomputes\n     * the running average.\n     * @param {number} value\n     * @returns {void}\n     */\n    addNext(value: number): void {\n        if (typeof value !== 'number') {\n            return;\n        }\n        this.n += 1;\n        this.average = this.average + ((value - this.average) / this.n);\n    }\n\n    /**\n     * Obtains the average value for the current subset of values.\n     * @returns {number} - computed average.\n     */\n    getAverage(): number {\n        return this.average;\n    }\n}\n\n/**\n * Subtracts the two numbers passed or returns 0 if any of the arguments are not a number.\n *\n * @param {*} x - The number we subtract from.\n * @param {*} y - The number we subtract.\n * @returns {number} - x - y or 0 if x or y is not a number.\n */\nexport function safeSubtract(x: any, y: any): number {\n    return isValidNumber(x) && isValidNumber(y) ? x - y : 0;\n}\n\n/**\n * Checks if the given value is a valid number.\n *\n * @param n - The value to check.\n * @returns - `true` if the value is a valid number, `false` otherwise.\n */\nexport function isValidNumber(n: any): boolean {\n    const v = Number.parseInt(n, 10);\n\n    return Number.isFinite(v); // Filter out NaN and Infinity.\n}\n","import { getLogger } from '@jitsi/logger';\n\nimport { MediaType } from '../../service/RTC/MediaType';\nimport { RTCEvents } from '../../service/RTC/RTCEvents';\nimport { StatisticsEvents } from '../../service/statistics/Events';\nimport browser from '../browser';\nimport FeatureFlags from '../flags/FeatureFlags';\nimport { isValidNumber } from '../util/MathUtil';\n\nconst logger = getLogger('stats:RTPStatsCollector');\n\n/**\n * Calculates packet lost percent using the number of lost packets and the\n * number of all packet.\n * @param lostPackets the number of lost packets\n * @param totalPackets the number of all packets.\n * @returns {number} packet loss percent\n */\nfunction calculatePacketLoss(lostPackets, totalPackets) {\n    if (lostPackets > 0 && totalPackets > 0) {\n        return Math.round(lostPackets / totalPackets * 100);\n    }\n\n    return 0;\n}\n\n/**\n * Holds \"statistics\" for a single SSRC.\n */\nclass SsrcStats {\n    /**\n     * Constructor.\n     */\n    constructor() {\n        this.loss = {};\n        this.bitrate = {\n            download: 0,\n            upload: 0\n        };\n        this.resolution = {};\n        this.framerate = 0;\n        this.codec = '';\n    }\n\n    /**\n     * Sets the \"loss\" object.\n     * @param loss the value to set.\n     */\n    setLoss(loss) {\n        this.loss = loss || {};\n    }\n\n    /**\n     * Sets resolution that belong to the ssrc represented by this instance.\n     * @param resolution new resolution value to be set.\n     */\n    setResolution(resolution) {\n        this.resolution = resolution || {};\n    }\n\n    /**\n     * Adds the \"download\" and \"upload\" fields from the \"bitrate\" parameter to\n     * the respective fields of the \"bitrate\" field of this object.\n     * @param bitrate an object holding the values to add.\n     */\n    addBitrate(bitrate) {\n        this.bitrate.download += bitrate.download;\n        this.bitrate.upload += bitrate.upload;\n    }\n\n    /**\n     * Resets the bit rate for given <tt>ssrc</tt> that belong to the peer\n     * represented by this instance.\n     */\n    resetBitrate() {\n        this.bitrate.download = 0;\n        this.bitrate.upload = 0;\n    }\n\n    /**\n     * Sets the \"framerate\".\n     * @param framerate the value to set.\n     */\n    setFramerate(framerate) {\n        this.framerate = framerate || 0;\n    }\n\n    /**\n     * Sets the codec.\n     * @param codec the value to set.\n     */\n    setCodec(codec) {\n        this.codec = codec || '';\n    }\n\n    /**\n     * Sets the encode stats.\n     * @param encodeStats the value to set.\n     */\n    setEncodeStats(encodeStats) {\n        this.encodeStats = encodeStats || {};\n    }\n\n    /**\n     * Sets the framesDecoded counter for inbound video streams.\n     * @param {number} framesDecoded the value to set.\n     */\n    setFramesDecoded(framesDecoded) {\n        this.framesDecoded = typeof framesDecoded === 'number' ? framesDecoded : undefined;\n    }\n}\n\n/**\n * Conference statistics.\n */\nclass ConferenceStats {\n    /**\n     * Constructor.\n     */\n    constructor() {\n        /**\n         * The bandwidth\n         * @type {{}}\n         */\n        this.bandwidth = {};\n\n        /**\n         * The bit rate\n         * @type {{}}\n         */\n        this.bitrate = {};\n\n        /**\n         * The packet loss rate\n         * @type {{}}\n         */\n        this.packetLoss = null;\n\n        /**\n         * Array with the transport information.\n         * @type {Array}\n         */\n        this.transport = [];\n    }\n}\n\n/* eslint-disable max-params */\n\n/**\n * <tt>StatsCollector</tt> registers for stats updates of given\n * <tt>peerconnection</tt> in given <tt>interval</tt>. On each update particular\n * stats are extracted and put in {@link SsrcStats} objects. Once the processing\n * is done <tt>audioLevelsUpdateCallback</tt> is called with <tt>this</tt>\n * instance as an event source.\n */\nexport default class StatsCollector {\n    /**\n     * Creates new <tt>StatsCollector</tt> instance.\n     * @param peerconnection WebRTC PeerConnection object.\n     * @param audioLevelsInterval\n     * @param statsInterval stats refresh interval given in ms.\n     * @param eventEmitter\n     * @constructor\n     */\n    constructor(peerconnection, audioLevelsInterval, statsInterval, eventEmitter) {\n        this.peerconnection = peerconnection;\n        this.currentStatsReport = null;\n        this.previousStatsReport = null;\n        this.audioLevelsIntervalId = null;\n        this.eventEmitter = eventEmitter;\n        this.conferenceStats = new ConferenceStats();\n\n        // Updates stats interval\n        this.audioLevelsIntervalMilis = audioLevelsInterval;\n\n        this.speakerList = [];\n        this.statsIntervalId = null;\n        this.statsIntervalMilis = statsInterval;\n\n        /**\n         * Maps SSRC numbers to {@link SsrcStats}.\n         * @type {Map<number,SsrcStats}\n         */\n        this.ssrc2stats = new Map();\n\n        /**\n         * Tracks whether the previous stats cycle had any inbound video SSRCs in the bad state\n         * (bytes received, no frames decoded). Used to emit a final all-clear call to QualityController\n         * when the set transitions from non-empty to empty.\n         * @type {boolean}\n         */\n        this._hadBadInboundSsrcs = false;\n    }\n\n    /**\n     * Set the list of the remote speakers for which audio levels are to be calculated.\n     *\n     * @param {Array<string>} speakerList - Endpoint ids.\n     * @returns {void}\n     */\n    setSpeakerList(speakerList) {\n        this.speakerList = speakerList;\n    }\n\n    /**\n     * Stops stats updates.\n     */\n    stop() {\n        if (this.audioLevelsIntervalId) {\n            clearInterval(this.audioLevelsIntervalId);\n            this.audioLevelsIntervalId = null;\n        }\n\n        if (this.statsIntervalId) {\n            clearInterval(this.statsIntervalId);\n            this.statsIntervalId = null;\n        }\n    }\n\n    /**\n     * Callback passed to <tt>getStats</tt> method.\n     * @param error an error that occurred on <tt>getStats</tt> call.\n     */\n    errorCallback(error) {\n        logger.error('Get stats error', error);\n        this.stop();\n    }\n\n    /**\n     * Starts stats updates.\n     */\n    start(startAudioLevelStats) {\n        if (startAudioLevelStats && browser.supportsReceiverStats()) {\n            this.audioLevelsIntervalId = setInterval(\n                () => {\n                    const audioLevels = this.peerconnection.getAudioLevels(this.speakerList);\n\n                    for (const ssrc in audioLevels) {\n                        if (audioLevels.hasOwnProperty(ssrc)) {\n                            // Use a scaling factor of 2.5 to report the same audio levels that getStats reports.\n                            const audioLevel = audioLevels[ssrc] * 2.5;\n\n                            this.eventEmitter.emit(\n                                StatisticsEvents.AUDIO_LEVEL,\n                                this.peerconnection,\n                                Number.parseInt(ssrc, 10),\n                                audioLevel,\n                                false /* isLocal */);\n                        }\n                    }\n                },\n                this.audioLevelsIntervalMilis\n            );\n        }\n\n        const processStats = () => {\n            // Interval updates\n            this.peerconnection.getStats()\n                .then(report => {\n                    this.currentStatsReport = typeof report?.result === 'function'\n                        ? report.result()\n                        : report;\n\n                    try {\n                        this.processStatsReport();\n                    } catch (error) {\n                        logger.error('Processing of RTP stats failed:', error);\n                    }\n                    this.previousStatsReport = this.currentStatsReport;\n                })\n                .catch(error => this.errorCallback(error));\n        };\n\n        processStats();\n        this.statsIntervalId = setInterval(processStats, this.statsIntervalMilis);\n    }\n\n    /**\n     * Process and emit statistics report.\n     * @private\n     */\n    _processAndEmitReport() {\n        // process stats\n        const totalPackets = {\n            download: 0,\n            upload: 0\n        };\n        const lostPackets = {\n            download: 0,\n            upload: 0\n        };\n        let bitrateDownload = 0;\n        let bitrateUpload = 0;\n        const resolutions = {};\n        const framerates = {};\n        const codecs = {};\n        let audioBitrateDownload = 0;\n        let audioBitrateUpload = 0;\n        let videoBitrateDownload = 0;\n        let videoBitrateUpload = 0;\n\n        // Collects per-SSRC inbound video stats for remote decoding detection in QualityController.\n        const inboundVideoStats = new Map();\n\n        // Collects per-SSRC framesDecoded counters for freeze detection in TrackStreamingStatus.\n        const framesDecodedMap = new Map();\n\n        for (const [ ssrc, ssrcStats ] of this.ssrc2stats) {\n            // process packet loss stats\n            const loss = ssrcStats.loss;\n            const type = loss.isDownloadStream ? 'download' : 'upload';\n\n            totalPackets[type] += loss.packetsTotal;\n            lostPackets[type] += loss.packetsLost;\n\n            const ssrcBitrateDownload = ssrcStats.bitrate.download;\n            const ssrcBitrateUpload = ssrcStats.bitrate.upload;\n\n            // process bitrate stats\n            bitrateDownload += ssrcBitrateDownload;\n            bitrateUpload += ssrcBitrateUpload;\n\n            ssrcStats.resetBitrate();\n\n            // collect resolutions and framerates\n            const track = this.peerconnection.getTrackBySSRC(ssrc);\n\n            if (!track) {\n                continue; // eslint-disable-line no-continue\n            }\n\n            // Collect inbound video stats only for streams where bytes are being received but no frames are decoded.\n            // Filtering here avoids sending stats for healthy streams to QualityController on every cycle.\n            if (loss.isDownloadStream && !track.isLocal() && !track.isAudioTrack()\n                    && ssrcBitrateDownload > 0 && ssrcStats.framerate === 0) {\n                const participantId = track.getParticipantId();\n\n                if (participantId) {\n                    inboundVideoStats.set(ssrc, {\n                        bitrateDownload: ssrcBitrateDownload,\n                        fps: ssrcStats.framerate,\n                        participantId\n                    });\n                }\n            }\n\n            // Collect framesDecoded for all remote inbound video streams (used by TrackStreamingStatus for\n            // freeze detection on browsers where mute/unmute events are unreliable).\n            if (loss.isDownloadStream && !track.isLocal() && track.isVideoTrack()\n                    && typeof ssrcStats.framesDecoded === 'number') {\n                framesDecodedMap.set(ssrc, ssrcStats.framesDecoded);\n            }\n\n            let audioCodec;\n            let videoCodec;\n\n            if (track.isAudioTrack()) {\n                audioBitrateDownload += ssrcBitrateDownload;\n                audioBitrateUpload += ssrcBitrateUpload;\n                audioCodec = ssrcStats.codec;\n            } else {\n                videoBitrateDownload += ssrcBitrateDownload;\n                videoBitrateUpload += ssrcBitrateUpload;\n                videoCodec = ssrcStats.codec;\n            }\n\n            const participantId = track.getParticipantId();\n\n            if (!participantId) {\n                // All tracks in ssrc-rewriting mode need not have a participant associated with it.\n                if (!FeatureFlags.isSsrcRewritingSupported()) {\n                    logger.error(`No participant ID returned by ${track}`);\n                }\n                continue;\n            }\n\n            const userCodecs = codecs[participantId] ?? { };\n\n            userCodecs[ssrc] = {\n                audio: audioCodec,\n                video: videoCodec\n            };\n\n            codecs[participantId] = userCodecs;\n            const { resolution } = ssrcStats;\n\n            if (!track.isVideoTrack()\n                || !isValidNumber(resolution?.height)\n                || !isValidNumber(resolution?.width)\n                || resolution.height === -1\n                || resolution.width === -1) {\n                continue;\n            }\n            const userResolutions = resolutions[participantId] || {};\n\n            // If simulcast (VP8) is used, there will be 3 \"outbound-rtp\" streams with different resolutions and 3\n            // different SSRCs. Based on the requested resolution and the current cpu and available bandwidth\n            // values, some of the streams might get suspended. Therefore the actual send resolution needs to be\n            // calculated based on the outbound-rtp streams that are currently active for the simulcast case.\n            // However for the SVC case, there will be only 1 \"outbound-rtp\" stream which will have the correct\n            // send resolution width and height.\n            if (track.isLocal() && !browser.supportsTrackBasedStats() && this.peerconnection.doesTrueSimulcast(track)) {\n                const localSsrcs = this.peerconnection.getLocalVideoSSRCs(track);\n\n                for (const localSsrc of localSsrcs) {\n                    const ssrcResolution = this.ssrc2stats.get(localSsrc)?.resolution;\n\n                    // The code processes resolution stats only for 'outbound-rtp' streams that are currently active.\n                    if (ssrcResolution?.height && ssrcResolution?.width) {\n                        resolution.height = Math.max(resolution.height, ssrcResolution.height);\n                        resolution.width = Math.max(resolution.width, ssrcResolution.width);\n                    }\n                }\n            }\n\n            userResolutions[ssrc] = resolution;\n            resolutions[participantId] = userResolutions;\n\n            if (ssrcStats.framerate > 0) {\n                const userFramerates = framerates[participantId] || {};\n\n                userFramerates[ssrc] = ssrcStats.framerate;\n                framerates[participantId] = userFramerates;\n            }\n        }\n\n        this.conferenceStats.bitrate = {\n            download: bitrateDownload,\n            upload: bitrateUpload\n        };\n\n        this.conferenceStats.bitrate.audio = {\n            download: audioBitrateDownload,\n            upload: audioBitrateUpload\n        };\n\n        this.conferenceStats.bitrate.video = {\n            download: videoBitrateDownload,\n            upload: videoBitrateUpload\n        };\n\n        this.conferenceStats.packetLoss = {\n            download:\n                calculatePacketLoss(lostPackets.download, totalPackets.download),\n            total:\n                calculatePacketLoss(\n                    lostPackets.download + lostPackets.upload,\n                    totalPackets.download + totalPackets.upload),\n            upload:\n                calculatePacketLoss(lostPackets.upload, totalPackets.upload)\n        };\n\n        this.eventEmitter.emit(\n            StatisticsEvents.CONNECTION_STATS,\n            this.peerconnection,\n            {\n                bandwidth: this.conferenceStats.bandwidth,\n                bitrate: this.conferenceStats.bitrate,\n                codec: codecs,\n                framerate: framerates,\n                framesDecoded: framesDecodedMap,\n                packetLoss: this.conferenceStats.packetLoss,\n                resolution: resolutions,\n                transport: this.conferenceStats.transport\n            });\n        this.conferenceStats.transport = [];\n\n        // Emit when there are currently bad SSRCs, or when the previous cycle had bad SSRCs and this one has\n        // none (all-clear), so QualityController can fire resolution events and clean up its tracker.\n        if (inboundVideoStats.size || this._hadBadInboundSsrcs) {\n            this.eventEmitter.emit(StatisticsEvents.INBOUND_VIDEO_STATS, this.peerconnection, inboundVideoStats);\n        }\n        this._hadBadInboundSsrcs = inboundVideoStats.size > 0;\n    }\n\n    /**\n     * Converts the value to a non-negative number.\n     * If the value is either invalid or negative then 0 will be returned.\n     * @param {*} v\n     * @return {number}\n     * @private\n     */\n    getNonNegativeValue(v) {\n        let value = v;\n\n        if (typeof value !== 'number') {\n            value = Number(value);\n        }\n\n        if (!isValidNumber(value)) {\n            return 0;\n        }\n\n        return Math.max(0, value);\n    }\n\n    /**\n     * Calculates bitrate between before and now using a supplied field name and its\n     * value in the stats.\n     * @param {RTCInboundRtpStreamStats|RTCSentRtpStreamStats} now the current stats\n     * @param {RTCInboundRtpStreamStats|RTCSentRtpStreamStats} before the\n     * previous stats.\n     * @param fieldName the field to use for calculations.\n     * @return {number} the calculated bitrate between now and before.\n     * @private\n     */\n    _calculateBitrate(now, before, fieldName) {\n        const bytesNow = this.getNonNegativeValue(now[fieldName]);\n        const bytesBefore = this.getNonNegativeValue(before[fieldName]);\n        const bytesProcessed = Math.max(0, bytesNow - bytesBefore);\n\n        const timeMs = now.timestamp - before.timestamp;\n        let bitrateKbps = 0;\n\n        if (timeMs > 0) {\n            // TODO is there any reason to round here?\n            bitrateKbps = Math.round((bytesProcessed * 8) / timeMs);\n        }\n\n        return bitrateKbps;\n    }\n\n    /**\n     * Calculates the frames per second rate between before and now using a supplied field name and its value in stats.\n     * @param {RTCOutboundRtpStreamStats|RTCSentRtpStreamStats} now the current stats\n     * @param {RTCOutboundRtpStreamStats|RTCSentRtpStreamStats} before the previous stats\n     * @param {string} fieldName the field to use for calculations.\n     * @returns {number} the calculated frame rate between now and before.\n     */\n    _calculateFps(now, before, fieldName) {\n        const timeMs = now.timestamp - before.timestamp;\n        let frameRate = 0;\n\n        if (timeMs > 0 && now[fieldName]) {\n            const numberOfFramesSinceBefore = now[fieldName] - before[fieldName];\n\n            frameRate = (numberOfFramesSinceBefore / timeMs) * 1000;\n        }\n\n        return frameRate;\n    }\n\n    /**\n     * Stats processing for spec-compliant RTCPeerConnection#getStats.\n     */\n    processStatsReport() {\n        const byteSentStats = {};\n        const encodedTimeStatsPerSsrc = new Map();\n\n        // Cumulative packetsReceived per inbound audio SSRC, collected during the pass below and emitted once so the\n        // RemoteAudioWedgeDetector can run off this poll instead of a separate getStats() loop.\n        const inboundAudioPacketsBySsrc = new Map();\n\n        this.currentStatsReport.forEach(now => {\n            const before = this.previousStatsReport ? this.previousStatsReport.get(now.id) : null;\n\n            // RTCIceCandidatePairStats - https://w3c.github.io/webrtc-stats/#candidatepair-dict*\n            if (now.type === 'candidate-pair' && now.nominated && now.state === 'succeeded') {\n                const availableIncomingBitrate = now.availableIncomingBitrate;\n                const availableOutgoingBitrate = now.availableOutgoingBitrate;\n\n                if (availableIncomingBitrate || availableOutgoingBitrate) {\n                    this.conferenceStats.bandwidth = {\n                        'download': Math.round(availableIncomingBitrate / 1000),\n                        'upload': Math.round(availableOutgoingBitrate / 1000)\n                    };\n                }\n\n                const remoteUsedCandidate = this.currentStatsReport.get(now.remoteCandidateId);\n                const localUsedCandidate = this.currentStatsReport.get(now.localCandidateId);\n\n                // RTCIceCandidateStats\n                // https://w3c.github.io/webrtc-stats/#icecandidate-dict*\n                if (remoteUsedCandidate && localUsedCandidate) {\n                    const remoteIpAddress = browser.isChromiumBased()\n                        ? remoteUsedCandidate.ip\n                        : remoteUsedCandidate.address;\n                    const remotePort = remoteUsedCandidate.port;\n                    const ip = `${remoteIpAddress}:${remotePort}`;\n\n                    const localIpAddress = browser.isChromiumBased()\n                        ? localUsedCandidate.ip\n                        : localUsedCandidate.address;\n                    const localPort = localUsedCandidate.port;\n                    const localip = `${localIpAddress}:${localPort}`;\n                    const type = remoteUsedCandidate.protocol;\n\n                    // Save the address unless it has been saved already.\n                    const conferenceStatsTransport = this.conferenceStats.transport;\n\n                    if (!conferenceStatsTransport.some(t =>\n                        t.ip === ip\n                        && t.type === type\n                        && t.localip === localip)) {\n                        conferenceStatsTransport.push({\n                            ip,\n                            localCandidateType: localUsedCandidate.candidateType,\n                            localip,\n                            networkType: localUsedCandidate.networkType,\n                            p2p: this.peerconnection.isP2P,\n                            remoteCandidateType: remoteUsedCandidate.candidateType,\n                            rtt: now.currentRoundTripTime * 1000,\n                            type\n                        });\n                    }\n                }\n\n            // RTCReceivedRtpStreamStats\n            // https://w3c.github.io/webrtc-stats/#receivedrtpstats-dict*\n            // RTCSentRtpStreamStats\n            // https://w3c.github.io/webrtc-stats/#sentrtpstats-dict*\n            } else if (now.type === 'inbound-rtp' || now.type === 'outbound-rtp') {\n                const ssrc = this.getNonNegativeValue(now.ssrc);\n\n                if (!ssrc) {\n                    return;\n                }\n\n                let ssrcStats = this.ssrc2stats.get(ssrc);\n\n                if (!ssrcStats) {\n                    ssrcStats = new SsrcStats();\n                    this.ssrc2stats.set(ssrc, ssrcStats);\n                }\n\n                let isDownloadStream = true;\n                let key = 'packetsReceived';\n\n                if (now.type === 'outbound-rtp') {\n                    isDownloadStream = false;\n                    key = 'packetsSent';\n                }\n\n                let packetsNow = now[key];\n\n                if (!packetsNow || packetsNow < 0) {\n                    packetsNow = 0;\n                }\n\n                if (now.type === 'inbound-rtp' && (now.kind === MediaType.AUDIO || now.mediaType === MediaType.AUDIO)) {\n                    inboundAudioPacketsBySsrc.set(ssrc, packetsNow);\n                }\n\n                if (before) {\n                    const packetsBefore = this.getNonNegativeValue(before[key]);\n                    const packetsDiff = Math.max(0, packetsNow - packetsBefore);\n\n                    const packetsLostNow = this.getNonNegativeValue(now.packetsLost);\n                    const packetsLostBefore = this.getNonNegativeValue(before.packetsLost);\n                    const packetsLostDiff = Math.max(0, packetsLostNow - packetsLostBefore);\n\n                    ssrcStats.setLoss({\n                        isDownloadStream,\n                        packetsLost: packetsLostDiff,\n                        packetsTotal: packetsDiff + packetsLostDiff\n                    });\n                }\n\n                let resolution;\n\n                // Process the stats for 'inbound-rtp' streams always and 'outbound-rtp' only if the browser is\n                // Chromium based and version 112 and later since 'track' based stats are no longer available there\n                // for calculating send resolution and frame rate.\n                if (typeof now.frameHeight !== 'undefined' && typeof now.frameWidth !== 'undefined') {\n                    // Assume the stream is active if the field is missing in the stats(Firefox)\n                    const isStreamActive = now.active ?? true;\n\n                    if (now.type === 'inbound-rtp' || (!browser.supportsTrackBasedStats() && isStreamActive)) {\n                        resolution = {\n                            height: now.frameHeight,\n                            width: now.frameWidth\n                        };\n                    }\n                }\n                ssrcStats.setResolution(resolution);\n\n                let frameRate = now.framesPerSecond;\n\n                if (!frameRate && before) {\n                    frameRate = this._calculateFps(now, before, 'framesSent');\n                }\n\n                ssrcStats.setFramerate(Math.round(frameRate || 0));\n\n                if (now.type === 'inbound-rtp' && before) {\n                    ssrcStats.addBitrate({\n                        'download': this._calculateBitrate(now, before, 'bytesReceived'),\n                        'upload': 0\n                    });\n                }\n\n                if (now.type === 'inbound-rtp' && typeof now.framesDecoded === 'number') {\n                    ssrcStats.setFramesDecoded(now.framesDecoded);\n                }\n\n                if (now.type !== 'inbound-rtp' && before) {\n                    byteSentStats[ssrc] = this.getNonNegativeValue(now.bytesSent);\n                    ssrcStats.addBitrate({\n                        'download': 0,\n                        'upload': this._calculateBitrate(now, before, 'bytesSent')\n                    });\n                }\n\n                const codec = this.currentStatsReport.get(now.codecId);\n\n                if (codec) {\n                    /**\n                     * The mime type has the following form: video/VP8 or audio/ISAC, so we what to keep just the type\n                     * after the '/', audio and video keys will be added on the processing side.\n                     */\n                    const codecShortType = codec.mimeType.split('/')[1];\n\n                    codecShortType && ssrcStats.setCodec(codecShortType);\n\n                    // Calculate the encodeTime stat for outbound video streams.\n                    const track = this.peerconnection.getTrackBySSRC(ssrc);\n\n                    if (now.type === 'outbound-rtp'\n                        && now.active\n                        && track?.isVideoTrack()\n                        && before?.totalEncodeTime\n                        && before?.framesEncoded\n                        && now.frameHeight\n                        && now.frameWidth) {\n                        const encodeTimeDelta = now.totalEncodeTime - before.totalEncodeTime;\n                        const framesEncodedDelta = now.framesEncoded - before.framesEncoded;\n                        const encodeTimePerFrameInMs = 1000 * encodeTimeDelta / framesEncodedDelta;\n                        const encodeTimeStats = {\n                            codec: codecShortType,\n                            encodeTime: encodeTimePerFrameInMs,\n                            qualityLimitationReason: now.qualityLimitationReason,\n                            resolution,\n                            timestamp: now.timestamp\n                        };\n\n                        encodedTimeStatsPerSsrc.set(ssrc, encodeTimeStats);\n                        ssrcStats.setEncodeStats(encodedTimeStatsPerSsrc);\n                    }\n                }\n\n            // Continue to use the 'track' based stats for Firefox and Safari and older versions of Chromium.\n            } else if (browser.supportsTrackBasedStats()\n                && now.type === 'track'\n                && now.kind === MediaType.VIDEO\n                && !now.remoteSource) {\n                const resolution = {\n                    height: now.frameHeight,\n                    width: now.frameWidth\n                };\n                const localVideoTracks = this.peerconnection.getLocalTracks(MediaType.VIDEO);\n\n                if (!localVideoTracks?.length) {\n                    return;\n                }\n\n                const ssrc = this.peerconnection.getSsrcByTrackId(now.trackIdentifier);\n\n                if (!ssrc) {\n                    return;\n                }\n                let ssrcStats = this.ssrc2stats.get(ssrc);\n\n                if (!ssrcStats) {\n                    ssrcStats = new SsrcStats();\n                    this.ssrc2stats.set(ssrc, ssrcStats);\n                }\n                if (resolution.height && resolution.width) {\n                    ssrcStats.setResolution(resolution);\n                }\n\n                // Calculate the frame rate. 'framesSent' is the total aggregate value for all the simulcast streams.\n                // Therefore, it needs to be divided by the total number of active simulcast streams.\n                let frameRate = now.framesPerSecond;\n\n                if (!frameRate && before) {\n                    frameRate = this._calculateFps(now, before, 'framesSent');\n                }\n                ssrcStats.setFramerate(frameRate);\n            }\n        });\n\n        if (Object.keys(byteSentStats).length) {\n            this.eventEmitter.emit(StatisticsEvents.BYTE_SENT_STATS, this.peerconnection, byteSentStats);\n        }\n\n        if (encodedTimeStatsPerSsrc.size) {\n            this.eventEmitter.emit(StatisticsEvents.ENCODE_TIME_STATS, this.peerconnection, encodedTimeStatsPerSsrc);\n        }\n\n        // Emitted on the RTC event bus (not the statistics one) so RemoteAudioWedgeDetector, which is scoped to a\n        // peerconnection, can consume it directly without threading through the conference-level stats plumbing.\n        this.peerconnection.eventEmitter.emit(\n            RTCEvents.INBOUND_AUDIO_STATS, this.peerconnection, inboundAudioPacketsBySsrc);\n\n        this._processAndEmitReport();\n    }\n}\n","import { getLogger } from '@jitsi/logger';\n\nimport JitsiConference from '../../JitsiConference';\nimport { JitsiTrackEvents } from '../../JitsiTrackEvents';\nimport { AnalyticsEvents } from '../../service/statistics/AnalyticsEvents';\nimport { StatisticsEvents } from '../../service/statistics/Events';\nimport { LOCAL_JID } from '../../service/statistics/constants';\nimport JitsiTrack from '../RTC/JitsiTrack';\nimport TraceablePeerConnection from '../RTC/TraceablePeerConnection';\nimport RTCStats from '../RTCStats/RTCStats';\nimport browser from '../browser';\nimport EventEmitter from '../util/EventEmitter';\nimport WatchRTC from '../watchRTC/WatchRTC';\nimport XMPP from '../xmpp/xmpp';\n\nimport analytics from './AnalyticsAdapter';\nimport LocalStats from './LocalStatsCollector';\nimport RTPStats from './RTPStatsCollector';\n\nconst logger = getLogger('stats:statistics');\n\nexport type IStatisticsOptions = {\n    aliasName?: string;\n    applicationName?: string;\n    callStatsID?: string;\n    callStatsSecret?: string;\n    confID?: string;\n    customScriptUrl?: string;\n    roomName?: string;\n    userName?: string;\n};\n\n/**\n * Statistics class provides various functionality related to collecting and reporting statistics.\n */\nexport default class Statistics {\n    /**\n     * Stores all active Statistics instances.\n     * @type {Set<Statistics>}\n     */\n    static _instances: Set<Statistics>;\n\n    /**\n     * Static getter for instances property\n     * Returns the Set holding all active Statistics instances. Lazily\n     * initializes the Set to allow any Set polyfills to be applied.\n     * @type {Set<Statistics>}\n     */\n    static get instances(): Set<Statistics> {\n        if (!Statistics._instances) {\n            Statistics._instances = new Set();\n        }\n\n        return Statistics._instances;\n    }\n\n    /**\n     * Flag indicating whether audio levels are enabled or not.\n     * @static\n     * @type {boolean}\n     */\n    static audioLevelsEnabled: boolean = false;\n\n    /**\n     * The interval for audio levels stats collection.\n     * @static\n     * @type {number}\n     */\n    static audioLevelsInterval: number = 200;\n\n    /**\n     * The interval for peer connection stats collection.\n     * @static\n     * @type {number}\n     */\n    static pcStatsInterval: number = 10000;\n\n    /**\n     * Flag indicating whether third party requests are disabled.\n     * @static\n     * @type {boolean}\n     */\n    static disableThirdPartyRequests: boolean = false;\n\n    /**\n     * Analytics adapter for sending events.\n     * @static\n     * @type {Object}\n     */\n    static analytics: {\n        addPermanentProperties: (properties: Record<string, any>) => void;\n        sendEvent: (eventName: string | Record<string, any>, properties?: Record<string, any>) => void;\n    } = analytics;\n\n    /**\n     * Array holding local statistics collectors.\n     * @static\n     * @type {Array}\n     */\n    static localStats: LocalStats[] = [];\n\n    /**\n     * Local JID constant.\n     * @static\n     * @type {string}\n     */\n    static LOCAL_JID: string = LOCAL_JID;\n\n    /**\n     * Init statistic options\n     * @static\n     * @param {Object} options - The options to initialize statistics with\n     */\n    static init(options: {\n        audioLevelsInterval?: number;\n        disableAudioLevels?: boolean;\n        disableThirdPartyRequests?: boolean;\n        pcStatsInterval?: number;\n    }): void {\n        Statistics.audioLevelsEnabled = !options.disableAudioLevels;\n        if (typeof options.pcStatsInterval === 'number') {\n            Statistics.pcStatsInterval = options.pcStatsInterval;\n        }\n        if (typeof options.audioLevelsInterval === 'number') {\n            Statistics.audioLevelsInterval = options.audioLevelsInterval;\n        }\n        Statistics.disableThirdPartyRequests = options.disableThirdPartyRequests;\n        LocalStats.init();\n        WatchRTC.init(options);\n    }\n\n    /**\n     * Starts collecting local statistics for a track.\n     * @static\n     * @param {JitsiTrack} track - The track to collect statistics for\n     * @param {Function} callback - The callback to invoke with audio levels\n     */\n    static startLocalStats(track: JitsiTrack, callback: (audioLevel: number) => void): void {\n        if (browser.isIosBrowser()) {\n            // On iOS browsers audio is lost if the audio input device is in use by another app\n            // https://bugs.webkit.org/show_bug.cgi?id=233473\n            // The culprit was using the AudioContext, so now we close the AudioContext during\n            // the track being muted, and re-instantiate it afterwards.\n            track.addEventListener(\n                JitsiTrackEvents.NO_DATA_FROM_SOURCE,\n                /**\n                 * Closes AudioContext on no audio data, and enables it on data received again.\n                 *\n                 * @param {boolean} value - Whether we receive audio data or not.\n                 */\n                async (value: boolean) => {\n                    if (value) {\n                        for (const localStat of Statistics.localStats) {\n                            localStat.stop();\n                        }\n                        await LocalStats.disconnectAudioContext();\n                    } else {\n                        LocalStats.connectAudioContext();\n                        for (const localStat of Statistics.localStats) {\n                            localStat.start();\n                        }\n                    }\n                }\n            );\n        }\n        if (!Statistics.audioLevelsEnabled) {\n            return;\n        }\n        track.addEventListener(\n            JitsiTrackEvents.LOCAL_TRACK_STOPPED,\n            () => {\n                Statistics.stopLocalStats(track);\n            }\n        );\n        const stream = track.getOriginalStream();\n        const localStats = new LocalStats(stream, Statistics.audioLevelsInterval, callback);\n\n        this.localStats.push(localStats);\n        localStats.start();\n    }\n\n    /**\n     * Stops collecting local statistics for a track.\n     * @static\n     * @param {JitsiTrack} track - The track to stop collecting statistics for\n     */\n    static stopLocalStats(track: JitsiTrack): void {\n        if (!Statistics.audioLevelsEnabled) {\n            return;\n        }\n        const stream = track.getOriginalStream();\n\n        for (let i = 0; i < Statistics.localStats.length; i++) {\n            if (Statistics.localStats[i].stream === stream) {\n                const localStats = Statistics.localStats.splice(i, 1);\n\n                localStats[0].stop();\n                break;\n            }\n        }\n    }\n\n    /**\n     * Sends event to analytics and logs a message to the logger/console.\n     * @static\n     * @param {string | Object} event - The event name, or an object which represents the entire event\n     * @param {Object} properties - Properties to attach to the event\n     */\n    static sendAnalyticsAndLog(event: string | Record<string, any>, properties: Record<string, any> = {}): void {\n        if (!event) {\n            logger.warn('No event or event name given.');\n\n            return;\n        }\n        let eventToLog;\n\n        // Also support an API with a single object as an event.\n        if (typeof event === 'object') {\n            eventToLog = event;\n        } else {\n            eventToLog = {\n                name: event,\n                properties\n            };\n        }\n        logger.debug(JSON.stringify(eventToLog));\n        // We do this last, because it may modify the object which is passed.\n        this.analytics.sendEvent(event, properties);\n    }\n\n    /**\n     * Sends event to analytics.\n     * @static\n     * @param {string | Object} eventName - The event name, or an object which represents the entire event\n     * @param {Object} properties - Properties to attach to the event\n     */\n    static sendAnalytics(eventName: string | Record<string, any>, properties: Record<string, any> = {}): void {\n        this.analytics.sendEvent(eventName, properties);\n    }\n\n    /**\n     * The options to configure Statistics.\n     * @typedef {Object} StatisticsOptions\n     * @property {string} userName - The user name to use\n     * @property {string} roomName - The room name we are currently in.\n     *\n     * @param {JitsiConference} conference - The conference instance from which the statistics were initialized.\n     * @param {StatisticsOptions} options - The options to use creating the\n     * Statistics.\n     */\n    rtpStatsMap: Map<string, RTPStats>;\n    eventEmitter: EventEmitter;\n    conference: JitsiConference;\n    xmpp: XMPP;\n    options: IStatisticsOptions;\n\n    constructor(conference: JitsiConference, options: IStatisticsOptions) {\n        /**\n         * {@link RTPStats} mapped by {@link TraceablePeerConnection.id} which\n         * collect RTP statistics for each peerconnection.\n         * @type {Map<string, RTPStats>}\n         */\n        this.rtpStatsMap = new Map();\n        this.eventEmitter = new EventEmitter();\n        this.conference = conference;\n        this.xmpp = conference?.xmpp;\n        this.options = options || ({} as IStatisticsOptions);\n        Statistics.instances.add(this);\n        RTCStats.attachToConference(this.conference);\n        // WatchRTC is not required to work for react native\n        if (!browser.isReactNative()) {\n            WatchRTC.start(this.options.roomName, this.options.userName);\n        }\n    }\n\n    /**\n     * Starts collecting RTP stats for given peerconnection.\n     * @param {TraceablePeerConnection} peerconnection\n     */\n    startRemoteStats(peerconnection: TraceablePeerConnection): void {\n        this.stopRemoteStats(peerconnection);\n        try {\n            const rtpStats = new RTPStats(\n                peerconnection,\n                Statistics.audioLevelsInterval,\n                Statistics.pcStatsInterval,\n                this.eventEmitter\n            );\n\n            rtpStats.start(Statistics.audioLevelsEnabled);\n            this.rtpStatsMap.set(String(peerconnection.id), rtpStats);\n        } catch (e) {\n            logger.error(`Failed to start collecting remote statistics: ${e}`);\n        }\n    }\n\n    /**\n     * Adds a listener for audio level events.\n     * @param {Function} listener - The listener to add\n     */\n    addAudioLevelListener(listener: (...args: any[]) => void): void {\n        if (!Statistics.audioLevelsEnabled) {\n            return;\n        }\n        this.eventEmitter.on(StatisticsEvents.AUDIO_LEVEL, listener);\n    }\n\n    /**\n     * Removes an audio level listener.\n     * @param {Function} listener - The listener to remove\n     */\n    removeAudioLevelListener(listener: (...args: any[]) => void): void {\n        if (!Statistics.audioLevelsEnabled) {\n            return;\n        }\n        this.eventEmitter.removeListener(StatisticsEvents.AUDIO_LEVEL, listener);\n    }\n\n    /**\n     * Adds a listener for before disposed events.\n     * @param {Function} listener - The listener to add\n     */\n    addBeforeDisposedListener(listener: (...args: any[]) => void): void {\n        this.eventEmitter.on(StatisticsEvents.BEFORE_DISPOSED, listener);\n    }\n\n    /**\n     * Removes a before disposed listener.\n     * @param {Function} listener - The listener to remove\n     */\n    removeBeforeDisposedListener(listener: (...args: any[]) => void): void {\n        this.eventEmitter.removeListener(\n            StatisticsEvents.BEFORE_DISPOSED, listener);\n    }\n\n    /**\n     * Adds a listener for connection stats events.\n     * @param {Function} listener - The listener to add\n     */\n    addConnectionStatsListener(listener: (...args: any[]) => void): void {\n        this.eventEmitter.on(StatisticsEvents.CONNECTION_STATS, listener);\n    }\n\n    /**\n     * Removes a connection stats listener.\n     * @param {Function} listener - The listener to remove\n     */\n    removeConnectionStatsListener(listener: (...args: any[]) => void): void {\n        this.eventEmitter.removeListener(\n            StatisticsEvents.CONNECTION_STATS,\n            listener);\n    }\n\n    /**\n     * Adds a listener for encode time stats events.\n     * @param {Function} listener - The listener to add\n     */\n    addEncodeTimeStatsListener(listener: (...args: any[]) => void): void {\n        this.eventEmitter.on(StatisticsEvents.ENCODE_TIME_STATS, listener);\n    }\n\n    /**\n     * Removes an encode time stats listener.\n     * @param {Function} listener - The listener to remove\n     */\n    removeEncodeTimeStatsListener(listener: (...args: any[]) => void): void {\n        this.eventEmitter.removeListener(StatisticsEvents.ENCODE_TIME_STATS, listener);\n    }\n\n    /**\n     * Adds a listener for inbound video stats events. The event fires when at least one remote video stream is\n     * receiving bytes but decoding no frames, and once more with an empty map when all such streams recover.\n     * @param {Function} listener - The listener to add\n     */\n    addInboundVideoStatsListener(listener: (...args: any[]) => void): void {\n        this.eventEmitter.on(StatisticsEvents.INBOUND_VIDEO_STATS, listener);\n    }\n\n    /**\n     * Removes an inbound video stats listener.\n     * @param {Function} listener - The listener to remove\n     */\n    removeInboundVideoStatsListener(listener: (...args: any[]) => void): void {\n        this.eventEmitter.removeListener(StatisticsEvents.INBOUND_VIDEO_STATS, listener);\n    }\n\n    /**\n     * Adds a listener for byte sent stats events.\n     * @param {Function} listener - The listener to add\n     */\n    addByteSentStatsListener(listener: (...args: any[]) => void): void {\n        this.eventEmitter.on(StatisticsEvents.BYTE_SENT_STATS, listener);\n    }\n\n    /**\n     * Removes a byte sent stats listener.\n     * @param {Function} listener - The listener to remove\n     */\n    removeByteSentStatsListener(listener: (...args: any[]) => void): void {\n        this.eventEmitter.removeListener(StatisticsEvents.BYTE_SENT_STATS,\n            listener);\n    }\n\n    /**\n     * Updates the list of speakers for which the audio levels are to be calculated. This is needed for the jvb pc only.\n     *\n     * @param {Array<string>} speakerList The list of remote endpoint ids.\n     * @returns {void}\n     */\n    setSpeakerList(speakerList: string[]): void {\n        for (const rtpStats of Array.from(this.rtpStatsMap.values())) {\n            if (!rtpStats.peerconnection.isP2P) {\n                rtpStats.setSpeakerList(speakerList);\n            }\n        }\n    }\n\n    /**\n     * Disposes of this instance, stopping any ongoing stats collection.\n     */\n    dispose(): void {\n        try {\n            this.eventEmitter.emit(StatisticsEvents.BEFORE_DISPOSED);\n            for (const tpcId of this.rtpStatsMap.keys()) {\n                this._stopRemoteStats(tpcId);\n            }\n            if (this.eventEmitter) {\n                this.eventEmitter.removeAllListeners();\n            }\n        } finally {\n            Statistics.instances.delete(this);\n        }\n    }\n\n    /**\n     * Stops remote RTP stats for given peerconnection ID.\n     * @param {string} tpcId {@link TraceablePeerConnection.id}\n     * @private\n     */\n    _stopRemoteStats(tpcId: string): void {\n        const rtpStats = this.rtpStatsMap.get(tpcId);\n\n        if (rtpStats) {\n            rtpStats.stop();\n            this.rtpStatsMap.delete(tpcId);\n        }\n    }\n\n    /**\n     * Stops collecting RTP stats for given peerconnection\n     * @param {TraceablePeerConnection} tpc\n     */\n    stopRemoteStats(tpc: TraceablePeerConnection): void {\n        this._stopRemoteStats(String(tpc.id));\n    }\n\n    /**\n     * Sends the given feedback\n     *\n     * @param {number} overall an integer between 1 and 5 indicating the user's rating.\n     * @param {string} comment the comment from the user.\n     * @returns {Promise} Resolves immediately.\n     */\n    sendFeedback(overall: number, comment: string): Promise<void> {\n        // Statistics.analytics.sendEvent is currently fire and forget, without\n        // confirmation of successful send.\n        Statistics.analytics.sendEvent(\n            AnalyticsEvents.FEEDBACK,\n            {\n                comment,\n                rating: overall\n            });\n\n        return Promise.resolve();\n    }\n}\n\n","export const LOCAL_JID = 'local';\n","/**\n * Implements utility to forward events from one eventEmitter to another.\n * @param src {object} instance of EventEmitter or another class that implements\n * addListener method which will register listener to EventEmitter instance.\n * @param dest {object} instance of EventEmitter or another class that\n * implements emit method which will emit an event.\n */\nexport default class EventEmitterForwarder {\n    src: any;\n    dest: any;\n    listeners: Map<any, any>;\n\n    /**\n     * @constructor\n     */\n    constructor(src: any, dest: any) {\n        if (!src || !dest || typeof src.addListener !== 'function' || typeof dest.emit !== 'function') {\n            throw new Error('Invalid arguments passed to EventEmitterForwarder');\n        }\n        this.src = src;\n        this.dest = dest;\n        this.listeners = new Map();\n    }\n\n    /**\n     * Adds event to be forwarded from src to dest.\n     * @param srcEvent {string} the event that EventEmitterForwarder is listening\n     * for.\n     * @param dstEvent {string} the event that will be fired from dest.\n     * @param arguments all other passed arguments are going to be fired with\n     * dstEvent.\n     */\n    forward(...args) {\n        const srcEvent = args[0];\n\n        // This will be the \"this\" value for emit function.\n        args[0] = this.dest;\n\n        // Using bind.apply to pass the arguments as Array-like object (\"arguments\")\n        const newListener = Function.prototype.bind.apply(this.dest.emit, args);\n\n        this.src.addListener(srcEvent, newListener);\n        this.listeners.set(srcEvent, newListener);\n    }\n\n    /**\n     * Clears the listeners for the supplied events.\n     *\n     * @param args all the events which listeners to be cleaned.\n     */\n    removeListeners(...args) {\n        args.forEach(a => {\n            const l = this.listeners.get(a);\n\n            if (l) {\n                this.src.removeListener(a, l);\n                this.listeners.delete(a);\n            }\n        });\n    }\n}\n","export enum AuthenticationEvents {\n    /**\n     * Event callback arguments:\n     * function(authenticationEnabled, userIdentity)\n     * authenticationEnabled - indicates whether authentication has been enabled\n     *                         in this session\n     * userIdentity - if user has been logged in then it contains user name. If\n     *                contains 'null' or 'undefined' then user is not logged in.\n     */\n    IDENTITY_UPDATED = 'authentication.identity_updated'\n}\n","export enum XMPPEvents {\n\n    /**\n     * Indicates error while adding ice candidate.\n     */\n    ADD_ICE_CANDIDATE_FAILED = 'xmpp.add_ice_candidate_failed',\n\n    // Designates an event indicating that the focus has asked us to mute our\n    // audio.\n    AUDIO_MUTED_BY_FOCUS = 'xmpp.audio_muted_by_focus',\n\n    AUTHENTICATION_REQUIRED = 'xmpp.authentication_required',\n\n    /**\n     * Event fired when we receive a message for AV moderation approved for the local participant.\n     */\n    AV_MODERATION_APPROVED = 'xmpp.av_moderation.approved',\n\n    /**\n     * Event fired when the moderation enable/disable changes.\n     */\n    AV_MODERATION_CHANGED = 'xmpp.av_moderation.changed',\n\n    /**\n     * Event fired when we receive message that a new jid was approved.\n     */\n    AV_MODERATION_PARTICIPANT_APPROVED = 'xmpp.av_moderation.participant.approved',\n\n    /**\n     * Event fired when we receive message that a new jid was rejected.\n     */\n    AV_MODERATION_PARTICIPANT_REJECTED = 'xmpp.av_moderation.participant.rejected',\n\n    /**\n     * Event fired when we receive a message for AV moderation.\n     */\n    AV_MODERATION_RECEIVED = 'xmpp.av_moderation.received',\n\n    /**\n    * Event fired when we receive a message for AV moderation rejected for the local participant.\n    */\n    AV_MODERATION_REJECTED = 'xmpp.av_moderation.rejected',\n\n    /**\n     * Event fired when we receive a message for breakout rooms.\n     */\n    BREAKOUT_ROOMS_EVENT = 'xmpp.breakout-rooms.event',\n\n    /**\n     * Event fired when a participant is requested to join a given (breakout) room.\n     */\n    BREAKOUT_ROOMS_MOVE_TO_ROOM = 'xmpp.breakout-rooms.move-to-room',\n\n    /**\n     * Event fired when the breakout rooms data was updated.\n     */\n    BREAKOUT_ROOMS_UPDATED = 'xmpp.breakout-rooms.updated',\n\n    BRIDGE_DOWN = 'xmpp.bridge_down',\n\n    /**\n     * Triggered when 'session-accept' is received from the responder.\n     */\n    CALL_ACCEPTED = 'xmpp.callaccepted.jingle',\n\n    // Triggered when Jicofo kills our media session, this can happen while\n    // we're still in the MUC, when it decides to terminate the media session.\n    // For example when the session is idle for too long, because we're the only\n    // person in the conference room.\n    CALL_ENDED = 'xmpp.callended.jingle',\n\n    // Designates an event indicating that an offer (e.g. Jingle\n    // session-initiate) was received.\n    CALL_INCOMING = 'xmpp.callincoming.jingle',\n\n    CHAT_ERROR_RECEIVED = 'xmpp.chat_error_received',\n\n    // The conference properties (as advertised by jicofo) have changed\n    CONFERENCE_PROPERTIES_CHANGED = 'xmpp.conference_properties_changed',\n\n    /**\n     * Event fired when conference creation timestamp is received.\n     */\n    CONFERENCE_TIMESTAMP_RECEIVED = 'xmpp.conference_timestamp_received',\n\n    /**\n     * This event is triggered when the ICE connects for the first time.\n     */\n    CONNECTION_ESTABLISHED = 'xmpp.connection.connected',\n\n    // Designates an event indicating that the connection to the XMPP server\n    // failed.\n    CONNECTION_FAILED = 'xmpp.connection.failed',\n\n    // Designates an event indicating that the media (ICE) connection failed.\n    // This should go to the RTC module.\n    CONNECTION_ICE_FAILED = 'xmpp.connection.ice.failed',\n\n    // Designates an event indicating that the media (ICE) connection was\n    // interrupted. This should go to the RTC module.\n    CONNECTION_INTERRUPTED = 'xmpp.connection.interrupted',\n\n    // Designates an event indicating that the media (ICE) connection was\n    // restored. This should go to the RTC module.\n    CONNECTION_RESTORED = 'xmpp.connection.restored',\n\n    /**\n     * Designates an event indicating connection status changes.\n     */\n    CONNECTION_STATUS_CHANGED = 'xmpp.connection.status.changed',\n\n    /**\n     * Designates an event indicating that the focus has asked us to disable our\n     * desktop share.\n     */\n    DESKTOP_MUTED_BY_FOCUS = 'xmpp.desktop_muted_by_focus',\n\n    // Designates an event indicating that the display name of a participant\n    // has changed.\n    DISPLAY_NAME_CHANGED = 'xmpp.display_name_changed',\n\n    /**\n     * Event for incoming presence error which is for required display name.\n     */\n    DISPLAY_NAME_REQUIRED = 'xmpp.display_name_required',\n\n    /**\n     * Chat room instance have been added to Strophe.emuc plugin.\n     */\n    EMUC_ROOM_ADDED = 'xmpp.emuc_room_added',\n\n    /**\n     * Chat room instance have been removed from Strophe.emuc plugin.\n     */\n    EMUC_ROOM_REMOVED = 'xmpp.emuc_room_removed',\n\n    ETHERPAD = 'xmpp.etherpad',\n\n    /**\n     * Event fired when we receive a message for files sharing.\n     */\n    FILE_SHARING_EVENT = 'xmpp.files-sharing.event',\n\n    /**\n     * Event emitted when a list file is received in the conference.\n     */\n    FILE_SHARING_FILES_RECEIVED = 'xmpp.files-sharing.list',\n\n    /**\n     * Event emitted when a file is added to the conference.\n     */\n    FILE_SHARING_FILE_ADDED = 'xmpp.files-sharing.add',\n\n    /**\n     * Event emitted when a file is removed from the conference.\n     */\n    FILE_SHARING_FILE_REMOVED = 'xmpp.files-sharing.remove',\n\n    FOCUS_DISCONNECTED = 'xmpp.focus_disconnected',\n\n    FOCUS_LEFT = 'xmpp.focus_left',\n\n    GRACEFUL_SHUTDOWN = 'xmpp.graceful_shutdown',\n\n    // Designates an event indicating that the local ICE connection state has\n    // changed.\n    ICE_CONNECTION_STATE_CHANGED = 'xmpp.ice_connection_state_changed',\n\n    // Designates an event indicating that an invite XMPP message in the MUC was\n    // received.\n    INVITE_MESSAGE_RECEIVED = 'xmpp.invite_message_received',\n\n    /**\n     * Event which is emitted when the body in an XMPP message in the MUC\n     * contains JSON\n     * TODO: this event contains a typo (xmmp vs xmpp) but it's unlikely this can be changed now\n     */\n    JSON_MESSAGE_RECEIVED = 'xmmp.json_message_received',\n\n    /**\n     * Designates an event indicating that we were kicked from the XMPP MUC.\n     * @param {boolean} isSelfPresence - whether it is for local participant\n     * or another participant.\n     * @param {string} actorJid - the jid of the participant who was initiator\n     * of the kick.\n     * @param {?string} participantJid - when it is not a kick for local participant,\n     * this is the jid of the participant which was kicked.\n     */\n    KICKED = 'xmpp.kicked',\n\n    // Designates an event indicating that our role in the XMPP MUC has changed.\n    LOCAL_ROLE_CHANGED = 'xmpp.localrole_changed',\n\n    /**\n     * Event fired when the unique meeting id is set.\n     */\n    MEETING_ID_SET = 'xmpp.meeting_id_set',\n\n    /**\n     * Event fired when a message is moderated.\n     */\n    MESSAGE_MODERATED = 'xmpp.message_moderated',\n\n    // Designates an event indicating that an XMPP message in the MUC was\n    // received.\n    MESSAGE_RECEIVED = 'xmpp.message_received',\n\n    // Designates an event indicating that an XMPP message in the MUC was\n    // retracted.\n    MESSAGE_RETRACTED = 'xmpp.message_retracted',\n\n    // Designates an event indicating that a participant was denied access to a conference from the lobby XMPP MUC.\n    MUC_DENIED_ACCESS = 'xmpp.muc_denied access',\n\n    // Designates an event indicating that the XMPP MUC was destroyed.\n    MUC_DESTROYED = 'xmpp.muc_destroyed',\n\n    // Designates an event indicating that we have joined the XMPP MUC.\n    MUC_JOINED = 'xmpp.muc_joined',\n\n    // Designates an event indicating that we are currently in process of joining the XMPP MUC.\n    MUC_JOIN_IN_PROGRESS = 'xmpp.muc_join_in_progress',\n\n    // Designates an event indicating that local participant left the muc\n    MUC_LEFT = 'xmpp.muc_left',\n\n    // Designates an event indicating that a participant joined the lobby XMPP MUC.\n    MUC_LOBBY_MEMBER_JOINED = 'xmpp.muc_lobby_member_joined',\n\n    // Designates an event indicating that a participant left the XMPP MUC.\n    MUC_LOBBY_MEMBER_LEFT = 'xmpp.muc_lobby_member_left',\n\n    // Designates an event indicating that a participant in the lobby XMPP MUC has been updated\n    MUC_LOBBY_MEMBER_UPDATED = 'xmpp.muc_lobby_member_updated',\n\n    // Designates an event indicating that the MUC has been locked or unlocked.\n    MUC_LOCK_CHANGED = 'xmpp.muc_lock_changed',\n\n    // Designates an event indicating that the MUC members only config has changed.\n    MUC_MEMBERS_ONLY_CHANGED = 'xmpp.muc_members_only_changed',\n\n    // Designates an event indicating that a bot participant type had changed\n    MUC_MEMBER_BOT_TYPE_CHANGED = 'xmpp.muc_member_bot_type_changed',\n\n    // Designates an event indicating that a participant joined the XMPP MUC.\n    MUC_MEMBER_JOINED = 'xmpp.muc_member_joined',\n\n    // Designates an event indicating that a participant left the XMPP MUC.\n    MUC_MEMBER_LEFT = 'xmpp.muc_member_left',\n\n    // Designates an event indicating that the MUC role of a participant has\n    // changed.\n    MUC_ROLE_CHANGED = 'xmpp.muc_role_changed',\n\n    // Designates an event indicating that the MUC visitors support has changed.\n    MUC_VISITORS_SUPPORTED_CHANGED = 'xmpp.muc_visitors_supported_changed',\n\n    // Designates an event indicating that the browser regenerated new SSRCs for an existing source on a P2P\n    // connection. The P2P session should be terminated so the call falls back to JVB.\n    P2P_TERMINATION_REQUIRED = 'xmpp.p2p.termination_required',\n\n    // Designates an event indicating that a participant in the XMPP MUC has\n    // advertised that they have audio muted (or unmuted).\n    PARTICIPANT_AUDIO_MUTED = 'xmpp.audio_muted',\n\n    /**\n     * Indicates that the features of the participant has been changed.\n     */\n    PARTICIPANT_FEATURES_CHANGED = 'xmpp.participant_features_changed',\n\n    // Designates an event indicating that a participant in the XMPP MUC has\n    // advertised that they have video muted (or unmuted).\n    PARTICIPANT_VIDEO_MUTED = 'xmpp.video_muted',\n\n    // Designates an event indicating that the video type (e.g. 'camera' or\n    // 'screen') for a participant has changed.\n    // Note = currently this event fires every time we receive presence from\n    // someone (regardless of whether or not the \"video type\" changed).\n    PARTICIPANT_VIDEO_TYPE_CHANGED = 'xmpp.video_type',\n\n    PASSWORD_REQUIRED = 'xmpp.password_required',\n\n    /**\n     * Event fired when we receive a self-presence with permissions.\n     */\n    PERMISSIONS_RECEIVED = 'xmpp.permissions_received',\n\n    /**\n     * Indicates that phone number changed.\n     */\n    PHONE_NUMBER_CHANGED = 'conference.phoneNumberChanged',\n\n    /**\n     * Event fired when we receive an answer for a poll.\n     */\n    POLLS_ANSWER_EVENT = 'xmpp.polls.answer.event',\n\n    /**\n     * Event fired when we receive a message for polls.\n     */\n    POLLS_EVENT = 'xmpp.polls.event',\n\n    /**\n     * Event fired when we received a poll or polls history event (old-polls).\n     */\n    POLLS_RECEIVE_EVENT = 'xmpp.polls.received.event',\n\n    PRESENCE_RECEIVED = 'xmpp.presence_received',\n    PRESENCE_STATUS = 'xmpp.presence_status',\n\n    // Designates an event indicating that a private XMPP message in the MUC was\n    // received.\n    PRIVATE_MESSAGE_RECEIVED = 'xmpp.private_message_received',\n    PROMPT_FOR_LOGIN = 'xmpp.prompt_for_login',\n\n    // Designates an event indicating that a reaction XMPP message in the MUC\n    // was received.\n    REACTION_RECEIVED = 'xmpp.reaction_received',\n\n    // xmpp is connected and obtained user media\n    READY_TO_JOIN = 'xmpp.ready_to_join',\n\n    /**\n     * Indicates that recording state changed.\n     */\n    RECORDER_STATE_CHANGED = 'xmpp.recorderStateChanged',\n\n    // Designates an event indicating that we received statistics from a\n    // participant in the MUC.\n    REMOTE_STATS = 'xmpp.remote_stats',\n\n    RESERVATION_ERROR = 'xmpp.room_reservation_error',\n\n    ROOM_CONNECT_ERROR = 'xmpp.room_connect_error',\n\n    ROOM_CONNECT_MEMBERS_ONLY_ERROR = 'xmpp.room_connect_error.members_only',\n\n    ROOM_CONNECT_NOT_ALLOWED_ERROR = 'xmpp.room_connect_error.not_allowed',\n\n    ROOM_DISCO_INFO_FAILED = 'xmpp.room_disco_info_failed',\n\n    /**\n     * Indicates that we have received a reply to our disco-info request for the room.\n     */\n    ROOM_DISCO_INFO_UPDATED = 'xmpp.room_disco_info_updated',\n\n    ROOM_JOIN_ERROR = 'xmpp.room_join_error',\n\n    /**\n     * Indicates that max users limit has been reached.\n     */\n    ROOM_MAX_USERS_ERROR = 'xmpp.room_max_users_error',\n\n    /**\n     * Event fired when we receive a message related to room metadata.\n     */\n    ROOM_METADATA_EVENT = 'xmpp.room-metadata.event',\n\n    /**\n     * Event fired when we receive a message related to room metadata.\n     */\n    ROOM_METADATA_UPDATED = 'xmpp.room-metadata.updated',\n\n    // Designates an event indicating that we sent an XMPP message to the MUC.\n    SENDING_CHAT_MESSAGE = 'xmpp.sending_chat_message',\n\n    // Designates an event indicating that we sent a private XMPP message to\n    // a specific user of the muc.\n    SENDING_PRIVATE_CHAT_MESSAGE = 'xmpp.sending_private_chat_message',\n\n    /**\n     * Event fired after receiving the confirmation about session accept.\n     */\n    SESSION_ACCEPT = 'xmpp.session_accept',\n\n    /**\n     * Event fired if we receive an error after sending the session accept.\n     */\n    SESSION_ACCEPT_ERROR = 'xmpp.session_accept_error',\n\n    /**\n     * Event fired when we do not get our 'session-accept' acknowledged by\n     * Jicofo. It most likely means that there is serious problem with our\n     * connection or XMPP server and we should reload the conference.\n     *\n     * We have seen that to happen in BOSH requests race condition when the BOSH\n     * request table containing the 'session-accept' was discarded by Prosody.\n     * Jicofo does send the RESULT immediately without any condition, so missing\n     * packets means that most likely it has never seen our IQ.\n     */\n    SESSION_ACCEPT_TIMEOUT = 'xmpp.session_accept_timeout',\n\n    SETTINGS_ERROR_RECEIVED = 'xmpp.settings_error_received',\n\n    /**\n     * Event fired when participant joins a meeting without audio.\n     */\n    SILENT_STATUS_CHANGED = 'xmpp.silent_status_changed',\n\n    /**\n     * Event fired after successful sending of jingle source-add.\n     */\n    SOURCE_ADD = 'xmpp.source_add',\n\n    /**\n     * Event fired after receiving an error sending of jingle source-add.\n     */\n    SOURCE_ADD_ERROR = 'xmpp.source_add_error',\n\n    /**\n     * Event fired after successful sending of jingle source-remove.\n     */\n    SOURCE_REMOVE = 'xmpp.source_remove',\n\n    /**\n     * Event fired after receiving an error sending of jingle source-remove.\n     */\n    SOURCE_REMOVE_ERROR = 'xmpp.source_remove_error',\n\n    /**\n     * Event fired when speaker stats update message is received.\n     */\n    SPEAKER_STATS_RECEIVED = 'xmpp.speaker_stats_received',\n\n    // Designates an event indicating that the subject of the XMPP MUC has\n    // changed.\n    SUBJECT_CHANGED = 'xmpp.subject_changed',\n\n    // FIXME: how does it belong to XMPP ? - it's detected by the PeerConnection\n    // suspending detected\n    SUSPEND_DETECTED = 'xmpp.suspend_detected',\n\n    /**\n     * Notifies for transcription status changes. The event provides the\n     * following parameters to its listeners:\n     *\n     * @param {String} status - The new status.\n     */\n    TRANSCRIPTION_STATUS_CHANGED = 'xmpp.transcription_status_changed',\n\n    /**\n     * Event fired when 'transport-info' with new ICE candidates is received.\n     */\n    TRANSPORT_INFO = 'xmpp.transportinfo.jingle',\n\n    // Designates an event indicating that the focus has asked us to disable our\n    // camera.\n    VIDEO_MUTED_BY_FOCUS = 'xmpp.video_muted_by_focus',\n\n    /**\n     * Indicates that video SIP GW state changed.\n     *\n     * @param {VideoSIPGWStatusConstants} status - Any of the following statuses:\n     * STATUS_BUSY, STATUS_AVAILABLE or STATUS_UNDEFINED.\n     */\n    VIDEO_SIP_GW_AVAILABILITY_CHANGED = 'xmpp.videoSIPGWAvailabilityChanged',\n\n    /**\n     * Indicates that video SIP GW Session state changed.\n     * The statuses are any of the following statuses:\n     * STATE_ON, STATE_OFF, STATE_PENDING, STATE_RETRYING, STATE_FAILED.\n     * {@see VideoSIPGWStateConstants}\n     *\n     * @param {options} event - {address, oldState, newState, displayName}.\n     */\n    VIDEO_SIP_GW_SESSION_STATE_CHANGED = 'xmpp.videoSIPGWSessionStateChanged',\n\n    /**\n     * Event indicating we have received a message from the visitors component.\n     */\n    VISITORS_MESSAGE = 'xmpp.visitors_message',\n\n    /**\n     * Event indicating that our request for promotion was rejected.\n     */\n    VISITORS_REJECTION = 'xmpp.visitors_rejection',\n\n}\n","import { getLogger } from '@jitsi/logger';\nimport { Strophe } from 'strophe.js';\n\nimport JitsiConference from './JitsiConference';\nimport * as JitsiConferenceErrors from './JitsiConferenceErrors';\nimport { JitsiConferenceEvents } from './JitsiConferenceEvents';\nimport { JitsiTrackEvents } from './JitsiTrackEvents';\nimport JitsiRemoteTrack from './modules/RTC/JitsiRemoteTrack';\nimport TraceablePeerConnection from './modules/RTC/TraceablePeerConnection';\nimport RTCStats from './modules/RTCStats/RTCStats';\nimport { RTCStatsEvents } from './modules/RTCStats/RTCStatsEvents';\nimport { IInboundVideoStats } from './modules/qualitycontrol/QualityController';\nimport JibriSession from './modules/recording/JibriSession';\nimport { SPEAKERS_AUDIO_LEVELS } from './modules/statistics/constants';\nimport Statistics from './modules/statistics/statistics';\nimport EventEmitterForwarder from './modules/util/EventEmitterForwarder';\nimport JingleSessionPC from './modules/xmpp/JingleSessionPC';\nimport { MediaType } from './service/RTC/MediaType';\nimport { RTCEvents } from './service/RTC/RTCEvents';\nimport { VideoType } from './service/RTC/VideoType';\nimport { AuthenticationEvents } from './service/authentication/AuthenticationEvents';\nimport {\n    AnalyticsEvents,\n    createBridgeDownEvent,\n    createConnectionStageReachedEvent,\n    createFocusLeftEvent,\n    createJingleEvent,\n    createRemotelyMutedEvent\n} from './service/statistics/AnalyticsEvents';\nimport { XMPPEvents } from './service/xmpp/XMPPEvents';\n\nconst logger = getLogger('core:JitsiConferenceEventManager');\n\n/**\n * Setups all event listeners related to conference\n */\nexport default class JitsiConferenceEventManager {\n    private conference: JitsiConference;\n    private xmppListeners: { [key: string]: (...args: any[]) => void; }; // Todo\n    private chatRoomForwarder?: EventEmitterForwarder;\n\n    /**\n     * Setups all event listeners related to conference\n     * @param conference {JitsiConference} the conference\n     */\n    constructor(conference: JitsiConference) {\n        this.conference = conference;\n        this.xmppListeners = {};\n    }\n\n    /**\n     * Add XMPP listener and save its reference for remove on leave conference.\n     * @param {string} eventName - The event name.\n     * @param {Function} listener - The listener function.\n     * @private\n     */\n    private _addConferenceXMPPListener(eventName: string, listener: (...args: any[]) => void): void { // Todo\n        this.xmppListeners[eventName] = listener;\n        this.conference.xmpp.addListener(eventName, listener);\n    }\n\n    /**\n     * Setups event listeners related to conference.chatRoom\n     */\n    setupChatRoomListeners(): void {\n        const conference = this.conference;\n        const chatRoom = conference.room;\n\n        this.chatRoomForwarder = new EventEmitterForwarder(chatRoom,\n            this.conference.eventEmitter);\n\n        chatRoom.addListener(XMPPEvents.PARTICIPANT_FEATURES_CHANGED, (from: string, features: Set<string>) => {\n            const participant = conference.getParticipantById(Strophe.getResourceFromJid(from));\n\n            if (participant) {\n                participant.setFeatures(features);\n                conference.eventEmitter.emit(JitsiConferenceEvents.PARTCIPANT_FEATURES_CHANGED, participant);\n            }\n        });\n\n        this.chatRoomForwarder.forward(XMPPEvents.PERMISSIONS_RECEIVED, JitsiConferenceEvents.PERMISSIONS_RECEIVED);\n\n        chatRoom.addListener(XMPPEvents.AUDIO_MUTED_BY_FOCUS,\n            (actor: string) => {\n                // TODO: Add a way to differentiate between commands which caused\n                // us to mute and those that did not change our state (i.e. we were\n                // already muted).\n                Statistics.sendAnalytics(createRemotelyMutedEvent(MediaType.AUDIO));\n\n                conference.mutedByFocusActor = actor;\n\n                // set isMutedByFocus when setAudioMute Promise ends\n                conference.rtc.setAudioMute().then(\n                    () => {\n                        conference.isMutedByFocus = true;\n                        conference.mutedByFocusActor = null;\n                    })\n                    .catch(\n                        (error: Error) => {\n                            conference.mutedByFocusActor = null;\n                            logger.warn(\n                                'Error while audio muting due to focus request', error);\n                        });\n            }\n        );\n\n        chatRoom.addListener(XMPPEvents.VIDEO_MUTED_BY_FOCUS,\n            (actor: string) => {\n                // TODO: Add a way to differentiate between commands which caused\n                // us to mute and those that did not change our state (i.e. we were\n                // already muted).\n                Statistics.sendAnalytics(createRemotelyMutedEvent(MediaType.VIDEO));\n\n                conference.mutedVideoByFocusActor = actor;\n\n                // set isVideoMutedByFocus when setVideoMute Promise ends\n                conference.rtc.setVideoMute().then(\n                    () => {\n                        conference.isVideoMutedByFocus = true;\n                        conference.mutedVideoByFocusActor = null;\n                    })\n                    .catch(\n                        (error: Error) => {\n                            conference.mutedVideoByFocusActor = null;\n                            logger.warn(\n                                'Error while video muting due to focus request', error);\n                        });\n            }\n        );\n\n        chatRoom.addListener(XMPPEvents.DESKTOP_MUTED_BY_FOCUS,\n            (actor: string) => {\n                // TODO: Add a way to differentiate between commands which caused\n                // us to mute and those that did not change our state (i.e. we were\n                // already muted).\n                Statistics.sendAnalytics(createRemotelyMutedEvent(MediaType.DESKTOP));\n\n                conference.mutedDesktopByFocusActor = actor;\n\n                // set isDesktopMutedByFocus when setDesktopMute Promise ends\n                conference.rtc.setDesktopMute().then(\n                    () => {\n                        conference.isDesktopMutedByFocus = true;\n                        conference.mutedDesktopByFocusActor = null;\n                    })\n                    .catch(\n                        (error: Error) => {\n                            conference.mutedDesktopByFocusActor = null;\n                            logger.warn(\n                                'Error while desktop video muting due to focus request', error);\n                        });\n            }\n        );\n\n        this.chatRoomForwarder.forward(XMPPEvents.SUBJECT_CHANGED,\n            JitsiConferenceEvents.SUBJECT_CHANGED);\n\n        this.chatRoomForwarder.forward(XMPPEvents.MUC_JOINED,\n            JitsiConferenceEvents.CONFERENCE_JOINED);\n\n        this.chatRoomForwarder.forward(XMPPEvents.MUC_JOIN_IN_PROGRESS,\n            JitsiConferenceEvents.CONFERENCE_JOIN_IN_PROGRESS);\n\n        this.chatRoomForwarder.forward(XMPPEvents.MEETING_ID_SET,\n            JitsiConferenceEvents.CONFERENCE_UNIQUE_ID_SET);\n\n        this.chatRoomForwarder.forward(XMPPEvents.CONFERENCE_TIMESTAMP_RECEIVED,\n            JitsiConferenceEvents.CONFERENCE_CREATED_TIMESTAMP);\n\n        // send some analytics events\n        chatRoom.addListener(XMPPEvents.MUC_JOINED,\n            () => {\n                this.conference._onMucJoined();\n\n                this.conference.isJvbConnectionInterrupted = false;\n\n                // TODO: Move all of the 'connectionTimes' logic to its own module.\n                Object.keys(chatRoom.connectionTimes).forEach(key => {\n                    const event\n                        = createConnectionStageReachedEvent(\n                            `conference_${key}`,\n                            { value: chatRoom.connectionTimes[key] });\n\n                    Statistics.sendAnalytics(event);\n                });\n\n                // TODO: Move all of the 'connectionTimes' logic to its own module.\n                Object.keys(chatRoom.xmpp.connectionTimes).forEach(key => {\n                    const event\n                        = createConnectionStageReachedEvent(\n                            `xmpp_${key}`,\n                            { value: chatRoom.xmpp.connectionTimes[key] });\n\n                    Statistics.sendAnalytics(event);\n                });\n            });\n\n        chatRoom.addListener(JitsiTrackEvents.TRACK_OWNER_SET, (track: JitsiRemoteTrack, owner: string, sourceName: string, videoType: VideoType) => {\n            if (track.getParticipantId() !== owner || track.getSourceName() !== sourceName) {\n                conference.eventEmitter.emit(JitsiConferenceEvents.TRACK_REMOVED, track);\n\n                // Update the owner and other properties on the track.\n                track.setOwner(owner);\n                track.setSourceName(sourceName);\n                track._setVideoType(videoType);\n                if (owner) {\n                    conference.eventEmitter.emit(JitsiConferenceEvents.TRACK_ADDED, track);\n                } else {\n                    console.warn('Decoder: disposing of an orphand track (chat room)');\n                    track.cleanDecoder();\n                }\n            }\n        });\n\n        this.chatRoomForwarder.forward(XMPPEvents.ROOM_JOIN_ERROR,\n            JitsiConferenceEvents.CONFERENCE_FAILED,\n            JitsiConferenceErrors.CONNECTION_ERROR);\n\n        this.chatRoomForwarder.forward(XMPPEvents.DISPLAY_NAME_REQUIRED,\n            JitsiConferenceEvents.CONFERENCE_FAILED,\n            JitsiConferenceErrors.DISPLAY_NAME_REQUIRED);\n\n        this.chatRoomForwarder.forward(XMPPEvents.ROOM_CONNECT_ERROR,\n            JitsiConferenceEvents.CONFERENCE_FAILED,\n            JitsiConferenceErrors.CONNECTION_ERROR);\n        this.chatRoomForwarder.forward(XMPPEvents.ROOM_CONNECT_NOT_ALLOWED_ERROR,\n            JitsiConferenceEvents.CONFERENCE_FAILED,\n            JitsiConferenceErrors.NOT_ALLOWED_ERROR);\n        this.chatRoomForwarder.forward(XMPPEvents.ROOM_CONNECT_MEMBERS_ONLY_ERROR,\n            JitsiConferenceEvents.CONFERENCE_FAILED,\n            JitsiConferenceErrors.MEMBERS_ONLY_ERROR);\n\n        this.chatRoomForwarder.forward(XMPPEvents.ROOM_MAX_USERS_ERROR,\n            JitsiConferenceEvents.CONFERENCE_FAILED,\n            JitsiConferenceErrors.CONFERENCE_MAX_USERS);\n\n        this.chatRoomForwarder.forward(XMPPEvents.PASSWORD_REQUIRED,\n            JitsiConferenceEvents.CONFERENCE_FAILED,\n            JitsiConferenceErrors.PASSWORD_REQUIRED);\n\n        this.chatRoomForwarder.forward(XMPPEvents.AUTHENTICATION_REQUIRED,\n            JitsiConferenceEvents.CONFERENCE_FAILED,\n            JitsiConferenceErrors.AUTHENTICATION_REQUIRED);\n\n        this.chatRoomForwarder.forward(XMPPEvents.BRIDGE_DOWN,\n            JitsiConferenceEvents.CONFERENCE_FAILED,\n            JitsiConferenceErrors.VIDEOBRIDGE_NOT_AVAILABLE);\n        chatRoom.addListener(\n            XMPPEvents.BRIDGE_DOWN,\n            () => Statistics.sendAnalytics(createBridgeDownEvent()));\n\n        this.chatRoomForwarder.forward(XMPPEvents.RESERVATION_ERROR,\n            JitsiConferenceEvents.CONFERENCE_FAILED,\n            JitsiConferenceErrors.RESERVATION_ERROR);\n\n        this.chatRoomForwarder.forward(XMPPEvents.GRACEFUL_SHUTDOWN,\n            JitsiConferenceEvents.CONFERENCE_FAILED,\n            JitsiConferenceErrors.GRACEFUL_SHUTDOWN);\n\n        this.chatRoomForwarder.forward(XMPPEvents.MUC_DESTROYED,\n            JitsiConferenceEvents.CONFERENCE_FAILED,\n            JitsiConferenceErrors.CONFERENCE_DESTROYED);\n\n        this.chatRoomForwarder.forward(XMPPEvents.CHAT_ERROR_RECEIVED,\n            JitsiConferenceEvents.CONFERENCE_ERROR,\n            JitsiConferenceErrors.CHAT_ERROR);\n\n        this.chatRoomForwarder.forward(XMPPEvents.SETTINGS_ERROR_RECEIVED,\n            JitsiConferenceEvents.CONFERENCE_ERROR,\n            JitsiConferenceErrors.SETTINGS_ERROR);\n\n        this.chatRoomForwarder.forward(XMPPEvents.FOCUS_DISCONNECTED,\n            JitsiConferenceEvents.CONFERENCE_FAILED,\n            JitsiConferenceErrors.FOCUS_DISCONNECTED);\n\n        chatRoom.addListener(XMPPEvents.FOCUS_LEFT,\n            () => {\n                Statistics.sendAnalytics(createFocusLeftEvent());\n                conference.eventEmitter.emit(\n                    JitsiConferenceEvents.CONFERENCE_FAILED,\n                    JitsiConferenceErrors.FOCUS_LEFT);\n            });\n\n        chatRoom.addListener(XMPPEvents.SESSION_ACCEPT_TIMEOUT,\n            (jingleSession: JingleSessionPC) => {\n                Statistics.sendAnalyticsAndLog(\n                    createJingleEvent(\n                        AnalyticsEvents.ACTION_JINGLE_SA_TIMEOUT,\n                        { p2p: jingleSession.isP2P }));\n            });\n\n        chatRoom.addListener(XMPPEvents.RECORDER_STATE_CHANGED,\n            (session: JibriSession, jid: string) => {\n\n                if (jid) {\n                    const resource = Strophe.getResourceFromJid(jid);\n                    const participant = conference.getParticipantById(resource) || resource;\n\n                    if (session.getStatus() === 'off') {\n                        session.setTerminator(participant);\n                    } else if (session.getStatus() === 'on') {\n                        session.setInitiator(participant);\n                    }\n                }\n\n                conference.eventEmitter.emit(\n                    JitsiConferenceEvents.RECORDER_STATE_CHANGED,\n                    session);\n            });\n\n        this.chatRoomForwarder.forward(XMPPEvents.TRANSCRIPTION_STATUS_CHANGED,\n            JitsiConferenceEvents.TRANSCRIPTION_STATUS_CHANGED);\n\n        this.chatRoomForwarder.forward(XMPPEvents.VIDEO_SIP_GW_AVAILABILITY_CHANGED,\n            JitsiConferenceEvents.VIDEO_SIP_GW_AVAILABILITY_CHANGED);\n\n        this.chatRoomForwarder.forward(\n            XMPPEvents.VIDEO_SIP_GW_SESSION_STATE_CHANGED,\n            JitsiConferenceEvents.VIDEO_SIP_GW_SESSION_STATE_CHANGED);\n\n        this.chatRoomForwarder.forward(XMPPEvents.PHONE_NUMBER_CHANGED,\n            JitsiConferenceEvents.PHONE_NUMBER_CHANGED);\n\n        chatRoom.setParticipantPropertyListener((id: string, prop: string, value: string) => {\n            const participant = conference.getParticipantById(id);\n\n            if (!participant) {\n                return;\n            }\n\n            participant.setProperty(prop, value);\n        });\n\n        chatRoom.addListener(XMPPEvents.KICKED,\n            conference.onMemberKicked.bind(conference));\n        chatRoom.addListener(XMPPEvents.SUSPEND_DETECTED,\n            conference.onSuspendDetected.bind(conference));\n\n        this.chatRoomForwarder.forward(XMPPEvents.MUC_LOCK_CHANGED,\n            JitsiConferenceEvents.LOCK_STATE_CHANGED);\n\n        this.chatRoomForwarder.forward(XMPPEvents.MUC_MEMBERS_ONLY_CHANGED,\n            JitsiConferenceEvents.MEMBERS_ONLY_CHANGED);\n        this.chatRoomForwarder.forward(XMPPEvents.MUC_VISITORS_SUPPORTED_CHANGED,\n            JitsiConferenceEvents.VISITORS_SUPPORTED_CHANGED);\n\n        chatRoom.addListener(XMPPEvents.MUC_MEMBER_JOINED,\n            conference.onMemberJoined.bind(conference));\n        this.chatRoomForwarder.forward(XMPPEvents.MUC_LOBBY_MEMBER_JOINED,\n            JitsiConferenceEvents.LOBBY_USER_JOINED);\n        this.chatRoomForwarder.forward(XMPPEvents.MUC_LOBBY_MEMBER_UPDATED,\n            JitsiConferenceEvents.LOBBY_USER_UPDATED);\n        this.chatRoomForwarder.forward(XMPPEvents.MUC_LOBBY_MEMBER_LEFT,\n            JitsiConferenceEvents.LOBBY_USER_LEFT);\n        chatRoom.addListener(XMPPEvents.MUC_MEMBER_BOT_TYPE_CHANGED,\n            conference._onMemberBotTypeChanged.bind(conference));\n        chatRoom.addListener(XMPPEvents.MUC_MEMBER_LEFT,\n            conference.onMemberLeft.bind(conference));\n        this.chatRoomForwarder.forward(XMPPEvents.MUC_LEFT,\n            JitsiConferenceEvents.CONFERENCE_LEFT);\n        this.chatRoomForwarder.forward(XMPPEvents.MUC_DENIED_ACCESS,\n            JitsiConferenceEvents.CONFERENCE_FAILED,\n            JitsiConferenceErrors.CONFERENCE_ACCESS_DENIED);\n\n        chatRoom.addListener(XMPPEvents.DISPLAY_NAME_CHANGED,\n            conference.onDisplayNameChanged.bind(conference));\n\n        chatRoom.addListener(XMPPEvents.SILENT_STATUS_CHANGED,\n            conference.onSilentStatusChanged.bind(conference));\n\n        chatRoom.addListener(XMPPEvents.LOCAL_ROLE_CHANGED, (role: string) => {\n            conference.onLocalRoleChanged(role);\n        });\n\n        chatRoom.addListener(XMPPEvents.MUC_ROLE_CHANGED,\n            conference.onUserRoleChanged.bind(conference));\n\n        chatRoom.addListener(AuthenticationEvents.IDENTITY_UPDATED,\n            (authEnabled: boolean, authIdentity: any) => {\n                conference.authEnabled = authEnabled;\n                conference.authIdentity = authIdentity;\n                conference.eventEmitter.emit(\n                    JitsiConferenceEvents.AUTH_STATUS_CHANGED, authEnabled,\n                    authIdentity);\n            });\n\n        chatRoom.addListener(\n            XMPPEvents.MESSAGE_RECEIVED,\n\n            // eslint-disable-next-line max-params\n            (jid: string, txt: string, myJid: string, ts: number,\n                    displayName: string, isVisitor: boolean, messageId: string, source: string, replyToId?: string) => {\n                const participantId = Strophe.getResourceFromJid(jid);\n\n                conference.eventEmitter.emit(\n                    JitsiConferenceEvents.MESSAGE_RECEIVED,\n                    participantId, txt, ts, displayName, isVisitor, messageId, source, replyToId);\n            });\n\n        this.chatRoomForwarder.forward(XMPPEvents.POLLS_RECEIVE_EVENT,\n            JitsiConferenceEvents.POLL_RECEIVED);\n        this.chatRoomForwarder.forward(XMPPEvents.POLLS_ANSWER_EVENT,\n            JitsiConferenceEvents.POLL_ANSWER_RECEIVED);\n\n        chatRoom.addListener(\n            XMPPEvents.REACTION_RECEIVED,\n\n            (jid: string, reactionList: string[], messageId: string) => {\n                const participantId = Strophe.getResourceFromJid(jid);\n\n                conference.eventEmitter.emit(\n                    JitsiConferenceEvents.REACTION_RECEIVED,\n                    participantId, reactionList, messageId);\n            });\n\n        chatRoom.addListener(\n            XMPPEvents.PRIVATE_MESSAGE_RECEIVED,\n\n            // eslint-disable-next-line max-params\n            (jid: string, txt: string, myJid: string, ts: number, messageId: string,\n                    displayName: string, isVisitor: boolean, ofrom: string, replyToId?: string) => {\n                const participantId = isVisitor ? ofrom : Strophe.getResourceFromJid(jid);\n\n                conference.eventEmitter.emit(\n                    JitsiConferenceEvents.PRIVATE_MESSAGE_RECEIVED,\n                    participantId, txt, ts, messageId, displayName, isVisitor, replyToId);\n            });\n\n        chatRoom?.addListener(XMPPEvents.MESSAGE_MODERATED,\n            (messageId: string, moderatorJid?: string, reason?: string) => {\n                const moderatorId = moderatorJid ? Strophe.getResourceFromJid(moderatorJid) : undefined;\n\n                conference.eventEmitter.emit(\n                    JitsiConferenceEvents.MESSAGE_MODERATED,\n                    messageId,\n                    moderatorId,\n                    reason\n                );\n            });\n\n        chatRoom.addListener(\n            XMPPEvents.MESSAGE_RETRACTED,\n\n            (jid: string, messageId: string) => {\n                const participantId = Strophe.getResourceFromJid(jid);\n\n                conference.eventEmitter.emit(\n                    JitsiConferenceEvents.MESSAGE_RETRACTED,\n                    participantId,\n                    messageId\n                );\n            });\n\n        chatRoom.addListener(XMPPEvents.PRESENCE_STATUS,\n            (jid: string, status: string) => {\n                const id = Strophe.getResourceFromJid(jid);\n                const participant = conference.getParticipantById(id);\n\n                if (!participant || participant._status === status) {\n                    return;\n                }\n                participant._status = status;\n                conference.eventEmitter.emit(\n                    JitsiConferenceEvents.USER_STATUS_CHANGED, id, status);\n            });\n\n        chatRoom.addListener(XMPPEvents.JSON_MESSAGE_RECEIVED,\n            (from: string, payload: any) => {\n                const id = Strophe.getResourceFromJid(from);\n                const participant = conference.getParticipantById(id);\n\n                if (participant) {\n                    conference.eventEmitter.emit(\n                        JitsiConferenceEvents.ENDPOINT_MESSAGE_RECEIVED,\n                        participant, payload);\n                } else {\n                    conference.eventEmitter.emit(\n                        JitsiConferenceEvents.NON_PARTICIPANT_MESSAGE_RECEIVED,\n                        id, payload);\n                }\n            });\n\n        // Breakout rooms.\n        this.chatRoomForwarder.forward(XMPPEvents.BREAKOUT_ROOMS_MOVE_TO_ROOM,\n            JitsiConferenceEvents.BREAKOUT_ROOMS_MOVE_TO_ROOM);\n        this.chatRoomForwarder.forward(XMPPEvents.BREAKOUT_ROOMS_UPDATED,\n            JitsiConferenceEvents.BREAKOUT_ROOMS_UPDATED);\n\n        // File sharing\n        this.chatRoomForwarder.forward(XMPPEvents.FILE_SHARING_FILES_RECEIVED,\n            JitsiConferenceEvents.FILE_SHARING_FILES_RECEIVED);\n        this.chatRoomForwarder.forward(XMPPEvents.FILE_SHARING_FILE_ADDED,\n            JitsiConferenceEvents.FILE_SHARING_FILE_ADDED);\n        this.chatRoomForwarder.forward(XMPPEvents.FILE_SHARING_FILE_REMOVED,\n            JitsiConferenceEvents.FILE_SHARING_FILE_REMOVED);\n\n        // Room metadata.\n        chatRoom.addListener(XMPPEvents.ROOM_METADATA_UPDATED, (metadata: any) => {\n            if (metadata.startMuted) {\n                const audio = metadata.startMuted.audio || false;\n                const video = metadata.startMuted.video || false;\n\n                audio && (conference.isMutedByFocus = true);\n                video && (conference.isVideoMutedByFocus = true);\n                conference._updateStartMutedPolicy(audio, video);\n            }\n            if (typeof metadata.recording?.isTranscribingEnabled !== 'undefined') {\n                conference._setTranscribingEnabled(Boolean(metadata.recording.isTranscribingEnabled));\n            }\n\n            if (metadata.services) {\n                chatRoom.xmpp.connection.jingle.onReceiveStunAndTurnCredentials(metadata);\n            }\n\n            conference.eventEmitter.emit(JitsiConferenceEvents.METADATA_UPDATED, metadata);\n        });\n    }\n\n    /**\n     * Setups event listeners related to conference.rtc\n     */\n    setupRTCListeners(): void {\n        const conference = this.conference;\n        const rtc = conference.rtc;\n\n        rtc.addListener(\n            RTCEvents.REMOTE_TRACK_ADDED,\n            conference.onRemoteTrackAdded.bind(conference));\n\n        rtc.addListener(\n            RTCEvents.REMOTE_TRACK_REMOVED,\n            conference.onRemoteTrackRemoved.bind(conference));\n\n        rtc.addListener(RTCEvents.DOMINANT_SPEAKER_CHANGED,\n            (dominant: string, previous: string[], silence: boolean) => {\n                if ((conference.lastDominantSpeaker !== dominant || conference.dominantSpeakerIsSilent !== silence)\n                        && conference.room) {\n                    conference.dominantSpeakerIsSilent = silence;\n                    conference.eventEmitter.emit(\n                        JitsiConferenceEvents.DOMINANT_SPEAKER_CHANGED, dominant, previous, silence);\n                    if (conference.statistics && conference.myUserId() === dominant) {\n                        // We are the new dominant speaker.\n                        conference.xmpp.sendDominantSpeakerEvent(conference.room.roomjid, silence);\n                        RTCStats.sendStatsEntry(RTCStatsEvents.DOMINANT_SPEAKER_CHANGED_EVENT);\n                    }\n                    if (conference.lastDominantSpeaker !== dominant) {\n                        conference.lastDominantSpeaker = dominant;\n\n                        if (previous?.length) {\n                            const speakerList = previous.slice(0);\n\n                            // Add the dominant speaker to the top of the list (exclude self).\n                            if (conference.myUserId() !== dominant) {\n                                speakerList.splice(0, 0, dominant);\n                            }\n\n                            // Trim the list to the top 5 speakers only.\n                            if (speakerList.length > SPEAKERS_AUDIO_LEVELS) {\n                                speakerList.splice(SPEAKERS_AUDIO_LEVELS, speakerList.length - SPEAKERS_AUDIO_LEVELS);\n                            }\n                            conference.statistics?.setSpeakerList(speakerList);\n                        }\n                    }\n                }\n            });\n\n        rtc.addListener(RTCEvents.DATA_CHANNEL_OPEN, () => {\n            const now = window.performance.now();\n            const key = 'data.channel.opened';\n\n            // TODO: Move all of the 'connectionTimes' logic to its own module.\n            logger.info(`(TIME) ${key}:\\t`, now);\n            conference.room.connectionTimes[key] = now;\n            Statistics.sendAnalytics(\n                createConnectionStageReachedEvent(key, { value: now }));\n\n            conference.eventEmitter.emit(JitsiConferenceEvents.DATA_CHANNEL_OPENED);\n        });\n\n        rtc.addListener(RTCEvents.DATA_CHANNEL_CLOSED, (ev: RTCDataChannelEvent) => {\n            conference.eventEmitter.emit(JitsiConferenceEvents.DATA_CHANNEL_CLOSED, ev);\n        });\n\n        rtc.addListener(RTCEvents.VIDEO_SSRCS_REMAPPED, (msg: any) => {\n            this.conference.jvbJingleSession.processSourceMap(msg, MediaType.VIDEO);\n        });\n\n        rtc.addListener(RTCEvents.AUDIO_SSRCS_REMAPPED, (msg: any) => {\n            this.conference.jvbJingleSession.processSourceMap(msg, MediaType.AUDIO);\n        });\n\n        rtc.addListener(RTCEvents.BRIDGE_BWE_STATS_RECEIVED, (bwe: any) => {\n            conference.eventEmitter.emit(JitsiConferenceEvents.BRIDGE_BWE_STATS_RECEIVED, bwe);\n        });\n\n        rtc.addListener(RTCEvents.TRANSLATED_SOURCE_SENDING_CHANGED, (change: any) => {\n            conference.eventEmitter.emit(JitsiConferenceEvents.TRANSLATED_SOURCE_SENDING_CHANGED, change);\n        });\n\n        rtc.addListener(RTCEvents.ENDPOINT_MESSAGE_RECEIVED,\n            (from: string, payload: any) => {\n                if (from === 'transcriber') {\n                    conference.eventEmitter.emit(\n                        JitsiConferenceEvents.NON_PARTICIPANT_MESSAGE_RECEIVED,\n                        from, payload);\n\n                    return;\n                }\n\n                const participant = conference.getParticipantById(from);\n\n                if (participant) {\n                    conference.eventEmitter.emit(\n                        JitsiConferenceEvents.ENDPOINT_MESSAGE_RECEIVED,\n                        participant, payload);\n                } else {\n                    logger.warn(\n                        'Ignored ENDPOINT_MESSAGE_RECEIVED for not existing '\n                            + `participant: ${from}`,\n                        payload);\n                }\n            });\n\n        rtc.addListener(RTCEvents.ENDPOINT_STATS_RECEIVED,\n            (from: string, payload: any) => {\n                const participant = conference.getParticipantById(from);\n\n                if (participant) {\n                    conference.eventEmitter.emit(JitsiConferenceEvents.ENDPOINT_STATS_RECEIVED, participant, payload);\n                } else {\n                    logger.warn(`Ignoring ENDPOINT_STATS_RECEIVED for a non-existant participant: ${from}`);\n                }\n            });\n    }\n\n    /**\n     * Setups event listeners related to conference.statistics\n     */\n    setupStatisticsListeners(): void {\n        const conference = this.conference;\n\n        if (!conference.statistics) {\n            return;\n        }\n\n        /* eslint-disable max-params */\n        conference.statistics.addAudioLevelListener((tpc: TraceablePeerConnection, ssrc: number, level: number, isLocal: boolean) => {\n            conference.rtc.setAudioLevel(tpc, ssrc, level, isLocal);\n        });\n\n        /* eslint-enable max-params */\n\n        // Forward the \"before stats disposed\" event\n        conference.statistics.addBeforeDisposedListener(() => {\n            conference.eventEmitter.emit(\n                JitsiConferenceEvents.BEFORE_STATISTICS_DISPOSED);\n        });\n\n        conference.statistics.addEncodeTimeStatsListener((tpc: TraceablePeerConnection, stats: RTCEncodedAudioFrameMetadata) => {\n            conference.eventEmitter.emit(\n                JitsiConferenceEvents.ENCODE_TIME_STATS_RECEIVED, tpc, stats);\n        });\n\n        conference.statistics.addInboundVideoStatsListener((tpc: TraceablePeerConnection, stats: Map<number, IInboundVideoStats>) => {\n            conference.eventEmitter.emit(\n                JitsiConferenceEvents.INBOUND_VIDEO_STATS_RECEIVED, tpc, stats);\n        });\n\n        // if we are in startSilent mode we will not be sending/receiving so nothing to detect\n        if (!conference.options.config.startSilent) {\n            conference.statistics.addByteSentStatsListener((tpc: TraceablePeerConnection, stats: RTCEncodedAudioFrameMetadata) => {\n                conference.getLocalTracks(MediaType.AUDIO).forEach(track => {\n                    const ssrc = tpc.getLocalSSRC(track);\n\n                    if (!ssrc || !stats.hasOwnProperty(ssrc)) {\n                        return;\n                    }\n\n                    track.onByteSentStatsReceived(tpc, stats[ssrc]);\n                });\n            });\n        }\n    }\n\n    /**\n     * Setups event listeners related to conference.xmpp\n     */\n    setupXMPPListeners(): void {\n        const conference = this.conference;\n\n        this._addConferenceXMPPListener(\n            XMPPEvents.CALL_INCOMING,\n            conference.onIncomingCall.bind(conference));\n        this._addConferenceXMPPListener(\n            XMPPEvents.CALL_ACCEPTED,\n            conference.onCallAccepted.bind(conference));\n        this._addConferenceXMPPListener(\n            XMPPEvents.TRANSPORT_INFO,\n            conference.onTransportInfo.bind(conference));\n        this._addConferenceXMPPListener(\n            XMPPEvents.CALL_ENDED,\n            conference.onCallEnded.bind(conference));\n\n        this._addConferenceXMPPListener(XMPPEvents.AV_MODERATION_CHANGED,\n            (value: boolean, mediaType: MediaType, actorJid: string) => {\n                const actorParticipant = conference.getParticipants().find(p => p.getJid() === actorJid);\n\n                conference.eventEmitter.emit(JitsiConferenceEvents.AV_MODERATION_CHANGED, {\n                    actor: actorParticipant,\n                    enabled: value,\n                    mediaType\n                });\n            });\n        this._addConferenceXMPPListener(XMPPEvents.AV_MODERATION_PARTICIPANT_APPROVED,\n            (mediaType: MediaType, jid: string) => {\n                const participant = conference.getParticipantById(Strophe.getResourceFromJid(jid));\n\n                if (participant) {\n                    conference.eventEmitter.emit(JitsiConferenceEvents.AV_MODERATION_PARTICIPANT_APPROVED, {\n                        mediaType,\n                        participant\n                    });\n                }\n            });\n        this._addConferenceXMPPListener(XMPPEvents.AV_MODERATION_PARTICIPANT_REJECTED,\n            (mediaType: MediaType, jid: string) => {\n                const participant = conference.getParticipantById(Strophe.getResourceFromJid(jid));\n\n                if (participant) {\n                    conference.eventEmitter.emit(JitsiConferenceEvents.AV_MODERATION_PARTICIPANT_REJECTED, {\n                        mediaType,\n                        participant\n                    });\n                }\n            });\n        this._addConferenceXMPPListener(XMPPEvents.AV_MODERATION_APPROVED,\n            (value: MediaType) => conference.eventEmitter.emit(JitsiConferenceEvents.AV_MODERATION_APPROVED, { mediaType: value }));\n        this._addConferenceXMPPListener(XMPPEvents.AV_MODERATION_REJECTED,\n            (value: MediaType) => {\n                conference.eventEmitter.emit(JitsiConferenceEvents.AV_MODERATION_REJECTED, { mediaType: value });\n            });\n\n        this._addConferenceXMPPListener(XMPPEvents.VISITORS_MESSAGE,\n            (value: string) => conference.eventEmitter.emit(JitsiConferenceEvents.VISITORS_MESSAGE, value));\n        this._addConferenceXMPPListener(XMPPEvents.VISITORS_REJECTION,\n            () => conference.eventEmitter.emit(JitsiConferenceEvents.VISITORS_REJECTION));\n    }\n\n\n    /**\n     * Removes event listeners related to conference.xmpp\n     */\n    removeXMPPListeners(): void {\n        const conference = this.conference;\n\n        Object.keys(this.xmppListeners).forEach(eventName => {\n            conference.xmpp.removeListener(\n                eventName,\n                this.xmppListeners[eventName]);\n        });\n        this.xmppListeners = {};\n    }\n}\n","/**\n * The number of remote speakers for which the audio levels will be calculated using\n * RTCRtpReceiver#getSynchronizationSources. Limit the number of endpoints to save cpu on the client as this API call\n * is known to take longer to execute when there are many audio receivers.\n */\nexport const SPEAKERS_AUDIO_LEVELS: number = 5;\n","/**\n * The events for the connection.\n */\n\nexport enum JitsiConnectionEvents {\n\n    /**\n     * Indicates that the connection has been disconnected. The event provides\n     * the following parameters to its listeners:\n     *\n     * @param msg {string} a message associated with the disconnect such as the\n     * last (known) error message\n     */\n    CONNECTION_DISCONNECTED = 'connection.connectionDisconnected',\n\n    /**\n     * Indicates that the connection has been established. The event provides\n     * the following parameters to its listeners:\n     *\n     * @param id {string} the ID of the local endpoint/participant/peer (within\n     * the context of the established connection)\n     */\n    CONNECTION_ESTABLISHED = 'connection.connectionEstablished',\n\n    /**\n     * Indicates that the connection has been failed for some reason. The event\n     * provides the following parameters to its listeners:\n     *\n     * @param errType {JitsiConnectionErrors} the type of error associated with\n     * the failure\n     * @param errReason {string} the error (message) associated with the failure\n     * @param credentials {object} the credentials used to connect (if any)\n     * @param errReasonDetails {object} an optional object with details about\n     * the error, like shard moving, suspending. Used for analytics purposes.\n     */\n    CONNECTION_FAILED = 'connection.connectionFailed',\n\n    /**\n     * The connection is redirected to a visitor node.\n     */\n    CONNECTION_REDIRECTED = 'connection.redirected',\n\n    /**\n     * The connection is trying to resume, but token is expired.\n     */\n    CONNECTION_TOKEN_EXPIRED = 'connection.token_expired',\n\n    /**\n     * Indicates that the display name is required over this connection and need to be supplied when\n     * joining the room.\n     * There are cases like lobby room where display name is required.\n     */\n    DISPLAY_NAME_REQUIRED = 'connection.display_name_required',\n\n    /**\n     * Indicates that the connection properties have been updated.\n     * @param properties {object} - All available connection properties (e.g. shard, region).\n     */\n    PROPERTIES_UPDATED = 'connection.propertiesUpdated',\n}\n\n// exported for backward compatibility\nexport const CONNECTION_DISCONNECTED = JitsiConnectionEvents.CONNECTION_DISCONNECTED;\nexport const CONNECTION_ESTABLISHED = JitsiConnectionEvents.CONNECTION_ESTABLISHED;\nexport const CONNECTION_FAILED = JitsiConnectionEvents.CONNECTION_FAILED;\nexport const CONNECTION_REDIRECTED = JitsiConnectionEvents.CONNECTION_REDIRECTED;\nexport const CONNECTION_TOKEN_EXPIRED = JitsiConnectionEvents.CONNECTION_TOKEN_EXPIRED;\nexport const DISPLAY_NAME_REQUIRED = JitsiConnectionEvents.DISPLAY_NAME_REQUIRED;\nexport const PROPERTIES_UPDATED = JitsiConnectionEvents.PROPERTIES_UPDATED;\n","import { Strophe } from 'strophe.js';\n\nimport JitsiConference from './JitsiConference';\nimport { JitsiConferenceEvents } from './JitsiConferenceEvents';\nimport JitsiRemoteTrack from './modules/RTC/JitsiRemoteTrack';\nimport { MediaType } from './service/RTC/MediaType';\nimport { SourceName } from './service/RTC/SignalingLayer';\nimport { VideoType } from './service/RTC/VideoType';\n\nexport interface ISourceInfo {\n    muted: boolean;\n    videoType: string;\n}\n\n/**\n * Represents a participant in (i.e. a member of) a conference.\n */\nexport default class JitsiParticipant {\n\n    private _jid: string;\n    private _id: string;\n    private _conference: JitsiConference;\n    private _role: string;\n    private _hidden: boolean;\n    private _statsID?: string;\n    private _properties: Map<string, any>;\n    private _identity?: object;\n    private _isReplacing?: boolean;\n    private _isReplaced?: boolean;\n    private _isSilent?: boolean;\n    private _features: Set<string>;\n    private _sources: Map<MediaType, Map<string, ISourceInfo>>;\n    private _botType?: string;\n    private _connectionJid?: string;\n    /**\n     * @internal\n     */\n    _status?: string;\n    /**\n     * @internal\n     */\n    _displayName: string;\n    /**\n     * @internal\n     */\n    _supportsDTMF: boolean;\n    /**\n     * @internal\n     */\n    _tracks: JitsiRemoteTrack[];\n\n    /* eslint-disable max-params */\n\n    /**\n     * Initializes a new JitsiParticipant instance.\n     *\n     * @param jid the conference XMPP jid\n     * @param conference\n     * @param displayName\n     * @param {Boolean} hidden - True if the new JitsiParticipant instance is to\n     * represent a hidden participant; otherwise, false.\n     * @param {string} statsID - optional participant statsID\n     * @param {string} status - the initial status if any.\n     * @param {object} identity - the xmpp identity\n     * @param {boolean?} isReplacing - whether this is a participant replacing another into the meeting.\n     * @param {boolean?} isReplaced - whether this is a participant to be kicked and replaced into the meeting.\n     * @param {boolean?} isSilent - whether participant has joined without audio\n     */\n    constructor(\n            jid: string,\n            conference: JitsiConference,\n            displayName: string,\n            hidden: boolean,\n            statsID?: string,\n            status?: string,\n            identity?: object,\n            isReplacing?: boolean,\n            isReplaced?: boolean,\n            isSilent?: boolean\n    ) {\n        this._jid = jid;\n        this._id = Strophe.getResourceFromJid(jid);\n        this._conference = conference;\n        this._displayName = displayName;\n        this._supportsDTMF = false;\n        this._tracks = [];\n        this._role = 'none';\n        this._status = status;\n        this._hidden = hidden;\n        this._statsID = statsID;\n        this._properties = new Map();\n        this._identity = identity;\n        this._isReplacing = isReplacing;\n        this._isReplaced = isReplaced;\n        this._isSilent = isSilent;\n        this._features = new Set();\n\n        /**\n         * Remote sources associated with the participant in the following format.\n         * Map<mediaType, Map<sourceName, ISourceInfo>>\n         *\n         * mediaType - 'audio' or 'video'.\n         * sourceName - name of the remote source.\n         * ISourceInfo: {\n         *   muted: boolean;\n         *   videoType: string;\n         * }\n         */\n        this._sources = new Map();\n    }\n\n    /**\n     * Determines whether all JitsiTracks which are of a specific MediaType and which belong to this\n     * JitsiParticipant are muted.\n     *\n     * @param {MediaType} mediaType - The MediaType of the JitsiTracks to be checked.\n     * @private\n     * @returns {Boolean} True if all JitsiTracks which are of the specified mediaType and which belong to this\n     * JitsiParticipant are muted; otherwise, false.\n     */\n    _isMediaTypeMuted(mediaType: MediaType): boolean {\n        return this.getTracks().reduce(\n            (muted, track) =>\n                muted && (track.getType() !== mediaType || (track as any).isMuted()),\n            true);\n    }\n\n    /**\n     * Sets source info.\n     * @param {MediaType} mediaType The media type, 'audio' or 'video'.\n     * @param {boolean} muted The new muted state.\n     * @param {SourceName} sourceName The name of the source.\n     * @param {string} videoType The video type of the source.\n     * @returns {void}\n     */\n    _setSources(mediaType: MediaType, muted: boolean, sourceName: SourceName, videoType: VideoType): void {\n        let sourceByMediaType = this._sources.get(mediaType);\n        const sourceInfo: ISourceInfo = {\n            muted,\n            videoType\n        };\n\n        if (sourceByMediaType?.size) {\n            sourceByMediaType.set(sourceName, sourceInfo);\n\n            return;\n        }\n\n        sourceByMediaType = new Map();\n        sourceByMediaType.set(sourceName, sourceInfo);\n        this._sources.set(mediaType, sourceByMediaType);\n    }\n\n    /**\n     * Returns the bot type for the participant.\n     *\n     * @returns {Optional<string>} - The bot type of the participant.\n     */\n    getBotType(): Optional<string> {\n        return this._botType;\n    }\n\n    /**\n     * @returns {JitsiConference} The conference that this participant belongs\n     * to.\n     */\n    getConference(): JitsiConference {\n        return this._conference;\n    }\n\n    /**\n     * Returns the connection jid for the participant.\n     *\n     * @returns {Optional<string>} - The connection jid of the participant.\n     */\n    getConnectionJid(): Optional<string> {\n        return this._connectionJid;\n    }\n\n    /**\n     * @returns {String} The human-readable display name of this participant.\n     */\n    getDisplayName(): string {\n        return this._displayName;\n    }\n\n    /**\n     * Returns a set with the features for the participant.\n     * @returns {Promise<Set<String>>}\n     */\n    getFeatures(): Promise<Set<string>> {\n        return Promise.resolve(this._features);\n    }\n\n    /**\n     * @returns {String} The ID of this participant.\n     */\n    getId(): string {\n        return this._id;\n    }\n\n    /**\n     * Returns the XMPP identity. This is defined by your application in the\n     * JWT `context` claims section.\n     *\n     * @returns {Optional<object>} - XMPP user identity.\n     */\n    getIdentity(): Optional<object> {\n        return this._identity;\n    }\n\n    /**\n     * @returns {String} The JID of this participant.\n     */\n    getJid(): string {\n        return this._jid;\n    }\n\n    /**\n     * Gets the value of a property of this participant.\n     */\n    getProperty(name: string): any {\n        return this._properties.get(name);\n    }\n\n    /**\n     * @returns {String} The role of this participant.\n     */\n    getRole(): string {\n        return this._role;\n    }\n\n    /**\n     * Returns the sources associated with this participant.\n     * @returns Map<string, Map<string, Object>>\n     */\n    getSources(): Map<MediaType, Map<string, ISourceInfo>> {\n        return this._sources;\n    }\n\n    /**\n     * @returns {String} The stats ID of this participant.\n     */\n    getStatsID(): string {\n        return this._statsID;\n    }\n\n    /**\n     * @returns {String} The status of the participant.\n     */\n    getStatus(): string {\n        return this._status;\n    }\n\n    /**\n     * @returns {Array.<JitsiRemoteTrack>} The list of media tracks for this\n     * participant.\n     */\n    getTracks(): (JitsiRemoteTrack)[] {\n        return this._tracks.slice();\n    }\n\n    /**\n     * @param {MediaType} mediaType\n     * @returns {Array.<JitsiRemoteTrack>} an array of media tracks for this\n     * participant, for given media type.\n     */\n    getTracksByMediaType(mediaType: MediaType): (JitsiRemoteTrack)[] {\n        return this.getTracks().filter(track => track.getType() === mediaType);\n    }\n\n    /**\n     * Checks current set features.\n     * @param {String} feature - the feature to check.\n     * @return {boolean} <tt>true</tt> if this <tt>participant</tt> contains the\n     * <tt>feature</tt>.\n     */\n    hasFeature(feature: string): boolean {\n        return this._features.has(feature);\n    }\n\n    /**\n     * @returns {Boolean} Whether this participant has muted their audio.\n     */\n    isAudioMuted(): boolean {\n        return this._isMediaTypeMuted(MediaType.AUDIO);\n    }\n\n    /**\n     * @returns {Boolean} Whether this participant is a hidden participant. Some\n     * special system participants may want to join hidden (like for example the\n     * recorder).\n     */\n    isHidden(): boolean {\n        return this._hidden;\n    }\n\n    /**\n     * @returns {Boolean} Whether this participant is a hidden participant. Some\n     * special system participants may want to join hidden (like for example the\n     * recorder).\n     */\n    isHiddenFromRecorder(): boolean {\n        return (this._identity as any)?.user?.['hidden-from-recorder'] === 'true';\n    }\n\n    /**\n     * @returns {Boolean} Whether this participant is a moderator or not.\n     */\n    isModerator(): boolean {\n        return this._role === 'moderator';\n    }\n\n    /**\n     * @returns {Boolean} Wheter this participants will be replaced by another\n     * participant in the meeting.\n     */\n    isReplaced(): boolean {\n        return this._isReplaced;\n    }\n\n    /**\n     * @returns {Boolean} Whether this participant replaces another participant\n     * from the meeting.\n     */\n    isReplacing(): boolean {\n        return this._isReplacing;\n    }\n\n    /**\n     * @returns {Boolean} Whether this participant has joined without audio.\n     */\n    isSilent(): boolean {\n        return this._isSilent;\n    }\n\n    /**\n     * @returns {Boolean} Whether this participant has muted their video.\n     */\n    isVideoMuted(): boolean {\n        return this._isMediaTypeMuted(MediaType.VIDEO);\n    }\n\n    /**\n     * Sets the bot type for the participant.\n     * @param {String} newBotType - The new bot type to set.\n     */\n    setBotType(newBotType: string): void {\n        this._botType = newBotType;\n    }\n\n    /**\n     * Sets the connection jid for the participant.\n     * @param {String} newJid - The connection jid to set.\n     */\n    setConnectionJid(newJid: string): void {\n        this._connectionJid = newJid;\n    }\n\n    /**\n     * Set new features.\n     * @param {Set<String>|undefined} newFeatures - Sets new features.\n     */\n    setFeatures(newFeatures?: Set<string>): void {\n        this._features = newFeatures || new Set();\n    }\n\n    /**\n     * Sets whether participant is being replaced by another based on jwt.\n     * @param {boolean} newIsReplaced - whether is being replaced.\n     */\n    setIsReplaced(newIsReplaced: boolean): void {\n        this._isReplaced = newIsReplaced;\n    }\n\n    /**\n     * Sets whether participant is replacing another based on jwt.\n     * @param {boolean} newIsReplacing - whether is replacing.\n     */\n    setIsReplacing(newIsReplacing: boolean): void {\n        this._isReplacing = newIsReplacing;\n    }\n\n    /**\n     * Sets whether participant has joined without audio.\n     * @param {boolean} newIsSilent - whether is silent.\n     */\n    setIsSilent(newIsSilent: boolean): void {\n        this._isSilent = newIsSilent;\n    }\n\n    /**\n     * Sets the value of a property of this participant, and fires an event if\n     * the value has changed.\n     * @param {string} name the name of the property.\n     * @param {any} value the value to set.\n     */\n    setProperty(name: string, value: any): void {\n        const oldValue = this._properties.get(name);\n\n        if (value !== oldValue) {\n            this._properties.set(name, value);\n            this._conference.eventEmitter.emit(\n                JitsiConferenceEvents.PARTICIPANT_PROPERTY_CHANGED,\n                this,\n                name,\n                oldValue,\n                value);\n        }\n    }\n\n    /**\n     * Sets a new participant role.\n     * @param {String} newRole - the new role.\n     */\n    setRole(newRole: string): void {\n        this._role = newRole;\n    }\n\n    /**\n     *\n     */\n    supportsDTMF(): boolean {\n        return this._supportsDTMF;\n    }\n}\n","/**\n * The errors for the JitsiTrack objects.\n */\n\nexport enum JitsiTrackErrors {\n\n    /**\n     * An error which indicates that some of requested constraints in\n     * getUserMedia call were not satisfied.\n     */\n    CONSTRAINT_FAILED = 'gum.constraint_failed',\n\n    /**\n     * A generic error which indicates an error occurred while selecting\n     * a DesktopCapturerSource from the electron app.\n     */\n    ELECTRON_DESKTOP_PICKER_ERROR = 'gum.electron_desktop_picker_error',\n\n    /**\n     * An error which indicates a custom desktop picker could not be detected\n     * for the electron app.\n     */\n    ELECTRON_DESKTOP_PICKER_NOT_FOUND = 'gum.electron_desktop_picker_not_found',\n\n    /**\n     * Generic getUserMedia error.\n     */\n    GENERAL = 'gum.general',\n\n    /**\n     * An error which indicates that requested device was not found.\n     */\n    NOT_FOUND = 'gum.not_found',\n\n    /**\n     * An error which indicates that user denied permission to share requested\n     * device.\n     */\n    PERMISSION_DENIED = 'gum.permission_denied',\n\n    /**\n     * Generic error for screensharing failure.\n     */\n    SCREENSHARING_GENERIC_ERROR = 'gum.screensharing_generic_error',\n\n    /**\n     * Error in getDisplayMedia when not supported. Can happen in Electron if no\n     * permission handler was set.\n     */\n    SCREENSHARING_NOT_SUPPORTED_ERROR = 'gdm.screen_sharing_not_supported',\n\n    /**\n     * An error which indicates that user canceled screen sharing window\n     * selection dialog.\n     */\n    SCREENSHARING_USER_CANCELED = 'gum.screensharing_user_canceled',\n\n    /**\n     * Indicates that the timeout passed to the obtainAudioAndVideoPermissions has expired without GUM resolving.\n     */\n    TIMEOUT = 'gum.timeout',\n\n    /**\n     * An error which indicates that track has been already disposed and cannot\n     * be longer used.\n     */\n    TRACK_IS_DISPOSED = 'track.track_is_disposed',\n\n    /**\n     * An error which indicates that track has no MediaStream associated.\n     */\n    TRACK_NO_STREAM_FOUND = 'track.no_stream_found',\n\n    /**\n     * An error which indicates that no tracks were found in the media stream\n     */\n    TRACK_NO_STREAM_TRACKS_FOUND = 'track.no_stream_tracks_found',\n\n    /**\n     * An error which indicates that there are too many tracks in the provided media stream\n     */\n    TRACK_TOO_MANY_TRACKS_IN_STREAM = 'track.too_many_tracks_in_stream',\n\n    /**\n     * An error which indicates that requested video resolution is not supported\n     * by a webcam.\n     */\n    UNSUPPORTED_RESOLUTION = 'gum.unsupported_resolution'\n}\n\n// exported for backward compatibility\nexport const CONSTRAINT_FAILED = JitsiTrackErrors.CONSTRAINT_FAILED;\nexport const ELECTRON_DESKTOP_PICKER_ERROR = JitsiTrackErrors.ELECTRON_DESKTOP_PICKER_ERROR;\nexport const ELECTRON_DESKTOP_PICKER_NOT_FOUND = JitsiTrackErrors.ELECTRON_DESKTOP_PICKER_NOT_FOUND;\nexport const GENERAL = JitsiTrackErrors.GENERAL;\nexport const NOT_FOUND = JitsiTrackErrors.NOT_FOUND;\nexport const PERMISSION_DENIED = JitsiTrackErrors.PERMISSION_DENIED;\nexport const SCREENSHARING_GENERIC_ERROR = JitsiTrackErrors.SCREENSHARING_GENERIC_ERROR;\nexport const SCREENSHARING_NOT_SUPPORTED_ERROR = JitsiTrackErrors.SCREENSHARING_NOT_SUPPORTED_ERROR;\nexport const SCREENSHARING_USER_CANCELED = JitsiTrackErrors.SCREENSHARING_USER_CANCELED;\nexport const TIMEOUT = JitsiTrackErrors.TIMEOUT;\nexport const TRACK_IS_DISPOSED = JitsiTrackErrors.TRACK_IS_DISPOSED;\nexport const TRACK_NO_STREAM_FOUND = JitsiTrackErrors.TRACK_NO_STREAM_FOUND;\nexport const UNSUPPORTED_RESOLUTION = JitsiTrackErrors.UNSUPPORTED_RESOLUTION;\nexport const TRACK_TOO_MANY_TRACKS_IN_STREAM = JitsiTrackErrors.TRACK_TOO_MANY_TRACKS_IN_STREAM;\nexport const TRACK_NO_STREAM_TRACKS_FOUND = JitsiTrackErrors.TRACK_NO_STREAM_TRACKS_FOUND;\n","import * as JitsiTrackErrors from './JitsiTrackErrors';\n\nexport interface IGumError {\n    constraint?: string;\n    constraintName?: string;\n    message?: string;\n    name?: string;\n    stack?: string;\n}\n\nexport interface IVideoConstraints {\n    mandatory?: { [key: string]: string | number; };\n}\n\nexport interface IGumOptions {\n    video?: IVideoConstraints;\n}\n\nexport interface IGum {\n    constraints?: IGumOptions | string;\n    devices?: ('audio' | 'video' | 'desktop' | 'screen' | 'audiooutput')[];\n    error: IGumError;\n}\n\nexport type DeviceType = 'audio' | 'video' | 'desktop' | 'screen' | 'audiooutput';\n\nconst TRACK_ERROR_TO_MESSAGE_MAP: { [key: string]: string; } = {\n    [JitsiTrackErrors.UNSUPPORTED_RESOLUTION]: 'Video resolution is not supported: ',\n    [JitsiTrackErrors.SCREENSHARING_USER_CANCELED]: 'User canceled screen sharing prompt',\n    [JitsiTrackErrors.SCREENSHARING_GENERIC_ERROR]: 'Unknown error from screensharing',\n    [JitsiTrackErrors.SCREENSHARING_NOT_SUPPORTED_ERROR]: 'Not supported',\n    [JitsiTrackErrors.ELECTRON_DESKTOP_PICKER_ERROR]: 'Unknown error from desktop picker',\n    [JitsiTrackErrors.ELECTRON_DESKTOP_PICKER_NOT_FOUND]: 'Failed to detect desktop picker',\n    [JitsiTrackErrors.GENERAL]: 'Generic getUserMedia error',\n    [JitsiTrackErrors.PERMISSION_DENIED]: 'User denied permission to use device(s): ',\n    [JitsiTrackErrors.NOT_FOUND]: 'Requested device(s) was/were not found: ',\n    [JitsiTrackErrors.CONSTRAINT_FAILED]: 'Constraint could not be satisfied: ',\n    [JitsiTrackErrors.TIMEOUT]: 'Could not start media source. Timeout occurred!',\n    [JitsiTrackErrors.TRACK_IS_DISPOSED]: 'Track has been already disposed',\n    [JitsiTrackErrors.TRACK_NO_STREAM_FOUND]: 'Track does not have an associated Media Stream'\n};\n\n/**\n *\n * Represents an error that occurred to a JitsiTrack. Can represent various\n * types of errors. For error descriptions (@see JitsiTrackErrors).\n */\nexport default class JitsiTrackError extends Error {\n    public gum?: IGum;\n\n    /**\n     * @param {IGumError|string} error - error object or error name\n     * @param {IGumOptions|string} [options] - getUserMedia constraints object or error message\n     * @param {DeviceType[]} [devices] - list of getUserMedia requested devices\n     */\n    constructor(\n            error: IGumError | string,\n            options?: IGumOptions | string,\n            devices?: DeviceType[]\n    ) {\n        super();\n\n        if (typeof error === 'object' && typeof error.name !== 'undefined') {\n            /**\n             * Additional information about original getUserMedia error\n             * and constraints.\n             * @type {IGum}\n             */\n            this.gum = {\n                constraints: options,\n                devices: devices && Array.isArray(devices) ? devices.slice(0) : undefined,\n                error\n            };\n\n            switch (error.name) {\n            case 'NotAllowedError':\n            case 'PermissionDeniedError':\n            case 'SecurityError':\n                this.name = JitsiTrackErrors.PERMISSION_DENIED;\n                this.message = TRACK_ERROR_TO_MESSAGE_MAP[this.name] + (this.gum.devices || []).join(', ');\n                break;\n            case 'DevicesNotFoundError':\n            case 'NotFoundError':\n                this.name = JitsiTrackErrors.NOT_FOUND;\n                this.message = TRACK_ERROR_TO_MESSAGE_MAP[this.name] + (this.gum.devices || []).join(', ');\n                break;\n            case 'ConstraintNotSatisfiedError':\n            case 'OverconstrainedError': {\n                const constraintName = error.constraintName || error.constraint;\n\n                // we treat deviceId as unsupported resolution, as we want to\n                // retry and finally if everything fails to remove deviceId from\n                // mandatory constraints\n                if (typeof options !== 'string'\n                        && options?.video\n                        && (!devices || devices.indexOf('video') > -1)\n                        && (constraintName === 'minWidth'\n                            || constraintName === 'maxWidth'\n                            || constraintName === 'minHeight'\n                            || constraintName === 'maxHeight'\n                            || constraintName === 'width'\n                            || constraintName === 'height'\n                            || constraintName === 'deviceId')) {\n                    this.name = JitsiTrackErrors.UNSUPPORTED_RESOLUTION;\n                    this.message = TRACK_ERROR_TO_MESSAGE_MAP[this.name]\n                            + this.getResolutionFromFailedConstraint(constraintName, options);\n                } else {\n                    this.name = JitsiTrackErrors.CONSTRAINT_FAILED;\n                    this.message = TRACK_ERROR_TO_MESSAGE_MAP[this.name] + error.constraintName;\n                }\n                break;\n            }\n            default:\n                this.name = JitsiTrackErrors.GENERAL;\n                this.message = error.message || TRACK_ERROR_TO_MESSAGE_MAP[this.name];\n                break;\n            }\n        } else if (typeof error === 'string') {\n            if (TRACK_ERROR_TO_MESSAGE_MAP[error]) {\n                this.name = error;\n                this.message = typeof options === 'string' ? options : TRACK_ERROR_TO_MESSAGE_MAP[error];\n            } else {\n            // this is some generic error that do not fit any of our\n            // pre-defined errors, so don't give it any specific name, just\n            // store message\n                this.message = error;\n            }\n        } else {\n            throw new Error('Invalid arguments');\n        }\n\n        this.stack = typeof error === 'string' ? new Error().stack : error.stack;\n    }\n\n    /**\n     * Gets failed resolution constraint from corresponding object.\n     * @param failedConstraintName - The name of the failed constraint\n     * @param constraints - The constraints object\n     * @returns The resolution value or empty string\n     */\n    private getResolutionFromFailedConstraint(failedConstraintName: string, constraints: IGumOptions): string | number {\n        if (constraints?.video?.mandatory) {\n            switch (failedConstraintName) {\n            case 'width':\n                return constraints.video.mandatory.minWidth;\n            case 'height':\n                return constraints.video.mandatory.minHeight;\n            default:\n                return constraints.video.mandatory[failedConstraintName] || '';\n            }\n        }\n\n        return '';\n    }\n}\n","/**\n * A specialized version of `_.forEach` for arrays without support for\n * iteratee shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns `array`.\n */\nfunction arrayEach(array, iteratee) {\n  var index = -1,\n      length = array == null ? 0 : array.length;\n\n  while (++index < length) {\n    if (iteratee(array[index], index, array) === false) {\n      break;\n    }\n  }\n  return array;\n}\n\nexport default arrayEach;\n","import arrayPush from './_arrayPush.js';\nimport getPrototype from './_getPrototype.js';\nimport getSymbols from './_getSymbols.js';\nimport stubArray from './stubArray.js';\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeGetSymbols = Object.getOwnPropertySymbols;\n\n/**\n * Creates an array of the own and inherited enumerable symbols of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of symbols.\n */\nvar getSymbolsIn = !nativeGetSymbols ? stubArray : function(object) {\n  var result = [];\n  while (object) {\n    arrayPush(result, getSymbols(object));\n    object = getPrototype(object);\n  }\n  return result;\n};\n\nexport default getSymbolsIn;\n","import baseGetAllKeys from './_baseGetAllKeys.js';\nimport getSymbolsIn from './_getSymbolsIn.js';\nimport keysIn from './keysIn.js';\n\n/**\n * Creates an array of own and inherited enumerable property names and\n * symbols of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names and symbols.\n */\nfunction getAllKeysIn(object) {\n  return baseGetAllKeys(object, keysIn, getSymbolsIn);\n}\n\nexport default getAllKeysIn;\n","/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Initializes an array clone.\n *\n * @private\n * @param {Array} array The array to clone.\n * @returns {Array} Returns the initialized clone.\n */\nfunction initCloneArray(array) {\n  var length = array.length,\n      result = new array.constructor(length);\n\n  // Add properties assigned by `RegExp#exec`.\n  if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) {\n    result.index = array.index;\n    result.input = array.input;\n  }\n  return result;\n}\n\nexport default initCloneArray;\n","/** Used to match `RegExp` flags from their coerced string values. */\nvar reFlags = /\\w*$/;\n\n/**\n * Creates a clone of `regexp`.\n *\n * @private\n * @param {Object} regexp The regexp to clone.\n * @returns {Object} Returns the cloned regexp.\n */\nfunction cloneRegExp(regexp) {\n  var result = new regexp.constructor(regexp.source, reFlags.exec(regexp));\n  result.lastIndex = regexp.lastIndex;\n  return result;\n}\n\nexport default cloneRegExp;\n","import Symbol from './_Symbol.js';\n\n/** Used to convert symbols to primitives and strings. */\nvar symbolProto = Symbol ? Symbol.prototype : undefined,\n    symbolValueOf = symbolProto ? symbolProto.valueOf : undefined;\n\n/**\n * Creates a clone of the `symbol` object.\n *\n * @private\n * @param {Object} symbol The symbol object to clone.\n * @returns {Object} Returns the cloned symbol object.\n */\nfunction cloneSymbol(symbol) {\n  return symbolValueOf ? Object(symbolValueOf.call(symbol)) : {};\n}\n\nexport default cloneSymbol;\n","import cloneArrayBuffer from './_cloneArrayBuffer.js';\nimport cloneDataView from './_cloneDataView.js';\nimport cloneRegExp from './_cloneRegExp.js';\nimport cloneSymbol from './_cloneSymbol.js';\nimport cloneTypedArray from './_cloneTypedArray.js';\n\n/** `Object#toString` result references. */\nvar boolTag = '[object Boolean]',\n    dateTag = '[object Date]',\n    mapTag = '[object Map]',\n    numberTag = '[object Number]',\n    regexpTag = '[object RegExp]',\n    setTag = '[object Set]',\n    stringTag = '[object String]',\n    symbolTag = '[object Symbol]';\n\nvar arrayBufferTag = '[object ArrayBuffer]',\n    dataViewTag = '[object DataView]',\n    float32Tag = '[object Float32Array]',\n    float64Tag = '[object Float64Array]',\n    int8Tag = '[object Int8Array]',\n    int16Tag = '[object Int16Array]',\n    int32Tag = '[object Int32Array]',\n    uint8Tag = '[object Uint8Array]',\n    uint8ClampedTag = '[object Uint8ClampedArray]',\n    uint16Tag = '[object Uint16Array]',\n    uint32Tag = '[object Uint32Array]';\n\n/**\n * Initializes an object clone based on its `toStringTag`.\n *\n * **Note:** This function only supports cloning values with tags of\n * `Boolean`, `Date`, `Error`, `Map`, `Number`, `RegExp`, `Set`, or `String`.\n *\n * @private\n * @param {Object} object The object to clone.\n * @param {string} tag The `toStringTag` of the object to clone.\n * @param {boolean} [isDeep] Specify a deep clone.\n * @returns {Object} Returns the initialized clone.\n */\nfunction initCloneByTag(object, tag, isDeep) {\n  var Ctor = object.constructor;\n  switch (tag) {\n    case arrayBufferTag:\n      return cloneArrayBuffer(object);\n\n    case boolTag:\n    case dateTag:\n      return new Ctor(+object);\n\n    case dataViewTag:\n      return cloneDataView(object, isDeep);\n\n    case float32Tag: case float64Tag:\n    case int8Tag: case int16Tag: case int32Tag:\n    case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag:\n      return cloneTypedArray(object, isDeep);\n\n    case mapTag:\n      return new Ctor;\n\n    case numberTag:\n    case stringTag:\n      return new Ctor(object);\n\n    case regexpTag:\n      return cloneRegExp(object);\n\n    case setTag:\n      return new Ctor;\n\n    case symbolTag:\n      return cloneSymbol(object);\n  }\n}\n\nexport default initCloneByTag;\n","import cloneArrayBuffer from './_cloneArrayBuffer.js';\n\n/**\n * Creates a clone of `dataView`.\n *\n * @private\n * @param {Object} dataView The data view to clone.\n * @param {boolean} [isDeep] Specify a deep clone.\n * @returns {Object} Returns the cloned data view.\n */\nfunction cloneDataView(dataView, isDeep) {\n  var buffer = isDeep ? cloneArrayBuffer(dataView.buffer) : dataView.buffer;\n  return new dataView.constructor(buffer, dataView.byteOffset, dataView.byteLength);\n}\n\nexport default cloneDataView;\n","import baseIsMap from './_baseIsMap.js';\nimport baseUnary from './_baseUnary.js';\nimport nodeUtil from './_nodeUtil.js';\n\n/* Node.js helper references. */\nvar nodeIsMap = nodeUtil && nodeUtil.isMap;\n\n/**\n * Checks if `value` is classified as a `Map` object.\n *\n * @static\n * @memberOf _\n * @since 4.3.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a map, else `false`.\n * @example\n *\n * _.isMap(new Map);\n * // => true\n *\n * _.isMap(new WeakMap);\n * // => false\n */\nvar isMap = nodeIsMap ? baseUnary(nodeIsMap) : baseIsMap;\n\nexport default isMap;\n","import getTag from './_getTag.js';\nimport isObjectLike from './isObjectLike.js';\n\n/** `Object#toString` result references. */\nvar mapTag = '[object Map]';\n\n/**\n * The base implementation of `_.isMap` without Node.js optimizations.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a map, else `false`.\n */\nfunction baseIsMap(value) {\n  return isObjectLike(value) && getTag(value) == mapTag;\n}\n\nexport default baseIsMap;\n","import baseIsSet from './_baseIsSet.js';\nimport baseUnary from './_baseUnary.js';\nimport nodeUtil from './_nodeUtil.js';\n\n/* Node.js helper references. */\nvar nodeIsSet = nodeUtil && nodeUtil.isSet;\n\n/**\n * Checks if `value` is classified as a `Set` object.\n *\n * @static\n * @memberOf _\n * @since 4.3.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a set, else `false`.\n * @example\n *\n * _.isSet(new Set);\n * // => true\n *\n * _.isSet(new WeakSet);\n * // => false\n */\nvar isSet = nodeIsSet ? baseUnary(nodeIsSet) : baseIsSet;\n\nexport default isSet;\n","import getTag from './_getTag.js';\nimport isObjectLike from './isObjectLike.js';\n\n/** `Object#toString` result references. */\nvar setTag = '[object Set]';\n\n/**\n * The base implementation of `_.isSet` without Node.js optimizations.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a set, else `false`.\n */\nfunction baseIsSet(value) {\n  return isObjectLike(value) && getTag(value) == setTag;\n}\n\nexport default baseIsSet;\n","import Stack from './_Stack.js';\nimport arrayEach from './_arrayEach.js';\nimport assignValue from './_assignValue.js';\nimport baseAssign from './_baseAssign.js';\nimport baseAssignIn from './_baseAssignIn.js';\nimport cloneBuffer from './_cloneBuffer.js';\nimport copyArray from './_copyArray.js';\nimport copySymbols from './_copySymbols.js';\nimport copySymbolsIn from './_copySymbolsIn.js';\nimport getAllKeys from './_getAllKeys.js';\nimport getAllKeysIn from './_getAllKeysIn.js';\nimport getTag from './_getTag.js';\nimport initCloneArray from './_initCloneArray.js';\nimport initCloneByTag from './_initCloneByTag.js';\nimport initCloneObject from './_initCloneObject.js';\nimport isArray from './isArray.js';\nimport isBuffer from './isBuffer.js';\nimport isMap from './isMap.js';\nimport isObject from './isObject.js';\nimport isSet from './isSet.js';\nimport keys from './keys.js';\nimport keysIn from './keysIn.js';\n\n/** Used to compose bitmasks for cloning. */\nvar CLONE_DEEP_FLAG = 1,\n    CLONE_FLAT_FLAG = 2,\n    CLONE_SYMBOLS_FLAG = 4;\n\n/** `Object#toString` result references. */\nvar argsTag = '[object Arguments]',\n    arrayTag = '[object Array]',\n    boolTag = '[object Boolean]',\n    dateTag = '[object Date]',\n    errorTag = '[object Error]',\n    funcTag = '[object Function]',\n    genTag = '[object GeneratorFunction]',\n    mapTag = '[object Map]',\n    numberTag = '[object Number]',\n    objectTag = '[object Object]',\n    regexpTag = '[object RegExp]',\n    setTag = '[object Set]',\n    stringTag = '[object String]',\n    symbolTag = '[object Symbol]',\n    weakMapTag = '[object WeakMap]';\n\nvar arrayBufferTag = '[object ArrayBuffer]',\n    dataViewTag = '[object DataView]',\n    float32Tag = '[object Float32Array]',\n    float64Tag = '[object Float64Array]',\n    int8Tag = '[object Int8Array]',\n    int16Tag = '[object Int16Array]',\n    int32Tag = '[object Int32Array]',\n    uint8Tag = '[object Uint8Array]',\n    uint8ClampedTag = '[object Uint8ClampedArray]',\n    uint16Tag = '[object Uint16Array]',\n    uint32Tag = '[object Uint32Array]';\n\n/** Used to identify `toStringTag` values supported by `_.clone`. */\nvar cloneableTags = {};\ncloneableTags[argsTag] = cloneableTags[arrayTag] =\ncloneableTags[arrayBufferTag] = cloneableTags[dataViewTag] =\ncloneableTags[boolTag] = cloneableTags[dateTag] =\ncloneableTags[float32Tag] = cloneableTags[float64Tag] =\ncloneableTags[int8Tag] = cloneableTags[int16Tag] =\ncloneableTags[int32Tag] = cloneableTags[mapTag] =\ncloneableTags[numberTag] = cloneableTags[objectTag] =\ncloneableTags[regexpTag] = cloneableTags[setTag] =\ncloneableTags[stringTag] = cloneableTags[symbolTag] =\ncloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] =\ncloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true;\ncloneableTags[errorTag] = cloneableTags[funcTag] =\ncloneableTags[weakMapTag] = false;\n\n/**\n * The base implementation of `_.clone` and `_.cloneDeep` which tracks\n * traversed objects.\n *\n * @private\n * @param {*} value The value to clone.\n * @param {boolean} bitmask The bitmask flags.\n *  1 - Deep clone\n *  2 - Flatten inherited properties\n *  4 - Clone symbols\n * @param {Function} [customizer] The function to customize cloning.\n * @param {string} [key] The key of `value`.\n * @param {Object} [object] The parent object of `value`.\n * @param {Object} [stack] Tracks traversed objects and their clone counterparts.\n * @returns {*} Returns the cloned value.\n */\nfunction baseClone(value, bitmask, customizer, key, object, stack) {\n  var result,\n      isDeep = bitmask & CLONE_DEEP_FLAG,\n      isFlat = bitmask & CLONE_FLAT_FLAG,\n      isFull = bitmask & CLONE_SYMBOLS_FLAG;\n\n  if (customizer) {\n    result = object ? customizer(value, key, object, stack) : customizer(value);\n  }\n  if (result !== undefined) {\n    return result;\n  }\n  if (!isObject(value)) {\n    return value;\n  }\n  var isArr = isArray(value);\n  if (isArr) {\n    result = initCloneArray(value);\n    if (!isDeep) {\n      return copyArray(value, result);\n    }\n  } else {\n    var tag = getTag(value),\n        isFunc = tag == funcTag || tag == genTag;\n\n    if (isBuffer(value)) {\n      return cloneBuffer(value, isDeep);\n    }\n    if (tag == objectTag || tag == argsTag || (isFunc && !object)) {\n      result = (isFlat || isFunc) ? {} : initCloneObject(value);\n      if (!isDeep) {\n        return isFlat\n          ? copySymbolsIn(value, baseAssignIn(result, value))\n          : copySymbols(value, baseAssign(result, value));\n      }\n    } else {\n      if (!cloneableTags[tag]) {\n        return object ? value : {};\n      }\n      result = initCloneByTag(value, tag, isDeep);\n    }\n  }\n  // Check for circular references and return its corresponding clone.\n  stack || (stack = new Stack);\n  var stacked = stack.get(value);\n  if (stacked) {\n    return stacked;\n  }\n  stack.set(value, result);\n\n  if (isSet(value)) {\n    value.forEach(function(subValue) {\n      result.add(baseClone(subValue, bitmask, customizer, subValue, value, stack));\n    });\n  } else if (isMap(value)) {\n    value.forEach(function(subValue, key) {\n      result.set(key, baseClone(subValue, bitmask, customizer, key, value, stack));\n    });\n  }\n\n  var keysFunc = isFull\n    ? (isFlat ? getAllKeysIn : getAllKeys)\n    : (isFlat ? keysIn : keys);\n\n  var props = isArr ? undefined : keysFunc(value);\n  arrayEach(props || value, function(subValue, key) {\n    if (props) {\n      key = subValue;\n      subValue = value[key];\n    }\n    // Recursively populate clone (susceptible to call stack limits).\n    assignValue(result, key, baseClone(subValue, bitmask, customizer, key, value, stack));\n  });\n  return result;\n}\n\nexport default baseClone;\n","import copyObject from './_copyObject.js';\nimport getSymbolsIn from './_getSymbolsIn.js';\n\n/**\n * Copies own and inherited symbols of `source` to `object`.\n *\n * @private\n * @param {Object} source The object to copy symbols from.\n * @param {Object} [object={}] The object to copy symbols to.\n * @returns {Object} Returns `object`.\n */\nfunction copySymbolsIn(source, object) {\n  return copyObject(source, getSymbolsIn(source), object);\n}\n\nexport default copySymbolsIn;\n","import copyObject from './_copyObject.js';\nimport keysIn from './keysIn.js';\n\n/**\n * The base implementation of `_.assignIn` without support for multiple sources\n * or `customizer` functions.\n *\n * @private\n * @param {Object} object The destination object.\n * @param {Object} source The source object.\n * @returns {Object} Returns `object`.\n */\nfunction baseAssignIn(object, source) {\n  return object && copyObject(source, keysIn(source), object);\n}\n\nexport default baseAssignIn;\n","import copyObject from './_copyObject.js';\nimport getSymbols from './_getSymbols.js';\n\n/**\n * Copies own symbols of `source` to `object`.\n *\n * @private\n * @param {Object} source The object to copy symbols from.\n * @param {Object} [object={}] The object to copy symbols to.\n * @returns {Object} Returns `object`.\n */\nfunction copySymbols(source, object) {\n  return copyObject(source, getSymbols(source), object);\n}\n\nexport default copySymbols;\n","import copyObject from './_copyObject.js';\nimport keys from './keys.js';\n\n/**\n * The base implementation of `_.assign` without support for multiple sources\n * or `customizer` functions.\n *\n * @private\n * @param {Object} object The destination object.\n * @param {Object} source The source object.\n * @returns {Object} Returns `object`.\n */\nfunction baseAssign(object, source) {\n  return object && copyObject(source, keys(source), object);\n}\n\nexport default baseAssign;\n","import baseClone from './_baseClone.js';\n\n/** Used to compose bitmasks for cloning. */\nvar CLONE_DEEP_FLAG = 1,\n    CLONE_SYMBOLS_FLAG = 4;\n\n/**\n * This method is like `_.clone` except that it recursively clones `value`.\n *\n * @static\n * @memberOf _\n * @since 1.0.0\n * @category Lang\n * @param {*} value The value to recursively clone.\n * @returns {*} Returns the deep cloned value.\n * @see _.clone\n * @example\n *\n * var objects = [{ 'a': 1 }, { 'b': 2 }];\n *\n * var deep = _.cloneDeep(objects);\n * console.log(deep[0] === objects[0]);\n * // => false\n */\nfunction cloneDeep(value) {\n  return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG);\n}\n\nexport default cloneDeep;\n","/**\n * Enumeration of the video types\n */\nexport enum VideoType {\n\n    /**\n     * The camera video type.\n     */\n    CAMERA = 'camera',\n\n    /**\n     * The desktop video type.\n     */\n    DESKTOP = 'desktop',\n\n    /**\n     * The high fps desktop video type.\n     */\n    DESKTOP_HIGH_FPS = 'desktop_high_fps'\n}\n","import EventEmitter, { EventListener } from './EventEmitter';\n\n/**\n * The class implements basic event operations - add/remove listener.\n * NOTE: The purpose of the class is to be extended in order to add\n * this functionality to other classes.\n */\nexport default class Listenable {\n    /**\n     * @internal\n     */\n    eventEmitter: EventEmitter;\n\n    /**\n     * Creates new instance.\n     */\n    constructor() {\n        this.eventEmitter = new EventEmitter();\n    }\n\n    /**\n   * Attaches a handler for events (e.g., \"participant joined\") in the conference.\n   * All possible events are defined in JitsiConferenceEvents.\n   * @param {string} eventId - The event ID.\n   * @param {Function} handler - Handler for the event.\n   */\n    on(eventId: string, handler: EventListener): void {\n        this.eventEmitter.on(eventId, handler);\n    }\n\n    /**\n   * Removes event listener.\n   * @param {string} eventId - The event ID.\n   * @param {Function} [handler] - Optional, the specific handler to unbind.\n   */\n    off(eventId: string, handler?: EventListener): void {\n        this.eventEmitter.removeListener(eventId, handler);\n    }\n\n    /**\n   * Adds a one-time listener function for the event.\n   * @param {string} eventId - The event ID.\n   * @param {Function} handler - Handler for the event.\n   */\n    once(eventId: string, handler: EventListener): void {\n        this.eventEmitter.once(eventId, handler);\n    }\n\n    /**\n     * Alias for on method.\n     * @param {string} eventId - The event ID.\n     * @param {Function} handler - Handler for the event.\n     */\n    addEventListener(eventId: string, handler: EventListener): void {\n        this.on(eventId, handler);\n    }\n\n    /**\n     * Alias for off method.\n     * @param {string} eventId - The event ID.\n     * @param {Function} [handler] - Optional, the specific handler to unbind.\n     */\n    removeEventListener(eventId: string, handler?: EventListener): void {\n        this.off(eventId, handler);\n    }\n\n    /**\n     * Adds new cancellable listener.\n     * @param {String} eventName the name of the event\n     * @param {Function} listener the listener.\n     * @returns {Function} - The unsubscribe function.\n     */\n    addCancellableListener(eventName: string, listener: EventListener): () => void {\n        this.addListener(eventName, listener);\n\n        return () => this.removeListener(eventName, listener);\n    }\n\n    /**\n     * Adds new listener.\n     * @param {String} eventName the name of the event\n     * @param {Function} listener the listener.\n     * @returns {EventEmitter} - The emitter, so that calls can be chained.\n     */\n    addListener(eventName: string, listener: EventListener): EventEmitter {\n        return this.eventEmitter.addListener(eventName, listener);\n    }\n\n    /**\n     * Removes listener.\n     * @param {String} eventName the name of the event that triggers the\n     * listener\n     * @param {Function} listener the listener.\n     * @returns {EventEmitter} - The emitter, so that calls can be chained.\n     */\n    removeListener(eventName: string, listener: EventListener): EventEmitter {\n        return this.eventEmitter.removeListener(eventName, listener);\n    }\n\n    /**\n     * Emits an event.\n     * @param {string} event - event name\n     */\n    emit(event: string, ...args: any[]): void {\n        this.eventEmitter.emit(event, ...args);\n    }\n\n    /**\n     * Removes all listeners for the event emitter.\n     */\n    removeAllListeners(): void {\n        this.eventEmitter.removeAllListeners();\n    }\n\n    /**\n     * Returns the number of listeners for the specified event.\n     * @param {string} [eventName] - The name of the event.\n     * @returns {number} - The number of listeners for the event.\n     */\n    listenerCount(eventName?: string): number {\n        return this.eventEmitter.listenerCount(eventName);\n    }\n}\n","import { safeJsonParse } from '@jitsi/js-utils/json';\nimport { getLogger } from '@jitsi/logger';\nimport { EventEmitter } from 'events';\n\nimport JitsiConference from '../../JitsiConference';\nimport { BridgeVideoType } from '../../service/RTC/BridgeVideoType';\nimport { RTCEvents } from '../../service/RTC/RTCEvents';\nimport { IReceiverAudioSubscriptionMessage } from '../../service/RTC/ReceiverAudioSubscription';\nimport { SourceName } from '../../service/RTC/SignalingLayer';\nimport { createBridgeChannelClosedEvent } from '../../service/statistics/AnalyticsEvents';\nimport ReceiverVideoConstraints from '../qualitycontrol/ReceiveVideoController';\nimport Statistics from '../statistics/statistics';\n\n\nconst logger = getLogger('rtc:BridgeChannel');\n\n/**\n * Handles a WebRTC RTCPeerConnection or a WebSocket instance to communicate\n * with the videobridge.\n */\nexport default class BridgeChannel {\n\n    private _channel: Nullable<RTCDataChannel | WebSocket> = null;\n    private _conference: JitsiConference;\n    private _connected: Optional<boolean> = undefined;\n    private _eventEmitter: EventEmitter;\n    private _mode: Nullable<'datachannel' | 'websocket'> = null;\n    private _areRetriesEnabled: boolean = false;\n    private _closedFromClient: boolean = false;\n    private _wsUrl?: string;\n    private _retryTimeout?: ReturnType<typeof setTimeout>;\n\n    /**\n     * Binds \"ondatachannel\" event listener on the given RTCPeerConnection\n     * instance, or creates a WebSocket connection with the videobridge.\n     * At least one of both, peerconnection or wsUrl parameters, must be\n     * given.\n     * @param {Nullable<RTCPeerConnection>} [peerconnection] WebRTC peer connection\n     * instance.\n     * @param {Nullable<string>} [wsUrl] WebSocket URL.\n     * @param {EventEmitter} emitter the EventEmitter instance to use for event emission.\n     * @param {JitsiConference} conference the conference instance.\n     */\n    constructor(\n            peerconnection: Nullable<RTCPeerConnection>,\n            wsUrl: Nullable<string>,\n            emitter: EventEmitter,\n            conference: JitsiConference\n    ) {\n        if (!peerconnection && !wsUrl) {\n            throw new TypeError('At least peerconnection or wsUrl must be given');\n        } else if (peerconnection && wsUrl) {\n            throw new TypeError('Just one of peerconnection or wsUrl must be given');\n        }\n\n        if (peerconnection) {\n            logger.debug('constructor() with peerconnection');\n        } else {\n            logger.debug(`constructor() with wsUrl:\"${wsUrl}\"`);\n        }\n\n        // The underlying WebRTC RTCDataChannel or WebSocket instance.\n        // @type {RTCDataChannel|WebSocket}\n        this._channel = null;\n\n        // The conference that uses this bridge channel.\n        this._conference = conference;\n\n        // Whether the channel is connected or not. It will start as undefined\n        // for the first connection attempt. Then transition to either true or false.\n        this._connected = undefined;\n\n        // @type {EventEmitter}\n        this._eventEmitter = emitter;\n\n        // Whether a RTCDataChannel or WebSocket is internally used.\n        // @type {string} \"datachannel\" / \"websocket\"\n        this._mode = null;\n\n        // Indicates whether the connection retries are enabled or not.\n        this._areRetriesEnabled = false;\n\n        // Indicates whether the connection was closed from the client or not.\n        this._closedFromClient = false;\n\n        // If a RTCPeerConnection is given, listen for new RTCDataChannel\n        // event.\n        if (peerconnection) {\n            const datachannel\n                = peerconnection.createDataChannel(\n                    'JVB data channel', {\n                        protocol: 'http://jitsi.org/protocols/colibri'\n                    });\n\n            // Handle the RTCDataChannel.\n            this._handleChannel(datachannel);\n            this._mode = 'datachannel';\n\n        // Otherwise create a WebSocket connection.\n        } else if (wsUrl) {\n            this._areRetriesEnabled = true;\n            this._wsUrl = wsUrl;\n            this._initWebSocket();\n        }\n    }\n\n    /**\n     * Initializes the web socket channel.\n     *\n     * @returns {void}\n     */\n    _initWebSocket(): void {\n        // Create a WebSocket instance.\n        const ws = new WebSocket(this._wsUrl);\n\n        // Handle the WebSocket.\n        this._handleChannel(ws);\n        this._mode = 'websocket';\n    }\n\n    /**\n     * Starts the websocket connection retries.\n     *\n     * @returns {void}\n     */\n    _startConnectionRetries(): void {\n        let timeoutS = 1;\n\n        const reload = (): void => {\n            const isConnecting = this._channel && (this._channel.readyState === 'connecting'\n                    || this._channel.readyState === WebSocket.CONNECTING);\n\n            // Should not spawn new websockets while one is already trying to connect.\n            if (isConnecting) {\n                // Timeout is still required as there is flag `_areRetriesEnabled` that\n                // blocks new retrying cycles until any channel opens in current cycle.\n                this._retryTimeout = setTimeout(reload, timeoutS * 1000);\n\n                return;\n            }\n\n            if (this.isOpen()) {\n                return;\n            }\n            this._initWebSocket();\n            timeoutS = Math.min(timeoutS * 2, 60);\n            this._retryTimeout = setTimeout(reload, timeoutS * 1000);\n        };\n\n        this._retryTimeout = setTimeout(reload, timeoutS * 1000);\n    }\n\n    /**\n     * Stops the websocket connection retries.\n     *\n     * @returns {void}\n     */\n    _stopConnectionRetries(): void {\n        if (this._retryTimeout) {\n            clearTimeout(this._retryTimeout);\n            this._retryTimeout = undefined;\n        }\n    }\n\n    /**\n     * Retries to establish the websocket connection after the connection was closed by the server.\n     *\n     * @param {CloseEvent} closeEvent - The close event that triggered the retries.\n     * @returns {void}\n     */\n    _retryWebSocketConnection(closeEvent: CloseEvent): void {\n        if (!this._areRetriesEnabled) {\n            return;\n        }\n        const { code, reason } = closeEvent;\n\n        Statistics.sendAnalytics(createBridgeChannelClosedEvent(code.toString(), reason));\n        this._areRetriesEnabled = false;\n        this._eventEmitter.once(RTCEvents.DATA_CHANNEL_OPEN, () => {\n            this._stopConnectionRetries();\n            this._areRetriesEnabled = true;\n        });\n        this._startConnectionRetries();\n    }\n\n    /**\n     * The channel mode.\n     * @return {string} \"datachannel\" or \"websocket\" (or null if not yet set).\n     */\n    get mode(): string {\n        return this._mode;\n    }\n\n    /**\n     * Closes the currently opened channel.\n     */\n    close(): void {\n        this._closedFromClient = true;\n        this._stopConnectionRetries();\n        this._areRetriesEnabled = false;\n        if (this._channel) {\n            try {\n                this._channel.close();\n            } catch (error) {} // eslint-disable-line no-empty\n\n            this._channel = null;\n        }\n    }\n\n    /**\n     * Whether there is an underlying RTCDataChannel or WebSocket and it's\n     * open.\n     * @return {boolean}\n     */\n    isOpen(): boolean {\n        return this._channel && (this._channel.readyState === 'open'\n            || this._channel.readyState === WebSocket.OPEN);\n    }\n\n    /**\n     * Sends local stats via the bridge channel.\n     * @param {Object} payload The payload of the message.\n     * @throws NetworkError/InvalidStateError/Error if the operation fails or if there is no data channel created.\n     */\n    sendEndpointStatsMessage(payload: Record<string, unknown>): void {\n        this._send({\n            colibriClass: 'EndpointStats',\n            ...payload\n        });\n    }\n\n    /**\n     * Sends message via the channel.\n     * @param {string} to The id of the endpoint that should receive the\n     * message. If \"\" the message will be sent to all participants.\n     * @param  {object} payload The payload of the message.\n     * @throws NetworkError or InvalidStateError from RTCDataChannel#send (@see\n     * {@link https://developer.mozilla.org/docs/Web/API/RTCDataChannel/send})\n     * or from WebSocket#send or Error with \"No opened channel\" message.\n     */\n    sendMessage(to: string, payload: Record<string, unknown>): void {\n        this._send({\n            colibriClass: 'EndpointMessage',\n            msgPayload: payload,\n            to\n        });\n    }\n\n    /**\n     * Sends a \"lastN value changed\" message via the channel.\n     * @param {number} value The new value for lastN. -1 means unlimited.\n     */\n    sendSetLastNMessage(value: number): void {\n        logger.debug(`Sending lastN=${value}.`);\n\n        this._send({\n            colibriClass: 'LastNChangedEvent',\n            lastN: value\n        });\n    }\n\n    /**\n     * Sends a message for audio subscription updates.\n     *\n     * @param {IReceiverAudioSubscriptionMessage} message - The audio subscription message.\n     * @returns {void}\n     */\n    sendReceiverAudioSubscriptionMessage(message: IReceiverAudioSubscriptionMessage): void {\n        const all = message.all ?? true;\n        const exclude = message.exclude ?? [];\n        const include = message.include ?? [];\n\n        logger.info(`Sending ReceiverAudioSubscription all=${all} `\n            + `include=[${include.join(', ')}] exclude=[${exclude.join(', ')}]`);\n        this._send({\n            all,\n            colibriClass: 'ReceiverAudioSubscription',\n            exclude,\n            include\n        });\n    }\n\n    /**\n     * Sends a 'ReceiverVideoConstraints' message via the bridge channel.\n     *\n     * @param {ReceiverVideoConstraints} constraints video constraints.\n     */\n    sendReceiverVideoConstraintsMessage(constraints: ReceiverVideoConstraints): void {\n        logger.info(`Sending ReceiverVideoConstraints with ${JSON.stringify(constraints)}`);\n        this._send({\n            colibriClass: 'ReceiverVideoConstraints',\n            ...constraints\n        });\n    }\n\n    /**\n     * Sends a 'SourceVideoTypeMessage' message via the bridge channel.\n     *\n     * @param {BridgeVideoType} videoType - the video type.\n     * @param {SourceName} sourceName - the source name of the video track.\n     * @returns {void}\n     */\n    sendSourceVideoTypeMessage(sourceName: SourceName, videoType: BridgeVideoType): void {\n        logger.info(`Sending SourceVideoTypeMessage with video type ${sourceName}: ${videoType}`);\n        this._send({\n            colibriClass: 'SourceVideoTypeMessage',\n            sourceName,\n            videoType\n        });\n    }\n\n    /**\n     * Set events on the given RTCDataChannel or WebSocket instance.\n     */\n    _handleChannel(channel: RTCDataChannel | WebSocket): void {\n        const emitter = this._eventEmitter;\n\n        channel.onopen = (): Nullable<void> => {\n            logger.info(`${this._mode} channel opened`);\n\n            this._connected = true;\n\n            emitter.emit(RTCEvents.DATA_CHANNEL_OPEN);\n        };\n\n        channel.onerror = (event: ErrorEvent): void => {\n            // WS error events contain no information about the failure (this is available in the onclose event) and\n            // the event references the WS object itself, which causes hangs on mobile.\n            if (this._mode !== 'websocket') {\n                logger.error(`Channel error: ${event.message}`);\n            }\n        };\n\n        channel.onmessage = ({ data }: { data: string; }): void => {\n            // JSON object.\n            let obj;\n\n            try {\n                obj = safeJsonParse(data);\n            } catch (error) {\n                logger.error('Failed to parse channel message as JSON: ', data, error);\n\n                return;\n            }\n\n            const colibriClass = obj.colibriClass;\n\n            switch (colibriClass) {\n            case 'ConnectionStats': {\n                const { estimatedDownlinkBandwidth } = obj;\n\n                logger.debug(`Connection stats: bwe=${estimatedDownlinkBandwidth} bps`);\n                emitter.emit(RTCEvents.BRIDGE_BWE_STATS_RECEIVED, estimatedDownlinkBandwidth);\n                break;\n            }\n\n            case 'DominantSpeakerEndpointChangeEvent': {\n                const { dominantSpeakerEndpoint, previousSpeakers = [], silence } = obj;\n\n                logger.debug(`Dominant speaker: ${dominantSpeakerEndpoint}, previous speakers: ${previousSpeakers}`);\n                emitter.emit(RTCEvents.DOMINANT_SPEAKER_CHANGED, dominantSpeakerEndpoint, previousSpeakers, silence);\n                break;\n            }\n            case 'EndpointConnectivityStatusChangeEvent': {\n                const endpoint = obj.endpoint;\n                const isActive = obj.active === 'true';\n\n                logger.info(`Endpoint connection status changed: ${endpoint} active=${isActive}`);\n                emitter.emit(RTCEvents.ENDPOINT_CONN_STATUS_CHANGED, endpoint, isActive);\n\n                break;\n            }\n            case 'EndpointMessage': {\n                if (!obj.msgPayload || typeof obj.msgPayload !== 'object') {\n                    logger.warn(`Dropping malformed EndpointMessage from ${obj.from}: missing msgPayload`);\n                    break;\n                }\n                emitter.emit(RTCEvents.ENDPOINT_MESSAGE_RECEIVED, obj.from, obj.msgPayload);\n\n                break;\n            }\n            case 'EndpointStats': {\n                emitter.emit(RTCEvents.ENDPOINT_STATS_RECEIVED, obj.from, obj);\n\n                break;\n            }\n            case 'ForwardedSources': {\n                const forwardedSources = obj.forwardedSources;\n\n                logger.info(`New forwarded sources: ${forwardedSources}`);\n                emitter.emit(RTCEvents.FORWARDED_SOURCES_CHANGED, forwardedSources);\n\n                break;\n            }\n            case 'SenderSourceConstraints': {\n                if (typeof obj.sourceName === 'string' && typeof obj.maxHeight === 'number') {\n                    logger.info(`SenderSourceConstraints: ${obj.sourceName} - ${obj.maxHeight}`);\n                    emitter.emit(RTCEvents.SENDER_VIDEO_CONSTRAINTS_CHANGED, obj);\n                } else {\n                    logger.error(`Invalid SenderSourceConstraints: ${obj.sourceName} - ${obj.maxHeight}`);\n                }\n                break;\n            }\n            case 'ServerHello': {\n                logger.info(`Received ServerHello, version=${obj.version}.`);\n                break;\n            }\n            case 'SyntheticSourceSendingChangeEvent': {\n                // `timestamp` is an RTP timestamp (48 kHz, wraps at 2^32), not epoch ms. Validated here\n                // like SenderSourceConstraints; malformed messages are logged and dropped.\n                if (typeof obj.sourceName === 'string' && typeof obj.sending === 'boolean'\n                        && Number.isInteger(obj.timestamp)\n                        && obj.timestamp >= 0 && obj.timestamp <= 0xFFFFFFFF) {\n                    logger.info(`SyntheticSourceSendingChangeEvent: ${obj.sourceName} `\n                        + `sending=${obj.sending} ts=${obj.timestamp}`);\n                    emitter.emit(RTCEvents.TRANSLATED_SOURCE_SENDING_CHANGED, {\n                        sending: obj.sending,\n                        sourceName: obj.sourceName,\n                        timestamp: obj.timestamp\n                    });\n                } else {\n                    logger.error(`Invalid SyntheticSourceSendingChangeEvent: ${JSON.stringify(obj)}`);\n                }\n                break;\n            }\n            case 'VideoSourcesMap': {\n                logger.info(`Received VideoSourcesMap: ${JSON.stringify(obj.mappedSources)}`);\n                emitter.emit(RTCEvents.VIDEO_SSRCS_REMAPPED, obj);\n                break;\n            }\n            case 'AudioSourcesMap': {\n                logger.info(`Received AudioSourcesMap: ${JSON.stringify(obj.mappedSources)}`);\n                emitter.emit(RTCEvents.AUDIO_SSRCS_REMAPPED, obj);\n                break;\n            }\n            default: {\n                logger.debug('Channel JSON-formatted message: ', obj);\n\n                // The received message appears to be appropriately formatted\n                // (i.e. is a JSON object which assigns a value to the\n                // mandatory property colibriClass) so don't just swallow it,\n                // expose it to public consumption.\n                emitter.emit(`rtc.datachannel.${colibriClass}`, obj);\n            }\n            }\n        };\n\n        channel.onclose = (event: CloseEvent): void => {\n            logger.debug(`Channel closed by ${this._closedFromClient ? 'client' : 'server'}`);\n\n            if (channel !== this._channel) {\n                logger.debug('Skip close handler, channel instance is not equal to stored one');\n\n                return;\n            }\n\n            // When the JVB closes the connection gracefully due to the participant being alone in the meeting it uses\n            // code 1001. However, the same code is also used by Cloudflare when it terminates the ws. Therefore, check\n            // for the number of remote participants in the call and abort retries only when the endpoint is the only\n            // endpoint in the call.\n            const isGracefulClose = this._closedFromClient\n                || (event.code === 1001 && this._conference.getParticipantCount() === 1);\n\n            if (!isGracefulClose) {\n                const { code, reason } = event;\n\n                logger.error(`Channel closed: ${code} ${reason}`);\n\n                if (this._mode === 'websocket') {\n                    this._retryWebSocketConnection(event);\n\n                    // We only want to send this event the first time the failure happens.\n                    if (this._connected !== false) {\n                        emitter.emit(RTCEvents.DATA_CHANNEL_CLOSED, {\n                            code,\n                            reason\n                        });\n                    }\n                }\n            }\n\n            this._connected = false;\n\n            // Remove the channel.\n            this._channel = null;\n        };\n\n        // Store the channel.\n        this._channel = channel;\n    }\n\n    /**\n     * Sends passed object via the channel.\n     * @param {object} jsonObject The object that will be sent.\n     * @throws NetworkError or InvalidStateError from RTCDataChannel#send (@see\n     * {@link https://developer.mozilla.org/docs/Web/API/RTCDataChannel/send})\n     * or from WebSocket#send or Error with \"No opened channel\" message.\n     */\n    _send(jsonObject: Record<string, unknown>): void {\n        const channel = this._channel;\n\n        if (!this.isOpen()) {\n            logger.error('Bridge Channel send: no opened channel.');\n            throw new Error('No opened channel');\n        }\n\n        channel.send(JSON.stringify(jsonObject));\n    }\n}\n","/**\n * The possible camera facing modes. For now support only 'user' and\n * 'environment' because 'left' and 'right' are not used anywhere in our\n * projects at the time of this writing. For more information please refer to\n * https://w3c.github.io/mediacapture-main/getusermedia.html\n * #def-constraint-facingMode.\n *\n * @enum {string}\n */\nexport enum CameraFacingMode {\n\n    /**\n     * The mode which specifies the environment-facing camera.\n     */\n    ENVIRONMENT = 'environment',\n\n    /**\n     * The mode which specifies the user-facing camera.\n     */\n    USER = 'user'\n}\n","/*\n *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.\n *\n *  Use of this source code is governed by a BSD-style license\n *  that can be found in the LICENSE file in the root of the source\n *  tree.\n */\n /* eslint-env node */\n'use strict';\n\nlet logDisabled_ = true;\nlet deprecationWarnings_ = true;\n\n/**\n * Extract browser version out of the provided user agent string.\n *\n * @param {!string} uastring userAgent string.\n * @param {!string} expr Regular expression used as match criteria.\n * @param {!number} pos position in the version string to be returned.\n * @return {!number} browser version.\n */\nexport function extractVersion(uastring, expr, pos) {\n  const match = uastring.match(expr);\n  return match && match.length >= pos && parseInt(match[pos], 10);\n}\n\n// Wraps the peerconnection event eventNameToWrap in a function\n// which returns the modified event object (or false to prevent\n// the event).\nexport function wrapPeerConnectionEvent(window, eventNameToWrap, wrapper) {\n  if (!window.RTCPeerConnection) {\n    return;\n  }\n  const proto = window.RTCPeerConnection.prototype;\n  const nativeAddEventListener = proto.addEventListener;\n  proto.addEventListener = function(nativeEventName, cb) {\n    if (nativeEventName !== eventNameToWrap) {\n      return nativeAddEventListener.apply(this, arguments);\n    }\n    const wrappedCallback = (e) => {\n      const modifiedEvent = wrapper(e);\n      if (modifiedEvent) {\n        if (cb.handleEvent) {\n          cb.handleEvent(modifiedEvent);\n        } else {\n          cb(modifiedEvent);\n        }\n      }\n    };\n    this._eventMap = this._eventMap || {};\n    if (!this._eventMap[eventNameToWrap]) {\n      this._eventMap[eventNameToWrap] = new Map();\n    }\n    this._eventMap[eventNameToWrap].set(cb, wrappedCallback);\n    return nativeAddEventListener.apply(this, [nativeEventName,\n      wrappedCallback]);\n  };\n\n  const nativeRemoveEventListener = proto.removeEventListener;\n  proto.removeEventListener = function(nativeEventName, cb) {\n    if (nativeEventName !== eventNameToWrap || !this._eventMap\n        || !this._eventMap[eventNameToWrap]) {\n      return nativeRemoveEventListener.apply(this, arguments);\n    }\n    if (!this._eventMap[eventNameToWrap].has(cb)) {\n      return nativeRemoveEventListener.apply(this, arguments);\n    }\n    const unwrappedCb = this._eventMap[eventNameToWrap].get(cb);\n    this._eventMap[eventNameToWrap].delete(cb);\n    if (this._eventMap[eventNameToWrap].size === 0) {\n      delete this._eventMap[eventNameToWrap];\n    }\n    if (Object.keys(this._eventMap).length === 0) {\n      delete this._eventMap;\n    }\n    return nativeRemoveEventListener.apply(this, [nativeEventName,\n      unwrappedCb]);\n  };\n\n  Object.defineProperty(proto, 'on' + eventNameToWrap, {\n    get() {\n      return this['_on' + eventNameToWrap];\n    },\n    set(cb) {\n      if (this['_on' + eventNameToWrap]) {\n        this.removeEventListener(eventNameToWrap,\n            this['_on' + eventNameToWrap]);\n        delete this['_on' + eventNameToWrap];\n      }\n      if (cb) {\n        this.addEventListener(eventNameToWrap,\n            this['_on' + eventNameToWrap] = cb);\n      }\n    },\n    enumerable: true,\n    configurable: true\n  });\n}\n\nexport function disableLog(bool) {\n  if (typeof bool !== 'boolean') {\n    return new Error('Argument type: ' + typeof bool +\n        '. Please use a boolean.');\n  }\n  logDisabled_ = bool;\n  return (bool) ? 'adapter.js logging disabled' :\n      'adapter.js logging enabled';\n}\n\n/**\n * Disable or enable deprecation warnings\n * @param {!boolean} bool set to true to disable warnings.\n */\nexport function disableWarnings(bool) {\n  if (typeof bool !== 'boolean') {\n    return new Error('Argument type: ' + typeof bool +\n        '. Please use a boolean.');\n  }\n  deprecationWarnings_ = !bool;\n  return 'adapter.js deprecation warnings ' + (bool ? 'disabled' : 'enabled');\n}\n\nexport function log() {\n  if (typeof window === 'object') {\n    if (logDisabled_) {\n      return;\n    }\n    if (typeof console !== 'undefined' && typeof console.log === 'function') {\n      console.log.apply(console, arguments);\n    }\n  }\n}\n\n/**\n * Shows a deprecation warning suggesting the modern and spec-compatible API.\n */\nexport function deprecated(oldMethod, newMethod) {\n  if (!deprecationWarnings_) {\n    return;\n  }\n  console.warn(oldMethod + ' is deprecated, please use ' + newMethod +\n      ' instead.');\n}\n\n/**\n * Browser detector.\n *\n * @return {object} result containing browser and version\n *     properties.\n */\nexport function detectBrowser(window) {\n  // Returned result object.\n  const result = {browser: null, version: null};\n\n  // Fail early if it's not a browser\n  if (typeof window === 'undefined' || !window.navigator) {\n    result.browser = 'Not a browser.';\n    return result;\n  }\n\n  const {navigator} = window;\n\n  if (navigator.mozGetUserMedia) { // Firefox.\n    result.browser = 'firefox';\n    result.version = extractVersion(navigator.userAgent,\n        /Firefox\\/(\\d+)\\./, 1);\n  } else if (navigator.webkitGetUserMedia ||\n      (window.isSecureContext === false && window.webkitRTCPeerConnection &&\n       !window.RTCIceGatherer)) {\n    // Chrome, Chromium, Webview, Opera.\n    // Version matches Chrome/WebRTC version.\n    // Chrome 74 removed webkitGetUserMedia on http as well so we need the\n    // more complicated fallback to webkitRTCPeerConnection.\n    result.browser = 'chrome';\n    result.version = extractVersion(navigator.userAgent,\n        /Chrom(e|ium)\\/(\\d+)\\./, 2);\n  } else if (window.RTCPeerConnection &&\n      navigator.userAgent.match(/AppleWebKit\\/(\\d+)\\./)) { // Safari.\n    result.browser = 'safari';\n    result.version = extractVersion(navigator.userAgent,\n        /AppleWebKit\\/(\\d+)\\./, 1);\n    result.supportsUnifiedPlan = window.RTCRtpTransceiver &&\n        'currentDirection' in window.RTCRtpTransceiver.prototype;\n  } else { // Default fallthrough: not supported.\n    result.browser = 'Not a supported browser.';\n    return result;\n  }\n\n  return result;\n}\n\n/**\n * Checks if something is an object.\n *\n * @param {*} val The something you want to check.\n * @return true if val is an object, false otherwise.\n */\nfunction isObject(val) {\n  return Object.prototype.toString.call(val) === '[object Object]';\n}\n\n/**\n * Remove all empty objects and undefined values\n * from a nested object -- an enhanced and vanilla version\n * of Lodash's `compact`.\n */\nexport function compactObject(data) {\n  if (!isObject(data)) {\n    return data;\n  }\n\n  return Object.keys(data).reduce(function(accumulator, key) {\n    const isObj = isObject(data[key]);\n    const value = isObj ? compactObject(data[key]) : data[key];\n    const isEmptyObject = isObj && !Object.keys(value).length;\n    if (value === undefined || isEmptyObject) {\n      return accumulator;\n    }\n    return Object.assign(accumulator, {[key]: value});\n  }, {});\n}\n\n/* iterates the stats graph recursively. */\nexport function walkStats(stats, base, resultSet) {\n  if (!base || resultSet.has(base.id)) {\n    return;\n  }\n  resultSet.set(base.id, base);\n  Object.keys(base).forEach(name => {\n    if (name.endsWith('Id')) {\n      walkStats(stats, stats.get(base[name]), resultSet);\n    } else if (name.endsWith('Ids')) {\n      base[name].forEach(id => {\n        walkStats(stats, stats.get(id), resultSet);\n      });\n    }\n  });\n}\n\n/* filter getStats for a sender/receiver track. */\nexport function filterStats(result, track, outbound) {\n  const streamStatsType = outbound ? 'outbound-rtp' : 'inbound-rtp';\n  const filteredResult = new Map();\n  if (track === null) {\n    return filteredResult;\n  }\n  const trackStats = [];\n  result.forEach(value => {\n    if (value.type === 'track' &&\n        value.trackIdentifier === track.id) {\n      trackStats.push(value);\n    }\n  });\n  trackStats.forEach(trackStat => {\n    result.forEach(stats => {\n      if (stats.type === streamStatsType && stats.trackId === trackStat.id) {\n        walkStats(result, stats, filteredResult);\n      }\n    });\n  });\n  return filteredResult;\n}\n\n","/*\n *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.\n *\n *  Use of this source code is governed by a BSD-style license\n *  that can be found in the LICENSE file in the root of the source\n *  tree.\n */\n/* eslint-env node */\n'use strict';\nimport * as utils from '../utils.js';\nconst logging = utils.log;\n\nexport function shimGetUserMedia(window, browserDetails) {\n  const navigator = window && window.navigator;\n\n  if (!navigator.mediaDevices) {\n    return;\n  }\n\n  const constraintsToChrome_ = function(c) {\n    if (typeof c !== 'object' || c.mandatory || c.optional) {\n      return c;\n    }\n    const cc = {};\n    Object.keys(c).forEach(key => {\n      if (key === 'require' || key === 'advanced' || key === 'mediaSource') {\n        return;\n      }\n      const r = (typeof c[key] === 'object') ? c[key] : {ideal: c[key]};\n      if (r.exact !== undefined && typeof r.exact === 'number') {\n        r.min = r.max = r.exact;\n      }\n      const oldname_ = function(prefix, name) {\n        if (prefix) {\n          return prefix + name.charAt(0).toUpperCase() + name.slice(1);\n        }\n        return (name === 'deviceId') ? 'sourceId' : name;\n      };\n      if (r.ideal !== undefined) {\n        cc.optional = cc.optional || [];\n        let oc = {};\n        if (typeof r.ideal === 'number') {\n          oc[oldname_('min', key)] = r.ideal;\n          cc.optional.push(oc);\n          oc = {};\n          oc[oldname_('max', key)] = r.ideal;\n          cc.optional.push(oc);\n        } else {\n          oc[oldname_('', key)] = r.ideal;\n          cc.optional.push(oc);\n        }\n      }\n      if (r.exact !== undefined && typeof r.exact !== 'number') {\n        cc.mandatory = cc.mandatory || {};\n        cc.mandatory[oldname_('', key)] = r.exact;\n      } else {\n        ['min', 'max'].forEach(mix => {\n          if (r[mix] !== undefined) {\n            cc.mandatory = cc.mandatory || {};\n            cc.mandatory[oldname_(mix, key)] = r[mix];\n          }\n        });\n      }\n    });\n    if (c.advanced) {\n      cc.optional = (cc.optional || []).concat(c.advanced);\n    }\n    return cc;\n  };\n\n  const shimConstraints_ = function(constraints, func) {\n    if (browserDetails.version >= 61) {\n      return func(constraints);\n    }\n    constraints = JSON.parse(JSON.stringify(constraints));\n    if (constraints && typeof constraints.audio === 'object') {\n      const remap = function(obj, a, b) {\n        if (a in obj && !(b in obj)) {\n          obj[b] = obj[a];\n          delete obj[a];\n        }\n      };\n      constraints = JSON.parse(JSON.stringify(constraints));\n      remap(constraints.audio, 'autoGainControl', 'googAutoGainControl');\n      remap(constraints.audio, 'noiseSuppression', 'googNoiseSuppression');\n      constraints.audio = constraintsToChrome_(constraints.audio);\n    }\n    if (constraints && typeof constraints.video === 'object') {\n      // Shim facingMode for mobile & surface pro.\n      let face = constraints.video.facingMode;\n      face = face && ((typeof face === 'object') ? face : {ideal: face});\n      const getSupportedFacingModeLies = browserDetails.version < 66;\n\n      if ((face && (face.exact === 'user' || face.exact === 'environment' ||\n                    face.ideal === 'user' || face.ideal === 'environment')) &&\n          !(navigator.mediaDevices.getSupportedConstraints &&\n            navigator.mediaDevices.getSupportedConstraints().facingMode &&\n            !getSupportedFacingModeLies)) {\n        delete constraints.video.facingMode;\n        let matches;\n        if (face.exact === 'environment' || face.ideal === 'environment') {\n          matches = ['back', 'rear'];\n        } else if (face.exact === 'user' || face.ideal === 'user') {\n          matches = ['front'];\n        }\n        if (matches) {\n          // Look for matches in label, or use last cam for back (typical).\n          return navigator.mediaDevices.enumerateDevices()\n          .then(devices => {\n            devices = devices.filter(d => d.kind === 'videoinput');\n            let dev = devices.find(d => matches.some(match =>\n              d.label.toLowerCase().includes(match)));\n            if (!dev && devices.length && matches.includes('back')) {\n              dev = devices[devices.length - 1]; // more likely the back cam\n            }\n            if (dev) {\n              constraints.video.deviceId = face.exact ? {exact: dev.deviceId} :\n                                                        {ideal: dev.deviceId};\n            }\n            constraints.video = constraintsToChrome_(constraints.video);\n            logging('chrome: ' + JSON.stringify(constraints));\n            return func(constraints);\n          });\n        }\n      }\n      constraints.video = constraintsToChrome_(constraints.video);\n    }\n    logging('chrome: ' + JSON.stringify(constraints));\n    return func(constraints);\n  };\n\n  const shimError_ = function(e) {\n    if (browserDetails.version >= 64) {\n      return e;\n    }\n    return {\n      name: {\n        PermissionDeniedError: 'NotAllowedError',\n        PermissionDismissedError: 'NotAllowedError',\n        InvalidStateError: 'NotAllowedError',\n        DevicesNotFoundError: 'NotFoundError',\n        ConstraintNotSatisfiedError: 'OverconstrainedError',\n        TrackStartError: 'NotReadableError',\n        MediaDeviceFailedDueToShutdown: 'NotAllowedError',\n        MediaDeviceKillSwitchOn: 'NotAllowedError',\n        TabCaptureError: 'AbortError',\n        ScreenCaptureError: 'AbortError',\n        DeviceCaptureError: 'AbortError'\n      }[e.name] || e.name,\n      message: e.message,\n      constraint: e.constraint || e.constraintName,\n      toString() {\n        return this.name + (this.message && ': ') + this.message;\n      }\n    };\n  };\n\n  const getUserMedia_ = function(constraints, onSuccess, onError) {\n    shimConstraints_(constraints, c => {\n      navigator.webkitGetUserMedia(c, onSuccess, e => {\n        if (onError) {\n          onError(shimError_(e));\n        }\n      });\n    });\n  };\n  navigator.getUserMedia = getUserMedia_.bind(navigator);\n\n  // Even though Chrome 45 has navigator.mediaDevices and a getUserMedia\n  // function which returns a Promise, it does not accept spec-style\n  // constraints.\n  if (navigator.mediaDevices.getUserMedia) {\n    const origGetUserMedia = navigator.mediaDevices.getUserMedia.\n        bind(navigator.mediaDevices);\n    navigator.mediaDevices.getUserMedia = function(cs) {\n      return shimConstraints_(cs, c => origGetUserMedia(c).then(stream => {\n        if (c.audio && !stream.getAudioTracks().length ||\n            c.video && !stream.getVideoTracks().length) {\n          stream.getTracks().forEach(track => {\n            track.stop();\n          });\n          throw new DOMException('', 'NotFoundError');\n        }\n        return stream;\n      }, e => Promise.reject(shimError_(e))));\n    };\n  }\n}\n","/*\n *  Copyright (c) 2018 The adapter.js project authors. All Rights Reserved.\n *\n *  Use of this source code is governed by a BSD-style license\n *  that can be found in the LICENSE file in the root of the source\n *  tree.\n */\n/* eslint-env node */\n'use strict';\nexport function shimGetDisplayMedia(window, getSourceId) {\n  if (window.navigator.mediaDevices &&\n    'getDisplayMedia' in window.navigator.mediaDevices) {\n    return;\n  }\n  if (!(window.navigator.mediaDevices)) {\n    return;\n  }\n  // getSourceId is a function that returns a promise resolving with\n  // the sourceId of the screen/window/tab to be shared.\n  if (typeof getSourceId !== 'function') {\n    console.error('shimGetDisplayMedia: getSourceId argument is not ' +\n        'a function');\n    return;\n  }\n  window.navigator.mediaDevices.getDisplayMedia =\n    function getDisplayMedia(constraints) {\n      return getSourceId(constraints)\n        .then(sourceId => {\n          const widthSpecified = constraints.video && constraints.video.width;\n          const heightSpecified = constraints.video &&\n            constraints.video.height;\n          const frameRateSpecified = constraints.video &&\n            constraints.video.frameRate;\n          constraints.video = {\n            mandatory: {\n              chromeMediaSource: 'desktop',\n              chromeMediaSourceId: sourceId,\n              maxFrameRate: frameRateSpecified || 3\n            }\n          };\n          if (widthSpecified) {\n            constraints.video.mandatory.maxWidth = widthSpecified;\n          }\n          if (heightSpecified) {\n            constraints.video.mandatory.maxHeight = heightSpecified;\n          }\n          return window.navigator.mediaDevices.getUserMedia(constraints);\n        });\n    };\n}\n","/*\n *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.\n *\n *  Use of this source code is governed by a BSD-style license\n *  that can be found in the LICENSE file in the root of the source\n *  tree.\n */\n /* eslint-env node */\n'use strict';\nimport * as utils from '../utils.js';\n\nexport {shimGetUserMedia} from './getusermedia';\nexport {shimGetDisplayMedia} from './getdisplaymedia';\n\nexport function shimMediaStream(window) {\n  window.MediaStream = window.MediaStream || window.webkitMediaStream;\n}\n\nexport function shimOnTrack(window) {\n  if (typeof window === 'object' && window.RTCPeerConnection && !('ontrack' in\n      window.RTCPeerConnection.prototype)) {\n    Object.defineProperty(window.RTCPeerConnection.prototype, 'ontrack', {\n      get() {\n        return this._ontrack;\n      },\n      set(f) {\n        if (this._ontrack) {\n          this.removeEventListener('track', this._ontrack);\n        }\n        this.addEventListener('track', this._ontrack = f);\n      },\n      enumerable: true,\n      configurable: true\n    });\n    const origSetRemoteDescription =\n        window.RTCPeerConnection.prototype.setRemoteDescription;\n    window.RTCPeerConnection.prototype.setRemoteDescription =\n      function setRemoteDescription() {\n        if (!this._ontrackpoly) {\n          this._ontrackpoly = (e) => {\n            // onaddstream does not fire when a track is added to an existing\n            // stream. But stream.onaddtrack is implemented so we use that.\n            e.stream.addEventListener('addtrack', te => {\n              let receiver;\n              if (window.RTCPeerConnection.prototype.getReceivers) {\n                receiver = this.getReceivers()\n                  .find(r => r.track && r.track.id === te.track.id);\n              } else {\n                receiver = {track: te.track};\n              }\n\n              const event = new Event('track');\n              event.track = te.track;\n              event.receiver = receiver;\n              event.transceiver = {receiver};\n              event.streams = [e.stream];\n              this.dispatchEvent(event);\n            });\n            e.stream.getTracks().forEach(track => {\n              let receiver;\n              if (window.RTCPeerConnection.prototype.getReceivers) {\n                receiver = this.getReceivers()\n                  .find(r => r.track && r.track.id === track.id);\n              } else {\n                receiver = {track};\n              }\n              const event = new Event('track');\n              event.track = track;\n              event.receiver = receiver;\n              event.transceiver = {receiver};\n              event.streams = [e.stream];\n              this.dispatchEvent(event);\n            });\n          };\n          this.addEventListener('addstream', this._ontrackpoly);\n        }\n        return origSetRemoteDescription.apply(this, arguments);\n      };\n  } else {\n    // even if RTCRtpTransceiver is in window, it is only used and\n    // emitted in unified-plan. Unfortunately this means we need\n    // to unconditionally wrap the event.\n    utils.wrapPeerConnectionEvent(window, 'track', e => {\n      if (!e.transceiver) {\n        Object.defineProperty(e, 'transceiver',\n          {value: {receiver: e.receiver}});\n      }\n      return e;\n    });\n  }\n}\n\nexport function shimGetSendersWithDtmf(window) {\n  // Overrides addTrack/removeTrack, depends on shimAddTrackRemoveTrack.\n  if (typeof window === 'object' && window.RTCPeerConnection &&\n      !('getSenders' in window.RTCPeerConnection.prototype) &&\n      'createDTMFSender' in window.RTCPeerConnection.prototype) {\n    const shimSenderWithDtmf = function(pc, track) {\n      return {\n        track,\n        get dtmf() {\n          if (this._dtmf === undefined) {\n            if (track.kind === 'audio') {\n              this._dtmf = pc.createDTMFSender(track);\n            } else {\n              this._dtmf = null;\n            }\n          }\n          return this._dtmf;\n        },\n        _pc: pc\n      };\n    };\n\n    // augment addTrack when getSenders is not available.\n    if (!window.RTCPeerConnection.prototype.getSenders) {\n      window.RTCPeerConnection.prototype.getSenders = function getSenders() {\n        this._senders = this._senders || [];\n        return this._senders.slice(); // return a copy of the internal state.\n      };\n      const origAddTrack = window.RTCPeerConnection.prototype.addTrack;\n      window.RTCPeerConnection.prototype.addTrack =\n        function addTrack(track, stream) {\n          let sender = origAddTrack.apply(this, arguments);\n          if (!sender) {\n            sender = shimSenderWithDtmf(this, track);\n            this._senders.push(sender);\n          }\n          return sender;\n        };\n\n      const origRemoveTrack = window.RTCPeerConnection.prototype.removeTrack;\n      window.RTCPeerConnection.prototype.removeTrack =\n        function removeTrack(sender) {\n          origRemoveTrack.apply(this, arguments);\n          const idx = this._senders.indexOf(sender);\n          if (idx !== -1) {\n            this._senders.splice(idx, 1);\n          }\n        };\n    }\n    const origAddStream = window.RTCPeerConnection.prototype.addStream;\n    window.RTCPeerConnection.prototype.addStream = function addStream(stream) {\n      this._senders = this._senders || [];\n      origAddStream.apply(this, [stream]);\n      stream.getTracks().forEach(track => {\n        this._senders.push(shimSenderWithDtmf(this, track));\n      });\n    };\n\n    const origRemoveStream = window.RTCPeerConnection.prototype.removeStream;\n    window.RTCPeerConnection.prototype.removeStream =\n      function removeStream(stream) {\n        this._senders = this._senders || [];\n        origRemoveStream.apply(this, [stream]);\n\n        stream.getTracks().forEach(track => {\n          const sender = this._senders.find(s => s.track === track);\n          if (sender) { // remove sender\n            this._senders.splice(this._senders.indexOf(sender), 1);\n          }\n        });\n      };\n  } else if (typeof window === 'object' && window.RTCPeerConnection &&\n             'getSenders' in window.RTCPeerConnection.prototype &&\n             'createDTMFSender' in window.RTCPeerConnection.prototype &&\n             window.RTCRtpSender &&\n             !('dtmf' in window.RTCRtpSender.prototype)) {\n    const origGetSenders = window.RTCPeerConnection.prototype.getSenders;\n    window.RTCPeerConnection.prototype.getSenders = function getSenders() {\n      const senders = origGetSenders.apply(this, []);\n      senders.forEach(sender => sender._pc = this);\n      return senders;\n    };\n\n    Object.defineProperty(window.RTCRtpSender.prototype, 'dtmf', {\n      get() {\n        if (this._dtmf === undefined) {\n          if (this.track.kind === 'audio') {\n            this._dtmf = this._pc.createDTMFSender(this.track);\n          } else {\n            this._dtmf = null;\n          }\n        }\n        return this._dtmf;\n      }\n    });\n  }\n}\n\nexport function shimGetStats(window) {\n  if (!window.RTCPeerConnection) {\n    return;\n  }\n\n  const origGetStats = window.RTCPeerConnection.prototype.getStats;\n  window.RTCPeerConnection.prototype.getStats = function getStats() {\n    const [selector, onSucc, onErr] = arguments;\n\n    // If selector is a function then we are in the old style stats so just\n    // pass back the original getStats format to avoid breaking old users.\n    if (arguments.length > 0 && typeof selector === 'function') {\n      return origGetStats.apply(this, arguments);\n    }\n\n    // When spec-style getStats is supported, return those when called with\n    // either no arguments or the selector argument is null.\n    if (origGetStats.length === 0 && (arguments.length === 0 ||\n        typeof selector !== 'function')) {\n      return origGetStats.apply(this, []);\n    }\n\n    const fixChromeStats_ = function(response) {\n      const standardReport = {};\n      const reports = response.result();\n      reports.forEach(report => {\n        const standardStats = {\n          id: report.id,\n          timestamp: report.timestamp,\n          type: {\n            localcandidate: 'local-candidate',\n            remotecandidate: 'remote-candidate'\n          }[report.type] || report.type\n        };\n        report.names().forEach(name => {\n          standardStats[name] = report.stat(name);\n        });\n        standardReport[standardStats.id] = standardStats;\n      });\n\n      return standardReport;\n    };\n\n    // shim getStats with maplike support\n    const makeMapStats = function(stats) {\n      return new Map(Object.keys(stats).map(key => [key, stats[key]]));\n    };\n\n    if (arguments.length >= 2) {\n      const successCallbackWrapper_ = function(response) {\n        onSucc(makeMapStats(fixChromeStats_(response)));\n      };\n\n      return origGetStats.apply(this, [successCallbackWrapper_,\n        selector]);\n    }\n\n    // promise-support\n    return new Promise((resolve, reject) => {\n      origGetStats.apply(this, [\n        function(response) {\n          resolve(makeMapStats(fixChromeStats_(response)));\n        }, reject]);\n    }).then(onSucc, onErr);\n  };\n}\n\nexport function shimSenderReceiverGetStats(window) {\n  if (!(typeof window === 'object' && window.RTCPeerConnection &&\n      window.RTCRtpSender && window.RTCRtpReceiver)) {\n    return;\n  }\n\n  // shim sender stats.\n  if (!('getStats' in window.RTCRtpSender.prototype)) {\n    const origGetSenders = window.RTCPeerConnection.prototype.getSenders;\n    if (origGetSenders) {\n      window.RTCPeerConnection.prototype.getSenders = function getSenders() {\n        const senders = origGetSenders.apply(this, []);\n        senders.forEach(sender => sender._pc = this);\n        return senders;\n      };\n    }\n\n    const origAddTrack = window.RTCPeerConnection.prototype.addTrack;\n    if (origAddTrack) {\n      window.RTCPeerConnection.prototype.addTrack = function addTrack() {\n        const sender = origAddTrack.apply(this, arguments);\n        sender._pc = this;\n        return sender;\n      };\n    }\n    window.RTCRtpSender.prototype.getStats = function getStats() {\n      const sender = this;\n      return this._pc.getStats().then(result =>\n        /* Note: this will include stats of all senders that\n         *   send a track with the same id as sender.track as\n         *   it is not possible to identify the RTCRtpSender.\n         */\n        utils.filterStats(result, sender.track, true));\n    };\n  }\n\n  // shim receiver stats.\n  if (!('getStats' in window.RTCRtpReceiver.prototype)) {\n    const origGetReceivers = window.RTCPeerConnection.prototype.getReceivers;\n    if (origGetReceivers) {\n      window.RTCPeerConnection.prototype.getReceivers =\n        function getReceivers() {\n          const receivers = origGetReceivers.apply(this, []);\n          receivers.forEach(receiver => receiver._pc = this);\n          return receivers;\n        };\n    }\n    utils.wrapPeerConnectionEvent(window, 'track', e => {\n      e.receiver._pc = e.srcElement;\n      return e;\n    });\n    window.RTCRtpReceiver.prototype.getStats = function getStats() {\n      const receiver = this;\n      return this._pc.getStats().then(result =>\n        utils.filterStats(result, receiver.track, false));\n    };\n  }\n\n  if (!('getStats' in window.RTCRtpSender.prototype &&\n      'getStats' in window.RTCRtpReceiver.prototype)) {\n    return;\n  }\n\n  // shim RTCPeerConnection.getStats(track).\n  const origGetStats = window.RTCPeerConnection.prototype.getStats;\n  window.RTCPeerConnection.prototype.getStats = function getStats() {\n    if (arguments.length > 0 &&\n        arguments[0] instanceof window.MediaStreamTrack) {\n      const track = arguments[0];\n      let sender;\n      let receiver;\n      let err;\n      this.getSenders().forEach(s => {\n        if (s.track === track) {\n          if (sender) {\n            err = true;\n          } else {\n            sender = s;\n          }\n        }\n      });\n      this.getReceivers().forEach(r => {\n        if (r.track === track) {\n          if (receiver) {\n            err = true;\n          } else {\n            receiver = r;\n          }\n        }\n        return r.track === track;\n      });\n      if (err || (sender && receiver)) {\n        return Promise.reject(new DOMException(\n          'There are more than one sender or receiver for the track.',\n          'InvalidAccessError'));\n      } else if (sender) {\n        return sender.getStats();\n      } else if (receiver) {\n        return receiver.getStats();\n      }\n      return Promise.reject(new DOMException(\n        'There is no sender or receiver for the track.',\n        'InvalidAccessError'));\n    }\n    return origGetStats.apply(this, arguments);\n  };\n}\n\nexport function shimAddTrackRemoveTrackWithNative(window) {\n  // shim addTrack/removeTrack with native variants in order to make\n  // the interactions with legacy getLocalStreams behave as in other browsers.\n  // Keeps a mapping stream.id => [stream, rtpsenders...]\n  window.RTCPeerConnection.prototype.getLocalStreams =\n    function getLocalStreams() {\n      this._shimmedLocalStreams = this._shimmedLocalStreams || {};\n      return Object.keys(this._shimmedLocalStreams)\n        .map(streamId => this._shimmedLocalStreams[streamId][0]);\n    };\n\n  const origAddTrack = window.RTCPeerConnection.prototype.addTrack;\n  window.RTCPeerConnection.prototype.addTrack =\n    function addTrack(track, stream) {\n      if (!stream) {\n        return origAddTrack.apply(this, arguments);\n      }\n      this._shimmedLocalStreams = this._shimmedLocalStreams || {};\n\n      const sender = origAddTrack.apply(this, arguments);\n      if (!this._shimmedLocalStreams[stream.id]) {\n        this._shimmedLocalStreams[stream.id] = [stream, sender];\n      } else if (this._shimmedLocalStreams[stream.id].indexOf(sender) === -1) {\n        this._shimmedLocalStreams[stream.id].push(sender);\n      }\n      return sender;\n    };\n\n  const origAddStream = window.RTCPeerConnection.prototype.addStream;\n  window.RTCPeerConnection.prototype.addStream = function addStream(stream) {\n    this._shimmedLocalStreams = this._shimmedLocalStreams || {};\n\n    stream.getTracks().forEach(track => {\n      const alreadyExists = this.getSenders().find(s => s.track === track);\n      if (alreadyExists) {\n        throw new DOMException('Track already exists.',\n            'InvalidAccessError');\n      }\n    });\n    const existingSenders = this.getSenders();\n    origAddStream.apply(this, arguments);\n    const newSenders = this.getSenders()\n      .filter(newSender => existingSenders.indexOf(newSender) === -1);\n    this._shimmedLocalStreams[stream.id] = [stream].concat(newSenders);\n  };\n\n  const origRemoveStream = window.RTCPeerConnection.prototype.removeStream;\n  window.RTCPeerConnection.prototype.removeStream =\n    function removeStream(stream) {\n      this._shimmedLocalStreams = this._shimmedLocalStreams || {};\n      delete this._shimmedLocalStreams[stream.id];\n      return origRemoveStream.apply(this, arguments);\n    };\n\n  const origRemoveTrack = window.RTCPeerConnection.prototype.removeTrack;\n  window.RTCPeerConnection.prototype.removeTrack =\n    function removeTrack(sender) {\n      this._shimmedLocalStreams = this._shimmedLocalStreams || {};\n      if (sender) {\n        Object.keys(this._shimmedLocalStreams).forEach(streamId => {\n          const idx = this._shimmedLocalStreams[streamId].indexOf(sender);\n          if (idx !== -1) {\n            this._shimmedLocalStreams[streamId].splice(idx, 1);\n          }\n          if (this._shimmedLocalStreams[streamId].length === 1) {\n            delete this._shimmedLocalStreams[streamId];\n          }\n        });\n      }\n      return origRemoveTrack.apply(this, arguments);\n    };\n}\n\nexport function shimAddTrackRemoveTrack(window, browserDetails) {\n  if (!window.RTCPeerConnection) {\n    return;\n  }\n  // shim addTrack and removeTrack.\n  if (window.RTCPeerConnection.prototype.addTrack &&\n      browserDetails.version >= 65) {\n    return shimAddTrackRemoveTrackWithNative(window);\n  }\n\n  // also shim pc.getLocalStreams when addTrack is shimmed\n  // to return the original streams.\n  const origGetLocalStreams = window.RTCPeerConnection.prototype\n      .getLocalStreams;\n  window.RTCPeerConnection.prototype.getLocalStreams =\n    function getLocalStreams() {\n      const nativeStreams = origGetLocalStreams.apply(this);\n      this._reverseStreams = this._reverseStreams || {};\n      return nativeStreams.map(stream => this._reverseStreams[stream.id]);\n    };\n\n  const origAddStream = window.RTCPeerConnection.prototype.addStream;\n  window.RTCPeerConnection.prototype.addStream = function addStream(stream) {\n    this._streams = this._streams || {};\n    this._reverseStreams = this._reverseStreams || {};\n\n    stream.getTracks().forEach(track => {\n      const alreadyExists = this.getSenders().find(s => s.track === track);\n      if (alreadyExists) {\n        throw new DOMException('Track already exists.',\n            'InvalidAccessError');\n      }\n    });\n    // Add identity mapping for consistency with addTrack.\n    // Unless this is being used with a stream from addTrack.\n    if (!this._reverseStreams[stream.id]) {\n      const newStream = new window.MediaStream(stream.getTracks());\n      this._streams[stream.id] = newStream;\n      this._reverseStreams[newStream.id] = stream;\n      stream = newStream;\n    }\n    origAddStream.apply(this, [stream]);\n  };\n\n  const origRemoveStream = window.RTCPeerConnection.prototype.removeStream;\n  window.RTCPeerConnection.prototype.removeStream =\n    function removeStream(stream) {\n      this._streams = this._streams || {};\n      this._reverseStreams = this._reverseStreams || {};\n\n      origRemoveStream.apply(this, [(this._streams[stream.id] || stream)]);\n      delete this._reverseStreams[(this._streams[stream.id] ?\n          this._streams[stream.id].id : stream.id)];\n      delete this._streams[stream.id];\n    };\n\n  window.RTCPeerConnection.prototype.addTrack =\n    function addTrack(track, stream) {\n      if (this.signalingState === 'closed') {\n        throw new DOMException(\n          'The RTCPeerConnection\\'s signalingState is \\'closed\\'.',\n          'InvalidStateError');\n      }\n      const streams = [].slice.call(arguments, 1);\n      if (streams.length !== 1 ||\n          !streams[0].getTracks().find(t => t === track)) {\n        // this is not fully correct but all we can manage without\n        // [[associated MediaStreams]] internal slot.\n        throw new DOMException(\n          'The adapter.js addTrack polyfill only supports a single ' +\n          ' stream which is associated with the specified track.',\n          'NotSupportedError');\n      }\n\n      const alreadyExists = this.getSenders().find(s => s.track === track);\n      if (alreadyExists) {\n        throw new DOMException('Track already exists.',\n            'InvalidAccessError');\n      }\n\n      this._streams = this._streams || {};\n      this._reverseStreams = this._reverseStreams || {};\n      const oldStream = this._streams[stream.id];\n      if (oldStream) {\n        // this is using odd Chrome behaviour, use with caution:\n        // https://bugs.chromium.org/p/webrtc/issues/detail?id=7815\n        // Note: we rely on the high-level addTrack/dtmf shim to\n        // create the sender with a dtmf sender.\n        oldStream.addTrack(track);\n\n        // Trigger ONN async.\n        Promise.resolve().then(() => {\n          this.dispatchEvent(new Event('negotiationneeded'));\n        });\n      } else {\n        const newStream = new window.MediaStream([track]);\n        this._streams[stream.id] = newStream;\n        this._reverseStreams[newStream.id] = stream;\n        this.addStream(newStream);\n      }\n      return this.getSenders().find(s => s.track === track);\n    };\n\n  // replace the internal stream id with the external one and\n  // vice versa.\n  function replaceInternalStreamId(pc, description) {\n    let sdp = description.sdp;\n    Object.keys(pc._reverseStreams || []).forEach(internalId => {\n      const externalStream = pc._reverseStreams[internalId];\n      const internalStream = pc._streams[externalStream.id];\n      sdp = sdp.replace(new RegExp(internalStream.id, 'g'),\n          externalStream.id);\n    });\n    return new RTCSessionDescription({\n      type: description.type,\n      sdp\n    });\n  }\n  function replaceExternalStreamId(pc, description) {\n    let sdp = description.sdp;\n    Object.keys(pc._reverseStreams || []).forEach(internalId => {\n      const externalStream = pc._reverseStreams[internalId];\n      const internalStream = pc._streams[externalStream.id];\n      sdp = sdp.replace(new RegExp(externalStream.id, 'g'),\n          internalStream.id);\n    });\n    return new RTCSessionDescription({\n      type: description.type,\n      sdp\n    });\n  }\n  ['createOffer', 'createAnswer'].forEach(function(method) {\n    const nativeMethod = window.RTCPeerConnection.prototype[method];\n    const methodObj = {[method]() {\n      const args = arguments;\n      const isLegacyCall = arguments.length &&\n          typeof arguments[0] === 'function';\n      if (isLegacyCall) {\n        return nativeMethod.apply(this, [\n          (description) => {\n            const desc = replaceInternalStreamId(this, description);\n            args[0].apply(null, [desc]);\n          },\n          (err) => {\n            if (args[1]) {\n              args[1].apply(null, err);\n            }\n          }, arguments[2]\n        ]);\n      }\n      return nativeMethod.apply(this, arguments)\n      .then(description => replaceInternalStreamId(this, description));\n    }};\n    window.RTCPeerConnection.prototype[method] = methodObj[method];\n  });\n\n  const origSetLocalDescription =\n      window.RTCPeerConnection.prototype.setLocalDescription;\n  window.RTCPeerConnection.prototype.setLocalDescription =\n    function setLocalDescription() {\n      if (!arguments.length || !arguments[0].type) {\n        return origSetLocalDescription.apply(this, arguments);\n      }\n      arguments[0] = replaceExternalStreamId(this, arguments[0]);\n      return origSetLocalDescription.apply(this, arguments);\n    };\n\n  // TODO: mangle getStats: https://w3c.github.io/webrtc-stats/#dom-rtcmediastreamstats-streamidentifier\n\n  const origLocalDescription = Object.getOwnPropertyDescriptor(\n      window.RTCPeerConnection.prototype, 'localDescription');\n  Object.defineProperty(window.RTCPeerConnection.prototype,\n      'localDescription', {\n        get() {\n          const description = origLocalDescription.get.apply(this);\n          if (description.type === '') {\n            return description;\n          }\n          return replaceInternalStreamId(this, description);\n        }\n      });\n\n  window.RTCPeerConnection.prototype.removeTrack =\n    function removeTrack(sender) {\n      if (this.signalingState === 'closed') {\n        throw new DOMException(\n          'The RTCPeerConnection\\'s signalingState is \\'closed\\'.',\n          'InvalidStateError');\n      }\n      // We can not yet check for sender instanceof RTCRtpSender\n      // since we shim RTPSender. So we check if sender._pc is set.\n      if (!sender._pc) {\n        throw new DOMException('Argument 1 of RTCPeerConnection.removeTrack ' +\n            'does not implement interface RTCRtpSender.', 'TypeError');\n      }\n      const isLocal = sender._pc === this;\n      if (!isLocal) {\n        throw new DOMException('Sender was not created by this connection.',\n            'InvalidAccessError');\n      }\n\n      // Search for the native stream the senders track belongs to.\n      this._streams = this._streams || {};\n      let stream;\n      Object.keys(this._streams).forEach(streamid => {\n        const hasTrack = this._streams[streamid].getTracks()\n          .find(track => sender.track === track);\n        if (hasTrack) {\n          stream = this._streams[streamid];\n        }\n      });\n\n      if (stream) {\n        if (stream.getTracks().length === 1) {\n          // if this is the last track of the stream, remove the stream. This\n          // takes care of any shimmed _senders.\n          this.removeStream(this._reverseStreams[stream.id]);\n        } else {\n          // relying on the same odd chrome behaviour as above.\n          stream.removeTrack(sender.track);\n        }\n        this.dispatchEvent(new Event('negotiationneeded'));\n      }\n    };\n}\n\nexport function shimPeerConnection(window, browserDetails) {\n  if (!window.RTCPeerConnection && window.webkitRTCPeerConnection) {\n    // very basic support for old versions.\n    window.RTCPeerConnection = window.webkitRTCPeerConnection;\n  }\n  if (!window.RTCPeerConnection) {\n    return;\n  }\n\n  // shim implicit creation of RTCSessionDescription/RTCIceCandidate\n  if (browserDetails.version < 53) {\n    ['setLocalDescription', 'setRemoteDescription', 'addIceCandidate']\n        .forEach(function(method) {\n          const nativeMethod = window.RTCPeerConnection.prototype[method];\n          const methodObj = {[method]() {\n            arguments[0] = new ((method === 'addIceCandidate') ?\n                window.RTCIceCandidate :\n                window.RTCSessionDescription)(arguments[0]);\n            return nativeMethod.apply(this, arguments);\n          }};\n          window.RTCPeerConnection.prototype[method] = methodObj[method];\n        });\n  }\n}\n\n// Attempt to fix ONN in plan-b mode.\nexport function fixNegotiationNeeded(window, browserDetails) {\n  utils.wrapPeerConnectionEvent(window, 'negotiationneeded', e => {\n    const pc = e.target;\n    if (browserDetails.version < 72 || (pc.getConfiguration &&\n        pc.getConfiguration().sdpSemantics === 'plan-b')) {\n      if (pc.signalingState !== 'stable') {\n        return;\n      }\n    }\n    return e;\n  });\n}\n","/*\n *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.\n *\n *  Use of this source code is governed by a BSD-style license\n *  that can be found in the LICENSE file in the root of the source\n *  tree.\n */\n/* eslint-env node */\n'use strict';\n\nimport * as utils from '../utils';\n\nexport function shimGetUserMedia(window, browserDetails) {\n  const navigator = window && window.navigator;\n  const MediaStreamTrack = window && window.MediaStreamTrack;\n\n  navigator.getUserMedia = function(constraints, onSuccess, onError) {\n    // Replace Firefox 44+'s deprecation warning with unprefixed version.\n    utils.deprecated('navigator.getUserMedia',\n        'navigator.mediaDevices.getUserMedia');\n    navigator.mediaDevices.getUserMedia(constraints).then(onSuccess, onError);\n  };\n\n  if (!(browserDetails.version > 55 &&\n      'autoGainControl' in navigator.mediaDevices.getSupportedConstraints())) {\n    const remap = function(obj, a, b) {\n      if (a in obj && !(b in obj)) {\n        obj[b] = obj[a];\n        delete obj[a];\n      }\n    };\n\n    const nativeGetUserMedia = navigator.mediaDevices.getUserMedia.\n        bind(navigator.mediaDevices);\n    navigator.mediaDevices.getUserMedia = function(c) {\n      if (typeof c === 'object' && typeof c.audio === 'object') {\n        c = JSON.parse(JSON.stringify(c));\n        remap(c.audio, 'autoGainControl', 'mozAutoGainControl');\n        remap(c.audio, 'noiseSuppression', 'mozNoiseSuppression');\n      }\n      return nativeGetUserMedia(c);\n    };\n\n    if (MediaStreamTrack && MediaStreamTrack.prototype.getSettings) {\n      const nativeGetSettings = MediaStreamTrack.prototype.getSettings;\n      MediaStreamTrack.prototype.getSettings = function() {\n        const obj = nativeGetSettings.apply(this, arguments);\n        remap(obj, 'mozAutoGainControl', 'autoGainControl');\n        remap(obj, 'mozNoiseSuppression', 'noiseSuppression');\n        return obj;\n      };\n    }\n\n    if (MediaStreamTrack && MediaStreamTrack.prototype.applyConstraints) {\n      const nativeApplyConstraints =\n        MediaStreamTrack.prototype.applyConstraints;\n      MediaStreamTrack.prototype.applyConstraints = function(c) {\n        if (this.kind === 'audio' && typeof c === 'object') {\n          c = JSON.parse(JSON.stringify(c));\n          remap(c, 'autoGainControl', 'mozAutoGainControl');\n          remap(c, 'noiseSuppression', 'mozNoiseSuppression');\n        }\n        return nativeApplyConstraints.apply(this, [c]);\n      };\n    }\n  }\n}\n","/*\n *  Copyright (c) 2018 The adapter.js project authors. All Rights Reserved.\n *\n *  Use of this source code is governed by a BSD-style license\n *  that can be found in the LICENSE file in the root of the source\n *  tree.\n */\n/* eslint-env node */\n'use strict';\n\nexport function shimGetDisplayMedia(window, preferredMediaSource) {\n  if (window.navigator.mediaDevices &&\n    'getDisplayMedia' in window.navigator.mediaDevices) {\n    return;\n  }\n  if (!(window.navigator.mediaDevices)) {\n    return;\n  }\n  window.navigator.mediaDevices.getDisplayMedia =\n    function getDisplayMedia(constraints) {\n      if (!(constraints && constraints.video)) {\n        const err = new DOMException('getDisplayMedia without video ' +\n            'constraints is undefined');\n        err.name = 'NotFoundError';\n        // from https://heycam.github.io/webidl/#idl-DOMException-error-names\n        err.code = 8;\n        return Promise.reject(err);\n      }\n      if (constraints.video === true) {\n        constraints.video = {mediaSource: preferredMediaSource};\n      } else {\n        constraints.video.mediaSource = preferredMediaSource;\n      }\n      return window.navigator.mediaDevices.getUserMedia(constraints);\n    };\n}\n","/*\n *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.\n *\n *  Use of this source code is governed by a BSD-style license\n *  that can be found in the LICENSE file in the root of the source\n *  tree.\n */\n/* eslint-env node */\n'use strict';\n\nimport * as utils from '../utils';\nexport {shimGetUserMedia} from './getusermedia';\nexport {shimGetDisplayMedia} from './getdisplaymedia';\n\nexport function shimOnTrack(window) {\n  if (typeof window === 'object' && window.RTCTrackEvent &&\n      ('receiver' in window.RTCTrackEvent.prototype) &&\n      !('transceiver' in window.RTCTrackEvent.prototype)) {\n    Object.defineProperty(window.RTCTrackEvent.prototype, 'transceiver', {\n      get() {\n        return {receiver: this.receiver};\n      }\n    });\n  }\n}\n\nexport function shimPeerConnection(window, browserDetails) {\n  if (typeof window !== 'object' ||\n      !(window.RTCPeerConnection || window.mozRTCPeerConnection)) {\n    return; // probably media.peerconnection.enabled=false in about:config\n  }\n  if (!window.RTCPeerConnection && window.mozRTCPeerConnection) {\n    // very basic support for old versions.\n    window.RTCPeerConnection = window.mozRTCPeerConnection;\n  }\n\n  if (browserDetails.version < 53) {\n    // shim away need for obsolete RTCIceCandidate/RTCSessionDescription.\n    ['setLocalDescription', 'setRemoteDescription', 'addIceCandidate']\n        .forEach(function(method) {\n          const nativeMethod = window.RTCPeerConnection.prototype[method];\n          const methodObj = {[method]() {\n            arguments[0] = new ((method === 'addIceCandidate') ?\n                window.RTCIceCandidate :\n                window.RTCSessionDescription)(arguments[0]);\n            return nativeMethod.apply(this, arguments);\n          }};\n          window.RTCPeerConnection.prototype[method] = methodObj[method];\n        });\n  }\n\n  const modernStatsTypes = {\n    inboundrtp: 'inbound-rtp',\n    outboundrtp: 'outbound-rtp',\n    candidatepair: 'candidate-pair',\n    localcandidate: 'local-candidate',\n    remotecandidate: 'remote-candidate'\n  };\n\n  const nativeGetStats = window.RTCPeerConnection.prototype.getStats;\n  window.RTCPeerConnection.prototype.getStats = function getStats() {\n    const [selector, onSucc, onErr] = arguments;\n    return nativeGetStats.apply(this, [selector || null])\n      .then(stats => {\n        if (browserDetails.version < 53 && !onSucc) {\n          // Shim only promise getStats with spec-hyphens in type names\n          // Leave callback version alone; misc old uses of forEach before Map\n          try {\n            stats.forEach(stat => {\n              stat.type = modernStatsTypes[stat.type] || stat.type;\n            });\n          } catch (e) {\n            if (e.name !== 'TypeError') {\n              throw e;\n            }\n            // Avoid TypeError: \"type\" is read-only, in old versions. 34-43ish\n            stats.forEach((stat, i) => {\n              stats.set(i, Object.assign({}, stat, {\n                type: modernStatsTypes[stat.type] || stat.type\n              }));\n            });\n          }\n        }\n        return stats;\n      })\n      .then(onSucc, onErr);\n  };\n}\n\nexport function shimSenderGetStats(window) {\n  if (!(typeof window === 'object' && window.RTCPeerConnection &&\n      window.RTCRtpSender)) {\n    return;\n  }\n  if (window.RTCRtpSender && 'getStats' in window.RTCRtpSender.prototype) {\n    return;\n  }\n  const origGetSenders = window.RTCPeerConnection.prototype.getSenders;\n  if (origGetSenders) {\n    window.RTCPeerConnection.prototype.getSenders = function getSenders() {\n      const senders = origGetSenders.apply(this, []);\n      senders.forEach(sender => sender._pc = this);\n      return senders;\n    };\n  }\n\n  const origAddTrack = window.RTCPeerConnection.prototype.addTrack;\n  if (origAddTrack) {\n    window.RTCPeerConnection.prototype.addTrack = function addTrack() {\n      const sender = origAddTrack.apply(this, arguments);\n      sender._pc = this;\n      return sender;\n    };\n  }\n  window.RTCRtpSender.prototype.getStats = function getStats() {\n    return this.track ? this._pc.getStats(this.track) :\n        Promise.resolve(new Map());\n  };\n}\n\nexport function shimReceiverGetStats(window) {\n  if (!(typeof window === 'object' && window.RTCPeerConnection &&\n      window.RTCRtpSender)) {\n    return;\n  }\n  if (window.RTCRtpSender && 'getStats' in window.RTCRtpReceiver.prototype) {\n    return;\n  }\n  const origGetReceivers = window.RTCPeerConnection.prototype.getReceivers;\n  if (origGetReceivers) {\n    window.RTCPeerConnection.prototype.getReceivers = function getReceivers() {\n      const receivers = origGetReceivers.apply(this, []);\n      receivers.forEach(receiver => receiver._pc = this);\n      return receivers;\n    };\n  }\n  utils.wrapPeerConnectionEvent(window, 'track', e => {\n    e.receiver._pc = e.srcElement;\n    return e;\n  });\n  window.RTCRtpReceiver.prototype.getStats = function getStats() {\n    return this._pc.getStats(this.track);\n  };\n}\n\nexport function shimRemoveStream(window) {\n  if (!window.RTCPeerConnection ||\n      'removeStream' in window.RTCPeerConnection.prototype) {\n    return;\n  }\n  window.RTCPeerConnection.prototype.removeStream =\n    function removeStream(stream) {\n      utils.deprecated('removeStream', 'removeTrack');\n      this.getSenders().forEach(sender => {\n        if (sender.track && stream.getTracks().includes(sender.track)) {\n          this.removeTrack(sender);\n        }\n      });\n    };\n}\n\nexport function shimRTCDataChannel(window) {\n  // rename DataChannel to RTCDataChannel (native fix in FF60):\n  // https://bugzilla.mozilla.org/show_bug.cgi?id=1173851\n  if (window.DataChannel && !window.RTCDataChannel) {\n    window.RTCDataChannel = window.DataChannel;\n  }\n}\n\nexport function shimAddTransceiver(window) {\n  // https://github.com/webrtcHacks/adapter/issues/998#issuecomment-516921647\n  // Firefox ignores the init sendEncodings options passed to addTransceiver\n  // https://bugzilla.mozilla.org/show_bug.cgi?id=1396918\n  if (!(typeof window === 'object' && window.RTCPeerConnection)) {\n    return;\n  }\n  const origAddTransceiver = window.RTCPeerConnection.prototype.addTransceiver;\n  if (origAddTransceiver) {\n    window.RTCPeerConnection.prototype.addTransceiver =\n      function addTransceiver() {\n        this.setParametersPromises = [];\n        const initParameters = arguments[1];\n        const shouldPerformCheck = initParameters &&\n                                  'sendEncodings' in initParameters;\n        if (shouldPerformCheck) {\n          // If sendEncodings params are provided, validate grammar\n          initParameters.sendEncodings.forEach((encodingParam) => {\n            if ('rid' in encodingParam) {\n              const ridRegex = /^[a-z0-9]{0,16}$/i;\n              if (!ridRegex.test(encodingParam.rid)) {\n                throw new TypeError('Invalid RID value provided.');\n              }\n            }\n            if ('scaleResolutionDownBy' in encodingParam) {\n              if (!(parseFloat(encodingParam.scaleResolutionDownBy) >= 1.0)) {\n                throw new RangeError('scale_resolution_down_by must be >= 1.0');\n              }\n            }\n            if ('maxFramerate' in encodingParam) {\n              if (!(parseFloat(encodingParam.maxFramerate) >= 0)) {\n                throw new RangeError('max_framerate must be >= 0.0');\n              }\n            }\n          });\n        }\n        const transceiver = origAddTransceiver.apply(this, arguments);\n        if (shouldPerformCheck) {\n          // Check if the init options were applied. If not we do this in an\n          // asynchronous way and save the promise reference in a global object.\n          // This is an ugly hack, but at the same time is way more robust than\n          // checking the sender parameters before and after the createOffer\n          // Also note that after the createoffer we are not 100% sure that\n          // the params were asynchronously applied so we might miss the\n          // opportunity to recreate offer.\n          const {sender} = transceiver;\n          const params = sender.getParameters();\n          if (!('encodings' in params) ||\n              // Avoid being fooled by patched getParameters() below.\n              (params.encodings.length === 1 &&\n               Object.keys(params.encodings[0]).length === 0)) {\n            params.encodings = initParameters.sendEncodings;\n            sender.sendEncodings = initParameters.sendEncodings;\n            this.setParametersPromises.push(sender.setParameters(params)\n              .then(() => {\n                delete sender.sendEncodings;\n              }).catch(() => {\n                delete sender.sendEncodings;\n              })\n            );\n          }\n        }\n        return transceiver;\n      };\n  }\n}\n\nexport function shimGetParameters(window) {\n  if (!(typeof window === 'object' && window.RTCRtpSender)) {\n    return;\n  }\n  const origGetParameters = window.RTCRtpSender.prototype.getParameters;\n  if (origGetParameters) {\n    window.RTCRtpSender.prototype.getParameters =\n      function getParameters() {\n        const params = origGetParameters.apply(this, arguments);\n        if (!('encodings' in params)) {\n          params.encodings = [].concat(this.sendEncodings || [{}]);\n        }\n        return params;\n      };\n  }\n}\n\nexport function shimCreateOffer(window) {\n  // https://github.com/webrtcHacks/adapter/issues/998#issuecomment-516921647\n  // Firefox ignores the init sendEncodings options passed to addTransceiver\n  // https://bugzilla.mozilla.org/show_bug.cgi?id=1396918\n  if (!(typeof window === 'object' && window.RTCPeerConnection)) {\n    return;\n  }\n  const origCreateOffer = window.RTCPeerConnection.prototype.createOffer;\n  window.RTCPeerConnection.prototype.createOffer = function createOffer() {\n    if (this.setParametersPromises && this.setParametersPromises.length) {\n      return Promise.all(this.setParametersPromises)\n      .then(() => {\n        return origCreateOffer.apply(this, arguments);\n      })\n      .finally(() => {\n        this.setParametersPromises = [];\n      });\n    }\n    return origCreateOffer.apply(this, arguments);\n  };\n}\n\nexport function shimCreateAnswer(window) {\n  // https://github.com/webrtcHacks/adapter/issues/998#issuecomment-516921647\n  // Firefox ignores the init sendEncodings options passed to addTransceiver\n  // https://bugzilla.mozilla.org/show_bug.cgi?id=1396918\n  if (!(typeof window === 'object' && window.RTCPeerConnection)) {\n    return;\n  }\n  const origCreateAnswer = window.RTCPeerConnection.prototype.createAnswer;\n  window.RTCPeerConnection.prototype.createAnswer = function createAnswer() {\n    if (this.setParametersPromises && this.setParametersPromises.length) {\n      return Promise.all(this.setParametersPromises)\n      .then(() => {\n        return origCreateAnswer.apply(this, arguments);\n      })\n      .finally(() => {\n        this.setParametersPromises = [];\n      });\n    }\n    return origCreateAnswer.apply(this, arguments);\n  };\n}\n","/*\n *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.\n *\n *  Use of this source code is governed by a BSD-style license\n *  that can be found in the LICENSE file in the root of the source\n *  tree.\n */\n'use strict';\nimport * as utils from '../utils';\n\nexport function shimLocalStreamsAPI(window) {\n  if (typeof window !== 'object' || !window.RTCPeerConnection) {\n    return;\n  }\n  if (!('getLocalStreams' in window.RTCPeerConnection.prototype)) {\n    window.RTCPeerConnection.prototype.getLocalStreams =\n      function getLocalStreams() {\n        if (!this._localStreams) {\n          this._localStreams = [];\n        }\n        return this._localStreams;\n      };\n  }\n  if (!('addStream' in window.RTCPeerConnection.prototype)) {\n    const _addTrack = window.RTCPeerConnection.prototype.addTrack;\n    window.RTCPeerConnection.prototype.addStream = function addStream(stream) {\n      if (!this._localStreams) {\n        this._localStreams = [];\n      }\n      if (!this._localStreams.includes(stream)) {\n        this._localStreams.push(stream);\n      }\n      // Try to emulate Chrome's behaviour of adding in audio-video order.\n      // Safari orders by track id.\n      stream.getAudioTracks().forEach(track => _addTrack.call(this, track,\n        stream));\n      stream.getVideoTracks().forEach(track => _addTrack.call(this, track,\n        stream));\n    };\n\n    window.RTCPeerConnection.prototype.addTrack =\n      function addTrack(track, ...streams) {\n        if (streams) {\n          streams.forEach((stream) => {\n            if (!this._localStreams) {\n              this._localStreams = [stream];\n            } else if (!this._localStreams.includes(stream)) {\n              this._localStreams.push(stream);\n            }\n          });\n        }\n        return _addTrack.apply(this, arguments);\n      };\n  }\n  if (!('removeStream' in window.RTCPeerConnection.prototype)) {\n    window.RTCPeerConnection.prototype.removeStream =\n      function removeStream(stream) {\n        if (!this._localStreams) {\n          this._localStreams = [];\n        }\n        const index = this._localStreams.indexOf(stream);\n        if (index === -1) {\n          return;\n        }\n        this._localStreams.splice(index, 1);\n        const tracks = stream.getTracks();\n        this.getSenders().forEach(sender => {\n          if (tracks.includes(sender.track)) {\n            this.removeTrack(sender);\n          }\n        });\n      };\n  }\n}\n\nexport function shimRemoteStreamsAPI(window) {\n  if (typeof window !== 'object' || !window.RTCPeerConnection) {\n    return;\n  }\n  if (!('getRemoteStreams' in window.RTCPeerConnection.prototype)) {\n    window.RTCPeerConnection.prototype.getRemoteStreams =\n      function getRemoteStreams() {\n        return this._remoteStreams ? this._remoteStreams : [];\n      };\n  }\n  if (!('onaddstream' in window.RTCPeerConnection.prototype)) {\n    Object.defineProperty(window.RTCPeerConnection.prototype, 'onaddstream', {\n      get() {\n        return this._onaddstream;\n      },\n      set(f) {\n        if (this._onaddstream) {\n          this.removeEventListener('addstream', this._onaddstream);\n          this.removeEventListener('track', this._onaddstreampoly);\n        }\n        this.addEventListener('addstream', this._onaddstream = f);\n        this.addEventListener('track', this._onaddstreampoly = (e) => {\n          e.streams.forEach(stream => {\n            if (!this._remoteStreams) {\n              this._remoteStreams = [];\n            }\n            if (this._remoteStreams.includes(stream)) {\n              return;\n            }\n            this._remoteStreams.push(stream);\n            const event = new Event('addstream');\n            event.stream = stream;\n            this.dispatchEvent(event);\n          });\n        });\n      }\n    });\n    const origSetRemoteDescription =\n      window.RTCPeerConnection.prototype.setRemoteDescription;\n    window.RTCPeerConnection.prototype.setRemoteDescription =\n      function setRemoteDescription() {\n        const pc = this;\n        if (!this._onaddstreampoly) {\n          this.addEventListener('track', this._onaddstreampoly = function(e) {\n            e.streams.forEach(stream => {\n              if (!pc._remoteStreams) {\n                pc._remoteStreams = [];\n              }\n              if (pc._remoteStreams.indexOf(stream) >= 0) {\n                return;\n              }\n              pc._remoteStreams.push(stream);\n              const event = new Event('addstream');\n              event.stream = stream;\n              pc.dispatchEvent(event);\n            });\n          });\n        }\n        return origSetRemoteDescription.apply(pc, arguments);\n      };\n  }\n}\n\nexport function shimCallbacksAPI(window) {\n  if (typeof window !== 'object' || !window.RTCPeerConnection) {\n    return;\n  }\n  const prototype = window.RTCPeerConnection.prototype;\n  const origCreateOffer = prototype.createOffer;\n  const origCreateAnswer = prototype.createAnswer;\n  const setLocalDescription = prototype.setLocalDescription;\n  const setRemoteDescription = prototype.setRemoteDescription;\n  const addIceCandidate = prototype.addIceCandidate;\n\n  prototype.createOffer =\n    function createOffer(successCallback, failureCallback) {\n      const options = (arguments.length >= 2) ? arguments[2] : arguments[0];\n      const promise = origCreateOffer.apply(this, [options]);\n      if (!failureCallback) {\n        return promise;\n      }\n      promise.then(successCallback, failureCallback);\n      return Promise.resolve();\n    };\n\n  prototype.createAnswer =\n    function createAnswer(successCallback, failureCallback) {\n      const options = (arguments.length >= 2) ? arguments[2] : arguments[0];\n      const promise = origCreateAnswer.apply(this, [options]);\n      if (!failureCallback) {\n        return promise;\n      }\n      promise.then(successCallback, failureCallback);\n      return Promise.resolve();\n    };\n\n  let withCallback = function(description, successCallback, failureCallback) {\n    const promise = setLocalDescription.apply(this, [description]);\n    if (!failureCallback) {\n      return promise;\n    }\n    promise.then(successCallback, failureCallback);\n    return Promise.resolve();\n  };\n  prototype.setLocalDescription = withCallback;\n\n  withCallback = function(description, successCallback, failureCallback) {\n    const promise = setRemoteDescription.apply(this, [description]);\n    if (!failureCallback) {\n      return promise;\n    }\n    promise.then(successCallback, failureCallback);\n    return Promise.resolve();\n  };\n  prototype.setRemoteDescription = withCallback;\n\n  withCallback = function(candidate, successCallback, failureCallback) {\n    const promise = addIceCandidate.apply(this, [candidate]);\n    if (!failureCallback) {\n      return promise;\n    }\n    promise.then(successCallback, failureCallback);\n    return Promise.resolve();\n  };\n  prototype.addIceCandidate = withCallback;\n}\n\nexport function shimGetUserMedia(window) {\n  const navigator = window && window.navigator;\n\n  if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {\n    // shim not needed in Safari 12.1\n    const mediaDevices = navigator.mediaDevices;\n    const _getUserMedia = mediaDevices.getUserMedia.bind(mediaDevices);\n    navigator.mediaDevices.getUserMedia = (constraints) => {\n      return _getUserMedia(shimConstraints(constraints));\n    };\n  }\n\n  if (!navigator.getUserMedia && navigator.mediaDevices &&\n    navigator.mediaDevices.getUserMedia) {\n    navigator.getUserMedia = function getUserMedia(constraints, cb, errcb) {\n      navigator.mediaDevices.getUserMedia(constraints)\n      .then(cb, errcb);\n    }.bind(navigator);\n  }\n}\n\nexport function shimConstraints(constraints) {\n  if (constraints && constraints.video !== undefined) {\n    return Object.assign({},\n      constraints,\n      {video: utils.compactObject(constraints.video)}\n    );\n  }\n\n  return constraints;\n}\n\nexport function shimRTCIceServerUrls(window) {\n  if (!window.RTCPeerConnection) {\n    return;\n  }\n  // migrate from non-spec RTCIceServer.url to RTCIceServer.urls\n  const OrigPeerConnection = window.RTCPeerConnection;\n  window.RTCPeerConnection =\n    function RTCPeerConnection(pcConfig, pcConstraints) {\n      if (pcConfig && pcConfig.iceServers) {\n        const newIceServers = [];\n        for (let i = 0; i < pcConfig.iceServers.length; i++) {\n          let server = pcConfig.iceServers[i];\n          if (!server.hasOwnProperty('urls') &&\n              server.hasOwnProperty('url')) {\n            utils.deprecated('RTCIceServer.url', 'RTCIceServer.urls');\n            server = JSON.parse(JSON.stringify(server));\n            server.urls = server.url;\n            delete server.url;\n            newIceServers.push(server);\n          } else {\n            newIceServers.push(pcConfig.iceServers[i]);\n          }\n        }\n        pcConfig.iceServers = newIceServers;\n      }\n      return new OrigPeerConnection(pcConfig, pcConstraints);\n    };\n  window.RTCPeerConnection.prototype = OrigPeerConnection.prototype;\n  // wrap static methods. Currently just generateCertificate.\n  if ('generateCertificate' in OrigPeerConnection) {\n    Object.defineProperty(window.RTCPeerConnection, 'generateCertificate', {\n      get() {\n        return OrigPeerConnection.generateCertificate;\n      }\n    });\n  }\n}\n\nexport function shimTrackEventTransceiver(window) {\n  // Add event.transceiver member over deprecated event.receiver\n  if (typeof window === 'object' && window.RTCTrackEvent &&\n      'receiver' in window.RTCTrackEvent.prototype &&\n      !('transceiver' in window.RTCTrackEvent.prototype)) {\n    Object.defineProperty(window.RTCTrackEvent.prototype, 'transceiver', {\n      get() {\n        return {receiver: this.receiver};\n      }\n    });\n  }\n}\n\nexport function shimCreateOfferLegacy(window) {\n  const origCreateOffer = window.RTCPeerConnection.prototype.createOffer;\n  window.RTCPeerConnection.prototype.createOffer =\n    function createOffer(offerOptions) {\n      if (offerOptions) {\n        if (typeof offerOptions.offerToReceiveAudio !== 'undefined') {\n          // support bit values\n          offerOptions.offerToReceiveAudio =\n            !!offerOptions.offerToReceiveAudio;\n        }\n        const audioTransceiver = this.getTransceivers().find(transceiver =>\n          transceiver.receiver.track.kind === 'audio');\n        if (offerOptions.offerToReceiveAudio === false && audioTransceiver) {\n          if (audioTransceiver.direction === 'sendrecv') {\n            if (audioTransceiver.setDirection) {\n              audioTransceiver.setDirection('sendonly');\n            } else {\n              audioTransceiver.direction = 'sendonly';\n            }\n          } else if (audioTransceiver.direction === 'recvonly') {\n            if (audioTransceiver.setDirection) {\n              audioTransceiver.setDirection('inactive');\n            } else {\n              audioTransceiver.direction = 'inactive';\n            }\n          }\n        } else if (offerOptions.offerToReceiveAudio === true &&\n            !audioTransceiver) {\n          this.addTransceiver('audio', {direction: 'recvonly'});\n        }\n\n        if (typeof offerOptions.offerToReceiveVideo !== 'undefined') {\n          // support bit values\n          offerOptions.offerToReceiveVideo =\n            !!offerOptions.offerToReceiveVideo;\n        }\n        const videoTransceiver = this.getTransceivers().find(transceiver =>\n          transceiver.receiver.track.kind === 'video');\n        if (offerOptions.offerToReceiveVideo === false && videoTransceiver) {\n          if (videoTransceiver.direction === 'sendrecv') {\n            if (videoTransceiver.setDirection) {\n              videoTransceiver.setDirection('sendonly');\n            } else {\n              videoTransceiver.direction = 'sendonly';\n            }\n          } else if (videoTransceiver.direction === 'recvonly') {\n            if (videoTransceiver.setDirection) {\n              videoTransceiver.setDirection('inactive');\n            } else {\n              videoTransceiver.direction = 'inactive';\n            }\n          }\n        } else if (offerOptions.offerToReceiveVideo === true &&\n            !videoTransceiver) {\n          this.addTransceiver('video', {direction: 'recvonly'});\n        }\n      }\n      return origCreateOffer.apply(this, arguments);\n    };\n}\n\nexport function shimAudioContext(window) {\n  if (typeof window !== 'object' || window.AudioContext) {\n    return;\n  }\n  window.AudioContext = window.webkitAudioContext;\n}\n\n","/*\n *  Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.\n *\n *  Use of this source code is governed by a BSD-style license\n *  that can be found in the LICENSE file in the root of the source\n *  tree.\n */\n/* eslint-env node */\n'use strict';\n\nimport SDPUtils from 'sdp';\nimport * as utils from './utils';\n\nexport function shimRTCIceCandidate(window) {\n  // foundation is arbitrarily chosen as an indicator for full support for\n  // https://w3c.github.io/webrtc-pc/#rtcicecandidate-interface\n  if (!window.RTCIceCandidate || (window.RTCIceCandidate && 'foundation' in\n      window.RTCIceCandidate.prototype)) {\n    return;\n  }\n\n  const NativeRTCIceCandidate = window.RTCIceCandidate;\n  window.RTCIceCandidate = function RTCIceCandidate(args) {\n    // Remove the a= which shouldn't be part of the candidate string.\n    if (typeof args === 'object' && args.candidate &&\n        args.candidate.indexOf('a=') === 0) {\n      args = JSON.parse(JSON.stringify(args));\n      args.candidate = args.candidate.substr(2);\n    }\n\n    if (args.candidate && args.candidate.length) {\n      // Augment the native candidate with the parsed fields.\n      const nativeCandidate = new NativeRTCIceCandidate(args);\n      const parsedCandidate = SDPUtils.parseCandidate(args.candidate);\n      const augmentedCandidate = Object.assign(nativeCandidate,\n          parsedCandidate);\n\n      // Add a serializer that does not serialize the extra attributes.\n      augmentedCandidate.toJSON = function toJSON() {\n        return {\n          candidate: augmentedCandidate.candidate,\n          sdpMid: augmentedCandidate.sdpMid,\n          sdpMLineIndex: augmentedCandidate.sdpMLineIndex,\n          usernameFragment: augmentedCandidate.usernameFragment,\n        };\n      };\n      return augmentedCandidate;\n    }\n    return new NativeRTCIceCandidate(args);\n  };\n  window.RTCIceCandidate.prototype = NativeRTCIceCandidate.prototype;\n\n  // Hook up the augmented candidate in onicecandidate and\n  // addEventListener('icecandidate', ...)\n  utils.wrapPeerConnectionEvent(window, 'icecandidate', e => {\n    if (e.candidate) {\n      Object.defineProperty(e, 'candidate', {\n        value: new window.RTCIceCandidate(e.candidate),\n        writable: 'false'\n      });\n    }\n    return e;\n  });\n}\n\nexport function shimMaxMessageSize(window, browserDetails) {\n  if (!window.RTCPeerConnection) {\n    return;\n  }\n\n  if (!('sctp' in window.RTCPeerConnection.prototype)) {\n    Object.defineProperty(window.RTCPeerConnection.prototype, 'sctp', {\n      get() {\n        return typeof this._sctp === 'undefined' ? null : this._sctp;\n      }\n    });\n  }\n\n  const sctpInDescription = function(description) {\n    if (!description || !description.sdp) {\n      return false;\n    }\n    const sections = SDPUtils.splitSections(description.sdp);\n    sections.shift();\n    return sections.some(mediaSection => {\n      const mLine = SDPUtils.parseMLine(mediaSection);\n      return mLine && mLine.kind === 'application'\n          && mLine.protocol.indexOf('SCTP') !== -1;\n    });\n  };\n\n  const getRemoteFirefoxVersion = function(description) {\n    // TODO: Is there a better solution for detecting Firefox?\n    const match = description.sdp.match(/mozilla...THIS_IS_SDPARTA-(\\d+)/);\n    if (match === null || match.length < 2) {\n      return -1;\n    }\n    const version = parseInt(match[1], 10);\n    // Test for NaN (yes, this is ugly)\n    return version !== version ? -1 : version;\n  };\n\n  const getCanSendMaxMessageSize = function(remoteIsFirefox) {\n    // Every implementation we know can send at least 64 KiB.\n    // Note: Although Chrome is technically able to send up to 256 KiB, the\n    //       data does not reach the other peer reliably.\n    //       See: https://bugs.chromium.org/p/webrtc/issues/detail?id=8419\n    let canSendMaxMessageSize = 65536;\n    if (browserDetails.browser === 'firefox') {\n      if (browserDetails.version < 57) {\n        if (remoteIsFirefox === -1) {\n          // FF < 57 will send in 16 KiB chunks using the deprecated PPID\n          // fragmentation.\n          canSendMaxMessageSize = 16384;\n        } else {\n          // However, other FF (and RAWRTC) can reassemble PPID-fragmented\n          // messages. Thus, supporting ~2 GiB when sending.\n          canSendMaxMessageSize = 2147483637;\n        }\n      } else if (browserDetails.version < 60) {\n        // Currently, all FF >= 57 will reset the remote maximum message size\n        // to the default value when a data channel is created at a later\n        // stage. :(\n        // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1426831\n        canSendMaxMessageSize =\n          browserDetails.version === 57 ? 65535 : 65536;\n      } else {\n        // FF >= 60 supports sending ~2 GiB\n        canSendMaxMessageSize = 2147483637;\n      }\n    }\n    return canSendMaxMessageSize;\n  };\n\n  const getMaxMessageSize = function(description, remoteIsFirefox) {\n    // Note: 65536 bytes is the default value from the SDP spec. Also,\n    //       every implementation we know supports receiving 65536 bytes.\n    let maxMessageSize = 65536;\n\n    // FF 57 has a slightly incorrect default remote max message size, so\n    // we need to adjust it here to avoid a failure when sending.\n    // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1425697\n    if (browserDetails.browser === 'firefox'\n         && browserDetails.version === 57) {\n      maxMessageSize = 65535;\n    }\n\n    const match = SDPUtils.matchPrefix(description.sdp,\n      'a=max-message-size:');\n    if (match.length > 0) {\n      maxMessageSize = parseInt(match[0].substr(19), 10);\n    } else if (browserDetails.browser === 'firefox' &&\n                remoteIsFirefox !== -1) {\n      // If the maximum message size is not present in the remote SDP and\n      // both local and remote are Firefox, the remote peer can receive\n      // ~2 GiB.\n      maxMessageSize = 2147483637;\n    }\n    return maxMessageSize;\n  };\n\n  const origSetRemoteDescription =\n      window.RTCPeerConnection.prototype.setRemoteDescription;\n  window.RTCPeerConnection.prototype.setRemoteDescription =\n    function setRemoteDescription() {\n      this._sctp = null;\n      // Chrome decided to not expose .sctp in plan-b mode.\n      // As usual, adapter.js has to do an 'ugly worakaround'\n      // to cover up the mess.\n      if (browserDetails.browser === 'chrome' && browserDetails.version >= 76) {\n        const {sdpSemantics} = this.getConfiguration();\n        if (sdpSemantics === 'plan-b') {\n          Object.defineProperty(this, 'sctp', {\n            get() {\n              return typeof this._sctp === 'undefined' ? null : this._sctp;\n            },\n            enumerable: true,\n            configurable: true,\n          });\n        }\n      }\n\n      if (sctpInDescription(arguments[0])) {\n        // Check if the remote is FF.\n        const isFirefox = getRemoteFirefoxVersion(arguments[0]);\n\n        // Get the maximum message size the local peer is capable of sending\n        const canSendMMS = getCanSendMaxMessageSize(isFirefox);\n\n        // Get the maximum message size of the remote peer.\n        const remoteMMS = getMaxMessageSize(arguments[0], isFirefox);\n\n        // Determine final maximum message size\n        let maxMessageSize;\n        if (canSendMMS === 0 && remoteMMS === 0) {\n          maxMessageSize = Number.POSITIVE_INFINITY;\n        } else if (canSendMMS === 0 || remoteMMS === 0) {\n          maxMessageSize = Math.max(canSendMMS, remoteMMS);\n        } else {\n          maxMessageSize = Math.min(canSendMMS, remoteMMS);\n        }\n\n        // Create a dummy RTCSctpTransport object and the 'maxMessageSize'\n        // attribute.\n        const sctp = {};\n        Object.defineProperty(sctp, 'maxMessageSize', {\n          get() {\n            return maxMessageSize;\n          }\n        });\n        this._sctp = sctp;\n      }\n\n      return origSetRemoteDescription.apply(this, arguments);\n    };\n}\n\nexport function shimSendThrowTypeError(window) {\n  if (!(window.RTCPeerConnection &&\n      'createDataChannel' in window.RTCPeerConnection.prototype)) {\n    return;\n  }\n\n  // Note: Although Firefox >= 57 has a native implementation, the maximum\n  //       message size can be reset for all data channels at a later stage.\n  //       See: https://bugzilla.mozilla.org/show_bug.cgi?id=1426831\n\n  function wrapDcSend(dc, pc) {\n    const origDataChannelSend = dc.send;\n    dc.send = function send() {\n      const data = arguments[0];\n      const length = data.length || data.size || data.byteLength;\n      if (dc.readyState === 'open' &&\n          pc.sctp && length > pc.sctp.maxMessageSize) {\n        throw new TypeError('Message too large (can send a maximum of ' +\n          pc.sctp.maxMessageSize + ' bytes)');\n      }\n      return origDataChannelSend.apply(dc, arguments);\n    };\n  }\n  const origCreateDataChannel =\n    window.RTCPeerConnection.prototype.createDataChannel;\n  window.RTCPeerConnection.prototype.createDataChannel =\n    function createDataChannel() {\n      const dataChannel = origCreateDataChannel.apply(this, arguments);\n      wrapDcSend(dataChannel, this);\n      return dataChannel;\n    };\n  utils.wrapPeerConnectionEvent(window, 'datachannel', e => {\n    wrapDcSend(e.channel, e.target);\n    return e;\n  });\n}\n\n\n/* shims RTCConnectionState by pretending it is the same as iceConnectionState.\n * See https://bugs.chromium.org/p/webrtc/issues/detail?id=6145#c12\n * for why this is a valid hack in Chrome. In Firefox it is slightly incorrect\n * since DTLS failures would be hidden. See\n * https://bugzilla.mozilla.org/show_bug.cgi?id=1265827\n * for the Firefox tracking bug.\n */\nexport function shimConnectionState(window) {\n  if (!window.RTCPeerConnection ||\n      'connectionState' in window.RTCPeerConnection.prototype) {\n    return;\n  }\n  const proto = window.RTCPeerConnection.prototype;\n  Object.defineProperty(proto, 'connectionState', {\n    get() {\n      return {\n        completed: 'connected',\n        checking: 'connecting'\n      }[this.iceConnectionState] || this.iceConnectionState;\n    },\n    enumerable: true,\n    configurable: true\n  });\n  Object.defineProperty(proto, 'onconnectionstatechange', {\n    get() {\n      return this._onconnectionstatechange || null;\n    },\n    set(cb) {\n      if (this._onconnectionstatechange) {\n        this.removeEventListener('connectionstatechange',\n            this._onconnectionstatechange);\n        delete this._onconnectionstatechange;\n      }\n      if (cb) {\n        this.addEventListener('connectionstatechange',\n            this._onconnectionstatechange = cb);\n      }\n    },\n    enumerable: true,\n    configurable: true\n  });\n\n  ['setLocalDescription', 'setRemoteDescription'].forEach((method) => {\n    const origMethod = proto[method];\n    proto[method] = function() {\n      if (!this._connectionstatechangepoly) {\n        this._connectionstatechangepoly = e => {\n          const pc = e.target;\n          if (pc._lastConnectionState !== pc.connectionState) {\n            pc._lastConnectionState = pc.connectionState;\n            const newEvent = new Event('connectionstatechange', e);\n            pc.dispatchEvent(newEvent);\n          }\n          return e;\n        };\n        this.addEventListener('iceconnectionstatechange',\n          this._connectionstatechangepoly);\n      }\n      return origMethod.apply(this, arguments);\n    };\n  });\n}\n\nexport function removeExtmapAllowMixed(window, browserDetails) {\n  /* remove a=extmap-allow-mixed for webrtc.org < M71 */\n  if (!window.RTCPeerConnection) {\n    return;\n  }\n  if (browserDetails.browser === 'chrome' && browserDetails.version >= 71) {\n    return;\n  }\n  if (browserDetails.browser === 'safari' && browserDetails.version >= 605) {\n    return;\n  }\n  const nativeSRD = window.RTCPeerConnection.prototype.setRemoteDescription;\n  window.RTCPeerConnection.prototype.setRemoteDescription =\n  function setRemoteDescription(desc) {\n    if (desc && desc.sdp && desc.sdp.indexOf('\\na=extmap-allow-mixed') !== -1) {\n      const sdp = desc.sdp.split('\\n').filter((line) => {\n        return line.trim() !== 'a=extmap-allow-mixed';\n      }).join('\\n');\n      // Safari enforces read-only-ness of RTCSessionDescription fields.\n      if (window.RTCSessionDescription &&\n          desc instanceof window.RTCSessionDescription) {\n        arguments[0] = new window.RTCSessionDescription({\n          type: desc.type,\n          sdp,\n        });\n      } else {\n        desc.sdp = sdp;\n      }\n    }\n    return nativeSRD.apply(this, arguments);\n  };\n}\n\nexport function shimAddIceCandidateNullOrEmpty(window, browserDetails) {\n  // Support for addIceCandidate(null or undefined)\n  // as well as addIceCandidate({candidate: \"\", ...})\n  // https://bugs.chromium.org/p/chromium/issues/detail?id=978582\n  // Note: must be called before other polyfills which change the signature.\n  if (!(window.RTCPeerConnection && window.RTCPeerConnection.prototype)) {\n    return;\n  }\n  const nativeAddIceCandidate =\n      window.RTCPeerConnection.prototype.addIceCandidate;\n  if (!nativeAddIceCandidate || nativeAddIceCandidate.length === 0) {\n    return;\n  }\n  window.RTCPeerConnection.prototype.addIceCandidate =\n    function addIceCandidate() {\n      if (!arguments[0]) {\n        if (arguments[1]) {\n          arguments[1].apply(null);\n        }\n        return Promise.resolve();\n      }\n      // Firefox 68+ emits and processes {candidate: \"\", ...}, ignore\n      // in older versions.\n      // Native support for ignoring exists for Chrome M77+.\n      // Safari ignores as well, exact version unknown but works in the same\n      // version that also ignores addIceCandidate(null).\n      if (((browserDetails.browser === 'chrome' && browserDetails.version < 78)\n           || (browserDetails.browser === 'firefox'\n               && browserDetails.version < 68)\n           || (browserDetails.browser === 'safari'))\n          && arguments[0] && arguments[0].candidate === '') {\n        return Promise.resolve();\n      }\n      return nativeAddIceCandidate.apply(this, arguments);\n    };\n}\n\n// Note: Make sure to call this ahead of APIs that modify\n// setLocalDescription.length\nexport function shimParameterlessSetLocalDescription(window, browserDetails) {\n  if (!(window.RTCPeerConnection && window.RTCPeerConnection.prototype)) {\n    return;\n  }\n  const nativeSetLocalDescription =\n      window.RTCPeerConnection.prototype.setLocalDescription;\n  if (!nativeSetLocalDescription || nativeSetLocalDescription.length === 0) {\n    return;\n  }\n  window.RTCPeerConnection.prototype.setLocalDescription =\n    function setLocalDescription() {\n      let desc = arguments[0] || {};\n      if (typeof desc !== 'object' || (desc.type && desc.sdp)) {\n        return nativeSetLocalDescription.apply(this, arguments);\n      }\n      // The remaining steps should technically happen when SLD comes off the\n      // RTCPeerConnection's operations chain (not ahead of going on it), but\n      // this is too difficult to shim. Instead, this shim only covers the\n      // common case where the operations chain is empty. This is imperfect, but\n      // should cover many cases. Rationale: Even if we can't reduce the glare\n      // window to zero on imperfect implementations, there's value in tapping\n      // into the perfect negotiation pattern that several browsers support.\n      desc = {type: desc.type, sdp: desc.sdp};\n      if (!desc.type) {\n        switch (this.signalingState) {\n          case 'stable':\n          case 'have-local-offer':\n          case 'have-remote-pranswer':\n            desc.type = 'offer';\n            break;\n          default:\n            desc.type = 'answer';\n            break;\n        }\n      }\n      if (desc.sdp || (desc.type !== 'offer' && desc.type !== 'answer')) {\n        return nativeSetLocalDescription.apply(this, [desc]);\n      }\n      const func = desc.type === 'offer' ? this.createOffer : this.createAnswer;\n      return func.apply(this)\n        .then(d => nativeSetLocalDescription.apply(this, [d]));\n    };\n}\n","/*\n *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.\n *\n *  Use of this source code is governed by a BSD-style license\n *  that can be found in the LICENSE file in the root of the source\n *  tree.\n */\nimport * as utils from './utils';\n\n  // Browser shims.\nimport * as chromeShim from './chrome/chrome_shim';\nimport * as firefoxShim from './firefox/firefox_shim';\nimport * as safariShim from './safari/safari_shim';\nimport * as commonShim from './common_shim';\nimport * as sdp from 'sdp';\n\n// Shimming starts here.\nexport function adapterFactory({window} = {}, options = {\n  shimChrome: true,\n  shimFirefox: true,\n  shimSafari: true,\n}) {\n  // Utils.\n  const logging = utils.log;\n  const browserDetails = utils.detectBrowser(window);\n\n  const adapter = {\n    browserDetails,\n    commonShim,\n    extractVersion: utils.extractVersion,\n    disableLog: utils.disableLog,\n    disableWarnings: utils.disableWarnings,\n    // Expose sdp as a convenience. For production apps include directly.\n    sdp,\n  };\n\n  // Shim browser if found.\n  switch (browserDetails.browser) {\n    case 'chrome':\n      if (!chromeShim || !chromeShim.shimPeerConnection ||\n          !options.shimChrome) {\n        logging('Chrome shim is not included in this adapter release.');\n        return adapter;\n      }\n      if (browserDetails.version === null) {\n        logging('Chrome shim can not determine version, not shimming.');\n        return adapter;\n      }\n      logging('adapter.js shimming chrome.');\n      // Export to the adapter global object visible in the browser.\n      adapter.browserShim = chromeShim;\n\n      // Must be called before shimPeerConnection.\n      commonShim.shimAddIceCandidateNullOrEmpty(window, browserDetails);\n      commonShim.shimParameterlessSetLocalDescription(window, browserDetails);\n\n      chromeShim.shimGetUserMedia(window, browserDetails);\n      chromeShim.shimMediaStream(window, browserDetails);\n      chromeShim.shimPeerConnection(window, browserDetails);\n      chromeShim.shimOnTrack(window, browserDetails);\n      chromeShim.shimAddTrackRemoveTrack(window, browserDetails);\n      chromeShim.shimGetSendersWithDtmf(window, browserDetails);\n      chromeShim.shimGetStats(window, browserDetails);\n      chromeShim.shimSenderReceiverGetStats(window, browserDetails);\n      chromeShim.fixNegotiationNeeded(window, browserDetails);\n\n      commonShim.shimRTCIceCandidate(window, browserDetails);\n      commonShim.shimConnectionState(window, browserDetails);\n      commonShim.shimMaxMessageSize(window, browserDetails);\n      commonShim.shimSendThrowTypeError(window, browserDetails);\n      commonShim.removeExtmapAllowMixed(window, browserDetails);\n      break;\n    case 'firefox':\n      if (!firefoxShim || !firefoxShim.shimPeerConnection ||\n          !options.shimFirefox) {\n        logging('Firefox shim is not included in this adapter release.');\n        return adapter;\n      }\n      logging('adapter.js shimming firefox.');\n      // Export to the adapter global object visible in the browser.\n      adapter.browserShim = firefoxShim;\n\n      // Must be called before shimPeerConnection.\n      commonShim.shimAddIceCandidateNullOrEmpty(window, browserDetails);\n      commonShim.shimParameterlessSetLocalDescription(window, browserDetails);\n\n      firefoxShim.shimGetUserMedia(window, browserDetails);\n      firefoxShim.shimPeerConnection(window, browserDetails);\n      firefoxShim.shimOnTrack(window, browserDetails);\n      firefoxShim.shimRemoveStream(window, browserDetails);\n      firefoxShim.shimSenderGetStats(window, browserDetails);\n      firefoxShim.shimReceiverGetStats(window, browserDetails);\n      firefoxShim.shimRTCDataChannel(window, browserDetails);\n      firefoxShim.shimAddTransceiver(window, browserDetails);\n      firefoxShim.shimGetParameters(window, browserDetails);\n      firefoxShim.shimCreateOffer(window, browserDetails);\n      firefoxShim.shimCreateAnswer(window, browserDetails);\n\n      commonShim.shimRTCIceCandidate(window, browserDetails);\n      commonShim.shimConnectionState(window, browserDetails);\n      commonShim.shimMaxMessageSize(window, browserDetails);\n      commonShim.shimSendThrowTypeError(window, browserDetails);\n      break;\n    case 'safari':\n      if (!safariShim || !options.shimSafari) {\n        logging('Safari shim is not included in this adapter release.');\n        return adapter;\n      }\n      logging('adapter.js shimming safari.');\n      // Export to the adapter global object visible in the browser.\n      adapter.browserShim = safariShim;\n\n      // Must be called before shimCallbackAPI.\n      commonShim.shimAddIceCandidateNullOrEmpty(window, browserDetails);\n      commonShim.shimParameterlessSetLocalDescription(window, browserDetails);\n\n      safariShim.shimRTCIceServerUrls(window, browserDetails);\n      safariShim.shimCreateOfferLegacy(window, browserDetails);\n      safariShim.shimCallbacksAPI(window, browserDetails);\n      safariShim.shimLocalStreamsAPI(window, browserDetails);\n      safariShim.shimRemoteStreamsAPI(window, browserDetails);\n      safariShim.shimTrackEventTransceiver(window, browserDetails);\n      safariShim.shimGetUserMedia(window, browserDetails);\n      safariShim.shimAudioContext(window, browserDetails);\n\n      commonShim.shimRTCIceCandidate(window, browserDetails);\n      commonShim.shimMaxMessageSize(window, browserDetails);\n      commonShim.shimSendThrowTypeError(window, browserDetails);\n      commonShim.removeExtmapAllowMixed(window, browserDetails);\n      break;\n    default:\n      logging('Unsupported browser!');\n      break;\n  }\n\n  return adapter;\n}\n","/*\n *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.\n *\n *  Use of this source code is governed by a BSD-style license\n *  that can be found in the LICENSE file in the root of the source\n *  tree.\n */\n/* eslint-env node */\n\n'use strict';\n\nimport {adapterFactory} from './adapter_factory.js';\n\nconst adapter =\n  adapterFactory({window: typeof window === 'undefined' ? undefined : window});\nexport default adapter;\n","const Resolutions = {\n    '1080': {\n        height: 1080,\n        width: 1920\n    },\n    '180': {\n        height: 180,\n        width: 320\n    },\n    '2160': {\n        height: 2160,\n        width: 3840\n    },\n    '240': {\n        height: 240,\n        width: 320\n    },\n    '360': {\n        height: 360,\n        width: 640\n    },\n    '480': {\n        height: 480,\n        width: 640\n    },\n    '4k': {\n        height: 2160,\n        width: 3840\n    },\n    '540': {\n        height: 540,\n        width: 960\n    },\n    '720': {\n        height: 720,\n        width: 1280\n    },\n    'fullhd': {\n        height: 1080,\n        width: 1920\n    },\n    'hd': {\n        height: 720,\n        width: 1280\n    },\n    'qhd': {\n        height: 540,\n        width: 960\n    },\n    'vga': {\n        height: 480,\n        width: 640\n    }\n};\n\nexport default Resolutions;\n\n","import { getLogger } from '@jitsi/logger';\n\nimport JitsiTrackError from '../../JitsiTrackError';\nimport * as JitsiTrackErrors from '../../JitsiTrackErrors';\nimport browser from '../browser';\n\nconst logger = getLogger('rtc:ScreenObtainer');\n\n/**\n * Interface for desktop sharing frame rate configuration.\n */\ninterface IFrameRateConfig {\n    max?: number;\n    min?: number;\n}\n\n/**\n * Interface for desktop sharing resolution configuration.\n */\ninterface IResolutionConfig {\n    height?: {\n        max?: number;\n        min?: number;\n    };\n    width?: {\n        max?: number;\n        min?: number;\n    };\n}\n\n/**\n * Interface for audio quality configuration.\n */\ninterface IAudioQuality {\n    autoGainControl?: boolean;\n    channelCount?: number;\n    echoCancellation?: boolean;\n    noiseSuppression?: boolean;\n    restrictOwnAudio?: boolean;\n    stereo?: boolean;\n}\n\n/**\n * Interface for screen share settings.\n */\ninterface IScreenShareSettings {\n    desktopDisplaySurface?: string;\n    desktopPreferCurrentTab?: boolean;\n    desktopSelfBrowserSurface?: string;\n    desktopSurfaceSwitching?: string;\n    desktopSystemAudio?: string;\n}\n\n\n/**\n * Interface for options parameter in obtainScreen methods.\n */\ninterface IObtainScreenOptions {\n    desktopSharingFrameRate?: IFrameRateConfig;\n    desktopSharingSources?: string[];\n    resolution?: number;\n    screenShareSettings?: IScreenShareSettings;\n}\n\n/**\n * Interface for audio constraints.\n */\ninterface IAudioConstraints {\n    mandatory?: {\n        chromeMediaSource?: string;\n        chromeMediaSourceId?: string;\n    };\n    optional?: {\n        autoGainControl?: boolean;\n        channelCount?: number;\n        echoCancellation?: boolean;\n        noiseSuppression?: boolean;\n    };\n}\n\n/**\n * Interface for legacy video constraints.\n */\ninterface ILegacyVideoConstraints {\n    mandatory: {\n        chromeMediaSource: string;\n        chromeMediaSourceId: string;\n        maxFrameRate: number;\n        maxHeight: number;\n        maxWidth: number;\n        minFrameRate: number;\n        minHeight?: number;\n        minWidth?: number;\n    };\n}\n\n/**\n * Interface for modern video constraints.\n */\ninterface IVideoConstraints {\n    displaySurface?: string;\n    frameRate?: IFrameRateConfig;\n    height?: number;\n    width?: number;\n}\n\n/**\n * Interface for constraint options.\n */\ninterface IConstraintOptions {\n    preferCurrentTab?: boolean;\n    selfBrowserSurface?: string;\n    surfaceSwitching?: string;\n    systemAudio?: string;\n}\n\n/**\n * Interface for getDisplayMedia constraints.\n */\ninterface IDisplayMediaConstraints {\n    audio: boolean | object;\n    cursor?: string;\n    preferCurrentTab?: boolean;\n    selfBrowserSurface?: string;\n    surfaceSwitching?: string;\n    systemAudio?: string;\n    video: boolean | IVideoConstraints;\n}\n\n/**\n * Interface for screen obtainer options.\n */\ninterface IScreenObtainerOptions {\n    audioQuality?: IAudioQuality;\n    desktopSharingFrameRate?: IFrameRateConfig;\n    desktopSharingResolution?: IResolutionConfig;\n    desktopSharingSources?: string[];\n    resolution?: number;\n    screenShareSettings?: IScreenShareSettings;\n    testing?: {\n        testMode?: boolean;\n    };\n}\n\n/**\n * Interface for screen capture result.\n */\ninterface IScreenCaptureResult {\n    sourceId: string;\n    sourceType?: string;\n    stream: MediaStream;\n}\n\n/**\n * The default frame rate for Screen Sharing.\n */\nexport const SS_DEFAULT_FRAME_RATE = 5;\n\n/**\n * Handles obtaining a stream from a screen capture on different browsers.\n */\nclass ScreenObtainer {\n    private _electronSkipDisplayMedia: boolean;\n    public obtainStream: Nullable<((\n        onSuccess: (result: IScreenCaptureResult) => void,\n        onFailure: (error: JitsiTrackError) => void,\n        options?: any\n    ) => void)>;\n\n    /**\n     * @internal\n     */\n    options: IScreenObtainerOptions;\n\n    constructor() {\n        this.obtainStream = this._createObtainStreamMethod();\n        this.options = {};\n        this._electronSkipDisplayMedia = false;\n    }\n\n    /**\n     * Initializes the function used to obtain a screen capture\n     * (this.obtainStream).\n     *\n     * @param {object} options\n     */\n    private init(options: IScreenObtainerOptions = {}) {\n        this.options = options;\n\n        if (!this.obtainStream) {\n            logger.warn('Desktop sharing not supported');\n        }\n    }\n\n    /**\n     * Returns a method which will be used to obtain the screen sharing stream\n     * (based on the browser type).\n     *\n     * @returns {Function}\n     * @private\n     */\n    private _createObtainStreamMethod() {\n        const supportsGetDisplayMedia = browser.supportsGetDisplayMedia();\n\n        if (browser.isElectron()) {\n            return this._obtainScreenOnElectron;\n        } else if (browser.isReactNative() && supportsGetDisplayMedia) {\n            return this.obtainScreenFromGetDisplayMediaRN;\n        } else if (supportsGetDisplayMedia) {\n            return this._obtainScreenFromGetDisplayMedia;\n        }\n        logger.warn('Screen sharing not supported on ', browser.getName());\n\n        return null;\n    }\n\n    /**\n     * Gets the appropriate constraints for audio sharing.\n     *\n     * @returns {IAudioQuality | boolean}\n     */\n    private _getAudioConstraints(): boolean | IAudioQuality {\n        const { audioQuality } = this.options;\n        const isTestModeEnabled = this.options.testing?.testMode;\n\n        // Chrome 140+ requires 'restrictOwnAudio' for proper audio sharing when not using stereo.\n        // Starting Chrome 137 'echoCancellation' was turned off by default for screen share audio and needs to be\n        // enabled explicity to avoid echo issues.\n        // See https://issues.chromium.org/issues/422611724 and https://chromestatus.com/feature/5128140732760064 for more details.\n        const supportsRestrictOwnAudio = browser.isChromiumBased()\n            && browser.isEngineVersionGreaterThan(141)\n            && !browser.isElectron();\n        const needsEchoCancellation = !audioQuality?.stereo\n            && browser.isChromiumBased()\n            && browser.isEngineVersionGreaterThan(136)\n            && !supportsRestrictOwnAudio;\n\n        const defaultAudioConstraints: IAudioQuality = {\n            autoGainControl: !audioQuality?.stereo,\n            channelCount: audioQuality?.stereo ? 2 : 1,\n            echoCancellation: !audioQuality?.stereo,\n            noiseSuppression: !audioQuality?.stereo\n        };\n\n        let audio: boolean | IAudioQuality = (audioQuality?.stereo || needsEchoCancellation)\n            ? defaultAudioConstraints\n            : !isTestModeEnabled;\n\n        if (supportsRestrictOwnAudio && !isTestModeEnabled) {\n            if (typeof audio === 'boolean') {\n                audio = {\n                    restrictOwnAudio: true\n                };\n            } else {\n                audio.restrictOwnAudio = true;\n            }\n        }\n\n        return audio;\n    }\n\n    /**\n     * Obtains a screen capture stream on Electron.\n     *\n     * @param onSuccess - Success callback.\n     * @param onFailure - Failure callback.\n     * @param {Object} options - Optional parameters.\n     */\n    private _obtainScreenOnElectron(onSuccess: (result: IScreenCaptureResult) => void, onFailure: (error: JitsiTrackError) => void, options: IObtainScreenOptions = {}) {\n        if (!this._electronSkipDisplayMedia) {\n            // Fall-back to the old API in case of not supported error. This can happen if\n            // an old Electron SDK is used with a new Jitsi Meet + lib-jitsi-meet version.\n            this._obtainScreenFromGetDisplayMedia(onSuccess, err => {\n                if (err.name === JitsiTrackErrors.SCREENSHARING_NOT_SUPPORTED_ERROR) {\n                    // Make sure we don't recurse infinitely.\n                    this._electronSkipDisplayMedia = true;\n                    this._obtainScreenOnElectron(onSuccess, onFailure);\n                } else {\n                    onFailure(err);\n                }\n            });\n\n            return;\n        }\n\n        // @ts-ignore TODO: legacy flow, remove after the Electron SDK supporting gDM has been out for a while.\n        if (typeof window.JitsiMeetScreenObtainer?.openDesktopPicker === 'function') {\n            const { desktopSharingFrameRate, desktopSharingResolution, desktopSharingSources } = this.options;\n\n            // @ts-ignore TODO: legacy flow, remove after the Electron SDK supporting gDM has been out for a while.\n            window.JitsiMeetScreenObtainer.openDesktopPicker(\n                {\n                    desktopSharingSources:\n                        options.desktopSharingSources || desktopSharingSources || [ 'screen', 'window' ]\n                },\n                (streamId: string, streamType: string, screenShareAudio = false) => {\n                    if (streamId) {\n                        let audioConstraints: boolean | IAudioConstraints = false;\n\n                        if (screenShareAudio) {\n                            audioConstraints = {};\n                            const optionalConstraints = this._getAudioConstraints();\n\n                            if (typeof optionalConstraints !== 'boolean') {\n                                audioConstraints = {\n                                    optional: optionalConstraints\n                                };\n                            }\n\n                            // Audio screen sharing for electron only works for screen type devices.\n                            // i.e. when the user shares the whole desktop.\n                            // Note. The documentation specifies that chromeMediaSourceId should not be present\n                            // which, in the case a users has multiple monitors, leads to them being shared all\n                            // at once. However we tested with chromeMediaSourceId present and it seems to be\n                            // working properly.\n                            if (streamType === 'screen') {\n                                (audioConstraints as IAudioConstraints).mandatory = {\n                                    chromeMediaSource: 'desktop'\n                                };\n                            }\n                        }\n\n                        const constraints: any = {\n                            audio: audioConstraints,\n                            video: {\n                                mandatory: {\n                                    chromeMediaSource: 'desktop',\n                                    chromeMediaSourceId: streamId,\n                                    maxFrameRate: desktopSharingFrameRate?.max ?? SS_DEFAULT_FRAME_RATE,\n                                    maxHeight: desktopSharingResolution?.height?.max ?? window.screen.height,\n                                    maxWidth: desktopSharingResolution?.width?.max ?? window.screen.width,\n                                    minFrameRate: desktopSharingFrameRate?.min ?? SS_DEFAULT_FRAME_RATE,\n                                    minHeight: desktopSharingResolution?.height?.min,\n                                    minWidth: desktopSharingResolution?.width?.min\n                                }\n                            } as ILegacyVideoConstraints\n                        };\n\n                        // We have to use the old API on Electron to get a desktop stream.\n                        navigator.mediaDevices.getUserMedia(constraints)\n                            .then(stream => {\n                                this.setContentHint(stream);\n                                onSuccess({\n                                    sourceId: streamId,\n                                    sourceType: streamType,\n                                    stream\n                                });\n                            })\n                            .catch(err => onFailure(err));\n                    } else {\n                        // As noted in Chrome Desktop Capture API:\n                        // If user didn't select any source (i.e. canceled the prompt)\n                        // then the callback is called with an empty streamId.\n                        onFailure(new JitsiTrackError(JitsiTrackErrors.SCREENSHARING_USER_CANCELED));\n                    }\n                },\n                err => onFailure(new JitsiTrackError(\n                    JitsiTrackErrors.ELECTRON_DESKTOP_PICKER_ERROR,\n                    err\n                ))\n            );\n        } else {\n            onFailure(new JitsiTrackError(JitsiTrackErrors.ELECTRON_DESKTOP_PICKER_NOT_FOUND));\n        }\n    }\n\n    /**\n     * Obtains a screen capture stream using getDisplayMedia.\n     *\n     * @param callback - The success callback.\n     * @param errorCallback - The error callback.\n     * @param {Object} options - Optional parameters.\n     */\n    private _obtainScreenFromGetDisplayMedia(callback: (result: IScreenCaptureResult) => void, errorCallback: (error: JitsiTrackError) => void, options: IObtainScreenOptions = {}) {\n        let getDisplayMedia;\n\n        // @ts-ignore Property 'getDisplayMedia' does not exist on type 'Navigator'\n        if (navigator.getDisplayMedia) {\n            // @ts-ignore Property 'getDisplayMedia' does not exist on type 'Navigator'\n            getDisplayMedia = navigator.getDisplayMedia.bind(navigator);\n        } else {\n            // eslint-disable-next-line max-len\n            getDisplayMedia = navigator.mediaDevices.getDisplayMedia.bind(navigator.mediaDevices);\n        }\n\n        const audio = this._getAudioConstraints();\n        let video: boolean | IVideoConstraints = {};\n        const constraintOpts: IConstraintOptions = {};\n\n        // The options passed to this method should take precedence over the global settings.\n        const {\n            desktopSharingFrameRate = this.options?.desktopSharingFrameRate,\n            resolution = this.options?.resolution,\n            screenShareSettings = this.options?.screenShareSettings\n        } = options;\n\n        if (typeof desktopSharingFrameRate === 'object') {\n            video.frameRate = desktopSharingFrameRate;\n        }\n\n        // At the time of this writing 'min' constraint for fps is not supported by getDisplayMedia on any of the\n        // browsers. getDisplayMedia will fail with an error \"invalid constraints\" in this case.\n        video.frameRate && delete video.frameRate.min;\n\n        if (browser.isChromiumBased()) {\n            // Show users the current tab is the preferred capture source, default: false.\n            browser.isEngineVersionGreaterThan(93)\n                && (constraintOpts.preferCurrentTab = screenShareSettings?.desktopPreferCurrentTab || false);\n\n            // Allow users to select system audio, default: include.\n            browser.isEngineVersionGreaterThan(104)\n                && (constraintOpts.systemAudio = screenShareSettings?.desktopSystemAudio || 'include');\n\n            // Allow users to seamlessly switch which tab they are sharing without having to select the tab again.\n            browser.isEngineVersionGreaterThan(106)\n                && (constraintOpts.surfaceSwitching = screenShareSettings?.desktopSurfaceSwitching || 'include');\n\n            // Allow a user to be shown a preference for what screen is to be captured, default: unset.\n            browser.isEngineVersionGreaterThan(106) && screenShareSettings?.desktopDisplaySurface\n                && (video.displaySurface = screenShareSettings?.desktopDisplaySurface);\n\n            // Allow users to select the current tab as a capture source, default: exclude.\n            browser.isEngineVersionGreaterThan(111)\n                && (constraintOpts.selfBrowserSurface = screenShareSettings?.desktopSelfBrowserSurface || 'exclude');\n\n            // Set bogus resolution constraints to work around\n            // https://bugs.chromium.org/p/chromium/issues/detail?id=1056311 for low fps screenshare. Capturing SS at\n            // very high resolutions restricts the framerate. Therefore, skip this hack when capture fps > 5 fps.\n            if (!(desktopSharingFrameRate?.max > SS_DEFAULT_FRAME_RATE)) {\n                video.height = 99999;\n                video.width = 99999;\n            }\n        }\n\n        // Allow a user to be shown a preference for what screen is to be captured.\n        if (browser.isSafari() && screenShareSettings?.desktopDisplaySurface) {\n            video.displaySurface = screenShareSettings?.desktopDisplaySurface;\n        }\n\n        if (Object.keys(video).length === 0) {\n            video = true;\n        }\n\n        const constraints = {\n            audio,\n            video,\n            ...constraintOpts,\n            cursor: 'always'\n        } as IDisplayMediaConstraints;\n\n        logger.info('Using getDisplayMedia for screen sharing', constraints);\n\n        getDisplayMedia(constraints)\n            .then(stream => {\n                this.setContentHint(stream);\n\n                // Apply min fps constraints to the track so that 0Hz mode doesn't kick in.\n                // https://bugs.chromium.org/p/webrtc/issues/detail?id=15539\n                if (browser.isChromiumBased()) {\n                    const track = stream.getVideoTracks()[0];\n                    let minFps = SS_DEFAULT_FRAME_RATE;\n\n                    if (typeof desktopSharingFrameRate?.min === 'number' && desktopSharingFrameRate.min > 0) {\n                        minFps = desktopSharingFrameRate.min;\n                    }\n\n                    const trackConstraints: any = {\n                        frameRate: {\n                            min: minFps\n                        }\n                    };\n\n                    // Set the resolution if it is specified in the options. This is currently only enabled for testing.\n                    // Note that this may result in browser crashes if the shared window is resized due to browser bugs\n                    // like https://issues.chromium.org/issues/40672396\n                    if (resolution && this.options.testing?.testMode) {\n                        trackConstraints.height = resolution;\n                        trackConstraints.width = Math.floor(resolution * 16 / 9);\n                    }\n\n                    try {\n                        track.applyConstraints(trackConstraints);\n                    } catch (err) {\n                        logger.warn(`Min fps=${minFps} constraint could not be applied on the desktop track,`\n                            + `${err.message}`);\n                    }\n                }\n\n                const videoTracks = stream?.getVideoTracks();\n                const track = videoTracks?.length > 0 ? videoTracks[0] : undefined;\n                const { deviceId } = track?.getSettings() ?? {};\n\n                callback({\n                    // Used by remote-control to identify the display that is currently shared.\n                    sourceId: deviceId ?? stream.id,\n                    stream\n                });\n            })\n            .catch(error => {\n                const errorDetails = {\n                    errorCode: error.code,\n                    errorMsg: error.message,\n                    errorName: error.name,\n                    errorStack: error.stack\n                };\n\n                logger.warn('getDisplayMedia error', JSON.stringify(constraints), JSON.stringify(errorDetails));\n\n                if (errorDetails.errorCode === DOMException.NOT_SUPPORTED_ERR) {\n                    // This error is thrown when an Electron client has not set a permissions handler.\n                    errorCallback(new JitsiTrackError(JitsiTrackErrors.SCREENSHARING_NOT_SUPPORTED_ERROR));\n                } else if (errorDetails.errorMsg?.indexOf('denied by system') !== -1) {\n                    // On Chrome this is the only thing different between error returned when user cancels\n                    // and when no permission was given on the OS level.\n                    errorCallback(new JitsiTrackError(JitsiTrackErrors.PERMISSION_DENIED));\n                } else if (errorDetails.errorMsg === 'NotReadableError') {\n                    // This can happen under some weird conditions:\n                    //  - https://issues.chromium.org/issues/369103607\n                    //  - https://issues.chromium.org/issues/353555347\n                    errorCallback(new JitsiTrackError(JitsiTrackErrors.SCREENSHARING_GENERIC_ERROR));\n                } else {\n                    errorCallback(new JitsiTrackError(JitsiTrackErrors.SCREENSHARING_USER_CANCELED));\n                }\n            });\n    }\n\n    /**\n     * Obtains a screen capture stream using getDisplayMedia.\n     *\n     * @param callback - The success callback.\n     * @param errorCallback - The error callback.\n     * @internal\n     */\n    obtainScreenFromGetDisplayMediaRN(callback: (result: IScreenCaptureResult) => void, errorCallback: (error: JitsiTrackError) => void) {\n        logger.info('Using getDisplayMedia for screen sharing');\n\n        navigator.mediaDevices.getDisplayMedia({ video: true })\n            .then(stream => {\n                this.setContentHint(stream);\n                callback({\n                    sourceId: stream.id,\n                    stream\n                });\n            })\n            .catch(() => {\n                errorCallback(new JitsiTrackError(JitsiTrackErrors\n                    .SCREENSHARING_USER_CANCELED));\n            });\n    }\n\n    /** Sets the contentHint on the transmitted MediaStreamTrack to indicate charaterstics in the video stream, which\n     * informs RTCPeerConnection on how to encode the track (to prefer motion or individual frame detail).\n     *\n     * @param {MediaStream} stream - The captured desktop stream.\n     * @returns {void}\n     */\n    public setContentHint(stream: MediaStream): void {\n        const { desktopSharingFrameRate } = this.options;\n        const desktopTrack = stream.getVideoTracks()[0];\n\n        // Set contentHint on the desktop track based on the fps requested.\n        if ('contentHint' in desktopTrack) {\n            desktopTrack.contentHint = desktopSharingFrameRate?.max > SS_DEFAULT_FRAME_RATE ? 'motion' : 'detail';\n        } else {\n            logger.warn('MediaStreamTrack contentHint attribute not supported');\n        }\n    }\n\n    /**\n     * Checks whether obtaining a screen capture is supported in the current\n     * environment.\n     * @returns {boolean}\n     */\n    public isSupported(): boolean {\n        return this.obtainStream !== null;\n    }\n\n    /**\n     * Sets the max frame rate to be used for a desktop track capture.\n     *\n     * @param {number} maxFps capture frame rate to be used for desktop tracks.\n     * @returns {void}\n     */\n    public setDesktopSharingFrameRate(maxFps: number): void {\n        logger.info(`Setting the desktop capture rate to ${maxFps}`);\n\n        this.options.desktopSharingFrameRate = {\n            max: maxFps,\n            min: SS_DEFAULT_FRAME_RATE\n        };\n    }\n}\n\nexport default new ScreenObtainer();\n","import { getLogger } from '@jitsi/logger';\nimport { cloneDeep } from 'lodash-es';\nimport 'webrtc-adapter';\n\nimport JitsiTrackError from '../../JitsiTrackError';\nimport * as JitsiTrackErrors from '../../JitsiTrackErrors';\nimport { CameraFacingMode } from '../../service/RTC/CameraFacingMode';\nimport { RTCEvents } from '../../service/RTC/RTCEvents';\nimport Resolutions from '../../service/RTC/Resolutions';\nimport { VideoType } from '../../service/RTC/VideoType';\nimport { AnalyticsEvents } from '../../service/statistics/AnalyticsEvents';\nimport RTCStats from '../RTCStats/RTCStats';\nimport { RTCStatsEvents } from '../RTCStats/RTCStatsEvents';\nimport browser from '../browser';\nimport Statistics from '../statistics/statistics';\nimport Listenable from '../util/Listenable';\nimport { isValidNumber } from '../util/MathUtil';\n\nimport screenObtainer from './ScreenObtainer';\n\nconst logger = getLogger('rtc:RTCUtils');\n\nconst AVAILABLE_DEVICES_POLL_INTERVAL_TIME = 3000; // ms\n\n/**\n * Default MediaStreamConstraints to use for calls to getUserMedia.\n *\n * @private\n */\nconst DEFAULT_CONSTRAINTS = {\n    video: {\n        frameRate: {\n            max: 30,\n            min: 15\n        },\n        height: {\n            ideal: 720,\n            max: 720,\n            min: 180\n        },\n        width: {\n            ideal: 1280,\n            max: 1280,\n            min: 320\n        }\n    }\n};\n\n// Currently audio output device change is supported only in Chrome and\n// default output always has 'default' device ID\nlet audioOutputDeviceId = 'default'; // default device\n// whether user has explicitly set a device to use\nlet audioOutputChanged = false;\n\n// Disables all audio processing\nlet disableAP = false;\n\n// Disables Acoustic Echo Cancellation\nlet disableAEC = false;\n\n// Disables Noise Suppression\nlet disableNS = false;\n\n// Disables Automatic Gain Control\nlet disableAGC = false;\n\n// Enables stereo.\nlet stereo = null;\n\nconst featureDetectionAudioEl = document.createElement('audio');\nlet isAudioOutputDeviceChangeAvailable = typeof featureDetectionAudioEl.setSinkId !== 'undefined';\n\n// The presence of the setSinkId symbol does not imply a working implementation. Probe the API once against the system\n// default sink ('') and downgrade the availability flag if the probe rejects, so the rest of the code stops trying\n// to call setSinkId for the duration of the session.\nif (isAudioOutputDeviceChangeAvailable) {\n    featureDetectionAudioEl.setSinkId('')\n        .catch(error => {\n            isAudioOutputDeviceChangeAvailable = false;\n            logger.info(\n                `setSinkId probe rejected (${error?.name}); audio output device change disabled for this session`);\n        });\n}\n\nlet availableDevices = [];\nlet availableDevicesPollTimer;\n\n/**\n * An empty function.\n */\nfunction emptyFuncton() {\n    // no-op\n}\n\n/**\n * Creates a constraints object to be passed into a call to getUserMedia.\n *\n * @param {Array} um - An array of user media types to get. The accepted types are \"video\", \"audio\", and \"desktop.\"\n * @param {Object} options - Various values to be added to the constraints.\n * @param {string} options.cameraDeviceId - The device id for the video capture device to get video from.\n * @param {Object} options.constraints - Default constraints object to use as a base for the returned constraints.\n * @param {Object} options.desktopStream - The desktop source id from which to capture a desktop sharing video.\n * @param {string} options.facingMode - Which direction the camera is pointing to (applicable on mobile)\n * @param {string} options.micDeviceId - The device id for the audio capture device to get audio from.\n * @private\n * @returns {Object}\n */\nfunction getConstraints(um = [], options = {}) {\n    // Create a deep copy of the constraints to avoid any modification of the passed in constraints object.\n    const constraints = cloneDeep(options.constraints || DEFAULT_CONSTRAINTS);\n\n    if (um.indexOf('video') >= 0) {\n        if (typeof constraints.video !== 'object' || constraints.video === null) {\n            constraints.video = {};\n        }\n\n        // The \"resolution\" option is a shortcut and takes precendence.\n        if (Resolutions[options.resolution]) {\n            const r = Resolutions[options.resolution];\n\n            constraints.video.height = { ideal: r.height };\n            constraints.video.width = { ideal: r.width };\n        }\n\n        if (!constraints.video.height) {\n            constraints.video.height = cloneDeep(DEFAULT_CONSTRAINTS.video.height);\n        }\n        if (!constraints.video.width) {\n            constraints.video.width = cloneDeep(DEFAULT_CONSTRAINTS.video.width);\n        }\n        if (!constraints.video.frameRate) {\n            constraints.video.frameRate = cloneDeep(DEFAULT_CONSTRAINTS.video.frameRate);\n        }\n\n        // Override the constraints on Safari because of the following webkit bug.\n        // https://bugs.webkit.org/show_bug.cgi?id=210932\n        // Camera doesn't start on older macOS versions if min/max constraints are specified.\n        // TODO: remove this hack when the bug fix is available on Mojave, Sierra and High Sierra.\n        if (browser.isWebKitBased()) {\n            if (constraints.video.height && constraints.video.height.ideal) {\n                constraints.video.height = { ideal: constraints.video.height.ideal };\n            } else {\n                logger.warn('Ideal camera height missing, camera may not start properly');\n            }\n            if (constraints.video.width && constraints.video.width.ideal) {\n                constraints.video.width = { ideal: constraints.video.width.ideal };\n            } else {\n                logger.warn('Ideal camera width missing, camera may not start properly');\n            }\n        }\n        if (options.cameraDeviceId) {\n            constraints.video.deviceId = { exact: options.cameraDeviceId };\n        } else if (browser.isMobileDevice()) {\n            constraints.video.facingMode = options.facingMode || CameraFacingMode.USER;\n        }\n    } else {\n        constraints.video = false;\n    }\n\n    if (um.indexOf('audio') >= 0) {\n        if (!constraints.audio || typeof constraints.audio === 'boolean') {\n            constraints.audio = {\n                autoGainControl: !disableAGC && !disableAP,\n                echoCancellation: !disableAEC && !disableAP,\n                noiseSuppression: !disableNS && !disableAP\n            };\n            if (stereo) {\n                Object.assign(constraints.audio, { channelCount: 2 });\n            }\n        } else {\n            const allowedAudioProps = {\n                autoGainControl: 'boolean',\n                channelCount: 'number',\n                echoCancellation: 'boolean',\n                noiseSuppression: 'boolean'\n            };\n\n            const validConstraints = {};\n\n            for (const [ key, value ] of Object.entries(constraints.audio)) {\n                if (allowedAudioProps[key]) {\n                    if (typeof value !== allowedAudioProps[key]) {\n                        continue;\n                    }\n                    if (key === 'channelCount' && ![ 1, 2 ].includes(value)) {\n                        continue;\n                    }\n                    validConstraints[key] = value;\n                }\n            }\n            constraints.audio = validConstraints;\n        }\n\n        if (options.micDeviceId) {\n            constraints.audio.deviceId = { exact: options.micDeviceId };\n        }\n    } else {\n        constraints.audio = false;\n    }\n\n    return constraints;\n}\n\n/**\n * Checks if new list of available media devices differs from previous one.\n * @param {MediaDeviceInfo[]} newDevices - list of new devices.\n * @returns {boolean} - true if list is different, false otherwise.\n */\nfunction compareAvailableMediaDevices(newDevices) {\n    if (newDevices.length !== availableDevices.length) {\n        return true;\n    }\n\n    /* eslint-disable newline-per-chained-call */\n\n    return (\n        newDevices.map(mediaDeviceInfoToJSON).sort().join('')\n            !== availableDevices\n                .map(mediaDeviceInfoToJSON).sort().join(''));\n\n    /* eslint-enable newline-per-chained-call */\n\n    /**\n     *\n     * @param info\n     */\n    function mediaDeviceInfoToJSON(info) {\n        return JSON.stringify({\n            deviceId: info.deviceId,\n            facing: info.facing,\n            groupId: info.groupId,\n            kind: info.kind,\n            label: info.label\n        });\n    }\n}\n\n/**\n * Sends analytics event with the passed device list.\n *\n * @param {Array<MediaDeviceInfo>} deviceList - List with info about the\n * available devices.\n * @returns {void}\n */\nfunction sendDeviceListToAnalytics(deviceList) {\n    const audioInputDeviceCount\n        = deviceList.filter(d => d.kind === 'audioinput').length;\n    const audioOutputDeviceCount\n        = deviceList.filter(d => d.kind === 'audiooutput').length;\n    const videoInputDeviceCount\n        = deviceList.filter(d => d.kind === 'videoinput').length;\n    const videoOutputDeviceCount\n        = deviceList.filter(d => d.kind === 'videooutput').length;\n\n    deviceList.forEach(device => {\n        const attributes = {\n            'audio_input_device_count': audioInputDeviceCount,\n            'audio_output_device_count': audioOutputDeviceCount,\n            'device_group_id': device.groupId,\n            'device_id': device.deviceId,\n            'device_kind': device.kind,\n            'device_label': device.label,\n            'video_input_device_count': videoInputDeviceCount,\n            'video_output_device_count': videoOutputDeviceCount\n        };\n\n        Statistics.sendAnalytics(AnalyticsEvents.AVAILABLE_DEVICE, attributes);\n    });\n}\n\n/**\n *\n */\nclass RTCUtils extends Listenable {\n    /**\n     *\n     */\n    constructor() {\n        super();\n\n        this._initOnce = false;\n    }\n\n    /**\n     * Depending on the browser, sets difference instance methods for\n     * interacting with user media and adds methods to native WebRTC-related\n     * objects. Also creates an instance variable for peer connection\n     * constraints.\n     *\n     * @param {Object} options\n     * @returns {void}\n     */\n    init(options = {}) {\n        if (typeof options.disableAEC === 'boolean') {\n            disableAEC = options.disableAEC;\n            logger.info(`Disable AEC: ${disableAEC}`);\n        }\n        if (typeof options.disableNS === 'boolean') {\n            disableNS = options.disableNS;\n            logger.info(`Disable NS: ${disableNS}`);\n        }\n        if (typeof options.disableAP === 'boolean') {\n            disableAP = options.disableAP;\n            logger.info(`Disable AP: ${disableAP}`);\n        }\n        if (typeof options.disableAGC === 'boolean') {\n            disableAGC = options.disableAGC;\n            logger.info(`Disable AGC: ${disableAGC}`);\n        }\n        if (typeof options.audioQuality?.stereo === 'boolean') {\n            stereo = options.audioQuality.stereo;\n            logger.info(`Stereo: ${stereo}`);\n        }\n\n        if (this._initOnce) {\n            return;\n        }\n\n        // Anything beyond this point needs to be initialized only once.\n        this._initOnce = true;\n\n        window.clearInterval(availableDevicesPollTimer);\n        availableDevicesPollTimer = undefined;\n\n        screenObtainer.init(options);\n\n        this.enumerateDevices(ds => {\n            availableDevices = ds.slice(0);\n\n            logger.debug('Available devices: ', availableDevices);\n            sendDeviceListToAnalytics(availableDevices);\n\n            this.eventEmitter.emit(\n                RTCEvents.DEVICE_LIST_AVAILABLE,\n                availableDevices);\n\n            if (browser.supportsDeviceChangeEvent()) {\n                navigator.mediaDevices.addEventListener(\n                    'devicechange',\n                    () => this.enumerateDevices(emptyFuncton));\n            } else {\n                // Periodically poll enumerateDevices() method to check if\n                // list of media devices has changed.\n                availableDevicesPollTimer = window.setInterval(\n                    () => this.enumerateDevices(emptyFuncton),\n                    AVAILABLE_DEVICES_POLL_INTERVAL_TIME);\n            }\n        });\n    }\n\n    /**\n     * Attaches the given media stream to the given element.\n     *\n     * @param {*} element DOM element.\n     * @param {*} stream MediaStream.\n     * @returns Promise<void>\n     */\n    attachMediaStream(element, stream) {\n        if (element) {\n            element.srcObject = stream;\n        }\n\n        if (element && stream\n                && this.isDeviceChangeAvailable('output')\n                && stream.getAudioTracks().length\n\n                // we skip setting audio output if there was no explicit change\n                && audioOutputChanged) {\n            return element.setSinkId(this.getAudioOutputDevice()).catch(ex => {\n                logger.warn(\n                    'Failed to set audio output device for the element. Default audio output device will be used'\n                        + ' instead',\n                    element?.id,\n                    new JitsiTrackError(ex, null, [ 'audiooutput' ]));\n            });\n        }\n\n        return Promise.resolve();\n    }\n\n    /**\n     *\n     * @param {Function} callback\n     */\n    enumerateDevices(callback) {\n        navigator.mediaDevices.enumerateDevices()\n            .then(devices => {\n                this._updateKnownDevices(devices);\n                callback(devices);\n            })\n            .catch(error => {\n                logger.warn(`Failed to  enumerate devices. ${error}`);\n                this._updateKnownDevices([]);\n                callback([]);\n            });\n    }\n\n    /**\n     * Acquires a media stream via getUserMedia that\n     * matches the given constraints\n     *\n     * @param {array} umDevices which devices to acquire (e.g. audio, video)\n     * @param {Object} constraints - Stream specifications to use.\n     * @param {number} timeout - The timeout in ms for GUM.\n     * @returns {Promise}\n     */\n    _getUserMedia(umDevices, constraints = {}, timeout = 0) {\n        return new Promise((resolve, reject) => {\n            let gumTimeout, timeoutExpired = false;\n\n            if (isValidNumber(timeout) && timeout > 0) {\n                gumTimeout = setTimeout(() => {\n                    timeoutExpired = true;\n                    gumTimeout = undefined;\n\n                    const timeoutError = new JitsiTrackError(JitsiTrackErrors.TIMEOUT);\n\n                    RTCStats.sendStatsEntry(RTCStatsEvents.GET_USER_MEDIA_ERROR_EVENT, null, {\n                        devices: umDevices,\n                        message: timeoutError.message,\n                        name: timeoutError.name\n                    });\n\n                    reject(timeoutError);\n                }, timeout);\n            }\n\n            navigator.mediaDevices.getUserMedia(constraints)\n                .then(stream => {\n                    logger.info('onUserMediaSuccess');\n                    this._updateGrantedPermissions(umDevices, stream);\n                    if (!timeoutExpired) {\n                        if (typeof gumTimeout !== 'undefined') {\n                            clearTimeout(gumTimeout);\n                        }\n                        resolve(stream);\n                    }\n                })\n                .catch(error => {\n                    logger.warn(`Failed to get access to local media. ${error} ${JSON.stringify(constraints)}`);\n                    const jitsiError = new JitsiTrackError(error, constraints, umDevices);\n\n                    if (!timeoutExpired) {\n                        // Skip emitting when the timeout already fired and reported the failure,\n                        // to avoid double-reporting a single gUM call.\n                        RTCStats.sendStatsEntry(RTCStatsEvents.GET_USER_MEDIA_ERROR_EVENT, null, {\n                            constraint: error.constraint,\n                            devices: umDevices,\n                            message: error.message,\n                            name: error.name\n                        });\n\n                        if (typeof gumTimeout !== 'undefined') {\n                            clearTimeout(gumTimeout);\n                        }\n                        reject(jitsiError);\n                    }\n\n                    if (jitsiError.name === JitsiTrackErrors.PERMISSION_DENIED) {\n                        this._updateGrantedPermissions(umDevices, undefined);\n                    }\n                });\n        });\n    }\n\n    /**\n     * Acquire a display stream via the screenObtainer. This requires extra\n     * logic compared to use screenObtainer versus normal device capture logic\n     * in RTCUtils#_getUserMedia.\n     *\n     * @param {Object} options - Optional parameters.\n     * @returns {Promise} A promise which will be resolved with an object which\n     * contains the acquired display stream. If desktop sharing is not supported\n     * then a rejected promise will be returned.\n     */\n    _getDesktopMedia(options) {\n        if (!screenObtainer.isSupported()) {\n            return Promise.reject(new Error('Desktop sharing is not supported!'));\n        }\n\n        return new Promise((resolve, reject) => {\n            screenObtainer.obtainStream(\n                stream => {\n                    resolve(stream);\n                },\n                error => {\n                    reject(error);\n                },\n                options);\n        });\n    }\n\n    /**\n     * Private utility for determining if the passed in MediaStream contains\n     * tracks of the type(s) specified in the requested devices.\n     *\n     * @param {string[]} requestedDevices - The track types that are expected to\n     * be includes in the stream.\n     * @param {MediaStream} stream - The MediaStream to check if it has the\n     * expected track types.\n     * @returns {string[]} An array of string with the missing track types. The\n     * array will be empty if all requestedDevices are found in the stream.\n     */\n    _getMissingTracks(requestedDevices = [], stream) {\n        const missingDevices = [];\n\n        const audioDeviceRequested = requestedDevices.includes('audio');\n        const audioTracksReceived\n            = stream && stream.getAudioTracks().length > 0;\n\n        if (audioDeviceRequested && !audioTracksReceived) {\n            missingDevices.push('audio');\n        }\n\n        const videoDeviceRequested = requestedDevices.includes('video');\n        const videoTracksReceived\n            = stream && stream.getVideoTracks().length > 0;\n\n        if (videoDeviceRequested && !videoTracksReceived) {\n            missingDevices.push('video');\n        }\n\n        return missingDevices;\n    }\n\n    /**\n     * Event handler for the 'devicechange' event.\n     *\n     * @param {MediaDeviceInfo[]} devices - list of media devices.\n     * @emits RTCEvents.DEVICE_LIST_CHANGED\n     */\n    _onMediaDevicesListChanged(devicesReceived) {\n        availableDevices = devicesReceived.slice(0);\n        logger.info('list of media devices has changed:', availableDevices);\n\n        sendDeviceListToAnalytics(availableDevices);\n\n        // Used by tracks to update the real device id before the consumer of lib-jitsi-meet receives the\n        // new device list.\n        this.eventEmitter.emit(RTCEvents.DEVICE_LIST_WILL_CHANGE, availableDevices);\n\n        this.eventEmitter.emit(RTCEvents.DEVICE_LIST_CHANGED, availableDevices);\n    }\n\n    /**\n     * Update known devices.\n     *\n     * @param {Array<Object>} pds - The new devices.\n     * @returns {void}\n     *\n     * NOTE: Use this function as a shared callback to handle both the devicechange event and the\n     * polling implementations.\n     * This prevents duplication and works around a chrome bug (verified to occur on 68) where devicechange\n     * fires twice in a row, which can cause async post devicechange processing to collide.\n     */\n    _updateKnownDevices(pds) {\n        if (compareAvailableMediaDevices(pds)) {\n            this._onMediaDevicesListChanged(pds);\n        }\n    }\n\n    /**\n     * Updates the granted permissions based on the options we requested and the\n     * streams we received.\n     * @param um the options we requested to getUserMedia.\n     * @param stream the stream we received from calling getUserMedia.\n     */\n    _updateGrantedPermissions(um, stream) {\n        const audioTracksReceived\n            = Boolean(stream) && stream.getAudioTracks().length > 0;\n        const videoTracksReceived\n            = Boolean(stream) && stream.getVideoTracks().length > 0;\n        const grantedPermissions = {};\n\n        if (um.indexOf('video') !== -1) {\n            grantedPermissions.video = videoTracksReceived;\n        }\n        if (um.indexOf('audio') !== -1) {\n            grantedPermissions.audio = audioTracksReceived;\n        }\n\n        this.eventEmitter.emit(RTCEvents.PERMISSIONS_CHANGED, grantedPermissions);\n    }\n\n    /**\n     * Gets streams from specified device types. This function intentionally\n     * ignores errors for upstream to catch and handle instead.\n     *\n     * @param {Object} options - A hash describing what devices to get and\n     * relevant constraints.\n     * @param {string[]} options.devices - The types of media to capture. Valid\n     * values are \"desktop\", \"audio\", and \"video\".\n     * @param {Object} [options.desktopSharingFrameRate]\n     * @param {Object} [options.desktopSharingFrameRate.min] - Minimum fps\n     * @param {Object} [options.desktopSharingFrameRate.max] - Maximum fps\n     * @param {string} [options.desktopSharingSourceDevice] - The device id or\n     * label for a video input source that should be used for screensharing.\n     * @param {string[]} [options.desktopSharingSources] - The types of sources (\"screen\", \"window\", etc)\n     * from which the user can select what to share.\n     * @param {string} [options.cameraDeviceId] - Camera device id\n     * @param {string} [options.micDeviceId] - Microphone device id\n     * @param {string} [options.resolution] - Resolution constraints\n     * @param {IStreamEffect[]} [options.effects] - Optional effects array for the track\n     * @param {ITrackConstraints} [options.constraints] - The constraints to use for\n     * the audio and video tracks.\n     * @returns {Promise<IStreamInfo[]>} The promise, when successful, will return an array of\n     * meta data for the requested device type, which includes the stream and\n     * track. If an error occurs, it will be deferred to the caller for\n     * handling.\n     */\n    obtainAudioAndVideoPermissions(options) {\n        const {\n            timeout,\n            ...otherOptions\n        } = options;\n\n        const mediaStreamsMetaData = [];\n        let constraints = {};\n\n        // Declare private functions to be used in the promise chain below.\n        // These functions are declared in the scope of this function because\n        // they are not being used anywhere else, so only this function needs to\n        // know about them.\n\n        /**\n         * Executes a request for desktop media if specified in options.\n         *\n         * @returns {Promise}\n         */\n        const maybeRequestDesktopDevice = function() {\n            const umDevices = otherOptions.devices || [];\n            const isDesktopDeviceRequested\n                = umDevices.indexOf('desktop') !== -1;\n\n            if (!isDesktopDeviceRequested) {\n                return Promise.resolve();\n            }\n\n            const {\n                desktopSharingSourceDevice,\n                desktopSharingSources,\n                resolution\n            } = otherOptions;\n\n            // Attempt to use a video input device as a screenshare source if\n            // the option is defined.\n            if (desktopSharingSourceDevice) {\n                const matchingDevice\n                    = availableDevices && availableDevices.find(device =>\n                        device.kind === 'videoinput'\n                            && (device.deviceId === desktopSharingSourceDevice\n                            || device.label === desktopSharingSourceDevice));\n\n                if (!matchingDevice) {\n                    return Promise.reject(new JitsiTrackError(\n                        { name: 'ConstraintNotSatisfiedError' },\n                        {},\n                        [ desktopSharingSourceDevice ]\n                    ));\n                }\n\n                const requestedDevices = [ 'video' ];\n                const deviceConstraints = {\n                    video: {\n                        deviceId: matchingDevice.deviceId\n\n                        // frameRate is omited here on purpose since this is a device that we'll pretend is a screen.\n                    }\n                };\n\n                return this._getUserMedia(requestedDevices, deviceConstraints, timeout)\n                    .then(stream => {\n                        return {\n                            sourceType: 'device',\n                            stream\n                        };\n                    });\n            }\n\n            return this._getDesktopMedia({\n                desktopSharingSources,\n                resolution });\n        }.bind(this);\n\n        /**\n         * Creates a meta data object about the passed in desktopStream and\n         * pushes the meta data to the internal array mediaStreamsMetaData to be\n         * returned later.\n         *\n         * @param {MediaStreamTrack} desktopStream - A track for a desktop\n         * capture.\n         * @returns {void}\n         */\n        const maybeCreateAndAddDesktopTrack = function(desktopStream) {\n            if (!desktopStream) {\n                return;\n            }\n\n            const { stream, sourceId, sourceType } = desktopStream;\n\n            const desktopAudioTracks = stream.getAudioTracks();\n\n            if (desktopAudioTracks.length) {\n                const desktopAudioStream = new MediaStream(desktopAudioTracks);\n\n                mediaStreamsMetaData.push({\n                    sourceId,\n                    sourceType,\n                    stream: desktopAudioStream,\n                    track: desktopAudioStream.getAudioTracks()[0]\n                });\n            }\n\n            const desktopVideoTracks = stream.getVideoTracks();\n\n            if (desktopVideoTracks.length) {\n                const desktopVideoStream = new MediaStream(desktopVideoTracks);\n\n                mediaStreamsMetaData.push({\n                    sourceId,\n                    sourceType,\n                    stream: desktopVideoStream,\n                    track: desktopVideoStream.getVideoTracks()[0],\n                    videoType: VideoType.DESKTOP\n                });\n            }\n        };\n\n        /**\n         * Executes a request for audio and/or video, as specified in options.\n         * By default both audio and video will be captured if options.devices\n         * is not defined.\n         *\n         * @returns {Promise}\n         */\n        const maybeRequestCaptureDevices = function() {\n            const umDevices = otherOptions.devices || [ 'audio', 'video' ];\n            const requestedCaptureDevices = umDevices.filter(device => device === 'audio' || device === 'video');\n\n            if (!requestedCaptureDevices.length) {\n                return Promise.resolve();\n            }\n\n            constraints = getConstraints(requestedCaptureDevices, otherOptions);\n\n            logger.info('Got media constraints: ', JSON.stringify(constraints));\n\n            return this._getUserMedia(requestedCaptureDevices, constraints, timeout);\n        }.bind(this);\n\n        /**\n         * Splits the passed in media stream into separate audio and video\n         * streams and creates meta data objects for each and pushes them to the\n         * internal array mediaStreamsMetaData to be returned later.\n         *\n         * @param {MediaStreamTrack} avStream - A track for with audio and/or\n         * video track.\n         * @returns {void}\n         */\n        const maybeCreateAndAddAVTracks = function(avStream) {\n            if (!avStream) {\n                return;\n            }\n\n            const audioTracks = avStream.getAudioTracks();\n\n            if (audioTracks.length) {\n                const audioStream = new MediaStream(audioTracks);\n\n                mediaStreamsMetaData.push({\n                    constraints: constraints.audio,\n                    effects: otherOptions.effects,\n                    stream: audioStream,\n                    track: audioStream.getAudioTracks()[0]\n                });\n            }\n\n            const videoTracks = avStream.getVideoTracks();\n\n            if (videoTracks.length) {\n                const videoStream = new MediaStream(videoTracks);\n\n                mediaStreamsMetaData.push({\n                    constraints: constraints.video,\n                    effects: otherOptions.effects,\n                    stream: videoStream,\n                    track: videoStream.getVideoTracks()[0],\n                    videoType: VideoType.CAMERA\n                });\n            }\n        };\n\n        return maybeRequestDesktopDevice()\n            .then(maybeCreateAndAddDesktopTrack)\n            .then(maybeRequestCaptureDevices)\n            .then(maybeCreateAndAddAVTracks)\n            .then(() => mediaStreamsMetaData)\n            .catch(error => {\n                mediaStreamsMetaData.forEach(({ stream }) => {\n                    this.stopMediaStream(stream);\n                });\n\n                return Promise.reject(error);\n            });\n    }\n\n    /**\n     * Returns true if changing the input (camera / microphone) or output\n     * (audio) device is supported and false if not.\n     * @params {string} [deviceType] - type of device to change. Default is\n     *      undefined or 'input', 'output' - for audio output device change.\n     * @returns {boolean} true if available, false otherwise.\n     */\n    isDeviceChangeAvailable(deviceType) {\n        if (deviceType === 'output' || deviceType === 'audiooutput') {\n            return isAudioOutputDeviceChangeAvailable;\n        }\n\n        return true;\n    }\n\n    /**\n     * A method to handle stopping of the stream.\n     * One point to handle the differences in various implementations.\n     * @param mediaStream MediaStream object to stop.\n     */\n    stopMediaStream(mediaStream) {\n        if (!mediaStream) {\n            return;\n        }\n\n        mediaStream.getTracks().forEach(track => {\n            if (track.stop) {\n                track.stop();\n            }\n        });\n\n        // leave stop for implementation still using it\n        if (mediaStream.stop) {\n            mediaStream.stop();\n        }\n\n        // The MediaStream implementation of the react-native-webrtc project has\n        // an explicit release method that is to be invoked in order to release\n        // used resources such as memory.\n        if (mediaStream.release) {\n            mediaStream.release();\n        }\n    }\n\n    /**\n     * Returns whether the desktop sharing is enabled or not.\n     * @returns {boolean}\n     */\n    isDesktopSharingEnabled() {\n        return screenObtainer.isSupported();\n    }\n\n    /**\n     * Sets current audio output device.\n     * @param {string} deviceId - id of 'audiooutput' device from\n     *      navigator.mediaDevices.enumerateDevices(), 'default' for default\n     *      device\n     * @returns {Promise} - resolves when audio output is changed, is rejected\n     *      otherwise\n     */\n    setAudioOutputDevice(deviceId) {\n        if (!this.isDeviceChangeAvailable('output')) {\n            return Promise.reject(\n                new Error('Audio output device change is not supported'));\n        }\n\n        return featureDetectionAudioEl.setSinkId(deviceId)\n            .then(() => {\n                audioOutputDeviceId = deviceId;\n                audioOutputChanged = true;\n\n                logger.debug(`Audio output device set to ${deviceId}`);\n\n                this.eventEmitter.emit(RTCEvents.AUDIO_OUTPUT_DEVICE_CHANGED,\n                    deviceId);\n            });\n    }\n\n    /**\n     * Sets the capture frame rate for desktop tracks.\n     *\n     * @param {number} maxFps - max fps to be used as the capture frame rate.\n     * @returns {void}\n     */\n    setDesktopSharingFrameRate(maxFps) {\n        screenObtainer.setDesktopSharingFrameRate(maxFps);\n    }\n\n    /**\n     * Returns currently used audio output device id, '' stands for default\n     * device\n     * @returns {string}\n     */\n    getAudioOutputDevice() {\n        return audioOutputDeviceId;\n    }\n\n    /**\n     * Returns list of available media devices if its obtained, otherwise an\n     * empty array is returned/\n     * @returns {Array} list of available media devices.\n     */\n    getCurrentlyAvailableMediaDevices() {\n        return availableDevices;\n    }\n\n    /**\n     * Returns event data for device to be reported to stats.\n     * @returns {MediaDeviceInfo} device.\n     */\n    getEventDataForActiveDevice(device) {\n        const deviceList = [];\n        const deviceData = {\n            deviceId: device.deviceId,\n            groupId: device.groupId,\n            kind: device.kind,\n            label: device.label\n        };\n\n        deviceList.push(deviceData);\n\n        return { deviceList };\n    }\n\n    /**\n     * Returns <tt>true<tt/> if a WebRTC MediaStream identified by given stream\n     * ID is considered a valid \"user\" stream which means that it's not a\n     * \"receive only\" stream nor a \"mixed\" JVB stream.\n     *\n     * Clients that implement Unified Plan, such as Firefox use recvonly\n     * \"streams/channels/tracks\" for receiving remote stream/tracks, as opposed\n     * to Plan B where there are only 3 channels: audio, video and data.\n     *\n     * @param {string} streamId The id of WebRTC MediaStream.\n     * @returns {boolean}\n     */\n    isUserStreamById(streamId) {\n        return streamId && streamId !== 'mixedmslabel' && streamId !== 'default';\n    }\n}\n\n\nexport default new RTCUtils();\n","import { getLogger } from '@jitsi/logger';\n\nimport JitsiConference from '../../JitsiConference';\nimport { JitsiTrackEvents } from '../../JitsiTrackEvents';\nimport { MediaType } from '../../service/RTC/MediaType';\nimport { VideoType } from '../../service/RTC/VideoType';\nimport browser from '../browser';\nimport Listenable from '../util/Listenable';\n\nimport RTCUtils from './RTCUtils';\nimport TraceablePeerConnection from './TraceablePeerConnection';\n\n\nconst logger = getLogger('rtc:JitsiTrack');\n\n/**\n * Type for MediaStreamTrack event handler functions.\n */\ntype MediaStreamTrackEventHandler = Optional<((this: MediaStreamTrack, ev: Event) => void)>;\n\n/**\n * Maps our handler types to MediaStreamTrack properties.\n */\nconst trackHandler2Prop = {\n    'track_ended': 'onended',\n    'track_mute': 'onmute', // Not supported on FF\n    'track_unmute': 'onunmute'\n};\n\n/**\n * Extended MediaStreamTrack interface that includes mobile-specific camera methods.\n */\nexport interface IExtendedMediaStreamTrack extends MediaStreamTrack {\n    _switchCamera?: () => void;\n}\n\n/**\n * Extended MediaStream interface that allows setting the muted property.\n */\nexport interface IExtendedMediaStream extends MediaStream {\n    muted?: boolean;\n}\n\n\n/**\n * Represents a single media track (either audio or video).\n *\n * @noInheritDoc\n */\nexport default class JitsiTrack extends Listenable {\n    private _streamInactiveHandler: MediaStreamTrackEventHandler;\n    private handlers: Map<string, MediaStreamTrackEventHandler>;\n    private audioLevel: number;\n    protected containers: HTMLElement[];\n    public type: MediaType;\n    /**\n     *  @internal\n     */\n    stream: IExtendedMediaStream;\n    /**\n     * @internal\n     */\n    track: IExtendedMediaStreamTrack;\n    public conference: JitsiConference;\n    public videoType: Optional<VideoType>;\n    public disposed: boolean;\n\n    /* eslint-disable max-params */\n    /**\n     * Represents a single media track (either audio or video).\n     * @param conference the rtc instance\n     * @param stream the WebRTC MediaStream instance\n     * @param track the WebRTC MediaStreamTrack instance, must be part of\n     * the given <tt>stream</tt>.\n     * @param streamInactiveHandler the function that will handle\n     *        onended/oninactive events of the stream.\n     * @param trackMediaType the media type of the JitsiTrack\n     * @param videoType the VideoType for this track if any\n     */\n    constructor(\n            conference: JitsiConference,\n            stream: MediaStream,\n            track: MediaStreamTrack,\n            streamInactiveHandler: MediaStreamTrackEventHandler,\n            trackMediaType: MediaType,\n            videoType?: VideoType\n    ) {\n        super();\n\n        /**\n         * Array with the HTML elements that are displaying the streams.\n         * @type {Array}\n         */\n        this.containers = [];\n        this.conference = conference;\n        this.audioLevel = -1;\n        this.type = trackMediaType;\n        this.track = track;\n        this.videoType = videoType;\n        this.handlers = new Map();\n\n        /**\n         * Indicates whether this JitsiTrack has been disposed. If true, this\n         * JitsiTrack is to be considered unusable and operations involving it\n         * are to fail (e.g. {@link JitsiConference#addTrack(JitsiTrack)},\n         * {@link JitsiConference#removeTrack(JitsiTrack)}).\n         * @type {boolean}\n         */\n        this.disposed = false;\n\n        /**\n         * The inactive handler which will be triggered when the underlying\n         * <tt>MediaStream</tt> ends.\n         *\n         * @private\n         * @type {Function}\n         */\n        this._streamInactiveHandler = streamInactiveHandler;\n\n        this._setStream(stream);\n    }\n\n    /**\n     * Adds onended/oninactive handler to a MediaStream or a MediaStreamTrack.\n     * Firefox doesn't fire a inactive event on the MediaStream, instead it fires\n     * a onended event on the MediaStreamTrack.\n     * @param {Function} handler the handler\n     */\n    private _addMediaStreamInactiveHandler(handler: MediaStreamTrackEventHandler): void {\n        if (browser.isFirefox() || browser.isWebKitBased()) {\n            this.track.onended = handler;\n        } else {\n            this.stream.oninactive = handler;\n        }\n    }\n\n    /**\n     * Attach time to first media tracker only if there is conference and only\n     * for the first element.\n     *\n     * @param {HTMLElement} container the HTML container which can be 'video' or\n     * 'audio' element.\n     * @internal\n     */\n    protected _attachTTFMTracker(_container: HTMLElement): void {\n        // Should be defined by the classes that are extending JitsiTrack\n    }\n\n    /**\n     * Called when the track has been attached to a new container.\n     *\n     * @param {HTMLElement} container the HTML container which can be 'video' or\n     * 'audio' element.\n     */\n    protected _onTrackAttach(_container: HTMLElement): void {\n        // Should be defined by the classes that are extending JitsiTrack\n    }\n\n    /**\n     * Called when the track has been detached from a container.\n     *\n     * @param {HTMLElement} container the HTML container which can be 'video' or\n     * 'audio' element.\n     */\n    protected _onTrackDetach(_container: HTMLElement): void {\n        // Should be defined by the classes that are extending JitsiTrack\n    }\n\n    /**\n     * Sets the stream property of JitsiTrack object and sets all stored\n     * handlers to it.\n     *\n     * @param {MediaStream} stream the new stream.\n     */\n    protected _setStream(stream: MediaStream): void {\n        if (this.stream === stream) {\n            return;\n        }\n\n        this.stream = stream;\n\n        // TODO Practically, that's like the opposite of _unregisterHandlers\n        // i.e. may be abstracted into a function/method called\n        // _registerHandlers for clarity and easing the maintenance of the two\n        // pieces of source code.\n        if (this.stream) {\n            for (const type of this.handlers.keys()) {\n                this._setHandler(type, this.handlers.get(type));\n            }\n            if (this._streamInactiveHandler) {\n                this._addMediaStreamInactiveHandler(this._streamInactiveHandler);\n            }\n        }\n    }\n\n    /**\n     * Unregisters all event handlers bound to the underlying media stream/track.\n     */\n    protected _unregisterHandlers(): void {\n        if (!this.stream) {\n            logger.warn(\n                `${this}: unable to unregister handlers - no stream object`);\n\n            return;\n        }\n\n        for (const type of this.handlers.keys()) {\n            // FIXME Why only video tracks?\n            for (const videoTrack of this.stream.getVideoTracks()) {\n                videoTrack[trackHandler2Prop[type]] = undefined;\n            }\n        }\n        if (this._streamInactiveHandler) {\n            this._addMediaStreamInactiveHandler(undefined);\n        }\n    }\n\n\n    /**\n     * Sets handler to the WebRTC MediaStream or MediaStreamTrack object\n     * depending on the passed type.\n     * @param {string} type the type of the handler that is going to be set\n     * @param {Function} handler the handler.\n     * @internal\n     */\n    _setHandler(type: string, handler: MediaStreamTrackEventHandler): void {\n        if (!trackHandler2Prop.hasOwnProperty(type)) {\n            logger.error(`Invalid handler type ${type}`);\n\n            return;\n        }\n        if (handler) {\n            this.handlers.set(type, handler);\n        } else {\n            this.handlers.delete(type);\n        }\n\n        if (this.stream) {\n            for (const track of this.stream.getTracks()) {\n                track[trackHandler2Prop[type]] = handler;\n            }\n        }\n    }\n\n    /**\n     * Checks whether the underlying WebRTC <tt>MediaStreamTrack</tt> is muted\n     * according to it's 'muted' field status.\n     * @return {boolean} <tt>true</tt> if the underlying\n     * <tt>MediaStreamTrack</tt> is muted or <tt>false</tt> otherwise.\n     * @internal\n     */\n    isWebRTCTrackMuted(): boolean {\n        return this.track?.muted;\n    }\n\n    /**\n     * Attaches the MediaStream of this track to an HTML container.\n     * Adds the container to the list of containers that are displaying the\n     * track.\n     *\n     * @param container the HTML container which can be 'video' or 'audio'\n     * element.\n     *\n     * @returns {void}\n     */\n    public attach(container: HTMLElement, _decode: boolean): Promise<void> {\n        let result = Promise.resolve();\n\n        if (this.stream) {\n            this._onTrackAttach(container);\n            result = RTCUtils.attachMediaStream(container, this.stream);\n        }\n        this.containers.push(container);\n        this._attachTTFMTracker(container);\n\n        return result;\n    }\n\n    /**\n     * Removes this JitsiTrack from the passed HTML container.\n     *\n     * @param container the HTML container to detach from this JitsiTrack. If\n     * <tt>null</tt> or <tt>undefined</tt>, all containers are removed. A\n     * container can be a 'video', 'audio' or 'object' HTML element instance to\n     * which this JitsiTrack is currently attached.\n     */\n    public detach(container?: HTMLElement): void {\n        for (let cs = this.containers, i = cs.length - 1; i >= 0; --i) {\n            const c = cs[i];\n\n            if (!container) {\n                this._onTrackDetach(c);\n                RTCUtils.attachMediaStream(c, null).catch(() => {\n                    logger.error(`Detach for ${this} failed!`);\n                });\n            }\n            if (!container || c === container) {\n                cs.splice(i, 1);\n            }\n        }\n\n        if (container) {\n            this._onTrackDetach(container);\n            RTCUtils.attachMediaStream(container, null).catch(() => {\n                logger.error(`Detach for ${this} failed!`);\n            });\n        }\n    }\n\n    /**\n     * Removes attached event listeners.\n     *\n     * @returns {Promise}\n     */\n    public dispose(): Promise<void> {\n        const p = Promise.resolve();\n\n        if (this.disposed) {\n            return p;\n        }\n\n        this.detach();\n        this.removeAllListeners();\n\n        this.disposed = true;\n\n        return p;\n    }\n\n    /**\n     * Returns id of the track.\n     * @returns {string|null} id of the track or null if this is fake track.\n     */\n    public getId(): Nullable<string> {\n        return this.getStreamId();\n    }\n\n    /**\n     * Returns the WebRTC MediaStream instance.\n     */\n    public getOriginalStream(): MediaStream {\n        return this.stream;\n    }\n\n    /**\n     * Returns the source name of the track.\n     * @returns {String|undefined}\n     */\n    public getSourceName(): Optional<string> {\n        // Should be defined by the classes that are extending JitsiTrack\n        return undefined;\n    }\n\n    /**\n     * Returns the primary SSRC associated with the track.\n     * @returns {number}\n     */\n    public getSsrc(): Optional<number> { // eslint-disable-line no-unused-vars\n        // Should be defined by the classes that are extending JitsiTrack\n        return undefined;\n    }\n\n    /**\n     * Returns the ID of the underlying WebRTC Media Stream(if any)\n     * @returns {String|null}\n     */\n    public getStreamId(): Nullable<string> {\n        return this.stream ? this.stream.id : null;\n    }\n\n    /**\n     * Return the underlying WebRTC MediaStreamTrack\n     * @returns {MediaStreamTrack}\n     */\n    public getTrack(): MediaStreamTrack {\n        return this.track;\n    }\n\n    /**\n     * Return the underlying WebRTC MediaStreamTrack label\n     * @returns {string}\n     */\n    public getTrackLabel(): string {\n        return this.track.label;\n    }\n\n    /**\n     * Returns the ID of the underlying WebRTC MediaStreamTrack(if any)\n     * @returns {String|null}\n     */\n    public getTrackId(): Nullable<string> {\n        return this.track ? this.track.id : null;\n    }\n\n    /**\n     * Returns the type (audio or video) of this track.\n     */\n    public getType(): MediaType {\n        return this.type;\n    }\n\n    /**\n     * Return meaningful usage label for this track depending on it's media and\n     * eventual video type.\n     * @returns {string}\n     */\n    public getUsageLabel(): string {\n        if (this.isAudioTrack()) {\n            return 'mic';\n        }\n\n        return this.videoType ? this.videoType : 'default';\n    }\n\n    /**\n     * Returns the video type (camera or desktop) of this track.\n     */\n    public getVideoType(): Optional<VideoType> {\n        return this.videoType;\n    }\n\n    /**\n     * Returns the height of the track in normalized landscape format.\n     */\n    public getHeight(): number {\n        return Math.min(this.track.getSettings().height, this.track.getSettings().width);\n    }\n\n    /**\n     * Returns the width of the track in normalized landscape format.\n     */\n    public getWidth(): number {\n        return Math.max(this.track.getSettings().height, this.track.getSettings().width);\n    }\n\n    /**\n     * Checks whether the MediaStream is active/not ended.\n     * When there is no check for active we don't have information and so\n     * will return that stream is active (in case of FF).\n     * @returns {boolean} whether MediaStream is active.\n     */\n    public isActive(): boolean {\n        if (typeof this.stream.active !== 'undefined') {\n            return this.stream.active;\n        }\n\n        return true;\n    }\n\n    /**\n     * Check if this is an audio track.\n     */\n    public isAudioTrack(): boolean {\n        return this.getType() === MediaType.AUDIO;\n    }\n\n    /**\n     * Checks whether this is a local track.\n     * @abstract\n     * @return {boolean} 'true' if it's a local track or 'false' otherwise.\n     */\n    public isLocal() {\n        return false;\n    }\n\n    /**\n     * Check whether this is a local audio track.\n     *\n     * @return {boolean} -  true if track represents a local audio track, false otherwise.\n     */\n    public isLocalAudioTrack(): boolean {\n        return this.isAudioTrack() && this.isLocal();\n    }\n\n    /**\n     * Check if this is a video track.\n     */\n    public isVideoTrack(): boolean {\n        return this.getType() === MediaType.VIDEO;\n    }\n\n    /**\n     * Checks whether this track is muted.\n     * @abstract\n     * @return {boolean}\n     */\n    public isMuted(): boolean {\n        return false;\n    }\n\n    /**\n     * Sets the audio level for the stream\n     * @param {number} audioLevel value between 0 and 1\n     * @param {TraceablePeerConnection} [tpc] the peerconnection instance which\n     * is source for the audio level. It can be <tt>undefined</tt> for\n     * a local track if the audio level was measured outside of the\n     * peerconnection (see /modules/statistics/LocalStatsCollector.js).\n     */\n    public setAudioLevel(audioLevel: number, tpc?: TraceablePeerConnection): void {\n        let newAudioLevel = audioLevel;\n\n        // When using getSynchornizationSources on the audio receiver to gather audio levels for\n        // remote tracks, browser reports last known audio levels even when the remote user is\n        // audio muted, we need to reset the value to zero here so that the audio levels are cleared.\n        // Remote tracks have the tpc info present while local tracks do not.\n        if (browser.supportsReceiverStats() && typeof tpc !== 'undefined' && this.isMuted()) {\n            newAudioLevel = 0;\n        }\n\n        if (this.audioLevel !== newAudioLevel) {\n            this.audioLevel = newAudioLevel;\n            this.emit(\n                JitsiTrackEvents.TRACK_AUDIO_LEVEL_CHANGED,\n                newAudioLevel,\n                tpc);\n\n        // LocalStatsCollector reports a value of 0.008 for muted mics\n        // and a value of 0 when there is no audio input.\n        } else if (this.audioLevel === 0\n            && newAudioLevel === 0\n            && this.isLocal()\n            && !this.isWebRTCTrackMuted()) {\n            this.emit(\n                JitsiTrackEvents.NO_AUDIO_INPUT,\n                newAudioLevel);\n        }\n    }\n\n    /**\n     * Sets new audio output device for track's DOM elements. Video tracks are\n     * ignored. Emits `JitsiTrackEvents.TRACK_AUDIO_OUTPUT_CHANGED`.\n     * @param {string} audioOutputDeviceId - id of 'audiooutput' device from\n     *      navigator.mediaDevices.enumerateDevices(), '' for default device\n     * @returns {Promise}\n     */\n    public setAudioOutput(audioOutputDeviceId: string): Promise<void> {\n        if (this.isVideoTrack()) {\n            return Promise.resolve();\n        }\n\n        if (!RTCUtils.isDeviceChangeAvailable('output')) {\n            return Promise.reject(\n                new Error('Audio output device change is not supported'));\n        }\n\n        // Use Promise.allSettled so a rejection on one container does not short-circuit the others and does not\n        // surface as an unhandled rejection (both callers — RTC._updateAudioOutputForAudioTracks and the\n        // AUDIO_OUTPUT_DEVICE_CHANGED listener on local tracks — invoke this fire-and-forget). The event is\n        // suppressed when every container failed so UI consumers do not show a sink change that did not happen.\n        return Promise.allSettled(\n            this.containers.map(element =>\n                (element as HTMLAudioElement | HTMLVideoElement).setSinkId(audioOutputDeviceId)\n                    .catch(error => {\n                        logger.warn(\n                            'Failed to change audio output device on element. Default or previously set audio'\n                                + ' output device will be used.',\n                            element,\n                            error);\n                        throw error;\n                    })))\n            .then(results => {\n                if (results.some(result => result.status === 'fulfilled')) {\n                    this.emit(JitsiTrackEvents.TRACK_AUDIO_OUTPUT_CHANGED, audioOutputDeviceId);\n                }\n            });\n    }\n\n    /**\n     * Assigns the source name to a track.\n     * @param {String} _name - The name to be assigned to the track.\n     * @returns {void}\n     */\n    public setSourceName(_name: string): void {\n        // Should be defined by the classes that are extending JitsiTrack\n    }\n}\n","import { getLogger } from '@jitsi/logger';\n\nimport JitsiConference from '../../JitsiConference';\nimport JitsiTrackError from '../../JitsiTrackError';\nimport {\n    JitsiTrackErrors,\n    TRACK_IS_DISPOSED,\n    TRACK_NO_STREAM_FOUND\n} from '../../JitsiTrackErrors';\nimport { JitsiTrackEvents } from '../../JitsiTrackEvents';\nimport { CameraFacingMode } from '../../service/RTC/CameraFacingMode';\nimport { MediaType } from '../../service/RTC/MediaType';\nimport { RTCEvents } from '../../service/RTC/RTCEvents';\nimport { VideoType } from '../../service/RTC/VideoType';\nimport {\n    AnalyticsEvents,\n    createNoDataFromSourceEvent\n} from '../../service/statistics/AnalyticsEvents';\nimport RTCStats from '../RTCStats/RTCStats';\nimport { RTCStatsEvents } from '../RTCStats/RTCStatsEvents';\nimport browser from '../browser';\nimport VADAudioAnalyser from '../detection/VADAudioAnalyser';\nimport Statistics from '../statistics/statistics';\nimport { isValidNumber } from '../util/MathUtil';\n\nimport JitsiTrack from './JitsiTrack';\nimport RTCUtils from './RTCUtils';\nimport TraceablePeerConnection from './TraceablePeerConnection';\n\n// eslint-disable-next-line @typescript-eslint/no-require-imports\nconst ort = require('onnxruntime-web/wasm');\n\nort.env.wasm.wasmPaths = '/libs/dist/';\n\nexport let encodingSession = null;\n/**\n * Loads the encoder model\n */\nexport async function loadEncoder() {\n\n    try {\n        encodingSession = await ort.InferenceSession.create('/libs/models/Encoder.onnx', { freeDimensionOverrides: {\n            batch: 1,\n        } });\n    } catch (error) {\n        console.error('Encoder model could not be loaded!: ', error);\n    }\n}\n// loadEncoder();\n\nconst logger = getLogger('rtc:JitsiLocalTrack');\n\nexport interface IStreamEffect {\n    isEnabled: (track: JitsiLocalTrack) => boolean;\n    isMuted?: () => boolean;\n    setMuted?: (muted: boolean) => void;\n    startEffect: (stream: MediaStream) => MediaStream;\n    stopEffect: () => void;\n}\n\nexport interface ITrackMetadata {\n    displaySurface?: string;\n    timestamp: number;\n}\n\nexport interface ITrackConstraints {\n    [key: string]: any;\n    height?: any;\n    width?: any;\n}\n\nexport interface ITrackInfo {\n    constraints: ITrackConstraints;\n    deviceId: string;\n    effects?: IStreamEffect[];\n    facingMode?: CameraFacingMode;\n    mediaType: MediaType;\n    rtcId: number;\n    sourceId?: string;\n    sourceType?: string;\n    stream: MediaStream;\n    track: MediaStreamTrack;\n    videoType?: VideoType;\n}\n\nexport interface IStreamInfo {\n    stream: MediaStream;\n    track: MediaStreamTrack;\n    videoType?: VideoType;\n}\n\nexport interface IAudioConstraints {\n    autoGainControl?: boolean;\n    channelCount?: number;\n    echoCancellation?: boolean;\n    noiseSuppression?: boolean;\n}\n\n/**\n * Represents a single media track(either audio or video).\n * One <tt>JitsiLocalTrack</tt> corresponds to one WebRTC MediaStreamTrack.\n */\nexport default class JitsiLocalTrack extends JitsiTrack {\n    private _setEffectInProgress: boolean;\n    private _constraints: ITrackConstraints;\n    private _prevSetMuted: Promise<void>;\n    private _facingMode?: CameraFacingMode;\n    private _trackEnded: boolean;\n    private _hasSentData: boolean;\n    private _testDataSent: boolean;\n    private _realDeviceId?: string;\n    private _sourceName?: string;\n    private _ssrc?: number;\n    private _trackMutedTS: number;\n    private _onDeviceListWillChange: (devices: MediaDeviceInfo[]) => void;\n    private _onAudioOutputDeviceChanged?: () => void;\n    private _streamEffect?: IStreamEffect;\n    private _originalStream?: MediaStream;\n    private _stopStreamInProgress: boolean;\n    private _effectEnabled?: boolean;\n    public metadata: ITrackMetadata;\n    public rtcId: number;\n    public sourceId?: string;\n    public sourceType?: string;\n    public deviceId: string;\n    public resolution?: number;\n    public maxEnabledResolution?: number;\n    public _encodedStream;\n    public _encodedTrack;\n\n    /**\n     * Constructs a new JitsiLocalTrack instance.\n     *\n     * @param {Object} trackInfo\n     * @param {Object} trackInfo.constraints - The contraints used for creating the track.\n     * @param {number} trackInfo.rtcId - The ID assigned by the RTC module.\n     * @param {Object} trackInfo.stream - The WebRTC MediaStream, parent of the track.\n     * @param {Object} trackInfo.track - The underlying WebRTC MediaStreamTrack for new JitsiLocalTrack.\n     * @param {string} trackInfo.mediaType - The MediaType of the JitsiLocalTrack.\n     * @param {string} trackInfo.videoType - The VideoType of the JitsiLocalTrack.\n     * @param {Array<Object>} trackInfo.effects - The effects to be applied to the JitsiLocalTrack.\n     * @param {string} trackInfo.deviceId - The ID of the local device for this track.\n     * @param {string} trackInfo.facingMode - Thehe camera facing mode used in getUserMedia call (for mobile only).\n     * @param {string} trackInfo.sourceId - The id of the desktop sharing source, which is the Chrome media source ID,\n     * returned by Desktop Picker on Electron. NOTE: defined for desktop sharing tracks only.\n     * @param {string} trackInfo.sourceType - The type of source the track originates from.\n     *\n     * @noInheritDoc\n     */\n    constructor({\n        constraints,\n        deviceId,\n        facingMode,\n        mediaType,\n        rtcId,\n        sourceId,\n        sourceType,\n        stream,\n        track,\n        videoType,\n        effects = []\n    }: ITrackInfo) {\n        super(\n            /* conference */ null,\n            stream,\n            track,\n            /* streamInactiveHandler */ () => this.emit(JitsiTrackEvents.LOCAL_TRACK_STOPPED, this),\n            mediaType,\n            videoType);\n        this._setEffectInProgress = false;\n        const effect = effects.find(e => e.isEnabled(this));\n\n        if (effect) {\n            this._startStreamEffect(effect);\n        }\n\n        const displaySurface = videoType === VideoType.DESKTOP\n            ? track.getSettings().displaySurface\n            : null;\n\n        /**\n         * Track metadata.\n         */\n        this.metadata = {\n            timestamp: Date.now(),\n            ...displaySurface ? { displaySurface } : {}\n        };\n\n\n        /**\n         * The ID assigned by the RTC module on instance creation.\n         *\n         * @type {number}\n         */\n        this.rtcId = rtcId;\n        this.sourceId = sourceId;\n        this.sourceType = sourceType ?? displaySurface;\n        // Cache the constraints of the track in case of any this track\n        // model needs to call getUserMedia again, such as when unmuting.\n        this._constraints = track.getConstraints();\n\n        // Encoded canvas to be sent trought RTC\n        this._encodedStream = null;\n        this._encodedTrack = null;\n\n        if (mediaType === MediaType.VIDEO) {\n            if (videoType === VideoType.CAMERA) {\n                // Safari returns an empty constraints object, construct the constraints using getSettings.\n                // Firefox in \"fingerprint resistance mode\" does a similar thing, except a `mediaSource` key is set.\n                if (!this._constraints.height || !this._constraints.width) {\n                    this._constraints = {\n                        height: { ideal: this.getHeight() },\n                        width: { ideal: this.getWidth() }\n                    };\n                }\n\n                // If the constraints are still empty, fallback to the constraints used for initial gUM.\n                if (!isValidNumber(this._constraints.height.ideal) && !isValidNumber(this._constraints.width.ideal)) {\n                    this._constraints.height = { ideal: constraints.height.ideal };\n                    this._constraints.width = { ideal: constraints.width.ideal };\n                }\n            }\n\n            // Get the resolution from the track itself since we do not know what camera capability the browser has\n            // picked for the given constraints, fallback to the constraints if MediaStreamTrack.getSettings() doesn't\n            // return the height.\n            this.resolution = this.getHeight();\n            if (!isValidNumber(this.resolution) && this._constraints.height?.ideal) {\n                this.resolution = this._constraints.height.ideal;\n            }\n            this.maxEnabledResolution = this.resolution;\n        }\n\n        this.deviceId = deviceId;\n\n        /**\n         * The <tt>Promise</tt> which represents the progress of a previously\n         * queued/scheduled {@link _setMuted} (from the point of view of\n         * {@link _queueSetMuted}).\n         *\n         * @private\n         * @type {Promise}\n         */\n        this._prevSetMuted = Promise.resolve();\n\n        /**\n         * The facing mode of the camera from which this JitsiLocalTrack\n         * instance was obtained.\n         *\n         * @private\n         * @type {CameraFacingMode|undefined}\n         */\n        this._facingMode = facingMode;\n\n        // Currently there is no way to know the MediaStreamTrack ended due to\n        // to device disconnect in Firefox through e.g. \"readyState\" property.\n        // Instead we will compare current track's label with device labels from\n        // enumerateDevices() list.\n        this._trackEnded = false;\n\n        /**\n         * Indicates whether data has been sent or not.\n         */\n        this._hasSentData = false;\n\n        /**\n         * Used only for detection of audio problems. We want to check only once\n         * whether the track is sending data ot not. This flag is set to false\n         * after the check.\n         */\n        this._testDataSent = true;\n\n        // Currently there is no way to determine with what device track was\n        // created (until getConstraints() support), however we can associate\n        // tracks with real devices obtained from enumerateDevices() call as\n        // soon as it's called.\n        // NOTE: this.deviceId corresponds to the device id specified in GUM constraints and this._realDeviceId seems to\n        // correspond to the id of a matching device from the available device list.\n        this._realDeviceId = this.deviceId === '' ? undefined : this.deviceId;\n\n        // The source name that will be signaled for this track.\n        this._sourceName = null;\n\n        // The primary SSRC associated with the local media track. This will be set after the local desc\n        // is processed once the track is added to the peerconnection.\n        this._ssrc = null;\n\n        this._trackMutedTS = 0;\n\n        this._onDeviceListWillChange = (devices: MediaDeviceInfo[]) => {\n            const oldRealDeviceId = this._realDeviceId;\n\n            this._setRealDeviceIdFromDeviceList(devices);\n\n            if (\n                // Mark track as ended for those browsers that do not support\n                // \"readyState\" property. We do not touch tracks created with\n                // default device ID \"\".\n                (typeof this.getTrack().readyState === 'undefined'\n                    && typeof this._realDeviceId !== 'undefined'\n                    && !devices.find(d => d.deviceId === this._realDeviceId))\n\n                // If there was an associated realDeviceID and after the device change the realDeviceId is undefined\n                // then the associated device has been disconnected and the _trackEnded flag needs to be set. In\n                // addition on some Chrome versions the readyState property is set after the device change event is\n                // triggered which causes issues in jitsi-meet with the selection of a new device because we don't\n                // detect that the old one was removed.\n                || (typeof oldRealDeviceId !== 'undefined' && typeof this._realDeviceId === 'undefined')\n            ) {\n                this._trackEnded = true;\n            }\n        };\n\n        // Subscribe each created local audio track to\n        // RTCEvents.AUDIO_OUTPUT_DEVICE_CHANGED event. This is different from\n        // handling this event for remote tracks (which are handled in RTC.js),\n        // because there might be local tracks not attached to a conference.\n        if (this.isAudioTrack() && RTCUtils.isDeviceChangeAvailable('output')) {\n            this._onAudioOutputDeviceChanged = this.setAudioOutput.bind(this);\n            RTCUtils.addListener(\n                RTCEvents.AUDIO_OUTPUT_DEVICE_CHANGED,\n                this._onAudioOutputDeviceChanged);\n        }\n\n        RTCUtils.addListener(RTCEvents.DEVICE_LIST_WILL_CHANGE, this._onDeviceListWillChange);\n\n        this._initNoDataFromSourceHandlers();\n\n        // if (mediaType === MediaType.VIDEO) {\n        //     if (videoType === VideoType.CAMERA) {\n        //         this.encodingRoutine();\n        //     }\n        // }\n    }\n\n    /**\n     * Adds stream to conference and marks it as \"unmute\" operation.\n     *\n     * @private\n     * @returns {Promise}\n     */\n    private _addStreamToConferenceAsUnmute(): Promise<void> {\n        if (!this.conference) {\n            return Promise.resolve();\n        }\n\n        // FIXME it would be good to not included conference as part of this process. Only TraceablePeerConnections to\n        // which the track is attached should care about this action. The TPCs to which the track is not attached can\n        // sync up when track is re-attached. A problem with that is that the \"modify sources\" queue is part of the\n        // JingleSessionPC and it would be excluded from the process. One solution would be to extract class between\n        // TPC and JingleSessionPC which would contain the queue and would notify the signaling layer when local SSRCs\n        // are changed. This would help to separate XMPP from the RTC module.\n        return new Promise((resolve, reject) => {\n            this.conference._addLocalTrackToPc(this)\n                .then(resolve, (error: any) => reject(new Error(error)));\n        });\n    }\n\n    /**\n     * Fires NO_DATA_FROM_SOURCE event and logs it to analytics\n     *\n     * @private\n     * @returns {void}\n     */\n    private _fireNoDataFromSourceEvent(): void {\n        const value = !this.isReceivingData();\n\n        this.emit(JitsiTrackEvents.NO_DATA_FROM_SOURCE, value);\n\n        logger.debug(`NO_DATA_FROM_SOURCE event with value ${value} detected for track: ${this}`);\n\n        // FIXME: Should we report all of those events\n        Statistics.sendAnalytics(createNoDataFromSourceEvent(this.getType(), value));\n    }\n\n    /**\n     * Sets handlers to the MediaStreamTrack object that will detect camera issues.\n     *\n     * @private\n     * @returns {void}\n     */\n    private _initNoDataFromSourceHandlers(): void {\n        if (!this._isNoDataFromSourceEventsEnabled()) {\n            return;\n        }\n\n        this._setHandler('track_mute', () => {\n            this._trackMutedTS = window.performance.now();\n            this._fireNoDataFromSourceEvent();\n        });\n\n        this._setHandler('track_unmute', () => {\n            this._fireNoDataFromSourceEvent();\n            Statistics.sendAnalyticsAndLog(\n                AnalyticsEvents.TRACK_UNMUTED,\n                {\n                    'media_type': this.getType(),\n                    'track_type': 'local',\n                    value: window.performance.now() - this._trackMutedTS\n                });\n        });\n\n        if (this.isVideoTrack() && this.videoType === VideoType.CAMERA) {\n            this._setHandler('track_ended', () => {\n                if (!this.isReceivingData()) {\n                    this._fireNoDataFromSourceEvent();\n                }\n            });\n        }\n    }\n\n    /**\n     * Returns true if no data from source events are enabled for this JitsiLocalTrack and false otherwise.\n     *\n     * @private\n     * @returns {boolean} - True if no data from source events are enabled for this JitsiLocalTrack and false otherwise.\n     */\n    private _isNoDataFromSourceEventsEnabled(): boolean {\n        // Disable the events for screen sharing.\n        return !this.isVideoTrack() || this.videoType !== VideoType.DESKTOP;\n    }\n\n    /**\n     * Initializes a new Promise to execute {@link #_setMuted}. May be called multiple times in a row and the\n     * invocations of {@link #_setMuted} and, consequently, {@link #mute} and/or {@link #unmute} will be resolved in a\n     * serialized fashion.\n     *\n     * @param {boolean} muted - The value to invoke <tt>_setMuted</tt> with.\n     * @private\n     * @returns {Promise}\n     */\n    private _queueSetMuted(muted: boolean): Promise<void> {\n        const setMuted = this._setMuted.bind(this, muted);\n\n        this._prevSetMuted = this._prevSetMuted.then(setMuted, setMuted);\n\n        return this._prevSetMuted;\n    }\n\n    /**\n     * Removes stream from conference and marks it as \"mute\" operation.\n     *\n     * @param {Function} successCallback - Callback that will be called when the operation is successful.\n     * @param {Function} errorCallback - Callback that will be called when the operation fails.\n     * @private\n     * @returns {Promise}\n     */\n    private _removeStreamFromConferenceAsMute(successCallback: () => void, errorCallback: (error: Error) => void): void {\n        if (!this.conference) {\n            successCallback();\n\n            return;\n        }\n        this.conference._removeLocalTrackFromPc(this).then(\n            successCallback,\n            (error: any) => errorCallback(new Error(error)));\n    }\n\n    /**\n     * Mutes / unmutes this track.\n     *\n     * @param {boolean} muted - If <tt>true</tt>, this track will be muted; otherwise, this track will be unmuted.\n     * @private\n     * @returns {Promise}\n     */\n    private _setMuted(muted: boolean): Promise<void> {\n        if (this.isMuted() === muted && this.videoType !== VideoType.DESKTOP) {\n            return Promise.resolve();\n        }\n\n        if (this.disposed) {\n            return Promise.reject(new JitsiTrackError(TRACK_IS_DISPOSED));\n        }\n\n        let promise: Promise<void | IStreamInfo[]> = Promise.resolve();\n\n        // A function that will print info about muted status transition\n        const logMuteInfo = () => logger.info(`Mute ${this}: ${muted}`);\n\n        // In React Native we mute the camera by setting track.enabled but that doesn't\n        // work for screen-share tracks, so do the remove-as-mute for those.\n        const doesVideoMuteByStreamRemove\n            = browser.isReactNative() ? this.videoType === VideoType.DESKTOP : browser.doesVideoMuteByStreamRemove();\n\n        // In the multi-stream mode, desktop tracks are muted from jitsi-meet instead of being removed from the\n        // conference. This is needed because we don't want the client to signal a source-remove to the remote peer for\n        // the desktop track when screenshare is stopped. Later when screenshare is started again, the same sender will\n        // be re-used without the need for signaling a new ssrc through source-add.\n        if (this.isAudioTrack() || !doesVideoMuteByStreamRemove) {\n            logMuteInfo();\n\n            // If we have a stream effect that implements its own mute functionality, prioritize it before\n            // normal mute e.g. the stream effect that implements system audio sharing has a custom\n            // mute state in which if the user mutes, system audio still has to go through.\n            if (this._streamEffect?.setMuted) {\n                this._streamEffect.setMuted(muted);\n            } else if (this.track) {\n                this.track.enabled = !muted;\n            }\n        } else if (muted) {\n            promise = new Promise((resolve, reject) => {\n                logMuteInfo();\n                this._removeStreamFromConferenceAsMute(\n                    () => {\n                        if (this._streamEffect) {\n                            this._stopStreamEffect();\n                        }\n\n                        // FIXME: Maybe here we should set the SRC for the\n                        // containers to something\n                        // We don't want any events to be fired on this stream\n                        this._unregisterHandlers();\n                        this.stopStream();\n                        this._setStream(null);\n\n                        resolve();\n                    },\n                    reject);\n            });\n        } else {\n            logMuteInfo();\n\n            let streamOptions;\n\n            if (this.videoType === VideoType.CAMERA) {\n                streamOptions = {\n                    cameraDeviceId: this.getDeviceId(),\n                    devices: [ MediaType.VIDEO ],\n                    effects: this._streamEffect ? [ this._streamEffect ] : [],\n                    facingMode: this.getCameraFacingMode()\n                };\n            } else {\n                streamOptions = {\n                    devices: [ MediaType.DESKTOP ],\n                };\n            }\n\n            promise\n                = RTCUtils.obtainAudioAndVideoPermissions({\n\n                    ...streamOptions,\n                    constraints: { video: this._constraints } }) as Promise<IStreamInfo[]>;\n\n            promise = promise.then((streamsInfo: IStreamInfo[]) => {\n                const streamInfo = streamsInfo.find(info => info.track.kind === this.getType());\n\n                if (streamInfo) {\n                    this._setStream(streamInfo.stream);\n                    this.track = streamInfo.track;\n\n                    // This is not good when video type changes after\n                    // unmute, but let's not crash here\n                    if (this.videoType !== streamInfo.videoType) {\n                        logger.warn(\n                            `${this}: video type has changed after unmute!`,\n                            this.videoType, streamInfo.videoType);\n                        this.videoType = streamInfo.videoType;\n                    }\n                } else {\n                    throw new JitsiTrackError(TRACK_NO_STREAM_FOUND);\n                }\n\n                if (this._streamEffect) {\n                    this._startStreamEffect(this._streamEffect);\n                }\n\n                this.containers.map(cont => RTCUtils.attachMediaStream(cont, this.stream).catch(() => {\n                    logger.error(`Attach media failed for ${this} on video unmute!`);\n                }));\n\n                return this._addStreamToConferenceAsUnmute();\n            });\n        }\n\n        return promise\n            .then(() => {\n                this._sendMuteStatus(muted);\n                const event = this.isAudioTrack() ? RTCStatsEvents.AUDIO_MUTE_CHANGED_EVENT : RTCStatsEvents.VIDEO_MUTE_CHANGED_EVENT;\n\n                RTCStats.sendStatsEntry(event, null, muted);\n\n                // Send the videoType message to the bridge.\n                this.isVideoTrack() && this.conference?._sendBridgeVideoTypeMessage(this);\n                this.emit(JitsiTrackEvents.TRACK_MUTE_CHANGED, this);\n            });\n    }\n\n    /**\n     * Sets real device ID by comparing track information with device information. This is temporary solution until\n     * getConstraints() method will be implemented in browsers.\n     *\n     * @param {MediaDeviceInfo[]} devices - The list of devices obtained from enumerateDevices() call.\n     * @private\n     * @returns {void}\n     */\n    private _setRealDeviceIdFromDeviceList(devices: MediaDeviceInfo[]): void {\n        const track = this.getTrack();\n        const kind = `${track.kind}input`;\n\n        // We need to match by deviceId as well, in case of multiple devices with the same label.\n        let device = devices.find(d => d.kind === kind && d.label === track.label && d.deviceId === this.deviceId);\n\n        if (!device && this._realDeviceId === 'default') { // the default device has been changed.\n            // If the default device was 'A' and the default device is changed to 'B' the label for the track will\n            // remain 'Default - A' but the label for the device in the device list will be updated to 'A'. That's\n            // why in order to match it we need to remove the 'Default - ' part.\n            const label = (track.label || '').replace('Default - ', '');\n\n            device = devices.find(d => d.kind === kind && d.label === label);\n        }\n\n        if (device) {\n            this._realDeviceId = device.deviceId;\n        } else {\n            this._realDeviceId = undefined;\n        }\n    }\n\n    /**\n     * Starts the effect process and returns the modified stream.\n     *\n     * @param {Object} effect - Represents effect instance\n     * @private\n     * @returns {void}\n     */\n    private _startStreamEffect(effect: IStreamEffect): void {\n        this._streamEffect = effect;\n        this._originalStream = this.stream;\n        this._setStream(this._streamEffect.startEffect(this._originalStream));\n        this.track = this.stream.getTracks()[0];\n        this._effectEnabled = true;\n    }\n\n    /**\n     * Stops the effect process and returns the original stream.\n     *\n     * @private\n     * @returns {void}\n     */\n    private _stopStreamEffect(): void {\n        if (this._streamEffect) {\n            this._streamEffect.stopEffect();\n            this._setStream(this._originalStream);\n            this._originalStream = null;\n            this.track = this.stream ? this.stream.getTracks()[0] : null;\n            this._effectEnabled = false;\n        }\n    }\n\n    /**\n     * Switches the camera facing mode if the WebRTC implementation supports the custom MediaStreamTrack._switchCamera\n     * method. Currently, the method in question is implemented in react-native-webrtc only. When such a WebRTC\n     * implementation is executing, the method is the preferred way to switch between the front/user-facing and the\n     * back/environment-facing cameras because it will likely be (as is the case of react-native-webrtc) noticeably\n     * faster that creating a new MediaStreamTrack via a new getUserMedia call with the switched facingMode constraint\n     * value. Moreover, the approach with a new getUserMedia call may not even work: WebRTC on Android and iOS is\n     * either very slow to open the camera a second time or plainly freezes attempting to do that.\n     *\n     * @returns {void}\n     */\n    private _switchCamera(): void {\n        if (this.isVideoTrack()\n            && this.videoType === VideoType.CAMERA\n            && typeof this.track._switchCamera === 'function') {\n            this.track._switchCamera();\n\n            this._facingMode\n                = this._facingMode === CameraFacingMode.ENVIRONMENT\n                    ? CameraFacingMode.USER\n                    : CameraFacingMode.ENVIRONMENT;\n        }\n    }\n\n    /**\n     * Stops the currently used effect (if there is one) and starts the passed effect (if there is one).\n     *\n     * @param {Object|undefined} effect - The new effect to be set.\n     * @private\n     * @returns {void}\n     */\n    private _switchStreamEffect(effect?: IStreamEffect): void {\n        if (this._streamEffect) {\n            this._stopStreamEffect();\n            this._streamEffect = undefined;\n        }\n        if (effect) {\n            this._startStreamEffect(effect);\n        }\n    }\n\n    /**\n     * @inheritdoc\n     *\n     * Stops sending the media track. And removes it from the HTML. NOTE: Works for local tracks only.\n     *\n     * @returns {Promise}\n     */\n    override async dispose(): Promise<void> {\n        if (this.disposed) {\n            return;\n        }\n\n        // Remove the effect instead of stopping it so that the original stream is restored\n        // on both the local track and on the peerconnection.\n        if (this._streamEffect) {\n            await this.setEffect(undefined);\n        }\n\n        if (this.conference) {\n            await this.conference.removeTrack(this);\n        }\n\n        if (this.stream) {\n            this.stopStream();\n        }\n\n        RTCUtils.removeListener(RTCEvents.DEVICE_LIST_WILL_CHANGE, this._onDeviceListWillChange);\n\n        if (this._onAudioOutputDeviceChanged) {\n            RTCUtils.removeListener(RTCEvents.AUDIO_OUTPUT_DEVICE_CHANGED,\n                this._onAudioOutputDeviceChanged);\n        }\n\n        return super.dispose();\n    }\n\n    /**\n     * Starts to encode the incoming images from the camera\n     */\n    encodingRoutine() {\n        // Creating canvas stream that will be sent to other participants\n        const canvasEncoded = document.createElement('canvas');\n\n        this._encodedStream = canvasEncoded.captureStream();\n        // Extracting track from canvas-sender\n        this._encodedTrack = this._encodedStream.getVideoTracks()[0];\n        const videoTrack = this.stream.getVideoTracks()[0];\n\n        // Applying onnx model to original stream and saving the output in the canvas-sender\n        this._applyONNXEncoder(videoTrack, canvasEncoded);\n    }\n\n    /**\n     *  Encoding/resizing algorithm, reduces the size of the input video by 1/4 (compression: 100*(1-1/(4**2))=93.75%)\n     * @param {*} stream original stream\n     * @param {*} canvasEncoded  canvas-sender that will be transformed in a stream carrying the encoded/resized image\n     */\n    _applyONNXEncoder(videoTrack, canvasEncoded) {\n        // Frame grabber from original track\n        const imageCapture = new ImageCapture(videoTrack);\n        // Extracting size from original track\n        const width = videoTrack.getSettings().width;\n        const height = videoTrack.getSettings().height;\n\n        // Setting canvas size where the encoded/resized image will be set\n        canvasEncoded.width = width / 2;\n        canvasEncoded.height = height / 2;\n        // Creating and preparing aux canvas where the grabbed frame will be painted\n        const canvasRaw = document.createElement('canvas');\n        const ctxRaw = canvasRaw.getContext('2d', { willReadFrequently: true });\n\n        canvasRaw.width = width;\n        canvasRaw.height = height;\n        const ctxEncoded = canvasEncoded.getContext('2d', { willReadFrequently: true });\n\n        /**\n         * Encodes each frame received by the camera, this function is repeated in loop\n         */\n        async function processFrame() {\n            try {\n                // Captures a frame from the original source\n                const frame = await imageCapture.grabFrame();\n\n                // Paints the frame in the aux canvas\n                ctxRaw.drawImage(frame, 0, 0, width, height);\n\n\n                // Moving data to set channels order as required by RTCweb standars\n                const encodedImg = ctxEncoded.createImageData(canvasEncoded.width, canvasEncoded.height);\n\n                // Setting encoded /resized image in the canvas-sender\n                ctxEncoded.putImageData(encodedImg, 0, 0);\n\n            } catch (error) {\n                logger.info('Error in encoder: ', error);\n            }\n            // Requesting loop\n            if (videoTrack.readyState == 'live') {\n                requestAnimationFrame(processFrame);\n            }\n        }\n        processFrame();\n    }\n\n    /**\n     * Returns the stream with the encoded/resize image\n     * @returns MediaStream\n     */\n    getEncodedStream() {\n        return this._encodedStream;\n    }\n\n    /**\n     * Returns the track /canvas with the encoded/resized image\n     * @returns CanvasCaptureMediaStreamTrack\n     */\n    getEncodedTrack() {\n        return this._encodedTrack;\n    }\n\n    /**\n     * Sends mute status for a track to conference if any.\n     *\n     * @param {boolean} mute - If track is muted.\n     * @internal\n     * @returns {void}\n     */\n    _sendMuteStatus(mute: boolean): void {\n        if (this.conference) {\n            this.conference._setTrackMuteStatus(this, mute) && this.conference.room.sendPresence();\n        }\n    }\n\n    /**\n     * Returns facing mode for video track from camera. For other cases (e.g. audio track or 'desktop' video track)\n     * returns undefined.\n     *\n     * @returns {Optional<CameraFacingMode>}\n     */\n    getCameraFacingMode(): Optional<CameraFacingMode> {\n        if (this.isVideoTrack() && this.videoType === VideoType.CAMERA) {\n            // MediaStreamTrack#getSettings() is not implemented in many\n            // browsers, so we need feature checking here. Progress on the\n            // respective browser's implementation can be tracked at\n            // https://bugs.chromium.org/p/webrtc/issues/detail?id=2481 for\n            // Chromium and https://bugzilla.mozilla.org/show_bug.cgi?id=1213517\n            // for Firefox. Even if a browser implements getSettings() already,\n            // it might still not return anything for 'facingMode'.\n            const trackSettings = this.track.getSettings?.();\n\n            if (trackSettings && 'facingMode' in trackSettings) {\n                return trackSettings.facingMode as CameraFacingMode;\n            }\n\n            if (typeof this._facingMode !== 'undefined') {\n                return this._facingMode;\n            }\n\n            // In most cases we are showing a webcam. So if we've gotten here,\n            // it should be relatively safe to assume that we are probably\n            // showing the user-facing camera.\n            return CameraFacingMode.USER;\n        }\n\n        return undefined;\n    }\n\n    /**\n     * Returns the capture resolution of the video track.\n     *\n     * @returns {Number}\n     */\n    getCaptureResolution(): number {\n        if (this.videoType === VideoType.CAMERA || !browser.isWebKitBased()) {\n            return this.resolution!;\n        }\n\n        return this.getHeight();\n    }\n\n    /**\n     * Returns device id associated with track.\n     *\n     * @returns {string}\n     */\n    getDeviceId(): string {\n        return this._realDeviceId || this.deviceId;\n    }\n\n    /**\n     * Get the duration of the track.\n     *\n     * @returns {Number} the duration of the track in seconds\n     */\n    getDuration(): number {\n        return (Date.now() / 1000) - (this.metadata.timestamp / 1000);\n    }\n\n    /**\n     * Returns the participant id which owns the track.\n     *\n     * @returns {string} the id of the participants. It corresponds to the\n     * Colibri endpoint id/MUC nickname in case of Jitsi-meet.\n     */\n    getParticipantId(): string {\n        return this.conference?.myUserId();\n    }\n\n    /**\n     * Returns the source name associated with the jitsi track.\n     *\n     * @returns {Nullable<string>} source name\n     */\n    override getSourceName(): Nullable<string> {\n        return this._sourceName;\n    }\n\n    /**\n     * Returns the primary SSRC associated with the track.\n     * @returns {Nullable<number>}\n     */\n    override getSsrc(): Nullable<number> {\n        return this._ssrc;\n    }\n\n    /**\n     * Returns if associated MediaStreamTrack is in the 'ended' state\n     *\n     * @returns {boolean}\n     */\n    isEnded(): boolean {\n        if (this.isVideoTrack() && this.isMuted()) {\n            // If a video track is muted the readyState will be ended, that's why we need to rely only on the\n            // _trackEnded flag.\n            return this._trackEnded;\n        }\n\n        return this.getTrack().readyState === 'ended' || this._trackEnded;\n    }\n\n    /**\n     * Returns <tt>true</tt>.\n     *\n     * @returns {boolean} <tt>true</tt>\n     */\n    override isLocal(): boolean {\n        return true;\n    }\n\n    /**\n     * Returns <tt>true</tt> - if the stream is muted and <tt>false</tt> otherwise.\n     *\n     * @returns {boolean} <tt>true</tt> - if the stream is muted and <tt>false</tt> otherwise.\n     */\n    override isMuted(): boolean {\n        // this.stream will be null when we mute local video on Chrome\n        if (!this.stream) {\n            return true;\n        }\n        if (this.isVideoTrack() && !this.isActive()) {\n            return true;\n        }\n\n        // If currently used stream effect has its own muted state, use that.\n        if (this._streamEffect?.isMuted) {\n            return this._streamEffect.isMuted();\n        }\n\n        return !this.track?.enabled;\n    }\n\n    /**\n     * Checks whether the attached MediaStream is receiving data from source or not. If the stream property is null\n     * (because of mute or another reason) this method will return false.\n     * NOTE: This method doesn't indicate problem with the streams directly. For example in case of video mute the\n     * method will return false or if the user has disposed the track.\n     *\n     * @returns {boolean} true if the stream is receiving data and false this otherwise.\n     */\n    isReceivingData(): boolean {\n        if (this.isVideoTrack()\n            && (this.isMuted() || this._stopStreamInProgress || this.videoType === VideoType.DESKTOP)) {\n            return true;\n        }\n\n        if (!this.stream) {\n            return false;\n        }\n\n        // In older version of the spec there is no muted property and readyState can have value muted. In the latest\n        // versions readyState can have values \"live\" and \"ended\" and there is muted boolean property. If the stream is\n        // muted that means that we aren't receiving any data from the source. We want to notify the users for error if\n        // the stream is muted or ended on it's creation.\n\n        // For video blur enabled use the original video stream\n        const stream = this._effectEnabled ? this._originalStream : this.stream;\n\n        return stream.getTracks().some(track =>\n            (!('readyState' in track) || track.readyState === 'live')\n            && (!('muted' in track) || track.muted !== true));\n    }\n\n    /**\n     * Asynchronously mutes this track.\n     *\n     * @returns {Promise}\n     */\n    mute(): Promise<void> {\n        return this._queueSetMuted(true);\n    }\n\n    /**\n     * Handles bytes sent statistics. NOTE: used only for audio tracks to detect audio issues.\n     *\n     * @param {TraceablePeerConnection} tpc - The peerconnection that is reporting the bytes sent stat.\n     * @param {number} bytesSent - The new value.\n     * @returns {void}\n     */\n    onByteSentStatsReceived(tpc: TraceablePeerConnection, bytesSent: number): void {\n        if (bytesSent > 0) {\n            this._hasSentData = true;\n        }\n        const iceConnectionState = tpc.getConnectionState();\n\n        if (this._testDataSent && iceConnectionState === 'connected') {\n            setTimeout(() => {\n                if (!this._hasSentData) {\n                    logger.warn(`${this} 'bytes sent' <= 0: \\\n                        ${bytesSent}`);\n\n                    Statistics.analytics.sendEvent(AnalyticsEvents.NO_BYTES_SENT, { 'media_type': this.getType() });\n                }\n            }, 3000);\n            this._testDataSent = false;\n        }\n    }\n\n    /**\n     * Sets the JitsiConference object associated with the track. This is temp solution.\n     *\n     * @param conference - JitsiConference object.\n     * @returns {void}\n     */\n    setConference(conference: JitsiConference): void {\n        this.conference = conference;\n    }\n\n    /**\n     * Sets the effect and switches between the modified stream and original one.\n     *\n     * @param {Object} effect - Represents the effect instance to be used.\n     * @returns {Promise}\n     */\n    setEffect(effect?: IStreamEffect): Promise<void> {\n        if (typeof this._streamEffect === 'undefined' && typeof effect === 'undefined') {\n            return Promise.resolve();\n        }\n\n        if (typeof effect !== 'undefined' && !effect.isEnabled(this)) {\n            return Promise.reject(new Error('Incompatible effect instance!'));\n        }\n\n        if (this._setEffectInProgress === true) {\n            return Promise.reject(new Error('setEffect already in progress!'));\n        }\n\n        // In case we have an audio track that is being enhanced with an effect, we still want it to be applied,\n        // even if the track is muted. Where as for video the actual track doesn't exists if it's muted.\n        if (this.isMuted() && !this.isAudioTrack()) {\n            this._streamEffect = effect;\n\n            return Promise.resolve();\n        }\n\n        const conference = this.conference;\n\n        if (!conference) {\n            this._switchStreamEffect(effect);\n            if (this.isVideoTrack()) {\n                this.containers.forEach(cont => {\n                    RTCUtils.attachMediaStream(cont, this.stream).catch(() => {\n                        logger.error(`Attach media failed for ${this} when trying to set effect.`);\n                    });\n                });\n            }\n\n            return Promise.resolve();\n        }\n\n        this._setEffectInProgress = true;\n\n        return conference._removeLocalTrackFromPc(this)\n            .then(() => {\n                this._switchStreamEffect(effect);\n                if (this.isVideoTrack()) {\n                    this.containers.forEach(cont => {\n                        RTCUtils.attachMediaStream(cont, this.stream).catch(() => {\n                            logger.error(`Attach media failed for ${this} when trying to set effect.`);\n                        });\n                    });\n                }\n\n                return conference._addLocalTrackToPc(this);\n            })\n            .then(() => {\n                this._setEffectInProgress = false;\n            })\n            .catch((error: any) => {\n                // Any error will be not recovarable and will trigger CONFERENCE_FAILED event. But let's try to cleanup\n                // everyhting related to the effect functionality.\n                this._setEffectInProgress = false;\n                this._switchStreamEffect();\n                logger.error('Failed to switch to the new stream!', error);\n                throw error;\n            });\n    }\n\n    /**\n     * Sets the source name to be used for signaling the jitsi track.\n     *\n     * @param {string} name The source name.\n     * @internal\n     */\n    override setSourceName(name: string): void {\n        this._sourceName = name;\n    }\n\n    /**\n     * Sets the primary SSRC for the track.\n     *\n     * @param {number} ssrc The SSRC.\n     */\n    setSsrc(ssrc: number): void {\n        if (isValidNumber(ssrc)) {\n            this._ssrc = ssrc;\n        }\n    }\n\n    /**\n     * Stops the associated MediaStream.\n     *\n     * @returns {void}\n     */\n    stopStream(): void {\n        /**\n         * Indicates that we are executing {@link #stopStream} i.e.\n         * {@link RTCUtils#stopMediaStream} for the <tt>MediaStream</tt>\n         * associated with this <tt>JitsiTrack</tt> instance.\n         *\n         * @private\n         * @type {boolean}\n         */\n        this._stopStreamInProgress = true;\n\n        try {\n            RTCUtils.stopMediaStream(this.stream);\n        } finally {\n            this._stopStreamInProgress = false;\n        }\n    }\n\n    /**\n     * Creates a text representation of this local track instance.\n     *\n     * @return {string}\n     */\n    override toString(): string {\n        return `LocalTrack[${this.rtcId},${this.getType()}]`;\n    }\n\n    /**\n     * Asynchronously unmutes this track.\n     *\n     * @returns {Promise}\n     */\n    unmute(): Promise<void> {\n        return this._queueSetMuted(false);\n    }\n\n    /**\n     * Applies media constraints to the current MediaStreamTrack.\n     *\n     * @param {IAudioConstraints} constraints - Media constraints to apply.\n     * @returns {Promise<void>}\n     */\n    async applyConstraints(constraints: IAudioConstraints): Promise<void> {\n        const mediaType = this.getType();\n\n        if (!this.isAudioTrack()) {\n            throw new Error(`Media ${mediaType} is not supported, track must be audio`);\n        }\n\n        const hasAudioMixEffect = typeof this._streamEffect?.setMuted === 'function';\n\n        if (this._streamEffect && !hasAudioMixEffect) {\n            throw new Error(`Cannot apply constraints while the effect ${JSON.stringify(\n                this._streamEffect)} is active`\n            );\n        }\n\n        const hasConference = Boolean(this.conference);\n        let audioAnalyser: VADAudioAnalyser | undefined;\n\n        if (hasConference) {\n            audioAnalyser = this.conference.getAudioAnalyser();\n\n            if (audioAnalyser) {\n                logger.debug(`Removing track ${this} from audio analyser`);\n                audioAnalyser._trackRemoved(this);\n            }\n\n            logger.debug(`Removing track ${this} from conference`);\n            await this.conference._removeLocalTrackFromPc(this);\n        }\n\n        const isMuted = this.isMuted();\n\n        if (hasAudioMixEffect) {\n            this._stopStreamEffect();\n        }\n\n        this.stopStream();\n\n        const initialSettings = this.track.getSettings();\n\n        const deviceId = initialSettings?.deviceId;\n        const deviceIdKey = mediaType === MediaType.AUDIO ? 'micDeviceId' : 'cameraDeviceId';\n        let mediaStreamData: IStreamInfo | undefined;\n\n        try {\n            logger.debug(`applyConstraints for track ${this} with constraints: ${JSON.stringify(constraints)}`);\n\n            const constraintsToApply = {\n                ...initialSettings,\n                ...constraints\n            };\n\n            [ mediaStreamData ] = await RTCUtils.obtainAudioAndVideoPermissions({\n                constraints: { [mediaType]: constraintsToApply },\n                ...(deviceId && { [deviceIdKey]: deviceId }),\n                devices: [ mediaType ]\n            });\n\n            if (!mediaStreamData?.stream) {\n                throw new JitsiTrackError(JitsiTrackErrors.CONSTRAINT_FAILED);\n            }\n\n        } catch (error) {\n            logger.error(\n                `applyConstraints failed for track ${this} with constraints: ${JSON.stringify(\n                    constraints\n                )}: `,\n                error\n            );\n\n            [ mediaStreamData ] = await RTCUtils.obtainAudioAndVideoPermissions({\n                constraints: { [mediaType]: initialSettings },\n                ...(deviceId && { [deviceIdKey]: deviceId }),\n                devices: [ mediaType ]\n            });\n        }\n\n        if (!mediaStreamData?.stream) {\n            throw new JitsiTrackError(JitsiTrackErrors.GENERAL);\n        }\n\n        logger.debug('Setting updated stream and track');\n\n        this._setStream(mediaStreamData.stream);\n        this.track = mediaStreamData.track;\n\n        if (hasAudioMixEffect) {\n            this._startStreamEffect(this._streamEffect);\n        }\n\n        if (isMuted) {\n            this._setMuted(true);\n        }\n\n        if (hasConference) {\n            logger.debug(`Adding track ${this} to conference`);\n            await this.conference._addLocalTrackToPc(this);\n\n            if (audioAnalyser) {\n                logger.debug(`Adding track ${this} to audio analyser`);\n                audioAnalyser._trackAdded(this);\n            }\n        }\n    }\n}\n","/**\n * Enumeration of the codec mime types\n * @type {{AV1: string, H264: string, OPUS: string, RED: string, ULPFEC: string, VP8: string, VP9: string}}\n */\nexport enum CodecMimeType {\n\n    /**\n     * AV1 codec mime type.\n     */\n    AV1 = 'av1',\n\n    /**\n     * The h264 codec mime type.\n     */\n    H264 = 'h264',\n\n    /**\n     * The opus codec mime type.\n     */\n    OPUS = 'opus',\n\n    /**\n     * The red codec mime type.\n     */\n    RED = 'red',\n\n    /**\n     * The ulpfec codec mime type.\n     */\n    ULPFEC = 'ulpfec',\n\n    /**\n     * The vp8 codec mime type.\n     */\n    VP8 = 'vp8',\n\n    /**\n     * The vp9 codec mime type.\n     */\n    VP9 = 'vp9'\n}\n","/**\n * Enumeration of the media direction types.\n */\nexport enum MediaDirection {\n\n    /**\n     * Media is send and receive is suspended.\n     */\n    INACTIVE = 'inactive',\n\n    /**\n     * Media is only received from remote peer.\n     */\n    RECVONLY = 'recvonly',\n\n    /**\n     * Media is only sent to the remote peer.\n     */\n    SENDONLY = 'sendonly',\n\n    /**\n     * Media is sent and received.\n     */\n    SENDRECV = 'sendrecv'\n}\n","export enum SignalingEvents {\n\n    /**\n     * Event triggered when participant's muted status changes.\n     *\n     * @param {string} endpointId the track owner's identifier (MUC nickname)\n     * @param {MediaType} mediaType \"audio\" or \"video\"\n     * @param {boolean} isMuted the new muted state\n     */\n    PEER_MUTED_CHANGED = 'signaling.peerMuted',\n\n    /**\n     * Event triggered when participant's video type changes.\n     *\n     * @param {string} endpointId the video owner's ID (MUC nickname)\n     * @param {VideoType} videoType the new value\n     */\n    PEER_VIDEO_TYPE_CHANGED = 'signaling.peerVideoType',\n\n    /**\n     * Event triggered when source's muted status changes.\n     *\n     * @param {string} sourceName - The name of the source.\n     * @param {boolean} isMuted - The new muted state.\n     */\n    SOURCE_MUTED_CHANGED = 'signaling.sourceMuted',\n\n    /**\n     * Event triggered when presence for a source is received.\n     *\n     * @param {string} sourceName - The name of the source.\n     * @param {string} endpointId - The endpoint id.\n     * @param {boolean} muted - The new muted state.\n     * @param {string} videoType - The video type of the source.\n     */\n    SOURCE_UPDATED = 'signaling.sourceUpdated',\n\n    /**\n     * Event triggered when source's video type changes.\n     *\n     * @param {string} source - The name of the source.\n     * @param {VideoType} videoType - The new value.\n     */\n    SOURCE_VIDEO_TYPE_CHANGED = 'signaling.sourceVideoType'\n}\n","import Listenable from '../../modules/util/Listenable';\nimport { isValidNumber } from '../../modules/util/MathUtil';\n\nimport { MediaType } from './MediaType';\nimport { VideoType } from './VideoType';\n\nexport type EndpointId = string;\nexport type SourceName = string;\n\nexport interface ISourceInfo {\n    muted?: boolean;\n    sourceName: SourceName;\n    videoType?: string;\n}\n\nexport interface IPeerMediaInfo {\n    codecList?: string[];\n    codecType?: string;\n    muted?: boolean;\n    videoType?: string;\n}\n/* eslint-disable @typescript-eslint/no-unused-vars */\n/* eslint-disable @typescript-eslint/no-empty-function */\n\n/**\n * Generates a source name.\n *\n * @param {EndpointId} endpointId - Jitsi Endpoint Id.\n * @param {MediaType} mediaType - the media type string.\n * @param {number} trackIdx - Track index (or sender idx? - to be figured out) starting from 0.\n * @returns {SourceName} eg. endpointA-v0\n */\nexport function getSourceNameForJitsiTrack(endpointId: EndpointId, mediaType: MediaType, trackIdx: number): SourceName {\n    const firstLetterOfMediaType = mediaType.substring(0, 1);\n\n    return `${endpointId}-${firstLetterOfMediaType}${trackIdx}`;\n}\n\n/**\n * Extracts MediaType from give source name (must be in the correct format as generated by\n * {@link getSourceNameForJitsiTrack}).\n *\n * @param {SourceName} sourceName - the source name.\n * @returns {MediaType}\n */\nexport function getMediaTypeFromSourceName(sourceName: SourceName): MediaType {\n    const firstLetterOfMediaTypeIdx = sourceName.lastIndexOf('-') + 1;\n\n    if (firstLetterOfMediaTypeIdx <= 0) {\n        throw new Error(`Invalid source name: ${sourceName}`);\n    }\n\n    const firstLetterOfMediaType = sourceName.substr(firstLetterOfMediaTypeIdx, 1);\n\n    if (firstLetterOfMediaType === 'v') {\n        return MediaType.VIDEO;\n    } else if (firstLetterOfMediaType === 'a') {\n        return MediaType.AUDIO;\n    }\n\n    throw new Error(`Invalid source name: ${sourceName}`);\n}\n\n/**\n * Extracts the owner endpoint id from a given source name (must be in the correct format as generated by\n * {@link getSourceNameForJitsiTrack}).\n *\n * @param {SourceName} sourceName - the source name, eg. endpointA-v0.\n * @returns {EndpointId}\n */\nexport function getEndpointIdFromSourceName(sourceName: SourceName): EndpointId {\n    // Strip the trailing media suffix (eg. '-v0', '-a0.en') to recover the owner endpoint id, which may itself\n    // contain '-'.\n    const match = sourceName.match(/^(.+)-[av]\\d+(\\.[^.]+)?$/);\n\n    if (!match) {\n        throw new Error(`Invalid source name: ${sourceName}`);\n    }\n\n    return match[1];\n}\n\n/**\n * Extracts source index (zero based) from a given source name (must be in the correct format as generated by\n * {@link getSourceNameForJitsiTrack}).\n *\n * @param {SourceName} sourceName - the source name, eg. endpointA-v0.\n * @returns {number}\n */\nexport function getSourceIndexFromSourceName(sourceName: SourceName): number {\n    const nameParts = sourceName.split('-');\n    const trackIdx = Number(nameParts[nameParts.length - 1].substring(1));\n\n    if (!isValidNumber(trackIdx)) {\n        throw new Error(`Failed to parse track idx for source name: ${sourceName}`);\n    }\n\n    return trackIdx;\n}\n\n/**\n * Checks whether the given source name belongs to a translated audio source. Translated sources follow the\n * convention {@code <regularSourceName>.<ISO-639-1-language>}, eg. endpointA-a0.en, whereas regular source\n * names never contain a dot.\n *\n * @param {SourceName} sourceName - The source name to check (callers may pass a null/undefined source name).\n * @returns {boolean}\n */\nexport function isTranslatedSourceName(sourceName?: SourceName | null): boolean {\n    return typeof sourceName === 'string' && sourceName.includes('.');\n}\n\n/**\n * An object that carries the info about specific media type advertised by\n * participant in the signaling channel.\n * @typedef {Object} IPeerMediaInfo\n * @property {boolean} muted indicates if the media is currently muted\n * @property {VideoType|undefined} videoType the type of the video if applicable\n */\n\n/**\n * Interface used to expose the information carried over the signaling channel\n * which is not available to the RTC module in the media SDP.\n *\n * @interface SignalingLayer\n */\nexport default class SignalingLayer extends Listenable {\n    /**\n     * Obtains the info about given media advertised in the MUC presence of\n     * the participant identified by the given MUC JID.\n     * @param {string} owner the MUC jid of the participant for whom\n     * {@link PeerMediaInfo} will be obtained.\n     * @param {MediaType} mediaType the type of the media for which presence\n     * @param {SourceName} sourceName - The name of the source for which the info is to be obtained.\n     * info will be obtained.\n     * @return {Nullable<IPeerMediaInfo>} presenceInfo an object with media presence\n     * info or <tt>null</tt> either if there is no presence available for given\n     * JID or if the media type given is invalid.\n     *\n     * @deprecated This method is to be replaced with getPeerSourceInfo.\n     */\n    getPeerMediaInfo(\n            owner: string, mediaType: MediaType, sourceName: SourceName\n    ): Nullable<IPeerMediaInfo> {\n        throw new Error('not implemented');\n    }\n\n    /**\n     * Obtains the info about a source for given name and endpoint ID.\n     * @param {EndpointId} owner - The owner's endpoint ID.\n     * @param {SourceName} sourceName - The name of the source for which the info is to be obtained.\n     * @returns {Optional<ITPCSourceInfo>}\n     */\n    getPeerSourceInfo(\n            owner: EndpointId, sourceName: SourceName\n    ): Optional<ISourceInfo> {\n        throw new Error('not implemented');\n    }\n\n    /**\n     * Obtains the endpoint ID for given SSRC.\n     * @param {number} ssrc the SSRC number.\n     * @return {Nullable<string>} the endpoint ID for given media SSRC.\n     */\n    getSSRCOwner(ssrc: number): Nullable<string> {\n        throw new Error('not implemented');\n    }\n\n    /**\n     * Obtains the source name for given SSRC.\n     * @param {number} ssrc the track's SSRC identifier.\n     * @returns {Optional<SourceName>} the track's source name.\n     */\n    getTrackSourceName(ssrc: number): Optional<SourceName> {\n        throw new Error('not implemented');\n    }\n\n    /**\n     * Removes the association between a given SSRC and its current owner so that it can re-used when the SSRC gets\n     * remapped to another source from a different endpoint.\n     * @param {number} ssrc a list of SSRCs.\n     */\n    removeSSRCOwners(ssrcList: number[]): void {\n    }\n\n    /**\n     * Set an SSRC owner.\n     *\n     * @param {number} ssrc - An SSRC to be owned.\n     * @param {string} endpointId - Owner's ID (MUC nickname).\n     * @param {SourceName} sourceName - The related source name.\n     * @throws TypeError if <tt>ssrc</tt> is not a number.\n     */\n    setSSRCOwner(ssrc: number, endpointId: string, sourceName: SourceName): void {\n    }\n\n    /**\n     * Adjusts muted status of given track.\n     *\n     * @param {SourceName} sourceName - the name of the track's source.\n     * @param {boolean} muted - the new muted status.\n     * @returns {boolean}\n     */\n    setTrackMuteStatus(sourceName: SourceName, muted: boolean) {\n    }\n\n    /**\n     * Sets track's video type.\n     * @param {SourceName} sourceName - the track's source name.\n     * @param {VideoType} videoType - the new video type.\n     * @returns {boolean}\n     */\n    setTrackVideoType(sourceName: SourceName, videoType: VideoType) {\n    }\n\n    /**\n     * Removes the SSRCs associated with a given endpoint from the SSRC owners.\n     *\n     * @param {string} id endpoint id of the participant leaving the call.\n     * @returns {void}\n     */\n    updateSsrcOwnersOnLeave(id: string): void {\n    }\n}\n","import browser from '../../modules/browser';\n\nimport { CodecMimeType } from './CodecMimeType';\n\n// Default value for assumed downlink bandwidth for the local endpoint which tells the bridge to use its own calculated\n// BWE value while determining the number of video streams to route to the endpoint.\nexport const ASSUMED_BANDWIDTH_BPS = -1;\n\n// Default lastN value to be used while ramping up lastN after a cpu limitation ceases to exist (if -1 or no value is\n// passed in config.js for channelLastN).\nexport const DEFAULT_LAST_N = 25;\n\n// LastN value to be signaled to the bridge when the local endpoint wants to receive all the remote video sources in\n// the call.\nexport const LAST_N_UNLIMITED = -1;\n\n// Default simulcast encodings config.\nexport const SIM_LAYERS = [\n    {\n        rid: '1',\n        scaleFactor: 4.0\n    },\n    {\n        rid: '2',\n        scaleFactor: 2.0\n    },\n    {\n        rid: '3',\n        scaleFactor: 1.0\n    }\n];\n\n/**\n * The ssrc-group semantics for SSRCs related to the video streams.\n */\nexport enum SSRC_GROUP_SEMANTICS {\n\n    // The semantics for group of SSRCs belonging to the same stream, primary and RTX.\n    FID = 'FID',\n\n    // The semantics for group with primary SSRCs for each of the simulcast streams.\n    SIM = 'SIM'\n}\n\n/**\n * Standard scalability mode settings for different video codecs and the default bitrates.\n */\nexport const STANDARD_CODEC_SETTINGS = {\n    av1: {\n        maxBitratesVideo: {\n            fullHd: 2000000,\n            high: 1000000,\n            low: 100000,\n            none: 0,\n            ssHigh: 2500000,\n            standard: 300000,\n            ultraHd: 4000000\n        },\n        scalabilityModeEnabled: browser.supportsScalabilityModeAPI(),\n        useKSVC: browser.supportsSVC(),\n        useSimulcast: !browser.supportsSVC(),\n    },\n    h264: {\n        maxBitratesVideo: {\n            fullHd: 4000000,\n            high: 2000000,\n            low: 400000,\n            none: 0,\n            ssHigh: 2500000,\n            standard: 800000,\n            ultraHd: 8000000,\n        },\n        scalabilityModeEnabled: browser.supportsScalabilityModeAPI()\n    },\n    vp8: {\n        maxBitratesVideo: {\n            fullHd: 3000000,\n            high: 1500000,\n            low: 200000,\n            none: 0,\n            ssHigh: 2500000,\n            standard: 500000,\n            ultraHd: 6000000,\n        },\n        scalabilityModeEnabled: false\n    },\n    vp9: {\n        maxBitratesVideo: {\n            fullHd: 2500000,\n            high: 1200000,\n            low: 100000,\n            none: 0,\n            ssHigh: 2500000,\n            standard: 300000,\n            ultraHd: 5000000\n        },\n        scalabilityModeEnabled: browser.supportsScalabilityModeAPI(),\n        useKSVC: browser.supportsSVC(),\n        useSimulcast: !browser.supportsSVC(),\n    }\n};\n\n/**\n * Video codecs in descending order of complexity for camera and desktop video types based on the results of manual\n * performance tests on different platforms. When a CPU limitation is encountered, client switches the call to use the\n * next codec in the list.\n */\nexport const VIDEO_CODECS_BY_COMPLEXITY = {\n    'camera': [\n        CodecMimeType.AV1,\n        CodecMimeType.VP9,\n        CodecMimeType.VP8\n    ],\n    'desktop': [\n        CodecMimeType.VP9,\n        CodecMimeType.VP8,\n        CodecMimeType.AV1\n    ]\n};\n\n/**\n * Standard video resolutions and the corresponding quality level that will be picked for the given resolution.\n * For quality levels:\n * 'high' and above - the encoder will be configured to encode 3 spatial layers.\n * 'standard' - the encoder will be configured to encode 2 spatial laters.\n * 'low' - the encoder will be configured to encode only 1 spatial layer.\n * In all the above cases, each of the layers will again have 3 temporal layers, except for VP8 codec for which only\n * 2 temporal layers are configured by default.\n */\nexport const VIDEO_QUALITY_LEVELS = [\n    {\n        height: 2160,\n        level: 'ultraHd'\n    },\n    {\n        height: 1080,\n        level: 'fullHd'\n    },\n    {\n        height: 720,\n        level: 'high'\n    },\n    {\n        height: 540,\n        level: 'standard'\n    },\n    {\n        height: 480,\n        level: 'standard'\n    },\n    {\n        height: 360,\n        level: 'standard'\n    },\n    {\n        height: 270,\n        level: 'low'\n    },\n    {\n        height: 180,\n        level: 'low'\n    },\n    {\n        height: 90,\n        level: 'low'\n    },\n    {\n        height: 0,\n        level: 'none'\n    }\n];\n\n/**\n * Enumerate the supported video resolutions.\n */\nexport enum VIDEO_QUALITY_SETTINGS {\n\n    // 1920x1080 or full High Definition.\n    FULL = 'fullHd',\n\n    // 1280x720 or High Definition.\n    HIGH = 'high',\n\n    // 320x180 or Low Definition.\n    LOW = 'low',\n\n    // When the camera is turned off.\n    NONE = 'none',\n\n    // 640x360 or Standard Definition.\n    STANDARD = 'standard',\n\n    // 3840x2160 or 4k.\n    ULTRA = 'ultraHd'\n}\n","import transform, { type MediaDescription } from 'sdp-transform';\n\nimport { MediaDirection } from '../../service/RTC/MediaDirection';\nimport { SSRC_GROUP_SEMANTICS } from '../../service/RTC/StandardVideoQualitySettings';\n\n/**\n * Parses the primary SSRC of given SSRC group.\n * @param {object} group the SSRC group object as defined by the 'sdp-transform'\n * @return {Number} the primary SSRC number\n */\nexport function parsePrimarySSRC(group: { ssrcs: string; }): number {\n    return parseInt(group.ssrcs.split(' ')[0], 10);\n}\n\n/**\n * Parses the secondary SSRC of given SSRC group.\n * @param {object} group the SSRC group object as defined by the 'sdp-transform'\n * @return {Number} the secondary SSRC number\n */\nexport function parseSecondarySSRC(group: { ssrcs: string; }): number {\n    return parseInt(group.ssrcs.split(' ')[1], 10);\n}\n\n/**\n * Tells how many distinct SSRCs are contained in given media line.\n * @param {Object} MediaDescription the media line object as defined by 'sdp-transform' lib\n * @return {number}\n */\nfunction _getSSRCCount(mLine: MediaDescription): number {\n    if (!mLine.ssrcs) {\n        return 0;\n    }\n\n    return mLine.ssrcs\n        .map(ssrcInfo => ssrcInfo.id)\n        .filter((ssrc, index, array) => array.indexOf(ssrc) === index)\n        .length;\n}\n\n/**\n * A wrapper around 'sdp-transform' media description object which provides\n * utility methods for common SDP/SSRC related operations.\n */\nexport class MLineWrap {\n    /*\n    * The underlying media line object as defined by 'sdp-transform'\n    * @internal\n    */\n    _mLine: MediaDescription;\n\n    /**\n     * Creates new <tt>MLineWrap</t>>\n     * @param {Object} _mLine the media line object as defined by 'sdp-transform'\n     * lib.\n     */\n    constructor(mLine: MediaDescription) {\n        if (!mLine) {\n            throw new Error('mLine is undefined');\n        }\n\n        this._mLine = mLine;\n    }\n\n    /**\n     * Getter for the mLine's \"ssrcs\" array. If the array was undefined an empty\n     * one will be preassigned.\n     *\n     * @return {Array<Object>} an array of 'sdp-transform' SSRC attributes\n     * objects.\n     */\n    get ssrcs(): MediaDescription['ssrcs'] {\n        if (!this._mLine.ssrcs) {\n            this._mLine.ssrcs = [];\n        }\n\n        return this._mLine.ssrcs;\n    }\n\n    /**\n     * Setter for the mLine's \"ssrcs\" array.\n     *\n     * @param {Array<Object>} ssrcs an array of 'sdp-transform' SSRC attributes\n     * objects.\n     */\n    set ssrcs(ssrcs: MediaDescription['ssrcs']) {\n        this._mLine.ssrcs = ssrcs;\n    }\n\n    /**\n     * Returns the direction of the underlying media description.\n     * @return {Optional<string>} the media direction name as defined in the SDP.\n     */\n    get direction(): Optional<string> {\n        return this._mLine.direction;\n    }\n\n    /**\n     * Modifies the direction of the underlying media description.\n     * @param {Optional<string>} direction the new direction to be set\n     */\n    set direction(direction: Optional<MediaDirection>) {\n        this._mLine.direction = direction;\n    }\n\n    /**\n     * Exposes the SSRC group array of the underlying media description object.\n     * @return {MediaDescription['ssrcGroups']}\n     */\n    get ssrcGroups(): MediaDescription['ssrcGroups'] {\n        if (!this._mLine.ssrcGroups) {\n            this._mLine.ssrcGroups = [];\n        }\n\n        return this._mLine.ssrcGroups;\n    }\n\n    /**\n     * Modifies the SSRC groups array of the underlying media description\n     * object.\n     * @param {MediaDescription['ssrcGroups']} ssrcGroups\n     */\n    set ssrcGroups(ssrcGroups: MediaDescription['ssrcGroups']) {\n        this._mLine.ssrcGroups = ssrcGroups;\n    }\n\n    /**\n     * Obtains value from SSRC attribute.\n     * @param {number} ssrcNumber the SSRC number for which attribute is to be\n     * found\n     * @param {string} attrName the name of the SSRC attribute to be found.\n     * @return {Optional<string>} the value of SSRC attribute or\n     * <tt>undefined</tt> if no such attribute exists.\n     */\n    getSSRCAttrValue(ssrcNumber: number, attrName: string): Optional<string> {\n        const attribute = this.ssrcs.find(\n            ssrcObj => ssrcObj.id === ssrcNumber\n            && ssrcObj.attribute === attrName);\n\n        return attribute?.value;\n    }\n\n    /**\n     * Removes all attributes for given SSRC number.\n     * @param {number} ssrcNum the SSRC number for which all attributes will be\n     * removed.\n     */\n    removeSSRC(ssrcNum: number): void {\n        if (!this._mLine.ssrcs?.length) {\n            return;\n        }\n\n        this._mLine.ssrcs\n            = this._mLine.ssrcs.filter(ssrcObj => ssrcObj.id !== ssrcNum);\n    }\n\n    /**\n     * Adds SSRC attribute\n     * @param {object} ssrcObj the SSRC attribute object as defined in\n     * the 'sdp-transform' lib.\n     */\n    addSSRCAttribute(ssrcObj: MediaDescription['ssrcs'][number]): void {\n        this.ssrcs.push(ssrcObj);\n    }\n\n    /**\n     * Finds a SSRC group matching both semantics and SSRCs in order.\n     * @param {string} semantics the name of the semantics\n     * @param {string} [ssrcs] group SSRCs as a string (like it's defined in\n     * SSRC group object of the 'sdp-transform' lib) e.g. \"1232546 342344 25434\"\n     * @return {Optional<MediaDescription['ssrcGroups'][number]>} the SSRC group object or <tt>undefined</tt> if not found.\n     */\n    findGroup(semantics: string, ssrcs?: string): Optional<MediaDescription['ssrcGroups'][number]> {\n        return this.ssrcGroups.find(\n            group =>\n                group.semantics === semantics\n                    && (!ssrcs || ssrcs === group.ssrcs));\n    }\n\n    /**\n     * Finds all groups matching given semantic's name.\n     * @param {string} semantics the name of the semantics\n     * @return {MediaDescription['ssrcGroups']} an array of SSRC group objects as defined by the 'sdp-transform' lib.\n     */\n    findGroups(semantics: string): MediaDescription['ssrcGroups'] {\n        return this.ssrcGroups.filter(\n            group => group.semantics === semantics);\n    }\n\n    /**\n     * Finds all groups matching given semantic's name and group's primary SSRC.\n     * @param {string} semantics the name of the semantics\n     * @param {number} primarySSRC the primary SSRC number to be matched\n     * @return {Optional<MediaDescription['ssrcGroups'][number]>} SSRC group object as defined by the 'sdp-transform' lib.\n     */\n    findGroupByPrimarySSRC(semantics: string, primarySSRC: number): Optional<MediaDescription['ssrcGroups'][number]> {\n        return this.ssrcGroups.find(\n            group => group.semantics === semantics\n                && parsePrimarySSRC(group) === primarySSRC);\n    }\n\n    /**\n     * Gets the SSRC count for the underlying media description.\n     * @return {number}\n     */\n    getSSRCCount(): number {\n        return _getSSRCCount(this._mLine);\n    }\n\n    /**\n     * Checks whether the underlying media description contains any SSRC groups.\n     * @return {boolean} <tt>true</tt> if there are any SSRC groups or\n     * <tt>false</tt> otherwise.\n     */\n    containsAnySSRCGroups(): boolean {\n        return this._mLine.ssrcGroups !== undefined;\n    }\n\n    /**\n     * Finds the primary video SSRC.\n     * @returns {Optional<number>} the primary video ssrc\n     * @throws Error if the underlying media description is not a video\n     */\n    getPrimaryVideoSsrc(): Optional<number> {\n        const mediaType = this._mLine.type;\n\n        if (mediaType !== 'video') {\n            throw new Error(\n                `getPrimarySsrc doesn't work with '${mediaType}'`);\n        }\n\n        const numSsrcs = _getSSRCCount(this._mLine);\n\n        if (numSsrcs === 1) {\n            // Not using \"ssrcs\" getter on purpose here\n            return this._mLine.ssrcs![0].id;\n        }\n\n        // Look for a SIM, FID, or FEC-FR group\n        if (this._mLine.ssrcGroups) {\n            const simGroup = this.findGroup(SSRC_GROUP_SEMANTICS.SIM);\n\n            if (simGroup) {\n                return parsePrimarySSRC(simGroup);\n            }\n            const fidGroup = this.findGroup(SSRC_GROUP_SEMANTICS.FID);\n\n            if (fidGroup) {\n                return parsePrimarySSRC(fidGroup);\n            }\n            const fecGroup = this.findGroup('FEC-FR');\n\n            if (fecGroup) {\n                return parsePrimarySSRC(fecGroup);\n            }\n        }\n    }\n\n    /**\n     * Obtains RTX SSRC from the underlying video description (the\n     * secondary SSRC of the first \"FID\" group found)\n     * @param {number} primarySsrc the video ssrc for which to find the\n     * corresponding rtx ssrc\n     * @returns {Optional<number>} the rtx ssrc (or undefined if there isn't\n     * one)\n     */\n    getRtxSSRC(primarySsrc: number): Optional<number> {\n        const fidGroup = this.findGroupByPrimarySSRC(SSRC_GROUP_SEMANTICS.FID, primarySsrc);\n\n        return fidGroup && parseSecondarySSRC(fidGroup);\n    }\n\n    /**\n     * Obtains all SSRCs contained in the underlying media description.\n     * @return {Array.<number>} an array with all SSRC as numbers.\n     */\n    getSSRCs(): number[] {\n        return this.ssrcs\n            .map(ssrcInfo => ssrcInfo.id)\n            .filter((ssrc, index, array) => array.indexOf(ssrc) === index);\n    }\n\n    /**\n     * Obtains primary video SSRCs.\n     * @return {Array.<number>} an array of all primary video SSRCs as numbers.\n     * @throws Error if the wrapped media description is not a video.\n     */\n    getPrimaryVideoSSRCs(): number[] {\n        const mediaType = this._mLine.type;\n\n        if (mediaType !== 'video') {\n            throw new Error(\n                `getPrimaryVideoSSRCs doesn't work with ${mediaType}`);\n        }\n\n        const videoSSRCs = this.getSSRCs();\n\n        for (const ssrcGroupInfo of this.ssrcGroups) {\n            // Right now, FID and FEC-FR groups are the only ones we parse to\n            // disqualify streams.  If/when others arise we'll\n            // need to add support for them here\n            if (ssrcGroupInfo.semantics === SSRC_GROUP_SEMANTICS.FID\n                    || ssrcGroupInfo.semantics === 'FEC-FR') {\n                // secondary streams should be filtered out\n                const secondarySsrc = parseSecondarySSRC(ssrcGroupInfo);\n\n                videoSSRCs.splice(\n                    videoSSRCs.indexOf(secondarySsrc), 1);\n            }\n        }\n\n        return videoSSRCs;\n    }\n\n    /**\n     * Removes all SSRC groups which contain given SSRC number at any position.\n     * @param {number} ssrc the SSRC for which all matching groups are to be\n     * removed.\n     */\n    removeGroupsWithSSRC(ssrc: number): void {\n        if (!this._mLine.ssrcGroups) {\n            return;\n        }\n\n        this._mLine.ssrcGroups = this._mLine.ssrcGroups\n            .filter(groupInfo => groupInfo.ssrcs.indexOf(`${ssrc}`) === -1);\n    }\n\n    /**\n     * Removes groups that match given semantics.\n     * @param {string} semantics e.g. \"SIM\" or \"FID\"\n     */\n    removeGroupsBySemantics(semantics: string): void {\n        if (!this._mLine.ssrcGroups) {\n            return;\n        }\n\n        this._mLine.ssrcGroups\n            = this._mLine.ssrcGroups\n                .filter(groupInfo => groupInfo.semantics !== semantics);\n    }\n\n    /**\n     * Adds given SSRC group to this media description.\n     * @param {object} group the SSRC group object as defined by\n     * the 'sdp-transform' lib.\n     */\n    addSSRCGroup(group: MediaDescription['ssrcGroups'][number]): void {\n        this.ssrcGroups.push(group);\n    }\n}\n\n/**\n * Utility class for SDP manipulation using the 'sdp-transform' library.\n *\n * Typical use usage scenario:\n *\n * const transformer = new SdpTransformWrap(rawSdp);\n * const videoMLine = transformer.selectMedia('video);\n * if (videoMLine) {\n *     videoMLiner.addSSRCAttribute({\n *         id: 2342343,\n *         attribute: \"cname\",\n *         value: \"someCname\"\n *     });\n *     rawSdp = transformer.toRawSdp();\n * }\n */\nexport class SdpTransformWrap {\n    private parsedSDP: transform.SessionDescription;\n\n    /**\n     * Creates new instance and parses the raw SDP into objects using\n     * 'sdp-transform' lib.\n     * @param {string} rawSDP the SDP in raw text format.\n     */\n    constructor(rawSDP: string) {\n        this.parsedSDP = transform.parse(rawSDP);\n    }\n\n    /**\n     * Selects all the m-lines from the SDP for a given media type.\n     *\n     * @param {string} mediaType the name of the media e.g. 'audio', 'video', 'data'.\n     * @return {MLineWrap|null} return {@link MLineWrap} instance for the media line or <tt>null</tt> if not found. The\n     * object returned references the underlying SDP state held by this <tt>SdpTransformWrap</tt> instance (it's not a\n     * copy).\n     */\n    selectMedia(mediaType: string): Nullable<MLineWrap[]> {\n        const selectedMLines = this.parsedSDP.media\n            .filter(mLine => mLine.type === mediaType)\n            .map(mLine => new MLineWrap(mLine as MediaDescription));\n\n        return selectedMLines ?? null;\n    }\n\n    /**\n     * Converts the currently stored SDP state in this instance to raw text SDP\n     * format.\n     * @return {string}\n     */\n    toRawSDP(): string {\n        return transform.write(this.parsedSDP);\n    }\n}\n","import { isEqual } from 'lodash-es';\n\nimport { MediaDirection } from '../../service/RTC/MediaDirection';\nimport { MediaType } from '../../service/RTC/MediaType';\nimport TraceablePeerConnection from '../RTC/TraceablePeerConnection';\nimport browser from '../browser';\n\nimport { MLineWrap, SdpTransformWrap } from './SdpTransformUtil';\nimport { ISsrcInfo } from './constants';\n\n/**\n * Fakes local SDP exposed to {@link JingleSessionPC} through the local description getter. Modifies the SDP, so that\n * the stream identifiers are unique across all of the local PeerConnections and that the source names and video types\n * are injected so that Jicofo can use them to identify the sources.\n */\nexport default class LocalSdpMunger {\n    private _localEndpointId: string;\n    private _tpc: TraceablePeerConnection;\n\n    /**\n     * Creates new <tt>LocalSdpMunger</tt> instance.\n     *\n     * @param {TraceablePeerConnection} tpc\n     * @param {string} localEndpointId - The endpoint id of the local user.\n     */\n    constructor(tpc: TraceablePeerConnection, localEndpointId: string) {\n        this._tpc = tpc;\n        this._localEndpointId = localEndpointId;\n    }\n\n    /**\n     * Updates or adds a 'msid' attribute for the local sources in the SDP. Also adds 'sourceName' and 'videoType'\n     * (if applicable) attributes. All other source attributes like 'cname', 'label' and 'mslabel' are removed since\n     * these are not processed by Jicofo.\n     *\n     * @param {MLineWrap} mediaSection - The media part (audio or video) of the session description which will be\n     * modified in place.\n     * @returns {void}\n     * @private\n     */\n    private _transformMediaIdentifiers(mediaSection: MLineWrap, ssrcMap: Map<string, ISsrcInfo>): void {\n        const mediaType = mediaSection._mLine.type;\n        const mediaDirection = mediaSection._mLine.direction;\n        const sources = [ ...new Set(mediaSection._mLine.ssrcs?.map(s => s.id)) ];\n        let trackId = mediaSection._mLine.msid?.split(' ')[1];\n        let sourceName: string | undefined;\n\n        if (ssrcMap.size) {\n            const sortedSources = sources.slice().sort();\n\n            for (const [ id, trackSsrcs ] of ssrcMap.entries()) {\n                if (isEqual(sortedSources, [ ...trackSsrcs.ssrcs ].sort())) {\n                    sourceName = id;\n                }\n            }\n            for (const source of sources) {\n                if ((mediaDirection === MediaDirection.SENDONLY || mediaDirection === MediaDirection.SENDRECV)\n                    && sourceName) {\n                    const msid = mediaSection.ssrcs.find(ssrc => ssrc.id === source && ssrc.attribute === 'msid');\n\n                    if (msid) {\n                        trackId = msid.value.split(' ')[1];\n                    }\n                    const generatedMsid = `${ssrcMap.get(sourceName).msid}-${this._tpc.id} ${trackId}-${this._tpc.id}`;\n                    const existingMsid = mediaSection.ssrcs\n                        .find(ssrc => ssrc.id === source && ssrc.attribute === 'msid');\n\n                    // Always overwrite msid since we want the msid to be in this format even if the browser generates\n                    // one. '<endpoint_id>-<mediaType>-<trackIndex>-<tpcId>' example - d8ff91-video-0-1\n                    if (existingMsid) {\n                        existingMsid.value = generatedMsid;\n                    } else {\n                        mediaSection.ssrcs.push({\n                            attribute: 'msid',\n                            id: source,\n                            value: generatedMsid\n                        });\n                    }\n\n                    // Inject source names as a=ssrc:3124985624 name:endpointA-v0\n                    mediaSection.ssrcs.push({\n                        attribute: 'name',\n                        id: source,\n                        value: sourceName\n                    });\n\n                    const videoType = this._tpc.getLocalVideoTracks()\n                        .find(track => track.getSourceName() === sourceName)\n                        ?.getVideoType();\n\n                    if (mediaType === MediaType.VIDEO && videoType) {\n                        // Inject videoType as a=ssrc:1234 videoType:desktop.\n                        mediaSection.ssrcs.push({\n                            attribute: 'videoType',\n                            id: source,\n                            value: videoType\n                        });\n                    }\n                }\n            }\n        }\n\n        // Ignore the 'label' and 'mslabel' attributes.\n        mediaSection.ssrcs\n            = mediaSection.ssrcs.filter(ssrc => ssrc.attribute !== 'label' && ssrc.attribute !== 'mslabel');\n\n        // Remove the 'cname' attribute on Firefox as a=ssrc line with only 'cname' attribute are present in the SDP\n        // for recvonly SSRCs generated by createAnswer. These do not have to be signaled to the peers.\n        if (browser.isFirefox()) {\n            mediaSection.ssrcs = mediaSection.ssrcs.filter(ssrc => ssrc.attribute !== 'cname');\n        }\n\n        // FF generates phantom SSRCs for recvonly/inactive m-lines that should not be signaled. Only strip\n        // them on m-lines that have never carried a local sender track — preserving SSRCs on previously\n        // active sender slots avoids a source-remove on mute and the SSRC-reuse rendering issue\n        // (https://bugzilla.mozilla.org/show_bug.cgi?id=1768729).\n        const mid = mediaSection._mLine.mid?.toString();\n        const midHasSentTrack = mid && this._tpc._midsWithSentTrack.has(mid);\n\n        if (browser.isFirefox()\n            && (mediaDirection === MediaDirection.RECVONLY || mediaDirection === MediaDirection.INACTIVE)\n            && !midHasSentTrack) {\n            mediaSection.ssrcs = undefined;\n            mediaSection.ssrcGroups = undefined;\n        }\n    }\n\n    /**\n     * This transformation will make sure that stream identifiers are unique across all of the local PeerConnections\n     * even if the same stream is used by multiple instances at the same time. It also injects 'sourceName' and\n     * 'videoType' attribute.\n     *\n     * @param {RTCSessionDescription} sessionDesc - The local session description (this instance remains unchanged).\n     * @param {Map<string, TPCSSRCInfo>} ssrcMap - The SSRC and source map for the local tracks.\n     * @return {RTCSessionDescription} - Transformed local session description\n     * (a modified copy of the one given as the input).\n     */\n    transformStreamIdentifiers(sessionDesc: RTCSessionDescription, ssrcMap: Map<string, ISsrcInfo>): RTCSessionDescription {\n        if (!sessionDesc?.sdp || !sessionDesc.type) {\n            return sessionDesc;\n        }\n\n        const transformer = new SdpTransformWrap(sessionDesc.sdp);\n        const audioMLine = transformer.selectMedia(MediaType.AUDIO)?.[0];\n\n        if (audioMLine) {\n            this._transformMediaIdentifiers(audioMLine, ssrcMap);\n        }\n\n        const videoMlines = transformer.selectMedia(MediaType.VIDEO);\n\n        if (videoMlines && Array.isArray(videoMlines)) {\n            for (const videoMLine of videoMlines) {\n                this._transformMediaIdentifiers(videoMLine, ssrcMap);\n            }\n        }\n\n        return {\n            sdp: transformer.toRawSDP(),\n            type: sessionDesc.type\n        } as RTCSessionDescription;\n    }\n}\n","import { getLogger } from '@jitsi/logger';\nimport type { MediaDescription } from 'sdp-transform';\n\nimport { CodecMimeType } from '../../service/RTC/CodecMimeType';\nimport { MediaDirection } from '../../service/RTC/MediaDirection';\nimport { SSRC_GROUP_SEMANTICS } from '../../service/RTC/StandardVideoQualitySettings';\nimport browser from '../browser';\nimport RandomUtil from '../util/RandomUtil';\n\nimport { ICryptoData, IExtmapData, IFingerprintData, IFmtpParameter, IICECandidate, IICEParams, IMediaLine, IRTCPFBData, IRTPMapData, ISsrcGroup } from './constants';\n\nconst logger = getLogger('sdp:SDPUtils');\n\nconst SDPUtil = {\n    /**\n     * Builds an ICE candidate line for SDP.\n     *\n     * @param {IICECandidate} cand - The ICE candidate object.\n     * @returns {string} - The SDP line for the ICE candidate.\n     */\n    buildICECandidate(cand: IICECandidate): string {\n        let line = [\n            `a=candidate:${cand.foundation}`,\n            cand.component,\n            cand.protocol,\n            cand.priority,\n            cand.ip,\n            cand.port,\n            'typ',\n            cand.type\n        ].join(' ');\n\n        line += ' ';\n        switch (cand.type) {\n        case 'srflx':\n        case 'prflx':\n        case 'relay':\n            if (cand.hasOwnAttribute('rel-addr')\n                    && cand.hasOwnAttribute('rel-port')) {\n                line += 'raddr';\n                line += ' ';\n                line += cand['rel-addr'];\n                line += ' ';\n                line += 'rport';\n                line += ' ';\n                line += cand['rel-port'];\n                line += ' ';\n            }\n            break;\n        }\n        if (cand.hasOwnAttribute('tcptype')) {\n            line += 'tcptype';\n            line += ' ';\n            line += cand.tcptype;\n            line += ' ';\n        }\n        line += 'generation';\n        line += ' ';\n        line += cand.hasOwnAttribute('generation') ? cand.generation : '0';\n\n        return line;\n    },\n\n    /**\n     * Builds an ICE password line for SDP.\n     *\n     * @param {string} pwd - The ICE password.\n     * @returns {string} - The SDP line for the ICE password.\n     */\n    buildICEPwd(pwd: string): string {\n        return `a=ice-pwd:${pwd}`;\n    },\n\n    /**\n     * Builds an ICE ufrag line for SDP.\n     *\n     * @param {string} frag - The ICE ufrag.\n     * @returns {string} - The SDP line for the ICE ufrag.\n     */\n    buildICEUfrag(frag: string): string {\n        return `a=ice-ufrag:${frag}`;\n    },\n\n    /**\n     * Builds an SDP media line.\n     *\n     * @param {IMediaLine} mline - The media line object.\n     * @returns {string} - The SDP media line.\n     */\n    buildMLine(mline: IMediaLine): string {\n        return (\n            `m=${mline.media} ${mline.port} ${mline.proto} ${\n                mline.fmt.join(' ')}`);\n    },\n\n    /**\n     * Builds an RTP map line for SDP.\n     *\n     * @param {Element} el - The RTP map element.\n     * @returns {String} - The SDP line for the RTP map.\n     */\n    buildRTPMap(el: Element): string {\n        let line\n            = `a=rtpmap:${el.getAttribute('id')} ${el.getAttribute('name')}/${\n                el.getAttribute('clockrate')}`;\n\n        if (el.getAttribute('channels')\n            && el.getAttribute('channels') !== '1') {\n            line += `/${el.getAttribute('channels')}`;\n        }\n\n        return line;\n    },\n\n    /**\n     * Builds an ICE candidate line for SDP.\n     *\n     * @param {Element} cand - The ICE candidate object.\n     * @returns {string} - The SDP line for the ICE candidate.\n     */\n    candidateFromJingle(cand: Element): string {\n        let line = 'a=candidate:';\n\n        line += cand.getAttribute('foundation');\n        line += ' ';\n        line += cand.getAttribute('component');\n        line += ' ';\n\n        let protocol = cand.getAttribute('protocol');\n\n        // use tcp candidates for FF\n\n        if (browser.isFirefox() && protocol.toLowerCase() === 'ssltcp') {\n            protocol = 'tcp';\n        }\n\n        line += protocol; // .toUpperCase(); // chrome M23 doesn't like this\n        line += ' ';\n        line += cand.getAttribute('priority');\n        line += ' ';\n        line += cand.getAttribute('ip');\n        line += ' ';\n        line += cand.getAttribute('port');\n        line += ' ';\n        line += 'typ';\n        line += ` ${cand.getAttribute('type')}`;\n        line += ' ';\n        switch (cand.getAttribute('type')) {\n        case 'srflx':\n        case 'prflx':\n        case 'relay':\n            if (cand.getAttribute('rel-addr')\n                    && cand.getAttribute('rel-port')) {\n                line += 'raddr';\n                line += ' ';\n                line += cand.getAttribute('rel-addr');\n                line += ' ';\n                line += 'rport';\n                line += ' ';\n                line += cand.getAttribute('rel-port');\n                line += ' ';\n            }\n            break;\n        }\n        if (protocol.toLowerCase() === 'tcp') {\n            line += 'tcptype';\n            line += ' ';\n            line += cand.getAttribute('tcptype');\n            line += ' ';\n        }\n        line += 'generation';\n        line += ' ';\n        line += cand.getAttribute('generation') || '0';\n\n        return `${line}\\r\\n`;\n    },\n\n    /**\n     * Builds an ICE candidate from SDP.\n     *\n     * @param {string} line - The SDP line for the ICE candidate.\n     * @returns {Nullable<IICECandidate>} - The Jingle XML representation of the ICE candidate.\n     */\n    candidateToJingle(line: string): Nullable<IICECandidate> {\n        // a=candidate:2979166662 1 udp 2113937151 192.168.2.100 57698 typ host\n        // generation 0\n        //      <candidate component=... foundation=... generation=... id=...\n        // ip=... network=... port=... priority=... protocol=... type=.../>\n        if (line.indexOf('candidate:') === 0) {\n            // eslint-disable-next-line no-param-reassign\n            line = `a=${line}`;\n        } else if (line.substring(0, 12) !== 'a=candidate:') {\n            logger.warn(\n                'parseCandidate called with a line that is not a candidate'\n                    + ' line');\n            logger.warn(line);\n\n            return null;\n        }\n        if (line.substring(line.length - 2) === '\\r\\n') { // chomp it\n            // eslint-disable-next-line no-param-reassign\n            line = line.substring(0, line.length - 2);\n        }\n        const candidate: Partial<IICECandidate> = {};\n        const elems = line.split(' ');\n\n        if (elems[6] !== 'typ') {\n            logger.warn('did not find typ in the right place');\n            logger.warn(line);\n\n            return null;\n        }\n        candidate.foundation = elems[0].substring(12);\n        candidate.component = elems[1];\n        candidate.protocol = elems[2].toLowerCase();\n        candidate.priority = elems[3];\n        candidate.ip = elems[4];\n        candidate.port = elems[5];\n\n        // elems[6] => \"typ\"\n        candidate.type = elems[7];\n\n        candidate.generation = '0'; // default, may be overwritten below\n        for (let i = 8; i < elems.length; i += 2) {\n            switch (elems[i]) {\n            case 'raddr':\n                candidate['rel-addr'] = elems[i + 1];\n                break;\n            case 'rport':\n                candidate['rel-port'] = elems[i + 1];\n                break;\n            case 'generation':\n                candidate.generation = elems[i + 1];\n                break;\n            case 'tcptype':\n                candidate.tcptype = elems[i + 1];\n                break;\n            default: // TODO\n                logger.debug(`not translating \"${elems[i]}\" = \"${elems[i + 1]}\"`);\n            }\n        }\n        candidate.network = '1';\n\n        // not applicable to SDP -- FIXME: should be unique, not just random\n        // eslint-disable-next-line newline-per-chained-call\n        candidate.id = Math.random().toString(36).substr(2, 10);\n\n        return candidate as IICECandidate;\n    },\n\n    filterSpecialChars(text: Nullable<Optional<string>>): Nullable<Optional<string>> {\n        // XXX Neither one of the falsy values (e.g. null, undefined, false,\n        // \"\", etc.) \"contain\" special chars.\n        // eslint-disable-next-line no-useless-escape\n        return text ? text.replace(/[\\\\\\/\\{,\\}\\+]/g, '') : text;\n    },\n\n    /**\n     * Finds a line in the SDP that starts with the given search pattern.\n     *\n     * @param {string} haystack - The SDP string to search.\n     * @param {string} needle - The line prefix to find.\n     * @param {string} sessionpart - The session part to search within.\n     * @returns {Optional<string>} - The found line or false if not found.\n     */\n    findLine(haystack: string, needle: string, sessionpart?: string): Optional<string> {\n        let lines = haystack.split('\\r\\n');\n\n        for (let i = 0; i < lines.length; i++) {\n            if (lines[i].substring(0, needle.length) === needle) {\n                return lines[i];\n            }\n        }\n        if (!sessionpart) {\n            return undefined;\n        }\n\n        // search session part\n        lines = sessionpart.split('\\r\\n');\n        for (let j = 0; j < lines.length; j++) {\n            if (lines[j].substring(0, needle.length) === needle) {\n                return lines[j];\n            }\n        }\n\n        return undefined;\n    },\n\n    /**\n     * Finds all lines in the SDP that start with the given search pattern.\n     *\n     * @param {string} haystack - The SDP string to search.\n     * @param {string} needle - The line prefix to find.\n     * @param {string} sessionpart - The session part to search within.\n     * @returns {string[]} - An array of found lines.\n     */\n    findLines(haystack: string, needle: string, sessionpart?: string): string[] {\n        let lines = haystack.split('\\r\\n');\n        const needles = [];\n\n        for (let i = 0; i < lines.length; i++) {\n            if (lines[i].substring(0, needle.length) === needle) {\n                needles.push(lines[i]);\n            }\n        }\n        if (needles.length || !sessionpart) {\n            return needles;\n        }\n\n        // search session part\n        lines = sessionpart.split('\\r\\n');\n        for (let j = 0; j < lines.length; j++) {\n            if (lines[j].substring(0, needle.length) === needle) {\n                needles.push(lines[j]);\n            }\n        }\n\n        return needles;\n    },\n\n    /**\n     * Generates a random SSRC value.\n     *\n     * @returns {number} - A random SSRC value.\n     */\n    generateSsrc(): number {\n        return RandomUtil.randomInt(1, 0xffffffff);\n    },\n\n    /**\n     * Gets the SSRC attribute value from the media line.\n     *\n     * @param {MediaDescription} mLine - The media line object.\n     * @param {number} ssrc - The SSRC value to search for.\n     * @param {string} attributeName - The attribute name to search for.\n     * @returns {string|null} - The attribute value or null if not found.\n     */\n    getSsrcAttribute(mLine: MediaDescription, ssrc: number, attributeName: string): Nullable<string> {\n        for (let i = 0; i < mLine.ssrcs.length; ++i) {\n            const ssrcLine = mLine.ssrcs[i];\n\n            if (ssrcLine.id === ssrc\n                && ssrcLine.attribute === attributeName) {\n                return ssrcLine.value;\n            }\n        }\n    },\n\n    /**\n     * Gets the ICE ufrag from the SDP.\n     *\n     * @param {string} sdp - The SDP string to search.\n     * @returns {Optional<string>} - The ICE ufrag value or undefined if not found.\n     */\n    getUfrag(sdp: string): Optional<string> {\n        const ufragLines\n            = sdp.split('\\n').filter(line => line.startsWith('a=ice-ufrag:'));\n\n        if (ufragLines.length > 0) {\n            return ufragLines[0].substr('a=ice-ufrag:'.length);\n        }\n    },\n\n    /**\n     * Gets the ICE parameters from the media description and session description.\n     *\n     * @param {string} mediadesc - The media description string.\n     * @param {string} sessiondesc - The session description string.\n     * @returns {Nullable<IICEParams>} - The ICE parameters object or null if not found.\n     */\n    iceparams(mediadesc: string, sessiondesc: string): Nullable<IICEParams> {\n        let data = null;\n        let pwd, ufrag;\n\n        if ((ufrag = SDPUtil.findLine(mediadesc, 'a=ice-ufrag:', sessiondesc))\n                && (pwd\n                    = SDPUtil.findLine(\n                        mediadesc,\n                        'a=ice-pwd:',\n                        sessiondesc))) {\n            data = {\n                pwd: SDPUtil.parseICEPwd(pwd),\n                ufrag: SDPUtil.parseICEUfrag(ufrag)\n            };\n        }\n\n        return data;\n    },\n\n    /**\n     * Parses a crypto line from the SDP.\n     *\n     * @param {string} line - The crypto line to parse.\n     * @returns {ICryptoData} - The parsed crypto parameters.\n     */\n    parseCrypto(line: string): ICryptoData {\n        const data: Partial<ICryptoData> = {};\n        const parts = line.substring(9).split(' ');\n\n        data.tag = parts.shift();\n        data['crypto-suite'] = parts.shift();\n        data['key-params'] = parts.shift();\n        if (parts.length) {\n            data['session-params'] = parts.join(' ');\n        }\n\n        return data as ICryptoData;\n    },\n\n    /**\n     * Parses an extmap line from the SDP.\n     *\n     * @param {string} line - The extmap line to parse.\n     * @returns {IExtmapData} - The parsed extmap parameters.\n     */\n    parseExtmap(line: string): IExtmapData {\n        const parts = line.substr(9).split(' ');\n        const data: Partial<IExtmapData> = {};\n\n        data.value = parts.shift();\n        if (data.value.indexOf('/') === -1) {\n            data.direction = 'both';\n        } else {\n            data.direction = data.value.substr(data.value.indexOf('/') + 1);\n            data.value = data.value.substr(0, data.value.indexOf('/'));\n        }\n        data.uri = parts.shift();\n        data.params = parts;\n\n        return data as IExtmapData;\n    },\n\n    /**\n     * Parses a fingerprint line from the SDP.\n     *\n     * @param {string} line - The fingerprint line to parse.\n     * @returns {IFingerprintData} - The parsed fingerprint parameters.\n     */\n    parseFingerprint(line: string): IFingerprintData { // RFC 4572\n        const data: Partial<IFingerprintData> = {};\n        const parts = line.substring(14).split(' ');\n\n        data.hash = parts.shift();\n        data.fingerprint = parts.shift();\n\n        // TODO assert that fingerprint satisfies 2UHEX *(\":\" 2UHEX) ?\n        return data as IFingerprintData;\n    },\n\n    /**\n     * Parses a fmtp line from the SDP.\n     *\n     * @param {string} line - The fmtp line to parse.\n     * @returns {IFmtpParameter[]} - The parsed fmtp parameters.\n     */\n    parseFmtp(line: string): IFmtpParameter[] {\n        const data = [];\n        let parts = line.split(' ');\n\n        parts.shift();\n        parts = parts.join(' ').split(';');\n        for (let i = 0; i < parts.length; i++) {\n            let key = parts[i].split('=')[0];\n\n            while (key.length && key[0] === ' ') {\n                key = key.substring(1);\n            }\n            const value = parts[i].split('=')[1];\n\n            if (key && value) {\n                data.push({ name: key,\n                    value });\n            } else if (key) {\n                // rfc 4733 (DTMF) style stuff\n                data.push({ name: '',\n                    value: key });\n            }\n        }\n\n        return data;\n    },\n\n    /**\n     * Parses the SSRCs from a group description.\n     *\n     * @param {MediaDescription['ssrcGroups'][number]} ssrcGroup - The SSRC group object.\n     * @returns {number[]} - The list of SSRCs in the group.\n     */\n    parseGroupSsrcs(ssrcGroup: MediaDescription['ssrcGroups'][number]): number[] {\n        return ssrcGroup\n            .ssrcs\n            .split(' ')\n            .map(ssrcStr => parseInt(ssrcStr, 10));\n    },\n\n    /**\n     * Parses an ICE candidate line from the SDP.\n     *\n     * @param {string} line - The ICE candidate line to parse.\n     * @returns {IICECandidate} - The parsed ICE candidate parameters.\n     */\n    parseICECandidate(line: string): IICECandidate {\n        const candidate: Partial<IICECandidate> = {};\n        const elems = line.split(' ');\n\n        candidate.foundation = elems[0].substring(12);\n        candidate.component = elems[1];\n        candidate.protocol = elems[2].toLowerCase();\n        candidate.priority = elems[3];\n        candidate.ip = elems[4];\n        candidate.port = elems[5];\n\n        // elems[6] => \"typ\"\n        candidate.type = elems[7];\n        candidate.generation = '0'; // default value, may be overwritten below\n        for (let i = 8; i < elems.length; i += 2) {\n            switch (elems[i]) {\n            case 'raddr':\n                candidate['rel-addr'] = elems[i + 1];\n                break;\n            case 'rport':\n                candidate['rel-port'] = elems[i + 1];\n                break;\n            case 'generation':\n                candidate.generation = elems[i + 1];\n                break;\n            case 'tcptype':\n                candidate.tcptype = elems[i + 1];\n                break;\n            default: // TODO\n                logger.debug(\n                    `parseICECandidate not translating \"${\n                        elems[i]}\" = \"${elems[i + 1]}\"`);\n            }\n        }\n        candidate.network = '1';\n\n        // not applicable to SDP -- FIXME: should be unique, not just random\n        // eslint-disable-next-line newline-per-chained-call\n        candidate.id = Math.random().toString(36).substr(2, 10);\n\n        return candidate as IICECandidate;\n    },\n\n    /**\n     * Parses an ICE password line from the SDP.\n     *\n     * @param {string} line - The ICE password line to parse.\n     * @returns {string} - The parsed ICE password.\n     */\n    parseICEPwd(line: string): string {\n        return line.substring(10);\n    },\n\n    /**\n     * Parses an ICE ufrag line from the SDP.\n     *\n     * @param {string} line - The ICE ufrag line to parse.\n     * @returns {string} - The parsed ICE ufrag.\n     */\n    parseICEUfrag(line: string): string {\n        return line.substring(12);\n    },\n\n    /**\n     * Parses a media ID line from the SDP.\n     *\n     * @param {string} line - The media ID line to parse.\n     * @returns {string} - The parsed media ID.\n     */\n    parseMID(line: string): string {\n        return line.substring(6);\n    },\n\n    /**\n     * Parses a media line from the SDP.\n     *\n     * @param {string} line - The media line to parse.\n     * @returns {IMediaLine} - The parsed media line data.\n     */\n    parseMLine(line: string): IMediaLine {\n        const data: Partial<IMediaLine> = {};\n        const parts = line.substring(2).split(' ');\n\n        data.media = parts.shift();\n        data.port = parts.shift();\n        data.proto = parts.shift();\n        if (parts[parts.length - 1] === '') { // trailing whitespace\n            parts.pop();\n        }\n        data.fmt = parts;\n\n        return data as IMediaLine;\n    },\n\n    /**\n     * Parses the MSID attribute from the given SSRC lines.\n     *\n     * @param {string[]} ssrcLines - The SSRC lines to search.\n     * @returns {Optional<string>} - The parsed MSID or undefined if not found.\n     */\n    parseMSIDAttribute(ssrcLines: string[]): Optional<string> {\n        const msidLine = ssrcLines.find(line => line.indexOf(' msid:') > 0);\n\n        if (!msidLine) {\n            return undefined;\n        }\n\n        const v = msidLine.substring(msidLine.indexOf(' msid:') + 6 /* the length of ' msid:' */);\n\n        return SDPUtil.filterSpecialChars(v);\n    },\n\n    /**\n     * Parse the 'most' primary video ssrc from the given m line\n     * @param {MediaDescription} videoMLine object as parsed from transform.parse\n     * @return {Optional<number>} the primary video ssrc from the given m line\n     */\n    parsePrimaryVideoSsrc(videoMLine: MediaDescription): Optional<number> {\n        const numSsrcs = (videoMLine.ssrcs)\n            .map(ssrcInfo => ssrcInfo.id)\n            .filter((ssrc, index, array) => array.indexOf(ssrc) === index)\n            .length;\n        const numGroups\n            = (videoMLine?.ssrcGroups?.length) || 0;\n\n        if (numSsrcs > 1 && numGroups === 0) {\n            // Ambiguous, can't figure out the primary\n            return;\n        }\n        let primarySsrc: Nullable<number> = null;\n\n        if (numSsrcs === 1) {\n            primarySsrc = videoMLine.ssrcs[0].id;\n        } else if (numSsrcs === 2) {\n            // Can figure it out if there's an FID group\n            const fidGroup\n                = videoMLine.ssrcGroups.find(\n                    group => group.semantics === SSRC_GROUP_SEMANTICS.FID);\n\n            if (fidGroup) {\n                primarySsrc = parseInt(fidGroup.ssrcs.split(' ')[0], 10);\n            }\n        } else if (numSsrcs >= 3) {\n            // Can figure it out if there's a sim group\n            const simGroup\n                = videoMLine.ssrcGroups.find(\n                    group => group.semantics === SSRC_GROUP_SEMANTICS.SIM);\n\n            if (simGroup) {\n                primarySsrc = parseInt(simGroup.ssrcs.split(' ')[0], 10);\n            }\n        }\n\n        return primarySsrc;\n    },\n\n    /**\n     * Parses an RTCP feedback line from the SDP.\n     *\n     * @param {string} line - The RTCP feedback line to parse.\n     * @returns {IRTCPFBData} - The parsed RTCP feedback data.\n     */\n    parseRTCPFB(line: string): IRTCPFBData {\n        const parts = line.substr(10).split(' ');\n        const data: Partial<IRTCPFBData> = {};\n\n        data.pt = parts.shift();\n        data.type = parts.shift();\n        data.params = parts;\n\n        return data as IRTCPFBData;\n    },\n\n    /**\n     * Parses an RTP map line from the SDP.\n     *\n     * @param {string} line - The RTP map line to parse.\n     * @returns {IRTPMapData} - The parsed RTP map data.\n     */\n    parseRTPMap(line: string): IRTPMapData {\n        const data: Partial<IRTPMapData> = {};\n        let parts = line.substring(9).split(' ');\n\n        data.id = parts.shift();\n        parts = parts[0].split('/');\n        data.name = parts.shift();\n        data.clockrate = parts.shift();\n        data.channels = parts.length ? parts.shift() : '1';\n\n        return data as IRTPMapData;\n    },\n\n    /**\n     * Parses SDP line \"a=sctpmap:...\" and extracts SCTP port from it.\n     *\n     * @param {string} line eg. \"a=sctpmap:5000 webrtc-datachannel\"\n     * @returns {[string, string, Nullable<string>]} [SCTP port number, protocol, streams]\n     */\n    parseSCTPMap(line: string): [string, string, Nullable<string>] {\n        const parts = line.substring(10).split(' ');\n        const sctpPort = parts[0];\n        const protocol = parts[1];\n\n        // Stream count is optional\n        const streamCount = parts.length > 2 ? parts[2] : null;\n\n\n        return [ sctpPort, protocol, streamCount ];// SCTP port\n    },\n\n    /**\n     * Parses the SCTP port line from the SDP.\n     *\n     * @param {string} line - The SCTP port line to parse.\n     * @returns {string} - The parsed SCTP port.\n     */\n    parseSCTPPort(line: string): string {\n        return line.substring(12);\n    },\n\n    /**\n     * Parses the SSRC lines from the SDP.\n     *\n     * @param {string} desc - The SDP description to parse.\n     * @returns {Map<string, string[]>} - A map of SSRCs to their corresponding lines.\n     */\n    parseSSRC(desc: string): Map<string, string[]> {\n        // proprietary mapping of a=ssrc lines\n        // TODO: see \"Jingle RTP Source Description\" by Juberti and P. Thatcher\n        // on google docs and parse according to that\n        const data = new Map();\n        const lines = desc.split('\\r\\n');\n\n        for (let i = 0; i < lines.length; i++) {\n            if (lines[i].substring(0, 7) === 'a=ssrc:') {\n                // FIXME: Use regex to smartly find the ssrc.\n                const ssrc = lines[i].split('a=ssrc:')[1].split(' ')[0];\n\n                if (!data.get(ssrc)) {\n                    data.set(ssrc, []);\n                }\n\n                data.get(ssrc).push(lines[i]);\n            }\n        }\n\n        return data;\n    },\n\n    /**\n     * Parses the 'a=ssrc-group' line.\n     *\n     * @param {string} line - The media line to parse.\n     * @returns {ISsrcGroup}\n     */\n    parseSSRCGroupLine(line: string): ISsrcGroup {\n        const parts = line.substr(13).split(' ');\n\n        return {\n            semantics: parts.shift(),\n            ssrcs: parts\n        };\n    },\n\n    /**\n     * Gets the source name out of the name attribute \"a=ssrc:254321 name:name1\".\n     *\n     * @param {string[]} ssrcLines\n     * @returns {Optional<string>}\n     */\n    parseSourceNameLine(ssrcLines: string[]): Optional<string> {\n        const sourceNameLine = ssrcLines.find(ssrcSdpLine => ssrcSdpLine.indexOf(' name:') > 0);\n\n        // Everything past the \"name:\" part\n        return sourceNameLine?.substring(sourceNameLine.indexOf(' name:') + 6);\n    },\n\n    /**\n     * Parse the \"videoType\" attribute encoded in a set of SSRC attributes (e.g.\n     * \"a=ssrc:1234 videoType:desktop\")\n     *\n     * @param {string[]} ssrcLines\n     * @returns {Optional<string>}\n     */\n    parseVideoTypeLine(ssrcLines: string[]): Optional<string> {\n        const s = ' videoType:';\n        const videoTypeLine = ssrcLines.find(ssrcSdpLine => ssrcSdpLine.indexOf(s) > 0);\n\n        return videoTypeLine?.substring(videoTypeLine.indexOf(s) + s.length);\n    },\n\n    /**\n     * Sets the given codecName as the preferred codec by moving it to the beginning\n     * of the payload types list (modifies the given mline in place). All instances\n     * of the codec are moved up.\n     * @param {MediaDescription} mLine the mline object from an sdp as parsed by transform.parse.\n     * @param {string} codecName the name of the preferred codec.\n     * @param {boolean} sortPayloadTypes whether the payloadtypes need to be sorted for a given codec.\n     */\n    preferCodec(mline: MediaDescription, codecName: string, sortPayloadTypes: boolean = false): void {\n        if (!mline || !codecName) {\n            return;\n        }\n\n        const matchingPayloadTypes = mline.rtp\n            .filter(rtp => rtp.codec && rtp.codec.toLowerCase() === codecName.toLowerCase())\n            .map(rtp => rtp.payload);\n\n        if (matchingPayloadTypes) {\n            if (sortPayloadTypes && codecName === CodecMimeType.H264) {\n                // Move all the H.264 codecs with packetization-mode=0 to top of the list.\n                const payloadsWithMode0 = matchingPayloadTypes.filter(payload => {\n                    const fmtp = mline.fmtp.find(item => item.payload === payload);\n\n                    if (fmtp) {\n                        return fmtp.config.includes('packetization-mode=0');\n                    }\n\n                    return false;\n                });\n\n                for (const pt of payloadsWithMode0.reverse()) {\n                    const idx = matchingPayloadTypes.findIndex(payloadType => payloadType === pt);\n\n                    if (idx >= 0) {\n                        matchingPayloadTypes.splice(idx, 1);\n                        matchingPayloadTypes.unshift(pt);\n                    }\n                }\n            }\n\n            // Call toString() on payloads to get around an issue within SDPTransform that sets\n            // payloads as a number, instead of a string, when there is only one payload.\n            const payloadTypes\n                = mline.payloads\n                .toString()\n                .split(' ')\n                .map(p => parseInt(p, 10));\n\n            for (const pt of matchingPayloadTypes.reverse()) {\n                const payloadIndex = payloadTypes.indexOf(pt);\n\n                payloadTypes.splice(payloadIndex, 1);\n                payloadTypes.unshift(pt);\n            }\n            mline.payloads = payloadTypes.join(' ');\n        } else {\n            logger.error(`No matching RTP payload type found for ${codecName}, failed to set preferred codecs`);\n        }\n    },\n\n    /**\n     * Rewrites the ICE credentials of an SDP and removes every ICE candidate from it. Used to build the patched\n     * remote offer that an in-place ICE restart is applied with: the new ufrag/pwd must be applied on their own,\n     * with the candidates trickled in afterwards via `addIceCandidate()`.\n     *\n     * Applying the new candidates in the same `setRemoteDescription()` as the new credentials makes libwebrtc stamp\n     * them with the new ICE generation (candidate lines carry no credentials of their own), treat them as brand new\n     * candidates for the same remote address and synchronously tear down the selected candidate pair - which\n     * defeats the make-before-break the whole in-place restart exists for.\n     *\n     * Reported upstream as https://issues.webrtc.org/issues/543082385\n     *\n     * Every other line, and the original line separators, are preserved verbatim.\n     *\n     * @param {string} sdp - The SDP to patch.\n     * @param {string} ufrag - The new ICE ufrag.\n     * @param {string} pwd - The new ICE pwd.\n     * @returns {string} - The patched SDP.\n     */\n    replaceIceCredentialsAndStripCandidates(sdp: string, ufrag: string, pwd: string): string {\n        const patched = [];\n\n        for (const line of sdp.split('\\n')) {\n            // Preserve the original line separator ('\\r\\n' vs '\\n').\n            const cr = line.endsWith('\\r') ? '\\r' : '';\n            const content = cr ? line.substring(0, line.length - 1) : line;\n\n            if (content.startsWith('a=candidate:') || content.startsWith('a=end-of-candidates')) {\n                continue;\n            }\n\n            if (content.startsWith('a=ice-ufrag:')) {\n                patched.push(`a=ice-ufrag:${ufrag}${cr}`);\n            } else if (content.startsWith('a=ice-pwd:')) {\n                patched.push(`a=ice-pwd:${pwd}${cr}`);\n            } else {\n                patched.push(line);\n            }\n        }\n\n        return patched.join('\\n');\n    },\n\n    /**\n     * Strips the given codec from the given mline. All related RTX payload\n     * types are also stripped. If the resulting mline would have no codecs,\n     * it's disabled.\n     *\n     * @param {MediaDescription} mLine the mline object from an sdp as parsed by transform.parse.\n     * @param {string} codecName the name of the codec which will be stripped.\n     * @param {boolean} highProfile determines if only the high profile codec needs to be stripped from the sdp for a\n     * given codec type.\n     */\n    stripCodec(mLine: MediaDescription, codecName: string, highProfile: boolean = false): void {\n        if (!mLine || !codecName) {\n            return;\n        }\n\n        const highProfileCodecs = new Map();\n        let removePts = [];\n\n        for (const rtp of mLine.rtp) {\n            if (rtp.codec && rtp.codec.toLowerCase() === codecName.toLowerCase()) {\n                if (highProfile) {\n                    highProfileCodecs.set(rtp.payload, rtp.codec);\n                } else {\n                    removePts.push(rtp.payload);\n                }\n            }\n        }\n\n        if (highProfile) {\n            removePts = mLine.fmtp\n                .filter(item => {\n                    const codec = highProfileCodecs.get(item.payload);\n\n                    if (codec) {\n                        // Firefox does not signal 'profile-id' for VP9 at all and Chrome omits it for the H.264\n                        // baseline profile. Both default to the low profile when the parameter is missing, therefore\n                        // these payload types have to be preserved.\n                        return codec.toLowerCase() === CodecMimeType.VP9\n                            ? item.config.includes('profile-id=') && !item.config.includes('profile-id=0')\n                            : item.config.includes('profile-level-id=')\n                                && !item.config.includes('profile-level-id=42');\n                    }\n\n                    return false;\n                })\n                .map(item => item.payload);\n        }\n\n        if (removePts.length > 0) {\n            // We also need to remove the payload types that are related to RTX\n            // for the codecs we want to disable.\n            const rtxApts = removePts.map(item => `apt=${item}`);\n            const rtxPts = mLine.fmtp.filter(\n                item => rtxApts.indexOf(item.config) !== -1);\n\n            removePts.push(...rtxPts.map(item => item.payload));\n\n            // Call toString() on payloads to get around an issue within\n            // SDPTransform that sets payloads as a number, instead of a string,\n            // when there is only one payload.\n            const allPts = mLine.payloads\n                .toString()\n                .split(' ')\n                .map(Number);\n            const keepPts = allPts.filter(pt => removePts.indexOf(pt) === -1);\n\n            if (keepPts.length === 0) {\n                // There are no other codecs, disable the stream.\n                mLine.port = 0;\n                mLine.direction = MediaDirection.INACTIVE;\n                mLine.payloads = '*';\n            } else {\n                mLine.payloads = keepPts.join(' ');\n            }\n\n            mLine.rtp = mLine.rtp.filter(\n                item => keepPts.indexOf(item.payload) !== -1);\n            mLine.fmtp = mLine.fmtp.filter(\n                item => keepPts.indexOf(item.payload) !== -1);\n            if (mLine.rtcpFb) {\n                mLine.rtcpFb = mLine.rtcpFb.filter(\n                    item => keepPts.indexOf(Number(item.payload)) !== -1);\n            }\n        }\n    }\n};\n\nexport default SDPUtil;\n","import { getLogger } from '@jitsi/logger';\n\nimport { MediaDirection } from '../../service/RTC/MediaDirection';\nimport { MediaType } from '../../service/RTC/MediaType';\nimport { SSRC_GROUP_SEMANTICS } from '../../service/RTC/StandardVideoQualitySettings';\n\nimport SDPUtil from './SDPUtil';\nimport { SdpTransformWrap, parseSecondarySSRC } from './SdpTransformUtil';\n\nconst logger = getLogger('sdp:RtxModifier');\n\n/**\n * Begin helper functions\n */\n/**\n * Updates or inserts the appropriate rtx information for primarySsrc with\n *  the given rtxSsrc.  If no rtx ssrc for primarySsrc currently exists, it will\n *  add the appropriate ssrc and ssrc group lines.  If primarySsrc already has\n *  an rtx ssrc, the appropriate ssrc and group lines will be updated\n * @param {MLineWrap} mLine\n * @param {object} primarySsrcInfo the info (ssrc, msid & cname) for the\n *  primary ssrc\n * @param {number} rtxSsrc the rtx ssrc to associate with the primary ssrc\n */\nfunction updateAssociatedRtxStream(mLine, primarySsrcInfo, rtxSsrc) {\n    const primarySsrc = primarySsrcInfo.id;\n    const primarySsrcMsid = primarySsrcInfo.msid;\n    const primarySsrcCname = primarySsrcInfo.cname;\n\n    const previousRtxSSRC = mLine.getRtxSSRC(primarySsrc);\n\n    if (previousRtxSSRC === rtxSsrc) {\n        return;\n    }\n    if (previousRtxSSRC) {\n        // Stream already had an rtx ssrc that is different than the one given,\n        //  remove all trace of the old one\n        mLine.removeSSRC(previousRtxSSRC);\n        mLine.removeGroupsWithSSRC(previousRtxSSRC);\n    }\n    mLine.addSSRCAttribute({\n        attribute: 'cname',\n        id: rtxSsrc,\n        value: primarySsrcCname\n    });\n    primarySsrcMsid && mLine.addSSRCAttribute({\n        attribute: 'msid',\n        id: rtxSsrc,\n        value: primarySsrcMsid\n    });\n    mLine.addSSRCGroup({\n        semantics: SSRC_GROUP_SEMANTICS.FID,\n        ssrcs: `${primarySsrc} ${rtxSsrc}`\n    });\n}\n\n/**\n * End helper functions\n */\n\n/**\n * Adds any missing RTX streams for video streams\n *  and makes sure that they remain consistent\n */\nexport default class RtxModifier {\n    /**\n     * Constructor\n     */\n    constructor() {\n        /**\n         * Map of video ssrc to corresponding RTX\n         *  ssrc\n         */\n        this.correspondingRtxSsrcs = new Map();\n    }\n\n    /**\n     * Clear the cached map of primary video ssrcs to\n     *  their corresponding rtx ssrcs so that they will\n     *  not be used for the next call to modifyRtxSsrcs\n     */\n    clearSsrcCache() {\n        this.correspondingRtxSsrcs.clear();\n    }\n\n    /**\n     * Explicitly set the primary video ssrc -> rtx ssrc\n     *  mapping to be used in modifyRtxSsrcs\n     * @param {Map} ssrcMapping a mapping of primary video\n     *  ssrcs to their corresponding rtx ssrcs\n     */\n    setSsrcCache(ssrcMapping) {\n        logger.debug('Setting ssrc cache to ', ssrcMapping);\n        this.correspondingRtxSsrcs = ssrcMapping;\n    }\n\n    /**\n     * Adds RTX ssrcs for any video ssrcs that don't already have them.  If the video ssrc has been seen before, and\n     * already had an RTX ssrc generated, the same RTX ssrc will be used again.\n     *\n     * @param {string} sdpStr sdp in raw string format\n     * @returns {string} The modified sdp in raw string format.\n     */\n    modifyRtxSsrcs(sdpStr) {\n        let modified = false;\n        const sdpTransformer = new SdpTransformWrap(sdpStr);\n        const videoMLines = sdpTransformer.selectMedia(MediaType.VIDEO);\n\n        if (!videoMLines?.length) {\n            logger.debug(`No 'video' media found in the sdp: ${sdpStr}`);\n\n            return sdpStr;\n        }\n\n        for (const videoMLine of videoMLines) {\n            if (this.modifyRtxSsrcs2(videoMLine)) {\n                modified = true;\n            }\n        }\n\n        return modified ? sdpTransformer.toRawSDP() : sdpStr;\n    }\n\n    /**\n     * Does the same thing as {@link modifyRtxSsrcs}, but takes the {@link MLineWrap} instance wrapping video media as\n     * an argument.\n     * @param {MLineWrap} videoMLine\n     * @return {boolean} <tt>true</tt> if the SDP wrapped by {@link SdpTransformWrap} has been modified or\n     * <tt>false</tt> otherwise.\n     */\n    modifyRtxSsrcs2(videoMLine) {\n        if (videoMLine.direction === MediaDirection.RECVONLY) {\n            return false;\n        }\n        if (videoMLine.getSSRCCount() < 1) {\n            return false;\n        }\n        const primaryVideoSsrcs = videoMLine.getPrimaryVideoSSRCs();\n\n        for (const ssrc of primaryVideoSsrcs) {\n            const msid = videoMLine.getSSRCAttrValue(ssrc, 'msid');\n            const cname = videoMLine.getSSRCAttrValue(ssrc, 'cname');\n            let correspondingRtxSsrc = this.correspondingRtxSsrcs.get(ssrc);\n\n            if (!correspondingRtxSsrc) {\n                // If there's one in the sdp already for it, we'll just set\n                //  that as the corresponding one\n                const previousAssociatedRtxStream = videoMLine.getRtxSSRC(ssrc);\n\n                if (previousAssociatedRtxStream) {\n                    correspondingRtxSsrc = previousAssociatedRtxStream;\n                } else {\n                    correspondingRtxSsrc = SDPUtil.generateSsrc();\n                }\n                this.correspondingRtxSsrcs.set(ssrc, correspondingRtxSsrc);\n            }\n            updateAssociatedRtxStream(\n                videoMLine,\n                {\n                    cname,\n                    id: ssrc,\n                    msid\n                },\n                correspondingRtxSsrc);\n        }\n\n        // FIXME we're not looking into much details whether the SDP has been\n        // modified or not once the precondition requirements are met.\n        return true;\n    }\n\n    /**\n     * Strip all rtx streams from the given sdp.\n     *\n     * @param {string} sdpStr sdp in raw string format\n     * @returns {string} sdp string with all rtx streams stripped\n     */\n    stripRtx(sdpStr) {\n        const sdpTransformer = new SdpTransformWrap(sdpStr);\n        const videoMLines = sdpTransformer.selectMedia(MediaType.VIDEO);\n\n        if (!videoMLines?.length) {\n            logger.debug(`No 'video' media found in the sdp: ${sdpStr}`);\n\n            return sdpStr;\n        }\n\n        for (const videoMLine of videoMLines) {\n            if (videoMLine.direction !== MediaDirection.RECVONLY\n                && videoMLine.getSSRCCount()\n                && videoMLine.containsAnySSRCGroups()) {\n                const fidGroups = videoMLine.findGroups(SSRC_GROUP_SEMANTICS.FID);\n\n                // Remove the fid groups from the mline\n                videoMLine.removeGroupsBySemantics(SSRC_GROUP_SEMANTICS.FID);\n\n                // Get the rtx ssrcs and remove them from the mline\n                for (const fidGroup of fidGroups) {\n                    const rtxSsrc = parseSecondarySSRC(fidGroup);\n\n                    videoMLine.removeSSRC(rtxSsrc);\n                }\n            }\n        }\n\n        return sdpTransformer.toRawSDP();\n    }\n}\n","\nexport enum XEP {\n\n    /**\n     * XEP-0338 - Signals the usage of bundled media, i.e., allows the use of a single set of ICE candidates for\n     * multiple media descriptions.\n     * https://xmpp.org/extensions/attic/xep-0338-1.0.0.html\n     */\n    BUNDLE_MEDIA = 'urn:xmpp:jingle:apps:grouping:0',\n\n    /**\n     * XEP-0320 - Signals the use of DTLS-SRTP in Jingle session.\n     * https://xmpp.org/extensions/xep-0320.html\n     */\n    DTLS_SRTP = 'urn:xmpp:jingle:apps:dtls:0',\n\n    /**\n     * XEP-0176 - Signaling ICE-UDP transport method.\n     * https://xmpp.org/extensions/xep-0176.html\n     */\n    ICE_UDP_TRANSPORT = 'urn:xmpp:jingle:transports:ice-udp:1',\n\n    /**\n     * XEP-0166 - Jingle.\n     * https://xmpp.org/extensions/xep-0166.html\n     */\n    JINGLE = 'urn:xmpp:jingle:1',\n\n    /**\n     * XEP-0327 - Rayo for allowing third-party control over media sessions.\n     */\n    RAYO = 'urn:xmpp:rayo:client:1',\n\n    /**\n     * XEP-0167 - Signals support for RTP audio.\n     * https://xmpp.org/extensions/xep-0167.html#support\n     */\n    RTP_AUDIO = 'urn:xmpp:jingle:apps:rtp:audio',\n\n    /**\n     * XEP-0293 - Signals the use of RTP Feedback Negotiation.\n     * https://xmpp.org/extensions/xep-0293.html\n     */\n    RTP_FEEDBACK = 'urn:xmpp:jingle:apps:rtp:rtcp-fb:0',\n\n    /**\n     * XEP-0294 - Signals the use of RTP Header Extensions.\n     * https://xmpp.org/extensions/xep-0294.html\n     */\n    RTP_HEADER_EXTENSIONS = 'urn:xmpp:jingle:apps:rtp:rtp-hdrext:0',\n\n    /**\n     * XEP-0167 - Signals parameters necessary for media sessions using RTP.\n     * https://xmpp.org/extensions/xep-0167.html\n     */\n    RTP_MEDIA = 'urn:xmpp:jingle:apps:rtp:1',\n\n    /**\n     * XEP-0167 - Signals support for RTP video.\n     * https://xmpp.org/extensions/xep-0167.html#support\n     */\n    RTP_VIDEO = 'urn:xmpp:jingle:apps:rtp:video',\n\n    /**\n     * XEP-0343 - Signaling WebRTC datachannels (bridge channel) in Jingle that uses DTLS/SCTP on top of ICE.\n     * https://xmpp.org/extensions/xep-0343.html\n     */\n    SCTP_DATA_CHANNEL = 'urn:xmpp:jingle:transports:dtls-sctp:1',\n\n    /**\n     * XEP-0339 - Signals Source-Specific Media Attributes in Jingle.\n     * https://xmpp.org/extensions/xep-0339.html\n     */\n    SOURCE_ATTRIBUTES = 'urn:xmpp:jingle:apps:rtp:ssma:0'\n}\n","import { getLogger } from '@jitsi/logger';\n\nconst logger = getLogger('util:XMLUtils');\n\n/**\n * Parses an XML string into a Document.\n * @param xmlString - The XML string to parse.\n * @returns Parsed XML Document or null if parsing fails.\n */\nexport function parseXML(xmlString: string): Nullable<Document> {\n    if (!xmlString || typeof xmlString !== 'string') {\n        return null;\n    }\n\n    const parser = new DOMParser();\n    const doc = parser.parseFromString(xmlString, 'text/xml');\n\n    // Check for parser errors.\n    const parserError = findFirst(doc, 'parsererror');\n\n    if (parserError) {\n        logger.error('XML parsing error:', parserError.textContent || '');\n        // Return the document anyway for compatibility\n        // jQuery also returns a document with parser errors\n    }\n\n    return doc;\n}\n\n/**\n * Finds all elements matching the CSS selector within the given element.\n * @param element - The element or document to search within.\n * @param selector - CSS selector string.\n * @returns Array of matching elements.\n */\nexport function findAll(element: Element | Document, selector: string): Element[] {\n    if (!element) {\n        return [];\n    }\n\n    try {\n        return Array.from(element.querySelectorAll(selector));\n    } catch (error) {\n        logger.error('findAll error:', selector, error);\n\n        return [];\n    }\n}\n\n/**\n * Gets the value of an attribute from an element.\n * @param element - The element to get the attribute from.\n * @param name - The attribute name.\n * @returns The attribute value or null if not found.\n */\nexport function getAttribute(element: Element | null, name: string): string | null {\n    if (!element || !name) {\n        return null;\n    }\n\n    return element.getAttribute(name);\n}\n\n/**\n * Sets an attribute on an element.\n * @param element - The element to set the attribute on.\n * @param name - The attribute name.\n * @param value - The attribute value.\n */\nexport function setAttribute(element: Element | null, name: string, value: string): void {\n    if (!element || !name) {\n        return;\n    }\n\n    element.setAttribute(name, value);\n}\n\n/**\n * Gets the text content of an element.\n * @param element - The element to get text from.\n * @returns The text content or empty string if element is null.\n */\nexport function getText(element: Element | null): string {\n    if (!element) {\n        return '';\n    }\n\n    return element.textContent || '';\n}\n\n/**\n * Sets the text content of an element.\n * @param element - The element to set text on.\n * @param text - The text content to set.\n */\nexport function setText(element: Element | null, text: string): void {\n    if (!element) {\n        return;\n    }\n\n    element.textContent = text;\n}\n\n/**\n * Gets the child elements of an element (excluding text nodes).\n * @param element - The parent element.\n * @returns Array of child elements.\n */\nexport function getChildren(element: Element): Element[] {\n    if (!element) {\n        return [];\n    }\n\n    return Array.from(element.children);\n}\n\n/**\n * Checks if any elements match the selector within the given element.\n * @param element - The element or document to search within.\n * @param selector - CSS selector string.\n * @returns True if at least one element matches the selector.\n */\nexport function exists(element: Element | Document, selector: string): boolean {\n    if (!element) {\n        return false;\n    }\n\n    try {\n        return element.querySelector(selector) !== null;\n    } catch (error) {\n        logger.error('exists error:', selector, error);\n\n        return false;\n    }\n}\n\n/**\n * Gets the first element matching the selector, or null if none found.\n * This is a convenience function equivalent to findAll(...)[0] || null.\n * @param element - The element or document to search within.\n * @param selector - CSS selector string.\n * @returns The first matching element or null.\n */\nexport function findFirst(element: Element | Document, selector: string): Element | null {\n    if (!element) {\n        return null;\n    }\n\n    try {\n        return element.querySelector(selector);\n    } catch (error) {\n        logger.error('findFirst error:', selector, error);\n\n        return null;\n    }\n}\n\n/**\n * Matches the characters that are not allowed in an XML 1.0 document. Sending\n * such characters (e.g. the START OF TEXT control character U+0002) in a\n * message produces a malformed stanza which makes the server terminate the\n * stream, dropping everyone from the meeting.\n *\n * The pattern is the inverse of the characters allowed by the XML 1.0\n * specification:\n *\n *     #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]\n *\n * Encoding the allowed ranges (rather than denying a list of forbidden ones)\n * keeps every permitted code point intact - including astral characters such\n * as emoji, which are represented as surrogate pairs - while stripping lone\n * surrogates (U+D800-U+DFFF), which are invalid in XML 1.0. The unicode flag\n * makes the pattern operate on whole code points instead of surrogate halves.\n */\n// eslint-disable-next-line no-control-regex\nconst INVALID_XML_CHARS_REGEXP = /[^\\u0009\\u000A\\u000D\\u0020-\\uD7FF\\uE000-\\uFFFD\\u{10000}-\\u{10FFFF}]/gu;\n\n/**\n * Removes the characters that are not allowed in an XML 1.0 document from the\n * given string.\n * @param text - The text to sanitize.\n * @returns The text without the XML-invalid characters.\n */\nexport function stripXMLInvalidChars(text: string): string {\n    return text.replace(INVALID_XML_CHARS_REGEXP, '');\n}\n","\nimport { cloneDeep } from 'lodash-es';\nimport transform from 'sdp-transform';\nimport { Strophe } from 'strophe.js';\n\nimport { MediaDirection } from '../../service/RTC/MediaDirection';\nimport { MediaType } from '../../service/RTC/MediaType';\nimport { SourceName } from '../../service/RTC/SignalingLayer';\nimport { SSRC_GROUP_SEMANTICS } from '../../service/RTC/StandardVideoQualitySettings';\nimport { XEP } from '../../service/xmpp/XMPPExtensioProtocols';\nimport { ITPCSourceInfo } from '../RTC/TraceablePeerConnection';\nimport browser from '../browser';\nimport { exists, findAll, findFirst, getAttribute, getText } from '../util/XMLUtils';\n\nimport SDPUtil from './SDPUtil';\nimport { IMediaInfo } from './constants';\n\n\n/**\n * A class that translates the Jingle messages received from the signaling server into SDP format that the\n * browser understands and vice versa. This is needed for media session establishment and for signaling local and\n * remote sources across peers.\n */\nexport default class SDP {\n    public raw: string;\n    public session: string;\n    public media: string[];\n    public isP2P: boolean;\n    public failICE: boolean;\n    public removeTcpCandidates: boolean;\n    public removeUdpCandidates: boolean;\n    public initialLastN?: number;\n\n    /**\n     * Constructor.\n     *\n     * @param {string} sdp - The SDP generated by the browser when SDP->Jingle conversion is needed, an empty string\n     * when Jingle->SDP conversion is needed.\n     * @param {boolean} isP2P - Whether this SDP belongs to a p2p peerconnection.\n     */\n    constructor(sdp: string, isP2P: boolean = false) {\n        this._updateSessionAndMediaSections(sdp);\n        this.isP2P = isP2P;\n        this.raw = this.session + this.media.join('');\n\n        // This flag will make {@link transportToJingle} and {@link jingle2media} replace ICE candidates IPs with\n        // invalid value of '1.1.1.1' which will cause ICE failure. The flag is used in the automated testing.\n        this.failICE = false;\n\n        // Whether or not to remove TCP ice candidates when translating from/to jingle.\n        this.removeTcpCandidates = false;\n\n        // Whether or not to remove UDP ice candidates when translating from/to jingle.\n        this.removeUdpCandidates = false;\n    }\n\n    /**\n     * Adjusts the msid semantic for a remote source based on the media type and the index of the m-line.\n     * This is needed for browsers that need both the streamId and trackId to be reported in the msid attribute.\n     *\n     * @param {String} msid - The msid attribute value.\n     * @param {MediaType} mediaType - The media type.\n     * @param {Number|String} idx - The index of the m-line in the SDP.\n     * @returns {String} - The adjusted msid semantic.\n     */\n    private _adjustMsidSemantic(msid: string, mediaType: MediaType, idx: number | string): string {\n        if (mediaType === MediaType.AUDIO || !browser.isChromiumBased() || browser.isEngineVersionGreaterThan(116)) {\n            return msid;\n        }\n\n        const msidParts = msid.split(' ');\n\n        if (msidParts.length === 2) {\n            return msid;\n        }\n\n        return `${msid} ${msid}-${idx}`;\n    }\n\n    /**\n     * Updates the media and session sections of the SDP based on the raw SDP string.\n     *\n     * @param {string} sdp - The SDP generated by the browser.\n     * @returns {void}\n     * @private\n     */\n    private _updateSessionAndMediaSections(sdp?: string): void {\n        const media = typeof sdp === 'string' ? sdp.split('\\r\\nm=') : this.raw.split('\\r\\nm=');\n\n        for (let i = 1, length = media.length; i < length; i++) {\n            let mediaI = `m=${media[i]}`;\n\n            if (i !== length - 1) {\n                mediaI += '\\r\\n';\n            }\n            media[i] = mediaI;\n        }\n        this.session = `${media.shift()}\\r\\n`;\n        this.media = media;\n    }\n\n    /**\n     * Removes every line of the given media section whose token (the text up to the first space) equals the provided\n     * prefix. Used to drop the {@code a=ssrc:} / {@code a=ssrc-group:} lines for a source that is being removed. The\n     * prefix is matched with a plain string comparison rather than a constructed RegExp so that a value carried in the\n     * signaling can never be interpreted as a pattern.\n     *\n     * @param {string} mediaSection - The media section (m-line block) to filter.\n     * @param {string} prefix - The full line token to remove, e.g. {@code a=ssrc:12345} or {@code a=ssrc-group:FID}.\n     * @returns {string} The media section with the matching lines removed.\n     */\n    private _removeLinesWithPrefix(mediaSection: string, prefix: string): string {\n        return mediaSection\n            .split('\\r\\n')\n            .filter(line => line !== prefix && !line.startsWith(`${prefix} `))\n            .join('\\r\\n');\n    }\n\n    /**\n     * Adds or removes the sources from the SDP.\n     *\n     * @param {Map<SourceName, ITPCSourceInfo>} sourceMap - The map of the sources that are being added/removed.\n     * @param {boolean} isAdd - Whether the sources are being added or removed.\n     * @returns {Array<number>} - The indices of the new m-lines that were added/modifed in the SDP.\n     */\n    public updateRemoteSources(sourceMap: Map<SourceName, ITPCSourceInfo>, isAdd: boolean = true): number[] {\n        const updatedMidIndices = [];\n\n        for (const source of sourceMap.values()) {\n            const { mediaType, mid, msid, ssrcList, groups } = source;\n            let idx;\n\n            if (isAdd) {\n                // For P2P, check if there is an m-line with the matching mediaType that doesn't have any ssrc lines.\n                // Update the existing m-line if it exists, otherwise create a new m-line and add the sources.\n                idx = this.media.findIndex(mLine => mLine.includes(`m=${mediaType}`) && !mLine.includes('a=ssrc'));\n                if (!this.isP2P || idx === -1) {\n                    this.addMlineForNewSource(mediaType, true, mid);\n                    idx = this.media.length - 1;\n                }\n            } else {\n                idx = this.media.findIndex(mLine => mLine.includes(`a=ssrc:${ssrcList[0]}`));\n\n                if (idx === -1) {\n                    continue; // eslint-disable-line no-continue\n                }\n            }\n\n            updatedMidIndices.push(idx);\n\n            if (isAdd) {\n                const updatedMsid = this._adjustMsidSemantic(msid, mediaType, idx);\n\n                ssrcList.forEach(ssrc => {\n                    this.media[idx] += `a=ssrc:${ssrc} msid:${updatedMsid}\\r\\n`;\n                });\n                groups?.forEach(group => {\n                    this.media[idx] += `a=ssrc-group:${group.semantics} ${group.ssrcs.join(' ')}\\r\\n`;\n                });\n            } else {\n                ssrcList.forEach(ssrc => {\n                    this.media[idx] = this._removeLinesWithPrefix(this.media[idx], `a=ssrc:${ssrc}`);\n                });\n                groups?.forEach(group => {\n                    this.media[idx] = this._removeLinesWithPrefix(this.media[idx], `a=ssrc-group:${group.semantics}`);\n                });\n\n                if (!this.isP2P) {\n                    // Reject the m-line so that the browser removes the associated transceiver from the list of\n                    // available transceivers. This will prevent the client from trying to re-use these inactive\n                    // transceivers when additional video sources are added to the peerconnection.\n                    const { media, port } = SDPUtil.parseMLine(this.media[idx].split('\\r\\n')[0]);\n\n                    this.media[idx] = this.media[idx]\n                        .replace(`a=${MediaDirection.SENDONLY}`, `a=${MediaDirection.INACTIVE}`);\n                    this.media[idx] = this.media[idx].replace(`m=${media} ${port}`, `m=${media} 0`);\n                }\n            }\n            this.raw = this.session + this.media.join('');\n        }\n\n        return updatedMidIndices;\n    }\n\n    /**\n     * Adds a new m-line to the description so that a new local or remote source can be added to the conference.\n     *\n     * @param {MediaType} mediaType media type of the new source that is being added.\n     * @param {boolean} isRemote - Whether this is for a remote source.\n     * @param {string} [mid] - The mid to assign to the new m-line. When the bridge demuxes by mid (mid-based demuxing\n     * under SSRC rewriting) this must be the mid the bridge stamps on the source's packets. Defaults to the next m-line\n     * index.\n     * @returns {void}\n     */\n    public addMlineForNewSource(mediaType: MediaType, isRemote: boolean = false, mid?: string): void {\n        const newMid = mid ?? this.media.length.toString();\n        const sdp = transform.parse(this.raw);\n        const mline = cloneDeep(sdp.media.find(m => m.type === mediaType));\n\n        // Edit media direction, mid and remove the existing ssrc lines in the m-line.\n        mline.mid = newMid;\n        mline.direction = isRemote ? MediaDirection.SENDONLY : MediaDirection.RECVONLY;\n        mline.msid = undefined;\n        mline.ssrcs = undefined;\n        mline.ssrcGroups = undefined;\n\n        sdp.media = [ ...sdp.media, mline ];\n\n        // We regenerate the BUNDLE group (since we added a new m-line).\n        sdp.groups.forEach(group => {\n            if (group.type === 'BUNDLE') {\n                group.mids = [ ...group.mids.split(' '), newMid ].join(' ');\n            }\n        });\n\n        this.raw = transform.write(sdp);\n        this._updateSessionAndMediaSections();\n    }\n\n    /**\n     * Converts the Jingle message element to SDP.\n     *\n     * @param {*} jingle - The Jingle message element.\n     * @returns {void}\n     */\n    public fromJingle(jingle: any): void {\n        const sessionId = Date.now();\n\n        // Use a unique session id for every TPC.\n        this.raw = 'v=0\\r\\n'\n            + `o=- ${sessionId} 2 IN IP4 0.0.0.0\\r\\n`\n            + 's=-\\r\\n'\n            + 't=0 0\\r\\n';\n\n        // Use *|xmlns to match xmlns attributes across any namespace (CSS Selectors Level 3)\n        const groups = findAll(jingle, `:scope>group[*|xmlns='${XEP.BUNDLE_MEDIA}']`);\n\n        if (this.isP2P && groups.length) {\n            groups.forEach(group => {\n                const contents = findAll(group, ':scope>content')?.map(content => content.getAttribute('name'));\n\n                if (contents?.length > 0) {\n                    this.raw\n                        += `a=group:${\n                            group.getAttribute('semantics')\n                                || group.getAttribute('type')} ${\n                            contents.join(' ')}\\r\\n`;\n                }\n            });\n        }\n\n        // Check if any fingerprint has cryptex attribute and add session-level a=cryptex\n        const allFingerprints = findAll(jingle, `:scope>content>transport[*|xmlns='${XEP.ICE_UDP_TRANSPORT}']>fingerprint[*|xmlns='${XEP.DTLS_SRTP}']`);\n        const hasCryptex = allFingerprints.some(fp => getAttribute(fp, 'cryptex') === 'true');\n\n        if (hasCryptex) {\n            this.raw += 'a=cryptex\\r\\n';\n        }\n\n        this.session = this.raw;\n\n        findAll(jingle, ':scope>content').forEach(content => {\n            const m = this.jingle2media(content);\n\n            this.media.push(m);\n        });\n\n        this.raw = this.session + this.media.join('');\n\n        if (this.isP2P) {\n            return;\n        }\n\n        // For offers from Jicofo, a new m-line needs to be created for each new remote source that is added to the\n        // conference.\n        const newSession = transform.parse(this.raw);\n        const newMedia = [];\n\n        newSession.media.forEach(mLine => {\n            const type = mLine.type;\n\n            if (type === MediaType.APPLICATION) {\n                const newMline = cloneDeep(mLine);\n\n                newMline.mid = newMedia.length.toString();\n                newMedia.push(newMline);\n\n                return;\n            }\n\n            if (!mLine.ssrcs?.length) {\n                const newMline = cloneDeep(mLine);\n\n                newMline.mid = newMedia.length.toString();\n                newMedia.push(newMline);\n\n                return;\n            }\n\n            mLine.ssrcs.forEach((ssrc, idx) => {\n                // Do nothing if the m-line with the given SSRC already exists.\n                if (newMedia.some(mline => mline.ssrcs?.some(source => source.id === ssrc.id))) {\n                    return;\n                }\n                const newMline = cloneDeep(mLine);\n\n                newMline.ssrcs = [];\n                newMline.ssrcGroups = [];\n                newMline.mid = newMedia.length.toString();\n                (newMline as any).bundleOnly = undefined;\n                newMline.direction = idx ? 'sendonly' : 'sendrecv';\n\n                // Add the sources and the related FID source group to the new m-line.\n                const ssrcId = ssrc.id.toString();\n                const group = mLine.ssrcGroups?.find(g => g.ssrcs.includes(ssrcId));\n\n                if (group) {\n                    if (ssrc.attribute === 'msid') {\n                        ssrc.value = this._adjustMsidSemantic(ssrc.value, type as MediaType, parseInt(newMline.mid, 10));\n                    }\n                    newMline.ssrcs.push(ssrc);\n                    const otherSsrc = group.ssrcs.split(' ').find(s => s !== ssrcId);\n\n                    if (otherSsrc) {\n                        const otherSource = mLine.ssrcs.find(source => source.id.toString() === otherSsrc);\n\n                        if (otherSource.attribute === 'msid') {\n                            otherSource.value = this._adjustMsidSemantic(otherSource.value, type as MediaType, parseInt(newMline.mid, 10));\n                        }\n                        newMline.ssrcs.push(otherSource);\n                    }\n                    newMline.ssrcGroups.push(group);\n                } else {\n                    newMline.ssrcs.push(ssrc);\n                }\n                newMedia.push(newMline);\n            });\n        });\n\n        newSession.media = newMedia;\n        const mids = [];\n\n        newMedia.forEach(mLine => {\n            mids.push(mLine.mid);\n        });\n\n        if (groups.length) {\n            // We regenerate the BUNDLE group (since we regenerated the mids)\n            newSession.groups = [ {\n                mids: mids.join(' '),\n                type: 'BUNDLE'\n            } ];\n        }\n\n        // msid semantic\n        newSession.msidSemantic = {\n            semantic: 'WMS',\n            token: '*'\n        };\n\n        // Increment the session version every time.\n        newSession.origin.sessionVersion++;\n\n        this.raw = transform.write(newSession);\n        this._updateSessionAndMediaSections();\n    }\n\n    /**\n     * Returns an SSRC Map by extracting SSRCs and SSRC groups from all the m-lines in the SDP.\n     *\n     * @returns {Map<number, IMediaInfo>}\n     */\n    public getMediaSsrcMap(): Map<number, IMediaInfo> {\n        const sourceInfo = new Map();\n\n        this.media.forEach((mediaItem, mediaindex) => {\n            const midLine = SDPUtil.findLine(mediaItem, 'a=mid:');\n            const mid = typeof midLine === 'string' ? SDPUtil.parseMID(midLine) : '';\n            const mline = SDPUtil.parseMLine(mediaItem.split('\\r\\n')[0]);\n            const isRecvOnly = SDPUtil.findLine(mediaItem, `a=${MediaDirection.RECVONLY}`);\n\n            // Do not process recvonly m-lines. Firefox generates recvonly SSRCs for all remote sources.\n            if (isRecvOnly && browser.isFirefox()) {\n                return;\n            }\n\n            const media = {\n                mediaType: mline.media,\n                mediaindex,\n                mid,\n                ssrcGroups: [],\n                ssrcs: {}\n            };\n\n            SDPUtil.findLines(mediaItem, 'a=ssrc:').forEach((line: string) => {\n                const linessrc = line.substring(7).split(' ')[0];\n\n                // Allocate new ChannelSsrc.\n                if (!media.ssrcs[linessrc]) {\n                    media.ssrcs[linessrc] = {\n                        lines: [],\n                        ssrc: linessrc\n                    };\n                }\n                media.ssrcs[linessrc].lines.push(line);\n            });\n\n            SDPUtil.findLines(mediaItem, 'a=ssrc-group:').forEach((line: string) => {\n                const idx = line.indexOf(' ');\n                const semantics = line.substr(0, idx).substr(13);\n                const ssrcs = line.substr(14 + semantics.length).split(' ');\n\n                if (ssrcs.length) {\n                    media.ssrcGroups.push({\n                        semantics,\n                        ssrcs\n                    });\n                }\n            });\n\n            sourceInfo.set(mediaindex, media);\n        });\n\n        return sourceInfo;\n    }\n\n    /**\n     * Converts the content section from Jingle to a media section that can be appended to the SDP.\n     *\n     * @param {Element} content - The content section from the Jingle message element.\n     * @returns {string} - The constructed media sections.\n     */\n    public jingle2media(content: Element): string {\n        const desc = findFirst(content, ':scope>description');\n\n        // Use *|xmlns to match xmlns attributes across any namespace (CSS Selectors Level 3)\n        const transport = findFirst(content, `:scope>transport[*|xmlns='${XEP.ICE_UDP_TRANSPORT}']`);\n        let sdp = '';\n\n        // Use *|xmlns to match xmlns attributes across any namespace (CSS Selectors Level 3)\n        const sctp = findFirst(transport, `:scope>sctpmap[*|xmlns='${XEP.SCTP_DATA_CHANNEL}']`);\n        const media: any = { media: getAttribute(desc, 'media') };\n        const mid = getAttribute(content, 'name');\n\n        media.port = '9';\n        if (getAttribute(content, 'senders') === 'rejected') {\n            media.port = '0';\n        }\n\n        // Use *|xmlns to match xmlns attributes across any namespace (CSS Selectors Level 3)\n        if (exists(transport, `:scope>fingerprint[*|xmlns='${XEP.DTLS_SRTP}']`)) {\n            media.proto = sctp ? 'UDP/DTLS/SCTP' : 'UDP/TLS/RTP/SAVPF';\n        } else {\n            media.proto = 'UDP/TLS/RTP/SAVPF';\n        }\n        if (sctp) {\n            sdp += `m=application ${media.port} UDP/DTLS/SCTP webrtc-datachannel\\r\\n`;\n            sdp += `a=sctp-port:${getAttribute(sctp, 'number')}\\r\\n`;\n            sdp += 'a=max-message-size:262144\\r\\n';\n        } else {\n            media.fmt = findAll(desc, ':scope>payload-type').map(payloadType => getAttribute(payloadType, 'id'));\n            sdp += `${SDPUtil.buildMLine(media)}\\r\\n`;\n        }\n\n        sdp += 'c=IN IP4 0.0.0.0\\r\\n';\n        if (!sctp) {\n            sdp += 'a=rtcp:1 IN IP4 0.0.0.0\\r\\n';\n        }\n\n        if (transport) {\n            const ufrag = getAttribute(transport, 'ufrag');\n            const pwd = getAttribute(transport, 'pwd');\n\n            if (ufrag) {\n                sdp += `${SDPUtil.buildICEUfrag(ufrag)}\\r\\n`;\n            }\n            if (pwd) {\n                sdp += `${SDPUtil.buildICEPwd(pwd)}\\r\\n`;\n            }\n\n            // Use *|xmlns to match xmlns attributes across any namespace (CSS Selectors Level 3)\n            findAll(transport, `:scope>fingerprint[*|xmlns='${XEP.DTLS_SRTP}']`).forEach(fingerprint => {\n                sdp += `a=fingerprint:${getAttribute(fingerprint, 'hash')} ${getText(fingerprint)}\\r\\n`;\n\n                const setup = getAttribute(fingerprint, 'setup');\n\n                if (setup) {\n                    sdp += `a=setup:${setup}\\r\\n`;\n                }\n            });\n        }\n\n        if (transport) {\n            findAll(transport, ':scope>candidate').forEach(candidate => {\n                let protocol = getAttribute(candidate, 'protocol');\n\n                protocol = typeof protocol === 'string' ? protocol.toLowerCase() : '';\n\n                if ((this.removeTcpCandidates && (protocol === 'tcp' || protocol === 'ssltcp'))\n                    || (this.removeUdpCandidates && protocol === 'udp')) {\n                    return;\n                } else if (this.failICE) {\n                    candidate.setAttribute('ip', '1.1.1.1');\n                }\n\n                sdp += SDPUtil.candidateFromJingle(candidate);\n            });\n        }\n\n        switch (getAttribute(content, 'senders')) {\n        case 'initiator':\n            sdp += `a=${MediaDirection.SENDONLY}\\r\\n`;\n            break;\n        case 'responder':\n            sdp += `a=${MediaDirection.RECVONLY}\\r\\n`;\n            break;\n        case 'none':\n            sdp += `a=${MediaDirection.INACTIVE}\\r\\n`;\n            break;\n        case 'both':\n            sdp += `a=${MediaDirection.SENDRECV}\\r\\n`;\n            break;\n        }\n        sdp += `a=mid:${mid}\\r\\n`;\n\n        // <description><rtcp-mux/></description>\n        // see http://code.google.com/p/libjingle/issues/detail?id=309 -- no spec though\n        // and http://mail.jabber.org/pipermail/jingle/2011-December/001761.html\n        if (exists(desc, ':scope>rtcp-mux')) {\n            sdp += 'a=rtcp-mux\\r\\n';\n        }\n\n        if (desc) {\n            findAll(desc, ':scope>payload-type').forEach(payloadType => {\n                sdp += `${SDPUtil.buildRTPMap(payloadType)}\\r\\n`;\n                const parameters = findAll(payloadType, ':scope>parameter');\n\n                if (parameters.length) {\n                    sdp += `a=fmtp:${getAttribute(payloadType, 'id')} `;\n                    sdp += parameters\n                        .map(parameter => {\n                            const name = getAttribute(parameter, 'name');\n\n                            return (name ? `${name}=` : '') + getAttribute(parameter, 'value');\n                        })\n                        .join(';');\n                    sdp += '\\r\\n';\n                }\n\n                sdp += this.rtcpFbFromJingle(payloadType, getAttribute(payloadType, 'id'));\n            });\n\n            sdp += this.rtcpFbFromJingle(desc, '*');\n\n            // Use *|xmlns to match xmlns attributes across any namespace (CSS Selectors Level 3)\n            findAll(desc, `:scope>rtp-hdrext[*|xmlns='${XEP.RTP_HEADER_EXTENSIONS}']`).forEach(hdrExt => {\n                sdp += `a=extmap:${getAttribute(hdrExt, 'id')} ${getAttribute(hdrExt, 'uri')}\\r\\n`;\n            });\n\n            // Use *|xmlns to match xmlns attributes across any namespace (CSS Selectors Level 3)\n            if (exists(desc, `:scope>extmap-allow-mixed[*|xmlns='${XEP.RTP_HEADER_EXTENSIONS}']`)) {\n                sdp += 'a=extmap-allow-mixed\\r\\n';\n            }\n        }\n\n        if (desc) {\n\n            // Use *|xmlns to match xmlns attributes across any namespace (CSS Selectors Level 3)\n            findAll(desc, `:scope>ssrc-group[*|xmlns='${XEP.SOURCE_ATTRIBUTES}']`).forEach(ssrcGroup => {\n                const semantics = getAttribute(ssrcGroup, 'semantics');\n                const children = Array.from(ssrcGroup.children || []);\n                const ssrcs = children.filter(child => child.localName === 'source')\n                    .map(source => getAttribute(source, 'ssrc'));\n\n                if (ssrcs.length) {\n                    sdp += `a=ssrc-group:${semantics} ${ssrcs.join(' ')}\\r\\n`;\n                }\n            });\n        }\n\n        let userSources = '';\n        let nonUserSources = '';\n\n        if (desc) {\n            // Use *|xmlns to match xmlns attributes across any namespace (CSS Selectors Level 3)\n            findAll(desc, `:scope>source[*|xmlns='${XEP.SOURCE_ATTRIBUTES}']`).forEach(source => {\n                const ssrc = getAttribute(source, 'ssrc');\n                let isUserSource = true;\n                let sourceStr = '';\n\n                findAll(source, ':scope>parameter')\n                    .forEach(parameter => {\n                        const name = getAttribute(parameter, 'name');\n                        let value = getAttribute(parameter, 'value');\n\n                        value = SDPUtil.filterSpecialChars(value);\n                        sourceStr += `a=ssrc:${ssrc} ${name}`;\n\n                        if (name === 'msid') {\n                            value = this._adjustMsidSemantic(value, media.media, mid);\n                        }\n                        if (value?.length) {\n                            sourceStr += `:${value}`;\n                        }\n\n                        sourceStr += '\\r\\n';\n\n                        if (value?.includes('mixedmslabel')) {\n                            isUserSource = false;\n                        }\n                    });\n\n                if (isUserSource) {\n                    userSources += sourceStr;\n                } else {\n                    nonUserSources += sourceStr;\n                }\n            });\n        }\n\n        // Append sources in the correct order, the mixedmslable m-line which has the JVB's SSRC for RTCP termination\n        // is expected to be in the first m-line.\n        sdp += nonUserSources + userSources;\n\n        return sdp;\n    }\n\n    /**\n     * Coverts the RTCP attributes for the session from XMPP format to SDP.\n     * https://xmpp.org/extensions/xep-0293.html\n     *\n     * @param {*} elem - Jingle message element.\n     * @param {*} payloadtype - Payload type for the codec.\n     * @returns {string}\n     */\n    public rtcpFbFromJingle(elem: any, payloadtype: any): string {\n        let sdp = '';\n\n        // Use *|xmlns to match xmlns attributes across any namespace (CSS Selectors Level 3)\n        const feedbackElementTrrInt = findFirst(elem, `:scope>rtcp-fb-trr-int[*|xmlns='${XEP.RTP_FEEDBACK}']`);\n\n        if (feedbackElementTrrInt) {\n            sdp += 'a=rtcp-fb:* trr-int ';\n            sdp += getAttribute(feedbackElementTrrInt, 'value') || '0';\n            sdp += '\\r\\n';\n        }\n\n        // Use *|xmlns to match xmlns attributes across any namespace (CSS Selectors Level 3)\n        const feedbackElements = findAll(elem, `:scope>rtcp-fb[*|xmlns='${XEP.RTP_FEEDBACK}']`);\n\n        feedbackElements.forEach(fb => {\n            sdp += `a=rtcp-fb:${payloadtype} ${fb.getAttribute('type')}`;\n            if (fb.hasAttribute('subtype')) {\n                sdp += ` ${fb.getAttribute('subtype')}`;\n            }\n            sdp += '\\r\\n';\n        });\n\n        return sdp;\n    }\n\n    /**\n     * Converts the RTCP attributes for the session from SDP to XMPP format.\n     * https://xmpp.org/extensions/xep-0293.html\n     *\n     * @param {number} mediaIndex - The index of the media section in the SDP.\n     * @param {*} elem - The Jingle message element.\n     * @param {string} payloadtype - payload type for the codec.\n     */\n    public rtcpFbToJingle(mediaIndex: number, elem: any, payloadtype: string): void {\n        const lines = SDPUtil.findLines(this.media[mediaIndex], `a=rtcp-fb:${payloadtype}`);\n\n        lines.forEach((line: string) => {\n            const feedback = SDPUtil.parseRTCPFB(line);\n\n            if (feedback.type === 'trr-int') {\n                elem.c('rtcp-fb-trr-int', {\n                    value: feedback.params[0],\n                    xmlns: XEP.RTP_FEEDBACK\n                });\n                elem.up();\n            } else {\n                elem.c('rtcp-fb', {\n                    type: feedback.type,\n                    xmlns: XEP.RTP_FEEDBACK\n                });\n                if (feedback.params.length > 0) {\n                    elem.attrs({ 'subtype': feedback.params[0] });\n                }\n                elem.up();\n            }\n        });\n    }\n\n    /**\n     * Converts the current SDP to a Jingle message that can be sent over the wire to a signaling server.\n     *\n     * @param {*} elem - The Jingle message element.\n     * @param {*} thecreator - Sender role, whether it is an 'initiator' or 'responder'.\n     * @returns - The updated Jingle message element.\n     */\n    public toJingle(elem: any, thecreator: any): any {\n        SDPUtil.findLines(this.session, 'a=group:').forEach((line: string) => {\n            const parts = line.split(' ');\n            const semantics = parts.shift().substr(8);\n\n            elem.c('group', {\n                semantics,\n                xmlns: XEP.BUNDLE_MEDIA\n            });\n\n            // Bundle all the media types. Jicofo expects the 'application' media type to be signaled as 'data'.\n            let mediaTypes = [ MediaType.AUDIO, MediaType.VIDEO, 'data' ];\n\n            // For p2p connection, 'mid' will be used in the bundle group.\n            if (this.isP2P) {\n                mediaTypes = this.media.map(mediaItem => {\n                    const midLine = SDPUtil.findLine(mediaItem, 'a=mid:');\n\n                    return typeof midLine === 'string' ? SDPUtil.parseMID(midLine) : '';\n                });\n            }\n            mediaTypes.forEach(type => elem.c('content', { name: type }).up());\n            elem.up();\n        });\n\n        this.media.forEach((mediaItem, i) => {\n            const mline = SDPUtil.parseMLine(mediaItem.split('\\r\\n')[0]);\n            const mediaType = mline.media === MediaType.APPLICATION ? 'data' : mline.media;\n\n            let ssrc: string | false = false;\n            const assrcline = SDPUtil.findLine(mediaItem, 'a=ssrc:', '');\n            const isRecvOnly = SDPUtil.findLine(mediaItem, `a=${MediaDirection.RECVONLY}`, '');\n\n            if (assrcline && typeof assrcline === 'string') {\n                ssrc = assrcline.substring(7).split(' ')[0];\n            }\n\n            const contents = findAll(elem.tree(), `content[name='${mediaType}']`);\n\n            // Append source groups from the new m-lines to the existing media description. The SDP will have multiple\n            // m-lines for audio and video including the recv-only ones for remote sources but there needs to be only\n            // one media description for a given media type that should include all the sources, i.e., both the camera\n            // and screenshare sources should be added to the 'video' description.\n            for (const content of contents) {\n                if (!content.hasAttribute('creator')) {\n                    // eslint-disable-next-line no-continue\n                    continue;\n                }\n\n                if (ssrc && !(isRecvOnly && browser.isFirefox())) {\n                    const description = findFirst(content, 'description');\n                    const ssrcMap = SDPUtil.parseSSRC(mediaItem);\n\n                    for (const [ availableSsrc, ssrcParameters ] of ssrcMap) {\n                        const sourceName = SDPUtil.parseSourceNameLine(ssrcParameters);\n                        const videoType = SDPUtil.parseVideoTypeLine(ssrcParameters);\n                        const source = Strophe.xmlElement('source', {\n                            name: sourceName,\n                            ssrc: availableSsrc,\n                            videoType,\n                            xmlns: XEP.SOURCE_ATTRIBUTES\n                        });\n\n                        const msid = SDPUtil.parseMSIDAttribute(ssrcParameters);\n\n                        if (msid) {\n                            const param = Strophe.xmlElement('parameter', {\n                                name: 'msid',\n                                value: msid\n                            });\n\n                            source.append(param);\n                        }\n                        description.append(source);\n                    }\n\n                    const ssrcGroupLines = SDPUtil.findLines(mediaItem, 'a=ssrc-group:');\n\n                    ssrcGroupLines.forEach((line: string) => {\n                        const { semantics, ssrcs } = SDPUtil.parseSSRCGroupLine(line);\n\n                        if (ssrcs.length) {\n                            const group = Strophe.xmlElement('ssrc-group', {\n                                semantics,\n                                xmlns: XEP.SOURCE_ATTRIBUTES\n                            });\n\n                            for (const val of ssrcs) {\n                                const src = Strophe.xmlElement('source', {\n                                    ssrc: val\n                                });\n\n                                group.append(src);\n                            }\n                            description.append(group);\n                        }\n                    });\n                }\n\n                return;\n            }\n            const midLine = SDPUtil.findLine(mediaItem, 'a=mid:', '');\n            const mid = typeof midLine === 'string' ? SDPUtil.parseMID(midLine) : '';\n\n            elem.c('content', {\n                creator: thecreator,\n                name: this.isP2P ? mid : mediaType\n            });\n\n            if (mediaType === MediaType.VIDEO && typeof this.initialLastN === 'number') {\n                elem.c('initial-last-n', {\n                    value: this.initialLastN,\n                    xmlns: 'jitsi:colibri2'\n                }).up();\n            }\n\n            if ([ MediaType.AUDIO, MediaType.VIDEO ].includes(mediaType as MediaType)) {\n                elem.c('description', {\n                    media: mediaType,\n                    xmlns: XEP.RTP_MEDIA\n                });\n\n                mline.fmt.forEach((format: string) => {\n                    const rtpmap = SDPUtil.findLine(mediaItem, `a=rtpmap:${format}`, '');\n\n                    if (typeof rtpmap === 'string') {\n                        elem.c('payload-type', SDPUtil.parseRTPMap(rtpmap));\n\n                        const afmtpline = SDPUtil.findLine(mediaItem, `a=fmtp:${format}`, '');\n\n                        if (afmtpline && typeof afmtpline === 'string') {\n                            const fmtpParameters = SDPUtil.parseFmtp(afmtpline);\n\n                            fmtpParameters.forEach((param: any) => elem.c('parameter', param).up());\n                        }\n\n                        this.rtcpFbToJingle(i, elem, format);\n                        elem.up();\n                    }\n                });\n\n                if (ssrc && !(isRecvOnly && browser.isFirefox())) {\n                    const ssrcMap = SDPUtil.parseSSRC(mediaItem);\n\n                    for (const [ availableSsrc, ssrcParameters ] of ssrcMap) {\n                        const sourceName = SDPUtil.parseSourceNameLine(ssrcParameters);\n                        const videoType = SDPUtil.parseVideoTypeLine(ssrcParameters);\n\n                        elem.c('source', {\n                            name: sourceName,\n                            ssrc: availableSsrc,\n                            videoType,\n                            xmlns: XEP.SOURCE_ATTRIBUTES\n                        });\n\n                        const msid = SDPUtil.parseMSIDAttribute(ssrcParameters);\n\n                        if (msid) {\n                            elem.c('parameter').attrs({\n                                name: 'msid',\n                                value: msid\n                            });\n                            elem.up();\n                        }\n\n                        elem.up();\n                    }\n\n                    const ssrcGroupLines = SDPUtil.findLines(mediaItem, 'a=ssrc-group:');\n\n                    ssrcGroupLines.forEach((line: string) => {\n                        const { semantics, ssrcs } = SDPUtil.parseSSRCGroupLine(line);\n\n                        if (ssrcs.length) {\n                            elem.c('ssrc-group', {\n                                semantics,\n                                xmlns: XEP.SOURCE_ATTRIBUTES\n                            });\n                            ssrcs.forEach(s => elem.c('source', { ssrc: s }).up());\n                            elem.up();\n                        }\n                    });\n                }\n\n                const ridLines = SDPUtil.findLines(mediaItem, 'a=rid:');\n\n                if (ridLines.length && browser.usesRidsForSimulcast()) {\n                    // Map a line which looks like \"a=rid:2 send\" to just the rid (\"2\").\n                    const rids = ridLines.map(ridLine => ridLine.split(':')[1].split(' ')[0]);\n\n                    rids.forEach(rid => {\n                        elem.c('source', {\n                            rid,\n                            xmlns: XEP.SOURCE_ATTRIBUTES\n                        });\n                        elem.up();\n                    });\n\n                    const unifiedSimulcast = SDPUtil.findLine(mediaItem, 'a=simulcast:');\n\n                    if (unifiedSimulcast) {\n                        elem.c('rid-group', {\n                            semantics: SSRC_GROUP_SEMANTICS.SIM,\n                            xmlns: XEP.SOURCE_ATTRIBUTES\n                        });\n                        rids.forEach(rid => elem.c('source', { rid }).up());\n                        elem.up();\n                    }\n                }\n\n                if (SDPUtil.findLine(mediaItem, 'a=rtcp-mux')) {\n                    elem.c('rtcp-mux').up();\n                }\n\n                this.rtcpFbToJingle(i, elem, '*');\n\n                const extmapLines = SDPUtil.findLines(mediaItem, 'a=extmap:', this.session);\n\n                extmapLines.forEach(extmapLine => {\n                    const extmap = SDPUtil.parseExtmap(extmapLine);\n\n                    elem.c('rtp-hdrext', {\n                        id: extmap.value,\n                        uri: extmap.uri,\n                        xmlns: XEP.RTP_HEADER_EXTENSIONS\n                    });\n\n                    if (extmap.hasOwnProperty('direction')) {\n                        switch (extmap.direction) {\n                        case MediaDirection.SENDONLY:\n                            elem.attrs({ senders: 'responder' });\n                            break;\n                        case MediaDirection.RECVONLY:\n                            elem.attrs({ senders: 'initiator' });\n                            break;\n                        case MediaDirection.SENDRECV:\n                            elem.attrs({ senders: 'both' });\n                            break;\n                        case MediaDirection.INACTIVE:\n                            elem.attrs({ senders: 'none' });\n                            break;\n                        }\n                    }\n\n                    elem.up();\n                });\n\n                if (SDPUtil.findLine(mediaItem, 'a=extmap-allow-mixed', this.session)) {\n                    elem.c('extmap-allow-mixed', {\n                        xmlns: XEP.RTP_HEADER_EXTENSIONS\n                    });\n                    elem.up();\n                }\n                elem.up(); // end of description\n            }\n\n            // Map ice-ufrag/pwd, dtls fingerprint, candidates.\n            this.transportToJingle(i, elem);\n\n            // Set senders attribute based on media direction\n            if (SDPUtil.findLine(mediaItem, `a=${MediaDirection.SENDRECV}`)) {\n                elem.attrs({ senders: 'both' });\n            } else if (SDPUtil.findLine(mediaItem, `a=${MediaDirection.SENDONLY}`)) {\n                elem.attrs({ senders: 'initiator' });\n            } else if (SDPUtil.findLine(mediaItem, `a=${MediaDirection.RECVONLY}`)) {\n                elem.attrs({ senders: 'responder' });\n            } else if (SDPUtil.findLine(mediaItem, `a=${MediaDirection.INACTIVE}`)) {\n                elem.attrs({ senders: 'none' });\n            }\n\n            // Reject an m-line only when port is 0 and a=bundle-only is not present in the section.\n            // The port is automatically set to 0 when bundle-only is used.\n            if (mline.port === '0' && !SDPUtil.findLine(mediaItem, 'a=bundle-only', this.session)) {\n                elem.attrs({ senders: 'rejected' });\n            }\n            elem.up(); // end of content\n        });\n        elem.up();\n\n        return elem;\n    }\n\n    /**\n     * Converts the session transport information from SDP to XMPP format.\n     *\n     * @param {*} mediaIndex The index for the m-line in the SDP.\n     * @param {*} elem The transport element.\n     */\n    public transportToJingle(mediaIndex: number, elem: any): void {\n        elem.c('transport');\n\n        const sctpport = SDPUtil.findLine(this.media[mediaIndex], 'a=sctp-port:', this.session);\n        const sctpmap = SDPUtil.findLine(this.media[mediaIndex], 'a=sctpmap:', this.session);\n\n        if (sctpport && typeof sctpport === 'string') {\n            const sctpAttrs = SDPUtil.parseSCTPPort(sctpport);\n\n            elem.c('sctpmap', {\n                number: sctpAttrs, // SCTP port\n                protocol: 'webrtc-datachannel', // protocol\n                xmlns: XEP.SCTP_DATA_CHANNEL\n            });\n\n            // The parser currently requires streams to be present.\n            elem.attrs({ streams: 0 });\n            elem.up();\n        } else if (sctpmap) {\n            const sctpAttrs = SDPUtil.parseSCTPMap(sctpmap);\n\n            elem.c('sctpmap', {\n                number: sctpAttrs[0], // SCTP port\n                protocol: sctpAttrs[1], // protocol\n                xmlns: XEP.SCTP_DATA_CHANNEL\n            });\n\n            // Optional stream count attribute.\n            elem.attrs({ streams: sctpAttrs.length > 2 ? sctpAttrs[2] : 0 });\n            elem.up();\n        }\n\n        const fingerprints = SDPUtil.findLines(this.media[mediaIndex], 'a=fingerprint:', this.session);\n        const hasCryptex = SDPUtil.findLine(this.media[mediaIndex], 'a=cryptex', this.session);\n\n        fingerprints.forEach(line => {\n            const fingerprint = SDPUtil.parseFingerprint(line);\n\n            fingerprint.xmlns = XEP.DTLS_SRTP;\n\n            elem.c('fingerprint').t(fingerprint.fingerprint);\n            delete fingerprint.fingerprint;\n\n            const setupLine = SDPUtil.findLine(this.media[mediaIndex], 'a=setup:', this.session);\n\n            if (setupLine && typeof setupLine === 'string') {\n                fingerprint.setup = setupLine.substr(8);\n            }\n\n            // Add cryptex attribute if a=cryptex is present in session or media section\n            if (hasCryptex) {\n                fingerprint.cryptex = 'true';\n            }\n\n            elem.attrs(fingerprint);\n            elem.up(); // end of fingerprint\n        });\n\n        const iceParameters = SDPUtil.iceparams(this.media[mediaIndex], this.session);\n\n        if (iceParameters) {\n            iceParameters.xmlns = XEP.ICE_UDP_TRANSPORT;\n            elem.attrs(iceParameters);\n\n            const candidateLines = SDPUtil.findLines(this.media[mediaIndex], 'a=candidate:', this.session);\n\n            candidateLines.forEach(line => { // add any a=candidate lines\n                const candidate = SDPUtil.candidateToJingle(line);\n\n                if (this.failICE) {\n                    candidate.ip = '1.1.1.1';\n                }\n\n                const protocol = candidate && typeof candidate.protocol === 'string'\n                    ? candidate.protocol.toLowerCase() : '';\n\n                if ((this.removeTcpCandidates && (protocol === 'tcp' || protocol === 'ssltcp'))\n                    || (this.removeUdpCandidates && protocol === 'udp')) {\n                    return;\n                }\n                elem.c('candidate', candidate).up();\n            });\n        }\n        elem.up(); // end of transport\n    }\n}\n","import * as transform from 'sdp-transform';\n\nimport { MediaDirection } from '../../service/RTC/MediaDirection';\nimport { MediaType } from '../../service/RTC/MediaType';\nimport { SIM_LAYERS, SSRC_GROUP_SEMANTICS } from '../../service/RTC/StandardVideoQualitySettings';\n\n/**\n * This class handles SDP munging for enabling simulcast for local video streams in Unified plan. A set of random SSRCs\n * are generated for the higher layer streams and they are cached for a given mid. The cached SSRCs are then reused on\n * the subsequent iterations while munging the local description. This class also handles imploding of the simulcast\n * SSRCs for remote endpoints into the primary FID group in remote description since Jicofo signals all SSRCs relevant\n * to a given endpoint.\n */\nexport default class SdpSimulcast {\n    private _numOfLayers: number;\n    private _ssrcCache: Map<string, Array<number>>;\n\n    /**\n     * Creates a new instance.\n     *\n     * @param options\n     */\n    constructor() {\n        this._ssrcCache = new Map();\n        this._numOfLayers = SIM_LAYERS.length;\n    }\n\n    /**\n     * Updates the given media description using the SSRCs that were cached for the mid associated\n     * with the media description and returns the modified media description.\n     *\n     * @param mLine\n     * @returns\n     */\n    _fillSsrcsFromCache(mLine: transform.MediaDescription): any {\n        const mid = mLine.mid;\n        const cachedSsrcs = this._ssrcCache.get(mid);\n        const newSsrcs = this._parseSimLayers(mLine);\n        const newMsid = this._getSsrcAttribute(mLine, newSsrcs[0], 'msid');\n        const newCname = this._getSsrcAttribute(mLine, newSsrcs[0], 'cname');\n\n        mLine.ssrcs = [];\n        mLine.ssrcGroups = [];\n\n        for (const ssrc of cachedSsrcs) {\n            mLine.ssrcs.push({\n                attribute: 'msid',\n                id: ssrc,\n                value: newMsid\n            });\n            mLine.ssrcs.push({\n                attribute: 'cname',\n                id: ssrc,\n                value: newCname\n            });\n        }\n\n        mLine.ssrcGroups.push({\n            semantics: SSRC_GROUP_SEMANTICS.SIM,\n            ssrcs: cachedSsrcs.join(' ')\n        });\n\n        return mLine;\n    }\n\n    /**\n     * Generates a new set of SSRCs for the higher simulcast layers/streams and adds the attributes and SIM group to\n     * the given media description and returns the modified media description.\n     *\n     * @param mLine\n     * @param primarySsrc\n     * @returns\n     */\n    _generateNewSsrcsForSimulcast(mLine: transform.MediaDescription, primarySsrc: number): any {\n        const cname = this._getSsrcAttribute(mLine, primarySsrc, 'cname');\n        let msid = this._getSsrcAttribute(mLine, primarySsrc, 'msid');\n\n        // In Unified-plan mode, the a=ssrc lines with the msid attribute are not present (only cname attributes are\n        // present) in the answers that Chrome and Safari generate for an offer received from Jicofo. Generate these\n        // a=ssrc lines using the msid values from the a=msid line.\n        if (!msid) {\n            msid = mLine.msid;\n            const primarySsrcs = mLine.ssrcs;\n\n            primarySsrcs.forEach(ssrc => {\n                mLine.ssrcs.push({\n                    attribute: 'msid',\n                    id: ssrc.id,\n                    value: msid\n                });\n            });\n        }\n\n        // Generate SIM layers.\n        const simSsrcs = [];\n\n        for (let i = 0; i < this._numOfLayers - 1; ++i) {\n            const simSsrc = this._generateSsrc();\n\n            mLine.ssrcs.push({\n                attribute: 'cname',\n                id: simSsrc,\n                value: cname\n            });\n            mLine.ssrcs.push({\n                attribute: 'msid',\n                id: simSsrc,\n                value: msid\n            });\n\n            simSsrcs.push(simSsrc);\n        }\n\n        mLine.ssrcGroups = mLine.ssrcGroups || [];\n        mLine.ssrcGroups.push({\n            semantics: SSRC_GROUP_SEMANTICS.SIM,\n            ssrcs: `${primarySsrc} ${simSsrcs.join(' ')}`\n        });\n\n        return mLine;\n    }\n\n    /**\n     * Returns a random number to be used for the SSRC.\n     *\n     * @returns\n     */\n    _generateSsrc(): number {\n        const max = 0xffffffff;\n\n        return Math.floor(Math.random() * max);\n    }\n\n    /**\n     * Returns the requested attribute value for a SSRC from a given media description.\n     *\n     * @param mLine\n     * @param ssrc\n     * @param attributeName\n     * @returns\n     */\n    _getSsrcAttribute(mLine: transform.MediaDescription, ssrc: number, attributeName: string): Optional<string> {\n        return mLine.ssrcs?.find(\n            ssrcInfo => Number(ssrcInfo.id) === ssrc\n            && ssrcInfo.attribute === attributeName)?.value;\n    }\n\n    /**\n     * Returns an array of all the primary SSRCs in the SIM group for a given media description.\n     *\n     * @param mLine\n     * @returns\n     */\n    _parseSimLayers(mLine: transform.MediaDescription): Nullable<Array<number>> {\n        const simGroup = mLine.ssrcGroups?.find(group => group.semantics === SSRC_GROUP_SEMANTICS.SIM);\n\n        if (simGroup) {\n            return simGroup.ssrcs.split(' ').map(ssrc => Number(ssrc));\n        }\n\n        if (mLine.ssrcs?.length) {\n            return [ Number(mLine.ssrcs[0].id) ];\n        }\n\n        return null;\n    }\n\n    /**\n     * Munges the given media description to enable simulcast for the video media sections that are in either have\n     * SENDRECV or SENDONLY as the media direction thereby ignoring all the RECVONLY transceivers created for remote\n     * endpoints.\n     * NOTE: This needs to be called only when simulcast is enabled.\n     *\n     * @param description\n     * @returns\n     */\n    mungeLocalDescription(description: RTCSessionDescription): RTCSessionDescription {\n        if (!description?.sdp) {\n            return description;\n        }\n        const session = transform.parse(description.sdp);\n\n        for (let media of session.media) {\n            // Ignore recvonly and inactive transceivers created for remote sources.\n            if (media.direction === MediaDirection.RECVONLY || media.direction === MediaDirection.INACTIVE) {\n                continue;\n            }\n\n            // Ignore audio m-lines.\n            if (media.type !== MediaType.VIDEO) {\n                continue;\n            }\n            const mid = media.mid;\n            const numSsrcs = new Set(media.ssrcs?.map(ssrcInfo => ssrcInfo.id));\n            const numGroups = media.ssrcGroups?.length ?? 0;\n            let primarySsrc: number;\n\n            // Do not munge if the description has no ssrcs or if simulcast is already enabled.\n            if (numSsrcs.size === 0 || numSsrcs.size > 2 || (numSsrcs.size === 2 && numGroups === 0)) {\n                continue;\n            }\n            if (numSsrcs.size === 1) {\n                primarySsrc = Number(media.ssrcs[0]?.id);\n            } else {\n                const fidGroup = media.ssrcGroups.find(group => group.semantics === SSRC_GROUP_SEMANTICS.FID);\n\n                if (fidGroup) {\n                    primarySsrc = Number(fidGroup.ssrcs.split(' ')[0]);\n                }\n            }\n\n            if (this._ssrcCache.has(mid)) {\n                media = this._fillSsrcsFromCache(media);\n            } else {\n                media = this._generateNewSsrcsForSimulcast(media, primarySsrc);\n                const simulcastSsrcs = this._parseSimLayers(media);\n\n                // Update the SSRCs in the cache so that they can re-used for the same mid again.\n                this._ssrcCache.set(mid, simulcastSsrcs);\n            }\n        }\n\n        return new RTCSessionDescription({\n            sdp: transform.write(session),\n            type: description.type\n        });\n    }\n}\n","import { getLogger } from '@jitsi/logger';\n\nimport JitsiConference from '../../JitsiConference';\nimport { JitsiConferenceEvents } from '../../JitsiConferenceEvents';\nimport { JitsiTrackEvents } from '../../JitsiTrackEvents';\nimport { RTCEvents } from '../../service/RTC/RTCEvents';\nimport { VideoType } from '../../service/RTC/VideoType';\nimport { createTrackStreamingStatusEvent } from '../../service/statistics/AnalyticsEvents';\nimport JitsiRemoteTrack from '../RTC/JitsiRemoteTrack';\nimport RTC from '../RTC/RTC';\nimport RTCStats from '../RTCStats/RTCStats';\nimport { RTCStatsEvents } from '../RTCStats/RTCStatsEvents';\nimport browser from '../browser';\nimport Statistics from '../statistics/statistics';\n\n/** Track streaming statuses. */\nexport enum TrackStreamingStatus {\n\n    /**\n     * Status indicating that streaming is currently active.\n     */\n    ACTIVE = 'active',\n\n    /**\n     * Status indicating that streaming is currently inactive.\n     * Inactive means the streaming was stopped on purpose from the bridge, like exiting forwarded sources or\n     * adaptivity decided to drop video because of not enough bandwidth.\n     */\n    INACTIVE = 'inactive',\n\n    /**\n     * Status indicating that streaming is currently interrupted.\n     */\n    INTERRUPTED = 'interrupted',\n\n    /**\n     * Status indicating that streaming is currently restoring.\n     */\n    RESTORING = 'restoring',\n}\n\ntype StreamingStatusMap = {\n    p2p?: boolean;\n    startedMs?: number;\n    streamingStatus?: string;\n    value?: number;\n    videoType?: VideoType;\n};\n\nconst logger = getLogger('connectivity:TrackStreamingStatus');\n\n/**\n * Default value of 500 milliseconds for {@link TrackStreamingStatusImpl.outOfForwardedSourcesTimeout}.\n */\nconst DEFAULT_NOT_IN_FORWARDED_SOURCES_TIMEOUT = 500;\n\n/**\n * Default value of 2500 milliseconds for {@link TrackStreamingStatusImpl.p2pRtcMuteTimeout}.\n */\nconst DEFAULT_P2P_RTC_MUTE_TIMEOUT = 2500;\n\n/**\n * Default value of 10000 milliseconds for {@link TrackStreamingStatusImpl.rtcMuteTimeout}.\n */\nconst DEFAULT_RTC_MUTE_TIMEOUT = 10000;\n\n/**\n * The time to wait a track to be restored. Track which was out of forwarded sources should be inactive and when\n * entering forwarded sources it becomes restoring and when data is received from bridge it will become active, but if\n * no data is received for some time we set status of that track streaming to interrupted.\n */\nconst DEFAULT_RESTORING_TIMEOUT = 10000;\n\n/**\n * Class is responsible for emitting JitsiTrackEvents.TRACK_STREAMING_STATUS_CHANGED events.\n */\nexport class TrackStreamingStatusImpl {\n    rtc: RTC;\n    conference: JitsiConference;\n    track: JitsiRemoteTrack;\n\n    /**  This holds the timeout callback ID scheduled using window.setTimeout. */\n    trackTimer: Nullable<number>;\n\n    /**\n     * If video track frozen detection through RTC mute event is supported, we wait some time until video track is\n     * considered frozen. But because when the track falls out of forwarded sources it is expected for the video to\n     * freeze this timeout must be significantly reduced in \"out of forwarded sources\" case.\n     *\n     * Basically this value is used instead of {@link rtcMuteTimeout} when track is not in forwarded sources.\n     */\n    outOfForwardedSourcesTimeout: number;\n\n    /**\n     * How long we are going to wait for the corresponding signaling mute event after the RTC video track muted\n     * event is fired on the Media stream, before the connection interrupted is fired. The default value is\n     * {@link DEFAULT_P2P_RTC_MUTE_TIMEOUT}.\n     */\n    p2pRtcMuteTimeout: number;\n\n    /**\n     * How long we're going to wait after the RTC video track muted event for the corresponding signalling mute\n     * event, before the connection interrupted is fired. The default value is {@link DEFAULT_RTC_MUTE_TIMEOUT}.\n     *\n     * @returns amount of time in milliseconds\n     */\n    rtcMuteTimeout: number;\n\n    /**\n     * This holds a timestamp indicating  when remote video track was RTC muted. The purpose of storing the\n     * timestamp is to avoid the transition to disconnected status in case of legitimate video mute operation where\n     * the signalling video muted event can arrive shortly after RTC muted event.\n     *\n     * The timestamp is measured in milliseconds obtained with <tt>Date.now()</tt>.\n     *\n     * FIXME merge this logic with NO_DATA_FROM_SOURCE event implemented in JitsiLocalTrack by extending the event\n     * to the remote track and allowing to set different timeout for local and remote tracks.\n     */\n    rtcMutedTimestamp: Nullable<number>;\n\n    /** This holds the restoring timeout callback ID scheduled using window.setTimeout. */\n    restoringTimer: Nullable<ReturnType<typeof setTimeout>>;\n\n    /**\n     * This holds the current streaming status (along with all the internal events that happen while in that\n     * state).\n     *\n     * The goal is to send this information to the analytics backend for post-mortem analysis.\n     */\n    streamingStatusMap: StreamingStatusMap;\n\n    _onP2PStatus: () => void;\n    _onUserLeft: () => void;\n    _onTrackRtcMuted: () => void;\n    _onTrackRtcUnmuted: () => void;\n    _onSignallingMuteChanged: () => void;\n    _onTrackVideoTypeChanged: () => void;\n    _onLastNValueChanged: () => void;\n    _onForwardedSourcesChanged: () => void;\n    _onConnectionStats: (tpc: any, data: any) => void;\n\n    /**\n     * The framesDecoded value from the most recent CONNECTION_STATS event for this track's SSRC.\n     * Used by the stats-based freeze detection path.\n     */\n    _lastFramesDecoded: Nullable<number>;\n\n    /**\n     * Timestamp (ms) of the last time framesDecoded was observed to have increased.\n     * Used to measure how long the track has been frozen.\n     */\n    _lastFramesDecodedAt: Nullable<number>;\n\n    /**\n     * True when the stats-based logic has concluded the video is currently frozen.\n     * Cleared when framesDecoded resumes advancing.\n     */\n    _statsTrackFrozen: boolean;\n\n    /* eslint-disable max-params */\n    /**\n     * Calculates the new {@link TrackStreamingStatus} based on the values given for some specific remote track. It is\n     * assumed that the conference is currently in the JVB mode (in contrary to the P2P mode)\n     * @param isInForwardedSources - indicates whether the track is in the forwarded sources set. When set to\n     * false it means that JVB is not sending any video for the track.\n     * @param isRestoringTimedout - if true it means that the track has been outside of forwarded sources too\n     * long to be considered {@link TrackStreamingStatus.RESTORING}.\n     * @param isVideoMuted - true if the track is video muted and we should not expect to receive any video.\n     * @param isVideoTrackFrozen - if the current browser support video frozen detection then it will be set to\n     * true when the video track is frozen. If the current browser does not support frozen detection the it's always\n     * false.\n     * @return {TrackStreamingStatus} the new streaming status for the track for whom the values above were provided.\n     * @private\n     */\n    static _getNewStateForJvbMode(\n            isInForwardedSources: boolean,\n            isRestoringTimedout: boolean,\n            isVideoMuted: boolean,\n            isVideoTrackFrozen: boolean): TrackStreamingStatus {\n\n        // We are currently not checking the endpoint connection status received from the JVB.\n        if (isVideoMuted) {\n            // If the connection is active according to JVB and the track is video muted there is no way for the\n            // connection to be inactive, because the detection logic below only makes sense for video.\n            return TrackStreamingStatus.ACTIVE;\n        }\n\n        // Logic when isVideoTrackFrozen is supported (either via RTC mute events or stats-based detection)\n        if (browser.supportsVideoMuteOnConnInterrupted() || isVideoTrackFrozen) {\n            if (!isVideoTrackFrozen) {\n                // If the video is playing we're good\n                return TrackStreamingStatus.ACTIVE;\n            } else if (isInForwardedSources) {\n                return isRestoringTimedout ? TrackStreamingStatus.INTERRUPTED : TrackStreamingStatus.RESTORING;\n            }\n\n            return TrackStreamingStatus.INACTIVE;\n        }\n\n        // Because this browser is incapable of detecting frozen video we must rely on the forwarded sources value\n        return isInForwardedSources ? TrackStreamingStatus.ACTIVE : TrackStreamingStatus.INACTIVE;\n    }\n\n    /* eslint-enable max-params */\n\n    /**\n     * In P2P mode we don't care about any values coming from the JVB and the streaming status can be only active or\n     * interrupted.\n     * @param isVideoMuted - true if video muted\n     * @param isVideoTrackFrozen - true if the video track for the remote track is currently frozen. If the\n     * current browser does not support video frozen detection then it's always false.\n     * @return {TrackStreamingStatus}\n     * @private\n     */\n    static _getNewStateForP2PMode(isVideoMuted: boolean, isVideoTrackFrozen: boolean): TrackStreamingStatus {\n        if (!browser.supportsVideoMuteOnConnInterrupted() && !isVideoTrackFrozen) {\n            // There's no way to detect problems in P2P when there's no video track frozen detection...\n            return TrackStreamingStatus.ACTIVE;\n        }\n\n        return isVideoMuted || !isVideoTrackFrozen\n            ? TrackStreamingStatus.ACTIVE : TrackStreamingStatus.INTERRUPTED;\n    }\n\n    /**\n     * Creates new instance of <tt>TrackStreamingStatus</tt>.\n     *\n     * @constructor\n     * @param rtc - the RTC service instance\n     * @param conference - parent conference instance // TODO: Needs JitsiConference Type\n     * @param {Object} options\n     * @param {number} [options.p2pRtcMuteTimeout=2500] custom value for\n     * {@link TrackStreamingStatusImpl.p2pRtcMuteTimeout}.\n     * @param {number} [options.rtcMuteTimeout=2000] custom value for\n     * {@link TrackStreamingStatusImpl.rtcMuteTimeout}.\n     * @param {number} [options.outOfForwardedSourcesTimeout=500] custom value for\n     * {@link TrackStreamingStatusImpl.outOfForwardedSourcesTimeout}.\n     */\n    constructor(rtc: RTC, conference: JitsiConference, track: JitsiRemoteTrack, options: {\n        outOfForwardedSourcesTimeout: number;\n        p2pRtcMuteTimeout: number;\n        rtcMuteTimeout: number;\n    }) {\n        this.rtc = rtc;\n        this.conference = conference;\n        this.track = track;\n\n        this.restoringTimer = null;\n        this.rtcMutedTimestamp = null;\n        this.streamingStatusMap = {};\n        this.trackTimer = null;\n        this._lastFramesDecoded = null;\n        this._lastFramesDecodedAt = null;\n        this._statsTrackFrozen = false;\n\n        this.outOfForwardedSourcesTimeout = typeof options.outOfForwardedSourcesTimeout === 'number'\n            ? options.outOfForwardedSourcesTimeout : DEFAULT_NOT_IN_FORWARDED_SOURCES_TIMEOUT;\n\n        this.p2pRtcMuteTimeout = typeof options.p2pRtcMuteTimeout === 'number'\n            ? options.p2pRtcMuteTimeout : DEFAULT_P2P_RTC_MUTE_TIMEOUT;\n\n        this.rtcMuteTimeout = typeof options.rtcMuteTimeout === 'number'\n            ? options.rtcMuteTimeout : DEFAULT_RTC_MUTE_TIMEOUT;\n        logger.info(`RtcMuteTimeout set to: ${this.rtcMuteTimeout}`);\n    }\n\n    /**\n     * Gets the video frozen timeout for given source name.\n     * @return how long are we going to wait since RTC video muted even, before a video track is considered\n     * frozen.\n     * @private\n     */\n    _getVideoFrozenTimeout(): number {\n        const sourceName = this.track.getSourceName();\n\n        return this.rtc.isInForwardedSources(sourceName)\n            ? this.rtcMuteTimeout\n            : this.conference.isP2PActive() ? this.p2pRtcMuteTimeout : this.outOfForwardedSourcesTimeout;\n    }\n\n    /**\n     * Initializes <tt>TrackStreamingStatus</tt> and bind required event listeners.\n     */\n    init(): void {\n        // Handles P2P status changes\n        this._onP2PStatus = this.figureOutStreamingStatus.bind(this);\n        this.conference.on(JitsiConferenceEvents.P2P_STATUS, this._onP2PStatus);\n\n        // Used to send analytics events for the participant that left the call.\n        this._onUserLeft = this.onUserLeft.bind(this);\n        this.conference.on(JitsiConferenceEvents.USER_LEFT, this._onUserLeft);\n\n        // On some browsers MediaStreamTrack trigger \"onmute\"/\"onunmute\" events for video type tracks when they stop\n        // receiving data which is often a sign that remote user is having connectivity issues.\n        if (browser.supportsVideoMuteOnConnInterrupted()) {\n\n            this._onTrackRtcMuted = this.onTrackRtcMuted.bind(this);\n            this.rtc.addListener(RTCEvents.REMOTE_TRACK_MUTE, this._onTrackRtcMuted);\n\n            this._onTrackRtcUnmuted = this.onTrackRtcUnmuted.bind(this);\n            this.rtc.addListener(RTCEvents.REMOTE_TRACK_UNMUTE, this._onTrackRtcUnmuted);\n\n            // Listened which will be bound to JitsiRemoteTrack to listen for signalling mute/unmute events.\n            this._onSignallingMuteChanged = this.onSignallingMuteChanged.bind(this);\n            this.track.on(JitsiTrackEvents.TRACK_MUTE_CHANGED, this._onSignallingMuteChanged);\n\n            // Used to send an analytics event when the video type changes.\n            this._onTrackVideoTypeChanged = this.onTrackVideoTypeChanged.bind(this);\n            this.track.on(JitsiTrackEvents.TRACK_VIDEOTYPE_CHANGED, this._onTrackVideoTypeChanged);\n        }\n\n        this._onForwardedSourcesChanged = this.onForwardedSourcesChanged.bind(this);\n        this.conference.on(JitsiConferenceEvents.FORWARDED_SOURCES_CHANGED, this._onForwardedSourcesChanged);\n\n        this._onLastNValueChanged = this.figureOutStreamingStatus.bind(this);\n        this.rtc.on(RTCEvents.LASTN_VALUE_CHANGED, this._onLastNValueChanged);\n\n        // On browsers where mute/unmute events are unreliable (Chrome >= M144, Firefox, Safari), use\n        // per-SSRC framesDecoded from the existing RTPStatsCollector polling cycle to detect frozen video.\n        if (!browser.supportsVideoMuteOnConnInterrupted() && this.track.isVideoTrack()) {\n            this._onConnectionStats = (_tpc: any, data: any) => this._handleFramesDecodedUpdate(data);\n            this.conference.statistics.addConnectionStatsListener(this._onConnectionStats);\n        }\n    }\n\n    /**\n     * Removes all event listeners and disposes of all resources held by this instance.\n     */\n    dispose(): void {\n        if (browser.supportsVideoMuteOnConnInterrupted()) {\n            this.rtc.removeListener(RTCEvents.REMOTE_TRACK_MUTE, this._onTrackRtcMuted);\n            this.rtc.removeListener(RTCEvents.REMOTE_TRACK_UNMUTE, this._onTrackRtcUnmuted);\n\n            this.track.off(JitsiTrackEvents.TRACK_MUTE_CHANGED, this._onSignallingMuteChanged);\n            this.track.off(JitsiTrackEvents.TRACK_VIDEOTYPE_CHANGED, this._onTrackVideoTypeChanged);\n        } else if (this.track.isVideoTrack()) {\n            this.conference.statistics.removeConnectionStatsListener(this._onConnectionStats);\n            this._statsTrackFrozen = false;\n        }\n\n        this.conference.off(JitsiConferenceEvents.FORWARDED_SOURCES_CHANGED, this._onForwardedSourcesChanged);\n        this.conference.off(JitsiConferenceEvents.P2P_STATUS, this._onP2PStatus);\n        this.conference.off(JitsiConferenceEvents.USER_LEFT, this._onUserLeft);\n        this.rtc.removeListener(RTCEvents.LASTN_VALUE_CHANGED, this._onLastNValueChanged);\n\n        this.clearTimeout();\n        this.clearRtcMutedTimestamp();\n        this.maybeSendTrackStreamingStatusEvent(Date.now());\n        this.figureOutStreamingStatus();\n    }\n\n    /**\n     * Changes streaming status.\n     * @param newStatus\n     */\n    _changeStreamingStatus(newStatus: TrackStreamingStatus): void {\n        if (this.track.getTrackStreamingStatus() !== newStatus) {\n\n            const sourceName = this.track.getSourceName();\n\n            this.track._setTrackStreamingStatus(newStatus);\n\n            logger.debug(`Emit track streaming status(${Date.now()}) ${sourceName}: ${newStatus}`);\n\n            // It's common for the event listeners to access the JitsiRemoteTrack. Thus pass it as a parameter here.\n            this.track.emit(JitsiTrackEvents.TRACK_STREAMING_STATUS_CHANGED, this.track, newStatus);\n            if (newStatus === TrackStreamingStatus.INACTIVE) {\n                RTCStats.sendStatsEntry(RTCStatsEvents.REMOTE_SOURCE_SUSPENDED_EVENT);\n            } else if (newStatus === TrackStreamingStatus.INTERRUPTED) {\n                RTCStats.sendStatsEntry(RTCStatsEvents.REMOTE_SOURCE_INTERRUPTED_EVENT);\n            }\n        }\n    }\n\n    /**\n     * Reset the postponed \"streaming interrupted\" event which was previously scheduled as a timeout on RTC 'onmute'\n     * event.\n     */\n    clearTimeout(): void {\n        if (this.trackTimer) {\n            window.clearTimeout(this.trackTimer);\n            this.trackTimer = null;\n        }\n    }\n\n    /**\n     * Clears the timestamp of the RTC muted event for remote video track.\n     */\n    clearRtcMutedTimestamp(): void {\n        this.rtcMutedTimestamp = null;\n    }\n\n    /**\n     * Checks if track is considered frozen.\n     * @return <tt>true</tt> if the video has frozen or <tt>false</tt> when it's either not considered frozen\n     * (yet) or if freeze detection is not supported by the current browser.\n     *\n     * FIXME merge this logic with NO_DATA_FROM_SOURCE event implemented in JitsiLocalTrack by extending the event to\n     *       the remote track and allowing to set different timeout for local and remote tracks.\n     */\n    isVideoTrackFrozen(): boolean {\n        // Stats-based detection path: covers browsers where mute/unmute events are unreliable\n        // (Chrome >= M144, Firefox, Safari). Set/cleared by _handleFramesDecodedUpdate().\n        if (this._statsTrackFrozen) {\n            return true;\n        }\n\n        if (!browser.supportsVideoMuteOnConnInterrupted()) {\n            return false;\n        }\n\n        const isVideoRTCMuted = this.track.isWebRTCTrackMuted();\n        const rtcMutedTimestamp = this.rtcMutedTimestamp;\n        const timeout = this._getVideoFrozenTimeout();\n\n        return isVideoRTCMuted && typeof rtcMutedTimestamp === 'number' && (Date.now() - rtcMutedTimestamp) >= timeout;\n    }\n\n    /**\n     * Handles per-SSRC framesDecoded data from the CONNECTION_STATS event emitted by RTPStatsCollector.\n     * Used as a freeze-detection fallback on browsers where MediaStreamTrack mute/unmute events are\n     * unreliable (Chrome >= M144, Firefox, Safari).\n     *\n     * Detection logic: record the timestamp of the last framesDecoded increment. If the counter stops\n     * advancing for longer than the configured frozen timeout, declare the track frozen. Clear the frozen\n     * state as soon as frames start advancing again.\n     *\n     * @param data - The CONNECTION_STATS event payload.\n     */\n    _handleFramesDecodedUpdate(data: any): void {\n        if (this.track.isP2P !== this.conference.isP2PActive()) {\n            this._lastFramesDecoded = null;\n            this._lastFramesDecodedAt = null;\n\n            if (this._statsTrackFrozen) {\n                this._statsTrackFrozen = false;\n                this.figureOutStreamingStatus();\n            }\n\n            return;\n        }\n\n        if (this.track.isMuted() || data.framesDecoded == null) {\n            return;\n        }\n\n        const ssrc = this.track.getSsrc();\n        const framesDecoded = data.framesDecoded.get(ssrc);\n        const now = Date.now();\n\n        if (framesDecoded == null) {\n            // No SSRC in the stats report — the remote track exists but no RTP packets have been\n            // received yet. Seed _lastFramesDecodedAt on the first absent poll so the stall timer\n            // starts running. Subsequent absent polls will fall through to the freeze check below.\n            if (this._lastFramesDecodedAt === null) {\n                this._lastFramesDecodedAt = now;\n            }\n        } else if (framesDecoded > (this._lastFramesDecoded ?? -1)) {\n            // Frames are advancing — track is healthy.\n            this._lastFramesDecodedAt = now;\n            this._lastFramesDecoded = framesDecoded;\n\n            if (this._statsTrackFrozen) {\n                logger.debug(`Stats-based freeze cleared for ${this.track.getSourceName()}`);\n                this._statsTrackFrozen = false;\n                this.figureOutStreamingStatus();\n            }\n\n            return;\n        }\n\n        // Frames are not advancing (SSRC absent or counter stalled). Declare frozen once the\n        // configured timeout has elapsed since we last saw frame progress.\n        if (this._lastFramesDecodedAt !== null\n                && (now - this._lastFramesDecodedAt) >= this._getVideoFrozenTimeout()\n                && !this._statsTrackFrozen) {\n            logger.debug(`Stats-based freeze detected for ${this.track.getSourceName()}`);\n            this._statsTrackFrozen = true;\n            this.figureOutStreamingStatus();\n        }\n    }\n\n    /**\n     * Figures out (and updates) the current streaming status for the track identified by the source name.\n     */\n    figureOutStreamingStatus(): void {\n        const sourceName = this.track.getSourceName();\n        const inP2PMode = this.conference.isP2PActive();\n        const isRestoringTimedOut = this._isRestoringTimedout();\n        const audioOnlyMode = this.conference.getLastN() === 0;\n\n        // NOTE Overriding videoMuted to true for audioOnlyMode should disable any detection based on video playback or\n        // forwarded sources.\n        const isVideoMuted = this.track.isMuted() || audioOnlyMode;\n        const isVideoTrackFrozen = this.isVideoTrackFrozen();\n        const isInForwardedSources = this.rtc.isInForwardedSources(sourceName);\n\n        const newState\n            = inP2PMode\n                ? TrackStreamingStatusImpl._getNewStateForP2PMode(\n                    isVideoMuted,\n                    isVideoTrackFrozen)\n                : TrackStreamingStatusImpl._getNewStateForJvbMode(\n                    isInForwardedSources,\n                    isRestoringTimedOut,\n                    isVideoMuted,\n                    isVideoTrackFrozen);\n\n        // if the new state is not restoring clear timers and timestamps that we use to track the restoring state\n        if (newState !== TrackStreamingStatus.RESTORING) {\n            this._clearRestoringTimer();\n        }\n\n        logger.debug(\n            `Figure out conn status for ${sourceName}, is video muted: ${\n                isVideoMuted} video track frozen: ${\n                isVideoTrackFrozen} p2p mode: ${\n                inP2PMode} is in forwarded sources: ${\n                isInForwardedSources} currentStatus => newStatus: ${\n                this.track.getTrackStreamingStatus()} => ${newState}`);\n\n        const oldStreamingStatus = this.streamingStatusMap || {};\n\n        // Send an analytics event (guard on either the p2p flag or the streaming status has changed since the last\n        // time this code block run).\n        if (!('p2p' in oldStreamingStatus)\n            || !('streamingStatus' in oldStreamingStatus)\n            || oldStreamingStatus.p2p !== inP2PMode\n            || oldStreamingStatus.streamingStatus !== newState) {\n\n            const nowMs = Date.now();\n\n            this.maybeSendTrackStreamingStatusEvent(nowMs);\n\n            this.streamingStatusMap = {\n                ...oldStreamingStatus,\n                p2p: inP2PMode,\n                startedMs: nowMs,\n                streamingStatus: newState\n            };\n\n            // sometimes (always?) we're late to hook the TRACK_VIDEOTYPE_CHANGED event and the video type is not in\n            // oldStreamingStatus.\n            if (!('videoType' in this.streamingStatusMap)) {\n                this.streamingStatusMap.videoType = this.track.getVideoType();\n            }\n        }\n        this._changeStreamingStatus(newState);\n    }\n\n    /**\n     * Computes the duration of the current streaming status for the track (i.e. 15 seconds in the INTERRUPTED state)\n     * and sends a track streaming status event.\n     * @param nowMs - The current time (in millis).\n     */\n    maybeSendTrackStreamingStatusEvent(nowMs: number): void {\n        const trackStreamingStatus = this.streamingStatusMap;\n\n        if (trackStreamingStatus\n            && 'startedMs' in trackStreamingStatus\n            && 'videoType' in trackStreamingStatus\n            && 'streamingStatus' in trackStreamingStatus\n            && 'p2p' in trackStreamingStatus) {\n            trackStreamingStatus.value = nowMs - trackStreamingStatus.startedMs;\n            Statistics.sendAnalytics(createTrackStreamingStatusEvent(trackStreamingStatus));\n        }\n    }\n\n    /**\n     * On change in forwarded sources set check all leaving and entering track to change their corresponding statuses.\n     *\n     * @param leavingForwardedSources - The array of sourceName leaving forwarded sources.\n     * @param enteringForwardedSources - The array of sourceName entering forwarded sources.\n     * @param timestamp - The time in millis\n     * @private\n     */\n    onForwardedSourcesChanged(\n            leavingForwardedSources: string[] = [],\n            enteringForwardedSources: string[] = [],\n            timestamp: number): void {\n\n        const sourceName = this.track.getSourceName();\n\n        // If the browser doesn't fire the mute/onmute events when the remote peer stops/starts sending media,\n        // calculate the streaming status for all the tracks since it won't get triggered automatically on the track\n        // that has started/stopped receiving media.\n        if (!browser.supportsVideoMuteOnConnInterrupted()) {\n            this.figureOutStreamingStatus();\n        }\n\n        if (leavingForwardedSources.includes(sourceName)) {\n            this.track._clearEnteredForwardedSourcesTimestamp();\n            this._clearRestoringTimer();\n            browser.supportsVideoMuteOnConnInterrupted() && this.figureOutStreamingStatus();\n        }\n\n        if (enteringForwardedSources.includes(sourceName)) {\n            // store the timestamp this track is entering forwarded sources\n            this.track._setEnteredForwardedSourcesTimestamp(timestamp);\n            browser.supportsVideoMuteOnConnInterrupted() && this.figureOutStreamingStatus();\n        }\n    }\n\n    /**\n     * Clears the restoring timer for video track and the timestamp for entering forwarded sources.\n     */\n    _clearRestoringTimer(): void {\n        const rTimer = this.restoringTimer;\n\n        if (rTimer) {\n            clearTimeout(rTimer);\n            this.restoringTimer = null;\n        }\n    }\n\n    /**\n     * Checks whether a track had stayed enough in restoring state, compares current time and the time the track\n     * entered in forwarded sources. If it hasn't timedout and there is no timer added, add new timer in order to give\n     * it more time to become active or mark it as interrupted on next check.\n     *\n     * @returns <tt>true</tt> if the track was in restoring state more than the timeout\n     * ({@link DEFAULT_RESTORING_TIMEOUT}.) in order to set its status to interrupted.\n     * @private\n     */\n    _isRestoringTimedout(): boolean {\n        const enteredForwardedSourcesTimestamp = this.track._getEnteredForwardedSourcesTimestamp();\n\n        if (enteredForwardedSourcesTimestamp\n            && (Date.now() - enteredForwardedSourcesTimestamp) >= DEFAULT_RESTORING_TIMEOUT) {\n            return true;\n        }\n\n        // still haven't reached timeout, if there is no timer scheduled, schedule one so we can track the restoring\n        // state and change it after reaching the timeout\n        const rTimer = this.restoringTimer;\n\n        if (!rTimer) {\n            this.restoringTimer = setTimeout(() => this.figureOutStreamingStatus(), DEFAULT_RESTORING_TIMEOUT);\n        }\n\n        return false;\n    }\n\n    /** Checks whether a track is the current track. */\n    _isCurrentTrack(track: JitsiRemoteTrack): boolean {\n        return track.getSourceName() === this.track.getSourceName();\n    }\n\n    /**\n     * Sends a last/final track streaming status event for the track of the user that left the conference.\n     * @param id - The id of the participant that left the conference.\n     */\n    onUserLeft(id: string): void {\n        if (this.track.getParticipantId() === id) {\n            this.maybeSendTrackStreamingStatusEvent(Date.now());\n            this.streamingStatusMap = {};\n        }\n    }\n\n    /**\n     * Handles RTC 'onmute' event for the video track.\n     *\n     * @param track - The video track for which 'onmute' event will be processed.\n     */\n    onTrackRtcMuted(track: JitsiRemoteTrack): void {\n        if (!this._isCurrentTrack(track)) {\n            return;\n        }\n\n        const sourceName = track.getSourceName();\n\n        logger.debug(`Detector track RTC muted: ${sourceName}`, Date.now());\n\n        this.rtcMutedTimestamp = Date.now();\n        if (!track.isMuted()) {\n            // If the user is not muted according to the signalling we'll give it some time, before the streaming\n            // interrupted event is triggered.\n            this.clearTimeout();\n\n            // The timeout is reduced when track is not in the forwarded sources\n            const timeout = this._getVideoFrozenTimeout();\n\n            this.trackTimer = window.setTimeout(() => {\n                logger.debug(`Set track RTC muted for: ${sourceName} after the timeout of ${timeout} ms`);\n                this.clearTimeout();\n                this.figureOutStreamingStatus();\n            }, timeout);\n        }\n    }\n\n    /**\n     * Handles RTC 'onunmute' event for the video track.\n     *\n     * @param track - The video track for which 'onunmute' event will be processed.\n     */\n    onTrackRtcUnmuted(track: JitsiRemoteTrack): void {\n        if (!this._isCurrentTrack(track)) {\n            return;\n        }\n\n        const sourceName = this.track.getSourceName();\n\n        logger.debug(`Detector track RTC unmuted: ${sourceName}`, Date.now());\n\n        this.clearTimeout();\n        this.clearRtcMutedTimestamp();\n\n        this.figureOutStreamingStatus();\n    }\n\n    /**\n     * Here the signalling \"mute\"/\"unmute\" events are processed.\n     *\n     * @param track - The remote video track for which the signalling mute/unmute event will be\n     * processed.\n     */\n    onSignallingMuteChanged(track: JitsiRemoteTrack): void {\n        if (!this._isCurrentTrack(track)) {\n            return;\n        }\n\n        this.figureOutStreamingStatus();\n    }\n\n    /**\n     * Sends a track streaming status event as a result of the video type changing.\n     * @deprecated this will go away with full multiple streams support\n     * @param type - The video type.\n     */\n    onTrackVideoTypeChanged(type: VideoType): void {\n        const nowMs = Date.now();\n\n        this.maybeSendTrackStreamingStatusEvent(nowMs);\n\n        this.streamingStatusMap = {\n            ...this.streamingStatusMap || {},\n            startedMs: nowMs,\n            videoType: type\n        };\n    }\n}\n\nexport default TrackStreamingStatusImpl;\n","import { getLogger } from '@jitsi/logger';\n\nimport JitsiConference from '../../JitsiConference';\nimport { JitsiTrackEvents } from '../../JitsiTrackEvents';\nimport { MediaType } from '../../service/RTC/MediaType';\nimport { RTCEvents } from '../../service/RTC/RTCEvents';\nimport { VideoType } from '../../service/RTC/VideoType';\nimport { createTtfmEvent } from '../../service/statistics/AnalyticsEvents';\nimport browser from '../browser';\nimport TrackStreamingStatusImpl, { TrackStreamingStatus } from '../connectivity/TrackStreamingStatus';\nimport Statistics from '../statistics/statistics';\nimport { isValidNumber } from '../util/MathUtil';\n\nimport JitsiTrack from './JitsiTrack';\nimport RTC from './RTC';\nimport RTCUtils from './RTCUtils';\n\nconst logger = getLogger('rtc:JitsiRemoteTrack');\n\n// eslint-disable-next-line @typescript-eslint/no-require-imports\nconst ort = require('onnxruntime-web/wasm');\n\nort.env.wasm.wasmPaths = '/libs/dist/';\nort.env.wasm.numThreads = 1;\n\nlet ttfmTrackerAudioAttached = false;\nlet ttfmTrackerVideoAttached = false;\n\nexport let decodingSession = null;\n/**\n * Loads the decoder model\n */\nexport async function loadDecoder(modelPath = '/libs/models/Decoder.onnx') {\n    try {\n        decodingSession = await ort.InferenceSession.create(modelPath,\n            {\n                enableCpuMemArena: false,\n                executionProviders: [ 'wasm' ],\n                freeDimensionOverrides: {\n                    batch: 1,\n                },\n                graphOptimizationLevel: 'extended',\n            }\n        );\n        logger.info('Decoder model has been loaded');\n    } catch (error) {\n        logger.error('Decoder model could not be loaded!: ', error);\n    }\n}\nloadDecoder();\n\n\n/**\n * List of container events that we are going to process. _onContainerEventHandler will be added as listener to the\n * container for every event in the list.\n */\nconst containerEvents = [ 'abort', 'canplaythrough', 'ended', 'error', 'stalled', 'suspend', 'waiting' ];\n\n/* eslint-disable max-params */\n\n/**\n * Represents a single media track (either audio or video).\n *\n * @noInheritDoc\n */\nexport default class JitsiRemoteTrack extends JitsiTrack {\n    private _sourceName: string;\n    private _trackStreamingStatus: Nullable<TrackStreamingStatus>;\n    private _trackStreamingStatusImpl: Nullable<TrackStreamingStatusImpl>;\n\n    /**\n     * This holds the timestamp indicating when remote video track entered forwarded sources set. Track entering\n     * forwardedSources will have streaming status restoring and when we start receiving video will become active,\n     * but if video is not received for certain time {@link DEFAULT_RESTORING_TIMEOUT} that track streaming status\n     * will become interrupted.\n     */\n    private _containerHandlers: { [key: string]: (event: Event) => void; };\n    private _decodedStream: Nullable<MediaStream> = null;\n    private _enteredForwardedSourcesTimestamp: Nullable<number>;\n    private _rtc: RTC;\n    private _muted: boolean;\n    private _hasBeenMuted: boolean;\n    private _ssrc: number;\n    private _animationFrameId: Nullable<number> = null;\n    private inputTensor: Nullable<any> = null;\n    private dataOutput: Nullable<ImageData> = null;\n    private inputBuffer: Nullable<Float32Array> = null;\n    private wasDisposed: boolean = false;\n    private trackID: string = 'no track ID yet';\n    private _rawVideo: Nullable<HTMLVideoElement> = null;\n\n    public ownerEndpointId: string;\n    public isP2P: boolean;\n    public rtcId: Nullable<string>;\n    public width: number = 0;\n    public height: number = 0;\n    public shouldDecode: boolean = false;\n    public decoderIsOn: boolean = false;\n    public isProcessingFrame: boolean = false;\n\n    /**\n     * Creates new JitsiRemoteTrack instance.\n     * @param {RTC} rtc the RTC service instance.\n     * @param {JitsiConference} conference the conference to which this track\n     *        belongs to\n     * @param {string} ownerEndpointId the endpoint ID of the track owner\n     * @param {MediaStream} stream WebRTC MediaStream, parent of the track\n     * @param {MediaStreamTrack} track underlying WebRTC MediaStreamTrack for\n     *        the new JitsiRemoteTrack\n     * @param {MediaType} mediaType the type of the media\n     * @param {VideoType} videoType the type of the video if applicable\n     * @param {number} ssrc the SSRC number of the Media Stream\n     * @param {boolean} muted the initial muted state\n     * @param {boolean} isP2P indicates whether or not this track belongs to a\n     * P2P session\n     * @param {String} sourceName the source name signaled for the track\n     * @throws {TypeError} if <tt>ssrc</tt> is not a number.\n     */\n    constructor(\n            rtc: RTC,\n            conference: JitsiConference,\n            ownerEndpointId: string,\n            stream: MediaStream,\n            track: MediaStreamTrack,\n            mediaType: MediaType,\n            videoType: VideoType,\n            ssrc: number,\n            _muted: boolean,\n            isP2P: boolean,\n            sourceName: string) {\n        super(\n            conference,\n            stream,\n            track,\n            () => {\n                // Nothing to do if the track is inactive.\n            },\n            mediaType,\n            videoType);\n        this._rtc = rtc;\n\n        // Prevent from mixing up type of SSRC which should be a number\n        if (typeof ssrc !== 'number') {\n            throw new TypeError(`SSRC ${ssrc} is not a number`);\n        }\n        this._ssrc = ssrc;\n        this.ownerEndpointId = ownerEndpointId;\n        this._muted = _muted;\n        this.isP2P = isP2P;\n        this._sourceName = sourceName;\n        this._trackStreamingStatus = null;\n        this._trackStreamingStatusImpl = null;\n        this.rtcId = null;\n\n        /**\n         * This holds the timestamp indicating when remote video track entered forwarded sources set. Track entering\n         * forwardedSources will have streaming status restoring and when we start receiving video will become active,\n         * but if video is not received for certain time {@link DEFAULT_RESTORING_TIMEOUT} that track streaming status\n         * will become interrupted.\n         */\n        this._enteredForwardedSourcesTimestamp = null;\n\n        this.addEventListener = this.on = this._addEventListener.bind(this);\n        this.removeEventListener = this.off = this._removeEventListener.bind(this);\n\n        logger.debug(`New remote track created: ${this}`);\n\n        // we want to mark whether the track has been ever muted\n        // to detect ttfm events for startmuted conferences, as it can\n        // significantly increase ttfm values\n        this._hasBeenMuted = _muted;\n\n        // Bind 'onmute' and 'onunmute' event handlers\n        this._bindTrackHandlers();\n        this._containerHandlers = {};\n        containerEvents.forEach(event => {\n            this._containerHandlers[event] = this._containerEventHandler.bind(this, event);\n        });\n\n    }\n\n    /* eslint-enable max-params */\n    /**\n     * Attaches the track handlers.\n     *\n     * @returns {void}\n     */\n    private _bindTrackHandlers(): void {\n        this.track.addEventListener('mute', () => this._onTrackMute());\n        this.track.addEventListener('unmute', () => this._onTrackUnmute());\n        this.track.addEventListener('ended', () => {\n            logger.debug(`\"onended\" event(${Date.now()}): ${this}`);\n        });\n    }\n\n    /**\n     * Overrides addEventListener method to init TrackStreamingStatus instance when there are listeners for the\n     * {@link JitsiTrackEvents.TRACK_STREAMING_STATUS_CHANGED} event.\n     *\n     * @param {string} event - event name\n     * @param {function} handler - event handler\n     */\n    private _addEventListener(event: string, handler: (...args: any[]) => void): void {\n        super.addListener(event, handler);\n\n        if (event === JitsiTrackEvents.TRACK_STREAMING_STATUS_CHANGED\n            && this.listenerCount(JitsiTrackEvents.TRACK_STREAMING_STATUS_CHANGED)\n            && !this._trackStreamingStatusImpl\n        ) {\n            this._initTrackStreamingStatus();\n            logger.debug(`Initializing track streaming status: ${this._sourceName}`);\n        }\n    }\n\n    /**\n     * Overrides removeEventListener method to dispose TrackStreamingStatus instance.\n     *\n     * @param {string} event - event name\n     * @param {function} handler - event handler\n     */\n    private _removeEventListener(event: string, handler: (...args: any[]) => void): void {\n        super.removeListener(event, handler);\n\n        if (event === JitsiTrackEvents.TRACK_STREAMING_STATUS_CHANGED\n            && !this.listenerCount(JitsiTrackEvents.TRACK_STREAMING_STATUS_CHANGED)\n        ) {\n            this._disposeTrackStreamingStatus();\n            logger.debug(`Disposing track streaming status: ${this._sourceName}`);\n        }\n    }\n\n    /**\n     * Callback invoked when the track is muted. Emits an event notifying\n     * listeners of the mute event.\n     *\n     * @private\n     * @returns {void}\n     */\n    private _onTrackMute(): void {\n        logger.debug(`\"onmute\" event(${Date.now()}): ${this}`);\n\n        // Ignore mute events that get fired on desktop tracks because of 0Hz screensharing introduced in Chromium.\n        // The sender stops sending frames if the content of the captured window doesn't change resulting in the\n        // receiver showing avatar instead of the shared content.\n        if (this.videoType === VideoType.DESKTOP) {\n            logger.debug('Ignoring mute event on desktop tracks.');\n\n            return;\n        }\n\n        this._rtc.eventEmitter.emit(RTCEvents.REMOTE_TRACK_MUTE, this);\n    }\n\n    /**\n     * Callback invoked when the track is unmuted. Emits an event notifying\n     * listeners of the mute event.\n     *\n     * @private\n     * @returns {void}\n     */\n    private _onTrackUnmute(): void {\n        logger.debug(`\"onunmute\" event(${Date.now()}): ${this}`);\n\n        this._rtc.eventEmitter.emit(RTCEvents.REMOTE_TRACK_UNMUTE, this);\n    }\n\n    /**\n     * Handles track play events.\n     */\n    private _playCallback(): void {\n        if (!this.conference.room) {\n            return;\n        }\n\n        const type = this.isVideoTrack() ? 'video' : 'audio';\n\n        const now = window.performance.now();\n\n        logger.info(`(TIME) Render ${type}:\\t`, now);\n        this.conference.getConnectionTimes()[`${type}.render`] = now;\n\n        // The conference can be started without calling GUM\n        // FIXME if there would be a module for connection times this kind\n        // of logic (gumDuration or ttfm) should end up there\n        const gumStart = window.connectionTimes['obtainPermissions.start'];\n        const gumEnd = window.connectionTimes['obtainPermissions.end'];\n        const gumDuration\n            = isValidNumber(gumEnd) && isValidNumber(gumStart) ? gumEnd - gumStart : 0;\n\n        // Subtract the muc.joined-to-session-initiate duration because jicofo\n        // waits until there are 2 participants to start Jingle sessions.\n        const ttfm = now\n            - (this.conference.getConnectionTimes()['session.initiate']\n                - this.conference.getConnectionTimes()['muc.joined'])\n            - gumDuration;\n\n        this.conference.getConnectionTimes()[`${type}.ttfm`] = ttfm;\n        logger.info(`(TIME) TTFM ${type}:\\t`, ttfm);\n\n        Statistics.sendAnalytics(createTtfmEvent(\n            {\n                'media_type': type,\n                muted: this._hasBeenMuted,\n                value: ttfm\n            }));\n\n    }\n\n    /**\n     * An event handler for events triggered by the attached container.\n     *\n     * @param {string} type - The type of the event.\n     */\n    private _containerEventHandler(type: string): void {\n        logger.debug(`${type} handler was called for a container with attached ${this}`);\n    }\n\n    /**\n     * Returns a string with a description of the current status of the track.\n     *\n     * @returns {string}\n     */\n    private _getStatus(): string {\n        const { enabled, muted, readyState } = this.track;\n\n        return `readyState: ${readyState}, muted: ${muted}, enabled: ${enabled}`;\n    }\n\n    /**\n     * Initializes trackStreamingStatusImpl.\n     */\n    private _initTrackStreamingStatus(): void {\n        const config = this.conference.options.config;\n\n        this._trackStreamingStatus = TrackStreamingStatus.ACTIVE;\n\n        this._trackStreamingStatusImpl = new TrackStreamingStatusImpl(\n            this._rtc,\n            this.conference,\n            this,\n            {\n                // These options are not public API, leaving it here only as an entry point through config for\n                // tuning up purposes. Default values should be adjusted as soon as optimal values are discovered.\n                outOfForwardedSourcesTimeout: config._peerConnStatusOutOfLastNTimeout,\n                p2pRtcMuteTimeout: config._p2pConnStatusRtcMuteTimeout,\n                rtcMuteTimeout: config._peerConnStatusRtcMuteTimeout\n            });\n\n        this._trackStreamingStatusImpl.init();\n\n        // In some edge cases, both browser 'unmute' and bridge's forwarded sources events are received before a\n        // LargeVideoUpdate is scheduled for auto-pinning a new screenshare track. If there are no layout changes and\n        // no further track events are received for the SS track, a black tile will be displayed for screenshare on\n        // stage. Fire a TRACK_STREAMING_STATUS_CHANGED event if the media is already being received for the remote\n        // track to prevent this from happening.\n        !this._trackStreamingStatusImpl.isVideoTrackFrozen()\n            && this._rtc.eventEmitter.emit(\n                JitsiTrackEvents.TRACK_STREAMING_STATUS_CHANGED,\n                this,\n                this._trackStreamingStatus);\n    }\n\n    /**\n     * Disposes trackStreamingStatusImpl and clears trackStreamingStatus.\n     */\n    private _disposeTrackStreamingStatus(): void {\n        if (this._trackStreamingStatusImpl) {\n            this._trackStreamingStatusImpl.dispose();\n            this._trackStreamingStatusImpl = null;\n            this._trackStreamingStatus = null;\n        }\n    }\n\n    /**\n     * Called when the track has been attached to a new container.\n     *\n     * @param {HTMLElement} container the HTML container which can be 'video' or 'audio' element.\n     * @internal\n     */\n    protected override _onTrackAttach(container: HTMLElement): void {\n        containerEvents.forEach(event => {\n            container.addEventListener(event, this._containerHandlers[event]);\n        });\n    }\n\n    /**\n     * Called when the track has been detached from a container.\n     *\n     * @param {HTMLElement} container the HTML container which can be 'video' or 'audio' element.\n     * @internal\n     */\n    protected override _onTrackDetach(container: HTMLElement): void {\n        containerEvents.forEach(event => {\n            container.removeEventListener(event, this._containerHandlers[event]);\n        });\n    }\n\n    /**\n     * Attach time to first media tracker only if there is conference and only\n     * for the first element.\n     * @param container the HTML container which can be 'video' or 'audio'\n     * element.\n     */\n    protected override _attachTTFMTracker(container: HTMLElement): void {\n        if ((ttfmTrackerAudioAttached && this.isAudioTrack())\n                || (ttfmTrackerVideoAttached && this.isVideoTrack())) {\n            return;\n        }\n\n        if (this.isAudioTrack()) {\n            ttfmTrackerAudioAttached = true;\n        }\n        if (this.isVideoTrack()) {\n            ttfmTrackerVideoAttached = true;\n        }\n\n        container.addEventListener('canplay', this._playCallback.bind(this));\n    }\n\n    isDecoderOn(): boolean {\n        return this.decoderIsOn;\n    }\n\n    /**\n     *  Performs the decoding routine to increase resolution\n     * @param container the HTML container which can be 'video' or 'audio'\n     * element.\n     */\n    increaseResolution(container: HTMLElement) {\n        if (this._animationFrameId) {\n            logger.warn('Decoder: canceling animation frame for track:', this.trackID);\n            cancelAnimationFrame(this._animationFrameId);\n        }\n        const canvasDecoded = document.createElement('canvas');\n\n        this._decodedStream = canvasDecoded.captureStream();\n        RTCUtils.attachMediaStream(container, this._decodedStream);\n\n        this._rawVideo = document.createElement('video');\n\n        this._rawVideo.srcObject = this.stream;\n        this._rawVideo.muted = true;\n        this._rawVideo.play().catch(() => { /* ignore */ });\n\n        this.trackID = this.stream.getVideoTracks()[0].id;\n\n        logger.info('Decoder: start increase resolution for track:', this.trackID, 'corresponding to', this.getParticipantId());\n\n        const canvasEncoded = document.createElement('canvas');\n        const ctxEncoded = canvasEncoded.getContext('2d', { willReadFrequently: true });\n        const ctxDecoded = canvasDecoded.getContext('2d', { willReadFrequently: true });\n\n        if (!this._rawVideo || !ctxEncoded || !ctxDecoded) {\n            logger.warn('Decoder: stopping because rack was not initialized correctly:', this.trackID);\n\n            return;\n        }\n\n        this.isProcessingFrame = false;\n        this.wasDisposed = false;\n        const processFrame = async () => {\n            if (!decodingSession) {\n                logger.error('Decoder: Decoder has not being loaded');\n\n                return;\n            }\n            if (!this.getParticipantId()) {\n                logger.error('Decoder: Was called for an orphaned track! Cleaning up..');\n                this.cleanDecoder();\n\n                return;\n\n            }\n            if (this.wasDisposed || !this._rawVideo) {\n                logger.warn('Decoder: stopping because disposed was called for this track:', this.trackID);\n\n                return;\n            }\n            if (this.isProcessingFrame) {\n                logger.warn('Decoder: skipping a frame because the previous one is still being processed for track', this.trackID);\n                this._animationFrameId = requestAnimationFrame(processFrame);\n\n                return;\n            }\n\n            if (!this._rawVideo.videoWidth || !this._rawVideo.videoHeight || this._rawVideo.readyState < HTMLMediaElement.HAVE_CURRENT_DATA) {\n                this._animationFrameId = requestAnimationFrame(processFrame);\n\n                return;\n            }\n\n            let outInference: Nullable<any> = null;\n\n            this.isProcessingFrame = true;\n            const nwidth = this._rawVideo.videoWidth;\n            const nheight = this._rawVideo.videoHeight;\n\n            if (nheight < 240 && !this.decoderIsOn) {\n                logger.info('Decoder: Activating decoder for track:', this.trackID, 'frame resolution: ', nwidth, 'x', nheight);\n                this.shouldDecode = true;\n            }\n            if (nheight >= 240 && this.decoderIsOn) {\n                logger.info('Decoder: Deactivating decoder for track:', this.trackID, 'frame resolution: ', nwidth, 'x', nheight);\n                this.shouldDecode = false;\n            }\n\n            if (this.shouldDecode) {\n                try {\n                    // check wether the canvas must be changed\n                    if (canvasEncoded.width !== nwidth || canvasEncoded.height !== nheight) {\n                        console.log('Decoder: changing encoding canvas from:', canvasEncoded.width, 'x', canvasEncoded.height, 'to', nwidth, 'x', nheight);\n                        canvasEncoded.width = nwidth;\n                        canvasEncoded.height = nheight;\n                    }\n\n                    if (canvasDecoded.width !== nwidth * 2 || canvasDecoded.height !== nheight * 2) {\n                        console.log('Decoder: changing decoded canvas from:', canvasDecoded.width, 'x', canvasDecoded.height, 'to', nwidth * 2, 'x', nheight * 2);\n                        canvasDecoded.width = nwidth * 2;\n                        canvasDecoded.height = nheight * 2;\n                    }\n\n                    // check wether the tensor must be re-allocated\n                    if (this.width != nwidth || this.height != nheight || !this.dataOutput || !this.inputBuffer) {\n                        console.log('Decoder: re-allocating tensor from:', this.width, 'x', this.height, 'to', nwidth, 'x', nheight);\n                        if (this.inputTensor) {\n                            this.inputTensor.dispose();\n                            this.inputTensor = null;\n                        }\n                        this.inputBuffer = new Float32Array(nwidth * nheight * 4);\n                        this.inputTensor = new ort.Tensor('float32', this.inputBuffer, [ 1, nheight, nwidth, 4 ]);\n                        this.dataOutput = new ImageData(2 * nwidth, 2 * nheight);\n                        this.width = nwidth;\n                        this.height = nheight;\n                    }\n\n                    ctxEncoded.drawImage(this._rawVideo, 0, 0, this.width, this.height);\n                    const imageEncode = ctxEncoded.getImageData(0, 0, this.width, this.height);\n\n                    this.inputBuffer.set(imageEncode.data);\n                    outInference = await decodingSession.run({ input: this.inputTensor });\n                    this.dataOutput.data.set(outInference.output.data);\n                    ctxDecoded.putImageData(this.dataOutput, 0, 0);\n\n                    if (!this.decoderIsOn) {\n                        this.decoderIsOn = true;\n                        logger.info('Decoder: ON for track:', this.trackID);\n                    }\n                } catch (error) {\n                    this.shouldDecode = false;\n                } finally {\n                    outInference?.output.dispose();\n                    outInference = null;\n                    this.isProcessingFrame = false;\n                }\n            }\n            if (!this.shouldDecode) {\n                canvasDecoded.width = this._rawVideo.videoWidth;\n                canvasDecoded.height = this._rawVideo.videoHeight;\n                ctxDecoded.drawImage(this._rawVideo, 0, 0, this._rawVideo.videoWidth, this._rawVideo.videoHeight);\n                if (this.decoderIsOn) {\n                    this.decoderIsOn = false;\n                    logger.info('Decoder: OFF for track', this.trackID);\n                }\n                this.isProcessingFrame = false;\n            }\n            if (this.wasDisposed) {\n                logger.info('Decoder: Finished processing frame and track was already disposed, clean up just in case');\n                this.cleanDecoder();\n\n                return;\n            } else this._animationFrameId = requestAnimationFrame(processFrame);\n\n        };\n\n        processFrame();\n    }\n\n    /**\n     * Attaches the MediaStream of this track to an HTML container.\n     * Adds the container to the list of containers that are displaying the\n     * track.\n     *\n     * @param container the HTML container which can be 'video' or 'audio'\n     * element.\n     *\n     * @returns {void}\n     */\n    override attach(container: HTMLElement, decode: boolean): Promise<void> {\n        let result = Promise.resolve();\n\n        if (this.stream) {\n            this._onTrackAttach(container);\n            if (this.type === MediaType.VIDEO && this.videoType === VideoType.CAMERA && decode && !browser.isSafari() && decodingSession) {\n                this.increaseResolution(container);\n            } else {\n                result = RTCUtils.attachMediaStream(container, this.stream);\n            }\n        }\n        this.containers.push(container);\n        this._attachTTFMTracker(container);\n\n        return result;\n    }\n\n    /**\n     * Changes the video type of the track.\n     *\n     * @param {string} type - The new video type(\"camera\", \"desktop\").\n     * @internal\n     */\n    _setVideoType(type: VideoType): void {\n        if (this.videoType === type) {\n            return;\n        }\n        this.videoType = type;\n        this.emit(JitsiTrackEvents.TRACK_VIDEOTYPE_CHANGED, type);\n    }\n\n    /**\n     * Updates track's streaming status.\n     *\n     * @param {string} state the current track streaming state. {@link TrackStreamingStatus}.\n     * @internal\n     */\n    _setTrackStreamingStatus(status: TrackStreamingStatus): void {\n        this._trackStreamingStatus = status;\n    }\n\n    /**\n     * Clears the timestamp of when the track entered forwarded sources.\n     * @internal\n     */\n    _clearEnteredForwardedSourcesTimestamp(): void {\n        this._enteredForwardedSourcesTimestamp = null;\n    }\n\n    /**\n     * Updates the timestamp of when the track entered forwarded sources.\n     *\n     * @param {number} timestamp the time in millis\n     * @internal\n     */\n    _setEnteredForwardedSourcesTimestamp(timestamp: number): void {\n        this._enteredForwardedSourcesTimestamp = timestamp;\n    }\n\n    /**\n     * Returns the timestamp of when the track entered forwarded sources.\n     *\n     * @returns {number} the time in millis\n     * @internal\n     */\n    _getEnteredForwardedSourcesTimestamp(): number | null {\n        return this._enteredForwardedSourcesTimestamp;\n    }\n\n    cleanDecoder() {\n        logger.info('Decoder: cleaning is called for track:', this.trackID);\n        if (this._animationFrameId !== null) {\n            cancelAnimationFrame(this._animationFrameId);\n            this._animationFrameId = null;\n        }\n        if (this._rawVideo) {\n            this._rawVideo.pause();\n            this._rawVideo.srcObject = null;\n            this._rawVideo = null;\n        }\n        if (this.inputTensor) {\n            this.inputTensor.dispose();\n            this.inputTensor = null;\n        }\n        if (this._decodedStream) {\n            this._decodedStream.getTracks().forEach(t => t.stop());\n            this._decodedStream = null;\n        }\n        this.shouldDecode = false;\n        this.isProcessingFrame = false;\n        this.decoderIsOn = false;\n        this.width = 0;\n        this.height = 0;\n        this.dataOutput = null;\n        this.wasDisposed = true;\n\n    }\n\n    /**\n     * Removes attached event listeners and dispose TrackStreamingStatus .\n     *\n     * @returns {Promise}\n     */\n    override async dispose(): Promise<void> {\n\n        if (this.type === MediaType.VIDEO && this.videoType === VideoType.CAMERA && !browser.isSafari() && !this.wasDisposed) {\n            console.log('Decoder: dispose called');\n            this.cleanDecoder();\n        }\n\n        if (this.disposed) {\n            return;\n        }\n\n        this._disposeTrackStreamingStatus();\n\n        return super.dispose();\n    }\n\n    /**\n     * Sets current muted status and fires an events for the change.\n     * @param value the muted status.\n     * @internal\n     */\n    setMute(value: boolean): void {\n        if (this._muted === value) {\n            return;\n        }\n\n        if (value) {\n            this._hasBeenMuted = true;\n        }\n\n        // we can have a fake video stream\n        if (this.stream) {\n            this.stream.muted = value;\n        }\n\n        this._muted = value;\n\n        logger.info(`Mute ${this}: ${value}`);\n        this.emit(JitsiTrackEvents.TRACK_MUTE_CHANGED, this);\n    }\n\n    /**\n     * Returns the current muted status of the track.\n     * @returns {boolean|*|JitsiRemoteTrack.muted} <tt>true</tt> if the track is\n     * muted and <tt>false</tt> otherwise.\n     */\n    override isMuted(): boolean {\n        return this._muted;\n    }\n\n    /**\n     * Returns the participant id which owns the track.\n     *\n     * @returns {string} the id of the participants. It corresponds to the\n     * Colibri endpoint id/MUC nickname in case of Jitsi-meet.\n     */\n    getParticipantId(): string {\n        return this.ownerEndpointId;\n    }\n\n    /**\n     * Returns the synchronization source identifier (SSRC) of this remote\n     * track.\n     *\n     * @override\n     * @returns {number} the SSRC of this remote track.\n     */\n    override getSsrc() {\n        return this._ssrc;\n    }\n\n\n    /**\n     * Returns the tracks source name\n     *\n     * @override\n     * @returns {string} the track's source name\n     */\n    override getSourceName(): string {\n        return this._sourceName;\n    }\n\n    /**\n     * Update the properties when the track is remapped to another source.\n     *\n     * @param {string} owner The endpoint ID of the new owner.\n     * @internal\n     */\n    setOwner(owner: string): void {\n        this.ownerEndpointId = owner;\n    }\n\n    /**\n     * Sets the name of the source associated with the remote track.\n     *\n     * @override\n     * @param {string} name - The source name to be associated with the track.\n     * @internal\n     */\n    override setSourceName(name: string): void {\n        this._sourceName = name;\n    }\n\n    /**\n     * Returns track's streaming status.\n     *\n     * @returns {string} the streaming status <tt>TrackStreamingStatus</tt> of the track. Returns null\n     * if trackStreamingStatusImpl hasn't been initialized.\n     *\n     * {@link TrackStreamingStatus}.\n     */\n    getTrackStreamingStatus(): Nullable<TrackStreamingStatus> {\n        return this._trackStreamingStatus;\n    }\n\n    /**\n     * Creates a text representation of this remote track instance.\n     * @return {string}\n     */\n    override toString(): string {\n        return `RemoteTrack[userID: ${this.getParticipantId()}, type: ${this.getType()}, ssrc: ${\n            this.getSsrc()}, p2p: ${this.isP2P}, sourceName: ${this._sourceName}, status: {${this._getStatus()}}]`;\n    }\n}\n","/**\n * Enumeration of the scalability modes supported by the video encoders.\n * For more information, check https://www.w3.org/TR/webrtc-svc/#dependencydiagrams*\n *\n * enum VideoEncoderScalabilityMode {\n *  L1T3: string;\n *  L2T3: string;\n *  L2T3_KEY: string;\n *  L3T3: string;\n *  L3T3_KEY: string;\n * }\n */\nexport enum VideoEncoderScalabilityMode {\n\n    /**\n     * L1T3 mode: 1-layer spatial and 3-layer temporal scalabilty encoding.\n     */\n    L1T3 = 'L1T3',\n\n    /**\n     * L2T2 mode: 2-layer spatial and 3-layer temporal scalability encoding.\n     */\n    L2T3 = 'L2T3',\n\n    /**\n     * L2T3_KEY mode: 2-layer spatial and 3-layer temporal scalability K-SVC encoding.\n     */\n    L2T3_KEY = 'L2T3_KEY',\n\n    /**\n     * L3T3 mode: -layer spatial and 3-layer temporal scalability encoding.\n     */\n    L3T3 = 'L3T3',\n\n    /**\n     * L3T3_Key mode: 3-layer spatial and 3-layer temporal scalability K-SVC encoding.\n     */\n    L3T3_KEY = 'L3T3_KEY'\n}\n","import { getLogger } from '@jitsi/logger';\nimport { cloneDeep } from 'lodash-es';\nimport transform, { type SessionDescription } from 'sdp-transform';\n\nimport { CodecMimeType } from '../../service/RTC/CodecMimeType';\nimport { MediaDirection } from '../../service/RTC/MediaDirection';\nimport { MediaType } from '../../service/RTC/MediaType';\nimport {\n    SIM_LAYERS,\n    SSRC_GROUP_SEMANTICS,\n    STANDARD_CODEC_SETTINGS,\n    VIDEO_QUALITY_LEVELS,\n    VIDEO_QUALITY_SETTINGS\n} from '../../service/RTC/StandardVideoQualitySettings';\nimport { VideoEncoderScalabilityMode } from '../../service/RTC/VideoEncoderScalabilityMode';\nimport { VideoType } from '../../service/RTC/VideoType';\nimport browser from '../browser';\nimport SDPUtil from '../sdp/SDPUtil';\n\nimport JitsiLocalTrack from './JitsiLocalTrack';\nimport TraceablePeerConnection, { IAppliedAudioQuality, IAudioQuality, IRTCRtpEncodingParameters, IVideoQuality } from './TraceablePeerConnection';\n\nconst logger = getLogger('rtc:TPCUtils');\nconst VIDEO_CODECS = [ CodecMimeType.AV1, CodecMimeType.H264, CodecMimeType.VP8, CodecMimeType.VP9 ];\n\n\n// Codec configuration interface (reusable for all video codecs)\nexport interface ICodecConfig {\n    maxBitratesVideo?: {\n        [key: string]: number;\n    };\n    scalabilityModeEnabled?: boolean;\n    useKSVC?: boolean;\n    useSimulcast?: boolean;\n}\n\nexport interface ITPCUtilsOptions {\n    audioQuality?: IAudioQuality;\n    isP2P?: boolean;\n    videoQuality?: IVideoQuality;\n}\n\n/**\n * Handles all the utility functions for the TraceablePeerConnection class, like calculating the encoding parameters,\n * determining the media direction, calculating bitrates based on the current codec settings, etc.\n */\nexport class TPCUtils {\n    private pc: TraceablePeerConnection;\n    private options: ITPCUtilsOptions;\n    /**\n     * @internal\n     */\n    codecSettings: IVideoQuality;\n    /**\n     * Creates a new instance for a given TraceablePeerConnection\n     *\n     * @param peerconnection - the tpc instance for which we have utility functions.\n     * @param options - additional options that can be passed to the utility functions.\n     * @param options.audioQuality - the audio quality settings that are used to calculate the audio codec parameters.\n     * @param options.isP2P - whether the connection is a P2P connection.\n     * @param options.videoQuality - the video quality settings that are used to calculate the encoding parameters.\n     */\n    constructor(peerconnection: TraceablePeerConnection, options: ITPCUtilsOptions = {}) {\n        this.pc = peerconnection;\n        this.options = options;\n        this.codecSettings = cloneDeep(STANDARD_CODEC_SETTINGS);\n\n        /**\n         * Reads videoQuality settings from config.js and overrides the code defaults for video codecs.\n         */\n        const videoQualitySettings = this.options.videoQuality;\n\n        if (videoQualitySettings) {\n            for (const codec of VIDEO_CODECS) {\n                const codecConfig = videoQualitySettings[codec];\n                const bitrateSettings = codecConfig?.maxBitratesVideo\n\n                    // Read the deprecated settings for max bitrates.\n                    ?? (videoQualitySettings?.maxbitratesvideo?.[codec.toUpperCase()]);\n\n                if (bitrateSettings) {\n                    const settings = Object.values(VIDEO_QUALITY_SETTINGS);\n\n                    [ ...settings, 'ssHigh' ].forEach(value => {\n                        if (bitrateSettings[value]) {\n                            this.codecSettings[codec].maxBitratesVideo[value] = bitrateSettings[value];\n                        }\n                    });\n                }\n\n                if (!codecConfig) {\n                    continue; // eslint-disable-line no-continue\n                }\n\n                const scalabilityModeEnabled = this.codecSettings[codec].scalabilityModeEnabled\n                    && (typeof codecConfig.scalabilityModeEnabled === 'undefined'\n                        || codecConfig.scalabilityModeEnabled);\n\n                if (scalabilityModeEnabled) {\n                    typeof codecConfig.useSimulcast !== 'undefined'\n                        && (this.codecSettings[codec].useSimulcast = codecConfig.useSimulcast);\n                    typeof codecConfig.useKSVC !== 'undefined'\n                        && (this.codecSettings[codec].useKSVC = codecConfig.useKSVC);\n                } else {\n                    this.codecSettings[codec].scalabilityModeEnabled = false;\n                }\n            }\n        }\n    }\n\n    /**\n     * Calculates the configuration of the active encoding when the browser sends only one stream, i,e,, when there is\n     * no spatial scalability configure (p2p) or when it is running in full SVC mode.\n     *\n     * @param {JitsiLocalTrack} localVideoTrack - The local video track.\n     * @param {CodecMimeType} codec - The video codec.\n     * @param {number} newHeight - The resolution that needs to be configured for the local video track.\n     * @returns {Object} configuration.\n     * @private\n     */\n    private _calculateActiveEncodingParams(localVideoTrack: JitsiLocalTrack, codec: CodecMimeType, newHeight: number): IRTCRtpEncodingParameters {\n        const codecBitrates = this.codecSettings[codec].maxBitratesVideo;\n        const trackCaptureHeight = localVideoTrack.getCaptureResolution();\n        const effectiveNewHeight = newHeight > trackCaptureHeight ? trackCaptureHeight : newHeight;\n        const desktopShareBitrate = this.options.videoQuality?.desktopbitrate || codecBitrates.ssHigh;\n        const isScreenshare = localVideoTrack.getVideoType() === VideoType.DESKTOP;\n        let scalabilityMode = this.codecSettings[codec].useKSVC\n            ? VideoEncoderScalabilityMode.L3T3_KEY : VideoEncoderScalabilityMode.L3T3;\n        const { height, level } = VIDEO_QUALITY_LEVELS.find(lvl => lvl.height <= effectiveNewHeight);\n        let maxBitrate;\n        let scaleResolutionDownBy = SIM_LAYERS[2].scaleFactor;\n\n        if (this._isScreenshareBitrateCapped(localVideoTrack)) {\n            scalabilityMode = VideoEncoderScalabilityMode.L1T3;\n            maxBitrate = desktopShareBitrate;\n        } else if (isScreenshare) {\n            maxBitrate = codecBitrates.ssHigh;\n        } else {\n            maxBitrate = codecBitrates[level];\n            effectiveNewHeight && (scaleResolutionDownBy = trackCaptureHeight / effectiveNewHeight);\n\n            if (height !== effectiveNewHeight) {\n                logger.debug(`Quality level with height=${height} was picked when requested height=${newHeight} for`\n                    + `track with capture height=${trackCaptureHeight}`);\n            }\n        }\n\n        const config: IRTCRtpEncodingParameters = {\n            active: effectiveNewHeight > 0,\n            maxBitrate,\n            rid: undefined,\n            scalabilityMode,\n            scaleResolutionDownBy\n        };\n\n        if (!config.active || isScreenshare) {\n            return config;\n        }\n\n        // Configure the sender to send all 3 spatial layers for resolutions 720p and higher.\n        switch (level) {\n        case VIDEO_QUALITY_SETTINGS.ULTRA:\n        case VIDEO_QUALITY_SETTINGS.FULL:\n        case VIDEO_QUALITY_SETTINGS.HIGH:\n            config.scalabilityMode = this.codecSettings[codec].useKSVC\n                ? VideoEncoderScalabilityMode.L3T3_KEY : VideoEncoderScalabilityMode.L3T3;\n            break;\n        case VIDEO_QUALITY_SETTINGS.STANDARD:\n            config.scalabilityMode = this.codecSettings[codec].useKSVC\n                ? VideoEncoderScalabilityMode.L2T3_KEY : VideoEncoderScalabilityMode.L2T3;\n            break;\n        default:\n            config.scalabilityMode = VideoEncoderScalabilityMode.L1T3;\n        }\n\n        return config;\n    }\n\n    /**\n     * Returns the codecs in the current order of preference in the SDP provided.\n     *\n     * @param {SessionDescription} parsedSdp the parsed SDP object.\n     * @returns {Array<CodecMimeType>}\n     * @private\n     */\n    private _getConfiguredVideoCodecsImpl(parsedSdp: SessionDescription): CodecMimeType[] {\n        const mLine = parsedSdp.media.find(m => m.type === MediaType.VIDEO);\n        const codecs = new Set(mLine.rtp\n            .filter(pt => pt.codec.toLowerCase() !== 'rtx')\n            .map(pt => pt.codec.toLowerCase()));\n\n        return Array.from(codecs) as CodecMimeType[];\n    }\n\n    /**\n     * The startup configuration for the stream encodings that are applicable to the video stream when a new sender is\n     * created on the peerconnection. The initial config takes into account the differences in browser's simulcast\n     * implementation.\n     *\n     * Encoding parameters:\n     * active - determine the on/off state of a particular encoding.\n     * maxBitrate - max. bitrate value to be applied to that particular encoding based on the encoding's resolution and\n     *  config.js videoQuality settings if applicable.\n     * rid - Rtp Stream ID that is configured for a particular simulcast stream.\n     * scaleResolutionDownBy - the factor by which the encoding is scaled down from the original resolution of the\n     *  captured video.\n     *\n     * @param {JitsiLocalTrack} localTrack - The local video track.\n     * @param {String} codec - The codec currently in use.\n     * @returns {Array<Object>} - The initial configuration for the stream encodings.\n     * @private\n     */\n    private _getVideoStreamEncodings(localTrack: JitsiLocalTrack, codec: string): Partial<IRTCRtpEncodingParameters>[] {\n        const captureResolution = localTrack.getCaptureResolution();\n        const codecBitrates = this.codecSettings[codec].maxBitratesVideo;\n        const videoType = localTrack.getVideoType();\n        let effectiveScaleFactors = SIM_LAYERS.map(sim => sim.scaleFactor);\n        let cameraMaxbitrate;\n\n        if (videoType === VideoType.CAMERA) {\n            const { level } = VIDEO_QUALITY_LEVELS.find(lvl => lvl.height <= captureResolution);\n\n            cameraMaxbitrate = codecBitrates[level];\n            if (level === VIDEO_QUALITY_SETTINGS.ULTRA) {\n                effectiveScaleFactors[1] = 6.0; // 360p\n                effectiveScaleFactors[0] = 12.0; // 180p\n            } else if (level === VIDEO_QUALITY_SETTINGS.FULL) {\n                effectiveScaleFactors[1] = 3.0; // 360p\n                effectiveScaleFactors[0] = 6.0; // 180p\n            }\n        }\n        const maxBitrate = videoType === VideoType.DESKTOP\n            ? codecBitrates.ssHigh : cameraMaxbitrate;\n        let effectiveBitrates = [ codecBitrates.low, codecBitrates.standard, maxBitrate ];\n\n        // The SSRCs on older versions of Firefox are reversed in SDP, i.e., they have resolution order of 1:2:4 as\n        // opposed to Chromium and other browsers. This has been reverted in Firefox 117 as part of the below commit.\n        // https://hg.mozilla.org/mozilla-central/rev/b0348f1f8d7197fb87158ba74542d28d46133997\n        // This revert seems to be applied only to camera tracks, the desktop stream encodings still have the\n        // resolution order of 4:2:1.\n        if (browser.isFirefox()\n            && !browser.supportsScalabilityModeAPI()\n            && (videoType === VideoType.DESKTOP || browser.isVersionLessThan(117))) {\n            effectiveBitrates = effectiveBitrates.reverse();\n            effectiveScaleFactors = effectiveScaleFactors.reverse();\n        }\n\n        const standardSimulcastEncodings: IRTCRtpEncodingParameters[] = [\n            {\n                active: this.pc.videoTransferActive,\n                maxBitrate: effectiveBitrates[0],\n                rid: SIM_LAYERS[0].rid,\n                scaleResolutionDownBy: effectiveScaleFactors[0]\n            },\n            {\n                active: this.pc.videoTransferActive,\n                maxBitrate: effectiveBitrates[1],\n                rid: SIM_LAYERS[1].rid,\n                scaleResolutionDownBy: effectiveScaleFactors[1]\n            },\n            {\n                active: this.pc.videoTransferActive,\n                maxBitrate: effectiveBitrates[2],\n                rid: SIM_LAYERS[2].rid,\n                scaleResolutionDownBy: effectiveScaleFactors[2]\n            }\n        ];\n\n        if (this.codecSettings[codec].scalabilityModeEnabled) {\n            // Configure all 3 encodings when simulcast is requested through config.js for AV1 and VP9 and for H.264\n            // always since that is the only supported mode when DD header extension is negotiated for H.264.\n            if (this.codecSettings[codec].useSimulcast || codec === CodecMimeType.H264) {\n                for (const encoding of standardSimulcastEncodings) {\n                    encoding.scalabilityMode = VideoEncoderScalabilityMode.L1T3;\n                }\n\n                return standardSimulcastEncodings;\n            }\n\n            // Configure only one encoding for the SVC mode.\n            return [\n                {\n                    active: this.pc.videoTransferActive,\n                    maxBitrate: effectiveBitrates[2],\n                    rid: SIM_LAYERS[0].rid,\n                    scalabilityMode: this.codecSettings[codec].useKSVC\n                        ? VideoEncoderScalabilityMode.L3T3_KEY : VideoEncoderScalabilityMode.L3T3,\n                    scaleResolutionDownBy: effectiveScaleFactors[2]\n                },\n                {\n                    active: false,\n                    maxBitrate: 0\n                },\n                {\n                    active: false,\n                    maxBitrate: 0\n                }\n            ];\n        }\n\n        return standardSimulcastEncodings;\n    }\n\n    /**\n     * Returns a boolean indicating whether the video encoder is running in full SVC mode, i.e., it sends only one\n     * video stream that has both temporal and spatial scalability.\n     *\n     * @param {CodecMimeType} codec - The video codec in use.\n     * @returns boolean - true if the video encoder is running in full SVC mode, false otherwise.\n     * @private\n     */\n    private _isRunningInFullSvcMode(codec: CodecMimeType): boolean {\n        return (codec === CodecMimeType.VP9 || codec === CodecMimeType.AV1)\n            && this.codecSettings[codec].scalabilityModeEnabled\n            && !this.codecSettings[codec].useSimulcast;\n    }\n\n    /**\n     * Returns a boolean indicating whether the bitrate needs to be capped for the local video track if it happens to\n     * be a screenshare track. The lower spatial layers for screensharing are disabled when low fps screensharing is in\n     * progress. Sending all three streams often results in the browser suspending the high resolution in low b/w and\n     * and low cpu conditions, especially on the low end machines. Suspending the low resolution streams ensures that\n     * the highest resolution stream is available always. Safari is an exception here since it does not send the\n     * desktop stream at all if only the high resolution stream is enabled.\n     *\n     * @param {JitsiLocalTrack} localVideoTrack - The local video track.\n     * @returns {boolean} - true if the bitrate needs to be capped for the screenshare track, false otherwise.\n     * @private\n     */\n    private _isScreenshareBitrateCapped(localVideoTrack: JitsiLocalTrack): boolean {\n        return localVideoTrack.getVideoType() === VideoType.DESKTOP\n            && this.pc._capScreenshareBitrate\n            && !browser.isWebKitBased();\n    }\n\n    /**\n     * Removes the sdes:mid RTP header extension from the remote SDP for Firefox. Opting into sdes:mid negotiation\n     * was enabled on Chrome to fix SSRC demuxing issues (https://issues.webrtc.org/issues/502130956), but Firefox\n     * does not handle the sdes:mid header extension well, causing audio/video SSRC demuxing failures.\n     *\n     * @param {SessionDescription} parsedSdp - The parsed SDP that needs to be munged.\n     * @returns {SessionDescription} The munged SDP.\n     * @internal\n     */\n    _stripSdesMid(parsedSdp: SessionDescription): SessionDescription {\n        if (!browser.isFirefox()) {\n            return parsedSdp;\n        }\n\n        const mungedSdp = parsedSdp;\n\n        for (const mLine of mungedSdp.media) {\n            if (mLine.ext) {\n                mLine.ext = mLine.ext.filter(ext => ext.uri !== 'urn:ietf:params:rtp-hdrext:sdes:mid');\n            }\n        }\n\n        return mungedSdp;\n    }\n\n    /**\n     * Returns the calculated active state of the stream encodings based on the frame height requested for the send\n     * stream. All the encodings that have a resolution lower than the frame height requested will be enabled.\n     *\n     * @param {JitsiLocalTrack} localVideoTrack The local video track.\n     * @param {CodecMimeType} codec - The codec currently in use.\n     * @param {number} newHeight The resolution requested for the video track.\n     * @returns {Array<boolean>}\n     * @internal\n     */\n    calculateEncodingsActiveState(localVideoTrack: JitsiLocalTrack, codec: CodecMimeType, newHeight: number): boolean[] {\n        const height = localVideoTrack.getCaptureResolution();\n        const videoStreamEncodings = this._getVideoStreamEncodings(localVideoTrack, codec);\n        const encodingsState = videoStreamEncodings\n        .map(encoding => height / encoding.scaleResolutionDownBy)\n        .map((frameHeight, idx) => {\n            let activeState = false;\n\n            // When video is suspended on the media session.\n            if (!this.pc.videoTransferActive) {\n                return activeState;\n            }\n\n            // Single video stream.\n            if (!this.pc.isSpatialScalabilityOn() || this._isRunningInFullSvcMode(codec)) {\n                const { active } = this._calculateActiveEncodingParams(localVideoTrack, codec, newHeight);\n\n                return idx === 0 ? active : activeState;\n            }\n\n            if (newHeight > 0) {\n                if (localVideoTrack.getVideoType() === VideoType.CAMERA) {\n                    activeState = frameHeight <= newHeight\n\n                        // Keep the LD stream enabled even when the LD stream's resolution is higher than of the\n                        // requested resolution. This can happen when camera is captured at high resolutions like 4k\n                        // but the requested resolution is 180. Since getParameters doesn't give us information about\n                        // the resolutions of the simulcast encodings, we have to rely on our initial config for the\n                        // simulcast streams.\n                        || videoStreamEncodings[idx]?.scaleResolutionDownBy === SIM_LAYERS[0].scaleFactor;\n                } else {\n                    // For screenshare, keep the HD layer enabled always and the lower layers only for high fps\n                    // screensharing.\n                    activeState = videoStreamEncodings[idx].scaleResolutionDownBy === SIM_LAYERS[2].scaleFactor\n                        || !this._isScreenshareBitrateCapped(localVideoTrack);\n                }\n            }\n\n            return activeState;\n        });\n\n        return encodingsState;\n    }\n\n    /**\n     * Returns the calculated max bitrates that need to be configured on the stream encodings based on the video\n     * type and other considerations associated with screenshare.\n     *\n     * @param {JitsiLocalTrack} localVideoTrack The local video track.\n     * @param {CodecMimeType} codec - The codec currently in use.\n     * @param {number} newHeight The resolution requested for the video track.\n     * @returns {Array<number>}\n     * @internal\n     */\n    calculateEncodingsBitrates(localVideoTrack: JitsiLocalTrack, codec: CodecMimeType, newHeight: number): number[] {\n        const codecBitrates = this.codecSettings[codec].maxBitratesVideo;\n        const desktopShareBitrate = this.options.videoQuality?.desktopbitrate || codecBitrates.ssHigh;\n        const encodingsBitrates = this._getVideoStreamEncodings(localVideoTrack, codec)\n        .map((encoding, idx) => {\n            let bitrate = encoding.maxBitrate;\n\n            // Single video stream.\n            if (!this.pc.isSpatialScalabilityOn() || this._isRunningInFullSvcMode(codec)) {\n                const { maxBitrate } = this._calculateActiveEncodingParams(localVideoTrack, codec, newHeight);\n\n                return idx === 0 ? maxBitrate : undefined;\n            }\n\n            // Multiple video streams.\n            if (this._isScreenshareBitrateCapped(localVideoTrack)) {\n                bitrate = desktopShareBitrate;\n            }\n\n            return bitrate;\n        });\n\n        return encodingsBitrates;\n    }\n\n    /**\n     * Returns the calculated scalability modes for the video encodings when scalability modes are supported.\n     *\n     * @param {JitsiLocalTrack} localVideoTrack The local video track.\n     * @param {CodecMimeType} codec - The codec currently in use.\n     * @param {number} maxHeight The resolution requested for the video track.\n     * @returns {Optional<Array<VideoEncoderScalabilityMode>>}\n     * @internal\n     */\n    calculateEncodingsScalabilityMode(localVideoTrack: JitsiLocalTrack, codec: CodecMimeType, maxHeight: number): Optional<Optional<VideoEncoderScalabilityMode>[]> {\n        if (!this.codecSettings[codec].scalabilityModeEnabled) {\n            return;\n        }\n\n        // Use LIT3 for P2P wherever its supported.\n        if (!this.pc.isSpatialScalabilityOn()) {\n            return [ VideoEncoderScalabilityMode.L1T3 ];\n        }\n\n        // Default modes for simulcast.\n        const scalabilityModes = [\n            VideoEncoderScalabilityMode.L1T3,\n            VideoEncoderScalabilityMode.L1T3,\n            VideoEncoderScalabilityMode.L1T3\n        ];\n\n        // Full SVC mode.\n        if (this._isRunningInFullSvcMode(codec)) {\n            const { scalabilityMode }\n                = this._calculateActiveEncodingParams(localVideoTrack, codec, maxHeight);\n\n            scalabilityModes[0] = scalabilityMode as VideoEncoderScalabilityMode;\n            scalabilityModes[1] = undefined;\n            scalabilityModes[2] = undefined;\n\n            return scalabilityModes;\n        }\n\n        return scalabilityModes;\n    }\n\n    /**\n     * Returns the scale factor that needs to be applied on the local video stream based on the desired resolution\n     * and the codec in use.\n     *\n     * @param {JitsiLocalTrack} localVideoTrack The local video track.\n     * @param {CodecMimeType} codec - The codec currently in use.\n     * @param {number} maxHeight The resolution requested for the video track.\n     * @returns {Array<float>}\n     * @internal\n     */\n    calculateEncodingsScaleFactor(localVideoTrack: JitsiLocalTrack, codec: CodecMimeType, maxHeight: number): number[] {\n        if (this.pc.isSpatialScalabilityOn() && this.isRunningInSimulcastMode(codec)) {\n            return this._getVideoStreamEncodings(localVideoTrack, codec)\n                .map(encoding => encoding.scaleResolutionDownBy);\n        }\n\n        // Single video stream.\n        const { scaleResolutionDownBy }\n            = this._calculateActiveEncodingParams(localVideoTrack, codec, maxHeight);\n\n        return [ scaleResolutionDownBy, undefined, undefined ];\n    }\n\n    /**\n     * Ensures that the ssrcs associated with a FID ssrc-group appear in the correct order, i.e., the primary ssrc\n     * first and the secondary rtx ssrc later. This is important for unified plan since we have only one FID group per\n     * media description.\n     * @param {Object} description the webRTC session description instance for the remote description.\n     * @returns {Object} the modified webRTC session description instance.\n     * @internal\n     */\n    ensureCorrectOrderOfSsrcs(description: RTCSessionDescription) {\n        const parsedSdp = transform.parse(description.sdp);\n\n        parsedSdp.media.forEach(mLine => {\n            if (mLine.type === MediaType.AUDIO) {\n                return;\n            }\n            if (!mLine.ssrcGroups?.length) {\n                return;\n            }\n            let reorderedSsrcs = [];\n\n            const ssrcs = new Set();\n\n            mLine.ssrcGroups.map(group =>\n                group.ssrcs\n                    .split(' ')\n                    .filter(Boolean)\n                    .forEach(ssrc => ssrcs.add(ssrc))\n            );\n\n            ssrcs.forEach(ssrc => {\n                const sources = mLine.ssrcs.filter(source => source.id.toString() === ssrc);\n\n                reorderedSsrcs = reorderedSsrcs.concat(sources);\n            });\n            mLine.ssrcs = reorderedSsrcs;\n        });\n\n        return new RTCSessionDescription({\n            sdp: transform.write(parsedSdp),\n            type: description.type\n        });\n    }\n\n    /**\n     * Returns the codec that is configured on the client as the preferred video codec for the given local video track.\n     *\n     * @param {JitsiLocalTrack} localTrack - The local video track.\n     * @returns {CodecMimeType} The codec that is set as the preferred codec for the given local video track.\n     * @internal\n     */\n    getConfiguredVideoCodec(localTrack: JitsiLocalTrack): CodecMimeType | string {\n        const localVideoTrack = localTrack ?? this.pc.getLocalVideoTracks()[0];\n        const rtpSender = this.pc.findSenderForTrack(localVideoTrack.getTrack());\n\n        if (this.pc.usesCodecSelectionAPI() && rtpSender) {\n            // added any to remove the subsequrnt @ts-ignore comments\n            const { encodings } = rtpSender.getParameters() as any;\n\n            if (encodings[0].codec) {\n                return encodings[0].codec.mimeType.split('/')[1].toLowerCase();\n            }\n        }\n\n        const sdp = this.pc.remoteDescription?.sdp;\n\n        if (!sdp) {\n            return CodecMimeType.VP8;\n        }\n        const parsedSdp = transform.parse(sdp);\n        const mLine = parsedSdp.media\n            .find(m => m.mid.toString() === this.pc.localTrackTransceiverMids.get(localVideoTrack.rtcId));\n        const payload = mLine.payloads.split(' ')[0];\n        const { codec } = mLine.rtp.find(rtp => rtp.payload === Number(payload));\n\n        if (codec) {\n            return Object.values(CodecMimeType).find(value => value === codec.toLowerCase());\n        }\n\n        return CodecMimeType.VP8;\n    }\n\n    /**\n     * Returns the codecs in the current order of preference as configured on the peerconnection.\n     *\n     * @param {string} - The local SDP to be used.\n     * @returns {Array}\n     * @internal\n     */\n    getConfiguredVideoCodecs(sdp: Optional<string>): CodecMimeType[] {\n        const currentSdp = sdp ?? this.pc.localDescription?.sdp;\n\n        if (!currentSdp) {\n            return [];\n        }\n        const parsedSdp = transform.parse(currentSdp);\n\n        return this._getConfiguredVideoCodecsImpl(parsedSdp);\n    }\n\n    /**\n     * Returns the desired media direction for the given media type based on the current state of the peerconnection.\n     *\n     * @param {MediaType} mediaType - The media type for which the desired media direction is to be obtained.\n     * @param {boolean} isAddOperation - Whether the direction is being set for a source add operation.\n     * @returns {MediaDirection} - The desired media direction for the given media type.\n     * @internal\n     */\n    getDesiredMediaDirection(mediaType: MediaType, isAddOperation = false): MediaDirection {\n        const hasLocalSource = this.pc.getLocalTracks(mediaType).length > 0;\n\n        if (isAddOperation) {\n            return hasLocalSource ? MediaDirection.SENDRECV : MediaDirection.SENDONLY;\n        }\n\n        return hasLocalSource ? MediaDirection.RECVONLY : MediaDirection.INACTIVE;\n    }\n\n    /**\n     * Obtains stream encodings that need to be configured on the given track based\n     * on the track media type and the simulcast setting.\n     * @param {JitsiLocalTrack} localTrack\n     * @internal\n     */\n    getStreamEncodings(localTrack: JitsiLocalTrack): Partial<IRTCRtpEncodingParameters>[] {\n        if (localTrack.isAudioTrack()) {\n            return [ { active: this.pc.audioTransferActive } ];\n        }\n        const codec = this.getConfiguredVideoCodec(localTrack);\n\n        if (this.pc.isSpatialScalabilityOn()) {\n            return this._getVideoStreamEncodings(localTrack, codec);\n        }\n\n        return [ {\n            active: this.pc.videoTransferActive,\n            maxBitrate: this.codecSettings[codec].maxBitratesVideo.high\n        } ];\n    }\n\n    /**\n     * Injects a 'SIM' ssrc-group line for simulcast into the given session description object to make Jicofo happy.\n     * This is needed only for Firefox since it does not generate it when simulcast is enabled but we run the check\n     * on all browsers just in case as it would break the functionality otherwise.\n     *\n     * @param desc A session description object (with 'type' and 'sdp' fields)\n     * @return A session description object with its sdp field modified to contain an inject ssrc-group for simulcast.\n     * @internal\n     */\n    injectSsrcGroupForSimulcast(desc: RTCSessionDescription): RTCSessionDescription {\n        const sdp = transform.parse(desc.sdp);\n        const videoMlines = sdp.media.filter(mline => mline.type === 'video');\n        let modified = false;\n\n        for (const video of videoMlines) {\n            if (!(video.simulcast || video.simulcast_03)) {\n                continue;\n            }\n            video.ssrcGroups = video.ssrcGroups || [];\n            if (video.ssrcGroups.find(group => group.semantics === SSRC_GROUP_SEMANTICS.SIM)) {\n                continue;\n            }\n            const fidGroups = video.ssrcGroups.filter(group => group.semantics === SSRC_GROUP_SEMANTICS.FID);\n            const ssrcs = [];\n\n            if (fidGroups?.length) {\n                fidGroups.forEach(group => {\n                    ssrcs.push(group.ssrcs.split(' ')[0]);\n                });\n            } else if (video.ssrcs) {\n                video.ssrcs.forEach(ssrc => {\n                    if (ssrc.attribute === 'msid') {\n                        ssrcs.push(ssrc.id);\n                    }\n                });\n            }\n\n            // Add a SIM group for every 3 FID groups.\n            for (let i = 0; i < ssrcs.length; i += 3) {\n                const simSsrcs = ssrcs.slice(i, i + 3);\n\n                video.ssrcGroups.push({\n                    semantics: SSRC_GROUP_SEMANTICS.SIM,\n                    ssrcs: simSsrcs.join(' ')\n                });\n                modified = true;\n            }\n        }\n\n        if (!modified) {\n            return desc;\n        }\n\n        return new RTCSessionDescription({\n            sdp: transform.write(sdp),\n            type: desc.type\n        });\n    }\n\n    /**\n     * Takes in a *unified plan* offer and inserts the appropriate parameters for adding simulcast receive support.\n     * @param {Object} desc - A session description object\n     * @param {String} desc.type - the type (offer/answer)\n     * @param {String} desc.sdp - the sdp content\n     * @internal\n     * @return {Object} A session description (same format as above) object with its sdp field modified to advertise\n     * simulcast receive support.\n     */\n    insertUnifiedPlanSimulcastReceive(desc: RTCSessionDescription): RTCSessionDescription {\n        // a=simulcast line is not needed on browsers where we SDP munging is used for enabling on simulcast.\n        // Remove this check when the client switches to RID/MID based simulcast on all browsers.\n        if (browser.usesSdpMungingForSimulcast()) {\n            return desc;\n        }\n        const rids = [\n            {\n                direction: 'recv',\n                id: SIM_LAYERS[0].rid\n            },\n            {\n                direction: 'recv',\n                id: SIM_LAYERS[1].rid\n            },\n            {\n                direction: 'recv',\n                id: SIM_LAYERS[2].rid\n            }\n        ];\n\n        const ridLine = rids.map(val => val.id).join(';');\n        const simulcastLine = `recv ${ridLine}`;\n        const sdp = transform.parse(desc.sdp);\n        const mLines = sdp.media.filter(m => m.type === MediaType.VIDEO);\n        const senderMids = Array.from(this.pc.localTrackTransceiverMids.values());\n\n        mLines.forEach((mLine, idx) => {\n            // FF 110+: recvonly slots reserved for local senders that haven't been registered yet\n            // (e.g., secondary sources before replaceTrack runs) also need simulcast info.\n            const isSenderMline = Boolean(senderMids.find(sender => mLine.mid.toString() === sender.toString()))\n                || idx === 0\n                || (browser.supportsEncodingsConfig() && mLine.direction === MediaDirection.RECVONLY);\n\n            if (isSenderMline) {\n                if (!mLine.simulcast_03 || !mLine.simulcast) {\n                    mLine.rids = rids;\n\n                    // eslint-disable-next-line camelcase\n                    mLine.simulcast_03 = {\n                        value: simulcastLine\n                    };\n                }\n            } else {\n                mLine.rids = undefined;\n                mLine.simulcast = undefined;\n\n                // eslint-disable-next-line camelcase\n                mLine.simulcast_03 = undefined;\n            }\n        });\n\n        return new RTCSessionDescription({\n            sdp: transform.write(sdp),\n            type: desc.type\n        });\n    }\n\n    /**\n     * Returns a boolean indicating whether the video encoder is running in Simulcast mode, i.e., three encodings need\n     * to be configured in 4:2:1 resolution order with temporal scalability.\n     *\n     * @param {CodecMimeType} videoCodec - The video codec in use.\n     * @returns {boolean}\n     * @internal\n     */\n    isRunningInSimulcastMode(videoCodec: CodecMimeType): boolean {\n        if (!this.codecSettings?.[videoCodec]) {\n            // If codec settings are not available, assume no simulcast\n            return false;\n        }\n\n        return videoCodec === CodecMimeType.VP8 // VP8 always\n\n            // For FF: scalabilityModeEnabled is not supported and we have to use simulcast.\n            // For other browsers we use K-SVC mode for VP9 when no scalability mode is set. Although\n            // only one outbound-rtp stream is present, three separate encodings have to be configured.\n            || (!this.codecSettings[videoCodec].scalabilityModeEnabled && videoCodec === CodecMimeType.VP9)\n\n            // FF uses simulcast with AV1.\n            || (!this.codecSettings[videoCodec].scalabilityModeEnabled\n                && this.codecSettings[videoCodec].useSimulcast\n                && videoCodec === CodecMimeType.AV1)\n\n            // When scalability is enabled, always for H.264, and only when simulcast is explicitly enabled via\n            // config.js for VP9 and AV1 since full SVC is the default mode for these 2 codecs.\n            || (this.codecSettings[videoCodec].scalabilityModeEnabled\n                && (videoCodec === CodecMimeType.H264 || this.codecSettings[videoCodec].useSimulcast));\n    }\n\n    /**\n     * Munges the session description to ensure that the codec order is as per the preferred codec settings.\n     *\n     * @param {SessionDescription} parsedSdp that needs to be munged\n     * @returns {SessionDescription} the munged SDP.\n     * @internal\n     */\n    mungeCodecOrder(parsedSdp: SessionDescription): SessionDescription {\n        const codecSettings = this.pc.codecSettings;\n\n        if (!codecSettings) {\n            return parsedSdp;\n        }\n\n        const mungedSdp = parsedSdp;\n        const { isP2P } = this.options;\n        const mLines = mungedSdp.media.filter(m => m.type === codecSettings.mediaType);\n\n        for (const mLine of mLines) {\n            const currentCodecs = this._getConfiguredVideoCodecsImpl(mungedSdp);\n\n            for (const codec of currentCodecs) {\n                if (isP2P) {\n                    // 1. Strip the high profile H264 codecs on all clients. macOS started offering encoder for H.264\n                    //   level 5.2 but a decoder only for level 3.1. Therfore, strip all main and high level codecs for\n                    //   H.264.\n                    // 2. There are multiple VP9 payload types generated by the browser, more payload types are added\n                    //   if the endpoint doesn't have a local video source. Therefore, strip all the high profile codec\n                    //   variants for VP9 so that only one payload type for VP9 is negotiated between the peers.\n                    if (codec === CodecMimeType.H264 || codec === CodecMimeType.VP9) {\n                        SDPUtil.stripCodec(mLine, codec, true /* high profile */);\n                    }\n\n                    // Do not negotiate ULPFEC and RED either.\n                    if (codec === CodecMimeType.ULPFEC || codec === CodecMimeType.RED) {\n                        SDPUtil.stripCodec(mLine, codec, false);\n                    }\n                }\n            }\n\n            // Reorder the codecs based on the preferred settings.\n            if (!this.pc.usesCodecSelectionAPI()) {\n                for (const codec of codecSettings.codecList.slice().reverse()) {\n                    SDPUtil.preferCodec(mLine, codec, isP2P);\n                }\n            }\n        }\n\n        return mungedSdp;\n    }\n\n    /**\n     * Munges the stereo flag as well as the opusMaxAverageBitrate in the SDP, based on values set through config.js,\n     * if present.\n     *\n     * @param {SessionDescription} parsedSdp that needs to be munged.\n     * @param {IAppliedAudioQuality} audioQuality - The audio quality settings applied on the peer connection.\n     * @returns {SessionDescription} the munged SDP.\n     * @internal\n     */\n    mungeOpus(parsedSdp: SessionDescription, audioQuality?: IAppliedAudioQuality): SessionDescription {\n        if (!audioQuality\n            || (typeof audioQuality.enableOpusDtx !== 'boolean'\n                && typeof audioQuality.stereo !== 'boolean'\n                && typeof audioQuality.opusMaxAverageBitrate !== 'number')) {\n            return parsedSdp;\n        }\n\n        const mungedSdp = parsedSdp;\n        const mLines = mungedSdp.media.filter(m => m.type === MediaType.AUDIO);\n\n        for (const mLine of mLines) {\n            const { payload } = mLine.rtp.find(protocol => protocol.codec === CodecMimeType.OPUS);\n\n            if (!payload) {\n                // eslint-disable-next-line no-continue\n                continue;\n            }\n\n            let fmtpOpus = mLine.fmtp.find(protocol => protocol.payload === payload);\n\n            if (!fmtpOpus) {\n                fmtpOpus = {\n                    config: '',\n                    payload\n                };\n            }\n\n            const fmtpConfig = transform.parseParams(fmtpOpus.config);\n            let sdpChanged = false;\n\n            if (typeof audioQuality?.stereo === 'boolean') {\n                fmtpConfig.stereo = audioQuality.stereo ? 1 : 0;\n                fmtpConfig['sprop-stereo'] = audioQuality.stereo ? 1 : 0;\n                sdpChanged = true;\n            }\n\n            if (typeof audioQuality?.opusMaxAverageBitrate === 'number') {\n                fmtpConfig.maxaveragebitrate = audioQuality.opusMaxAverageBitrate;\n                sdpChanged = true;\n            }\n\n            // On Firefox, the OpusDtx enablement has no effect\n            if (!browser.isFirefox() && audioQuality?.enableOpusDtx) {\n                fmtpConfig.usedtx = 1;\n                sdpChanged = true;\n            }\n\n            if (!sdpChanged) {\n                // eslint-disable-next-line no-continue\n                continue;\n            }\n\n            let mungedConfig = '';\n\n            for (const key of Object.keys(fmtpConfig)) {\n                mungedConfig += `${key}=${fmtpConfig[key]}; `;\n            }\n\n            fmtpOpus.config = mungedConfig.trim();\n        }\n\n        return mungedSdp;\n    }\n\n    /**\n     * Munges the session SDP by setting the max bitrates on the video m-lines when VP9 K-SVC codec is in use.\n     *\n     * @param {SessionDescription} parsedSdp that needs to be munged.\n     * @param {boolean} isLocalSdp - Whether the max bitrate (via b=AS line in SDP) is set on local SDP.\n     * @returns {SessionDescription} The munged SDP.\n     * @internal\n     */\n    setMaxBitrates(parsedSdp: SessionDescription, isLocalSdp = false): SessionDescription {\n        const pcCodecSettings = this.pc.codecSettings;\n\n        if (!pcCodecSettings) {\n            return parsedSdp;\n        }\n\n        // Find all the m-lines associated with the local sources.\n        const mungedSdp = parsedSdp;\n        const direction = isLocalSdp ? MediaDirection.RECVONLY : MediaDirection.SENDONLY;\n        const mLines = mungedSdp.media.filter(m => m.type === MediaType.VIDEO && m.direction !== direction);\n        const currentCodec = pcCodecSettings.codecList[0];\n        const codecScalabilityModeSettings = this.codecSettings[currentCodec];\n\n        for (const mLine of mLines) {\n            const isDoingVp9KSvc = currentCodec === CodecMimeType.VP9\n                && !codecScalabilityModeSettings.scalabilityModeEnabled;\n            const localTrack = this.pc.getLocalVideoTracks()\n                .find(track => this.pc.localTrackTransceiverMids.get(track.rtcId) === mLine.mid.toString());\n\n            if (localTrack\n                && (isDoingVp9KSvc\n\n                    // Setting bitrates in the SDP for SVC codecs is no longer needed in the newer versions where\n                    // maxBitrates from the RTCRtpEncodingParameters directly affect the target bitrate for the encoder.\n                    || (this._isRunningInFullSvcMode(currentCodec) && !this.pc.usesCodecSelectionAPI()))) {\n                let maxBitrate;\n\n                if (localTrack.getVideoType() === VideoType.DESKTOP) {\n                    maxBitrate = codecScalabilityModeSettings.maxBitratesVideo.ssHigh;\n                } else {\n                    const { level } = VIDEO_QUALITY_LEVELS.find(lvl => lvl.height <= localTrack.getCaptureResolution());\n\n                    maxBitrate = codecScalabilityModeSettings.maxBitratesVideo[level];\n                }\n\n                const limit = Math.floor(maxBitrate / 1000);\n\n                // Use only the highest spatial layer bitrates for now as there is no API available yet for configuring\n                // the bitrates on the individual SVC layers.\n                mLine.bandwidth = [ {\n                    limit,\n                    type: 'AS'\n                } ];\n            } else {\n                // Clear the bandwidth limit in SDP when VP9 is no longer the preferred codec.\n                // This is needed on react native clients as react-native-webrtc returns the\n                // SDP that the application passed instead of returning the SDP off the native side.\n                // This line automatically gets cleared on web on every renegotiation.\n                mLine.bandwidth = undefined;\n            }\n        }\n\n        return mungedSdp;\n    }\n}\n","import { getLogger } from '@jitsi/logger';\nimport { cloneDeep } from 'lodash-es';\nimport transform from 'sdp-transform';\n\nimport { CodecMimeType } from '../../service/RTC/CodecMimeType';\nimport { MediaDirection } from '../../service/RTC/MediaDirection';\nimport { MediaType } from '../../service/RTC/MediaType';\nimport { RTCEvents } from '../../service/RTC/RTCEvents';\nimport { SignalingEvents } from '../../service/RTC/SignalingEvents';\nimport SignalingLayer, { getSourceIndexFromSourceName, isTranslatedSourceName } from '../../service/RTC/SignalingLayer';\nimport { SSRC_GROUP_SEMANTICS, VIDEO_QUALITY_LEVELS } from '../../service/RTC/StandardVideoQualitySettings';\nimport { VideoEncoderScalabilityMode } from '../../service/RTC/VideoEncoderScalabilityMode';\nimport { VideoType } from '../../service/RTC/VideoType';\nimport { AnalyticsEvents } from '../../service/statistics/AnalyticsEvents';\nimport RTCStats from '../RTCStats/RTCStats';\nimport { RTCStatsEvents } from '../RTCStats/RTCStatsEvents';\nimport browser from '../browser';\nimport FeatureFlags from '../flags/FeatureFlags';\nimport LocalSdpMunger from '../sdp/LocalSdpMunger';\nimport RtxModifier from '../sdp/RtxModifier';\nimport SDP from '../sdp/SDP';\nimport SDPUtil from '../sdp/SDPUtil';\nimport SdpSimulcast from '../sdp/SdpSimulcast';\nimport { SdpTransformWrap } from '../sdp/SdpTransformUtil';\nimport { ISsrcGroupInfo, ISsrcInfo } from '../sdp/constants';\nimport Statistics from '../statistics/statistics';\nimport EventEmitter from '../util/EventEmitter';\nimport { isValidNumber } from '../util/MathUtil';\n\nimport JitsiLocalTrack from './JitsiLocalTrack';\nimport JitsiRemoteTrack from './JitsiRemoteTrack';\nimport RTC from './RTC';\nimport RTCUtils from './RTCUtils';\nimport { SS_DEFAULT_FRAME_RATE } from './ScreenObtainer';\nimport { ICodecConfig, TPCUtils } from './TPCUtils';\n\n\nconst logger = getLogger('rtc:TraceablePeerConnection');\nconst DEGRADATION_PREFERENCE_CAMERA = 'maintain-framerate';\nconst DEGRADATION_PREFERENCE_DESKTOP = 'maintain-resolution';\n\n/**\n * Interface for legacy WebRTC stats report (pre-standard)\n */\ninterface ILegacyStatsReport {\n    id: string;\n    names: () => string[];\n    stat: (name: string) => string | number;\n}\n\n/**\n * Interface for legacy stats response with result() method\n */\ninterface ILegacyStatsResponse {\n    result: () => ILegacyStatsReport[];\n}\nexport interface IRTCRtpEncodingParameters extends RTCRtpEncodingParameters {\n    codec?: RTCRtpCodec;\n    degradationPreference?: string;\n    rid: string;\n    // Firefox only supports the non-standard way.\n    scalabilityMode?: VideoEncoderScalabilityMode;\n}\n\n/**\n * Union type for getStats() return value (legacy vs modern)\n */\ntype StatsResponse = RTCStatsReport | ILegacyStatsResponse;\n\ninterface ITouchToneRequest {\n    duration: number;\n    interToneGap: number;\n    tones: string;\n}\n\nexport interface ITPCSourceInfo {\n    groups?: Array<ISsrcGroupInfo>;\n    mediaType?: MediaType;\n    mid?: string;\n    msid?: string;\n    ssrcList?: Array<string>;\n    ssrcs?: Array<string>;\n    videoType?: VideoType;\n}\n\nexport interface ITPCOptions {\n    audioQuality: IAudioQuality;\n    capScreenshareBitrate: boolean;\n    codecSettings: ICodecSettings;\n    disableRtx: boolean;\n    disableSimulcast: boolean;\n    maxstats: number;\n    startSilent: boolean;\n    usesCodecSelectionAPI: boolean;\n    videoQuality: IVideoQuality;\n}\n\nexport interface IAudioQuality {\n    enableOpusDtx?: boolean;\n    opusMaxAverageBitrate?: number;\n    opusMaxAverageBitrateMono?: number;\n    opusMaxAverageBitrateStereo?: number;\n    stereo?: boolean;\n}\n\nexport interface IAppliedAudioQuality {\n    enableOpusDtx?: boolean;\n    opusMaxAverageBitrate?: number;\n    stereo?: boolean;\n}\n\nexport interface IVideoQuality {\n    desktopbitrate?: number;\n    maxBitratesVideo?: Record<string, number>;\n    preferredCodec?: CodecMimeType;\n    [CodecMimeType.AV1]?: ICodecConfig;\n    [CodecMimeType.H264]?: ICodecConfig;\n    [CodecMimeType.VP8]?: ICodecConfig;\n    [CodecMimeType.VP9]?: ICodecConfig;\n    maxbitratesvideo?: {\n        [codec: string]: {\n            [quality: string]: number;\n        };\n    };\n}\n\nexport interface ICodecSettings {\n    codecList: CodecMimeType[];\n    mediaType?: MediaType;\n    screenshareCodec?: CodecMimeType;\n}\n\ninterface IUpdateLogEntry {\n    time: Date;\n    type: string;\n    value: string;\n}\n\ninterface IStatsEntry {\n    endTime: Date;\n    startTime: Date;\n    times: number[];\n    values: any[];\n}\n\ninterface ITraceFunction {\n    (what: string, info?: string, opts?: any): void;\n}\n\n\n/* eslint-disable max-params */\n/**\n * Creates new instance of 'TraceablePeerConnection'.\n */\nexport default class TraceablePeerConnection {\n    // Private properties\n    private _dtmfSender?: RTCDTMFSender;\n    private _dtmfTonesQueue: ITouchToneRequest[];\n    private _dtlsTransport?: RTCDtlsTransport;\n    private _usesCodecSelectionAPI: boolean;\n    private _senderMaxHeights: Map<string, number>;\n    private _localSsrcMap?: Map<string, ISsrcInfo>;\n    private _remoteSsrcMap: Map<string, ITPCSourceInfo>;\n    private _lastVideoSenderUpdatePromise: Promise<void>;\n    private _localUfrag: string;\n    private _pcId: string;\n    private _remoteUfrag: string;\n    private _signalingLayer: SignalingLayer;\n    /**\n     * @internal\n     */\n    _capScreenshareBitrate: boolean;\n    /**\n     * Mids of transceivers that have ever carried a local sender track. Never cleared on mute/remove\n     * so LocalSdpMunger can preserve the SSRCs of previously-active sender slots.\n     * @internal\n     */\n    _midsWithSentTrack: Set<string>;\n\n    // public property declarations\n    audioTransferActive: boolean;\n    audioQualityLocal: Optional<IAppliedAudioQuality>;\n    audioQualityRemote: Optional<IAppliedAudioQuality>;\n    videoTransferActive: boolean;\n    id: number;\n    isP2P: boolean;\n    remoteTracksBySsrc: Map<number, JitsiRemoteTrack>;\n    remoteTracks: Map<string, Map<MediaType, Set<JitsiRemoteTrack>>>;\n    localTracks: Map<number, JitsiLocalTrack>;\n    localSSRCs: Map<number, ISsrcInfo>;\n    remoteSSRCs: Set<number>;\n    remoteSources: Map<string, number>;\n    options: ITPCOptions;\n    peerconnection: RTCPeerConnection;\n    tpcUtils: TPCUtils;\n    updateLog: Array<IUpdateLogEntry>;\n    stats: Record<string, IStatsEntry>;\n    statsinterval?: number;\n    simulcast: SdpSimulcast;\n    localSdpMunger: LocalSdpMunger;\n    eventEmitter: EventEmitter;\n    rtxModifier: RtxModifier;\n    localTrackTransceiverMids: Map<number, string>;\n    codecSettings: ICodecSettings;\n    maxstats: number;\n    rtc: RTC;\n    trace: ITraceFunction;\n    onicecandidate?: ((event: RTCPeerConnectionIceEvent) => void);\n    onTrack: (evt: RTCTrackEvent) => void;\n    onsignalingstatechange?: ((event: Event) => void);\n    oniceconnectionstatechange?: ((event: Event) => void);\n    onnegotiationneeded?: ((event: Event) => void);\n    onconnectionstatechange?: ((event: Event) => void);\n    ondatachannel?: ((event: RTCDataChannelEvent) => void);\n\n    /**\n     * @param {RTC} rtc the instance of <tt>RTC</tt> service\n     * @param {number} id the peer connection id assigned by the parent RTC module.\n     * @param {SignalingLayer} signalingLayer the signaling layer instance\n     * @param {object} pcConfig The {@code RTCConfiguration} to use for the WebRTC peer connection.\n     * @param {object} constraints WebRTC 'PeerConnection' constraints\n     * @param {boolean} isP2P indicates whether or not the new instance will be used in a peer to peer connection.\n     * @param {object} options <tt>TracablePeerConnection</tt> config options.\n     * @param {Object} options.audioQuality - Quality settings to applied on the outbound audio stream.\n     * @param {boolean} options.capScreenshareBitrate if set to true, lower layers will be disabled for screenshare.\n     * @param {Array<CodecMimeType>} options.codecSettings - codec settings to be applied for video streams.\n     * @param {boolean} options.disableSimulcast if set to 'true' will disable the simulcast.\n     * @param {boolean} options.disableRtx if set to 'true' will disable the RTX.\n     * @param {boolean} options.enableInsertableStreams set to true when the insertable streams constraints is to be\n     * enabled on the PeerConnection.\n     * @param {boolean} options.forceTurnRelay If set to true, the browser will generate only Relay ICE candidates.\n     * @param {boolean} options.startSilent If set to 'true' no audio will be sent or received.\n     * @param {Object} options.videoQuality - Quality settings to applied on the outbound video streams.\n     *\n     * FIXME: initially the purpose of TraceablePeerConnection was to be able to\n     * debug the peer connection. Since many other responsibilities have been added\n     * it would make sense to extract a separate class from it and come up with\n     * a more suitable name.\n     *\n     * @constructor\n     */\n    constructor(\n            rtc: RTC,\n            id: number,\n            signalingLayer: SignalingLayer,\n            pcConfig: RTCConfiguration,\n            constraints: { optional?: any[]; },\n            isP2P: boolean,\n            options: ITPCOptions\n    ) {\n        /**\n         * Indicates whether or not this peer connection instance is actively\n         * sending/receiving audio media. When set to <tt>false</tt> the SDP audio\n         * media direction will be adjusted to 'inactive' in order to suspend\n         * the transmission.\n         * @type {boolean}\n         * @internal\n         */\n        this.audioTransferActive = !(options.startSilent === true);\n\n        /**\n         * The DTMF sender instance used to send DTMF tones.\n         *\n         * @type {RTCDTMFSender|undefined}\n         * @private\n         */\n        this._dtmfSender = undefined;\n\n        /**\n         * @typedef {Object} TouchToneRequest\n         * @property {string} tones - The DTMF tones string as defined by\n         * {@code RTCDTMFSender.insertDTMF}, 'tones' argument.\n         * @property {number} duration - The amount of time in milliseconds that\n         * each DTMF should last.\n         * @property {string} interToneGap - The length of time in miliseconds to\n         * wait between tones.\n         */\n        /**\n         * TouchToneRequests which are waiting to be played. This queue is filled\n         * if there are touch tones currently being played.\n         *\n         * @type {Array<TouchToneRequest>}\n         * @private\n         */\n        this._dtmfTonesQueue = [];\n\n        /**\n         * Indicates whether or not this peer connection instance is actively\n         * sending/receiving video media. When set to <tt>false</tt> the SDP video\n         * media direction will be adjusted to 'inactive' in order to suspend\n         * the transmission.\n         * @type {boolean}\n         * @internal\n         */\n        this.videoTransferActive = true;\n\n        /**\n         * The parent instance of RTC service which created this\n         * <tt>TracablePeerConnection</tt>.\n         * @type {RTC}\n         */\n        this.rtc = rtc;\n\n        /**\n         * The peer connection identifier assigned by the RTC module.\n         * @type {number}\n         */\n        this.id = id;\n\n        /**\n         * RTCStats identifier for this peerconnection.\n         */\n        this._pcId = `PC_${this.id}`;\n\n        /**\n         * Indicates whether or not this instance is used in a peer to peer\n         * connection.\n         * @type {boolean}\n         */\n        this.isP2P = isP2P;\n\n        /**\n         * A map that holds remote tracks signaled on the peerconnection indexed by their SSRC.\n         * @type {Map<number, JitsiRemoteTrack>}\n         */\n        this.remoteTracksBySsrc = new Map();\n\n        /**\n         * The map holds remote tracks associated with this peer connection.\n         * It maps user's JID to media type and a set of\n         * remote tracks.\n         * @type {Map<string, Map<MediaType, Set<JitsiRemoteTrack>>>}\n         */\n        this.remoteTracks = new Map();\n\n        /**\n         * A map which stores local tracks mapped by {@link JitsiLocalTrack.rtcId}\n         * @type {Map<number, JitsiLocalTrack>}\n         */\n        this.localTracks = new Map();\n\n        /**\n         * @typedef {Object} TPCGroupInfo\n         * @property {string} semantics the SSRC groups semantics\n         * @property {Array<number>} ssrcs group's SSRCs in order where the first\n         * one is group's primary SSRC, the second one is secondary (RTX) and so\n         * on...\n         */\n        /**\n         * @typedef {Object} TPCSSRCInfo\n         * @property {Array<number>} ssrcs an array which holds all track's SSRCs\n         * @property {Array<TPCGroupInfo>} groups an array stores all track's SSRC\n         * groups\n         */\n        /**\n         * Holds the info about local track's SSRCs mapped per their\n         * {@link JitsiLocalTrack.rtcId}\n         * @type {Map<number, TPCSSRCInfo>}\n         */\n        this.localSSRCs = new Map();\n\n        /**\n         * The set of remote SSRCs seen so far.\n         * Distinguishes new SSRCs from those that have been remapped.\n         * @type {Set<number>}\n         */\n        this.remoteSSRCs = new Set();\n\n        /**\n         * Mapping of source-names and their associated SSRCs that have been signaled by the JVB.\n         * @type {Map<string, number>}\n         */\n        this.remoteSources = new Map();\n\n        /**\n         * The local ICE username fragment for this session.\n         */\n        this._localUfrag = null;\n\n        /**\n         * The remote ICE username fragment for this session.\n         */\n        this._remoteUfrag = null;\n\n        /**\n         * The DTLS transport object for the PeerConnection.\n         * Note: this assume only one shared transport exists because we bundled\n         *       all streams on the same underlying transport.\n         */\n        this._dtlsTransport = null;\n\n        /**\n         * The signaling layer which operates this peer connection.\n         * @type {SignalingLayer}\n         */\n        this._signalingLayer = signalingLayer;\n\n        // SignalingLayer listeners\n        this._peerVideoTypeChanged = this._peerVideoTypeChanged.bind(this);\n        this._signalingLayer.on(SignalingEvents.PEER_VIDEO_TYPE_CHANGED, this._peerVideoTypeChanged);\n\n        this._peerMutedChanged = this._peerMutedChanged.bind(this);\n        this._signalingLayer.on(SignalingEvents.PEER_MUTED_CHANGED, this._peerMutedChanged);\n        this.options = options;\n\n        // Initialize audio quality from config\n        if (this.options?.audioQuality) {\n            const audioQualityConfig = this.options.audioQuality;\n            const stereo = typeof audioQualityConfig.stereo === 'boolean'\n                ? audioQualityConfig.stereo\n                : undefined;\n\n            // Determine maxaveragebitrate:\n            // - Prefer the explicit stereo/mono fields.\n            // - Fall back to the legacy opusMaxAverageBitrate if the new fields are unset.\n            const opusMaxAverageBitrate = stereo\n                ? (audioQualityConfig.opusMaxAverageBitrateStereo\n                    ?? audioQualityConfig.opusMaxAverageBitrateMono\n                    ?? audioQualityConfig.opusMaxAverageBitrate)\n                : (audioQualityConfig.opusMaxAverageBitrateMono\n                    ?? audioQualityConfig.opusMaxAverageBitrateStereo\n                    ?? audioQualityConfig.opusMaxAverageBitrate);\n\n            const audioQuality = {\n                enableOpusDtx: audioQualityConfig.enableOpusDtx,\n                opusMaxAverageBitrate,\n                stereo\n            };\n\n            this.audioQualityLocal = audioQuality;\n            this.audioQualityRemote = audioQuality;\n        }\n\n        // Setup SignalingLayer listeners for source-name based events.\n        this._signalingLayer.on(SignalingEvents.SOURCE_MUTED_CHANGED,\n            (sourceName, isMuted) => this._sourceMutedChanged(sourceName, isMuted));\n        this._signalingLayer.on(SignalingEvents.SOURCE_VIDEO_TYPE_CHANGED,\n            (sourceName, videoType) => this._sourceVideoTypeChanged(sourceName, videoType));\n\n        // Make sure constraints is properly formatted in order to provide information about whether or not this\n        // connection is P2P to rtcstats.\n        const safeConstraints = constraints || {};\n\n        safeConstraints.optional = safeConstraints.optional || [];\n\n        // The `optional` parameter needs to be of type array, otherwise chrome will throw an error.\n        // Firefox and Safari just ignore it.\n        if (Array.isArray(safeConstraints.optional)) {\n            safeConstraints.optional.push({ rtcStatsSFUP2P: this.isP2P });\n        } else {\n            logger.warn('Optional param is not an array, rtcstats p2p data is omitted.');\n        }\n\n        // RTCPeerConnection constructor only accepts RTCConfiguration\n        // @ts-ignore\n        this.peerconnection = new RTCPeerConnection(pcConfig, safeConstraints);\n\n        this.tpcUtils = new TPCUtils(this, {\n            audioQuality: options.audioQuality,\n            isP2P: this.isP2P,\n            videoQuality: options.videoQuality\n        });\n        this.updateLog = [];\n        this.stats = {};\n        this.statsinterval = null;\n\n        /**\n         * Flag used to indicate if low fps screenshare is desired.\n         */\n        this._capScreenshareBitrate = this.options.capScreenshareBitrate;\n\n        /**\n         * Codec preferences set for the peerconnection through config.js.\n         */\n        this.codecSettings = this.options.codecSettings;\n\n        /**\n         * Flag used to indicate if RTCRtpTransceiver#setCodecPreferences is to be used instead of SDP\n         * munging for codec selection.\n         */\n        browser.supportsCodecPreferences()\n            && logger.info('Using RTCRtpTransceiver#setCodecPreferences for codec selection');\n\n        /**\n         * Flag used to indicate if the codecs are configured using the codec selection API without having the need to\n         * trigger a renegotiation for the change to be effective.\n         */\n        this._usesCodecSelectionAPI = this.options.usesCodecSelectionAPI;\n\n        this._midsWithSentTrack = new Set<string>();\n\n        /**\n         * @type {number} The max number of stats to keep in this.stats. Limit to\n         * 300 values, i.e. 5 minutes; set to 0 to disable\n         */\n        this.maxstats = options.maxstats;\n\n        this.simulcast = new SdpSimulcast();\n\n        /**\n         * Munges local SDP provided to the Jingle Session in order to prevent from\n         * sending SSRC updates on attach/detach and mute/unmute (for video).\n         * @type {LocalSdpMunger}\n         */\n        this.localSdpMunger = new LocalSdpMunger(this, this.rtc.getLocalEndpointId());\n\n        /**\n         * TracablePeerConnection uses RTC's eventEmitter\n         * @type {EventEmitter}\n         */\n        this.eventEmitter = rtc.eventEmitter;\n        this.rtxModifier = new RtxModifier();\n\n        /**\n         * The height constraints to be applied on the sender per local video source (source name as the key).\n         * @type {Map<string, number>}\n         */\n        this._senderMaxHeights = new Map();\n\n        /**\n         * Holds the RTCRtpTransceiver mids that the local tracks are attached to, mapped per their\n         * {@link JitsiLocalTrack.rtcId}.\n         * @type {Map<string, string>}\n         */\n        this.localTrackTransceiverMids = new Map();\n\n        /**\n         * Holds the SSRC map for the local tracks mapped by their source names.\n         *\n         * @type {Map<string, TPCSourceInfo>}\n         * @property {string} msid - The track's MSID.\n         * @property {Array<string>} ssrcs - The SSRCs associated with the track.\n         * @property {Array<TPCGroupInfo>} groups - The SSRC groups associated with the track.\n         */\n        this._localSsrcMap = null;\n\n        /**\n         * Holds the SSRC map for the remote tracks mapped by their source names.\n         *\n         * @type {Map<string, TPCSourceInfo>}\n         * @property {string} mediaType - The media type of the track.\n         * @property {string} msid - The track's MSID.\n         * @property {Array<TPCGroupInfo>} groups - The SSRC groups associated with the track.\n         * @property {Array<string>} ssrcList - The SSRCs associated with the track.\n         * @property {VideoType} videoType - The videoType of the track (undefined for audio tracks).\n         */\n        this._remoteSsrcMap = new Map();\n\n        // override as desired\n        this.trace = (what, info) => {\n            logger.trace(what, info);\n\n            this.updateLog.push({\n                time: new Date(),\n                type: what,\n                value: info || ''\n            });\n        };\n        this.onicecandidate = null;\n        this.peerconnection.onicecandidate = event => {\n            this.trace(\n                'onicecandidate',\n                JSON.stringify(event.candidate, null, ' '));\n\n            if (this.onicecandidate !== null) {\n                this.onicecandidate(event);\n            }\n        };\n\n        this.onTrack = evt => {\n            const stream = evt.streams[0];\n\n            this._remoteTrackAdded(stream, evt.track, evt.transceiver);\n            stream.addEventListener('removetrack', e => {\n                this._remoteTrackRemoved(stream, e.track);\n            });\n        };\n        this.peerconnection.addEventListener('track', this.onTrack);\n\n        this.onsignalingstatechange = null;\n        this.peerconnection.onsignalingstatechange = event => {\n            this.trace('onsignalingstatechange', this.signalingState);\n            if (this.onsignalingstatechange !== null) {\n                this.onsignalingstatechange(event);\n            }\n        };\n        this.oniceconnectionstatechange = null;\n        this.peerconnection.oniceconnectionstatechange = event => {\n            this.trace('oniceconnectionstatechange', this.iceConnectionState);\n            if (this.oniceconnectionstatechange !== null) {\n                this.oniceconnectionstatechange(event);\n            }\n        };\n        this.onnegotiationneeded = null;\n        this.peerconnection.onnegotiationneeded = event => {\n            this.trace('onnegotiationneeded');\n            if (this.onnegotiationneeded !== null) {\n                this.onnegotiationneeded(event);\n            }\n        };\n        this.onconnectionstatechange = null;\n        this.peerconnection.onconnectionstatechange = event => {\n            this.trace('onconnectionstatechange', this.connectionState);\n            if (this.onconnectionstatechange !== null) {\n                this.onconnectionstatechange(event);\n            }\n        };\n        this.ondatachannel = null;\n        this.peerconnection.ondatachannel = event => {\n            this.trace('ondatachannel');\n            if (this.ondatachannel !== null) {\n                this.ondatachannel(event);\n            }\n        };\n\n        if (this.maxstats) {\n            this.statsinterval = window.setInterval(() => {\n                this.getStats().then((stats: StatsResponse) => {\n                    if (typeof (stats as ILegacyStatsResponse)?.result === 'function') {\n                        const results = (stats as ILegacyStatsResponse).result();\n\n                        for (let i = 0; i < results.length; ++i) {\n                            const res = results[i];\n\n                            res.names().forEach(name => {\n                                this._processStat(res, name, res.stat(name));\n                            });\n                        }\n                    } else {\n                        (stats as RTCStatsReport).forEach(r => this._processStat(r, '', r));\n                    }\n                });\n            }, 1000);\n        }\n\n        this._lastVideoSenderUpdatePromise = Promise.resolve();\n\n        logger.info(`Create new ${this}`);\n    }\n\n\n    /**\n     * Returns a string representation of a SessionDescription object.\n     */\n    static dumpSDP = function(description: Optional<Nullable<RTCSessionDescription>>): string {\n        if (!description?.sdp) {\n            return '';\n        }\n\n        return `type: ${description.type}\\r\\n${description.sdp}`;\n    };\n\n    /**\n     * Returns the transceiver direction to apply to a sender when a local track is added to or removed from this\n     * peerconnection via {@link replaceTrack}.\n     *\n     * Two orthogonal Firefox workarounds share this helper:\n     *\n     * - On track addition: Firefox <= 153 does not honor <tt>encoding.active = false</tt> for audio senders\n     *   (https://bugzilla.mozilla.org/show_bug.cgi?id=1813848), so an audio sender is suspended via the transceiver\n     *   direction while audio transfer is inactive on this peerconnection (the JVB connection while the call is\n     *   routed over P2P). Otherwise an audio track added on unmute would be sent over the suspended JVB connection\n     *   and the remote peer would receive it twice (once over JVB, once over P2P). Only audio is handled this way:\n     *   video keeps using <tt>encoding.active</tt> so that simulcast / screenshare SDP and the P2P video path are\n     *   left untouched.\n     * - On track removal: Firefox does not rebuild the m-line if the direction goes to <tt>recvonly</tt>, so the\n     *   ssrcs from the removed track need to be preserved by keeping direction at <tt>sendrecv</tt>\n     *   (https://bugzilla.mozilla.org/show_bug.cgi?id=1768729). This still applies to all Firefox versions.\n     *\n     * @param {boolean} hasTrack - whether a local track is attached to the sender after the operation.\n     * @param {MediaType} mediaType - the media type of the local track.\n     * @param {boolean} mediaTransferActive - whether media transfer is active for the track's media type.\n     * @returns {MediaDirection}\n     */\n    static getTransceiverDirection(\n            hasTrack: boolean,\n            mediaType: Optional<MediaType>,\n            mediaTransferActive: boolean): MediaDirection {\n        if (hasTrack) {\n            return !browser.supportsRTCRtpEncodingParametersActiveForAudio()\n                    && mediaType === MediaType.AUDIO\n                    && !mediaTransferActive\n                ? MediaDirection.INACTIVE\n                : MediaDirection.SENDRECV;\n        }\n\n        return browser.isFirefox() ? MediaDirection.SENDRECV : MediaDirection.RECVONLY;\n    }\n\n    /**\n     * Returns the transceiver direction to apply to a Firefox sender when media transfer is suspended or resumed\n     * on this peerconnection (see {@link setMediaTransferActive}). Returns <tt>undefined</tt> when the direction\n     * should be left unchanged - i.e. when resuming a sender that has no local track attached, in which case the\n     * direction is set later by {@link replaceTrack} once a track is added.\n     *\n     * @param {boolean} enable - <tt>true</tt> when resuming media transfer, <tt>false</tt> when suspending it.\n     * @param {boolean} hasTrack - whether the sender has a local track attached.\n     * @returns {MediaDirection|undefined}\n     */\n    static getMediaTransferDirection(enable: boolean, hasTrack: boolean): Optional<MediaDirection> {\n        if (!enable) {\n            return MediaDirection.INACTIVE;\n        }\n\n        return hasTrack ? MediaDirection.SENDRECV : undefined;\n    }\n\n    /**\n     * Handles remote track mute / unmute events.\n     * @param {string} endpointId the track owner's identifier (MUC nickname)\n     * @param {MediaType} mediaType \"audio\" or \"video\"\n     * @param {boolean} isMuted the new mute state\n     * @private\n     */\n    private _peerMutedChanged(endpointId: string, mediaType: MediaType, isMuted: boolean): void {\n        // Check if endpointId is a value to avoid doing action on all remote tracks\n        if (!endpointId) {\n            logger.error(`${this} On peerMuteChanged - no endpoint ID`);\n\n            return;\n        }\n        const track = this.getRemoteTracks(endpointId, mediaType);\n\n        if (track.length) {\n            // NOTE 1 track per media type is assumed\n            track[0].setMute(isMuted);\n        }\n    }\n\n    /**\n     * Handles remote source videoType changed events.\n     *\n     * @param {string} sourceName - The name of the remote source.\n     * @param {boolean} isMuted - The new value.\n     */\n    private _sourceVideoTypeChanged(sourceName: string, videoType: VideoType): void {\n        const track = this.getRemoteTracks().slice().reverse().find(t => t.getSourceName() === sourceName);\n\n        if (!track) {\n            return;\n        }\n\n        track._setVideoType(videoType);\n    }\n\n\n    /**\n     * Configures the RTCRtpEncodingParameters of the outbound rtp stream associated with the given track.\n     *\n     * @param {JitsiLocalTracj} localTrack - The local track whose outbound stream needs to be configured.\n     * @returns {Promise} - A promise that resolves when the operation is successful, rejected otherwise.\n     */\n    private _configureSenderEncodings = async (localTrack: JitsiLocalTrack): Promise<void> => {\n        const mediaType = localTrack.getType();\n        const transceiver = localTrack?.track && localTrack.getOriginalStream()\n            ? this.peerconnection.getTransceivers().find(t => t.sender?.track?.id === localTrack.getTrackId())\n            : this.peerconnection.getTransceivers().find(t => t.receiver?.track?.kind === mediaType);\n        const parameters = transceiver?.sender?.getParameters() as RTCRtpSendParameters;\n\n        // Resolve if the encodings are not available yet. This happens immediately after the track is added to the\n        // peerconnection on chrome in unified-plan. It is ok to ignore and not report the error here since the\n        // action that triggers 'addTrack' (like unmute) will also configure the encodings and set bitrates after that.\n        if (!parameters?.encodings?.length) {\n            return;\n        }\n\n        const desiredEncodings = this.tpcUtils.getStreamEncodings(localTrack);\n\n        if (browser.supportsEncodingsConfig()) {\n            // FF 110+ rejects encodings length/rid changes; skip on mismatch to keep the call alive.\n            if (parameters.encodings.length !== desiredEncodings.length) {\n                return;\n            }\n            parameters.encodings.forEach((encoding: IRTCRtpEncodingParameters, idx: number) => {\n                const desired = desiredEncodings[idx];\n\n                if (!desired) {\n                    return;\n                }\n                if (desired.active !== undefined) {\n                    encoding.active = desired.active;\n                }\n                if (desired.maxBitrate !== undefined) {\n                    encoding.maxBitrate = desired.maxBitrate;\n                }\n                if (desired.scaleResolutionDownBy !== undefined) {\n                    encoding.scaleResolutionDownBy = desired.scaleResolutionDownBy;\n                }\n                if (desired.scalabilityMode !== undefined) {\n                    encoding.scalabilityMode = desired.scalabilityMode;\n                }\n            });\n        } else {\n            parameters.encodings = desiredEncodings as RTCRtpEncodingParameters[];\n        }\n\n        await transceiver.sender.setParameters(parameters);\n    };\n\n    /**\n     * Enables/disables the streams by changing the active field on RTCRtpEncodingParameters for a given RTCRtpSender.\n     *\n     * @param {RTCRtpSender} sender - the sender associated with a MediaStreamTrack.\n     * @param {boolean} enable - whether the streams needs to be enabled or disabled.\n     * @returns {Promise} - A promise that resolves when the operation is successful, rejected otherwise.\n     */\n    private _enableSenderEncodings = async (sender: RTCRtpSender, enable: boolean): Promise<void> => {\n        const parameters: RTCRtpSendParameters = sender.getParameters() as RTCRtpSendParameters;\n\n        if (parameters?.encodings?.length) {\n            for (const encoding of parameters.encodings) {\n                encoding.active = enable;\n            }\n        }\n\n        await sender.setParameters(parameters);\n\n        // Firefox <= 153 does not stop sending audio when only encoding.active is set to false\n        // (https://bugzilla.mozilla.org/show_bug.cgi?id=1813848), so an audio sender is suspended/resumed via the\n        // transceiver direction as well (see getMediaTransferDirection). Gated on the browser capability so the\n        // workaround drops out once Firefox 154+ ships the fix. Audio only - video keeps using encoding.active to\n        // avoid perturbing simulcast/screenshare SDP and the P2P video path.\n        if (!browser.supportsRTCRtpEncodingParametersActiveForAudio() && sender.track?.kind === MediaType.AUDIO) {\n            const transceiver = this.peerconnection.getTransceivers().find(t => t.sender === sender);\n            const direction = TraceablePeerConnection.getMediaTransferDirection(enable, Boolean(sender.track));\n\n            // direction is undefined when resuming a sender with no local track attached; leave it untouched so it\n            // gets set by replaceTrack when a track is added/removed.\n            if (transceiver && direction) {\n                transceiver.direction = direction;\n            }\n        }\n    };\n\n\n    /**\n     * Returns the list of RTCRtpReceivers created for the source of the given media type associated with\n     * the set of remote endpoints specified.\n     * @param {Array<string>} endpoints list of the endpoints\n     * @param {string} mediaType 'audio' or 'video'\n     * @returns {Array<RTCRtpReceiver>} list of receivers created by the peerconnection.\n     */\n    private _getReceiversByEndpointIds(endpoints: string[], mediaType: MediaType): RTCRtpReceiver[] {\n        let remoteTracks = [];\n        let receivers = [];\n\n        for (const endpoint of endpoints) {\n            remoteTracks = remoteTracks.concat(this.getRemoteTracks(endpoint, mediaType));\n        }\n\n        // Get the ids of the MediaStreamTracks associated with each of these remote tracks.\n        const remoteTrackIds = remoteTracks.map(remote => remote.track?.id);\n\n        receivers = this.peerconnection.getReceivers()\n            .filter(receiver => receiver.track?.kind === mediaType\n                && remoteTrackIds.find(trackId => trackId === receiver.track.id));\n\n        return receivers;\n    }\n\n\n    /**\n     * Handles {@link SignalingEvents.PEER_VIDEO_TYPE_CHANGED}\n     * @param {string} endpointId the video owner's ID (MUC nickname)\n     * @param {VideoType} videoType the new value\n     * @private\n     */\n    private _peerVideoTypeChanged(endpointId: string, videoType: VideoType): void {\n        // Check if endpointId has a value to avoid action on random track\n        if (!endpointId) {\n            logger.error(`${this} No endpointID on peerVideoTypeChanged`);\n\n            return;\n        }\n        const videoTrack = this.getRemoteTracks(endpointId, MediaType.VIDEO);\n\n        if (videoTrack.length) {\n            // NOTE 1 track per media type is assumed\n            videoTrack[0]._setVideoType(videoType);\n        }\n    }\n\n\n    /**\n     * Adjusts the media direction on the remote description based on availability of local and remote sources in a p2p\n     * media connection.\n     *\n     * @param {RTCSessionDescription} remoteDescription the WebRTC session description\n     *  instance for the remote description.\n     * @returns the transformed remoteDescription.\n     * @private\n     */\n    private _adjustRemoteMediaDirection(remoteDescription: RTCSessionDescription): RTCSessionDescription {\n        const transformer = new SdpTransformWrap(remoteDescription?.sdp);\n\n        [ MediaType.AUDIO, MediaType.VIDEO ].forEach(mediaType => {\n            const media = transformer.selectMedia(mediaType);\n            const localSources = this.getLocalTracks(mediaType).length;\n            const remoteSources = this.getRemoteTracks(null, mediaType).length;\n\n            media.forEach((mLine, idx) => {\n                if (localSources && localSources === remoteSources) {\n                    mLine.direction = MediaDirection.SENDRECV;\n                } else if (!localSources && !remoteSources) {\n                    mLine.direction = MediaDirection.INACTIVE;\n                } else if (!localSources) {\n                    mLine.direction = MediaDirection.SENDONLY;\n                } else if (!remoteSources) {\n                    mLine.direction = MediaDirection.RECVONLY;\n\n                // When there are 2 local sources and 1 remote source,\n                // the first m-line should be set to 'sendrecv' while\n                // the second one needs to be set to 'recvonly'.\n                } else if (localSources > remoteSources) {\n                    mLine.direction = idx ? MediaDirection.RECVONLY : MediaDirection.SENDRECV;\n\n                // When there are 2 remote sources and 1 local source, the first m-line\n                // should be set to 'sendrecv' while\n                // the second one needs to be set to 'sendonly'.\n                } else {\n                    mLine.direction = idx ? MediaDirection.SENDONLY : MediaDirection.SENDRECV;\n                }\n            });\n        });\n\n        return new RTCSessionDescription({\n            sdp: transformer.toRawSDP(),\n            type: remoteDescription.type\n        });\n    }\n\n    /**\n     * Returns the codec to be used for screenshare based on the supported codecs and the preferred codec requested\n     * through config.js setting.\n     *\n     * @param {CodecMimeType} defaultCodec - the preferred codec for video tracks.\n     * @returns {CodecMimeType}\n     */\n    private _getPreferredCodecForScreenshare(defaultCodec: CodecMimeType): CodecMimeType {\n        // Use the same codec for both camera and screenshare if the client doesn't support the codec selection API.\n        if (!this.usesCodecSelectionAPI()) {\n            return defaultCodec;\n        }\n\n        const { screenshareCodec } = this.codecSettings;\n\n        if (screenshareCodec && this.codecSettings.codecList.find(c => c === screenshareCodec)) {\n            return screenshareCodec;\n        }\n\n        // Default to AV1 for screenshare if its supported and is not overriden through config.js.\n        if (this.codecSettings.codecList.find(c => c === CodecMimeType.AV1)) {\n            return CodecMimeType.AV1;\n        }\n\n        return defaultCodec;\n    }\n\n    /**\n     * Sets up the _dtlsTransport object and initializes callbacks for it.\n     */\n    private _initializeDtlsTransport(): void {\n        // We are assuming here that we only have one bundled transport here\n        if (!this.peerconnection.getSenders || this._dtlsTransport) {\n            return;\n        }\n\n        const senders = this.peerconnection.getSenders();\n\n        if (senders.length !== 0 && senders[0].transport) {\n            this._dtlsTransport = senders[0].transport;\n\n            this._dtlsTransport.onerror = error => {\n                logger.error(`${this} DtlsTransport error: ${error}`);\n            };\n\n            this._dtlsTransport.onstatechange = () => {\n                this.trace('dtlsTransport.onstatechange', this._dtlsTransport.state);\n            };\n        }\n    }\n\n\n    /**\n     * Set the simulcast stream encoding properties on the RTCRtpSender.\n     *\n     * @param {JitsiLocalTrack} localTrack - the current track in use for which the encodings are to be set.\n     * @returns {Promise<void>} - resolved when done.\n     */\n    private _setEncodings(localTrack: JitsiLocalTrack): Promise<void> {\n        if (localTrack.getType() === MediaType.VIDEO) {\n            return this._updateVideoSenderParameters(() => this._configureSenderEncodings(localTrack));\n        }\n\n        return this._configureSenderEncodings(localTrack);\n    }\n\n    /**\n     * Munges the provided description to update the codec order, set the max bitrates (for VP9 K-SVC), set stereo flag\n     * and update the DD Header extensions for AV1.\n     *\n     * @param {RTCSessionDescription} description - The description to be munged.\n     * @param {boolean} isLocal - Whether the description is local or remote.\n     * @returns {RTCSessionDescription} - The munged description.\n     */\n    private _mungeDescription(description: RTCSessionDescription, isLocal: boolean = true): RTCSessionDescription {\n        this.trace('RTCSessionDescription::preTransform', TraceablePeerConnection.dumpSDP(description));\n        let mungedSdp = transform.parse(description?.sdp);\n        const audioQuality = this.audioQualityLocal;\n\n        mungedSdp = this.tpcUtils.mungeOpus(mungedSdp, audioQuality);\n        mungedSdp = this.tpcUtils.mungeCodecOrder(mungedSdp);\n        mungedSdp = this.tpcUtils.setMaxBitrates(mungedSdp, true);\n\n        if (!isLocal) {\n            mungedSdp = this.tpcUtils._stripSdesMid(mungedSdp);\n        }\n        const mungedDescription = new RTCSessionDescription({\n            sdp: transform.write(mungedSdp),\n            type: description.type\n        });\n\n        this.trace('RTCSessionDescription::postTransform', TraceablePeerConnection.dumpSDP(mungedDescription));\n\n        return mungedDescription;\n    }\n\n\n    /**\n     * Returns a wrapped-up promise so that the setParameters() call on the RTCRtpSender\n     * for video sources are chained.\n     * This is needed on Chrome as it resets the transaction id after\n     * executing setParameters() and can affect the next on\n     * the fly updates if they are not chained.\n     * https://chromium.googlesource.com/external/webrtc/+/master/pc/rtp_sender.cc#340\n     * @param {Function} nextFunction - The function to be called when the last video sender update promise is settled.\n     * @returns {Promise}\n     */\n    private _updateVideoSenderParameters(nextFunction: () => void): Promise<void> {\n        const nextPromise = this._lastVideoSenderUpdatePromise\n            .finally(nextFunction);\n\n        this._lastVideoSenderUpdatePromise = nextPromise;\n\n        return nextPromise;\n    }\n\n    /**\n     * Configures the video stream with resolution / degradation / maximum bitrates\n     *\n     * @param {number} frameHeight - The max frame height to be imposed on the outgoing video stream.\n     * @param {JitsiLocalTrack} - The local track for which the sender constraints have to be applied.\n     * @param {preferredCodec} - The video codec that needs to be configured on\n     * the sender associated with the video source.\n     * @returns {Promise} promise that will be resolved when the operation is successful and rejected otherwise.\n     */\n    private _updateVideoSenderEncodings(frameHeight: number, localVideoTrack: JitsiLocalTrack, preferredCodec: CodecMimeType): Promise<void> {\n        const videoSender = this.findSenderForTrack(localVideoTrack.getTrack());\n        const videoType = localVideoTrack.getVideoType();\n        const isScreensharingTrack = videoType === VideoType.DESKTOP;\n\n        if (!videoSender) {\n            return Promise.resolve();\n        }\n        const parameters = videoSender.getParameters() as RTCRtpSendParameters;\n\n        if (!parameters?.encodings?.length) {\n            return Promise.resolve();\n        }\n\n        const isSharingLowFpsScreen = isScreensharingTrack && this._capScreenshareBitrate;\n\n        // Set the degradation preference.\n        const preference = isSharingLowFpsScreen\n            ? DEGRADATION_PREFERENCE_DESKTOP // Prefer resolution for low fps share.\n            : DEGRADATION_PREFERENCE_CAMERA; // Prefer frame-rate for high fps share and camera.\n\n        parameters.degradationPreference = preference;\n\n        // Calculate the encodings active state based on the resolution requested by the bridge.\n        const codecForCamera = preferredCodec ?? this.tpcUtils.getConfiguredVideoCodec(localVideoTrack);\n        const codec = isScreensharingTrack ? this._getPreferredCodecForScreenshare(codecForCamera as CodecMimeType) : codecForCamera as CodecMimeType;\n        const activeState = this.tpcUtils.calculateEncodingsActiveState(localVideoTrack, codec, frameHeight);\n        let bitrates = this.tpcUtils.calculateEncodingsBitrates(localVideoTrack, codec, frameHeight);\n        const scalabilityModes = this.tpcUtils.calculateEncodingsScalabilityMode(localVideoTrack, codec, frameHeight);\n        let scaleFactors = this.tpcUtils.calculateEncodingsScaleFactor(localVideoTrack, codec, frameHeight);\n        let needsUpdate = false;\n\n        // Do not configure 'scaleResolutionDownBy' and 'maxBitrate' for encoders running in VP9 legacy K-SVC mode since\n        // the browser sends only the lowest resolution layer when those\n        // are configured. Those fields need to be reset in\n        // case they were set when the endpoint was encoding video using the other codecs before switching over to VP9\n        // K-SVC codec.\n        if (codec === CodecMimeType.VP9\n            && browser.supportsSVC()\n            && this.isSpatialScalabilityOn()\n            && !this.tpcUtils.codecSettings[codec].scalabilityModeEnabled) {\n            scaleFactors = scaleFactors.map(() => undefined);\n            bitrates = bitrates.map(() => undefined);\n        }\n\n        for (const idx in parameters.encodings) {\n            if (parameters.encodings.hasOwnProperty(idx)) {\n                const encoding = parameters.encodings[idx] as IRTCRtpEncodingParameters;\n                const {\n                    active = undefined,\n                    codec: currentCodec = undefined,\n                    maxBitrate = undefined,\n                    scalabilityMode = undefined,\n                    scaleResolutionDownBy = undefined\n                } = encoding;\n\n                if (active !== activeState[idx]) {\n                    encoding.active = activeState[idx];\n                    needsUpdate = true;\n                }\n\n                // Firefox doesn't follow the spec and lets application specify the degradation preference on the\n                // encodings.\n                browser.isFirefox() && (encoding.degradationPreference = preference);\n\n                if (scaleResolutionDownBy !== scaleFactors[idx]) {\n                    encoding.scaleResolutionDownBy = scaleFactors[idx];\n                    needsUpdate = true;\n                }\n                if (maxBitrate !== bitrates[idx]) {\n                    encoding.maxBitrate = bitrates[idx];\n                    needsUpdate = true;\n                }\n\n                // Configure scalability mode when its supported and enabled.\n                if (scalabilityModes) {\n                    if (scalabilityMode !== scalabilityModes[idx]) {\n                        encoding.scalabilityMode = scalabilityModes[idx];\n                        needsUpdate = true;\n                    }\n                } else {\n                    encoding.scalabilityMode = undefined;\n                }\n\n                const expectedPattern = `${MediaType.VIDEO}/${codec.toUpperCase()}`;\n\n                // Configure the codec here if its supported.\n                if (this.usesCodecSelectionAPI() && currentCodec?.mimeType !== expectedPattern) {\n                    const matchingCodec = parameters.codecs.find(pt => pt.mimeType === expectedPattern);\n\n                    encoding.codec = matchingCodec;\n                    needsUpdate = true;\n\n                    Statistics.sendAnalytics(\n                        AnalyticsEvents.VIDEO_CODEC_CHANGED,\n                        {\n                            value: codec,\n                            videoType\n                        });\n                }\n            }\n        }\n\n        if (!needsUpdate) {\n            return Promise.resolve();\n        }\n\n        logger.info(`${this} setting max height=${frameHeight},encodings=${JSON.stringify(parameters.encodings)}`);\n\n        return videoSender.setParameters(parameters).then(() => {\n            localVideoTrack.maxEnabledResolution = frameHeight;\n            this.eventEmitter.emit(RTCEvents.LOCAL_TRACK_MAX_ENABLED_RESOLUTION_CHANGED, localVideoTrack);\n        });\n    }\n\n\n    /**\n     * Callback ivoked by {@code this._dtmfSender} when it has finished playing\n     * a single tone.\n     *\n     * @param {Object} event - The tonechange event which indicates what characters\n     * are left to be played for the current tone.\n     * @private\n     * @returns {void}\n     */\n    private _onToneChange(event: { tone: string; }): void {\n        // An empty event.tone indicates the current tones have finished playing.\n        // Automatically start playing any queued tones on finish.\n        if (this._dtmfSender && event.tone === '' && this._dtmfTonesQueue.length) {\n            const { tones, duration, interToneGap } = this._dtmfTonesQueue.shift();\n\n            this._dtmfSender.insertDTMF(tones, duration, interToneGap);\n        }\n    }\n\n\n    /**\n     * Internal method to create an SDP offer or answer for the peer connection.\n     * Handles codec preferences, SDP munging for simulcast and RTX, and source information extraction.\n     * @private\n     */\n    private _createOfferOrAnswer(isOffer: boolean, constraints: Optional<RTCOfferOptions>): Promise<RTCSessionDescription> {\n        const logName = isOffer ? 'Offer' : 'Answer';\n\n        this.trace(`create${logName}`, JSON.stringify(constraints, null, ' '));\n\n        const handleSuccess = (resultSdp: Nullable<RTCSessionDescription>, resolveFn: (result: RTCSessionDescription) => void, rejectFn: (error: string) => void): void => {\n            try {\n                this.trace(\n                    `create${logName}OnSuccess::preTransform`, TraceablePeerConnection.dumpSDP(resultSdp));\n\n                // Munge local description to add 3 SSRCs for video tracks when spatial scalability is enabled.\n                if (this.isSpatialScalabilityOn() && browser.usesSdpMungingForSimulcast()) {\n                    // eslint-disable-next-line no-param-reassign\n                    resultSdp = this.simulcast.mungeLocalDescription(resultSdp);\n                    this.trace(`create${logName} OnSuccess::postTransform (simulcast)`,\n                         TraceablePeerConnection.dumpSDP(resultSdp));\n                }\n\n                if (!this.options.disableRtx && browser.usesSdpMungingForSimulcast()) {\n                    // eslint-disable-next-line no-param-reassign\n                    resultSdp = new RTCSessionDescription({\n                        sdp: this.rtxModifier.modifyRtxSsrcs(resultSdp?.sdp),\n                        type: resultSdp.type\n                    });\n\n                    this.trace(\n                        `create${logName}`\n                             + 'OnSuccess::postTransform (rtx modifier)',\n                        TraceablePeerConnection.dumpSDP(resultSdp));\n                }\n\n                if (resultSdp?.sdp) {\n                    this._processAndExtractSourceInfo(resultSdp.sdp);\n                }\n\n                resolveFn(resultSdp as RTCSessionDescription);\n            } catch (e) {\n                this.trace(`create${logName}OnError`, e);\n                this.trace(`create${logName}OnError`, TraceablePeerConnection.dumpSDP(resultSdp));\n                logger.error(`${this} create${logName}OnError`, e, TraceablePeerConnection.dumpSDP(resultSdp));\n\n                rejectFn(e);\n            }\n        };\n\n        const handleFailure = (err: string, rejectFn: (error: string) => void): void => {\n            this.trace(`create${logName}OnFailure`, err);\n            rejectFn(err);\n        };\n\n        // Set the codec preference before creating an offer or answer so that the generated SDP will have\n        // the correct preference order.\n        if (browser.supportsCodecPreferences() && this.codecSettings) {\n            const { codecList, mediaType } = this.codecSettings;\n            const transceivers = this.peerconnection.getTransceivers()\n                .filter(t => t.receiver && t.receiver?.track?.kind === mediaType);\n            let capabilities = RTCRtpReceiver.getCapabilities(mediaType)?.codecs;\n\n            if (transceivers.length && capabilities) {\n                // Rearrange the codec list as per the preference order.\n                for (const codec of codecList.slice().reverse()) {\n                    // Move the desired codecs (all variations of it as well) to the beginning of the list\n                    /* eslint-disable-next-line arrow-body-style */\n                    capabilities.sort(caps => {\n                        return caps.mimeType.toLowerCase() === `${mediaType}/${codec}` ? -1 : 1;\n                    });\n                }\n\n                // Disable ulpfec and RED on the p2p peerconnection.\n                if (this.isP2P && mediaType === MediaType.VIDEO) {\n                    capabilities = capabilities\n                        .filter(caps => caps.mimeType.toLowerCase() !== `${MediaType.VIDEO}/${CodecMimeType.ULPFEC}`\n                                && caps.mimeType.toLowerCase() !== `${MediaType.VIDEO}/${CodecMimeType.RED}`);\n                }\n\n                // Apply codec preference to all the transceivers associated with the given media type.\n                for (const transceiver of transceivers) {\n                    transceiver.setCodecPreferences(capabilities);\n                }\n            }\n        }\n\n        return new Promise((resolve, reject) => {\n            let oaPromise;\n\n            if (isOffer) {\n                oaPromise = this.peerconnection.createOffer(constraints);\n            } else {\n                oaPromise = this.peerconnection.createAnswer(constraints);\n            }\n\n            oaPromise\n                .then(\n                    sdp => handleSuccess(sdp, resolve, reject),\n                    error => handleFailure(error, reject));\n        });\n    }\n\n    /**\n     * Extract primary SSRC from given {@link ITPCSSRCInfo} object.\n     * @param {ITPCSSRCInfo} ssrcObj\n     * @return {Nullable<number>} the primary SSRC or <tt>null</tt>\n     */\n    private _extractPrimarySSRC(ssrcObj: ISsrcInfo): Nullable<number> {\n        if (ssrcObj?.groups?.length) {\n            return ssrcObj.groups[0].ssrcs[0];\n        } else if (ssrcObj?.ssrcs?.length) {\n            return ssrcObj.ssrcs[0];\n        }\n\n        return null;\n    }\n\n    /**\n     * Sends a stats entry to the rtcstats server about the mute state change for local track.\n     *\n     * @param {JitsiLocalTrack} track - The local track.\n     * @param {boolean} muted - muted state.\n     */\n    _sendRtcStatsEvent(track: JitsiLocalTrack, muted: boolean): void {\n        const mediaType = track.getType();\n\n        if (mediaType === MediaType.AUDIO) {\n            RTCStats.sendStatsEntry(RTCStatsEvents.AUDIO_MUTE_CHANGED_EVENT, this._pcId, muted);\n        } else if (track.getVideoType() === VideoType.DESKTOP) {\n            RTCStats.sendStatsEntry(RTCStatsEvents.SCREENSHARE_MUTE_CHANGED_EVENT, this._pcId, muted);\n        } else {\n            RTCStats.sendStatsEntry(RTCStatsEvents.VIDEO_MUTE_CHANGED_EVENT, this._pcId, muted);\n        }\n    }\n\n    /**\n     * Handles remote source mute and unmute changed events.\n     *\n     * @param {string} sourceName - The name of the remote source.\n     * @param {boolean} isMuted - The new mute state.\n     * @internal\n     */\n    _sourceMutedChanged(sourceName: string, isMuted: boolean): void {\n        const track = this.getRemoteTracks().slice().reverse().find(t => t.getSourceName() === sourceName);\n\n        if (!track) {\n            logger.debug(`Remote track not found for source=${sourceName}, mute update failed!`);\n\n            return;\n        }\n\n        track.setMute(isMuted);\n    }\n\n    /* eslint-enable max-params */\n\n    /**\n     * Process stat and adds it to the array of stats we store.\n     * @param report the current stats report.\n     * @param name the name of the report, if available\n     * @param statValue the value to add.\n     * @private\n     */\n    _processStat(report: RTCStats | ILegacyStatsReport, name: string, statValue: string | number | RTCStats): void {\n        const id = `${report.id}-${name}`;\n        let s = this.stats[id];\n        const now = new Date();\n\n        if (!s) {\n            this.stats[id] = s = {\n                endTime: now,\n                startTime: now,\n                times: [],\n                values: []\n            };\n        }\n        s.values.push(statValue);\n        s.times.push(now.getTime());\n        if (s.values.length > this.maxstats) {\n            s.values.shift();\n            s.times.shift();\n        }\n        s.endTime = now;\n    }\n\n\n    /**\n     * Forwards the {@link peerconnection.iceConnectionState} state except that it\n     * will convert \"completed\" into \"connected\" where both mean that the ICE has\n     * succeeded and is up and running. We never see \"completed\" state for\n     * the JVB connection, but it started appearing for the P2P one. This method\n     * allows to adapt old logic to this new situation.\n     * @return {RTCIceConnectionState}\n     */\n    getConnectionState(): RTCIceConnectionState {\n        const state = this.peerconnection.iceConnectionState;\n\n        if (state === 'completed') {\n            return 'connected';\n        }\n\n        return state;\n    }\n\n    /**\n     * Obtains the media direction for given {@link MediaType} that needs to be set on a p2p peerconnection's remote SDP\n     * after a source-add or source-remove action. The method takes into account whether or not there are any\n     * local tracks for the given media type.\n     * @param {MediaType} mediaType - The media type for which the direction is to be calculated.\n     * @param {boolean} isAddOperation whether the direction is to be calculated after a source-add action.\n     * @return {string} one of the SDP direction constants ('sendrecv, 'recvonly' etc.)\n     * which should be used when setting\n     * local description on the peerconnection.\n     * @internal\n     */\n    getDesiredMediaDirection(mediaType: MediaType, isAddOperation = false): MediaDirection {\n        return this.tpcUtils.getDesiredMediaDirection(mediaType, isAddOperation);\n    }\n\n    /**\n     * Tells whether or not this TPC instance has spatial scalability enabled.\n     * @return {boolean} <tt>true</tt> if spatial scalability is enabled and active or\n     * <tt>false</tt> if it's turned off.\n     */\n    isSpatialScalabilityOn(): boolean {\n        const h264SimulcastEnabled = this.tpcUtils.codecSettings[CodecMimeType.H264].scalabilityModeEnabled;\n\n        return !this.options.disableSimulcast\n            && (this.codecSettings.codecList[0] !== CodecMimeType.H264 || h264SimulcastEnabled);\n    }\n\n    /**\n     * Obtains audio levels of the remote audio tracks by getting the source information on the RTCRtpReceivers.\n     * The information relevant to the ssrc is updated each time a RTP packet constaining the ssrc is received.\n     * @param {Array<string>} speakerList list of endpoint ids for which audio levels are to be gathered.\n     * @returns {Object} containing ssrc and audio level information as a key-value pair.\n     */\n    getAudioLevels(speakerList: string[] = []): Record<string, number> {\n        const audioLevels = {};\n        const audioReceivers = speakerList.length\n            ? this._getReceiversByEndpointIds(speakerList, MediaType.AUDIO)\n            : this.peerconnection.getReceivers()\n                .filter(receiver => receiver.track\n                    && receiver.track.kind === MediaType.AUDIO && receiver.track.enabled);\n\n        audioReceivers.forEach(remote => {\n            const ssrc = remote.getSynchronizationSources();\n\n            if (ssrc?.length) {\n                // As per spec, this audiolevel is a value between 0..1 (linear), where 1.0\n                // represents 0 dBov, 0 represents silence, and 0.5 represents approximately\n                // 6 dBSPL change in the sound pressure level from 0 dBov.\n                // https://www.w3.org/TR/webrtc/#dom-rtcrtpcontributingsource-audiolevel\n                audioLevels[ssrc[0].source] = ssrc[0].audioLevel;\n            }\n        });\n\n        return audioLevels;\n    }\n\n    /**\n     * Checks if the browser is currently doing true simulcast where in three\n     * different media streams are being sent to the\n     * bridge. Currently this happens always for VP8 and only if simulcast is enabled for VP9/AV1/H264.\n     *\n     * @param {JitsiLocalTrack} localTrack - The local video track.\n     * @returns {boolean}\n     */\n    doesTrueSimulcast(localTrack: JitsiLocalTrack): boolean {\n        const currentCodec = this.tpcUtils.getConfiguredVideoCodec(localTrack);\n\n        return this.isSpatialScalabilityOn() && this.tpcUtils.isRunningInSimulcastMode(currentCodec as CodecMimeType);\n    }\n\n    /**\n     * Returns the SSRCs associated with a given local video track.\n     *\n     * @param {JitsiLocalTrack} localTrack\n     * @returns\n     */\n    getLocalVideoSSRCs(localTrack: JitsiLocalTrack): number[] {\n        const ssrcs = [];\n\n        if (!localTrack?.isVideoTrack()) {\n            return ssrcs;\n        }\n\n        const ssrcGroup = this.isSpatialScalabilityOn() ? SSRC_GROUP_SEMANTICS.SIM : SSRC_GROUP_SEMANTICS.FID;\n\n        return this.localSSRCs.get(localTrack.rtcId)\n            ?.groups?.find(group => group.semantics === ssrcGroup)?.ssrcs || ssrcs;\n    }\n\n    /**\n     * Obtains local tracks for given {@link MediaType}. If the <tt>mediaType</tt>\n     * argument is omitted the list of all local tracks will be returned.\n     * @param {MediaType} [mediaType]\n     * @return {Array<JitsiLocalTrack>}\n     */\n    getLocalTracks(mediaType: Optional<MediaType> = undefined): JitsiLocalTrack[] {\n        let tracks = Array.from(this.localTracks.values());\n\n        if (mediaType !== undefined) {\n            tracks = tracks.filter(track => track.getType() === mediaType);\n        }\n\n        return tracks;\n    }\n\n    /**\n     * Retrieves the local video tracks.\n     *\n     * @returns {Array<JitsiLocalTrack>} - local video tracks.\n     */\n    getLocalVideoTracks(): JitsiLocalTrack[] {\n        return this.getLocalTracks(MediaType.VIDEO);\n    }\n\n    /**\n     * Obtains all remote tracks currently known to this PeerConnection instance.\n     *\n     * @param {optional<string>} [endpointId] - The track owner's identifier (MUC nickname)\n     * @param {optional<MediaType>} [mediaType] - The remote tracks will be filtered by their media type if this argument is\n     * specified.\n     * @return {Array<JitsiRemoteTrack>}\n     */\n    getRemoteTracks(endpointId: Optional<string> = undefined, mediaType: Optional<MediaType> = undefined): JitsiRemoteTrack[] {\n        let remoteTracks = [];\n\n        if (FeatureFlags.isSsrcRewritingSupported()) {\n            for (const remoteTrack of this.remoteTracksBySsrc.values()) {\n                const owner = remoteTrack.getParticipantId();\n\n                if (owner && (!endpointId || owner === endpointId)) {\n                    if (!mediaType || remoteTrack.getType() === mediaType) {\n                        remoteTracks.push(remoteTrack);\n                    }\n                }\n            }\n\n            return remoteTracks;\n        }\n\n        const endpoints = endpointId ? [ endpointId ] : this.remoteTracks.keys();\n\n        for (const endpoint of endpoints) {\n            const endpointTracksByMediaType = this.remoteTracks.get(endpoint);\n\n            if (endpointTracksByMediaType) {\n                for (const trackMediaType of endpointTracksByMediaType.keys()) {\n                    // per media type filtering\n                    if (!mediaType || mediaType === trackMediaType) {\n                        remoteTracks = remoteTracks.concat(Array.from(endpointTracksByMediaType.get(trackMediaType)));\n                    }\n                }\n            }\n        }\n\n        return remoteTracks;\n    }\n\n    /**\n     * Returns the remote sourceInfo for a given source name.\n     *\n     * @param {string} sourceName - The source name.\n     * @returns {TPCSourceInfo}\n     */\n    getRemoteSourceInfoBySourceName(sourceName: string): ITPCSourceInfo {\n        return cloneDeep(this._remoteSsrcMap.get(sourceName));\n    }\n\n    /**\n     * Returns a map of source names and their associated SSRCs for the remote participant.\n     *\n     * @param {string} id Endpoint id of the remote participant.\n     * @returns {Map<string, TPCSourceInfo>} The map of source names and their associated SSRCs.\n     */\n    getRemoteSourceInfoByParticipant(id: string): Map<string, ITPCSourceInfo> {\n        const removeSsrcInfo = new Map();\n        const remoteTracks = this.getRemoteTracks(id);\n\n        if (!remoteTracks?.length) {\n            return removeSsrcInfo;\n        }\n        const primarySsrcs = remoteTracks.map(track => track.getSsrc());\n\n        for (const [ sourceName, sourceInfo ] of this._remoteSsrcMap) {\n            if (sourceInfo.ssrcList?.some(ssrc => primarySsrcs.includes(Number(ssrc)))) {\n                removeSsrcInfo.set(sourceName, sourceInfo);\n            }\n        }\n\n        return removeSsrcInfo;\n    }\n\n    /**\n     * Returns the target bitrates configured for the local video source.\n     *\n     * @param {JitsiLocalTrack} - The local video track.\n     * @returns {Object}\n     */\n    getTargetVideoBitrates(localTrack: JitsiLocalTrack): any {\n        const currentCodec = this.tpcUtils.getConfiguredVideoCodec(localTrack);\n\n        return this.tpcUtils.codecSettings[currentCodec].maxBitratesVideo;\n    }\n\n    /**\n     * Tries to find {@link JitsiTrack} for given SSRC number. It will search both local and remote tracks bound to this\n     * instance.\n     * @param {number} ssrc\n     * @return {Nullable<JitsiRemoteTrack | JitsiLocalTrack>}\n     */\n    getTrackBySSRC(ssrc: number): Nullable<JitsiRemoteTrack | JitsiLocalTrack> {\n        if (typeof ssrc !== 'number') {\n            throw new Error(`SSRC ${ssrc} is not a number`);\n        }\n        for (const localTrack of this.localTracks.values()) {\n            const { ssrcs } = this.localSSRCs.get(localTrack.rtcId) ?? { ssrcs: [] };\n\n            if (ssrcs.find(localSsrc => Number(localSsrc) === ssrc)) {\n                return localTrack;\n            }\n        }\n\n        if (FeatureFlags.isSsrcRewritingSupported()) {\n            return this.remoteTracksBySsrc.get(ssrc);\n        }\n\n        for (const remoteTrack of this.getRemoteTracks()) {\n            if (remoteTrack.getSsrc() === ssrc) {\n                return remoteTrack;\n            }\n        }\n\n        return null;\n    }\n\n    /**\n     * Tries to find SSRC number for given {@link JitsiTrack} id. It will search\n     * both local and remote tracks bound to this instance.\n     * @param {string} id\n     * @return {Nullable<number>}\n     */\n    getSsrcByTrackId(id: string): Nullable<number> {\n\n        const findTrackById = track => track.getTrack().id === id;\n        const localTrack = this.getLocalTracks().find(findTrackById);\n\n        if (localTrack) {\n            return this.getLocalSSRC(localTrack);\n        }\n\n        const remoteTrack = this.getRemoteTracks().find(findTrackById);\n\n        if (remoteTrack) {\n            return remoteTrack.getSsrc();\n        }\n\n        return null;\n    }\n\n    /**\n     * Called on \"track added\" and \"stream added\" PeerConnection events (because we\n     * handle streams on per track basis). Finds the owner and the SSRC for\n     * the track and passes that to ChatRoom for further processing.\n     * @param {MediaStream} stream the WebRTC MediaStream instance which is\n     * the parent of the track\n     * @param {MediaStreamTrack} track the WebRTC MediaStreamTrack added for remote\n     * participant.\n     * @param {RTCRtpTransceiver} transceiver the WebRTC transceiver that is created\n     * for the remote participant in unified plan.\n     */\n    _remoteTrackAdded(stream: MediaStream, track: MediaStreamTrack, transceiver: Nullable<RTCRtpTransceiver> = null): void {\n        const streamId = stream.id;\n        const mediaType = track.kind as MediaType;\n\n        // Do not create remote tracks for 'mixed' JVB SSRCs (used by JVB for RTCP termination).\n        if (!this.isP2P && !RTCUtils.isUserStreamById(streamId)) {\n            return;\n        }\n        logger.info(`${this} Received track event for remote stream[id=${streamId},type=${mediaType}]`);\n\n        // look up an associated JID for a stream id\n        if (!mediaType) {\n            logger.error(`MediaType undefined for remote track, stream id: ${streamId}, track creation failed!`);\n\n            return;\n        }\n\n        const remoteSDP = new SDP(this.remoteDescription?.sdp);\n        let mediaLine;\n\n        // Find the matching mline using 'mid' or the 'msid' attr of the stream.\n        if (transceiver?.mid) {\n            const mid = transceiver.mid;\n\n            // @ts-ignore\n            mediaLine = remoteSDP.media.find(mls => SDPUtil.findLine(mls, `a=mid:${mid}`));\n        } else {\n            mediaLine = remoteSDP.media.find(mls => {\n                // @ts-ignore\n                const msid = SDPUtil.findLine(mls, 'a=msid:');\n\n                return typeof msid === 'string' && streamId === msid.substring(7).split(' ')[0];\n            });\n        }\n\n        if (!mediaLine) {\n            logger.error(\n                `Matching media line not found in remote SDP for remote stream[id=${streamId},type=${mediaType}],`\n                    + 'track creation failed!');\n\n            return;\n        }\n        // @ts-ignore\n        let ssrcLines = SDPUtil.findLines(mediaLine, 'a=ssrc:');\n\n        ssrcLines = ssrcLines.filter(line => line.indexOf(`msid:${streamId}`) !== -1);\n        if (!ssrcLines.length) {\n            logger.error(`No SSRC lines found in remote SDP for remote stream[msid=${streamId},type=${mediaType}]`\n                    + 'track creation failed!');\n\n            return;\n        }\n\n        // FIXME the length of ssrcLines[0] not verified, but it will fail\n        // with global error handler anyway\n        const ssrcStr = ssrcLines[0].substring(7).split(' ')[0];\n        const trackSsrc = Number(ssrcStr);\n        const ownerEndpointId = this._signalingLayer.getSSRCOwner(trackSsrc);\n\n        if (!isValidNumber(trackSsrc) || trackSsrc < 0) {\n            logger.error(`Invalid SSRC for remote stream[ssrc=${trackSsrc},id=${streamId},type=${mediaType}]`\n                    + 'track creation failed!');\n\n            return;\n        }\n\n        if (!ownerEndpointId) {\n            logger.error(`No SSRC owner known for remote stream[ssrc=${trackSsrc},id=${streamId},type=${mediaType}]`\n                + 'track creation failed!');\n\n            return;\n        }\n\n        const sourceName = this._signalingLayer.getTrackSourceName(trackSsrc);\n        const peerMediaInfo = this._signalingLayer.getPeerMediaInfo(ownerEndpointId, mediaType, sourceName);\n\n        // Translated sources are never carried in presence, so peerMediaInfo defaults to muted. They represent\n        // actively flowing synthesized audio, so treat them as unmuted.\n        const muted = isTranslatedSourceName(sourceName) ? false : (peerMediaInfo?.muted ?? true);\n        const trackDetails = {\n            mediaType,\n            muted,\n            ssrc: trackSsrc,\n            stream,\n            track,\n            videoType: peerMediaInfo?.videoType\n        };\n\n        if (this._remoteSsrcMap.has(sourceName) && mediaType === MediaType.VIDEO) {\n            trackDetails.videoType = this._remoteSsrcMap.get(sourceName).videoType;\n        }\n\n        this._createRemoteTrack(ownerEndpointId, sourceName, trackDetails);\n    }\n\n    /**\n     * Initializes a new JitsiRemoteTrack instance with the data provided by the signaling layer and SDP.\n     *\n     * @param {string} ownerEndpointId - The owner's endpoint ID (MUC nickname)\n     * @param {String} sourceName - The track's source name\n     * @param {Object} trackDetails - The track's details.\n     * @param {MediaType} trackDetails.mediaType - media type, 'audio' or 'video'.\n     * @param {boolean} trackDetails.muted - The initial muted status.\n     * @param {number} trackDetails.ssrc - The track's main SSRC number.\n     * @param {MediaStream} trackDetails.stream - The WebRTC stream instance.\n     * @param {MediaStreamTrack} trackDetails.track - The WebRTC track instance.\n     * @param {VideoType} trackDetails.videoType - The track's type of the video (if applicable).\n     */\n    _createRemoteTrack(ownerEndpointId, sourceName, trackDetails) {\n        const { mediaType, muted, ssrc, stream, track, videoType } = trackDetails;\n\n        logger.info(`${this} creating remote track[endpoint=${ownerEndpointId},ssrc=${ssrc},`\n            + `type=${mediaType},sourceName=${sourceName}]`);\n        let remoteTracksMap;\n        let userTracksByMediaType;\n\n        if (FeatureFlags.isSsrcRewritingSupported()) {\n            const existingTrack = this.remoteTracksBySsrc.get(ssrc);\n\n            if (existingTrack) {\n                logger.info(`${this} ignored duplicated track event for SSRC[ssrc=${ssrc},type=${mediaType}]`);\n\n                return;\n            }\n        } else {\n            remoteTracksMap = this.remoteTracks.get(ownerEndpointId);\n\n            if (!remoteTracksMap) {\n                remoteTracksMap = new Map();\n                remoteTracksMap.set(MediaType.AUDIO, new Set());\n                remoteTracksMap.set(MediaType.VIDEO, new Set());\n                this.remoteTracks.set(ownerEndpointId, remoteTracksMap);\n            }\n\n            userTracksByMediaType = remoteTracksMap.get(mediaType);\n\n            if (userTracksByMediaType?.size\n                && Array.from(userTracksByMediaType).find((jitsiTrack: JitsiRemoteTrack) => jitsiTrack.getTrack() === track)) {\n                // Ignore duplicated event which can originate either from 'onStreamAdded' or 'onTrackAdded'.\n                logger.info(`${this} ignored duplicated track event for track[endpoint=${ownerEndpointId},`\n                    + `type=${mediaType}]`);\n\n                return;\n            }\n        }\n\n        const remoteTrack\n            = new JitsiRemoteTrack(\n                    this.rtc,\n                    this.rtc.conference,\n                    ownerEndpointId,\n                    stream,\n                    track,\n                    mediaType,\n                    videoType,\n                    ssrc,\n                    muted,\n                    this.isP2P,\n                    sourceName);\n\n        if (FeatureFlags.isSsrcRewritingSupported()) {\n            this.remoteTracksBySsrc.set(ssrc, remoteTrack);\n        } else {\n            userTracksByMediaType.add(remoteTrack);\n        }\n\n        this.eventEmitter.emit(RTCEvents.REMOTE_TRACK_ADDED, remoteTrack, this);\n    }\n\n    /**\n     * Handles remote media track removal.\n     *\n     * @param {MediaStream} stream - WebRTC MediaStream instance which is the parent of the track.\n     * @param {MediaStreamTrack} track - WebRTC MediaStreamTrack which has been removed from the PeerConnection.\n     * @returns {void}\n     */\n    _remoteTrackRemoved(stream: MediaStream, track: MediaStreamTrack): void {\n        const streamId = stream.id;\n        const trackId = track?.id;\n\n        // Ignore stream removed events for JVB \"mixed\" sources (used for RTCP termination).\n        if (!RTCUtils.isUserStreamById(streamId)) {\n            return;\n        }\n\n        if (!streamId) {\n            logger.error(`${this} remote track removal failed - no stream ID`);\n\n            return;\n        }\n\n        if (!trackId) {\n            logger.error(`${this} remote track removal failed - no track ID`);\n\n            return;\n        }\n\n        const toBeRemoved = this.getRemoteTracks().find(\n            remoteTrack => remoteTrack.getStreamId() === streamId && remoteTrack.getTrackId() === trackId);\n\n        if (!toBeRemoved) {\n            logger.error(`${this} remote track removal failed - track not found`);\n\n            return;\n        }\n\n        this._removeRemoteTrack(toBeRemoved);\n    }\n\n    /**\n     * Removes and disposes given <tt>JitsiRemoteTrack</tt> instance. Emits {@link RTCEvents.REMOTE_TRACK_REMOVED}.\n     *\n     * @param {JitsiRemoteTrack} toBeRemoved - The remote track to be removed.\n     * @returns {void}\n     */\n    _removeRemoteTrack(toBeRemoved: JitsiRemoteTrack): void {\n        logger.info(`${this} Removing remote track stream[id=${toBeRemoved.getStreamId()},`\n            + `trackId=${toBeRemoved.getTrackId()}]`);\n\n        const participantId = toBeRemoved.getParticipantId();\n        const ssrc = toBeRemoved.getSsrc();\n\n        toBeRemoved.dispose();\n\n        if (FeatureFlags.isSsrcRewritingSupported()) {\n            if (!participantId) {\n                return;\n            }\n\n            // Drop the SSRC->track entry so that a later source-add reusing the same rewritten SSRC (e.g. the wedge\n            // recovery recycling a source via source-remove then source-add) is not discarded as a duplicate by\n            // _createRemoteTrack. Guarded so a slot already remapped to a different current track is left alone.\n            if (this.remoteTracksBySsrc.get(ssrc) === toBeRemoved) {\n                this.remoteTracksBySsrc.delete(ssrc);\n            }\n        } else {\n            const userTracksByMediaType = this.remoteTracks.get(participantId);\n\n            if (!userTracksByMediaType) {\n                logger.error(`${this} removeRemoteTrack: no remote tracks map for endpoint=${participantId}`);\n            } else if (!userTracksByMediaType.get(toBeRemoved.getType())?.delete(toBeRemoved)) {\n                logger.error(`${this} Failed to remove ${toBeRemoved} - type mapping messed up ?`);\n            }\n        }\n\n        this.eventEmitter.emit(RTCEvents.REMOTE_TRACK_REMOVED, toBeRemoved);\n    }\n\n    /**\n     * Processes the local SDP and creates an SSRC map for every local track.\n     *\n     * @param {string} localSDP - SDP from the local description.\n     * @returns {void}\n     */\n    _processAndExtractSourceInfo(localSDP: string): void {\n        /**\n         * @type {Map<string, TPCSourceInfo>} The map of source names and their associated SSRCs.\n         */\n        const ssrcMap = new Map();\n\n        if (!localSDP || typeof localSDP !== 'string') {\n            throw new Error('Local SDP must be a valid string, aborting!!');\n        }\n        const session = transform.parse(localSDP);\n        const media = session.media.filter(mline => mline.direction === MediaDirection.SENDONLY\n            || mline.direction === MediaDirection.SENDRECV);\n\n        if (!media.length) {\n            this._localSsrcMap = ssrcMap;\n\n            return;\n        }\n\n        for (const localTrack of this.localTracks.values()) {\n            const sourceName = localTrack.getSourceName();\n            const trackIndex = getSourceIndexFromSourceName(sourceName);\n            const mediaType = localTrack.getType();\n            const mLines = media.filter(m => m.type === mediaType);\n            const mLine = mLines[trackIndex];\n\n            if (!mLine) {\n                continue;\n            }\n\n            const ssrcGroups = mLine.ssrcGroups;\n            let ssrcs = mLine.ssrcs;\n\n            if (ssrcs?.length) {\n                // Filter the ssrcs with 'cname' attribute.\n                ssrcs = ssrcs.filter(s => s.attribute === 'cname');\n\n                const msid = `${this.rtc.getLocalEndpointId()}-${mediaType}-${trackIndex}`;\n                const ssrcInfo = {\n                    groups: [],\n                    msid,\n                    ssrcs: []\n                };\n\n                ssrcs.forEach(ssrc => ssrcInfo.ssrcs.push(ssrc.id));\n\n                if (ssrcGroups?.length) {\n                    for (const group of ssrcGroups) {\n                        const parsedGroup = {\n                            semantics: group.semantics,\n                            ssrcs: group.ssrcs.split(' ').map(ssrcStr => parseInt(ssrcStr, 10))\n                        };\n\n                        ssrcInfo.groups.push(parsedGroup);\n                    }\n\n                    const simGroup = ssrcGroups.find(group => group.semantics === SSRC_GROUP_SEMANTICS.SIM);\n\n                    // Add a SIM group if its missing in the description (happens on Firefox).\n                    if (this.isSpatialScalabilityOn() && !simGroup) {\n                        const groupSsrcs = ssrcGroups.map(group => group.ssrcs[0]);\n\n                        ssrcInfo.groups.push({\n                            semantics: SSRC_GROUP_SEMANTICS.SIM,\n                            ssrcs: groupSsrcs\n                        });\n                    }\n                }\n\n                ssrcMap.set(sourceName, ssrcInfo);\n\n                const oldSsrcInfo = this.localSSRCs.get(localTrack.rtcId);\n                const oldSsrc = this._extractPrimarySSRC(oldSsrcInfo);\n                const newSsrc = this._extractPrimarySSRC(ssrcInfo);\n\n                if (oldSsrc !== newSsrc) {\n                    oldSsrc && logger.debug(`${this} Overwriting SSRC for track=${localTrack}] with ssrc=${newSsrc}`);\n                    this.localSSRCs.set(localTrack.rtcId, ssrcInfo);\n                    localTrack.setSsrc(newSsrc);\n                }\n            }\n        }\n        this._localSsrcMap = ssrcMap;\n    }\n\n    /**\n     * @param {JitsiLocalTrack} localTrack\n     * @returns {Nullable<number>}\n     */\n    getLocalSSRC(localTrack: JitsiLocalTrack): Nullable<number> {\n        const ssrcInfo = this._getSSRC(localTrack.rtcId.toString());\n\n        return ssrcInfo?.ssrcs[0];\n    }\n\n    /**\n     * Gets the signaling state of the peer connection.\n     */\n    get signalingState(): string {\n        return this.peerconnection.signalingState;\n    }\n\n    /**\n     * Gets the ICE connection state of the peer connection.\n     */\n    get iceConnectionState(): string {\n        return this.peerconnection.iceConnectionState;\n    }\n\n    /**\n     * Gets the connection state of the peer connection.\n     */\n    get connectionState(): string {\n        return this.peerconnection.connectionState;\n    }\n\n    /**\n     * Gets the local description of the peer connection, with optional transformations for\n     * simulcast and stream identifiers.\n     */\n    get localDescription(): RTCSessionDescription {\n        let desc = this.peerconnection.localDescription;\n\n        if (!desc) {\n            logger.debug(`${this} getLocalDescription no localDescription found`);\n\n            // @ts-ignore\n            return {};\n        }\n\n        this.trace('getLocalDescription::preTransform', TraceablePeerConnection.dumpSDP(desc));\n\n        if (!this.isP2P) {\n            desc = this.tpcUtils.injectSsrcGroupForSimulcast(desc);\n            this.trace('getLocalDescription::postTransform (inject ssrc group)', TraceablePeerConnection.dumpSDP(desc));\n        }\n\n        desc = this.localSdpMunger.transformStreamIdentifiers(desc, this._localSsrcMap);\n\n        return desc;\n    }\n\n    /**\n     * Gets the remote description of the peer connection, with optional adjustments for media direction in P2P mode.\n     */\n    get remoteDescription(): RTCSessionDescription {\n        let desc = this.peerconnection.remoteDescription;\n\n        if (!desc) {\n            logger.debug(`${this} getRemoteDescription no remoteDescription found`);\n\n            // @ts-ignore\n            return {};\n        }\n        this.trace('getRemoteDescription::preTransform', TraceablePeerConnection.dumpSDP(desc));\n\n        if (this.isP2P) {\n            desc = this._adjustRemoteMediaDirection(desc);\n        }\n\n        return desc;\n    }\n\n    /**\n     * Retrieves the SSRC (Synchronization Source) identifier associated with the given RTC ID.\n     * @private\n     */\n    _getSSRC(rtcId: string): Nullable<ISsrcInfo> {\n        return this.localSSRCs.get(Number(rtcId));\n    }\n\n    /**\n     * Checks if low fps screensharing is in progress.\n     *\n     * @private\n     * @returns {boolean} Returns true if 5 fps screensharing is in progress, false otherwise.\n     */\n    isSharingLowFpsScreen(): boolean {\n        return this._isSharingScreen() && this._capScreenshareBitrate;\n    }\n\n    /**\n     * Checks if screensharing is in progress.\n     *\n     * @returns {boolean}  Returns true if a desktop track has been added to the peerconnection, false otherwise.\n     */\n    _isSharingScreen(): boolean {\n        const tracks = this.getLocalVideoTracks();\n\n        return Boolean(tracks.find(track => track.videoType === VideoType.DESKTOP));\n    }\n\n    /**\n     * Add {@link JitsiLocalTrack} to this TPC.\n     * @param {JitsiLocalTrack} track\n     * @param {boolean} isInitiator indicates if the endpoint is the offerer.\n     * @returns {Promise<void>} - resolved when done.\n     */\n    addTrack = async (track: JitsiLocalTrack, isInitiator = false): Promise<void> => {\n        const rtcId = track.rtcId;\n\n        if (this.localTracks.has(rtcId)) {\n            throw new Error(`${track} is already in ${this}`);\n        }\n\n        logger.info(`${this} adding ${track}`);\n        let webrtcStream = null;\n        let mediaStreamTrack = null;\n\n        if (track.type === MediaType.VIDEO) {\n            if (track.videoType === VideoType.CAMERA) {\n                try {\n                    webrtcStream = track.getOriginalStream();\n                    mediaStreamTrack = track.getTrack();\n                } catch (error) {\n                    logger.info('Problems adding encoded streams at TraceablePeerConnection:', error);\n                }\n            }\n        } else {\n            webrtcStream = track.getOriginalStream();\n            mediaStreamTrack = track.getTrack();\n        }\n        let transceiver;\n\n        if (isInitiator) {\n            const streams = [];\n\n            webrtcStream && streams.push(webrtcStream);\n\n            // Use pc.addTransceiver() for the initiator case when local tracks are getting added\n            // to the peerconnection before a session-initiate is sent over to the peer.\n            const transceiverInit = {\n                direction: MediaDirection.SENDRECV,\n                sendEncodings: [],\n                streams\n            };\n\n            if (!browser.isFirefox() || browser.supportsEncodingsConfig()) {\n                transceiverInit.sendEncodings = this.tpcUtils.getStreamEncodings(track);\n            }\n\n            transceiver = this.peerconnection.addTransceiver(mediaStreamTrack, transceiverInit);\n        } else {\n            // Use pc.addTrack() for responder case so that we can re-use the m-lines that were created\n            // when setRemoteDescription was called. pc.addTrack() automatically  attaches to any existing\n            // unused \"recv-only\" transceiver.\n            const sender = this.peerconnection.addTrack(mediaStreamTrack);\n\n            // Find the corresponding transceiver that the track was attached to.\n            transceiver = this.peerconnection.getTransceivers().find(t => t.sender === sender);\n        }\n\n        if (transceiver?.mid) {\n            const mid = transceiver.mid.toString();\n\n            this.localTrackTransceiverMids.set(track.rtcId, mid);\n            this._midsWithSentTrack.add(mid);\n        }\n\n        if (track) {\n            this.localTracks.set(rtcId, track);\n        }\n\n        // FF < 110 doesn't honor sendEncodings on addTransceiver; configure the encodings via setParameters.\n        if (browser.isFirefox() && !browser.supportsEncodingsConfig()\n                && webrtcStream && this.doesTrueSimulcast(track)) {\n            await this._setEncodings(track);\n        }\n    };\n\n    /**\n     * Adds local track to the RTCPeerConnection.\n     *\n     * @param {JitsiLocalTrack} track the track to be added to the pc.\n     * @return {Promise<boolean>} Promise that resolves to true if the underlying PeerConnection's state has changed and\n     * renegotiation is required, false if no renegotiation is needed or Promise is rejected when something goes wrong.\n     */\n    addTrackToPc(track: JitsiLocalTrack): Promise<boolean> {\n        logger.info(`${this} Adding track=${track} to PC`);\n\n        if (!this._assertTrackBelongs('addTrackToPc', track)) {\n            // Abort\n            return Promise.reject('Track not found on the peerconnection');\n        }\n\n        const webRtcStream = track.getOriginalStream();\n\n        if (!webRtcStream) {\n            logger.error(`${this} Unable to add track=${track} to PC - no WebRTC stream`);\n\n            return Promise.reject('Stream not found');\n        }\n\n        return this.replaceTrack(null, track, true /* isMuteOperation */).then(() => {\n            let shouldRenegotiate = false;\n\n            if (track) {\n                if (track.isAudioTrack()) {\n                    // Sync audioQualityLocal from microphone track settings (stereo/mono)\n                    const isMicrophoneTrack = !track.sourceType && !track.sourceId && track.deviceId;\n\n                    if (isMicrophoneTrack && track.getTrack()) {\n                        const channelCount = track.getTrack()?.getSettings?.()?.channelCount;\n\n                        if (typeof channelCount === 'number') {\n                            const stereo = channelCount === 2;\n                            const opusMaxAverageBitrate = stereo\n                                ? this.options?.audioQuality?.opusMaxAverageBitrateStereo\n                                : this.options?.audioQuality?.opusMaxAverageBitrateMono;\n\n                            // Update if stereo or bitrate differs from current\n                            if (this.audioQualityLocal?.stereo !== stereo\n                                || this.audioQualityLocal?.opusMaxAverageBitrate !== opusMaxAverageBitrate) {\n\n                                this.audioQualityLocal = {\n                                    ...this.audioQualityLocal,\n                                    opusMaxAverageBitrate,\n                                    stereo\n                                };\n                                logger.info(`${this} audio quality updated: stereo=${stereo}, bitrate=${opusMaxAverageBitrate}bps`);\n\n                                shouldRenegotiate = true;\n                            }\n                        }\n                    }\n                }\n            }\n\n            return shouldRenegotiate;\n        });\n    }\n\n    /**\n     * This method when called will check if given <tt>localTrack</tt> belongs to\n     * this TPC (that it has been previously added using {@link addTrack}). If the\n     * track does not belong an error message will be logged.\n     * @param {string} methodName the method name that will be logged in an error\n     * message\n     * @param {JitsiLocalTrack} localTrack\n     * @return {boolean} <tt>true</tt> if given local track belongs to this TPC or\n     * <tt>false</tt> otherwise.\n     * @private\n     */\n    _assertTrackBelongs(methodName: string, localTrack: JitsiLocalTrack): boolean {\n        const doesBelong = this.localTracks.has(localTrack?.rtcId);\n\n        if (!doesBelong) {\n            logger.error(`${this} ${methodName}: track=${localTrack} does not belong to pc`);\n        }\n\n        return doesBelong;\n    }\n\n    /**\n     * Returns the codecs in the current order of preference as configured on the peerconnection.\n     *\n     * @param {RTCSessionDescription} - The local description to be used.\n     * @returns {Array}\n     */\n    getConfiguredVideoCodecs(description?: RTCSessionDescription): CodecMimeType[] {\n        return this.tpcUtils.getConfiguredVideoCodecs(description?.sdp);\n    }\n\n    /**\n     * Enables or disables simulcast for screenshare based on the frame rate requested for desktop track capture.\n     *\n     * @param {number} maxFps framerate to be used for desktop track capture.\n     */\n    setDesktopSharingFrameRate(maxFps: number): void {\n        const lowFps = maxFps <= SS_DEFAULT_FRAME_RATE;\n\n        this._capScreenshareBitrate = this.isSpatialScalabilityOn() && lowFps;\n    }\n\n    /**\n     * Sets the codec preference on the peerconnection. The codec preference goes into effect when\n     * the next renegotiation happens for older clients that do not support the codec selection API.\n     *\n     * @param {Array<CodecMimeType>} codecList - Preferred codecs for video.\n     * @param {CodecMimeType} screenshareCodec - The preferred codec for screenshare.\n     * @returns {boolean} - Returns true if the codec settings were updated, false otherwise.\n     */\n    setVideoCodecs(codecList: CodecMimeType[], screenshareCodec: CodecMimeType): boolean {\n        let updated = false;\n\n        if (!this.codecSettings || !codecList?.length) {\n            return updated;\n        }\n\n        this.codecSettings.codecList = codecList;\n        if (screenshareCodec) {\n            this.codecSettings.screenshareCodec = screenshareCodec;\n        }\n\n        if (!this.usesCodecSelectionAPI()) {\n            return updated;\n        }\n\n        for (const track of this.getLocalVideoTracks()) {\n            const currentCodec = this.tpcUtils.getConfiguredVideoCodec(track);\n\n            if (screenshareCodec && track.getVideoType() === VideoType.DESKTOP && screenshareCodec !== currentCodec) {\n                this.configureVideoSenderEncodings(track, screenshareCodec);\n                updated = true;\n            } else if (currentCodec !== codecList[0]) {\n                this.configureVideoSenderEncodings(track);\n                updated = true;\n            }\n        }\n\n        updated && RTCStats.sendStatsEntry(RTCStatsEvents.CODEC_CHANGED_EVENT, this._pcId, {\n            camera: codecList[0],\n            screenshare: screenshareCodec\n        });\n\n        return updated;\n    }\n\n    /**\n     * Remove local track from this TPC.\n     * @param {JitsiLocalTrack} localTrack the track to be removed from this TPC.\n     *\n     * FIXME It should probably remove a boolean just like {@link removeTrackFromPc}\n     *       The same applies to addTrack.\n     */\n    removeTrack(localTrack: JitsiLocalTrack): void {\n        const webRtcStream = localTrack.getOriginalStream();\n\n        this.trace(\n            'removeStream',\n            localTrack.rtcId.toString(), webRtcStream ? webRtcStream.id : undefined);\n\n        if (!this._assertTrackBelongs('removeStream', localTrack)) {\n            // Abort - nothing to be done here\n            return;\n        }\n        this.localTracks.delete(localTrack.rtcId);\n        this.localSSRCs.delete(localTrack.rtcId);\n\n        if (webRtcStream) {\n            // @ts-ignore\n            this.peerconnection.removeStream(webRtcStream);\n        }\n    }\n\n    /**\n     * Returns the receiver corresponding to the given MediaStreamTrack.\n     *\n     * @param {MediaSreamTrack} track - The media stream track used for the search.\n     * @returns {Optional<RTCRtpReceiver>} - The found receiver or undefined if no receiver\n     * was found.\n     */\n    findReceiverForTrack(track: MediaStreamTrack): Optional<RTCRtpReceiver> {\n        return this.peerconnection.getReceivers().find(r => r.track === track);\n    }\n\n    /**\n     * Returns the sender corresponding to the given MediaStreamTrack.\n     *\n     * @param {MediaSreamTrack} track - The media stream track used for the search.\n     * @returns {Optional<RTCRtpSender>} - The found sender or undefined if no sender\n     * was found.\n     */\n    findSenderForTrack(track: MediaStreamTrack): Optional<RTCRtpSender> {\n        return this.peerconnection.getSenders().find(s => s.track === track);\n    }\n\n    /**\n     * Processes the local description SDP and caches the mids of the mlines associated with the given tracks.\n     *\n     * @param {Array<JitsiLocalTrack>} localTracks - local tracks that are added to the peerconnection.\n     * @returns {void}\n     */\n    processLocalSdpForTransceiverInfo(localTracks: JitsiLocalTrack[]): void {\n        const localSdp = this.localDescription?.sdp;\n\n        if (!localSdp) {\n            return;\n        }\n\n        [ MediaType.AUDIO, MediaType.VIDEO ].forEach(mediaType => {\n            const tracks = localTracks.filter(t => t.getType() === mediaType);\n            const parsedSdp = transform.parse(localSdp);\n            const mLines = parsedSdp.media.filter(mline => mline.type === mediaType);\n\n            tracks.forEach((track, idx) => {\n                if (!this.localTrackTransceiverMids.has(track.rtcId)) {\n                    this.localTrackTransceiverMids.set(track.rtcId, mLines[idx].mid.toString());\n                }\n            });\n        });\n    }\n\n    /**\n     * Replaces <tt>oldTrack</tt> with <tt>newTrack</tt> from the peer connection.\n     * Either <tt>oldTrack</tt> or <tt>newTrack</tt> can be null; replacing a valid\n     * <tt>oldTrack</tt> with a null <tt>newTrack</tt> effectively just removes\n     * <tt>oldTrack</tt>\n     *\n     * @param {Nullable<JitsiLocalTrack>} oldTrack - The current track in use to be replaced on the pc.\n     * @param {Nullable<JitsiLocalTrack>} newTrack - The new track to be used.\n     * @param {boolean} isMuteOperation - Whether the operation is a mute/unmute operation.\n     * @returns {Promise<boolean>} - If the promise resolves with true, renegotiation will be needed.\n     * Otherwise no renegotiation is needed.\n     */\n    replaceTrack(oldTrack: Nullable<JitsiLocalTrack>, newTrack: Nullable<JitsiLocalTrack>, isMuteOperation = false): Promise<boolean> {\n        if (!(oldTrack || newTrack)) {\n            logger.info(`${this} replaceTrack called with no new track and no old track`);\n\n            return Promise.resolve(false);\n        }\n\n        logger.info(`${this} TPC.replaceTrack old=${oldTrack}, new=${newTrack}`);\n\n        let transceiver;\n        const mediaType = newTrack?.getType() ?? oldTrack?.getType();\n        const localTracks = this.getLocalTracks(mediaType);\n        const track = newTrack?.getTrack() ?? null;\n        const isNewLocalSource = localTracks?.length\n            && !oldTrack\n            && newTrack\n            && !localTracks.find(t => t === newTrack);\n\n        // If old track exists, replace the track on the corresponding sender.\n        if (oldTrack && !oldTrack.isMuted()) {\n            transceiver = this.peerconnection.getTransceivers().find(t => t.sender.track === oldTrack.getTrack());\n\n        // Find the first recvonly transceiver when more than one track of the same media type is being added to the pc.\n        // As part of the track addition, a new m-line was added to the remote description with direction set to\n        // recvonly.\n        } else if (isNewLocalSource) {\n            transceiver = this.peerconnection.getTransceivers().find(\n                t => t.receiver.track.kind === mediaType\n                && t.direction === MediaDirection.RECVONLY\n\n                // Re-use any existing recvonly transceiver (if available) for p2p case.\n                && ((this.isP2P && t.currentDirection === MediaDirection.RECVONLY)\n                // @ts-ignore\n                    || (t.currentDirection === MediaDirection.INACTIVE && !t.stopped)));\n\n        // For mute/unmute operations, find the transceiver based on the track index in the source name if present,\n        // otherwise it is assumed to be the first local track that was added to the peerconnection.\n        } else {\n            transceiver = this.peerconnection.getTransceivers().find(t => t.receiver.track.kind === mediaType);\n            const sourceName = newTrack?.getSourceName() ?? oldTrack?.getSourceName();\n\n            if (sourceName) {\n                const trackIndex = getSourceIndexFromSourceName(sourceName);\n\n                if (this.isP2P) {\n                    transceiver = this.peerconnection.getTransceivers()\n                        .filter(t => t.receiver.track.kind === mediaType)[trackIndex];\n                } else if (oldTrack) {\n                    const transceiverMid = this.localTrackTransceiverMids.get(oldTrack.rtcId);\n\n                    transceiver = this.peerconnection.getTransceivers().find(t => t.mid === transceiverMid);\n                } else if (trackIndex) {\n                    transceiver = this.peerconnection.getTransceivers()\n                            .filter(t => t.receiver.track.kind === mediaType\n                                && t.direction !== MediaDirection.RECVONLY)[trackIndex];\n                }\n            }\n        }\n\n        if (!transceiver) {\n            return Promise.reject(\n                new Error(`Replace track failed - no transceiver for old: ${oldTrack}, new: ${newTrack}`));\n        }\n\n        return transceiver.sender.replaceTrack(track)\n            .then(() => {\n                if (isMuteOperation) {\n                    // Send RTCStats events for mute operations.\n                    this._sendRtcStatsEvent((oldTrack ?? newTrack), (oldTrack && !newTrack));\n\n                    return Promise.resolve();\n                }\n                if (oldTrack) {\n                    this.localTracks.delete(oldTrack.rtcId);\n                    this.localTrackTransceiverMids.delete(oldTrack.rtcId);\n                }\n\n                if (newTrack) {\n                    const newMid = transceiver?.mid?.toString();\n\n                    this.localTrackTransceiverMids.set(newTrack.rtcId, newMid);\n                    this.localTracks.set(newTrack.rtcId, newTrack);\n                    if (newMid) {\n                        this._midsWithSentTrack.add(newMid);\n                    }\n\n                    // Send RTCStats event when the track is added for the first time.\n                    this._sendRtcStatsEvent(newTrack, false);\n                }\n\n                // Update the local SSRC cache for the case when one track gets replaced with another and no\n                // renegotiation is triggered as a result of this.\n                if (oldTrack && newTrack) {\n                    const oldTrackSSRC = this.localSSRCs.get(oldTrack.rtcId);\n\n                    if (oldTrackSSRC) {\n                        this.localSSRCs.delete(oldTrack.rtcId);\n                        this.localSSRCs.set(newTrack.rtcId, oldTrackSSRC);\n                        const oldSsrcNum = this._extractPrimarySSRC(oldTrackSSRC);\n\n                        newTrack.setSsrc(oldSsrcNum);\n                    }\n\n                    // When a screenshare is stopped and started again, replace track will be called.\n                    if (oldTrack.getVideoType() === VideoType.DESKTOP) {\n                        RTCStats.sendStatsEntry(RTCStatsEvents.SCREENSHARE_MUTE_CHANGED_EVENT, this._pcId, false);\n                    }\n                }\n\n                // In the scenario where we remove the oldTrack (oldTrack is not null and newTrack is null) on FF\n                // if we change the direction to RECVONLY, create answer will generate SDP with only 1 receive\n                // only ssrc instead of keeping all 6 ssrcs that we currently have. Stopping the screen sharing\n                // and then starting it again will trigger 2 rounds of source-remove and source-add replacing\n                // the 6 ssrcs for the screen sharing with 1 receive only ssrc and then removing the receive\n                // only ssrc and adding the same 6 ssrcs. On the remote participant's side the same ssrcs will\n                // be reused on a new m-line and if the remote participant is FF due to\n                // https://bugzilla.mozilla.org/show_bug.cgi?id=1768729 the video stream won't be rendered.\n                // That's why we need keep the direction to SENDRECV for FF.\n                //\n                // NOTE: If we return to the approach of not removing the track for FF and instead using the\n                // enabled property for muting the track, we may need to change the direction to\n                // RECVONLY if FF still sends the media even though the enabled flag is set to false.\n                // On Firefox the transceiver direction (not encoding.active) is what suspends an audio sender\n                // while audio transfer is inactive on this peerconnection - the JVB connection during P2P (see\n                // getTransceiverDirection and _enableSenderEncodings).\n                const mediaTransferActive = mediaType === MediaType.VIDEO\n                    ? this.videoTransferActive\n                    : this.audioTransferActive;\n\n                transceiver.direction = TraceablePeerConnection.getTransceiverDirection(\n                    Boolean(newTrack), mediaType, mediaTransferActive);\n\n                // Configure simulcast encodings on Firefox when a track is added to the\n                // peerconnection for the first time.\n                const configureEncodingsPromise\n                    = browser.isFirefox() && !oldTrack && newTrack && this.doesTrueSimulcast(newTrack)\n                        ? this._setEncodings(newTrack)\n                        : Promise.resolve();\n\n                return configureEncodingsPromise.then(() => this.isP2P);\n            });\n    }\n\n    /**\n     * Removes local track from the RTCPeerConnection.\n     *\n     * @param {JitsiLocalTrack} localTrack the local track to be removed.\n     * @return {Promise<boolean>} Promise that resolves to true if the underlying PeerConnection's state has changed and\n     * renegotiation is required, false if no renegotiation is needed or Promise is rejected when something goes wrong.\n     */\n    removeTrackFromPc(localTrack: JitsiLocalTrack): Promise<boolean> {\n        const webRtcStream = localTrack.getOriginalStream();\n\n        this.trace('removeTrack', `${localTrack.rtcId} ${webRtcStream ? webRtcStream.id : 'null'}`);\n\n        if (!this._assertTrackBelongs('removeTrack', localTrack)) {\n            // Abort - nothing to be done here\n            return Promise.reject('Track not found in the peerconnection');\n        }\n\n        return this.replaceTrack(localTrack, null, true /* isMuteOperation */).then(() => false);\n    }\n\n    /**\n     * Updates the remote source map with the given source map for adding or removing sources.\n     *\n     * @param {Map<string, TPCSourceInfo>} sourceMap - The map of source names to their corresponding SSRCs.\n     * @param {boolean} isAdd - Whether the sources are being added or removed.\n     * @returns {void}\n     */\n    updateRemoteSources(sourceMap: Map<string, ITPCSourceInfo>, isAdd: boolean): void {\n        for (const [ sourceName, ssrcInfo ] of sourceMap) {\n            if (isAdd) {\n                this._remoteSsrcMap.set(sourceName, ssrcInfo);\n            } else {\n                this._remoteSsrcMap.delete(sourceName);\n            }\n        }\n    }\n\n    /**\n     * Returns true if the codec selection API is used for switching between codecs for the video sources.\n     *\n     * @returns {boolean}\n     */\n    usesCodecSelectionAPI(): boolean {\n        // Browser throws an error when H.264 is set on the encodings. Therefore, munge the SDP when H.264 needs to be\n        // selected.\n        // TODO: Remove this check when the above issue is fixed.\n        return this._usesCodecSelectionAPI && this.codecSettings.codecList[0] !== CodecMimeType.H264;\n    }\n\n    /**\n     * Creates a new data channel on the peer connection with the specified label and options.\n     */\n    createDataChannel(label: string, opts: RTCDataChannelInit): RTCDataChannel {\n        this.trace('createDataChannel', label, opts);\n\n        return this.peerconnection.createDataChannel(label, opts);\n    }\n\n    /**\n     * Returns the expected send resolution for a local video track based on what encodings are currently active.\n     *\n     * @param {JitsiLocalTrack} localTrack - The local video track.\n     * @returns {number}\n     */\n    calculateExpectedSendResolution(localTrack: JitsiLocalTrack): number {\n        const captureResolution = localTrack.getCaptureResolution();\n        let result = Math.min(localTrack.maxEnabledResolution, captureResolution);\n\n        if (localTrack.getVideoType() === VideoType.CAMERA) {\n            // Find the closest matching resolution based on the current codec, simulcast config and the requested\n            // resolution by the bridge or the peer.\n            if (this.doesTrueSimulcast(localTrack)) {\n                const sender = this.findSenderForTrack(localTrack.getTrack());\n\n                if (!sender) {\n                    return result;\n                }\n\n                const { encodings } = sender.getParameters() as RTCRtpSendParameters;\n\n                result = encodings.reduce((maxValue, encoding) => {\n                    if (encoding.active) {\n                        // eslint-disable-next-line no-param-reassign\n                        maxValue = Math.max(maxValue, Math.floor(captureResolution / encoding.scaleResolutionDownBy));\n                    }\n\n                    return maxValue;\n                }, 0);\n            }\n        }\n\n        return result;\n    }\n\n    /**\n     * Configures the stream encodings for the audio tracks that are added to the peerconnection.\n     *\n     * @param {Nullable<JitsiLocalTrack>} localAudioTrack - The local audio track.\n     * @returns {Promise} promise that will be resolved when the operation is successful and rejected otherwise.\n     */\n    configureAudioSenderEncodings(localAudioTrack: Nullable<JitsiLocalTrack> = null): Promise<PromiseSettledResult<void>[]> | Promise<void> {\n        if (localAudioTrack) {\n            return this._setEncodings(localAudioTrack);\n        }\n        const promises = [];\n\n        for (const track of this.getLocalTracks(MediaType.AUDIO)) {\n            promises.push(this._setEncodings(track));\n        }\n\n        return Promise.allSettled(promises);\n    }\n\n    /**\n     * Configures the stream encodings depending on the video type,\n     * scalability mode and the bitrate settings for the codec\n     * that is currently selected.\n     *\n     * @param {Nullable<JitsiLocalTrack>} - The local track for which the sender encodings have to configured.\n     * @param {CodecMimeType} - The preferred codec for the video track.\n     * @returns {Promise} promise that will be resolved when the operation is successful and rejected otherwise.\n     */\n    configureVideoSenderEncodings(localVideoTrack: Nullable<JitsiLocalTrack> = null, codec: Nullable<CodecMimeType> = null): Promise<PromiseSettledResult<void>[]> | Promise<void> {\n        const preferredCodec = codec ?? this.codecSettings.codecList[0];\n\n        if (localVideoTrack) {\n            const height = this._senderMaxHeights.get(localVideoTrack.getSourceName())\n            ?? VIDEO_QUALITY_LEVELS[0].height;\n\n            return this.setSenderVideoConstraints(height, localVideoTrack, preferredCodec);\n        }\n        const promises = [];\n\n        for (const track of this.getLocalVideoTracks()) {\n            const maxHeight = this._senderMaxHeights.get(track.getSourceName()) ?? VIDEO_QUALITY_LEVELS[0].height;\n\n            promises.push(this.setSenderVideoConstraints(maxHeight, track, preferredCodec));\n        }\n\n        return Promise.allSettled(promises);\n    }\n\n    /**\n     * Sets the local description on the peerconnection.\n     *\n     * @param {RTCSessionDescription} description - The local description to be set.\n     * @returns {Promise<void>} - Resolved when the operation is successful and rejected with an error otherwise.\n     */\n    setLocalDescription(description: RTCSessionDescription): Promise<void> {\n        let localDescription = description;\n\n        localDescription = this._mungeDescription(localDescription, true);\n\n        return new Promise((resolve, reject) => {\n            this.peerconnection.setLocalDescription(localDescription)\n                .then(() => {\n                    this.trace('setLocalDescriptionOnSuccess');\n                    const localUfrag = SDPUtil.getUfrag(localDescription.sdp);\n\n                    if (localUfrag !== this._localUfrag) {\n                        this._localUfrag = localUfrag;\n                        this.eventEmitter.emit(RTCEvents.LOCAL_UFRAG_CHANGED, this, localUfrag);\n                    }\n\n                    this._initializeDtlsTransport();\n\n                    resolve();\n                }, err => {\n                    this.trace('setLocalDescriptionOnFailure', err);\n                    reject(err);\n                });\n        });\n    }\n\n    /**\n     * Sets the remote description on the peerconnection.\n     *\n     * @param {RTCSessionDescription} description - The remote description to be set.\n     * @returns {Promise<void>} - Resolved when the operation is successful and rejected with an error otherwise.\n     */\n    setRemoteDescription(description: RTCSessionDescription): Promise<void> {\n        let remoteDescription = description;\n\n        if (this.isSpatialScalabilityOn()) {\n            remoteDescription = this.tpcUtils.insertUnifiedPlanSimulcastReceive(remoteDescription);\n            this.trace(\n                'setRemoteDescription::postTransform (sim receive)',\n                TraceablePeerConnection.dumpSDP(remoteDescription));\n        }\n        remoteDescription = this.tpcUtils.ensureCorrectOrderOfSsrcs(remoteDescription);\n        this.trace(\n            'setRemoteDescription::postTransform (correct ssrc order)',\n             TraceablePeerConnection.dumpSDP(remoteDescription));\n\n        remoteDescription = this._mungeDescription(remoteDescription, false);\n\n        return new Promise((resolve, reject) => {\n            this.peerconnection.setRemoteDescription(remoteDescription)\n                .then(() => {\n                    this.trace('setRemoteDescriptionOnSuccess');\n                    const remoteUfrag = SDPUtil.getUfrag(remoteDescription.sdp);\n\n                    if (remoteUfrag !== this._remoteUfrag) {\n                        this._remoteUfrag = remoteUfrag;\n                        this.eventEmitter.emit(RTCEvents.REMOTE_UFRAG_CHANGED, this, remoteUfrag);\n                    }\n\n                    this._initializeDtlsTransport();\n\n                    resolve();\n                })\n                .catch(err => {\n                    this.trace('setRemoteDescriptionOnFailure', err);\n                    reject(err);\n                });\n        });\n    }\n\n    /**\n     * Changes the resolution of the video stream that is sent to the peer based on the resolution requested by the peer\n     * and user preference, sets the degradation preference on the sender\n     * based on the video type, configures the maximum\n     * bitrates on the send stream.\n     *\n     * @param {number} frameHeight - The max frame height to be imposed on the outgoing video stream.\n     * @param {JitsiLocalTrack} - The local track for which the sender constraints have to be applied.\n     * @param {preferredCodec} - The video codec that needs to be configured on the\n     * sender associated with the video source.\n     * @returns {Promise} promise that will be resolved when the operation is successful and rejected otherwise.\n     */\n    setSenderVideoConstraints(frameHeight: number, localVideoTrack: JitsiLocalTrack, preferredCodec?: Optional<CodecMimeType>): Promise<void> {\n        if (frameHeight < 0 || !isValidNumber(frameHeight)) {\n            throw new Error(`Invalid frameHeight: ${frameHeight}`);\n        }\n        if (!localVideoTrack) {\n            throw new Error('Local video track is missing');\n        }\n        const sourceName = localVideoTrack.getSourceName();\n\n        this._senderMaxHeights.set(sourceName, frameHeight);\n\n        // Ignore sender constraints if the video track is muted.\n        if (localVideoTrack.isMuted()) {\n            return Promise.resolve();\n        }\n\n        const codec = preferredCodec ?? this.codecSettings.codecList[0];\n\n        return this._updateVideoSenderParameters(\n            () => this._updateVideoSenderEncodings(frameHeight, localVideoTrack, codec));\n    }\n\n    /**\n     * Resumes or suspends media on the peerconnection by setting the active state on RTCRtpEncodingParameters\n     * associated with all the senders that have a track attached to it.\n     *\n     * @param {boolean} enable - whether outgoing media needs to be enabled or disabled.\n     * @param {string} mediaType - media type, 'audio' or 'video', if neither is passed, all outgoing media will either\n     * be enabled or disabled.\n     * @returns {Promise} - A promise that is resolved when the change is succesful on all the senders, rejected\n     * otherwise.\n     */\n    setMediaTransferActive(enable: boolean, mediaType?: Optional<MediaType>): Promise<void> {\n        logger.info(`${this} ${enable ? 'Resuming' : 'Suspending'} media transfer.`);\n\n        const senders = this.peerconnection.getSenders()\n            .filter(s => Boolean(s.track) && (!mediaType || s.track.kind === mediaType));\n        const promises = [];\n\n        for (const sender of senders) {\n            if (sender.track.kind === MediaType.VIDEO) {\n                promises.push(this._updateVideoSenderParameters(() => this._enableSenderEncodings(sender, enable)));\n            } else {\n                promises.push(this._enableSenderEncodings(sender, enable));\n            }\n        }\n\n        return Promise.allSettled(promises)\n            .then(settledResult => {\n                const errors = settledResult\n                    .filter(result => result.status === 'rejected')\n                    .map(result => result.reason);\n\n                if (errors.length) {\n                    return Promise.reject(new Error('Failed to change encodings on the RTCRtpSenders'\n                        + `${errors.join(' ')}`));\n                }\n\n                return Promise.resolve();\n            });\n    }\n\n    /**\n     * Enables/disables outgoing video media transmission on this peer connection. When disabled the stream encoding's\n     * active state is enabled or disabled to send or stop the media.\n     * @param {boolean} active <tt>true</tt> to enable video media transmission\n     * or <tt>false</tt> to disable. If the value\n     * is not a boolean the call will have no effect.\n     * @return {Promise} A promise that is resolved when the change is succesful, rejected otherwise.\n     * @public\n     */\n    setVideoTransferActive(active: boolean): Promise<void> {\n        logger.debug(`${this} video transfer active: ${active}`);\n        const changed = this.videoTransferActive !== active;\n\n        this.videoTransferActive = active;\n\n        if (changed) {\n            return this.setMediaTransferActive(active, MediaType.VIDEO);\n        }\n\n        return Promise.resolve();\n    }\n\n    /**\n     * Sends DTMF tones if possible.\n     *\n     * @param {string} tones - The DTMF tones string as defined by {@code RTCDTMFSender.insertDTMF}, 'tones' argument.\n     * @param {number} duration - The amount of time in milliseconds that each DTMF should last. It's 200ms by default.\n     * @param {number} interToneGap - The length of time in miliseconds to wait between tones. It's 200ms by default.\n     *\n     * @returns {void}\n     */\n    sendTones(tones: string, duration = 200, interToneGap = 200): void {\n        if (!this._dtmfSender) {\n            if (this.peerconnection.getSenders) {\n                const rtpSender = this.peerconnection.getSenders().find(s => s.dtmf);\n\n                this._dtmfSender = rtpSender?.dtmf;\n                this._dtmfSender && logger.info(`${this} initialized DTMFSender using getSenders`);\n            }\n\n            if (!this._dtmfSender) {\n                const localAudioTrack = Array.from(this.localTracks.values()).find(t => t.isAudioTrack());\n\n                // @ts-ignore\n                if (this.peerconnection.createDTMFSender && localAudioTrack) {\n                    // @ts-ignore\n                    this._dtmfSender = this.peerconnection.createDTMFSender(localAudioTrack.getTrack());\n                }\n                this._dtmfSender && logger.info(`${this} initialized DTMFSender using deprecated createDTMFSender`);\n            }\n\n            if (this._dtmfSender) {\n                this._dtmfSender.ontonechange = this._onToneChange.bind(this);\n            }\n        }\n\n        if (this._dtmfSender) {\n            if (this._dtmfSender.toneBuffer) {\n                this._dtmfTonesQueue.push({\n                    duration,\n                    interToneGap,\n                    tones\n                });\n\n                return;\n            }\n\n            this._dtmfSender.insertDTMF(tones, duration, interToneGap);\n        } else {\n            logger.warn(`${this} sendTones - failed to select DTMFSender`);\n        }\n    }\n\n    /**\n     * Closes underlying WebRTC PeerConnection instance and removes all remote\n     * tracks by emitting {@link RTCEvents.REMOTE_TRACK_REMOVED} for each one of\n     * them.\n     */\n    close(): void {\n        this.trace('stop');\n\n        // Off SignalingEvents\n        this._signalingLayer.off(SignalingEvents.PEER_MUTED_CHANGED, this._peerMutedChanged);\n        this._signalingLayer.off(SignalingEvents.PEER_VIDEO_TYPE_CHANGED, this._peerVideoTypeChanged);\n        this.peerconnection.removeEventListener('track', this.onTrack);\n\n        if (FeatureFlags.isSsrcRewritingSupported()) {\n            for (const remoteTrack of this.remoteTracksBySsrc.values()) {\n                this._removeRemoteTrack(remoteTrack);\n            }\n            this.remoteTracksBySsrc.clear();\n        } else {\n            for (const peerTracks of this.remoteTracks.values()) {\n                for (const remoteTracks of peerTracks.values()) {\n                    for (const remoteTrack of remoteTracks) {\n                        this._removeRemoteTrack(remoteTrack);\n                    }\n                }\n            }\n            this.remoteTracks.clear();\n        }\n\n        this._dtmfSender = null;\n        this._dtmfTonesQueue = [];\n\n        if (!this.rtc._removePeerConnection(this)) {\n            logger.error(`${this} rtc._removePeerConnection returned false`);\n        }\n        if (this.statsinterval !== null) {\n            window.clearInterval(this.statsinterval);\n            this.statsinterval = null;\n        }\n        logger.info(`${this} Closing peerconnection`);\n        this.peerconnection.close();\n    }\n\n    /**\n     * Creates an SDP answer for the peer connection based on the provided constraints.\n     */\n    createAnswer(constraints: Optional<RTCOfferOptions>): Promise<RTCSessionDescription> {\n        return this._createOfferOrAnswer(false /* answer */, constraints);\n    }\n\n    /**\n     * Creates an SDP offer for the peer connection based on the provided constraints.\n     */\n    createOffer(constraints: Optional<RTCOfferOptions>): Promise<RTCSessionDescription> {\n        return this._createOfferOrAnswer(true /* offer */, constraints);\n    }\n\n    /**\n     * Track the SSRCs seen so far.\n     * @param {number} ssrc - SSRC.\n     * @return {boolean} - Whether this is a new SSRC.\n     */\n    addRemoteSsrc(ssrc: number): boolean {\n        const existing = this.remoteSSRCs.has(ssrc);\n\n        if (!existing) {\n            this.remoteSSRCs.add(ssrc);\n        }\n\n        return !existing;\n    }\n\n    /**\n     * Adds an ICE candidate to the peer connection.\n     */\n    addIceCandidate(candidate: RTCIceCandidate): Promise<void> {\n        this.trace('addIceCandidate', JSON.stringify({\n            candidate: candidate.candidate,\n            sdpMLineIndex: candidate.sdpMLineIndex,\n            sdpMid: candidate.sdpMid,\n            usernameFragment: candidate.usernameFragment\n        }, null, ' '));\n\n        return this.peerconnection.addIceCandidate(candidate);\n    }\n\n    /**\n     * Obtains call-related stats from the peer connection.\n     *\n     * @returns {Promise<Object>} Promise which resolves with data providing statistics about\n     * the peerconnection.\n     */\n    getStats(): Promise<RTCStatsReport> {\n        return this.peerconnection.getStats();\n    }\n\n    /**\n     * Creates a text representation of this <tt>TraceablePeerConnection</tt>\n     * instance.\n     * @return {string}\n     */\n    toString(): string {\n        return `TPC[id=${this.id},type=${this.isP2P ? 'P2P' : 'JVB'}]`;\n    }\n}\n","import { getLogger } from '@jitsi/logger';\nimport { cloneDeep, isEqual } from 'lodash-es';\n\nimport { JitsiConferenceEvents } from '../../JitsiConferenceEvents';\nimport { MediaType } from '../../service/RTC/MediaType';\nimport { RTCEvents } from '../../service/RTC/RTCEvents';\nimport { VideoType } from '../../service/RTC/VideoType';\nimport browser from '../browser';\nimport Listenable from '../util/Listenable';\nimport { safeCounterIncrement } from '../util/MathUtil';\n\nimport BridgeChannel from './BridgeChannel';\nimport JitsiLocalTrack from './JitsiLocalTrack';\nimport RTCUtils from './RTCUtils';\nimport TraceablePeerConnection from './TraceablePeerConnection';\n\n\nconst logger = getLogger('rtc:RTC');\n\n/**\n * The counter used to generated id numbers assigned to peer connections\n * @type {number}\n */\nlet peerConnectionIdCounter = 0;\n\n/**\n * The counter used to generate id number for the local\n * <code>MediaStreamTrack</code>s.\n * @type {number}\n */\nlet rtcTrackIdCounter = 0;\n\n/**\n * Creates {@code JitsiLocalTrack} instances from the passed in meta information\n * about MedieaTracks.\n *\n * @param {Object[]} mediaStreamMetaData - An array of meta information with\n * MediaTrack instances. Each can look like:\n * {{\n *     stream: MediaStream instance that holds a track with audio or video,\n *     track: MediaTrack within the MediaStream,\n *     videoType: \"camera\" or \"desktop\" or falsy,\n *     sourceId: ID of the desktopsharing source,\n *     sourceType: The desktopsharing source type,\n *     effects: Array of effect types\n * }}\n */\nfunction _createLocalTracks(mediaStreamMetaData = []) {\n    return mediaStreamMetaData.map(metaData => {\n        const {\n            constraints,\n            sourceId,\n            sourceType,\n            stream,\n            track,\n            videoType,\n            effects\n        } = metaData;\n\n        const { deviceId, facingMode } = track.getSettings();\n\n        // FIXME Move rtcTrackIdCounter to a static method in JitsiLocalTrack\n        // so RTC does not need to handle ID management. This move would be\n        // safer to do once the old createLocalTracks is removed.\n        rtcTrackIdCounter = safeCounterIncrement(rtcTrackIdCounter);\n\n        return new JitsiLocalTrack({\n            constraints,\n            deviceId,\n            effects,\n            facingMode,\n            mediaType: track.kind,\n            rtcId: rtcTrackIdCounter,\n            sourceId,\n            sourceType,\n            stream,\n            track,\n            videoType: videoType || null\n        });\n    });\n}\n\n/**\n *\n */\nexport default class RTC extends Listenable {\n    /**\n     *\n     * @param conference\n     * @param options\n     */\n    constructor(conference, options = {}) {\n        super();\n        this.conference = conference;\n\n        /**\n         * A map of active <tt>TraceablePeerConnection</tt>.\n         * @type {Map.<number, TraceablePeerConnection>}\n         */\n        this.peerConnections = new Map();\n\n        this.localTracks = [];\n\n        this.options = options;\n\n        // BridgeChannel instance.\n        // @private\n        // @type {BridgeChannel}\n        this._channel = null;\n\n        /**\n         * The value specified to the last invocation of setLastN before the\n         * channel completed opening. If non-null, the value will be sent\n         * through a channel (once) as soon as it opens and will then be\n         * discarded.\n         * @private\n         * @type {number}\n         */\n        this._lastN = undefined;\n\n        /**\n         * Defines the forwarded sources list. It can be null or an array once initialised with a channel forwarded\n         * sources event.\n         *\n         * @type {Array<string>|null}\n         * @private\n         */\n        this._forwardedSources = null;\n\n        // The forwarded sources change listener.\n        this._forwardedSourcesChangeListener = this._onForwardedSourcesChanged.bind(this);\n\n        this._onDeviceListChanged = this._onDeviceListChanged.bind(this);\n        this._updateAudioOutputForAudioTracks = this._updateAudioOutputForAudioTracks.bind(this);\n\n        // Switch audio output device on all remote audio tracks. Local audio\n        // tracks handle this event by themselves.\n        if (RTCUtils.isDeviceChangeAvailable('output')) {\n            RTCUtils.addListener(\n                RTCEvents.AUDIO_OUTPUT_DEVICE_CHANGED,\n                this._updateAudioOutputForAudioTracks\n            );\n\n            RTCUtils.addListener(\n                RTCEvents.DEVICE_LIST_CHANGED,\n                this._onDeviceListChanged\n            );\n        }\n    }\n\n    /**\n     * Removes any listeners and stored state from this {@code RTC} instance.\n     *\n     * @returns {void}\n     */\n    destroy() {\n        RTCUtils.removeListener(RTCEvents.AUDIO_OUTPUT_DEVICE_CHANGED, this._updateAudioOutputForAudioTracks);\n        RTCUtils.removeListener(RTCEvents.DEVICE_LIST_CHANGED, this._onDeviceListChanged);\n\n        if (this._channelOpenListener) {\n            this.removeListener(RTCEvents.DATA_CHANNEL_OPEN, this._channelOpenListener);\n        }\n    }\n\n    /**\n     * Exposes the private helper for converting a WebRTC MediaStream to a\n     * JitsiLocalTrack.\n     *\n     * @param {Array<Object>} tracksInfo\n     * @returns {Array<JitsiLocalTrack>}\n     */\n    static createLocalTracks(tracksInfo) {\n        return _createLocalTracks(tracksInfo);\n    }\n\n    /**\n     * Creates the local MediaStreams.\n     * @param {object} [options] Optional parameters.\n     * @param {Array=} options.devices The devices that will be requested.\n     * @param {string=} options.resolution Resolution constraints.\n     * @param {string=} options.cameraDeviceId\n     * @param {string=} options.micDeviceId\n     * @returns {*} Promise object that will receive the new JitsiTracks\n     */\n    static obtainAudioAndVideoPermissions(options) {\n        return RTCUtils.obtainAudioAndVideoPermissions(options)\n            .then(tracksInfo => _createLocalTracks(tracksInfo));\n    }\n\n    /**\n     * Initializes the bridge channel of this instance.\n     * At least one of both, peerconnection or wsUrl parameters, must be\n     * given.\n     * @param {RTCPeerConnection} [peerconnection] WebRTC peer connection\n     * instance.\n     * @param {string} [wsUrl] WebSocket URL.\n     */\n    initializeBridgeChannel(peerconnection, wsUrl) {\n        this._channel = new BridgeChannel(peerconnection, wsUrl, this.eventEmitter, this.conference);\n\n        this._channelOpenListener = () => {\n            const logError = (error, msgType, value) => {\n                logger.error(`Cannot send ${msgType}(${JSON.stringify(value)}) endpoint message`, error);\n            };\n\n            // When the channel becomes available, tell the bridge about video selections so that it can do adaptive\n            // simulcast, we want the notification to trigger even if userJid is undefined, or null.\n            if (this._receiverVideoConstraints) {\n                try {\n                    this._channel.sendReceiverVideoConstraintsMessage(this._receiverVideoConstraints);\n                } catch (error) {\n                    logError(error, 'ReceiverVideoConstraints', this._receiverVideoConstraints);\n                }\n            }\n            if (typeof this._lastN !== 'undefined' && this._lastN !== -1) {\n                try {\n                    this._channel.sendSetLastNMessage(this._lastN);\n                } catch (error) {\n                    logError(error, 'LastNChangedEvent', this._lastN);\n                }\n            }\n        };\n        this.addListener(RTCEvents.DATA_CHANNEL_OPEN, this._channelOpenListener);\n\n        // Add forwarded sources change listener.\n        this.addListener(RTCEvents.FORWARDED_SOURCES_CHANGED, this._forwardedSourcesChangeListener);\n    }\n\n    /**\n     * Callback invoked when the list of known audio and video devices has\n     * been updated. Attempts to update the known available audio output\n     * devices.\n     *\n     * @private\n     * @returns {void}\n     */\n    _onDeviceListChanged() {\n        this._updateAudioOutputForAudioTracks(RTCUtils.getAudioOutputDevice());\n    }\n\n    /**\n     * Receives events when forwarded sources had changed.\n     *\n     * @param {array} forwardedSources The new forwarded sources.\n     * @private\n     */\n    _onForwardedSourcesChanged(forwardedSources = []) {\n        const oldForwardedSources = this._forwardedSources || [];\n        let leavingForwardedSources = [];\n        let enteringForwardedSources = [];\n        const timestamp = Date.now();\n\n        this._forwardedSources = forwardedSources;\n\n        leavingForwardedSources = oldForwardedSources.filter(sourceName => !this.isInForwardedSources(sourceName));\n\n        enteringForwardedSources = forwardedSources.filter(\n            sourceName => oldForwardedSources.indexOf(sourceName) === -1);\n\n        logger.debug(`Fowarded sources changed leaving=${leavingForwardedSources}, entering=`\n            + `${enteringForwardedSources} at ${timestamp}`);\n        this.conference.eventEmitter.emit(\n            JitsiConferenceEvents.FORWARDED_SOURCES_CHANGED,\n            leavingForwardedSources,\n            enteringForwardedSources,\n            timestamp);\n    }\n\n    /**\n     * Should be called when current media session ends and after the\n     * PeerConnection has been closed using PeerConnection.close() method.\n     */\n    onCallEnded() {\n        if (this._channel) {\n            // The BridgeChannel is not explicitly closed as the PeerConnection\n            // is closed on call ended which triggers datachannel onclose\n            // events. If using a WebSocket, the channel must be closed since\n            // it is not managed by the PeerConnection.\n            // The reference is cleared to disable any logic related to the\n            // channel.\n            if (this._channel && this._channel.mode === 'websocket') {\n                this._channel.close();\n            }\n\n            this._channel = null;\n        }\n    }\n\n    /**\n     * Sets the capture frame rate to be used for desktop tracks.\n     *\n     * @param {number} maxFps framerate to be used for desktop track capture.\n     */\n    setDesktopSharingFrameRate(maxFps) {\n        RTCUtils.setDesktopSharingFrameRate(maxFps);\n    }\n\n    /**\n     * Sets the receiver video constraints that determine how bitrate is allocated to each of the video streams\n     * requested from the bridge. The constraints are cached and sent through the bridge channel once the channel\n     * is established.\n     * @param {*} constraints\n     */\n    setReceiverVideoConstraints(constraints) {\n        if (isEqual(this._receiverVideoConstraints, constraints)) {\n            return;\n        }\n\n        this._receiverVideoConstraints = cloneDeep(constraints);\n\n        if (this._channel && this._channel.isOpen()) {\n            this._channel.sendReceiverVideoConstraintsMessage(constraints);\n        }\n    }\n\n    /**\n     * Sends the track's  video type to the JVB.\n     * @param {SourceName} sourceName - the track's source name.\n     * @param {BridgeVideoType} videoType - the track's video type.\n     */\n    sendSourceVideoType(sourceName, videoType) {\n        if (this._channel && this._channel.isOpen()) {\n            this._channel.sendSourceVideoTypeMessage(sourceName, videoType);\n        }\n    }\n\n    /**\n     *\n     * @param eventType\n     * @param listener\n     */\n    static addListener(eventType, listener) {\n        RTCUtils.addListener(eventType, listener);\n    }\n\n    /**\n     *\n     * @param eventType\n     * @param listener\n     */\n    static removeListener(eventType, listener) {\n        RTCUtils.removeListener(eventType, listener);\n    }\n\n    /**\n     *\n     * @param options\n     */\n    static init(options = {}) {\n        this.options = options;\n\n        return RTCUtils.init(this.options);\n    }\n\n    /* eslint-disable max-params */\n\n    /**\n     * Creates new <tt>TraceablePeerConnection</tt>\n     * @param {SignalingLayer} signaling The signaling layer that will provide information about the media or\n     * participants which is not carried over SDP.\n     * @param {object} pcConfig The {@code RTCConfiguration} to use for the WebRTC peer connection.\n     * @param {boolean} isP2P Indicates whether or not the new TPC will be used in a peer to peer type of session.\n     * @param {object} options The config options.\n     * @param {Object} options.audioQuality - Quality settings to applied on the outbound audio stream.\n     * @param {boolean} options.capScreenshareBitrate if set to true, lower layers will be disabled for screenshare.\n     * @param {Array<CodecMimeType>} options.codecSettings - codec settings to be applied for video streams.\n     * @param {boolean} options.disableSimulcast if set to 'true' will disable the simulcast.\n     * @param {boolean} options.disableRtx if set to 'true' will disable the RTX.\n     * @param {boolean} options.enableInsertableStreams set to true when the insertable streams constraints is to be\n     * enabled on the PeerConnection.\n     * @param {boolean} options.forceTurnRelay If set to true, the browser will generate only Relay ICE candidates.\n     * @param {boolean} options.startSilent If set to 'true' no audio will be sent or received.\n     * @param {Object} options.videoQuality - Quality settings to applied on the outbound video streams.\n     * @return {TraceablePeerConnection}\n     */\n    createPeerConnection(signaling, pcConfig, isP2P, options) {\n        const pcConstraints = {};\n\n        if (options.enableInsertableStreams) {\n            logger.debug('E2EE - setting insertable streams constraints');\n            pcConfig.encodedInsertableStreams = true;\n        }\n\n        if (options.forceTurnRelay) {\n            pcConfig.iceTransportPolicy = 'relay';\n        }\n\n        // Set the RTCBundlePolicy to max-bundle so that only one set of ice candidates is generated.\n        // The default policy generates separate ice candidates for audio and video connections.\n        // This change is necessary for Unified plan to work properly on Chrome and Safari.\n        pcConfig.bundlePolicy = 'max-bundle';\n\n        peerConnectionIdCounter = safeCounterIncrement(peerConnectionIdCounter);\n\n        const newConnection\n            = new TraceablePeerConnection(\n                this,\n                peerConnectionIdCounter,\n                signaling,\n                pcConfig, pcConstraints,\n                isP2P, options);\n\n        this.peerConnections.set(newConnection.id, newConnection);\n\n        return newConnection;\n    }\n\n    /* eslint-enable max-params */\n\n    /**\n     * Removed given peer connection from this RTC module instance.\n     * @param {TraceablePeerConnection} traceablePeerConnection\n     * @return {boolean} <tt>true</tt> if the given peer connection was removed\n     * successfully or <tt>false</tt> if there was no peer connection mapped in\n     * this RTC instance.\n     */\n    _removePeerConnection(traceablePeerConnection) {\n        const id = traceablePeerConnection.id;\n\n        if (this.peerConnections.has(id)) {\n            // NOTE Remote tracks are not removed here.\n            this.peerConnections.delete(id);\n\n            return true;\n        }\n\n        return false;\n\n    }\n\n    /**\n     *\n     * @param track\n     */\n    addLocalTrack(track) {\n        if (!track) {\n            throw new Error('track must not be null nor undefined');\n        }\n\n        this.localTracks.push(track);\n\n        track.conference = this.conference;\n    }\n\n    /**\n     * Get forwarded sources list.\n     * @returns {Array<string>|null}\n     */\n    getForwardedSources() {\n        return this._forwardedSources;\n    }\n\n    /**\n     * Get local video track.\n     * @returns {JitsiLocalTrack|undefined}\n     */\n    getLocalVideoTrack() {\n        const localVideo = this.getLocalTracks(MediaType.VIDEO);\n\n        return localVideo.length ? localVideo[0] : undefined;\n    }\n\n    /**\n     * Returns all the local video tracks.\n     * @returns {Array<JitsiLocalTrack>}\n     */\n    getLocalVideoTracks() {\n        return this.getLocalTracks(MediaType.VIDEO);\n    }\n\n    /**\n     * Get local audio track.\n     * @returns {JitsiLocalTrack|undefined}\n     */\n    getLocalAudioTrack() {\n        const localAudio = this.getLocalTracks(MediaType.AUDIO);\n\n        return localAudio.length ? localAudio[0] : undefined;\n    }\n\n    /**\n     * Returns the endpoint id for the local user.\n     * @returns {string}\n     */\n    getLocalEndpointId() {\n        return this.conference.myUserId();\n    }\n\n    /**\n     * Returns the local tracks of the given media type, or all local tracks if\n     * no specific type is given.\n     * @param {MediaType} [mediaType] Optional media type filter.\n     * (audio or video).\n     */\n    getLocalTracks(mediaType) {\n        if (!mediaType) {\n            return this.localTracks.slice();\n        }\n\n        return this.localTracks.filter(\n                track => track.getType() === mediaType);\n    }\n\n    /**\n     * Obtains all remote tracks currently known to this RTC module instance.\n     * @param {MediaType} [mediaType] The remote tracks will be filtered\n     *      by their media type if this argument is specified.\n     * @return {Array<JitsiRemoteTrack>}\n     */\n    getRemoteTracks(mediaType) {\n        let remoteTracks = [];\n\n        for (const tpc of this.peerConnections.values()) {\n            const pcRemoteTracks = tpc.getRemoteTracks(undefined, mediaType);\n\n            if (pcRemoteTracks) {\n                remoteTracks = remoteTracks.concat(pcRemoteTracks);\n            }\n        }\n\n        return remoteTracks;\n    }\n\n    /**\n     * Set mute for all local audio streams attached to the conference.\n     * @returns {Promise}\n     */\n    setAudioMute() {\n        const mutePromises = [];\n\n        this.getLocalTracks(MediaType.AUDIO).forEach(audioTrack => {\n            mutePromises.push(audioTrack.mute());\n        });\n\n        return Promise.all(mutePromises);\n    }\n\n    /**\n    * Set mute for all local video streams attached to the conference.\n    * @returns {Promise}\n    */\n    setVideoMute() {\n        const mutePromises = [];\n        const tracks = this.localTracks.filter(\n                track => track.getType() === MediaType.VIDEO\n                && track.getVideoType() === VideoType.CAMERA);\n\n        tracks.forEach(track => mutePromises.push(track.mute()));\n\n        return Promise.all(mutePromises);\n    }\n\n    /**\n    * Set mute for all local desktop video streams attached to the conference.\n    * @returns {Promise}\n    */\n    setDesktopMute() {\n        const mutePromises = [];\n        const tracks = this.localTracks.filter(\n                track => track.getType() === MediaType.VIDEO\n                && track.getVideoType() === VideoType.DESKTOP);\n\n        tracks.forEach(track => mutePromises.push(track.mute()));\n\n        return Promise.all(mutePromises);\n    }\n\n    /**\n     *\n     * @param track\n     */\n    removeLocalTrack(track) {\n        const pos = this.localTracks.indexOf(track);\n\n        if (pos === -1) {\n            return;\n        }\n\n        this.localTracks.splice(pos, 1);\n    }\n\n    /**\n     *\n     * @param elSelector\n     * @param stream\n     */\n    static attachMediaStream(elSelector, stream) {\n        return RTCUtils.attachMediaStream(elSelector, stream);\n    }\n\n    /**\n     * Returns true if changing the input (camera / microphone) or output\n     * (audio) device is supported and false if not.\n     * @param {string} [deviceType] Type of device to change. Default is\n     *      undefined or 'input', 'output' - for audio output device change.\n     * @returns {boolean} true if available, false otherwise.\n     */\n    static isDeviceChangeAvailable(deviceType) {\n        return RTCUtils.isDeviceChangeAvailable(deviceType);\n    }\n\n    /**\n     * Returns whether the current execution environment supports WebRTC (for\n     * use within this library).\n     *\n     * @returns {boolean} {@code true} if WebRTC is supported in the current\n     * execution environment (for use within this library); {@code false},\n     * otherwise.\n     */\n    static isWebRtcSupported() {\n        return browser.isSupported();\n    }\n\n    /**\n     * Returns currently used audio output device id, '' stands for default\n     * device\n     * @returns {string}\n     */\n    static getAudioOutputDevice() {\n        return RTCUtils.getAudioOutputDevice();\n    }\n\n    /**\n     * Returns list of available media devices if its obtained, otherwise an\n     * empty array is returned/\n     * @returns {array} list of available media devices.\n     */\n    static getCurrentlyAvailableMediaDevices() {\n        return RTCUtils.getCurrentlyAvailableMediaDevices();\n    }\n\n    /**\n     * Returns event data for device to be reported to stats.\n     * @returns {MediaDeviceInfo} device.\n     */\n    static getEventDataForActiveDevice(device) {\n        return RTCUtils.getEventDataForActiveDevice(device);\n    }\n\n    /**\n     * Sets current audio output device.\n     * @param {string} deviceId Id of 'audiooutput' device from\n     *      navigator.mediaDevices.enumerateDevices().\n     * @returns {Promise} resolves when audio output is changed, is rejected\n     *      otherwise\n     */\n    static setAudioOutputDevice(deviceId) {\n        return RTCUtils.setAudioOutputDevice(deviceId);\n    }\n\n    /**\n     * Allows to receive list of available cameras/microphones.\n     * @param {function} callback Would receive array of devices as an\n     *      argument.\n     */\n    static enumerateDevices(callback) {\n        RTCUtils.enumerateDevices(callback);\n    }\n\n    /**\n     * A method to handle stopping of the stream.\n     * One point to handle the differences in various implementations.\n     * @param {MediaStream} mediaStream MediaStream object to stop.\n     */\n    static stopMediaStream(mediaStream) {\n        RTCUtils.stopMediaStream(mediaStream);\n    }\n\n    /**\n     * Returns whether the desktop sharing is enabled or not.\n     * @returns {boolean}\n     */\n    static isDesktopSharingEnabled() {\n        return RTCUtils.isDesktopSharingEnabled();\n    }\n\n    /**\n     * Closes the currently opened bridge channel.\n     */\n    closeBridgeChannel() {\n        if (this._channel) {\n            this._channel.close();\n            this._channel = null;\n        }\n    }\n\n    /* eslint-disable max-params */\n    /**\n     *\n     * @param {TraceablePeerConnection} tpc\n     * @param {number} ssrc\n     * @param {number} audioLevel\n     * @param {boolean} isLocal\n     */\n    setAudioLevel(tpc, ssrc, audioLevel, isLocal) {\n        const track = tpc.getTrackBySSRC(ssrc);\n\n        if (!track) {\n            return;\n        } else if (!track.isAudioTrack()) {\n            logger.warn(`Received audio level for non-audio track: ${ssrc}`);\n\n            return;\n        } else if (track.isLocal() !== isLocal) {\n            logger.error(\n                `${track} was expected to ${isLocal ? 'be' : 'not be'} local`);\n        }\n\n        track.setAudioLevel(audioLevel, tpc);\n    }\n\n    /**\n     * Sends message via the bridge channel.\n     * @param {string} to The id of the endpoint that should receive the\n     *      message. If \"\" the message will be sent to all participants.\n     * @param {object} payload The payload of the message.\n     * @throws NetworkError or InvalidStateError or Error if the operation\n     * fails or there is no data channel created.\n     */\n    sendChannelMessage(to, payload) {\n        if (this._channel) {\n            this._channel.sendMessage(to, payload);\n        } else {\n            throw new Error('BridgeChannel has not been initialized yet');\n        }\n    }\n\n    /**\n     * Sends the local stats via the bridge channel.\n     * @param {Object} payload The payload of the message.\n     * @throws NetworkError/InvalidStateError/Error if the operation fails or if there is no data channel created.\n     */\n    sendEndpointStatsMessage(payload) {\n        if (this._channel && this._channel.isOpen()) {\n            this._channel.sendEndpointStatsMessage(payload);\n        }\n    }\n\n    /**\n     * Sends a receiver audio subscription message.\n     * @param {*} message\n     */\n    sendReceiverAudioSubscriptionMessage(message) {\n        if (this._channel && this._channel.isOpen()) {\n            this._channel.sendReceiverAudioSubscriptionMessage(message);\n        }\n    }\n\n    /**\n     * Selects a new value for \"lastN\". The requested amount of videos are going\n     * to be delivered after the value is in effect. Set to -1 for unlimited or\n     * all available videos.\n     * @param {number} value the new value for lastN.\n     */\n    setLastN(value) {\n        if (this._lastN !== value) {\n            this._lastN = value;\n            if (this._channel && this._channel.isOpen()) {\n                this._channel.sendSetLastNMessage(value);\n            }\n            this.eventEmitter.emit(RTCEvents.LASTN_VALUE_CHANGED, value);\n        }\n    }\n\n    /**\n     * Indicates if the source name is currently included in the forwarded sources.\n     *\n     * @param {string} sourceName The source name that we check for forwarded sources.\n     * @returns {boolean} true if the source name is in the forwarded sources or if we don't have bridge channel\n     * support, otherwise we return false.\n     */\n    isInForwardedSources(sourceName) {\n        return !this._forwardedSources // forwardedSources not initialised yet.\n            || this._forwardedSources.indexOf(sourceName) > -1;\n    }\n\n    /**\n     * Updates the target audio output device for all remote audio tracks.\n     *\n     * @param {string} deviceId - The device id of the audio ouput device to\n     * use for all remote tracks.\n     * @private\n     * @returns {void}\n     */\n    _updateAudioOutputForAudioTracks(deviceId) {\n        const remoteAudioTracks = this.getRemoteTracks(MediaType.AUDIO);\n\n        for (const track of remoteAudioTracks) {\n            track.setAudioOutput(deviceId);\n        }\n    }\n}\n","export enum ConnectionQualityEvents {\n\n    /**\n     * Indicates that the local connection statistics were updated.\n     */\n    LOCAL_STATS_UPDATED = 'cq.local_stats_updated',\n\n    /**\n     * Indicates that the connection statistics for a particular remote participant\n     * were updated.\n     */\n    REMOTE_STATS_UPDATED = 'cq.remote_stats_updated'\n}\n","import { getLogger } from '@jitsi/logger';\n\nimport JitsiConference, { IConferenceOptions } from '../../JitsiConference';\nimport { JitsiConferenceEvents as ConferenceEvents } from '../../JitsiConferenceEvents';\nimport JitsiParticipant from '../../JitsiParticipant';\nimport { RTCEvents } from '../../service/RTC/RTCEvents';\nimport Resolutions from '../../service/RTC/Resolutions';\nimport { VIDEO_QUALITY_LEVELS } from '../../service/RTC/StandardVideoQualitySettings';\nimport { VideoType } from '../../service/RTC/VideoType';\nimport { ConnectionQualityEvents } from '../../service/connectivity/ConnectionQualityEvents';\nimport { XMPPEvents } from '../../service/xmpp/XMPPEvents';\nimport TraceablePeerConnection from '../RTC/TraceablePeerConnection';\nimport EventEmitter from '../util/EventEmitter';\nimport JingleSessionPC from '../xmpp/JingleSessionPC';\n\nconst logger = getLogger('connectivity:ConnectionQuality');\n\n/**\n * The value to use for the \"type\" field for messages sent by ConnectionQuality\n * over the data channel.\n */\nconst STATS_MESSAGE_TYPE = 'stats';\n\n/**\n * The maximum bitrate to use as a measurement against the participant's current\n * bitrate. This cap helps in the cases where the participant's bitrate is high\n * but not enough to fulfill high targets, such as with 1080p.\n */\nconst MAX_TARGET_BITRATE = 2500;\n\n/**\n * The initial bitrate for video in kbps.\n */\nconst startBitrate = 800;\n\n/**\n * Gets the expected bitrate (in kbps) in perfect network conditions.\n * @param simulcast {boolean} whether simulcast is enabled or not.\n * @param resolution {Resolution} the resolution.\n * @param millisSinceStart {number} the number of milliseconds since sending video started.\n * @param bitrates {Object} the bitrates for the local video source.\n */\nfunction getTarget(simulcast: boolean, resolution: { height: number; width: number; }, millisSinceStart: number, bitrates?: { download: number; upload: number; }): number {\n    let target = 0;\n    let height = Math.min(resolution.height, resolution.width);\n\n    // Find the first format with height no bigger than ours.\n    let qualityLevel = VIDEO_QUALITY_LEVELS.find(f => f.height <= height);\n\n    if (qualityLevel && simulcast) {\n        // Sum the target fields from all simulcast layers for the given\n        // resolution (e.g. 720p + 360p + 180p) for VP8 simulcast.\n        for (height = qualityLevel.height; height >= 180; height /= 2) {\n            const targetHeight = height;\n\n            qualityLevel = VIDEO_QUALITY_LEVELS.find(f => f.height === targetHeight);\n            if (qualityLevel) {\n                target += bitrates[qualityLevel.level];\n            } else {\n                break;\n            }\n        }\n    } else if (qualityLevel) {\n        // For VP9 SVC, H.264 (simulcast automatically disabled) and p2p, target bitrate will be\n        // same as that of the individual stream bitrate.\n        target = bitrates[qualityLevel.level];\n    }\n\n    // Allow for an additional 1 second for ramp up -- delay any initial drop\n    // of connection quality by 1 second. Convert target from bps to kbps.\n    return Math.min(target / 1000, rampUp(Math.max(0, millisSinceStart - 1000)));\n}\n\n/**\n * Gets the bitrate to which GCC would have ramped up in perfect network\n * conditions after millisSinceStart milliseconds.\n * @param millisSinceStart {number} the number of milliseconds since sending\n * video was enabled.\n */\nfunction rampUp(millisSinceStart: number): number {\n    if (millisSinceStart > 60000) {\n        return Number.MAX_SAFE_INTEGER;\n    }\n\n    // According to GCC the send side bandwidth estimation grows with at most\n    // 8% per second.\n    // https://tools.ietf.org/html/draft-ietf-rmcat-gcc-02#section-5.5\n    return startBitrate * Math.pow(1.08, millisSinceStart / 1000);\n}\n\nexport interface ILocalStats {\n    bandwidth?: {\n        download?: number;\n        upload?: number;\n    };\n    bitrate?: {\n        upload: number;\n    };\n    bridgeCount?: number;\n    connectionQuality: number;\n    jvbRTT?: number;\n    maxEnabledResolution?: { height: number; width: number; };\n    packetLoss?: {\n        upload?: number;\n    };\n    serverRegion?: string;\n}\n\nexport type IRemoteStats = Pick<\n    ILocalStats,\n    'bitrate' | 'connectionQuality' | 'jvbRTT' | 'maxEnabledResolution' | 'packetLoss' | 'serverRegion'\n>;\n\n/**\n * A class which monitors the local statistics coming from the RTC modules, and\n * calculates a \"connection quality\" value, in percent, for the media\n * connection. A value of 100% indicates a very good network connection, and a\n * value of 0% indicates a poor connection.\n */\nexport default class ConnectionQuality {\n    private eventEmitter: EventEmitter;\n    private _conference: JitsiConference;\n    private _localStats: ILocalStats;\n    private _lastConnectionQualityUpdate: number;\n    private _options: IConferenceOptions;\n    private _remoteStats: { [key: string]: any; };\n    private _timeIceConnected: number;\n    private _timeVideoUnmuted: number;\n\n    /**\n     *\n     * @param conference\n     * @param eventEmitter\n     * @param options\n     */\n    constructor(conference: JitsiConference, eventEmitter: EventEmitter, options: IConferenceOptions) {\n        this.eventEmitter = eventEmitter;\n\n        /**\n         * The owning JitsiConference.\n         */\n        this._conference = conference;\n\n        /**\n         * Holds statistics about the local connection quality.\n         */\n        this._localStats = {\n            connectionQuality: 100,\n            jvbRTT: undefined\n        };\n\n        /**\n         * The time this._localStats.connectionQuality was last updated.\n         */\n        this._lastConnectionQualityUpdate = -1;\n\n        /**\n         * Conference options.\n         */\n        this._options = options;\n\n        /**\n         * Maps a participant ID to an object holding connection quality\n         * statistics received from this participant.\n         */\n        this._remoteStats = {};\n\n        /**\n         * The time that the ICE state last changed to CONNECTED. We use this\n         * to calculate how much time we as a sender have had to ramp-up.\n         */\n        this._timeIceConnected = -1;\n\n        /**\n         * The time that local video was unmuted. We use this to calculate how\n         * much time we as a sender have had to ramp-up.\n         */\n        this._timeVideoUnmuted = -1;\n\n        conference.on(\n            ConferenceEvents.BRIDGE_BWE_STATS_RECEIVED,\n            bwe => {\n                if (bwe && this._localStats?.bandwidth) {\n                    this._localStats.bandwidth.download = Math.floor(bwe / 1000);\n                }\n            });\n\n        // TODO: consider ignoring these events and letting the user of\n        // lib-jitsi-meet handle these separately.\n        conference.on(\n            ConferenceEvents.CONNECTION_INTERRUPTED,\n            () => {\n                this._updateLocalConnectionQuality(0);\n                this.eventEmitter.emit(ConnectionQualityEvents.LOCAL_STATS_UPDATED, this._localStats);\n                this._broadcastLocalStats();\n            });\n\n        conference.room.addListener(\n            XMPPEvents.ICE_CONNECTION_STATE_CHANGED,\n            (jingleSession: JingleSessionPC, newState: string) => {\n                if (!jingleSession.isP2P && newState === 'connected') {\n                    this._timeIceConnected = window.performance.now();\n                }\n            });\n\n        // Listen to DataChannel message from other participants in the\n        // conference, and update the _remoteStats field accordingly.\n        // TODO - Delete this when all the mobile endpoints switch to using the new Colibri\n        // message format for sending the endpoint stats.\n        conference.on(\n            ConferenceEvents.ENDPOINT_MESSAGE_RECEIVED,\n            (participant: JitsiParticipant, payload: { type: string; values: any; }) => {\n                if (payload.type === STATS_MESSAGE_TYPE) {\n                    this._updateRemoteStats(participant.getId(), payload.values);\n                }\n            });\n\n        conference.on(\n            ConferenceEvents.ENDPOINT_STATS_RECEIVED,\n            (participant: JitsiParticipant, payload: IRemoteStats) => {\n                this._updateRemoteStats(participant.getId(), payload);\n            });\n\n        if (!this._options.config.disableLocalStats) {\n            // Listen to local statistics events originating from the RTC module and update the _localStats field.\n            conference.statistics.addConnectionStatsListener(this._updateLocalStats.bind(this));\n        }\n\n        // Save the last time we were unmuted.\n        conference.on(\n            ConferenceEvents.TRACK_MUTE_CHANGED,\n            track => {\n                if (track.isVideoTrack()) {\n                    if (track.isMuted()) {\n                        this._timeVideoUnmuted = -1;\n                    } else {\n                        this._maybeUpdateUnmuteTime();\n                    }\n                }\n            });\n        conference.on(\n            ConferenceEvents.TRACK_ADDED,\n            track => {\n                if (track.isVideoTrack() && !track.isMuted()) {\n                    this._maybeUpdateUnmuteTime();\n                }\n            });\n\n        conference.on(ConferenceEvents.VIDEO_CODEC_CHANGED, this._resetVideoUnmuteTime.bind(this));\n\n        conference.on(ConferenceEvents._MEDIA_SESSION_ACTIVE_CHANGED, this._resetVideoUnmuteTime.bind(this));\n\n        conference.rtc.on(\n            RTCEvents.LOCAL_TRACK_MAX_ENABLED_RESOLUTION_CHANGED,\n            track => {\n                this._localStats.maxEnabledResolution = track.maxEnabledResolution;\n            });\n\n        conference.on(\n            ConferenceEvents.SERVER_REGION_CHANGED,\n            serverRegion => {\n                this._localStats.serverRegion = serverRegion;\n            });\n\n        conference.on(\n            ConferenceEvents.PROPERTIES_CHANGED,\n            properties => {\n                this._localStats.bridgeCount\n                    = Number(properties?.['bridge-count']);\n            }\n        );\n    }\n\n    /**\n     * Broadcasts the local statistics to all other participants in the\n     * conference.\n     */\n    private _broadcastLocalStats(): void {\n        // broadcasting local stats is disabled\n        if (this._options.config.disableLocalStatsBroadcast) {\n            return;\n        }\n\n        // Send only the data that remote participants care about.\n        const data = {\n            bitrate: this._localStats.bitrate,\n            connectionQuality: this._localStats.connectionQuality,\n            jvbRTT: this._localStats.jvbRTT,\n            maxEnabledResolution: this._localStats.maxEnabledResolution,\n            packetLoss: this._localStats.packetLoss,\n            serverRegion: this._localStats.serverRegion\n        };\n\n        try {\n            this._conference.sendEndpointStatsMessage(data);\n        } catch (err) {\n            // Ignore the error as we might hit it in the beginning of the call before the channel is ready.\n            // The statistics will be sent again after few seconds and error is logged elseware as well.\n        }\n    }\n\n    /**\n     * Calculates a new \"connection quality\" value.\n     * @param videoType {VideoType} the type of the video source (camera or a screen capture).\n     * @param isMuted {boolean} whether the local video is muted.\n     * @param resolutionName {Resolution} the input resolution used by the camera.\n     * @returns {*} the newly calculated connection quality.\n     */\n    private _calculateConnectionQuality(videoType: VideoType, isMuted: boolean, resolutionName: keyof typeof Resolutions): number {\n\n        // resolutionName is an index into Resolutions (where \"720\" is\n        // \"1280x720\" and \"960\" is \"960x720\" ...).\n        const resolution = Resolutions[resolutionName];\n\n        let quality = 100;\n        let packetLoss;\n\n        // TODO: take into account packet loss for received streams\n        if (this._localStats.packetLoss) {\n            packetLoss = this._localStats.packetLoss.upload;\n        }\n\n        if (isMuted || !resolution || videoType === VideoType.DESKTOP\n            || this._timeIceConnected < 0\n            || this._timeVideoUnmuted < 0) {\n\n            // Calculate a value based on packet loss only.\n            if (packetLoss === undefined) {\n                logger.error('Cannot calculate connection quality, unknown '\n                    + 'packet loss.');\n                quality = 100;\n            } else if (packetLoss <= 2) {\n                quality = 100; // Full 5 bars.\n            } else if (packetLoss <= 4) {\n                quality = 70; // 4 bars\n            } else if (packetLoss <= 6) {\n                quality = 50; // 3 bars\n            } else if (packetLoss <= 8) {\n                quality = 30; // 2 bars\n            } else if (packetLoss <= 12) {\n                quality = 10; // 1 bars\n            } else {\n                quality = 0; // Still 1 bar, but slower climb-up.\n            }\n        } else {\n            // Calculate a value based on the send video bitrate on the active TPC.\n            const activeTPC = this._conference.getActivePeerConnection();\n\n            if (activeTPC) {\n                // Time since sending of video was enabled.\n                const millisSinceStart = window.performance.now()\n                    - Math.max(this._timeVideoUnmuted, this._timeIceConnected);\n                const statsInterval = this._options.config?.pcStatsInterval ?? 10000;\n\n                // Expected sending bitrate in perfect conditions.\n                let target = getTarget(\n                    activeTPC.doesTrueSimulcast(undefined),\n                    resolution,\n                    millisSinceStart,\n                    activeTPC.getTargetVideoBitrates(undefined));\n\n                target = Math.min(target, MAX_TARGET_BITRATE);\n\n                // Calculate the quality only after the stats are available (after video was enabled).\n                if (millisSinceStart > statsInterval) {\n                    quality = 100 * this._localStats.bitrate.upload / target;\n                }\n            }\n\n            // Whatever the bitrate, drop early if there is significant loss\n            if (packetLoss && packetLoss >= 10) {\n                quality = Math.min(quality, 30);\n            }\n        }\n\n        // Make sure that the quality doesn't climb quickly\n        if (this._lastConnectionQualityUpdate > 0) {\n            const maxIncreasePerSecond = 2;\n            const prevConnectionQuality = this._localStats.connectionQuality;\n            const diffSeconds = (window.performance.now() - this._lastConnectionQualityUpdate) / 1000;\n\n            quality = Math.min(quality, prevConnectionQuality + (diffSeconds * maxIncreasePerSecond));\n        }\n\n        return Math.min(100, quality);\n    }\n\n    /**\n     * Sets _timeVideoUnmuted if it was previously unset. If it was already set,\n     * doesn't change it.\n     */\n    private _maybeUpdateUnmuteTime(): void {\n        if (this._timeVideoUnmuted < 0) {\n            this._timeVideoUnmuted = window.performance.now();\n        }\n    }\n\n    /**\n     * Resets the time video was unmuted and triggers a new ramp-up.\n     *\n     * @private\n     * @returns {void}\n     */\n    private _resetVideoUnmuteTime(): void {\n        this._timeVideoUnmuted = -1;\n        this._maybeUpdateUnmuteTime();\n    }\n\n    /**\n     * Updates the localConnectionQuality value\n     * @param values {number} the new value. Should be in [0, 100].\n     */\n    private _updateLocalConnectionQuality(value: number): void {\n        this._localStats.connectionQuality = value;\n        this._lastConnectionQualityUpdate = window.performance.now();\n    }\n\n    /**\n     * Updates the local statistics\n     * @param {TraceablePeerConnection} tpc the peerconnection which emitted\n     * the stats\n     * @param data new statistics\n     */\n    private _updateLocalStats(tpc: TraceablePeerConnection, data: { transport: { rtt: number; }[]; }): void {\n        // Update jvbRTT\n        if (!tpc.isP2P) {\n            const jvbRTT\n                = data.transport?.length && data.transport[0].rtt;\n\n            this._localStats.jvbRTT = jvbRTT ? jvbRTT : undefined;\n        }\n\n        // Do not continue with processing of other stats if they do not\n        // originate from the active peerconnection\n        if (tpc !== this._conference.getActivePeerConnection()) {\n            return;\n        }\n\n        let key;\n        const updateLocalConnectionQuality = !this._conference.isConnectionInterrupted();\n        const localVideoTrack = this._conference.getLocalVideoTrack();\n        const videoType = localVideoTrack?.videoType;\n        const isMuted = localVideoTrack ? localVideoTrack.isMuted() : true;\n        const resolutionName = localVideoTrack\n            ? Math.min(localVideoTrack.resolution, localVideoTrack.maxEnabledResolution).toString() as keyof typeof Resolutions : null;\n\n        if (!isMuted) {\n            this._maybeUpdateUnmuteTime();\n        }\n\n        // Copy the fields already in 'data'.\n        for (key in data) {\n            if (data.hasOwnProperty(key)) {\n                // Prevent overwriting available download bandwidth as this statistic is provided by the bridge.\n                if (key === 'bandwidth' && data[key].hasOwnProperty('download') && !tpc.isP2P) {\n                    if (!this._localStats[key]) {\n                        this._localStats[key] = {};\n                    }\n                    this._localStats[key].download = this._localStats[key].download || data[key].download;\n                    this._localStats[key].upload = data[key].upload;\n                } else {\n                    this._localStats[key] = data[key];\n                }\n            }\n        }\n\n        // And re-calculate the connectionQuality field.\n        if (updateLocalConnectionQuality) {\n            this._updateLocalConnectionQuality(\n                this._calculateConnectionQuality(\n                    videoType,\n                    isMuted,\n                    resolutionName));\n        }\n\n        this.eventEmitter.emit(ConnectionQualityEvents.LOCAL_STATS_UPDATED, this._localStats);\n        this._broadcastLocalStats();\n    }\n\n    /**\n     * Updates remote statistics\n     * @param id the id of the remote participant\n     * @param data the statistics received\n     */\n    private _updateRemoteStats(id: string, data: IRemoteStats): void {\n        // Use only the fields we need\n        this._remoteStats[id] = {\n            bitrate: data.bitrate,\n            connectionQuality: data.connectionQuality,\n            jvbRTT: data.jvbRTT,\n            maxEnabledResolution: data.maxEnabledResolution,\n            packetLoss: data.packetLoss,\n            serverRegion: data.serverRegion\n        };\n\n        this.eventEmitter.emit(\n            ConnectionQualityEvents.REMOTE_STATS_UPDATED,\n            id,\n            this._remoteStats[id]);\n    }\n\n    /**\n     * Returns the local statistics.\n     * Exported only for use in jitsi-meet-torture.\n     */\n    public getStats(): ILocalStats {\n        return this._localStats;\n    }\n}\n","import { getLogger } from '@jitsi/logger';\n\nimport JitsiConference from '../../JitsiConference';\nimport RTCStats from '../RTCStats/RTCStats';\nimport { RTCStatsEvents } from '../RTCStats/RTCStatsEvents';\n\nconst logger = getLogger('connectivity:IceFailedHandling');\n\n/**\n * This class deals with shenanigans around JVB media session's ICE failed status handling.\n *\n * If ICE connection is not re-established within 2 secs after the internet comes back online, the client will initiate\n * a session restart via 'session-terminate'. This results in Jicofo re-inviting the participant into the conference by\n * recreating the jvb media session so that there is minimla disruption to the user by default.\n */\nexport default class IceFailedHandling {\n    private _conference: JitsiConference;\n    private _canceled: boolean = false;\n    private _iceFailedTimeout?: number;\n\n    /**\n     * Creates new {@code DelayedIceFailed} task.\n     * @param {JitsiConference} conference\n     */\n    constructor(conference: JitsiConference) {\n        this._conference = conference;\n    }\n\n    /**\n     * After making sure there's no way for the ICE connection to recover this method either sends ICE failed\n     * notification to Jicofo or emits the ice failed conference event.\n     * @private\n     * @returns {void}\n     */\n    _actOnIceFailed(): void {\n        if (!this._conference.room) {\n            return;\n        }\n\n        const jvbConnection = this._conference.jvbJingleSession;\n        const jvbConnIceState = jvbConnection?.getIceConnectionState();\n\n        if (!jvbConnection) {\n            logger.warn('Not sending ICE failed - no JVB connection');\n        } else if (jvbConnIceState === 'connected') {\n            logger.info('ICE connection restored - not sending ICE failed');\n        } else {\n            logger.info(`Sending ICE failed - the connection did not recover, ICE state: ${jvbConnIceState}`);\n            RTCStats.sendStatsEntry(RTCStatsEvents.JVB_ICE_RESTARTED_EVENT);\n            this._conference._stopJvbSession({\n                reason: 'connectivity-error',\n                reasonDescription: 'ICE FAILED',\n                requestRestart: true,\n                sendSessionTerminate: true\n            });\n        }\n    }\n\n    /**\n     * Starts the task.\n     * @returns {void}\n     */\n    start(): void {\n        //  Using xmpp.ping allows to handle both XMPP being disconnected and internet offline cases. The ping function\n        // uses sendIQ2 method which is resilient to XMPP connection disconnected state and will patiently wait until it\n        // gets reconnected.\n        //  This also handles the case about waiting for the internet to come back online, because ping\n        // will only succeed when the internet is online and then there's a chance for the ICE to recover from FAILED to\n        // CONNECTED which is the extra 2 second timeout after ping.\n        //  The 65 second timeout is given on purpose as there's no chance for XMPP to recover after 65 seconds of no\n        // communication with the server. Such resume attempt will result in unrecoverable conference failed event due\n        // to 'item-not-found' error returned by the server.\n        this._conference.xmpp.ping(65000).then(\n            () => {\n                if (!this._canceled) {\n                    this._iceFailedTimeout = window.setTimeout(() => {\n                        this._iceFailedTimeout = undefined;\n                        this._actOnIceFailed();\n                    }, 2000);\n                }\n            },\n            error => {\n                logger.error('PING error/timeout - not sending ICE failed', error);\n            });\n    }\n\n    /**\n     * Cancels the task.\n     * @returns {void}\n     */\n    cancel(): void {\n        this._canceled = true;\n        window.clearTimeout(this._iceFailedTimeout);\n    }\n}\n","export enum DetectionEvents {\n\n    /** Event triggered by {@link NoAudioSignalDetector} when the local audio device associated with a JitsiConference\n     * starts receiving audio levels with the value of 0 meaning no audio is being captured on that device, or when\n     * it starts receiving audio levels !== 0 after being in a state of no audio.\n     * @event\n     * @type {boolean} - true when the current conference audio track has audio input false otherwise.\n     */\n    AUDIO_INPUT_STATE_CHANGE = 'audio_input_state_changed',\n\n    /**\n     * Event triggered by a audio detector indicating that its active state has changed from active to inactive or vice\n     * versa.\n     * @event\n     * @type {boolean} - true when service has changed to active false otherwise.\n     */\n    DETECTOR_STATE_CHANGE = 'detector_state_change',\n\n    /** Event triggered by NoAudioSignalDetector when the local audio device associated with a JitsiConference goes\n     * silent for a period of time, meaning that the device is either broken or hardware/software muted.\n     * @event\n     * @type {void}\n     */\n    NO_AUDIO_INPUT = 'no_audio_input_detected',\n\n    /**\n     *  Event generated by {@link VADNoiseDetection} when the tracked device is considered noisy.\n     *  @event\n     *  @type {Object}\n     */\n    VAD_NOISY_DEVICE = 'detection.vad_noise_device',\n\n    /**\n     * Event generated by VADReportingService when if finishes creating a VAD report for the monitored devices.\n     * The generated objects are of type Array<Object>, one score for each monitored device.\n     * @event VAD_REPORT_PUBLISHED\n     * @type Array<Object> with the following structure:\n     * @property {Date} timestamp - Timestamp at which the compute took place.\n     * @property {number} avgVAD - Average VAD score over monitored period of time.\n     * @property {string} deviceId - Associate local audio device ID.\n     */\n    VAD_REPORT_PUBLISHED = 'vad-report-published',\n\n    /**\n     * Event generated by {@link TrackVADEmitter} when PCM sample VAD score is available.\n     *\n     * @event\n     * @type {Object}\n     * @property {Date}   timestamp - Exact time at which processed PCM sample was generated.\n     * @property {number} score - VAD score on a scale from 0 to 1 (i.e. 0.7)\n     * @property {Float32Array} pcmData - Raw PCM data with which the VAD score was calculated.\n     * @property {string} deviceId - Device id of the associated track.\n     */\n    VAD_SCORE_PUBLISHED = 'detection.vad_score_published',\n\n    /**\n     *  Event generated by {@link VADTalkMutedDetection} when a user is talking while the mic is muted.\n     *\n     *  @event\n     *  @type {Object}\n     */\n    VAD_TALK_WHILE_MUTED = 'detection.vad_talk_while_muted'\n}\n","import type JitsiConference from '../../JitsiConference';\nimport { JitsiConferenceEvents } from '../../JitsiConferenceEvents';\nimport { JitsiTrackEvents } from '../../JitsiTrackEvents';\nimport type JitsiLocalTrack from '../RTC/JitsiLocalTrack';\nimport type TraceablePeerConnection from '../RTC/TraceablePeerConnection';\nimport EventEmitter from '../util/EventEmitter';\n\nimport { DetectionEvents } from './DetectionEvents';\n\n// We wait a certain time interval for constant silence input from the current device to account for\n// potential abnormalities and for a better use experience i.e. don't generate event the instant\n// an audio track is added to the tcr.\n// Potential improvement - add this as a configurable parameter.\nconst SILENCE_PERIOD_MS = 4000;\n\n/**\n * Detect if there is no audio input on the current TraceAblePeerConnection selected track. The no audio\n * state must be constant for a configured amount of time in order for the event to be triggered.\n * @fires DetectionEvents.AUDIO_INPUT_STATE_CHANGE\n * @fires DetectionEvents.NO_AUDIO_INPUT\n */\nexport default class NoAudioSignalDetection extends EventEmitter {\n    private _conference: JitsiConference;\n    private _timeoutTrigger: Nullable<Timeout>;\n    private _hasAudioInput: Nullable<boolean>;\n    private _audioTrack: Nullable<JitsiLocalTrack>;\n    private _eventFired: boolean;\n\n    /**\n     * Creates new NoAudioSignalDetection.\n     *\n     * @param conference the JitsiConference instance that created us.\n     * @constructor\n     */\n    constructor(conference: JitsiConference) {\n        super();\n\n        this._conference = conference;\n        this._timeoutTrigger = null;\n        this._hasAudioInput = null;\n        this._audioTrack = null;\n        this._eventFired = false;\n\n        conference.on(JitsiConferenceEvents.TRACK_ADDED, this._trackAdded.bind(this));\n    }\n\n    /**\n     * Clear the timeout state.\n     */\n    private _clearTriggerTimeout(): void {\n        if (this._timeoutTrigger) {\n            clearTimeout(this._timeoutTrigger);\n            this._timeoutTrigger = null;\n        }\n    }\n\n    /**\n     * Generated event triggered by a change in the current conference audio input state.\n     *\n     * @param {number} audioLevel - The audio level of the ssrc.\n     * @fires DetectionEvents.AUDIO_INPUT_STATE_CHANGE\n     */\n    private _handleAudioInputStateChange(audioLevel: number): void {\n        // Current audio input state of the active local track in the conference, true for audio input false for no\n        // audio input.\n        const status = audioLevel !== 0;\n\n        // If this is the first audio event picked up or the current status is different from the previous trigger\n        // the event.\n        if (this._hasAudioInput === null || this._hasAudioInput !== status) {\n            this._hasAudioInput = status;\n            this.emit(DetectionEvents.AUDIO_INPUT_STATE_CHANGE, this._hasAudioInput);\n        }\n    }\n\n    /**\n     * Generate event triggered by a prolonged period of no audio input.\n     *\n     * @param {number} audioLevel - The audio level of the ssrc.\n     * @fires DetectionEvents.NO_AUDIO_INPUT\n     */\n    private _handleNoAudioInputDetection(audioLevel: number): void {\n        if (this._eventFired) {\n            return;\n        }\n\n        if (audioLevel === 0 && !this._timeoutTrigger) {\n            this._timeoutTrigger = setTimeout(() => {\n                this._eventFired = true;\n\n                this.emit(DetectionEvents.NO_AUDIO_INPUT);\n            }, SILENCE_PERIOD_MS);\n        } else if (audioLevel !== 0 && this._timeoutTrigger) {\n            this._clearTriggerTimeout();\n        }\n    }\n\n    /**\n     * Receives audio level events for all send and receive streams on the current TraceablePeerConnection.\n     *\n     * @param {TraceablePeerConnection} tpc - TraceablePeerConnection of the owning conference.\n     * @param {number} ssrc - The synchronization source identifier (SSRC) of the endpoint/participant/stream\n     * being reported.\n     * @param {number} audioLevel - The audio level of the ssrc.\n     * @param {boolean} isLocal - true for local/send streams or false for remote/receive streams.\n     */\n    private _audioLevel(tpc: TraceablePeerConnection, ssrc: number, audioLevel: number, isLocal: boolean): void {\n        // We are interested in the local audio streams\n        if (!isLocal || !this._audioTrack) {\n            return;\n        }\n\n        // Get currently active local tracks from the TraceablePeerConnection\n        const localSSRCs = tpc.localSSRCs.get(this._audioTrack.rtcId);\n\n        // Only target the current active track in the tpc. For some reason audio levels for previous\n        // devices are also picked up from the PeerConnection so we filter them out.\n        if (!localSSRCs?.ssrcs.includes(ssrc)) {\n            return;\n        }\n\n        // First handle audio input state change. In case the state changed to no input the no audio input event\n        // can try to fire again.\n        this._handleAudioInputStateChange(audioLevel);\n        this._handleNoAudioInputDetection(audioLevel);\n    }\n\n    /**\n     * Notifies NoAudioSignalDetection that a JitsiTrack was added to the associated JitsiConference.\n     * Only take into account local audio tracks.\n     *\n     * @param {JitsiTrack} track - The added JitsiTrack.\n     */\n    private _trackAdded(track: JitsiLocalTrack): void {\n        if (track.isLocalAudioTrack()) {\n            // Reset state for the new track.\n            this._audioTrack = track;\n            this._eventFired = false;\n            this._clearTriggerTimeout();\n\n            // Listen for the audio levels on the newly added audio track\n            track.on(\n                JitsiTrackEvents.NO_AUDIO_INPUT,\n                (audioLevel: number) => {\n                    this._handleNoAudioInputDetection(audioLevel);\n                }\n            );\n            track.on(\n                JitsiTrackEvents.TRACK_AUDIO_LEVEL_CHANGED,\n                (audioLevel: number) => {\n                    this._handleNoAudioInputDetection(audioLevel);\n                    this._handleAudioInputStateChange(audioLevel);\n                }\n            );\n        }\n    }\n}\n","import JitsiConference from '../../JitsiConference';\nimport { JitsiConferenceEvents } from '../../JitsiConferenceEvents';\nimport { RTCEvents } from '../../service/RTC/RTCEvents';\n\n/**\n * The value which we use to say, every sound over this threshold\n * is talking on the mic.\n * @type {number}\n */\nconst SPEECH_DETECT_THRESHOLD: number = 0.6;\n\n/**\n * The <tt>P2PDominantSpeakerDetection</tt> is activated only when p2p is\n * currently used.\n * Listens for changes in the audio level changes of the local p2p audio track\n * or remote p2p one and fires dominant speaker events to be able to use\n * features depending on those events (speaker stats), to make them work without\n * the video bridge.\n */\nexport default class P2PDominantSpeakerDetection {\n    private conference: JitsiConference;\n    private myUserID: string;\n\n    /**\n     * Creates P2PDominantSpeakerDetection\n     * @param conference the JitsiConference instance that created us.\n     * @constructor\n     */\n    constructor(conference: JitsiConference) {\n        this.conference = conference;\n\n        conference.addEventListener(\n            JitsiConferenceEvents.TRACK_AUDIO_LEVEL_CHANGED,\n            this._audioLevel.bind(this));\n\n        this.myUserID = this.conference.myUserId();\n    }\n\n    /**\n     * Receives audio level events for all streams in the conference.\n     *\n     * @param {String} id - The participant id\n     * @param {number} audioLevel - The audio level.\n     */\n    private _audioLevel(id: string, audioLevel: number): void {\n        // we do not process if p2p is not active\n        // or audio level is under certain threshold\n        // or if the audio level is for local audio track which is muted\n        if (!this.conference.isP2PActive()\n            || audioLevel <= SPEECH_DETECT_THRESHOLD\n            || (id === this.myUserID\n                    && this.conference.getLocalAudioTrack().isMuted())) {\n            return;\n        }\n\n        this.conference.rtc.eventEmitter.emit(\n            RTCEvents.DOMINANT_SPEAKER_CHANGED,\n            id);\n    }\n}\n","/**\n * Adapter that creates AudioContext objects depending on the browser.\n *\n * @returns {Optional<AudioContext>} - Return a new AudioContext or undefined if the browser does not support it.\n */\nexport function createAudioContext(options?: AudioContextOptions): Optional<AudioContext> {\n    const AudioContextImpl = window.AudioContext || (window as any).webkitAudioContext;\n\n    if (!AudioContextImpl) {\n        return undefined;\n    }\n\n    return new AudioContextImpl(options);\n}\n","import JitsiLocalTrack from '../RTC/JitsiLocalTrack';\nimport RTC from '../RTC/RTC';\nimport EventEmitter from '../util/EventEmitter';\nimport { createAudioContext } from '../webaudio/WebAudioUtils';\n\nimport { DetectionEvents } from './DetectionEvents';\n\nexport interface IVadProcessor {\n    calculateAudioFrameVAD: (pcmSample: Float32Array | number[]) => number;\n    getRequiredPCMFrequency: () => number;\n    getSampleLength: () => number;\n}\n\nexport type AudioContextType = AudioContext;\nexport type ScriptProcessorNodeType = ScriptProcessorNode;\nexport type MediaStreamAudioSourceNodeType = MediaStreamAudioSourceNode;\n\n/**\n * Connects an audio JitsiLocalTrack to a vadProcessor using WebAudio ScriptProcessorNode.\n * Once an object is created audio from the local track flows through the ScriptProcessorNode as raw PCM.\n * The PCM is processed by the injected vad module and a voice activity detection score is obtained, the\n * score is published to consumers via an EventEmitter.\n * After work is done with this service the destroy method needs to be called for a proper cleanup.\n *\n * @fires VAD_SCORE_PUBLISHED\n */\nexport default class TrackVADEmitter extends EventEmitter {\n    private _procNodeSampleRate: number;\n    private _vadProcessor: IVadProcessor;\n    private _localTrack: JitsiLocalTrack;\n    private _bufferResidue: Float32Array;\n    private _audioContext: AudioContextType;\n    private _vadSampleSize: number;\n    private _audioSource!: MediaStreamAudioSourceNodeType;\n    private _audioProcessingNode!: ScriptProcessorNodeType;\n    private _destroyed?: boolean;\n\n    /**\n     * Constructor.\n     *\n     * @param {number} procNodeSampleRate - Sample rate of the ScriptProcessorNode. Possible values  256, 512, 1024,\n     *  2048, 4096, 8192, 16384. Passing other values will default to closes neighbor.\n     * @param {Object} vadProcessor - VAD processor that allows us to calculate VAD score for PCM samples.\n     * @param {JitsiLocalTrack} jitsiLocalTrack - JitsiLocalTrack corresponding to micDeviceId.\n     */\n    constructor(procNodeSampleRate: number, vadProcessor: IVadProcessor, jitsiLocalTrack: JitsiLocalTrack) {\n        super();\n\n        /**\n         * Sample rate of the ScriptProcessorNode.\n         */\n        this._procNodeSampleRate = procNodeSampleRate;\n\n        /**\n         * VAD Processor that allows us to calculate VAD score for PCM samples\n         */\n        this._vadProcessor = vadProcessor;\n\n        /**\n         * The JitsiLocalTrack instance.\n         */\n        this._localTrack = jitsiLocalTrack;\n\n        /**\n         * Buffer to hold residue PCM resulting after a ScriptProcessorNode callback\n         */\n        this._bufferResidue = new Float32Array([]);\n\n        /**\n         * The AudioContext instance with the preferred sample frequency.\n         */\n        this._audioContext = createAudioContext({ sampleRate: vadProcessor.getRequiredPCMFrequency() });\n\n        /**\n         * PCM Sample size expected by the VAD Processor instance. We cache it here as this value is used extensively,\n         * saves a couple of function calls.\n         */\n        this._vadSampleSize = vadProcessor.getSampleLength();\n\n        /**\n         * Event listener function that will be called by the ScriptProcessNode with raw PCM data, depending on the set\n         * sample rate.\n         */\n        this._onAudioProcess = this._onAudioProcess.bind(this);\n\n        this._initializeAudioContext();\n    }\n\n    /**\n     * Factory method that sets up all the necessary components for the creation of the TrackVADEmitter.\n     *\n     * @param {string} micDeviceId - Target microphone device id.\n     * @param {number} procNodeSampleRate - Sample rate of the proc node.\n     * @param {Object} vadProcessor -Module that calculates the voice activity score for a certain audio PCM sample.\n     * The processor needs to implement the following functions:\n     * - <tt>getSampleLength()</tt> - Returns the sample size accepted by getSampleLength.\n     * - <tt>getRequiredPCMFrequency()</tt> - Returns the PCM frequency at which the processor operates.\n     * - <tt>calculateAudioFrameVAD(pcmSample)</tt> - Process a 32 float pcm sample of getSampleLength size.\n     * @returns {Promise<TrackVADEmitter>} - Promise resolving in a new instance of TrackVADEmitter.\n     */\n    static create(\n            micDeviceId: string,\n            procNodeSampleRate: number,\n            vadProcessor: IVadProcessor\n    ): Promise<TrackVADEmitter> {\n        return RTC.obtainAudioAndVideoPermissions({\n            devices: [ 'audio' ],\n            micDeviceId\n        }).then((localTrack: JitsiLocalTrack[]) => {\n            // We only expect one audio track when specifying a device id.\n            if (!localTrack[0]) {\n                throw new Error(`Failed to create jitsi local track for device id: ${micDeviceId}`);\n            }\n\n            return new TrackVADEmitter(procNodeSampleRate, vadProcessor, localTrack[0]);\n\n            // We have no exception handling at this point as there is nothing to clean up, the vadProcessor\n            // life cycle is handled by whoever created this instance.\n        });\n    }\n\n    /**\n     * Sets up the audio graph in the AudioContext.\n     *\n     * @returns {void}\n     */\n    _initializeAudioContext(): void {\n        this._audioSource = this._audioContext.createMediaStreamSource(this._localTrack.stream);\n\n        // TODO AudioProcessingNode is deprecated in the web audio specifications and the recommended replacement\n        // is audio worklet, however at the point of implementation AudioProcessingNode was still de de facto way\n        // of achieving this functionality and supported in all major browsers as opposed to audio worklet which\n        // was only available in Chrome. This todo is just a reminder that we should replace AudioProcessingNode\n        // with audio worklet when it's mature enough and has more browser support.\n        // We don't need stereo for determining the VAD score so we create a single channel processing node.\n        this._audioProcessingNode = this._audioContext.createScriptProcessor(this._procNodeSampleRate, 1, 1);\n    }\n\n    /**\n     * ScriptProcessorNode callback, the input parameters contains the PCM audio that is then sent to rnnoise.\n     * Rnnoise only accepts PCM samples of 480 bytes whereas the webaudio processor node can't sample at a multiple\n     * of 480 thus after each _onAudioProcess callback there will remain and PCM buffer residue equal\n     * to _procNodeSampleRate / 480 which will be added to the next sample buffer and so on.\\\n     *\n     *\n     * @param {AudioProcessingEvent} audioEvent - Audio event.\n     * @returns {void}\n     * @fires VAD_SCORE_PUBLISHED\n     */\n    _onAudioProcess(audioEvent: AudioProcessingEvent): void {\n        // Prepend the residue PCM buffer from the previous process callback.\n        const inData = audioEvent.inputBuffer.getChannelData(0);\n        const completeInData = [ ...this._bufferResidue, ...inData ];\n        const sampleTimestamp = Date.now();\n\n        let i = 0;\n\n        for (; i + this._vadSampleSize < completeInData.length; i += this._vadSampleSize) {\n            const pcmSample = completeInData.slice(i, i + this._vadSampleSize);\n\n            // The VAD processor might change the values inside the array so we make a copy.\n            const vadScore = this._vadProcessor.calculateAudioFrameVAD(pcmSample.slice());\n\n            this.emit(DetectionEvents.VAD_SCORE_PUBLISHED, {\n                deviceId: this._localTrack.getDeviceId(),\n                pcmData: pcmSample,\n                score: vadScore,\n                timestamp: sampleTimestamp\n            });\n        }\n\n        this._bufferResidue = new Float32Array(completeInData.slice(i, completeInData.length));\n    }\n\n    /**\n     * Connects the nodes in the AudioContext to start the flow of audio data.\n     *\n     * @returns {void}\n     */\n    _connectAudioGraph(): void {\n        this._audioProcessingNode.onaudioprocess = this._onAudioProcess;\n        this._audioSource.connect(this._audioProcessingNode);\n        this._audioProcessingNode.connect(this._audioContext.destination);\n    }\n\n    /**\n     * Disconnects the nodes in the AudioContext.\n     *\n     * @returns {void}\n     */\n    _disconnectAudioGraph(): void {\n        // Even thought we disconnect the processing node it seems that some callbacks remain queued,\n        // resulting in calls with and uninitialized context.\n        // eslint-disable-next-line  @typescript-eslint/no-empty-function\n        this._audioProcessingNode.onaudioprocess = () => {};\n        this._audioProcessingNode.disconnect();\n        this._audioSource.disconnect();\n    }\n\n    /**\n     * Cleanup potentially acquired resources.\n     *\n     * @returns {void}\n     */\n    _cleanupResources(): void {\n        this._disconnectAudioGraph();\n        this._localTrack.stopStream();\n    }\n\n    /**\n     * Start the emitter by connecting the audio graph.\n     *\n     * @returns {void}\n     */\n    start(): void {\n        this._connectAudioGraph();\n    }\n\n    /**\n     * Stops the emitter by disconnecting the audio graph.\n     *\n     * @returns {void}\n     */\n    stop(): void {\n        this._disconnectAudioGraph();\n        this._bufferResidue = new Float32Array([]);\n    }\n\n    /**\n     * Destroy TrackVADEmitter instance (release resources and stop callbacks).\n     *\n     * @returns {void}\n     */\n    destroy(): void {\n        if (this._destroyed) {\n            return;\n        }\n\n        this._cleanupResources();\n        this._destroyed = true;\n    }\n}\n","import { getLogger } from '@jitsi/logger';\n\nimport JitsiConference from '../../JitsiConference';\nimport { JitsiConferenceEvents } from '../../JitsiConferenceEvents';\nimport JitsiLocalTrack from '../RTC/JitsiLocalTrack';\nimport EventEmitter from '../util/EventEmitter';\n\nimport { DetectionEvents } from './DetectionEvents';\nimport TrackVADEmitter from './TrackVADEmitter';\n\nconst logger = getLogger('vad:VADAudioAnalyser');\n\n/**\n * Sample rate of TrackVADEmitter, it defines how many audio samples are processed at a time.\n * @type {number}\n */\nconst VAD_EMITTER_SAMPLE_RATE: number = 4096;\n\nexport interface IVADProcessor {\n    calculateAudioFrameVAD: (pcmSample: Float32Array | number[]) => number;\n    getRequiredPCMFrequency: () => number;\n    getSampleLength: () => number;\n}\n\nexport interface IVADDetectionService {\n    changeMuteState: (isMuted: boolean) => void;\n    isActive: () => boolean;\n    on: (event: string, handler: () => void) => void;\n    processVADScore: (vadScore: IVADScore) => void;\n    reset: () => void;\n}\n\nexport interface IVADScore {\n    deviceId: string;\n    pcmData: Float32Array | number[];\n    score: number;\n    timestamp: number;\n}\n\n/**\n * Connects a TrackVADEmitter to the target conference local audio track and manages various services that use\n * the data to produce audio analytics (VADTalkMutedDetection and VADNoiseDetection).\n */\nexport default class VADAudioAnalyser extends EventEmitter {\n    private _createVADProcessor: () => IVADProcessor;\n    private _vadEmitter: Nullable<TrackVADEmitter>;\n    private _isVADEmitterRunning: boolean;\n    private _detectionServices: IVADDetectionService[];\n    private _vadInitTracker: Promise<void>;\n\n    /**\n     * Creates <tt>VADAudioAnalyser</tt>\n     * @param {JitsiConference} conference - JitsiConference instance that created us.\n     * @param {Object} createVADProcessor - Function that creates a Voice activity detection processor. The processor\n     * needs to implement the following functions:\n     * - <tt>getSampleLength()</tt> - Returns the sample size accepted by getSampleLength.\n     * - <tt>getRequiredPCMFrequency()</tt> - Returns the PCM frequency at which the processor operates.\n     * - <tt>calculateAudioFrameVAD(pcmSample)</tt> - Process a 32 float pcm sample of getSampleLength size.\n     * @constructor\n     */\n    constructor(conference: JitsiConference, createVADProcessor: () => IVADProcessor) {\n        super();\n\n        /**\n         * Member function that instantiates a VAD processor.\n         */\n        this._createVADProcessor = createVADProcessor;\n\n        /**\n         * Current {@link TrackVADEmitter}. VAD Emitter uses a {@link JitsiLocalTrack} and VAD processor to generate\n         * period voice probability scores.\n         */\n        this._vadEmitter = null;\n\n        /**\n         * Current state of the _vadEmitter\n         */\n        this._isVADEmitterRunning = false;\n\n        /**\n         * Array of currently attached VAD processing services.\n         */\n        this._detectionServices = [];\n\n        /**\n         * Promise used to chain create and destroy operations associated with TRACK_ADDED and TRACK_REMOVED events\n         * coming from the conference.\n         * Because we have an async created component (VAD Processor) we need to make sure that it's initialized before\n         * we destroy it ( when changing the device for instance), or when we use it from an external point of entry\n         * i.e. (TRACK_MUTE_CHANGED event callback).\n         */\n        this._vadInitTracker = Promise.resolve();\n\n        /**\n         * Listens for {@link TrackVADEmitter} events and processes them.\n         */\n        this._processVADScore = this._processVADScore.bind(this);\n\n        conference.on(JitsiConferenceEvents.TRACK_ADDED, this._trackAdded.bind(this));\n        conference.on(JitsiConferenceEvents.TRACK_REMOVED, this._trackRemoved.bind(this));\n        conference.on(JitsiConferenceEvents.TRACK_MUTE_CHANGED, this._trackMuteChanged.bind(this));\n    }\n\n    /**\n     * Attach a VAD detector service to the analyser and handle it's state changes.\n     *\n     * @param {Object} vadTMDetector\n     */\n    addVADDetectionService(vadService: IVADDetectionService): void {\n        this._detectionServices.push(vadService);\n        vadService.on(DetectionEvents.DETECTOR_STATE_CHANGE, () => {\n            // When the state of a detector changes check if there are any active detectors attached so that\n            // the _vadEmitter doesn't run needlessly.\n            const activeDetector = this._detectionServices.filter(detector => detector.isActive() === true);\n\n            // If there are no active detectors running and the vadEmitter is running then stop the emitter as it is\n            // uses a considerable amount of CPU. Otherwise start the service if it's stopped and there is a detector\n            // that needs it.\n            if (!activeDetector.length && this._isVADEmitterRunning) {\n                this._stopVADEmitter();\n            } else if (!this._isVADEmitterRunning) {\n                this._startVADEmitter();\n            }\n        });\n    }\n\n    /**\n     * Start the {@link TrackVADEmitter} and attach the event listener.\n     * @returns {void}\n     */\n    _startVADEmitter(): void {\n        if (this._vadEmitter) {\n            this._vadEmitter.on(DetectionEvents.VAD_SCORE_PUBLISHED, this._processVADScore);\n            this._vadEmitter.start();\n            this._isVADEmitterRunning = true;\n        }\n    }\n\n    /**\n     * Stop the {@link TrackVADEmitter} and detach the event listener.\n     * @returns {void}\n     */\n    _stopVADEmitter(): void {\n        if (this._vadEmitter) {\n            this._vadEmitter.removeListener(DetectionEvents.VAD_SCORE_PUBLISHED, this._processVADScore);\n            this._vadEmitter.stop();\n        }\n        this._isVADEmitterRunning = false;\n    }\n\n    /**\n     * Listens for {@link TrackVADEmitter} events and directs them to attached services as needed.\n     *\n     * @param {Object} vadScore -VAD score emitted by {@link TrackVADEmitter}\n     * @param {Date}   vadScore.timestamp - Exact time at which processed PCM sample was generated.\n     * @param {number} vadScore.score - VAD score on a scale from 0 to 1 (i.e. 0.7)\n     * @param {Float32Array} pcmData - Raw PCM data with which the VAD score was calculated.\n     * @param {string} vadScore.deviceId - Device id of the associated track.\n     * @listens VAD_SCORE_PUBLISHED\n     */\n    _processVADScore(vadScore: IVADScore): void {\n        for (const detector of this._detectionServices) {\n            detector.processVADScore(vadScore);\n        }\n    }\n\n    /**\n     * Change the isMuted state of all attached detection services.\n     *\n     * @param {boolean} isMuted\n     */\n    _changeDetectorsMuteState(isMuted: boolean): void {\n        for (const detector of this._detectionServices) {\n            detector.changeMuteState(isMuted);\n        }\n    }\n\n    /**\n     * Notifies the detector that a track was added to the associated {@link JitsiConference}.\n     * Only take into account local audio tracks.\n     * @param {JitsiLocalTrack} track - The added track.\n     * @returns {void}\n     * @listens TRACK_ADDED\n     */\n    _trackAdded(track: JitsiLocalTrack): void {\n        if (track.isLocalAudioTrack()) {\n            // Keep a track promise so we take into account successive TRACK_ADD events being generated so that we\n            // destroy/create the processing context in the proper order.\n            this._vadInitTracker = this._vadInitTracker.then(() => this._createVADProcessor())\n                .then((vadProcessor: IVADProcessor) =>\n                    TrackVADEmitter.create(track.getDeviceId(), VAD_EMITTER_SAMPLE_RATE, vadProcessor)\n                )\n                .then((vadEmitter: TrackVADEmitter) => {\n                    logger.debug('Created VAD emitter for track: ', track.getTrackLabel());\n\n                    this._vadEmitter = vadEmitter;\n\n                    // Iterate through the detection services and set their appropriate mute state, depending on\n                    // service this will trigger a DETECTOR_STATE_CHANGE which in turn might start the _vadEmitter.\n                    this._changeDetectorsMuteState(track.isMuted());\n                })\n                .catch(error => {\n                    logger.warn('Failed to start VADAudioAnalyser', error);\n                });\n        }\n    }\n\n    /**\n     * Notifies the detector that the mute state of a {@link JitsiConference} track has changed. Only takes into account\n     * local audio tracks.\n     * @param {JitsiLocalTrack} track - The track whose mute state has changed.\n     * @returns {void}\n     * @listens TRACK_MUTE_CHANGED\n     */\n    _trackMuteChanged(track: JitsiLocalTrack): void {\n        if (track.isLocalAudioTrack()) {\n            // On a mute toggle reset the state.\n            this._vadInitTracker = this._vadInitTracker.then(() => {\n                // Set mute status for the attached detection services.\n                this._changeDetectorsMuteState(track.isMuted());\n            });\n        }\n    }\n\n    /**\n     * Notifies the detector that a track associated with the {@link JitsiConference} was removed. Only takes into\n     * account local audio tracks. Cleans up resources associated with the track and resets the processing context.\n     *\n     * @param {JitsiLocalTrack} track - The removed track.\n     * @returns {void}\n     * @listens TRACK_REMOVED\n     */\n    _trackRemoved(track: JitsiLocalTrack): void {\n        if (track.isLocalAudioTrack()) {\n            // Use the promise to make sure operations are in sequence.\n            this._vadInitTracker = this._vadInitTracker.then(() => {\n                logger.debug('Removing track from VAD detection - ', track.getTrackLabel());\n\n                // Track was removed, clean up and set appropriate states.\n                if (this._vadEmitter) {\n                    this._stopVADEmitter();\n                    this._vadEmitter.destroy();\n                    this._vadEmitter = null;\n                }\n\n                // Reset state of detectors when active track is removed.\n                for (const detector of this._detectionServices) {\n                    detector.reset();\n                }\n            });\n        }\n    }\n}\n","import EventEmitter from '../util/EventEmitter';\nimport { calculateAverage, filterPositiveValues } from '../util/MathUtil';\n\nimport { DetectionEvents } from './DetectionEvents';\nimport { IVADScore } from './VADAudioAnalyser';\n\n/**\n * The average value VAD needs to be under over a period of time to be considered noise.\n * @type {number}\n */\nconst VAD_NOISE_AVG_THRESHOLD: number = 0.2;\n\n/**\n * The average values that audio input need to be over to be considered loud.\n * @type {number}\n */\nconst NOISY_AUDIO_LEVEL_THRESHOLD: number = 0.040;\n\n/**\n * The value that a VAD score needs to be under in order for processing to begin.\n * @type {number}\n */\nconst VAD_SCORE_TRIGGER: number = 0.2;\n\n/**\n * The value that a VAD score needs to be under in order for processing to begin.\n * @type {number}\n */\nconst AUDIO_LEVEL_SCORE_TRIGGER: number = 0.020;\n\n/**\n * Time span over which we calculate an average score used to determine if we trigger the event.\n * @type {number}\n */\nconst PROCESS_TIME_FRAME_SPAN_MS: number = 1500;\n\n/**\n * Detect if provided VAD score and PCM data is considered noise.\n */\nexport default class VADNoiseDetection extends EventEmitter {\n    /**\n     * Flag which denotes the current state of the detection service i.e.if there is already a processing operation\n     * ongoing.\n     */\n    private _processing: boolean;\n\n    /**\n     * Buffer that keeps the VAD scores for a period of time.\n     */\n    private _scoreArray: number[];\n\n    /**\n     * Buffer that keeps audio level samples for a period of time.\n     */\n    private _audioLvlArray: number[];\n\n    /**\n     * Current state of the service, if it's not active no processing will occur.\n     */\n    private _active: boolean;\n\n    /**\n     * Timeout reference for processing VAD scores.\n     */\n    private _processTimeout?: ReturnType<typeof setTimeout>;\n\n    /**\n     * Creates <tt>VADNoiseDetection</tt>\n     *\n     * @constructor\n     */\n    constructor() {\n        super();\n\n        /**\n         * Flag which denotes the current state of the detection service i.e.if there is already a processing operation\n         * ongoing.\n         */\n        this._processing = false;\n\n        /**\n         * Buffer that keeps the VAD scores for a period of time.\n         */\n        this._scoreArray = [];\n\n        /**\n         * Buffer that keeps audio level samples for a period of time.\n         */\n        this._audioLvlArray = [];\n\n        /**\n         * Current state of the service, if it's not active no processing will occur.\n         */\n        this._active = false;\n\n        /**\n         * Timeout reference for processing VAD scores.\n         */\n        this._processTimeout = null;\n\n        this._calculateNoisyScore = this._calculateNoisyScore.bind(this);\n    }\n\n    /**\n     * Compute cumulative VAD score and PCM audio levels once the PROCESS_TIME_FRAME_SPAN_MS timeout has elapsed.\n     * If the score is above the set threshold fire the event.\n     * @returns {void}\n     * @fires VAD_NOISY_DEVICE\n     */\n    private _calculateNoisyScore(): void {\n        const scoreAvg = calculateAverage(new Float32Array(this._scoreArray));\n        const audioLevelAvg = calculateAverage(new Float32Array(this._audioLvlArray));\n\n        if (scoreAvg < VAD_NOISE_AVG_THRESHOLD && audioLevelAvg > NOISY_AUDIO_LEVEL_THRESHOLD) {\n            this.emit(DetectionEvents.VAD_NOISY_DEVICE);\n\n            this._setActiveState(false);\n        }\n\n        // We reset the context in case a new process phase needs to be triggered.\n        this.reset();\n    }\n\n    /**\n     * Set the active state of the detection service and notify any listeners.\n     *\n     * @param {boolean} active\n     * @fires DETECTOR_STATE_CHANGE\n     */\n    private _setActiveState(active: boolean): void {\n        this._active = active;\n        this.emit(DetectionEvents.DETECTOR_STATE_CHANGE, this._active);\n    }\n\n    /**\n     * Record the vad score and average volume in the appropriate buffers.\n     *\n     * @param {number} vadScore\n     * @param {number} avgAudioLvl - average audio level of the PCM sample associated with the VAD score.s\n     */\n    private _recordValues(vadScore: number, avgAudioLvl: number): void {\n        this._scoreArray.push(vadScore);\n        this._audioLvlArray.push(avgAudioLvl);\n    }\n\n    /**\n     * Change the state according to the muted status of the tracked device.\n     *\n     * @param {boolean} isMuted - Is the device muted or not.\n     */\n    public changeMuteState(isMuted: boolean): void {\n        // This service only needs to run when the microphone is not muted.\n        this._setActiveState(!isMuted);\n        this.reset();\n    }\n\n    /**\n     * Check whether or not the service is active or not.\n     *\n     * @returns {boolean}\n     */\n    public isActive(): boolean {\n        return this._active;\n    }\n\n    /**\n     * Listens for {@link TrackVADEmitter} events and processes them.\n     *\n     * @param {Object} vadScore -VAD score emitted by {@link TrackVADEmitter}\n     * @param {number}   vadScore.timestamp - Exact time at which processed PCM sample was generated.\n     * @param {number} vadScore.score - VAD score on a scale from 0 to 1 (i.e. 0.7)\n     * @param {Float32Array} vadScore.pcmData - Raw PCM Data associated with the VAD score.\n     * @param {string} vadScore.deviceId - Device id of the associated track.\n     * @listens VAD_SCORE_PUBLISHED\n     */\n    public processVADScore(vadScore: IVADScore): void {\n        if (!this._active) {\n            return;\n        }\n\n        // There is a processing phase on going, add score to buffer array.\n        if (this._processing) {\n        // Filter and calculate sample average so we don't have to process one large array at a time.\n            const pcmDataArray = Array.isArray(vadScore.pcmData) ? new Float32Array(vadScore.pcmData) : vadScore.pcmData;\n            const posAudioLevels = filterPositiveValues(pcmDataArray);\n\n            this._recordValues(vadScore.score, calculateAverage(new Float32Array(posAudioLevels)));\n\n            return;\n        }\n\n        // If the VAD score for the sample is low and audio level has a high enough level we can start listening for\n        // noise\n        if (vadScore.score < VAD_SCORE_TRIGGER) {\n            const pcmDataArray = Array.isArray(vadScore.pcmData) ? new Float32Array(vadScore.pcmData) : vadScore.pcmData;\n            const posAudioLevels = filterPositiveValues(pcmDataArray);\n            const avgAudioLvl = calculateAverage(new Float32Array(posAudioLevels));\n\n            if (avgAudioLvl > AUDIO_LEVEL_SCORE_TRIGGER) {\n                this._processing = true;\n                this._recordValues(vadScore.score, avgAudioLvl);\n\n                // Once the preset timeout executes the final score will be calculated.\n                this._processTimeout = setTimeout(this._calculateNoisyScore, PROCESS_TIME_FRAME_SPAN_MS);\n            }\n        }\n    }\n\n    /**\n     * Reset the processing context, clear buffers, cancel the timeout trigger.\n     *\n     * @returns {void}\n     */\n    public reset(): void {\n        this._processing = false;\n        this._scoreArray = [];\n        this._audioLvlArray = [];\n        if (this._processTimeout) {\n            clearTimeout(this._processTimeout);\n            this._processTimeout = null;\n        }\n    }\n}\n","import EventEmitter from '../util/EventEmitter';\nimport { calculateAverage } from '../util/MathUtil';\n\nimport { DetectionEvents } from './DetectionEvents';\n\n/**\n * The threshold which the average VAD values for a span of time needs to exceed to trigger an event.\n * @type {number}\n */\nconst VAD_AVG_THRESHOLD = 0.6;\n\n/**\n * The VAD score needed to trigger the processing algorithm, i.e. if a sample has the VAD score >= VAD_VOICE_LEVEL\n * we start processing all scores for a time span defined by const PROCESS_TIME_FRAME_SPAN_MS.\n * @type {number}\n */\nconst VAD_VOICE_LEVEL = 0.9;\n\n/**\n * Sample rate of TrackVADEmitter, it defines how many audio samples are processed at a time.\n * @type {number}\n */\n\n/**\n * Time span over which we calculate an average score used to determine if we trigger the event.\n * @type {number}\n */\nconst PROCESS_TIME_FRAME_SPAN_MS = 700;\n\nexport interface IVADScore {\n    deviceId: string;\n    score: number;\n    timestamp: number;\n}\n\n/**\n * Detect if provided VAD score which is generated on a muted device is voice and fires an event.\n */\nexport default class VADTalkMutedDetection extends EventEmitter {\n    private _processing: boolean;\n    private _scoreArray: number[];\n    private _active: boolean;\n    private _processTimeout?: ReturnType<typeof setTimeout>;\n\n    /**\n     * Creates <tt>VADTalkMutedDetection</tt>\n     * @constructor\n     */\n    constructor() {\n        super();\n\n        /**\n         * Flag which denotes the current state of the detection service i.e.if there is already a processing operation\n         * ongoing.\n         */\n        this._processing = false;\n\n        /**\n         * Buffer that keeps the VAD scores for a period of time.\n         */\n        this._scoreArray = [];\n\n        /**\n         * Current mute state of the audio track being monitored.\n         */\n        this._active = false;\n        this._calculateVADScore = this._calculateVADScore.bind(this);\n    }\n\n    /**\n     * Compute cumulative VAD score function called once the PROCESS_TIME_FRAME_SPAN_MS timeout has elapsed.\n     * @returns {void}\n     * @fires VAD_TALK_WHILE_MUTED\n     */\n    private _calculateVADScore(): void {\n        const score = calculateAverage(new Float32Array(this._scoreArray));\n\n        if (score > VAD_AVG_THRESHOLD) {\n            this.emit(DetectionEvents.VAD_TALK_WHILE_MUTED);\n\n            // Event was fired. Stop event emitter and remove listeners so no residue events kick off after this point\n            // and a single VAD_TALK_WHILE_MUTED is generated per mic muted state.\n            this._setActiveState(false);\n        }\n\n        // We reset the context in case a new process phase needs to be triggered.\n        this.reset();\n    }\n\n    /**\n     * Set the active state of the detection service and notify any listeners.\n     *\n     * @param {boolean} active\n     * @fires DETECTOR_STATE_CHANGE\n     */\n    private _setActiveState(active: boolean): void {\n        this._active = active;\n        this.emit(DetectionEvents.DETECTOR_STATE_CHANGE, this._active);\n    }\n\n    /**\n     * Change the state according to the muted status of the tracked device.\n     *\n     * @param {boolean} isMuted - Is the device muted or not.\n     */\n    public changeMuteState(isMuted: boolean): void {\n        // This service only needs to run when the microphone is muted.\n        this._setActiveState(isMuted);\n        this.reset();\n    }\n\n    /**\n     * Check whether or not the service is active or not.\n     *\n     * @returns {boolean}\n     */\n    public isActive(): boolean {\n        return this._active;\n    }\n\n    /**\n     * Listens for {@link TrackVADEmitter} events and processes them.\n     *\n     * @param {Object} vadScore -VAD score emitted by {@link TrackVADEmitter}\n     * @param {number}   vadScore.timestamp - Exact time at which processed PCM sample was generated.\n     * @param {number} vadScore.score - VAD score on a scale from 0 to 1 (i.e. 0.7)\n     * @param {string} vadScore.deviceId - Device id of the associated track.\n     * @listens VAD_SCORE_PUBLISHED\n     */\n    public processVADScore(vadScore: IVADScore): void {\n        if (!this._active) {\n            return;\n        }\n        // There is a processing phase on going, add score to buffer array.\n\n\n        if (this._processing) {\n            this._scoreArray.push(vadScore.score);\n\n            return;\n        }\n\n        // Because we remove all listeners on the vadEmitter once the main event is triggered,\n        // there is no need to check for rogue events.\n        if (vadScore.score > VAD_VOICE_LEVEL) {\n            this._processing = true;\n            this._scoreArray.push(vadScore.score);\n\n            // Start gathering VAD scores for the configured period of time.\n            this._processTimeout = setTimeout(this._calculateVADScore, PROCESS_TIME_FRAME_SPAN_MS);\n        }\n    }\n\n    /**\n     * Reset the processing context, clear buffer, cancel the timeout trigger.\n     *\n     * @returns {void}\n     */\n    public reset(): void {\n        this._processing = false;\n        this._scoreArray = [];\n        clearTimeout(this._processTimeout);\n    }\n}\n","export class InvalidTokenError extends Error {\n}\nInvalidTokenError.prototype.name = \"InvalidTokenError\";\nfunction b64DecodeUnicode(str) {\n    return decodeURIComponent(atob(str).replace(/(.)/g, (m, p) => {\n        let code = p.charCodeAt(0).toString(16).toUpperCase();\n        if (code.length < 2) {\n            code = \"0\" + code;\n        }\n        return \"%\" + code;\n    }));\n}\nfunction base64UrlDecode(str) {\n    let output = str.replace(/-/g, \"+\").replace(/_/g, \"/\");\n    switch (output.length % 4) {\n        case 0:\n            break;\n        case 2:\n            output += \"==\";\n            break;\n        case 3:\n            output += \"=\";\n            break;\n        default:\n            throw new Error(\"base64 string is not of the correct length\");\n    }\n    try {\n        return b64DecodeUnicode(output);\n    }\n    catch (err) {\n        return atob(output);\n    }\n}\nexport function jwtDecode(token, options) {\n    if (typeof token !== \"string\") {\n        throw new InvalidTokenError(\"Invalid token specified: must be a string\");\n    }\n    options || (options = {});\n    const pos = options.header === true ? 0 : 1;\n    const part = token.split(\".\")[pos];\n    if (typeof part !== \"string\") {\n        throw new InvalidTokenError(`Invalid token specified: missing part #${pos + 1}`);\n    }\n    let decoded;\n    try {\n        decoded = base64UrlDecode(part);\n    }\n    catch (e) {\n        throw new InvalidTokenError(`Invalid token specified: invalid base64 for part #${pos + 1} (${e.message})`);\n    }\n    try {\n        return JSON.parse(decoded);\n    }\n    catch (e) {\n        throw new InvalidTokenError(`Invalid token specified: invalid json for part #${pos + 1} (${e.message})`);\n    }\n}\n","import Symbol from './_Symbol.js';\nimport arrayMap from './_arrayMap.js';\nimport isArray from './isArray.js';\nimport isSymbol from './isSymbol.js';\n\n/** Used as references for various `Number` constants. */\nvar INFINITY = 1 / 0;\n\n/** Used to convert symbols to primitives and strings. */\nvar symbolProto = Symbol ? Symbol.prototype : undefined,\n    symbolToString = symbolProto ? symbolProto.toString : undefined;\n\n/**\n * The base implementation of `_.toString` which doesn't convert nullish\n * values to empty strings.\n *\n * @private\n * @param {*} value The value to process.\n * @returns {string} Returns the string.\n */\nfunction baseToString(value) {\n  // Exit early for strings to avoid a performance hit in some environments.\n  if (typeof value == 'string') {\n    return value;\n  }\n  if (isArray(value)) {\n    // Recursively convert values (susceptible to call stack limits).\n    return arrayMap(value, baseToString) + '';\n  }\n  if (isSymbol(value)) {\n    return symbolToString ? symbolToString.call(value) : '';\n  }\n  var result = (value + '');\n  return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;\n}\n\nexport default baseToString;\n","/**\n * A specialized version of `_.map` for arrays without support for iteratee\n * shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns the new mapped array.\n */\nfunction arrayMap(array, iteratee) {\n  var index = -1,\n      length = array == null ? 0 : array.length,\n      result = Array(length);\n\n  while (++index < length) {\n    result[index] = iteratee(array[index], index, array);\n  }\n  return result;\n}\n\nexport default arrayMap;\n","import baseGetTag from './_baseGetTag.js';\nimport isObjectLike from './isObjectLike.js';\n\n/** `Object#toString` result references. */\nvar symbolTag = '[object Symbol]';\n\n/**\n * Checks if `value` is classified as a `Symbol` primitive or object.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.\n * @example\n *\n * _.isSymbol(Symbol.iterator);\n * // => true\n *\n * _.isSymbol('abc');\n * // => false\n */\nfunction isSymbol(value) {\n  return typeof value == 'symbol' ||\n    (isObjectLike(value) && baseGetTag(value) == symbolTag);\n}\n\nexport default isSymbol;\n","import basePropertyOf from './_basePropertyOf.js';\n\n/** Used to map HTML entities to characters. */\nvar htmlUnescapes = {\n  '&amp;': '&',\n  '&lt;': '<',\n  '&gt;': '>',\n  '&quot;': '\"',\n  '&#39;': \"'\"\n};\n\n/**\n * Used by `_.unescape` to convert HTML entities to characters.\n *\n * @private\n * @param {string} chr The matched character to unescape.\n * @returns {string} Returns the unescaped character.\n */\nvar unescapeHtmlChar = basePropertyOf(htmlUnescapes);\n\nexport default unescapeHtmlChar;\n","/**\n * The base implementation of `_.propertyOf` without support for deep paths.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Function} Returns the new accessor function.\n */\nfunction basePropertyOf(object) {\n  return function(key) {\n    return object == null ? undefined : object[key];\n  };\n}\n\nexport default basePropertyOf;\n","import toString from './toString.js';\nimport unescapeHtmlChar from './_unescapeHtmlChar.js';\n\n/** Used to match HTML entities and HTML characters. */\nvar reEscapedHtml = /&(?:amp|lt|gt|quot|#39);/g,\n    reHasEscapedHtml = RegExp(reEscapedHtml.source);\n\n/**\n * The inverse of `_.escape`; this method converts the HTML entities\n * `&amp;`, `&lt;`, `&gt;`, `&quot;`, and `&#39;` in `string` to\n * their corresponding characters.\n *\n * **Note:** No other HTML entities are unescaped. To unescape additional\n * HTML entities use a third-party library like [_he_](https://mths.be/he).\n *\n * @static\n * @memberOf _\n * @since 0.6.0\n * @category String\n * @param {string} [string=''] The string to unescape.\n * @returns {string} Returns the unescaped string.\n * @example\n *\n * _.unescape('fred, barney, &amp; pebbles');\n * // => 'fred, barney, & pebbles'\n */\nfunction unescape(string) {\n  string = toString(string);\n  return (string && reHasEscapedHtml.test(string))\n    ? string.replace(reEscapedHtml, unescapeHtmlChar)\n    : string;\n}\n\nexport default unescape;\n","import baseToString from './_baseToString.js';\n\n/**\n * Converts `value` to a string. An empty string is returned for `null`\n * and `undefined` values. The sign of `-0` is preserved.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to convert.\n * @returns {string} Returns the converted string.\n * @example\n *\n * _.toString(null);\n * // => ''\n *\n * _.toString(-0);\n * // => '-0'\n *\n * _.toString([1, 2, 3]);\n * // => '1,2,3'\n */\nfunction toString(value) {\n  return value == null ? '' : baseToString(value);\n}\n\nexport default toString;\n","/**\n * The errors for the connection.\n */\n\nexport enum JitsiConnectionErrors {\n\n    /**\n     * When the conference-request to jicofo fails.\n     */\n    CONFERENCE_REQUEST_FAILED = 'connection.conferenceRequestFailed',\n\n    /**\n     * Indicates that the connection was dropped with an error which was most likely\n     * caused by some networking issues. The dropped term in this context means that\n     * the connection was closed unexpectedly (not on user's request).\n     *\n     * One example is 'item-not-found' error thrown by Prosody when the BOSH session\n     * times out after 60 seconds of inactivity. On the other hand 'item-not-found'\n     * could also happen when BOSH request is sent to the server with the session-id\n     * that is not know to the server. But this should not happen in lib-jitsi-meet\n     * case as long as the service is configured correctly (there is no bug).\n     */\n    CONNECTION_DROPPED_ERROR = 'connection.droppedError',\n\n    /**\n     * Not ready error. When the conference error is not ready according to jicofo.\n     */\n    NOT_LIVE_ERROR = 'connection.notLiveError',\n\n    /**\n     * Not specified errors.\n     */\n    OTHER_ERROR = 'connection.otherError',\n\n    /**\n     * Indicates that a password is required in order to join the conference.\n     */\n    PASSWORD_REQUIRED = 'connection.passwordRequired',\n\n    /**\n     * Indicates that the connection was dropped, because of too many 5xx HTTP\n     * errors on BOSH requests.\n     */\n    SERVER_ERROR = 'connection.serverError',\n\n    /**\n     * Indicates that the connection was dropped, because of conference being moved to a new shard.\n     */\n    SHARD_CHANGED_ERROR = 'connection.shardChangedError'\n}\n\n// exported for backward compatibility\nexport const CONFERENCE_REQUEST_FAILED = JitsiConnectionErrors.CONFERENCE_REQUEST_FAILED;\nexport const CONNECTION_DROPPED_ERROR = JitsiConnectionErrors.CONNECTION_DROPPED_ERROR;\nexport const NOT_LIVE_ERROR = JitsiConnectionErrors.NOT_LIVE_ERROR;\nexport const OTHER_ERROR = JitsiConnectionErrors.OTHER_ERROR;\nexport const PASSWORD_REQUIRED = JitsiConnectionErrors.PASSWORD_REQUIRED;\nexport const SERVER_ERROR = JitsiConnectionErrors.SERVER_ERROR;\nexport const SHARD_CHANGED_ERROR = JitsiConnectionErrors.SHARD_CHANGED_ERROR;\n","/* eslint-disable */\n\n/*\n * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined\n * in FIPS PUB 180-1\n * Version 2.1a Copyright Paul Johnston 2000 - 2002.\n * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet\n * Distributed under the BSD License\n * See http://pajhome.org.uk/crypt/md5 for details.\n */\n/* global define */\n\n/* Some functions and variables have been stripped for use with Strophe */\n\n/*\n * Calculate the SHA-1 of an array of big-endian words, and a bit length\n */\nfunction core_sha1(x: number[], len: number): number[] {\n    /* append padding */\n    x[len >> 5] |= 0x80 << (24 - len % 32);\n    x[((len + 64 >> 9) << 4) + 15] = len;\n\n    var w = new Array(80);\n    var a =  1732584193;\n    var b = -271733879;\n    var c = -1732584194;\n    var d =  271733878;\n    var e = -1009589776;\n\n    var i, j, t, olda, oldb, oldc, oldd, olde;\n    for (i = 0; i < x.length; i += 16) {\n        olda = a;\n        oldb = b;\n        oldc = c;\n        oldd = d;\n        olde = e;\n\n        for (j = 0; j < 80; j++) {\n            if (j < 16) {\n                w[j] = x[i + j];\n            } else {\n                w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1);\n            }\n\n            t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)),\n                         safe_add(safe_add(e, w[j]), sha1_kt(j)));\n            e = d;\n            d = c;\n            c = rol(b, 30);\n            b = a;\n            a = t;\n        }\n\n        a = safe_add(a, olda);\n        b = safe_add(b, oldb);\n        c = safe_add(c, oldc);\n        d = safe_add(d, oldd);\n        e = safe_add(e, olde);\n    }\n    return [a, b, c, d, e];\n}\n\n/*\n * Perform the appropriate triplet combination function for the current\n * iteration\n */\nfunction sha1_ft (t: number, b: number, c: number, d: number): number {\n    if (t < 20) { return (b & c) | ((~b) & d); }\n    if (t < 40) { return b ^ c ^ d; }\n    if (t < 60) { return (b & c) | (b & d) | (c & d); }\n    return b ^ c ^ d;\n}\n\n/*\n * Determine the appropriate additive constant for the current iteration\n */\nfunction sha1_kt(t: number): number {\n    return (t < 20) ?  1518500249 : (t < 40) ?  1859775393 : (t < 60) ? -1894007588 : -899497514;\n}\n\n/*\n * Calculate the HMAC-SHA1 of a key and some data\n */\nfunction core_hmac_sha1(key: string, data: string): number[] {\n    var bkey = str2binb(key);\n    if (bkey.length > 16) {\n        bkey = core_sha1(bkey, key.length * 8);\n    }\n\n    var ipad = new Array(16), opad = new Array(16);\n    for (var i = 0; i < 16; i++) {\n        ipad[i] = bkey[i] ^ 0x36363636;\n        opad[i] = bkey[i] ^ 0x5C5C5C5C;\n    }\n\n    var hash = core_sha1(ipad.concat(str2binb(data)), 512 + data.length * 8);\n    return core_sha1(opad.concat(hash), 512 + 160);\n}\n\n/*\n * Add integers, wrapping at 2^32. This uses 16-bit operations internally\n * to work around bugs in some JS interpreters.\n */\nfunction safe_add(x: number, y: number): number {\n    var lsw = (x & 0xFFFF) + (y & 0xFFFF);\n    var msw = (x >> 16) + (y >> 16) + (lsw >> 16);\n    return (msw << 16) | (lsw & 0xFFFF);\n}\n\n/*\n * Bitwise rotate a 32-bit number to the left.\n */\nfunction rol(num: number, cnt: number): number {\n    return (num << cnt) | (num >>> (32 - cnt));\n}\n\n/*\n * Convert an 8-bit or 16-bit string to an array of big-endian words\n * In 8-bit function, characters >255 have their hi-byte silently ignored.\n */\nfunction str2binb(str: string): number[] {\n    var bin = [];\n    var mask = 255;\n    for (var i = 0; i < str.length * 8; i += 8) {\n        bin[i>>5] |= (str.charCodeAt(i / 8) & mask) << (24 - i%32);\n    }\n    return bin;\n}\n\n/*\n * Convert an array of big-endian words to a base-64 string\n */\nfunction binb2b64 (binarray: number[]): string {\n    var tab = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n    var str = \"\";\n    var triplet, j;\n    for (var i = 0; i < binarray.length * 4; i += 3) {\n        triplet = (((binarray[i   >> 2] >> 8 * (3 -  i   %4)) & 0xFF) << 16) |\n                  (((binarray[i+1 >> 2] >> 8 * (3 - (i+1)%4)) & 0xFF) << 8 ) |\n                  ((binarray[i+2 >> 2] >> 8 * (3 - (i+2)%4)) & 0xFF);\n\n        for (j = 0; j < 4; j++) {\n            if (i * 8 + j * 6 > binarray.length * 32) { str += \"=\"; }\n            else { str += tab.charAt((triplet >> 6*(3-j)) & 0x3F); }\n        }\n    }\n    return str;\n}\n\n/*\n * Convert an array of big-endian words to a string\n */\nfunction binb2str(bin: number[]): string {\n    var str = \"\";\n    var mask = 255;\n    for (var i = 0; i < bin.length * 32; i += 8) {\n        str += String.fromCharCode((bin[i>>5] >>> (24 - i%32)) & mask);\n    }\n    return str;\n}\n\n/*\n * These are the functions you'll usually want to call\n * They take string arguments and return either hex or base-64 encoded strings\n */\nconst SHA1 = {\n    b64_hmac_sha1:  function (key: string, data: string): string { return binb2b64(core_hmac_sha1(key, data)); },\n    b64_sha1:       function (s: string): string { return binb2b64(core_sha1(str2binb(s),s.length * 8)); },\n    binb2str:       binb2str,\n    core_hmac_sha1: core_hmac_sha1,\n    str_hmac_sha1:  function (key: string, data: string): string { return binb2str(core_hmac_sha1(key, data)); },\n    str_sha1:       function (s: string): string { return binb2str(core_sha1(str2binb(s),s.length * 8)); },\n};\nexport { SHA1 as default };\n","import { Strophe } from 'strophe.js'; // eslint-disable-line camelcase\n\nimport { XMPPEvents } from '../../service/xmpp/XMPPEvents';\nimport Listenable from '../util/Listenable';\nimport { findAll, getAttribute } from '../util/XMLUtils';\n\nimport ChatRoom from './ChatRoom';\nimport sha1 from './sha1';\n\n/**\n * The property\n */\nconst IDENTITY_PROPERTIES = [ 'category', 'type', 'lang', 'name' ];\nconst IDENTITY_PROPERTIES_FOR_COMPARE = [ 'category', 'type', 'lang' ];\nconst HASH = 'sha-1';\n\ntype Identity = {\n    category: string;\n    lang?: string;\n    name?: string;\n    type: string;\n};\n\n/**\n *\n * @param a\n * @param b\n */\nfunction compareIdentities(a: Identity, b: Identity): number {\n    let res = 0;\n\n    IDENTITY_PROPERTIES_FOR_COMPARE.some(key =>\n        (res = ((a[key as keyof Identity] > b[key as keyof Identity]) && 1) || ((a[key as keyof Identity] < b[key as keyof Identity]) && -1)) !== 0\n    );\n\n    return res;\n}\n\n/**\n * Produces a sha-1 from provided identity and features values.\n *\n * @param {Array<Object>} identities - The identity objects.\n * @param {Array<string>} features - The features.\n * @returns {string}\n */\nfunction generateSha(identities: Identity[], features: string[]): string {\n    const sortedIdentities = identities.sort(compareIdentities).reduce(\n        (accumulatedValue, identity) => `${\n            IDENTITY_PROPERTIES.reduce(\n                (tmp, key, idx) =>\n                    tmp\n                        + (idx === 0 ? '' : '/')\n                        + (identity[key as keyof Identity] ? identity[key as keyof Identity] : ''),\n                '')\n        }<`, '');\n    const sortedFeatures = features.sort().reduce(\n        (tmp, feature) => `${tmp + feature}<`, '');\n\n    return sha1.b64_sha1(sortedIdentities + sortedFeatures);\n}\n\n/**\n * Parses the disco-info node and returns the sets of features and identities.\n * @param {String} node The node with results to parse.\n * @returns {{features: Set<string>, identities: Set<Identity>}}\n */\nexport function parseDiscoInfo(node: Element): { features: Set<string>; identities: Set<Identity>; } {\n    const features = new Set<string>();\n    const identities = new Set<Identity>();\n\n    findAll(node, ':scope>query>feature').forEach(el => features.add(getAttribute(el, 'var')));\n    findAll(node, ':scope>query>identity').forEach(el => identities.add({\n        category: getAttribute(el, 'category'),\n        name: getAttribute(el, 'name'),\n        type: getAttribute(el, 'type')\n    }));\n\n    return {\n        features,\n        identities\n    };\n}\n\n/**\n * Implements xep-0115 ( http://xmpp.org/extensions/xep-0115.html )\n */\nexport default class Caps extends Listenable {\n    public node: string;\n    public disco: any; // Todo - strophe.disco\n    public version: string;\n    public rooms: Set<ChatRoom>;\n    public externalFeatures: Set<string>;\n    /**\n     * Constructs new Caps instance.\n     * @param {Strophe.Connection} connection the strophe connection object\n     * @param {String} node the value of the node attribute of the \"c\" xml node\n     * that will be sent to the other participants\n     */\n    constructor(connection: Strophe.Connection = {}, node: string = 'http://jitsi.org/jitsimeet') {\n        super();\n        this.node = node;\n        this.disco = connection.disco;\n        if (!this.disco) {\n            throw new Error(\n                'Missing strophe-plugins '\n                + '(disco plugin is required)!');\n        }\n\n        this.version = '';\n        this.rooms = new Set<ChatRoom>();\n\n        // We keep track of features added outside the library and we publish them\n        // in the presence of the participant for simplicity, avoiding the disco info request-response.\n        this.externalFeatures = new Set<string>();\n\n        const emuc = connection.emuc;\n\n        emuc.addListener(XMPPEvents.EMUC_ROOM_ADDED,\n            (room: ChatRoom) => this._addChatRoom(room));\n        emuc.addListener(XMPPEvents.EMUC_ROOM_REMOVED,\n            (room: ChatRoom) => this._removeChatRoom(room));\n        Object.keys(emuc.rooms).forEach((jid: string) => {\n            this._addChatRoom(emuc.rooms[jid]);\n        });\n\n        Strophe.addNamespace('CAPS', 'http://jabber.org/protocol/caps');\n        this.disco.addFeature(Strophe.NS.CAPS);\n    }\n\n\n    /**\n     * Returns a set with the features and identities for a host.\n     * @param {String} jid the jid of the host\n     * @param {String|null} node the node to query\n     * @param {int} timeout the timeout in ms for reply from the host.\n     * @returns {Promise<{features: Set<string>, identities: Set<Identity>}>}\n     * @private\n     */\n    private _getDiscoInfo(jid: string, node: string | null, timeout: number): Promise<{ features: Set<string>; identities: Set<Identity>; }> {\n        return new Promise((resolve, reject) =>\n            this.disco.info(jid, node, (response: Element) => {\n                resolve(parseDiscoInfo(response));\n            }, reject, timeout)\n        );\n    }\n\n    /**\n     * Adds ChatRoom instance to the list of rooms. Adds listeners to the room\n     * and adds \"c\" element to the presences of the room.\n     * @param {ChatRoom} room the room.\n     */\n    private _addChatRoom(room: ChatRoom): void {\n        this.rooms.add(room);\n        this._fixChatRoomPresenceMap(room);\n\n        this._updateRoomWithExternalFeatures(room);\n    }\n\n    /**\n     * Creates/updates the \"c\" xml node into the presence of the passed room.\n     * @param {ChatRoom} room the room.\n     */\n    private _fixChatRoomPresenceMap(room: ChatRoom): void {\n        room.addOrReplaceInPresence('c', {\n            attributes: {\n                hash: HASH,\n                node: this.node,\n                ver: this.version,\n                xmlns: Strophe.NS.CAPS\n            }\n        });\n    }\n\n    /**\n     * Generates the value for the \"ver\" attribute.\n     */\n    private _generateVersion(): void {\n        this.version\n            = generateSha(this.disco._identities, this.disco._features);\n\n        this._notifyVersionChanged();\n    }\n\n\n    /**\n     * Handles this.version changes.\n     */\n    private _notifyVersionChanged(): void {\n        // update the version for all rooms\n        this.rooms.forEach(room => this._fixChatRoomPresenceMap(room));\n    }\n\n    /**\n     * Removes ChatRoom instance from the list of rooms. Removes listeners\n     * added from the Caps class.\n     * @param {ChatRoom} room the room.\n     */\n    private _removeChatRoom(room: ChatRoom): void {\n        this.rooms.delete(room);\n    }\n\n    /**\n     * Updates the presences in the room based on the current values in externalFeatures.\n     * @param {ChatRoom} room the room to update.\n     * @private\n     */\n    private _updateRoomWithExternalFeatures(room: ChatRoom): void {\n        if (this.externalFeatures.size === 0) {\n            room.removeFromPresence('features');\n        } else {\n            const children: Array<{ attributes: { var: string; }; tagName: string; }> = [];\n\n            this.externalFeatures.forEach(f => {\n                children.push({\n                    attributes: { 'var': f },\n                    'tagName': 'feature'\n                });\n            });\n\n            room.addOrReplaceInPresence('features', { children });\n        }\n    }\n\n\n    /**\n     * Adds new feature to the list of supported features for the local\n     * participant\n     * @param {String} feature the name of the feature.\n     * @param {boolean} submit if true - new presence with updated \"c\" node\n     * will be sent.\n     * @param {boolean} external whether this feature was added externally to the library.\n     * We put features used directly by the clients (is jibri, remote-control enabled etc.) in the presence\n     * to avoid additional disco-info queries by those clients.\n     */\n    public addFeature(feature: string, submit: boolean = false, external: boolean = false): void {\n        this.disco.addFeature(feature);\n        this._generateVersion();\n\n        if (external && !this.externalFeatures.has(feature)) {\n            this.externalFeatures.add(feature);\n            this.rooms.forEach(room => this._updateRoomWithExternalFeatures(room));\n        }\n\n        if (submit) {\n            this.submit();\n        }\n    }\n\n    /**\n     * Returns a set with the features for a host.\n     * @param {String} jid the jid of the host\n     * @param {int} timeout the timeout in ms for reply from the host.\n     * @returns {Promise<{features: Set<string>, identities: Set<Identity>}>}\n     */\n    public getFeaturesAndIdentities(jid: string, node: string, timeout: number = 5000): Promise<{ features: Set<string>; identities: Set<Identity>; }> {\n        return this._getDiscoInfo(jid, node, timeout);\n    }\n\n    /**\n     * Removes a feature from the list of supported features for the local\n     * participant\n     * @param {String} feature the name of the feature.\n     * @param {boolean} submit if true - new presence with updated \"c\" node\n     * will be sent.\n     * @param {boolean} external whether this feature was added externally to the library.\n     */\n    public removeFeature(feature: string, submit: boolean = false, external: boolean = false): void {\n        this.disco.removeFeature(feature);\n        this._generateVersion();\n\n        if (external && this.externalFeatures.has(feature)) {\n            this.externalFeatures.delete(feature);\n            this.rooms.forEach(room => this._updateRoomWithExternalFeatures(room));\n        }\n\n        if (submit) {\n            this.submit();\n        }\n    }\n\n    /**\n         * Sends new presence stanza for every room from the list of rooms.\n         */\n    public submit(): void {\n        this.rooms.forEach(room => room.sendPresence(undefined));\n    }\n}\n","import { XMPPEvents } from '../../service/xmpp/XMPPEvents';\n\nimport ChatRoom from './ChatRoom';\nimport XMPP from './xmpp';\n\nexport const IDENTITY_TYPE = 'file-sharing';\n\n/**\n * The file metadata used in file sharing.\n * Fields like `authorParticipantId`, `authorParticipantJid`, and `authorParticipantName` and `conferenceFullName` will\n * be set by the backend, so passing them is optional.\n */\nexport type IFileMetadata = {\n    /**\n     * The ID of the participant who uploaded the file.\n     */\n    authorParticipantId?: string;\n\n    /**\n     * The connection JID of the participant who uploaded the file.\n     */\n    authorParticipantJid?: string;\n\n    /**\n     * The name of the participant who uploaded the file.\n     */\n    authorParticipantName?: string;\n\n    /**\n     * The jid of the conference where the file was uploaded.\n     */\n    conferenceFullName?: string;\n\n    /**\n     * The unique ID of the file.\n     */\n    fileId: string;\n\n    /**\n     * The name of the file.\n     */\n    fileName: string;\n\n    /**\n     * The size of the file in bytes.\n     */\n    fileSize: number;\n\n    /**\n     * The file type (file extension).\n     */\n    fileType: string;\n\n    /**\n     * The time when it was uploaded.\n     */\n    timestamp: number;\n};\n\n/**\n * The FileSharing logic.\n */\nexport default class FileSharing {\n    private _mainRoom: ChatRoom;\n    private _xmpp: XMPP;\n\n    /**\n     * Constructs File sharing manager for a room.\n     *\n     * @param {ChatRoom} room the main room.\n     */\n    constructor(room: ChatRoom) {\n        this._mainRoom = room;\n        this._xmpp = room.xmpp;\n\n        this._handleMessages = this._handleMessages.bind(this);\n        this._mainRoom.xmpp.addListener(XMPPEvents.FILE_SHARING_EVENT, this._handleMessages);\n    }\n\n    /**\n     * Stops listening for events.\n     */\n    dispose() {\n        this._mainRoom.xmpp.removeListener(XMPPEvents.FILE_SHARING_EVENT, this._handleMessages);\n    }\n\n    /**\n     * Whether file sharing is supported on backend.\n     *\n     * @returns {boolean} whether file sharing is supported on backend.\n     */\n    isSupported() {\n        return Boolean(this._xmpp.fileSharingComponentAddress);\n    }\n\n    /**\n     * Returns the file sharing identity type (service name).\n     *\n     * @returns {string} the file sharing service name.\n     */\n    getIdentityType() {\n        return IDENTITY_TYPE;\n    }\n\n    /**\n     * Adds a file to the file sharing component after the file has been uploaded.\n     * @param metadata - The metadata of the file to be added.\n     */\n    addFile(metadata: IFileMetadata) {\n        const message = {\n            type: 'add',\n            xmlns: 'http://jitsi.org/jitmeet'\n        };\n\n        this._sendMessage(message, metadata);\n    }\n\n    /**\n     * Removes a file from the file sharing component after the file was deleted.\n     * @param fileId - The file ID of the file to be removed.\n     */\n    removeFile(fileId: string) {\n        const message = {\n            fileId,\n            type: 'remove',\n            xmlns: 'http://jitsi.org/jitmeet'\n        };\n\n        this._sendMessage(message);\n    }\n\n    /**\n     * Helper to send a file sharing message to the component.\n     *\n     * @param {Object} message - Command that needs to be sent.\n     * @param {Object} content - The content to add to the element created if any.\n     */\n    _sendMessage(message: object, content?: object) {\n        const msg = $msg({ to: this._xmpp.fileSharingComponentAddress });\n\n        msg.c(IDENTITY_TYPE, message, content ? JSON.stringify(content) : undefined).up();\n\n        this._xmpp.connection.send(msg);\n    }\n\n    /**\n     * Handles a message for file sharing.\n     *\n     * @param {object} payload - Arbitrary data.\n     */\n    _handleMessages(payload) {\n        switch (payload.event) {\n        case 'add':\n\n            this._mainRoom.eventEmitter.emit(XMPPEvents.FILE_SHARING_FILE_ADDED, payload.file);\n\n            break;\n        case 'remove': {\n            this._mainRoom.eventEmitter.emit(XMPPEvents.FILE_SHARING_FILE_REMOVED, payload.fileId);\n            break;\n        }\n        case 'list': {\n            this._mainRoom.eventEmitter.emit(XMPPEvents.FILE_SHARING_FILES_RECEIVED, payload.files);\n            break;\n        }\n        }\n    }\n}\n","// Number of times the client attempts to reconnect to the XMPP server or JVB (in case of an ICE failure).\nexport const MAX_CONNECTION_RETRIES = 3;\n","import { getLogger } from '@jitsi/logger';\n\nimport Listenable from '../util/Listenable';\n\nexport const NETWORK_INFO_EVENT = 'NETWORK_INFO_CHANGED';\n\nconst logger = getLogger('connectivity:NetworkInfo');\n\nexport interface ICurrentNetworkInfo {\n    isOnline: boolean;\n}\n\n/**\n * Module provides information about the current status of the internet\n * connection. Lib-jitsi-meet doesn't have any logic for detecting internet\n * online/offline, but rather it relies on the information supplied by the app\n * that uses it. By default the online state is assumed and the lib acts as if\n * it was connected. See {@link JitsiMeetJS.setNetworkInfo}.\n */\nexport class NetworkInfo extends Listenable {\n    private _current: ICurrentNetworkInfo;\n\n    /**\n     * Creates new {@link NetworkInfo} instance.\n     */\n    constructor() {\n        super();\n        this._current = {\n            isOnline: true\n        };\n    }\n\n    /**\n     * Updates the network info state.\n     *\n     * @param {object} state - The network info state.\n     * @param {boolean} state.isOnline - {@code true} if the internet connectivity is online or {@code false}\n     * otherwise.\n     */\n    updateNetworkInfo({ isOnline }: { isOnline: boolean; }): void {\n        logger.debug('updateNetworkInfo', { isOnline });\n        this._current = {\n            isOnline: isOnline === true\n        };\n        this.eventEmitter.emit(NETWORK_INFO_EVENT, this._current);\n    }\n\n    /**\n     * Returns the online/offline internet status. By default the value is {@code true} and changes only if\n     * the lib's user wires the state through {@link JitsiMeetJS.setNetworkInfo} like the jitsi-meet does. Because of\n     * that any logic should still assume that the internet may be offline and should handle the failure gracefully.\n     * It's only a good hint in the other way around: to pause internet operations until it comes back online.\n     * @returns {boolean}\n     */\n    isOnline(): boolean {\n        return this._current.isOnline === true;\n    }\n}\n\nconst networkInfo = new NetworkInfo();\n\nexport default networkInfo;\n","/**\n * Gets next timeout using the full jitter pattern.\n *\n * NOTE that there are no checks for argument correctness, so either do the math or use defaults.\n *\n * @param {number} retry - The retry number.\n * @param {number} minDelay - The minimal delay in milliseconds.\n * @param {number} base - The exponent base.\n * @returns {number} - The amount of waiting before trying another time given in milliseconds.\n * @private\n */\nexport function getJitterDelay(retry: number, minDelay: number = 500, base: number = 2): number {\n    return Math.floor((Math.random() * ((Math.pow(base, retry) * 1000) - minDelay)) + minDelay);\n}\n","import { getLogger } from '@jitsi/logger';\nimport Strophe from 'strophe.js';\n\nimport {\n    NETWORK_INFO_EVENT,\n    default as NetworkInfo\n} from '../connectivity/NetworkInfo';\nimport { getJitterDelay } from '../util/Retry';\n\nconst logger = getLogger('xmpp:ResumeTask');\n\n\nexport interface INetworkInfoEvent {\n    isOnline: boolean;\n}\n\n/**\n * The class contains the logic for triggering connection resume via XEP-0198 stream management.\n * It does two things, the first one is it tracks the internet online/offline status and it makes sure that\n * the reconnect is attempted only while online. The seconds thing is that it tracks the retry attempts and extends\n * the retry interval using the full jitter pattern.\n */\nexport default class ResumeTask {\n    private _stropheConn: Strophe.Connection;\n    private _resumeRetryN: number;\n    private _retryDelay: Optional<number>;\n    private _resumeTimeout: Optional<ReturnType<typeof setTimeout>>;\n    private _networkOnlineListener: Nullable<() => void>;\n\n    /**\n     * Initializes new {@code RetryTask}.\n     * @param {Strophe.Connection} stropheConnection - The Strophe connection instance.\n     */\n    constructor(stropheConnection: Strophe.Connection) {\n        this._stropheConn = stropheConnection;\n        this._resumeRetryN = 0;\n        this._retryDelay = undefined;\n        this._resumeTimeout = undefined;\n        this._networkOnlineListener = null;\n    }\n\n    /**\n     * @returns {number} - The amount of retries.\n     */\n    get retryCount(): number {\n        return this._resumeRetryN;\n    }\n\n    /**\n     * @returns {number|undefined} - How much the app will wait before trying to resume the XMPP connection. When\n     * 'undefined' it means that no resume task was not scheduled.\n     */\n    get retryDelay(): Optional<number> {\n        return this._retryDelay;\n    }\n\n    /**\n     * Removes network online listener for the NETWORK_INFO_EVENT event.\n     *\n     * @private\n     * @returns {void}\n     */\n    private _removeNetworkOnlineListener(): void {\n        if (this._networkOnlineListener) {\n            this._networkOnlineListener();\n            this._networkOnlineListener = null;\n        }\n    }\n\n    /**\n     * Schedules a delayed timeout which will execute the resume action.\n     * @private\n     * @returns {void}\n     */\n    private _scheduleResume(): void {\n        if (this._resumeTimeout) {\n            // NO-OP\n            return;\n        }\n\n        // The retry delay will be:\n        //   1st retry: 1.5s - 3s\n        //   2nd retry: 3s - 9s\n        //   3rd and next retry: 4.5s - 27s\n        this._retryDelay = getJitterDelay(\n            /* retry */ this._resumeRetryN,\n            /* minDelay */ this._resumeRetryN * 1500,\n            3\n        );\n\n        logger.info(`Will try to resume the XMPP connection in ${this.retryDelay}ms`);\n\n        this._resumeTimeout = setTimeout(() => this.resumeConnection(), this.retryDelay);\n    }\n\n    /**\n     * Cancels the delayed resume task.\n     *\n     * @returns {void}\n     */\n    cancelResume(): void {\n        if (this._resumeTimeout) {\n            logger.info('Canceling connection resume task');\n            clearTimeout(this._resumeTimeout);\n            this._resumeTimeout = undefined;\n            this._retryDelay = undefined;\n        }\n    }\n\n    /**\n     * Resumes the XMPP connection using the stream management plugin.\n     *\n     * @returns {void}\n     */\n    resumeConnection(): void {\n        this._resumeTimeout = undefined;\n\n        const { streamManagement } = this._stropheConn;\n        const resumeToken = streamManagement.getResumeToken();\n\n        // Things may have changed since when the task was scheduled\n        if (!resumeToken) {\n            return;\n        }\n\n        logger.info('Trying to resume the XMPP connection');\n\n        const url = new URL(this._stropheConn.service);\n        let { search } = url;\n        const pattern = /(previd=)([\\w-]+)/;\n        const oldToken = search.match(pattern);\n\n        // Replace previd if the previd value has changed.\n        if (oldToken && oldToken.indexOf(resumeToken) === -1) {\n            search = search.replace(pattern, `$1${resumeToken}`);\n\n        // Append previd if it doesn't exist.\n        } else if (!oldToken) {\n            search += search.indexOf('?') === -1 ? `?previd=${resumeToken}` : `&previd=${resumeToken}`;\n        }\n\n        url.search = search;\n\n        this._stropheConn.service = url.toString();\n\n        try {\n            streamManagement.resume();\n        } catch (e) {\n            logger.error('Failed to resume XMPP connection', e);\n        }\n    }\n\n    /**\n     * Cancels the retry task. It's called by {@link XmppConnection} when it's no longer interested in reconnecting for\n     * example when the disconnect method is called.\n     *\n     * @returns {void}\n     */\n    cancel(): void {\n        this.cancelResume();\n        this._removeNetworkOnlineListener();\n        this._resumeRetryN = 0;\n    }\n\n    /**\n     * Called by {@link XmppConnection} when the connection drops and it's a signal it wants to schedule a reconnect.\n     *\n     * @returns {void}\n     */\n    schedule(): void {\n        this.cancelResume();\n        this._removeNetworkOnlineListener();\n\n        this._resumeRetryN += 1;\n\n        this._networkOnlineListener = NetworkInfo.addCancellableListener(\n            NETWORK_INFO_EVENT,\n            ({ isOnline }: INetworkInfoEvent) => {\n                if (isOnline) {\n                    this._scheduleResume();\n                } else {\n                    this.cancelResume();\n                }\n            }\n        ) as () => void;\n\n        NetworkInfo.isOnline() && this._scheduleResume();\n    }\n}\n","/**\n * Attaches to the {@link Strophe.Connection.rawInput} which is called whenever any data is received from the server.\n */\n\nimport { Strophe } from 'strophe.js';\n\nimport XmppConnection from './XmppConnection';\n\n\nexport default class LastRequestTracker {\n    private _lastSuccess: Nullable<number>;\n    private _lastFailedMessage: Nullable<string>;\n\n    /**\n     * Initializes new instance.\n     */\n    constructor() {\n        this._lastSuccess = null;\n        this._lastFailedMessage = null;\n    }\n\n    /**\n     * Starts tracking requests on the given connection.\n     *\n     * @param {XmppConnection} xmppConnection - The XMPP connection which manages the given {@code stropheConnection}.\n     * @param {Strophe.Connection} stropheConnection - Strophe connection instance.\n     */\n    startTracking(xmppConnection: XmppConnection, stropheConnection: Strophe.Connection): void {\n        const originalRawInput = stropheConnection.rawInput;\n\n        stropheConnection.rawInput = (...args: any[]): void => {\n            const rawMessage = args[0];\n\n            if (rawMessage.includes('failure')) {\n                this._lastFailedMessage = rawMessage;\n            }\n\n            // It's okay to use rawInput callback only once the connection has been established, otherwise it will\n            // treat 'item-not-found' or other connection error on websocket reconnect as successful stanza received.\n            if (xmppConnection.connected) {\n                this._lastSuccess = Date.now();\n            }\n            originalRawInput.apply(stropheConnection, args);\n        };\n    }\n\n    /**\n     * Returns the last raw failed incoming message on the xmpp connection.\n     *\n     * @returns {Nullable<string>}\n     */\n    getLastFailedMessage(): Nullable<string> {\n        return this._lastFailedMessage;\n    }\n\n    /**\n     * Returns how many milliseconds have passed since the last successful BOSH request.\n     *\n     * @returns {Nullable<number>}\n     */\n    getTimeSinceLastSuccess(): Nullable<number> {\n        return this._lastSuccess\n            ? Date.now() - this._lastSuccess\n            : null;\n    }\n}\n","/* eslint-disable */\n\nimport { $build, Strophe } from 'strophe.js';\n\n/**\n* StropheJS - Stream Management XEP-0198\n*\n* This plugin implements stream management ACK capabilities of the specs XEP-0198.\n* Note: Resumption is not supported in this current implementation.\n*\n* Reference: http://xmpp.org/extensions/xep-0198.html\n*\n* @class streamManagement\n*/\ninterface IStreamManagementPlugin {\n\tlogging: boolean;\n\tautoSendCountOnEveryIncomingStanza: boolean;\n\trequestResponseInterval: number;\n\t_c: any;\n\t_NS: string;\n\t_isStreamManagementEnabled: boolean;\n\t_serverProcesssedStanzasCounter: number | null;\n\t_clientProcessedStanzasCounter: number | null;\n\t_clientSentStanzasCounter: number | null;\n\t_originalXMLOutput: ((elem: Element) => any) | null;\n\t_requestHandler: any;\n\t_incomingHandler: any;\n\t_requestResponseIntervalCount: number;\n\t_isSupported: boolean;\n\t_unacknowledgedStanzas: Element[];\n\t_acknowledgedStanzaListeners: ((stanza: Element) => void)[];\n\t_resumeToken?: string;\n\t_connectionStatus?: number;\n\t_resuming?: boolean;\n\t_connectArgs?: IArguments;\n\t_originalConnect?: (...args: any[]) => any;\n\t_originalOnStreamFeaturesAfterSASL?: (...args: any[]) => any;\n\t_originalDoDisconnect?: (...args: any[]) => any;\n\t_originalDisconnect?: (...args: any[]) => any;\n\t_resumeState?: any;\n\t_storedJid?: string;\n\t_ackHandler?: any;\n\t_enabledHandler?: any;\n\t_resumeFailedHandler?: any;\n\t_resumedHandler?: any;\n\n\taddAcknowledgedStanzaListener(listener: (stanza: Element) => void): void;\n\tenable(resume: boolean): void;\n\tgetResumeToken(): string | undefined;\n\tisSupported(): boolean;\n\tresume(): void;\n\trequestAcknowledgement(): void;\n\tgetOutgoingCounter(): number | null;\n\tgetIncomingCounter(): number | null;\n\tinit(conn: any): void;\n\tstatusChanged(status: number): void;\n\txmlOutput(elem: Element): any;\n\t_interceptDisconnect(): void;\n\t_interceptDoDisconnect(): void;\n\t_interceptConnectArgs(): void;\n\t_onStreamFeaturesAfterSASL(elem: Element): any;\n\t_incomingStanzaHandler(elem: Element): boolean;\n\t_handleEnabled(elem: Element): boolean;\n\t_handleResumeFailed(elem: Element): boolean;\n\t_handleResumed(elem: Element): boolean;\n\t_handleAcknowledgedStanzas(reportedHandledCount: number, lastKnownHandledCount: number): void;\n\t_handleServerRequestHandler(): boolean;\n\t_handleServerAck(elem: Element): boolean;\n\t_answerProcessedStanzas(): void;\n\t_increaseSentStanzasCounter(elem: Element): void;\n\t_increaseReceivedStanzasCounter(): void;\n\t_throwError(msg: string): never;\n}\n\nconst streamManagement: IStreamManagementPlugin = {\n\n\t/**\n\t* @property {Boolean} logging: Set to true to enable logging regarding out of sync stanzas.\n\t*/\n\tlogging: false,\n\n\t/**\n\t* @property {Boolean} autoSendCountOnEveryIncomingStanza: Set to true to send an 'a' response after every stanza.\n\t* @default false\n\t* @public\n\t*/\n\tautoSendCountOnEveryIncomingStanza: false,\n\n\t/**\n\t* @property {Integer} requestResponseInterval: Set this value to send a request for counter on very interval\n\t* number of stanzas sent. Set to 0 to disable.\n\t* @default 5\n\t* @public\n\t*/\n\trequestResponseInterval: 5,\n\n\t/**\n\t* @property {Pointer} _c: Strophe connection instance.\n\t* @private\n\t*/\n\t_c: null,\n\n\t/**\n\t* @property {String} _NS XMPP Namespace.\n\t* @private\n\t*/\n\t_NS: 'urn:xmpp:sm:3',\n\n\t/**\n\t* @property {Boolean} _isStreamManagementEnabled\n\t* @private\n\t*/\n\t_isStreamManagementEnabled: false,\n\n\t/**\n\t* @property {Integer} _serverProcesssedStanzasCounter: Keeps count of stanzas confirmed processed by the server.\n\t* The server is the source of truth of this value. It is the 'h' attribute on the latest 'a' element received\n\t* from the server.\n\t* @private\n\t*/\n\t_serverProcesssedStanzasCounter: null,\n\n\t/**\n\t* @property {Integer} _clientProcessedStanzasCounter: Counter of stanzas received by the client from the server.\n\t* Client is the source of truth of this value. It is the 'h' attribute in the 'a' sent from the client to\n\t* the server.\n\t* @private\n\t*/\n\t_clientProcessedStanzasCounter: null,\n\n\t/**\n\t* @property {Integer} _clientSentStanzasCounter\n\t* @private\n\t*/\n\t_clientSentStanzasCounter: null,\n\n\t/**\n\t* Stores a reference to Strophe connection xmlOutput function to wrap counting functionality.\n\t* @method _originalXMLOutput\n\t* @type {Handler}\n\t* @private\n\t*/\n\t_originalXMLOutput: null,\n\n\t/**\n\t* @property {Handler} _requestHandler: Stores reference to handler that process count request from server.\n\t* @private\n\t*/\n\t_requestHandler: null,\n\n\t/**\n\t* @property {Handler} _incomingHandler: Stores reference to handler that processes incoming stanzas count.\n\t* @private\n\t*/\n\t_incomingHandler: null,\n\n\t/**\n\t* @property {Integer} _requestResponseIntervalCount: Counts sent stanzas since last response request.\n\t*/\n\t_requestResponseIntervalCount: 0,\n\n\t/**\n\t * @property {boolean} _isSupported: indicates whether or not the server has advertised support for the stream\n\t * management namespace.\n\t */\n\t_isSupported: false,\n\n\t/**\n\t* @property {Queue} _unacknowledgedStanzas: Maintains a list of packet ids for stanzas which have yet to be acknowledged.\n\t*/\n\t_unacknowledgedStanzas: [],\n\n\t/**\n\t* @property {Array} _acknowledgedStanzaListeners: Stores callbacks for each stanza acknowledged by the server.\n\t* Provides the packet id of the stanza as a parameter.\n\t* @private\n\t*/\n\t_acknowledgedStanzaListeners: [],\n\n\taddAcknowledgedStanzaListener: function(listener: (stanza: Element) => void): void {\n\t\tthis._acknowledgedStanzaListeners.push(listener);\n\t},\n\n\tenable: function(resume: boolean): void {\n\t\tif (!this._isSupported) {\n\t\t\tthrow new Error('The server doesn\\'t support urn:xmpp:sm:3 namespace');\n\t\t} else if (this._connectionStatus !== Strophe.Status.CONNECTED) {\n\t\t\tthrow new Error('enable() can only be called in the CONNECTED state');\n\t\t}\n\t\tthis._c.send($build('enable', { xmlns: this._NS, resume }));\n\t\tthis._c.flush();\n\t\tthis._c.pause();\n\t},\n\n\tgetResumeToken: function(): Optional<string> {\n\t\treturn this._resumeToken;\n\t},\n\n\tisSupported(): boolean {\n\t\treturn this._isSupported;\n\t},\n\n\tresume: function(): void {\n\t\tif (!this.getResumeToken()) {\n\t\t\tthrow new Error('No resume token');\n\t\t}\n\t\tif (this._connectionStatus !== Strophe.Status.DISCONNECTED) {\n\t\t\tthrow new Error('resume() can only be called in the DISCONNECTED state');\n\t\t}\n\n\t\tthis._c.options.explicitResourceBinding = true;\n\t\tthis._resuming = true;\n\n\t\tthis._originalConnect!.apply(this._c, this._connectArgs);\n\t},\n\n\trequestAcknowledgement: function(): void {\n\t\tif (this._connectionStatus !== Strophe.Status.CONNECTED) {\n\t\t\tthrow new Error('requestAcknowledgement() can only be called in the CONNECTED state');\n\t\t}\n\t\tthis._requestResponseIntervalCount = 0;\n\t\tthis._c.send($build('r', { xmlns: this._NS }));\n\t},\n\n\tgetOutgoingCounter: function(): Nullable<number> {\n\t\treturn this._clientSentStanzasCounter;\n\t},\n\n\tgetIncomingCounter: function(): Nullable<number> {\n\t\treturn this._clientProcessedStanzasCounter;\n\t},\n\n\tinit: function(conn: any): void {\n\t\tthis._c = conn;\n\t\tStrophe.addNamespace('SM', this._NS);\n\n\t\t// Storing original xmlOutput function to use additional logic\n\t\tthis._originalXMLOutput = this._c.xmlOutput;\n\t\tthis._c.xmlOutput = this.xmlOutput.bind(this);\n\n\t\tthis._originalConnect = this._c.connect;\n\t\tthis._c.connect = this._interceptConnectArgs.bind(this);\n\n\t\tthis._originalOnStreamFeaturesAfterSASL = this._c._onStreamFeaturesAfterSASL;\n\t\tthis._c._onStreamFeaturesAfterSASL = this._onStreamFeaturesAfterSASL.bind(this);\n\n\t\tthis._originalDoDisconnect = this._c._doDisconnect;\n\t\tthis._c._doDisconnect = this._interceptDoDisconnect.bind(this);\n\n\t\tthis._originalDisconnect = this._c.disconnect;\n\t\tthis._c.disconnect = this._interceptDisconnect.bind(this);\n\t},\n\n\t_interceptDisconnect: function(): void {\n\t\tthis._resumeToken = undefined;\n\t\tthis._originalDisconnect!.apply(this._c, arguments);\n\t},\n\n\t_interceptDoDisconnect: function(): void {\n\t\tif (this.getResumeToken()\n\t\t\t\t&& !this._resuming\n\t\t\t\t&& this._c.connected && !this._c.disconnecting) {\n\t\t\tthis._resumeState = {\n\t\t\t\thandlers: this._c.handlers,\n\t\t\t\ttimedHandlers: this._c.timedHandlers,\n\t\t\t\tremoveTimeds: this._c.removeTimeds,\n\t\t\t\tremoveHandlers: this._c.removeHandlers,\n\t\t\t\taddTimeds: this._c.addTimeds,\n\t\t\t\taddHandlers: this._c.addHandlers\n\t\t\t};\n\t\t\tthis._storedJid = this._c.jid;\n\n\t\t\tthis.logging && Strophe.debug('SM stored resume state, handler count: ' + this._resumeState.handlers.length);\n\t\t}\n\n\t\t// Remove any queued stanzas from the buffer that have failed to send while the socket was closed,\n\t\t// as they would interfere with the resume flow. They will be resent anyway.\n\t\tthis._c._data = [];\n\n\t\tthis._originalDoDisconnect!.apply(this._c, arguments);\n\t},\n\n\t_interceptConnectArgs: function(): void {\n\t\tthis._connectArgs = arguments;\n\n\t\tthis._originalConnect!.apply(this._c, arguments);\n\t},\n\n\t_onStreamFeaturesAfterSASL: function(elem: Element): any {\n\t\tthis._isSupported = elem.getElementsByTagNameNS(this._NS, \"sm\").length > 0;\n\n\t\treturn this._originalOnStreamFeaturesAfterSASL!.apply(this._c, arguments);\n\t},\n\n\tstatusChanged: function (status: number): void {\n\t\tthis._connectionStatus = status;\n\t\tif (!this.getResumeToken()\n\t\t\t&& (status === Strophe.Status.CONNECTED || status === Strophe.Status.DISCONNECTED)) {\n\t\t\tthis.logging && Strophe.debug('SM reset state');\n\n\t\t\tthis._serverProcesssedStanzasCounter = 0;\n\t\t\tthis._clientProcessedStanzasCounter = 0;\n\n\t\t\tthis._clientSentStanzasCounter = 0;\n\n\t\t\tthis._isStreamManagementEnabled = false;\n\t\t\tthis._requestResponseIntervalCount = 0;\n\n\t\t\t// FIXME not described in JSDocs\n\t\t\tthis._resuming = false;\n\n\t\t\tif (status === Strophe.Status.DISCONNECTED) {\n\t\t\t\tthis._isSupported = false;\n\t\t\t}\n\n\t\t\tthis._unacknowledgedStanzas = [];\n\n\t\t\tif (this._requestHandler) {\n\t\t\t\tthis._c.deleteHandler(this._requestHandler);\n\t\t\t}\n\n\t\t\tif (this._incomingHandler) {\n\t\t\t\tthis._c.deleteHandler(this._incomingHandler);\n\t\t\t}\n\n\t\t\tthis._requestHandler = this._c.addHandler(this._handleServerRequestHandler.bind(this), this._NS, 'r');\n\t\t\tthis._ackHandler = this._c.addHandler(this._handleServerAck.bind(this), this._NS, 'a');\n\t\t\tthis._incomingHandler = this._c.addHandler(this._incomingStanzaHandler.bind(this));\n\n\t\t\t// FIXME handler instances stored, but never used\n\t\t\tthis._enabledHandler = this._c._addSysHandler(this._handleEnabled.bind(this), this._NS, 'enabled');\n\t\t\tthis._resumeFailedHandler = this._c._addSysHandler(this._handleResumeFailed.bind(this), this._NS, 'failed');\n\t\t\tthis._resumedHandler =  this._c._addSysHandler(this._handleResumed.bind(this), this._NS,'resumed');\n\n\t\t} else if (status === Strophe.Status.BINDREQUIRED)  {\n\t\t\tthis._c.jid = this._storedJid;\n\n\t\t\t// Restore Strophe handlers\n\t\t\tfor (const h of (this._resumeState.handlers || [])\n\t\t\t\t\t.concat(this._resumeState.addHandlers || [])) {\n\t\t\t\tthis._c._addSysHandler(h.handler, h.ns, h.name, h.type, h.id);\n\t\t\t}\n\t\t\tfor (const h of (this._resumeState.timedHandlers || [])\n\t\t\t\t\t.concat(this._resumeState.addTimeds)) {\n\t\t\t\tthis._c.addTimedHandler(h.period, h.handler);\n\t\t\t}\n\t\t\tfor (const h of (this._resumeState.removeTimeds || [])\n\t\t\t\t\t.concat(this._resumeState.removeHandlers || [])) {\n\t\t\t\tthis._c.deleteTimedHandler(h);\n\t\t\t}\n\n\t\t\t// FIXME check conditions if there's session ID and if enabled\n\t\t\tthis._c.send($build('resume', {\n\t\t\t\txmlns: this._NS,\n\t\t\t\th: this._clientProcessedStanzasCounter,\n\t\t\t\tprevid: this._resumeToken\n\t\t\t}));\n\t\t\tthis._c.flush();\n\t\t} else if (status === Strophe.Status.ERROR) {\n\t\t\tthis.logging && Strophe.debug('SM cleared resume token on error');\n\t\t\tthis._resumeToken = undefined;\n\t\t}\n\t},\n\n\t/**\n\t* This method overrides the send method implemented by Strophe.Connection\n\t* to count outgoing stanzas\n\t*\n\t* @method Send\n\t* @public\n\t*/\n\txmlOutput: function(elem: Element): any {\n\t\tif (Strophe.isTagEqual(elem, 'iq') ||\n\t\t\tStrophe.isTagEqual(elem, 'presence') ||\n\t\t\tStrophe.isTagEqual(elem, 'message')) {\n\t\t\tthis._increaseSentStanzasCounter(elem);\n\t\t}\n\n\t\treturn this._originalXMLOutput!.call(this._c, elem);\n\t},\n\n\t_handleEnabled: function(elem: Element): boolean {\n\t\tthis._isStreamManagementEnabled = true;\n\t\t// FIXME fail if requested, but not enabled\n\t\tthis._resumeToken = elem.getAttribute('resume') === 'true' && elem.getAttribute('id') || undefined;\n\n\t\tthis._c.resume();\n\n\t\treturn true;\n\t},\n\n\t_handleResumeFailed: function(elem: Element): boolean {\n\t\tconst error = elem && (\n\t\t\t(elem.firstElementChild && (elem.firstElementChild as Element).tagName)\n\t\t\t|| (elem.firstChild && (elem.firstChild as Element).tagName));\n\n\t\tthis._c._changeConnectStatus(Strophe.Status.ERROR, error, elem);\n\t\tthis._c._doDisconnect();\n\n\t\treturn true;\n\t},\n\n\t_handleResumed: function(elem: Element): boolean {\n\t\t// FIXME check if in the correct state\n\t\tvar handledCount = parseInt(elem.getAttribute('h')!);\n\t\tthis._handleAcknowledgedStanzas(handledCount, this._serverProcesssedStanzasCounter!);\n\n\t\tthis._resuming = false;\n\t\tthis._c.do_bind = false; // No need to bind our resource anymore\n\t\tthis._c.authenticated = true;\n\t\tthis._c.restored = true;\n\n\t\tif (this._unacknowledgedStanzas.length > 0) {\n\t\t\tthis.logging && Strophe.debug('SM Sending unacknowledged stanzas', this._unacknowledgedStanzas);\n\t\t\tfor(const stanza of this._unacknowledgedStanzas) {\n\t\t\t\tthis._c.send(stanza);\n\t\t\t}\n\t\t} else {\n\t\t\tthis.logging && Strophe.debug('SM No unacknowledged stanzas', this._unacknowledgedStanzas);\n\t\t}\n\n\t\tthis._c._changeConnectStatus(Strophe.Status.CONNECTED, null);\n\n\t\treturn true;\n\t},\n\n\t_incomingStanzaHandler: function(elem: Element): boolean {\n\t\tif (Strophe.isTagEqual(elem, 'iq') || Strophe.isTagEqual(elem, 'presence') || Strophe.isTagEqual(elem, 'message'))  {\n\t\t\tthis._increaseReceivedStanzasCounter();\n\n\t\t\tif (this.autoSendCountOnEveryIncomingStanza) {\n\t\t\t\tthis._answerProcessedStanzas();\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t},\n\n\t_handleAcknowledgedStanzas: function(reportedHandledCount: number, lastKnownHandledCount: number): void {\n\t\tvar delta = reportedHandledCount - lastKnownHandledCount;\n\n\t\tif (delta < 0) {\n\t\t\tthis._throwError('New reported stanza count lower than previous. New: ' + reportedHandledCount + ' - Previous: ' + lastKnownHandledCount);\n\t\t}\n\n\t\tif (delta > this._unacknowledgedStanzas.length) {\n\t\t\tthis._throwError('Higher reported acknowledge count than unacknowledged stanzas. Reported Acknowledge Count: ' + delta + ' - Unacknowledge Stanza Count: ' + this._unacknowledgedStanzas.length + ' - New: ' + reportedHandledCount + ' - Previous: ' + lastKnownHandledCount);\n\t\t}\n\n\t\tfor(var i = 0; i < delta; i++) {\n\t\t\tvar stanza = this._unacknowledgedStanzas.shift()!;\n\t\t\tfor (var j = 0; j < this._acknowledgedStanzaListeners.length; j++) {\n\t\t\t\tthis._acknowledgedStanzaListeners[j](stanza);\n\t\t\t}\n\t\t}\n\n\t\tif (this.logging && this._unacknowledgedStanzas.length > 0) {\n\t\t\tStrophe.warn('SM Unacknowledged stanzas', this._unacknowledgedStanzas);\n\t\t}\n\n\t\tthis._serverProcesssedStanzasCounter = reportedHandledCount;\n\n\t\tif (this.requestResponseInterval > 0) {\n\t\t\tthis._requestResponseIntervalCount = 0;\n\t\t}\n\t},\n\n\t_handleServerRequestHandler: function(): boolean {\n\t\tthis._answerProcessedStanzas();\n\n\t\treturn true;\n\t},\n\n\t_handleServerAck: function(elem: Element): boolean {\n\t\tvar handledCount = parseInt(elem.getAttribute('h')!);\n\t\tthis._handleAcknowledgedStanzas(handledCount, this._serverProcesssedStanzasCounter!);\n\n\t\treturn true;\n\t},\n\n\t_answerProcessedStanzas: function(): void {\n\t\tif (this._isStreamManagementEnabled) {\n\t\t\tthis._c.send($build('a', { xmlns: this._NS, h: this._clientProcessedStanzasCounter }));\n\t\t}\n\t},\n\n\t_increaseSentStanzasCounter: function(elem: Element): void {\n\t\tif (this._isStreamManagementEnabled) {\n\t\t\tif (this._unacknowledgedStanzas.indexOf(elem) !== -1) {\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis._unacknowledgedStanzas.push(elem);\n\t\t\tthis._clientSentStanzasCounter!++;\n\n\t\t\tif (this.requestResponseInterval > 0) {\n\t\t\t\tthis._requestResponseIntervalCount++;\n\n\t\t\t\tif (this._requestResponseIntervalCount === this.requestResponseInterval) {\n\t\t\t\t\t// FIXME Can not call send from onIdle.\n\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\tif (this._connectionStatus === Strophe.Status.CONNECTED) {\n\t\t\t\t\t\t\tthis.requestAcknowledgement();\n\t\t\t\t\t\t}\n\t\t\t\t\t}, 1);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t_increaseReceivedStanzasCounter: function(): void {\n\t\tif (this._isStreamManagementEnabled) {\n\t\t\tthis._clientProcessedStanzasCounter!++;\n\t\t}\n\t},\n\n\t_throwError: function(msg: string): never {\n\t\tStrophe.error(msg);\n\t\tthrow new Error(msg);\n\t}\n\n};\n\nStrophe.addConnectionPlugin('streamManagement', streamManagement);\n","import Listenable from '../util/Listenable';\n\nimport XmppConnection from './XmppConnection';\n\n/**\n * Creates ConnectionPlugin class that extends the passed class.\n * @param {Class} base the definition of the class that will be extended by\n * ConnectionPlugin\n */\nfunction getConnectionPluginDefinition<T extends new (...args: any[]) => {}>(base: T = class {} as T) {\n    /**\n     * Base class for strophe connection plugins.\n     */\n    return class extends base {\n        connection: Nullable<XmppConnection>;\n        /**\n         *\n         */\n        constructor(...args: any[]) {\n            super(...args);\n            this.connection = null;\n        }\n\n        /**\n         *\n         * @param connection\n         */\n        init(connection: XmppConnection): void {\n            this.connection = connection;\n        }\n    };\n}\n\n/**\n * ConnectionPlugin class.\n */\nexport default getConnectionPluginDefinition();\n\n/**\n * ConnectionPlugin class that extends Listenable.\n */\nexport const ConnectionPluginListenable = getConnectionPluginDefinition(Listenable);\n","import { getLogger } from '@jitsi/logger';\nimport { $iq, Strophe } from 'strophe.js';\n\nimport ConnectionPlugin from './ConnectionPlugin';\n\nconst logger = getLogger('xmpp:strophe.ping');\n\n/**\n * Default ping every 10 sec\n */\nconst PING_DEFAULT_INTERVAL = 10000;\n\n/**\n * Default ping timeout error after 5 sec of waiting.\n */\nconst PING_DEFAULT_TIMEOUT = 5000;\n\n/**\n * Default value for how many ping failures will be tolerated before the WebSocket connection is killed.\n * The worst case scenario in case of ping timing out without a response is (25 seconds at the time of this writing):\n * PING_THRESHOLD * PING_INTERVAL + PING_TIMEOUT\n */\nconst PING_DEFAULT_THRESHOLD = 2;\n\nexport interface IPingOptions {\n    interval?: number;\n    threshold?: number;\n    timeout?: number;\n}\n\nexport interface IPingConnectionPluginOptions {\n    getTimeSinceLastServerResponse: () => number;\n    onPingThresholdExceeded: () => void;\n    pingOptions?: IPingOptions;\n}\n\n/**\n * XEP-0199 ping plugin.\n *\n * Registers \"urn:xmpp:ping\" namespace under Strophe.NS.PING.\n */\nexport default class PingConnectionPlugin extends ConnectionPlugin {\n    failedPings: number;\n    _onPingThresholdExceeded: () => void;\n    _getTimeSinceLastServerResponse: () => number;\n    pingInterval: number;\n    pingTimeout: number;\n    pingThreshold: number;\n    pingTimestampsToKeep: number;\n    pingExecIntervals: number[];\n    intervalId: Nullable<number>;\n    _lastServerCheck: number;\n\n    /**\n     * Constructs new object\n     * @param {Object} options\n     * @param {Function} options.onPingThresholdExceeded - Callback called when ping fails too many times (controlled\n     * by the {@link PING_THRESHOLD} constant).\n     * @param {Function} options.getTimeSinceLastServerResponse - A function to obtain the last seen\n     * response from the server.\n     * @param {Object} options.pingOptions - The ping options if any.\n     * @constructor\n     */\n    constructor({ getTimeSinceLastServerResponse, onPingThresholdExceeded, pingOptions = {} }: IPingConnectionPluginOptions) {\n        super();\n        this.failedPings = 0;\n        this._onPingThresholdExceeded = onPingThresholdExceeded;\n        this._getTimeSinceLastServerResponse = getTimeSinceLastServerResponse;\n\n        this.pingInterval = typeof pingOptions.interval === 'number' ? pingOptions.interval : PING_DEFAULT_INTERVAL;\n        this.pingTimeout = typeof pingOptions.timeout === 'number' ? pingOptions.timeout : PING_DEFAULT_TIMEOUT;\n        this.pingThreshold = typeof pingOptions.threshold === 'number'\n            ? pingOptions.threshold : PING_DEFAULT_THRESHOLD;\n\n        // The number of timestamps of send pings to keep.\n        // The current value is 2 minutes.\n        this.pingTimestampsToKeep = Math.round(120000 / this.pingInterval);\n        this.pingExecIntervals = new Array(this.pingTimestampsToKeep);\n    }\n\n    /**\n     * Initializes the plugin. Method called by Strophe.\n     * @param connection Strophe connection instance.\n     */\n    override init(connection: Strophe.Connection): void {\n        super.init(connection);\n        Strophe.addNamespace('PING', 'urn:xmpp:ping');\n    }\n\n    /* eslint-disable max-params */\n\n    /**\n     * Sends \"ping\" to given <tt>jid</tt>\n     * @param jid the JID to which ping request will be sent.\n     * @param success callback called on success.\n     * @param error callback called on error.\n     * @param timeout ms how long are we going to wait for the response. On\n     * timeout <tt>error<//t> callback is called with undefined error argument.\n     */\n    ping(jid: string, success: (result: any) => void, error: (err: any) => void, timeout: number): void {\n        this._addPingExecutionTimestamp();\n\n        const iq = $iq({\n            to: jid,\n            type: 'get'\n        });\n\n        iq.c('ping', { xmlns: Strophe.NS.PING });\n        this.connection.sendIQ2(iq, { timeout })\n            .then(success, error);\n    }\n\n    /* eslint-enable max-params */\n\n    /**\n     * Starts to send ping in given interval to specified remote JID.\n     * This plugin supports only one such task and <tt>stopInterval</tt>\n     * must be called before starting a new one.\n     * @param remoteJid remote JID to which ping requests will be sent to.\n     */\n    startInterval(remoteJid: string): void {\n        clearInterval(this.intervalId);\n        this.intervalId = window.setInterval(() => {\n\n            // when there were some server responses in the interval since the last time we checked (_lastServerCheck)\n            // let's skip the ping\n\n            const now = Date.now();\n\n            if (this._getTimeSinceLastServerResponse() < now - this._lastServerCheck) {\n                // do this just to keep in sync the intervals so we can detect suspended device\n                this._addPingExecutionTimestamp();\n\n                this._lastServerCheck = now;\n                this.failedPings = 0;\n\n                return;\n            }\n\n            this.ping(remoteJid, () => {\n                // server response is measured on raw input and ping response time is measured after all the xmpp\n                // processing is done in js, so there can be some misalignment when we do the check above.\n                // That's why we store the last time we got the response\n                this._lastServerCheck = this._getTimeSinceLastServerResponse() + Date.now();\n\n                this.failedPings = 0;\n            }, error => {\n                this.failedPings += 1;\n                const errmsg = `Ping ${error ? 'error' : 'timeout'}`;\n\n                if (this.failedPings >= this.pingThreshold) {\n                    logger.error(errmsg, error);\n                    this._onPingThresholdExceeded?.();\n                } else {\n                    logger.warn(errmsg, error);\n                }\n            }, this.pingTimeout);\n        }, this.pingInterval);\n        logger.info(`XMPP pings will be sent every ${this.pingInterval} ms`);\n    }\n\n    /**\n     * Stops current \"ping\"  interval task.\n     */\n    stopInterval(): void {\n        if (this.intervalId) {\n            window.clearInterval(this.intervalId);\n            this.intervalId = null;\n            this.failedPings = 0;\n            logger.info('Ping interval cleared');\n        }\n    }\n\n    /**\n     * Adds the current time to the array of send ping timestamps.\n     * @private\n     */\n    _addPingExecutionTimestamp(): void {\n        this.pingExecIntervals.push(new Date().getTime());\n\n        // keep array length to PING_TIMESTAMPS_TO_KEEP\n        if (this.pingExecIntervals.length > this.pingTimestampsToKeep) {\n            this.pingExecIntervals.shift();\n        }\n    }\n\n    /**\n     * Returns the maximum time between the recent sent pings, if there is a\n     * big value it means the computer was inactive for some time(suspended).\n     * Checks the maximum gap between sending pings, considering and the\n     * current time. Trying to detect computer inactivity (sleep).\n     *\n     * @returns {int} the time ping was suspended, if it was not 0 is returned.\n     */\n    getPingSuspendTime(): number {\n        const pingIntervals = this.pingExecIntervals.slice();\n\n        // we need current time, as if ping was sent now\n        // if computer sleeps we will get correct interval after next\n        // scheduled ping, bet we sometimes need that interval before waiting\n        // for the next ping, on closing the connection on error.\n        pingIntervals.push(new Date().getTime());\n\n        let maxInterval = 0;\n        let previousTS = pingIntervals[0];\n\n        pingIntervals.forEach(e => {\n            const currentInterval = e - previousTS;\n\n            if (currentInterval > maxInterval) {\n                maxInterval = currentInterval;\n            }\n\n            previousTS = e;\n        });\n\n        // remove the interval between the ping sent\n        // this way in normal execution there is no suspend and the return\n        // will be 0 or close to 0.\n        maxInterval -= this.pingInterval;\n\n        // make sure we do not return less than 0\n        return Math.max(maxInterval, 0);\n    }\n}\n","import { getLogger } from '@jitsi/logger';\nimport { $pres, Strophe } from 'strophe.js';\n\nimport { MAX_CONNECTION_RETRIES } from '../../service/connectivity/Constants';\nimport Listenable from '../util/Listenable';\n\nimport ResumeTask from './ResumeTask';\nimport LastSuccessTracker from './StropheLastSuccess';\nimport './strophe.stream-management';\nimport MucConnectionPlugin from './strophe.emuc';\nimport JingleConnectionPlugin from './strophe.jingle';\nimport PingConnectionPlugin, { IPingOptions } from './strophe.ping';\nimport RayoConnectionPlugin from './strophe.rayo';\n\nconst logger = getLogger('xmpp:XmppConnection');\n\n/**\n * Extended ping options interface that includes domain property\n */\ninterface IXmppPingOptions extends IPingOptions {\n    domain?: string;\n}\n\n/**\n * Interface for connection plugins\n */\ninterface IConnectionPlugin {\n    init: (connection: XmppConnection) => void;\n}\n\n/**\n * IQ result callback type - result is typically an XML Element\n */\nexport type IQResultCallback = (result: Element) => void;\n\n/**\n * IQ error callback type - error can be a string, Element, Error object, or undefined (timeout)\n */\nexport type ErrorCallback = (error: string | Element | Error | undefined) => void;\n\n/**\n * Connection status callback type\n */\ntype IConnectionStatusCallback = (status: Strophe.Status, condition?: string, element?: Element) => void;\n\n/**\n * @typedef DeferredSendIQ Object\n * @property {Element} iq - The IQ to send.\n * @property {function} resolve - The resolve method of the deferred Promise.\n * @property {function} reject - The reject method of the deferred Promise.\n * @property {number} timeout - The ID of the timeout task that needs to be cleared, before sending the IQ.\n * @property {number} start - The timestamp when the deferred IQ was created.\n */\ninterface IDeferredSendIQ {\n    iq: Element | undefined;\n    reject: (error: string | Element | Error | undefined) => void;\n    resolve: (result: Element) => void;\n    start: number;\n    timeout: ReturnType<typeof setTimeout>;\n}\n\n/**\n * Constructor options interface for XmppConnection\n */\ninterface IXmppConnectionOptions {\n    enableWebsocketResume?: boolean;\n    serviceUrl: string;\n    shard?: string;\n    websocketKeepAlive?: number;\n    websocketKeepAliveUrl?: string;\n    xmppPing?: IXmppPingOptions;\n}\n\n/**\n * Internal options interface\n */\ninterface IInternalOptions {\n    enableWebsocketResume: boolean;\n    pingOptions?: IXmppPingOptions;\n    shard?: string;\n    websocketKeepAlive: number;\n    websocketKeepAliveUrl?: string;\n}\n\nconst TOKEN_REFRESH = 'token_refresh';\n\n/**\n * Adds one more status to Strophe.Status enum.\n */\nenum ExtendedStatus {\n    RESUMING = 15\n}\n\n/**\n * The lib-jitsi-meet layer for {@link Strophe.Connection}.\n * @internal\n */\nexport default class XmppConnection extends Listenable {\n\n    private _options: IInternalOptions;\n    private _usesWebsocket: boolean;\n    private _rawInputTracker: LastSuccessTracker;\n    private _resumeTask: ResumeTask;\n    private _deferredIQs: IDeferredSendIQ[];\n    private _oneSuccessfulConnect: boolean;\n    private _status: Strophe.Status;\n    private _wsKeepAlive: Optional<ReturnType<typeof setTimeout>>;\n\n    /**\n     * @internal\n     */\n    _stropheConn: Strophe.Connection;\n    public ping: PingConnectionPlugin;\n    public jingle?: JingleConnectionPlugin;\n    public rayo?: RayoConnectionPlugin;\n    public emuc?: MucConnectionPlugin;\n    /**\n     * @internal\n     */\n    _breakoutMovingToMain?: string;\n\n    /**\n     * The list of {@link XmppConnection} events.\n     *\n     * @returns {Object}\n     */\n    static get Events() {\n        return {\n            CONN_SHARD_CHANGED: 'CONN_SHARD_CHANGED',\n            CONN_STATUS_CHANGED: 'CONN_STATUS_CHANGED'\n        };\n    }\n\n    /**\n     * The list of Xmpp connection statuses.\n     *\n     * @returns {Strophe.Status}\n     */\n    static get Status() {\n        return { ...Strophe.Status, ...ExtendedStatus };\n    }\n\n    /**\n     * Initializes new connection instance.\n     *\n     * @param {Object} options\n     * @param {String} options.serviceUrl - The BOSH or WebSocket service URL.\n     * @param {String} options.shard - The BOSH or WebSocket is connecting to this shard.\n     * Useful for detecting when shard changes.\n     * @param {String} [options.enableWebsocketResume=true] - True/false to control the stream resumption functionality.\n     * It will enable automatically by default if supported by the XMPP server.\n     * @param {Number} [options.websocketKeepAlive=60000] - The websocket keep alive interval.\n     * It's the interval + a up to a minute of jitter. Pass -1 to disable.\n     * The keep alive is HTTP GET request to {@link options.serviceUrl} or to {@link options.websocketKeepAliveUrl}.\n     * @param {Number} [options.websocketKeepAliveUrl] - The websocket keep alive url to use if any,\n     * if missing the serviceUrl url will be used.\n     * @param {Object} [options.xmppPing] - The xmpp ping settings.\n     */\n    constructor({ enableWebsocketResume, websocketKeepAlive, websocketKeepAliveUrl, serviceUrl, shard, xmppPing }: IXmppConnectionOptions) {\n        super();\n        this._options = {\n            enableWebsocketResume: typeof enableWebsocketResume === 'undefined' ? true : enableWebsocketResume,\n            pingOptions: xmppPing,\n            shard,\n            websocketKeepAlive: typeof websocketKeepAlive === 'undefined' ? 60 * 1000 : Number(websocketKeepAlive),\n            websocketKeepAliveUrl\n        };\n\n        this._stropheConn = new Strophe.Connection(serviceUrl);\n\n        // The mechanisms priorities as defined by Strophe\n        // *      Mechanism       Priority\n        // *      ------------------------\n        // *      SCRAM-SHA-1     60\n        // *      PLAIN           50\n        // *      ANONYMOUS       20\n        this._stropheConn.registerSASLMechanisms([\n            Strophe.SASLAnonymous,\n            Strophe.SASLPlain,\n            Strophe.SASLSHA1\n        ]);\n        this._usesWebsocket = serviceUrl.startsWith('ws:') || serviceUrl.startsWith('wss:');\n\n        // The default maxRetries is 5, which is too long.\n        this._stropheConn.maxRetries = 3;\n\n        this._rawInputTracker = new LastSuccessTracker();\n        this._rawInputTracker.startTracking(this, this._stropheConn);\n\n        this._resumeTask = new ResumeTask(this._stropheConn);\n\n        /**\n         * @typedef DeferredSendIQ Object\n         * @property {Element} iq - The IQ to send.\n         * @property {function} resolve - The resolve method of the deferred Promise.\n         * @property {function} reject - The reject method of the deferred Promise.\n         * @property {number} timeout - The ID of the timeout task that needs to be cleared, before sending the IQ.\n         */\n        /**\n         * Deferred IQs to be sent upon reconnect.\n         * @type {Array<DeferredSendIQ>}\n         * @private\n         */\n        this._deferredIQs = [];\n\n        // Ping plugin is mandatory for the Websocket mode to work correctly. It's used to detect when the connection\n        // is broken (WebSocket/TCP connection not closed gracefully).\n        this.addConnectionPlugin(\n            'ping',\n            new PingConnectionPlugin({\n                getTimeSinceLastServerResponse: () => this.getTimeSinceLastSuccess(),\n                onPingThresholdExceeded: () => this._onPingErrorThresholdExceeded(),\n                pingOptions: xmppPing\n            }));\n\n        // tracks whether this is the initial connection or a reconnect\n        this._oneSuccessfulConnect = false;\n    }\n\n    /**\n     * A getter for the connected state.\n     *\n     * @returns {boolean}\n     */\n    get connected(): boolean {\n        const websocket = this._stropheConn?._proto?.socket;\n\n        return (this._status === Strophe.Status.CONNECTED || this._status === Strophe.Status.ATTACHED)\n            && (!this.isUsingWebSocket || (websocket && websocket.readyState === WebSocket.OPEN));\n    }\n\n    /**\n     * Retrieves the feature discovery plugin instance.\n     *\n     * @returns {Strophe.Connection.disco}\n     */\n    get disco() {\n        return this._stropheConn.disco;\n    }\n\n    /**\n     * A getter for the disconnecting state.\n     *\n     * @returns {boolean}\n     */\n    get disconnecting(): boolean {\n        return this._stropheConn.disconnecting === true;\n    }\n\n    /**\n     * A getter for the domain.\n     *\n     * @returns {Nullable<string>}\n     */\n    get domain(): Nullable<string> {\n        return this._stropheConn.domain;\n    }\n\n    /**\n     * Tells if Websocket is used as the transport for the current XMPP connection. Returns true for Websocket or false\n     * for BOSH.\n     * @returns {boolean}\n     */\n    get isUsingWebSocket(): boolean {\n        return this._usesWebsocket;\n    }\n\n    /**\n     * A getter for the JID.\n     *\n     * @returns {string|null}\n     */\n    get jid(): string | null {\n        return this._stropheConn.jid;\n    }\n\n    /**\n     * Returns headers for the last BOSH response received.\n     *\n     * @returns {string}\n     */\n    get lastResponseHeaders(): string {\n        return this._stropheConn._proto?.lastResponseHeaders;\n    }\n\n    /**\n     * A getter for the logger plugin instance.\n     *\n     * @returns {*}\n     */\n    get logger() {\n        return this._stropheConn.logger;\n    }\n\n    /**\n     * A getter for the connection options.\n     *\n     * @returns {*}\n     */\n    get options() {\n        return this._stropheConn.options;\n    }\n\n    /**\n     * A getter for the domain to be used for ping.\n     */\n    get pingDomain(): string | null {\n        return this._options.pingOptions?.domain || this.domain;\n    }\n\n    /**\n     * A getter for the service URL.\n     *\n     * @returns {string}\n     */\n    get service(): string {\n        return this._stropheConn.service;\n    }\n\n    /**\n     * Sets new value for shard.\n     * @param value the new shard value.\n     */\n    set shard(value: string) {\n        this._options.shard = value;\n    }\n\n    /**\n     * Returns the current connection status.\n     *\n     * @returns {Strophe.Status}\n     */\n    get status(): Strophe.Status {\n        return this._status;\n    }\n\n    /**\n     * Adds a connection plugin to this instance.\n     *\n     * @param {string} name - The name of the plugin or rather a key under which it will be stored on this connection\n     * instance.\n     * @param {IConnectionPlugin} plugin - The plugin to add.\n     */\n    addConnectionPlugin(name: string, plugin: IConnectionPlugin): void {\n        (this as unknown as Record<string, IConnectionPlugin>)[name] = plugin;\n        plugin.init(this);\n    }\n\n    /**\n     * See {@link Strophe.Connection.addHandler}\n     *\n     * @returns {Object} - handler for the connection.\n     */\n    addHandler(...args: Parameters<Strophe.Connection['addHandler']>): ReturnType<Strophe.Connection['addHandler']> {\n        return this._stropheConn.addHandler(...args);\n    }\n\n    /**\n     * See {@link Strophe.Connection.deleteHandler}\n     *\n     * @returns {void}\n     */\n    deleteHandler(...args: Parameters<Strophe.Connection['deleteHandler']>): ReturnType<Strophe.Connection['deleteHandler']> {\n        this._stropheConn.deleteHandler(...args);\n    }\n\n    /* eslint-disable max-params */\n    /**\n     * Wraps {@link Strophe.Connection.attach} method in order to intercept the connection status updates.\n     * See {@link Strophe.Connection.attach} for the params description.\n     *\n     * @returns {void}\n     */\n    attach(jid: string, sid: string, rid: string, callback: IConnectionStatusCallback, ...args: Parameters<Strophe.Connection['attach']>): void {\n        this._stropheConn.attach(jid, sid, rid, this._stropheConnectionCb.bind(this, callback), ...args);\n    }\n\n    /**\n     * Wraps Strophe.Connection.connect method in order to intercept the connection status updates.\n     * See {@link Strophe.Connection.connect} for the params description.\n     *\n     * @returns {void}\n     */\n    connect(jid: string, pass: string, callback: IConnectionStatusCallback, ...args: Parameters<Strophe.Connection['connect']>): void {\n        this._stropheConn.connect(jid, pass, this._stropheConnectionCb.bind(this, callback), ...args);\n    }\n\n    /* eslint-enable max-params */\n\n    /**\n     * Handles {@link Strophe.Status} updates for the current connection.\n     *\n     * @param {function} targetCallback - The callback passed by the {@link XmppConnection} consumer to one of\n     * the connect methods.\n     * @param {Strophe.Status} status - The new connection status.\n     * @param {*} args - The rest of the arguments passed by Strophe.\n     * @private\n    */\n    _stropheConnectionCb(targetCallback: IConnectionStatusCallback, status: Strophe.Status, condition?: string, element?: Element): void {\n        this._status = status;\n\n        if (status === Strophe.Status.CONNECTED || status === Strophe.Status.ATTACHED) {\n            this._maybeEnableStreamResume();\n\n            // after connecting - immediately check whether shard changed,\n            // we need this only when using websockets as bosh checks headers from every response\n            if (this._usesWebsocket) {\n                if (this._oneSuccessfulConnect) {\n                    // on reconnect we do it immediately\n                    this._maybeStartWSKeepAlive(0);\n                } else {\n                    // delay it a bit to not interfere with the connection process\n                    // and to allow backend to correct any possible split brain issues\n                    // Store timeout so it can be cleared if needed\n                    this._maybeStartWSKeepAlive(5000);\n                }\n            }\n            this._oneSuccessfulConnect = true;\n\n            this._processDeferredIQs();\n            this._resumeTask.cancel();\n            this.ping.startInterval(this._options.pingOptions?.domain || this.domain);\n        } else if (status === Strophe.Status.DISCONNECTED) {\n            this.ping.stopInterval();\n\n            // if resumption is scheduled skip disconnecting state event fire\n            if (this._tryResumingConnection(condition === TOKEN_REFRESH)) {\n\n                if (condition !== TOKEN_REFRESH) {\n                    // let's fire event that status changed to resuming\n                    // we do not fire it on refresh, as consumers should get\n                    // the event and execute refresh with a new token\n                    this.eventEmitter.emit(XmppConnection.Events.CONN_STATUS_CHANGED, ExtendedStatus.RESUMING);\n                }\n\n                return;\n            }\n\n            clearTimeout(this._wsKeepAlive);\n        }\n\n        targetCallback(status, condition, element);\n        this.eventEmitter.emit(XmppConnection.Events.CONN_STATUS_CHANGED, status);\n    }\n\n    /**\n     * Clears the list of IQs and rejects deferred Promises with an error.\n     *\n     * @private\n     */\n    _clearDeferredIQs(): void {\n        for (const deferred of this._deferredIQs) {\n            deferred.reject(new Error('disconnect'));\n        }\n        this._deferredIQs = [];\n    }\n\n    /**\n     * The method is meant to be used for testing. It's a shortcut for closing the WebSocket.\n     *\n     * @returns {void}\n     */\n    closeWebsocket(): void {\n        if (this._stropheConn?._proto) {\n            this._stropheConn._proto._closeSocket();\n            this._stropheConn._proto._onClose(null);\n        }\n    }\n\n    /**\n     * See {@link Strophe.Connection.disconnect}.\n     *\n     * @returns {void}\n     */\n    disconnect(...args: Parameters<Strophe.Connection['disconnect']>): void {\n        this._resumeTask.cancel();\n        clearTimeout(this._wsKeepAlive);\n        this._clearDeferredIQs();\n        this._stropheConn.disconnect(...args);\n    }\n\n    /**\n     * See {@link Strophe.Connection.flush}.\n     *\n     * @returns {void}\n     */\n    flush(...args: Parameters<Strophe.Connection['flush']>): void {\n        this._stropheConn.flush(...args);\n    }\n\n    /**\n     * See {@link LastRequestTracker.getTimeSinceLastSuccess}.\n     *\n     * @returns {number|null}\n     */\n    getTimeSinceLastSuccess(): number | null {\n        return this._rawInputTracker.getTimeSinceLastSuccess();\n    }\n\n    /**\n     * See {@link LastRequestTracker.getLastFailedMessage}.\n     *\n     * @returns {string|null}\n     */\n    getLastFailedMessage(): string | null {\n        return this._rawInputTracker.getLastFailedMessage();\n    }\n\n    /**\n     * Requests a resume token from the server if enabled and all requirements are met.\n     *\n     * @private\n     */\n    _maybeEnableStreamResume(): void {\n        if (!this._options.enableWebsocketResume) {\n\n            return;\n        }\n\n        const { streamManagement } = this._stropheConn;\n\n        if (!this.isUsingWebSocket) {\n            logger.warn('Stream resume enabled, but WebSockets are not enabled');\n        } else if (!streamManagement) {\n            logger.warn('Stream resume enabled, but Strophe streamManagement plugin is not installed');\n        } else if (!streamManagement.isSupported()) {\n            logger.warn('Stream resume enabled, but XEP-0198 is not supported by the server');\n        } else if (!streamManagement.getResumeToken()) {\n            logger.info('Enabling XEP-0198 stream management');\n            streamManagement.enable(/* resume */ true);\n        }\n    }\n\n    /**\n     * Starts the Websocket keep alive if enabled.\n     *\n     * @param {number|undefined} forcedTimeout - If provided, this timeout will be used instead of\n     * the configured one with added jitter.\n     *\n     * @private\n     * @returns {void}\n     */\n    _maybeStartWSKeepAlive(forcedTimeout?: number): void {\n        const { websocketKeepAlive } = this._options;\n\n        // if websocketKeepAlive is not set keepAlive is disabled\n        if (this._usesWebsocket && websocketKeepAlive > 0) {\n            this._wsKeepAlive || logger.info(`WebSocket keep alive interval: ${websocketKeepAlive}ms`);\n            clearTimeout(this._wsKeepAlive);\n\n            const interval = forcedTimeout\n                ?? (/* base */ websocketKeepAlive + /* jitter */ (Math.random() * 60 * 1000));\n\n            logger.debug(`Scheduling next WebSocket keep-alive in ${interval}ms`);\n\n            this._wsKeepAlive = setTimeout(\n                () => this._keepAliveAndCheckShard()\n                    .then(() => this._maybeStartWSKeepAlive()),\n                interval);\n        }\n    }\n\n    /**\n     * Do a http GET to the shard and if shard change will throw an event.\n     *\n     * @private\n     * @returns {Promise}\n     */\n    _keepAliveAndCheckShard(): Promise<void> {\n        const { shard, websocketKeepAliveUrl } = this._options;\n        const url = websocketKeepAliveUrl ? websocketKeepAliveUrl\n            : this.service.replace('wss://', 'https://').replace('ws://', 'http://');\n\n        return fetch(url)\n            .then(response => {\n\n                // skips header checking if there is no info in options\n                if (!shard) {\n                    return;\n                }\n\n                const responseShard = response.headers.get('x-jitsi-shard');\n\n                !responseShard && logger.warn('No x-jitsi-shard header present in keep-alive response');\n\n                // Ignore if no shard header is present.\n                if (responseShard && responseShard !== shard) {\n                    logger.error(\n                        `Detected that shard changed from ${shard} to ${responseShard}`);\n                    this.eventEmitter.emit(XmppConnection.Events.CONN_SHARD_CHANGED);\n                }\n            })\n            .catch(error => {\n                logger.error(`Websocket Keep alive failed for url: ${url}`, { error });\n            });\n    }\n\n    /**\n     * Goes over the list of {@link DeferredSendIQ} tasks and sends them.\n     *\n     * @private\n     * @returns {void}\n     */\n    _processDeferredIQs(): void {\n        for (const deferred of this._deferredIQs) {\n            if (deferred.iq) {\n                clearTimeout(deferred.timeout);\n\n                const timeLeft = Date.now() - deferred.start;\n\n                this.sendIQ(\n                    deferred.iq,\n                    result => deferred.resolve(result),\n                    error => deferred.reject(error),\n                    timeLeft);\n            }\n        }\n\n        this._deferredIQs = [];\n    }\n\n    /**\n     * Send a stanza. This function is called to push data onto the send queue to go out over the wire.\n     *\n     * @param {Element|Strophe.Builder} stanza - The stanza to send.\n     * @returns {void}\n     */\n    send(stanza: Element | Strophe.Builder): void {\n        if (!this.connected) {\n            logger.error(`Trying to send stanza while not connected. Status:${this._status} Proto:${\n                this.isUsingWebSocket ? this._stropheConn?._proto?.socket?.readyState : 'bosh'\n            }`);\n            throw new Error('Not connected');\n        }\n        this._stropheConn.send(stanza);\n    }\n\n    /**\n     * Helper function to send IQ stanzas.\n     *\n     * @param {Element} elem - The stanza to send.\n     * @param {Function} callback - The callback function for a successful request.\n     * @param {Function} errback - The callback function for a failed or timed out request.  On timeout, the stanza will\n     * be null.\n     * @param {number} timeout - The time specified in milliseconds for a timeout to occur.\n     * @returns {number} - The id used to send the IQ.\n     */\n    sendIQ(elem: Element, callback: Optional<IQResultCallback> = undefined, errback: Optional<ErrorCallback> = undefined, timeout: Optional<number> = undefined): number | undefined {\n        if (!this.connected) {\n            errback('Not connected');\n\n            return;\n        }\n\n        return this._stropheConn.sendIQ(elem, callback, errback, timeout);\n    }\n\n    /**\n     * Sends an IQ immediately if connected or puts it on the send queue otherwise(in contrary to other send methods\n     * which would fail immediately if disconnected).\n     *\n     * @param {Element} iq - The IQ to send.\n     * @param {Object} options - Options object\n     * @param {options.timeout} timeout - How long to wait for the response.\n     * The time when the connection is reconnecting is included, which means that\n     * the IQ may never be sent and still fail with a timeout.\n     */\n    sendIQ2(iq: Element, { timeout }: { timeout: number; }): Promise<Element> {\n        return new Promise((resolve, reject) => {\n            if (this.connected) {\n                this.sendIQ(\n                    iq,\n                    result => resolve(result),\n                    error => reject(error),\n                    timeout);\n            } else {\n                const deferred: IDeferredSendIQ = {\n                    iq,\n                    reject,\n                    resolve,\n                    start: Date.now(),\n                    timeout: setTimeout(() => {\n                        // clears the IQ on timeout and invalidates the deferred task\n                        deferred.iq = undefined;\n\n                        // Strophe calls with undefined on timeout\n                        reject(undefined);\n                    }, timeout)\n                };\n\n                this._deferredIQs.push(deferred);\n            }\n        });\n    }\n\n    /**\n     * Called by the ping plugin when ping fails too many times.\n     *\n     * @returns {void}\n     */\n    _onPingErrorThresholdExceeded(): void {\n        if (this.isUsingWebSocket) {\n            logger.warn('Ping error threshold exceeded - killing the WebSocket');\n            this.closeWebsocket();\n        }\n    }\n\n    /**\n     *  Helper function to send presence stanzas. The main benefit is for sending presence stanzas for which you expect\n     *  a responding presence stanza with the same id (for example when leaving a chat room).\n     *\n     * @param {Element} elem - The stanza to send.\n     * @param {Function} callback - The callback function for a successful request.\n     * @param {Function} errback - The callback function for a failed or timed out request. On timeout, the stanza will\n     * be null.\n     * @param {number} timeout - The time specified in milliseconds for a timeout to occur.\n     * @returns {number} - The id used to send the presence.\n     */\n    sendPresence(elem: Element, callback: IQResultCallback, errback: ErrorCallback, timeout: number): void {\n        if (!this.connected) {\n            errback('Not connected');\n\n            return;\n        }\n        this._stropheConn.sendPresence(elem, callback, errback, timeout);\n    }\n\n    /**\n     * The method gracefully closes the BOSH connection by using 'navigator.sendBeacon'.\n     *\n     * @returns {boolean} - true if the beacon was sent.\n     */\n    sendUnavailableBeacon(): boolean {\n        if (!navigator.sendBeacon || this._stropheConn.disconnecting || !this._stropheConn.connected) {\n            return false;\n        }\n\n        this._stropheConn._changeConnectStatus(Strophe.Status.DISCONNECTING);\n        this._stropheConn.disconnecting = true;\n\n        const body = this._stropheConn._proto._buildBody()\n            .attrs({\n                type: 'terminate'\n            });\n        const pres = $pres({\n            type: 'unavailable',\n            xmlns: Strophe.NS.CLIENT\n        });\n\n        body.cnode(pres.tree());\n\n        const res = navigator.sendBeacon(\n            this.service.indexOf('https://') === -1 ? `https:${this.service}` : this.service,\n            Strophe.serialize(body.tree()));\n\n        logger.info(`Successfully send unavailable beacon ${res}`);\n\n        this._stropheConn._proto._abortAllRequests();\n        this._stropheConn._doDisconnect();\n\n        return true;\n    }\n\n    /**\n     * Tries to use stream management plugin to resume dropped XMPP connection. The streamManagement plugin clears\n     * the resume token if any connection error occurs which would put it in unrecoverable state, so as long as\n     * the token is present it means the connection can be resumed.\n     *\n     * @private\n     * @returns {boolean} - Whether a resume attempt was scheduled or executed.\n     */\n    _tryResumingConnection(force = false): boolean {\n        const { streamManagement } = this._stropheConn;\n        const resumeToken = streamManagement?.getResumeToken();\n\n        if (resumeToken) {\n            if (force) {\n                logger.info('Trying to resume XMPP connection immediately due to token refresh');\n\n                this._resumeTask.resumeConnection();\n\n                return true;\n            } else {\n                this._resumeTask.schedule();\n            }\n\n            const r = this._resumeTask.retryCount <= MAX_CONNECTION_RETRIES;\n\n            if (!r) {\n                logger.warn(`Maximum resume tries reached (${MAX_CONNECTION_RETRIES}), giving up.`);\n            }\n\n            return r;\n        }\n\n        return false;\n    }\n\n    /**\n     * This method allows renewal of the tokens if they are expiring. The token is included in the service URL.\n     *\n     * @param {string} serviceUrl - The new service URL to connect to, if needed.\n     */\n    refreshToken(serviceUrl: string): Promise<void> {\n        this._stropheConn.service = serviceUrl;\n\n        return new Promise((resolve, reject) => {\n            let timeoutId: ReturnType<typeof setTimeout> = undefined;\n            const unsubscribe = this.addCancellableListener(\n                XmppConnection.Events.CONN_STATUS_CHANGED,\n                status => {\n                    if (status === Strophe.Status.CONNECTED && this._stropheConn.restored) {\n                        clearTimeout(timeoutId);\n                        unsubscribe();\n                        resolve();\n                    }\n                }\n            );\n\n            // this will trigger a resume\n            this._stropheConn.streamManagement?._interceptDoDisconnect(TOKEN_REFRESH);\n\n            timeoutId = setTimeout(() => {\n                unsubscribe();\n                reject(new Error('Token refresh timed out'));\n            }, 3000);\n        });\n    }\n\n    cancelResume() {\n        this._resumeTask.cancelResume();\n    }\n}\n","/**\n * Centralized Strophe error handler for logging and analytics.\n * Extracts error code, reason, message, and context from XMPP error stanzas.\n */\n\nimport { getLogger } from '@jitsi/logger';\n\nimport RTCStats from '../RTCStats/RTCStats';\nimport { RTCStatsEvents } from '../RTCStats/RTCStatsEvents';\n\nconst logger = getLogger('xmpp:StropheErrorHandler');\n\nexport interface IStropheErrorContext {\n    [key: string]: any;\n    operation?: string;\n    roomJid?: string;\n    userJid?: string;\n}\n\nexport function handleStropheError(errResponse: any, context: IStropheErrorContext = {}) {\n    const errorObj: any = {};\n    let errorEl: Element | null = null;\n\n    if (errResponse) {\n        if (errResponse.nodeType === 1 && errResponse.tagName.toUpperCase() === 'ERROR') {\n            errorEl = errResponse;\n        } else if (errResponse.nodeType === 1) {\n            const errorElements = errResponse.getElementsByTagName('error');\n\n            if (errorElements?.length > 0) {\n                errorEl = Array.from(errorElements as HTMLCollectionOf<Element>)[0] || null;\n            }\n        }\n    }\n\n    if (errorEl) {\n        errorObj.code = errorEl.getAttribute('code') || undefined;\n\n        // Get first child element as reason\n        const reasonEl = Array.from(errorEl.children)[0];\n\n        if (reasonEl) {\n            errorObj.reason = reasonEl.tagName;\n        }\n\n        // Get <text> child element\n        const msgEl = Array.from(errorEl.getElementsByTagName('text'))[0];\n\n        if (msgEl?.textContent) {\n            errorObj.msg = msgEl.textContent;\n        }\n\n        // Raw XML string for debugging\n        errorObj.raw = errorEl.outerHTML;\n\n    // if the connection is not established we directly return a string as error from sendIQ method\n    } else if (typeof errResponse === 'string') {\n        errorObj.reason = errResponse;\n    } else if (!errResponse) { // null or undefined\n        errorObj.reason = 'timeout';\n    } else { // Invalid type of error.\n        errorObj.reason = 'unknown';\n    }\n\n    // Merge in contextual info\n    Object.assign(errorObj, context);\n\n    logger.error('Strophe error:', JSON.stringify(errorObj));\n    RTCStats.sendStatsEntry(RTCStatsEvents.STROPHE_ERROR_EVENT, null, errorObj);\n}\n","/* eslint-disable newline-per-chained-call */\nimport { getLogger } from '@jitsi/logger';\nimport { $iq } from 'strophe.js';\n\nimport { CONFERENCE_REQUEST_FAILED, NOT_LIVE_ERROR } from '../../JitsiConnectionErrors';\nimport { CONNECTION_FAILED, CONNECTION_REDIRECTED } from '../../JitsiConnectionEvents';\nimport { AuthenticationEvents } from '../../service/authentication/AuthenticationEvents';\nimport { XMPPEvents } from '../../service/xmpp/XMPPEvents';\nimport Settings from '../settings/Settings';\nimport Listenable from '../util/Listenable';\nimport { exists, findFirst, getAttribute, getText } from '../util/XMLUtils';\n\nimport { handleStropheError } from './StropheErrorHandler';\n\n\nconst logger = getLogger('xmpp:Moderator');\n\n/**\n * Exponential backoff timer.\n * @param step the step to use.\n */\nfunction createExpBackoffTimer(step) {\n    let count = 1;\n    const maxTimeout = 120000;\n\n    return function(reset) {\n        // Reset call\n        if (reset) {\n            count = 1;\n\n            return;\n        }\n\n        // Calculate next timeout\n        const timeout = Math.pow(2, count - 1);\n\n        count += 1;\n\n        return Math.min(timeout * step, maxTimeout);\n    };\n}\n\n/**\n * The moderator/focus responsible for direct communication with jicofo\n */\nexport default class Moderator extends Listenable {\n    /**\n     * Constructs moderator.\n     * @param xmpp The xmpp.\n     */\n    constructor(xmpp) {\n        super();\n\n        this.getNextTimeout = createExpBackoffTimer(1000);\n        this.getNextErrorTimeout = createExpBackoffTimer(1000);\n        this.options = xmpp.options;\n\n        // Whether SIP gateway (jigasi) support is enabled. TODO: use presence so it can be changed based on jigasi\n        // availability.\n        this.sipGatewayEnabled = false;\n\n        // Response to conference request may contain whether visitors are supported\n        // in certain cases we need to know this to be able to get decisions on some errors (max-occupants reached)\n        this.visitorsSupported = false;\n\n        this.xmpp = xmpp;\n        this.connection = xmpp.connection;\n\n        // The JID to which conference-iq requests are sent over XMPP.\n        this.targetJid = this.options.hosts?.focus;\n\n        // If not specified default to 'focus.domain'\n        if (!this.targetJid) {\n            this.targetJid = `focus.${this.options.hosts?.domain}`;\n        }\n\n        this.targetUrl = this.options.conferenceRequestUrl;\n\n        // Whether to send conference requests over HTTP or XMPP\n        this.mode = this.targetUrl ? 'http' : 'xmpp';\n        logger.info(`Using ${this.mode} for conference requests.`);\n\n        // The set of JIDs known to belong to jicofo. Populated from configuration\n        // and responses from conference requests.\n        this.focusUserJids = new Set();\n\n        if (this.options.focusUserJid) {\n            this.focusUserJids.add(this.options.focusUserJid);\n        }\n\n        // FIXME: Message listener that talks to POPUP window\n        /**\n         *\n         * @param event\n         */\n        function listener(event) {\n            if (event.data && event.data.sessionId) {\n                if (event.origin !== window.location.origin) {\n                    logger.warn(`Ignoring sessionId from different origin: ${event.origin}`);\n\n                    return;\n                }\n                Settings.sessionId = event.data.sessionId;\n\n                // After popup is closed we will authenticate\n            }\n        }\n\n        // Register\n        window.addEventListener('message', listener, false);\n    }\n\n    /**\n     * Check whether the supplied jid is a known jid for focus.\n     * @param jid\n     * @returns {boolean}\n     */\n    isFocusJid(jid) {\n        if (!jid) {\n            return false;\n        }\n\n        for (const focusJid of this.focusUserJids) {\n            // jid may be a full JID, and focusUserJids may be bare JIDs\n            if (jid.indexOf(`${focusJid}/`) === 0) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    /**\n     * Is sip gw enabled.\n     * @returns {boolean}\n     */\n    isSipGatewayEnabled() {\n        return this.sipGatewayEnabled;\n    }\n\n    /**\n     * Create a conference request based on the configured options and saved Settings.\n     *\n     * A conference request has the following format:\n     * {\n     *   room: \"room@example.com\",\n     *   sessionId: \"foo\", // optional\n     *   machineUdi: \"bar\", // optional\n     *   identity: \"baz\", // optional\n     *   properties: { } // map string to string\n     * }\n     *\n     * It can be encoded in either JSON or and IQ.\n     *\n     * @param roomJid - The room jid for which to send conference request.\n     *\n     * @returns the created conference request.\n     */\n    _createConferenceRequest(roomJid) {\n        // Session Id used for authentication\n        const { sessionId } = Settings;\n        const config = this.options;\n        const properties = {};\n\n        if (config.startAudioMuted !== undefined) {\n            properties.startAudioMuted = config.startAudioMuted;\n        }\n        if (config.startVideoMuted !== undefined) {\n            properties.startVideoMuted = config.startVideoMuted;\n        }\n\n        // this flag determines whether the bridge will include this call in its\n        // rtcstats reporting or not. If the site admin hasn't set the flag in\n        // config.js, then the client defaults to false (see\n        // react/features/rtcstats/functions.js in jitsi-meet). The server-side\n        // components default to true to match the pre-existing behavior, so we only\n        // signal if false.\n        const rtcstatsEnabled = config?.analytics?.rtcstatsEnabled ?? false;\n\n        if (!rtcstatsEnabled) {\n            properties.rtcstatsEnabled = false;\n        }\n\n        const conferenceRequest = {\n            machineUid: Settings.machineId,\n            properties,\n            room: roomJid\n        };\n\n        if (sessionId) {\n            conferenceRequest.sessionId = sessionId;\n        }\n\n        if (!config.iAmRecorder && !config.iAmSipGateway) {\n            conferenceRequest.properties['visitors-version'] = 1;\n\n            if (this.options.preferVisitor) {\n                conferenceRequest.properties.visitor = true;\n            }\n        }\n\n        return conferenceRequest;\n    }\n\n    /**\n     * Create a conference request and encode it as an IQ.\n     *\n     * @param roomJid - The room jid for which to send conference request.\n     */\n    _createConferenceIq(roomJid) {\n        const conferenceRequest = this._createConferenceRequest(roomJid);\n\n        // Generate create conference IQ\n        const elem = $iq({\n            to: this.targetJid,\n            type: 'set'\n        });\n\n        elem.c('conference', {\n            'machine-uid': conferenceRequest.machineUid,\n            room: roomJid,\n            token: this.xmpp.token,\n            xmlns: 'http://jitsi.org/protocol/focus'\n        });\n\n        if (conferenceRequest.sessionId) {\n            elem.attrs({ 'session-id': conferenceRequest.sessionId });\n        }\n\n        for (const k in conferenceRequest.properties) {\n            if (conferenceRequest.properties.hasOwnProperty(k)) {\n                elem.c(\n                    'property', {\n                        name: k,\n                        value: conferenceRequest.properties[k]\n                    })\n                    .up();\n            }\n        }\n\n        return elem;\n    }\n\n    /**\n     * Parses a conference IQ.\n     * @param resultIq the result IQ that is received.\n     * @returns {{properties: {}}} Returns an object with the parsed properties.\n     * @private\n     */\n    _parseConferenceIq(resultIq) {\n        const conferenceRequest = { properties: {} };\n\n        const conferenceEl = findFirst(resultIq, 'conference');\n\n        conferenceRequest.focusJid = getAttribute(conferenceEl, 'focusjid');\n        conferenceRequest.sessionId = getAttribute(conferenceEl, 'session-id');\n        conferenceRequest.identity = getAttribute(conferenceEl, 'identity');\n        conferenceRequest.ready = getAttribute(conferenceEl, 'ready') === 'true';\n        conferenceRequest.vnode = getAttribute(conferenceEl, 'vnode');\n\n        if (exists(resultIq, ':scope>conference>property[name=\"authentication\"][value=\"true\"]')) {\n            conferenceRequest.properties.authentication = 'true';\n        }\n\n        if (exists(resultIq, ':scope>conference>property[name=\"externalAuth\"][value=\"true\"]')) {\n            conferenceRequest.properties.externalAuth = 'true';\n        }\n\n        // Check if jicofo has jigasi support enabled.\n        if (exists(resultIq, ':scope>conference>property[name=\"sipGatewayEnabled\"][value=\"true\"]')) {\n            conferenceRequest.properties.sipGatewayEnabled = 'true';\n        }\n\n        // check for explicit false, all other cases is considered live\n        if (exists(resultIq, ':scope>conference>property[name=\"live\"][value=\"false\"]')) {\n            conferenceRequest.properties.live = 'false';\n        }\n\n        return conferenceRequest;\n    }\n\n    // FIXME We need to show the fact that we're waiting for the focus to the user\n    // (or that the focus is not available)\n    /**\n     * Allocates the conference focus.\n     * @param roomJid - The room jid for which to send conference request.\n     * @returns {Promise} - Resolved when Jicofo allows to join the room. It's never\n     * rejected, and it'll keep on pinging Jicofo forever.\n     */\n    sendConferenceRequest(roomJid) {\n        // there is no point of sending conference iq when in visitor mode (disableFocus)\n        // when we have sent early the conference request via http\n        // we want to skip sending it here, or visitors can loop\n        if (this.conferenceRequestSent) {\n            return Promise.resolve();\n        }\n\n        // to mark whether we have already sent a conference request\n        this.conferenceRequestSent = false;\n\n        return new Promise((resolve, reject) => {\n            if (this.mode === 'xmpp') {\n                logger.info(`Sending conference request over XMPP to ${this.targetJid}`);\n\n                this.connection.sendIQ(\n                    this._createConferenceIq(roomJid),\n                    result => this._handleIqSuccess(roomJid, result, resolve, reject),\n                    error => this._handleIqError(roomJid, error, resolve, reject));\n\n                // XXX We're pressed for time here because we're beginning a complex\n                // and/or lengthy conference-establishment process which supposedly\n                // involves multiple RTTs. We don't have the time to wait for Strophe to\n                // decide to send our IQ.\n                this.connection.flush();\n            } else {\n                logger.info(`Sending conference request over HTTP to ${this.targetUrl}`);\n                fetch(this.targetUrl, {\n                    body: JSON.stringify(this._createConferenceRequest(roomJid)),\n                    headers: {\n                        'Content-Type': 'application/json',\n                        ...this.xmpp.token ? { 'Authorization': `Bearer ${this.xmpp.token}` } : {}\n                    },\n                    method: 'POST'\n                })\n                    .then(response => {\n                        if (!response.ok) {\n                            response.text()\n                                .then(text => {\n                                    logger.warn(`Received HTTP ${response.status} ${\n                                        response.statusText}. Body: ${text}`);\n                                    const sessionError = response.status === 400\n                                        && text.indexOf('400 invalid-session') > 0;\n                                    const notAuthorized = response.status === 403;\n\n                                    this._handleError(roomJid, sessionError, notAuthorized, resolve, reject);\n                                })\n                                .catch(error => {\n                                    logger.warn(`Error: ${error}`);\n                                    this._handleError(roomJid, undefined, undefined, resolve, () => reject(error));\n                                });\n\n                            // _handleError has either scheduled a retry or fired an event indicating failure.\n                            return;\n                        }\n                        response.json()\n                            .then(resultJson => {\n                                this._handleSuccess(roomJid, resultJson, resolve, reject);\n                            });\n                    })\n                    .catch(error => {\n                        logger.warn(`Error: ${error}`);\n                        this._handleError(roomJid, undefined, undefined, resolve, () => reject(error));\n                    });\n            }\n        }).then(() => {\n            this.conferenceRequestSent = true;\n        })\n        .finally(() => {\n            this.xmpp.connection._breakoutMovingToMain = undefined;\n        });\n    }\n\n    /**\n     * Handles success response for conference IQ.\n     * @param roomJid\n     * @param conferenceRequest\n     * @param callback\n     * @param errorCallback\n     * @private\n     */\n    _handleSuccess(roomJid, conferenceRequest, callback, errorCallback) {\n        // Reset the error timeout (because we haven't failed here).\n        this.getNextErrorTimeout(true);\n\n        if (conferenceRequest.focusJid) {\n            logger.info(`Adding focus JID: ${conferenceRequest.focusJid}`);\n            this.focusUserJids.add(conferenceRequest.focusJid);\n        } else {\n            logger.warn('Conference request response contained no focusJid.');\n        }\n\n        const authenticationEnabled = conferenceRequest.properties.authentication === 'true';\n\n        logger.info(`Authentication enabled: ${authenticationEnabled}`);\n\n        if (conferenceRequest.sessionId) {\n            logger.info(`Received sessionId: ${conferenceRequest.sessionId}`);\n            Settings.sessionId = conferenceRequest.sessionId;\n        }\n\n        this.eventEmitter.emit(\n            AuthenticationEvents.IDENTITY_UPDATED, authenticationEnabled, conferenceRequest.identity);\n\n        this.sipGatewayEnabled = conferenceRequest.properties.sipGatewayEnabled;\n        logger.info(`Sip gateway enabled: ${this.sipGatewayEnabled}`);\n\n        if (conferenceRequest.properties.live === 'false') {\n            this.getNextTimeout(true);\n\n            logger.info('Conference is not live.');\n\n            this.xmpp.eventEmitter.emit(CONNECTION_FAILED, NOT_LIVE_ERROR);\n\n            errorCallback();\n\n            return;\n        }\n\n        this.visitorsSupported = conferenceRequest.properties['visitors-supported'];\n\n        if (conferenceRequest.ready) {\n            // Reset the non-error timeout (because we've succeeded here).\n            this.getNextTimeout(true);\n\n            // we want to ignore redirects when this is jibri (record/live-stream or a sip jibri)\n            // we ignore redirects when moving from a breakout room to the main room\n            if (conferenceRequest.vnode && !this.options.iAmRecorder && !this.options.iAmSipGateway) {\n                if (this.connection._breakoutMovingToMain === roomJid) {\n                    logger.info('Skipping redirect as we are moving from breakout to main.');\n\n                    callback();\n\n                    return;\n                }\n\n                logger.warn(`Redirected to: ${conferenceRequest.vnode} with focusJid ${conferenceRequest.focusJid}`);\n\n                this.xmpp.eventEmitter.emit(CONNECTION_REDIRECTED, conferenceRequest.vnode, conferenceRequest.focusJid);\n\n                errorCallback();\n\n                return;\n            }\n\n            logger.info('Conference-request successful, ready to join the MUC.');\n            callback();\n        } else {\n            const waitMs = this.getNextTimeout();\n\n            // This was a successful response, but the \"ready\" flag is not set. Retry after a timeout.\n            logger.info(`Not ready yet, will retry in ${waitMs} ms.`);\n            window.setTimeout(\n                () => this.sendConferenceRequest(roomJid)\n                    .then(callback).catch(errorCallback),\n                waitMs);\n        }\n    }\n\n    /**\n     * Handles error response for conference IQ.\n     * @param roomJid\n     * @param sessionError\n     * @param notAuthorized\n     * @param callback\n     * @param errorCallback\n     * @private\n     */\n    _handleError(roomJid, sessionError, notAuthorized, callback, errorCallback) { // eslint-disable-line max-params\n        // If the session is invalid, remove and try again without session ID to get\n        // a new one\n        if (sessionError) {\n            logger.info('Session expired! - removing');\n            Settings.sessionId = undefined;\n        }\n\n        // Not authorized to create new room\n        if (notAuthorized) {\n            logger.warn('Unauthorized to start the conference');\n            this.eventEmitter.emit(XMPPEvents.AUTHENTICATION_REQUIRED);\n\n            errorCallback();\n\n            return;\n        }\n\n        const waitMs = this.getNextErrorTimeout();\n\n        if (sessionError && waitMs < 60000) {\n            // If the session is invalid, retry a limited number of times and then fire an error.\n            logger.info(`Invalid session, will retry after ${waitMs} ms.`);\n            this.getNextTimeout(true);\n            window.setTimeout(() => this.sendConferenceRequest(roomJid)\n                .then(callback)\n                .catch(errorCallback), waitMs);\n        } else {\n            logger.error('Failed to get a successful response, giving up.');\n\n            // This is a \"fatal\" error and the user of the lib should handle it accordingly.\n            this.xmpp.eventEmitter.emit(CONNECTION_FAILED, CONFERENCE_REQUEST_FAILED);\n\n            errorCallback();\n        }\n    }\n\n    /**\n     * Invoked by {@link #sendConferenceRequest} upon its request receiving an xmpp error result.\n     *\n     * @param roomJid - The room jid used to send conference request.\n     * @param error - the error result of the request that {@link sendConferenceRequest} sent\n     * @param {Function} callback - the function to be called back upon the\n     * successful allocation of the conference focus\n     * @param errorCallback\n     */\n    _handleIqError(roomJid, error, callback, errorCallback) {\n        // Call handleStropheError for centralized error logging and analytics\n        handleStropheError(error, {\n            mode: this.mode,\n            operation: 'conference request (IQ)',\n            roomJid,\n            targetJid: this.targetJid,\n            userJid: this.connection.jid\n        });\n\n        // The reservation system only works over XMPP. Handle the error separately.\n        // Check for error returned by the reservation system\n        // Convert Strophe object to DOM element for XMLUtils functions\n        const reservationErr = findFirst(error, ':scope>error>reservation-error');\n\n        if (reservationErr) {\n            // Trigger error event\n            const errorCode = getAttribute(reservationErr, 'error-code');\n            const errorTextNode = findFirst(error, ':scope>error>text');\n            let errorMsg;\n\n            if (errorTextNode) {\n                errorMsg = getText(errorTextNode);\n            }\n            this.eventEmitter.emit(\n                XMPPEvents.RESERVATION_ERROR,\n                errorCode,\n                errorMsg);\n\n            errorCallback();\n\n            return;\n        }\n\n        const invalidSession = Boolean(\n            exists(error, ':scope>error>session-invalid') || exists(error, ':scope>error>not-acceptable'));\n\n        // Not authorized to create new room\n        const notAuthorized = exists(error, ':scope>error>not-authorized');\n\n        this._handleError(roomJid, invalidSession, notAuthorized, callback, errorCallback);\n    }\n\n    /**\n     * Invoked by {@link #sendConferenecRequest} upon its request receiving a\n     * success (i.e. non-error) result.\n     *\n     * @param roomJid - The room jid used to send conference request.\n     * @param result - the success (i.e. non-error) result of the request that {@link #sendConferenecRequest} sent\n     * @param {Function} callback - the function to be called back upon the\n     * successful allocation of the conference focus\n     * @param errorCallback\n     */\n    _handleIqSuccess(roomJid, result, callback, errorCallback) {\n        // Setup config options\n        const conferenceRequest = this._parseConferenceIq(result);\n\n        this._handleSuccess(roomJid, conferenceRequest, callback, errorCallback);\n    }\n\n    /**\n     * Authenticate by sending a conference IQ.\n     * @param roomJid The room jid.\n     * @returns {Promise<unknown>}\n     */\n    authenticate(roomJid) {\n        return new Promise((resolve, reject) => {\n            this.connection.sendIQ(\n                this._createConferenceIq(roomJid),\n                result => {\n                    const sessionId = getAttribute(findFirst(result, 'conference'), 'session-id');\n\n                    if (sessionId) {\n                        logger.info(`Received sessionId:  ${sessionId}`);\n                        Settings.sessionId = sessionId;\n                    } else {\n                        logger.warn('Response did not contain a session-id');\n                    }\n\n                    resolve();\n                },\n                errorIq => {\n                    handleStropheError(errorIq, {\n                        operation: 'authenticate conference',\n                        roomJid,\n                        targetJid: this.targetJid,\n                        userJid: this.connection.jid\n                    });\n\n                    const errorEl = findFirst(errorIq, ':scope>iq>error');\n                    const firstErrorChild = errorEl?.children?.length > 0 ? errorEl.children[0] : undefined;\n\n                    reject({\n                        error: firstErrorChild?.tagName,\n                        message: getText(findFirst(errorIq, ':scope>iq>error>text'))\n                    });\n                }\n            );\n        });\n    }\n\n    /**\n     * Logout by sending conference IQ.\n     * @param callback\n     */\n    logout(callback) {\n        const iq = $iq({\n            to: this.targetJid,\n            type: 'set'\n        });\n        const { sessionId } = Settings;\n\n        if (!sessionId) {\n            callback();\n\n            return;\n        }\n        iq.c('logout', {\n            'session-id': sessionId,\n            xmlns: 'http://jitsi.org/protocol/focus'\n        });\n        this.connection.sendIQ(\n            iq,\n            result => {\n                logger.info('Log out OK', result);\n                Settings.sessionId = undefined;\n                callback();\n            },\n            error => {\n                handleStropheError(error, {\n                    operation: 'logout',\n                    sessionId,\n                    targetJid: this.targetJid,\n                    userJid: this.connection.jid\n                });\n            }\n        );\n    }\n}\n","/* eslint-disable */\n\nimport { $iq, Strophe } from 'strophe.js';\nimport { handleStropheError } from './StropheErrorHandler';\n\nStrophe.addConnectionPlugin('disco',\n{\n    _connection: null,\n    _identities : [],\n    _features : [],\n    _items : [],\n    /** Function: init\n     * Plugin init\n     *\n     * Parameters:\n     *   (Strophe.Connection) conn - Strophe connection\n     */\n    init: function(conn)\n    {\n    this._connection = conn;\n        this._identities = [];\n        this._features   = [];\n        this._items      = [];\n        // disco info\n        conn.addHandler(this._onDiscoInfo.bind(this), Strophe.NS.DISCO_INFO, 'iq', 'get', null, null);\n        // disco items\n        conn.addHandler(this._onDiscoItems.bind(this), Strophe.NS.DISCO_ITEMS, 'iq', 'get', null, null);\n    },\n    /** Function: addIdentity\n     * See http://xmpp.org/registrar/disco-categories.html\n     * Parameters:\n     *   (String) category - category of identity (like client, automation, etc ...)\n     *   (String) type - type of identity (like pc, web, bot , etc ...)\n     *   (String) name - name of identity in natural language\n     *   (String) lang - lang of name parameter\n     *\n     * Returns:\n     *   Boolean\n     */\n    addIdentity: function(category, type, name, lang)\n    {\n        if (typeof name === 'undefined') {\n           name = '';\n        }\n        if (typeof lang === 'undefined') {\n           lang = '';\n        }\n        for (var i=0; i<this._identities.length; i++)\n        {\n            if (this._identities[i].category == category &&\n                this._identities[i].type == type &&\n                this._identities[i].name == name &&\n                this._identities[i].lang == lang)\n            {\n                return false;\n            }\n        }\n        this._identities.push({category: category, type: type, name: name, lang: lang});\n        return true;\n    },\n    /** Function: addFeature\n     *\n     * Parameters:\n     *   (String) var_name - feature name (like jabber:iq:version)\n     *\n     * Returns:\n     *   boolean\n     */\n    addFeature: function(var_name)\n    {\n        for (var i=0; i<this._features.length; i++)\n        {\n             if (this._features[i] == var_name)\n                 return false;\n        }\n        this._features.push(var_name);\n        return true;\n    },\n    /** Function: removeFeature\n     *\n     * Parameters:\n     *   (String) var_name - feature name (like jabber:iq:version)\n     *\n     * Returns:\n     *   boolean\n     */\n    removeFeature: function(var_name)\n    {\n        for (var i=0; i<this._features.length; i++)\n        {\n             if (this._features[i] === var_name){\n                 this._features.splice(i,1);\n                 return true;\n             }\n        }\n        return false;\n    },\n    /** Function: addItem\n     *\n     * Parameters:\n     *   (String) jid\n     *   (String) name\n     *   (String) node\n     *   (Function) call_back\n     *\n     * Returns:\n     *   boolean\n     */\n    addItem: function(jid, name, node, call_back)\n    {\n        if (node && !call_back)\n            return false;\n        this._items.push({jid: jid, name: name, node: node, call_back: call_back});\n        return true;\n    },\n    /** Function: info\n     * Info query\n     *\n     * Parameters:\n     *   (Function) call_back\n     *   (String) jid\n     *   (String) node\n     */\n    info: function(jid, node, success, error, timeout)\n    {\n        var attrs = {xmlns: Strophe.NS.DISCO_INFO};\n        if (node)\n            attrs.node = node;\n\n        var info = $iq({from:this._connection.jid,\n                         to:jid, type:'get'}).c('query', attrs);\n        this._connection.sendIQ(info, success, error ? err => {\n            handleStropheError(err, {\n                jid,\n                node,\n                operation: 'disco info query',\n                userJid: this._connection.jid\n            });\n            error(err);\n        } : undefined, timeout);\n    },\n    /** Function: items\n     * Items query\n     *\n     * Parameters:\n     *   (Function) call_back\n     *   (String) jid\n     *   (String) node\n     */\n    items: function(jid, node, success, error, timeout)\n    {\n        var attrs = {xmlns: Strophe.NS.DISCO_ITEMS};\n        if (node)\n            attrs.node = node;\n\n        var items = $iq({from:this._connection.jid,\n                         to:jid, type:'get'}).c('query', attrs);\n        this._connection.sendIQ(items, success, error ? err => {\n            handleStropheError(err, {\n                jid,\n                node,\n                operation: 'disco items query',\n                userJid: this._connection.jid\n            });\n            error(err);\n        } : undefined, timeout);\n    },\n\n    /** PrivateFunction: _buildIQResult\n     */\n    _buildIQResult: function(stanza, query_attrs)\n    {\n        var id   =  stanza.getAttribute('id');\n        var from = stanza.getAttribute('from');\n        var iqresult = $iq({type: 'result', id: id});\n\n        if (from !== null) {\n            iqresult.attrs({to: from});\n        }\n\n        return iqresult.c('query', query_attrs);\n    },\n\n    /** PrivateFunction: _onDiscoInfo\n     * Called when receive info request\n     */\n    _onDiscoInfo: function(stanza)\n    {\n        var node = stanza.getElementsByTagName('query')[0].getAttribute('node');\n        var attrs = {xmlns: Strophe.NS.DISCO_INFO};\n        var i;\n        if (node)\n        {\n            attrs.node = node;\n        }\n        var iqresult = this._buildIQResult(stanza, attrs);\n        for (i=0; i<this._identities.length; i++)\n        {\n            attrs = {category: this._identities[i].category,\n                         type    : this._identities[i].type};\n            if (this._identities[i].name)\n                attrs.name = this._identities[i].name;\n            if (this._identities[i].lang)\n                attrs['xml:lang'] = this._identities[i].lang;\n            iqresult.c('identity', attrs).up();\n        }\n        for (i=0; i<this._features.length; i++)\n        {\n            iqresult.c('feature', {'var':this._features[i]}).up();\n        }\n        this._connection.send(iqresult.tree());\n        return true;\n    },\n    /** PrivateFunction: _onDiscoItems\n     * Called when receive items request\n     */\n    _onDiscoItems: function(stanza)\n    {\n        var query_attrs = {xmlns: Strophe.NS.DISCO_ITEMS};\n        var node = stanza.getElementsByTagName('query')[0].getAttribute('node');\n        var items, i;\n        if (node)\n        {\n            query_attrs.node = node;\n            items = [];\n            for (i = 0; i < this._items.length; i++)\n            {\n                if (this._items[i].node == node)\n                {\n                    items = this._items[i].call_back(stanza);\n                    break;\n                }\n            }\n        }\n        else\n        {\n            items = this._items;\n        }\n        var iqresult = this._buildIQResult(stanza, query_attrs);\n        for (i = 0; i < items.length; i++)\n        {\n            var attrs = {jid:  items[i].jid};\n            if (items[i].name)\n                attrs.name = items[i].name;\n            if (items[i].node)\n                attrs.node = items[i].node;\n            iqresult.c('item', attrs).up();\n        }\n        this._connection.send(iqresult.tree());\n        return true;\n    }\n});\n","export enum JitsiTranscriptionStatus {\n\n    /**\n     * The transcription is off.\n     */\n    OFF = 'OFF',\n\n    /**\n     * The transcription is on.\n     */\n    ON = 'ON'\n}\n\n// exported for backward compatibility\nexport const ON = JitsiTranscriptionStatus.ON;\nexport const OFF = JitsiTranscriptionStatus.OFF;\n","import { getLogger } from '@jitsi/logger';\nimport { $msg } from 'strophe.js';\n\nimport { MediaType } from '../../service/RTC/MediaType';\nimport { XMPPEvents } from '../../service/xmpp/XMPPEvents';\n\nimport ChatRoom from './ChatRoom';\nimport XMPP from './xmpp';\n\nconst logger = getLogger('xmpp:AVModeration');\n\nexport interface IModerationEnabledByType {\n    audio: boolean;\n    desktop: boolean;\n    video: boolean;\n}\n\nexport interface IMessageObject {\n    actor: string;\n    approved: boolean;\n    enabled: boolean;\n    mediaType: MediaType;\n    removed: boolean;\n    whitelists: { audio: string[]; video: string[]; };\n}\n\n/**\n * The AVModeration logic.\n */\nexport default class AVModeration {\n    private _xmpp: XMPP;\n    private _mainRoom: ChatRoom;\n    private _moderationEnabledByType: IModerationEnabledByType;\n    private _whitelistAudio: string[];\n    private _whitelistDesktop: string[];\n    private _whitelistVideo: string[];\n\n    /**\n     * Constructs AV moderation room.\n     *\n     * @param {ChatRoom} room the main room.\n     */\n    constructor(room: ChatRoom) {\n        this._xmpp = room.xmpp;\n\n        this._mainRoom = room;\n\n        this._moderationEnabledByType = {\n            [MediaType.AUDIO]: false,\n            [MediaType.DESKTOP]: false,\n            [MediaType.VIDEO]: false\n        };\n\n        this._whitelistAudio = [];\n        this._whitelistDesktop = [];\n        this._whitelistVideo = [];\n\n        this._onMessage = this._onMessage.bind(this);\n        this._xmpp.addListener(XMPPEvents.AV_MODERATION_RECEIVED, this._onMessage);\n    }\n\n    /**\n     * Stops listening for events.\n     */\n    dispose() {\n        this._xmpp.removeListener(XMPPEvents.AV_MODERATION_RECEIVED, this._onMessage);\n    }\n\n    /**\n     * Whether AV moderation is supported on backend.\n     *\n     * @returns {boolean} whether AV moderation is supported on backend.\n     */\n    isSupported() {\n        return Boolean(this._xmpp.avModerationComponentAddress);\n    }\n\n    /**\n     * Enables or disables AV Moderation by sending a msg with command to the component.\n     */\n    enable(state: boolean, mediaType: MediaType) {\n        if (!this.isSupported() || !this._mainRoom.isModerator()) {\n            logger.error(`Cannot enable:${state} AV moderation supported:${this.isSupported()},\n                moderator:${this._mainRoom.isModerator()}`);\n\n            return;\n        }\n\n        if (state === this._moderationEnabledByType[mediaType]) {\n            logger.warn(`Moderation already in state:${state} for mediaType:${mediaType}`);\n\n            return;\n        }\n\n        // send the enable/disable message\n        const msg = $msg({ to: this._xmpp.avModerationComponentAddress });\n\n        msg.c('av_moderation', {\n            enable: state,\n            mediaType\n        }).up();\n\n        this._xmpp.connection.send(msg);\n    }\n\n    /**\n     * Approves that a participant can unmute by sending a msg with its jid to the component.\n     */\n    approve(mediaType: MediaType, jid: string) {\n        if (!this.isSupported() || !this._mainRoom.isModerator()) {\n            logger.error(`Cannot approve in AV moderation supported:${this.isSupported()},\n                moderator:${this._mainRoom.isModerator()}`);\n\n            return;\n        }\n\n        // send a message to whitelist the jid and approve it to unmute\n        const msg = $msg({ to: this._xmpp.avModerationComponentAddress });\n\n        msg.c('av_moderation', {\n            jidToWhitelist: jid,\n            mediaType\n        }).up();\n\n        this._xmpp.connection.send(msg);\n    }\n\n    /**\n     * Rejects that a participant can unmute by sending a msg with its jid to the component.\n     */\n    reject(mediaType: MediaType, jid: string) {\n        if (!this.isSupported() || !this._mainRoom.isModerator()) {\n            logger.error(`Cannot reject in AV moderation supported:${this.isSupported()},\n                moderator:${this._mainRoom.isModerator()}`);\n\n            return;\n        }\n\n        // send a message to remove from whitelist the jid and reject it to unmute\n        const msg = $msg({ to: this._xmpp.avModerationComponentAddress });\n\n        msg.c('av_moderation', {\n            jidToBlacklist: jid,\n            mediaType\n        }).up();\n\n        this._xmpp.connection.send(msg);\n    }\n\n    /**\n     * Receives av_moderation parsed messages as json.\n     * @param obj the parsed json content of the message to process.\n     * @private\n     */\n    _onMessage(obj: IMessageObject) {\n        const { removed, mediaType: media, enabled, approved, actor, whitelists: newWhitelists } = obj;\n\n        if (newWhitelists) {\n            let oldList;\n\n            switch (media) {\n            case MediaType.AUDIO:\n                oldList = this._whitelistAudio;\n                break;\n            case MediaType.DESKTOP:\n                oldList = this._whitelistDesktop;\n                break;\n            case MediaType.VIDEO:\n                oldList = this._whitelistVideo;\n                break;\n            default:\n                logger.error(`Unknown media type: ${media}`);\n\n                return;\n            }\n            const newList = Array.isArray(newWhitelists[media]) ? newWhitelists[media] : [];\n\n            if (removed) {\n                oldList.filter(x => !newList.includes(x))\n                    .forEach(jid => this._xmpp.eventEmitter\n                        .emit(XMPPEvents.AV_MODERATION_PARTICIPANT_REJECTED, media, jid));\n            } else {\n                newList.filter(x => !oldList.includes(x))\n                    .forEach(jid => this._xmpp.eventEmitter\n                        .emit(XMPPEvents.AV_MODERATION_PARTICIPANT_APPROVED, media, jid));\n            }\n\n            switch (media) {\n            case MediaType.AUDIO:\n                this._whitelistAudio = newList;\n                break;\n            case MediaType.DESKTOP:\n                this._whitelistDesktop = newList;\n                break;\n            case MediaType.VIDEO:\n                this._whitelistVideo = newList;\n                break;\n            }\n        } else if (enabled !== undefined && this._moderationEnabledByType[media] !== enabled) {\n            this._moderationEnabledByType[media] = enabled;\n\n            this._xmpp.eventEmitter.emit(XMPPEvents.AV_MODERATION_CHANGED, enabled, media, actor);\n        } else if (removed) {\n            this._xmpp.eventEmitter.emit(XMPPEvents.AV_MODERATION_REJECTED, media);\n        } else if (approved) {\n            this._xmpp.eventEmitter.emit(XMPPEvents.AV_MODERATION_APPROVED, media);\n        }\n    }\n}\n","import { getLogger } from '@jitsi/logger';\nimport { $msg, Strophe } from 'strophe.js';\n\nimport { XMPPEvents } from '../../service/xmpp/XMPPEvents';\n\nconst FEATURE_KEY = 'features/breakout-rooms';\nconst BREAKOUT_ROOM_ACTIONS = {\n    ADD: `${FEATURE_KEY}/add`,\n    MOVE_TO_ROOM: `${FEATURE_KEY}/move-to-room`,\n    REMOVE: `${FEATURE_KEY}/remove`,\n    RENAME: `${FEATURE_KEY}/rename`\n};\nconst BREAKOUT_ROOM_EVENTS = {\n    MOVE_TO_ROOM: `${FEATURE_KEY}/move-to-room`,\n    UPDATE: `${FEATURE_KEY}/update`\n};\n\nconst logger = getLogger('xmpp:BreakoutRooms');\n\n/**\n * Helper class for handling breakout rooms.\n */\nexport default class BreakoutRooms {\n\n    /**\n     * Constructs breakout room.\n     *\n     * @param {ChatRoom} room the room we are in.\n     */\n    constructor(room) {\n        this.room = room;\n\n        this._handleMessages = this._handleMessages.bind(this);\n        this.room.xmpp.addListener(XMPPEvents.BREAKOUT_ROOMS_EVENT, this._handleMessages);\n\n        this._rooms = {};\n    }\n\n    /**\n     * Stops listening for events.\n     */\n    dispose() {\n        this.room.xmpp.removeListener(XMPPEvents.BREAKOUT_ROOMS_EVENT, this._handleMessages);\n    }\n\n    /**\n     * Creates a breakout room with the given subject.\n     *\n     * @param {string} subject - A subject for the breakout room.\n     */\n    createBreakoutRoom(subject) {\n        if (!this.isSupported() || !this.room.isModerator()) {\n            logger.error(`Cannot create breakout room - supported:${this.isSupported()},\n                moderator:${this.room.isModerator()}`);\n\n            return;\n        }\n\n        logger.debug('Create breakout room');\n\n        const message = {\n            subject,\n            type: BREAKOUT_ROOM_ACTIONS.ADD\n        };\n\n        this._sendMessage(message);\n    }\n\n    /**\n     * Removes a breakout room.\n     *\n     * @param {string} breakoutRoomJid - JID of the room to be removed.\n     */\n    removeBreakoutRoom(breakoutRoomJid) {\n        if (!this.isSupported() || !this.room.isModerator()) {\n            logger.error(`Cannot remove breakout room - supported:${this.isSupported()},\n                moderator:${this.room.isModerator()}`);\n\n            return;\n        }\n\n        logger.debug(`Remove breakout room: ${breakoutRoomJid}`);\n\n        const message = {\n            breakoutRoomJid,\n            type: BREAKOUT_ROOM_ACTIONS.REMOVE\n        };\n\n        this._sendMessage(message);\n    }\n\n    /**\n     * Changes the subject of a breakout room.\n     *\n     * @param {string} breakoutRoomJid - JID of the room to be removed.\n     * @param {string} subject - A new subject for the breakout room.\n     */\n    renameBreakoutRoom(breakoutRoomJid, subject) {\n        if (!this.isSupported() || !this.room.isModerator()) {\n            logger.error(`Cannot rename breakout room - supported:${this.isSupported()},\n                moderator:${this.room.isModerator()}`);\n\n            return;\n        }\n\n        logger.debug(`Rename breakout room: ${breakoutRoomJid}`);\n\n        const message = {\n            breakoutRoomJid,\n            subject,\n            type: BREAKOUT_ROOM_ACTIONS.RENAME\n\n        };\n\n        this._sendMessage(message);\n    }\n\n    /**\n     * Sends the given participant to the given room.\n     *\n     * @param {string} participantJid - JID of the participant to be sent to a room.\n     * @param {string} roomJid - JID of the target room.\n     */\n    sendParticipantToRoom(participantJid, roomJid) {\n        if (!this.isSupported() || !this.room.isModerator()) {\n            logger.error(`Cannot send participant to room - supported:${this.isSupported()},\n                moderator:${this.room.isModerator()}`);\n\n            return;\n        }\n\n        logger.debug(`Send participant: ${participantJid} to room: ${roomJid}`);\n\n        const message = {\n            participantJid,\n            roomJid,\n            type: BREAKOUT_ROOM_ACTIONS.MOVE_TO_ROOM\n        };\n\n        this._sendMessage(message);\n    }\n\n    /**\n     * Retrieves whether a breakout room feature is supported.\n     *\n     * @param {string} feature - Feature to check.\n     * @returns Wether the feature is supported.\n     */\n    isFeatureSupported(feature) {\n        return Boolean((this.room.xmpp.breakoutRoomsFeatures || {})[feature]);\n    }\n\n    /**\n     * Whether Breakout Rooms support is enabled in the backend or not.\n     */\n    isSupported() {\n        return Boolean(this.getComponentAddress());\n    }\n\n    /**\n     * Gets the address of the Breakout Rooms XMPP component.\n     *\n     * @returns The address of the component.\n     */\n    getComponentAddress() {\n        return this.room.xmpp.breakoutRoomsComponentAddress;\n    }\n\n    /**\n     * Stores if the current room is a breakout room.\n     *\n     * @param {boolean} isBreakoutRoom - Whether this room is a breakout room.\n     */\n    _setIsBreakoutRoom(isBreakoutRoom) {\n        this._isBreakoutRoom = isBreakoutRoom;\n    }\n\n    /**\n     * Checks whether this room is a breakout room.\n     *\n     * @returns True if the room is a breakout room, false otherwise.\n     */\n    isBreakoutRoom() {\n        if (typeof this._isBreakoutRoom !== 'undefined') {\n            return this._isBreakoutRoom;\n        }\n\n        // Use heuristic, helpful for checking in the MUC_JOINED event.\n        return Strophe.getDomainFromJid(this.room.myroomjid) === this.getComponentAddress();\n    }\n\n    /**\n     * Sets the main room JID associated with this breakout room. Only applies when\n     * in a breakout room.\n     *\n     * @param {string} jid - The main room JID.\n     */\n    _setMainRoomJid(jid) {\n        this._mainRoomJid = jid;\n    }\n\n    /**\n     * Gets the main room's JID associated with this breakout room.\n     *\n     * @returns The main room JID.\n     */\n    getMainRoomJid() {\n        return this._mainRoomJid;\n    }\n\n    /**\n     * Handles a message for managing breakout rooms.\n     *\n     * @param {object} payload - Arbitrary data.\n     */\n    _handleMessages(payload) {\n        switch (payload.event) {\n        case BREAKOUT_ROOM_EVENTS.MOVE_TO_ROOM:\n            this.room.eventEmitter.emit(XMPPEvents.BREAKOUT_ROOMS_MOVE_TO_ROOM, payload.roomJid);\n            break;\n        case BREAKOUT_ROOM_EVENTS.UPDATE: {\n            const filteredPayload = this._filterUpdatePayload(payload);\n\n            this._rooms = filteredPayload.rooms;\n            this.room.eventEmitter.emit(XMPPEvents.BREAKOUT_ROOMS_UPDATED, filteredPayload);\n            break;\n        }\n        }\n    }\n\n    /**\n     * Filters the hidden participants from the payload.\n     *\n     * @param {Object} payload - The payload of the update message.\n     * @return {Object} - The filtered payload.\n     */\n    _filterUpdatePayload(payload) {\n        const hiddenDomain = this.room.options.hiddenDomain;\n        const { rooms } = payload;\n        const filteredRooms = {};\n\n        Object.entries(rooms).forEach(([ key, room ]) => {\n            const { participants = {} } = room;\n            const filteredParticipants = {};\n\n            Object.entries(participants).forEach(([ k, participant ]) => {\n                if (Strophe.getDomainFromJid(participant.jid) !== hiddenDomain) {\n                    filteredParticipants[k] = participant;\n                }\n            });\n\n            filteredRooms[key] = {\n                ...room,\n                participants: filteredParticipants\n            };\n        });\n\n        return {\n            ...payload,\n            rooms: filteredRooms\n        };\n    }\n\n    /**\n     * Helper to send a breakout rooms message to the component.\n     *\n     * @param {Object} message - Command that needs to be sent.\n     */\n    _sendMessage(message) {\n        const msg = $msg({ to: this.getComponentAddress() });\n\n        msg.c('breakout_rooms', message).up();\n\n        this.room.xmpp.connection.send(msg);\n    }\n}\n",null,null,null,null,"var l=\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\",y=\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_\",b=r=>{let t=typeof Uint8Array>\"u\"?[]:new Uint8Array(256),o=l.length;for(let e=0;e<o;e++)t[r.charCodeAt(e)]=e;return t},m=b(l),p=b(y),w=/^[-A-Za-z0-9\\-_]*$/,B=/^[-A-Za-z0-9+/]*={0,3}$/;function h(r,t){let o=r.length,e=r.length*.75,n,f=0,s,i,a,g;r[r.length-1]===\"=\"&&(e--,r[r.length-2]===\"=\"&&e--);let A=new ArrayBuffer(e),u=new Uint8Array(A),c=t?p:m;for(n=0;n<o;n+=4)s=c[r.charCodeAt(n)],i=c[r.charCodeAt(n+1)],a=c[r.charCodeAt(n+2)],g=c[r.charCodeAt(n+3)],u[f++]=s<<2|i>>4,u[f++]=(i&15)<<4|a>>2,u[f++]=(a&3)<<6|g&63;return A}function U(r,t){let o=new Uint8Array(r),e,n=\"\",f=o.length,s=t?y:l;for(e=0;e<f;e+=3)n+=s[o[e]>>2],n+=s[(o[e]&3)<<4|o[e+1]>>4],n+=s[(o[e+1]&15)<<2|o[e+2]>>6],n+=s[o[e+2]&63];let i=f%3;return i===2?n=n.substring(0,n.length-1)+(t?\"\":\"=\"):i===1&&(n=n.substring(0,n.length-2)+(t?\"\":\"==\")),n}function d(r,t){return new TextDecoder().decode(h(r,t))}function k(r,t){return U(new TextEncoder().encode(r),t)}function C(r,t){if(!(typeof r==\"string\"||r instanceof String))return!1;try{return t?w.test(r):B.test(r)}catch{return!1}}var S={toString:d,fromString:k,toArrayBuffer:h,fromArrayBuffer:U,validate:C};export{S as base64,U as fromArrayBuffer,k as fromString,h as toArrayBuffer,d as toString,C as validate};\n",null,null,null,null,null,"import { base64 } from '@hexagon/base64';\nimport { ml_kem768 } from '@noble/post-quantum/ml-kem.js';\n\nexport function base64ToUint8Array(str: string): Uint8Array {\n    return new Uint8Array(base64.toArrayBuffer(str));\n}\n\nexport function uint8ArrayToBase64(array: Uint8Array): string {\n    return base64.fromArrayBuffer(array.buffer as ArrayBuffer);\n}\n\nexport function encapsulateKyber(publicKey: Uint8Array): {\n    cipherText: Uint8Array;\n    sharedSecret: Uint8Array;\n} {\n    return ml_kem768.encapsulate(publicKey);\n}\n\nexport function decapsulateKyber(cipherText: Uint8Array, secretKey: Uint8Array): Uint8Array {\n    return ml_kem768.decapsulate(cipherText, secretKey);\n}\n\nexport function generateKyberKeys(): {\n    publicKey: Uint8Array;\n    secretKey: Uint8Array;\n} {\n    return ml_kem768.keygen();\n}\n","import { xchacha20poly1305 } from '@noble/ciphers/chacha.js';\nimport { concatBytes, randomBytes } from '@noble/ciphers/utils.js';\n\nimport { base64ToUint8Array, uint8ArrayToBase64 } from '../e2ee-internxt/Utils';\n\nconst CHAT_AUX = new TextEncoder().encode('Group Chat Message');\nconst NONCE_LEN_BYTES = 24;\n\nexport function encryptSymmetricallySync(\n        message: string,\n        encyptionKey: Uint8Array,\n): string {\n    try {\n        console.info('E2E: ChatRoom encrypting message.');\n        const messageBuffer = new TextEncoder().encode(message);\n        const nonce = randomBytes(NONCE_LEN_BYTES);\n        const chacha = xchacha20poly1305(encyptionKey, nonce, CHAT_AUX);\n        const cipher = chacha.encrypt(messageBuffer);\n        const cipherWithNonce = concatBytes(cipher, nonce);\n\n        return uint8ArrayToBase64(cipherWithNonce);\n    } catch (error) {\n        throw new Error(`Failed to encrypt symmetrically: ${error}`);\n    }\n}\n\nexport function decryptSymmetricallySync(\n        ciphertext: string,\n        encryptionKey: Uint8Array,\n): string {\n    try {\n        console.info('E2E: ChatRoom decrypting message.');\n        const cipherBuffer = base64ToUint8Array(ciphertext);\n        const cipher = cipherBuffer.slice(0, cipherBuffer.length - NONCE_LEN_BYTES);\n        const nonce = cipherBuffer.slice(cipherBuffer.length - NONCE_LEN_BYTES);\n        const chacha = xchacha20poly1305(encryptionKey, nonce, CHAT_AUX);\n        const message = chacha.decrypt(cipher);\n\n        return new TextDecoder().decode(message);\n\n    } catch (error) {\n        throw new Error(`Failed to decrypt symmetrically: ${error} for ciphertext: ${ciphertext}`);\n    }\n}\n","import { getLogger } from '@jitsi/logger';\nimport { $msg, Strophe } from 'strophe.js';\n\nimport { AUTH_ERROR_TYPES } from '../../JitsiConferenceErrors';\nimport { XMPPEvents } from '../../service/xmpp/XMPPEvents';\n\nimport { handleStropheError } from './StropheErrorHandler';\n\nconst logger = getLogger('xmpp:Lobby');\n\n/**\n * The command type for updating a lobby participant's e-mail address.\n *\n * @type {string}\n */\nconst EMAIL_COMMAND = 'email';\n\n/**\n * The Lobby room implementation. Setting a room to members only, joining the lobby room\n * approving or denying access to participants from the lobby room.\n */\nexport default class Lobby {\n\n    /**\n     * Constructs lobby room.\n     *\n     * @param {ChatRoom} room the main room.\n     */\n    constructor(room) {\n        this.xmpp = room.xmpp;\n        this.mainRoom = room;\n\n        const maybeJoinLobbyRoom = this._maybeJoinLobbyRoom.bind(this);\n\n        this.mainRoom.addEventListener(\n            XMPPEvents.LOCAL_ROLE_CHANGED,\n            maybeJoinLobbyRoom);\n\n        this.mainRoom.addEventListener(\n            XMPPEvents.MUC_MEMBERS_ONLY_CHANGED,\n            maybeJoinLobbyRoom);\n\n        this.mainRoom.addEventListener(\n            XMPPEvents.ROOM_CONNECT_MEMBERS_ONLY_ERROR,\n            jid => {\n                this.lobbyRoomJid = jid;\n            });\n    }\n\n    /**\n     * Whether lobby is supported on backend.\n     *\n     * @returns {boolean} whether lobby is supported on backend.\n     */\n    isSupported() {\n        return this.xmpp.lobbySupported;\n    }\n\n    /**\n     * Enables lobby by setting the main room to be members only and joins the lobby chat room.\n     *\n     * @returns {Promise}\n     */\n    enable() {\n        if (!this.isSupported()) {\n            return Promise.reject(new Error('Lobby not supported!'));\n        }\n\n        // let's wait for the room data form to be populated after XMPPEvents.MUC_JOINED\n        if (!this.mainRoom.initialDiscoRoomInfoReceived) {\n            return new Promise((resolve, reject) => {\n                let unsubscribers = [];\n                const unsubscribe = () => {\n                    unsubscribers.forEach(remove => remove());\n                    unsubscribers = [];\n                };\n\n                unsubscribers.push(\n                    this.mainRoom.addCancellableListener(XMPPEvents.ROOM_DISCO_INFO_UPDATED, () => {\n                        unsubscribe();\n\n                        if (this.mainRoom.membersOnlyEnabled) {\n                            resolve();\n\n                            return;\n                        }\n\n                        this.mainRoom.setMembersOnly(true, resolve, reject);\n                    }));\n\n                // on timeout or failure\n                unsubscribers.push(this.mainRoom.addCancellableListener(XMPPEvents.ROOM_DISCO_INFO_FAILED, e => {\n                    unsubscribe();\n                    reject(e);\n                }));\n            });\n        }\n\n        if (this.mainRoom.membersOnlyEnabled) {\n            return Promise.resolve();\n        }\n\n        return new Promise((resolve, reject) => {\n            this.mainRoom.setMembersOnly(true, resolve, reject);\n        });\n    }\n\n    /**\n     * Disable lobby by setting the main room to be non members only and levaes the lobby chat room if joined.\n     *\n     * @returns {void}\n     */\n    disable() {\n        if (!this.isSupported() || !this.mainRoom.isModerator()\n                || !this.lobbyRoom || !this.mainRoom.membersOnlyEnabled) {\n            return;\n        }\n\n        this.mainRoom.setMembersOnly(false);\n    }\n\n    /**\n     * Broadcast a message to all participants in the lobby room\n     * @param {Object} message The message to send\n     *\n     * @returns {void}\n     */\n    sendMessage(message) {\n        if (this.lobbyRoom) {\n            this.lobbyRoom.sendMessage(JSON.stringify(message), 'json-message');\n        }\n    }\n\n    /**\n     * Sends a private message to a participant in a lobby room.\n     * @param {string} id The message to send\n     * @param {Object} message The message to send\n     *\n     * @returns {void}\n     */\n    sendPrivateMessage(id, message) {\n        if (this.lobbyRoom) {\n            this.lobbyRoom.sendPrivateMessage(id, JSON.stringify(message), 'json-message');\n        }\n    }\n\n    /**\n     * Retracts a previously sent message in the lobby room.\n     * @param {string} messageId - The id of the message being retracted.\n     * @param {string} [id] - The participant id, if the message was private.\n     * @returns {void}\n     */\n    sendMessageRetraction(messageId, id) {\n        if (this.lobbyRoom) {\n            this.lobbyRoom.sendMessageRetraction(messageId, id);\n        }\n    }\n\n    /**\n     * Adds a message retraction listener to the lobby room.\n     * @param {Function} listener - Called with (messageId, participantId) when a message is retracted.\n     * @returns {Function} Handler returned to be able to remove it later.\n     */\n    addMessageRetractionListener(listener) {\n        if (this.lobbyRoom) {\n            const handler = (participantId, messageId) => {\n                listener(messageId, Strophe.getResourceFromJid(participantId));\n            };\n\n            this.lobbyRoom.on(XMPPEvents.MESSAGE_RETRACTED, handler);\n\n            return handler;\n        }\n    }\n\n    /**\n     * Removes a message retraction handler from the lobby room.\n     * @param {Function} handler - The handler function to remove.\n     * @returns {void}\n     */\n    removeMessageRetractionHandler(handler) {\n        if (this.lobbyRoom) {\n            this.lobbyRoom.off(XMPPEvents.MESSAGE_RETRACTED, handler);\n        }\n    }\n\n    /**\n     * Gets the local id for a participant in a lobby room.\n     * This is used for lobby room private chat messages.\n     *\n     * @returns {string}\n     */\n    getLocalId() {\n        if (this.lobbyRoom) {\n            return Strophe.getResourceFromJid(this.lobbyRoom.myroomjid);\n        }\n    }\n\n    /**\n     * Adds a message listener to the lobby room.\n     * @param {Function} listener The listener function,\n     * called when a new message is received in the lobby room.\n     *\n     * @returns {Function} Handler returned to be able to remove it later.\n     */\n    addMessageListener(listener) {\n        if (this.lobbyRoom) {\n            const handler = (participantId, message) => {\n                listener(message, Strophe.getResourceFromJid(participantId));\n            };\n\n            this.lobbyRoom.on(XMPPEvents.JSON_MESSAGE_RECEIVED, handler);\n\n            return handler;\n        }\n    }\n\n    /**\n     * Remove a message handler from the lobby room.\n     * @param {Function} handler The handler function to remove.\n     *\n     * @returns {void}\n     */\n    removeMessageHandler(handler) {\n        if (this.lobbyRoom) {\n            this.lobbyRoom.off(XMPPEvents.JSON_MESSAGE_RECEIVED, handler);\n        }\n    }\n\n    /**\n     * Leaves the lobby room.\n     *\n     * @returns {Promise}\n     */\n    leave() {\n        if (this.lobbyRoom) {\n            return this.lobbyRoom.leave()\n                .then(() => {\n                    this.lobbyRoom = undefined;\n                    logger.info('Lobby room left!');\n                })\n                .catch(() => {}); // eslint-disable-line no-empty-function\n        }\n\n        return Promise.reject(\n                new Error('The lobby has already been left'));\n    }\n\n    /**\n     * We had received a jid for the lobby room.\n     *\n     * @param jid the lobby room jid to join.\n     */\n    setLobbyRoomJid(jid) {\n        this.lobbyRoomJid = jid;\n    }\n\n    /**\n     * Checks the state of mainRoom, lobbyRoom and current user role to decide whether to join lobby room.\n     * @private\n     */\n    _maybeJoinLobbyRoom() {\n        if (!this.isSupported()) {\n            return;\n        }\n\n        const isModerator = this.mainRoom.joined && this.mainRoom.isModerator();\n\n        if (isModerator && this.mainRoom.membersOnlyEnabled && !this.lobbyRoom) {\n            // join the lobby\n            this.join()\n                .then(() => logger.info('Joined lobby room'))\n                .catch(e => logger.error('Failed joining lobby', e));\n        }\n    }\n\n    /**\n     * Joins a lobby room setting display name and eventually avatar(using the email provided).\n     *\n     * @param {string} username is required.\n     * @param {string} email is optional.\n     * @returns {Promise} resolves once we join the room.\n     */\n    join(displayName, email) {\n        const isModerator = this.mainRoom.joined && this.mainRoom.isModerator();\n\n        if (!this.lobbyRoomJid) {\n            return Promise.reject(new Error('Missing lobbyRoomJid, cannot join lobby room.'));\n        }\n\n        const roomName = Strophe.getNodeFromJid(this.lobbyRoomJid);\n        const customDomain = Strophe.getDomainFromJid(this.lobbyRoomJid);\n\n        this.lobbyRoom = this.xmpp.createRoom(\n            roomName, {\n                customDomain,\n                disableDiscoInfo: true,\n                disableFocus: true,\n                disableRoomCreationRetry: true,\n                enableLobby: false\n            }\n        );\n\n        if (displayName) {\n            // remove previously set nickname\n            this.lobbyRoom.addOrReplaceInPresence('nick', {\n                attributes: { xmlns: 'http://jabber.org/protocol/nick' },\n                value: displayName\n            });\n        }\n\n        if (isModerator) {\n            this.lobbyRoom.addPresenceListener(EMAIL_COMMAND, (node, from) => {\n                this.mainRoom.eventEmitter.emit(XMPPEvents.MUC_LOBBY_MEMBER_UPDATED, from, { email: node.value });\n            });\n            this.lobbyRoom.addEventListener(\n                XMPPEvents.MUC_MEMBER_JOINED,\n                // eslint-disable-next-line max-params\n                (from, nick, role, isHiddenDomain, statsID, status, identity, botType, jid) => {\n                    // we need to ignore joins on lobby for participants that are already in the main room\n                    if (Object.values(this.mainRoom.members).find(m => m.jid === jid)) {\n                        return;\n                    }\n\n                    // Check if the user is a member if any breakout room.\n                    for (const room of Object.values(this.mainRoom.getBreakoutRooms()._rooms)) {\n                        if (Object.values(room.participants).find(p => p.jid === jid)) {\n                            return;\n                        }\n                    }\n\n                    // we emit the new event on the main room so we can propagate\n                    // events to the conference\n                    this.mainRoom.eventEmitter.emit(\n                        XMPPEvents.MUC_LOBBY_MEMBER_JOINED,\n                        Strophe.getResourceFromJid(from),\n                        nick,\n                        identity ? identity.avatar : undefined\n                    );\n                });\n            this.lobbyRoom.addEventListener(\n                XMPPEvents.MUC_MEMBER_LEFT, from => {\n                    // we emit the new event on the main room so we can propagate\n                    // events to the conference\n                    this.mainRoom.eventEmitter.emit(\n                        XMPPEvents.MUC_LOBBY_MEMBER_LEFT,\n                        Strophe.getResourceFromJid(from)\n                    );\n                });\n            this.lobbyRoom.addEventListener(\n                XMPPEvents.MUC_DESTROYED,\n                () => {\n                    // let's make sure we emit that all lobby users had left\n                    Object.keys(this.lobbyRoom.members)\n                        .forEach(j => this.mainRoom.eventEmitter.emit(\n                            XMPPEvents.MUC_LOBBY_MEMBER_LEFT, Strophe.getResourceFromJid(j)));\n\n                    this.lobbyRoom.clean();\n\n                    this.lobbyRoom = undefined;\n                    logger.info('Lobby room left(destroyed)!');\n                });\n        } else {\n            // this should only be handled by those waiting in lobby\n            this.lobbyRoom.addEventListener(XMPPEvents.KICKED, isSelfPresence => {\n                if (isSelfPresence) {\n                    this.mainRoom.eventEmitter.emit(XMPPEvents.MUC_DENIED_ACCESS);\n\n                    this.lobbyRoom.clean();\n\n\n                }\n            });\n\n            // As there is still reference of the main room\n            // the invite will be detected and addressed to its eventEmitter, even though we are not in it\n            // the invite message should be received directly to the xmpp conn in general\n            this.mainRoom.addEventListener(\n                XMPPEvents.INVITE_MESSAGE_RECEIVED,\n                (roomJid, from, txt, invitePassword) => {\n                    logger.debug(`Received approval to join ${roomJid} ${from} ${txt}`);\n                    if (roomJid === this.mainRoom.roomjid) {\n                        // we are now allowed, so let's join\n                        this.mainRoom.join(invitePassword);\n                    }\n                });\n            this.lobbyRoom.addEventListener(\n                XMPPEvents.MUC_DESTROYED,\n                (reason, jid) => {\n                    this.lobbyRoom?.clean();\n\n                    this.lobbyRoom = undefined;\n                    logger.info('Lobby room left(destroyed)!');\n\n                    // we are receiving the jid of the main room\n                    // means we are invited to join, maybe lobby was disabled\n                    if (jid) {\n                        this.mainRoom.join();\n\n                        return;\n                    }\n\n                    this.mainRoom.eventEmitter.emit(XMPPEvents.MUC_DESTROYED, reason);\n                });\n\n            // If participant retries joining shared password while waiting in the lobby\n            // and succeeds make sure we leave lobby\n            this.mainRoom.addEventListener(\n                XMPPEvents.MUC_JOINED,\n                () => {\n                    this.leave().catch(() => {\n                        // this may happen if the room has been destroyed.\n                    });\n                });\n        }\n\n        return new Promise((resolve, reject) => {\n            this.lobbyRoom.addEventListener(XMPPEvents.MUC_JOINED, () => {\n                resolve();\n\n                // send our email, as we do not handle this on initial presence we need a second one\n                if (email && !isModerator) {\n                    this.lobbyRoom.addOrReplaceInPresence(EMAIL_COMMAND, { value: email })\n                        && this.lobbyRoom.sendPresence();\n                }\n            });\n            this.lobbyRoom.addEventListener(XMPPEvents.ROOM_JOIN_ERROR, reject);\n            this.lobbyRoom.addEventListener(XMPPEvents.ROOM_CONNECT_ERROR, reject);\n            this.lobbyRoom.addEventListener(XMPPEvents.ROOM_CONNECT_NOT_ALLOWED_ERROR, (type, txt) => {\n                if (type === AUTH_ERROR_TYPES.ROOM_CREATION_RESTRICTION) {\n                    logger.info('Lobby room creation not allowed, we will retry on main room.');\n                    this.lobbyRoom?.clean();\n\n                    this.lobbyRoom = undefined;\n\n                    this.mainRoom.join();\n                } else {\n                    reject(type, txt);\n                }\n            });\n\n            this.lobbyRoom.join();\n        });\n    }\n\n    /**\n     * Should be possible only for moderators.\n     * @param id\n     */\n    denyAccess(id) {\n        if (!this.isSupported() || !this.mainRoom.isModerator()) {\n            return;\n        }\n\n        const jid = Object.keys(this.lobbyRoom.members)\n            .find(j => Strophe.getResourceFromJid(j) === id);\n\n        if (jid) {\n            this.lobbyRoom.kick(jid);\n        } else {\n            logger.error(`Not found member for ${id} in lobby room.`);\n        }\n    }\n\n    /**\n     * Should be possible only for moderators.\n     * @param param or an array of ids.\n     */\n    approveAccess(param) {\n        if (!this.isSupported() || !this.mainRoom.isModerator()) {\n            return;\n        }\n\n        // Get the main room JID. If we are in a breakout room we'll use the main\n        // room's lobby.\n        let mainRoomJid = this.mainRoom.roomjid;\n\n        if (this.mainRoom.getBreakoutRooms().isBreakoutRoom()) {\n            mainRoomJid = this.mainRoom.getBreakoutRooms().getMainRoomJid();\n        }\n\n        const membersToApprove = [];\n        let ids = param;\n\n        if (!Array.isArray(param)) {\n            ids = [ param ];\n        }\n\n        ids.forEach(id => {\n            const memberRoomJid = Object.keys(this.lobbyRoom.members)\n                .find(j => Strophe.getResourceFromJid(j) === id);\n\n            if (memberRoomJid) {\n                membersToApprove.push(this.lobbyRoom.members[memberRoomJid].jid);\n            } else {\n                logger.error(`Not found member for ${memberRoomJid} in lobby room.`);\n            }\n        });\n\n        if (membersToApprove.length > 0) {\n            const msgToSend\n                = $msg({ to: mainRoomJid })\n                    .c('x', { xmlns: 'http://jabber.org/protocol/muc#user' });\n\n            membersToApprove.forEach(jid => {\n                msgToSend.c('invite', { to: jid }).up();\n            });\n\n            this.xmpp.connection.sendIQ(msgToSend,\n                () => { }, // eslint-disable-line no-empty-function\n                e => {\n                    handleStropheError(e, {\n                        membersToApprove,\n                        operation: 'lobby approve members',\n                        roomJid: this.lobbyRoom,\n                        userJid: this.xmpp.connection.jid\n                    });\n                });\n        }\n    }\n}\n","import { XMPPEvents } from '../../service/xmpp/XMPPEvents';\n\nimport ChatRoom from './ChatRoom';\nimport XMPP from './xmpp';\n\nexport const COMMAND_ANSWER_POLL = 'answer-poll';\nexport const COMMAND_NEW_POLL = 'new-poll';\nexport const COMMAND_OLD_POLLS = 'old-polls';\n\nexport default class Polls {\n    private _mainRoom: ChatRoom;\n    private _xmpp: XMPP;\n\n    /**\n     * Constructs polls for a room.\n     *\n     * @param {ChatRoom} room the main room.\n     */\n    constructor(room: ChatRoom) {\n        this._mainRoom = room;\n        this._xmpp = room.xmpp;\n\n        this._handleMessages = this._handleMessages.bind(this);\n        this._mainRoom.xmpp.addListener(XMPPEvents.POLLS_EVENT, this._handleMessages);\n    }\n\n    /**\n     * Whether polls is supported on backend.\n     *\n     * @returns {boolean} whether polls is supported on backend.\n     */\n    isSupported() {\n        return Boolean(this._xmpp.pollsComponentAddress);\n    }\n\n    /**\n     * Stops listening for events.\n     */\n    dispose() {\n        this._mainRoom.xmpp.removeListener(XMPPEvents.POLLS_EVENT, this._handleMessages);\n    }\n\n    /**\n     * Creates and sends a new poll.\n     *\n     * @param pollId\n     * @param question\n     * @param answers\n     */\n    createPoll(pollId: string, question: string, answers: Array<{ name: string; }>) {\n        this._mainRoom.sendPrivateMessage(\n            this._xmpp.pollsComponentAddress,\n            JSON.stringify({\n                answers: answers,\n                command: COMMAND_NEW_POLL,\n                pollId,\n                question,\n                type: 'polls'\n            }),\n            'json-message',\n            true);\n    }\n\n    /**\n     * Sends answers for a poll.\n     *\n     * @param pollId\n     * @param answers\n     */\n    answerPoll(pollId: string, answers: Array<boolean>) {\n        this._mainRoom.sendPrivateMessage(\n            this._xmpp.pollsComponentAddress,\n            JSON.stringify({\n                answers,\n                command: COMMAND_ANSWER_POLL,\n                pollId,\n                type: 'polls'\n            }),\n            'json-message',\n            true);\n    }\n\n    /**\n     * Handles a message for polls.\n     *\n     * @param {object} payload - Arbitrary data.\n     */\n    _handleMessages(payload) {\n        switch (payload.command) {\n        case COMMAND_NEW_POLL:\n            this._mainRoom.eventEmitter.emit(XMPPEvents.POLLS_RECEIVE_EVENT, payload);\n\n            break;\n        case COMMAND_OLD_POLLS: {\n            payload?.polls?.forEach((poll: any) => {\n                this._mainRoom.eventEmitter.emit(XMPPEvents.POLLS_RECEIVE_EVENT, {\n                    history: true,\n                    ...poll\n                });\n            });\n            break;\n        }\n        case COMMAND_ANSWER_POLL: {\n            this._mainRoom.eventEmitter.emit(XMPPEvents.POLLS_ANSWER_EVENT, payload);\n            break;\n        }\n        }\n    }\n}\n","import { getLogger } from '@jitsi/logger';\nimport { isEqual } from 'lodash-es';\nimport { $msg } from 'strophe.js';\n\nimport { XMPPEvents } from '../../service/xmpp/XMPPEvents';\n\nimport { JITSI_MEET_MUC_TYPE } from './xmpp';\n\nconst logger = getLogger('xmpp:RoomMetadata');\n\n/**\n * Helper class for handling room metadata.\n */\nexport default class RoomMetadata {\n    room: any;\n    _metadata: any;\n\n    /**\n     * Constructs lobby room.\n     *\n     * @param {ChatRoom} room the room we are in.\n     */\n    constructor(room) {\n        this.room = room;\n\n        this._handleMessages = this._handleMessages.bind(this);\n        this.room.xmpp.addListener(XMPPEvents.ROOM_METADATA_EVENT, this._handleMessages);\n\n        this._metadata = {};\n    }\n\n    /**\n     * Stops listening for events.\n     */\n    dispose() {\n        this.room.xmpp.removeListener(XMPPEvents.ROOM_METADATA_EVENT, this._handleMessages);\n    }\n\n    /**\n     * Sets metadata for the given key.\n     *\n     * @param {string} key - key under which the metadata will be stored.\n     * @param {object} data - data to be stored.\n     */\n    setMetadata(key, data) {\n        if (!this.isSupported()) {\n            logger.error(`Cannot set room metadata - supported:${this.isSupported()}`);\n\n            return;\n        }\n\n        const message = {\n            data,\n            key\n        };\n\n        this._sendMessage(message);\n    }\n\n    /**\n     * Gets the stored metadata (all of it).\n     *\n     * @returns The stored metadata.\n     */\n    getMetadata() {\n        return this._metadata;\n    }\n\n    /**\n     * Whether Breakout Rooms support is enabled in the backend or not.\n     */\n    isSupported() {\n        return Boolean(this.getComponentAddress());\n    }\n\n    /**\n     * Gets the address of the Breakout Rooms XMPP component.\n     *\n     * @returns The address of the component.\n     */\n    getComponentAddress() {\n        return this.room.xmpp.roomMetadataComponentAddress;\n    }\n\n    /**\n     * Handles a message with metadata updates.\n     *\n     * @param {object} payload - Arbitrary data.\n     */\n    _handleMessages(payload) {\n        const { metadata } = payload;\n\n        if (!metadata || isEqual(this._metadata, metadata)) {\n            return;\n        }\n\n        this._metadata = metadata;\n        logger.debug('Received metadata update', JSON.stringify(metadata));\n        this.room.eventEmitter.emit(XMPPEvents.ROOM_METADATA_UPDATED, metadata);\n    }\n\n    /**\n     * Helper to send a breakout rooms message to the component.\n     *\n     * @param {Object} message - Command that needs to be sent.\n     */\n    _sendMessage(message) {\n        message[JITSI_MEET_MUC_TYPE] = 'room_metadata';\n\n        const msg = $msg({ to: this.getComponentAddress() });\n\n        msg.c('room_metadata', {\n            room: this.room.roomjid,\n            xmlns: 'http://jitsi.org/jitmeet'\n        }, JSON.stringify(message)).up();\n\n        this.room.xmpp.connection.send(msg);\n    }\n}\n","import { getLogger } from '@jitsi/logger';\nimport emojiRegex from 'emoji-regex';\nimport { isEqual } from 'lodash-es';\nimport { $iq, $msg, $pres, Strophe } from 'strophe.js';\nimport { v4 as uuidv4 } from 'uuid';\n\nimport { AUTH_ERROR_TYPES } from '../../JitsiConferenceErrors';\nimport { JitsiConferenceEvents } from '../../JitsiConferenceEvents';\nimport * as JitsiTranscriptionStatus from '../../JitsiTranscriptionStatus';\nimport { MediaType } from '../../service/RTC/MediaType';\nimport { VideoType } from '../../service/RTC/VideoType';\nimport { AuthenticationEvents } from '../../service/authentication/AuthenticationEvents';\nimport { XMPPEvents } from '../../service/xmpp/XMPPEvents';\nimport Settings from '../settings/Settings';\nimport EventEmitterForwarder from '../util/EventEmitterForwarder';\nimport Listenable from '../util/Listenable';\nimport { getJitterDelay } from '../util/Retry';\nimport { exists, findAll, findFirst, getAttribute, getText, stripXMLInvalidChars } from '../util/XMLUtils';\n\nimport AVModeration from './AVModeration';\nimport BreakoutRooms from './BreakoutRooms';\nimport { decryptSymmetricallySync, encryptSymmetricallySync } from './ChetRoomCrypto';\nimport FileSharing from './FileSharing';\nimport Lobby from './Lobby';\nimport Polls from './Polls';\nimport RoomMetadata from './RoomMetadata';\nimport { handleStropheError } from './StropheErrorHandler';\nimport XmppConnection, { ErrorCallback } from './XmppConnection';\nimport XMPP, { FEATURE_TRANSCRIBER } from './xmpp';\n\n// Callback types\ntype SuccessCallback = () => void;\ntype ParticipantPropertyListener = (participantId: string, key: string, value: string) => void;\nexport type PresenceHandler = (node: IPresenceNode, participantId: string, from: string) => void;\n\n// Node type for presence JSON structure\ninterface IPresenceNode {\n    attributes?: Record<string, string>;\n    children?: IPresenceNode[];\n    tagName: string;\n    value?: string ;\n}\n\n// Member type for room members\ninterface IRoomMember {\n    affiliation?: string;\n    botType?: string;\n    displayName?: string;\n    features?: Set<string>;\n    id?: string;\n    identity?: IIdentity;\n    isFocus?: boolean;\n    isHiddenDomain?: boolean;\n    isReplaceParticipant?: number;\n    isSilent?: boolean;\n    jid?: string;\n    nick?: string;\n    region?: string;\n    role?: string;\n    statsID?: string;\n    status?: string;\n    version?: string;\n}\n\n// Options interface for ChatRoom constructor\nexport interface IChatRoomOptions {\n    deploymentInfo?: any;\n    disableDiscoInfo?: boolean;\n    disableFocus?: boolean;\n    disableRoomCreationRetry?: boolean;\n    enableLobby?: boolean;\n    hiddenDomain?: string;\n    hiddenFromRecorderFeatureEnabled?: boolean;\n    isChatEncrypted?: boolean;\n    statsId?: string;\n}\n\n// Presence map structure\ninterface IPresenceMap {\n    length?: number;\n    nodes: IPresenceNode[];\n    to?: string;\n    xns?: string;\n}\n\n// Identity information interface\ninterface IIdentity {\n    group?: string;\n    user?: {\n        avatar?: string;\n        'hidden-from-recorder'?: string;\n        id?: string;\n        name?: string;\n    };\n}\n\n// Peer media info type\ninterface IPeerMediaInfo {\n    codecType?: string;\n    muted: boolean;\n    videoType?: VideoType | string;\n}\n\ninterface IPendingEncryptedMessage {\n    displayName?: string;\n    from: string;\n    isVisitorMessage: boolean;\n    messageId: string;\n    replyToId?: string;\n    source?: string;\n    stamp: string | null;\n    txt: string;\n}\n\nconst logger = getLogger('xmpp:ChatRoom');\n\n/**\n * Regex that matches all emojis.\n */\nconst EMOJI_REGEX = emojiRegex();\n\n/**\n * How long we're going to wait for IQ response, before timeout error is triggered.\n * @type {number}\n */\nconst IQ_TIMEOUT = 10000;\n\nexport const parser = {\n    json2packet(nodes: IPresenceNode[], packet: any): void {\n        for (let i = 0; i < nodes.length; i++) {\n            const node = nodes[i];\n\n            if (node) {\n                packet.c(node.tagName, node.attributes);\n                if (node.value) {\n                    packet.t(node.value);\n                }\n                if (node.children) {\n                    this.json2packet(node.children, packet);\n                }\n                packet.up();\n            }\n        }\n\n        // packet.up();\n    },\n    packet2JSON(xmlElement: Element, nodes: IPresenceNode[]): void {\n        for (const child of Array.from(xmlElement.children)) {\n            const node: IPresenceNode = {\n                attributes: {},\n                children: [],\n                tagName: child.tagName\n            };\n\n            for (const attr of Array.from(child.attributes)) {\n                node.attributes[attr.name] = attr.value;\n            }\n            const text = Strophe.getText(child);\n\n            if (text) {\n                // Using Strophe.getText will do work for traversing all direct\n                // child text nodes but returns an escaped value, which is not\n                // desirable at this point.\n                node.value = Strophe.xmlunescape(text);\n            }\n            nodes.push(node);\n            this.packet2JSON(child, node.children);\n        }\n    }\n};\n\n/**\n * Returns array of JS objects from the presence JSON associated with the passed\n / nodeName\n * @param pres the presence JSON\n * @param nodeName the name of the node (videomuted, audiomuted, etc)\n */\nexport function filterNodeFromPresenceJSON(pres: IPresenceNode[], nodeName: string): IPresenceNode[] {\n    const res: IPresenceNode[] = [];\n\n    for (let i = 0; i < pres.length; i++) {\n        if (pres[i].tagName === nodeName) {\n            res.push(pres[i]);\n        }\n    }\n\n    return res;\n}\n\n// XXX As ChatRoom constructs XMPP stanzas and Strophe is build around the idea\n// of chaining function calls, allow long function call chains.\n/* eslint-disable newline-per-chained-call */\n\n/**\n * Array of affiliations that are allowed in members only room.\n * @type {string[]}\n */\nconst MEMBERS_AFFILIATIONS = [ 'owner', 'admin', 'member' ];\n\n/**\n * Process nodes to extract data needed for MUC_JOINED and MUC_MEMBER_JOINED events.\n *\n */\nfunction extractIdentityInformation(node: IPresenceNode, hiddenFromRecorderFeatureEnabled: boolean): IIdentity {\n    const identity: IIdentity = {};\n    const userInfo = node.children.find(c => c.tagName === 'user');\n    const HIDDEN_FROM_RECORDER = 'hidden-from-recorder';\n\n    if (userInfo) {\n        identity.user = {};\n\n        // Add all children from the user node except hidden-from-recorder\n        for (const child of userInfo.children) {\n            if (child.tagName && child.value !== undefined && child.tagName !== HIDDEN_FROM_RECORDER) {\n                identity.user[child.tagName] = child.value;\n            }\n        }\n\n        // Separately check if we should add hidden-from-recorder\n        if (hiddenFromRecorderFeatureEnabled) {\n            const hiddenFromRecorder = userInfo.children.find(c => c.tagName === HIDDEN_FROM_RECORDER);\n\n            if (hiddenFromRecorder) {\n                identity.user[HIDDEN_FROM_RECORDER] = hiddenFromRecorder.value;\n            }\n        }\n    }\n    const groupInfo = node.children.find(c => c.tagName === 'group');\n\n    if (groupInfo) {\n        identity.group = groupInfo.value;\n    }\n\n    return identity;\n}\n\n/**\n *\n */\nexport default class ChatRoom extends Listenable {\n\n    private encryptionKey?: Uint8Array;\n    private password?: string;\n    private replaceParticipant: boolean;\n    private members: Record<string, IRoomMember>;\n    private presHandlers: Record<string, PresenceHandler[]>;\n    private _removeConnListeners: (() => void)[];\n    private inProgressEmitted: boolean;\n    private noBridgeAvailable: boolean;\n    private options: IChatRoomOptions;\n    private eventsForwarder: EventEmitterForwarder;\n    private lobby?: Lobby;\n    private avModeration: AVModeration;\n    private breakoutRooms: BreakoutRooms;\n    private fileSharing: FileSharing;\n    private polls: Polls;\n    private roomMetadata: RoomMetadata;\n    private lastPresences: Record<string, IPresenceNode[]>;\n    private phoneNumber: Nullable<string>;\n    private phonePin: Nullable<string>;\n    private participantPropertyListener?: ParticipantPropertyListener;\n    private locked: boolean;\n    private initialDiscoRoomInfoReceived: boolean;\n    private presenceUpdateTime: number;\n    private presenceSyncTime?: number;\n    private meetingId?: string;\n    private focusFeatures?: Set<string>;\n    private subject?: string;\n    private _roomCreationRetries?: number;\n    private cachedShortTermCredentials?: Record<string, string>;\n    private pendingEncryptedMessages: IPendingEncryptedMessage[];\n    public xmpp: XMPP;\n    public connection: XmppConnection;\n    public roomjid: string;\n    public myroomjid: string;\n    public joined: boolean;\n    public presMap: IPresenceMap;\n    public role: Nullable<string>;\n    public focusMucJid: Nullable<string>;\n    public connectionTimes: Record<string, number>;\n    public transcriptionStatus: string;\n    public membersOnlyEnabled?: boolean;\n    public visitorsSupported?: boolean;\n\n    /* eslint-disable max-params */\n\n    /**\n     *\n     * @param {XmppConnection} connection - The XMPP connection instance.\n     * @param jid\n     * @param password\n     * @param XMPP\n     * @param options\n     * @param {boolean} options.disableFocus - when set to {@code false} will\n     * not invite Jicofo into the room.\n     * @param {boolean} options.disableDiscoInfo - when set to {@code false} will skip disco info.\n     * This is intended to be used only for lobby rooms.\n     * @param {boolean} options.enableLobby - when set to {@code false} will skip creating lobby room.\n     * @param {boolean} options.hiddenFromRecorderFeatureEnabled - when set to {@code true} we will check identity tag\n     * for node presence.\n     */\n    constructor(connection: XmppConnection, jid: string, password: Optional<string>, xmpp: XMPP, options?: IChatRoomOptions) {\n        super();\n        this.xmpp = xmpp;\n        this.connection = connection;\n        this.roomjid = Strophe.getBareJidFromJid(jid);\n        this.myroomjid = jid;\n        this.password = password;\n        this.replaceParticipant = false;\n        logger.info(`Joining MUC as ${this.myroomjid}`);\n        this.members = {};\n        this.presMap = { nodes: [] };\n        this.presHandlers = {};\n        this._removeConnListeners = [];\n        this.joined = false;\n        this.inProgressEmitted = false;\n        this.role = null;\n        this.focusMucJid = null;\n        this.noBridgeAvailable = false;\n        this.options = options || {};\n        this.pendingEncryptedMessages = [];\n\n        this.eventsForwarder = new EventEmitterForwarder(this.xmpp.moderator, this.eventEmitter);\n        this.eventsForwarder.forward(AuthenticationEvents.IDENTITY_UPDATED, AuthenticationEvents.IDENTITY_UPDATED);\n        this.eventsForwarder.forward(XMPPEvents.AUTHENTICATION_REQUIRED, XMPPEvents.AUTHENTICATION_REQUIRED);\n        this.eventsForwarder.forward(XMPPEvents.FOCUS_DISCONNECTED, XMPPEvents.FOCUS_DISCONNECTED);\n        this.eventsForwarder.forward(XMPPEvents.RESERVATION_ERROR, XMPPEvents.RESERVATION_ERROR);\n\n        if (typeof this.options.enableLobby === 'undefined' || this.options.enableLobby) {\n            this.lobby = new Lobby(this);\n        }\n        this.avModeration = new AVModeration(this);\n        this.breakoutRooms = new BreakoutRooms(this);\n        this.fileSharing = new FileSharing(this);\n        this.polls = new Polls(this);\n        this.roomMetadata = new RoomMetadata(this);\n        this.initPresenceMap(options);\n        this.lastPresences = {};\n        this.phoneNumber = null;\n        this.phonePin = null;\n        this.connectionTimes = {};\n        this.participantPropertyListener = null;\n\n        this.locked = false;\n        this.transcriptionStatus = JitsiTranscriptionStatus.OFF;\n        this.initialDiscoRoomInfoReceived = false;\n\n        this.eventEmitter.once(JitsiConferenceEvents.E2EE_CHAT_KEY_RECEIVED, this.setEncryptionKey.bind(this));\n\n    }\n\n    /* eslint-enable max-params */\n\n    /**\n     *\n     */\n    private initPresenceMap(options: IChatRoomOptions = {}): void {\n        this.presMap.to = this.myroomjid;\n        this.presMap.xns = 'http://jabber.org/protocol/muc';\n        this.presMap.nodes = [];\n\n        if (options.statsId) {\n            this.presMap.nodes.push({\n                'tagName': 'stats-id',\n                'value': options.statsId\n            });\n        }\n\n        this.presenceUpdateTime = Date.now();\n    }\n\n\n    /**\n     * Extracts the features from the presence.\n     * @param node the node to process.\n     * @return features the Set of features where extracted data is added.\n     * @private\n     */\n    private _extractFeatures(node: IPresenceNode): Set<string> {\n        const features = new Set<string>();\n\n        for (let j = 0; j < node.children.length; j++) {\n            const { attributes } = node.children[j];\n\n            if (attributes?.var) {\n                features.add(attributes.var);\n            }\n        }\n\n        return features;\n    }\n\n    /**\n     * Initialize some properties when the focus participant is verified.\n     * @param from jid of the focus\n     * @param features the features reported in jicofo presence\n     */\n    private _initFocus(from: string, features?: Set<string>): void {\n        this.focusMucJid = from;\n        this.focusFeatures = features;\n    }\n\n    /**\n     * Handles Xmpp Connection status updates.\n     *\n     * @param {Strophe.Status} status - The Strophe connection status.\n     */\n    private _onConnStatusChanged(status: Strophe.Status): void {\n        // Send cached presence when the XMPP connection is re-established, only if needed\n        if (status === XmppConnection.Status.CONNECTED && this.presenceUpdateTime > this.presenceSyncTime) {\n            this.sendPresence();\n        }\n    }\n\n    /**\n     *\n     * @param node\n     * @param from\n     */\n    private _processNode(node: IPresenceNode, from: string): void {\n        // make sure we catch all errors coming from any handler\n        // otherwise we can remove the presence handler from strophe\n        try {\n            const tagHandlers = this.presHandlers[node.tagName] ?? [];\n\n            tagHandlers.forEach(handler => {\n                handler(node, Strophe.getResourceFromJid(from), from);\n            });\n        } catch (e) {\n            logger.error(`Error processing:${node.tagName} node.`, e);\n        }\n    }\n\n    /**\n     * Clean any listeners or resources, executed on leaving.\n     */\n    private clean(): void {\n        this._removeConnListeners.forEach(remove => remove());\n        this._removeConnListeners = [];\n\n        this.eventsForwarder.removeListeners(\n            AuthenticationEvents.IDENTITY_UPDATED,\n            XMPPEvents.AUTHENTICATION_REQUIRED,\n            XMPPEvents.FOCUS_DISCONNECTED,\n            XMPPEvents.RESERVATION_ERROR);\n\n        this.joined = false;\n        this.inProgressEmitted = false;\n    }\n\n    /**\n     * Parses XEP-0461 reply message information from a message stanza.\n     * @param {Element} msg - The message stanza.\n     * @returns {string|null} The ID of the message being replied to, or null if not a reply.\n     * @private\n     */\n    private _parseReplyMessage(msg: Element): string | null {\n        return getAttribute(\n            findFirst(msg, ':scope>reply[*|xmlns=\"urn:xmpp:reply:0\"]'),\n            'to'\n        );\n    }\n\n    public setEncryptionKey(key: Uint8Array): void {\n        this.encryptionKey = key;\n        logger.info('E2E: ChatRoom got encryption key.');\n\n        if (this.pendingEncryptedMessages.length > 0) {\n            logger.info(`E2E: Decrypting ${this.pendingEncryptedMessages.length} queued messages`);\n            this.pendingEncryptedMessages.forEach(msg => {\n                try {\n                    const chatMessage = decryptSymmetricallySync(msg.txt, this.encryptionKey);\n\n                    this.eventEmitter.emit(XMPPEvents.MESSAGE_RECEIVED,\n                        msg.from, chatMessage, this.myroomjid, msg.stamp, msg.displayName,\n                        msg.isVisitorMessage, msg.messageId, msg.source, msg.replyToId);\n\n                } catch (e) {\n                    logger.error('Failed to decrypt queued message', e);\n                }\n            });\n            this.pendingEncryptedMessages = [];\n        }\n    }\n\n    /**\n     * Joins the chat room.\n     * @param {string} password - Password to unlock room on joining.\n     * @returns {Promise} - resolved when join completes. At the time of this\n     * writing it's never rejected.\n     */\n    public join(password?: string, replaceParticipant?: boolean): Promise<void> {\n        this.password = password;\n        this.replaceParticipant = replaceParticipant;\n\n        return new Promise(resolve => {\n            this.options.disableFocus\n                && logger.info(`Conference focus disabled for ${this.roomjid}`);\n\n            const preJoin\n                = this.options.disableFocus\n                    ? Promise.resolve()\n                        .finally(() => {\n                            this.xmpp.connection._breakoutMovingToMain = undefined;\n                        })\n                    : this.xmpp.moderator.sendConferenceRequest(this.roomjid);\n\n            preJoin.then(() => {\n                this.sendPresence(true);\n                this._removeConnListeners.push(\n                    this.connection.addCancellableListener(\n                        XmppConnection.Events.CONN_STATUS_CHANGED,\n                        this._onConnStatusChanged.bind(this))\n                );\n                resolve();\n            })\n            .catch(e => logger.trace('PreJoin rejected', e));\n        });\n    }\n\n    /**\n     *\n     * @param fromJoin - Whether this is initial presence to join the room.\n     */\n    public sendPresence(fromJoin: boolean = false): void {\n        const to = this.presMap.to;\n\n        if (!this.connection || !this.connection.connected || !to || (!this.joined && !fromJoin)) {\n            // Too early to send presence - not initialized\n            return;\n        }\n\n        const pres = $pres({ to });\n\n        // xep-0045 defines: \"including in the initial presence stanza an empty\n        // <x/> element qualified by the 'http://jabber.org/protocol/muc'\n        // namespace\" and subsequent presences should not include that or it can\n        // be considered as joining, and server can send us the message history\n        // for the room on every presence\n        if (fromJoin) {\n            if (this.replaceParticipant) {\n                pres.c('flip_device').up();\n            }\n\n            pres.c('x', { xmlns: this.presMap.xns });\n\n            if (this.password) {\n                pres.c('password').t(this.password).up();\n            }\n\n            // send the machineId with the initial presence\n            if (this.xmpp.moderator.targetUrl) {\n                pres.c('billingid').t(Settings.machineId).up();\n            }\n\n            pres.up();\n        }\n\n        parser.json2packet(this.presMap.nodes, pres);\n\n        // we store time we last synced presence state\n        this.presenceSyncTime = Date.now();\n\n        this.connection.send(pres);\n        if (fromJoin) {\n            // XXX We're pressed for time here because we're beginning a complex\n            // and/or lengthy conference-establishment process which supposedly\n            // involves multiple RTTs. We don't have the time to wait for\n            // Strophe to decide to send our IQ.\n            this.connection.flush();\n        }\n    }\n\n    /**\n     * Sends the presence unavailable, signaling the server\n     * we want to leave the room.\n     */\n    public doLeave(reason?: string): void {\n        logger.info('do leave', this.myroomjid);\n        const pres = $pres({\n            to: this.myroomjid,\n            type: 'unavailable'\n        });\n\n        if (reason) {\n            pres.c('status').t(reason).up();\n        }\n\n        this.presMap.length = 0;\n\n        // XXX Strophe is asynchronously sending by default. Unfortunately, that\n        // means that there may not be enough time to send the unavailable\n        // presence. Switching Strophe to synchronous sending is not much of an\n        // option because it may lead to a noticeable delay in navigating away\n        // from the current location. As a compromise, we will try to increase\n        // the chances of sending the unavailable presence within the short time\n        // span that we have upon unloading by invoking flush() on the\n        // connection. We flush() once before sending/queuing the unavailable\n        // presence in order to attemtp to have the unavailable presence at the\n        // top of the send queue. We flush() once more after sending/queuing the\n        // unavailable presence in order to attempt to have it sent as soon as\n        // possible.\n        // FIXME do not use Strophe.Connection in the ChatRoom directly\n        !this.connection.isUsingWebSocket && this.connection.flush();\n        this.connection.send(pres);\n        this.connection.flush();\n    }\n\n    /**\n     *\n     */\n    public discoRoomInfo(): void {\n        // https://xmpp.org/extensions/xep-0045.html#disco-roominfo\n\n        const getInfo\n            = $iq({\n                to: this.roomjid,\n                type: 'get'\n            })\n                .c('query', { xmlns: Strophe.NS.DISCO_INFO });\n\n        this.connection.sendIQ(getInfo, result => {\n            const locked = findAll(result, ':scope>query>feature[var=\"muc_passwordprotected\"]').length === 1;\n\n            if (locked !== this.locked) {\n                this.eventEmitter.emit(XMPPEvents.MUC_LOCK_CHANGED, locked);\n                this.locked = locked;\n            }\n\n            const meetingIdValEl = findFirst(result, ':scope>query>x[type=\"result\"]>field[var=\"muc#roominfo_meetingId\"]>value');\n\n            if (meetingIdValEl) {\n                this.setMeetingId(getText(meetingIdValEl));\n            } else {\n                logger.warn('No meeting ID from backend');\n            }\n\n            const meetingCreatedTSValEl = findFirst(result,\n                ':scope>query>x[type=\"result\"]>field[var=\"muc#roominfo_created_timestamp\"]>value');\n\n            if (meetingCreatedTSValEl) {\n                this.eventEmitter.emit(XMPPEvents.CONFERENCE_TIMESTAMP_RECEIVED, getText(meetingCreatedTSValEl));\n            } else {\n                logger.warn('No conference duration from backend');\n            }\n\n            const membersOnly = findAll(result, ':scope>query>feature[var=\"muc_membersonly\"]').length === 1;\n\n            const lobbyRoomField = findFirst(result,\n                ':scope>query>x[type=\"result\"]>field[var=\"muc#roominfo_lobbyroom\"]>value');\n\n            if (this.lobby) {\n                this.lobby.setLobbyRoomJid(\n                    lobbyRoomField ? getText(lobbyRoomField) : undefined);\n            }\n\n            const isBreakoutField = findFirst(result,\n                ':scope>query>x[type=\"result\"]>field[var=\"muc#roominfo_isbreakout\"]>value');\n            const isBreakoutRoom = Boolean(getText(isBreakoutField));\n\n            this.breakoutRooms._setIsBreakoutRoom(isBreakoutRoom);\n\n            const breakoutMainRoomField = findFirst(result,\n                ':scope>query>x[type=\"result\"]>field[var=\"muc#roominfo_breakout_main_room\"]>value');\n\n            if (breakoutMainRoomField) {\n                this.breakoutRooms._setMainRoomJid(getText(breakoutMainRoomField));\n            }\n\n            if (membersOnly !== this.membersOnlyEnabled) {\n                this.membersOnlyEnabled = membersOnly;\n                this.eventEmitter.emit(XMPPEvents.MUC_MEMBERS_ONLY_CHANGED, membersOnly);\n            }\n\n            const visitorsEnabledEl = findFirst(result,\n                ':scope>query>x[type=\"result\"]>field[var=\"muc#roominfo_visitorsEnabled\"]>value');\n            const visitorsSupported = getText(visitorsEnabledEl) === '1';\n\n            if (visitorsSupported !== this.visitorsSupported) {\n                this.visitorsSupported = visitorsSupported;\n                this.eventEmitter.emit(XMPPEvents.MUC_VISITORS_SUPPORTED_CHANGED, visitorsSupported);\n            }\n\n            this.initialDiscoRoomInfoReceived = true;\n            this.eventEmitter.emit(XMPPEvents.ROOM_DISCO_INFO_UPDATED);\n        }, error => {\n            handleStropheError(error, {\n                operation: 'get room disco info',\n                roomJid: this.roomjid,\n                userJid: this.connection.jid\n            });\n            this.eventEmitter.emit(XMPPEvents.ROOM_DISCO_INFO_FAILED, error);\n        },\n        IQ_TIMEOUT);\n    }\n\n    /**\n     * Sets the meeting unique Id (received from the backend).\n     *\n     * @param {string} meetingId - The new meetings id.\n     * @returns {void}\n     */\n    public setMeetingId(meetingId: string): void {\n        if (this.meetingId !== meetingId) {\n            if (this.meetingId) {\n                logger.warn(`Meeting Id changed from:${this.meetingId} to:${meetingId}`);\n            }\n            this.meetingId = meetingId;\n            this.eventEmitter.emit(XMPPEvents.MEETING_ID_SET, meetingId);\n        }\n    }\n\n    /**\n     *\n     */\n    public createNonAnonymousRoom(): void {\n        // http://xmpp.org/extensions/xep-0045.html#createroom-reserved\n\n        if (this.options.disableDiscoInfo) {\n            return;\n        }\n\n        const getForm = $iq({ to: this.roomjid,\n            type: 'get' })\n            .c('query', { xmlns: 'http://jabber.org/protocol/muc#owner' })\n            .c('x', { type: 'submit',\n                xmlns: 'jabber:x:data' });\n\n        this.connection.sendIQ(getForm, form => {\n            // Use *|xmlns to match xmlns attributes across any namespace (CSS Selectors Level 3)\n            if (!exists(form, ':scope>query>x[*|xmlns=\"jabber:x:data\"]>field[var=\"muc#roomconfig_whois\"]')) {\n                logger.error('non-anonymous rooms not supported');\n\n                return;\n            }\n\n            const formSubmit = $iq({ to: this.roomjid,\n                type: 'set' })\n                .c('query', { xmlns: 'http://jabber.org/protocol/muc#owner' });\n\n            formSubmit.c('x', { type: 'submit',\n                xmlns: 'jabber:x:data' });\n\n            formSubmit.c('field', { 'var': 'FORM_TYPE' })\n                .c('value')\n                .t('http://jabber.org/protocol/muc#roomconfig').up().up();\n\n            formSubmit.c('field', { 'var': 'muc#roomconfig_whois' })\n                .c('value').t('anyone').up().up();\n\n            this.connection.sendIQ(formSubmit, undefined, error => {\n                handleStropheError(error, {\n                    operation: 'submit room configuration form',\n                    roomJid: this.roomjid,\n                    userJid: this.connection.jid\n                });\n            });\n\n        }, error => {\n            handleStropheError(error, {\n                operation: 'get room configuration form',\n                roomJid: this.roomjid,\n                userJid: this.connection.jid\n            });\n        });\n    }\n\n    /**\n     *\n     * @param pres\n     * @internal\n     */\n    onPresence(pres: Element): void {\n        const from = pres.getAttribute('from');\n        const member: IRoomMember = {};\n        const statusEl = pres.getElementsByTagName('status')[0];\n\n        if (statusEl) {\n            member.status = statusEl.textContent || '';\n        }\n        let hasStatusUpdate = false;\n        let hasVersionUpdate = false;\n        const xElement\n            = pres.getElementsByTagNameNS(\n                'http://jabber.org/protocol/muc#user', 'x')[0];\n        const mucUserItem\n            = xElement?.getElementsByTagName('item')[0];\n\n        member.isReplaceParticipant\n            = pres.getElementsByTagName('flip_device').length;\n\n        member.affiliation\n            = mucUserItem?.getAttribute('affiliation');\n        member.role = mucUserItem?.getAttribute('role');\n\n        // Focus recognition\n        const jid = mucUserItem?.getAttribute('jid');\n\n        member.jid = jid;\n        member.isFocus = this.xmpp.moderator.isFocusJid(jid);\n        member.isHiddenDomain\n            = jid?.indexOf('@') > 0\n                && this.options.hiddenDomain\n                    === jid.substring(jid.indexOf('@') + 1, jid.indexOf('/'));\n\n        this.eventEmitter.emit(XMPPEvents.PRESENCE_RECEIVED, {\n            fromHiddenDomain: member.isHiddenDomain,\n            isFocus: member.isFocus,\n            presence: pres\n        });\n\n        const xEl = pres.querySelector('x');\n\n        if (xEl) {\n            xEl.remove();\n        }\n\n        const nodes: IPresenceNode[] = [];\n\n        parser.packet2JSON(pres, nodes);\n        this.lastPresences[from] = nodes;\n\n        for (let i = 0; i < nodes.length; i++) {\n            const node = nodes[i];\n\n            switch (node.tagName) {\n            case 'bot': {\n                const { attributes } = node;\n\n                if (!attributes) {\n                    break;\n                }\n                const { type } = attributes;\n\n                member.botType = type;\n                break;\n            }\n            case 'nick':\n                member.nick = node.value;\n                break;\n            case 'silent':\n                member.isSilent = Boolean(node.value);\n                break;\n            case 'userId':\n                member.id = node.value;\n                break;\n            case 'stats-id':\n                member.statsID = node.value;\n                break;\n            case 'identity':\n                member.identity = extractIdentityInformation(node, this.options.hiddenFromRecorderFeatureEnabled);\n                break;\n            case 'features': {\n                member.features = this._extractFeatures(node);\n                break;\n            }\n            case 'jitsi_participant_region': {\n                member.region = node.value;\n                break;\n            }\n            case 'stat': {\n                const { attributes } = node;\n\n                if (!attributes) {\n                    break;\n                }\n                const { name } = attributes;\n\n                if (name === 'version') {\n                    member.version = attributes.value;\n                }\n                break;\n            }\n            }\n        }\n\n        if (!this.joined && !this.inProgressEmitted) {\n            const now = this.connectionTimes['muc.join.started'] = window.performance.now();\n\n            logger.info('(TIME) MUC join started:\\t', now);\n\n            this.eventEmitter.emit(XMPPEvents.MUC_JOIN_IN_PROGRESS);\n            this.inProgressEmitted = true;\n        }\n\n        if (from === this.myroomjid) {\n            const newRole = member.role || 'none';\n\n            if (!this.joined) {\n                this.joined = true;\n                const now = this.connectionTimes['muc.joined']\n                    = window.performance.now();\n\n                logger.info('(TIME) MUC joined:\\t', now);\n\n                // set correct initial state of locked\n                if (this.password) {\n                    this.locked = true;\n                }\n\n                if (member.region && this.options?.deploymentInfo) {\n                    this.options.deploymentInfo.userRegion = member.region;\n                }\n\n                // Re-send presence in case any presence updates were added,\n                // but blocked from sending, during the join process.\n                // send the presence only if there was a modification after we had synced it\n                if (this.presenceUpdateTime > this.presenceSyncTime) {\n                    this.sendPresence();\n                }\n\n                // we need to reset it because of breakout rooms which will reuse connection but will invite jicofo\n                this.xmpp.moderator.conferenceRequestSent = false;\n\n                this.eventEmitter.emit(XMPPEvents.MUC_JOINED);\n\n                // Now let's check the disco-info to retrieve the\n                // meeting Id if any\n                !this.options.disableDiscoInfo && this.discoRoomInfo();\n            }\n\n            if (this.role !== newRole) {\n                this.role = newRole;\n                this.eventEmitter.emit(\n                    XMPPEvents.LOCAL_ROLE_CHANGED,\n                    this.role);\n            }\n\n            if (exists(xElement, ':scope>status[code=\"110\"]')) {\n                // let's check for some backend forced permissions\n                // Use *|xmlns to match xmlns attributes across any namespace (CSS Selectors Level 3)\n                const permissionEl = findFirst(pres, ':scope>permissions[*|xmlns=\"http://jitsi.org/jitmeet\"]');\n\n                if (permissionEl) {\n                    const permissionsMap = {};\n\n                    findAll(permissionEl, 'p').forEach(p => {\n                        permissionsMap[getAttribute(p, 'name')] = getAttribute(p, 'val');\n                    });\n\n                    this.eventEmitter.emit(XMPPEvents.PERMISSIONS_RECEIVED, permissionsMap);\n                }\n            }\n        } else if (jid === undefined) {\n            logger.info('Ignoring member with undefined JID');\n        } else if (this.members[from] === undefined) {\n            // new participant\n            this.members[from] = member;\n            logger.info('entered', from);\n            hasStatusUpdate = member.status !== undefined;\n            hasVersionUpdate = member.version !== undefined;\n            if (member.isFocus) {\n                this._initFocus(from, member.features);\n            } else {\n                // identity is being added to member joined, so external\n                // services can be notified for that (currently identity is\n                // not used inside library)\n                this.eventEmitter.emit(\n                    XMPPEvents.MUC_MEMBER_JOINED,\n                    from,\n                    member.nick,\n                    member.role,\n                    member.isHiddenDomain,\n                    member.statsID,\n                    member.status,\n                    member.identity,\n                    member.botType,\n                    member.jid,\n                    member.features,\n                    member.isReplaceParticipant,\n                    member.isSilent);\n\n                // we are reporting the status with the join\n                // so we do not want a second event about status update\n                hasStatusUpdate = false;\n            }\n        } else {\n            // Presence update for existing participant\n            // Watch role change:\n            const memberOfThis = this.members[from];\n\n            if (memberOfThis.role !== member.role) {\n                memberOfThis.role = member.role;\n                this.eventEmitter.emit(\n                    XMPPEvents.MUC_ROLE_CHANGED, from, member.role);\n            }\n\n            // affiliation changed\n            if (memberOfThis.affiliation !== member.affiliation) {\n                memberOfThis.affiliation = member.affiliation;\n            }\n\n            // fire event that botType had changed\n            if (memberOfThis.botType !== member.botType) {\n                memberOfThis.botType = member.botType;\n                this.eventEmitter.emit(\n                    XMPPEvents.MUC_MEMBER_BOT_TYPE_CHANGED,\n                    from,\n                    member.botType);\n            }\n\n            if (member.isFocus) {\n                // From time to time first few presences of the focus are not\n                // containing it's jid. That way we can mark later the focus\n                // member instead of not marking it at all and not starting the\n                // conference.\n                // FIXME: Maybe there is a better way to handle this issue. It\n                // seems there is some period of time in prosody that the\n                // configuration form is received but not applied. And if any\n                // participant joins during that period of time the first\n                // presence from the focus won't contain\n                // <item jid=\"focus...\" />.\n                // By default we are disabling the waiting for form submission in order to use the room\n                // and we had enabled by default that jids are public in the room ,\n                // so this case should not happen, if public jid is turned off we will receive the jid\n                // when we become moderator in the room\n                memberOfThis.isFocus = true;\n                this._initFocus(from, member.features);\n            }\n\n            // store the new display name\n            if (member.displayName) {\n                memberOfThis.displayName = member.displayName;\n            }\n\n            // join without audio\n            if (member.isSilent) {\n                memberOfThis.isSilent = member.isSilent;\n            }\n\n            // update stored status message to be able to detect changes\n            if (memberOfThis.status !== member.status) {\n                hasStatusUpdate = true;\n                memberOfThis.status = member.status;\n            }\n\n            if (memberOfThis.version !== member.version) {\n                hasVersionUpdate = true;\n                memberOfThis.version = member.version;\n            }\n\n            if (!isEqual(memberOfThis.features, member.features)) {\n                memberOfThis.features = member.features;\n                this.eventEmitter.emit(XMPPEvents.PARTICIPANT_FEATURES_CHANGED, from, member.features);\n            }\n        }\n\n        const participantProperties = new Map();\n\n        // after we had fired member or room joined events, lets fire events\n        // for the rest info we got in presence\n        for (let i = 0; i < nodes.length; i++) {\n            const node = nodes[i];\n\n            switch (node.tagName) {\n            case 'nick':\n                if (!member.isFocus) {\n                    const displayName\n                    // @ts-ignore will fix after xmpp PR merge\n                        = this.xmpp.options.displayJids\n                            ? Strophe.getResourceFromJid(from)\n                            : member.nick;\n\n                    this.eventEmitter.emit(\n                        XMPPEvents.DISPLAY_NAME_CHANGED,\n                        from,\n                        displayName);\n                }\n                break;\n            case 'silent':\n                this.eventEmitter.emit(\n                    XMPPEvents.SILENT_STATUS_CHANGED,\n                    from,\n                    member.isSilent);\n                break;\n            case 'bridgeNotAvailable':\n                if (member.isFocus && !this.noBridgeAvailable) {\n                    this.noBridgeAvailable = true;\n                    this.eventEmitter.emit(XMPPEvents.BRIDGE_DOWN);\n                }\n                break;\n            case 'conference-properties':\n                if (member.isFocus) {\n                    const properties = {};\n\n                    for (let j = 0; j < node.children.length; j++) {\n                        const { attributes } = node.children[j];\n\n                        if (attributes?.key) {\n                            properties[attributes.key] = attributes.value;\n                        }\n                    }\n\n                    this.eventEmitter.emit(XMPPEvents.CONFERENCE_PROPERTIES_CHANGED, properties);\n                }\n                break;\n            case 'transcription-status': {\n                const { attributes } = node;\n\n                if (!attributes) {\n                    break;\n                }\n\n                const { status } = attributes;\n\n                if (status && status !== this.transcriptionStatus\n                    && member.isHiddenDomain && member.features.has(FEATURE_TRANSCRIBER)) {\n                    this.transcriptionStatus = status;\n                    this.eventEmitter.emit(\n                        XMPPEvents.TRANSCRIPTION_STATUS_CHANGED,\n                        status,\n                        Strophe.getResourceFromJid(from)\n                    );\n                }\n\n                break;\n            }\n            case 'call-control': {\n                const att = node.attributes;\n\n                if (!att) {\n                    break;\n                }\n                this.phoneNumber = att.phone || null;\n                this.phonePin = att.pin || null;\n                this.eventEmitter.emit(XMPPEvents.PHONE_NUMBER_CHANGED);\n                break;\n            }\n            case 'etherpad':\n                if (member.isFocus) {\n                    this._processNode(node, from);\n                }\n                break;\n            default: {\n                if (node.tagName.startsWith('jitsi_participant_')) {\n                    participantProperties\n                        .set(node.tagName.substring('jitsi_participant_'.length), node.value);\n                } else {\n                    this._processNode(node, from);\n                }\n            }\n            }\n        }\n\n        // All participant properties are in `participantProperties`, call the event handlers now.\n        const participantId = Strophe.getResourceFromJid(from);\n\n        for (const [ key, value ] of participantProperties) {\n            this.participantPropertyListener(participantId, key, value);\n        }\n\n        // Trigger status message update if necessary\n        if (hasStatusUpdate) {\n            this.eventEmitter.emit(\n                XMPPEvents.PRESENCE_STATUS,\n                from,\n                member.status);\n        }\n\n        if (hasVersionUpdate) {\n            logger.info(`Received version for ${jid}: ${member.version}`);\n        }\n    }\n\n    /**\n     * Sets the special listener to be used for \"command\"s whose name starts\n     * with \"jitsi_participant_\".\n     */\n    public setParticipantPropertyListener(listener: ParticipantPropertyListener): void {\n        this.participantPropertyListener = listener;\n    }\n\n    /**\n     * Send text message to the other participants in the conference\n     * @param message\n     * @param elementName\n     * @param replyToId\n     * @param messageId - Optional explicit stanza id\n     */\n    public sendMessage(message: string, elementName: string, replyToId?: string, messageId?: string): void {\n        const attrs: Record<string, string> = {\n            to: this.roomjid,\n            type: 'groupchat'\n        };\n\n        if (messageId) {\n            attrs.id = messageId;\n        }\n\n        const msg = $msg(attrs);\n\n        const cleanMessage = stripXMLInvalidChars(message);\n\n        let sentMessage = cleanMessage;\n\n        if (this.encryptionKey) {\n            sentMessage = encryptSymmetricallySync(cleanMessage, this.encryptionKey);\n        }\n\n        // We are adding the message in a packet extension. If this element\n        // is different from 'body', we add a custom namespace.\n        // e.g. for 'json-message' extension of message stanza.\n        if (elementName === 'body') {\n            msg.c(elementName, {}, sentMessage);\n        } else {\n            msg.c(elementName, { xmlns: 'http://jitsi.org/jitmeet' }, sentMessage);\n        }\n\n        if (replyToId) {\n            msg.up().c('reply', { to: replyToId });\n        }\n\n        this.connection.send(msg);\n        this.eventEmitter.emit(XMPPEvents.SENDING_CHAT_MESSAGE, sentMessage);\n    }\n\n    /**\n     * Sends a reaction message to the other participants in the conference.\n     * @param {string} reaction - The reaction being sent.\n     * @param {string} messageId - The id of the message being sent.\n     * @param {string} receiverId - The receiver of the message if it is private.\n     */\n    public sendReaction(reaction: string, messageId: string, receiverId?: string): void {\n        const m = reaction.match(EMOJI_REGEX);\n\n        if (!m?.[0]) {\n            throw new Error(`Invalid reaction: ${reaction}`);\n        }\n\n        // Adds the 'to' attribute depending on if the message is private or not.\n        const msg = receiverId ? $msg({ to: `${this.roomjid}/${receiverId}`,\n            type: 'chat' }) : $msg({ to: this.roomjid,\n            type: 'groupchat' });\n\n        msg.c('reactions', { id: messageId,\n            xmlns: 'urn:xmpp:reactions:0' })\n            .c('reaction', {}, m[0])\n            .up().c('store', { xmlns: 'urn:xmpp:hints' });\n\n        this.connection.send(msg);\n    }\n\n    /* eslint-disable max-params */\n    /**\n     * Send private text message to another participant of the conference\n     * @param id id/muc resource of the receiver\n     * @param message\n     * @param elementName\n     * @param useDirectJid\n     * @param replyToId\n     * @param messageId\n     */\n    public sendPrivateMessage(id: string, message: string, elementName: string, useDirectJid: boolean = false, replyToId?: string, messageId?: string): void {\n        const targetJid = useDirectJid ? id : `${this.roomjid}/${id}`;\n        const attrs: Record<string, string> = { to: targetJid, type: 'chat' };\n\n        if (messageId) {\n            attrs.id = messageId;\n        }\n        const msg = $msg(attrs);\n\n        const cleanMessage = stripXMLInvalidChars(message);\n\n        // We are adding the message in packet. If this element is different\n        // from 'body', we add our custom namespace for the same.\n        // e.g. for 'json-message' message extension.\n        if (elementName === 'body') {\n            msg.c(elementName, cleanMessage).up();\n        } else {\n            msg.c(elementName, { xmlns: 'http://jitsi.org/jitmeet' }, cleanMessage)\n                .up();\n        }\n\n        if (replyToId) {\n            msg.c('reply', { to: replyToId });\n        }\n        this.connection.send(msg);\n        this.eventEmitter.emit(\n            XMPPEvents.SENDING_PRIVATE_CHAT_MESSAGE, cleanMessage);\n    }\n\n    /**\n     * Retracts a previously sent message.\n     *\n     * @param {string} messageId - The id of the message being retracted.\n     * @param {string} receiverId - The receiver if the message was private.\n     * @param {boolean} useDirectJid - Whether receiverId is already a JID.\n     */\n    public sendMessageRetraction(\n            messageId: string,\n            receiverId?: string,\n            useDirectJid: boolean = false): void {\n\n        if (!messageId) {\n            logger.warn('sendMessageRetraction: no messageId provided');\n\n            return;\n        }\n\n        let msg;\n\n        if (receiverId) {\n            const targetJid = useDirectJid\n                ? receiverId\n                : `${this.roomjid}/${receiverId}`;\n\n            msg = $msg({\n                to: targetJid,\n                type: 'chat'\n            });\n        } else {\n            msg = $msg({\n                to: this.roomjid,\n                type: 'groupchat'\n            });\n        }\n\n        msg.c('retract', {\n            id: messageId,\n            xmlns: 'urn:xmpp:message-retract:1'\n        })\n        .up()\n        .c('fallback', {\n            for: 'urn:xmpp:message-retract:1',\n            xmlns: 'urn:xmpp:fallback:0'\n        })\n        .up()\n        .c('body')\n        .t('I retracted a previous message, but it\\'s unsupported by your client.')\n        .up()\n        .c('store', {\n            xmlns: 'urn:xmpp:hints'\n        })\n        .up();\n\n        this.connection.send(msg);\n    }\n\n    /* eslint-enable max-params */\n\n    /**\n     *\n     * @param subject\n     */\n    public setSubject(subject: string): void {\n        const valueToProcess = subject ? stripXMLInvalidChars(subject.trim()) : subject;\n\n        if (valueToProcess === this.subject) {\n            // subject already set to the new value\n            return;\n        }\n\n        const msg = $msg({ to: this.roomjid,\n            type: 'groupchat' });\n\n        msg.c('subject', valueToProcess);\n        this.subject = valueToProcess;\n        this.connection.send(msg);\n    }\n\n    /**\n     * Sends a moderation request to retract a message.\n     *\n     * @param {string} messageId - The id of the message to moderate.\n     * @param {string} [reason] - Optional moderation reason.\n     */\n    public moderateMessage(messageId: string, reason?: string): void {\n        const msg = $msg({\n            to: this.roomjid,\n            type: 'groupchat'\n        });\n\n        msg.c('apply-to', {\n            id: messageId,\n            xmlns: 'urn:xmpp:fasten:0'\n        })\n            .c('moderated', {\n                xmlns: 'urn:xmpp:message-moderate:1'\n            })\n            .c('retract', {\n                xmlns: 'urn:xmpp:message-retract:1'\n            })\n            .up();\n\n        if (reason) {\n            msg.c('reason', {}, reason).up();\n        }\n\n        this.connection.send(msg);\n    }\n\n    /**\n     *\n     * @param pres\n     * @param from\n     * @internal\n     */\n    onPresenceUnavailable(pres: Element, from: string): boolean {\n        // ignore presence\n        // Use *|xmlns to match xmlns attributes across any namespace (CSS Selectors Level 3)\n        if (exists(pres, ':scope>ignore[*|xmlns=\"http://jitsi.org/jitmeet/\"]')) {\n            return true;\n        }\n\n        // room destroyed ?\n        // Use *|xmlns to match xmlns attributes across any namespace (CSS Selectors Level 3)\n        const destroySelect = findFirst(pres, ':scope>x[*|xmlns=\"http://jabber.org/protocol/muc#user\"]>destroy');\n\n        if (destroySelect) {\n            let reason;\n            const reasonSelect = findFirst(pres, ':scope>x[*|xmlns=\"http://jabber.org/protocol/muc#user\"]>destroy>reason');\n\n            if (reasonSelect) {\n                reason = getText(reasonSelect);\n            }\n\n            this.eventEmitter.emit(XMPPEvents.MUC_DESTROYED, reason, getAttribute(destroySelect, 'jid'));\n            this.connection.emuc.doLeave(this.roomjid);\n\n            return true;\n        }\n\n        // Status code 110 indicates that this notification is \"self-presence\".\n        const isSelfPresence = exists(pres, ':scope>x[*|xmlns=\"http://jabber.org/protocol/muc#user\"]>status[code=\"110\"]');\n        const isKick = exists(pres, ':scope>x[*|xmlns=\"http://jabber.org/protocol/muc#user\"]>status[code=\"307\"]');\n        const membersKeys = Object.keys(this.members);\n        const isReplaceParticipant = exists(pres, 'flip_device');\n\n        if (isKick) {\n            const actorSelect = findFirst(pres, ':scope>x[*|xmlns=\"http://jabber.org/protocol/muc#user\"]>item>actor');\n            let actorNick;\n\n            if (actorSelect) {\n                actorNick = getAttribute(actorSelect, 'nick');\n            }\n\n            let reason;\n            const reasonSelect = findFirst(pres, ':scope>x[*|xmlns=\"http://jabber.org/protocol/muc#user\"]>item>reason');\n\n            if (reasonSelect) {\n                reason = getText(reasonSelect);\n            }\n\n            logger.info(`Kicked by ${from}`);\n\n            // we first fire the kicked so we can show the participant\n            // who kicked, before notifying that participant left\n            // we fire kicked for us and for any participant kicked\n            this.eventEmitter.emit(\n                XMPPEvents.KICKED,\n                isSelfPresence,\n                actorNick,\n                Strophe.getResourceFromJid(from),\n                reason,\n                isReplaceParticipant);\n        }\n\n        if (isSelfPresence) {\n            // If the status code is 110 this means we're leaving and we would\n            // like to remove everyone else from our view, so we trigger the\n            // event.\n            membersKeys.forEach(jid => {\n                const member = this.members[jid];\n\n                delete this.members[jid];\n                delete this.lastPresences[jid];\n                if (!member.isFocus) {\n                    this.eventEmitter.emit(XMPPEvents.MUC_MEMBER_LEFT, jid);\n                }\n            });\n            this.connection.emuc.doLeave(this.roomjid);\n\n            // we fire muc_left only if this is not a kick,\n            // kick has both statuses 110 and 307.\n            if (!isKick) {\n                this.eventEmitter.emit(XMPPEvents.MUC_LEFT);\n            }\n        } else {\n            const reasonSelect = findFirst(pres, ':scope>status');\n            const member = this.members[from];\n            let reason;\n\n            if (reasonSelect) {\n                reason = getText(reasonSelect);\n            }\n\n            delete this.members[from];\n            delete this.lastPresences[from];\n\n            // In this case we *do* fire MUC_MEMBER_LEFT for the focus?\n            this.eventEmitter.emit(XMPPEvents.MUC_MEMBER_LEFT, from, reason);\n\n            if (member && member.isHiddenDomain && member.features.has(FEATURE_TRANSCRIBER)\n                && this.transcriptionStatus !== JitsiTranscriptionStatus.OFF) {\n                this.transcriptionStatus = JitsiTranscriptionStatus.OFF;\n                this.eventEmitter.emit(\n                    XMPPEvents.TRANSCRIPTION_STATUS_CHANGED,\n                    this.transcriptionStatus,\n                    Strophe.getResourceFromJid(from),\n                    true /* exited abruptly */\n                );\n            }\n\n            if (member?.isFocus) {\n                logger.info('Focus has left the room - leaving conference');\n                this.eventEmitter.emit(XMPPEvents.FOCUS_LEFT);\n            }\n        }\n    }\n\n    /**\n     *\n     * @param msg\n     * @param from\n     * @internal\n     */\n    onMessage(msg: Element, from: string): boolean {\n        const type = msg.getAttribute('type');\n\n        if (type === 'error') {\n            const settingsErrorEl = findAll(msg, ':scope>settings-error>text');\n            const settingsErrorMsg = settingsErrorEl.length ? getText(settingsErrorEl[0]) : '';\n\n            if (settingsErrorMsg.length) {\n                this.eventEmitter.emit(XMPPEvents.SETTINGS_ERROR_RECEIVED, settingsErrorMsg);\n\n                return true;\n            }\n            const errorEl = findAll(msg, ':scope>error>text');\n            const errorMsg = errorEl.length ? getText(errorEl[0]) : '';\n\n            this.eventEmitter.emit(XMPPEvents.CHAT_ERROR_RECEIVED, errorMsg);\n\n            return true;\n        }\n\n        const reactions = findAll(msg, ':scope>[*|xmlns=\"urn:xmpp:reactions:0\"]>reaction');\n\n        if (reactions.length > 0) {\n            const messageId = getAttribute(findFirst(msg, ':scope>[*|xmlns=\"urn:xmpp:reactions:0\"]'), 'id');\n            const reactionList = [];\n\n            reactions.forEach(reactionElem => {\n                const reaction = getText(reactionElem);\n                const m = reaction.match(EMOJI_REGEX);\n\n                // Only allow one reaction per <reaction> element.\n                if (m?.[0]) {\n                    reactionList.push(m[0]);\n                }\n            });\n\n            if (reactionList.length > 0) {\n                this.eventEmitter.emit(XMPPEvents.REACTION_RECEIVED, from, reactionList, messageId);\n            }\n\n            return true;\n        }\n\n\n        const bodyEl = findFirst(msg, ':scope>body');\n        const txt = bodyEl ? getText(bodyEl) : '';\n        const subject = findFirst(msg, ':scope>subject');\n\n        if (subject) {\n            const subjectText = getText(subject);\n\n            if (subjectText || subjectText === '') {\n                this.subject = subjectText.trim();\n                this.eventEmitter.emit(XMPPEvents.SUBJECT_CHANGED, subjectText);\n                logger.info(`Subject is changed to ${subjectText}`);\n            }\n        }\n\n        // xep-0203 delay\n        const delayEl = findFirst(msg, ':scope>delay');\n        let stamp = getAttribute(delayEl, 'stamp');\n\n        if (!stamp) {\n            // or xep-0091 delay, UTC timestamp\n            // Use *|xmlns to match xmlns attributes across any namespace (CSS Selectors Level 3)\n            stamp = getAttribute(findFirst(msg, ':scope>[*|xmlns=\"jabber:x:delay\"]'), 'stamp');\n\n            if (stamp) {\n                // the format is CCYYMMDDThh:mm:ss\n                const dateParts = stamp.match(/(\\d{4})(\\d{2})(\\d{2}T\\d{2}:\\d{2}:\\d{2})/);\n\n                if (dateParts?.length === 4) {\n                    stamp = `${dateParts[1]}-${dateParts[2]}-${dateParts[3]}Z`;\n                }\n            }\n        }\n\n        if (from === this.roomjid) {\n            let invite;\n\n            // Use *|xmlns to match xmlns attributes across any namespace (CSS Selectors Level 3)\n            if (exists(msg, ':scope>x[*|xmlns=\"http://jabber.org/protocol/muc#user\"]>status[code=\"104\"]')) {\n                this.discoRoomInfo();\n            } else if (invite = findFirst(msg, ':scope>x[*|xmlns=\"http://jabber.org/protocol/muc#user\"]>invite')) {\n                const passwordSelect = findFirst(msg, ':scope>x[*|xmlns=\"http://jabber.org/protocol/muc#user\"]>password');\n                let password;\n\n                if (passwordSelect) {\n                    password = getText(passwordSelect);\n                }\n\n                this.eventEmitter.emit(XMPPEvents.INVITE_MESSAGE_RECEIVED,\n                    from, getAttribute(invite, 'from'), txt, password);\n            }\n        }\n\n        // Use *|xmlns to match xmlns attributes across any namespace (CSS Selectors Level 3)\n        const jsonMessage = getText(findFirst(msg, ':scope>json-message[*|xmlns=\"http://jitsi.org/jitmeet\"]'));\n\n        if (jsonMessage) {\n            const parsedJson = this.xmpp.tryParseJSONAndVerify(jsonMessage);\n\n            // We emit this event if the message is a valid json, and is not\n            // delivered after a delay, i.e. stamp is null.\n            // e.g. - subtitles should not be displayed if delayed.\n            if (parsedJson && stamp === null) {\n                this.eventEmitter.emit(XMPPEvents.JSON_MESSAGE_RECEIVED,\n                    from, parsedJson, stamp !== null);\n\n                return;\n            }\n        }\n\n        const applyToEl = findFirst(msg, ':scope>apply-to[*|xmlns=\"urn:xmpp:fasten:0\"]');\n\n        if (applyToEl) {\n            const moderatedEl = findFirst(applyToEl, ':scope>moderated[*|xmlns=\"urn:xmpp:message-moderate:1\"]');\n\n            if (moderatedEl) {\n                const retractEl = findFirst(moderatedEl, ':scope>retract[*|xmlns=\"urn:xmpp:message-retract:1\"]');\n\n                if (retractEl) {\n                    const messageId = getAttribute(applyToEl, 'id');\n                    const moderator = getAttribute(moderatedEl, 'by');\n                    const reason = getText(findFirst(moderatedEl, 'reason'));\n\n                    this.eventEmitter.emit(XMPPEvents.MESSAGE_MODERATED, messageId, moderator, reason);\n\n                    return true;\n                }\n            }\n        }\n\n        const retractEl = findFirst(msg, ':scope>retract[*|xmlns=\"urn:xmpp:message-retract:1\"]');\n\n        if (retractEl) {\n            const retractedMessageId = getAttribute(retractEl, 'id');\n\n            if (!retractedMessageId) {\n                logger.warn('MESSAGE_RETRACTED: missing retracted message id');\n\n                return true;\n\n            }\n\n            this.eventEmitter.emit(XMPPEvents.MESSAGE_RETRACTED,\n                from, retractedMessageId);\n\n            return true;\n        }\n\n        if (txt) {\n            const messageId = getAttribute(msg, 'id') || uuidv4();\n            const replyToId = this._parseReplyMessage(msg);\n            const displayNameEl = findFirst(msg, ':scope>display-name[*|xmlns=\"http://jitsi.org/protocol/display-name\"]');\n            const isVisitorMessage = getAttribute(displayNameEl, 'source') === 'visitor';\n\n            if (type === 'chat') {\n                let displayName;\n                let originalFrom;\n\n                if (isVisitorMessage) {\n                    displayName = getText(displayNameEl);\n\n                    // Check for original visitor JID in addresses element (XEP-0033)\n                    const addressesEl = findFirst(msg, ':scope>addresses[*|xmlns=\"http://jabber.org/protocol/address\"]');\n\n                    if (addressesEl) {\n                        const ofromEl = findFirst(addressesEl, 'address[type=\"ofrom\"]');\n\n                        if (ofromEl) {\n                            originalFrom = getAttribute(ofromEl, 'jid');\n                        }\n                    }\n                }\n                this.eventEmitter.emit(XMPPEvents.PRIVATE_MESSAGE_RECEIVED,\n                        from, txt, this.myroomjid, stamp, messageId, displayName, isVisitorMessage, originalFrom, replyToId);\n            } else if (type === 'groupchat') {\n                const displayName = displayNameEl ? getText(displayNameEl) : undefined;\n                let sourceAttrValue = getAttribute(displayNameEl, 'source');\n\n                if (sourceAttrValue === null) {\n                    // When displayNameEl[0] doesn't exist or there is no source attribute getAttribute returns null.\n                    // Lets unify the reported values and use undefined instead.\n                    sourceAttrValue = undefined;\n                }\n                const source = isVisitorMessage ? undefined : sourceAttrValue;\n\n                if (this.options.isChatEncrypted && !this.encryptionKey) {\n                    this.pendingEncryptedMessages.push({\n                        displayName,\n                        from,\n                        isVisitorMessage,\n                        messageId,\n                        replyToId,\n                        source,\n                        stamp,\n                        txt,\n                    });\n\n                    return;\n                }\n\n                const chatMessage = this.encryptionKey ? decryptSymmetricallySync(txt, this.encryptionKey) : txt;\n\n                // we will fire explicitly that this is a visitor(isVisitor:true) to the conference\n                // a message with explicit name set\n                this.eventEmitter.emit(XMPPEvents.MESSAGE_RECEIVED,\n                    from, chatMessage, this.myroomjid, stamp, displayName, isVisitorMessage, messageId, source, replyToId);\n            }\n        }\n    }\n\n    /**\n     *\n     * @param pres\n     * @param from\n     * @internal\n     */\n    onPresenceError(pres: Element, from: string): void {\n        let errorDescriptionNode;\n\n        if (from === this.myroomjid) {\n            // we have tried to join, and we received an error, let's send again conference-iq on next attempt\n            // as it may turn out that jicofo left the room if we were the first to try,\n            // and the user delayed the attempt for entering the password or such\n            this.xmpp.moderator.conferenceRequestSent = false;\n        }\n\n        // Use *|xmlns to match xmlns attributes across any namespace (CSS Selectors Level 3)\n        if (exists(pres, ':scope>error[type=\"auth\"]>not-authorized[*|xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\"]')) {\n            logger.debug('on password required', from);\n            this.eventEmitter.emit(XMPPEvents.PASSWORD_REQUIRED);\n        } else if (exists(pres,\n            ':scope>error[type=\"cancel\"]>not-allowed[*|xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\"]')) {\n            const toDomain = Strophe.getDomainFromJid(pres.getAttribute('to'));\n\n            // @ts-ignore will fix after xmpp PR merge\n            if (toDomain === this.xmpp.options.hosts.anonymousdomain) {\n                // enter the room by replying with 'not-authorized'. This would\n                // result in reconnection from authorized domain.\n                // We're either missing Jicofo/Prosody config for anonymous\n                // domains or something is wrong.\n                this.eventEmitter.emit(XMPPEvents.ROOM_JOIN_ERROR);\n\n            } else {\n                logger.warn('onPresError ', pres);\n\n                const txtNode = findFirst(pres,\n                    ':scope>error[type=\"cancel\"]>text[*|xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\"]');\n                const txt = getText(txtNode);\n                let type = AUTH_ERROR_TYPES.GENERAL;\n\n                // a race where we have sent a conference request to jicofo and jicofo was about to leave or just left\n                // because of no participants in the room, and we tried to create the room, without having\n                // permissions for that (only jicofo creates rooms)\n                if (txt === 'Room creation is restricted'\n                    // or case when using jwt, where we connected and then lost connection and restored it\n                    // and failed to join the call before jicofo leaves,\n                    // or send a conference-request and got a connection problem before joining but jicofo already left\n                    || exists(pres,\n                        ':scope>error[type=\"cancel\"]>room-does-not-exist[*|xmlns=\"http://jitsi.org/jitmeet\"]')) {\n                    type = AUTH_ERROR_TYPES.ROOM_CREATION_RESTRICTION;\n\n                    if (!this.options.disableRoomCreationRetry) {\n                        if (!this._roomCreationRetries) {\n                            this._roomCreationRetries = 0;\n                        }\n                        this._roomCreationRetries++;\n\n                        if (this._roomCreationRetries <= 3) {\n                            const retryDelay = getJitterDelay(\n                                /* retry */ this._roomCreationRetries,\n                                /* minDelay */ 500,\n                                1.5);\n\n                            // let's retry inviting jicofo and joining the room, retries will take between 1 and 3 seconds\n                            setTimeout(() => this.join(this.password, this.replaceParticipant), retryDelay);\n\n                            return;\n                        }\n                    }\n                } else if (exists(pres,\n                    ':scope>error[type=\"cancel\"]>authentication-required[*|xmlns=\"http://jitsi.org/jitmeet\"]')) {\n                    type = AUTH_ERROR_TYPES.ROOM_UNAUTHENTICATED_ACCESS_DISABLED;\n                } else if (exists(pres,\n                    ':scope>error[type=\"cancel\"]>no-main-participants[*|xmlns=\"jitsi:visitors\"]')) {\n                    type = AUTH_ERROR_TYPES.NO_MAIN_PARTICIPANTS;\n                } else if (exists(pres,\n                    ':scope>error[type=\"cancel\"]>promotion-not-allowed[*|xmlns=\"jitsi:visitors\"]')) {\n                    type = AUTH_ERROR_TYPES.PROMOTION_NOT_ALLOWED;\n                } else if (exists(pres,\n                    ':scope>error[type=\"cancel\"]>no-visitors-lobby[*|xmlns=\"jitsi:visitors\"]')) {\n                    type = AUTH_ERROR_TYPES.NO_VISITORS_LOBBY;\n                }\n\n                // A breakout room refusing our own (re)join presence with a generic\n                // not-allowed. This happens on reconnect when our session is no longer a\n                // member of the breakout. Don't surface a hard CONFERENCE_FAILED (\"you do\n                // not have permission to join the call\") - route the user back to the main\n                // room via the normal move-to-room flow instead.\n                if (type === AUTH_ERROR_TYPES.GENERAL\n                        && from === this.myroomjid\n                        && this.getBreakoutRooms()?.isBreakoutRoom()) {\n                    const mainRoomJid = this.getBreakoutRooms().getMainRoomJid();\n\n                    if (mainRoomJid) {\n                        logger.warn(`Breakout join not-allowed for ${from}; moving back to main room ${mainRoomJid}`);\n                        this.eventEmitter.emit(XMPPEvents.BREAKOUT_ROOMS_MOVE_TO_ROOM, mainRoomJid);\n\n                        return;\n                    }\n                }\n\n                this.eventEmitter.emit(XMPPEvents.ROOM_CONNECT_NOT_ALLOWED_ERROR, type, txt);\n            }\n        } else if (exists(pres, ':scope>error>service-unavailable')) {\n            logger.warn('Maximum users limit for the room has been reached',\n                pres);\n            this.eventEmitter.emit(XMPPEvents.ROOM_MAX_USERS_ERROR, {\n                visitorsSupported: this.xmpp.moderator.visitorsSupported\n            });\n        } else if (exists(pres,\n            ':scope>error[type=\"auth\"]>registration-required[*|xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\"]')) {\n\n            // let's extract the lobby jid from the custom field\n            const lobbyRoomNode = findFirst(pres, ':scope>error[type=\"auth\"]>lobbyroom');\n            let lobbyRoomJid;\n\n            if (lobbyRoomNode) {\n                lobbyRoomJid = getText(lobbyRoomNode);\n            }\n\n            const waitingForHost = exists(pres, ':scope>error[type=\"auth\"]>waiting-for-host');\n\n            this.eventEmitter.emit(XMPPEvents.ROOM_CONNECT_MEMBERS_ONLY_ERROR, lobbyRoomJid, waitingForHost);\n        } else if (errorDescriptionNode = findFirst(pres,\n            ':scope>error[type=\"modify\"]>displayname-required[*|xmlns=\"http://jitsi.org/jitmeet\"]')) {\n            logger.warn('display name required ', pres);\n            this.eventEmitter.emit(XMPPEvents.DISPLAY_NAME_REQUIRED, getAttribute(errorDescriptionNode, 'lobby'));\n        } else {\n            logger.warn('onPresError ', pres);\n            this.eventEmitter.emit(XMPPEvents.ROOM_CONNECT_ERROR);\n        }\n    }\n\n    /**\n     *\n     * @param jid\n     * @param affiliation\n     */\n    public setAffiliation(jid: string, affiliation: string): void {\n        const grantIQ = $iq({\n            to: this.roomjid,\n            type: 'set'\n        })\n        .c('query', { xmlns: 'http://jabber.org/protocol/muc#admin' })\n        .c('item', {\n            affiliation,\n            jid: Strophe.getBareJidFromJid(jid)\n        })\n        .c('reason').t(`Your affiliation has been changed to '${affiliation}'.`)\n        .up().up().up();\n\n        this.connection.sendIQ(\n            grantIQ,\n            result => logger.info('Set affiliation of participant with jid: ', jid, 'to', affiliation, result),\n            error => {\n                handleStropheError(error, {\n                    affiliation,\n                    operation: 'set affiliation of participant',\n                    participantJid: jid,\n                    roomJid: this.roomjid,\n                    userJid: this.connection.jid\n                });\n            });\n    }\n\n    /**\n     *\n     * @param jid\n     * @param reason\n     */\n    public kick(jid: string, reason: string = 'You have been kicked.'): void {\n        const kickIQ = $iq({ to: this.roomjid,\n            type: 'set' })\n            .c('query', { xmlns: 'http://jabber.org/protocol/muc#admin' })\n            .c('item', { nick: Strophe.getResourceFromJid(jid),\n                role: 'none' })\n            .c('reason').t(reason).up().up().up();\n\n        this.connection.sendIQ(\n            kickIQ,\n            result => logger.info('Kick participant with jid: ', jid, result),\n            error => {\n                handleStropheError(error, {\n                    operation: 'kick participant',\n                    participantJid: jid,\n                    reason,\n                    roomJid: this.roomjid,\n                    userJid: this.connection.jid\n                });\n            }, undefined);\n    }\n\n    /* eslint-disable max-params */\n\n    /**\n     *\n     * @param key\n     * @param onSuccess\n     * @param onError\n     * @param onNotSupported\n     */\n    public lockRoom(key: Nullable<string>, onSuccess: SuccessCallback, onError: ErrorCallback, onNotSupported: () => void): void {\n        // http://xmpp.org/extensions/xep-0045.html#roomconfig\n        this.connection.sendIQ(\n            $iq({\n                to: this.roomjid,\n                type: 'get'\n            })\n                .c('query', { xmlns: 'http://jabber.org/protocol/muc#owner' }),\n            res => {\n                // Use *|xmlns to match xmlns attributes across any namespace (CSS Selectors Level 3)\n                if (exists(res,\n                    ':scope>query>x[*|xmlns=\"jabber:x:data\"]>field[var=\"muc#roomconfig_roomsecret\"]')) {\n                    const formsubmit\n                        = $iq({\n                            to: this.roomjid,\n                            type: 'set'\n                        })\n                            .c('query', {\n                                xmlns: 'http://jabber.org/protocol/muc#owner'\n                            });\n\n                    formsubmit.c('x', {\n                        type: 'submit',\n                        xmlns: 'jabber:x:data'\n                    });\n                    formsubmit\n                        .c('field', { 'var': 'FORM_TYPE' })\n                        .c('value')\n                        .t('http://jabber.org/protocol/muc#roomconfig')\n                        .up()\n                        .up();\n                    formsubmit\n                        .c('field', { 'var': 'muc#roomconfig_roomsecret' })\n                        .c('value')\n                        .t(key)\n                        .up()\n                        .up();\n                    formsubmit\n                        .c('field',\n                             { 'var': 'muc#roomconfig_passwordprotectedroom' })\n                        .c('value')\n                        .t(key === null || key.length === 0 ? '0' : '1')\n                        .up()\n                        .up();\n\n                    // if members only enabled\n                    if (this.membersOnlyEnabled) {\n                        formsubmit\n                            .c('field', { 'var': 'muc#roomconfig_membersonly' })\n                            .c('value')\n                            .t('true')\n                            .up()\n                            .up();\n                    }\n\n                    // Fixes a bug in prosody 0.9.+\n                    // https://prosody.im/issues/issue/373\n                    formsubmit\n                        .c('field', { 'var': 'muc#roomconfig_whois' })\n                        .c('value')\n                        .t('anyone')\n                        .up()\n                        .up();\n\n                    this.connection.sendIQ(\n                        formsubmit,\n                        () => {\n\n                            // we set the password in chat room so we can use it\n                            // later when dialing out\n                            this.password = key;\n                            onSuccess();\n                        },\n                        error => {\n                            handleStropheError(error, {\n                                operation: 'lock room (submit form)',\n                                roomJid: this.roomjid,\n                                userJid: this.connection.jid\n                            });\n                            onError(error);\n                        });\n                } else {\n                    onNotSupported();\n                }\n            },\n            error => {\n                handleStropheError(error, {\n                    operation: 'lock room (get configuration)',\n                    roomJid: this.roomjid,\n                    userJid: this.connection.jid\n                });\n                onError(error);\n            });\n    }\n\n    /* eslint-enable max-params */\n\n    /**\n     * Turns off or on the members only config for the main room.\n     *\n     * @param {boolean} enabled - Whether to turn it on or off.\n     * @param onSuccess - optional callback.\n     * @param onError - optional callback.\n     */\n    public setMembersOnly(enabled: boolean, onSuccess: SuccessCallback, onError: ErrorCallback): void {\n        if (enabled && Object.values(this.members).filter(m => !m.isFocus).length) {\n            // first grant membership to all that are in the room\n            const affiliationsIq = $iq({\n                to: this.roomjid,\n                type: 'set' })\n                .c('query', {\n                    xmlns: 'http://jabber.org/protocol/muc#admin' });\n            let sendIq = false;\n\n            Object.values(this.members).forEach(m => {\n                if (m.jid && !MEMBERS_AFFILIATIONS.includes(m.affiliation)) {\n                    affiliationsIq.c('item', {\n                        'affiliation': 'member',\n                        'jid': Strophe.getBareJidFromJid(m.jid)\n                    }).up();\n                    sendIq = true;\n                }\n            });\n\n            sendIq && this.xmpp.connection.sendIQ(affiliationsIq.up(), undefined, error => {\n                handleStropheError(error, {\n                    operation: 'set members affiliation',\n                    roomJid: this.roomjid,\n                    userJid: this.xmpp.connection.jid\n                });\n            });\n        }\n        // eslint-disable-next-line @typescript-eslint/no-empty-function\n        const errorCallback = onError ? onError : () => {};\n\n        this.xmpp.connection.sendIQ(\n            $iq({\n                to: this.roomjid,\n                type: 'get'\n            }).c('query', { xmlns: 'http://jabber.org/protocol/muc#owner' }),\n            res => {\n                // Use *|xmlns to match xmlns attributes across any namespace (CSS Selectors Level 3)\n                if (exists(res, ':scope>query>x[*|xmlns=\"jabber:x:data\"]>field[var=\"muc#roomconfig_membersonly\"]')) {\n                    const formToSubmit\n                        = $iq({\n                            to: this.roomjid,\n                            type: 'set'\n                        }).c('query', { xmlns: 'http://jabber.org/protocol/muc#owner' });\n\n                    formToSubmit.c('x', {\n                        type: 'submit',\n                        xmlns: 'jabber:x:data'\n                    });\n                    formToSubmit\n                        .c('field', { 'var': 'FORM_TYPE' })\n                        .c('value')\n                        .t('http://jabber.org/protocol/muc#roomconfig')\n                        .up()\n                        .up();\n                    formToSubmit\n                        .c('field', { 'var': 'muc#roomconfig_membersonly' })\n                        .c('value')\n                        .t(enabled ? 'true' : 'false')\n                        .up()\n                        .up();\n\n                    // if room is locked from other participant or we are locking it\n                    if (this.locked) {\n                        formToSubmit\n                            .c('field',\n                                { 'var': 'muc#roomconfig_passwordprotectedroom' })\n                            .c('value')\n                            .t('1')\n                            .up()\n                            .up();\n                    }\n\n                    this.xmpp.connection.sendIQ(formToSubmit, onSuccess, error => {\n                        handleStropheError(error, {\n                            enabled,\n                            operation: 'set members only (submit form)',\n                            roomJid: this.roomjid,\n                            userJid: this.xmpp.connection.jid\n                        });\n                        errorCallback(error);\n                    });\n                } else {\n                    errorCallback(new Error('Setting members only room not supported!'));\n                }\n            },\n            error => {\n                handleStropheError(error, {\n                    enabled,\n                    operation: 'set members only (get configuration)',\n                    roomJid: this.roomjid,\n                    userJid: this.xmpp.connection.jid\n                });\n                errorCallback(error);\n            });\n    }\n\n\n    /**\n     * Adds the key to the presence map, overriding any previous value.\n     * @param key The key to add or replace.\n     * @param values The new values.\n     * @returns {boolean|null} <tt>true</tt> if the operation succeeded or <tt>false</tt> when no add or replace was\n     * performed as the value was already there.\n     * @internal\n     */\n    addOrReplaceInPresence(key: string, values: any): Nullable<boolean> {\n        values.tagName = key;\n\n        const matchingNodes = this.presMap.nodes.filter(node => key === node.tagName);\n\n        // if we have found just one, let's check is it the same\n        if (matchingNodes.length === 1 && isEqual(matchingNodes[0], values)) {\n            return false;\n        }\n\n        this.removeFromPresence(key);\n        this.presMap.nodes.push(values);\n        this.presenceUpdateTime = Date.now();\n\n        return true;\n    }\n\n    /**\n     * Retrieves a value from the presence map.\n     *\n     * @param {string} key - The key to find the value for.\n     * @returns {Object?}\n     * @internal\n     */\n    getFromPresence(key: string): Optional<IPresenceNode> {\n        return this.presMap.nodes.find(node => key === node.tagName);\n    }\n\n    /**\n     * Removes a key from the presence map.\n     * @param key\n     * @internal\n     */\n    removeFromPresence(key: string): void {\n        const nodes = this.presMap.nodes.filter(node => key !== node.tagName);\n\n        this.presMap.nodes = nodes;\n        this.presenceUpdateTime = Date.now();\n    }\n\n    /**\n     *\n     * @param name\n     * @param handler\n     * @internal\n     */\n    addPresenceListener(name: string, handler: PresenceHandler): void {\n        if (typeof handler !== 'function') {\n            throw new Error('\"handler\" is not a function');\n        }\n        let tagHandlers = this.presHandlers[name];\n\n        if (!tagHandlers) {\n            this.presHandlers[name] = tagHandlers = [];\n        }\n        if (tagHandlers.indexOf(handler) === -1) {\n            tagHandlers.push(handler);\n        } else {\n            logger.warn(\n                `Trying to add the same handler more than once for: ${name}`);\n        }\n    }\n\n    /**\n     *\n     * @param name\n     * @param handler\n     * @internal\n     */\n    removePresenceListener(name: string, handler: PresenceHandler): void {\n        const tagHandlers = this.presHandlers[name];\n        const handlerIdx = tagHandlers ? tagHandlers.indexOf(handler) : -1;\n\n        // eslint-disable-next-line no-negated-condition\n        if (handlerIdx !== -1) {\n            tagHandlers.splice(handlerIdx, 1);\n        } else {\n            logger.warn(`Handler for: ${name} was not registered`);\n        }\n    }\n\n    /**\n     * Checks if the user identified by given <tt>mucJid</tt> is the conference\n     * focus.\n     * @param mucJid the full MUC address of the user to be checked.\n     * @returns {boolean|null} <tt>true</tt> if MUC user is the conference focus\n     * or <tt>false</tt> if is not. When given <tt>mucJid</tt> does not exist in\n     * the MUC then <tt>null</tt> is returned.\n     */\n    public isFocus(mucJid: string): Nullable<boolean> {\n        const member = this.members[mucJid];\n\n        if (member) {\n            return member.isFocus;\n        }\n\n        return null;\n    }\n\n    /**\n     *\n     */\n    public isModerator(): boolean {\n        return this.role === 'moderator';\n    }\n\n    /**\n     * Obtains the info about given media advertised (in legacy format) in the MUC presence of the participant\n     * identified by the given endpoint JID. This is for mantining interop with endpoints that do not support\n     * source-name signaling (Jigasi and very old mobile clients).\n     *\n     * @param {string} endpointId the endpoint ID mapped to the participant which corresponds to MUC nickname.\n     * @param {MediaType} mediaType the type of the media for which presence info will be obtained.\n     * @return {PeerMediaInfo} presenceInfo an object with media presence info or <tt>null</tt> either if there\n     * is no presence available or if the media type given is invalid.\n     */\n    public getMediaPresenceInfo(endpointId: string, mediaType: MediaType): Nullable<IPeerMediaInfo> {\n        // Will figure out current muted status by looking up owner's presence\n        const pres = this.lastPresences[`${this.roomjid}/${endpointId}`];\n\n        if (!pres) {\n            // No presence available\n            return null;\n        }\n        const data: IPeerMediaInfo = {\n            muted: true, // muted by default\n            videoType: mediaType === MediaType.VIDEO ? VideoType.CAMERA : undefined // 'camera' by default\n        };\n        let mutedNode: Nullable<IPresenceNode[]> = null;\n\n        if (mediaType === MediaType.AUDIO) {\n            mutedNode = filterNodeFromPresenceJSON(pres, 'audiomuted');\n        } else if (mediaType === MediaType.VIDEO) {\n            mutedNode = filterNodeFromPresenceJSON(pres, 'videomuted');\n            const codecTypeNode = filterNodeFromPresenceJSON(pres, 'jitsi_participant_codecType');\n            const videoTypeNode = filterNodeFromPresenceJSON(pres, 'videoType');\n\n            if (videoTypeNode.length > 0) {\n                data.videoType = videoTypeNode[0].value;\n            }\n            if (codecTypeNode.length > 0) {\n                data.codecType = codecTypeNode[0].value;\n            }\n        } else {\n            logger.error(`Unsupported media type: ${mediaType}`);\n\n            return null;\n        }\n\n        if (mutedNode.length > 0) {\n            data.muted = mutedNode[0].value === 'true';\n        }\n\n        return data;\n    }\n\n    /**\n     *\n     * @param peerJid\n     */\n    public getMemberRole(peerJid: string): Nullable<string> {\n        if (this.members[peerJid]) {\n            return this.members[peerJid].role;\n        }\n\n        return null;\n    }\n\n    /**\n     * Returns the last presence advertised by a MUC member.\n     * @param {string} mucNick\n     * @returns {*}\n     * @internal\n     */\n    getLastPresence(mucNick: string): Optional<IPresenceNode[]> {\n        return this.lastPresences[`${this.roomjid}/${mucNick}`];\n    }\n\n    /**\n     * Dials a number.\n     * @param number the number\n     */\n    public dial(number: string): Promise<void> {\n        return this.connection.rayo.dial(number, 'fromnumber',\n            Strophe.getBareJidFromJid(this.myroomjid), this.password,\n            this.focusMucJid);\n    }\n\n    /**\n     * Hangup an existing call\n     */\n    public hangup() {\n        return this.connection.rayo.hangup();\n    }\n\n    /**\n     *\n     * @returns {Lobby}\n     */\n    public getLobby(): Optional<Lobby> {\n        return this.lobby;\n    }\n\n    /**\n     * @returns {AVModeration}\n     */\n    public getAVModeration(): AVModeration {\n        return this.avModeration;\n    }\n\n    /**\n     * @returns {BreakoutRooms}\n     */\n    public getBreakoutRooms(): BreakoutRooms {\n        return this.breakoutRooms;\n    }\n\n    /**\n     * @returns {FileSharing}\n     */\n    public getFileSharing(): FileSharing {\n        return this.fileSharing;\n    }\n\n    /**\n     * @returns {RoomMetadata}\n     */\n    public getMetadataHandler(): RoomMetadata {\n        return this.roomMetadata;\n    }\n\n    /**\n     * @returns {Polls}\n     */\n    public getPolls(): Polls {\n        return this.polls;\n    }\n\n    /**\n     * Returns the phone number for joining the conference.\n     */\n    public getPhoneNumber(): Nullable<string> {\n        return this.phoneNumber;\n    }\n\n    /**\n     * Returns the pin for joining the conference with phone.\n     */\n    public getPhonePin(): Nullable<string> {\n        return this.phonePin;\n    }\n\n    /**\n     * Returns the meeting unique ID if any came from backend.\n     *\n     * @returns {string} - The meeting ID.\n     */\n    public getMeetingId(): Optional<string> {\n        return this.meetingId;\n    }\n\n    /**\n     * Mutes remote participant.\n     * @param jid of the participant\n     * @param mute\n     * @param mediaType\n     */\n    public muteParticipant(jid: string, mute: boolean, mediaType: string): void {\n        logger.info('set mute', mute, jid);\n        const iqToFocus = $iq(\n            { to: this.focusMucJid,\n                type: 'set' })\n            .c('mute', {\n                jid,\n                xmlns: `http://jitsi.org/jitmeet/${mediaType}`\n            })\n            .t(mute.toString())\n            .up();\n\n        this.connection.sendIQ(\n            iqToFocus,\n            result => logger.info('set mute', result),\n            error => {\n                handleStropheError(error, {\n                    mediaType,\n                    mute,\n                    operation: 'set mute participant',\n                    participantJid: jid,\n                    roomJid: this.roomjid,\n                    userJid: this.connection.jid\n                });\n            });\n    }\n\n    /**\n     * Handle remote mute reqyest from focus.\n     *\n     * @param iq\n     * @internal\n     */\n    onMute(iq: Element): void {\n        const from = iq.getAttribute('from');\n\n        if (from !== this.focusMucJid) {\n            logger.warn('Ignored mute from non focus peer');\n\n            return;\n        }\n        const mute = findFirst(iq, 'mute');\n\n        if (getText(mute) === 'true') {\n            this.eventEmitter.emit(XMPPEvents.AUDIO_MUTED_BY_FOCUS, getAttribute(mute, 'actor'));\n        } else {\n            // XXX Why do we support anything but muting? Why do we encode the\n            // value in the text of the element? Why do we use a separate XML\n            // namespace?\n            logger.warn('Ignoring a mute request which does not explicitly '\n                + 'specify a positive mute command.');\n        }\n    }\n\n    /**\n     * Handle remote video mute request from focus.\n     *\n     * @param iq\n     * @internal\n     */\n    onMuteVideo(iq: Element): void {\n        const from = iq.getAttribute('from');\n\n        if (from !== this.focusMucJid) {\n            logger.warn('Ignored mute from non focus peer');\n\n            return;\n        }\n        const mute = findFirst(iq, 'mute');\n\n        if (getText(mute) === 'true') {\n            this.eventEmitter.emit(XMPPEvents.VIDEO_MUTED_BY_FOCUS, getAttribute(mute, 'actor'));\n        } else {\n            // XXX Why do we support anything but muting? Why do we encode the\n            // value in the text of the element? Why do we use a separate XML\n            // namespace?\n            logger.warn('Ignoring a mute request which does not explicitly '\n                + 'specify a positive mute command.');\n        }\n    }\n\n    /**\n     * Handle remote desktop sharing mute request from focus.\n     *\n     * @param iq\n     * @internal\n     */\n    onMuteDesktop(iq: Element): void {\n        const from = iq.getAttribute('from');\n\n        if (from !== this.focusMucJid) {\n            logger.warn('Ignored mute from non focus peer');\n\n            return;\n        }\n        const mute = findFirst(iq, 'mute');\n\n        if (getText(mute) === 'true') {\n            this.eventEmitter.emit(XMPPEvents.DESKTOP_MUTED_BY_FOCUS, getAttribute(mute, 'actor'));\n        } else {\n            // XXX Why do we support anything but muting? Why do we encode the\n            // value in the text of the element? Why do we use a separate XML\n            // namespace?\n            logger.warn('Ignoring a mute request which does not explicitly '\n                + 'specify a positive mute command.');\n        }\n    }\n\n    /**\n     * Leaves the room. Closes the jingle session.\n     * @returns {Promise} which is resolved if XMPPEvents.MUC_LEFT is received\n     * less than 5s after sending presence unavailable. Otherwise the promise is\n     * rejected.\n     */\n    public leave(reason?: string): Promise<any> {\n        this.avModeration.dispose();\n        this.breakoutRooms.dispose();\n        this.fileSharing.dispose();\n        this.polls.dispose();\n        this.roomMetadata.dispose();\n\n        const promises = [];\n\n        this.lobby?.lobbyRoom && promises.push(this.lobby.leave());\n\n        promises.push(new Promise((resolve, reject) => {\n            let timeout: number | Timeout = -1;\n\n            const onMucLeft = (doReject = false) => {\n                this.eventEmitter.removeListener(XMPPEvents.MUC_LEFT, onMucLeft);\n                clearTimeout(timeout as number);\n\n                // This will reset the joined flag to false. If we reset it earlier any self presence will be\n                // interpreted as muc join. That's why we reset the flag once we have received presence unavalable\n                // (MUC_LEFT).\n                this.clean();\n\n                if (doReject) {\n                    // The timeout expired. Make sure we clean the EMUC state.\n                    this.connection.emuc.doLeave(this.roomjid);\n                    reject(new Error('The timeout for the confirmation about leaving the room expired.'));\n                } else {\n                    resolve(undefined);\n                }\n            };\n\n            if (this.joined) {\n                timeout = setTimeout(() => onMucLeft(true), 5000);\n                this.eventEmitter.on(XMPPEvents.MUC_LEFT, onMucLeft);\n                this.doLeave(reason);\n            } else {\n                // we are clearing up, and we haven't joined the room\n                // there is no point of sending presence unavailable and check for timeout\n                // let's just clean\n                this.connection.emuc.doLeave(this.roomjid);\n                this.clean();\n                resolve(undefined);\n            }\n        }));\n\n        return Promise.allSettled(promises);\n    }\n\n    /**\n     * Ends the conference for all participants.\n     */\n    public end(): void {\n        if (this.breakoutRooms.isBreakoutRoom()) {\n            logger.warn('Cannot end conference: this is a breakout room.');\n\n            return;\n        }\n\n        // Send the end conference message.\n        const msg = $msg({ to: this.xmpp.endConferenceComponentAddress });\n\n        msg.c('end_conference').up();\n\n        this.xmpp.connection.send(msg);\n    }\n\n    /**\n     * Requests short-lived credentials for a service.\n     * The function does not use anything from the room, but the backend requires the sender\n     * to be in the room as the credentials contain the meeting ID and are valid only for the room.\n     * @param service\n     */\n    public getShortTermCredentials(service: string): Promise<string> {\n        // Gets credentials via xep-0215 and cache it\n        return new Promise((resolve, reject) => {\n            const cachedCredentials = this.cachedShortTermCredentials || {};\n\n            if (cachedCredentials[service]) {\n                resolve(cachedCredentials[service]);\n\n                return;\n            }\n\n            this.connection.sendIQ(\n                $iq({\n                    // @ts-ignore will fix after xmpp PR merge\n                    to: this.xmpp.options.hosts.domain,\n                    type: 'get'\n                })\n                    .c('credentials', { xmlns: 'urn:xmpp:extdisco:2' })\n                    .c('service', {\n                        host: service,\n                        type: 'short-lived-token'\n                    }),\n                res => {\n                    // Use *|xmlns to match xmlns attributes across any namespace (CSS Selectors Level 3)\n                    const resultServiceEl = findFirst(res, ':scope>credentials[*|xmlns=\"urn:xmpp:extdisco:2\"]>service');\n                    const currentDate = new Date();\n                    const expirationDate = new Date(getAttribute(resultServiceEl, 'expires'));\n\n                    cachedCredentials[service] = getAttribute(resultServiceEl, 'password');\n                    this.cachedShortTermCredentials = cachedCredentials;\n\n                    setTimeout(() => {\n                        this.cachedShortTermCredentials[service] = undefined;\n                    }, expirationDate.getTime() - currentDate.getTime() - 10_000);\n\n                    resolve(this.cachedShortTermCredentials[service]);\n                },\n                error => {\n                    handleStropheError(error, {\n                        operation: 'get short term credentials',\n                        roomJid: this.roomjid,\n                        service,\n                        userJid: this.connection.jid\n                    });\n                    reject(error);\n                });\n        });\n    }\n}\n\nexport { ChatRoom };\n\n/* eslint-enable newline-per-chained-call */\n","export default () => {\n\t// https://mths.be/emoji\n\treturn /[#*0-9]\\uFE0F?\\u20E3|[\\xA9\\xAE\\u203C\\u2049\\u2122\\u2139\\u2194-\\u2199\\u21A9\\u21AA\\u231A\\u231B\\u2328\\u23CF\\u23ED-\\u23EF\\u23F1\\u23F2\\u23F8-\\u23FA\\u24C2\\u25AA\\u25AB\\u25B6\\u25C0\\u25FB\\u25FC\\u25FE\\u2600-\\u2604\\u260E\\u2611\\u2614\\u2615\\u2618\\u2620\\u2622\\u2623\\u2626\\u262A\\u262E\\u262F\\u2638-\\u263A\\u2640\\u2642\\u2648-\\u2653\\u265F\\u2660\\u2663\\u2665\\u2666\\u2668\\u267B\\u267E\\u267F\\u2692\\u2694-\\u2697\\u2699\\u269B\\u269C\\u26A0\\u26A7\\u26AA\\u26B0\\u26B1\\u26BD\\u26BE\\u26C4\\u26C8\\u26CF\\u26D1\\u26E9\\u26F0-\\u26F5\\u26F7\\u26F8\\u26FA\\u2702\\u2708\\u2709\\u270F\\u2712\\u2714\\u2716\\u271D\\u2721\\u2733\\u2734\\u2744\\u2747\\u2757\\u2763\\u27A1\\u2934\\u2935\\u2B05-\\u2B07\\u2B1B\\u2B1C\\u2B55\\u3030\\u303D\\u3297\\u3299]\\uFE0F?|[\\u261D\\u270C\\u270D](?:\\uD83C[\\uDFFB-\\uDFFF]|\\uFE0F)?|[\\u270A\\u270B](?:\\uD83C[\\uDFFB-\\uDFFF])?|[\\u23E9-\\u23EC\\u23F0\\u23F3\\u25FD\\u2693\\u26A1\\u26AB\\u26C5\\u26CE\\u26D4\\u26EA\\u26FD\\u2705\\u2728\\u274C\\u274E\\u2753-\\u2755\\u2795-\\u2797\\u27B0\\u27BF\\u2B50]|\\u26D3\\uFE0F?(?:\\u200D\\uD83D\\uDCA5)?|\\u26F9(?:\\uD83C[\\uDFFB-\\uDFFF]|\\uFE0F)?(?:\\u200D[\\u2640\\u2642]\\uFE0F?)?|\\u2764\\uFE0F?(?:\\u200D(?:\\uD83D\\uDD25|\\uD83E\\uDE79))?|\\uD83C(?:[\\uDC04\\uDD70\\uDD71\\uDD7E\\uDD7F\\uDE02\\uDE37\\uDF21\\uDF24-\\uDF2C\\uDF36\\uDF7D\\uDF96\\uDF97\\uDF99-\\uDF9B\\uDF9E\\uDF9F\\uDFCD\\uDFCE\\uDFD4-\\uDFDF\\uDFF5\\uDFF7]\\uFE0F?|[\\uDF85\\uDFC2\\uDFC7](?:\\uD83C[\\uDFFB-\\uDFFF])?|[\\uDFC4\\uDFCA](?:\\uD83C[\\uDFFB-\\uDFFF])?(?:\\u200D[\\u2640\\u2642]\\uFE0F?)?|[\\uDFCB\\uDFCC](?:\\uD83C[\\uDFFB-\\uDFFF]|\\uFE0F)?(?:\\u200D[\\u2640\\u2642]\\uFE0F?)?|[\\uDCCF\\uDD8E\\uDD91-\\uDD9A\\uDE01\\uDE1A\\uDE2F\\uDE32-\\uDE36\\uDE38-\\uDE3A\\uDE50\\uDE51\\uDF00-\\uDF20\\uDF2D-\\uDF35\\uDF37-\\uDF43\\uDF45-\\uDF4A\\uDF4C-\\uDF7C\\uDF7E-\\uDF84\\uDF86-\\uDF93\\uDFA0-\\uDFC1\\uDFC5\\uDFC6\\uDFC8\\uDFC9\\uDFCF-\\uDFD3\\uDFE0-\\uDFF0\\uDFF8-\\uDFFF]|\\uDDE6\\uD83C[\\uDDE8-\\uDDEC\\uDDEE\\uDDF1\\uDDF2\\uDDF4\\uDDF6-\\uDDFA\\uDDFC\\uDDFD\\uDDFF]|\\uDDE7\\uD83C[\\uDDE6\\uDDE7\\uDDE9-\\uDDEF\\uDDF1-\\uDDF4\\uDDF6-\\uDDF9\\uDDFB\\uDDFC\\uDDFE\\uDDFF]|\\uDDE8\\uD83C[\\uDDE6\\uDDE8\\uDDE9\\uDDEB-\\uDDEE\\uDDF0-\\uDDF7\\uDDFA-\\uDDFF]|\\uDDE9\\uD83C[\\uDDEA\\uDDEC\\uDDEF\\uDDF0\\uDDF2\\uDDF4\\uDDFF]|\\uDDEA\\uD83C[\\uDDE6\\uDDE8\\uDDEA\\uDDEC\\uDDED\\uDDF7-\\uDDFA]|\\uDDEB\\uD83C[\\uDDEE-\\uDDF0\\uDDF2\\uDDF4\\uDDF7]|\\uDDEC\\uD83C[\\uDDE6\\uDDE7\\uDDE9-\\uDDEE\\uDDF1-\\uDDF3\\uDDF5-\\uDDFA\\uDDFC\\uDDFE]|\\uDDED\\uD83C[\\uDDF0\\uDDF2\\uDDF3\\uDDF7\\uDDF9\\uDDFA]|\\uDDEE\\uD83C[\\uDDE8-\\uDDEA\\uDDF1-\\uDDF4\\uDDF6-\\uDDF9]|\\uDDEF\\uD83C[\\uDDEA\\uDDF2\\uDDF4\\uDDF5]|\\uDDF0\\uD83C[\\uDDEA\\uDDEC-\\uDDEE\\uDDF2\\uDDF3\\uDDF5\\uDDF7\\uDDFC\\uDDFE\\uDDFF]|\\uDDF1\\uD83C[\\uDDE6-\\uDDE8\\uDDEE\\uDDF0\\uDDF7-\\uDDFB\\uDDFE]|\\uDDF2\\uD83C[\\uDDE6\\uDDE8-\\uDDED\\uDDF0-\\uDDFF]|\\uDDF3\\uD83C[\\uDDE6\\uDDE8\\uDDEA-\\uDDEC\\uDDEE\\uDDF1\\uDDF4\\uDDF5\\uDDF7\\uDDFA\\uDDFF]|\\uDDF4\\uD83C\\uDDF2|\\uDDF5\\uD83C[\\uDDE6\\uDDEA-\\uDDED\\uDDF0-\\uDDF3\\uDDF7-\\uDDF9\\uDDFC\\uDDFE]|\\uDDF6\\uD83C\\uDDE6|\\uDDF7\\uD83C[\\uDDEA\\uDDF4\\uDDF8\\uDDFA\\uDDFC]|\\uDDF8\\uD83C[\\uDDE6-\\uDDEA\\uDDEC-\\uDDF4\\uDDF7-\\uDDF9\\uDDFB\\uDDFD-\\uDDFF]|\\uDDF9\\uD83C[\\uDDE6\\uDDE8\\uDDE9\\uDDEB-\\uDDED\\uDDEF-\\uDDF4\\uDDF7\\uDDF9\\uDDFB\\uDDFC\\uDDFF]|\\uDDFA\\uD83C[\\uDDE6\\uDDEC\\uDDF2\\uDDF3\\uDDF8\\uDDFE\\uDDFF]|\\uDDFB\\uD83C[\\uDDE6\\uDDE8\\uDDEA\\uDDEC\\uDDEE\\uDDF3\\uDDFA]|\\uDDFC\\uD83C[\\uDDEB\\uDDF8]|\\uDDFD\\uD83C\\uDDF0|\\uDDFE\\uD83C[\\uDDEA\\uDDF9]|\\uDDFF\\uD83C[\\uDDE6\\uDDF2\\uDDFC]|\\uDF44(?:\\u200D\\uD83D\\uDFEB)?|\\uDF4B(?:\\u200D\\uD83D\\uDFE9)?|\\uDFC3(?:\\uD83C[\\uDFFB-\\uDFFF])?(?:\\u200D(?:[\\u2640\\u2642]\\uFE0F?(?:\\u200D\\u27A1\\uFE0F?)?|\\u27A1\\uFE0F?))?|\\uDFF3\\uFE0F?(?:\\u200D(?:\\u26A7\\uFE0F?|\\uD83C\\uDF08))?|\\uDFF4(?:\\u200D\\u2620\\uFE0F?|\\uDB40\\uDC67\\uDB40\\uDC62\\uDB40(?:\\uDC65\\uDB40\\uDC6E\\uDB40\\uDC67|\\uDC73\\uDB40\\uDC63\\uDB40\\uDC74|\\uDC77\\uDB40\\uDC6C\\uDB40\\uDC73)\\uDB40\\uDC7F)?)|\\uD83D(?:[\\uDC3F\\uDCFD\\uDD49\\uDD4A\\uDD6F\\uDD70\\uDD73\\uDD76-\\uDD79\\uDD87\\uDD8A-\\uDD8D\\uDDA5\\uDDA8\\uDDB1\\uDDB2\\uDDBC\\uDDC2-\\uDDC4\\uDDD1-\\uDDD3\\uDDDC-\\uDDDE\\uDDE1\\uDDE3\\uDDE8\\uDDEF\\uDDF3\\uDDFA\\uDECB\\uDECD-\\uDECF\\uDEE0-\\uDEE5\\uDEE9\\uDEF0\\uDEF3]\\uFE0F?|[\\uDC42\\uDC43\\uDC46-\\uDC50\\uDC66\\uDC67\\uDC6B-\\uDC6D\\uDC72\\uDC74-\\uDC76\\uDC78\\uDC7C\\uDC83\\uDC85\\uDC8F\\uDC91\\uDCAA\\uDD7A\\uDD95\\uDD96\\uDE4C\\uDE4F\\uDEC0\\uDECC](?:\\uD83C[\\uDFFB-\\uDFFF])?|[\\uDC6E\\uDC70\\uDC71\\uDC73\\uDC77\\uDC81\\uDC82\\uDC86\\uDC87\\uDE45-\\uDE47\\uDE4B\\uDE4D\\uDE4E\\uDEA3\\uDEB4\\uDEB5](?:\\uD83C[\\uDFFB-\\uDFFF])?(?:\\u200D[\\u2640\\u2642]\\uFE0F?)?|[\\uDD74\\uDD90](?:\\uD83C[\\uDFFB-\\uDFFF]|\\uFE0F)?|[\\uDC00-\\uDC07\\uDC09-\\uDC14\\uDC16-\\uDC25\\uDC27-\\uDC3A\\uDC3C-\\uDC3E\\uDC40\\uDC44\\uDC45\\uDC51-\\uDC65\\uDC6A\\uDC79-\\uDC7B\\uDC7D-\\uDC80\\uDC84\\uDC88-\\uDC8E\\uDC90\\uDC92-\\uDCA9\\uDCAB-\\uDCFC\\uDCFF-\\uDD3D\\uDD4B-\\uDD4E\\uDD50-\\uDD67\\uDDA4\\uDDFB-\\uDE2D\\uDE2F-\\uDE34\\uDE37-\\uDE41\\uDE43\\uDE44\\uDE48-\\uDE4A\\uDE80-\\uDEA2\\uDEA4-\\uDEB3\\uDEB7-\\uDEBF\\uDEC1-\\uDEC5\\uDED0-\\uDED2\\uDED5-\\uDED7\\uDEDC-\\uDEDF\\uDEEB\\uDEEC\\uDEF4-\\uDEFC\\uDFE0-\\uDFEB\\uDFF0]|\\uDC08(?:\\u200D\\u2B1B)?|\\uDC15(?:\\u200D\\uD83E\\uDDBA)?|\\uDC26(?:\\u200D(?:\\u2B1B|\\uD83D\\uDD25))?|\\uDC3B(?:\\u200D\\u2744\\uFE0F?)?|\\uDC41\\uFE0F?(?:\\u200D\\uD83D\\uDDE8\\uFE0F?)?|\\uDC68(?:\\u200D(?:[\\u2695\\u2696\\u2708]\\uFE0F?|\\u2764\\uFE0F?\\u200D\\uD83D(?:\\uDC8B\\u200D\\uD83D)?\\uDC68|\\uD83C[\\uDF3E\\uDF73\\uDF7C\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D(?:[\\uDC68\\uDC69]\\u200D\\uD83D(?:\\uDC66(?:\\u200D\\uD83D\\uDC66)?|\\uDC67(?:\\u200D\\uD83D[\\uDC66\\uDC67])?)|[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uDC66(?:\\u200D\\uD83D\\uDC66)?|\\uDC67(?:\\u200D\\uD83D[\\uDC66\\uDC67])?)|\\uD83E(?:[\\uDDAF\\uDDBC\\uDDBD](?:\\u200D\\u27A1\\uFE0F?)?|[\\uDDB0-\\uDDB3]))|\\uD83C(?:\\uDFFB(?:\\u200D(?:[\\u2695\\u2696\\u2708]\\uFE0F?|\\u2764\\uFE0F?\\u200D\\uD83D(?:\\uDC8B\\u200D\\uD83D)?\\uDC68\\uD83C[\\uDFFB-\\uDFFF]|\\uD83C[\\uDF3E\\uDF73\\uDF7C\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E(?:[\\uDDAF\\uDDBC\\uDDBD](?:\\u200D\\u27A1\\uFE0F?)?|[\\uDDB0-\\uDDB3]|\\uDD1D\\u200D\\uD83D\\uDC68\\uD83C[\\uDFFC-\\uDFFF])))?|\\uDFFC(?:\\u200D(?:[\\u2695\\u2696\\u2708]\\uFE0F?|\\u2764\\uFE0F?\\u200D\\uD83D(?:\\uDC8B\\u200D\\uD83D)?\\uDC68\\uD83C[\\uDFFB-\\uDFFF]|\\uD83C[\\uDF3E\\uDF73\\uDF7C\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E(?:[\\uDDAF\\uDDBC\\uDDBD](?:\\u200D\\u27A1\\uFE0F?)?|[\\uDDB0-\\uDDB3]|\\uDD1D\\u200D\\uD83D\\uDC68\\uD83C[\\uDFFB\\uDFFD-\\uDFFF])))?|\\uDFFD(?:\\u200D(?:[\\u2695\\u2696\\u2708]\\uFE0F?|\\u2764\\uFE0F?\\u200D\\uD83D(?:\\uDC8B\\u200D\\uD83D)?\\uDC68\\uD83C[\\uDFFB-\\uDFFF]|\\uD83C[\\uDF3E\\uDF73\\uDF7C\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E(?:[\\uDDAF\\uDDBC\\uDDBD](?:\\u200D\\u27A1\\uFE0F?)?|[\\uDDB0-\\uDDB3]|\\uDD1D\\u200D\\uD83D\\uDC68\\uD83C[\\uDFFB\\uDFFC\\uDFFE\\uDFFF])))?|\\uDFFE(?:\\u200D(?:[\\u2695\\u2696\\u2708]\\uFE0F?|\\u2764\\uFE0F?\\u200D\\uD83D(?:\\uDC8B\\u200D\\uD83D)?\\uDC68\\uD83C[\\uDFFB-\\uDFFF]|\\uD83C[\\uDF3E\\uDF73\\uDF7C\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E(?:[\\uDDAF\\uDDBC\\uDDBD](?:\\u200D\\u27A1\\uFE0F?)?|[\\uDDB0-\\uDDB3]|\\uDD1D\\u200D\\uD83D\\uDC68\\uD83C[\\uDFFB-\\uDFFD\\uDFFF])))?|\\uDFFF(?:\\u200D(?:[\\u2695\\u2696\\u2708]\\uFE0F?|\\u2764\\uFE0F?\\u200D\\uD83D(?:\\uDC8B\\u200D\\uD83D)?\\uDC68\\uD83C[\\uDFFB-\\uDFFF]|\\uD83C[\\uDF3E\\uDF73\\uDF7C\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E(?:[\\uDDAF\\uDDBC\\uDDBD](?:\\u200D\\u27A1\\uFE0F?)?|[\\uDDB0-\\uDDB3]|\\uDD1D\\u200D\\uD83D\\uDC68\\uD83C[\\uDFFB-\\uDFFE])))?))?|\\uDC69(?:\\u200D(?:[\\u2695\\u2696\\u2708]\\uFE0F?|\\u2764\\uFE0F?\\u200D\\uD83D(?:\\uDC8B\\u200D\\uD83D)?[\\uDC68\\uDC69]|\\uD83C[\\uDF3E\\uDF73\\uDF7C\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D(?:[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uDC66(?:\\u200D\\uD83D\\uDC66)?|\\uDC67(?:\\u200D\\uD83D[\\uDC66\\uDC67])?|\\uDC69\\u200D\\uD83D(?:\\uDC66(?:\\u200D\\uD83D\\uDC66)?|\\uDC67(?:\\u200D\\uD83D[\\uDC66\\uDC67])?))|\\uD83E(?:[\\uDDAF\\uDDBC\\uDDBD](?:\\u200D\\u27A1\\uFE0F?)?|[\\uDDB0-\\uDDB3]))|\\uD83C(?:\\uDFFB(?:\\u200D(?:[\\u2695\\u2696\\u2708]\\uFE0F?|\\u2764\\uFE0F?\\u200D\\uD83D(?:[\\uDC68\\uDC69]|\\uDC8B\\u200D\\uD83D[\\uDC68\\uDC69])\\uD83C[\\uDFFB-\\uDFFF]|\\uD83C[\\uDF3E\\uDF73\\uDF7C\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E(?:[\\uDDAF\\uDDBC\\uDDBD](?:\\u200D\\u27A1\\uFE0F?)?|[\\uDDB0-\\uDDB3]|\\uDD1D\\u200D\\uD83D[\\uDC68\\uDC69]\\uD83C[\\uDFFC-\\uDFFF])))?|\\uDFFC(?:\\u200D(?:[\\u2695\\u2696\\u2708]\\uFE0F?|\\u2764\\uFE0F?\\u200D\\uD83D(?:[\\uDC68\\uDC69]|\\uDC8B\\u200D\\uD83D[\\uDC68\\uDC69])\\uD83C[\\uDFFB-\\uDFFF]|\\uD83C[\\uDF3E\\uDF73\\uDF7C\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E(?:[\\uDDAF\\uDDBC\\uDDBD](?:\\u200D\\u27A1\\uFE0F?)?|[\\uDDB0-\\uDDB3]|\\uDD1D\\u200D\\uD83D[\\uDC68\\uDC69]\\uD83C[\\uDFFB\\uDFFD-\\uDFFF])))?|\\uDFFD(?:\\u200D(?:[\\u2695\\u2696\\u2708]\\uFE0F?|\\u2764\\uFE0F?\\u200D\\uD83D(?:[\\uDC68\\uDC69]|\\uDC8B\\u200D\\uD83D[\\uDC68\\uDC69])\\uD83C[\\uDFFB-\\uDFFF]|\\uD83C[\\uDF3E\\uDF73\\uDF7C\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E(?:[\\uDDAF\\uDDBC\\uDDBD](?:\\u200D\\u27A1\\uFE0F?)?|[\\uDDB0-\\uDDB3]|\\uDD1D\\u200D\\uD83D[\\uDC68\\uDC69]\\uD83C[\\uDFFB\\uDFFC\\uDFFE\\uDFFF])))?|\\uDFFE(?:\\u200D(?:[\\u2695\\u2696\\u2708]\\uFE0F?|\\u2764\\uFE0F?\\u200D\\uD83D(?:[\\uDC68\\uDC69]|\\uDC8B\\u200D\\uD83D[\\uDC68\\uDC69])\\uD83C[\\uDFFB-\\uDFFF]|\\uD83C[\\uDF3E\\uDF73\\uDF7C\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E(?:[\\uDDAF\\uDDBC\\uDDBD](?:\\u200D\\u27A1\\uFE0F?)?|[\\uDDB0-\\uDDB3]|\\uDD1D\\u200D\\uD83D[\\uDC68\\uDC69]\\uD83C[\\uDFFB-\\uDFFD\\uDFFF])))?|\\uDFFF(?:\\u200D(?:[\\u2695\\u2696\\u2708]\\uFE0F?|\\u2764\\uFE0F?\\u200D\\uD83D(?:[\\uDC68\\uDC69]|\\uDC8B\\u200D\\uD83D[\\uDC68\\uDC69])\\uD83C[\\uDFFB-\\uDFFF]|\\uD83C[\\uDF3E\\uDF73\\uDF7C\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E(?:[\\uDDAF\\uDDBC\\uDDBD](?:\\u200D\\u27A1\\uFE0F?)?|[\\uDDB0-\\uDDB3]|\\uDD1D\\u200D\\uD83D[\\uDC68\\uDC69]\\uD83C[\\uDFFB-\\uDFFE])))?))?|\\uDC6F(?:\\u200D[\\u2640\\u2642]\\uFE0F?)?|\\uDD75(?:\\uD83C[\\uDFFB-\\uDFFF]|\\uFE0F)?(?:\\u200D[\\u2640\\u2642]\\uFE0F?)?|\\uDE2E(?:\\u200D\\uD83D\\uDCA8)?|\\uDE35(?:\\u200D\\uD83D\\uDCAB)?|\\uDE36(?:\\u200D\\uD83C\\uDF2B\\uFE0F?)?|\\uDE42(?:\\u200D[\\u2194\\u2195]\\uFE0F?)?|\\uDEB6(?:\\uD83C[\\uDFFB-\\uDFFF])?(?:\\u200D(?:[\\u2640\\u2642]\\uFE0F?(?:\\u200D\\u27A1\\uFE0F?)?|\\u27A1\\uFE0F?))?)|\\uD83E(?:[\\uDD0C\\uDD0F\\uDD18-\\uDD1F\\uDD30-\\uDD34\\uDD36\\uDD77\\uDDB5\\uDDB6\\uDDBB\\uDDD2\\uDDD3\\uDDD5\\uDEC3-\\uDEC5\\uDEF0\\uDEF2-\\uDEF8](?:\\uD83C[\\uDFFB-\\uDFFF])?|[\\uDD26\\uDD35\\uDD37-\\uDD39\\uDD3D\\uDD3E\\uDDB8\\uDDB9\\uDDCD\\uDDCF\\uDDD4\\uDDD6-\\uDDDD](?:\\uD83C[\\uDFFB-\\uDFFF])?(?:\\u200D[\\u2640\\u2642]\\uFE0F?)?|[\\uDDDE\\uDDDF](?:\\u200D[\\u2640\\u2642]\\uFE0F?)?|[\\uDD0D\\uDD0E\\uDD10-\\uDD17\\uDD20-\\uDD25\\uDD27-\\uDD2F\\uDD3A\\uDD3F-\\uDD45\\uDD47-\\uDD76\\uDD78-\\uDDB4\\uDDB7\\uDDBA\\uDDBC-\\uDDCC\\uDDD0\\uDDE0-\\uDDFF\\uDE70-\\uDE7C\\uDE80-\\uDE89\\uDE8F-\\uDEC2\\uDEC6\\uDECE-\\uDEDC\\uDEDF-\\uDEE9]|\\uDD3C(?:\\u200D[\\u2640\\u2642]\\uFE0F?|\\uD83C[\\uDFFB-\\uDFFF])?|\\uDDCE(?:\\uD83C[\\uDFFB-\\uDFFF])?(?:\\u200D(?:[\\u2640\\u2642]\\uFE0F?(?:\\u200D\\u27A1\\uFE0F?)?|\\u27A1\\uFE0F?))?|\\uDDD1(?:\\u200D(?:[\\u2695\\u2696\\u2708]\\uFE0F?|\\uD83C[\\uDF3E\\uDF73\\uDF7C\\uDF84\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E(?:[\\uDDAF\\uDDBC\\uDDBD](?:\\u200D\\u27A1\\uFE0F?)?|[\\uDDB0-\\uDDB3]|\\uDD1D\\u200D\\uD83E\\uDDD1|\\uDDD1\\u200D\\uD83E\\uDDD2(?:\\u200D\\uD83E\\uDDD2)?|\\uDDD2(?:\\u200D\\uD83E\\uDDD2)?))|\\uD83C(?:\\uDFFB(?:\\u200D(?:[\\u2695\\u2696\\u2708]\\uFE0F?|\\u2764\\uFE0F?\\u200D(?:\\uD83D\\uDC8B\\u200D)?\\uD83E\\uDDD1\\uD83C[\\uDFFC-\\uDFFF]|\\uD83C[\\uDF3E\\uDF73\\uDF7C\\uDF84\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E(?:[\\uDDAF\\uDDBC\\uDDBD](?:\\u200D\\u27A1\\uFE0F?)?|[\\uDDB0-\\uDDB3]|\\uDD1D\\u200D\\uD83E\\uDDD1\\uD83C[\\uDFFB-\\uDFFF])))?|\\uDFFC(?:\\u200D(?:[\\u2695\\u2696\\u2708]\\uFE0F?|\\u2764\\uFE0F?\\u200D(?:\\uD83D\\uDC8B\\u200D)?\\uD83E\\uDDD1\\uD83C[\\uDFFB\\uDFFD-\\uDFFF]|\\uD83C[\\uDF3E\\uDF73\\uDF7C\\uDF84\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E(?:[\\uDDAF\\uDDBC\\uDDBD](?:\\u200D\\u27A1\\uFE0F?)?|[\\uDDB0-\\uDDB3]|\\uDD1D\\u200D\\uD83E\\uDDD1\\uD83C[\\uDFFB-\\uDFFF])))?|\\uDFFD(?:\\u200D(?:[\\u2695\\u2696\\u2708]\\uFE0F?|\\u2764\\uFE0F?\\u200D(?:\\uD83D\\uDC8B\\u200D)?\\uD83E\\uDDD1\\uD83C[\\uDFFB\\uDFFC\\uDFFE\\uDFFF]|\\uD83C[\\uDF3E\\uDF73\\uDF7C\\uDF84\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E(?:[\\uDDAF\\uDDBC\\uDDBD](?:\\u200D\\u27A1\\uFE0F?)?|[\\uDDB0-\\uDDB3]|\\uDD1D\\u200D\\uD83E\\uDDD1\\uD83C[\\uDFFB-\\uDFFF])))?|\\uDFFE(?:\\u200D(?:[\\u2695\\u2696\\u2708]\\uFE0F?|\\u2764\\uFE0F?\\u200D(?:\\uD83D\\uDC8B\\u200D)?\\uD83E\\uDDD1\\uD83C[\\uDFFB-\\uDFFD\\uDFFF]|\\uD83C[\\uDF3E\\uDF73\\uDF7C\\uDF84\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E(?:[\\uDDAF\\uDDBC\\uDDBD](?:\\u200D\\u27A1\\uFE0F?)?|[\\uDDB0-\\uDDB3]|\\uDD1D\\u200D\\uD83E\\uDDD1\\uD83C[\\uDFFB-\\uDFFF])))?|\\uDFFF(?:\\u200D(?:[\\u2695\\u2696\\u2708]\\uFE0F?|\\u2764\\uFE0F?\\u200D(?:\\uD83D\\uDC8B\\u200D)?\\uD83E\\uDDD1\\uD83C[\\uDFFB-\\uDFFE]|\\uD83C[\\uDF3E\\uDF73\\uDF7C\\uDF84\\uDF93\\uDFA4\\uDFA8\\uDFEB\\uDFED]|\\uD83D[\\uDCBB\\uDCBC\\uDD27\\uDD2C\\uDE80\\uDE92]|\\uD83E(?:[\\uDDAF\\uDDBC\\uDDBD](?:\\u200D\\u27A1\\uFE0F?)?|[\\uDDB0-\\uDDB3]|\\uDD1D\\u200D\\uD83E\\uDDD1\\uD83C[\\uDFFB-\\uDFFF])))?))?|\\uDEF1(?:\\uD83C(?:\\uDFFB(?:\\u200D\\uD83E\\uDEF2\\uD83C[\\uDFFC-\\uDFFF])?|\\uDFFC(?:\\u200D\\uD83E\\uDEF2\\uD83C[\\uDFFB\\uDFFD-\\uDFFF])?|\\uDFFD(?:\\u200D\\uD83E\\uDEF2\\uD83C[\\uDFFB\\uDFFC\\uDFFE\\uDFFF])?|\\uDFFE(?:\\u200D\\uD83E\\uDEF2\\uD83C[\\uDFFB-\\uDFFD\\uDFFF])?|\\uDFFF(?:\\u200D\\uD83E\\uDEF2\\uD83C[\\uDFFB-\\uDFFE])?))?)/g;\n};\n","import { getLogger } from '@jitsi/logger';\nimport { Strophe } from 'strophe.js';\n\nimport { CONNECTION_REDIRECTED } from '../../JitsiConnectionEvents';\nimport { XMPPEvents } from '../../service/xmpp/XMPPEvents';\nimport { exists, findFirst, getAttribute } from '../util/XMLUtils';\n\nimport ChatRoom, { IChatRoomOptions } from './ChatRoom';\nimport { ConnectionPluginListenable } from './ConnectionPlugin';\nimport XmppConnection from './XmppConnection';\nimport XMPP from './xmpp';\n\nconst logger = getLogger('xmpp:strophe.emuc');\n\n/**\n * MUC connection plugin.\n */\nexport default class MucConnectionPlugin extends ConnectionPluginListenable {\n    /**\n     * XMPP connection instance\n     */\n    private xmpp: XMPP;\n\n    /**\n     * Map of room JIDs to ChatRoom instances\n     */\n    private rooms: { [roomJid: string]: ChatRoom; };\n\n    /**\n     *\n     * @param xmpp\n     */\n    constructor(xmpp: XMPP) {\n        super();\n        this.xmpp = xmpp;\n        this.rooms = {};\n    }\n\n    /**\n     *\n     * @param connection\n     */\n    override init(connection: XmppConnection): void {\n        super.init(connection);\n\n        // add handlers (just once)\n        this.connection.addHandler(this.onPresence.bind(this), null,\n            'presence', null, null, null, null);\n        this.connection.addHandler(this.onPresenceUnavailable.bind(this),\n            null, 'presence', 'unavailable', null);\n        this.connection.addHandler(this.onPresenceError.bind(this), null,\n            'presence', 'error', null);\n        this.connection.addHandler(this.onMessage.bind(this), null,\n            'message', null, null);\n        this.connection.addHandler(this.onMute.bind(this),\n            'http://jitsi.org/jitmeet/audio', 'iq', 'set', null, null);\n        this.connection.addHandler(this.onMuteVideo.bind(this),\n            'http://jitsi.org/jitmeet/video', 'iq', 'set', null, null);\n        this.connection.addHandler(this.onMuteDesktop.bind(this),\n            'http://jitsi.org/jitmeet/desktop', 'iq', 'set', null, null);\n        this.connection.addHandler(this.onVisitors.bind(this),\n            'jitsi:visitors', 'iq', 'set', null, null);\n    }\n\n    /**\n     *\n     * @param jid\n     * @param password\n     * @param options\n     */\n    createRoom(jid: string, password: string, options: IChatRoomOptions): ChatRoom {\n        const roomJid = Strophe.getBareJidFromJid(jid);\n\n        if (this.isRoomCreated(roomJid)) {\n            const errmsg = 'You are already in the room!';\n\n            logger.error(errmsg);\n            throw new Error(errmsg);\n        }\n        this.rooms[roomJid] = new ChatRoom(this.connection, jid,\n            password, this.xmpp, options);\n        this.eventEmitter.emit(\n            XMPPEvents.EMUC_ROOM_ADDED, this.rooms[roomJid]);\n\n        return this.rooms[roomJid];\n    }\n\n    /**\n     *  Check if a room with the passed JID is already created.\n     *\n     * @param {string} roomJid - The JID of the room.\n     * @returns {boolean}\n     */\n    isRoomCreated(roomJid: string): boolean {\n        return roomJid in this.rooms;\n    }\n\n    /**\n     *\n     * @param jid\n     */\n    doLeave(jid: string): void {\n        this.eventEmitter.emit(\n            XMPPEvents.EMUC_ROOM_REMOVED, this.rooms[jid]);\n        delete this.rooms[jid];\n    }\n\n    /**\n     *\n     * @param pres\n     */\n    onPresence(pres: Element): boolean {\n        const from = pres.getAttribute('from');\n\n        // What is this for? A workaround for something?\n        if (pres.getAttribute('type')) {\n            return true;\n        }\n\n        const room = this.rooms[Strophe.getBareJidFromJid(from)];\n\n        if (!room) {\n            return true;\n        }\n\n        // Parse status.\n        // Use *|xmlns to match xmlns attributes across any namespace (CSS Selectors Level 3)\n        if (exists(pres, ':scope>x[*|xmlns=\"http://jabber.org/protocol/muc#user\"]>status[code=\"201\"]')) {\n            room.createNonAnonymousRoom();\n        }\n\n        room.onPresence(pres);\n\n        return true;\n    }\n\n    /**\n     *\n     * @param pres\n     */\n    onPresenceUnavailable(pres: Element): boolean {\n        const from = pres.getAttribute('from');\n        const room = this.rooms[Strophe.getBareJidFromJid(from)];\n\n        if (!room) {\n            return true;\n        }\n\n        room.onPresenceUnavailable(pres, from);\n\n        return true;\n    }\n\n    /**\n     *\n     * @param pres\n     */\n    onPresenceError(pres: Element): boolean {\n        const from = pres.getAttribute('from');\n        const room = this.rooms[Strophe.getBareJidFromJid(from)];\n\n        if (!room) {\n            return true;\n        }\n\n        room.onPresenceError(pres, from);\n\n        return true;\n    }\n\n    /**\n     *\n     * @param msg\n     */\n    onMessage(msg: Element): boolean {\n        // FIXME: this is a hack. but jingle on muc makes nickchanges hard\n        const from = msg.getAttribute('from');\n        const room = this.rooms[Strophe.getBareJidFromJid(from)];\n\n        if (!room) {\n            return true;\n        }\n\n        room.onMessage(msg, from);\n\n        return true;\n    }\n\n    /**\n     * Handle remote mute request from focus.\n     *\n     * @param iq\n     */\n    onMute(iq: Element): boolean {\n        const from = iq.getAttribute('from');\n        const room = this.rooms[Strophe.getBareJidFromJid(from)];\n\n        // Returning false would result in the listener being deregistered by Strophe\n        if (!room) {\n            return true;\n        }\n\n        room.onMute(iq);\n\n        return true;\n    }\n\n    /**\n     * Handle remote video mute request from focus.\n     *\n     * @param iq\n     */\n    onMuteVideo(iq: Element): boolean {\n        const from = iq.getAttribute('from');\n        const room = this.rooms[Strophe.getBareJidFromJid(from)];\n\n        // Returning false would result in the listener being deregistered by Strophe\n        if (!room) {\n            return true;\n        }\n\n        room.onMuteVideo(iq);\n\n        return true;\n    }\n\n    /**\n     * Handle remote desktop sharing mute request from focus.\n     *\n     * @param iq\n     */\n    onMuteDesktop(iq) {\n        const from = iq.getAttribute('from');\n        const room = this.rooms[Strophe.getBareJidFromJid(from)];\n\n        // Returning false would result in the listener being deregistered by Strophe\n        if (!room) {\n            return true;\n        }\n\n        room.onMuteDesktop(iq);\n\n        return true;\n    }\n\n    /**\n     * A visitor IQ is received, pass it to the room.\n     * @param iq The received iq.\n     * @returns {boolean}\n     */\n    onVisitors(iq: Element): boolean {\n        const from = iq.getAttribute('from');\n        const room = this.rooms[Strophe.getBareJidFromJid(from)];\n\n        if (!room) {\n            return true;\n        }\n\n        // Use *|xmlns to match xmlns attributes across any namespace (CSS Selectors Level 3)\n        const visitors = findFirst(iq, ':scope>visitors[*|xmlns=\"jitsi:visitors\"]');\n        const response = findFirst(visitors, ':scope>promotion-response');\n\n        if (visitors && response) {\n            if (String(getAttribute(response, 'allow')).toLowerCase() === 'true') {\n                logger.info('Promotion request accepted. Redirected to main room.');\n                this.xmpp.eventEmitter.emit(\n                    CONNECTION_REDIRECTED, undefined, getAttribute(visitors, 'focusjid'), getAttribute(response, 'username'));\n            } else {\n                logger.info('Promotion request rejected.');\n                this.xmpp.eventEmitter.emit(XMPPEvents.VISITORS_REJECTION);\n            }\n        }\n\n        return true;\n    }\n}\n","import { safeJsonParse } from '@jitsi/js-utils/json';\nimport { getLogger } from '@jitsi/logger';\nimport { $build } from 'strophe.js';\n\nimport { MediaType } from '../../service/RTC/MediaType';\nimport { SSRC_GROUP_SEMANTICS } from '../../service/RTC/StandardVideoQualitySettings';\nimport { VideoType } from '../../service/RTC/VideoType';\nimport { XEP } from '../../service/xmpp/XMPPExtensioProtocols';\nimport { findFirst } from '../util/XMLUtils';\n\nconst logger = getLogger('xmpp:JingleHelperFunctions');\n\nexport interface ISourceCompactJson {\n    m?: string;\n    n: string;\n    s: string;\n    v?: any;\n}\n\nexport interface ICompactSsrcGroup extends Array<string> { }\n\nexport interface IJsonMessage {\n    sources: {\n        [owner: string]: [ISourceCompactJson[], ICompactSsrcGroup[], ISourceCompactJson[], ICompactSsrcGroup[]];\n    };\n}\n\n/**\n * Creates a \"source\" XML element for the source described in compact JSON format in [sourceCompactJson].\n * @param {*} owner the endpoint ID of the owner of the source.\n * @param {*} sourceCompactJson the compact JSON representation of the source.\n * @param {boolean} isVideo whether the source is a video source\n * @returns the created \"source\" XML element.\n */\nfunction _createSourceExtension(owner: string, sourceCompactJson: ISourceCompactJson, isVideo: boolean = false): Node {\n    let videoType = sourceCompactJson.v ? VideoType.DESKTOP : undefined;\n\n    // If the video type is not specified, it is assumed to be a camera for video sources.\n    // Jicofo adds the video type only for desktop sharing sources.\n    if (!videoType && isVideo) {\n        videoType = VideoType.CAMERA;\n    }\n\n    const node = $build('source', {\n        name: sourceCompactJson.n,\n        ssrc: sourceCompactJson.s,\n        videoType,\n        xmlns: XEP.SOURCE_ATTRIBUTES\n    });\n\n    if (sourceCompactJson.m) {\n        node.c('parameter', {\n            name: 'msid',\n            value: sourceCompactJson.m\n        }).up();\n    }\n    node.c('ssrc-info', {\n        owner,\n        xmlns: 'http://jitsi.org/jitmeet'\n    }).up();\n\n    return node.node;\n}\n\n/**\n * Creates an \"ssrc-group\" XML element for the SSRC group described in compact JSON format in [ssrcGroupCompactJson].\n * @param {*} ssrcGroupCompactJson the compact JSON representation of the SSRC group.\n * @returns the created \"ssrc-group\" element.\n */\nfunction _createSsrcGroupExtension(ssrcGroupCompactJson: ICompactSsrcGroup): Node {\n    const node = $build('ssrc-group', {\n        semantics: _getSemantics(ssrcGroupCompactJson[0]),\n        xmlns: XEP.SOURCE_ATTRIBUTES\n    });\n\n    for (let i = 1; i < ssrcGroupCompactJson.length; i++) {\n        node.c('source', {\n            ssrc: ssrcGroupCompactJson[i],\n            xmlns: XEP.SOURCE_ATTRIBUTES\n        }).up();\n    }\n\n    return node.node;\n}\n\n/**\n * Finds in a Jingle IQ the RTP description element with the given media type. If one does not exists, create it (as\n *  well as the required  \"content\" parent element) and adds it to the IQ.\n * @param {*} iq\n * @param {*} mediaType The media type, \"audio\" or \"video\".\n * @returns the RTP description element with the given media type.\n */\nfunction _getOrCreateRtpDescription(iq: Element, mediaType: string): Element {\n    const jingle = findFirst(iq, 'jingle');\n    let content = findFirst(jingle, `:scope>content[name=\"${mediaType}\"]`);\n\n    if (!content) {\n        // I'm not sure if \"creator\" and \"senders\" are required.\n        content = $build('content', {\n            name: mediaType\n        }).node;\n        jingle?.appendChild(content);\n    }\n\n    let description = findFirst(content, 'description');\n\n    if (!description) {\n        description = $build('description', {\n            media: mediaType,\n            xmlns: XEP.RTP_MEDIA\n        }).node;\n        content.appendChild(description);\n    }\n\n    return description;\n}\n\n/**\n * Converts the short string representing SSRC group semantics in compact JSON format to the standard representation\n * (i.e. convert \"f\" to \"FID\" and \"s\" to \"SIM\").\n * @param {*} str the compact JSON format representation of an SSRC group's semantics.\n * @returns the SSRC group semantics corresponding to [str].\n */\nfunction _getSemantics(str: string): Nullable<string> {\n    if (str === 'f') {\n        return SSRC_GROUP_SEMANTICS.FID;\n    } else if (str === 's') {\n        return SSRC_GROUP_SEMANTICS.SIM;\n    }\n\n    return null;\n}\n\n/**\n * Reads a JSON-encoded message (from a \"json-message\" element) and extracts source descriptions. Adds the extracted\n * source descriptions to the given Jingle IQ in the standard Jingle format.\n *\n * Encoding sources in this compact JSON format instead of standard Jingle was introduced in order to reduce the\n * network traffic and load on the XMPP server. The format is described in Jicofo [TODO: insert link].\n *\n * @param {*} iq the IQ to which source descriptions will be added.\n * @param {*} jsonMessageXml The XML node for the \"json-message\" element.\n * @returns {Map<string, Array<string>} The audio and video ssrcs extracted from the JSON-encoded message with remote\n * endpoint id as the key.\n */\nexport function expandSourcesFromJson(iq: Element, jsonMessageXml: Element): Nullable<Map<string, string[]>> {\n    let json: any;\n\n    try {\n        json = safeJsonParse(jsonMessageXml.textContent || '');\n    } catch (error) {\n        logger.error(`json-message XML contained invalid JSON, ignoring: ${jsonMessageXml.textContent}`);\n\n        return null;\n    }\n\n    if (!json?.sources) {\n        // It might be a message of a different type, no need to log.\n        return null;\n    }\n\n    // This is where we'll add \"source\" and \"ssrc-group\" elements. Create them elements if they don't exist.\n    const audioRtpDescription = _getOrCreateRtpDescription(iq, MediaType.AUDIO);\n    const videoRtpDescription = _getOrCreateRtpDescription(iq, MediaType.VIDEO);\n    const ssrcMap = new Map<string, string[]>();\n\n    for (const owner in json.sources) {\n        if (json.sources.hasOwnProperty(owner)) {\n            const ssrcs: string[] = [];\n            const ownerSources = json.sources[owner] as [ISourceCompactJson[], ICompactSsrcGroup[], ISourceCompactJson[], ICompactSsrcGroup[]];\n\n            // The video sources, video ssrc-groups, audio sources and audio ssrc-groups are encoded in that order in\n            // the elements of the array.\n            const videoSources = ownerSources?.length ? ownerSources[0] : [];\n            const videoSsrcGroups = ownerSources?.length > 1 ? ownerSources[1] : [];\n            const audioSources = ownerSources?.length > 2 ? ownerSources[2] : [];\n            const audioSsrcGroups = ownerSources?.length > 3 ? ownerSources[3] : [];\n\n            if (videoSources?.length) {\n                for (let i = 0; i < videoSources.length; i++) {\n                    videoRtpDescription.appendChild(_createSourceExtension(owner, videoSources[i], true));\n                    ssrcs.push(videoSources[i]?.s);\n                }\n            }\n\n            if (videoSsrcGroups?.length) {\n                for (let i = 0; i < videoSsrcGroups.length; i++) {\n                    videoRtpDescription.appendChild(_createSsrcGroupExtension(videoSsrcGroups[i]));\n                }\n            }\n            if (audioSources?.length) {\n                for (let i = 0; i < audioSources.length; i++) {\n                    audioRtpDescription.appendChild(_createSourceExtension(owner, audioSources[i]));\n                    ssrcs.push(audioSources[i]?.s);\n                }\n            }\n\n            if (audioSsrcGroups?.length) {\n                for (let i = 0; i < audioSsrcGroups.length; i++) {\n                    audioRtpDescription.appendChild(_createSsrcGroupExtension(audioSsrcGroups[i]));\n                }\n            }\n            ssrcMap.set(owner, ssrcs);\n        }\n    }\n\n    return ssrcMap;\n}\n","/**\n * The reason an in-place ICE restart of the JVB session was requested. Used only for local logging and\n * telemetry (analytics, RTCStats) - it is not sent to the bridge or to jicofo, which only see a plain\n * ice-restart request with no reason attached.\n */\nexport enum IceRestartReason {\n\n    /**\n     * Requested explicitly through the public API, for example from the browser console\n     * (`APP.conference._room.restartJvbIce()`), with no reason given.\n     */\n    API = 'api',\n\n    /**\n     * The existing ICE connection failed and the reactive recovery flow requested a restart.\n     */\n    ICE_FAILED = 'ice-failed',\n\n    /**\n     * The client proactively requested a restart after detecting a network change (mobile only).\n     */\n    NETWORK_CHANGE = 'network-change'\n}\n","import { getLogger } from '@jitsi/logger';\n\nimport { MediaType } from '../../service/RTC/MediaType';\nimport { RTCEvents } from '../../service/RTC/RTCEvents';\n\nimport JitsiRemoteTrack from './JitsiRemoteTrack';\nimport TraceablePeerConnection from './TraceablePeerConnection';\n\nconst logger = getLogger('rtc:RemoteAudioWedgeDetector');\n\n/**\n * The default duration (in milliseconds) for which a mapped, unmuted remote audio source must receive zero inbound RTP\n * before it is considered wedged.\n */\nconst DEFAULT_WEDGE_TIMEOUT_MS = 15000;\n\n/**\n * The minimum number of consecutive eligible (mapped + unmuted) zero-RTP samples required before a source can be\n * declared wedged, regardless of how short the configured timeout is. This debounces transient stats artifacts - most\n * notably the inbound-rtp report being momentarily absent (treated as zero) during renegotiation/track churn - so a\n * single bad sample cannot trigger a recovery.\n */\nconst MIN_SAMPLES = 2;\n\n/**\n * The maximum number of recoveries to trigger for a receive slot (a rewritten SSRC). Recycling the source is only a fix\n * for the wedge; if the slot still receives nothing after this many attempts it is not wedged (the sender is silent, or\n * the bridge is not forwarding it), and further recycles are pure renegotiation churn.\n */\nconst MAX_RECOVERY_ATTEMPTS = 2;\n\ninterface IEligibleZeroState {\n\n    /**\n     * The number of consecutive eligible zero-RTP samples observed in the current streak.\n     */\n    samples: number;\n\n    /**\n     * The timestamp (Date.now()) of the first eligible zero-RTP sample in the current streak.\n     */\n    since: number;\n}\n\ninterface IRecoveryState {\n\n    /**\n     * The number of recoveries triggered for the slot so far.\n     */\n    attempts: number;\n\n    /**\n     * The timestamp (Date.now()) until which detection is suppressed for the slot, so the watchdog does not re-fire\n     * while a recycle renegotiation is in flight.\n     */\n    cooldownUntil: number;\n}\n\nexport interface IRemoteAudioWedgeDetectorOptions {\n\n    /**\n     * Callback invoked with the wedged remote audio track when the watchdog fires. The consumer is expected to recover\n     * the source (e.g. by recycling it via source-remove/source-add).\n     */\n    onWedgeDetected: (track: JitsiRemoteTrack) => void;\n\n    /**\n     * The duration (in milliseconds) for which a source must receive zero inbound RTP before it is considered wedged.\n     * Defaults to {@link DEFAULT_WEDGE_TIMEOUT_MS}.\n     */\n    wedgeTimeoutMs?: number;\n}\n\n/**\n * Watchdog that detects the Chrome/WebRTC audio-demux wedge against a JVB peerconnection that uses SSRC rewriting.\n *\n * When the bridge starts forwarding a rewritten remote audio SSRC before the client's Jingle renegotiation signals it,\n * Chrome can latch an unsignaled receive stream on the wrong audio m-section and then silently fail to bind the\n * signaled sink, leaving the app with a receiver that never receives a packet. The user-visible symptom is a remote\n * participant that is permanently silent while {@code getStats()} reports zero inbound RTP for the SSRC even though RTP\n * is arriving on the wire.\n *\n * This detector is purely a recovery mechanism: it does not depend on any Chrome internals. Rather than running its own\n * stats poll, it piggybacks on the {@link StatsCollector} that already polls the peerconnection every stats cycle: it\n * consumes the per-SSRC inbound audio packet counts emitted as {@link RTCEvents.INBOUND_AUDIO_STATS} and flags any\n * remote audio source that is mapped (a {@link JitsiRemoteTrack} exists) and unmuted (per signaling) yet has received\n * no RTP packets at all for the detection window. The wedge is recoverable from JS because recycling the source\n * (source-remove then source-add) deletes the zombie receive stream and a subsequent re-add binds cleanly.\n *\n * Detection keys off the cumulative {@code packetsReceived} being zero (i.e. \"literally nothing inbound\", which is the\n * confirmed signature of the wedge) rather than off a per-poll delta. A delta-based \"no growth\" check would produce\n * false positives for a genuinely unmuted-but-silent participant, since audio can stop emitting packets during silence\n * (DTX/comfort noise). A source that has ever received a packet is therefore considered healthy and is excluded from\n * further evaluation.\n *\n * A source must stay continuously eligible (mapped + unmuted) and at zero RTP for {@code wedgeTimeoutMs} of wall-clock\n * time before it fires. Eligibility - unlike the cumulative packet count - is not monotonic (a participant can mute and\n * unmute), so the streak is reset whenever the source becomes muted, unmapped, or receives any packet; this is what the\n * repeated samples verify. A {@link MIN_SAMPLES} floor debounces transient stats artifacts.\n *\n * Evaluation is skipped entirely while media transfer is suspended on the peerconnection. A JVB session is kept alive\n * but suspended for the duration of an active P2P session, and a suspended session receives no RTP at all by design, so\n * every remote audio source on it would otherwise look permanently wedged.\n *\n * Recoveries are capped at {@link MAX_RECOVERY_ATTEMPTS} per receive slot, i.e. per rewritten SSRC - the identity a\n * recovery preserves, since recycling the source hands it a new m-line and msid. Zero inbound RTP is not exclusive to\n * the wedge - a bridge that discards silence forwards nothing at all for a sender that is digitally silent from the\n * start of its stream - and recycling cannot fix a slot that is receiving nothing because nothing is being sent to it.\n * The cap bounds that case to a couple of renegotiations instead of one every detection window for the rest of the\n * call.\n */\nexport default class RemoteAudioWedgeDetector {\n    private _pc: TraceablePeerConnection;\n    private _onWedgeDetected: (track: JitsiRemoteTrack) => void;\n    private _wedgeTimeoutMs: number;\n    private _started: boolean;\n\n    /**\n     * Maps an SSRC to the state of its current streak of eligible (mapped + unmuted) zero-RTP samples.\n     */\n    private _eligibleZeroBySsrc: Map<number, IEligibleZeroState>;\n\n    /**\n     * The set of SSRCs that have been observed receiving at least one RTP packet. Such a source is demuxing correctly\n     * and cannot be wedged (the wedge is \"never received anything\", and the cumulative packet count is monotonic), so\n     * it is excluded from evaluation for the rest of the peerconnection's lifetime.\n     *\n     * Entries are never dropped, not even when the SSRC stops being mapped. Under SSRC rewriting a rewritten SSRC gets\n     * exactly one receive m-line for the lifetime of the peerconnection: {@link TraceablePeerConnection.addRemoteSsrc}\n     * only reports an SSRC as new once, so a source-add (which creates the m-line) happens once per SSRC and every\n     * later appearance of that SSRC in a source map is an in-place remap onto the same m-line, transceiver and track.\n     * A remap therefore inherits an m-line that is already demuxing that SSRC correctly and cannot be wedged, whichever\n     * source now occupies it.\n     */\n    private _healthyBySsrc: Set<number>;\n\n    /**\n     * Maps a receive slot (rewritten SSRC) to the state of the recoveries triggered for it: the cooldown that keeps the\n     * watchdog quiet while a recycle renegotiation is in flight and the re-added source (same SSRC, fresh m-line/track)\n     * starts receiving, and the attempt count that stops it recycling a slot that recycling cannot fix.\n     *\n     * Keyed on the SSRC rather than on the source name or the m-line. The m-line cannot carry the count because a\n     * recovery replaces it (source-remove then source-add mints a fresh msid), so a per-m-line budget would reset on\n     * every attempt and never converge. The SSRC is what a recovery preserves, and it also keeps an exhausted budget\n     * with the slot when the bridge remaps it to a different source, whose receive path is just as dead.\n     */\n    private _recoveryStateBySsrc: Map<number, IRecoveryState>;\n\n    /**\n     * Creates a new {@code RemoteAudioWedgeDetector}. The detector is inert until {@link start} is called.\n     *\n     * @param {TraceablePeerConnection} pc - The peerconnection to monitor.\n     * @param {IRemoteAudioWedgeDetectorOptions} options - The detector options.\n     */\n    constructor(pc: TraceablePeerConnection, options: IRemoteAudioWedgeDetectorOptions) {\n        this._pc = pc;\n        this._onWedgeDetected = options.onWedgeDetected;\n        this._wedgeTimeoutMs = options.wedgeTimeoutMs ?? DEFAULT_WEDGE_TIMEOUT_MS;\n        this._started = false;\n        this._eligibleZeroBySsrc = new Map();\n        this._healthyBySsrc = new Set();\n        this._recoveryStateBySsrc = new Map();\n    }\n\n    /**\n     * Handles a batch of inbound audio packet counts from the {@link StatsCollector}'s stats poll. Ignores reports for\n     * other peerconnections (the stats event is emitted on the shared RTC event bus).\n     *\n     * @param {TraceablePeerConnection} pc - The peerconnection the stats belong to.\n     * @param {Map<number, number>} packetsBySsrc - Cumulative packetsReceived per inbound audio SSRC.\n     * @returns {void}\n     */\n    private _onInboundAudioStats = (pc: TraceablePeerConnection, packetsBySsrc: Map<number, number>): void => {\n        if (pc !== this._pc) {\n            return;\n        }\n\n        try {\n            this._evaluate(packetsBySsrc);\n        } catch (error) {\n            logger.warn('Error while evaluating remote audio sources for the wedge', error);\n        }\n    };\n\n    /**\n     * Evaluates every mapped, unmuted remote audio source against the given inbound packet counts for the wedge\n     * signature.\n     *\n     * @param {Map<number, number>} packetsBySsrc - Cumulative packetsReceived per inbound audio SSRC.\n     * @returns {void}\n     */\n    private _evaluate(packetsBySsrc: Map<number, number>): void {\n        const now = Date.now();\n\n        // Media transfer is suspended for the whole of an active P2P session, during which the session receives no RTP\n        // by design. Drop the streaks so the detection window starts over when it resumes rather than counting the\n        // suspended period against the sources.\n        if (!this._pc.audioTransferActive) {\n            this._eligibleZeroBySsrc.clear();\n\n            return;\n        }\n\n        // A source can only be wedged if it is mapped, unmuted, not in a post-recovery cooldown, and has not yet been\n        // confirmed healthy (received a packet).\n        const candidates: Array<{ ssrc: number; track: JitsiRemoteTrack; }> = [];\n\n        for (const track of this._pc.getRemoteTracks(undefined, MediaType.AUDIO)) {\n            const ssrc = track.getSsrc();\n\n            if (typeof ssrc !== 'number') {\n                continue; // eslint-disable-line no-continue\n            }\n\n            if (this._healthyBySsrc.has(ssrc) || track.isMuted()) {\n                continue; // eslint-disable-line no-continue\n            }\n\n            const recovery = this._recoveryStateBySsrc.get(ssrc);\n\n            if (recovery && (recovery.attempts >= MAX_RECOVERY_ATTEMPTS || now < recovery.cooldownUntil)) {\n                continue; // eslint-disable-line no-continue\n            }\n\n            candidates.push({\n                ssrc,\n                track\n            });\n        }\n\n        // Drop streak bookkeeping for any SSRC that is no longer a candidate (unmapped, muted, cooling down, or now\n        // healthy). This is what resets the streak for a source that became ineligible mid-window.\n        const candidateSsrcs = new Set(candidates.map(candidate => candidate.ssrc));\n\n        for (const ssrc of this._eligibleZeroBySsrc.keys()) {\n            if (!candidateSsrcs.has(ssrc)) {\n                this._eligibleZeroBySsrc.delete(ssrc);\n            }\n        }\n\n        for (const { ssrc, track } of candidates) {\n            // A source that has received any RTP is demuxing correctly. Mark it healthy so it is never evaluated again\n            // (the cumulative count is monotonic, so it cannot regress to zero) and reset any streak.\n            if ((packetsBySsrc.get(ssrc) ?? 0) > 0) {\n                this._healthyBySsrc.add(ssrc);\n                this._eligibleZeroBySsrc.delete(ssrc);\n\n                continue; // eslint-disable-line no-continue\n            }\n\n            const state = this._eligibleZeroBySsrc.get(ssrc);\n\n            if (!state) {\n                // Start of a streak: record when the source first went silent so the elapsed duration can be measured\n                // against wall-clock time on subsequent samples.\n                this._eligibleZeroBySsrc.set(ssrc, {\n                    samples: 1,\n                    since: now\n                });\n\n                continue; // eslint-disable-line no-continue\n            }\n\n            state.samples++;\n\n            if (state.samples >= MIN_SAMPLES && now - state.since >= this._wedgeTimeoutMs) {\n                const sourceName = track.getSourceName();\n                const attempts = (this._recoveryStateBySsrc.get(ssrc)?.attempts ?? 0) + 1;\n\n                logger.warn(`Detected wedged remote audio source ${sourceName} (ssrc=${ssrc}, owner=`\n                    + `${track.getParticipantId()}): zero inbound RTP for ${now - state.since}ms `\n                    + `while continuously mapped and unmuted. Triggering recovery (attempt ${attempts} of `\n                    + `${MAX_RECOVERY_ATTEMPTS}).`);\n                this._eligibleZeroBySsrc.delete(ssrc);\n\n                // Suppress further detection for this source while the recycle renegotiation completes. Until then the\n                // source is still wedged (so it would immediately re-fire), and once recovery re-adds it (same SSRC,\n                // fresh m-line/track) the new receiver reads zero for a moment before media flows. Keying the state\n                // off the SSRC, which the re-add preserves, covers the remove/re-add transition.\n                this._recoveryStateBySsrc.set(ssrc, {\n                    attempts,\n                    cooldownUntil: now + this._wedgeTimeoutMs\n                });\n\n                if (attempts >= MAX_RECOVERY_ATTEMPTS) {\n                    logger.warn(`Remote audio source ${sourceName} (ssrc=${ssrc}) has been recycled `\n                        + `${attempts} times without receiving any RTP; it is not recoverable by recycling. No `\n                        + 'further recovery will be attempted for it on this m-line.');\n                }\n\n                this._onWedgeDetected(track);\n            }\n        }\n    }\n\n    /**\n     * Starts the watchdog by subscribing to the {@link StatsCollector}'s inbound audio stats. Subsequent calls are\n     * no-ops while it is already running.\n     *\n     * @returns {void}\n     */\n    start(): void {\n        if (this._started) {\n            return;\n        }\n        this._started = true;\n        logger.debug(`Starting remote audio wedge detector (wedgeTimeout=${this._wedgeTimeoutMs}ms), driven by the `\n            + 'stats collector inbound audio stats');\n        this._pc.eventEmitter.addListener(RTCEvents.INBOUND_AUDIO_STATS, this._onInboundAudioStats);\n    }\n\n    /**\n     * Stops the watchdog and clears its bookkeeping. Safe to call when not started.\n     *\n     * @returns {void}\n     */\n    stop(): void {\n        if (this._started) {\n            this._pc.eventEmitter.removeListener(RTCEvents.INBOUND_AUDIO_STATS, this._onInboundAudioStats);\n            this._started = false;\n        }\n        this._eligibleZeroBySsrc.clear();\n        this._healthyBySsrc.clear();\n        this._recoveryStateBySsrc.clear();\n    }\n}\n","import { isEqual } from 'lodash-es';\nimport Strophe from 'strophe';\n\nimport { XEP } from '../../service/xmpp/XMPPExtensioProtocols';\n\nimport SDP from './SDP';\nimport SDPUtil from './SDPUtil';\nimport { IDiffSourceInfo } from './constants';\n\n\n/**\n * A class that provides methods for comparing the source information present in two different SDPs so that the delta\n * can be signaled to Jicofo via 'source-remove' or 'source-add'.\n */\nexport class SDPDiffer {\n    private isP2P: boolean;\n    private mySdp: SDP;\n    private othersSdp: SDP;\n\n    /**\n     * Constructor.\n     *\n     * @param {SDP} mySdp - the new SDP.\n     * @param {SDP} othersSdp - the old SDP.\n     * @param {boolean} isP2P - Whether the SDPs belong to a p2p peerconnection.\n     */\n    constructor(mySdp: SDP, othersSdp: SDP, isP2P: boolean) {\n        this.isP2P = isP2P;\n        this.mySdp = mySdp;\n        this.othersSdp = othersSdp;\n    }\n\n    /**\n     * Returns a map of the sources that are present in 'othersSdp' but not in 'mySdp'.\n     *\n     * @returns {*}\n     */\n    getNewMedia(): IDiffSourceInfo {\n        const mySources = this.mySdp.getMediaSsrcMap();\n        const othersSources = this.othersSdp.getMediaSsrcMap();\n        const diff: IDiffSourceInfo = {};\n\n        for (const [ index, othersSource ] of othersSources.entries()) {\n            const mySource = mySources.get(index);\n\n            if (!mySource) {\n                diff[index] = othersSource;\n                continue; // eslint-disable-line no-continue\n            }\n\n            const othersSsrcs = Object.keys(othersSource.ssrcs);\n\n            if (othersSsrcs.length && !isEqual(Object.keys(mySource.ssrcs).sort(), [ ...othersSsrcs ].sort())) {\n                diff[index] = othersSource;\n            }\n        }\n\n        return diff;\n    }\n\n    /**\n     * Adds the diff source info to the provided IQ stanza.\n     *\n     * @param {Strophe.Builder} modify - Stanza IQ.\n     * @returns {boolean}\n     */\n    toJingle(modify: Strophe.Builder): boolean {\n        let modified = false;\n        const diffSourceInfo = this.getNewMedia();\n\n        for (const media of Object.values(diffSourceInfo)) {\n            modified = true;\n            modify.c('content', { name: this.isP2P ? media.mid : media.mediaType });\n\n            modify.c('description', {\n                media: media.mediaType,\n                xmlns: XEP.RTP_MEDIA\n            });\n\n            Object.keys(media.ssrcs).forEach(ssrcNum => {\n                const mediaSsrc = media.ssrcs[ssrcNum];\n                const ssrcLines = mediaSsrc.lines;\n                const sourceName = SDPUtil.parseSourceNameLine(ssrcLines);\n                const videoType = SDPUtil.parseVideoTypeLine(ssrcLines);\n\n                modify.c('source', { xmlns: XEP.SOURCE_ATTRIBUTES });\n                modify.attrs({\n                    name: sourceName,\n                    ssrc: mediaSsrc.ssrc,\n                    videoType\n                });\n\n                // Only MSID attribute is sent\n                const msid = SDPUtil.parseMSIDAttribute(ssrcLines);\n\n                if (msid) {\n                    modify.c('parameter', { name: 'msid', value: msid }).up();\n                }\n\n                modify.up(); // end of source\n            });\n\n            // generate source groups from lines\n            media.ssrcGroups.forEach(ssrcGroup => {\n                if (ssrcGroup.ssrcs.length) {\n\n                    modify.c('ssrc-group', {\n                        semantics: ssrcGroup.semantics,\n                        xmlns: XEP.SOURCE_ATTRIBUTES\n                    });\n\n                    ssrcGroup.ssrcs.forEach(ssrc => {\n                        modify.c('source', { ssrc }).up(); // end of source\n                    });\n                    modify.up(); // end of ssrc-group\n                }\n            });\n\n            modify.up(); // end of description\n            modify.up(); // end of content\n        }\n\n        return modified;\n    }\n}\n","export default function onlyOnce(fn) {\n    return function (...args) {\n        if (fn === null) throw new Error(\"Callback was already called.\");\n        var callFn = fn;\n        fn = null;\n        callFn.apply(this, args);\n    };\n}\n","/* istanbul ignore file */\n\nexport var hasQueueMicrotask = typeof queueMicrotask === 'function' && queueMicrotask;\nexport var hasSetImmediate = typeof setImmediate === 'function' && setImmediate;\nexport var hasNextTick = typeof process === 'object' && typeof process.nextTick === 'function';\n\nexport function fallback(fn) {\n    setTimeout(fn, 0);\n}\n\nexport function wrap(defer) {\n    return (fn, ...args) => defer(() => fn(...args));\n}\n\nvar _defer;\n\nif (hasQueueMicrotask) {\n    _defer = queueMicrotask;\n} else if (hasSetImmediate) {\n    _defer = setImmediate;\n} else if (hasNextTick) {\n    _defer = process.nextTick;\n} else {\n    _defer = fallback;\n}\n\nexport default wrap(_defer);\n","// Simple doubly linked list (https://en.wikipedia.org/wiki/Doubly_linked_list) implementation\n// used for queues. This implementation assumes that the node provided by the user can be modified\n// to adjust the next and last properties. We implement only the minimal functionality\n// for queue support.\nexport default class DLL {\n    constructor() {\n        this.head = this.tail = null;\n        this.length = 0;\n    }\n\n    removeLink(node) {\n        if (node.prev) node.prev.next = node.next;\n        else this.head = node.next\n        if (node.next) node.next.prev = node.prev;\n        else this.tail = node.prev;\n\n        node.prev = node.next = null;\n        this.length -= 1;\n        return node;\n    }\n\n    empty () {\n        while(this.head) this.shift();\n        return this;\n    }\n\n    insertAfter(node, newNode) {\n        newNode.prev = node;\n        newNode.next = node.next;\n        if (node.next) node.next.prev = newNode;\n        else this.tail = newNode;\n        node.next = newNode;\n        this.length += 1;\n    }\n\n    insertBefore(node, newNode) {\n        newNode.prev = node.prev;\n        newNode.next = node;\n        if (node.prev) node.prev.next = newNode;\n        else this.head = newNode;\n        node.prev = newNode;\n        this.length += 1;\n    }\n\n    unshift(node) {\n        if (this.head) this.insertBefore(this.head, node);\n        else setInitial(this, node);\n    }\n\n    push(node) {\n        if (this.tail) this.insertAfter(this.tail, node);\n        else setInitial(this, node);\n    }\n\n    shift() {\n        return this.head && this.removeLink(this.head);\n    }\n\n    pop() {\n        return this.tail && this.removeLink(this.tail);\n    }\n\n    toArray() {\n        return [...this]\n    }\n\n    *[Symbol.iterator] () {\n        var cur = this.head\n        while (cur) {\n            yield cur.data\n            cur = cur.next\n        }\n    }\n\n    remove (testFn) {\n        var curr = this.head;\n        while(curr) {\n            var {next} = curr;\n            if (testFn(curr)) {\n                this.removeLink(curr);\n            }\n            curr = next;\n        }\n        return this;\n    }\n}\n\nfunction setInitial(dll, node) {\n    dll.length = 1;\n    dll.head = dll.tail = node;\n}\n\n","import initialParams from './internal/initialParams.js'\nimport setImmediate from './internal/setImmediate.js'\nimport { isAsync } from './internal/wrapAsync.js'\n\n/**\n * Take a sync function and make it async, passing its return value to a\n * callback. This is useful for plugging sync functions into a waterfall,\n * series, or other async functions. Any arguments passed to the generated\n * function will be passed to the wrapped function (except for the final\n * callback argument). Errors thrown will be passed to the callback.\n *\n * If the function passed to `asyncify` returns a Promise, that promises's\n * resolved/rejected state will be used to call the callback, rather than simply\n * the synchronous return value.\n *\n * This also means you can asyncify ES2017 `async` functions.\n *\n * @name asyncify\n * @static\n * @memberOf module:Utils\n * @method\n * @alias wrapSync\n * @category Util\n * @param {Function} func - The synchronous function, or Promise-returning\n * function to convert to an {@link AsyncFunction}.\n * @returns {AsyncFunction} An asynchronous wrapper of the `func`. To be\n * invoked with `(args..., callback)`.\n * @example\n *\n * // passing a regular synchronous function\n * async.waterfall([\n *     async.apply(fs.readFile, filename, \"utf8\"),\n *     async.asyncify(JSON.parse),\n *     function (data, next) {\n *         // data is the result of parsing the text.\n *         // If there was a parsing error, it would have been caught.\n *     }\n * ], callback);\n *\n * // passing a function returning a promise\n * async.waterfall([\n *     async.apply(fs.readFile, filename, \"utf8\"),\n *     async.asyncify(function (contents) {\n *         return db.model.create(contents);\n *     }),\n *     function (model, next) {\n *         // `model` is the instantiated model object.\n *         // If there was an error, this function would be skipped.\n *     }\n * ], callback);\n *\n * // es2017 example, though `asyncify` is not needed if your JS environment\n * // supports async functions out of the box\n * var q = async.queue(async.asyncify(async function(file) {\n *     var intermediateStep = await processFile(file);\n *     return await somePromise(intermediateStep)\n * }));\n *\n * q.push(files);\n */\nexport default function asyncify(func) {\n    if (isAsync(func)) {\n        return function (...args/*, callback*/) {\n            const callback = args.pop()\n            const promise = func.apply(this, args)\n            return handlePromise(promise, callback)\n        }\n    }\n\n    return initialParams(function (args, callback) {\n        var result;\n        try {\n            result = func.apply(this, args);\n        } catch (e) {\n            return callback(e);\n        }\n        // if result is Promise object\n        if (result && typeof result.then === 'function') {\n            return handlePromise(result, callback)\n        } else {\n            callback(null, result);\n        }\n    });\n}\n\nfunction handlePromise(promise, callback) {\n    return promise.then(value => {\n        invokeCallback(callback, null, value);\n    }, err => {\n        invokeCallback(callback, err && err.message ? err : new Error(err));\n    });\n}\n\nfunction invokeCallback(callback, error, value) {\n    try {\n        callback(error, value);\n    } catch (err) {\n        setImmediate(e => { throw e }, err);\n    }\n}\n","import asyncify from '../asyncify.js'\n\nfunction isAsync(fn) {\n    return fn[Symbol.toStringTag] === 'AsyncFunction';\n}\n\nfunction isAsyncGenerator(fn) {\n    return fn[Symbol.toStringTag] === 'AsyncGenerator';\n}\n\nfunction isAsyncIterable(obj) {\n    return typeof obj[Symbol.asyncIterator] === 'function';\n}\n\nfunction wrapAsync(asyncFn) {\n    if (typeof asyncFn !== 'function') throw new Error('expected a function')\n    return isAsync(asyncFn) ? asyncify(asyncFn) : asyncFn;\n}\n\nexport default wrapAsync;\n\nexport { isAsync, isAsyncGenerator, isAsyncIterable };\n","export default function (fn) {\n    return function (...args/*, callback*/) {\n        var callback = args.pop();\n        return fn.call(this, args, callback);\n    };\n}\n","import onlyOnce from './onlyOnce.js'\nimport setImmediate from './setImmediate.js'\nimport DLL from './DoublyLinkedList.js'\nimport wrapAsync from './wrapAsync.js'\n\nexport default function queue(worker, concurrency, payload) {\n    if (concurrency == null) {\n        concurrency = 1;\n    }\n    else if(concurrency === 0) {\n        throw new RangeError('Concurrency must not be zero');\n    }\n\n    var _worker = wrapAsync(worker);\n    var numRunning = 0;\n    var workersList = [];\n    const events = {\n        error: [],\n        drain: [],\n        saturated: [],\n        unsaturated: [],\n        empty: []\n    }\n\n    function on (event, handler) {\n        events[event].push(handler)\n    }\n\n    function once (event, handler) {\n        const handleAndRemove = (...args) => {\n            off(event, handleAndRemove)\n            handler(...args)\n        }\n        events[event].push(handleAndRemove)\n    }\n\n    function off (event, handler) {\n        if (!event) return Object.keys(events).forEach(ev => events[ev] = [])\n        if (!handler) return events[event] = []\n        events[event] = events[event].filter(ev => ev !== handler)\n    }\n\n    function trigger (event, ...args) {\n        events[event].forEach(handler => handler(...args))\n    }\n\n    var processingScheduled = false;\n    function _insert(data, insertAtFront, rejectOnError, callback) {\n        if (callback != null && typeof callback !== 'function') {\n            throw new Error('task callback must be a function');\n        }\n        q.started = true;\n\n        var res, rej;\n        function promiseCallback (err, ...args) {\n            // we don't care about the error, let the global error handler\n            // deal with it\n            if (err) return rejectOnError ? rej(err) : res()\n            if (args.length <= 1) return res(args[0])\n            res(args)\n        }\n\n        var item = q._createTaskItem(\n            data,\n            rejectOnError ? promiseCallback :\n                (callback || promiseCallback)\n        );\n\n        if (insertAtFront) {\n            q._tasks.unshift(item);\n        } else {\n            q._tasks.push(item);\n        }\n\n        if (!processingScheduled) {\n            processingScheduled = true;\n            setImmediate(() => {\n                processingScheduled = false;\n                q.process();\n            });\n        }\n\n        if (rejectOnError || !callback) {\n            return new Promise((resolve, reject) => {\n                res = resolve\n                rej = reject\n            })\n        }\n    }\n\n    function _createCB(tasks) {\n        return function (err, ...args) {\n            numRunning -= 1;\n\n            for (var i = 0, l = tasks.length; i < l; i++) {\n                var task = tasks[i];\n\n                var index = workersList.indexOf(task);\n                if (index === 0) {\n                    workersList.shift();\n                } else if (index > 0) {\n                    workersList.splice(index, 1);\n                }\n\n                task.callback(err, ...args);\n\n                if (err != null) {\n                    trigger('error', err, task.data);\n                }\n            }\n\n            if (numRunning <= (q.concurrency - q.buffer) ) {\n                trigger('unsaturated')\n            }\n\n            if (q.idle()) {\n                trigger('drain')\n            }\n            q.process();\n        };\n    }\n\n    function _maybeDrain(data) {\n        if (data.length === 0 && q.idle()) {\n            // call drain immediately if there are no tasks\n            setImmediate(() => trigger('drain'));\n            return true\n        }\n        return false\n    }\n\n    const eventMethod = (name) => (handler) => {\n        if (!handler) {\n            return new Promise((resolve, reject) => {\n                once(name, (err, data) => {\n                    if (err) return reject(err)\n                    resolve(data)\n                })\n            })\n        }\n        off(name)\n        on(name, handler)\n\n    }\n\n    var isProcessing = false;\n    var q = {\n        _tasks: new DLL(),\n        _createTaskItem (data, callback) {\n            return {\n                data,\n                callback\n            };\n        },\n        *[Symbol.iterator] () {\n            yield* q._tasks[Symbol.iterator]()\n        },\n        concurrency,\n        payload,\n        buffer: concurrency / 4,\n        started: false,\n        paused: false,\n        push (data, callback) {\n            if (Array.isArray(data)) {\n                if (_maybeDrain(data)) return\n                return data.map(datum => _insert(datum, false, false, callback))\n            }\n            return _insert(data, false, false, callback);\n        },\n        pushAsync (data, callback) {\n            if (Array.isArray(data)) {\n                if (_maybeDrain(data)) return\n                return data.map(datum => _insert(datum, false, true, callback))\n            }\n            return _insert(data, false, true, callback);\n        },\n        kill () {\n            off()\n            q._tasks.empty();\n        },\n        unshift (data, callback) {\n            if (Array.isArray(data)) {\n                if (_maybeDrain(data)) return\n                return data.map(datum => _insert(datum, true, false, callback))\n            }\n            return _insert(data, true, false, callback);\n        },\n        unshiftAsync (data, callback) {\n            if (Array.isArray(data)) {\n                if (_maybeDrain(data)) return\n                return data.map(datum => _insert(datum, true, true, callback))\n            }\n            return _insert(data, true, true, callback);\n        },\n        remove (testFn) {\n            q._tasks.remove(testFn);\n        },\n        process () {\n            // Avoid trying to start too many processing operations. This can occur\n            // when callbacks resolve synchronously (#1267).\n            if (isProcessing) {\n                return;\n            }\n            isProcessing = true;\n            while(!q.paused && numRunning < q.concurrency && q._tasks.length){\n                var tasks = [], data = [];\n                var l = q._tasks.length;\n                if (q.payload) l = Math.min(l, q.payload);\n                for (var i = 0; i < l; i++) {\n                    var node = q._tasks.shift();\n                    tasks.push(node);\n                    workersList.push(node);\n                    data.push(node.data);\n                }\n\n                numRunning += 1;\n\n                if (q._tasks.length === 0) {\n                    trigger('empty');\n                }\n\n                if (numRunning === q.concurrency) {\n                    trigger('saturated');\n                }\n\n                var cb = onlyOnce(_createCB(tasks));\n                _worker(data, cb);\n            }\n            isProcessing = false;\n        },\n        length () {\n            return q._tasks.length;\n        },\n        running () {\n            return numRunning;\n        },\n        workersList () {\n            return workersList;\n        },\n        idle() {\n            return q._tasks.length + numRunning === 0;\n        },\n        pause () {\n            q.paused = true;\n        },\n        resume () {\n            if (q.paused === false) { return; }\n            q.paused = false;\n            setImmediate(q.process);\n        }\n    };\n    // define these as fixed properties, so people get useful errors when updating\n    Object.defineProperties(q, {\n        saturated: {\n            writable: false,\n            value: eventMethod('saturated')\n        },\n        unsaturated: {\n            writable: false,\n            value: eventMethod('unsaturated')\n        },\n        empty: {\n            writable: false,\n            value: eventMethod('empty')\n        },\n        drain: {\n            writable: false,\n            value: eventMethod('drain')\n        },\n        error: {\n            writable: false,\n            value: eventMethod('error')\n        },\n    })\n    return q;\n}\n","import { getLogger } from '@jitsi/logger';\nimport { AsyncQueue as AsyncQueueType, queue } from 'async-es';\n\nconst logger = getLogger('utils:AsyncQueue');\n\n/**\n * Error to be passed to a callback of a queued task when the queue is cleared.\n */\nexport class ClearedQueueError extends Error {\n    /**\n     * Creates new instance.\n     */\n    constructor(message: string) {\n        super(message);\n        this.name = 'ClearedQueueError';\n    }\n}\n\nexport type Task = (callback: (err?: Error) => void) => void;\nexport type TaskCallback = (err?: Error) => void;\n\n/**\n * A queue for async task execution.\n */\nexport default class AsyncQueue {\n    private _queue: AsyncQueueType<Task>;\n    private _stopped: boolean;\n    private _taskCallbacks: Map<Task, Optional<TaskCallback>>;\n\n    /**\n     * Creates new instance.\n     */\n    constructor() {\n        this._queue = queue(this._processQueueTasks.bind(this), 1);\n        this._stopped = false;\n        this._taskCallbacks = new Map();\n    }\n\n    /**\n     * Internal task processing implementation which makes things work.\n     */\n    private _processQueueTasks(task: Task, finishedCallback: TaskCallback): void {\n        try {\n            task(finishedCallback);\n        } catch (error) {\n            logger.error(`Task failed: ${error?.stack}`);\n            finishedCallback(error);\n        } finally {\n            this._taskCallbacks.delete(task);\n        }\n    }\n\n    /**\n     * Removes any pending tasks from the queue.\n     */\n    clear(): void {\n        for (const finishedCallback of this._taskCallbacks.values()) {\n            try {\n                finishedCallback?.(new ClearedQueueError('The queue has been cleared'));\n            } catch (error) {\n                logger.error('Error in callback while clearing the queue:', error);\n            }\n        }\n        this._queue.kill();\n    }\n\n    /**\n     * Pauses the execution of the tasks on the queue.\n     */\n    pause(): void {\n        this._queue.pause();\n    }\n\n    /**\n     * The 'task' function will be given a callback it MUST call with either:\n     *  1) No arguments if it was successful or\n     *  2) An error argument if there was an error\n     * If the task wants to process the success or failure of the task, it\n     * should pass the {@code callback} to the push function, e.g.:\n     * queue.push(task, (err) => {\n     *     if (err) {\n     *         // error handling\n     *     } else {\n     *         // success handling\n     *     }\n     * });\n     *\n     * @param {Task} task - The task to be executed. See the description above.\n     * @param {TaskCallback} [callback] - Optional callback to be called after the task has been executed.\n     */\n    push(task: Task, callback?: TaskCallback): void {\n        if (this._stopped) {\n            callback?.(new Error('The queue has been stopped'));\n\n            return;\n        }\n        this._taskCallbacks.set(task, callback);\n        this._queue.push(task, callback);\n    }\n\n    /**\n     * Resumes the execution of the tasks on the queue.\n     */\n    resume(): void {\n        this._queue.resume();\n    }\n\n    /**\n     * Shutdowns the queue. All already queued tasks will execute, but no future tasks can be added. If a task is added\n     * after the queue has been shutdown then the callback will be called with an error.\n     */\n    shutdown(): void {\n        this._stopped = true;\n    }\n}\n","import queue from './internal/queue.js'\nimport wrapAsync from './internal/wrapAsync.js'\n\n/**\n * A queue of tasks for the worker function to complete.\n * @typedef {Iterable} QueueObject\n * @memberOf module:ControlFlow\n * @property {Function} length - a function returning the number of items\n * waiting to be processed. Invoke with `queue.length()`.\n * @property {boolean} started - a boolean indicating whether or not any\n * items have been pushed and processed by the queue.\n * @property {Function} running - a function returning the number of items\n * currently being processed. Invoke with `queue.running()`.\n * @property {Function} workersList - a function returning the array of items\n * currently being processed. Invoke with `queue.workersList()`.\n * @property {Function} idle - a function returning false if there are items\n * waiting or being processed, or true if not. Invoke with `queue.idle()`.\n * @property {number} concurrency - an integer for determining how many `worker`\n * functions should be run in parallel. This property can be changed after a\n * `queue` is created to alter the concurrency on-the-fly.\n * @property {number} payload - an integer that specifies how many items are\n * passed to the worker function at a time. only applies if this is a\n * [cargo]{@link module:ControlFlow.cargo} object\n * @property {AsyncFunction} push - add a new task to the `queue`. Calls `callback`\n * once the `worker` has finished processing the task. Instead of a single task,\n * a `tasks` array can be submitted. The respective callback is used for every\n * task in the list. Invoke with `queue.push(task, [callback])`,\n * @property {AsyncFunction} unshift - add a new task to the front of the `queue`.\n * Invoke with `queue.unshift(task, [callback])`.\n * @property {AsyncFunction} pushAsync - the same as `q.push`, except this returns\n * a promise that rejects if an error occurs.\n * @property {AsyncFunction} unshiftAsync - the same as `q.unshift`, except this returns\n * a promise that rejects if an error occurs.\n * @property {Function} remove - remove items from the queue that match a test\n * function.  The test function will be passed an object with a `data` property,\n * and a `priority` property, if this is a\n * [priorityQueue]{@link module:ControlFlow.priorityQueue} object.\n * Invoked with `queue.remove(testFn)`, where `testFn` is of the form\n * `function ({data, priority}) {}` and returns a Boolean.\n * @property {Function} saturated - a function that sets a callback that is\n * called when the number of running workers hits the `concurrency` limit, and\n * further tasks will be queued.  If the callback is omitted, `q.saturated()`\n * returns a promise for the next occurrence.\n * @property {Function} unsaturated - a function that sets a callback that is\n * called when the number of running workers is less than the `concurrency` &\n * `buffer` limits, and further tasks will not be queued. If the callback is\n * omitted, `q.unsaturated()` returns a promise for the next occurrence.\n * @property {number} buffer - A minimum threshold buffer in order to say that\n * the `queue` is `unsaturated`.\n * @property {Function} empty - a function that sets a callback that is called\n * when the last item from the `queue` is given to a `worker`. If the callback\n * is omitted, `q.empty()` returns a promise for the next occurrence.\n * @property {Function} drain - a function that sets a callback that is called\n * when the last item from the `queue` has returned from the `worker`. If the\n * callback is omitted, `q.drain()` returns a promise for the next occurrence.\n * @property {Function} error - a function that sets a callback that is called\n * when a task errors. Has the signature `function(error, task)`. If the\n * callback is omitted, `error()` returns a promise that rejects on the next\n * error.\n * @property {boolean} paused - a boolean for determining whether the queue is\n * in a paused state.\n * @property {Function} pause - a function that pauses the processing of tasks\n * until `resume()` is called. Invoke with `queue.pause()`.\n * @property {Function} resume - a function that resumes the processing of\n * queued tasks when the queue is paused. Invoke with `queue.resume()`.\n * @property {Function} kill - a function that removes the `drain` callback and\n * empties remaining tasks from the queue forcing it to go idle. No more tasks\n * should be pushed to the queue after calling this function. Invoke with `queue.kill()`.\n *\n * @example\n * const q = async.queue(worker, 2)\n * q.push(item1)\n * q.push(item2)\n * q.push(item3)\n * // queues are iterable, spread into an array to inspect\n * const items = [...q] // [item1, item2, item3]\n * // or use for of\n * for (let item of q) {\n *     console.log(item)\n * }\n *\n * q.drain(() => {\n *     console.log('all done')\n * })\n * // or\n * await q.drain()\n */\n\n/**\n * Creates a `queue` object with the specified `concurrency`. Tasks added to the\n * `queue` are processed in parallel (up to the `concurrency` limit). If all\n * `worker`s are in progress, the task is queued until one becomes available.\n * Once a `worker` completes a `task`, that `task`'s callback is called.\n *\n * @name queue\n * @static\n * @memberOf module:ControlFlow\n * @method\n * @category Control Flow\n * @param {AsyncFunction} worker - An async function for processing a queued task.\n * If you want to handle errors from an individual task, pass a callback to\n * `q.push()`. Invoked with (task, callback).\n * @param {number} [concurrency=1] - An `integer` for determining how many\n * `worker` functions should be run in parallel.  If omitted, the concurrency\n * defaults to `1`.  If the concurrency is `0`, an error is thrown.\n * @returns {module:ControlFlow.QueueObject} A queue object to manage the tasks. Callbacks can be\n * attached as certain properties to listen for specific events during the\n * lifecycle of the queue.\n * @example\n *\n * // create a queue object with concurrency 2\n * var q = async.queue(function(task, callback) {\n *     console.log('hello ' + task.name);\n *     callback();\n * }, 2);\n *\n * // assign a callback\n * q.drain(function() {\n *     console.log('all items have been processed');\n * });\n * // or await the end\n * await q.drain()\n *\n * // assign an error callback\n * q.error(function(err, task) {\n *     console.error('task experienced an error');\n * });\n *\n * // add some items to the queue\n * q.push({name: 'foo'}, function(err) {\n *     console.log('finished processing foo');\n * });\n * // callback is optional\n * q.push({name: 'bar'});\n *\n * // add some items to the queue (batch-wise)\n * q.push([{name: 'baz'},{name: 'bay'},{name: 'bax'}], function(err) {\n *     console.log('finished processing item');\n * });\n *\n * // add some items to the front of the queue\n * q.unshift({name: 'bar'}, function (err) {\n *     console.log('finished processing bar');\n * });\n */\nexport default function (worker, concurrency) {\n    var _worker = wrapAsync(worker);\n    return queue((items, cb) => {\n        _worker(items[0], cb);\n    }, concurrency, 1);\n}\n","import { findFirst, getAttribute } from './XMLUtils';\n\nconst ELEMENT = 'traceparent';\nconst NAMESPACE = 'jitsi:opentelemetry';\nconst TRACE_ID_ATTR_NAME = 'trace_id';\nconst PARENT_ID_ATTR_NAME = 'parent_id';\nconst TRACE_FLAGS_ATTR_NAME = 'trace_flags';\n\nexport class TraceParentExtension {\n    traceId: string;\n    parentId: string;\n    traceFlags: string;\n\n    readonly ELEMENT = ELEMENT;\n\n    constructor(traceId: string, parentId: string, traceFlags: string) {\n        this.traceId = traceId;\n        this.parentId = parentId;\n        this.traceFlags = traceFlags;\n    }\n\n    static fromElement(element: Element) {\n        const traceParentExtension = findFirst(element, `:scope>${ELEMENT}[*|xmlns=\"${NAMESPACE}\"]`);\n\n        if (traceParentExtension == null) {\n            return null;\n        }\n\n        const traceId = getAttribute(traceParentExtension, TRACE_ID_ATTR_NAME);\n\n        if (traceId == null) {\n            return null;\n        }\n\n        const parentId = getAttribute(traceParentExtension, PARENT_ID_ATTR_NAME);\n\n        if (parentId == null) {\n            return null;\n        }\n\n        const traceFlags = getAttribute(traceParentExtension, TRACE_FLAGS_ATTR_NAME);\n\n        if (traceFlags == null) {\n            return null;\n        }\n\n        return new TraceParentExtension(traceId, parentId, traceFlags);\n    }\n\n    asAttributes() {\n        const attrs = {\n            xmlns: NAMESPACE,\n        };\n\n        attrs[TRACE_ID_ATTR_NAME] = this.traceId;\n        attrs[PARENT_ID_ATTR_NAME] = this.parentId;\n        attrs[TRACE_FLAGS_ATTR_NAME] = this.traceFlags;\n\n        return attrs;\n    }\n}\n","export enum JingleSessionState {\n\n    /**\n     * The active Jingle session state as defined in XEP-0166\n     * (after 'session-invite'/'session-accept').\n     */\n    ACTIVE = 'active',\n\n    /**\n     * The ended Jingle session state as defined in XEP-0166\n     * (after 'session-terminate').\n     */\n    ENDED = 'ended',\n\n    /**\n     * The pending Jingle session state which means the session as defined in\n     * XEP-0166(before 'session-invite/session-accept' took place).\n     */\n    PENDING = 'pending'\n}\n\n// exported for backward compatibility\nexport const PENDING = JingleSessionState.PENDING;\nexport const ACTIVE = JingleSessionState.ACTIVE;\nexport const ENDED = JingleSessionState.ENDED;\n","/* eslint-disable @typescript-eslint/no-unused-vars */\n/* eslint-disable @typescript-eslint/no-empty-function */\n\nimport { getLogger } from '@jitsi/logger';\n\nimport RTC from '../RTC/RTC';\nimport Listenable from '../util/Listenable';\n\nimport ChatRoom from './ChatRoom';\nimport { JingleSessionState } from './JingleSessionState';\nimport SignalingLayerImpl from './SignalingLayerImpl';\nimport XmppConnection from './XmppConnection';\n\nconst logger = getLogger('xmpp:JingleSession');\n\n/**\n * JingleSession provides an API to manage a single Jingle session. We will\n * have different implementations depending on the underlying interface used\n * (i.e. WebRTC and ORTC) and here we hold the code common to all of them.\n */\nexport default class JingleSession extends Listenable {\n    /**\n     * The signaling layer.\n     * @internal\n     */\n    _signalingLayer: Nullable<SignalingLayerImpl>;\n\n    /**\n     * The Jingle session identifier.\n     */\n    public sid: string;\n\n    /**\n     * Our JID.\n     */\n    public localJid: string;\n\n    /**\n     * The JID of the remote peer.\n     */\n    public remoteJid: string;\n\n    /**\n     * The XMPP connection.\n     */\n    public connection: XmppConnection;\n\n    /**\n     * The media constraints object passed to the PeerConnection onCreateAnswer/Offer.\n     */\n    public mediaConstraints: object;\n\n    /**\n     * The {@code RTCConfiguration} object passed to the PeerConnection's constructor.\n     */\n    public pcConfig: object;\n\n    /**\n     * Indicates whether this instance is an initiator or an answerer of\n     * the Jingle session.\n     */\n    public isInitiator: boolean;\n\n    /**\n     * Whether to use dripping or not. Dripping is sending trickle\n     * candidates not one-by-one.\n     */\n    public usedrip: boolean;\n\n    /**\n     *  When dripping is used, stores ICE candidates which are to be sent.\n     */\n    public dripContainer: RTCIceCandidate[];\n\n    /**\n     * The chat room instance associated with the session.\n     * @internal\n     */\n    room: Nullable<ChatRoom>;\n\n    /**\n     * Jingle session state - uninitialized until {@link initialize} is\n     * called\n     */\n    public state: Nullable<JingleSessionState>;\n\n    /**\n     * The RTC service instance\n     * @internal\n     */\n    rtc: Nullable<RTC>;\n\n    /**\n     * Creates new <tt>JingleSession</tt>.\n     * @param {string} sid the Jingle session identifier\n     * @param {string} localJid our JID\n     * @param {string} remoteJid the JID of the remote peer\n     * @param {XmppConnection} connection the XMPP connection\n     * @param {Object} mediaConstraints the media constraints object passed to the PeerConnection onCreateAnswer/Offer.\n     * @param {Object} pcConfig The {@code RTCConfiguration} object passed to the PeerConnection's constructor.\n     * @param {boolean} isInitiator indicates if it will be the side which initiates the session.\n     */\n    constructor(\n            sid: string,\n            localJid: string,\n            remoteJid: string,\n            connection: XmppConnection,\n            mediaConstraints: object,\n            pcConfig: object,\n            isInitiator: boolean\n    ) {\n        super();\n        this.sid = sid;\n        this.localJid = localJid;\n        this.remoteJid = remoteJid;\n        this.connection = connection;\n        this.mediaConstraints = mediaConstraints;\n        this.pcConfig = pcConfig;\n\n        /**\n         * Indicates whether this instance is an initiator or an answerer of\n         * the Jingle session.\n         * @type {boolean}\n         */\n        this.isInitiator = isInitiator;\n\n        /**\n         * Whether to use dripping or not. Dripping is sending trickle\n         * candidates not one-by-one.\n         */\n        this.usedrip = true;\n\n        /**\n         *  When dripping is used, stores ICE candidates which are to be sent.\n         */\n        this.dripContainer = [];\n\n        /**\n         * The chat room instance associated with the session.\n         * @type {ChatRoom}\n         */\n        this.room = null;\n\n        /**\n         * The signaling layer.\n         * @type {Nullable<SignalingLayerImpl>}\n         * @internal\n         */\n        this._signalingLayer = null;\n\n        /**\n         * Jingle session state - uninitialized until {@link initialize} is\n         * called @type {JingleSessionState}\n         */\n        this.state = null;\n\n        /**\n         * The RTC service instance\n         * @type {RTC}\n         */\n        this.rtc = null;\n    }\n\n    /**\n     * Returns XMPP address of this session's initiator.\n     * @return {string}\n     */\n    get initiatorJid(): string {\n        return this.isInitiator ? this.localJid : this.remoteJid;\n    }\n\n    /**\n     * Returns XMPP address of this session's responder.\n     * @return {string}\n     */\n    get responderJid(): string {\n        return this.isInitiator ? this.remoteJid : this.localJid;\n    }\n\n    /**\n     * The implementing class finishes initialization here. Called at the end of\n     * {@link initialize}.\n     * @param {Object} options - The options specific to the implementing class.\n     * @protected\n     */\n    protected doInitialize(options: object): void { }\n\n    /**\n     * Prepares this object to initiate a session.\n     * @param {ChatRoom} room the chat room for the conference associated with\n     * this session\n     * @param {RTC} rtc the RTC service instance\n     * @param {SignalingLayerImpl} signalingLayer - The signaling layer instance.\n     * @param {object} options - the options, see implementing class's\n     * {@link #doInitialize} description for more details.\n     */\n    public initialize(\n            room: ChatRoom,\n            rtc: RTC,\n            signalingLayer: SignalingLayerImpl,\n            options: object\n    ): void {\n        if (this.state !== null) {\n            const errmsg\n                = `attempt to initiate on session ${this.sid}\n                   in state ${this.state}`;\n\n            logger.error(errmsg);\n            throw new Error(errmsg);\n        }\n\n        // TODO decouple from room\n        this.room = room;\n        this.rtc = rtc;\n        this._signalingLayer = signalingLayer;\n        this.state = JingleSessionState.PENDING;\n        this.doInitialize(options);\n    }\n\n    /**\n     * Adds the ICE candidates found in the 'contents' array as remote\n     * candidates?\n     * Note: currently only used on transport-info\n     *\n     * @param contents\n     */\n    public addIceCandidates(contents: unknown): void {}\n\n    /**\n     * Returns current state of this <tt>JingleSession</tt> instance.\n     * @returns {Nullable<JingleSessionState>} the current state of this session instance.\n     */\n    public getState(): Nullable<JingleSessionState> {\n        return this.state;\n    }\n\n    /**\n     * Handles an 'add-source' event.\n     *\n     * @param contents an array of Jingle 'content' elements.\n     */\n    public addSources(contents: unknown): void {}\n\n    /**\n     * Handles a 'remove-source' event.\n     *\n     * @param contents an array of Jingle 'content' elements.\n     */\n    public removeSources(contents: unknown): void {}\n\n    /**\n     * Terminates this Jingle session by sending session-terminate\n     * @param success a callback called once the 'session-terminate' packet has\n     * been acknowledged with RESULT.\n     * @param failure a callback called when either timeout occurs or ERROR\n     * response is received.\n     * @param {Object} options\n     * @param {string} [options.reason] XMPP Jingle error condition\n     * @param {string} [options.reasonDescription] some meaningful error message\n     * @param {boolean} [options.requestRestart=false] set to true to ask Jicofo to start a new session one this once is\n     * terminated.\n     * @param {boolean} [options.sendSessionTerminate=true] set to false to skip\n     * sending session-terminate. It may not make sense to send it if the XMPP\n     * connection has been closed already or if the remote peer has disconnected\n     */\n    public terminate(\n            success: Optional<(() => void)>,\n            failure: Optional<(() => void)>,\n            options: {\n                reason?: string;\n                reasonDescription?: string;\n                requestRestart?: boolean;\n                sendSessionTerminate?: boolean;\n            }\n    ): void {}\n\n    /**\n     * Handles an offer from the remote peer (prepares to accept a session).\n     * @param jingle the 'jingle' XML element.\n     * @param success callback called when we the incoming session has been\n     * accepted\n     * @param failure callback called when we fail for any reason, will supply\n     * error object with details(which is meant more to be printed to the logger\n     * than analysed in the code, as the error is unrecoverable anyway)\n     */\n    public acceptOffer(\n            jingle: unknown,\n            success: Optional<(() => void)>,\n            failure: Optional<((error: unknown) => void)>\n    ): void {}\n}\n\n","export enum MediaSessionEvents {\n\n    /**\n     * Event triggered when the remote party signals video max frame heights for its local sources.\n     */\n    REMOTE_SOURCE_CONSTRAINTS_CHANGED = 'media_session.REMOTE_SOURCE_CONSTRAINTS_CHANGED',\n\n    /**\n     * Event triggered when the video codec of the local video track has changed.\n     */\n    VIDEO_CODEC_CHANGED = 'media_session.VIDEO_CODEC_CHANGED'\n}\n","import { getLogger } from '@jitsi/logger';\nimport { isEqual } from 'lodash-es';\nimport { $build, $iq, Strophe } from 'strophe.js';\n\nimport { JitsiConferenceEvents } from '../../JitsiConferenceEvents';\nimport { JitsiTrackEvents } from '../../JitsiTrackEvents';\nimport { CodecMimeType } from '../../service/RTC/CodecMimeType';\nimport { IceRestartReason } from '../../service/RTC/IceRestartReason';\nimport { MediaDirection } from '../../service/RTC/MediaDirection';\nimport { MediaType } from '../../service/RTC/MediaType';\nimport { SSRC_GROUP_SEMANTICS } from '../../service/RTC/StandardVideoQualitySettings';\nimport { VideoType } from '../../service/RTC/VideoType';\nimport { AnalyticsEvents, createAudioWedgeRecoveryEvent, createJingleEvent } from '../../service/statistics/AnalyticsEvents';\nimport { XMPPEvents } from '../../service/xmpp/XMPPEvents';\nimport { XEP } from '../../service/xmpp/XMPPExtensioProtocols';\nimport JitsiLocalTrack from '../RTC/JitsiLocalTrack';\nimport JitsiRemoteTrack from '../RTC/JitsiRemoteTrack';\nimport RemoteAudioWedgeDetector from '../RTC/RemoteAudioWedgeDetector';\nimport { SS_DEFAULT_FRAME_RATE } from '../RTC/ScreenObtainer';\nimport TraceablePeerConnection, { IAudioQuality, IVideoQuality } from '../RTC/TraceablePeerConnection';\nimport RTCStats from '../RTCStats/RTCStats';\nimport { RTCStatsEvents } from '../RTCStats/RTCStatsEvents';\nimport browser from '../browser';\nimport FeatureFlags from '../flags/FeatureFlags';\nimport SDP from '../sdp/SDP';\nimport { SDPDiffer } from '../sdp/SDPDiffer';\nimport SDPUtil from '../sdp/SDPUtil';\nimport Statistics from '../statistics/statistics';\nimport AsyncQueue, { ClearedQueueError } from '../util/AsyncQueue';\nimport { TraceParentExtension } from '../util/OTel';\nimport { exists, findAll, findFirst, getAttribute } from '../util/XMLUtils';\n\nimport JingleSession from './JingleSession';\nimport { JingleSessionState } from './JingleSessionState';\nimport { MediaSessionEvents } from './MediaSessionEvents';\nimport { handleStropheError } from './StropheErrorHandler';\nimport XmppConnection from './XmppConnection';\n\nconst logger = getLogger('xmpp:JingleSessionPC');\n\n/**\n * Constant tells how long we're going to wait for IQ response, before timeout\n * error is  triggered.\n * @type {number}\n */\nconst IQ_TIMEOUT: number = 10000;\n\n/*\n * The default number of samples (per stat) to keep when webrtc stats gathering\n * is enabled in TraceablePeerConnection.\n */\nconst DEFAULT_MAX_STATS: number = 300;\n\n/**\n * The time duration for which the client keeps gathering ICE candidates to be sent out in a single IQ.\n * @type {number} timeout in ms.\n */\nconst ICE_CAND_GATHERING_TIMEOUT: number = 150;\n\n/**\n * How long the media stats sampler runs after an in-place ICE restart started, in ms.\n * @type {number}\n */\nconst ICE_RESTART_STATS_DURATION: number = 3000;\n\n/**\n * The interval at which media stats are sampled during an ICE restart, in ms.\n * @type {number}\n */\nconst ICE_RESTART_STATS_INTERVAL: number = 100;\n\n/**\n * The prefix used by all the logs of the in-place ICE restart flow, so that a whole restart can be extracted from\n * a log file with a single grep.\n * @type {string}\n */\nconst ICE_RESTART_LOG_PREFIX: string = '[ice-restart]';\n\n/**\n * Matches a plain decimal string (no sign, no separators). Used as the first check on a signaled ssrc attribute.\n * @type {RegExp}\n */\nconst SSRC_PATTERN = /^\\d+$/;\n\n/**\n * The largest valid RTP SSRC, i.e. the unsigned 32-bit maximum (RFC 5576).\n * @type {number}\n */\nconst MAX_SSRC = 0xFFFFFFFF;\n\n/**\n * Checks that a signaled ssrc attribute is a plain decimal string within the unsigned 32-bit SSRC range (RFC 5576).\n * Signaled ssrcs are validated before use since they end up in SDP text, string lookups, and {@code Number()}\n * coercion (a digit string above the 32-bit range would lose integer precision when coerced).\n *\n * @param {string} ssrc - The raw ssrc attribute value.\n * @returns {boolean} Whether the value is a valid SSRC.\n */\nfunction isValidSsrc(ssrc: string): boolean {\n    return SSRC_PATTERN.test(ssrc) && Number(ssrc) <= MAX_SSRC;\n}\n\n/**\n * Reads the endpoint ID given a string which represents either the endpoint's full JID, or the endpoint ID itself.\n * @param {String} jidOrEndpointId A string which is either the full JID of a participant, or the ID of an\n * endpoint/participant.\n * @returns The endpoint ID associated with 'jidOrEndpointId'.\n */\nfunction getEndpointId(jidOrEndpointId: string): string {\n    return Strophe.getResourceFromJid(jidOrEndpointId) || jidOrEndpointId;\n}\n\n/**\n * Add \"source\" element as a child of \"description\" element.\n * @param {Object} description The \"description\" element to add to.\n * @param {Object} s Contains properties of the source being added.\n * @param {Number} ssrc_ The SSRC.\n * @param {String} msid The \"msid\" attribute.\n */\nfunction _addSourceElement(description: any, s: any, ssrc_: number, msid: string): void {\n    const source = description.c('source', {\n        name: s.source,\n        ssrc: ssrc_,\n        videoType: s.videoType?.toLowerCase(),\n        xmlns: XEP.SOURCE_ATTRIBUTES\n    });\n\n    source.c('parameter', {\n        name: 'msid',\n        value: msid\n    }).up();\n\n    // The mid the bridge stamps on this source's packets (mid-based demuxing under SSRC rewriting). Used as the\n    // m-line's mid so the negotiated SDP matches the stamped extension.\n    if (s.mid) {\n        source.c('parameter', {\n            name: 'mid',\n            value: s.mid\n        }).up();\n    }\n\n    source.c('ssrc-info', {\n        owner: s.owner,\n        xmlns: 'http://jitsi.org/jitmeet'\n    }).up();\n\n    source.up();\n}\n\n/**\n * @typedef {Object} JingleSessionPCOptions\n * video test ?(ask George).\n * @property {boolean} disableRtx - Described in the config.js[1].\n * @property {boolean} disableSimulcast - Described in the config.js[1].\n * @property {boolean} enableInsertableStreams - Set to true when the insertable streams constraints is to be enabled\n * on the PeerConnection.\n * @property {boolean} failICE - it's an option used in the tests. Set to\n * <tt>true</tt> to block any real candidates and make the ICE fail.\n * @property {boolean} gatherStats - Described in the config.js[1].\n * @property {object} p2p - Peer to peer related options (FIXME those could be\n * fetched from config.p2p on the upper level).\n * @property {Object} testing - Testing and/or experimental options.\n * @property {boolean} webrtcIceUdpDisable - Described in the config.js[1].\n * @property {boolean} webrtcIceTcpDisable - Described in the config.js[1].\n *\n * [1]: https://github.com/jitsi/jitsi-meet/blob/master/config.js\n */\ninterface IJingleSessionPCOptions {\n    audioQuality?: IAudioQuality;\n    channelLastN?: number;\n    codecSettings?: CodecMimeType[];\n    desktopSharingFrameRate?: {\n        max?: number;\n    };\n    disableRtx?: boolean;\n    disableSimulcast?: boolean;\n    enableInsertableStreams?: boolean;\n    failICE?: boolean;\n    forceTurnRelay?: boolean;\n    gatherStats?: boolean;\n    p2p?: object;\n    startSilent?: boolean;\n    testing?: {\n        debugIceRestart?: boolean;\n        enableCodecSelectionAPI?: boolean;\n        failICE?: boolean;\n    };\n    videoQuality?: IVideoQuality;\n    webrtcIceTcpDisable?: boolean;\n    webrtcIceUdpDisable?: boolean;\n}\n\n/**\n * Interface for Jingle error objects returned by the error handler.\n */\ninterface IJingleError {\n    code?: string;\n    msg?: string;\n    reason?: string;\n    session?: string;\n}\n\n/**\n * Interface for remote source frame height constraints.\n */\ninterface ISourceFrameHeight {\n    maxHeight: string;\n    sourceName: string;\n}\n\n/**\n * Interface for Jingle session termination options.\n */\nexport interface ITerminateOptions {\n    reason?: string;\n    reasonDescription?: string;\n    requestRestart?: boolean;\n    sendSessionTerminate?: boolean;\n}\n\n/**\n *\n */\nexport default class JingleSessionPC extends JingleSession {\n    private _bridgeSessionId: Nullable<string>;\n    private _cachedOldLocalSdp: Optional<SDP>;\n    private _cachedNewLocalSdp: Optional<SDP>;\n    private _iceCheckingStartedTimestamp: Nullable<number>;\n    private _gatheringStartedTimestamp: Nullable<number>;\n    private _iceRestartT0: Nullable<number>;\n    private _iceRestartStatsTimer: Nullable<number>;\n    private _lastIceGeneration: number;\n    private _sourceReceiverConstraints: Nullable<Map<string, number>>;\n    private _localSendReceiveVideoActive: boolean;\n    private _remoteSendReceiveVideoActive: boolean;\n    private _gatheringReported: boolean;\n    private _xmppListeners: Array<() => void>;\n    private _removeSenderVideoConstraintsChangeListener: Nullable<() => void>;\n    private _audioWedgeDetector: Nullable<RemoteAudioWedgeDetector>;\n    private usesCodecSelectionAPI: boolean;\n    private wasConnected: boolean;\n    private isReconnect: boolean;\n    private wasstable: boolean;\n    private webrtcIceUdpDisable: boolean;\n    private webrtcIceTcpDisable: boolean;\n    private remoteSourceMaxFrameHeights: ISourceFrameHeight[];\n\n    /**\n     * @internal\n     */\n    isP2P: boolean;\n\n    lasticecandidate: boolean;\n    numRemoteVideoSources: number;\n    numRemoteAudioSources: number;\n    modificationQueue: AsyncQueue;\n    establishmentDuration: Nullable<number>;\n    options: IJingleSessionPCOptions;\n    peerconnection: TraceablePeerConnection;\n    failICE: boolean;\n\n    /**\n     * Parses 'senders' attribute of the video content.\n     * @param {Element} jingleContents\n     * @return {Nullable<string>} one of the values of content \"senders\" attribute\n     * defined by Jingle. If there is no \"senders\" attribute or if the value is\n     * invalid then <tt>null</tt> will be returned.\n     * @private\n     */\n    static parseVideoSenders(jingleContents: Element): Nullable<string> {\n        const videoContents = findFirst(jingleContents, ':scope>content[name=\"video\"]');\n        const senders = getAttribute(videoContents, 'senders');\n\n        if (senders === 'both'\n            || senders === 'initiator'\n            || senders === 'responder'\n            || senders === 'none') {\n            return senders;\n        }\n\n        return null;\n    }\n\n    /**\n     * Parses the source-name and max frame height value of the 'content-modify' IQ when source-name signaling\n     * is enabled.\n     *\n     * @param {Element} jingleContents - An element pointing to the '>jingle' element.\n     * @returns {Nullable<Object>}\n     */\n    static parseSourceMaxFrameHeight(jingleContents: Element): Nullable<ISourceFrameHeight[]> {\n        const receiverConstraints: ISourceFrameHeight[] = [];\n        const sourceFrameHeightSel = findAll(jingleContents, ':scope>content[name=\"video\"]>source-frame-height');\n        let maxHeight: string, sourceName: string;\n\n        if (sourceFrameHeightSel.length) {\n            sourceFrameHeightSel.forEach(source => {\n                sourceName = source.getAttribute('sourceName');\n                maxHeight = source.getAttribute('maxHeight');\n                receiverConstraints.push({\n                    maxHeight,\n                    sourceName\n                });\n            });\n\n            return receiverConstraints;\n        }\n\n        return null;\n    }\n\n    /* eslint-disable max-params */\n\n    /**\n     * Creates new <tt>JingleSessionPC</tt>\n     * @param {string} sid the Jingle Session ID - random string which identifies the session\n     * @param {string} localJid our JID\n     * @param {string} remoteJid remote peer JID\n     * @param {XmppConnection} connection - The XMPP connection instance.\n     * @param mediaConstraints the media constraints object passed to createOffer/Answer, as defined\n     * by the WebRTC standard\n     * @param pcConfig The {@code RTCConfiguration} to use for the WebRTC peer connection.\n     * @param {boolean} isP2P indicates whether this instance is meant to be used in a direct, peer to\n     * peer connection or <tt>false</tt> if it's a JVB connection.\n     * @param {boolean} isInitiator indicates if it will be the side which initiates the session.\n     * @constructor\n     *\n     * @implements {SignalingLayer}\n     */\n    constructor(\n            sid: string,\n            localJid: string,\n            remoteJid: string,\n            connection: XmppConnection,\n            mediaConstraints: MediaStreamConstraints,\n            pcConfig: RTCConfiguration,\n            isP2P: boolean,\n            isInitiator: boolean) {\n        super(\n            sid,\n            localJid,\n            remoteJid, connection, mediaConstraints, pcConfig, isInitiator);\n\n        /**\n         * The bridge session's identifier. One Jingle session can during\n         * it's lifetime participate in multiple bridge sessions managed by\n         * Jicofo. A new bridge session is started whenever Jicofo sends\n         * 'session-initiate'.\n         *\n         * @type {?string}\n         * @private\n         */\n        this._bridgeSessionId = null;\n\n        /**\n         * The oldest SDP passed to {@link notifyMySSRCUpdate} while the XMPP connection was offline that will be\n         * used to update Jicofo once the XMPP connection goes back online.\n         * @type {Optional<SDP>}\n         * @private\n         */\n        this._cachedOldLocalSdp = undefined;\n\n        /**\n         * The latest SDP passed to {@link notifyMySSRCUpdate} while the XMPP connection was offline that will be\n         * used to update Jicofo once the XMPP connection goes back online.\n         * @type {Optional<SDP>}\n         * @private\n         */\n        this._cachedNewLocalSdp = undefined;\n\n        /**\n         * Stores result of {@link window.performance.now()} at the time when\n         * ICE enters 'checking' state.\n         * @type {Nullable<number>}\n         * @private\n         */\n        this._iceCheckingStartedTimestamp = null;\n\n        /**\n         * Stores result of {@link window.performance.now()} at the time when\n         * first ICE candidate is spawned by the peerconnection to mark when\n         * ICE gathering started. That's, because ICE gathering state changed\n         * events are not supported by most of the browsers, so we try something\n         * that will work everywhere. It may not be as accurate, but given that\n         * 'host' candidate usually comes first, the delay should be minimal.\n         * @type {Nullable<number>} null if no value has been stored yet\n         * @private\n         */\n        this._gatheringStartedTimestamp = null;\n\n        /**\n         * Stores the result of {@link window.performance.now()} at the time when an in-place ICE restart started.\n         * Used as the reference point (\"t+Xms\") for the ICE restart instrumentation logs. Reset to null when the\n         * ICE restart stats sampler finishes.\n         * @type {Nullable<number>}\n         * @private\n         */\n        this._iceRestartT0 = null;\n\n        /**\n         * The id of the interval timer of the ICE restart stats sampler, if it is currently running.\n         * @type {Nullable<number>}\n         * @private\n         */\n        this._iceRestartStatsTimer = null;\n\n        /**\n         * The highest ICE generation of a bridge transport that was applied to this session, as carried by the\n         * `ice-generation` attribute of the `<transport>` of an in-place ICE restart 'transport-info'. Zero means\n         * no in-place ICE restart has been applied yet (the initial transport carries no generation). Used as a\n         * monotonic guard against duplicate or reordered pushes, see {@link onBridgeIceRestartTransport}.\n         * @type {number}\n         * @private\n         */\n        this._lastIceGeneration = 0;\n\n        /**\n         * Receiver constraints (max height) set by the application per remote source. Will be used for p2p connection.\n         *\n         * @type {Map<string, number>}\n         */\n        this._sourceReceiverConstraints = undefined;\n\n        /**\n         * Indicates whether or not this session is willing to send/receive\n         * video media. When set to <tt>false</tt> the underlying peer\n         * connection will disable local video transfer and the remote peer will\n         * be will be asked to stop sending video via 'content-modify' IQ\n         * (the senders attribute of video contents will be adjusted\n         * accordingly). Note that this notification is sent only in P2P\n         * session, because Jicofo does not support it yet. Obviously when\n         * the value is changed from <tt>false</tt> to <tt>true</tt> another\n         * notification will be sent to resume video transfer on the remote\n         * side.\n         * @type {boolean}\n         * @private\n         */\n        this._localSendReceiveVideoActive = true;\n\n        /**\n         * Indicates whether or not the remote peer has video transfer active.\n         * When set to <tt>true</tt> it means that remote peer is neither\n         * sending nor willing to receive video. In such case we'll ask\n         * our peerconnection to stop sending video by calling\n         * {@link TraceablePeerConnection.setVideoTransferActive} with\n         * <tt>false</tt>.\n         * @type {boolean}\n         * @private\n         */\n        this._remoteSendReceiveVideoActive = true;\n\n        /**\n         * Marks that ICE gathering duration has been reported already. That\n         * prevents reporting it again.\n         * @type {boolean}\n         * @private\n         */\n        this._gatheringReported = false;\n\n        this.lasticecandidate = false;\n\n        /**\n         * Indicates whether or not this <tt>JingleSessionPC</tt> is used in\n         * a peer to peer type of session.\n         * @type {boolean} <tt>true</tt> if it's a peer to peer\n         * session or <tt>false</tt> if it's a JVB session\n         */\n        this.isP2P = isP2P;\n\n        /**\n         * Number of remote video sources, in SSRC rewriting mode.\n         * Used to generate next unique msid attribute.\n         *\n         * @type {Number}\n         */\n        this.numRemoteVideoSources = 0;\n\n        /**\n         * Number of remote audio sources, in SSRC rewriting mode.\n         * Used to generate next unique msid attribute.\n         *\n         * @type {Number}\n         */\n        this.numRemoteAudioSources = 0;\n\n        /**\n         * Remote preference for the receive video max frame heights when source-name signaling is enabled.\n         *\n         * @type {Optional<Map<string, number>>}\n         * @private\n         */\n        this.remoteSourceMaxFrameHeights = undefined;\n\n        /**\n         * The queue used to serialize operations done on the peerconnection after the session is established.\n         * The queue is paused until the first offer/answer cycle is complete. Only track or codec related\n         * operations which necessitate a renegotiation cycle need to be pushed to the modification queue.\n         * These tasks will be executed after the session has been established.\n         *\n         * @type {AsyncQueue}\n         */\n        this.modificationQueue = new AsyncQueue();\n        this.modificationQueue.pause();\n\n        /**\n         * Flag used to guarantee that the connection established event is\n         * triggered just once.\n         * @type {boolean}\n         */\n        this.wasConnected = false;\n\n        /**\n         * Keeps track of how long (in ms) it took from ICE start to ICE\n         * connect.\n         *\n         * @type {number}\n         */\n        this.establishmentDuration = undefined;\n\n        this._audioWedgeDetector = null;\n\n        this._xmppListeners = [];\n        this._xmppListeners.push(\n            connection.addCancellableListener(\n                XmppConnection.Events.CONN_STATUS_CHANGED,\n                this.onXmppStatusChanged.bind(this))\n        );\n\n        this._removeSenderVideoConstraintsChangeListener = undefined;\n    }\n\n    /**\n     * Handles either Jingle 'source-add' or 'source-remove' message for this Jingle session.\n     *\n     * @param {boolean} isAdd <tt>true</tt> for 'source-add' or <tt>false</tt> otherwise.\n     * @param {Array<Element>} elem an array of Jingle \"content\" elements.\n     * @returns {Promise} resolved when the operation is done or rejected with an error.\n     */\n    private _addOrRemoveRemoteStream(isAdd: boolean, elem: Element[]): void {\n        const logPrefix = isAdd ? 'addRemoteStream' : 'removeRemoteStream';\n        const workFunction = (finishedCallback: (error) => void) => {\n            if (!this.peerconnection.remoteDescription?.sdp) {\n                const errMsg = `${logPrefix} - received before remoteDescription is set, ignoring!!`;\n\n                logger.error(errMsg);\n                finishedCallback(errMsg);\n\n                return;\n            }\n\n            logger.debug(`${this} Processing ${logPrefix}`);\n\n            const currentRemoteSdp = new SDP(this.peerconnection.remoteDescription.sdp, this.isP2P);\n            const sourceDescription = this._processSourceMapFromJingle(elem, isAdd);\n\n            if (!sourceDescription.size) {\n                logger.debug(`${this} ${logPrefix} - no sources to ${isAdd ? 'add' : 'remove'}`);\n                finishedCallback(undefined);\n            }\n\n            logger.debug(`${isAdd ? 'adding' : 'removing'} sources=${Array.from(sourceDescription.keys())}`);\n\n            // Update the remote description.\n            const modifiedMids = currentRemoteSdp.updateRemoteSources(sourceDescription, isAdd);\n\n            for (const mid of modifiedMids) {\n                if (this.isP2P) {\n                    const { media } = SDPUtil.parseMLine(currentRemoteSdp.media[mid].split('\\r\\n')[0]);\n                    const desiredDirection = this.peerconnection.getDesiredMediaDirection(media as MediaType, isAdd);\n                    const currentDirections = isAdd ? [ MediaDirection.RECVONLY, MediaDirection.INACTIVE ]\n                        : [ MediaDirection.SENDRECV, MediaDirection.SENDONLY ];\n\n                    currentDirections.forEach(direction => {\n                        currentRemoteSdp.media[mid] = currentRemoteSdp.media[mid]\n                            .replace(`a=${direction}`, `a=${desiredDirection}`);\n                    });\n                    currentRemoteSdp.raw = currentRemoteSdp.session + currentRemoteSdp.media.join('');\n                }\n            }\n\n            this._renegotiate(currentRemoteSdp.raw).then(() => {\n                logger.debug(`${this} ${logPrefix} - OK`);\n                finishedCallback(undefined);\n            }, error => {\n                logger.error(`${this} ${logPrefix} failed:`, error);\n                finishedCallback(error);\n            });\n        };\n\n        logger.debug(`${this} Queued ${logPrefix} task`);\n\n        // Queue and execute\n        this.modificationQueue.push(workFunction);\n    }\n\n    /**\n     * See {@link addTrackToPc} and {@link removeTrackFromPc}.\n     *\n     * @param {boolean} isRemove <tt>true</tt> for \"remove\" operation or <tt>false</tt> for \"add\" operation.\n     * @param {JitsiLocalTrack} track the track that will be added/removed.\n     * @returns {Promise} resolved when the operation is done or rejected with an error.\n     */\n    private _addRemoveTrack(isRemove: boolean, track: JitsiLocalTrack): Promise<void> {\n        if (!track) {\n            return Promise.reject('invalid \"track\" argument value');\n        }\n        const operationName = isRemove ? 'removeTrack' : 'addTrack';\n        const workFunction = finishedCallback => {\n            const tpc = this.peerconnection;\n\n            if (!tpc) {\n                finishedCallback(`Error:  tried ${operationName} track with no active peer connection`);\n\n                return;\n            }\n            const operationPromise\n                = isRemove\n                    ? tpc.removeTrackFromPc(track)\n                    : tpc.addTrackToPc(track);\n\n            operationPromise\n                .then(shouldRenegotiate => {\n                    if (shouldRenegotiate) {\n                        this._renegotiate().then(finishedCallback);\n                    } else {\n                        finishedCallback();\n                    }\n                },\n                finishedCallback /* will be called with an error */);\n        };\n\n        logger.debug(`${this} Queued ${operationName} task`);\n\n        return new Promise((resolve, reject) => {\n            this.modificationQueue.push(\n                workFunction,\n                error => {\n                    if (error) {\n                        if (error instanceof ClearedQueueError) {\n                            // The session might have been terminated before the task was executed, making it obsolete.\n                            logger.debug(`${this} ${operationName} aborted: session terminated`);\n                            resolve();\n\n                            return;\n                        }\n                        logger.error(`${this} ${operationName} failed`);\n                        reject(error);\n                    } else {\n                        logger.debug(`${this} ${operationName} done`);\n                        resolve();\n                    }\n                });\n        });\n    }\n\n    /**\n     * Checks whether or not this session instance is still operational.\n     *\n     * @returns {boolean} {@code true} if operation or {@code false} otherwise.\n     */\n    private _assertNotEnded(): boolean {\n        return this.state !== JingleSessionState.ENDED;\n    }\n\n    /**\n     * Starts the remote audio wedge watchdog for this session if applicable. The watchdog only runs against a JVB\n     * connection that uses SSRC rewriting, since that is the only configuration affected by the Chrome/WebRTC\n     * audio-demux wedge. It is started once the connection is established and is a no-op on subsequent ICE\n     * (re)connections.\n     *\n     * @returns {void}\n     */\n    private _maybeStartAudioWedgeDetector(): void {\n        if (this._audioWedgeDetector\n                || this.isP2P\n                || !FeatureFlags.isSsrcRewritingSupported()\n                || this.options.startSilent) {\n            return;\n        }\n\n        this._audioWedgeDetector = new RemoteAudioWedgeDetector(this.peerconnection, {\n            onWedgeDetected: track => this._recoverWedgedAudioSource(track)\n        });\n        this._audioWedgeDetector.start();\n    }\n\n    /**\n     * Takes in a jingle offer iq, returns the new sdp offer that can be set as remote description in the\n     * peerconnection.\n     *\n     * @param {Element} offerIq the incoming offer.\n     * @returns {SDP object} the jingle offer translated to SDP.\n     */\n    private _processNewJingleOfferIq(offerIq: Element): SDP {\n        const remoteSdp = new SDP('', this.isP2P);\n\n        if (this.webrtcIceTcpDisable) {\n            remoteSdp.removeTcpCandidates = true;\n        }\n        if (this.webrtcIceUdpDisable) {\n            remoteSdp.removeUdpCandidates = true;\n        }\n        if (this.failICE) {\n            remoteSdp.failICE = true;\n        }\n\n        remoteSdp.fromJingle(offerIq);\n        this._processSourceMapFromJingle(findAll(offerIq, ':scope>content'));\n\n        return remoteSdp;\n    }\n\n    /**\n     * Parses the SSRC information from the source-add/source-remove element passed and updates the SSRC owners.\n     *\n     * @param {Object} sourceElement the source-add/source-remove element from jingle.\n     * @param {boolean} isAdd true if the sources are being added, false if they are to be removed.\n     * @returns {Map<string, Object>} - The map of source name to ssrcs, msid and groups.\n     */\n    private _processSourceMapFromJingle(sourceElement: object, isAdd: boolean = true): Map<string, object> {\n        /**\n         * Map of source name to ssrcs, mediaType, msid and groups.\n         * @type {Map<string,\n         *  {\n         *      mediaType: string,\n         *      msid: string,\n         *      ssrcList: Array<number>,\n         *      groups: ISsrcGroupInfo\n         *  }>}\n         */\n        const sourceDescription = new Map();\n        const sourceElementArray = Array.isArray(sourceElement) ? sourceElement : [ sourceElement ];\n\n        for (const content of sourceElementArray) {\n            const descriptionsWithSources\n                = findAll(content, ':scope>description').filter((el: Element) => exists(el, ':scope>source'));\n\n            for (const description of descriptionsWithSources) {\n                const mediaType = getAttribute(description, 'media');\n\n                if (mediaType === MediaType.AUDIO && this.options.startSilent) {\n\n                    // eslint-disable-next-line no-continue\n                    continue;\n                }\n\n                // Get direct source children, excluding those inside ssrc-group elements\n                const sources = findAll(description, ':scope>source');\n                const removeSsrcs = [];\n\n                for (const source of sources) {\n                    const ssrc = getAttribute(source, 'ssrc');\n\n                    if (!isValidSsrc(ssrc)) {\n                        logger.warn(`${this} Ignoring source with invalid ssrc=${ssrc}`);\n\n                        // eslint-disable-next-line no-continue\n                        continue;\n                    }\n\n                    const sourceName = getAttribute(source, 'name');\n                    const msid = getAttribute(findFirst(source, ':scope>parameter[name=\"msid\"]'), 'value');\n                    const mid = getAttribute(findFirst(source, ':scope>parameter[name=\"mid\"]'), 'value');\n                    let videoType = getAttribute(source, 'videoType');\n\n                    // If the videoType is DESKTOP_HIGH_FPS for remote tracks, we should treat it as DESKTOP.\n                    if (videoType === VideoType.DESKTOP_HIGH_FPS) {\n                        videoType = VideoType.DESKTOP;\n                    }\n\n                    if (sourceDescription.has(sourceName)) {\n                        sourceDescription.get(sourceName).ssrcList?.push(ssrc);\n                    } else {\n                        sourceDescription.set(sourceName, {\n                            groups: [],\n                            mediaType,\n                            mid,\n                            msid,\n                            ssrcList: [ ssrc ],\n                            videoType\n                        });\n                    }\n\n                    // Update the source owner and source name.\n                    // Use *|xmlns to match xmlns attributes across any namespace (CSS Selectors Level 3)\n                    const owner = getAttribute(\n                        findFirst(source, ':scope>ssrc-info[*|xmlns=\"http://jitsi.org/jitmeet\"]'), 'owner');\n\n                    if (owner && isAdd) {\n                        // JVB source-add.\n                        this._signalingLayer.setSSRCOwner(Number(ssrc), getEndpointId(owner), sourceName);\n                    } else if (isAdd) {\n                        // P2P source-add.\n                        this._signalingLayer.setSSRCOwner(Number(ssrc),\n                            Strophe.getResourceFromJid(this.remoteJid), sourceName);\n                    } else {\n                        removeSsrcs.push(Number(ssrc));\n                    }\n                }\n\n                // 'source-remove' from remote peer.\n                removeSsrcs.length && this._signalingLayer.removeSSRCOwners(removeSsrcs);\n\n                findAll(description, ':scope>ssrc-group').forEach(group => {\n                    const semantics = getAttribute(group, 'semantics');\n\n                    if (!Object.values(SSRC_GROUP_SEMANTICS).includes(semantics as SSRC_GROUP_SEMANTICS)) {\n                        logger.warn(`${this} Ignoring ssrc-group with unknown semantics=${semantics}`);\n\n                        return;\n                    }\n\n                    const groupSsrcs = [];\n\n                    findAll(group, ':scope>source').forEach(source => {\n                        groupSsrcs.push(getAttribute(source, 'ssrc'));\n                    });\n\n                    // A group's member ssrcs are only used if the group's ssrc set matches a source's (already\n                    // validated) ssrcList below, so a group referencing an invalid ssrc can never be attached and\n                    // does not need a separate numeric check here.\n                    for (const [ sourceName, { ssrcList } ] of sourceDescription) {\n                        if (isEqual(ssrcList.slice().sort(), groupSsrcs.slice().sort())) {\n                            sourceDescription.get(sourceName).groups.push({\n                                semantics,\n                                ssrcs: groupSsrcs\n                            });\n                        }\n                    }\n                });\n            }\n        }\n\n        sourceDescription.size && this.peerconnection.updateRemoteSources(sourceDescription, isAdd);\n\n        return sourceDescription;\n    }\n\n    /**\n     * Recovers a remote audio source that the {@link RemoteAudioWedgeDetector} has flagged as wedged (mapped and\n     * unmuted, but receiving no inbound RTP). The recovery recycles just that source by synthesizing a source-remove\n     * followed by a source-add, reusing the same machinery as {@link processSourceMap}. The source-remove rejects the\n     * source's m-line (forcing Chrome to delete the stuck receive stream) and the source-add re-signals the same SSRC\n     * on a fresh m-line, which binds cleanly. Both operations are scoped to the single affected source.\n     *\n     * The recovery is gated by a guard that runs on the modification queue: the bridge can remap the slot (the same\n     * rewritten SSRC) to a different source, or remove it entirely, between detection and execution. The guard\n     * re-resolves the track by SSRC at execution time and skips the recovery if the SSRC is no longer mapped to the\n     * source that was detected as wedged - letting the normal sources-map flow own the slot and the watchdog re-detect\n     * on a later cycle. This prevents recycling a source with stale owner/source-name metadata.\n     *\n     * @param {JitsiRemoteTrack} track - The wedged remote audio track.\n     * @returns {void}\n     */\n    private _recoverWedgedAudioSource(track: JitsiRemoteTrack): void {\n        const ssrc = track.getSsrc();\n        const detectedSource = track.getSourceName();\n\n        if (typeof ssrc !== 'number' || !detectedSource) {\n            logger.warn(`${this} Cannot recover wedged audio source, missing ssrc/source-name`);\n\n            return;\n        }\n\n        const workFunction = (finishedCallback: (error?) => void) => {\n            // The slot may have been remapped or removed between detection and now. getTrackBySSRC always resolves to a\n            // remote track for a rewritten remote SSRC.\n            const currentTrack = this.peerconnection?.getTrackBySSRC(ssrc) as Nullable<JitsiRemoteTrack>;\n\n            if (!currentTrack || currentTrack.getSourceName() !== detectedSource) {\n                logger.warn(`${this} Skipping wedge recovery for audio source ${detectedSource} (ssrc=${ssrc}): the `\n                    + `slot was remapped or removed (now=${currentTrack?.getSourceName() ?? 'gone'}). The watchdog `\n                    + 'will re-detect if it is still wedged.');\n                finishedCallback();\n\n                return;\n            }\n\n            const source = currentTrack.getSourceName();\n            const owner = currentTrack.getParticipantId();\n\n            logger.warn(`${this} Recycling wedged remote audio source ${source} (ssrc=${ssrc}, owner=${owner})`);\n\n            // Builds a single-source Jingle \"content\" element for the wedged source, identical in shape to the ones\n            // produced by processSourceMap for an audio source-add.\n            const buildSourceNode = () => {\n                const src = { owner, source };\n                const msid = `remote-audio-${++this.numRemoteAudioSources}`;\n                const node = $build('content', {\n                    name: MediaType.AUDIO,\n                    xmlns: 'urn:xmpp:jingle:1'\n                }).c('description', {\n                    media: MediaType.AUDIO,\n                    xmlns: XEP.RTP_MEDIA\n                });\n\n                _addSourceElement(node, src, ssrc, `${msid} ${msid}`);\n\n                return node.up().node;\n            };\n\n            this._addOrRemoveRemoteStream(false /* remove */, buildSourceNode());\n            this._addOrRemoveRemoteStream(true /* add */, buildSourceNode());\n\n            Statistics.sendAnalytics(createAudioWedgeRecoveryEvent({\n                owner,\n                'source_name': source,\n                ssrc\n            }));\n\n            finishedCallback();\n        };\n\n        logger.debug(`${this} Queued wedge recovery task for audio source ${detectedSource} (ssrc=${ssrc})`);\n        this.modificationQueue.push(workFunction);\n    }\n\n    /**\n     * Does a new offer/answer flow using the existing remote description (if not provided) and signals any new sources\n     * to Jicofo or the remote peer.\n     *\n     * @param {string} [optionalRemoteSdp] optional, raw remote sdp to use.  If not provided, the remote sdp from the\n     * peerconnection will be used.\n     * @returns {Promise} promise which resolves when the o/a flow is complete with no arguments or rejects with an\n     * error {string}\n     */\n    private async _renegotiate(optionalRemoteSdp?: string): Promise<void> {\n        if (this.peerconnection.signalingState === 'closed') {\n            throw new Error('Attempted to renegotiate in state closed');\n        }\n\n        const remoteSdp = optionalRemoteSdp || this.peerconnection.remoteDescription.sdp;\n\n        if (!remoteSdp) {\n            throw new Error(`Cannot renegotiate without remote description, state=${this.state}`);\n        }\n\n        const remoteDescription = {\n            sdp: remoteSdp,\n            type: 'offer'\n        } as RTCSessionDescription;\n\n        const oldLocalSDP = this.peerconnection.localDescription.sdp;\n\n        logger.debug(`${this} Renegotiate: setting remote description`);\n\n        try {\n            await this.peerconnection.setRemoteDescription(remoteDescription);\n            logger.debug(`${this} Renegotiate: creating answer`);\n            const answer = await this.peerconnection.createAnswer(this.mediaConstraints as RTCOfferOptions);\n\n            logger.debug(`${this} Renegotiate: setting local description`);\n            await this.peerconnection.setLocalDescription(answer);\n            if (oldLocalSDP) {\n                // Send the source updates after every renegotiation cycle.\n                this.notifyMySSRCUpdate(new SDP(oldLocalSDP), new SDP(this.peerconnection.localDescription.sdp));\n            }\n        } catch (error) {\n            logger.error(`${this} Renegotiate failed:`, error);\n            throw error;\n        }\n    }\n\n    /**\n     * Sends 'content-modify' IQ in order to ask the remote peer to either stop or resume sending video media or to\n     * adjust sender's video constraints.\n     *\n     * @returns {void}\n     */\n    private _sendContentModify() {\n        const senders = this._localSendReceiveVideoActive ? 'both' : 'none';\n        const sessionModify\n            = $iq({\n                to: this.remoteJid,\n                type: 'set'\n            })\n                .c('jingle', {\n                    action: 'content-modify',\n                    initiator: this.initiatorJid,\n                    sid: this.sid,\n                    xmlns: 'urn:xmpp:jingle:1'\n                })\n                .c('content', {\n                    name: MediaType.VIDEO,\n                    senders\n                });\n\n        if (typeof this._sourceReceiverConstraints !== 'undefined') {\n            this._sourceReceiverConstraints.forEach((maxHeight, sourceName) => {\n                sessionModify\n                    .c('source-frame-height', { xmlns: 'http://jitsi.org/jitmeet/video' })\n                    .attrs({\n                        maxHeight,\n                        sourceName\n                    });\n\n                sessionModify.up();\n                logger.info(`${this} sending content-modify for source-name: ${sourceName}, maxHeight: ${maxHeight}`);\n            });\n        }\n\n        logger.debug(sessionModify.tree());\n\n        this.connection.sendIQ(\n            sessionModify,\n            null,\n            this.newJingleErrorHandler(),\n            IQ_TIMEOUT);\n    }\n\n    /**\n     * Sends given candidate in Jingle 'transport-info' message.\n     *\n     * @param {RTCIceCandidate} candidate the WebRTC ICE candidate instance\n     * @returns {void}\n     */\n    private _sendIceCandidate(candidate: RTCIceCandidate): void {\n        const localSDP = new SDP(this.peerconnection.localDescription.sdp);\n\n        if (candidate?.candidate.length && !this.lasticecandidate) {\n            const ice = SDPUtil.iceparams(localSDP.media[candidate.sdpMLineIndex], localSDP.session);\n            const jcand = SDPUtil.candidateToJingle(candidate.candidate);\n\n            if (!(ice && jcand)) {\n                logger.error('failed to get ice && jcand');\n\n                return;\n            }\n            ice.xmlns = XEP.ICE_UDP_TRANSPORT;\n\n            if (this.usedrip) {\n                if (this.dripContainer.length === 0) {\n                    setTimeout(() => {\n                        if (this.dripContainer.length === 0) {\n                            return;\n                        }\n                        this._sendIceCandidates(this.dripContainer);\n                        this.dripContainer = [];\n                    }, ICE_CAND_GATHERING_TIMEOUT);\n                }\n                this.dripContainer.push(candidate);\n            } else {\n                this._sendIceCandidates([ candidate ]);\n            }\n        } else {\n            logger.debug(`${this} _sendIceCandidate: last candidate`);\n\n            // FIXME: remember to re-think in ICE-restart\n            this.lasticecandidate = true;\n        }\n    }\n\n    /**\n     * Sends given candidates in Jingle 'transport-info' message.\n     *\n     * @param {Array<RTCIceCandidate>} candidates an array of the WebRTC ICE candidate instances.\n     * @returns {void}\n     */\n    private _sendIceCandidates(candidates: RTCIceCandidate[]): void {\n        if (!this._assertNotEnded()) {\n\n            return;\n        }\n\n        logger.debug(`${this} _sendIceCandidates count: ${candidates?.length}`);\n        const cand = $iq({ to: this.remoteJid,\n            type: 'set' })\n            .c('jingle', { action: 'transport-info',\n                initiator: this.initiatorJid,\n                sid: this.sid,\n                xmlns: 'urn:xmpp:jingle:1' });\n\n        const localSDP = new SDP(this.peerconnection.localDescription.sdp);\n\n        for (let mid = 0; mid < localSDP.media.length; mid++) {\n            const cands = candidates.filter(el => el.sdpMLineIndex === mid);\n            const mline\n                = SDPUtil.parseMLine(localSDP.media[mid].split('\\r\\n')[0]);\n\n            if (cands.length > 0) {\n                const ice\n                    = SDPUtil.iceparams(localSDP.media[mid], localSDP.session);\n\n                ice.xmlns = XEP.ICE_UDP_TRANSPORT;\n                cand.c('content', {\n                    creator: this.initiatorJid === this.localJid\n                        ? 'initiator' : 'responder',\n                    name: cands[0].sdpMid ? cands[0].sdpMid : mline.media\n                }).c('transport', ice);\n                for (let i = 0; i < cands.length; i++) {\n                    const candidate\n                        = SDPUtil.candidateToJingle(cands[i].candidate);\n\n                    // Mangle ICE candidate if 'failICE' test option is enabled\n\n                    if (this.failICE) {\n                        candidate.ip = '1.1.1.1';\n                    }\n                    cand.c('candidate', candidate).up();\n                }\n\n                // add fingerprint\n                const fingerprintLine\n                    = SDPUtil.findLine(\n                        localSDP.media[mid],\n                        'a=fingerprint:', localSDP.session);\n\n                if (fingerprintLine) {\n                    const tmp = SDPUtil.parseFingerprint(fingerprintLine);\n\n                    tmp.required = true;\n                    cand.c(\n                        'fingerprint',\n                        { xmlns: 'urn:xmpp:jingle:apps:dtls:0' })\n                        .t(tmp.fingerprint);\n                    delete tmp.fingerprint;\n                    cand.attrs(tmp);\n                    cand.up();\n                }\n                cand.up(); // transport\n                cand.up(); // content\n            }\n        }\n\n        // might merge last-candidate notification into this, but it is called\n        // a lot later. See webrtc issue #2340\n        // logger.debug('was this the last candidate', this.lasticecandidate);\n        this.connection.sendIQ(\n            cand, null, this.newJingleErrorHandler(), IQ_TIMEOUT);\n    }\n\n    /**\n     * Starts a short-lived sampler which logs, every {@link ICE_RESTART_STATS_INTERVAL} ms for up to\n     * {@link ICE_RESTART_STATS_DURATION} ms after an ICE restart started, the number of audio/video bytes sent and\n     * received since the previous sample, video freeze/PLI/dropped-frame counters (to pin down whether a visible\n     * freeze is caused by receive-side packet loss around the pair cutover, as opposed to the send-side ICE\n     * mechanics), the currently selected ICE candidate pair (id and state) and the total number of STUN\n     * connectivity checks sent and responses received. This shows precisely when media stopped and resumed in each\n     * direction during the restart, and when connectivity checks for the new ICE generation started.\n     *\n     * This is diagnostic-only and is off unless the `testing.debugIceRestart` config option is set.\n     *\n     * @private\n     * @returns {void}\n     */\n    private _startIceRestartStatsSampler(): void {\n        if (!this.options?.testing?.debugIceRestart) {\n            return;\n        }\n\n        if (this._iceRestartStatsTimer !== null) {\n            window.clearInterval(this._iceRestartStatsTimer);\n            this._iceRestartStatsTimer = null;\n        }\n\n        const t0 = this._iceRestartT0 ?? window.performance.now();\n        let prev: Nullable<{\n            audioIn: number;\n            audioOut: number;\n            reqSent: number;\n            respRecv: number;\n            videoFramesDropped: number;\n            videoFreezeCount: number;\n            videoFreezeDurationMs: number;\n            videoIn: number;\n            videoOut: number;\n            videoPliCount: number;\n        }> = null;\n\n        const stop = () => {\n            if (this._iceRestartStatsTimer !== null) {\n                window.clearInterval(this._iceRestartStatsTimer);\n                this._iceRestartStatsTimer = null;\n            }\n            this._iceRestartT0 = null;\n        };\n\n        const sample = () => {\n            const now = window.performance.now();\n\n            if (now - t0 > ICE_RESTART_STATS_DURATION\n                    || this.state === JingleSessionState.ENDED\n                    || this.peerconnection?.signalingState === 'closed') {\n                logger.info(`${this} ${ICE_RESTART_LOG_PREFIX} t+${Math.round(now - t0)}ms: stats sampler done`);\n                stop();\n\n                return;\n            }\n\n            this.peerconnection.getStats().then(report => {\n                const cur = {\n                    audioIn: 0,\n                    audioOut: 0,\n                    reqSent: 0,\n                    respRecv: 0,\n                    videoFramesDropped: 0,\n                    videoFreezeCount: 0,\n                    videoFreezeDurationMs: 0,\n                    videoIn: 0,\n                    videoOut: 0,\n                    videoPliCount: 0\n                };\n                const pairsById = new Map<string, any>();\n                let selectedPairId: Nullable<string> = null;\n\n                report.forEach(stat => {\n                    switch (stat.type) {\n                    case 'outbound-rtp':\n                        cur[stat.kind === MediaType.AUDIO ? 'audioOut' : 'videoOut'] += stat.bytesSent ?? 0;\n                        break;\n                    case 'inbound-rtp':\n                        cur[stat.kind === MediaType.AUDIO ? 'audioIn' : 'videoIn'] += stat.bytesReceived ?? 0;\n                        if (stat.kind === MediaType.VIDEO) {\n                            cur.videoFramesDropped += stat.framesDropped ?? 0;\n                            cur.videoFreezeCount += stat.freezeCount ?? 0;\n                            cur.videoFreezeDurationMs += (stat.totalFreezesDuration ?? 0) * 1000;\n                            cur.videoPliCount += stat.pliCount ?? 0;\n                        }\n                        break;\n                    case 'candidate-pair':\n                        pairsById.set(stat.id, stat);\n                        cur.reqSent += stat.requestsSent ?? 0;\n                        cur.respRecv += stat.responsesReceived ?? 0;\n                        break;\n                    case 'transport':\n                        selectedPairId = stat.selectedCandidatePairId ?? selectedPairId;\n                        break;\n                    }\n                });\n\n                const pair = selectedPairId ? pairsById.get(selectedPairId) : undefined;\n                const pairStr = pair ? `${selectedPairId}/${pair.state}${pair.nominated ? '(nom)' : ''}` : 'none';\n                const d = (key: keyof typeof cur) => (prev === null ? cur[key] : cur[key] - prev[key]);\n\n                logger.info(`${this} ${ICE_RESTART_LOG_PREFIX} t+${Math.round(now - t0)}ms: `\n                    + `video out +${d('videoOut')}B in +${d('videoIn')}B `\n                    + `audio out +${d('audioOut')}B in +${d('audioIn')}B `\n                    + `video freezes +${d('videoFreezeCount')} (+${Math.round(d('videoFreezeDurationMs'))}ms) `\n                    + `pli +${d('videoPliCount')} framesDropped +${d('videoFramesDropped')} `\n                    + `pair=${pairStr} pairs=${pairsById.size} checks sent +${d('reqSent')} resp +${d('respRecv')}`\n                    + `${prev === null ? ' (baseline, absolute values)' : ''}`);\n                prev = cur;\n            })\n            .catch(error => {\n                logger.warn(`${this} ${ICE_RESTART_LOG_PREFIX} stats sampler failed: ${error}`);\n                stop();\n            });\n        };\n\n        // Sample periodically, and take an immediate baseline sample.\n        this._iceRestartStatsTimer = window.setInterval(sample, ICE_RESTART_STATS_INTERVAL);\n        sample();\n    }\n\n    /**\n     * Parses the `<candidate>` elements of a Jingle transport into {@link RTCIceCandidate} instances.\n     *\n     * @param {Element[]} candidateElements - the `<candidate>` elements.\n     * @returns {RTCIceCandidate[]}\n     * @private\n     */\n    private _parseIceCandidates(candidateElements: Element[]): RTCIceCandidate[] {\n        return candidateElements.map(candidate => {\n            let line = SDPUtil.candidateFromJingle(candidate);\n\n            line = line.replace('\\r\\n', '').replace('a=', '');\n\n            // FIXME this code does not care to handle\n            // non-bundle transport\n            return new RTCIceCandidate({\n                candidate: line,\n                sdpMLineIndex: 0,\n\n                // FF comes up with more complex names like audio-23423,\n                // Given that it works on both Chrome and FF without\n                // providing it, let's leave it like this for the time\n                // being...\n                // sdpMid: 'audio',\n                sdpMid: ''\n            });\n        });\n    }\n\n    /**\n     * Adds the given ICE candidates to the peer connection. The caller is responsible for the serialization with\n     * the rest of the peer connection operations (i.e. this is meant to be called from within a modification\n     * queue task).\n     *\n     * @param {RTCIceCandidate[]} iceCandidates - the candidates to add.\n     * @returns {Promise<void>} - resolves once all of the candidates have been added (or have failed to be added,\n     * which is only logged).\n     * @private\n     */\n    private _addIceCandidatesToPeerConnection(iceCandidates: RTCIceCandidate[]): Promise<void> {\n        return Promise.all(iceCandidates.map(iceCandidate => this.peerconnection.addIceCandidate(iceCandidate)\n            .then(\n                () => logger.debug(`${this} addIceCandidate ok!`),\n                err => logger.error(`${this} addIceCandidate failed!`, err))))\n            .then(() => undefined);\n    }\n\n    /**\n     * Sends a Jingle 'transport-info' carrying the local transport (the ICE credentials that the browser rotated\n     * to while answering the bridge's ICE restart offer), tagged with the `ice-generation` of that restart round.\n     * Jicofo's regular 'transport-info' handling relays it to the bridge, which needs it because it is the\n     * controlling agent: its outgoing connectivity checks have to be authenticated with our new credentials.\n     *\n     * @param {SDP} localSDP - the local session description with the new local transport.\n     * @param {number} generation - the ICE generation of the restart round these credentials belong to.\n     * @returns {void}\n     */\n    private _sendIceRestartTransportInfo(localSDP: SDP, generation: number): void {\n        const transportInfo = $iq({ to: this.remoteJid, type: 'set' })\n            .c('jingle', {\n                action: 'transport-info',\n                initiator: this.initiatorJid,\n                sid: this.sid,\n                xmlns: 'urn:xmpp:jingle:1'\n            });\n\n        localSDP.media.forEach((medialines, idx) => {\n            const mline = SDPUtil.parseMLine(medialines.split('\\r\\n')[0]);\n\n            transportInfo.c('content', {\n                creator: this.initiatorJid === this.localJid ? 'initiator' : 'responder',\n                name: mline.media\n            });\n            localSDP.transportToJingle(idx, transportInfo);\n\n            // transportToJingle() leaves the cursor back on <content>, so tag the <transport> it just appended\n            // directly rather than through the builder.\n            const transportEl = transportInfo.node?.lastElementChild;\n\n            if (transportEl?.tagName === 'transport') {\n                transportEl.setAttribute('ice-generation', String(generation));\n            } else {\n                logger.warn(`${this} ${ICE_RESTART_LOG_PREFIX} gen=${generation}: could not tag the transport `\n                    + 'with the ICE generation');\n            }\n\n            transportInfo.up();\n        });\n\n        logger.info(`${this} ${ICE_RESTART_LOG_PREFIX} gen=${generation}: signalling our new local ICE `\n            + `credentials (ufrag=${SDPUtil.getUfrag(localSDP.raw)})`);\n        this.connection.sendIQ(transportInfo, null, this.newJingleErrorHandler(), IQ_TIMEOUT);\n    }\n\n    /**\n     * Sends Jingle 'session-accept' message.\n     *\n     * @param {function()} success callback called when we receive 'RESULT' packet for the 'session-accept'.\n     * @param {function(error)} failure called when we receive an error response or when the request has timed out.\n     * @returns {void}\n     */\n    private _sendSessionAccept(success: () => void, failure: (error: IJingleError) => void, trace?: TraceParentExtension) {\n        // NOTE: since we're just reading from it, we don't need to be within\n        //  the modification queue to access the local description\n        const localSDP = new SDP(this.peerconnection.localDescription.sdp, this.isP2P);\n        const accept = $iq({ to: this.remoteJid,\n            type: 'set' })\n            .c('jingle', {\n                action: 'session-accept',\n                initiator: this.initiatorJid,\n                responder: this.responderJid,\n                sid: this.sid,\n                xmlns: 'urn:xmpp:jingle:1'\n            });\n\n        if (this.webrtcIceTcpDisable) {\n            localSDP.removeTcpCandidates = true;\n        }\n        if (this.webrtcIceUdpDisable) {\n            localSDP.removeUdpCandidates = true;\n        }\n        if (this.failICE) {\n            localSDP.failICE = true;\n        }\n        if (typeof this.options.channelLastN === 'number' && this.options.channelLastN >= 0) {\n            // @ts-ignore will be fixed after merge of sdp\n            localSDP.initialLastN = this.options.channelLastN;\n        }\n        if (trace != null) {\n            accept.c(trace.ELEMENT, trace.asAttributes()).up();\n        }\n        localSDP.toJingle(\n            accept,\n            this.initiatorJid === this.localJid ? 'initiator' : 'responder');\n\n        logger.info(`${this} Sending session-accept`);\n        logger.debug(accept.tree());\n        this.connection.sendIQ(accept,\n            success,\n            this.newJingleErrorHandler(error => {\n                failure(error);\n\n                // 'session-accept' is a critical timeout and we'll\n                // have to restart\n                this.room.eventEmitter.emit(\n                    XMPPEvents.SESSION_ACCEPT_TIMEOUT, this);\n            }),\n            IQ_TIMEOUT);\n\n        // XXX Videobridge needs WebRTC's answer (ICE ufrag and pwd, DTLS\n        // fingerprint and setup) ASAP in order to start the connection\n        // establishment.\n        //\n        // FIXME Flushing the connection at this point triggers an issue with\n        // BOSH request handling in Prosody on slow connections.\n        //\n        // The problem is that this request will be quite large and it may take\n        // time before it reaches Prosody. In the meantime Strophe may decide\n        // to send the next one. And it was observed that a small request with\n        // 'transport-info' usually follows this one. It does reach Prosody\n        // before the previous one was completely received. 'rid' on the server\n        // is increased and Prosody ignores the request with 'session-accept'.\n        // It will never reach Jicofo and everything in the request table is\n        // lost. Removing the flush does not guarantee it will never happen, but\n        // makes it much less likely('transport-info' is bundled with\n        // 'session-accept' and any immediate requests).\n        //\n        // this.connection.flush();\n    }\n\n    /**\n     * Sends 'session-initiate' to the remote peer.\n     *\n     * NOTE this method is synchronous and we're not waiting for the RESULT\n     * response which would delay the startup process.\n     *\n     * @param {string} offerSdp  - The local session description which will be used to generate an offer.\n     * @returns {void}\n     */\n    private _sendSessionInitiate(offerSdp: string): void {\n        let init = $iq({\n            to: this.remoteJid,\n            type: 'set'\n        }).c('jingle', {\n            action: 'session-initiate',\n            initiator: this.initiatorJid,\n            sid: this.sid,\n            xmlns: 'urn:xmpp:jingle:1'\n        });\n\n        new SDP(offerSdp, this.isP2P).toJingle(\n            init,\n            this.isInitiator ? 'initiator' : 'responder');\n        init = init.tree();\n        logger.debug(`${this} Session-initiate: `, init);\n        this.connection.sendIQ(init,\n            () => {\n                logger.info(`${this} Got RESULT for \"session-initiate\"`);\n            },\n            error => {\n                handleStropheError(error, {\n                    isP2P: this.isP2P,\n                    operation: 'session-initiate',\n                    remoteJid: this.remoteJid,\n                    roomJid: this.room?.roomjid,\n                    session: this.toString(),\n                    sid: this.sid,\n                    userJid: this.connection.jid\n                });\n            },\n            IQ_TIMEOUT);\n    }\n\n\n    /**\n     * Method returns function(errorResponse) which is a callback to be passed to Strophe connection.sendIQ method. An\n     * 'error' structure is created that is passed as 1st argument to given <tt>failureCb</tt>. The format of this\n     * structure is as follows:\n     * {\n     *  code: {XMPP error response code}\n     *  reason: {the name of XMPP error reason element or 'timeout' if the\n      *          request has timed out within <tt>IQ_TIMEOUT</tt> milliseconds}\n     *  source: {request.tree() that provides original request}\n     *  session: {this JingleSessionPC.toString()}\n     * }\n     * @param failureCb function(error) called when error response was returned or when a timeout has occurred.\n     * @returns {function(this:JingleSessionPC)}\n     */\n    private newJingleErrorHandler(failureCb?: (error: IJingleError) => void): ErrorCallback {\n        return errResponse => {\n            const error: IJingleError = {\n                code: undefined,\n                msg: undefined,\n                reason: undefined,\n                session: undefined\n            };\n\n            if (errResponse instanceof Element) {\n                // Get XMPP error code and condition(reason)\n                const errorElSel = findFirst(errResponse, 'error');\n\n                if (errorElSel) {\n                    error.code = getAttribute(errorElSel, 'code');\n                    const errorResponseChildren = errorElSel.children;\n\n                    if (errorResponseChildren.length) {\n                        error.reason = errorResponseChildren[0].tagName;\n                    }\n                }\n            }\n\n            if (!errResponse) {\n                error.reason = 'timeout';\n            }\n\n            // When remote peer decides to terminate the session, but it still has few messages on the queue for\n            // processing, it will first send us 'session-terminate' (we enter ENDED) and then follow with\n            // 'item-not-found' for the queued requests. These 'item-not-found' errors can be ignored.\n            const ignoreErrors = this.state === JingleSessionState.ENDED && error?.reason === 'item-not-found';\n\n            if (!ignoreErrors) {\n                failureCb?.(error);\n\n                // Call handleStropheError for centralized error logging and analytics.\n                handleStropheError(errResponse, {\n                    isP2P: this.isP2P,\n                    operation: 'Jingle IQ',\n                    remoteJid: this.remoteJid,\n                    roomJid: this.room?.roomjid,\n                    session: this.toString(),\n                    sid: this.sid,\n                    state: this.state,\n                    userJid: this.connection.jid\n                });\n            }\n        };\n    }\n\n    /**\n     * Figures out added/removed ssrcs and sends updated IQs to the remote peer or Jicofo.\n     *\n     * @param oldSDP SDP object for old description.\n     * @param newSDP SDP object for new description.\n     * @returns {void}\n     */\n    private notifyMySSRCUpdate(oldSDP: SDP, newSDP: SDP): void {\n        if (this.state !== JingleSessionState.ACTIVE) {\n            logger.warn(`${this} Skipping SSRC update in '${this.state} ' state.`);\n\n            return;\n        }\n\n        if (!this.connection.connected) {\n            // The goal is to compare the oldest SDP with the latest one upon reconnect\n            if (!this._cachedOldLocalSdp) {\n                this._cachedOldLocalSdp = oldSDP;\n            }\n            this._cachedNewLocalSdp = newSDP;\n            logger.warn(`${this} Not sending SSRC update while the signaling is disconnected`);\n\n            return;\n        }\n\n        this._cachedOldLocalSdp = undefined;\n        this._cachedNewLocalSdp = undefined;\n\n        const getSignaledSourceInfo = sdpDiffer => {\n            const newMedia = sdpDiffer.getNewMedia();\n            let ssrcs = [];\n            let mediaType = null;\n            const sourceNames = new Set<string>();\n\n            // It is assumed that sources are signaled one at a time.\n            Object.keys(newMedia).forEach(mediaIndex => {\n                const signaledSsrcs = Object.keys(newMedia[mediaIndex].ssrcs);\n\n                mediaType = newMedia[mediaIndex].mediaType;\n                if (signaledSsrcs?.length) {\n                    ssrcs = ssrcs.concat(signaledSsrcs);\n                    signaledSsrcs.forEach(ssrcNum => {\n                        const sourceName = SDPUtil.parseSourceNameLine(newMedia[mediaIndex].ssrcs[ssrcNum].lines);\n\n                        if (sourceName) {\n                            sourceNames.add(sourceName);\n                        }\n                    });\n                }\n            });\n\n            return {\n                mediaType,\n                sourceNames: Array.from(sourceNames),\n                ssrcs\n            };\n        };\n\n        // send source-remove IQ.\n        let sdpDiffer = new SDPDiffer(newSDP, oldSDP, this.isP2P);\n        const remove = $iq({ to: this.remoteJid,\n            type: 'set' })\n            .c('jingle', {\n                action: 'source-remove',\n                initiator: this.initiatorJid,\n                sid: this.sid,\n                xmlns: 'urn:xmpp:jingle:1'\n            }\n            );\n\n        sdpDiffer.toJingle(remove);\n\n        // context a common object for one run of ssrc update (source-add and source-remove) so we can match them if we\n        // need to\n        const ctx = {};\n        const removedSsrcInfo = getSignaledSourceInfo(sdpDiffer);\n\n        if (removedSsrcInfo.ssrcs.length) {\n            // Source-remove should never happen on a P2P connection. If it does, the browser has likely\n            // regenerated SSRCs for an existing source. Sending source-remove on P2P can cause the remote track to\n            // stop rendering (https://bugzilla.mozilla.org/show_bug.cgi?id=1768729), so terminate the P2P session and\n            // fall back to JVB instead.\n            if (this.isP2P) {\n                logger.warn(`${this} Unexpected source-remove on P2P for ${removedSsrcInfo.mediaType}`\n                    + ` ssrcs=${removedSsrcInfo.ssrcs} - terminating P2P session`);\n                this.room.eventEmitter.emit(XMPPEvents.P2P_TERMINATION_REQUIRED, this);\n\n                return;\n            }\n\n            // Log only the SSRCs instead of the full IQ.\n            logger.info(`${this} Sending source-remove for ${removedSsrcInfo.mediaType}`\n                + ` ssrcs=${removedSsrcInfo.ssrcs}`);\n            this.connection.sendIQ(\n                remove,\n                () => {\n                    this.room.eventEmitter.emit(XMPPEvents.SOURCE_REMOVE, this, ctx);\n                },\n                this.newJingleErrorHandler(error => {\n                    this.room.eventEmitter.emit(XMPPEvents.SOURCE_REMOVE_ERROR, this, error, ctx);\n                }),\n                IQ_TIMEOUT);\n        }\n\n        // send source-add IQ.\n        sdpDiffer = new SDPDiffer(oldSDP, newSDP, this.isP2P);\n        const add = $iq({ to: this.remoteJid,\n            type: 'set' })\n            .c('jingle', {\n                action: 'source-add',\n                initiator: this.initiatorJid,\n                sid: this.sid,\n                xmlns: 'urn:xmpp:jingle:1'\n            }\n            );\n\n        sdpDiffer.toJingle(add);\n        const addedSsrcInfo = getSignaledSourceInfo(sdpDiffer);\n\n        if (addedSsrcInfo.ssrcs.length) {\n            // Log only the SSRCs instead of the full IQ.\n            logger.info(`${this} Sending source-add for ${addedSsrcInfo.mediaType} ssrcs=${addedSsrcInfo.ssrcs}`);\n            this.connection.sendIQ(\n                add,\n                () => {\n                    this.room.eventEmitter.emit(XMPPEvents.SOURCE_ADD, this, ctx);\n                },\n                this.newJingleErrorHandler(error => {\n                    this.room.eventEmitter.emit(\n                        XMPPEvents.SOURCE_ADD_ERROR,\n                        this,\n                        error,\n                        addedSsrcInfo.mediaType,\n                        ctx,\n                        addedSsrcInfo.sourceNames);\n                }),\n                IQ_TIMEOUT);\n        }\n    }\n\n\n    /**\n     * Handles XMPP connection state changes. Resends any session updates that were cached while the XMPP connection\n     * was down.\n     *\n     * @param {Strophe.Status} status - The new status.\n     * @returns {void}\n     */\n    private onXmppStatusChanged(status: Strophe.Status): void {\n        if (status === XmppConnection.Status.CONNECTED && this._cachedOldLocalSdp) {\n            logger.info(`${this} Sending SSRC update on reconnect`);\n            this.notifyMySSRCUpdate(\n                this._cachedOldLocalSdp,\n                this._cachedNewLocalSdp);\n        }\n    }\n\n\n    /**\n     * This is a setRemoteDescription/setLocalDescription cycle which starts at converting Strophe Jingle IQ into\n     * remote offer SDP. Once converted, setRemoteDescription, createAnswer and setLocalDescription calls follow.\n     *\n     * @param jingleOfferAnswerIq element pointing to the jingle element of the offer (or answer) IQ\n     * @param success callback called when sRD/sLD cycle finishes successfully.\n     * @param failure callback called with an error object as an argument if we fail at any point during setRD,\n     * createAnswer, setLD.\n     * @param {Array<JitsiLocalTrack>} [localTracks] the optional list of the local tracks that will be added, before\n     * the offer/answer cycle executes (for the local track addition to be an atomic operation together with the\n     * offer/answer).\n     * @returns {void}\n     */\n    private setOfferAnswerCycle(jingleOfferAnswerIq: Element, success: () => void, failure: (error: Error) => void, localTracks: JitsiLocalTrack[] = []): void {\n        logger.debug(`${this} Executing setOfferAnswerCycle task`);\n\n        const addTracks = [];\n        const audioTracks = localTracks.filter(track => track.getType() === MediaType.AUDIO);\n        const videoTracks = localTracks.filter(track => track.getType() === MediaType.VIDEO);\n        let tracks = localTracks;\n\n        // Add only 1 video track at a time. Adding 2 or more video tracks to the peerconnection at the same time\n        // makes the browser go into a renegotiation loop by firing 'negotiationneeded' event after every\n        // renegotiation.\n        if (videoTracks.length > 1) {\n            tracks = [ ...audioTracks, videoTracks[0] ];\n        }\n        for (const track of tracks) {\n            addTracks.push(this.peerconnection.addTrack(track, this.isInitiator));\n        }\n        const newRemoteSdp = this._processNewJingleOfferIq(jingleOfferAnswerIq);\n        const bridgeSession = findFirst(jingleOfferAnswerIq, ':scope>bridge-session[*|xmlns=\"http://jitsi.org/protocol/focus\"]');\n        const bridgeSessionId = getAttribute(bridgeSession, 'id');\n\n        if (bridgeSessionId !== this._bridgeSessionId) {\n            this._bridgeSessionId = bridgeSessionId;\n        }\n\n        Promise.all(addTracks)\n            .then(() => this._renegotiate(newRemoteSdp.raw))\n            .then(() => {\n                this.peerconnection.processLocalSdpForTransceiverInfo(tracks);\n                if (this.state === JingleSessionState.PENDING) {\n                    this.state = JingleSessionState.ACTIVE;\n\n                    // #1 Sync up video transfer active/inactive only after the initial O/A cycle. We want to\n                    // adjust the video media direction only in the local SDP and the Jingle contents direction\n                    // included in the initial offer/answer is mapped to the remote SDP. Jingle 'content-modify'\n                    // IQ is processed in a way that it will only modify local SDP when remote peer is no longer\n                    // interested in receiving video content. Changing media direction in the remote SDP will mess\n                    // up our SDP translation chain (simulcast, video mute, RTX etc.)\n                    // #2 Sends the max frame height if it was set, before the session-initiate/accept\n                    if (this.isP2P && (!this._localSendReceiveVideoActive || this._sourceReceiverConstraints)) {\n                        this._sendContentModify();\n                    }\n                }\n\n            })\n            .then(() => {\n                logger.debug(`${this} setOfferAnswerCycle task done`);\n                success();\n            })\n            .catch(error => {\n                logger.error(`${this} setOfferAnswerCycle task failed: ${error}`);\n                failure(error);\n            });\n    }\n\n    /**\n     * Asks Jicofo to restart ICE for this endpoint on the bridge, by sending a Jingle 'session-info' carrying a\n     * `<bridge-session ice-restart=\"true\"/>`. Jicofo forwards the request to the bridge over colibri2; the bridge\n     * creates a NEW ICE agent with fresh credentials while the old one keeps carrying media, and its transport\n     * comes back to us as a 'transport-info' tagged with an `ice-generation`, handled by\n     * {@link onBridgeIceRestartTransport} - that is where the restart is actually applied.\n     *\n     * Grep the logs for `[ice-restart]` to follow a restart end to end.\n     *\n     * @param {IceRestartReason} reason - why the restart was requested, for the logs.\n     * @returns {Promise<void>} - resolves when Jicofo has acknowledged the request, rejects if it did not accept\n     * it (which is the signal to fall back to a full session restart).\n     */\n    public restartIce(reason: IceRestartReason = IceRestartReason.API): Promise<void> {\n        if (this.isP2P) {\n            return Promise.reject(new Error('an in-place ICE restart is only supported for the JVB session'));\n        }\n\n        if (!this._bridgeSessionId) {\n            return Promise.reject(new Error('no bridge session ID is known for this session'));\n        }\n\n        if (!this._assertNotEnded()) {\n            return Promise.reject(new Error('the session has ended'));\n        }\n\n        this._iceRestartT0 = window.performance.now();\n        this._startIceRestartStatsSampler();\n\n        const sessionInfo = $iq({ to: this.remoteJid, type: 'set' })\n            .c('jingle', {\n                action: 'session-info',\n                initiator: this.initiatorJid,\n                sid: this.sid,\n                xmlns: 'urn:xmpp:jingle:1'\n            })\n            .c('bridge-session', {\n                'ice-restart': true,\n                'id': this._bridgeSessionId,\n                'xmlns': 'http://jitsi.org/protocol/focus'\n            })\n            .up();\n\n        logger.info(`${this} ${ICE_RESTART_LOG_PREFIX} requesting an in-place ICE restart, reason=${reason}, `\n            + `bridgeSession=${this._bridgeSessionId}, lastAppliedGeneration=${this._lastIceGeneration}`);\n        Statistics.sendAnalytics(createJingleEvent(\n            AnalyticsEvents.ACTION_JINGLE_ICE_RESTART_REQUESTED, {\n                p2p: this.isP2P,\n                reason\n            }));\n        RTCStats.sendStatsEntry(RTCStatsEvents.ICE_RESTART_REQUESTED_EVENT, null, { reason });\n\n        return new Promise<void>((resolve, reject) => {\n            this.connection.sendIQ(\n                sessionInfo,\n                () => {\n                    logger.info(`${this} ${ICE_RESTART_LOG_PREFIX} the ICE restart request was accepted`);\n                    resolve();\n                },\n                this.newJingleErrorHandler(error => {\n                    logger.warn(`${this} ${ICE_RESTART_LOG_PREFIX} the ICE restart request was rejected: `\n                        + `${JSON.stringify(error)}`);\n                    reject(new Error(error?.reason ?? error?.msg ?? 'the ICE restart request was rejected'));\n                }),\n                IQ_TIMEOUT);\n        });\n    }\n\n    /**\n     * Applies the bridge's new ICE transport for an in-place ICE restart. Called for a Jingle 'transport-info'\n     * whose `<transport>` carries an `ice-generation` attribute, which marks it as the transport of a NEW ICE\n     * agent the bridge created in response to {@link restartIce} (as opposed to plain trickled candidates).\n     *\n     * The whole thing runs as a single modification queue task:\n     *  1. the generation is checked against the last one applied, and anything not strictly newer is dropped\n     *     (pushes can be duplicated or reordered);\n     *  2. a patched offer is built from the current remote description with the bridge's new ICE credentials\n     *     substituted in and ALL candidate lines stripped;\n     *  3. that offer is applied and answered with a real `createAnswer()` - we stay the answerer, so the restart\n     *     is entirely local and needs no signalling round trip on the critical path. The browser rotates our own\n     *     ICE credentials as part of answering;\n     *  4. only THEN are the bridge's new candidates trickled in with `addIceCandidate()`. Adding them as part of\n     *     the offer in step 2 would make libwebrtc destroy and rebuild the selected candidate pair synchronously,\n     *     which is exactly the media freeze the make-before-break design exists to avoid;\n     *  5. our new local ICE credentials are signalled back, tagged with the same generation - the bridge is the\n     *     controlling agent and needs them to authenticate its connectivity checks.\n     *\n     * @param {Element} transportEl - the `<transport>` element of the incoming 'transport-info'.\n     * @returns {void}\n     */\n    public onBridgeIceRestartTransport(transportEl: Element): void {\n        const generation = Number(transportEl.getAttribute('ice-generation'));\n        const ufrag = transportEl.getAttribute('ufrag');\n        const pwd = transportEl.getAttribute('pwd');\n        const candidates = this._parseIceCandidates(findAll(transportEl, ':scope>candidate'));\n\n        if (!Number.isInteger(generation) || generation <= 0) {\n            logger.error(`${this} ${ICE_RESTART_LOG_PREFIX} ignoring a bridge transport with an invalid ICE `\n                + `generation (${transportEl.getAttribute('ice-generation')})`);\n\n            return;\n        }\n\n        if (!ufrag || !pwd) {\n            logger.error(`${this} ${ICE_RESTART_LOG_PREFIX} gen=${generation}: ignoring a bridge transport with `\n                + 'incomplete ICE credentials');\n\n            return;\n        }\n\n        logger.info(`${this} ${ICE_RESTART_LOG_PREFIX} gen=${generation}: received the bridge's new transport, `\n            + `ufrag=${ufrag}, candidates=${candidates.length}`);\n\n        if (this._iceRestartT0 === null) {\n            this._iceRestartT0 = window.performance.now();\n            this._startIceRestartStatsSampler();\n        }\n\n        const t0 = this._iceRestartT0;\n        const dt = () => Math.round(window.performance.now() - t0);\n\n        const workFunction = async (finishedCallback: (err?: Error) => void) => {\n            try {\n                if (generation <= this._lastIceGeneration) {\n                    logger.warn(`${this} ${ICE_RESTART_LOG_PREFIX} gen=${generation}: ignoring a stale bridge `\n                        + `transport, generation ${this._lastIceGeneration} has already been applied`);\n                    finishedCallback();\n\n                    return;\n                }\n\n                const pc = this.peerconnection.peerconnection;\n                const remoteSdp = this.peerconnection.remoteDescription?.sdp;\n\n                if (!remoteSdp) {\n                    throw new Error('there is no current remote description');\n                }\n\n                logger.info(`${this} ${ICE_RESTART_LOG_PREFIX} gen=${generation} t+${dt()}ms: applying, `\n                    + `signalingState=${pc.signalingState}, iceConnectionState=${pc.iceConnectionState}`);\n                this._lastIceGeneration = generation;\n\n                // Allow the candidates the browser gathers for the new generation to be signalled.\n                this.lasticecandidate = false;\n\n                const patchedOffer = SDPUtil.replaceIceCredentialsAndStripCandidates(remoteSdp, ufrag, pwd);\n\n                // Drive the offer/answer through the regular renegotiation path rather than calling\n                // setRemoteDescription/createAnswer/setLocalDescription directly: it keeps\n                // TraceablePeerConnection's own view of the session consistent, and it signals any SSRCs the\n                // browser regenerates while answering, which would otherwise go unsignalled.\n                await this._renegotiate(patchedOffer);\n                logger.info(`${this} ${ICE_RESTART_LOG_PREFIX} gen=${generation} t+${dt()}ms: the patched offer `\n                    + `was applied (candidates stripped) and answered, signalingState=${pc.signalingState}`);\n\n                // The candidates must be added only now, after the offer/answer cycle has completed. Adding them\n                // together with the new credentials tears down the selected pair and breaks make-before-break, see\n                // SDPUtil.replaceIceCredentialsAndStripCandidates and https://issues.webrtc.org/issues/543082385\n                await this._addIceCandidatesToPeerConnection(candidates);\n                logger.info(`${this} ${ICE_RESTART_LOG_PREFIX} gen=${generation} t+${dt()}ms: `\n                    + `${candidates.length} of the bridge's candidates were added`);\n\n                this._sendIceRestartTransportInfo(\n                    new SDP(this.peerconnection.localDescription.sdp), generation);\n\n                Statistics.sendAnalytics(createJingleEvent(AnalyticsEvents.ACTION_JINGLE_ICE_RESTART_SUCCESS, {\n                    p2p: this.isP2P,\n                    value: this.sid\n                }));\n                RTCStats.sendStatsEntry(RTCStatsEvents.ICE_RESTART_APPLIED_EVENT, null, { generation });\n                logger.info(`${this} ${ICE_RESTART_LOG_PREFIX} gen=${generation} t+${dt()}ms: done`);\n                finishedCallback();\n            } catch (error) {\n                logger.error(`${this} ${ICE_RESTART_LOG_PREFIX} gen=${generation} t+${dt()}ms: failed`, error);\n                finishedCallback(error as Error);\n            } finally {\n                // The stats sampler, when it is enabled, owns _iceRestartT0 and resets it when it is done.\n                if (this._iceRestartStatsTimer === null) {\n                    this._iceRestartT0 = null;\n                }\n            }\n        };\n\n        this.modificationQueue.push(workFunction, (error?: Error) => {\n            if (error && !(error instanceof ClearedQueueError)) {\n                logger.error(`${this} ${ICE_RESTART_LOG_PREFIX} gen=${generation}: the task failed: ${error}`);\n            }\n        });\n    }\n\n    /**\n     * Accepts incoming Jingle 'session-initiate' and should send 'session-accept' in result.\n     *\n     * @param jingleOffer element pointing to the jingle element of the offer IQ\n     * @param success callback called when we accept incoming session successfully and receive RESULT packet to\n     * 'session-accept' sent.\n     * @param failure function(error) called if for any reason we fail to accept the incoming offer. 'error' argument\n     * can be used to log some details about the error.\n     * @param {Array<JitsiLocalTrack>} [localTracks] the optional list of the local tracks that will be added, before\n     * the offer/answer cycle executes. We allow the localTracks to optionally be passed in so that the addition of the\n     * local tracks and the processing of the initial offer can all be done atomically. We want to make sure that any\n     * other operations which originate in the XMPP Jingle messages related with this session to be executed with an\n     * assumption that the initial offer/answer cycle has been executed already.\n     */\n    public override acceptOffer(\n            jingleOffer: Element,\n            success: () => void,\n            failure: (error: any) => void,\n            localTracks: JitsiLocalTrack[] = []): void {\n        const trace = TraceParentExtension.fromElement(jingleOffer);\n\n        this.setOfferAnswerCycle(\n            jingleOffer,\n            () => {\n                // FIXME we may not care about RESULT packet for session-accept\n                // then we should either call 'success' here immediately or\n                // modify sendSessionAccept method to do that\n                this._sendSessionAccept(() => {\n                    // Start processing tasks on the modification queue.\n                    logger.debug(`${this} Resuming the modification queue after session is established!`);\n                    this.modificationQueue.resume();\n\n                    success();\n                    this.room.eventEmitter.emit(XMPPEvents.SESSION_ACCEPT, this);\n\n                    // The first video track is added to the peerconnection and signaled as part of the session-accept.\n                    // Add secondary video tracks (that were already added to conference) to the peerconnection here.\n                    // This will happen when someone shares a secondary source to a two people call, the other user\n                    // leaves and joins the call again, a new peerconnection is created for p2p/jvb connection. At this\n                    // point, there are 2 video tracks which need to be signaled to the remote peer.\n                    const videoTracks = localTracks.filter(track => track.getType() === MediaType.VIDEO);\n\n                    videoTracks.length && videoTracks.splice(0, 1);\n                    videoTracks.length && this.addTracks(videoTracks);\n                },\n                error => {\n                    failure(error);\n                    this.room.eventEmitter.emit(XMPPEvents.SESSION_ACCEPT_ERROR, this, error);\n                }, trace);\n            },\n            failure,\n            localTracks);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    public override addIceCandidates(elem: Element): void {\n        if (this.peerconnection.signalingState === 'closed') {\n            logger.warn(`${this} Ignored add ICE candidate when in closed state`);\n\n            return;\n        }\n\n        const iceCandidates = this._parseIceCandidates(findAll(elem, ':scope>content>transport>candidate'));\n\n        if (!iceCandidates.length) {\n            logger.error(`${this} No ICE candidates to add ?`, elem[0]?.outerHTML);\n\n            return;\n        }\n\n        // We want to have this task queued, so that we know it is executed,\n        // after the initial sRD/sLD offer/answer cycle was done (based on\n        // the assumption that candidates are spawned after the offer/answer\n        // and XMPP preserves order).\n        const workFunction = finishedCallback => {\n            this._addIceCandidatesToPeerConnection(iceCandidates);\n\n            finishedCallback();\n            logger.debug(`${this} ICE candidates task finished`);\n        };\n\n        logger.debug(`${this} Queued add (${iceCandidates.length}) ICE candidates task`);\n        this.modificationQueue.push(workFunction);\n    }\n\n    /**\n     * Handles a Jingle source-add message for this Jingle session.\n     *\n     * @param {Array<Element>} elem an array of Jingle \"content\" elements.\n     * @returns {Promise} resolved when the operation is done or rejected with an error.\n     */\n    public addRemoteStream(elem: Element[]): void {\n        this._addOrRemoveRemoteStream(true /* add */, elem);\n    }\n\n    /**\n     * Adds a new track to the peerconnection. This method needs to be called only when a secondary JitsiLocalTrack is\n     * being added to the peerconnection for the first time.\n     *\n     * @param {Array<JitsiLocalTrack>} localTracks - Tracks to be added to the peer connection.\n     * @returns {Promise<void>} that resolves when the track is successfully added to the peerconnection, rejected\n     * otherwise.\n     */\n    public addTracks(localTracks: Nullable<JitsiLocalTrack[]> = null): Promise<void> {\n        if (!localTracks?.length) {\n            Promise.reject(new Error('No tracks passed'));\n        }\n\n        const replaceTracks = [];\n        const workFunction = finishedCallback => {\n            const remoteSdp = new SDP(this.peerconnection.remoteDescription.sdp, this.isP2P);\n            const recvOnlyTransceiver = this.peerconnection.peerconnection.getTransceivers()\n                    .find(t => t.receiver.track.kind === MediaType.VIDEO\n                        && t.direction === MediaDirection.RECVONLY\n                        && t.currentDirection === MediaDirection.RECVONLY);\n\n            // Add transceivers by adding a new mline in the remote description for each track. Do not create a new\n            // m-line if a recv-only transceiver exists in the p2p case. The new track will be attached to the\n            // existing one in that case.\n            for (const track of localTracks) {\n                if (!this.isP2P || !recvOnlyTransceiver) {\n                    remoteSdp.addMlineForNewSource(track.getType());\n                }\n            }\n\n            this._renegotiate(remoteSdp.raw)\n                .then(() => {\n                    // Replace the tracks on the newly generated transceivers.\n                    for (const track of localTracks) {\n                        replaceTracks.push(this.peerconnection.replaceTrack(null, track));\n                    }\n\n                    return Promise.all(replaceTracks);\n                })\n\n                // Trigger a renegotiation here since renegotiations are suppressed at TPC.replaceTrack for screenshare\n                // tracks. This is done here so that presence for screenshare tracks is sent before signaling.\n                .then(() => this._renegotiate())\n                .then(() => finishedCallback(), error => finishedCallback(error));\n        };\n\n        return new Promise((resolve, reject) => {\n            logger.debug(`${this} Queued renegotiation after addTrack`);\n\n            this.modificationQueue.push(\n                workFunction,\n                error => {\n                    if (error) {\n                        if (error instanceof ClearedQueueError) {\n                            // The session might have been terminated before the task was executed, making it obsolete.\n                            logger.debug(`${this} renegotiation after addTrack aborted: session terminated`);\n                            resolve();\n\n                            return;\n                        }\n                        logger.error(`${this} renegotiation after addTrack error`, error);\n                        reject(error);\n                    } else {\n                        logger.debug(`${this} renegotiation after addTrack executed - OK`);\n                        resolve();\n                    }\n                });\n        });\n    }\n\n    /**\n     * Adds local track back to the peerconnection associated with this session.\n     *\n     * @param {JitsiLocalTrack} track - the local track to be added back to the peerconnection.\n     * @return {Promise} a promise that will resolve once the local track is added back to this session and\n     * renegotiation succeeds (if its warranted). Will be rejected with a <tt>string</tt> that provides some error\n     * details in case something goes wrong.\n     * @returns {Promise<void>}\n     */\n    public addTrackToPc(track: JitsiLocalTrack): Promise<void> {\n        return this._addRemoveTrack(false /* add */, track)\n            .then(async () => {\n                // Configure the video encodings after the track is unmuted. If the user joins the call muted and\n                // unmutes it the first time, all the parameters need to be configured.\n                if (track.isVideoTrack()) {\n                    await this.peerconnection.configureVideoSenderEncodings(track);\n                }\n            });\n    }\n\n    /**\n     * Closes the underlying peerconnection and shuts down the modification queue.\n     *\n     * @returns {void}\n     */\n    public close(): void {\n        this.state = JingleSessionState.ENDED;\n        this.establishmentDuration = undefined;\n\n        this._audioWedgeDetector?.stop();\n        this._audioWedgeDetector = null;\n\n        if (this._iceRestartStatsTimer !== null) {\n            window.clearInterval(this._iceRestartStatsTimer);\n            this._iceRestartStatsTimer = null;\n        }\n        this._iceRestartT0 = null;\n\n        if (this.peerconnection) {\n            this.peerconnection.onicecandidate = null;\n            this.peerconnection.oniceconnectionstatechange = null;\n            this.peerconnection.onnegotiationneeded = null;\n            this.peerconnection.onsignalingstatechange = null;\n        }\n\n        logger.debug(`${this} Clearing modificationQueue`);\n\n        // Remove any pending tasks from the queue\n        this.modificationQueue.clear();\n\n        logger.debug(`${this} Queued PC close task`);\n        this.modificationQueue.push(finishCallback => {\n            // do not try to close if already closed.\n            this.peerconnection?.close();\n            finishCallback();\n            logger.debug(`${this} PC close task done!`);\n        });\n\n        logger.debug(`${this} Shutdown modificationQueue!`);\n\n        // No more tasks can go in after the close task\n        this.modificationQueue.shutdown();\n    }\n\n    /**\n     * @inheritDoc\n     * @param {JingleSessionPCOptions} options  - a set of config options.\n     * @returns {void}\n     */\n    public override doInitialize(options: IJingleSessionPCOptions): void {\n        this.failICE = Boolean(options.testing?.failICE);\n        this.lasticecandidate = false;\n        this.options = options;\n\n        /**\n         * {@code true} if reconnect is in progress.\n         * @type {boolean}\n         */\n        this.isReconnect = false;\n\n        /**\n         * Set to {@code true} if the connection was ever stable\n         * @type {boolean}\n         */\n        this.wasstable = false;\n        this.webrtcIceUdpDisable = Boolean(options.webrtcIceUdpDisable);\n        this.webrtcIceTcpDisable = Boolean(options.webrtcIceTcpDisable);\n\n        const pcOptions = {\n            audioQuality: options.audioQuality,\n            capScreenshareBitrate: undefined,\n            codecSettings: options.codecSettings,\n            disableRtx: options.disableRtx,\n            disableSimulcast: this.isP2P ? true : options.disableSimulcast,\n            enableInsertableStreams: options.enableInsertableStreams,\n            forceTurnRelay: options.forceTurnRelay,\n            maxstats: undefined,\n            startSilent: undefined,\n            usesCodecSelectionAPI: undefined,\n            videoQuality: undefined\n        };\n\n        if (options.gatherStats) {\n            pcOptions.maxstats = DEFAULT_MAX_STATS;\n        }\n        pcOptions.usesCodecSelectionAPI = this.usesCodecSelectionAPI\n            = browser.supportsCodecSelectionAPI()\n            && (options.testing?.enableCodecSelectionAPI ?? true)\n            && !this.isP2P;\n\n        if (options.videoQuality) {\n            const settings = Object.entries(options.videoQuality)\n            .map(entry => {\n                entry[0] = entry[0].toLowerCase();\n\n                return entry;\n            });\n\n            pcOptions.videoQuality = Object.fromEntries(settings);\n        }\n\n        if (!this.isP2P) {\n            // Do not send lower spatial layers for low fps screenshare and enable them only for high fps screenshare.\n            pcOptions.capScreenshareBitrate = !(options.desktopSharingFrameRate?.max > SS_DEFAULT_FRAME_RATE);\n        }\n\n        if (options.startSilent) {\n            pcOptions.startSilent = true;\n        }\n\n        this.peerconnection\n            = this.rtc.createPeerConnection(\n                    this._signalingLayer,\n                    this.pcConfig,\n                    this.isP2P,\n                    pcOptions);\n\n        this.peerconnection.onicecandidate = ev => {\n            if (!ev) {\n                // There was an incomplete check for ev before which left\n                // the last line of the function unprotected from a potential\n                // throw of an exception. Consequently, it may be argued that\n                // the check is unnecessary. Anyway, I'm leaving it and making\n                // the check complete.\n                return;\n            }\n\n            // XXX this is broken, candidate is not parsed.\n            const candidate = ev.candidate;\n            const now = window.performance.now();\n\n            if (this._iceRestartT0 !== null && this.options?.testing?.debugIceRestart) {\n                const t = Math.round(now - this._iceRestartT0);\n\n                if (candidate) {\n                    logger.info(`${this} ${ICE_RESTART_LOG_PREFIX} gen=${this._lastIceGeneration} t+${t}ms: `\n                        + `local candidate gathered (${candidate.type}/${candidate.protocol}, `\n                        + `mid=${candidate.sdpMid})`);\n                } else {\n                    logger.info(`${this} ${ICE_RESTART_LOG_PREFIX} gen=${this._lastIceGeneration} t+${t}ms: `\n                        + 'end of local candidate gathering');\n                }\n            }\n\n            if (candidate) {\n                if (this._gatheringStartedTimestamp === null) {\n                    this._gatheringStartedTimestamp = now;\n                }\n\n                // Discard candidates of disabled protocols.\n                let protocol = candidate.protocol as string;\n\n                if (typeof protocol === 'string') {\n                    protocol = protocol.toLowerCase();\n                    if (protocol === 'tcp' || protocol === 'ssltcp') {\n                        if (this.webrtcIceTcpDisable) {\n                            return;\n                        }\n                    } else if (protocol === 'udp') {\n                        if (this.webrtcIceUdpDisable) {\n                            return;\n                        }\n                    }\n                }\n            } else if (!this._gatheringReported) {\n                // End of gathering\n                Statistics.sendAnalytics(\n                    AnalyticsEvents.ICE_DURATION,\n                    {\n                        initiator: this.isInitiator,\n                        p2p: this.isP2P,\n                        phase: 'gathering',\n                        value: now - this._gatheringStartedTimestamp\n                    });\n                this._gatheringReported = true;\n            }\n            if (this.isP2P) {\n                this._sendIceCandidate(candidate);\n            }\n        };\n\n        // Note there is a change in the spec about closed:\n        // This value moved into the RTCPeerConnectionState enum in\n        // the May 13, 2016 draft of the specification, as it reflects the state\n        // of the RTCPeerConnection, not the signaling connection. You now\n        // detect a closed connection by checking for connectionState to be\n        // \"closed\" instead.\n        // I suppose at some point this will be moved to onconnectionstatechange\n        this.peerconnection.onsignalingstatechange = () => {\n            if (this.peerconnection.signalingState === 'stable') {\n                this.wasstable = true;\n            } else if (this.peerconnection.signalingState === 'closed'\n                || this.peerconnection.connectionState === 'closed') {\n                this.room.eventEmitter.emit(XMPPEvents.SUSPEND_DETECTED, this);\n            }\n        };\n\n        /**\n         * The oniceconnectionstatechange event handler contains the code to\n         * execute when the iceconnectionstatechange event, of type Event,\n         * is received by this RTCPeerConnection. Such an event is sent when\n         * the value of RTCPeerConnection.iceConnectionState changes.\n         */\n        this.peerconnection.oniceconnectionstatechange = () => {\n            const now = window.performance.now();\n            let isStable = false;\n\n            if (!this.isP2P) {\n                this.room.connectionTimes[\n                    `ice.state.${this.peerconnection.iceConnectionState}`]\n                    = now;\n            }\n            logger.info(`(TIME) ICE ${this.peerconnection.iceConnectionState} ${this.isP2P ? 'P2P' : 'JVB'}:\\t`, now);\n\n            Statistics.sendAnalytics(\n                AnalyticsEvents.ICE_STATE_CHANGED,\n                {\n                    p2p: this.isP2P,\n                    reconnect: this.isReconnect,\n                    'signaling_state': this.peerconnection.signalingState,\n                    state: this.peerconnection.iceConnectionState,\n                    value: now\n                });\n\n            this.room.eventEmitter.emit(\n                XMPPEvents.ICE_CONNECTION_STATE_CHANGED,\n                this,\n                this.peerconnection.iceConnectionState);\n            switch (this.peerconnection.iceConnectionState) {\n            case 'checking':\n                this._iceCheckingStartedTimestamp = now;\n                break;\n            case 'connected':\n            case 'completed':\n                // Informs interested parties that the connection has been restored. This includes the case when\n                // media connection to the bridge has been restored after an ICE failure by using session-terminate.\n                if (this.peerconnection.signalingState === 'stable') {\n                    isStable = true;\n                    this.room.eventEmitter.emit(XMPPEvents.CONNECTION_RESTORED, this);\n                }\n\n                this._maybeStartAudioWedgeDetector();\n\n                // Add a workaround for an issue on chrome in Unified plan when the local endpoint is the offerer.\n                // The 'signalingstatechange' event for 'stable' is handled after the 'iceconnectionstatechange' event\n                // for 'completed' is handled by the client. This prevents the client from firing a\n                // CONNECTION_ESTABLISHED event for the p2p session. As a result, the offerer continues to stay on the\n                // jvb connection while the remote peer switches to the p2p connection breaking the media flow between\n                // the endpoints.\n                // TODO - file a chromium bug and add the information here.\n                if (!this.wasConnected\n                    && (this.wasstable\n                        || isStable\n                        || (this.isInitiator && (browser.isChromiumBased() || browser.isReactNative())))) {\n\n                    Statistics.sendAnalytics(\n                        AnalyticsEvents.ICE_DURATION,\n                        {\n                            initiator: this.isInitiator,\n                            p2p: this.isP2P,\n                            phase: 'checking',\n                            value: now - this._iceCheckingStartedTimestamp\n                        });\n\n                    // Switch between ICE gathering and ICE checking whichever\n                    // started first (scenarios are different for initiator\n                    // vs responder)\n                    const iceStarted\n                        = Math.min(\n                            this._iceCheckingStartedTimestamp,\n                            this._gatheringStartedTimestamp);\n\n                    this.establishmentDuration = now - iceStarted;\n\n                    Statistics.sendAnalytics(\n                        AnalyticsEvents.ICE_DURATION,\n                        {\n                            initiator: this.isInitiator,\n                            p2p: this.isP2P,\n                            phase: 'establishment',\n                            value: this.establishmentDuration\n                        });\n\n                    this.wasConnected = true;\n                    this.room.eventEmitter.emit(\n                        XMPPEvents.CONNECTION_ESTABLISHED, this);\n                }\n                this.isReconnect = false;\n                break;\n            case 'disconnected':\n                this.isReconnect = true;\n\n                // Informs interested parties that the connection has been\n                // interrupted.\n                if (this.wasstable) {\n                    this.room.eventEmitter.emit(\n                        XMPPEvents.CONNECTION_INTERRUPTED, this);\n                }\n                break;\n            case 'failed':\n                this.room.eventEmitter.emit(\n                    XMPPEvents.CONNECTION_ICE_FAILED, this);\n                break;\n            }\n        };\n\n\n        /**\n         * The connection state event is fired whenever the aggregate of underlying\n         * transports change their state.\n         */\n        this.peerconnection.onconnectionstatechange = () => {\n            const icestate = this.peerconnection.iceConnectionState;\n\n            logger.info(`(TIME) ${this.isP2P ? 'P2P' : 'JVB'} PC state is now ${this.peerconnection.connectionState} `\n                + `(ICE state ${this.peerconnection.iceConnectionState}):\\t`, window.performance.now());\n\n            switch (this.peerconnection.connectionState) {\n            case 'failed':\n                // Since version 76 Chrome no longer switches ICE connection\n                // state to failed (see\n                // https://bugs.chromium.org/p/chromium/issues/detail?id=982793\n                // for details) we use this workaround to recover from lost connections\n                if (icestate === 'disconnected') {\n                    this.room.eventEmitter.emit(\n                        XMPPEvents.CONNECTION_ICE_FAILED, this);\n                }\n                break;\n            }\n        };\n\n        /**\n         * The negotiationneeded event is fired whenever we shake the media on the\n         * RTCPeerConnection object.\n         */\n        this.peerconnection.onnegotiationneeded = () => {\n            const state = this.peerconnection.signalingState;\n            const remoteDescription = this.peerconnection.remoteDescription;\n\n            if (!this.isP2P\n                && state === 'stable'\n                && remoteDescription\n                && typeof remoteDescription.sdp === 'string') {\n                logger.info(`${this} onnegotiationneeded fired on ${this.peerconnection}`);\n\n                const workFunction = async finishedCallback => {\n                    try {\n                        await this._renegotiate();\n                        await this.peerconnection.configureAudioSenderEncodings();\n                        finishedCallback();\n                    } catch (error) {\n                        finishedCallback(error);\n                    }\n                };\n\n                this.modificationQueue.push(\n                    workFunction,\n                    error => {\n                        if (error) {\n                            logger.error(`${this} onnegotiationneeded error`, error);\n                        } else {\n                            logger.debug(`${this} onnegotiationneeded executed - OK`);\n                        }\n                    });\n            }\n        };\n    }\n\n    /**\n     * Returns the ice connection state for the peer connection.\n     *\n     * @returns the ice connection state for the peer connection.\n     */\n    public getIceConnectionState(): RTCIceConnectionState {\n        return this.peerconnection.getConnectionState();\n    }\n\n    /**\n     * Returns the preference for max frame height for the remote video sources.\n     *\n     * @returns {Optional<$Map<string, number>>}\n     */\n    public getRemoteSourcesRecvMaxFrameHeight(): Optional<ISourceFrameHeight[]> {\n        if (this.isP2P) {\n            return this.remoteSourceMaxFrameHeights;\n        }\n\n        return undefined;\n    }\n\n    /**\n     * Creates an offer and sends Jingle 'session-initiate' to the remote peer.\n     *\n     * @param {Array<JitsiLocalTrack>} localTracks the local tracks that will be added, before the offer/answer cycle\n     * executes (for the local track addition to be an atomic operation together with the offer/answer).\n     * @returns {Promise<void>} that resolves when the offer is sent to the remote peer, rejected otherwise.\n     */\n    public async invite(localTracks: JitsiLocalTrack[] = []): Promise<void> {\n        if (!this.isInitiator) {\n            throw new Error('Trying to invite from the responder session');\n        }\n        logger.debug(`${this} Executing invite task`);\n\n        const addTracks = [];\n\n        for (const track of localTracks) {\n            addTracks.push(this.peerconnection.addTrack(track, this.isInitiator));\n        }\n\n        try {\n            await Promise.all(addTracks);\n            const offerSdp = await this.peerconnection.createOffer(this.mediaConstraints as RTCOfferOptions);\n\n            await this.peerconnection.setLocalDescription(offerSdp);\n            this.peerconnection.processLocalSdpForTransceiverInfo(localTracks);\n            this._sendSessionInitiate(this.peerconnection.localDescription.sdp);\n\n            logger.debug(`${this} invite executed - OK`);\n        } catch (error) {\n            logger.error(`${this} invite error`, error);\n            throw error;\n        }\n    }\n\n    /**\n     * Enables/disables local video based on 'senders' attribute of the video conent in 'content-modify' IQ sent by the\n     * remote peer. Also, checks if the sourceMaxFrameHeight (as requested by the p2p peer) or the senders attribute of\n     * the video content has changed and modifies the local video resolution accordingly.\n     *\n     * @param {Element} jingleContents - The content of the 'content-modify' IQ sent by the remote peer.\n     * @returns {void}\n     */\n    public modifyContents(jingleContents: Element): void {\n        const newVideoSenders = JingleSessionPC.parseVideoSenders(jingleContents);\n        const sourceMaxFrameHeights = JingleSessionPC.parseSourceMaxFrameHeight(jingleContents);\n\n        if (sourceMaxFrameHeights) {\n            this.remoteSourceMaxFrameHeights = sourceMaxFrameHeights;\n            this.eventEmitter.emit(MediaSessionEvents.REMOTE_SOURCE_CONSTRAINTS_CHANGED, this, sourceMaxFrameHeights);\n        }\n\n        if (newVideoSenders === null) {\n            logger.error(`${this} - failed to parse video \"senders\" attribute in \"content-modify\" action`);\n\n            return;\n        }\n\n        if (!this._assertNotEnded()) {\n            return;\n        }\n\n        const isRemoteVideoActive\n            = newVideoSenders === 'both'\n                || (newVideoSenders === 'initiator' && this.isInitiator)\n                || (newVideoSenders === 'responder' && !this.isInitiator);\n\n        if (isRemoteVideoActive !== this._remoteSendReceiveVideoActive) {\n            logger.debug(`${this} new remote video active: ${isRemoteVideoActive}`);\n            this._remoteSendReceiveVideoActive = isRemoteVideoActive;\n\n            this.peerconnection\n                .setVideoTransferActive(this._localSendReceiveVideoActive && this._remoteSendReceiveVideoActive);\n        }\n    }\n\n    /**\n     * Handles the termination of the session.\n     *\n     * @param {string} reasonCondition - The XMPP Jingle reason condition.\n     * @param {string} reasonText - The XMPP Jingle reason text.\n     * @returns {void}\n     */\n    public onTerminated(reasonCondition: string, reasonText: string) {\n        // Do something with reason and reasonCondition when we start to care\n        // this.reasonCondition = reasonCondition;\n        // this.reasonText = reasonText;\n        logger.info(`${this} Session terminated`, reasonCondition, reasonText);\n\n        this._xmppListeners.forEach(removeListener => removeListener());\n        this._xmppListeners = [];\n\n        if (this._removeSenderVideoConstraintsChangeListener) {\n            this._removeSenderVideoConstraintsChangeListener();\n        }\n\n        if (FeatureFlags.isSsrcRewritingSupported() && this.peerconnection) {\n            this.peerconnection.getRemoteTracks().forEach(track => {\n                this.room.eventEmitter.emit(JitsiConferenceEvents.TRACK_REMOVED, track);\n            });\n        }\n\n        this.close();\n    }\n\n    /**\n     * Processes the source map message received from the bridge and creates a new remote track for newly signaled\n     * SSRCs or updates the source-name and owner on the remote track for an existing SSRC.\n     *\n     * @param {Object} message - The source map message.\n     * @param {string} mediaType - The media type, 'audio' or 'video'.\n     * @returns {void}\n     */\n    public processSourceMap(message: any, mediaType: MediaType): void {\n        if (!FeatureFlags.isSsrcRewritingSupported()) {\n            return;\n        }\n\n        if (mediaType === MediaType.AUDIO && this.options.startSilent) {\n\n            return;\n        }\n\n        const newSsrcs = [];\n\n        for (const src of message.mappedSources) {\n            const { owner, source, ssrc } = src;\n            const isNewSsrc = this.peerconnection.addRemoteSsrc(ssrc);\n\n            if (isNewSsrc) {\n                newSsrcs.push(src);\n                logger.debug(`New SSRC signaled ${ssrc}: owner=${owner}, source-name=${source}`);\n\n                // Check if there is an old mapping for the given source and clear the owner on the associated track.\n                const oldSsrc = this.peerconnection.remoteSources.get(source);\n\n                if (oldSsrc) {\n                    this._signalingLayer.removeSSRCOwners([ oldSsrc ]);\n                    const track = this.peerconnection.getTrackBySSRC(oldSsrc);\n\n                    if (track) {\n                        this.room.eventEmitter.emit(JitsiTrackEvents.TRACK_OWNER_SET, track);\n                    }\n                }\n            } else {\n                const track = this.peerconnection.getTrackBySSRC(ssrc);\n\n                if (!track || (track.getParticipantId() === owner && track.getSourceName() === source)) {\n                    !track && logger.warn(`Remote track for SSRC=${ssrc} hasn't been created yet,`\n                        + 'not processing the source map');\n                    continue; // eslint-disable-line no-continue\n                }\n                logger.debug(`Existing SSRC re-mapped ${ssrc}: new owner=${owner}, source-name=${source}`);\n\n                this._signalingLayer.setSSRCOwner(ssrc, owner, source);\n                const oldSourceName = track.getSourceName();\n                const sourceInfo = this.peerconnection.getRemoteSourceInfoBySourceName(oldSourceName);\n\n                // Update the SSRC map on the peerconnection.\n                if (sourceInfo) {\n                    this.peerconnection.updateRemoteSources(new Map([ [ oldSourceName, sourceInfo ] ]), false);\n                    this.peerconnection.updateRemoteSources(new Map([ [ source, sourceInfo ] ]), true /* isAdd */);\n                }\n\n                // Update the muted state and the video type on the track since the presence for this track could have\n                // been received before the updated source map is received on the bridge channel.\n                const { muted, videoType } = this._signalingLayer.getPeerMediaInfo(owner, mediaType, source);\n\n                typeof muted !== 'undefined' && this.peerconnection._sourceMutedChanged(source, muted);\n                this.room.eventEmitter.emit(JitsiTrackEvents.TRACK_OWNER_SET, track, owner, source, videoType);\n            }\n        }\n\n        // Add the new SSRCs to the remote description by generating a source message.\n        if (newSsrcs.length) {\n            let node = $build('content', {\n                name: mediaType,\n                xmlns: 'urn:xmpp:jingle:1'\n            }).c('description', {\n                media: mediaType,\n                xmlns: XEP.RTP_MEDIA\n            });\n\n            for (const src of newSsrcs) {\n                const { rtx, ssrc, source } = src;\n                let msid;\n\n                if (mediaType === MediaType.VIDEO) {\n                    const idx = ++this.numRemoteVideoSources;\n\n                    msid = `remote-video-${idx} remote-video-${idx}`;\n\n                    if (rtx !== '-1') {\n                        _addSourceElement(node, src, rtx, msid);\n                        node.c('ssrc-group', {\n                            semantics: SSRC_GROUP_SEMANTICS.FID,\n                            xmlns: XEP.SOURCE_ATTRIBUTES\n                        })\n                            .c('source', {\n                                ssrc,\n                                xmlns: XEP.SOURCE_ATTRIBUTES\n                            })\n                            .up()\n                            .c('source', {\n                                ssrc: rtx,\n                                xmlns: XEP.SOURCE_ATTRIBUTES\n                            })\n                            .up()\n                            .up();\n                    }\n                } else {\n                    const idx = ++this.numRemoteAudioSources;\n\n                    msid = `remote-audio-${idx} remote-audio-${idx}`;\n                }\n                _addSourceElement(node, src, ssrc, msid);\n                this.peerconnection.remoteSources.set(source, ssrc);\n            }\n            node = node.up();\n            this._addOrRemoveRemoteStream(true /* add */, node.node);\n        }\n    }\n\n    /**\n     * Handles a Jingle source-remove message for this Jingle session.\n     *\n     * @param {Array<Element>} contents - An array of content elements from the source-remove message.\n     * @returns {void}\n     */\n    public removeRemoteStream(elem: Element[]): void {\n        this._addOrRemoveRemoteStream(false /* remove */, elem);\n    }\n\n    /**\n     * Handles the deletion of SSRCs associated with a remote user from the remote description when the user leaves.\n     *\n     * @param {string} id Endpoint id of the participant that has left the call.\n     * @returns {void}\n     */\n    public removeRemoteStreamsOnLeave(id: string): void {\n        const workFunction = finishCallback => {\n            const removeSsrcInfo = this.peerconnection.getRemoteSourceInfoByParticipant(id);\n\n            if (removeSsrcInfo.size) {\n                logger.debug(`${this} Removing SSRCs for user ${id}, sources=${Array.from(removeSsrcInfo.keys())}`);\n                const newRemoteSdp = new SDP(this.peerconnection.remoteDescription.sdp, this.isP2P);\n\n                newRemoteSdp.updateRemoteSources(removeSsrcInfo, false /* isAdd */);\n                this.peerconnection.updateRemoteSources(removeSsrcInfo, false /* isAdd */);\n\n                this._renegotiate(newRemoteSdp.raw)\n                    .then(() => finishCallback(), error => finishCallback(error));\n            } else {\n                finishCallback();\n            }\n        };\n\n        logger.debug(`${this} Queued removeRemoteStreamsOnLeave task for participant ${id}`);\n\n        this.modificationQueue.push(\n            workFunction,\n            error => {\n                if (error) {\n                    logger.error(`${this} removeRemoteStreamsOnLeave error:`, error);\n                } else {\n                    logger.info(`${this} removeRemoteStreamsOnLeave done!`);\n                }\n            });\n    }\n\n    /**\n     * Removes local track from the peerconnection as part of the mute operation.\n     *\n     * @param {JitsiLocalTrack} track the local track to be removed.\n     * @return {Promise} a promise which will be resolved once the local track is removed from this session or rejected\n     * with a <tt>string</tt> that the describes the error if anything goes wrong.\n     */\n    public removeTrackFromPc(track: JitsiLocalTrack): Promise<void> {\n        return this._addRemoveTrack(true /* remove */, track);\n    }\n\n    /**\n     * Replaces <tt>oldTrack</tt> with <tt>newTrack</tt> and performs a single offer/answer cycle (if needed) after\n     * both operations are done.\n     * <tt>oldTrack</tt> or <tt>newTrack</tt> can be null; replacing a valid <tt>oldTrack</tt> with a null\n     * <tt>newTrack</tt> effectively just removes <tt>oldTrack</tt>.\n     *\n     * @param {Nullable<JitsiLocalTrack>} oldTrack the current track in use to be replaced.\n     * @param {Nullable<JitsiLocalTrack>} newTrack the new track to use.\n     * @returns {Promise} which resolves once the replacement is complete with no arguments or rejects with an error.\n     */\n    public replaceTrack(oldTrack: Nullable<JitsiLocalTrack>, newTrack: Nullable<JitsiLocalTrack>): Promise<void> {\n        const workFunction = finishedCallback => {\n            logger.debug(`${this} replaceTrack worker started. oldTrack = ${oldTrack}, newTrack = ${newTrack}`);\n\n            this.peerconnection.replaceTrack(oldTrack, newTrack)\n                .then(shouldRenegotiate => {\n                    let promise = Promise.resolve();\n\n                    logger.debug(`${this} TPC.replaceTrack finished. shouldRenegotiate = ${\n                        shouldRenegotiate}, JingleSessionState = ${this.state}`);\n\n                    if (shouldRenegotiate && (oldTrack || newTrack) && this.state === JingleSessionState.ACTIVE) {\n                        promise = this._renegotiate();\n                    }\n\n                    return promise.then(() => {\n                        // Set the source name of the new track.\n                        if (oldTrack && newTrack && oldTrack.isVideoTrack()) {\n                            newTrack.setSourceName(oldTrack.getSourceName());\n                        }\n                    });\n                })\n                .then(() => finishedCallback(), error => finishedCallback(error));\n        };\n\n        return new Promise((resolve, reject) => {\n            logger.debug(`${this} Queued replaceTrack task. Old track = ${oldTrack}, new track = ${newTrack}`);\n\n            this.modificationQueue.push(\n                workFunction,\n                error => {\n                    if (error) {\n                        if (error instanceof ClearedQueueError) {\n                            // The session might have been terminated before the task was executed, making it obsolete.\n                            logger.debug('Replace track aborted: session terminated');\n                            resolve();\n\n                            return;\n                        }\n                        logger.error(`${this} Replace track error:`, error);\n                        reject(error);\n                    } else {\n                        logger.info(`${this}  Replace track done!`);\n                        resolve();\n                    }\n                });\n        });\n    }\n\n    /**\n     * Sets the answer received from the remote peer as the remote description.\n     *\n     * @param {Element} jingleAnswer - The jingle answer element.\n     * @returns {Promise<void>} that resolves when the answer is set as the remote description, rejected otherwise.\n     */\n    public async setAnswer(jingleAnswer: Element): Promise<void> {\n        if (!this.isInitiator) {\n            throw new Error('Trying to set an answer on the responder session');\n        }\n        logger.debug(`${this} Executing setAnswer task`);\n\n        const newRemoteSdp = this._processNewJingleOfferIq(jingleAnswer);\n        const oldLocalSdp = new SDP(this.peerconnection.localDescription.sdp);\n        const remoteDescription = {\n            sdp: newRemoteSdp.raw,\n            type: 'answer'\n        } as RTCSessionDescription;\n\n        try {\n            await this.peerconnection.setRemoteDescription(remoteDescription);\n            if (this.state === JingleSessionState.PENDING) {\n                this.state = JingleSessionState.ACTIVE;\n\n                // Start processing tasks on the modification queue.\n                logger.debug(`${this} Resuming the modification queue after session is established!`);\n                this.modificationQueue.resume();\n                const newLocalSdp = new SDP(this.peerconnection.localDescription.sdp);\n\n                this._sendContentModify();\n                this.notifyMySSRCUpdate(oldLocalSdp, newLocalSdp);\n            }\n            logger.debug(`${this} setAnswer task done`);\n        } catch (error) {\n            logger.error(`${this} setAnswer task failed: ${error}`);\n            throw error;\n        }\n    }\n\n    /**\n     * Resumes or suspends media transfer over the underlying peer connection.\n     *\n     * @param {boolean} active - <tt>true</tt> to enable media transfer or <tt>false</tt> to suspend media transmission.\n     * @returns {Promise<void>}\n     */\n    public setMediaTransferActive(active: boolean): Promise<void> {\n        const changed = this.peerconnection.audioTransferActive !== active\n            || this.peerconnection.videoTransferActive !== active;\n\n        if (!changed) {\n            return Promise.resolve();\n        }\n\n        return this.peerconnection.setMediaTransferActive(active)\n            .then(async () => {\n                this.peerconnection.audioTransferActive = active;\n                this.peerconnection.videoTransferActive = active;\n\n                // Reconfigure the audio and video tracks so that only the correct encodings are active.\n                const promises = [];\n\n                promises.push(this.peerconnection.configureVideoSenderEncodings());\n                promises.push(this.peerconnection.configureAudioSenderEncodings());\n                await Promise.allSettled(promises);\n            });\n    }\n\n    /**\n     * Resumes or suspends video media transfer over the p2p peer connection.\n     *\n     * @param {boolean} videoActive <tt>true</tt> to enable video media transfer or <tt>false</tt> to suspend video\n     * media transmission.\n     * @return {Promise} a <tt>Promise</tt> which will resolve once the operation is done. It will be rejected with\n     * an error description as a string in case anything goes wrong.\n     */\n    public setP2pVideoTransferActive(videoActive: boolean): Promise<void> {\n        if (!this.peerconnection) {\n            return Promise.reject('Can not modify video transfer active state,'\n                    + ' before \"initialize\" is called');\n        }\n\n        if (this._localSendReceiveVideoActive !== videoActive) {\n            this._localSendReceiveVideoActive = videoActive;\n            if (this.isP2P && this.state === JingleSessionState.ACTIVE) {\n                this._sendContentModify();\n            }\n\n            return this.peerconnection\n                .setVideoTransferActive(this._localSendReceiveVideoActive && this._remoteSendReceiveVideoActive);\n        }\n\n        return Promise.resolve();\n    }\n\n    /**\n     * Adjust the preference for max video frame height that the local party is willing to receive. Signals\n     * the remote p2p peer.\n     *\n     * @param {Map<string, number>} sourceReceiverConstraints - The receiver constraints per source.\n     * @returns {void}\n     */\n    public setReceiverVideoConstraint(sourceReceiverConstraints: Map<string, number>): void {\n        logger.info(`${this} setReceiverVideoConstraint - constraints: ${JSON.stringify(sourceReceiverConstraints)}`);\n        this._sourceReceiverConstraints = sourceReceiverConstraints;\n\n        if (this.isP2P) {\n            // Tell the remote peer about our receive constraint. If Jingle session is not yet active the state will\n            // be synced after offer/answer.\n            if (this.state === JingleSessionState.ACTIVE) {\n                this._sendContentModify();\n            }\n        }\n    }\n\n    /**\n     * Sets the resolution constraint on the local video tracks.\n     *\n     * @param {number} maxFrameHeight - The user preferred max frame height.\n     * @param {string} sourceName - The source name of the track.\n     * @returns {Promise} promise that will be resolved when the operation is\n     * successful and rejected otherwise.\n     */\n    public setSenderVideoConstraint(maxFrameHeight: number, sourceName: Nullable<string> = null): Promise<void> {\n        if (this._assertNotEnded()) {\n            logger.info(`${this} setSenderVideoConstraint: ${maxFrameHeight}, sourceName: ${sourceName}`);\n\n            const jitsiLocalTrack = sourceName\n                ? this.rtc.getLocalVideoTracks().find(track => track.getSourceName() === sourceName)\n                : this.rtc.getLocalVideoTrack();\n\n            return this.peerconnection.setSenderVideoConstraints(maxFrameHeight, jitsiLocalTrack);\n        }\n\n        return Promise.resolve();\n    }\n\n    /**\n     * Updates the codecs on the peerconnection and initiates a renegotiation (if needed) for the\n     * new codec config to take effect.\n     *\n     * @param {Array<CodecMimeType>} codecList - Preferred codecs for video.\n     * @param {CodecMimeType} screenshareCodec - The preferred screenshare codec.\n     * @returns {void}\n     */\n    public setVideoCodecs(codecList: CodecMimeType[], screenshareCodec: Optional<CodecMimeType>): void {\n        if (this._assertNotEnded()) {\n            const updated = this.peerconnection.setVideoCodecs(codecList, screenshareCodec);\n\n            if (updated) {\n                this.eventEmitter.emit(MediaSessionEvents.VIDEO_CODEC_CHANGED);\n            }\n\n            // Browser throws an error when H.264 is set on the encodings. Therefore, munge the SDP when H.264 needs to\n            // be selected.\n            // TODO: Remove this check when the above issue is fixed.\n            if (this.usesCodecSelectionAPI && codecList[0] !== CodecMimeType.H264) {\n                return;\n            }\n\n            // Skip renegotiation when the selected codec order matches with that of the remote SDP.\n            const currentCodecOrder = this.peerconnection.getConfiguredVideoCodecs();\n\n            if (codecList.every((val, index) => val === currentCodecOrder[index])) {\n                return;\n            }\n\n            this.eventEmitter.emit(MediaSessionEvents.VIDEO_CODEC_CHANGED);\n            Statistics.sendAnalytics(\n                AnalyticsEvents.VIDEO_CODEC_CHANGED,\n                {\n                    value: codecList[0],\n                    videoType: VideoType.CAMERA\n                });\n\n            logger.info(`${this} setVideoCodecs: codecList=${codecList}, screenshareCodec=${screenshareCodec}`);\n\n            // Initiate a renegotiate for the codec setting to take effect.\n            const workFunction = async finishedCallback => {\n                try {\n                    await this._renegotiate();\n                    await this.peerconnection.configureVideoSenderEncodings();\n                    logger.debug(`${this} setVideoCodecs task is done`);\n\n                    return finishedCallback();\n                } catch (error) {\n                    logger.error(`${this} setVideoCodecs task failed: ${error}`);\n\n                    return finishedCallback(error);\n                }\n            };\n\n            logger.debug(`${this} Queued setVideoCodecs task`);\n\n            // Queue and execute\n            this.modificationQueue.push(workFunction);\n        }\n    }\n\n    /**\n     * @inheritDoc\n     */\n    public override terminate(\n            success: () => void,\n            failure: (error: IJingleError) => void,\n            options: ITerminateOptions = {}) {\n        if (this.state === JingleSessionState.ENDED) {\n            return;\n        }\n\n        if (!options || Boolean(options.sendSessionTerminate)) {\n            const sessionTerminate\n                = $iq({\n                    to: this.remoteJid,\n                    type: 'set'\n                })\n                    .c('jingle', {\n                        action: 'session-terminate',\n                        initiator: this.initiatorJid,\n                        sid: this.sid,\n                        xmlns: 'urn:xmpp:jingle:1'\n                    })\n                    .c('reason')\n                    .c((options?.reason) || 'success')\n                    .up();\n\n            if (options?.reasonDescription) {\n                sessionTerminate\n                    .c('text')\n                    .t(options.reasonDescription)\n                    .up()\n                    .up();\n            } else {\n                sessionTerminate.up();\n            }\n\n            this._bridgeSessionId\n                && sessionTerminate.c(\n                    'bridge-session', {\n                        id: this._bridgeSessionId,\n                        restart: options?.requestRestart === true,\n                        xmlns: 'http://jitsi.org/protocol/focus'\n                    }).up();\n\n            logger.info(`${this} Sending session-terminate`);\n            logger.debug(sessionTerminate.tree());\n\n            this.connection.sendIQ(\n                sessionTerminate,\n                success,\n                this.newJingleErrorHandler(failure),\n                IQ_TIMEOUT);\n        } else {\n            logger.info(`${this} Skipped sending session-terminate`);\n        }\n\n        // this should result in 'onTerminated' being called by strophe.jingle.js\n        this.connection.jingle.terminate(this.sid);\n    }\n\n    /**\n     * Converts to string with minor summary.\n     *\n     * @return {string}\n     */\n    public override toString(): string {\n        return `JingleSessionPC[session=${this.isP2P ? 'P2P' : 'JVB'},initiator=${this.isInitiator},sid=${this.sid}]`;\n    }\n}\n","import { getLogger } from '@jitsi/logger';\nimport { cloneDeep } from 'lodash-es';\nimport { $iq, Strophe } from 'strophe.js';\n\nimport { XMPPEvents } from '../../service/xmpp/XMPPEvents';\nimport RandomUtil from '../util/RandomUtil';\nimport { findAll, findFirst, getAttribute, getText } from '../util/XMLUtils';\n\nimport ConnectionPlugin from './ConnectionPlugin';\nimport { expandSourcesFromJson } from './JingleHelperFunctions';\nimport JingleSessionPC from './JingleSessionPC';\nimport { handleStropheError } from './StropheErrorHandler';\n\nconst logger = getLogger('xmpp:strophe.jingle');\n\n// XXX Strophe is build around the idea of chaining function calls so allow long\n// function call chains.\n/* eslint-disable newline-per-chained-call */\n\n/**\n * Parses the transport XML element and returns the list of ICE candidates formatted as text.\n *\n * @param {*} transport Transport XML element extracted from the IQ.\n * @returns {Array<string>}\n */\nfunction _parseIceCandidates(transport) {\n    const candidates = findAll(transport, ':scope>candidate');\n    const parseCandidates = [];\n\n    // Extract the candidate information from the IQ.\n    candidates.forEach(candidate => {\n        const attributes = candidate.attributes;\n        const candidateAttrs = [];\n\n        for (let i = 0; i < attributes.length; i++) {\n            const attr = attributes[i];\n\n            candidateAttrs.push(`${attr.name}: ${attr.value}`);\n        }\n        parseCandidates.push(candidateAttrs.join(' '));\n    });\n\n    return parseCandidates;\n}\n\n/**\n * Parse service received over xep-0215 and add it to the list of ice servers.\n * @param iceservers - the list of ice servers to add the parsed service to.\n * @param param1\n * @param param1.type\n * @param param1.host\n * @param param1.port\n * @param param1.username\n * @param param1.password\n * @param param1.transport\n * @private\n */\nfunction _parseService(iceservers, { type, host, port, username, password, transport }) {\n    const dict = {};\n\n    switch (type) {\n    case 'stun': {\n        dict.urls = `stun:${host}`;\n        if (port) {\n            dict.urls += `:${port}`;\n        }\n        iceservers.push(dict);\n        break;\n    }\n    case 'turn':\n    case 'turns': {\n        dict.urls = `${type}:${host}`;\n        dict.username = username;\n        if (port) {\n            dict.urls += `:${port}`;\n        }\n        if (transport && transport !== 'udp') {\n            dict.urls += `?transport=${transport}`;\n        }\n        dict.credential = password;\n        iceservers.push(dict);\n        break;\n    }\n    }\n}\n\n/**\n *\n */\nexport default class JingleConnectionPlugin extends ConnectionPlugin {\n    /**\n     * Creates new <tt>JingleConnectionPlugin</tt>\n     * @param {XMPP} xmpp\n     * @param {EventEmitter} eventEmitter\n     * @param {Object} iceConfig an object that holds the iceConfig to be passed\n     * to the p2p and the jvb <tt>PeerConnection</tt>.\n     */\n    constructor(xmpp, eventEmitter, iceConfig) {\n        super();\n        this.xmpp = xmpp;\n        this.eventEmitter = eventEmitter;\n        this.sessions = {};\n        this.jvbIceConfig = iceConfig.jvb;\n        this.p2pIceConfig = iceConfig.p2p;\n        this.mediaConstraints = {\n            offerToReceiveAudio: true,\n            offerToReceiveVideo: true\n        };\n    }\n\n    /**\n     *\n     * @param connection\n     */\n    init(connection) {\n        super.init(connection);\n        this.connection.addHandler(this.onJingle.bind(this),\n            'urn:xmpp:jingle:1', 'iq', 'set', null, null);\n    }\n\n    /**\n     *\n     * @param iq\n     */\n    onJingle(iq) {\n        const jingleElement = findFirst(iq, 'jingle');\n        const sid = getAttribute(jingleElement, 'sid');\n        const action = getAttribute(jingleElement, 'action');\n        const fromJid = getAttribute(iq, 'from');\n\n        // send ack first\n        const ack = $iq({ id: iq.getAttribute('id'),\n            to: fromJid,\n            type: 'result'\n        });\n\n        let sess = this.sessions[sid];\n\n        if (action !== 'session-initiate') {\n            if (!sess) {\n                ack.attrs({ type: 'error' });\n                ack.c('error', { type: 'cancel' })\n                    .c('item-not-found', {\n                        xmlns: 'urn:ietf:params:xml:ns:xmpp-stanzas'\n                    })\n                    .up()\n                    .c('unknown-session', {\n                        xmlns: 'urn:xmpp:jingle:errors:1'\n                    });\n                logger.warn(`invalid session id: ${sid}`);\n                logger.debug(iq);\n                this.connection.send(ack);\n\n                return true;\n            }\n\n            // local jid is not checked\n            if (fromJid !== sess.remoteJid) {\n                logger.warn(\n                    'jid mismatch for session id', sid, sess.remoteJid, iq);\n                ack.attrs({ type: 'error' });\n                ack.c('error', { type: 'cancel' })\n                    .c('item-not-found', {\n                        xmlns: 'urn:ietf:params:xml:ns:xmpp-stanzas'\n                    })\n                    .up()\n                    .c('unknown-session', {\n                        xmlns: 'urn:xmpp:jingle:errors:1'\n                    });\n                this.connection.send(ack);\n\n                return true;\n            }\n        } else if (sess !== undefined) {\n            // Existing session with same session id. This might be out-of-order\n            // if the sess.remoteJid is the same as from.\n            ack.attrs({ type: 'error' });\n            ack.c('error', { type: 'cancel' })\n                .c('service-unavailable', {\n                    xmlns: 'urn:ietf:params:xml:ns:xmpp-stanzas'\n                })\n                .up();\n            logger.warn('duplicate session id', sid, iq);\n            this.connection.send(ack);\n\n            return true;\n        }\n        const now = window.performance.now();\n\n        // FIXME that should work most of the time, but we'd have to\n        // think how secure it is to assume that user with \"focus\"\n        // nickname is Jicofo.\n        const isP2P = Strophe.getResourceFromJid(fromJid) !== 'focus';\n\n        // see http://xmpp.org/extensions/xep-0166.html#concepts-session\n\n        const jsonMessages = findAll(iq, 'jingle>json-message');\n\n        if (jsonMessages?.length) {\n            let audioVideoSsrcs;\n\n            logger.info(`Found a JSON-encoded element in ${action}, translating to standard Jingle.`);\n            for (let i = 0; i < jsonMessages.length; i++) {\n                // Currently there is always a single json-message in the IQ with the source information.\n                audioVideoSsrcs = expandSourcesFromJson(iq, jsonMessages[i]);\n            }\n\n            if (audioVideoSsrcs?.size) {\n                const logMessage = [];\n\n                for (const endpoint of audioVideoSsrcs.keys()) {\n                    logMessage.push(`${endpoint}:[${audioVideoSsrcs.get(endpoint)}]`);\n                }\n                logger.debug(`Received ${action} from ${fromJid} with sources=${logMessage.join(', ')}`);\n            }\n\n            // TODO: is there a way to remove the json-message elements once we've extracted the information?\n            // removeChild doesn't seem to work.\n        }\n\n        switch (action) {\n        case 'session-initiate': {\n            logger.info('(TIME) received session-initiate:\\t', now);\n\n            isP2P && logger.debug(`Received ${action} from ${fromJid}`);\n            const pcConfig = isP2P ? this.p2pIceConfig : this.jvbIceConfig;\n\n            sess\n                = new JingleSessionPC(\n                    sid,\n                    iq.getAttribute('to'),\n                    fromJid,\n                    this.connection,\n                    this.mediaConstraints,\n                    cloneDeep(pcConfig),\n                    isP2P,\n                    /* initiator */ false);\n\n            this.sessions[sess.sid] = sess;\n            this.eventEmitter.emit(XMPPEvents.CALL_INCOMING, sess, jingleElement, now);\n            break;\n        }\n        case 'session-accept': {\n            const ssrcs = [];\n\n            // Extract the SSRCs from the session-accept received from a p2p peer.\n            findAll(iq, 'jingle>content').forEach(content => {\n                const ssrc = getAttribute(findFirst(content, 'description'), 'ssrc');\n\n                ssrc && ssrcs.push(ssrc);\n            });\n\n            logger.debug(`Received ${action} from ${fromJid} with ssrcs=${ssrcs}`);\n            this.eventEmitter.emit(XMPPEvents.CALL_ACCEPTED, sess, jingleElement);\n            break;\n        }\n        case 'content-modify': {\n            logger.debug(`Received ${action} from ${fromJid}`);\n            sess.modifyContents(jingleElement);\n            break;\n        }\n        case 'transport-info': {\n            const transportElement = findFirst(iq, 'jingle>content>transport');\n            const candidates = _parseIceCandidates(transportElement);\n\n            logger.debug(`Received ${action} from ${fromJid} for candidates=${candidates.join(', ')}`);\n\n            // A transport tagged with an ice-generation is the transport of a new ICE agent that the bridge\n            // created in response to an in-place ICE restart request. It replaces the remote ICE credentials\n            // and its candidates have to be added only after the offer/answer completes, so it is applied as a\n            // single atomic operation instead of going through the generic candidate handling.\n            if (transportElement?.getAttribute('ice-generation')) {\n                sess.onBridgeIceRestartTransport(transportElement);\n                break;\n            }\n\n            this.eventEmitter.emit(XMPPEvents.TRANSPORT_INFO, sess, jingleElement);\n            break;\n        }\n        case 'session-terminate': {\n            logger.info('terminating...', sess.sid);\n            let reasonCondition = null;\n            let reasonText = null;\n\n            const reasonElement = findFirst(iq, ':scope>jingle>reason');\n\n            if (reasonElement) {\n                const firstReasonChild = reasonElement.children?.length > 0 ? reasonElement.children[0] : undefined;\n\n                reasonCondition = firstReasonChild ? firstReasonChild.tagName : null;\n                reasonText = getText(findFirst(iq, ':scope>jingle>reason>text'));\n            }\n\n            logger.debug(`Received ${action} from ${fromJid} disconnect reason=${reasonText}`);\n            this.terminate(sess.sid, reasonCondition, reasonText);\n            this.eventEmitter.emit(XMPPEvents.CALL_ENDED, sess, reasonCondition, reasonText);\n            break;\n        }\n        case 'transport-replace':\n            logger.error(`Ignoring ${action} from ${fromJid} as it is not supported by the client.`);\n            break;\n        case 'source-add':\n            sess.addRemoteStream(findAll(iq, ':scope>jingle>content'));\n            break;\n        case 'source-remove':\n            sess.removeRemoteStream(findAll(iq, ':scope>jingle>content'));\n            break;\n        default:\n            logger.warn('jingle action not implemented', action);\n            ack.attrs({ type: 'error' });\n            ack.c('error', { type: 'cancel' })\n                .c('bad-request',\n                    { xmlns: 'urn:ietf:params:xml:ns:xmpp-stanzas' })\n                .up();\n            break;\n        }\n        this.connection.send(ack);\n\n        return true;\n    }\n\n    /**\n     * Creates new <tt>JingleSessionPC</tt> meant to be used in a direct P2P\n     * connection, configured as 'initiator'.\n     * @param {string} me our JID\n     * @param {string} peer remote participant's JID\n     * @return {JingleSessionPC}\n     */\n    newP2PJingleSession(me, peer) {\n        const sess\n            = new JingleSessionPC(\n                RandomUtil.randomHexString(12),\n                me,\n                peer,\n                this.connection,\n                this.mediaConstraints,\n                this.p2pIceConfig,\n                /* P2P */ true,\n                /* initiator */ true);\n\n        this.sessions[sess.sid] = sess;\n\n        return sess;\n    }\n\n    /**\n     *\n     * @param sid\n     * @param reasonCondition\n     * @param reasonText\n     */\n    terminate(sid, reasonCondition = undefined, reasonText = undefined) {\n        if (this.sessions.hasOwnProperty(sid)) {\n            if (this.sessions[sid].state !== 'ended') {\n                this.sessions[sid].onTerminated(reasonCondition, reasonText);\n            }\n            delete this.sessions[sid];\n        }\n    }\n\n    /**\n     *\n     */\n    getStunAndTurnCredentials() {\n        // get stun and turn configuration from server via xep-0215\n        // uses time-limited credentials as described in\n        // http://tools.ietf.org/html/draft-uberti-behave-turn-rest-00\n        //\n        // See https://modules.prosody.im/mod_turncredentials.html\n        // for a prosody module which implements this.\n        // Or the new implementation https://modules.prosody.im/mod_external_services which will be in prosody 0.12\n        //\n        // Currently, this doesn't work with updateIce and therefore credentials\n        // with a long validity have to be fetched before creating the\n        // peerconnection.\n        // TODO: implement refresh via updateIce as described in\n        //      https://code.google.com/p/webrtc/issues/detail?id=1650\n        this.connection.sendIQ(\n            $iq({ to: this.xmpp.options.hosts.domain,\n                type: 'get' })\n                .c('services', { xmlns: 'urn:xmpp:extdisco:2' }),\n            v2Res => this.onReceiveStunAndTurnCredentials(v2Res),\n            error => {\n                handleStropheError(error, {\n                    domain: this.xmpp.options.hosts.domain,\n                    operation: 'get STUN/TURN credentials (extdisco:2)',\n                    userJid: this.connection.jid,\n                    xmlns: 'urn:xmpp:extdisco:2'\n                });\n                logger.warn('getting turn credentials with extdisco:2 failed, trying extdisco:1');\n                this.connection.sendIQ(\n                    $iq({ to: this.xmpp.options.hosts.domain,\n                        type: 'get' })\n                        .c('services', { xmlns: 'urn:xmpp:extdisco:1' }),\n                    v1Res => this.onReceiveStunAndTurnCredentials(v1Res),\n                    err => {\n                        handleStropheError(err, {\n                            domain: this.xmpp.options.hosts.domain,\n                            operation: 'get STUN/TURN credentials (extdisco:1)',\n                            userJid: this.connection.jid,\n                            xmlns: 'urn:xmpp:extdisco:1'\n                        });\n                        logger.warn('getting turn credentials failed');\n                        logger.warn('is mod_turncredentials or similar installed and configured?');\n                    }\n                );\n            });\n    }\n\n    /**\n     * Parses response when querying for services using urn:xmpp:extdisco:1 or urn:xmpp:extdisco:2.\n     * Stores results in jvbIceConfig and p2pIceConfig.\n     * @param res The response iq.\n     * @return {boolean} Whether something was processed from the supplied message.\n     */\n    onReceiveStunAndTurnCredentials(res) {\n        let iceservers = [];\n\n        if (Array.isArray(res?.services)) {\n            res.services.forEach(s => _parseService(iceservers, s));\n        } else {\n            findAll(res, ':scope>services>service').forEach(el => _parseService(iceservers, {\n                host: getAttribute(el, 'host'),\n                password: getAttribute(el, 'password'),\n                port: getAttribute(el, 'port'),\n                transport: getAttribute(el, 'transport'),\n                type: getAttribute(el, 'type'),\n                username: getAttribute(el, 'username')\n            }));\n        }\n\n        const options = this.xmpp.options;\n        const { iceServersOverride = [] } = options;\n\n        iceServersOverride.forEach(({ targetType, urls, username, credential }) => {\n            if (![ 'turn', 'turns', 'stun' ].includes(targetType)) {\n                return;\n            }\n\n            const pattern = `${targetType}:`;\n\n            if (typeof urls === 'undefined'\n                && typeof username === 'undefined'\n                && typeof credential === 'undefined') {\n                return;\n            }\n\n            if (urls === null) { // remove this type of ice server\n                iceservers = iceservers.filter(server => !server.urls.startsWith(pattern));\n            }\n\n\n            iceservers.forEach(server => {\n                if (!server.urls.startsWith(pattern)) {\n                    return;\n                }\n\n                server.urls = urls ?? server.urls;\n\n                if (username === null) {\n                    delete server.username;\n                } else {\n                    server.username = username ?? server.username;\n                }\n\n                if (credential === null) {\n                    delete server.credential;\n                } else {\n                    server.credential = credential ?? server.credential;\n                }\n            });\n        });\n\n        // Shuffle ICEServers for loadbalancing\n        for (let i = iceservers.length - 1; i > 0; i--) {\n            const j = Math.floor(Math.random() * (i + 1));\n            const temp = iceservers[i];\n\n            iceservers[i] = iceservers[j];\n            iceservers[j] = temp;\n        }\n\n        let filter;\n\n        if (options.useTurnUdp) {\n            filter = s => s.urls.startsWith('turn');\n        } else {\n            // By default we filter out STUN and TURN/UDP and leave only TURN/TCP.\n            filter = s => s.urls.startsWith('turn') && (s.urls.indexOf('transport=tcp') >= 0);\n        }\n\n        this.jvbIceConfig.iceServers = iceservers.filter(filter);\n        this.p2pIceConfig.iceServers = iceservers;\n\n        return iceservers.length > 0;\n    }\n\n    /**\n     * Returns the data saved in 'updateLog' in a format to be logged.\n     * @returns {Record<string, unknown>} An object containing the data to be logged.\n     */\n    getLog() {\n        const data = {};\n\n        Object.keys(this.sessions).forEach(sid => {\n            const session = this.sessions[sid];\n            const pc = session.peerconnection;\n\n            if (pc && pc.updateLog) {\n                // FIXME: should probably be a .dump call\n                data[`jingle_${sid}`] = {\n                    stats: pc.stats,\n                    updateLog: pc.updateLog,\n                    url: window.location.href\n                };\n            }\n        });\n\n        return data;\n    }\n}\n\n/* eslint-enable newline-per-chained-call */\n","import { Strophe } from 'strophe.js';\n\nimport ConnectionPlugin from './ConnectionPlugin';\n\n\n/**\n *  Logs raw stanzas and makes them available for download as JSON\n */\nclass StropheLogger extends ConnectionPlugin {\n    /**\n     *\n     */\n    private log: any;\n\n    /**\n     *\n     */\n    constructor() {\n        super();\n        this.log = [];\n    }\n\n    /**\n     *\n     * @param connection\n     */\n    override init(connection: Strophe.Connection): void {\n        super.init(connection);\n        connection.rawInput = this.logIncoming.bind(this);\n        connection.rawOutput = this.logOutgoing.bind(this);\n    }\n\n    /**\n     *\n     * @param stanza\n     */\n    logIncoming(stanza: Element | Strophe.Builder): void {\n        this.log.push([ new Date().getTime(), 'incoming', stanza ]);\n    }\n\n    /**\n     *\n     * @param stanza\n     */\n    logOutgoing(stanza: Element | Strophe.Builder): void {\n        this.log.push([ new Date().getTime(), 'outgoing', stanza ]);\n    }\n}\n\n/**\n *\n */\nexport default function() {\n    Strophe.addConnectionPlugin('logger', new StropheLogger());\n}\n","import { getLogger } from '@jitsi/logger';\nimport { $iq, type Connection } from 'strophe.js';\n\nimport { findFirst, getAttribute } from '../util/XMLUtils';\n\nimport ConnectionPlugin from './ConnectionPlugin';\nimport { handleStropheError } from './StropheErrorHandler';\n\nconst logger = getLogger('xmpp:strophe.rayo');\n\nconst RAYO_XMLNS = 'urn:xmpp:rayo:1';\n\n/**\n *\n */\nexport default class RayoConnectionPlugin extends ConnectionPlugin {\n    private callResource: Nullable<string> = null;\n\n    /**\n     *\n     * @param connection\n     */\n    override init(connection: Connection): void {\n        super.init(connection);\n\n        connection.addHandler(\n            this.onRayo.bind(this),\n            RAYO_XMLNS,\n            'iq',\n            'set',\n            null,\n            null\n        );\n    }\n\n    /**\n     *\n     * @param iq\n     */\n    onRayo(iq: any): any {\n        logger.info('Rayo IQ', iq);\n    }\n\n    /* eslint-disable max-params */\n\n    /**\n     *\n     * @param to\n     * @param from\n     * @param roomName\n     * @param roomPass\n     * @param focusMucJid\n     */\n    dial(\n            to: string,\n            from: string,\n            roomName: string,\n            roomPass: string,\n            focusMucJid: string\n    ): Promise<void> {\n        return new Promise((resolve, reject) => {\n            if (!focusMucJid) {\n                reject(new Error('Internal error!'));\n\n                return;\n            }\n            const req = $iq({\n                to: focusMucJid,\n                type: 'set',\n            });\n\n            req.c('dial', {\n                from,\n                to,\n                xmlns: RAYO_XMLNS,\n            });\n            req.c('header', {\n                name: 'JvbRoomName',\n                value: roomName,\n            }).up();\n\n            if (roomPass?.length) {\n                req.c('header', {\n                    name: 'JvbRoomPassword',\n                    value: roomPass,\n                }).up();\n            }\n\n            (this.connection as Connection).sendIQ(\n                req,\n                result => {\n                    logger.info('Dial result ', result);\n\n                    const resource = getAttribute(findFirst(result, 'ref'), 'uri');\n\n                    this.callResource = resource.substr('xmpp:'.length);\n                    logger.info(`Received call resource: ${this.callResource}`);\n                    resolve();\n                },\n                error => {\n                    handleStropheError(error, {\n                        from,\n                        operation: 'dial (Rayo)',\n                        roomName,\n                        to,\n                        userJid: (this.connection as Connection).jid\n                    });\n                    reject(error);\n                }\n            );\n        });\n    }\n\n    /* eslint-enable max-params */\n\n    /**\n     *\n     */\n    hangup(): Promise<void> {\n        return new Promise((resolve, reject) => {\n            if (!this.callResource) {\n                reject(new Error('No call in progress'));\n                logger.warn('No call in progress');\n\n                return;\n            }\n\n            const req = $iq({\n                to: this.callResource,\n                type: 'set',\n            });\n\n            req.c('hangup', {\n                xmlns: RAYO_XMLNS,\n            });\n\n            (this.connection as Connection).sendIQ(\n                req,\n                result => {\n                    logger.info('Hangup result ', result);\n                    this.callResource = null;\n                    resolve();\n                },\n                error => {\n                    handleStropheError(error, {\n                        callResource: this.callResource,\n                        operation: 'hangup (Rayo)',\n                        userJid: (this.connection as Connection).jid\n                    });\n                    this.callResource = null;\n                    reject(new Error('Hangup error '));\n                }\n            );\n        });\n    }\n}\n","/**\n * Strophe logger implementation. Logs from level WARN and above.\n */\nimport { getLogger } from '@jitsi/logger';\nimport { Strophe } from 'strophe.js';\n\nconst logger = getLogger('xmpp:strophe.util');\n\n/**\n * This is the last HTTP error status captured from Strophe debug logs.\n * The purpose of storing it is to distinguish between the network and\n * infrastructure reason for connection being dropped (see connectionHandler in\n * xmpp.js). The value will be cleared (-1) if the subsequent request succeeds\n * which means that the failure could be transient.\n *\n * FIXME in the latest Strophe (not released on npm) there is API to handle\n * particular HTTP errors, but there is no way to learn if the subsequent\n * request succeeded in order to tell if the error was one time incident or if\n * it was the reason for dropping the connection by Strophe (the connection is\n * dropped after 5 subsequent failures). Ideally Strophe should provide more\n * details about the reason on why the connection stopped.\n *\n * @type {number}\n */\nlet lastErrorStatus: number = -1;\n\n\n/**\n * A regular expression used to catch Strophe's log message indicating that the\n * last BOSH request was successful. When there is such message seen the\n * {@link lastErrorStatus} will be set back to '-1'.\n * @type {RegExp}\n */\nconst resetLastErrorStatusRegExpr: RegExp = /request id \\d+.\\d+ got 200/;\n\n/**\n * A regular expression used to capture the current value of the BOSH request\n * error status (HTTP error code or '0' or something else).\n * @type {RegExp}\n */\nconst lastErrorStatusRegExpr: RegExp\n    = /request errored, status: (\\d+), number of errors: \\d+/;\n\n/**\n *\n */\nexport default function(): void {\n\n    Strophe.log = function(level: number, msg: any): void {\n        // Our global handler reports uncaught errors to the stats which may\n        // interpret those as partial call failure.\n        // Strophe log entry about secondary request timeout does not mean that\n        // it's a final failure(the request will be restarted), so we lower it's\n        // level here to a warning.\n        logger.trace('Strophe', level, msg);\n        if (typeof msg === 'string'\n                && msg.indexOf('Request ') !== -1\n                && msg.indexOf('timed out (secondary), restarting') !== -1) {\n            // eslint-disable-next-line no-param-reassign\n            level = Strophe.LogLevel.WARN;\n        }\n\n        /* eslint-disable no-case-declarations */\n        switch (level) {\n        case Strophe.LogLevel.DEBUG:\n            // The log message which reports successful status is logged on\n            // Strophe's DEBUG level.\n            if (lastErrorStatus !== -1\n                    && resetLastErrorStatusRegExpr.test(msg)) {\n                logger.debug('Reset lastErrorStatus');\n                lastErrorStatus = -1;\n            }\n            break;\n        case Strophe.LogLevel.WARN:\n            logger.warn(`Strophe: ${msg}`);\n            const errStatusCapture = lastErrorStatusRegExpr.exec(msg);\n\n            if (errStatusCapture?.length === 2) {\n                lastErrorStatus = parseInt(errStatusCapture[1], 10);\n                logger.debug(`lastErrorStatus set to: ${lastErrorStatus}`);\n            }\n            break;\n        case Strophe.LogLevel.ERROR:\n        case Strophe.LogLevel.FATAL:\n            logger.error(`Strophe: ${msg}`, msg);\n            break;\n        }\n\n        /* eslint-enable no-case-declarations */\n    };\n\n    /**\n     * Returns error status (HTTP error code) of the last BOSH request.\n     *\n     * @return {number} HTTP error code, '0' for unknown or \"god knows what\"\n     * (this is a hack).\n     */\n    Strophe.getLastErrorStatus = function(): number {\n        return lastErrorStatus;\n    };\n\n    Strophe.getStatusString = function(status: number): string {\n        switch (status) {\n        case Strophe.Status.BINDREQUIRED:\n            return 'BINDREQUIRED';\n        case Strophe.Status.ERROR:\n            return 'ERROR';\n        case Strophe.Status.CONNECTING:\n            return 'CONNECTING';\n        case Strophe.Status.CONNFAIL:\n            return 'CONNFAIL';\n        case Strophe.Status.AUTHENTICATING:\n            return 'AUTHENTICATING';\n        case Strophe.Status.AUTHFAIL:\n            return 'AUTHFAIL';\n        case Strophe.Status.CONNECTED:\n            return 'CONNECTED';\n        case Strophe.Status.DISCONNECTED:\n            return 'DISCONNECTED';\n        case Strophe.Status.DISCONNECTING:\n            return 'DISCONNECTING';\n        case Strophe.Status.ATTACHED:\n            return 'ATTACHED';\n        default:\n            return 'unknown';\n        }\n    };\n}\n","import { safeJsonParse } from '@jitsi/js-utils/json';\nimport { getLogger } from '@jitsi/logger';\nimport { JwtPayload, jwtDecode } from 'jwt-decode';\nimport { cloneDeep, unescape } from 'lodash-es';\nimport { $msg, Strophe } from 'strophe.js';\n\nimport * as JitsiConnectionErrors from '../../JitsiConnectionErrors';\nimport * as JitsiConnectionEvents from '../../JitsiConnectionEvents';\nimport { XMPPEvents } from '../../service/xmpp/XMPPEvents';\nimport { XEP } from '../../service/xmpp/XMPPExtensioProtocols';\nimport RTCStats from '../RTCStats/RTCStats';\nimport { RTCStatsEvents } from '../RTCStats/RTCStatsEvents';\nimport browser from '../browser';\nimport { E2EEncryption } from '../e2ee-internxt/E2EEncryption';\nimport FeatureFlags from '../flags/FeatureFlags';\nimport Statistics from '../statistics/statistics';\nimport Listenable from '../util/Listenable';\nimport RandomUtil from '../util/RandomUtil';\nimport { exists, findFirst, getText } from '../util/XMLUtils';\n\nimport Caps, { parseDiscoInfo } from './Caps';\nimport ChatRoom from './ChatRoom';\nimport { IDENTITY_TYPE as FILE_SHARING_IDENTITY_TYPE } from './FileSharing';\nimport XmppConnection from './XmppConnection';\nimport Moderator from './moderator';\nimport './strophe.disco';\nimport MucConnectionPlugin from './strophe.emuc';\nimport JingleConnectionPlugin from './strophe.jingle';\nimport initStropheLogger from './strophe.logger';\nimport RayoConnectionPlugin from './strophe.rayo';\nimport initStropheUtil from './strophe.util';\n\nconst logger = getLogger('xmpp:Xmpp');\n\n/**\n * Connection options interface\n */\ninterface ICreateConnectionOptions {\n    enableWebsocketResume?: boolean;\n    serviceUrl?: string;\n    shard?: string;\n    token?: string;\n    websocketKeepAlive?: number;\n    websocketKeepAliveUrl?: string;\n    xmppPing?: Record<string, unknown>;\n}\n\n/**\n * Credentials interface for connection handler\n */\ninterface IConnectionCredentials {\n    jid?: string;\n    password?: string;\n    rid?: string;\n    sid?: string;\n}\n\n/**\n * Room creation options interface\n */\ninterface IRoomCreationOptions {\n    customDomain?: string;\n    isChatEncrypted?: boolean;\n    statsId?: string;\n}\n\n/**\n * Connection details for failure reasons\n */\ninterface IConnectionFailedReasonDetails {\n    shard_changed?: boolean;\n    suspend_time?: number;\n    time_since_last_success?: number;\n}\n\n/**\n * Deployment info interface\n */\ninterface IDeploymentInfo {\n    backendRelease?: string;\n    region?: string;\n    shard?: string;\n}\n\n/**\n * Hosts configuration interface\n */\ninterface IHostsConfig {\n    anonymousdomain?: string;\n    domain?: string;\n    muc?: string;\n}\n\n/**\n * Testing configuration interface\n */\ninterface ITestingConfig {\n    enableGracefulReconnect?: boolean;\n}\n\n/**\n * P2P configuration interface\n */\ninterface IP2PConfig {\n    iceTransportPolicy?: string;\n    stunServers?: Array<{ urls: string; }>;\n}\n\n/**\n * XMPP options interface\n */\nexport interface IXMPPOptions {\n    audioTranslation?: {\n        enabled?: boolean;\n    };\n    bosh?: string;\n    deploymentInfo?: IDeploymentInfo;\n    disableBeforeUnloadHandlers?: boolean;\n    disableRtx?: boolean;\n    enableOpusRed?: boolean;\n    enableRemb?: boolean;\n    enableTcc?: boolean;\n    enableWebsocketResume?: boolean;\n    hosts?: IHostsConfig;\n    p2p?: IP2PConfig;\n    p2pStunServers?: Array<{ urls: string; }>;\n    serviceUrl?: string;\n    testing?: ITestingConfig;\n    websocketKeepAlive?: number;\n    websocketKeepAliveUrl?: string;\n    xmppPing?: Record<string, unknown>;\n}\n\nexport interface IFaceLandmarksPayload {\n    duration: number;\n    faceExpression: string;\n    timestamp: number;\n}\n\n/**\n * Identity interface for disco info\n */\nexport interface IIdentity {\n    name?: string;\n    type: string;\n}\n\n/**\n * Breakout rooms features interface\n */\ninterface IBreakoutRoomsFeatures {\n    rename?: boolean;\n}\n\n/**\n * JSON message interface\n */\ninterface IJsonMessage {\n    [key: string]: unknown;\n    users?: unknown;\n}\n\n/**\n* Regex to extract exact error message on jwt error.\n*/\nconst FAILURE_REGEX = /<failure.*><not-allowed\\/><text>(.*)<\\/text><\\/failure>/gi;\n\n/**\n * Creates XMPP connection.\n *\n * @param {Object} options\n * @param {string} [options.token] - JWT token used for authentication(JWT authentication module must be enabled in\n * Prosody).\n * @param {string} options.serviceUrl - The service URL for XMPP connection.\n * @param {string} options.shard - The shard where XMPP connection initially landed.\n * @param {string} options.enableWebsocketResume - True to enable stream resumption.\n * @param {number} [options.websocketKeepAlive] - See {@link XmppConnection} constructor.\n * @param {number} [options.websocketKeepAliveUrl] - See {@link XmppConnection} constructor.\n * @param {Object} [options.xmppPing] - See {@link XmppConnection} constructor.\n * @returns {XmppConnection}\n */\nfunction createConnection({\n    enableWebsocketResume,\n    serviceUrl = '/http-bind',\n    shard,\n    token,\n    websocketKeepAlive,\n    websocketKeepAliveUrl,\n    xmppPing }: ICreateConnectionOptions): XmppConnection {\n\n    // Append token as URL param\n    if (token) {\n        // eslint-disable-next-line no-param-reassign\n        serviceUrl += `${serviceUrl.indexOf('?') === -1 ? '?' : '&'}token=${token}`;\n    }\n\n    return new XmppConnection({\n        enableWebsocketResume,\n        serviceUrl,\n        shard,\n        websocketKeepAlive,\n        websocketKeepAliveUrl,\n        xmppPing\n    });\n}\n\n/**\n * Initializes Strophe plugins that need to work with Strophe.Connection directly rather than the lib-jitsi-meet's\n * {@link XmppConnection} wrapper.\n *\n * @returns {void}\n */\nfunction initStropheNativePlugins(): void {\n    initStropheUtil();\n    initStropheLogger();\n}\n\n// FIXME: remove once we have a default config template. -saghul\n/**\n * A list of ice servers to use by default for P2P.\n */\nexport const DEFAULT_STUN_SERVERS: Array<{ urls: string; }> = [\n    { urls: 'stun:meet-jit-si-turnrelay.jitsi.net:443' }\n];\n\n/**\n * The name of the field used to recognize a chat message as carrying a JSON\n * payload from another endpoint.\n * If the json-message of a chat message contains a valid JSON object, and\n * the JSON has this key, then it is a valid json-message to be sent.\n */\nexport const JITSI_MEET_MUC_TYPE: string = 'type';\n\n/**\n * The feature used by jigasi participants.\n * @type {string}\n */\nexport const FEATURE_JIGASI: string = 'http://jitsi.org/protocol/jigasi';\n\n/**\n * The feature used by jibri participants.\n * @type {string}\n */\nexport const FEATURE_JIBRI: string = 'http://jitsi.org/protocol/jibri';\n\n/**\n * The feature used by jigasi transcriber participants.\n * @type {string}\n */\nexport const FEATURE_TRANSCRIBER: string = 'http://jitsi.org/protocol/transcriber';\n\n/**\n * The feature used to mark support for receiving AI audio translation.\n * @type {string}\n */\nexport const FEATURE_AUDIO_TRANSLATION: string = 'http://jitsi.org/protocol/audio-translation';\n\n/**\n * The feature used by the lib to mark support for e2ee. We use the feature by putting it in the presence\n * to avoid additional signaling (disco-info).\n * @type {string}\n */\nexport const FEATURE_E2EE: string = 'https://jitsi.org/meet/e2ee';\n\n/**\n * @internal\n */\nexport default class XMPP extends Listenable {\n    private _anonymousConnectionFailed: Optional<boolean>;\n    private _components: string[];\n    private _disconnectInProgress: Optional<Promise<void>> | boolean;\n    private _lastErrorMsg: Optional<string>;\n    private _preComponentsMsgs: Element[];\n    private _sysMessageHandler: unknown;\n    private _startConnecting: Optional<boolean>;\n    private _unloadEventTypes: string[];\n    private _unloadHandler: Optional<(ev: Event) => void>;\n    private _wasDisconnected: boolean;\n    public connection: Nullable<XmppConnection>;\n    public connectionTimes: Record<string, number>;\n    public options: IXMPPOptions;\n    public token: Optional<string>;\n    public authenticatedUser: boolean;\n    public moderator: Moderator;\n    public caps: Caps;\n    public sendDiscoInfo: Optional<boolean>;\n    public sendDeploymentInfo: Optional<boolean>;\n    public connectionFailed: Optional<boolean>;\n    public lobbySupported: Optional<boolean>;\n    public avModerationComponentAddress: Optional<string>;\n    public endConferenceComponentAddress: Optional<string>;\n    public speakerStatsComponentAddress: Optional<string>;\n    public breakoutRoomsComponentAddress: Optional<string>;\n    public breakoutRoomsFeatures: Optional<IBreakoutRoomsFeatures>;\n    public fileSharingComponentAddress: Optional<string>;\n    public roomMetadataComponentAddress: Optional<string>;\n    public pollsComponentAddress: Optional<string>;\n    public audioTranslationComponentAddress: Optional<string>;\n\n\n    /**\n     * FIXME describe all options\n     * @param {Object} options\n     * @param {String} options.serviceUrl - URL passed to the XMPP client which will be used to establish XMPP\n     * connection with the server.\n     * @param {boolean} options.enableWebsocketResume - Enables XEP-0198 stream management which will make the XMPP\n     * module try to resume the session in case the Websocket connection breaks.\n     * @param {number} [options.websocketKeepAlive] - The websocket keep alive interval. See {@link XmppConnection}\n     * constructor for more details.\n     * @param {number} [options.websocketKeepAliveUrl] - The websocket keep alive url. See {@link XmppConnection}\n     * constructor for more details.\n     * @param {Object} [options.xmppPing] - The xmpp ping settings.\n     * @param {Array<Object>} options.p2pStunServers see {@link JingleConnectionPlugin} for more details.\n     * @param token\n     */\n    constructor(options: IXMPPOptions, token?: string) {\n        super();\n\n        if (options.bosh && !options.serviceUrl) {\n            throw new Error('The \"bosh\" option is no longer supported, please use \"serviceUrl\" instead');\n        }\n\n        this.connection = null;\n        this._disconnectInProgress = false;\n        this.connectionTimes = {};\n        this.options = options;\n        this.token = token;\n        this.authenticatedUser = false;\n\n        if (!this.options.deploymentInfo) {\n            this.options.deploymentInfo = {};\n        }\n\n        // Cache of components used for certain features.\n        this._components = [];\n\n        // We want to track messages that are received before we process the disco-info components\n        // re-order of receiving we may drop some messages\n        this._preComponentsMsgs = [];\n\n        initStropheNativePlugins();\n\n        const xmppPing = options.xmppPing || {};\n\n        // let's ping the main domain (in case a guest one is used for the connection)\n        xmppPing.domain = options.hosts.domain;\n\n        this.connection = createConnection({\n            enableWebsocketResume: options.enableWebsocketResume,\n            serviceUrl: options.serviceUrl,\n            shard: options.deploymentInfo.shard,\n            token,\n            websocketKeepAlive: options.websocketKeepAlive,\n            websocketKeepAliveUrl: options.websocketKeepAliveUrl,\n            xmppPing\n        });\n\n        this.moderator = new Moderator(this);\n\n        // forwards the shard changed event\n        this.connection.on(XmppConnection.Events.CONN_SHARD_CHANGED, () => {\n            /* eslint-disable camelcase */\n            const details: IConnectionFailedReasonDetails = {\n                shard_changed: true,\n                suspend_time: this.connection.ping.getPingSuspendTime(),\n                time_since_last_success: this.connection.getTimeSinceLastSuccess()\n            };\n            /* eslint-enable camelcase */\n\n            if (this.options.testing?.enableGracefulReconnect) {\n                logger.debug('Shard changed, attempting graceful reconnect');\n                this.eventEmitter.emit(\n                    JitsiConnectionEvents.CONNECTION_FAILED,\n                    JitsiConnectionErrors.SHARD_CHANGED_ERROR\n                );\n            } else {\n                logger.error('Shard changed, kicking the user off the conference and forcing reload', JSON.stringify(details));\n                this.eventEmitter.emit(\n                    JitsiConnectionEvents.CONNECTION_FAILED,\n                    JitsiConnectionErrors.OTHER_ERROR,\n                    undefined,\n                    undefined,\n                    details);\n            }\n        });\n\n        this.connection.on(XmppConnection.Events.CONN_STATUS_CHANGED, status => {\n            if (status === XmppConnection.Status.RESUMING) {\n                // we will be resuming in a bit let's check the token (if any) for expiration\n                if (this.token) {\n                    const payload = jwtDecode<JwtPayload>(this.token);\n\n                    if (new Date().getTime() >= payload.exp * 1000) {\n                        // we want to cancel the scheduled resume as the token is expired\n                        this.connection.cancelResume();\n\n                        // notify that a new token is needed and passed via refreshToken of the connection\n                        this.eventEmitter.emit(JitsiConnectionEvents.CONNECTION_TOKEN_EXPIRED);\n                    }\n                }\n            }\n        });\n\n        this._initStrophePlugins();\n\n        this.caps = new Caps(this.connection, /* clientNode */ 'https://jitsi.org/jitsi-meet');\n\n        // Initialize features advertised in disco-info\n        this.initFeaturesList();\n\n        this.connection.addHandler(this._onPrivateMessage.bind(this), null, 'message', null, null);\n\n        // Setup a disconnect on unload as a way to facilitate API consumers. It\n        // sounds like they would want that. A problem for them though may be if\n        // they wanted to utilize the connected connection in an unload handler\n        // of their own. However, it should be fairly easy for them to do that\n        // by registering their unload handler before us.\n        const events = `${this.options.disableBeforeUnloadHandlers ? '' : 'beforeunload '}unload`;\n\n        this._unloadHandler = (ev: Event) => {\n            // type-checking added as disconnect returns Promise<void> | boolean\n            const result = this.disconnect(ev);\n\n            if (result instanceof Promise) {\n                result.catch(() => {\n                    // Ignore errors in order to not break the unload.\n                });\n            }\n        };\n        this._unloadEventTypes = events.split(' ');\n\n        for (const event of this._unloadEventTypes) {\n            window.addEventListener(event, this._unloadHandler);\n        }\n    }\n\n    /**\n     * Removes the beforeunload/unload listeners registered in the constructor. Without this each created connection\n     * would leak its listeners on the window object.\n     *\n     * @returns {void}\n     */\n    private _removeUnloadHandlers(): void {\n        if (!this._unloadHandler) {\n            return;\n        }\n\n        for (const event of this._unloadEventTypes) {\n            window.removeEventListener(event, this._unloadHandler);\n        }\n\n        this._unloadHandler = undefined;\n    }\n\n    /**\n     * Initializes the list of feature advertised through the disco-info\n     * mechanism.\n     */\n    private initFeaturesList(): void {\n        // http://xmpp.org/extensions/xep-0167.html#support\n        // http://xmpp.org/extensions/xep-0176.html#support\n        this.caps.addFeature(XEP.JINGLE);\n        this.caps.addFeature(XEP.RTP_MEDIA);\n        this.caps.addFeature(XEP.ICE_UDP_TRANSPORT);\n        this.caps.addFeature(XEP.DTLS_SRTP);\n        this.caps.addFeature(XEP.SCTP_DATA_CHANNEL);\n        this.caps.addFeature(XEP.RTP_AUDIO);\n        this.caps.addFeature(XEP.RTP_VIDEO);\n        this.caps.addFeature('http://jitsi.org/json-encoded-sources');\n\n        if (!(this.options.disableRtx || !browser.supportsRTX())) {\n            this.caps.addFeature('urn:ietf:rfc:4588');\n        }\n        if (this.options.enableOpusRed === true && browser.supportsAudioRed()) {\n            this.caps.addFeature('http://jitsi.org/opus-red');\n        }\n\n        if (typeof this.options.enableRemb === 'undefined' || this.options.enableRemb) {\n            this.caps.addFeature('http://jitsi.org/remb');\n        }\n\n        // Disable TCC on Firefox 114 and older versions because of a known issue where BWE is halved on every\n        // renegotiation.\n        if (!(browser.isFirefox() && browser.isVersionLessThan(115))\n            && (typeof this.options.enableTcc === 'undefined' || this.options.enableTcc)) {\n            this.caps.addFeature('http://jitsi.org/tcc');\n        }\n        if (this.connection.rayo) {\n            this.caps.addFeature('urn:xmpp:rayo:client:1');\n        }\n\n        if (E2EEncryption.isSupported(this.options)) {\n            this.caps.addFeature(FEATURE_E2EE, false, true);\n        }\n\n        // Advertise source-name signaling when the endpoint supports it.\n        logger.debug('Source-name signaling is enabled');\n        this.caps.addFeature('http://jitsi.org/source-name');\n\n        logger.debug('Receiving multiple video streams is enabled');\n        this.caps.addFeature('http://jitsi.org/receive-multiple-video-streams');\n\n        // Advertise support for ssrc-rewriting.\n        if (FeatureFlags.isSsrcRewritingSupported()) {\n            this.caps.addFeature('http://jitsi.org/ssrc-rewriting-1');\n        }\n\n        // Advertise support for demuxing forwarded media by the RTP sdes:mid header extension.\n        if (FeatureFlags.isRtpMidDemuxSupported()) {\n            this.caps.addFeature('http://jitsi.org/rtp-mid-demux');\n        }\n\n        // Use \"-1\" as a version that we can bump later. This should match\n        // the version added in moderator.js, this one here is mostly defined\n        // for keeping stats, since it is not made available to jocofo at\n        // the time of the initial conference-request.\n        this.caps.addFeature('http://jitsi.org/visitors-1');\n\n        // Advertise support for startMuted policy through room metadata.\n        this.caps.addFeature('http://jitsi.org/start-muted-room-metadata');\n\n        // Advertise AI audio-translation support (opt-in via the audioTranslation connection option).\n        if (this.options.audioTranslation?.enabled) {\n            this.caps.addFeature(FEATURE_AUDIO_TRANSLATION);\n        }\n    }\n\n\n    /**\n     * A private message is received, message that is not addressed to the muc.\n     * We expect private message coming from plugins component if it is\n     * enabled and running.\n     *\n     * @param {string} msg - The message.\n     */\n    private _onPrivateMessage(msg: Element): boolean {\n        const from = msg.getAttribute('from');\n\n        if (!this._components.includes(from)) {\n            this._preComponentsMsgs.push(msg);\n\n            return true;\n        }\n\n        // Use *|xmlns to match xmlns attributes across any namespace (CSS Selectors Level 3)\n        const jsonMessage = getText(findFirst(msg, ':scope>json-message[*|xmlns=\"http://jitsi.org/jitmeet\"]'));\n        const parsedJson = this.tryParseJSONAndVerify(jsonMessage);\n\n        if (!parsedJson || typeof parsedJson !== 'object') {\n            return true;\n        }\n\n        if (parsedJson[JITSI_MEET_MUC_TYPE] === 'speakerstats' && parsedJson.users) {\n            this.eventEmitter.emit(XMPPEvents.SPEAKER_STATS_RECEIVED, parsedJson.users);\n        } else if (parsedJson[JITSI_MEET_MUC_TYPE] === 'av_moderation') {\n            this.eventEmitter.emit(XMPPEvents.AV_MODERATION_RECEIVED, parsedJson);\n        } else if (parsedJson[JITSI_MEET_MUC_TYPE] === 'breakout_rooms') {\n            this.eventEmitter.emit(XMPPEvents.BREAKOUT_ROOMS_EVENT, parsedJson);\n        } else if (parsedJson[JITSI_MEET_MUC_TYPE] === FILE_SHARING_IDENTITY_TYPE) {\n            this.eventEmitter.emit(XMPPEvents.FILE_SHARING_EVENT, parsedJson);\n        } else if (parsedJson[JITSI_MEET_MUC_TYPE] === 'room_metadata') {\n            this.eventEmitter.emit(XMPPEvents.ROOM_METADATA_EVENT, parsedJson);\n        } else if (parsedJson[JITSI_MEET_MUC_TYPE] === 'visitors') {\n            this.eventEmitter.emit(XMPPEvents.VISITORS_MESSAGE, parsedJson);\n        } else if (parsedJson[JITSI_MEET_MUC_TYPE] === 'polls') {\n            this.eventEmitter.emit(XMPPEvents.POLLS_EVENT, parsedJson);\n        }\n\n        return true;\n    }\n\n    /**\n     * Sends deployment info to stats if not sent already.\n     * We want to try sending it on failure to connect\n     * or when we get a sys message(from jiconop2)\n     * or after success or failure of disco-info\n     * @param force Whether to force sending without checking anything.\n     * @private\n     */\n    private _maybeSendDeploymentInfoStat(force: boolean = false): void {\n        const acceptedStatuses = [\n            Strophe.Status.ERROR,\n            Strophe.Status.CONNFAIL,\n            Strophe.Status.AUTHFAIL,\n            Strophe.Status.DISCONNECTED,\n            Strophe.Status.CONNTIMEOUT\n        ];\n\n        if (!force && !(acceptedStatuses.includes(this.connection.status) && this.sendDeploymentInfo)) {\n            return;\n        }\n\n        // Log deployment-specific information, if available. Defined outside\n        // the application by individual deployments\n        const aprops = this.options.deploymentInfo;\n\n        if (Object.keys(aprops ?? {}).length > 0) {\n            const logObject = { id: undefined };\n\n            for (const attr in aprops) {\n                if (aprops.hasOwnProperty(attr)) {\n                    logObject[attr] = aprops[attr];\n                }\n            }\n\n            // Let's push to analytics any updates that may have come from the backend\n            Statistics.analytics.addPermanentProperties({ ...logObject });\n\n            logObject.id = 'deployment_info';\n            const entry = JSON.stringify(logObject);\n\n            logger.info(entry);\n        }\n\n        this.sendDeploymentInfo = false;\n\n        const { region, shard } = aprops;\n\n        if (region || shard) {\n            // avoids sending empty values\n            this.eventEmitter.emit(JitsiConnectionEvents.PROPERTIES_UPDATED, cloneDeep({ region, shard }));\n        }\n    }\n\n\n    /**\n     * Process received identities.\n     * @param {Set<String>} identities The identities to process.\n     * @param {Set<String>} features The features to process, optional. If missing lobby component will be queried\n     * for more features.\n     * @private\n     */\n    private _processDiscoInfoIdentities(identities: Set<IIdentity>, features?: Set<string>): void {\n        // check for speakerstats\n        identities.forEach(identity => {\n            if (identity.type === 'av_moderation') {\n                this.avModerationComponentAddress = identity.name;\n                this._components.push(this.avModerationComponentAddress);\n            }\n\n            if (identity.type === 'end_conference') {\n                this.endConferenceComponentAddress = identity.name;\n                this._components.push(this.endConferenceComponentAddress);\n            }\n\n            if (identity.type === 'audio-translation') {\n                this.audioTranslationComponentAddress = identity.name;\n                this._components.push(this.audioTranslationComponentAddress);\n            }\n\n            if (identity.type === 'speakerstats') {\n                this.speakerStatsComponentAddress = identity.name;\n                this._components.push(this.speakerStatsComponentAddress);\n            }\n\n            if (identity.type === 'lobbyrooms') {\n                this.lobbySupported = true;\n                const processLobbyFeatures = f => {\n                    f.forEach(fr => {\n                        if (fr.endsWith('#displayname_required')) {\n                            this.eventEmitter.emit(JitsiConnectionEvents.DISPLAY_NAME_REQUIRED);\n                        }\n                    });\n                };\n\n                if (features) {\n                    processLobbyFeatures(features);\n                } else {\n                    identity.name && this.caps.getFeaturesAndIdentities(identity.name, identity.type)\n                        .then(({ features: f }) => processLobbyFeatures(f))\n                        .catch(e => logger.warn('Error getting features from lobby.', e?.message));\n                }\n            }\n\n            if (identity.type === 'shard') {\n                this.options.deploymentInfo.shard = this.connection.shard = identity.name;\n            }\n\n            if (identity.type === 'region') {\n                // @ts-ignore property 'region' does not exist on 'XmppConnection'\n                this.options.deploymentInfo.region = this.connection.region = identity.name;\n            }\n\n            if (identity.type === 'release') {\n                this.options.deploymentInfo.backendRelease = identity.name;\n            }\n\n            if (identity.type === 'breakout_rooms') {\n                this.breakoutRoomsComponentAddress = identity.name;\n                this._components.push(this.breakoutRoomsComponentAddress);\n\n                const processBreakoutRoomsFeatures = f => {\n                    this.breakoutRoomsFeatures = {};\n\n                    f.forEach(fr => {\n                        if (fr.endsWith('#rename')) {\n                            this.breakoutRoomsFeatures.rename = true;\n                        }\n                    });\n                };\n\n                if (features) {\n                    processBreakoutRoomsFeatures(features);\n                } else {\n                    identity.name && this.caps.getFeaturesAndIdentities(identity.name, identity.type)\n                        .then(({ features: f }) => processBreakoutRoomsFeatures(f))\n                        .catch(e => logger.warn('Error getting features for breakout rooms.', e?.message));\n                }\n            }\n\n            if (identity.type === FILE_SHARING_IDENTITY_TYPE) {\n                this.fileSharingComponentAddress = identity.name;\n                this._components.push(this.fileSharingComponentAddress);\n            }\n\n            if (identity.type === 'room_metadata') {\n                // we will receive the turn info via metadata\n                this.sendDiscoInfo = false;\n                this.roomMetadataComponentAddress = identity.name;\n                this._components.push(this.roomMetadataComponentAddress);\n            }\n\n            if (identity.type === 'visitors') {\n                this._components.push(identity.name);\n            }\n\n            if (identity.type === 'polls') {\n                this.pollsComponentAddress = identity.name;\n                this._components.push(this.pollsComponentAddress);\n            }\n        });\n\n        this._maybeSendDeploymentInfoStat(true);\n\n        if (this._components.length > 0) {\n            this._preComponentsMsgs.forEach(this._onPrivateMessage.bind(this));\n        }\n        this._preComponentsMsgs = [];\n    }\n\n    /**\n    * Parses a raw failure xmpp xml message received on auth failed.\n    *\n    * @param {string} msg - The raw failure message from xmpp.\n    * @returns {string|null} - The parsed message from the raw xmpp message.\n    */\n    private _parseConnectionFailedMessage(msg?: string): Nullable<string> {\n        if (!msg) {\n            return null;\n        }\n\n        FAILURE_REGEX.lastIndex = 0;\n        const matches = FAILURE_REGEX.exec(msg);\n\n        return matches ? matches[1] : null;\n    }\n\n    /**\n     *\n     * @param jid\n     * @param password\n     */\n    private _connect(jid: string, password?: string): void {\n        // connection.connect() starts the connection process.\n        //\n        // As the connection process proceeds, the user supplied callback will\n        // be triggered multiple times with status updates. The callback should\n        // take two arguments - the status code and the error condition.\n        //\n        // The status code will be one of the values in the Strophe.Status\n        // constants. The error condition will be one of the conditions defined\n        // in RFC 3920 or the condition ‘strophe-parsererror’.\n        //\n        // The Parameters wait, hold and route are optional and only relevant\n        // for BOSH connections. Please see XEP 124 for a more detailed\n        // explanation of the optional parameters.\n        //\n        // Connection status constants for use by the connection handler\n        // callback.\n        //\n        //  Status.ERROR - An error has occurred (websockets specific)\n        //  Status.CONNECTING - The connection is currently being made\n        //  Status.CONNFAIL - The connection attempt failed\n        //  Status.AUTHENTICATING - The connection is authenticating\n        //  Status.AUTHFAIL - The authentication attempt failed\n        //  Status.CONNECTED - The connection has succeeded\n        //  Status.DISCONNECTED - The connection has been terminated\n        //  Status.DISCONNECTING - The connection is currently being terminated\n        //  Status.ATTACHED - The connection has been attached\n\n        this._resetState();\n\n        // we want to send this only on the initial connect\n        this.sendDiscoInfo = true;\n        this.sendDeploymentInfo = true;\n\n        if (this.connection._stropheConn?._addSysHandler) {\n            this._sysMessageHandler = this.connection._stropheConn._addSysHandler(\n                this._onSystemMessage.bind(this),\n                null,\n                'message'\n            );\n        } else {\n            logger.warn('Cannot attach strophe system handler, jiconop cannot operate');\n        }\n\n        this.connection.connect(\n            jid,\n            password,\n            this.connectionHandler.bind(this, {\n                jid,\n                password\n            }));\n    }\n\n    /**\n     * Receives system messages during the connect/login process and checks for services or\n     * @param msg The received message.\n     * @returns {void}\n     * @private\n     */\n    private _onSystemMessage(msg: Element): void {\n        // proceed only if the message has any of the expected information\n        if (!exists(msg, ':scope>services') && !exists(msg, ':scope>query')) {\n            return;\n        }\n\n        const { features, identities } = parseDiscoInfo(msg);\n\n        this._processDiscoInfoIdentities(identities, features);\n\n        if (identities.size > 0 || features.size > 0) {\n            this.connection._stropheConn.deleteHandler(this._sysMessageHandler);\n            this._sysMessageHandler = null;\n        }\n    }\n\n    /**\n     * The method is supposed to gracefully close the XMPP connection and the main goal is to make sure that the current\n     * participant will be removed from the conference XMPP MUC, so that it doesn't leave a \"ghost\" participant behind.\n     *\n     * @param {Object} ev - Optionally, the event which triggered the necessity to disconnect from the XMPP server\n     * (e.g. beforeunload, unload).\n     * @private\n     * @returns {void}\n     */\n    private _cleanupXmppConnection(ev: Optional<Event>): void {\n        // XXX Strophe is asynchronously sending by default. Unfortunately, that means that there may not be enough time\n        // to send an unavailable presence or disconnect at all. Switching Strophe to synchronous sending is not much of\n        // an option because it may lead to a noticeable delay in navigating away from the current location. As\n        // a compromise, we will try to increase the chances of sending an unavailable presence and/or disconnecting\n        // within the short time span that we have upon unloading by invoking flush() on the connection. We flush() once\n        // before disconnect() in order to attempt to have its unavailable presence at the top of the send queue. We\n        // flush() once more after disconnect() in order to attempt to have its unavailable presence sent as soon as\n        // possible.\n        !this.connection.isUsingWebSocket && this.connection.flush();\n\n        if (!this.connection.isUsingWebSocket && ev !== null && typeof ev !== 'undefined') {\n            const evType = ev.type;\n\n            if (evType === 'beforeunload' || evType === 'unload') {\n                // XXX Whatever we said above, synchronous sending is the best (known) way to properly disconnect from\n                // the XMPP server. Consequently, it may be fine to have the source code and comment it in or out\n                // depending on whether we want to run with it for some time.\n                this.connection.options.sync = true;\n\n                // This is needed in some browsers where sync xhr sending is disabled by default on unload.\n                if (this.connection.sendUnavailableBeacon()) {\n\n                    return;\n                }\n            }\n        }\n\n        this.connection.disconnect();\n\n        this._startConnecting = false;\n\n        if (this.connection.options.sync !== true) {\n            this.connection.flush();\n        }\n    }\n\n    /**\n     *\n     */\n    private _initStrophePlugins(): void {\n        const iceConfig = {\n            jvb: { iceServers: [ ] },\n            p2p: { iceServers: [ ], iceTransportPolicy: undefined }\n        };\n\n        const p2pStunServers = (this.options.p2p?.stunServers) || DEFAULT_STUN_SERVERS;\n\n        if (Array.isArray(p2pStunServers)) {\n            logger.info('P2P STUN servers: ', p2pStunServers);\n            iceConfig.p2p.iceServers = p2pStunServers;\n        }\n\n        if (this.options.p2p?.iceTransportPolicy) {\n            logger.info('P2P ICE transport policy: ',\n                this.options.p2p.iceTransportPolicy);\n\n            iceConfig.p2p.iceTransportPolicy\n                = this.options.p2p.iceTransportPolicy;\n        }\n\n        this.connection.addConnectionPlugin('emuc', new MucConnectionPlugin(this));\n        this.connection.addConnectionPlugin('jingle', new JingleConnectionPlugin(this, this.eventEmitter, iceConfig));\n        this.connection.addConnectionPlugin('rayo', new RayoConnectionPlugin());\n    }\n\n    /**\n     * Returns details about connection failure. Shard change or is it after\n     * suspend.\n     * @returns { IConnectionFailedReasonDetails} contains details about a connection failure.\n     * @private\n     */\n    private _getConnectionFailedReasonDetails(): IConnectionFailedReasonDetails {\n        const details: IConnectionFailedReasonDetails = {};\n\n        // check for moving between shard if information is available\n        if (this.options.deploymentInfo?.shard\n            && this.connection.lastResponseHeaders) {\n\n            // split headers by line\n            const headersArr = this.connection.lastResponseHeaders\n                .trim().split(/[\\r\\n]+/);\n            const headers = {};\n\n            headersArr.forEach(line => {\n                const parts = line.split(': ');\n                const header = parts.shift();\n                const value = parts.join(': ');\n\n                headers[header] = value;\n            });\n\n            /* eslint-disable camelcase */\n            details.shard_changed\n                = this.options.deploymentInfo.shard\n                    !== headers['x-jitsi-shard'];\n            /* eslint-enable camelcase */\n        }\n\n        /* eslint-disable camelcase */\n        // check for possible suspend\n        details.suspend_time = this.connection.ping.getPingSuspendTime();\n        details.time_since_last_success = this.connection.getTimeSinceLastSuccess();\n        /* eslint-enable camelcase */\n\n        return details;\n    }\n\n    /**\n     * Resets any state/flag before starting a new connection.\n     * @private\n     */\n    private _resetState(): void {\n        this._anonymousConnectionFailed = false;\n        this.connectionFailed = false;\n        this._lastErrorMsg = undefined;\n        this._disconnectInProgress = undefined;\n        this._wasDisconnected = false;\n    }\n\n    /**\n     * Returns the current XMPP connection instance.\n     */\n    public getConnection(): XmppConnection {\n        return this.connection;\n    }\n\n    /**\n     * Receive connection status changes and handles them.\n     *\n     * @param {Object} credentials\n     * @param {string} credentials.jid - The user's XMPP ID passed to the\n     * connect method. For example, 'user@xmpp.com'.\n     * @param {string} credentials.password - The password passed to the connect\n     * method.\n     * @param {string} status - One of Strophe's connection status strings.\n     * @param {string} [msg] - The connection error message provided by Strophe.\n     */\n    public connectionHandler(credentials: IConnectionCredentials = {}, status: Strophe.Status, msg?: string): void {\n        const now = window.performance.now();\n        const statusStr = Strophe.getStatusString(status).toLowerCase();\n\n        this.connectionTimes[statusStr] = now;\n        logger.info(`(TIME) Strophe ${statusStr}${msg ? `[${msg}]` : ''}:\\t`, now);\n\n        this.eventEmitter.emit(XMPPEvents.CONNECTION_STATUS_CHANGED, credentials, status, msg);\n        this._maybeSendDeploymentInfoStat();\n        if (status === Strophe.Status.CONNECTED || status === Strophe.Status.ATTACHED) {\n            // once connected or attached we no longer need this handle, drop it if it exist\n            if (this._sysMessageHandler) {\n                this.connection._stropheConn.deleteHandler(this._sysMessageHandler);\n                this._sysMessageHandler = null;\n            }\n            this.sendDiscoInfo && this.connection.jingle.getStunAndTurnCredentials();\n\n            logger.info(`My Jabber ID: ${this.connection.jid}`);\n\n            this._wasDisconnected && RTCStats.sendStatsEntry(RTCStatsEvents.STROPHE_RECONNECTED_EVENT);\n\n            // XmppConnection emits CONNECTED again on reconnect - a good opportunity to clear any \"last error\" flags\n            this._resetState();\n\n            // make sure we will send the info after the features request succeeds or fails\n            this.sendDeploymentInfo = false;\n            this.sendDiscoInfo && this.caps.getFeaturesAndIdentities(this.options.hosts.domain, undefined)\n                .then(({ features, identities }) => {\n                    if (!features.has(Strophe.NS.PING)) {\n                        logger.error(`Ping NOT supported by ${\n                            this.options.hosts.domain} - please enable ping in your XMPP server config`);\n                    }\n\n                    this._processDiscoInfoIdentities(\n                        identities, undefined /* when querying we will query for features */);\n                })\n                .catch(error => {\n                    logger.error('Feature discovery error', error);\n\n                    this._maybeSendDeploymentInfoStat(true);\n                });\n\n            // make sure we don't query again\n            this.sendDiscoInfo = false;\n\n            if (credentials.password) {\n                this.authenticatedUser = true;\n            }\n            if (this.connection && this.connection.connected\n                && Strophe.getResourceFromJid(this.connection.jid)) {\n                // .connected is true while connecting?\n                // this.connection.send($pres());\n                this.eventEmitter.emit(\n                    JitsiConnectionEvents.CONNECTION_ESTABLISHED,\n                    Strophe.getResourceFromJid(this.connection.jid));\n            }\n        } else if (status === Strophe.Status.CONNFAIL) {\n            if (msg === 'x-strophe-bad-non-anon-jid') {\n                this._anonymousConnectionFailed = true;\n            } else {\n                this.connectionFailed = true;\n            }\n            this._lastErrorMsg = msg;\n            if (msg === 'giving-up') {\n                this.eventEmitter.emit(\n                    JitsiConnectionEvents.CONNECTION_FAILED,\n                    JitsiConnectionErrors.OTHER_ERROR, msg);\n            }\n        } else if (status === Strophe.Status.ERROR) {\n            this._lastErrorMsg = msg;\n        } else if (status === Strophe.Status.DISCONNECTED) {\n            RTCStats.sendStatsEntry(RTCStatsEvents.STROPHE_DISCONNECTED_EVENT);\n            this._wasDisconnected = true;\n            // Stop ping interval\n            this.connection.ping.stopInterval();\n            const wasIntentionalDisconnect = Boolean(this._disconnectInProgress);\n            const errMsg = msg || this._lastErrorMsg;\n\n            if (this._anonymousConnectionFailed) {\n                // prompt user for username and password\n                this.eventEmitter.emit(\n                    JitsiConnectionEvents.CONNECTION_FAILED,\n                    JitsiConnectionErrors.PASSWORD_REQUIRED);\n            } else if (this.connectionFailed) {\n                this.eventEmitter.emit(\n                    JitsiConnectionEvents.CONNECTION_FAILED,\n                    JitsiConnectionErrors.OTHER_ERROR,\n                    errMsg,\n                    undefined, /* credentials */\n                    this._getConnectionFailedReasonDetails());\n            } else if (wasIntentionalDisconnect) {\n                this.eventEmitter.emit(\n                    JitsiConnectionEvents.CONNECTION_DISCONNECTED, errMsg);\n            } else {\n                // XXX if Strophe drops the connection while not being asked to,\n                // it means that most likely some serious error has occurred.\n                // One currently known case is when a BOSH request fails for\n                // more than 4 times. The connection is dropped without\n                // supplying a reason(error message/event) through the API.\n                logger.error('XMPP connection dropped!');\n\n                // XXX if the last request error is within 5xx range it means it\n                // was a server failure\n                const lastErrorStatus = Strophe.getLastErrorStatus();\n\n                if (lastErrorStatus >= 500 && lastErrorStatus < 600) {\n                    this.eventEmitter.emit(\n                        JitsiConnectionEvents.CONNECTION_FAILED,\n                        JitsiConnectionErrors.SERVER_ERROR,\n                        errMsg || 'server-error',\n                        /* credentials */ undefined,\n                        this._getConnectionFailedReasonDetails());\n                } else {\n                    this.eventEmitter.emit(\n                        JitsiConnectionEvents.CONNECTION_FAILED,\n                        JitsiConnectionErrors.CONNECTION_DROPPED_ERROR,\n                        errMsg || 'connection-dropped-error',\n                        /* credentials */ undefined,\n                        this._getConnectionFailedReasonDetails());\n                }\n            }\n        } else if (status === Strophe.Status.AUTHFAIL) {\n            const lastFailedRawMessage = this.getConnection().getLastFailedMessage();\n\n            // wrong password or username, prompt user\n            this.eventEmitter.emit(\n                JitsiConnectionEvents.CONNECTION_FAILED,\n                JitsiConnectionErrors.PASSWORD_REQUIRED,\n                msg || this._parseConnectionFailedMessage(lastFailedRawMessage),\n                credentials);\n\n            this.connection.disconnect();\n        }\n    }\n\n    /**\n     * Attach to existing connection. Can be used for optimizations. For\n     * example: if the connection is created on the server we can attach to it\n     * and start using it.\n     *\n     * @param options {object} connecting options - rid, sid, jid and password.\n     */\n    public attach(options: IConnectionCredentials): void {\n        this._resetState();\n\n        // we want to send this only on the initial connect\n        this.sendDiscoInfo = true;\n\n        const now = this.connectionTimes.attaching = window.performance.now();\n\n        logger.info('(TIME) Strophe Attaching:\\t', now);\n        this.connection.attach(options.jid, options.sid,\n            (Number.parseInt(options.rid, 10) + 1).toString(),\n            this.connectionHandler.bind(this, {\n                jid: options.jid,\n                password: options.password\n            }));\n    }\n\n    /**\n     *\n     * @param jid\n     * @param password\n     */\n    public connect(jid: string, password: string) {\n        if (!jid) {\n            const { anonymousdomain, domain } = this.options.hosts;\n            let configDomain = anonymousdomain || domain;\n\n            // Force authenticated domain if room is appended with '?login=true'\n            // or if we're joining with the token\n\n            // FIXME Do not rely on window.location because (1) React Native\n            // does not have a window.location by default and (2) here we cannot\n            // know for sure that query/search has not be stripped from\n            // window.location by the time the following executes.\n            const { location } = window;\n\n            if (anonymousdomain) {\n                const search = location?.search;\n\n                if ((search && search.indexOf('login=true') !== -1)\n                        || this.token) {\n                    configDomain = domain;\n                }\n            }\n\n            // eslint-disable-next-line no-param-reassign\n            jid = configDomain || (location?.hostname);\n        }\n\n        this._startConnecting = true;\n\n        return this._connect(jid, password);\n    }\n\n    /**\n     * Joins or creates a muc with the provided jid, created from the passed\n     * in room name and muc host and onCreateResource result.\n     *\n     * @param {string} roomName - The name of the muc to join.\n     * @param {Object} options - Configuration for how to join the muc.\n     * @param {Function} [onCreateResource] - Callback to invoke when a resource\n     * is to be added to the jid.\n     * @returns {ChatRoom} Resolves with an instance of a strophe muc.\n     */\n    public createRoom(roomName: string, options: IRoomCreationOptions, onCreateResource: (jid: string, user: any) => string): ChatRoom {\n        // Support passing the domain in a String object as part of the room name.\n        const domain = (roomName as { domain?: string; }).domain || options.customDomain;\n\n        // There are cases (when using subdomain) where muc can hold an uppercase part\n        let roomjid = `${this.getRoomJid(roomName, domain)}/`;\n        const mucNickname = onCreateResource\n            ? onCreateResource(this.connection.jid, this.authenticatedUser)\n            : RandomUtil.randomHexString(8).toLowerCase();\n\n        logger.info(`JID ${this.connection.jid} using MUC nickname ${mucNickname}`);\n        roomjid += mucNickname;\n\n        return this.connection.emuc?.createRoom?.(roomjid, null, options);\n    }\n\n    /**\n     * Returns the room JID based on the passed room name and domain.\n     *\n     * @param {string} roomName - The room name.\n     * @param {string} domain - The domain.\n     * @returns {string} - The room JID.\n     */\n    public getRoomJid(roomName: string, domain: string): string {\n        return `${roomName}@${domain ? domain : this.options.hosts.muc.toLowerCase()}`;\n    }\n\n    /**\n     * Check if a room with the passed JID is already created.\n     *\n     * @param {string} roomJid - The JID of the room.\n     * @returns {boolean}\n     */\n    public isRoomCreated(roomName: string, domain: string): boolean {\n        return this.connection.emuc?.isRoomCreated?.(this.getRoomJid(roomName, domain)) || false;\n    }\n\n    /**\n     * Returns the jid of the participant associated with the Strophe connection.\n     *\n     * @returns {string} The jid of the participant.\n     */\n    public getJid(): string {\n        return this.connection.jid;\n    }\n\n    /**\n     * Returns the logs from strophe.jingle.\n     * @returns {Record<string, unknown>} - The jingle logs.\n     */\n    public getJingleLog(): Record<string, unknown> {\n        const jingle = this.connection.jingle;\n\n\n        return jingle ? jingle.getLog() : { metadata: {} };\n    }\n\n    /**\n     * Returns the logs from strophe.\n     */\n    public getXmppLog(): Nullable<object> {\n        return this.connection.logger?.log || null;\n    }\n\n    /**\n     *\n     */\n    public dial(...args: [to: string, from: string, roomName: string, roomPass: string, focusMucJid: string]): Promise<void> {\n        return this.connection.rayo?.dial(...args);\n    }\n\n    /**\n     * Pings the server.\n     * @param timeout how many ms before a timeout should occur.\n     * @returns {Promise} resolved on ping success and reject on an error or\n     * a timeout.\n     */\n    public ping(timeout: number): Promise<void> {\n        return new Promise((resolve, reject) => {\n            this.connection.ping.ping(this.connection.pingDomain, resolve, reject, timeout);\n        });\n    }\n\n    /**\n     *\n     */\n    public getSessions(): object {\n        return this.connection.jingle.sessions;\n    }\n\n    /**\n     * Disconnects this from the XMPP server (if this is connected).\n     *\n     * @param {Object} ev - Optionally, the event which triggered the necessity to\n     * disconnect from the XMPP server (e.g. beforeunload, unload).\n     * @returns {Promise} - Resolves when the disconnect process is finished or rejects with an error.\n     */\n    public disconnect(ev: Optional<Event> = undefined): Promise<void> | boolean {\n        logger.info(`XMPP disconnect triggered by the event=${ev?.type}`);\n\n        // Remove the window unload listeners registered in the constructor so we don't leak them when multiple\n        // connections are created over the lifetime of the page.\n        this._removeUnloadHandlers();\n\n        if (this._disconnectInProgress) {\n            return this._disconnectInProgress;\n        } else if (!this.connection || !this._startConnecting) {\n            // we have created a connection, but never called connect we still want to resolve on calling disconnect\n            // this is visitors use case when using http to send conference request.\n            return Promise.resolve();\n        }\n\n        this._disconnectInProgress = new Promise(resolve => {\n            const disconnectListener = (credentials, status) => {\n                if (status === Strophe.Status.DISCONNECTED) {\n                    this.eventEmitter.removeListener(XMPPEvents.CONNECTION_STATUS_CHANGED, disconnectListener);\n                    resolve();\n                }\n            };\n\n            this.eventEmitter.on(XMPPEvents.CONNECTION_STATUS_CHANGED, disconnectListener);\n        });\n\n        this._cleanupXmppConnection(ev);\n\n        return this._disconnectInProgress;\n    }\n\n    /**\n     * Notifies speaker stats component if available that we are the new\n     * dominant speaker in the conference.\n     * @param {String} roomJid - The room jid where the speaker event occurred.\n     * @param {boolean} silence - Whether the dominant speaker is silent or not.\n     */\n    public sendDominantSpeakerEvent(roomJid: string, silence: boolean): void {\n        // no speaker stats component advertised\n        if (!this.speakerStatsComponentAddress || !roomJid) {\n            return;\n        }\n\n        const msg = $msg({ to: this.speakerStatsComponentAddress });\n\n        msg.c('speakerstats', {\n            room: roomJid,\n            silence,\n            xmlns: 'http://jitsi.org/jitmeet'\n        }).up();\n\n        this.connection.send(msg);\n    }\n\n    /**\n     * Sends face landmarks to speaker stats component.\n     * @param {String} roomJid - The room jid where the speaker event occurred.\n     * @param {Object} payload - The expression to be sent to the speaker stats.\n     */\n    public sendFaceLandmarksEvent(roomJid: string, payload: IFaceLandmarksPayload): void {\n        // no speaker stats component advertised\n        if (!this.speakerStatsComponentAddress || !roomJid) {\n            return;\n        }\n\n        const msg = $msg({ to: this.speakerStatsComponentAddress });\n\n        msg.c('faceLandmarks', {\n            duration: payload.duration,\n            faceExpression: payload.faceExpression,\n            room: roomJid,\n            timestamp: payload.timestamp,\n            xmlns: 'http://jitsi.org/jitmeet'\n        }).up();\n\n        this.connection.send(msg);\n    }\n\n    /**\n     * Check if the given argument is a valid JSON ENDPOINT_MESSAGE string by\n     * parsing it and checking if it has a field called 'type'.\n     *\n     * @param {string} jsonString check if this string is a valid json string\n     * and contains the special structure.\n     * @returns {boolean, object} if given object is a valid JSON string, return\n     * the json object. Otherwise, returns false.\n     */\n    public tryParseJSONAndVerify(jsonString: string): boolean | IJsonMessage {\n        // ignore empty strings, like message errors\n        if (!jsonString) {\n            return false;\n        }\n\n        try {\n            // Note: we use `unescape` to also convert HTML entities to UTF-8 since\n            // Jigasi seems to encode them like that in some circumstances.\n            const json = safeJsonParse(unescape(jsonString));\n\n            // Handle non-exception-throwing cases:\n            // Neither JSON.parse(false) or JSON.parse(1234) throw errors,\n            // hence the type-checking,\n            // but... JSON.parse(null) returns null, and\n            // typeof null === \"object\",\n            // so we must check for that, too.\n            // Thankfully, null is falsey, so this suffices:\n            if (json && typeof json === 'object') {\n                const type = json[JITSI_MEET_MUC_TYPE];\n\n                if (typeof type !== 'undefined') {\n                    return json;\n                }\n\n                logger.debug('parsing valid json but does not have correct '\n                    + 'structure', 'topic: ', type);\n            }\n        } catch (e) {\n            logger.error(`Error parsing json ${jsonString}`, e);\n\n            return false;\n        }\n\n        return false;\n    }\n\n    /**\n     * This method allows renewal of the tokens if they are expiring.\n     * @param token - The new token.\n     */\n    refreshToken(token: string): Promise<void> {\n        this.token = token;\n\n        let serviceUrl = this.options.serviceUrl;\n\n        serviceUrl += `${serviceUrl.indexOf('?') === -1 ? '?' : '&'}token=${token}`;\n\n        return this.connection.refreshToken(serviceUrl);\n    }\n}\n",null,null,null,null,"// vodozemac message types\nexport const PREKEY_MESSAGE = 0;\nexport const NORMAL_MESSAGE = 1;\n\nexport const OLM_MESSAGE = 'olm';\nexport const OLM_MESSAGE_TYPES = {\n    CHAT_KEY: 'chat-key',\n    CHAT_KEY_REQUEST: 'chat-key-request',\n    ERROR: 'error',\n    KEY_INFO: 'key-info',\n    KEY_UPDATE: 'key-update',\n    KEY_UPDATE_REQ: 'key-update-request',\n    PQ_SESSION_ACK: 'pq-session-ack',\n    PQ_SESSION_INIT: 'pq-session-init',\n    SESSION_ACK: 'session-ack',\n    SESSION_DONE: 'session-done',\n    SESSION_INIT: 'session-init',\n};\nexport type MessageType =\n    (typeof OLM_MESSAGE_TYPES)[keyof typeof OLM_MESSAGE_TYPES];\n\nexport const PROTOCOL_STATUS = {\n    DONE: 'protocol-established',\n    READY_TO_START: 'ready-to-start',\n    TERMINATED: 'protocol-terminated',\n    WAITING_DONE: 'waiting-for-done',\n    WAITING_PQ_SESSION_ACK: 'waiting-for-pq-session-ack',\n    WAITING_PQ_SESSION_INIT: 'waiting-for-pq-session-init',\n    WAITING_SESSION_ACK: 'waiting-for-session-ack',\n};\n\nexport type ProtocolStatus =\n    (typeof PROTOCOL_STATUS)[keyof typeof PROTOCOL_STATUS];\n\nexport type ReplyMessage = KeyInfo | SessionInit | PQsessionInit | PQsessionAck;\n\nexport type KeyInfo = {\n    ciphertext: string;\n    pqCiphertext: string;\n};\n\nexport type SessionInit = {\n    commitment: string;\n    otKey: string;\n    publicKey: string;\n    publicKyberKey: string;\n};\nexport type PQsessionAck = {\n    ciphertext: string;\n    encapsKyber: string;\n    pqCiphertext: string;\n};\n\nexport type PQsessionInit = {\n    ciphertext: string;\n    encapsKyber: string;\n    publicKey: string;\n    publicKyberKey: string;\n};\n\nexport type ParticipantEvent = {\n    id: string;\n    type: 'join' | 'leave';\n};\n\nexport type MediaKeys = {\n    index: number;\n    olmKey: Uint8Array;\n    pqKey: Uint8Array;\n    userID: string;\n};\n\nexport class CryptoError extends Error {\n    constructor(message: string) {\n        super(message);\n        this.name = 'CryptoError';\n    }\n}\n","import { blake3 } from '@noble/hashes/blake3.js';\nimport { bytesToHex, concatBytes, randomBytes, utf8ToBytes } from '@noble/hashes/utils.js';\n\nimport { CryptoError, MediaKeys } from './Types';\n\nconst CONTEXT_DERIVE_KEY = 'Internxt Meet Web App 2025-11-12 15:46:31 derive one key from two keys';\nconst CONTEXT_RATCHET = 'Internxt Meet Web App 2025-11-12 17:09:10 ratchet media key';\n\nconst AES_ALGORITHM = 'AES-GCM';\nconst AES_KEY_BIT_LENGTH = 256;\nconst KEY_FORMAT = 'raw';\nconst IV_LEN_BYTES = 16;\n\nexport function hashChatKeys(keyECC: Uint8Array, keyPQ: Uint8Array): Uint8Array {\n    try {\n        const hasher = blake3.create();\n\n        hasher.update(keyECC).update(keyPQ);\n\n        return hasher.digest();\n    } catch (e) {\n        throw new CryptoError(`${e.name}: ${e.message}`);\n    }\n}\n\n\nexport function hashData(data: string[]): Uint8Array {\n    try {\n        const hasher = blake3.create();\n\n        for (const chunk of data) {\n            hasher.update(utf8ToBytes(chunk));\n        }\n\n        return hasher.digest();\n    } catch (e) {\n        throw new CryptoError(`${e.name}: ${e.message}`);\n    }\n}\n\nexport function commitToMediaKey(keys: MediaKeys, commitment: Uint8Array): string {\n    try {\n        const hasher = blake3.create();\n\n        hasher.update(commitment);\n        hasher.update(keys.olmKey);\n        hasher.update(keys.pqKey);\n        hasher.update(new Uint8Array(keys.index));\n        hasher.update(utf8ToBytes(keys.userID));\n        const result = hasher.digest();\n\n        return bytesToHex(result);\n    } catch (e) {\n        throw new CryptoError(`${e.name}: ${e.message}`);\n    }\n}\n\n// This funcion must remain async for tests to work\nexport async function hashKey(keys: MediaKeys): Promise<string> {\n    try {\n        const hasher = blake3.create();\n\n        hasher.update(keys.olmKey);\n        hasher.update(keys.pqKey);\n        hasher.update(new Uint8Array(keys.index));\n        hasher.update(utf8ToBytes(keys.userID));\n        const result = hasher.digest();\n\n        return bytesToHex(result);\n    } catch (e) {\n        throw new CryptoError(`${e.name}: ${e.message}`);\n    }\n}\n\nexport function getBitsFromString(byteLen: number, data: string): Uint8Array {\n    try {\n        return blake3(utf8ToBytes(data), { dkLen: byteLen });\n    } catch (e) {\n        throw new CryptoError(`${e.name}: ${e.message}`);\n    }\n}\n\nexport function deriveSymmetricCryptoKeyFromTwoKeys(key1: Uint8Array, key2: Uint8Array): Uint8Array {\n    try {\n        const combined_key = blake3(key1, { key: key2 });\n\n        return blake3(combined_key, { context: utf8ToBytes(CONTEXT_DERIVE_KEY) });\n    } catch (e) {\n        throw new CryptoError(`${e.name}: ${e.message}`);\n    }\n}\n\nexport async function importSymmetricCryptoKey(keyData: Uint8Array | ArrayBuffer): Promise<CryptoKey> {\n    try {\n        return await crypto.subtle.importKey(\n        KEY_FORMAT,\n        new Uint8Array(keyData),\n        {\n            length: AES_KEY_BIT_LENGTH,\n            name: AES_ALGORITHM,\n        },\n        true,\n        [ 'encrypt', 'decrypt' ],\n        );\n    } catch (e) {\n        throw new CryptoError(`${e.name}: ${e.message}`);\n    }\n}\n\n\nexport function ratchetMediaKey(key: MediaKeys): MediaKeys {\n    try {\n        const olmKey = blake3(key.olmKey, { context: utf8ToBytes(CONTEXT_RATCHET) });\n        const pqKey = blake3(key.pqKey, { context: utf8ToBytes(CONTEXT_RATCHET) });\n        const index = key.index + 1;\n        const userID = key.userID;\n\n        return { index, olmKey, pqKey, userID };\n    } catch (e) {\n        throw new CryptoError(`${e.name}: ${e.message}`);\n    }\n}\n\nfunction createNISTbasedIV(freeField?: string): Uint8Array {\n    try {\n        if (!freeField) {\n            return randomBytes(IV_LEN_BYTES);\n        }\n\n        const iv = new Uint8Array(16);\n        const randFiled = randomBytes(12);\n\n        iv.set(randFiled, 0);\n\n        const freeFiledFixedLength = getBitsFromString(4, freeField);\n\n        iv.set(freeFiledFixedLength, 12);\n\n        return iv;\n    } catch (e) {\n        throw new CryptoError(`${e.name}: ${e.message}`);\n    }\n}\n\nexport async function encryptSymmetrically(\n        encryptionKey: CryptoKey,\n        message: Uint8Array,\n        additionalData: Uint8Array,\n        freeField?: string,\n): Promise<Uint8Array> {\n    try {\n        const iv = createNISTbasedIV(freeField);\n        const encrypted = await crypto.subtle.encrypt({ additionalData: additionalData as BufferSource, iv: iv as BufferSource, name: AES_ALGORITHM }, encryptionKey, message as BufferSource);\n        const ciphertext = new Uint8Array(encrypted);\n\n        return concatBytes(ciphertext, iv);\n    } catch (e) {\n        throw new CryptoError(`${e.name}: ${e.message}`);\n    }\n}\n\nexport async function decryptSymmetrically(\n        encryptionKey: CryptoKey,\n        combined: Uint8Array,\n        additionalData: Uint8Array,\n): Promise<Uint8Array> {\n    try {\n        const ciphertext = combined.slice(0, combined.length - IV_LEN_BYTES);\n        const iv = combined.slice(combined.length - IV_LEN_BYTES);\n\n        const decrypted = await crypto.subtle.decrypt(\n            { additionalData: additionalData as BufferSource, iv: iv as BufferSource, name: AES_ALGORITHM },\n            encryptionKey,\n            ciphertext as BufferSource,\n        );\n\n        return new Uint8Array(decrypted);\n\n    } catch (e) {\n        throw new CryptoError(`${e.name}: ${e.message}`);\n    }\n}\n\nexport function genSymmetricKey(): Uint8Array {\n    try {\n        return randomBytes(AES_KEY_BIT_LENGTH / 8);\n    } catch (e) {\n        throw new CryptoError(`${e.name}: ${e.message}`);\n    }\n}\n","/* global RTCRtpScriptTransform */\nimport { getLogger } from '@jitsi/logger';\n\nimport Listenable from '../util/Listenable';\n\nconst logger = getLogger('modules/e2ee-internxt/E2EEContext');\n\n/**\n * Context encapsulating the cryptography bits required for E2EE.\n * This uses the WebRTC Insertable Streams API which is explained in\n *   https://github.com/alvestrand/webrtc-media-streams/blob/master/explainer.md\n * that provides access to the encoded frames and allows them to be transformed.\n *\n */\nexport default class E2EEcontext extends Listenable {\n    private readonly _worker: Worker;\n    private _workerUrl: string | null = null;\n    private scriptEl: HTMLScriptElement | null = null;\n\n    constructor() {\n        super();\n        this._worker = this._initializeWorker();\n\n        this._worker.onerror = e => logger.error(e);\n\n        this._worker.onmessage = (event: MessageEvent) => {\n            const { operation, sas } = event.data;\n\n            if (operation === 'updateSAS' && sas) {\n                this.updateSAS(sas);\n            }\n        };\n    }\n\n    private _initializeWorker(): Worker {\n        this.scriptEl = document.querySelector<HTMLScriptElement>(\n            'script[src*=\"lib-meet\"]',\n        );\n        let baseUrl = '';\n\n        if (this.scriptEl) {\n            const idx = this.scriptEl.src.lastIndexOf('/');\n\n            baseUrl = `${this.scriptEl.src.substring(0, idx)}/`;\n        }\n\n        let workerUrl = `${baseUrl}lib-meet.e2ee-worker.js`;\n\n        if (baseUrl && baseUrl !== '/') {\n            const workerBlob = new Blob([ `importScripts(\"${workerUrl}\");` ], {\n                type: 'application/javascript',\n            });\n\n            workerUrl = URL.createObjectURL(workerBlob);\n            this._workerUrl = workerUrl;\n        }\n\n        return new Worker(workerUrl, { name: 'E2EE Worker' });\n    }\n\n    private async updateSAS(sas: string[]) {\n        this.emit('sasUpdated', sas);\n    }\n\n    /**\n     * Disposes of the worker and cleans up resources.\n     */\n    dispose() {\n        logger.info('E2EE: Disposing E2EE context and terminating worker');\n\n        this.cleanupAll();\n        this._worker.terminate();\n        if (this._workerUrl) {\n            URL.revokeObjectURL(this._workerUrl);\n            this._workerUrl = null;\n        }\n        this.scriptEl?.remove();\n        this.scriptEl = null;\n    }\n\n    cleanup(participantId: string) {\n        this._worker.postMessage({\n            operation: 'cleanup',\n            participantId,\n        });\n    }\n\n    cleanupAll() {\n        this._worker.postMessage({\n            operation: 'cleanupAll',\n        });\n    }\n\n    /**\n     * Handles the given {@code RTCRtpReceiver} by creating a {@code TransformStream} which will inject\n     * a frame decoder.\n     *\n     * @param {RTCRtpReceiver} receiver - The receiver which will get the decoding function injected.\n     * @param {string} participantId - The participant id that this receiver belongs to.\n     */\n    handleReceiver(receiver: RTCRtpReceiver, participantId: string) {\n        if (receiver.kJitsiE2EE) return;\n        receiver.kJitsiE2EE = true;\n\n        const options = {\n            operation: 'decode',\n            participantId,\n        };\n\n        if (window.RTCRtpScriptTransform) {\n            receiver.transform = new RTCRtpScriptTransform(\n                this._worker,\n                options,\n            );\n        } else if (receiver.createEncodedStreams) {\n            const { readable, writable } = receiver.createEncodedStreams();\n\n            this._worker.postMessage(\n                {\n                    ...options,\n                    readableStream: readable,\n                    writableStream: writable,\n                },\n                [ readable, writable ],\n            );\n        } else logger.error('Receiver does not support encoded streams.!');\n    }\n\n    /**\n     * Handles the given {@code RTCRtpSender} by creating a {@code TransformStream} which will inject\n     * a frame encoder.\n     *\n     * @param {RTCRtpSender} sender - The sender which will get the encoding function injected.\n     * @param {string} participantId - The participant id that this sender belongs to.\n     */\n    handleSender(sender: RTCRtpSender, participantId: string) {\n        if (sender.kJitsiE2EE) return;\n        sender.kJitsiE2EE = true;\n\n        const options = {\n            operation: 'encode',\n            participantId,\n        };\n\n        if (window.RTCRtpScriptTransform) {\n            sender.transform = new RTCRtpScriptTransform(this._worker, options);\n        } else if (sender.createEncodedStreams) {\n            const { readable, writable } = sender.createEncodedStreams();\n\n            this._worker.postMessage(\n                {\n                    ...options,\n                    readableStream: readable,\n                    writableStream: writable,\n                },\n                [ readable, writable ],\n            );\n        } else logger.error('Sender does not support encoded streams.');\n    }\n\n    setKey(\n            participantId: string,\n            olmKey: Uint8Array,\n            pqKey: Uint8Array,\n            index: number,\n    ) {\n        this._worker.postMessage({\n            index,\n            olmKey,\n            operation: 'setKey',\n            participantId,\n            pqKey,\n        });\n    }\n\n    setKeysCommitment(participantId: string, commitment: Uint8Array) {\n        this._worker.postMessage({\n            commitment,\n            operation: 'setKeysCommitment',\n            participantId,\n        });\n    }\n\n    setChatKeyHash(chatKeyHash: Uint8Array) {\n        this._worker.postMessage({\n            chatKeyHash,\n            operation: 'setChatKeyHash',\n        });\n    }\n\n    ratchetKeys(participantId: string) {\n        this._worker.postMessage({\n            operation: 'ratchetKeys',\n            participantId,\n        });\n    }\n\n}\n","import { Account, Session } from 'vodozemac-wasm';\n\nimport { decryptSymmetrically, deriveSymmetricCryptoKeyFromTwoKeys, encryptSymmetrically, hashKey, importSymmetricCryptoKey } from './CryptoUtils';\nimport {\n    CryptoError,\n    KeyInfo,\n    MediaKeys,\n    NORMAL_MESSAGE,\n    PREKEY_MESSAGE,\n    PROTOCOL_STATUS,\n    ProtocolStatus,\n} from './Types';\nimport { base64ToUint8Array, uint8ArrayToBase64 } from './Utils';\n\n\nconst AUX = new TextEncoder().encode('Session Key Exchange');\nconst AUX_CHAT = new TextEncoder().encode('Chat Key Exchange');\n\nexport class SessionData {\n    private status: ProtocolStatus;\n    private commitment: string;\n    private keyToSend: MediaKeys;\n    private session?: Session;\n    private pqSessionKey?: CryptoKey;\n    private kemSecret: Uint8Array;\n\n    constructor(key: MediaKeys) {\n        this.status = PROTOCOL_STATUS.READY_TO_START;\n        this.keyToSend = key;\n    }\n\n    indexChanged(key: MediaKeys): boolean {\n        return this.keyToSend.index !== key.index;\n    }\n\n    createInboundOLMchannel(\n            account: Account,\n            publicKey: string,\n            ciphertext: string,\n    ) {\n        try {\n            const { plaintext, session } = account.create_inbound_session(\n            publicKey,\n            PREKEY_MESSAGE,\n            ciphertext,\n            );\n\n            this.session = session;\n            this.commitment = new TextDecoder().decode(plaintext);\n        } catch (e) {\n            throw new CryptoError(`${e.name}: ${e.message}`);\n        }\n    }\n\n    createOutboundOLMchannel(\n            account: Account,\n            publicKey: string,\n            otKey: string,\n            commitment: string,\n    ) {\n        try {\n            this.commitment = commitment;\n            this.session = account.create_outbound_session(publicKey, otKey);\n        } catch (e) {\n            throw new CryptoError(`${e.name}: ${e.message}`);\n        }\n    }\n\n    setSecret(sharedSecret: Uint8Array) {\n        this.kemSecret = sharedSecret;\n    }\n\n    isDone(): boolean {\n        return (\n            this.status === PROTOCOL_STATUS.DONE\n            || this.status === PROTOCOL_STATUS.WAITING_DONE\n        );\n    }\n\n    validateStatus(status: ProtocolStatus) {\n        if (this.status !== status)\n            throw new Error(\n                `Protocol status is ${this.status} but expected ${status}.`,\n            );\n    }\n\n    async validateCommitment(key: MediaKeys) {\n        const commitment = await hashKey(key);\n\n        if (this.commitment !== commitment)\n            throw new Error('Keys do not match the commitment.');\n    }\n\n    setStatus(status: ProtocolStatus) {\n        if (this.status === PROTOCOL_STATUS.TERMINATED) {\n            throw new Error('Terminated while processing.');\n        }\n        this.status = status;\n    }\n\n    clearSession() {\n        this.status = PROTOCOL_STATUS.TERMINATED;\n        this.session?.free();\n    }\n\n    setDone() {\n        this.status = PROTOCOL_STATUS.DONE;\n        this.commitment = '';\n        this.kemSecret = new Uint8Array();\n        this.keyToSend = {\n            index: -1,\n            olmKey: new Uint8Array(),\n            pqKey: new Uint8Array(),\n            userID: '',\n        };\n    }\n\n    async keyCommitment(): Promise<string> {\n        return hashKey(this.keyToSend);\n    }\n\n    async createKeyInfoMessage(key: MediaKeys): Promise<KeyInfo> {\n        const ciphertext = this.encryptGivenKeyInfo(key.olmKey, key.index);\n        const cipher = await encryptSymmetrically(\n            this.pqSessionKey,\n            key.pqKey,\n            AUX,\n        );\n        const pqCiphertext = uint8ArrayToBase64(cipher);\n\n        return {\n            ciphertext,\n            pqCiphertext,\n        };\n    }\n\n    encryptKeyCommitment(commitmentToKeys: string): string {\n        try {\n            const ciphertext = this.session.encrypt(\n            new TextEncoder().encode(commitmentToKeys),\n            );\n\n            return ciphertext.ciphertext;\n        } catch (e) {\n            throw new CryptoError(`${e.name}: ${e.message}`);\n        }\n    }\n\n    async encryptKeys(): Promise<{ ciphertext: string; pqCiphertext: string; }> {\n        const ciphertext = this.encryptGivenKeyInfo(\n            this.keyToSend.olmKey,\n            this.keyToSend.index,\n        );\n        const cipher = await encryptSymmetrically(\n            this.pqSessionKey,\n            this.keyToSend.pqKey,\n            AUX,\n        );\n        const pqCiphertext = uint8ArrayToBase64(cipher);\n\n        return { ciphertext, pqCiphertext };\n    }\n\n    async encryptChatKey(chatKeyECC: Uint8Array, chatKeyPQ: Uint8Array): Promise<{ ciphertext: string; pqCiphertext: string; }> {\n        try {\n            const encrypted = this.session.encrypt(chatKeyECC);\n            const ciphertext = encrypted.ciphertext;\n\n            const cipher = await encryptSymmetrically(\n            this.pqSessionKey,\n            chatKeyPQ,\n            AUX_CHAT,\n            );\n            const pqCiphertext = uint8ArrayToBase64(cipher);\n\n            return { ciphertext, pqCiphertext };\n        } catch (e) {\n            throw new CryptoError(`${e.name}: ${e.message}`);\n        }\n    }\n\n    async decryptChatKey(\n            ciphertext: string,\n            pqCiphertext: string,\n    ): Promise<{ keyECC: Uint8Array; keyPQ: Uint8Array; }> {\n        try {\n            const eccKey = this.session.decrypt(NORMAL_MESSAGE, ciphertext);\n            const pqCipher = base64ToUint8Array(pqCiphertext);\n            const pqKey = await decryptSymmetrically(\n            this.pqSessionKey,\n            pqCipher,\n            AUX_CHAT,\n            );\n\n            return { keyECC: eccKey, keyPQ: pqKey };\n        } catch (e) {\n            throw new CryptoError(`${e.name}: ${e.message}`);\n        }\n    }\n\n    async decryptKeys(\n            pId: string,\n            ciphertext: string,\n            pqCiphertext: string,\n    ): Promise<MediaKeys> {\n        try {\n            const result = this.session.decrypt(NORMAL_MESSAGE, ciphertext);\n            const index = result[result.length - 1];\n            const key = result.slice(0, -1);\n            const pqCipher = base64ToUint8Array(pqCiphertext);\n            const pqKey = await decryptSymmetrically(\n            this.pqSessionKey,\n            pqCipher,\n            AUX,\n            );\n            const mediaKey = {\n                index,\n                olmKey: key,\n                pqKey,\n                userID: pId,\n            };\n\n            return mediaKey;\n        } catch (e) {\n            throw new CryptoError(`${e.name}: ${e.message}`);\n        }\n    }\n\n    encryptGivenKeyInfo(key: Uint8Array, index: number): string {\n        try {\n            const message = new Uint8Array(key.length + 1);\n\n            message.set(key, 0);\n            message.set([ index ], key.length);\n            const encrypted = this.session.encrypt(message);\n\n            return encrypted.ciphertext;\n        } catch (e) {\n            throw new CryptoError(`${e.name}: ${e.message}`);\n        }\n    }\n\n    async deriveSharedPQkey(key1: Uint8Array, key2?: Uint8Array) {\n        const secret = key2 || this.kemSecret;\n        const key = deriveSymmetricCryptoKeyFromTwoKeys(\n            key1,\n            secret,\n        );\n\n        this.pqSessionKey = await importSymmetricCryptoKey(key);\n    }\n}\n","import initVodozemac, { Account } from 'vodozemac-wasm';\n\nimport { genSymmetricKey, ratchetMediaKey } from './CryptoUtils';\nimport { SessionData } from './SessionData';\nimport {\n    CryptoError,\n    KeyInfo,\n    MediaKeys,\n    PQsessionAck,\n    PQsessionInit,\n    PROTOCOL_STATUS,\n    SessionInit,\n} from './Types';\nimport { base64ToUint8Array, decapsulateKyber, encapsulateKyber, generateKyberKeys, uint8ArrayToBase64 } from './Utils';\n\n\nexport class OlmAdapter {\n    private _mediaKey: MediaKeys;\n\n    private _publicKyberKey: string = '';\n    private _privateKyberKey: Uint8Array = new Uint8Array();\n    private _olmAccount: Account;\n    private _publicCurve25519Key: string = '';\n    private readonly _olmDataMap: Map<string, SessionData>;\n\n    constructor(id: string) {\n        this._mediaKey = {\n            index: -1,\n            olmKey: new Uint8Array(),\n            pqKey: new Uint8Array(),\n            userID: id,\n        };\n        this._olmDataMap = new Map<string, SessionData>();\n    }\n\n    private _getParticipantOlmData(pId: string): SessionData {\n        if (!this._olmDataMap.has(pId)) {\n            this._olmDataMap.set(pId, new SessionData(this._mediaKey));\n        }\n\n        return this._olmDataMap.get(pId);\n    }\n\n    async init() {\n        await initVodozemac();\n    }\n\n    genMyPublicKeys(): { pk: string; pkKyber: string; } {\n        try {\n            this._olmAccount = new Account();\n            this._publicCurve25519Key = this._olmAccount.curve25519_key;\n\n            const { publicKey, secretKey } = generateKyberKeys();\n            const publicKeyBase64 = uint8ArrayToBase64(publicKey);\n\n            this._publicKyberKey = publicKeyBase64;\n            this._privateKyberKey = secretKey;\n\n            return { pk: this._publicCurve25519Key, pkKyber: publicKeyBase64 };\n        } catch (error) {\n            throw new CryptoError(`${error.name}: ${error.message}`);\n        }\n    }\n\n    generateOneTimeKeys(size: number): string[] {\n        try {\n            this._olmAccount.generate_one_time_keys(size);\n            const keys: string[] = Array.from(\n                this._olmAccount.one_time_keys.values(),\n            );\n\n            return keys;\n        } catch (error) {\n            throw new CryptoError(`${error.name}: ${error.message}`);\n        }\n    }\n\n    ratchetMyKeys(): MediaKeys {\n        const key = ratchetMediaKey(this._mediaKey);\n\n        this._mediaKey = key;\n\n        return key;\n    }\n\n    isSessionDone(pId: string): boolean {\n        const olmData = this._getParticipantOlmData(pId);\n\n        return olmData.isDone();\n    }\n\n    updateMyKeys(): MediaKeys {\n        const newMediaKey = {\n            index: this._mediaKey.index + 1,\n            olmKey: genSymmetricKey(),\n            pqKey: genSymmetricKey(),\n            userID: this._mediaKey.userID,\n        };\n\n        this._mediaKey = newMediaKey;\n\n        return newMediaKey;\n    }\n\n    async encryptCurrentKey(pId: string): Promise<KeyInfo> {\n        try {\n            const olmData = this._getParticipantOlmData(pId);\n\n            olmData.validateStatus(PROTOCOL_STATUS.DONE);\n            const data = await olmData.createKeyInfoMessage(this._mediaKey);\n\n            return data;\n        } catch (error) {\n            throw new CryptoError(`${error.name}: ${error.message}`);\n        }\n    }\n\n    deleteParticipantSession(pId: string) {\n        this._olmDataMap.delete(pId);\n    }\n\n    clearParticipantSession(pId: string) {\n        const olmData = this._getParticipantOlmData(pId);\n\n        olmData.clearSession();\n    }\n\n    async clearMySession() {\n        this._olmAccount?.free();\n        this._olmDataMap.clear();\n    }\n\n    async createPQsessionInitMessage(\n            pId: string,\n            otKey: string,\n            publicKey: string,\n            publicKyberKey: string,\n            commitment: string,\n    ): Promise<PQsessionInit> {\n        try {\n            const olmData = this._getParticipantOlmData(pId);\n\n            olmData.validateStatus(PROTOCOL_STATUS.READY_TO_START);\n\n            olmData.createOutboundOLMchannel(\n                this._olmAccount,\n                publicKey,\n                otKey,\n                commitment,\n            );\n\n            const publicKeyArray = base64ToUint8Array(publicKyberKey);\n            const { cipherText, sharedSecret } = encapsulateKyber(publicKeyArray);\n\n            olmData.setSecret(sharedSecret);\n            const commitmentToKeys = await olmData.keyCommitment();\n            const ciphertext = olmData.encryptKeyCommitment(commitmentToKeys);\n\n            olmData.setStatus(PROTOCOL_STATUS.WAITING_PQ_SESSION_ACK);\n\n            return {\n                ciphertext: ciphertext,\n                encapsKyber: uint8ArrayToBase64(cipherText),\n                publicKey: this._publicCurve25519Key,\n                publicKyberKey: this._publicKyberKey,\n            };\n        } catch (error) {\n            throw new CryptoError(`${error.name}: ${error.message}`);\n        }\n    }\n\n    async createPQsessionAckMessage(\n            pId: string,\n            encapsKyber: string,\n            publicKey: string,\n            publicKyberKey: string,\n            ciphertext: string,\n    ): Promise<PQsessionAck> {\n        try {\n            const olmData = this._getParticipantOlmData(pId);\n\n            olmData.validateStatus(PROTOCOL_STATUS.WAITING_PQ_SESSION_INIT);\n\n            olmData.createInboundOLMchannel(\n                this._olmAccount,\n                publicKey,\n                ciphertext,\n            );\n\n            const decapsArray = base64ToUint8Array(encapsKyber);\n            const decapsulatedSecret = decapsulateKyber(\n                decapsArray,\n                this._privateKyberKey,\n            );\n\n            const publicKeyArray = base64ToUint8Array(publicKyberKey);\n            const { cipherText, sharedSecret }\n                = encapsulateKyber(publicKeyArray);\n            const encapsulatedBase64 = uint8ArrayToBase64(cipherText);\n\n            await olmData.deriveSharedPQkey(sharedSecret, decapsulatedSecret);\n\n            const { ciphertext: olmEncKeyInfo, pqCiphertext: pqEncKeyInfo }\n                = await olmData.encryptKeys();\n\n            olmData.setStatus(PROTOCOL_STATUS.WAITING_SESSION_ACK);\n\n            return {\n                ciphertext: olmEncKeyInfo,\n                encapsKyber: encapsulatedBase64,\n                pqCiphertext: pqEncKeyInfo,\n            };\n        } catch (error) {\n            throw new CryptoError(`${error.name}: ${error.message}`);\n        }\n    }\n\n    async createSessionAckMessage(\n            pId: string,\n            encapsKyber: string,\n            ciphertext: string,\n            pqCiphertext: string,\n    ): Promise<{\n                data: KeyInfo;\n                key: MediaKeys;\n            }> {\n        try {\n            const olmData = this._getParticipantOlmData(pId);\n\n            olmData.validateStatus(PROTOCOL_STATUS.WAITING_PQ_SESSION_ACK);\n\n            const decapsArray = base64ToUint8Array(encapsKyber);\n            const decapsulatedSecret = decapsulateKyber(\n                decapsArray,\n                this._privateKyberKey,\n            );\n\n            await olmData.deriveSharedPQkey(decapsulatedSecret);\n            const key = await olmData.decryptKeys(\n                pId,\n                ciphertext,\n                pqCiphertext,\n            );\n\n            await olmData.validateCommitment(key);\n\n            const {\n                ciphertext: olmCiphertext,\n                pqCiphertext: pqCiphertextBase64,\n            } = await olmData.encryptKeys();\n\n            const data: KeyInfo = {\n                ciphertext: olmCiphertext,\n                pqCiphertext: pqCiphertextBase64,\n            };\n\n            olmData.setStatus(PROTOCOL_STATUS.WAITING_DONE);\n\n            return { data, key };\n        } catch (error) {\n            throw new CryptoError(`${error.name}: ${error.message}`);\n        }\n    }\n\n    async createSessionDoneMessage(\n            pId: string,\n            ciphertext: string,\n            pqCiphertext: string,\n    ): Promise<{\n                key: MediaKeys;\n                keyChanged: boolean;\n            }> {\n        try {\n            const olmData = this._getParticipantOlmData(pId);\n\n            olmData.validateStatus(PROTOCOL_STATUS.WAITING_SESSION_ACK);\n\n            const key = await olmData.decryptKeys(\n                pId,\n                ciphertext,\n                pqCiphertext,\n            );\n\n            await olmData.validateCommitment(key);\n\n            const keyChanged = olmData.indexChanged(this._mediaKey);\n\n            olmData.setDone();\n\n            return { key, keyChanged };\n        } catch (error) {\n            throw new CryptoError(`${error.name}: ${error.message}`);\n        }\n    }\n\n    processSessionDoneMessage(pId: string): boolean {\n        const olmData = this._getParticipantOlmData(pId);\n\n        olmData.validateStatus(PROTOCOL_STATUS.WAITING_DONE);\n        const keyChanged = olmData.indexChanged(this._mediaKey);\n\n        olmData.setDone();\n\n        return keyChanged;\n    }\n\n    async encryptChatKey(\n            pId: string,\n            chatKeyECC: Uint8Array,\n            chatKeyPQ: Uint8Array,\n    ): Promise<KeyInfo> {\n        try {\n            const olmData = this._getParticipantOlmData(pId);\n\n            olmData.validateStatus(PROTOCOL_STATUS.DONE);\n\n            return olmData.encryptChatKey(chatKeyECC, chatKeyPQ);\n        } catch (error) {\n            throw new CryptoError(`${error.name}: ${error.message}`);\n        }\n    }\n\n    async decryptChatKey(\n            pId: string,\n            ciphertext: string,\n            pqCiphertext: string,\n    ): Promise<{ keyECC: Uint8Array; keyPQ: Uint8Array; }> {\n        try {\n            const olmData = this._getParticipantOlmData(pId);\n\n            olmData.validateStatus(PROTOCOL_STATUS.DONE);\n\n            return olmData.decryptChatKey(ciphertext, pqCiphertext);\n        } catch (error) {\n            throw new CryptoError(`${error.name}: ${error.message}`);\n        }\n    }\n\n    async decryptKey(\n            pId: string,\n            ciphertext: string,\n            pqCiphertext: string,\n    ): Promise<MediaKeys> {\n        try {\n            const olmData = this._getParticipantOlmData(pId);\n\n            if (!olmData.isDone()) {\n                throw new Error('Session init is not done yet');\n            }\n\n            return olmData.decryptKeys(pId, ciphertext, pqCiphertext);\n        } catch (error) {\n            throw new CryptoError(`${error.name}: ${error.message}`);\n        }\n    }\n\n    async createSessionInitMessage(\n            pId: string,\n            otKey: string,\n    ): Promise<SessionInit> {\n        const olmData = this._getParticipantOlmData(pId);\n\n        olmData.validateStatus(PROTOCOL_STATUS.READY_TO_START);\n        const commitment = await olmData.keyCommitment();\n\n        olmData.setStatus(PROTOCOL_STATUS.WAITING_PQ_SESSION_INIT);\n\n        return {\n            commitment,\n            otKey,\n            publicKey: this._publicCurve25519Key,\n            publicKyberKey: this._publicKyberKey,\n        };\n    }\n}\n","import { getBitsFromString } from './CryptoUtils';\n\nconst SAS_BYTE_LENGTH = 6;\n\nexport const emojiMapping = [\n    [ '🐶', 'dog' ],\n    [ '🐱', 'cat' ],\n    [ '🦁', 'lion' ],\n    [ '🐎', 'horse' ],\n    [ '🦄', 'unicorn' ],\n    [ '🐷', 'pig' ],\n    [ '🐘', 'elephant' ],\n    [ '🐰', 'rabbit' ],\n    [ '🐼', 'panda' ],\n    [ '🐓', 'rooster' ],\n    [ '🐧', 'penguin' ],\n    [ '🐢', 'turtle' ],\n    [ '🐟', 'fish' ],\n    [ '🐙', 'octopus' ],\n    [ '🦋', 'butterfly' ],\n    [ '🌷', 'flower' ],\n    [ '🌳', 'tree' ],\n    [ '🌵', 'cactus' ],\n    [ '🍄', 'mushroom' ],\n    [ '🌏', 'globe' ],\n    [ '🌙', 'moon' ],\n    [ '☁️', 'cloud' ],\n    [ '🔥', 'fire' ],\n    [ '🍌', 'banana' ],\n    [ '🍎', 'apple' ],\n    [ '🍓', 'strawberry' ],\n    [ '🌽', 'corn' ],\n    [ '🍕', 'pizza' ],\n    [ '🎂', 'cake' ],\n    [ '❤️', 'heart' ],\n    [ '🙂', 'smiley' ],\n    [ '🤖', 'robot' ],\n    [ '🎩', 'hat' ],\n    [ '👓', 'glasses' ],\n    [ '🔧', 'spanner' ],\n    [ '🎅', 'santa' ],\n    [ '👍', 'thumbs up' ],\n    [ '☂️', 'umbrella' ],\n    [ '⌛', 'hourglass' ],\n    [ '⏰', 'clock' ],\n    [ '🎁', 'gift' ],\n    [ '💡', 'light bulb' ],\n    [ '📕', 'book' ],\n    [ '✏️', 'pencil' ],\n    [ '📎', 'paperclip' ],\n    [ '✂️', 'scissors' ],\n    [ '🔒', 'lock' ],\n    [ '🔑', 'key' ],\n    [ '🔨', 'hammer' ],\n    [ '☎️', 'telephone' ],\n    [ '🏁', 'flag' ],\n    [ '🚂', 'train' ],\n    [ '🚲', 'bicycle' ],\n    [ '✈️', 'aeroplane' ],\n    [ '🚀', 'rocket' ],\n    [ '🏆', 'trophy' ],\n    [ '⚽', 'ball' ],\n    [ '🎸', 'guitar' ],\n    [ '🎺', 'trumpet' ],\n    [ '🔔', 'bell' ],\n    [ '⚓️', 'anchor' ],\n    [ '🎧', 'headphones' ],\n    [ '📁', 'folder' ],\n    [ '📌', 'pin' ],\n];\n\n\n/**\n * Generates a SAS composed of emojies.\n * Borrowed from the Matrix JS SDK.\n *\n * @param {string} data - The string from which to generate SAS.\n * @returns {Promise<string[][]>} The SAS emojies.\n */\nexport function generateEmojiSas(data: string): string[][] {\n    const sasBytes = getBitsFromString(SAS_BYTE_LENGTH, data);\n    // Just like base64.\n    const emojis = [\n        sasBytes[0] >> 2,\n        ((sasBytes[0] & 0x3) << 4) | (sasBytes[1] >> 4),\n        ((sasBytes[1] & 0xf) << 2) | (sasBytes[2] >> 6),\n        sasBytes[2] & 0x3f,\n        sasBytes[3] >> 2,\n        ((sasBytes[3] & 0x3) << 4) | (sasBytes[4] >> 4),\n        ((sasBytes[4] & 0xf) << 2) | (sasBytes[5] >> 6),\n    ];\n\n    return emojis.map(num => emojiMapping[num]);\n}\n\n","/// <reference types=\"node\" />\n\nimport JitsiConference from '../../JitsiConference';\nimport { JitsiConferenceEvents } from '../../JitsiConferenceEvents';\nimport JitsiParticipant from '../../JitsiParticipant';\nimport { RTCEvents } from '../../service/RTC/RTCEvents';\nimport JitsiLocalTrack from '../RTC/JitsiLocalTrack';\nimport JitsiTrack from '../RTC/JitsiTrack';\nimport TraceablePeerConnection from '../RTC/TraceablePeerConnection';\nimport browser from '../browser';\nimport Listenable from '../util/Listenable';\nimport JingleSessionPC from '../xmpp/JingleSessionPC';\nimport { FEATURE_E2EE, JITSI_MEET_MUC_TYPE } from '../xmpp/xmpp';\n\nimport { deriveSymmetricCryptoKeyFromTwoKeys, genSymmetricKey, hashChatKeys, hashData } from './CryptoUtils';\nimport E2EEContext from './E2EEContext';\nimport { OlmAdapter } from './OlmAdapter';\nimport { generateEmojiSas } from './SAS';\nimport {\n    CryptoError,\n    MediaKeys,\n    MessageType,\n    OLM_MESSAGE,\n    OLM_MESSAGE_TYPES,\n    ParticipantEvent,\n    ReplyMessage,\n} from './Types';\n\n\nexport const REQ_TIMEOUT = 20 * 1000;\n\nfunction timeout<T>(ms: number): Promise<T> {\n    return new Promise((_, reject) =>\n        setTimeout(() => reject(new Error('Request timed out')), ms),\n    );\n}\n\n/**\n * This module integrates {@link E2EEContext} with {@link OlmAdapter} in order to distribute the keys for encryption.\n */\nexport class ManagedKeyHandler extends Listenable {\n    private chatKeyECC: Uint8Array;\n    private chatKeyPQ: Uint8Array;\n    private askedForChatKey: boolean;\n    private readonly myID: string;\n    private readonly _participantEventQueue: ParticipantEvent[];\n    private _processingEvents: boolean;\n    private readonly _reqs: Map<\n        string,\n        { reject?: (args?: unknown) => void; resolve: (args?: unknown) => void; }\n    >;\n\n    private readonly update: Map<\n        string,\n        { reject?: (args?: unknown) => void; resolve: (args?: unknown) => void; }\n    >;\n\n    max_wait: number;\n    conference: JitsiConference;\n    e2eeCtx: E2EEContext;\n    enabled: boolean;\n    initialized: boolean;\n    initSessions: Promise<unknown[]> | null;\n    _olmAdapter: OlmAdapter;\n    _conferenceJoined: boolean;\n\n    onUserJoined: ((id: string) => void) | undefined;\n    onUserLeft: ((id: string) => void) | undefined;\n    onEndpointMessageReceived: ((participant: JitsiParticipant, payload: any) => void) | undefined;\n    onConferenceJoined: (() => void) | undefined;\n    onConferenceLeft: (() => void) | undefined;\n    onMediaSessionStarted: ((session: JingleSessionPC) => void) | undefined;\n    onTrackAdded: ((track: JitsiTrack) => void) | undefined;\n    onRemoteTrackAdded: ((track: JitsiLocalTrack, tpc: TraceablePeerConnection) => void) | undefined;\n    onTrackMuteChanged: ((track: JitsiLocalTrack) => void) | undefined;\n    onSasUpdated: ((sasStr: string) => void) | undefined;\n\n    /**\n     * Build a new AutomaticKeyHandler instance, which will be used in a given conference.\n     */\n    constructor(conference: JitsiConference) {\n        super();\n        this.initialized = false;\n        this.max_wait = REQ_TIMEOUT;\n        this.conference = conference;\n        this.myID = conference.myUserId() || '';\n        this.e2eeCtx = new E2EEContext();\n        this._reqs = new Map();\n        this.update = new Map();\n        this.chatKeyECC = new Uint8Array();\n        this.chatKeyPQ = new Uint8Array();\n        this.askedForChatKey = false;\n\n        this.enabled = false;\n        this._participantEventQueue = [];\n        this._processingEvents = false;\n        this.initSessions = null;\n\n        this.onUserJoined = this._onParticipantJoined.bind(this);\n        this.onUserLeft = this._onParticipantLeft.bind(this);\n        this.onEndpointMessageReceived = this._onEndpointMessageReceived.bind(this);\n        this.onConferenceLeft = this._onConferenceLeft.bind(this);\n        this.onConferenceJoined = () => this._conferenceJoined = true;\n        this.onMediaSessionStarted = this._onMediaSessionStarted.bind(this);\n        this.onTrackAdded = this._onTrackAddedHandler.bind(this);\n        this.onRemoteTrackAdded = this._setupReceiverE2EEForTrack.bind(this);\n        this.onTrackMuteChanged = this._trackMuteChanged.bind(this);\n        this.onSasUpdated = this.sasUpdatedHandler.bind(this);\n\n        this.conference.on(\n            JitsiConferenceEvents.USER_JOINED,\n            this.onUserJoined,\n        );\n        this.conference.on(\n            JitsiConferenceEvents.USER_LEFT,\n            this.onUserLeft,\n        );\n        this.conference.on(\n            JitsiConferenceEvents.ENDPOINT_MESSAGE_RECEIVED,\n            this.onEndpointMessageReceived,\n        );\n        this.conference.on(\n            JitsiConferenceEvents.CONFERENCE_LEFT,\n            this.onConferenceLeft,\n        );\n        this.conference.on(\n            JitsiConferenceEvents.CONFERENCE_JOINED,\n            this.onConferenceJoined\n        );\n        this.conference.on(\n            JitsiConferenceEvents._MEDIA_SESSION_STARTED,\n            this.onMediaSessionStarted,\n        );\n        this.conference.on(\n            JitsiConferenceEvents.TRACK_ADDED,\n            this.onTrackAdded,\n        );\n        this.conference.rtc?.on(\n            RTCEvents.REMOTE_TRACK_ADDED,\n            this.onRemoteTrackAdded,\n        );\n        this.conference.on(\n            JitsiConferenceEvents.TRACK_MUTE_CHANGED,\n            this.onTrackMuteChanged,\n        );\n\n        this._conferenceJoined = false;\n\n        this._olmAdapter = new OlmAdapter(this.myID);\n\n        this.e2eeCtx.on('sasUpdated', this.onSasUpdated);\n    }\n\n    private _onTrackAddedHandler = (track: JitsiTrack) => {\n        if (track.isLocal()) {\n            this._onLocalTrackAdded(track as JitsiLocalTrack);\n        }\n    };\n\n    private sasUpdatedHandler = (sasStr: string) => {\n        const sas = generateEmojiSas(sasStr);\n\n        this.log('info', `Emitting SAS: ${sas.join(', ')}`);\n        this.conference.eventEmitter.emit(\n        JitsiConferenceEvents.E2EE_SAS_AVAILABLE,\n        sas,\n        );\n    };\n\n    private async init() {\n        await this._olmAdapter.init();\n        this.initialized = true;\n    }\n\n    /**\n     * Setup E2EE on the new track that has been added to the conference, apply it on all the open peerconnections.\n     * @param {JitsiLocalTrack} track - the new track that's being added to the conference.\n     * @private\n     */\n    private _onLocalTrackAdded(track: JitsiLocalTrack) {\n        for (const session of this.conference.getMediaSessions()) {\n            this._setupSenderE2EEForTrack(session, track);\n        }\n    }\n\n    /**\n     * Setups E2E encryption for the new session.\n     * @param {JingleSessionPC} session - the new media session.\n     * @private\n     */\n    private _onMediaSessionStarted(session: JingleSessionPC) {\n        const localTracks = this.conference.getLocalTracks();\n\n        for (const track of localTracks) {\n            this._setupSenderE2EEForTrack(session, track);\n        }\n    }\n\n    private updateMyKeys() {\n        const { olmKey, pqKey, index } = this._olmAdapter.updateMyKeys();\n\n        this.setKey(olmKey, pqKey, index);\n    }\n\n    private async createKeyUpdatePromise(pId: string) {\n        const promise = new Promise((resolve, reject) => {\n            this.update.set(pId, { reject, resolve });\n        });\n\n        return Promise.race([ promise, timeout(this.max_wait) ]);\n    }\n\n    private async createSessionPromise(pId: string) {\n        const promise = new Promise((resolve, reject) => {\n            this._reqs.set(pId, { reject, resolve });\n        });\n\n        return Promise.race([ promise, timeout(this.max_wait) ]);\n    }\n\n    private resolveSessionPromise(pId: string) {\n        const promise = this._reqs.get(pId);\n\n        if (promise) {\n            promise.resolve();\n            this._reqs.delete(pId);\n        }\n    }\n\n    private resolveAllSessionPromises() {\n        for (const promise of this.update.values()) {\n            promise?.resolve();\n        }\n        this._reqs.clear();\n    }\n\n    private resolveKeyUpdatePromise(pID: string) {\n        const requestPromise = this.update.get(pID);\n\n        if (requestPromise) {\n            requestPromise.resolve();\n            this.update.delete(pID);\n        } else\n            this.log(\n                'warn',\n                `Trying to resolve non-esistant key update with ${pID}.`,\n            );\n    }\n\n    /**\n     * Setup E2EE for the receiving side.\n     *\n     * @private\n     */\n    private _setupReceiverE2EEForTrack(\n            track: JitsiLocalTrack,\n            tpc: TraceablePeerConnection,\n    ) {\n        if (!this.enabled) {\n            return;\n        }\n\n        const receiver = tpc.findReceiverForTrack(track.track);\n\n        if (receiver) {\n            this.e2eeCtx.handleReceiver(\n                receiver,\n                track.getParticipantId(),\n            );\n        } else {\n            this.log(\n                'warn',\n                `Could not handle E2EE for ${track}: receiver not found in: ${tpc}`,\n            );\n        }\n    }\n\n    /**\n     * Setup E2EE for the sending side.\n     *\n     * @param {JingleSessionPC} session - the session which sends the media produced by the track.\n     * @param {JitsiLocalTrack} track - the local track for which e2e encoder will be configured.\n     * @private\n     */\n    private _setupSenderE2EEForTrack(session: JingleSessionPC, track: JitsiLocalTrack) {\n        if (!this.enabled) {\n            return;\n        }\n\n        const pc = session.peerconnection;\n        const sender = pc?.findSenderForTrack(track.track);\n\n        if (sender) {\n            this.e2eeCtx.handleSender(\n                sender,\n                track.getParticipantId(),\n            );\n        } else {\n            this.log(\n                'warn',\n                `Could not handle E2EE for ${track}: sender not found in ${pc}`,\n            );\n        }\n    }\n\n    /**\n     * Setup E2EE on the sender that is created for the unmuted local video track.\n     * @param {JitsiLocalTrack} track - the track for which muted status has changed.\n     * @private\n     */\n    private _trackMuteChanged(track: JitsiLocalTrack) {\n        if (\n            browser.doesVideoMuteByStreamRemove()\n            && track.isLocal()\n            && track.isVideoTrack()\n            && !track.isMuted()\n        ) {\n            for (const session of this.conference.getMediaSessions()) {\n                this._setupSenderE2EEForTrack(session, track);\n            }\n        }\n    }\n\n    /**\n     * Advances (using ratcheting) the current key when a new participant joins the conference.\n     *\n     * @private\n     */\n    private async _handleParticipantJoined(id: string) {\n        this.log('info', `Participant ${id} joined the conference.`);\n        if (!this._conferenceJoined || !this.enabled) return;\n        if (!this.initialized) {\n            await this.init();\n        }\n        const participants = this.conference.getParticipants();\n        const { olmKey, pqKey, index } = this._olmAdapter.ratchetMyKeys();\n\n        this.setKey(olmKey, pqKey, index);\n        for (const participant of participants) {\n            const pId = participant.getId();\n\n            if (this._olmAdapter.isSessionDone(pId)) {\n                this.log('info', `Ratchted keys of user ${pId}.`);\n                this.e2eeCtx.ratchetKeys(pId);\n            }\n        }\n    }\n\n    /**\n     * Rotates the current key when a participant leaves the conference.\n     * @private\n     */\n    private async _handleParticipantLeft(id: string) {\n        this.log('info', `Participant ${id} left the conference.`);\n\n        if (!this.enabled) return;\n        if (!this.initialized) {\n            await this.init();\n        }\n\n        this.resolveSessionPromise(id);\n        if (this.update.get(id)) this.resolveKeyUpdatePromise(id);\n        this.updateMyKeys();\n        const participants = this.conference.getParticipants();\n        const updateBatch = participants.map(async participant => {\n            const pId = participant.getId();\n\n            try {\n                if (this._olmAdapter.isSessionDone(pId)) {\n                    this.log('info', `Sending key update to ${pId}.`);\n                    const result = this.createKeyUpdatePromise(pId);\n                    const data = await this._olmAdapter.encryptCurrentKey(pId);\n\n                    this._sendMessage(OLM_MESSAGE_TYPES.KEY_UPDATE, data, pId);\n                    this.log(\n                        'info',\n                        `Key update with ${pId} finished successfully.`,\n                    );\n\n                    return await result;\n                }\n            } catch (error) {\n                this.log(\n                    'warn',\n                    `Key update request timed out for ${pId}: ${error}`,\n                );\n                this.log('info', 'Explicitly requesting new current key.');\n                try {\n                    const result = this.createKeyUpdatePromise(pId);\n\n                    this._sendMessage(\n                        OLM_MESSAGE_TYPES.KEY_UPDATE_REQ,\n                        'update',\n                        pId,\n                    );\n                    this.log(\n                        'info',\n                        `Key update with ${pId} finished successfully.`,\n                    );\n\n                    return await result;\n                } catch (err) {\n                    this.log(\n                        'error',\n                        `Explicit key update request timed out for ${pId}: ${err}`,\n                    );\n                }\n            }\n        });\n\n        await Promise.allSettled(updateBatch);\n    }\n\n    private clearAllSessions() {\n        this.resolveAllSessionPromises();\n        const participants = this.conference.getParticipants();\n\n        for (const participant of participants) {\n            this._olmAdapter.deleteParticipantSession(participant.getId());\n        }\n    }\n\n    private _onConferenceLeft() {\n        this._conferenceJoined = false;\n        this.dispose();\n    }\n\n    private async updateKey(pId: string, ciphertext: string, pqCiphertext: string) {\n        try {\n            const key = await this._olmAdapter.decryptKey(\n                pId,\n                ciphertext,\n                pqCiphertext,\n            );\n\n            this.updateParticipantKey(pId, key);\n        } catch (error) {\n            throw new Error(\n                `updateParticipantKey failed for participant ${pId}: ${error}`,\n            );\n        }\n    }\n\n    private isThisParticipantFirst(pId: string): boolean {\n        const localParticipantId = this.myID;\n        const participants = this.conference.getParticipants();\n        const list = participants.filter(\n            participant =>\n                (participant.hasFeature(FEATURE_E2EE)\n                || participant.getProperty('e2ee.enabled') === 'true')\n                && localParticipantId > participant.getId(),\n        ).sort((a, b) => a.getId().localeCompare(b.getId()));\n\n        if (list.length === 0) return false;\n        const firstParticipant = list[0].getId();\n\n        return firstParticipant === pId;\n    }\n\n    private async _onEndpointMessageReceived(participant: JitsiParticipant, payload) {\n        try {\n            if (\n                !payload.olm\n                || payload[JITSI_MEET_MUC_TYPE] !== OLM_MESSAGE\n            ) {\n                this.log('error', 'Incorrect payload');\n\n                return;\n            }\n            if (!this.initialized) {\n                throw new Error('Not initialized');\n            }\n\n            const msg = payload.olm;\n            const pId = participant.getId();\n\n            switch (msg.type) {\n            case OLM_MESSAGE_TYPES.SESSION_INIT: {\n                this.log('info', `Got session-init from ${pId}.`);\n                const { otKey, publicKey, publicKyberKey, commitment }\n                        = msg.data;\n                const data\n                        = await this._olmAdapter.createPQsessionInitMessage(\n                            pId,\n                            otKey,\n                            publicKey,\n                            publicKyberKey,\n                            commitment,\n                        );\n\n                this.setKeyCommitment(pId, publicKey, publicKyberKey);\n                this._sendMessage(\n                        OLM_MESSAGE_TYPES.PQ_SESSION_INIT,\n                        data,\n                        pId,\n                );\n                break;\n            }\n\n            case OLM_MESSAGE_TYPES.PQ_SESSION_INIT: {\n                this.log('info', `Got pq-session-init from ${pId}.`);\n                const {\n                    encapsKyber,\n                    publicKey,\n                    publicKyberKey,\n                    ciphertext,\n                } = msg.data;\n                const data\n                        = await this._olmAdapter.createPQsessionAckMessage(\n                            pId,\n                            encapsKyber,\n                            publicKey,\n                            publicKyberKey,\n                            ciphertext,\n                        );\n\n                this.setKeyCommitment(pId, publicKey, publicKyberKey);\n                this._sendMessage(\n                        OLM_MESSAGE_TYPES.PQ_SESSION_ACK,\n                        data,\n                        pId,\n                );\n                break;\n            }\n            case OLM_MESSAGE_TYPES.PQ_SESSION_ACK: {\n                this.log('info', `Got pq-session-ack from ${pId}.`);\n                const { encapsKyber, ciphertext, pqCiphertext } = msg.data;\n\n                const { data, key }\n                        = await this._olmAdapter.createSessionAckMessage(\n                            pId,\n                            encapsKyber,\n                            ciphertext,\n                            pqCiphertext,\n                        );\n\n                this.updateParticipantKey(pId, key);\n                this._sendMessage(OLM_MESSAGE_TYPES.SESSION_ACK, data, pId);\n                break;\n            }\n            case OLM_MESSAGE_TYPES.SESSION_ACK: {\n                this.log('info', `Got session-ack from ${pId}.`);\n                const { ciphertext, pqCiphertext } = msg.data;\n                const { keyChanged, key }\n                        = await this._olmAdapter.createSessionDoneMessage(\n                            pId,\n                            ciphertext,\n                            pqCiphertext,\n                        );\n\n                this.updateParticipantKey(pId, key);\n                this._sendMessage(\n                        OLM_MESSAGE_TYPES.SESSION_DONE,\n                        'done',\n                        pId,\n                );\n\n                if (!this.askedForChatKey && this.isThisParticipantFirst(pId)) {\n                    this.log('info', `Requesting chat key from ${pId}.`);\n                    this._sendMessage(\n                        OLM_MESSAGE_TYPES.CHAT_KEY_REQUEST,\n                        'chat',\n                        pId,\n                    );\n                    this.askedForChatKey = true;\n                }\n                if (keyChanged) {\n                    const data\n                            = await this._olmAdapter.encryptCurrentKey(pId);\n\n                    this._sendMessage(\n                            OLM_MESSAGE_TYPES.KEY_INFO,\n                            data,\n                            pId,\n                    );\n                }\n                const requestPromise = this._reqs.get(pId);\n\n                if (requestPromise) {\n                    requestPromise.resolve();\n                    this._reqs.delete(pId);\n                } else {\n                    const user = { name: participant.getDisplayName(), pId };\n\n                    this.conference.eventEmitter.emit(\n                        JitsiConferenceEvents.E2EE_KEY_SYNC_AFTER_TIMEOUT, user);\n                    this.log(\n                            'warn',\n                            `Session with ${pId} (${user.name}) was established after reaching time out.`,\n                    );\n                }\n                break;\n            }\n            case OLM_MESSAGE_TYPES.ERROR: {\n                this.log('error', msg.data.error);\n                break;\n            }\n            case OLM_MESSAGE_TYPES.SESSION_DONE: {\n                this.log('info', `Got session-done from ${pId}.`);\n                const keyChanged\n                        = this._olmAdapter.processSessionDoneMessage(pId);\n\n                if (keyChanged) {\n                    const data\n                            = await this._olmAdapter.encryptCurrentKey(pId);\n\n                    this._sendMessage(\n                            OLM_MESSAGE_TYPES.KEY_INFO,\n                            data,\n                            pId,\n                    );\n                }\n                this.log(\n                        'info',\n                        `Participant ${pId} established E2E channel with us.`,\n                );\n                break;\n            }\n            case OLM_MESSAGE_TYPES.KEY_INFO: {\n                this.log('info', `Got key-info from ${pId}.`);\n                const { ciphertext, pqCiphertext } = msg.data;\n\n                await this.updateKey(pId, ciphertext, pqCiphertext);\n                break;\n            }\n            case OLM_MESSAGE_TYPES.KEY_UPDATE: {\n                this.log('info', `Got key-update from ${pId}.`);\n                const { ciphertext, pqCiphertext } = msg.data;\n\n                await this.updateKey(pId, ciphertext, pqCiphertext);\n                this.resolveKeyUpdatePromise(pId);\n                break;\n            }\n            case OLM_MESSAGE_TYPES.KEY_UPDATE_REQ: {\n                this.log('info', `Got key-update-req from ${pId}.`);\n                const data = await this._olmAdapter.encryptCurrentKey(pId);\n\n                this._sendMessage(OLM_MESSAGE_TYPES.KEY_UPDATE, data, pId);\n                break;\n            }\n            case OLM_MESSAGE_TYPES.CHAT_KEY: {\n                this.log('info', `Got chat key from ${pId}. `);\n                const { ciphertext, pqCiphertext } = msg.data;\n                const { keyECC, keyPQ } = await this._olmAdapter.decryptChatKey(pId, ciphertext, pqCiphertext);\n\n                this.setMyChatKey(keyECC, keyPQ);\n                break;\n            }\n            case OLM_MESSAGE_TYPES.CHAT_KEY_REQUEST: {\n                this.log('info', `Got chat key request from ${pId}.`);\n                const data = await this._olmAdapter.encryptChatKey(pId, this.chatKeyECC, this.chatKeyPQ);\n\n                this._sendMessage(OLM_MESSAGE_TYPES.CHAT_KEY, data, pId);\n                break;\n            }\n            }\n        } catch (error) {\n            this.log('error', `Error while processing message: ${error}`);\n            const user = { name: participant.getDisplayName(), pId: participant.getId() };\n\n            if (error instanceof CryptoError) {\n                this.log('error', `Crypto error occured: ${error}`);\n                this.conference.eventEmitter.emit(\n                JitsiConferenceEvents.E2EE_CRYPTO_FAILED, user);\n                this.log(\n                    'error',\n                    `Processing message from user ID ${user.pId} (${user.name}) failed due to a crypto error: ${error}`,\n                );\n            }\n        }\n    }\n\n    private setKeyCommitment(pId: string, publicKey: string, publicKyberKey: string) {\n        const keyCommitment = hashData([ pId, publicKey, publicKyberKey ]);\n\n        this.e2eeCtx.setKeysCommitment(\n            pId,\n            keyCommitment,\n        );\n    }\n\n    private setMyChatKey(keyECC: Uint8Array, keyPQ: Uint8Array) {\n        const chatKeyHash = hashChatKeys(keyECC, keyPQ);\n\n        this.e2eeCtx.setChatKeyHash(\n            chatKeyHash,\n        );\n        this.chatKeyECC = keyECC;\n        this.chatKeyPQ = keyPQ;\n        const key = deriveSymmetricCryptoKeyFromTwoKeys(keyECC, keyPQ);\n\n        this.conference.eventEmitter.emit(JitsiConferenceEvents.E2EE_CHAT_KEY_RECEIVED, key);\n        this.log('info', 'Set chat key hash and emit key to the ChatRoom module.');\n    }\n\n    /**\n     * Updates a participant's key.\n     *\n     * @param {string} id - The participant ID.\n     * @param {MediaKey} key - The new key of the participant.\n     */\n    private updateParticipantKey(id: string, key: MediaKeys) {\n        this.e2eeCtx.setKey(id, key.olmKey, key.pqKey, key.index);\n    }\n\n    /**\n     * Sends the given object to the given participant ID via XMPP MUC private messages.\n     *\n     * @param {MessageType} type - The message type.\n     * @param {ReplyMessage} data - The message data.\n     * @param {string} participantId - The target participant ID.\n     */\n    private _sendMessage(\n            type: MessageType,\n            data: ReplyMessage | 'update' | 'done' | 'chat',\n            participantId: string,\n    ) {\n        const msg = {\n            [JITSI_MEET_MUC_TYPE]: OLM_MESSAGE,\n            olm: {\n                data,\n                type,\n            },\n        };\n\n        this.conference.sendMessage(msg, participantId);\n    }\n\n    private _queueParticipantEvent(type: 'join' | 'leave', id: string) {\n        this._participantEventQueue.push({\n            id,\n            type,\n\n        });\n\n        if (!this._processingEvents) {\n            this._processParticipantEvents();\n        }\n    }\n\n    private async _processParticipantEvents() {\n        if (this._processingEvents) {\n            return;\n        }\n\n        this._processingEvents = true;\n\n        try {\n            while (this._participantEventQueue.length > 0) {\n                const event = this._participantEventQueue.shift();\n\n                if (event?.type === 'join') {\n                    await this._handleParticipantJoined(event.id);\n                } else if (event?.type === 'leave') {\n                    await this._handleParticipantLeft(event.id);\n                    this.e2eeCtx.cleanup(event.id);\n                }\n            }\n        } finally {\n            this._processingEvents = false;\n        }\n    }\n\n    private log(level: 'info' | 'error' | 'warn', message: string) {\n        console[level](`E2E: User ${this.myID}: ${message}`);\n    }\n\n    _onParticipantJoined(id: string) {\n        this._queueParticipantEvent('join', id);\n    }\n\n    _onParticipantLeft(id: string) {\n        if (this.enabled && this.initialized) {\n            this._olmAdapter.clearParticipantSession(id);\n            if (this.update.get(id)) this.resolveKeyUpdatePromise(id);\n        }\n\n        this._queueParticipantEvent('leave', id);\n    }\n\n    /**\n     * Set the keys of the current participant.\n     * @param {Uint8Array} olmKey - The olm key.\n     * @param {Uint8Array} pqKey - The pq key.\n     * @param {number} index - The keys index.\n     */\n    setKey(olmKey: Uint8Array, pqKey: Uint8Array, index: number) {\n        this.e2eeCtx.setKey(this.myID, olmKey, pqKey, index);\n    }\n\n    /**\n     * Indicates whether E2EE is currently enabled or not.\n     *\n     * @returns {boolean}\n     */\n    isEnabled() {\n        return this.enabled;\n    }\n\n    /**\n     * Enables End-To-End encryption.\n     */\n    async enableE2E() {\n        const localParticipantId = this.myID;\n        const { pkKyber, pk } = this._olmAdapter.genMyPublicKeys();\n\n        this.setKeyCommitment(localParticipantId, pk, pkKyber);\n        this.updateMyKeys();\n\n        const participants = this.conference.getParticipants();\n\n        this.log(\n            'info',\n            `There are following IDs in the meeting: [ ${participants.map(p => `${p.getId()}`).join(', ')}]`,\n        );\n        const list = participants.filter(\n            participant =>\n                (participant.hasFeature(FEATURE_E2EE)\n                || participant.getProperty('e2ee.enabled') === 'true')\n                && localParticipantId > participant.getId(),\n        );\n        const keys = this._olmAdapter.generateOneTimeKeys(list.length);\n\n        this.log(\n            'info',\n            `Should send session-init to IDs: [ ${list.map(p => p.getId())}]`,\n        );\n\n        if (!this.askedForChatKey && list.length === 0) {\n            this.log('info', 'Generated chat keys');\n            const chatKeyECC = genSymmetricKey();\n            const chatKeyPQ = genSymmetricKey();\n\n            this.askedForChatKey = true;\n            this.setMyChatKey(chatKeyECC, chatKeyPQ);\n        }\n\n        this.initSessions = (async () => {\n            const promises = list.map(async participant => {\n                const pId = participant.getId();\n\n                try {\n                    const lastKey = keys.pop();\n\n                    if (!lastKey) throw new Error('No one time keys');\n                    const data\n                        = await this._olmAdapter.createSessionInitMessage(\n                            pId,\n                            lastKey,\n                        );\n\n                    this.log('info', `Sent session-init to participant ${pId}`);\n                    this._sendMessage(\n                        OLM_MESSAGE_TYPES.SESSION_INIT,\n                        data,\n                        pId,\n                    );\n\n                    const result = await this.createSessionPromise(pId);\n\n                    this.log(\n                        'info',\n                        `Session with ${pId} initialized successfully.`,\n                    );\n\n                    return result;\n                } catch (error) {\n                    const user = { name: participant.getDisplayName(), pId };\n\n                    if (error instanceof CryptoError) {\n                        this.log('error', `Crypto error occured: ${error}`);\n                        this.conference.eventEmitter.emit(\n                JitsiConferenceEvents.E2EE_CRYPTO_FAILED, user);\n                        this.log(\n                        'error',\n                        `Session initialization request with user with ID ${pId} (${user.name}) failed due to a crypto error: ${error}`,\n                        );\n                    } else {\n\n                        this.conference.eventEmitter.emit(\n                JitsiConferenceEvents.E2EE_KEY_SYNC_FAILED, user);\n                        this.log(\n                        'error',\n                        `Session initialization request timed out for user with ID ${pId} (${user.name}): ${error}`,\n                        );\n                    }\n                }\n            });\n\n            return Promise.all(promises);\n        })();\n        await this.initSessions;\n    }\n\n    dispose() {\n        this._olmAdapter.clearMySession();\n        this.clearAllSessions();\n        this.conference.off(\n            JitsiConferenceEvents.USER_JOINED,\n            this.onUserJoined,\n        );\n        this.conference.off(\n            JitsiConferenceEvents.USER_LEFT,\n            this.onUserLeft,\n        );\n        this.conference.off(\n            JitsiConferenceEvents.ENDPOINT_MESSAGE_RECEIVED,\n            this.onEndpointMessageReceived,\n        );\n        this.conference.off(\n            JitsiConferenceEvents.CONFERENCE_LEFT,\n            this.onConferenceLeft,\n        );\n        this.conference.off(\n            JitsiConferenceEvents.CONFERENCE_JOINED,\n            this.onConferenceJoined\n        );\n        this.conference.off(\n            JitsiConferenceEvents._MEDIA_SESSION_STARTED,\n            this.onMediaSessionStarted,\n        );\n        this.conference.off(\n            JitsiConferenceEvents.TRACK_ADDED,\n            this.onTrackAdded,\n        );\n        this.conference.rtc?.off(\n            RTCEvents.REMOTE_TRACK_ADDED,\n            this.onRemoteTrackAdded,\n        );\n        this.conference.off(\n            JitsiConferenceEvents.TRACK_MUTE_CHANGED,\n            this.onTrackMuteChanged,\n        );\n        this.e2eeCtx.off('sasUpdated', this.onSasUpdated);\n\n        this.onUserJoined = undefined;\n        this.onUserLeft = undefined;\n        this.onEndpointMessageReceived = undefined;\n        this.onConferenceJoined = undefined;\n        this.onConferenceLeft = undefined;\n        this.onMediaSessionStarted = undefined;\n        this.onTrackAdded = undefined;\n        this.onRemoteTrackAdded = undefined;\n        this.onTrackMuteChanged = undefined;\n        this.onSasUpdated = undefined;\n\n        this.e2eeCtx.dispose();\n        this._reqs.clear();\n        this.update.clear();\n    }\n\n    /**\n     * Disables End-To-End encryption.\n     */\n    async disableE2E() {\n        this.e2eeCtx.cleanupAll();\n        this.clearAllSessions();\n    }\n\n    /**\n     * Enables / disables End-To-End encryption.\n     *\n     * @param {boolean} enabled - whether E2EE should be enabled or not.\n     * @returns {void}\n     */\n    async setEnabled(enabled: boolean) {\n        if (enabled === this.enabled) {\n            return;\n        }\n        this.enabled = enabled;\n\n        if (!this.initialized) {\n            await this.init();\n        }\n\n        if (enabled) {\n            this.log('info', 'Enabling e2ee');\n            await this.enableE2E();\n        }\n\n        if (!enabled) {\n            this.log('info', 'Disabling e2ee');\n            await this.disableE2E();\n        }\n\n        this.conference.setLocalParticipantProperty('e2ee.enabled', enabled.toString());\n        this.conference.restartMediaSessions();\n    }\n\n    async messageReceived(participant: JitsiParticipant, payload) {\n        if (!participant) {\n            this.log('error', 'Got message from an unknown participant');\n\n            return;\n        }\n        this._onEndpointMessageReceived(participant, payload);\n    }\n\n    leaveConference() {\n        this._onConferenceLeft();\n    }\n}\n","import JitsiConference from '../../JitsiConference';\nimport browser from '../browser';\n\nimport { ManagedKeyHandler } from './ManagedKeyHandler';\n\n/**\n * This module integrates {@link ManagedKeyHandler} with {@link JitsiConference} in order to enable E2E encryption.\n */\nexport class E2EEncryption {\n    private readonly _keyHandler: ManagedKeyHandler;\n    /**\n     * A constructor.\n     * @param {JitsiConference} conference - The conference instance for which E2E encryption is to be enabled.\n     */\n    constructor(conference: JitsiConference) {\n        this._keyHandler = new ManagedKeyHandler(conference);\n    }\n\n    /**\n     * Indicates if E2EE is supported in the current platform.\n     *\n     * @param {object} config - Global configuration.\n     * @returns {boolean}\n     */\n    static isSupported(config) {\n        if (config.e2ee?.disabled || config.testing?.disableE2EE) {\n            return false;\n        }\n\n        return (\n            browser.supportsInsertableStreams()\n            || (config.enableEncodedTransformSupport\n                && browser.supportsEncodedTransform())\n        );\n    }\n\n    /**\n     * Indicates whether E2EE is currently enabled or not.\n     *\n     * @returns {boolean}\n     */\n    isEnabled() {\n        return this._keyHandler.isEnabled();\n    }\n\n    dispose() {\n        this._keyHandler.dispose();\n    }\n\n    /**\n     * Enables / disables End-To-End encryption.\n     *\n     * @param {boolean} enabled - whether E2EE should be enabled or not.\n     * @returns {void}\n     */\n    async setEnabled(enabled: boolean): Promise<void> {\n        await this._keyHandler.setEnabled(enabled);\n    }\n\n    /**\n     * Sets keys and index for End-to-End encryption.\n     *\n     * @param {Uint8Array} olmKey - The olm key.\n     * @param {Uint8Array} pqKey - The pq key.\n     * @param {number} index - The index of the encryption key.\n     * @returns {void}\n     */\n    setEncryptionKey(olmKey: Uint8Array, pqKey: Uint8Array, index: number) {\n        this._keyHandler.setKey(olmKey, pqKey, index);\n    }\n}\n","export enum E2ePingEvents {\n\n    /**\n     * Indicates that the end-to-end round-trip-time for a participant has changed.\n     */\n    E2E_RTT_CHANGED = 'e2eping.e2e_rtt_changed'\n}\n","import { getLogger } from '@jitsi/logger';\n\nimport JitsiConference from '../../JitsiConference';\nimport { JitsiConferenceEvents } from '../../JitsiConferenceEvents';\nimport JitsiParticipant from '../../JitsiParticipant';\nimport { E2ePingEvents } from '../../service/e2eping/E2ePingEvents';\n\nconst logger = getLogger('e2eping');\n\n/**\n * The 'type' of a message which designates an e2e ping request.\n * @type {string}\n */\nconst E2E_PING_REQUEST: string = 'e2e-ping-request';\n\n/**\n * The 'type' of a message which designates an e2e ping response.\n * @type {string}\n */\nconst E2E_PING_RESPONSE: string = 'e2e-ping-response';\n\n/**\n * The number of requests to wait for before emitting an RTT value.\n */\nconst DEFAULT_NUM_REQUESTS: number = 5;\n\n/**\n * The maximum number of messages per second to aim for. This is for the entire\n * conference, with the assumption that all endpoints join at once.\n */\nconst DEFAULT_MAX_MESSAGES_PER_SECOND: number = 250;\n\n/**\n * The conference size beyond which e2e pings will be disabled.\n */\nconst DEFAULT_MAX_CONFERENCE_SIZE: number = 200;\n\nexport interface IPingMessage {\n    id: number;\n    type: string;\n}\n\nexport interface IE2ePingOptions {\n    e2eping?: {\n        enabled?: boolean;\n        maxConferenceSize?: number;\n        maxMessagesPerSecond?: number;\n        numRequests?: number;\n    };\n}\n\nexport interface IRequest {\n    id: number;\n    rtt?: number;\n    timeSent: number;\n}\n\n/**\n * Saves e2e ping related state for a single JitsiParticipant.\n */\nclass ParticipantWrapper {\n    participant: JitsiParticipant;\n    e2eping: E2ePing;\n    id: string;\n    requests: { [key: number]: IRequest; };\n    lastRequestId: number;\n    timeout: Nullable<number>;\n\n    /**\n     * Creates a ParticipantWrapper\n     * @param {JitsiParticipant} participant - The remote participant that this\n     * object wraps.\n     * @param {E2ePing} e2eping\n     */\n    constructor(participant: JitsiParticipant, e2eping: E2ePing) {\n        // The JitsiParticipant\n        this.participant = participant;\n\n        // The E2ePing\n        this.e2eping = e2eping;\n\n        // Caches the ID\n        this.id = participant.getId();\n\n        // Recently sent requests\n        this.requests = {};\n\n        // The ID of the last sent request. We just increment it for each new\n        // request. Start at 1 so we can consider only thruthy values valid.\n        this.lastRequestId = 1;\n\n        this.sendRequest = this.sendRequest.bind(this);\n        this.handleResponse = this.handleResponse.bind(this);\n        this.maybeLogRttAndStop = this.maybeLogRttAndStop.bind(this);\n        this.scheduleNext = this.scheduleNext.bind(this);\n        this.stop = this.stop.bind(this);\n        this.getDelay = this.getDelay.bind(this);\n        this.timeout = this.scheduleNext();\n    }\n\n    /**\n     * Schedule the next ping to be sent.\n     */\n    scheduleNext(): number {\n        return window.setTimeout(this.sendRequest, this.getDelay());\n    }\n\n    /**\n     * Stop pinging this participant, canceling a scheduled ping, if any.\n     */\n    stop(): void {\n        if (this.timeout) {\n            window.clearTimeout(this.timeout);\n        }\n        this.e2eping.removeParticipant(this.id);\n    }\n\n    /**\n     * Get the delay until the next ping in milliseconds.\n     */\n    getDelay(): number {\n        const conferenceSize = this.e2eping.conference.getParticipants().length;\n        const endpointPairs = conferenceSize * (conferenceSize - 1) / 2;\n        const totalMessages = endpointPairs * this.e2eping.numRequests;\n        const totalSeconds = totalMessages / this.e2eping.maxMessagesPerSecond;\n\n        // Randomize between .5 and 1.5\n        const r = 1.5 - Math.random();\n        const delayBetweenMessages = r * Math.max(1000 * (totalSeconds / this.e2eping.numRequests), 1000);\n\n        return delayBetweenMessages;\n    }\n\n    /**\n     * Sends the next ping request.\n     * @type {*}\n     */\n    sendRequest(): void {\n        const requestId = this.lastRequestId++;\n        const requestMessage = {\n            id: requestId,\n            type: E2E_PING_REQUEST\n        };\n\n        this.e2eping.sendMessage(requestMessage, this.id);\n        this.requests[requestId] = {\n            id: requestId,\n            timeSent: window.performance.now()\n        };\n    }\n\n    /**\n     * Handles a response from this participant.\n     * @type {*}\n     */\n    handleResponse(response: any): void {\n        const request = this.requests[response.id];\n\n        if (request) {\n            request.rtt = window.performance.now() - request.timeSent;\n        }\n        this.maybeLogRttAndStop();\n    }\n\n    /**\n     * Check if we've received the pre-configured number of responses, and if\n     * so log the measured RTT and stop sending requests.\n     * @type {*}\n     */\n    maybeLogRttAndStop(): void {\n        // The RTT we'll report is the minimum RTT measured\n        let rtt = Infinity;\n        let request: any, requestId: any;\n        let numRequestsWithResponses = 0;\n        let totalNumRequests = 0;\n\n        for (requestId in this.requests) {\n            if (this.requests.hasOwnProperty(requestId)) {\n                request = this.requests[requestId];\n\n                totalNumRequests++;\n                if (request.rtt) {\n                    numRequestsWithResponses++;\n                    rtt = Math.min(rtt, request.rtt);\n                }\n            }\n        }\n\n        if (numRequestsWithResponses >= this.e2eping.numRequests) {\n            logger.info(`Measured RTT=${rtt} ms to ${this.id} (in ${this.participant.getProperty('region')})`);\n            this.stop();\n\n            this.e2eping.conference.eventEmitter.emit(\n                E2ePingEvents.E2E_RTT_CHANGED, this.participant, rtt);\n\n            return;\n        } else if (totalNumRequests > 2 * this.e2eping.numRequests) {\n            logger.info(`Stopping e2eping for ${this.id} because we sent ${totalNumRequests} with only `\n                + `${numRequestsWithResponses} responses.`);\n            this.stop();\n\n            return;\n        }\n\n        this.timeout = this.scheduleNext();\n    }\n}\n\n/**\n * Implements end-to-end ping (from one conference participant to another) via\n * the jitsi-videobridge channel (either WebRTC data channel or web socket).\n *\n * TODO: use a broadcast message instead of individual pings to each remote\n * participant.\n *\n * This class:\n * 1. Sends periodic ping requests to all other participants in the\n * conference.\n * 2. Responds to ping requests from other participants.\n * 3. Fires events with the end-to-end RTT to each participant whenever a\n * response is received.\n * 4. Fires analytics events with the end-to-end RTT periodically.\n */\nexport default class E2ePing {\n\n    conference: JitsiConference;\n    eventEmitter: any;\n    sendMessage: (message: IPingMessage, participantId: string) => void;\n    participants: { [key: string]: ParticipantWrapper; };\n    numRequests: number;\n    maxConferenceSize: number;\n    maxMessagesPerSecond: number;\n\n    /**\n     * @param {JitsiConference} conference - The conference.\n     * @param {Function} sendMessage - The function to use to send a message.\n     * @param {Object} options\n     */\n    constructor(\n            conference: JitsiConference,\n            options: IE2ePingOptions,\n            sendMessage: (message: IPingMessage, participantId: string) => void) {\n        this.conference = conference;\n        this.eventEmitter = conference.eventEmitter;\n        this.sendMessage = sendMessage;\n\n        // Maps a participant ID to its ParticipantWrapper\n        this.participants = {};\n\n        this.numRequests = DEFAULT_NUM_REQUESTS;\n        this.maxConferenceSize = DEFAULT_MAX_CONFERENCE_SIZE;\n        this.maxMessagesPerSecond = DEFAULT_MAX_MESSAGES_PER_SECOND;\n\n        if (options?.e2eping) {\n            if (typeof options.e2eping.numRequests === 'number') {\n                this.numRequests = options.e2eping.numRequests;\n            }\n            if (typeof options.e2eping.maxConferenceSize === 'number') {\n                this.maxConferenceSize = options.e2eping.maxConferenceSize;\n            }\n            if (typeof options.e2eping.maxMessagesPerSecond === 'number') {\n                this.maxMessagesPerSecond = options.e2eping.maxMessagesPerSecond;\n            }\n        }\n        logger.info(\n            `Initializing e2e ping with numRequests=${this.numRequests}, maxConferenceSize=${this.maxConferenceSize}, `\n            + `maxMessagesPerSecond=${this.maxMessagesPerSecond}.`);\n\n        this.participantJoined = this.participantJoined.bind(this);\n\n        this.participantLeft = this.participantLeft.bind(this);\n        conference.on(JitsiConferenceEvents.USER_LEFT, this.participantLeft);\n\n        this.messageReceived = this.messageReceived.bind(this);\n        conference.on(JitsiConferenceEvents.ENDPOINT_MESSAGE_RECEIVED, this.messageReceived);\n\n        this.conferenceJoined = this.conferenceJoined.bind(this);\n        conference.on(JitsiConferenceEvents.CONFERENCE_JOINED, this.conferenceJoined);\n    }\n\n    /**\n     * Delay processing USER_JOINED events until the MUC is fully joined,\n     * otherwise the apparent conference size will be wrong.\n     */\n    conferenceJoined(): void {\n        this.conference.getParticipants().forEach(p => this.participantJoined(p.getId(), p));\n        this.conference.on(JitsiConferenceEvents.USER_JOINED, this.participantJoined);\n    }\n\n    /**\n     * Handles a message that was received.\n     *\n     * @param participant - The message sender.\n     * @param payload - The payload of the message.\n     */\n    messageReceived(participant: JitsiParticipant, payload: IPingMessage): void {\n        // Listen to E2E PING requests and responses from other participants\n        // in the conference.\n        if (payload.type === E2E_PING_REQUEST) {\n            this.handleRequest(participant.getId(), payload);\n        } else if (payload.type === E2E_PING_RESPONSE) {\n            this.handleResponse(participant.getId(), payload);\n        }\n    }\n\n    /**\n     * Handles a participant joining the conference. Starts to send ping\n     * requests to the participant.\n     *\n     * @param {String} id - The ID of the participant.\n     * @param {JitsiParticipant} participant - The participant that joined.\n     */\n    participantJoined(id: string, participant: JitsiParticipant): void {\n        if (this.participants[id]) {\n            logger.info(`Participant wrapper already exists for ${id}. Clearing.`);\n            this.participants[id].stop();\n        }\n\n        if (this.conference.getParticipants().length > this.maxConferenceSize) {\n            return;\n        }\n\n        // We don't need to send e2eping in both directions for a pair of\n        // endpoints. Force only one direction with just string comparison of\n        // the IDs.\n        if (this.conference.myUserId() > id) {\n            logger.info(`Starting e2eping for participant ${id}`);\n            this.participants[id] = new ParticipantWrapper(participant, this);\n        }\n    }\n\n    /**\n     * Remove a participant without calling \"stop\".\n     */\n    removeParticipant(id: string): void {\n        if (this.participants[id]) {\n            delete this.participants[id];\n        }\n    }\n\n    /**\n     * Handles a participant leaving the conference. Stops sending requests.\n     *\n     * @param {String} id - The ID of the participant.\n     */\n    participantLeft(id: string): void {\n        if (this.participants[id]) {\n            this.participants[id].stop();\n            delete this.participants[id];\n        }\n    }\n\n    /**\n     * Handles a ping request coming from another participant.\n     *\n     * @param {string} participantId - The ID of the participant who sent the\n     * request.\n     * @param {Object} request - The request.\n     */\n    handleRequest(participantId: string, request: { id: number; }): void {\n        // If it's a valid request, just send a response.\n        if (request?.id) {\n            const response = {\n                id: request.id,\n                type: E2E_PING_RESPONSE\n            };\n\n            this.sendMessage(response, participantId);\n        } else {\n            logger.info(`Received an invalid e2e ping request from ${participantId}.`);\n        }\n    }\n\n    /**\n     * Handles a ping response coming from another participant\n     * @param {string} participantId - The ID of the participant who sent the\n     * response.\n     * @param {Object} response - The response.\n     */\n    handleResponse(participantId: string, response: { id: number; }): void {\n        const participantWrapper = this.participants[participantId];\n\n        if (participantWrapper) {\n            participantWrapper.handleResponse(response);\n        }\n    }\n\n    /**\n     * Stops this E2ePing (i.e. stop sending requests).\n     */\n    stop(): void {\n        logger.info('Stopping e2eping');\n\n        this.conference.off(JitsiConferenceEvents.USER_JOINED, this.participantJoined);\n        this.conference.off(JitsiConferenceEvents.USER_LEFT, this.participantLeft);\n        this.conference.off(JitsiConferenceEvents.ENDPOINT_MESSAGE_RECEIVED, this.messageReceived);\n\n        for (const id in this.participants) {\n            if (this.participants.hasOwnProperty(id)) {\n                this.participants[id].stop();\n            }\n        }\n\n        this.participants = {};\n    }\n}\n","import { getLogger } from '@jitsi/logger';\n\nimport JitsiConference from '../../JitsiConference';\nimport { RTCEvents } from '../../service/RTC/RTCEvents';\nimport JitsiRemoteTrack from '../RTC/JitsiRemoteTrack';\nimport TraceablePeerConnection from '../RTC/TraceablePeerConnection';\nimport FeatureFlags from '../flags/FeatureFlags';\n\n// Flag to set on receivers to avoid setting up the lite mode\n// more than once.\nconst kJitsiLiteMode = Symbol('kJitsiLiteMode');\n\nconst logger = getLogger('testing:LiteModeContext');\n\n/**\n * This module implements a discard-all insertable stream.  Use to reduce decoder CPU load for testing.\n */\nexport class LiteModeContext {\n    private enabled: boolean;\n\n    /**\n     * A constructor.\n     * @param {JitsiConference} conference - The conference instance for which lite mode is to be enabled.\n     */\n    constructor(conference: JitsiConference) {\n        this.enabled = FeatureFlags.isRunInLiteModeEnabled();\n        if (!this.enabled) {\n            return;\n        }\n\n        conference.rtc.on(\n            RTCEvents.REMOTE_TRACK_ADDED,\n            (track: JitsiRemoteTrack, tpc: TraceablePeerConnection) => this._setupLiteModeForTrack(tpc, track));\n    }\n\n    /**\n     * Setup Lite Mode for a track.\n     *\n     * @private\n     */\n    private _setupLiteModeForTrack(tpc: TraceablePeerConnection, track: JitsiRemoteTrack): void {\n        if (!this.enabled) {\n            return;\n        }\n\n        const receiver = tpc.findReceiverForTrack(track.getTrack());\n\n        if (!receiver) {\n            logger.warn(`Could not set up lite mode for ${track}: receiver not found in: ${tpc}`);\n\n            return;\n        }\n\n        if (receiver[kJitsiLiteMode]) {\n            return;\n        }\n        receiver[kJitsiLiteMode] = true;\n\n        const receiverStreams = receiver.createEncodedStreams();\n\n        const transformStream = new TransformStream({\n            transform: () => {\n                // Don't call controller.enqueue(encodedFrame), and so drop everything\n            }\n        });\n\n        receiverStreams.readable.pipeThrough(transformStream).pipeTo(receiverStreams.writable);\n    }\n}\n","import { getLogger } from '@jitsi/logger';\n\nimport JitsiConference from '../../JitsiConference';\nimport { CodecMimeType } from '../../service/RTC/CodecMimeType';\nimport { MediaType } from '../../service/RTC/MediaType';\nimport { VIDEO_CODECS_BY_COMPLEXITY } from '../../service/RTC/StandardVideoQualitySettings';\nimport { VideoType } from '../../service/RTC/VideoType';\nimport JitsiLocalTrack from '../RTC/JitsiLocalTrack';\nimport browser from '../browser';\nimport JingleSessionPC from '../xmpp/JingleSessionPC';\n\nconst logger = getLogger('qc:CodecSelection');\n\n// Default video codec preferences on mobile and desktop endpoints.\nconst DESKTOP_VIDEO_CODEC_ORDER = [ CodecMimeType.AV1, CodecMimeType.VP9, CodecMimeType.VP8, CodecMimeType.H264 ];\nconst MOBILE_P2P_VIDEO_CODEC_ORDER = [ CodecMimeType.H264, CodecMimeType.VP8, CodecMimeType.VP9, CodecMimeType.AV1 ];\nconst MOBILE_VIDEO_CODEC_ORDER = [ CodecMimeType.VP8, CodecMimeType.VP9, CodecMimeType.H264, CodecMimeType.AV1 ];\n\nexport interface ICodecSelectionOptions {\n    [connectionType: string]: {\n        disabledCodec?: string;\n        enableAV1ForFF?: boolean;\n        preferenceOrder?: string[];\n        preferredCodec?: string;\n        screenshareCodec?: string;\n    };\n}\n\nexport type CodecPreferenceOrder = { [connectionType: string]: string[]; };\nexport type ScreenshareCodec = { [connectionType: string]: string; };\n\n/**\n * This class handles the codec selection mechanism for the conference based on the config.js settings.\n * The preferred codec is selected based on the settings and the list of codecs supported by the browser.\n * The preferred codec is published in presence which is then used by the other endpoints in the\n * conference to pick a supported codec at join time and when the call transitions between p2p and jvb\n * connections.\n */\nexport class CodecSelection {\n    private codecPreferenceOrder: CodecPreferenceOrder;\n    private conference: JitsiConference;\n    private encodeTimeStats: Map<string, unknown>;\n    private options: ICodecSelectionOptions;\n    private screenshareCodec: ScreenshareCodec;\n    private visitorCodecs: string[];\n\n    /**\n     * Creates a new instance for a given conference.\n     *\n     * @param {JitsiConference} conference the conference instance\n     * @param {*} options\n     * @param {string} options.jvb settings (codec list, preferred and disabled) for the jvb connection.\n     * @param {string} options.p2p settings (codec list, preferred and disabled) for the p2p connection.\n     */\n    constructor(conference: JitsiConference, options: ICodecSelectionOptions) {\n        this.codecPreferenceOrder = {};\n        this.conference = conference;\n        this.encodeTimeStats = new Map();\n        this.options = options;\n        this.screenshareCodec = {};\n        this.visitorCodecs = [];\n\n        for (const connectionType of Object.keys(options)) {\n            let { disabledCodec, preferredCodec, preferenceOrder } = options[connectionType];\n            const { enableAV1ForFF = false, screenshareCodec } = options[connectionType];\n            const supportedCodecs = new Set(this._getSupportedVideoCodecs(connectionType));\n\n            // Default preference codec order when no codec preferences are set in config.js\n            let selectedOrder = Array.from(supportedCodecs);\n\n            if (preferenceOrder) {\n                preferenceOrder = preferenceOrder.map(codec => codec.toLowerCase());\n\n                // Select all codecs that are supported by the browser.\n                selectedOrder = preferenceOrder.filter(codec => supportedCodecs.has(codec));\n\n            // Generate the codec list based on the supported codecs and the preferred/disabled (deprecated) settings\n            } else if (preferredCodec || disabledCodec) {\n                disabledCodec = disabledCodec?.toLowerCase();\n                preferredCodec = preferredCodec?.toLowerCase();\n\n                // VP8 cannot be disabled since it the default codec.\n                if (disabledCodec && disabledCodec !== CodecMimeType.VP8) {\n                    selectedOrder = selectedOrder.filter(codec => codec !== disabledCodec);\n                }\n\n                const index = selectedOrder.findIndex(codec => codec === preferredCodec);\n\n                // Move the preferred codec to the top of the list.\n                if (preferredCodec && index !== -1) {\n                    selectedOrder.splice(index, 1);\n                    selectedOrder.unshift(preferredCodec);\n                }\n            }\n\n            // Push AV1 and VP9 to the end of the list if they are supported by the browser but has implementation bugs\n            // For example, 136 and newer versions of Firefox supports AV1 but only simulcast and not SVC. Even with\n            // simulcast, temporal scalability is not supported. This way Firefox will continue to decode AV1 from\n            // other endpoints but will use VP8 for encoding. Similar issues exist with VP9 on Safari and Firefox.\n            const isVp9EncodeSupported = browser.supportsVP9() || (browser.isWebKitBased() && connectionType === 'p2p');\n\n            [ CodecMimeType.AV1, CodecMimeType.VP9 ].forEach(codec => {\n                if ((codec === CodecMimeType.AV1 && browser.isFirefox() && !enableAV1ForFF)\n                    || (codec === CodecMimeType.VP9 && !isVp9EncodeSupported)) {\n                    const index = selectedOrder.findIndex(selectedCodec => selectedCodec === codec);\n\n                    if (index !== -1) {\n                        selectedOrder.splice(index, 1);\n\n                        selectedOrder.push(codec);\n                    }\n                }\n            });\n\n            // Safari retports AV1 as supported on M3+ macs. Because of some decoder/encoder issues reported AV1 should\n            // be disabled until all issues are resolved.\n            if (browser.isWebKitBased()) {\n                selectedOrder = selectedOrder.filter(codec => codec !== CodecMimeType.AV1);\n            }\n\n            logger.info(`Codec preference order for ${connectionType} connection is ${selectedOrder}`);\n            this.codecPreferenceOrder[connectionType] = selectedOrder;\n\n            // Set the preferred screenshare codec.\n            if (screenshareCodec && supportedCodecs.has(screenshareCodec.toLowerCase())) {\n                this.screenshareCodec[connectionType] = screenshareCodec.toLowerCase();\n            }\n        }\n    }\n\n    /**\n     * Returns a list of video codecs that are supported by the browser.\n     *\n     * @param {string} connectionType - media connection type, p2p or jvb.\n     * @returns {Array}\n     */\n    _getSupportedVideoCodecs(connectionType: string): string[] {\n        const videoCodecMimeTypes = browser.isMobileDevice() && connectionType === 'p2p'\n            ? MOBILE_P2P_VIDEO_CODEC_ORDER\n            : browser.isMobileDevice() ? MOBILE_VIDEO_CODEC_ORDER : DESKTOP_VIDEO_CODEC_ORDER;\n\n        const supportedCodecs = videoCodecMimeTypes.filter(codec =>\n            (window.RTCRtpReceiver?.getCapabilities?.(MediaType.VIDEO)?.codecs ?? [])\n                .some(supportedCodec => supportedCodec.mimeType.toLowerCase() === `${MediaType.VIDEO}/${codec}`));\n\n        // Select VP8 as the default codec if RTCRtpReceiver.getCapabilities() is not supported by the browser or if it\n        // returns an empty set.\n        !supportedCodecs.length && supportedCodecs.push(CodecMimeType.VP8);\n\n        return supportedCodecs;\n    }\n\n    /**\n     * Returns the current codec preference order for the given connection type.\n     *\n     * @param {String} connectionType The media connection type, 'p2p' or 'jvb'.\n     * @returns {Array<string>}\n     */\n    getCodecPreferenceList(connectionType: string): string[] {\n        return this.codecPreferenceOrder[connectionType];\n    }\n\n    /**\n     * Returns the preferred screenshare codec for the given connection type.\n     *\n     * @param {Optional} connectionType The media connection type, 'p2p' or 'jvb'.\n     * @returns CodecMimeType\n     */\n    getScreenshareCodec(connectionType: string): Optional<string> {\n        return this.screenshareCodec[connectionType];\n    }\n\n    /**\n     * Sets the codec on the media session based on the codec preference order configured in config.js and the supported\n     * codecs published by the remote participants in their presence.\n     *\n     * @param {JingleSessionPC} mediaSession session for which the codec selection has to be made.\n     */\n    selectPreferredCodec(mediaSession?: JingleSessionPC): void {\n        const session = mediaSession ? mediaSession : this.conference.jvbJingleSession;\n\n        if (!session) {\n            return;\n        }\n\n        let localPreferredCodecOrder = this.codecPreferenceOrder.jvb;\n\n        // E2EE is curently supported only for VP8 codec.\n        if (this.conference.isE2EEEnabled()) {\n            localPreferredCodecOrder = [ CodecMimeType.VP8 ];\n        }\n\n        const remoteParticipants = this.conference.getParticipants().map(participant => participant.getId());\n        const remoteCodecsPerParticipant = remoteParticipants?.map(remote => {\n            const peerMediaInfo = session._signalingLayer.getPeerMediaInfo(remote, MediaType.VIDEO);\n\n            if (peerMediaInfo?.codecList) {\n                return peerMediaInfo.codecList;\n            } else if (peerMediaInfo?.codecType) {\n                return [ peerMediaInfo.codecType ];\n            }\n\n            return [];\n        }) ?? [];\n\n        // Include the visitor codecs.\n        this.visitorCodecs.length && remoteCodecsPerParticipant.push(this.visitorCodecs);\n\n        const selectedCodecOrder = localPreferredCodecOrder.reduce<CodecMimeType[]>((acc, localCodec) => {\n            let codecNotSupportedByRemote = false;\n\n            // Remove any codecs that are not supported by any of the remote endpoints. The order of the supported\n            // codecs locally however will remain the same since we want to support asymmetric codecs.\n            for (const remoteCodecs of remoteCodecsPerParticipant) {\n                // Ignore remote participants that do not publish codec preference in presence (transcriber).\n                if (remoteCodecs.length) {\n                    codecNotSupportedByRemote = codecNotSupportedByRemote\n                    || !remoteCodecs.find(participantCodec => participantCodec === localCodec);\n                }\n            }\n            if (!codecNotSupportedByRemote) {\n                acc.push(localCodec as CodecMimeType);\n            }\n\n            return acc;\n        }, []);\n\n        if (!selectedCodecOrder.length) {\n            logger.warn('Invalid codec list generated because of a user joining/leaving the call');\n\n            return;\n        }\n\n        session.setVideoCodecs(selectedCodecOrder, this.screenshareCodec?.jvb as CodecMimeType);\n    }\n\n    /**\n     * Changes the codec preference order.\n     *\n     * @param {JitsiLocalTrack} localTrack - The local video track.\n     * @param {CodecMimeType} codec - The codec used for encoding the given local video track.\n     * @returns boolean - Returns true if the codec order has been updated, false otherwise.\n     */\n    changeCodecPreferenceOrder(localTrack: JitsiLocalTrack, codec: string): boolean {\n        const session = this.conference.getActiveMediaSession();\n        const connectionType = session.isP2P ? 'p2p' : 'jvb';\n        const codecOrder = this.codecPreferenceOrder[connectionType];\n        const videoType = localTrack.getVideoType();\n        const codecsByVideoType = VIDEO_CODECS_BY_COMPLEXITY[videoType]\n            .filter(val => Boolean(codecOrder.find(supportedCodec => supportedCodec === val)));\n        const codecIndex = codecsByVideoType.findIndex(val => val === codec.toLowerCase());\n\n        // Do nothing if we are using the lowest complexity codec already.\n        if (codecIndex === codecsByVideoType.length - 1) {\n            return false;\n        }\n\n        const newCodec = codecsByVideoType[codecIndex + 1];\n\n        if (videoType === VideoType.CAMERA) {\n            const idx = codecOrder.findIndex(val => val === newCodec);\n\n            codecOrder.splice(idx, 1);\n            codecOrder.unshift(newCodec);\n            logger.info(`QualityController - switching camera codec to ${newCodec} because of cpu restriction`);\n        } else {\n            this.screenshareCodec[connectionType] = newCodec;\n            logger.info(`QualityController - switching screenshare codec to ${newCodec} because of cpu restriction`);\n        }\n\n        this.selectPreferredCodec(session);\n\n        return true;\n    }\n\n    /**\n     * Updates the aggregate list of the codecs supported by all the visitors in the call and calculates the\n     * selected codec if needed.\n     * @param {Array} codecList - visitor codecs.\n     * @returns {void}\n     */\n    updateVisitorCodecs(codecList: string[]): void {\n        if (this.visitorCodecs === codecList) {\n            return;\n        }\n\n        this.visitorCodecs = codecList;\n        this.selectPreferredCodec();\n    }\n}\n","/**\n * Enum representing the audio subscription options for remote audio streams. Retained for backwards\n * compatibility: {@link normalizeReceiverAudioSubscription} maps the legacy { mode, list } message to the\n * current {@link IReceiverAudioSubscriptionMessage} shape.\n */\nexport enum ReceiverAudioSubscription {\n    /**\n     * Subscribe to all remote audio streams signaled in the conference.\n     */\n    ALL = 'All',\n\n    /**\n     * Subscribe to all remote audio streams except the explicitly excluded ones.\n     */\n    EXCLUDE = 'Exclude',\n\n    /**\n     * Subscribe only to the explicitly included remote audio streams.\n     */\n    INCLUDE = 'Include',\n\n    /**\n     * Do not subscribe to any remote audio streams.\n     */\n    NONE = 'None'\n}\n\n/**\n * Message describing which remote audio streams the local endpoint wants the Jitsi Videobridge to forward.\n * The three fields combine rather than being mutually exclusive: `all` is the baseline (forward every regular\n * source); `include` adds extra sources on top (e.g. bridge-injected translated audio that `all` never\n * delivers); `exclude` drops specific sources. See the bridge's route-loudest configuration at\n * https://github.com/jitsi/jitsi-videobridge/blob/master/jvb/src/main/resources/reference.conf\n */\nexport interface IReceiverAudioSubscriptionMessage {\n    /**\n     * Whether to subscribe to every regular remote audio source (the baseline). Defaults to true; set to\n     * false to receive only the explicitly included sources (or nothing when `include` is empty).\n     */\n    all?: boolean;\n\n    /**\n     * Source names to drop from the subscription. Defaults to an empty list.\n     */\n    exclude?: string[];\n\n    /**\n     * Source names to additionally forward on top of the baseline (e.g. opt-in/translated sources that are\n     * not delivered by `all`). Defaults to an empty list.\n     */\n    include?: string[];\n}\n\n/**\n * Legacy audio-subscription message shape (pre `{ all, include, exclude }`). Still accepted by\n * {@link JitsiConference.setAudioSubscriptionMode} and normalised via {@link normalizeReceiverAudioSubscription}.\n */\nexport interface ILegacyReceiverAudioSubscriptionMessage {\n    /**\n     * Source names for the INCLUDE/EXCLUDE modes.\n     */\n    list?: string[];\n\n    /**\n     * The subscription mode.\n     */\n    mode: ReceiverAudioSubscription;\n}\n\n/**\n * Normalises a legacy { mode, list } message to the { all, include, exclude } shape, or returns an\n * already-current message with its fields defaulted.\n *\n * @param {IReceiverAudioSubscriptionMessage | ILegacyReceiverAudioSubscriptionMessage} message - The message.\n * @returns {IReceiverAudioSubscriptionMessage} The normalised subscription.\n */\nexport function normalizeReceiverAudioSubscription(\n        message: IReceiverAudioSubscriptionMessage | ILegacyReceiverAudioSubscriptionMessage\n): IReceiverAudioSubscriptionMessage {\n    if ('mode' in message) {\n        const list = message.list ?? [];\n\n        switch (message.mode) {\n        case ReceiverAudioSubscription.NONE:\n            return { all: false, exclude: [], include: [] };\n        case ReceiverAudioSubscription.INCLUDE:\n            return { all: false, exclude: [], include: list };\n        case ReceiverAudioSubscription.EXCLUDE:\n            return { all: true, exclude: list, include: [] };\n        default:\n            return { all: true, exclude: [], include: [] };\n        }\n    }\n\n    return {\n        all: message.all ?? true,\n        exclude: message.exclude ?? [],\n        include: message.include ?? []\n    };\n}\n","\nimport { getLogger } from '@jitsi/logger';\nimport { isEqual } from 'lodash-es';\n\nimport JitsiConference from '../../JitsiConference';\nimport {\n    ILegacyReceiverAudioSubscriptionMessage,\n    IReceiverAudioSubscriptionMessage,\n    normalizeReceiverAudioSubscription\n} from '../../service/RTC/ReceiverAudioSubscription';\nimport RTC from '../RTC/RTC';\n\nconst logger = getLogger('qc:ReceiveAudioController');\n\n/**\n * Controller for the local endpoint's remote-audio subscription. The subscription sent to the bridge combines\n * three dimensions: `all` (the baseline — forward every regular source), `include` (extra opt-in sources on\n * top, e.g. bridge-injected translated audio) and `exclude` (sources to drop). The default is `all: true`.\n */\nexport class ReceiverAudioController {\n    private _rtc: RTC;\n\n    /**\n     * Whether the baseline subscription to every regular remote source is active. Defaults to true.\n     */\n    private _all: boolean;\n\n    /**\n     * Source names dropped from the subscription.\n     */\n    private _exclude: string[];\n\n    /**\n     * Source names additionally forwarded on top of the baseline (e.g. translated sources).\n     */\n    private _include: string[];\n\n    /**\n     * Creates a new instance of the ReceiverAudioController.\n     */\n    constructor(conference: JitsiConference) {\n        this._rtc = conference.rtc;\n        this._all = true;\n        this._exclude = [];\n        this._include = [];\n    }\n\n    /**\n     * Gets the current audio subscription.\n     *\n     * @returns {IReceiverAudioSubscriptionMessage} The current audio subscription.\n     */\n    get audioSubscription(): IReceiverAudioSubscriptionMessage {\n        return {\n            all: this._all,\n            exclude: [ ...this._exclude ],\n            include: [ ...this._include ]\n        };\n    }\n\n    /**\n     * Sends the current subscription to the bridge.\n     *\n     * @returns {void}\n     */\n    private _send(): void {\n        this._rtc.sendReceiverAudioSubscriptionMessage({\n            all: this._all,\n            exclude: this._exclude,\n            include: this._include\n        });\n    }\n\n    /**\n     * Mutes or unmutes all remote audio by toggling the baseline. The explicit include/exclude overlays (e.g.\n     * opted-in translated sources) are preserved so they are restored on unmute rather than lost across the cycle.\n     *\n     * @param {boolean} muted - Indicates whether the remote audio should be muted.\n     * @returns {void}\n     */\n    muteRemoteAudio(muted: boolean): void {\n        this.setAudioSubscriptionMode({\n            all: !muted,\n            exclude: this._exclude,\n            include: this._include\n        });\n    }\n\n    /**\n     * Re-sends the current audio subscription to the bridge. Used when the bridge channel (re)opens so the\n     * bridge always learns the receiver's subscription (the default { all: true } until includes are added).\n     *\n     * @returns {void}\n     */\n    resendSubscription(): void {\n        this._send();\n    }\n\n    /**\n     * Replaces the set of additionally-included sources (e.g. translated sources), preserving the `all`\n     * baseline and any excludes.\n     *\n     * @param {Array<string>} include - The full set of source names to include on top of the baseline.\n     * @returns {void}\n     */\n    setIncludeSources(include: string[]): void {\n        this.setAudioSubscriptionMode({\n            all: this._all,\n            exclude: this._exclude,\n            include\n        });\n    }\n\n    /**\n     * Sets the full audio subscription (all / include / exclude). No-op when nothing changed. Also accepts the\n     * legacy { mode, list } message for backwards compatibility, normalising it to the current shape.\n     *\n     * @param {IReceiverAudioSubscriptionMessage | ILegacyReceiverAudioSubscriptionMessage} message - The\n     * subscription to apply.\n     * @returns {void}\n     */\n    setAudioSubscriptionMode(\n            message: IReceiverAudioSubscriptionMessage | ILegacyReceiverAudioSubscriptionMessage): void {\n        const { all, exclude, include } = normalizeReceiverAudioSubscription(message);\n\n        if (this._all === all && isEqual(this._exclude, exclude) && isEqual(this._include, include)) {\n            logger.debug('Ignoring ReceiverAudioSubscription, no change needed.');\n\n            return;\n        }\n\n        this._all = all;\n        this._exclude = exclude;\n        this._include = include;\n        this._send();\n    }\n\n}\n","import { getLogger } from '@jitsi/logger';\nimport { isEqual } from 'lodash-es';\n\nimport JitsiConference from '../../JitsiConference';\nimport { MediaType } from '../../service/RTC/MediaType';\nimport { ASSUMED_BANDWIDTH_BPS, LAST_N_UNLIMITED } from '../../service/RTC/StandardVideoQualitySettings';\nimport RTC from '../RTC/RTC';\nimport JingleSessionPC from '../xmpp/JingleSessionPC';\n\nconst logger = getLogger('qc:ReceiveVideoController');\nconst MAX_HEIGHT = 720;\n\nexport interface IReceiverVideoConstraint {\n    maxHeight: number;\n}\n\nexport interface IReceiverVideoConstraints {\n    assumedBandwidthBps?: number;\n    constraints?: { [sourceName: string]: IReceiverVideoConstraint; };\n    defaultConstraints?: IReceiverVideoConstraint;\n    lastN?: number;\n}\n\n/**\n * This class manages the receive video contraints for a given {@link JitsiConference}. These constraints are\n * determined by the application based on how the remote video streams need to be displayed. This class is responsible\n * for communicating these constraints to the bridge over the bridge channel.\n */\nexport default class ReceiveVideoController {\n    private _conference: JitsiConference;\n    private _rtc: RTC;\n    private _lastN: number;\n    private _maxFrameHeight: number;\n    /**\n     * The map that holds the max frame height requested per remote source for p2p connection.\n     *\n     * @type Map<string, number>\n     */\n    private _sourceReceiverConstraints: Map<string, number>;\n    /**\n     * The number of bps requested from the bridge.\n     */\n    private _assumedBandwidthBps: number;\n    private _lastNLimitedByCpu: boolean;\n    private _receiveResolutionLimitedByCpu: boolean;\n    private _receiverVideoConstraints: IReceiverVideoConstraints;\n\n    /**\n     * Creates a new instance for a given conference.\n     *\n     * @param {JitsiConference} conference the conference instance for which the new instance will be managing\n     * the receive video quality constraints.\n     */\n    constructor(conference: JitsiConference) {\n        this._conference = conference;\n        this._rtc = conference.rtc;\n        const { config } = conference.options;\n\n        // The number of videos requested from the bridge, -1 represents unlimited or all available videos.\n        this._lastN = config?.startLastN ?? config?.channelLastN ?? LAST_N_UNLIMITED;\n\n        // The number representing the maximum video height the local client should receive from the bridge.\n        this._maxFrameHeight = MAX_HEIGHT;\n\n        /**\n         * The map that holds the max frame height requested per remote source for p2p connection.\n         *\n         * @type Map<string, number>\n         */\n        this._sourceReceiverConstraints = new Map();\n\n        /**\n         * The number of bps requested from the bridge.\n         */\n        this._assumedBandwidthBps = ASSUMED_BANDWIDTH_BPS;\n\n        this._lastNLimitedByCpu = false;\n        this._receiveResolutionLimitedByCpu = false;\n\n        // The default receiver video constraints.\n        this._receiverVideoConstraints = {\n            assumedBandwidthBps: this._assumedBandwidthBps,\n            lastN: this._lastN\n        };\n    }\n\n    /**\n     * Returns a map of all the remote source names and the corresponding max frame heights.\n     *\n     * @param {JingleSessionPC} mediaSession - the media session.\n     * @param {number} maxFrameHeight - the height to be requested for remote sources.\n     * @returns\n     */\n    _getDefaultSourceReceiverConstraints(\n            mediaSession: JingleSessionPC,\n            maxFrameHeight?: number\n    ): Map<string, number> {\n        const height = maxFrameHeight ?? MAX_HEIGHT;\n        const remoteVideoTracks = mediaSession.peerconnection?.getRemoteTracks(null, MediaType.VIDEO) || [];\n        const receiverConstraints = new Map<string, number>();\n\n        for (const track of remoteVideoTracks) {\n            receiverConstraints.set(track.getSourceName(), height);\n        }\n\n        return receiverConstraints;\n    }\n\n    /**\n     * Updates the source based constraints based on the maxHeight set.\n     *\n     * @param {number} maxFrameHeight - the height to be requested for remote sources.\n     * @returns {void}\n     */\n    _updateIndividualConstraints(maxFrameHeight?: number): void {\n        const individualConstraints = this._receiverVideoConstraints.constraints;\n\n        if (individualConstraints && Object.keys(individualConstraints).length) {\n            for (const value of Object.values(individualConstraints)) {\n                value.maxHeight = maxFrameHeight ?? Math.min(value.maxHeight, this._maxFrameHeight);\n            }\n        } else {\n            this._receiverVideoConstraints.defaultConstraints = { 'maxHeight': this._maxFrameHeight };\n        }\n    }\n\n    /**\n     * Returns the last set of receiver constraints that were set on the bridge channel.\n     *\n     * @returns {IReceiverVideoConstraints}\n     */\n    getCurrentReceiverConstraints(): IReceiverVideoConstraints {\n        return this._receiverVideoConstraints;\n    }\n\n    /**\n     * Returns the lastN value for the conference.\n     *\n     * @returns {number}\n     */\n    getLastN(): number {\n        return this._lastN;\n    }\n\n    /**\n     * Checks whether last-n was lowered because of a cpu limitation.\n     *\n     * @returns {boolean}\n     */\n    isLastNLimitedByCpu(): boolean {\n        return this._lastNLimitedByCpu;\n    }\n\n    /**\n     * Handles the {@link JitsiConferenceEvents.MEDIA_SESSION_STARTED}, that is when the conference creates new media\n     * session. The preferred receive frameHeight is applied on the media session.\n     *\n     * @param {JingleSessionPC} mediaSession - the started media session.\n     * @returns {void}\n     */\n    onMediaSessionStarted(mediaSession: JingleSessionPC): void {\n        if (mediaSession.isP2P) {\n            mediaSession.setReceiverVideoConstraint(this._getDefaultSourceReceiverConstraints(mediaSession));\n        } else {\n            this._rtc.setReceiverVideoConstraints(this._receiverVideoConstraints);\n        }\n    }\n\n    /**\n     * Sets the assumed bandwidth bps the local participant should receive from remote participants.\n     *\n     * @param {number|undefined} assumedBandwidthBps - the new value.\n     * @returns {void}\n     */\n    setAssumedBandwidthBps(assumedBandwidthBps?: number): void {\n        if (this._receiverVideoConstraints.assumedBandwidthBps !== assumedBandwidthBps) {\n            this._receiverVideoConstraints.assumedBandwidthBps = assumedBandwidthBps;\n            this._rtc.setReceiverVideoConstraints(this._receiverVideoConstraints);\n        }\n    }\n\n    /**\n     * Selects a new value for \"lastN\". The requested amount of videos are going to be delivered after the value is\n     * in effect. Set to -1 for unlimited or all available videos.\n     *\n     * @param {number} value the new value for lastN.\n     * @returns {void}\n     */\n    setLastN(value: number): void {\n        if (this._lastN !== value) {\n            this._lastN = value;\n            this._receiverVideoConstraints.lastN = value;\n            this._rtc.setReceiverVideoConstraints(this._receiverVideoConstraints);\n        }\n    }\n\n    /**\n     * Updates the lastNLimitedByCpu field.\n     *\n     * @param {boolean} enabled\n     * @returns {void}\n     */\n    setLastNLimitedByCpu(enabled: boolean): void {\n        if (this._lastNLimitedByCpu !== enabled) {\n            this._lastNLimitedByCpu = enabled;\n            logger.info(`ReceiveVideoController - Setting the lastNLimitedByCpu flag to ${enabled}`);\n        }\n    }\n\n    /**\n     * Sets the maximum video resolution the local participant should receive from remote participants.\n     *\n     * @param {number|undefined} maxFrameHeight - the new value.\n     * @returns {void}\n     */\n    setPreferredReceiveMaxFrameHeight(maxFrameHeight?: number): void {\n        this._maxFrameHeight = maxFrameHeight;\n\n        for (const session of this._conference.getMediaSessions()) {\n            if (session.isP2P) {\n                session.setReceiverVideoConstraint(this._getDefaultSourceReceiverConstraints(session, maxFrameHeight));\n            } else {\n                this._updateIndividualConstraints(maxFrameHeight);\n                this._rtc.setReceiverVideoConstraints(this._receiverVideoConstraints);\n            }\n        }\n    }\n\n    /**\n     * Sets the receiver constraints for the conference.\n     *\n     * @param {IReceiverVideoConstraints} constraints The video constraints.\n     */\n    setReceiverConstraints(constraints: IReceiverVideoConstraints): void {\n        if (!constraints) {\n            return;\n        }\n\n        const constraintsChanged = !isEqual(this._receiverVideoConstraints, constraints);\n\n        if (constraintsChanged || this._lastNLimitedByCpu || this._receiveResolutionLimitedByCpu) {\n            this._receiverVideoConstraints = constraints;\n\n            this._assumedBandwidthBps = constraints.assumedBandwidthBps ?? this._assumedBandwidthBps;\n            this._lastN = typeof constraints.lastN !== 'undefined' && !this._lastNLimitedByCpu\n                ? constraints.lastN : this._lastN;\n            this._receiverVideoConstraints.lastN = this._lastN;\n            this._receiveResolutionLimitedByCpu && this._updateIndividualConstraints();\n\n            // Send the constraints on the bridge channel.\n            this._rtc.setReceiverVideoConstraints(this._receiverVideoConstraints);\n\n            const p2pSession = this._conference.getMediaSessions().find(session => session.isP2P);\n\n            if (!p2pSession || !this._receiverVideoConstraints.constraints) {\n                return;\n            }\n\n            const mappedConstraints: [string, number][] = Array.from(Object.entries(this._receiverVideoConstraints.constraints))\n                .map(([ key, value ]) => [ key, value.maxHeight ]);\n\n            this._sourceReceiverConstraints = new Map(mappedConstraints);\n\n            // Send the receiver constraints to the peer through a \"content-modify\" message.\n            p2pSession.setReceiverVideoConstraint(this._sourceReceiverConstraints);\n        }\n    }\n\n    /**\n     * Updates the receivedResolutioLimitedByCpu field.\n     *\n     * @param {boolean} enabled\n     * @return {void}\n     */\n    setReceiveResolutionLimitedByCpu(enabled: boolean): void {\n        if (this._receiveResolutionLimitedByCpu !== enabled) {\n            this._receiveResolutionLimitedByCpu = enabled;\n            logger.info(`ReceiveVideoController - Setting the receiveResolutionLimitedByCpu flag to ${enabled}`);\n        }\n    }\n}\n","import { getLogger } from '@jitsi/logger';\n\nimport JitsiConference from '../../JitsiConference';\nimport JingleSessionPC from '../xmpp/JingleSessionPC';\nimport { MediaSessionEvents } from '../xmpp/MediaSessionEvents';\n\nconst logger = getLogger('qc:SendVideoController');\nconst MAX_LOCAL_RESOLUTION = 2160;\n\nexport interface IVideoConstraint {\n    maxHeight: number;\n    sourceName: string;\n}\n\n/**\n * The class manages send video constraints across media sessions({@link JingleSessionPC}) which belong to\n * {@link JitsiConference}. It finds the lowest common value, between the local user's send preference and\n * the remote party's receive preference. Also this module will consider only the active session's receive value,\n * because local tracks are shared and while JVB may have no preference, the remote p2p may have and they may be totally\n * different.\n */\nexport default class SendVideoController {\n    private _conference: JitsiConference;\n    private _preferredSendMaxFrameHeight: number;\n\n    /**\n     * Per-session source-name sender constraints. WeakMap so ended sessions are released by the GC without\n     * explicit cleanup. Keyed by session, value is a map of sourceName -> maxHeight.\n     */\n    private _sessionSenderConstraints: WeakMap<JingleSessionPC, Map<string, number>>;\n\n    /**\n     * Creates new instance for a given conference.\n     *\n     * @param {JitsiConference} conference - the conference instance for which the new instance will be managing\n     * the send video quality constraints.\n     */\n    constructor(conference: JitsiConference) {\n        this._conference = conference;\n        this._preferredSendMaxFrameHeight = MAX_LOCAL_RESOLUTION;\n        this._sessionSenderConstraints = new WeakMap();\n    }\n\n    /**\n     * Returns the constraint map for the currently active session, or undefined when there is no active session.\n     *\n     * @returns {Map<string, number> | undefined}\n     * @private\n     */\n    private _activeSessionMap(): Map<string, number> | undefined {\n        const activeSession = this._conference.getActiveMediaSession();\n\n        return activeSession ? this._sessionSenderConstraints.get(activeSession) : undefined;\n    }\n\n    /**\n     * Figures out the send video constraint as specified by {@link _selectSendMaxFrameHeight} and sets it on all media\n     * sessions for the reasons mentioned in this class description.\n     *\n     * @param {string} sourceName - The source for which sender constraints have changed.\n     * @returns {Promise<void>}\n     * @private\n     */\n    async _propagateSendMaxFrameHeight(sourceName: string): Promise<void> {\n        if (!sourceName) {\n            throw new Error('sourceName missing for calculating the sendMaxHeight for video tracks');\n        }\n        const sendMaxFrameHeight = this._selectSendMaxFrameHeight(sourceName);\n        const promises = [];\n\n        if (sendMaxFrameHeight !== undefined && sendMaxFrameHeight >= 0) {\n            for (const session of this._conference.getMediaSessions()) {\n                promises.push(session.setSenderVideoConstraint(sendMaxFrameHeight, sourceName));\n            }\n        }\n\n        await Promise.all(promises);\n    }\n\n    /**\n     * Selects the lowest common value for the local video send constraint by looking at local user's preference and\n     * the active media session's receive preference set by the remote party.\n     *\n     * @param {string} sourceName - The source for which sender constraints have changed.\n     * @returns {Optional<number>}\n     * @private\n     */\n    _selectSendMaxFrameHeight(sourceName: string): Optional<number> {\n        if (!sourceName) {\n            throw new Error('sourceName missing for calculating the sendMaxHeight for video tracks');\n        }\n        const remoteRecvMaxFrameHeight = this._activeSessionMap()?.get(sourceName);\n\n        if (this._preferredSendMaxFrameHeight >= 0 && remoteRecvMaxFrameHeight !== undefined && remoteRecvMaxFrameHeight >= 0) {\n            return Math.min(this._preferredSendMaxFrameHeight, remoteRecvMaxFrameHeight);\n        } else if (remoteRecvMaxFrameHeight !== undefined && remoteRecvMaxFrameHeight >= 0) {\n            return remoteRecvMaxFrameHeight;\n        }\n\n        return this._preferredSendMaxFrameHeight;\n    }\n\n    /**\n     * Configures the video encodings on the local sources when a media connection is established or becomes active.\n     *\n     * @returns {void}\n     */\n    configureConstraintsForLocalSources(): void {\n        for (const track of this._conference.getLocalVideoTracks()) {\n            const sourceName = track.getSourceName();\n\n            sourceName && this._propagateSendMaxFrameHeight(sourceName);\n        }\n    }\n\n    /**\n     * Handles the {@link JitsiConferenceEvents.MEDIA_SESSION_STARTED}, that is when the conference creates new media\n     * session. It doesn't mean it's already active though. For example the JVB connection may be created after\n     * the conference has entered the p2p mode already.\n     *\n     * @param {JingleSessionPC} mediaSession - the started media session.\n     */\n    onMediaSessionStarted(mediaSession: JingleSessionPC): void {\n        this._sessionSenderConstraints.set(mediaSession, new Map());\n\n        mediaSession.addListener(\n            MediaSessionEvents.REMOTE_SOURCE_CONSTRAINTS_CHANGED,\n            (session: JingleSessionPC, sourceConstraints: Array<IVideoConstraint>) => {\n                if (session !== this._conference.getActiveMediaSession()) {\n                    // Store constraints for inactive sessions so configureConstraintsForLocalSources picks up\n                    // the correct per-session values when this session later becomes active (e.g. JVB -> P2P).\n                    const sessionMap = this._sessionSenderConstraints.get(session);\n\n                    if (sessionMap) {\n                        for (const { sourceName, maxHeight } of sourceConstraints) {\n                            const height = Number(maxHeight);\n\n                            if (!Number.isFinite(height)) {\n                                continue;\n                            }\n                            sessionMap.set(sourceName, height === -1 ? MAX_LOCAL_RESOLUTION : height);\n                        }\n                    }\n                } else {\n                    sourceConstraints.forEach(constraint => this.onSenderConstraintsReceived(constraint));\n                }\n            });\n    }\n\n    /**\n     * Propagates the video constraints if they have changed.\n     *\n     * @param {IVideoConstraint} videoConstraints - The sender video constraints received from the bridge.\n     * @returns {Promise<void>}\n     */\n    async onSenderConstraintsReceived(videoConstraints: IVideoConstraint): Promise<void> {\n        const { maxHeight, sourceName } = videoConstraints;\n        const localVideoTracks = this._conference.getLocalVideoTracks() ?? [];\n        const sessionMap = this._activeSessionMap();\n\n        for (const track of localVideoTracks) {\n            if (track.getSourceName() === sourceName) {\n                const normalizedHeight = maxHeight === -1 ? MAX_LOCAL_RESOLUTION : maxHeight;\n\n                if (sessionMap?.get(sourceName) !== normalizedHeight) {\n                    sessionMap?.set(sourceName, normalizedHeight);\n                    logger.debug(`Sender constraints for source:${sourceName} changed to maxHeight:${maxHeight}`);\n                    await this._propagateSendMaxFrameHeight(sourceName);\n                }\n            }\n        }\n    }\n\n    /**\n     * Sets local preference for max send video frame height.\n     *\n     * @param {number} maxFrameHeight - the new value to set.\n     * @returns {Promise<void>} - resolved when the operation is complete.\n     */\n    async setPreferredSendMaxFrameHeight(maxFrameHeight: number): Promise<void> {\n        this._preferredSendMaxFrameHeight = maxFrameHeight;\n        const promises: Promise<void>[] = [];\n\n        for (const sourceName of (this._activeSessionMap()?.keys() ?? [])) {\n            promises.push(this._propagateSendMaxFrameHeight(sourceName));\n        }\n\n        await Promise.allSettled(promises);\n    }\n}\n","import { getLogger } from '@jitsi/logger';\n\nimport JitsiConference from '../../JitsiConference';\nimport { JitsiConferenceEvents } from '../../JitsiConferenceEvents';\nimport { CodecMimeType } from '../../service/RTC/CodecMimeType';\nimport { RTCEvents } from '../../service/RTC/RTCEvents';\nimport {\n    DEFAULT_LAST_N,\n    LAST_N_UNLIMITED,\n    VIDEO_CODECS_BY_COMPLEXITY,\n    VIDEO_QUALITY_LEVELS\n} from '../../service/RTC/StandardVideoQualitySettings';\nimport { AnalyticsEvents } from '../../service/statistics/AnalyticsEvents';\nimport JitsiLocalTrack from '../RTC/JitsiLocalTrack';\nimport TraceablePeerConnection from '../RTC/TraceablePeerConnection';\nimport RTCStats from '../RTCStats/RTCStats';\nimport { RTCStatsEvents } from '../RTCStats/RTCStatsEvents';\nimport Statistics from '../statistics/statistics';\nimport { isValidNumber } from '../util/MathUtil';\nimport JingleSessionPC from '../xmpp/JingleSessionPC';\n\nimport { CodecSelection } from './CodecSelection';\nimport { ReceiverAudioController } from './ReceiveAudioController';\nimport ReceiveVideoController from './ReceiveVideoController';\nimport SendVideoController, { IVideoConstraint } from './SendVideoController';\n\n\nconst logger = getLogger('qc:QualityController');\n\n// Period for which the client will wait for the cpu limitation flag to be reset in the peerconnection stats before it\n// attempts to rectify the situation by attempting a codec switch.\nconst LIMITED_BY_CPU_TIMEOUT = 60000;\n\n// The min. value that lastN will be set to while trying to fix video quality issues.\nconst MIN_LAST_N = 3;\n\n// Number of consecutive polling cycles (each ~10s) a stream must fail the decoding check before firing the event.\nexport const NOT_DECODING_THRESHOLD_CYCLES = 6;\n\nenum QualityLimitationReason {\n    BANDWIDTH = 'bandwidth',\n    CPU = 'cpu',\n    NONE = 'none'\n}\n\ninterface IResolution {\n    height: number;\n    width: number;\n}\n\ninterface IOutboundRtpStats {\n    codec: CodecMimeType;\n    encodeTime: number;\n    qualityLimitationReason: QualityLimitationReason;\n    resolution: IResolution;\n    timestamp: number;\n}\n\nexport interface ISourceStats {\n    avgEncodeTime: number;\n    codec: CodecMimeType;\n    encodeResolution: number;\n    localTrack: JitsiLocalTrack;\n    qualityLimitationReason: QualityLimitationReason;\n    timestamp: number;\n    tpc: TraceablePeerConnection;\n}\n\ninterface ITrackStats {\n    encodeResolution: number;\n    encodeTime: number;\n    qualityLimitationReason: QualityLimitationReason;\n}\n\nexport interface IInboundVideoStats {\n    bitrateDownload: number;\n    fps: number;\n    participantId: string;\n}\n\ninterface INotDecodingTracker {\n    consecutiveCycles: number;\n    isIssueActive: boolean;\n    participantId: string;\n}\n\n/* eslint-disable require-jsdoc */\nexport class FixedSizeArray {\n    private _data: ISourceStats[];\n    private _maxSize: number;\n\n    constructor(size: number) {\n        this._maxSize = size;\n        this._data = [];\n    }\n\n    add(item: ISourceStats): void {\n        if (this._data.length >= this._maxSize) {\n            this._data.shift();\n        }\n        this._data.push(item);\n    }\n\n    get(index: number): Optional<ISourceStats> {\n        if (index < 0 || index >= this._data.length) {\n            throw new Error('Index out of bounds');\n        }\n\n        return this._data[index];\n    }\n\n    size(): number {\n        return this._data.length;\n    }\n}\n/* eslint-enable require-jsdoc */\n\n/**\n * QualityController class that is responsible for maintaining optimal video quality experience on the local endpoint\n * by controlling the codec, encode resolution and receive resolution of the remote video streams. It also makes\n * adjustments based on the outbound and inbound rtp stream stats reported by the underlying peer connection.\n */\nexport class QualityController {\n    private _audioController: ReceiverAudioController;\n    private _codecController: CodecSelection;\n    private _conference: JitsiConference;\n    private _enableAdaptiveMode: boolean;\n    private _encodeTimeStats: Map<number, FixedSizeArray>;\n    private _isLastNRampupBlocked: boolean;\n    private _lastNRampupTime: number;\n    private _lastNRampupTimeout: Optional<number>;\n    private _limitedByCpuTimeout: Optional<number>;\n    private _notDecodingVideoTracker: Map<number, INotDecodingTracker>;\n    private _receiveVideoController: ReceiveVideoController;\n    private _sendVideoController: SendVideoController;\n    private _timer: Optional<number>;\n\n    /**\n     *\n     * @param {JitsiConference} conference - The JitsiConference instance.\n     * @param {Object} options - video quality settings passed through config.js.\n     */\n    constructor(conference: JitsiConference, options: {\n        enableAdaptiveMode: boolean;\n        jvb: object;\n        lastNRampupTime: number;\n        p2p: object;\n    }) {\n        this._audioController = new ReceiverAudioController(conference);\n        this._conference = conference;\n        const { jvb, p2p } = options;\n\n        this._codecController = new CodecSelection(conference, { jvb,\n            p2p });\n        this._enableAdaptiveMode = options.enableAdaptiveMode ?? true;\n        this._encodeTimeStats = new Map();\n        this._isLastNRampupBlocked = false;\n        this._lastNRampupTime = options.lastNRampupTime;\n        this._notDecodingVideoTracker = new Map();\n        this._receiveVideoController = new ReceiveVideoController(conference);\n        this._sendVideoController = new SendVideoController(conference);\n\n        this._conference.on(\n            JitsiConferenceEvents._MEDIA_SESSION_STARTED,\n            (session: JingleSessionPC) => {\n                this._codecController.selectPreferredCodec(session);\n                this._receiveVideoController.onMediaSessionStarted(session);\n                this._sendVideoController.onMediaSessionStarted(session);\n            });\n        this._conference.on(\n                JitsiConferenceEvents._MEDIA_SESSION_ACTIVE_CHANGED,\n                () => this._sendVideoController.configureConstraintsForLocalSources());\n        this._conference.on(\n            JitsiConferenceEvents.CONFERENCE_VISITOR_CODECS_CHANGED,\n            (codecList: CodecMimeType[]) => this._codecController.updateVisitorCodecs(codecList));\n\n        // Debounce the calls to codec selection when there is a burst of joins and leaves.\n        const debouncedSelectCodec = this._debounce(\n            () => this._codecController.selectPreferredCodec(this._conference.jvbJingleSession),\n            1000);\n\n        this._conference.on(JitsiConferenceEvents.USER_JOINED, debouncedSelectCodec.bind(this));\n        this._conference.on(JitsiConferenceEvents.USER_LEFT, debouncedSelectCodec.bind(this));\n        this._conference.rtc.on(\n            RTCEvents.SENDER_VIDEO_CONSTRAINTS_CHANGED,\n            (videoConstraints: IVideoConstraint) =>\n                this._sendVideoController.onSenderConstraintsReceived(videoConstraints));\n        this._conference.on(\n            JitsiConferenceEvents.ENCODE_TIME_STATS_RECEIVED,\n            (tpc: TraceablePeerConnection, stats: Map<number, IOutboundRtpStats>) =>\n                this._processOutboundRtpStats(tpc, stats));\n        this._conference.on(\n            JitsiConferenceEvents.INBOUND_VIDEO_STATS_RECEIVED,\n            (tpc: TraceablePeerConnection, stats: Map<number, IInboundVideoStats>) =>\n                this._processInboundVideoStats(tpc, stats));\n    }\n\n    /**\n     * Creates a debounced function that delays the execution of the provided function until after the specified delay\n     * has elapsed. Unlike typical debounce implementations, the timer does not reset when the function is called again\n     * within the delay period.\n     *\n     * @param {Function} func - The function to be debounced.\n     * @param {number} delay - The delay in milliseconds.\n     * @returns {Function} - The debounced function.\n     */\n    _debounce(func: Function, delay: number) { // eslint-disable-line @typescript-eslint/no-unsafe-function-type\n        return function(...args: any) {\n            /* eslint-disable @typescript-eslint/no-invalid-this */\n            if (!this._timer) {\n                this._timer = setTimeout(() => {\n                    this._timer = null;\n                    func.apply(this, args);\n                }, delay);\n            }\n            /* eslint-enable @typescript-eslint/no-invalid-this */\n        };\n    }\n\n    /**\n     * Adjusts the lastN value so that fewer remote video sources are received from the bridge in an attempt to improve\n     * encode resolution of the outbound video streams based on cpuLimited parameter passed. If cpuLimited is false,\n     * the lastN value will slowly be ramped back up to the channelLastN value set in config.js.\n     *\n     * @param {boolean} cpuLimited - whether the endpoint is cpu limited or not.\n     * @returns boolean - Returns true if an action was taken, false otherwise.\n     */\n    _lowerOrRaiseLastN(cpuLimited: boolean): boolean {\n        const lastN = this.receiveVideoController.getLastN();\n        let newLastN = lastN;\n\n        if (cpuLimited && (lastN !== LAST_N_UNLIMITED && lastN <= MIN_LAST_N)) {\n            return false;\n        }\n\n        // If channelLastN is not set or set to -1 in config.js, the client will ramp up lastN to only up to 25.\n        let { channelLastN = DEFAULT_LAST_N } = this._conference.options.config;\n\n        channelLastN = channelLastN === LAST_N_UNLIMITED ? DEFAULT_LAST_N : channelLastN;\n        if (cpuLimited) {\n            const videoStreamsReceived = this._conference.getForwardedSources().length;\n\n            newLastN = Math.floor(videoStreamsReceived / 2);\n            if (newLastN < MIN_LAST_N) {\n                newLastN = MIN_LAST_N;\n            }\n\n        // Increment lastN by 1 every LAST_N_RAMPUP_TIME (60) secs.\n        } else if (lastN < channelLastN) {\n            newLastN++;\n        }\n\n        if (newLastN === lastN) {\n            return false;\n        }\n\n        const isStillLimitedByCpu = newLastN < channelLastN;\n\n        this.receiveVideoController.setLastNLimitedByCpu(isStillLimitedByCpu);\n        logger.info(`QualityController - setting lastN=${newLastN}, limitedByCpu=${isStillLimitedByCpu}`);\n        this.receiveVideoController.setLastN(newLastN);\n\n        return true;\n    }\n\n    /**\n     * Adjusts the requested resolution for remote video sources by updating the receiver constraints in an attempt to\n     * improve the encode resolution of the outbound video streams.\n     * @return {void}\n     */\n    _maybeLowerReceiveResolution(): void {\n        const currentConstraints = this.receiveVideoController.getCurrentReceiverConstraints();\n        const individualConstraints = currentConstraints.constraints;\n        let maxHeight = 0;\n\n        if (individualConstraints && Object.keys(individualConstraints).length) {\n            for (const value of Object.values(individualConstraints)) {\n                const v: any = value;\n\n                maxHeight = Math.max(maxHeight, v.maxHeight);\n            }\n        }\n\n        const currentLevel = VIDEO_QUALITY_LEVELS.findIndex(lvl => lvl.height <= maxHeight);\n\n        // Do not lower the resolution to less than 180p.\n        if (VIDEO_QUALITY_LEVELS[currentLevel].height === 180) {\n            return;\n        }\n\n        this.receiveVideoController.setPreferredReceiveMaxFrameHeight(VIDEO_QUALITY_LEVELS[currentLevel + 1].height);\n    }\n\n    /**\n     * Updates the codec preference order for the local endpoint on the active media session and switches the video\n     * codec if needed.\n     *\n     * @param {number} trackId - The track ID of the local video track for which stats have been captured.\n     * @returns {boolean} - Returns true if video codec was changed.\n     */\n    _maybeSwitchVideoCodec(trackId: number): boolean {\n        const stats = this._encodeTimeStats.get(trackId);\n        const { codec, encodeResolution, localTrack } = stats.get(stats.size() - 1);\n        const codecsByVideoType = VIDEO_CODECS_BY_COMPLEXITY[localTrack.getVideoType()];\n        const codecIndex = codecsByVideoType.findIndex(val => val === codec.toLowerCase());\n\n        // Do nothing if the encoder is using the lowest complexity codec already.\n        if (codecIndex === codecsByVideoType.length - 1) {\n            return false;\n        }\n\n        if (!this._limitedByCpuTimeout) {\n            this._limitedByCpuTimeout = window.setTimeout(() => {\n                this._limitedByCpuTimeout = undefined;\n                const updatedStats = this._encodeTimeStats.get(trackId);\n                const latestSourceStats: ISourceStats = updatedStats.get(updatedStats.size() - 1);\n                const expectedSendResolution\n                    = Math.min(localTrack.maxEnabledResolution, localTrack.getCaptureResolution());\n\n                // If the encoder is still limited by CPU, switch to a lower complexity codec.\n                if (latestSourceStats.qualityLimitationReason === QualityLimitationReason.CPU\n                        || encodeResolution < expectedSendResolution) {\n                    return this.codecController.changeCodecPreferenceOrder(localTrack, codec);\n                }\n            }, LIMITED_BY_CPU_TIMEOUT);\n        }\n\n        return false;\n    }\n\n    /**\n     * Adjusts codec, lastN or receive resolution based on the send resolution (of the outbound streams) and limitation\n     * reported by the browser in the WebRTC stats. Recovery is also attempted if the limitation goes away. No action\n     * is taken if the adaptive mode has been disabled through config.js.\n     *\n     * @param {ISourceStats} sourceStats - The outbound-rtp stats for a local video track.\n     * @returns {void}\n     */\n    _performQualityOptimizations(sourceStats: ISourceStats): void {\n        // Do not attempt run time adjustments if the adaptive mode is disabled.\n        if (!this._enableAdaptiveMode) {\n            return;\n        }\n        const { encodeResolution, localTrack, qualityLimitationReason, tpc } = sourceStats;\n\n        // Older browser versions might not report the resolution in the stats.\n        if (!isValidNumber(encodeResolution)) {\n            return;\n        }\n        const trackId = localTrack.rtcId;\n\n        if (encodeResolution === tpc.calculateExpectedSendResolution(localTrack)) {\n            if (this._limitedByCpuTimeout) {\n                window.clearTimeout(this._limitedByCpuTimeout);\n                this._limitedByCpuTimeout = undefined;\n            }\n\n            if (qualityLimitationReason === QualityLimitationReason.NONE\n                && this.receiveVideoController.isLastNLimitedByCpu()) {\n                if (!this._lastNRampupTimeout && !this._isLastNRampupBlocked) {\n                    RTCStats.sendStatsEntry(RTCStatsEvents.ENCODER_CPU_RESTRICTED_EVENT, null, false);\n\n                    // Ramp up the number of received videos if CPU limitation no longer exists. If the cpu\n                    // limitation returns as a consequence, do not attempt to ramp up again, continue to\n                    // increment the lastN value otherwise until it is equal to the channelLastN value.\n                    this._lastNRampupTimeout = window.setTimeout(() => {\n                        this._lastNRampupTimeout = undefined;\n                        const updatedStats = this._encodeTimeStats.get(trackId);\n                        const latestSourceStats: ISourceStats = updatedStats.get(updatedStats.size() - 1);\n\n                        if (latestSourceStats.qualityLimitationReason === QualityLimitationReason.CPU) {\n                            this._isLastNRampupBlocked = true;\n                        } else {\n                            this._lowerOrRaiseLastN(false /* raise */);\n                        }\n                    }, this._lastNRampupTime);\n                }\n            }\n\n            return;\n        }\n\n        // Do nothing if the limitation reason is bandwidth since the browser will dynamically adapt the outbound\n        // resolution based on available uplink bandwith. Otherwise,\n        // 1. Switch the codec to the lowest complexity one incrementally.\n        // 2. Switch to a lower lastN value, cutting the receive videos by half in every iteration until\n        // MIN_LAST_N value is reached.\n        // 3. Lower the receive resolution of individual streams up to 180p.\n        if (qualityLimitationReason === QualityLimitationReason.CPU) {\n            if (this._lastNRampupTimeout) {\n                window.clearTimeout(this._lastNRampupTimeout);\n                this._lastNRampupTimeout = undefined;\n                this._isLastNRampupBlocked = true;\n            }\n            RTCStats.sendStatsEntry(RTCStatsEvents.ENCODER_CPU_RESTRICTED_EVENT, null, true);\n            const codecSwitched = this._maybeSwitchVideoCodec(trackId);\n\n            if (!codecSwitched && !this._limitedByCpuTimeout) {\n                const lastNChanged = this._lowerOrRaiseLastN(true /* lower */);\n\n                if (!lastNChanged) {\n                    this.receiveVideoController.setReceiveResolutionLimitedByCpu(true);\n                    this._maybeLowerReceiveResolution();\n                }\n            }\n        }\n    }\n\n    /**\n     * Processes inbound video stats for remote streams that are receiving bytes but decoding no frames.\n     * Only SSRCs already filtered to the problematic condition (bitrateDownload > 0, fps === 0) are passed in.\n     * Tracks each affected SSRC across consecutive polling cycles and fires RTCStats + Amplitude analytics events\n     * after NOT_DECODING_THRESHOLD_CYCLES consecutive bad cycles. Fires again with stopped=false when resolved.\n     *\n     * @param {TraceablePeerConnection} tpc - The peer connection where stats were captured.\n     * @param {Map<number, IInboundVideoStats>} stats - Per-SSRC stats for streams currently failing the check.\n     * @returns {void}\n     */\n    _processInboundVideoStats(tpc: TraceablePeerConnection, stats: Map<number, IInboundVideoStats>): void {\n        const activeSession = this._conference.getActiveMediaSession();\n\n        if (activeSession?.peerconnection !== tpc) {\n            return;\n        }\n\n        // Advance counters for SSRCs that are still in the problematic state.\n        for (const [ ssrc, { participantId } ] of stats) {\n            const tracker = this._notDecodingVideoTracker.get(ssrc)\n                ?? { consecutiveCycles: 0, isIssueActive: false, participantId };\n\n            tracker.consecutiveCycles++;\n\n            if (tracker.consecutiveCycles >= NOT_DECODING_THRESHOLD_CYCLES && !tracker.isIssueActive) {\n                tracker.isIssueActive = true;\n                logger.warn(`QualityController - remote video not decoding detected: ssrc=${ssrc}, participantId=${participantId}`);\n\n                const eventData = { participantId, ssrc, stopped: true };\n\n                RTCStats.sendStatsEntry(RTCStatsEvents.REMOTE_VIDEO_DECODING_EVENT, null, eventData);\n                Statistics.sendAnalytics(AnalyticsEvents.REMOTE_VIDEO_DECODING, eventData);\n            }\n\n            this._notDecodingVideoTracker.set(ssrc, tracker);\n        }\n\n        // Resolve any SSRCs that were being tracked but are no longer in the problematic state.\n        // An SSRC absent from the incoming stats means its condition has cleared (fps recovered or bytes stopped).\n        for (const [ ssrc, tracker ] of this._notDecodingVideoTracker) {\n            if (!stats.has(ssrc)) {\n                if (tracker.isIssueActive) {\n                    logger.info(`QualityController - remote video decoding resumed: ssrc=${ssrc}, participantId=${tracker.participantId}`);\n\n                    const eventData = { participantId: tracker.participantId, ssrc, stopped: false };\n\n                    RTCStats.sendStatsEntry(RTCStatsEvents.REMOTE_VIDEO_DECODING_EVENT, null, eventData);\n                    Statistics.sendAnalytics(AnalyticsEvents.REMOTE_VIDEO_DECODING, eventData);\n                }\n                this._notDecodingVideoTracker.delete(ssrc);\n            }\n        }\n    }\n\n    /**\n     * Processes the outbound RTP stream stats as reported by the WebRTC peerconnection and makes runtime adjustments\n     * to the client for better quality experience if the adaptive mode is enabled.\n     *\n     * @param {TraceablePeerConnection} tpc - The underlying WebRTC peerconnection where stats have been captured.\n     * @param {Map<number, IOutboundRtpStats>} stats - Outbound-rtp stream stats per SSRC.\n     * @returns void\n     */\n    _processOutboundRtpStats(tpc: TraceablePeerConnection, stats: Map<number, IOutboundRtpStats>): void {\n        const activeSession = this._conference.getActiveMediaSession();\n\n        // Process stats only for the active media session.\n        if (activeSession.peerconnection !== tpc) {\n            return;\n        }\n\n        const statsPerTrack = new Map();\n\n        for (const ssrc of stats.keys()) {\n            const { codec, encodeTime, qualityLimitationReason, resolution, timestamp } = stats.get(ssrc);\n            const track = tpc.getTrackBySSRC(ssrc);\n            const trackId = track.rtcId;\n            let existingStats = statsPerTrack.get(trackId);\n            const encodeResolution = Math.min(resolution?.height, resolution?.width);\n            const ssrcStats = {\n                encodeResolution,\n                encodeTime,\n                qualityLimitationReason\n            };\n\n            if (existingStats) {\n                existingStats.codec = codec;\n                existingStats.timestamp = timestamp;\n                existingStats.trackStats.push(ssrcStats);\n            } else {\n                existingStats = {\n                    codec,\n                    timestamp,\n                    trackStats: [ ssrcStats ]\n                };\n\n                statsPerTrack.set(trackId, existingStats);\n            }\n        }\n\n        // Aggregate the stats for multiple simulcast streams with different SSRCs but for the same video stream.\n        for (const trackId of statsPerTrack.keys()) {\n            const { codec, timestamp, trackStats } = statsPerTrack.get(trackId);\n            const totalEncodeTime = trackStats\n                .map((stat: ITrackStats) => stat.encodeTime)\n                .reduce((totalValue: number, currentValue: number) => totalValue + currentValue, 0);\n            const avgEncodeTime: number = totalEncodeTime / trackStats.length;\n            const { qualityLimitationReason = QualityLimitationReason.NONE }\n                = trackStats\n                    .find((stat: ITrackStats) => stat.qualityLimitationReason !== QualityLimitationReason.NONE) ?? {};\n            const encodeResolution: number = trackStats\n                .map((stat: ITrackStats) => stat.encodeResolution)\n                .reduce((resolution: number, currentValue: number) => Math.max(resolution, currentValue), 0);\n            const localTrack = this._conference.getLocalVideoTracks().find(t => t.rtcId === trackId);\n\n            const exisitingStats: FixedSizeArray = this._encodeTimeStats.get(trackId);\n            const sourceStats = {\n                avgEncodeTime,\n                codec,\n                encodeResolution,\n                localTrack,\n                qualityLimitationReason,\n                timestamp,\n                tpc\n            };\n\n            if (exisitingStats) {\n                exisitingStats.add(sourceStats);\n            } else {\n                // Save stats for only the last 5 mins.\n                const data = new FixedSizeArray(300);\n\n                data.add(sourceStats);\n                this._encodeTimeStats.set(trackId, data);\n            }\n\n            logger.debug(`Encode stats for ${localTrack}: codec=${codec}, time=${avgEncodeTime},`\n                + `resolution=${encodeResolution}, qualityLimitationReason=${qualityLimitationReason}`);\n\n            this._performQualityOptimizations(sourceStats);\n        }\n    }\n\n    /**\n     * Gets the audio controller instance.\n     */\n    get audioController() {\n        return this._audioController;\n    }\n\n    /**\n     * Gets the codec controller instance.\n     */\n    get codecController() {\n        return this._codecController;\n    }\n\n    /**\n     * Gets the receive video controller instance.\n     */\n    get receiveVideoController() {\n        return this._receiveVideoController;\n    }\n\n    /**\n     * Gets the send video controller instance.\n     */\n    get sendVideoController() {\n        return this._sendVideoController;\n    }\n\n    /**\n     * Cleans up the QualityController by clearing all active timeouts and disposing of controllers.\n     * This prevents memory leaks and ensures proper cleanup when the controller is no longer needed.\n     */\n    dispose(): void {\n        // Clear all active timeouts to prevent memory leaks\n        if (this._timer) {\n            clearTimeout(this._timer);\n            this._timer = undefined;\n        }\n\n        if (this._limitedByCpuTimeout) {\n            clearTimeout(this._limitedByCpuTimeout);\n            this._limitedByCpuTimeout = undefined;\n        }\n\n        if (this._lastNRampupTimeout) {\n            clearTimeout(this._lastNRampupTimeout);\n            this._lastNRampupTimeout = undefined;\n        }\n\n        // Clear the encode time stats\n        this._encodeTimeStats.clear();\n\n        // Clear the remote video decoding tracker\n        this._notDecodingVideoTracker.clear();\n\n        logger.info('QualityController disposed, all timeouts cleared');\n    }\n}\n","import { getLogger } from '@jitsi/logger';\nimport { $iq } from 'strophe.js';\n\nimport JitsiParticipant from '../../JitsiParticipant';\nimport { handleStropheError } from '../xmpp/StropheErrorHandler';\nimport XmppConnection from '../xmpp/XmppConnection';\n\nimport { getSessionIdFromIq } from './recordingXMLUtils';\n\nconst logger = getLogger('recording:JibriSession');\n\nexport interface IJibriSessionOptions {\n    connection?: XmppConnection;\n    focusMucJid?: string;\n    mode?: string;\n    sessionID?: string;\n    status?: string;\n}\n\nexport interface IStartOptions {\n    appData?: string;\n    broadcastId?: string;\n    focusMucJid: string;\n    streamId?: string;\n}\n\nexport interface IStopOptions {\n    connection?: XmppConnection;\n    focusMucJid: string;\n    mode?: string;\n}\n\nexport interface IQOptions {\n    action?: 'start' | 'stop';\n    appData?: string;\n    broadcastId?: string;\n    focusMucJid: string;\n    mode?: string;\n    streamId?: string;\n}\n\n/**\n * Represents a recording session.\n */\nexport default class JibriSession {\n    private _connection?: XmppConnection;\n    private _mode?: string;\n    private _jibriJid: Nullable<string> = null;\n    private _statusFromJicofo: string = '';\n    private _sessionID?: string;\n    private _status?: string;\n    private _error?: string;\n    private _liveStreamViewURL?: string;\n    private _initiator?: JitsiParticipant | string;\n    private _terminator?: JitsiParticipant | string;\n    private _focusMucJid?: string;\n\n    /**\n     * Initializes a new JibriSession instance.\n     *\n     * @constructor\n     */\n    constructor(options: IJibriSessionOptions = {}) {\n        this._connection = options.connection;\n        this._mode = options.mode;\n        this._jibriJid = null;\n        this._statusFromJicofo = '';\n        this._setSessionID(options.sessionID);\n        this.setStatus(options.status);\n        this._focusMucJid = options.focusMucJid;\n    }\n\n    /**\n     * Returns the error related to the session instance, if any.\n     *\n     * @returns {Optional<string>}\n     */\n    getError(): Optional<string> {\n        return this._error;\n    }\n\n    /**\n     * Returns the session ID of the session instance.\n     *\n     * @returns {Optional<string>}\n     */\n    getID(): Optional<string> {\n        return this._sessionID;\n    }\n\n    /**\n     * Returns the initiator of the session instance.\n     *\n     * @returns {JitsiParticipant|string} The participant that started the session.\n     */\n    getInitiator(): JitsiParticipant | string {\n        return this._initiator;\n    }\n\n    /**\n     * Returns the streaming URL of the session.\n     *\n     * @returns {Optional<string>}\n     */\n    getLiveStreamViewURL(): Optional<string> {\n        return this._liveStreamViewURL;\n    }\n\n    /**\n     * Returns the current status of the session.\n     *\n     * @returns {Optional<string>}\n     */\n    getStatus(): Optional<string> {\n        // If _status is not set fallback to the status reported by jicofo.\n        if (this._status) {\n            return this._status;\n        }\n\n        return this._statusFromJicofo;\n    }\n\n    /**\n     * @returns {Optional<string>}\n     */\n    getJibriJid(): Optional<string> {\n        return this._jibriJid;\n    }\n\n    /**\n     * Returns the jid of the participant that stopped the session.\n     *\n     * @returns {JitsiParticipant|string} The participant that stopped the session.\n     */\n    getTerminator(): JitsiParticipant | string {\n        return this._terminator;\n    }\n\n    /**\n     * Returns the current recording mode of the session, such as \"file\".\n     *\n     * @returns {string}\n     */\n    getMode(): string {\n        return this._mode;\n    }\n\n    /**\n     * Sets the last known error message related to the session.\n     *\n     * @param {string} error - The error string explaining why the session\n     * entered an error state.\n     * @returns {void}\n     */\n    setError(error: string): void {\n        this._error = error;\n    }\n\n    /**\n     * Sets the last live stream URL for the session instance. Usually this is\n     * a YouTube URL and usually this is only set for \"stream\" sessions.\n     *\n     * @param {string} url - The live stream URL associated with the session.\n     * @returns {void}\n     */\n    setLiveStreamViewURL(url: string): void {\n        this._liveStreamViewURL = url;\n    }\n\n    /**\n     * Sets the last known status for this recording session.\n     *\n     * @param {string} status - The new status to set.\n     * @returns {void}\n     */\n    setStatus(status?: string): void {\n        this._status = status;\n    }\n\n    /**\n     * Set the session status reported by jicofo. If a jibri is present in the room,\n     * the status is always 'on'. Otherwise, we fallback to the status reported by jicofo.\n     *\n     * @param {string} status\n     */\n    setStatusFromJicofo(status: string): void {\n        this._statusFromJicofo = status;\n    }\n\n    /**\n     * Set the JID of the jibri associated with this session.\n     *\n     * @param {*} jibriJid\n     */\n    setJibriJid(jibriJid: Nullable<string>): void {\n        this._jibriJid = jibriJid;\n    }\n\n    /**\n     * Sets the participant that started the session.\n     * @param {JitsiParticipant | string} participant - The participant or resource id\n     * if local participant.\n     */\n    setInitiator(participant: JitsiParticipant | string): void {\n        this._initiator = participant;\n    }\n\n    /**\n     * Sets the participant that stopped the session.\n     * @param {JitsiParticipant | string} participant - The participant or the resource id\n     * if local participant.\n     */\n    setTerminator(participant: JitsiParticipant | string): void {\n        this._terminator = participant;\n    }\n\n    /**\n     * Sends a message to start the actual recording.\n     *\n     * @param {Object} options - Additional arguments for starting therecording.\n     * @param {string} [options.appData] - Data specific to the app/service that the result file will be uploaded.\n     * @param {string} [options.broadcastId] - The broadcast ID of an associated YouTube stream, used for knowing the\n     * URL from which the stream can be viewed.\n     * @param {string} options.focusMucJid - The JID of the focus participant that controls recording.\n     * @param {streamId} options.streamId - Necessary for live streaming, this is the stream key needed to start a live\n     * streaming session with the streaming service provider.\n     * @returns Promise\n     */\n    start({ appData, broadcastId, focusMucJid, streamId }: IStartOptions): Promise<void> {\n        logger.info('Starting recording session');\n\n        return new Promise((resolve, reject) => {\n            this._connection?.sendIQ(\n                JibriSession._createIQ({\n                    action: 'start',\n                    appData,\n                    broadcastId,\n                    focusMucJid,\n                    mode: this._mode,\n                    streamId\n                }),\n                (result: any) => {\n                    this.setStatus('pending');\n                    this._setSessionID(\n                        getSessionIdFromIq(result)\n                    );\n\n                    resolve();\n                },\n                (error: any) => {\n                    this._setErrorFromIq(error);\n                    handleStropheError(error, {\n                        operation: 'start Jibri session request',\n                        userJid: this._connection?.jid,\n                    });\n\n                    reject(error);\n                }\n            );\n        });\n    }\n\n    /**\n     * Sends a message to actually stop the recording session.\n     *\n     * @param {Object} options - Additional arguments for stopping the recording.\n     * @param {XmppConnection} [options.connection] - The XMPP connection to use.\n     * @param {Object} options.focusMucJid - The JID of the focus participant that controls recording.\n     * @param {string} [options.mode] - The recording mode of the session.\n     * @returns Promise\n     */\n    static stop({ connection, focusMucJid, mode }: IStopOptions): Promise<any> {\n        logger.info('Stopping recording session');\n\n        return new Promise((resolve, reject) => {\n            connection?.sendIQ(\n                JibriSession._createIQ({\n                    action: 'stop',\n                    focusMucJid,\n                    mode\n                }),\n                resolve,\n                (error: any) => {\n                    handleStropheError(error, {\n                        operation: 'stop Jibri session request',\n                        userJid: connection?.jid\n                    });\n                    reject(error);\n                }\n            );\n        });\n    }\n\n    /**\n     * Generates the message to change the status of the recording session.\n     *\n     * @param {string} [options.action] - The action to set the IQ\n     * @param {string} [options.appData] - Data specific to the app/service that\n     * the result file will be uploaded.\n     * @param {string} [options.broadcastId] - The broadcast ID of an\n     * associated YouTube stream, used for knowing the URL from which the stream\n     * can be viewed.\n     * @param {string} options.focusMucJid - The JID of the focus participant\n     * that controls recording.\n     * @param {string} options.mode - The recording mode for the session we create this IQ for.\n     * @param {streamId} options.streamId - Necessary for live streaming, this\n     * is the stream key needed to start a live streaming session with the\n     * streaming service provider.\n     * @returns Object - The XMPP IQ message.\n     */\n    static _createIQ({ action, appData, broadcastId, focusMucJid, mode, streamId }: IQOptions) {\n        return $iq({\n            to: focusMucJid,\n            type: 'set'\n        })\n        .c('jibri', {\n            'action': action,\n            'app_data': appData,\n            'recording_mode': mode,\n            'streamid': streamId,\n            'xmlns': 'http://jitsi.org/protocol/jibri',\n            'you_tube_broadcast_id': broadcastId\n        })\n        .up();\n    }\n\n    /**\n     * Handles the error from an iq and stores the error.\n     *\n     * @param {Node} errorIq - The error response from an Iq.\n     * @private\n     * @returns {void}\n     */\n    _setErrorFromIq(errorIq: any): void {\n        let error;\n\n        if (errorIq) {\n            if (typeof errorIq === 'string') {\n                error = errorIq;\n            } else if (errorIq.nodeType === 1) {\n                const errors = errorIq.getElementsByTagName('error');\n\n                if (errors?.length > 0) {\n                    const errorChildren = errors[0].children;\n\n                    error = errorChildren?.length > 0 ? errorChildren[0].tagName : undefined;\n                }\n            }\n        } else {\n            error = 'timeout';\n        }\n\n        this.setError(error ?? 'unknown');\n    }\n\n    /**\n     * Sets the known session ID for this recording session.\n     *\n     * @param {string} sessionID\n     * @private\n     * @returns {void}\n     */\n    _setSessionID(sessionID?: string): void {\n        this._sessionID = sessionID;\n    }\n}\n","/**\n * A collection of utility functions for taking in XML and parsing it to return\n * certain values.\n */\n\nexport interface IFocusRecordingUpdate {\n    error?: string;\n    initiator?: string;\n    recordingMode?: string;\n    sessionID?: string;\n    status?: string;\n}\n\nexport interface IHiddenDomainUpdate {\n    liveStreamViewURL?: string;\n    mode?: string;\n    sessionID?: string;\n}\n\n/**\n * Parses the presence update of the focus and returns an object with the\n * statuses related to recording.\n *\n * @param {Element} presence - An XMPP presence update.\n * @returns {Optional<Object>} The current presence values related to recording.\n */\nexport function getFocusRecordingUpdate(presence: Element): Optional<IFocusRecordingUpdate> {\n    const jibriStatus = presence?.getElementsByTagName('jibri-recording-status')[0];\n\n    if (!jibriStatus) {\n        return;\n    }\n\n    return {\n        error: jibriStatus.getAttribute('failure_reason'),\n        initiator: jibriStatus.getAttribute('initiator'),\n        recordingMode: jibriStatus.getAttribute('recording_mode'),\n        sessionID: jibriStatus.getAttribute('session_id'),\n        status: jibriStatus.getAttribute('status')\n    };\n}\n\n/**\n * Parses the presence update from a hidden domain participant and returns\n * an object with the statuses related to recording.\n *\n * @param {Element} presence - An XMPP presence update.\n * @returns {Object} The current presence values related to recording.\n */\nexport function getHiddenDomainUpdate(presence: Element): IHiddenDomainUpdate {\n    const liveStreamViewURL = presence.getElementsByTagName('live-stream-view-url')[0]?.textContent;\n    const mode = presence.getElementsByTagName('mode')[0]?.textContent?.toLowerCase();\n    const sessionID = presence.getElementsByTagName('session_id')[0]?.textContent;\n\n    return {\n        liveStreamViewURL,\n        mode,\n        sessionID\n    };\n}\n\n/**\n * Returns the recording session ID from a successful IQ.\n *\n * @param {Element} response - The response from the IQ.\n * @returns {string} The session ID of the recording session.\n */\nexport function getSessionIdFromIq(response: Element): Nullable<string> {\n    return response?.getElementsByTagName('jibri')[0]?.getAttribute('session_id') ?? null;\n}\n","import { getLogger } from '@jitsi/logger';\n\nimport { XMPPEvents } from '../../service/xmpp/XMPPEvents';\nimport ChatRoom from '../xmpp/ChatRoom';\n\nimport JibriSession from './JibriSession';\nimport { getFocusRecordingUpdate, getHiddenDomainUpdate } from './recordingXMLUtils';\n\nconst logger = getLogger('recording:RecordingManager');\n\nexport interface IRecordingOptions {\n    appData?: string;\n    broadcastId?: string;\n    mode: string;\n    streamId?: string;\n}\n\n/**\n * A class responsible for starting and stopping recording sessions and emitting\n * state updates for them.\n */\nclass RecordingManager {\n    private _sessions: { [key: string]: JibriSession; } = {};\n    private _chatRoom: ChatRoom;\n\n    /**\n     * Initialize {@code RecordingManager} with other objects that are necessary\n     * for starting a recording.\n     *\n     * @param {ChatRoom} chatRoom - The chat room to handle.\n     * @returns {void}\n     */\n    constructor(chatRoom: ChatRoom) {\n        /**\n         * All known recording sessions from the current conference.\n         */\n        this._chatRoom = chatRoom;\n\n        this.onPresence = this.onPresence.bind(this);\n\n        this.onMemberLeft = this.onMemberLeft.bind(this);\n\n        this._chatRoom.eventEmitter.addListener(\n            XMPPEvents.PRESENCE_RECEIVED, this.onPresence);\n        this._chatRoom.eventEmitter.addListener(\n            XMPPEvents.MUC_MEMBER_LEFT, this.onMemberLeft);\n    }\n\n    /**\n     * Finds an existing recording session by session ID.\n     *\n     * @param {string} sessionID - The session ID associated with the recording.\n     * @returns {Optional<JibriSession>}\n     */\n    getSession(sessionID: string): Optional<JibriSession> {\n        return this._sessions[sessionID];\n    }\n\n    /**\n     * Find a session with a specific jibri JID.\n     *\n     * @param {string} jibriJid the JID to search for.\n     * @returns\n     */\n    getSessionByJibriJid(jibriJid: string): Optional<JibriSession> {\n        let s: Optional<JibriSession>;\n\n        Object.values(this._sessions).forEach(session => {\n            if (session.getJibriJid() === jibriJid) {\n                s = session;\n            }\n        });\n\n        return s;\n    }\n\n    /**\n     * Callback to invoke to parse through a presence update to find recording\n     * related updates (from Jibri participant doing the recording and the\n     * focus which controls recording).\n     *\n     * @param {Object} event - The presence data from the pubsub event.\n     * @param {Element} event.presence - An XMPP presence update.\n     * @param {boolean} event.fromHiddenDomain - Whether or not the update comes\n     * from a participant that is trusted but not visible, as would be the case\n     * with the Jibri recorder participant.\n     * @param {boolean} event.isFocus - Whether or not the update comes from the\n     * conference focus.\n     * @returns {void}\n     */\n    onPresence({ fromHiddenDomain, isFocus, presence }:\n    { fromHiddenDomain: boolean; isFocus: boolean; presence: Element; }): void {\n        if (isFocus) {\n            this._handleFocusPresence(presence);\n        } else if (fromHiddenDomain) {\n            this._handleJibriPresence(presence);\n        }\n    }\n\n    /**\n     * Handle a participant leaving the room.\n     * @param {string} jid the JID of the participant that left.\n     */\n    onMemberLeft(jid: string): void {\n        const session = this.getSessionByJibriJid(jid);\n\n        if (session) {\n\n            const prevStatus = session.getStatus();\n\n            // Setting to ''\n            session.setStatus('');\n            session.setJibriJid(null);\n\n            if (session.getStatus() !== prevStatus) {\n                this._emitSessionUpdate(session);\n            }\n        }\n    }\n\n    /**\n     * Start a recording session.\n     *\n     * @param {Object} options - Configuration for the recording.\n     * @param {string} [options.appData] - Data specific to the app/service that\n     * the result file will be uploaded.\n     * @param {string} [optional] options.broadcastId - The channel on which a\n     * live stream will occur.\n     * @param {string} options.mode - The mode in which recording should be\n     * started. Recognized values are \"file\" and \"stream\".\n     * @param {string} [optional] options.streamId - The stream key to be used\n     * for live stream broadcasting. Required for live streaming.\n     * @returns {Promise} A promise for starting a recording, which will pass\n     * back the session on success. The promise resolves after receiving an\n     * acknowledgment of the start request success or fail.\n     */\n    startRecording(options: IRecordingOptions): Promise<JibriSession> {\n        const session = new JibriSession({\n            ...options,\n            connection: this._chatRoom.connection\n        });\n\n        return session.start({\n            appData: options.appData,\n            broadcastId: options.broadcastId,\n            focusMucJid: this._chatRoom.focusMucJid,\n            streamId: options.streamId\n        })\n            .then(() => {\n                // Only store the session and emit if the session has not been\n                // added already. This is a workaround for the session getting\n                // created due to a presence update to announce a \"pending\"\n                // recording being received before JibriSession#start finishes.\n                if (!this.getSession(session.getID())) {\n                    this._addSession(session);\n                    this._emitSessionUpdate(session);\n                }\n\n                return session;\n            })\n            .catch(error => {\n                this._emitSessionUpdate(session);\n\n                return Promise.reject(error);\n            });\n    }\n\n    /**\n     * Stop a recording session.\n     *\n     * @param {string} sessionID - The ID associated with the recording session\n     * to be stopped.\n     * @returns {Promise} The promise resolves after receiving an\n     * acknowledgment of the stop request success or fail.\n     */\n    stopRecording(sessionID: string): Promise<any> {\n        const session = this.getSession(sessionID);\n\n        return JibriSession.stop({\n            connection: this._chatRoom.connection,\n            focusMucJid: this._chatRoom.focusMucJid,\n            mode: session?.getMode()\n        });\n    }\n\n    /**\n     * Stores a reference to the passed in JibriSession.\n     *\n     * @param {string} session - The JibriSession instance to store.\n     * @returns {void}\n     */\n    _addSession(session: JibriSession): void {\n        this._sessions[session.getID()] = session;\n    }\n\n    /**\n     * Create a new instance of a recording session and stores a reference to\n     * it.\n     *\n     * @param {string} sessionID - The session ID of the recording in progress.\n     * @param {string} status - The current status of the recording session.\n     * @param {string} mode - The recording mode of the session.\n     * @returns {JibriSession}\n     */\n    _createSession(sessionID: string, status: string, mode: string): JibriSession {\n        const session = new JibriSession({\n            connection: this._chatRoom.connection,\n            focusMucJid: this._chatRoom.focusMucJid,\n            mode,\n            sessionID,\n            status\n        });\n\n        this._addSession(session);\n\n        return session;\n    }\n\n    /**\n     * Notifies listeners of an update to a recording session.\n     *\n     * @param {JibriSession} session - The session that has been updated.\n     * @param {string|undefined} initiator - The jid of the initiator of the update.\n     */\n    _emitSessionUpdate(session: JibriSession, initiator?: string): void {\n        this._chatRoom.eventEmitter.emit(\n            XMPPEvents.RECORDER_STATE_CHANGED, session, initiator);\n    }\n\n    /**\n     * Parses presence to update an existing JibriSession or to create a new\n     * JibriSession.\n     *\n     * @param {Element} presence - An XMPP presence update.\n     * @returns {void}\n     */\n    _handleFocusPresence(presence: Element): void {\n        const jibriStatus = getFocusRecordingUpdate(presence);\n\n        if (!jibriStatus) {\n            return;\n        }\n\n        const { error, initiator, recordingMode, sessionID, status } = jibriStatus;\n\n        // We'll look for an existing session or create one (in case we're a\n        // participant joining a call with an existing recording going on).\n        let session = this.getSession(sessionID);\n\n        // Handle the case where a status update is received in presence but\n        // the local participant has joined while the JibriSession has already\n        // ended.\n        if (!session && status === 'off') {\n            logger.warn(\n                'Ignoring recording presence update',\n                'Received a new session with status off.');\n\n            return;\n        }\n\n        // Jicofo sends updates via presence, and any extension in presence\n        // is sent until it is explicitly removed.  It's difficult for\n        // Jicofo to know when a presence has been sent once, so it won't\n        // remove jibri status extension.  This means we may receive the same\n        // status update more than once, so check for that here\n        if (session\n            && session.getStatus() === status\n            && session.getError() === error) {\n            logger.warn('Ignoring duplicate presence update: ',\n                JSON.stringify(jibriStatus));\n\n            return;\n        }\n\n        if (!session) {\n            session = this._createSession(sessionID, status, recordingMode);\n        }\n\n        session.setStatusFromJicofo(status);\n\n        if (this._chatRoom.role === 'visitor') {\n            // visitors will not receive presence updates from jibri, so we handle their status here\n            session.setStatus(status);\n        }\n\n        if (error) {\n            session.setError(error);\n        }\n\n        this._emitSessionUpdate(session, initiator);\n    }\n\n    /**\n     * Handles updates from the Jibri which can broadcast a YouTube URL that\n     * needs to be updated in a JibriSession.\n     *\n     * @param {Element} presence - An XMPP presence update.\n     * @returns {void}\n     */\n    _handleJibriPresence(presence: Element): void {\n        const { liveStreamViewURL, mode, sessionID }\n            = getHiddenDomainUpdate(presence);\n\n        if (!sessionID) {\n            logger.warn(\n                'Ignoring potential jibri presence due to no session id.');\n\n            return;\n        }\n\n        let session = this.getSession(sessionID);\n\n        if (!session) {\n            session = this._createSession(sessionID, 'on', mode);\n        }\n\n        // When a jibri is present the status is always 'on';\n        session.setStatus('on');\n        session.setJibriJid(presence.getAttribute('from'));\n        session.setLiveStreamViewURL(liveStreamViewURL);\n\n        this._emitSessionUpdate(session);\n    }\n}\n\nexport default RecordingManager;\n","import { getLogger } from '@jitsi/logger';\nimport { isEqual } from 'lodash-es';\n\nimport JitsiConference from '../../JitsiConference';\nimport { JitsiConferenceEvents as ConferenceEvents } from '../../JitsiConferenceEvents';\nimport JitsiParticipant from '../../JitsiParticipant';\nimport { MediaType } from '../../service/RTC/MediaType';\nimport { VideoType } from '../../service/RTC/VideoType';\nimport { ConnectionQualityEvents } from '../../service/connectivity/ConnectionQualityEvents';\nimport {\n    createRtpStatsEvent,\n    createTransportStatsEvent\n} from '../../service/statistics/AnalyticsEvents';\nimport JitsiLocalTrack from '../RTC/JitsiLocalTrack';\nimport JitsiRemoteTrack from '../RTC/JitsiRemoteTrack';\nimport TraceablePeerConnection from '../RTC/TraceablePeerConnection';\nimport browser from '../browser';\nimport { isValidNumber } from '../util/MathUtil';\nimport JingleSession from '../xmpp/JingleSession';\n\nimport Statistics from './statistics';\n\nconst logger = getLogger('stats:AvgRTPStatsReporter');\n\n/**\n * This will calculate an average for one, named stat and submit it to\n * the analytics module when requested. It automatically counts the samples.\n */\nclass AverageStatReport {\n    private _name: string;\n    private _count: number;\n    private _sum: number;\n    private _samples: number[];\n\n    /**\n     * Creates new <tt>AverageStatReport</tt> for given name.\n     * @param {string} name that's the name of the event that will be reported\n     * to the analytics module.\n     */\n    constructor(name: string) {\n        this._name = name;\n        this._count = 0;\n        this._sum = 0;\n        this._samples = [];\n    }\n\n    /**\n     * Adds the next value that will be included in the average when\n     * {@link calculate} is called.\n     * @param {Optional<number>} nextValue\n     */\n    addNext(nextValue: Optional<number>): void {\n        if (typeof nextValue === 'undefined') {\n            return;\n        }\n\n        if (typeof nextValue !== 'number') {\n            logger.error(`${this._name} - invalid value for idx: ${this._count}`, nextValue);\n        } else if (isValidNumber(nextValue)) {\n            this._sum += nextValue;\n            this._samples.push(nextValue);\n            this._count += 1;\n        }\n    }\n\n    /**\n     * Calculates an average for the samples collected using {@link addNext}.\n     * @return {number|NaN} an average of all collected samples or <tt>NaN</tt>\n     * if no samples were collected.\n     */\n    calculate(): number {\n        return this._count === 0 ? NaN : this._sum / this._count;\n    }\n\n    /**\n     * Appends the report to the analytics \"data\" object. The object will be\n     * set under <tt>prefix</tt> + {@link this.name} key.\n     * @param {Object} report the analytics \"data\" object\n     */\n    appendReport(report: Record<string, unknown>): void {\n        report[`${this._name}_avg`] = this.calculate();\n        report[`${this._name}_samples`] = JSON.stringify(this._samples);\n    }\n\n    /**\n     * Clears all memory of any samples collected, so that new average can be\n     * calculated using this instance.\n     */\n    reset(): void {\n        this._samples = [];\n        this._sum = 0;\n        this._count = 0;\n    }\n}\n\n/**\n * Class gathers the stats that are calculated and reported for a\n * {@link TraceablePeerConnection} even if it's not currently active. For\n * example we want to monitor RTT for the JVB connection while in P2P mode.\n */\nclass ConnectionAvgStats {\n    private _n: number;\n    private _sampleIdx: number;\n    private _avgRTT: AverageStatReport;\n    private _avgRemoteRTTMap: Map<string, AverageStatReport>;\n    private _avgRtpStatsReporter: AvgRTPStatsReporter;\n    private _avgEnd2EndRTT: Optional<number>;\n    private _onConnectionStats: (tpc: TraceablePeerConnection) => void;\n    private _onUserLeft?: (id: string) => void;\n    private _onRemoteStatsUpdated?: (id: string, data: any) => void;\n    public isP2P: boolean;\n\n    /**\n     * Creates new <tt>ConnectionAvgStats</tt>\n     * @param {AvgRTPStatsReporter} avgRtpStatsReporter\n     * @param {boolean} isP2P\n     * @param {number} n the number of samples, before arithmetic mean is to be\n     * calculated and values submitted to the analytics module.\n     */\n    constructor(avgRtpStatsReporter: AvgRTPStatsReporter, isP2P: boolean, n: number) {\n        /**\n         * Is this instance for JVB or P2P connection ?\n         * @type {boolean}\n         */\n        this.isP2P = isP2P;\n\n        /**\n         * How many samples are to be included in arithmetic mean calculation.\n         * @type {number}\n         * @private\n         */\n        this._n = n;\n\n        /**\n         * The current sample index. Starts from 0 and goes up to {@link _n})\n         * when analytics report will be submitted.\n         * @type {number}\n         * @private\n         */\n        this._sampleIdx = 0;\n\n        /**\n         * Average round trip time reported by the ICE candidate pair.\n         * @type {AverageStatReport}\n         */\n        this._avgRTT = new AverageStatReport('rtt');\n\n        /**\n         * Map stores average RTT to the JVB reported by remote participants.\n         * Mapped per participant id {@link JitsiParticipant.getId}.\n         *\n         * This is used only when {@link ConnectionAvgStats.isP2P} equals to\n         * <tt>false</tt>.\n         *\n         * @type {Map<string,AverageStatReport>}\n         * @private\n         */\n        this._avgRemoteRTTMap = new Map();\n\n        /**\n         * The conference for which stats will be collected and reported.\n         * @type {JitsiConference}\n         * @private\n         */\n        this._avgRtpStatsReporter = avgRtpStatsReporter;\n\n        /**\n         * The latest average E2E RTT for the JVB connection only.\n         *\n         * This is used only when {@link ConnectionAvgStats.isP2P} equals to\n         * <tt>false</tt>.\n         *\n         * @type {number}\n         */\n        this._avgEnd2EndRTT = undefined;\n\n        this._onConnectionStats = (tpc: TraceablePeerConnection) => {\n            if (this.isP2P === tpc.isP2P) {\n                this._calculateAvgStats(tpc.getStats());\n            }\n        };\n\n        const conference = avgRtpStatsReporter._conference;\n\n        conference.statistics.addConnectionStatsListener(\n            this._onConnectionStats);\n\n        if (!this.isP2P) {\n            this._onUserLeft = (id: string) => this._avgRemoteRTTMap.delete(id);\n            conference.on(ConferenceEvents.USER_LEFT, this._onUserLeft);\n\n            this._onRemoteStatsUpdated\n                = (id: string, data: any) => this._processRemoteStats(id, data);\n            conference.on(\n                ConnectionQualityEvents.REMOTE_STATS_UPDATED,\n                this._onRemoteStatsUpdated);\n        }\n    }\n\n    /**\n     * Processes next batch of stats.\n     * @param {go figure} data\n     * @private\n     */\n    private _calculateAvgStats(data: any): void {\n        if (!data) {\n            logger.error('No stats');\n\n            return;\n        }\n\n        if (browser.supportsRTTStatistics()) {\n            if (data.transport?.length) {\n                this._avgRTT.addNext(data.transport[0].rtt);\n            }\n        }\n\n        this._sampleIdx += 1;\n\n        if (this._sampleIdx >= this._n) {\n            if (browser.supportsRTTStatistics()) {\n                const conference = this._avgRtpStatsReporter._conference;\n\n                const batchReport: Record<string, unknown> = {\n                    'conference_size': conference.getParticipantCount(),\n                    p2p: this.isP2P\n                };\n\n                if (data.transport?.length) {\n                    Object.assign(batchReport, {\n                        'local_candidate_type':\n                            data.transport[0].localCandidateType,\n                        'remote_candidate_type':\n                            data.transport[0].remoteCandidateType,\n                        'transport_type': data.transport[0].type\n                    });\n                }\n\n                this._avgRTT.appendReport(batchReport);\n\n                if (this.isP2P) {\n                    // Report RTT diff only for P2P.\n                    const jvbEnd2EndRTT = this\n                        ._avgRtpStatsReporter.jvbStatsMonitor._avgEnd2EndRTT;\n\n                    if (isValidNumber(jvbEnd2EndRTT)) {\n                        batchReport.rtt_diff\n                            = this._avgRTT.calculate() - jvbEnd2EndRTT;\n                    }\n                } else {\n                    // Report end to end RTT only for JVB.\n                    const avgRemoteRTT = this._calculateAvgRemoteRTT();\n                    const avgLocalRTT = this._avgRTT.calculate();\n\n                    this._avgEnd2EndRTT = avgLocalRTT + avgRemoteRTT;\n\n                    if (isValidNumber(avgLocalRTT) && isValidNumber(avgRemoteRTT)) {\n                        batchReport.end2end_rtt_avg = this._avgEnd2EndRTT;\n                    }\n                }\n\n                Statistics.sendAnalytics(createRtpStatsEvent(batchReport));\n            }\n\n            this._resetAvgStats();\n        }\n    }\n\n    /**\n     * Calculates arithmetic mean of all RTTs towards the JVB reported by\n     * participants.\n     * @return {number|NaN} NaN if not available (not enough data)\n     * @private\n     */\n    private _calculateAvgRemoteRTT(): number {\n        let count = 0, sum = 0;\n\n        // FIXME should we ignore RTT for participant\n        // who \"is having connectivity issues\" ?\n        for (const remoteAvg of this._avgRemoteRTTMap.values()) {\n            const avg = remoteAvg.calculate();\n\n            if (isValidNumber(avg)) {\n                sum += avg;\n                count += 1;\n                remoteAvg.reset();\n            }\n        }\n\n        return count === 0 ? NaN : sum / count;\n    }\n\n    /**\n     * Processes {@link ConnectionQualityEvents.REMOTE_STATS_UPDATED} to analyse\n     * RTT towards the JVB reported by each participant.\n     * @param {string} id {@link JitsiParticipant.getId}\n     * @param {go figure in ConnectionQuality.js} data\n     * @private\n     */\n    private _processRemoteStats(id: string, data: any): void {\n        const validData = typeof data.jvbRTT === 'number';\n        let rttAvg = this._avgRemoteRTTMap.get(id);\n\n        if (!rttAvg && validData) {\n            rttAvg = new AverageStatReport(`${id}_stat_rtt`);\n            this._avgRemoteRTTMap.set(id, rttAvg);\n        }\n\n        if (validData) {\n            rttAvg.addNext(data.jvbRTT);\n        } else if (rttAvg) {\n            this._avgRemoteRTTMap.delete(id);\n        }\n    }\n\n    /**\n     * Reset cache of all averages and {@link _sampleIdx}.\n     * @internal\n     */\n    _resetAvgStats(): void {\n        this._avgRTT.reset();\n        if (this._avgRemoteRTTMap) {\n            this._avgRemoteRTTMap.clear();\n        }\n        this._sampleIdx = 0;\n    }\n\n    /**\n     *\n     */\n    public dispose(): void {\n        const conference = this._avgRtpStatsReporter._conference;\n\n        conference.statistics.removeConnectionStatsListener(\n            this._onConnectionStats);\n        if (!this.isP2P) {\n            conference.off(\n                ConnectionQualityEvents.REMOTE_STATS_UPDATED,\n                this._onRemoteStatsUpdated);\n            conference.off(\n                ConferenceEvents.USER_LEFT,\n                this._onUserLeft);\n        }\n    }\n}\n\n/**\n * Reports average RTP statistics values (arithmetic mean) to the analytics\n * module for things like bit rate, bandwidth, packet loss etc. It keeps track\n * of the P2P vs JVB conference modes and submits the values under different\n * namespaces (the events for P2P mode have 'p2p.' prefix). Every switch between\n * P2P mode resets the data collected so far and averages are calculated from\n * scratch.\n */\nexport default class AvgRTPStatsReporter {\n    _n: number;\n    _sampleIdx: number;\n    _conference: JitsiConference;\n    _avgAudioBitrateUp: AverageStatReport;\n    _avgAudioBitrateDown: AverageStatReport;\n    _avgVideoBitrateUp: AverageStatReport;\n    _avgVideoBitrateDown: AverageStatReport;\n    _avgBandwidthUp: AverageStatReport;\n    _avgBandwidthDown: AverageStatReport;\n    _avgPacketLossTotal: AverageStatReport;\n    _avgPacketLossUp: AverageStatReport;\n    _avgPacketLossDown: AverageStatReport;\n    _avgRemoteFPS: AverageStatReport;\n    _avgRemoteScreenFPS: AverageStatReport;\n    _avgLocalFPS: AverageStatReport;\n    _avgLocalScreenFPS: AverageStatReport;\n    _avgRemoteCameraPixels: AverageStatReport;\n    _avgRemoteScreenPixels: AverageStatReport;\n    _avgLocalCameraPixels: AverageStatReport;\n    _avgLocalScreenPixels: AverageStatReport;\n    _avgCQ: AverageStatReport;\n    _cachedTransportStats: Optional<Record<string, unknown>>;\n    _onLocalStatsUpdated: (data: any) => void;\n    _onP2PStatusChanged: () => void;\n    _onJvb121StatusChanged: (activeSession: JingleSession) => void;\n    jvbStatsMonitor: ConnectionAvgStats;\n    p2pStatsMonitor: ConnectionAvgStats;\n\n    /**\n     * Creates new instance of <tt>AvgRTPStatsReporter</tt>\n     * @param {JitsiConference} conference\n     * @param {number} n the number of samples, before arithmetic mean is to be\n     * calculated and values submitted to the analytics module.\n     */\n    constructor(conference: JitsiConference, n: number) {\n        /**\n         * How many {@link ConnectionQualityEvents.LOCAL_STATS_UPDATED} samples\n         * are to be included in arithmetic mean calculation.\n         * @type {number}\n         * @private\n         */\n        this._n = n;\n\n        if (n > 0) {\n            logger.info(`Avg RTP stats will be calculated every ${n} samples`);\n        } else {\n            logger.info('Avg RTP stats reports are disabled.');\n\n            // Do not initialize\n            return;\n        }\n\n        /**\n         * The current sample index. Starts from 0 and goes up to {@link _n})\n         * when analytics report will be submitted.\n         * @type {number}\n         * @private\n         */\n        this._sampleIdx = 0;\n\n        /**\n         * The conference for which stats will be collected and reported.\n         * @type {JitsiConference}\n         * @private\n         */\n        this._conference = conference;\n\n        /**\n         * Average audio upload bitrate\n         * XXX What are the units?\n         * @type {AverageStatReport}\n         * @private\n         */\n        this._avgAudioBitrateUp\n            = new AverageStatReport('bitrate_audio_upload');\n\n        /**\n         * Average audio download bitrate\n         * XXX What are the units?\n         * @type {AverageStatReport}\n         * @private\n         */\n        this._avgAudioBitrateDown\n            = new AverageStatReport('bitrate_audio_download');\n\n        /**\n         * Average video upload bitrate\n         * XXX What are the units?\n         * @type {AverageStatReport}\n         * @private\n         */\n        this._avgVideoBitrateUp\n            = new AverageStatReport('bitrate_video_upload');\n\n        /**\n         * Average video download bitrate\n         * XXX What are the units?\n         * @type {AverageStatReport}\n         * @private\n         */\n        this._avgVideoBitrateDown\n            = new AverageStatReport('bitrate_video_download');\n\n        /**\n         * Average upload bandwidth\n         * XXX What are the units?\n         * @type {AverageStatReport}\n         * @private\n         */\n        this._avgBandwidthUp\n            = new AverageStatReport('bandwidth_upload');\n\n        /**\n         * Average download bandwidth\n         * XXX What are the units?\n         * @type {AverageStatReport}\n         * @private\n         */\n        this._avgBandwidthDown\n            = new AverageStatReport('bandwidth_download');\n\n        /**\n         * Average total packet loss\n         * XXX What are the units?\n         * @type {AverageStatReport}\n         * @private\n         */\n        this._avgPacketLossTotal\n            = new AverageStatReport('packet_loss_total');\n\n        /**\n         * Average upload packet loss\n         * XXX What are the units?\n         * @type {AverageStatReport}\n         * @private\n         */\n        this._avgPacketLossUp\n            = new AverageStatReport('packet_loss_upload');\n\n        /**\n         * Average download packet loss\n         * XXX What are the units?\n         * @type {AverageStatReport}\n         * @private\n         */\n        this._avgPacketLossDown\n            = new AverageStatReport('packet_loss_download');\n\n        /**\n         * Average FPS for remote videos\n         * @type {AverageStatReport}\n         * @private\n         */\n        this._avgRemoteFPS = new AverageStatReport('framerate_remote');\n\n        /**\n         * Average FPS for remote screen streaming videos (reported only if not\n         * a <tt>NaN</tt>).\n         * @type {AverageStatReport}\n         * @private\n         */\n        this._avgRemoteScreenFPS\n            = new AverageStatReport('framerate_screen_remote');\n\n        /**\n         * Average FPS for local video (camera)\n         * @type {AverageStatReport}\n         * @private\n         */\n        this._avgLocalFPS = new AverageStatReport('framerate_local');\n\n        /**\n         * Average FPS for local screen streaming video (reported only if not\n         * a <tt>NaN</tt>).\n         * @type {AverageStatReport}\n         * @private\n         */\n        this._avgLocalScreenFPS\n            = new AverageStatReport('framerate_screen_local');\n\n        /**\n         * Average pixels for remote screen streaming videos (reported only if\n         * not a <tt>NaN</tt>).\n         * @type {AverageStatReport}\n         * @private\n         */\n        this._avgRemoteCameraPixels\n            = new AverageStatReport('pixels_remote');\n\n        /**\n         * Average pixels for remote screen streaming videos (reported only if\n         * not a <tt>NaN</tt>).\n         * @type {AverageStatReport}\n         * @private\n         */\n        this._avgRemoteScreenPixels\n            = new AverageStatReport('pixels_screen_remote');\n\n        /**\n         * Average pixels for local video (camera)\n         * @type {AverageStatReport}\n         * @private\n         */\n        this._avgLocalCameraPixels\n            = new AverageStatReport('pixels_local');\n\n        /**\n         * Average pixels for local screen streaming video (reported only if not\n         * a <tt>NaN</tt>).\n         * @type {AverageStatReport}\n         * @private\n         */\n        this._avgLocalScreenPixels\n            = new AverageStatReport('pixels_screen_local');\n\n        /**\n         * Average connection quality as defined by\n         * the {@link ConnectionQuality} module.\n         * @type {AverageStatReport}\n         * @private\n         */\n        this._avgCQ = new AverageStatReport('connection_quality');\n        this._cachedTransportStats = undefined;\n\n        this._onLocalStatsUpdated = (data: any) => {\n            this._calculateAvgStats(data);\n            this._maybeSendTransportAnalyticsEvent(data);\n        };\n        conference.on(\n            ConnectionQualityEvents.LOCAL_STATS_UPDATED,\n            this._onLocalStatsUpdated);\n\n        this._onP2PStatusChanged = () => {\n            logger.debug('Resetting average stats calculation');\n            this._resetAvgStats();\n            this.jvbStatsMonitor._resetAvgStats();\n            this.p2pStatsMonitor._resetAvgStats();\n        };\n        conference.on(\n            ConferenceEvents.P2P_STATUS,\n            this._onP2PStatusChanged);\n\n        this._onJvb121StatusChanged = activeSession => {\n\n            if (activeSession === conference.jvbJingleSession) {\n                logger.info('Resetting JVB avg RTP stats');\n                this._resetAvgJvbStats();\n            }\n        };\n        conference.on(\n            ConferenceEvents._MEDIA_SESSION_ACTIVE_CHANGED,\n            this._onJvb121StatusChanged);\n\n        this.jvbStatsMonitor\n            = new ConnectionAvgStats(this, false /* JVB */, n);\n\n        this.p2pStatsMonitor\n            = new ConnectionAvgStats(this, true /* P2P */, n);\n    }\n\n    /**\n     * Processes next batch of stats reported on\n     * {@link ConnectionQualityEvents.LOCAL_STATS_UPDATED}.\n     * @param {*} data\n     * @private\n     */\n    private _calculateAvgStats(data: any): void {\n\n        if (!data) {\n            logger.error('No stats');\n\n            return;\n        }\n\n        const isP2P = this._conference.isP2PActive();\n        const confSize = this._conference.getParticipantCount();\n\n        if (!isP2P && confSize < 2) {\n\n            // There's no point in collecting stats for a JVB conference of 1.\n            // That happens for short period of time after everyone leaves\n            // the room, until Jicofo terminates the session.\n            return;\n        }\n\n        /* Uncomment to figure out stats structure\n        for (const key in data) {\n            if (data.hasOwnProperty(key)) {\n                logger.info(`local stat ${key}: `, data[key]);\n            }\n        } */\n\n        const bitrate = data.bitrate;\n        const bandwidth = data.bandwidth;\n        const packetLoss = data.packetLoss;\n        const frameRate = data.framerate;\n        const resolution = data.resolution;\n\n        if (!bitrate) {\n            logger.error('No \"bitrate\"');\n\n            return;\n        } else if (!bandwidth) {\n            logger.error('No \"bandwidth\"');\n\n            return;\n        } else if (!packetLoss) {\n            logger.error('No \"packetloss\"');\n\n            return;\n        } else if (!frameRate) {\n            logger.error('No \"framerate\"');\n\n            return;\n        } else if (!resolution) {\n            logger.error('No resolution');\n\n            return;\n        }\n\n        this._avgAudioBitrateUp.addNext(bitrate.audio.upload);\n        this._avgAudioBitrateDown.addNext(bitrate.audio.download);\n\n        this._avgVideoBitrateUp.addNext(bitrate.video.upload);\n        this._avgVideoBitrateDown.addNext(bitrate.video.download);\n\n        if (browser.supportsBandwidthStatistics()) {\n            this._avgBandwidthUp.addNext(bandwidth.upload);\n            this._avgBandwidthDown.addNext(bandwidth.download);\n        }\n\n        this._avgPacketLossUp.addNext(packetLoss.upload);\n        this._avgPacketLossDown.addNext(packetLoss.download);\n        this._avgPacketLossTotal.addNext(packetLoss.total);\n\n        this._avgCQ.addNext(data.connectionQuality);\n\n        if (frameRate) {\n            this._avgRemoteFPS.addNext(\n                this._calculateAvgVideoFps(\n                    frameRate, false /* remote */, VideoType.CAMERA));\n            this._avgRemoteScreenFPS.addNext(\n                this._calculateAvgVideoFps(\n                    frameRate, false /* remote */, VideoType.DESKTOP));\n\n            this._avgLocalFPS.addNext(\n                this._calculateAvgVideoFps(\n                    frameRate, true /* local */, VideoType.CAMERA));\n            this._avgLocalScreenFPS.addNext(\n                this._calculateAvgVideoFps(\n                    frameRate, true /* local */, VideoType.DESKTOP));\n        }\n\n        if (resolution) {\n            this._avgRemoteCameraPixels.addNext(\n                this._calculateAvgVideoPixels(\n                    resolution, false /* remote */, VideoType.CAMERA));\n\n            this._avgRemoteScreenPixels.addNext(\n                this._calculateAvgVideoPixels(\n                    resolution, false /* remote */, VideoType.DESKTOP));\n\n            this._avgLocalCameraPixels.addNext(\n                this._calculateAvgVideoPixels(\n                    resolution, true /* local */, VideoType.CAMERA));\n\n            this._avgLocalScreenPixels.addNext(\n                this._calculateAvgVideoPixels(\n                    resolution, true /* local */, VideoType.DESKTOP));\n        }\n\n        this._sampleIdx += 1;\n\n        if (this._sampleIdx >= this._n) {\n            const batchReport: Record<string, unknown> = {\n                'conference_size': confSize,\n                p2p: isP2P\n            };\n\n            if (data.transport?.length) {\n                Object.assign(batchReport, {\n                    'local_candidate_type':\n                        data.transport[0].localCandidateType,\n                    'remote_candidate_type':\n                        data.transport[0].remoteCandidateType,\n                    'transport_type': data.transport[0].type\n                });\n            }\n\n            this._avgAudioBitrateUp.appendReport(batchReport);\n            this._avgAudioBitrateDown.appendReport(batchReport);\n\n            this._avgVideoBitrateUp.appendReport(batchReport);\n            this._avgVideoBitrateDown.appendReport(batchReport);\n\n            if (browser.supportsBandwidthStatistics()) {\n                this._avgBandwidthUp.appendReport(batchReport);\n                this._avgBandwidthDown.appendReport(batchReport);\n            }\n            this._avgPacketLossUp.appendReport(batchReport);\n            this._avgPacketLossDown.appendReport(batchReport);\n            this._avgPacketLossTotal.appendReport(batchReport);\n\n            this._avgRemoteFPS.appendReport(batchReport);\n            if (isValidNumber(this._avgRemoteScreenFPS.calculate())) {\n                this._avgRemoteScreenFPS.appendReport(batchReport);\n            }\n            this._avgLocalFPS.appendReport(batchReport);\n            if (isValidNumber(this._avgLocalScreenFPS.calculate())) {\n                this._avgLocalScreenFPS.appendReport(batchReport);\n            }\n\n            this._avgRemoteCameraPixels.appendReport(batchReport);\n            if (isValidNumber(this._avgRemoteScreenPixels.calculate())) {\n                this._avgRemoteScreenPixels.appendReport(batchReport);\n            }\n            this._avgLocalCameraPixels.appendReport(batchReport);\n            if (isValidNumber(this._avgLocalScreenPixels.calculate())) {\n                this._avgLocalScreenPixels.appendReport(batchReport);\n            }\n\n            this._avgCQ.appendReport(batchReport);\n\n            Statistics.sendAnalytics(createRtpStatsEvent(batchReport));\n\n            this._resetAvgStats();\n        }\n    }\n\n    /**\n     * Calculates average number of pixels for the report\n     *\n     * @param {map} peerResolutions a map of peer resolutions\n     * @param {boolean} isLocal if the average is to be calculated for the local\n     * video or <tt>false</tt> if for remote videos.\n     * @param {VideoType} videoType\n     * @return {number|NaN} average number of pixels or <tt>NaN</tt> if there\n     * are no samples.\n     * @private\n     */\n    private _calculateAvgVideoPixels(peerResolutions: Record<string, any>, isLocal: boolean, videoType: VideoType): number {\n        let peerPixelsSum = 0;\n        let peerCount = 0;\n        const myID = this._conference.myUserId();\n\n        for (const peerID of Object.keys(peerResolutions)) {\n            if (isLocal ? peerID === myID : peerID !== myID) {\n                const participant\n                    = isLocal\n                        ? null\n                        : this._conference.getParticipantById(peerID);\n                const videosResolution = peerResolutions[peerID];\n\n                // Do not continue without participant for non local peerID\n                if ((isLocal || participant) && videosResolution) {\n                    const peerAvgPixels = this._calculatePeerAvgVideoPixels(\n                        videosResolution, participant, videoType);\n\n                    if (isValidNumber(peerAvgPixels)) {\n                        peerPixelsSum += peerAvgPixels;\n                        peerCount += 1;\n                    }\n                }\n            }\n        }\n\n        return peerCount === 0 ? NaN : peerPixelsSum / peerCount;\n    }\n\n    /**\n     * Calculate average pixels for either remote or local participant\n     * @param {object} videos maps resolution per video SSRC\n     * @param {JitsiParticipant|null} participant remote participant or\n     * <tt>null</tt> for local video pixels calculation.\n     * @param {VideoType} videoType the type of the video for which an average\n     * will be calculated.\n     * @return {number|NaN} average video pixels of all participant's videos or\n     * <tt>NaN</tt> if currently not available\n     * @private\n     */\n    private _calculatePeerAvgVideoPixels(videos: Record<string, any>, participant: Nullable<JitsiParticipant>, videoType: VideoType): number {\n        let ssrcs = Object.keys(videos).map(ssrc => Number(ssrc));\n        let videoTracks: Nullable<JitsiLocalTrack[] | JitsiRemoteTrack[]> = null;\n\n        // NOTE that this method is supposed to be called for the stats\n        // received from the current peerconnection.\n        const tpc = this._conference.getActivePeerConnection();\n\n        if (participant) {\n            videoTracks = participant.getTracksByMediaType(MediaType.VIDEO);\n            if (videoTracks) {\n                ssrcs\n                    = ssrcs.filter(\n                        ssrc => videoTracks.find(\n                            track =>\n                                !track.isMuted()\n                                    && track.getSsrc() === ssrc\n                                    && track.videoType === videoType));\n            }\n        } else {\n            videoTracks = this._conference.getLocalTracks(MediaType.VIDEO);\n            ssrcs\n                = ssrcs.filter(\n                    ssrc => videoTracks.find(\n                        track =>\n                            !track.isMuted()\n                                && tpc.getLocalSSRC(track as JitsiLocalTrack) === ssrc\n                                && track.videoType === videoType));\n        }\n\n        let peerPixelsSum = 0;\n        let peerSsrcCount = 0;\n\n        for (const ssrc of ssrcs) {\n            const peerSsrcPixels\n                = Number(videos[ssrc].height) * Number(videos[ssrc].width);\n\n            // FPS is reported as 0 for users with no video\n            if (isValidNumber(peerSsrcPixels) && peerSsrcPixels > 0) {\n                peerPixelsSum += peerSsrcPixels;\n                peerSsrcCount += 1;\n            }\n        }\n\n        return peerSsrcCount === 0 ? NaN : peerPixelsSum / peerSsrcCount;\n    }\n\n    /**\n     * Calculates average FPS for the report\n     * @param {go figure} frameRate\n     * @param {boolean} isLocal if the average is to be calculated for the local\n     * video or <tt>false</tt> if for remote videos.\n     * @param {VideoType} videoType\n     * @return {number|NaN} average FPS or <tt>NaN</tt> if there are no samples.\n     * @private\n     */\n    private _calculateAvgVideoFps(frameRate: Record<string, any>, isLocal: boolean, videoType: VideoType): number {\n        let peerFpsSum = 0;\n        let peerCount = 0;\n        const myID = this._conference.myUserId();\n\n        for (const peerID of Object.keys(frameRate)) {\n            if (isLocal ? peerID === myID : peerID !== myID) {\n                const participant\n                    = isLocal\n                        ? null : this._conference.getParticipantById(peerID);\n                const videosFps = frameRate[peerID];\n\n                // Do not continue without participant for non local peerID\n                if ((isLocal || participant) && videosFps) {\n                    const peerAvgFPS\n                        = this._calculatePeerAvgVideoFps(\n                            videosFps, participant, videoType);\n\n                    if (isValidNumber(peerAvgFPS)) {\n                        peerFpsSum += peerAvgFPS;\n                        peerCount += 1;\n                    }\n                }\n            }\n        }\n\n        return peerCount === 0 ? NaN : peerFpsSum / peerCount;\n    }\n\n    /**\n     * Calculate average FPS for either remote or local participant\n     * @param {object} videos maps FPS per video SSRC\n     * @param {JitsiParticipant|null} participant remote participant or\n     * <tt>null</tt> for local FPS calculation.\n     * @param {VideoType} videoType the type of the video for which an average\n     * will be calculated.\n     * @return {number|NaN} average FPS of all participant's videos or\n     * <tt>NaN</tt> if currently not available\n     * @private\n     */\n    private _calculatePeerAvgVideoFps(videos: Record<string, any>, participant: Nullable<JitsiParticipant>, videoType: VideoType): number {\n        let ssrcs = Object.keys(videos).map(ssrc => Number(ssrc));\n        let videoTracks: Nullable<JitsiLocalTrack[] | JitsiRemoteTrack[]> = null;\n\n        // NOTE that this method is supposed to be called for the stats\n        // received from the current peerconnection.\n        const tpc = this._conference.getActivePeerConnection();\n\n        if (participant) {\n            videoTracks = participant.getTracksByMediaType(MediaType.VIDEO);\n            if (videoTracks) {\n                ssrcs\n                    = ssrcs.filter(\n                        ssrc => videoTracks.find(\n                            track => !track.isMuted()\n                                && track.getSsrc() === ssrc\n                                && track.videoType === videoType));\n            }\n        } else {\n            videoTracks = this._conference.getLocalTracks(MediaType.VIDEO);\n            ssrcs\n                = ssrcs.filter(\n                    ssrc => videoTracks.find(\n                        track => !track.isMuted()\n                            && tpc.getLocalSSRC(track as JitsiLocalTrack) === ssrc\n                            && track.videoType === videoType));\n        }\n\n        let peerFpsSum = 0;\n        let peerSsrcCount = 0;\n\n        for (const ssrc of ssrcs) {\n            const peerSsrcFps = Number(videos[ssrc]);\n\n            // FPS is reported as 0 for users with no video\n            if (isValidNumber(peerSsrcFps) && peerSsrcFps > 0) {\n                peerFpsSum += peerSsrcFps;\n                peerSsrcCount += 1;\n            }\n        }\n\n        return peerSsrcCount === 0 ? NaN : peerFpsSum / peerSsrcCount;\n    }\n\n    /**\n     * Sends the 'transport.stats' analytics event whenever we detect that\n     * there is a change in the local or remote candidate type on the transport\n     * that is currently selected.\n     * @param {*} data\n     * @private\n     */\n    private _maybeSendTransportAnalyticsEvent(data: any): void {\n        if (!data?.transport?.length) {\n            return;\n        }\n        const transportStats = {\n            'local_candidate_type': data.transport[0].localCandidateType,\n            'p2p': data.transport[0].p2p,\n            'remote_candidate_type': data.transport[0].remoteCandidateType,\n            'transport_type': data.transport[0].type\n        };\n\n        if (!this._cachedTransportStats || !isEqual(transportStats, this._cachedTransportStats)) {\n            this._cachedTransportStats = transportStats;\n            Statistics.sendAnalytics(createTransportStatsEvent(transportStats));\n        }\n    }\n\n    /**\n     * Resets the stats related to JVB connection. Must not be called when in\n     * P2P mode, because then the {@link AverageStatReport} instances are\n     * tracking P2P stats. Note that this should never happen unless something\n     * is wrong with the P2P and JVB121 events.\n     * @private\n     */\n    private _resetAvgJvbStats(): void {\n        this._resetAvgStats();\n        this.jvbStatsMonitor._resetAvgStats();\n    }\n\n    /**\n     * Reset cache of all averages and {@link _sampleIdx}.\n     * @private\n     */\n    private _resetAvgStats(): void {\n        this._avgAudioBitrateUp.reset();\n        this._avgAudioBitrateDown.reset();\n\n        this._avgVideoBitrateUp.reset();\n        this._avgVideoBitrateDown.reset();\n\n        this._avgBandwidthUp.reset();\n        this._avgBandwidthDown.reset();\n\n        this._avgPacketLossUp.reset();\n        this._avgPacketLossDown.reset();\n        this._avgPacketLossTotal.reset();\n\n        this._avgRemoteFPS.reset();\n        this._avgRemoteScreenFPS.reset();\n        this._avgLocalFPS.reset();\n        this._avgLocalScreenFPS.reset();\n\n        this._avgRemoteCameraPixels.reset();\n        this._avgRemoteScreenPixels.reset();\n        this._avgLocalCameraPixels.reset();\n        this._avgLocalScreenPixels.reset();\n\n        this._avgCQ.reset();\n\n        this._sampleIdx = 0;\n    }\n\n    /**\n     * Unregisters all event listeners and stops working.\n     */\n    public dispose(): void {\n        this._conference.off(\n            ConferenceEvents.P2P_STATUS,\n            this._onP2PStatusChanged);\n        this._conference.off(\n            ConnectionQualityEvents.LOCAL_STATS_UPDATED,\n            this._onLocalStatsUpdated);\n        this._conference.off(\n            ConferenceEvents._MEDIA_SESSION_ACTIVE_CHANGED,\n            this._onJvb121StatusChanged);\n        this.jvbStatsMonitor.dispose();\n        this.p2pStatsMonitor.dispose();\n    }\n}\n","/**\n * Interface for face landmarks.\n */\nexport interface IFaceLandmarks {\n    duration: number;\n    faceExpression: string;\n}\n\n/**\n * A model for keeping track of each user's total\n * time as a dominant speaker. The model also\n * keeps track of the user's last known name\n * in case the user has left the meeting,\n * which is also tracked.\n */\nclass SpeakerStats {\n    private _userId: string;\n    private displayName: string;\n    private _isLocalStats: boolean;\n    private totalDominantSpeakerTime: number;\n    private _dominantSpeakerStart: number;\n    private _isDominantSpeaker: boolean;\n    private _isSilent: boolean;\n    private _hasLeft: boolean;\n    private _faceLandmarks: IFaceLandmarks[];\n\n    /**\n     * Initializes a new SpeakerStats instance.\n     *\n     * @constructor\n     * @param {string} userId - The id of the user being tracked.\n     * @param {string} displayName - The name of the user being tracked.\n     * @param {boolean} isLocalStats - True if the stats model tracks\n     * the local user.\n     * @returns {void}\n     */\n    constructor(userId: string, displayName: string, isLocalStats: boolean) {\n        this._userId = userId;\n        this.setDisplayName(displayName);\n        this._isLocalStats = isLocalStats || false;\n        this.setDominantSpeaker(false, false);\n        this.totalDominantSpeakerTime = 0;\n        this._dominantSpeakerStart = 0;\n        this._isDominantSpeaker = false;\n        this._isSilent = false;\n        this._hasLeft = false;\n        this._faceLandmarks = [];\n    }\n\n    /**\n     * Get the user id being tracked.\n     *\n     * @returns {string} The user id.\n     */\n    getUserId(): string {\n        return this._userId;\n    }\n\n    /**\n     * Get the name of the user being tracked.\n     *\n     * @returns {string} The user name.\n     */\n    getDisplayName(): string {\n        return this.displayName;\n    }\n\n    /**\n     * Updates the last known name of the user being tracked.\n     *\n     * @param {string} newName - The user name.\n     * @returns {void}\n     */\n    setDisplayName(newName: string): void {\n        this.displayName = newName;\n    }\n\n    /**\n     * Returns true if the stats are tracking the local user.\n     *\n     * @returns {boolean}\n     */\n    isLocalStats(): boolean {\n        return this._isLocalStats;\n    }\n\n    /**\n     * Returns true if the tracked user is currently a dominant speaker.\n     *\n     * @returns {boolean}\n     */\n    isDominantSpeaker(): boolean {\n        return this._isDominantSpeaker;\n    }\n\n    /**\n     * Returns true if the tracked user is currently a dominant speaker.\n     *\n     * @param {boolean} isNowDominantSpeaker - If true, the user will be accumulating time\n     * as dominant speaker. If false, the user will not accumulate time\n     * and will record any time accumulated since starting as dominant speaker.\n     * @param {boolean} silence - Indicates whether the dominant speaker is silent or not.\n     * @returns {void}\n     */\n    setDominantSpeaker(isNowDominantSpeaker: boolean, silence: boolean): void {\n        if (!this.isDominantSpeaker() && isNowDominantSpeaker && !silence) {\n            this._dominantSpeakerStart = Date.now();\n        } else if (this.isDominantSpeaker()) {\n            if (!isNowDominantSpeaker) {\n                if (!this._isSilent) {\n                    const now = Date.now();\n                    const timeElapsed = now - this._dominantSpeakerStart;\n\n                    this.totalDominantSpeakerTime += timeElapsed;\n                    this._dominantSpeakerStart = 0;\n                }\n            } else if (this._isSilent && !silence) {\n                this._dominantSpeakerStart = Date.now();\n            } else if (!this._isSilent && silence) {\n                const now = Date.now();\n                const timeElapsed = now - this._dominantSpeakerStart;\n\n                this.totalDominantSpeakerTime += timeElapsed;\n                this._dominantSpeakerStart = 0;\n            }\n        }\n\n        this._isDominantSpeaker = isNowDominantSpeaker;\n        this._isSilent = silence;\n    }\n\n    /**\n     * Get how long the tracked user has been dominant speaker.\n     *\n     * @returns {number} - The speaker time in milliseconds.\n     */\n    getTotalDominantSpeakerTime(): number {\n        let total = this.totalDominantSpeakerTime;\n\n        if (this.isDominantSpeaker() && !this._isSilent) {\n            total += Date.now() - this._dominantSpeakerStart;\n        }\n\n        return total;\n    }\n\n    /**\n     * Get whether or not the user is still in the meeting.\n     *\n     * @returns {boolean} True if the user is no longer in the meeting.\n     */\n    hasLeft(): boolean {\n        return this._hasLeft;\n    }\n\n    /**\n     * Set the user as having left the meeting.\n     *\n     * @returns {void}\n     */\n    markAsHasLeft(): void {\n        this._hasLeft = true;\n        this.setDominantSpeaker(false, false);\n    }\n\n    /**\n     * Gets the face landmarks of the user.\n     *\n     * @returns {IFaceLandmarks[]}\n     */\n    getFaceLandmarks(): IFaceLandmarks[] {\n        return this._faceLandmarks;\n    }\n\n    /**\n     * Sets the face landmarks of the user.\n     *\n     * @param {IFaceLandmarks[]} faceLandmarks - object with face expressions.\n     * @returns {void}\n     */\n    setFaceLandmarks(faceLandmarks: IFaceLandmarks[]): void {\n        this._faceLandmarks = faceLandmarks;\n    }\n\n    /**\n     * Adds new face landmarks to speaker stats.\n     *\n     * @param  {IFaceLandmarks} faceLandmarks\n     */\n    addFaceLandmarks(faceLandmarks: IFaceLandmarks): void {\n        this._faceLandmarks.push(faceLandmarks);\n    }\n}\n\nexport default SpeakerStats;\n","import JitsiConference from '../../JitsiConference';\nimport { JitsiConferenceEvents } from '../../JitsiConferenceEvents';\nimport JitsiParticipant from '../../JitsiParticipant';\nimport { XMPPEvents } from '../../service/xmpp/XMPPEvents';\n\nimport { type IFaceLandmarks, default as SpeakerStats } from './SpeakerStats';\n\n/**\n * The value to use for the \"type\" field for messages sent\n * over the data channel that contain a face landmark.\n */\n\nconst FACE_LANDMARK_MESSAGE_TYPE = 'face-landmarks';\n\nexport interface ISpeakerStatsState {\n    dominantSpeakerId: Nullable<string>;\n    users: {\n        [userId: string]: SpeakerStats;\n    };\n}\n\nexport interface IFaceLandmarkMessage {\n    faceLandmarks: IFaceLandmarks;\n    type: string;\n}\n\n/**\n * A collection for tracking speaker stats. Attaches listeners\n * to the conference to automatically update on tracked events.\n */\nexport default class SpeakerStatsCollector {\n    stats: ISpeakerStatsState;\n    conference: JitsiConference;\n\n    /**\n     * Initializes a new SpeakerStatsCollector instance.\n     *\n     * @constructor\n     * @param {JitsiConference} conference - The conference to track.\n     * @returns {void}\n     */\n    constructor(conference: JitsiConference) {\n        this.stats = {\n            dominantSpeakerId: null,\n            users: {\n\n                // userId: SpeakerStats\n            }\n        };\n\n        const userId = conference.myUserId();\n\n        this.stats.users[userId] = new SpeakerStats(userId, null, true);\n        this.conference = conference;\n\n        conference.addEventListener(\n            JitsiConferenceEvents.DOMINANT_SPEAKER_CHANGED,\n            this._onDominantSpeaker.bind(this));\n        conference.addEventListener(\n            JitsiConferenceEvents.USER_JOINED,\n            this._onUserJoin.bind(this));\n        conference.addEventListener(\n            JitsiConferenceEvents.USER_LEFT,\n            this._onUserLeave.bind(this));\n        conference.addEventListener(\n            JitsiConferenceEvents.DISPLAY_NAME_CHANGED,\n            this._onDisplayNameChange.bind(this));\n\n        conference.on(\n            JitsiConferenceEvents.ENDPOINT_MESSAGE_RECEIVED,\n                (participant: JitsiParticipant, { type, faceLandmarks }: IFaceLandmarkMessage) => {\n                    if (type === FACE_LANDMARK_MESSAGE_TYPE) {\n                        this._onFaceLandmarkAdd(participant.getId(), faceLandmarks);\n                    }\n                });\n        if (conference.xmpp) {\n            conference.xmpp.addListener(\n                XMPPEvents.SPEAKER_STATS_RECEIVED,\n                this._updateStats.bind(this));\n        }\n    }\n\n    /**\n     * Reacts to dominant speaker change events by changing its speaker stats\n     * models to reflect the current dominant speaker.\n     *\n     * @param {string} dominantSpeakerId - The user id of the new dominant speaker.\n     * @param {Array[string]} previous - The array with previous speakers.\n     * @param {boolean} silence - Indecates whether the dominant speaker is silent or not.\n     * @returns {void}\n     * @private\n     */\n    _onDominantSpeaker(dominantSpeakerId: string, previous: string[], silence: boolean): void {\n        const oldDominantSpeaker\n            = this.stats.users[this.stats.dominantSpeakerId as string];\n        const newDominantSpeaker = this.stats.users[dominantSpeakerId];\n\n        oldDominantSpeaker?.setDominantSpeaker(false, false);\n        newDominantSpeaker?.setDominantSpeaker(true, silence);\n        this.stats.dominantSpeakerId = dominantSpeakerId;\n    }\n\n    /**\n     * Reacts to user join events by creating a new SpeakerStats model.\n     *\n     * @param {string} userId - The user id of the new user.\n     * @param {JitsiParticipant} - The JitsiParticipant model for the new user.\n     * @returns {void}\n     * @private\n     */\n    _onUserJoin(userId: string, participant: JitsiParticipant): void {\n        if (participant.isHidden()) {\n            return;\n        }\n\n        if (!this.stats.users[userId]) {\n            this.stats.users[userId] = new SpeakerStats(userId, participant.getDisplayName(), false);\n        }\n    }\n\n    /**\n     * Reacts to user leave events by updating the associated user's\n     * SpeakerStats model.\n     *\n     * @param {string} userId - The user id of the user that left.\n     * @returns {void}\n     * @private\n     */\n    _onUserLeave(userId: string): void {\n        const savedUser = this.stats.users[userId];\n\n        if (savedUser) {\n            savedUser.markAsHasLeft();\n        }\n    }\n\n    /**\n     * Reacts to user name change events by updating the last known name\n     * tracked in the associated SpeakerStats model.\n     *\n     * @param {string} userId - The user id of the user that left.\n     * @returns {void}\n     * @private\n     */\n    _onDisplayNameChange(userId: string, newName: string): void {\n        const savedUser = this.stats.users[userId];\n\n        if (savedUser) {\n            savedUser.setDisplayName(newName);\n        }\n    }\n\n    /**\n     * Processes a new face landmark object of a remote user.\n     *\n     * @param {string} userId - The user id of the user that left.\n     * @param {IFaceLandmarks} data - The face landmark object.\n     * @returns {void}\n     * @private\n     */\n    _onFaceLandmarkAdd(userId: string, data: IFaceLandmarks): void {\n        const savedUser = this.stats.users[userId];\n\n        if (savedUser && data) {\n            savedUser.addFaceLandmarks(data);\n        }\n    }\n\n    /**\n     * Return a copy of the tracked SpeakerStats models.\n     *\n     * @returns {Object} The keys are the user ids and the values are the\n     * associated user's SpeakerStats model.\n     */\n    getStats(): { [userId: string]: SpeakerStats; } {\n        return this.stats.users;\n    }\n\n    /**\n     * Updates of the current stats is requested, passing the new values.\n     *\n     * @param {Object} newStats - The new values used to update current one.\n     * @private\n     */\n    _updateStats(newStats: { [userId: string]: any; }): void {\n        for (const userId in newStats) { // eslint-disable-line guard-for-in\n            let speakerStatsToUpdate;\n            const newParticipant = this.conference.getParticipantById(userId);\n\n            // we want to ignore hidden participants\n            if (!newParticipant?.isHidden()) {\n                if (this.stats.users[userId]) {\n                    speakerStatsToUpdate = this.stats.users[userId];\n\n                    if (!speakerStatsToUpdate.getDisplayName()) {\n                        speakerStatsToUpdate\n                            .setDisplayName(newStats[userId].displayName);\n                    }\n                } else {\n                    speakerStatsToUpdate = new SpeakerStats(\n                        userId, newStats[userId].displayName, false);\n                    this.stats.users[userId] = speakerStatsToUpdate;\n                    speakerStatsToUpdate.markAsHasLeft();\n                }\n\n                speakerStatsToUpdate.totalDominantSpeakerTime\n                    = newStats[userId].totalDominantSpeakerTime;\n\n                if (Array.isArray(newStats[userId].faceLandmarks)) {\n                    speakerStatsToUpdate.setFaceLandmarks(newStats[userId].faceLandmarks);\n                }\n            }\n        }\n    }\n}\n","import { getLogger } from '@jitsi/logger';\n\nimport JitsiConference from '../../JitsiConference';\n\nconst logger = getLogger('misc:ComponentsVersions');\n\n/**\n * Discovers component versions in a conference.\n */\nexport default class ComponentsVersions {\n    versions: { [key: string]: string; };\n    conference: JitsiConference;\n\n    /**\n     * Creates new instance of <tt>ComponentsVersions</tt> which will be discovering\n     * the versions of conferencing system components in given\n     * <tt>JitsiConference</tt>.\n     * @param conference <tt>JitsiConference</tt> instance which will be used to\n     *        listen for focus presence updates.\n     * @constructor\n     */\n    constructor(conference) {\n        this.versions = {};\n\n        this.conference = conference;\n        this.conference.addCommandListener('versions', this._processVersions.bind(this));\n    }\n\n    /**\n     * Processes versions information from presence.\n     *\n     * @param {*} versions - The versions element.\n     * @param {*} mucJid - MUC JID for the sender.\n     * @returns {void}\n     */\n    _processVersions(versions, _, mucJid) {\n        if (!this.conference.isFocus(mucJid)) {\n            logger.warn(\n                `Received versions not from the focus user: ${versions}`,\n                mucJid);\n\n            return;\n        }\n\n        versions.children.forEach(component => {\n            const name = component.attributes.name;\n            const version = component.value;\n\n            if (this.versions[name] !== version) {\n                this.versions[name] = version;\n                logger.info(`Got ${name} version: ${version}`);\n            }\n        });\n    }\n\n    /**\n     * Obtains the version of conferencing system component.\n     * @param componentName the name of the component for which we want to obtain\n     *        the version.\n     * @returns {String} which describes the version of the component identified by\n     *          given <tt>componentName</tt> or <tt>undefined</tt> if not found.\n     */\n    getComponentVersion(componentName) {\n        return this.versions[componentName];\n    }\n}\n","export enum VideoSIPGWStatusConstants {\n\n    /**\n     * Status that video SIP GW service is available.\n     */\n    STATUS_AVAILABLE = 'available',\n\n    /**\n     * Status that video SIP GW service is available but there are no free nodes\n     * at the moment to serve new requests.\n     */\n    STATUS_BUSY = 'busy',\n\n    /**\n     * Status that video SIP GW service is not available.\n     */\n    STATUS_UNDEFINED = 'undefined'\n}\n\nexport enum VideoSIPGWStateConstants {\n\n    /**\n     * Video SIP GW session state, tried to start but it failed.\n     */\n    STATE_FAILED = 'failed',\n\n    /**\n     * Video SIP GW session state, currently stopped and not running.\n     */\n    STATE_OFF = 'off',\n\n    /**\n     * Video SIP GW session state, currently running.\n     */\n    STATE_ON = 'on',\n\n    /**\n     * Video SIP GW session state, currently is starting.\n     */\n    STATE_PENDING = 'pending',\n\n    /**\n     * Video SIP GW session state, has observed some issues and is retrying at the\n     * moment.\n     */\n    STATE_RETRYING = 'retrying'\n}\n\nexport enum VideoSIPGWErrorConstants {\n\n    /**\n     * Error on trying to create video SIP GW session in conference where\n     * there is no room connection (hasn't joined or has left the room).\n     */\n    ERROR_NO_CONNECTION = 'error_no_connection',\n\n    /**\n     * Error on trying to create video SIP GW session with address for which\n     * there is an already created session.\n     */\n    ERROR_SESSION_EXISTS = 'error_session_already_exists'\n}\n\n// exported for backward compatibility\nexport const STATUS_AVAILABLE = VideoSIPGWStatusConstants.STATUS_AVAILABLE;\nexport const STATUS_UNDEFINED = VideoSIPGWStatusConstants.STATUS_UNDEFINED;\nexport const STATUS_BUSY = VideoSIPGWStatusConstants.STATUS_BUSY;\n\nexport const STATE_ON = VideoSIPGWStateConstants.STATE_ON;\nexport const STATE_OFF = VideoSIPGWStateConstants.STATE_OFF;\nexport const STATE_PENDING = VideoSIPGWStateConstants.STATE_PENDING;\nexport const STATE_RETRYING = VideoSIPGWStateConstants.STATE_RETRYING;\nexport const STATE_FAILED = VideoSIPGWStateConstants.STATE_FAILED;\n\nexport const ERROR_NO_CONNECTION = VideoSIPGWErrorConstants.ERROR_NO_CONNECTION;\nexport const ERROR_SESSION_EXISTS = VideoSIPGWErrorConstants.ERROR_SESSION_EXISTS;\n","import { getLogger } from '@jitsi/logger';\nimport { $iq } from 'strophe.js';\n\nimport Listenable from '../util/Listenable';\nimport ChatRoom from '../xmpp/ChatRoom';\nimport { handleStropheError } from '../xmpp/StropheErrorHandler';\n\nimport * as VideoSIPGWConstants from './VideoSIPGWConstants';\n\nconst logger = getLogger('videosipgw:JitsiVideoSIPGWSession');\n\n/**\n * The event name for current sip video session state changed.\n * @type {string} event name for sip video session state changed.\n */\nconst STATE_CHANGED: string = 'STATE_CHANGED';\n\n/**\n * Jitsi video SIP GW session. Holding its state and able to start/stop it.\n * When session is in OFF or FAILED stated it cannot be used anymore.\n */\nexport default class JitsiVideoSIPGWSession extends Listenable {\n    sipAddress: string;\n    displayName: string;\n    chatRoom: ChatRoom;\n    state?: string;\n\n    /**\n     * Creates new session with the desired sip address and display name.\n     *\n     * @param {string} sipAddress - The sip address to use when\n     * starting the session.\n     * @param {string} displayName - The display name to use for\n     * that participant.\n     * @param {ChatRoom} chatRoom - The chat room this session is bound to.\n     */\n    constructor(sipAddress: string, displayName: string, chatRoom: ChatRoom) {\n        super();\n\n        this.sipAddress = sipAddress;\n        this.displayName = displayName;\n        this.chatRoom = chatRoom;\n\n        /*\n         * The initial state is undefined. Initial state cannot be STATE_OFF,\n         * the session enters this state when it was in STATE_ON and was stopped\n         * and such session cannot be used anymore.\n         *\n         * @type {VideoSIPGWConstants|undefined}\n         */\n        this.state = undefined;\n    }\n\n    /**\n     * Sends a jibri command using an iq.\n     *\n     * @private\n     * @param {string} action - The action to send ('start' or 'stop').\n     */\n    private _sendJibriIQ(action: string): void {\n        const attributes = {\n            'action': action,\n            'displayname': this.displayName,\n            'sipaddress': this.sipAddress,\n            'xmlns': 'http://jitsi.org/protocol/jibri'\n        };\n\n        const iq = $iq({\n            to: this.chatRoom.focusMucJid,\n            type: 'set' })\n            .c('jibri', attributes)\n            .up();\n\n        logger.debug(`${action} video SIP GW session`, iq.nodeTree);\n        this.chatRoom.connection.sendIQ(\n            iq,\n            () => {}, // eslint-disable-line @typescript-eslint/no-empty-function\n            (error: any) => {\n                handleStropheError(error, {\n                    operation: `${action} video SIP GW session`,\n                    roomJid: this.chatRoom.roomjid,\n                    sipAddress: this.sipAddress,\n                    userJid: this.chatRoom.connection.jid\n                });\n                this.setState(VideoSIPGWConstants.STATE_FAILED);\n            },\n            undefined);\n    }\n\n    /**\n     * Stops the current session.\n     */\n    stop(): void {\n        if (this.state === VideoSIPGWConstants.STATE_OFF\n            || this.state === VideoSIPGWConstants.STATE_FAILED) {\n            logger.warn('Video SIP GW session already stopped or failed!');\n\n            return;\n        }\n\n        this._sendJibriIQ('stop');\n    }\n\n    /**\n     * Starts a new session. Sends an iq to the focus.\n     */\n    start(): void {\n        // if state is off, this session was active for some reason\n        // and we should create new one, rather than reusing it\n        if (this.state === VideoSIPGWConstants.STATE_ON\n            || this.state === VideoSIPGWConstants.STATE_OFF\n            || this.state === VideoSIPGWConstants.STATE_PENDING\n            || this.state === VideoSIPGWConstants.STATE_RETRYING) {\n            logger.warn('Video SIP GW session already started!');\n\n            return;\n        }\n\n        this._sendJibriIQ('start');\n    }\n\n    /**\n     * Changes the state of this session.\n     *\n     * @param {string} newState - The new {VideoSIPGWConstants} state to set.\n     * @param {string} [optional] failureReason - The reason why a failure state\n     * was entered.\n     * @returns {void}\n     */\n    setState(newState: string, failureReason?: string): void {\n        if (newState === this.state) {\n            return;\n        }\n\n        const oldState = this.state;\n\n        this.state = newState;\n        this.eventEmitter.emit(STATE_CHANGED,\n            {\n                address: this.sipAddress,\n                displayName: this.displayName,\n                failureReason,\n                newState: this.state,\n                oldState\n            }\n        );\n    }\n\n    /**\n     * Subscribes the passed listener to the event for state change of this\n     * session.\n     *\n     * @param {EventListener} listener - The function that will receive the event.\n     */\n    addStateListener(listener: EventListener): void {\n        this.addListener(STATE_CHANGED, listener);\n    }\n\n    /**\n     * Unsubscribes the passed handler.\n     *\n     * @param {EventListener} listener - The function to be removed.\n     */\n    removeStateListener(listener: EventListener): void {\n        this.removeListener(STATE_CHANGED, listener);\n    }\n}\n","import { getLogger } from '@jitsi/logger';\nconst logger = getLogger('videosipgw:VideoSIPGW');\n\nimport { XMPPEvents } from '../../service/xmpp/XMPPEvents';\nimport EventEmitter from '../util/EventEmitter';\nimport ChatRoom from '../xmpp/ChatRoom';\n\nimport JitsiVideoSIPGWSession from './JitsiVideoSIPGWSession';\nimport * as Constants from './VideoSIPGWConstants';\n\n\nexport interface ISessionStateChangeEvent {\n    address: string;\n    displayName?: string;\n    newState: string;\n    oldState?: string;\n}\n\nexport interface INodeAttributes {\n    failure_reason?: string;\n    sipaddress?: string;\n    state: string;\n}\n\n/**\n * Main video SIP GW handler. Stores references of all created sessions.\n */\nexport default class VideoSIPGW {\n    private chatRoom: ChatRoom;\n    private eventEmitter: EventEmitter;\n    private sessions: Record<string, JitsiVideoSIPGWSession>;\n    private sessionStateChangeListener: (event: ISessionStateChangeEvent) => void;\n    private state?: string;\n\n    /**\n     * Creates new handler.\n     *\n     * @param {ChatRoom} chatRoom - Tha chat room to handle.\n     */\n    constructor(chatRoom: ChatRoom) {\n        this.chatRoom = chatRoom;\n        this.eventEmitter = chatRoom.eventEmitter;\n        logger.debug('creating VideoSIPGW');\n        this.sessions = {};\n\n        this.sessionStateChangeListener = this.sessionStateChanged.bind(this);\n\n        // VideoSIPGW, JitsiConference and ChatRoom are not reusable and no\n        // more than one VideoSIPGW can be created per JitsiConference,\n        // so we don't bother to cleanup\n        chatRoom.addPresenceListener('jibri-sip-call-state',\n            this.handleJibriSIPState.bind(this));\n    }\n\n    /**\n     * Handles presence nodes with name: jibri-sip-call-state.\n     *\n     * @param {Object} node the presence node Object to handle.\n     * Object representing part of the presence received over xmpp.\n     */\n    handleJibriSIPState(node: { attributes?: INodeAttributes; }): void {\n        const attributes = node.attributes;\n\n        if (!attributes) {\n            return;\n        }\n\n        logger.debug('Handle video sip gw state : ', attributes);\n\n        const newState = attributes.state;\n\n        if (newState === this.state) {\n            return;\n        }\n\n        switch (newState) {\n        case Constants.STATE_ON:\n        case Constants.STATE_OFF:\n        case Constants.STATE_PENDING:\n        case Constants.STATE_RETRYING:\n        case Constants.STATE_FAILED: {\n            const address = attributes.sipaddress;\n\n            if (!address) {\n                return;\n            }\n\n            // find the corresponding session and set its state\n            const session = this.sessions[address];\n\n            if (session) {\n                session.setState(newState, attributes.failure_reason);\n            } else {\n                logger.warn('Video SIP GW session not found:', address);\n            }\n        }\n        }\n    }\n\n    /**\n     * Creates new session and stores its reference if it does not exist or\n     * returns an error otherwise.\n     *\n     * @param {string} sipAddress - The sip address to use.\n     * @param {string} displayName - The display name to use.\n     * @returns {JitsiVideoSIPGWSession|Error}\n     */\n    createVideoSIPGWSession(sipAddress: string, displayName: string): JitsiVideoSIPGWSession | Error {\n        if (this.sessions[sipAddress]) {\n            logger.warn('There was already a Video SIP GW session for address',\n                sipAddress);\n\n            return new Error(Constants.ERROR_SESSION_EXISTS);\n        }\n\n        const session = new JitsiVideoSIPGWSession(\n            sipAddress, displayName, this.chatRoom);\n\n        session.addStateListener(this.sessionStateChangeListener as unknown as EventListener);\n\n        this.sessions[sipAddress] = session;\n\n        return session;\n    }\n\n    /**\n     * Listener for session state changed. When a session goes to off or failed\n     * we delete its reference.\n     *\n     * @param {options} event - { address, oldState, newState, displayName }\n     */\n    sessionStateChanged(event: ISessionStateChangeEvent): void {\n        const address = event.address;\n\n        if (event.newState === Constants.STATE_OFF\n            || event.newState === Constants.STATE_FAILED) {\n            const session = this.sessions[address];\n\n            if (!session) {\n                logger.error('Missing Video SIP GW session with address:',\n                    address);\n\n                return;\n            }\n\n            session.removeStateListener(this.sessionStateChangeListener as unknown as EventListener);\n            delete this.sessions[address];\n        }\n\n        this.eventEmitter.emit(\n            XMPPEvents.VIDEO_SIP_GW_SESSION_STATE_CHANGED,\n            event);\n    }\n}\n","import { safeJsonParse } from '@jitsi/js-utils/json';\nimport { getLogger } from '@jitsi/logger';\nimport { Strophe } from 'strophe.js';\n\nimport { MediaType } from '../../service/RTC/MediaType';\nimport { SignalingEvents } from '../../service/RTC/SignalingEvents';\nimport SignalingLayer, { EndpointId, IPeerMediaInfo, ISourceInfo, SourceName, getEndpointIdFromSourceName, getMediaTypeFromSourceName } from '../../service/RTC/SignalingLayer';\nimport { VideoType } from '../../service/RTC/VideoType';\nimport { XMPPEvents } from '../../service/xmpp/XMPPEvents';\nimport FeatureFlags from '../flags/FeatureFlags';\n\nimport ChatRoom, { filterNodeFromPresenceJSON } from './ChatRoom';\n\n\nconst logger = getLogger('xmpp:SignalingLayerImpl');\n\nexport const SOURCE_INFO_PRESENCE_ELEMENT = 'SourceInfo';\n\nexport interface IPresenceNode {\n    [key: string]: any;\n    tagName: string;\n    value?: string; // for other possible properties\n}\n\n/**\n * Default XMPP implementation of the {@link SignalingLayer} interface. Obtains\n * the data from the MUC presence.\n */\nexport default class SignalingLayerImpl extends SignalingLayer {\n    /**\n     * A map that stores SSRCs of remote streams and the corresponding jid and source name.\n     * @type {Map<number, { endpointId: EndpointId, sourceName: SourceName }>}\n     */\n    private _ssrcOwners: Map<number, { endpointId: EndpointId; sourceName: SourceName; }>;\n\n    /**\n     * @type {ChatRoom|null}\n     */\n    private _chatRoom?: ChatRoom;\n\n    /**\n     * @type {Record<SourceName, Partial<ISourceInfo>>}\n     * @private\n     */\n    private _localSourceState: Record<SourceName, Partial<ISourceInfo>>;\n\n    /**\n     * @type {Record<EndpointId, Record<SourceName, ISourceInfo>>}\n     * @private\n     */\n    private _remoteSourceState: Record<EndpointId, Record<SourceName, ISourceInfo>>;\n\n    // Event handler references for cleanup\n    private _audioMuteHandler?: (node: IPresenceNode, from: string) => void;\n    private _videoMuteHandler?: (node: IPresenceNode, from: string) => void;\n    private _videoTypeHandler?: (node: IPresenceNode, from: string) => void;\n    private _sourceInfoHandler?: (node: IPresenceNode, mucNick: string) => void;\n    private _memberLeftHandler?: (jid: string) => void;\n\n    /**\n     * Creates new instance.\n     */\n    constructor() {\n        super();\n\n        this._ssrcOwners = new Map();\n        this._chatRoom = null;\n        this._localSourceState = { };\n        this._remoteSourceState = { };\n\n    }\n\n    /**\n     * Adds <SourceInfo> element to the local presence.\n     *\n     * @returns {boolean}\n     * @private\n     */\n    private _addLocalSourceInfoToPresence(): boolean {\n        if (this._chatRoom) {\n            return this._chatRoom.addOrReplaceInPresence(\n                SOURCE_INFO_PRESENCE_ELEMENT,\n                { value: JSON.stringify(this._localSourceState) });\n        }\n\n        return false;\n    }\n\n    /**\n     * Binds event listeners to the chat room instance.\n     * @param {ChatRoom} room\n     * @private\n     * @returns {void}\n     */\n    private _bindChatRoomEventHandlers(room: ChatRoom): void {\n        // Add handlers for 'audiomuted', 'videomuted' and 'videoType' fields in presence in order to support interop\n        // with very old versions of mobile clients and jigasi that do not support source-name signaling.\n        const emitAudioMutedEvent = (endpointId: string, muted: boolean) => {\n            this.eventEmitter.emit(\n                SignalingEvents.PEER_MUTED_CHANGED,\n                endpointId,\n                MediaType.AUDIO,\n                muted);\n        };\n\n        this._audioMuteHandler = (node: IPresenceNode, from: string) => {\n            if (!this._doesEndpointSendNewSourceInfo(from)) {\n                emitAudioMutedEvent(from, node.value === 'true');\n            }\n        };\n        room.addPresenceListener('audiomuted', this._audioMuteHandler);\n\n        const emitVideoMutedEvent = (endpointId: string, muted: boolean) => {\n            this.eventEmitter.emit(\n                SignalingEvents.PEER_MUTED_CHANGED,\n                endpointId,\n                MediaType.VIDEO,\n                muted);\n        };\n\n        this._videoMuteHandler = (node: IPresenceNode, from: string) => {\n            if (!this._doesEndpointSendNewSourceInfo(from)) {\n                emitVideoMutedEvent(from, node.value === 'true');\n            }\n        };\n        room.addPresenceListener('videomuted', this._videoMuteHandler);\n\n        const emitVideoTypeEvent = (endpointId: string, videoType: string) => {\n            this.eventEmitter.emit(\n                SignalingEvents.PEER_VIDEO_TYPE_CHANGED,\n                endpointId, videoType);\n        };\n\n        this._videoTypeHandler = (node: IPresenceNode, from: string) => {\n            if (!this._doesEndpointSendNewSourceInfo(from)) {\n                emitVideoTypeEvent(from, node.value);\n            }\n        };\n        room.addPresenceListener('videoType', this._videoTypeHandler);\n\n        // Add handlers for presence in the new format.\n        this._sourceInfoHandler = (node: IPresenceNode, mucNick: string) => {\n            const endpointId = mucNick;\n            const { value } = node;\n            const sourceInfoJSON = safeJsonParse(value);\n            const emitEventsFromHere = this._doesEndpointSendNewSourceInfo(endpointId);\n            const endpointSourceState = this._remoteSourceState[endpointId] || (this._remoteSourceState[endpointId] = {});\n            const negotiatedOwners = new Map<SourceName, EndpointId>();\n\n            for (const owner of this._ssrcOwners.values()) {\n                negotiatedOwners.set(owner.sourceName, owner.endpointId);\n            }\n\n            for (const sourceName of Object.keys(sourceInfoJSON)) {\n                let owner;\n\n                try {\n                    owner = getEndpointIdFromSourceName(sourceName);\n                } catch (e) {\n                    // Malformed name in untrusted presence: skip this entry, keep processing the rest.\n                    logger.warn(`Ignoring SourceInfo with invalid source name: ${sourceName}`);\n                    continue;\n                }\n\n                const negotiatedOwner = negotiatedOwners.get(sourceName);\n\n                // A sender may only advertise state for sources it owns. A not-yet-negotiated source has no\n                // negotiated owner and relies on the source name check alone.\n                if (owner !== endpointId || (negotiatedOwner && negotiatedOwner !== endpointId)) {\n                    logger.warn(`Ignoring SourceInfo for ${sourceName} not owned by ${endpointId}`);\n                    continue;\n                }\n\n                let sourceChanged = false;\n                const mediaType = getMediaTypeFromSourceName(sourceName);\n                const newMutedState = Boolean(sourceInfoJSON[sourceName].muted);\n                const oldSourceState = endpointSourceState[sourceName]\n                    || (endpointSourceState[sourceName] = { sourceName });\n\n                if (oldSourceState.muted !== newMutedState) {\n                    sourceChanged = true;\n                    oldSourceState.muted = newMutedState;\n                    if (emitEventsFromHere && !this._localSourceState[sourceName]) {\n                        this.eventEmitter.emit(SignalingEvents.SOURCE_MUTED_CHANGED, sourceName, newMutedState);\n                    }\n                }\n\n                // Assume a default videoType of 'camera' for video sources.\n                const newVideoType = mediaType === MediaType.VIDEO\n                    ? sourceInfoJSON[sourceName].videoType ?? VideoType.CAMERA\n                    : undefined;\n\n                if (oldSourceState.videoType !== newVideoType) {\n                    oldSourceState.videoType = newVideoType;\n                    sourceChanged = true;\n\n                    // Since having a mix of eps that do/don't support multi-stream in the same call is supported, emit\n                    // SOURCE_VIDEO_TYPE_CHANGED event when the remote source changes videoType.\n                    if (emitEventsFromHere && !this._localSourceState[sourceName]) {\n                        this.eventEmitter.emit(SignalingEvents.SOURCE_VIDEO_TYPE_CHANGED, sourceName, newVideoType);\n                    }\n                }\n\n                if (sourceChanged && FeatureFlags.isSsrcRewritingSupported()) {\n                    this.eventEmitter.emit(\n                        SignalingEvents.SOURCE_UPDATED,\n                        sourceName,\n                        mucNick,\n                        newMutedState,\n                        newVideoType);\n                }\n            }\n\n            // Cleanup removed source names\n            const newSourceNames = Object.keys(sourceInfoJSON);\n\n            for (const sourceName of Object.keys(endpointSourceState)) {\n                if (newSourceNames.indexOf(sourceName) === -1) {\n                    delete endpointSourceState[sourceName];\n                }\n            }\n        };\n        room.addPresenceListener('SourceInfo', this._sourceInfoHandler);\n\n        // Cleanup when participant leaves\n        this._memberLeftHandler = (jid: string) => {\n            const endpointId = Strophe.getResourceFromJid(jid);\n\n            delete this._remoteSourceState[endpointId];\n        };\n        room.addEventListener(XMPPEvents.MUC_MEMBER_LEFT, this._memberLeftHandler);\n    }\n\n    /**\n     * Check is given endpoint has advertised <SourceInfo/> in it's presence which means that the source name signaling\n     * is used by this endpoint.\n     *\n     * @param {EndpointId} endpointId\n     * @returns {boolean}\n     */\n    private _doesEndpointSendNewSourceInfo(endpointId: EndpointId): boolean {\n        const presence = this._chatRoom?.getLastPresence(endpointId);\n\n        return Boolean(presence?.find((node: IPresenceNode) => node.tagName === SOURCE_INFO_PRESENCE_ELEMENT));\n    }\n\n    /**\n     * Logs a debug or error message to console depending on whether SSRC rewriting is enabled or not.\n     * Owner changes are permitted only when SSRC rewriting is enabled.\n     *\n     * @param {string} message - The message to be logged.\n     * @returns {void}\n     */\n    private _logOwnerChangedMessage(message: string): void {\n        if (FeatureFlags.isSsrcRewritingSupported()) {\n            logger.debug(message);\n        } else {\n            logger.error(message);\n        }\n    }\n\n    /**\n     * @inheritDoc\n     */\n    public override getPeerMediaInfo(owner: string, mediaType: MediaType, sourceName?: SourceName): Optional<IPeerMediaInfo> {\n        const legacyGetPeerMediaInfo = (): Optional<IPeerMediaInfo> => {\n            if (this._chatRoom) {\n                return this._chatRoom.getMediaPresenceInfo(owner, mediaType);\n            }\n            logger.warn('Requested peer media info, before room was set');\n        };\n\n        const lastPresence = this._chatRoom?.getLastPresence(owner);\n\n        if (!lastPresence) {\n            logger.warn(`getPeerMediaInfo - no presence stored for: ${owner}`);\n\n            return;\n        }\n        if (!this._doesEndpointSendNewSourceInfo(owner)) {\n            return legacyGetPeerMediaInfo();\n        }\n\n        if (sourceName) {\n            return this.getPeerSourceInfo(owner, sourceName);\n        }\n\n        const mediaInfo: IPeerMediaInfo = {\n            muted: true\n        };\n\n        if (mediaType === MediaType.VIDEO) {\n            mediaInfo.videoType = undefined;\n            const codecListNode = filterNodeFromPresenceJSON(lastPresence, 'jitsi_participant_codecList');\n            const codecTypeNode = filterNodeFromPresenceJSON(lastPresence, 'jitsi_participant_codecType');\n\n            if (codecListNode.length) {\n                mediaInfo.codecList = codecListNode[0].value?.split(',') ?? [];\n            } else if (codecTypeNode.length > 0) {\n                mediaInfo.codecType = codecTypeNode[0].value;\n            }\n        }\n\n        return mediaInfo;\n    }\n\n    /**\n     * @inheritDoc\n     */\n    public override getPeerSourceInfo(owner: EndpointId, sourceName: SourceName): Optional<ISourceInfo> {\n        const mediaType = getMediaTypeFromSourceName(sourceName);\n        const mediaInfo: ISourceInfo = mediaType === MediaType.VIDEO\n            ? { muted: true, sourceName, videoType: VideoType.CAMERA }\n            : { muted: true, sourceName };\n\n        return this._remoteSourceState[owner]\n            ? this._remoteSourceState[owner][sourceName] ?? mediaInfo\n            : undefined;\n    }\n\n    /**\n     * @inheritDoc\n     */\n    public override getSSRCOwner(ssrc: number): Optional<string> {\n        return this._ssrcOwners.get(ssrc)?.endpointId;\n    }\n\n    /**\n     * @inheritDoc\n     */\n    public override getTrackSourceName(ssrc: number): Optional<SourceName> {\n        return this._ssrcOwners.get(ssrc)?.sourceName;\n    }\n\n    /**\n     * @inheritDoc\n     */\n    public override removeSSRCOwners(ssrcList: number[]): void {\n        if (!ssrcList?.length) {\n            return;\n        }\n\n        for (const ssrc of ssrcList) {\n            this._ssrcOwners.delete(ssrc);\n        }\n    }\n\n    /**\n     * Sets the <tt>ChatRoom</tt> instance used and binds presence listeners.\n     * @param {ChatRoom} room\n     */\n    public setChatRoom(room: ChatRoom): void {\n        const oldChatRoom = this._chatRoom;\n\n        this._chatRoom = room;\n        if (oldChatRoom) {\n            oldChatRoom.removePresenceListener(\n                'audiomuted', this._audioMuteHandler);\n            oldChatRoom.removePresenceListener(\n                'videomuted', this._videoMuteHandler);\n            oldChatRoom.removePresenceListener(\n                'videoType', this._videoTypeHandler);\n            this._sourceInfoHandler\n                && oldChatRoom.removePresenceListener(SOURCE_INFO_PRESENCE_ELEMENT, this._sourceInfoHandler);\n            this._memberLeftHandler\n                && oldChatRoom.removeEventListener(XMPPEvents.MUC_MEMBER_LEFT, this._memberLeftHandler);\n        }\n        if (room) {\n            this._bindChatRoomEventHandlers(room);\n            this._addLocalSourceInfoToPresence();\n        }\n    }\n\n    /**\n     * @inheritDoc\n     */\n    public override setSSRCOwner(ssrc: number, newEndpointId: string, newSourceName: string): void {\n        if (typeof ssrc !== 'number') {\n            throw new TypeError(`SSRC(${ssrc}) must be a number`);\n        }\n\n        // Now signaling layer instance is shared between different JingleSessionPC instances, so although very unlikely\n        // an SSRC conflict could potentially occur. Log a message to make debugging easier.\n        const existingOwner = this._ssrcOwners.get(ssrc);\n\n        if (existingOwner) {\n            const { endpointId, sourceName } = existingOwner;\n\n            if (endpointId !== newEndpointId || sourceName !== newSourceName) {\n                this._logOwnerChangedMessage(\n                    `SSRC owner re-assigned from ${existingOwner}(source-name=${sourceName}) to ${\n                        newEndpointId}(source-name=${newSourceName})`);\n            }\n        }\n        this._ssrcOwners.set(ssrc, {\n            endpointId: newEndpointId,\n            sourceName: newSourceName\n        });\n    }\n\n    /**\n     * @inheritDoc\n     */\n    public override setTrackMuteStatus(sourceName: SourceName, muted: boolean): boolean {\n        if (!this._localSourceState[sourceName]) {\n            this._localSourceState[sourceName] = {};\n        }\n\n        this._localSourceState[sourceName].muted = muted;\n        logger.debug(`Mute state of ${sourceName} changed to muted=${muted}`);\n\n        if (this._chatRoom) {\n            return this._addLocalSourceInfoToPresence();\n        }\n\n        return false;\n    }\n\n    /**\n     * @inheritDoc\n     */\n    public override setTrackVideoType(sourceName: SourceName, videoType: VideoType): boolean {\n        if (!this._localSourceState[sourceName]) {\n            this._localSourceState[sourceName] = {};\n        }\n\n        if (this._localSourceState[sourceName].videoType !== videoType) {\n            // Include only if not a camera (default)\n            this._localSourceState[sourceName].videoType = videoType === VideoType.CAMERA ? undefined : videoType;\n\n            return this._addLocalSourceInfoToPresence();\n        }\n\n        return false;\n    }\n\n    /**\n     * @inheritDoc\n     */\n    public override updateSsrcOwnersOnLeave(id: string): void {\n        const ssrcs: number[] = [];\n\n        this._ssrcOwners.forEach(({ endpointId }, ssrc) => {\n            if (endpointId === id) {\n                ssrcs.push(ssrc);\n            }\n        });\n\n        if (!ssrcs?.length) {\n            return;\n        }\n\n        this.removeSSRCOwners(ssrcs);\n    }\n}\n","/**\n * Enumeration of the video types that are signaled to the bridge\n * @type {{CAMERA: string, DESKTOP: string, DESKTOP_HIGH_FPS: string, NONE: string}}\n */\nexport enum BridgeVideoType {\n\n    /**\n     * The camera video type.\n     */\n    CAMERA = 'camera',\n\n    /**\n     * The low fps desktop video type.\n     */\n    DESKTOP = 'desktop',\n\n    /**\n     * The high fps desktop video type.\n     */\n    DESKTOP_HIGH_FPS = 'desktop_high_fps',\n\n    /**\n     * Video type when no local source is present.\n     */\n    NONE = 'none'\n}\n","import { getLogger } from '@jitsi/logger';\nimport { isEqual } from 'lodash-es';\nimport { $msg, Strophe } from 'strophe.js';\n\nimport { JitsiAudioTranslationErrors } from './JitsiAudioTranslationErrors';\nimport * as JitsiConferenceErrors from './JitsiConferenceErrors';\nimport JitsiConferenceEventManager from './JitsiConferenceEventManager';\nimport { JitsiConferenceEvents } from './JitsiConferenceEvents';\nimport type JitsiConnection from './JitsiConnection';\nimport { JitsiConnectionEvents } from './JitsiConnectionEvents';\nimport JitsiParticipant from './JitsiParticipant';\nimport JitsiTrackError from './JitsiTrackError';\nimport * as JitsiTrackErrors from './JitsiTrackErrors';\nimport { JitsiTrackEvents } from './JitsiTrackEvents';\nimport type JitsiLocalTrack from './modules/RTC/JitsiLocalTrack';\nimport type JitsiRemoteTrack from './modules/RTC/JitsiRemoteTrack';\nimport JitsiTrack from './modules/RTC/JitsiTrack';\nimport RTC from './modules/RTC/RTC';\nimport { SS_DEFAULT_FRAME_RATE } from './modules/RTC/ScreenObtainer';\nimport type TraceablePeerConnection from './modules/RTC/TraceablePeerConnection';\nimport browser from './modules/browser';\nimport ConnectionQuality from './modules/connectivity/ConnectionQuality';\nimport IceFailedHandling from './modules/connectivity/IceFailedHandling';\nimport { DetectionEvents } from './modules/detection/DetectionEvents';\nimport NoAudioSignalDetection from './modules/detection/NoAudioSignalDetection';\nimport P2PDominantSpeakerDetection from './modules/detection/P2PDominantSpeakerDetection';\nimport VADAudioAnalyser, { IVADProcessor } from './modules/detection/VADAudioAnalyser';\nimport VADNoiseDetection from './modules/detection/VADNoiseDetection';\nimport VADTalkMutedDetection from './modules/detection/VADTalkMutedDetection';\nimport { E2EEncryption } from './modules/e2ee-internxt/E2EEncryption';\nimport E2ePing from './modules/e2eping/e2eping';\nimport FeatureFlags from './modules/flags/FeatureFlags';\nimport { LiteModeContext } from './modules/litemode/LiteModeContext';\nimport { QualityController } from './modules/qualitycontrol/QualityController';\nimport { IReceiverVideoConstraints } from './modules/qualitycontrol/ReceiveVideoController';\nimport JibriSession from './modules/recording/JibriSession';\nimport RecordingManager, { IRecordingOptions } from './modules/recording/RecordingManager';\nimport Settings from './modules/settings/Settings';\nimport AvgRTPStatsReporter from './modules/statistics/AvgRTPStatsReporter';\nimport LocalStatsCollector from './modules/statistics/LocalStatsCollector';\nimport SpeakerStats from './modules/statistics/SpeakerStats';\nimport SpeakerStatsCollector from './modules/statistics/SpeakerStatsCollector';\nimport Statistics from './modules/statistics/statistics';\nimport Listenable from './modules/util/Listenable';\nimport { isValidNumber, safeSubtract } from './modules/util/MathUtil';\nimport RandomUtil from './modules/util/RandomUtil';\nimport { getJitterDelay } from './modules/util/Retry';\nimport { findAll, findFirst, getAttribute } from './modules/util/XMLUtils';\nimport ComponentsVersions from './modules/version/ComponentsVersions';\nimport JitsiVideoSIPGWSession from './modules/videosipgw/JitsiVideoSIPGWSession';\nimport VideoSIPGW from './modules/videosipgw/VideoSIPGW';\nimport * as VideoSIPGWConstants from './modules/videosipgw/VideoSIPGWConstants';\nimport BreakoutRooms from './modules/xmpp/BreakoutRooms';\nimport type { ChatRoom, PresenceHandler } from './modules/xmpp/ChatRoom';\nimport FileSharing from './modules/xmpp/FileSharing';\nimport type JingleSessionPC from './modules/xmpp/JingleSessionPC';\nimport { MediaSessionEvents } from './modules/xmpp/MediaSessionEvents';\nimport Polls from './modules/xmpp/Polls';\nimport RoomMetadata from './modules/xmpp/RoomMetadata';\nimport SignalingLayerImpl from './modules/xmpp/SignalingLayerImpl';\nimport XMPP, {\n    FEATURE_E2EE,\n    FEATURE_JIGASI,\n    IFaceLandmarksPayload,\n    JITSI_MEET_MUC_TYPE\n} from './modules/xmpp/xmpp';\nimport { BridgeVideoType } from './service/RTC/BridgeVideoType';\nimport { CodecMimeType } from './service/RTC/CodecMimeType';\nimport { IceRestartReason } from './service/RTC/IceRestartReason';\nimport { MediaType } from './service/RTC/MediaType';\nimport { RTCEvents } from './service/RTC/RTCEvents';\nimport {\n    ILegacyReceiverAudioSubscriptionMessage,\n    IReceiverAudioSubscriptionMessage\n} from './service/RTC/ReceiverAudioSubscription';\nimport { SignalingEvents } from './service/RTC/SignalingEvents';\nimport {\n    getMediaTypeFromSourceName,\n    getSourceNameForJitsiTrack,\n    isTranslatedSourceName\n} from './service/RTC/SignalingLayer';\nimport { VideoType } from './service/RTC/VideoType';\nimport { MAX_CONNECTION_RETRIES } from './service/connectivity/Constants';\nimport {\n    AnalyticsEvents,\n    createConferenceEvent,\n    createJingleEvent,\n    createJvbIceFailedEvent,\n    createP2PEvent\n} from './service/statistics/AnalyticsEvents';\nimport { XMPPEvents } from './service/xmpp/XMPPEvents';\n\nexport interface IConferenceOptions {\n    config: {\n        _p2pConnStatusRtcMuteTimeout?: number;\n        _peerConnStatusOutOfLastNTimeout?: number;\n        _peerConnStatusRtcMuteTimeout?: number;\n        analytics?: {\n            rtcstatsEnabled?: boolean;\n            rtcstatsEndpoint?: string;\n        };\n        applicationName?: string;\n        audioTranslation?: {\n            enabled?: boolean;\n        };\n        avgRtpStatsN?: number;\n        channelLastN?: number;\n        confID?: string;\n        createVADProcessor?: () => IVADProcessor;\n        deploymentInfo?: {\n            userRegion?: string;\n        };\n        disableAudioLevels?: boolean;\n        disableLocalStats?: boolean;\n        disableLocalStatsBroadcast?: boolean;\n        e2eping?: {\n            enabled?: boolean;\n        };\n        enableIceRestart?: boolean;\n        enableNoAudioDetection?: boolean;\n        enableNoisyMicDetection?: boolean;\n        enableTalkWhileMuted?: boolean;\n        hiddenDomain?: string;\n        isChatEncrypted?: boolean;\n        p2p?: {\n            backToP2PDelay?: number;\n            codecPreferenceOrder?: string[];\n            disabledCodec?: string;\n            enabled?: boolean;\n            mobileCodecPreferenceOrder?: string[];\n            mobileScreenshareCodec?: string;\n            preferredCodec?: string;\n            screenshareCodec?: string;\n        };\n        pcStatsInterval?: number;\n        startAudioMuted?: number;\n        startLastN?: number;\n        startSilent?: boolean;\n        startVideoMuted?: number;\n        statisticsDisplayName?: string;\n        statisticsId?: string;\n        testing?: {\n            allowMultipleTracks?: boolean;\n            enableAV1ForFF?: boolean;\n            enableFirefoxP2p?: boolean;\n            forceInitiator?: boolean;\n            forceResponder?: boolean;\n            lastNRampupTime?: number;\n            p2pTestMode?: boolean;\n        };\n        transcriptionLanguage?: string;\n        videoQuality?: {\n            codecPreferenceOrder?: string[];\n            disabledCodec?: string;\n            enableAdaptiveMode?: boolean;\n            mobileCodecPreferenceOrder?: string[];\n            mobileScreenshareCodec?: string;\n            preferredCodec?: string;\n            screenshareCodec?: string;\n        };\n    };\n    connection: JitsiConnection;\n    customDomain?: string;\n    name: string;\n}\n\nexport interface IStartMutedPolicy {\n    audio: boolean;\n    video: boolean;\n}\n\nexport interface IConferenceProperties {\n    'audio-limit-reached'?: string;\n    'bridge-count'?: string;\n    'video-limit-reached'?: string;\n    'visitor-codecs'?: string;\n    'visitor-count'?: number;\n}\n\nexport interface IStatisticsOptions {\n    aliasName?: string;\n    applicationName?: string;\n    confID?: string;\n    roomName?: string;\n    userName?: string;\n}\n\nexport interface IStopSessionOptions {\n    reason?: string;\n    reasonDescription?: string;\n    requestRestart?: boolean;\n    sendSessionTerminate?: boolean;\n}\n\nconst logger = getLogger('core:JitsiConference');\n\n/**\n * How long (ms) to keep an in-flight translation request around for error correlation. The component only\n * replies on failure, so a request with no reply within this window is assumed to have succeeded.\n */\nconst TRANSLATION_REQUEST_TIMEOUT = 15000;\n\n/**\n * How long since Jicofo is supposed to send a session-initiate, before\n * {@link ACTION_JINGLE_SI_TIMEOUT} analytics event is sent (in ms).\n * @type {number}\n */\nconst JINGLE_SI_TIMEOUT: number = 5000;\n\n/**\n * How long (ms) to wait for ICE to recover after an in-place ICE restart (triggered by an ICE failure) before\n * falling back to a session restart.\n */\nconst JVB_ICE_RESTART_RECOVERY_TIMEOUT = 15000;\n\n/**\n * Default source language for transcribing the local participant.\n */\nconst DEFAULT_TRANSCRIPTION_LANGUAGE: string = 'en-US';\n\n/**\n * Checks if a given string is a valid video codec mime type.\n *\n * @param {string} codec the codec string that needs to be validated.\n * @returns {CodecMimeType|null} mime type if valid, null otherwise.\n * @private\n */\nfunction _getCodecMimeType(codec: string): Nullable<CodecMimeType> {\n    if (typeof codec === 'string') {\n        return Object.values(CodecMimeType).find(value => value === codec.toLowerCase()) || null;\n    }\n\n    return null;\n}\n\n/**\n * Error returned by authenticateAndUpgradeRole when authentication or connection fails.\n */\ninterface IUpgradeRoleError {\n    authenticationError?: string;\n    connectionError?: JitsiConnectionEvents;\n    credentials?: {\n        jid?: string;\n        password?: string;\n    };\n    message?: string;\n}\n\n/**\n * Options for authenticateAndUpgradeRole.\n */\ninterface IAuthenticateAndUpgradeRoleOptions {\n    id: string;\n    onCreateResource?: typeof JitsiConference.staticResourceCreator;\n    onLoginSuccessful?: () => void;\n    password: string;\n}\ninterface IProcessWithCancel extends Promise<void> {\n    cancel: () => void;\n}\n\n\n/**\n * Creates a JitsiConference object with the given name and properties.\n * Note: this constructor is not a part of the public API (objects should be\n * created using JitsiConnection.createConference).\n * @param options.config properties / settings related to the conference that\n * will be created.\n * @param options.name the name of the conference\n * @param options.connection the JitsiConnection object for this\n * JitsiConference.\n * @param {number} [options.config.avgRtpStatsN=15] how many samples are to be\n * collected by `AvgRTPStatsReporter`, before arithmetic mean is\n * calculated and submitted to the analytics module.\n * @param {boolean} [options.config.p2p.enabled] when set to <tt>true</tt>\n * the peer to peer mode will be enabled. It means that when there are only 2\n * participants in the conference an attempt to make direct connection will be\n * made. If the connection succeeds the conference will stop sending data\n * through the JVB connection and will use the direct one instead.\n * @param {number} [options.config.p2p.backToP2PDelay=5] a delay given in\n * seconds, before the conference switches back to P2P, after the 3rd\n * participant has left the room.\n * @param {number} [options.config.channelLastN=-1] The requested amount of\n * videos are going to be delivered after the value is in effect. Set to -1 for\n * unlimited or all available videos.\n *\n * @noInheritDoc\n */\nexport default class JitsiConference extends Listenable {\n    private _transcribingEnabled?: boolean;\n    private _visitorCodecs?: string[];\n    private _hasVisitors?: boolean;\n    private _sessionInitiateTimeout?: number;\n    private _desktopSharingFrameRate?: number;\n    private _numberOfParticipantsOnJoin?: number;\n    private _delayedIceFailed?: IceFailedHandling;\n    private _audioAnalyser?: VADAudioAnalyser;\n    private _noAudioSignalDetection?: NoAudioSignalDetection;\n    private _signalingLayer: SignalingLayerImpl;\n\n    /**\n     * The default language remote audio is translated into for every speaker, or null when off.\n     * Per-participant overrides in {@link _participantTranslationLanguages} take precedence over this.\n     */\n    private _receiverTranslationLanguage: string | null = null;\n\n    /**\n     * Per-participant translation overrides (endpointId -> language, or null to explicitly disable for\n     * that speaker). An entry present here wins over {@link _receiverTranslationLanguage}; an absent entry\n     * inherits the default. Set via {@link setParticipantTranslationLanguage}.\n     */\n    private _participantTranslationLanguages: Map<string, string | null> = new Map();\n\n    /**\n     * Translation requests last advertised to the audio-translation module (endpointId -> language),\n     * used to send only the delta on roster changes.\n     */\n    private _translationRequests: Map<string, string> = new Map();\n\n    /**\n     * In-flight translation-request deltas keyed by stanza id. The component only replies on failure\n     * (success is silent), so this maps an error reply back to the endpoints the failed request touched.\n     */\n    private _pendingTranslationRequests: Map<string, { [endpointId: string]: string; }> = new Map();\n\n    /**\n     * The registered Strophe handler for translation-request error replies, or undefined when not registered.\n     * Stored so it can be removed from the (connection-scoped) handler list on {@link leave}.\n     */\n    private _translationErrorHandler?: ReturnType<Strophe.Connection['addHandler']>;\n\n    // Stored so the (connection-scoped) translation-listeners handler can be removed on leave().\n    private _translationListenersHandler?: ReturnType<Strophe.Connection['addHandler']>;\n\n    /**\n     * Monotonic counter used to mint translation-request stanza ids for error correlation.\n     */\n    private _translationRequestSeq = 0;\n    private _conferenceJoinAnalyticsEventSent?: number;\n    private _e2eEncryption?: E2EEncryption;\n    private _liteModeContext?: LiteModeContext;\n    private _audioSenderLimitReached?: boolean;\n    private _videoSenderLimitReached?: boolean;\n    private _firefoxP2pEnabled: boolean;\n    private _iceRestarts: number;\n    private _unsubscribers: Array<() => void>;\n    private _xmpp: XMPP;\n\n    /**\n     * @internal\n     */\n    _statsCurrentId: string;\n\n    public options: IConferenceOptions;\n    public connection: JitsiConnection;\n    public eventManager: JitsiConferenceEventManager;\n    public participants: Map<string, JitsiParticipant>;\n    public componentsVersions: ComponentsVersions;\n    public jvbJingleSession?: JingleSessionPC;\n    public lastDominantSpeaker?: string;\n    public dtmfManager?: object;\n    public somebodySupportsDTMF: boolean;\n    public authEnabled: boolean;\n    public startMutedPolicy: IStartMutedPolicy;\n    public isMutedByFocus: boolean;\n    public mutedByFocusActor?: string;\n    public isVideoMutedByFocus: boolean;\n    public mutedVideoByFocusActor?: string;\n    public wasStopped: boolean;\n    public properties: IConferenceProperties;\n    public connectionQuality: ConnectionQuality;\n    public avgRtpStatsReporter?: AvgRTPStatsReporter;\n    public isJvbConnectionInterrupted: boolean;\n    public speakerStatsCollector: SpeakerStatsCollector;\n    public deferredStartP2PTask?: number;\n    public backToP2PDelay: number;\n    public isP2PConnectionInterrupted: boolean;\n    public p2p: boolean;\n    public p2pJingleSession?: JingleSessionPC;\n    public videoSIPGWHandler: VideoSIPGW;\n    public recordingManager: RecordingManager;\n    public room?: ChatRoom;\n    public e2eping?: E2ePing;\n    public rtc?: RTC;\n    public qualityController?: QualityController;\n    public statistics?: Statistics;\n    public p2pDominantSpeakerDetection?: P2PDominantSpeakerDetection;\n    public authIdentity?: string;\n    public p2pEstablishmentDuration?: number;\n    public jvbEstablishmentDuration?: number;\n    public isDesktopMutedByFocus: boolean;\n    public mutedDesktopByFocusActor?: string;\n    public dominantSpeakerIsSilent?: boolean;\n\n\n    /**\n     * @param {IConferenceOptions} options\n     */\n    constructor(options: IConferenceOptions) {\n        super();\n        if (!options.name || options.name.toLowerCase() !== options.name.toString()) {\n            const errmsg\n                = 'Invalid conference name (no conference name passed or it '\n                + 'contains invalid characters like capital letters)!';\n            const additionalLogMsg = options.name\n                ? `roomName=${options.name}; condition - ${options.name.toLowerCase()}!==${options.name.toString()}`\n                : 'No room name passed!';\n\n            logger.error(`${errmsg} ${additionalLogMsg}`);\n            throw new Error(errmsg);\n        }\n\n        this.connection = options.connection;\n        this._xmpp = this.connection?.xmpp;\n\n        if (this._xmpp.isRoomCreated(options.name, options.customDomain)) {\n            const errmsg = 'A conference with the same name has already been created!';\n\n            delete this.connection;\n            delete this._xmpp;\n            logger.error(errmsg);\n            throw new Error(errmsg);\n        }\n\n        this.options = options;\n        this.eventManager = new JitsiConferenceEventManager(this);\n\n        /**\n         * List of all the participants in the conference.\n         * @type {Map<string, JitsiParticipant>}\n         */\n        this.participants = new Map();\n\n        /**\n         * The signaling layer instance.\n         * @type {SignalingLayerImpl}\n         * @private\n         */\n        this._signalingLayer = new SignalingLayerImpl();\n\n        this._init(options);\n        this.componentsVersions = new ComponentsVersions(this);\n\n        /**\n         * Jingle session instance for the JVB connection.\n         * @type {JingleSessionPC}\n         */\n        this.jvbJingleSession = null;\n        this.lastDominantSpeaker = null;\n        this.dtmfManager = null;\n        this.somebodySupportsDTMF = false;\n        this.authEnabled = false;\n        this.startMutedPolicy = {\n            audio: false,\n            video: false\n        };\n\n        // AV Moderation.\n        this.isMutedByFocus = false;\n        this.isVideoMutedByFocus = false;\n        this.isDesktopMutedByFocus = false;\n        this.mutedByFocusActor = null;\n        this.mutedVideoByFocusActor = null;\n        this.mutedDesktopByFocusActor = null;\n\n        // Flag indicates if the 'onCallEnded' method was ever called on this\n        // instance. Used to log extra analytics event for debugging purpose.\n        // We need to know if the potential issue happened before or after\n        // the restart.\n        this.wasStopped = false;\n\n        // Conference properties, maintained by jicofo.\n        this.properties = {};\n\n        /**\n         * The object which monitors local and remote connection statistics (e.g.\n         * sending bitrate) and calculates a number which represents the connection\n         * quality.\n         */\n        this.connectionQuality = new ConnectionQuality(this, this.eventEmitter, options);\n\n        /**\n         * Reports average RTP statistics to the analytics module.\n         * @type {AvgRTPStatsReporter}\n         */\n        this.avgRtpStatsReporter = new AvgRTPStatsReporter(this, options.config.avgRtpStatsN || 15);\n\n        /**\n         * Indicates whether the connection is interrupted or not.\n         */\n        this.isJvbConnectionInterrupted = false;\n\n        /**\n         * The object which tracks active speaker times\n         */\n        this.speakerStatsCollector = new SpeakerStatsCollector(this);\n\n        /* P2P related fields below: */\n\n        /**\n         * Stores reference to deferred start P2P task. It's created when 3rd\n         * participant leaves the room in order to avoid ping pong effect (it\n         * could be just a page reload).\n         * @type {number|null}\n         */\n        this.deferredStartP2PTask = null;\n\n        const delay = Number.parseInt(String(options.config.p2p?.backToP2PDelay || 5), 10);\n\n        /**\n         * A delay given in seconds, before the conference switches back to P2P\n         * after the 3rd participant has left.\n         * @type {number}\n         */\n        this.backToP2PDelay = isValidNumber(delay) ? delay : 5;\n        logger.info(`backToP2PDelay: ${this.backToP2PDelay}`);\n\n        /**\n         * If set to <tt>true</tt> it means the P2P ICE is no longer connected.\n         * When <tt>false</tt> it means that P2P ICE (media) connection is up\n         * and running.\n         * @type {boolean}\n         */\n        this.isP2PConnectionInterrupted = false;\n\n        /**\n         * Flag set to <tt>true</tt> when P2P session has been established\n         * (ICE has been connected) and this conference is currently in the peer to\n         * peer mode (P2P connection is the active one).\n         * @type {boolean}\n         */\n        this.p2p = false;\n\n        /**\n         * A JingleSession for the direct peer to peer connection.\n         * @type {JingleSessionPC}\n         */\n        this.p2pJingleSession = null;\n\n        this.videoSIPGWHandler = new VideoSIPGW(this.room);\n        this.recordingManager = new RecordingManager(this.room);\n\n        /**\n         * If the conference.joined event has been sent this will store the timestamp when it happened.\n         *\n         * @type {undefined|number}\n         * @private\n         */\n        this._conferenceJoinAnalyticsEventSent = undefined;\n\n        /**\n         * End-to-End Encryption. Make it available if supported.\n         */\n        if (this.isE2EESupported()) {\n            logger.info('End-to-End Encryption is supported');\n            this._e2eEncryption = new E2EEncryption(this);\n        }\n\n        if (FeatureFlags.isRunInLiteModeEnabled()) {\n            logger.info('Lite mode enabled');\n            this._liteModeContext = new LiteModeContext(this);\n        }\n\n        /**\n         * Flag set to <tt>true</tt> when Jicofo sends a presence message indicating that the max audio sender limit has\n         * been reached for the call. Once this is set, unmuting audio will be disabled\n         * from the client until it gets reset\n         * again by Jicofo.\n         */\n        this._audioSenderLimitReached = undefined;\n\n        /**\n         * Flag set to <tt>true</tt> when Jicofo sends a presence message indicating that the max video sender limit has\n         * been reached for the call. Once this is set, unmuting video will be disabled\n         * from the client until it gets reset\n         * again by Jicofo.\n         */\n        this._videoSenderLimitReached = undefined;\n\n        this._firefoxP2pEnabled = browser.isVersionGreaterThan(109)\n            && (this.options.config.testing?.enableFirefoxP2p ?? true);\n\n        /**\n         * Number of times ICE restarts that have been attempted after ICE connectivity with the JVB was lost.\n         */\n        this._iceRestarts = 0;\n        this._unsubscribers = [];\n\n        this.eventEmitter.once(JitsiConferenceEvents.E2EE_CHAT_KEY_RECEIVED, key => {\n            this.room.eventEmitter.emit(JitsiConferenceEvents.E2EE_CHAT_KEY_RECEIVED, key);\n        });\n    }\n\n    /**\n     * Create a resource for the a jid. We require\n     * endpoint IDs to be 8 hex digits because in some cases they get serialized\n     * into a 32bit field.\n     *\n     * @returns {string}\n     */\n    static staticResourceCreator(): string {\n        const time = new Date().getTime();\n\n        return time.toString(16).slice(-8);\n    }\n\n\n    /**\n     * Create a resource for the a jid. We use the room nickname (the resource part\n     * of the occupant JID, see XEP-0045) as the endpoint ID in colibri. We require\n     * endpoint IDs to be 8 hex digits because in some cases they get serialized\n     * into a 32bit field.\n     *\n     * @param {string} jid - The id set onto the XMPP connection.\n     * @param {boolean} isAuthenticatedUser - Whether or not the user has connected\n     * to the XMPP service with a password.\n     * @returns {string}\n     */\n    static resourceCreator(jid: string, isAuthenticatedUser: boolean): string {\n        let mucNickname: string;\n\n        if (isAuthenticatedUser) {\n            // For authenticated users generate a random ID.\n            mucNickname = RandomUtil.randomHexString(8).toLowerCase();\n        } else {\n            // Use first part of node for anonymous users if it matches format\n            mucNickname = Strophe.getNodeFromJid(jid)?.substr(0, 8)\n.toLowerCase();\n\n            // But if this doesn't have the required format we just generate a new\n            // random nickname.\n            const re = /[0-9a-f]{8}/g;\n\n            if (!mucNickname || !re.test(mucNickname)) {\n                mucNickname = RandomUtil.randomHexString(8).toLowerCase();\n            }\n        }\n\n        return mucNickname;\n    }\n\n    /**\n     * Initializes the conference object properties\n     * @param options {object}\n     * @param options.connection {JitsiConnection} overrides this.connection\n     */\n    private _init(options: IConferenceOptions): void {\n        this.eventManager.setupXMPPListeners();\n\n        const { config } = this.options;\n\n        this._statsCurrentId = config.statisticsId ?? Settings.callStatsUserName;\n        this.room = this._xmpp.createRoom(\n            this.options.name, {\n                ...config,\n                statsId: this._statsCurrentId\n            },\n            JitsiConference.staticResourceCreator\n        );\n\n        this._signalingLayer.setChatRoom(this.room);\n        this._signalingLayer.on(\n            SignalingEvents.SOURCE_UPDATED,\n            (sourceName, endpointId, muted, videoType) => {\n                const participant = this.participants.get(endpointId);\n                const mediaType = getMediaTypeFromSourceName(sourceName);\n\n                if (participant) {\n                    participant._setSources(mediaType, muted, sourceName, videoType);\n                    this.eventEmitter.emit(JitsiConferenceEvents.PARTICIPANT_SOURCE_UPDATED, participant);\n                }\n            });\n\n        // ICE Connection interrupted/restored listeners.\n        this._onIceConnectionEstablished = this._onIceConnectionEstablished.bind(this);\n        this.room.addListener(XMPPEvents.CONNECTION_ESTABLISHED, this._onIceConnectionEstablished);\n\n        this._onIceConnectionFailed = this._onIceConnectionFailed.bind(this);\n        this.room.addListener(XMPPEvents.CONNECTION_ICE_FAILED, this._onIceConnectionFailed);\n\n        this._onIceConnectionInterrupted = this._onIceConnectionInterrupted.bind(this);\n        this.room.addListener(XMPPEvents.CONNECTION_INTERRUPTED, this._onIceConnectionInterrupted);\n\n        this._onIceConnectionRestored = this._onIceConnectionRestored.bind(this);\n        this.room.addListener(XMPPEvents.CONNECTION_RESTORED, this._onIceConnectionRestored);\n\n        this._onP2PTerminationRequired = this._onP2PTerminationRequired.bind(this);\n        this.room.addListener(XMPPEvents.P2P_TERMINATION_REQUIRED, this._onP2PTerminationRequired);\n\n        this._updateProperties = this._updateProperties.bind(this);\n        this.room.addListener(XMPPEvents.CONFERENCE_PROPERTIES_CHANGED, this._updateProperties);\n\n        this._sendConferenceJoinAnalyticsEvent = this._sendConferenceJoinAnalyticsEvent.bind(this);\n        this.room.addListener(XMPPEvents.MEETING_ID_SET, this._sendConferenceJoinAnalyticsEvent);\n\n        this._removeLocalSourceOnReject = this._removeLocalSourceOnReject.bind(this);\n        this._updateRoomPresence = this._updateRoomPresence.bind(this);\n        this.room.addListener(XMPPEvents.SESSION_ACCEPT, this._updateRoomPresence);\n        this.room.addListener(XMPPEvents.SOURCE_ADD, this._updateRoomPresence);\n        this.room.addListener(XMPPEvents.SOURCE_ADD_ERROR, this._removeLocalSourceOnReject);\n        this.room.addListener(XMPPEvents.SOURCE_REMOVE, this._updateRoomPresence);\n\n        if (config.e2eping?.enabled) {\n            this.e2eping = new E2ePing(\n                this,\n                config,\n                (message, to) => {\n                    try {\n                        this.sendMessage(message, to, true /* sendThroughVideobridge */);\n                    } catch (error) {\n                        logger.warn('Failed to send E2E ping request or response.', error?.msg);\n                    }\n                });\n        }\n\n        if (!this.rtc) {\n            this.rtc = new RTC(this, options);\n            this.eventManager.setupRTCListeners();\n            this._registerRtcListeners(this.rtc);\n        }\n\n        // Get the codec preference settings from config.js.\n        const qualityOptions = {\n            enableAdaptiveMode: config.videoQuality?.enableAdaptiveMode,\n            jvb: {\n                disabledCodec: _getCodecMimeType(config.videoQuality?.disabledCodec),\n                enableAV1ForFF: config.testing?.enableAV1ForFF,\n                preferenceOrder: browser.isMobileDevice()\n                    ? config.videoQuality?.mobileCodecPreferenceOrder\n                    : config.videoQuality?.codecPreferenceOrder,\n                preferredCodec: _getCodecMimeType(config.videoQuality?.preferredCodec),\n                screenshareCodec: browser.isMobileDevice()\n                    ? _getCodecMimeType(config.videoQuality?.mobileScreenshareCodec)\n                    : _getCodecMimeType(config.videoQuality?.screenshareCodec)\n            },\n            lastNRampupTime: config.testing?.lastNRampupTime ?? 60000,\n            p2p: {\n                disabledCodec: _getCodecMimeType(config.p2p?.disabledCodec),\n                enableAV1ForFF: true, // For P2P no simulcast is needed, therefore AV1 can be used.\n                preferenceOrder: browser.isMobileDevice()\n                    ? config.p2p?.mobileCodecPreferenceOrder\n                    : config.p2p?.codecPreferenceOrder,\n                preferredCodec: _getCodecMimeType(config.p2p?.preferredCodec),\n                screenshareCodec: browser.isMobileDevice()\n                    ? _getCodecMimeType(config.p2p?.mobileScreenshareCodec)\n                    : _getCodecMimeType(config.p2p?.screenshareCodec)\n            }\n        };\n\n        this.qualityController = new QualityController(this, qualityOptions);\n\n        if (!this.statistics) {\n            this.statistics = new Statistics(this, {\n                // @ts-ignore\n                aliasName: this._statsCurrentId,\n                applicationName: config.applicationName,\n                confID: config.confID ?? `${this.connection.options.hosts.domain}/${this.options.name}`,\n                roomName: this.options.name,\n                userName: config.statisticsDisplayName ?? this.myUserId()\n            });\n            Statistics.analytics.addPermanentProperties({\n                'callstats_name': this._statsCurrentId\n            });\n        }\n\n        this.eventManager.setupChatRoomListeners();\n\n        // Always add listeners because on reload we are executing leave and the\n        // listeners are removed from statistics module.\n        this.eventManager.setupStatisticsListeners();\n\n        // Disable VAD processing on Safari since it causes audio input to\n        // fail on some of the mobile devices.\n        if (config.enableTalkWhileMuted && browser.supportsVADDetection()) {\n            // If VAD processor factory method is provided uses VAD based detection, otherwise fallback to audio level\n            // based detection.\n            if (config.createVADProcessor) {\n                logger.info('Using VAD detection for generating talk while muted events');\n\n                if (!this._audioAnalyser) {\n                    this._audioAnalyser = new VADAudioAnalyser(this, config.createVADProcessor);\n                }\n\n                const vadTalkMutedDetection = new VADTalkMutedDetection();\n\n                vadTalkMutedDetection.on(DetectionEvents.VAD_TALK_WHILE_MUTED, () =>\n                    this.eventEmitter.emit(JitsiConferenceEvents.TALK_WHILE_MUTED));\n                this._audioAnalyser.addVADDetectionService(vadTalkMutedDetection);\n            } else {\n                logger.warn('No VAD Processor was provided. Talk while muted detection service was not initialized!');\n            }\n        }\n\n        // Disable noisy mic detection on safari since it causes the audio input to\n        // fail on Safari on iPadOS.\n        if (config.enableNoisyMicDetection && browser.supportsVADDetection()) {\n            if (config.createVADProcessor) {\n                if (!this._audioAnalyser) {\n                    this._audioAnalyser = new VADAudioAnalyser(this, config.createVADProcessor);\n                }\n\n                const vadNoiseDetection = new VADNoiseDetection();\n\n                vadNoiseDetection.on(DetectionEvents.VAD_NOISY_DEVICE, () =>\n                    this.eventEmitter.emit(JitsiConferenceEvents.NOISY_MIC));\n                this._audioAnalyser.addVADDetectionService(vadNoiseDetection);\n            } else {\n                logger.warn('No VAD Processor was provided. Noisy microphone detection service was not initialized!');\n            }\n        }\n\n        // Generates events based on no audio input detector.\n        if (config.enableNoAudioDetection && !config.disableAudioLevels\n            && LocalStatsCollector.isLocalStatsSupported()) {\n            this._noAudioSignalDetection = new NoAudioSignalDetection(this);\n            this._noAudioSignalDetection.on(DetectionEvents.NO_AUDIO_INPUT, () =>\n                this.eventEmitter.emit(JitsiConferenceEvents.NO_AUDIO_INPUT));\n            this._noAudioSignalDetection.on(DetectionEvents.AUDIO_INPUT_STATE_CHANGE, hasAudioSignal =>\n                this.eventEmitter.emit(JitsiConferenceEvents.AUDIO_INPUT_STATE_CHANGE, hasAudioSignal));\n        }\n\n        if ('channelLastN' in config) {\n            this.setLastN(config.channelLastN);\n        }\n\n        // creates dominant speaker detection that works only in p2p mode\n        this.p2pDominantSpeakerDetection = new P2PDominantSpeakerDetection(this);\n\n        // TODO: Drop this after the change to use the region from the http requests\n        //  to prosody is propagated to majority of deployments\n        if (config?.deploymentInfo?.userRegion) {\n            this.setLocalParticipantProperty('region', config.deploymentInfo.userRegion);\n        }\n\n        // Publish the codec preference to presence.\n        this.setLocalParticipantProperty('codecList',\n             this.qualityController.codecController.getCodecPreferenceList('jvb'));\n\n        // Set transcription language presence extension.\n        // In case the language config is undefined or has the default value that the transcriber uses\n        // (in our case Jigasi uses 'en-US'), don't set the participant property in order to avoid\n        // needlessly polluting the presence stanza.\n        const transcriptionLanguage = config?.transcriptionLanguage ?? DEFAULT_TRANSCRIPTION_LANGUAGE;\n\n        if (transcriptionLanguage !== DEFAULT_TRANSCRIPTION_LANGUAGE) {\n            this.setTranscriptionLanguage(transcriptionLanguage);\n        }\n    }\n\n    /**\n   * Registers event listeners on the RTC instance.\n   * @param {RTC} rtc - the RTC module instance used by this conference.\n   * @private\n   * @returns {void}\n   */\n    private _registerRtcListeners(rtc: RTC): void {\n        rtc.addListener(RTCEvents.DATA_CHANNEL_OPEN, () => {\n            for (const localTrack of this.rtc.localTracks) {\n                localTrack.isVideoTrack() && this._sendBridgeVideoTypeMessage(localTrack);\n            }\n\n            // (Re)establish the audio subscription on the bridge whenever the channel opens. Defaults to ALL\n            // until translation is enabled, at which point the Include list is sent instead. Only when the\n            // audio-translation feature is enabled — otherwise leave the bridge's default subscription untouched.\n            if (this.options.config.audioTranslation?.enabled) {\n                this.qualityController.audioController.resendSubscription();\n            }\n        });\n    }\n\n\n    /**\n     * Sends a conference.join analytics event.\n     *\n     * @returns {void}\n     */\n    private _sendConferenceJoinAnalyticsEvent(): void {\n        const meetingId = this.getMeetingUniqueId();\n\n        if (this._conferenceJoinAnalyticsEventSent || !meetingId || this.getActivePeerConnection() === null) {\n            return;\n        }\n\n        const conferenceConnectionTimes = this.getConnectionTimes();\n        const xmppConnectionTimes = this.connection.getConnectionTimes();\n        const gumStart = window.connectionTimes['firstObtainPermissions.start'];\n        const gumEnd = window.connectionTimes['firstObtainPermissions.end'];\n        const globalNSConnectionTimes = window.JitsiMeetJS?.app?.connectionTimes ?? {};\n        const connectionTimes = {\n            ...conferenceConnectionTimes,\n            ...xmppConnectionTimes,\n            ...globalNSConnectionTimes,\n            connectedToMUCJoinedTime: safeSubtract(\n                conferenceConnectionTimes['muc.joined'], xmppConnectionTimes.connected),\n            connectingToMUCJoinedTime: safeSubtract(\n                conferenceConnectionTimes['muc.joined'], xmppConnectionTimes.connecting),\n            gumDuration: safeSubtract(gumEnd, gumStart),\n            numberOfParticipantsOnJoin: this._numberOfParticipantsOnJoin,\n            xmppConnectingTime: safeSubtract(xmppConnectionTimes.connected, xmppConnectionTimes.connecting)\n        };\n\n        Statistics.sendAnalytics(createConferenceEvent('joined', {\n            ...connectionTimes,\n            meetingId,\n            participantId: `${meetingId}.${this._statsCurrentId}`,\n            supportsTurnInRoomMetadata: true\n        }));\n        this._conferenceJoinAnalyticsEventSent = Date.now();\n    }\n\n    /**\n     * Sends conference.left analytics event.\n     * @private\n     */\n    private _sendConferenceLeftAnalyticsEvent(): void {\n        const meetingId = this.getMeetingUniqueId();\n\n        if (!meetingId || !this._conferenceJoinAnalyticsEventSent) {\n\n            return;\n        }\n\n        Statistics.sendAnalytics(createConferenceEvent('left', {\n            meetingId,\n            participantId: `${meetingId}.${this._statsCurrentId}`,\n            stats: {\n                duration: Math.floor((Date.now() - this._conferenceJoinAnalyticsEventSent) / 1000)\n            }\n        }));\n    }\n\n    /**\n     * Restarts all active media sessions.\n     *\n     * @returns {void}\n     */\n    private _restartMediaSessions(): void {\n        if (this.p2pJingleSession) {\n            this._stopP2PSession({\n                reasonDescription: 'restart',\n                requestRestart: true\n            });\n        }\n\n        if (this.jvbJingleSession) {\n            this._stopJvbSession({\n                reason: 'success',\n                reasonDescription: 'restart required',\n                requestRestart: true,\n                sendSessionTerminate: true\n            });\n        }\n\n        this._maybeStartOrStopP2P(false);\n    }\n\n\n    /**\n   * Fires TRACK_AUDIO_LEVEL_CHANGED change conference event (for local tracks).\n   * @param {number} audioLevel - The audio level.\n   * @param {TraceablePeerConnection} [tpc] - The peer connection.\n   * @private\n   */\n    private _fireAudioLevelChangeEvent(audioLevel: number, tpc: TraceablePeerConnection): void {\n        const activeTpc = this.getActivePeerConnection();\n\n        // There will be no TraceablePeerConnection if audio levels do not come from\n        // a peerconnection. LocalStatsCollector.js measures audio levels using Web\n        // Audio Analyser API and emits local audio levels events through\n        // JitsiTrack.setAudioLevel, but does not provide TPC instance which is\n        // optional.\n        if (!tpc || activeTpc === tpc) {\n            this.eventEmitter.emit(\n                JitsiConferenceEvents.TRACK_AUDIO_LEVEL_CHANGED,\n                this.myUserId(), audioLevel);\n        }\n    }\n\n    /**\n   * Fires TRACK_MUTE_CHANGED change conference event.\n   * @param {JitsiLocalTrack} track - The JitsiTrack object related to the event.\n   */\n    private _fireMuteChangeEvent(track: JitsiLocalTrack): void {\n        // check if track was muted by focus and now is unmuted by user\n        if (this.isMutedByFocus && track.isAudioTrack() && !track.isMuted()) {\n            this.isMutedByFocus = false;\n\n            // unmute local user on server\n            this.room.muteParticipant(this.room.myroomjid, false, MediaType.AUDIO);\n        } else if (this.isVideoMutedByFocus && track.isVideoTrack()\n                && track.getVideoType() !== VideoType.DESKTOP && !track.isMuted()) {\n            this.isVideoMutedByFocus = false;\n\n            // unmute local user on server\n            this.room.muteParticipant(this.room.myroomjid, false, MediaType.VIDEO);\n        } else if (this.isDesktopMutedByFocus && track.isVideoTrack()\n                && track.getVideoType() === VideoType.DESKTOP && !track.isMuted()) {\n            this.isDesktopMutedByFocus = false;\n\n            // unmute local user on server\n            this.room.muteParticipant(this.room.myroomjid, false, MediaType.DESKTOP);\n        }\n\n        let actorParticipant;\n\n        if (this.mutedByFocusActor && track.isAudioTrack()) {\n            const actorId = Strophe.getResourceFromJid(this.mutedByFocusActor);\n\n            actorParticipant = this.participants.get(actorId);\n        } else if (this.mutedVideoByFocusActor && track.isVideoTrack()\n                && track.getVideoType() !== VideoType.DESKTOP) {\n            const actorId = Strophe.getResourceFromJid(this.mutedVideoByFocusActor);\n\n            actorParticipant = this.participants.get(actorId);\n        } else if (this.mutedDesktopByFocusActor && track.isVideoTrack()\n                && track.getVideoType() === VideoType.DESKTOP) {\n            const actorId = Strophe.getResourceFromJid(this.mutedDesktopByFocusActor);\n\n            actorParticipant = this.participants.get(actorId);\n        }\n\n        // Send the video type message to the bridge if the track is not removed/added to the pc as part of\n        // the mute/unmute operation.\n        // In React Native we mute the camera by setting track.enabled but that doesn't\n        // work for screen-share tracks, so do the remove-as-mute for those.\n        const doesVideoMuteByStreamRemove\n           = browser.isReactNative() ? track.videoType === VideoType.DESKTOP : browser.doesVideoMuteByStreamRemove();\n\n        if (track.isVideoTrack() && !doesVideoMuteByStreamRemove) {\n            this._sendBridgeVideoTypeMessage(track);\n        }\n\n        this.eventEmitter.emit(JitsiConferenceEvents.TRACK_MUTE_CHANGED, track, actorParticipant);\n    }\n\n\n    /**\n   * Replaces the tracks at the lower level by going through the Jingle session\n   * and WebRTC peer connection. The method will resolve immediately if there is\n   * currently no JingleSession started.\n   * @param {JitsiLocalTrack|null} oldTrack - The track to be removed during\n   * the process or <tt>null</t> if the method should act as \"add track\".\n   * @param {JitsiLocalTrack|null} newTrack - The new track to be added or\n   * <tt>null</tt> if the method should act as \"remove track\".\n   * @return {Promise} Resolved when the process is done or rejected with a string\n   * which describes the error.\n   * @private\n   */\n    private async _doReplaceTrack(oldTrack?: JitsiLocalTrack, newTrack?: JitsiLocalTrack): Promise<void> {\n        const replaceTrackPromises = [];\n\n        if (this.jvbJingleSession) {\n            replaceTrackPromises.push(this.jvbJingleSession.replaceTrack(oldTrack, newTrack));\n        } else {\n            logger.info('_doReplaceTrack - no JVB JingleSession');\n        }\n\n        if (this.p2pJingleSession) {\n            replaceTrackPromises.push(this.p2pJingleSession.replaceTrack(oldTrack, newTrack));\n        } else {\n            logger.info('_doReplaceTrack - no P2P JingleSession');\n        }\n\n        await Promise.all(replaceTrackPromises);\n    }\n\n    /**\n   * Handler for when a source-add for a local source is rejected by Jicofo.\n   * @param {JingleSessionPC} jingleSession - The media session.\n   * @param {Error} error - The error message.\n   * @param {MediaType} mediaType - The media type of the track associated with the source that was rejected.\n   * @param {Object} _ctx - Unused context object passed by JingleSessionPC.\n   * @param {Array<string>} sourceNames - Source names of the rejected sources, when available.\n   * @returns {void}\n   */\n    private _removeLocalSourceOnReject(\n            jingleSession: JingleSessionPC,\n            error: Error,\n            mediaType: MediaType,\n            _ctx?: object,\n            sourceNames: string[] = []): void {\n        if (!jingleSession) {\n            return;\n        }\n        const errorReason = (error as { reason?: string; })?.reason;\n\n        logger.warn(`Source-add rejected on ${jingleSession}, reason=\"${errorReason}\", message=\"${error?.message}\"`\n            + `, sourceNames=${sourceNames.join(',')}`);\n\n        const localTracks = this.getLocalTracks(mediaType);\n        const rejectedTracks = sourceNames.length\n            ? localTracks.filter(t => sourceNames.includes(t.getSourceName()))\n            : localTracks.slice(0, 1);\n\n        for (const track of rejectedTracks) {\n            this.eventEmitter.emit(JitsiConferenceEvents.TRACK_UNMUTE_REJECTED, track);\n        }\n    }\n\n    /**\n   * Operations related to creating a new track.\n   * @param {JitsiLocalTrack} newTrack - The new track being created.\n   */\n    private _setupNewTrack(newTrack: JitsiLocalTrack): void {\n        const mediaType = newTrack.getType();\n\n        if (!newTrack.getSourceName()) {\n            const sourceName = getSourceNameForJitsiTrack(\n            this.myUserId(),\n            mediaType,\n            this.getLocalTracks(mediaType)?.length);\n\n            newTrack.setSourceName(sourceName);\n        }\n\n        this.rtc.addLocalTrack(newTrack);\n        newTrack.setConference(this);\n\n\n        // Add event handlers.\n        this._unsubscribers.push(newTrack.addCancellableListener(JitsiTrackEvents.TRACK_MUTE_CHANGED, this._fireMuteChangeEvent.bind(this, newTrack)));\n\n        if (newTrack.isAudioTrack()) {\n            this._unsubscribers.push(newTrack.addCancellableListener(JitsiTrackEvents.TRACK_AUDIO_LEVEL_CHANGED, this._fireAudioLevelChangeEvent.bind(this)));\n        }\n\n        this.eventEmitter.emit(JitsiConferenceEvents.TRACK_ADDED, newTrack);\n    }\n\n    /**\n   * Sets the video type.\n   * @param {JitsiLocalTrack} track - The track.\n   * @return {boolean} <tt>true</tt> if video type was changed in presence.\n   * @private\n   */\n    private _setNewVideoType(track: JitsiLocalTrack): boolean {\n        let videoTypeChanged = false;\n\n        if (track) {\n            videoTypeChanged = this._signalingLayer.setTrackVideoType(track.getSourceName(), track.videoType) || false;\n        }\n\n        return videoTypeChanged;\n    }\n\n    /**\n     * Maybe clears the timeout which emits {@link ACTION_JINGLE_SI_TIMEOUT}\n     * analytics event.\n     * @private\n     */\n    private _maybeClearSITimeout(): void {\n        if (this._sessionInitiateTimeout\n                && (this.jvbJingleSession || this.getParticipantCount() < 2)) {\n            window.clearTimeout(this._sessionInitiateTimeout);\n            this._sessionInitiateTimeout = null;\n        }\n    }\n\n    /**\n     * Sets a timeout which will emit {@link ACTION_JINGLE_SI_TIMEOUT} analytics\n     * event.\n     * @private\n     */\n    private _maybeSetSITimeout(): void {\n        // Jicofo is supposed to invite if there are at least 2 participants\n        if (!this.jvbJingleSession\n                && this.getParticipantCount() >= 2\n                && !this._sessionInitiateTimeout) {\n            this._sessionInitiateTimeout = window.setTimeout(() => {\n                this._sessionInitiateTimeout = null;\n                Statistics.sendAnalytics(createJingleEvent(\n                    AnalyticsEvents.ACTION_JINGLE_SI_TIMEOUT,\n                    {\n                        p2p: false,\n                        value: JINGLE_SI_TIMEOUT\n                    }));\n            }, JINGLE_SI_TIMEOUT);\n        }\n    }\n\n\n    /**\n     * Clears the deferred start P2P task if it has been scheduled.\n     * @private\n     */\n    private _maybeClearDeferredStartP2P(): void {\n        if (this.deferredStartP2PTask) {\n            logger.info('Cleared deferred start P2P task');\n            clearTimeout(this.deferredStartP2PTask);\n            this.deferredStartP2PTask = null;\n        }\n    }\n\n    /**\n         * Removes from the conference remote tracks associated with the JVB\n     * connection.\n     * @private\n     */\n    private _removeRemoteJVBTracks(): void {\n        this._removeRemoteTracks(\n            'JVB', this.jvbJingleSession.peerconnection.getRemoteTracks());\n    }\n\n    /**\n     * Removes from the conference remote tracks associated with the P2P\n     * connection.\n     * @private\n     */\n    private _removeRemoteP2PTracks(): void {\n        this._removeRemoteTracks(\n            'P2P', this.p2pJingleSession.peerconnection.getRemoteTracks());\n    }\n\n    /**\n     * Generates fake \"remote track removed\" events for given Jingle session.\n     * @param {string} sessionNickname the session's nickname which will appear in\n     * log messages.\n     * @param {Array<JitsiRemoteTrack>} remoteTracks the tracks that will be removed\n     * @private\n     */\n    private _removeRemoteTracks(sessionNickname: string, remoteTracks: JitsiRemoteTrack[]): void {\n        for (const track of remoteTracks) {\n            logger.info(`Removing remote ${sessionNickname} track: ${track}`);\n            this.onRemoteTrackRemoved(track);\n        }\n    }\n\n    /**\n     * Resumes media transfer over the JVB connection.\n     * @private\n     */\n    private _resumeMediaTransferForJvbConnection(): void {\n        logger.info('Resuming media transfer over the JVB connection...');\n        this.jvbJingleSession.setMediaTransferActive(true)\n            .then(() => {\n                logger.info('Resumed media transfer over the JVB connection!');\n            })\n            .catch(error => {\n                logger.error('Failed to resume media transfer over the JVB connection:', error);\n            });\n    }\n\n    /**\n     * Sets new P2P status and updates some events/states hijacked from\n     * the <tt>JitsiConference</tt>.\n         * @param {boolean} newStatus the new P2P status value, <tt>true</tt> means that\n     * P2P is now in use, <tt>false</tt> means that the JVB connection is now in use\n     * @private\n     */\n    private _setP2PStatus(newStatus: boolean): void {\n        if (this.p2p === newStatus) {\n            logger.debug(`Called _setP2PStatus with the same status: ${newStatus}`);\n\n            return;\n        }\n        this.p2p = newStatus;\n        if (newStatus) {\n            logger.info('Peer to peer connection established!');\n\n            // When we end up in a valid P2P session need to reset the properties\n            // in case they have persisted, after session with another peer.\n            Statistics.analytics.addPermanentProperties({\n                p2pFailed: false\n            });\n\n            // Sync up video transfer active in case p2pJingleSession not existed\n            // when the lastN value was being adjusted.\n            const isVideoActive = this.getLastN() !== 0;\n\n            this.p2pJingleSession.setP2pVideoTransferActive(isVideoActive)\n                .catch(error => {\n                    logger.error(`Failed to sync up P2P video transfer status (${isVideoActive}), ${error}`);\n                });\n        } else {\n            logger.info('Peer to peer connection closed!');\n        }\n\n        // Clear dtmfManager, so that it can be recreated with new connection\n        this.dtmfManager = null;\n\n        // Update P2P status\n        this.eventEmitter.emit(\n            JitsiConferenceEvents.P2P_STATUS,\n            this,\n            this.p2p);\n        this.eventEmitter.emit(JitsiConferenceEvents._MEDIA_SESSION_ACTIVE_CHANGED, this.getActiveMediaSession());\n\n        // Refresh connection interrupted/restored\n        this.eventEmitter.emit(\n            this.isConnectionInterrupted()\n                ? JitsiConferenceEvents.CONNECTION_INTERRUPTED\n                : JitsiConferenceEvents.CONNECTION_RESTORED);\n    }\n\n    /**\n     * Starts new P2P session.\n     * @param {string} remoteJid the JID of the remote participant\n     * @private\n     */\n    private _startP2PSession(remoteJid: string): void {\n        this._maybeClearDeferredStartP2P();\n        if (this.p2pJingleSession) {\n            logger.error('P2P session already started!');\n\n            return;\n        }\n\n        this.isP2PConnectionInterrupted = false;\n        this.p2pJingleSession\n            = this.xmpp.connection.jingle.newP2PJingleSession(\n                this.room.myroomjid,\n                remoteJid);\n        logger.info(\n            'Created new P2P JingleSession', this.room.myroomjid, remoteJid);\n        this._sendConferenceJoinAnalyticsEvent();\n\n        this.p2pJingleSession.initialize(\n            this.room,\n            this.rtc,\n            this._signalingLayer,\n            {\n                ...this.options.config,\n                codecSettings: {\n                    codecList: this.qualityController.codecController.getCodecPreferenceList('p2p'),\n                    mediaType: MediaType.VIDEO,\n                    screenshareCodec: this.qualityController.codecController.getScreenshareCodec('p2p')\n                },\n                enableInsertableStreams: this.isE2EEEnabled() || FeatureFlags.isRunInLiteModeEnabled()\n            });\n\n        const localTracks = this.getLocalTracks();\n\n        this.p2pJingleSession.invite(localTracks)\n            .then(() => {\n                this.p2pJingleSession?.addEventListener(MediaSessionEvents.VIDEO_CODEC_CHANGED, () => {\n                    this.eventEmitter.emit(JitsiConferenceEvents.VIDEO_CODEC_CHANGED);\n                });\n            })\n            .catch(error => {\n                logger.error('Failed to start P2P Jingle session', error);\n\n                if (this.p2pJingleSession) {\n                    this.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_FAILED,\n                    JitsiConferenceErrors.OFFER_ANSWER_FAILED, error);\n                }\n            });\n    }\n\n    /**\n     * Suspends media transfer over the JVB connection.\n     * @private\n     */\n    private _suspendMediaTransferForJvbConnection(): void {\n        logger.info('Suspending media transfer over the JVB connection...');\n        this.jvbJingleSession.setMediaTransferActive(false)\n            .then(() => {\n                logger.info('Suspended media transfer over the JVB connection !');\n            })\n            .catch(error => {\n                logger.error('Failed to suspend media transfer over the JVB connection:', error);\n            });\n    }\n\n    /**\n     * Method when called will decide whether it's the time to start or stop\n     * the P2P session.\n     * @param {boolean} userLeftEvent if <tt>true</tt> it means that the call\n     * originates from the user left event.\n     * @private\n     */\n    private _maybeStartOrStopP2P(userLeftEvent: boolean = false): void {\n        if (!this.isP2PEnabled()\n                || this.isP2PTestModeEnabled()\n                || (browser.isFirefox() && !this._firefoxP2pEnabled)\n                || this.isE2EEEnabled()) {\n            logger.info('Auto P2P disabled');\n\n            return;\n        }\n        const peers = this.getParticipants();\n        const peerCount = peers.length;\n\n        // FIXME 1 peer and it must *support* P2P switching\n        const shouldBeInP2P = this._shouldBeInP2PMode();\n\n        // Clear deferred \"start P2P\" task\n        if (!shouldBeInP2P && this.deferredStartP2PTask) {\n            this._maybeClearDeferredStartP2P();\n        }\n\n        // Start peer to peer session\n        if (!this.p2pJingleSession && shouldBeInP2P) {\n            const peer = peerCount && peers[0];\n            const myId = this.myUserId();\n            const peersId = peer.getId();\n            const jid = peer.getJid();\n\n            // Force initiator or responder mode for testing if option is passed to config.\n            if (this.options.config.testing?.forceInitiator) {\n                logger.debug(`Forcing P2P initiator, will start P2P with: ${jid}`);\n                this._startP2PSession(jid);\n            } else if (this.options.config.testing?.forceResponder) {\n                logger.debug(`Forcing P2P responder, will wait for the other peer ${jid} to start P2P`);\n            } else {\n                if (myId > peersId) {\n                    logger.debug('I\\'m the bigger peersId - the other peer should start P2P', myId, peersId);\n\n                    return;\n                } else if (myId === peersId) {\n                    logger.error('The same IDs ? ', myId, peersId);\n\n                    return;\n                }\n\n                if (userLeftEvent) {\n                    if (this.deferredStartP2PTask) {\n                        logger.error('Deferred start P2P task\\'s been set already!');\n\n                        return;\n                    }\n                    logger.info(`Will start P2P with: ${jid} after ${this.backToP2PDelay} seconds...`);\n                    this.deferredStartP2PTask = Number(setTimeout(\n                        this._startP2PSession.bind(this, jid),\n                        this.backToP2PDelay * 1000));\n                } else {\n                    logger.info(`Will start P2P with: ${jid}`);\n                    this._startP2PSession(jid);\n                }\n            }\n        } else if (this.p2pJingleSession && !shouldBeInP2P) {\n            logger.info(`Will stop P2P with: ${this.p2pJingleSession.remoteJid}`);\n\n            // Log that there will be a switch back to the JVB connection\n            if (this.p2pJingleSession.isInitiator && peerCount > 1) {\n                Statistics.sendAnalyticsAndLog(\n                    createP2PEvent(AnalyticsEvents.ACTION_P2P_SWITCH_TO_JVB));\n            }\n            this._stopP2PSession();\n        }\n    }\n\n    /**\n     * Tells whether or not this conference should be currently in the P2P mode.\n     *\n     * @private\n     * @returns {boolean}\n     */\n    private _shouldBeInP2PMode(): boolean {\n        const peers = this.getParticipants();\n        const peerCount = peers.length;\n        const hasBotPeer = peers.find(p => p.getBotType() === 'poltergeist'\n            || p.hasFeature(FEATURE_JIGASI)) !== undefined;\n        const shouldBeInP2P = peerCount === 1 && !hasBotPeer && !this._hasVisitors\n        && !this._transcribingEnabled && this._buildDesiredTranslations().size === 0;\n\n        logger.debug(`P2P? peerCount: ${peerCount}, hasBotPeer: ${hasBotPeer} => ${shouldBeInP2P}`);\n\n        return shouldBeInP2P;\n    }\n\n    /**\n     * Stops the current P2P session.\n     * @param {Object} options - Options for stopping P2P.\n     * @param {string} options.reason - One of the Jingle \"reason\" element\n     * names as defined by https://xmpp.org/extensions/xep-0166.html#def-reason\n     * @param {string} options.reasonDescription - Text description that will be\n     * included in the session terminate message.\n     * @param {boolean} options.requestRestart - Whether this is due to a session restart, in which case\n     * media will not be resumed on the JVB.\n     * @private\n     */\n    private _stopP2PSession(options: { reason?: string; reasonDescription?: string; requestRestart?: boolean; } = {}): void {\n        const {\n            reason = 'success',\n            reasonDescription = 'Turning off P2P session',\n            requestRestart = false\n        } = options;\n\n        if (!this.p2pJingleSession) {\n            logger.error('No P2P session to be stopped!');\n\n            return;\n        }\n\n        const wasP2PEstablished = this.isP2PActive();\n\n        // Swap remote tracks, but only if the P2P has been fully established\n        if (wasP2PEstablished) {\n            if (this.jvbJingleSession && !requestRestart) {\n                this._resumeMediaTransferForJvbConnection();\n            }\n\n            // Remove remote P2P tracks\n            this._removeRemoteP2PTracks();\n        }\n\n        // Stop P2P stats\n        logger.info('Stopping remote stats for P2P connection');\n        this.statistics.stopRemoteStats(this.p2pJingleSession.peerconnection);\n\n        this.p2pJingleSession.terminate(\n            () => {\n                logger.info('P2P session terminate RESULT');\n                this.p2pJingleSession = null;\n            },\n            error => {\n                // Because both initiator and responder are simultaneously\n                // terminating their JingleSessions in case of the 'to JVB switch'\n                // when 3rd participant joins, both will dispose their sessions and\n                // reply with 'item-not-found' (see strophe.jingle.js). We don't\n                // want to log this as an error since it's expected behaviour.\n                //\n                // We want them both to terminate, because in case of initiator's\n                // crash the responder would stay in P2P mode until ICE fails which\n                // could take up to 20 seconds.\n                //\n                // NOTE: whilst this is an error callback,  'success' as a reason is\n                // considered as graceful session terminate\n                // where both initiator and responder terminate their sessions\n                // simultaneously.\n                if (reason !== 'success') {\n                    logger.error('An error occurred while trying to terminate P2P Jingle session', error);\n                }\n            }, {\n                reason,\n                reasonDescription,\n                sendSessionTerminate: Boolean(this.room\n                    && this.getParticipantById(\n                        Strophe.getResourceFromJid(this.p2pJingleSession.remoteJid))\n                )\n            });\n\n        this.p2pJingleSession = null;\n\n        // Update P2P status and other affected events/states\n        this._setP2PStatus(false);\n\n        if (wasP2PEstablished) {\n            // Add back remote JVB tracks\n            if (this.jvbJingleSession && !requestRestart) {\n                this._addRemoteJVBTracks();\n            } else {\n                logger.info('Not adding remote JVB tracks - no session yet');\n            }\n        }\n    }\n\n    /**\n     * Updates room presence if needed and send the packet in case of a modification.\n     * @param {JingleSessionPC} jingleSession the session firing the event, contains the peer connection which\n     * tracks we will check.\n     * @param {Object|null} ctx a context object we can distinguish multiple calls of the same pass of updating tracks.\n     */\n    private _updateRoomPresence(jingleSession: JingleSessionPC, ctx: { skip?: boolean; } = {}): void {\n        if (!jingleSession) {\n            return;\n        }\n\n        // skips sending presence twice for the same pass of updating ssrcs\n        if (ctx) {\n            if (ctx.skip) {\n                return;\n            }\n            ctx.skip = true;\n        }\n\n        let presenceChanged = false;\n        let muteStatusChanged: boolean;\n        let videoTypeChanged: boolean;\n        const localTracks = jingleSession.peerconnection.getLocalTracks();\n\n        // Set presence for all the available local tracks.\n        for (const track of localTracks) {\n            const muted = track.isMuted();\n\n            muteStatusChanged = this._setTrackMuteStatus(track, muted);\n            muteStatusChanged && logger.debug(`Updating mute state of ${track} in presence to muted=${muted}`);\n            if (track.getType() === MediaType.VIDEO) {\n                videoTypeChanged = this._setNewVideoType(track);\n                videoTypeChanged && logger.debug(`Updating videoType in presence to ${track.getVideoType()}`);\n            }\n            presenceChanged = presenceChanged || muteStatusChanged || videoTypeChanged;\n        }\n\n        presenceChanged && this.room.sendPresence();\n    }\n\n\n    /**\n     * Updates features for a participant.\n     * @param {JitsiParticipant} participant - The participant to query for features.\n     * @returns {void}\n     * @private\n     */\n    private _updateFeatures(participant: JitsiParticipant): void {\n        participant.getFeatures()\n            .then(features => {\n                participant._supportsDTMF = features.has('urn:xmpp:jingle:dtmf:0');\n                this.updateDTMFSupport();\n\n                if (features.has(FEATURE_JIGASI)) {\n                    participant.setProperty('features_jigasi', true);\n                }\n\n                if (features.has(FEATURE_E2EE)) {\n                    participant.setProperty('features_e2ee', true);\n                }\n            })\n            .catch(() => false);\n    }\n\n\n    /**\n     * Accepts an incoming call event for the JVB Jingle session.\n     * @param {JingleSessionPC} jingleSession - The Jingle session for the incoming call.\n     * @param {Element} jingleOffer - An element pointing to 'jingle' IQ element containing the offer.\n     * @param {number} now - The timestamp when the call was received.\n     * @private\n     */\n    private _acceptJvbIncomingCall(jingleSession: JingleSessionPC, jingleOffer: Element, now: number): void {\n        // Accept incoming call\n        this.jvbJingleSession = jingleSession;\n        this.room.connectionTimes['session.initiate'] = now;\n        this._sendConferenceJoinAnalyticsEvent();\n\n        if (this.wasStopped) {\n            Statistics.sendAnalyticsAndLog(createJingleEvent(AnalyticsEvents.ACTION_JINGLE_RESTART, { p2p: false }));\n        }\n\n        // Use *|xmlns to match xmlns attributes across any namespace (CSS Selectors Level 3)\n        const serverRegion = getAttribute(findFirst(jingleOffer, ':scope>bridge-session[*|xmlns=\"http://jitsi.org/protocol/focus\"]'), 'region');\n\n        this.eventEmitter.emit(JitsiConferenceEvents.SERVER_REGION_CHANGED, serverRegion);\n\n        this._maybeClearSITimeout();\n        Statistics.sendAnalytics(createJingleEvent(\n            AnalyticsEvents.ACTION_JINGLE_SI_RECEIVED,\n            {\n                p2p: false,\n                value: now\n            }));\n\n        try {\n            jingleSession.initialize(\n                this.room,\n                this.rtc,\n                this._signalingLayer,\n                {\n                    ...this.options.config,\n                    codecSettings: {\n                        codecList: this.qualityController.codecController.getCodecPreferenceList('jvb'),\n                        mediaType: MediaType.VIDEO,\n                        screenshareCodec: this.qualityController.codecController.getScreenshareCodec('jvb')\n                    },\n                    enableInsertableStreams: this.isE2EEEnabled() || FeatureFlags.isRunInLiteModeEnabled()\n                });\n        } catch (error) {\n            logger.error(error);\n\n            return;\n        }\n\n        // Open a channel with the videobridge.\n        this._setBridgeChannel(jingleOffer, jingleSession.peerconnection);\n\n        const localTracks = this.getLocalTracks();\n\n        try {\n            jingleSession.acceptOffer(\n                jingleOffer,\n                () => {\n                    // If for any reason invite for the JVB session arrived after\n                    // the P2P has been established already the media transfer needs\n                    // to be turned off here.\n                    if (this.isP2PActive() && this.jvbJingleSession) {\n                        this._suspendMediaTransferForJvbConnection();\n                    }\n\n                    this.eventEmitter.emit(JitsiConferenceEvents._MEDIA_SESSION_STARTED, jingleSession);\n                    if (!this.isP2PActive()) {\n                        this.eventEmitter.emit(JitsiConferenceEvents._MEDIA_SESSION_ACTIVE_CHANGED, jingleSession);\n                    }\n\n                    jingleSession.addEventListener(MediaSessionEvents.VIDEO_CODEC_CHANGED, () => {\n                        this.eventEmitter.emit(JitsiConferenceEvents.VIDEO_CODEC_CHANGED);\n                    });\n                },\n                error => {\n                    logger.error('Failed to accept incoming JVB Jingle session', error);\n                    this.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_FAILED,\n                        JitsiConferenceErrors.OFFER_ANSWER_FAILED, error);\n                },\n                localTracks\n            );\n\n            // Set the capture fps for screenshare if it is set through the UI.\n            this._desktopSharingFrameRate\n                && jingleSession.peerconnection.setDesktopSharingFrameRate(this._desktopSharingFrameRate);\n\n            this.statistics.startRemoteStats(this.jvbJingleSession.peerconnection);\n        } catch (e) {\n            logger.error(e);\n        }\n    }\n\n    /**\n     * Sets the BridgeChannel.\n     *\n     * @param {Object} offerIq - An element pointing to the jingle element of\n     * the offer IQ which may carry the WebSocket URL for the 'websocket'\n     * BridgeChannel mode.\n     * @param {TraceablePeerConnection} pc - The peer connection which will be used\n     * to listen for new WebRTC Data Channels (in the 'datachannel' mode).\n     * @private\n     */\n    private _setBridgeChannel(offerIq: Element, pc: TraceablePeerConnection): void {\n        const ignoreDomain = this.connection?.options?.bridgeChannel?.ignoreDomain;\n        const preferSctp = this.connection?.options?.bridgeChannel?.preferSctp ?? true;\n        const sctpOffered = findAll(offerIq, ':scope>content[name=\"data\"]').length === 1;\n        let wsUrl = null;\n\n        logger.info(`SCTP: offered=${sctpOffered}, prefered=${preferSctp}`);\n\n        if (!(sctpOffered && preferSctp)) {\n            findAll(offerIq, ':scope>content>transport>web-socket')\n                .map(e => e.getAttribute('url'))\n                .forEach(url => {\n                    if (!wsUrl && (!ignoreDomain || ignoreDomain !== new URL(url).hostname)) {\n                        wsUrl = url;\n                        logger.info(`Using colibri-ws url ${url}`);\n                    } else if (!wsUrl) {\n                        logger.info(`Ignoring colibri-ws url with domain ${ignoreDomain}`);\n                    }\n                });\n\n            if (!wsUrl) {\n                const firstWsUrl = findFirst(offerIq, ':scope>content>transport>web-socket');\n\n                if (firstWsUrl) {\n                    wsUrl = firstWsUrl.getAttribute('url');\n                    logger.info(`Falling back to ${wsUrl}`);\n                }\n            }\n        }\n\n        if (wsUrl && !(sctpOffered && preferSctp)) {\n            // If the offer contains a websocket and we don't prefer SCTP use it.\n            this.rtc.initializeBridgeChannel(null, wsUrl);\n        } else if (sctpOffered) {\n            // Otherwise, fall back to an attempt to use SCTP.\n            this.rtc.initializeBridgeChannel(pc.peerconnection, null);\n        } else {\n            logger.warn('Neither SCTP nor a websocket is available. Will not initialize bridge channel.');\n        }\n    }\n\n    /**\n     * Rejects incoming Jingle call.\n     * @param {JingleSessionPC} jingleSession - The session instance to be rejected.\n     * @param {object} [options] - Optional parameters for rejection.\n     * @param {string} options.reason - The name of the reason element as defined by Jingle.\n     * @param {string} options.reasonDescription - The reason description which will be\n     *  included in Jingle 'session-terminate' message.\n     * @param {string} options.errorMsg - An error message to be logged on global error handler.\n     * @private\n     */\n    private _rejectIncomingCall(jingleSession: JingleSessionPC, options: {\n        errorMsg?: string;\n        reason?: string;\n        reasonDescription?: string;\n    }): void {\n        if (options?.errorMsg) {\n            logger.warn(options.errorMsg);\n        }\n\n        // Terminate the jingle session with a reason\n        jingleSession.terminate(\n            null /* success callback => we don't care */,\n            error => {\n                logger.warn(\n                    'An error occurred while trying to terminate'\n                        + ' invalid Jingle session', error);\n            }, {\n                reason: options?.reason,\n                reasonDescription: options?.reasonDescription,\n                sendSessionTerminate: true\n            });\n    }\n\n    /**\n     * Handles an incoming call event for the P2P Jingle session.\n     * @param {JingleSessionPC} jingleSession - The Jingle session for the incoming call.\n     * @param {Element} jingleOffer - An element pointing to 'jingle' IQ element containing the offer.\n     * @private\n     */\n    private _onIncomingCallP2P(jingleSession: JingleSessionPC, jingleOffer: Element): void {\n        let rejectReason;\n        const contentName = getAttribute(findFirst(jingleOffer, ':scope>content'), 'name');\n        const peerUsesUnifiedPlan = contentName === '0' || contentName === '1';\n\n        // Reject P2P between endpoints that are not running in the same mode w.r.t to SDPs (plan-b and unified plan).\n        if (!peerUsesUnifiedPlan) {\n            rejectReason = {\n                errorMsg: 'P2P across two endpoints in different SDP modes is disabled',\n                reason: 'decline',\n                reasonDescription: 'P2P disabled'\n            };\n        } else if ((!this.isP2PEnabled() && !this.isP2PTestModeEnabled())\n            || (browser.isFirefox() && !this._firefoxP2pEnabled)) {\n            rejectReason = {\n                errorMsg: 'P2P mode disabled in the configuration or browser unsupported',\n                reason: 'decline',\n                reasonDescription: 'P2P disabled'\n            };\n        } else if (this.p2pJingleSession) {\n            // Reject incoming P2P call (already in progress)\n            rejectReason = {\n                errorMsg: 'Duplicated P2P \"session-initiate\"',\n                reason: 'busy',\n                reasonDescription: 'P2P already in progress'\n            };\n        } else if (!this._shouldBeInP2PMode()) {\n            rejectReason = {\n                errorMsg: 'Received P2P \"session-initiate\" when should not be in P2P mode',\n                reason: 'decline',\n                reasonDescription: 'P2P requirements not met'\n            };\n            Statistics.sendAnalytics(createJingleEvent(AnalyticsEvents.ACTION_P2P_DECLINED));\n        }\n\n        if (rejectReason) {\n            this._rejectIncomingCall(jingleSession, rejectReason);\n        } else {\n            this._acceptP2PIncomingCall(jingleSession, jingleOffer);\n        }\n    }\n\n\n    /**\n     * Handles CONNECTION_INTERRUPTED event.\n     * @param {JingleSessionPC} session - The Jingle session.\n     * @private\n     */\n    private _onIceConnectionInterrupted(session: JingleSessionPC): void {\n        if (session.isP2P) {\n            this.isP2PConnectionInterrupted = true;\n        } else {\n            this.isJvbConnectionInterrupted = true;\n        }\n        if (session.isP2P === this.isP2PActive()) {\n            this.eventEmitter.emit(JitsiConferenceEvents.CONNECTION_INTERRUPTED);\n        }\n    }\n\n    /**\n     * Handles CONNECTION_ICE_FAILED event.\n     * @param {JingleSessionPC} session - The Jingle session.\n     * @private\n     */\n    private _onIceConnectionFailed(session: JingleSessionPC): void {\n        if (session.isP2P) {\n            // Add p2pFailed property to analytics to distinguish, between \"good\"\n            // and \"bad\" connection\n            Statistics.analytics.addPermanentProperties({ p2pFailed: true });\n\n            if (this.p2pJingleSession) {\n                Statistics.sendAnalyticsAndLog(\n                    createP2PEvent(\n                        AnalyticsEvents.ACTION_P2P_FAILED,\n                        {\n                            initiator: this.p2pJingleSession.isInitiator\n                        }));\n\n            }\n            this._stopP2PSession({\n                reason: 'connectivity-error',\n                reasonDescription: 'ICE FAILED'\n            });\n        } else if (session && this.jvbJingleSession === session && this._iceRestarts < MAX_CONNECTION_RETRIES) {\n            // Use an exponential backoff timer for ICE restarts.\n            const jitterDelay = getJitterDelay(this._iceRestarts, 1000 /* min. delay */);\n\n            setTimeout(() => {\n                this._iceRestarts++;\n                if (this.isIceRestartSupported()) {\n                    logger.info(`Attempting an in-place ICE restart after ${jitterDelay}`);\n                    this._restartJvbIceWithFallback();\n                } else {\n                    logger.error(`triggering ice restart after ${jitterDelay} `);\n                    this._delayedIceFailed = new IceFailedHandling(this);\n                    this._delayedIceFailed.start();\n                }\n            }, jitterDelay);\n        } else if (this.jvbJingleSession === session) {\n            logger.warn('ICE failed, force reloading the conference after failed attempts to re-establish ICE');\n            Statistics.sendAnalyticsAndLog(\n                createJvbIceFailedEvent(\n                    AnalyticsEvents.ACTION_JVB_ICE_FAILED,\n                    {\n                        participantId: this.myUserId(),\n                        userRegion: this.options.config.deploymentInfo?.userRegion\n                    }));\n            this.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_FAILED, JitsiConferenceErrors.ICE_FAILED);\n        }\n    }\n\n    /**\n     * Attempts an in-place ICE restart of the JVB session, falling back to the legacy session restart\n     * (session-terminate with a restart request, handled by Jicofo with a re-invite) if the request fails or if\n     * ICE doesn't recover within a timeout.\n     *\n     * @private\n     * @returns {void}\n     */\n    private _restartJvbIceWithFallback(): void {\n        const fallback = (message: string) => {\n            logger.warn(`${message}, falling back to a session restart`);\n            this._delayedIceFailed = new IceFailedHandling(this);\n            this._delayedIceFailed.start();\n        };\n\n        this.restartJvbIce(IceRestartReason.ICE_FAILED)\n            .then(() => {\n                setTimeout(() => {\n                    const iceState = this.jvbJingleSession?.getIceConnectionState();\n\n                    if (iceState !== 'connected' && iceState !== 'completed') {\n                        fallback(`ICE not recovered (state=${iceState}) after an in-place ICE restart`);\n                    }\n                }, JVB_ICE_RESTART_RECOVERY_TIMEOUT);\n            })\n            .catch(error => fallback(`In-place ICE restart request failed (${error?.message ?? error})`));\n    }\n\n    /**\n     * Handles P2P_TERMINATION_REQUIRED event. Fired when a source-remove is detected on a P2P connection, which\n     * indicates that the browser has regenerated SSRCs for an existing source. The P2P session is stopped so the\n     * call falls back to JVB.\n     *\n     * @param {JingleSessionPC} session - The P2P Jingle session.\n     * @private\n     */\n    private _onP2PTerminationRequired(session: JingleSessionPC): void {\n        if (session !== this.p2pJingleSession) {\n            return;\n        }\n\n        logger.warn('Stopping P2P session due to SSRC regeneration on P2P connection');\n        this._stopP2PSession({\n            reason: 'connectivity-error',\n            reasonDescription: 'P2P SSRC regeneration'\n        });\n    }\n\n    /**\n     * Handles CONNECTION_RESTORED event.\n     * @param {JingleSessionPC} session - The Jingle session.\n     * @private\n     */\n    private _onIceConnectionRestored(session: JingleSessionPC): void {\n        if (session.isP2P) {\n            this.isP2PConnectionInterrupted = false;\n        } else {\n            this.isJvbConnectionInterrupted = false;\n            this._delayedIceFailed?.cancel();\n        }\n\n        if (session.isP2P === this.isP2PActive()) {\n            this.eventEmitter.emit(JitsiConferenceEvents.CONNECTION_RESTORED);\n        }\n    }\n\n    /**\n     * Accepts an incoming P2P Jingle call.\n     * @param {JingleSessionPC} jingleSession - The Jingle session instance.\n     * @param {Element} jingleOffer - An element pointing to 'jingle' IQ element containing the offer.\n     * @private\n     */\n    private _acceptP2PIncomingCall(jingleSession: JingleSessionPC, jingleOffer: Element): void {\n        this.isP2PConnectionInterrupted = false;\n\n        // Accept the offer\n        this.p2pJingleSession = jingleSession;\n        this._sendConferenceJoinAnalyticsEvent();\n\n        this.p2pJingleSession.initialize(\n            this.room,\n            this.rtc,\n            this._signalingLayer,\n            {\n                ...this.options.config,\n                codecSettings: {\n                    codecList: this.qualityController.codecController.getCodecPreferenceList('p2p'),\n                    mediaType: MediaType.VIDEO,\n                    screenshareCodec: this.qualityController.codecController.getScreenshareCodec('p2p')\n                },\n                enableInsertableStreams: this.isE2EEEnabled() || FeatureFlags.isRunInLiteModeEnabled()\n            });\n\n        const localTracks = this.getLocalTracks();\n\n        this.p2pJingleSession.acceptOffer(\n            jingleOffer,\n            () => {\n                logger.debug('Got RESULT for P2P \"session-accept\"');\n\n                this.eventEmitter.emit(\n                    JitsiConferenceEvents._MEDIA_SESSION_STARTED,\n                    jingleSession);\n\n                jingleSession.addEventListener(MediaSessionEvents.VIDEO_CODEC_CHANGED, () => {\n                    this.eventEmitter.emit(JitsiConferenceEvents.VIDEO_CODEC_CHANGED);\n                });\n            },\n            error => {\n                logger.error('Failed to accept incoming P2P Jingle session', error);\n                if (this.p2pJingleSession) {\n                    this.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_FAILED,\n                        JitsiConferenceErrors.OFFER_ANSWER_FAILED, error);\n                }\n            },\n            localTracks);\n    }\n\n    /**\n     * Adds remote tracks to the conference associated with the JVB session.\n     * @private\n     * @returns {void}\n     */\n    private _addRemoteJVBTracks(): void {\n        this._addRemoteTracks('JVB', this.jvbJingleSession.peerconnection.getRemoteTracks());\n    }\n\n    /**\n     * Adds remote tracks to the conference associated with the P2P session.\n     * @private\n     * @returns {void}\n     */\n    private _addRemoteP2PTracks(): void {\n        this._addRemoteTracks('P2P', this.p2pJingleSession.peerconnection.getRemoteTracks());\n    }\n\n    /**\n     * Generates fake \"remote track added\" events for given Jingle session.\n     * @param {string} logName - The session's nickname which will appear in log messages.\n     * @param {Array<JitsiRemoteTrack>} remoteTracks - The tracks that will be added.\n     * @private\n     */\n    private _addRemoteTracks(logName: string, remoteTracks: JitsiRemoteTrack[]): void {\n        for (const track of remoteTracks) {\n            if (this.participants.has(track.ownerEndpointId)) {\n                logger.info(`Adding remote ${logName} track: ${track}`);\n                this.onRemoteTrackAdded(track);\n            }\n        }\n    }\n\n    /**\n     * Handles the ICE connection establishment event for a Jingle session.\n     * @private\n     * @param {JingleSessionPC} jingleSession - The Jingle session for which ICE connection was established.\n     */\n    private _onIceConnectionEstablished(jingleSession: JingleSessionPC): void {\n        if (this.p2pJingleSession !== null) {\n            // store the establishment time of the p2p session as a field of the\n            // JitsiConference because the p2pJingleSession might get disposed (thus\n            // the value is lost).\n            this.p2pEstablishmentDuration\n                = this.p2pJingleSession.establishmentDuration;\n        }\n\n        if (this.jvbJingleSession !== null) {\n            this.jvbEstablishmentDuration\n                = this.jvbJingleSession.establishmentDuration;\n        }\n\n        let done = false;\n\n        // We don't care about the JVB case, there's nothing to be done\n        if (!jingleSession.isP2P) {\n            done = true;\n        } else if (this.p2pJingleSession !== jingleSession) {\n            logger.error('CONNECTION_ESTABLISHED - wrong P2P session instance ?!');\n\n            done = true;\n        }\n\n        if (isValidNumber(this.p2pEstablishmentDuration)\n                && isValidNumber(this.jvbEstablishmentDuration)) {\n            const establishmentDurationDiff\n                = this.p2pEstablishmentDuration - this.jvbEstablishmentDuration;\n\n            Statistics.sendAnalytics(\n                AnalyticsEvents.ICE_ESTABLISHMENT_DURATION_DIFF,\n                { value: establishmentDurationDiff });\n        }\n\n        if (jingleSession.isP2P === this.isP2PActive()) {\n            this.eventEmitter.emit(JitsiConferenceEvents.CONNECTION_ESTABLISHED);\n        }\n\n        if (done) {\n\n            return;\n        }\n\n        // Update P2P status and emit events\n        this._setP2PStatus(true);\n\n        // Remove remote tracks\n        if (this.jvbJingleSession) {\n            this._removeRemoteJVBTracks();\n        } else {\n            logger.info('Not removing remote JVB tracks - no session yet');\n        }\n\n        this._addRemoteP2PTracks();\n\n        // Stop media transfer over the JVB connection\n        if (this.jvbJingleSession) {\n            this._suspendMediaTransferForJvbConnection();\n        }\n\n        logger.info('Starting remote stats with p2p connection');\n        this.statistics.startRemoteStats(this.p2pJingleSession.peerconnection);\n\n        Statistics.sendAnalyticsAndLog(\n            createP2PEvent(\n                AnalyticsEvents.ACTION_P2P_ESTABLISHED,\n                {\n                    initiator: this.p2pJingleSession.isInitiator\n                }));\n    }\n\n    /**\n     * Called when the chat room reads a new list of properties from jicofo's\n     * presence. The properties may have changed, but they don't have to.\n     *\n     * @param {Object} properties - The properties keyed by the property name\n     * ('key').\n     * @private\n     */\n    private _updateProperties(properties: IConferenceProperties = {}): void {\n        const changed = !isEqual(properties, this.properties);\n\n        this.properties = properties;\n        if (changed) {\n            this.eventEmitter.emit(JitsiConferenceEvents.PROPERTIES_CHANGED, this.properties);\n\n            const audioLimitReached = this.properties['audio-limit-reached'] === 'true';\n            const videoLimitReached = this.properties['video-limit-reached'] === 'true';\n\n            if (this._audioSenderLimitReached !== audioLimitReached) {\n                this._audioSenderLimitReached = audioLimitReached;\n                this.eventEmitter.emit(JitsiConferenceEvents.AUDIO_UNMUTE_PERMISSIONS_CHANGED, audioLimitReached);\n                logger.info(`Audio unmute permissions set by Jicofo to ${audioLimitReached}`);\n            }\n\n            if (this._videoSenderLimitReached !== videoLimitReached) {\n                this._videoSenderLimitReached = videoLimitReached;\n                this.eventEmitter.emit(JitsiConferenceEvents.VIDEO_UNMUTE_PERMISSIONS_CHANGED, videoLimitReached);\n                logger.info(`Video unmute permissions set by Jicofo to ${videoLimitReached}`);\n            }\n\n            // Some of the properties need to be added to analytics events.\n            const analyticsKeys = [\n\n                // The number of jitsi-videobridge instances currently used for the\n                // conference.\n                'bridge-count'\n            ];\n\n            analyticsKeys.forEach(key => {\n                if (properties[key] !== undefined) {\n                    Statistics.analytics.addPermanentProperties({\n                        [key.replace('-', '_')]: properties[key]\n                    });\n                }\n            });\n\n            // Handle changes to aggregate list of visitor codecs.\n            let publishedCodecs = this.properties['visitor-codecs']?.split(',');\n\n            if (publishedCodecs?.length) {\n                publishedCodecs = publishedCodecs.filter(codec => typeof codec === 'string'\n                    && codec.trim().length\n                    && Object.values(CodecMimeType).find(val => val === codec));\n            }\n\n            if (this._visitorCodecs !== publishedCodecs) {\n                this._visitorCodecs = publishedCodecs;\n                this.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_VISITOR_CODECS_CHANGED, this._visitorCodecs);\n            }\n\n            const oldValue = this._hasVisitors;\n\n            this._hasVisitors = this.properties['visitor-count'] > 0;\n\n            oldValue !== this._hasVisitors && this._maybeStartOrStopP2P(true);\n        }\n    }\n\n    /**\n     * Fires CONFERENCE_FAILED event with INCOMPATIBLE_SERVER_VERSIONS parameter.\n     * @returns {void}\n     * @private\n     */\n    private _fireIncompatibleVersionsEvent(): void {\n        this.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_FAILED,\n            JitsiConferenceErrors.INCOMPATIBLE_SERVER_VERSIONS);\n    }\n\n    /**\n     * Whether translation is active for any speaker, via the default language or a per-participant override.\n     *\n     * @returns {boolean}\n     */\n    private _isReceiverTranslationActive(): boolean {\n        return Boolean(this._receiverTranslationLanguage)\n            || Array.from(this._participantTranslationLanguages.values()).some(language => language !== null);\n    }\n\n    /**\n     * Resolves the effective translation language for a speaker: the per-participant override if one is set\n     * (which may be null to disable), otherwise the default language.\n     *\n     * @param {string} endpointId - The speaker's endpoint id.\n     * @returns {string|null}\n     */\n    private _resolveTranslationLanguage(endpointId: string): string | null {\n        if (this._participantTranslationLanguages.has(endpointId)) {\n            return this._participantTranslationLanguages.get(endpointId) ?? null;\n        }\n\n        return this._receiverTranslationLanguage;\n    }\n\n    /**\n     * Builds the cumulative set of translated speakers: endpointId -> target language, for every remote\n     * participant whose effective language is set. Drives both the request stanza and the audio subscription.\n     *\n     * @returns {Map<string, string>}\n     */\n    private _buildDesiredTranslations(): Map<string, string> {\n        const desired = new Map<string, string>();\n\n        this.getParticipants().forEach(participant => {\n            const endpointId = participant.getId();\n            const language = this._resolveTranslationLanguage(endpointId);\n\n            if (language) {\n                desired.set(endpointId, language);\n            }\n        });\n\n        return desired;\n    }\n\n    /**\n     * Sends only the delta (vs. what was last advertised) of the desired translation\n     * requests to the audio-translation module: endpointId -> language to set, -> '' to cancel.\n     *\n     * @returns {void}\n     */\n    private _updateTranslationRequests(): void {\n        const desired = this._buildDesiredTranslations();\n        const delta: { [endpointId: string]: string; } = {};\n\n        desired.forEach((lang, endpointId) => {\n            if (this._translationRequests.get(endpointId) !== lang) {\n                delta[endpointId] = lang;\n            }\n        });\n        this._translationRequests.forEach((_lang, endpointId) => {\n            if (!desired.has(endpointId)) {\n                delta[endpointId] = '';\n            }\n        });\n\n        if (Object.keys(delta).length === 0) {\n            return;\n        }\n\n        // Only commit the advertised state once the delta has actually been sent. Otherwise a request issued\n        // before the audio-translation component is discovered would be dropped: the desired state would be\n        // recorded as advertised, so subsequent deltas would compare against it and never re-send.\n        if (this._sendTranslationRequestStanza(delta)) {\n            this._translationRequests = desired;\n        }\n    }\n\n    /**\n     * Sends a translation-request delta to the audio-translation module as a JSON map.\n     *\n     * @param {Object} delta - The changed endpointId -> language entries ('' to cancel).\n     * @returns {boolean} Whether the delta was sent (false when no component has been discovered yet).\n     */\n    private _sendTranslationRequestStanza(delta: { [endpointId: string]: string; }): boolean {\n        const componentAddress = this.xmpp.audioTranslationComponentAddress;\n\n        if (!componentAddress) {\n            logger.warn('Cannot request audio translation: no audio-translation component discovered.');\n\n            return false;\n        }\n\n        this._registerTranslationErrorHandler(componentAddress);\n\n        // Tag the request so a (failure-only) error reply from the component can be mapped back to it.\n        const id = `audio-translation-${++this._translationRequestSeq}`;\n\n        this._pendingTranslationRequests.set(id, delta);\n\n        // The component stays silent on success, so drop the pending entry after a grace period.\n        window.setTimeout(() => this._pendingTranslationRequests.delete(id), TRANSLATION_REQUEST_TIMEOUT);\n\n        const message = $msg({ id,\n            to: componentAddress });\n\n        message.c('audio-translation', { xmlns: 'http://jitsi.org/jitmeet' })\n            .t(JSON.stringify(delta))\n            .up();\n\n        this.xmpp.connection.send(message);\n\n        return true;\n    }\n\n    /**\n     * Registers (once) the handler for `<message type='error'>` replies from the audio-translation\n     * component, so request failures can be surfaced to the UI.\n     *\n     * @param {string} componentAddress - The audio-translation component JID.\n     * @returns {void}\n     */\n    private _registerTranslationErrorHandler(componentAddress: string): void {\n        if (this._translationErrorHandler) {\n            return;\n        }\n        this._translationErrorHandler = this.xmpp.connection.addHandler(\n            this._onTranslationRequestError.bind(this), null, 'message', 'error', null, componentAddress);\n    }\n\n    /**\n     * Handles an error reply from the audio-translation component: maps it back to the failed request via\n     * the stanza id and emits {@link JitsiConferenceEvents.AUDIO_TRANSLATION_FAILED} with the affected\n     * endpoints and the error condition. Returns true to keep the Strophe handler registered.\n     *\n     * @param {Element} stanza - The `<message type='error'>` stanza.\n     * @returns {boolean}\n     */\n    private _onTranslationRequestError(stanza: Element): boolean {\n        const id = getAttribute(stanza, 'id');\n        const requests = id ? this._pendingTranslationRequests.get(id) : undefined;\n\n        if (id) {\n            this._pendingTranslationRequests.delete(id);\n        }\n\n        const condition = findFirst(stanza, 'error')?.firstElementChild?.localName;\n        const error = (Object.values(JitsiAudioTranslationErrors) as string[]).includes(condition ?? '')\n            ? condition as JitsiAudioTranslationErrors\n            : JitsiAudioTranslationErrors.UNKNOWN;\n        const endpointIds = requests ? Object.keys(requests) : [];\n\n        logger.warn(`Audio translation request failed (${error}) for [${endpointIds.join(', ')}]`);\n        this.eventEmitter.emit(JitsiConferenceEvents.AUDIO_TRANSLATION_FAILED, {\n            endpointIds,\n            error,\n            requests\n        });\n\n        return true;\n    }\n\n    /**\n     * Registers (once) the handler for translation-listeners pushes from the audio-translation component.\n     * Registered on join and independent of whether the local participant ever requests a translation, since\n     * the notification is about other participants translating this participant's audio.\n     *\n     * @returns {void}\n     */\n    private _registerTranslationListenersHandler(): void {\n        const componentAddress = this.xmpp.audioTranslationComponentAddress;\n\n        if (this._translationListenersHandler || !componentAddress) {\n            return;\n        }\n        this._translationListenersHandler = this.xmpp.connection.addHandler(\n            this._onTranslationListenersChanged.bind(this), null, 'message', null, null, componentAddress);\n    }\n\n    /**\n     * Handles a translation-listeners push from the audio-translation component and emits\n     * {@link JitsiConferenceEvents.AUDIO_TRANSLATION_LISTENERS_CHANGED} with the endpoint ids currently\n     * listening to a translation of the local participant. Returns true to keep the handler registered.\n     *\n     * @param {Element} stanza - The message stanza from the component.\n     * @returns {boolean}\n     */\n    private _onTranslationListenersChanged(stanza: Element): boolean {\n        const child = findFirst(stanza, 'translation-listeners');\n\n        if (!child) {\n            return true; // Another message from the component (e.g. an error reply handled elsewhere).\n        }\n\n        let listeners: string[] = [];\n\n        // A blank body means \"no listeners\" (an empty list), so only non-empty text is parsed; genuinely\n        // malformed JSON still falls into the catch below and is logged.\n        const text = (child.textContent ?? '').trim();\n\n        if (text) {\n            try {\n                const parsed = JSON.parse(text);\n\n                if (Array.isArray(parsed)) {\n                    listeners = parsed.filter((id): id is string => typeof id === 'string');\n                }\n            } catch (e) {\n                logger.warn('Ignoring malformed translation-listeners payload', e);\n\n                return true;\n            }\n        }\n\n        this.eventEmitter.emit(JitsiConferenceEvents.AUDIO_TRANSLATION_LISTENERS_CHANGED, listeners);\n\n        return true;\n    }\n\n    /**\n     * Subscribes to the cumulative set of translated sources by including them on top of the `all` baseline,\n     * named by convention {endpointId}-a0.{language} so they can be requested before the source is signaled.\n     * Keeping the baseline means the original audio still flows (and can be ducked); an empty include list\n     * (no active translations) clears the opt-in set. Resilient to the source not yet being signaled.\n     *\n     * @returns {void}\n     */\n    private _updateTranslationSubscription(): void {\n        const include = Array.from(\n            this._buildDesiredTranslations(),\n            ([ endpointId, language ]) =>\n                `${getSourceNameForJitsiTrack(endpointId, MediaType.AUDIO, 0)}.${language}`);\n\n        this.qualityController.audioController.setIncludeSources(include);\n    }\n\n    /**\n     * Checks whether an in-place ICE restart of the JVB session can be used: it must be enabled in the client\n     * configuration ('enableIceRestart').\n     *\n     * @returns {boolean}\n     */\n    public isIceRestartSupported(): boolean {\n        return Boolean(this.options.config.enableIceRestart);\n    }\n\n    /**\n     * Triggers an in-place ICE restart of the JVB session: Jicofo is asked to have the bridge create a new ICE\n     * agent with fresh credentials while the old one keeps carrying media (make-before-break). The bridge's new\n     * transport comes back asynchronously as a Jingle 'transport-info' and is applied by\n     * {@link JingleSessionPC.onBridgeIceRestartTransport}, so the promise returned here settling only means that\n     * the request itself was accepted. Trigger from the console: `APP.conference._room.restartJvbIce()`.\n     *\n     * @param {IceRestartReason} reason - Why the restart was triggered, for logs and analytics.\n     * @returns {Promise<void>} - Resolves when Jicofo has accepted the request, rejects otherwise.\n     */\n    public restartJvbIce(reason: IceRestartReason = IceRestartReason.API): Promise<void> {\n        if (!this.isIceRestartSupported()) {\n            return Promise.reject(new Error('ICE restart is not supported (disabled in config)'));\n        }\n\n        const session = this.jvbJingleSession;\n\n        if (!session) {\n            return Promise.reject(new Error('No JVB Jingle session'));\n        }\n\n        return session.restartIce(reason);\n    }\n\n    public restartMediaSessions() {\n        this._restartMediaSessions();\n    }\n\n    /**\n   * Sends the 'VideoTypeMessage' to the bridge on the bridge channel so that the bridge can make bitrate allocation\n   * decisions based on the video type of the local source.\n   *\n   * @param {JitsiLocalTrack} localtrack - The track associated with the local source signaled to the bridge.\n   * @returns {void}\n   * @internal\n   */\n    _sendBridgeVideoTypeMessage(localtrack: JitsiLocalTrack): void {\n        let videoType = !localtrack || localtrack.isMuted() ? BridgeVideoType.NONE : localtrack.getVideoType();\n\n        if (videoType === VideoType.DESKTOP && this._desktopSharingFrameRate > SS_DEFAULT_FRAME_RATE) {\n            videoType = BridgeVideoType.DESKTOP_HIGH_FPS;\n        }\n\n        localtrack && this.rtc.sendSourceVideoType(localtrack.getSourceName(), videoType);\n    }\n\n    /**\n     * Stops the current JVB jingle session.\n     *\n     * @param {Object} options - options for stopping JVB session.\n     * @param {string} options.reason - One of the Jingle \"reason\" element\n     * names as defined by https://xmpp.org/extensions/xep-0166.html#def-reason\n     * @param {string} options.reasonDescription - Text description that will be included\n     * in the session terminate message.\n     * @param {boolean} options.requestRestart - Whether this is due to\n     * a session restart, in which case, session will be\n     * set to null.\n     * @param {boolean} options.sendSessionTerminate - Whether session-terminate needs to be sent to Jicofo.\n     * @internal\n     */\n    _stopJvbSession(options?: { reason?: string; reasonDescription?: string; requestRestart?: boolean; sendSessionTerminate?: boolean; }): void {\n        const {\n            requestRestart = false,\n            sendSessionTerminate = false\n        } = options;\n\n        if (!this.jvbJingleSession) {\n            logger.error('No JVB session to be stopped');\n\n            return;\n        }\n\n        // Remove remote JVB tracks.\n        !this.isP2PActive() && this._removeRemoteJVBTracks();\n\n        logger.info('Stopping stats for jvb connection');\n        this.statistics.stopRemoteStats(this.jvbJingleSession.peerconnection);\n\n        this.jvbJingleSession.terminate(\n            () => {\n                if (requestRestart && sendSessionTerminate) {\n                    logger.info('session-terminate for ice restart - done');\n                }\n                this.jvbJingleSession = null;\n            },\n            error => {\n                if (requestRestart && sendSessionTerminate) {\n                    logger.error('session-terminate for ice restart failed: reloading the client');\n\n                    // Initiate a client reload if Jicofo responds to the session-terminate with an error.\n                    this.eventEmitter.emit(\n                        JitsiConferenceEvents.CONFERENCE_FAILED,\n                        JitsiConferenceErrors.ICE_FAILED);\n                }\n                logger.error(`An error occurred while trying to terminate the JVB session', reason=${error.reason},`\n                    + `msg=${error.msg}`);\n            },\n            options);\n    }\n\n    /**\n     * Method called by the {@link JitsiLocalTrack} in order to remove the underlying MediaStream from the\n     * RTCPeerConnection.\n     * @param {JitsiLocalTrack} track - The local track that will be removed.\n     * @return {Promise} Resolved when the process is done or rejected with a string which describes the error.\n     * @internal\n     */\n    _removeLocalTrackFromPc(track: JitsiLocalTrack): Promise<PromiseSettledResult<void>[]> {\n        const removePromises = [];\n\n        if (track.conference === this) {\n            if (this.jvbJingleSession) {\n                removePromises.push(this.jvbJingleSession.removeTrackFromPc(track));\n            } else {\n                logger.debug('Remove local MediaStream - no JVB JingleSession started yet');\n            }\n            if (this.p2pJingleSession) {\n                removePromises.push(this.p2pJingleSession.removeTrackFromPc(track));\n            } else {\n                logger.debug('Remove local MediaStream - no P2P JingleSession started yet');\n            }\n        }\n\n        return Promise.allSettled(removePromises);\n    }\n\n\n    /**\n   * Method called by the {@link JitsiLocalTrack} in order to add the underlying MediaStream to the RTCPeerConnection.\n   * @param {JitsiLocalTrack} track - The local track that will be added to the pc.\n   * @return {Promise} Resolved when the process is done or rejected with a string which describes the error.\n   * @internal\n   */\n    async _addLocalTrackToPc(track: JitsiLocalTrack): Promise<void> {\n        const addPromises = [];\n\n        if (track.conference === this) {\n            if (this.jvbJingleSession) {\n                addPromises.push(this.jvbJingleSession.addTrackToPc(track));\n            } else {\n                logger.debug('Add local MediaStream - no JVB Jingle session started yet');\n            }\n\n            if (this.p2pJingleSession) {\n                addPromises.push(this.p2pJingleSession.addTrackToPc(track));\n            } else {\n                logger.debug('Add local MediaStream - no P2P Jingle session started yet');\n            }\n        } else {\n            // If the track hasn't been added to the conference yet because of start muted by focus, add it to the\n            // conference instead of adding it only to the media sessions.\n            addPromises.push(this.addTrack(track));\n        }\n\n        await Promise.allSettled(addPromises);\n    }\n\n\n    /**\n   * Sets mute status.\n   * @param {JitsiLocalTrack} localTrack - The local track.\n   * @param {boolean} isMuted - Whether the track is muted.\n   * @return {boolean} <tt>true</tt> when presence was changed, <tt>false</tt> otherwise.\n   * @internal\n   */\n    _setTrackMuteStatus(localTrack: JitsiLocalTrack, isMuted: boolean): boolean {\n        let presenceChanged = false;\n\n        if (localTrack) {\n            presenceChanged = this._signalingLayer.setTrackMuteStatus(localTrack.getSourceName(), isMuted) || false;\n            presenceChanged && logger.debug(`Mute state of ${localTrack} changed to muted=${isMuted}`);\n        }\n\n        return presenceChanged;\n    }\n\n\n    /**\n     * Updates conference startMuted policy if needed and fires an event.\n     * @param {boolean} audio - Whether audio should be muted.\n     * @param {boolean} video - Whether video should be muted.\n     * @returns {void}\n     * @internal\n     */\n    _updateStartMutedPolicy(audio: boolean, video: boolean): void {\n        // Update the start muted policy for the conference only if the meta data is received before conference join.\n        if (this.isJoined()) {\n            return;\n        }\n\n        let updated = false;\n\n        if (audio !== this.startMutedPolicy.audio) {\n            this.startMutedPolicy.audio = audio;\n            updated = true;\n        }\n\n        if (video !== this.startMutedPolicy.video) {\n            this.startMutedPolicy.video = video;\n            updated = true;\n        }\n        if (updated) {\n            this.eventEmitter.emit(\n                JitsiConferenceEvents.START_MUTED_POLICY_CHANGED,\n                this.startMutedPolicy\n            );\n        }\n    }\n\n    /**\n     * Set the transcribingEnabled flag. When transcribing is enabled, p2p is disabled.\n     * @param {boolean} enabled - Whether transcribing should be enabled.\n     * @internal\n     */\n    _setTranscribingEnabled(enabled: boolean): void {\n        if (this._transcribingEnabled !== enabled) {\n            this._transcribingEnabled = enabled;\n            this._maybeStartOrStopP2P(true);\n        }\n    }\n\n\n    /**\n     * Get notified when we joined the room.\n     *\n     * @internal\n     */\n    _onMucJoined(): void {\n        this._numberOfParticipantsOnJoin = this.getParticipantCount();\n        this._registerTranslationListenersHandler();\n        this._maybeStartOrStopP2P();\n    }\n\n    /**\n     * Get notified when member bot type had changed.\n     * @param jid the member jid\n     * @param botType the new botType value\n     * @internal\n     */\n    _onMemberBotTypeChanged(jid: string, botType: string): void {\n\n        // find the participant and mark it as non bot, as the real one will join\n        // in a moment\n        const peers = this.getParticipants();\n        const botParticipant = peers.find(p => p.getJid() === jid);\n\n        if (botParticipant) {\n            botParticipant.setBotType(botType);\n            const id = Strophe.getResourceFromJid(jid);\n\n            this.eventEmitter.emit(\n                JitsiConferenceEvents.BOT_TYPE_CHANGED,\n                id,\n                botType);\n        }\n\n        // if botType changed to undefined, botType was removed, in case of\n        // poltergeist mode this is the moment when the poltergeist had exited and\n        // the real participant had already replaced it.\n        // In this case we can check and try p2p\n        if (!botParticipant.getBotType()) {\n            this._maybeStartOrStopP2P();\n        }\n    }\n\n\n    /**\n     * Handles the suspend detected event. Leaves the room and fires suspended.\n     * @param {JingleSessionPC} jingleSession - The Jingle session.\n     * @internal\n     */\n    onSuspendDetected(jingleSession: JingleSessionPC): void {\n        if (!jingleSession.isP2P) {\n            this.leave();\n            this.eventEmitter.emit(JitsiConferenceEvents.SUSPEND_DETECTED);\n        }\n    }\n\n\n    /**\n     * Joins the conference.\n     * @param password {string} the password\n     * @param replaceParticipant {boolean} whether the current join replaces\n     * an existing participant with same jwt from the meeting.\n     */\n    public join(password: string = '', replaceParticipant: boolean = false) {\n        if (this.room) {\n            this.room.join(password, replaceParticipant).then(() => this._maybeSetSITimeout());\n        }\n    }\n\n    /**\n     * Connects to the XMPP server using the specified credentials and contacts\n     * Jicofo in order to obtain a session ID (which is then stored in the local\n     * storage). The user's role of the parent conference will be upgraded to\n     * moderator (by Jicofo). It's also used to join the conference when starting\n     * from anonymous domain and only authenticated users are allowed to create new\n     * rooms.\n     *\n     * @param options - Options for authentication and upgrade.\n     * @returns A thenable which settles when the process finishes and has a cancel method.\n     * @internal\n     */\n    authenticateAndUpgradeRole({\n        id,\n        password,\n        onCreateResource,\n\n        // 2. Let the API client/consumer know as soon as the XMPP user has been\n        //    successfully logged in.\n        onLoginSuccessful\n    }: IAuthenticateAndUpgradeRoleOptions): Promise<void> {\n        let canceled = false;\n        let rejectPromise: (reason?: IUpgradeRoleError | {}) => void;\n        let xmpp: XMPP = new XMPP(this.connection.options, undefined);\n\n        const process = new Promise<void>((resolve, reject) => {\n            // The process is represented by a Thenable with a cancel method. The\n            // Thenable is implemented using Promise and the cancel using the\n            // Promise's reject function.\n            rejectPromise = reject;\n            xmpp.addListener(\n                JitsiConnectionEvents.CONNECTION_DISCONNECTED,\n                () => {\n                    xmpp = undefined;\n                });\n            xmpp.addListener(\n                JitsiConnectionEvents.CONNECTION_ESTABLISHED,\n                () => {\n                    if (canceled) {\n                        return;\n                    }\n\n                    // Let the caller know that the XMPP login was successful.\n                    onLoginSuccessful?.();\n                    const { config } = this.options;\n\n                    // Now authenticate with Jicofo and get a new session ID.\n                    const room = xmpp.createRoom(\n                    this.options.name,\n                    {\n                        ...config,\n                        statsId: this._statsCurrentId\n                    },\n                    onCreateResource\n                    );\n\n                    room.xmpp.moderator.authenticate(room.roomjid)\n                    .then(() => {\n                        xmpp?.disconnect();\n\n                        if (canceled) {\n                            return;\n                        }\n\n                        // we execute this logic in JitsiConference where we bind the current conference as `this`\n                        // At this point we should have the new session ID\n                        // stored in the settings. Send a new conference IQ.\n                        this.room.xmpp.moderator.sendConferenceRequest(this.room.roomjid)\n                            .catch(e => logger.trace('sendConferenceRequest rejected', e))\n                            .finally(() => {\n                                // we need to reset it because of breakout rooms which will\n                                // reuse connection but will invite jicofo\n                                this.room.xmpp.moderator.conferenceRequestSent = false;\n\n                                resolve(undefined);\n                            });\n                    })\n                    .catch(({ error, message }) => {\n                        xmpp.disconnect();\n\n                        reject({\n                            authenticationError: error,\n                            message\n                        });\n                    });\n                });\n            xmpp.addListener(\n                JitsiConnectionEvents.CONNECTION_FAILED,\n                (connectionError: JitsiConnectionEvents, message: string, credentials: { jid?: string; password?: string; }) => {\n                    reject({\n                        connectionError,\n                        credentials,\n                        message\n                    });\n                    xmpp = undefined;\n                });\n\n            canceled || xmpp.connect(id, password);\n        });\n\n        /**\n     * Cancels the process, if it's in progress, of authenticating and upgrading\n     * the role of the local participant/user.\n     *\n     * @public\n     * @returns {void}\n     */\n        (process as IProcessWithCancel).cancel = () => {\n            canceled = true;\n            rejectPromise({});\n            xmpp?.disconnect();\n        };\n\n        return process;\n    }\n\n    /**\n   * Check if joined to the conference.\n   * @returns {boolean} True if joined, false otherwise.\n   */\n    public isJoined(): boolean {\n        return this.room?.joined;\n    }\n\n    /**\n   * Tells whether or not the P2P mode is enabled in the configuration.\n   * @returns {boolean} True if P2P is enabled, false otherwise.\n   */\n    public isP2PEnabled(): boolean {\n        return (\n            Boolean(this.options.config.p2p?.enabled)\n\n      // FIXME: remove once we have a default config template. -saghul\n      || typeof this.options.config.p2p === 'undefined'\n        );\n    }\n\n    /**\n   * When in P2P test mode, the conference will not automatically switch to P2P\n   * when there are 2 participants.\n   * @returns {boolean} True if P2P test mode is enabled, false otherwise.\n   */\n    public isP2PTestModeEnabled(): boolean {\n        return Boolean(\n      this.options.config.testing?.p2pTestMode\n        );\n    }\n\n    public cleanUpWebWorkers(): void {\n        if (this._e2eEncryption) {\n            this._e2eEncryption.dispose();\n            this._e2eEncryption = null;\n        }\n    }\n\n    /**\n   * Leaves the conference.\n   * @param {string|undefined} reason - The reason for leaving the conference.\n   * @returns {Promise}\n   */\n    public async leave(reason?: string): Promise<void> {\n        if (this.avgRtpStatsReporter) {\n            this.avgRtpStatsReporter.dispose();\n            this.avgRtpStatsReporter = null;\n        }\n\n        if (this.e2eping) {\n            this.e2eping.stop();\n            this.e2eping = null;\n        }\n\n        this.getLocalTracks().forEach(track => this.onLocalTrackRemoved(track));\n\n        this.rtc.closeBridgeChannel();\n\n        this._sendConferenceLeftAnalyticsEvent();\n\n        if (this.statistics) {\n            this.statistics.dispose();\n        }\n\n        this.cleanUpWebWorkers();\n\n        this._delayedIceFailed?.cancel();\n\n        this._maybeClearSITimeout();\n\n        // Close both JVb and P2P JingleSessions\n        if (this.jvbJingleSession) {\n            this.jvbJingleSession.close();\n            this.jvbJingleSession = null;\n        }\n        if (this.p2pJingleSession) {\n            this.p2pJingleSession.close();\n            this.p2pJingleSession = null;\n        }\n\n        // Leave the conference. If this.room == null we are calling second time leave().\n        if (!this.room) {\n            return;\n        }\n\n        // let's check is this breakout\n        if (reason === 'switch_room' && this.getBreakoutRooms()?.isBreakoutRoom()) {\n            const mJid = this.getBreakoutRooms().getMainRoomJid();\n\n            this.xmpp.connection._breakoutMovingToMain = mJid;\n        }\n\n        const room = this.room;\n\n        // Unregister connection state listeners\n        room.removeListener(\n            XMPPEvents.CONNECTION_INTERRUPTED,\n            this._onIceConnectionInterrupted\n        );\n        room.removeListener(\n            XMPPEvents.CONNECTION_RESTORED,\n            this._onIceConnectionRestored\n        );\n        room.removeListener(\n            XMPPEvents.CONNECTION_ESTABLISHED,\n            this._onIceConnectionEstablished\n        );\n\n        room.removeListener(\n            XMPPEvents.CONFERENCE_PROPERTIES_CHANGED,\n            this._updateProperties\n        );\n\n        room.removeListener(XMPPEvents.MEETING_ID_SET, this._sendConferenceJoinAnalyticsEvent);\n        room.removeListener(XMPPEvents.P2P_TERMINATION_REQUIRED, this._onP2PTerminationRequired);\n        room.removeListener(XMPPEvents.SESSION_ACCEPT, this._updateRoomPresence);\n        room.removeListener(XMPPEvents.SOURCE_ADD, this._updateRoomPresence);\n        room.removeListener(XMPPEvents.SOURCE_ADD_ERROR, this._removeLocalSourceOnReject);\n        room.removeListener(XMPPEvents.SOURCE_REMOVE, this._updateRoomPresence);\n\n        // The translation error-reply handler is registered on the (connection-scoped) Strophe connection, which\n        // outlives this conference, so remove it here to avoid retaining the conference and emitting after leave.\n        if (this._translationErrorHandler) {\n            this.xmpp.connection?.deleteHandler(this._translationErrorHandler);\n            this._translationErrorHandler = undefined;\n        }\n\n        if (this._translationListenersHandler) {\n            this.xmpp.connection?.deleteHandler(this._translationListenersHandler);\n            this._translationListenersHandler = undefined;\n        }\n\n        this.eventManager.removeXMPPListeners();\n\n        this._signalingLayer.setChatRoom(null);\n\n        this.room = null;\n\n        let leaveError;\n\n        try {\n            await room.leave(reason);\n        } catch (err) {\n            leaveError = err;\n\n            // Remove all participants because currently the conference\n            // won't be usable anyway. This is done on success automatically\n            // by the ChatRoom instance.\n            this.getParticipants().forEach(\n        participant => this.onMemberLeft(participant.getJid())\n            );\n        }\n\n        if (this.qualityController) {\n            this.qualityController.dispose();\n        }\n\n        if (this.rtc) {\n            this.rtc.destroy();\n        }\n\n        if (leaveError) {\n            throw leaveError;\n        }\n    }\n\n    /**\n   * Disposes of conference resources. This operation is a short-hand for leaving\n   * the conference and disconnecting the connection.\n   * @returns {Promise}\n   */\n    public async dispose(): Promise<void> {\n        await this.leave();\n        await this.connection?.disconnect();\n    }\n\n    /**\n   * Returns true if end conference support is enabled in the backend.\n   * @returns {boolean} whether end conference is supported in the backend.\n   */\n    public isEndConferenceSupported(): boolean {\n        return Boolean(this.room?.xmpp.endConferenceComponentAddress);\n    }\n\n    /**\n   * Ends the conference.\n   */\n    public end(): void {\n        if (!this.isEndConferenceSupported()) {\n            logger.warn('Cannot end conference: is not supported.');\n\n            return;\n        }\n        if (!this.room) {\n            throw new Error('You have already left the conference');\n        }\n\n        this.room.end();\n    }\n\n    /**\n   * Returns the currently active media session if any.\n   * @returns {Optional<JingleSessionPC>}\n   */\n    public getActiveMediaSession(): Optional<JingleSessionPC> {\n        return this.isP2PActive() ? this.p2pJingleSession : this.jvbJingleSession;\n    }\n\n    /**\n   * Returns an array containing all media sessions existing in this conference.\n   * @returns {Array<JingleSessionPC>}\n   */\n    public getMediaSessions(): JingleSessionPC[] {\n        const sessions = [];\n\n        this.jvbJingleSession && sessions.push(this.jvbJingleSession);\n        this.p2pJingleSession && sessions.push(this.p2pJingleSession);\n\n        return sessions;\n    }\n\n    /**\n   * Returns name of this conference.\n   * @returns {string}\n   */\n    public getName(): string {\n        return this.options.name.toString();\n    }\n\n    /**\n   * Returns the {@link JitsiConnection} used by this conference.\n   * @returns {JitsiConnection}\n   */\n    public getConnection(): JitsiConnection {\n        return this.connection;\n    }\n\n    /**\n   * Check if authentication is enabled for this conference.\n   * @returns {boolean}\n   */\n    public isAuthEnabled(): boolean {\n        return this.authEnabled;\n    }\n\n    /**\n   * Check if user is logged in.\n   * @returns {boolean}\n   */\n    public isLoggedIn(): boolean {\n        return Boolean(this.authIdentity);\n    }\n\n    /**\n   * Get authorized login.\n   * @returns {string|null}\n   */\n    public getAuthLogin(): Nullable<string> {\n        return this.authIdentity;\n    }\n\n    /**\n   * Returns the local tracks of the given media type, or all local tracks if no\n   * specific type is given.\n   * @param {MediaType} [mediaType] Optional media type (audio or video).\n   * @returns {Array<JitsiLocalTrack>}\n   */\n    public getLocalTracks(mediaType?: MediaType): JitsiLocalTrack[] {\n        let tracks = [];\n\n        if (this.rtc) {\n            tracks = this.rtc.getLocalTracks(mediaType);\n        }\n\n        return tracks;\n    }\n\n    /**\n   * Obtains local audio track.\n   * @returns {JitsiLocalTrack|null}\n   */\n    public getLocalAudioTrack(): Nullable<JitsiLocalTrack> {\n        return this.rtc ? this.rtc.getLocalAudioTrack() : null;\n    }\n\n    /**\n   * Obtains local video track.\n   * @returns {JitsiLocalTrack|null}\n   */\n    public getLocalVideoTrack(): Nullable<JitsiLocalTrack> {\n        return this.rtc ? this.rtc.getLocalVideoTrack() : null;\n    }\n\n    /**\n   * Returns all the local video tracks.\n   * @returns {Array<JitsiLocalTrack>|null}\n   */\n    public getLocalVideoTracks(): Nullable<JitsiLocalTrack[]> {\n        return this.rtc ? this.rtc.getLocalVideoTracks() : null;\n    }\n\n    /**\n   * Receives notifications from other participants about commands / custom events\n   * (sent by sendCommand or sendCommandOnce methods).\n   * @param {string} command - The name of the command.\n   * @param {Function} handler - Handler for the command.\n   */\n    public addCommandListener(command: string, handler: PresenceHandler): void {\n        if (this.room) {\n            this.room.addPresenceListener(command, handler);\n        }\n    }\n\n    /**\n   * Removes command listener.\n   * @param {string} command - The name of the command.\n   * @param {Function} handler - Handler to remove for the command.\n   */\n    public removeCommandListener(command: string, handler: PresenceHandler): void {\n        if (this.room) {\n            this.room.removePresenceListener(command, handler);\n        }\n    }\n\n    /**\n    /**\n   * Sends text message to the other participants in the conference.\n   * @param {string} message - The text message.\n   * @param {string} [elementName='body'] - The element name to encapsulate the message.\n   * @param {string} [replyToId] - The ID of the message being replied to.\n   * @param {string} [messageId] - Optional explicit id to stamp on the outgoing stanza.\n   * @deprecated Use 'sendMessage' instead. TODO: this should be private.\n   */\n    public sendTextMessage(message: string, elementName: string = 'body', replyToId?: string, messageId?: string): void {\n        if (this.room) {\n            this.room.sendMessage(message, elementName, replyToId, messageId);\n        }\n    }\n\n    /**\n   * Sends a reaction to the other participants in the conference.\n   * @param {string} reaction - The reaction.\n   * @param {string} messageId - The ID of the message to attach the reaction to.\n   * @param {string} receiverId - The intended recipient, if the message is private.\n   */\n    public sendReaction(reaction: string, messageId: string, receiverId: string): void {\n        if (this.room) {\n            this.room.sendReaction(reaction, messageId, receiverId);\n        }\n    }\n\n    /**\n     * Sends a message retraction to the other participants in the conference.\n     *\n     * @param {string} messageId - The ID of the message being retracted.\n     * @param {string} [receiverId] - The intended recipient if the message is private.\n     * @param {boolean} [useFullJid=false] - Whether receiverId is already a full JID.\n     */\n    public sendMessageRetraction(messageId: string, receiverId?: string, useFullJid = false): void {\n        if (this.room) {\n            this.room.sendMessageRetraction(messageId, receiverId, useFullJid);\n        }\n    }\n\n    /**\n   * Sends private text message to another participant of the conference.\n   * @param {string} id - The ID of the participant to send a private message.\n   * @param {string} message - The text message.\n   * @param {string} [elementName='body'] - The element name to encapsulate the message.\n   * @param {boolean} [useFullJid=false] - Whether to use the full JID.\n   * @param {string} [replyToId] - The ID of the message being replied to.\n   * @param {string} [messageId] - The ID to set on the outgoing private message stanza.\n   * @deprecated Use 'sendMessage' instead. TODO: this should be private.\n   */\n    public sendPrivateTextMessage(id: string, message: string, elementName: string = 'body', useFullJid = false, replyToId?: string, messageId?: string): void {\n        if (this.room) {\n            this.room.sendPrivateMessage(id, message, elementName, useFullJid, replyToId, messageId);\n        }\n    }\n\n    /**\n     * Sends a moderation request for a message.\n     *\n     * @param {string} messageId - The id of the message.\n     * @param {string} [reason] - Optional moderation reason\n     */\n    public moderateMessage(messageId: string, reason?: string): void {\n        this.room?.moderateMessage(messageId, reason);\n    }\n\n    /**\n   * Send presence command.\n   * @param {string} name - The name of the command.\n   * @param {Record<string, unknown>} values - With keys and values that will be sent.\n   */\n    public sendCommand(name: string, values: Record<string, unknown>): void {\n        if (this.room) {\n            this.room.addOrReplaceInPresence(name, values) && this.room.sendPresence();\n        } else {\n            logger.warn('Not sending a command, room not initialized.');\n        }\n    }\n\n    /**\n   * Send presence command one time.\n   * @param {string} name - The name of the command.\n   * @param {Record<string, unknown>} values - With keys and values that will be sent.\n   */\n    public sendCommandOnce(name: string, values: Record<string, unknown>): void {\n        this.sendCommand(name, values);\n        this.removeCommand(name);\n    }\n\n    /**\n   * Removes presence command.\n   * @param {string} name - The name of the command.\n   */\n    public removeCommand(name: string): void {\n        if (this.room) {\n            this.room.removeFromPresence(name);\n        }\n    }\n\n    /**\n   * Sets the display name for this conference.\n   * @param {string} name - The display name to set.\n   */\n    public setDisplayName(name: string): void {\n        if (this.room) {\n            const nickKey = 'nick';\n\n            if (name) {\n                this.room.addOrReplaceInPresence(nickKey, {\n                    attributes: { xmlns: 'http://jabber.org/protocol/nick' },\n                    value: name\n                }) && this.room.sendPresence(false);\n            } else if (this.room.getFromPresence(nickKey)) {\n                this.room.removeFromPresence(nickKey);\n                this.room.sendPresence(false);\n            }\n        }\n    }\n\n    /**\n   * Set join without audio.\n   * @param {boolean} silent - Whether user joined without audio.\n   */\n    public setIsSilent(silent: boolean): void {\n        if (this.room) {\n            this.room.addOrReplaceInPresence('silent', {\n                attributes: { xmlns: 'http://jitsi.org/protocol/silent' },\n                value: silent\n            }) && this.room.sendPresence(false);\n        }\n    }\n\n    /**\n   * Set new subject for this conference. (Available only for moderator)\n   * @param {string} subject - New subject.\n   */\n    public setSubject(subject: string): void {\n        if (this.room && this.isModerator()) {\n            this.room.setSubject(subject);\n        } else {\n            logger.warn(`Failed to set subject, ${this.room ? '' : 'not in a room, '}${\n                this.isModerator() ? '' : 'participant is not a moderator'}`);\n        }\n    }\n\n    /**\n   * Returns the transcription status.\n   * @returns {string} \"on\" or \"off\".\n   */\n    public getTranscriptionStatus(): string {\n        return this.room.transcriptionStatus;\n    }\n\n    /**\n   * Adds JitsiLocalTrack object to the conference.\n   * @param {JitsiLocalTrack} track - The JitsiLocalTrack object.\n   * @returns {Promise<void>}\n   * @throws {Error} If the specified track is a video track and there is already\n   * another video track in the conference.\n   */\n    public addTrack(track: JitsiLocalTrack): Promise<void> {\n        if (!track) {\n            throw new Error('addTrack - a track is required');\n        }\n\n        const mediaType = track.getType();\n        const localTracks = this.rtc.getLocalTracks(mediaType);\n\n        // Ensure there's exactly 1 local track of each media type in the conference.\n        if (localTracks.length > 0) {\n            // Don't be excessively harsh and severe if the API\n            // client happens to attempt to add the same local track twice.\n            if (track === localTracks[0]) {\n                return Promise.resolve();\n            }\n\n            // Currently, only adding multiple video streams of different video types is supported.\n            // TODO - remove this limitation once issues with jitsi-meet trying to add multiple camera streams is fixed.\n            if (\n                this.options.config.testing?.allowMultipleTracks\n                || (mediaType === MediaType.VIDEO && !localTracks.find(t =>\n                    t.getVideoType() === track.getVideoType()))) {\n                const sourceName = getSourceNameForJitsiTrack(\n                    this.myUserId(),\n                    mediaType,\n                    this.getLocalTracks(mediaType)?.length);\n\n                track.setSourceName(sourceName);\n                const addTrackPromises = [];\n\n                this.p2pJingleSession && addTrackPromises.push(this.p2pJingleSession.addTracks([ track ]));\n                this.jvbJingleSession && addTrackPromises.push(this.jvbJingleSession.addTracks([ track ]));\n\n                return Promise.all(addTrackPromises)\n                    .then(() => {\n                        this._setupNewTrack(track);\n                        mediaType === MediaType.VIDEO && this._sendBridgeVideoTypeMessage(track);\n                        this._updateRoomPresence(this.getActiveMediaSession());\n\n                        if (this.isMutedByFocus || this.isVideoMutedByFocus || this.isDesktopMutedByFocus) {\n                            this._fireMuteChangeEvent(track);\n                        }\n                    });\n            }\n\n            return Promise.reject(new Error(`Cannot add second ${mediaType} track to the conference`));\n        }\n\n        return this.replaceTrack(null, track)\n            .then(() => {\n                // Presence needs to be sent here for desktop track since we need the presence to reach the remote peer\n                // before signaling so that a fake participant tile is created for screenshare. Otherwise, presence will\n                // only be sent after a session-accept or source-add is ack'ed.\n                if (track.getVideoType() === VideoType.DESKTOP) {\n                    this._updateRoomPresence(this.getActiveMediaSession());\n                }\n            });\n    }\n\n    /**\n   * Clear JitsiLocalTrack properties and listeners.\n   * @param {JitsiLocalTrack} track - The JitsiLocalTrack object.\n   * @internal\n   */\n    onLocalTrackRemoved(track: JitsiLocalTrack): void {\n        track.setConference(null);\n        this.rtc.removeLocalTrack(track);\n        this._unsubscribers.forEach(remove => remove());\n        this._unsubscribers = [];\n\n        this.eventEmitter.emit(JitsiConferenceEvents.TRACK_REMOVED, track);\n    }\n\n    /**\n   * Removes JitsiLocalTrack from the conference and performs\n   * a new offer/answer cycle.\n   * @param {JitsiLocalTrack} track - The track to remove.\n   * @returns {Promise}\n   */\n    public removeTrack(track: JitsiLocalTrack): Promise<void> {\n        return this.replaceTrack(track, null);\n    }\n\n    /**\n   * Replaces oldTrack with newTrack and performs a single offer/answer\n   * cycle after both operations are done. Either oldTrack or newTrack\n   * can be null; replacing a valid 'oldTrack' with a null 'newTrack'\n   * effectively just removes 'oldTrack'\n   * @param {JitsiLocalTrack} oldTrack - The current stream in use to be replaced.\n   * @param {JitsiLocalTrack} newTrack - The new stream to use.\n   * @returns {Promise} Resolves when the replacement is finished.\n   */\n    public replaceTrack(oldTrack?: JitsiLocalTrack, newTrack?: JitsiLocalTrack): Promise<void> {\n        const oldVideoType = oldTrack?.getVideoType();\n        const mediaType = oldTrack?.getType() || newTrack?.getType();\n        const newVideoType = newTrack?.getVideoType();\n\n        if (oldTrack && newTrack && oldVideoType !== newVideoType) {\n            throw new Error(\n                `Replacing a track of videoType=${oldVideoType} with a track of videoType=${newVideoType} is`\n                + ' not supported in this mode.');\n        }\n\n        if (newTrack) {\n            const sourceName = oldTrack\n                ? oldTrack.getSourceName()\n                : getSourceNameForJitsiTrack(\n                    this.myUserId(),\n                    mediaType,\n                    this.getLocalTracks(mediaType)?.length);\n\n            newTrack.setSourceName(sourceName);\n        }\n        const oldTrackBelongsToConference = this === oldTrack?.conference;\n\n        if (oldTrackBelongsToConference && oldTrack.disposed) {\n            return Promise.reject(new JitsiTrackError(JitsiTrackErrors.TRACK_IS_DISPOSED));\n        }\n        if (newTrack?.disposed) {\n            return Promise.reject(new JitsiTrackError(JitsiTrackErrors.TRACK_IS_DISPOSED));\n        }\n\n        if (oldTrack && !oldTrackBelongsToConference) {\n            logger.warn(`JitsiConference.replaceTrack oldTrack (${oldTrack} does not belong to this conference`);\n        }\n\n\n        // Now replace the stream at the lower levels\n        return this._doReplaceTrack(oldTrackBelongsToConference ? oldTrack : null, newTrack)\n            .then(() => {\n                if (oldTrackBelongsToConference && !oldTrack.isMuted() && !newTrack) {\n                    oldTrack._sendMuteStatus(true);\n                }\n                oldTrackBelongsToConference && this.onLocalTrackRemoved(oldTrack);\n                newTrack && this._setupNewTrack(newTrack);\n\n                // Send 'VideoTypeMessage' on the bridge channel when a video track is added/removed.\n                if ((oldTrackBelongsToConference && oldTrack?.isVideoTrack()) || newTrack?.isVideoTrack()) {\n                    this._sendBridgeVideoTypeMessage(newTrack);\n                }\n                this._updateRoomPresence(this.getActiveMediaSession());\n                if (newTrack !== null && (this.isMutedByFocus || this.isVideoMutedByFocus\n                        || this.isDesktopMutedByFocus)) {\n                    this._fireMuteChangeEvent(newTrack);\n                }\n\n                return Promise.resolve();\n            })\n            .catch(error => {\n                logger.error(`replaceTrack failed: ${error?.stack}`);\n\n                return Promise.reject(error);\n            });\n    }\n\n    /**\n   * Get role of the local user.\n   * @returns {string} User role: 'moderator' or 'none'.\n   */\n    public getRole(): string {\n        return this.room.role;\n    }\n\n    /**\n     * Returns whether or not the current conference has been joined as a hidden user.\n     * @returns {boolean} True if hidden, false otherwise. Will return false if no connection is active.\n     */\n    public isHidden(): boolean {\n        if (!this.connection) {\n            return false;\n        }\n\n        return Strophe.getDomainFromJid(this.connection.getJid())\n             === this.options.config.hiddenDomain;\n    }\n\n    /**\n     * Check if local user is moderator.\n     * @returns {boolean} true if local user is moderator, false otherwise. If\n     * we're no longer in the conference room then <tt>false</tt> is returned.\n     */\n    public isModerator(): boolean {\n        return this.room ? this.room.isModerator() : false;\n    }\n\n    /**\n     * Set password for the room.\n     * @param {string} password new password for the room.\n     * @returns {Promise}\n     */\n    public lock(password: string): Promise<void> {\n        if (!this.isModerator()) {\n            return Promise.reject(new Error('You are not moderator.'));\n        }\n\n        return new Promise((resolve, reject) => {\n            this.room.lockRoom(\n                password || '',\n                () => resolve(),\n                (err: Error) => reject(err),\n                () => reject(JitsiConferenceErrors.PASSWORD_NOT_SUPPORTED)\n            );\n        });\n    }\n\n    /**\n     * Remove password from the room.\n     * @returns {Promise}\n     */\n    public unlock(): Promise<void> {\n        return this.lock('');\n    }\n\n    /**\n     * Obtains the current value for \"lastN\". See {@link setLastN} for more info.\n     * @returns {number}\n     */\n    public getLastN(): number {\n        return this.qualityController.receiveVideoController.getLastN();\n    }\n\n    /**\n     * Obtains the forwarded sources list in this conference.\n     * @return {Array<string>}\n     * @internal\n     */\n    getForwardedSources(): string[] {\n        return this.rtc.getForwardedSources();\n    }\n\n    /**\n     * Sets the audio subscription mode for the local user. The legacy { mode, list } message is also accepted\n     * for backwards compatibility and normalised to the { all, include, exclude } shape.\n     *\n     * @param {IReceiverAudioSubscriptionMessage | ILegacyReceiverAudioSubscriptionMessage} message - The audio\n     * subscription to set.\n     * @returns {void}\n     */\n    public setAudioSubscriptionMode(\n            message: IReceiverAudioSubscriptionMessage | ILegacyReceiverAudioSubscriptionMessage): void {\n        this.qualityController.audioController.setAudioSubscriptionMode(message);\n    }\n\n    /**\n     * Selects a new value for \"lastN\". The requested amount of videos are going\n     * to be delivered after the value is in effect. Set to -1 for unlimited or\n     * all available videos.\n     * @param lastN the new number of videos the user would like to receive.\n     * @throws Error or RangeError if the given value is not a number or is smaller\n     * than -1.\n     */\n    public setLastN(lastN: number): void {\n        if (!Number.isInteger(lastN)) {\n            throw new Error(`Invalid value for lastN: ${lastN}`);\n        }\n        const n = Number(lastN);\n\n        if (n < -1) {\n            throw new RangeError('lastN cannot be smaller than -1');\n        }\n        this.qualityController.receiveVideoController.setLastN(n);\n\n        // If the P2P session is not fully established yet, we wait until it gets established.\n        if (this.p2pJingleSession) {\n            const isVideoActive = n !== 0;\n\n            this.p2pJingleSession\n                .setP2pVideoTransferActive(isVideoActive)\n                .catch(error => {\n                    logger.error(`Failed to adjust video transfer status (${isVideoActive})`, error);\n                });\n        }\n    }\n\n    /**\n     * @return Array<JitsiParticipant> an array of all participants in this conference.\n     */\n    public getParticipants(): JitsiParticipant[] {\n        return Array.from(this.participants.values());\n    }\n\n    /**\n     * Returns the number of participants in the conference, including the local\n     * participant.\n     * @param countHidden {boolean} Whether or not to include hidden participants\n     * in the count. Default: false.\n     **/\n    public getParticipantCount(countHidden = false): number {\n        let participants = this.getParticipants();\n\n        if (!countHidden) {\n            participants = participants.filter(p => !p.isHidden());\n        }\n\n        // Add one for the local participant.\n        return participants.length + 1;\n    }\n\n    /**\n     * @returns {JitsiParticipant} the participant in this conference with the\n     * specified id (or undefined if there isn't one).\n     * @param id the id of the participant.\n     */\n    public getParticipantById(id: string): Optional<JitsiParticipant> {\n        return this.participants.get(id);\n    }\n\n    /**\n     * Grant owner rights to the participant.\n     * @param {string} id id of the participant to grant owner rights to.\n     */\n    public grantOwner(id: string): void {\n        const participant = this.getParticipantById(id);\n\n        if (!participant) {\n            return;\n        }\n        this.room.setAffiliation(participant.getConnectionJid(), 'owner');\n    }\n\n    /**\n     * Revoke owner rights to the participant or local Participant as\n     * the user might want to refuse to be a moderator.\n     * @param {string} id id of the participant to revoke owner rights to.\n     */\n    public revokeOwner(id: string): void {\n        const participant = this.getParticipantById(id);\n        const isMyself = this.myUserId() === id;\n        const role = this.isMembersOnly() ? 'member' : 'none';\n\n        if (isMyself) {\n            this.room.setAffiliation(this.connection.getJid(), role);\n        } else if (participant) {\n            this.room.setAffiliation(participant.getConnectionJid(), role);\n        }\n    }\n\n    /**\n     * Kick participant from this conference.\n     * @param {string} id id of the participant to kick\n     * @param {string} reason reason of the participant to kick\n     */\n    public kickParticipant(id: string, reason: string): void {\n        const participant = this.getParticipantById(id);\n\n        if (!participant) {\n            return;\n        }\n        this.room.kick(participant.getJid(), reason);\n    }\n\n    /**\n     * Mutes or unmutes the remote audio streams based on the provided parameter.\n     *\n     * @param {boolean} muted - Whether the user should stop receiving remote audio.\n     * @returns {void}\n     */\n    public muteRemoteAudio(muted: boolean): void {\n        this.qualityController.audioController.muteRemoteAudio(muted);\n    }\n\n    /**\n     * Enables (or disables, when null) receiving translated audio for every remote\n     * speaker in the given language.\n     *\n     * @param {string|null} language - The target language (2-letter ISO code), or null to disable.\n     * @returns {void}\n     */\n    public setReceiverTranslationLanguage(language: string | null): void {\n        if (this._receiverTranslationLanguage === language) {\n            return;\n        }\n        this._receiverTranslationLanguage = language;\n\n        // Rebuilds the cumulative request delta and the Include subscription (an empty Include when nothing\n        // is translated clears the opt-in set; the persistent ALL base keeps regular audio flowing).\n        this._updateTranslationRequests();\n        this._updateTranslationSubscription();\n\n        // Translated audio is delivered via the bridge, so P2P must be disabled while it is active.\n        this._maybeStartOrStopP2P();\n    }\n\n    /**\n     * @returns {string|null} the default language remote audio is translated into, or null if off.\n     */\n    public getReceiverTranslationLanguage(): string | null {\n        return this._receiverTranslationLanguage;\n    }\n\n    /**\n     * Enables (or disables, when null) translated audio for a single remote speaker, overriding the default\n     * set via {@link setReceiverTranslationLanguage}. Sends the request-stanza delta and updates the\n     * cumulative audio subscription.\n     *\n     * @param {string} participantId - The speaker's endpoint id.\n     * @param {string|null} language - The target language (2-letter ISO code), or null to disable for this speaker.\n     * @returns {void}\n     */\n    public setParticipantTranslationLanguage(participantId: string, language: string | null): void {\n        const current = this._participantTranslationLanguages.has(participantId)\n            ? this._participantTranslationLanguages.get(participantId) ?? null\n            : undefined;\n\n        if (current === language) {\n            return;\n        }\n        this._participantTranslationLanguages.set(participantId, language);\n\n        this._updateTranslationRequests();\n        this._updateTranslationSubscription();\n\n        // Translated audio is delivered via the bridge, so P2P must be disabled while it is active.\n        this._maybeStartOrStopP2P();\n    }\n\n    /**\n     * @param {string} participantId - The speaker's endpoint id.\n     * @returns {string|null} the effective translation language for the given speaker (the per-participant\n     * override if set, otherwise the default), or null if not translated.\n     */\n    public getParticipantTranslationLanguage(participantId: string): string | null {\n        return this._resolveTranslationLanguage(participantId);\n    }\n\n    /**\n     * Turns off all audio translation: clears the default language and every per-participant override, then\n     * sends the resulting removals and clears the audio subscription's Include set.\n     *\n     * @returns {void}\n     */\n    public clearTranslation(): void {\n        if (this._receiverTranslationLanguage === null && this._participantTranslationLanguages.size === 0) {\n            return;\n        }\n        this._receiverTranslationLanguage = null;\n        this._participantTranslationLanguages.clear();\n\n        this._updateTranslationRequests();\n        this._updateTranslationSubscription();\n    }\n\n    /**\n     * Mutes a participant.\n     * @param {string} id The id of the participant to mute.\n     */\n    public muteParticipant(id: string, mediaType: MediaType = MediaType.AUDIO): void {\n        if (!mediaType) {\n            logger.error(`Unsupported media type: ${mediaType}`);\n\n            return;\n        }\n\n        const participant = this.getParticipantById(id);\n\n        if (!participant) {\n            return;\n        }\n\n        this.room.muteParticipant(participant.getJid(), true, mediaType);\n    }\n\n\n    /* eslint-disable max-params */\n\n    /**\n     * Notifies this JitsiConference that a new member has joined its chat room.\n     *\n     * FIXME This should NOT be exposed!\n     *\n     * @param jid the jid of the participant in the MUC\n     * @param nick the display name of the participant\n     * @param role the role of the participant in the MUC\n     * @param isHidden indicates if this is a hidden participant (system\n     * participant for example a recorder).\n     * @param statsID the participant statsID (optional)\n     * @param status the initial status if any\n     * @param identity the member identity, if any\n     * @param botType the member botType, if any\n     * @param fullJid the member full jid, if any\n     * @param features the member features, if any.\n     * @param isReplaceParticipant whether this join replaces a participant with\n     * the same jwt.\n     * @internal\n     */\n    onMemberJoined(\n            jid: string, nick: string, role: string, isHidden: boolean, statsID: string, status: string, identity: object, botType: string, fullJid: string, features: Set<string> | undefined, isReplaceParticipant: boolean\n    ): void {\n        const id = Strophe.getResourceFromJid(jid);\n\n        if (id === 'focus' || this.myUserId() === id) {\n            return;\n        }\n        const participant = new JitsiParticipant(jid, this, nick, isHidden, statsID, status, identity);\n\n        participant.setConnectionJid(fullJid);\n        participant.setRole(role);\n        participant.setBotType(botType);\n        participant.setFeatures(features);\n        participant.setIsReplacing(isReplaceParticipant);\n\n        // Set remote tracks on the participant if source signaling was received before presence.\n        const remoteTracks = this.isP2PActive()\n            ? this.p2pJingleSession?.peerconnection.getRemoteTracks(id) ?? []\n            : this.jvbJingleSession?.peerconnection.getRemoteTracks(id) ?? [];\n\n        for (const track of remoteTracks) {\n            participant._tracks.push(track);\n        }\n\n        this.participants.set(id, participant);\n        this.eventEmitter.emit(\n            JitsiConferenceEvents.USER_JOINED,\n            id,\n            participant);\n\n        // Translate the newly-joined speaker too, if translation is active (delta-only).\n        if (this._isReceiverTranslationActive()) {\n            this._updateTranslationRequests();\n            this._updateTranslationSubscription();\n        }\n\n        this._updateFeatures(participant);\n\n        // maybeStart only if we had finished joining as then we will have information for the number of participants\n        if (this.isJoined()) {\n            this._maybeStartOrStopP2P();\n        }\n\n        this._maybeSetSITimeout();\n        const { startAudioMuted, startVideoMuted } = this.options.config;\n\n        // Ignore startAudio/startVideoMuted settings if the media session has already been established.\n        // Apply the policy if the number of participants exceeds the startMuted thresholds.\n        if ((this.jvbJingleSession && this.getActiveMediaSession() === this.jvbJingleSession)\n            || ((typeof startAudioMuted === 'undefined' || startAudioMuted === -1)\n                && (typeof startVideoMuted === 'undefined' || startVideoMuted === -1))) {\n            return;\n        }\n\n        let audioMuted = false;\n        let videoMuted = false;\n        const numberOfParticipants = this.getParticipantCount();\n\n        if (numberOfParticipants > this.options.config.startAudioMuted) {\n            audioMuted = true;\n        }\n\n        if (numberOfParticipants > this.options.config.startVideoMuted) {\n            videoMuted = true;\n        }\n\n        if ((audioMuted && !this.startMutedPolicy.audio) || (videoMuted && !this.startMutedPolicy.video)) {\n            this._updateStartMutedPolicy(audioMuted, videoMuted);\n        }\n    }\n\n    /**\n     * Handles the logic when a remote participant leaves the conference.\n     * @param {string} jid - The Jabber ID (JID) of the participant who left.\n     * @param {string} [reason] - Optional reason provided for the participant leaving.\n     * @internal\n     */\n    onMemberLeft(jid: string, reason?: string): void {\n        const id = Strophe.getResourceFromJid(jid);\n\n        if (id === 'focus' || this.myUserId() === id) {\n            return;\n        }\n\n        const mediaSessions = this.getMediaSessions();\n        let tracksToBeRemoved = [];\n\n        for (const session of mediaSessions) {\n            const remoteTracks = session.peerconnection.getRemoteTracks(id);\n\n            remoteTracks && (tracksToBeRemoved = [ ...tracksToBeRemoved, ...remoteTracks ]);\n\n            // Update the SSRC owners list.\n            session._signalingLayer.updateSsrcOwnersOnLeave(id);\n            if (!FeatureFlags.isSsrcRewritingSupported()) {\n                // Remove the ssrcs from the remote description and renegotiate.\n                session.removeRemoteStreamsOnLeave(id);\n            }\n        }\n\n        tracksToBeRemoved.forEach(track => {\n            // Fire the event before renegotiation is done so that the thumbnails can be removed immediately.\n            this.eventEmitter.emit(JitsiConferenceEvents.TRACK_REMOVED, track);\n\n            if (FeatureFlags.isSsrcRewritingSupported()) {\n                track.setSourceName(null);\n                track.setOwner(null);\n                console.warn('Decoder: disposing of an orphand track (tracksToBeRemoved)');\n                track.cleanDecoder();\n            }\n        });\n\n        const participant = this.participants.get(id);\n\n        if (participant) {\n            this.participants.delete(id);\n            this.eventEmitter.emit(JitsiConferenceEvents.USER_LEFT, id, participant, reason);\n\n            // Drop the departed speaker from translation, including any per-participant override (delta-only).\n            const hadTranslationOverride = this._participantTranslationLanguages.delete(id);\n\n            if (hadTranslationOverride || this._translationRequests.has(id) || this._isReceiverTranslationActive()) {\n                this._updateTranslationRequests();\n                this._updateTranslationSubscription();\n            }\n        }\n\n        if (this.room !== null) { // Skip if we have left the room already.\n            this._maybeStartOrStopP2P(true /* triggered by user left event */);\n            this._maybeClearSITimeout();\n        }\n    }\n\n    /* eslint-disable max-params */\n\n    /**\n     * Designates an event indicating that we were kicked from the XMPP MUC.\n     * @param {boolean} isSelfPresence - whether it is for local participant\n     * or another participant.\n     * @param {string} actorId - the id of the participant who was initiator\n     * of the kick.\n     * @param {string?} kickedParticipantId - when it is not a kick for local participant,\n     * this is the id of the participant which was kicked.\n     * @param {string} reason - reason of the participant to kick\n     * @param {boolean?} isReplaceParticipant - whether this is a server initiated kick in order\n     * to replace it with a participant with same jwt.\n     * @internal\n     */\n    onMemberKicked(isSelfPresence: boolean, actorId: string, kickedParticipantId: string, reason: string, isReplaceParticipant: boolean): void {\n        let actorParticipant;\n\n        if (actorId === this.myUserId()) {\n            // When we kick someone we also want to send the PARTICIPANT_KICKED event, but there is no\n            // JitsiParticipant object for ourselves so create a minimum fake one.\n            actorParticipant = {\n                getId: () => actorId\n            };\n        } else {\n            actorParticipant = this.participants.get(actorId);\n        }\n\n        if (isSelfPresence) {\n            if (!actorParticipant) {\n                // When meet-server kicks us we need to send the PARTICIPANT_KICKED event, but there is no\n                // JitsiParticipant object for ourselves so create a minimum fake one.\n                actorParticipant = {\n                    getDisplayName: () => 'Display Name',\n                    getId: () => kickedParticipantId,\n                };\n            }\n            this.leave().finally(() => this._xmpp.disconnect());\n            this.eventEmitter.emit(\n                JitsiConferenceEvents.KICKED, actorParticipant, reason, isReplaceParticipant);\n\n            return;\n        }\n\n        const kickedParticipant = this.participants.get(kickedParticipantId);\n\n        kickedParticipant.setIsReplaced(isReplaceParticipant);\n\n        this.eventEmitter.emit(\n            JitsiConferenceEvents.PARTICIPANT_KICKED, actorParticipant, kickedParticipant, reason);\n    }\n\n    /**\n     * Method called on local MUC role change.\n     * @param {string} role the name of new user's role as defined by XMPP MUC.\n     * @internal\n     */\n    onLocalRoleChanged(role: string): void {\n        // Emit role changed for local JID\n        this.eventEmitter.emit(\n            JitsiConferenceEvents.USER_ROLE_CHANGED, this.myUserId(), role);\n    }\n\n    /**\n     * Handles changes to a user's role within the conference.\n     * @param {string} jid - The Jabber ID (JID) of the user whose role has changed.\n     * @param {string} role - The new role assigned to the user (e.g., 'moderator', 'participant').\n     * @internal\n     */\n    onUserRoleChanged(jid: string, role: string): void {\n        const id = Strophe.getResourceFromJid(jid);\n        const participant = this.getParticipantById(id);\n\n        if (!participant) {\n            return;\n        }\n        participant.setRole(role);\n        this.eventEmitter.emit(JitsiConferenceEvents.USER_ROLE_CHANGED, id, role);\n    }\n\n    /**\n     * Handles updates to a participant's display name.\n     * @param {string} jid - The Jabber ID (JID) of the participant whose display name changed.\n     * @param {string} displayName - The new display name for the participant.\n     * @internal\n     */\n    onDisplayNameChanged(jid: string, displayName: string): void {\n        const id = Strophe.getResourceFromJid(jid);\n        const participant = this.getParticipantById(id);\n\n        if (!participant) {\n            return;\n        }\n\n        if (participant._displayName === displayName) {\n            return;\n        }\n\n        participant._displayName = displayName;\n        this.eventEmitter.emit(\n            JitsiConferenceEvents.DISPLAY_NAME_CHANGED,\n            id,\n            displayName);\n    }\n\n    /**\n     * Handles changes to a participant's silent status.\n     * @param {string} jid - The Jabber ID (JID) of the participant whose silent status has changed.\n     * @param {boolean} isSilent - The new silent status of the participant (true if silent, false otherwise).\n     * @internal\n     */\n    onSilentStatusChanged(jid: string, isSilent: boolean): void {\n        const id = Strophe.getResourceFromJid(jid);\n        const participant = this.getParticipantById(id);\n\n        if (!participant) {\n            return;\n        }\n\n        participant.setIsSilent(isSilent);\n        this.eventEmitter.emit(\n            JitsiConferenceEvents.SILENT_STATUS_CHANGED,\n            id,\n            isSilent);\n    }\n\n    /**\n     * Notifies this JitsiConference that a JitsiRemoteTrack was added to the conference.\n     *\n     * @param {JitsiRemoteTrack} track the JitsiRemoteTrack which was added to this JitsiConference.\n     * @internal\n     */\n    onRemoteTrackAdded(track: JitsiRemoteTrack): void {\n        if (track.isP2P && !this.isP2PActive()) {\n            logger.info('Trying to add remote P2P track, when not in P2P - IGNORED');\n\n            return;\n        } else if (!track.isP2P && this.isP2PActive()) {\n            logger.info('Trying to add remote JVB track, when in P2P - IGNORED');\n\n            return;\n        }\n\n        const id = track.getParticipantId();\n        const participant = this.getParticipantById(id);\n\n        // Add track to JitsiParticipant.\n        if (participant) {\n            participant._tracks.push(track);\n        } else {\n            logger.info(`Source signaling received before presence for ${id}`);\n        }\n\n        const emitter = this.eventEmitter;\n\n        // Translated tracks have no mute lifecycle (presence/source-info is only signaled for the original\n        // sources), so skip the relay for them.\n        !isTranslatedSourceName(track.getSourceName()) && track.addEventListener(\n            JitsiTrackEvents.TRACK_MUTE_CHANGED,\n            () => emitter.emit(JitsiConferenceEvents.TRACK_MUTE_CHANGED, track));\n        // Skip translated audio tracks. They share the participant id with the original source and would\n        // otherwise clobber the original speaker's levels on the conference-level event.\n        track.isAudioTrack() && !isTranslatedSourceName(track.getSourceName()) && track.addEventListener(\n            JitsiTrackEvents.TRACK_AUDIO_LEVEL_CHANGED,\n            (audioLevel: number, tpc: TraceablePeerConnection) => {\n                const activeTPC = this.getActivePeerConnection();\n\n                if (activeTPC === tpc) {\n                    emitter.emit(JitsiConferenceEvents.TRACK_AUDIO_LEVEL_CHANGED, id, audioLevel);\n                }\n            }\n        );\n\n        emitter.emit(JitsiConferenceEvents.TRACK_ADDED, track);\n    }\n\n\n    // eslint-disable-next-line no-unused-vars\n    /**\n     * Callback called by the Jingle plugin when 'session-answer' is received.\n     * @param {JingleSessionPC} session - The Jingle session for which an answer was received.\n     * @param {Element} answer - An element pointing to 'jingle' IQ element.\n     * @internal\n     */\n    onCallAccepted(session: JingleSessionPC, answer: Element): void {\n        if (this.p2pJingleSession === session) {\n            logger.info('P2P setAnswer');\n\n            this.p2pJingleSession.setAnswer(answer)\n                .then(() => {\n                    this.eventEmitter.emit(JitsiConferenceEvents._MEDIA_SESSION_STARTED, this.p2pJingleSession);\n                })\n                .catch(error => {\n                    logger.error('Error setting P2P answer', error);\n                    if (this.p2pJingleSession) {\n                        this.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_FAILED,\n                            JitsiConferenceErrors.OFFER_ANSWER_FAILED, error);\n                    }\n                });\n        }\n    }\n\n\n    // eslint-disable-next-line no-unused-vars\n    /**\n     * Callback called by the Jingle plugin when 'transport-info' is received.\n     * @param {JingleSessionPC} session - The Jingle session for which the IQ was received.\n     * @param {Element} transportInfo - An element pointing to 'jingle' IQ element.\n     * @internal\n     */\n    onTransportInfo(session: JingleSessionPC, transportInfo: Element): void {\n        if (this.p2pJingleSession === session) {\n            logger.info('P2P addIceCandidates');\n            this.p2pJingleSession.addIceCandidates(transportInfo);\n        }\n    }\n\n    /**\n     * Notifies this JitsiConference that a JitsiRemoteTrack was removed from the conference.\n     *\n     * @param {JitsiRemoteTrack} removedTrack - The track that was removed.\n     * @internal\n     */\n    onRemoteTrackRemoved(removedTrack: JitsiRemoteTrack): void {\n        this.getParticipants().forEach(participant => {\n            const tracks = participant.getTracks();\n\n            for (let i = 0; i < tracks.length; i++) {\n                if (tracks[i] === removedTrack) {\n                    // Since the tracks have been compared and are\n                    // considered equal the result of splice can be ignored.\n                    participant._tracks.splice(i, 1);\n\n                    this.eventEmitter.emit(JitsiConferenceEvents.TRACK_REMOVED, removedTrack);\n\n                    break;\n                }\n            }\n        }, this);\n    }\n\n    /**\n     * Handles an incoming call event.\n     * @param {JingleSessionPC} jingleSession - The Jingle session for the incoming call.\n     * @param {Element} jingleOffer - An element pointing to 'jingle' IQ element containing the offer.\n     * @param {number} now - The timestamp when the call was received.\n     * @internal\n     */\n    onIncomingCall(jingleSession: JingleSessionPC, jingleOffer: Element, now: number): void {\n        // Handle incoming P2P call\n        if (jingleSession.isP2P) {\n            this._onIncomingCallP2P(jingleSession, jingleOffer);\n        } else {\n            if (!this.isFocus(jingleSession.remoteJid)) {\n                const description = 'Rejecting session-initiate from non-focus.';\n\n                this._rejectIncomingCall(\n                    jingleSession, {\n                        errorMsg: description,\n                        reason: 'security-error',\n                        reasonDescription: description\n                    });\n\n                return;\n            }\n            this._acceptJvbIncomingCall(jingleSession, jingleOffer, now);\n        }\n    }\n\n    /**\n     * Handles the call ended event.\n     * XXX is this due to the remote side terminating the Jingle session?\n     *\n     * @param {JingleSessionPC} jingleSession - The Jingle session which has been terminated.\n     * @param {String} reasonCondition - The Jingle reason condition.\n     * @param {String|null} reasonText - Human readable reason text which may provide\n     *  more details about why the call has been terminated.\n     * @internal\n     */\n    onCallEnded(jingleSession: JingleSessionPC, reasonCondition: string, reasonText: string): void {\n        logger.info(\n            `Call ended: ${reasonCondition} - ${reasonText} P2P ?${\n                jingleSession.isP2P}`);\n        if (jingleSession === this.jvbJingleSession) {\n            this.wasStopped = true;\n\n            Statistics.sendAnalytics(\n                createJingleEvent(AnalyticsEvents.ACTION_JINGLE_TERMINATE, { p2p: false }));\n\n            // Stop the stats\n            if (this.statistics) {\n                this.statistics.stopRemoteStats(this.jvbJingleSession.peerconnection);\n            }\n\n            // Current JVB JingleSession is no longer valid, so set it to null\n            this.jvbJingleSession = null;\n\n            // Let the RTC service do any cleanups\n            this.rtc.onCallEnded();\n        } else if (jingleSession === this.p2pJingleSession) {\n            const stopOptions: { requestRestart?: boolean; } = {};\n\n            if (reasonCondition === 'connectivity-error' && reasonText === 'ICE FAILED') {\n                // It can happen that the other peer detects ICE failed and\n                // terminates the session, before we get the event\n                // on our side. But we are able to parse the reason and mark it here.\n                Statistics.analytics.addPermanentProperties({ p2pFailed: true });\n            } else if (reasonCondition === 'success' && reasonText === 'restart') {\n                // When we are restarting media sessions we don't want to switch the tracks to the JVB just yet.\n                stopOptions.requestRestart = true;\n            }\n            this._stopP2PSession(stopOptions);\n        } else {\n            logger.error(\n                'Received onCallEnded for invalid session',\n                jingleSession.sid,\n                jingleSession.remoteJid,\n                reasonCondition,\n                reasonText);\n        }\n    }\n\n    /**\n     * Updates DTMF support based on participants' capabilities.\n     * @returns {void}\n     */\n    public updateDTMFSupport(): void {\n        let somebodySupportsDTMF = false;\n        const participants = this.getParticipants();\n\n        // check if at least 1 participant supports DTMF\n        for (let i = 0; i < participants.length; i += 1) {\n            if (participants[i].supportsDTMF()) {\n                somebodySupportsDTMF = true;\n                break;\n            }\n        }\n        if (somebodySupportsDTMF !== this.somebodySupportsDTMF) {\n            this.somebodySupportsDTMF = somebodySupportsDTMF;\n            this.eventEmitter.emit(\n                JitsiConferenceEvents.DTMF_SUPPORT_CHANGED,\n                somebodySupportsDTMF);\n        }\n    }\n\n    /**\n     * Allows to check if there is at least one user in the conference that supports DTMF.\n     * @returns {boolean} True if somebody supports DTMF, false otherwise.\n     */\n    public isDTMFSupported(): boolean {\n        return this.somebodySupportsDTMF;\n    }\n\n    /**\n     * Returns the local user's ID.\n     * @returns {string|null} Local user's ID or null if not available.\n     */\n    public myUserId(): Nullable<string> {\n        return (\n            this.room?.myroomjid\n                ? Strophe.getResourceFromJid(this.room.myroomjid)\n                : null);\n    }\n\n    /**\n     * Sends DTMF tones to the active peer connection.\n     * @param {string} tones - The DTMF tones to send.\n     * @param {number} duration - The duration of each tone in milliseconds.\n     * @param {number} pause - The pause duration between tones in milliseconds.\n     * @returns {void}\n     */\n    public sendTones(tones: string, duration: number, pause: number): void {\n        const peerConnection = this.getActivePeerConnection();\n\n        if (peerConnection) {\n            peerConnection.sendTones(tones, duration, pause);\n        } else {\n            logger.warn('cannot sendTones: no peer connection');\n        }\n    }\n\n    /**\n     * Starts recording the current conference.\n     *\n     * @param {IRecordingOptions} options - Configuration for the recording.\n     * @returns {Promise} Resolves when recording starts successfully, rejects otherwise.\n     */\n    public startRecording(options: IRecordingOptions): Promise<JibriSession> {\n        if (this.room) {\n            return this.recordingManager.startRecording(options);\n        }\n\n        return Promise.reject(new Error('The conference is not created yet!'));\n    }\n\n    /**\n     * Stops a recording session.\n     *\n     * @param {string} sessionID - The ID of the recording session to stop.\n     * @returns {Promise} Resolves when recording stops successfully, rejects otherwise.\n     */\n    public stopRecording(sessionID: string): Promise<void> {\n        if (this.room) {\n            return this.recordingManager.stopRecording(sessionID);\n        }\n\n        return Promise.reject(new Error('The conference is not created yet!'));\n    }\n\n    /**\n     * Returns true if SIP calls are supported, false otherwise.\n     * @returns {boolean} True if SIP calling is supported, false otherwise.\n     */\n    public isSIPCallingSupported(): boolean {\n        return this.room?.xmpp?.moderator?.isSipGatewayEnabled() ?? false;\n    }\n\n    /**\n     * Dials a phone number to join the conference.\n     * @param {string} number - The phone number to dial.\n     * @returns {Promise} Resolves when the dial is successful, rejects otherwise.\n     */\n    public dial(number: string): Promise<void> {\n        if (this.room) {\n            return this.room.dial(number);\n        }\n\n        return Promise.reject(new Error('The conference is not created yet!'));\n    }\n\n    /**\n     * Hangs up an existing call.\n     * @returns {Promise} Resolves when the hangup is successful.\n     */\n    public hangup(): Promise<void> {\n        if (this.room) {\n            return this.room.hangup();\n        }\n\n        return Promise.resolve();\n    }\n\n    /**\n     * Returns the phone number for joining the conference.\n     * @returns {string|null} The phone number or null if not available.\n     */\n    public getPhoneNumber(): Nullable<string> {\n        if (this.room) {\n            return this.room.getPhoneNumber();\n        }\n\n        return null;\n    }\n\n    /**\n     * Returns the PIN for joining the conference via phone.\n     * @returns {string|null} The phone PIN or null if not available.\n     */\n    public getPhonePin(): Nullable<string> {\n        if (this.room) {\n            return this.room.getPhonePin();\n        }\n\n        return null;\n    }\n\n    /**\n     * Returns the meeting unique ID if any.\n     * @returns {string|undefined} The meeting ID or undefined if not available.\n     */\n    public getMeetingUniqueId(): Optional<string> {\n        if (this.room) {\n            return this.room.getMeetingId();\n        }\n    }\n\n    /**\n     * Returns the active peer connection (P2P or JVB).\n     * @returns {TraceablePeerConnection|null} The active peer connection or null if none is available.\n     * @public\n     */\n    public getActivePeerConnection(): Nullable<TraceablePeerConnection> {\n        const session = this.isP2PActive() ? this.p2pJingleSession : this.jvbJingleSession;\n\n        return session ? session.peerconnection : null;\n    }\n\n    /**\n     * Returns the connection state for the current room.\n     * NOTE that \"completed\" ICE state which can appear on the P2P connection will\n     * be converted to \"connected\".\n     * @returns {string|null} The ICE connection state or null if no active peer connection exists.\n     */\n    public getConnectionState(): Nullable<string> {\n        const peerConnection = this.getActivePeerConnection();\n\n        return peerConnection ? peerConnection.getConnectionState() : null;\n    }\n\n    /**\n     * Sets the start muted policy for new participants.\n     * @param {Object} policy - Object with boolean properties for audio and video muting.\n     * @param {boolean} policy.audio - Whether audio should be muted for new participants.\n     * @param {boolean} policy.video - Whether video should be muted for new participants.\n     * @returns {void}\n     */\n    public setStartMutedPolicy(policy: { audio: boolean; video: boolean; }): void {\n        if (!this.isModerator()) {\n            logger.warn(`Failed to set start muted policy, ${this.room ? '' : 'not in a room, '}${\n                this.isModerator() ? '' : 'participant is not a moderator'}`);\n\n            return;\n        }\n\n        logger.info(`Setting start muted policy: ${JSON.stringify(policy)} in presence and in conference metadata`);\n\n        // TODO: to remove using presence for startmuted policy after old clients update to using metadata always.\n        this.room.addOrReplaceInPresence('startmuted', {\n            attributes: {\n                audio: policy.audio,\n                video: policy.video,\n                xmlns: 'http://jitsi.org/jitmeet/start-muted'\n            }\n        }) && this.room.sendPresence();\n\n        this.getMetadataHandler().setMetadata('startMuted', {\n            audio: policy.audio,\n            video: policy.video\n        });\n    }\n\n    /**\n     * Returns the current start muted policy.\n     * @returns {Object} Object with audio and video properties indicating the start muted policy.\n     * @internal\n     */\n    getStartMutedPolicy(): { audio: boolean; video: boolean; } {\n        return this.startMutedPolicy;\n    }\n\n    /**\n     * Returns measured connection times.\n     * @returns {Object} The connection times for the room.\n     */\n    public getConnectionTimes(): object {\n        return this.room.connectionTimes;\n    }\n\n    /**\n     * Sets a property for the local participant.\n     * @param {string} name - The name of the property.\n     * @param {string} value - The value of the property.\n     * @param {boolean} [useRawKeys] - Skip the \"jitsi_participant_\" prefix when true.\n     * @returns {void}\n     */\n    public setLocalParticipantProperty(name: string, value: string | string[], useRawKeys = false): void {\n        this.sendCommand(useRawKeys ? name : `jitsi_participant_${name}`, { value });\n    }\n\n    /**\n     * Sets multiple properties for the local participant in a single presence update.\n     * @param {Record<string, string | string[]>} properties - Object of property names to values.\n     * @param {boolean} [useRawKeys] - Skip the \"jitsi_participant_\" prefix when true.\n     * @returns {void}\n     */\n    public setLocalParticipantProperties(properties: Record<string, string | string[]>, useRawKeys = false): void {\n        if (!this.room) {\n            return;\n        }\n\n        let changed = false;\n\n        for (const name of Object.keys(properties)) {\n            const tagName = useRawKeys ? name : `jitsi_participant_${name}`;\n            const wasChanged = this.room.addOrReplaceInPresence(tagName, { value: properties[name] });\n\n            changed = changed || Boolean(wasChanged);\n        }\n\n        if (changed) {\n            this.room.sendPresence();\n        }\n    }\n\n    /**\n     * Removes a property for the local participant and sends the updated presence.\n     * @param {string} name - The name of the property to remove.\n     * @param {boolean} [useRawKeys] - Skip the \"jitsi_participant_\" prefix when true.\n     * @returns {void}\n     */\n    public removeLocalParticipantProperty(name: string, useRawKeys = false): void {\n        this.removeCommand(useRawKeys ? name : `jitsi_participant_${name}`);\n        if (this.room) {\n            this.room.sendPresence();\n        }\n    }\n\n    /**\n     * Sets the transcription language.\n     * NB: Unlike _init_ here we don't check for the default value since we want to allow\n     * the value to be reset.\n     * @param {string} lang - The new transcription language to be used.\n     * @returns {void}\n     */\n    public setTranscriptionLanguage(lang: string): void {\n        this.setLocalParticipantProperty('transcription_language', lang);\n    }\n\n    /**\n     * Gets a local participant property.\n     * @param {string} name - The name of the property to retrieve.\n     * @param {boolean} [useRawKeys] - Skip the \"jitsi_participant_\" prefix when true.\n     * @returns {string|undefined} The value of the property if it exists, otherwise undefined.\n     */\n    public getLocalParticipantProperty(name: string, useRawKeys = false): Optional<string> {\n        const tagName = useRawKeys ? name : `jitsi_participant_${name}`;\n        const property = this.room.presMap.nodes.find(prop =>\n            prop.tagName === tagName\n        );\n\n        return property ? property.value : undefined;\n    }\n\n    /**\n     * Sends feedback if enabled.\n     * @param {number} overallFeedback - An integer between 1 and 5 indicating user feedback.\n     * @param {string} detailedFeedback - Detailed feedback from the user (not yet used).\n     * @returns {Promise} Resolves if feedback is submitted successfully.\n     */\n    public sendFeedback(overallFeedback: number, detailedFeedback: string): Promise<void> {\n        return this.statistics.sendFeedback(overallFeedback, detailedFeedback);\n    }\n\n\n    /**\n     * Finds the SSRC of a given track.\n     * @param {JitsiTrack} track - The track to find the SSRC for.\n     * @returns {Optional<number>} The SSRC of the specified track, or undefined if not found.\n     */\n    public getSsrcByTrack(track: JitsiTrack): Optional<number> {\n        return track.isLocal() ? this.getActivePeerConnection()?.getLocalSSRC(track as JitsiLocalTrack) : track.getSsrc();\n    }\n\n\n    /**\n     * Sends an application log (no-op since callstats is no longer supported).\n     * @returns {void}\n     */\n    public sendApplicationLog(): void {\n        // eslint-disable-next-line no-empty-function\n    }\n\n    /**\n     * Checks if the user identified by given MUC JID is the conference focus.\n     * @param {string} mucJid - The full MUC address of the user to check.\n     * @returns {boolean|null} True if the user is the conference focus,\n     * false if not, null if not in MUC or invalid JID.\n     * @internal\n     */\n    isFocus(mucJid: string): Nullable<boolean> {\n        return this.room ? this.room.isFocus(mucJid) : null;\n    }\n\n    /**\n     * Sends a message via the data channel.\n     * @param {string} to - The ID of the endpoint to receive the message, or empty string to broadcast.\n     * @param {object} payload - The payload of the message.\n     * @throws {NetworkError|InvalidStateError|Error} If the operation fails.\n     * @deprecated Use 'sendMessage' instead. TODO: this should be private.\n     */\n    public sendEndpointMessage(to: string, payload: object): void {\n        this.rtc.sendChannelMessage(to, payload);\n    }\n\n    /**\n     * Sends local stats via the bridge channel to other endpoints selectively.\n     * @param {Object} payload - The payload of the message.\n     * @throws {NetworkError|InvalidStateError|Error} If the operation fails or no data channel exists.\n     * @internal\n     */\n    sendEndpointStatsMessage(payload: object): void {\n        this.rtc.sendEndpointStatsMessage(payload);\n    }\n\n    /**\n     * Sends a broadcast message via the data channel.\n     * @param {object} payload - The payload of the message.\n     * @throws {NetworkError|InvalidStateError|Error} If the operation fails.\n     * @deprecated Use 'sendMessage' instead. TODO: this should be private.\n     */\n    public broadcastEndpointMessage(payload: object): void {\n        this.sendEndpointMessage('', payload);\n    }\n\n    /**\n     * Sends a message to a given endpoint or broadcasts it to all endpoints.\n     * @param {string|object} message - The message to send (string for chat, object for JSON).\n     * @param {string} [to=''] - The ID of the recipient endpoint, or empty string to broadcast.\n     * @param {boolean} [sendThroughVideobridge=false] - Whether to send through jitsi-videobridge.\n     * @param {string} [replyToId] - The ID of the message being replied to.\n     */\n    public sendMessage(message: any, to = '', sendThroughVideobridge = false, replyToId?: string): void {\n        const messageType = typeof message;\n\n        // Through videobridge we support only objects. Through XMPP we support\n        // objects (encapsulated in a specific JSON format) and strings (i.e.\n        // regular chat messages).\n        if (messageType !== 'object'\n                && (sendThroughVideobridge || messageType !== 'string')) {\n            logger.error(`Can not send a message of type ${messageType}`);\n\n            return;\n        }\n\n        if (sendThroughVideobridge) {\n            this.sendEndpointMessage(to, message);\n        } else {\n            let messageToSend = message;\n\n            // Name of packet extension of message stanza to send the required\n            // message in.\n            let elementName = 'body';\n\n            if (messageType === 'object') {\n                elementName = 'json-message';\n\n                // Mark as valid JSON message if not already\n                if (!messageToSend.hasOwnProperty(JITSI_MEET_MUC_TYPE)) {\n                    messageToSend[JITSI_MEET_MUC_TYPE] = '';\n                }\n\n                try {\n                    messageToSend = JSON.stringify(messageToSend);\n                } catch (e) {\n                    logger.error('Can not send a message, stringify failed: ', e);\n\n                    return;\n                }\n            }\n\n            if (to) {\n                this.sendPrivateTextMessage(to, messageToSend, elementName, false, replyToId);\n            } else {\n                // Broadcast\n                this.sendTextMessage(messageToSend, elementName, replyToId);\n            }\n        }\n    }\n\n    /**\n     * Checks if the connection is interrupted.\n     * @returns {boolean} True if the connection is interrupted, false otherwise.\n     */\n    public isConnectionInterrupted(): boolean {\n        return this.isP2PActive()\n            ? this.isP2PConnectionInterrupted : this.isJvbConnectionInterrupted;\n    }\n\n    /**\n     * Gets a conference property with a given key.\n     *\n     * @param {string} key - The key.\n     * @returns {*} The value\n     */\n    public getProperty(key: string): any {\n        return this.properties[key];\n    }\n\n    /**\n     * Checks whether or not the conference is currently in the peer to peer mode.\n     * Being in peer to peer mode means that the direct connection has been\n     * established and the P2P connection is being used for media transmission.\n     * @return {boolean} <tt>true</tt> if in P2P mode or <tt>false</tt> otherwise.\n     */\n    public isP2PActive(): boolean {\n        return this.p2p;\n    }\n\n    /**\n     * Returns the current ICE state of the P2P connection.\n     * NOTE: method is used by the jitsi-meet-torture tests.\n     * @return {string|null} an ICE state or <tt>null</tt> if there's currently\n     * no P2P connection.\n     */\n    public getP2PConnectionState(): Nullable<string> {\n        if (this.isP2PActive()) {\n            return this.p2pJingleSession.peerconnection.getConnectionState();\n        }\n\n        return null;\n    }\n\n    /**\n     * Configures the peerconnection so that a given framre rate can be achieved for desktop share.\n     *\n     * @param {number} maxFps The capture framerate to be used for desktop tracks.\n     * @returns {boolean} true if the operation is successful, false otherwise.\n     */\n    public setDesktopSharingFrameRate(maxFps: number): boolean {\n        if (!isValidNumber(maxFps)) {\n            logger.error(`Invalid value ${maxFps} specified for desktop capture frame rate`);\n\n            return false;\n        }\n\n        const fps = Number(maxFps);\n\n        this._desktopSharingFrameRate = fps;\n\n        // Set capture fps for screenshare.\n        this.jvbJingleSession?.peerconnection.setDesktopSharingFrameRate(fps);\n\n        // Set the capture rate for desktop sharing.\n        this.rtc.setDesktopSharingFrameRate(fps);\n\n        return true;\n    }\n\n    /**\n     * Manually starts new P2P session (should be used only in the tests).\n     * @returns {void}\n     * @internal\n     */\n    startP2PSession(): void {\n        const peers = this.getParticipants();\n\n        // Start peer to peer session\n        if (peers.length === 1) {\n            const peerJid = peers[0].getJid();\n\n            this._startP2PSession(peerJid);\n        } else {\n            throw new Error(\n                'There must be exactly 1 participant to start the P2P session !');\n        }\n    }\n\n    /**\n     * Manually stops the current P2P session (should be used only in the tests).\n     * @param {Object} options - Options for stopping P2P.\n     * @returns {void}\n     * @internal\n     */\n    stopP2PSession(options: {\n        reason: string;\n        reasonDescription: string;\n        requestRestart: boolean;\n    }): void {\n        this._stopP2PSession(options);\n    }\n\n    /**\n     * Get a summary of how long current participants have been the dominant speaker\n     * @returns {{[userId: string]: SpeakerStats}} The speaker statistics.\n     */\n    public getSpeakerStats(): { [userId: string]: SpeakerStats; } {\n        return this.speakerStatsCollector.getStats();\n    }\n\n    /**\n     * Sends a face landmarks object to the xmpp server.\n     * @param {IFaceLandmarksPayload} payload - The face landmarks data to send.\n     * @returns {void}\n     */\n    public sendFaceLandmarks(payload: IFaceLandmarksPayload): void {\n        if (payload.faceExpression) {\n            this._xmpp.sendFaceLandmarksEvent(this.room.roomjid, payload);\n        }\n    }\n\n    /**\n     * Sets the constraints for the video that is requested from the bridge.\n     *\n     * @param {IReceiverVideoConstraints} videoConstraints The constraints which are specified in the following format. The message updates\n     * the fields that are present and leaves the rest unchanged on the bridge.\n     * Therefore, any field that is not applicable\n     * anymore should be cleared by passing an empty object or list (whatever is applicable).\n     * {\n     *      'lastN': 20,\n     *      'selectedSources': ['A', 'B', 'C'],\n     *      'onStageSources': ['A'],\n     *      'defaultConstraints': { 'maxHeight': 180 },\n     *      'constraints': {\n     *          'A': { 'maxHeight': 720 }\n     *      }\n     * }\n     * Where A, B and C are source-names of the remote tracks that are being requested from the bridge.\n     * @returns {void}\n     */\n    public setReceiverConstraints(videoConstraints: IReceiverVideoConstraints): void {\n        this.qualityController.receiveVideoController.setReceiverConstraints(videoConstraints);\n    }\n\n    /**\n     * Sets the assumed bandwidth bps for the video that is requested from the bridge.\n     *\n     * @param {Number} assumedBandwidthBps - The bandwidth value expressed in bits per second.\n     * @returns {void}\n     */\n    public setAssumedBandwidthBps(assumedBandwidthBps: number): void {\n        this.qualityController.receiveVideoController.setAssumedBandwidthBps(assumedBandwidthBps);\n    }\n\n    /**\n     * Sets the maximum video size the local participant should receive from remote\n     * participants.\n     *\n     * @param {number} maxFrameHeight - the maximum frame height, in pixels,\n     * this receiver is willing to receive.\n     * @returns {void}\n     */\n    public setReceiverVideoConstraint(maxFrameHeight: number): void {\n        this.qualityController.receiveVideoController.setPreferredReceiveMaxFrameHeight(maxFrameHeight);\n    }\n\n    /**\n     * Sets the maximum video size the local participant should send to remote\n     * participants.\n     * @param {number} maxFrameHeight - The user preferred max frame height.\n     * @returns {Promise} promise that will be resolved when the operation is\n     * successful and rejected otherwise.\n     */\n    public setSenderVideoConstraint(maxFrameHeight: number): Promise<void> {\n        return this.qualityController.sendVideoController.setPreferredSendMaxFrameHeight(maxFrameHeight);\n    }\n\n    /**\n     * Creates a video SIP GW session and returns it if service is enabled. Before\n     * creating a session one need to check whether video SIP GW service is\n     * available in the system. Even\n     * if there are available nodes to serve this request, after creating the\n     * session those nodes can be taken and the request about using the\n     * created session can fail.\n     *\n     * @param {string} sipAddress - The sip address to be used.\n     * @param {string} displayName - The display name to be used for this session.\n     * @returns {JitsiVideoSIPGWSession|Error} Returns null if conference is not\n     * initialised and there is no room.\n     */\n    public createVideoSIPGWSession(sipAddress: string, displayName: string): JitsiVideoSIPGWSession | Error {\n        if (!this.room) {\n            return new Error(VideoSIPGWConstants.ERROR_NO_CONNECTION);\n        }\n\n        return this.videoSIPGWHandler\n            .createVideoSIPGWSession(sipAddress, displayName);\n    }\n\n    /**\n     * Returns whether End-To-End encryption is enabled.\n     *\n     * @returns {boolean}\n     */\n    public isE2EEEnabled(): boolean {\n        return Boolean(this._e2eEncryption?.isEnabled());\n    }\n\n    /**\n     * Returns whether End-To-End encryption is supported. Note that not all participants\n     * in the conference may support it.\n     *\n     * @returns {boolean}\n     */\n    public isE2EESupported(): boolean {\n        return E2EEncryption.isSupported(this.options.config);\n    }\n\n    /**\n     * Enables / disables End-to-End encryption.\n     *\n     * @param {boolean} enabled whether to enable E2EE or not.\n     * @returns {void}\n     */\n    public toggleE2EE(enabled: boolean): void {\n        if (!this.isE2EESupported()) {\n            logger.warn('Cannot enable / disable E2EE: platform is not supported.');\n\n            return;\n        }\n\n        this._e2eEncryption.setEnabled(enabled);\n    }\n\n    /**\n     * Sets the key and index for End-to-End encryption.\n     *\n     * @param {CryptoKey} [keyInfo.encryptionKey] - encryption key.\n     * @param {Number} [keyInfo.index] - the index of the encryption key.\n     * @returns {void}\n     */\n    public setMediaEncryptionKey(olmKey: Uint8Array, pqKey: Uint8Array, index: number): void {\n        this._e2eEncryption.setEncryptionKey(olmKey, pqKey, index);\n    }\n\n    /**\n     * Returns <tt>true</tt> if lobby support is enabled in the backend.\n     *\n     * @returns {boolean} whether lobby is supported in the backend.\n     */\n    public isLobbySupported(): boolean {\n        return Boolean(this.room?.getLobby().isSupported());\n    }\n\n    /**\n     * Returns <tt>true</tt> if the room has members only enabled.\n     *\n     * @returns {boolean} whether conference room is members only.\n     */\n    public isMembersOnly(): boolean {\n        return Boolean(this.room?.membersOnlyEnabled);\n    }\n\n    /**\n     * Returns <tt>true</tt> if the room supports visitors feature.\n     *\n     * @returns {boolean} whether conference room has visitors support.\n     */\n    public isVisitorsSupported(): boolean {\n        return Boolean(this.room?.visitorsSupported);\n    }\n\n    /**\n     * Enables lobby by moderators\n     *\n     * @returns {Promise} resolves when lobby room is joined or rejects with the error.\n     */\n    public enableLobby(): Promise<void> {\n        if (this.room && this.isModerator()) {\n            return this.room.getLobby().enable();\n        }\n\n        return Promise.reject(\n            new Error('The conference not started or user is not moderator'));\n    }\n\n    /**\n     * Disabled lobby by moderators\n     *\n     * @returns {void}\n     */\n    public disableLobby(): void {\n        if (this.room && this.isModerator()) {\n            this.room.getLobby().disable();\n        } else {\n            logger.warn(`Failed to disable lobby, ${this.room ? '' : 'not in a room, '}${\n                this.isModerator() ? '' : 'participant is not a moderator'}`);\n        }\n    }\n\n    /**\n     * Joins the lobby room with display name and optional email or with a shared password to skip waiting.\n     *\n     * @param {string} displayName Display name should be set to show it to moderators.\n     * @param {string} email Optional email is used to present avatar to the moderator.\n     * @returns {Promise<never>}\n     */\n    public joinLobby(displayName: string, email: string): Promise<void> {\n        if (this.room) {\n            if (!this.room.getLobby()?.lobbyRoom?.joined) {\n                return this.room.getLobby().join(displayName, email);\n            } else {\n                logger.warn('Already joined the lobby');\n\n                return Promise.resolve();\n            }\n\n        }\n\n        return Promise.reject(new Error('The conference not started'));\n    }\n\n    /**\n     * Gets the local id for a participant in a lobby room.\n     * Returns undefined when current participant is not in the lobby room.\n     * This is used for lobby room private chat messages.\n     *\n     * @returns {string}\n     */\n    public myLobbyUserId(): Optional<string> {\n        if (this.room) {\n            return this.room.getLobby().getLocalId();\n        }\n    }\n\n    /**\n     * Sends a message to a lobby room.\n     * When id is specified it sends a private message.\n     * Otherwise it sends the message to all moderators.\n     * @param {object} message The message to send\n     * @param {string} id The participant id.\n     *\n     * @returns {void}\n     */\n    public sendLobbyMessage(message: object, id: string): void {\n        if (this.room) {\n            if (id) {\n                return this.room.getLobby().sendPrivateMessage(id, message);\n            }\n\n            return this.room.getLobby().sendMessage(message);\n        }\n    }\n\n    /**\n     * Adds a message listener to the lobby room\n     * @param {Function} listener The listener function,\n     * called when a new message is received in the lobby room.\n     *\n     * @returns {Function} Handler returned to be able to remove it later.\n     */\n    public addLobbyMessageListener(listener: (message: object) => void): Optional<EventListener> {\n        if (this.room) {\n            return this.room.getLobby().addMessageListener(listener) as Optional<EventListener>;\n        }\n    }\n\n    /**\n     * Removes a message handler from the lobby room\n     * @param {Function} handler The handler function  to remove.\n     *\n     * @returns {void}\n     */\n    public removeLobbyMessageHandler(handler: (message: object) => void): void {\n        if (this.room) {\n            return this.room.getLobby().removeMessageHandler(handler);\n        }\n    }\n\n    /**\n     * Sends a message retraction to the lobby room.\n     * @param {string} messageId - The ID of the message being retracted.\n     * @param {string} [id] - The participant id, if the message was private.\n     * @returns {void}\n     */\n    public sendLobbyMessageRetraction(messageId: string, id?: string): void {\n        const lobby = this.room?.getLobby();\n\n        lobby?.sendMessageRetraction(messageId, id);\n    }\n\n    /**\n     * Adds a message retraction listener to the lobby room.\n     * @param {Function} listener - called with (messageId, participantId).\n     * @returns {Optional<EventListener>}\n     */\n    public addLobbyMessageRetractionListener(\n            listener: (messageId: string, participantId: string) => void): Optional<EventListener> {\n        const lobby = this.room?.getLobby();\n\n        return lobby?.addMessageRetractionListener(listener) as Optional<EventListener>;\n    }\n\n    /**\n     * Removes a message retraction handler from the lobby room.\n     * @param {Function} handler - The handler function to remove.\n     * @returns {void}\n     */\n    public removeLobbyMessageRetractionHandler(handler: (messageId: string, participantId: string) => void): void {\n        const lobby = this.room?.getLobby();\n\n        lobby?.removeMessageRetractionHandler(handler);\n    }\n\n    /**\n     * Denies an occupant in the lobby room access to the conference.\n     * @param {string} id The participant id.\n     * @returns {void}\n     */\n    public lobbyDenyAccess(id: string): void {\n        if (this.room) {\n            this.room.getLobby().denyAccess(id);\n        }\n    }\n\n    /**\n     * Approves the request to join the conference to a participant waiting in the lobby.\n     *\n     * @param {string|Array<string>} param The participant id or an array of ids.\n     * @returns {void}\n     */\n    public lobbyApproveAccess(param: string | string[]): void {\n        if (this.room) {\n            this.room.getLobby().approveAccess(param);\n        }\n    }\n\n    /**\n     * Returns <tt>true</tt> if AV Moderation support is enabled in the backend.\n     *\n     * @returns {boolean} whether AV Moderation is supported in the backend.\n     */\n    public isAVModerationSupported(): boolean {\n        return Boolean(this.room?.getAVModeration().isSupported());\n    }\n\n    /**\n     * Enables AV Moderation.\n     * @param {MediaType} mediaType \"audio\", \"desktop\" or \"video\"\n     * @returns {void}\n     */\n    public enableAVModeration(mediaType: MediaType): void {\n        if (this.room && this.isModerator()\n            && (mediaType === MediaType.AUDIO || mediaType === MediaType.DESKTOP || mediaType === MediaType.VIDEO)) {\n            this.room.getAVModeration().enable(true, mediaType);\n        } else {\n            logger.warn(`Failed to enable AV moderation, ${this.room ? '' : 'not in a room, '}${\n                this.isModerator() ? '' : 'participant is not a moderator, '}${\n                this.room && this.isModerator() ? 'wrong media type passed' : ''}`);\n        }\n    }\n\n    /**\n     * Disables AV Moderation.\n     * @param {MediaType} mediaType \"audio\", \"desktop\" or \"video\"\n     * @returns {void}\n     */\n    public disableAVModeration(mediaType: MediaType): void {\n        if (this.room && this.isModerator()\n            && (mediaType === MediaType.AUDIO || mediaType === MediaType.DESKTOP || mediaType === MediaType.VIDEO)) {\n            this.room.getAVModeration().enable(false, mediaType);\n        } else {\n            logger.warn(`Failed to disable AV moderation, ${this.room ? '' : 'not in a room, '}${\n                this.isModerator() ? '' : 'participant is not a moderator, '}${\n                this.room && this.isModerator() ? 'wrong media type passed' : ''}`);\n        }\n    }\n\n    /**\n     * Approve participant access to certain media, allows unmuting audio or video.\n     *\n     * @param {MediaType} mediaType \"audio\", \"desktop\" or \"video\"\n     * @param id the id of the participant.\n     * @returns {void}\n     */\n    public avModerationApprove(mediaType: MediaType, id: string): void {\n        if (this.room && this.isModerator()\n            && (mediaType === MediaType.AUDIO || mediaType === MediaType.DESKTOP || mediaType === MediaType.VIDEO)) {\n\n            const participant = this.getParticipantById(id);\n\n            if (!participant) {\n                return;\n            }\n\n            this.room.getAVModeration().approve(mediaType, participant.getJid());\n        } else {\n            logger.warn(`AV moderation approve skipped , ${this.room ? '' : 'not in a room, '}${\n                this.isModerator() ? '' : 'participant is not a moderator, '}${\n                this.room && this.isModerator() ? 'wrong media type passed' : ''}`);\n        }\n    }\n\n    /**\n     * Reject participant access to certain media, blocks unmuting audio or video.\n     *\n     * @param {MediaType} mediaType \"audio\", \"desktop\" or \"video\"\n     * @param id the id of the participant.\n     * @returns {void}\n     */\n    public avModerationReject(mediaType: MediaType, id: string): void {\n        if (this.room && this.isModerator()\n            && (mediaType === MediaType.AUDIO || mediaType === MediaType.DESKTOP || mediaType === MediaType.VIDEO)) {\n\n            const participant = this.getParticipantById(id);\n\n            if (!participant) {\n                return;\n            }\n\n            this.room.getAVModeration().reject(mediaType, participant.getJid());\n        } else {\n            logger.warn(`AV moderation reject skipped , ${this.room ? '' : 'not in a room, '}${\n                this.isModerator() ? '' : 'participant is not a moderator, '}${\n                this.room && this.isModerator() ? 'wrong media type passed' : ''}`);\n        }\n    }\n\n    /**\n     * Returns the breakout rooms manager object.\n     *\n     * @returns {Optional<BreakoutRooms>} the breakout rooms manager.\n     */\n    public getBreakoutRooms(): Optional<BreakoutRooms> {\n        return this.room?.getBreakoutRooms();\n    }\n\n    /**\n     * Returns the file sharing manager object.\n     *\n     * @returns {Optional<FileSharing>} the file sharing manager.\n     */\n    public getFileSharing(): Optional<FileSharing> {\n        return this.room?.getFileSharing();\n    }\n\n    /**\n     * Returns the metadata handler object.\n     *\n     * @returns {Optional<RoomMetadata>} the room metadata handler.\n     */\n    public getMetadataHandler(): Optional<RoomMetadata> {\n        return this.room?.getMetadataHandler();\n    }\n\n    /**\n     * Returns the polls object.\n     *\n     * @returns {Optional<Polls>} the polls.\n     */\n    public getPolls(): Optional<Polls> {\n        return this.room?.getPolls();\n    }\n\n    /**\n     * Requests short-term credentials from the backend if available.\n     * @param {string} service - The service for which to request the credentials.\n     * @returns {Promise} A promise that resolves with the credentials or rejects with an error.\n     */\n    public getShortTermCredentials(service: string): Promise<string> {\n        if (this.room) {\n            return this.room.getShortTermCredentials(service);\n        }\n\n        return Promise.reject(new Error('The conference is not created yet!'));\n    }\n\n    /**\n     * @internal\n     * @returns {Optional<VADAudioAnalyser>} the audio analyser.\n     */\n    getAudioAnalyser(): Optional<VADAudioAnalyser> {\n        return this?._audioAnalyser;\n    }\n\n    /**\n     * @internal\n     * @returns {XMPP} the XMPP connection object.\n     */\n    get xmpp(): XMPP {\n        return this._xmpp;\n    }\n}\n","import { getLogger } from '@jitsi/logger';\n\nimport JitsiConference from './JitsiConference';\nimport { JitsiConnectionEvents } from './JitsiConnectionEvents';\nimport RTCStats from './modules/RTCStats/RTCStats';\nimport FeatureFlags from './modules/flags/FeatureFlags';\nimport Statistics from './modules/statistics/statistics';\nimport XMPP from './modules/xmpp/xmpp';\nimport {\n    AnalyticsEvents,\n    createConnectionFailedEvent\n} from './service/statistics/AnalyticsEvents';\n\nconst logger = getLogger('core:JitsiConnection');\n\nexport interface IConnectionOptions {\n    analytics?: any;\n    audioTranslation?: {\n        enabled?: boolean;\n    };\n    bridgeChannel?: {\n        ignoreDomain?: string;\n        preferSctp?: boolean;\n    };\n    disableFocus?: boolean;\n    enableWebsocketResume: boolean;\n    flags?: Record<string, any>;\n    hosts: {\n        domain: string;\n    };\n    name?: string;\n    p2pStunServers: any[];\n    serviceUrl: string;\n    websocketKeepAlive?: number;\n    websocketKeepAliveUrl?: string;\n    xmppPing?: any;\n}\n\nexport interface IConnectOptions {\n    id?: string;\n    name?: string;\n    password?: string;\n}\n\nexport interface IAttachOptions {\n    jid: string;\n    rid: string;\n    sid: string;\n}\n\n/**\n * Creates a new connection object for the Jitsi Meet server side video\n * conferencing service. Provides access to the JitsiConference interface.\n */\nexport default class JitsiConnection {\n    private appID?: string;\n    private token?: string;\n    private _xmpp: XMPP;\n    readonly options: IConnectionOptions;\n\n    /**\n     * Creates a new JitsiConnection instance.\n     * @param appID - Identification for the provider of Jitsi Meet video conferencing services.\n     * @param token - The JWT token used to authenticate with the server (optional).\n     * @param options - Object with properties / settings related to connection with the server.\n     */\n    constructor(appID: string, token: Nullable<string>, options: IConnectionOptions) {\n        this.appID = appID;\n        this.token = token;\n        this.options = options;\n\n        // Initialize the feature flags so that they are advertised through the disco-info.\n        FeatureFlags.init(options.flags || {});\n\n        this._xmpp = new XMPP(options, token);\n\n        this.addEventListener(JitsiConnectionEvents.CONNECTION_FAILED,\n            (errType: string, msg: string, credentials: any, details: any) => {\n                Statistics.sendAnalyticsAndLog(\n                    createConnectionFailedEvent(errType, msg, details));\n            });\n\n        this.addEventListener(JitsiConnectionEvents.CONNECTION_DISCONNECTED,\n            (msg: string) => {\n                // we can see disconnects from normal tab closing of the browser\n                // and then there are no msgs, but we want to log only disconnects\n                // when there is real error\n                // XXX Do we need the difference in handling between the log and\n                // analytics event here?\n                if (msg) {\n                    Statistics.sendAnalytics(\n                        AnalyticsEvents.CONNECTION_DISCONNECTED,\n                        { message: msg });\n                }\n            });\n    }\n\n    /**\n     * Connect the client with the server.\n     * @param options - Connecting options (for example authentications parameters).\n     * @param options.id - The username to use when connecting, if any.\n     * @param options.password - The password to use when connecting with username, if any.\n     * @param options.name - The name of the room/conference we will be connecting to. This is needed on connection\n     * time to be able to send conference-request over http. If missing the flow where we send conference-iq to jicofo over\n     * the established xmpp connection will be used, even in the case where we have configured conference http request url\n     * to be used.\n     */\n    connect(options: IConnectOptions = {}): void {\n\n        RTCStats.startWithConnection(this);\n\n        // if we get redirected, we set disableFocus to skip sending the conference request twice\n        if (this.xmpp.moderator.targetUrl && !this.options.disableFocus && options.name) {\n            // The domain (optional) will uses this.options.hosts.muc.toLowerCase() if not provided\n            this.xmpp.moderator.sendConferenceRequest(this.xmpp.getRoomJid(options.name, undefined))\n                .then(() => {\n                    this.xmpp.connect(options.id, options.password);\n                })\n                .catch(e => logger.trace('sendConferenceRequest rejected', e));\n        } else {\n            this.xmpp.connect(options.id, options.password);\n        }\n    }\n\n    /**\n     * Attach to existing connection. Can be used for optimizations. For example:\n     * if the connection is created on the server we can attach to it and start\n     * using it.\n     *\n     * @param options - Connecting options - rid, sid and jid.\n     */\n    attach(options: IAttachOptions): void {\n        this.xmpp.attach(options);\n    }\n\n    /**\n     * Disconnect the client from the server.\n     * @param args - Optional arguments to be passed to XMPP.disconnect\n     * @returns Promise that resolves when the disconnect process is finished or rejects with an error.\n     */\n    disconnect(...args: any): boolean | Promise<void> {\n        // XXX Forward any arguments passed to JitsiConnection.disconnect to\n        // XMPP.disconnect. For example, the caller of JitsiConnection.disconnect\n        // may optionally pass the event which triggered the disconnect in order to\n        // provide the implementation with finer-grained context.\n        return this.xmpp.disconnect(...args);\n    }\n\n    /**\n     * Returns the jid of the participant associated with the XMPP connection.\n     *\n     * @returns The jid of the participant.\n     */\n    getJid(): string {\n        return this.xmpp.getJid();\n    }\n\n    /**\n     * This method allows renewal of the tokens if they are expiring.\n     * @param token - The new token.\n     */\n    refreshToken(token: string): Promise<void> {\n        this.token = token;\n\n        return this._xmpp.refreshToken(this.token);\n    }\n\n    /**\n     * Creates and joins new conference.\n     * @param name - The name of the conference; if null - a generated name will be\n     * provided from the api\n     * @param options - Object with properties / settings related to the conference\n     * that will be created.\n     * @returns The new conference object.\n     */\n    initJitsiConference(name: Nullable<string>, options: Record<string, any>): JitsiConference {\n        return new JitsiConference({\n            config: options,\n            connection: this,\n            name\n        });\n    }\n\n    /**\n     * Subscribes the passed listener to the event.\n     * @param event - The connection event.\n     * @param listener - The function that will receive the event\n     */\n    addEventListener(event: JitsiConnectionEvents, listener: (...args: any[]) => void): void {\n        this.xmpp.addListener(event, listener);\n    }\n\n    /**\n     * Unsubscribes the passed handler.\n     * @param event - The connection event.\n     * @param listener - The function that will receive the event\n     */\n    removeEventListener(event: JitsiConnectionEvents, listener: (...args: any[]) => void): void {\n        this.xmpp.removeListener(event, listener);\n    }\n\n    /**\n     * Returns measured connectionTimes.\n     * @returns Object containing connection timing information\n     */\n    getConnectionTimes(): Record<string, any> {\n        return this.xmpp.connectionTimes;\n    }\n\n    /**\n     * Adds new feature to the list of supported features for the local\n     * participant.\n     * @param feature - The name of the feature.\n     * @param submit - If true - the new list of features will be\n     * immediately submitted to the others.\n     */\n    addFeature(feature: string, submit: boolean = false): void {\n        this.xmpp.caps.addFeature(feature, submit, true);\n    }\n\n    /**\n     * Removes a feature from the list of supported features for the local\n     * participant\n     * @param feature - The name of the feature.\n     * @param submit - If true - the new list of features will be\n     * immediately submitted to the others.\n     */\n    removeFeature(feature: string, submit: boolean = false): void {\n        this.xmpp.caps.removeFeature(feature, submit, true);\n    }\n\n    /**\n     * Get object with internal logs.\n     * @returns Object containing connection logs and metadata\n     */\n    getLogs(): Record<string, any> {\n        const data = this.xmpp.getJingleLog();\n\n        const metadata: Record<string, any> = {};\n\n        metadata.time = new Date();\n        metadata.url = window.location.href;\n        metadata.ua = navigator.userAgent;\n\n        const log = this.xmpp.getXmppLog();\n\n        if (log) {\n            metadata.xmpp = log;\n        }\n\n        data.metadata = metadata;\n\n        return data;\n    }\n\n    /**\n     * Get the XMPP instance.\n     * @internal\n     */\n    get xmpp(): XMPP {\n        return this._xmpp;\n    }\n}\n","export enum JitsiMediaDevicesEvents {\n\n    /**\n     * Indicates that the list of available media devices has been changed. The\n     * event provides the following parameters to its listeners:\n     *\n     * @param {MediaDeviceInfo[]} devices - array of MediaDeviceInfo or\n     *  MediaDeviceInfo-like objects that are currently connected.\n     *  @see https://developer.mozilla.org/en-US/docs/Web/API/MediaDeviceInfo\n     */\n    DEVICE_LIST_CHANGED = 'mediaDevices.devicechange',\n\n    /**\n     * Event emitted when the user granted/blocked a permission for the camera / mic.\n     * Used to keep track of the granted permissions on browsers which don't\n     * support the Permissions API.\n     */\n    PERMISSIONS_CHANGED = 'rtc.permissions_changed',\n\n    /**\n     * Indicates that the environment is currently showing permission prompt to\n     * access camera and/or microphone. The event provides the following\n     * parameters to its listeners:\n     *\n     * @param {'chrome'|'opera'|'firefox'|'safari'|'nwjs'\n     *  |'react-native'|'android'} environmentType - type of browser or\n     *  other execution environment.\n     */\n    PERMISSION_PROMPT_IS_SHOWN = 'mediaDevices.permissionPromptIsShown'\n}\n","import { JitsiMediaDevicesEvents } from './JitsiMediaDevicesEvents';\nimport RTC from './modules/RTC/RTC';\nimport browser from './modules/browser';\nimport Listenable from './modules/util/Listenable';\nimport { MediaType } from './service/RTC/MediaType';\nimport { RTCEvents } from './service/RTC/RTCEvents';\n\nconst AUDIO_PERMISSION_NAME = 'microphone' as PermissionName;\nconst PERMISSION_GRANTED_STATUS = 'granted';\nconst VIDEO_PERMISSION_NAME = 'camera' as PermissionName;\n\n/**\n * Media devices utilities for Jitsi.\n * @noInheritDoc\n */\nexport default class JitsiMediaDevices extends Listenable {\n    private _initialized: boolean;\n    private _permissions: { [key: string]: boolean; };\n    private _permissionsApiSupported: Promise<boolean>;\n\n    /**\n     * Initializes a `JitsiMediaDevices` object. There will be a single\n     * instance of this class.\n     */\n    constructor() {\n        super();\n        this._initialized = false;\n        this._permissions = {};\n        this._permissionsApiSupported = Promise.resolve(false);\n    }\n\n    /**\n     * Parses a PermissionState object and returns true for granted and false otherwise.\n     *\n     * @param {PermissionState} permissionStatus - The PermissionState object retrieved from the Permissions API.\n     * @returns {boolean} - True for granted and false for denied.\n     * @throws {TypeError}\n     */\n    private _parsePermissionState(permissionStatus: PermissionStatus = {} as PermissionStatus): boolean {\n        const status = permissionStatus.state;\n\n        if (typeof status !== 'string') {\n            throw new TypeError();\n        }\n\n        return status === PERMISSION_GRANTED_STATUS;\n    }\n\n    /**\n     * Updates the local granted/denied permissions cache. A permissions might be\n     * granted, denied, or undefined. This is represented by having its media\n     * type key set to `true` or `false` respectively.\n     *\n     * @param {Object} permissions - Object with the permissions.\n     */\n    private _handlePermissionsChange(permissions: { [key: string]: boolean; }): void {\n        const hasPermissionsChanged\n            = [ MediaType.AUDIO, MediaType.VIDEO ]\n                .some(type => type in permissions && permissions[type] !== this._permissions[type]);\n\n        if (hasPermissionsChanged) {\n            this._permissions = {\n                ...this._permissions,\n                ...permissions\n            };\n            this.eventEmitter.emit(JitsiMediaDevicesEvents.PERMISSIONS_CHANGED, this._permissions);\n\n            if (this._permissions[MediaType.AUDIO] || this._permissions[MediaType.VIDEO]) {\n                // Triggering device list update when the permissions are granted in order to update\n                // the labels the devices.\n                this.enumerateDevices(() => {\n                    // Empty callback - device list update triggered\n                });\n            }\n        }\n    }\n\n    /**\n     * Initialize. Start listening for device changes and initialize permissions checks.\n     * @internal\n     */\n    init(): void {\n        if (this._initialized) {\n            return;\n        }\n        this._initialized = true;\n\n        RTC.addListener(\n            RTCEvents.DEVICE_LIST_CHANGED,\n            devices =>\n                this.eventEmitter.emit(\n                    JitsiMediaDevicesEvents.DEVICE_LIST_CHANGED,\n                    devices));\n\n        // We would still want to update the permissions cache in case the permissions API is not supported.\n        RTC.addListener(\n            RTCEvents.PERMISSIONS_CHANGED,\n            permissions => this._handlePermissionsChange(permissions));\n\n        // Test if the W3C Permissions API is implemented and the 'camera' and 'microphone' permissions are\n        // implemented. If supported add onchange listeners.\n        this._permissionsApiSupported = new Promise(resolve => {\n            if (!navigator.permissions) {\n                resolve(false);\n\n                return;\n            }\n\n            const promises: Promise<boolean>[] = [];\n\n            promises.push(navigator.permissions.query({ name: VIDEO_PERMISSION_NAME })\n                .then(status => {\n                    this._handlePermissionsChange({\n                        [MediaType.VIDEO]: this._parsePermissionState(status)\n                    });\n                    status.onchange = () => {\n                        try {\n                            this._handlePermissionsChange({\n                                [MediaType.VIDEO]: this._parsePermissionState(status)\n                            });\n                        } catch (error) {\n                            // Nothing to do.\n                        }\n                    };\n\n                    return true;\n                })\n                .catch(() => false));\n\n            promises.push(navigator.permissions.query({ name: AUDIO_PERMISSION_NAME })\n                .then(status => {\n                    this._handlePermissionsChange({\n                        [MediaType.AUDIO]: this._parsePermissionState(status)\n                    });\n                    status.onchange = () => {\n                        try {\n                            this._handlePermissionsChange({\n                                [MediaType.AUDIO]: this._parsePermissionState(status)\n                            });\n                        } catch (error) {\n                            // Nothing to do.\n                        }\n                    };\n\n                    return true;\n                })\n                .catch(() => false));\n\n            Promise.all(promises).then(results => resolve(results.every(supported => supported)));\n\n        });\n    }\n\n    /**\n     * Executes callback with list of media devices connected.\n     * @param {function} callback\n     */\n    enumerateDevices(callback: (devices: MediaDeviceInfo[]) => void): void {\n        RTC.enumerateDevices(callback);\n    }\n\n    /**\n     * Returns true if changing the input (camera / microphone) or output\n     * (audio) device is supported and false if not.\n     * @param {string} [deviceType] - type of device to change. Default is\n     *      undefined or 'input', 'output' - for audio output device change.\n     * @returns {boolean} true if available, false otherwise.\n     */\n    isDeviceChangeAvailable(deviceType?: string): boolean {\n        return RTC.isDeviceChangeAvailable(deviceType);\n    }\n\n    /**\n     * Checks if the permission for the given device was granted.\n     *\n     * @param {'audio'|'video'} [type] - type of devices to check,\n     *      undefined stands for both 'audio' and 'video' together\n     * @returns {Promise<boolean>}\n     */\n    isDevicePermissionGranted(type?: MediaType): Promise<boolean> {\n        return new Promise(resolve => {\n            // Shortcut: first check if we already know the permission was\n            // granted.\n            if (type in this._permissions) {\n                resolve(this._permissions[type]);\n\n                return;\n            }\n\n            // Check using the Permissions API.\n            this._permissionsApiSupported.then(supported => {\n                if (!supported) {\n                    resolve(false);\n\n                    return;\n                }\n\n                const promises: Promise<PermissionStatus>[] = [];\n\n                switch (type) {\n                case MediaType.VIDEO:\n                    promises.push(\n                        navigator.permissions.query({\n                            name: VIDEO_PERMISSION_NAME\n                        }));\n                    break;\n                case MediaType.AUDIO:\n                    promises.push(\n                        navigator.permissions.query({\n                            name: AUDIO_PERMISSION_NAME\n                        }));\n                    break;\n                default:\n                    promises.push(\n                        navigator.permissions.query({\n                            name: VIDEO_PERMISSION_NAME\n                        }));\n                    promises.push(\n                        navigator.permissions.query({\n                            name: AUDIO_PERMISSION_NAME\n                        }));\n                }\n\n                Promise.all(promises).then(\n                    results => resolve(results.every(permissionStatus => {\n                        try {\n                            return this._parsePermissionState(permissionStatus);\n                        } catch {\n                            return false;\n                        }\n                    })),\n                    () => resolve(false)\n                );\n            });\n        });\n    }\n\n    /**\n     * Returns true if it is possible to be simultaneously capturing audio from more than one device.\n     *\n     * @returns {boolean}\n     */\n    isMultipleAudioInputSupported(): boolean {\n        return !(\n            (browser.isFirefox() && browser.isVersionLessThan(101))\n            || browser.isIosBrowser()\n        );\n    }\n\n    /**\n     * Returns currently used audio output device id, 'default' stands\n     * for default device\n     * @returns {string}\n     */\n    getAudioOutputDevice(): string {\n        return RTC.getAudioOutputDevice();\n    }\n\n    /**\n     * Sets current audio output device.\n     * @param {string} deviceId - id of 'audiooutput' device from\n     *      navigator.mediaDevices.enumerateDevices(), 'default' is for\n     *      default device\n     * @returns {Promise} - resolves when audio output is changed, is rejected\n     *      otherwise\n     */\n    setAudioOutputDevice(deviceId: string): Promise<void> {\n        return RTC.setAudioOutputDevice(deviceId);\n    }\n}\n","import { getLogger } from '@jitsi/logger';\n\nimport { JitsiTrackEvents } from '../../JitsiTrackEvents';\nimport JitsiLocalTrack from '../RTC/JitsiLocalTrack';\nimport RTC from '../RTC/RTC';\nimport Statistics from '../statistics/statistics';\n\nexport interface IActiveDeviceInfo {\n    deviceId: string;\n    deviceLabel: string;\n}\n\nconst logger = getLogger('vad:ActiveDeviceDetector');\n\n// If after 3000 ms the detector did not find any active devices consider that there aren't any usable ones available\n// i.e. audioLevel > 0.008\nconst DETECTION_TIMEOUT = 3000;\n\n\n/**\n * Go through all audio devices on the system and return one that is active, i.e. has audio signal.\n *\n * @returns Promise<IActiveDeviceInfo> - Object containing information about the found device.\n */\nexport default function getActiveAudioDevice(): Promise<IActiveDeviceInfo> {\n\n    return new Promise(resolve => {\n        RTC.enumerateDevices((devices: MediaDeviceInfo[]) => {\n            const audioDevices = devices.filter(device => device.kind === 'audioinput');\n            const devicePromiseArray: Promise<JitsiLocalTrack>[] = [];\n\n\n            for (const micDevice of audioDevices) {\n                const devicePromise = RTC.obtainAudioAndVideoPermissions({\n                    devices: [ 'audio' ],\n                    micDeviceId: micDevice.deviceId\n                }).then((tracks: JitsiLocalTrack[]) => {\n\n                    // We expect a single device to be available when obtained from obtainAudioAndVideoPermissions\n                    // that's  why only take p.value[0].\n                    const track = tracks[0];\n\n                    Statistics.startLocalStats(track, track.setAudioLevel.bind(track));\n\n                    return track;\n                });\n\n                devicePromiseArray.push(devicePromise);\n            }\n\n            Promise.allSettled(devicePromiseArray).then(outcomeArray => {\n                const successfulPromises = outcomeArray.filter(p => p.status === 'fulfilled');\n                const rejectedPromises = outcomeArray.filter(p => p.status === 'rejected');\n\n\n                const availableDevices = successfulPromises.map(p => (p as PromiseFulfilledResult<JitsiLocalTrack>).value);\n                const rejectReasons = rejectedPromises.map(p => (p as any).value);\n\n                for (const reason of rejectReasons) {\n                    logger.error('Failed to acquire audio device with error: ', reason);\n                }\n\n                // Setup event handlers for monitored devices.\n                for (const device of availableDevices) {\n                    device.on(JitsiTrackEvents.TRACK_AUDIO_LEVEL_CHANGED, audioLevel => {\n                        // This is a very naive approach but works, a more accurate one would be to use rnnoise in\n                        // order to limit  the number of false positives. The 0.008 constant is due to how\n                        // LocalStatsCollector from lib-jitsi-meet publishes audio-levels, in this case 0.008 denotes //\n                        // no input.\n                        if (audioLevel > 0.008) {\n                            stopActiveDevices(availableDevices);\n                            resolve({\n                                deviceId: device.deviceId,\n                                deviceLabel: device.getTrack().label\n                            });\n                        }\n                    });\n                }\n\n                // Cancel the detection in case no devices was found with audioLevel > 0 in the set timeout.\n                setTimeout(() => {\n                    stopActiveDevices(availableDevices);\n                    resolve({\n                        deviceId: '',\n                        deviceLabel: ''\n                    });\n                }, DETECTION_TIMEOUT);\n\n            });\n\n        });\n    });\n}\n\n/**\n * Stop the streams of the provided JitsiLocalTracks.\n *\n * @param {Array<JitsiLocalTrack>} deviceList - Array of JitsiLocalTracks to stop.\n * @returns {void}\n */\nfunction stopActiveDevices(deviceList: JitsiLocalTrack[]): void {\n    for (const device of deviceList) {\n        device.stopStream();\n    }\n}\n","import { getLogger } from '@jitsi/logger';\n\nimport { MediaType } from '../../service/RTC/MediaType';\nimport { type IPeerMediaInfo, default as SignalingLayer } from '../../service/RTC/SignalingLayer';\nimport ChatRoom from '../xmpp/ChatRoom';\n\nconst logger = getLogger('proxyconnection:CustomSignalingLayer');\n\n/**\n * Custom semi-mock implementation for the Proxy connection service.\n */\nexport default class CustomSignalingLayer extends SignalingLayer {\n    /**\n     * A map that stores SSRCs of remote streams.\n     * @type {Map<number, string>} maps SSRC number to jid\n     */\n    private ssrcOwners: Map<number, string>;\n\n    /**\n     *\n     * @type {ChatRoom|null}\n     */\n    public chatRoom: Nullable<ChatRoom>;\n\n    /**\n     * Creates new instance.\n     */\n    constructor() {\n        super();\n\n        this.ssrcOwners = new Map<number, string>();\n        this.chatRoom = null;\n    }\n\n    /**\n     * @inheritDoc\n     */\n    override getPeerMediaInfo(_owner: string, _mediaType: MediaType, _sourceName: string): IPeerMediaInfo {\n        return { };\n    }\n\n    /**\n     * @inheritDoc\n     */\n    override getPeerSourceInfo(_owner: string, _sourceName: string): any {\n        return undefined;\n    }\n\n    /**\n     * @inheritDoc\n     */\n    override getSSRCOwner(ssrc: number): Optional<string> {\n        return this.ssrcOwners.get(ssrc);\n    }\n\n    /**\n     * @inheritDoc\n     */\n    override getTrackSourceName(_ssrc: number): Optional<string> {\n        return undefined;\n    }\n\n    /**\n     * @inheritDoc\n     */\n    override removeSSRCOwners(ssrcList: number[]): void {\n        if (!ssrcList?.length) {\n            return;\n        }\n\n        for (const ssrc of ssrcList) {\n            this.ssrcOwners.delete(ssrc);\n        }\n    }\n\n    /**\n     * Sets the <tt>ChatRoom</tt> instance used.\n     * @param {ChatRoom} room\n     */\n    setChatRoom(room: ChatRoom): void {\n        this.chatRoom = room;\n    }\n\n    /**\n     * @inheritDoc\n     */\n    override setSSRCOwner(ssrc: number, endpointId: string): void {\n        if (typeof ssrc !== 'number') {\n            throw new TypeError(`SSRC(${ssrc}) must be a number`);\n        }\n\n        // Now signaling layer instance is shared between different JingleSessionPC instances, so although very unlikely\n        // an SSRC conflict could potentially occur. Log a message to make debugging easier.\n        const existingOwner = this.ssrcOwners.get(ssrc);\n\n        if (existingOwner && existingOwner !== endpointId) {\n            logger.error(`SSRC owner re-assigned from ${existingOwner} to ${endpointId}`);\n        }\n        this.ssrcOwners.set(ssrc, endpointId);\n    }\n\n    /**\n     * @inheritDoc\n     */\n    override setTrackMuteStatus(_sourceName: string, _muted: boolean): boolean {\n        return false;\n    }\n\n    /**\n     * @inheritDoc\n     */\n    override setTrackVideoType(_sourceName: string, _videoType: string): boolean {\n        return false;\n    }\n\n    /**\n     * @inheritDoc\n     */\n    override updateSsrcOwnersOnLeave(id: string): void {\n        const ssrcs = Array.from(this.ssrcOwners)\n            .filter((entry: [number, string]) => entry[1] === id)\n            .map((entry: [number, string]) => entry[0]);\n\n        if (!ssrcs?.length) {\n            return;\n        }\n\n        this.removeSSRCOwners(ssrcs);\n    }\n}\n","/**\n * The know jingle actions that can be sent and should be acted upon by\n * {@code ProxyConnectionService} and {@code ProxyConnectionPC}.\n */\nexport enum ACTIONS {\n    ACCEPT = 'session-accept',\n    CONNECTION_ERROR = 'connection-error-encountered',\n    INITIATE = 'session-initiate',\n    TERMINATE = 'session-terminate',\n    TRANSPORT_INFO = 'transport-info',\n    UNAVAILABLE = 'unavailable'\n}\n","import { getLogger } from '@jitsi/logger';\n\nimport { getAttribute } from '../../modules/util/XMLUtils';\nimport { RTCEvents } from '../../service/RTC/RTCEvents';\nimport { XMPPEvents } from '../../service/xmpp/XMPPEvents';\nimport RTC from '../RTC/RTC';\nimport JingleSessionPC from '../xmpp/JingleSessionPC';\nimport { DEFAULT_STUN_SERVERS } from '../xmpp/xmpp';\n\nimport CustomSignalingLayer from './CustomSignalingLayer';\nimport { ACTIONS } from './constants';\n\nconst logger = getLogger('proxyconnection:ProxyConnectionPC');\n\n/**\n * An adapter around {@code JingleSessionPC} so its logic can be re-used without\n * an XMPP connection. It is being re-used for consistency with the rest of the\n * codebase and to leverage existing peer connection event handling. Also\n * this class provides a facade to hide most of the API for\n * {@code JingleSessionPC}.\n */\nexport default class ProxyConnectionPC {\n    /**\n     * Initializes a new {@code ProxyConnectionPC} instance.\n     *\n     * @param {Object} options - Values to initialize the instance with.\n     * @param {Object} [options.pcConfig] - The {@code RTCConfiguration} to use for the WebRTC peer connection.\n     * @param {boolean} [options.isInitiator] - If true, the local client should send offers. If false, the local\n     * client should send answers. Defaults to false.\n     * @param {Function} options.onRemoteStream - Callback to invoke when a remote media stream has been received\n     * through the peer connection.\n     * @param {string} options.peerJid - The jid of the remote client with which the peer connection is being establish\n     * and which should receive direct messages regarding peer connection updates.\n     * @param {boolean} [options.receiveVideo] - Whether or not the peer connection should accept incoming video\n     * streams. Defaults to false.\n     * @param {Function} options.onSendMessage - Callback to invoke when a message has to be sent (signaled) out.\n     */\n    constructor(options = {}) {\n        this._options = {\n            isInitiator: false,\n            pcConfig: {},\n            receiveAudio: false,\n            receiveVideo: false,\n            ...options\n        };\n\n        /**\n         * Instances of {@code JitsiTrack} associated with this instance of\n         * {@code ProxyConnectionPC}.\n         *\n         * @type {Array<JitsiTrack>}\n         */\n        this._tracks = [];\n\n        /**\n         * The active instance of {@code JingleSessionPC}.\n         *\n         * @type {JingleSessionPC|null}\n         */\n        this._peerConnection = null;\n\n        // Bind event handlers so they are only bound once for every instance.\n        this._onError = this._onError.bind(this);\n        this._onRemoteStream = this._onRemoteStream.bind(this);\n        this._onSendMessage = this._onSendMessage.bind(this);\n    }\n\n    /**\n     * Returns the jid of the remote peer with which this peer connection should\n     * be established with.\n     *\n     * @returns {string}\n     */\n    getPeerJid() {\n        return this._options.peerJid;\n    }\n\n    /**\n     * Updates the peer connection based on the passed in jingle.\n     *\n     * @param {Element} jingleElement - An XML jingle element describing how the peer connection should be updated.\n     * @returns {void}\n     */\n    processMessage(jingleElement) {\n        switch (getAttribute(jingleElement, 'action')) {\n        case ACTIONS.ACCEPT:\n            this._onSessionAccept(jingleElement);\n            break;\n\n        case ACTIONS.INITIATE:\n            this._onSessionInitiate(jingleElement);\n            break;\n\n        case ACTIONS.TERMINATE:\n            this._onSessionTerminate(jingleElement);\n            break;\n\n        case ACTIONS.TRANSPORT_INFO:\n            this._onTransportInfo(jingleElement);\n            break;\n        }\n    }\n\n    /**\n     * Instantiates a peer connection and starts the offer/answer cycle to\n     * establish a connection with a remote peer.\n     *\n     * @param {Array<JitsiLocalTrack>} localTracks - Initial local tracks to add\n     * to add to the peer connection.\n     * @returns {void}\n     */\n    start(localTracks = []) {\n        if (this._peerConnection) {\n            return;\n        }\n\n        this._tracks = this._tracks.concat(localTracks);\n\n        this._peerConnection = this._createPeerConnection();\n\n        this._peerConnection.invite(localTracks);\n    }\n\n    /**\n     * Begins the process of disconnecting from a remote peer and cleaning up\n     * the peer connection.\n     *\n     * @returns {void}\n     */\n    stop() {\n        if (this._peerConnection) {\n            this._peerConnection.terminate();\n        }\n\n        this._onSessionTerminate();\n    }\n\n    /**\n     * Instantiates a new {@code JingleSessionPC} by stubbing out the various\n     * dependencies of {@code JingleSessionPC}.\n     *\n     * @private\n     * @returns {JingleSessionPC}\n     */\n    _createPeerConnection() {\n        /**\n         * {@code JingleSessionPC} takes in the entire jitsi-meet config.js\n         * object, which may not be accessible from the caller.\n         *\n         * @type {Object}\n         */\n        const configStub = {};\n\n        /**\n         * {@code JingleSessionPC} assumes an XMPP/Strophe connection object is\n         * passed through, which also has the jingle plugin initialized on it.\n         * This connection object is used to signal out peer connection updates\n         * via iqs, and those updates need to be piped back out to the remote\n         * peer.\n         *\n         * @type {Object}\n         */\n        const connectionStub = {\n            // At the time this is used for Spot and it's okay to say the connection is always connected, because if\n            // spot has no signalling it will not be in a meeting where this is used.\n            // eslint-disable-next-line no-empty-function\n            addCancellableListener: () => () => { },\n            // eslint-disable-next-line no-empty-function\n            addEventListener: () => () => { },\n            connected: true,\n            jingle: {\n                terminate: () => { /** no-op */ }\n            },\n            sendIQ: this._onSendMessage\n        };\n\n        /**\n         * {@code JingleSessionPC} can take in a custom ice configuration,\n         * depending on the peer connection type, peer-to-peer or other.\n         * However, {@code ProxyConnectionPC} always assume a peer-to-peer\n         * connection so the ice configuration is hard-coded with defaults.\n         *\n         * @type {Object}\n         */\n        const pcConfigStub = {\n            iceServers: DEFAULT_STUN_SERVERS,\n            ...this._options.pcConfig\n        };\n\n        /**\n         * {@code JingleSessionPC} expects an instance of\n         * {@code JitsiConference}, which has an event emitter that is used\n         * to signal various connection updates that the local client should\n         * act upon. The conference instance is not a dependency of a proxy\n         * connection, but the emitted events can be relevant to the proxy\n         * connection so the event emitter is stubbed.\n         *\n         * @param {string} event - The constant for the event type.\n         * @type {Function}\n         * @returns {void}\n         */\n        const emitter = event => {\n            switch (event) {\n            case XMPPEvents.CONNECTION_ICE_FAILED:\n            case XMPPEvents.CONNECTION_FAILED:\n                this._onError(ACTIONS.CONNECTION_ERROR, event);\n                break;\n            }\n        };\n\n        /**\n         * {@link JingleSessionPC} expects an instance of\n         * {@link ChatRoom} to be passed in. {@link ProxyConnectionPC}\n         * is instantiated outside of the {@code JitsiConference}, so it must be\n         * stubbed to prevent errors.\n         *\n         * @type {Object}\n         */\n        const roomStub = {\n            addEventListener: () => { /* no op */ },\n            addPresenceListener: () => { /* no-op */ },\n            connectionTimes: [],\n            eventEmitter: { emit: emitter },\n            removeEventListener: () => { /* no op */ },\n            removePresenceListener: () => { /* no-op */ }\n        };\n\n        /**\n         * A {@code JitsiConference} stub passed to the {@link RTC} module.\n         * @type {Object}\n         */\n        const conferenceStub = {\n            myUserId: () => ''\n        };\n\n        /**\n         * Create an instance of {@code RTC} as it is required for peer\n         * connection creation by {@code JingleSessionPC}. An existing instance\n         * of {@code RTC} from elsewhere should not be re-used because it is\n         * a stateful grouping of utilities.\n         */\n        this._rtc = new RTC(conferenceStub, {});\n\n        /**\n         * Add the remote track listener here as {@code JingleSessionPC} has\n         * {@code TraceablePeerConnection} which uses {@code RTC}'s event\n         * emitter.\n         */\n        this._rtc.addListener(\n            RTCEvents.REMOTE_TRACK_ADDED,\n            this._onRemoteStream\n        );\n\n        const peerConnection = new JingleSessionPC(\n            undefined, // sid\n            undefined, // localJid\n            this._options.peerJid, // remoteJid\n            connectionStub, // connection\n            {\n                offerToReceiveAudio: this._options.receiveAudio,\n                offerToReceiveVideo: this._options.receiveVideo\n            }, // mediaConstraints\n            pcConfigStub, // pcConfig\n            true, // isP2P\n            this._options.isInitiator // isInitiator\n        );\n\n        const signalingLayer = new CustomSignalingLayer();\n\n        signalingLayer.setChatRoom(roomStub);\n\n        /**\n         * An additional initialize call is necessary to properly set instance\n         * variable for calling.\n         */\n        peerConnection.initialize(roomStub, this._rtc, signalingLayer, configStub);\n\n        return peerConnection;\n    }\n\n    /**\n     * Invoked when a connection related issue has been encountered.\n     *\n     * @param {string} errorType - The constant indicating the type of the error\n     * that occurred.\n     * @param {string} details - Optional additional data about the error.\n     * @private\n     * @returns {void}\n     */\n    _onError(errorType, details = '') {\n        this._options.onError(this._options.peerJid, errorType, details);\n    }\n\n    /**\n     * Callback invoked when the peer connection has received a remote media\n     * stream.\n     *\n     * @param {JitsiRemoteTrack} jitsiRemoteTrack - The remote media stream\n     * wrapped in {@code JitsiRemoteTrack}.\n     * @private\n     * @returns {void}\n     */\n    _onRemoteStream(jitsiRemoteTrack) {\n        this._tracks.push(jitsiRemoteTrack);\n\n        this._options.onRemoteStream(jitsiRemoteTrack);\n    }\n\n    /**\n     * Callback invoked when {@code JingleSessionPC} needs to signal a message\n     * out to the remote peer.\n     *\n     * @param {XML} iq - The message to signal out.\n     * @param {Function} callback - Callback when the IQ was acknowledged.\n     * @private\n     * @returns {void}\n     */\n    _onSendMessage(iq, callback) {\n        this._options.onSendMessage(this._options.peerJid, iq);\n\n        if (callback) {\n            // Fake some time to receive the acknowledge.\n            setTimeout(callback, 250);\n        }\n    }\n\n    /**\n     * Callback invoked in response to an agreement to start a proxy connection.\n     * The passed in jingle element should contain an SDP answer to a previously\n     * sent SDP offer.\n     *\n     * @param {Element} jingleElement - The jingle element.\n     * @private\n     * @returns {void}\n     */\n    _onSessionAccept(jingleElement) {\n        if (!this._peerConnection) {\n            logger.error('Received an answer when no peer connection exists.');\n\n            return;\n        }\n\n        this._peerConnection.setAnswer(jingleElement);\n    }\n\n    /**\n     * Callback invoked in response to a request to start a proxy connection.\n     * The passed in jingle element should contain an SDP offer.\n     *\n     * @param {Element} jingleElement - The jingle element.\n     * @private\n     * @returns {void}\n     */\n    _onSessionInitiate(jingleElement) {\n        if (this._peerConnection) {\n            logger.error('Received an offer when an offer was already sent.');\n\n            return;\n        }\n\n        this._peerConnection = this._createPeerConnection();\n\n        this._peerConnection.acceptOffer(\n            jingleElement,\n            () => { /** no-op */ },\n            () => this._onError(\n                this._options.peerJid,\n                ACTIONS.CONNECTION_ERROR,\n                'session initiate error'\n            ),\n            []\n        );\n    }\n\n    /**\n     * Callback invoked in response to a request to disconnect an active proxy\n     * connection. Cleans up tracks and the peer connection.\n     *\n     * @private\n     * @returns {void}\n     */\n    _onSessionTerminate() {\n        this._tracks.forEach(track => track.dispose());\n        this._tracks = [];\n\n        if (this._peerConnection) {\n            this._peerConnection.onTerminated();\n        }\n\n        if (this._rtc) {\n            this._rtc.removeListener(\n                RTCEvents.REMOTE_TRACK_ADDED,\n                this._onRemoteStream\n            );\n\n            this._rtc.destroy();\n        }\n    }\n\n    /**\n     * Callback invoked in response to ICE candidates from the remote peer.\n     * The passed in jingle element should contain an ICE candidate.\n     *\n     * @param {Element} jingleElement - The jingle element.\n     * @private\n     * @returns {void}\n     */\n    _onTransportInfo(jingleElement) {\n        this._peerConnection.addIceCandidates(jingleElement);\n    }\n}\n","import { getLogger } from '@jitsi/logger';\nimport { $iq } from 'strophe.js';\n\nimport { findFirst, getAttribute, parseXML } from '../../modules/util/XMLUtils';\nimport { MediaType } from '../../service/RTC/MediaType';\nimport { getSourceNameForJitsiTrack } from '../../service/RTC/SignalingLayer';\nimport { VideoType } from '../../service/RTC/VideoType';\nimport RTC from '../RTC/RTC';\n\nimport ProxyConnectionPC from './ProxyConnectionPC';\nimport { ACTIONS } from './constants';\n\nconst logger = getLogger('proxyconnection:ProxyConnectionService');\n\n/**\n * Instantiates a new ProxyConnectionPC and ensures only one exists at a given\n * time. Currently it assumes ProxyConnectionPC is used only for screensharing\n * and assumes IQs to be used for communication.\n */\nexport default class ProxyConnectionService {\n    /**\n     * Initializes a new {@code ProxyConnectionService} instance.\n     *\n     * @param {Object} options - Values to initialize the instance with.\n     * @param {boolean} [options.convertVideoToDesktop] - Whether or not proxied video should be returned as a desktop\n     * stream. Defaults to false.\n     * @param {Object} [options.pcConfig] - The {@code RTCConfiguration} to use for the WebRTC peer connection.\n     * @param {JitsiConnection} [options.jitsiConnection] - The {@code JitsiConnection} which will be used to fetch\n     * TURN credentials for the P2P connection.\n     * @param {Function} options.onRemoteStream - Callback to invoke when a remote video stream has been received and\n     * converted to a {@code JitsiLocakTrack}. The {@code JitsiLocakTrack} will be passed in.\n     * @param {Function} options.onSendMessage - Callback to invoke when a message has to be sent (signaled) out. The\n     * arguments passed in are the jid to send the message to and the message.\n     */\n    constructor(options = {}) {\n        const {\n            jitsiConnection,\n            ...otherOptions\n        } = options;\n\n        /**\n         * Holds a reference to the collection of all callbacks.\n         *\n         * @type {Object}\n         */\n        this._options = {\n            pcConfig: jitsiConnection && jitsiConnection.xmpp.connection.jingle.p2pIceConfig,\n            ...otherOptions\n        };\n\n        /**\n         * The active instance of {@code ProxyConnectionService}.\n         *\n         * @type {ProxyConnectionPC|null}\n         */\n        this._peerConnection = null;\n\n        // Bind event handlers so they are only bound once for every instance.\n        this._onFatalError = this._onFatalError.bind(this);\n        this._onSendMessage = this._onSendMessage.bind(this);\n        this._onRemoteStream = this._onRemoteStream.bind(this);\n    }\n\n    /**\n     * Parses a message object regarding a proxy connection to create a new\n     * proxy connection or update and existing connection.\n     *\n     * @param {Object} message - A message object regarding establishing or\n     * updating a proxy connection.\n     * @param {Object} message.data - An object containing additional message\n     * details.\n     * @param {string} message.data.iq - The stringified iq which explains how\n     * and what to update regarding the proxy connection.\n     * @param {string} message.from - The message sender's full jid. Used for\n     * sending replies.\n     * @returns {void}\n     */\n    processMessage(message) {\n        const peerJid = message.from;\n\n        if (!peerJid) {\n            return;\n        }\n\n        // If a proxy connection has already been established and messages come\n        // from another peer jid then those messages should be replied to with\n        // a rejection.\n        if (this._peerConnection\n            && this._peerConnection.getPeerJid() !== peerJid) {\n            this._onFatalError(\n                peerJid,\n                ACTIONS.CONNECTION_ERROR,\n                'rejected'\n            );\n\n            return;\n        }\n\n        const iq = this._convertStringToXML(message.data.iq);\n        const jingleElement = findFirst(iq, 'jingle');\n        const action = getAttribute(jingleElement, 'action');\n\n        if (action === ACTIONS.INITIATE) {\n            this._peerConnection = this._createPeerConnection(peerJid, {\n                isInitiator: false,\n                receiveVideo: true\n            });\n        }\n\n        // Truthy check for peer connection added to protect against possibly\n        // receiving actions before an ACTIONS.INITIATE.\n        if (this._peerConnection && jingleElement) {\n            this._peerConnection.processMessage(jingleElement);\n        }\n\n        // Take additional steps to ensure the peer connection is cleaned up\n        // if it is to be closed.\n        if (action === ACTIONS.CONNECTION_ERROR\n            || action === ACTIONS.UNAVAILABLE\n            || action === ACTIONS.TERMINATE) {\n            this._selfCloseConnection();\n        }\n\n\n    }\n\n    /**\n     * Instantiates and initiates a proxy peer connection.\n     *\n     * @param {string} peerJid - The jid of the remote client that should\n     * receive messages.\n     * @param {Array<JitsiLocalTrack>} localTracks - Initial media tracks to\n     * send through to the peer.\n     * @returns {void}\n     */\n    start(peerJid, localTracks = []) {\n        this._peerConnection = this._createPeerConnection(peerJid, {\n            isInitiator: true,\n            receiveVideo: false\n        });\n\n        localTracks.forEach((localTrack, localTrackIndex) => {\n            const localSourceNameTrack = getSourceNameForJitsiTrack('peer', localTrack.getType(), localTrackIndex);\n\n            localTrack.setSourceName(localSourceNameTrack);\n        });\n\n        this._peerConnection.start(localTracks);\n    }\n\n    /**\n     * Terminates any active proxy peer connection.\n     *\n     * @returns {void}\n     */\n    stop() {\n        if (this._peerConnection) {\n            this._peerConnection.stop();\n        }\n\n        this._peerConnection = null;\n    }\n\n    /**\n     * Transforms a stringified xML into a XML element.\n     *\n     * @param {string} xml - The XML in string form.\n     * @private\n     * @returns {Object|null} An element version of the xml. Null will be returned\n     * if an error is encountered during transformation.\n     */\n    _convertStringToXML(xml) {\n        try {\n            const xmlDom = parseXML(xml);\n\n            return xmlDom;\n        } catch (e) {\n            logger.error('Attempted to convert incorrectly formatted xml');\n\n            return null;\n        }\n    }\n\n    /**\n     * Helper for creating an instance of {@code ProxyConnectionPC}.\n     *\n     * @param {string} peerJid - The jid of the remote peer with which the\n     * {@code ProxyConnectionPC} will be established with.\n     * @param {Object} options - Additional defaults to instantiate the\n     * {@code ProxyConnectionPC} with. See the constructor of ProxyConnectionPC\n     * for more details.\n     * @private\n     * @returns {ProxyConnectionPC}\n     */\n    _createPeerConnection(peerJid, options = {}) {\n        if (!peerJid) {\n            throw new Error('Cannot create ProxyConnectionPC without a peer.');\n        }\n\n        const pcOptions = {\n            onError: this._onFatalError,\n            onRemoteStream: this._onRemoteStream,\n            onSendMessage: this._onSendMessage,\n            pcConfig: this._options.pcConfig,\n            peerJid,\n            ...options\n        };\n\n        return new ProxyConnectionPC(pcOptions);\n    }\n\n    /**\n     * Callback invoked when an error occurs that should cause\n     * {@code ProxyConnectionPC} to be closed if the peer is currently\n     * connected. Sends an error message/reply back to the peer.\n     *\n     * @param {string} peerJid - The peer jid with which the connection was\n     * attempted or started, and to which an iq with error details should be\n     * sent.\n     * @param {string} errorType - The constant indicating the type of the error\n     * that occurred.\n     * @param {string} details - Optional additional data about the error.\n     * @private\n     * @returns {void}\n     */\n    _onFatalError(peerJid, errorType, details = '') {\n        logger.error(\n            'Received a proxy connection error', peerJid, errorType, details);\n\n        const iq = $iq({\n            to: peerJid,\n            type: 'set'\n        })\n            .c('jingle', {\n                action: errorType,\n                xmlns: 'urn:xmpp:jingle:1'\n            })\n            .c('details')\n            .t(details)\n            .up();\n\n        this._onSendMessage(peerJid, iq);\n\n        if (this._peerConnection\n            && this._peerConnection.getPeerJid() === peerJid) {\n            this._selfCloseConnection();\n        }\n    }\n\n    /**\n     * Callback invoked when the remote peer of the {@code ProxyConnectionPC}\n     * has offered a media stream. The stream is converted into a\n     * {@code JitsiLocalTrack} for local usage if the {@code onRemoteStream}\n     * callback is defined.\n     *\n     * @param {JitsiRemoteTrack} jitsiRemoteTrack - The {@code JitsiRemoteTrack}\n     * for the peer's media stream.\n     * @private\n     * @returns {void}\n     */\n    _onRemoteStream(jitsiRemoteTrack) {\n        if (!this._options.onRemoteStream) {\n            logger.error('Remote track received without callback.');\n            jitsiRemoteTrack.dispose();\n\n            return;\n        }\n\n        const isVideo = jitsiRemoteTrack.isVideoTrack();\n        let videoType;\n\n        if (isVideo) {\n            videoType = this._options.convertVideoToDesktop\n                ? VideoType.DESKTOP : VideoType.CAMERA;\n        }\n\n        // Grab the webrtc media stream and pipe it through the same processing\n        // that would occur for a locally obtained media stream.\n        const mediaStream = jitsiRemoteTrack.getOriginalStream();\n        const jitsiLocalTracks = RTC.createLocalTracks(\n            [\n                {\n                    deviceId:\n                        `proxy:${this._peerConnection.getPeerJid()}`,\n                    mediaType: isVideo ? MediaType.VIDEO : MediaType.AUDIO,\n                    sourceType: 'proxy',\n                    stream: mediaStream,\n                    track: mediaStream.getVideoTracks()[0],\n                    videoType\n                }\n            ]);\n\n        this._options.onRemoteStream(jitsiLocalTracks[0]);\n    }\n\n    /**\n     * Formats and forwards a message an iq to be sent to a peer jid.\n     *\n     * @param {string} peerJid - The jid the iq should be sent to.\n     * @param {Object} iq - The iq which would be sent to the peer jid.\n     * @private\n     * @returns {void}\n     */\n    _onSendMessage(peerJid, iq) {\n        if (!this._options.onSendMessage) {\n            return;\n        }\n\n        try {\n            const stringifiedIq\n                = new XMLSerializer().serializeToString(iq.nodeTree || iq);\n\n            this._options.onSendMessage(peerJid, { iq: stringifiedIq });\n        } catch (e) {\n            logger.error('Attempted to send an incorrectly formatted iq.');\n        }\n    }\n\n    /**\n     * Invoked when preemptively closing the {@code ProxyConnectionPC}.\n     *\n     * @private\n     * @returns {void}\n     */\n    _selfCloseConnection() {\n        this.stop();\n\n        this._options.onConnectionClosed\n            && this._options.onConnectionClosed();\n    }\n}\n","/** Class for providing information about an ICE candidate */\nclass ParsedIceCandidate {\n  /** Create a new object\n   * @param {Object} iceCandidate the ice candidate */\n  constructor(iceCandidate) {\n    this.iceCandidateStr = iceCandidate.candidate;\n\n    this.parse();\n  }\n\n  /** Parse the ICE candidate\n   * @private\n   */\n  parse() {\n    let parsed = this.iceCandidateStr.split(' ');\n    if (parsed.length < 8) {\n      return;\n    }\n\n    /* Candidate string examples with indices:\n               0            1  2    3           4           5\n       \"candidate:911959162 1 udp 2113937151 192.168.1.175 49977\n        6   7     8        9   10   11    12         13\n       typ host generation 0 ufrag WBVw network-cost 50\"\n\n               0             1  2    3           4          5\n       \"candidate:3941065291 1 udp 33562367   172.18.0.2   30704\n        6   7     8        9   10   11    12      13  14    15   16         17\n       typ relay raddr 0.0.0.0 rport 0 generation 0 ufrag 2R2F network-cost 50\"\n    */\n\n    this.protocol = (parsed[1] === '1' ? 'rtp' : 'rtcp');\n    this.transport = parsed[2];\n    this.typeTransport = this.extractTypeTransport(parsed[3]);\n\n    this.ipv6 = parsed[4].indexOf(':') !== -1;\n    this.ipAddress = parsed[4];\n    this.port = parsed[5];\n\n    this.type = parsed[7];\n  }\n\n  /** get the type of transport from the preference\n   * @param {String} preference the preference from the ICE candidate\n   * @return {String} UDP, TCP, or TLS\n   * @private\n   */\n  extractTypeTransport(preference) {\n    let ret = 'None';\n\n    let tmp = (preference >> 24);\n    if (this.protocol === 'rtp' && tmp >= 0 && tmp <= 2) {\n      switch (tmp) {\n        case 0:\n          ret = 'TLS';\n          break;\n        case 1:\n          ret = 'TCP';\n          break;\n        case 2:\n          ret = 'UDP';\n          break;\n      }\n    }\n\n    return ret;\n  };\n\n  /** the candidate as string\n   * @return {String} the candidate\n   * @public\n   */\n  getString() {\n    return this.iceCandidateStr;\n  }\n\n  /* --------- Type --------- */\n\n  /** Type\n   * @return {String} type\n   * @public\n   */\n  getType() {\n    return this.type;\n  }\n\n  /** host candidate or not\n   * @return {Boolean} host or not\n   * @public\n   */\n  isHost() {\n    return this.type.toLowerCase() === 'host';\n  }\n\n  /** server reflexive candidate or not\n   * @return {Boolean} reflexive or not\n   * @public\n   */\n  isServerReflexive() {\n    return this.type.toLowerCase() === 'srflx';\n  }\n\n  /** peer reflexive candidate or not\n   * @return {Boolean} reflexive or not\n   * @public\n   */\n  isPeerReflexive() {\n    return this.type.toLowerCase() === 'prflx';\n  }\n\n  /** relay candidate or not\n   * @return {Boolean} relay or not\n   * @public\n   */\n  isRelay() {\n    return this.type.toLowerCase() === 'relay' || this.type.toLowerCase() === 'relayed';\n  }\n\n  /** public candidate or not\n   * @return {Boolean} relay or not\n   * @public\n   */\n  isPublicIp() {\n    return this.type.toLowerCase() === 'srflx' || this.type.toLowerCase() === 'prflx';\n  }\n\n  /* --------- Type transport --------- */\n\n  /** type transport\n   * @return {String} type transport (UDP, TCP, or TLS)\n   * @public\n   */\n  getTypeTransport() {\n    return this.typeTransport;\n  }\n\n  /** Type transport UDP\n   * @return {Boolean} if UDP or not\n   */\n  isTypeTransportUdp() {\n    return this.typeTransport === 'UDP';\n  }\n\n  /** Type transport TCP\n   * @return {Boolean} if TCP or not\n   */\n  isTypeTransportTcp() {\n    return this.typeTransport === 'TCP';\n  }\n\n  /** Type transport TLS\n   * @return {Boolean} if TLS or not\n   */\n  isTypeTransportTls() {\n    return this.typeTransport === 'TLS';\n  }\n\n  /* --------- Transport --------- */\n\n  /** Transport used\n   * @return {String} transport (udp or tcp)\n   * @public\n   */\n  getTransport() {\n    return this.transport;\n  }\n\n  /** UDP\n   * @return {Boolean} UDP or not\n   * @public\n   */\n  isUdp() {\n    return this.transport.toLowerCase() === 'udp';\n  }\n\n  /** TCP\n   * @return {Boolean} TCP or not\n   * @public\n   */\n  isTcp() {\n    return this.transport.toLowerCase() === 'tcp';\n  }\n\n\n  /* --------- Protocol --------- */\n\n  /** Protocol used\n   * @return {String} protocol (rtp or rtcp)\n   * @public\n   */\n  getProtocol() {\n    return this.protocol;\n  }\n\n  /** RTP\n   * @return {Boolean} RTP or not\n   * @public\n   */\n  isRtp() {\n    return this.protocol === 'rtp';\n  }\n\n  /** RTCP\n   * @return {Boolean} RTCP or not\n   * @public\n   */\n  isRtcp() {\n    return this.protocol === 'rtcp';\n  }\n\n\n  /* --------- IP/port --------- */\n\n  /** IPv6 or not\n   * @return {Boolean} ipv6 or not\n   */\n  isIpv6() {\n    return this.ipv6;\n  }\n\n  /** IP address\n   * @return {String} IP address\n   * @public\n   */\n  getIpAddress() {\n    return this.ipAddress;\n  }\n\n  /** port\n   * @return {String} port\n   * @public\n   */\n  getPort() {\n    return this.port;\n  }\n}\n\nexport {ParsedIceCandidate};\n","export const Constants = {\n  codeBaseType: {\n    chrome: 'Chrome',\n    firefox: 'Firefox',\n    edge: 'Edge',\n    plugin: 'Plugin',\n  },\n\n  browserName: {\n    chrome: 'Chrome',\n    firefox: 'Firefox',\n    edge: 'Edge',\n    msie: 'Microsoft Internet Explorer',\n    safari: 'Safari',\n  },\n\n  osName: {\n    windows: 'Windows',\n    mac: 'Mac OS X',\n    android: 'Android',\n    ios: 'iOS',\n  },\n};\n\n/**\n * detect - Detect the browser related inforamtion\n * @public\n * @return {Object} Browser and OS information\n */\nexport function detect() {\n  let browserName = Constants.browserName.chrome;\n  let osName = null;\n  let osVersion = null;\n  let userAgent = null;\n  let agentVersion = null;\n\n  let codeBaseType = Constants.codeBaseType.chrome;\n\n  if (window && (!window.navigator || !window.navigator.userAgent || window.csioReactNative)) {\n    if (window && window.csioGetOsName) {\n      osName = window.csioGetOsName();\n    }\n\n    if (window && window.csioGetOsVer) {\n      osVersion = window.csioGetOsVer();\n    }\n\n    if (window && window.csioReactNative) {\n      userAgent = 'react-native';\n    }\n\n    return {\n      browserName: browserName,\n      codeBase: codeBaseType,\n      os: osName,\n      osVersion: osVersion,\n      userAgent: userAgent,\n    };\n  }\n\n  userAgent = navigator.userAgent;\n  let nAgt = userAgent.toLowerCase();\n\n  agentVersion = navigator.appVersion;\n  let nVer;\n  let fullVersion;\n  if (agentVersion) {\n    nVer = agentVersion.toLowerCase();\n    fullVersion = '' + parseFloat(nVer);\n  }\n  let verOffset;\n  let version = 'version';\n\n\n  // In Opera, the true version is after \"Opera\" or after \"Version\"\n  if ((verOffset = nAgt.indexOf('opera')) !== -1) {\n    browserName = Constants.browserName.opera;\n    fullVersion = nAgt.substring(verOffset + 6);\n    if ((verOffset = nAgt.indexOf(version)) !== -1) {\n      fullVersion = nAgt.substring(verOffset + 8);\n    }\n    codeBaseType = Constants.codeBaseType.chrome;\n  } else if ((verOffset = nAgt.indexOf('opr')) !== -1) {\n    browserName = Constants.browserName.opera;\n    fullVersion = nAgt.substring(verOffset + 4);\n    if ((verOffset = nAgt.indexOf(version)) !== -1) {\n      fullVersion = nAgt.substring(verOffset + 8);\n    }\n    codeBaseType = Constants.codeBaseType.chrome;\n  } else if ((verOffset = nAgt.indexOf('msie')) !== -1) { // In MSIE, the true version is after \"MSIE\" in userAgent\n    browserName = Constants.browserName.msie;\n    fullVersion = nAgt.substring(verOffset + 5);\n    codeBaseType = Constants.codeBaseType.chrome;\n  } else if ((verOffset = nAgt.indexOf('edge')) !== -1) {\n    browserName = Constants.browserName.edge;\n    fullVersion = nAgt.substring(verOffset + 5);\n    codeBaseType = Constants.codeBaseType.edge;\n  } else if ((verOffset = nAgt.indexOf('edg')) !== -1) {\n    browserName = Constants.browserName.edge;\n    fullVersion = nAgt.substring(verOffset + 4);\n    codeBaseType = Constants.codeBaseType.chrome;\n  } else if ((verOffset = nAgt.indexOf('chrome')) !== -1) { // In Chrome, the true version is after \"Chrome\"\n    browserName = Constants.browserName.chrome;\n    fullVersion = nAgt.substring(verOffset + 7);\n    codeBaseType = Constants.codeBaseType.chrome;\n  } else if ((verOffset = nAgt.indexOf('safari')) !== -1) { // In Safari, the true version is after \"Safari\" or after \"Version\"\n    browserName = Constants.browserName.safari;\n    fullVersion = nAgt.substring(verOffset + 7);\n    if ((verOffset = nAgt.indexOf(version)) !== -1) {\n      fullVersion = nAgt.substring(verOffset + 8);\n      if (fullVersion) {\n        let version = fullVersion.split(' ');\n        if (version && version.length > 0) {\n          fullVersion = version[0];\n        }\n      }\n    }\n    codeBaseType = Constants.codeBaseType.chrome;\n  } else if ((verOffset = nAgt.indexOf('firefox')) !== -1) { // In Firefox, the true version is after \"Firefox\"\n    browserName = Constants.browserName.firefox;\n    fullVersion = nAgt.substring(verOffset + 8);\n    codeBaseType = Constants.codeBaseType.firefox;\n  } else if ((verOffset = nAgt.indexOf('trident')) !== -1) { // IE 11 has no MSIE\n    browserName = Constants.browserName.msie;\n    verOffset = nAgt.indexOf('rv'); // In IE11, the true version is after \"rv\"\n    fullVersion = nAgt.substring(verOffset + 3, verOffset + 7);\n    codeBaseType = Constants.codeBaseType.chrome;\n  }\n\n  // system\n  // source: http://jsfiddle.net/ChristianL/AVyND/\n  let clientStrings = [\n    {s: 'Windows 3.11', r: /win16/},\n    {s: 'Windows 95', r: /(windows 95|win95|windows_95)/},\n    {s: 'Windows ME', r: /(win 9x 4.90|windows me)/},\n    {s: 'Windows 98', r: /(windows 98|win98)/},\n    {s: 'Windows CE', r: /windows ce/},\n    {s: 'Windows 2000', r: /(windows nt 5.0|windows 2000)/},\n    {s: 'Windows XP', r: /(windows nt 5.1|windows xp)/},\n    {s: 'Windows Server 2003', r: /windows nt 5.2/},\n    {s: 'Windows Vista', r: /windows nt 6.0/},\n    {s: 'Windows 7', r: /(windows 7|windows nt 6.1)/},\n    {s: 'Windows 8.1', r: /(windows 8.1|windows nt 6.3)/},\n    {s: 'Windows 8', r: /(windows 8|windows nt 6.2)/},\n    {s: 'Windows 10', r: /(windows 10|windows nt 10.0)/},\n    {s: 'Windows NT 4.0', r: /(windows nt 4.0|winnt4.0|winnt|windows nt)/},\n    {s: 'Windows ME', r: /windows me/},\n    {s: 'Android', r: /android/},\n    {s: 'Open BSD', r: /openbsd/},\n    {s: 'Sun OS', r: /sunos/},\n    {s: 'Linux', r: /(linux|x11)/},\n    {s: 'iOS', r: /(iphone|ipad|ipod)/},\n    {s: 'Mac OS X', r: /mac os x/},\n    {s: 'Mac OS', r: /(macppc|macintel|mac_powerpc|macintosh)/},\n    {s: 'QNX', r: /qnx/},\n    {s: 'UNIX', r: /unix/},\n    {s: 'BeOS', r: /beos/},\n    {s: 'OS/2', r: /os\\/2/},\n    {s: 'Search Bot', r: /(nuhk|googlebot|yammybot|openbot|slurp|msnbot|ask jeeves\\/teoma|ia_archiver)/},\n  ];\n\n  let id;\n  let cs;\n  for (id in clientStrings) {\n    if (!clientStrings.hasOwnProperty(id)) {\n      continue;\n    }\n    cs = clientStrings[id];\n    if (cs.r.test(nAgt)) {\n      osName = cs.s;\n      break;\n    }\n  }\n\n\n  if (osName && (/Windows/.test(osName))) {\n    osVersion = /Windows (.*)/.exec(osName)[1];\n    osName = Constants.osName.windows;\n  }\n\n  switch (osName) {\n    case Constants.osName.mac:\n      osVersion = /mac os x (1[\\.\\_\\d]+)/.exec(nAgt);\n      if (!osVersion) {\n        break;\n      }\n      osVersion = osVersion[1];\n      break;\n    case Constants.osName.android:\n      osVersion = /android ([\\.\\_\\d]+)/.exec(nAgt);\n      if (!osVersion) {\n        break;\n      }\n      osVersion = osVersion[1];\n      break;\n    case Constants.osName.ios:\n      if (!nVer) {\n        break;\n      }\n      osVersion = /os (\\d+)_(\\d+)_?(\\d+)?/.exec(nVer);\n      if (!osVersion) {\n        break;\n      }\n      osVersion = osVersion[1] + '.' + osVersion[2] + '.' + (osVersion[3] | 0);\n      break;\n  }\n\n  const splitWords = fullVersion.split(' ');\n  let browserVersion = fullVersion;\n  if (splitWords && splitWords.length > 0) {\n    browserVersion = splitWords[0];\n  }\n\n  return {\n    browserName: browserName,\n    browserVersion: browserVersion,\n    os: osName,\n    osVersion: osVersion,\n    codeBase: codeBaseType,\n    userAgent: userAgent,\n  };\n};\n","import {Constants} from './detectbrowser';\n\n\n/** Represents a adapter for the result of getStats*/\nclass StatsAdapter {\n  /**\n  * Create a StatsAdapter Component for parsing WebRTC getStats\n  * @param {Object} codeBase The codebase for the stats\n  * @param {Object} browser The browser for the stats\n  * @constructor\n  */\n  constructor(codeBase, browser) {\n    this.codeBase = codeBase;\n    this.browser = browser;\n  }\n\n  /**\n   * getIceCandidates - Obtains ice candidates from stats\n   *\n   * @param {Object} rawData - Raw data by browser on getstats call/promise.\n   *\n   * @return {Object} Ice candidate information\n   */\n  getIceCandidates(rawData) {\n    if (!rawData) {\n      return {localCandidates: [], remoteCandidates: [],\n        iceCandidatePairs: []};\n    }\n    let rawStats = this.extractRawStats(rawData);\n    let result = this.processRawStatsForIceInfo(rawStats);\n    return result;\n  }\n\n  /**\n   * extractRawStats - extracts the objects from raw stats\n   * @private\n   * @param {Object} rawStats raw stats from browser\n   *\n   * @return {Object[]} Array of Objects from raw stats\n   */\n  extractRawStats(rawStats) {\n    let results = [];\n    let key;\n\n    let firefox = Constants.codeBaseType.firefox;\n    let chrome = Constants.codeBaseType.chrome;\n    let safari = Constants.browserName.safari;\n    if (this.codeBase === firefox && this.browser !== safari) {\n      rawStats.forEach(function(item) {\n        results.push(item);\n      });\n    } else if (this.codeBase === chrome && this.browser !== safari) {\n      if (rawStats && rawStats.result) {\n        results = rawStats.result();\n      } else if (rawStats && rawStats.forEach) {\n        results = [];\n        rawStats.forEach(function(item) {\n          results.push(item);\n        });\n      }\n    } else {\n      for (key in rawStats) {\n        if (rawStats.hasOwnProperty(key)) {\n          results.push(rawStats[key]);\n        }\n      }\n    }\n    return results;\n  }\n\n  /**\n   * processRawStatsForIceInfo - process the raw stats to obtain ICE related information\n   *\n   * @param {Object} rawStats extracted raw stats\n   *\n   * @return {Object} Ice information\n   */\n  processRawStatsForIceInfo(rawStats) {\n    let localCandidates = [];\n    let remoteCandidates = [];\n    let candidatePairs = [];\n    let selectedCandidatePairId;\n\n    if (!rawStats) {\n      return {localCandidates: localCandidates, remoteCandidates: remoteCandidates,\n        iceCandidatePairs: candidatePairs};\n    }\n\n    for (let i = 0; i < rawStats.length; ++i) {\n      let parsedStats = this.getParsedStats(rawStats[i]);\n      let classifiedStats = this.statsClassifier(parsedStats);\n      if (classifiedStats.candidatePair) {\n        candidatePairs.push(classifiedStats.candidatePair);\n      } else if (classifiedStats.transportStats) {\n        if (classifiedStats.transportStats.type === 'transport') {\n          selectedCandidatePairId = classifiedStats.transportStats.selectedCandidatePairId;\n          continue;\n        }\n        candidatePairs.push(classifiedStats.transportStats);\n      } else if (classifiedStats.localCandidate) {\n        let cand = classifiedStats.localCandidate;\n        if (cand.candidateType == 'relay' || cand.candidateType == 'relayed') {\n          if (!cand.mozLocalTransport) {\n            // assume Chrome, get it from the priority\n            let relayType = cand.priority >> 24;\n            cand.mozLocalTransport = this.formatRelayType(relayType);\n          }\n          cand.mozLocalTransport = cand.mozLocalTransport.toLowerCase();\n        }\n        localCandidates.push(cand);\n      } else if (classifiedStats.remoteCandidate) {\n        remoteCandidates.push(classifiedStats.remoteCandidate);\n      }\n    }\n\n    if (selectedCandidatePairId) {\n      for (let i=0; i < candidatePairs.length; ++i) {\n        if (candidatePairs[i].id === selectedCandidatePairId) {\n          candidatePairs[i].googActiveConnection = 'true';\n        }\n      }\n    }\n\n    return {localCandidates: localCandidates, remoteCandidates: remoteCandidates,\n      iceCandidatePairs: candidatePairs};\n  }\n\n  /**\n   * getParsedStats - Parse the each raw stats object to dictionary\n   * @private\n   * @param {Object} rawStats raw stats object from browser\n   * @return {Object} parsed stats dictionary\n   */\n  getParsedStats(rawStats) {\n    let stats = {};\n    if (rawStats.timestamp instanceof Date) {\n      stats.timestamp = rawStats.timestamp.getTime().toString();\n    }\n\n    if (rawStats.type) {\n      stats.type = rawStats.type;\n    }\n\n    if (rawStats.names) {\n      let names = rawStats.names();\n      for (let i = 0; i < names.length; ++i) {\n        stats[names[i]] = rawStats.stat(names[i]);\n      }\n    } else {\n      Object.assign(stats, rawStats);\n    }\n\n    // for react-native, values is a array of objects each contains a single -\n    // stat value\n    if (stats.values) {\n      for (let i = 0; i < stats.values.length; i++) {\n        let values = stats.values[i];\n        Object.assign(stats, values);\n      }\n      delete stats.values;\n    }\n    return stats;\n  }\n\n  /**\n   * statsClassifier - classifies the parsed stats dictionary\n   * @private\n   * @param {Object} stats dictionary\n   * @return {Object} stats dictionary after on classification\n   */\n  statsClassifier(stats) {\n    let result = {};\n    let isType = (...expectedTypes) => {\n      for (let i = 0; i < expectedTypes.length; i++) {\n        let expectedType = expectedTypes[i];\n        if (stats.type === expectedType) {\n          return true;\n        }\n      }\n      return false;\n    };\n\n    let typeIsInbound = isType('inbound-rtp', 'inboundrtp');\n    let isRemote = (stats.isRemote === 'true' || stats.isRemote === true);\n    if (typeIsInbound || isType('outbound-rtp', 'outboundrtp')) {\n      result.tracks = {};\n      result.tracks.data = stats;\n      result.tracks.ssrc = stats.ssrc;\n      result.tracks.streamType = typeIsInbound ? 'inbound' : 'outbound';\n      result.tracks.reportType = 'local';\n      if (stats.isRemote !== undefined) {\n        result.tracks.reportType = isRemote ? 'remote' : 'local';\n      }\n    } else if (isType('candidatepair') && stats.selected) {\n      result.transportStats = stats;\n    } else if (isType('localcandidate', 'local-candidate')) {\n      result.localCandidate = stats;\n    } else if (isType('remotecandidate', 'remote-candidate')) {\n      result.remoteCandidate = stats;\n    } else if (isType('transport', 'googCandidatePair')) {\n      result.transportStats = stats;\n    } else if (isType('VideoBwe')) {\n      result.bwe = stats;\n    } else if (isType('track')) {\n      result.trackStats = stats;\n    } else if (isType('candidate-pair')) {\n      result.candidatePair = stats;\n    } else if (isType('codec')) {\n      result.codec = stats;\n    } else if (isType('ssrc')) {\n      result.tracks = {};\n      result.tracks.data = stats;\n      result.tracks.ssrc = stats.ssrc;\n      result.tracks.reportType = 'local';\n      result.tracks.streamType = (stats.bytesSent) ? 'outbound' : 'inbound';\n    }\n    return result;\n  }\n\n   /**\n    * formatRelayType - returns the formated realayType\n    *\n    * @param {Number} relayType\n    *\n    * @return {String} formated relayType string\n    */\n   formatRelayType(relayType) {\n    let ret = 'none';\n    switch (relayType) {\n      case 0:\n        ret = 'tls';\n        break;\n      case 1:\n        ret = 'tcp';\n        break;\n      case 2:\n        ret = 'udp';\n        break;\n    }\n    return ret;\n  }\n}\n\nexport {StatsAdapter};\n","import {Constants} from './detectbrowser';\nimport {StatsAdapter} from './statsadapter';\n\n/** Class that handles getStats */\nclass GetStatsHandler {\n  /**\n   * Creates an instance of GetStatsHandler.\n   * @param {Object} browserInfo\n   * @constructor\n   */\n  constructor(browserInfo) {\n    this.codeBase = browserInfo.codeBase;\n    this.browserName = browserInfo.browserName;\n\n    this.adapter = new StatsAdapter(this.codeBase, this.browserName);\n\n    this.isPromiseBased = true;\n  }\n\n  /**\n   * getIceCandidates - gets ice candiates information from getstats\n   * @param {Object} pc\n   * @public\n   * @return {Promise} promise resolves when the ice candiates are obtained from getstats\n   */\n  getIceCandidates(pc) {\n    let self = this;\n    return new Promise( function(resolve, reject) {\n      self.csioGetStats(self.iceCandidatesHandler.bind(self), pc, (candidatesObj) => {\n        resolve(candidatesObj);\n      });\n    });\n  }\n\n\n  /**\n   * iceCandidatesHandler - getstats callback handler for getting ice candidate information\n   * @param {Object} stats\n   * @param {Function} callback\n   * @private\n   */\n  iceCandidatesHandler(stats, callback) {\n    let candidatesObj = this.adapter.getIceCandidates(stats);\n    callback(candidatesObj);\n  }\n\n  /**\n   * Calls the broswer getStats promise or function\n   * @private\n   * @param {Function} statsHandler\n   * @param {Object} pc\n   * @param {Function} callback\n   *\n   */\n  csioGetStats(statsHandler, pc, callback) {\n    let firefox = Constants.codeBaseType.firefox;\n    let chrome = Constants.codeBaseType.chrome;\n    let edge = Constants.codeBaseType.edge;\n    let safari = Constants.browserName.safari;\n\n    if (!pc) {\n      return;\n    }\n\n    if (this.codeBase === firefox) {\n      this.getStatsFirefox(statsHandler, pc, callback);\n    } else if (this.browserName === safari) {\n      this.getStatsSafari(statsHandler, pc, callback);\n    } else if (this.codeBase === chrome) {\n      this.getStatsChrome(statsHandler, pc, callback);\n    } else if (this.codeBase === edge) {\n      this.getStatsEdge(statsHandler, pc, callback);\n    }\n  }\n\n  /**\n   * Calls the broswer getStats promise or function for firefox\n   * @private\n   * @memberof GetStatsHandler\n   * @param {Function} statsHandler\n   * @param {Object} pc\n   * @param {Function} callback\n   */\n  getStatsFirefox(statsHandler, pc, callback) {\n    let self = this;\n\n    if (!self.isPromiseBased) {\n      pc.getStats(null, (stats) => {\n        statsHandler(stats, callback);\n      }, () => {});\n      return;\n    }\n\n    try {\n      pc.getStats()\n      .then((stats) => {\n        statsHandler(stats, callback);\n      })\n      .catch(function(e) {\n        self.isPromiseBased = false;\n        pc.getStats(null, (stats)=>{\n          statsHandler(stats, callback);\n        }, () => {});\n      });\n    } catch (e) {\n      self.isPromiseBased = false;\n      pc.getStats(null, (stats) => {\n        statsHandler(stats, callback);\n      }, () => {});\n    }\n  }\n\n  /**\n   * Calls the broswer getStats promise or function for chrome\n   * @private\n   * @memberof GetStatsHandler\n   * @param {Function} statsHandler\n   * @param {Object} pc\n   * @param {Function} callback\n   */\n  getStatsChrome(statsHandler, pc, callback) {\n    let self = this;\n\n    if (window && window.csioReactNative) {\n      pc.getStats(null, (stats) => {\n        statsHandler(stats, callback);\n      },\n      function logError(e) {\n      });\n      return;\n    }\n\n    if (!self.isPromiseBased) {\n      pc.getStats((stats) => {\n        statsHandler(stats, callback);\n      });\n      return;\n    }\n\n    try {\n      pc.getStats()\n      .then((stats) => {\n        statsHandler(stats, callback);\n      })\n      .catch(function(e) {\n         // console.error('Error ', e);\n        self.isPromiseBased = false;\n        pc.getStats((stats) => {\n          statsHandler(stats, callback);\n        });\n      });\n    } catch (e) {\n      // todo @karthik can you please check whether it will be self.isPromiseBased or not ?\n      self.isPromiseBased = false;\n      pc.getStats((stats) => {\n        statsHandler(stats, callback);\n      });\n    }\n  }\n\n  /**\n   * Calls the broswer getStats for edge\n   * @private\n   * @memberof GetStatsHandler\n   * @param {Function} statsHandler\n   * @param {Object} pc\n   * @param {Function} callback\n   */\n  getStatsEdge(statsHandler, pc, callback) {\n    pc.getStats()\n    .then((stats) => {\n      statsHandler(stats, callback);\n    })\n    .catch(function(e) {\n    });\n  }\n\n  /**\n   * Calls the broswer getStats for safari\n   * @private\n   * @memberof GetStatsHandler\n   * @param {Function} statsHandler\n   * @param {Object} pc\n   * @param {Function} callback\n   */\n  getStatsSafari(statsHandler, pc, callback) {\n    pc.getStats()\n    .then((stats) => {\n       statsHandler(stats, callback);\n    })\n    .catch(function(e) {\n    });\n  }\n}\n\nexport {GetStatsHandler};\n","import {ParsedIceCandidate} from './utility/parsedIceCandidate';\nimport {GetStatsHandler} from './utility/stats/getstatshandler';\nimport {Constants} from './utility/stats/detectbrowser';\n\nconst ICE_CHECKING_TIMEOUT = 10000;\nconst CONNECTION_TIMEOUT = 30000;\n\nclass TurnConnection {\n  /**\n   * Create a new instance\n   * @param {Object} browserInfo\n   */\n  constructor(browserInfo) {\n    this.reset();\n\n    this.statshandler = new GetStatsHandler(browserInfo);\n  }\n\n  /**\n   * Reset the module\n   */\n  reset() {\n    this.disconnect();\n\n    this.iceServers = null;\n\n    this.pctpc1 = null;\n    this.pctpc2 = null;\n\n    this.sendChannel = null;\n\n    this.messageCallback = null;\n    this.errorCallback = null;\n\n    this.parsedIceResults = {};\n\n    this.resolveCb = null;\n    this.rejectCb = null;\n    this.localIpAddressInfo = [];\n    this.localIpAddresses = [];\n    this.localIp = null;\n    this.localIpType = null;\n    this.numberOfLocalIp = 0;\n  }\n\n  setMessageCallback(func) {\n    this.messageCallback = func;\n  }\n\n  setErrorCallback(func) {\n    this.errorCallback = func;\n  }\n\n  send(data) {\n    if (this.sendChannel && this.sendChannel.readyState === 'open') {\n      try {\n        this.sendChannel.send(data);\n      } catch (error) {\n        this.raiseSendError(new Error('Send channel Error'));\n      }\n    } else {\n      this.raiseSendError(new Error('No send channel'));\n    }\n  }\n\n  raiseSendError(error) {\n    if (this.errorCallback) {\n      this.errorCallback(error);\n    }\n    // console.error('sendChannel error:', error);\n  }\n\n  assignEvent(obj, ev, func) {\n    if (obj.addEventListener) {\n      obj.addEventListener(ev, func.bind(this), false);\n    } else if (obj.attachEvent) {\n      ev = 'on' + ev;\n      obj.attachEvent(ev, func.bind(this));\n    }\n  }\n\n  /**\n   * Start the TURN connection\n   * @param {JSON} iceServers\n   * @return {Promise} resolves when the datachannel is open\n   */\n  connect(iceServers) {\n    this.reset();\n\n    let promise = new Promise((resolve, reject) => {\n      this.resolveCb = resolve;\n      this.rejectCb = reject;\n    });\n\n    this.iceServers = iceServers;\n\n    let CSRTCPeerConnection = null;\n    try {\n      if (RTCPeerConnection) {\n        CSRTCPeerConnection = RTCPeerConnection;\n      } else if (webkitRTCPeerConnection) {\n        CSRTCPeerConnection = webkitRTCPeerConnection;\n      } else if (mozRTCPeerConnection) {\n        CSRTCPeerConnection = mozRTCPeerConnection;\n      } else if (window && window.RTCPeerConnection) {\n        CSRTCPeerConnection = window.RTCPeerConnection;\n      }\n\n      if (!CSRTCPeerConnection) {\n        let err = new Error('RTCPeerConnection not found');\n        err.continueFlag = false,\n        this.rejectCb(err);\n        return promise;\n      }\n    } catch (err) {\n        err.continueFlag = false,\n        this.rejectCb(err);\n        return promise;\n    }\n\n    // Settings\n    let datachannelLabel = 'precalltest';\n    let datachannelSettings = {\n      ordered: false,\n      maxRetransmits: 0,\n    };\n    let servers = {\n      'iceTransportPolicy': 'all',\n      'iceServers': this.iceServers,\n    };\n    // console.log('ICE servers:', servers);\n\n    // PeerConnection objects\n    try {\n      this.pctpc1 = new CSRTCPeerConnection(servers);\n      this.pctpc2 = new CSRTCPeerConnection(servers);\n    } catch (err) {\n      // console.error('Error creating PCs:', err);\n      this.rejectDisconnect(false, new Error('Error creating PCs'));\n      return promise;\n    }\n\n    // console.log('created pcs:', this.pctpc1, this.pctpc2);\n\n    // make sure the connection gets closed at some point\n    this.connectionTimer = setTimeout(() => {\n      // console.error('Connection timeout');\n      delete this.connectionTimer;\n      this.rejectDisconnect(false, new Error('Connection timeout'));\n    }, CONNECTION_TIMEOUT);\n\n    try {\n      // Datachannel as only source\n      this.sendChannel = this.pctpc1.createDataChannel(datachannelLabel, datachannelSettings);\n       // console.log('created datachannel');\n      this.sendChannel.binaryType = 'arraybuffer';\n      this.assignEvent(this.sendChannel, 'error', (error) => {\n        // console.error('Datachannel error:', error);\n        this.raiseSendError(new Error('Datachannel error'));\n        this.rejectDisconnect(true, new Error('Datachannel error'));\n      });\n       // console.log('add onerror event');\n      this.assignEvent(this.pctpc2, 'datachannel', (event) => {\n        let channel = event.channel;\n        this.assignEvent(channel, 'open', (event) => {\n          if (this.resolveCb) {\n            this.resolveCb();\n            this.resolveCb = null;\n          }\n        });\n        this.assignEvent(channel, 'close', (event) => {\n          if (this && this.disconnect) {\n            // console.log('datachannel close');\n            this.disconnect();\n          }\n        });\n        this.assignEvent(channel, 'message', (event) => {\n          if (this.messageCallback) {\n            this.messageCallback(event.data);\n          }\n        });\n        this.assignEvent(channel, 'error', (error) => {\n          if (this.errorCallback) {\n            this.errorCallback(error);\n          }\n          // console.error('receiveChannel error:', error);\n          this.rejectDisconnect(true, new Error('receiveChannel error'));\n        });\n      });\n    } catch (err) {\n      // console.error('Error adding datachannel:', err);\n      this.rejectDisconnect(false, new Error('Error adding datachannel'));\n      return promise;\n    }\n\n    try {\n      // Set callbacks for connection procedure\n      this.assignEvent(this.pctpc1, 'icecandidate', (e) => {\n        this.onIceCandidate(this.pctpc1, e);\n      });\n      this.assignEvent(this.pctpc1, 'iceconnectionstatechange', (e) => {\n        this.onIceStateChange(this.pctpc1, e);\n      });\n\n      this.assignEvent(this.pctpc2, 'icecandidate', (e) => {\n        this.onIceCandidate(this.pctpc2, e);\n      });\n      this.assignEvent(this.pctpc2, 'iceconnectionstatechange', (e) => {\n        this.onIceStateChange(this.pctpc2, e);\n      });\n\n      // Start connection procedure\n      // console.log('pctpc1 createOffer start');\n      this.pctpc1.createOffer()\n      .then(\n        (desc, test) => {\n          this.onCreateOfferSuccess(desc);\n        },\n        (e) => {\n          this.onCreateOfferError(this.pctpc1, e);\n        }\n      );\n    } catch (err) {\n      // console.error('Error starting connection:', err);\n      this.rejectDisconnect(false, new Error('Error starting connection'));\n      return promise;\n    }\n\n    return promise;\n  }\n\n  /**\n   * Reject and disconnect\n   * @param {Boolean} continueFlag indicate if it should be tried again\n   * @param {Error} err the occured error\n   */\n  rejectDisconnect(continueFlag, err) {\n    this.disconnect();\n    if (this.rejectCb) {\n      // console.log('rejectDisconnect');\n      err.continueFlag = continueFlag;\n      this.rejectCb(err);\n    }\n\n    this.resolveCb = null;\n    this.rejectCb = null;\n  }\n\n  /**\n   * Stop the precall tests\n   */\n  disconnect() {\n    // console.log('disconnect');\n    clearTimeout(this.connectionTimer);\n    clearTimeout(this.iceTimer);\n    if (this.sendChannel) {\n      try {\n        this.sendChannel.close();\n      } catch (err) {\n        // console.error(err);\n      }\n    }\n\n    if (this.pctpc1) {\n      try {\n        this.pctpc1.close();\n      } catch (err) {\n        // console.error(err);\n      }\n    }\n    this.pctpc1 = null;\n\n    if (this.pctpc2) {\n      try {\n        this.pctpc2.close();\n      } catch (err) {\n        // console.error(err);\n      }\n    }\n    this.pctpc2 = null;\n  }\n\n  /*\n   * PRIVATE: Methods for connection procedure\n   */\n  getName(pc) {\n    return (pc === this.pctpc1) ? 'pctpc1' : 'pctpc2';\n  }\n\n  getOtherPc(pc) {\n    return (pc === this.pctpc1) ? this.pctpc2 : this.pctpc1;\n  }\n\n  onCreateOfferError(pc, error) {\n    // console.error('Failed to create offer: ' + error.toString());\n    this.rejectDisconnect(false, new Error('Failed to create offer'));\n  }\n\n  onCreateAnswerError(pc, error) {\n    // console.error('Failed to create answer: ' + error.toString());\n    this.rejectDisconnect(false, new Error('Failed to create answer'));\n  }\n\n  onCreateOfferSuccess(desc) {\n    try {\n      // console.log('Offer from pctpc1, pctpc1 setLocalDescription start', this.pctpc1);\n      this.pctpc1.setLocalDescription(desc).then(\n        () => {\n          this.onSetLocalSuccess(this.pctpc1);\n        },\n        (e) => {\n          this.onSetSessionDescriptionError(this.pctpc1, e);\n        }\n      );\n       // console.log('pctpc2 setRemoteDescription start');\n      this.pctpc2.setRemoteDescription(desc).then(\n        () => {\n          this.onSetRemoteSuccess(this.pctpc2);\n        },\n        (e) => {\n          this.onSetRemoteSessionDescriptionError(this.pctpc2, e);\n        }\n      );\n      // console.log('pctpc2 createAnswer start');\n      // Since the 'remote' side has no media stream we need\n      // to pass in the right constraints in order for it to\n      // accept the incoming offer of audio and video.\n      this.pctpc2.createAnswer().then(\n        (desc) => {\n          this.onCreateAnswerSuccess(desc);\n        },\n        (e) => {\n          this.onCreateAnswerError(this.pctpc2, e);\n        }\n      );\n    } catch (err) {\n      // console.error('Error processing offer:', err);\n      this.rejectDisconnect(false, new Error('Error processing offer'));\n    }\n  }\n\n  onSetLocalSuccess(pc) {\n     (this.getName(pc) + ' setLocalDescription complete');\n  }\n\n  onSetRemoteSuccess(pc) {\n     (this.getName(pc) + ' setRemoteDescription complete');\n  }\n\n  onSetSessionDescriptionError(pc, error) {\n    // console.error('Failed to set session description: ' + error.toString());\n    this.rejectDisconnect(false, new Error('Failed to set session description'));\n  }\n\n  onSetRemoteSessionDescriptionError(pc, error) {\n    // console.error('Failed to set session description: ' + error.toString());\n    this.rejectDisconnect(false, new Error('Failed to set session description'));\n  }\n\n  onCreateAnswerSuccess(desc) {\n    try {\n      // console.log('Answer from pctpc2, pctpc2 setLocalDescription start');\n      this.pctpc2.setLocalDescription(desc).then(\n        () => {\n          this.onSetLocalSuccess(this.pctpc2);\n        },\n        (e) => {\n          this.onSetSessionDescriptionError(this.pctpc2, e);\n        }\n      );\n      // console.log('pctpc1 setRemoteDescription start');\n      this.pctpc1.setRemoteDescription(desc).then(\n        () => {\n          this.onSetRemoteSuccess(this.pctpc1);\n        },\n        (e) => {\n          this.onSetRemoteSessionDescriptionError(this.pctpc1, e);\n        }\n      );\n    } catch (err) {\n      // console.error('Error processing answer:', err);\n      this.rejectDisconnect(false, new Error('Error processing answer'));\n    }\n  }\n\n  onIceCandidate(pc, event) {\n    try {\n      // null - indicates iceGatheringState is complete\n      if (!event.candidate) {\n        return;\n      }\n      // end-of-candidates -  indicates end of generation of candidates\n      // https://github.com/w3c/webrtc-pc/issues/1952#issuecomment-416645360\n      if (!event.candidate.candidate) {\n        return;\n      }\n\n      // only add relay candidates\n      let parsed = new ParsedIceCandidate(event.candidate);\n\n      if (pc == this.pctpc1) {\n        // console.log('candidate:', parsed.getType(), parsed);\n\n        if (this.statshandler.codeBase == Constants.codeBaseType.chrome) {\n          // check seen candidates for Chrome (doesn't work reliably with getStats)\n          if (parsed.isRelay()) {\n            if (parsed.isTypeTransportUdp()) {\n              this.parsedIceResults.relayUdpGathered = true;\n            }\n            if (parsed.isTypeTransportTcp()) {\n              this.parsedIceResults.relayTcpGathered = true;\n            }\n            if (parsed.isTypeTransportTls()) {\n              this.parsedIceResults.relayTlsGathered = true;\n            }\n          }\n\n          if (parsed.isServerReflexive()) {\n            this.parsedIceResults.srflxGathered = true;\n          }\n        }\n      }\n\n      if (!parsed.isRelay()) {\n        if (!this.localIpAddresses.includes(parsed.getIpAddress())) {\n          this.localIpAddresses.push(parsed.getIpAddress());\n          this.localIpAddressInfo.push({\n            ip: parsed.getIpAddress(),\n            candidateType: parsed.getType(),\n            networkType: 'unknown',\n          });\n          if (parsed.isPublicIp()) {\n            this.numberOfLocalIp++;\n          }\n        }\n        if (parsed.isPublicIp() && this.localIp === null) {\n          this.localIp = parsed.getIpAddress();\n          this.localIpType = parsed.getType();\n        }\n        return;\n      }\n\n      this.getOtherPc(pc).addIceCandidate(event.candidate)\n      .then(\n        () => {\n          this.onAddIceCandidateSuccess(pc);\n        },\n        (err) => {\n          this.onAddIceCandidateError(pc, err, parsed.isRelay());\n        }\n      );\n    } catch (err) {\n      // console.error('Error processing ICE candidate:', err);\n      this.rejectDisconnect(false, err);\n    }\n  }\n\n  onAddIceCandidateSuccess(pc) {\n     (this.getName(pc) + ' addIceCandidate success');\n  }\n\n  onAddIceCandidateError(pc, error, isRelay) {\n    // console.error(this.getName(pc) + ' failed to add ICE Candidate: ' + error.toString());\n    if (isRelay) {\n      this.rejectDisconnect(false, new Error('failed to add ICE Candidate'));\n    }\n  }\n\n  onIceStateChange(pc, event) {\n    try {\n      let newstate = '(?)';\n      if (pc) {\n        newstate = pc.iceConnectionState;\n      }\n      if (newstate === 'failed') {\n        // console.error('ICE failure');\n        this.rejectDisconnect(true, new Error('ICE failure'));\n      }\n\n      // timeout, since chrome seems to be stuck in checking\n      if (newstate === 'checking' && !this.iceTimer) {\n        this.iceTimer = setTimeout(() => {\n          delete this.iceTimer;\n          // console.error('ICE timeout');\n          this.rejectDisconnect(true, new Error('ICE timeout'));\n        }, ICE_CHECKING_TIMEOUT);\n      }\n      if (newstate === 'completed' || newstate === 'connected') {\n        clearTimeout(this.iceTimer);\n        delete this.iceTimer;\n      }\n\n      // console.warn('ICE state change:', newstate);\n    } catch (err) {\n      // console.error('Error processing ICE state change:', err);\n      this.rejectDisconnect(false, new Error('Error processing ICE state change'));\n    }\n  }\n\n  getIceResults() {\n    return new Promise((resolve, reject) => {\n      let iceServers = JSON.parse(JSON.stringify(this.iceServers)); // deepcopy, needed for react native\n      for (let i = 0; i < iceServers.length; i++) {\n        let server = iceServers[i];\n        if (!iceServers.hasOwnProperty(server)) {\n          delete server.credential;\n        }\n      };\n\n      let iceResults = {\n        turnIpAddress: '',\n        turnIpVersion: '',\n        turnTransport: '',\n        iceServers: iceServers,\n        ipv6Supported: false,\n        ipv4Supported: false,\n        relayTlsGathered: false,\n        relayTcpGathered: false,\n        relayUdpGathered: false,\n        srflxGathered: false,\n        relayTlsSuccess: false,\n        relayTcpSuccess: false,\n        relayUdpSuccess: false,\n        srflxSuccess: false,\n        localIpAddressInfo: [],\n        localIP: '',\n        numberOfLocalIPs: 0,\n        localIPType: '',\n        localIPNetworkType: '',\n      };\n\n      // merge results from parsed ICE candidates (to get Chrome's seen candidates)\n      for (let entry in this.parsedIceResults) {\n        if (this.parsedIceResults.hasOwnProperty(entry)) {\n          iceResults[entry] = this.parsedIceResults[entry];\n        }\n      }\n\n      // get stats\n      if (!this.pctpc1) {\n        reject(new Error('PC not available for stats'));\n        return;\n      }\n      this.statshandler.getIceCandidates(this.pctpc1).then((results) => {\n         // console.log('ICE results:', results);\n        iceResults.localIP = this.localIp;\n        iceResults.localIPType = this.localIpType;\n        iceResults.numberOfLocalIPs = this.numberOfLocalIp;\n        for (let j = 0; j < this.localIpAddressInfo.length; j++) {\n          let ipInfo = this.localIpAddressInfo[j];\n          for (let i = 0; i < results.localCandidates.length; i++) {\n            let candidate = results.localCandidates[i];\n            let ip = null;\n            if (candidate.ip) {\n              ip = candidate.ip;\n            } else if (candidate.address) {\n              ip = candidate.address;\n            } else {\n              ip = candidate.ipAddress;\n            }\n            if (ip === ipInfo.ip && candidate.networkType !== 'unknown') {\n              ipInfo.networkType = candidate.networkType;\n            }\n          }\n          iceResults.localIpAddressInfo.push(ipInfo);\n        }\n\n        let foundActiveCand = false;\n        for (let i = 0; i < results.iceCandidatePairs.length; i++) {\n          let pair = results.iceCandidatePairs[i];\n          const googActiveConnection = typeof pair.googActiveConnection === 'string' ?\n              pair.googActiveConnection === 'true' : pair.googActiveConnection;\n          const selected = typeof pair.selected === 'string' ?\n              pair.selected === 'true' : pair.selected;\n          if (googActiveConnection || selected) {\n            for (let i = 0; i < results.localCandidates.length; i++) {\n              let cand = results.localCandidates[i];\n              // figure out IP address\n              let ip = null;\n              if (cand.ip) {\n                ip = cand.ip;\n              } else if (cand.address) {\n                ip = cand.address;\n              } else {\n                ip = cand.ipAddress;\n              }\n\n              // fill infos for active pair\n              if (cand.id == pair.localCandidateId) {\n                 // console.log('Active candidate local transport:', cand);\n\n                iceResults.turnIpAddress = ip;\n                iceResults.turnNetworkType = cand.networkType;\n                iceResults.localIPNetworkType = cand.networkType;\n                let ipv6 = ip.indexOf(':') !== -1;\n                iceResults.turnIpVersion = ipv6?'ipv6':'ipv4';\n\n                iceResults.turnTransport = cand.mozLocalTransport;\n\n                foundActiveCand = true;\n              }\n              /* For Chrome, the active candidate sometimes is not in 'succeeded' state,\n                  so it would not trigger the normal relay*Succeeded setting below ..\n              */\n              if (cand.candidateType === 'relay' || cand.candidateType === 'relayed') {\n                if (cand.mozLocalTransport === 'udp') {\n                  iceResults.relayUdpSuccess = true;\n                }\n                if (cand.mozLocalTransport === 'tcp') {\n                  iceResults.relayTcpSuccess = true;\n                }\n                if (cand.mozLocalTransport === 'tls') {\n                  iceResults.relayTlsSuccess = true;\n                }\n              }\n\n              if (!ip) {\n                continue;\n              }\n              // IPv6 candidate seen?\n              if (ip.indexOf(':') !== -1) {\n                iceResults.ipv6Supported = true;\n              } else {\n                iceResults.ipv4Supported = true;\n              }\n            }\n          }\n        }\n\n        // NOTE candidate and pair checking is unreliable for getStats (e.g. chrome doesnt necessarily generate stats for all candidates)\n\n        // check for existing candidates\n        for (let i = 0; i < results.localCandidates.length; i++) {\n          let cand = results.localCandidates[i];\n          if (cand.candidateType === 'relay' || cand.candidateType === 'relayed') {\n            if (cand.mozLocalTransport === 'udp') {\n              iceResults.relayUdpGathered = true;\n            }\n            if (cand.mozLocalTransport === 'tcp') {\n              iceResults.relayTcpGathered = true;\n            }\n            if (cand.mozLocalTransport === 'tls') {\n              iceResults.relayTlsGathered = true;\n            }\n          }\n\n          if (cand.candidateType === 'srflx' || cand.candidateType === 'serverreflexive') {\n            iceResults.srflxGathered = true;\n          }\n        }\n\n        // check for successful pairs\n        for (let i = 0; i < results.iceCandidatePairs.length; i++) {\n          let pair = results.iceCandidatePairs[i];\n          if (pair.state === 'succeeded') {\n            for (let i = 0; i < results.localCandidates.length; i++) {\n              let cand = results.localCandidates[i];\n              if (cand.id == pair.localCandidateId) {\n                if (cand.candidateType === 'relay' || cand.candidateType === 'relayed') {\n                  if (cand.mozLocalTransport === 'udp') {\n                    iceResults.relayUdpSuccess = true;\n                  }\n                  if (cand.mozLocalTransport === 'tcp') {\n                    iceResults.relayTcpSuccess = true;\n                  }\n                  if (cand.mozLocalTransport === 'tls') {\n                    iceResults.relayTlsSuccess = true;\n                  }\n                }\n\n                if (cand.candidateType === 'srflx' || cand.candidateType === 'serverreflexive') {\n                  iceResults.srflxSuccess = true;\n                }\n              }\n            }\n          }\n        }\n\n        if (!foundActiveCand) {\n          // console.error('Active ICE candidate pair not found.');\n        }\n        resolve(iceResults);\n      },\n      (e) => {\n        reject(e);\n      });\n    },\n    (e) => {\n      reject(e);\n    });\n  }\n}\n\nexport {TurnConnection};\n","/** @module Timestamps */\n\n/** Return the current timestamp with millisecond accuracy if available\n * @return {Number} The timestamp\n * @public */\nexport function getCurrent() {\n  if (!window || !window.performance || !window.performance.now) {\n    return Date.now();\n  }\n  if (!window.performance.timing || !window.performance.timing.navigationStart) {\n    return Date.now();\n  }\n  return window.performance.now() + window.performance.timing.navigationStart;\n}\n","/** A base class for tests that need the TURN server */\nclass TurnTest {\n  /** Create a new instance (normally with super())\n   * @param {TurnConnection} connection the connection to the TURN server\n   */\n  constructor(connection) {\n    this.connection = connection;\n    this.active = false;\n\n    this.results = {};\n  }\n\n  /*\n   * Public functions\n   */\n\n  /** Returns the obtained results from the test\n   * @return {Object} the results\n   * @public\n   */\n  getResults() {\n    return this.results;\n  }\n\n  /** Start the tests\n   * @return {Promise} resolve when test is completed successfully\n   * @public\n   */\n  start() {\n    let promise = new Promise((resolve, reject) => {\n      this.resolveCb = resolve;\n      this.rejectCb = reject;\n    });\n\n    this.connection.setMessageCallback(this.handleMessage.bind(this));\n    this.connection.setErrorCallback(this.handleError.bind(this));\n\n    this.active = true;\n    this.forceStopped = false;\n    this.initiate();\n\n    return promise;\n  }\n\n  /** Stop the test\n   * @protected */\n  stop() {\n    this.active = false;\n  }\n\n  /** Force the test to stop\n   * @public\n   */\n  forceStop() {\n    this.forceStopped = true;\n    this.stop();\n    this.finished();\n  }\n\n  /** Returns if this test is currently running\n   * @return {Boolean} active or not\n   * @public\n   */\n  isActive() {\n    return this.active;\n  }\n\n  /*\n   * Override functions\n   */\n\n  /** Initiate the test sequence\n   * @protected\n   */\n  initiate() {\n    // console.error('initiate not implemented');\n  }\n\n  /** Handle the response for a sent msg\n   * @param {String} msg The received message\n   * @protected\n   */\n  handleMessage(msg) {\n    // console.error('handleMessage not implemented');\n  }\n\n  /** Handle an error occuring on the connection's datachannel\n   * @param {Error} error The received message\n   * @protected\n   */\n  handleError(error) {\n    // console.error('handleError not implemented');\n  }\n\n  /*\n   * Protected functions\n   */\n\n  /** Send data through the connection\n   * @param {String} msg The message to send\n   * @protected\n   */\n  send(msg) {\n    this.connection.send(msg);\n  }\n\n  /** The test finished successful.\n   * WARNING finished() or failed() HAS to be called by the inherited class\n   * @protected\n   */\n  finished() {\n    this.active = false;\n    if (this.resolveCb) {\n      this.resolveCb();\n      this.resolveCb = null;\n    }\n  }\n\n  /** The test failed.\n   * WARNING finished() or failed() HAS to be called by the inherited class\n   * @param {Error} error The error that was raised\n   * @protected\n   */\n  failed(error) {\n    this.active = false;\n    if (this.rejectCb) {\n      this.rejectCb(error);\n      this.rejectCb = null;\n    }\n  }\n}\n\nexport {TurnTest};\n","import * as Timestamps from '../utility/timestamps';\n/* eslint require-jsdoc: 0 */\n\nimport {TurnTest} from './turnTest';\n\nconst RTTSAMPLES = 10;\nconst TIMEOUT = 100; // ms\nconst LAST_TIMEOUT = 500; // ms\n\nclass RttTest extends TurnTest {\n  constructor(connection) {\n    super(connection);\n\n    this.sendTimer = null;\n    this.countSent = 0;\n    this.rtts = [];\n  }\n\n  /*\n   * Override functions\n   */\n  initiate() {\n    this.results.startTimestamp = Timestamps.getCurrent();\n    this.sendPing();\n  }\n\n  handleMessage(msg) {\n    if (!this.isActive()) {\n      return;\n    }\n\n    let sentTs = parseInt(msg, 10);\n    let rtt = this.calculateRtt(sentTs); // ms\n\n    this.rtts.push(rtt);\n    if (this.countSent < RTTSAMPLES) {\n      this.sendPing();\n      return;\n    }\n\n    // enough samples arrived\n    this.calculateMetrics();\n  }\n\n  handleError(error) {\n    this.fillResults();\n\n    this.failed(error);\n  }\n\n  /*\n   * Private functions\n   */\n  sendPing() {\n    if (!this.isActive()) {\n      return;\n    }\n\n    let now = Timestamps.getCurrent(); // ms\n    this.send(now.toString());\n    this.countSent += 1;\n\n    // cancel timer\n    if (this.sendTimer) {\n      clearTimeout(this.sendTimer);\n      this.sendTimer = null;\n    }\n    // setup timer\n    if (this.countSent < RTTSAMPLES) {\n      this.sendTimer = setTimeout(this.sendPing.bind(this), TIMEOUT);\n      return;\n    }\n    this.sendTimer = setTimeout(this.calculateMetrics.bind(this), LAST_TIMEOUT);\n  }\n\n  calculateRtt(sentTs) {\n    let now = Timestamps.getCurrent();\n    return now - sentTs;\n  }\n\n  calculateMetrics() {\n    if (this.sendTimer) {\n      clearTimeout(this.sendTimer);\n      this.sendTimer = null;\n    }\n\n    this.fillResults();\n\n    this.finished();\n  }\n\n  fillResults() {\n    this.results.sentMessages = this.countSent;\n    this.results.unAckedMessages = this.countSent - this.rtts.length;\n    this.results.maxMessages = RTTSAMPLES;\n    this.results.forceStopped = this.forceStopped;\n\n    this.results.median = this.median();\n    this.results.average = this.average();\n\n    /* use standard deviation instead of variance\n    when calculating jitter\n    ToDo: clean up the code so that key 'variance'\n    is not used instead of std  */\n    this.results.variance = this.std();\n\n    this.results.endTimestamp = Timestamps.getCurrent();\n  }\n\n  median() {\n    if (this.rtts.length == 0) {\n      return LAST_TIMEOUT;\n    }\n\n    // the middle entry of the sorted list\n    this.rtts.sort();\n    let half = Math.floor(this.rtts.length/2);\n    return this.rtts[half];\n  }\n\n  average() {\n    if (this.rtts.length == 0) {\n      return LAST_TIMEOUT;\n    }\n\n    let sum = 0;\n    for (let i = 0; i < this.rtts.length; i++ ) {\n      sum += this.rtts[i];\n    }\n    return sum / this.rtts.length;\n  }\n\n  variance() {\n    if (this.rtts.length == 0) {\n      return LAST_TIMEOUT;\n    }\n\n    let variance = 0;\n    let average = this.average();\n    for (let i = 0; i < this.rtts.length; i++) {\n      let rtt = this.rtts[i];\n      variance += Math.pow(rtt - average, 2);\n    }\n    variance /= this.rtts.length;\n    return variance;\n  }\n\n  std() {\n    let variance = this.variance();\n    if (variance <= 0) {\n      return 0;\n    }\n    let std = Math.sqrt(variance);\n    return std;\n  }\n\n  stop() {\n    if (!this.isActive()) {\n      return;\n    }\n    super.stop();\n    this.fillResults();\n  }\n}\n\nexport {RttTest};\n","import * as Timestamps from '../utility/timestamps';\n\n\n/** Create a random string\n * @param {Integer} length The length of the string\n * @return {String} The string of a certain length\n */\nfunction randomAsciiString(length) {\n  let result = '';\n  for (let i = 0; i < length; i++) {\n    // Visible ASCII chars are between 35 and 93.\n    result += String.fromCharCode(35 + Math.random() * (93-35));\n  }\n  return result;\n}\n\n/** Class produces strings of a certain length that contain a timestamp.\n * Due to the timestamp, the message is always unique, although the padding is constant.\n * The random padding ensures that the effect of compression in the network is mitigated.\n * Since the timestamp should be kept in float, the size of the message might vary by a few bytes. */\nclass MessageMaker {\n  /** Create a new object\n   * @param {Integer} size The total size of the message\n   */\n  constructor(size = 1200) {\n    this.message = {timestamp: '', sentBytes: 10000, padding: ''};\n\n    const TIMESTAMP_BYTES = Timestamps.getCurrent().toString().length;\n    const MESSAGE_BYTES = JSON.stringify(this.message).length;\n    const PADDING = randomAsciiString(size - TIMESTAMP_BYTES - MESSAGE_BYTES);\n\n    // NOTE somehow this creates slightly too big messages?\n    this.message.padding = PADDING;\n  }\n\n  /** Make a new message\n   * @param {Number} sentBytes the amount of bytes sent so far\n   * @return {String} The message\n   * @public\n   */\n  make(sentBytes) {\n    this.message.timestamp = Timestamps.getCurrent();\n    this.message.sentBytes = sentBytes;\n    return JSON.stringify(this.message);\n  }\n}\n\nexport {MessageMaker, randomAsciiString};\n","import * as Timestamps from '../utility/timestamps';\nimport {MessageMaker} from '../utility/messageMaker';\n/* eslint require-jsdoc: 0 */\n\nimport {TurnTest} from './turnTest';\n\nclass ThroughputTest extends TurnTest {\n  constructor(connection, rtt, loss) {\n    super(connection);\n\n    this.sentBytes = 0;\n    this.receivedBytes = 0;\n    this.secondHalfBytes = 0;\n    this.secondHalfStart = null;\n    this.bufferEmpty = 1;\n\n    this.chunkSize = 1200;\n    this.messageMaker = new MessageMaker(this.chunkSize);\n\n    this.duration = 5000; // ms\n    if (rtt != null) {\n      // duration is dependent on RTT, upper bound 10 s, lower bound 1 s\n      // it seems 50 RTTs is needed for reliable testing\n      let duration = 50 * rtt;\n      this.duration = Math.max(Math.min(duration, 10*1000), 1*1000);\n    }\n    this.sendTimer = null;\n\n    this.intervals = [];\n    this.intervalStart = 0;\n    this.intervalLength = 100; // ms\n    this.intervalBytes = 0;\n    this.loss = loss;\n    this.lastReceivedTimestamp = 0;\n  }\n\n  /*\n   * Override functions\n   */\n  initiate() {\n    if (window && window.csioReactNative) {\n      /* NOTE react-native does not support RTCDataChannel.bufferedAmount, so it\n          is stuck in a loop when putting data to the buffer.\n          Also, when it is ever supported, there is no removeEventListener which has be taken care of */\n      let errMsg = 'Not running throughput test for react-native';\n      // console.error(errMsg);\n      this.handleError(new Error(errMsg));\n      return;\n    }\n    // console.log('start', this.duration);\n    this.startSend();\n  }\n\n  handleMessage(msg) {\n    if (!this.isActive()) {\n      return;\n    }\n\n    // save last received message for loss calculations\n    this.lastMessage = msg;\n\n    // count the total received bytes\n    this.receivedBytes += msg.length;\n\n    // record start time, and set timer to stop\n    let now = Timestamps.getCurrent();\n    this.lastReceivedTimestamp = now;\n    if (!this.sendTimer) {\n      this.results.startTimestamp = now;\n      this.sendTimer = setTimeout(() => {\n        this.stop();\n        this.finished();\n      }, this.duration);\n    }\n\n    // calculate intervals\n    if (this.intervalStart == 0) {\n      this.intervalStart = now;\n    }\n    this.intervalBytes += msg.length;\n    if (now - this.intervalStart >= this.intervalLength) {\n      // average throughput\n      let intervalDuration = now - this.intervalStart; // ms\n      let intervalAvg = this.averageThroughput(this.intervalBytes, intervalDuration);\n\n      // RTT\n      let rtt = null;\n      try {\n        let msgJson = JSON.parse(this.lastMessage);\n        rtt = now - msgJson.timestamp;\n      } catch (e) {\n        // console.error('Error parsing msg:', msg, e);\n      }\n\n      // add and reset\n      this.intervals.push({\n        'startTimestamp': this.intervalStart,\n        'endTimestamp': now,\n        'bytesReceived': this.intervalBytes,\n        'average': intervalAvg,\n        'rtt': rtt,\n      });\n\n      this.intervalStart = now;\n      this.intervalBytes = 0;\n    }\n\n    // calculation for second half of the connection\n    if (this.results.startTimestamp && now - this.results.startTimestamp > this.duration/2) {\n      if (!this.secondHalfStart) {\n        this.secondHalfStart = now;\n      }\n      this.secondHalfBytes += msg.length;\n    }\n  }\n\n  handleError(error) {\n    this.stop();\n\n    this.failed(error);\n  }\n\n  /*\n   * Private functions\n   */\n  averageThroughput(bytes, milliseconds) {\n    if (milliseconds === 0) {\n      return 0;\n    }\n    let seconds = milliseconds/1000.0;\n    let avg = ((bytes / seconds) * 8.0 ) / 1024.0; // kbps\n    return avg;\n  }\n\n   // Listen for one bufferedamountlow event.\n  bufferListener() {\n    this.sendChannel.removeEventListener('bufferedamountlow', this.bufferListener.bind(this));\n    this.fillBuffer();\n  }\n\n  fillBuffer() {\n    // NOTE bufferedAmount might be 0 when the event is processed too late\n    if (this.sendChannel.bufferedAmount == 0) {\n      this.bufferEmpty += 1;\n    }\n\n    while (this.isActive()) {\n      if (this.sentBytes > 1000000) {\n        break;\n      }\n      if (this.sendChannel.bufferedAmount > this.bufferFullThreshold) {\n        if (this.usePolling) {\n          setTimeout(this.fillBuffer.bind(this), 250); // max rate: 11Mbps <= (300 * 1200 Bytes) / 0.25 s\n        } else {\n          this.sendChannel.addEventListener('bufferedamountlow', this.bufferListener.bind(this));\n        }\n        return;\n      }\n      let message = this.messageMaker.make(this.sentBytes);\n      this.sentBytes += message.length;\n      this.send(message);\n    }\n    this.sendChannel.removeEventListener('bufferedamountlow', this.bufferListener.bind(this));\n  }\n\n  startSend() {\n    if (!this.isActive()) {\n      return;\n    }\n\n    // the amount of data to be buffered\n    this.bufferFullThreshold = 1000 * this.chunkSize;\n    this.sendChannel = this.connection.sendChannel;\n    this.usePolling = true;\n    if (typeof this.sendChannel.bufferedAmountLowThreshold === 'number') {\n       // console.log('Using the bufferedamountlow event for flow control');\n      this.usePolling = false;\n\n      this.sendChannel.bufferedAmountLowThreshold = this.bufferFullThreshold/10;\n    }\n    setTimeout(this.fillBuffer.bind(this), 0);\n  }\n\n  fillResults() {\n    this.results.endTimestamp = this.lastReceivedTimestamp;\n    this.results.maxDuration = this.duration;\n    this.results.forceStopped = this.forceStopped;\n    this.results.bufferEmpty = this.bufferEmpty;\n    this.results.intervals = this.intervals;\n\n    this.results.bytesPrepared = this.sentBytes;\n    this.results.bytesReceived = this.receivedBytes;\n\n    if (!this.results.startTimestamp) {\n      this.results.startTimestamp = this.results.endTimestamp;\n    }\n    // calculate average throughput\n    let duration = 0;\n    let average = 0;\n    if (this.secondHalfStart) {\n      duration = this.results.endTimestamp - this.secondHalfStart; // ms\n      average = this.averageThroughput(this.secondHalfBytes, duration);\n    }\n    // fallback if there is no data for second half\n    let allDuration = this.results.endTimestamp - this.results.startTimestamp; // ms\n    let allAverage = this.averageThroughput(this.receivedBytes, allDuration);\n    if (allAverage > average) {\n      average = allAverage;\n    }\n\n    this.results.average = average;\n    this.results.fractionLostBytes = this.loss;\n  }\n\n  stop() {\n    if (!this.isActive()) {\n      return;\n    }\n    clearTimeout(this.sendTimer);\n    this.sendTimer = null;\n\n    super.stop();\n    this.fillResults();\n  }\n}\n\nexport {ThroughputTest};\n","import * as Timestamps from '../utility/timestamps';\nimport {MessageMaker} from '../utility/messageMaker';\n/* eslint require-jsdoc: 0 */\n\nimport {TurnTest} from './turnTest';\n\nconst MAX_BUFFER_FILL = 2;\nclass LossTest extends TurnTest {\n  constructor(connection) {\n    super(connection);\n\n    this.sentBytes = 0;\n    this.receivedBytes = 0;\n\n    this.chunkSize = 1024;\n    this.messageMaker = new MessageMaker(this.chunkSize);\n\n    this.duration = 3000; // ms\n    this.sendTimer = null;\n    this.lastMessage = null;\n    this.numBufferFill = 0;\n  }\n\n  /*\n   * Override functions\n   */\n  initiate() {\n    if (window && window.csioReactNative) {\n      /* NOTE react-native does not support RTCDataChannel.bufferedAmount, so it\n          is stuck in a loop when putting data to the buffer.\n          Also, when it is ever supported, there is no removeEventListener which has be taken care of */\n      let errMsg = 'Not running loss test for react-native';\n       (errMsg);\n      this.handleError(new Error(errMsg));\n      return;\n    }\n     // console.log('LossTest start', this.duration);\n    let now = Timestamps.getCurrent();\n    this.results.startTimestamp = now;\n    this.startSend();\n  }\n\n  handleMessage(msg) {\n    if (!this.isActive()) {\n      return;\n    }\n    this.lastMessage = msg;\n    // count the total received bytes\n    this.receivedBytes += msg.length;\n\n    // record start time, and set timer to stop\n    if (!this.sendTimer) {\n      this.sendTimer = setTimeout(() => {\n        this.stop();\n        this.finished();\n      }, this.duration);\n    }\n  }\n\n  handleError(error) {\n    this.stop();\n    this.failed(error);\n  }\n\n  fillBuffer() {\n    let sentData = 0;\n    while (this.isActive()) {\n      if (sentData > this.bufferFullThreshold) {\n        break;\n      }\n      let message = this.messageMaker.make(this.sentBytes);\n      this.sentBytes += message.length;\n      sentData += message.length;\n      setTimeout(this.send(message), 8); // sending by pacing, making sure we send 1Mbps\n    }\n    sentData = 0;\n    this.numBufferFill++;\n    if (this.numBufferFill >= MAX_BUFFER_FILL) {\n      return;\n    } else {\n      this.startSend();\n    }\n  }\n\n  startSend() {\n    if (!this.isActive()) {\n      return;\n    }\n    // the amount of data to be buffered\n    this.bufferFullThreshold = (1000 * this.chunkSize) / 8; // The threshold is 1 Mbps\n    this.sendChannel = this.connection.sendChannel;\n    setTimeout(this.fillBuffer.bind(this), 250);\n  }\n\n  fillResults() {\n    this.results.endTimestamp = Timestamps.getCurrent();\n    this.results.maxDuration = this.duration;\n    this.results.forceStopped = this.forceStopped;\n    this.results.sentBytes = this.sentBytes;\n    this.results.bytesReceived = this.receivedBytes;\n\n    let msgJson = null;\n    try {\n      msgJson = JSON.parse(this.lastMessage);\n    } catch (e) {\n      // console.error('Error parsing msg:', msg, e);\n      return;\n    }\n    if (msgJson) {\n      let totalBytes = msgJson.sentBytes + this.lastMessage.length;\n\n      this.results.bytesSent = totalBytes;\n      this.results.fractionLostBytes = 1 - this.receivedBytes/totalBytes;\n    } else {\n      this.results.bytesSent = -1;\n      this.results.fractionLostBytes = -1;\n    }\n     // console.log('Loss Results are ', this.results);\n  }\n\n  stop() {\n    if (!this.isActive()) {\n      return;\n    }\n    clearTimeout(this.sendTimer);\n    this.sendTimer = null;\n\n    super.stop();\n    this.fillResults();\n  }\n}\n\nexport {LossTest};\n","import * as Timestamps from './timestamps';\nimport {randomAsciiString} from './messageMaker';\n\nlet status = {\n  'success': 'success',\n  'stopped': 'stopped',\n  'failed': 'failed',\n};\n\n/** Stores results for tests and failures, and returns a complete results object.\n * The tests themselves are responsible for the format of their own results. */\nclass ResultsHandler {\n  /** Creates a new object */\n  constructor() {\n    this.start = Timestamps.getCurrent();\n    this.id = `${Math.trunc(this.start)}-${randomAsciiString(20)}`;\n    this.version = '@@pctVersion';\n    this.failures = [];\n    this.results = {};\n    this.status = status.success;\n  }\n\n  /** Sets status to stopped\n   */\n  setStatusStopped() {\n    if (this.status === status.failed) {\n      return;\n    }\n    this.status = status.stopped;\n  }\n\n  /** Sets status to failed\n   */\n  setStatusFailed() {\n    this.status = status.failed;\n  }\n\n  /** Sets status to success\n   */\n  setStatusSuccess() {\n    if (this.status === status.stopped) {\n      return;\n    }\n    this.status = status.success;\n  }\n\n  /** Returns the overall result of the PreCallTest\n   * @return {Object} the results\n   */\n  getResults() {\n    let results = {\n      id: this.id,\n      version: this.version,\n      status: this.status,\n      startTimestamp: this.start,\n      endTimestamp: Timestamps.getCurrent(),\n      failures: this.failures,\n      tests: this.results,\n    };\n\n    return results;\n  }\n\n  /** Return the number of failures that have occured\n   * @return {Number} the number of failures\n   */\n  getFailureNumber() {\n    return this.failures.length;\n  }\n\n  /** Returns the current ID\n   * @return {String} the ID\n   */\n  getId() {\n    return this.id;\n  }\n\n  /** adds test result\n   * @param {String} testName the name of the test\n   * @param {Object} result the test result\n   */\n  add(testName, result) {\n    this.results[testName] = result;\n    if (result.hasOwnProperty('forceStopped') && result.forceStopped == true) {\n      this.setStatusStopped();\n    }\n  }\n\n  /** adds a failure to start a PreCallTest, e.g. no connection to TURN server\n   * @param {Error} reason A description for the failure\n   */\n  failure(reason) {\n    if (typeof reason === 'object') {\n      reason = reason.toString();\n    }\n    let failure = {\n      timestamp: Timestamps.getCurrent(),\n      reason: reason,\n    };\n    this.failures.push(failure);\n  }\n}\n\nexport {ResultsHandler};\n","import * as Timestamps from './timestamps';\n\n/** ---- Online checks ---- */\nclass OnlineCheck {\n  /**\n   * constructor\n   */\n  constructor() {\n    this.active = false; // added, because react-native does not support removeEventListener\n  }\n\n  /** checks if the browser has a connection\n   * @private\n   */\n  start() {\n    this.active = true;\n    this.onlineCheck = [];\n\n    if (!window || !window.addEventListener || typeof window.addEventListener != 'function') {\n      return;\n    }\n\n    window.addEventListener('offline', () => {\n      this.addEntry();\n    });\n    window.addEventListener('online', () => {\n      this.addEntry();\n    });\n\n    this.addEntry();\n  }\n\n  /** adds an entry for online check\n   * @private\n   */\n  addEntry() {\n    if (!this.active) {\n      return;\n    }\n\n    let now = Timestamps.getCurrent();\n    if (navigator && navigator.onLine) {\n      let entry = navigator.onLine;\n\n      this.onlineCheck.push({'timestamp': now, 'online': entry});\n    }\n  }\n\n  /** stops checking for browser connection\n   * @return {Object} online check results\n   * @private\n   */\n  stop() {\n    this.active = false;\n\n    if (window && window.removeEventListener && typeof window.removeEventListener === 'function') {\n      window.removeEventListener('offline', () => {\n        this.addEntry();\n      });\n      window.removeEventListener('online', () => {\n        this.addEntry();\n      });\n    }\n\n    return this.onlineCheck;\n  }\n}\n\nexport {OnlineCheck};\n","import {TurnConnection} from './turnConnection';\nimport {RttTest} from './tests/rttTest';\nimport {ThroughputTest} from './tests/throughputTest';\nimport {LossTest} from './tests/lossTest';\nimport {ResultsHandler} from './utility/resultsHandler';\nimport {OnlineCheck} from './utility/onlineCheck';\nimport {detect, Constants} from './utility/stats/detectbrowser';\n\n/** the names of the tests */\nconst TEST_NAMES = {\n  RTT: 'rtt',\n  LOSS: 'loss',\n  THROUGHPUT: 'throughput',\n};\n\n/** the number of times the connection to the TURN server is retried if failed */\nconst FAILURE_RETRIES = 10;\n\n/**\n * Main class for PreCallTest. It performs a series of tests to measure the\n * user's connectivity.\n */\nclass PreCallTest {\n  /** Create a new instance */\n  constructor() {\n    this.browserInfo = detect();\n    this.onlineCheck = new OnlineCheck();\n    this.callsInProgress = 0;\n\n    /* The sequence of TURN tests */\n    this.turnTests = [\n      TEST_NAMES.RTT,\n      TEST_NAMES.LOSS,\n      TEST_NAMES.THROUGHPUT,\n    ];\n    this.active = false;\n    this.rtt = null;\n    this.fractionLostBytes = -1;\n    this.resultsHandler = null;\n    this.startResolve = null;\n    this.startReject = null;\n  }\n\n  /*\n   * Public methods\n   */\n\n  /** Start the precall tests\n   * @param {JSON} iceServers an RTCIceServer object/array\n   * @public\n   */\n  start(iceServers) {\n    this.iceServers = iceServers;\n\n    return new Promise((resolve, reject) => {\n      this.startResolve = resolve;\n      this.startReject = reject;\n\n      if (this.browserInfo.browserName === Constants.browserName.msie) {\n        // console.warn('precalltest: disable for IE');\n        // this.callback(null, 'Not started: disabled for IE');\n        this.startReject(new Error('Not started: disabled for IE'));\n        \n        return;\n      }\n\n      if (this.active) {\n        // console.warn('Not started: already in progress');\n        // this.callback(null, 'Not started: already in progress');\n        this.startReject(new Error('Not started: already in progress'));\n        \n        return;\n      }\n\n      if (this.callsInProgress > 0) {\n        // console.warn('Not started: call in progress');\n        // this.callback(null, 'Not started: call in progress');\n        this.startReject(new Error('Not started: call in progress'));\n        \n        return;\n      }\n\n      if (!iceServers) {\n        // console.warn('Not started: no ICE servers given');\n        // this.callback(null, 'Not started: no ICE servers given');\n        this.startReject(new Error('Not started: no ICE servers given'));\n        \n        return;\n      }\n\n      // console.log('PreCallTest start');\n      this.turnTestCounter = 0;\n      this.resultsHandler = new ResultsHandler();\n\n      let endpointInfo = {\n        type: 'browser',\n        os: this.browserInfo.os,\n        osVersion: this.browserInfo.osVersion,\n        buildName: this.browserInfo.browserName,\n        buildVersion: this.browserInfo.browserVersion,\n        userAgent: this.browserInfo.userAgent,\n      };\n      this.resultsHandler.add('endpointInfo', endpointInfo);\n\n      this.onlineCheck.start();\n\n      this.active = true;\n\n      this._start();\n    });\n  }\n\n  /** Internal start function\n   * @private\n   */\n  _start() {\n    if (!this.active) {\n      return;\n    }\n    this.turnConnection = new TurnConnection(this.browserInfo);\n    this.turnConnection.connect(this.iceServers).then(\n      () => {\n        // console.log('TURN connected.');\n        if (!this.active) {\n          this.stop();\n          return;\n        }\n\n        if (this.resultsHandler) {\n          this.resultsHandler.setStatusSuccess();\n        }\n        this.startTurnTests().then(() => {\n          // console.log('All TURN tests completed');\n          this.stop();\n        }, (e) => {\n          // console.error(e);\n          this.stop();\n        });\n      }, (e) => {\n        let continueFlag = e.continueFlag;\n        // console.log('TURN connection failed:', e);\n        if (this.resultsHandler) {\n          this.resultsHandler.failure(e);\n        }\n        if (!continueFlag) {\n          this.turnConnection.disconnect();\n          this.active = false;\n          let message = '';\n          try {\n            message = e.stack;\n          } catch (err) {\n            message = e.toString();\n          }\n          if (!message || message === '') {\n            message = e.toString();\n          }\n\n          if (this.resultsHandler) {\n            this.resultsHandler.setStatusFailed();\n          }\n\n          // console.warn('Error:', message);\n          // this.callback(null, message);\n          this.startReject(new Error(message));\n\n          return;\n        }\n        if (this.resultsHandler) {\n          this.resultsHandler.setStatusFailed();\n          if (this.resultsHandler.getFailureNumber() >= FAILURE_RETRIES) {\n            this.stop();\n            return;\n          }\n        } else {\n          this.stop();\n          return;\n        }\n        // restart if it hasn't failed too often already\n        this.turnConnection.disconnect();\n        setTimeout(() => {\n          // console.warn('PreCallTest REstart');\n          this._start();\n        }, 0);\n      });\n  }\n\n  /** Stop the precall tests\n   * @private */\n  stop() {\n    if (!this.active) {\n      return;\n    }\n\n    this.active = false;\n    if (this.activeTurnTest) {\n       // console.warn('Stopping active test');\n      this.activeTurnTest.forceStop();\n    }\n    // console.log('PreCallTest stop');\n\n    let onlineCheckResults = this.onlineCheck.stop();\n    if (this.resultsHandler) {\n      this.resultsHandler.add('onlineStatus', onlineCheckResults);\n    }\n\n    this.turnConnection.getIceResults().then((iceResults) => {\n      if (this.resultsHandler) {\n        this.resultsHandler.add('ice', iceResults);\n      }\n\n      // stop everything\n      // console.log('ICE obtained');\n      this.turnConnection.disconnect();\n\n      // send results\n      this.sendResults();\n    }, (err) => {\n      if (this.resultsHandler) {\n        this.resultsHandler.failure(err);\n      }\n\n      // stop everything\n      // console.log('ICE failure');\n      this.turnConnection.disconnect();\n\n      // send results\n      this.sendResults();\n    });\n  }\n\n  /** Start the precall tests\n   * @param {JSON} results full pct results\n   * @return {JSON}\n   * @private\n   */\n  getPublicPrecalltestResults(results) {\n    const publicResults = {\n      mediaConnectivity: false,\n      throughput: null,\n      fractionalLoss: null,\n      rtt: null,\n      jitter: null,\n      timestamp: Date.now(),\n    };\n    if (!results || !results.tests) {\n      return publicResults;\n    }\n\n    publicResults.startTimestamp = results.startTimestamp;\n    publicResults.endTimestamp = results.endTimestamp;\n\n    if (results.tests.rtt) {\n      publicResults.rtt = results.tests.rtt.median;\n      publicResults.mediaConnectivity = true;\n      publicResults.jitter = results.tests.rtt.variance;\n    }\n\n    if (results.tests.throughput) {\n      publicResults.throughput = results.tests.throughput.average;\n      publicResults.fractionalLoss = Math.max(results.tests.throughput.fractionLostBytes, 0);\n      publicResults.mediaConnectivity = true;\n      // publicResults.bytesSent = results.tests.throughput.bytesSent;\n    }\n\n    if (results.tests.ice) {\n      if (results.tests.ice.relayTcpSuccess ||\n          results.tests.ice.relayTlsSuccess ||\n          results.tests.ice.relayUdpSuccess) {\n        publicResults.mediaConnectivity = true;\n      }\n    }\n    return publicResults;\n  }\n\n  /** Send results via callback\n   * @private\n   */\n  sendResults() {\n    if (!this.resultsHandler) {\n        // this.callback(null, 'No results present');\n        this.startReject(new Error('No results present'));\n        return;\n    }\n\n    const results = this.resultsHandler.getResults();\n    const resultsMin = this.getPublicPrecalltestResults(results);\n    // console.log('**** Results ', results, resultsMin);\n      //this.callback(resultsMin, null);\n    this.startResolve(resultsMin);\n  }\n\n  /** Call starts\n   * @public */\n  callStarts() {\n    this.callsInProgress += 1;\n\n    if (this.resultsHandler) {\n      this.resultsHandler.setStatusStopped();\n    }\n\n    this.stop();\n  }\n\n  /** Call finished\n   * @public */\n  callFinished() {\n    this.callsInProgress -= 1;\n    // NOTE tests could be restarted here, if callsInProgress is 0\n  }\n\n  /**\n   * Disconnect the peer connection (used only when some crash occurs)\n   */\n  crashDisconnect() {\n    try {\n       // console.error('something crashed');\n      this.turnConnection.disconnect();\n    } catch (err) {\n       (err);\n    }\n  }\n\n  /*\n   * Private methods\n   */\n\n  /** Start TURN tests. The tests are serialized, the sequence given in this.turnTests\n   * @return {Promise} all tests completed or error, does not reject if a single test fails\n   * @private */\n  startTurnTests() {\n    if (this.turnTestCounter >= this.turnTests.length) {\n      return new Promise((resolve, reject) => {\n        resolve();\n      });\n    }\n\n    let testName = this.turnTests[this.turnTestCounter];\n    let test = null;\n    switch (testName) {\n      case TEST_NAMES.RTT:\n        test = new RttTest(this.turnConnection);\n        break;\n      case TEST_NAMES.LOSS:\n        test = new LossTest(this.turnConnection);\n        break;\n      case TEST_NAMES.THROUGHPUT:\n        test = new ThroughputTest(this.turnConnection, this.rtt, this.fractionLostBytes);\n        break;\n      default:\n        return new Promise((resolve, reject) => {\n          reject(new Error(`Unknown test: ${testName}`));\n        });\n    }\n\n    this.activeTurnTest = test;\n    if (!this.active) {\n      return new Promise((resolve, reject) => {\n        reject(new Error('Test trying to start while testing is not active'));\n      });\n    }\n    return test.start() // returns the Promise\n    .then(() => {\n      // console.info('Test succeeded', testName);\n      this.handleTestResults(testName, test.getResults());\n\n      this.turnTestCounter += 1;\n      this.activeTurnTest = null;\n      return this.startTurnTests();\n    }, (e) => {\n      // console.error('Test failed', testName, e);\n      this.handleTestResults(testName, test.getResults(), e);\n\n      this.turnTestCounter += 1;\n      this.activeTurnTest = null;\n      return this.startTurnTests();\n    });\n  }\n\n  /** handle the results from a test\n   * @param {String} testName the name of the test\n   * @param {Object} results the results of the test\n   * @param {Error=} error if the test failed\n   */\n  handleTestResults(testName, results, error=null) {\n    if (error == null && testName == TEST_NAMES.RTT) {\n      this.rtt = results.median;\n    } else if (error == null && testName == TEST_NAMES.LOSS) {\n      this.fractionLostBytes = results.fractionLostBytes;\n    }\n    if (this.resultsHandler) {\n      this.resultsHandler.add(testName, results);\n    }\n  }\n}\n\nexport default PreCallTest;\n\n// for standlone browserify based testing\n// (function() {\n//   if (('function' === typeof define) && (define.amd)) {/* AMD support */\n//     define('PreCallTest', [], PreCallTest);\n//   } else {/* Browsers and Web Workers*/\n//     global.PreCallTest = PreCallTest;\n//   }\n//   module.exports = PreCallTest;\n// })(typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : this); // eslint-disable-line\n","/**\n * Promise-like object which can be passed around for resolving it later. It\n * implements the \"thenable\" interface, so it can be used wherever a Promise\n * could be used.\n *\n * In addition a \"reject on timeout\" functionality is provided.\n */\nexport default class Deferred<T = any> {\n    private _timeout?: Timeout;\n    promise: Promise<T>;\n    resolve: (value: T | PromiseLike<T>) => void;\n    reject: (reason?: any) => void;\n    then: Promise<T>['then'];\n    catch: Promise<T>['catch'];\n\n    /**\n     * Instantiates a Deferred object.\n     */\n    constructor() {\n        this.promise = new Promise<T>((resolve, reject) => {\n            this.resolve = (value: T | PromiseLike<T>) => {\n                this.clearRejectTimeout();\n                resolve(value);\n            };\n            this.reject = (reason?: any) => {\n                this.clearRejectTimeout();\n                reject(reason);\n            };\n        });\n        this.then = this.promise.then.bind(this.promise);\n        this.catch = this.promise.catch.bind(this.promise);\n    }\n\n    /**\n     * Clears the reject timeout.\n     */\n    clearRejectTimeout(): void {\n        clearTimeout(this._timeout);\n    }\n\n    /**\n     * Rejects the promise after the given timeout.\n     */\n    setRejectTimeout(ms: number): void {\n        this._timeout = setTimeout(() => {\n            this.reject(new Error('timeout'));\n        }, ms);\n    }\n}\n","import currentExecutingScript from 'current-executing-script';\n\n/* eslint-disable max-params */\n\nexport interface ILoadScriptOptions {\n    async: boolean;\n    errorCallback?: () => void;\n    loadCallback?: () => void;\n    prepend: boolean;\n    relativeURL: boolean;\n    src: string;\n}\n\n/**\n * Implements utility functions which facilitate the dealing with scripts such\n * as the download and execution of a JavaScript file.\n */\nconst ScriptUtil = {\n    /**\n     * Loads a script from a specific source.\n     * @param options\n     * @param options.src the source from the which the script is to be (down)loaded\n     * @param options.async true to asynchronously load the script or false to\n     * synchronously load the script\n     * @param options.prepend true to schedule the loading of the script as soon as\n     * possible or false to schedule the loading of the script at the end of the\n     * scripts known at the time\n     * @param options.relativeURL whether we need load the library from url relative\n     * to the url that lib-jitsi-meet was loaded. Useful when sourcing the\n     * library from different location than the app that is using it\n     * @param options.loadCallback on load callback function\n     * @param options.errorCallback callback to be called on error loading the script\n     */\n    loadScript({\n        src,\n        async,\n        prepend,\n        relativeURL,\n        loadCallback,\n        errorCallback\n    }: ILoadScriptOptions): void {\n        const d = document;\n        const tagName = 'script';\n        const script = d.createElement(tagName);\n        const referenceNode = d.getElementsByTagName(tagName)[0];\n\n        script.async = async;\n\n        if (relativeURL) {\n            // finds the src url of the current loaded script\n            // and use it as base of the src supplied argument\n            const scriptEl = currentExecutingScript();\n\n            if (scriptEl) {\n                const scriptSrc = scriptEl.src;\n                const baseScriptSrc\n                    = scriptSrc.substring(0, scriptSrc.lastIndexOf('/') + 1);\n\n                if (scriptSrc && baseScriptSrc) {\n                    // eslint-disable-next-line no-param-reassign\n                    src = baseScriptSrc + src;\n                }\n            }\n        }\n\n        if (loadCallback) {\n            script.onload = loadCallback;\n        }\n        if (errorCallback) {\n            script.onerror = errorCallback;\n        }\n\n        script.src = src;\n        if (prepend) {\n            referenceNode.parentNode.insertBefore(script, referenceNode);\n        } else {\n            referenceNode.parentNode.appendChild(script);\n        }\n    }\n};\n\n/* eslint-enable max-params */\n\nexport default ScriptUtil;\n","import { getLogger } from '@jitsi/logger';\n\nimport { createAudioContext } from './WebAudioUtils';\n\nconst logger = getLogger('webaudio:AudioMixer');\n\n/**\n * The AudioMixer, as the name implies, mixes a number of MediaStreams containing audio tracks into a single\n * MediaStream.\n */\nexport default class AudioMixer {\n    private _started: boolean;\n    private _streamsToMix: MediaStream[];\n    private _streamMSSArray: MediaStreamAudioSourceNode[];\n    private _audioContext?: AudioContext;\n    private _mixedMSD?: MediaStreamAudioDestinationNode;\n\n    /**\n     * Create AudioMixer instance.\n     */\n    constructor() {\n        this._started = false;\n        this._streamsToMix = [];\n        this._streamMSSArray = [];\n    }\n\n    /**\n     * Add audio MediaStream to be mixed, if the stream doesn't contain any audio tracks it will be ignored.\n     *\n     * @param {MediaStream} stream - MediaStream to be mixed.\n     */\n    addMediaStream(stream: MediaStream): void {\n        if (!stream.getAudioTracks() || stream.getAudioTracks().length === 0) {\n            logger.warn('Added MediaStream doesn\\'t contain audio tracks.');\n        }\n\n        this._streamsToMix.push(stream);\n    }\n\n    /**\n     * At this point a WebAudio ChannelMergerNode is created and and the two associated MediaStreams are connected to\n     * it; the resulting mixed MediaStream is returned.\n     *\n     * @returns {Nullable<MediaStream>} - MediaStream containing added streams mixed together, or null if no MediaStream\n     * is added.\n     */\n    start(): Nullable<MediaStream> {\n        // If the mixer was already started just return the existing mixed stream.\n        if (this._started && this._mixedMSD) {\n            return this._mixedMSD.stream;\n        }\n\n        this._audioContext = createAudioContext();\n\n        if (!this._streamsToMix.length) {\n            logger.warn('No MediaStream\\'s added to AudioMixer, nothing will happen.');\n\n            return null;\n        }\n\n        this._started = true;\n\n        this._mixedMSD = this._audioContext!.createMediaStreamDestination();\n\n        for (const stream of this._streamsToMix) {\n            const streamMSS = this._audioContext!.createMediaStreamSource(stream);\n\n            streamMSS.connect(this._mixedMSD);\n\n            // Maintain a list of MediaStreamAudioSourceNode so we can disconnect them on reset.\n            this._streamMSSArray.push(streamMSS);\n        }\n\n        return this._mixedMSD.stream;\n    }\n\n    /**\n     * Disconnect MediaStreamAudioSourceNode and clear references.\n     *\n     * @returns {void}\n     */\n    reset(): void {\n        this._started = false;\n        this._streamsToMix = [];\n\n        // Clean up created MediaStreamAudioSourceNode.\n        for (const streamMSS of this._streamMSSArray) {\n            streamMSS.disconnect();\n        }\n\n        this._streamMSSArray = [];\n\n        if (this._audioContext) {\n            this._audioContext = undefined;\n        }\n        this._mixedMSD = undefined;\n    }\n}\n","// This file is auto-generated during build\nexport const COMMIT_HASH = 'aa5ca22c';\n","import Logger from '@jitsi/logger';\nimport { merge } from 'lodash-es';\n\nimport { JitsiAudioTranslationErrors } from './JitsiAudioTranslationErrors';\nimport JitsiConference, { IConferenceOptions } from './JitsiConference';\nimport * as JitsiConferenceErrors from './JitsiConferenceErrors';\nimport { JitsiConferenceEvents } from './JitsiConferenceEvents';\nimport JitsiConnection, { IConnectionOptions } from './JitsiConnection';\nimport * as JitsiConnectionErrors from './JitsiConnectionErrors';\nimport { JitsiConnectionEvents } from './JitsiConnectionEvents';\nimport JitsiMediaDevices from './JitsiMediaDevices';\nimport { JitsiMediaDevicesEvents } from './JitsiMediaDevicesEvents';\nimport JitsiTrackError from './JitsiTrackError';\nimport * as JitsiTrackErrors from './JitsiTrackErrors';\nimport { JitsiTrackEvents } from './JitsiTrackEvents';\nimport * as JitsiTranscriptionStatus from './JitsiTranscriptionStatus';\nimport JitsiLocalTrack from './modules/RTC/JitsiLocalTrack';\nimport RTC from './modules/RTC/RTC';\nimport RTCStats from './modules/RTCStats/RTCStats';\nimport { RTCStatsEvents } from './modules/RTCStats/RTCStatsEvents';\nimport browser from './modules/browser';\nimport NetworkInfo from './modules/connectivity/NetworkInfo';\nimport { TrackStreamingStatus } from './modules/connectivity/TrackStreamingStatus';\nimport getActiveAudioDevice from './modules/detection/ActiveDeviceDetector';\nimport { DetectionEvents } from './modules/detection/DetectionEvents';\nimport TrackVADEmitter from './modules/detection/TrackVADEmitter';\nimport ProxyConnectionService\n    from './modules/proxyconnection/ProxyConnectionService';\nimport recordingConstants from './modules/recording/recordingConstants';\nimport Settings from './modules/settings/Settings';\nimport LocalStatsCollector from './modules/statistics/LocalStatsCollector';\nimport runPreCallTest, { IIceServer, IPreCallResult } from './modules/statistics/PreCallTest';\nimport Statistics from './modules/statistics/statistics';\nimport Deferred from './modules/util/Deferred';\nimport ScriptUtil from './modules/util/ScriptUtil';\nimport * as VideoSIPGWConstants from './modules/videosipgw/VideoSIPGWConstants';\nimport AudioMixer from './modules/webaudio/AudioMixer';\nimport { IceRestartReason } from './service/RTC/IceRestartReason';\nimport { MediaType } from './service/RTC/MediaType';\nimport { VideoType } from './service/RTC/VideoType';\nimport { ConnectionQualityEvents } from './service/connectivity/ConnectionQualityEvents';\nimport { E2ePingEvents } from './service/e2eping/E2ePingEvents';\nimport { createGetUserMediaEvent } from './service/statistics/AnalyticsEvents';\nimport { COMMIT_HASH } from './version';\n\nconst logger = Logger.getLogger('core:JitsiMeetJS');\n\n// Settin the default log levels to info early so that we avoid overriding a log level set externally.\nLogger.setLogLevel(Logger.levels.INFO);\n\n/**\n * Indicates whether GUM has been executed or not.\n */\nlet hasGUMExecuted = false;\n\n/**\n * Extracts from an 'options' objects with a specific format (TODO what IS the\n * format?) the attributes which are to be logged in analytics events.\n *\n * @param options gum options (???)\n * @returns {*} the attributes to attach to analytics events.\n */\nfunction getAnalyticsAttributesFromOptions(options) {\n    const attributes: any = {};\n\n    /* eslint-disable */\n\n    attributes.audio_requested = options.devices.includes(MediaType.AUDIO);\n    attributes.video_requested = options.devices.includes(MediaType.VIDEO);\n    attributes.screen_sharing_requested = options.devices.includes(VideoType.DESKTOP);\n\n    if (attributes.video_requested) {\n        attributes.resolution = options.resolution;\n    }\n\n    /* eslint-enable */\n\n    return attributes;\n}\n\ninterface ICreateLocalTrackOptions {\n    cameraDeviceId?: string;\n    devices?: any[];\n    fireSlowPromiseEvent?: boolean;\n    micDeviceId?: string;\n    resolution?: string;\n}\n\ntype desktopSharingSourceType = 'screen' | 'window';\n\ninterface IJitsiMeetJSOptions {\n    analytics?: {\n        rtcstatsLogFlushSizeBytes?: number;\n        rtcstatsStoreLogs?: boolean;\n    };\n    audioLevelsInterval?: number;\n    desktopSharingSources?: Array<desktopSharingSourceType>;\n    disableAudioLevels?: boolean;\n    disableThirdPartyRequests?: boolean;\n    enableAnalyticsLogging?: boolean;\n    enableWindowOnErrorHandler?: boolean;\n    externalStorage?: Storage;\n    flags?: {\n        runInLiteMode?: boolean;\n        ssrcRewritingEnabled?: boolean;\n    };\n    pcStatsInterval?: number;\n}\n\ninterface ICreateLocalTrackFromMediaStreamOptions {\n    mediaType: MediaType;\n    sourceType: string;\n    stream: MediaStream;\n    track: MediaStreamTrack;\n    videoType?: VideoType;\n}\n\nexport interface IJoinConferenceOptions {\n    conferenceOptions?: IConferenceOptions;\n    connectionOptions?: IConnectionOptions;\n    jaas?: {\n        release?: string; // backend release \"1234\"\n        useStaging?: boolean;\n    };\n    tracks?: JitsiLocalTrack[];\n}\n\nconst mediaDevices = new JitsiMediaDevices();\n\n/**\n * The public API of the Jitsi Meet library (a.k.a. `JitsiMeetJS`).\n */\nconst JitsiMeetJS = {\n    JitsiConnection,\n\n    /**\n     * `ProxyConnectionService` is used to connect a remote peer to a local Jitsi participant without going\n     * through a Jitsi conference. It is currently used for room integration development, specifically wireless\n     * screensharing. Its API is experimental and will likely change; usage of it is advised against.\n     */\n    ProxyConnectionService,\n\n    /**\n     * Registers new global logger transport to the library logging framework.\n     *\n     * @param globalTransport\n     * @see Logger.addGlobalTransport\n     */\n    addGlobalLogTransport(globalTransport) {\n        Logger.addGlobalTransport(globalTransport);\n    },\n\n    /**\n     * Analytics configuration.\n     */\n    analytics: Statistics.analytics as unknown,\n\n    /**\n     * Constants used throughout the library.\n     */\n    constants: {\n        iceRestartReason: IceRestartReason,\n        recording: recordingConstants,\n        sipVideoGW: VideoSIPGWConstants,\n        trackStreamingStatus: TrackStreamingStatus,\n        transcriptionStatus: JitsiTranscriptionStatus,\n    },\n\n    /**\n     * Create AudioMixer, which is essentially a wrapper over web audio ChannelMergerNode. It essentially allows the\n     * user to mix multiple MediaStreams into a single one.\n     *\n     * @returns {AudioMixer}\n     */\n    createAudioMixer() {\n        return new AudioMixer();\n    },\n\n    /**\n     * Creates local media tracks.\n     *\n     * @param options Object with properties / settings specifying the tracks which should be created. should be\n     * created or some additional configurations about resolution for example.\n     * @param {Array} options.effects optional effects array for the track\n     * @param {Array} options.devices the devices that will be requested\n     * @param {string} options.resolution resolution constraints\n     * @param {string} options.cameraDeviceId\n     * @param {string} options.micDeviceId\n     *\n     * @returns {Promise.<{Array.<JitsiTrack>}, JitsiTrackError>} A promise that returns an array of created\n     * JitsiTracks if resolved, or a JitsiTrackError if rejected.\n     */\n    createLocalTracks(options: ICreateLocalTrackOptions = {}): Promise<JitsiLocalTrack[] | JitsiTrackError> {\n        let isFirstGUM = false;\n        const startTS = window.performance.now();\n\n        if (!window.connectionTimes) {\n            window.connectionTimes = {};\n        }\n\n        if (!hasGUMExecuted) {\n            hasGUMExecuted = true;\n            isFirstGUM = true;\n            window.connectionTimes['firstObtainPermissions.start'] = startTS;\n        }\n        window.connectionTimes['obtainPermissions.start'] = startTS;\n\n        return RTC.obtainAudioAndVideoPermissions(options)\n            .then(tracks => {\n                const endTS = window.performance.now();\n\n                window.connectionTimes['obtainPermissions.end'] = endTS;\n\n                if (isFirstGUM) {\n                    window.connectionTimes['firstObtainPermissions.end'] = endTS;\n                }\n\n                Statistics.sendAnalytics(\n                    createGetUserMediaEvent(\n                        'success',\n                        getAnalyticsAttributesFromOptions(options)));\n\n                if (this.isCollectingLocalStats()) {\n                    for (let i = 0; i < tracks.length; i++) {\n                        const track = tracks[i];\n\n                        if (track.getType() === MediaType.AUDIO) {\n                            Statistics.startLocalStats(track,\n                                track.setAudioLevel.bind(track));\n                        }\n                    }\n                }\n\n                // set real device ids\n                const currentlyAvailableMediaDevices\n                    = RTC.getCurrentlyAvailableMediaDevices();\n\n                if (currentlyAvailableMediaDevices) {\n                    for (let i = 0; i < tracks.length; i++) {\n                        const track = tracks[i];\n\n                        track._setRealDeviceIdFromDeviceList(\n                            currentlyAvailableMediaDevices);\n                    }\n                }\n\n                return tracks;\n            })\n            .catch(error => {\n                if (error.name === JitsiTrackErrors.SCREENSHARING_USER_CANCELED) {\n                    Statistics.sendAnalytics(\n                        createGetUserMediaEvent(\n                            'warning',\n                            {\n                                reason: 'extension install user canceled'\n                            }));\n                } else if (error.name === JitsiTrackErrors.NOT_FOUND) {\n                    const attributes\n                        = getAnalyticsAttributesFromOptions(options);\n\n                    attributes.reason = 'device not found';\n                    attributes.devices = error.gum.devices.join('.');\n                    Statistics.sendAnalytics(\n                        createGetUserMediaEvent('error', attributes));\n                } else {\n                    const attributes\n                        = getAnalyticsAttributesFromOptions(options);\n\n                    attributes.reason = error.name;\n                    Statistics.sendAnalytics(\n                        createGetUserMediaEvent('error', attributes));\n                }\n\n                const endTS = window.performance.now();\n\n                window.connectionTimes['obtainPermissions.end'] = endTS;\n\n                if (isFirstGUM) {\n                    window.connectionTimes['firstObtainPermissions.end'] = endTS;\n                }\n\n                return Promise.reject(error);\n            });\n    },\n\n    /**\n     * Manually create JitsiLocalTrack's from the provided track info, by exposing the RTC method\n     *\n     * @param {Array<ICreateLocalTrackFromMediaStreamOptions>} tracksInfo - array of track information\n     * @returns {Array<JitsiLocalTrack>} - created local tracks\n     */\n    createLocalTracksFromMediaStreams(tracksInfo: ICreateLocalTrackFromMediaStreamOptions[]): JitsiLocalTrack[] {\n        return RTC.createLocalTracks(tracksInfo.map(trackInfo => {\n            const tracks = trackInfo.stream.getTracks()\n                .filter(track => track.kind === trackInfo.mediaType);\n\n            if (!tracks || tracks.length === 0) {\n                // eslint-disable-next-line @typescript-eslint/only-throw-error\n                throw new JitsiTrackError(JitsiTrackErrors.TRACK_NO_STREAM_TRACKS_FOUND, null, null);\n            }\n\n            if (tracks.length > 1) {\n                // eslint-disable-next-line @typescript-eslint/only-throw-error\n                throw new JitsiTrackError(JitsiTrackErrors.TRACK_TOO_MANY_TRACKS_IN_STREAM, null, null);\n            }\n\n            trackInfo.track = tracks[0];\n\n            return trackInfo;\n        }));\n    },\n\n    /**\n     * Create a TrackVADEmitter service that connects an audio track to an VAD (voice activity detection) processor in\n     * order to obtain VAD scores for individual PCM audio samples.\n     *\n     * @param {string} localAudioDeviceId - The target local audio device.\n     * @param {number} sampleRate - Sample rate at which the emitter will operate. Possible values  256, 512, 1024,\n     * 4096, 8192, 16384. Passing other values will default to closes neighbor.\n     * I.e. Providing a value of 4096 means that the emitter will process 4096 PCM samples at a time, higher values mean\n     * longer calls, lowers values mean more calls but shorter.\n     * @param {Object} vadProcessor - VAD Processors that does the actual compute on a PCM sample.The processor needs\n     * to implement the following functions:\n     * - <tt>getSampleLength()</tt> - Returns the sample size accepted by calculateAudioFrameVAD.\n     * - <tt>getRequiredPCMFrequency()</tt> - Returns the PCM frequency at which the processor operates.\n     * i.e. (16KHz, 44.1 KHz etc.)\n     * - <tt>calculateAudioFrameVAD(pcmSample)</tt> - Process a 32 float pcm sample of getSampleLength size.\n     * @returns {Promise<TrackVADEmitter>}\n     */\n    createTrackVADEmitter(localAudioDeviceId, sampleRate, vadProcessor) {\n        return TrackVADEmitter.create(localAudioDeviceId, sampleRate, vadProcessor);\n    },\n\n    errorTypes: {\n        JitsiTrackError\n    },\n    errors: {\n        audioTranslation: JitsiAudioTranslationErrors,\n        conference: JitsiConferenceErrors,\n        connection: JitsiConnectionErrors,\n        track: JitsiTrackErrors\n    },\n    events: {\n        conference: JitsiConferenceEvents,\n        connection: JitsiConnectionEvents,\n        connectionQuality: ConnectionQualityEvents,\n        detection: DetectionEvents,\n        e2eping: E2ePingEvents,\n        mediaDevices: JitsiMediaDevicesEvents,\n        rtcstats: RTCStatsEvents,\n        track: JitsiTrackEvents\n    },\n\n    /**\n     * Go through all audio devices on the system and return one that is active, i.e. has audio signal.\n     *\n     * @returns Promise<Object> - Object containing information about the found device.\n     */\n    getActiveAudioDevice() {\n        return getActiveAudioDevice();\n    },\n\n    /**\n     * Initializes the library.\n     *\n     * @param options - The options to use for initializing the library.\n     * @returns {void}\n     */\n    init(options: IJitsiMeetJSOptions = {}) {\n        // Start capturing and sending logs to the rtcstats server as soon as possible.\n        const {\n            analytics: {\n                rtcstatsStoreLogs,\n                rtcstatsLogFlushSizeBytes\n            } = {}\n        } = options;\n\n        if (rtcstatsStoreLogs) {\n            Logger.addGlobalTransport(RTCStats.getDefaultLogCollector(rtcstatsLogFlushSizeBytes));\n        }\n\n        // @ts-ignore\n        logger.info(`This appears to be ${browser.getName()}, ver: ${browser.getVersion()}`);\n\n        mediaDevices.init();\n        Settings.init(options.externalStorage);\n        Statistics.init(options);\n\n        // Initialize global window.connectionTimes\n        // FIXME do not use 'window'\n        if (!window.connectionTimes) {\n            window.connectionTimes = {};\n        }\n\n        if (options.enableAnalyticsLogging !== true) {\n            logger.warn('Analytics disabled, disposing.');\n            this.analytics.dispose();\n        }\n\n        RTC.init(options);\n    },\n\n    /**\n     * Checks if local tracks can collect stats and collection is enabled.\n     *\n     * @returns {boolean} True if local stats are being collected.\n     */\n    isCollectingLocalStats() {\n        return Statistics.audioLevelsEnabled && LocalStatsCollector.isLocalStatsSupported();\n    },\n\n    /**\n     * Returns whether the desktop sharing is enabled or not.\n     *\n     * @returns {boolean}\n     */\n    isDesktopSharingEnabled() {\n        return RTC.isDesktopSharingEnabled();\n    },\n\n    /**\n     * Checks if the current environment supports having multiple audio\n     * input devices in use simultaneously.\n     *\n     * @returns {boolean} True if multiple audio input devices can be used.\n     */\n    isMultipleAudioInputSupported() {\n        return this.mediaDevices.isMultipleAudioInputSupported();\n    },\n\n    /**\n     * Returns whether the current execution environment supports WebRTC (for\n     * use within this library).\n     *\n     * @returns {boolean} `true` if WebRTC is supported in the current\n     * execution environment (for use within this library); `false`,\n     * otherwise.\n     */\n    isWebRtcSupported() {\n        return RTC.isWebRtcSupported();\n    },\n\n    /**\n     * Simple way to create a {JitsiConference}. All options are optional and sane defaults\n     * will be chosen for JaaS users.\n     *\n     * @param roomName - The name of the conference.\n     * @param appId - The application id (also known as tenant).\n     * @param token - The token (JWT) to use for authentication.\n     * @param options - The options to use for joining the conference.\n     */\n    async joinConference(\n            roomName: string,\n            appId: string = '',\n            token: Nullable<string> = null,\n            options: IJoinConferenceOptions = {}): Promise<JitsiConference> {\n        const d = new Deferred();\n        let connectionOptions = options.connectionOptions ?? {};\n\n        // Provide a solid default config in case of JaaS.\n        if (appId.startsWith('vpaas-magic-cookie')) {\n            // Initialize RTCStats logging.\n            Logger.addGlobalTransport(RTCStats.getDefaultLogCollector());\n\n            const useStage = options.jaas?.useStaging ?? false;\n            const jaasDomain = useStage ? 'staging.8x8.vc' : '8x8.vc';\n            let serviceUrl = `wss://${jaasDomain}/${appId}/xmpp-websocket?room=${roomName}`;\n\n            if (options.jaas?.release) {\n                serviceUrl = `${serviceUrl}&release=release-${options.jaas.release}`;\n            }\n\n            const opts = {\n                analytics: {\n                    rtcstatsEnabled: true,\n                    rtcstatsEndpoint: `wss://rtcstats-server-${useStage ? 'pilot' : '8x8'}.jitsi.net/`,\n                    rtcstatsSendSdp: true,\n                },\n                conferenceRequestUrl: `https://${jaasDomain}/${appId}/conference-request/v1?room=${roomName}`,\n                hosts: {\n                    domain: jaasDomain,\n                    muc: `conference.${appId}.${jaasDomain}`\n                },\n                serviceUrl,\n                websocketKeepAliveUrl: `https://${jaasDomain}/${appId}/_unlock?room=${roomName}`\n            };\n\n            connectionOptions = merge(connectionOptions, opts);\n        }\n\n        const conn = new JitsiConnection(appId, token, connectionOptions as IConnectionOptions);\n\n        function cleanupListeners() {\n            conn.removeEventListener(\n                JitsiConnectionEvents.CONNECTION_ESTABLISHED, onConnectionEstablished);\n            conn.removeEventListener(\n                JitsiConnectionEvents.CONNECTION_FAILED, onConnectionFailed);\n        }\n\n        function onConnectionEstablished() {\n            cleanupListeners();\n\n            const conf = conn.initJitsiConference(roomName, options.conferenceOptions ?? {});\n\n            d.resolve(conf);\n\n            // Make sure this runs after the promise was resolved so that local track events can be\n            // listened to.\n            queueMicrotask(() => {\n                for (const track of options.tracks || []) {\n                    conf.addTrack(track);\n                }\n\n                conf.join();\n\n                // Default to receiving 720p for everyone.\n                conf.setReceiverConstraints({\n                    defaultConstraints: { maxHeight: 720 },\n                    lastN: -1\n                });\n            });\n        }\n\n        function onConnectionFailed(error: string) {\n            cleanupListeners();\n            d.reject(error);\n        }\n\n        conn.addEventListener(\n            JitsiConnectionEvents.CONNECTION_ESTABLISHED, onConnectionEstablished);\n        conn.addEventListener(\n            JitsiConnectionEvents.CONNECTION_FAILED, onConnectionFailed);\n        conn.connect({ name: roomName });\n\n        return d as unknown as Promise<JitsiConference>;\n    },\n\n    logLevels: Logger.levels,\n    mediaDevices,\n\n    /**\n     * Removes global logging transport from the library logging framework.\n     *\n     * @param globalTransport\n     * @see Logger.removeGlobalTransport\n     */\n    removeGlobalLogTransport(globalTransport) {\n        Logger.removeGlobalTransport(globalTransport);\n    },\n\n    /**\n     * Expose rtcstats to the public API.\n     */\n    rtcstats: {\n        /**\n         * Checks if the rtcstats trace is available.\n         * The trace is the abstraction for the underlying rtcstats websocket connection.\n         *\n         * @returns {boolean} <tt>true</tt> if the rtcstats trace is available or\n         * <tt>false</tt> otherwise.\n         */\n        isTraceAvailable() {\n            return RTCStats.isTraceAvailable();\n        },\n\n        /**\n         * Events generated by rtcstats, such as PeerConnections state,\n         * and websocket connection state.\n         *\n         * @param {RTCStatsEvents} event - The event name.\n         * @param {function} handler - The event handler.\n         */\n        on(event, handler) {\n            RTCStats.events.on(event, handler);\n        },\n\n        /**\n         * Sends identity data to the rtcstats server. This data is used\n         * to identify the specifics of a particular client, it can be any object\n         * and will show in the generated rtcstats dump under \"identity\" entries.\n         *\n         * @param {Object} identityData - Identity data to send.\n         * @returns {void}\n         */\n        sendIdentityEntry(identityData) {\n            RTCStats.sendIdentity(identityData);\n        },\n\n        /**\n         * Sends a stats entry to rtcstats server.\n         * @param {string} statsType - The type of stats to send.\n         * @param {Object} data - The stats data to send.\n         */\n        sendStatsEntry(statsType: RTCStatsEvents, data?: Optional<any>) {\n            RTCStats.sendStatsEntry(statsType, null, data);\n        }\n    },\n\n    /**\n     * Run a pre-call test to check the network conditions.\n     *\n     * @param {IIceServer} iceServers  - The ICE servers to use for the test,\n     * @returns {Promise<PreCallResult | any>} - A Promise that resolves with the test results or rejects with an error\n     * message.\n     */\n    runPreCallTest(iceServers: IIceServer[]): Promise<IPreCallResult | any> {\n        return runPreCallTest(iceServers);\n    },\n\n    /**\n    * Sets global options which will be used by all loggers. Changing these\n    * works even after other loggers are created.\n    *\n    * @param options\n    * @see Logger.setGlobalOptions\n    */\n    setGlobalLogOptions(options) {\n        Logger.setGlobalOptions(options);\n    },\n\n    /**\n     * Sets the log level to the <tt>Logger</tt> instance.\n     *\n     * @param {Logger.levels} level the logging level to be set\n     * @see Logger.setLogLevel\n     */\n    setLogLevel(level) {\n        Logger.setLogLevel(level);\n    },\n\n    /**\n     * Sets the log level to the <tt>Logger</tt> instance with given id.\n     *\n     * @param {Logger.levels} level the logging level to be set\n     * @param {string} id the logger id to which new logging level will be set.\n     * Usually it's the name of the JavaScript source file including the path\n     * ex. \"modules/xmpp/ChatRoom.js\"\n     */\n    setLogLevelById(level, id) {\n        Logger.setLogLevelById(level, id);\n    },\n\n    /**\n     * Informs lib-jitsi-meet about the current network status.\n     *\n     * @param {object} state - The network info state.\n     * @param {boolean} state.isOnline - `true` if the internet connectivity is online or `false`\n     * otherwise.\n     */\n    setNetworkInfo({ isOnline }) {\n        NetworkInfo.updateNetworkInfo({ isOnline });\n    },\n\n    /**\n     * Represents a hub/namespace for utility functionality which may be of\n     * interest to lib-jitsi-meet clients.\n     */\n    util: {\n        ScriptUtil,\n        browser\n    },\n    version: COMMIT_HASH\n};\n\nexport default JitsiMeetJS;\n","export interface IRecordingConstants {\n    error: {\n        BUSY: string;\n        ERROR: string;\n        POLICY_VIOLATION: string;\n        RESOURCE_CONSTRAINT: string;\n        SERVICE_UNAVAILABLE: string;\n        UNEXPECTED_REQUEST: string;\n    };\n    mode: {\n        FILE: string;\n        STREAM: string;\n    };\n    status: {\n        OFF: string;\n        ON: string;\n        PENDING: string;\n    };\n}\n\nconst recordingConstants: IRecordingConstants = {\n    error: {\n        BUSY: 'busy',\n        ERROR: 'error',\n        POLICY_VIOLATION: 'policy-violation',\n        RESOURCE_CONSTRAINT: 'resource-constraint',\n        SERVICE_UNAVAILABLE: 'service-unavailable',\n        UNEXPECTED_REQUEST: 'unexpected-request'\n    },\n    mode: {\n        FILE: 'file',\n        STREAM: 'stream'\n    },\n    status: {\n        OFF: 'off',\n        ON: 'on',\n        PENDING: 'pending'\n    }\n};\n\nexport default recordingConstants;\n","import PreCallTest from '@jitsi/precall-test';\n\n\nexport interface IPreCallResult {\n\n    // Maximum bandwidth reached in kbps  (kilo bits per second).\n    fractionalLoss: number;\n\n    // Round trip time in milliseconds.\n    jitter: number;\n\n    // Variation in packet arrival times during the transmission of media.\n    mediaConnectivity: boolean;\n\n    // Packet loss percentage over all the test traffic.\n    rtt: number;\n    throughput: number; // Whether the data channel was able to send data or not.\n}\n\n// Same interface as a PeerConnection configuration object.\nexport interface IIceServer {\n    credential?: string;\n    urls: Array<string> | string;\n    username?: string;\n}\n\n/**\n * Run a pre-call test to check the network conditions. It uses a TURN server to establish\n * a connection between two PeerConnections using the server as a relay. Afterwards it sends\n * some test traffic through a data channel to measure the network conditions, these are\n * recorded and returned through a Promise.\n *\n * @param {Array<IIceServer>} - The ICE servers to use for the test, these are passes to the PeerConnection constructor.\n * @returns {Promise<IPreCallResult | any>} - A Promise that resolves with the test results or rejects with an error.\n */\nexport default async function runPreCallTest(iceServers: Array<IIceServer>): Promise<IPreCallResult | string> {\n    const test = new PreCallTest();\n\n    return await test.start(iceServers);\n}\n","const ljm = require('./JitsiMeetJS').default;\n\n/**\n * Tries to deal with the following problem: {@code JitsiMeetJS} is not only\n * this module, it's also a global (i.e. attached to {@code window}) namespace\n * for all globals of the projects in the Jitsi Meet family. If lib-jitsi-meet\n * is loaded through an HTML {@code script} tag, {@code JitsiMeetJS} will\n * automatically be attached to {@code window} by webpack. Unfortunately,\n * webpack's source code does not check whether the global variable has already\n * been assigned and overwrites it. Which is OK for the module\n * {@code JitsiMeetJS} but is not OK for the namespace {@code JitsiMeetJS}\n * because it may already contain the values of other projects in the Jitsi Meet\n * family. The solution offered here works around webpack by merging all\n * existing values of the namespace {@code JitsiMeetJS} into the module\n * {@code JitsiMeetJS}.\n *\n * @param {Object} module - The module {@code JitsiMeetJS} (which will be\n * exported and may be attached to {@code window} by webpack later on).\n * @private\n * @returns {Object} - A {@code JitsiMeetJS} module which contains all existing\n * value of the namespace {@code JitsiMeetJS} (if any).\n */\nfunction _mergeNamespaceAndModule(module) {\n    return (\n        typeof window.JitsiMeetJS === 'object'\n            ? { ...window.JitsiMeetJS,\n                ...module }\n            : module);\n}\n\nmodule.exports = _mergeNamespaceAndModule(ljm);\n","'use strict';\n\n\nconst internals = {\n    suspectRx: /\"(?:_|\\\\u005[Ff])(?:_|\\\\u005[Ff])(?:p|\\\\u0070)(?:r|\\\\u0072)(?:o|\\\\u006[Ff])(?:t|\\\\u0074)(?:o|\\\\u006[Ff])(?:_|\\\\u005[Ff])(?:_|\\\\u005[Ff])\"\\s*\\:/\n};\n\n\nexports.parse = function (text, ...args) {\n\n    // Normalize arguments\n\n    const firstOptions = typeof args[0] === 'object' && args[0];\n    const reviver = args.length > 1 || !firstOptions ? args[0] : undefined;\n    const options = (args.length > 1 && args[1]) || firstOptions || {};\n\n    // Parse normally, allowing exceptions\n\n    const obj = JSON.parse(text, reviver);\n\n    // options.protoAction: 'error' (default) / 'remove' / 'ignore'\n\n    if (options.protoAction === 'ignore') {\n        return obj;\n    }\n\n    // Ignore null and non-objects\n\n    if (!obj ||\n        typeof obj !== 'object') {\n\n        return obj;\n    }\n\n    // Check original string for potential exploit\n\n    if (!text.match(internals.suspectRx)) {\n        return obj;\n    }\n\n    // Scan result for proto keys\n\n    exports.scan(obj, options);\n\n    return obj;\n};\n\n\nexports.scan = function (obj, options = {}) {\n\n    let next = [obj];\n\n    while (next.length) {\n        const nodes = next;\n        next = [];\n\n        for (const node of nodes) {\n            if (Object.prototype.hasOwnProperty.call(node, '__proto__')) {      // Avoid calling node.hasOwnProperty directly\n                if (options.protoAction !== 'remove') {\n                    throw new SyntaxError('Object contains forbidden prototype property');\n                }\n\n                delete node.__proto__;\n            }\n\n            for (const key in node) {\n                const value = node[key];\n                if (value &&\n                    typeof value === 'object') {\n\n                    next.push(node[key]);\n                }\n            }\n        }\n    }\n};\n\n\nexports.safeParse = function (text, reviver) {\n\n    try {\n        return exports.parse(text, reviver);\n    }\n    catch (ignoreError) {\n        return null;\n    }\n};\n","/* Copyright @ 2016-present 8x8, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nvar Logger = require('./Logger.js');\n\n/**\n * Creates new <tt>LogCollector</tt>. Class implements <tt>LoggerTransport</tt>\n * and thus can be added as global transport in order to capture all the logs.\n *\n * It captures subsequent log lines created whenever <tt>Logger</tt> logs\n * a message and stores them in a queue in order to batch log entries. There are\n * time and size limit constraints which determine how often batch entries are\n * stored. Whenever one of these limits is exceeded the <tt>LogCollector</tt>\n * will use the <tt>logStorage</tt> object given as an argument to save\n * the batch log entry.\n *\n * @param {Object} logStorage an object which allows to store the logs collected\n * @param {function(string|object[])} logStorage.storeLogs a method called when\n * this <tt>LogCollector</tt> requests log entry storage. The method's argument\n * is an array which can contain <tt>string</tt>s and <tt>object</tt>s. If given\n * item is an object it means that it's an aggregated message. That is a message\n * which is the same as the previous one and it's representation has\n * the following format:\n * {\n *   {string} text: 'the text of some duplicated message'\n *   {number} count: 3 // how many times the message appeared in a row\n * }\n * If a message \"B\" after an aggregated message \"A\" is different, then it breaks\n * the sequence of \"A\". Which means that even if the next message \"C\" is\n * the same as \"A\" it will start a new aggregated message \"C\".\n * @param {function()} logStorage.isReady a method which should return\n * a <tt>boolean</tt> to tell the collector that it's ready to store. During the\n * time storage is not ready log batches will be cached and stored on the next\n * occasion (flush or interval timeout).\n *\n * @param {Object} options the <tt>LogCollector</tt> configuration options.\n * @param {number} options.maxEntryLength the size limit for a single log entry\n * to be stored. The <tt>LogCollector</tt> will push the entry as soon as it\n * reaches or exceeds this limit given that <tt>logStorage.isReady</tt>\n * returns <tt>true</tt>. Otherwise the log entry will be cached until the log\n * storage becomes ready. Note that the \"is ready\" condition is checked every\n * <tt>options.storeInterval</tt> milliseconds.\n * @param {number} options.storeInterval how often the logs should be stored in\n * case <tt>maxEntryLength</tt> was not exceeded.\n * @param {boolean} options.stringifyObjects indicates whether or not object\n * arguments should be \"stringified\" with <tt>JSON.stringify</tt> when a log\n * message is composed. Note that objects logged on the error log level are\n * always stringified.\n *\n * @constructor\n */\nfunction LogCollector(logStorage, options) {\n    this.logStorage = logStorage;\n    this.stringifyObjects = options && options.stringifyObjects ? options.stringifyObjects : false;\n    this.storeInterval = options && options.storeInterval ? options.storeInterval: 30000;\n    this.maxEntryLength = options && options.maxEntryLength ? options.maxEntryLength : 10000;\n    // Bind the log method for each level to the corresponding method name\n    // in order to implement \"global log transport\" object.\n    Object.values(Logger.levels).forEach(\n    function (logLevel) {\n        this[logLevel] = function () {\n            this._log.apply(this, arguments);\n        }.bind(this, logLevel);\n    }.bind(this));\n    /**\n     * The ID of store logs interval if one is currently scheduled or\n     * <tt>null</tt> otherwise.\n     * @type {number|null}\n     */\n    this.storeLogsIntervalID = null;\n    /**\n     * The log messages that are to be batched into log entry when\n     * {@link LogCollector._flush} method is called.\n     * @type {string[]}\n     */\n    this.queue = [];\n    /**\n     * The total length of all messages currently stored in the {@link queue}.\n     * @type {number}\n     */\n    this.totalLen = 0;\n    /**\n     * An array used to temporarily store log batches, before the storage gets\n     * ready.\n     * @type {string[]}\n     */\n    this.outputCache = [];\n}\n\n/**\n * Method called inside of {@link formatLogMessage} in order to covert an\n * <tt>Object</tt> argument to string. The conversion will happen when either\n * 'stringifyObjects' option is enabled or on the {@link Logger.levels.ERROR}\n * log level. The default implementation uses <tt>JSON.stringify</tt> and\n * returns \"[object with circular refs?]\" instead of an object if it fails.\n *\n * @param {object} someObject the <tt>object</tt> to be stringified.\n *\n * @return {string} the result of <tt>JSON.stringify</tt> or\n * \"[object with circular refs?]\" if any error occurs during \"stringification\".\n *\n * @protected\n */\nLogCollector.prototype.stringify = function (someObject) {\n    try {\n        return JSON.stringify(someObject);\n    } catch (error) {\n        return '[object with circular refs?]';\n    }\n};\n\n/**\n * Formats log entry for the given logging level and arguments passed to the\n * <tt>Logger</tt>'s log method. The first argument is log level and the next\n * arguments have to be captured using JS built-in 'arguments' variable.\n *\n * @param {Logger.levels} logLevel provides the logging level of the message to\n * be logged.\n * @param {Date} timestamp - The {@code Date} when a message has been logged.\n *\n * @return {string|null} a non-empty string representation of the log entry\n * crafted from the log arguments. If the return value is <tt>null</tt> then\n * the message wil be discarded by this <tt>LogCollector</tt>.\n *\n * @protected\n */\nLogCollector.prototype.formatLogMessage = function (\nlogLevel /* timestamp, arg2, arg3, arg4... */) { // jshint ignore:line\n    var msg = '';\n    for (var i = 1, len = arguments.length; i < len; i++) {\n        var arg = arguments[i];\n\n        if (arg instanceof Error) {\n            msg += arg.toString() + ': ' + arg.stack;\n        } else if (this.stringifyObjects && typeof arg === 'object') {\n        // NOTE: We were trying to stringify all error logs before but because of a bug that we were getting the keys\n        // of the log levels which are all with upper case and comparing it with the keys which are all lower case we\n        // were never actually strinfying the error logs. That's why I've removed the check for error logs here.\n        // NOTE: The non-enumerable properties of the objects wouldn't be included in the string after JSON.strigify.\n        // For example Map instance will be translated to '{}'. So I think we have to eventually do something better\n        // for parsing the arguments. But since this option for strigify is part of the public interface and I think\n        // it could be useful in some cases I will it for now.\n            msg += this.stringify(arg);\n        } else {\n            msg += arg;\n        }\n        if (i !== len - 1) {\n            msg += ' ';\n        }\n    }\n    return msg.length ? msg : null;\n};\n\n/**\n * The log method bound to each of the logging levels in order to implement\n * \"global log transport\" object.\n *\n * @private\n */\nLogCollector.prototype._log = function() {\n\n    // var logLevel = arguments[0]; first argument is the log level\n    var timestamp = arguments[1];\n    var msg = this.formatLogMessage.apply(this, arguments);\n    if (msg) {\n        // The same as the previous message aggregation logic\n        var prevMessage = this.queue[this.queue.length - 1];\n        var prevMessageText = prevMessage && prevMessage.text;\n        if (prevMessageText === msg) {\n            prevMessage.count += 1;\n        } else {\n            this.queue.push({\n                text: msg,\n                timestamp: timestamp,\n                count: 1\n            });\n            this.totalLen += msg.length;\n        }\n    }\n\n    if (this.totalLen >= this.maxEntryLength) {\n        this._flush(true /* force */, true /* reschedule */);\n    }\n};\n\n/**\n * Starts periodical \"store logs\" task which will be triggered at the interval\n * specified in the constructor options.\n */\nLogCollector.prototype.start = function () {\n    this._reschedulePublishInterval();\n};\n\n/**\n * Reschedules the periodical \"store logs\" task which will store the next batch\n * log entry in the storage.\n * @private\n */\nLogCollector.prototype._reschedulePublishInterval = function () {\n    if (this.storeLogsIntervalID) {\n        window.clearTimeout(this.storeLogsIntervalID);\n        this.storeLogsIntervalID = null;\n    }\n    // It's actually a timeout, because it is rescheduled on every flush\n    this.storeLogsIntervalID = window.setTimeout(\n        this._flush.bind(\n            this, false /* do not force */, true /* reschedule */),\n        this.storeInterval);\n};\n\n/**\n * Call this method to flush the log entry buffer and store it in the log\n * storage immediately (given that the storage is ready).\n */\nLogCollector.prototype.flush = function() {\n    this._flush(\n        false /* do not force, as it will not be stored anyway */,\n        true /* reschedule next update */ );\n};\n\n/**\n * Passes the logs to logStorage.storeLogs in order to store them. If logStorage.storeLogs throws an error, it prints it.\n * Note: We are not retrying to pass the logs to the logStorage if there is an error.\n * @param {string[]} logs - The logs to be stored.\n */\nLogCollector.prototype._storeLogs = function (logs) {\n    try {\n        this.logStorage.storeLogs(logs);\n    } catch (error) {\n        console.error('LogCollector error when calling logStorage.storeLogs(): ', error);\n    }\n};\n\n/**\n * Stores the next batch log entry in the log storage.\n * @param {boolean} force enforce current logs batch to be stored or cached if\n * there is anything to be logged, but the storage is not ready yet. One of\n * legitimate reasons to force is when the logs length exceeds size limit which\n * could result in truncation.\n * @param {boolean} reschedule <tt>true</tt> if the next periodic task should be\n * scheduled after the log entry is stored. <tt>false</tt> will end the periodic\n * task cycle.\n * @private\n */\nLogCollector.prototype._flush = function(force, reschedule) {\n    var logStorageReady = false;\n\n    try {\n        logStorageReady = this.logStorage.isReady();\n    } catch (error) {\n        console.error('LogCollector error when calling logStorage.isReady(): ', error);\n    }\n\n    // Publish only if there's anything to be logged\n    if (this.totalLen > 0 && (logStorageReady || force)) {\n        //FIXME avoid truncating\n        // right now we don't care if the message size is \"slightly\" exceeded\n        if (logStorageReady) {\n            // Sends all cached logs\n            if (this.outputCache.length) {\n                this.outputCache.forEach(\n                    function (cachedQueue) {\n                        this._storeLogs(cachedQueue);\n                    }.bind(this)\n                );\n                // Clear the cache\n                this.outputCache = [];\n            }\n            // Send current batch\n            this._storeLogs(this.queue);\n        } else {\n            this.outputCache.push(this.queue);\n        }\n\n        this.queue = [];\n        this.totalLen = 0;\n    }\n\n    if (reschedule) {\n        this._reschedulePublishInterval();\n    }\n};\n\n/**\n * Stops the periodical \"store logs\" task and immediately stores any pending\n * log entries as a batch.\n */\nLogCollector.prototype.stop = function() {\n    // Flush and stop publishing logs\n    this._flush(false /* do not force */, false /* do not reschedule */);\n};\n\nmodule.exports = LogCollector;\n","/* Copyright @ 2015-present 8x8, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/*jslint latedef:false*/\n\n/**\n * Ordered log levels.\n */\nvar levels = {\n    \"trace\": 0,\n    \"debug\": 1,\n    \"info\": 2,\n    \"log\": 3,\n    \"warn\": 4,\n    \"error\": 5\n};\n\n/**\n * The default transport - console\n * @type LoggerTransport\n */\nLogger.consoleTransport = console;\n\n/**\n * The array which stores currently registered global transports.\n * @type {[LoggerTransport]}\n */\nvar globalTransports = [ Logger.consoleTransport ];\n\n/**\n * Adds given {@link LoggerTransport} instance to the list of global\n * transports which means that it'll be used by all {@link Logger}s\n * @param {LoggerTransport} transport\n */\nLogger.addGlobalTransport = function(transport) {\n    if (globalTransports.indexOf(transport) === -1) {\n        globalTransports.push(transport);\n    }\n};\n\n/**\n * Removes given {@link LoggerTransport} instance from the list of global\n * transports\n * @param {LoggerTransport} transport\n */\nLogger.removeGlobalTransport = function(transport) {\n    var transportIdx = globalTransports.indexOf(transport);\n    if (transportIdx !== -1) {\n        globalTransports.splice(transportIdx, 1);\n    }\n};\n\n/**\n * The global configuration options.\n */\nvar globalOptions = {};\n\n/**\n * Sets global options which will be used by all loggers. Changing these works\n * even after other loggers are created.\n */\nLogger.setGlobalOptions = function(options) {\n    globalOptions = options || {};\n};\n\n/**\n * Parses Error's object stack trace and extracts information about the last\n * caller before the log method was called.\n * @returns JS object with info about the caller - method name, file location,\n * line and column.\n */\nfunction getCallerInfo() {\n    var callerInfo = {\n        methodName: \"\",\n        fileLocation: \"\",\n        line: null,\n        column: null\n    };\n    //gets the part of the stack without the logger wrappers\n    var error = new Error();\n    var stack = error.stack? error.stack.split(\"\\n\") : [];\n    if(!stack || stack.length < 3) {\n        return callerInfo;\n    }\n    var m = null;\n    if(stack[3]) {\n        m = stack[3].match(/\\s*at\\s*(.+?)\\s*\\((\\S*)\\s*:(\\d*)\\s*:(\\d*)\\)/);\n    }\n    if(!m || m.length <= 4) {\n        //Firefox && Safari\n        if(stack[2].indexOf(\"log@\") === 0){\n            //Safari\n            callerInfo.methodName = stack[3].substr(0, stack[3].indexOf(\"@\"));\n        } else {\n            //Firefox\n            callerInfo.methodName = stack[2].substr(0, stack[2].indexOf(\"@\"));\n        }\n        return callerInfo;\n    }\n\n    callerInfo.methodName = m[1];\n    callerInfo.fileLocation = m[2];\n    callerInfo.line = m[3];\n    callerInfo.column = m[4];\n    return callerInfo;\n}\n\n/**\n * Logs messages using the transports and level from the logger.\n * @param logger a logger instance.\n * @param level the log level of the message. See the levels variable.\n * @param arguments array with arguments that will be logged.\n */\nfunction log() {\n    var logger = arguments[0], level = arguments[1],\n        args = Array.prototype.slice.call(arguments, 2);\n    if(levels[level] < logger.level) {\n        return;\n    }\n\n    var callerInfo\n        = !(logger.options.disableCallerInfo || globalOptions.disableCallerInfo) &&\n            getCallerInfo();\n    var transports = globalTransports.concat(logger.transports);\n    for(var i = 0; i < transports.length; i++) {\n        var t = transports[i];\n        var l = t[level];\n        if(l && typeof(l) === \"function\") {\n            var logPrefixes = [];\n\n            logPrefixes.push(new Date().toISOString());\n\n            // Include the log level for log parsing and filtering.\n            logPrefixes.push(\"[\" + level.toUpperCase() +\"]\");\n\n            if (logger.id) {\n                logPrefixes.push(\"[\" + logger.id + \"]\");\n            }\n\n            if (callerInfo && callerInfo.methodName.length > 1) {\n                logPrefixes.push(\"<\" + callerInfo.methodName + \">: \");\n            }\n\n            var fullLogParts = logPrefixes.concat(args);\n\n            try {\n                l.bind(t).apply(t, fullLogParts);\n            } catch (error) {\n                // It would be nice to send the error to the logger but this could send us into an endless loop.\n                // That's why we use only console for logging here.\n                console.error(\"An error occured when trying to log with one of the available transports\", error);\n            }\n        }\n    }\n}\n\n/**\n *\n * Constructs new logger object.\n * @param level the logging level for the new logger\n * @param id optional identifier for the logger instance.\n * @param {LoggerTransport} transports optional list of handlers(objects) for\n * the logs. The handlers must support - log, warn, error, debug, info, trace.\n * @param options optional configuration file for how the logger should behave.\n * @param {boolean} options.disableCallerInfo Whether the call site of a logger\n * method invocation should be included in the log. Defaults to false, so the\n * call site will be included.\n */\nfunction Logger(level, id, transports, options) {\n    this.id = id;\n    this.options = options || {};\n    this.transports = transports;\n    if(!this.transports) {\n        this.transports = [];\n    }\n    this.level = levels[level];\n    var methods = Object.keys(levels);\n    for(var i = 0; i < methods.length; i++){\n        this[methods[i]] =\n            log.bind(null, this, methods[i]);\n    }\n}\n\n/**\n * Sets the log level for the logger.\n * @param level the new log level.\n */\nLogger.prototype.setLevel = function (level) {\n    this.level = levels[level];\n};\nmodule.exports = Logger;\n\n/**\n * Enum for the supported log levels.\n */\nLogger.levels = {\n    TRACE: \"trace\",\n    DEBUG: \"debug\",\n    INFO: \"info\",\n    LOG: \"log\",\n    WARN: \"warn\",\n    ERROR: \"error\"\n};\n","/* Copyright @ 2015-present 8x8, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nvar Logger = require(\"./Logger\");\nvar LogCollector = require(\"./LogCollector\");\n\n/**\n * Definition of the log method\n * @name log_method\n * @function\n * @param {...*} log_args the arguments to be logged\n */\n/**\n * The logger's transport type definition.\n *\n * @typedef {object} LoggerTransport\n *\n * @property {log_method} trace method called to log on {@link Logger.levels.TRACE} logging level\n * @property {log_method} debug method called to log on {@link Logger.levels.DEBUG} logging level\n * @property {log_method} info method called to log on {@link Logger.levels.INFO} logging level\n * @property {log_method} log method called to log on {@link Logger.levels.LOG} logging level\n * @property {log_method} warn method called to log on {@link Logger.levels.WARN} logging level\n * @property {log_method} error method called to log on {@link Logger.levels.ERROR} logging level\n */\n\n/**\n * Map with the created loggers with ID.\n */\nvar idLoggers = {};\n\n/**\n * Array with the loggers without id.\n */\nvar loggers = [];\n\n/**\n * Log level for the lbrary.\n */\nvar curLevel = Logger.levels.TRACE;\n\n\nmodule.exports = {\n    /**\n     * Adds given {@link LoggerTransport} instance to the list of global\n     * transports which means that it'll be used by all {@link Logger}s\n     * @param {LoggerTransport} transport\n     */\n    addGlobalTransport: function(transport) {\n        Logger.addGlobalTransport(transport);\n    },\n    /**\n     * Removes given {@link LoggerTransport} instance from the list of global\n     * transports\n     * @param {LoggerTransport} transport\n     */\n    removeGlobalTransport: function(transport) {\n        Logger.removeGlobalTransport(transport);\n    },\n    /**\n    * Sets global options which will be used by all loggers. Changing these\n    * works even after other loggers are created.\n    */\n    setGlobalOptions: function(options) {\n        Logger.setGlobalOptions(options);\n    },\n    /**\n     * Creates new logger.\n     * @arguments the same as Logger constructor\n     */\n    getLogger: function(id, transports, options) {\n        var logger = new Logger(curLevel, id, transports, options);\n        if(id) {\n            idLoggers[id] = idLoggers[id] || [];\n            idLoggers[id].push(logger);\n        } else {\n            loggers.push(logger);\n        }\n        return logger;\n    },\n    /**\n     * Creates a new Logger, without keeping track of it in the loggers list\n     * @arguments the same as Logger constructor\n     */\n    getUntrackedLogger: function(id, transports, options) {\n        return new Logger(curLevel, id, transports, options);\n    },\n    /**\n     * Changes the log level for the existing loggers by id.\n     * @param level the new log level.\n     * @param id if specified the level will be changed only for loggers with the\n     * same id. Otherwise the operation will affect all loggers that don't\n     * have id.\n     */\n    setLogLevelById: function(level, id) {\n        var l = id? (idLoggers[id] || []) : loggers;\n        for(var i = 0; i < l.length; i++) {\n            l[i].setLevel(level);\n        }\n    },\n    /**\n     * Changes the log level for all existing loggers.\n     * @param level the new log level.\n     */\n    setLogLevel: function (level) {\n        curLevel = level;\n        var i = 0;\n        for(; i < loggers.length; i++) {\n            loggers[i].setLevel(level);\n        }\n\n        for(var id in idLoggers) {\n            var l = idLoggers[id] || [];\n            for(i = 0; i < l.length; i++) {\n                l[i].setLevel(level);\n            }\n        }\n    },\n    /**\n     * The supported log levels.\n     */\n    levels: Logger.levels,\n    /**\n     * Exports the <tt>LogCollector</tt>.\n     */\n    LogCollector: LogCollector\n};\n","/* Copyright @ 2016-present 8x8, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nvar Logger = require('./Logger.js');\n\n/**\n * Creates new <tt>LogCollector</tt>. Class implements <tt>LoggerTransport</tt>\n * and thus can be added as global transport in order to capture all the logs.\n *\n * It captures subsequent log lines created whenever <tt>Logger</tt> logs\n * a message and stores them in a queue in order to batch log entries. There are\n * time and size limit constraints which determine how often batch entries are\n * stored. Whenever one of these limits is exceeded the <tt>LogCollector</tt>\n * will use the <tt>logStorage</tt> object given as an argument to save\n * the batch log entry.\n *\n * @param {Object} logStorage an object which allows to store the logs collected\n * @param {function(string|object[])} logStorage.storeLogs a method called when\n * this <tt>LogCollector</tt> requests log entry storage. The method's argument\n * is an array which can contain <tt>string</tt>s and <tt>object</tt>s. If given\n * item is an object it means that it's an aggregated message. That is a message\n * which is the same as the previous one and it's representation has\n * the following format:\n * {\n *   {string} text: 'the text of some duplicated message'\n *   {number} count: 3 // how many times the message appeared in a row\n * }\n * If a message \"B\" after an aggregated message \"A\" is different, then it breaks\n * the sequence of \"A\". Which means that even if the next message \"C\" is\n * the same as \"A\" it will start a new aggregated message \"C\".\n * @param {function()} logStorage.isReady a method which should return\n * a <tt>boolean</tt> to tell the collector that it's ready to store. During the\n * time storage is not ready log batches will be cached and stored on the next\n * occasion (flush or interval timeout).\n *\n * @param {Object} options the <tt>LogCollector</tt> configuration options.\n * @param {number} options.maxEntryLength the size limit for a single log entry\n * to be stored. The <tt>LogCollector</tt> will push the entry as soon as it\n * reaches or exceeds this limit given that <tt>logStorage.isReady</tt>\n * returns <tt>true</tt>. Otherwise the log entry will be cached until the log\n * storage becomes ready. Note that the \"is ready\" condition is checked every\n * <tt>options.storeInterval</tt> milliseconds.\n * @param {number} options.storeInterval how often the logs should be stored in\n * case <tt>maxEntryLength</tt> was not exceeded.\n * @param {boolean} options.stringifyObjects indicates whether or not object\n * arguments should be \"stringified\" with <tt>JSON.stringify</tt> when a log\n * message is composed. Note that objects logged on the error log level are\n * always stringified.\n *\n * @constructor\n */\nfunction LogCollector(logStorage, options) {\n    this.logStorage = logStorage;\n    this.stringifyObjects = options && options.stringifyObjects ? options.stringifyObjects : false;\n    this.storeInterval = options && options.storeInterval ? options.storeInterval: 30000;\n    this.maxEntryLength = options && options.maxEntryLength ? options.maxEntryLength : 10000;\n    // Bind the log method for each level to the corresponding method name\n    // in order to implement \"global log transport\" object.\n    Object.values(Logger.levels).forEach(\n    function (logLevel) {\n        this[logLevel] = function () {\n            this._log.apply(this, arguments);\n        }.bind(this, logLevel);\n    }.bind(this));\n    /**\n     * The ID of store logs interval if one is currently scheduled or\n     * <tt>null</tt> otherwise.\n     * @type {number|null}\n     */\n    this.storeLogsIntervalID = null;\n    /**\n     * The log messages that are to be batched into log entry when\n     * {@link LogCollector._flush} method is called.\n     * @type {string[]}\n     */\n    this.queue = [];\n    /**\n     * The total length of all messages currently stored in the {@link queue}.\n     * @type {number}\n     */\n    this.totalLen = 0;\n    /**\n     * An array used to temporarily store log batches, before the storage gets\n     * ready.\n     * @type {string[]}\n     */\n    this.outputCache = [];\n}\n\n/**\n * Method called inside of {@link formatLogMessage} in order to covert an\n * <tt>Object</tt> argument to string. The conversion will happen when either\n * 'stringifyObjects' option is enabled or on the {@link Logger.levels.ERROR}\n * log level. The default implementation uses <tt>JSON.stringify</tt> and\n * returns \"[object with circular refs?]\" instead of an object if it fails.\n *\n * @param {object} someObject the <tt>object</tt> to be stringified.\n *\n * @return {string} the result of <tt>JSON.stringify</tt> or\n * \"[object with circular refs?]\" if any error occurs during \"stringification\".\n *\n * @protected\n */\nLogCollector.prototype.stringify = function (someObject) {\n    try {\n        return JSON.stringify(someObject);\n    } catch (error) {\n        return '[object with circular refs?]';\n    }\n};\n\n/**\n * Formats log entry for the given logging level and arguments passed to the\n * <tt>Logger</tt>'s log method. The first argument is log level and the next\n * arguments have to be captured using JS built-in 'arguments' variable.\n *\n * @param {Logger.levels} logLevel provides the logging level of the message to\n * be logged.\n * @param {Date} timestamp - The {@code Date} when a message has been logged.\n *\n * @return {string|null} a non-empty string representation of the log entry\n * crafted from the log arguments. If the return value is <tt>null</tt> then\n * the message wil be discarded by this <tt>LogCollector</tt>.\n *\n * @protected\n */\nLogCollector.prototype.formatLogMessage = function (\nlogLevel /* timestamp, arg2, arg3, arg4... */) { // jshint ignore:line\n    var msg = '';\n    for (var i = 1, len = arguments.length; i < len; i++) {\n        var arg = arguments[i];\n\n        if (arg instanceof Error) {\n            msg += arg.toString() + ': ' + arg.stack;\n        } else if (this.stringifyObjects && typeof arg === 'object') {\n        // NOTE: We were trying to stringify all error logs before but because of a bug that we were getting the keys\n        // of the log levels which are all with upper case and comparing it with the keys which are all lower case we\n        // were never actually strinfying the error logs. That's why I've removed the check for error logs here.\n        // NOTE: The non-enumerable properties of the objects wouldn't be included in the string after JSON.strigify.\n        // For example Map instance will be translated to '{}'. So I think we have to eventually do something better\n        // for parsing the arguments. But since this option for strigify is part of the public interface and I think\n        // it could be useful in some cases I will it for now.\n            msg += this.stringify(arg);\n        } else {\n            msg += arg;\n        }\n        if (i !== len - 1) {\n            msg += ' ';\n        }\n    }\n    return msg.length ? msg : null;\n};\n\n/**\n * The log method bound to each of the logging levels in order to implement\n * \"global log transport\" object.\n *\n * @private\n */\nLogCollector.prototype._log = function() {\n\n    // var logLevel = arguments[0]; first argument is the log level\n    var timestamp = arguments[1];\n    var msg = this.formatLogMessage.apply(this, arguments);\n    if (msg) {\n        // The same as the previous message aggregation logic\n        var prevMessage = this.queue[this.queue.length - 1];\n        var prevMessageText = prevMessage && prevMessage.text;\n        if (prevMessageText === msg) {\n            prevMessage.count += 1;\n        } else {\n            this.queue.push({\n                text: msg,\n                timestamp: timestamp,\n                count: 1\n            });\n            this.totalLen += msg.length;\n        }\n    }\n\n    if (this.totalLen >= this.maxEntryLength) {\n        this._flush(true /* force */, true /* reschedule */);\n    }\n};\n\n/**\n * Starts periodical \"store logs\" task which will be triggered at the interval\n * specified in the constructor options.\n */\nLogCollector.prototype.start = function () {\n    this._reschedulePublishInterval();\n};\n\n/**\n * Reschedules the periodical \"store logs\" task which will store the next batch\n * log entry in the storage.\n * @private\n */\nLogCollector.prototype._reschedulePublishInterval = function () {\n    if (this.storeLogsIntervalID) {\n        window.clearTimeout(this.storeLogsIntervalID);\n        this.storeLogsIntervalID = null;\n    }\n    // It's actually a timeout, because it is rescheduled on every flush\n    this.storeLogsIntervalID = window.setTimeout(\n        this._flush.bind(\n            this, false /* do not force */, true /* reschedule */),\n        this.storeInterval);\n};\n\n/**\n * Call this method to flush the log entry buffer and store it in the log\n * storage immediately (given that the storage is ready).\n */\nLogCollector.prototype.flush = function() {\n    this._flush(\n        false /* do not force, as it will not be stored anyway */,\n        true /* reschedule next update */ );\n};\n\n/**\n * Passes the logs to logStorage.storeLogs in order to store them. If logStorage.storeLogs throws an error, it prints it.\n * Note: We are not retrying to pass the logs to the logStorage if there is an error.\n * @param {string[]} logs - The logs to be stored.\n */\nLogCollector.prototype._storeLogs = function (logs) {\n    try {\n        this.logStorage.storeLogs(logs);\n    } catch (error) {\n        console.error('LogCollector error when calling logStorage.storeLogs(): ', error);\n    }\n};\n\n/**\n * Stores the next batch log entry in the log storage.\n * @param {boolean} force enforce current logs batch to be stored or cached if\n * there is anything to be logged, but the storage is not ready yet. One of\n * legitimate reasons to force is when the logs length exceeds size limit which\n * could result in truncation.\n * @param {boolean} reschedule <tt>true</tt> if the next periodic task should be\n * scheduled after the log entry is stored. <tt>false</tt> will end the periodic\n * task cycle.\n * @private\n */\nLogCollector.prototype._flush = function(force, reschedule) {\n    var logStorageReady = false;\n\n    try {\n        logStorageReady = this.logStorage.isReady();\n    } catch (error) {\n        console.error('LogCollector error when calling logStorage.isReady(): ', error);\n    }\n\n    // Publish only if there's anything to be logged\n    if (this.totalLen > 0 && (logStorageReady || force)) {\n        //FIXME avoid truncating\n        // right now we don't care if the message size is \"slightly\" exceeded\n        if (logStorageReady) {\n            // Sends all cached logs\n            if (this.outputCache.length) {\n                this.outputCache.forEach(\n                    function (cachedQueue) {\n                        this._storeLogs(cachedQueue);\n                    }.bind(this)\n                );\n                // Clear the cache\n                this.outputCache = [];\n            }\n            // Send current batch\n            this._storeLogs(this.queue);\n        } else {\n            this.outputCache.push(this.queue);\n        }\n\n        this.queue = [];\n        this.totalLen = 0;\n    }\n\n    if (reschedule) {\n        this._reschedulePublishInterval();\n    }\n};\n\n/**\n * Stops the periodical \"store logs\" task and immediately stores any pending\n * log entries as a batch.\n */\nLogCollector.prototype.stop = function() {\n    // Flush and stop publishing logs\n    this._flush(false /* do not force */, false /* do not reschedule */);\n};\n\nmodule.exports = LogCollector;\n","/* Copyright @ 2015-present 8x8, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/*jslint latedef:false*/\n\n/**\n * Ordered log levels.\n */\nvar levels = {\n    \"trace\": 0,\n    \"debug\": 1,\n    \"info\": 2,\n    \"log\": 3,\n    \"warn\": 4,\n    \"error\": 5\n};\n\n/**\n * The default transport - console\n * @type LoggerTransport\n */\nLogger.consoleTransport = console;\n\n/**\n * The array which stores currently registered global transports.\n * @type {[LoggerTransport]}\n */\nvar globalTransports = [ Logger.consoleTransport ];\n\n/**\n * Adds given {@link LoggerTransport} instance to the list of global\n * transports which means that it'll be used by all {@link Logger}s\n * @param {LoggerTransport} transport\n */\nLogger.addGlobalTransport = function(transport) {\n    if (globalTransports.indexOf(transport) === -1) {\n        globalTransports.push(transport);\n    }\n};\n\n/**\n * Removes given {@link LoggerTransport} instance from the list of global\n * transports\n * @param {LoggerTransport} transport\n */\nLogger.removeGlobalTransport = function(transport) {\n    var transportIdx = globalTransports.indexOf(transport);\n    if (transportIdx !== -1) {\n        globalTransports.splice(transportIdx, 1);\n    }\n};\n\n/**\n * The global configuration options.\n */\nvar globalOptions = {};\n\n/**\n * Sets global options which will be used by all loggers. Changing these works\n * even after other loggers are created.\n */\nLogger.setGlobalOptions = function(options) {\n    globalOptions = options || {};\n};\n\n/**\n * Parses Error's object stack trace and extracts information about the last\n * caller before the log method was called.\n * @returns JS object with info about the caller - method name, file location,\n * line and column.\n */\nfunction getCallerInfo() {\n    var callerInfo = {\n        methodName: \"\",\n        fileLocation: \"\",\n        line: null,\n        column: null\n    };\n    //gets the part of the stack without the logger wrappers\n    var error = new Error();\n    var stack = error.stack? error.stack.split(\"\\n\") : [];\n    if(!stack || stack.length < 3) {\n        return callerInfo;\n    }\n    var m = null;\n    if(stack[3]) {\n        m = stack[3].match(/\\s*at\\s*(.+?)\\s*\\((\\S*)\\s*:(\\d*)\\s*:(\\d*)\\)/);\n    }\n    if(!m || m.length <= 4) {\n        //Firefox && Safari\n        if(stack[2].indexOf(\"log@\") === 0){\n            //Safari\n            callerInfo.methodName = stack[3].substr(0, stack[3].indexOf(\"@\"));\n        } else {\n            //Firefox\n            callerInfo.methodName = stack[2].substr(0, stack[2].indexOf(\"@\"));\n        }\n        return callerInfo;\n    }\n\n    callerInfo.methodName = m[1];\n    callerInfo.fileLocation = m[2];\n    callerInfo.line = m[3];\n    callerInfo.column = m[4];\n    return callerInfo;\n}\n\n/**\n * Logs messages using the transports and level from the logger.\n * @param logger a logger instance.\n * @param level the log level of the message. See the levels variable.\n * @param arguments array with arguments that will be logged.\n */\nfunction log() {\n    var logger = arguments[0], level = arguments[1],\n        args = Array.prototype.slice.call(arguments, 2);\n    if(levels[level] < logger.level) {\n        return;\n    }\n\n    var callerInfo\n        = !(logger.options.disableCallerInfo || globalOptions.disableCallerInfo) &&\n            getCallerInfo();\n    var transports = globalTransports.concat(logger.transports);\n    for(var i = 0; i < transports.length; i++) {\n        var t = transports[i];\n        var l = t[level];\n        if(l && typeof(l) === \"function\") {\n            var logPrefixes = [];\n\n            logPrefixes.push(new Date().toISOString());\n\n            if (logger.id) {\n                logPrefixes.push(\"[\" + logger.id + \"]\");\n            }\n\n            if (callerInfo && callerInfo.methodName.length > 1) {\n                logPrefixes.push(\"<\" + callerInfo.methodName + \">: \");\n            }\n\n            var fullLogParts = logPrefixes.concat(args);\n\n            try {\n                l.bind(t).apply(t, fullLogParts);\n            } catch (error) {\n                // It would be nice to send the error to the logger but this could send us into an endless loop.\n                // That's why we use only console for logging here.\n                console.error(\"An error occured when trying to log with one of the available transports\", error);\n            }\n        }\n    }\n}\n\n/**\n *\n * Constructs new logger object.\n * @param level the logging level for the new logger\n * @param id optional identifier for the logger instance.\n * @param {LoggerTransport} transports optional list of handlers(objects) for\n * the logs. The handlers must support - log, warn, error, debug, info, trace.\n * @param options optional configuration file for how the logger should behave.\n * @param {boolean} options.disableCallerInfo Whether the call site of a logger\n * method invocation should be included in the log. Defaults to false, so the\n * call site will be included.\n */\nfunction Logger(level, id, transports, options) {\n    this.id = id;\n    this.options = options || {};\n    this.transports = transports;\n    if(!this.transports) {\n        this.transports = [];\n    }\n    this.level = levels[level];\n    var methods = Object.keys(levels);\n    for(var i = 0; i < methods.length; i++){\n        this[methods[i]] =\n            log.bind(null, this, methods[i]);\n    }\n}\n\n/**\n * Sets the log level for the logger.\n * @param level the new log level.\n */\nLogger.prototype.setLevel = function (level) {\n    this.level = levels[level];\n};\nmodule.exports = Logger;\n\n/**\n * Enum for the supported log levels.\n */\nLogger.levels = {\n    TRACE: \"trace\",\n    DEBUG: \"debug\",\n    INFO: \"info\",\n    LOG: \"log\",\n    WARN: \"warn\",\n    ERROR: \"error\"\n};\n","/* Copyright @ 2015-present 8x8, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nvar Logger = require(\"./Logger\");\nvar LogCollector = require(\"./LogCollector\");\n\n/**\n * Definition of the log method\n * @name log_method\n * @function\n * @param {...*} log_args the arguments to be logged\n */\n/**\n * The logger's transport type definition.\n *\n * @typedef {object} LoggerTransport\n *\n * @property {log_method} trace method called to log on {@link Logger.levels.TRACE} logging level\n * @property {log_method} debug method called to log on {@link Logger.levels.DEBUG} logging level\n * @property {log_method} info method called to log on {@link Logger.levels.INFO} logging level\n * @property {log_method} log method called to log on {@link Logger.levels.LOG} logging level\n * @property {log_method} warn method called to log on {@link Logger.levels.WARN} logging level\n * @property {log_method} error method called to log on {@link Logger.levels.ERROR} logging level\n */\n\n/**\n * Map with the created loggers with ID.\n */\nvar idLoggers = {};\n\n/**\n * Array with the loggers without id.\n */\nvar loggers = [];\n\n/**\n * Log level for the lbrary.\n */\nvar curLevel = Logger.levels.TRACE;\n\n\nmodule.exports = {\n    /**\n     * Adds given {@link LoggerTransport} instance to the list of global\n     * transports which means that it'll be used by all {@link Logger}s\n     * @param {LoggerTransport} transport\n     */\n    addGlobalTransport: function(transport) {\n        Logger.addGlobalTransport(transport);\n    },\n    /**\n     * Removes given {@link LoggerTransport} instance from the list of global\n     * transports\n     * @param {LoggerTransport} transport\n     */\n    removeGlobalTransport: function(transport) {\n        Logger.removeGlobalTransport(transport);\n    },\n    /**\n    * Sets global options which will be used by all loggers. Changing these\n    * works even after other loggers are created.\n    */\n    setGlobalOptions: function(options) {\n        Logger.setGlobalOptions(options);\n    },\n    /**\n     * Creates new logger.\n     * @arguments the same as Logger constructor\n     */\n    getLogger: function(id, transports, options) {\n        var logger = new Logger(curLevel, id, transports, options);\n        if(id) {\n            idLoggers[id] = idLoggers[id] || [];\n            idLoggers[id].push(logger);\n        } else {\n            loggers.push(logger);\n        }\n        return logger;\n    },\n    /**\n     * Creates a new Logger, without keeping track of it in the loggers list\n     * @arguments the same as Logger constructor\n     */\n    getUntrackedLogger: function(id, transports, options) {\n        return new Logger(curLevel, id, transports, options);\n    },\n    /**\n     * Changes the log level for the existing loggers by id.\n     * @param level the new log level.\n     * @param id if specified the level will be changed only for loggers with the\n     * same id. Otherwise the operation will affect all loggers that don't\n     * have id.\n     */\n    setLogLevelById: function(level, id) {\n        var l = id? (idLoggers[id] || []) : loggers;\n        for(var i = 0; i < l.length; i++) {\n            l[i].setLevel(level);\n        }\n    },\n    /**\n     * Changes the log level for all existing loggers.\n     * @param level the new log level.\n     */\n    setLogLevel: function (level) {\n        curLevel = level;\n        var i = 0;\n        for(; i < loggers.length; i++) {\n            loggers[i].setLevel(level);\n        }\n\n        for(var id in idLoggers) {\n            var l = idLoggers[id] || [];\n            for(i = 0; i < l.length; i++) {\n                l[i].setLevel(level);\n            }\n        }\n    },\n    /**\n     * The supported log levels.\n     */\n    levels: Logger.levels,\n    /**\n     * Exports the <tt>LogCollector</tt>.\n     */\n    LogCollector: LogCollector\n};\n","(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"watchRTC\"] = factory();\n\telse\n\t\troot[\"watchRTC\"] = factory();\n})(this, function() {\nreturn ","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.addStateListener = exports.persistentStart = exports.persistentEnd = exports.addStatsListener = exports.disconnect = exports.connect = exports.mapTrack = exports.mapStream = exports.addEvent = exports.enableDataCollection = exports.disableDataCollection = exports.addKeys = exports.setUserRating = exports.addTags = exports.setConfig = exports.init = void 0;\nrequire(\"./types\");\nvar sdk_1 = require(\"./sdk\");\n/**\n * Initialize SDK. Can be called multiple times but it will be initialized only at the first time.\n * Use 'setConfig' function after if you don't have rtcRoomId and rtcPeerId yet.\n * @param watchrtc\n * @param prefixesToWrap\n * @param services\n */\nvar init = function (watchrtcConfig, services) {\n    (0, sdk_1.initSDK)((watchrtcConfig || {}), [\"\"], services);\n};\nexports.init = init;\n/**\n * You also can use watchRTC.setConfig function to set watchRTC configuration after calling init()\n * and before the creation of RTCPeerConnection objects\n */\nvar setConfig = function (watchrtcConfig) {\n    (0, sdk_1.setConfig)(watchrtcConfig);\n};\nexports.setConfig = setConfig;\n/**\n * @deprecated Tags no longer supported. Use addKeys instead\n * Add tags for peer session\n * @param rtcTags[]\n */\nvar addTags = function (\n/** [\"tag1\", \"tag2\", \"tag3\"] */\n_rtcTags) { };\nexports.addTags = addTags;\n/**\n * Set user rating and/or comment for peer session\n * @param rating number from 1 to 5\n * @param comment string\n */\nvar setUserRating = function (\n/** 1 | 2 | 3 | 4 | 5 */\nrating, comment) {\n    (0, sdk_1.setUserRating)(rating, comment);\n};\nexports.setUserRating = setUserRating;\n/**\n * Add keys for peer session\n * @param keys\n */\nvar addKeys = function (\n/** { \"key1\": \"value1\", \"key2\": [\"value2_1\", \"value2_2\"]} */\nkeys) {\n    (0, sdk_1.addKeys)(keys);\n};\nexports.addKeys = addKeys;\n/**\n * Disables data collection\n */\nvar disableDataCollection = function () {\n    (0, sdk_1.disableDataCollection)();\n};\nexports.disableDataCollection = disableDataCollection;\n/**\n * Enables data collection\n */\nvar enableDataCollection = function () {\n    (0, sdk_1.enableDataCollection)();\n};\nexports.enableDataCollection = enableDataCollection;\nvar addEvent = function (event) {\n    (0, sdk_1.addEvent)(event);\n};\nexports.addEvent = addEvent;\n/**\n * Map an incoming stream with a human-readable name\n * @param id The identifier of the stream (streamIdentifier attribute)\n * @param name The human-readable name\n * @deprecated\n */\nvar mapStream = function (id, name) {\n    (0, sdk_1.mapStream)(id, name);\n};\nexports.mapStream = mapStream;\n/**\n * Map an incoming track with a human-readable name\n * @param id The identifier of the track (trackIdentifier attribute)\n * @param name The human-readable name\n */\nvar mapTrack = function (id, name) {\n    (0, sdk_1.mapTrack)(id, name);\n};\nexports.mapTrack = mapTrack;\nvar connect = function () {\n    (0, sdk_1.connect)();\n};\nexports.connect = connect;\nvar disconnect = function () {\n    (0, sdk_1.disconnect)();\n};\nexports.disconnect = disconnect;\nvar addStatsListener = function (listener) {\n    (0, sdk_1.registerOnStatsListener)(listener);\n};\nexports.addStatsListener = addStatsListener;\nvar persistentEnd = function (nailUpCallEnd) {\n    (0, sdk_1.persistentEnd)(nailUpCallEnd);\n};\nexports.persistentEnd = persistentEnd;\nvar persistentStart = function (roomId, peerId) {\n    (0, sdk_1.persistentStart)(roomId, peerId);\n};\nexports.persistentStart = persistentStart;\nvar addStateListener = function (listener) {\n    (0, sdk_1.registerStateListener)(listener);\n};\nexports.addStateListener = addStateListener;\nexports.default = {\n    /**\n     * Initialize SDK. Can be called multiple times but it will be initialized only at the first time.\n     * Use 'setConfig' function after if you don't have rtcRoomId and rtcPeerId yet.\n     * @param watchrtc\n     * @param prefixesToWrap\n     */\n    init: exports.init,\n    /**\n     * @deprecated Tags no longer supported. Use addKeys instead\n     * Add tags for peer session\n     * @param rtcTags[]\n     */\n    addTags: exports.addTags,\n    /**\n     * Set user rating and/or comment for peer session\n     * @param rating number from 1 to 5\n     * @param comment string\n     */\n    setUserRating: exports.setUserRating,\n    /**\n     * Add keys for peer session\n     * @param keys\n     */\n    addKeys: exports.addKeys,\n    /**\n     * You also can use watchRTC.setConfig function to set watchRTC configuration after calling init()\n     * and before the creation of RTCPeerConnection objects\n     */\n    setConfig: exports.setConfig,\n    /**\n     * Disables data collection\n     */\n    disableDataCollection: exports.disableDataCollection,\n    /**\n     * Enables data collection\n     */\n    enableDataCollection: exports.enableDataCollection,\n    addEvent: exports.addEvent,\n    /**\n     * Map an incoming stream with a human-readable name\n     * @param id The identifier of the stream (streamIdentifier attribute)\n     * @param name The human-readable name\n     * @deprecated\n     */\n    mapStream: exports.mapStream,\n    /**\n     * Map an incoming track with a human-readable name\n     * @param id The identifier of the track (trackIdentifier attribute)\n     * @param name The human-readable name\n     */\n    mapTrack: exports.mapTrack,\n    connect: exports.connect,\n    disconnect: exports.disconnect,\n    addStatsListener: exports.addStatsListener,\n    persistentEnd: exports.persistentEnd,\n    persistentStart: exports.persistentStart,\n    addStateListener: exports.addStateListener,\n    qualityrtc: {\n        run: sdk_1.qrtcRun,\n        stop: sdk_1.qrtcStop,\n    },\n};\n","\"use strict\";\nvar __assign = (this && this.__assign) || function () {\n    __assign = Object.assign || function(t) {\n        for (var s, i = 1, n = arguments.length; i < n; i++) {\n            s = arguments[i];\n            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))\n                t[p] = s[p];\n        }\n        return t;\n    };\n    return __assign.apply(this, arguments);\n};\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n    return new (P || (P = Promise))(function (resolve, reject) {\n        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n        function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n        step((generator = generator.apply(thisArg, _arguments || [])).next());\n    });\n};\nvar __generator = (this && this.__generator) || function (thisArg, body) {\n    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\n    return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\n    function verb(n) { return function (v) { return step([n, v]); }; }\n    function step(op) {\n        if (f) throw new TypeError(\"Generator is already executing.\");\n        while (g && (g = 0, op[0] && (_ = 0)), _) try {\n            if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\n            if (y = 0, t) op = [op[0] & 2, t.value];\n            switch (op[0]) {\n                case 0: case 1: t = op; break;\n                case 4: _.label++; return { value: op[1], done: false };\n                case 5: _.label++; y = op[1]; op = [0]; continue;\n                case 7: op = _.ops.pop(); _.trys.pop(); continue;\n                default:\n                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\n                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\n                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\n                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\n                    if (t[2]) _.ops.pop();\n                    _.trys.pop(); continue;\n            }\n            op = body.call(thisArg, _);\n        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\n        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\n    }\n};\nvar __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {\n    if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {\n        if (ar || !(i in from)) {\n            if (!ar) ar = Array.prototype.slice.call(from, 0, i);\n            ar[i] = from[i];\n        }\n    }\n    return to.concat(ar || Array.prototype.slice.call(from));\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.qrtcStop = exports.qrtcRun = exports.persistentStart = exports.persistentEnd = exports.registerStateListener = exports.registerOnStatsListener = exports.disconnect = exports.connect = exports.mapTrack = exports.mapStream = exports.addEvent = exports.enableDataCollection = exports.disableDataCollection = exports.addKeys = exports.setUserRating = exports.setConfig = exports.initSDK = exports.sdkLogWithoutTrace = exports.sdkLog = void 0;\nvar watchrtcsocket_1 = require(\"./watchrtcsocket\");\nvar watchrtchttp_1 = require(\"./watchrtchttp\");\nvar utils_1 = require(\"./utils\");\nvar version_1 = require(\"./version\");\nvar isBrowser = typeof window !== \"undefined\";\nvar globalContext = isBrowser ? window : global;\nvar standardGetstats = true;\nvar isFirefox = isBrowser ? !!globalContext.mozRTCPeerConnection : false;\nvar isSafari = isBrowser\n    ? !isFirefox && globalContext.RTCPeerConnection && !globalContext.navigator.webkitGetUserMedia\n    : false;\n// Data structure for RTCPeerConnection related stuff we need\nvar openChannels = {};\nvar peerconnectioncounter = 0;\nvar connectionData = {};\nvar watchrtcIdentifiers = {\n    rtcRoomId: undefined,\n    rtcPeerId: undefined,\n    projectId: undefined,\n};\nvar watchrtcConfig = null;\nvar http = null;\nvar socket = null;\nvar trace;\nvar lastConnectionOpen = 0; // so we know when was the last active connection seen\nvar getStatsInterval;\nvar tryingToConnectSocket = false;\nvar hardwareInfo;\nvar currentAudioOutputId;\nvar authFailed = false;\nvar reconnectTimerId;\nvar lostConnectionTs = 0;\nvar isManualConnect = false;\nvar isManualDisconnect = false;\nvar getStatsCallback = null;\nvar stateListener = null;\nvar freshConnection = true;\nexports.sdkLog = (0, utils_1.getSdkLogger)(function () { return watchrtcConfig === null || watchrtcConfig === void 0 ? void 0 : watchrtcConfig.logLevel; });\nexports.sdkLogWithoutTrace = (0, utils_1.getSdkLogWithoutTrace)(function () { return watchrtcConfig === null || watchrtcConfig === void 0 ? void 0 : watchrtcConfig.logLevel; });\nvar debugTrack = function (track) {\n    if (track) {\n        return \"\".concat(track.kind, \":\").concat(track.id, \" state:\").concat(track.readyState, \" muted:\").concat(track.muted, \" label:\").concat(track.label);\n    }\n    return \"no track\";\n};\n// Data structure for storing and applying mapTrack\nvar mappedTrack = {};\nvar maybeOpenWebsocketConnection = function (_a) {\n    var _b;\n    var _c = _a.forceRecreate, forceRecreate = _c === void 0 ? false : _c, _d = _a.reconnecting, reconnecting = _d === void 0 ? false : _d, _e = _a.pcId, pcId = _e === void 0 ? \"PC_unknown\" : _e, _f = _a.nailUp, nailUp = _f === void 0 ? false : _f;\n    if (socket === null || socket === void 0 ? void 0 : socket.isDisabledDataCollection()) {\n        (0, exports.sdkLog)(\"debug\", \"maybeOpenWebsocketConnection. disabledDataCollection, ignore [\".concat(pcId, \"]\"));\n        return;\n    }\n    (0, exports.sdkLog)(\"debug\", \"maybeOpenWebsocketConnection called: [\".concat(pcId, \"]\"), {\n        forceRecreate: forceRecreate,\n        reconnecting: reconnecting,\n        isManualDisconnect: isManualDisconnect,\n        isManualConnect: isManualConnect,\n        tryingToConnectSocket: tryingToConnectSocket,\n        watchrtcConfig: JSON.stringify(watchrtcConfig),\n        disabled: socket === null || socket === void 0 ? void 0 : socket.isDisabledDataCollection(),\n        openChannels: JSON.stringify(openChannels),\n    });\n    isManualDisconnect = false;\n    var opened = ((_b = socket === null || socket === void 0 ? void 0 : socket.connection) === null || _b === void 0 ? void 0 : _b.readyState) === globalContext.WebSocket.OPEN;\n    if (opened) {\n        var roomIdOrPeerIdChanged = (0, utils_1.isRoomIdOrPeerIdChanged)(watchrtcIdentifiers, watchrtcConfig);\n        if (roomIdOrPeerIdChanged && forceRecreate) {\n            (0, exports.sdkLog)(\"debug\", \"maybeOpenWebsocketConnection. Closing WS connection. [\".concat(pcId, \"]\"));\n            socket === null || socket === void 0 ? void 0 : socket.close();\n        }\n        else {\n            (0, exports.sdkLog)(\"debug\", \"maybeOpenWebsocketConnection. WS connection already opened [\".concat(pcId, \"]\"));\n            return;\n        }\n    }\n    var connectionCount = (0, utils_1.countOfValidConnections)(openChannels);\n    if (!isManualConnect && connectionCount < 1 && !tryingToConnectSocket) {\n        (0, exports.sdkLog)(\"debug\", \"maybeOpenWebsocketConnection. WS connection not opened - previous connect call not finished or missing peer connection [\".concat(pcId, \"]\"), {\n            openChannels: JSON.stringify(openChannels),\n            connectionCount: connectionCount,\n            tryingToConnectSocket: tryingToConnectSocket,\n            isManualConnect: isManualConnect,\n        });\n        return;\n    }\n    var canConnect = (0, utils_1.validateConfig)(watchrtcConfig);\n    var id = Object.keys(openChannels)[connectionCount - 1]; // not very critical, but for consistency with trace\n    if (!canConnect) {\n        tryingToConnectSocket = false;\n        (0, exports.sdkLog)(\"debug\", \"maybeOpenWebsocketConnection. WS connection not opened - invalid config [\".concat(pcId, \"]\"), {\n            watchrtcConfig: watchrtcConfig,\n        });\n        return;\n    }\n    if (watchrtcConfig.keys) {\n        Object.keys(watchrtcConfig.keys || {}).forEach(function (k) {\n            if (typeof watchrtcConfig.keys[k] === \"string\") {\n                watchrtcConfig.keys[k] = [watchrtcConfig.keys[k]];\n            }\n        });\n    }\n    var useToken = !!watchrtcConfig.rtcToken;\n    var wsConnectionData = (0, utils_1.getConnectionData)(\"ws\", useToken ? watchrtcConfig.rtcToken : watchrtcConfig.rtcApiKey, watchrtcConfig.proxyUrl);\n    if (!socket) {\n        (0, exports.sdkLog)(\"debug\", \"maybeOpenWebsocketConnection. WS socket wasn't initialized [\".concat(pcId, \"]\"));\n    }\n    tryingToConnectSocket = true;\n    lastConnectionOpen = Date.now();\n    (0, exports.sdkLog)(\"debug\", \"maybeOpenWebsocketConnection. Opening websocket connection [\".concat(pcId, \"]\"));\n    startStatsCollection(nailUp);\n    var wsOpeningTimestamp = Date.now();\n    socket === null || socket === void 0 ? void 0 : socket.connect({\n        url: \"\".concat(wsConnectionData.url, \"?\").concat(useToken ? \"token\" : \"apiKey\", \"=\").concat(wsConnectionData.key, \"&timestamp=\").concat(Date.now()),\n        options: { cleanOldTraces: freshConnection },\n        onData: function (data) {\n            var _a;\n            for (var _i = 0, _b = Object.entries(data); _i < _b.length; _i++) {\n                var _c = _b[_i], key = _c[0], value = _c[1];\n                connectionData[key] = value;\n            }\n            watchrtcIdentifiers.projectId = data.projectId;\n            tryingToConnectSocket = false;\n            watchrtcConfig.allowBrowserLogCollection = Boolean(data.collectConsoleLogEnabled);\n            if (!watchrtcConfig.allowBrowserLogCollection) {\n                (0, utils_1.restoreOriginalConsoleMethods)();\n                // clean up collected logs from socket buffer\n                if (socket === null || socket === void 0 ? void 0 : socket.buffer) {\n                    socket.buffer = socket.buffer.filter(function (data) { return data[0] !== \"log\"; });\n                }\n            }\n            else {\n                if (!((_a = watchrtcConfig === null || watchrtcConfig === void 0 ? void 0 : watchrtcConfig.console) === null || _a === void 0 ? void 0 : _a.override) && data.collectConsoleLogLevel) {\n                    (0, utils_1.setConsoleLevel)(data.collectConsoleLogLevel, trace);\n                }\n            }\n            (0, exports.sdkLog)(\"info\", \"Connection established. watchRTCConnectionId: \".concat(data.connectionId, \" sdkVersion:\").concat(version_1.default, \" [\").concat(pcId, \"]\"));\n            if (data.interval !== watchrtcConfig.collectionInterval) {\n                var oldInterval = watchrtcConfig.collectionInterval;\n                watchrtcConfig.collectionInterval = data.interval;\n                resetConnectionState();\n                startStatsCollection();\n                (0, exports.sdkLog)(\"error\", \"Collection interval mismatch - connection state reset\");\n                trace({ data: [\"collectionIntervalChange\", null, { oldInterval: oldInterval }] });\n            }\n            trace({ data: [\"watchrtc\", id, __assign(__assign(__assign({}, watchrtcConfig), data), { sdkVersion: version_1.default })] });\n            if (reconnecting) {\n                (0, exports.sdkLog)(\"debug\", \"websocket onData reconnecting\");\n                trace({ data: [\"reconnect\", null, null] });\n            }\n            if (hardwareInfo) {\n                trace({ data: [\"hardware\", null, hardwareInfo] });\n            }\n            trace({ data: [\"sessionId\", null, globalContext.watchRTCSessionId] });\n        },\n        onError: function (_, type) {\n            (0, exports.sdkLog)(\"debug\", \"websocket onError \".concat(type));\n            if (type === \"auth\") {\n                authFailed = true;\n            }\n            tryingToConnectSocket = false;\n            lastConnectionOpen = 0;\n        },\n        onOpen: function () {\n            freshConnection = false;\n            if (stateListener) {\n                stateListener({ connectionStatus: \"connected\" });\n            }\n            if (reconnecting) {\n                var reconnectDuration = Date.now() - lostConnectionTs;\n                trace({ data: [\"reconnectDuration\", null, reconnectDuration] });\n            }\n            authFailed = false;\n            if (reconnectTimerId) {\n                clearInterval(reconnectTimerId);\n                reconnectTimerId = undefined;\n            }\n            var delta = Date.now() - wsOpeningTimestamp;\n            (0, exports.sdkLog)(\"debug\", \"maybeOpenWebsocketConnection. Connection opened. Opening time - \".concat(delta, \" ms [\").concat(pcId, \"]\"));\n        },\n        onClose: function (closeEvent) {\n            if (stateListener) {\n                stateListener({ connectionStatus: \"disconnected\" });\n            }\n            var code = closeEvent.code, reason = closeEvent.reason, wasClean = closeEvent.wasClean;\n            (0, exports.sdkLog)(\"debug\", \"close event. authFailed: \".concat(authFailed, \" code: \").concat(code, \" reason: \").concat(reason, \" wasClean: \").concat(wasClean, \" reconnectTimerId: \").concat(reconnectTimerId), { authFailed: authFailed, code: code, reason: reason, wasClean: wasClean, reconnectTimerId: reconnectTimerId });\n            if (authFailed) {\n                (0, exports.sdkLog)(\"debug\", \"websocket authFailed\");\n                if (reconnectTimerId) {\n                    clearInterval(reconnectTimerId);\n                }\n            }\n            else if (!reconnectTimerId && !isManualDisconnect) {\n                (0, exports.sdkLog)(\"debug\", \"websocket onClose reconnecting\");\n                lostConnectionTs = Date.now();\n                maybeOpenWebsocketConnection({ reconnecting: true, pcId: pcId });\n                reconnectTimerId = setInterval(function () {\n                    maybeOpenWebsocketConnection({ reconnecting: true, pcId: pcId });\n                }, 30 * 1000);\n            }\n        },\n    });\n};\nvar startStatsCollection = function (nailUp) {\n    if (nailUp === void 0) { nailUp = false; }\n    globalContext.clearInterval(getStatsInterval);\n    if (nailUp) {\n        (0, exports.sdkLog)(\"debug\", \"startStatsCollection - nail up\");\n        var _loop_1 = function (pcInfo) {\n            if (pcInfo.pc.signalingState !== \"closed\") {\n                pcInfo.pc.getStats(null).then(function (res) {\n                    var now = {};\n                    if (standardGetstats || isFirefox || isSafari) {\n                        if (isFirefox) {\n                            res.forEach(function (report) {\n                                now[\"\".concat(report.type, \"_\").concat(report.id)] = report;\n                            });\n                        }\n                        else {\n                            now = (0, utils_1.map2obj)(res);\n                        }\n                    }\n                    else {\n                        now = (0, utils_1.mangleChromeStats)(pcInfo.pc, res);\n                    }\n                    pcInfo.nailUpRef = JSON.parse(JSON.stringify(now));\n                });\n            }\n        };\n        // collect the new reference reports to use\n        for (var _i = 0, _a = Object.values(openChannels); _i < _a.length; _i++) {\n            var pcInfo = _a[_i];\n            _loop_1(pcInfo);\n        }\n    }\n    getStatsInterval = globalContext.setInterval(function () {\n        return __awaiter(this, void 0, void 0, function () {\n            var stats, _i, _a, pcInfo, _b, peer, streams;\n            return __generator(this, function (_c) {\n                switch (_c.label) {\n                    case 0:\n                        if (!(!isManualConnect && (0, utils_1.countOfValidConnections)(openChannels) === 0)) return [3 /*break*/, 1];\n                        if (watchrtcConfig === null || watchrtcConfig === void 0 ? void 0 : watchrtcConfig.logGetStats) {\n                            (0, exports.sdkLog)(\"debug\", \"getStatsInterval. No valid connections at this time\");\n                        }\n                        // if we don't have any connection for 20 sec we can close the socket\n                        if (lastConnectionOpen && lastConnectionOpen + 20000 < Date.now()) {\n                            freshConnection = true;\n                            globalContext.clearInterval(getStatsInterval);\n                            socket === null || socket === void 0 ? void 0 : socket.close();\n                            (0, exports.sdkLog)(\"info\", \"Last connection closed. watchRTCConnectionId: \".concat(connectionData === null || connectionData === void 0 ? void 0 : connectionData.connectionId, \" sdkVersion: \").concat(version_1.default));\n                        }\n                        return [3 /*break*/, 6];\n                    case 1:\n                        lastConnectionOpen = Date.now();\n                        stats = { connections: {}, streams: {} };\n                        _i = 0, _a = Object.values(openChannels);\n                        _c.label = 2;\n                    case 2:\n                        if (!(_i < _a.length)) return [3 /*break*/, 5];\n                        pcInfo = _a[_i];\n                        if (watchrtcConfig === null || watchrtcConfig === void 0 ? void 0 : watchrtcConfig.logGetStats) {\n                            (0, exports.sdkLogWithoutTrace)(\"debug\", \"getStatsInterval. \".concat(pcInfo.id, \" signalingState: \").concat(pcInfo.pc.signalingState));\n                        }\n                        if (!(pcInfo.pc.signalingState !== \"closed\")) return [3 /*break*/, 4];\n                        return [4 /*yield*/, getStats(pcInfo)];\n                    case 3:\n                        _b = _c.sent(), peer = _b.peer, streams = _b.streams;\n                        stats.connections = __assign(__assign({}, stats.connections), peer);\n                        stats.streams = __assign(__assign({}, stats.streams), streams);\n                        _c.label = 4;\n                    case 4:\n                        _i++;\n                        return [3 /*break*/, 2];\n                    case 5:\n                        if (getStatsCallback) {\n                            getStatsCallback(stats);\n                        }\n                        _c.label = 6;\n                    case 6: return [2 /*return*/];\n                }\n            });\n        });\n    }, watchrtcConfig.collectionInterval);\n};\nvar getStats = function (pcInfo) {\n    return new Promise(function (resolve, __reject) {\n        if (pcInfo) {\n            var id_1 = pcInfo.id, pc_1 = pcInfo.pc, prev_1 = pcInfo.prev, nailUpRef_1 = pcInfo.nailUpRef;\n            if (standardGetstats || isFirefox || isSafari) {\n                pc_1.getStats(null).then(function (res) {\n                    if (watchrtcConfig === null || watchrtcConfig === void 0 ? void 0 : watchrtcConfig.logGetStats) {\n                        (0, exports.sdkLogWithoutTrace)(\"debug\", \"getStats res\", { res: res });\n                    }\n                    var now = {};\n                    if (isFirefox) {\n                        res.forEach(function (report) {\n                            now[\"\".concat(report.type, \"_\").concat(report.id)] = report;\n                        });\n                    }\n                    else {\n                        now = (0, utils_1.map2obj)(res);\n                    }\n                    var base = JSON.parse(JSON.stringify(now)); // our new prev\n                    now = (0, utils_1.applyPatchForRTT)(prev_1, now);\n                    if (nailUpRef_1) {\n                        now = (0, utils_1.subtractNailUpReferenceStats)(nailUpRef_1, now);\n                    }\n                    var data = (0, utils_1.deltaCompression)(prev_1, now);\n                    if (watchrtcConfig === null || watchrtcConfig === void 0 ? void 0 : watchrtcConfig.logGetStats) {\n                        (0, exports.sdkLogWithoutTrace)(\"debug\", \"getStats(null) [\".concat(id_1, \"]\"), { data: data });\n                    }\n                    if ((data === null || data === void 0 ? void 0 : data.timestamp) !== null && (data === null || data === void 0 ? void 0 : data.timestamp) !== -Infinity) {\n                        trace({ data: [\"getstats\", id_1, data] });\n                    }\n                    pcInfo.prev = base;\n                    resolve((0, utils_1.exposeApplicationStatsForPC)(id_1, prev_1, now, mappedTrack));\n                });\n            }\n            else {\n                pc_1.getStats(function (res) {\n                    var now = (0, utils_1.mangleChromeStats)(pc_1, res);\n                    var base = JSON.parse(JSON.stringify(now)); // our new prev\n                    if (nailUpRef_1) {\n                        now = (0, utils_1.subtractNailUpReferenceStats)(nailUpRef_1, now);\n                    }\n                    var data = (0, utils_1.deltaCompression)(prev_1, now);\n                    if (watchrtcConfig === null || watchrtcConfig === void 0 ? void 0 : watchrtcConfig.logGetStats) {\n                        (0, exports.sdkLogWithoutTrace)(\"debug\", \"getStats() [\".concat(id_1, \"]\"), { data: data });\n                    }\n                    if ((data === null || data === void 0 ? void 0 : data.timestamp) !== null && (data === null || data === void 0 ? void 0 : data.timestamp) !== -Infinity) {\n                        trace({ data: [\"getstats\", id_1, data] });\n                    }\n                    pcInfo.prev = base;\n                    resolve((0, utils_1.exposeApplicationStatsForPC)(id_1, prev_1, now, mappedTrack));\n                });\n            }\n        }\n    });\n};\nvar getHardware = function () {\n    setTimeout(function () {\n        // if get hardware take more than 50 ms then do not save it\n        var getHardwareStartTime = Date.now();\n        (0, utils_1.getHardwareInfo)()\n            .then(function (hwInfo) {\n            var getHardwareTime = Date.now() - getHardwareStartTime;\n            if (getHardwareTime <= 50000) {\n                hardwareInfo = hwInfo;\n                (0, exports.sdkLog)(\"debug\", \"getHardware\", { hardwareInfo: hardwareInfo });\n            }\n            else {\n                (0, exports.sdkLog)(\"debug\", \"getHardware failure: getHardwareTime: \".concat(getHardwareTime), { hardwareInfo: hardwareInfo });\n            }\n        })\n            .catch(function (err) {\n            (0, exports.sdkLog)(\"error\", \"Error. Get hardware info: \".concat(err.message));\n        });\n    }, 0);\n};\n/**\n * Initialize SDK.\n * @param watchrtc\n * @param prefixesToWrap\n * @param services\n */\nvar initSDK = function (watchrtc, prefixesToWrap, services) {\n    var _a, _b;\n    var initialized = globalContext.watchRTCInitialized;\n    if (initialized) {\n        (0, exports.sdkLogWithoutTrace)(\"info\", \"init. watchRTC SDK already has been initialized\");\n        return;\n    }\n    if (!globalContext.RTCPeerConnection) {\n        (0, exports.sdkLogWithoutTrace)(\"info\", \"init. RTCPeerConnection does not exist in global globalContext\");\n        return;\n    }\n    var isRTCPeerConnectionNative = globalContext.RTCPeerConnection.toString().indexOf(\"[native code]\") !== -1;\n    if (!isRTCPeerConnectionNative && isBrowser) {\n        (0, exports.sdkLog)(\"info\", \"init. RTCPeerConnection object has been already overridden\");\n    }\n    globalContext.watchRTCInitialized = true;\n    globalContext.watchRTCSessionId = (0, utils_1.generateID)();\n    getHardware();\n    if (isBrowser) {\n        var urlParams = new URLSearchParams(location.search);\n        if (urlParams.has(\"watchrtc\") && urlParams.get(\"watchrtc\") === \"debug\") {\n            watchrtc.logLevel = \"debug\";\n        }\n    }\n    socket = (services === null || services === void 0 ? void 0 : services.socketService) || new watchrtcsocket_1.default();\n    http = (services === null || services === void 0 ? void 0 : services.httpService) || new watchrtchttp_1.default();\n    watchrtc.collectionInterval = (_a = watchrtc.collectionInterval) !== null && _a !== void 0 ? _a : 8000;\n    watchrtc.logLevel = watchrtc.logLevel || \"debug\";\n    watchrtcConfig = watchrtc;\n    watchrtcIdentifiers.rtcRoomId = watchrtcConfig.rtcRoomId;\n    watchrtcIdentifiers.rtcPeerId = watchrtcConfig.rtcPeerId;\n    trace = socket.trace;\n    if (watchrtcConfig.wsUrl) {\n        (0, exports.sdkLog)(\"info\", \"\\\"wsUrl\\\" config property is deprecated. Use \\\"proxyUrl\\\" instead of it\");\n    }\n    if (watchrtcConfig.proxyUrl) {\n        (0, exports.sdkLog)(\"info\", \"\\\"proxyUrl\\\" is used\");\n    }\n    if (watchrtcConfig === null || watchrtcConfig === void 0 ? void 0 : watchrtcConfig.debug) {\n        (0, exports.sdkLog)(\"info\", \"\\\"debug\\\" config property is deprecated. Use \\\"logLevel\\\" instead of it\");\n    }\n    prefixesToWrap.forEach(function (prefix) {\n        if (!globalContext[prefix + \"RTCPeerConnection\"]) {\n            (0, exports.sdkLog)(\"debug\", \"RTCPeerConnection prefixes override failed\");\n            return;\n        }\n        var origPeerConnection = globalContext[prefix + \"RTCPeerConnection\"];\n        var peerconnection = function (config, constraints) {\n            if (config === null || config === void 0 ? void 0 : config.watchrtc) {\n                watchrtcConfig = __assign(__assign({}, watchrtcConfig), config.watchrtc);\n                watchrtcIdentifiers.rtcRoomId = watchrtcConfig.rtcRoomId;\n                watchrtcIdentifiers.rtcPeerId = watchrtcConfig.rtcPeerId;\n            }\n            var pc = new origPeerConnection(config, constraints);\n            var id = \"PC_\" + peerconnectioncounter++;\n            pc.__rtcStatsId = id;\n            openChannels[id] = {\n                id: id,\n                pc: pc,\n                validConnection: false,\n            };\n            if (!config) {\n                config = { nullConfig: true };\n            }\n            config = JSON.parse(JSON.stringify(config)); // deepcopy\n            // don't log credentials\n            ((config && config.iceServers) || []).forEach(function (server) {\n                delete server.credential;\n            });\n            if (config === null || config === void 0 ? void 0 : config.watchrtc) {\n                delete config.watchrtc;\n            }\n            if (isFirefox) {\n                config.browserType = \"moz\";\n            }\n            else {\n                config.browserType = \"webkit\";\n            }\n            (0, exports.sdkLog)(\"debug\", \"new RTCPeerConnection called.\", {\n                config: JSON.stringify(config),\n                constraints: constraints,\n            });\n            trace({ data: [\"create\", id, config] });\n            // TODO: do we want to log constraints here? They are chrome-proprietary.\n            // http://stackoverflow.com/questions/31003928/what-do-each-of-these-experimental-goog-rtcpeerconnectionconstraints-do\n            if (constraints) {\n                trace({ data: [\"constraints\", id, constraints] });\n            }\n            pc.addEventListener(\"icecandidate\", function (e) {\n                (0, exports.sdkLog)(\"debug\", \"onicecandidate id:[\".concat(id, \"], candidate:[\").concat(e.candidate, \"]\"));\n                trace({ data: [\"onicecandidate\", id, e.candidate] });\n            });\n            pc.addEventListener(\"icecandidateerror\", function (e) {\n                (0, exports.sdkLog)(\"debug\", \"onicecandidateerror id:[\".concat(id, \"], error:[\").concat(e.errorCode, \":\").concat(e.errorText, \"]\"));\n                trace({ data: [\"onicecandidateerror\", id, \"\".concat(e.errorCode, \":\").concat(e.errorText)] });\n            });\n            pc.addEventListener(\"addstream\", function (e) {\n                trace({\n                    data: [\n                        \"onaddstream\",\n                        id,\n                        e.stream.id +\n                            \" \" +\n                            e.stream.getTracks().map(function (t) {\n                                return t.kind + \":\" + t.id;\n                            }),\n                    ],\n                });\n            });\n            pc.addEventListener(\"track\", function (e) {\n                trace({\n                    data: [\n                        \"ontrack\",\n                        id,\n                        debugTrack(e.track) +\n                            \" \" +\n                            e.streams.map(function (stream) {\n                                return \"stream:\" + stream.id;\n                            }),\n                    ],\n                });\n                // https://redmine.testrtc.com/issues/7166\n                e.track.addEventListener(\"ended\", function () {\n                    trace({\n                        data: [\n                            \"ontrack\",\n                            id,\n                            debugTrack(e.track) +\n                                \" \" +\n                                e.streams.map(function (stream) {\n                                    return \"stream:\" + stream.id;\n                                }),\n                        ],\n                    });\n                });\n                // Disable mute/umute tracks events: https://redmine.testrtc.com/issues/9240\n                // e.track.addEventListener(\"mute\", () => {\n                //   trace({\n                //     data: [\n                //       \"ontrack\",\n                //       id,\n                //       debugTrack(e.track) +\n                //         \" \" +\n                //         e.streams.map((stream: any) => {\n                //           return \"stream:\" + stream.id;\n                //         }),\n                //     ],\n                //   });\n                // });\n                //\n                // e.track.addEventListener(\"unmute\", () => {\n                //   trace({\n                //     data: [\n                //       \"ontrack\",\n                //       id,\n                //       debugTrack(e.track) +\n                //         \" \" +\n                //         e.streams.map((stream: any) => {\n                //           return \"stream:\" + stream.id;\n                //         }),\n                //     ],\n                //   });\n                // });\n            });\n            pc.addEventListener(\"removestream\", function (e) {\n                trace({\n                    data: [\n                        \"onremovestream\",\n                        id,\n                        e.stream.id +\n                            \" \" +\n                            e.stream.getTracks().map(function (t) {\n                                return t.kind + \":\" + t.id;\n                            }),\n                    ],\n                });\n            });\n            pc.addEventListener(\"signalingstatechange\", function () {\n                if (openChannels[id] && !openChannels[id].validConnection) {\n                    openChannels[id].validConnection = true;\n                    setTimeout(function () {\n                        (0, exports.sdkLog)(\"debug\", \"signalingstatechage. forceRecreate websocket connection[\".concat(id, \"]\"), {\n                            openChannels: JSON.stringify(openChannels),\n                        });\n                        maybeOpenWebsocketConnection({ forceRecreate: true, pcId: id });\n                    }, 5000);\n                }\n                else {\n                    (0, exports.sdkLog)(\"debug\", \"signalingstatechage. WS connection opening not triggered - peer connection not in channels or was already opened [\".concat(id, \"]\"), { openChannels: JSON.stringify(openChannels) });\n                }\n                trace({ data: [\"onsignalingstatechange\", id, pc.signalingState] });\n            });\n            pc.addEventListener(\"iceconnectionstatechange\", function () {\n                (0, exports.sdkLog)(\"debug\", \"oniceconnectionstatechange id:[\".concat(id, \"], state:[\").concat(pc.iceConnectionState, \"]\"));\n                trace({ data: [\"oniceconnectionstatechange\", id, pc.iceConnectionState] });\n            });\n            pc.addEventListener(\"icegatheringstatechange\", function () {\n                (0, exports.sdkLog)(\"debug\", \"onicegatheringstatechange id:[\".concat(id, \"], state:[\").concat(pc.iceGatheringState, \"]\"));\n                trace({ data: [\"onicegatheringstatechange\", id, pc.iceGatheringState] });\n            });\n            pc.addEventListener(\"connectionstatechange\", function () {\n                (0, exports.sdkLog)(\"debug\", \"onconnectionstatechange id:[\".concat(id, \"], state:[\").concat(pc.connectionState, \"]\"));\n                trace({ data: [\"onconnectionstatechange\", id, pc.connectionState] });\n            });\n            pc.addEventListener(\"negotiationneeded\", function () {\n                (0, exports.sdkLog)(\"debug\", \"onnegotiationneeded id:[\".concat(id, \"]\"));\n                trace({ data: [\"onnegotiationneeded\", id, undefined] });\n            });\n            pc.addEventListener(\"datachannel\", function (event) {\n                (0, exports.sdkLog)(\"debug\", \"ondatachannel id:[\".concat(id, \"], data:[\").concat(event.channel.id, \" \").concat(event.channel.label, \"]\"));\n                trace({ data: [\"ondatachannel\", id, [event.channel.id, event.channel.label]] });\n            });\n            // https://redmine.testrtc.com/issues/6529\n            // pc.addEventListener(\"iceconnectionstatechange\", () => {\n            //   if (pc.iceConnectionState === \"connected\") {\n            //     getStats(openChannels[id]);\n            //   }\n            // });\n            (0, exports.sdkLog)(\"debug\", \"RTCPeerConnection override complete [\".concat(id, \"].\"));\n            return pc;\n        };\n        if (\"HTMLMediaElement\" in globalContext && \"setSinkId\" in HTMLMediaElement.prototype) {\n            var nativeMethod_1 = HTMLMediaElement.prototype.setSinkId;\n            HTMLMediaElement.prototype.setSinkId = function () {\n                var selectedDeviceId = arguments[0];\n                navigator.mediaDevices\n                    .enumerateDevices()\n                    .then(function (devices) {\n                    var currentDevice = devices.find(function (_a) {\n                        var deviceId = _a.deviceId;\n                        return deviceId === selectedDeviceId;\n                    });\n                    if (currentDevice && currentDevice.deviceId !== currentAudioOutputId) {\n                        trace({ data: [\"audioOutputChange\", null, currentDevice.label] });\n                    }\n                    currentAudioOutputId = selectedDeviceId;\n                })\n                    .catch(function (error) {\n                    (0, exports.sdkLog)(\"debug\", error.message, { error: error });\n                });\n                return nativeMethod_1.apply(this, arguments);\n            };\n        }\n        // wrap RTCRtpTransceiver.setCodecPreferences\n        if (\"RTCRtpTransceiver\" in globalContext && \"setCodecPreferences\" in globalContext.RTCRtpTransceiver.prototype) {\n            var origRTCRtpTransceiver = globalContext.RTCRtpTransceiver;\n            var nativeMethod_2 = origRTCRtpTransceiver.prototype.setCodecPreferences;\n            origRTCRtpTransceiver.prototype.setCodecPreferences = function () {\n                trace({ data: [\"setCodecPreferences\", this.__pcId, arguments] });\n                return nativeMethod_2.apply(this, arguments);\n            };\n        }\n        // wrap RTCRtpSender.setParameters\n        if (\"RTCRtpSender\" in globalContext && \"setParameters\" in globalContext.RTCRtpSender.prototype) {\n            var origRTCRtpSender = globalContext.RTCRtpSender;\n            var nativeMethod_3 = origRTCRtpSender.prototype.setParameters;\n            origRTCRtpSender.prototype.setParameters = function () {\n                trace({ data: [\"setParameters\", this.__pcId, arguments] });\n                return nativeMethod_3.apply(this, arguments);\n            };\n        }\n        // wrap RTCRtpSender.replaceTrack\n        if (\"RTCRtpSender\" in globalContext && \"replaceTrack\" in globalContext.RTCRtpSender.prototype) {\n            var origRTCRtpSender = globalContext.RTCRtpSender;\n            var nativeMethod_4 = origRTCRtpSender.prototype.replaceTrack;\n            origRTCRtpSender.prototype.replaceTrack = function () {\n                var track = arguments[0];\n                if (track) {\n                    trace({\n                        data: [\"replaceTrack\", this.__pcId, debugTrack(track)],\n                    });\n                    // Check if the label is not the same as previous one - to detect a device change\n                    var originalTrack = this.track;\n                    if (originalTrack && originalTrack.label !== track.label) {\n                        trace({ data: [\"\".concat(track.kind, \"InputChange\"), this.__pcId, track.label] });\n                    }\n                }\n                else {\n                    trace({ data: [\"replaceTrack\", this.__pcId, null] });\n                }\n                return nativeMethod_4.apply(this, arguments);\n            };\n        }\n        // adding pc id to sender for above logic\n        [\"addTransceiver\"].forEach(function (method) {\n            var nativeMethod = origPeerConnection.prototype[method];\n            if (nativeMethod) {\n                origPeerConnection.prototype[method] = function () {\n                    var _this_1 = this;\n                    var streams = \"\";\n                    if (arguments[1] && arguments[1].streams) {\n                        streams = arguments[1].streams.map(function (s) { return \"stream:\" + s.id; }).join(\";\");\n                    }\n                    var trackOrKind = typeof arguments[0] === \"string\"\n                        ? arguments[0]\n                        : arguments[0].kind + \":\" + arguments[0].id + \" \" + arguments[0].label;\n                    var init = arguments[1] ? __assign(__assign({}, arguments[1]), { streams: streams }) : null;\n                    trace({ data: [method, this.__rtcStatsId, [trackOrKind, init]] });\n                    var transceiver = nativeMethod.apply(this, arguments);\n                    transceiver.sender.__pcId = this.__rtcStatsId;\n                    // https://redmine.testrtc.com/issues/7166\n                    var track = arguments[0];\n                    if (typeof track === \"object\") {\n                        trace({\n                            data: [\"onlocaltrack\", this.__rtcStatsId, debugTrack(track)],\n                        });\n                        track.addEventListener(\"ended\", function () {\n                            trace({\n                                data: [\"onlocaltrack\", _this_1.__rtcStatsId, debugTrack(track)],\n                            });\n                        });\n                        // Disable mute/umute tracks events: https://redmine.testrtc.com/issues/9240\n                        // track.addEventListener(\"mute\", () => {\n                        //   trace({\n                        //     data: [\"onlocaltrack\", this.__rtcStatsId, debugTrack(track)],\n                        //   });\n                        // });\n                        //\n                        // track.addEventListener(\"unmute\", () => {\n                        //   trace({\n                        //     data: [\"onlocaltrack\", this.__rtcStatsId, debugTrack(track)],\n                        //   });\n                        // });\n                    }\n                    return transceiver;\n                };\n            }\n        });\n        [\"createDataChannel\", \"restartIce\"].forEach(function (method) {\n            var nativeMethod = origPeerConnection.prototype[method];\n            if (nativeMethod) {\n                origPeerConnection.prototype[method] = function () {\n                    trace({ data: [method, this.__rtcStatsId, arguments] });\n                    return nativeMethod.apply(this, arguments);\n                };\n            }\n        });\n        [\"close\"].forEach(function (method) {\n            var nativeMethod = origPeerConnection.prototype[method];\n            if (nativeMethod) {\n                origPeerConnection.prototype[method] = function () {\n                    trace({ data: [method, this.__rtcStatsId, arguments] });\n                    delete openChannels[this.__rtcStatsId];\n                    isManualDisconnect = true;\n                    (0, exports.sdkLog)(\"debug\", \"on RTCPeerConnection(\".concat(this.__rtcStatsId, \") close\"));\n                    return nativeMethod.apply(this, arguments);\n                };\n            }\n        });\n        [\"addStream\", \"removeStream\"].forEach(function (method) {\n            var nativeMethod = origPeerConnection.prototype[method];\n            if (nativeMethod) {\n                origPeerConnection.prototype[method] = function () {\n                    var _this_1 = this;\n                    var stream = arguments[0];\n                    var streamInfo = stream\n                        .getTracks()\n                        .map(function (t) {\n                        return t.kind + \":\" + t.id;\n                    })\n                        .join(\",\");\n                    trace({ data: [method, this.__rtcStatsId, stream.id + \" \" + streamInfo] });\n                    // https://redmine.testrtc.com/issues/7166\n                    if (method === \"addStream\") {\n                        stream.getTracks().map(function (track) {\n                            trace({\n                                data: [\"onlocaltrack\", _this_1.__rtcStatsId, debugTrack(track) + \" \" + stream.id],\n                            });\n                            track.addEventListener(\"ended\", function () {\n                                trace({\n                                    data: [\"onlocaltrack\", _this_1.__rtcStatsId, debugTrack(track) + \" \" + stream.id],\n                                });\n                            });\n                            // Disable mute/umute tracks events: https://redmine.testrtc.com/issues/9240\n                            // track.addEventListener(\"mute\", () => {\n                            //   trace({\n                            //     data: [\"onlocaltrack\", this.__rtcStatsId, debugTrack(track) + \" \" + stream.id],\n                            //   });\n                            // });\n                            //\n                            // track.addEventListener(\"unmute\", () => {\n                            //   trace({\n                            //     data: [\"onlocaltrack\", this.__rtcStatsId, debugTrack(track) + \" \" + stream.id],\n                            //   });\n                            // });\n                        });\n                    }\n                    return nativeMethod.apply(this, arguments);\n                };\n            }\n        });\n        [\"addTrack\"].forEach(function (method) {\n            var nativeMethod = origPeerConnection.prototype[method];\n            if (nativeMethod) {\n                origPeerConnection.prototype[method] = function () {\n                    var _this_1 = this;\n                    var track = arguments[0];\n                    var streams = [].slice.call(arguments, 1);\n                    trace({\n                        data: [\n                            method,\n                            this.__rtcStatsId,\n                            debugTrack(track) +\n                                \" \" +\n                                (streams\n                                    .map(function (s) {\n                                    return \"stream:\" + s.id;\n                                })\n                                    .join(\";\") || \"-\"),\n                        ],\n                    });\n                    // https://redmine.testrtc.com/issues/7166\n                    trace({\n                        data: [\n                            \"onlocaltrack\",\n                            this.__rtcStatsId,\n                            debugTrack(track) +\n                                \" \" +\n                                streams.map(function (stream) {\n                                    return \"stream:\" + stream.id;\n                                }),\n                        ],\n                    });\n                    track.addEventListener(\"ended\", function () {\n                        trace({\n                            data: [\n                                \"onlocaltrack\",\n                                _this_1.__rtcStatsId,\n                                debugTrack(track) +\n                                    \" \" +\n                                    streams.map(function (stream) {\n                                        return \"stream:\" + stream.id;\n                                    }),\n                            ],\n                        });\n                    });\n                    // Disable mute/umute tracks events: https://redmine.testrtc.com/issues/9240\n                    // track.addEventListener(\"mute\", () => {\n                    //   trace({\n                    //     data: [\n                    //       \"onlocaltrack\",\n                    //       this.__rtcStatsId,\n                    //       debugTrack(track) +\n                    //         \" \" +\n                    //         streams.map((stream: any) => {\n                    //           return \"stream:\" + stream.id;\n                    //         }),\n                    //     ],\n                    //   });\n                    // });\n                    //\n                    // track.addEventListener(\"unmute\", () => {\n                    //   trace({\n                    //     data: [\n                    //       \"onlocaltrack\",\n                    //       this.__rtcStatsId,\n                    //       debugTrack(track) +\n                    //         \" \" +\n                    //         streams.map((stream: any) => {\n                    //           return \"stream:\" + stream.id;\n                    //         }),\n                    //     ],\n                    //   });\n                    // });\n                    var sender = nativeMethod.apply(this, arguments);\n                    sender.__pcId = this.__rtcStatsId;\n                    // Associate the peer id to the existing transceivers\n                    var transceivers = this.getTransceivers();\n                    if (transceivers) {\n                        transceivers.forEach(function (transceiver) {\n                            transceiver.__pcId = _this_1.__rtcStatsId;\n                        });\n                    }\n                    return sender;\n                };\n            }\n        });\n        [\"removeTrack\"].forEach(function (method) {\n            var nativeMethod = origPeerConnection.prototype[method];\n            if (nativeMethod) {\n                origPeerConnection.prototype[method] = function () {\n                    var track = arguments[0].track;\n                    trace({\n                        data: [method, this.__rtcStatsId, track ? debugTrack(track) : \"null\"],\n                    });\n                    return nativeMethod.apply(this, arguments);\n                };\n            }\n        });\n        [\"createOffer\", \"createAnswer\"].forEach(function (method) {\n            var nativeMethod = origPeerConnection.prototype[method];\n            if (nativeMethod) {\n                origPeerConnection.prototype[method] = function () {\n                    var rtcStatsId = this.__rtcStatsId;\n                    var args = arguments;\n                    var opts;\n                    if (arguments.length === 1 && typeof arguments[0] === \"object\") {\n                        opts = arguments[0];\n                    }\n                    else if (arguments.length === 3 && typeof arguments[2] === \"object\") {\n                        opts = arguments[2];\n                    }\n                    trace({ data: [method, this.__rtcStatsId, opts] });\n                    return nativeMethod.apply(this, opts ? [opts] : undefined).then(function (description) {\n                        trace({ data: [method + \"OnSuccess\", rtcStatsId, description] });\n                        if (args.length > 0 && typeof args[0] === \"function\") {\n                            args[0].apply(null, [description]);\n                            return undefined;\n                        }\n                        return description;\n                    }, function (err) {\n                        trace({ data: [method + \"OnFailure\", rtcStatsId, err.toString()] });\n                        if (args.length > 1 && typeof args[1] === \"function\") {\n                            args[1].apply(null, [err]);\n                            return;\n                        }\n                        throw err;\n                    });\n                };\n            }\n        });\n        [\"setLocalDescription\", \"setRemoteDescription\", \"addIceCandidate\"].forEach(function (method) {\n            var nativeMethod = origPeerConnection.prototype[method];\n            if (nativeMethod) {\n                origPeerConnection.prototype[method] = function () {\n                    var rtcStatsId = this.__rtcStatsId;\n                    var args = arguments;\n                    var _this = this;\n                    // because of setLocalDescription(null) sometimes we don't have SDP value\n                    // fippo suggested: Access pc.localDescription.sdp in the successcallback\n                    var needToHandleSDPInSuccessCallback = method === \"setLocalDescription\" && (!args[0] || (args[0] && !args[0].sdp));\n                    trace({\n                        data: [method, this.__rtcStatsId, needToHandleSDPInSuccessCallback ? { parameterless: true } : args[0]],\n                    });\n                    return nativeMethod.apply(this, [args[0]]).then(function () {\n                        trace({\n                            data: [\n                                method + \"OnSuccess\",\n                                rtcStatsId,\n                                needToHandleSDPInSuccessCallback ? _this === null || _this === void 0 ? void 0 : _this.localDescription : undefined,\n                            ],\n                        });\n                        if (args.length >= 2 && typeof args[1] === \"function\") {\n                            args[1].apply(null, []);\n                            return undefined;\n                        }\n                        return undefined;\n                    }, function (err) {\n                        trace({ data: [method + \"OnFailure\", rtcStatsId, err.toString()] });\n                        if (args.length >= 3 && typeof args[2] === \"function\") {\n                            args[2].apply(null, [err]);\n                            return undefined;\n                        }\n                        throw err;\n                    });\n                };\n            }\n        });\n        // wrap static methods. Currently just generateCertificate.\n        if (origPeerConnection.generateCertificate) {\n            Object.defineProperty(peerconnection, \"generateCertificate\", {\n                get: function () {\n                    return arguments.length\n                        ? origPeerConnection.generateCertificate.apply(null, arguments)\n                        : origPeerConnection.generateCertificate;\n                },\n            });\n        }\n        globalContext[prefix + \"RTCPeerConnection\"] = peerconnection;\n        globalContext[prefix + \"RTCPeerConnection\"].prototype = origPeerConnection.prototype;\n        (0, exports.sdkLog)(\"debug\", \"RTCPeerConnection prefixes override complete\");\n    });\n    if (isBrowser) {\n        // getUserMedia wrappers\n        prefixesToWrap.forEach(function (prefix) {\n            var name = prefix + (prefix.length ? \"GetUserMedia\" : \"getUserMedia\");\n            if (!navigator[name]) {\n                return;\n            }\n            var origGetUserMedia = navigator[name].bind(navigator);\n            var gum = function () {\n                trace({ data: [\"getUserMedia\", null, arguments[0]] });\n                var cb = arguments[1];\n                var eb = arguments[2];\n                origGetUserMedia(arguments[0], function (stream) {\n                    // we log the stream id, track ids and tracks readystate since that is ended GUM fails\n                    // to acquire the cam (in chrome)\n                    trace({ data: [\"getUserMediaOnSuccess\", null, (0, utils_1.dumpStream)(stream)] });\n                    if (cb) {\n                        cb(stream);\n                    }\n                }, function (err) {\n                    var errorData = [\"getUserMediaOnFailure\", null, err.name];\n                    trace({ data: errorData });\n                    httpReportError(errorData);\n                    if (eb) {\n                        eb(err);\n                    }\n                });\n            };\n            navigator[name] = gum.bind(navigator);\n        });\n        if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {\n            var origGetUserMedia_1 = navigator.mediaDevices.getUserMedia.bind(navigator.mediaDevices);\n            var gum = function () {\n                trace({ data: [\"navigator.mediaDevices.getUserMedia\", null, arguments[0]] });\n                return origGetUserMedia_1.apply(navigator.mediaDevices, arguments).then(function (stream) {\n                    trace({ data: [\"navigator.mediaDevices.getUserMediaOnSuccess\", null, (0, utils_1.dumpStream)(stream)] });\n                    return stream;\n                }, function (err) {\n                    var errorData = [\"navigator.mediaDevices.getUserMediaOnFailure\", null, err.name];\n                    trace({ data: errorData });\n                    httpReportError(errorData);\n                    return Promise.reject(err);\n                });\n            };\n            navigator.mediaDevices.getUserMedia = gum.bind(navigator.mediaDevices);\n        }\n        // getDisplayMedia\n        if (navigator.mediaDevices && navigator.mediaDevices.getDisplayMedia) {\n            var origGetDisplayMedia_1 = navigator.mediaDevices.getDisplayMedia.bind(navigator.mediaDevices);\n            var gdm = function () {\n                trace({ data: [\"navigator.mediaDevices.getDisplayMedia\", null, arguments[0]] });\n                return origGetDisplayMedia_1.apply(navigator.mediaDevices, arguments).then(function (stream) {\n                    trace({ data: [\"navigator.mediaDevices.getDisplayMediaOnSuccess\", null, (0, utils_1.dumpStream)(stream)] });\n                    return stream;\n                }, function (err) {\n                    var errorData = [\"navigator.mediaDevices.getDisplayMediaOnFailure\", null, err.name];\n                    trace({ data: errorData });\n                    httpReportError(errorData);\n                    return Promise.reject(err);\n                });\n            };\n            navigator.mediaDevices.getDisplayMedia = gdm.bind(navigator.mediaDevices);\n        }\n    }\n    if ((_b = watchrtc.console) === null || _b === void 0 ? void 0 : _b.level) {\n        (0, utils_1.setConsoleLevel)(watchrtc.console.level, trace);\n    }\n};\nexports.initSDK = initSDK;\nvar setConfig = function (newWatchrtcConfig) {\n    var _a;\n    var initialized = globalContext.watchRTCInitialized;\n    if (!initialized) {\n        (0, exports.sdkLog)(\"error\", \"SDK is not initialized. Use 'init' function first.\");\n        return;\n    }\n    var collectConsoleDisabled = (watchrtcConfig === null || watchrtcConfig === void 0 ? void 0 : watchrtcConfig.allowBrowserLogCollection) === false;\n    if (!collectConsoleDisabled && ((_a = newWatchrtcConfig === null || newWatchrtcConfig === void 0 ? void 0 : newWatchrtcConfig.console) === null || _a === void 0 ? void 0 : _a.override) === true && newWatchrtcConfig.console.level) {\n        (0, utils_1.setConsoleLevel)(newWatchrtcConfig.console.level, trace);\n    }\n    if (\"collectionInterval\" in newWatchrtcConfig) {\n        delete newWatchrtcConfig.collectionInterval;\n    }\n    watchrtcConfig = __assign(__assign({}, watchrtcConfig), newWatchrtcConfig);\n    watchrtcIdentifiers.rtcRoomId = watchrtcConfig.rtcRoomId;\n    watchrtcIdentifiers.rtcPeerId = watchrtcConfig.rtcPeerId;\n    (0, exports.sdkLog)(\"debug\", \"setConfig\", {\n        newWatchrtcConfig: JSON.stringify(newWatchrtcConfig),\n        watchrtcConfig: JSON.stringify(watchrtcConfig),\n    });\n    maybeOpenWebsocketConnection({});\n};\nexports.setConfig = setConfig;\n/**\n * Set user rating and/or comment for peer session\n * @param rating number from 1 to 5\n * @param comment string\n */\nvar setUserRating = function (\n/** 1 | 2 | 3 | 4 | 5 */\nrating, ratingComment) {\n    var _a;\n    var initialized = globalContext.watchRTCInitialized;\n    if (!initialized) {\n        (0, exports.sdkLog)(\"error\", \"SDK is not initialized. Use 'init' function first.\");\n        return Promise.resolve({ error: \"SDK is not initialized. Use 'init' function first.\" });\n    }\n    var isValidRating = (0, utils_1.validateRating)(rating);\n    if (!isValidRating) {\n        return Promise.resolve({ error: \"Rating is invalid\" });\n    }\n    var opened = ((_a = socket === null || socket === void 0 ? void 0 : socket.connection) === null || _a === void 0 ? void 0 : _a.readyState) === globalContext.WebSocket.OPEN;\n    var data = [\"userRating\", null, { rating: rating, ratingComment: ratingComment }];\n    return new Promise(function (resolve, reject) {\n        var options = { promiseFuncs: { resolve: resolve, reject: reject } };\n        if (opened) {\n            trace({ data: data, options: options });\n        }\n        else {\n            httpTrace.apply(void 0, data).then(function () { return resolve({}); })\n                .catch(function (error) { return resolve({ error: error }); });\n        }\n    });\n};\nexports.setUserRating = setUserRating;\n/**\n * Add keys for peer session\n * @param keys\n */\nvar addKeys = function (\n/** { \"key1\": \"value1\", \"key2\": [\"value2_1\", \"value2_2\"]} */\nkeys) {\n    var _a;\n    var initialized = globalContext.watchRTCInitialized;\n    if (!initialized) {\n        (0, exports.sdkLog)(\"error\", \"SDK is not initialized. Use 'init' function first.\");\n        return;\n    }\n    Object.keys(keys || {}).forEach(function (k) {\n        if (typeof keys[k] === \"string\") {\n            keys[k] = [keys[k]];\n        }\n    });\n    var data = [\"keys\", null, keys];\n    var opened = ((_a = socket === null || socket === void 0 ? void 0 : socket.connection) === null || _a === void 0 ? void 0 : _a.readyState) === globalContext.WebSocket.OPEN;\n    var wasConnected = socket === null || socket === void 0 ? void 0 : socket.wasConnected;\n    return new Promise(function (resolve, reject) {\n        var options = { promiseFuncs: { resolve: resolve, reject: reject } };\n        if (opened) {\n            trace({ data: data, options: options });\n        }\n        else if (!wasConnected) {\n            trace({ data: data, options: options });\n        }\n        else {\n            httpTrace.apply(void 0, data).then(function () { return resolve({}); })\n                .catch(function (error) { return resolve({ error: error }); });\n        }\n    });\n};\nexports.addKeys = addKeys;\nvar disableDataCollection = function () {\n    var initialized = globalContext.watchRTCInitialized;\n    if (!initialized) {\n        (0, exports.sdkLog)(\"error\", \"SDK is not initialized. Use 'init' function first.\");\n        return;\n    }\n    trace({ data: [\"disableDataCollection\", null, null] });\n    socket === null || socket === void 0 ? void 0 : socket.disableDataCollection();\n};\nexports.disableDataCollection = disableDataCollection;\nvar enableDataCollection = function () {\n    var initialized = globalContext.watchRTCInitialized;\n    if (!initialized) {\n        (0, exports.sdkLog)(\"error\", \"SDK is not initialized. Use 'init' function first.\");\n        return;\n    }\n    trace({ data: [\"enableDataCollection\", null, null] });\n    socket === null || socket === void 0 ? void 0 : socket.enableDataCollection();\n};\nexports.enableDataCollection = enableDataCollection;\nvar addEvent = function (event) {\n    var initialized = globalContext.watchRTCInitialized;\n    if (!initialized) {\n        (0, exports.sdkLog)(\"error\", \"addEvent error. SDK is not initialized. Use 'init' function first.\");\n        return;\n    }\n    // const opened = socket?.connection?.readyState === WS.OPEN;\n    // if (!opened && socket?.wasConnected) {\n    //   sdkLog(\"error\", `addEvent error. Connection has been closed.`);\n    //   return;\n    // }\n    var isEventValid = (0, utils_1.validateEvent)(event, openChannels);\n    if (!isEventValid) {\n        return;\n    }\n    // Don't keep `pc` information in event, only extract the id\n    var validatedEvent = __assign({}, event);\n    var source = null;\n    if (validatedEvent.pc) {\n        source = validatedEvent.pc.__rtcStatsId || null;\n        delete validatedEvent.pc;\n    }\n    var data = [\"event\", source, validatedEvent];\n    return new Promise(function (resolve, reject) {\n        var options = { promiseFuncs: { resolve: resolve, reject: reject } };\n        trace({ data: data, options: options });\n    });\n};\nexports.addEvent = addEvent;\nvar mapStream = function (id, name) {\n    var initialized = globalContext.watchRTCInitialized;\n    if (!initialized) {\n        (0, exports.sdkLog)(\"error\", \"mapStream error. SDK is not initialized. Use 'init' function first.\");\n        return;\n    }\n    var isDataValid = !!id && !!name;\n    if (!isDataValid) {\n        return;\n    }\n    var data = [\"mapStream\", null, { id: id, name: name }];\n    (0, exports.sdkLog)(\"info\", \"mapStream method is deprecated. Please use mapTrack instead.\");\n    trace({ data: data });\n};\nexports.mapStream = mapStream;\nvar mapTrack = function (id, name) {\n    var initialized = globalContext.watchRTCInitialized;\n    if (!initialized) {\n        (0, exports.sdkLog)(\"error\", \"mapTrack error. SDK is not initialized. Use 'init' function first.\");\n        return;\n    }\n    var isDataValid = !!id && !!name;\n    if (!isDataValid) {\n        return;\n    }\n    mappedTrack[id] = name;\n    var data = [\"mapTrack\", null, { id: id, name: name }];\n    trace({ data: data });\n};\nexports.mapTrack = mapTrack;\nvar connect = function () {\n    var initialized = globalContext.watchRTCInitialized;\n    if (!initialized) {\n        (0, exports.sdkLog)(\"error\", \"connect error. SDK is not initialized. Use 'init' function first.\");\n        return;\n    }\n    freshConnection = true;\n    isManualConnect = true;\n    (0, exports.sdkLog)(\"debug\", \"manual connect\");\n    maybeOpenWebsocketConnection({});\n};\nexports.connect = connect;\nvar disconnect = function () {\n    var initialized = globalContext.watchRTCInitialized;\n    if (!initialized) {\n        (0, exports.sdkLog)(\"error\", \"disconnect error. SDK is not initialized. Use 'init' function first.\");\n        return;\n    }\n    isManualConnect = false;\n    isManualDisconnect = true;\n    socket === null || socket === void 0 ? void 0 : socket.close();\n    (0, exports.sdkLog)(\"debug\", \"manual disconnect\");\n};\nexports.disconnect = disconnect;\nvar registerOnStatsListener = function (listener) {\n    getStatsCallback = listener;\n};\nexports.registerOnStatsListener = registerOnStatsListener;\nvar registerStateListener = function (listener) {\n    stateListener = listener;\n};\nexports.registerStateListener = registerStateListener;\nvar httpTrace = function () {\n    var _a;\n    var data = [];\n    for (var _i = 0; _i < arguments.length; _i++) {\n        data[_i] = arguments[_i];\n    }\n    if (!watchrtcIdentifiers.rtcRoomId || !watchrtcIdentifiers.rtcPeerId) {\n        var message = \"Missing configuration parameters rtcPeerId and rtcRoomId to connect\";\n        if (!watchrtcIdentifiers.rtcRoomId && watchrtcIdentifiers.rtcPeerId) {\n            message = \"Missing configuration parameter rtcRoomId to connect\";\n        }\n        else if (!watchrtcIdentifiers.rtcPeerId && watchrtcIdentifiers.rtcRoomId) {\n            message = \"Missing configuration parameter rtcPeerId to connect\";\n        }\n        (0, exports.sdkLog)(\"error\", message);\n        return Promise.reject(message);\n    }\n    if (!watchrtcIdentifiers.projectId && !watchrtcConfig.rtcApiKey) {\n        var message = \"Missing apiKey to enable trace before connection establishment\";\n        (0, exports.sdkLog)(\"info\", message);\n        return Promise.reject(message);\n    }\n    var httpConnectionData = (0, utils_1.getConnectionData)(\"http\", watchrtcConfig.rtcApiKey, watchrtcConfig.proxyUrl);\n    return http\n        ? http.trace.apply(http, __spreadArray([\"\".concat(httpConnectionData.url, \"/trace\"), (_a = watchrtcIdentifiers.projectId) !== null && _a !== void 0 ? _a : httpConnectionData.key, watchrtcIdentifiers.rtcRoomId,\n            watchrtcIdentifiers.rtcPeerId], data, false)) : Promise.reject(\"Invalid configuration of http service\");\n};\nvar httpReportError = function (data) {\n    var apiKey = watchrtcConfig === null || watchrtcConfig === void 0 ? void 0 : watchrtcConfig.rtcApiKey;\n    var rtcRoomId = watchrtcConfig === null || watchrtcConfig === void 0 ? void 0 : watchrtcConfig.rtcRoomId;\n    var rtcPeerId = watchrtcConfig === null || watchrtcConfig === void 0 ? void 0 : watchrtcConfig.rtcPeerId;\n    if (!apiKey || !rtcRoomId || !rtcPeerId) {\n        (0, exports.sdkLog)(\"error\", \"Cannot report an error. Please provide rtcApiKey, rtcRoomId and rtcPeerId \");\n        return;\n    }\n    var httpConnectionData = (0, utils_1.getConnectionData)(\"http\", watchrtcConfig === null || watchrtcConfig === void 0 ? void 0 : watchrtcConfig.rtcApiKey, watchrtcConfig.proxyUrl);\n    data = data || (socket === null || socket === void 0 ? void 0 : socket.buffer) || [];\n    http === null || http === void 0 ? void 0 : http.trace(\"\".concat(httpConnectionData.url, \"/error\"), httpConnectionData.key, rtcRoomId, rtcPeerId, data);\n};\nvar persistentEnd = function (nailUpCallEnd) {\n    var initialized = globalContext.watchRTCInitialized;\n    if (!initialized) {\n        (0, exports.sdkLog)(\"error\", \"persistentEnd error. SDK is not initialized. Use 'init' function first.\");\n        return;\n    }\n    clearInterval(getStatsInterval);\n    isManualConnect = false;\n    isManualDisconnect = true;\n    socket === null || socket === void 0 ? void 0 : socket.close(nailUpCallEnd);\n    (0, exports.sdkLog)(\"debug\", \"persistentEnd. sessionId: \".concat(globalContext.watchRTCSessionId));\n};\nexports.persistentEnd = persistentEnd;\nvar resetConnectionState = function () {\n    var _a;\n    (0, exports.sdkLog)(\"debug\", \"resetConnectionState sessionId: \".concat(globalContext.watchRTCSessionId));\n    for (var _i = 0, _b = Object.values(openChannels); _i < _b.length; _i++) {\n        var channel = _b[_i];\n        channel.prev = null;\n    }\n    if ((_a = socket === null || socket === void 0 ? void 0 : socket.buffer) === null || _a === void 0 ? void 0 : _a.length) {\n        socket.buffer = socket.buffer.filter(function (_a) {\n            var traceType = _a[0];\n            return traceType !== \"getstats\";\n        });\n    }\n};\nvar persistentStart = function (roomId, peerId) {\n    var initialized = globalContext.watchRTCInitialized;\n    if (!initialized) {\n        (0, exports.sdkLog)(\"error\", \"persistentStart error. SDK is not initialized. Use 'init' function first.\");\n        return;\n    }\n    watchrtcConfig = __assign(__assign({}, watchrtcConfig), { rtcRoomId: roomId, rtcPeerId: peerId });\n    watchrtcIdentifiers.rtcRoomId = roomId;\n    watchrtcIdentifiers.rtcPeerId = peerId;\n    resetConnectionState();\n    maybeOpenWebsocketConnection({ nailUp: true });\n    (0, exports.sdkLog)(\"debug\", \"persistentStart. sessionId: \".concat(globalContext.watchRTCSessionId), { watchrtcConfig: watchrtcConfig });\n};\nexports.persistentStart = persistentStart;\n// (globalContext as any).setUserRating = setUserRating;\n// (globalContext as any).addTags = addTags;\n// (globalContext as any).addKeys = addKeys;\n// (globalContext as any).init = initSDK;\n// (globalContext as any).addEvent = addEvent;\n// (globalContext as any).wrtcConnect = connect;\n// (globalContext as any).wrtcDisconnect = disconnect;\n/* QRTC SDK part */\nvar loadJS = function (url) {\n    return new Promise(function (resolve, reject) {\n        var script = document.createElement(\"script\");\n        script.src = url;\n        script.onload = resolve;\n        script.onerror = reject;\n        document.head.appendChild(script);\n    });\n};\nvar loadConfig = function (url) { return __awaiter(void 0, void 0, void 0, function () {\n    var response;\n    return __generator(this, function (_a) {\n        switch (_a.label) {\n            case 0: return [4 /*yield*/, fetch(url)];\n            case 1:\n                response = _a.sent();\n                return [4 /*yield*/, response.json()];\n            case 2: return [2 /*return*/, _a.sent()];\n        }\n    });\n}); };\nvar qrtcStopRequest = false;\n/*\n    const answer = await watchRTC.qualityrtc.run({\n      options: {\n        // run: \"Location\",\n\n        // if missing, will use default unpkg.com values\n        codeUrl: `http://localhost:8081/lib/main.bundle.js`,\n\n        // should not be passed, and will read from watchRTC server, passing this for development testing\n        configUrl: `https://niceincontact.testrtc.com/.netlify/functions/get-config`\n      },\n      progressCallback});\n\n */\nvar qrtcRun = function (_a) {\n    var options = _a.options, progressCallback = _a.progressCallback;\n    return __awaiter(void 0, void 0, void 0, function () {\n        var answer, codeUrl, queryParams_1, httpConnectionData, isNetlifyRequest, configUrl, _b, configAnswer, codeLoad, qualityRTC, progressCallbackWrapper, configData, netlifyBaseUrl, config;\n        return __generator(this, function (_c) {\n            switch (_c.label) {\n                case 0:\n                    if (!isBrowser) {\n                        (0, exports.sdkLogWithoutTrace)(\"info\", \"Cannot run qualityRTC test in non-browser environment\");\n                        return [2 /*return*/];\n                    }\n                    qrtcStopRequest = false;\n                    // disable WatchRTC SDK data collection while QRTC SDK working\n                    (0, exports.disableDataCollection)();\n                    _c.label = 1;\n                case 1:\n                    _c.trys.push([1, , 4, 5]);\n                    codeUrl = (options === null || options === void 0 ? void 0 : options.codeUrl) || \"https://qualityrtc-sdk.s3.amazonaws.com/\".concat(version_1.default, \"/main.bundle.js\");\n                    queryParams_1 = {};\n                    if (options) {\n                        Object.keys(options || {}).forEach(function (key) {\n                            if (typeof options[key] === \"string\") {\n                                queryParams_1[key] = options[key];\n                            }\n                        });\n                    }\n                    httpConnectionData = (0, utils_1.getConnectionData)(\"http\", watchrtcConfig === null || watchrtcConfig === void 0 ? void 0 : watchrtcConfig.rtcApiKey, watchrtcConfig.proxyUrl);\n                    isNetlifyRequest = !!(options === null || options === void 0 ? void 0 : options.configUrl);\n                    configUrl = isNetlifyRequest\n                        ? \"\".concat(options.configUrl, \"/.netlify/functions/get-config\")\n                        : httpConnectionData.url +\n                            \"/get-qualityrtc-config?apiKey=\".concat(httpConnectionData.key, \"&\").concat(new URLSearchParams(queryParams_1));\n                    console.log(\"runNetworkTest: request to run, loading lib and config\", {\n                        codeUrl: codeUrl,\n                        configUrl: configUrl,\n                    });\n                    return [4 /*yield*/, Promise.all([loadConfig(configUrl), loadJS(codeUrl)])];\n                case 2:\n                    _b = _c.sent(), configAnswer = _b[0], codeLoad = _b[1];\n                    console.log(\"runNetworkTest:JS code & config loaded\", {\n                        codeLoad: codeLoad,\n                        configAnswer: configAnswer,\n                    });\n                    qualityRTC = globalContext.__qualityRTC;\n                    if (!qualityRTC) {\n                        throw new Error(\"runNetworkTest:Failed to load qualityRTC, __qualityRTC is undefined\");\n                    }\n                    progressCallbackWrapper = function (progress) {\n                        if (qrtcStopRequest) {\n                            return false;\n                        }\n                        else if (progressCallback) {\n                            progressCallback(progress);\n                        }\n                        return true;\n                    };\n                    configData = isNetlifyRequest ? configAnswer.config : configAnswer.jsonConfig.config;\n                    netlifyBaseUrl = isNetlifyRequest ? options === null || options === void 0 ? void 0 : options.configUrl : new URL(configAnswer.url).origin;\n                    config = __assign(__assign({}, configData), { isProbe: true, options: __assign(__assign(__assign({}, configData.options), options), { wakeLock: true, netlifyBaseUrl: netlifyBaseUrl }) });\n                    console.log(\"runNetworkTest: code & config loaded, running test\", {\n                        config: config,\n                        configData: configData,\n                        qualityRTC: qualityRTC,\n                        netlifyBaseUrl: netlifyBaseUrl,\n                    });\n                    return [4 /*yield*/, qualityRTC.run({\n                            config: config,\n                            progressCallback: progressCallbackWrapper,\n                        })];\n                case 3:\n                    answer = _c.sent();\n                    console.log(\"runNetworkTest:JS Test completed\", { answer: answer });\n                    return [3 /*break*/, 5];\n                case 4:\n                    (0, exports.enableDataCollection)();\n                    return [7 /*endfinally*/];\n                case 5: return [2 /*return*/, answer];\n            }\n        });\n    });\n};\nexports.qrtcRun = qrtcRun;\nvar qrtcStop = function () {\n    if (!isBrowser) {\n        (0, exports.sdkLogWithoutTrace)(\"info\", \"Cannot run qualityRTC test in non-browser environment\");\n        return;\n    }\n    qrtcStopRequest = true;\n};\nexports.qrtcStop = qrtcStop;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.getStreamsFromStats = exports.getTransportFromStats = void 0;\nvar getTransportFromStats = function (id, reports) {\n    if (!reports) {\n        return null;\n    }\n    var reportKeys = Object.keys(reports);\n    var keyPairs = reportKeys.filter(function (reportKey) { return reports[reportKey].type === \"candidate-pair\" && reports[reportKey].nominated; });\n    if (keyPairs.length > 0) {\n        var _a = reports[keyPairs[0]], localCandidateId_1 = _a.localCandidateId, remoteCandidateId_1 = _a.remoteCandidateId;\n        var localCandidateKey = reportKeys.find(function (reportKey) { return reports[reportKey].type === \"local-candidate\" && reports[reportKey].id === localCandidateId_1; });\n        var remoteCandidateKey = reportKeys.find(function (reportKey) { return reports[reportKey].type === \"remote-candidate\" && reports[reportKey].id === remoteCandidateId_1; });\n        if (localCandidateKey && remoteCandidateKey) {\n            var localCandidate = reports[localCandidateKey];\n            var remoteCandidate = reports[remoteCandidateKey];\n            var peer = {};\n            peer[id] = {\n                connection: localCandidate.candidateType === \"relay\" ? \"relay\" : \"direct\",\n                transport: localCandidate.candidateType === \"relay\" ? localCandidate.relayProtocol : \"udp\",\n                address: \"\".concat(remoteCandidate.address, \":\").concat(remoteCandidate.port),\n            };\n            return peer;\n        }\n    }\n    return null;\n};\nexports.getTransportFromStats = getTransportFromStats;\nvar getStreamsFromStats = function (id, previous, current, mappedTrack) {\n    var streams = {};\n    var currentReportsKeys = Object.keys(current);\n    var streamsKeys = currentReportsKeys.filter(function (keys) { return current[keys].type === \"inbound-rtp\" || current[keys].type === \"outbound-rtp\"; });\n    streamsKeys.forEach(function (streamKey) {\n        var currentReport = current[streamKey];\n        var previousReport = previous && streamKey in previous ? previous[streamKey] : null;\n        var direction = currentReport.type === \"inbound-rtp\" ? \"inbound\" : \"outbound\";\n        var kind = currentReport.kind;\n        var currentRemoteReport = currentReport.remoteId in current ? current[currentReport.remoteId] : null;\n        var previousRemoteReport = previousReport && previousReport.remoteId in previous ? previous[previousReport.remoteId] : null;\n        var deltaSeconds = previousReport ? (currentReport.timestamp - previousReport.timestamp) / 1000 : null;\n        var stream = {\n            direction: direction,\n            kind: kind,\n            peerId: id,\n        };\n        // Specific video (in inbound, outbound\n        if (kind === \"video\") {\n            stream.frameWidth = currentReport.frameWidth;\n            stream.frameHeight = currentReport.frameHeight;\n            stream.framerate = currentReport.framesPerSecond;\n        }\n        if (currentReport.type === \"inbound-rtp\") {\n            stream.jitter = currentReport.jitter;\n            // For inbound stream, trackIdentifier is part of the inbound-rtp report\n            stream.mappedName =\n                currentReport.trackIdentifier in mappedTrack ? mappedTrack[currentReport.trackIdentifier] : null;\n            // Compute intermediate values if previous report exists\n            stream.bytesReceived = previousReport ? currentReport.bytesReceived - previousReport.bytesReceived : null;\n            stream.packetsReceived = previousReport ? currentReport.packetsReceived - previousReport.packetsReceived : null;\n            stream.packetsLost = previousReport ? currentReport.packetsLost - previousReport.packetsLost : null;\n            stream.packetsLoss =\n                stream.packetsLost + stream.packetsReceived > 0\n                    ? (stream.packetsLost * 100) / (stream.packetsLost + stream.packetsReceived)\n                    : null;\n            stream.bitrate = deltaSeconds ? (stream.bytesReceived * 8) / deltaSeconds : null;\n            // Compute intermediate stats from remoteId (remoteOutbound);\n            stream.roundTripTime =\n                currentRemoteReport && \"roundTripTime\" in currentRemoteReport ? currentRemoteReport.roundTripTime : null;\n        }\n        else {\n            // Compute intermediate values if previous report exists\n            stream.bytesSent = previousReport ? currentReport.bytesSent - previousReport.bytesSent : null;\n            stream.packetsSent = previousReport ? currentReport.packetsSent - previousReport.packetsSent : null;\n            stream.bitrate = deltaSeconds ? (stream.bytesSent * 8) / deltaSeconds : null;\n            // Compute intermediate stats from remoteId (remoteInbound)\n            stream.roundTripTime =\n                currentRemoteReport && \"roundTripTime\" in currentRemoteReport ? currentRemoteReport.roundTripTime : null;\n            stream.jitter = currentRemoteReport && \"jitter\" in currentRemoteReport ? currentRemoteReport.jitter : null;\n            stream.packetsLost =\n                currentRemoteReport && previousRemoteReport\n                    ? currentRemoteReport.packetsLost - previousRemoteReport.packetsLost\n                    : null;\n            stream.packetsLoss =\n                currentRemoteReport && \"fractionLost\" in currentRemoteReport ? currentRemoteReport.fractionLost : null;\n            // For outbound stream, trackIdentifier is part of the media-source report\n            var mediaSourceKey = currentReportsKeys.find(function (key) { return current[key].id === currentReport.mediaSourceId; });\n            if (mediaSourceKey) {\n                var outboundTrackIdentifier = current[mediaSourceKey].trackIdentifier;\n                stream.mappedName = outboundTrackIdentifier in mappedTrack ? mappedTrack[outboundTrackIdentifier] : null;\n            }\n        }\n        // Compute codec name from codecId (codec)\n        var codecKey = currentReportsKeys.find(function (key) { return current[key].id === currentReport.codecId; });\n        if (codecKey) {\n            var mimeType = current[codecKey].mimeType || \"\";\n            stream.codec = mimeType.includes(\"/\") ? mimeType.split(\"/\")[1] : mimeType;\n        }\n        streams[current[streamKey].id] = stream;\n    });\n    return streams;\n};\nexports.getStreamsFromStats = getStreamsFromStats;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\n","\"use strict\";\nvar __assign = (this && this.__assign) || function () {\n    __assign = Object.assign || function(t) {\n        for (var s, i = 1, n = arguments.length; i < n; i++) {\n            s = arguments[i];\n            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))\n                t[p] = s[p];\n        }\n        return t;\n    };\n    return __assign.apply(this, arguments);\n};\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n    return new (P || (P = Promise))(function (resolve, reject) {\n        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n        function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n        step((generator = generator.apply(thisArg, _arguments || [])).next());\n    });\n};\nvar __generator = (this && this.__generator) || function (thisArg, body) {\n    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\n    return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\n    function verb(n) { return function (v) { return step([n, v]); }; }\n    function step(op) {\n        if (f) throw new TypeError(\"Generator is already executing.\");\n        while (g && (g = 0, op[0] && (_ = 0)), _) try {\n            if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\n            if (y = 0, t) op = [op[0] & 2, t.value];\n            switch (op[0]) {\n                case 0: case 1: t = op; break;\n                case 4: _.label++; return { value: op[1], done: false };\n                case 5: _.label++; y = op[1]; op = [0]; continue;\n                case 7: op = _.ops.pop(); _.trys.pop(); continue;\n                default:\n                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\n                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\n                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\n                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\n                    if (t[2]) _.ops.pop();\n                    _.trys.pop(); continue;\n            }\n            op = body.call(thisArg, _);\n        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\n        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\n    }\n};\nvar __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {\n    if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {\n        if (ar || !(i in from)) {\n            if (!ar) ar = Array.prototype.slice.call(from, 0, i);\n            ar[i] = from[i];\n        }\n    }\n    return to.concat(ar || Array.prototype.slice.call(from));\n};\nvar _a;\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.generateID = exports.subtractNailUpReferenceStats = exports.applyPatchForRTT = exports.exposeApplicationStatsForPC = exports.restoreOriginalConsoleMethods = exports.setConsoleLevel = exports.getHardwareInfo = exports.validateEvent = exports.validateRating = exports.isRoomIdOrPeerIdChanged = exports.countOfValidConnections = exports.validateConfig = exports.getConnectionData = exports.dumpStream = exports.map2obj = exports.mangleChromeStats = exports.deltaCompression = exports.getSdkLogWithoutTrace = exports.getSdkLogger = exports.logPrefix = void 0;\nvar GPU = require(\"./detect-gpu\");\nvar stats_1 = require(\"./stats\");\nvar sdk_1 = require(\"./sdk\");\nvar getCurrTimeStamp = function () {\n    var date = new Date();\n    var dateStr = (\"00\" + (date.getMonth() + 1)).slice(-2) +\n        \"/\" +\n        (\"00\" + date.getDate()).slice(-2) +\n        \"/\" +\n        date.getFullYear() +\n        \" \" +\n        (\"00\" + date.getHours()).slice(-2) +\n        \":\" +\n        (\"00\" + date.getMinutes()).slice(-2) +\n        \":\" +\n        (\"00\" + date.getSeconds()).slice(-2) +\n        \":\" +\n        (\"000\" + date.getMilliseconds()).slice(-3);\n    return dateStr;\n};\nvar logPrefix = function (level) {\n    if (level === void 0) { level = \"info\"; }\n    return level === \"error\"\n        ? [\n            \"\".concat(getCurrTimeStamp(), \" %cwatchRTC %cERROR\"),\n            \"background: \".concat(\"gold\", \"; color: black; padding: 2px 0.5em; border-radius: 0.5em;\"),\n            \"background: \".concat(\"red\", \"; color: white; padding: 2px 0.5em; border-radius: 0.5em;\"),\n        ]\n        : [\n            \"\".concat(getCurrTimeStamp(), \" %cwatchRTC\"),\n            \"background: \".concat(\"gold\", \"; color: black; padding: 2px 0.5em; border-radius: 0.5em;\"),\n        ];\n};\nexports.logPrefix = logPrefix;\nvar logLevels = [\"debug\", \"info\", \"error\"];\nvar sdkLogger = function (log, getLogLevel) {\n    if (log === void 0) { log = console.log; }\n    return function (level, message, object) {\n        var allowed = getLogLevel();\n        var allowedValue = logLevels.indexOf(allowed);\n        var currentValue = logLevels.indexOf(level);\n        if (allowed === \"silent\" || currentValue < allowedValue) {\n            return;\n        }\n        var args = __spreadArray(__spreadArray([], (0, exports.logPrefix)(level), true), [message], false);\n        if (object) {\n            args.push(object);\n        }\n        log.apply(void 0, args);\n    };\n};\nexports.getSdkLogger = sdkLogger.bind(null, console.log);\nexports.getSdkLogWithoutTrace = sdkLogger.bind(null, (_a = console._original_log) !== null && _a !== void 0 ? _a : console.log);\n// apply a delta compression to the stats report. Reduces size by ~90%.\n// To reduce further, report keys could be compressed.\n// Muly: maybe can improve using https://github.com/AsyncBanana/microdiff?utm_source=tldrnewsletter\nvar deltaCompression = function (oldStats, newStats) {\n    oldStats = oldStats || {};\n    newStats = newStats || {};\n    newStats = JSON.parse(JSON.stringify(newStats));\n    Object.keys(newStats).forEach(function (id) {\n        var report = newStats[id];\n        delete report.id;\n        if (!oldStats[id]) {\n            return;\n        }\n        Object.keys(report).forEach(function (name) {\n            if (report.timestamp && typeof report.timestamp === \"string\") {\n                report.timestamp = new Date(report.timestamp).getTime();\n            }\n            if (report[name] === oldStats[id][name]) {\n                delete newStats[id][name];\n            }\n            else if (Array.isArray(report[name])) {\n                // Arrays get serialized if anything changed.\n                if (JSON.stringify(report[name]) === JSON.stringify(oldStats[id][name])) {\n                    delete newStats[id][name];\n                }\n            }\n            if (Object.keys(report).length === 0) {\n                delete newStats[id];\n            }\n            else if (Object.keys(report).length === 1 && report.timestamp) {\n                delete newStats[id];\n            }\n        });\n    });\n    var timestamp = -Infinity;\n    Object.keys(newStats).forEach(function (id) {\n        var report = newStats[id];\n        if (report.timestamp > timestamp) {\n            timestamp = report.timestamp;\n        }\n    });\n    Object.keys(newStats).forEach(function (id) {\n        var report = newStats[id];\n        if (report.timestamp === timestamp) {\n            report.timestamp = 0;\n        }\n    });\n    newStats.timestamp = timestamp;\n    return newStats;\n};\nexports.deltaCompression = deltaCompression;\nvar mangleChromeStats = function (pc, response) {\n    var standardReport = {};\n    var reports = response.result();\n    reports.forEach(function (report) {\n        var standardStats = {\n            id: report.id,\n            timestamp: report.timestamp.getTime(),\n            type: report.type,\n        };\n        report.names().forEach(function (name) {\n            standardStats[name] = report.stat(name);\n        });\n        standardReport[standardStats.id] = standardStats;\n    });\n    return standardReport;\n};\nexports.mangleChromeStats = mangleChromeStats;\n// transforms a maplike to an object. Mostly for getStats +\n// JSON.parse(JSON.stringify())\nvar map2obj = function (m) {\n    if (!m.entries) {\n        return m;\n    }\n    var o = {};\n    m.forEach(function (v, k) {\n        o[k] = v;\n    });\n    return o;\n};\nexports.map2obj = map2obj;\nvar dumpStream = function (stream) {\n    return {\n        id: stream.id,\n        tracks: stream.getTracks().map(function (track) {\n            return {\n                id: track.id,\n                kind: track.kind,\n                label: track.label,\n                enabled: track.enabled,\n                muted: track.muted,\n                readyState: track.readyState, // `live` or `ended`\n            };\n        }),\n    };\n};\nexports.dumpStream = dumpStream;\nvar getConnectionData = function (type, key, proxyURL) {\n    var localUrl = \"\".concat(type == \"ws\" ? \"ws\" : \"http\", \"://localhost:9101\");\n    var staging1Url = \"\".concat(type == \"ws\" ? \"wss\" : \"https\", \"://watchrtc-staging1.testrtc.com\");\n    var staging2Url = \"\".concat(type == \"ws\" ? \"wss\" : \"https\", \"://watchrtc-staging2.testrtc.com\");\n    var productionUrl = \"\".concat(type == \"ws\" ? \"wss\" : \"https\", \"://watchrtc.testrtc.com\");\n    var production1Url = \"\".concat(type == \"ws\" ? \"wss\" : \"https\", \"://watchrtc-app1.testrtc.com\");\n    if (proxyURL && type === \"http\") {\n        if (proxyURL.includes(\"wss://\")) {\n            proxyURL = proxyURL.replace(\"wss://\", \"https://\");\n        }\n        else {\n            proxyURL = proxyURL.replace(\"ws://\", \"http://\");\n        }\n    }\n    var splitted = key.split(\":\");\n    if (key.indexOf(\"local\") !== -1) {\n        return {\n            url: proxyURL || localUrl,\n            key: splitted[1],\n        };\n    }\n    else if (key.indexOf(\"staging1\") !== -1) {\n        return {\n            url: proxyURL || staging1Url,\n            key: splitted[1],\n        };\n    }\n    else if (key.indexOf(\"staging\") !== -1) {\n        return {\n            url: proxyURL || staging2Url,\n            key: splitted[1],\n        };\n    }\n    else if (key.indexOf(\"production1\") !== -1) {\n        return {\n            url: proxyURL || production1Url,\n            key: splitted[1],\n        };\n    }\n    else if (key.indexOf(\"production\") !== -1) {\n        return {\n            url: proxyURL || productionUrl,\n            key: splitted[1],\n        };\n    }\n    else {\n        return {\n            url: proxyURL || productionUrl,\n            key: splitted[0],\n        };\n    }\n};\nexports.getConnectionData = getConnectionData;\nvar validateConfig = function (config) {\n    if (!(config === null || config === void 0 ? void 0 : config.rtcApiKey)) {\n        (0, sdk_1.sdkLog)(\"debug\", \"config.rtcApiKey or config.rtcToken need to be provided.\");\n        return false;\n    }\n    if (!(config === null || config === void 0 ? void 0 : config.rtcRoomId) || !(config === null || config === void 0 ? void 0 : config.rtcPeerId)) {\n        (0, sdk_1.sdkLog)(\"debug\", \"config.rtcRoomId or config.rtcPeerId is empty.\");\n        return false;\n    }\n    return true;\n};\nexports.validateConfig = validateConfig;\nvar countOfValidConnections = function (openChannels) {\n    return Object.keys(openChannels).filter(function (id) { return openChannels[id].validConnection; }).length;\n};\nexports.countOfValidConnections = countOfValidConnections;\nvar isRoomIdOrPeerIdChanged = function (watchrtcIdentifiers, watchrtcConfig) {\n    var changed = false;\n    if (watchrtcConfig.rtcRoomId &&\n        watchrtcIdentifiers.rtcRoomId &&\n        watchrtcIdentifiers.rtcRoomId !== watchrtcConfig.rtcRoomId) {\n        changed = true;\n    }\n    if (watchrtcConfig.rtcPeerId &&\n        watchrtcIdentifiers.rtcPeerId &&\n        watchrtcIdentifiers.rtcPeerId !== watchrtcConfig.rtcPeerId) {\n        changed = true;\n    }\n    if (changed) {\n        (0, sdk_1.sdkLog)(\"debug\", \"maybeOpenWebsocketConnection. rtcRoomId or rtcPeerId has been changed\", {\n            old: {\n                rtcRoomId: watchrtcIdentifiers.rtcRoomId,\n                rtcPeerId: watchrtcIdentifiers.rtcPeerId,\n            },\n            new: {\n                rtcRoomId: watchrtcConfig.rtcRoomId,\n                rtcPeerId: watchrtcConfig.rtcPeerId,\n            },\n        });\n    }\n    return changed;\n};\nexports.isRoomIdOrPeerIdChanged = isRoomIdOrPeerIdChanged;\nvar validateRating = function (rating) {\n    if (!rating) {\n        (0, sdk_1.sdkLog)(\"error\", \"rating parameter is required\");\n        return false;\n    }\n    if (typeof rating !== \"number\" || rating < 1 || rating > 5) {\n        (0, sdk_1.sdkLog)(\"error\", \"rating parameter should be number from 1 to 5\");\n        return false;\n    }\n    return true;\n};\nexports.validateRating = validateRating;\nvar validateEvent = function (event, channels) {\n    if (!event) {\n        (0, sdk_1.sdkLog)(\"error\", \"event parameter is required\");\n        return false;\n    }\n    if (![\"global\", \"local\", \"log\"].includes(event.type)) {\n        (0, sdk_1.sdkLog)(\"error\", \"event.type should be either \\\"global\\\" or \\\"local\\\" or \\\"log\\\"\");\n        return false;\n    }\n    if (event.parameters && typeof event.parameters !== \"object\") {\n        (0, sdk_1.sdkLog)(\"error\", \"event.parameters should be JSON object\\\"\");\n        return false;\n    }\n    if (event.pc && !(event.pc.__rtcStatsId in channels)) {\n        (0, sdk_1.sdkLog)(\"error\", \"event.pc should be a RTCPeerConnection used in the call\\\"\");\n        return false;\n    }\n    return true;\n};\nexports.validateEvent = validateEvent;\nvar getHardwareInfo = function () { return __awaiter(void 0, void 0, void 0, function () {\n    function number_format(num) {\n        return (Math.round(num * 100) / 100).toFixed(2);\n    }\n    var loadBenchmarks, gpuInfo, result, memory;\n    return __generator(this, function (_a) {\n        switch (_a.label) {\n            case 0:\n                if (typeof window === \"undefined\") {\n                    return [2 /*return*/];\n                }\n                loadBenchmarks = function (fileName) { return __awaiter(void 0, void 0, void 0, function () {\n                    return __generator(this, function (_a) {\n                        switch (_a.label) {\n                            case 0: return [4 /*yield*/, new Promise(function (resolve) {\n                                    try {\n                                        var data = require(\"./gpu-benchmarks/\".concat(fileName));\n                                        data.shift();\n                                        return resolve(data);\n                                    }\n                                    catch (err) {\n                                        (0, sdk_1.sdkLog)(\"error\", \"Error. getHardwareInfo. loadBenchmarks\", { err: err.stack, fileName: fileName });\n                                        resolve([]);\n                                    }\n                                })];\n                            case 1: return [2 /*return*/, _a.sent()];\n                        }\n                    });\n                }); };\n                return [4 /*yield*/, GPU.getGPUTier({\n                        override: { loadBenchmarks: loadBenchmarks },\n                    })];\n            case 1:\n                gpuInfo = _a.sent();\n                result = __assign(__assign({}, gpuInfo), { cores_count: window.navigator.hardwareConcurrency });\n                memory = window.performance[\"memory\"];\n                if (memory) {\n                    result.jsHeapSizeLimit = number_format(memory.jsHeapSizeLimit / 1048576);\n                    result.totalJSHeapSize = number_format(memory.totalJSHeapSize / 1048576);\n                    result.usedJSHeapSize = number_format(memory.usedJSHeapSize / 1048576);\n                }\n                return [2 /*return*/, result];\n        }\n    });\n}); };\nexports.getHardwareInfo = getHardwareInfo;\nvar patchConsoleConfig = {\n    originalMethodPrefix: \"_original_\",\n    methodsToPatch: [\"log\", \"debug\", \"info\", \"warn\", \"error\"],\n    level: \"\",\n};\nvar patchConsoleMethod = function (methodName, trace) {\n    var originalMethod = console[methodName];\n    if (!originalMethod) {\n        return;\n    }\n    console[patchConsoleConfig.originalMethodPrefix + methodName] = originalMethod;\n    console[methodName] = function () {\n        var args = [];\n        for (var _i = 0; _i < arguments.length; _i++) {\n            args[_i] = arguments[_i];\n        }\n        if (patchConsoleConfig.level && args.length && trace) {\n            var currentMethodIndex = patchConsoleConfig.methodsToPatch.indexOf(methodName);\n            var configMethodIndex = patchConsoleConfig.methodsToPatch.indexOf(patchConsoleConfig.level);\n            var shouldTraceMethod = currentMethodIndex >= 0 && currentMethodIndex >= configMethodIndex;\n            if (shouldTraceMethod) {\n                var text = stringifyArgs(args);\n                trace({ data: [\"log\", null, { type: methodName, text: text }] });\n            }\n        }\n        originalMethod.apply(console, args);\n    };\n};\nvar setConsoleLevel = function (level, trace) {\n    if (level && patchConsoleConfig.methodsToPatch.includes(level) && level !== patchConsoleConfig.level) {\n        var currentIndex = patchConsoleConfig.methodsToPatch.indexOf(level);\n        var previousIndex = patchConsoleConfig.methodsToPatch.indexOf(patchConsoleConfig.level);\n        if (previousIndex < 0) {\n            for (var _i = 0, _a = patchConsoleConfig.methodsToPatch.slice(currentIndex); _i < _a.length; _i++) {\n                var methodName = _a[_i];\n                patchConsoleMethod(methodName, trace);\n            }\n        }\n        else if (currentIndex < previousIndex) {\n            for (var _b = 0, _c = patchConsoleConfig.methodsToPatch.slice(currentIndex, previousIndex); _b < _c.length; _b++) {\n                var methodName = _c[_b];\n                patchConsoleMethod(methodName, trace);\n            }\n        }\n        patchConsoleConfig.level = level;\n    }\n};\nexports.setConsoleLevel = setConsoleLevel;\nvar restoreOriginalConsoleMethods = function () {\n    if (!(\"console\" in window)) {\n        return;\n    }\n    for (var _i = 0, _a = patchConsoleConfig.methodsToPatch; _i < _a.length; _i++) {\n        var methodName = _a[_i];\n        var originalMethod = console[patchConsoleConfig.originalMethodPrefix + methodName];\n        if (!originalMethod) {\n            continue;\n        }\n        console[methodName] = originalMethod.bind(console);\n        delete console[patchConsoleConfig.originalMethodPrefix + methodName];\n    }\n};\nexports.restoreOriginalConsoleMethods = restoreOriginalConsoleMethods;\nvar exposeApplicationStatsForPC = function (id, previous, current, mappedTradk) {\n    return {\n        peer: (0, stats_1.getTransportFromStats)(id, current),\n        streams: (0, stats_1.getStreamsFromStats)(id, previous, current, mappedTradk),\n    };\n};\nexports.exposeApplicationStatsForPC = exposeApplicationStatsForPC;\nvar stringifyArgs = function (args) {\n    try {\n        return args.map(function (item) { return (typeof item === \"string\" ? item : JSON.stringify(item, replacerFunc())); }).join(\" \");\n    }\n    catch (_a) {\n        // do not log anything to not go into loop\n        // can fail with Illegal Invocation of JSON.stringify\n        // assumption - when customer also uses custom logger and binds another context\n        // so just ignore it\n        return \"\";\n    }\n};\n// avoid \"Converting circular structure to JSON\" error while JSON.stringifying\nvar replacerFunc = function () {\n    var visited = new WeakSet();\n    return function (_key, value) {\n        if (typeof value === \"object\" && value !== null) {\n            if (visited.has(value)) {\n                return;\n            }\n            visited.add(value);\n        }\n        return value;\n    };\n};\nvar applyPatchForRTT = function (oldStats, newStats) {\n    oldStats = oldStats || {};\n    newStats = newStats || {};\n    var hasOldStats = true;\n    if (Object.keys(oldStats).length === 0) {\n        hasOldStats = false;\n    }\n    var keys = Object.keys(newStats);\n    var reportKeys = keys.filter(function (key) { return newStats[key].type === \"remote-outbound-rtp\" || newStats[key].type === \"remote-inbound-rtp\"; });\n    reportKeys.forEach(function (reportKey) {\n        // case for Firefox/Safari\n        if (!(\"roundTripTime\" in newStats[reportKey])) {\n            newStats[reportKey].roundTripTime = NaN;\n        }\n        else {\n            // case Chrome\n            var statsHaveRTTMeasurements = \"roundTripTimeMeasurements\" in newStats[reportKey] &&\n                Boolean(oldStats[reportKey]) &&\n                \"roundTripTimeMeasurements\" in oldStats[reportKey];\n            if (hasOldStats && statsHaveRTTMeasurements) {\n                if (newStats[reportKey].roundTripTimeMeasurements === oldStats[reportKey].roundTripTimeMeasurements) {\n                    newStats[reportKey].roundTripTime = NaN;\n                }\n            }\n        }\n    });\n    return newStats;\n};\nexports.applyPatchForRTT = applyPatchForRTT;\nvar subtractNailUpReferenceStats = function (referenceStats, newStats) {\n    var _loop_1 = function (key, report) {\n        if (key in referenceStats) {\n            var referenceReport_1 = referenceStats[key];\n            switch (report.type) {\n                case \"inbound-rtp\":\n                    [\n                        \"bytesReceived\",\n                        \"packetsReceived\",\n                        \"packetsLost\",\n                        \"framesDecoded\",\n                        \"keyFramesDecoded\",\n                        \"framesRendered\",\n                        \"framesDropped\",\n                        \"qpSum\",\n                        \"totalDecodeTime\",\n                        \"totalInterFrameDelay\",\n                        \"totalSquaredInterFrameDelay\",\n                        \"pauseCount\",\n                        \"totalPausesDuration\",\n                        \"freezeCount\",\n                        \"totalFreezesDuration\",\n                        \"headerBytesReceived\",\n                        \"packetsDiscarded\",\n                        \"fecBytesReceived\",\n                        \"fecPacketsReceived\",\n                        \"fecPacketsDiscarded\",\n                        \"firCount\",\n                        \"pliCount\",\n                        \"totalProcessingDelay\",\n                        \"nackCount\",\n                        \"jitterBufferEmittedCount\",\n                        \"totalSamplesReceived\",\n                        \"concealedSamples\",\n                        \"silentConcealedSamples\",\n                        \"concealmentEvents\",\n                        \"totalAudioEnergy\",\n                        \"totalSamplesDuration\",\n                        \"framesReceived\",\n                        \"framesAssembledFromMultiplePackets\",\n                        \"totalAssemblyTime\",\n                        \"retransmittedPacketsReceived\",\n                        \"retransmittedBytesReceived\",\n                    ].forEach(function (stat) {\n                        if (stat in report) {\n                            report[stat] = Math.max(report[stat] - referenceReport_1[stat], 0);\n                        }\n                    });\n                    break;\n                case \"outbound-rtp\":\n                    [\n                        \"packetsSent\",\n                        \"bytesSent\",\n                        \"headerBytesSent\",\n                        \"retransmittedPacketsSent\",\n                        \"retransmittedBytesSent\",\n                        \"totalEncodedBytesTarget\",\n                        \"framesSent\",\n                        \"hugeFramesSent\",\n                        \"framesEncoded\",\n                        \"keyFramesEncoded\",\n                        \"qpSum\",\n                        \"totalEncodeTime\",\n                        \"totalPacketsSendDelay\",\n                        \"qualityLimitationResolutionChanges\",\n                        \"qualityLimitationDurations\",\n                        \"nackCount\",\n                        \"firCount\",\n                        \"pliCount\",\n                    ].forEach(function (stat) {\n                        if (stat in report) {\n                            if (stat === \"qualityLimitationDurations\") {\n                                report[stat].bandwidth = Math.max(report[stat].bandwidth - referenceReport_1[stat].bandwidth, 0);\n                                report[stat].cpu = Math.max(report[stat].cpu - referenceReport_1[stat].cpu, 0);\n                                report[stat].other = Math.max(report[stat].other - referenceReport_1[stat].other, 0);\n                                report[stat].none = Math.max(report[stat].none - referenceReport_1[stat].none, 0);\n                            }\n                            else {\n                                report[stat] = Math.max(report[stat] - referenceReport_1[stat], 0);\n                            }\n                        }\n                    });\n                    break;\n                case \"remote-inbound-rtp\":\n                    [\"packetsReceived\", \"packetsLost\", \"totalRoundTripTime\", \"roundTripTimeMeasurements\"].forEach(function (stat) {\n                        if (stat in report) {\n                            report[stat] = Math.max(report[stat] - referenceReport_1[stat], 0);\n                        }\n                    });\n                    break;\n                case \"remote-outbound-rtp\":\n                    [\"packetsSent\", \"bytesSent\", \"totalRoundTripTime\", \"roundTripTimeMeasurements\"].forEach(function (stat) {\n                        if (stat in report) {\n                            report[stat] = Math.max(report[stat] - referenceReport_1[stat], 0);\n                        }\n                    });\n                    break;\n                case \"media-source\":\n                    [\n                        \"totalAudioEnergy\",\n                        \"totalSamplesDuration\",\n                        \"droppedSamplesDuration\",\n                        \"droppedSamplesEvents\",\n                        \"totalCaptureDelay\",\n                        \"totalSamplesCaptured\",\n                        \"frames\",\n                    ].forEach(function (stat) {\n                        if (stat in report) {\n                            report[stat] = Math.max(report[stat] - referenceReport_1[stat], 0);\n                        }\n                    });\n                    break;\n                case \"media-playout\":\n                    [\n                        \"synthesizedSamplesDuration\",\n                        \"synthesizedSamplesEvents\",\n                        \"totalSamplesDuration\",\n                        \"totalPlayoutDelay\",\n                        \"totalSamplesCount\",\n                    ].forEach(function (stat) {\n                        if (stat in report) {\n                            report[stat] = Math.max(report[stat] - referenceReport_1[stat], 0);\n                        }\n                    });\n                    break;\n                case \"peer-connection\":\n                    [\"dataChannelsOpened\", \"dataChannelsClosed\"].forEach(function (stat) {\n                        if (stat in report) {\n                            report[stat] = Math.max(report[stat] - referenceReport_1[stat], 0);\n                        }\n                    });\n                    break;\n                case \"data-channel\":\n                    [\"messagesSent\", \"bytesSent\", \"messagesReceived\", \"bytesReceived\"].forEach(function (stat) {\n                        if (stat in report) {\n                            report[stat] = Math.max(report[stat] - referenceReport_1[stat], 0);\n                        }\n                    });\n                    break;\n                case \"transport\":\n                    [\"packetsSent\", \"packetsReceived\", \"bytesSent\", \"bytesReceived\", \"selectedCandidatePairChanges\"].forEach(function (stat) {\n                        if (stat in report) {\n                            report[stat] = Math.max(report[stat] - referenceReport_1[stat], 0);\n                        }\n                    });\n                    break;\n                case \"candidate-pair\":\n                    [\n                        \"packetsSent\",\n                        \"packetsReceived\",\n                        \"bytesSent\",\n                        \"bytesReceived\",\n                        \"totalRoundTripTime\",\n                        \"requestsReceived\",\n                        \"requestsSent\",\n                        \"responsesReceived\",\n                        \"responsesSent\",\n                        \"consentRequestsSent\",\n                        \"packetsDiscardedOnSend\",\n                        \"bytesDiscardedOnSend\",\n                    ].forEach(function (stat) {\n                        if (stat in report) {\n                            report[stat] = Math.max(report[stat] - referenceReport_1[stat], 0);\n                        }\n                    });\n                    break;\n                default:\n                    break;\n            }\n        }\n    };\n    for (var _i = 0, _a = Object.entries(newStats); _i < _a.length; _i++) {\n        var _b = _a[_i], key = _b[0], report = _b[1];\n        _loop_1(key, report);\n    }\n    return newStats;\n};\nexports.subtractNailUpReferenceStats = subtractNailUpReferenceStats;\nvar generateID = function () {\n    return Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);\n};\nexports.generateID = generateID;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.default = \"1.38.2\";\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar sdk_1 = require(\"./sdk\");\nvar WatchRTCHttp = /** @class */ (function () {\n    function WatchRTCHttp() {\n        if (WatchRTCHttp._instance) {\n            (0, sdk_1.sdkLog)(\"info\", \"WatchRTCSocket instance already created\");\n        }\n        else {\n            WatchRTCHttp._instance = this;\n        }\n    }\n    WatchRTCHttp.prototype.trace = function (url, projectId, rtcRoomId, rtcPeerId) {\n        var data = [];\n        for (var _i = 4; _i < arguments.length; _i++) {\n            data[_i - 4] = arguments[_i];\n        }\n        var args = Array.prototype.slice.call(data);\n        args.push(Date.now());\n        if (args[1] instanceof RTCPeerConnection) {\n            args[1] = args[1].__rtcStatsId;\n        }\n        var response = fetch(url, {\n            method: \"POST\",\n            mode: \"cors\",\n            cache: \"no-cache\",\n            credentials: \"same-origin\",\n            headers: {\n                \"Content-Type\": \"application/json\",\n            },\n            body: JSON.stringify({\n                data: data,\n                projectId: projectId,\n                rtcRoomId: rtcRoomId,\n                rtcPeerId: rtcPeerId,\n            }),\n        });\n        return response\n            .then(function () { return ({}); })\n            .catch(function (err) {\n            (0, sdk_1.sdkLog)(\"error\", err.message, { err: err.stack });\n            return { error: err };\n        });\n    };\n    return WatchRTCHttp;\n}());\nexports.default = WatchRTCHttp;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar sdk_1 = require(\"./sdk\");\nvar LZString = require(\"./lz-string\");\nvar PROTOCOL_VERSION = \"2.0\";\nvar MSG_TIME_DIFF_THRESHLOD = 12 * 60 * 60 * 1000; // 12 hours\nvar isBrowser = typeof window !== \"undefined\";\nvar globalContext = isBrowser ? window : global;\nvar WatchRTCSocket = /** @class */ (function () {\n    function WatchRTCSocket() {\n        var _this_1 = this;\n        this.connection = null;\n        this.wasConnected = false;\n        this.buffer = [];\n        this.sendInterval = 1;\n        this.onClose = function () { };\n        this.dataCollection = true;\n        this.sendPromises = [];\n        this.prevMessageTs = Date.now();\n        this.trace = function (_a) {\n            var data = _a.data, options = _a.options;\n            var args = Array.prototype.slice.call(data);\n            var prevMessageTs = _this_1.prevMessageTs;\n            var now = Date.now();\n            var timeSinceLastMessage = now - prevMessageTs;\n            if (Math.abs(timeSinceLastMessage) >= MSG_TIME_DIFF_THRESHLOD) {\n                _this_1.trace({ data: [\"timeChange\", null, { now: now, prevMessageTs: prevMessageTs, timeSinceLastMessage: timeSinceLastMessage }] });\n            }\n            args.push(now);\n            if (args[1] instanceof RTCPeerConnection) {\n                args[1] = args[1].__rtcStatsId;\n            }\n            if (!WatchRTCSocket._instance.dataCollection) {\n                if (options === null || options === void 0 ? void 0 : options.promiseFuncs) {\n                    options.promiseFuncs.resolve({ error: \"Data collection disabled\" });\n                }\n                return;\n            }\n            // Don't store a new message if the connection is not open and the buffer is full (> 1000 messages)\n            if (!WatchRTCSocket._instance.connection ||\n                WatchRTCSocket._instance.connection.readyState !== globalContext.WebSocket.OPEN) {\n                if (WatchRTCSocket._instance.buffer.length > 1000) {\n                    if (options === null || options === void 0 ? void 0 : options.promiseFuncs) {\n                        options.promiseFuncs.resolve({ error: \"Message buffer size exceeded\" });\n                    }\n                    return;\n                }\n            }\n            // Else, store the message in the buffer\n            WatchRTCSocket._instance.buffer.push(args);\n            if (options === null || options === void 0 ? void 0 : options.promiseFuncs) {\n                WatchRTCSocket._instance.sendPromises.push(options.promiseFuncs);\n            }\n            // If the connection is open and the buffer threshold is reached, send the messages\n            if (WatchRTCSocket._instance.connection &&\n                WatchRTCSocket._instance.connection.readyState === globalContext.WebSocket.OPEN) {\n                if (WatchRTCSocket._instance.buffer.length >= WatchRTCSocket._instance.sendInterval) {\n                    var lines = JSON.stringify(WatchRTCSocket._instance.buffer);\n                    var compressedMessage = LZString.compressToEncodedURIComponent(lines);\n                    (0, sdk_1.sdkLogWithoutTrace)(\"debug\", \"lines: \".concat(lines.length));\n                    (0, sdk_1.sdkLogWithoutTrace)(\"debug\", \"compressedMessage: \".concat(compressedMessage.length));\n                    WatchRTCSocket._instance.buffer = [];\n                    WatchRTCSocket._instance.connection.send(compressedMessage);\n                    WatchRTCSocket._instance.sendPromises.forEach(function (_a) {\n                        var resolve = _a.resolve;\n                        return resolve({});\n                    });\n                    WatchRTCSocket._instance.sendPromises = [];\n                }\n            }\n        };\n        if (WatchRTCSocket._instance) {\n            (0, sdk_1.sdkLog)(\"info\", \"WatchRTCSocket instance already created\");\n        }\n        else {\n            WatchRTCSocket._instance = this;\n        }\n    }\n    WatchRTCSocket.prototype.connect = function (_a) {\n        var url = _a.url, onData = _a.onData, onError = _a.onError, onOpen = _a.onOpen, onClose = _a.onClose, _b = _a.options, options = _b === void 0 ? {} : _b;\n        var cleanOldTraces = options.cleanOldTraces;\n        if (WatchRTCSocket._instance.connection) {\n            WatchRTCSocket._instance.connection.close();\n            WatchRTCSocket._instance.connection = null;\n        }\n        var _this = WatchRTCSocket._instance;\n        if (cleanOldTraces) {\n            // we want to keep last 10 minutes of logs, to prevent old logs timestamp impacting actual session duration\n            var timeThreshold_1 = Date.now() - 10 * 60 * 1000; // 10 min\n            var relevantTraces = _this.buffer.filter(function (data) { return data[3] > timeThreshold_1; });\n            var filteredCount = _this.buffer.length - relevantTraces.length;\n            _this.buffer = relevantTraces;\n            var args = [\"oldTracesCleanup\", null, { filteredCount: filteredCount }, Date.now()];\n            (0, sdk_1.sdkLog)(\"info\", \"watchRTC SDK flushed \".concat(filteredCount, \" messages\"));\n            _this.buffer.push(args);\n        }\n        WatchRTCSocket._instance.connection = new globalContext.WebSocket(url, PROTOCOL_VERSION);\n        WatchRTCSocket._instance.connection.onopen = onOpen || null;\n        WatchRTCSocket._instance.connection.onclose = onClose || null;\n        WatchRTCSocket._instance.connection.onmessage = function (e) {\n            var _a;\n            try {\n                var data = JSON.parse(e.data);\n                if (data.error) {\n                    (_a = _this === null || _this === void 0 ? void 0 : _this.connection) === null || _a === void 0 ? void 0 : _a.close();\n                    _this.connection = null;\n                    (0, sdk_1.sdkLog)(\"error\", \"\\n\" + data.error);\n                    onError(data.error, \"auth\");\n                }\n                else {\n                    if (data.sendInterval) {\n                        WatchRTCSocket._instance.sendInterval = data.sendInterval;\n                    }\n                    onData(data);\n                    WatchRTCSocket._instance.wasConnected = true;\n                }\n            }\n            catch (err) {\n                (0, sdk_1.sdkLog)(\"error\", \"\\n\", { err: err.stack });\n                onError(err.message);\n            }\n        };\n        WatchRTCSocket._instance.connection.onerror = function (e) {\n            (0, sdk_1.sdkLog)(\"error\", \"\\n\", e);\n            onError(e, \"connection\");\n        };\n    };\n    WatchRTCSocket.prototype.close = function (nailUpCallEnd) {\n        var _a, _b;\n        if (nailUpCallEnd && ((_b = (_a = WatchRTCSocket._instance) === null || _a === void 0 ? void 0 : _a.connection) === null || _b === void 0 ? void 0 : _b.readyState) === globalContext.WebSocket.OPEN) {\n            var lines = JSON.stringify([\"nailUpCallEnd\", null, null, Date.now()]);\n            var compressedMessage = LZString.compressToEncodedURIComponent(lines);\n            WatchRTCSocket._instance.connection.send(compressedMessage);\n        }\n        WatchRTCSocket._instance.buffer = [];\n        WatchRTCSocket._instance.sendPromises.forEach(function (_a) {\n            var resolve = _a.resolve;\n            return resolve({ error: \"Connection was close\" });\n        });\n        WatchRTCSocket._instance.sendPromises = [];\n        if (WatchRTCSocket._instance.connection) {\n            WatchRTCSocket._instance.connection.close();\n            WatchRTCSocket._instance.onClose();\n            WatchRTCSocket._instance.connection = null;\n        }\n    };\n    WatchRTCSocket.prototype.disableDataCollection = function () {\n        (0, sdk_1.sdkLog)(\"debug\", \"Data collection disabled.\");\n        WatchRTCSocket._instance.dataCollection = false;\n    };\n    WatchRTCSocket.prototype.enableDataCollection = function () {\n        (0, sdk_1.sdkLog)(\"debug\", \"Data collection enabled.\");\n        WatchRTCSocket._instance.dataCollection = true;\n    };\n    WatchRTCSocket.prototype.isDisabledDataCollection = function () {\n        return !WatchRTCSocket._instance.dataCollection;\n    };\n    return WatchRTCSocket;\n}());\nexports.default = WatchRTCSocket;\n","!(function (e, r) {\n  \"object\" == typeof exports && \"undefined\" != typeof module\n    ? r(exports)\n    : \"function\" == typeof define && define.amd\n    ? define([\"exports\"], r)\n    : r(((e = \"undefined\" != typeof globalThis ? globalThis : e || self).DetectGPU = {}));\n})(this, function (e) {\n  \"use strict\";\n  var r = function (e, n) {\n    return (r =\n      Object.setPrototypeOf ||\n      ({ __proto__: [] } instanceof Array &&\n        function (e, r) {\n          e.__proto__ = r;\n        }) ||\n      function (e, r) {\n        for (var n in r) Object.prototype.hasOwnProperty.call(r, n) && (e[n] = r[n]);\n      })(e, n);\n  };\n  function n(e, r, n, t) {\n    return new (n || (n = Promise))(function (o, a) {\n      function i(e) {\n        try {\n          u(t.next(e));\n        } catch (e) {\n          a(e);\n        }\n      }\n      function c(e) {\n        try {\n          u(t.throw(e));\n        } catch (e) {\n          a(e);\n        }\n      }\n      function u(e) {\n        var r;\n        e.done\n          ? o(e.value)\n          : ((r = e.value),\n            r instanceof n\n              ? r\n              : new n(function (e) {\n                  e(r);\n                })).then(i, c);\n      }\n      u((t = t.apply(e, r || [])).next());\n    });\n  }\n  function t(e, r) {\n    var n,\n      t,\n      o,\n      a,\n      i = {\n        label: 0,\n        sent: function () {\n          if (1 & o[0]) throw o[1];\n          return o[1];\n        },\n        trys: [],\n        ops: [],\n      };\n    return (\n      (a = { next: c(0), throw: c(1), return: c(2) }),\n      \"function\" == typeof Symbol &&\n        (a[Symbol.iterator] = function () {\n          return this;\n        }),\n      a\n    );\n    function c(a) {\n      return function (c) {\n        return (function (a) {\n          if (n) throw new TypeError(\"Generator is already executing.\");\n          for (; i; )\n            try {\n              if (\n                ((n = 1),\n                t &&\n                  (o = 2 & a[0] ? t.return : a[0] ? t.throw || ((o = t.return) && o.call(t), 0) : t.next) &&\n                  !(o = o.call(t, a[1])).done)\n              )\n                return o;\n              switch (((t = 0), o && (a = [2 & a[0], o.value]), a[0])) {\n                case 0:\n                case 1:\n                  o = a;\n                  break;\n                case 4:\n                  return i.label++, { value: a[1], done: !1 };\n                case 5:\n                  i.label++, (t = a[1]), (a = [0]);\n                  continue;\n                case 7:\n                  (a = i.ops.pop()), i.trys.pop();\n                  continue;\n                default:\n                  if (!((o = i.trys), (o = o.length > 0 && o[o.length - 1]) || (6 !== a[0] && 2 !== a[0]))) {\n                    i = 0;\n                    continue;\n                  }\n                  if (3 === a[0] && (!o || (a[1] > o[0] && a[1] < o[3]))) {\n                    i.label = a[1];\n                    break;\n                  }\n                  if (6 === a[0] && i.label < o[1]) {\n                    (i.label = o[1]), (o = a);\n                    break;\n                  }\n                  if (o && i.label < o[2]) {\n                    (i.label = o[2]), i.ops.push(a);\n                    break;\n                  }\n                  o[2] && i.ops.pop(), i.trys.pop();\n                  continue;\n              }\n              a = r.call(e, i);\n            } catch (e) {\n              (a = [6, e]), (t = 0);\n            } finally {\n              n = o = 0;\n            }\n          if (5 & a[0]) throw a[1];\n          return { value: a[0] ? a[1] : void 0, done: !0 };\n        })([a, c]);\n      };\n    }\n  }\n  var o = [\n    \"geforce 320m\",\n    \"geforce 8600\",\n    \"geforce 8600m gt\",\n    \"geforce 8800 gs\",\n    \"geforce 8800 gt\",\n    \"geforce 9400\",\n    \"geforce 9400m g\",\n    \"geforce 9400m\",\n    \"geforce 9600m gt\",\n    \"geforce 9600m\",\n    \"geforce fx go5200\",\n    \"geforce gt 120\",\n    \"geforce gt 130\",\n    \"geforce gt 330m\",\n    \"geforce gtx 285\",\n    \"google swiftshader\",\n    \"intel g41\",\n    \"intel g45\",\n    \"intel gma 4500mhd\",\n    \"intel gma x3100\",\n    \"intel hd 3000\",\n    \"intel q45\",\n    \"legacy\",\n    \"mali-2\",\n    \"mali-3\",\n    \"mali-4\",\n    \"quadro fx 1500\",\n    \"quadro fx 4\",\n    \"quadro fx 5\",\n    \"radeon hd 2400\",\n    \"radeon hd 2600\",\n    \"radeon hd 4670\",\n    \"radeon hd 4850\",\n    \"radeon hd 4870\",\n    \"radeon hd 5670\",\n    \"radeon hd 5750\",\n    \"radeon hd 6290\",\n    \"radeon hd 6300\",\n    \"radeon hd 6310\",\n    \"radeon hd 6320\",\n    \"radeon hd 6490m\",\n    \"radeon hd 6630m\",\n    \"radeon hd 6750m\",\n    \"radeon hd 6770m\",\n    \"radeon hd 6970m\",\n    \"sgx 543\",\n    \"sgx543\",\n  ];\n  function a(e) {\n    return (e = e\n      .toLowerCase()\n      .replace(/^angle ?\\((.+)\\)*$/, \"$1\")\n      .replace(/\\s(\\d{1,2}gb|direct3d.+$)|\\(r\\)| \\([^)]+\\)$/g, \"\"));\n  }\n  const i = 34962;\n  var c = \"undefined\" == typeof window,\n    u = (function () {\n      if (!c) {\n        var e = window.navigator,\n          r = e.userAgent,\n          n = e.platform,\n          t = e.maxTouchPoints,\n          o = /(iphone|ipod|ipad)/i.test(r),\n          a = \"iPad\" === n || (\"MacIntel\" === n && t > 0 && !window.MSStream);\n        return { isIpad: a, isMobile: /android/i.test(r) || o || a, isSafari12: /Version\\/12.+Safari/.test(r) };\n      }\n    })();\n  function f(e, r, n) {\n    if (!n) return [r];\n    var t,\n      o = (function (e) {\n        var r =\n            \"\\n    precision highp float;\\n    attribute vec3 aPosition;\\n    varying float vvv;\\n    void main() {\\n      vvv = 0.31622776601683794;\\n      gl_Position = vec4(aPosition, 1.0);\\n    }\\n  \",\n          n =\n            \"\\n    precision highp float;\\n    varying float vvv;\\n    void main() {\\n      vec4 enc = vec4(1.0, 255.0, 65025.0, 16581375.0) * vvv;\\n      enc = fract(enc);\\n      enc -= enc.yzww * vec4(1.0 / 255.0, 1.0 / 255.0, 1.0 / 255.0, 0.0);\\n      gl_FragColor = enc;\\n    }\\n  \",\n          t = e.createShader(35633),\n          o = e.createShader(35632),\n          a = e.createProgram();\n        if (!(o && t && a)) return;\n        e.shaderSource(t, r),\n          e.shaderSource(o, n),\n          e.compileShader(t),\n          e.compileShader(o),\n          e.attachShader(a, t),\n          e.attachShader(a, o),\n          e.linkProgram(a),\n          e.detachShader(a, t),\n          e.detachShader(a, o),\n          e.deleteShader(t),\n          e.deleteShader(o),\n          e.useProgram(a);\n        var c = e.createBuffer();\n        e.bindBuffer(i, c), e.bufferData(i, new Float32Array([-1, -1, 0, 3, -1, 0, -1, 3, 0]), 35044);\n        var u = e.getAttribLocation(a, \"aPosition\");\n        e.vertexAttribPointer(u, 3, 5126, !1, 0, 0),\n          e.enableVertexAttribArray(u),\n          e.clearColor(1, 1, 1, 1),\n          e.clear(16384),\n          e.viewport(0, 0, 1, 1),\n          e.drawArrays(4, 0, 3);\n        var f = new Uint8Array(4);\n        return e.readPixels(0, 0, 1, 1, 6408, 5121, f), e.deleteProgram(a), e.deleteBuffer(c), f.join(\"\");\n      })(e),\n      a = \"801621810\",\n      c = \"8016218135\",\n      f = \"80162181161\",\n      l = (null == u ? void 0 : u.isIpad)\n        ? [\n            [\"a7\", f, 12],\n            [\"a8\", c, 15],\n            [\"a8x\", c, 15],\n            [\"a9\", c, 15],\n            [\"a9x\", c, 15],\n            [\"a10\", c, 15],\n            [\"a10x\", c, 15],\n            [\"a12\", a, 15],\n            [\"a12x\", a, 15],\n            [\"a12z\", a, 15],\n            [\"a14\", a, 15],\n            [\"m1\", a, 15],\n          ]\n        : [\n            [\"a7\", f, 12],\n            [\"a8\", c, 12],\n            [\"a9\", c, 15],\n            [\"a10\", c, 15],\n            [\"a11\", a, 15],\n            [\"a12\", a, 15],\n            [\"a13\", a, 15],\n            [\"a14\", a, 15],\n          ];\n    return (\n      \"80162181255\" === o\n        ? (t = l.filter(function (e) {\n            return e[2] >= 14;\n          }))\n        : (t = l.filter(function (e) {\n            return e[1] === o;\n          })).length || (t = l),\n      t.map(function (e) {\n        var r = e[0];\n        return \"apple \".concat(r, \" gpu\");\n      })\n    );\n  }\n  var l = [],\n    d = [];\n  function s(e, r) {\n    if (e === r) return 0;\n    var n = e;\n    e.length > r.length && ((e = r), (r = n));\n    for (var t = e.length, o = r.length; t > 0 && e.charCodeAt(~-t) === r.charCodeAt(~-o); ) t--, o--;\n    for (var a, i = 0; i < t && e.charCodeAt(i) === r.charCodeAt(i); ) i++;\n    if (((o -= i), 0 === (t -= i))) return o;\n    for (var c, u, f = 0, s = 0, h = 0; s < t; ) (d[s] = e.charCodeAt(i + s)), (l[s] = ++s);\n    for (; h < o; )\n      for (a = r.charCodeAt(i + h), c = h++, f = h, s = 0; s < t; s++)\n        (u = a === d[s] ? c : c + 1), (c = l[s]), (f = l[s] = c > f ? (u > f ? f + 1 : u) : u > c ? c + 1 : u);\n    return f;\n  }\n  function h(e) {\n    return null != e;\n  }\n  var v = (function (e) {\n    function n(r) {\n      var n = this.constructor,\n        t = e.call(this, r) || this;\n      return Object.setPrototypeOf(t, n.prototype), t;\n    }\n    return (\n      (function (e, n) {\n        if (\"function\" != typeof n && null !== n)\n          throw new TypeError(\"Class extends value \" + String(n) + \" is not a constructor or null\");\n        function t() {\n          this.constructor = e;\n        }\n        r(e, n), (e.prototype = null === n ? Object.create(n) : ((t.prototype = n.prototype), new t()));\n      })(n, e),\n      n\n    );\n  })(Error);\n  (e.getGPUTier = function (e) {\n    var r = void 0 === e ? {} : e,\n      i = r.mobileTiers,\n      l = void 0 === i ? [0, 15, 30, 60] : i,\n      d = r.desktopTiers,\n      p = void 0 === d ? [0, 15, 30, 60] : d,\n      g = r.override,\n      m = void 0 === g ? {} : g,\n      b = r.glContext,\n      w = r.failIfMajorPerformanceCaveat,\n      y = void 0 !== w && w,\n      x = r.benchmarksURL,\n      P = void 0 === x ? \"https://unpkg.com/detect-gpu@\".concat(\"4.0.8\", \"/dist/benchmarks\") : x;\n    return n(void 0, void 0, void 0, function () {\n      var e, r, i, d, g, w, x, A, S, _, C, E, L, M, j, B, k, O, T, U, I, D, R, G, N, K;\n      return t(this, function (W) {\n        switch (W.label) {\n          case 0:\n            if (((e = {}), c)) return [2, { tier: 0, type: \"SSR\" }];\n            if (\n              ((r = m.isIpad),\n              (i = void 0 === r ? !!(null == u ? void 0 : u.isIpad) : r),\n              (d = m.isMobile),\n              (g = void 0 === d ? !!(null == u ? void 0 : u.isMobile) : d),\n              (w = m.screenSize),\n              (x = void 0 === w ? window.screen : w),\n              (A = m.loadBenchmarks),\n              (S =\n                void 0 === A\n                  ? function (e) {\n                      return n(void 0, void 0, void 0, function () {\n                        var r;\n                        return t(this, function (n) {\n                          switch (n.label) {\n                            case 0:\n                              return [\n                                4,\n                                fetch(\"\".concat(P, \"/\").concat(e)).then(function (e) {\n                                  return e.json();\n                                }),\n                              ];\n                            case 1:\n                              if (((r = n.sent()), parseInt(r.shift().split(\".\")[0], 10) < 4))\n                                throw new v(\"Detect GPU benchmark data is out of date. Please update to version 4x\");\n                              return [2, r];\n                          }\n                        });\n                      });\n                    }\n                  : A),\n              (_ = m.renderer),\n              (C = function (e) {\n                for (\n                  var r = 0,\n                    n = g\n                      ? [\"adreno\", \"apple\", \"mali-t\", \"mali\", \"nvidia\", \"powervr\"]\n                      : [\"intel\", \"apple\", \"amd\", \"radeon\", \"nvidia\", \"geforce\"];\n                  r < n.length;\n                  r++\n                ) {\n                  var t = n[r];\n                  if (e.includes(t)) return t;\n                }\n              }),\n              (E = function (r) {\n                return n(void 0, void 0, void 0, function () {\n                  var n, o, a, c, u, f, l, d, h, p, m, b, w, y, P, A, _, E, L, M, j, B, k, O, T, U;\n                  return t(this, function (t) {\n                    switch (t.label) {\n                      case 0:\n                        if (!(n = C(r))) return [2];\n                        (o = \"\"\n                          .concat(g ? \"m\" : \"d\", \"-\")\n                          .concat(n)\n                          .concat(i ? \"-ipad\" : \"\", \".json\")),\n                          (a = e[o] = null !== (U = e[o]) && void 0 !== U ? U : S(o)),\n                          (t.label = 1);\n                      case 1:\n                        return t.trys.push([1, 3, , 4]), [4, a];\n                      case 2:\n                        return (c = t.sent()), [3, 4];\n                      case 3:\n                        if ((u = t.sent()) instanceof v) throw u;\n                        return [2];\n                      case 4:\n                        if (\n                          ((f = (function (e) {\n                            var r,\n                              n =\n                                (e = e.replace(/\\([^)]+\\)/, \"\")).match(/\\d+/) ||\n                                e.match(/(\\W|^)([A-Za-z]{1,3})(\\W|$)/g);\n                            return null !== (r = null == n ? void 0 : n.join(\"\").replace(/\\W|amd/g, \"\")) && void 0 !== r\n                              ? r\n                              : \"\";\n                          })(r)),\n                          (l = c.filter(function (e) {\n                            return e[1] === f;\n                          })).length ||\n                            (l = c.filter(function (e) {\n                              return e[0].includes(r);\n                            })),\n                          0 === (d = l.length))\n                        )\n                          return [2];\n                        for (\n                          h =\n                            d > 1\n                              ? l\n                                  .map(function (e) {\n                                    return [e, s(r, e[0])];\n                                  })\n                                  .sort(function (e, r) {\n                                    return e[1] - r[1];\n                                  })[0][0]\n                              : l[0],\n                            p = h[0],\n                            m = h[3],\n                            b = Number.MAX_VALUE,\n                            y = window.devicePixelRatio,\n                            P = x.width * y * x.height * y,\n                            A = 0,\n                            _ = m;\n                          A < _.length;\n                          A++\n                        )\n                          (E = _[A]),\n                            (L = E[0]),\n                            (M = E[1]),\n                            (j = L * M),\n                            (B = Math.abs(P - j)) < b && ((b = B), (w = E));\n                        return w ? ((O = (k = w)[2]), (T = k[3]), [2, [b, O, p, T]]) : [2];\n                    }\n                  });\n                });\n              }),\n              (L = function (e, r, n, t, o) {\n                return { device: o, fps: t, gpu: n, isMobile: g, tier: e, type: r };\n              }),\n              (j = \"\"),\n              _)\n            )\n              (_ = a(_)), (M = [_]);\n            else {\n              if (\n                !(B =\n                  b ||\n                  (function (e, r) {\n                    void 0 === r && (r = !1);\n                    var n = {\n                      alpha: !1,\n                      antialias: !1,\n                      depth: !1,\n                      failIfMajorPerformanceCaveat: r,\n                      powerPreference: \"high-performance\",\n                      stencil: !1,\n                    };\n                    e && delete n.powerPreference;\n                    var t = window.document.createElement(\"canvas\"),\n                      o = t.getContext(\"webgl\", n) || t.getContext(\"experimental-webgl\", n);\n                    return null != o ? o : void 0;\n                  })(null == u ? void 0 : u.isSafari12, y))\n              )\n                return [2, L(0, \"WEBGL_UNSUPPORTED\")];\n              if (\n                ((k = B.getExtension(\"WEBGL_debug_renderer_info\")) && (_ = B.getParameter(k.UNMASKED_RENDERER_WEBGL)),\n                !_)\n              )\n                return [2, L(1, \"FALLBACK\")];\n              (j = _),\n                (_ = a(_)),\n                (M = (function (e, r, n) {\n                  return \"apple gpu\" === r ? f(e, r, n) : [r];\n                })(B, _, g));\n            }\n            return [4, Promise.all(M.map(E))];\n          case 1:\n            if (\n              !(O = W.sent()\n                .filter(h)\n                .sort(function (e, r) {\n                  var n = e[0],\n                    t = void 0 === n ? Number.MAX_VALUE : n,\n                    o = e[1],\n                    a = r[0],\n                    i = void 0 === a ? Number.MAX_VALUE : a,\n                    c = r[1];\n                  return t === i ? o - c : t - i;\n                })).length\n            )\n              return [\n                2,\n                (T = o.find(function (e) {\n                  return _.includes(e);\n                }))\n                  ? L(0, \"BLOCKLISTED\", T)\n                  : L(1, \"FALLBACK\", \"\".concat(_, \" (\").concat(j, \")\")),\n              ];\n            if (((U = O[0]), (I = U[1]), (D = U[2]), (R = U[3]), -1 === I)) return [2, L(0, \"BLOCKLISTED\", D, I, R)];\n            for (G = g ? l : p, N = 0, K = 0; K < G.length; K++) I >= G[K] && (N = K);\n            return [2, L(N, \"BENCHMARK\", D, I, R)];\n        }\n      });\n    });\n  }),\n    Object.defineProperty(e, \"__esModule\", { value: !0 });\n});\n//# sourceMappingURL=detect-gpu.umd.js.map\n","var map = {\n\t\"./d-adreno.json\": 622,\n\t\"./d-amd.json\": 183,\n\t\"./d-apple.json\": 732,\n\t\"./d-geforce.json\": 405,\n\t\"./d-intel.json\": 178,\n\t\"./d-nvidia.json\": 217,\n\t\"./d-radeon.json\": 145,\n\t\"./m-adreno.json\": 921,\n\t\"./m-apple-ipad.json\": 535,\n\t\"./m-apple.json\": 438,\n\t\"./m-intel.json\": 283,\n\t\"./m-mali-t.json\": 327,\n\t\"./m-mali.json\": 538,\n\t\"./m-nvidia.json\": 884,\n\t\"./m-powervr.json\": 214\n};\n\n\nfunction webpackContext(req) {\n\tvar id = webpackContextResolve(req);\n\treturn __webpack_require__(id);\n}\nfunction webpackContextResolve(req) {\n\tif(!__webpack_require__.o(map, req)) {\n\t\tvar e = new Error(\"Cannot find module '\" + req + \"'\");\n\t\te.code = 'MODULE_NOT_FOUND';\n\t\tthrow e;\n\t}\n\treturn map[req];\n}\nwebpackContext.keys = function webpackContextKeys() {\n\treturn Object.keys(map);\n};\nwebpackContext.resolve = webpackContextResolve;\nmodule.exports = webpackContext;\nwebpackContext.id = 804;","var LZString = (function () {\n  function o(o, r) {\n    if (!t[o]) {\n      t[o] = {};\n      for (var n = 0; n < o.length; n++) t[o][o.charAt(n)] = n;\n    }\n    return t[o][r];\n  }\n  var r = String.fromCharCode,\n    n = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\",\n    e = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-$\",\n    t = {},\n    i = {\n      compressToBase64: function (o) {\n        if (null == o) return \"\";\n        var r = i._compress(o, 6, function (o) {\n          return n.charAt(o);\n        });\n        switch (r.length % 4) {\n          default:\n          case 0:\n            return r;\n          case 1:\n            return r + \"===\";\n          case 2:\n            return r + \"==\";\n          case 3:\n            return r + \"=\";\n        }\n      },\n      decompressFromBase64: function (r) {\n        return null == r\n          ? \"\"\n          : \"\" == r\n          ? null\n          : i._decompress(r.length, 32, function (e) {\n              return o(n, r.charAt(e));\n            });\n      },\n      compressToUTF16: function (o) {\n        return null == o\n          ? \"\"\n          : i._compress(o, 15, function (o) {\n              return r(o + 32);\n            }) + \" \";\n      },\n      decompressFromUTF16: function (o) {\n        return null == o\n          ? \"\"\n          : \"\" == o\n          ? null\n          : i._decompress(o.length, 16384, function (r) {\n              return o.charCodeAt(r) - 32;\n            });\n      },\n      compressToUint8Array: function (o) {\n        for (\n          var r = i.compress(o), n = new Uint8Array(2 * r.length), e = 0, t = r.length;\n          t > e;\n          e++\n        ) {\n          var s = r.charCodeAt(e);\n          (n[2 * e] = s >>> 8), (n[2 * e + 1] = s % 256);\n        }\n        return n;\n      },\n      decompressFromUint8Array: function (o) {\n        if (null === o || void 0 === o) return i.decompress(o);\n        for (var n = new Array(o.length / 2), e = 0, t = n.length; t > e; e++)\n          n[e] = 256 * o[2 * e] + o[2 * e + 1];\n        var s = [];\n        return (\n          n.forEach(function (o) {\n            s.push(r(o));\n          }),\n          i.decompress(s.join(\"\"))\n        );\n      },\n      compressToEncodedURIComponent: function (o) {\n        return null == o\n          ? \"\"\n          : i._compress(o, 6, function (o) {\n              return e.charAt(o);\n            });\n      },\n      decompressFromEncodedURIComponent: function (r) {\n        return null == r\n          ? \"\"\n          : \"\" == r\n          ? null\n          : ((r = r.replace(/ /g, \"+\")),\n            i._decompress(r.length, 32, function (n) {\n              return o(e, r.charAt(n));\n            }));\n      },\n      compress: function (o) {\n        return i._compress(o, 16, function (o) {\n          return r(o);\n        });\n      },\n      _compress: function (o, r, n) {\n        if (null == o) return \"\";\n        var e,\n          t,\n          i,\n          s = {},\n          p = {},\n          u = \"\",\n          c = \"\",\n          a = \"\",\n          l = 2,\n          f = 3,\n          h = 2,\n          d = [],\n          m = 0,\n          v = 0;\n        for (i = 0; i < o.length; i += 1)\n          if (\n            ((u = o.charAt(i)),\n            Object.prototype.hasOwnProperty.call(s, u) || ((s[u] = f++), (p[u] = !0)),\n            (c = a + u),\n            Object.prototype.hasOwnProperty.call(s, c))\n          )\n            a = c;\n          else {\n            if (Object.prototype.hasOwnProperty.call(p, a)) {\n              if (a.charCodeAt(0) < 256) {\n                for (e = 0; h > e; e++)\n                  (m <<= 1), v == r - 1 ? ((v = 0), d.push(n(m)), (m = 0)) : v++;\n                for (t = a.charCodeAt(0), e = 0; 8 > e; e++)\n                  (m = (m << 1) | (1 & t)),\n                    v == r - 1 ? ((v = 0), d.push(n(m)), (m = 0)) : v++,\n                    (t >>= 1);\n              } else {\n                for (t = 1, e = 0; h > e; e++)\n                  (m = (m << 1) | t), v == r - 1 ? ((v = 0), d.push(n(m)), (m = 0)) : v++, (t = 0);\n                for (t = a.charCodeAt(0), e = 0; 16 > e; e++)\n                  (m = (m << 1) | (1 & t)),\n                    v == r - 1 ? ((v = 0), d.push(n(m)), (m = 0)) : v++,\n                    (t >>= 1);\n              }\n              l--, 0 == l && ((l = Math.pow(2, h)), h++), delete p[a];\n            } else\n              for (t = s[a], e = 0; h > e; e++)\n                (m = (m << 1) | (1 & t)),\n                  v == r - 1 ? ((v = 0), d.push(n(m)), (m = 0)) : v++,\n                  (t >>= 1);\n            l--, 0 == l && ((l = Math.pow(2, h)), h++), (s[c] = f++), (a = String(u));\n          }\n        if (\"\" !== a) {\n          if (Object.prototype.hasOwnProperty.call(p, a)) {\n            if (a.charCodeAt(0) < 256) {\n              for (e = 0; h > e; e++)\n                (m <<= 1), v == r - 1 ? ((v = 0), d.push(n(m)), (m = 0)) : v++;\n              for (t = a.charCodeAt(0), e = 0; 8 > e; e++)\n                (m = (m << 1) | (1 & t)),\n                  v == r - 1 ? ((v = 0), d.push(n(m)), (m = 0)) : v++,\n                  (t >>= 1);\n            } else {\n              for (t = 1, e = 0; h > e; e++)\n                (m = (m << 1) | t), v == r - 1 ? ((v = 0), d.push(n(m)), (m = 0)) : v++, (t = 0);\n              for (t = a.charCodeAt(0), e = 0; 16 > e; e++)\n                (m = (m << 1) | (1 & t)),\n                  v == r - 1 ? ((v = 0), d.push(n(m)), (m = 0)) : v++,\n                  (t >>= 1);\n            }\n            l--, 0 == l && ((l = Math.pow(2, h)), h++), delete p[a];\n          } else\n            for (t = s[a], e = 0; h > e; e++)\n              (m = (m << 1) | (1 & t)),\n                v == r - 1 ? ((v = 0), d.push(n(m)), (m = 0)) : v++,\n                (t >>= 1);\n          l--, 0 == l && ((l = Math.pow(2, h)), h++);\n        }\n        for (t = 2, e = 0; h > e; e++)\n          (m = (m << 1) | (1 & t)), v == r - 1 ? ((v = 0), d.push(n(m)), (m = 0)) : v++, (t >>= 1);\n        for (;;) {\n          if (((m <<= 1), v == r - 1)) {\n            d.push(n(m));\n            break;\n          }\n          v++;\n        }\n        return d.join(\"\");\n      },\n      decompress: function (o) {\n        return null == o\n          ? \"\"\n          : \"\" == o\n          ? null\n          : i._decompress(o.length, 32768, function (r) {\n              return o.charCodeAt(r);\n            });\n      },\n      _decompress: function (o, n, e) {\n        var t,\n          i,\n          s,\n          p,\n          u,\n          c,\n          a,\n          l,\n          f = [],\n          h = 4,\n          d = 4,\n          m = 3,\n          v = \"\",\n          w = [],\n          A = { val: e(0), position: n, index: 1 };\n        for (i = 0; 3 > i; i += 1) f[i] = i;\n        for (p = 0, c = Math.pow(2, 2), a = 1; a != c; )\n          (u = A.val & A.position),\n            (A.position >>= 1),\n            0 == A.position && ((A.position = n), (A.val = e(A.index++))),\n            (p |= (u > 0 ? 1 : 0) * a),\n            (a <<= 1);\n        switch ((t = p)) {\n          case 0:\n            for (p = 0, c = Math.pow(2, 8), a = 1; a != c; )\n              (u = A.val & A.position),\n                (A.position >>= 1),\n                0 == A.position && ((A.position = n), (A.val = e(A.index++))),\n                (p |= (u > 0 ? 1 : 0) * a),\n                (a <<= 1);\n            l = r(p);\n            break;\n          case 1:\n            for (p = 0, c = Math.pow(2, 16), a = 1; a != c; )\n              (u = A.val & A.position),\n                (A.position >>= 1),\n                0 == A.position && ((A.position = n), (A.val = e(A.index++))),\n                (p |= (u > 0 ? 1 : 0) * a),\n                (a <<= 1);\n            l = r(p);\n            break;\n          case 2:\n            return \"\";\n        }\n        for (f[3] = l, s = l, w.push(l); ; ) {\n          if (A.index > o) return \"\";\n          for (p = 0, c = Math.pow(2, m), a = 1; a != c; )\n            (u = A.val & A.position),\n              (A.position >>= 1),\n              0 == A.position && ((A.position = n), (A.val = e(A.index++))),\n              (p |= (u > 0 ? 1 : 0) * a),\n              (a <<= 1);\n          switch ((l = p)) {\n            case 0:\n              for (p = 0, c = Math.pow(2, 8), a = 1; a != c; )\n                (u = A.val & A.position),\n                  (A.position >>= 1),\n                  0 == A.position && ((A.position = n), (A.val = e(A.index++))),\n                  (p |= (u > 0 ? 1 : 0) * a),\n                  (a <<= 1);\n              (f[d++] = r(p)), (l = d - 1), h--;\n              break;\n            case 1:\n              for (p = 0, c = Math.pow(2, 16), a = 1; a != c; )\n                (u = A.val & A.position),\n                  (A.position >>= 1),\n                  0 == A.position && ((A.position = n), (A.val = e(A.index++))),\n                  (p |= (u > 0 ? 1 : 0) * a),\n                  (a <<= 1);\n              (f[d++] = r(p)), (l = d - 1), h--;\n              break;\n            case 2:\n              return w.join(\"\");\n          }\n          if ((0 == h && ((h = Math.pow(2, m)), m++), f[l])) v = f[l];\n          else {\n            if (l !== d) return null;\n            v = s + s.charAt(0);\n          }\n          w.push(v),\n            (f[d++] = s + v.charAt(0)),\n            h--,\n            (s = v),\n            0 == h && ((h = Math.pow(2, m)), m++);\n        }\n      },\n    };\n  return i;\n})();\n\"function\" == typeof define && define.amd\n  ? define(function () {\n      return LZString;\n    })\n  : \"undefined\" != typeof module && null != module && (module.exports = LZString);\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tif(__webpack_module_cache__[moduleId]) {\n\t\treturn __webpack_module_cache__[moduleId].exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","// module exports must be returned from runtime so entry inlining is disabled\n// startup\n// Load entry module and return exports\nreturn __webpack_require__(607);\n","__webpack_require__.g = (function() {\n\tif (typeof globalThis === 'object') return globalThis;\n\ttry {\n\t\treturn this || new Function('return this')();\n\t} catch (e) {\n\t\tif (typeof window === 'object') return window;\n\t}\n})();","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","/*!\n * currentExecutingScript\n * Get the currently executing script, regardless of its source/trigger/synchronicity. Similar to HTML5's `document.currentScript` but arguably much more useful!\n * Copyright (c) 2015 James M. Greene\n * Licensed MIT\n * https://github.com/JamesMGreene/currentExecutingScript\n * v0.1.3\n */\n(function(root, factory) {\n  if (typeof define === \"function\" && define.amd) {\n    // AMD. Register as an anonymous module.\n    define([], factory);\n  } else if (typeof exports === \"object\") {\n    // CommonJS-like environments that support `module.exports`,\n    // like Node.js. Does not work with strict CommonJS!\n    module.exports = factory();\n  } else {\n    // Browser globals (`root` is `window`)\n    root.currentExecutingScript = factory();\n  }\n}(\n  // Current context/scope\n  this || window,\n\n  // Factory function to return the export\n  function() {\n\nvar scriptReadyRegex = /^(interactive|loaded|complete)$/;\n\n// This page's URL (minus query string and fragment identifer hash, if any)\nvar fullPageUrl = !!window.location ? window.location.href : null;\nvar pageUrl = fullPageUrl ? fullPageUrl.replace(/#.*$/, \"\").replace(/\\?.*$/, \"\") || null : null;\n\n// Live NodeList collection\nvar scripts = document.getElementsByTagName(\"script\");\n\n// Check if the browser supports the `readyState` property on `script` elements\nvar supportsScriptReadyState = \"readyState\" in (scripts[0] || document.createElement(\"script\"));\n\n// Lousy browser detection for [not] Opera\nvar isNotOpera = !window.opera || window.opera.toString() !== \"[object Opera]\";\n\n// Detect if `document.currentScript` is supported\nvar hasNativeCurrentScriptAccessor = \"currentScript\" in document;\n\nvar originalStackDepthConfig;\n// Detect if the V8 Error Stack Trace API is supported\nif (\"stackTraceLimit\" in Error && Error.stackTraceLimit !== Infinity) {\n  originalStackDepthConfig = Error.stackTraceLimit;\n  Error.stackTraceLimit = Infinity;\n}\n\n\n// In some browsers (e.g. Chrome), you can get the current stack from an Error\n// object instance without needing to throw it. Avoiding an unnecessary\n// use of `throw` saves time and performance.\nvar hasStackBeforeThrowing = false,\n    hasStackAfterThrowing = false;\n(function() {\n  try {\n    var err = new Error();\n    hasStackBeforeThrowing = typeof err.stack === \"string\" && !!err.stack;\n    throw err;\n  }\n  catch (thrownErr) {\n    hasStackAfterThrowing = typeof thrownErr.stack === \"string\" && !!thrownErr.stack;\n  }\n})();\n\n\n// Normalize whitespace within a string\nfunction normalizeWhitespace(str) {\n  return str ? str.replace(/^\\s+$|\\s+$/g, \"\").replace(/\\s\\s+/g, \" \") : \"\";\n}\n\n// Get script object based on the `src` URL\nfunction getScriptFromUrl(url, eligibleScripts) {\n  var i,\n      script = null;\n\n  eligibleScripts = eligibleScripts || scripts;\n\n  if (typeof url === \"string\" && url) {\n    for (i = eligibleScripts.length; i--; ) {\n      if (eligibleScripts[i].src === url) {\n        // NOTE: Could check if the same script URL is used by more than one `script` element\n        // here... but let's not. That would yield less useful results in \"loose\" detection. ;)\n        script = eligibleScripts[i];\n        break;\n      }\n    }\n  }\n  return script;\n}\n\n// Get script object based on the caller function's source code body (text)\nfunction getInlineScriptFromCallerSource(callerFnSource, eligibleScripts) {\n  var i, inlineScriptText,\n      script = null,\n      callerSourceText = normalizeWhitespace(callerFnSource);\n\n  eligibleScripts = eligibleScripts || scripts;\n\n  if (callerFnSource && callerSourceText) {\n    for (i = eligibleScripts.length; i--; ) {\n      // Only look at inline scripts\n      if (!eligibleScripts[i].hasAttribute(\"src\")) {\n        inlineScriptText = normalizeWhitespace(eligibleScripts[i].text);\n        if (inlineScriptText.indexOf(callerSourceText) !== -1) {\n          // If more than one match is found, don't return any\n          if (script) {\n            script = null;\n            break;\n          }\n          script = eligibleScripts[i];\n        }\n      }\n    }\n  }\n\n  return script;\n}\n\n// If there is only a single inline script on the page, return it; otherwise `null`\nfunction getSoleInlineScript(eligibleScripts) {\n  var i, len,\n      script = null;\n  eligibleScripts = eligibleScripts || scripts;\n  for (i = 0, len = eligibleScripts.length; i < len; i++) {\n    if (!eligibleScripts[i].hasAttribute(\"src\")) {\n      if (script) {\n        script = null;\n        break;\n      }\n      script = eligibleScripts[i];\n    }\n  }\n  return script;\n}\n\n// Get the currently executing script URL from an Error stack trace\nfunction getScriptUrlFromStack(stack, skipStackDepth) {\n  var matches, remainingStack,\n      url = null,\n      ignoreMessage = typeof skipStackDepth === \"number\";\n  skipStackDepth = ignoreMessage ? Math.round(skipStackDepth) : 0;\n  if (typeof stack === \"string\" && stack) {\n    if (ignoreMessage) {\n      matches = stack.match(/(data:text\\/javascript(?:;[^,]+)?,.+?|(?:|blob:)(?:http[s]?|file):\\/\\/[\\/]?.+?\\/[^:\\)]*?)(?::\\d+)(?::\\d+)?/);\n    }\n    else {\n      matches = stack.match(/^(?:|[^:@]*@|.+\\)@(?=data:text\\/javascript|blob|http[s]?|file)|.+?\\s+(?: at |@)(?:[^:\\(]+ )*[\\(]?)(data:text\\/javascript(?:;[^,]+)?,.+?|(?:|blob:)(?:http[s]?|file):\\/\\/[\\/]?.+?\\/[^:\\)]*?)(?::\\d+)(?::\\d+)?/);\n\n      if (!(matches && matches[1])) {\n        matches = stack.match(/\\)@(data:text\\/javascript(?:;[^,]+)?,.+?|(?:|blob:)(?:http[s]?|file):\\/\\/[\\/]?.+?\\/[^:\\)]*?)(?::\\d+)(?::\\d+)?/);\n      }\n    }\n\n    if (matches && matches[1]) {\n      if (skipStackDepth > 0) {\n        remainingStack = stack.slice(stack.indexOf(matches[0]) + matches[0].length);\n        url = getScriptUrlFromStack(remainingStack, (skipStackDepth - 1));\n      }\n      else {\n        url = matches[1];\n      }\n    }\n\n    // TODO: Handle more edge cases!\n    // Fixes #1\n    // See https://github.com/JamesMGreene/currentExecutingScript/issues/1\n\n    // ???\n\n  }\n  return url;\n}\n\n\n// Get the farthest currently executing (i.e. yes, EXECUTING) `script` DOM\n// element for the caller function, regardless of whether it is that `script`\n// DOM element is currently being evaluated for the first time. The farthest\n// currently executing `script` DOM element would typically be considered the\n// originator of the current execution stack.\nfunction _farthestExecutingScript() {\n  /*jshint noarg:false */\n\n  // TODO: Implement!\n  // Fixes #3\n  // See https://github.com/JamesMGreene/currentExecutingScript/issues/3\n  return null;\n\n/*\n  // Yes, this IS possible, i.e. if a script removes other scripts (or itself)\n  if (scripts.length === 0) {\n    return null;\n  }\n\n  // Guaranteed accurate in IE 6-10.\n  // Not accurate/supported in any other browsers.\n  if (isNotOpera && supportsScriptReadyState) {\n    for (var i = scripts.length; i--; ) {\n      if (scripts[i].readyState === \"interactive\") {\n        return scripts[i];\n      }\n    }\n  }\n\n  var stack,\n      e = new Error();\n  if (hasStackBeforeThrowing) {\n    stack = e.stack;\n  }\n  if (!stack && hasStackAfterThrowing) {\n    try {\n      throw e;\n    }\n    catch (err) {\n      // NOTE: Cannot use `err.sourceURL` or `err.fileName` as they will always be THIS script\n      stack = err.stack;\n    }\n  }\n  if (stack) {\n    var url = getScriptUrlFromStack(stack, skipStackDepth);\n    var script = getScriptFromUrl(url, scripts );\n    if (!script && pageUrl && url === pageUrl) {\n      // Try to find the correct inline script by searching through\n      // inline scripts' text content for the caller function's source\n      // code to be present. If the caller function's source code is\n      // not available, see if there is only one inline script element\n      // in the DOM and return that (even though it may be wrong)\n\n      // TODO: Implement!\n      // Fixes #4 in part\n      // See https://github.com/JamesMGreene/currentExecutingScript/issues/4\n\n      var callerFn = _farthestExecutingScript.caller || null,\n          callerFnStack = [],\n          callerFnSource = null;\n\n      while (callerFn) {\n        callerFnStack.push(callerFn);\n        callerFn = callerFn.caller || null;\n      }\n      callerFn = callerFnStack.slice(-1)[0];\n      callerFnSource = callerFn ? (\"\" + callerFn) : null;\n\n\n      if (callerFnSource) {\n        script = getInlineScriptFromCallerSource(callerFnSource);\n      }\n      else {\n        // NOTE: This is a loose assumption that could be inaccurate!\n        //\n        // Inaccuracies:\n        //  - If the inline script that initiated the call was also removed from the DOM.\n        //  - If the call was initiated by an element's inline event handler,\n        //    e.g. `<a onclick=\"(function() { alert(currentExecutingScript()); }()\">click</a>`\n        script = getSoleInlineScript();\n      }\n    }\n    return script;\n  }\n\n  // NOTE: This is a loose assumption that could be inaccurate!\n  //\n  // Inaccuracies:\n  //  - If a script is created dynamically and appended to some position\n  //    other than the very end of the document.\n  //  - If multiple scripts are created dynamically and all appended to the\n  //    same position within the document (and do not have their `async` attributes\n  //    set to `false`, at least in browsers that support async script evaluation.\n  //    other than the very end of the document.\n  //  - If any scripts are added with the `async` attribute set to `true` in a browser\n  //    that supports it.\n  //  - May get confused by `script` elements within `svg` elements\n  return scripts[scripts.length - 1] || null;\n*/\n}\n\n\n// Get the originating currently executing (i.e. yes, EXECUTING) `script` DOM\n// element or attribute node (e.g. `onclick`) for the caller function,\n// regardless of whether it is that `script` DOM element is currently being\n// evaluated for the first time. The originating currently executing `script`\n// DOM element [or attribute node] is the originator of the current execution stack.\nfunction _originatingExecutingScript() {\n  // TODO: Implement!\n  // Fixes #2\n  // See https://github.com/JamesMGreene/currentExecutingScript/issues/2\n  return null;\n}\n\n// Get the nearest currently executing (i.e. yes, EXECUTING) `script` DOM\n// element for the caller function, regardless of whether it is that `script`\n// DOM element is currently being evaluated for the first time.\nfunction _nearestExecutingScript() {\n  /*jshint noarg:false */\n\n  // Yes, this IS possible, i.e. if a script removes other scripts (or itself)\n  if (scripts.length === 0) {\n    return null;\n  }\n\n  var i, e, stack, url, script,\n      eligibleScripts = [],\n      skipStackDepth = _nearestExecutingScript.skipStackDepth || 1,\n\n      // TODO: Implement!\n      // Fixes #4 in part\n      // See https://github.com/JamesMGreene/currentExecutingScript/issues/4\n      callerFnSource = null;  //(\"\" + (_nearestExecutingScript.caller || \"\")) || null;\n\n  // This part will only help in IE 6-10.\n  for (i = 0; i < scripts.length; i++) {\n    if (isNotOpera && supportsScriptReadyState) {\n      if (scriptReadyRegex.test(scripts[i].readyState)) {\n        eligibleScripts.push(scripts[i]);\n      }\n    }\n    else {\n      eligibleScripts.push(scripts[i]);\n    }\n  }\n\n  e = new Error();\n  if (hasStackBeforeThrowing) {\n    stack = e.stack;\n  }\n  if (!stack && hasStackAfterThrowing) {\n    try {\n      throw e;\n    }\n    catch (err) {\n      // NOTE: Cannot use `err.sourceURL` or `err.fileName` as they will always be THIS script\n      stack = err.stack;\n    }\n  }\n\n  if (stack) {\n    url = getScriptUrlFromStack(stack, skipStackDepth);\n    script = getScriptFromUrl(url, eligibleScripts);\n\n    if (!script && pageUrl && url === pageUrl) {\n      // Try to find the correct inline script by searching through\n      // inline scripts' text content for the caller function's source\n      // code to be present.\n      if (callerFnSource) {\n        script = getInlineScriptFromCallerSource(callerFnSource, eligibleScripts);\n      }\n      // If the caller function's source code is not available, see if\n      // there is only one inline script element in the DOM and return\n      // that (even though it may be wrong)...\n      else {\n        // NOTE: This is a loose assumption that could be inaccurate!\n        //\n        // Inaccuracies:\n        //  - If the inline script that initiated the call was also removed from the DOM.\n        //  - If the call was initiated by an element's inline event handler,\n        //    e.g. `<a onclick=\"(function() { alert(currentExecutingScript()); }()\">click</a>`\n        script = getSoleInlineScript(eligibleScripts);\n      }\n    }\n  }\n\n  //\n  // Welcome to the Island of Inaccurate Assumptions!\n  // NOTE: ALL of the following are loose assumptions that could be inaccurate!\n  //\n\n  if (!script) {\n    // Inaccuracies:\n    //  - If the inline script that initiated the call was also removed from the DOM.\n    //  - If the call was initiated by an element's inline event handler,\n    //    e.g. `<a onclick=\"(function() { alert(currentExecutingScript()); }()\">click</a>`\n    if (eligibleScripts.length === 1) {\n      script = eligibleScripts[0];\n    }\n  }\n\n  if (!script) {\n    // Inaccuracies:\n    //  - If script currently being synchronously evaluated by the parser is the\n    //    originator of this call stack but NOT the source script of the caller/invocation\n    //    e.g.\n    //    ```html\n    //    <script id=\"a\">\n    //    function getCurrentScriptCallerFn() {\n    //      return currentExecutingScript.near();\n    //    }\n    //    </script>\n    //    <script id=\"b\">\n    //    // Should get `script[id=\"a\"]` but will get `script[id=\"b\"]` instead\n    //    getCurrentScriptCallerFn();\n    //    </script>\n    if (hasNativeCurrentScriptAccessor) {\n      script = document.currentScript;\n    }\n  }\n\n  if (!script) {\n    // Inaccuracies:\n    //  - If script currently being synchronously evaluated by the parser is the\n    //    originator of this call stack but NOT the source script of the caller/invocation\n    //    e.g.\n    //    ```html\n    //    <script id=\"a\">\n    //    function getCurrentScriptCallerFn() {\n    //      return currentExecutingScript.near();\n    //    }\n    //    </script>\n    //    <script id=\"b\">\n    //    // Should get `script[id=\"a\"]` but will get `script[id=\"b\"]` instead\n    //    getCurrentScriptCallerFn();\n    //    </script>\n    if (isNotOpera && supportsScriptReadyState) {\n      for (i = eligibleScripts.length; i--; ) {\n        if (eligibleScripts[i].readyState === \"interactive\") {\n          script = eligibleScripts[i];\n          break;\n        }\n      }\n    }\n  }\n\n  if (!script) {\n    // Inaccuracies:\n    //  - If a script is created dynamically and appended to some position\n    //    other than the very end of the document.\n    //  - If multiple scripts are created dynamically and all appended to the\n    //    same position within the document (and do not have their `async` attributes\n    //    set to `false`, at least in browsers that support async script evaluation.\n    //    other than the very end of the document.\n    //  - If any scripts are added with the `async` attribute set to `true` in a browser\n    //    that supports it.\n    //  - May get confused by `script` elements within `svg` elements\n    //  - If script currently being synchronously evaluated by the parser is the\n    //    originator of this call stack but NOT the source script of the caller/invocation\n    //    e.g.\n    //    ```html\n    //    <script id=\"a\">\n    //    function getCurrentScriptCallerFn() {\n    //      return currentExecutingScript.near();\n    //    }\n    //    </script>\n    //    <script id=\"b\">\n    //    // Should get `script[id=\"a\"]` but will get `script[id=\"b\"]` instead\n    //    getCurrentScriptCallerFn();\n    //    </script>\n    //    ```\n    script = eligibleScripts[eligibleScripts.length - 1] || null;\n  }\n\n  return script;\n}\n\n// Default stack depth to skip over when analyzing call stack frames\n_nearestExecutingScript.skipStackDepth = 1;\n\n\n\n    //\n    // Export the API\n    //\n    var currentExecutingScript    = _nearestExecutingScript;      // default\n    currentExecutingScript.near   = _nearestExecutingScript;\n    currentExecutingScript.far    = _farthestExecutingScript;\n    currentExecutingScript.origin = _originatingExecutingScript;\n\n\n    // Just return a value to define the module export.\n    // This example returns an object, but the module\n    // can return a function as the exported value.\n    return currentExecutingScript;\n  })\n);\n","// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// copy of this software and associated documentation files (the\n// \"Software\"), to deal in the Software without restriction, including\n// without limitation the rights to use, copy, modify, merge, publish,\n// distribute, sublicense, and/or sell copies of the Software, and to permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n'use strict';\n\nvar R = typeof Reflect === 'object' ? Reflect : null\nvar ReflectApply = R && typeof R.apply === 'function'\n  ? R.apply\n  : function ReflectApply(target, receiver, args) {\n    return Function.prototype.apply.call(target, receiver, args);\n  }\n\nvar ReflectOwnKeys\nif (R && typeof R.ownKeys === 'function') {\n  ReflectOwnKeys = R.ownKeys\n} else if (Object.getOwnPropertySymbols) {\n  ReflectOwnKeys = function ReflectOwnKeys(target) {\n    return Object.getOwnPropertyNames(target)\n      .concat(Object.getOwnPropertySymbols(target));\n  };\n} else {\n  ReflectOwnKeys = function ReflectOwnKeys(target) {\n    return Object.getOwnPropertyNames(target);\n  };\n}\n\nfunction ProcessEmitWarning(warning) {\n  if (console && console.warn) console.warn(warning);\n}\n\nvar NumberIsNaN = Number.isNaN || function NumberIsNaN(value) {\n  return value !== value;\n}\n\nfunction EventEmitter() {\n  EventEmitter.init.call(this);\n}\nmodule.exports = EventEmitter;\nmodule.exports.once = once;\n\n// Backwards-compat with node 0.10.x\nEventEmitter.EventEmitter = EventEmitter;\n\nEventEmitter.prototype._events = undefined;\nEventEmitter.prototype._eventsCount = 0;\nEventEmitter.prototype._maxListeners = undefined;\n\n// By default EventEmitters will print a warning if more than 10 listeners are\n// added to it. This is a useful default which helps finding memory leaks.\nvar defaultMaxListeners = 10;\n\nfunction checkListener(listener) {\n  if (typeof listener !== 'function') {\n    throw new TypeError('The \"listener\" argument must be of type Function. Received type ' + typeof listener);\n  }\n}\n\nObject.defineProperty(EventEmitter, 'defaultMaxListeners', {\n  enumerable: true,\n  get: function() {\n    return defaultMaxListeners;\n  },\n  set: function(arg) {\n    if (typeof arg !== 'number' || arg < 0 || NumberIsNaN(arg)) {\n      throw new RangeError('The value of \"defaultMaxListeners\" is out of range. It must be a non-negative number. Received ' + arg + '.');\n    }\n    defaultMaxListeners = arg;\n  }\n});\n\nEventEmitter.init = function() {\n\n  if (this._events === undefined ||\n      this._events === Object.getPrototypeOf(this)._events) {\n    this._events = Object.create(null);\n    this._eventsCount = 0;\n  }\n\n  this._maxListeners = this._maxListeners || undefined;\n};\n\n// Obviously not all Emitters should be limited to 10. This function allows\n// that to be increased. Set to zero for unlimited.\nEventEmitter.prototype.setMaxListeners = function setMaxListeners(n) {\n  if (typeof n !== 'number' || n < 0 || NumberIsNaN(n)) {\n    throw new RangeError('The value of \"n\" is out of range. It must be a non-negative number. Received ' + n + '.');\n  }\n  this._maxListeners = n;\n  return this;\n};\n\nfunction _getMaxListeners(that) {\n  if (that._maxListeners === undefined)\n    return EventEmitter.defaultMaxListeners;\n  return that._maxListeners;\n}\n\nEventEmitter.prototype.getMaxListeners = function getMaxListeners() {\n  return _getMaxListeners(this);\n};\n\nEventEmitter.prototype.emit = function emit(type) {\n  var args = [];\n  for (var i = 1; i < arguments.length; i++) args.push(arguments[i]);\n  var doError = (type === 'error');\n\n  var events = this._events;\n  if (events !== undefined)\n    doError = (doError && events.error === undefined);\n  else if (!doError)\n    return false;\n\n  // If there is no 'error' event listener then throw.\n  if (doError) {\n    var er;\n    if (args.length > 0)\n      er = args[0];\n    if (er instanceof Error) {\n      // Note: The comments on the `throw` lines are intentional, they show\n      // up in Node's output if this results in an unhandled exception.\n      throw er; // Unhandled 'error' event\n    }\n    // At least give some kind of context to the user\n    var err = new Error('Unhandled error.' + (er ? ' (' + er.message + ')' : ''));\n    err.context = er;\n    throw err; // Unhandled 'error' event\n  }\n\n  var handler = events[type];\n\n  if (handler === undefined)\n    return false;\n\n  if (typeof handler === 'function') {\n    ReflectApply(handler, this, args);\n  } else {\n    var len = handler.length;\n    var listeners = arrayClone(handler, len);\n    for (var i = 0; i < len; ++i)\n      ReflectApply(listeners[i], this, args);\n  }\n\n  return true;\n};\n\nfunction _addListener(target, type, listener, prepend) {\n  var m;\n  var events;\n  var existing;\n\n  checkListener(listener);\n\n  events = target._events;\n  if (events === undefined) {\n    events = target._events = Object.create(null);\n    target._eventsCount = 0;\n  } else {\n    // To avoid recursion in the case that type === \"newListener\"! Before\n    // adding it to the listeners, first emit \"newListener\".\n    if (events.newListener !== undefined) {\n      target.emit('newListener', type,\n                  listener.listener ? listener.listener : listener);\n\n      // Re-assign `events` because a newListener handler could have caused the\n      // this._events to be assigned to a new object\n      events = target._events;\n    }\n    existing = events[type];\n  }\n\n  if (existing === undefined) {\n    // Optimize the case of one listener. Don't need the extra array object.\n    existing = events[type] = listener;\n    ++target._eventsCount;\n  } else {\n    if (typeof existing === 'function') {\n      // Adding the second element, need to change to array.\n      existing = events[type] =\n        prepend ? [listener, existing] : [existing, listener];\n      // If we've already got an array, just append.\n    } else if (prepend) {\n      existing.unshift(listener);\n    } else {\n      existing.push(listener);\n    }\n\n    // Check for listener leak\n    m = _getMaxListeners(target);\n    if (m > 0 && existing.length > m && !existing.warned) {\n      existing.warned = true;\n      // No error code for this since it is a Warning\n      // eslint-disable-next-line no-restricted-syntax\n      var w = new Error('Possible EventEmitter memory leak detected. ' +\n                          existing.length + ' ' + String(type) + ' listeners ' +\n                          'added. Use emitter.setMaxListeners() to ' +\n                          'increase limit');\n      w.name = 'MaxListenersExceededWarning';\n      w.emitter = target;\n      w.type = type;\n      w.count = existing.length;\n      ProcessEmitWarning(w);\n    }\n  }\n\n  return target;\n}\n\nEventEmitter.prototype.addListener = function addListener(type, listener) {\n  return _addListener(this, type, listener, false);\n};\n\nEventEmitter.prototype.on = EventEmitter.prototype.addListener;\n\nEventEmitter.prototype.prependListener =\n    function prependListener(type, listener) {\n      return _addListener(this, type, listener, true);\n    };\n\nfunction onceWrapper() {\n  if (!this.fired) {\n    this.target.removeListener(this.type, this.wrapFn);\n    this.fired = true;\n    if (arguments.length === 0)\n      return this.listener.call(this.target);\n    return this.listener.apply(this.target, arguments);\n  }\n}\n\nfunction _onceWrap(target, type, listener) {\n  var state = { fired: false, wrapFn: undefined, target: target, type: type, listener: listener };\n  var wrapped = onceWrapper.bind(state);\n  wrapped.listener = listener;\n  state.wrapFn = wrapped;\n  return wrapped;\n}\n\nEventEmitter.prototype.once = function once(type, listener) {\n  checkListener(listener);\n  this.on(type, _onceWrap(this, type, listener));\n  return this;\n};\n\nEventEmitter.prototype.prependOnceListener =\n    function prependOnceListener(type, listener) {\n      checkListener(listener);\n      this.prependListener(type, _onceWrap(this, type, listener));\n      return this;\n    };\n\n// Emits a 'removeListener' event if and only if the listener was removed.\nEventEmitter.prototype.removeListener =\n    function removeListener(type, listener) {\n      var list, events, position, i, originalListener;\n\n      checkListener(listener);\n\n      events = this._events;\n      if (events === undefined)\n        return this;\n\n      list = events[type];\n      if (list === undefined)\n        return this;\n\n      if (list === listener || list.listener === listener) {\n        if (--this._eventsCount === 0)\n          this._events = Object.create(null);\n        else {\n          delete events[type];\n          if (events.removeListener)\n            this.emit('removeListener', type, list.listener || listener);\n        }\n      } else if (typeof list !== 'function') {\n        position = -1;\n\n        for (i = list.length - 1; i >= 0; i--) {\n          if (list[i] === listener || list[i].listener === listener) {\n            originalListener = list[i].listener;\n            position = i;\n            break;\n          }\n        }\n\n        if (position < 0)\n          return this;\n\n        if (position === 0)\n          list.shift();\n        else {\n          spliceOne(list, position);\n        }\n\n        if (list.length === 1)\n          events[type] = list[0];\n\n        if (events.removeListener !== undefined)\n          this.emit('removeListener', type, originalListener || listener);\n      }\n\n      return this;\n    };\n\nEventEmitter.prototype.off = EventEmitter.prototype.removeListener;\n\nEventEmitter.prototype.removeAllListeners =\n    function removeAllListeners(type) {\n      var listeners, events, i;\n\n      events = this._events;\n      if (events === undefined)\n        return this;\n\n      // not listening for removeListener, no need to emit\n      if (events.removeListener === undefined) {\n        if (arguments.length === 0) {\n          this._events = Object.create(null);\n          this._eventsCount = 0;\n        } else if (events[type] !== undefined) {\n          if (--this._eventsCount === 0)\n            this._events = Object.create(null);\n          else\n            delete events[type];\n        }\n        return this;\n      }\n\n      // emit removeListener for all listeners on all events\n      if (arguments.length === 0) {\n        var keys = Object.keys(events);\n        var key;\n        for (i = 0; i < keys.length; ++i) {\n          key = keys[i];\n          if (key === 'removeListener') continue;\n          this.removeAllListeners(key);\n        }\n        this.removeAllListeners('removeListener');\n        this._events = Object.create(null);\n        this._eventsCount = 0;\n        return this;\n      }\n\n      listeners = events[type];\n\n      if (typeof listeners === 'function') {\n        this.removeListener(type, listeners);\n      } else if (listeners !== undefined) {\n        // LIFO order\n        for (i = listeners.length - 1; i >= 0; i--) {\n          this.removeListener(type, listeners[i]);\n        }\n      }\n\n      return this;\n    };\n\nfunction _listeners(target, type, unwrap) {\n  var events = target._events;\n\n  if (events === undefined)\n    return [];\n\n  var evlistener = events[type];\n  if (evlistener === undefined)\n    return [];\n\n  if (typeof evlistener === 'function')\n    return unwrap ? [evlistener.listener || evlistener] : [evlistener];\n\n  return unwrap ?\n    unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length);\n}\n\nEventEmitter.prototype.listeners = function listeners(type) {\n  return _listeners(this, type, true);\n};\n\nEventEmitter.prototype.rawListeners = function rawListeners(type) {\n  return _listeners(this, type, false);\n};\n\nEventEmitter.listenerCount = function(emitter, type) {\n  if (typeof emitter.listenerCount === 'function') {\n    return emitter.listenerCount(type);\n  } else {\n    return listenerCount.call(emitter, type);\n  }\n};\n\nEventEmitter.prototype.listenerCount = listenerCount;\nfunction listenerCount(type) {\n  var events = this._events;\n\n  if (events !== undefined) {\n    var evlistener = events[type];\n\n    if (typeof evlistener === 'function') {\n      return 1;\n    } else if (evlistener !== undefined) {\n      return evlistener.length;\n    }\n  }\n\n  return 0;\n}\n\nEventEmitter.prototype.eventNames = function eventNames() {\n  return this._eventsCount > 0 ? ReflectOwnKeys(this._events) : [];\n};\n\nfunction arrayClone(arr, n) {\n  var copy = new Array(n);\n  for (var i = 0; i < n; ++i)\n    copy[i] = arr[i];\n  return copy;\n}\n\nfunction spliceOne(list, index) {\n  for (; index + 1 < list.length; index++)\n    list[index] = list[index + 1];\n  list.pop();\n}\n\nfunction unwrapListeners(arr) {\n  var ret = new Array(arr.length);\n  for (var i = 0; i < ret.length; ++i) {\n    ret[i] = arr[i].listener || arr[i];\n  }\n  return ret;\n}\n\nfunction once(emitter, name) {\n  return new Promise(function (resolve, reject) {\n    function errorListener(err) {\n      emitter.removeListener(name, resolver);\n      reject(err);\n    }\n\n    function resolver() {\n      if (typeof emitter.removeListener === 'function') {\n        emitter.removeListener('error', errorListener);\n      }\n      resolve([].slice.call(arguments));\n    };\n\n    eventTargetAgnosticAddListener(emitter, name, resolver, { once: true });\n    if (name !== 'error') {\n      addErrorHandlerIfEventEmitter(emitter, errorListener, { once: true });\n    }\n  });\n}\n\nfunction addErrorHandlerIfEventEmitter(emitter, handler, flags) {\n  if (typeof emitter.on === 'function') {\n    eventTargetAgnosticAddListener(emitter, 'error', handler, flags);\n  }\n}\n\nfunction eventTargetAgnosticAddListener(emitter, name, listener, flags) {\n  if (typeof emitter.on === 'function') {\n    if (flags.once) {\n      emitter.once(name, listener);\n    } else {\n      emitter.on(name, listener);\n    }\n  } else if (typeof emitter.addEventListener === 'function') {\n    // EventTarget does not have `error` event semantics like Node\n    // EventEmitters, we do not listen for `error` events here.\n    emitter.addEventListener(name, function wrapListener(arg) {\n      // IE does not have builtin `{ once: true }` support so we\n      // have to do it manually.\n      if (flags.once) {\n        emitter.removeEventListener(name, wrapListener);\n      }\n      listener(arg);\n    });\n  } else {\n    throw new TypeError('The \"emitter\" argument must be of type EventEmitter. Received type ' + typeof emitter);\n  }\n}\n","/**\n * [js-md5]{@link https://github.com/emn178/js-md5}\n *\n * @namespace md5\n * @version 0.7.3\n * @author Chen, Yi-Cyuan [emn178@gmail.com]\n * @copyright Chen, Yi-Cyuan 2014-2017\n * @license MIT\n */\n(function () {\n  'use strict';\n\n  var ERROR = 'input is invalid type';\n  var WINDOW = typeof window === 'object';\n  var root = WINDOW ? window : {};\n  if (root.JS_MD5_NO_WINDOW) {\n    WINDOW = false;\n  }\n  var WEB_WORKER = !WINDOW && typeof self === 'object';\n  var NODE_JS = !root.JS_MD5_NO_NODE_JS && typeof process === 'object' && process.versions && process.versions.node;\n  if (NODE_JS) {\n    root = global;\n  } else if (WEB_WORKER) {\n    root = self;\n  }\n  var COMMON_JS = !root.JS_MD5_NO_COMMON_JS && typeof module === 'object' && module.exports;\n  var AMD = typeof define === 'function' && define.amd;\n  var ARRAY_BUFFER = !root.JS_MD5_NO_ARRAY_BUFFER && typeof ArrayBuffer !== 'undefined';\n  var HEX_CHARS = '0123456789abcdef'.split('');\n  var EXTRA = [128, 32768, 8388608, -2147483648];\n  var SHIFT = [0, 8, 16, 24];\n  var OUTPUT_TYPES = ['hex', 'array', 'digest', 'buffer', 'arrayBuffer', 'base64'];\n  var BASE64_ENCODE_CHAR = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.split('');\n\n  var blocks = [], buffer8;\n  if (ARRAY_BUFFER) {\n    var buffer = new ArrayBuffer(68);\n    buffer8 = new Uint8Array(buffer);\n    blocks = new Uint32Array(buffer);\n  }\n\n  if (root.JS_MD5_NO_NODE_JS || !Array.isArray) {\n    Array.isArray = function (obj) {\n      return Object.prototype.toString.call(obj) === '[object Array]';\n    };\n  }\n\n  if (ARRAY_BUFFER && (root.JS_MD5_NO_ARRAY_BUFFER_IS_VIEW || !ArrayBuffer.isView)) {\n    ArrayBuffer.isView = function (obj) {\n      return typeof obj === 'object' && obj.buffer && obj.buffer.constructor === ArrayBuffer;\n    };\n  }\n\n  /**\n   * @method hex\n   * @memberof md5\n   * @description Output hash as hex string\n   * @param {String|Array|Uint8Array|ArrayBuffer} message message to hash\n   * @returns {String} Hex string\n   * @example\n   * md5.hex('The quick brown fox jumps over the lazy dog');\n   * // equal to\n   * md5('The quick brown fox jumps over the lazy dog');\n   */\n  /**\n   * @method digest\n   * @memberof md5\n   * @description Output hash as bytes array\n   * @param {String|Array|Uint8Array|ArrayBuffer} message message to hash\n   * @returns {Array} Bytes array\n   * @example\n   * md5.digest('The quick brown fox jumps over the lazy dog');\n   */\n  /**\n   * @method array\n   * @memberof md5\n   * @description Output hash as bytes array\n   * @param {String|Array|Uint8Array|ArrayBuffer} message message to hash\n   * @returns {Array} Bytes array\n   * @example\n   * md5.array('The quick brown fox jumps over the lazy dog');\n   */\n  /**\n   * @method arrayBuffer\n   * @memberof md5\n   * @description Output hash as ArrayBuffer\n   * @param {String|Array|Uint8Array|ArrayBuffer} message message to hash\n   * @returns {ArrayBuffer} ArrayBuffer\n   * @example\n   * md5.arrayBuffer('The quick brown fox jumps over the lazy dog');\n   */\n  /**\n   * @method buffer\n   * @deprecated This maybe confuse with Buffer in node.js. Please use arrayBuffer instead.\n   * @memberof md5\n   * @description Output hash as ArrayBuffer\n   * @param {String|Array|Uint8Array|ArrayBuffer} message message to hash\n   * @returns {ArrayBuffer} ArrayBuffer\n   * @example\n   * md5.buffer('The quick brown fox jumps over the lazy dog');\n   */\n  /**\n   * @method base64\n   * @memberof md5\n   * @description Output hash as base64 string\n   * @param {String|Array|Uint8Array|ArrayBuffer} message message to hash\n   * @returns {String} base64 string\n   * @example\n   * md5.base64('The quick brown fox jumps over the lazy dog');\n   */\n  var createOutputMethod = function (outputType) {\n    return function (message) {\n      return new Md5(true).update(message)[outputType]();\n    };\n  };\n\n  /**\n   * @method create\n   * @memberof md5\n   * @description Create Md5 object\n   * @returns {Md5} Md5 object.\n   * @example\n   * var hash = md5.create();\n   */\n  /**\n   * @method update\n   * @memberof md5\n   * @description Create and update Md5 object\n   * @param {String|Array|Uint8Array|ArrayBuffer} message message to hash\n   * @returns {Md5} Md5 object.\n   * @example\n   * var hash = md5.update('The quick brown fox jumps over the lazy dog');\n   * // equal to\n   * var hash = md5.create();\n   * hash.update('The quick brown fox jumps over the lazy dog');\n   */\n  var createMethod = function () {\n    var method = createOutputMethod('hex');\n    if (NODE_JS) {\n      method = nodeWrap(method);\n    }\n    method.create = function () {\n      return new Md5();\n    };\n    method.update = function (message) {\n      return method.create().update(message);\n    };\n    for (var i = 0; i < OUTPUT_TYPES.length; ++i) {\n      var type = OUTPUT_TYPES[i];\n      method[type] = createOutputMethod(type);\n    }\n    return method;\n  };\n\n  var nodeWrap = function (method) {\n    var crypto = eval(\"require('crypto')\");\n    var Buffer = eval(\"require('buffer').Buffer\");\n    var nodeMethod = function (message) {\n      if (typeof message === 'string') {\n        return crypto.createHash('md5').update(message, 'utf8').digest('hex');\n      } else {\n        if (message === null || message === undefined) {\n          throw ERROR;\n        } else if (message.constructor === ArrayBuffer) {\n          message = new Uint8Array(message);\n        }\n      }\n      if (Array.isArray(message) || ArrayBuffer.isView(message) ||\n        message.constructor === Buffer) {\n        return crypto.createHash('md5').update(new Buffer(message)).digest('hex');\n      } else {\n        return method(message);\n      }\n    };\n    return nodeMethod;\n  };\n\n  /**\n   * Md5 class\n   * @class Md5\n   * @description This is internal class.\n   * @see {@link md5.create}\n   */\n  function Md5(sharedMemory) {\n    if (sharedMemory) {\n      blocks[0] = blocks[16] = blocks[1] = blocks[2] = blocks[3] =\n      blocks[4] = blocks[5] = blocks[6] = blocks[7] =\n      blocks[8] = blocks[9] = blocks[10] = blocks[11] =\n      blocks[12] = blocks[13] = blocks[14] = blocks[15] = 0;\n      this.blocks = blocks;\n      this.buffer8 = buffer8;\n    } else {\n      if (ARRAY_BUFFER) {\n        var buffer = new ArrayBuffer(68);\n        this.buffer8 = new Uint8Array(buffer);\n        this.blocks = new Uint32Array(buffer);\n      } else {\n        this.blocks = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];\n      }\n    }\n    this.h0 = this.h1 = this.h2 = this.h3 = this.start = this.bytes = this.hBytes = 0;\n    this.finalized = this.hashed = false;\n    this.first = true;\n  }\n\n  /**\n   * @method update\n   * @memberof Md5\n   * @instance\n   * @description Update hash\n   * @param {String|Array|Uint8Array|ArrayBuffer} message message to hash\n   * @returns {Md5} Md5 object.\n   * @see {@link md5.update}\n   */\n  Md5.prototype.update = function (message) {\n    if (this.finalized) {\n      return;\n    }\n\n    var notString, type = typeof message;\n    if (type !== 'string') {\n      if (type === 'object') {\n        if (message === null) {\n          throw ERROR;\n        } else if (ARRAY_BUFFER && message.constructor === ArrayBuffer) {\n          message = new Uint8Array(message);\n        } else if (!Array.isArray(message)) {\n          if (!ARRAY_BUFFER || !ArrayBuffer.isView(message)) {\n            throw ERROR;\n          }\n        }\n      } else {\n        throw ERROR;\n      }\n      notString = true;\n    }\n    var code, index = 0, i, length = message.length, blocks = this.blocks;\n    var buffer8 = this.buffer8;\n\n    while (index < length) {\n      if (this.hashed) {\n        this.hashed = false;\n        blocks[0] = blocks[16];\n        blocks[16] = blocks[1] = blocks[2] = blocks[3] =\n        blocks[4] = blocks[5] = blocks[6] = blocks[7] =\n        blocks[8] = blocks[9] = blocks[10] = blocks[11] =\n        blocks[12] = blocks[13] = blocks[14] = blocks[15] = 0;\n      }\n\n      if (notString) {\n        if (ARRAY_BUFFER) {\n          for (i = this.start; index < length && i < 64; ++index) {\n            buffer8[i++] = message[index];\n          }\n        } else {\n          for (i = this.start; index < length && i < 64; ++index) {\n            blocks[i >> 2] |= message[index] << SHIFT[i++ & 3];\n          }\n        }\n      } else {\n        if (ARRAY_BUFFER) {\n          for (i = this.start; index < length && i < 64; ++index) {\n            code = message.charCodeAt(index);\n            if (code < 0x80) {\n              buffer8[i++] = code;\n            } else if (code < 0x800) {\n              buffer8[i++] = 0xc0 | (code >> 6);\n              buffer8[i++] = 0x80 | (code & 0x3f);\n            } else if (code < 0xd800 || code >= 0xe000) {\n              buffer8[i++] = 0xe0 | (code >> 12);\n              buffer8[i++] = 0x80 | ((code >> 6) & 0x3f);\n              buffer8[i++] = 0x80 | (code & 0x3f);\n            } else {\n              code = 0x10000 + (((code & 0x3ff) << 10) | (message.charCodeAt(++index) & 0x3ff));\n              buffer8[i++] = 0xf0 | (code >> 18);\n              buffer8[i++] = 0x80 | ((code >> 12) & 0x3f);\n              buffer8[i++] = 0x80 | ((code >> 6) & 0x3f);\n              buffer8[i++] = 0x80 | (code & 0x3f);\n            }\n          }\n        } else {\n          for (i = this.start; index < length && i < 64; ++index) {\n            code = message.charCodeAt(index);\n            if (code < 0x80) {\n              blocks[i >> 2] |= code << SHIFT[i++ & 3];\n            } else if (code < 0x800) {\n              blocks[i >> 2] |= (0xc0 | (code >> 6)) << SHIFT[i++ & 3];\n              blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];\n            } else if (code < 0xd800 || code >= 0xe000) {\n              blocks[i >> 2] |= (0xe0 | (code >> 12)) << SHIFT[i++ & 3];\n              blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3];\n              blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];\n            } else {\n              code = 0x10000 + (((code & 0x3ff) << 10) | (message.charCodeAt(++index) & 0x3ff));\n              blocks[i >> 2] |= (0xf0 | (code >> 18)) << SHIFT[i++ & 3];\n              blocks[i >> 2] |= (0x80 | ((code >> 12) & 0x3f)) << SHIFT[i++ & 3];\n              blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3];\n              blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];\n            }\n          }\n        }\n      }\n      this.lastByteIndex = i;\n      this.bytes += i - this.start;\n      if (i >= 64) {\n        this.start = i - 64;\n        this.hash();\n        this.hashed = true;\n      } else {\n        this.start = i;\n      }\n    }\n    if (this.bytes > 4294967295) {\n      this.hBytes += this.bytes / 4294967296 << 0;\n      this.bytes = this.bytes % 4294967296;\n    }\n    return this;\n  };\n\n  Md5.prototype.finalize = function () {\n    if (this.finalized) {\n      return;\n    }\n    this.finalized = true;\n    var blocks = this.blocks, i = this.lastByteIndex;\n    blocks[i >> 2] |= EXTRA[i & 3];\n    if (i >= 56) {\n      if (!this.hashed) {\n        this.hash();\n      }\n      blocks[0] = blocks[16];\n      blocks[16] = blocks[1] = blocks[2] = blocks[3] =\n      blocks[4] = blocks[5] = blocks[6] = blocks[7] =\n      blocks[8] = blocks[9] = blocks[10] = blocks[11] =\n      blocks[12] = blocks[13] = blocks[14] = blocks[15] = 0;\n    }\n    blocks[14] = this.bytes << 3;\n    blocks[15] = this.hBytes << 3 | this.bytes >>> 29;\n    this.hash();\n  };\n\n  Md5.prototype.hash = function () {\n    var a, b, c, d, bc, da, blocks = this.blocks;\n\n    if (this.first) {\n      a = blocks[0] - 680876937;\n      a = (a << 7 | a >>> 25) - 271733879 << 0;\n      d = (-1732584194 ^ a & 2004318071) + blocks[1] - 117830708;\n      d = (d << 12 | d >>> 20) + a << 0;\n      c = (-271733879 ^ (d & (a ^ -271733879))) + blocks[2] - 1126478375;\n      c = (c << 17 | c >>> 15) + d << 0;\n      b = (a ^ (c & (d ^ a))) + blocks[3] - 1316259209;\n      b = (b << 22 | b >>> 10) + c << 0;\n    } else {\n      a = this.h0;\n      b = this.h1;\n      c = this.h2;\n      d = this.h3;\n      a += (d ^ (b & (c ^ d))) + blocks[0] - 680876936;\n      a = (a << 7 | a >>> 25) + b << 0;\n      d += (c ^ (a & (b ^ c))) + blocks[1] - 389564586;\n      d = (d << 12 | d >>> 20) + a << 0;\n      c += (b ^ (d & (a ^ b))) + blocks[2] + 606105819;\n      c = (c << 17 | c >>> 15) + d << 0;\n      b += (a ^ (c & (d ^ a))) + blocks[3] - 1044525330;\n      b = (b << 22 | b >>> 10) + c << 0;\n    }\n\n    a += (d ^ (b & (c ^ d))) + blocks[4] - 176418897;\n    a = (a << 7 | a >>> 25) + b << 0;\n    d += (c ^ (a & (b ^ c))) + blocks[5] + 1200080426;\n    d = (d << 12 | d >>> 20) + a << 0;\n    c += (b ^ (d & (a ^ b))) + blocks[6] - 1473231341;\n    c = (c << 17 | c >>> 15) + d << 0;\n    b += (a ^ (c & (d ^ a))) + blocks[7] - 45705983;\n    b = (b << 22 | b >>> 10) + c << 0;\n    a += (d ^ (b & (c ^ d))) + blocks[8] + 1770035416;\n    a = (a << 7 | a >>> 25) + b << 0;\n    d += (c ^ (a & (b ^ c))) + blocks[9] - 1958414417;\n    d = (d << 12 | d >>> 20) + a << 0;\n    c += (b ^ (d & (a ^ b))) + blocks[10] - 42063;\n    c = (c << 17 | c >>> 15) + d << 0;\n    b += (a ^ (c & (d ^ a))) + blocks[11] - 1990404162;\n    b = (b << 22 | b >>> 10) + c << 0;\n    a += (d ^ (b & (c ^ d))) + blocks[12] + 1804603682;\n    a = (a << 7 | a >>> 25) + b << 0;\n    d += (c ^ (a & (b ^ c))) + blocks[13] - 40341101;\n    d = (d << 12 | d >>> 20) + a << 0;\n    c += (b ^ (d & (a ^ b))) + blocks[14] - 1502002290;\n    c = (c << 17 | c >>> 15) + d << 0;\n    b += (a ^ (c & (d ^ a))) + blocks[15] + 1236535329;\n    b = (b << 22 | b >>> 10) + c << 0;\n    a += (c ^ (d & (b ^ c))) + blocks[1] - 165796510;\n    a = (a << 5 | a >>> 27) + b << 0;\n    d += (b ^ (c & (a ^ b))) + blocks[6] - 1069501632;\n    d = (d << 9 | d >>> 23) + a << 0;\n    c += (a ^ (b & (d ^ a))) + blocks[11] + 643717713;\n    c = (c << 14 | c >>> 18) + d << 0;\n    b += (d ^ (a & (c ^ d))) + blocks[0] - 373897302;\n    b = (b << 20 | b >>> 12) + c << 0;\n    a += (c ^ (d & (b ^ c))) + blocks[5] - 701558691;\n    a = (a << 5 | a >>> 27) + b << 0;\n    d += (b ^ (c & (a ^ b))) + blocks[10] + 38016083;\n    d = (d << 9 | d >>> 23) + a << 0;\n    c += (a ^ (b & (d ^ a))) + blocks[15] - 660478335;\n    c = (c << 14 | c >>> 18) + d << 0;\n    b += (d ^ (a & (c ^ d))) + blocks[4] - 405537848;\n    b = (b << 20 | b >>> 12) + c << 0;\n    a += (c ^ (d & (b ^ c))) + blocks[9] + 568446438;\n    a = (a << 5 | a >>> 27) + b << 0;\n    d += (b ^ (c & (a ^ b))) + blocks[14] - 1019803690;\n    d = (d << 9 | d >>> 23) + a << 0;\n    c += (a ^ (b & (d ^ a))) + blocks[3] - 187363961;\n    c = (c << 14 | c >>> 18) + d << 0;\n    b += (d ^ (a & (c ^ d))) + blocks[8] + 1163531501;\n    b = (b << 20 | b >>> 12) + c << 0;\n    a += (c ^ (d & (b ^ c))) + blocks[13] - 1444681467;\n    a = (a << 5 | a >>> 27) + b << 0;\n    d += (b ^ (c & (a ^ b))) + blocks[2] - 51403784;\n    d = (d << 9 | d >>> 23) + a << 0;\n    c += (a ^ (b & (d ^ a))) + blocks[7] + 1735328473;\n    c = (c << 14 | c >>> 18) + d << 0;\n    b += (d ^ (a & (c ^ d))) + blocks[12] - 1926607734;\n    b = (b << 20 | b >>> 12) + c << 0;\n    bc = b ^ c;\n    a += (bc ^ d) + blocks[5] - 378558;\n    a = (a << 4 | a >>> 28) + b << 0;\n    d += (bc ^ a) + blocks[8] - 2022574463;\n    d = (d << 11 | d >>> 21) + a << 0;\n    da = d ^ a;\n    c += (da ^ b) + blocks[11] + 1839030562;\n    c = (c << 16 | c >>> 16) + d << 0;\n    b += (da ^ c) + blocks[14] - 35309556;\n    b = (b << 23 | b >>> 9) + c << 0;\n    bc = b ^ c;\n    a += (bc ^ d) + blocks[1] - 1530992060;\n    a = (a << 4 | a >>> 28) + b << 0;\n    d += (bc ^ a) + blocks[4] + 1272893353;\n    d = (d << 11 | d >>> 21) + a << 0;\n    da = d ^ a;\n    c += (da ^ b) + blocks[7] - 155497632;\n    c = (c << 16 | c >>> 16) + d << 0;\n    b += (da ^ c) + blocks[10] - 1094730640;\n    b = (b << 23 | b >>> 9) + c << 0;\n    bc = b ^ c;\n    a += (bc ^ d) + blocks[13] + 681279174;\n    a = (a << 4 | a >>> 28) + b << 0;\n    d += (bc ^ a) + blocks[0] - 358537222;\n    d = (d << 11 | d >>> 21) + a << 0;\n    da = d ^ a;\n    c += (da ^ b) + blocks[3] - 722521979;\n    c = (c << 16 | c >>> 16) + d << 0;\n    b += (da ^ c) + blocks[6] + 76029189;\n    b = (b << 23 | b >>> 9) + c << 0;\n    bc = b ^ c;\n    a += (bc ^ d) + blocks[9] - 640364487;\n    a = (a << 4 | a >>> 28) + b << 0;\n    d += (bc ^ a) + blocks[12] - 421815835;\n    d = (d << 11 | d >>> 21) + a << 0;\n    da = d ^ a;\n    c += (da ^ b) + blocks[15] + 530742520;\n    c = (c << 16 | c >>> 16) + d << 0;\n    b += (da ^ c) + blocks[2] - 995338651;\n    b = (b << 23 | b >>> 9) + c << 0;\n    a += (c ^ (b | ~d)) + blocks[0] - 198630844;\n    a = (a << 6 | a >>> 26) + b << 0;\n    d += (b ^ (a | ~c)) + blocks[7] + 1126891415;\n    d = (d << 10 | d >>> 22) + a << 0;\n    c += (a ^ (d | ~b)) + blocks[14] - 1416354905;\n    c = (c << 15 | c >>> 17) + d << 0;\n    b += (d ^ (c | ~a)) + blocks[5] - 57434055;\n    b = (b << 21 | b >>> 11) + c << 0;\n    a += (c ^ (b | ~d)) + blocks[12] + 1700485571;\n    a = (a << 6 | a >>> 26) + b << 0;\n    d += (b ^ (a | ~c)) + blocks[3] - 1894986606;\n    d = (d << 10 | d >>> 22) + a << 0;\n    c += (a ^ (d | ~b)) + blocks[10] - 1051523;\n    c = (c << 15 | c >>> 17) + d << 0;\n    b += (d ^ (c | ~a)) + blocks[1] - 2054922799;\n    b = (b << 21 | b >>> 11) + c << 0;\n    a += (c ^ (b | ~d)) + blocks[8] + 1873313359;\n    a = (a << 6 | a >>> 26) + b << 0;\n    d += (b ^ (a | ~c)) + blocks[15] - 30611744;\n    d = (d << 10 | d >>> 22) + a << 0;\n    c += (a ^ (d | ~b)) + blocks[6] - 1560198380;\n    c = (c << 15 | c >>> 17) + d << 0;\n    b += (d ^ (c | ~a)) + blocks[13] + 1309151649;\n    b = (b << 21 | b >>> 11) + c << 0;\n    a += (c ^ (b | ~d)) + blocks[4] - 145523070;\n    a = (a << 6 | a >>> 26) + b << 0;\n    d += (b ^ (a | ~c)) + blocks[11] - 1120210379;\n    d = (d << 10 | d >>> 22) + a << 0;\n    c += (a ^ (d | ~b)) + blocks[2] + 718787259;\n    c = (c << 15 | c >>> 17) + d << 0;\n    b += (d ^ (c | ~a)) + blocks[9] - 343485551;\n    b = (b << 21 | b >>> 11) + c << 0;\n\n    if (this.first) {\n      this.h0 = a + 1732584193 << 0;\n      this.h1 = b - 271733879 << 0;\n      this.h2 = c - 1732584194 << 0;\n      this.h3 = d + 271733878 << 0;\n      this.first = false;\n    } else {\n      this.h0 = this.h0 + a << 0;\n      this.h1 = this.h1 + b << 0;\n      this.h2 = this.h2 + c << 0;\n      this.h3 = this.h3 + d << 0;\n    }\n  };\n\n  /**\n   * @method hex\n   * @memberof Md5\n   * @instance\n   * @description Output hash as hex string\n   * @returns {String} Hex string\n   * @see {@link md5.hex}\n   * @example\n   * hash.hex();\n   */\n  Md5.prototype.hex = function () {\n    this.finalize();\n\n    var h0 = this.h0, h1 = this.h1, h2 = this.h2, h3 = this.h3;\n\n    return HEX_CHARS[(h0 >> 4) & 0x0F] + HEX_CHARS[h0 & 0x0F] +\n      HEX_CHARS[(h0 >> 12) & 0x0F] + HEX_CHARS[(h0 >> 8) & 0x0F] +\n      HEX_CHARS[(h0 >> 20) & 0x0F] + HEX_CHARS[(h0 >> 16) & 0x0F] +\n      HEX_CHARS[(h0 >> 28) & 0x0F] + HEX_CHARS[(h0 >> 24) & 0x0F] +\n      HEX_CHARS[(h1 >> 4) & 0x0F] + HEX_CHARS[h1 & 0x0F] +\n      HEX_CHARS[(h1 >> 12) & 0x0F] + HEX_CHARS[(h1 >> 8) & 0x0F] +\n      HEX_CHARS[(h1 >> 20) & 0x0F] + HEX_CHARS[(h1 >> 16) & 0x0F] +\n      HEX_CHARS[(h1 >> 28) & 0x0F] + HEX_CHARS[(h1 >> 24) & 0x0F] +\n      HEX_CHARS[(h2 >> 4) & 0x0F] + HEX_CHARS[h2 & 0x0F] +\n      HEX_CHARS[(h2 >> 12) & 0x0F] + HEX_CHARS[(h2 >> 8) & 0x0F] +\n      HEX_CHARS[(h2 >> 20) & 0x0F] + HEX_CHARS[(h2 >> 16) & 0x0F] +\n      HEX_CHARS[(h2 >> 28) & 0x0F] + HEX_CHARS[(h2 >> 24) & 0x0F] +\n      HEX_CHARS[(h3 >> 4) & 0x0F] + HEX_CHARS[h3 & 0x0F] +\n      HEX_CHARS[(h3 >> 12) & 0x0F] + HEX_CHARS[(h3 >> 8) & 0x0F] +\n      HEX_CHARS[(h3 >> 20) & 0x0F] + HEX_CHARS[(h3 >> 16) & 0x0F] +\n      HEX_CHARS[(h3 >> 28) & 0x0F] + HEX_CHARS[(h3 >> 24) & 0x0F];\n  };\n\n  /**\n   * @method toString\n   * @memberof Md5\n   * @instance\n   * @description Output hash as hex string\n   * @returns {String} Hex string\n   * @see {@link md5.hex}\n   * @example\n   * hash.toString();\n   */\n  Md5.prototype.toString = Md5.prototype.hex;\n\n  /**\n   * @method digest\n   * @memberof Md5\n   * @instance\n   * @description Output hash as bytes array\n   * @returns {Array} Bytes array\n   * @see {@link md5.digest}\n   * @example\n   * hash.digest();\n   */\n  Md5.prototype.digest = function () {\n    this.finalize();\n\n    var h0 = this.h0, h1 = this.h1, h2 = this.h2, h3 = this.h3;\n    return [\n      h0 & 0xFF, (h0 >> 8) & 0xFF, (h0 >> 16) & 0xFF, (h0 >> 24) & 0xFF,\n      h1 & 0xFF, (h1 >> 8) & 0xFF, (h1 >> 16) & 0xFF, (h1 >> 24) & 0xFF,\n      h2 & 0xFF, (h2 >> 8) & 0xFF, (h2 >> 16) & 0xFF, (h2 >> 24) & 0xFF,\n      h3 & 0xFF, (h3 >> 8) & 0xFF, (h3 >> 16) & 0xFF, (h3 >> 24) & 0xFF\n    ];\n  };\n\n  /**\n   * @method array\n   * @memberof Md5\n   * @instance\n   * @description Output hash as bytes array\n   * @returns {Array} Bytes array\n   * @see {@link md5.array}\n   * @example\n   * hash.array();\n   */\n  Md5.prototype.array = Md5.prototype.digest;\n\n  /**\n   * @method arrayBuffer\n   * @memberof Md5\n   * @instance\n   * @description Output hash as ArrayBuffer\n   * @returns {ArrayBuffer} ArrayBuffer\n   * @see {@link md5.arrayBuffer}\n   * @example\n   * hash.arrayBuffer();\n   */\n  Md5.prototype.arrayBuffer = function () {\n    this.finalize();\n\n    var buffer = new ArrayBuffer(16);\n    var blocks = new Uint32Array(buffer);\n    blocks[0] = this.h0;\n    blocks[1] = this.h1;\n    blocks[2] = this.h2;\n    blocks[3] = this.h3;\n    return buffer;\n  };\n\n  /**\n   * @method buffer\n   * @deprecated This maybe confuse with Buffer in node.js. Please use arrayBuffer instead.\n   * @memberof Md5\n   * @instance\n   * @description Output hash as ArrayBuffer\n   * @returns {ArrayBuffer} ArrayBuffer\n   * @see {@link md5.buffer}\n   * @example\n   * hash.buffer();\n   */\n  Md5.prototype.buffer = Md5.prototype.arrayBuffer;\n\n  /**\n   * @method base64\n   * @memberof Md5\n   * @instance\n   * @description Output hash as base64 string\n   * @returns {String} base64 string\n   * @see {@link md5.base64}\n   * @example\n   * hash.base64();\n   */\n  Md5.prototype.base64 = function () {\n    var v1, v2, v3, base64Str = '', bytes = this.array();\n    for (var i = 0; i < 15;) {\n      v1 = bytes[i++];\n      v2 = bytes[i++];\n      v3 = bytes[i++];\n      base64Str += BASE64_ENCODE_CHAR[v1 >>> 2] +\n        BASE64_ENCODE_CHAR[(v1 << 4 | v2 >>> 4) & 63] +\n        BASE64_ENCODE_CHAR[(v2 << 2 | v3 >>> 6) & 63] +\n        BASE64_ENCODE_CHAR[v3 & 63];\n    }\n    v1 = bytes[i];\n    base64Str += BASE64_ENCODE_CHAR[v1 >>> 2] +\n      BASE64_ENCODE_CHAR[(v1 << 4) & 63] +\n      '==';\n    return base64Str;\n  };\n\n  var exports = createMethod();\n\n  if (COMMON_JS) {\n    module.exports = exports;\n  } else {\n    /**\n     * @method md5\b\n     * @description Md5 hash function, export to global in browsers.\n     * @param {String|Array|Uint8Array|ArrayBuffer} message message to hash\n     * @returns {String} md5 hashes\n     * @example\n     * md5(''); // d41d8cd98f00b204e9800998ecf8427e\n     * md5('The quick brown fox jumps over the lazy dog'); // 9e107d9d372bb6826bd81d3542a419d6\n     * md5('The quick brown fox jumps over the lazy dog.'); // e4d909c290d0fb1ca068ffaddf22cbd0\n     *\n     * // It also supports UTF-8 encoding\n     * md5('中文'); // a7bac2239fcdcb3a067903d8077c4a07\n     *\n     * // It also supports byte `Array`, `Uint8Array`, `ArrayBuffer`\n     * md5([]); // d41d8cd98f00b204e9800998ecf8427e\n     * md5(new Uint8Array([])); // d41d8cd98f00b204e9800998ecf8427e\n     */\n    root.md5 = exports;\n    if (AMD) {\n      define(function () {\n        return exports;\n      });\n    }\n  }\n})();\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { Backend } from './backend.js';\nimport { InferenceSession } from './inference-session.js';\n\ninterface BackendInfo {\n  backend: Backend;\n  priority: number;\n\n  initPromise?: Promise<void>;\n  initialized?: boolean;\n  aborted?: boolean;\n  error?: string;\n}\n\nconst backends: Map<string, BackendInfo> = new Map();\nconst backendsSortedByPriority: string[] = [];\n\n/**\n * Register a backend.\n *\n * @param name - the name as a key to lookup as an execution provider.\n * @param backend - the backend object.\n * @param priority - an integer indicating the priority of the backend. Higher number means higher priority. if priority\n * < 0, it will be considered as a 'beta' version and will not be used as a fallback backend by default.\n *\n * @ignore\n */\nexport const registerBackend = (name: string, backend: Backend, priority: number): void => {\n  if (backend && typeof backend.init === 'function' && typeof backend.createInferenceSessionHandler === 'function') {\n    const currentBackend = backends.get(name);\n    if (currentBackend === undefined) {\n      backends.set(name, { backend, priority });\n    } else if (currentBackend.priority > priority) {\n      // same name is already registered with a higher priority. skip registeration.\n      return;\n    } else if (currentBackend.priority === priority) {\n      if (currentBackend.backend !== backend) {\n        throw new Error(`cannot register backend \"${name}\" using priority ${priority}`);\n      }\n    }\n\n    if (priority >= 0) {\n      const i = backendsSortedByPriority.indexOf(name);\n      if (i !== -1) {\n        backendsSortedByPriority.splice(i, 1);\n      }\n\n      for (let i = 0; i < backendsSortedByPriority.length; i++) {\n        if (backends.get(backendsSortedByPriority[i])!.priority <= priority) {\n          backendsSortedByPriority.splice(i, 0, name);\n          return;\n        }\n      }\n      backendsSortedByPriority.push(name);\n    }\n    return;\n  }\n\n  throw new TypeError('not a valid backend');\n};\n\n/**\n * Try to resolve and initialize a backend.\n *\n * @param backendName - the name of the backend.\n * @returns the backend instance if resolved and initialized successfully, or an error message if failed.\n */\nconst tryResolveAndInitializeBackend = async (backendName: string): Promise<Backend | string> => {\n  const backendInfo = backends.get(backendName);\n  if (!backendInfo) {\n    return 'backend not found.';\n  }\n\n  if (backendInfo.initialized) {\n    return backendInfo.backend;\n  } else if (backendInfo.aborted) {\n    return backendInfo.error!;\n  } else {\n    const isInitializing = !!backendInfo.initPromise;\n    try {\n      if (!isInitializing) {\n        backendInfo.initPromise = backendInfo.backend.init(backendName);\n      }\n      await backendInfo.initPromise;\n      backendInfo.initialized = true;\n      return backendInfo.backend;\n    } catch (e) {\n      if (!isInitializing) {\n        backendInfo.error = `${e}`;\n        backendInfo.aborted = true;\n      }\n      return backendInfo.error!;\n    } finally {\n      delete backendInfo.initPromise;\n    }\n  }\n};\n\n/**\n * Resolve execution providers from the specific session options.\n *\n * @param options - the session options object.\n * @returns a promise that resolves to a tuple of an initialized backend instance and a session options object with\n * filtered EP list.\n *\n * @ignore\n */\nexport const resolveBackendAndExecutionProviders = async (\n  options: InferenceSession.SessionOptions,\n): Promise<[backend: Backend, options: InferenceSession.SessionOptions]> => {\n  // extract backend hints from session options\n  const eps = options.executionProviders || [];\n  const backendHints = eps.map((i) => (typeof i === 'string' ? i : i.name));\n  const backendNames = backendHints.length === 0 ? backendsSortedByPriority : backendHints;\n\n  // try to resolve and initialize all requested backends\n  let backend: Backend | undefined;\n  const errors = [];\n  const availableBackendNames = new Set<string>();\n  for (const backendName of backendNames) {\n    const resolveResult = await tryResolveAndInitializeBackend(backendName);\n    if (typeof resolveResult === 'string') {\n      errors.push({ name: backendName, err: resolveResult });\n    } else {\n      if (!backend) {\n        backend = resolveResult;\n      }\n      if (backend === resolveResult) {\n        availableBackendNames.add(backendName);\n      }\n    }\n  }\n\n  // if no backend is available, throw error.\n  if (!backend) {\n    throw new Error(`no available backend found. ERR: ${errors.map((e) => `[${e.name}] ${e.err}`).join(', ')}`);\n  }\n\n  // for each explicitly requested backend, if it's not available, output warning message.\n  for (const { name, err } of errors) {\n    if (backendHints.includes(name)) {\n      // eslint-disable-next-line no-console\n      console.warn(\n        `removing requested execution provider \"${name}\" from session options because it is not available: ${err}`,\n      );\n    }\n  }\n\n  const filteredEps = eps.filter((i) => availableBackendNames.has(typeof i === 'string' ? i : i.name));\n\n  return [\n    backend,\n    new Proxy(options, {\n      get: (target, prop) => {\n        if (prop === 'executionProviders') {\n          return filteredEps;\n        }\n        return Reflect.get(target, prop);\n      },\n    }),\n  ];\n};\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\n// This file is generated by /js/scripts/update-version.ts\n// Do not modify file content manually.\n\nexport const version = '1.29.0';\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { Env } from './env.js';\nimport { version } from './version.js';\n\ntype LogLevelType = Env['logLevel'];\n\nlet logLevelValue: Required<LogLevelType> = 'warning';\n\nexport const env: Env = {\n  wasm: {},\n  webgl: {} as Env.WebGLFlags,\n  webgpu: {} as Env.WebGpuFlags,\n  versions: { common: version },\n\n  set logLevel(value: LogLevelType) {\n    if (value === undefined) {\n      return;\n    }\n    if (typeof value !== 'string' || ['verbose', 'info', 'warning', 'error', 'fatal'].indexOf(value) === -1) {\n      throw new Error(`Unsupported logging level: ${value}`);\n    }\n    logLevelValue = value;\n  },\n  get logLevel(): Required<LogLevelType> {\n    return logLevelValue;\n  },\n};\n\n// set property 'logLevel' so that they can be correctly transferred to worker by `postMessage()`.\nObject.defineProperty(env, 'logLevel', { enumerable: true });\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { env as envImpl } from './env-impl.js';\nimport { TryGetGlobalType } from './type-helper.js';\n\nexport declare namespace Env {\n  export type WasmPathPrefix = string;\n  export interface WasmFilePaths {\n    /**\n     * Specify the override path for the main .wasm file.\n     *\n     * This path should be an absolute path.\n     *\n     * If not modified, the filename of the .wasm file is:\n     * - `ort-wasm-simd-threaded.wasm` for default build\n     * - `ort-wasm-simd-threaded.jsep.wasm` for JSEP build (with WebGPU and WebNN)\n     * - `ort-wasm-simd-threaded.asyncify.wasm` for WebGPU build with Asyncify (with WebNN)\n     * - `ort-wasm-simd-threaded.jspi.wasm` for WebGPU build with JSPI support (with WebNN)\n     */\n    wasm?: URL | string;\n    /**\n     * Specify the override path for the main .mjs file.\n     *\n     * This path should be an absolute path.\n     *\n     * If not modified, the filename of the .mjs file is:\n     * - `ort-wasm-simd-threaded.mjs` for default build\n     * - `ort-wasm-simd-threaded.jsep.mjs` for JSEP build (with WebGPU and WebNN)\n     * - `ort-wasm-simd-threaded.asyncify.mjs` for WebGPU build with Asyncify (with WebNN)\n     * - `ort-wasm-simd-threaded.jspi.mjs` for WebGPU build with JSPI support (with WebNN)\n     */\n    mjs?: URL | string;\n  }\n  export type WasmPrefixOrFilePaths = WasmPathPrefix | WasmFilePaths;\n  export interface WebAssemblyFlags {\n    /**\n     * set or get number of thread(s). If omitted or set to 0, number of thread(s) will be determined by system. If set\n     * to 1, no worker thread will be spawned.\n     *\n     * This setting is available only when WebAssembly multithread feature is available in current context.\n     *\n     * @defaultValue `0`\n     */\n    numThreads?: number;\n\n    /**\n     * set a value indicating whether to enable SIMD.\n     *\n     * ONNX Runtime will perform feature detection based on the value of this property. Specifically, when the value is\n     * set to:\n     * - `undefined`, `true` or `\"fixed\"`: will check availability of Fixed-width SIMD.\n     * - `\"relaxed\"`: will check availability of Relaxed SIMD.\n     * - `false`: will not perform SIMD feature checking.\n     *\n     * Setting this property does not make ONNX Runtime to switch to the corresponding runtime automatically. User need\n     * to set `wasmPaths` or `wasmBinary` property to load the corresponding runtime.\n     *\n     * This setting is available only when WebAssembly SIMD feature is available in current context.\n     *\n     * @defaultValue `true`\n     */\n    simd?: boolean | 'fixed' | 'relaxed';\n\n    /**\n     * set or get a boolean value indicating whether to enable trace.\n     *\n     * @defaultValue `false`\n     *\n     * @deprecated Use `env.trace` instead. If `env.trace` is set, this property will be ignored.\n     */\n    trace?: boolean;\n\n    /**\n     * Set or get a number specifying the timeout for initialization of WebAssembly backend, in milliseconds. A zero\n     * value indicates no timeout is set.\n     *\n     * @defaultValue `0`\n     */\n    initTimeout?: number;\n\n    /**\n     * Set a custom URL prefix to the .wasm/.mjs files, or an object of overrides for both .wasm/.mjs file. The override\n     * path should be an absolute path.\n     */\n    wasmPaths?: WasmPrefixOrFilePaths;\n\n    /**\n     * Set a custom buffer which contains the WebAssembly binary. If this property is set, the `wasmPaths` property will\n     * be ignored.\n     */\n    wasmBinary?: ArrayBufferLike | Uint8Array;\n\n    /**\n     * Set or get a boolean value indicating whether to proxy the execution of main thread to a worker thread.\n     *\n     * @defaultValue `false`\n     */\n    proxy?: boolean;\n  }\n\n  export interface WebGLFlags {\n    /**\n     * Set or get the WebGL Context ID (webgl or webgl2).\n     *\n     * @defaultValue `'webgl2'`\n     */\n    contextId?: 'webgl' | 'webgl2';\n    /**\n     * Get the WebGL rendering context.\n     */\n    readonly context: WebGLRenderingContext;\n    /**\n     * Set or get the maximum batch size for matmul. 0 means to disable batching.\n     *\n     * @deprecated\n     */\n    matmulMaxBatchSize?: number;\n    /**\n     * Set or get the texture cache mode.\n     *\n     * @defaultValue `'full'`\n     */\n    textureCacheMode?: 'initializerOnly' | 'full';\n    /**\n     * Set or get the packed texture mode\n     *\n     * @defaultValue `false`\n     */\n    pack?: boolean;\n    /**\n     * Set or get whether enable async download.\n     *\n     * @defaultValue `false`\n     */\n    async?: boolean;\n  }\n\n  export interface WebGpuProfilingDataV1TensorMetadata {\n    dims: readonly number[];\n    dataType: string;\n  }\n  export interface WebGpuProfilingDataV1 {\n    version: 1;\n    inputsMetadata: readonly WebGpuProfilingDataV1TensorMetadata[];\n    outputsMetadata: readonly WebGpuProfilingDataV1TensorMetadata[];\n    kernelId: number;\n    kernelType: string;\n    kernelName: string;\n    programName: string;\n    startTime: number;\n    endTime: number;\n  }\n\n  export type WebGpuProfilingData = WebGpuProfilingDataV1;\n\n  export interface WebGpuFlags {\n    /**\n     * Set or get the profiling mode.\n     *\n     * @deprecated Use `env.webgpu.profiling.mode` instead. If `env.webgpu.profiling.mode` is set, this property will be\n     * ignored.\n     */\n    profilingMode?: 'off' | 'default';\n    /**\n     * Set or get the profiling configuration.\n     */\n    profiling: {\n      /**\n       * Set or get the profiling mode.\n       *\n       * @defaultValue `'off'`\n       */\n      mode?: 'off' | 'default';\n\n      /**\n       * Set or get a callback function when a profiling data is received. If not set, the profiling data will be\n       * printed to console.\n       */\n      ondata?: (data: WebGpuProfilingData) => void;\n    };\n    /**\n     * Set or get the power preference.\n     *\n     * Setting this property only has effect before the first WebGPU inference session is created. The value will be\n     * used as options for `navigator.gpu.requestAdapter()`.\n     *\n     * See {@link https://gpuweb.github.io/gpuweb/#dictdef-gpurequestadapteroptions} for more details.\n     *\n     * @defaultValue `undefined`\n     *\n     * @deprecated Create your own GPUAdapter, use it to create a GPUDevice instance and set {@link device} property if\n     * you want to use a specific power preference.\n     */\n    powerPreference?: 'low-power' | 'high-performance';\n    /**\n     * Set or get the force fallback adapter flag.\n     *\n     * Setting this property only has effect before the first WebGPU inference session is created. The value will be\n     * used as options for `navigator.gpu.requestAdapter()`.\n     *\n     * See {@link https://gpuweb.github.io/gpuweb/#dictdef-gpurequestadapteroptions} for more details.\n     *\n     * @defaultValue `undefined`\n     *\n     * @deprecated Create your own GPUAdapter, use it to create a GPUDevice instance and set {@link device} property if\n     * you want to use a specific fallback option.\n     */\n    forceFallbackAdapter?: boolean;\n    /**\n     * Set or get the adapter for WebGPU.\n     *\n     * Setting this property only has effect before the first WebGPU inference session is created. The value will be\n     * used as the GPU adapter for the underlying WebGPU backend to create GPU device.\n     *\n     * If this property is not set, it will be available to get after the first WebGPU inference session is created. The\n     * value will be the GPU adapter that created by the underlying WebGPU backend.\n     *\n     * When use with TypeScript, the type of this property is `GPUAdapter` defined in \"@webgpu/types\".\n     *\n     * @deprecated It is no longer recommended to use this property. The latest WebGPU spec adds `GPUDevice.adapterInfo`\n     * (https://www.w3.org/TR/webgpu/#dom-gpudevice-adapterinfo), which allows to get the adapter information from the\n     * device. When it's available, there is no need to set/get the {@link adapter} property.\n     */\n    adapter: TryGetGlobalType<'GPUAdapter'>;\n    /**\n     * Set or get the GPU device for WebGPU.\n     *\n     * There are 3 valid scenarios of accessing this property:\n     * - Set a value before the first WebGPU inference session is created. The value will be used by the WebGPU backend\n     * to perform calculations. If the value is not a `GPUDevice` object, an error will be thrown.\n     * - Get the value before the first WebGPU inference session is created. This will try to create a new GPUDevice\n     * instance. Returns a `Promise` that resolves to a `GPUDevice` object.\n     * - Get the value after the first WebGPU inference session is created. Returns a resolved `Promise` to the\n     * `GPUDevice` object used by the WebGPU backend.\n     */\n    get device(): Promise<TryGetGlobalType<'GPUDevice'>>;\n    set device(value: TryGetGlobalType<'GPUDevice'>);\n    /**\n     * Set or get whether validate input content.\n     *\n     * @defaultValue `false`\n     */\n    validateInputContent?: boolean;\n  }\n}\n\nexport interface Env {\n  /**\n   * set the severity level for logging.\n   *\n   * @defaultValue `'warning'`\n   */\n  logLevel?: 'verbose' | 'info' | 'warning' | 'error' | 'fatal';\n\n  /**\n   * Indicate whether run in debug mode.\n   *\n   * @defaultValue `false`\n   */\n  debug?: boolean;\n\n  /**\n   * set or get a boolean value indicating whether to enable trace.\n   *\n   * @defaultValue `false`\n   */\n  trace?: boolean;\n\n  /**\n   * Get version of the current package.\n   */\n  readonly versions: {\n    readonly common: string;\n    readonly web?: string;\n    readonly node?: string;\n    // eslint-disable-next-line @typescript-eslint/naming-convention\n    readonly 'react-native'?: string;\n  };\n\n  /**\n   * Represent a set of flags for WebAssembly\n   */\n  readonly wasm: Env.WebAssemblyFlags;\n\n  /**\n   * Represent a set of flags for WebGL\n   */\n  readonly webgl: Env.WebGLFlags;\n\n  /**\n   * Represent a set of flags for WebGPU\n   */\n  readonly webgpu: Env.WebGpuFlags;\n\n  [name: string]: unknown;\n}\n\n/**\n * Represent a set of flags as a global singleton.\n */\nexport const env: Env = envImpl;\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { TensorToDataUrlOptions, TensorToImageDataOptions } from './tensor-conversion.js';\nimport { Tensor } from './tensor.js';\n\n/**\n * implementation of Tensor.toDataURL()\n */\nexport const tensorToDataURL = (tensor: Tensor, options?: TensorToDataUrlOptions): string => {\n  const canvas = typeof document !== 'undefined' ? document.createElement('canvas') : new OffscreenCanvas(1, 1);\n  canvas.width = tensor.dims[3];\n  canvas.height = tensor.dims[2];\n  const pixels2DContext = canvas.getContext('2d') as\n    | CanvasRenderingContext2D\n    | OffscreenCanvasRenderingContext2D\n    | null;\n\n  if (pixels2DContext != null) {\n    // Default values for height and width & format\n    let width: number;\n    let height: number;\n    if (options?.tensorLayout !== undefined && options.tensorLayout === 'NHWC') {\n      width = tensor.dims[2];\n      height = tensor.dims[3];\n    } else {\n      // Default layout is NCWH\n      width = tensor.dims[3];\n      height = tensor.dims[2];\n    }\n\n    const inputformat = options?.format !== undefined ? options.format : 'RGB';\n\n    const norm = options?.norm;\n    let normMean: [number, number, number, number];\n    let normBias: [number, number, number, number];\n    if (norm === undefined || norm.mean === undefined) {\n      normMean = [255, 255, 255, 255];\n    } else {\n      if (typeof norm.mean === 'number') {\n        normMean = [norm.mean, norm.mean, norm.mean, norm.mean];\n      } else {\n        normMean = [norm.mean[0], norm.mean[1], norm.mean[2], 0];\n        if (norm.mean[3] !== undefined) {\n          normMean[3] = norm.mean[3];\n        }\n      }\n    }\n    if (norm === undefined || norm.bias === undefined) {\n      normBias = [0, 0, 0, 0];\n    } else {\n      if (typeof norm.bias === 'number') {\n        normBias = [norm.bias, norm.bias, norm.bias, norm.bias];\n      } else {\n        normBias = [norm.bias[0], norm.bias[1], norm.bias[2], 0];\n        if (norm.bias[3] !== undefined) {\n          normBias[3] = norm.bias[3];\n        }\n      }\n    }\n\n    const stride = height * width;\n    // Default pointer assignments\n    let rTensorPointer = 0,\n      gTensorPointer = stride,\n      bTensorPointer = stride * 2,\n      aTensorPointer = -1;\n\n    // Updating the pointer assignments based on the input image format\n    if (inputformat === 'RGBA') {\n      rTensorPointer = 0;\n      gTensorPointer = stride;\n      bTensorPointer = stride * 2;\n      aTensorPointer = stride * 3;\n    } else if (inputformat === 'RGB') {\n      rTensorPointer = 0;\n      gTensorPointer = stride;\n      bTensorPointer = stride * 2;\n    } else if (inputformat === 'RBG') {\n      rTensorPointer = 0;\n      bTensorPointer = stride;\n      gTensorPointer = stride * 2;\n    }\n\n    for (let i = 0; i < height; i++) {\n      for (let j = 0; j < width; j++) {\n        const R = ((tensor.data[rTensorPointer++] as number) - normBias[0]) * normMean[0]; // R value\n        const G = ((tensor.data[gTensorPointer++] as number) - normBias[1]) * normMean[1]; // G value\n        const B = ((tensor.data[bTensorPointer++] as number) - normBias[2]) * normMean[2]; // B value\n        const A = aTensorPointer === -1 ? 255 : ((tensor.data[aTensorPointer++] as number) - normBias[3]) * normMean[3]; // A value\n\n        pixels2DContext.fillStyle = 'rgba(' + R + ',' + G + ',' + B + ',' + A + ')';\n        pixels2DContext.fillRect(j, i, 1, 1);\n      }\n    }\n    if ('toDataURL' in canvas) {\n      return canvas.toDataURL();\n    } else {\n      throw new Error('toDataURL is not supported');\n    }\n  } else {\n    throw new Error('Can not access image data');\n  }\n};\n\n/**\n * implementation of Tensor.toImageData()\n */\nexport const tensorToImageData = (tensor: Tensor, options?: TensorToImageDataOptions): ImageData => {\n  const pixels2DContext =\n    typeof document !== 'undefined'\n      ? document.createElement('canvas').getContext('2d')\n      : (new OffscreenCanvas(1, 1).getContext('2d') as OffscreenCanvasRenderingContext2D);\n  let image: ImageData;\n  if (pixels2DContext != null) {\n    // Default values for height and width & format\n    let width: number;\n    let height: number;\n    let channels: number;\n    if (options?.tensorLayout !== undefined && options.tensorLayout === 'NHWC') {\n      width = tensor.dims[2];\n      height = tensor.dims[1];\n      channels = tensor.dims[3];\n    } else {\n      // Default layout is NCWH\n      width = tensor.dims[3];\n      height = tensor.dims[2];\n      channels = tensor.dims[1];\n    }\n    const inputformat = options !== undefined ? (options.format !== undefined ? options.format : 'RGB') : 'RGB';\n\n    const norm = options?.norm;\n    let normMean: [number, number, number, number];\n    let normBias: [number, number, number, number];\n    if (norm === undefined || norm.mean === undefined) {\n      normMean = [255, 255, 255, 255];\n    } else {\n      if (typeof norm.mean === 'number') {\n        normMean = [norm.mean, norm.mean, norm.mean, norm.mean];\n      } else {\n        normMean = [norm.mean[0], norm.mean[1], norm.mean[2], 255];\n        if (norm.mean[3] !== undefined) {\n          normMean[3] = norm.mean[3];\n        }\n      }\n    }\n    if (norm === undefined || norm.bias === undefined) {\n      normBias = [0, 0, 0, 0];\n    } else {\n      if (typeof norm.bias === 'number') {\n        normBias = [norm.bias, norm.bias, norm.bias, norm.bias];\n      } else {\n        normBias = [norm.bias[0], norm.bias[1], norm.bias[2], 0];\n        if (norm.bias[3] !== undefined) {\n          normBias[3] = norm.bias[3];\n        }\n      }\n    }\n\n    const stride = height * width;\n    if (options !== undefined) {\n      if (\n        (options.format !== undefined && channels === 4 && options.format !== 'RGBA') ||\n        (channels === 3 && options.format !== 'RGB' && options.format !== 'BGR')\n      ) {\n        throw new Error(\"Tensor format doesn't match input tensor dims\");\n      }\n    }\n\n    // Default pointer assignments\n    const step = 4;\n    let rImagePointer = 0,\n      gImagePointer = 1,\n      bImagePointer = 2,\n      aImagePointer = 3;\n    let rTensorPointer = 0,\n      gTensorPointer = stride,\n      bTensorPointer = stride * 2,\n      aTensorPointer = -1;\n\n    // Updating the pointer assignments based on the input image format\n    if (inputformat === 'RGBA') {\n      rTensorPointer = 0;\n      gTensorPointer = stride;\n      bTensorPointer = stride * 2;\n      aTensorPointer = stride * 3;\n    } else if (inputformat === 'RGB') {\n      rTensorPointer = 0;\n      gTensorPointer = stride;\n      bTensorPointer = stride * 2;\n    } else if (inputformat === 'RBG') {\n      rTensorPointer = 0;\n      bTensorPointer = stride;\n      gTensorPointer = stride * 2;\n    }\n\n    image = pixels2DContext.createImageData(width, height);\n\n    for (\n      let i = 0;\n      i < height * width;\n      rImagePointer += step, gImagePointer += step, bImagePointer += step, aImagePointer += step, i++\n    ) {\n      image.data[rImagePointer] = ((tensor.data[rTensorPointer++] as number) - normBias[0]) * normMean[0]; // R value\n      image.data[gImagePointer] = ((tensor.data[gTensorPointer++] as number) - normBias[1]) * normMean[1]; // G value\n      image.data[bImagePointer] = ((tensor.data[bTensorPointer++] as number) - normBias[2]) * normMean[2]; // B value\n      image.data[aImagePointer] =\n        aTensorPointer === -1 ? 255 : ((tensor.data[aTensorPointer++] as number) - normBias[3]) * normMean[3]; // A value\n    }\n  } else {\n    throw new Error('Can not access image data');\n  }\n  return image;\n};\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport {\n  OptionsDimensions,\n  OptionsFormat,\n  OptionsNormalizationParameters,\n  OptionsTensorFormat,\n  OptionsTensorLayout,\n  TensorFromGpuBufferOptions,\n  TensorFromImageBitmapOptions,\n  TensorFromImageDataOptions,\n  TensorFromImageElementOptions,\n  TensorFromMLTensorOptions,\n  TensorFromTextureOptions,\n  TensorFromUrlOptions,\n} from './tensor-factory.js';\nimport { Tensor } from './tensor-impl.js';\nimport { Tensor as TensorInterface } from './tensor.js';\n\ninterface BufferToTensorOptions\n  extends OptionsDimensions, OptionsTensorLayout, OptionsNormalizationParameters, OptionsFormat, OptionsTensorFormat {}\n\n/**\n * Create a new tensor object from image object\n *\n * @param buffer - Extracted image buffer data - assuming RGBA format\n * @param imageFormat - input image configuration - required configurations height, width, format\n * @param tensorFormat - output tensor configuration - Default is RGB format\n */\nexport const bufferToTensor = (buffer: Uint8ClampedArray | undefined, options: BufferToTensorOptions): Tensor => {\n  if (buffer === undefined) {\n    throw new Error('Image buffer must be defined');\n  }\n  if (options.height === undefined || options.width === undefined) {\n    throw new Error('Image height and width must be defined');\n  }\n  if (options.tensorLayout === 'NHWC') {\n    throw new Error('NHWC Tensor layout is not supported yet');\n  }\n\n  const { height, width } = options;\n\n  const norm = options.norm ?? { mean: 255, bias: 0 };\n  let normMean: [number, number, number, number];\n  let normBias: [number, number, number, number];\n\n  if (typeof norm.mean === 'number') {\n    normMean = [norm.mean, norm.mean, norm.mean, norm.mean];\n  } else {\n    normMean = [norm.mean![0], norm.mean![1], norm.mean![2], norm.mean![3] ?? 255];\n  }\n\n  if (typeof norm.bias === 'number') {\n    normBias = [norm.bias, norm.bias, norm.bias, norm.bias];\n  } else {\n    normBias = [norm.bias![0], norm.bias![1], norm.bias![2], norm.bias![3] ?? 0];\n  }\n\n  const inputformat = options.format !== undefined ? options.format : 'RGBA';\n  // default value is RGBA since imagedata and HTMLImageElement uses it\n\n  const outputformat =\n    options.tensorFormat !== undefined ? (options.tensorFormat !== undefined ? options.tensorFormat : 'RGB') : 'RGB';\n  const stride = height * width;\n  const float32Data = outputformat === 'RGBA' ? new Float32Array(stride * 4) : new Float32Array(stride * 3);\n\n  // Default pointer assignments\n  let step = 4,\n    rImagePointer = 0,\n    gImagePointer = 1,\n    bImagePointer = 2,\n    aImagePointer = 3;\n  let rTensorPointer = 0,\n    gTensorPointer = stride,\n    bTensorPointer = stride * 2,\n    aTensorPointer = -1;\n\n  // Updating the pointer assignments based on the input image format\n  if (inputformat === 'RGB') {\n    step = 3;\n    rImagePointer = 0;\n    gImagePointer = 1;\n    bImagePointer = 2;\n    aImagePointer = -1;\n  }\n\n  // Updating the pointer assignments based on the output tensor format\n  if (outputformat === 'RGBA') {\n    aTensorPointer = stride * 3;\n  } else if (outputformat === 'RBG') {\n    rTensorPointer = 0;\n    bTensorPointer = stride;\n    gTensorPointer = stride * 2;\n  } else if (outputformat === 'BGR') {\n    bTensorPointer = 0;\n    gTensorPointer = stride;\n    rTensorPointer = stride * 2;\n  }\n\n  for (\n    let i = 0;\n    i < stride;\n    i++, rImagePointer += step, bImagePointer += step, gImagePointer += step, aImagePointer += step\n  ) {\n    float32Data[rTensorPointer++] = (buffer[rImagePointer] + normBias[0]) / normMean[0];\n    float32Data[gTensorPointer++] = (buffer[gImagePointer] + normBias[1]) / normMean[1];\n    float32Data[bTensorPointer++] = (buffer[bImagePointer] + normBias[2]) / normMean[2];\n    if (aTensorPointer !== -1 && aImagePointer !== -1) {\n      float32Data[aTensorPointer++] = (buffer[aImagePointer] + normBias[3]) / normMean[3];\n    }\n  }\n\n  // Float32Array -> ort.Tensor\n  const outputTensor =\n    outputformat === 'RGBA'\n      ? new Tensor('float32', float32Data, [1, 4, height, width])\n      : new Tensor('float32', float32Data, [1, 3, height, width]);\n  return outputTensor;\n};\n\n/**\n * implementation of Tensor.fromImage().\n */\nexport const tensorFromImage = async (\n  image: ImageData | HTMLImageElement | ImageBitmap | string,\n  options?:\n    | TensorFromImageDataOptions\n    | TensorFromImageElementOptions\n    | TensorFromImageBitmapOptions\n    | TensorFromUrlOptions,\n): Promise<Tensor> => {\n  // checking the type of image object\n  const isHTMLImageEle = typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement;\n  const isImageDataEle = typeof ImageData !== 'undefined' && image instanceof ImageData;\n  const isImageBitmap = typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap;\n  const isString = typeof image === 'string';\n\n  let data: Uint8ClampedArray | undefined;\n  let bufferToTensorOptions: BufferToTensorOptions = options ?? {};\n\n  const createCanvas = () => {\n    if (typeof document !== 'undefined') {\n      return document.createElement('canvas');\n    } else if (typeof OffscreenCanvas !== 'undefined') {\n      return new OffscreenCanvas(1, 1);\n    } else {\n      throw new Error('Canvas is not supported');\n    }\n  };\n  const createCanvasContext = (canvas: HTMLCanvasElement | OffscreenCanvas) => {\n    if (typeof HTMLCanvasElement !== 'undefined' && canvas instanceof HTMLCanvasElement) {\n      return canvas.getContext('2d');\n    } else if (canvas instanceof OffscreenCanvas) {\n      return canvas.getContext('2d') as OffscreenCanvasRenderingContext2D;\n    } else {\n      return null;\n    }\n  };\n  // filling and checking image configuration options\n  if (isHTMLImageEle) {\n    // HTMLImageElement - image object - format is RGBA by default\n    const canvas = createCanvas();\n    canvas.width = image.width;\n    canvas.height = image.height;\n    const pixels2DContext = createCanvasContext(canvas);\n\n    if (pixels2DContext != null) {\n      let height = image.height;\n      let width = image.width;\n      if (options !== undefined && options.resizedHeight !== undefined && options.resizedWidth !== undefined) {\n        height = options.resizedHeight;\n        width = options.resizedWidth;\n      }\n\n      if (options !== undefined) {\n        bufferToTensorOptions = options;\n        if (options.tensorFormat !== undefined) {\n          throw new Error('Image input config format must be RGBA for HTMLImageElement');\n        } else {\n          bufferToTensorOptions.tensorFormat = 'RGBA';\n        }\n        bufferToTensorOptions.height = height;\n        bufferToTensorOptions.width = width;\n      } else {\n        bufferToTensorOptions.tensorFormat = 'RGBA';\n        bufferToTensorOptions.height = height;\n        bufferToTensorOptions.width = width;\n      }\n\n      pixels2DContext.drawImage(image, 0, 0);\n      data = pixels2DContext.getImageData(0, 0, width, height).data;\n    } else {\n      throw new Error('Can not access image data');\n    }\n  } else if (isImageDataEle) {\n    let height: number;\n    let width: number;\n\n    if (options !== undefined && options.resizedWidth !== undefined && options.resizedHeight !== undefined) {\n      height = options.resizedHeight;\n      width = options.resizedWidth;\n    } else {\n      height = image.height;\n      width = image.width;\n    }\n\n    if (options !== undefined) {\n      bufferToTensorOptions = options;\n    }\n    bufferToTensorOptions.format = 'RGBA';\n    bufferToTensorOptions.height = height;\n    bufferToTensorOptions.width = width;\n\n    if (options !== undefined) {\n      const tempCanvas = createCanvas();\n\n      tempCanvas.width = width;\n      tempCanvas.height = height;\n\n      const pixels2DContext = createCanvasContext(tempCanvas);\n\n      if (pixels2DContext != null) {\n        pixels2DContext.putImageData(image, 0, 0);\n        data = pixels2DContext.getImageData(0, 0, width, height).data;\n      } else {\n        throw new Error('Can not access image data');\n      }\n    } else {\n      data = image.data;\n    }\n  } else if (isImageBitmap) {\n    // ImageBitmap - image object - format must be provided by user\n    if (options === undefined) {\n      throw new Error('Please provide image config with format for Imagebitmap');\n    }\n\n    const canvas = createCanvas();\n    canvas.width = image.width;\n    canvas.height = image.height;\n    const pixels2DContext = createCanvasContext(canvas);\n\n    if (pixels2DContext != null) {\n      const height = image.height;\n      const width = image.width;\n      pixels2DContext.drawImage(image, 0, 0, width, height);\n      data = pixels2DContext.getImageData(0, 0, width, height).data;\n      bufferToTensorOptions.height = height;\n      bufferToTensorOptions.width = width;\n      return bufferToTensor(data, bufferToTensorOptions);\n    } else {\n      throw new Error('Can not access image data');\n    }\n  } else if (isString) {\n    return new Promise((resolve, reject) => {\n      const canvas = createCanvas();\n      const context = createCanvasContext(canvas);\n      if (!image || !context) {\n        return reject();\n      }\n      const newImage = new Image();\n      newImage.crossOrigin = 'Anonymous';\n      newImage.src = image;\n      newImage.onload = () => {\n        canvas.width = newImage.width;\n        canvas.height = newImage.height;\n        context.drawImage(newImage, 0, 0, canvas.width, canvas.height);\n        const img = context.getImageData(0, 0, canvas.width, canvas.height);\n\n        bufferToTensorOptions.height = canvas.height;\n        bufferToTensorOptions.width = canvas.width;\n        resolve(bufferToTensor(img.data, bufferToTensorOptions));\n      };\n    });\n  } else {\n    throw new Error('Input data provided is not supported - aborted tensor creation');\n  }\n\n  if (data !== undefined) {\n    return bufferToTensor(data, bufferToTensorOptions);\n  } else {\n    throw new Error('Input data provided is not supported - aborted tensor creation');\n  }\n};\n\n/**\n * implementation of Tensor.fromTexture().\n */\nexport const tensorFromTexture = <T extends TensorInterface.TextureDataTypes>(\n  texture: TensorInterface.TextureType,\n  options: TensorFromTextureOptions<T>,\n): Tensor => {\n  const { width, height, download, dispose } = options;\n  // Always assume RGBAF32. TODO: support different texture format\n  const dims = [1, height, width, 4];\n  return new Tensor({ location: 'texture', type: 'float32', texture, dims, download, dispose });\n};\n\n/**\n * implementation of Tensor.fromGpuBuffer().\n */\nexport const tensorFromGpuBuffer = <T extends TensorInterface.GpuBufferDataTypes>(\n  gpuBuffer: TensorInterface.GpuBufferType,\n  options: TensorFromGpuBufferOptions<T>,\n): Tensor => {\n  const { dataType, dims, download, dispose } = options;\n  return new Tensor({ location: 'gpu-buffer', type: dataType ?? 'float32', gpuBuffer, dims, download, dispose });\n};\n\n/**\n * implementation of Tensor.fromMLTensor().\n */\nexport const tensorFromMLTensor = <T extends TensorInterface.MLTensorDataTypes>(\n  mlTensor: TensorInterface.MLTensorType,\n  options: TensorFromMLTensorOptions<T>,\n): Tensor => {\n  const { dataType, dims, download, dispose } = options;\n  return new Tensor({ location: 'ml-tensor', type: dataType ?? 'float32', mlTensor, dims, download, dispose });\n};\n\n/**\n * implementation of Tensor.fromPinnedBuffer().\n */\nexport const tensorFromPinnedBuffer = <T extends TensorInterface.CpuPinnedDataTypes>(\n  type: T,\n  buffer: TensorInterface.DataTypeMap[T],\n  dims?: readonly number[],\n): Tensor => new Tensor({ location: 'cpu-pinned', type, data: buffer, dims: dims ?? [buffer.length] });\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { Tensor } from './tensor.js';\n\nexport type SupportedTypedArrayConstructors =\n  | Float32ArrayConstructor\n  | Uint8ArrayConstructor\n  | Int8ArrayConstructor\n  | Uint16ArrayConstructor\n  | Int16ArrayConstructor\n  | Int32ArrayConstructor\n  | BigInt64ArrayConstructor\n  | Uint8ArrayConstructor\n  | Float64ArrayConstructor\n  | Uint32ArrayConstructor\n  | BigUint64ArrayConstructor;\nexport type SupportedTypedArray = InstanceType<SupportedTypedArrayConstructors>;\n\n// a runtime map that maps type string to TypedArray constructor. Should match Tensor.DataTypeMap.\nexport const NUMERIC_TENSOR_TYPE_TO_TYPEDARRAY_MAP = new Map<string, SupportedTypedArrayConstructors>([\n  ['float32', Float32Array],\n  ['uint8', Uint8Array],\n  ['int8', Int8Array],\n  ['uint16', Uint16Array],\n  ['int16', Int16Array],\n  ['int32', Int32Array],\n  ['bool', Uint8Array],\n  ['float64', Float64Array],\n  ['uint32', Uint32Array],\n  ['int4', Uint8Array],\n  ['uint4', Uint8Array],\n]);\n\n// a runtime map that maps type string to TypedArray constructor. Should match Tensor.DataTypeMap.\nexport const NUMERIC_TENSOR_TYPEDARRAY_TO_TYPE_MAP = new Map<SupportedTypedArrayConstructors, Tensor.Type>([\n  [Float32Array, 'float32'],\n  [Uint8Array, 'uint8'],\n  [Int8Array, 'int8'],\n  [Uint16Array, 'uint16'],\n  [Int16Array, 'int16'],\n  [Int32Array, 'int32'],\n  [Float64Array, 'float64'],\n  [Uint32Array, 'uint32'],\n]);\n\n// the following code allows delaying execution of BigInt/Float16Array checking. This allows lazy initialization for\n// NUMERIC_TENSOR_TYPE_TO_TYPEDARRAY_MAP and NUMERIC_TENSOR_TYPEDARRAY_TO_TYPE_MAP, which allows BigInt/Float16Array\n// polyfill if available.\nlet isTypedArrayChecked = false;\nexport const checkTypedArray = () => {\n  if (!isTypedArrayChecked) {\n    isTypedArrayChecked = true;\n    const isBigInt64ArrayAvailable = typeof BigInt64Array !== 'undefined' && BigInt64Array.from;\n    const isBigUint64ArrayAvailable = typeof BigUint64Array !== 'undefined' && BigUint64Array.from;\n\n    // eslint-disable-next-line @typescript-eslint/naming-convention, @typescript-eslint/no-explicit-any\n    const Float16Array = (globalThis as any).Float16Array;\n    const isFloat16ArrayAvailable = typeof Float16Array !== 'undefined' && Float16Array.from;\n\n    if (isBigInt64ArrayAvailable) {\n      NUMERIC_TENSOR_TYPE_TO_TYPEDARRAY_MAP.set('int64', BigInt64Array);\n      NUMERIC_TENSOR_TYPEDARRAY_TO_TYPE_MAP.set(BigInt64Array, 'int64');\n    }\n    if (isBigUint64ArrayAvailable) {\n      NUMERIC_TENSOR_TYPE_TO_TYPEDARRAY_MAP.set('uint64', BigUint64Array);\n      NUMERIC_TENSOR_TYPEDARRAY_TO_TYPE_MAP.set(BigUint64Array, 'uint64');\n    }\n    if (isFloat16ArrayAvailable) {\n      NUMERIC_TENSOR_TYPE_TO_TYPEDARRAY_MAP.set('float16', Float16Array);\n      NUMERIC_TENSOR_TYPEDARRAY_TO_TYPE_MAP.set(Float16Array, 'float16');\n    } else {\n      // if Float16Array is not available, use 'Uint16Array' to store the data.\n      NUMERIC_TENSOR_TYPE_TO_TYPEDARRAY_MAP.set('float16', Uint16Array);\n    }\n  }\n};\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport {\n  CpuPinnedConstructorParameters,\n  GpuBufferConstructorParameters,\n  MLTensorConstructorParameters,\n  TextureConstructorParameters,\n} from './tensor-factory.js';\nimport { Tensor } from './tensor-impl.js';\n\n/**\n * calculate size from dims.\n *\n * @param dims the dims array. May be an illegal input.\n */\nexport const calculateSize = (dims: readonly unknown[]): number => {\n  let size = 1;\n  for (let i = 0; i < dims.length; i++) {\n    const dim = dims[i];\n    if (typeof dim !== 'number' || !Number.isSafeInteger(dim)) {\n      throw new TypeError(`dims[${i}] must be an integer, got: ${dim}`);\n    }\n    if (dim < 0) {\n      throw new RangeError(`dims[${i}] must be a non-negative integer, got: ${dim}`);\n    }\n    size *= dim;\n  }\n  return size;\n};\n\n/**\n * implementation of Tensor.reshape()\n */\nexport const tensorReshape = (tensor: Tensor, dims: readonly number[]): Tensor => {\n  switch (tensor.location) {\n    case 'cpu':\n      return new Tensor(tensor.type, tensor.data, dims);\n    case 'cpu-pinned':\n      return new Tensor({\n        location: 'cpu-pinned',\n        data: tensor.data as CpuPinnedConstructorParameters['data'],\n        type: tensor.type as CpuPinnedConstructorParameters['type'],\n        dims,\n      });\n    case 'texture':\n      return new Tensor({\n        location: 'texture',\n        texture: tensor.texture,\n        type: tensor.type as TextureConstructorParameters['type'],\n        dims,\n      });\n    case 'gpu-buffer':\n      return new Tensor({\n        location: 'gpu-buffer',\n        gpuBuffer: tensor.gpuBuffer,\n        type: tensor.type as GpuBufferConstructorParameters['type'],\n        dims,\n      });\n    case 'ml-tensor':\n      return new Tensor({\n        location: 'ml-tensor',\n        mlTensor: tensor.mlTensor,\n        type: tensor.type as MLTensorConstructorParameters['type'],\n        dims,\n      });\n    default:\n      throw new Error(`tensorReshape: tensor location ${tensor.location} is not supported`);\n  }\n};\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { tensorToDataURL, tensorToImageData } from './tensor-conversion-impl.js';\nimport { TensorToDataUrlOptions, TensorToImageDataOptions } from './tensor-conversion.js';\nimport {\n  tensorFromGpuBuffer,\n  tensorFromImage,\n  tensorFromMLTensor,\n  tensorFromPinnedBuffer,\n  tensorFromTexture,\n} from './tensor-factory-impl.js';\nimport {\n  CpuPinnedConstructorParameters,\n  GpuBufferConstructorParameters,\n  MLTensorConstructorParameters,\n  TensorFromGpuBufferOptions,\n  TensorFromImageBitmapOptions,\n  TensorFromImageDataOptions,\n  TensorFromImageElementOptions,\n  TensorFromMLTensorOptions,\n  TensorFromTextureOptions,\n  TensorFromUrlOptions,\n  TextureConstructorParameters,\n} from './tensor-factory.js';\nimport {\n  checkTypedArray,\n  NUMERIC_TENSOR_TYPE_TO_TYPEDARRAY_MAP,\n  NUMERIC_TENSOR_TYPEDARRAY_TO_TYPE_MAP,\n  SupportedTypedArray,\n  SupportedTypedArrayConstructors,\n} from './tensor-impl-type-mapping.js';\nimport { calculateSize, tensorReshape } from './tensor-utils-impl.js';\nimport { Tensor as TensorInterface } from './tensor.js';\n\n// type aliases for those exported from Tensor interface\n\ntype TensorType = TensorInterface.Type;\ntype TensorDataType = TensorInterface.DataType;\ntype TensorDataLocation = TensorInterface.DataLocation;\ntype TensorTextureType = TensorInterface.TextureType;\ntype TensorGpuBufferType = TensorInterface.GpuBufferType;\ntype TensorMLTensorType = TensorInterface.MLTensorType;\n\n/**\n * the implementation of Tensor interface.\n *\n * @ignore\n */\nexport class Tensor implements TensorInterface {\n  // #region constructors\n\n  /**\n   * Construct a new CPU tensor object from the given type, data and dims.\n   */\n  constructor(\n    type: TensorType,\n    data: TensorDataType | Uint8ClampedArray | readonly string[] | readonly number[] | readonly boolean[],\n    dims?: readonly number[],\n  );\n  /**\n   * Construct a new CPU tensor object from the given data and dims. Type is inferred from data.\n   */\n  constructor(\n    data: TensorDataType | Uint8ClampedArray | readonly string[] | readonly boolean[],\n    dims?: readonly number[],\n  );\n  /**\n   * Construct a new tensor object from the pinned CPU data with the given type and dims.\n   *\n   * Tensor's location will be set to 'cpu-pinned'.\n   *\n   * @param params - Specify the parameters to construct the tensor.\n   */\n  constructor(params: CpuPinnedConstructorParameters);\n  /**\n   * Construct a new tensor object from the WebGL texture with the given type and dims.\n   *\n   * Tensor's location will be set to 'texture'.\n   *\n   * @param params - Specify the parameters to construct the tensor.\n   */\n  constructor(params: TextureConstructorParameters);\n  /**\n   * Construct a new tensor object from the WebGPU buffer with the given type and dims.\n   *\n   * Tensor's location will be set to 'gpu-buffer'.\n   *\n   * @param params - Specify the parameters to construct the tensor.\n   */\n  constructor(params: GpuBufferConstructorParameters);\n\n  /**\n   * Construct a new tensor object from the WebNN MLTensor with the given type and dims.\n   *\n   * Tensor's location will be set to 'ml-tensor'.\n   *\n   * @param params - Specify the parameters to construct the tensor.\n   */\n  constructor(params: MLTensorConstructorParameters);\n\n  /**\n   * implementation.\n   */\n  constructor(\n    arg0:\n      | TensorType\n      | TensorDataType\n      | Uint8ClampedArray\n      | readonly string[]\n      | readonly boolean[]\n      | CpuPinnedConstructorParameters\n      | TextureConstructorParameters\n      | GpuBufferConstructorParameters\n      | MLTensorConstructorParameters,\n    arg1?: TensorDataType | Uint8ClampedArray | readonly number[] | readonly string[] | readonly boolean[],\n    arg2?: readonly number[],\n  ) {\n    // perform one-time check for BigInt/Float16Array support\n    checkTypedArray();\n\n    let type: TensorType;\n    let dims: readonly number[];\n\n    if (typeof arg0 === 'object' && 'location' in arg0) {\n      //\n      // constructing tensor from specific location\n      //\n      this.dataLocation = arg0.location;\n      type = arg0.type;\n      dims = arg0.dims;\n      switch (arg0.location) {\n        case 'cpu-pinned': {\n          const expectedTypedArrayConstructor = NUMERIC_TENSOR_TYPE_TO_TYPEDARRAY_MAP.get(type);\n          if (!expectedTypedArrayConstructor) {\n            throw new TypeError(`unsupported type \"${type}\" to create tensor from pinned buffer`);\n          }\n          if (!(arg0.data instanceof expectedTypedArrayConstructor)) {\n            throw new TypeError(`buffer should be of type ${expectedTypedArrayConstructor.name}`);\n          }\n          this.cpuData = arg0.data;\n          break;\n        }\n        case 'texture': {\n          if (type !== 'float32') {\n            throw new TypeError(`unsupported type \"${type}\" to create tensor from texture`);\n          }\n          this.gpuTextureData = arg0.texture;\n          this.downloader = arg0.download;\n          this.disposer = arg0.dispose;\n          break;\n        }\n        case 'gpu-buffer': {\n          if (\n            type !== 'float32' &&\n            type !== 'float16' &&\n            type !== 'int32' &&\n            type !== 'int64' &&\n            type !== 'uint32' &&\n            type !== 'uint8' &&\n            type !== 'bool' &&\n            type !== 'uint4' &&\n            type !== 'int4'\n          ) {\n            throw new TypeError(`unsupported type \"${type}\" to create tensor from gpu buffer`);\n          }\n          this.gpuBufferData = arg0.gpuBuffer;\n          this.downloader = arg0.download;\n          this.disposer = arg0.dispose;\n          break;\n        }\n        case 'ml-tensor': {\n          if (\n            type !== 'float32' &&\n            type !== 'float16' &&\n            type !== 'int32' &&\n            type !== 'int64' &&\n            type !== 'uint32' &&\n            type !== 'uint64' &&\n            type !== 'int8' &&\n            type !== 'uint8' &&\n            type !== 'bool' &&\n            type !== 'uint4' &&\n            type !== 'int4'\n          ) {\n            throw new TypeError(`unsupported type \"${type}\" to create tensor from MLTensor`);\n          }\n          this.mlTensorData = arg0.mlTensor;\n          this.downloader = arg0.download;\n          this.disposer = arg0.dispose;\n          break;\n        }\n        default:\n          throw new Error(`Tensor constructor: unsupported location '${this.dataLocation}'`);\n      }\n    } else {\n      //\n      // constructing tensor of location 'cpu'\n      //\n      let data: TensorDataType;\n      let maybeDims: typeof arg1 | typeof arg2;\n      // check whether arg0 is type or data\n      if (typeof arg0 === 'string') {\n        //\n        // Override: constructor(type, data, ...)\n        //\n        type = arg0;\n        maybeDims = arg2;\n        if (arg0 === 'string') {\n          // string tensor\n          if (!Array.isArray(arg1)) {\n            throw new TypeError(\"A string tensor's data must be a string array.\");\n          }\n          // we don't check whether every element in the array is string; this is too slow. we assume it's correct and\n          // error will be populated at inference\n          data = arg1;\n        } else {\n          // numeric tensor\n          const typedArrayConstructor = NUMERIC_TENSOR_TYPE_TO_TYPEDARRAY_MAP.get(arg0);\n          if (typedArrayConstructor === undefined) {\n            throw new TypeError(`Unsupported tensor type: ${arg0}.`);\n          }\n          if (Array.isArray(arg1)) {\n            if ((arg0 === 'float16' && typedArrayConstructor === Uint16Array) || arg0 === 'uint4' || arg0 === 'int4') {\n              // - 'float16':\n              //   When no Float16Array polyfill is used, we cannot create 'float16' tensor from number array.\n              //\n              //   Throw error here because when user try to use number array as data,\n              //   e.g. new Tensor('float16', [1, 2, 3, 4], dims)), it will actually call\n              //   Uint16Array.from(arg1) which generates wrong data.\n              //\n              // - 'uint4' and 'int4':\n              //   Uint8Array.from(arg1) will generate wrong data for 'uint4' and 'int4' tensor.\n              //\n              throw new TypeError(\n                `Creating a ${arg0} tensor from number array is not supported. Please use ${typedArrayConstructor.name} as data.`,\n              );\n            } else if (arg0 === 'uint64' || arg0 === 'int64') {\n              // use 'as any' here because:\n              // 1. TypeScript's check on type of 'Array.isArray()' does not work with readonly arrays.\n              // see https://github.com/microsoft/TypeScript/issues/17002\n              // 2. TypeScript's check on union type of '(BigInt64ArrayConstructor|BigUint64ArrayConstructor).from()'\n              // does not accept parameter mapFn.\n              // 3. parameters of 'SupportedTypedArrayConstructors.from()' does not match the requirement of the union\n              // type.\n\n              // assume 'arg1' is of type \"readonly number[]|readonly bigint[]\" here.\n\n              // eslint-disable-next-line @typescript-eslint/no-explicit-any\n              data = (typedArrayConstructor as any).from(arg1, BigInt);\n            } else {\n              // assume 'arg1' is of type \"readonly number[]\" here.\n              // eslint-disable-next-line @typescript-eslint/no-explicit-any\n              data = (typedArrayConstructor as any).from(arg1);\n            }\n          } else if (arg1 instanceof typedArrayConstructor) {\n            data = arg1;\n          } else if (arg1 instanceof Uint8ClampedArray) {\n            if (arg0 === 'uint8') {\n              data = Uint8Array.from(arg1);\n            } else {\n              throw new TypeError(`A Uint8ClampedArray tensor's data must be type of uint8`);\n            }\n          } else if (arg0 === 'float16' && arg1 instanceof Uint16Array && typedArrayConstructor !== Uint16Array) {\n            // when Float16Array is available and data is of type Uint16Array.\n            // We allow Uint16Array to be passed in as data for 'float16' tensor until Float16Array is generally\n            // supported in JavaScript environment.\n\n            // eslint-disable-next-line @typescript-eslint/no-explicit-any\n            data = new (globalThis as any).Float16Array(arg1.buffer, arg1.byteOffset, arg1.length);\n          } else {\n            throw new TypeError(`A ${type} tensor's data must be type of ${typedArrayConstructor}`);\n          }\n        }\n      } else {\n        //\n        // Override: constructor(data, ...)\n        //\n        maybeDims = arg1;\n        if (Array.isArray(arg0)) {\n          // only boolean[] and string[] is supported\n          if (arg0.length === 0) {\n            throw new TypeError('Tensor type cannot be inferred from an empty array.');\n          }\n          const firstElementType = typeof arg0[0];\n          if (firstElementType === 'string') {\n            type = 'string';\n            data = arg0;\n          } else if (firstElementType === 'boolean') {\n            type = 'bool';\n            // 'arg0' is of type 'boolean[]'. Uint8Array.from(boolean[]) actually works, but typescript thinks this is\n            // wrong type. We use 'as any' to make it happy.\n            // eslint-disable-next-line @typescript-eslint/no-explicit-any\n            data = Uint8Array.from(arg0 as any[]);\n          } else {\n            throw new TypeError(`Invalid element type of data array: ${firstElementType}.`);\n          }\n        } else if (arg0 instanceof Uint8ClampedArray) {\n          type = 'uint8';\n          data = Uint8Array.from(arg0);\n        } else {\n          // get tensor type from TypedArray\n          const mappedType = NUMERIC_TENSOR_TYPEDARRAY_TO_TYPE_MAP.get(\n            arg0.constructor as SupportedTypedArrayConstructors,\n          );\n          if (mappedType === undefined) {\n            throw new TypeError(`Unsupported type for tensor data: ${arg0.constructor}.`);\n          }\n          type = mappedType;\n          data = arg0 as SupportedTypedArray;\n        }\n      }\n\n      // type and data is processed, now processing dims\n      if (maybeDims === undefined) {\n        // assume 1-D tensor if dims omitted\n        maybeDims = [data.length];\n      } else if (!Array.isArray(maybeDims)) {\n        throw new TypeError(\"A tensor's dims must be a number array\");\n      }\n      dims = maybeDims as readonly number[];\n\n      this.cpuData = data;\n      this.dataLocation = 'cpu';\n    }\n\n    // perform check on dims\n    const size = calculateSize(dims);\n    // if data is on CPU, check whether data length matches tensor size\n    if (this.cpuData && size !== this.cpuData.length) {\n      if ((type === 'uint4' || type === 'int4') && Math.ceil(size / 2) === this.cpuData.length) {\n        // for (u)int4, the data length is half of the tensor size. So we check this special case when size is odd.\n      } else {\n        throw new Error(`Tensor's size(${size}) does not match data length(${this.cpuData.length}).`);\n      }\n    }\n\n    this.type = type;\n    this.dims = dims;\n    this.size = size;\n  }\n  // #endregion\n\n  // #region factory\n  static async fromImage(\n    image: ImageData | HTMLImageElement | ImageBitmap | string,\n    options?:\n      | TensorFromImageDataOptions\n      | TensorFromImageElementOptions\n      | TensorFromImageBitmapOptions\n      | TensorFromUrlOptions,\n  ): Promise<TensorInterface> {\n    return tensorFromImage(image, options);\n  }\n\n  static fromTexture<T extends TensorInterface.TextureDataTypes>(\n    texture: TensorTextureType,\n    options: TensorFromTextureOptions<T>,\n  ): TensorInterface {\n    return tensorFromTexture(texture, options);\n  }\n\n  static fromGpuBuffer<T extends TensorInterface.GpuBufferDataTypes>(\n    gpuBuffer: TensorGpuBufferType,\n    options: TensorFromGpuBufferOptions<T>,\n  ): TensorInterface {\n    return tensorFromGpuBuffer(gpuBuffer, options);\n  }\n\n  static fromMLTensor<T extends TensorInterface.MLTensorDataTypes>(\n    mlTensor: TensorMLTensorType,\n    options: TensorFromMLTensorOptions<T>,\n  ): TensorInterface {\n    return tensorFromMLTensor(mlTensor, options);\n  }\n\n  static fromPinnedBuffer<T extends TensorInterface.CpuPinnedDataTypes>(\n    type: T,\n    buffer: TensorInterface.DataTypeMap[T],\n    dims?: readonly number[],\n  ): Tensor {\n    return tensorFromPinnedBuffer(type, buffer, dims);\n  }\n\n  // #endregion\n\n  // #region conversions\n  toDataURL(options?: TensorToDataUrlOptions): string {\n    return tensorToDataURL(this, options);\n  }\n\n  toImageData(options?: TensorToImageDataOptions): ImageData {\n    return tensorToImageData(this, options);\n  }\n  // #endregion\n\n  // #region public fields\n  readonly dims: readonly number[];\n  readonly type: TensorType;\n  readonly size: number;\n  // #endregion\n\n  // #region private fields\n\n  /**\n   * stores the location of the data.\n   */\n  private dataLocation: TensorDataLocation;\n\n  /**\n   * stores the data on CPU, if location is 'cpu' or 'cpu-pinned'. otherwise empty.\n   */\n  private cpuData?: TensorDataType;\n\n  /**\n   * stores the underlying texture when location is 'texture'. otherwise empty.\n   */\n  private gpuTextureData?: TensorTextureType;\n\n  /**\n   * stores the underlying GPU buffer when location is 'gpu-buffer'. otherwise empty.\n   */\n  private gpuBufferData?: TensorGpuBufferType;\n\n  /**\n   * stores the underlying WebNN MLTensor when location is 'ml-tensor'. otherwise empty.\n   */\n  private mlTensorData?: TensorMLTensorType;\n\n  /**\n   * stores an optional downloader function to download data from GPU to CPU.\n   */\n  private downloader?(): Promise<TensorDataType>;\n\n  /**\n   * a flag indicating whether the data is being downloaded from GPU to CPU.\n   */\n  private isDownloading?: boolean;\n\n  /**\n   * stores an optional disposer function to dispose the underlying data.\n   */\n  private disposer?(): void;\n  // #endregion\n\n  // #region properties\n  get data(): TensorDataType {\n    this.ensureValid();\n    if (!this.cpuData) {\n      throw new Error(\n        'The data is not on CPU. Use `getData()` to download GPU data to CPU, ' +\n          'or use `texture` or `gpuBuffer` property to access the GPU data directly.',\n      );\n    }\n    return this.cpuData;\n  }\n\n  get location(): TensorDataLocation {\n    return this.dataLocation;\n  }\n\n  get texture(): TensorTextureType {\n    this.ensureValid();\n    if (!this.gpuTextureData) {\n      throw new Error('The data is not stored as a WebGL texture.');\n    }\n    return this.gpuTextureData;\n  }\n\n  get gpuBuffer(): TensorGpuBufferType {\n    this.ensureValid();\n    if (!this.gpuBufferData) {\n      throw new Error('The data is not stored as a WebGPU buffer.');\n    }\n    return this.gpuBufferData;\n  }\n\n  get mlTensor(): TensorMLTensorType {\n    this.ensureValid();\n    if (!this.mlTensorData) {\n      throw new Error('The data is not stored as a WebNN MLTensor.');\n    }\n    return this.mlTensorData;\n  }\n  // #endregion\n\n  // #region methods\n\n  async getData(releaseData?: boolean): Promise<TensorDataType> {\n    this.ensureValid();\n    switch (this.dataLocation) {\n      case 'cpu':\n      case 'cpu-pinned':\n        return this.data;\n      case 'texture':\n      case 'gpu-buffer':\n      case 'ml-tensor': {\n        if (!this.downloader) {\n          throw new Error('The current tensor is not created with a specified data downloader.');\n        }\n        if (this.isDownloading) {\n          throw new Error('The current tensor is being downloaded.');\n        }\n        try {\n          this.isDownloading = true;\n          const data = await this.downloader();\n          this.downloader = undefined;\n          this.dataLocation = 'cpu';\n          this.cpuData = data;\n\n          if (releaseData && this.disposer) {\n            this.disposer();\n            this.disposer = undefined;\n          }\n\n          return data;\n        } finally {\n          this.isDownloading = false;\n        }\n      }\n      default:\n        throw new Error(`cannot get data from location: ${this.dataLocation}`);\n    }\n  }\n\n  dispose(): void {\n    if (this.isDownloading) {\n      throw new Error('The current tensor is being downloaded.');\n    }\n\n    if (this.disposer) {\n      this.disposer();\n      this.disposer = undefined;\n    }\n    this.cpuData = undefined;\n    this.gpuTextureData = undefined;\n    this.gpuBufferData = undefined;\n    this.mlTensorData = undefined;\n    this.downloader = undefined;\n    this.isDownloading = undefined;\n\n    this.dataLocation = 'none';\n  }\n\n  // #endregion\n\n  // #region tensor utilities\n  private ensureValid(): void {\n    if (this.dataLocation === 'none') {\n      throw new Error('The tensor is disposed.');\n    }\n  }\n\n  reshape(dims: readonly number[]): TensorInterface {\n    this.ensureValid();\n    if (this.downloader || this.disposer) {\n      throw new Error('Cannot reshape a tensor that owns GPU resource.');\n    }\n    return tensorReshape(this, dims);\n  }\n  // #endregion\n}\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { TensorFactory } from './tensor-factory.js';\nimport { Tensor as TensorImpl } from './tensor-impl.js';\nimport { TypedTensorUtils } from './tensor-utils.js';\nimport { TryGetGlobalType } from './type-helper.js';\n\n/* eslint-disable @typescript-eslint/no-redeclare */\n\n/**\n * represent a basic tensor with specified dimensions and data type.\n */\ninterface TypedTensorBase<T extends Tensor.Type> {\n  /**\n   * Get the dimensions of the tensor.\n   */\n  readonly dims: readonly number[];\n  /**\n   * Get the data type of the tensor.\n   */\n  readonly type: T;\n  /**\n   * Get the buffer data of the tensor.\n   *\n   * If the data is not on CPU (eg. it's in the form of WebGL texture or WebGPU buffer), throw error.\n   */\n  readonly data: Tensor.DataTypeMap[T];\n  /**\n   * Get the location of the data.\n   */\n  readonly location: Tensor.DataLocation;\n  /**\n   * Get the WebGL texture that holds the tensor data.\n   *\n   * If the data is not on GPU as WebGL texture, throw error.\n   */\n  readonly texture: Tensor.TextureType;\n  /**\n   * Get the WebGPU buffer that holds the tensor data.\n   *\n   * If the data is not on GPU as WebGPU buffer, throw error.\n   */\n  readonly gpuBuffer: Tensor.GpuBufferType;\n\n  /**\n   * Get the WebNN MLTensor that holds the tensor data.\n   *\n   * If the data is not in a WebNN MLTensor, throw error.\n   */\n  readonly mlTensor: Tensor.MLTensorType;\n\n  /**\n   * Get the buffer data of the tensor.\n   *\n   * If the data is on CPU, returns the data immediately.\n   * If the data is on GPU, downloads the data and returns the promise.\n   *\n   * @param releaseData - whether release the data on GPU. Ignore if data is already on CPU.\n   */\n  getData(releaseData?: boolean): Promise<Tensor.DataTypeMap[T]>;\n\n  /**\n   * Dispose the tensor data.\n   *\n   * If the data is on CPU, remove its internal reference to the underlying data.\n   * If the data is on GPU, release the data on GPU.\n   *\n   * After calling this function, the tensor is considered no longer valid. Its location will be set to 'none'.\n   */\n  dispose(): void;\n}\n\nexport declare namespace Tensor {\n  interface DataTypeMap {\n    float32: Float32Array;\n    uint8: Uint8Array;\n    int8: Int8Array;\n    uint16: Uint16Array;\n    int16: Int16Array;\n    int32: Int32Array;\n    int64: BigInt64Array;\n    string: string[];\n    bool: Uint8Array;\n    float16: Uint16Array; // Keep using Uint16Array until we have a concrete solution for float 16.\n    float64: Float64Array;\n    uint32: Uint32Array;\n    uint64: BigUint64Array;\n    // complex64: never;\n    // complex128: never;\n    // bfloat16: never;\n    uint4: Uint8Array;\n    int4: Int8Array;\n  }\n\n  interface ElementTypeMap {\n    float32: number;\n    uint8: number;\n    int8: number;\n    uint16: number;\n    int16: number;\n    int32: number;\n    int64: bigint;\n    string: string;\n    bool: boolean;\n    float16: number; // Keep using Uint16Array until we have a concrete solution for float 16.\n    float64: number;\n    uint32: number;\n    uint64: bigint;\n    // complex64: never;\n    // complex128: never;\n    // bfloat16: never;\n    uint4: number;\n    int4: number;\n  }\n\n  type DataType = DataTypeMap[Type];\n  type ElementType = ElementTypeMap[Type];\n\n  /**\n   * supported data types for constructing a tensor from a pinned CPU buffer\n   */\n  export type CpuPinnedDataTypes = Exclude<Tensor.Type, 'string'>;\n\n  /**\n   * type alias for WebGL texture\n   */\n  export type TextureType = WebGLTexture;\n\n  /**\n   * supported data types for constructing a tensor from a WebGL texture\n   */\n  export type TextureDataTypes = 'float32';\n\n  type GpuBufferTypeFallback = { size: number; mapState: 'unmapped' | 'pending' | 'mapped' };\n  /**\n   * type alias for WebGPU buffer\n   */\n  export type GpuBufferType = TryGetGlobalType<'GPUBuffer', GpuBufferTypeFallback>;\n\n  type MLTensorTypeFallback = { destroy(): void };\n  /**\n   * type alias for WebNN MLTensor\n   *\n   * The specification for WebNN's MLTensor is currently in flux.\n   */\n  export type MLTensorType = TryGetGlobalType<'MLTensor', MLTensorTypeFallback>;\n\n  /**\n   * supported data types for constructing a tensor from a WebGPU buffer\n   */\n  export type GpuBufferDataTypes = 'float32' | 'float16' | 'int32' | 'int64' | 'uint32' | 'uint8' | 'bool';\n\n  /**\n   * supported data types for constructing a tensor from a WebNN MLTensor\n   */\n  export type MLTensorDataTypes =\n    | 'float32'\n    | 'float16'\n    | 'int8'\n    | 'uint8'\n    | 'int32'\n    | 'uint32'\n    | 'int64'\n    | 'uint64'\n    | 'bool'\n    | 'uint4'\n    | 'int4';\n\n  /**\n   * represent where the tensor data is stored\n   */\n  export type DataLocation = 'none' | 'cpu' | 'cpu-pinned' | 'texture' | 'gpu-buffer' | 'ml-tensor';\n\n  /**\n   * represent the data type of a tensor\n   */\n  export type Type = keyof DataTypeMap;\n}\n\n/**\n * Represent multi-dimensional arrays to feed to or fetch from model inferencing.\n */\nexport interface TypedTensor<T extends Tensor.Type> extends TypedTensorBase<T>, TypedTensorUtils<T> {}\n/**\n * Represent multi-dimensional arrays to feed to or fetch from model inferencing.\n */\nexport interface Tensor extends TypedTensorBase<Tensor.Type>, TypedTensorUtils<Tensor.Type> {}\n\n/**\n * type TensorConstructor defines the constructors of 'Tensor' to create CPU tensor instances.\n */\nexport interface TensorConstructor extends TensorFactory {\n  // #region CPU tensor - specify element type\n  /**\n   * Construct a new string tensor object from the given type, data and dims.\n   *\n   * @param type - Specify the element type.\n   * @param data - Specify the CPU tensor data.\n   * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n   */\n  new (\n    type: 'string',\n    data: Tensor.DataTypeMap['string'] | readonly string[],\n    dims?: readonly number[],\n  ): TypedTensor<'string'>;\n\n  /**\n   * Construct a new bool tensor object from the given type, data and dims.\n   *\n   * @param type - Specify the element type.\n   * @param data - Specify the CPU tensor data.\n   * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n   */\n  new (\n    type: 'bool',\n    data: Tensor.DataTypeMap['bool'] | readonly boolean[],\n    dims?: readonly number[],\n  ): TypedTensor<'bool'>;\n\n  /**\n   * Construct a new uint8 tensor object from a Uint8ClampedArray, data and dims.\n   *\n   * @param type - Specify the element type.\n   * @param data - Specify the CPU tensor data.\n   * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n   */\n  new (type: 'uint8', data: Uint8ClampedArray, dims?: readonly number[]): TypedTensor<'uint8'>;\n\n  /**\n   * Construct a new 64-bit integer typed tensor object from the given type, data and dims.\n   *\n   * @param type - Specify the element type.\n   * @param data - Specify the CPU tensor data.\n   * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n   */\n  new <T extends 'uint64' | 'int64'>(\n    type: T,\n    data: Tensor.DataTypeMap[T] | readonly bigint[] | readonly number[],\n    dims?: readonly number[],\n  ): TypedTensor<T>;\n\n  /**\n   * Construct a new numeric tensor object from the given type, data and dims.\n   *\n   * @param type - Specify the element type.\n   * @param data - Specify the CPU tensor data.\n   * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n   */\n  new <T extends Exclude<Tensor.Type, 'string' | 'bool' | 'uint64' | 'int64'>>(\n    type: T,\n    data: Tensor.DataTypeMap[T] | readonly number[],\n    dims?: readonly number[],\n  ): TypedTensor<T>;\n  // #endregion\n\n  // #region CPU tensor - infer element types\n\n  /**\n   * Construct a new float32 tensor object from the given data and dims.\n   *\n   * @param data - Specify the CPU tensor data.\n   * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n   */\n  new (data: Float32Array, dims?: readonly number[]): TypedTensor<'float32'>;\n\n  /**\n   * Construct a new int8 tensor object from the given data and dims.\n   *\n   * @param data - Specify the CPU tensor data.\n   * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n   */\n  new (data: Int8Array, dims?: readonly number[]): TypedTensor<'int8'>;\n\n  /**\n   * Construct a new uint8 tensor object from the given data and dims.\n   *\n   * @param data - Specify the CPU tensor data.\n   * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n   */\n  new (data: Uint8Array, dims?: readonly number[]): TypedTensor<'uint8'>;\n\n  /**\n   * Construct a new uint8 tensor object from the given data and dims.\n   *\n   * @param data - Specify the CPU tensor data.\n   * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n   */\n  new (data: Uint8ClampedArray, dims?: readonly number[]): TypedTensor<'uint8'>;\n\n  /**\n   * Construct a new uint16 tensor object from the given data and dims.\n   *\n   * @param data - Specify the CPU tensor data.\n   * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n   */\n  new (data: Uint16Array, dims?: readonly number[]): TypedTensor<'uint16'>;\n\n  /**\n   * Construct a new int16 tensor object from the given data and dims.\n   *\n   * @param data - Specify the CPU tensor data.\n   * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n   */\n  new (data: Int16Array, dims?: readonly number[]): TypedTensor<'int16'>;\n\n  /**\n   * Construct a new int32 tensor object from the given data and dims.\n   *\n   * @param data - Specify the CPU tensor data.\n   * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n   */\n  new (data: Int32Array, dims?: readonly number[]): TypedTensor<'int32'>;\n\n  /**\n   * Construct a new int64 tensor object from the given data and dims.\n   *\n   * @param data - Specify the CPU tensor data.\n   * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n   */\n  new (data: BigInt64Array, dims?: readonly number[]): TypedTensor<'int64'>;\n\n  /**\n   * Construct a new string tensor object from the given data and dims.\n   *\n   * @param data - Specify the CPU tensor data.\n   * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n   */\n  new (data: readonly string[], dims?: readonly number[]): TypedTensor<'string'>;\n\n  /**\n   * Construct a new bool tensor object from the given data and dims.\n   *\n   * @param data - Specify the CPU tensor data.\n   * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n   */\n  new (data: readonly boolean[], dims?: readonly number[]): TypedTensor<'bool'>;\n\n  /**\n   * Construct a new float64 tensor object from the given data and dims.\n   *\n   * @param data - Specify the CPU tensor data.\n   * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n   */\n  new (data: Float64Array, dims?: readonly number[]): TypedTensor<'float64'>;\n\n  /**\n   * Construct a new uint32 tensor object from the given data and dims.\n   *\n   * @param data - Specify the CPU tensor data.\n   * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n   */\n  new (data: Uint32Array, dims?: readonly number[]): TypedTensor<'uint32'>;\n\n  /**\n   * Construct a new uint64 tensor object from the given data and dims.\n   *\n   * @param data - Specify the CPU tensor data.\n   * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n   */\n  new (data: BigUint64Array, dims?: readonly number[]): TypedTensor<'uint64'>;\n\n  // #endregion\n\n  // #region CPU tensor - fall back to non-generic tensor type declaration\n\n  /**\n   * Construct a new tensor object from the given type, data and dims.\n   *\n   * @param type - Specify the element type.\n   * @param data - Specify the CPU tensor data.\n   * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n   */\n  new (\n    type: Tensor.Type,\n    data: Tensor.DataType | readonly number[] | readonly string[] | readonly bigint[] | readonly boolean[],\n    dims?: readonly number[],\n  ): Tensor;\n\n  /**\n   * Construct a new tensor object from the given data and dims.\n   *\n   * @param data - Specify the CPU tensor data.\n   * @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n   */\n  new (data: Tensor.DataType, dims?: readonly number[]): Tensor;\n  // #endregion\n}\n\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport const Tensor = TensorImpl as TensorConstructor;\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { env } from './env-impl.js';\n\n/**\n * @ignore\n */\nexport const TRACE = (deviceType: string, label: string) => {\n  if (typeof env.trace === 'undefined' ? !env.wasm.trace : !env.trace) {\n    return;\n  }\n  // eslint-disable-next-line no-console\n  console.timeStamp(`${deviceType}::ORT::${label}`);\n};\n\nconst TRACE_FUNC = (msg: string, extraMsg?: string) => {\n  const stack = new Error().stack?.split(/\\r\\n|\\r|\\n/g) || [];\n  let hasTraceFunc = false;\n  for (let i = 0; i < stack.length; i++) {\n    if (hasTraceFunc && !stack[i].includes('TRACE_FUNC')) {\n      let label = `FUNC_${msg}::${stack[i].trim().split(' ')[1]}`;\n      if (extraMsg) {\n        label += `::${extraMsg}`;\n      }\n      TRACE('CPU', label);\n      return;\n    }\n    if (stack[i].includes('TRACE_FUNC')) {\n      hasTraceFunc = true;\n    }\n  }\n};\n\n/**\n * @ignore\n */\nexport const TRACE_FUNC_BEGIN = (extraMsg?: string) => {\n  if (typeof env.trace === 'undefined' ? !env.wasm.trace : !env.trace) {\n    return;\n  }\n  TRACE_FUNC('BEGIN', extraMsg);\n};\n\n/**\n * @ignore\n */\nexport const TRACE_FUNC_END = (extraMsg?: string) => {\n  if (typeof env.trace === 'undefined' ? !env.wasm.trace : !env.trace) {\n    return;\n  }\n  TRACE_FUNC('END', extraMsg);\n};\n\n/**\n * @ignore\n */\nexport const TRACE_EVENT_BEGIN = (extraMsg?: string) => {\n  if (typeof env.trace === 'undefined' ? !env.wasm.trace : !env.trace) {\n    return;\n  }\n  // eslint-disable-next-line no-console\n  console.time(`ORT::${extraMsg}`);\n};\n\n/**\n * @ignore\n */\nexport const TRACE_EVENT_END = (extraMsg?: string) => {\n  if (typeof env.trace === 'undefined' ? !env.wasm.trace : !env.trace) {\n    return;\n  }\n  // eslint-disable-next-line no-console\n  console.timeEnd(`ORT::${extraMsg}`);\n};\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { resolveBackendAndExecutionProviders } from './backend-impl.js';\nimport { InferenceSessionHandler } from './backend.js';\nimport { InferenceSession as InferenceSessionInterface } from './inference-session.js';\nimport { OnnxValue } from './onnx-value.js';\nimport { Tensor } from './tensor.js';\nimport { TRACE_FUNC_BEGIN, TRACE_FUNC_END, TRACE_EVENT_BEGIN, TRACE_EVENT_END } from './trace.js';\n\ntype SessionOptions = InferenceSessionInterface.SessionOptions;\ntype RunOptions = InferenceSessionInterface.RunOptions;\ntype FeedsType = InferenceSessionInterface.FeedsType;\ntype FetchesType = InferenceSessionInterface.FetchesType;\ntype ReturnType = InferenceSessionInterface.ReturnType;\n\nexport class InferenceSession implements InferenceSessionInterface {\n  private constructor(handler: InferenceSessionHandler) {\n    this.handler = handler;\n  }\n  run(feeds: FeedsType, options?: RunOptions): Promise<ReturnType>;\n  run(feeds: FeedsType, fetches: FetchesType, options?: RunOptions): Promise<ReturnType>;\n  async run(feeds: FeedsType, arg1?: FetchesType | RunOptions, arg2?: RunOptions): Promise<ReturnType> {\n    TRACE_FUNC_BEGIN();\n    TRACE_EVENT_BEGIN('InferenceSession.run');\n    const fetches: { [name: string]: OnnxValue | null } = {};\n    let options: RunOptions = {};\n    // check inputs\n    if (typeof feeds !== 'object' || feeds === null || feeds instanceof Tensor || Array.isArray(feeds)) {\n      throw new TypeError(\n        \"'feeds' must be an object that use input names as keys and OnnxValue as corresponding values.\",\n      );\n    }\n\n    let isFetchesEmpty = true;\n    // determine which override is being used\n    if (typeof arg1 === 'object') {\n      if (arg1 === null) {\n        throw new TypeError('Unexpected argument[1]: cannot be null.');\n      }\n      if (arg1 instanceof Tensor) {\n        throw new TypeError(\"'fetches' cannot be a Tensor\");\n      }\n\n      if (Array.isArray(arg1)) {\n        if (arg1.length === 0) {\n          throw new TypeError(\"'fetches' cannot be an empty array.\");\n        }\n        isFetchesEmpty = false;\n        // output names\n        for (const name of arg1) {\n          if (typeof name !== 'string') {\n            throw new TypeError(\"'fetches' must be a string array or an object.\");\n          }\n          if (this.outputNames.indexOf(name) === -1) {\n            throw new RangeError(`'fetches' contains invalid output name: ${name}.`);\n          }\n          fetches[name] = null;\n        }\n\n        if (typeof arg2 === 'object' && arg2 !== null) {\n          options = arg2;\n        } else if (typeof arg2 !== 'undefined') {\n          throw new TypeError(\"'options' must be an object.\");\n        }\n      } else {\n        // decide whether arg1 is fetches or options\n        // if any output name is present and its value is valid OnnxValue, we consider it fetches\n        let isFetches = false;\n        const arg1Keys = Object.getOwnPropertyNames(arg1);\n        for (const name of this.outputNames) {\n          if (arg1Keys.indexOf(name) !== -1) {\n            const v = (arg1 as InferenceSessionInterface.NullableOnnxValueMapType)[name];\n            if (v === null || v instanceof Tensor) {\n              isFetches = true;\n              isFetchesEmpty = false;\n              fetches[name] = v;\n            }\n          }\n        }\n\n        if (isFetches) {\n          if (typeof arg2 === 'object' && arg2 !== null) {\n            options = arg2;\n          } else if (typeof arg2 !== 'undefined') {\n            throw new TypeError(\"'options' must be an object.\");\n          }\n        } else {\n          options = arg1 as RunOptions;\n        }\n      }\n    } else if (typeof arg1 !== 'undefined') {\n      throw new TypeError(\"Unexpected argument[1]: must be 'fetches' or 'options'.\");\n    }\n\n    // check if all inputs are in feed\n    for (const name of this.inputNames) {\n      if (typeof feeds[name] === 'undefined') {\n        throw new Error(`input '${name}' is missing in 'feeds'.`);\n      }\n    }\n\n    // if no fetches is specified, we use the full output names list\n    if (isFetchesEmpty) {\n      for (const name of this.outputNames) {\n        fetches[name] = null;\n      }\n    }\n\n    // feeds, fetches and options are prepared\n\n    const results = await this.handler.run(feeds, fetches, options);\n    const returnValue: { [name: string]: OnnxValue } = {};\n    for (const key in results) {\n      if (Object.hasOwnProperty.call(results, key)) {\n        const result = results[key];\n        if (result instanceof Tensor) {\n          returnValue[key] = result;\n        } else {\n          returnValue[key] = new Tensor(result.type, result.data, result.dims);\n        }\n      }\n    }\n    TRACE_EVENT_END('InferenceSession.run');\n    TRACE_FUNC_END();\n    return returnValue;\n  }\n\n  async release(): Promise<void> {\n    return this.handler.dispose();\n  }\n\n  static create(path: string, options?: SessionOptions): Promise<InferenceSessionInterface>;\n  static create(buffer: ArrayBufferLike, options?: SessionOptions): Promise<InferenceSessionInterface>;\n  static create(\n    buffer: ArrayBufferLike,\n    byteOffset: number,\n    byteLength?: number,\n    options?: SessionOptions,\n  ): Promise<InferenceSessionInterface>;\n  static create(buffer: Uint8Array, options?: SessionOptions): Promise<InferenceSessionInterface>;\n  static async create(\n    arg0: string | ArrayBufferLike | Uint8Array,\n    arg1?: SessionOptions | number,\n    arg2?: number,\n    arg3?: SessionOptions,\n  ): Promise<InferenceSessionInterface> {\n    TRACE_FUNC_BEGIN();\n    TRACE_EVENT_BEGIN('InferenceSession.create');\n    // either load from a file or buffer\n    let filePathOrUint8Array: string | Uint8Array;\n    let options: SessionOptions = {};\n\n    if (typeof arg0 === 'string') {\n      filePathOrUint8Array = arg0;\n      if (typeof arg1 === 'object' && arg1 !== null) {\n        options = arg1;\n      } else if (typeof arg1 !== 'undefined') {\n        throw new TypeError(\"'options' must be an object.\");\n      }\n    } else if (arg0 instanceof Uint8Array) {\n      filePathOrUint8Array = arg0;\n      if (typeof arg1 === 'object' && arg1 !== null) {\n        options = arg1;\n      } else if (typeof arg1 !== 'undefined') {\n        throw new TypeError(\"'options' must be an object.\");\n      }\n    } else if (\n      arg0 instanceof ArrayBuffer ||\n      (typeof SharedArrayBuffer !== 'undefined' && arg0 instanceof SharedArrayBuffer)\n    ) {\n      const buffer = arg0;\n      let byteOffset = 0;\n      let byteLength = arg0.byteLength;\n      if (typeof arg1 === 'object' && arg1 !== null) {\n        options = arg1;\n      } else if (typeof arg1 === 'number') {\n        byteOffset = arg1;\n        if (!Number.isSafeInteger(byteOffset)) {\n          throw new RangeError(\"'byteOffset' must be an integer.\");\n        }\n        if (byteOffset < 0 || byteOffset >= buffer.byteLength) {\n          throw new RangeError(`'byteOffset' is out of range [0, ${buffer.byteLength}).`);\n        }\n        byteLength = arg0.byteLength - byteOffset;\n        if (typeof arg2 === 'number') {\n          byteLength = arg2;\n          if (!Number.isSafeInteger(byteLength)) {\n            throw new RangeError(\"'byteLength' must be an integer.\");\n          }\n          if (byteLength <= 0 || byteOffset + byteLength > buffer.byteLength) {\n            throw new RangeError(`'byteLength' is out of range (0, ${buffer.byteLength - byteOffset}].`);\n          }\n          if (typeof arg3 === 'object' && arg3 !== null) {\n            options = arg3;\n          } else if (typeof arg3 !== 'undefined') {\n            throw new TypeError(\"'options' must be an object.\");\n          }\n        } else if (typeof arg2 !== 'undefined') {\n          throw new TypeError(\"'byteLength' must be a number.\");\n        }\n      } else if (typeof arg1 !== 'undefined') {\n        throw new TypeError(\"'options' must be an object.\");\n      }\n      filePathOrUint8Array = new Uint8Array(buffer, byteOffset, byteLength);\n    } else {\n      throw new TypeError(\"Unexpected argument[0]: must be 'path' or 'buffer'.\");\n    }\n\n    // resolve backend, update session options with validated EPs, and create session handler\n    const [backend, optionsWithValidatedEPs] = await resolveBackendAndExecutionProviders(options);\n    const handler = await backend.createInferenceSessionHandler(filePathOrUint8Array, optionsWithValidatedEPs);\n    TRACE_EVENT_END('InferenceSession.create');\n    TRACE_FUNC_END();\n    return new InferenceSession(handler);\n  }\n\n  startProfiling(): void {\n    this.handler.startProfiling();\n  }\n  endProfiling(): void {\n    this.handler.endProfiling();\n  }\n\n  get inputNames(): readonly string[] {\n    return this.handler.inputNames;\n  }\n  get outputNames(): readonly string[] {\n    return this.handler.outputNames;\n  }\n\n  get inputMetadata(): readonly InferenceSessionInterface.ValueMetadata[] {\n    return this.handler.inputMetadata;\n  }\n\n  get outputMetadata(): readonly InferenceSessionInterface.ValueMetadata[] {\n    return this.handler.outputMetadata;\n  }\n\n  private handler: InferenceSessionHandler;\n}\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { InferenceSession as InferenceSessionImpl } from './inference-session-impl.js';\nimport { OnnxModelOptions } from './onnx-model.js';\nimport { OnnxValue, OnnxValueDataLocation } from './onnx-value.js';\nimport type { Tensor } from './tensor.js';\nimport { TryGetGlobalType } from './type-helper.js';\n\n/* eslint-disable @typescript-eslint/no-redeclare */\n\nexport declare namespace InferenceSession {\n  // #region input/output types\n\n  type OnnxValueMapType = { readonly [name: string]: OnnxValue };\n  type NullableOnnxValueMapType = { readonly [name: string]: OnnxValue | null };\n\n  /**\n   * A feeds (model inputs) is an object that uses input names as keys and OnnxValue as corresponding values.\n   */\n  type FeedsType = OnnxValueMapType;\n\n  /**\n   * A fetches (model outputs) could be one of the following:\n   *\n   * - Omitted. Use model's output names definition.\n   * - An array of string indicating the output names.\n   * - An object that use output names as keys and OnnxValue or null as corresponding values.\n   *\n   * @remarks\n   * different from input argument, in output, OnnxValue is optional. If an OnnxValue is present it will be\n   * used as a pre-allocated value by the inference engine; if omitted, inference engine will allocate buffer\n   * internally.\n   */\n  type FetchesType = readonly string[] | NullableOnnxValueMapType;\n\n  /**\n   * A inferencing return type is an object that uses output names as keys and OnnxValue as corresponding values.\n   */\n  type ReturnType = OnnxValueMapType;\n\n  // #endregion\n\n  // #region session options\n\n  /**\n   * A set of configurations for session behavior.\n   */\n  export interface SessionOptions extends OnnxModelOptions {\n    /**\n     * An array of execution provider options.\n     *\n     * An execution provider option can be a string indicating the name of the execution provider,\n     * or an object of corresponding type.\n     */\n    executionProviders?: readonly ExecutionProviderConfig[];\n\n    /**\n     * The intra OP threads number.\n     *\n     * This setting is available only in ONNXRuntime (Node.js binding and react-native).\n     */\n    intraOpNumThreads?: number;\n\n    /**\n     * The inter OP threads number.\n     *\n     * This setting is available only in ONNXRuntime (Node.js binding and react-native).\n     */\n    interOpNumThreads?: number;\n\n    /**\n     * The free dimension override.\n     *\n     * This setting is available only in ONNXRuntime (Node.js binding and react-native) or WebAssembly backend\n     */\n    freeDimensionOverrides?: { readonly [dimensionName: string]: number };\n\n    /**\n     * The optimization level.\n     *\n     * This setting is available only in ONNXRuntime (Node.js binding and react-native) or WebAssembly backend\n     */\n    graphOptimizationLevel?: 'disabled' | 'basic' | 'extended' | 'layout' | 'all';\n\n    /**\n     * Whether enable CPU memory arena.\n     *\n     * This setting is available only in ONNXRuntime (Node.js binding and react-native) or WebAssembly backend\n     */\n    enableCpuMemArena?: boolean;\n\n    /**\n     * Whether enable memory pattern.\n     *\n     * This setting is available only in ONNXRuntime (Node.js binding and react-native) or WebAssembly backend\n     */\n    enableMemPattern?: boolean;\n\n    /**\n     * Execution mode.\n     *\n     * This setting is available only in ONNXRuntime (Node.js binding and react-native) or WebAssembly backend\n     */\n    executionMode?: 'sequential' | 'parallel';\n\n    /**\n     * Optimized model file path.\n     *\n     * If this setting is specified, the optimized model will be dumped. In browser, a blob will be created\n     * with a pop-up window.\n     */\n    optimizedModelFilePath?: string;\n\n    /**\n     * Whether enable profiling.\n     *\n     * This setting is a placeholder for a future use.\n     */\n    enableProfiling?: boolean;\n\n    /**\n     * File prefix for profiling.\n     *\n     * This setting is a placeholder for a future use.\n     */\n    profileFilePrefix?: string;\n\n    /**\n     * Log ID.\n     *\n     * This setting is available only in ONNXRuntime (Node.js binding and react-native) or WebAssembly backend\n     */\n    logId?: string;\n\n    /**\n     * Log severity level. See\n     * https://github.com/microsoft/onnxruntime/blob/main/include/onnxruntime/core/common/logging/severity.h\n     *\n     * This setting is available only in ONNXRuntime (Node.js binding and react-native) or WebAssembly backend\n     */\n    logSeverityLevel?: 0 | 1 | 2 | 3 | 4;\n\n    /**\n     * Log verbosity level.\n     *\n     * This setting is available only in WebAssembly backend. Will support Node.js binding and react-native later\n     */\n    logVerbosityLevel?: number;\n\n    /**\n     * Specify string as a preferred data location for all outputs, or an object that use output names as keys and a\n     * preferred data location as corresponding values.\n     *\n     * This setting is available only in ONNXRuntime Web for WebGL and WebGPU EP.\n     */\n    preferredOutputLocation?: OnnxValueDataLocation | { readonly [outputName: string]: OnnxValueDataLocation };\n\n    /**\n     * Whether enable graph capture.\n     * This setting is available only in ONNXRuntime Web for WebGPU EP.\n     */\n    enableGraphCapture?: boolean;\n\n    /**\n     * Store configurations for a session. See\n     * https://github.com/microsoft/onnxruntime/blob/main/include/onnxruntime/core/session/\n     * onnxruntime_session_options_config_keys.h\n     *\n     * This setting is available only in WebAssembly backend. Will support Node.js binding and react-native later\n     *\n     * @example\n     * ```js\n     * extra: {\n     *   session: {\n     *     set_denormal_as_zero: \"1\",\n     *     disable_prepacking: \"1\"\n     *   },\n     *   optimization: {\n     *     enable_gelu_approximation: \"1\"\n     *   }\n     * }\n     * ```\n     */\n    extra?: Record<string, unknown>;\n  }\n\n  // #region execution providers\n\n  // Currently, we have the following backends to support execution providers:\n  // Backend Node.js binding: supports 'cpu', 'dml' (win32), 'coreml' (macOS) and 'cuda' (linux).\n  // Backend WebAssembly: supports 'cpu', 'wasm', 'webgpu' and 'webnn'.\n  // Backend ONNX.js: supports 'webgl'.\n  // Backend React Native: supports 'cpu', 'xnnpack', 'coreml' (iOS), 'nnapi' (Android).\n  interface ExecutionProviderOptionMap {\n    coreml: CoreMLExecutionProviderOption;\n    cpu: CpuExecutionProviderOption;\n    cuda: CudaExecutionProviderOption;\n    dml: DmlExecutionProviderOption;\n    nnapi: NnapiExecutionProviderOption;\n    tensorrt: TensorRtExecutionProviderOption;\n    wasm: WebAssemblyExecutionProviderOption;\n    webgl: WebGLExecutionProviderOption;\n    webgpu: WebGpuExecutionProviderOption;\n    webnn: WebNNExecutionProviderOption;\n    qnn: QnnExecutionProviderOption;\n    xnnpack: XnnpackExecutionProviderOption;\n  }\n\n  type ExecutionProviderName = keyof ExecutionProviderOptionMap;\n  type ExecutionProviderConfig =\n    | ExecutionProviderOptionMap[ExecutionProviderName]\n    | ExecutionProviderOption\n    | ExecutionProviderName\n    | string;\n\n  export interface ExecutionProviderOption {\n    readonly name: string;\n  }\n  export interface CpuExecutionProviderOption extends ExecutionProviderOption {\n    readonly name: 'cpu';\n    useArena?: boolean;\n  }\n  export interface CudaExecutionProviderOption extends ExecutionProviderOption {\n    readonly name: 'cuda';\n    deviceId?: number;\n  }\n  export interface DmlExecutionProviderOption extends ExecutionProviderOption {\n    readonly name: 'dml';\n    deviceId?: number;\n  }\n  export interface TensorRtExecutionProviderOption extends ExecutionProviderOption {\n    readonly name: 'tensorrt';\n    deviceId?: number;\n  }\n  export interface WebAssemblyExecutionProviderOption extends ExecutionProviderOption {\n    readonly name: 'wasm';\n  }\n  export interface WebGLExecutionProviderOption extends ExecutionProviderOption {\n    readonly name: 'webgl';\n    // TODO: add flags\n  }\n  export interface XnnpackExecutionProviderOption extends ExecutionProviderOption {\n    readonly name: 'xnnpack';\n  }\n  export interface WebGpuExecutionProviderOption extends ExecutionProviderOption {\n    readonly name: 'webgpu';\n\n    /**\n     * Specify the preferred layout when running layout sensitive operators.\n     *\n     * @default 'NCHW'\n     */\n    preferredLayout?: 'NCHW' | 'NHWC';\n\n    /**\n     * Specify a list of node names that should be executed on CPU even when WebGPU EP is used.\n     */\n    forceCpuNodeNames?: readonly string[];\n\n    /**\n     * Specify the validation mode for WebGPU execution provider.\n     * - 'disabled': Disable all validation.\n     * When used in Node.js, disable validation may cause process crash if WebGPU errors occur. Be cautious when using\n     * this mode.\n     * When used in web, this mode is equivalent to 'wgpuOnly'.\n     * - 'wgpuOnly': Perform WebGPU internal validation only.\n     * - 'basic': Perform basic validation including WebGPU internal validation. This is the default mode.\n     * - 'full': Perform full validation. This mode may have performance impact. Use it for debugging purpose.\n     *\n     * @default 'basic'\n     */\n    validationMode?: 'disabled' | 'wgpuOnly' | 'basic' | 'full';\n\n    /**\n     * Specify the cache mode for storage buffers.\n     * - 'disabled': Disable buffer cache. Buffers are destroyed when no longer in use.\n     * - 'lazyRelease': Buffers are released lazily, at the end of the current run.\n     * - 'simple': Released buffers are cached and reused only for requests of the exact same size.\n     * - 'bucket': Released buffers are cached and reused using predefined size buckets. This is the default mode.\n     *\n     * For static-shape models, 'simple' may reduce GPU memory usage, because exact-size buffers are reused across\n     * runs instead of allocating new bucket-sized buffers.\n     *\n     * @default 'bucket'\n     */\n    storageBufferCacheMode?: 'disabled' | 'lazyRelease' | 'simple' | 'bucket';\n\n    /**\n     * Specify the cache mode for uniform buffers.\n     *\n     * See {@link storageBufferCacheMode} for a description of the available modes.\n     *\n     * @default 'simple'\n     */\n    uniformBufferCacheMode?: 'disabled' | 'lazyRelease' | 'simple' | 'bucket';\n\n    /**\n     * Specify the cache mode for query resolve buffers.\n     *\n     * See {@link storageBufferCacheMode} for a description of the available modes.\n     *\n     * @default 'disabled'\n     */\n    queryResolveBufferCacheMode?: 'disabled' | 'lazyRelease' | 'simple' | 'bucket';\n\n    /**\n     * Specify the cache mode for buffers not covered by the other buffer cache mode options.\n     *\n     * See {@link storageBufferCacheMode} for a description of the available modes.\n     *\n     * @default 'disabled'\n     */\n    defaultBufferCacheMode?: 'disabled' | 'lazyRelease' | 'simple' | 'bucket';\n\n    /**\n     * Specify an optional WebGPU device to be used by the WebGPU execution provider.\n     */\n    device?: TryGetGlobalType<'GPUDevice'>;\n  }\n\n  // #region WebNN options\n\n  interface WebNNExecutionProviderName extends ExecutionProviderOption {\n    readonly name: 'webnn';\n  }\n\n  /**\n   * Represents a set of options for creating a WebNN MLContext.\n   *\n   * @see https://www.w3.org/TR/webnn/#dictdef-mlcontextoptions\n   */\n  export interface WebNNContextOptions {\n    deviceType?: 'cpu' | 'gpu' | 'npu';\n    numThreads?: number;\n    powerPreference?: 'default' | 'low-power' | 'high-performance';\n  }\n\n  /**\n   * Represents a set of options for WebNN execution provider without MLContext.\n   */\n  export interface WebNNOptionsWithoutMLContext extends WebNNExecutionProviderName, WebNNContextOptions {\n    context?: never;\n  }\n\n  /**\n   * Represents a set of options for WebNN execution provider with MLContext.\n   *\n   * When MLContext is provided, the deviceType is also required so that the WebNN EP can determine the preferred\n   * channel layout.\n   *\n   * @see https://www.w3.org/TR/webnn/#dom-ml-createcontext\n   */\n  export interface WebNNOptionsWithMLContext\n    extends\n      WebNNExecutionProviderName,\n      Omit<WebNNContextOptions, 'deviceType'>,\n      Required<Pick<WebNNContextOptions, 'deviceType'>> {\n    context: TryGetGlobalType<'MLContext'>;\n  }\n\n  /**\n   * Represents a set of options for WebNN execution provider with MLContext which is created from GPUDevice.\n   *\n   * @see https://www.w3.org/TR/webnn/#dom-ml-createcontext-gpudevice\n   */\n  export interface WebNNOptionsWebGpu extends WebNNExecutionProviderName {\n    context: TryGetGlobalType<'MLContext'>;\n    gpuDevice: TryGetGlobalType<'GPUDevice'>;\n  }\n\n  /**\n   * Options for WebNN execution provider.\n   */\n  export type WebNNExecutionProviderOption =\n    | WebNNOptionsWithoutMLContext\n    | WebNNOptionsWithMLContext\n    | WebNNOptionsWebGpu;\n\n  // #endregion\n\n  export interface QnnExecutionProviderOption extends ExecutionProviderOption {\n    readonly name: 'qnn';\n    /**\n     * Specify the QNN backend type. E.g., 'cpu' or 'htp'.\n     * Mutually exclusive with `backendPath`.\n     *\n     * @default 'htp'\n     */\n    backendType?: string;\n    /**\n     * Specify a path to the QNN backend library.\n     * Mutually exclusive with `backendType`.\n     */\n    backendPath?: string;\n    /**\n     * Specify whether to enable HTP FP16 precision.\n     *\n     * @default true\n     */\n    enableFp16Precision?: boolean;\n  }\n  export interface CoreMLExecutionProviderOption extends ExecutionProviderOption {\n    readonly name: 'coreml';\n    /**\n     * The bit flags for CoreML execution provider.\n     *\n     * ```\n     * COREML_FLAG_USE_CPU_ONLY = 0x001\n     * COREML_FLAG_ENABLE_ON_SUBGRAPH = 0x002\n     * COREML_FLAG_ONLY_ENABLE_DEVICE_WITH_ANE = 0x004\n     * COREML_FLAG_ONLY_ALLOW_STATIC_INPUT_SHAPES = 0x008\n     * COREML_FLAG_CREATE_MLPROGRAM = 0x010\n     * COREML_FLAG_USE_CPU_AND_GPU = 0x020\n     * ```\n     *\n     * See include/onnxruntime/core/providers/coreml/coreml_provider_factory.h for more details.\n     *\n     * This flag is available only in ONNXRuntime (Node.js binding).\n     */\n    coreMlFlags?: number;\n    /**\n     * Specify whether to use CPU only in CoreML EP.\n     *\n     * This setting is available only in ONNXRuntime (react-native).\n     */\n    useCPUOnly?: boolean;\n    useCPUAndGPU?: boolean;\n    /**\n     * Specify whether to enable CoreML EP on subgraph.\n     *\n     * This setting is available only in ONNXRuntime (react-native).\n     */\n    enableOnSubgraph?: boolean;\n    /**\n     * Specify whether to only enable CoreML EP for Apple devices with ANE (Apple Neural Engine).\n     *\n     * This setting is available only in ONNXRuntime (react-native).\n     */\n    onlyEnableDeviceWithANE?: boolean;\n  }\n  export interface NnapiExecutionProviderOption extends ExecutionProviderOption {\n    readonly name: 'nnapi';\n    useFP16?: boolean;\n    useNCHW?: boolean;\n    cpuDisabled?: boolean;\n    cpuOnly?: boolean;\n  }\n  // #endregion\n\n  // #endregion\n\n  // #region run options\n\n  /**\n   * A set of configurations for inference run behavior\n   */\n  export interface RunOptions {\n    /**\n     * Log severity level. See\n     * https://github.com/microsoft/onnxruntime/blob/main/include/onnxruntime/core/common/logging/severity.h\n     *\n     * This setting is available only in ONNXRuntime (Node.js binding and react-native) or WebAssembly backend\n     */\n    logSeverityLevel?: 0 | 1 | 2 | 3 | 4;\n\n    /**\n     * Log verbosity level.\n     *\n     * This setting is available only in WebAssembly backend. Will support Node.js binding and react-native later\n     */\n    logVerbosityLevel?: number;\n\n    /**\n     * Terminate all incomplete OrtRun calls as soon as possible if true\n     *\n     * This setting is available only in WebAssembly backend. Will support Node.js binding and react-native later\n     */\n    terminate?: boolean;\n\n    /**\n     * A tag for the Run() calls using this\n     *\n     * This setting is available only in ONNXRuntime (Node.js binding and react-native) or WebAssembly backend\n     */\n    tag?: string;\n\n    /**\n     * Set a single run configuration entry. See\n     * https://github.com/microsoft/onnxruntime/blob/main/include/onnxruntime/core/session/\n     * onnxruntime_run_options_config_keys.h\n     *\n     * This setting is available only in WebAssembly backend. Will support Node.js binding and react-native later\n     *\n     * @example\n     *\n     * ```js\n     * extra: {\n     *   memory: {\n     *     enable_memory_arena_shrinkage: \"1\",\n     *   }\n     * }\n     * ```\n     */\n    extra?: Record<string, unknown>;\n  }\n\n  // #endregion\n\n  // #region value metadata\n\n  /**\n   * The common part of the value metadata type for both tensor and non-tensor values.\n   */\n  export interface ValueMetadataBase {\n    /**\n     * The name of the specified input or output.\n     */\n    readonly name: string;\n  }\n\n  /**\n   * Represents the metadata of a non-tensor value.\n   */\n  export interface NonTensorValueMetadata extends ValueMetadataBase {\n    /**\n     * Get a value indicating whether the value is a tensor.\n     */\n    readonly isTensor: false;\n  }\n\n  /**\n   * Represents the metadata of a tensor value.\n   */\n  export interface TensorValueMetadata extends ValueMetadataBase {\n    /**\n     * Get a value indicating whether the value is a tensor.\n     */\n    readonly isTensor: true;\n    /**\n     * Get the data type of the tensor.\n     */\n    readonly type: Tensor.Type;\n    /**\n     * Get the shape of the tensor.\n     *\n     * If the shape is not defined, the value will an empty array. Otherwise, it will be an array representing the shape\n     * of the tensor. Each element in the array can be a number or a string. If the element is a number, it represents\n     * the corresponding dimension size. If the element is a string, it represents a symbolic dimension.\n     */\n    readonly shape: ReadonlyArray<number | string>;\n  }\n\n  /**\n   * Represents the metadata of a value.\n   */\n  export type ValueMetadata = NonTensorValueMetadata | TensorValueMetadata;\n\n  // #endregion\n}\n\n/**\n * Represent a runtime instance of an ONNX model.\n */\nexport interface InferenceSession {\n  // #region run()\n\n  /**\n   * Execute the model asynchronously with the given feeds and options.\n   *\n   * @param feeds - Representation of the model input. See type description of `InferenceSession.InputType` for detail.\n   * @param options - Optional. A set of options that controls the behavior of model inference.\n   * @returns A promise that resolves to a map, which uses output names as keys and OnnxValue as corresponding values.\n   */\n  run(feeds: InferenceSession.FeedsType, options?: InferenceSession.RunOptions): Promise<InferenceSession.ReturnType>;\n\n  /**\n   * Execute the model asynchronously with the given feeds, fetches and options.\n   *\n   * @param feeds - Representation of the model input. See type description of `InferenceSession.InputType` for detail.\n   * @param fetches - Representation of the model output. See type description of `InferenceSession.OutputType` for\n   * detail.\n   * @param options - Optional. A set of options that controls the behavior of model inference.\n   * @returns A promise that resolves to a map, which uses output names as keys and OnnxValue as corresponding values.\n   */\n  run(\n    feeds: InferenceSession.FeedsType,\n    fetches: InferenceSession.FetchesType,\n    options?: InferenceSession.RunOptions,\n  ): Promise<InferenceSession.ReturnType>;\n\n  // #endregion\n\n  // #region release()\n\n  /**\n   * Release the inference session and the underlying resources.\n   */\n  release(): Promise<void>;\n\n  // #endregion\n\n  // #region profiling\n\n  /**\n   * Start profiling.\n   */\n  startProfiling(): void;\n\n  /**\n   * End profiling.\n   */\n  endProfiling(): void;\n\n  // #endregion\n\n  // #region metadata\n\n  /**\n   * Get input names of the loaded model.\n   */\n  readonly inputNames: readonly string[];\n\n  /**\n   * Get output names of the loaded model.\n   */\n  readonly outputNames: readonly string[];\n\n  /**\n   * Get input metadata of the loaded model.\n   */\n  readonly inputMetadata: readonly InferenceSession.ValueMetadata[];\n\n  /**\n   * Get output metadata of the loaded model.\n   */\n  readonly outputMetadata: readonly InferenceSession.ValueMetadata[];\n\n  // #endregion\n}\n\nexport interface InferenceSessionFactory {\n  // #region create()\n\n  /**\n   * Create a new inference session and load model asynchronously from an ONNX model file.\n   *\n   * @param uri - The URI or file path of the model to load.\n   * @param options - specify configuration for creating a new inference session.\n   * @returns A promise that resolves to an InferenceSession object.\n   */\n  create(uri: string, options?: InferenceSession.SessionOptions): Promise<InferenceSession>;\n\n  /**\n   * Create a new inference session and load model asynchronously from an array bufer.\n   *\n   * @param buffer - An ArrayBuffer representation of an ONNX model.\n   * @param options - specify configuration for creating a new inference session.\n   * @returns A promise that resolves to an InferenceSession object.\n   */\n  create(buffer: ArrayBufferLike, options?: InferenceSession.SessionOptions): Promise<InferenceSession>;\n\n  /**\n   * Create a new inference session and load model asynchronously from segment of an array bufer.\n   *\n   * @param buffer - An ArrayBuffer representation of an ONNX model.\n   * @param byteOffset - The beginning of the specified portion of the array buffer.\n   * @param byteLength - The length in bytes of the array buffer.\n   * @param options - specify configuration for creating a new inference session.\n   * @returns A promise that resolves to an InferenceSession object.\n   */\n  create(\n    buffer: ArrayBufferLike,\n    byteOffset: number,\n    byteLength?: number,\n    options?: InferenceSession.SessionOptions,\n  ): Promise<InferenceSession>;\n\n  /**\n   * Create a new inference session and load model asynchronously from a Uint8Array.\n   *\n   * @param buffer - A Uint8Array representation of an ONNX model.\n   * @param options - specify configuration for creating a new inference session.\n   * @returns A promise that resolves to an InferenceSession object.\n   */\n  create(buffer: Uint8Array, options?: InferenceSession.SessionOptions): Promise<InferenceSession>;\n\n  // #endregion\n}\n\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport const InferenceSession: InferenceSessionFactory = InferenceSessionImpl;\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { InferenceSession } from './inference-session.js';\nimport { OnnxValue } from './onnx-value.js';\n\n/**\n * @ignore\n */\nexport declare namespace SessionHandler {\n  type FeedsType = { [name: string]: OnnxValue };\n  type FetchesType = { [name: string]: OnnxValue | null };\n  type ReturnType = { [name: string]: OnnxValue };\n}\n\n/**\n * Represents shared SessionHandler functionality\n *\n * @ignore\n */\ninterface SessionHandler {\n  dispose(): Promise<void>;\n\n  readonly inputNames: readonly string[];\n  readonly outputNames: readonly string[];\n\n  readonly inputMetadata: readonly InferenceSession.ValueMetadata[];\n  readonly outputMetadata: readonly InferenceSession.ValueMetadata[];\n}\n\n/**\n * Represent a handler instance of an inference session.\n *\n * @ignore\n */\nexport interface InferenceSessionHandler extends SessionHandler {\n  startProfiling(): void;\n  endProfiling(): void;\n\n  run(\n    feeds: SessionHandler.FeedsType,\n    fetches: SessionHandler.FetchesType,\n    options: InferenceSession.RunOptions,\n  ): Promise<SessionHandler.ReturnType>;\n}\n\n/**\n * Represent a backend that provides implementation of model inferencing.\n *\n * @ignore\n */\nexport interface Backend {\n  /**\n   * Initialize the backend asynchronously. Should throw when failed.\n   */\n  init(backendName: string): Promise<void>;\n\n  createInferenceSessionHandler(\n    uriOrBuffer: string | Uint8Array,\n    options?: InferenceSession.SessionOptions,\n  ): Promise<InferenceSessionHandler>;\n}\n\nexport { registerBackend } from './backend-impl.js';\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { OptionsFormat, OptionsNormalizationParameters, OptionsTensorLayout } from './tensor-factory.js';\n\nexport interface TensorToDataUrlOptions extends OptionsTensorLayout, OptionsFormat, OptionsNormalizationParameters {}\n\nexport interface TensorToImageDataOptions extends OptionsTensorLayout, OptionsFormat, OptionsNormalizationParameters {}\n\nexport interface ConversionUtils {\n  /**\n   * creates a DataURL instance from tensor\n   *\n   * @param options - An optional object representing options for creating a DataURL instance from the tensor.\n   *\n   * The following default settings will be applied:\n   * - `format`: `'RGB'`\n   * - `tensorLayout`: `'NCHW'`\n   * @returns a DataURL string representing the image converted from tensor data\n   */\n  toDataURL(options?: TensorToDataUrlOptions): string;\n\n  /**\n   * creates an ImageData instance from tensor\n   *\n   * @param options - An optional object representing options for creating an ImageData instance from the tensor.\n   *\n   * The following default settings will be applied:\n   * - `format`: `'RGB'`\n   * - `tensorLayout`: `'NCHW'`\n   * @returns an ImageData instance representing the image converted from tensor data\n   */\n  toImageData(options?: TensorToImageDataOptions): ImageData;\n}\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { Tensor, TypedTensor } from './tensor.js';\n\nexport type ImageFormat = 'RGB' | 'RGBA' | 'BGR' | 'RBG';\nexport type ImageTensorLayout = 'NHWC' | 'NCHW';\n\n// the following region contains type definitions for constructing tensor from a specific location.\n\n// #region types for constructing a tensor from a specific location\n\n/**\n * represent common properties of the parameter for constructing a tensor from a specific location.\n */\ninterface CommonConstructorParameters<T> extends Pick<Tensor, 'dims'> {\n  /**\n   * Specify the data type of the tensor.\n   */\n  readonly type: T;\n}\n\n/**\n * represent the parameter for constructing a tensor from a GPU resource.\n */\ninterface GpuResourceConstructorParameters<T extends Tensor.Type> {\n  /**\n   * an optional callback function to download data from GPU to CPU.\n   *\n   * If not provided, the tensor treat the GPU data as external resource.\n   */\n  download?(): Promise<Tensor.DataTypeMap[T]>;\n\n  /**\n   * an optional callback function that will be called when the tensor is disposed.\n   *\n   * If not provided, the tensor treat the GPU data as external resource.\n   */\n  dispose?(): void;\n}\n\n/**\n * represent the parameter for constructing a tensor from a pinned CPU buffer\n */\nexport interface CpuPinnedConstructorParameters<\n  T extends Tensor.CpuPinnedDataTypes = Tensor.CpuPinnedDataTypes,\n> extends CommonConstructorParameters<T> {\n  /**\n   * Specify the location of the data to be 'cpu-pinned'.\n   */\n  readonly location: 'cpu-pinned';\n  /**\n   * Specify the CPU pinned buffer that holds the tensor data.\n   */\n  readonly data: Tensor.DataTypeMap[T];\n}\n\n/**\n * represent the parameter for constructing a tensor from a WebGL texture\n */\nexport interface TextureConstructorParameters<T extends Tensor.TextureDataTypes = Tensor.TextureDataTypes>\n  extends CommonConstructorParameters<T>, GpuResourceConstructorParameters<T> {\n  /**\n   * Specify the location of the data to be 'texture'.\n   */\n  readonly location: 'texture';\n  /**\n   * Specify the WebGL texture that holds the tensor data.\n   */\n  readonly texture: Tensor.TextureType;\n}\n\n/**\n * represent the parameter for constructing a tensor from a WebGPU buffer\n */\nexport interface GpuBufferConstructorParameters<T extends Tensor.GpuBufferDataTypes = Tensor.GpuBufferDataTypes>\n  extends CommonConstructorParameters<T>, GpuResourceConstructorParameters<T> {\n  /**\n   * Specify the location of the data to be 'gpu-buffer'.\n   */\n  readonly location: 'gpu-buffer';\n  /**\n   * Specify the WebGPU buffer that holds the tensor data.\n   */\n  readonly gpuBuffer: Tensor.GpuBufferType;\n}\n\nexport interface MLTensorConstructorParameters<T extends Tensor.MLTensorDataTypes = Tensor.MLTensorDataTypes>\n  extends CommonConstructorParameters<T>, GpuResourceConstructorParameters<T> {\n  /**\n   * Specify the location of the data to be 'ml-tensor'.\n   */\n  readonly location: 'ml-tensor';\n\n  /**\n   * Specify the WebNN MLTensor that holds the tensor data.\n   */\n  readonly mlTensor: Tensor.MLTensorType;\n}\n\n// #endregion\n\n// the following region contains type definitions of each individual options.\n// the tensor factory functions use a composition of those options as the parameter type.\n\n// #region Options fields\n\nexport interface OptionsFormat {\n  /**\n   * Describes the image format represented in RGBA color space.\n   */\n  format?: ImageFormat;\n}\n\nexport interface OptionsTensorFormat {\n  /**\n   * Describes the image format of the tensor.\n   *\n   * NOTE: this is different from option 'format'. While option 'format' represents the original image, 'tensorFormat'\n   * represents the target format of the tensor. A transpose will be performed if they are different.\n   */\n  tensorFormat?: ImageFormat;\n}\n\nexport interface OptionsTensorDataType {\n  /**\n   * Describes the data type of the tensor.\n   */\n  dataType?: 'float32' | 'uint8';\n}\n\nexport interface OptionsTensorLayout {\n  /**\n   * Describes the tensor layout when representing data of one or more image(s).\n   */\n  tensorLayout?: ImageTensorLayout;\n}\n\nexport interface OptionsDimensions {\n  /**\n   * Describes the image height in pixel\n   */\n  height?: number;\n  /**\n   * Describes the image width in pixel\n   */\n  width?: number;\n}\n\nexport interface OptionResizedDimensions {\n  /**\n   * Describes the resized height. If omitted, original height will be used.\n   */\n  resizedHeight?: number;\n  /**\n   * Describes resized width - can be accessed via tensor dimensions as well\n   */\n  resizedWidth?: number;\n}\n\nexport interface OptionsNormalizationParameters {\n  /**\n   * Describes normalization parameters when preprocessing the image as model input.\n   *\n   * Data element are ranged from 0 to 255.\n   */\n  norm?: {\n    /**\n     * The 'bias' value for image normalization.\n     * - If omitted, use default value 0.\n     * - If it's a single number, apply to each channel\n     * - If it's an array of 3 or 4 numbers, apply element-wise. Number of elements need to match the number of channels\n     * for the corresponding image format\n     */\n    bias?: number | [number, number, number] | [number, number, number, number];\n    /**\n     * The 'mean' value for image normalization.\n     * - If omitted, use default value 255.\n     * - If it's a single number, apply to each channel\n     * - If it's an array of 3 or 4 numbers, apply element-wise. Number of elements need to match the number of channels\n     * for the corresponding image format\n     */\n    mean?: number | [number, number, number] | [number, number, number, number];\n  };\n}\n\n// #endregion\n\n// #region Options composition\n\nexport interface TensorFromImageDataOptions\n  extends\n    OptionResizedDimensions,\n    OptionsTensorFormat,\n    OptionsTensorLayout,\n    OptionsTensorDataType,\n    OptionsNormalizationParameters {}\n\nexport interface TensorFromImageElementOptions\n  extends\n    OptionResizedDimensions,\n    OptionsTensorFormat,\n    OptionsTensorLayout,\n    OptionsTensorDataType,\n    OptionsNormalizationParameters {}\n\nexport interface TensorFromUrlOptions\n  extends\n    OptionsDimensions,\n    OptionResizedDimensions,\n    OptionsTensorFormat,\n    OptionsTensorLayout,\n    OptionsTensorDataType,\n    OptionsNormalizationParameters {}\n\nexport interface TensorFromImageBitmapOptions\n  extends\n    OptionResizedDimensions,\n    OptionsTensorFormat,\n    OptionsTensorLayout,\n    OptionsTensorDataType,\n    OptionsNormalizationParameters {}\n\nexport interface TensorFromTextureOptions<T extends Tensor.TextureDataTypes>\n  extends Required<OptionsDimensions>, OptionsFormat, GpuResourceConstructorParameters<T> /* TODO: add more */ {}\n\nexport interface TensorFromGpuBufferOptions<T extends Tensor.GpuBufferDataTypes>\n  extends Pick<Tensor, 'dims'>, GpuResourceConstructorParameters<T> {\n  /**\n   * Describes the data type of the tensor.\n   */\n  dataType?: T;\n}\n\nexport interface TensorFromMLTensorOptions<T extends Tensor.MLTensorDataTypes>\n  extends Pick<Tensor, 'dims'>, GpuResourceConstructorParameters<T> {\n  /**\n   * Describes the data type of the tensor.\n   */\n  dataType?: T;\n}\n\n// #endregion\n\n/**\n * type TensorFactory defines the factory functions of 'Tensor' to create tensor instances from existing data or\n * resources.\n */\nexport interface TensorFactory {\n  /**\n   * create a tensor from an ImageData object\n   *\n   * @param imageData - the ImageData object to create tensor from\n   * @param options - An optional object representing options for creating tensor from ImageData.\n   *\n   * The following default settings will be applied:\n   * - `tensorFormat`: `'RGB'`\n   * - `tensorLayout`: `'NCHW'`\n   * - `dataType`: `'float32'`\n   * @returns A promise that resolves to a tensor object\n   */\n  fromImage(\n    imageData: ImageData,\n    options?: TensorFromImageDataOptions,\n  ): Promise<TypedTensor<'float32'> | TypedTensor<'uint8'>>;\n\n  /**\n   * create a tensor from a HTMLImageElement object\n   *\n   * @param imageElement - the HTMLImageElement object to create tensor from\n   * @param options - An optional object representing options for creating tensor from HTMLImageElement.\n   *\n   * The following default settings will be applied:\n   * - `tensorFormat`: `'RGB'`\n   * - `tensorLayout`: `'NCHW'`\n   * - `dataType`: `'float32'`\n   * @returns A promise that resolves to a tensor object\n   */\n  fromImage(\n    imageElement: HTMLImageElement,\n    options?: TensorFromImageElementOptions,\n  ): Promise<TypedTensor<'float32'> | TypedTensor<'uint8'>>;\n\n  /**\n   * create a tensor from URL\n   *\n   * @param urlSource - a string as a URL to the image or a data URL containing the image data.\n   * @param options - An optional object representing options for creating tensor from URL.\n   *\n   * The following default settings will be applied:\n   * - `tensorFormat`: `'RGB'`\n   * - `tensorLayout`: `'NCHW'`\n   * - `dataType`: `'float32'`\n   * @returns A promise that resolves to a tensor object\n   */\n  fromImage(urlSource: string, options?: TensorFromUrlOptions): Promise<TypedTensor<'float32'> | TypedTensor<'uint8'>>;\n\n  /**\n   * create a tensor from an ImageBitmap object\n   *\n   * @param bitmap - the ImageBitmap object to create tensor from\n   * @param options - An optional object representing options for creating tensor from URL.\n   *\n   * The following default settings will be applied:\n   * - `tensorFormat`: `'RGB'`\n   * - `tensorLayout`: `'NCHW'`\n   * - `dataType`: `'float32'`\n   * @returns A promise that resolves to a tensor object\n   */\n  fromImage(\n    bitmap: ImageBitmap,\n    options: TensorFromImageBitmapOptions,\n  ): Promise<TypedTensor<'float32'> | TypedTensor<'uint8'>>;\n\n  /**\n   * create a tensor from a WebGL texture\n   *\n   * @param texture - the WebGLTexture object to create tensor from\n   * @param options - An optional object representing options for creating tensor from WebGL texture.\n   *\n   * The options include following properties:\n   * - `width`: the width of the texture. Required.\n   * - `height`: the height of the texture. Required.\n   * - `format`: the format of the texture. If omitted, assume 'RGBA'.\n   * - `download`: an optional function to download the tensor data from GPU to CPU. If omitted, the GPU data\n   * will not be able to download. Usually, this is provided by a GPU backend for the inference outputs. Users don't\n   * need to provide this function.\n   * - `dispose`: an optional function to dispose the tensor data on GPU. If omitted, the GPU data will not be disposed.\n   * Usually, this is provided by a GPU backend for the inference outputs. Users don't need to provide this function.\n   *\n   * @returns a tensor object\n   */\n  fromTexture<T extends Tensor.TextureDataTypes = 'float32'>(\n    texture: Tensor.TextureType,\n    options: TensorFromTextureOptions<T>,\n  ): TypedTensor<'float32'>;\n\n  /**\n   * create a tensor from a WebGPU buffer\n   *\n   * @param buffer - the GPUBuffer object to create tensor from\n   * @param options - An optional object representing options for creating tensor from WebGPU buffer.\n   *\n   * The options include following properties:\n   * - `dataType`: the data type of the tensor. If omitted, assume 'float32'.\n   * - `dims`: the dimension of the tensor. Required.\n   * - `download`: an optional function to download the tensor data from GPU to CPU. If omitted, the GPU data\n   * will not be able to download. Usually, this is provided by a GPU backend for the inference outputs. Users don't\n   * need to provide this function.\n   * - `dispose`: an optional function to dispose the tensor data on GPU. If omitted, the GPU data will not be disposed.\n   * Usually, this is provided by a GPU backend for the inference outputs. Users don't need to provide this function.\n   *\n   * @returns a tensor object\n   */\n  fromGpuBuffer<T extends Tensor.GpuBufferDataTypes>(\n    buffer: Tensor.GpuBufferType,\n    options: TensorFromGpuBufferOptions<T>,\n  ): TypedTensor<T>;\n\n  /**\n   * create a tensor from a WebNN MLTensor\n   *\n   * @param tensor - the MLTensor object to create tensor from\n   * @param options - An optional object representing options for creating tensor from a WebNN MLTensor.\n   *\n   * The options include following properties:\n   * - `dataType`: the data type of the tensor. If omitted, assume 'float32'.\n   * - `dims`: the dimension of the tensor. Required.\n   * - `download`: an optional function to download the tensor data from the MLTensor to CPU. If omitted, the MLTensor\n   * data will not be able to download. Usually, this is provided by the WebNN backend for the inference outputs.\n   * Users don't need to provide this function.\n   * - `dispose`: an optional function to dispose the tensor data on the WebNN MLTensor. If omitted, the MLTensor will\n   * not be disposed. Usually, this is provided by the WebNN backend for the inference outputs. Users don't need to\n   * provide this function.\n   *\n   * @returns a tensor object\n   */\n  fromMLTensor<T extends Tensor.MLTensorDataTypes>(\n    tensor: Tensor.MLTensorType,\n    options: TensorFromMLTensorOptions<T>,\n  ): TypedTensor<T>;\n\n  /**\n   * create a tensor from a pre-allocated buffer. The buffer will be used as a pinned buffer.\n   *\n   * @param type - the tensor element type.\n   * @param buffer - a TypedArray corresponding to the type.\n   * @param dims - specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.\n   *\n   * @returns a tensor object\n   */\n  fromPinnedBuffer<T extends Exclude<Tensor.Type, 'string'>>(\n    type: T,\n    buffer: Tensor.DataTypeMap[T],\n    dims?: readonly number[],\n  ): TypedTensor<T>;\n}\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\n/**\n * A string that represents a file's URL or path.\n *\n * Path is vailable only in onnxruntime-node or onnxruntime-web running in Node.js.\n */\nexport type FileUrlOrPath = string;\n\n/**\n * A Blob object that represents a file.\n */\nexport type FileBlob = Blob;\n\n/**\n * A Uint8Array, ArrayBuffer or SharedArrayBuffer object that represents a file content.\n *\n * When it is an ArrayBuffer or SharedArrayBuffer, the whole buffer is assumed to be the file content.\n */\nexport type FileData = Uint8Array | ArrayBufferLike;\n\n/**\n * Represents a file that can be loaded by the ONNX Runtime JavaScript API.\n */\nexport type FileType = FileUrlOrPath | FileBlob | FileData;\n\n/**\n * Represents an external data file.\n */\nexport interface ExternalDataFileDescription {\n  /**\n   * Specify the external data file.\n   */\n  data: FileType;\n  /**\n   * Specify the file path.\n   */\n  path: string;\n}\n\n/**\n * Represents an external data file.\n *\n * When using a string, it should be a file URL or path that in the same directory as the model file.\n */\nexport type ExternalDataFileType = ExternalDataFileDescription | FileUrlOrPath;\n\n/**\n * Options for model loading.\n */\nexport interface OnnxModelOptions {\n  /**\n   * Specifying a list of files that represents the external data.\n   */\n  externalData?: readonly ExternalDataFileType[];\n}\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { Tensor } from './tensor.js';\n\nexport type NonTensorType = never;\n\n/**\n * Type OnnxValue Represents both tensors and non-tensors value for model's inputs/outputs.\n *\n * NOTE: currently not support non-tensor\n */\nexport type OnnxValue = Tensor | NonTensorType;\n\n/**\n * Type OnnxValueDataLocation represents the location of the data of an OnnxValue.\n */\nexport type OnnxValueDataLocation = Tensor.DataLocation;\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\n/**\n * # ONNX Runtime JavaScript API\n *\n * ONNX Runtime JavaScript API is a unified API for all JavaScript usages, including the following NPM packages:\n *\n * - [onnxruntime-node](https://www.npmjs.com/package/onnxruntime-node)\n * - [onnxruntime-web](https://www.npmjs.com/package/onnxruntime-web)\n * - [onnxruntime-react-native](https://www.npmjs.com/package/onnxruntime-react-native)\n *\n * See also:\n * - [Get Started](https://onnxruntime.ai/docs/get-started/with-javascript/)\n * - [Inference examples](https://github.com/microsoft/onnxruntime-inference-examples/tree/main/js)\n *\n * @packageDocumentation\n */\n\nexport * from './backend.js';\nexport * from './env.js';\nexport * from './inference-session.js';\nexport * from './tensor.js';\nexport * from './tensor-conversion.js';\nexport * from './tensor-factory.js';\nexport * from './trace.js';\nexport * from './onnx-model.js';\nexport * from './onnx-value.js';\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nexport const isNode = !!(typeof process !== 'undefined' && process.versions && process.versions.node);\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\n/// <reference lib=\"webworker\" />\n\n//\n// * type hack for \"HTMLImageElement\"\n//\n// in typescript, the type of \"HTMLImageElement\" is defined in lib.dom.d.ts, which is conflict with lib.webworker.d.ts.\n// when we use webworker, the lib.webworker.d.ts will be used, which does not have HTMLImageElement defined.\n//\n// we will get the following errors complaining that HTMLImageElement is not defined:\n//\n// ====================================================================================================================\n//\n// ../common/dist/cjs/tensor-factory.d.ts:187:29 - error TS2552: Cannot find name 'HTMLImageElement'. Did you mean\n// 'HTMLLIElement'?\n//\n// 187     fromImage(imageElement: HTMLImageElement, options?: TensorFromImageElementOptions):\n// Promise<TypedTensor<'float32'> | TypedTensor<'uint8'>>;\n//                                 ~~~~~~~~~~~~~~~~\n//\n// node_modules/@webgpu/types/dist/index.d.ts:83:7 - error TS2552: Cannot find name 'HTMLImageElement'. Did you mean\n// 'HTMLLIElement'?\n//\n// 83     | HTMLImageElement\n//          ~~~~~~~~~~~~~~~~\n//\n// ====================================================================================================================\n//\n// `HTMLImageElement` is only used in type declaration and not in real code. So we define it as `unknown` here to\n// bypass the type check.\n\n//\n// * type hack for \"document\"\n//\n// in typescript, the type of \"document\" is defined in lib.dom.d.ts, so it's not available in webworker.\n//\n// we will get the following errors complaining that document is not defined:\n//\n// ====================================================================================================================\n//\n// lib/wasm/wasm-utils-import.ts:7:33 - error TS2584: Cannot find name 'document'. Do you need to change your target\n// library? Try changing the 'lib' compiler option to include 'dom'.\n//\n// 7 export const scriptSrc = typeof document !== 'undefined' ? (document?.currentScript as HTMLScriptElement)?.src :\n//                                   ~~~~~~~~\n//\n// lib/wasm/wasm-utils-import.ts:7:61 - error TS2584: Cannot find name 'document'. Do you need to change your target\n// library? Try changing the 'lib' compiler option to include 'dom'.\n//\n// 7 export const scriptSrc = typeof document !== 'undefined' ? (document?.currentScript as HTMLScriptElement)?.src :\n//                                                               ~~~~~~~~\n//\n// lib/wasm/wasm-utils-import.ts:7:88 - error TS2552: Cannot find name 'HTMLScriptElement'. Did you mean\n// 'HTMLLIElement'?\n//\n// 7 export const scriptSrc = typeof document !== 'undefined' ? (document?.currentScript as HTMLScriptElement)?.src :\n//                                                                                          ~~~~~~~~~~~~~~~~~\n// ====================================================================================================================\n//\n// `document` is used to get the current script URL, which is not available in webworker. This file is served as a\n// \"dual\" file for entries of both webworker and the esm module.\n//\ndeclare global {\n  type HTMLImageElement = unknown;\n  type HTMLScriptElement = { src?: string };\n  const document: undefined | { currentScript?: HTMLScriptElement };\n}\n\n/**\n * @summary\n *\n * This file is served as a \"dual\" file for both entries of the following:\n * - The proxy worker itself.\n *   - When used as a worker, it listens to the messages from the main thread and performs the corresponding operations.\n *   - Should be imported directly using `new Worker()` in the main thread.\n *\n * - The ESM module that creates the proxy worker (as a worker launcher).\n *   - When used as a worker launcher, it creates the proxy worker and returns it.\n *   - Should be imported using `import()` in the main thread, with the query parameter `import=1`.\n *\n * This file will be always compiling into ESM format.\n */\n\nimport type { OrtWasmMessage, SerializableTensorMetadata } from '../proxy-messages.js';\nimport {\n  createSession,\n  copyFromExternalBuffer,\n  endProfiling,\n  extractTransferableBuffers,\n  initEp,\n  initRuntime,\n  releaseSession,\n  run,\n} from '../wasm-core-impl.js';\nimport { initializeWebAssembly } from '../wasm-factory.js';\nimport { scriptSrc } from '../wasm-utils-import.js';\n\nconst WORKER_NAME = 'ort-wasm-proxy-worker';\nconst isProxyWorker = globalThis.self?.name === WORKER_NAME;\n\nif (isProxyWorker) {\n  // Worker thread\n  self.onmessage = (ev: MessageEvent<OrtWasmMessage>): void => {\n    const { type, in: message } = ev.data;\n    try {\n      switch (type) {\n        case 'init-wasm':\n          initializeWebAssembly(message!.wasm).then(\n            () => {\n              initRuntime(message!).then(\n                () => {\n                  postMessage({ type });\n                },\n                (err) => {\n                  postMessage({ type, err });\n                },\n              );\n            },\n            (err) => {\n              postMessage({ type, err });\n            },\n          );\n          break;\n        case 'init-ep': {\n          const { epName, env } = message!;\n          initEp(env, epName).then(\n            () => {\n              postMessage({ type });\n            },\n            (err) => {\n              postMessage({ type, err });\n            },\n          );\n          break;\n        }\n        case 'copy-from': {\n          const { buffer } = message!;\n          const bufferData = copyFromExternalBuffer(buffer);\n          postMessage({ type, out: bufferData });\n          break;\n        }\n        case 'create': {\n          const { model, options } = message!;\n          createSession(model, options).then(\n            (sessionMetadata) => {\n              postMessage({ type, out: sessionMetadata });\n            },\n            (err) => {\n              postMessage({ type, err });\n            },\n          );\n          break;\n        }\n        case 'release':\n          releaseSession(message!);\n          postMessage({ type });\n          break;\n        case 'run': {\n          const { sessionId, inputIndices, inputs, outputIndices, options } = message!;\n          run(sessionId, inputIndices, inputs, outputIndices, new Array(outputIndices.length).fill(null), options).then(\n            (outputs) => {\n              if (outputs.some((o) => o[3] !== 'cpu')) {\n                postMessage({ type, err: 'Proxy does not support non-cpu tensor location.' });\n              } else {\n                postMessage(\n                  { type, out: outputs },\n                  extractTransferableBuffers([...inputs, ...outputs] as SerializableTensorMetadata[]),\n                );\n              }\n            },\n            (err) => {\n              postMessage({ type, err });\n            },\n          );\n          break;\n        }\n        case 'end-profiling':\n          endProfiling(message!);\n          postMessage({ type });\n          break;\n        default:\n      }\n    } catch (err) {\n      postMessage({ type, err });\n    }\n  };\n}\n\nexport default isProxyWorker\n  ? null\n  : (urlOverride?: string) =>\n      new Worker(urlOverride ?? scriptSrc!, { type: BUILD_DEFS.IS_ESM ? 'module' : 'classic', name: WORKER_NAME });\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport type { OrtWasmModule } from './wasm-types';\nimport { isNode } from './wasm-utils-env';\n\n/**\n * The origin of the current location.\n *\n * In Node.js, this is undefined.\n */\nconst origin = isNode || typeof location === 'undefined' ? undefined : location.origin;\n\n/**\n * Some bundlers (eg. Webpack) will rewrite `import.meta.url` to a file URL at compile time.\n *\n * This function checks if `import.meta.url` starts with `file:`, but using the `>` and `<` operators instead of\n * `startsWith` function so that code minimizers can remove the dead code correctly.\n *\n * For example, if we use terser to minify the following code:\n * ```js\n * if (\"file://hard-coded-filename\".startsWith(\"file:\")) {\n *   console.log(1)\n * } else {\n *   console.log(2)\n * }\n *\n * if (\"file://hard-coded-filename\" > \"file:\" && \"file://hard-coded-filename\" < \"file;\") {\n *   console.log(3)\n * } else {\n *   console.log(4)\n * }\n * ```\n *\n * The minified code will be:\n * ```js\n * \"file://hard-coded-filename\".startsWith(\"file:\")?console.log(1):console.log(2),console.log(3);\n * ```\n *\n * (use Terser 5.39.0 with default options, https://try.terser.org/)\n *\n * @returns true if the import.meta.url is hardcoded as a file URI.\n */\nexport const isEsmImportMetaUrlHardcodedAsFileUri =\n  BUILD_DEFS.IS_ESM && BUILD_DEFS.ESM_IMPORT_META_URL! > 'file:' && BUILD_DEFS.ESM_IMPORT_META_URL! < 'file;';\n\nconst getScriptSrc = (): string | undefined => {\n  // if Nodejs, return undefined\n  if (isNode) {\n    return undefined;\n  }\n  // if It's ESM, use import.meta.url\n  if (BUILD_DEFS.IS_ESM) {\n    // For ESM, if the import.meta.url is a file URL, this usually means the bundler rewrites `import.meta.url` to\n    // the file path at compile time. In this case, this file path cannot be used to determine the runtime URL.\n    //\n    // We need to use the URL constructor like this:\n    // ```js\n    // new URL('actual-bundle-name.js', import.meta.url).href\n    // ```\n    // So that bundler can preprocess the URL correctly.\n    if (isEsmImportMetaUrlHardcodedAsFileUri) {\n      // if the rewritten URL is a relative path, we need to use the origin to resolve the URL.\n\n      // The following is a workaround for Vite.\n      //\n      // Vite uses a bundler(rollup/rolldown) that does not rewrite `import.meta.url` to a file URL. So in theory, this\n      // code path should not be executed in Vite. However, the bundler does not know it and it still try to load the\n      // following pattern:\n      // - `return new URL('filename', import.meta.url).href`\n      //\n      // By replacing the pattern above with the following code, we can skip the resource loading behavior:\n      // - `const URL2 = URL; return new URL2('filename', import.meta.url).href;`\n      //\n      // And it still works in Webpack.\n      const URL2 = URL;\n      return new URL(new URL2(BUILD_DEFS.BUNDLE_FILENAME, BUILD_DEFS.ESM_IMPORT_META_URL).href, origin).href;\n    }\n\n    return BUILD_DEFS.ESM_IMPORT_META_URL;\n  }\n\n  return typeof document !== 'undefined'\n    ? (document.currentScript as HTMLScriptElement)?.src\n    : // use `self.location.href` if available\n      typeof self !== 'undefined'\n      ? self.location?.href\n      : undefined;\n};\n\n/**\n * The classic script source URL. This is not always available in non ESModule environments.\n *\n * In Node.js, this is undefined.\n */\nexport const scriptSrc = getScriptSrc();\n\n/**\n * Infer the wasm path prefix from the script source URL.\n *\n * @returns The inferred wasm path prefix, or undefined if the script source URL is not available or is a blob URL.\n */\nexport const inferWasmPathPrefixFromScriptSrc = (): string | undefined => {\n  if (scriptSrc && !scriptSrc.startsWith('blob:')) {\n    return scriptSrc.substring(0, scriptSrc.lastIndexOf('/') + 1);\n  }\n  return undefined;\n};\n\n/**\n * Check if the given filename with prefix is from the same origin.\n */\nconst isSameOrigin = (filename: string, prefixOverride?: string) => {\n  try {\n    const baseUrl = prefixOverride ?? scriptSrc;\n    const url = baseUrl ? new URL(filename, baseUrl) : new URL(filename);\n    return url.origin === origin;\n  } catch {\n    return false;\n  }\n};\n\n/**\n * Normalize the inputs to an absolute URL with the given prefix override. If failed, return undefined.\n */\nconst normalizeUrl = (filename: string, prefixOverride?: string) => {\n  const baseUrl = prefixOverride ?? scriptSrc;\n  try {\n    const url = baseUrl ? new URL(filename, baseUrl) : new URL(filename);\n    return url.href;\n  } catch {\n    return undefined;\n  }\n};\n\n/**\n * Create a fallback URL if an absolute URL cannot be created by the normalizeUrl function.\n */\nconst fallbackUrl = (filename: string, prefixOverride?: string) => `${prefixOverride ?? './'}${filename}`;\n\n/**\n * This helper function is used to preload a module from a URL.\n *\n * If the origin of the worker URL is different from the current origin, the worker cannot be loaded directly.\n * See discussions in https://github.com/webpack-contrib/worker-loader/issues/154\n *\n * In this case, we will fetch the worker URL and create a new Blob URL with the same origin as a workaround.\n *\n * @param absoluteUrl - The absolute URL to preload.\n *\n * @returns - A promise that resolves to a new Blob URL\n */\nconst preload = async (absoluteUrl: string): Promise<string> => {\n  const response = await fetch(absoluteUrl, { credentials: 'same-origin' });\n  const blob = await response.blob();\n  return URL.createObjectURL(blob);\n};\n\n/**\n * This helper function is used to dynamically import a module from a URL.\n *\n * The build script has special handling for this function to ensure that the URL is not bundled into the final output.\n *\n * @param url - The URL to import.\n *\n * @returns - A promise that resolves to the default export of the module.\n */\nconst dynamicImportDefault = async <T>(url: string): Promise<T> =>\n  (await import(/* webpackIgnore: true */ /* @vite-ignore */ url)).default;\n\n/**\n * The proxy worker factory imported from the proxy worker module.\n *\n * This is only available when the WebAssembly proxy is not disabled.\n */\nconst createProxyWorker: ((urlOverride?: string) => Worker) | undefined =\n  // eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires\n  BUILD_DEFS.DISABLE_WASM_PROXY ? undefined : require('./proxy-worker/main').default;\n\n/**\n * Import the proxy worker.\n *\n * This function will perform the following steps:\n * 1. If a preload is needed, it will preload the module and return the object URL.\n * 2. Use the proxy worker factory to create the proxy worker.\n *\n * @returns - A promise that resolves to a tuple of 2 elements:\n *            - The object URL of the preloaded module, or undefined if no preload is needed.\n *            - The proxy worker.\n */\nexport const importProxyWorker = async (): Promise<[undefined | string, Worker]> => {\n  if (!scriptSrc) {\n    throw new Error('Failed to load proxy worker: cannot determine the script source URL.');\n  }\n\n  // If the script source is from the same origin, we can use the embedded proxy module directly.\n  if (isSameOrigin(scriptSrc)) {\n    return [undefined, createProxyWorker!()];\n  }\n\n  // Otherwise, need to preload\n  const url = await preload(scriptSrc);\n  return [url, createProxyWorker!(url)];\n};\n\n/**\n * The embedded WebAssembly module.\n *\n * This is only available in ESM and when embedding is not disabled.\n */\nconst embeddedWasmModule: EmscriptenModuleFactory<OrtWasmModule> | undefined =\n  BUILD_DEFS.IS_ESM && BUILD_DEFS.ENABLE_BUNDLE_WASM_JS\n    ? // eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires\n      require(\n        !BUILD_DEFS.DISABLE_JSEP\n          ? '../../dist/ort-wasm-simd-threaded.jsep.mjs'\n          : BUILD_DEFS.ENABLE_JSPI\n            ? '../../dist/ort-wasm-simd-threaded.jspi.mjs'\n            : !BUILD_DEFS.DISABLE_WEBGPU\n              ? '../../dist/ort-wasm-simd-threaded.asyncify.mjs'\n              : '../../dist/ort-wasm-simd-threaded.mjs',\n      ).default\n    : undefined;\n\n/**\n * Import the WebAssembly module.\n *\n * This function will perform the following steps:\n * 1. If the embedded module exists and no custom URL is specified, use the embedded module.\n * 2. If a preload is needed, it will preload the module and return the object URL.\n * 3. Otherwise, it will perform a dynamic import of the module.\n *\n * @returns - A promise that resolves to a tuple of 2 elements:\n *            - The object URL of the preloaded module, or undefined if no preload is needed.\n *            - The default export of the module, which is a factory function to create the WebAssembly module.\n */\nexport const importWasmModule = async (\n  urlOverride: string | undefined,\n  prefixOverride: string | undefined,\n  isMultiThreaded: boolean,\n  isWasmOverridden: boolean,\n): Promise<[undefined | string, EmscriptenModuleFactory<OrtWasmModule>]> => {\n  //\n  // Check if we should use the embedded module.\n  //\n\n  // To use the embedded module, it should be available, and no URL override or prefix override should be specified.\n  let useEmbeddedModule = embeddedWasmModule && !(urlOverride || prefixOverride);\n  if (useEmbeddedModule) {\n    if (!scriptSrc) {\n      // no URL info available.\n      //\n      // Note: when the embedded module is available, it means the current script is ESM. Usually, in ESM, the\n      // `import.meta.url` is available. But in some cases (eg. Cloudflare Workers), the value of `import.meta.url`\n      // can be `null` or `undefined`. In this case, we can only load the embedded module when:\n      //\n      // 1. The WebAssembly module binary is overridden:\n      //    ```js\n      //    env.wasm.wasmPaths = undefined;  // or not specified\n      //    env.wasm.wasmBinary = /* a Uint8Array containing the WebAssembly binary */;\n      //    ```\n      //\n      // 2. The \".wasm\" only is overridden.\n      //    ```js\n      //    env.wasm.wasmPaths = { wasm: /* URL of the .wasm file */ };\n      //    ```\n      //\n      if (isWasmOverridden && !isMultiThreaded) {\n        useEmbeddedModule = true;\n      } else {\n        throw new Error('cannot determine the script source URL.');\n      }\n    } else {\n      // if the script source is available, we can check if it is from the same origin.\n      // Also use the embedded module when wasmBinary is provided and single-threaded (eg. Blob URL workers\n      // where isSameOrigin fails but no file resolution or worker spawning is needed).\n      useEmbeddedModule = isSameOrigin(scriptSrc) || (isWasmOverridden && !isMultiThreaded);\n    }\n  }\n  if (useEmbeddedModule) {\n    return [undefined, embeddedWasmModule!];\n  } else {\n    const wasmModuleFilename = !BUILD_DEFS.DISABLE_JSEP\n      ? 'ort-wasm-simd-threaded.jsep.mjs'\n      : BUILD_DEFS.ENABLE_JSPI\n        ? 'ort-wasm-simd-threaded.jspi.mjs'\n        : !BUILD_DEFS.DISABLE_WEBGPU\n          ? 'ort-wasm-simd-threaded.asyncify.mjs'\n          : 'ort-wasm-simd-threaded.mjs';\n    const wasmModuleUrl = urlOverride ?? normalizeUrl(wasmModuleFilename, prefixOverride);\n    // need to preload if all of the following conditions are met:\n    // 1. not in Node.js.\n    //    - Node.js does not have the same origin policy for creating workers.\n    // 2. multi-threaded is enabled.\n    //    - If multi-threaded is disabled, no worker will be created. So we don't need to preload the module.\n    // 3. the absolute URL is available.\n    //    - If the absolute URL is failed to be created, the origin cannot be determined. In this case, we will not\n    //    preload the module.\n    // 4. the worker URL is not from the same origin.\n    //    - If the worker URL is from the same origin, we can create the worker directly.\n    const needPreload = !isNode && isMultiThreaded && wasmModuleUrl && !isSameOrigin(wasmModuleUrl, prefixOverride);\n    const url = needPreload\n      ? await preload(wasmModuleUrl)\n      : (wasmModuleUrl ?? fallbackUrl(wasmModuleFilename, prefixOverride));\n    return [needPreload ? url : undefined, await dynamicImportDefault<EmscriptenModuleFactory<OrtWasmModule>>(url)];\n  }\n};\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { Env } from 'onnxruntime-common';\n\nimport type { OrtWasmModule } from './wasm-types';\nimport { importWasmModule, inferWasmPathPrefixFromScriptSrc } from './wasm-utils-import';\n\nlet wasm: OrtWasmModule | undefined;\nlet initialized = false;\nlet initializing = false;\nlet aborted = false;\n\nconst isMultiThreadSupported = (): boolean => {\n  // If 'SharedArrayBuffer' is not available, WebAssembly threads will not work.\n  if (typeof SharedArrayBuffer === 'undefined') {\n    return false;\n  }\n\n  try {\n    // Test for transferability of SABs (for browsers. needed for Firefox)\n    // https://groups.google.com/forum/#!msg/mozilla.dev.platform/IHkBZlHETpA/dwsMNchWEQAJ\n    if (typeof MessageChannel !== 'undefined') {\n      new MessageChannel().port1.postMessage(new SharedArrayBuffer(1));\n    }\n\n    // Test for WebAssembly threads capability (for both browsers and Node.js)\n    // This typed array is a WebAssembly program containing threaded instructions.\n    return WebAssembly.validate(\n      new Uint8Array([\n        0, 97, 115, 109, 1, 0, 0, 0, 1, 4, 1, 96, 0, 0, 3, 2, 1, 0, 5, 4, 1, 3, 1, 1, 10, 11, 1, 9, 0, 65, 0, 254, 16,\n        2, 0, 26, 11,\n      ]),\n    );\n  } catch {\n    return false;\n  }\n};\n\nconst isSimdSupported = (): boolean => {\n  try {\n    // Test for WebAssembly SIMD capability (for both browsers and Node.js)\n    // This typed array is a WebAssembly program containing SIMD instructions.\n\n    // The binary data is generated from the following code by wat2wasm:\n    //\n    // (module\n    //   (type $t0 (func))\n    //   (func $f0 (type $t0)\n    //     (drop\n    //       (i32x4.dot_i16x8_s\n    //         (i8x16.splat\n    //           (i32.const 0))\n    //         (v128.const i32x4 0x00000000 0x00000000 0x00000000 0x00000000)))))\n\n    return WebAssembly.validate(\n      new Uint8Array([\n        0, 97, 115, 109, 1, 0, 0, 0, 1, 4, 1, 96, 0, 0, 3, 2, 1, 0, 10, 30, 1, 28, 0, 65, 0, 253, 15, 253, 12, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 253, 186, 1, 26, 11,\n      ]),\n    );\n  } catch {\n    return false;\n  }\n};\n\nconst isRelaxedSimdSupported = (): boolean => {\n  try {\n    // Test for WebAssembly Relaxed SIMD capability (for both browsers and Node.js)\n    // This typed array is a WebAssembly program containing Relaxed SIMD instructions.\n\n    // The binary data is generated from the following code by wat2wasm:\n    // (module\n    //   (func (result v128)\n    //      i32.const 1\n    //      i8x16.splat\n    //      i32.const 2\n    //      i8x16.splat\n    //      i32.const 3\n    //      i8x16.splat\n    //      i32x4.relaxed_dot_i8x16_i7x16_add_s\n    //   )\n    //  )\n    return WebAssembly.validate(\n      new Uint8Array([\n        0, 97, 115, 109, 1, 0, 0, 0, 1, 5, 1, 96, 0, 1, 123, 3, 2, 1, 0, 10, 19, 1, 17, 0, 65, 1, 253, 15, 65, 2, 253,\n        15, 65, 3, 253, 15, 253, 147, 2, 11,\n      ]),\n    );\n  } catch {\n    return false;\n  }\n};\n\nexport const initializeWebAssembly = async (flags: Env.WebAssemblyFlags): Promise<void> => {\n  if (initialized) {\n    return Promise.resolve();\n  }\n  if (initializing) {\n    throw new Error(\"multiple calls to 'initializeWebAssembly()' detected.\");\n  }\n  if (aborted) {\n    throw new Error(\"previous call to 'initializeWebAssembly()' failed.\");\n  }\n\n  initializing = true;\n\n  // wasm flags are already initialized\n  const timeout = flags.initTimeout!;\n  let numThreads = flags.numThreads!;\n\n  // ensure SIMD is supported\n  if (flags.simd === false) {\n    // skip SIMD feature checking as it is disabled explicitly by user\n  } else if (flags.simd === 'relaxed') {\n    // check if relaxed SIMD is supported\n    if (!isRelaxedSimdSupported()) {\n      throw new Error('Relaxed WebAssembly SIMD is not supported in the current environment.');\n    }\n  } else if (!isSimdSupported()) {\n    throw new Error('WebAssembly SIMD is not supported in the current environment.');\n  }\n\n  if (BUILD_DEFS.ENABLE_JSPI) {\n    if (!('Suspending' in WebAssembly)) {\n      throw new Error('WebAssembly JSPI is not supported in the current environment.');\n    }\n  }\n\n  // check if multi-threading is supported\n  const multiThreadSupported = isMultiThreadSupported();\n  if (numThreads > 1 && !multiThreadSupported) {\n    if (typeof self !== 'undefined' && !self.crossOriginIsolated) {\n      // eslint-disable-next-line no-console\n      console.warn(\n        'env.wasm.numThreads is set to ' +\n          numThreads +\n          ', but this will not work unless you enable crossOriginIsolated mode. ' +\n          'See https://web.dev/cross-origin-isolation-guide/ for more info.',\n      );\n    }\n\n    // eslint-disable-next-line no-console\n    console.warn(\n      'WebAssembly multi-threading is not supported in the current environment. ' + 'Falling back to single-threading.',\n    );\n\n    // set flags.numThreads to 1 so that OrtInit() will not create a global thread pool.\n    flags.numThreads = numThreads = 1;\n  }\n\n  const wasmPaths = flags.wasmPaths;\n  const wasmPrefixOverride = typeof wasmPaths === 'string' ? wasmPaths : undefined;\n  const mjsPathOverrideFlag = (wasmPaths as Env.WasmFilePaths)?.mjs;\n  const mjsPathOverride = (mjsPathOverrideFlag as URL)?.href ?? mjsPathOverrideFlag;\n  const wasmPathOverrideFlag = (wasmPaths as Env.WasmFilePaths)?.wasm;\n  const wasmPathOverride = (wasmPathOverrideFlag as URL)?.href ?? wasmPathOverrideFlag;\n  const wasmBinaryOverride = flags.wasmBinary;\n\n  const [objectUrl, ortWasmFactory] = await importWasmModule(\n    mjsPathOverride,\n    wasmPrefixOverride,\n    numThreads > 1,\n    !!wasmBinaryOverride || !!wasmPathOverride,\n  );\n\n  let isTimeout = false;\n\n  const tasks: Array<Promise<void>> = [];\n\n  // promise for timeout\n  if (timeout > 0) {\n    tasks.push(\n      new Promise((resolve) => {\n        setTimeout(() => {\n          isTimeout = true;\n          resolve();\n        }, timeout);\n      }),\n    );\n  }\n\n  // promise for module initialization\n  tasks.push(\n    new Promise((resolve, reject) => {\n      const config: Partial<OrtWasmModule> = {\n        /**\n         * The number of threads. WebAssembly will create (Module.numThreads - 1) workers. If it is 1, no worker will be\n         * created.\n         */\n        numThreads,\n      };\n\n      if (wasmBinaryOverride) {\n        // Set a custom buffer which contains the WebAssembly binary. This will skip the wasm file fetching.\n        config.wasmBinary = wasmBinaryOverride as ArrayBuffer;\n\n        // Offer an implementation of locateFile() that returns the file name directly. This helps to avoid an error\n        // thrown later from the following code when `import.meta.url` is a blob URL:\n        // ```\n        //   return new URL(\"ort-wasm-simd-threaded.jsep.wasm\", import.meta.url).href;\n        // ```\n        config.locateFile = (fileName) => fileName;\n      } else if (wasmPathOverride || wasmPrefixOverride) {\n        // A callback function to locate the WebAssembly file. The function should return the full path of the file.\n        //\n        // Since Emscripten 3.1.58, this function is only called for the .wasm file.\n        config.locateFile = (fileName) => wasmPathOverride ?? wasmPrefixOverride + fileName;\n      } else if (mjsPathOverride && mjsPathOverride.indexOf('blob:') !== 0) {\n        // if mjs path is specified, use it as the base path for the .wasm file.\n        config.locateFile = (fileName) => new URL(fileName, mjsPathOverride).href;\n      } else if (objectUrl) {\n        const inferredWasmPathPrefix = inferWasmPathPrefixFromScriptSrc();\n        if (inferredWasmPathPrefix) {\n          // if the wasm module is preloaded, use the inferred wasm path as the base path for the .wasm file.\n          config.locateFile = (fileName) => inferredWasmPathPrefix + fileName;\n        }\n      }\n\n      ortWasmFactory(config).then(\n        // wasm module initialized successfully\n        (module) => {\n          initializing = false;\n          initialized = true;\n          wasm = module;\n          resolve();\n          if (objectUrl) {\n            URL.revokeObjectURL(objectUrl);\n          }\n        },\n        // wasm module failed to initialize\n        (what) => {\n          initializing = false;\n          aborted = true;\n          reject(what);\n        },\n      );\n    }),\n  );\n\n  await Promise.race(tasks);\n\n  if (isTimeout) {\n    throw new Error(`WebAssembly backend initializing failed due to timeout: ${timeout}ms`);\n  }\n};\n\nexport const getInstance = (): OrtWasmModule => {\n  if (initialized && wasm) {\n    return wasm;\n  }\n\n  throw new Error('WebAssembly is not initialized yet.');\n};\n\nexport const dispose = (): void => {\n  if (initialized && !initializing && !aborted) {\n    // TODO: currently \"PThread.terminateAllThreads()\" is not exposed in the wasm module.\n    //       And this function is not yet called by any code.\n    //       If it is needed in the future, we should expose it in the wasm module and uncomment the following line.\n\n    // wasm?.PThread?.terminateAllThreads();\n    wasm = undefined;\n\n    initializing = false;\n    initialized = false;\n    aborted = true;\n  }\n};\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { getInstance } from './wasm-factory';\n\nexport const allocWasmString = (data: string, allocs: number[]): number => {\n  const wasm = getInstance();\n\n  const dataLength = wasm.lengthBytesUTF8(data) + 1;\n  const dataOffset = wasm._malloc(dataLength);\n  wasm.stringToUTF8(data, dataOffset, dataLength);\n  allocs.push(dataOffset);\n\n  return dataOffset;\n};\n\ninterface ExtraOptionsHandler {\n  (name: string, value: string): void;\n}\n\nexport const iterateExtraOptions = (\n  options: Record<string, unknown>,\n  prefix: string,\n  seen: WeakSet<Record<string, unknown>>,\n  handler: ExtraOptionsHandler,\n): void => {\n  if (typeof options == 'object' && options !== null) {\n    if (seen.has(options)) {\n      throw new Error('Circular reference in options');\n    } else {\n      seen.add(options);\n    }\n  }\n\n  Object.entries(options).forEach(([key, value]) => {\n    const name = prefix ? prefix + key : key;\n    if (typeof value === 'object') {\n      iterateExtraOptions(value as Record<string, unknown>, name + '.', seen, handler);\n    } else if (typeof value === 'string' || typeof value === 'number') {\n      handler(name, value.toString());\n    } else if (typeof value === 'boolean') {\n      handler(name, value ? '1' : '0');\n    } else {\n      throw new Error(`Can't handle extra config type: ${typeof value}`);\n    }\n  });\n};\n\n/**\n * check web assembly API's last error and throw error if any error occurred.\n * @param message a message used when an error occurred.\n */\nexport const checkLastError = (message: string): void => {\n  const wasm = getInstance();\n\n  const stack = wasm.stackSave();\n  try {\n    const ptrSize = wasm.PTR_SIZE;\n    const paramsOffset = wasm.stackAlloc(2 * ptrSize);\n    wasm._OrtGetLastError(paramsOffset, paramsOffset + ptrSize);\n    const errorCode = Number(wasm.getValue(paramsOffset, ptrSize === 4 ? 'i32' : 'i64'));\n    const errorMessagePointer = wasm.getValue(paramsOffset + ptrSize, '*');\n    const errorMessage = errorMessagePointer ? wasm.UTF8ToString(errorMessagePointer) : '';\n    throw new Error(`${message} ERROR_CODE: ${errorCode}, ERROR_MESSAGE: ${errorMessage}`);\n  } finally {\n    wasm.stackRestore(stack);\n  }\n};\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { InferenceSession } from 'onnxruntime-common';\n\nimport { getInstance } from './wasm-factory';\nimport { allocWasmString, checkLastError, iterateExtraOptions } from './wasm-utils';\n\nexport const setRunOptions = (options: InferenceSession.RunOptions): [number, number[]] => {\n  const wasm = getInstance();\n  let runOptionsHandle = 0;\n  const allocs: number[] = [];\n\n  const runOptions: InferenceSession.RunOptions = options || {};\n\n  try {\n    if (options?.logSeverityLevel === undefined) {\n      runOptions.logSeverityLevel = 2; // Default to warning\n    } else if (\n      typeof options.logSeverityLevel !== 'number' ||\n      !Number.isInteger(options.logSeverityLevel) ||\n      options.logSeverityLevel < 0 ||\n      options.logSeverityLevel > 4\n    ) {\n      throw new Error(`log severity level is not valid: ${options.logSeverityLevel}`);\n    }\n\n    if (options?.logVerbosityLevel === undefined) {\n      runOptions.logVerbosityLevel = 0; // Default to 0\n    } else if (typeof options.logVerbosityLevel !== 'number' || !Number.isInteger(options.logVerbosityLevel)) {\n      throw new Error(`log verbosity level is not valid: ${options.logVerbosityLevel}`);\n    }\n\n    if (options?.terminate === undefined) {\n      runOptions.terminate = false;\n    }\n\n    let tagDataOffset = 0;\n    if (options?.tag !== undefined) {\n      tagDataOffset = allocWasmString(options.tag, allocs);\n    }\n\n    runOptionsHandle = wasm._OrtCreateRunOptions(\n      runOptions.logSeverityLevel!,\n      runOptions.logVerbosityLevel!,\n      !!runOptions.terminate!,\n      tagDataOffset,\n    );\n    if (runOptionsHandle === 0) {\n      checkLastError(\"Can't create run options.\");\n    }\n\n    if (options?.extra !== undefined) {\n      iterateExtraOptions(options.extra, '', new WeakSet<Record<string, unknown>>(), (key, value) => {\n        const keyDataOffset = allocWasmString(key, allocs);\n        const valueDataOffset = allocWasmString(value, allocs);\n\n        if (wasm._OrtAddRunConfigEntry(runOptionsHandle, keyDataOffset, valueDataOffset) !== 0) {\n          checkLastError(`Can't set a run config entry: ${key} - ${value}.`);\n        }\n      });\n    }\n\n    return [runOptionsHandle, allocs];\n  } catch (e) {\n    if (runOptionsHandle !== 0) {\n      wasm._OrtReleaseRunOptions(runOptionsHandle);\n    }\n    allocs.forEach((alloc) => wasm._free(alloc));\n    throw e;\n  }\n};\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport type { InferenceSession } from 'onnxruntime-common';\n\nimport { getInstance } from './wasm-factory';\nimport { allocWasmString, checkLastError, iterateExtraOptions } from './wasm-utils';\n\nconst getGraphOptimzationLevel = (graphOptimizationLevel: string | unknown): number => {\n  switch (graphOptimizationLevel) {\n    case 'disabled':\n      return 0;\n    case 'basic':\n      return 1;\n    case 'extended':\n      return 2;\n    case 'layout':\n      return 3;\n    case 'all':\n      return 99;\n    default:\n      throw new Error(`unsupported graph optimization level: ${graphOptimizationLevel}`);\n  }\n};\n\nconst getExecutionMode = (executionMode: 'sequential' | 'parallel'): number => {\n  switch (executionMode) {\n    case 'sequential':\n      return 0;\n    case 'parallel':\n      return 1;\n    default:\n      throw new Error(`unsupported execution mode: ${executionMode}`);\n  }\n};\n\nconst appendDefaultOptions = (options: InferenceSession.SessionOptions): void => {\n  if (!options.extra) {\n    options.extra = {};\n  }\n  if (!options.extra.session) {\n    options.extra.session = {};\n  }\n  const session = options.extra.session as Record<string, string>;\n  if (!session.use_ort_model_bytes_directly) {\n    // eslint-disable-next-line camelcase\n    session.use_ort_model_bytes_directly = '1';\n  }\n\n  // if using JSEP with WebGPU, always disable memory pattern\n  if (\n    options.executionProviders &&\n    options.executionProviders.some((ep) => (typeof ep === 'string' ? ep : ep.name) === 'webgpu')\n  ) {\n    options.enableMemPattern = false;\n  }\n};\n\nconst appendSessionConfig = (sessionOptionsHandle: number, key: string, value: string, allocs: number[]): void => {\n  const keyDataOffset = allocWasmString(key, allocs);\n  const valueDataOffset = allocWasmString(value, allocs);\n  if (getInstance()._OrtAddSessionConfigEntry(sessionOptionsHandle, keyDataOffset, valueDataOffset) !== 0) {\n    checkLastError(`Can't set a session config entry: ${key} - ${value}.`);\n  }\n};\n\nconst appendEpOption = (epOptions: Array<[number, number]>, key: string, value: string, allocs: number[]): void => {\n  const keyDataOffset = allocWasmString(key, allocs);\n  const valueDataOffset = allocWasmString(value, allocs);\n  epOptions.push([keyDataOffset, valueDataOffset]);\n};\n\nconst setExecutionProviders = async (\n  sessionOptionsHandle: number,\n  sessionOptions: InferenceSession.SessionOptions,\n  allocs: number[],\n): Promise<void> => {\n  const executionProviders = sessionOptions.executionProviders!;\n  for (const ep of executionProviders) {\n    let epName = typeof ep === 'string' ? ep : ep.name;\n    const epOptions: Array<[number, number]> = [];\n\n    // check EP name\n    switch (epName) {\n      case 'webnn':\n        epName = 'WEBNN';\n        // Disable QDQ fusion so DQ/Q nodes are preserved as individual ops for WebNN EP.\n        appendSessionConfig(sessionOptionsHandle, 'session.disable_quant_qdq', '1', allocs);\n        // Forcibly prevent constant folding from replacing DQ nodes with constants.\n        appendSessionConfig(sessionOptionsHandle, 'session.disable_qdq_constant_folding', '1', allocs);\n        if (typeof ep !== 'string') {\n          const webnnOptions = ep as InferenceSession.WebNNExecutionProviderOption;\n          // const context = (webnnOptions as InferenceSession.WebNNOptionsWithMLContext)?.context;\n          const deviceType = (webnnOptions as InferenceSession.WebNNContextOptions)?.deviceType;\n          if (deviceType) {\n            appendSessionConfig(sessionOptionsHandle, 'deviceType', deviceType, allocs);\n          }\n        }\n        break;\n      case 'webgpu':\n        if (!BUILD_DEFS.DISABLE_WEBGPU) {\n          epName = 'WebGPU';\n          let customDevice: GPUDevice | undefined;\n\n          if (typeof ep !== 'string') {\n            const webgpuOptions = ep as InferenceSession.WebGpuExecutionProviderOption;\n\n            // set custom GPU device\n            if (webgpuOptions.device) {\n              if (typeof GPUDevice !== 'undefined' && webgpuOptions.device instanceof GPUDevice) {\n                customDevice = webgpuOptions.device;\n              } else {\n                throw new Error('Invalid GPU device set in WebGPU EP options.');\n              }\n            }\n\n            // set graph capture option from session options\n            const { enableGraphCapture } = sessionOptions;\n            if (typeof enableGraphCapture === 'boolean' && enableGraphCapture) {\n              appendEpOption(epOptions, 'enableGraphCapture', '1', allocs);\n            }\n\n            // set layout option\n            if (typeof webgpuOptions.preferredLayout === 'string') {\n              appendEpOption(epOptions, 'preferredLayout', webgpuOptions.preferredLayout, allocs);\n            }\n\n            // set force CPU fallback nodes\n            if (webgpuOptions.forceCpuNodeNames) {\n              const names = Array.isArray(webgpuOptions.forceCpuNodeNames)\n                ? webgpuOptions.forceCpuNodeNames\n                : [webgpuOptions.forceCpuNodeNames];\n\n              appendEpOption(epOptions, 'forceCpuNodeNames', names.join('\\n'), allocs);\n            }\n\n            // set validation mode\n            if (webgpuOptions.validationMode) {\n              appendEpOption(epOptions, 'validationMode', webgpuOptions.validationMode, allocs);\n            }\n\n            // set buffer cache modes\n            for (const key of [\n              'storageBufferCacheMode',\n              'uniformBufferCacheMode',\n              'queryResolveBufferCacheMode',\n              'defaultBufferCacheMode',\n            ] as const) {\n              const mode = webgpuOptions[key];\n              if (mode) {\n                if (mode !== 'disabled' && mode !== 'lazyRelease' && mode !== 'simple' && mode !== 'bucket') {\n                  throw new Error(`${key} must be one of 'disabled', 'lazyRelease', 'simple' or 'bucket': ${mode}`);\n                }\n                appendEpOption(epOptions, key, mode, allocs);\n              }\n            }\n          }\n\n          const info = getInstance().webgpuRegisterDevice!(customDevice);\n          if (info) {\n            const [deviceId, instanceHandle, deviceHandle] = info;\n            appendEpOption(epOptions, 'deviceId', deviceId.toString(), allocs);\n            appendEpOption(epOptions, 'webgpuInstance', instanceHandle.toString(), allocs);\n            appendEpOption(epOptions, 'webgpuDevice', deviceHandle.toString(), allocs);\n          }\n        } else {\n          epName = 'JS';\n          if (typeof ep !== 'string') {\n            const webgpuOptions = ep as InferenceSession.WebGpuExecutionProviderOption;\n            if (webgpuOptions?.preferredLayout) {\n              if (webgpuOptions.preferredLayout !== 'NCHW' && webgpuOptions.preferredLayout !== 'NHWC') {\n                throw new Error(`preferredLayout must be either 'NCHW' or 'NHWC': ${webgpuOptions.preferredLayout}`);\n              }\n              appendSessionConfig(sessionOptionsHandle, 'preferredLayout', webgpuOptions.preferredLayout, allocs);\n            }\n          }\n        }\n        break;\n      case 'wasm':\n      case 'cpu':\n        continue;\n      default:\n        throw new Error(`not supported execution provider: ${epName}`);\n    }\n\n    const epNameDataOffset = allocWasmString(epName, allocs);\n    const epOptionsCount = epOptions.length;\n    let keysOffset = 0;\n    let valuesOffset = 0;\n    if (epOptionsCount > 0) {\n      keysOffset = getInstance()._malloc(epOptionsCount * getInstance().PTR_SIZE);\n      allocs.push(keysOffset);\n      valuesOffset = getInstance()._malloc(epOptionsCount * getInstance().PTR_SIZE);\n      allocs.push(valuesOffset);\n      for (let i = 0; i < epOptionsCount; i++) {\n        getInstance().setValue(keysOffset + i * getInstance().PTR_SIZE, epOptions[i][0], '*');\n        getInstance().setValue(valuesOffset + i * getInstance().PTR_SIZE, epOptions[i][1], '*');\n      }\n    }\n    if (\n      (await getInstance()._OrtAppendExecutionProvider(\n        sessionOptionsHandle,\n        epNameDataOffset,\n        keysOffset,\n        valuesOffset,\n        epOptionsCount,\n      )) !== 0\n    ) {\n      checkLastError(`Can't append execution provider: ${epName}.`);\n    }\n  }\n};\n\nexport const setSessionOptions = async (options?: InferenceSession.SessionOptions): Promise<[number, number[]]> => {\n  const wasm = getInstance();\n  let sessionOptionsHandle = 0;\n  const allocs: number[] = [];\n\n  const sessionOptions: InferenceSession.SessionOptions = options || {};\n  appendDefaultOptions(sessionOptions);\n\n  try {\n    const graphOptimizationLevel = getGraphOptimzationLevel(sessionOptions.graphOptimizationLevel ?? 'all');\n    const executionMode = getExecutionMode(sessionOptions.executionMode ?? 'sequential');\n    const logIdDataOffset =\n      typeof sessionOptions.logId === 'string' ? allocWasmString(sessionOptions.logId, allocs) : 0;\n\n    const logSeverityLevel = sessionOptions.logSeverityLevel ?? 2; // Default to 2 - warning\n    if (!Number.isInteger(logSeverityLevel) || logSeverityLevel < 0 || logSeverityLevel > 4) {\n      throw new Error(`log severity level is not valid: ${logSeverityLevel}`);\n    }\n\n    const logVerbosityLevel = sessionOptions.logVerbosityLevel ?? 0; // Default to 0 - verbose\n    if (!Number.isInteger(logVerbosityLevel) || logVerbosityLevel < 0 || logVerbosityLevel > 4) {\n      throw new Error(`log verbosity level is not valid: ${logVerbosityLevel}`);\n    }\n\n    const optimizedModelFilePathOffset =\n      typeof sessionOptions.optimizedModelFilePath === 'string'\n        ? allocWasmString(sessionOptions.optimizedModelFilePath, allocs)\n        : 0;\n\n    sessionOptionsHandle = wasm._OrtCreateSessionOptions(\n      graphOptimizationLevel,\n      !!sessionOptions.enableCpuMemArena,\n      !!sessionOptions.enableMemPattern,\n      executionMode,\n      !!sessionOptions.enableProfiling,\n      0,\n      logIdDataOffset,\n      logSeverityLevel,\n      logVerbosityLevel,\n      optimizedModelFilePathOffset,\n    );\n    if (sessionOptionsHandle === 0) {\n      checkLastError(\"Can't create session options.\");\n    }\n\n    if (sessionOptions.executionProviders) {\n      await setExecutionProviders(sessionOptionsHandle, sessionOptions, allocs);\n    }\n\n    if (sessionOptions.enableGraphCapture !== undefined) {\n      if (typeof sessionOptions.enableGraphCapture !== 'boolean') {\n        throw new Error(`enableGraphCapture must be a boolean value: ${sessionOptions.enableGraphCapture}`);\n      }\n      appendSessionConfig(\n        sessionOptionsHandle,\n        'enableGraphCapture',\n        sessionOptions.enableGraphCapture.toString(),\n        allocs,\n      );\n    }\n\n    if (sessionOptions.freeDimensionOverrides) {\n      for (const [name, value] of Object.entries(sessionOptions.freeDimensionOverrides)) {\n        if (typeof name !== 'string') {\n          throw new Error(`free dimension override name must be a string: ${name}`);\n        }\n        if (typeof value !== 'number' || !Number.isInteger(value) || value < 0) {\n          throw new Error(`free dimension override value must be a non-negative integer: ${value}`);\n        }\n        const nameOffset = allocWasmString(name, allocs);\n        if (wasm._OrtAddFreeDimensionOverride(sessionOptionsHandle, nameOffset, value) !== 0) {\n          checkLastError(`Can't set a free dimension override: ${name} - ${value}.`);\n        }\n      }\n    }\n\n    if (sessionOptions.extra !== undefined) {\n      iterateExtraOptions(sessionOptions.extra, '', new WeakSet<Record<string, unknown>>(), (key, value) => {\n        appendSessionConfig(sessionOptionsHandle, key, value, allocs);\n      });\n    }\n\n    return [sessionOptionsHandle, allocs];\n  } catch (e) {\n    if (sessionOptionsHandle !== 0) {\n      if (wasm._OrtReleaseSessionOptions(sessionOptionsHandle) !== 0) {\n        checkLastError(\"Can't release session options.\");\n      }\n    }\n    allocs.forEach((alloc) => wasm._free(alloc));\n    throw e;\n  }\n};\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { Tensor } from 'onnxruntime-common';\n\n// This file includes common definitions. They do NOT have dependency on the WebAssembly instance.\n\n/**\n * Copied from ONNX definition. Use this to drop dependency 'onnx_proto' to decrease compiled .js file size.\n */\nexport const enum DataType {\n  undefined = 0,\n  float = 1,\n  uint8 = 2,\n  int8 = 3,\n  uint16 = 4,\n  int16 = 5,\n  int32 = 6,\n  int64 = 7,\n  string = 8,\n  bool = 9,\n  float16 = 10,\n  double = 11,\n  uint32 = 12,\n  uint64 = 13,\n  complex64 = 14,\n  complex128 = 15,\n  bfloat16 = 16,\n\n  // 4-bit data-types\n  uint4 = 21,\n  int4 = 22,\n}\n\n/**\n * Map string tensor data to enum value\n */\nexport const tensorDataTypeStringToEnum = (type: string): DataType => {\n  switch (type) {\n    case 'int8':\n      return DataType.int8;\n    case 'uint8':\n      return DataType.uint8;\n    case 'bool':\n      return DataType.bool;\n    case 'int16':\n      return DataType.int16;\n    case 'uint16':\n      return DataType.uint16;\n    case 'int32':\n      return DataType.int32;\n    case 'uint32':\n      return DataType.uint32;\n    case 'float16':\n      return DataType.float16;\n    case 'float32':\n      return DataType.float;\n    case 'float64':\n      return DataType.double;\n    case 'string':\n      return DataType.string;\n    case 'int64':\n      return DataType.int64;\n    case 'uint64':\n      return DataType.uint64;\n    case 'int4':\n      return DataType.int4;\n    case 'uint4':\n      return DataType.uint4;\n\n    default:\n      throw new Error(`unsupported data type: ${type}`);\n  }\n};\n\n/**\n * Map enum value to string tensor data\n */\nexport const tensorDataTypeEnumToString = (typeProto: DataType): Tensor.Type => {\n  switch (typeProto) {\n    case DataType.int8:\n      return 'int8';\n    case DataType.uint8:\n      return 'uint8';\n    case DataType.bool:\n      return 'bool';\n    case DataType.int16:\n      return 'int16';\n    case DataType.uint16:\n      return 'uint16';\n    case DataType.int32:\n      return 'int32';\n    case DataType.uint32:\n      return 'uint32';\n    case DataType.float16:\n      return 'float16';\n    case DataType.float:\n      return 'float32';\n    case DataType.double:\n      return 'float64';\n    case DataType.string:\n      return 'string';\n    case DataType.int64:\n      return 'int64';\n    case DataType.uint64:\n      return 'uint64';\n    case DataType.int4:\n      return 'int4';\n    case DataType.uint4:\n      return 'uint4';\n\n    default:\n      throw new Error(`unsupported data type: ${typeProto}`);\n  }\n};\n\n/**\n * get tensor size in bytes by the given data type and dimensions\n * @returns size in integer or undefined if the data type is not supported\n */\nexport const calculateTensorSizeInBytes = (\n  dateType: number,\n  dimsOrSize: readonly number[] | number,\n): number | undefined => {\n  const elementSize = [\n    -1, // undefined = 0\n    4, // float = 1\n    1, // uint8 = 2\n    1, // int8 = 3\n    2, // uint16 = 4\n    2, // int16 = 5\n    4, // int32 = 6\n    8, // int64 = 7\n    -1, // string = 8\n    1, // bool = 9\n    2, // float16 = 10\n    8, // double = 11\n    4, // uint32 = 12\n    8, // uint64 = 13\n    -1, // complex64 = 14\n    -1, // complex128 = 15\n    -1, // bfloat16 = 16\n    -1, // FLOAT8E4M3FN = 17\n    -1, // FLOAT8E4M3FNUZ = 18\n    -1, // FLOAT8E5M2 = 19\n    -1, // FLOAT8E5M2FNUZ = 20\n    0.5, // uint4 = 21\n    0.5, // int4 = 22\n  ][dateType];\n\n  const size = typeof dimsOrSize === 'number' ? dimsOrSize : dimsOrSize.reduce((a, b) => a * b, 1);\n  return elementSize > 0 ? Math.ceil(size * elementSize) : undefined;\n};\n\n/**\n * get typed array constructor by the given tensor type\n */\nexport const tensorTypeToTypedArrayConstructor = (\n  type: Tensor.Type,\n):\n  | Float32ArrayConstructor\n  | Uint8ArrayConstructor\n  | Int8ArrayConstructor\n  | Uint16ArrayConstructor\n  | Int16ArrayConstructor\n  | Int32ArrayConstructor\n  | BigInt64ArrayConstructor\n  | Uint8ArrayConstructor\n  | Float64ArrayConstructor\n  | Uint32ArrayConstructor\n  | BigUint64ArrayConstructor => {\n  switch (type) {\n    case 'float16':\n      // Float16 tensor data is stored as raw 16-bit values. Prefer a native or polyfilled Float16Array when\n      // available so callers can work with float16 values directly; otherwise fall back to Uint16Array storage.\n      return typeof Float16Array !== 'undefined' ? (Float16Array as unknown as Uint16ArrayConstructor) : Uint16Array;\n    case 'float32':\n      return Float32Array;\n    case 'uint8':\n      return Uint8Array;\n    case 'int8':\n      return Int8Array;\n    case 'uint16':\n      return Uint16Array;\n    case 'int16':\n      return Int16Array;\n    case 'int32':\n      return Int32Array;\n    case 'bool':\n      return Uint8Array;\n    case 'float64':\n      return Float64Array;\n    case 'uint32':\n      return Uint32Array;\n    case 'int64':\n      return BigInt64Array;\n    case 'uint64':\n      return BigUint64Array;\n    default:\n      throw new Error(`unsupported type: ${type}`);\n  }\n};\n\n/**\n * Map string log level to integer value\n */\nexport const logLevelStringToEnum = (logLevel?: 'verbose' | 'info' | 'warning' | 'error' | 'fatal'): number => {\n  switch (logLevel) {\n    case 'verbose':\n      return 0;\n    case 'info':\n      return 1;\n    case 'warning':\n      return 2;\n    case 'error':\n      return 3;\n    case 'fatal':\n      return 4;\n    default:\n      throw new Error(`unsupported logging level: ${logLevel}`);\n  }\n};\n\n/**\n * Check whether the given tensor type is supported by GPU buffer\n */\nexport const isGpuBufferSupportedType = (type: Tensor.Type): type is Tensor.GpuBufferDataTypes =>\n  type === 'float32' ||\n  type === 'float16' ||\n  type === 'int32' ||\n  type === 'int64' ||\n  type === 'uint32' ||\n  type === 'uint8' ||\n  type === 'bool' ||\n  type === 'uint4' ||\n  type === 'int4';\n\n/**\n * Check whether the given tensor type is supported by WebNN MLTensor\n */\nexport const isMLTensorSupportedType = (type: Tensor.Type): type is Tensor.MLTensorDataTypes =>\n  type === 'float32' ||\n  type === 'float16' ||\n  type === 'int32' ||\n  type === 'int64' ||\n  type === 'uint32' ||\n  type === 'uint64' ||\n  type === 'int8' ||\n  type === 'uint8' ||\n  type === 'bool' ||\n  type === 'uint4' ||\n  type === 'int4';\n\n/**\n * Map string data location to integer value\n */\nexport const dataLocationStringToEnum = (location: Tensor.DataLocation): number => {\n  switch (location) {\n    case 'none':\n      return 0;\n    case 'cpu':\n      return 1;\n    case 'cpu-pinned':\n      return 2;\n    case 'texture':\n      return 3;\n    case 'gpu-buffer':\n      return 4;\n    case 'ml-tensor':\n      return 5;\n    default:\n      throw new Error(`unsupported data location: ${location}`);\n  }\n};\n\n/**\n * Map integer data location to string value\n */\nexport const dataLocationEnumToString = (location: number): Tensor.DataLocation | undefined =>\n  (['none', 'cpu', 'cpu-pinned', 'texture', 'gpu-buffer', 'ml-tensor'] as const)[location];\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { isNode } from './wasm-utils-env';\n\n/**\n * Load a file into a Uint8Array.\n *\n * @param file - the file to load. Can be a URL/path, a Blob, an ArrayBuffer, or a Uint8Array.\n * @returns a Uint8Array containing the file data.\n */\nexport const loadFile = async (file: string | Blob | ArrayBufferLike | Uint8Array): Promise<Uint8Array> => {\n  if (typeof file === 'string') {\n    if (isNode) {\n      // load file into ArrayBuffer in Node.js\n      try {\n        const { readFile } = require('node:fs/promises');\n        return new Uint8Array(await readFile(file));\n      } catch (e) {\n        if (e.code === 'ERR_FS_FILE_TOO_LARGE') {\n          // file is too large, use fs.createReadStream instead\n          const { createReadStream } = require('node:fs');\n          const stream = createReadStream(file);\n          const chunks: Uint8Array[] = [];\n          for await (const chunk of stream) {\n            chunks.push(chunk);\n          }\n          return new Uint8Array(Buffer.concat(chunks));\n        }\n        throw e;\n      }\n    } else {\n      // load file into ArrayBuffer in browsers\n      const response = await fetch(file);\n      if (!response.ok) {\n        throw new Error(`failed to load external data file: ${file}`);\n      }\n      const contentLengthHeader = response.headers.get('Content-Length');\n      const fileSize = contentLengthHeader ? parseInt(contentLengthHeader, 10) : 0;\n      if (fileSize < 1073741824 /* 1GB */) {\n        // when Content-Length header is not set, we cannot determine the file size. We assume it is small enough to\n        // load into memory.\n        return new Uint8Array(await response.arrayBuffer());\n      } else {\n        // file is too large, use stream instead\n        if (!response.body) {\n          throw new Error(`failed to load external data file: ${file}, no response body.`);\n        }\n        const reader = response.body.getReader();\n\n        let buffer;\n        try {\n          // try to create ArrayBuffer directly\n          buffer = new ArrayBuffer(fileSize);\n        } catch (e) {\n          if (e instanceof RangeError) {\n            // use WebAssembly Memory to allocate larger ArrayBuffer\n            const pages = Math.ceil(fileSize / 65536);\n            buffer = new WebAssembly.Memory({ initial: pages, maximum: pages }).buffer;\n          } else {\n            throw e;\n          }\n        }\n\n        let offset = 0;\n        while (true) {\n          const { done, value } = await reader.read();\n          if (done) {\n            break;\n          }\n          const chunkSize = value.byteLength;\n          const chunk = new Uint8Array(buffer, offset, chunkSize);\n          chunk.set(value);\n          offset += chunkSize;\n        }\n        return new Uint8Array(buffer, 0, fileSize);\n      }\n    }\n  } else if (file instanceof Blob) {\n    return new Uint8Array(await file.arrayBuffer());\n  } else if (file instanceof Uint8Array) {\n    return file;\n  } else {\n    return new Uint8Array(file);\n  }\n};\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\n// WebNN API currently does not have a TypeScript definition file. This file is a workaround with types generated from\n// WebNN API specification.\n// https://github.com/webmachinelearning/webnn/issues/677\n/// <reference path=\"jsep/webnn/webnn.d.ts\" />\n\nimport { Env, InferenceSession, Tensor, TRACE_EVENT_BEGIN, TRACE_EVENT_END } from 'onnxruntime-common';\n\nimport {\n  SerializableInternalBuffer,\n  SerializableSessionMetadata,\n  SerializableTensorMetadata,\n  TensorMetadata,\n} from './proxy-messages';\nimport { setRunOptions } from './run-options';\nimport { setSessionOptions } from './session-options';\nimport {\n  calculateTensorSizeInBytes,\n  dataLocationStringToEnum,\n  isGpuBufferSupportedType,\n  isMLTensorSupportedType,\n  logLevelStringToEnum,\n  tensorDataTypeEnumToString,\n  tensorDataTypeStringToEnum,\n  tensorTypeToTypedArrayConstructor,\n} from './wasm-common';\nimport { getInstance } from './wasm-factory';\nimport { allocWasmString, checkLastError } from './wasm-utils';\nimport { loadFile } from './wasm-utils-load-file';\n\n// #region Initializations\n\n/**\n * There are 4 different \"initialization\" steps for ORT. They happen in different places and different time.\n *\n * 1. JavaScript initialization for onnxruntime-common and onnxruntime-web.\n *    This is the first initialization step. In this step, onnxruntime-web calls onnxruntime-common's registerBackend()\n * function multiple times to register all the available backends. The backend registration is very fast. It only\n * registers the backend name with the uninitialized backend object. No heavy initialization is done in this step.\n *    Refer to web/lib/index.ts for the backend registration.\n *\n * 2. WebAssembly artifact initialization.\n *    This happens when any registered wasm backend is used for the first time (ie. `ort.InferenceSession.create()` is\n * called). In this step, onnxruntime-web does the followings:\n *     - create a proxy worker and make sure the proxy worker is ready to receive messages, if proxy is enabled.\n *     - perform feature detection, locate correct WebAssembly artifact path and call the Emscripten generated\n * JavaScript code to initialize the WebAssembly runtime.\n *         - if proxy is enabled, this step happens in the proxy worker using message 'init-wasm'.\n *         - downloading the 'ort-wasm{...}.wasm' file is done in this step.\n *         - if multi-thread is enabled, one or more webworker will be created to initialize the PThread threadpool.\n *\n * 3. ORT environment initialization.\n *    This happens after step 2. In this step, onnxruntime-web performs ONNX Runtime environment initialization.\n * Function `_OrtInit()` is called in this step.\n *     - if proxy is enabled, this step happens in the proxy worker using message 'init-ort'.\n *     - logging level (ort.env.logLevel) and thread number (ort.env.wasm.numThreads) are set in this step.\n *\n * 4. Session initialization.\n *    This happens when `ort.InferenceSession.create()` is called. Unlike the first 3 steps (they only called once),\n * this step will be done for each session. In this step, onnxruntime-web does the followings:\n *    If the parameter is a URL:\n *    - download the model data from the URL.\n *    - copy the model data to the WASM heap. (proxy: 'copy-from')\n *    - dereference the model buffer. This step allows the original ArrayBuffer to be garbage collected.\n *    - call `_OrtCreateSession()` to create the session. (proxy: 'create')\n *\n *    If the parameter is a Uint8Array object:\n *    - copy the model data to the WASM heap. (proxy: 'copy-from')\n *    - call `_OrtCreateSession()` to create the session. (proxy: 'create')\n *\n *\n */\n\n/**\n * initialize ORT environment.\n *\n * @param numThreads SetGlobalIntraOpNumThreads(numThreads)\n * @param loggingLevel CreateEnv(static_cast<OrtLoggingLevel>(logging_level))\n */\nconst initOrt = (numThreads: number, loggingLevel: number): void => {\n  const errorCode = getInstance()._OrtInit(numThreads, loggingLevel);\n  if (errorCode !== 0) {\n    checkLastError(\"Can't initialize onnxruntime.\");\n  }\n};\n\n/**\n * initialize runtime environment.\n * @param env passed in the environment config object.\n */\nexport const initRuntime = async (env: Env): Promise<void> => {\n  // init ORT\n  initOrt(env.wasm.numThreads!, logLevelStringToEnum(env.logLevel));\n};\n\n/**\n * perform EP specific initialization.\n *\n * @param env\n * @param epName\n */\nexport const initEp = async (env: Env, epName: string): Promise<void> => {\n  // initialize ASYNCIFY support\n  getInstance().asyncInit?.();\n\n  // perform WebGPU availability check ( either JSEP or WebGPU EP )\n  let webgpuAdapter: GPUAdapter | null = env.webgpu.adapter;\n  if (epName === 'webgpu') {\n    if (typeof navigator === 'undefined' || !navigator.gpu) {\n      throw new Error('WebGPU is not supported in current environment');\n    }\n    if (!webgpuAdapter) {\n      // if adapter is not set, request a new adapter.\n      const powerPreference = env.webgpu.powerPreference;\n      if (powerPreference !== undefined && powerPreference !== 'low-power' && powerPreference !== 'high-performance') {\n        throw new Error(`Invalid powerPreference setting: \"${powerPreference}\"`);\n      }\n      const forceFallbackAdapter = env.webgpu.forceFallbackAdapter;\n      if (forceFallbackAdapter !== undefined && typeof forceFallbackAdapter !== 'boolean') {\n        throw new Error(`Invalid forceFallbackAdapter setting: \"${forceFallbackAdapter}\"`);\n      }\n      webgpuAdapter = await navigator.gpu.requestAdapter({ powerPreference, forceFallbackAdapter });\n      if (!webgpuAdapter) {\n        throw new Error(\n          'Failed to get GPU adapter. ' +\n            'You may need to enable flag \"--enable-unsafe-webgpu\" if you are using Chrome.',\n        );\n      }\n    } else {\n      // if adapter is set, validate it.\n      if (\n        typeof webgpuAdapter.limits !== 'object' ||\n        typeof webgpuAdapter.features !== 'object' ||\n        typeof webgpuAdapter.requestDevice !== 'function'\n      ) {\n        throw new Error('Invalid GPU adapter set in `env.webgpu.adapter`. It must be a GPUAdapter object.');\n      }\n    }\n  }\n\n  // perform WebNN availability check ( either JSEP or WebNN EP )\n  if (epName === 'webnn') {\n    if (typeof navigator === 'undefined' || !(navigator as unknown as { ml: unknown }).ml) {\n      throw new Error('WebNN is not supported in current environment');\n    }\n  }\n\n  if (!BUILD_DEFS.DISABLE_JSEP) {\n    // eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires\n    const initJsep = require('./jsep/init').init;\n\n    if (epName === 'webgpu') {\n      await initJsep('webgpu', getInstance(), env, webgpuAdapter);\n    }\n    if (epName === 'webnn') {\n      await initJsep('webnn', getInstance(), env);\n    }\n  } else {\n    if (!BUILD_DEFS.DISABLE_WEBGPU && epName === 'webgpu') {\n      getInstance().webgpuInit!((device) => {\n        env.webgpu.device = device;\n      });\n    }\n    if (!BUILD_DEFS.DISABLE_WEBNN && epName === 'webnn') {\n      // eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires\n      const backend = new (require('./jsep/backend-webnn').WebNNBackend)(env);\n      getInstance().webnnInit!([\n        backend,\n        // webnnReserveTensorId\n        () => backend.reserveTensorId(),\n        // webnnReleaseTensorId,\n        (tensorId: number) => backend.releaseTensorId(tensorId),\n        // webnnEnsureTensor\n        async (sessionId: number | undefined, tensorId: number, onnxDataType: number, shape: number[], copyOld) =>\n          backend.ensureTensor(sessionId, tensorId, onnxDataType, shape, copyOld),\n        // webnnUploadTensor\n        (tensorId: number, data: Uint8Array) => {\n          backend.uploadTensor(tensorId, data);\n        },\n        // webnnDownloadTensor\n        async (tensorId: number, dstBuffer: ArrayBufferView | ArrayBuffer) =>\n          backend.downloadTensor(tensorId, dstBuffer),\n        // webnnRegisterMLContext\n        (sessionId: number, mlContext: MLContext) => backend.registerMLContext(sessionId, mlContext),\n        // webnnEnableTraceEvent\n        !!env.trace,\n      ]);\n    }\n  }\n};\n\n// #endregion Initializations\n\n/**\n * valid data locations for input/output tensors.\n */\ntype SupportedTensorDataLocationForInputOutput =\n  | 'cpu'\n  | 'cpu-pinned'\n  | 'gpu-buffer'\n  | 'ml-tensor'\n  // Use 'ml-tensor' during inference, but output a tensor located on the CPU.\n  | 'ml-tensor-cpu-output';\n\ntype IOBindingState = {\n  /**\n   * the handle of IO binding.\n   */\n  readonly handle: number;\n\n  /**\n   * the preferred location for each output tensor.\n   *\n   * value is one of 'cpu', 'cpu-pinned', 'gpu-buffer', 'ml-tensor'.\n   */\n  readonly outputPreferredLocations: readonly SupportedTensorDataLocationForInputOutput[];\n\n  /**\n   * enum value of the preferred location for each output tensor.\n   */\n  readonly outputPreferredLocationsEncoded: readonly number[];\n};\n\n/**\n *  tuple elements are: InferenceSession ID; inputNamesUTF8Encoded; outputNamesUTF8Encoded; bindingState\n */\ntype SessionMetadata = [\n  inferenceSessionId: number,\n  inputNamesUTF8Encoded: number[],\n  outputNamesUTF8Encoded: number[],\n  bindingState: IOBindingState | null,\n  enableGraphCapture: boolean,\n  inputOutputBound: boolean,\n];\n\nconst activeSessions = new Map<number, SessionMetadata>();\n\n/**\n * get the input/output count of the session.\n * @param sessionHandle the handle representing the session. should be non-zero.\n * @returns a tuple including 2 numbers, representing the input count and output count.\n */\nconst getSessionInputOutputCount = (sessionHandle: number): [number, number] => {\n  const wasm = getInstance();\n  const stack = wasm.stackSave();\n  try {\n    const ptrSize = wasm.PTR_SIZE;\n    const dataOffset = wasm.stackAlloc(2 * ptrSize);\n    const errorCode = wasm._OrtGetInputOutputCount(sessionHandle, dataOffset, dataOffset + ptrSize);\n    if (errorCode !== 0) {\n      checkLastError(\"Can't get session input/output count.\");\n    }\n    const type = ptrSize === 4 ? 'i32' : 'i64';\n    return [Number(wasm.getValue(dataOffset, type)), Number(wasm.getValue(dataOffset + ptrSize, type))];\n  } finally {\n    wasm.stackRestore(stack);\n  }\n};\n\nconst getSessionInputOutputMetadata = (\n  sessionHandle: number,\n  index: number,\n): [nameOffset: number, elementType: number, dims?: Array<number | string>] => {\n  const wasm = getInstance();\n  const stack = wasm.stackSave();\n  let metadataOffset = 0;\n  try {\n    const ptrSize = wasm.PTR_SIZE;\n    const dataOffset = wasm.stackAlloc(2 * ptrSize);\n    const errorCode = wasm._OrtGetInputOutputMetadata(sessionHandle, index, dataOffset, dataOffset + ptrSize);\n    if (errorCode !== 0) {\n      checkLastError(\"Can't get session input/output metadata.\");\n    }\n    const nameOffset = Number(wasm.getValue(dataOffset, '*'));\n    metadataOffset = Number(wasm.getValue(dataOffset + ptrSize, '*'));\n    // get element type\n    const elementType = wasm.HEAP32[metadataOffset / 4];\n    if (elementType === 0) {\n      return [nameOffset, 0]; // non-tensor\n    }\n\n    // get dims count\n    const dimsCount = wasm.HEAPU32[metadataOffset / 4 + 1];\n    // get dims\n    const dims: Array<number | string> = [];\n    for (let i = 0; i < dimsCount; i++) {\n      const symbolicDimNameOffset = Number(wasm.getValue(metadataOffset + 8 + i * ptrSize, '*'));\n      dims.push(\n        symbolicDimNameOffset !== 0\n          ? wasm.UTF8ToString(symbolicDimNameOffset)\n          : Number(wasm.getValue(metadataOffset + 8 + (i + dimsCount) * ptrSize, '*')),\n      );\n    }\n    return [nameOffset, elementType, dims];\n  } finally {\n    wasm.stackRestore(stack);\n    if (metadataOffset !== 0) {\n      wasm._OrtFree(metadataOffset);\n    }\n  }\n};\n\n/**\n * allocate the memory and memcpy the external buffer.\n *\n * @param model - the external buffer containing the model data. Must not be the same buffer as the WASM heap.\n * @returns a 2-elements tuple - the pointer and size of the allocated buffer\n */\nexport const copyFromExternalBuffer = (model: Uint8Array): [number, number] => {\n  const wasm = getInstance();\n  const modelDataOffset = wasm._malloc(model.byteLength);\n  if (modelDataOffset === 0) {\n    throw new Error(`Can't create a session. failed to allocate a buffer of size ${model.byteLength}.`);\n  }\n  wasm.HEAPU8.set(model, modelDataOffset);\n  return [modelDataOffset, model.byteLength];\n};\n\n/**\n * create an inference session from a model data buffer.\n *\n * @param modelData - either a Uint8Array object representing the model data, or a 2-elements tuple containing the\n *     pointer and size of the model data buffer.\n * @param options an optional session options object.\n * @returns a 3-elements tuple containing [session handle, input names, output names]\n */\nexport const createSession = async (\n  modelData: Uint8Array | SerializableInternalBuffer,\n  options?: InferenceSession.SessionOptions,\n): Promise<SerializableSessionMetadata> => {\n  let modelDataOffset: number, modelDataLength: number;\n  const wasm = getInstance();\n\n  if (Array.isArray(modelData)) {\n    // if model data is an array, it must be a 2-elements tuple containing the pointer and size of the model data\n    [modelDataOffset, modelDataLength] = modelData;\n  } else if (modelData.buffer === wasm.HEAPU8.buffer) {\n    // if model data uses the same buffer as the WASM heap, we don't need to copy it.\n    [modelDataOffset, modelDataLength] = [modelData.byteOffset, modelData.byteLength];\n  } else {\n    // otherwise, copy the model data to the WASM heap.\n    [modelDataOffset, modelDataLength] = copyFromExternalBuffer(modelData);\n  }\n\n  let sessionHandle = 0;\n  let sessionOptionsHandle = 0;\n  let ioBindingHandle = 0;\n  let allocs: number[] = [];\n  const inputNamesUTF8Encoded = [];\n  const outputNamesUTF8Encoded = [];\n\n  try {\n    [sessionOptionsHandle, allocs] = await setSessionOptions(options);\n\n    if (options?.externalData && wasm.mountExternalData) {\n      const loadingPromises = [];\n      for (const file of options.externalData) {\n        const path = typeof file === 'string' ? file : file.path;\n        const data = typeof file === 'string' ? file : file.data;\n        if (BUILD_DEFS.ENABLE_JSPI && data instanceof Blob) {\n          wasm.mountExternalData(path, data);\n          continue;\n        }\n        loadingPromises.push(\n          loadFile(data).then((fileData) => {\n            wasm.mountExternalData(path, fileData);\n          }),\n        );\n      }\n\n      // wait for all external data files to be loaded\n      await Promise.all(loadingPromises);\n    }\n\n    for (const provider of options?.executionProviders ?? []) {\n      const providerName = typeof provider === 'string' ? provider : provider.name;\n      if (providerName === 'webnn') {\n        wasm.shouldTransferToMLTensor = false;\n        if (typeof provider !== 'string') {\n          const webnnOptions = provider as InferenceSession.WebNNExecutionProviderOption;\n          const context = (webnnOptions as InferenceSession.WebNNOptionsWithMLContext)?.context;\n          const gpuDevice = (webnnOptions as InferenceSession.WebNNOptionsWebGpu)?.gpuDevice;\n          const deviceType = (webnnOptions as InferenceSession.WebNNContextOptions)?.deviceType;\n          const powerPreference = (webnnOptions as InferenceSession.WebNNContextOptions)?.powerPreference;\n          if (context) {\n            wasm.currentContext = context as MLContext;\n          } else if (gpuDevice) {\n            wasm.currentContext = await wasm.webnnCreateMLContext!(gpuDevice);\n          } else {\n            wasm.currentContext = await wasm.webnnCreateMLContext!({ deviceType, powerPreference });\n          }\n        } else {\n          wasm.currentContext = await wasm.webnnCreateMLContext!();\n        }\n        break;\n      }\n    }\n\n    sessionHandle = await wasm._OrtCreateSession(modelDataOffset, modelDataLength, sessionOptionsHandle);\n    wasm.webgpuOnCreateSession?.(sessionHandle);\n    if (sessionHandle === 0) {\n      checkLastError(\"Can't create a session.\");\n    }\n\n    wasm.jsepOnCreateSession?.();\n\n    // clear current MLContext after session creation\n    if (wasm.currentContext) {\n      wasm.webnnRegisterMLContext!(sessionHandle, wasm.currentContext);\n      wasm.currentContext = undefined;\n      wasm.shouldTransferToMLTensor = true;\n    }\n\n    const [inputCount, outputCount] = getSessionInputOutputCount(sessionHandle);\n\n    const enableGraphCapture = !!options?.enableGraphCapture;\n\n    const inputNames = [];\n    const outputNames = [];\n    const inputMetadata: InferenceSession.ValueMetadata[] = [];\n    const outputMetadata: InferenceSession.ValueMetadata[] = [];\n    const outputPreferredLocations: SupportedTensorDataLocationForInputOutput[] = [];\n    for (let i = 0; i < inputCount; i++) {\n      const [nameOffset, elementType, shape] = getSessionInputOutputMetadata(sessionHandle, i);\n      if (nameOffset === 0) {\n        checkLastError(\"Can't get an input name.\");\n      }\n      inputNamesUTF8Encoded.push(nameOffset);\n      const name = wasm.UTF8ToString(nameOffset);\n      inputNames.push(name);\n      inputMetadata.push(\n        elementType === 0\n          ? { name, isTensor: false }\n          : { name, isTensor: true, type: tensorDataTypeEnumToString(elementType), shape: shape! },\n      );\n    }\n    for (let i = 0; i < outputCount; i++) {\n      const [nameOffset, elementType, shape] = getSessionInputOutputMetadata(sessionHandle, i + inputCount);\n      if (nameOffset === 0) {\n        checkLastError(\"Can't get an output name.\");\n      }\n      outputNamesUTF8Encoded.push(nameOffset);\n      const nameString = wasm.UTF8ToString(nameOffset);\n      outputNames.push(nameString);\n      outputMetadata.push(\n        elementType === 0\n          ? { name: nameString, isTensor: false }\n          : { name: nameString, isTensor: true, type: tensorDataTypeEnumToString(elementType), shape: shape! },\n      );\n\n      if (!BUILD_DEFS.DISABLE_JSEP || !BUILD_DEFS.DISABLE_WEBGPU) {\n        if (enableGraphCapture && options?.preferredOutputLocation === undefined) {\n          outputPreferredLocations.push('gpu-buffer');\n          continue;\n        }\n        const location =\n          typeof options?.preferredOutputLocation === 'string'\n            ? options.preferredOutputLocation\n            : (options?.preferredOutputLocation?.[nameString] ?? 'cpu');\n        const isGraphOutput = wasm.webnnIsGraphOutput;\n        if (location === 'cpu' && isGraphOutput && isGraphOutput(sessionHandle, nameString)) {\n          outputPreferredLocations.push('ml-tensor-cpu-output');\n          continue;\n        }\n        if (location !== 'cpu' && location !== 'cpu-pinned' && location !== 'gpu-buffer' && location !== 'ml-tensor') {\n          throw new Error(`Not supported preferred output location: ${location}.`);\n        }\n        if (enableGraphCapture && location !== 'gpu-buffer') {\n          throw new Error(\n            `Not supported preferred output location: ${location}. Only 'gpu-buffer' location is supported when enableGraphCapture is true.`,\n          );\n        }\n        outputPreferredLocations.push(location);\n      }\n    }\n\n    // use IO binding only when at least one output is preferred to be on GPU.\n    let bindingState: IOBindingState | null = null;\n    if (\n      (!BUILD_DEFS.DISABLE_JSEP || !BUILD_DEFS.DISABLE_WEBGPU) &&\n      outputPreferredLocations.some((l) => l === 'gpu-buffer' || l === 'ml-tensor' || l === 'ml-tensor-cpu-output')\n    ) {\n      ioBindingHandle = wasm._OrtCreateBinding(sessionHandle);\n      if (ioBindingHandle === 0) {\n        checkLastError(\"Can't create IO binding.\");\n      }\n\n      bindingState = {\n        handle: ioBindingHandle,\n        outputPreferredLocations,\n        outputPreferredLocationsEncoded: outputPreferredLocations\n          // 'ml-tensor-cpu-output' is treated as 'ml-tensor' for the purpose of IO binding.\n          .map((l) => (l === 'ml-tensor-cpu-output' ? 'ml-tensor' : l))\n          .map((l) => dataLocationStringToEnum(l)),\n      };\n    }\n\n    activeSessions.set(sessionHandle, [\n      sessionHandle,\n      inputNamesUTF8Encoded,\n      outputNamesUTF8Encoded,\n      bindingState,\n      enableGraphCapture,\n      false,\n    ]);\n    return [sessionHandle, inputNames, outputNames, inputMetadata, outputMetadata];\n  } catch (e) {\n    inputNamesUTF8Encoded.forEach((buf) => wasm._OrtFree(buf));\n    outputNamesUTF8Encoded.forEach((buf) => wasm._OrtFree(buf));\n\n    if (ioBindingHandle !== 0) {\n      if (wasm._OrtReleaseBinding(ioBindingHandle) !== 0) {\n        checkLastError(\"Can't release IO binding.\");\n      }\n    }\n\n    if (sessionHandle !== 0) {\n      if (wasm._OrtReleaseSession(sessionHandle) !== 0) {\n        checkLastError(\"Can't release session.\");\n      }\n    }\n    throw e;\n  } finally {\n    wasm._free(modelDataOffset);\n    if (sessionOptionsHandle !== 0) {\n      if (wasm._OrtReleaseSessionOptions(sessionOptionsHandle) !== 0) {\n        checkLastError(\"Can't release session options.\");\n      }\n    }\n    allocs.forEach((alloc) => wasm._free(alloc));\n\n    // unmount external data if necessary\n    wasm.unmountExternalData?.();\n  }\n};\n\nexport const releaseSession = (sessionId: number): void => {\n  const wasm = getInstance();\n  const session = activeSessions.get(sessionId);\n  if (!session) {\n    throw new Error(`cannot release session. invalid session id: ${sessionId}`);\n  }\n  const [sessionHandle, inputNamesUTF8Encoded, outputNamesUTF8Encoded, ioBindingState, enableGraphCapture] = session;\n\n  if (ioBindingState) {\n    if (enableGraphCapture) {\n      if (wasm._OrtClearBoundOutputs(ioBindingState.handle) !== 0) {\n        checkLastError(\"Can't clear bound outputs.\");\n      }\n    }\n    if (wasm._OrtReleaseBinding(ioBindingState.handle) !== 0) {\n      checkLastError(\"Can't release IO binding.\");\n    }\n  }\n\n  wasm.jsepOnReleaseSession?.(sessionId);\n  wasm.webnnOnReleaseSession?.(sessionId);\n  wasm.webgpuOnReleaseSession?.(sessionId);\n\n  inputNamesUTF8Encoded.forEach((buf) => wasm._OrtFree(buf));\n  outputNamesUTF8Encoded.forEach((buf) => wasm._OrtFree(buf));\n  if (wasm._OrtReleaseSession(sessionHandle) !== 0) {\n    checkLastError(\"Can't release session.\");\n  }\n  activeSessions.delete(sessionId);\n};\n\nexport const prepareInputOutputTensor = async (\n  tensor: TensorMetadata | null,\n  tensorHandles: number[],\n  allocs: number[],\n  sessionId: number,\n  tensorNameUTF8Encoded: number,\n  index: number,\n  enableGraphCapture = false,\n): Promise<void> => {\n  if (!tensor) {\n    tensorHandles.push(0);\n    return;\n  }\n\n  const wasm = getInstance();\n  const ptrSize = wasm.PTR_SIZE;\n\n  const dataType = tensor[0];\n  const dims = tensor[1];\n  const location = tensor[3];\n  let actualLocation = location;\n\n  let rawData: number;\n  let dataByteLength: number;\n\n  if (dataType === 'string' && (location === 'gpu-buffer' || location === 'ml-tensor')) {\n    throw new Error('String tensor is not supported on GPU.');\n  }\n\n  if (enableGraphCapture && location !== 'gpu-buffer') {\n    throw new Error(\n      `External buffer must be provided for input/output index ${index} when enableGraphCapture is true.`,\n    );\n  }\n\n  if (location === 'gpu-buffer') {\n    const gpuBuffer = tensor[2].gpuBuffer;\n    dataByteLength = calculateTensorSizeInBytes(tensorDataTypeStringToEnum(dataType), dims)!;\n\n    if (!BUILD_DEFS.DISABLE_WEBGPU) {\n      const registerBuffer = wasm.webgpuRegisterBuffer;\n      if (!registerBuffer) {\n        throw new Error('Tensor location \"gpu-buffer\" is not supported without using WebGPU.');\n      }\n\n      rawData = registerBuffer(gpuBuffer, sessionId);\n    } else {\n      const registerBuffer = wasm.jsepRegisterBuffer;\n      if (!registerBuffer) {\n        throw new Error('Tensor location \"gpu-buffer\" is not supported without using WebGPU.');\n      }\n      rawData = registerBuffer(sessionId, index, gpuBuffer, dataByteLength);\n    }\n  } else if (location === 'ml-tensor') {\n    const mlTensor = tensor[2].mlTensor;\n    dataByteLength = calculateTensorSizeInBytes(tensorDataTypeStringToEnum(dataType), dims)!;\n\n    const registerMLTensor = wasm.webnnRegisterMLTensor;\n    if (!registerMLTensor) {\n      throw new Error('Tensor location \"ml-tensor\" is not supported without using WebNN.');\n    }\n    rawData = registerMLTensor(sessionId, mlTensor, tensorDataTypeStringToEnum(dataType), dims);\n  } else {\n    const data = tensor[2];\n\n    if (Array.isArray(data)) {\n      // string tensor\n      dataByteLength = ptrSize * data.length;\n      rawData = wasm._malloc(dataByteLength);\n      allocs.push(rawData);\n      for (let i = 0; i < data.length; i++) {\n        if (typeof data[i] !== 'string') {\n          throw new TypeError(`tensor data at index ${i} is not a string`);\n        }\n        wasm.setValue(rawData + i * ptrSize, allocWasmString(data[i], allocs), '*');\n      }\n    } else {\n      const isGraphInput = wasm.webnnIsGraphInput;\n      const isGraphOutput = wasm.webnnIsGraphOutput;\n      if (dataType !== 'string' && isGraphInput && isGraphOutput) {\n        const tensorName = wasm.UTF8ToString(tensorNameUTF8Encoded);\n        // Promote the tensor to 'ml-tensor' if it is a graph input.\n        if (isGraphInput(sessionId, tensorName) || isGraphOutput(sessionId, tensorName)) {\n          const dataTypeEnum = tensorDataTypeStringToEnum(dataType);\n          dataByteLength = calculateTensorSizeInBytes(dataTypeEnum, dims)!;\n          actualLocation = 'ml-tensor';\n          const createTemporaryTensor = wasm.webnnCreateTemporaryTensor;\n          const uploadTensor = wasm.webnnUploadTensor;\n          if (!createTemporaryTensor || !uploadTensor) {\n            throw new Error('Tensor location \"ml-tensor\" is not supported without using WebNN.');\n          }\n          const tensorId = await createTemporaryTensor(sessionId, dataTypeEnum, dims);\n          uploadTensor(tensorId, new Uint8Array(data.buffer, data.byteOffset, data.byteLength));\n          rawData = tensorId;\n        } else {\n          dataByteLength = data.byteLength;\n          rawData = wasm._malloc(dataByteLength);\n          allocs.push(rawData);\n          wasm.HEAPU8.set(new Uint8Array(data.buffer, data.byteOffset, dataByteLength), rawData);\n        }\n      } else {\n        dataByteLength = data.byteLength;\n        rawData = wasm._malloc(dataByteLength);\n        allocs.push(rawData);\n        wasm.HEAPU8.set(new Uint8Array(data.buffer, data.byteOffset, dataByteLength), rawData);\n      }\n    }\n  }\n\n  const stack = wasm.stackSave();\n  const dimsOffset = wasm.stackAlloc(4 * dims.length);\n  try {\n    dims.forEach((d, index) => wasm.setValue(dimsOffset + index * ptrSize, d, ptrSize === 4 ? 'i32' : 'i64'));\n    const tensor = wasm._OrtCreateTensor(\n      tensorDataTypeStringToEnum(dataType),\n      rawData,\n      dataByteLength,\n      dimsOffset,\n      dims.length,\n      dataLocationStringToEnum(actualLocation),\n    );\n    if (tensor === 0) {\n      checkLastError(`Can't create tensor for input/output. session=${sessionId}, index=${index}.`);\n    }\n    tensorHandles.push(tensor);\n  } finally {\n    wasm.stackRestore(stack);\n  }\n};\n\n/**\n * perform inference run\n */\nexport const run = async (\n  sessionId: number,\n  inputIndices: number[],\n  inputTensors: TensorMetadata[],\n  outputIndices: number[],\n  outputTensors: Array<TensorMetadata | null>,\n  options: InferenceSession.RunOptions,\n): Promise<TensorMetadata[]> => {\n  const wasm = getInstance();\n  const ptrSize = wasm.PTR_SIZE;\n  const session = activeSessions.get(sessionId);\n  if (!session) {\n    throw new Error(`cannot run inference. invalid session id: ${sessionId}`);\n  }\n  const sessionHandle = session[0];\n  const inputNamesUTF8Encoded = session[1];\n  const outputNamesUTF8Encoded = session[2];\n  const ioBindingState = session[3];\n  const enableGraphCapture = session[4];\n  const inputOutputBound = session[5];\n\n  const inputCount = inputIndices.length;\n  const outputCount = outputIndices.length;\n\n  let runOptionsHandle = 0;\n  let runOptionsAllocs: number[] = [];\n\n  const inputTensorHandles: number[] = [];\n  const outputTensorHandles: number[] = [];\n  const inputOutputAllocs: number[] = [];\n  const preAllocatedOutputs: number[] = [];\n\n  const beforeRunStack = wasm.stackSave();\n  const inputValuesOffset = wasm.stackAlloc(inputCount * ptrSize);\n  const inputNamesOffset = wasm.stackAlloc(inputCount * ptrSize);\n  const outputValuesOffset = wasm.stackAlloc(outputCount * ptrSize);\n  const outputNamesOffset = wasm.stackAlloc(outputCount * ptrSize);\n\n  try {\n    [runOptionsHandle, runOptionsAllocs] = setRunOptions(options);\n\n    TRACE_EVENT_BEGIN('wasm prepareInputOutputTensor');\n    // create input tensors\n    for (let i = 0; i < inputCount; i++) {\n      await prepareInputOutputTensor(\n        inputTensors[i],\n        inputTensorHandles,\n        inputOutputAllocs,\n        sessionId,\n        inputNamesUTF8Encoded[inputIndices[i]],\n        inputIndices[i],\n        enableGraphCapture,\n      );\n    }\n\n    // create output tensors\n    for (let i = 0; i < outputCount; i++) {\n      await prepareInputOutputTensor(\n        outputTensors[i],\n        outputTensorHandles,\n        inputOutputAllocs,\n        sessionId,\n        outputNamesUTF8Encoded[outputIndices[i]],\n        inputCount + outputIndices[i],\n        enableGraphCapture,\n      );\n    }\n    TRACE_EVENT_END('wasm prepareInputOutputTensor');\n\n    for (let i = 0; i < inputCount; i++) {\n      wasm.setValue(inputValuesOffset + i * ptrSize, inputTensorHandles[i], '*');\n      wasm.setValue(inputNamesOffset + i * ptrSize, inputNamesUTF8Encoded[inputIndices[i]], '*');\n    }\n    for (let i = 0; i < outputCount; i++) {\n      wasm.setValue(outputValuesOffset + i * ptrSize, outputTensorHandles[i], '*');\n      wasm.setValue(outputNamesOffset + i * ptrSize, outputNamesUTF8Encoded[outputIndices[i]], '*');\n    }\n\n    if ((!BUILD_DEFS.DISABLE_JSEP || !BUILD_DEFS.DISABLE_WEBGPU) && ioBindingState && !inputOutputBound) {\n      const { handle, outputPreferredLocations, outputPreferredLocationsEncoded } = ioBindingState;\n\n      if (inputNamesUTF8Encoded.length !== inputCount) {\n        throw new Error(\n          `input count from feeds (${inputCount}) is expected to be always equal to model's input count (${inputNamesUTF8Encoded.length}).`,\n        );\n      }\n\n      TRACE_EVENT_BEGIN('wasm bindInputsOutputs');\n      // process inputs\n      for (let i = 0; i < inputCount; i++) {\n        const index = inputIndices[i];\n        const errorCode = await wasm._OrtBindInput(handle, inputNamesUTF8Encoded[index], inputTensorHandles[i]);\n        if (errorCode !== 0) {\n          checkLastError(`Can't bind input[${i}] for session=${sessionId}.`);\n        }\n      }\n\n      // process pre-allocated outputs\n      for (let i = 0; i < outputCount; i++) {\n        const index = outputIndices[i];\n        const location = outputTensors[i]?.[3]; // undefined means output is not pre-allocated.\n\n        if (location) {\n          // output is pre-allocated, store and bind the tensor.\n          preAllocatedOutputs.push(outputTensorHandles[i]);\n          const errorCode = wasm._OrtBindOutput(handle, outputNamesUTF8Encoded[index], outputTensorHandles[i], 0);\n          if (errorCode !== 0) {\n            checkLastError(`Can't bind pre-allocated output[${i}] for session=${sessionId}.`);\n          }\n        } else {\n          // output is not pre-allocated. reset preferred location.\n          const errorCode = wasm._OrtBindOutput(\n            handle,\n            outputNamesUTF8Encoded[index],\n            0,\n            outputPreferredLocationsEncoded[index],\n          );\n          if (errorCode !== 0) {\n            checkLastError(`Can't bind output[${i}] to ${outputPreferredLocations[i]} for session=${sessionId}.`);\n          }\n        }\n      }\n      TRACE_EVENT_END('wasm bindInputsOutputs');\n      activeSessions.set(sessionId, [\n        sessionHandle,\n        inputNamesUTF8Encoded,\n        outputNamesUTF8Encoded,\n        ioBindingState,\n        enableGraphCapture,\n        true,\n      ]);\n    }\n\n    wasm.jsepOnRunStart?.(sessionHandle);\n    wasm.webnnOnRunStart?.(sessionHandle);\n\n    let errorCode: number;\n    if ((!BUILD_DEFS.DISABLE_JSEP || !BUILD_DEFS.DISABLE_WEBGPU) && ioBindingState) {\n      errorCode = await wasm._OrtRunWithBinding(\n        sessionHandle,\n        ioBindingState.handle,\n        outputCount,\n        outputValuesOffset,\n        runOptionsHandle,\n      );\n    } else {\n      errorCode = await wasm._OrtRun(\n        sessionHandle,\n        inputNamesOffset,\n        inputValuesOffset,\n        inputCount,\n        outputNamesOffset,\n        outputCount,\n        outputValuesOffset,\n        runOptionsHandle,\n      );\n    }\n\n    if (errorCode !== 0) {\n      checkLastError('failed to call OrtRun().');\n    }\n\n    const output: TensorMetadata[] = [];\n    const outputPromises: Array<Promise<[number, Tensor.DataType]>> = [];\n\n    TRACE_EVENT_BEGIN('wasm ProcessOutputTensor');\n    for (let i = 0; i < outputCount; i++) {\n      const tensor = Number(wasm.getValue(outputValuesOffset + i * ptrSize, '*'));\n      // TODO: revisit this part to ensure it works for WebGPU when both pre-allocated outputs and\n      // preferred location are specified.\n      // Certain pre-allocated tensors may already be bound in the IO binding. e.g. the WebNN backend\n      // always binds its tensor to 'ml-tensor'. In such cases, the tensor ID might change after binding,\n      // but copying data for these tensors should still be avoided.\n      if (tensor === outputTensorHandles[i] || preAllocatedOutputs.includes(outputTensorHandles[i])) {\n        // output tensor is pre-allocated. no need to copy data.\n        output.push(outputTensors[i]!);\n        if (tensor !== outputTensorHandles[i]) {\n          // release redundant tensor earlier.\n          if (wasm._OrtReleaseTensor(tensor) !== 0) {\n            checkLastError(\"Can't release tensor.\");\n          }\n        }\n        continue;\n      }\n\n      const beforeGetTensorDataStack = wasm.stackSave();\n      // stack allocate 4 pointer value\n      const tensorDataOffset = wasm.stackAlloc(4 * ptrSize);\n\n      let keepOutputTensor = false;\n      let type: Tensor.Type | undefined,\n        dataOffset = 0;\n      try {\n        const errorCode = wasm._OrtGetTensorData(\n          tensor,\n          tensorDataOffset,\n          tensorDataOffset + ptrSize,\n          tensorDataOffset + 2 * ptrSize,\n\n          tensorDataOffset + 3 * ptrSize,\n        );\n        if (errorCode !== 0) {\n          checkLastError(`Can't access output tensor data on index ${i}.`);\n        }\n        const valueType = ptrSize === 4 ? 'i32' : 'i64';\n        const dataType = Number(wasm.getValue(tensorDataOffset, valueType));\n        dataOffset = wasm.getValue(tensorDataOffset + ptrSize, '*');\n        const dimsOffset = wasm.getValue(tensorDataOffset + ptrSize * 2, '*');\n        const dimsLength = Number(wasm.getValue(tensorDataOffset + ptrSize * 3, valueType));\n        const dims = [];\n        for (let i = 0; i < dimsLength; i++) {\n          dims.push(Number(wasm.getValue(dimsOffset + i * ptrSize, valueType)));\n        }\n        if (wasm._OrtFree(dimsOffset) !== 0) {\n          checkLastError(\"Can't free memory for tensor dims.\");\n        }\n        const size = dims.reduce((a, b) => a * b, 1);\n        type = tensorDataTypeEnumToString(dataType);\n\n        const preferredLocation = ioBindingState?.outputPreferredLocations[outputIndices[i]];\n\n        if (type === 'string') {\n          if (preferredLocation === 'gpu-buffer' || preferredLocation === 'ml-tensor') {\n            throw new Error('String tensor is not supported on GPU.');\n          }\n          const stringData: string[] = [];\n          for (let i = 0; i < size; i++) {\n            const offset = wasm.getValue(dataOffset + i * ptrSize, '*');\n            const nextOffset = wasm.getValue(dataOffset + (i + 1) * ptrSize, '*');\n            const maxBytesToRead = i === size - 1 ? undefined : nextOffset - offset;\n            stringData.push(wasm.UTF8ToString(offset, maxBytesToRead));\n          }\n          output.push([type, dims, stringData, 'cpu']);\n        } else {\n          // If a certain output's preferred location is GPU but the tensor is empty, we still need to create a CPU\n          // tensor for it. There is no mapping GPU buffer for an empty tensor.\n          if (preferredLocation === 'gpu-buffer' && size > 0) {\n            const getBuffer = !BUILD_DEFS.DISABLE_WEBGPU ? wasm.webgpuGetBuffer : wasm.jsepGetBuffer;\n            if (!getBuffer) {\n              throw new Error('preferredLocation \"gpu-buffer\" is not supported without using WebGPU.');\n            }\n            const gpuBuffer = getBuffer(dataOffset);\n            const bufferSize = calculateTensorSizeInBytes(dataType, size);\n            if (bufferSize === undefined || !isGpuBufferSupportedType(type)) {\n              throw new Error(`Unsupported data type: ${type}`);\n            }\n\n            // do not release the tensor right now. it will be released when user calls tensor.dispose().\n            keepOutputTensor = true;\n\n            if (!BUILD_DEFS.DISABLE_WEBGPU) {\n              wasm.webgpuRegisterBuffer!(gpuBuffer, sessionId, dataOffset);\n              const downloadDataFunction = wasm.webgpuCreateDownloader!(gpuBuffer, bufferSize, sessionId);\n              output.push([\n                type,\n                dims,\n                {\n                  gpuBuffer,\n                  download: async () => {\n                    const arrayBuffer = await downloadDataFunction();\n                    const data = new (tensorTypeToTypedArrayConstructor(type!))(arrayBuffer);\n                    return data as Tensor.DataTypeMap[Tensor.GpuBufferDataTypes];\n                  },\n                  dispose: () => {\n                    if (wasm._OrtReleaseTensor(tensor) !== 0) {\n                      checkLastError(\"Can't release tensor.\");\n                    }\n                  },\n                },\n                'gpu-buffer',\n              ]);\n            } else {\n              output.push([\n                type,\n                dims,\n                {\n                  gpuBuffer,\n                  download: wasm.jsepCreateDownloader!(gpuBuffer, bufferSize, type),\n                  dispose: () => {\n                    if (wasm._OrtReleaseTensor(tensor) !== 0) {\n                      checkLastError(\"Can't release tensor.\");\n                    }\n                  },\n                },\n                'gpu-buffer',\n              ]);\n            }\n          } else if (preferredLocation === 'ml-tensor' && size > 0) {\n            const ensureTensor = wasm.webnnEnsureTensor;\n            const isGraphInputOutputTypeSupported = wasm.webnnIsGraphInputOutputTypeSupported;\n            if (!ensureTensor || !isGraphInputOutputTypeSupported) {\n              throw new Error('preferredLocation \"ml-tensor\" is not supported without using WebNN.');\n            }\n            const tensorSize = calculateTensorSizeInBytes(dataType, size);\n            if (tensorSize === undefined || !isMLTensorSupportedType(type)) {\n              throw new Error(`Unsupported data type: ${type}`);\n            }\n            if (!isGraphInputOutputTypeSupported(sessionId, type, false)) {\n              throw new Error(\n                `preferredLocation \"ml-tensor\" for ${type} output is not supported by current WebNN Context.`,\n              );\n            }\n\n            // If the graph has been partitioned, the output tensor may have not been created. For this reason, we use\n            // ensureTensor to get/create the MLTensor. In which case, we don't need to copy the data if a new tensor\n            // has been created.\n            const mlTensor = await ensureTensor(sessionId, dataOffset, dataType, dims, false);\n\n            // do not release the tensor right now. it will be released when user calls tensor.dispose().\n            keepOutputTensor = true;\n\n            output.push([\n              type,\n              dims,\n              {\n                mlTensor,\n                download: wasm.webnnCreateMLTensorDownloader!(dataOffset, type),\n                dispose: () => {\n                  wasm.webnnReleaseTensorId!(dataOffset);\n                  wasm._OrtReleaseTensor(tensor);\n                },\n              },\n              'ml-tensor',\n            ]);\n          } else if (preferredLocation === 'ml-tensor-cpu-output' && size > 0) {\n            const data = wasm.webnnCreateMLTensorDownloader!(dataOffset, type as Tensor.MLTensorDataTypes)();\n            const index = output.length;\n            // Delay the data download and releasing the tensor until we can wait for all output tensors to be downloaded.\n            keepOutputTensor = true;\n            outputPromises.push(\n              (async () => {\n                const result: [number, Tensor.DataType] = [index, await data];\n                wasm.webnnReleaseTensorId!(dataOffset);\n                wasm._OrtReleaseTensor(tensor);\n                return result;\n              })(),\n            );\n            output.push([type, dims, [], 'cpu']);\n          } else {\n            const typedArrayConstructor = tensorTypeToTypedArrayConstructor(type);\n            const data = new typedArrayConstructor(size);\n            new Uint8Array(data.buffer, data.byteOffset, data.byteLength).set(\n              wasm.HEAPU8.subarray(dataOffset, dataOffset + data.byteLength),\n            );\n            output.push([type, dims, data, 'cpu']);\n          }\n        }\n      } finally {\n        wasm.stackRestore(beforeGetTensorDataStack);\n        if (type === 'string' && dataOffset) {\n          wasm._free(dataOffset);\n        }\n        if (!keepOutputTensor) {\n          wasm._OrtReleaseTensor(tensor);\n        }\n      }\n    }\n\n    if (ioBindingState && !enableGraphCapture) {\n      if (wasm._OrtClearBoundOutputs(ioBindingState.handle) !== 0) {\n        checkLastError(\"Can't clear bound outputs.\");\n      }\n      activeSessions.set(sessionId, [\n        sessionHandle,\n        inputNamesUTF8Encoded,\n        outputNamesUTF8Encoded,\n        ioBindingState,\n        enableGraphCapture,\n        false,\n      ]);\n    }\n    // Wait for all output tensor data to be downloaded.\n    for (const [index, data] of await Promise.all(outputPromises)) {\n      output[index][2] = data;\n    }\n    TRACE_EVENT_END('wasm ProcessOutputTensor');\n    return output;\n  } finally {\n    wasm.webnnOnRunEnd?.(sessionHandle);\n\n    wasm.stackRestore(beforeRunStack);\n\n    if (!BUILD_DEFS.DISABLE_WEBGPU) {\n      inputTensors.forEach((t) => {\n        if (t && t[3] === 'gpu-buffer') {\n          wasm.webgpuUnregisterBuffer!(t[2].gpuBuffer);\n        }\n      });\n      outputTensors.forEach((t) => {\n        if (t && t[3] === 'gpu-buffer') {\n          wasm.webgpuUnregisterBuffer!(t[2].gpuBuffer);\n        }\n      });\n    }\n    inputTensorHandles.forEach((v) => wasm._OrtReleaseTensor(v));\n    outputTensorHandles.forEach((v) => wasm._OrtReleaseTensor(v));\n    inputOutputAllocs.forEach((p) => wasm._free(p));\n\n    if (runOptionsHandle !== 0) {\n      wasm._OrtReleaseRunOptions(runOptionsHandle);\n    }\n    runOptionsAllocs.forEach((p) => wasm._free(p));\n  }\n};\n\n/**\n * end profiling\n */\nexport const endProfiling = (sessionId: number): void => {\n  const wasm = getInstance();\n  const session = activeSessions.get(sessionId);\n  if (!session) {\n    throw new Error('invalid session id');\n  }\n  const sessionHandle = session[0];\n\n  // profile file name is not used yet, but it must be freed.\n  const profileFileName = wasm._OrtEndProfiling(sessionHandle);\n  if (profileFileName === 0) {\n    checkLastError(\"Can't get an profile file name.\");\n  }\n  wasm._OrtFree(profileFileName);\n};\n\nexport const extractTransferableBuffers = (tensors: readonly SerializableTensorMetadata[]): ArrayBufferLike[] => {\n  const buffers: ArrayBufferLike[] = [];\n  for (const tensor of tensors) {\n    const data = tensor[2];\n    if (!Array.isArray(data) && 'buffer' in data) {\n      buffers.push(data.buffer);\n    }\n  }\n  return buffers;\n};\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { env, InferenceSession } from 'onnxruntime-common';\n\nimport {\n  OrtWasmMessage,\n  SerializableInternalBuffer,\n  SerializableSessionMetadata,\n  SerializableTensorMetadata,\n  TensorMetadata,\n} from './proxy-messages';\nimport * as core from './wasm-core-impl';\nimport { initializeWebAssembly } from './wasm-factory';\nimport {\n  importProxyWorker,\n  inferWasmPathPrefixFromScriptSrc,\n  isEsmImportMetaUrlHardcodedAsFileUri,\n} from './wasm-utils-import';\n\nconst isProxy = (): boolean => !!env.wasm.proxy && typeof document !== 'undefined';\nlet proxyWorker: Worker | undefined;\nlet initializing = false;\nlet initialized = false;\nlet aborted = false;\nlet temporaryObjectUrl: string | undefined;\n\ntype PromiseCallbacks<T = void> = [resolve: (result: T) => void, reject: (reason: unknown) => void];\nlet initWasmCallbacks: PromiseCallbacks;\nconst queuedCallbacks: Map<OrtWasmMessage['type'], Array<PromiseCallbacks<unknown>>> = new Map();\n\nconst enqueueCallbacks = (type: OrtWasmMessage['type'], callbacks: PromiseCallbacks<unknown>): void => {\n  const queue = queuedCallbacks.get(type);\n  if (queue) {\n    queue.push(callbacks);\n  } else {\n    queuedCallbacks.set(type, [callbacks]);\n  }\n};\n\nconst ensureWorker = (): void => {\n  if (initializing || !initialized || aborted || !proxyWorker) {\n    throw new Error('worker not ready');\n  }\n};\n\nconst onProxyWorkerMessage = (ev: MessageEvent<OrtWasmMessage>): void => {\n  switch (ev.data.type) {\n    case 'init-wasm':\n      initializing = false;\n      if (ev.data.err) {\n        aborted = true;\n        initWasmCallbacks[1](ev.data.err);\n      } else {\n        initialized = true;\n        initWasmCallbacks[0]();\n      }\n      if (temporaryObjectUrl) {\n        URL.revokeObjectURL(temporaryObjectUrl);\n        temporaryObjectUrl = undefined;\n      }\n      break;\n    case 'init-ep':\n    case 'copy-from':\n    case 'create':\n    case 'release':\n    case 'run':\n    case 'end-profiling': {\n      const callbacks = queuedCallbacks.get(ev.data.type)!;\n      if (ev.data.err) {\n        callbacks.shift()![1](ev.data.err);\n      } else {\n        callbacks.shift()![0](ev.data.out!);\n      }\n      break;\n    }\n    default:\n  }\n};\n\nexport const initializeWebAssemblyAndOrtRuntime = async (): Promise<void> => {\n  if (initialized) {\n    return;\n  }\n  if (initializing) {\n    throw new Error(\"multiple calls to 'initWasm()' detected.\");\n  }\n  if (aborted) {\n    throw new Error(\"previous call to 'initWasm()' failed.\");\n  }\n\n  initializing = true;\n\n  if (!BUILD_DEFS.DISABLE_WASM_PROXY && isProxy()) {\n    return new Promise<void>((resolve, reject) => {\n      proxyWorker?.terminate();\n\n      void importProxyWorker().then(([objectUrl, worker]) => {\n        try {\n          proxyWorker = worker;\n          proxyWorker.onerror = (ev: ErrorEvent) => reject(ev);\n          proxyWorker.onmessage = onProxyWorkerMessage;\n          initWasmCallbacks = [resolve, reject];\n          const message: OrtWasmMessage = { type: 'init-wasm', in: env };\n\n          // if the proxy worker is loaded from a blob URL, we need to make sure the path information is not lost.\n          //\n          // when `env.wasm.wasmPaths` is not set, we need to pass the path information to the worker.\n          //\n          if (!BUILD_DEFS.ENABLE_BUNDLE_WASM_JS && !message.in!.wasm.wasmPaths && objectUrl) {\n            // for a build not bundled the wasm JS, we need to pass the path prefix to the worker.\n            // the path prefix will be used to resolve the path to both the wasm JS and the wasm file.\n            const inferredWasmPathPrefix = inferWasmPathPrefixFromScriptSrc();\n            if (inferredWasmPathPrefix) {\n              message.in!.wasm.wasmPaths = inferredWasmPathPrefix;\n            }\n          }\n\n          if (\n            BUILD_DEFS.IS_ESM &&\n            BUILD_DEFS.ENABLE_BUNDLE_WASM_JS &&\n            !message.in!.wasm.wasmPaths &&\n            (objectUrl || isEsmImportMetaUrlHardcodedAsFileUri)\n          ) {\n            // for a build bundled the wasm JS, if either of the following conditions is met:\n            // - the proxy worker is loaded from a blob URL\n            // - `import.meta.url` is a file URL, it means it is overwritten by the bundler.\n            //\n            // in either case, the path information is lost, we need to pass the path of the .wasm file to the worker.\n            // we need to use the bundler preferred URL format:\n            // new URL('filename', import.meta.url)\n            // so that the bundler can handle the file using corresponding loaders.\n            message.in!.wasm.wasmPaths = {\n              wasm: !BUILD_DEFS.DISABLE_JSEP\n                ? new URL('ort-wasm-simd-threaded.jsep.wasm', BUILD_DEFS.ESM_IMPORT_META_URL).href\n                : BUILD_DEFS.ENABLE_JSPI\n                  ? new URL('ort-wasm-simd-threaded.jspi.wasm', BUILD_DEFS.ESM_IMPORT_META_URL).href\n                  : !BUILD_DEFS.DISABLE_WEBGPU\n                    ? new URL('ort-wasm-simd-threaded.asyncify.wasm', BUILD_DEFS.ESM_IMPORT_META_URL).href\n                    : new URL('ort-wasm-simd-threaded.wasm', BUILD_DEFS.ESM_IMPORT_META_URL).href,\n            };\n          }\n          proxyWorker.postMessage(message);\n          temporaryObjectUrl = objectUrl;\n        } catch (e) {\n          reject(e);\n        }\n      }, reject);\n    });\n  } else {\n    try {\n      await initializeWebAssembly(env.wasm);\n      await core.initRuntime(env);\n      initialized = true;\n    } catch (e) {\n      aborted = true;\n      throw e;\n    } finally {\n      initializing = false;\n    }\n  }\n};\n\nexport const initializeOrtEp = async (epName: string): Promise<void> => {\n  if (!BUILD_DEFS.DISABLE_WASM_PROXY && isProxy()) {\n    ensureWorker();\n    return new Promise<void>((resolve, reject) => {\n      enqueueCallbacks('init-ep', [resolve, reject]);\n      const message: OrtWasmMessage = { type: 'init-ep', in: { epName, env } };\n      proxyWorker!.postMessage(message);\n    });\n  } else {\n    await core.initEp(env, epName);\n  }\n};\n\nexport const copyFromExternalBuffer = async (buffer: Uint8Array): Promise<SerializableInternalBuffer> => {\n  if (!BUILD_DEFS.DISABLE_WASM_PROXY && isProxy()) {\n    ensureWorker();\n    return new Promise<SerializableInternalBuffer>((resolve, reject) => {\n      enqueueCallbacks('copy-from', [resolve, reject]);\n      const message: OrtWasmMessage = { type: 'copy-from', in: { buffer } };\n      proxyWorker!.postMessage(message, [buffer.buffer]);\n    });\n  } else {\n    return core.copyFromExternalBuffer(buffer);\n  }\n};\n\nexport const createSession = async (\n  model: SerializableInternalBuffer | Uint8Array,\n  options?: InferenceSession.SessionOptions,\n): Promise<SerializableSessionMetadata> => {\n  if (!BUILD_DEFS.DISABLE_WASM_PROXY && isProxy()) {\n    // check unsupported options\n    if (options?.preferredOutputLocation) {\n      throw new Error('session option \"preferredOutputLocation\" is not supported for proxy.');\n    }\n    ensureWorker();\n    return new Promise<SerializableSessionMetadata>((resolve, reject) => {\n      enqueueCallbacks('create', [resolve, reject]);\n      const message: OrtWasmMessage = { type: 'create', in: { model, options: { ...options } } };\n      const transferable: Transferable[] = [];\n      if (model instanceof Uint8Array) {\n        transferable.push(model.buffer);\n      }\n      proxyWorker!.postMessage(message, transferable);\n    });\n  } else {\n    return core.createSession(model, options);\n  }\n};\n\nexport const releaseSession = async (sessionId: number): Promise<void> => {\n  if (!BUILD_DEFS.DISABLE_WASM_PROXY && isProxy()) {\n    ensureWorker();\n    return new Promise<void>((resolve, reject) => {\n      enqueueCallbacks('release', [resolve, reject]);\n      const message: OrtWasmMessage = { type: 'release', in: sessionId };\n      proxyWorker!.postMessage(message);\n    });\n  } else {\n    core.releaseSession(sessionId);\n  }\n};\n\nexport const run = async (\n  sessionId: number,\n  inputIndices: number[],\n  inputs: TensorMetadata[],\n  outputIndices: number[],\n  outputs: Array<TensorMetadata | null>,\n  options: InferenceSession.RunOptions,\n): Promise<TensorMetadata[]> => {\n  if (!BUILD_DEFS.DISABLE_WASM_PROXY && isProxy()) {\n    // check inputs location\n    if (inputs.some((t) => t[3] !== 'cpu')) {\n      throw new Error('input tensor on GPU is not supported for proxy.');\n    }\n    // check outputs location\n    if (outputs.some((t) => t)) {\n      throw new Error('pre-allocated output tensor is not supported for proxy.');\n    }\n    ensureWorker();\n    return new Promise<SerializableTensorMetadata[]>((resolve, reject) => {\n      enqueueCallbacks('run', [resolve, reject]);\n      const serializableInputs = inputs as SerializableTensorMetadata[]; // every input is on CPU.\n      const message: OrtWasmMessage = {\n        type: 'run',\n        in: { sessionId, inputIndices, inputs: serializableInputs, outputIndices, options },\n      };\n      proxyWorker!.postMessage(message, core.extractTransferableBuffers(serializableInputs));\n    });\n  } else {\n    return core.run(sessionId, inputIndices, inputs, outputIndices, outputs, options);\n  }\n};\n\nexport const endProfiling = async (sessionId: number): Promise<void> => {\n  if (!BUILD_DEFS.DISABLE_WASM_PROXY && isProxy()) {\n    ensureWorker();\n    return new Promise<void>((resolve, reject) => {\n      enqueueCallbacks('end-profiling', [resolve, reject]);\n      const message: OrtWasmMessage = { type: 'end-profiling', in: sessionId };\n      proxyWorker!.postMessage(message);\n    });\n  } else {\n    core.endProfiling(sessionId);\n  }\n};\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport {\n  InferenceSession,\n  InferenceSessionHandler,\n  SessionHandler,\n  Tensor,\n  TRACE_FUNC_BEGIN,\n  TRACE_FUNC_END,\n} from 'onnxruntime-common';\n\nimport { SerializableInternalBuffer, TensorMetadata } from './proxy-messages';\nimport { copyFromExternalBuffer, createSession, endProfiling, releaseSession, run } from './proxy-wrapper';\nimport { isGpuBufferSupportedType, isMLTensorSupportedType } from './wasm-common';\nimport { isNode } from './wasm-utils-env';\nimport { loadFile } from './wasm-utils-load-file';\n\nexport const encodeTensorMetadata = (tensor: Tensor, getName: () => string): TensorMetadata => {\n  switch (tensor.location) {\n    case 'cpu':\n      return [tensor.type, tensor.dims, tensor.data, 'cpu'];\n    case 'gpu-buffer':\n      return [tensor.type, tensor.dims, { gpuBuffer: tensor.gpuBuffer }, 'gpu-buffer'];\n    case 'ml-tensor':\n      return [tensor.type, tensor.dims, { mlTensor: tensor.mlTensor }, 'ml-tensor'];\n    default:\n      throw new Error(`invalid data location: ${tensor.location} for ${getName()}`);\n  }\n};\n\nexport const decodeTensorMetadata = (tensor: TensorMetadata): Tensor => {\n  switch (tensor[3]) {\n    case 'cpu':\n      return new Tensor(tensor[0], tensor[2], tensor[1]);\n    case 'gpu-buffer': {\n      const dataType = tensor[0];\n      if (!isGpuBufferSupportedType(dataType)) {\n        throw new Error(`not supported data type: ${dataType} for deserializing GPU tensor`);\n      }\n      const { gpuBuffer, download, dispose } = tensor[2];\n      return Tensor.fromGpuBuffer(gpuBuffer, { dataType, dims: tensor[1], download, dispose });\n    }\n    case 'ml-tensor': {\n      const dataType = tensor[0];\n      if (!isMLTensorSupportedType(dataType)) {\n        throw new Error(`not supported data type: ${dataType} for deserializing MLTensor tensor`);\n      }\n      const { mlTensor, download, dispose } = tensor[2];\n      return Tensor.fromMLTensor(mlTensor, { dataType, dims: tensor[1], download, dispose });\n    }\n    default:\n      throw new Error(`invalid data location: ${tensor[3]}`);\n  }\n};\n\nexport class OnnxruntimeWebAssemblySessionHandler implements InferenceSessionHandler {\n  private sessionId: number;\n\n  inputNames: readonly string[];\n  outputNames: readonly string[];\n  inputMetadata: readonly InferenceSession.ValueMetadata[];\n  outputMetadata: readonly InferenceSession.ValueMetadata[];\n\n  async fetchModelAndCopyToWasmMemory(path: string): Promise<SerializableInternalBuffer> {\n    // fetch model from url and move to wasm heap.\n    return copyFromExternalBuffer(await loadFile(path));\n  }\n\n  async loadModel(pathOrBuffer: string | Uint8Array, options?: InferenceSession.SessionOptions): Promise<void> {\n    TRACE_FUNC_BEGIN();\n    let model: Parameters<typeof createSession>[0];\n\n    if (typeof pathOrBuffer === 'string') {\n      if (isNode) {\n        // node\n        model = await loadFile(pathOrBuffer);\n      } else {\n        // browser\n        // fetch model and copy to wasm heap.\n        model = await this.fetchModelAndCopyToWasmMemory(pathOrBuffer);\n      }\n    } else {\n      model = pathOrBuffer;\n    }\n\n    [this.sessionId, this.inputNames, this.outputNames, this.inputMetadata, this.outputMetadata] = await createSession(\n      model,\n      options,\n    );\n    TRACE_FUNC_END();\n  }\n\n  async dispose(): Promise<void> {\n    return releaseSession(this.sessionId);\n  }\n\n  async run(\n    feeds: SessionHandler.FeedsType,\n    fetches: SessionHandler.FetchesType,\n    options: InferenceSession.RunOptions,\n  ): Promise<SessionHandler.ReturnType> {\n    TRACE_FUNC_BEGIN();\n    const inputArray: Tensor[] = [];\n    const inputIndices: number[] = [];\n    Object.entries(feeds).forEach((kvp) => {\n      const name = kvp[0];\n      const tensor = kvp[1];\n      const index = this.inputNames.indexOf(name);\n      if (index === -1) {\n        throw new Error(`invalid input '${name}'`);\n      }\n      inputArray.push(tensor);\n      inputIndices.push(index);\n    });\n\n    const outputArray: Array<Tensor | null> = [];\n    const outputIndices: number[] = [];\n    Object.entries(fetches).forEach((kvp) => {\n      const name = kvp[0];\n      const tensor = kvp[1];\n      const index = this.outputNames.indexOf(name);\n      if (index === -1) {\n        throw new Error(`invalid output '${name}'`);\n      }\n      outputArray.push(tensor);\n      outputIndices.push(index);\n    });\n\n    const inputs = inputArray.map((t, i) =>\n      encodeTensorMetadata(t, () => `input \"${this.inputNames[inputIndices[i]]}\"`),\n    );\n    const outputs = outputArray.map((t, i) =>\n      t ? encodeTensorMetadata(t, () => `output \"${this.outputNames[outputIndices[i]]}\"`) : null,\n    );\n\n    const results = await run(this.sessionId, inputIndices, inputs, outputIndices, outputs, options);\n\n    const resultMap: SessionHandler.ReturnType = {};\n    for (let i = 0; i < results.length; i++) {\n      resultMap[this.outputNames[outputIndices[i]]] = outputArray[i] ?? decodeTensorMetadata(results[i]);\n    }\n    TRACE_FUNC_END();\n    return resultMap;\n  }\n\n  startProfiling(): void {\n    // TODO: implement profiling\n  }\n\n  endProfiling(): void {\n    void endProfiling(this.sessionId);\n  }\n}\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\nimport { Backend, env, InferenceSession, InferenceSessionHandler } from 'onnxruntime-common';\n\nimport { initializeOrtEp, initializeWebAssemblyAndOrtRuntime } from './wasm/proxy-wrapper';\nimport { OnnxruntimeWebAssemblySessionHandler } from './wasm/session-handler-inference';\n\n/**\n * This function initializes all flags for WebAssembly.\n *\n * Those flags are accessible from `ort.env.wasm`. Users are allow to set those flags before the first inference session\n * being created, to override default value.\n */\nexport const initializeFlags = (): void => {\n  if (typeof env.wasm.initTimeout !== 'number' || env.wasm.initTimeout < 0) {\n    env.wasm.initTimeout = 0;\n  }\n\n  const simd = env.wasm.simd;\n  if (typeof simd !== 'boolean' && simd !== undefined && simd !== 'fixed' && simd !== 'relaxed') {\n    // eslint-disable-next-line no-console\n    console.warn(\n      `Property \"env.wasm.simd\" is set to unknown value \"${simd}\". Reset it to \\`false\\` and ignore SIMD feature checking.`,\n    );\n    env.wasm.simd = false;\n  }\n\n  if (typeof env.wasm.proxy !== 'boolean') {\n    env.wasm.proxy = false;\n  }\n\n  if (typeof env.wasm.trace !== 'boolean') {\n    env.wasm.trace = false;\n  }\n\n  if (typeof env.wasm.numThreads !== 'number' || !Number.isInteger(env.wasm.numThreads) || env.wasm.numThreads <= 0) {\n    // The following logic only applies when `ort.env.wasm.numThreads` is not set by user. We will always honor user's\n    // setting if it is provided.\n\n    // Browser: when crossOriginIsolated is false, SharedArrayBuffer is not available so WebAssembly threads will not\n    // work. In this case, we will set numThreads to 1.\n    //\n    // There is an exception: when the browser is configured to force-enable SharedArrayBuffer (e.g. Chromuim with\n    // --enable-features=SharedArrayBuffer), it is possible that `self.crossOriginIsolated` is false and\n    // SharedArrayBuffer is available at the same time. This is usually for testing. In this case,  we will still set\n    // numThreads to 1 here. If we want to enable multi-threading in test, we should set `ort.env.wasm.numThreads` to a\n    // value greater than 1.\n    if (typeof self !== 'undefined' && !self.crossOriginIsolated) {\n      env.wasm.numThreads = 1;\n    } else {\n      const numCpuLogicalCores =\n        typeof navigator === 'undefined' ? require('node:os').cpus().length : navigator.hardwareConcurrency;\n      env.wasm.numThreads = Math.min(4, Math.ceil((numCpuLogicalCores || 1) / 2));\n    }\n  }\n};\n\nexport class OnnxruntimeWebAssemblyBackend implements Backend {\n  /**\n   * This function initializes the WebAssembly backend.\n   *\n   * This function will be called only once for each backend name. It will be called the first time when\n   * `ort.InferenceSession.create()` is called with a registered backend name.\n   *\n   * @param backendName - the registered backend name.\n   */\n  async init(backendName: string): Promise<void> {\n    // populate wasm flags\n    initializeFlags();\n\n    // init wasm\n    await initializeWebAssemblyAndOrtRuntime();\n\n    // performe EP specific initialization\n    await initializeOrtEp(backendName);\n  }\n  createInferenceSessionHandler(\n    path: string,\n    options?: InferenceSession.SessionOptions,\n  ): Promise<InferenceSessionHandler>;\n  createInferenceSessionHandler(\n    buffer: Uint8Array,\n    options?: InferenceSession.SessionOptions,\n  ): Promise<InferenceSessionHandler>;\n  async createInferenceSessionHandler(\n    pathOrBuffer: string | Uint8Array,\n    options?: InferenceSession.SessionOptions,\n  ): Promise<InferenceSessionHandler> {\n    const handler = new OnnxruntimeWebAssemblySessionHandler();\n    await handler.loadModel(pathOrBuffer, options);\n    return handler;\n  }\n}\n\nexport const wasmBackend = new OnnxruntimeWebAssemblyBackend();\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\n/* eslint-disable @typescript-eslint/no-var-requires, @typescript-eslint/no-require-imports */\n\n// We use \"require\" instead of \"import\" here because import statement must be put in top level. Our current code does\n// not allow bundler to tree-shaking code as expected because some codes are treated as having side effects.\n// So we import code inside the if-clause to allow bundler remove the code safely.\n\nexport * from 'onnxruntime-common';\nimport * as ort from 'onnxruntime-common';\nexport default ort;\n\nimport { registerBackend, env } from 'onnxruntime-common';\nimport { version } from './version';\n\nif (!BUILD_DEFS.DISABLE_WEBGL) {\n  const onnxjsBackend = require('./backend-onnxjs').onnxjsBackend;\n  registerBackend('webgl', onnxjsBackend, -10);\n}\n\nif (!BUILD_DEFS.DISABLE_JSEP && !BUILD_DEFS.DISABLE_WEBGPU) {\n  throw new Error(\n    'The current build is specified to enable both JSEP and WebGPU EP. This is not a valid configuration. ' +\n      'JSEP and WebGPU EPs cannot be enabled at the same time.',\n  );\n}\n\nif (!BUILD_DEFS.DISABLE_WEBNN && BUILD_DEFS.DISABLE_JSEP && BUILD_DEFS.DISABLE_WEBGPU) {\n  throw new Error(\n    'The current build is specified to enable WebNN EP without JSEP or WebGPU EP. This is not a valid configuration. ' +\n      'WebNN EP requires either JSEP or WebGPU EP to be enabled.',\n  );\n}\n\nif (!BUILD_DEFS.DISABLE_WASM) {\n  const wasmBackend = require('./backend-wasm').wasmBackend;\n  if (!BUILD_DEFS.DISABLE_JSEP || !BUILD_DEFS.DISABLE_WEBGPU) {\n    registerBackend('webgpu', wasmBackend, 5);\n  }\n  if (!BUILD_DEFS.DISABLE_WEBNN) {\n    registerBackend('webnn', wasmBackend, 5);\n  }\n  registerBackend('cpu', wasmBackend, 10);\n  registerBackend('wasm', wasmBackend, 10);\n}\n\nObject.defineProperty(env.versions, 'web', { value: version, enumerable: true });\n","// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n\n// This file is generated by /js/scripts/update-version.ts\n// Do not modify file content manually.\n\nexport const version = '1.29.0';\n","var grammar = module.exports = {\n  v: [{\n    name: 'version',\n    reg: /^(\\d*)$/\n  }],\n  o: [{ //o=- 20518 0 IN IP4 203.0.113.1\n    // NB: sessionId will be a String in most cases because it is huge\n    name: 'origin',\n    reg: /^(\\S*) (\\d*) (\\d*) (\\S*) IP(\\d) (\\S*)/,\n    names: ['username', 'sessionId', 'sessionVersion', 'netType', 'ipVer', 'address'],\n    format: '%s %s %d %s IP%d %s'\n  }],\n  // default parsing of these only (though some of these feel outdated)\n  s: [{ name: 'name' }],\n  i: [{ name: 'description' }],\n  u: [{ name: 'uri' }],\n  e: [{ name: 'email' }],\n  p: [{ name: 'phone' }],\n  z: [{ name: 'timezones' }], // TODO: this one can actually be parsed properly..\n  r: [{ name: 'repeats' }],   // TODO: this one can also be parsed properly\n  //k: [{}], // outdated thing ignored\n  t: [{ //t=0 0\n    name: 'timing',\n    reg: /^(\\d*) (\\d*)/,\n    names: ['start', 'stop'],\n    format: '%d %d'\n  }],\n  c: [{ //c=IN IP4 10.47.197.26\n    name: 'connection',\n    reg: /^IN IP(\\d) (\\S*)/,\n    names: ['version', 'ip'],\n    format: 'IN IP%d %s'\n  }],\n  b: [{ //b=AS:4000\n    push: 'bandwidth',\n    reg: /^(TIAS|AS|CT|RR|RS):(\\d*)/,\n    names: ['type', 'limit'],\n    format: '%s:%s'\n  }],\n  m: [{ //m=video 51744 RTP/AVP 126 97 98 34 31\n    // NB: special - pushes to session\n    // TODO: rtp/fmtp should be filtered by the payloads found here?\n    reg: /^(\\w*) (\\d*) ([\\w\\/]*)(?: (.*))?/,\n    names: ['type', 'port', 'protocol', 'payloads'],\n    format: '%s %d %s %s'\n  }],\n  a: [\n    { //a=rtpmap:110 opus/48000/2\n      push: 'rtp',\n      reg: /^rtpmap:(\\d*) ([\\w\\-\\.]*)(?:\\s*\\/(\\d*)(?:\\s*\\/(\\S*))?)?/,\n      names: ['payload', 'codec', 'rate', 'encoding'],\n      format: function (o) {\n        return (o.encoding) ?\n          'rtpmap:%d %s/%s/%s':\n          o.rate ?\n          'rtpmap:%d %s/%s':\n          'rtpmap:%d %s';\n      }\n    },\n    { //a=fmtp:108 profile-level-id=24;object=23;bitrate=64000\n      //a=fmtp:111 minptime=10; useinbandfec=1\n      push: 'fmtp',\n      reg: /^fmtp:(\\d*) ([\\S| ]*)/,\n      names: ['payload', 'config'],\n      format: 'fmtp:%d %s'\n    },\n    { //a=control:streamid=0\n      name: 'control',\n      reg: /^control:(.*)/,\n      format: 'control:%s'\n    },\n    { //a=rtcp:65179 IN IP4 193.84.77.194\n      name: 'rtcp',\n      reg: /^rtcp:(\\d*)(?: (\\S*) IP(\\d) (\\S*))?/,\n      names: ['port', 'netType', 'ipVer', 'address'],\n      format: function (o) {\n        return (o.address != null) ?\n          'rtcp:%d %s IP%d %s':\n          'rtcp:%d';\n      }\n    },\n    { //a=rtcp-fb:98 trr-int 100\n      push: 'rtcpFbTrrInt',\n      reg: /^rtcp-fb:(\\*|\\d*) trr-int (\\d*)/,\n      names: ['payload', 'value'],\n      format: 'rtcp-fb:%d trr-int %d'\n    },\n    { //a=rtcp-fb:98 nack rpsi\n      push: 'rtcpFb',\n      reg: /^rtcp-fb:(\\*|\\d*) ([\\w-_]*)(?: ([\\w-_]*))?/,\n      names: ['payload', 'type', 'subtype'],\n      format: function (o) {\n        return (o.subtype != null) ?\n          'rtcp-fb:%s %s %s':\n          'rtcp-fb:%s %s';\n      }\n    },\n    { //a=extmap:2 urn:ietf:params:rtp-hdrext:toffset\n      //a=extmap:1/recvonly URI-gps-string\n      push: 'ext',\n      reg: /^extmap:(\\d+)(?:\\/(\\w+))? (\\S*)(?: (\\S*))?/,\n      names: ['value', 'direction', 'uri', 'config'],\n      format: function (o) {\n        return 'extmap:%d' + (o.direction ? '/%s' : '%v') + ' %s' + (o.config ? ' %s' : '');\n      }\n    },\n    { //a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:PS1uQCVeeCFCanVmcjkpPywjNWhcYD0mXXtxaVBR|2^20|1:32\n      push: 'crypto',\n      reg: /^crypto:(\\d*) ([\\w_]*) (\\S*)(?: (\\S*))?/,\n      names: ['id', 'suite', 'config', 'sessionConfig'],\n      format: function (o) {\n        return (o.sessionConfig != null) ?\n          'crypto:%d %s %s %s':\n          'crypto:%d %s %s';\n      }\n    },\n    { //a=setup:actpass\n      name: 'setup',\n      reg: /^setup:(\\w*)/,\n      format: 'setup:%s'\n    },\n    { //a=mid:1\n      name: 'mid',\n      reg: /^mid:([^\\s]*)/,\n      format: 'mid:%s'\n    },\n    { //a=msid:0c8b064d-d807-43b4-b434-f92a889d8587 98178685-d409-46e0-8e16-7ef0db0db64a\n      name: 'msid',\n      reg: /^msid:(.*)/,\n      format: 'msid:%s'\n    },\n    { //a=ptime:20\n      name: 'ptime',\n      reg: /^ptime:(\\d*)/,\n      format: 'ptime:%d'\n    },\n    { //a=maxptime:60\n      name: 'maxptime',\n      reg: /^maxptime:(\\d*)/,\n      format: 'maxptime:%d'\n    },\n    { //a=sendrecv\n      name: 'direction',\n      reg: /^(sendrecv|recvonly|sendonly|inactive)/\n    },\n    { //a=ice-lite\n      name: 'icelite',\n      reg: /^(ice-lite)/\n    },\n    { //a=ice-ufrag:F7gI\n      name: 'iceUfrag',\n      reg: /^ice-ufrag:(\\S*)/,\n      format: 'ice-ufrag:%s'\n    },\n    { //a=ice-pwd:x9cml/YzichV2+XlhiMu8g\n      name: 'icePwd',\n      reg: /^ice-pwd:(\\S*)/,\n      format: 'ice-pwd:%s'\n    },\n    { //a=fingerprint:SHA-1 00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF:00:11:22:33\n      name: 'fingerprint',\n      reg: /^fingerprint:(\\S*) (\\S*)/,\n      names: ['type', 'hash'],\n      format: 'fingerprint:%s %s'\n    },\n    { //a=candidate:0 1 UDP 2113667327 203.0.113.1 54400 typ host\n      //a=candidate:1162875081 1 udp 2113937151 192.168.34.75 60017 typ host generation 0 network-id 3 network-cost 10\n      //a=candidate:3289912957 2 udp 1845501695 193.84.77.194 60017 typ srflx raddr 192.168.34.75 rport 60017 generation 0 network-id 3 network-cost 10\n      //a=candidate:229815620 1 tcp 1518280447 192.168.150.19 60017 typ host tcptype active generation 0 network-id 3 network-cost 10\n      //a=candidate:3289912957 2 tcp 1845501695 193.84.77.194 60017 typ srflx raddr 192.168.34.75 rport 60017 tcptype passive generation 0 network-id 3 network-cost 10\n      push:'candidates',\n      reg: /^candidate:(\\S*) (\\d*) (\\S*) (\\d*) (\\S*) (\\d*) typ (\\S*)(?: raddr (\\S*) rport (\\d*))?(?: tcptype (\\S*))?(?: generation (\\d*))?(?: network-id (\\d*))?(?: network-cost (\\d*))?/,\n      names: ['foundation', 'component', 'transport', 'priority', 'ip', 'port', 'type', 'raddr', 'rport', 'tcptype', 'generation', 'network-id', 'network-cost'],\n      format: function (o) {\n        var str = 'candidate:%s %d %s %d %s %d typ %s';\n\n        str += (o.raddr != null) ? ' raddr %s rport %d' : '%v%v';\n\n        // NB: candidate has three optional chunks, so %void middles one if it's missing\n        str += (o.tcptype != null) ? ' tcptype %s' : '%v';\n\n        if (o.generation != null) {\n          str += ' generation %d';\n        }\n\n        str += (o['network-id'] != null) ? ' network-id %d' : '%v';\n        str += (o['network-cost'] != null) ? ' network-cost %d' : '%v';\n        return str;\n      }\n    },\n    { //a=end-of-candidates (keep after the candidates line for readability)\n      name: 'endOfCandidates',\n      reg: /^(end-of-candidates)/\n    },\n    { //a=remote-candidates:1 203.0.113.1 54400 2 203.0.113.1 54401 ...\n      name: 'remoteCandidates',\n      reg: /^remote-candidates:(.*)/,\n      format: 'remote-candidates:%s'\n    },\n    { //a=ice-options:google-ice\n      name: 'iceOptions',\n      reg: /^ice-options:(\\S*)/,\n      format: 'ice-options:%s'\n    },\n    { //a=ssrc:2566107569 cname:t9YU8M1UxTF8Y1A1\n      push: 'ssrcs',\n      reg: /^ssrc:(\\d*) ([\\w_]*)(?::(.*))?/,\n      names: ['id', 'attribute', 'value'],\n      format: function (o) {\n        var str = 'ssrc:%d';\n        if (o.attribute != null) {\n          str += ' %s';\n          if (o.value != null) {\n            str += ':%s';\n          }\n        }\n        return str;\n      }\n    },\n    { //a=ssrc-group:FEC 1 2\n      //a=ssrc-group:FEC-FR 3004364195 1080772241\n      push: 'ssrcGroups',\n      // token-char = %x21 / %x23-27 / %x2A-2B / %x2D-2E / %x30-39 / %x41-5A / %x5E-7E\n      reg: /^ssrc-group:([\\x21\\x23\\x24\\x25\\x26\\x27\\x2A\\x2B\\x2D\\x2E\\w]*) (.*)/,\n      names: ['semantics', 'ssrcs'],\n      format: 'ssrc-group:%s %s'\n    },\n    { //a=msid-semantic: WMS Jvlam5X3SX1OP6pn20zWogvaKJz5Hjf9OnlV\n      name: 'msidSemantic',\n      reg: /^msid-semantic:\\s?(\\w*) (\\S*)/,\n      names: ['semantic', 'token'],\n      format: 'msid-semantic: %s %s' // space after ':' is not accidental\n    },\n    { //a=group:BUNDLE audio video\n      push: 'groups',\n      reg: /^group:(\\w*) (.*)/,\n      names: ['type', 'mids'],\n      format: 'group:%s %s'\n    },\n    { //a=rtcp-mux\n      name: 'rtcpMux',\n      reg: /^(rtcp-mux)/\n    },\n    { //a=rtcp-rsize\n      name: 'rtcpRsize',\n      reg: /^(rtcp-rsize)/\n    },\n    { //a=sctpmap:5000 webrtc-datachannel 1024\n      name: 'sctpmap',\n      reg: /^sctpmap:([\\w_\\/]*) (\\S*)(?: (\\S*))?/,\n      names: ['sctpmapNumber', 'app', 'maxMessageSize'],\n      format: function (o) {\n        return (o.maxMessageSize != null) ?\n          'sctpmap:%s %s %s' :\n          'sctpmap:%s %s';\n      }\n    },\n    { //a=x-google-flag:conference\n      name: 'xGoogleFlag',\n      reg: /^x-google-flag:([^\\s]*)/,\n      format: 'x-google-flag:%s'\n    },\n    { //a=rid:1 send max-width=1280;max-height=720;max-fps=30;depend=0\n      push: 'rids',\n      reg: /^rid:([\\d\\w]+) (\\w+)(?: ([\\S| ]*))?/,\n      names: ['id', 'direction', 'params'],\n      format: function (o) {\n        return (o.params) ? 'rid:%s %s %s' : 'rid:%s %s';\n      }\n    },\n    { //a=imageattr:97 send [x=800,y=640,sar=1.1,q=0.6] [x=480,y=320] recv [x=330,y=250]\n      //a=imageattr:* send [x=800,y=640] recv *\n      //a=imageattr:100 recv [x=320,y=240]\n      push: 'imageattrs',\n      reg: new RegExp(\n        //a=imageattr:97\n        '^imageattr:(\\\\d+|\\\\*)' +\n        //send [x=800,y=640,sar=1.1,q=0.6] [x=480,y=320]\n        '[\\\\s\\\\t]+(send|recv)[\\\\s\\\\t]+(\\\\*|\\\\[\\\\S+\\\\](?:[\\\\s\\\\t]+\\\\[\\\\S+\\\\])*)' +\n        //recv [x=330,y=250]\n        '(?:[\\\\s\\\\t]+(recv|send)[\\\\s\\\\t]+(\\\\*|\\\\[\\\\S+\\\\](?:[\\\\s\\\\t]+\\\\[\\\\S+\\\\])*))?'\n      ),\n      names: ['pt', 'dir1', 'attrs1', 'dir2', 'attrs2'],\n      format: function (o) {\n        return 'imageattr:%s %s %s' + (o.dir2 ? ' %s %s' : '');\n      }\n    },\n    { //a=simulcast:send 1,2,3;~4,~5 recv 6;~7,~8\n      //a=simulcast:recv 1;4,5 send 6;7\n      name: 'simulcast',\n      reg: new RegExp(\n        //a=simulcast:\n        '^simulcast:' +\n        //send 1,2,3;~4,~5\n        '(send|recv) ([a-zA-Z0-9\\\\-_~;,]+)' +\n        //space + recv 6;~7,~8\n        '(?:\\\\s?(send|recv) ([a-zA-Z0-9\\\\-_~;,]+))?' +\n        //end\n        '$'\n      ),\n      names: ['dir1', 'list1', 'dir2', 'list2'],\n      format: function (o) {\n        return 'simulcast:%s %s' + (o.dir2 ? ' %s %s' : '');\n      }\n    },\n    { //Old simulcast draft 03 (implemented by Firefox)\n      //  https://tools.ietf.org/html/draft-ietf-mmusic-sdp-simulcast-03\n      //a=simulcast: recv pt=97;98 send pt=97\n      //a=simulcast: send rid=5;6;7 paused=6,7\n      name: 'simulcast_03',\n      reg: /^simulcast:[\\s\\t]+([\\S+\\s\\t]+)$/,\n      names: ['value'],\n      format: 'simulcast: %s'\n    },\n    {\n      //a=framerate:25\n      //a=framerate:29.97\n      name: 'framerate',\n      reg: /^framerate:(\\d+(?:$|\\.\\d+))/,\n      format: 'framerate:%s'\n    },\n    { // any a= that we don't understand is kepts verbatim on media.invalid\n      push: 'invalid',\n      names: ['value']\n    }\n  ]\n};\n\n// set sensible defaults to avoid polluting the grammar with boring details\nObject.keys(grammar).forEach(function (key) {\n  var objs = grammar[key];\n  objs.forEach(function (obj) {\n    if (!obj.reg) {\n      obj.reg = /(.*)/;\n    }\n    if (!obj.format) {\n      obj.format = '%s';\n    }\n  });\n});\n","var parser = require('./parser');\nvar writer = require('./writer');\n\nexports.write = writer;\nexports.parse = parser.parse;\nexports.parseFmtpConfig = parser.parseFmtpConfig;\nexports.parseParams = parser.parseParams;\nexports.parsePayloads = parser.parsePayloads;\nexports.parseRemoteCandidates = parser.parseRemoteCandidates;\nexports.parseImageAttributes = parser.parseImageAttributes;\nexports.parseSimulcastStreamList = parser.parseSimulcastStreamList;\n","var toIntIfInt = function (v) {\n  return String(Number(v)) === v ? Number(v) : v;\n};\n\nvar attachProperties = function (match, location, names, rawName) {\n  if (rawName && !names) {\n    location[rawName] = toIntIfInt(match[1]);\n  }\n  else {\n    for (var i = 0; i < names.length; i += 1) {\n      if (match[i+1] != null) {\n        location[names[i]] = toIntIfInt(match[i+1]);\n      }\n    }\n  }\n};\n\nvar parseReg = function (obj, location, content) {\n  var needsBlank = obj.name && obj.names;\n  if (obj.push && !location[obj.push]) {\n    location[obj.push] = [];\n  }\n  else if (needsBlank && !location[obj.name]) {\n    location[obj.name] = {};\n  }\n  var keyLocation = obj.push ?\n    {} :  // blank object that will be pushed\n    needsBlank ? location[obj.name] : location; // otherwise, named location or root\n\n  attachProperties(content.match(obj.reg), keyLocation, obj.names, obj.name);\n\n  if (obj.push) {\n    location[obj.push].push(keyLocation);\n  }\n};\n\nvar grammar = require('./grammar');\nvar validLine = RegExp.prototype.test.bind(/^([a-z])=(.*)/);\n\nexports.parse = function (sdp) {\n  var session = {}\n    , media = []\n    , location = session; // points at where properties go under (one of the above)\n\n  // parse lines we understand\n  sdp.split(/(\\r\\n|\\r|\\n)/).filter(validLine).forEach(function (l) {\n    var type = l[0];\n    var content = l.slice(2);\n    if (type === 'm') {\n      media.push({rtp: [], fmtp: []});\n      location = media[media.length-1]; // point at latest media line\n    }\n\n    for (var j = 0; j < (grammar[type] || []).length; j += 1) {\n      var obj = grammar[type][j];\n      if (obj.reg.test(content)) {\n        return parseReg(obj, location, content);\n      }\n    }\n  });\n\n  session.media = media; // link it up\n  return session;\n};\n\nvar paramReducer = function (acc, expr) {\n  var s = expr.split(/=(.+)/, 2);\n  if (s.length === 2) {\n    acc[s[0]] = toIntIfInt(s[1]);\n  }\n  return acc;\n};\n\nexports.parseParams = function (str) {\n  return str.split(/\\;\\s?/).reduce(paramReducer, {});\n};\n\n// For backward compatibility - alias will be removed in 3.0.0\nexports.parseFmtpConfig = exports.parseParams;\n\nexports.parsePayloads = function (str) {\n  return str.split(' ').map(Number);\n};\n\nexports.parseRemoteCandidates = function (str) {\n  var candidates = [];\n  var parts = str.split(' ').map(toIntIfInt);\n  for (var i = 0; i < parts.length; i += 3) {\n    candidates.push({\n      component: parts[i],\n      ip: parts[i + 1],\n      port: parts[i + 2]\n    });\n  }\n  return candidates;\n};\n\nexports.parseImageAttributes = function (str) {\n  return str.split(' ').map(function (item) {\n    return item.substring(1, item.length-1).split(',').reduce(paramReducer, {});\n  });\n};\n\nexports.parseSimulcastStreamList = function (str) {\n  return str.split(';').map(function (stream) {\n    return stream.split(',').map(function (format) {\n      var scid, paused = false;\n\n      if (format[0] !== '~') {\n        scid = toIntIfInt(format);\n      } else {\n        scid = toIntIfInt(format.substring(1, format.length));\n        paused = true;\n      }\n\n      return {\n        scid: scid,\n        paused: paused\n      };\n    });\n  });\n};\n","var grammar = require('./grammar');\n\n// customized util.format - discards excess arguments and can void middle ones\nvar formatRegExp = /%[sdv%]/g;\nvar format = function (formatStr) {\n  var i = 1;\n  var args = arguments;\n  var len = args.length;\n  return formatStr.replace(formatRegExp, function (x) {\n    if (i >= len) {\n      return x; // missing argument\n    }\n    var arg = args[i];\n    i += 1;\n    switch (x) {\n    case '%%':\n      return '%';\n    case '%s':\n      return String(arg);\n    case '%d':\n      return Number(arg);\n    case '%v':\n      return '';\n    }\n  });\n  // NB: we discard excess arguments - they are typically undefined from makeLine\n};\n\nvar makeLine = function (type, obj, location) {\n  var str = obj.format instanceof Function ?\n    (obj.format(obj.push ? location : location[obj.name])) :\n    obj.format;\n\n  var args = [type + '=' + str];\n  if (obj.names) {\n    for (var i = 0; i < obj.names.length; i += 1) {\n      var n = obj.names[i];\n      if (obj.name) {\n        args.push(location[obj.name][n]);\n      }\n      else { // for mLine and push attributes\n        args.push(location[obj.names[i]]);\n      }\n    }\n  }\n  else {\n    args.push(location[obj.name]);\n  }\n  return format.apply(null, args);\n};\n\n// RFC specified order\n// TODO: extend this with all the rest\nvar defaultOuterOrder = [\n  'v', 'o', 's', 'i',\n  'u', 'e', 'p', 'c',\n  'b', 't', 'r', 'z', 'a'\n];\nvar defaultInnerOrder = ['i', 'c', 'b', 'a'];\n\n\nmodule.exports = function (session, opts) {\n  opts = opts || {};\n  // ensure certain properties exist\n  if (session.version == null) {\n    session.version = 0; // 'v=0' must be there (only defined version atm)\n  }\n  if (session.name == null) {\n    session.name = ' '; // 's= ' must be there if no meaningful name set\n  }\n  session.media.forEach(function (mLine) {\n    if (mLine.payloads == null) {\n      mLine.payloads = '';\n    }\n  });\n\n  var outerOrder = opts.outerOrder || defaultOuterOrder;\n  var innerOrder = opts.innerOrder || defaultInnerOrder;\n  var sdp = [];\n\n  // loop through outerOrder for matching properties on session\n  outerOrder.forEach(function (type) {\n    grammar[type].forEach(function (obj) {\n      if (obj.name in session && session[obj.name] != null) {\n        sdp.push(makeLine(type, obj, session));\n      }\n      else if (obj.push in session && session[obj.push] != null) {\n        session[obj.push].forEach(function (el) {\n          sdp.push(makeLine(type, obj, el));\n        });\n      }\n    });\n  });\n\n  // then for each media line, follow the innerOrder\n  session.media.forEach(function (mLine) {\n    sdp.push(makeLine('m', grammar.m[0], mLine));\n\n    innerOrder.forEach(function (type) {\n      grammar[type].forEach(function (obj) {\n        if (obj.name in mLine && mLine[obj.name] != null) {\n          sdp.push(makeLine(type, obj, mLine));\n        }\n        else if (obj.push in mLine && mLine[obj.push] != null) {\n          mLine[obj.push].forEach(function (el) {\n            sdp.push(makeLine(type, obj, el));\n          });\n        }\n      });\n    });\n  });\n\n  return sdp.join('\\r\\n') + '\\r\\n';\n};\n","/* eslint-env node */\n'use strict';\n\n// SDP helpers.\nconst SDPUtils = {};\n\n// Generate an alphanumeric identifier for cname or mids.\n// TODO: use UUIDs instead? https://gist.github.com/jed/982883\nSDPUtils.generateIdentifier = function() {\n  return Math.random().toString(36).substring(2, 12);\n};\n\n// The RTCP CNAME used by all peerconnections from the same JS.\nSDPUtils.localCName = SDPUtils.generateIdentifier();\n\n// Splits SDP into lines, dealing with both CRLF and LF.\nSDPUtils.splitLines = function(blob) {\n  return blob.trim().split('\\n').map(line => line.trim());\n};\n// Splits SDP into sessionpart and mediasections. Ensures CRLF.\nSDPUtils.splitSections = function(blob) {\n  const parts = blob.split('\\nm=');\n  return parts.map((part, index) => (index > 0 ?\n    'm=' + part : part).trim() + '\\r\\n');\n};\n\n// Returns the session description.\nSDPUtils.getDescription = function(blob) {\n  const sections = SDPUtils.splitSections(blob);\n  return sections && sections[0];\n};\n\n// Returns the individual media sections.\nSDPUtils.getMediaSections = function(blob) {\n  const sections = SDPUtils.splitSections(blob);\n  sections.shift();\n  return sections;\n};\n\n// Returns lines that start with a certain prefix.\nSDPUtils.matchPrefix = function(blob, prefix) {\n  return SDPUtils.splitLines(blob).filter(line => line.indexOf(prefix) === 0);\n};\n\n// Parses an ICE candidate line. Sample input:\n// candidate:702786350 2 udp 41819902 8.8.8.8 60769 typ relay raddr 8.8.8.8\n// rport 55996\"\n// Input can be prefixed with a=.\nSDPUtils.parseCandidate = function(line) {\n  let parts;\n  // Parse both variants.\n  if (line.indexOf('a=candidate:') === 0) {\n    parts = line.substring(12).split(' ');\n  } else {\n    parts = line.substring(10).split(' ');\n  }\n\n  const candidate = {\n    foundation: parts[0],\n    component: {1: 'rtp', 2: 'rtcp'}[parts[1]] || parts[1],\n    protocol: parts[2].toLowerCase(),\n    priority: parseInt(parts[3], 10),\n    ip: parts[4],\n    address: parts[4], // address is an alias for ip.\n    port: parseInt(parts[5], 10),\n    // skip parts[6] == 'typ'\n    type: parts[7],\n  };\n\n  for (let i = 8; i < parts.length; i += 2) {\n    switch (parts[i]) {\n      case 'raddr':\n        candidate.relatedAddress = parts[i + 1];\n        break;\n      case 'rport':\n        candidate.relatedPort = parseInt(parts[i + 1], 10);\n        break;\n      case 'tcptype':\n        candidate.tcpType = parts[i + 1];\n        break;\n      case 'ufrag':\n        candidate.ufrag = parts[i + 1]; // for backward compatibility.\n        candidate.usernameFragment = parts[i + 1];\n        break;\n      default: // extension handling, in particular ufrag. Don't overwrite.\n        if (candidate[parts[i]] === undefined) {\n          candidate[parts[i]] = parts[i + 1];\n        }\n        break;\n    }\n  }\n  return candidate;\n};\n\n// Translates a candidate object into SDP candidate attribute.\n// This does not include the a= prefix!\nSDPUtils.writeCandidate = function(candidate) {\n  const sdp = [];\n  sdp.push(candidate.foundation);\n\n  const component = candidate.component;\n  if (component === 'rtp') {\n    sdp.push(1);\n  } else if (component === 'rtcp') {\n    sdp.push(2);\n  } else {\n    sdp.push(component);\n  }\n  sdp.push(candidate.protocol.toUpperCase());\n  sdp.push(candidate.priority);\n  sdp.push(candidate.address || candidate.ip);\n  sdp.push(candidate.port);\n\n  const type = candidate.type;\n  sdp.push('typ');\n  sdp.push(type);\n  if (type !== 'host' && candidate.relatedAddress &&\n      candidate.relatedPort) {\n    sdp.push('raddr');\n    sdp.push(candidate.relatedAddress);\n    sdp.push('rport');\n    sdp.push(candidate.relatedPort);\n  }\n  if (candidate.tcpType && candidate.protocol.toLowerCase() === 'tcp') {\n    sdp.push('tcptype');\n    sdp.push(candidate.tcpType);\n  }\n  if (candidate.usernameFragment || candidate.ufrag) {\n    sdp.push('ufrag');\n    sdp.push(candidate.usernameFragment || candidate.ufrag);\n  }\n  return 'candidate:' + sdp.join(' ');\n};\n\n// Parses an ice-options line, returns an array of option tags.\n// Sample input:\n// a=ice-options:foo bar\nSDPUtils.parseIceOptions = function(line) {\n  return line.substring(14).split(' ');\n};\n\n// Parses a rtpmap line, returns RTCRtpCoddecParameters. Sample input:\n// a=rtpmap:111 opus/48000/2\nSDPUtils.parseRtpMap = function(line) {\n  let parts = line.substring(9).split(' ');\n  const parsed = {\n    payloadType: parseInt(parts.shift(), 10), // was: id\n  };\n\n  parts = parts[0].split('/');\n\n  parsed.name = parts[0];\n  parsed.clockRate = parseInt(parts[1], 10); // was: clockrate\n  parsed.channels = parts.length === 3 ? parseInt(parts[2], 10) : 1;\n  // legacy alias, got renamed back to channels in ORTC.\n  parsed.numChannels = parsed.channels;\n  return parsed;\n};\n\n// Generates a rtpmap line from RTCRtpCodecCapability or\n// RTCRtpCodecParameters.\nSDPUtils.writeRtpMap = function(codec) {\n  let pt = codec.payloadType;\n  if (codec.preferredPayloadType !== undefined) {\n    pt = codec.preferredPayloadType;\n  }\n  const channels = codec.channels || codec.numChannels || 1;\n  return 'a=rtpmap:' + pt + ' ' + codec.name + '/' + codec.clockRate +\n      (channels !== 1 ? '/' + channels : '') + '\\r\\n';\n};\n\n// Parses a extmap line (headerextension from RFC 5285). Sample input:\n// a=extmap:2 urn:ietf:params:rtp-hdrext:toffset\n// a=extmap:2/sendonly urn:ietf:params:rtp-hdrext:toffset\nSDPUtils.parseExtmap = function(line) {\n  const parts = line.substring(9).split(' ');\n  return {\n    id: parseInt(parts[0], 10),\n    direction: parts[0].indexOf('/') > 0 ? parts[0].split('/')[1] : 'sendrecv',\n    uri: parts[1],\n    attributes: parts.slice(2).join(' '),\n  };\n};\n\n// Generates an extmap line from RTCRtpHeaderExtensionParameters or\n// RTCRtpHeaderExtension.\nSDPUtils.writeExtmap = function(headerExtension) {\n  return 'a=extmap:' + (headerExtension.id || headerExtension.preferredId) +\n      (headerExtension.direction && headerExtension.direction !== 'sendrecv'\n        ? '/' + headerExtension.direction\n        : '') +\n      ' ' + headerExtension.uri +\n      (headerExtension.attributes ? ' ' + headerExtension.attributes : '') +\n      '\\r\\n';\n};\n\n// Parses a fmtp line, returns dictionary. Sample input:\n// a=fmtp:96 vbr=on;cng=on\n// Also deals with vbr=on; cng=on\n// Non-key-value such as telephone-events `0-15` get parsed as\n// {`0-15`:undefined}\nSDPUtils.parseFmtp = function(line) {\n  const parsed = {};\n  let kv;\n  const parts = line.substring(line.indexOf(' ') + 1).split(';');\n  for (let j = 0; j < parts.length; j++) {\n    kv = parts[j].trim().split('=');\n    parsed[kv[0].trim()] = kv[1];\n  }\n  return parsed;\n};\n\n// Generates a fmtp line from RTCRtpCodecCapability or RTCRtpCodecParameters.\nSDPUtils.writeFmtp = function(codec) {\n  let line = '';\n  let pt = codec.payloadType;\n  if (codec.preferredPayloadType !== undefined) {\n    pt = codec.preferredPayloadType;\n  }\n  if (codec.parameters && Object.keys(codec.parameters).length) {\n    const params = [];\n    Object.keys(codec.parameters).forEach(param => {\n      if (codec.parameters[param] !== undefined) {\n        params.push(param + '=' + codec.parameters[param]);\n      } else {\n        params.push(param);\n      }\n    });\n    line += 'a=fmtp:' + pt + ' ' + params.join(';') + '\\r\\n';\n  }\n  return line;\n};\n\n// Parses a rtcp-fb line, returns RTCPRtcpFeedback object. Sample input:\n// a=rtcp-fb:98 nack rpsi\nSDPUtils.parseRtcpFb = function(line) {\n  const parts = line.substring(line.indexOf(' ') + 1).split(' ');\n  return {\n    type: parts.shift(),\n    parameter: parts.join(' '),\n  };\n};\n\n// Generate a=rtcp-fb lines from RTCRtpCodecCapability or RTCRtpCodecParameters.\nSDPUtils.writeRtcpFb = function(codec) {\n  let lines = '';\n  let pt = codec.payloadType;\n  if (codec.preferredPayloadType !== undefined) {\n    pt = codec.preferredPayloadType;\n  }\n  if (codec.rtcpFeedback && codec.rtcpFeedback.length) {\n    // FIXME: special handling for trr-int?\n    codec.rtcpFeedback.forEach(fb => {\n      lines += 'a=rtcp-fb:' + pt + ' ' + fb.type +\n      (fb.parameter && fb.parameter.length ? ' ' + fb.parameter : '') +\n          '\\r\\n';\n    });\n  }\n  return lines;\n};\n\n// Parses a RFC 5576 ssrc media attribute. Sample input:\n// a=ssrc:3735928559 cname:something\nSDPUtils.parseSsrcMedia = function(line) {\n  const sp = line.indexOf(' ');\n  const parts = {\n    ssrc: parseInt(line.substring(7, sp), 10),\n  };\n  const colon = line.indexOf(':', sp);\n  if (colon > -1) {\n    parts.attribute = line.substring(sp + 1, colon);\n    parts.value = line.substring(colon + 1);\n  } else {\n    parts.attribute = line.substring(sp + 1);\n  }\n  return parts;\n};\n\n// Parse a ssrc-group line (see RFC 5576). Sample input:\n// a=ssrc-group:semantics 12 34\nSDPUtils.parseSsrcGroup = function(line) {\n  const parts = line.substring(13).split(' ');\n  return {\n    semantics: parts.shift(),\n    ssrcs: parts.map(ssrc => parseInt(ssrc, 10)),\n  };\n};\n\n// Extracts the MID (RFC 5888) from a media section.\n// Returns the MID or undefined if no mid line was found.\nSDPUtils.getMid = function(mediaSection) {\n  const mid = SDPUtils.matchPrefix(mediaSection, 'a=mid:')[0];\n  if (mid) {\n    return mid.substring(6);\n  }\n};\n\n// Parses a fingerprint line for DTLS-SRTP.\nSDPUtils.parseFingerprint = function(line) {\n  const parts = line.substring(14).split(' ');\n  return {\n    algorithm: parts[0].toLowerCase(), // algorithm is case-sensitive in Edge.\n    value: parts[1].toUpperCase(), // the definition is upper-case in RFC 4572.\n  };\n};\n\n// Extracts DTLS parameters from SDP media section or sessionpart.\n// FIXME: for consistency with other functions this should only\n//   get the fingerprint line as input. See also getIceParameters.\nSDPUtils.getDtlsParameters = function(mediaSection, sessionpart) {\n  const lines = SDPUtils.matchPrefix(mediaSection + sessionpart,\n    'a=fingerprint:');\n  // Note: a=setup line is ignored since we use the 'auto' role in Edge.\n  return {\n    role: 'auto',\n    fingerprints: lines.map(SDPUtils.parseFingerprint),\n  };\n};\n\n// Serializes DTLS parameters to SDP.\nSDPUtils.writeDtlsParameters = function(params, setupType) {\n  let sdp = 'a=setup:' + setupType + '\\r\\n';\n  params.fingerprints.forEach(fp => {\n    sdp += 'a=fingerprint:' + fp.algorithm + ' ' + fp.value + '\\r\\n';\n  });\n  return sdp;\n};\n\n// Parses a=crypto lines into\n//   https://rawgit.com/aboba/edgertc/master/msortc-rs4.html#dictionary-rtcsrtpsdesparameters-members\nSDPUtils.parseCryptoLine = function(line) {\n  const parts = line.substring(9).split(' ');\n  return {\n    tag: parseInt(parts[0], 10),\n    cryptoSuite: parts[1],\n    keyParams: parts[2],\n    sessionParams: parts.slice(3),\n  };\n};\n\nSDPUtils.writeCryptoLine = function(parameters) {\n  return 'a=crypto:' + parameters.tag + ' ' +\n    parameters.cryptoSuite + ' ' +\n    (typeof parameters.keyParams === 'object'\n      ? SDPUtils.writeCryptoKeyParams(parameters.keyParams)\n      : parameters.keyParams) +\n    (parameters.sessionParams ? ' ' + parameters.sessionParams.join(' ') : '') +\n    '\\r\\n';\n};\n\n// Parses the crypto key parameters into\n//   https://rawgit.com/aboba/edgertc/master/msortc-rs4.html#rtcsrtpkeyparam*\nSDPUtils.parseCryptoKeyParams = function(keyParams) {\n  if (keyParams.indexOf('inline:') !== 0) {\n    return null;\n  }\n  const parts = keyParams.substring(7).split('|');\n  return {\n    keyMethod: 'inline',\n    keySalt: parts[0],\n    lifeTime: parts[1],\n    mkiValue: parts[2] ? parts[2].split(':')[0] : undefined,\n    mkiLength: parts[2] ? parts[2].split(':')[1] : undefined,\n  };\n};\n\nSDPUtils.writeCryptoKeyParams = function(keyParams) {\n  return keyParams.keyMethod + ':'\n    + keyParams.keySalt +\n    (keyParams.lifeTime ? '|' + keyParams.lifeTime : '') +\n    (keyParams.mkiValue && keyParams.mkiLength\n      ? '|' + keyParams.mkiValue + ':' + keyParams.mkiLength\n      : '');\n};\n\n// Extracts all SDES parameters.\nSDPUtils.getCryptoParameters = function(mediaSection, sessionpart) {\n  const lines = SDPUtils.matchPrefix(mediaSection + sessionpart,\n    'a=crypto:');\n  return lines.map(SDPUtils.parseCryptoLine);\n};\n\n// Parses ICE information from SDP media section or sessionpart.\n// FIXME: for consistency with other functions this should only\n//   get the ice-ufrag and ice-pwd lines as input.\nSDPUtils.getIceParameters = function(mediaSection, sessionpart) {\n  const ufrag = SDPUtils.matchPrefix(mediaSection + sessionpart,\n    'a=ice-ufrag:')[0];\n  const pwd = SDPUtils.matchPrefix(mediaSection + sessionpart,\n    'a=ice-pwd:')[0];\n  if (!(ufrag && pwd)) {\n    return null;\n  }\n  return {\n    usernameFragment: ufrag.substring(12),\n    password: pwd.substring(10),\n  };\n};\n\n// Serializes ICE parameters to SDP.\nSDPUtils.writeIceParameters = function(params) {\n  let sdp = 'a=ice-ufrag:' + params.usernameFragment + '\\r\\n' +\n      'a=ice-pwd:' + params.password + '\\r\\n';\n  if (params.iceLite) {\n    sdp += 'a=ice-lite\\r\\n';\n  }\n  return sdp;\n};\n\n// Parses the SDP media section and returns RTCRtpParameters.\nSDPUtils.parseRtpParameters = function(mediaSection) {\n  const description = {\n    codecs: [],\n    headerExtensions: [],\n    fecMechanisms: [],\n    rtcp: [],\n  };\n  const lines = SDPUtils.splitLines(mediaSection);\n  const mline = lines[0].split(' ');\n  description.profile = mline[2];\n  for (let i = 3; i < mline.length; i++) { // find all codecs from mline[3..]\n    const pt = mline[i];\n    const rtpmapline = SDPUtils.matchPrefix(\n      mediaSection, 'a=rtpmap:' + pt + ' ')[0];\n    if (rtpmapline) {\n      const codec = SDPUtils.parseRtpMap(rtpmapline);\n      const fmtps = SDPUtils.matchPrefix(\n        mediaSection, 'a=fmtp:' + pt + ' ');\n      // Only the first a=fmtp:<pt> is considered.\n      codec.parameters = fmtps.length ? SDPUtils.parseFmtp(fmtps[0]) : {};\n      codec.rtcpFeedback = SDPUtils.matchPrefix(\n        mediaSection, 'a=rtcp-fb:' + pt + ' ')\n        .map(SDPUtils.parseRtcpFb);\n      description.codecs.push(codec);\n      // parse FEC mechanisms from rtpmap lines.\n      switch (codec.name.toUpperCase()) {\n        case 'RED':\n        case 'ULPFEC':\n          description.fecMechanisms.push(codec.name.toUpperCase());\n          break;\n        default: // only RED and ULPFEC are recognized as FEC mechanisms.\n          break;\n      }\n    }\n  }\n  SDPUtils.matchPrefix(mediaSection, 'a=extmap:').forEach(line => {\n    description.headerExtensions.push(SDPUtils.parseExtmap(line));\n  });\n  const wildcardRtcpFb = SDPUtils.matchPrefix(mediaSection, 'a=rtcp-fb:* ')\n    .map(SDPUtils.parseRtcpFb);\n  description.codecs.forEach(codec => {\n    wildcardRtcpFb.forEach(fb=> {\n      const duplicate = codec.rtcpFeedback.find(existingFeedback => {\n        return existingFeedback.type === fb.type &&\n          existingFeedback.parameter === fb.parameter;\n      });\n      if (!duplicate) {\n        codec.rtcpFeedback.push(fb);\n      }\n    });\n  });\n  // FIXME: parse rtcp.\n  return description;\n};\n\n// Generates parts of the SDP media section describing the capabilities /\n// parameters.\nSDPUtils.writeRtpDescription = function(kind, caps) {\n  let sdp = '';\n\n  // Build the mline.\n  sdp += 'm=' + kind + ' ';\n  sdp += caps.codecs.length > 0 ? '9' : '0'; // reject if no codecs.\n  sdp += ' ' + (caps.profile || 'UDP/TLS/RTP/SAVPF') + ' ';\n  sdp += caps.codecs.map(codec => {\n    if (codec.preferredPayloadType !== undefined) {\n      return codec.preferredPayloadType;\n    }\n    return codec.payloadType;\n  }).join(' ') + '\\r\\n';\n\n  sdp += 'c=IN IP4 0.0.0.0\\r\\n';\n  sdp += 'a=rtcp:9 IN IP4 0.0.0.0\\r\\n';\n\n  // Add a=rtpmap lines for each codec. Also fmtp and rtcp-fb.\n  caps.codecs.forEach(codec => {\n    sdp += SDPUtils.writeRtpMap(codec);\n    sdp += SDPUtils.writeFmtp(codec);\n    sdp += SDPUtils.writeRtcpFb(codec);\n  });\n  let maxptime = 0;\n  caps.codecs.forEach(codec => {\n    if (codec.maxptime > maxptime) {\n      maxptime = codec.maxptime;\n    }\n  });\n  if (maxptime > 0) {\n    sdp += 'a=maxptime:' + maxptime + '\\r\\n';\n  }\n\n  if (caps.headerExtensions) {\n    caps.headerExtensions.forEach(extension => {\n      sdp += SDPUtils.writeExtmap(extension);\n    });\n  }\n  // FIXME: write fecMechanisms.\n  return sdp;\n};\n\n// Parses the SDP media section and returns an array of\n// RTCRtpEncodingParameters.\nSDPUtils.parseRtpEncodingParameters = function(mediaSection) {\n  const encodingParameters = [];\n  const description = SDPUtils.parseRtpParameters(mediaSection);\n  const hasRed = description.fecMechanisms.indexOf('RED') !== -1;\n  const hasUlpfec = description.fecMechanisms.indexOf('ULPFEC') !== -1;\n\n  // filter a=ssrc:... cname:, ignore PlanB-msid\n  const ssrcs = SDPUtils.matchPrefix(mediaSection, 'a=ssrc:')\n    .map(line => SDPUtils.parseSsrcMedia(line))\n    .filter(parts => parts.attribute === 'cname');\n  const primarySsrc = ssrcs.length > 0 && ssrcs[0].ssrc;\n  let secondarySsrc;\n\n  const flows = SDPUtils.matchPrefix(mediaSection, 'a=ssrc-group:FID')\n    .map(line => {\n      const parts = line.substring(17).split(' ');\n      return parts.map(part => parseInt(part, 10));\n    });\n  if (flows.length > 0 && flows[0].length > 1 && flows[0][0] === primarySsrc) {\n    secondarySsrc = flows[0][1];\n  }\n\n  description.codecs.forEach(codec => {\n    if (codec.name.toUpperCase() === 'RTX' && codec.parameters.apt) {\n      let encParam = {\n        ssrc: primarySsrc,\n        codecPayloadType: parseInt(codec.parameters.apt, 10),\n      };\n      if (primarySsrc && secondarySsrc) {\n        encParam.rtx = {ssrc: secondarySsrc};\n      }\n      encodingParameters.push(encParam);\n      if (hasRed) {\n        encParam = JSON.parse(JSON.stringify(encParam));\n        encParam.fec = {\n          ssrc: primarySsrc,\n          mechanism: hasUlpfec ? 'red+ulpfec' : 'red',\n        };\n        encodingParameters.push(encParam);\n      }\n    }\n  });\n  if (encodingParameters.length === 0 && primarySsrc) {\n    encodingParameters.push({\n      ssrc: primarySsrc,\n    });\n  }\n\n  // we support both b=AS and b=TIAS but interpret AS as TIAS.\n  let bandwidth = SDPUtils.matchPrefix(mediaSection, 'b=');\n  if (bandwidth.length) {\n    if (bandwidth[0].indexOf('b=TIAS:') === 0) {\n      bandwidth = parseInt(bandwidth[0].substring(7), 10);\n    } else if (bandwidth[0].indexOf('b=AS:') === 0) {\n      // use formula from JSEP to convert b=AS to TIAS value.\n      bandwidth = parseInt(bandwidth[0].substring(5), 10) * 1000 * 0.95\n          - (50 * 40 * 8);\n    } else {\n      bandwidth = undefined;\n    }\n    encodingParameters.forEach(params => {\n      params.maxBitrate = bandwidth;\n    });\n  }\n  return encodingParameters;\n};\n\n// parses http://draft.ortc.org/#rtcrtcpparameters*\nSDPUtils.parseRtcpParameters = function(mediaSection) {\n  const rtcpParameters = {};\n\n  // Gets the first SSRC. Note that with RTX there might be multiple\n  // SSRCs.\n  const remoteSsrc = SDPUtils.matchPrefix(mediaSection, 'a=ssrc:')\n    .map(line => SDPUtils.parseSsrcMedia(line))\n    .filter(obj => obj.attribute === 'cname')[0];\n  if (remoteSsrc) {\n    rtcpParameters.cname = remoteSsrc.value;\n    rtcpParameters.ssrc = remoteSsrc.ssrc;\n  }\n\n  // Edge uses the compound attribute instead of reducedSize\n  // compound is !reducedSize\n  const rsize = SDPUtils.matchPrefix(mediaSection, 'a=rtcp-rsize');\n  rtcpParameters.reducedSize = rsize.length > 0;\n  rtcpParameters.compound = rsize.length === 0;\n\n  // parses the rtcp-mux attrіbute.\n  // Note that Edge does not support unmuxed RTCP.\n  const mux = SDPUtils.matchPrefix(mediaSection, 'a=rtcp-mux');\n  rtcpParameters.mux = mux.length > 0;\n\n  return rtcpParameters;\n};\n\nSDPUtils.writeRtcpParameters = function(rtcpParameters) {\n  let sdp = '';\n  if (rtcpParameters.reducedSize) {\n    sdp += 'a=rtcp-rsize\\r\\n';\n  }\n  if (rtcpParameters.mux) {\n    sdp += 'a=rtcp-mux\\r\\n';\n  }\n  if (rtcpParameters.ssrc !== undefined && rtcpParameters.cname) {\n    sdp += 'a=ssrc:' + rtcpParameters.ssrc +\n      ' cname:' + rtcpParameters.cname + '\\r\\n';\n  }\n  return sdp;\n};\n\n\n// parses either a=msid: or a=ssrc:... msid lines and returns\n// the id of the MediaStream and MediaStreamTrack.\nSDPUtils.parseMsid = function(mediaSection) {\n  let parts;\n  const spec = SDPUtils.matchPrefix(mediaSection, 'a=msid:');\n  if (spec.length === 1) {\n    parts = spec[0].substring(7).split(' ');\n    return {stream: parts[0], track: parts[1]};\n  }\n  const planB = SDPUtils.matchPrefix(mediaSection, 'a=ssrc:')\n    .map(line => SDPUtils.parseSsrcMedia(line))\n    .filter(msidParts => msidParts.attribute === 'msid');\n  if (planB.length > 0) {\n    parts = planB[0].value.split(' ');\n    return {stream: parts[0], track: parts[1]};\n  }\n};\n\n// SCTP\n// parses draft-ietf-mmusic-sctp-sdp-26 first and falls back\n// to draft-ietf-mmusic-sctp-sdp-05\nSDPUtils.parseSctpDescription = function(mediaSection) {\n  const mline = SDPUtils.parseMLine(mediaSection);\n  const maxSizeLine = SDPUtils.matchPrefix(mediaSection, 'a=max-message-size:');\n  let maxMessageSize;\n  if (maxSizeLine.length > 0) {\n    maxMessageSize = parseInt(maxSizeLine[0].substring(19), 10);\n  }\n  if (isNaN(maxMessageSize)) {\n    maxMessageSize = 65536;\n  }\n  const sctpPort = SDPUtils.matchPrefix(mediaSection, 'a=sctp-port:');\n  if (sctpPort.length > 0) {\n    return {\n      port: parseInt(sctpPort[0].substring(12), 10),\n      protocol: mline.fmt,\n      maxMessageSize,\n    };\n  }\n  const sctpMapLines = SDPUtils.matchPrefix(mediaSection, 'a=sctpmap:');\n  if (sctpMapLines.length > 0) {\n    const parts = sctpMapLines[0]\n      .substring(10)\n      .split(' ');\n    return {\n      port: parseInt(parts[0], 10),\n      protocol: parts[1],\n      maxMessageSize,\n    };\n  }\n};\n\n// SCTP\n// outputs the draft-ietf-mmusic-sctp-sdp-26 version that all browsers\n// support by now receiving in this format, unless we originally parsed\n// as the draft-ietf-mmusic-sctp-sdp-05 format (indicated by the m-line\n// protocol of DTLS/SCTP -- without UDP/ or TCP/)\nSDPUtils.writeSctpDescription = function(media, sctp) {\n  let output = [];\n  if (media.protocol !== 'DTLS/SCTP') {\n    output = [\n      'm=' + media.kind + ' 9 ' + media.protocol + ' ' + sctp.protocol + '\\r\\n',\n      'c=IN IP4 0.0.0.0\\r\\n',\n      'a=sctp-port:' + sctp.port + '\\r\\n',\n    ];\n  } else {\n    output = [\n      'm=' + media.kind + ' 9 ' + media.protocol + ' ' + sctp.port + '\\r\\n',\n      'c=IN IP4 0.0.0.0\\r\\n',\n      'a=sctpmap:' + sctp.port + ' ' + sctp.protocol + ' 65535\\r\\n',\n    ];\n  }\n  if (sctp.maxMessageSize !== undefined) {\n    output.push('a=max-message-size:' + sctp.maxMessageSize + '\\r\\n');\n  }\n  return output.join('');\n};\n\n// Generate a session ID for SDP.\n// https://tools.ietf.org/html/draft-ietf-rtcweb-jsep-20#section-5.2.1\n// recommends using a cryptographically random +ve 64-bit value\n// but right now this should be acceptable and within the right range\nSDPUtils.generateSessionId = function() {\n  return Math.random().toString().substr(2, 22);\n};\n\n// Write boiler plate for start of SDP\n// sessId argument is optional - if not supplied it will\n// be generated randomly\n// sessVersion is optional and defaults to 2\n// sessUser is optional and defaults to 'thisisadapterortc'\nSDPUtils.writeSessionBoilerplate = function(sessId, sessVer, sessUser) {\n  let sessionId;\n  const version = sessVer !== undefined ? sessVer : 2;\n  if (sessId) {\n    sessionId = sessId;\n  } else {\n    sessionId = SDPUtils.generateSessionId();\n  }\n  const user = sessUser || 'thisisadapterortc';\n  // FIXME: sess-id should be an NTP timestamp.\n  return 'v=0\\r\\n' +\n      'o=' + user + ' ' + sessionId + ' ' + version +\n        ' IN IP4 127.0.0.1\\r\\n' +\n      's=-\\r\\n' +\n      't=0 0\\r\\n';\n};\n\n// Gets the direction from the mediaSection or the sessionpart.\nSDPUtils.getDirection = function(mediaSection, sessionpart) {\n  // Look for sendrecv, sendonly, recvonly, inactive, default to sendrecv.\n  const lines = SDPUtils.splitLines(mediaSection);\n  for (let i = 0; i < lines.length; i++) {\n    switch (lines[i]) {\n      case 'a=sendrecv':\n      case 'a=sendonly':\n      case 'a=recvonly':\n      case 'a=inactive':\n        return lines[i].substring(2);\n      default:\n        // FIXME: What should happen here?\n    }\n  }\n  if (sessionpart) {\n    return SDPUtils.getDirection(sessionpart);\n  }\n  return 'sendrecv';\n};\n\nSDPUtils.getKind = function(mediaSection) {\n  const lines = SDPUtils.splitLines(mediaSection);\n  const mline = lines[0].split(' ');\n  return mline[0].substring(2);\n};\n\nSDPUtils.isRejected = function(mediaSection) {\n  return mediaSection.split(' ', 2)[1] === '0';\n};\n\nSDPUtils.parseMLine = function(mediaSection) {\n  const lines = SDPUtils.splitLines(mediaSection);\n  const parts = lines[0].substring(2).split(' ');\n  return {\n    kind: parts[0],\n    port: parseInt(parts[1], 10),\n    protocol: parts[2],\n    fmt: parts.slice(3).join(' '),\n  };\n};\n\nSDPUtils.parseOLine = function(mediaSection) {\n  const line = SDPUtils.matchPrefix(mediaSection, 'o=')[0];\n  const parts = line.substring(2).split(' ');\n  return {\n    username: parts[0],\n    sessionId: parts[1],\n    sessionVersion: parseInt(parts[2], 10),\n    netType: parts[3],\n    addressType: parts[4],\n    address: parts[5],\n  };\n};\n\n// a very naive interpretation of a valid SDP.\nSDPUtils.isValidSDP = function(blob) {\n  if (typeof blob !== 'string' || blob.length === 0) {\n    return false;\n  }\n  const lines = SDPUtils.splitLines(blob);\n  for (let i = 0; i < lines.length; i++) {\n    if (lines[i].length < 2 || lines[i].charAt(1) !== '=') {\n      return false;\n    }\n    // TODO: check the modifier a bit more.\n  }\n  return true;\n};\n\n// Expose public methods.\nif (typeof module === 'object') {\n  module.exports = SDPUtils;\n}\n","(function (global, factory) {\n            typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :\n            typeof define === 'function' && define.amd ? define(['exports'], factory) :\n            (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.strophe = {}));\n})(this, (function (exports) { 'use strict';\n\n            var global$1 = typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {};\n\n            /*\n             * This module provides uniform\n             * Shims APIs and globals that are not present in all JS environments,\n             * the most common example for Strophe being browser APIs like WebSocket\n             * and DOM that don't exist under nodejs.\n             *\n             * Usually these will be supplied in nodejs by conditionally requiring a\n             * NPM module that provides a compatible implementation.\n             */\n\n            /* global global */\n\n            /**\n             * WHATWG WebSockets API\n             * https://www.w3.org/TR/websockets/\n             *\n             * Interface to use the web socket protocol\n             *\n             * Used implementations:\n             * - supported browsers: built-in in WebSocket global\n             *   https://developer.mozilla.org/en-US/docs/Web/API/WebSocket#Browser_compatibility\n             * - nodejs: use standard-compliant 'ws' module\n             *   https://www.npmjs.com/package/ws\n             */\n            function getWebSocketImplementation() {\n              let WebSocketImplementation = global$1.WebSocket;\n\n              if (typeof WebSocketImplementation === 'undefined') {\n                throw new Error('WebSocket global not found!');\n              }\n\n              return WebSocketImplementation;\n            }\n\n            const WebSocket = getWebSocketImplementation();\n            /**\n             * DOMParser\n             * https://w3c.github.io/DOM-Parsing/#the-domparser-interface\n             *\n             * Interface to parse XML strings into Document objects\n             *\n             * Used implementations:\n             * - supported browsers: built-in in DOMParser global\n             *   https://developer.mozilla.org/en-US/docs/Web/API/DOMParser#Browser_compatibility\n             * - nodejs: use '@xmldom/xmldom' module\n             *   https://www.npmjs.com/package/@xmldom/xmldom\n             */\n\n            function getDOMParserImplementation() {\n              let DOMParserImplementation = global$1.DOMParser;\n\n              if (typeof DOMParserImplementation === 'undefined') {\n                throw new Error('DOMParser global not found!');\n              }\n\n              return DOMParserImplementation;\n            }\n\n            const DOMParser = getDOMParserImplementation();\n            /**\n             *  Gets IE xml doc object. Used by getDummyXMLDocument shim.\n             *\n             *  Returns:\n             *    A Microsoft XML DOM Object\n             *  See Also:\n             *    http://msdn.microsoft.com/en-us/library/ms757837%28VS.85%29.aspx\n             */\n\n            function _getIEXmlDom() {\n              const docStrings = [\"Msxml2.DOMDocument.6.0\", \"Msxml2.DOMDocument.5.0\", \"Msxml2.DOMDocument.4.0\", \"MSXML2.DOMDocument.3.0\", \"MSXML2.DOMDocument\", \"MSXML.DOMDocument\", \"Microsoft.XMLDOM\"];\n\n              for (let d = 0; d < docStrings.length; d++) {\n                try {\n                  // eslint-disable-next-line no-undef\n                  const doc = new ActiveXObject(docStrings[d]);\n                  return doc;\n                } catch (e) {// Try next one\n                }\n              }\n            }\n            /**\n             * Creates a dummy XML DOM document to serve as an element and text node generator.\n             *\n             * Used implementations:\n             *  - IE < 10: avoid using createDocument() due to a memory leak, use ie-specific\n             *    workaround\n             *  - other supported browsers: use document's createDocument\n             *  - nodejs: use '@xmldom/xmldom'\n             */\n\n\n            function getDummyXMLDOMDocument() {\n              // nodejs\n              if (typeof document === 'undefined') {\n                try {\n                  const DOMImplementation = getDOMParserImplementation();\n                  return new DOMImplementation().createDocument('jabber:client', 'strophe', null);\n                } catch (err) {\n                  throw new Error('You must install the \"@xmldom/xmldom\" package to use Strophe in nodejs.');\n                }\n              } // IE < 10\n\n\n              if (document.implementation.createDocument === undefined || document.implementation.createDocument && document.documentMode && document.documentMode < 10) {\n                const doc = _getIEXmlDom();\n\n                doc.appendChild(doc.createElement('strophe'));\n                return doc;\n              } // All other supported browsers\n\n\n              return document.implementation.createDocument('jabber:client', 'strophe', null);\n            }\n\n            /*\n             * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message\n             * Digest Algorithm, as defined in RFC 1321.\n             * Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.\n             * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet\n             * Distributed under the BSD License\n             * See http://pajhome.org.uk/crypt/md5 for more info.\n             */\n\n            /*\n             * Everything that isn't used by Strophe has been stripped here!\n             */\n\n            /*\n             * Add integers, wrapping at 2^32. This uses 16-bit operations internally\n             * to work around bugs in some JS interpreters.\n             */\n            const safe_add$1 = function (x, y) {\n              const lsw = (x & 0xFFFF) + (y & 0xFFFF);\n              const msw = (x >> 16) + (y >> 16) + (lsw >> 16);\n              return msw << 16 | lsw & 0xFFFF;\n            };\n            /*\n             * Bitwise rotate a 32-bit number to the left.\n             */\n\n\n            const bit_rol = function (num, cnt) {\n              return num << cnt | num >>> 32 - cnt;\n            };\n            /*\n             * Convert a string to an array of little-endian words\n             */\n\n\n            const str2binl = function (str) {\n              if (typeof str !== \"string\") {\n                throw new Error(\"str2binl was passed a non-string\");\n              }\n\n              const bin = [];\n\n              for (let i = 0; i < str.length * 8; i += 8) {\n                bin[i >> 5] |= (str.charCodeAt(i / 8) & 255) << i % 32;\n              }\n\n              return bin;\n            };\n            /*\n             * Convert an array of little-endian words to a string\n             */\n\n\n            const binl2str = function (bin) {\n              let str = \"\";\n\n              for (let i = 0; i < bin.length * 32; i += 8) {\n                str += String.fromCharCode(bin[i >> 5] >>> i % 32 & 255);\n              }\n\n              return str;\n            };\n            /*\n             * Convert an array of little-endian words to a hex string.\n             */\n\n\n            const binl2hex = function (binarray) {\n              const hex_tab = \"0123456789abcdef\";\n              let str = \"\";\n\n              for (let i = 0; i < binarray.length * 4; i++) {\n                str += hex_tab.charAt(binarray[i >> 2] >> i % 4 * 8 + 4 & 0xF) + hex_tab.charAt(binarray[i >> 2] >> i % 4 * 8 & 0xF);\n              }\n\n              return str;\n            };\n            /*\n             * These functions implement the four basic operations the algorithm uses.\n             */\n\n\n            const md5_cmn = function (q, a, b, x, s, t) {\n              return safe_add$1(bit_rol(safe_add$1(safe_add$1(a, q), safe_add$1(x, t)), s), b);\n            };\n\n            const md5_ff = function (a, b, c, d, x, s, t) {\n              return md5_cmn(b & c | ~b & d, a, b, x, s, t);\n            };\n\n            const md5_gg = function (a, b, c, d, x, s, t) {\n              return md5_cmn(b & d | c & ~d, a, b, x, s, t);\n            };\n\n            const md5_hh = function (a, b, c, d, x, s, t) {\n              return md5_cmn(b ^ c ^ d, a, b, x, s, t);\n            };\n\n            const md5_ii = function (a, b, c, d, x, s, t) {\n              return md5_cmn(c ^ (b | ~d), a, b, x, s, t);\n            };\n            /*\n             * Calculate the MD5 of an array of little-endian words, and a bit length\n             */\n\n\n            const core_md5 = function (x, len) {\n              /* append padding */\n              x[len >> 5] |= 0x80 << len % 32;\n              x[(len + 64 >>> 9 << 4) + 14] = len;\n              let a = 1732584193;\n              let b = -271733879;\n              let c = -1732584194;\n              let d = 271733878;\n              let olda, oldb, oldc, oldd;\n\n              for (let i = 0; i < x.length; i += 16) {\n                olda = a;\n                oldb = b;\n                oldc = c;\n                oldd = d;\n                a = md5_ff(a, b, c, d, x[i + 0], 7, -680876936);\n                d = md5_ff(d, a, b, c, x[i + 1], 12, -389564586);\n                c = md5_ff(c, d, a, b, x[i + 2], 17, 606105819);\n                b = md5_ff(b, c, d, a, x[i + 3], 22, -1044525330);\n                a = md5_ff(a, b, c, d, x[i + 4], 7, -176418897);\n                d = md5_ff(d, a, b, c, x[i + 5], 12, 1200080426);\n                c = md5_ff(c, d, a, b, x[i + 6], 17, -1473231341);\n                b = md5_ff(b, c, d, a, x[i + 7], 22, -45705983);\n                a = md5_ff(a, b, c, d, x[i + 8], 7, 1770035416);\n                d = md5_ff(d, a, b, c, x[i + 9], 12, -1958414417);\n                c = md5_ff(c, d, a, b, x[i + 10], 17, -42063);\n                b = md5_ff(b, c, d, a, x[i + 11], 22, -1990404162);\n                a = md5_ff(a, b, c, d, x[i + 12], 7, 1804603682);\n                d = md5_ff(d, a, b, c, x[i + 13], 12, -40341101);\n                c = md5_ff(c, d, a, b, x[i + 14], 17, -1502002290);\n                b = md5_ff(b, c, d, a, x[i + 15], 22, 1236535329);\n                a = md5_gg(a, b, c, d, x[i + 1], 5, -165796510);\n                d = md5_gg(d, a, b, c, x[i + 6], 9, -1069501632);\n                c = md5_gg(c, d, a, b, x[i + 11], 14, 643717713);\n                b = md5_gg(b, c, d, a, x[i + 0], 20, -373897302);\n                a = md5_gg(a, b, c, d, x[i + 5], 5, -701558691);\n                d = md5_gg(d, a, b, c, x[i + 10], 9, 38016083);\n                c = md5_gg(c, d, a, b, x[i + 15], 14, -660478335);\n                b = md5_gg(b, c, d, a, x[i + 4], 20, -405537848);\n                a = md5_gg(a, b, c, d, x[i + 9], 5, 568446438);\n                d = md5_gg(d, a, b, c, x[i + 14], 9, -1019803690);\n                c = md5_gg(c, d, a, b, x[i + 3], 14, -187363961);\n                b = md5_gg(b, c, d, a, x[i + 8], 20, 1163531501);\n                a = md5_gg(a, b, c, d, x[i + 13], 5, -1444681467);\n                d = md5_gg(d, a, b, c, x[i + 2], 9, -51403784);\n                c = md5_gg(c, d, a, b, x[i + 7], 14, 1735328473);\n                b = md5_gg(b, c, d, a, x[i + 12], 20, -1926607734);\n                a = md5_hh(a, b, c, d, x[i + 5], 4, -378558);\n                d = md5_hh(d, a, b, c, x[i + 8], 11, -2022574463);\n                c = md5_hh(c, d, a, b, x[i + 11], 16, 1839030562);\n                b = md5_hh(b, c, d, a, x[i + 14], 23, -35309556);\n                a = md5_hh(a, b, c, d, x[i + 1], 4, -1530992060);\n                d = md5_hh(d, a, b, c, x[i + 4], 11, 1272893353);\n                c = md5_hh(c, d, a, b, x[i + 7], 16, -155497632);\n                b = md5_hh(b, c, d, a, x[i + 10], 23, -1094730640);\n                a = md5_hh(a, b, c, d, x[i + 13], 4, 681279174);\n                d = md5_hh(d, a, b, c, x[i + 0], 11, -358537222);\n                c = md5_hh(c, d, a, b, x[i + 3], 16, -722521979);\n                b = md5_hh(b, c, d, a, x[i + 6], 23, 76029189);\n                a = md5_hh(a, b, c, d, x[i + 9], 4, -640364487);\n                d = md5_hh(d, a, b, c, x[i + 12], 11, -421815835);\n                c = md5_hh(c, d, a, b, x[i + 15], 16, 530742520);\n                b = md5_hh(b, c, d, a, x[i + 2], 23, -995338651);\n                a = md5_ii(a, b, c, d, x[i + 0], 6, -198630844);\n                d = md5_ii(d, a, b, c, x[i + 7], 10, 1126891415);\n                c = md5_ii(c, d, a, b, x[i + 14], 15, -1416354905);\n                b = md5_ii(b, c, d, a, x[i + 5], 21, -57434055);\n                a = md5_ii(a, b, c, d, x[i + 12], 6, 1700485571);\n                d = md5_ii(d, a, b, c, x[i + 3], 10, -1894986606);\n                c = md5_ii(c, d, a, b, x[i + 10], 15, -1051523);\n                b = md5_ii(b, c, d, a, x[i + 1], 21, -2054922799);\n                a = md5_ii(a, b, c, d, x[i + 8], 6, 1873313359);\n                d = md5_ii(d, a, b, c, x[i + 15], 10, -30611744);\n                c = md5_ii(c, d, a, b, x[i + 6], 15, -1560198380);\n                b = md5_ii(b, c, d, a, x[i + 13], 21, 1309151649);\n                a = md5_ii(a, b, c, d, x[i + 4], 6, -145523070);\n                d = md5_ii(d, a, b, c, x[i + 11], 10, -1120210379);\n                c = md5_ii(c, d, a, b, x[i + 2], 15, 718787259);\n                b = md5_ii(b, c, d, a, x[i + 9], 21, -343485551);\n                a = safe_add$1(a, olda);\n                b = safe_add$1(b, oldb);\n                c = safe_add$1(c, oldc);\n                d = safe_add$1(d, oldd);\n              }\n\n              return [a, b, c, d];\n            };\n            /*\n             * These are the functions you'll usually want to call.\n             * They take string arguments and return either hex or base-64 encoded\n             * strings.\n             */\n\n\n            const MD5 = {\n              hexdigest: function (s) {\n                return binl2hex(core_md5(str2binl(s), s.length * 8));\n              },\n              hash: function (s) {\n                return binl2str(core_md5(str2binl(s), s.length * 8));\n              }\n            };\n\n            /** Class: Strophe.SASLMechanism\n             *\n             *  Encapsulates an SASL authentication mechanism.\n             *\n             *  User code may override the priority for each mechanism or disable it completely.\n             *  See <priority> for information about changing priority and <test> for informatian on\n             *  how to disable a mechanism.\n             *\n             *  By default, all mechanisms are enabled and the priorities are\n             *\n             *      SCRAM-SHA-1 - 60\n             *      PLAIN       - 50\n             *      OAUTHBEARER - 40\n             *      X-OAUTH2    - 30\n             *      ANONYMOUS   - 20\n             *      EXTERNAL    - 10\n             *\n             *  See: Strophe.Connection.addSupportedSASLMechanisms\n             */\n            class SASLMechanism {\n              /**\n               * PrivateConstructor: Strophe.SASLMechanism\n               * SASL auth mechanism abstraction.\n               *\n               *  Parameters:\n               *    (String) name - SASL Mechanism name.\n               *    (Boolean) isClientFirst - If client should send response first without challenge.\n               *    (Number) priority - Priority.\n               *\n               *  Returns:\n               *    A new Strophe.SASLMechanism object.\n               */\n              constructor(name, isClientFirst, priority) {\n                /** PrivateVariable: mechname\n                 *  Mechanism name.\n                 */\n                this.mechname = name;\n                /** PrivateVariable: isClientFirst\n                 *  If client sends response without initial server challenge.\n                 */\n\n                this.isClientFirst = isClientFirst;\n                /** Variable: priority\n                 *  Determines which <SASLMechanism> is chosen for authentication (Higher is better).\n                 *  Users may override this to prioritize mechanisms differently.\n                 *\n                 *  Example: (This will cause Strophe to choose the mechanism that the server sent first)\n                 *\n                 *  > Strophe.SASLPlain.priority = Strophe.SASLSHA1.priority;\n                 *\n                 *  See <SASL mechanisms> for a list of available mechanisms.\n                 *\n                 */\n\n                this.priority = priority;\n              }\n              /**\n               *  Function: test\n               *  Checks if mechanism able to run.\n               *  To disable a mechanism, make this return false;\n               *\n               *  To disable plain authentication run\n               *  > Strophe.SASLPlain.test = function() {\n               *  >   return false;\n               *  > }\n               *\n               *  See <SASL mechanisms> for a list of available mechanisms.\n               *\n               *  Parameters:\n               *    (Strophe.Connection) connection - Target Connection.\n               *\n               *  Returns:\n               *    (Boolean) If mechanism was able to run.\n               */\n\n\n              test() {\n                // eslint-disable-line class-methods-use-this\n                return true;\n              }\n              /** PrivateFunction: onStart\n               *  Called before starting mechanism on some connection.\n               *\n               *  Parameters:\n               *    (Strophe.Connection) connection - Target Connection.\n               */\n\n\n              onStart(connection) {\n                this._connection = connection;\n              }\n              /** PrivateFunction: onChallenge\n               *  Called by protocol implementation on incoming challenge.\n               *\n               *  By deafult, if the client is expected to send data first (isClientFirst === true),\n               *  this method is called with `challenge` as null on the first call,\n               *  unless `clientChallenge` is overridden in the relevant subclass.\n               *\n               *  Parameters:\n               *    (Strophe.Connection) connection - Target Connection.\n               *    (String) challenge - current challenge to handle.\n               *\n               *  Returns:\n               *    (String) Mechanism response.\n               */\n\n\n              onChallenge(connection, challenge) {\n                // eslint-disable-line\n                throw new Error(\"You should implement challenge handling!\");\n              }\n              /** PrivateFunction: clientChallenge\n               *  Called by the protocol implementation if the client is expected to send\n               *  data first in the authentication exchange (i.e. isClientFirst === true).\n               *\n               *  Parameters:\n               *    (Strophe.Connection) connection - Target Connection.\n               *\n               *  Returns:\n               *    (String) Mechanism response.\n               */\n\n\n              clientChallenge(connection) {\n                if (!this.isClientFirst) {\n                  throw new Error(\"clientChallenge should not be called if isClientFirst is false!\");\n                }\n\n                return this.onChallenge(connection);\n              }\n              /** PrivateFunction: onFailure\n               *  Protocol informs mechanism implementation about SASL failure.\n               */\n\n\n              onFailure() {\n                this._connection = null;\n              }\n              /** PrivateFunction: onSuccess\n               *  Protocol informs mechanism implementation about SASL success.\n               */\n\n\n              onSuccess() {\n                this._connection = null;\n              }\n\n            }\n\n            class SASLAnonymous extends SASLMechanism {\n              /** PrivateConstructor: SASLAnonymous\n               *  SASL ANONYMOUS authentication.\n               */\n              constructor() {\n                let mechname = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'ANONYMOUS';\n                let isClientFirst = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;\n                let priority = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 20;\n                super(mechname, isClientFirst, priority);\n              }\n\n              test(connection) {\n                // eslint-disable-line class-methods-use-this\n                return connection.authcid === null;\n              }\n\n            }\n\n            class SASLExternal extends SASLMechanism {\n              /** PrivateConstructor: SASLExternal\n               *  SASL EXTERNAL authentication.\n               *\n               *  The EXTERNAL mechanism allows a client to request the server to use\n               *  credentials established by means external to the mechanism to\n               *  authenticate the client. The external means may be, for instance,\n               *  TLS services.\n               */\n              constructor() {\n                let mechname = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'EXTERNAL';\n                let isClientFirst = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;\n                let priority = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 10;\n                super(mechname, isClientFirst, priority);\n              }\n\n              onChallenge(connection) {\n                // eslint-disable-line class-methods-use-this\n\n                /** According to XEP-178, an authzid SHOULD NOT be presented when the\n                 * authcid contained or implied in the client certificate is the JID (i.e.\n                 * authzid) with which the user wants to log in as.\n                 *\n                 * To NOT send the authzid, the user should therefore set the authcid equal\n                 * to the JID when instantiating a new Strophe.Connection object.\n                 */\n                return connection.authcid === connection.authzid ? '' : connection.authzid;\n              }\n\n            }\n\n            const utils = {\n              utf16to8: function (str) {\n                var i, c;\n                var out = \"\";\n                var len = str.length;\n\n                for (i = 0; i < len; i++) {\n                  c = str.charCodeAt(i);\n\n                  if (c >= 0x0000 && c <= 0x007F) {\n                    out += str.charAt(i);\n                  } else if (c > 0x07FF) {\n                    out += String.fromCharCode(0xE0 | c >> 12 & 0x0F);\n                    out += String.fromCharCode(0x80 | c >> 6 & 0x3F);\n                    out += String.fromCharCode(0x80 | c >> 0 & 0x3F);\n                  } else {\n                    out += String.fromCharCode(0xC0 | c >> 6 & 0x1F);\n                    out += String.fromCharCode(0x80 | c >> 0 & 0x3F);\n                  }\n                }\n\n                return out;\n              },\n              addCookies: function (cookies) {\n                /* Parameters:\n                 *  (Object) cookies - either a map of cookie names\n                 *    to string values or to maps of cookie values.\n                 *\n                 * For example:\n                 * { \"myCookie\": \"1234\" }\n                 *\n                 * or:\n                 * { \"myCookie\": {\n                 *      \"value\": \"1234\",\n                 *      \"domain\": \".example.org\",\n                 *      \"path\": \"/\",\n                 *      \"expires\": expirationDate\n                 *      }\n                 *  }\n                 *\n                 *  These values get passed to Strophe.Connection via\n                 *   options.cookies\n                 */\n                cookies = cookies || {};\n\n                for (const cookieName in cookies) {\n                  if (Object.prototype.hasOwnProperty.call(cookies, cookieName)) {\n                    let expires = '';\n                    let domain = '';\n                    let path = '';\n                    const cookieObj = cookies[cookieName];\n                    const isObj = typeof cookieObj === \"object\";\n                    const cookieValue = escape(unescape(isObj ? cookieObj.value : cookieObj));\n\n                    if (isObj) {\n                      expires = cookieObj.expires ? \";expires=\" + cookieObj.expires : '';\n                      domain = cookieObj.domain ? \";domain=\" + cookieObj.domain : '';\n                      path = cookieObj.path ? \";path=\" + cookieObj.path : '';\n                    }\n\n                    document.cookie = cookieName + '=' + cookieValue + expires + domain + path;\n                  }\n                }\n              }\n            };\n\n            class SASLOAuthBearer extends SASLMechanism {\n              /** PrivateConstructor: SASLOAuthBearer\n               *  SASL OAuth Bearer authentication.\n               */\n              constructor() {\n                let mechname = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'OAUTHBEARER';\n                let isClientFirst = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;\n                let priority = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 40;\n                super(mechname, isClientFirst, priority);\n              }\n\n              test(connection) {\n                // eslint-disable-line class-methods-use-this\n                return connection.pass !== null;\n              }\n\n              onChallenge(connection) {\n                // eslint-disable-line class-methods-use-this\n                let auth_str = 'n,';\n\n                if (connection.authcid !== null) {\n                  auth_str = auth_str + 'a=' + connection.authzid;\n                }\n\n                auth_str = auth_str + ',';\n                auth_str = auth_str + \"\\u0001\";\n                auth_str = auth_str + 'auth=Bearer ';\n                auth_str = auth_str + connection.pass;\n                auth_str = auth_str + \"\\u0001\";\n                auth_str = auth_str + \"\\u0001\";\n                return utils.utf16to8(auth_str);\n              }\n\n            }\n\n            class SASLPlain extends SASLMechanism {\n              /** PrivateConstructor: SASLPlain\n               *  SASL PLAIN authentication.\n               */\n              constructor() {\n                let mechname = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'PLAIN';\n                let isClientFirst = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;\n                let priority = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 50;\n                super(mechname, isClientFirst, priority);\n              }\n\n              test(connection) {\n                // eslint-disable-line class-methods-use-this\n                return connection.authcid !== null;\n              }\n\n              onChallenge(connection) {\n                // eslint-disable-line class-methods-use-this\n                const {\n                  authcid,\n                  authzid,\n                  domain,\n                  pass\n                } = connection;\n\n                if (!domain) {\n                  throw new Error(\"SASLPlain onChallenge: domain is not defined!\");\n                } // Only include authzid if it differs from authcid.\n                // See: https://tools.ietf.org/html/rfc6120#section-6.3.8\n\n\n                let auth_str = authzid !== `${authcid}@${domain}` ? authzid : '';\n                auth_str = auth_str + \"\\u0000\";\n                auth_str = auth_str + authcid;\n                auth_str = auth_str + \"\\u0000\";\n                auth_str = auth_str + pass;\n                return utils.utf16to8(auth_str);\n              }\n\n            }\n\n            /*\n             * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined\n             * in FIPS PUB 180-1\n             * Version 2.1a Copyright Paul Johnston 2000 - 2002.\n             * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet\n             * Distributed under the BSD License\n             * See http://pajhome.org.uk/crypt/md5 for details.\n             */\n\n            /* global define */\n\n            /* Some functions and variables have been stripped for use with Strophe */\n\n            /*\n             * Calculate the SHA-1 of an array of big-endian words, and a bit length\n             */\n            function core_sha1(x, len) {\n              /* append padding */\n              x[len >> 5] |= 0x80 << 24 - len % 32;\n              x[(len + 64 >> 9 << 4) + 15] = len;\n              var w = new Array(80);\n              var a = 1732584193;\n              var b = -271733879;\n              var c = -1732584194;\n              var d = 271733878;\n              var e = -1009589776;\n              var i, j, t, olda, oldb, oldc, oldd, olde;\n\n              for (i = 0; i < x.length; i += 16) {\n                olda = a;\n                oldb = b;\n                oldc = c;\n                oldd = d;\n                olde = e;\n\n                for (j = 0; j < 80; j++) {\n                  if (j < 16) {\n                    w[j] = x[i + j];\n                  } else {\n                    w[j] = rol(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1);\n                  }\n\n                  t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)), safe_add(safe_add(e, w[j]), sha1_kt(j)));\n                  e = d;\n                  d = c;\n                  c = rol(b, 30);\n                  b = a;\n                  a = t;\n                }\n\n                a = safe_add(a, olda);\n                b = safe_add(b, oldb);\n                c = safe_add(c, oldc);\n                d = safe_add(d, oldd);\n                e = safe_add(e, olde);\n              }\n\n              return [a, b, c, d, e];\n            }\n            /*\n             * Perform the appropriate triplet combination function for the current\n             * iteration\n             */\n\n\n            function sha1_ft(t, b, c, d) {\n              if (t < 20) {\n                return b & c | ~b & d;\n              }\n\n              if (t < 40) {\n                return b ^ c ^ d;\n              }\n\n              if (t < 60) {\n                return b & c | b & d | c & d;\n              }\n\n              return b ^ c ^ d;\n            }\n            /*\n             * Determine the appropriate additive constant for the current iteration\n             */\n\n\n            function sha1_kt(t) {\n              return t < 20 ? 1518500249 : t < 40 ? 1859775393 : t < 60 ? -1894007588 : -899497514;\n            }\n            /*\n             * Calculate the HMAC-SHA1 of a key and some data\n             */\n\n\n            function core_hmac_sha1(key, data) {\n              var bkey = str2binb(key);\n\n              if (bkey.length > 16) {\n                bkey = core_sha1(bkey, key.length * 8);\n              }\n\n              var ipad = new Array(16),\n                  opad = new Array(16);\n\n              for (var i = 0; i < 16; i++) {\n                ipad[i] = bkey[i] ^ 0x36363636;\n                opad[i] = bkey[i] ^ 0x5C5C5C5C;\n              }\n\n              var hash = core_sha1(ipad.concat(str2binb(data)), 512 + data.length * 8);\n              return core_sha1(opad.concat(hash), 512 + 160);\n            }\n            /*\n             * Add integers, wrapping at 2^32. This uses 16-bit operations internally\n             * to work around bugs in some JS interpreters.\n             */\n\n\n            function safe_add(x, y) {\n              var lsw = (x & 0xFFFF) + (y & 0xFFFF);\n              var msw = (x >> 16) + (y >> 16) + (lsw >> 16);\n              return msw << 16 | lsw & 0xFFFF;\n            }\n            /*\n             * Bitwise rotate a 32-bit number to the left.\n             */\n\n\n            function rol(num, cnt) {\n              return num << cnt | num >>> 32 - cnt;\n            }\n            /*\n             * Convert an 8-bit or 16-bit string to an array of big-endian words\n             * In 8-bit function, characters >255 have their hi-byte silently ignored.\n             */\n\n\n            function str2binb(str) {\n              var bin = [];\n              var mask = 255;\n\n              for (var i = 0; i < str.length * 8; i += 8) {\n                bin[i >> 5] |= (str.charCodeAt(i / 8) & mask) << 24 - i % 32;\n              }\n\n              return bin;\n            }\n            /*\n             * Convert an array of big-endian words to a base-64 string\n             */\n\n\n            function binb2b64(binarray) {\n              var tab = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n              var str = \"\";\n              var triplet, j;\n\n              for (var i = 0; i < binarray.length * 4; i += 3) {\n                triplet = (binarray[i >> 2] >> 8 * (3 - i % 4) & 0xFF) << 16 | (binarray[i + 1 >> 2] >> 8 * (3 - (i + 1) % 4) & 0xFF) << 8 | binarray[i + 2 >> 2] >> 8 * (3 - (i + 2) % 4) & 0xFF;\n\n                for (j = 0; j < 4; j++) {\n                  if (i * 8 + j * 6 > binarray.length * 32) {\n                    str += \"=\";\n                  } else {\n                    str += tab.charAt(triplet >> 6 * (3 - j) & 0x3F);\n                  }\n                }\n              }\n\n              return str;\n            }\n            /*\n             * Convert an array of big-endian words to a string\n             */\n\n\n            function binb2str(bin) {\n              var str = \"\";\n              var mask = 255;\n\n              for (var i = 0; i < bin.length * 32; i += 8) {\n                str += String.fromCharCode(bin[i >> 5] >>> 24 - i % 32 & mask);\n              }\n\n              return str;\n            }\n            /*\n             * These are the functions you'll usually want to call\n             * They take string arguments and return either hex or base-64 encoded strings\n             */\n\n\n            const SHA1 = {\n              b64_hmac_sha1: function (key, data) {\n                return binb2b64(core_hmac_sha1(key, data));\n              },\n              b64_sha1: function (s) {\n                return binb2b64(core_sha1(str2binb(s), s.length * 8));\n              },\n              binb2str: binb2str,\n              core_hmac_sha1: core_hmac_sha1,\n              str_hmac_sha1: function (key, data) {\n                return binb2str(core_hmac_sha1(key, data));\n              },\n              str_sha1: function (s) {\n                return binb2str(core_sha1(str2binb(s), s.length * 8));\n              }\n            };\n\n            class SASLSHA1 extends SASLMechanism {\n              /** PrivateConstructor: SASLSHA1\n               *  SASL SCRAM SHA 1 authentication.\n               */\n              constructor() {\n                let mechname = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'SCRAM-SHA-1';\n                let isClientFirst = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;\n                let priority = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 60;\n                super(mechname, isClientFirst, priority);\n              }\n\n              test(connection) {\n                // eslint-disable-line class-methods-use-this\n                return connection.authcid !== null;\n              }\n\n              onChallenge(connection, challenge) {\n                // eslint-disable-line class-methods-use-this\n                let nonce, salt, iter, Hi, U, U_old, i, k;\n                let responseText = \"c=biws,\";\n                let authMessage = `${connection._sasl_data[\"client-first-message-bare\"]},${challenge},`;\n                const cnonce = connection._sasl_data.cnonce;\n                const attribMatch = /([a-z]+)=([^,]+)(,|$)/;\n\n                while (challenge.match(attribMatch)) {\n                  const matches = challenge.match(attribMatch);\n                  challenge = challenge.replace(matches[0], \"\");\n\n                  switch (matches[1]) {\n                    case \"r\":\n                      nonce = matches[2];\n                      break;\n\n                    case \"s\":\n                      salt = matches[2];\n                      break;\n\n                    case \"i\":\n                      iter = matches[2];\n                      break;\n                  }\n                }\n\n                if (nonce.slice(0, cnonce.length) !== cnonce) {\n                  connection._sasl_data = {};\n                  return connection._sasl_failure_cb();\n                }\n\n                responseText += \"r=\" + nonce;\n                authMessage += responseText;\n                salt = atob(salt);\n                salt += \"\\x00\\x00\\x00\\x01\";\n                const pass = utils.utf16to8(connection.pass);\n                Hi = U_old = SHA1.core_hmac_sha1(pass, salt);\n\n                for (i = 1; i < iter; i++) {\n                  U = SHA1.core_hmac_sha1(pass, SHA1.binb2str(U_old));\n\n                  for (k = 0; k < 5; k++) {\n                    Hi[k] ^= U[k];\n                  }\n\n                  U_old = U;\n                }\n\n                Hi = SHA1.binb2str(Hi);\n                const clientKey = SHA1.core_hmac_sha1(Hi, \"Client Key\");\n                const serverKey = SHA1.str_hmac_sha1(Hi, \"Server Key\");\n                const clientSignature = SHA1.core_hmac_sha1(SHA1.str_sha1(SHA1.binb2str(clientKey)), authMessage);\n                connection._sasl_data[\"server-signature\"] = SHA1.b64_hmac_sha1(serverKey, authMessage);\n\n                for (k = 0; k < 5; k++) {\n                  clientKey[k] ^= clientSignature[k];\n                }\n\n                responseText += \",p=\" + btoa(SHA1.binb2str(clientKey));\n                return responseText;\n              }\n\n              clientChallenge(connection, test_cnonce) {\n                // eslint-disable-line class-methods-use-this\n                const cnonce = test_cnonce || MD5.hexdigest(\"\" + Math.random() * 1234567890);\n                let auth_str = \"n=\" + utils.utf16to8(connection.authcid);\n                auth_str += \",r=\";\n                auth_str += cnonce;\n                connection._sasl_data.cnonce = cnonce;\n                connection._sasl_data[\"client-first-message-bare\"] = auth_str;\n                auth_str = \"n,,\" + auth_str;\n                return auth_str;\n              }\n\n            }\n\n            class SASLXOAuth2 extends SASLMechanism {\n              /** PrivateConstructor: SASLXOAuth2\n               *  SASL X-OAuth2 authentication.\n               */\n              constructor() {\n                let mechname = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'X-OAUTH2';\n                let isClientFirst = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;\n                let priority = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 30;\n                super(mechname, isClientFirst, priority);\n              }\n\n              test(connection) {\n                // eslint-disable-line class-methods-use-this\n                return connection.pass !== null;\n              }\n\n              onChallenge(connection) {\n                // eslint-disable-line class-methods-use-this\n                let auth_str = '\\u0000';\n\n                if (connection.authcid !== null) {\n                  auth_str = auth_str + connection.authzid;\n                }\n\n                auth_str = auth_str + \"\\u0000\";\n                auth_str = auth_str + connection.pass;\n                return utils.utf16to8(auth_str);\n              }\n\n            }\n\n            /*\n                This program is distributed under the terms of the MIT license.\n                Please see the LICENSE file for details.\n\n                Copyright 2006-2018, OGG, LLC\n            */\n            /** Function: $build\n             *  Create a Strophe.Builder.\n             *  This is an alias for 'new Strophe.Builder(name, attrs)'.\n             *\n             *  Parameters:\n             *    (String) name - The root element name.\n             *    (Object) attrs - The attributes for the root element in object notation.\n             *\n             *  Returns:\n             *    A new Strophe.Builder object.\n             */\n\n            function $build(name, attrs) {\n              return new Strophe.Builder(name, attrs);\n            }\n            /** Function: $msg\n             *  Create a Strophe.Builder with a <message/> element as the root.\n             *\n             *  Parameters:\n             *    (Object) attrs - The <message/> element attributes in object notation.\n             *\n             *  Returns:\n             *    A new Strophe.Builder object.\n             */\n\n            function $msg(attrs) {\n              return new Strophe.Builder(\"message\", attrs);\n            }\n            /** Function: $iq\n             *  Create a Strophe.Builder with an <iq/> element as the root.\n             *\n             *  Parameters:\n             *    (Object) attrs - The <iq/> element attributes in object notation.\n             *\n             *  Returns:\n             *    A new Strophe.Builder object.\n             */\n\n            function $iq(attrs) {\n              return new Strophe.Builder(\"iq\", attrs);\n            }\n            /** Function: $pres\n             *  Create a Strophe.Builder with a <presence/> element as the root.\n             *\n             *  Parameters:\n             *    (Object) attrs - The <presence/> element attributes in object notation.\n             *\n             *  Returns:\n             *    A new Strophe.Builder object.\n             */\n\n            function $pres(attrs) {\n              return new Strophe.Builder(\"presence\", attrs);\n            }\n            /** Class: Strophe\n             *  An object container for all Strophe library functions.\n             *\n             *  This class is just a container for all the objects and constants\n             *  used in the library.  It is not meant to be instantiated, but to\n             *  provide a namespace for library objects, constants, and functions.\n             */\n\n            const Strophe = {\n              /** Constant: VERSION */\n              VERSION: \"1.5.0\",\n\n              /** Constants: XMPP Namespace Constants\n               *  Common namespace constants from the XMPP RFCs and XEPs.\n               *\n               *  NS.HTTPBIND - HTTP BIND namespace from XEP 124.\n               *  NS.BOSH - BOSH namespace from XEP 206.\n               *  NS.CLIENT - Main XMPP client namespace.\n               *  NS.AUTH - Legacy authentication namespace.\n               *  NS.ROSTER - Roster operations namespace.\n               *  NS.PROFILE - Profile namespace.\n               *  NS.DISCO_INFO - Service discovery info namespace from XEP 30.\n               *  NS.DISCO_ITEMS - Service discovery items namespace from XEP 30.\n               *  NS.MUC - Multi-User Chat namespace from XEP 45.\n               *  NS.SASL - XMPP SASL namespace from RFC 3920.\n               *  NS.STREAM - XMPP Streams namespace from RFC 3920.\n               *  NS.BIND - XMPP Binding namespace from RFC 3920 and RFC 6120.\n               *  NS.SESSION - XMPP Session namespace from RFC 3920.\n               *  NS.XHTML_IM - XHTML-IM namespace from XEP 71.\n               *  NS.XHTML - XHTML body namespace from XEP 71.\n               */\n              NS: {\n                HTTPBIND: \"http://jabber.org/protocol/httpbind\",\n                BOSH: \"urn:xmpp:xbosh\",\n                CLIENT: \"jabber:client\",\n                AUTH: \"jabber:iq:auth\",\n                ROSTER: \"jabber:iq:roster\",\n                PROFILE: \"jabber:iq:profile\",\n                DISCO_INFO: \"http://jabber.org/protocol/disco#info\",\n                DISCO_ITEMS: \"http://jabber.org/protocol/disco#items\",\n                MUC: \"http://jabber.org/protocol/muc\",\n                SASL: \"urn:ietf:params:xml:ns:xmpp-sasl\",\n                STREAM: \"http://etherx.jabber.org/streams\",\n                FRAMING: \"urn:ietf:params:xml:ns:xmpp-framing\",\n                BIND: \"urn:ietf:params:xml:ns:xmpp-bind\",\n                SESSION: \"urn:ietf:params:xml:ns:xmpp-session\",\n                VERSION: \"jabber:iq:version\",\n                STANZAS: \"urn:ietf:params:xml:ns:xmpp-stanzas\",\n                XHTML_IM: \"http://jabber.org/protocol/xhtml-im\",\n                XHTML: \"http://www.w3.org/1999/xhtml\"\n              },\n\n              /** Constants: XHTML_IM Namespace\n               *  contains allowed tags, tag attributes, and css properties.\n               *  Used in the createHtml function to filter incoming html into the allowed XHTML-IM subset.\n               *  See http://xmpp.org/extensions/xep-0071.html#profile-summary for the list of recommended\n               *  allowed tags and their attributes.\n               */\n              XHTML: {\n                tags: ['a', 'blockquote', 'br', 'cite', 'em', 'img', 'li', 'ol', 'p', 'span', 'strong', 'ul', 'body'],\n                attributes: {\n                  'a': ['href'],\n                  'blockquote': ['style'],\n                  'br': [],\n                  'cite': ['style'],\n                  'em': [],\n                  'img': ['src', 'alt', 'style', 'height', 'width'],\n                  'li': ['style'],\n                  'ol': ['style'],\n                  'p': ['style'],\n                  'span': ['style'],\n                  'strong': [],\n                  'ul': ['style'],\n                  'body': []\n                },\n                css: ['background-color', 'color', 'font-family', 'font-size', 'font-style', 'font-weight', 'margin-left', 'margin-right', 'text-align', 'text-decoration'],\n\n                /** Function: XHTML.validTag\n                 *\n                 * Utility method to determine whether a tag is allowed\n                 * in the XHTML_IM namespace.\n                 *\n                 * XHTML tag names are case sensitive and must be lower case.\n                 */\n                validTag(tag) {\n                  for (let i = 0; i < Strophe.XHTML.tags.length; i++) {\n                    if (tag === Strophe.XHTML.tags[i]) {\n                      return true;\n                    }\n                  }\n\n                  return false;\n                },\n\n                /** Function: XHTML.validAttribute\n                 *\n                 * Utility method to determine whether an attribute is allowed\n                 * as recommended per XEP-0071\n                 *\n                 * XHTML attribute names are case sensitive and must be lower case.\n                 */\n                validAttribute(tag, attribute) {\n                  if (typeof Strophe.XHTML.attributes[tag] !== 'undefined' && Strophe.XHTML.attributes[tag].length > 0) {\n                    for (let i = 0; i < Strophe.XHTML.attributes[tag].length; i++) {\n                      if (attribute === Strophe.XHTML.attributes[tag][i]) {\n                        return true;\n                      }\n                    }\n                  }\n\n                  return false;\n                },\n\n                validCSS(style) {\n                  for (let i = 0; i < Strophe.XHTML.css.length; i++) {\n                    if (style === Strophe.XHTML.css[i]) {\n                      return true;\n                    }\n                  }\n\n                  return false;\n                }\n\n              },\n\n              /** Constants: Connection Status Constants\n               *  Connection status constants for use by the connection handler\n               *  callback.\n               *\n               *  Status.ERROR - An error has occurred\n               *  Status.CONNECTING - The connection is currently being made\n               *  Status.CONNFAIL - The connection attempt failed\n               *  Status.AUTHENTICATING - The connection is authenticating\n               *  Status.AUTHFAIL - The authentication attempt failed\n               *  Status.CONNECTED - The connection has succeeded\n               *  Status.DISCONNECTED - The connection has been terminated\n               *  Status.DISCONNECTING - The connection is currently being terminated\n               *  Status.ATTACHED - The connection has been attached\n               *  Status.REDIRECT - The connection has been redirected\n               *  Status.CONNTIMEOUT - The connection has timed out\n               */\n              Status: {\n                ERROR: 0,\n                CONNECTING: 1,\n                CONNFAIL: 2,\n                AUTHENTICATING: 3,\n                AUTHFAIL: 4,\n                CONNECTED: 5,\n                DISCONNECTED: 6,\n                DISCONNECTING: 7,\n                ATTACHED: 8,\n                REDIRECT: 9,\n                CONNTIMEOUT: 10,\n                BINDREQUIRED: 11,\n                ATTACHFAIL: 12\n              },\n              ErrorCondition: {\n                BAD_FORMAT: \"bad-format\",\n                CONFLICT: \"conflict\",\n                MISSING_JID_NODE: \"x-strophe-bad-non-anon-jid\",\n                NO_AUTH_MECH: \"no-auth-mech\",\n                UNKNOWN_REASON: \"unknown\"\n              },\n\n              /** Constants: Log Level Constants\n               *  Logging level indicators.\n               *\n               *  LogLevel.DEBUG - Debug output\n               *  LogLevel.INFO - Informational output\n               *  LogLevel.WARN - Warnings\n               *  LogLevel.ERROR - Errors\n               *  LogLevel.FATAL - Fatal errors\n               */\n              LogLevel: {\n                DEBUG: 0,\n                INFO: 1,\n                WARN: 2,\n                ERROR: 3,\n                FATAL: 4\n              },\n\n              /** PrivateConstants: DOM Element Type Constants\n               *  DOM element types.\n               *\n               *  ElementType.NORMAL - Normal element.\n               *  ElementType.TEXT - Text data element.\n               *  ElementType.FRAGMENT - XHTML fragment element.\n               */\n              ElementType: {\n                NORMAL: 1,\n                TEXT: 3,\n                CDATA: 4,\n                FRAGMENT: 11\n              },\n\n              /** PrivateConstants: Timeout Values\n               *  Timeout values for error states.  These values are in seconds.\n               *  These should not be changed unless you know exactly what you are\n               *  doing.\n               *\n               *  TIMEOUT - Timeout multiplier. A waiting request will be considered\n               *      failed after Math.floor(TIMEOUT * wait) seconds have elapsed.\n               *      This defaults to 1.1, and with default wait, 66 seconds.\n               *  SECONDARY_TIMEOUT - Secondary timeout multiplier. In cases where\n               *      Strophe can detect early failure, it will consider the request\n               *      failed if it doesn't return after\n               *      Math.floor(SECONDARY_TIMEOUT * wait) seconds have elapsed.\n               *      This defaults to 0.1, and with default wait, 6 seconds.\n               */\n              TIMEOUT: 1.1,\n              SECONDARY_TIMEOUT: 0.1,\n\n              /** Function: addNamespace\n               *  This function is used to extend the current namespaces in\n               *  Strophe.NS.  It takes a key and a value with the key being the\n               *  name of the new namespace, with its actual value.\n               *  For example:\n               *  Strophe.addNamespace('PUBSUB', \"http://jabber.org/protocol/pubsub\");\n               *\n               *  Parameters:\n               *    (String) name - The name under which the namespace will be\n               *      referenced under Strophe.NS\n               *    (String) value - The actual namespace.\n               */\n              addNamespace(name, value) {\n                Strophe.NS[name] = value;\n              },\n\n              /** Function: forEachChild\n               *  Map a function over some or all child elements of a given element.\n               *\n               *  This is a small convenience function for mapping a function over\n               *  some or all of the children of an element.  If elemName is null, all\n               *  children will be passed to the function, otherwise only children\n               *  whose tag names match elemName will be passed.\n               *\n               *  Parameters:\n               *    (XMLElement) elem - The element to operate on.\n               *    (String) elemName - The child element tag name filter.\n               *    (Function) func - The function to apply to each child.  This\n               *      function should take a single argument, a DOM element.\n               */\n              forEachChild(elem, elemName, func) {\n                for (let i = 0; i < elem.childNodes.length; i++) {\n                  const childNode = elem.childNodes[i];\n\n                  if (childNode.nodeType === Strophe.ElementType.NORMAL && (!elemName || this.isTagEqual(childNode, elemName))) {\n                    func(childNode);\n                  }\n                }\n              },\n\n              /** Function: isTagEqual\n               *  Compare an element's tag name with a string.\n               *\n               *  This function is case sensitive.\n               *\n               *  Parameters:\n               *    (XMLElement) el - A DOM element.\n               *    (String) name - The element name.\n               *\n               *  Returns:\n               *    true if the element's tag name matches _el_, and false\n               *    otherwise.\n               */\n              isTagEqual(el, name) {\n                return el.tagName === name;\n              },\n\n              /** PrivateVariable: _xmlGenerator\n               *  _Private_ variable that caches a DOM document to\n               *  generate elements.\n               */\n              _xmlGenerator: null,\n\n              /** Function: xmlGenerator\n               *  Get the DOM document to generate elements.\n               *\n               *  Returns:\n               *    The currently used DOM document.\n               */\n              xmlGenerator() {\n                if (!Strophe._xmlGenerator) {\n                  Strophe._xmlGenerator = getDummyXMLDOMDocument();\n                }\n\n                return Strophe._xmlGenerator;\n              },\n\n              /** Function: xmlElement\n               *  Create an XML DOM element.\n               *\n               *  This function creates an XML DOM element correctly across all\n               *  implementations. Note that these are not HTML DOM elements, which\n               *  aren't appropriate for XMPP stanzas.\n               *\n               *  Parameters:\n               *    (String) name - The name for the element.\n               *    (Array|Object) attrs - An optional array or object containing\n               *      key/value pairs to use as element attributes. The object should\n               *      be in the format {'key': 'value'} or {key: 'value'}. The array\n               *      should have the format [['key1', 'value1'], ['key2', 'value2']].\n               *    (String) text - The text child data for the element.\n               *\n               *  Returns:\n               *    A new XML DOM element.\n               */\n              xmlElement(name) {\n                if (!name) {\n                  return null;\n                }\n\n                const node = Strophe.xmlGenerator().createElement(name); // FIXME: this should throw errors if args are the wrong type or\n                // there are more than two optional args\n\n                for (let a = 1; a < arguments.length; a++) {\n                  const arg = arguments[a];\n\n                  if (!arg) {\n                    continue;\n                  }\n\n                  if (typeof arg === \"string\" || typeof arg === \"number\") {\n                    node.appendChild(Strophe.xmlTextNode(arg));\n                  } else if (typeof arg === \"object\" && typeof arg.sort === \"function\") {\n                    for (let i = 0; i < arg.length; i++) {\n                      const attr = arg[i];\n\n                      if (typeof attr === \"object\" && typeof attr.sort === \"function\" && attr[1] !== undefined && attr[1] !== null) {\n                        node.setAttribute(attr[0], attr[1]);\n                      }\n                    }\n                  } else if (typeof arg === \"object\") {\n                    for (const k in arg) {\n                      if (Object.prototype.hasOwnProperty.call(arg, k) && arg[k] !== undefined && arg[k] !== null) {\n                        node.setAttribute(k, arg[k]);\n                      }\n                    }\n                  }\n                }\n\n                return node;\n              },\n\n              /*  Function: xmlescape\n               *  Excapes invalid xml characters.\n               *\n               *  Parameters:\n               *     (String) text - text to escape.\n               *\n               *  Returns:\n               *      Escaped text.\n               */\n              xmlescape(text) {\n                text = text.replace(/\\&/g, \"&amp;\");\n                text = text.replace(/</g, \"&lt;\");\n                text = text.replace(/>/g, \"&gt;\");\n                text = text.replace(/'/g, \"&apos;\");\n                text = text.replace(/\"/g, \"&quot;\");\n                return text;\n              },\n\n              /*  Function: xmlunescape\n              *  Unexcapes invalid xml characters.\n              *\n              *  Parameters:\n              *     (String) text - text to unescape.\n              *\n              *  Returns:\n              *      Unescaped text.\n              */\n              xmlunescape(text) {\n                text = text.replace(/\\&amp;/g, \"&\");\n                text = text.replace(/&lt;/g, \"<\");\n                text = text.replace(/&gt;/g, \">\");\n                text = text.replace(/&apos;/g, \"'\");\n                text = text.replace(/&quot;/g, \"\\\"\");\n                return text;\n              },\n\n              /** Function: xmlTextNode\n               *  Creates an XML DOM text node.\n               *\n               *  Provides a cross implementation version of document.createTextNode.\n               *\n               *  Parameters:\n               *    (String) text - The content of the text node.\n               *\n               *  Returns:\n               *    A new XML DOM text node.\n               */\n              xmlTextNode(text) {\n                return Strophe.xmlGenerator().createTextNode(text);\n              },\n\n              /** Function: xmlHtmlNode\n               *  Creates an XML DOM html node.\n               *\n               *  Parameters:\n               *    (String) html - The content of the html node.\n               *\n               *  Returns:\n               *    A new XML DOM text node.\n               */\n              xmlHtmlNode(html) {\n                let node; //ensure text is escaped\n\n                if (DOMParser) {\n                  const parser = new DOMParser();\n                  node = parser.parseFromString(html, \"text/xml\");\n                } else {\n                  node = new ActiveXObject(\"Microsoft.XMLDOM\");\n                  node.async = \"false\";\n                  node.loadXML(html);\n                }\n\n                return node;\n              },\n\n              /** Function: getText\n               *  Get the concatenation of all text children of an element.\n               *\n               *  Parameters:\n               *    (XMLElement) elem - A DOM element.\n               *\n               *  Returns:\n               *    A String with the concatenated text of all text element children.\n               */\n              getText(elem) {\n                if (!elem) {\n                  return null;\n                }\n\n                let str = \"\";\n\n                if (elem.childNodes.length === 0 && elem.nodeType === Strophe.ElementType.TEXT) {\n                  str += elem.nodeValue;\n                }\n\n                for (let i = 0; i < elem.childNodes.length; i++) {\n                  if (elem.childNodes[i].nodeType === Strophe.ElementType.TEXT) {\n                    str += elem.childNodes[i].nodeValue;\n                  }\n                }\n\n                return Strophe.xmlescape(str);\n              },\n\n              /** Function: copyElement\n               *  Copy an XML DOM element.\n               *\n               *  This function copies a DOM element and all its descendants and returns\n               *  the new copy.\n               *\n               *  Parameters:\n               *    (XMLElement) elem - A DOM element.\n               *\n               *  Returns:\n               *    A new, copied DOM element tree.\n               */\n              copyElement(elem) {\n                let el;\n\n                if (elem.nodeType === Strophe.ElementType.NORMAL) {\n                  el = Strophe.xmlElement(elem.tagName);\n\n                  for (let i = 0; i < elem.attributes.length; i++) {\n                    el.setAttribute(elem.attributes[i].nodeName, elem.attributes[i].value);\n                  }\n\n                  for (let i = 0; i < elem.childNodes.length; i++) {\n                    el.appendChild(Strophe.copyElement(elem.childNodes[i]));\n                  }\n                } else if (elem.nodeType === Strophe.ElementType.TEXT) {\n                  el = Strophe.xmlGenerator().createTextNode(elem.nodeValue);\n                }\n\n                return el;\n              },\n\n              /** Function: createHtml\n               *  Copy an HTML DOM element into an XML DOM.\n               *\n               *  This function copies a DOM element and all its descendants and returns\n               *  the new copy.\n               *\n               *  Parameters:\n               *    (HTMLElement) elem - A DOM element.\n               *\n               *  Returns:\n               *    A new, copied DOM element tree.\n               */\n              createHtml(elem) {\n                let el;\n\n                if (elem.nodeType === Strophe.ElementType.NORMAL) {\n                  const tag = elem.nodeName.toLowerCase(); // XHTML tags must be lower case.\n\n                  if (Strophe.XHTML.validTag(tag)) {\n                    try {\n                      el = Strophe.xmlElement(tag);\n\n                      for (let i = 0; i < Strophe.XHTML.attributes[tag].length; i++) {\n                        const attribute = Strophe.XHTML.attributes[tag][i];\n                        let value = elem.getAttribute(attribute);\n\n                        if (typeof value === 'undefined' || value === null || value === '' || value === false || value === 0) {\n                          continue;\n                        }\n\n                        if (attribute === 'style' && typeof value === 'object' && typeof value.cssText !== 'undefined') {\n                          value = value.cssText; // we're dealing with IE, need to get CSS out\n                        } // filter out invalid css styles\n\n\n                        if (attribute === 'style') {\n                          const css = [];\n                          const cssAttrs = value.split(';');\n\n                          for (let j = 0; j < cssAttrs.length; j++) {\n                            const attr = cssAttrs[j].split(':');\n                            const cssName = attr[0].replace(/^\\s*/, \"\").replace(/\\s*$/, \"\").toLowerCase();\n\n                            if (Strophe.XHTML.validCSS(cssName)) {\n                              const cssValue = attr[1].replace(/^\\s*/, \"\").replace(/\\s*$/, \"\");\n                              css.push(cssName + ': ' + cssValue);\n                            }\n                          }\n\n                          if (css.length > 0) {\n                            value = css.join('; ');\n                            el.setAttribute(attribute, value);\n                          }\n                        } else {\n                          el.setAttribute(attribute, value);\n                        }\n                      }\n\n                      for (let i = 0; i < elem.childNodes.length; i++) {\n                        el.appendChild(Strophe.createHtml(elem.childNodes[i]));\n                      }\n                    } catch (e) {\n                      // invalid elements\n                      el = Strophe.xmlTextNode('');\n                    }\n                  } else {\n                    el = Strophe.xmlGenerator().createDocumentFragment();\n\n                    for (let i = 0; i < elem.childNodes.length; i++) {\n                      el.appendChild(Strophe.createHtml(elem.childNodes[i]));\n                    }\n                  }\n                } else if (elem.nodeType === Strophe.ElementType.FRAGMENT) {\n                  el = Strophe.xmlGenerator().createDocumentFragment();\n\n                  for (let i = 0; i < elem.childNodes.length; i++) {\n                    el.appendChild(Strophe.createHtml(elem.childNodes[i]));\n                  }\n                } else if (elem.nodeType === Strophe.ElementType.TEXT) {\n                  el = Strophe.xmlTextNode(elem.nodeValue);\n                }\n\n                return el;\n              },\n\n              /** Function: escapeNode\n               *  Escape the node part (also called local part) of a JID.\n               *\n               *  Parameters:\n               *    (String) node - A node (or local part).\n               *\n               *  Returns:\n               *    An escaped node (or local part).\n               */\n              escapeNode(node) {\n                if (typeof node !== \"string\") {\n                  return node;\n                }\n\n                return node.replace(/^\\s+|\\s+$/g, '').replace(/\\\\/g, \"\\\\5c\").replace(/ /g, \"\\\\20\").replace(/\\\"/g, \"\\\\22\").replace(/\\&/g, \"\\\\26\").replace(/\\'/g, \"\\\\27\").replace(/\\//g, \"\\\\2f\").replace(/:/g, \"\\\\3a\").replace(/</g, \"\\\\3c\").replace(/>/g, \"\\\\3e\").replace(/@/g, \"\\\\40\");\n              },\n\n              /** Function: unescapeNode\n               *  Unescape a node part (also called local part) of a JID.\n               *\n               *  Parameters:\n               *    (String) node - A node (or local part).\n               *\n               *  Returns:\n               *    An unescaped node (or local part).\n               */\n              unescapeNode(node) {\n                if (typeof node !== \"string\") {\n                  return node;\n                }\n\n                return node.replace(/\\\\20/g, \" \").replace(/\\\\22/g, '\"').replace(/\\\\26/g, \"&\").replace(/\\\\27/g, \"'\").replace(/\\\\2f/g, \"/\").replace(/\\\\3a/g, \":\").replace(/\\\\3c/g, \"<\").replace(/\\\\3e/g, \">\").replace(/\\\\40/g, \"@\").replace(/\\\\5c/g, \"\\\\\");\n              },\n\n              /** Function: getNodeFromJid\n               *  Get the node portion of a JID String.\n               *\n               *  Parameters:\n               *    (String) jid - A JID.\n               *\n               *  Returns:\n               *    A String containing the node.\n               */\n              getNodeFromJid(jid) {\n                if (jid.indexOf(\"@\") < 0) {\n                  return null;\n                }\n\n                return jid.split(\"@\")[0];\n              },\n\n              /** Function: getDomainFromJid\n               *  Get the domain portion of a JID String.\n               *\n               *  Parameters:\n               *    (String) jid - A JID.\n               *\n               *  Returns:\n               *    A String containing the domain.\n               */\n              getDomainFromJid(jid) {\n                const bare = Strophe.getBareJidFromJid(jid);\n\n                if (bare.indexOf(\"@\") < 0) {\n                  return bare;\n                } else {\n                  const parts = bare.split(\"@\");\n                  parts.splice(0, 1);\n                  return parts.join('@');\n                }\n              },\n\n              /** Function: getResourceFromJid\n               *  Get the resource portion of a JID String.\n               *\n               *  Parameters:\n               *    (String) jid - A JID.\n               *\n               *  Returns:\n               *    A String containing the resource.\n               */\n              getResourceFromJid(jid) {\n                if (!jid) {\n                  return null;\n                }\n\n                const s = jid.split(\"/\");\n\n                if (s.length < 2) {\n                  return null;\n                }\n\n                s.splice(0, 1);\n                return s.join('/');\n              },\n\n              /** Function: getBareJidFromJid\n               *  Get the bare JID from a JID String.\n               *\n               *  Parameters:\n               *    (String) jid - A JID.\n               *\n               *  Returns:\n               *    A String containing the bare JID.\n               */\n              getBareJidFromJid(jid) {\n                return jid ? jid.split(\"/\")[0] : null;\n              },\n\n              /** PrivateFunction: _handleError\n               *  _Private_ function that properly logs an error to the console\n               */\n              _handleError(e) {\n                if (typeof e.stack !== \"undefined\") {\n                  Strophe.fatal(e.stack);\n                }\n\n                if (e.sourceURL) {\n                  Strophe.fatal(\"error: \" + this.handler + \" \" + e.sourceURL + \":\" + e.line + \" - \" + e.name + \": \" + e.message);\n                } else if (e.fileName) {\n                  Strophe.fatal(\"error: \" + this.handler + \" \" + e.fileName + \":\" + e.lineNumber + \" - \" + e.name + \": \" + e.message);\n                } else {\n                  Strophe.fatal(\"error: \" + e.message);\n                }\n              },\n\n              /** Function: log\n               *  User overrideable logging function.\n               *\n               *  This function is called whenever the Strophe library calls any\n               *  of the logging functions.  The default implementation of this\n               *  function logs only fatal errors.  If client code wishes to handle the logging\n               *  messages, it should override this with\n               *  > Strophe.log = function (level, msg) {\n               *  >   (user code here)\n               *  > };\n               *\n               *  Please note that data sent and received over the wire is logged\n               *  via Strophe.Connection.rawInput() and Strophe.Connection.rawOutput().\n               *\n               *  The different levels and their meanings are\n               *\n               *    DEBUG - Messages useful for debugging purposes.\n               *    INFO - Informational messages.  This is mostly information like\n               *      'disconnect was called' or 'SASL auth succeeded'.\n               *    WARN - Warnings about potential problems.  This is mostly used\n               *      to report transient connection errors like request timeouts.\n               *    ERROR - Some error occurred.\n               *    FATAL - A non-recoverable fatal error occurred.\n               *\n               *  Parameters:\n               *    (Integer) level - The log level of the log message.  This will\n               *      be one of the values in Strophe.LogLevel.\n               *    (String) msg - The log message.\n               */\n              log(level, msg) {\n                if (level === this.LogLevel.FATAL) {\n                  var _console;\n\n                  (_console = console) === null || _console === void 0 ? void 0 : _console.error(msg);\n                }\n              },\n\n              /** Function: debug\n               *  Log a message at the Strophe.LogLevel.DEBUG level.\n               *\n               *  Parameters:\n               *    (String) msg - The log message.\n               */\n              debug(msg) {\n                this.log(this.LogLevel.DEBUG, msg);\n              },\n\n              /** Function: info\n               *  Log a message at the Strophe.LogLevel.INFO level.\n               *\n               *  Parameters:\n               *    (String) msg - The log message.\n               */\n              info(msg) {\n                this.log(this.LogLevel.INFO, msg);\n              },\n\n              /** Function: warn\n               *  Log a message at the Strophe.LogLevel.WARN level.\n               *\n               *  Parameters:\n               *    (String) msg - The log message.\n               */\n              warn(msg) {\n                this.log(this.LogLevel.WARN, msg);\n              },\n\n              /** Function: error\n               *  Log a message at the Strophe.LogLevel.ERROR level.\n               *\n               *  Parameters:\n               *    (String) msg - The log message.\n               */\n              error(msg) {\n                this.log(this.LogLevel.ERROR, msg);\n              },\n\n              /** Function: fatal\n               *  Log a message at the Strophe.LogLevel.FATAL level.\n               *\n               *  Parameters:\n               *    (String) msg - The log message.\n               */\n              fatal(msg) {\n                this.log(this.LogLevel.FATAL, msg);\n              },\n\n              /** Function: serialize\n               *  Render a DOM element and all descendants to a String.\n               *\n               *  Parameters:\n               *    (XMLElement) elem - A DOM element.\n               *\n               *  Returns:\n               *    The serialized element tree as a String.\n               */\n              serialize(elem) {\n                if (!elem) {\n                  return null;\n                }\n\n                if (typeof elem.tree === \"function\") {\n                  elem = elem.tree();\n                }\n\n                const names = [...Array(elem.attributes.length).keys()].map(i => elem.attributes[i].nodeName);\n                names.sort();\n                let result = names.reduce((a, n) => `${a} ${n}=\"${Strophe.xmlescape(elem.attributes.getNamedItem(n).value)}\"`, `<${elem.nodeName}`);\n\n                if (elem.childNodes.length > 0) {\n                  result += \">\";\n\n                  for (let i = 0; i < elem.childNodes.length; i++) {\n                    const child = elem.childNodes[i];\n\n                    switch (child.nodeType) {\n                      case Strophe.ElementType.NORMAL:\n                        // normal element, so recurse\n                        result += Strophe.serialize(child);\n                        break;\n\n                      case Strophe.ElementType.TEXT:\n                        // text element to escape values\n                        result += Strophe.xmlescape(child.nodeValue);\n                        break;\n\n                      case Strophe.ElementType.CDATA:\n                        // cdata section so don't escape values\n                        result += \"<![CDATA[\" + child.nodeValue + \"]]>\";\n                    }\n                  }\n\n                  result += \"</\" + elem.nodeName + \">\";\n                } else {\n                  result += \"/>\";\n                }\n\n                return result;\n              },\n\n              /** PrivateVariable: _requestId\n               *  _Private_ variable that keeps track of the request ids for\n               *  connections.\n               */\n              _requestId: 0,\n\n              /** PrivateVariable: Strophe.connectionPlugins\n               *  _Private_ variable Used to store plugin names that need\n               *  initialization on Strophe.Connection construction.\n               */\n              _connectionPlugins: {},\n\n              /** Function: addConnectionPlugin\n               *  Extends the Strophe.Connection object with the given plugin.\n               *\n               *  Parameters:\n               *    (String) name - The name of the extension.\n               *    (Object) ptype - The plugin's prototype.\n               */\n              addConnectionPlugin(name, ptype) {\n                Strophe._connectionPlugins[name] = ptype;\n              }\n\n            };\n            /** Class: Strophe.Builder\n             *  XML DOM builder.\n             *\n             *  This object provides an interface similar to JQuery but for building\n             *  DOM elements easily and rapidly.  All the functions except for toString()\n             *  and tree() return the object, so calls can be chained.  Here's an\n             *  example using the $iq() builder helper.\n             *  > $iq({to: 'you', from: 'me', type: 'get', id: '1'})\n             *  >     .c('query', {xmlns: 'strophe:example'})\n             *  >     .c('example')\n             *  >     .toString()\n             *\n             *  The above generates this XML fragment\n             *  > <iq to='you' from='me' type='get' id='1'>\n             *  >   <query xmlns='strophe:example'>\n             *  >     <example/>\n             *  >   </query>\n             *  > </iq>\n             *  The corresponding DOM manipulations to get a similar fragment would be\n             *  a lot more tedious and probably involve several helper variables.\n             *\n             *  Since adding children makes new operations operate on the child, up()\n             *  is provided to traverse up the tree.  To add two children, do\n             *  > builder.c('child1', ...).up().c('child2', ...)\n             *  The next operation on the Builder will be relative to the second child.\n             */\n\n            /** Constructor: Strophe.Builder\n             *  Create a Strophe.Builder object.\n             *\n             *  The attributes should be passed in object notation.  For example\n             *  > let b = new Builder('message', {to: 'you', from: 'me'});\n             *  or\n             *  > let b = new Builder('messsage', {'xml:lang': 'en'});\n             *\n             *  Parameters:\n             *    (String) name - The name of the root element.\n             *    (Object) attrs - The attributes for the root element in object notation.\n             *\n             *  Returns:\n             *    A new Strophe.Builder.\n             */\n\n            Strophe.Builder = class Builder {\n              constructor(name, attrs) {\n                // Set correct namespace for jabber:client elements\n                if (name === \"presence\" || name === \"message\" || name === \"iq\") {\n                  if (attrs && !attrs.xmlns) {\n                    attrs.xmlns = Strophe.NS.CLIENT;\n                  } else if (!attrs) {\n                    attrs = {\n                      xmlns: Strophe.NS.CLIENT\n                    };\n                  }\n                } // Holds the tree being built.\n\n\n                this.nodeTree = Strophe.xmlElement(name, attrs); // Points to the current operation node.\n\n                this.node = this.nodeTree;\n              }\n              /** Function: tree\n               *  Return the DOM tree.\n               *\n               *  This function returns the current DOM tree as an element object.  This\n               *  is suitable for passing to functions like Strophe.Connection.send().\n               *\n               *  Returns:\n               *    The DOM tree as a element object.\n               */\n\n\n              tree() {\n                return this.nodeTree;\n              }\n              /** Function: toString\n               *  Serialize the DOM tree to a String.\n               *\n               *  This function returns a string serialization of the current DOM\n               *  tree.  It is often used internally to pass data to a\n               *  Strophe.Request object.\n               *\n               *  Returns:\n               *    The serialized DOM tree in a String.\n               */\n\n\n              toString() {\n                return Strophe.serialize(this.nodeTree);\n              }\n              /** Function: up\n               *  Make the current parent element the new current element.\n               *\n               *  This function is often used after c() to traverse back up the tree.\n               *  For example, to add two children to the same element\n               *  > builder.c('child1', {}).up().c('child2', {});\n               *\n               *  Returns:\n               *    The Stophe.Builder object.\n               */\n\n\n              up() {\n                this.node = this.node.parentNode;\n                return this;\n              }\n              /** Function: root\n               *  Make the root element the new current element.\n               *\n               *  When at a deeply nested element in the tree, this function can be used\n               *  to jump back to the root of the tree, instead of having to repeatedly\n               *  call up().\n               *\n               *  Returns:\n               *    The Stophe.Builder object.\n               */\n\n\n              root() {\n                this.node = this.nodeTree;\n                return this;\n              }\n              /** Function: attrs\n               *  Add or modify attributes of the current element.\n               *\n               *  The attributes should be passed in object notation.  This function\n               *  does not move the current element pointer.\n               *\n               *  Parameters:\n               *    (Object) moreattrs - The attributes to add/modify in object notation.\n               *\n               *  Returns:\n               *    The Strophe.Builder object.\n               */\n\n\n              attrs(moreattrs) {\n                for (const k in moreattrs) {\n                  if (Object.prototype.hasOwnProperty.call(moreattrs, k)) {\n                    if (moreattrs[k] === undefined) {\n                      this.node.removeAttribute(k);\n                    } else {\n                      this.node.setAttribute(k, moreattrs[k]);\n                    }\n                  }\n                }\n\n                return this;\n              }\n              /** Function: c\n               *  Add a child to the current element and make it the new current\n               *  element.\n               *\n               *  This function moves the current element pointer to the child,\n               *  unless text is provided.  If you need to add another child, it\n               *  is necessary to use up() to go back to the parent in the tree.\n               *\n               *  Parameters:\n               *    (String) name - The name of the child.\n               *    (Object) attrs - The attributes of the child in object notation.\n               *    (String) text - The text to add to the child.\n               *\n               *  Returns:\n               *    The Strophe.Builder object.\n               */\n\n\n              c(name, attrs, text) {\n                const child = Strophe.xmlElement(name, attrs, text);\n                this.node.appendChild(child);\n\n                if (typeof text !== \"string\" && typeof text !== \"number\") {\n                  this.node = child;\n                }\n\n                return this;\n              }\n              /** Function: cnode\n               *  Add a child to the current element and make it the new current\n               *  element.\n               *\n               *  This function is the same as c() except that instead of using a\n               *  name and an attributes object to create the child it uses an\n               *  existing DOM element object.\n               *\n               *  Parameters:\n               *    (XMLElement) elem - A DOM element.\n               *\n               *  Returns:\n               *    The Strophe.Builder object.\n               */\n\n\n              cnode(elem) {\n                let impNode;\n                const xmlGen = Strophe.xmlGenerator();\n\n                try {\n                  impNode = xmlGen.importNode !== undefined;\n                } catch (e) {\n                  impNode = false;\n                }\n\n                const newElem = impNode ? xmlGen.importNode(elem, true) : Strophe.copyElement(elem);\n                this.node.appendChild(newElem);\n                this.node = newElem;\n                return this;\n              }\n              /** Function: t\n               *  Add a child text element.\n               *\n               *  This *does not* make the child the new current element since there\n               *  are no children of text elements.\n               *\n               *  Parameters:\n               *    (String) text - The text data to append to the current element.\n               *\n               *  Returns:\n               *    The Strophe.Builder object.\n               */\n\n\n              t(text) {\n                const child = Strophe.xmlTextNode(text);\n                this.node.appendChild(child);\n                return this;\n              }\n              /** Function: h\n               *  Replace current element contents with the HTML passed in.\n               *\n               *  This *does not* make the child the new current element\n               *\n               *  Parameters:\n               *    (String) html - The html to insert as contents of current element.\n               *\n               *  Returns:\n               *    The Strophe.Builder object.\n               */\n\n\n              h(html) {\n                const fragment = Strophe.xmlGenerator().createElement('body'); // force the browser to try and fix any invalid HTML tags\n\n                fragment.innerHTML = html; // copy cleaned html into an xml dom\n\n                const xhtml = Strophe.createHtml(fragment);\n\n                while (xhtml.childNodes.length > 0) {\n                  this.node.appendChild(xhtml.childNodes[0]);\n                }\n\n                return this;\n              }\n\n            };\n            /** PrivateClass: Strophe.Handler\n             *  _Private_ helper class for managing stanza handlers.\n             *\n             *  A Strophe.Handler encapsulates a user provided callback function to be\n             *  executed when matching stanzas are received by the connection.\n             *  Handlers can be either one-off or persistant depending on their\n             *  return value. Returning true will cause a Handler to remain active, and\n             *  returning false will remove the Handler.\n             *\n             *  Users will not use Strophe.Handler objects directly, but instead they\n             *  will use Strophe.Connection.addHandler() and\n             *  Strophe.Connection.deleteHandler().\n             */\n\n            /** PrivateConstructor: Strophe.Handler\n             *  Create and initialize a new Strophe.Handler.\n             *\n             *  Parameters:\n             *    (Function) handler - A function to be executed when the handler is run.\n             *    (String) ns - The namespace to match.\n             *    (String) name - The element name to match.\n             *    (String) type - The element type to match.\n             *    (String) id - The element id attribute to match.\n             *    (String) from - The element from attribute to match.\n             *    (Object) options - Handler options\n             *\n             *  Returns:\n             *    A new Strophe.Handler object.\n             */\n\n            Strophe.Handler = function (handler, ns, name, type, id, from, options) {\n              this.handler = handler;\n              this.ns = ns;\n              this.name = name;\n              this.type = type;\n              this.id = id;\n              this.options = options || {\n                'matchBareFromJid': false,\n                'ignoreNamespaceFragment': false\n              }; // BBB: Maintain backward compatibility with old `matchBare` option\n\n              if (this.options.matchBare) {\n                Strophe.warn('The \"matchBare\" option is deprecated, use \"matchBareFromJid\" instead.');\n                this.options.matchBareFromJid = this.options.matchBare;\n                delete this.options.matchBare;\n              }\n\n              if (this.options.matchBareFromJid) {\n                this.from = from ? Strophe.getBareJidFromJid(from) : null;\n              } else {\n                this.from = from;\n              } // whether the handler is a user handler or a system handler\n\n\n              this.user = true;\n            };\n\n            Strophe.Handler.prototype = {\n              /** PrivateFunction: getNamespace\n               *  Returns the XML namespace attribute on an element.\n               *  If `ignoreNamespaceFragment` was passed in for this handler, then the\n               *  URL fragment will be stripped.\n               *\n               *  Parameters:\n               *    (XMLElement) elem - The XML element with the namespace.\n               *\n               *  Returns:\n               *    The namespace, with optionally the fragment stripped.\n               */\n              getNamespace(elem) {\n                let elNamespace = elem.getAttribute(\"xmlns\");\n\n                if (elNamespace && this.options.ignoreNamespaceFragment) {\n                  elNamespace = elNamespace.split('#')[0];\n                }\n\n                return elNamespace;\n              },\n\n              /** PrivateFunction: namespaceMatch\n               *  Tests if a stanza matches the namespace set for this Strophe.Handler.\n               *\n               *  Parameters:\n               *    (XMLElement) elem - The XML element to test.\n               *\n               *  Returns:\n               *    true if the stanza matches and false otherwise.\n               */\n              namespaceMatch(elem) {\n                let nsMatch = false;\n\n                if (!this.ns) {\n                  return true;\n                } else {\n                  Strophe.forEachChild(elem, null, elem => {\n                    if (this.getNamespace(elem) === this.ns) {\n                      nsMatch = true;\n                    }\n                  });\n                  return nsMatch || this.getNamespace(elem) === this.ns;\n                }\n              },\n\n              /** PrivateFunction: isMatch\n               *  Tests if a stanza matches the Strophe.Handler.\n               *\n               *  Parameters:\n               *    (XMLElement) elem - The XML element to test.\n               *\n               *  Returns:\n               *    true if the stanza matches and false otherwise.\n               */\n              isMatch(elem) {\n                let from = elem.getAttribute('from');\n\n                if (this.options.matchBareFromJid) {\n                  from = Strophe.getBareJidFromJid(from);\n                }\n\n                const elem_type = elem.getAttribute(\"type\");\n\n                if (this.namespaceMatch(elem) && (!this.name || Strophe.isTagEqual(elem, this.name)) && (!this.type || (Array.isArray(this.type) ? this.type.indexOf(elem_type) !== -1 : elem_type === this.type)) && (!this.id || elem.getAttribute(\"id\") === this.id) && (!this.from || from === this.from)) {\n                  return true;\n                }\n\n                return false;\n              },\n\n              /** PrivateFunction: run\n               *  Run the callback on a matching stanza.\n               *\n               *  Parameters:\n               *    (XMLElement) elem - The DOM element that triggered the\n               *      Strophe.Handler.\n               *\n               *  Returns:\n               *    A boolean indicating if the handler should remain active.\n               */\n              run(elem) {\n                let result = null;\n\n                try {\n                  result = this.handler(elem);\n                } catch (e) {\n                  Strophe._handleError(e);\n\n                  throw e;\n                }\n\n                return result;\n              },\n\n              /** PrivateFunction: toString\n               *  Get a String representation of the Strophe.Handler object.\n               *\n               *  Returns:\n               *    A String.\n               */\n              toString() {\n                return \"{Handler: \" + this.handler + \"(\" + this.name + \",\" + this.id + \",\" + this.ns + \")}\";\n              }\n\n            };\n            /** PrivateClass: Strophe.TimedHandler\n             *  _Private_ helper class for managing timed handlers.\n             *\n             *  A Strophe.TimedHandler encapsulates a user provided callback that\n             *  should be called after a certain period of time or at regular\n             *  intervals.  The return value of the callback determines whether the\n             *  Strophe.TimedHandler will continue to fire.\n             *\n             *  Users will not use Strophe.TimedHandler objects directly, but instead\n             *  they will use Strophe.Connection.addTimedHandler() and\n             *  Strophe.Connection.deleteTimedHandler().\n             */\n\n            Strophe.TimedHandler = class TimedHandler {\n              /** PrivateConstructor: Strophe.TimedHandler\n               *  Create and initialize a new Strophe.TimedHandler object.\n               *\n               *  Parameters:\n               *    (Integer) period - The number of milliseconds to wait before the\n               *      handler is called.\n               *    (Function) handler - The callback to run when the handler fires.  This\n               *      function should take no arguments.\n               *\n               *  Returns:\n               *    A new Strophe.TimedHandler object.\n               */\n              constructor(period, handler) {\n                this.period = period;\n                this.handler = handler;\n                this.lastCalled = new Date().getTime();\n                this.user = true;\n              }\n              /** PrivateFunction: run\n               *  Run the callback for the Strophe.TimedHandler.\n               *\n               *  Returns:\n               *    true if the Strophe.TimedHandler should be called again, and false\n               *      otherwise.\n               */\n\n\n              run() {\n                this.lastCalled = new Date().getTime();\n                return this.handler();\n              }\n              /** PrivateFunction: reset\n               *  Reset the last called time for the Strophe.TimedHandler.\n               */\n\n\n              reset() {\n                this.lastCalled = new Date().getTime();\n              }\n              /** PrivateFunction: toString\n               *  Get a string representation of the Strophe.TimedHandler object.\n               *\n               *  Returns:\n               *    The string representation.\n               */\n\n\n              toString() {\n                return \"{TimedHandler: \" + this.handler + \"(\" + this.period + \")}\";\n              }\n\n            };\n            /** Class: Strophe.Connection\n             *  XMPP Connection manager.\n             *\n             *  This class is the main part of Strophe.  It manages a BOSH or websocket\n             *  connection to an XMPP server and dispatches events to the user callbacks\n             *  as data arrives. It supports SASL PLAIN, SASL SCRAM-SHA-1\n             *  and legacy authentication.\n             *\n             *  After creating a Strophe.Connection object, the user will typically\n             *  call connect() with a user supplied callback to handle connection level\n             *  events like authentication failure, disconnection, or connection\n             *  complete.\n             *\n             *  The user will also have several event handlers defined by using\n             *  addHandler() and addTimedHandler().  These will allow the user code to\n             *  respond to interesting stanzas or do something periodically with the\n             *  connection. These handlers will be active once authentication is\n             *  finished.\n             *\n             *  To send data to the connection, use send().\n             */\n\n            /** Constructor: Strophe.Connection\n             *  Create and initialize a Strophe.Connection object.\n             *\n             *  The transport-protocol for this connection will be chosen automatically\n             *  based on the given service parameter. URLs starting with \"ws://\" or\n             *  \"wss://\" will use WebSockets, URLs starting with \"http://\", \"https://\"\n             *  or without a protocol will use BOSH.\n             *\n             *  To make Strophe connect to the current host you can leave out the protocol\n             *  and host part and just pass the path, e.g.\n             *\n             *  > let conn = new Strophe.Connection(\"/http-bind/\");\n             *\n             *  Options common to both Websocket and BOSH:\n             *  ------------------------------------------\n             *\n             *  cookies:\n             *\n             *  The *cookies* option allows you to pass in cookies to be added to the\n             *  document. These cookies will then be included in the BOSH XMLHttpRequest\n             *  or in the websocket connection.\n             *\n             *  The passed in value must be a map of cookie names and string values.\n             *\n             *  > { \"myCookie\": {\n             *  >     \"value\": \"1234\",\n             *  >     \"domain\": \".example.org\",\n             *  >     \"path\": \"/\",\n             *  >     \"expires\": expirationDate\n             *  >     }\n             *  > }\n             *\n             *  Note that cookies can't be set in this way for other domains (i.e. cross-domain).\n             *  Those cookies need to be set under those domains, for example they can be\n             *  set server-side by making a XHR call to that domain to ask it to set any\n             *  necessary cookies.\n             *\n             *  mechanisms:\n             *\n             *  The *mechanisms* option allows you to specify the SASL mechanisms that this\n             *  instance of Strophe.Connection (and therefore your XMPP client) will\n             *  support.\n             *\n             *  The value must be an array of objects with Strophe.SASLMechanism\n             *  prototypes.\n             *\n             *  If nothing is specified, then the following mechanisms (and their\n             *  priorities) are registered:\n             *\n             *      SCRAM-SHA-1 - 60\n             *      PLAIN       - 50\n             *      OAUTHBEARER - 40\n             *      X-OAUTH2    - 30\n             *      ANONYMOUS   - 20\n             *      EXTERNAL    - 10\n             *\n             *  explicitResourceBinding:\n             *\n             *  If `explicitResourceBinding` is set to a truthy value, then the XMPP client\n             *  needs to explicitly call `Strophe.Connection.prototype.bind` once the XMPP\n             *  server has advertised the \"urn:ietf:params:xml:ns:xmpp-bind\" feature.\n             *\n             *  Making this step explicit allows client authors to first finish other\n             *  stream related tasks, such as setting up an XEP-0198 Stream Management\n             *  session, before binding the JID resource for this session.\n             *\n             *  WebSocket options:\n             *  ------------------\n             *\n             *  protocol:\n             *\n             *  If you want to connect to the current host with a WebSocket connection you\n             *  can tell Strophe to use WebSockets through a \"protocol\" attribute in the\n             *  optional options parameter. Valid values are \"ws\" for WebSocket and \"wss\"\n             *  for Secure WebSocket.\n             *  So to connect to \"wss://CURRENT_HOSTNAME/xmpp-websocket\" you would call\n             *\n             *  > let conn = new Strophe.Connection(\"/xmpp-websocket/\", {protocol: \"wss\"});\n             *\n             *  Note that relative URLs _NOT_ starting with a \"/\" will also include the path\n             *  of the current site.\n             *\n             *  Also because downgrading security is not permitted by browsers, when using\n             *  relative URLs both BOSH and WebSocket connections will use their secure\n             *  variants if the current connection to the site is also secure (https).\n             *\n             *  worker:\n             *\n             *  Set this option to URL from where the shared worker script should be loaded.\n             *\n             *  To run the websocket connection inside a shared worker.\n             *  This allows you to share a single websocket-based connection between\n             *  multiple Strophe.Connection instances, for example one per browser tab.\n             *\n             *  The script to use is the one in `src/shared-connection-worker.js`.\n             *\n             *  BOSH options:\n             *  -------------\n             *\n             *  By adding \"sync\" to the options, you can control if requests will\n             *  be made synchronously or not. The default behaviour is asynchronous.\n             *  If you want to make requests synchronous, make \"sync\" evaluate to true.\n             *  > let conn = new Strophe.Connection(\"/http-bind/\", {sync: true});\n             *\n             *  You can also toggle this on an already established connection.\n             *  > conn.options.sync = true;\n             *\n             *  The *customHeaders* option can be used to provide custom HTTP headers to be\n             *  included in the XMLHttpRequests made.\n             *\n             *  The *keepalive* option can be used to instruct Strophe to maintain the\n             *  current BOSH session across interruptions such as webpage reloads.\n             *\n             *  It will do this by caching the sessions tokens in sessionStorage, and when\n             *  \"restore\" is called it will check whether there are cached tokens with\n             *  which it can resume an existing session.\n             *\n             *  The *withCredentials* option should receive a Boolean value and is used to\n             *  indicate wether cookies should be included in ajax requests (by default\n             *  they're not).\n             *  Set this value to true if you are connecting to a BOSH service\n             *  and for some reason need to send cookies to it.\n             *  In order for this to work cross-domain, the server must also enable\n             *  credentials by setting the Access-Control-Allow-Credentials response header\n             *  to \"true\". For most usecases however this setting should be false (which\n             *  is the default).\n             *  Additionally, when using Access-Control-Allow-Credentials, the\n             *  Access-Control-Allow-Origin header can't be set to the wildcard \"*\", but\n             *  instead must be restricted to actual domains.\n             *\n             *  The *contentType* option can be set to change the default Content-Type\n             *  of \"text/xml; charset=utf-8\", which can be useful to reduce the amount of\n             *  CORS preflight requests that are sent to the server.\n             *\n             *  Parameters:\n             *    (String) service - The BOSH or WebSocket service URL.\n             *    (Object) options - A hash of configuration options\n             *\n             *  Returns:\n             *    A new Strophe.Connection object.\n             */\n\n            Strophe.Connection = class Connection {\n              constructor(service, options) {\n                // The service URL\n                this.service = service; // Configuration options\n\n                this.options = options || {};\n                this.setProtocol();\n                /* The connected JID. */\n\n                this.jid = \"\";\n                /* the JIDs domain */\n\n                this.domain = null;\n                /* stream:features */\n\n                this.features = null; // SASL\n\n                this._sasl_data = {};\n                this.do_bind = false;\n                this.do_session = false;\n                this.mechanisms = {}; // handler lists\n\n                this.timedHandlers = [];\n                this.handlers = [];\n                this.removeTimeds = [];\n                this.removeHandlers = [];\n                this.addTimeds = [];\n                this.addHandlers = [];\n                this.protocolErrorHandlers = {\n                  'HTTP': {},\n                  'websocket': {}\n                };\n                this._idleTimeout = null;\n                this._disconnectTimeout = null;\n                this.authenticated = false;\n                this.connected = false;\n                this.disconnecting = false;\n                this.do_authentication = true;\n                this.paused = false;\n                this.restored = false;\n                this._data = [];\n                this._uniqueId = 0;\n                this._sasl_success_handler = null;\n                this._sasl_failure_handler = null;\n                this._sasl_challenge_handler = null; // Max retries before disconnecting\n\n                this.maxRetries = 5; // Call onIdle callback every 1/10th of a second\n\n                this._idleTimeout = setTimeout(() => this._onIdle(), 100);\n                utils.addCookies(this.options.cookies);\n                this.registerSASLMechanisms(this.options.mechanisms); // A client must always respond to incoming IQ \"set\" and \"get\" stanzas.\n                // See https://datatracker.ietf.org/doc/html/rfc6120#section-8.2.3\n                //\n                // This is a fallback handler which gets called when no other handler\n                // was called for a received IQ \"set\" or \"get\".\n\n                this.iqFallbackHandler = new Strophe.Handler(iq => this.send($iq({\n                  type: 'error',\n                  id: iq.getAttribute('id')\n                }).c('error', {\n                  'type': 'cancel'\n                }).c('service-unavailable', {\n                  'xmlns': Strophe.NS.STANZAS\n                })), null, 'iq', ['get', 'set']); // initialize plugins\n\n                for (const k in Strophe._connectionPlugins) {\n                  if (Object.prototype.hasOwnProperty.call(Strophe._connectionPlugins, k)) {\n                    const F = function () {};\n\n                    F.prototype = Strophe._connectionPlugins[k];\n                    this[k] = new F();\n                    this[k].init(this);\n                  }\n                }\n              }\n              /** Function: setProtocol\n               *  Select protocal based on this.options or this.service\n               */\n\n\n              setProtocol() {\n                const proto = this.options.protocol || \"\";\n\n                if (this.options.worker) {\n                  this._proto = new Strophe.WorkerWebsocket(this);\n                } else if (this.service.indexOf(\"ws:\") === 0 || this.service.indexOf(\"wss:\") === 0 || proto.indexOf(\"ws\") === 0) {\n                  this._proto = new Strophe.Websocket(this);\n                } else {\n                  this._proto = new Strophe.Bosh(this);\n                }\n              }\n              /** Function: reset\n               *  Reset the connection.\n               *\n               *  This function should be called after a connection is disconnected\n               *  before that connection is reused.\n               */\n\n\n              reset() {\n                this._proto._reset(); // SASL\n\n\n                this.do_session = false;\n                this.do_bind = false; // handler lists\n\n                this.timedHandlers = [];\n                this.handlers = [];\n                this.removeTimeds = [];\n                this.removeHandlers = [];\n                this.addTimeds = [];\n                this.addHandlers = [];\n                this.authenticated = false;\n                this.connected = false;\n                this.disconnecting = false;\n                this.restored = false;\n                this._data = [];\n                this._requests = [];\n                this._uniqueId = 0;\n              }\n              /** Function: pause\n               *  Pause the request manager.\n               *\n               *  This will prevent Strophe from sending any more requests to the\n               *  server.  This is very useful for temporarily pausing\n               *  BOSH-Connections while a lot of send() calls are happening quickly.\n               *  This causes Strophe to send the data in a single request, saving\n               *  many request trips.\n               */\n\n\n              pause() {\n                this.paused = true;\n              }\n              /** Function: resume\n               *  Resume the request manager.\n               *\n               *  This resumes after pause() has been called.\n               */\n\n\n              resume() {\n                this.paused = false;\n              }\n              /** Function: getUniqueId\n               *  Generate a unique ID for use in <iq/> elements.\n               *\n               *  All <iq/> stanzas are required to have unique id attributes.  This\n               *  function makes creating these easy.  Each connection instance has\n               *  a counter which starts from zero, and the value of this counter\n               *  plus a colon followed by the suffix becomes the unique id. If no\n               *  suffix is supplied, the counter is used as the unique id.\n               *\n               *  Suffixes are used to make debugging easier when reading the stream\n               *  data, and their use is recommended.  The counter resets to 0 for\n               *  every new connection for the same reason.  For connections to the\n               *  same server that authenticate the same way, all the ids should be\n               *  the same, which makes it easy to see changes.  This is useful for\n               *  automated testing as well.\n               *\n               *  Parameters:\n               *    (String) suffix - A optional suffix to append to the id.\n               *\n               *  Returns:\n               *    A unique string to be used for the id attribute.\n               */\n\n\n              getUniqueId(suffix) {\n                // eslint-disable-line class-methods-use-this\n                const uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {\n                  const r = Math.random() * 16 | 0,\n                        v = c === 'x' ? r : r & 0x3 | 0x8;\n                  return v.toString(16);\n                });\n\n                if (typeof suffix === \"string\" || typeof suffix === \"number\") {\n                  return uuid + \":\" + suffix;\n                } else {\n                  return uuid + \"\";\n                }\n              }\n              /** Function: addProtocolErrorHandler\n               *  Register a handler function for when a protocol (websocker or HTTP)\n               *  error occurs.\n               *\n               *  NOTE: Currently only HTTP errors for BOSH requests are handled.\n               *  Patches that handle websocket errors would be very welcome.\n               *\n               *  Parameters:\n               *    (String) protocol - 'HTTP' or 'websocket'\n               *    (Integer) status_code - Error status code (e.g 500, 400 or 404)\n               *    (Function) callback - Function that will fire on Http error\n               *\n               *  Example:\n               *  function onError(err_code){\n               *    //do stuff\n               *  }\n               *\n               *  let conn = Strophe.connect('http://example.com/http-bind');\n               *  conn.addProtocolErrorHandler('HTTP', 500, onError);\n               *  // Triggers HTTP 500 error and onError handler will be called\n               *  conn.connect('user_jid@incorrect_jabber_host', 'secret', onConnect);\n               */\n\n\n              addProtocolErrorHandler(protocol, status_code, callback) {\n                this.protocolErrorHandlers[protocol][status_code] = callback;\n              }\n              /** Function: connect\n               *  Starts the connection process.\n               *\n               *  As the connection process proceeds, the user supplied callback will\n               *  be triggered multiple times with status updates.  The callback\n               *  should take two arguments - the status code and the error condition.\n               *\n               *  The status code will be one of the values in the Strophe.Status\n               *  constants.  The error condition will be one of the conditions\n               *  defined in RFC 3920 or the condition 'strophe-parsererror'.\n               *\n               *  The Parameters _wait_, _hold_ and _route_ are optional and only relevant\n               *  for BOSH connections. Please see XEP 124 for a more detailed explanation\n               *  of the optional parameters.\n               *\n               *  Parameters:\n               *    (String) jid - The user's JID.  This may be a bare JID,\n               *      or a full JID.  If a node is not supplied, SASL OAUTHBEARER or\n               *      SASL ANONYMOUS authentication will be attempted (OAUTHBEARER will\n               *      process the provided password value as an access token).\n               *    (String) pass - The user's password.\n               *    (Function) callback - The connect callback function.\n               *    (Integer) wait - The optional HTTPBIND wait value.  This is the\n               *      time the server will wait before returning an empty result for\n               *      a request.  The default setting of 60 seconds is recommended.\n               *    (Integer) hold - The optional HTTPBIND hold value.  This is the\n               *      number of connections the server will hold at one time.  This\n               *      should almost always be set to 1 (the default).\n               *    (String) route - The optional route value.\n               *    (String) authcid - The optional alternative authentication identity\n               *      (username) if intending to impersonate another user.\n               *      When using the SASL-EXTERNAL authentication mechanism, for example\n               *      with client certificates, then the authcid value is used to\n               *      determine whether an authorization JID (authzid) should be sent to\n               *      the server. The authzid should NOT be sent to the server if the\n               *      authzid and authcid are the same. So to prevent it from being sent\n               *      (for example when the JID is already contained in the client\n               *      certificate), set authcid to that same JID. See XEP-178 for more\n               *      details.\n               *     (Integer) disconnection_timeout - The optional disconnection timeout\n               *      in milliseconds before _doDisconnect will be called.\n               */\n\n\n              connect(jid, pass, callback, wait, hold, route, authcid) {\n                let disconnection_timeout = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : 3000;\n                this.jid = jid;\n                /** Variable: authzid\n                 *  Authorization identity.\n                 */\n\n                this.authzid = Strophe.getBareJidFromJid(this.jid);\n                /** Variable: authcid\n                 *  Authentication identity (User name).\n                 */\n\n                this.authcid = authcid || Strophe.getNodeFromJid(this.jid);\n                /** Variable: pass\n                 *  Authentication identity (User password).\n                 */\n\n                this.pass = pass;\n                this.connect_callback = callback;\n                this.disconnecting = false;\n                this.connected = false;\n                this.authenticated = false;\n                this.restored = false;\n                this.disconnection_timeout = disconnection_timeout; // parse jid for domain\n\n                this.domain = Strophe.getDomainFromJid(this.jid);\n\n                this._changeConnectStatus(Strophe.Status.CONNECTING, null);\n\n                this._proto._connect(wait, hold, route);\n              }\n              /** Function: attach\n               *  Attach to an already created and authenticated BOSH session.\n               *\n               *  This function is provided to allow Strophe to attach to BOSH\n               *  sessions which have been created externally, perhaps by a Web\n               *  application.  This is often used to support auto-login type features\n               *  without putting user credentials into the page.\n               *\n               *  Parameters:\n               *    (String) jid - The full JID that is bound by the session.\n               *    (String) sid - The SID of the BOSH session.\n               *    (String) rid - The current RID of the BOSH session.  This RID\n               *      will be used by the next request.\n               *    (Function) callback The connect callback function.\n               *    (Integer) wait - The optional HTTPBIND wait value.  This is the\n               *      time the server will wait before returning an empty result for\n               *      a request.  The default setting of 60 seconds is recommended.\n               *      Other settings will require tweaks to the Strophe.TIMEOUT value.\n               *    (Integer) hold - The optional HTTPBIND hold value.  This is the\n               *      number of connections the server will hold at one time.  This\n               *      should almost always be set to 1 (the default).\n               *    (Integer) wind - The optional HTTBIND window value.  This is the\n               *      allowed range of request ids that are valid.  The default is 5.\n               */\n\n\n              attach(jid, sid, rid, callback, wait, hold, wind) {\n                if (this._proto._attach) {\n                  return this._proto._attach(jid, sid, rid, callback, wait, hold, wind);\n                } else {\n                  const error = new Error('The \"attach\" method is not available for your connection protocol');\n                  error.name = 'StropheSessionError';\n                  throw error;\n                }\n              }\n              /** Function: restore\n               *  Attempt to restore a cached BOSH session.\n               *\n               *  This function is only useful in conjunction with providing the\n               *  \"keepalive\":true option when instantiating a new Strophe.Connection.\n               *\n               *  When \"keepalive\" is set to true, Strophe will cache the BOSH tokens\n               *  RID (Request ID) and SID (Session ID) and then when this function is\n               *  called, it will attempt to restore the session from those cached\n               *  tokens.\n               *\n               *  This function must therefore be called instead of connect or attach.\n               *\n               *  For an example on how to use it, please see examples/restore.js\n               *\n               *  Parameters:\n               *    (String) jid - The user's JID.  This may be a bare JID or a full JID.\n               *    (Function) callback - The connect callback function.\n               *    (Integer) wait - The optional HTTPBIND wait value.  This is the\n               *      time the server will wait before returning an empty result for\n               *      a request.  The default setting of 60 seconds is recommended.\n               *    (Integer) hold - The optional HTTPBIND hold value.  This is the\n               *      number of connections the server will hold at one time.  This\n               *      should almost always be set to 1 (the default).\n               *    (Integer) wind - The optional HTTBIND window value.  This is the\n               *      allowed range of request ids that are valid.  The default is 5.\n               */\n\n\n              restore(jid, callback, wait, hold, wind) {\n                if (this._sessionCachingSupported()) {\n                  this._proto._restore(jid, callback, wait, hold, wind);\n                } else {\n                  const error = new Error('The \"restore\" method can only be used with a BOSH connection.');\n                  error.name = 'StropheSessionError';\n                  throw error;\n                }\n              }\n              /** PrivateFunction: _sessionCachingSupported\n               * Checks whether sessionStorage and JSON are supported and whether we're\n               * using BOSH.\n               */\n\n\n              _sessionCachingSupported() {\n                if (this._proto instanceof Strophe.Bosh) {\n                  if (!JSON) {\n                    return false;\n                  }\n\n                  try {\n                    sessionStorage.setItem('_strophe_', '_strophe_');\n                    sessionStorage.removeItem('_strophe_');\n                  } catch (e) {\n                    return false;\n                  }\n\n                  return true;\n                }\n\n                return false;\n              }\n              /** Function: xmlInput\n               *  User overrideable function that receives XML data coming into the\n               *  connection.\n               *\n               *  The default function does nothing.  User code can override this with\n               *  > Strophe.Connection.xmlInput = function (elem) {\n               *  >   (user code)\n               *  > };\n               *\n               *  Due to limitations of current Browsers' XML-Parsers the opening and closing\n               *  <stream> tag for WebSocket-Connoctions will be passed as selfclosing here.\n               *\n               *  BOSH-Connections will have all stanzas wrapped in a <body> tag. See\n               *  <Strophe.Bosh.strip> if you want to strip this tag.\n               *\n               *  Parameters:\n               *    (XMLElement) elem - The XML data received by the connection.\n               */\n\n\n              xmlInput(elem) {\n                // eslint-disable-line\n                return;\n              }\n              /** Function: xmlOutput\n               *  User overrideable function that receives XML data sent to the\n               *  connection.\n               *\n               *  The default function does nothing.  User code can override this with\n               *  > Strophe.Connection.xmlOutput = function (elem) {\n               *  >   (user code)\n               *  > };\n               *\n               *  Due to limitations of current Browsers' XML-Parsers the opening and closing\n               *  <stream> tag for WebSocket-Connoctions will be passed as selfclosing here.\n               *\n               *  BOSH-Connections will have all stanzas wrapped in a <body> tag. See\n               *  <Strophe.Bosh.strip> if you want to strip this tag.\n               *\n               *  Parameters:\n               *    (XMLElement) elem - The XMLdata sent by the connection.\n               */\n\n\n              xmlOutput(elem) {\n                // eslint-disable-line\n                return;\n              }\n              /** Function: rawInput\n               *  User overrideable function that receives raw data coming into the\n               *  connection.\n               *\n               *  The default function does nothing.  User code can override this with\n               *  > Strophe.Connection.rawInput = function (data) {\n               *  >   (user code)\n               *  > };\n               *\n               *  Parameters:\n               *    (String) data - The data received by the connection.\n               */\n\n\n              rawInput(data) {\n                // eslint-disable-line\n                return;\n              }\n              /** Function: rawOutput\n               *  User overrideable function that receives raw data sent to the\n               *  connection.\n               *\n               *  The default function does nothing.  User code can override this with\n               *  > Strophe.Connection.rawOutput = function (data) {\n               *  >   (user code)\n               *  > };\n               *\n               *  Parameters:\n               *    (String) data - The data sent by the connection.\n               */\n\n\n              rawOutput(data) {\n                // eslint-disable-line\n                return;\n              }\n              /** Function: nextValidRid\n               *  User overrideable function that receives the new valid rid.\n               *\n               *  The default function does nothing. User code can override this with\n               *  > Strophe.Connection.nextValidRid = function (rid) {\n               *  >    (user code)\n               *  > };\n               *\n               *  Parameters:\n               *    (Number) rid - The next valid rid\n               */\n\n\n              nextValidRid(rid) {\n                // eslint-disable-line\n                return;\n              }\n              /** Function: send\n               *  Send a stanza.\n               *\n               *  This function is called to push data onto the send queue to\n               *  go out over the wire.  Whenever a request is sent to the BOSH\n               *  server, all pending data is sent and the queue is flushed.\n               *\n               *  Parameters:\n               *    (XMLElement |\n               *     [XMLElement] |\n               *     Strophe.Builder) elem - The stanza to send.\n               */\n\n\n              send(elem) {\n                if (elem === null) {\n                  return;\n                }\n\n                if (typeof elem.sort === \"function\") {\n                  for (let i = 0; i < elem.length; i++) {\n                    this._queueData(elem[i]);\n                  }\n                } else if (typeof elem.tree === \"function\") {\n                  this._queueData(elem.tree());\n                } else {\n                  this._queueData(elem);\n                }\n\n                this._proto._send();\n              }\n              /** Function: flush\n               *  Immediately send any pending outgoing data.\n               *\n               *  Normally send() queues outgoing data until the next idle period\n               *  (100ms), which optimizes network use in the common cases when\n               *  several send()s are called in succession. flush() can be used to\n               *  immediately send all pending data.\n               */\n\n\n              flush() {\n                // cancel the pending idle period and run the idle function\n                // immediately\n                clearTimeout(this._idleTimeout);\n\n                this._onIdle();\n              }\n              /** Function: sendPresence\n               *  Helper function to send presence stanzas. The main benefit is for\n               *  sending presence stanzas for which you expect a responding presence\n               *  stanza with the same id (for example when leaving a chat room).\n               *\n               *  Parameters:\n               *    (XMLElement) elem - The stanza to send.\n               *    (Function) callback - The callback function for a successful request.\n               *    (Function) errback - The callback function for a failed or timed\n               *      out request.  On timeout, the stanza will be null.\n               *    (Integer) timeout - The time specified in milliseconds for a\n               *      timeout to occur.\n               *\n               *  Returns:\n               *    The id used to send the presence.\n               */\n\n\n              sendPresence(elem, callback, errback, timeout) {\n                let timeoutHandler = null;\n\n                if (typeof elem.tree === \"function\") {\n                  elem = elem.tree();\n                }\n\n                let id = elem.getAttribute('id');\n\n                if (!id) {\n                  // inject id if not found\n                  id = this.getUniqueId(\"sendPresence\");\n                  elem.setAttribute(\"id\", id);\n                }\n\n                if (typeof callback === \"function\" || typeof errback === \"function\") {\n                  const handler = this.addHandler(stanza => {\n                    // remove timeout handler if there is one\n                    if (timeoutHandler) {\n                      this.deleteTimedHandler(timeoutHandler);\n                    }\n\n                    if (stanza.getAttribute('type') === 'error') {\n                      if (errback) {\n                        errback(stanza);\n                      }\n                    } else if (callback) {\n                      callback(stanza);\n                    }\n                  }, null, 'presence', null, id); // if timeout specified, set up a timeout handler.\n\n                  if (timeout) {\n                    timeoutHandler = this.addTimedHandler(timeout, () => {\n                      // get rid of normal handler\n                      this.deleteHandler(handler); // call errback on timeout with null stanza\n\n                      if (errback) {\n                        errback(null);\n                      }\n\n                      return false;\n                    });\n                  }\n                }\n\n                this.send(elem);\n                return id;\n              }\n              /** Function: sendIQ\n               *  Helper function to send IQ stanzas.\n               *\n               *  Parameters:\n               *    (XMLElement) elem - The stanza to send.\n               *    (Function) callback - The callback function for a successful request.\n               *    (Function) errback - The callback function for a failed or timed\n               *      out request.  On timeout, the stanza will be null.\n               *    (Integer) timeout - The time specified in milliseconds for a\n               *      timeout to occur.\n               *\n               *  Returns:\n               *    The id used to send the IQ.\n              */\n\n\n              sendIQ(elem, callback, errback, timeout) {\n                let timeoutHandler = null;\n\n                if (typeof elem.tree === \"function\") {\n                  elem = elem.tree();\n                }\n\n                let id = elem.getAttribute('id');\n\n                if (!id) {\n                  // inject id if not found\n                  id = this.getUniqueId(\"sendIQ\");\n                  elem.setAttribute(\"id\", id);\n                }\n\n                if (typeof callback === \"function\" || typeof errback === \"function\") {\n                  const handler = this.addHandler(stanza => {\n                    // remove timeout handler if there is one\n                    if (timeoutHandler) {\n                      this.deleteTimedHandler(timeoutHandler);\n                    }\n\n                    const iqtype = stanza.getAttribute('type');\n\n                    if (iqtype === 'result') {\n                      if (callback) {\n                        callback(stanza);\n                      }\n                    } else if (iqtype === 'error') {\n                      if (errback) {\n                        errback(stanza);\n                      }\n                    } else {\n                      const error = new Error(`Got bad IQ type of ${iqtype}`);\n                      error.name = \"StropheError\";\n                      throw error;\n                    }\n                  }, null, 'iq', ['error', 'result'], id); // if timeout specified, set up a timeout handler.\n\n                  if (timeout) {\n                    timeoutHandler = this.addTimedHandler(timeout, () => {\n                      // get rid of normal handler\n                      this.deleteHandler(handler); // call errback on timeout with null stanza\n\n                      if (errback) {\n                        errback(null);\n                      }\n\n                      return false;\n                    });\n                  }\n                }\n\n                this.send(elem);\n                return id;\n              }\n              /** PrivateFunction: _queueData\n               *  Queue outgoing data for later sending.  Also ensures that the data\n               *  is a DOMElement.\n               */\n\n\n              _queueData(element) {\n                if (element === null || !element.tagName || !element.childNodes) {\n                  const error = new Error(\"Cannot queue non-DOMElement.\");\n                  error.name = \"StropheError\";\n                  throw error;\n                }\n\n                this._data.push(element);\n              }\n              /** PrivateFunction: _sendRestart\n               *  Send an xmpp:restart stanza.\n               */\n\n\n              _sendRestart() {\n                this._data.push(\"restart\");\n\n                this._proto._sendRestart();\n\n                this._idleTimeout = setTimeout(() => this._onIdle(), 100);\n              }\n              /** Function: addTimedHandler\n               *  Add a timed handler to the connection.\n               *\n               *  This function adds a timed handler.  The provided handler will\n               *  be called every period milliseconds until it returns false,\n               *  the connection is terminated, or the handler is removed.  Handlers\n               *  that wish to continue being invoked should return true.\n               *\n               *  Because of method binding it is necessary to save the result of\n               *  this function if you wish to remove a handler with\n               *  deleteTimedHandler().\n               *\n               *  Note that user handlers are not active until authentication is\n               *  successful.\n               *\n               *  Parameters:\n               *    (Integer) period - The period of the handler.\n               *    (Function) handler - The callback function.\n               *\n               *  Returns:\n               *    A reference to the handler that can be used to remove it.\n               */\n\n\n              addTimedHandler(period, handler) {\n                const thand = new Strophe.TimedHandler(period, handler);\n                this.addTimeds.push(thand);\n                return thand;\n              }\n              /** Function: deleteTimedHandler\n               *  Delete a timed handler for a connection.\n               *\n               *  This function removes a timed handler from the connection.  The\n               *  handRef parameter is *not* the function passed to addTimedHandler(),\n               *  but is the reference returned from addTimedHandler().\n               *\n               *  Parameters:\n               *    (Strophe.TimedHandler) handRef - The handler reference.\n               */\n\n\n              deleteTimedHandler(handRef) {\n                // this must be done in the Idle loop so that we don't change\n                // the handlers during iteration\n                this.removeTimeds.push(handRef);\n              }\n              /** Function: addHandler\n               *  Add a stanza handler for the connection.\n               *\n               *  This function adds a stanza handler to the connection.  The\n               *  handler callback will be called for any stanza that matches\n               *  the parameters.  Note that if multiple parameters are supplied,\n               *  they must all match for the handler to be invoked.\n               *\n               *  The handler will receive the stanza that triggered it as its argument.\n               *  *The handler should return true if it is to be invoked again;\n               *  returning false will remove the handler after it returns.*\n               *\n               *  As a convenience, the ns parameters applies to the top level element\n               *  and also any of its immediate children.  This is primarily to make\n               *  matching /iq/query elements easy.\n               *\n               *  Options\n               *  ~~~~~~~\n               *  With the options argument, you can specify boolean flags that affect how\n               *  matches are being done.\n               *\n               *  Currently two flags exist:\n               *\n               *  - matchBareFromJid:\n               *      When set to true, the from parameter and the\n               *      from attribute on the stanza will be matched as bare JIDs instead\n               *      of full JIDs. To use this, pass {matchBareFromJid: true} as the\n               *      value of options. The default value for matchBareFromJid is false.\n               *\n               *  - ignoreNamespaceFragment:\n               *      When set to true, a fragment specified on the stanza's namespace\n               *      URL will be ignored when it's matched with the one configured for\n               *      the handler.\n               *\n               *      This means that if you register like this:\n               *      >   connection.addHandler(\n               *      >       handler,\n               *      >       'http://jabber.org/protocol/muc',\n               *      >       null, null, null, null,\n               *      >       {'ignoreNamespaceFragment': true}\n               *      >   );\n               *\n               *      Then a stanza with XML namespace of\n               *      'http://jabber.org/protocol/muc#user' will also be matched. If\n               *      'ignoreNamespaceFragment' is false, then only stanzas with\n               *      'http://jabber.org/protocol/muc' will be matched.\n               *\n               *  Deleting the handler\n               *  ~~~~~~~~~~~~~~~~~~~~\n               *  The return value should be saved if you wish to remove the handler\n               *  with deleteHandler().\n               *\n               *  Parameters:\n               *    (Function) handler - The user callback.\n               *    (String) ns - The namespace to match.\n               *    (String) name - The stanza name to match.\n               *    (String|Array) type - The stanza type (or types if an array) to match.\n               *    (String) id - The stanza id attribute to match.\n               *    (String) from - The stanza from attribute to match.\n               *    (String) options - The handler options\n               *\n               *  Returns:\n               *    A reference to the handler that can be used to remove it.\n               */\n\n\n              addHandler(handler, ns, name, type, id, from, options) {\n                const hand = new Strophe.Handler(handler, ns, name, type, id, from, options);\n                this.addHandlers.push(hand);\n                return hand;\n              }\n              /** Function: deleteHandler\n               *  Delete a stanza handler for a connection.\n               *\n               *  This function removes a stanza handler from the connection.  The\n               *  handRef parameter is *not* the function passed to addHandler(),\n               *  but is the reference returned from addHandler().\n               *\n               *  Parameters:\n               *    (Strophe.Handler) handRef - The handler reference.\n               */\n\n\n              deleteHandler(handRef) {\n                // this must be done in the Idle loop so that we don't change\n                // the handlers during iteration\n                this.removeHandlers.push(handRef); // If a handler is being deleted while it is being added,\n                // prevent it from getting added\n\n                const i = this.addHandlers.indexOf(handRef);\n\n                if (i >= 0) {\n                  this.addHandlers.splice(i, 1);\n                }\n              }\n              /** Function: registerSASLMechanisms\n               *\n               * Register the SASL mechanisms which will be supported by this instance of\n               * Strophe.Connection (i.e. which this XMPP client will support).\n               *\n               *  Parameters:\n               *    (Array) mechanisms - Array of objects with Strophe.SASLMechanism prototypes\n               *\n               */\n\n\n              registerSASLMechanisms(mechanisms) {\n                this.mechanisms = {};\n                mechanisms = mechanisms || [Strophe.SASLAnonymous, Strophe.SASLExternal, Strophe.SASLOAuthBearer, Strophe.SASLXOAuth2, Strophe.SASLPlain, Strophe.SASLSHA1];\n                mechanisms.forEach(m => this.registerSASLMechanism(m));\n              }\n              /** Function: registerSASLMechanism\n               *\n               * Register a single SASL mechanism, to be supported by this client.\n               *\n               *  Parameters:\n               *    (Object) mechanism - Object with a Strophe.SASLMechanism prototype\n               *\n               */\n\n\n              registerSASLMechanism(Mechanism) {\n                const mechanism = new Mechanism();\n                this.mechanisms[mechanism.mechname] = mechanism;\n              }\n              /** Function: disconnect\n               *  Start the graceful disconnection process.\n               *\n               *  This function starts the disconnection process.  This process starts\n               *  by sending unavailable presence and sending BOSH body of type\n               *  terminate.  A timeout handler makes sure that disconnection happens\n               *  even if the BOSH server does not respond.\n               *  If the Connection object isn't connected, at least tries to abort all pending requests\n               *  so the connection object won't generate successful requests (which were already opened).\n               *\n               *  The user supplied connection callback will be notified of the\n               *  progress as this process happens.\n               *\n               *  Parameters:\n               *    (String) reason - The reason the disconnect is occuring.\n               */\n\n\n              disconnect(reason) {\n                this._changeConnectStatus(Strophe.Status.DISCONNECTING, reason);\n\n                if (reason) {\n                  Strophe.warn(\"Disconnect was called because: \" + reason);\n                } else {\n                  Strophe.info(\"Disconnect was called\");\n                }\n\n                if (this.connected) {\n                  let pres = false;\n                  this.disconnecting = true;\n\n                  if (this.authenticated) {\n                    pres = $pres({\n                      'xmlns': Strophe.NS.CLIENT,\n                      'type': 'unavailable'\n                    });\n                  } // setup timeout handler\n\n\n                  this._disconnectTimeout = this._addSysTimedHandler(this.disconnection_timeout, this._onDisconnectTimeout.bind(this));\n\n                  this._proto._disconnect(pres);\n                } else {\n                  Strophe.warn(\"Disconnect was called before Strophe connected to the server\");\n\n                  this._proto._abortAllRequests();\n\n                  this._doDisconnect();\n                }\n              }\n              /** PrivateFunction: _changeConnectStatus\n               *  _Private_ helper function that makes sure plugins and the user's\n               *  callback are notified of connection status changes.\n               *\n               *  Parameters:\n               *    (Integer) status - the new connection status, one of the values\n               *      in Strophe.Status\n               *    (String) condition - the error condition or null\n               *    (XMLElement) elem - The triggering stanza.\n               */\n\n\n              _changeConnectStatus(status, condition, elem) {\n                // notify all plugins listening for status changes\n                for (const k in Strophe._connectionPlugins) {\n                  if (Object.prototype.hasOwnProperty.call(Strophe._connectionPlugins, k)) {\n                    const plugin = this[k];\n\n                    if (plugin.statusChanged) {\n                      try {\n                        plugin.statusChanged(status, condition);\n                      } catch (err) {\n                        Strophe.error(`${k} plugin caused an exception changing status: ${err}`);\n                      }\n                    }\n                  }\n                } // notify the user's callback\n\n\n                if (this.connect_callback) {\n                  try {\n                    this.connect_callback(status, condition, elem);\n                  } catch (e) {\n                    Strophe._handleError(e);\n\n                    Strophe.error(`User connection callback caused an exception: ${e}`);\n                  }\n                }\n              }\n              /** PrivateFunction: _doDisconnect\n               *  _Private_ function to disconnect.\n               *\n               *  This is the last piece of the disconnection logic.  This resets the\n               *  connection and alerts the user's connection callback.\n               */\n\n\n              _doDisconnect(condition) {\n                if (typeof this._idleTimeout === \"number\") {\n                  clearTimeout(this._idleTimeout);\n                } // Cancel Disconnect Timeout\n\n\n                if (this._disconnectTimeout !== null) {\n                  this.deleteTimedHandler(this._disconnectTimeout);\n                  this._disconnectTimeout = null;\n                }\n\n                Strophe.debug(\"_doDisconnect was called\");\n\n                this._proto._doDisconnect();\n\n                this.authenticated = false;\n                this.disconnecting = false;\n                this.restored = false; // delete handlers\n\n                this.handlers = [];\n                this.timedHandlers = [];\n                this.removeTimeds = [];\n                this.removeHandlers = [];\n                this.addTimeds = [];\n                this.addHandlers = []; // tell the parent we disconnected\n\n                this._changeConnectStatus(Strophe.Status.DISCONNECTED, condition);\n\n                this.connected = false;\n              }\n              /** PrivateFunction: _dataRecv\n               *  _Private_ handler to processes incoming data from the the connection.\n               *\n               *  Except for _connect_cb handling the initial connection request,\n               *  this function handles the incoming data for all requests.  This\n               *  function also fires stanza handlers that match each incoming\n               *  stanza.\n               *\n               *  Parameters:\n               *    (Strophe.Request) req - The request that has data ready.\n               *    (string) req - The stanza a raw string (optiona).\n               */\n\n\n              _dataRecv(req, raw) {\n                const elem = this._proto._reqToData(req);\n\n                if (elem === null) {\n                  return;\n                }\n\n                if (this.xmlInput !== Strophe.Connection.prototype.xmlInput) {\n                  if (elem.nodeName === this._proto.strip && elem.childNodes.length) {\n                    this.xmlInput(elem.childNodes[0]);\n                  } else {\n                    this.xmlInput(elem);\n                  }\n                }\n\n                if (this.rawInput !== Strophe.Connection.prototype.rawInput) {\n                  if (raw) {\n                    this.rawInput(raw);\n                  } else {\n                    this.rawInput(Strophe.serialize(elem));\n                  }\n                } // remove handlers scheduled for deletion\n\n\n                while (this.removeHandlers.length > 0) {\n                  const hand = this.removeHandlers.pop();\n                  const i = this.handlers.indexOf(hand);\n\n                  if (i >= 0) {\n                    this.handlers.splice(i, 1);\n                  }\n                } // add handlers scheduled for addition\n\n\n                while (this.addHandlers.length > 0) {\n                  this.handlers.push(this.addHandlers.pop());\n                } // handle graceful disconnect\n\n\n                if (this.disconnecting && this._proto._emptyQueue()) {\n                  this._doDisconnect();\n\n                  return;\n                }\n\n                const type = elem.getAttribute(\"type\");\n\n                if (type !== null && type === \"terminate\") {\n                  // Don't process stanzas that come in after disconnect\n                  if (this.disconnecting) {\n                    return;\n                  } // an error occurred\n\n\n                  let cond = elem.getAttribute(\"condition\");\n                  const conflict = elem.getElementsByTagName(\"conflict\");\n\n                  if (cond !== null) {\n                    if (cond === \"remote-stream-error\" && conflict.length > 0) {\n                      cond = \"conflict\";\n                    }\n\n                    this._changeConnectStatus(Strophe.Status.CONNFAIL, cond);\n                  } else {\n                    this._changeConnectStatus(Strophe.Status.CONNFAIL, Strophe.ErrorCondition.UNKOWN_REASON);\n                  }\n\n                  this._doDisconnect(cond);\n\n                  return;\n                } // send each incoming stanza through the handler chain\n\n\n                Strophe.forEachChild(elem, null, child => {\n                  const matches = [];\n                  this.handlers = this.handlers.reduce((handlers, handler) => {\n                    try {\n                      if (handler.isMatch(child) && (this.authenticated || !handler.user)) {\n                        if (handler.run(child)) {\n                          handlers.push(handler);\n                        }\n\n                        matches.push(handler);\n                      } else {\n                        handlers.push(handler);\n                      }\n                    } catch (e) {\n                      // if the handler throws an exception, we consider it as false\n                      Strophe.warn('Removing Strophe handlers due to uncaught exception: ' + e.message);\n                    }\n\n                    return handlers;\n                  }, []); // If no handler was fired for an incoming IQ with type=\"set\",\n                  // then we return an IQ error stanza with service-unavailable.\n\n                  if (!matches.length && this.iqFallbackHandler.isMatch(child)) {\n                    this.iqFallbackHandler.run(child);\n                  }\n                });\n              }\n              /** PrivateFunction: _connect_cb\n               *  _Private_ handler for initial connection request.\n               *\n               *  This handler is used to process the initial connection request\n               *  response from the BOSH server. It is used to set up authentication\n               *  handlers and start the authentication process.\n               *\n               *  SASL authentication will be attempted if available, otherwise\n               *  the code will fall back to legacy authentication.\n               *\n               *  Parameters:\n               *    (Strophe.Request) req - The current request.\n               *    (Function) _callback - low level (xmpp) connect callback function.\n               *      Useful for plugins with their own xmpp connect callback (when they\n               *      want to do something special).\n               */\n\n\n              _connect_cb(req, _callback, raw) {\n                Strophe.debug(\"_connect_cb was called\");\n                this.connected = true;\n                let bodyWrap;\n\n                try {\n                  bodyWrap = this._proto._reqToData(req);\n                } catch (e) {\n                  if (e.name !== Strophe.ErrorCondition.BAD_FORMAT) {\n                    throw e;\n                  }\n\n                  this._changeConnectStatus(Strophe.Status.CONNFAIL, Strophe.ErrorCondition.BAD_FORMAT);\n\n                  this._doDisconnect(Strophe.ErrorCondition.BAD_FORMAT);\n                }\n\n                if (!bodyWrap) {\n                  return;\n                }\n\n                if (this.xmlInput !== Strophe.Connection.prototype.xmlInput) {\n                  if (bodyWrap.nodeName === this._proto.strip && bodyWrap.childNodes.length) {\n                    this.xmlInput(bodyWrap.childNodes[0]);\n                  } else {\n                    this.xmlInput(bodyWrap);\n                  }\n                }\n\n                if (this.rawInput !== Strophe.Connection.prototype.rawInput) {\n                  if (raw) {\n                    this.rawInput(raw);\n                  } else {\n                    this.rawInput(Strophe.serialize(bodyWrap));\n                  }\n                }\n\n                const conncheck = this._proto._connect_cb(bodyWrap);\n\n                if (conncheck === Strophe.Status.CONNFAIL) {\n                  return;\n                } // Check for the stream:features tag\n\n\n                let hasFeatures;\n\n                if (bodyWrap.getElementsByTagNameNS) {\n                  hasFeatures = bodyWrap.getElementsByTagNameNS(Strophe.NS.STREAM, \"features\").length > 0;\n                } else {\n                  hasFeatures = bodyWrap.getElementsByTagName(\"stream:features\").length > 0 || bodyWrap.getElementsByTagName(\"features\").length > 0;\n                }\n\n                if (!hasFeatures) {\n                  this._proto._no_auth_received(_callback);\n\n                  return;\n                }\n\n                const matched = Array.from(bodyWrap.getElementsByTagName(\"mechanism\")).map(m => this.mechanisms[m.textContent]).filter(m => m);\n\n                if (matched.length === 0) {\n                  if (bodyWrap.getElementsByTagName(\"auth\").length === 0) {\n                    // There are no matching SASL mechanisms and also no legacy\n                    // auth available.\n                    this._proto._no_auth_received(_callback);\n\n                    return;\n                  }\n                }\n\n                if (this.do_authentication !== false) {\n                  this.authenticate(matched);\n                }\n              }\n              /** Function: sortMechanismsByPriority\n               *\n               *  Sorts an array of objects with prototype SASLMechanism according to\n               *  their priorities.\n               *\n               *  Parameters:\n               *    (Array) mechanisms - Array of SASL mechanisms.\n               *\n               */\n\n\n              sortMechanismsByPriority(mechanisms) {\n                // eslint-disable-line class-methods-use-this\n                // Sorting mechanisms according to priority.\n                for (let i = 0; i < mechanisms.length - 1; ++i) {\n                  let higher = i;\n\n                  for (let j = i + 1; j < mechanisms.length; ++j) {\n                    if (mechanisms[j].priority > mechanisms[higher].priority) {\n                      higher = j;\n                    }\n                  }\n\n                  if (higher !== i) {\n                    const swap = mechanisms[i];\n                    mechanisms[i] = mechanisms[higher];\n                    mechanisms[higher] = swap;\n                  }\n                }\n\n                return mechanisms;\n              }\n              /** Function: authenticate\n               * Set up authentication\n               *\n               *  Continues the initial connection request by setting up authentication\n               *  handlers and starting the authentication process.\n               *\n               *  SASL authentication will be attempted if available, otherwise\n               *  the code will fall back to legacy authentication.\n               *\n               *  Parameters:\n               *    (Array) matched - Array of SASL mechanisms supported.\n               *\n               */\n\n\n              authenticate(matched) {\n                if (!this._attemptSASLAuth(matched)) {\n                  this._attemptLegacyAuth();\n                }\n              }\n              /** PrivateFunction: _attemptSASLAuth\n               *\n               *  Iterate through an array of SASL mechanisms and attempt authentication\n               *  with the highest priority (enabled) mechanism.\n               *\n               *  Parameters:\n               *    (Array) mechanisms - Array of SASL mechanisms.\n               *\n               *  Returns:\n               *    (Boolean) mechanism_found - true or false, depending on whether a\n               *          valid SASL mechanism was found with which authentication could be\n               *          started.\n               */\n\n\n              _attemptSASLAuth(mechanisms) {\n                mechanisms = this.sortMechanismsByPriority(mechanisms || []);\n                let mechanism_found = false;\n\n                for (let i = 0; i < mechanisms.length; ++i) {\n                  if (!mechanisms[i].test(this)) {\n                    continue;\n                  }\n\n                  this._sasl_success_handler = this._addSysHandler(this._sasl_success_cb.bind(this), null, \"success\", null, null);\n                  this._sasl_failure_handler = this._addSysHandler(this._sasl_failure_cb.bind(this), null, \"failure\", null, null);\n                  this._sasl_challenge_handler = this._addSysHandler(this._sasl_challenge_cb.bind(this), null, \"challenge\", null, null);\n                  this._sasl_mechanism = mechanisms[i];\n\n                  this._sasl_mechanism.onStart(this);\n\n                  const request_auth_exchange = $build(\"auth\", {\n                    'xmlns': Strophe.NS.SASL,\n                    'mechanism': this._sasl_mechanism.mechname\n                  });\n\n                  if (this._sasl_mechanism.isClientFirst) {\n                    const response = this._sasl_mechanism.clientChallenge(this);\n\n                    request_auth_exchange.t(btoa(response));\n                  }\n\n                  this.send(request_auth_exchange.tree());\n                  mechanism_found = true;\n                  break;\n                }\n\n                return mechanism_found;\n              }\n              /** PrivateFunction: _sasl_challenge_cb\n               *  _Private_ handler for the SASL challenge\n               *\n               */\n\n\n              _sasl_challenge_cb(elem) {\n                const challenge = atob(Strophe.getText(elem));\n\n                const response = this._sasl_mechanism.onChallenge(this, challenge);\n\n                const stanza = $build('response', {\n                  'xmlns': Strophe.NS.SASL\n                });\n\n                if (response !== \"\") {\n                  stanza.t(btoa(response));\n                }\n\n                this.send(stanza.tree());\n                return true;\n              }\n              /** PrivateFunction: _attemptLegacyAuth\n               *\n               *  Attempt legacy (i.e. non-SASL) authentication.\n               */\n\n\n              _attemptLegacyAuth() {\n                if (Strophe.getNodeFromJid(this.jid) === null) {\n                  // we don't have a node, which is required for non-anonymous\n                  // client connections\n                  this._changeConnectStatus(Strophe.Status.CONNFAIL, Strophe.ErrorCondition.MISSING_JID_NODE);\n\n                  this.disconnect(Strophe.ErrorCondition.MISSING_JID_NODE);\n                } else {\n                  // Fall back to legacy authentication\n                  this._changeConnectStatus(Strophe.Status.AUTHENTICATING, null);\n\n                  this._addSysHandler(this._onLegacyAuthIQResult.bind(this), null, null, null, \"_auth_1\");\n\n                  this.send($iq({\n                    'type': \"get\",\n                    'to': this.domain,\n                    'id': \"_auth_1\"\n                  }).c(\"query\", {\n                    xmlns: Strophe.NS.AUTH\n                  }).c(\"username\", {}).t(Strophe.getNodeFromJid(this.jid)).tree());\n                }\n              }\n              /** PrivateFunction: _onLegacyAuthIQResult\n               *  _Private_ handler for legacy authentication.\n               *\n               *  This handler is called in response to the initial <iq type='get'/>\n               *  for legacy authentication.  It builds an authentication <iq/> and\n               *  sends it, creating a handler (calling back to _auth2_cb()) to\n               *  handle the result\n               *\n               *  Parameters:\n               *    (XMLElement) elem - The stanza that triggered the callback.\n               *\n               *  Returns:\n               *    false to remove the handler.\n               */\n\n\n              _onLegacyAuthIQResult(elem) {\n                // eslint-disable-line no-unused-vars\n                // build plaintext auth iq\n                const iq = $iq({\n                  type: \"set\",\n                  id: \"_auth_2\"\n                }).c('query', {\n                  xmlns: Strophe.NS.AUTH\n                }).c('username', {}).t(Strophe.getNodeFromJid(this.jid)).up().c('password').t(this.pass);\n\n                if (!Strophe.getResourceFromJid(this.jid)) {\n                  // since the user has not supplied a resource, we pick\n                  // a default one here.  unlike other auth methods, the server\n                  // cannot do this for us.\n                  this.jid = Strophe.getBareJidFromJid(this.jid) + '/strophe';\n                }\n\n                iq.up().c('resource', {}).t(Strophe.getResourceFromJid(this.jid));\n\n                this._addSysHandler(this._auth2_cb.bind(this), null, null, null, \"_auth_2\");\n\n                this.send(iq.tree());\n                return false;\n              }\n              /** PrivateFunction: _sasl_success_cb\n               *  _Private_ handler for succesful SASL authentication.\n               *\n               *  Parameters:\n               *    (XMLElement) elem - The matching stanza.\n               *\n               *  Returns:\n               *    false to remove the handler.\n               */\n\n\n              _sasl_success_cb(elem) {\n                if (this._sasl_data[\"server-signature\"]) {\n                  let serverSignature;\n                  const success = atob(Strophe.getText(elem));\n                  const attribMatch = /([a-z]+)=([^,]+)(,|$)/;\n                  const matches = success.match(attribMatch);\n\n                  if (matches[1] === \"v\") {\n                    serverSignature = matches[2];\n                  }\n\n                  if (serverSignature !== this._sasl_data[\"server-signature\"]) {\n                    // remove old handlers\n                    this.deleteHandler(this._sasl_failure_handler);\n                    this._sasl_failure_handler = null;\n\n                    if (this._sasl_challenge_handler) {\n                      this.deleteHandler(this._sasl_challenge_handler);\n                      this._sasl_challenge_handler = null;\n                    }\n\n                    this._sasl_data = {};\n                    return this._sasl_failure_cb(null);\n                  }\n                }\n\n                Strophe.info(\"SASL authentication succeeded.\");\n\n                if (this._sasl_mechanism) {\n                  this._sasl_mechanism.onSuccess();\n                } // remove old handlers\n\n\n                this.deleteHandler(this._sasl_failure_handler);\n                this._sasl_failure_handler = null;\n\n                if (this._sasl_challenge_handler) {\n                  this.deleteHandler(this._sasl_challenge_handler);\n                  this._sasl_challenge_handler = null;\n                }\n\n                const streamfeature_handlers = [];\n\n                const wrapper = (handlers, elem) => {\n                  while (handlers.length) {\n                    this.deleteHandler(handlers.pop());\n                  }\n\n                  this._onStreamFeaturesAfterSASL(elem);\n\n                  return false;\n                };\n\n                streamfeature_handlers.push(this._addSysHandler(elem => wrapper(streamfeature_handlers, elem), null, \"stream:features\", null, null));\n                streamfeature_handlers.push(this._addSysHandler(elem => wrapper(streamfeature_handlers, elem), Strophe.NS.STREAM, \"features\", null, null)); // we must send an xmpp:restart now\n\n                this._sendRestart();\n\n                return false;\n              }\n              /** PrivateFunction: _onStreamFeaturesAfterSASL\n               *  Parameters:\n               *    (XMLElement) elem - The matching stanza.\n               *\n               *  Returns:\n               *    false to remove the handler.\n               */\n\n\n              _onStreamFeaturesAfterSASL(elem) {\n                // save stream:features for future usage\n                this.features = elem;\n\n                for (let i = 0; i < elem.childNodes.length; i++) {\n                  const child = elem.childNodes[i];\n\n                  if (child.nodeName === 'bind') {\n                    this.do_bind = true;\n                  }\n\n                  if (child.nodeName === 'session') {\n                    this.do_session = true;\n                  }\n                }\n\n                if (!this.do_bind) {\n                  this._changeConnectStatus(Strophe.Status.AUTHFAIL, null);\n\n                  return false;\n                } else if (!this.options.explicitResourceBinding) {\n                  this.bind();\n                } else {\n                  this._changeConnectStatus(Strophe.Status.BINDREQUIRED, null);\n                }\n\n                return false;\n              }\n              /** Function: bind\n               *\n               *  Sends an IQ to the XMPP server to bind a JID resource for this session.\n               *\n               *  https://tools.ietf.org/html/rfc6120#section-7.5\n               *\n               *  If `explicitResourceBinding` was set to a truthy value in the options\n               *  passed to the Strophe.Connection constructor, then this function needs\n               *  to be called explicitly by the client author.\n               *\n               *  Otherwise it'll be called automatically as soon as the XMPP server\n               *  advertises the \"urn:ietf:params:xml:ns:xmpp-bind\" stream feature.\n               */\n\n\n              bind() {\n                if (!this.do_bind) {\n                  Strophe.log(Strophe.LogLevel.INFO, `Strophe.Connection.prototype.bind called but \"do_bind\" is false`);\n                  return;\n                }\n\n                this._addSysHandler(this._onResourceBindResultIQ.bind(this), null, null, null, \"_bind_auth_2\");\n\n                const resource = Strophe.getResourceFromJid(this.jid);\n\n                if (resource) {\n                  this.send($iq({\n                    type: \"set\",\n                    id: \"_bind_auth_2\"\n                  }).c('bind', {\n                    xmlns: Strophe.NS.BIND\n                  }).c('resource', {}).t(resource).tree());\n                } else {\n                  this.send($iq({\n                    type: \"set\",\n                    id: \"_bind_auth_2\"\n                  }).c('bind', {\n                    xmlns: Strophe.NS.BIND\n                  }).tree());\n                }\n              }\n              /** PrivateFunction: _onResourceBindIQ\n               *  _Private_ handler for binding result and session start.\n               *\n               *  Parameters:\n               *    (XMLElement) elem - The matching stanza.\n               *\n               *  Returns:\n               *    false to remove the handler.\n               */\n\n\n              _onResourceBindResultIQ(elem) {\n                if (elem.getAttribute(\"type\") === \"error\") {\n                  Strophe.warn(\"Resource binding failed.\");\n                  const conflict = elem.getElementsByTagName(\"conflict\");\n                  let condition;\n\n                  if (conflict.length > 0) {\n                    condition = Strophe.ErrorCondition.CONFLICT;\n                  }\n\n                  this._changeConnectStatus(Strophe.Status.AUTHFAIL, condition, elem);\n\n                  return false;\n                } // TODO - need to grab errors\n\n\n                const bind = elem.getElementsByTagName(\"bind\");\n\n                if (bind.length > 0) {\n                  const jidNode = bind[0].getElementsByTagName(\"jid\");\n\n                  if (jidNode.length > 0) {\n                    this.authenticated = true;\n                    this.jid = Strophe.getText(jidNode[0]);\n\n                    if (this.do_session) {\n                      this._establishSession();\n                    } else {\n                      this._changeConnectStatus(Strophe.Status.CONNECTED, null);\n                    }\n                  }\n                } else {\n                  Strophe.warn(\"Resource binding failed.\");\n\n                  this._changeConnectStatus(Strophe.Status.AUTHFAIL, null, elem);\n\n                  return false;\n                }\n              }\n              /** PrivateFunction: _establishSession\n               *  Send IQ request to establish a session with the XMPP server.\n               *\n               *  See https://xmpp.org/rfcs/rfc3921.html#session\n               *\n               *  Note: The protocol for session establishment has been determined as\n               *  unnecessary and removed in RFC-6121.\n               */\n\n\n              _establishSession() {\n                if (!this.do_session) {\n                  throw new Error(`Strophe.Connection.prototype._establishSession ` + `called but apparently ${Strophe.NS.SESSION} wasn't advertised by the server`);\n                }\n\n                this._addSysHandler(this._onSessionResultIQ.bind(this), null, null, null, \"_session_auth_2\");\n\n                this.send($iq({\n                  type: \"set\",\n                  id: \"_session_auth_2\"\n                }).c('session', {\n                  xmlns: Strophe.NS.SESSION\n                }).tree());\n              }\n              /** PrivateFunction: _onSessionResultIQ\n               *  _Private_ handler for the server's IQ response to a client's session\n               *  request.\n               *\n               *  This sets Connection.authenticated to true on success, which\n               *  starts the processing of user handlers.\n               *\n               *  See https://xmpp.org/rfcs/rfc3921.html#session\n               *\n               *  Note: The protocol for session establishment has been determined as\n               *  unnecessary and removed in RFC-6121.\n               *\n               *  Parameters:\n               *    (XMLElement) elem - The matching stanza.\n               *\n               *  Returns:\n               *    false to remove the handler.\n               */\n\n\n              _onSessionResultIQ(elem) {\n                if (elem.getAttribute(\"type\") === \"result\") {\n                  this.authenticated = true;\n\n                  this._changeConnectStatus(Strophe.Status.CONNECTED, null);\n                } else if (elem.getAttribute(\"type\") === \"error\") {\n                  this.authenticated = false;\n                  Strophe.warn(\"Session creation failed.\");\n\n                  this._changeConnectStatus(Strophe.Status.AUTHFAIL, null, elem);\n\n                  return false;\n                }\n\n                return false;\n              }\n              /** PrivateFunction: _sasl_failure_cb\n               *  _Private_ handler for SASL authentication failure.\n               *\n               *  Parameters:\n               *    (XMLElement) elem - The matching stanza.\n               *\n               *  Returns:\n               *    false to remove the handler.\n               */\n\n\n              _sasl_failure_cb(elem) {\n                // delete unneeded handlers\n                if (this._sasl_success_handler) {\n                  this.deleteHandler(this._sasl_success_handler);\n                  this._sasl_success_handler = null;\n                }\n\n                if (this._sasl_challenge_handler) {\n                  this.deleteHandler(this._sasl_challenge_handler);\n                  this._sasl_challenge_handler = null;\n                }\n\n                if (this._sasl_mechanism) this._sasl_mechanism.onFailure();\n\n                this._changeConnectStatus(Strophe.Status.AUTHFAIL, null, elem);\n\n                return false;\n              }\n              /** PrivateFunction: _auth2_cb\n               *  _Private_ handler to finish legacy authentication.\n               *\n               *  This handler is called when the result from the jabber:iq:auth\n               *  <iq/> stanza is returned.\n               *\n               *  Parameters:\n               *    (XMLElement) elem - The stanza that triggered the callback.\n               *\n               *  Returns:\n               *    false to remove the handler.\n               */\n\n\n              _auth2_cb(elem) {\n                if (elem.getAttribute(\"type\") === \"result\") {\n                  this.authenticated = true;\n\n                  this._changeConnectStatus(Strophe.Status.CONNECTED, null);\n                } else if (elem.getAttribute(\"type\") === \"error\") {\n                  this._changeConnectStatus(Strophe.Status.AUTHFAIL, null, elem);\n\n                  this.disconnect('authentication failed');\n                }\n\n                return false;\n              }\n              /** PrivateFunction: _addSysTimedHandler\n               *  _Private_ function to add a system level timed handler.\n               *\n               *  This function is used to add a Strophe.TimedHandler for the\n               *  library code.  System timed handlers are allowed to run before\n               *  authentication is complete.\n               *\n               *  Parameters:\n               *    (Integer) period - The period of the handler.\n               *    (Function) handler - The callback function.\n               */\n\n\n              _addSysTimedHandler(period, handler) {\n                const thand = new Strophe.TimedHandler(period, handler);\n                thand.user = false;\n                this.addTimeds.push(thand);\n                return thand;\n              }\n              /** PrivateFunction: _addSysHandler\n               *  _Private_ function to add a system level stanza handler.\n               *\n               *  This function is used to add a Strophe.Handler for the\n               *  library code.  System stanza handlers are allowed to run before\n               *  authentication is complete.\n               *\n               *  Parameters:\n               *    (Function) handler - The callback function.\n               *    (String) ns - The namespace to match.\n               *    (String) name - The stanza name to match.\n               *    (String) type - The stanza type attribute to match.\n               *    (String) id - The stanza id attribute to match.\n               */\n\n\n              _addSysHandler(handler, ns, name, type, id) {\n                const hand = new Strophe.Handler(handler, ns, name, type, id);\n                hand.user = false;\n                this.addHandlers.push(hand);\n                return hand;\n              }\n              /** PrivateFunction: _onDisconnectTimeout\n               *  _Private_ timeout handler for handling non-graceful disconnection.\n               *\n               *  If the graceful disconnect process does not complete within the\n               *  time allotted, this handler finishes the disconnect anyway.\n               *\n               *  Returns:\n               *    false to remove the handler.\n               */\n\n\n              _onDisconnectTimeout() {\n                Strophe.debug(\"_onDisconnectTimeout was called\");\n\n                this._changeConnectStatus(Strophe.Status.CONNTIMEOUT, null);\n\n                this._proto._onDisconnectTimeout(); // actually disconnect\n\n\n                this._doDisconnect();\n\n                return false;\n              }\n              /** PrivateFunction: _onIdle\n               *  _Private_ handler to process events during idle cycle.\n               *\n               *  This handler is called every 100ms to fire timed handlers that\n               *  are ready and keep poll requests going.\n               */\n\n\n              _onIdle() {\n                // add timed handlers scheduled for addition\n                // NOTE: we add before remove in the case a timed handler is\n                // added and then deleted before the next _onIdle() call.\n                while (this.addTimeds.length > 0) {\n                  this.timedHandlers.push(this.addTimeds.pop());\n                } // remove timed handlers that have been scheduled for deletion\n\n\n                while (this.removeTimeds.length > 0) {\n                  const thand = this.removeTimeds.pop();\n                  const i = this.timedHandlers.indexOf(thand);\n\n                  if (i >= 0) {\n                    this.timedHandlers.splice(i, 1);\n                  }\n                } // call ready timed handlers\n\n\n                const now = new Date().getTime();\n                const newList = [];\n\n                for (let i = 0; i < this.timedHandlers.length; i++) {\n                  const thand = this.timedHandlers[i];\n\n                  if (this.authenticated || !thand.user) {\n                    const since = thand.lastCalled + thand.period;\n\n                    if (since - now <= 0) {\n                      if (thand.run()) {\n                        newList.push(thand);\n                      }\n                    } else {\n                      newList.push(thand);\n                    }\n                  }\n                }\n\n                this.timedHandlers = newList;\n                clearTimeout(this._idleTimeout);\n\n                this._proto._onIdle(); // reactivate the timer only if connected\n\n\n                if (this.connected) {\n                  this._idleTimeout = setTimeout(() => this._onIdle(), 100);\n                }\n              }\n\n            };\n            Strophe.SASLMechanism = SASLMechanism;\n            /** Constants: SASL mechanisms\n             *  Available authentication mechanisms\n             *\n             *  Strophe.SASLAnonymous   - SASL ANONYMOUS authentication.\n             *  Strophe.SASLPlain       - SASL PLAIN authentication.\n             *  Strophe.SASLSHA1        - SASL SCRAM-SHA-1 authentication\n             *  Strophe.SASLOAuthBearer - SASL OAuth Bearer authentication\n             *  Strophe.SASLExternal    - SASL EXTERNAL authentication\n             *  Strophe.SASLXOAuth2     - SASL X-OAuth2 authentication\n             */\n\n            Strophe.SASLAnonymous = SASLAnonymous;\n            Strophe.SASLPlain = SASLPlain;\n            Strophe.SASLSHA1 = SASLSHA1;\n            Strophe.SASLOAuthBearer = SASLOAuthBearer;\n            Strophe.SASLExternal = SASLExternal;\n            Strophe.SASLXOAuth2 = SASLXOAuth2;\n            var core = {\n              'Strophe': Strophe,\n              '$build': $build,\n              '$iq': $iq,\n              '$msg': $msg,\n              '$pres': $pres,\n              'SHA1': SHA1,\n              'MD5': MD5,\n              'b64_hmac_sha1': SHA1.b64_hmac_sha1,\n              'b64_sha1': SHA1.b64_sha1,\n              'str_hmac_sha1': SHA1.str_hmac_sha1,\n              'str_sha1': SHA1.str_sha1\n            };\n\n            /*\n                This program is distributed under the terms of the MIT license.\n                Please see the LICENSE file for details.\n\n                Copyright 2006-2008, OGG, LLC\n            */\n            /** PrivateClass: Strophe.Request\n             *  _Private_ helper class that provides a cross implementation abstraction\n             *  for a BOSH related XMLHttpRequest.\n             *\n             *  The Strophe.Request class is used internally to encapsulate BOSH request\n             *  information.  It is not meant to be used from user's code.\n             */\n\n            Strophe.Request = class Request {\n              /** PrivateConstructor: Strophe.Request\n               *  Create and initialize a new Strophe.Request object.\n               *\n               *  Parameters:\n               *    (XMLElement) elem - The XML data to be sent in the request.\n               *    (Function) func - The function that will be called when the\n               *      XMLHttpRequest readyState changes.\n               *    (Integer) rid - The BOSH rid attribute associated with this request.\n               *    (Integer) sends - The number of times this same request has been sent.\n               */\n              constructor(elem, func, rid, sends) {\n                this.id = ++Strophe._requestId;\n                this.xmlData = elem;\n                this.data = Strophe.serialize(elem); // save original function in case we need to make a new request\n                // from this one.\n\n                this.origFunc = func;\n                this.func = func;\n                this.rid = rid;\n                this.date = NaN;\n                this.sends = sends || 0;\n                this.abort = false;\n                this.dead = null;\n\n                this.age = function () {\n                  if (!this.date) {\n                    return 0;\n                  }\n\n                  const now = new Date();\n                  return (now - this.date) / 1000;\n                };\n\n                this.timeDead = function () {\n                  if (!this.dead) {\n                    return 0;\n                  }\n\n                  const now = new Date();\n                  return (now - this.dead) / 1000;\n                };\n\n                this.xhr = this._newXHR();\n              }\n              /** PrivateFunction: getResponse\n               *  Get a response from the underlying XMLHttpRequest.\n               *\n               *  This function attempts to get a response from the request and checks\n               *  for errors.\n               *\n               *  Throws:\n               *    \"parsererror\" - A parser error occured.\n               *    \"bad-format\" - The entity has sent XML that cannot be processed.\n               *\n               *  Returns:\n               *    The DOM element tree of the response.\n               */\n\n\n              getResponse() {\n                let node = null;\n\n                if (this.xhr.responseXML && this.xhr.responseXML.documentElement) {\n                  node = this.xhr.responseXML.documentElement;\n\n                  if (node.tagName === \"parsererror\") {\n                    Strophe.error(\"invalid response received\");\n                    Strophe.error(\"responseText: \" + this.xhr.responseText);\n                    Strophe.error(\"responseXML: \" + Strophe.serialize(this.xhr.responseXML));\n                    throw new Error(\"parsererror\");\n                  }\n                } else if (this.xhr.responseText) {\n                  // In React Native, we may get responseText but no responseXML.  We can try to parse it manually.\n                  Strophe.debug(\"Got responseText but no responseXML; attempting to parse it with DOMParser...\");\n                  node = new DOMParser().parseFromString(this.xhr.responseText, 'application/xml').documentElement;\n\n                  if (!node) {\n                    throw new Error('Parsing produced null node');\n                  } else if (node.querySelector('parsererror')) {\n                    Strophe.error(\"invalid response received: \" + node.querySelector('parsererror').textContent);\n                    Strophe.error(\"responseText: \" + this.xhr.responseText);\n                    const error = new Error();\n                    error.name = Strophe.ErrorCondition.BAD_FORMAT;\n                    throw error;\n                  }\n                }\n\n                return node;\n              }\n              /** PrivateFunction: _newXHR\n               *  _Private_ helper function to create XMLHttpRequests.\n               *\n               *  This function creates XMLHttpRequests across all implementations.\n               *\n               *  Returns:\n               *    A new XMLHttpRequest.\n               */\n\n\n              _newXHR() {\n                let xhr = null;\n\n                if (window.XMLHttpRequest) {\n                  xhr = new XMLHttpRequest();\n\n                  if (xhr.overrideMimeType) {\n                    xhr.overrideMimeType(\"text/xml; charset=utf-8\");\n                  }\n                } else if (window.ActiveXObject) {\n                  xhr = new ActiveXObject(\"Microsoft.XMLHTTP\");\n                } // use Function.bind() to prepend ourselves as an argument\n\n\n                xhr.onreadystatechange = this.func.bind(null, this);\n                return xhr;\n              }\n\n            };\n            /** Class: Strophe.Bosh\n             *  _Private_ helper class that handles BOSH Connections\n             *\n             *  The Strophe.Bosh class is used internally by Strophe.Connection\n             *  to encapsulate BOSH sessions. It is not meant to be used from user's code.\n             */\n\n            /** File: bosh.js\n             *  A JavaScript library to enable BOSH in Strophejs.\n             *\n             *  this library uses Bidirectional-streams Over Synchronous HTTP (BOSH)\n             *  to emulate a persistent, stateful, two-way connection to an XMPP server.\n             *  More information on BOSH can be found in XEP 124.\n             */\n\n            /** PrivateConstructor: Strophe.Bosh\n             *  Create and initialize a Strophe.Bosh object.\n             *\n             *  Parameters:\n             *    (Strophe.Connection) connection - The Strophe.Connection that will use BOSH.\n             *\n             *  Returns:\n             *    A new Strophe.Bosh object.\n             */\n\n            Strophe.Bosh = class Bosh {\n              constructor(connection) {\n                this._conn = connection;\n                /* request id for body tags */\n\n                this.rid = Math.floor(Math.random() * 4294967295);\n                /* The current session ID. */\n\n                this.sid = null; // default BOSH values\n\n                this.hold = 1;\n                this.wait = 60;\n                this.window = 5;\n                this.errors = 0;\n                this.inactivity = null;\n                this.lastResponseHeaders = null;\n                this._requests = [];\n              }\n              /** PrivateFunction: _buildBody\n               *  _Private_ helper function to generate the <body/> wrapper for BOSH.\n               *\n               *  Returns:\n               *    A Strophe.Builder with a <body/> element.\n               */\n\n\n              _buildBody() {\n                const bodyWrap = $build('body', {\n                  'rid': this.rid++,\n                  'xmlns': Strophe.NS.HTTPBIND\n                });\n\n                if (this.sid !== null) {\n                  bodyWrap.attrs({\n                    'sid': this.sid\n                  });\n                }\n\n                if (this._conn.options.keepalive && this._conn._sessionCachingSupported()) {\n                  this._cacheSession();\n                }\n\n                return bodyWrap;\n              }\n              /** PrivateFunction: _reset\n               *  Reset the connection.\n               *\n               *  This function is called by the reset function of the Strophe Connection\n               */\n\n\n              _reset() {\n                this.rid = Math.floor(Math.random() * 4294967295);\n                this.sid = null;\n                this.errors = 0;\n\n                if (this._conn._sessionCachingSupported()) {\n                  window.sessionStorage.removeItem('strophe-bosh-session');\n                }\n\n                this._conn.nextValidRid(this.rid);\n              }\n              /** PrivateFunction: _connect\n               *  _Private_ function that initializes the BOSH connection.\n               *\n               *  Creates and sends the Request that initializes the BOSH connection.\n               */\n\n\n              _connect(wait, hold, route) {\n                this.wait = wait || this.wait;\n                this.hold = hold || this.hold;\n                this.errors = 0;\n\n                const body = this._buildBody().attrs({\n                  \"to\": this._conn.domain,\n                  \"xml:lang\": \"en\",\n                  \"wait\": this.wait,\n                  \"hold\": this.hold,\n                  \"content\": \"text/xml; charset=utf-8\",\n                  \"ver\": \"1.6\",\n                  \"xmpp:version\": \"1.0\",\n                  \"xmlns:xmpp\": Strophe.NS.BOSH\n                });\n\n                if (route) {\n                  body.attrs({\n                    'route': route\n                  });\n                }\n\n                const _connect_cb = this._conn._connect_cb;\n\n                this._requests.push(new Strophe.Request(body.tree(), this._onRequestStateChange.bind(this, _connect_cb.bind(this._conn)), body.tree().getAttribute(\"rid\")));\n\n                this._throttledRequestHandler();\n              }\n              /** PrivateFunction: _attach\n               *  Attach to an already created and authenticated BOSH session.\n               *\n               *  This function is provided to allow Strophe to attach to BOSH\n               *  sessions which have been created externally, perhaps by a Web\n               *  application.  This is often used to support auto-login type features\n               *  without putting user credentials into the page.\n               *\n               *  Parameters:\n               *    (String) jid - The full JID that is bound by the session.\n               *    (String) sid - The SID of the BOSH session.\n               *    (String) rid - The current RID of the BOSH session.  This RID\n               *      will be used by the next request.\n               *    (Function) callback The connect callback function.\n               *    (Integer) wait - The optional HTTPBIND wait value.  This is the\n               *      time the server will wait before returning an empty result for\n               *      a request.  The default setting of 60 seconds is recommended.\n               *      Other settings will require tweaks to the Strophe.TIMEOUT value.\n               *    (Integer) hold - The optional HTTPBIND hold value.  This is the\n               *      number of connections the server will hold at one time.  This\n               *      should almost always be set to 1 (the default).\n               *    (Integer) wind - The optional HTTBIND window value.  This is the\n               *      allowed range of request ids that are valid.  The default is 5.\n               */\n\n\n              _attach(jid, sid, rid, callback, wait, hold, wind) {\n                this._conn.jid = jid;\n                this.sid = sid;\n                this.rid = rid;\n                this._conn.connect_callback = callback;\n                this._conn.domain = Strophe.getDomainFromJid(this._conn.jid);\n                this._conn.authenticated = true;\n                this._conn.connected = true;\n                this.wait = wait || this.wait;\n                this.hold = hold || this.hold;\n                this.window = wind || this.window;\n\n                this._conn._changeConnectStatus(Strophe.Status.ATTACHED, null);\n              }\n              /** PrivateFunction: _restore\n               *  Attempt to restore a cached BOSH session\n               *\n               *  Parameters:\n               *    (String) jid - The full JID that is bound by the session.\n               *      This parameter is optional but recommended, specifically in cases\n               *      where prebinded BOSH sessions are used where it's important to know\n               *      that the right session is being restored.\n               *    (Function) callback The connect callback function.\n               *    (Integer) wait - The optional HTTPBIND wait value.  This is the\n               *      time the server will wait before returning an empty result for\n               *      a request.  The default setting of 60 seconds is recommended.\n               *      Other settings will require tweaks to the Strophe.TIMEOUT value.\n               *    (Integer) hold - The optional HTTPBIND hold value.  This is the\n               *      number of connections the server will hold at one time.  This\n               *      should almost always be set to 1 (the default).\n               *    (Integer) wind - The optional HTTBIND window value.  This is the\n               *      allowed range of request ids that are valid.  The default is 5.\n               */\n\n\n              _restore(jid, callback, wait, hold, wind) {\n                const session = JSON.parse(window.sessionStorage.getItem('strophe-bosh-session'));\n\n                if (typeof session !== \"undefined\" && session !== null && session.rid && session.sid && session.jid && (typeof jid === \"undefined\" || jid === null || Strophe.getBareJidFromJid(session.jid) === Strophe.getBareJidFromJid(jid) || // If authcid is null, then it's an anonymous login, so\n                // we compare only the domains:\n                Strophe.getNodeFromJid(jid) === null && Strophe.getDomainFromJid(session.jid) === jid)) {\n                  this._conn.restored = true;\n\n                  this._attach(session.jid, session.sid, session.rid, callback, wait, hold, wind);\n                } else {\n                  const error = new Error(\"_restore: no restoreable session.\");\n                  error.name = \"StropheSessionError\";\n                  throw error;\n                }\n              }\n              /** PrivateFunction: _cacheSession\n               *  _Private_ handler for the beforeunload event.\n               *\n               *  This handler is used to process the Bosh-part of the initial request.\n               *  Parameters:\n               *    (Strophe.Request) bodyWrap - The received stanza.\n               */\n\n\n              _cacheSession() {\n                if (this._conn.authenticated) {\n                  if (this._conn.jid && this.rid && this.sid) {\n                    window.sessionStorage.setItem('strophe-bosh-session', JSON.stringify({\n                      'jid': this._conn.jid,\n                      'rid': this.rid,\n                      'sid': this.sid\n                    }));\n                  }\n                } else {\n                  window.sessionStorage.removeItem('strophe-bosh-session');\n                }\n              }\n              /** PrivateFunction: _connect_cb\n               *  _Private_ handler for initial connection request.\n               *\n               *  This handler is used to process the Bosh-part of the initial request.\n               *  Parameters:\n               *    (Strophe.Request) bodyWrap - The received stanza.\n               */\n\n\n              _connect_cb(bodyWrap) {\n                const typ = bodyWrap.getAttribute(\"type\");\n\n                if (typ !== null && typ === \"terminate\") {\n                  // an error occurred\n                  let cond = bodyWrap.getAttribute(\"condition\");\n                  Strophe.error(\"BOSH-Connection failed: \" + cond);\n                  const conflict = bodyWrap.getElementsByTagName(\"conflict\");\n\n                  if (cond !== null) {\n                    if (cond === \"remote-stream-error\" && conflict.length > 0) {\n                      cond = \"conflict\";\n                    }\n\n                    this._conn._changeConnectStatus(Strophe.Status.CONNFAIL, cond);\n                  } else {\n                    this._conn._changeConnectStatus(Strophe.Status.CONNFAIL, \"unknown\");\n                  }\n\n                  this._conn._doDisconnect(cond);\n\n                  return Strophe.Status.CONNFAIL;\n                } // check to make sure we don't overwrite these if _connect_cb is\n                // called multiple times in the case of missing stream:features\n\n\n                if (!this.sid) {\n                  this.sid = bodyWrap.getAttribute(\"sid\");\n                }\n\n                const wind = bodyWrap.getAttribute('requests');\n\n                if (wind) {\n                  this.window = parseInt(wind, 10);\n                }\n\n                const hold = bodyWrap.getAttribute('hold');\n\n                if (hold) {\n                  this.hold = parseInt(hold, 10);\n                }\n\n                const wait = bodyWrap.getAttribute('wait');\n\n                if (wait) {\n                  this.wait = parseInt(wait, 10);\n                }\n\n                const inactivity = bodyWrap.getAttribute('inactivity');\n\n                if (inactivity) {\n                  this.inactivity = parseInt(inactivity, 10);\n                }\n              }\n              /** PrivateFunction: _disconnect\n               *  _Private_ part of Connection.disconnect for Bosh\n               *\n               *  Parameters:\n               *    (Request) pres - This stanza will be sent before disconnecting.\n               */\n\n\n              _disconnect(pres) {\n                this._sendTerminate(pres);\n              }\n              /** PrivateFunction: _doDisconnect\n               *  _Private_ function to disconnect.\n               *\n               *  Resets the SID and RID.\n               */\n\n\n              _doDisconnect() {\n                this.sid = null;\n                this.rid = Math.floor(Math.random() * 4294967295);\n\n                if (this._conn._sessionCachingSupported()) {\n                  window.sessionStorage.removeItem('strophe-bosh-session');\n                }\n\n                this._conn.nextValidRid(this.rid);\n              }\n              /** PrivateFunction: _emptyQueue\n               * _Private_ function to check if the Request queue is empty.\n               *\n               *  Returns:\n               *    True, if there are no Requests queued, False otherwise.\n               */\n\n\n              _emptyQueue() {\n                return this._requests.length === 0;\n              }\n              /** PrivateFunction: _callProtocolErrorHandlers\n               *  _Private_ function to call error handlers registered for HTTP errors.\n               *\n               *  Parameters:\n               *    (Strophe.Request) req - The request that is changing readyState.\n               */\n\n\n              _callProtocolErrorHandlers(req) {\n                const reqStatus = Bosh._getRequestStatus(req);\n\n                const err_callback = this._conn.protocolErrorHandlers.HTTP[reqStatus];\n\n                if (err_callback) {\n                  err_callback.call(this, reqStatus);\n                }\n              }\n              /** PrivateFunction: _hitError\n               *  _Private_ function to handle the error count.\n               *\n               *  Requests are resent automatically until their error count reaches\n               *  5.  Each time an error is encountered, this function is called to\n               *  increment the count and disconnect if the count is too high.\n               *\n               *  Parameters:\n               *    (Integer) reqStatus - The request status.\n               */\n\n\n              _hitError(reqStatus) {\n                this.errors++;\n                Strophe.warn(\"request errored, status: \" + reqStatus + \", number of errors: \" + this.errors);\n\n                if (this.errors > 4) {\n                  this._conn._onDisconnectTimeout();\n                }\n              }\n              /** PrivateFunction: _no_auth_received\n               *\n               * Called on stream start/restart when no stream:features\n               * has been received and sends a blank poll request.\n               */\n\n\n              _no_auth_received(callback) {\n                Strophe.warn(\"Server did not yet offer a supported authentication \" + \"mechanism. Sending a blank poll request.\");\n\n                if (callback) {\n                  callback = callback.bind(this._conn);\n                } else {\n                  callback = this._conn._connect_cb.bind(this._conn);\n                }\n\n                const body = this._buildBody();\n\n                this._requests.push(new Strophe.Request(body.tree(), this._onRequestStateChange.bind(this, callback), body.tree().getAttribute(\"rid\")));\n\n                this._throttledRequestHandler();\n              }\n              /** PrivateFunction: _onDisconnectTimeout\n               *  _Private_ timeout handler for handling non-graceful disconnection.\n               *\n               *  Cancels all remaining Requests and clears the queue.\n               */\n\n\n              _onDisconnectTimeout() {\n                this._abortAllRequests();\n              }\n              /** PrivateFunction: _abortAllRequests\n               *  _Private_ helper function that makes sure all pending requests are aborted.\n               */\n\n\n              _abortAllRequests() {\n                while (this._requests.length > 0) {\n                  const req = this._requests.pop();\n\n                  req.abort = true;\n                  req.xhr.abort();\n\n                  req.xhr.onreadystatechange = function () {};\n                }\n              }\n              /** PrivateFunction: _onIdle\n               *  _Private_ handler called by Strophe.Connection._onIdle\n               *\n               *  Sends all queued Requests or polls with empty Request if there are none.\n               */\n\n\n              _onIdle() {\n                const data = this._conn._data; // if no requests are in progress, poll\n\n                if (this._conn.authenticated && this._requests.length === 0 && data.length === 0 && !this._conn.disconnecting) {\n                  Strophe.debug(\"no requests during idle cycle, sending blank request\");\n                  data.push(null);\n                }\n\n                if (this._conn.paused) {\n                  return;\n                }\n\n                if (this._requests.length < 2 && data.length > 0) {\n                  const body = this._buildBody();\n\n                  for (let i = 0; i < data.length; i++) {\n                    if (data[i] !== null) {\n                      if (data[i] === \"restart\") {\n                        body.attrs({\n                          \"to\": this._conn.domain,\n                          \"xml:lang\": \"en\",\n                          \"xmpp:restart\": \"true\",\n                          \"xmlns:xmpp\": Strophe.NS.BOSH\n                        });\n                      } else {\n                        body.cnode(data[i]).up();\n                      }\n                    }\n                  }\n\n                  delete this._conn._data;\n                  this._conn._data = [];\n\n                  this._requests.push(new Strophe.Request(body.tree(), this._onRequestStateChange.bind(this, this._conn._dataRecv.bind(this._conn)), body.tree().getAttribute(\"rid\")));\n\n                  this._throttledRequestHandler();\n                }\n\n                if (this._requests.length > 0) {\n                  const time_elapsed = this._requests[0].age();\n\n                  if (this._requests[0].dead !== null) {\n                    if (this._requests[0].timeDead() > Math.floor(Strophe.SECONDARY_TIMEOUT * this.wait)) {\n                      this._throttledRequestHandler();\n                    }\n                  }\n\n                  if (time_elapsed > Math.floor(Strophe.TIMEOUT * this.wait)) {\n                    Strophe.warn(\"Request \" + this._requests[0].id + \" timed out, over \" + Math.floor(Strophe.TIMEOUT * this.wait) + \" seconds since last activity\");\n\n                    this._throttledRequestHandler();\n                  }\n                }\n              }\n              /** PrivateFunction: _getRequestStatus\n               *\n               *  Returns the HTTP status code from a Strophe.Request\n               *\n               *  Parameters:\n               *    (Strophe.Request) req - The Strophe.Request instance.\n               *    (Integer) def - The default value that should be returned if no\n               *          status value was found.\n               */\n\n\n              static _getRequestStatus(req, def) {\n                let reqStatus;\n\n                if (req.xhr.readyState === 4) {\n                  try {\n                    reqStatus = req.xhr.status;\n                  } catch (e) {\n                    // ignore errors from undefined status attribute. Works\n                    // around a browser bug\n                    Strophe.error(\"Caught an error while retrieving a request's status, \" + \"reqStatus: \" + reqStatus);\n                  }\n                }\n\n                if (typeof reqStatus === \"undefined\") {\n                  reqStatus = typeof def === 'number' ? def : 0;\n                }\n\n                return reqStatus;\n              }\n              /** PrivateFunction: _onRequestStateChange\n               *  _Private_ handler for Strophe.Request state changes.\n               *\n               *  This function is called when the XMLHttpRequest readyState changes.\n               *  It contains a lot of error handling logic for the many ways that\n               *  requests can fail, and calls the request callback when requests\n               *  succeed.\n               *\n               *  Parameters:\n               *    (Function) func - The handler for the request.\n               *    (Strophe.Request) req - The request that is changing readyState.\n               */\n\n\n              _onRequestStateChange(func, req) {\n                Strophe.debug(\"request id \" + req.id + \".\" + req.sends + \" state changed to \" + req.xhr.readyState);\n\n                if (req.abort) {\n                  req.abort = false;\n                  return;\n                }\n\n                if (req.xhr.readyState !== 4) {\n                  // The request is not yet complete\n                  return;\n                }\n\n                const reqStatus = Bosh._getRequestStatus(req);\n\n                this.lastResponseHeaders = req.xhr.getAllResponseHeaders();\n\n                if (this._conn.disconnecting && reqStatus >= 400) {\n                  this._hitError(reqStatus);\n\n                  this._callProtocolErrorHandlers(req);\n\n                  return;\n                }\n\n                const reqIs0 = this._requests[0] === req;\n                const reqIs1 = this._requests[1] === req;\n                const valid_request = reqStatus > 0 && reqStatus < 500;\n                const too_many_retries = req.sends > this._conn.maxRetries;\n\n                if (valid_request || too_many_retries) {\n                  // remove from internal queue\n                  this._removeRequest(req);\n\n                  Strophe.debug(\"request id \" + req.id + \" should now be removed\");\n                }\n\n                if (reqStatus === 200) {\n                  // request succeeded\n                  // if request 1 finished, or request 0 finished and request\n                  // 1 is over Strophe.SECONDARY_TIMEOUT seconds old, we need to\n                  // restart the other - both will be in the first spot, as the\n                  // completed request has been removed from the queue already\n                  if (reqIs1 || reqIs0 && this._requests.length > 0 && this._requests[0].age() > Math.floor(Strophe.SECONDARY_TIMEOUT * this.wait)) {\n                    this._restartRequest(0);\n                  }\n\n                  this._conn.nextValidRid(Number(req.rid) + 1);\n\n                  Strophe.debug(\"request id \" + req.id + \".\" + req.sends + \" got 200\");\n                  func(req); // call handler\n\n                  this.errors = 0;\n                } else if (reqStatus === 0 || reqStatus >= 400 && reqStatus < 600 || reqStatus >= 12000) {\n                  // request failed\n                  Strophe.error(\"request id \" + req.id + \".\" + req.sends + \" error \" + reqStatus + \" happened\");\n\n                  this._hitError(reqStatus);\n\n                  this._callProtocolErrorHandlers(req);\n\n                  if (reqStatus >= 400 && reqStatus < 500) {\n                    this._conn._changeConnectStatus(Strophe.Status.DISCONNECTING, null);\n\n                    this._conn._doDisconnect();\n                  }\n                } else {\n                  Strophe.error(\"request id \" + req.id + \".\" + req.sends + \" error \" + reqStatus + \" happened\");\n                }\n\n                if (!valid_request && !too_many_retries) {\n                  this._throttledRequestHandler();\n                } else if (too_many_retries && !this._conn.connected) {\n                  this._conn._changeConnectStatus(Strophe.Status.CONNFAIL, \"giving-up\");\n                }\n              }\n              /** PrivateFunction: _processRequest\n               *  _Private_ function to process a request in the queue.\n               *\n               *  This function takes requests off the queue and sends them and\n               *  restarts dead requests.\n               *\n               *  Parameters:\n               *    (Integer) i - The index of the request in the queue.\n               */\n\n\n              _processRequest(i) {\n                let req = this._requests[i];\n\n                const reqStatus = Bosh._getRequestStatus(req, -1); // make sure we limit the number of retries\n\n\n                if (req.sends > this._conn.maxRetries) {\n                  this._conn._onDisconnectTimeout();\n\n                  return;\n                }\n\n                const time_elapsed = req.age();\n                const primary_timeout = !isNaN(time_elapsed) && time_elapsed > Math.floor(Strophe.TIMEOUT * this.wait);\n                const secondary_timeout = req.dead !== null && req.timeDead() > Math.floor(Strophe.SECONDARY_TIMEOUT * this.wait);\n                const server_error = req.xhr.readyState === 4 && (reqStatus < 1 || reqStatus >= 500);\n\n                if (primary_timeout || secondary_timeout || server_error) {\n                  if (secondary_timeout) {\n                    Strophe.error(`Request ${this._requests[i].id} timed out (secondary), restarting`);\n                  }\n\n                  req.abort = true;\n                  req.xhr.abort(); // setting to null fails on IE6, so set to empty function\n\n                  req.xhr.onreadystatechange = function () {};\n\n                  this._requests[i] = new Strophe.Request(req.xmlData, req.origFunc, req.rid, req.sends);\n                  req = this._requests[i];\n                }\n\n                if (req.xhr.readyState === 0) {\n                  Strophe.debug(\"request id \" + req.id + \".\" + req.sends + \" posting\");\n\n                  try {\n                    const content_type = this._conn.options.contentType || \"text/xml; charset=utf-8\";\n                    req.xhr.open(\"POST\", this._conn.service, this._conn.options.sync ? false : true);\n\n                    if (typeof req.xhr.setRequestHeader !== 'undefined') {\n                      // IE9 doesn't have setRequestHeader\n                      req.xhr.setRequestHeader(\"Content-Type\", content_type);\n                    }\n\n                    if (this._conn.options.withCredentials) {\n                      req.xhr.withCredentials = true;\n                    }\n                  } catch (e2) {\n                    Strophe.error(\"XHR open failed: \" + e2.toString());\n\n                    if (!this._conn.connected) {\n                      this._conn._changeConnectStatus(Strophe.Status.CONNFAIL, \"bad-service\");\n                    }\n\n                    this._conn.disconnect();\n\n                    return;\n                  } // Fires the XHR request -- may be invoked immediately\n                  // or on a gradually expanding retry window for reconnects\n\n\n                  const sendFunc = () => {\n                    req.date = new Date();\n\n                    if (this._conn.options.customHeaders) {\n                      const headers = this._conn.options.customHeaders;\n\n                      for (const header in headers) {\n                        if (Object.prototype.hasOwnProperty.call(headers, header)) {\n                          req.xhr.setRequestHeader(header, headers[header]);\n                        }\n                      }\n                    }\n\n                    req.xhr.send(req.data);\n                  }; // Implement progressive backoff for reconnects --\n                  // First retry (send === 1) should also be instantaneous\n\n\n                  if (req.sends > 1) {\n                    // Using a cube of the retry number creates a nicely\n                    // expanding retry window\n                    const backoff = Math.min(Math.floor(Strophe.TIMEOUT * this.wait), Math.pow(req.sends, 3)) * 1000;\n                    setTimeout(function () {\n                      // XXX: setTimeout should be called only with function expressions (23974bc1)\n                      sendFunc();\n                    }, backoff);\n                  } else {\n                    sendFunc();\n                  }\n\n                  req.sends++;\n\n                  if (this._conn.xmlOutput !== Strophe.Connection.prototype.xmlOutput) {\n                    if (req.xmlData.nodeName === this.strip && req.xmlData.childNodes.length) {\n                      this._conn.xmlOutput(req.xmlData.childNodes[0]);\n                    } else {\n                      this._conn.xmlOutput(req.xmlData);\n                    }\n                  }\n\n                  if (this._conn.rawOutput !== Strophe.Connection.prototype.rawOutput) {\n                    this._conn.rawOutput(req.data);\n                  }\n                } else {\n                  Strophe.debug(\"_processRequest: \" + (i === 0 ? \"first\" : \"second\") + \" request has readyState of \" + req.xhr.readyState);\n                }\n              }\n              /** PrivateFunction: _removeRequest\n               *  _Private_ function to remove a request from the queue.\n               *\n               *  Parameters:\n               *    (Strophe.Request) req - The request to remove.\n               */\n\n\n              _removeRequest(req) {\n                Strophe.debug(\"removing request\");\n\n                for (let i = this._requests.length - 1; i >= 0; i--) {\n                  if (req === this._requests[i]) {\n                    this._requests.splice(i, 1);\n                  }\n                } // IE6 fails on setting to null, so set to empty function\n\n\n                req.xhr.onreadystatechange = function () {};\n\n                this._throttledRequestHandler();\n              }\n              /** PrivateFunction: _restartRequest\n               *  _Private_ function to restart a request that is presumed dead.\n               *\n               *  Parameters:\n               *    (Integer) i - The index of the request in the queue.\n               */\n\n\n              _restartRequest(i) {\n                const req = this._requests[i];\n\n                if (req.dead === null) {\n                  req.dead = new Date();\n                }\n\n                this._processRequest(i);\n              }\n              /** PrivateFunction: _reqToData\n               * _Private_ function to get a stanza out of a request.\n               *\n               * Tries to extract a stanza out of a Request Object.\n               * When this fails the current connection will be disconnected.\n               *\n               *  Parameters:\n               *    (Object) req - The Request.\n               *\n               *  Returns:\n               *    The stanza that was passed.\n               */\n\n\n              _reqToData(req) {\n                try {\n                  return req.getResponse();\n                } catch (e) {\n                  if (e.message !== \"parsererror\") {\n                    throw e;\n                  }\n\n                  this._conn.disconnect(\"strophe-parsererror\");\n                }\n              }\n              /** PrivateFunction: _sendTerminate\n               *  _Private_ function to send initial disconnect sequence.\n               *\n               *  This is the first step in a graceful disconnect.  It sends\n               *  the BOSH server a terminate body and includes an unavailable\n               *  presence if authentication has completed.\n               */\n\n\n              _sendTerminate(pres) {\n                Strophe.debug(\"_sendTerminate was called\");\n\n                const body = this._buildBody().attrs({\n                  type: \"terminate\"\n                });\n\n                if (pres) {\n                  body.cnode(pres.tree());\n                }\n\n                const req = new Strophe.Request(body.tree(), this._onRequestStateChange.bind(this, this._conn._dataRecv.bind(this._conn)), body.tree().getAttribute(\"rid\"));\n\n                this._requests.push(req);\n\n                this._throttledRequestHandler();\n              }\n              /** PrivateFunction: _send\n               *  _Private_ part of the Connection.send function for BOSH\n               *\n               * Just triggers the RequestHandler to send the messages that are in the queue\n               */\n\n\n              _send() {\n                clearTimeout(this._conn._idleTimeout);\n\n                this._throttledRequestHandler();\n\n                this._conn._idleTimeout = setTimeout(() => this._conn._onIdle(), 100);\n              }\n              /** PrivateFunction: _sendRestart\n               *\n               *  Send an xmpp:restart stanza.\n               */\n\n\n              _sendRestart() {\n                this._throttledRequestHandler();\n\n                clearTimeout(this._conn._idleTimeout);\n              }\n              /** PrivateFunction: _throttledRequestHandler\n               *  _Private_ function to throttle requests to the connection window.\n               *\n               *  This function makes sure we don't send requests so fast that the\n               *  request ids overflow the connection window in the case that one\n               *  request died.\n               */\n\n\n              _throttledRequestHandler() {\n                if (!this._requests) {\n                  Strophe.debug(\"_throttledRequestHandler called with \" + \"undefined requests\");\n                } else {\n                  Strophe.debug(\"_throttledRequestHandler called with \" + this._requests.length + \" requests\");\n                }\n\n                if (!this._requests || this._requests.length === 0) {\n                  return;\n                }\n\n                if (this._requests.length > 0) {\n                  this._processRequest(0);\n                }\n\n                if (this._requests.length > 1 && Math.abs(this._requests[0].rid - this._requests[1].rid) < this.window) {\n                  this._processRequest(1);\n                }\n              }\n\n            };\n            /** Variable: strip\n             *\n             *  BOSH-Connections will have all stanzas wrapped in a <body> tag when\n             *  passed to <Strophe.Connection.xmlInput> or <Strophe.Connection.xmlOutput>.\n             *  To strip this tag, User code can set <Strophe.Bosh.strip> to \"body\":\n             *\n             *  > Strophe.Bosh.prototype.strip = \"body\";\n             *\n             *  This will enable stripping of the body tag in both\n             *  <Strophe.Connection.xmlInput> and <Strophe.Connection.xmlOutput>.\n             */\n\n            Strophe.Bosh.prototype.strip = null;\n\n            /*\n                This program is distributed under the terms of the MIT license.\n                Please see the LICENSE file for details.\n\n                Copyright 2006-2008, OGG, LLC\n            */\n            /** Class: Strophe.WebSocket\n             *  _Private_ helper class that handles WebSocket Connections\n             *\n             *  The Strophe.WebSocket class is used internally by Strophe.Connection\n             *  to encapsulate WebSocket sessions. It is not meant to be used from user's code.\n             */\n\n            /** File: websocket.js\n             *  A JavaScript library to enable XMPP over Websocket in Strophejs.\n             *\n             *  This file implements XMPP over WebSockets for Strophejs.\n             *  If a Connection is established with a Websocket url (ws://...)\n             *  Strophe will use WebSockets.\n             *  For more information on XMPP-over-WebSocket see RFC 7395:\n             *  http://tools.ietf.org/html/rfc7395\n             *\n             *  WebSocket support implemented by Andreas Guth (andreas.guth@rwth-aachen.de)\n             */\n\n            Strophe.Websocket = class Websocket {\n              /** PrivateConstructor: Strophe.Websocket\n               *  Create and initialize a Strophe.WebSocket object.\n               *  Currently only sets the connection Object.\n               *\n               *  Parameters:\n               *    (Strophe.Connection) connection - The Strophe.Connection that will use WebSockets.\n               *\n               *  Returns:\n               *    A new Strophe.WebSocket object.\n               */\n              constructor(connection) {\n                this._conn = connection;\n                this.strip = \"wrapper\";\n                const service = connection.service;\n\n                if (service.indexOf(\"ws:\") !== 0 && service.indexOf(\"wss:\") !== 0) {\n                  // If the service is not an absolute URL, assume it is a path and put the absolute\n                  // URL together from options, current URL and the path.\n                  let new_service = \"\";\n\n                  if (connection.options.protocol === \"ws\" && window.location.protocol !== \"https:\") {\n                    new_service += \"ws\";\n                  } else {\n                    new_service += \"wss\";\n                  }\n\n                  new_service += \"://\" + window.location.host;\n\n                  if (service.indexOf(\"/\") !== 0) {\n                    new_service += window.location.pathname + service;\n                  } else {\n                    new_service += service;\n                  }\n\n                  connection.service = new_service;\n                }\n              }\n              /** PrivateFunction: _buildStream\n               *  _Private_ helper function to generate the <stream> start tag for WebSockets\n               *\n               *  Returns:\n               *    A Strophe.Builder with a <stream> element.\n               */\n\n\n              _buildStream() {\n                return $build(\"open\", {\n                  \"xmlns\": Strophe.NS.FRAMING,\n                  \"to\": this._conn.domain,\n                  \"version\": '1.0'\n                });\n              }\n              /** PrivateFunction: _checkStreamError\n               * _Private_ checks a message for stream:error\n               *\n               *  Parameters:\n               *    (Strophe.Request) bodyWrap - The received stanza.\n               *    connectstatus - The ConnectStatus that will be set on error.\n               *  Returns:\n               *     true if there was a streamerror, false otherwise.\n               */\n\n\n              _checkStreamError(bodyWrap, connectstatus) {\n                let errors;\n\n                if (bodyWrap.getElementsByTagNameNS) {\n                  errors = bodyWrap.getElementsByTagNameNS(Strophe.NS.STREAM, \"error\");\n                } else {\n                  errors = bodyWrap.getElementsByTagName(\"stream:error\");\n                }\n\n                if (errors.length === 0) {\n                  return false;\n                }\n\n                const error = errors[0];\n                let condition = \"\";\n                let text = \"\";\n                const ns = \"urn:ietf:params:xml:ns:xmpp-streams\";\n\n                for (let i = 0; i < error.childNodes.length; i++) {\n                  const e = error.childNodes[i];\n\n                  if (e.getAttribute(\"xmlns\") !== ns) {\n                    break;\n                  }\n\n                  if (e.nodeName === \"text\") {\n                    text = e.textContent;\n                  } else {\n                    condition = e.nodeName;\n                  }\n                }\n\n                let errorString = \"WebSocket stream error: \";\n\n                if (condition) {\n                  errorString += condition;\n                } else {\n                  errorString += \"unknown\";\n                }\n\n                if (text) {\n                  errorString += \" - \" + text;\n                }\n\n                Strophe.error(errorString); // close the connection on stream_error\n\n                this._conn._changeConnectStatus(connectstatus, condition);\n\n                this._conn._doDisconnect();\n\n                return true;\n              }\n              /** PrivateFunction: _reset\n               *  Reset the connection.\n               *\n               *  This function is called by the reset function of the Strophe Connection.\n               *  Is not needed by WebSockets.\n               */\n\n\n              _reset() {\n                // eslint-disable-line class-methods-use-this\n                return;\n              }\n              /** PrivateFunction: _connect\n               *  _Private_ function called by Strophe.Connection.connect\n               *\n               *  Creates a WebSocket for a connection and assigns Callbacks to it.\n               *  Does nothing if there already is a WebSocket.\n               */\n\n\n              _connect() {\n                // Ensure that there is no open WebSocket from a previous Connection.\n                this._closeSocket();\n\n                this.socket = new WebSocket(this._conn.service, \"xmpp\");\n\n                this.socket.onopen = () => this._onOpen();\n\n                this.socket.onerror = e => this._onError(e);\n\n                this.socket.onclose = e => this._onClose(e); // Gets replaced with this._onMessage once _onInitialMessage is called\n\n\n                this.socket.onmessage = message => this._onInitialMessage(message);\n              }\n              /** PrivateFunction: _connect_cb\n               *  _Private_ function called by Strophe.Connection._connect_cb\n               *\n               * checks for stream:error\n               *\n               *  Parameters:\n               *    (Strophe.Request) bodyWrap - The received stanza.\n               */\n\n\n              _connect_cb(bodyWrap) {\n                const error = this._checkStreamError(bodyWrap, Strophe.Status.CONNFAIL);\n\n                if (error) {\n                  return Strophe.Status.CONNFAIL;\n                }\n              }\n              /** PrivateFunction: _handleStreamStart\n               * _Private_ function that checks the opening <open /> tag for errors.\n               *\n               * Disconnects if there is an error and returns false, true otherwise.\n               *\n               *  Parameters:\n               *    (Node) message - Stanza containing the <open /> tag.\n               */\n\n\n              _handleStreamStart(message) {\n                let error = false; // Check for errors in the <open /> tag\n\n                const ns = message.getAttribute(\"xmlns\");\n\n                if (typeof ns !== \"string\") {\n                  error = \"Missing xmlns in <open />\";\n                } else if (ns !== Strophe.NS.FRAMING) {\n                  error = \"Wrong xmlns in <open />: \" + ns;\n                }\n\n                const ver = message.getAttribute(\"version\");\n\n                if (typeof ver !== \"string\") {\n                  error = \"Missing version in <open />\";\n                } else if (ver !== \"1.0\") {\n                  error = \"Wrong version in <open />: \" + ver;\n                }\n\n                if (error) {\n                  this._conn._changeConnectStatus(Strophe.Status.CONNFAIL, error);\n\n                  this._conn._doDisconnect();\n\n                  return false;\n                }\n\n                return true;\n              }\n              /** PrivateFunction: _onInitialMessage\n               * _Private_ function that handles the first connection messages.\n               *\n               * On receiving an opening stream tag this callback replaces itself with the real\n               * message handler. On receiving a stream error the connection is terminated.\n               */\n\n\n              _onInitialMessage(message) {\n                if (message.data.indexOf(\"<open \") === 0 || message.data.indexOf(\"<?xml\") === 0) {\n                  // Strip the XML Declaration, if there is one\n                  const data = message.data.replace(/^(<\\?.*?\\?>\\s*)*/, \"\");\n                  if (data === '') return;\n                  const streamStart = new DOMParser().parseFromString(data, \"text/xml\").documentElement;\n\n                  this._conn.xmlInput(streamStart);\n\n                  this._conn.rawInput(message.data); //_handleStreamSteart will check for XML errors and disconnect on error\n\n\n                  if (this._handleStreamStart(streamStart)) {\n                    //_connect_cb will check for stream:error and disconnect on error\n                    this._connect_cb(streamStart);\n                  }\n                } else if (message.data.indexOf(\"<close \") === 0) {\n                  // <close xmlns=\"urn:ietf:params:xml:ns:xmpp-framing />\n                  // Parse the raw string to an XML element\n                  const parsedMessage = new DOMParser().parseFromString(message.data, \"text/xml\").documentElement; // Report this input to the raw and xml handlers\n\n                  this._conn.xmlInput(parsedMessage);\n\n                  this._conn.rawInput(message.data);\n\n                  const see_uri = parsedMessage.getAttribute(\"see-other-uri\");\n\n                  if (see_uri) {\n                    const service = this._conn.service; // Valid scenarios: WSS->WSS, WS->ANY\n\n                    const isSecureRedirect = service.indexOf(\"wss:\") >= 0 && see_uri.indexOf(\"wss:\") >= 0 || service.indexOf(\"ws:\") >= 0;\n\n                    if (isSecureRedirect) {\n                      this._conn._changeConnectStatus(Strophe.Status.REDIRECT, \"Received see-other-uri, resetting connection\");\n\n                      this._conn.reset();\n\n                      this._conn.service = see_uri;\n\n                      this._connect();\n                    }\n                  } else {\n                    this._conn._changeConnectStatus(Strophe.Status.CONNFAIL, \"Received closing stream\");\n\n                    this._conn._doDisconnect();\n                  }\n                } else {\n                  this._replaceMessageHandler();\n\n                  const string = this._streamWrap(message.data);\n\n                  const elem = new DOMParser().parseFromString(string, \"text/xml\").documentElement;\n\n                  this._conn._connect_cb(elem, null, message.data);\n                }\n              }\n              /** PrivateFunction: _replaceMessageHandler\n               *\n               * Called by _onInitialMessage in order to replace itself with the general message handler.\n               * This method is overridden by Strophe.WorkerWebsocket, which manages a\n               * websocket connection via a service worker and doesn't have direct access\n               * to the socket.\n               */\n\n\n              _replaceMessageHandler() {\n                this.socket.onmessage = m => this._onMessage(m);\n              }\n              /** PrivateFunction: _disconnect\n               *  _Private_ function called by Strophe.Connection.disconnect\n               *\n               *  Disconnects and sends a last stanza if one is given\n               *\n               *  Parameters:\n               *    (Request) pres - This stanza will be sent before disconnecting.\n               */\n\n\n              _disconnect(pres) {\n                if (this.socket && this.socket.readyState !== WebSocket.CLOSED) {\n                  if (pres) {\n                    this._conn.send(pres);\n                  }\n\n                  const close = $build(\"close\", {\n                    \"xmlns\": Strophe.NS.FRAMING\n                  });\n\n                  this._conn.xmlOutput(close.tree());\n\n                  const closeString = Strophe.serialize(close);\n\n                  this._conn.rawOutput(closeString);\n\n                  try {\n                    this.socket.send(closeString);\n                  } catch (e) {\n                    Strophe.warn(\"Couldn't send <close /> tag.\");\n                  }\n                }\n\n                setTimeout(() => this._conn._doDisconnect(), 0);\n              }\n              /** PrivateFunction: _doDisconnect\n               *  _Private_ function to disconnect.\n               *\n               *  Just closes the Socket for WebSockets\n               */\n\n\n              _doDisconnect() {\n                Strophe.debug(\"WebSockets _doDisconnect was called\");\n\n                this._closeSocket();\n              }\n              /** PrivateFunction _streamWrap\n               *  _Private_ helper function to wrap a stanza in a <stream> tag.\n               *  This is used so Strophe can process stanzas from WebSockets like BOSH\n               */\n\n\n              _streamWrap(stanza) {\n                // eslint-disable-line class-methods-use-this\n                return \"<wrapper>\" + stanza + '</wrapper>';\n              }\n              /** PrivateFunction: _closeSocket\n               *  _Private_ function to close the WebSocket.\n               *\n               *  Closes the socket if it is still open and deletes it\n               */\n\n\n              _closeSocket() {\n                if (this.socket) {\n                  try {\n                    this.socket.onclose = null;\n                    this.socket.onerror = null;\n                    this.socket.onmessage = null;\n                    this.socket.close();\n                  } catch (e) {\n                    Strophe.debug(e.message);\n                  }\n                }\n\n                this.socket = null;\n              }\n              /** PrivateFunction: _emptyQueue\n               * _Private_ function to check if the message queue is empty.\n               *\n               *  Returns:\n               *    True, because WebSocket messages are send immediately after queueing.\n               */\n\n\n              _emptyQueue() {\n                // eslint-disable-line class-methods-use-this\n                return true;\n              }\n              /** PrivateFunction: _onClose\n               * _Private_ function to handle websockets closing.\n               */\n\n\n              _onClose(e) {\n                if (this._conn.connected && !this._conn.disconnecting) {\n                  Strophe.error(\"Websocket closed unexpectedly\");\n\n                  this._conn._doDisconnect();\n                } else if (e && e.code === 1006 && !this._conn.connected && this.socket) {\n                  // in case the onError callback was not called (Safari 10 does not\n                  // call onerror when the initial connection fails) we need to\n                  // dispatch a CONNFAIL status update to be consistent with the\n                  // behavior on other browsers.\n                  Strophe.error(\"Websocket closed unexcectedly\");\n\n                  this._conn._changeConnectStatus(Strophe.Status.CONNFAIL, \"The WebSocket connection could not be established or was disconnected.\");\n\n                  this._conn._doDisconnect();\n                } else {\n                  Strophe.debug(\"Websocket closed\");\n                }\n              }\n              /** PrivateFunction: _no_auth_received\n               *\n               * Called on stream start/restart when no stream:features\n               * has been received.\n               */\n\n\n              _no_auth_received(callback) {\n                Strophe.error(\"Server did not offer a supported authentication mechanism\");\n\n                this._conn._changeConnectStatus(Strophe.Status.CONNFAIL, Strophe.ErrorCondition.NO_AUTH_MECH);\n\n                if (callback) {\n                  callback.call(this._conn);\n                }\n\n                this._conn._doDisconnect();\n              }\n              /** PrivateFunction: _onDisconnectTimeout\n               *  _Private_ timeout handler for handling non-graceful disconnection.\n               *\n               *  This does nothing for WebSockets\n               */\n\n\n              _onDisconnectTimeout() {} // eslint-disable-line class-methods-use-this\n\n              /** PrivateFunction: _abortAllRequests\n               *  _Private_ helper function that makes sure all pending requests are aborted.\n               */\n\n\n              _abortAllRequests() {} // eslint-disable-line class-methods-use-this\n\n              /** PrivateFunction: _onError\n               * _Private_ function to handle websockets errors.\n               *\n               * Parameters:\n               * (Object) error - The websocket error.\n               */\n\n\n              _onError(error) {\n                Strophe.error(\"Websocket error \" + JSON.stringify(error));\n\n                this._conn._changeConnectStatus(Strophe.Status.CONNFAIL, \"The WebSocket connection could not be established or was disconnected.\");\n\n                this._disconnect();\n              }\n              /** PrivateFunction: _onIdle\n               *  _Private_ function called by Strophe.Connection._onIdle\n               *\n               *  sends all queued stanzas\n               */\n\n\n              _onIdle() {\n                const data = this._conn._data;\n\n                if (data.length > 0 && !this._conn.paused) {\n                  for (let i = 0; i < data.length; i++) {\n                    if (data[i] !== null) {\n                      let stanza;\n\n                      if (data[i] === \"restart\") {\n                        stanza = this._buildStream().tree();\n                      } else {\n                        stanza = data[i];\n                      }\n\n                      const rawStanza = Strophe.serialize(stanza);\n\n                      this._conn.xmlOutput(stanza);\n\n                      this._conn.rawOutput(rawStanza);\n\n                      this.socket.send(rawStanza);\n                    }\n                  }\n\n                  this._conn._data = [];\n                }\n              }\n              /** PrivateFunction: _onMessage\n               * _Private_ function to handle websockets messages.\n               *\n               * This function parses each of the messages as if they are full documents.\n               * [TODO : We may actually want to use a SAX Push parser].\n               *\n               * Since all XMPP traffic starts with\n               *  <stream:stream version='1.0'\n               *                 xml:lang='en'\n               *                 xmlns='jabber:client'\n               *                 xmlns:stream='http://etherx.jabber.org/streams'\n               *                 id='3697395463'\n               *                 from='SERVER'>\n               *\n               * The first stanza will always fail to be parsed.\n               *\n               * Additionally, the seconds stanza will always be <stream:features> with\n               * the stream NS defined in the previous stanza, so we need to 'force'\n               * the inclusion of the NS in this stanza.\n               *\n               * Parameters:\n               * (string) message - The websocket message.\n               */\n\n\n              _onMessage(message) {\n                let elem; // check for closing stream\n\n                const close = '<close xmlns=\"urn:ietf:params:xml:ns:xmpp-framing\" />';\n\n                if (message.data === close) {\n                  this._conn.rawInput(close);\n\n                  this._conn.xmlInput(message);\n\n                  if (!this._conn.disconnecting) {\n                    this._conn._doDisconnect();\n                  }\n\n                  return;\n                } else if (message.data.search(\"<open \") === 0) {\n                  // This handles stream restarts\n                  elem = new DOMParser().parseFromString(message.data, \"text/xml\").documentElement;\n\n                  if (!this._handleStreamStart(elem)) {\n                    return;\n                  }\n                } else {\n                  const data = this._streamWrap(message.data);\n\n                  elem = new DOMParser().parseFromString(data, \"text/xml\").documentElement;\n                }\n\n                if (this._checkStreamError(elem, Strophe.Status.ERROR)) {\n                  return;\n                } //handle unavailable presence stanza before disconnecting\n\n\n                if (this._conn.disconnecting && elem.firstChild.nodeName === \"presence\" && elem.firstChild.getAttribute(\"type\") === \"unavailable\") {\n                  this._conn.xmlInput(elem);\n\n                  this._conn.rawInput(Strophe.serialize(elem)); // if we are already disconnecting we will ignore the unavailable stanza and\n                  // wait for the </stream:stream> tag before we close the connection\n\n\n                  return;\n                }\n\n                this._conn._dataRecv(elem, message.data);\n              }\n              /** PrivateFunction: _onOpen\n               * _Private_ function to handle websockets connection setup.\n               *\n               * The opening stream tag is sent here.\n               */\n\n\n              _onOpen() {\n                Strophe.debug(\"Websocket open\");\n\n                const start = this._buildStream();\n\n                this._conn.xmlOutput(start.tree());\n\n                const startString = Strophe.serialize(start);\n\n                this._conn.rawOutput(startString);\n\n                this.socket.send(startString);\n              }\n              /** PrivateFunction: _reqToData\n               * _Private_ function to get a stanza out of a request.\n               *\n               * WebSockets don't use requests, so the passed argument is just returned.\n               *\n               *  Parameters:\n               *    (Object) stanza - The stanza.\n               *\n               *  Returns:\n               *    The stanza that was passed.\n               */\n\n\n              _reqToData(stanza) {\n                // eslint-disable-line class-methods-use-this\n                return stanza;\n              }\n              /** PrivateFunction: _send\n               *  _Private_ part of the Connection.send function for WebSocket\n               *\n               * Just flushes the messages that are in the queue\n               */\n\n\n              _send() {\n                this._conn.flush();\n              }\n              /** PrivateFunction: _sendRestart\n               *\n               *  Send an xmpp:restart stanza.\n               */\n\n\n              _sendRestart() {\n                clearTimeout(this._conn._idleTimeout);\n\n                this._conn._onIdle.bind(this._conn)();\n              }\n\n            };\n\n            /*\n                This program is distributed under the terms of the MIT license.\n                Please see the LICENSE file for details.\n\n                Copyright 2020, JC Brand\n            */\n            const lmap = {};\n            lmap['debug'] = Strophe.LogLevel.DEBUG;\n            lmap['info'] = Strophe.LogLevel.INFO;\n            lmap['warn'] = Strophe.LogLevel.WARN;\n            lmap['error'] = Strophe.LogLevel.ERROR;\n            lmap['fatal'] = Strophe.LogLevel.FATAL;\n            /** Class: Strophe.WorkerWebsocket\n             *  _Private_ helper class that handles a websocket connection inside a shared worker.\n             */\n\n            Strophe.WorkerWebsocket = class WorkerWebsocket extends Strophe.Websocket {\n              /** PrivateConstructor: Strophe.WorkerWebsocket\n               *  Create and initialize a Strophe.WorkerWebsocket object.\n               *\n               *  Parameters:\n               *    (Strophe.Connection) connection - The Strophe.Connection\n               *\n               *  Returns:\n               *    A new Strophe.WorkerWebsocket object.\n               */\n              constructor(connection) {\n                super(connection);\n                this._conn = connection;\n                this.worker = new SharedWorker(this._conn.options.worker, 'Strophe XMPP Connection');\n\n                this.worker.onerror = e => {\n                  var _console;\n\n                  (_console = console) === null || _console === void 0 ? void 0 : _console.error(e);\n                  Strophe.log(Strophe.LogLevel.ERROR, `Shared Worker Error: ${e}`);\n                };\n              }\n\n              get socket() {\n                return {\n                  'send': str => this.worker.port.postMessage(['send', str])\n                };\n              }\n\n              _connect() {\n                this._messageHandler = m => this._onInitialMessage(m);\n\n                this.worker.port.start();\n\n                this.worker.port.onmessage = ev => this._onWorkerMessage(ev);\n\n                this.worker.port.postMessage(['_connect', this._conn.service, this._conn.jid]);\n              }\n\n              _attach(callback) {\n                this._messageHandler = m => this._onMessage(m);\n\n                this._conn.connect_callback = callback;\n                this.worker.port.start();\n\n                this.worker.port.onmessage = ev => this._onWorkerMessage(ev);\n\n                this.worker.port.postMessage(['_attach', this._conn.service]);\n              }\n\n              _attachCallback(status, jid) {\n                if (status === Strophe.Status.ATTACHED) {\n                  this._conn.jid = jid;\n                  this._conn.authenticated = true;\n                  this._conn.connected = true;\n                  this._conn.restored = true;\n\n                  this._conn._changeConnectStatus(Strophe.Status.ATTACHED);\n                } else if (status === Strophe.Status.ATTACHFAIL) {\n                  this._conn.authenticated = false;\n                  this._conn.connected = false;\n                  this._conn.restored = false;\n\n                  this._conn._changeConnectStatus(Strophe.Status.ATTACHFAIL);\n                }\n              }\n\n              _disconnect(readyState, pres) {\n                pres && this._conn.send(pres);\n                const close = $build(\"close\", {\n                  \"xmlns\": Strophe.NS.FRAMING\n                });\n\n                this._conn.xmlOutput(close.tree());\n\n                const closeString = Strophe.serialize(close);\n\n                this._conn.rawOutput(closeString);\n\n                this.worker.port.postMessage(['send', closeString]);\n\n                this._conn._doDisconnect();\n              }\n\n              _onClose(e) {\n                if (this._conn.connected && !this._conn.disconnecting) {\n                  Strophe.error(\"Websocket closed unexpectedly\");\n\n                  this._conn._doDisconnect();\n                } else if (e && e.code === 1006 && !this._conn.connected) {\n                  // in case the onError callback was not called (Safari 10 does not\n                  // call onerror when the initial connection fails) we need to\n                  // dispatch a CONNFAIL status update to be consistent with the\n                  // behavior on other browsers.\n                  Strophe.error(\"Websocket closed unexcectedly\");\n\n                  this._conn._changeConnectStatus(Strophe.Status.CONNFAIL, \"The WebSocket connection could not be established or was disconnected.\");\n\n                  this._conn._doDisconnect();\n                } else {\n                  Strophe.debug(\"Websocket closed\");\n                }\n              }\n\n              _closeSocket() {\n                this.worker.port.postMessage(['_closeSocket']);\n              }\n              /** PrivateFunction: _replaceMessageHandler\n               *\n               * Called by _onInitialMessage in order to replace itself with the general message handler.\n               * This method is overridden by Strophe.WorkerWebsocket, which manages a\n               * websocket connection via a service worker and doesn't have direct access\n               * to the socket.\n               */\n\n\n              _replaceMessageHandler() {\n                this._messageHandler = m => this._onMessage(m);\n              }\n              /** PrivateFunction: _onWorkerMessage\n               * _Private_ function that handles messages received from the service worker\n               */\n\n\n              _onWorkerMessage(ev) {\n                const {\n                  data\n                } = ev;\n                const method_name = data[0];\n\n                if (method_name === '_onMessage') {\n                  this._messageHandler(data[1]);\n                } else if (method_name in this) {\n                  try {\n                    this[method_name].apply(this, ev.data.slice(1));\n                  } catch (e) {\n                    Strophe.log(Strophe.LogLevel.ERROR, e);\n                  }\n                } else if (method_name === 'log') {\n                  const level = data[1];\n                  const msg = data[2];\n                  Strophe.log(lmap[level], msg);\n                } else {\n                  Strophe.log(Strophe.LogLevel.ERROR, `Found unhandled service worker message: ${data}`);\n                }\n              }\n\n            };\n\n            global$1.$build = core.$build;\n            global$1.$iq = core.$iq;\n            global$1.$msg = core.$msg;\n            global$1.$pres = core.$pres;\n            global$1.Strophe = core.Strophe;\n            const {\n              b64_sha1\n            } = SHA1;\n\n            exports.$build = $build;\n            exports.$iq = $iq;\n            exports.$msg = $msg;\n            exports.$pres = $pres;\n            exports.Strophe = Strophe;\n            exports.b64_sha1 = b64_sha1;\n\n            Object.defineProperty(exports, '__esModule', { value: true });\n\n}));\n","/////////////////////////////////////////////////////////////////////////////////\n/* UAParser.js v1.0.35\n   Copyright © 2012-2021 Faisal Salman <f@faisalman.com>\n   MIT License *//*\n   Detect Browser, Engine, OS, CPU, and Device type/model from User-Agent data.\n   Supports browser & node.js environment. \n   Demo   : https://faisalman.github.io/ua-parser-js\n   Source : https://github.com/faisalman/ua-parser-js */\n/////////////////////////////////////////////////////////////////////////////////\n\n(function (window, undefined) {\n\n    'use strict';\n\n    //////////////\n    // Constants\n    /////////////\n\n\n    var LIBVERSION  = '1.0.35',\n        EMPTY       = '',\n        UNKNOWN     = '?',\n        FUNC_TYPE   = 'function',\n        UNDEF_TYPE  = 'undefined',\n        OBJ_TYPE    = 'object',\n        STR_TYPE    = 'string',\n        MAJOR       = 'major',\n        MODEL       = 'model',\n        NAME        = 'name',\n        TYPE        = 'type',\n        VENDOR      = 'vendor',\n        VERSION     = 'version',\n        ARCHITECTURE= 'architecture',\n        CONSOLE     = 'console',\n        MOBILE      = 'mobile',\n        TABLET      = 'tablet',\n        SMARTTV     = 'smarttv',\n        WEARABLE    = 'wearable',\n        EMBEDDED    = 'embedded',\n        UA_MAX_LENGTH = 350;\n\n    var AMAZON  = 'Amazon',\n        APPLE   = 'Apple',\n        ASUS    = 'ASUS',\n        BLACKBERRY = 'BlackBerry',\n        BROWSER = 'Browser',\n        CHROME  = 'Chrome',\n        EDGE    = 'Edge',\n        FIREFOX = 'Firefox',\n        GOOGLE  = 'Google',\n        HUAWEI  = 'Huawei',\n        LG      = 'LG',\n        MICROSOFT = 'Microsoft',\n        MOTOROLA  = 'Motorola',\n        OPERA   = 'Opera',\n        SAMSUNG = 'Samsung',\n        SHARP   = 'Sharp',\n        SONY    = 'Sony',\n        VIERA   = 'Viera',\n        XIAOMI  = 'Xiaomi',\n        ZEBRA   = 'Zebra',\n        FACEBOOK    = 'Facebook',\n        CHROMIUM_OS = 'Chromium OS',\n        MAC_OS  = 'Mac OS';\n\n    ///////////\n    // Helper\n    //////////\n\n    var extend = function (regexes, extensions) {\n            var mergedRegexes = {};\n            for (var i in regexes) {\n                if (extensions[i] && extensions[i].length % 2 === 0) {\n                    mergedRegexes[i] = extensions[i].concat(regexes[i]);\n                } else {\n                    mergedRegexes[i] = regexes[i];\n                }\n            }\n            return mergedRegexes;\n        },\n        enumerize = function (arr) {\n            var enums = {};\n            for (var i=0; i<arr.length; i++) {\n                enums[arr[i].toUpperCase()] = arr[i];\n            }\n            return enums;\n        },\n        has = function (str1, str2) {\n            return typeof str1 === STR_TYPE ? lowerize(str2).indexOf(lowerize(str1)) !== -1 : false;\n        },\n        lowerize = function (str) {\n            return str.toLowerCase();\n        },\n        majorize = function (version) {\n            return typeof(version) === STR_TYPE ? version.replace(/[^\\d\\.]/g, EMPTY).split('.')[0] : undefined;\n        },\n        trim = function (str, len) {\n            if (typeof(str) === STR_TYPE) {\n                str = str.replace(/^\\s\\s*/, EMPTY);\n                return typeof(len) === UNDEF_TYPE ? str : str.substring(0, UA_MAX_LENGTH);\n            }\n    };\n\n    ///////////////\n    // Map helper\n    //////////////\n\n    var rgxMapper = function (ua, arrays) {\n\n            var i = 0, j, k, p, q, matches, match;\n\n            // loop through all regexes maps\n            while (i < arrays.length && !matches) {\n\n                var regex = arrays[i],       // even sequence (0,2,4,..)\n                    props = arrays[i + 1];   // odd sequence (1,3,5,..)\n                j = k = 0;\n\n                // try matching uastring with regexes\n                while (j < regex.length && !matches) {\n\n                    if (!regex[j]) { break; }\n                    matches = regex[j++].exec(ua);\n\n                    if (!!matches) {\n                        for (p = 0; p < props.length; p++) {\n                            match = matches[++k];\n                            q = props[p];\n                            // check if given property is actually array\n                            if (typeof q === OBJ_TYPE && q.length > 0) {\n                                if (q.length === 2) {\n                                    if (typeof q[1] == FUNC_TYPE) {\n                                        // assign modified match\n                                        this[q[0]] = q[1].call(this, match);\n                                    } else {\n                                        // assign given value, ignore regex match\n                                        this[q[0]] = q[1];\n                                    }\n                                } else if (q.length === 3) {\n                                    // check whether function or regex\n                                    if (typeof q[1] === FUNC_TYPE && !(q[1].exec && q[1].test)) {\n                                        // call function (usually string mapper)\n                                        this[q[0]] = match ? q[1].call(this, match, q[2]) : undefined;\n                                    } else {\n                                        // sanitize match using given regex\n                                        this[q[0]] = match ? match.replace(q[1], q[2]) : undefined;\n                                    }\n                                } else if (q.length === 4) {\n                                        this[q[0]] = match ? q[3].call(this, match.replace(q[1], q[2])) : undefined;\n                                }\n                            } else {\n                                this[q] = match ? match : undefined;\n                            }\n                        }\n                    }\n                }\n                i += 2;\n            }\n        },\n\n        strMapper = function (str, map) {\n\n            for (var i in map) {\n                // check if current value is array\n                if (typeof map[i] === OBJ_TYPE && map[i].length > 0) {\n                    for (var j = 0; j < map[i].length; j++) {\n                        if (has(map[i][j], str)) {\n                            return (i === UNKNOWN) ? undefined : i;\n                        }\n                    }\n                } else if (has(map[i], str)) {\n                    return (i === UNKNOWN) ? undefined : i;\n                }\n            }\n            return str;\n    };\n\n    ///////////////\n    // String map\n    //////////////\n\n    // Safari < 3.0\n    var oldSafariMap = {\n            '1.0'   : '/8',\n            '1.2'   : '/1',\n            '1.3'   : '/3',\n            '2.0'   : '/412',\n            '2.0.2' : '/416',\n            '2.0.3' : '/417',\n            '2.0.4' : '/419',\n            '?'     : '/'\n        },\n        windowsVersionMap = {\n            'ME'        : '4.90',\n            'NT 3.11'   : 'NT3.51',\n            'NT 4.0'    : 'NT4.0',\n            '2000'      : 'NT 5.0',\n            'XP'        : ['NT 5.1', 'NT 5.2'],\n            'Vista'     : 'NT 6.0',\n            '7'         : 'NT 6.1',\n            '8'         : 'NT 6.2',\n            '8.1'       : 'NT 6.3',\n            '10'        : ['NT 6.4', 'NT 10.0'],\n            'RT'        : 'ARM'\n    };\n\n    //////////////\n    // Regex map\n    /////////////\n\n    var regexes = {\n\n        browser : [[\n\n            /\\b(?:crmo|crios)\\/([\\w\\.]+)/i                                      // Chrome for Android/iOS\n            ], [VERSION, [NAME, 'Chrome']], [\n            /edg(?:e|ios|a)?\\/([\\w\\.]+)/i                                       // Microsoft Edge\n            ], [VERSION, [NAME, 'Edge']], [\n\n            // Presto based\n            /(opera mini)\\/([-\\w\\.]+)/i,                                        // Opera Mini\n            /(opera [mobiletab]{3,6})\\b.+version\\/([-\\w\\.]+)/i,                 // Opera Mobi/Tablet\n            /(opera)(?:.+version\\/|[\\/ ]+)([\\w\\.]+)/i                           // Opera\n            ], [NAME, VERSION], [\n            /opios[\\/ ]+([\\w\\.]+)/i                                             // Opera mini on iphone >= 8.0\n            ], [VERSION, [NAME, OPERA+' Mini']], [\n            /\\bopr\\/([\\w\\.]+)/i                                                 // Opera Webkit\n            ], [VERSION, [NAME, OPERA]], [\n\n            // Mixed\n            /(kindle)\\/([\\w\\.]+)/i,                                             // Kindle\n            /(lunascape|maxthon|netfront|jasmine|blazer)[\\/ ]?([\\w\\.]*)/i,      // Lunascape/Maxthon/Netfront/Jasmine/Blazer\n            // Trident based\n            /(avant |iemobile|slim)(?:browser)?[\\/ ]?([\\w\\.]*)/i,               // Avant/IEMobile/SlimBrowser\n            /(ba?idubrowser)[\\/ ]?([\\w\\.]+)/i,                                  // Baidu Browser\n            /(?:ms|\\()(ie) ([\\w\\.]+)/i,                                         // Internet Explorer\n\n            // Webkit/KHTML based                                               // Flock/RockMelt/Midori/Epiphany/Silk/Skyfire/Bolt/Iron/Iridium/PhantomJS/Bowser/QupZilla/Falkon\n            /(flock|rockmelt|midori|epiphany|silk|skyfire|bolt|iron|vivaldi|iridium|phantomjs|bowser|quark|qupzilla|falkon|rekonq|puffin|brave|whale(?!.+naver)|qqbrowserlite|qq|duckduckgo)\\/([-\\w\\.]+)/i,\n                                                                                // Rekonq/Puffin/Brave/Whale/QQBrowserLite/QQ, aka ShouQ\n            /(heytap|ovi)browser\\/([\\d\\.]+)/i,                                  // Heytap/Ovi\n            /(weibo)__([\\d\\.]+)/i                                               // Weibo\n            ], [NAME, VERSION], [\n            /(?:\\buc? ?browser|(?:juc.+)ucweb)[\\/ ]?([\\w\\.]+)/i                 // UCBrowser\n            ], [VERSION, [NAME, 'UC'+BROWSER]], [\n            /microm.+\\bqbcore\\/([\\w\\.]+)/i,                                     // WeChat Desktop for Windows Built-in Browser\n            /\\bqbcore\\/([\\w\\.]+).+microm/i\n            ], [VERSION, [NAME, 'WeChat(Win) Desktop']], [\n            /micromessenger\\/([\\w\\.]+)/i                                        // WeChat\n            ], [VERSION, [NAME, 'WeChat']], [\n            /konqueror\\/([\\w\\.]+)/i                                             // Konqueror\n            ], [VERSION, [NAME, 'Konqueror']], [\n            /trident.+rv[: ]([\\w\\.]{1,9})\\b.+like gecko/i                       // IE11\n            ], [VERSION, [NAME, 'IE']], [\n            /ya(?:search)?browser\\/([\\w\\.]+)/i                                  // Yandex\n            ], [VERSION, [NAME, 'Yandex']], [\n            /(avast|avg)\\/([\\w\\.]+)/i                                           // Avast/AVG Secure Browser\n            ], [[NAME, /(.+)/, '$1 Secure '+BROWSER], VERSION], [\n            /\\bfocus\\/([\\w\\.]+)/i                                               // Firefox Focus\n            ], [VERSION, [NAME, FIREFOX+' Focus']], [\n            /\\bopt\\/([\\w\\.]+)/i                                                 // Opera Touch\n            ], [VERSION, [NAME, OPERA+' Touch']], [\n            /coc_coc\\w+\\/([\\w\\.]+)/i                                            // Coc Coc Browser\n            ], [VERSION, [NAME, 'Coc Coc']], [\n            /dolfin\\/([\\w\\.]+)/i                                                // Dolphin\n            ], [VERSION, [NAME, 'Dolphin']], [\n            /coast\\/([\\w\\.]+)/i                                                 // Opera Coast\n            ], [VERSION, [NAME, OPERA+' Coast']], [\n            /miuibrowser\\/([\\w\\.]+)/i                                           // MIUI Browser\n            ], [VERSION, [NAME, 'MIUI '+BROWSER]], [\n            /fxios\\/([-\\w\\.]+)/i                                                // Firefox for iOS\n            ], [VERSION, [NAME, FIREFOX]], [\n            /\\bqihu|(qi?ho?o?|360)browser/i                                     // 360\n            ], [[NAME, '360 '+BROWSER]], [\n            /(oculus|samsung|sailfish|huawei)browser\\/([\\w\\.]+)/i\n            ], [[NAME, /(.+)/, '$1 '+BROWSER], VERSION], [                      // Oculus/Samsung/Sailfish/Huawei Browser\n            /(comodo_dragon)\\/([\\w\\.]+)/i                                       // Comodo Dragon\n            ], [[NAME, /_/g, ' '], VERSION], [\n            /(electron)\\/([\\w\\.]+) safari/i,                                    // Electron-based App\n            /(tesla)(?: qtcarbrowser|\\/(20\\d\\d\\.[-\\w\\.]+))/i,                   // Tesla\n            /m?(qqbrowser|baiduboxapp|2345Explorer)[\\/ ]?([\\w\\.]+)/i            // QQBrowser/Baidu App/2345 Browser\n            ], [NAME, VERSION], [\n            /(metasr)[\\/ ]?([\\w\\.]+)/i,                                         // SouGouBrowser\n            /(lbbrowser)/i,                                                     // LieBao Browser\n            /\\[(linkedin)app\\]/i                                                // LinkedIn App for iOS & Android\n            ], [NAME], [\n\n            // WebView\n            /((?:fban\\/fbios|fb_iab\\/fb4a)(?!.+fbav)|;fbav\\/([\\w\\.]+);)/i       // Facebook App for iOS & Android\n            ], [[NAME, FACEBOOK], VERSION], [\n            /(kakao(?:talk|story))[\\/ ]([\\w\\.]+)/i,                             // Kakao App\n            /(naver)\\(.*?(\\d+\\.[\\w\\.]+).*\\)/i,                                  // Naver InApp\n            /safari (line)\\/([\\w\\.]+)/i,                                        // Line App for iOS\n            /\\b(line)\\/([\\w\\.]+)\\/iab/i,                                        // Line App for Android\n            /(chromium|instagram)[\\/ ]([-\\w\\.]+)/i                              // Chromium/Instagram\n            ], [NAME, VERSION], [\n            /\\bgsa\\/([\\w\\.]+) .*safari\\//i                                      // Google Search Appliance on iOS\n            ], [VERSION, [NAME, 'GSA']], [\n            /musical_ly(?:.+app_?version\\/|_)([\\w\\.]+)/i                        // TikTok\n            ], [VERSION, [NAME, 'TikTok']], [\n\n            /headlesschrome(?:\\/([\\w\\.]+)| )/i                                  // Chrome Headless\n            ], [VERSION, [NAME, CHROME+' Headless']], [\n\n            / wv\\).+(chrome)\\/([\\w\\.]+)/i                                       // Chrome WebView\n            ], [[NAME, CHROME+' WebView'], VERSION], [\n\n            /droid.+ version\\/([\\w\\.]+)\\b.+(?:mobile safari|safari)/i           // Android Browser\n            ], [VERSION, [NAME, 'Android '+BROWSER]], [\n\n            /(chrome|omniweb|arora|[tizenoka]{5} ?browser)\\/v?([\\w\\.]+)/i       // Chrome/OmniWeb/Arora/Tizen/Nokia\n            ], [NAME, VERSION], [\n\n            /version\\/([\\w\\.\\,]+) .*mobile\\/\\w+ (safari)/i                      // Mobile Safari\n            ], [VERSION, [NAME, 'Mobile Safari']], [\n            /version\\/([\\w(\\.|\\,)]+) .*(mobile ?safari|safari)/i                // Safari & Safari Mobile\n            ], [VERSION, NAME], [\n            /webkit.+?(mobile ?safari|safari)(\\/[\\w\\.]+)/i                      // Safari < 3.0\n            ], [NAME, [VERSION, strMapper, oldSafariMap]], [\n\n            /(webkit|khtml)\\/([\\w\\.]+)/i\n            ], [NAME, VERSION], [\n\n            // Gecko based\n            /(navigator|netscape\\d?)\\/([-\\w\\.]+)/i                              // Netscape\n            ], [[NAME, 'Netscape'], VERSION], [\n            /mobile vr; rv:([\\w\\.]+)\\).+firefox/i                               // Firefox Reality\n            ], [VERSION, [NAME, FIREFOX+' Reality']], [\n            /ekiohf.+(flow)\\/([\\w\\.]+)/i,                                       // Flow\n            /(swiftfox)/i,                                                      // Swiftfox\n            /(icedragon|iceweasel|camino|chimera|fennec|maemo browser|minimo|conkeror|klar)[\\/ ]?([\\w\\.\\+]+)/i,\n                                                                                // IceDragon/Iceweasel/Camino/Chimera/Fennec/Maemo/Minimo/Conkeror/Klar\n            /(seamonkey|k-meleon|icecat|iceape|firebird|phoenix|palemoon|basilisk|waterfox)\\/([-\\w\\.]+)$/i,\n                                                                                // Firefox/SeaMonkey/K-Meleon/IceCat/IceApe/Firebird/Phoenix\n            /(firefox)\\/([\\w\\.]+)/i,                                            // Other Firefox-based\n            /(mozilla)\\/([\\w\\.]+) .+rv\\:.+gecko\\/\\d+/i,                         // Mozilla\n\n            // Other\n            /(polaris|lynx|dillo|icab|doris|amaya|w3m|netsurf|sleipnir|obigo|mosaic|(?:go|ice|up)[\\. ]?browser)[-\\/ ]?v?([\\w\\.]+)/i,\n                                                                                // Polaris/Lynx/Dillo/iCab/Doris/Amaya/w3m/NetSurf/Sleipnir/Obigo/Mosaic/Go/ICE/UP.Browser\n            /(links) \\(([\\w\\.]+)/i,                                             // Links\n            /panasonic;(viera)/i                                                // Panasonic Viera\n            ], [NAME, VERSION], [\n            \n            /(cobalt)\\/([\\w\\.]+)/i                                              // Cobalt\n            ], [NAME, [VERSION, /master.|lts./, \"\"]]\n        ],\n\n        cpu : [[\n\n            /(?:(amd|x(?:(?:86|64)[-_])?|wow|win)64)[;\\)]/i                     // AMD64 (x64)\n            ], [[ARCHITECTURE, 'amd64']], [\n\n            /(ia32(?=;))/i                                                      // IA32 (quicktime)\n            ], [[ARCHITECTURE, lowerize]], [\n\n            /((?:i[346]|x)86)[;\\)]/i                                            // IA32 (x86)\n            ], [[ARCHITECTURE, 'ia32']], [\n\n            /\\b(aarch64|arm(v?8e?l?|_?64))\\b/i                                 // ARM64\n            ], [[ARCHITECTURE, 'arm64']], [\n\n            /\\b(arm(?:v[67])?ht?n?[fl]p?)\\b/i                                   // ARMHF\n            ], [[ARCHITECTURE, 'armhf']], [\n\n            // PocketPC mistakenly identified as PowerPC\n            /windows (ce|mobile); ppc;/i\n            ], [[ARCHITECTURE, 'arm']], [\n\n            /((?:ppc|powerpc)(?:64)?)(?: mac|;|\\))/i                            // PowerPC\n            ], [[ARCHITECTURE, /ower/, EMPTY, lowerize]], [\n\n            /(sun4\\w)[;\\)]/i                                                    // SPARC\n            ], [[ARCHITECTURE, 'sparc']], [\n\n            /((?:avr32|ia64(?=;))|68k(?=\\))|\\barm(?=v(?:[1-7]|[5-7]1)l?|;|eabi)|(?=atmel )avr|(?:irix|mips|sparc)(?:64)?\\b|pa-risc)/i\n                                                                                // IA64, 68K, ARM/64, AVR/32, IRIX/64, MIPS/64, SPARC/64, PA-RISC\n            ], [[ARCHITECTURE, lowerize]]\n        ],\n\n        device : [[\n\n            //////////////////////////\n            // MOBILES & TABLETS\n            /////////////////////////\n\n            // Samsung\n            /\\b(sch-i[89]0\\d|shw-m380s|sm-[ptx]\\w{2,4}|gt-[pn]\\d{2,4}|sgh-t8[56]9|nexus 10)/i\n            ], [MODEL, [VENDOR, SAMSUNG], [TYPE, TABLET]], [\n            /\\b((?:s[cgp]h|gt|sm)-\\w+|sc[g-]?[\\d]+a?|galaxy nexus)/i,\n            /samsung[- ]([-\\w]+)/i,\n            /sec-(sgh\\w+)/i\n            ], [MODEL, [VENDOR, SAMSUNG], [TYPE, MOBILE]], [\n\n            // Apple\n            /(?:\\/|\\()(ip(?:hone|od)[\\w, ]*)(?:\\/|;)/i                          // iPod/iPhone\n            ], [MODEL, [VENDOR, APPLE], [TYPE, MOBILE]], [\n            /\\((ipad);[-\\w\\),; ]+apple/i,                                       // iPad\n            /applecoremedia\\/[\\w\\.]+ \\((ipad)/i,\n            /\\b(ipad)\\d\\d?,\\d\\d?[;\\]].+ios/i\n            ], [MODEL, [VENDOR, APPLE], [TYPE, TABLET]], [\n            /(macintosh);/i\n            ], [MODEL, [VENDOR, APPLE]], [\n\n            // Sharp\n            /\\b(sh-?[altvz]?\\d\\d[a-ekm]?)/i\n            ], [MODEL, [VENDOR, SHARP], [TYPE, MOBILE]], [\n\n            // Huawei\n            /\\b((?:ag[rs][23]?|bah2?|sht?|btv)-a?[lw]\\d{2})\\b(?!.+d\\/s)/i\n            ], [MODEL, [VENDOR, HUAWEI], [TYPE, TABLET]], [\n            /(?:huawei|honor)([-\\w ]+)[;\\)]/i,\n            /\\b(nexus 6p|\\w{2,4}e?-[atu]?[ln][\\dx][012359c][adn]?)\\b(?!.+d\\/s)/i\n            ], [MODEL, [VENDOR, HUAWEI], [TYPE, MOBILE]], [\n\n            // Xiaomi\n            /\\b(poco[\\w ]+)(?: bui|\\))/i,                                       // Xiaomi POCO\n            /\\b; (\\w+) build\\/hm\\1/i,                                           // Xiaomi Hongmi 'numeric' models\n            /\\b(hm[-_ ]?note?[_ ]?(?:\\d\\w)?) bui/i,                             // Xiaomi Hongmi\n            /\\b(redmi[\\-_ ]?(?:note|k)?[\\w_ ]+)(?: bui|\\))/i,                   // Xiaomi Redmi\n            /\\b(mi[-_ ]?(?:a\\d|one|one[_ ]plus|note lte|max|cc)?[_ ]?(?:\\d?\\w?)[_ ]?(?:plus|se|lite)?)(?: bui|\\))/i // Xiaomi Mi\n            ], [[MODEL, /_/g, ' '], [VENDOR, XIAOMI], [TYPE, MOBILE]], [\n            /\\b(mi[-_ ]?(?:pad)(?:[\\w_ ]+))(?: bui|\\))/i                        // Mi Pad tablets\n            ],[[MODEL, /_/g, ' '], [VENDOR, XIAOMI], [TYPE, TABLET]], [\n\n            // OPPO\n            /; (\\w+) bui.+ oppo/i,\n            /\\b(cph[12]\\d{3}|p(?:af|c[al]|d\\w|e[ar])[mt]\\d0|x9007|a101op)\\b/i\n            ], [MODEL, [VENDOR, 'OPPO'], [TYPE, MOBILE]], [\n\n            // Vivo\n            /vivo (\\w+)(?: bui|\\))/i,\n            /\\b(v[12]\\d{3}\\w?[at])(?: bui|;)/i\n            ], [MODEL, [VENDOR, 'Vivo'], [TYPE, MOBILE]], [\n\n            // Realme\n            /\\b(rmx[12]\\d{3})(?: bui|;|\\))/i\n            ], [MODEL, [VENDOR, 'Realme'], [TYPE, MOBILE]], [\n\n            // Motorola\n            /\\b(milestone|droid(?:[2-4x]| (?:bionic|x2|pro|razr))?:?( 4g)?)\\b[\\w ]+build\\//i,\n            /\\bmot(?:orola)?[- ](\\w*)/i,\n            /((?:moto[\\w\\(\\) ]+|xt\\d{3,4}|nexus 6)(?= bui|\\)))/i\n            ], [MODEL, [VENDOR, MOTOROLA], [TYPE, MOBILE]], [\n            /\\b(mz60\\d|xoom[2 ]{0,2}) build\\//i\n            ], [MODEL, [VENDOR, MOTOROLA], [TYPE, TABLET]], [\n\n            // LG\n            /((?=lg)?[vl]k\\-?\\d{3}) bui| 3\\.[-\\w; ]{10}lg?-([06cv9]{3,4})/i\n            ], [MODEL, [VENDOR, LG], [TYPE, TABLET]], [\n            /(lm(?:-?f100[nv]?|-[\\w\\.]+)(?= bui|\\))|nexus [45])/i,\n            /\\blg[-e;\\/ ]+((?!browser|netcast|android tv)\\w+)/i,\n            /\\blg-?([\\d\\w]+) bui/i\n            ], [MODEL, [VENDOR, LG], [TYPE, MOBILE]], [\n\n            // Lenovo\n            /(ideatab[-\\w ]+)/i,\n            /lenovo ?(s[56]000[-\\w]+|tab(?:[\\w ]+)|yt[-\\d\\w]{6}|tb[-\\d\\w]{6})/i\n            ], [MODEL, [VENDOR, 'Lenovo'], [TYPE, TABLET]], [\n\n            // Nokia\n            /(?:maemo|nokia).*(n900|lumia \\d+)/i,\n            /nokia[-_ ]?([-\\w\\.]*)/i\n            ], [[MODEL, /_/g, ' '], [VENDOR, 'Nokia'], [TYPE, MOBILE]], [\n\n            // Google\n            /(pixel c)\\b/i                                                      // Google Pixel C\n            ], [MODEL, [VENDOR, GOOGLE], [TYPE, TABLET]], [\n            /droid.+; (pixel[\\daxl ]{0,6})(?: bui|\\))/i                         // Google Pixel\n            ], [MODEL, [VENDOR, GOOGLE], [TYPE, MOBILE]], [\n\n            // Sony\n            /droid.+ (a?\\d[0-2]{2}so|[c-g]\\d{4}|so[-gl]\\w+|xq-a\\w[4-7][12])(?= bui|\\).+chrome\\/(?![1-6]{0,1}\\d\\.))/i\n            ], [MODEL, [VENDOR, SONY], [TYPE, MOBILE]], [\n            /sony tablet [ps]/i,\n            /\\b(?:sony)?sgp\\w+(?: bui|\\))/i\n            ], [[MODEL, 'Xperia Tablet'], [VENDOR, SONY], [TYPE, TABLET]], [\n\n            // OnePlus\n            / (kb2005|in20[12]5|be20[12][59])\\b/i,\n            /(?:one)?(?:plus)? (a\\d0\\d\\d)(?: b|\\))/i\n            ], [MODEL, [VENDOR, 'OnePlus'], [TYPE, MOBILE]], [\n\n            // Amazon\n            /(alexa)webm/i,\n            /(kf[a-z]{2}wi|aeo[c-r]{2})( bui|\\))/i,                             // Kindle Fire without Silk / Echo Show\n            /(kf[a-z]+)( bui|\\)).+silk\\//i                                      // Kindle Fire HD\n            ], [MODEL, [VENDOR, AMAZON], [TYPE, TABLET]], [\n            /((?:sd|kf)[0349hijorstuw]+)( bui|\\)).+silk\\//i                     // Fire Phone\n            ], [[MODEL, /(.+)/g, 'Fire Phone $1'], [VENDOR, AMAZON], [TYPE, MOBILE]], [\n\n            // BlackBerry\n            /(playbook);[-\\w\\),; ]+(rim)/i                                      // BlackBerry PlayBook\n            ], [MODEL, VENDOR, [TYPE, TABLET]], [\n            /\\b((?:bb[a-f]|st[hv])100-\\d)/i,\n            /\\(bb10; (\\w+)/i                                                    // BlackBerry 10\n            ], [MODEL, [VENDOR, BLACKBERRY], [TYPE, MOBILE]], [\n\n            // Asus\n            /(?:\\b|asus_)(transfo[prime ]{4,10} \\w+|eeepc|slider \\w+|nexus 7|padfone|p00[cj])/i\n            ], [MODEL, [VENDOR, ASUS], [TYPE, TABLET]], [\n            / (z[bes]6[027][012][km][ls]|zenfone \\d\\w?)\\b/i\n            ], [MODEL, [VENDOR, ASUS], [TYPE, MOBILE]], [\n\n            // HTC\n            /(nexus 9)/i                                                        // HTC Nexus 9\n            ], [MODEL, [VENDOR, 'HTC'], [TYPE, TABLET]], [\n            /(htc)[-;_ ]{1,2}([\\w ]+(?=\\)| bui)|\\w+)/i,                         // HTC\n\n            // ZTE\n            /(zte)[- ]([\\w ]+?)(?: bui|\\/|\\))/i,\n            /(alcatel|geeksphone|nexian|panasonic(?!(?:;|\\.))|sony(?!-bra))[-_ ]?([-\\w]*)/i         // Alcatel/GeeksPhone/Nexian/Panasonic/Sony\n            ], [VENDOR, [MODEL, /_/g, ' '], [TYPE, MOBILE]], [\n\n            // Acer\n            /droid.+; ([ab][1-7]-?[0178a]\\d\\d?)/i\n            ], [MODEL, [VENDOR, 'Acer'], [TYPE, TABLET]], [\n\n            // Meizu\n            /droid.+; (m[1-5] note) bui/i,\n            /\\bmz-([-\\w]{2,})/i\n            ], [MODEL, [VENDOR, 'Meizu'], [TYPE, MOBILE]], [\n\n            // MIXED\n            /(blackberry|benq|palm(?=\\-)|sonyericsson|acer|asus|dell|meizu|motorola|polytron)[-_ ]?([-\\w]*)/i,\n                                                                                // BlackBerry/BenQ/Palm/Sony-Ericsson/Acer/Asus/Dell/Meizu/Motorola/Polytron\n            /(hp) ([\\w ]+\\w)/i,                                                 // HP iPAQ\n            /(asus)-?(\\w+)/i,                                                   // Asus\n            /(microsoft); (lumia[\\w ]+)/i,                                      // Microsoft Lumia\n            /(lenovo)[-_ ]?([-\\w]+)/i,                                          // Lenovo\n            /(jolla)/i,                                                         // Jolla\n            /(oppo) ?([\\w ]+) bui/i                                             // OPPO\n            ], [VENDOR, MODEL, [TYPE, MOBILE]], [\n\n            /(kobo)\\s(ereader|touch)/i,                                         // Kobo\n            /(archos) (gamepad2?)/i,                                            // Archos\n            /(hp).+(touchpad(?!.+tablet)|tablet)/i,                             // HP TouchPad\n            /(kindle)\\/([\\w\\.]+)/i,                                             // Kindle\n            /(nook)[\\w ]+build\\/(\\w+)/i,                                        // Nook\n            /(dell) (strea[kpr\\d ]*[\\dko])/i,                                   // Dell Streak\n            /(le[- ]+pan)[- ]+(\\w{1,9}) bui/i,                                  // Le Pan Tablets\n            /(trinity)[- ]*(t\\d{3}) bui/i,                                      // Trinity Tablets\n            /(gigaset)[- ]+(q\\w{1,9}) bui/i,                                    // Gigaset Tablets\n            /(vodafone) ([\\w ]+)(?:\\)| bui)/i                                   // Vodafone\n            ], [VENDOR, MODEL, [TYPE, TABLET]], [\n\n            /(surface duo)/i                                                    // Surface Duo\n            ], [MODEL, [VENDOR, MICROSOFT], [TYPE, TABLET]], [\n            /droid [\\d\\.]+; (fp\\du?)(?: b|\\))/i                                 // Fairphone\n            ], [MODEL, [VENDOR, 'Fairphone'], [TYPE, MOBILE]], [\n            /(u304aa)/i                                                         // AT&T\n            ], [MODEL, [VENDOR, 'AT&T'], [TYPE, MOBILE]], [\n            /\\bsie-(\\w*)/i                                                      // Siemens\n            ], [MODEL, [VENDOR, 'Siemens'], [TYPE, MOBILE]], [\n            /\\b(rct\\w+) b/i                                                     // RCA Tablets\n            ], [MODEL, [VENDOR, 'RCA'], [TYPE, TABLET]], [\n            /\\b(venue[\\d ]{2,7}) b/i                                            // Dell Venue Tablets\n            ], [MODEL, [VENDOR, 'Dell'], [TYPE, TABLET]], [\n            /\\b(q(?:mv|ta)\\w+) b/i                                              // Verizon Tablet\n            ], [MODEL, [VENDOR, 'Verizon'], [TYPE, TABLET]], [\n            /\\b(?:barnes[& ]+noble |bn[rt])([\\w\\+ ]*) b/i                       // Barnes & Noble Tablet\n            ], [MODEL, [VENDOR, 'Barnes & Noble'], [TYPE, TABLET]], [\n            /\\b(tm\\d{3}\\w+) b/i\n            ], [MODEL, [VENDOR, 'NuVision'], [TYPE, TABLET]], [\n            /\\b(k88) b/i                                                        // ZTE K Series Tablet\n            ], [MODEL, [VENDOR, 'ZTE'], [TYPE, TABLET]], [\n            /\\b(nx\\d{3}j) b/i                                                   // ZTE Nubia\n            ], [MODEL, [VENDOR, 'ZTE'], [TYPE, MOBILE]], [\n            /\\b(gen\\d{3}) b.+49h/i                                              // Swiss GEN Mobile\n            ], [MODEL, [VENDOR, 'Swiss'], [TYPE, MOBILE]], [\n            /\\b(zur\\d{3}) b/i                                                   // Swiss ZUR Tablet\n            ], [MODEL, [VENDOR, 'Swiss'], [TYPE, TABLET]], [\n            /\\b((zeki)?tb.*\\b) b/i                                              // Zeki Tablets\n            ], [MODEL, [VENDOR, 'Zeki'], [TYPE, TABLET]], [\n            /\\b([yr]\\d{2}) b/i,\n            /\\b(dragon[- ]+touch |dt)(\\w{5}) b/i                                // Dragon Touch Tablet\n            ], [[VENDOR, 'Dragon Touch'], MODEL, [TYPE, TABLET]], [\n            /\\b(ns-?\\w{0,9}) b/i                                                // Insignia Tablets\n            ], [MODEL, [VENDOR, 'Insignia'], [TYPE, TABLET]], [\n            /\\b((nxa|next)-?\\w{0,9}) b/i                                        // NextBook Tablets\n            ], [MODEL, [VENDOR, 'NextBook'], [TYPE, TABLET]], [\n            /\\b(xtreme\\_)?(v(1[045]|2[015]|[3469]0|7[05])) b/i                  // Voice Xtreme Phones\n            ], [[VENDOR, 'Voice'], MODEL, [TYPE, MOBILE]], [\n            /\\b(lvtel\\-)?(v1[12]) b/i                                           // LvTel Phones\n            ], [[VENDOR, 'LvTel'], MODEL, [TYPE, MOBILE]], [\n            /\\b(ph-1) /i                                                        // Essential PH-1\n            ], [MODEL, [VENDOR, 'Essential'], [TYPE, MOBILE]], [\n            /\\b(v(100md|700na|7011|917g).*\\b) b/i                               // Envizen Tablets\n            ], [MODEL, [VENDOR, 'Envizen'], [TYPE, TABLET]], [\n            /\\b(trio[-\\w\\. ]+) b/i                                              // MachSpeed Tablets\n            ], [MODEL, [VENDOR, 'MachSpeed'], [TYPE, TABLET]], [\n            /\\btu_(1491) b/i                                                    // Rotor Tablets\n            ], [MODEL, [VENDOR, 'Rotor'], [TYPE, TABLET]], [\n            /(shield[\\w ]+) b/i                                                 // Nvidia Shield Tablets\n            ], [MODEL, [VENDOR, 'Nvidia'], [TYPE, TABLET]], [\n            /(sprint) (\\w+)/i                                                   // Sprint Phones\n            ], [VENDOR, MODEL, [TYPE, MOBILE]], [\n            /(kin\\.[onetw]{3})/i                                                // Microsoft Kin\n            ], [[MODEL, /\\./g, ' '], [VENDOR, MICROSOFT], [TYPE, MOBILE]], [\n            /droid.+; (cc6666?|et5[16]|mc[239][23]x?|vc8[03]x?)\\)/i             // Zebra\n            ], [MODEL, [VENDOR, ZEBRA], [TYPE, TABLET]], [\n            /droid.+; (ec30|ps20|tc[2-8]\\d[kx])\\)/i\n            ], [MODEL, [VENDOR, ZEBRA], [TYPE, MOBILE]], [\n\n            ///////////////////\n            // SMARTTVS\n            ///////////////////\n\n            /smart-tv.+(samsung)/i                                              // Samsung\n            ], [VENDOR, [TYPE, SMARTTV]], [\n            /hbbtv.+maple;(\\d+)/i\n            ], [[MODEL, /^/, 'SmartTV'], [VENDOR, SAMSUNG], [TYPE, SMARTTV]], [\n            /(nux; netcast.+smarttv|lg (netcast\\.tv-201\\d|android tv))/i        // LG SmartTV\n            ], [[VENDOR, LG], [TYPE, SMARTTV]], [\n            /(apple) ?tv/i                                                      // Apple TV\n            ], [VENDOR, [MODEL, APPLE+' TV'], [TYPE, SMARTTV]], [\n            /crkey/i                                                            // Google Chromecast\n            ], [[MODEL, CHROME+'cast'], [VENDOR, GOOGLE], [TYPE, SMARTTV]], [\n            /droid.+aft(\\w)( bui|\\))/i                                          // Fire TV\n            ], [MODEL, [VENDOR, AMAZON], [TYPE, SMARTTV]], [\n            /\\(dtv[\\);].+(aquos)/i,\n            /(aquos-tv[\\w ]+)\\)/i                                               // Sharp\n            ], [MODEL, [VENDOR, SHARP], [TYPE, SMARTTV]],[\n            /(bravia[\\w ]+)( bui|\\))/i                                              // Sony\n            ], [MODEL, [VENDOR, SONY], [TYPE, SMARTTV]], [\n            /(mitv-\\w{5}) bui/i                                                 // Xiaomi\n            ], [MODEL, [VENDOR, XIAOMI], [TYPE, SMARTTV]], [\n            /Hbbtv.*(technisat) (.*);/i                                         // TechniSAT\n            ], [VENDOR, MODEL, [TYPE, SMARTTV]], [\n            /\\b(roku)[\\dx]*[\\)\\/]((?:dvp-)?[\\d\\.]*)/i,                          // Roku\n            /hbbtv\\/\\d+\\.\\d+\\.\\d+ +\\([\\w\\+ ]*; *([\\w\\d][^;]*);([^;]*)/i         // HbbTV devices\n            ], [[VENDOR, trim], [MODEL, trim], [TYPE, SMARTTV]], [\n            /\\b(android tv|smart[- ]?tv|opera tv|tv; rv:)\\b/i                   // SmartTV from Unidentified Vendors\n            ], [[TYPE, SMARTTV]], [\n\n            ///////////////////\n            // CONSOLES\n            ///////////////////\n\n            /(ouya)/i,                                                          // Ouya\n            /(nintendo) ([wids3utch]+)/i                                        // Nintendo\n            ], [VENDOR, MODEL, [TYPE, CONSOLE]], [\n            /droid.+; (shield) bui/i                                            // Nvidia\n            ], [MODEL, [VENDOR, 'Nvidia'], [TYPE, CONSOLE]], [\n            /(playstation [345portablevi]+)/i                                   // Playstation\n            ], [MODEL, [VENDOR, SONY], [TYPE, CONSOLE]], [\n            /\\b(xbox(?: one)?(?!; xbox))[\\); ]/i                                // Microsoft Xbox\n            ], [MODEL, [VENDOR, MICROSOFT], [TYPE, CONSOLE]], [\n\n            ///////////////////\n            // WEARABLES\n            ///////////////////\n\n            /((pebble))app/i                                                    // Pebble\n            ], [VENDOR, MODEL, [TYPE, WEARABLE]], [\n            /(watch)(?: ?os[,\\/]|\\d,\\d\\/)[\\d\\.]+/i                              // Apple Watch\n            ], [MODEL, [VENDOR, APPLE], [TYPE, WEARABLE]], [\n            /droid.+; (glass) \\d/i                                              // Google Glass\n            ], [MODEL, [VENDOR, GOOGLE], [TYPE, WEARABLE]], [\n            /droid.+; (wt63?0{2,3})\\)/i\n            ], [MODEL, [VENDOR, ZEBRA], [TYPE, WEARABLE]], [\n            /(quest( 2| pro)?)/i                                                // Oculus Quest\n            ], [MODEL, [VENDOR, FACEBOOK], [TYPE, WEARABLE]], [\n\n            ///////////////////\n            // EMBEDDED\n            ///////////////////\n\n            /(tesla)(?: qtcarbrowser|\\/[-\\w\\.]+)/i                              // Tesla\n            ], [VENDOR, [TYPE, EMBEDDED]], [\n            /(aeobc)\\b/i                                                        // Echo Dot\n            ], [MODEL, [VENDOR, AMAZON], [TYPE, EMBEDDED]], [\n\n            ////////////////////\n            // MIXED (GENERIC)\n            ///////////////////\n\n            /droid .+?; ([^;]+?)(?: bui|\\) applew).+? mobile safari/i           // Android Phones from Unidentified Vendors\n            ], [MODEL, [TYPE, MOBILE]], [\n            /droid .+?; ([^;]+?)(?: bui|\\) applew).+?(?! mobile) safari/i       // Android Tablets from Unidentified Vendors\n            ], [MODEL, [TYPE, TABLET]], [\n            /\\b((tablet|tab)[;\\/]|focus\\/\\d(?!.+mobile))/i                      // Unidentifiable Tablet\n            ], [[TYPE, TABLET]], [\n            /(phone|mobile(?:[;\\/]| [ \\w\\/\\.]*safari)|pda(?=.+windows ce))/i    // Unidentifiable Mobile\n            ], [[TYPE, MOBILE]], [\n            /(android[-\\w\\. ]{0,9});.+buil/i                                    // Generic Android Device\n            ], [MODEL, [VENDOR, 'Generic']]\n        ],\n\n        engine : [[\n\n            /windows.+ edge\\/([\\w\\.]+)/i                                       // EdgeHTML\n            ], [VERSION, [NAME, EDGE+'HTML']], [\n\n            /webkit\\/537\\.36.+chrome\\/(?!27)([\\w\\.]+)/i                         // Blink\n            ], [VERSION, [NAME, 'Blink']], [\n\n            /(presto)\\/([\\w\\.]+)/i,                                             // Presto\n            /(webkit|trident|netfront|netsurf|amaya|lynx|w3m|goanna)\\/([\\w\\.]+)/i, // WebKit/Trident/NetFront/NetSurf/Amaya/Lynx/w3m/Goanna\n            /ekioh(flow)\\/([\\w\\.]+)/i,                                          // Flow\n            /(khtml|tasman|links)[\\/ ]\\(?([\\w\\.]+)/i,                           // KHTML/Tasman/Links\n            /(icab)[\\/ ]([23]\\.[\\d\\.]+)/i,                                      // iCab\n            /\\b(libweb)/i\n            ], [NAME, VERSION], [\n\n            /rv\\:([\\w\\.]{1,9})\\b.+(gecko)/i                                     // Gecko\n            ], [VERSION, NAME]\n        ],\n\n        os : [[\n\n            // Windows\n            /microsoft (windows) (vista|xp)/i                                   // Windows (iTunes)\n            ], [NAME, VERSION], [\n            /(windows) nt 6\\.2; (arm)/i,                                        // Windows RT\n            /(windows (?:phone(?: os)?|mobile))[\\/ ]?([\\d\\.\\w ]*)/i,            // Windows Phone\n            /(windows)[\\/ ]?([ntce\\d\\. ]+\\w)(?!.+xbox)/i\n            ], [NAME, [VERSION, strMapper, windowsVersionMap]], [\n            /(win(?=3|9|n)|win 9x )([nt\\d\\.]+)/i\n            ], [[NAME, 'Windows'], [VERSION, strMapper, windowsVersionMap]], [\n\n            // iOS/macOS\n            /ip[honead]{2,4}\\b(?:.*os ([\\w]+) like mac|; opera)/i,              // iOS\n            /ios;fbsv\\/([\\d\\.]+)/i,\n            /cfnetwork\\/.+darwin/i\n            ], [[VERSION, /_/g, '.'], [NAME, 'iOS']], [\n            /(mac os x) ?([\\w\\. ]*)/i,\n            /(macintosh|mac_powerpc\\b)(?!.+haiku)/i                             // Mac OS\n            ], [[NAME, MAC_OS], [VERSION, /_/g, '.']], [\n\n            // Mobile OSes\n            /droid ([\\w\\.]+)\\b.+(android[- ]x86|harmonyos)/i                    // Android-x86/HarmonyOS\n            ], [VERSION, NAME], [                                               // Android/WebOS/QNX/Bada/RIM/Maemo/MeeGo/Sailfish OS\n            /(android|webos|qnx|bada|rim tablet os|maemo|meego|sailfish)[-\\/ ]?([\\w\\.]*)/i,\n            /(blackberry)\\w*\\/([\\w\\.]*)/i,                                      // Blackberry\n            /(tizen|kaios)[\\/ ]([\\w\\.]+)/i,                                     // Tizen/KaiOS\n            /\\((series40);/i                                                    // Series 40\n            ], [NAME, VERSION], [\n            /\\(bb(10);/i                                                        // BlackBerry 10\n            ], [VERSION, [NAME, BLACKBERRY]], [\n            /(?:symbian ?os|symbos|s60(?=;)|series60)[-\\/ ]?([\\w\\.]*)/i         // Symbian\n            ], [VERSION, [NAME, 'Symbian']], [\n            /mozilla\\/[\\d\\.]+ \\((?:mobile|tablet|tv|mobile; [\\w ]+); rv:.+ gecko\\/([\\w\\.]+)/i // Firefox OS\n            ], [VERSION, [NAME, FIREFOX+' OS']], [\n            /web0s;.+rt(tv)/i,\n            /\\b(?:hp)?wos(?:browser)?\\/([\\w\\.]+)/i                              // WebOS\n            ], [VERSION, [NAME, 'webOS']], [\n            /watch(?: ?os[,\\/]|\\d,\\d\\/)([\\d\\.]+)/i                              // watchOS\n            ], [VERSION, [NAME, 'watchOS']], [\n\n            // Google Chromecast\n            /crkey\\/([\\d\\.]+)/i                                                 // Google Chromecast\n            ], [VERSION, [NAME, CHROME+'cast']], [\n            /(cros) [\\w]+(?:\\)| ([\\w\\.]+)\\b)/i                                  // Chromium OS\n            ], [[NAME, CHROMIUM_OS], VERSION],[\n\n            // Smart TVs\n            /panasonic;(viera)/i,                                               // Panasonic Viera\n            /(netrange)mmh/i,                                                   // Netrange\n            /(nettv)\\/(\\d+\\.[\\w\\.]+)/i,                                         // NetTV\n\n            // Console\n            /(nintendo|playstation) ([wids345portablevuch]+)/i,                 // Nintendo/Playstation\n            /(xbox); +xbox ([^\\);]+)/i,                                         // Microsoft Xbox (360, One, X, S, Series X, Series S)\n\n            // Other\n            /\\b(joli|palm)\\b ?(?:os)?\\/?([\\w\\.]*)/i,                            // Joli/Palm\n            /(mint)[\\/\\(\\) ]?(\\w*)/i,                                           // Mint\n            /(mageia|vectorlinux)[; ]/i,                                        // Mageia/VectorLinux\n            /([kxln]?ubuntu|debian|suse|opensuse|gentoo|arch(?= linux)|slackware|fedora|mandriva|centos|pclinuxos|red ?hat|zenwalk|linpus|raspbian|plan 9|minix|risc os|contiki|deepin|manjaro|elementary os|sabayon|linspire)(?: gnu\\/linux)?(?: enterprise)?(?:[- ]linux)?(?:-gnu)?[-\\/ ]?(?!chrom|package)([-\\w\\.]*)/i,\n                                                                                // Ubuntu/Debian/SUSE/Gentoo/Arch/Slackware/Fedora/Mandriva/CentOS/PCLinuxOS/RedHat/Zenwalk/Linpus/Raspbian/Plan9/Minix/RISCOS/Contiki/Deepin/Manjaro/elementary/Sabayon/Linspire\n            /(hurd|linux) ?([\\w\\.]*)/i,                                         // Hurd/Linux\n            /(gnu) ?([\\w\\.]*)/i,                                                // GNU\n            /\\b([-frentopcghs]{0,5}bsd|dragonfly)[\\/ ]?(?!amd|[ix346]{1,2}86)([\\w\\.]*)/i, // FreeBSD/NetBSD/OpenBSD/PC-BSD/GhostBSD/DragonFly\n            /(haiku) (\\w+)/i                                                    // Haiku\n            ], [NAME, VERSION], [\n            /(sunos) ?([\\w\\.\\d]*)/i                                             // Solaris\n            ], [[NAME, 'Solaris'], VERSION], [\n            /((?:open)?solaris)[-\\/ ]?([\\w\\.]*)/i,                              // Solaris\n            /(aix) ((\\d)(?=\\.|\\)| )[\\w\\.])*/i,                                  // AIX\n            /\\b(beos|os\\/2|amigaos|morphos|openvms|fuchsia|hp-ux|serenityos)/i, // BeOS/OS2/AmigaOS/MorphOS/OpenVMS/Fuchsia/HP-UX/SerenityOS\n            /(unix) ?([\\w\\.]*)/i                                                // UNIX\n            ], [NAME, VERSION]\n        ]\n    };\n\n    /////////////////\n    // Constructor\n    ////////////////\n\n    var UAParser = function (ua, extensions) {\n\n        if (typeof ua === OBJ_TYPE) {\n            extensions = ua;\n            ua = undefined;\n        }\n\n        if (!(this instanceof UAParser)) {\n            return new UAParser(ua, extensions).getResult();\n        }\n\n        var _navigator = (typeof window !== UNDEF_TYPE && window.navigator) ? window.navigator : undefined;\n        var _ua = ua || ((_navigator && _navigator.userAgent) ? _navigator.userAgent : EMPTY);\n        var _uach = (_navigator && _navigator.userAgentData) ? _navigator.userAgentData : undefined;\n        var _rgxmap = extensions ? extend(regexes, extensions) : regexes;\n        var _isSelfNav = _navigator && _navigator.userAgent == _ua;\n\n        this.getBrowser = function () {\n            var _browser = {};\n            _browser[NAME] = undefined;\n            _browser[VERSION] = undefined;\n            rgxMapper.call(_browser, _ua, _rgxmap.browser);\n            _browser[MAJOR] = majorize(_browser[VERSION]);\n            // Brave-specific detection\n            if (_isSelfNav && _navigator && _navigator.brave && typeof _navigator.brave.isBrave == FUNC_TYPE) {\n                _browser[NAME] = 'Brave';\n            }\n            return _browser;\n        };\n        this.getCPU = function () {\n            var _cpu = {};\n            _cpu[ARCHITECTURE] = undefined;\n            rgxMapper.call(_cpu, _ua, _rgxmap.cpu);\n            return _cpu;\n        };\n        this.getDevice = function () {\n            var _device = {};\n            _device[VENDOR] = undefined;\n            _device[MODEL] = undefined;\n            _device[TYPE] = undefined;\n            rgxMapper.call(_device, _ua, _rgxmap.device);\n            if (_isSelfNav && !_device[TYPE] && _uach && _uach.mobile) {\n                _device[TYPE] = MOBILE;\n            }\n            // iPadOS-specific detection: identified as Mac, but has some iOS-only properties\n            if (_isSelfNav && _device[MODEL] == 'Macintosh' && _navigator && typeof _navigator.standalone !== UNDEF_TYPE && _navigator.maxTouchPoints && _navigator.maxTouchPoints > 2) {\n                _device[MODEL] = 'iPad';\n                _device[TYPE] = TABLET;\n            }\n            return _device;\n        };\n        this.getEngine = function () {\n            var _engine = {};\n            _engine[NAME] = undefined;\n            _engine[VERSION] = undefined;\n            rgxMapper.call(_engine, _ua, _rgxmap.engine);\n            return _engine;\n        };\n        this.getOS = function () {\n            var _os = {};\n            _os[NAME] = undefined;\n            _os[VERSION] = undefined;\n            rgxMapper.call(_os, _ua, _rgxmap.os);\n            if (_isSelfNav && !_os[NAME] && _uach && _uach.platform != 'Unknown') {\n                _os[NAME] = _uach.platform  \n                                    .replace(/chrome os/i, CHROMIUM_OS)\n                                    .replace(/macos/i, MAC_OS);           // backward compatibility\n            }\n            return _os;\n        };\n        this.getResult = function () {\n            return {\n                ua      : this.getUA(),\n                browser : this.getBrowser(),\n                engine  : this.getEngine(),\n                os      : this.getOS(),\n                device  : this.getDevice(),\n                cpu     : this.getCPU()\n            };\n        };\n        this.getUA = function () {\n            return _ua;\n        };\n        this.setUA = function (ua) {\n            _ua = (typeof ua === STR_TYPE && ua.length > UA_MAX_LENGTH) ? trim(ua, UA_MAX_LENGTH) : ua;\n            return this;\n        };\n        this.setUA(_ua);\n        return this;\n    };\n\n    UAParser.VERSION = LIBVERSION;\n    UAParser.BROWSER =  enumerize([NAME, VERSION, MAJOR]);\n    UAParser.CPU = enumerize([ARCHITECTURE]);\n    UAParser.DEVICE = enumerize([MODEL, VENDOR, TYPE, CONSOLE, MOBILE, SMARTTV, TABLET, WEARABLE, EMBEDDED]);\n    UAParser.ENGINE = UAParser.OS = enumerize([NAME, VERSION]);\n\n    ///////////\n    // Export\n    //////////\n\n    // check js environment\n    if (typeof(exports) !== UNDEF_TYPE) {\n        // nodejs env\n        if (typeof module !== UNDEF_TYPE && module.exports) {\n            exports = module.exports = UAParser;\n        }\n        exports.UAParser = UAParser;\n    } else {\n        // requirejs env (optional)\n        if (typeof(define) === FUNC_TYPE && define.amd) {\n            define(function () {\n                return UAParser;\n            });\n        } else if (typeof window !== UNDEF_TYPE) {\n            // browser env\n            window.UAParser = UAParser;\n        }\n    }\n\n    // jQuery/Zepto specific (optional)\n    // Note:\n    //   In AMD env the global scope should be kept clean, but jQuery is an exception.\n    //   jQuery always exports to global scope, unless jQuery.noConflict(true) is used,\n    //   and we should catch that.\n    var $ = typeof window !== UNDEF_TYPE && (window.jQuery || window.Zepto);\n    if ($ && !$.ua) {\n        var parser = new UAParser();\n        $.ua = parser.getResult();\n        $.ua.get = function () {\n            return parser.getUA();\n        };\n        $.ua.set = function (ua) {\n            parser.setUA(ua);\n            var result = parser.getResult();\n            for (var prop in result) {\n                $.ua[prop] = result[prop];\n            }\n        };\n    }\n\n})(typeof window === 'object' ? window : this);\n","let wasm;\n\nfunction addToExternrefTable0(obj) {\n    const idx = wasm.__externref_table_alloc();\n    wasm.__wbindgen_export_2.set(idx, obj);\n    return idx;\n}\n\nfunction handleError(f, args) {\n    try {\n        return f.apply(this, args);\n    } catch (e) {\n        const idx = addToExternrefTable0(e);\n        wasm.__wbindgen_exn_store(idx);\n    }\n}\n\nfunction isLikeNone(x) {\n    return x === undefined || x === null;\n}\n\nconst cachedTextDecoder = (typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-8', { ignoreBOM: true, fatal: true }) : { decode: () => { throw Error('TextDecoder not available') } } );\n\nif (typeof TextDecoder !== 'undefined') { cachedTextDecoder.decode(); };\n\nlet cachedUint8ArrayMemory0 = null;\n\nfunction getUint8ArrayMemory0() {\n    if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) {\n        cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer);\n    }\n    return cachedUint8ArrayMemory0;\n}\n\nfunction getStringFromWasm0(ptr, len) {\n    ptr = ptr >>> 0;\n    return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len));\n}\n\nlet WASM_VECTOR_LEN = 0;\n\nfunction passArray8ToWasm0(arg, malloc) {\n    const ptr = malloc(arg.length * 1, 1) >>> 0;\n    getUint8ArrayMemory0().set(arg, ptr / 1);\n    WASM_VECTOR_LEN = arg.length;\n    return ptr;\n}\n\nfunction takeFromExternrefTable0(idx) {\n    const value = wasm.__wbindgen_export_2.get(idx);\n    wasm.__externref_table_dealloc(idx);\n    return value;\n}\n\nconst cachedTextEncoder = (typeof TextEncoder !== 'undefined' ? new TextEncoder('utf-8') : { encode: () => { throw Error('TextEncoder not available') } } );\n\nconst encodeString = (typeof cachedTextEncoder.encodeInto === 'function'\n    ? function (arg, view) {\n    return cachedTextEncoder.encodeInto(arg, view);\n}\n    : function (arg, view) {\n    const buf = cachedTextEncoder.encode(arg);\n    view.set(buf);\n    return {\n        read: arg.length,\n        written: buf.length\n    };\n});\n\nfunction passStringToWasm0(arg, malloc, realloc) {\n\n    if (realloc === undefined) {\n        const buf = cachedTextEncoder.encode(arg);\n        const ptr = malloc(buf.length, 1) >>> 0;\n        getUint8ArrayMemory0().subarray(ptr, ptr + buf.length).set(buf);\n        WASM_VECTOR_LEN = buf.length;\n        return ptr;\n    }\n\n    let len = arg.length;\n    let ptr = malloc(len, 1) >>> 0;\n\n    const mem = getUint8ArrayMemory0();\n\n    let offset = 0;\n\n    for (; offset < len; offset++) {\n        const code = arg.charCodeAt(offset);\n        if (code > 0x7F) break;\n        mem[ptr + offset] = code;\n    }\n\n    if (offset !== len) {\n        if (offset !== 0) {\n            arg = arg.slice(offset);\n        }\n        ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0;\n        const view = getUint8ArrayMemory0().subarray(ptr + offset, ptr + len);\n        const ret = encodeString(arg, view);\n\n        offset += ret.written;\n        ptr = realloc(ptr, len, offset, 1) >>> 0;\n    }\n\n    WASM_VECTOR_LEN = offset;\n    return ptr;\n}\n\nfunction getArrayU8FromWasm0(ptr, len) {\n    ptr = ptr >>> 0;\n    return getUint8ArrayMemory0().subarray(ptr / 1, ptr / 1 + len);\n}\n\nlet cachedUint16ArrayMemory0 = null;\n\nfunction getUint16ArrayMemory0() {\n    if (cachedUint16ArrayMemory0 === null || cachedUint16ArrayMemory0.byteLength === 0) {\n        cachedUint16ArrayMemory0 = new Uint16Array(wasm.memory.buffer);\n    }\n    return cachedUint16ArrayMemory0;\n}\n\nfunction getArrayU16FromWasm0(ptr, len) {\n    ptr = ptr >>> 0;\n    return getUint16ArrayMemory0().subarray(ptr / 2, ptr / 2 + len);\n}\n/**\n * @param {string} key\n * @param {Uint8Array} message\n * @param {string} signature\n */\nexport function verify_signature(key, message, signature) {\n    const ptr0 = passStringToWasm0(key, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);\n    const len0 = WASM_VECTOR_LEN;\n    const ptr1 = passArray8ToWasm0(message, wasm.__wbindgen_malloc);\n    const len1 = WASM_VECTOR_LEN;\n    const ptr2 = passStringToWasm0(signature, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);\n    const len2 = WASM_VECTOR_LEN;\n    const ret = wasm.verify_signature(ptr0, len0, ptr1, len1, ptr2, len2);\n    if (ret[1]) {\n        throw takeFromExternrefTable0(ret[0]);\n    }\n}\n\nexport function main() {\n    wasm.main();\n}\n\nconst AccountFinalization = (typeof FinalizationRegistry === 'undefined')\n    ? { register: () => {}, unregister: () => {} }\n    : new FinalizationRegistry(ptr => wasm.__wbg_account_free(ptr >>> 0, 1));\n\nexport class Account {\n\n    static __wrap(ptr) {\n        ptr = ptr >>> 0;\n        const obj = Object.create(Account.prototype);\n        obj.__wbg_ptr = ptr;\n        AccountFinalization.register(obj, obj.__wbg_ptr, obj);\n        return obj;\n    }\n\n    __destroy_into_raw() {\n        const ptr = this.__wbg_ptr;\n        this.__wbg_ptr = 0;\n        AccountFinalization.unregister(this);\n        return ptr;\n    }\n\n    free() {\n        const ptr = this.__destroy_into_raw();\n        wasm.__wbg_account_free(ptr, 0);\n    }\n    constructor() {\n        const ret = wasm.account_new();\n        this.__wbg_ptr = ret >>> 0;\n        AccountFinalization.register(this, this.__wbg_ptr, this);\n        return this;\n    }\n    /**\n     * @param {string} pickle\n     * @param {Uint8Array} pickle_key\n     * @returns {Account}\n     */\n    static from_pickle(pickle, pickle_key) {\n        const ptr0 = passStringToWasm0(pickle, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);\n        const len0 = WASM_VECTOR_LEN;\n        const ptr1 = passArray8ToWasm0(pickle_key, wasm.__wbindgen_malloc);\n        const len1 = WASM_VECTOR_LEN;\n        const ret = wasm.account_from_pickle(ptr0, len0, ptr1, len1);\n        if (ret[2]) {\n            throw takeFromExternrefTable0(ret[1]);\n        }\n        return Account.__wrap(ret[0]);\n    }\n    /**\n     * @param {string} pickle\n     * @param {Uint8Array} pickle_key\n     * @returns {Account}\n     */\n    static from_libolm_pickle(pickle, pickle_key) {\n        const ptr0 = passStringToWasm0(pickle, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);\n        const len0 = WASM_VECTOR_LEN;\n        const ptr1 = passArray8ToWasm0(pickle_key, wasm.__wbindgen_malloc);\n        const len1 = WASM_VECTOR_LEN;\n        const ret = wasm.account_from_libolm_pickle(ptr0, len0, ptr1, len1);\n        if (ret[2]) {\n            throw takeFromExternrefTable0(ret[1]);\n        }\n        return Account.__wrap(ret[0]);\n    }\n    /**\n     * @param {Uint8Array} pickle_key\n     * @returns {string}\n     */\n    pickle(pickle_key) {\n        let deferred3_0;\n        let deferred3_1;\n        try {\n            const ptr0 = passArray8ToWasm0(pickle_key, wasm.__wbindgen_malloc);\n            const len0 = WASM_VECTOR_LEN;\n            const ret = wasm.account_pickle(this.__wbg_ptr, ptr0, len0);\n            var ptr2 = ret[0];\n            var len2 = ret[1];\n            if (ret[3]) {\n                ptr2 = 0; len2 = 0;\n                throw takeFromExternrefTable0(ret[2]);\n            }\n            deferred3_0 = ptr2;\n            deferred3_1 = len2;\n            return getStringFromWasm0(ptr2, len2);\n        } finally {\n            wasm.__wbindgen_free(deferred3_0, deferred3_1, 1);\n        }\n    }\n    /**\n     * @returns {string}\n     */\n    get ed25519_key() {\n        let deferred1_0;\n        let deferred1_1;\n        try {\n            const ret = wasm.account_ed25519_key(this.__wbg_ptr);\n            deferred1_0 = ret[0];\n            deferred1_1 = ret[1];\n            return getStringFromWasm0(ret[0], ret[1]);\n        } finally {\n            wasm.__wbindgen_free(deferred1_0, deferred1_1, 1);\n        }\n    }\n    /**\n     * @returns {string}\n     */\n    get curve25519_key() {\n        let deferred1_0;\n        let deferred1_1;\n        try {\n            const ret = wasm.account_curve25519_key(this.__wbg_ptr);\n            deferred1_0 = ret[0];\n            deferred1_1 = ret[1];\n            return getStringFromWasm0(ret[0], ret[1]);\n        } finally {\n            wasm.__wbindgen_free(deferred1_0, deferred1_1, 1);\n        }\n    }\n    /**\n     * @param {string} message\n     * @returns {string}\n     */\n    sign(message) {\n        let deferred2_0;\n        let deferred2_1;\n        try {\n            const ptr0 = passStringToWasm0(message, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);\n            const len0 = WASM_VECTOR_LEN;\n            const ret = wasm.account_sign(this.__wbg_ptr, ptr0, len0);\n            deferred2_0 = ret[0];\n            deferred2_1 = ret[1];\n            return getStringFromWasm0(ret[0], ret[1]);\n        } finally {\n            wasm.__wbindgen_free(deferred2_0, deferred2_1, 1);\n        }\n    }\n    /**\n     * @returns {number}\n     */\n    get max_number_of_one_time_keys() {\n        const ret = wasm.account_max_number_of_one_time_keys(this.__wbg_ptr);\n        return ret >>> 0;\n    }\n    /**\n     * @returns {any}\n     */\n    get one_time_keys() {\n        const ret = wasm.account_one_time_keys(this.__wbg_ptr);\n        if (ret[2]) {\n            throw takeFromExternrefTable0(ret[1]);\n        }\n        return takeFromExternrefTable0(ret[0]);\n    }\n    /**\n     * @param {number} count\n     */\n    generate_one_time_keys(count) {\n        wasm.account_generate_one_time_keys(this.__wbg_ptr, count);\n    }\n    /**\n     * @returns {any}\n     */\n    get fallback_key() {\n        const ret = wasm.account_fallback_key(this.__wbg_ptr);\n        if (ret[2]) {\n            throw takeFromExternrefTable0(ret[1]);\n        }\n        return takeFromExternrefTable0(ret[0]);\n    }\n    /**\n     * @returns {boolean}\n     */\n    forget_fallback_key() {\n        const ret = wasm.account_forget_fallback_key(this.__wbg_ptr);\n        return ret !== 0;\n    }\n    generate_fallback_key() {\n        wasm.account_generate_fallback_key(this.__wbg_ptr);\n    }\n    mark_keys_as_published() {\n        wasm.account_mark_keys_as_published(this.__wbg_ptr);\n    }\n    /**\n     * @param {string} identity_key\n     * @param {string} one_time_key\n     * @returns {Session}\n     */\n    create_outbound_session(identity_key, one_time_key) {\n        const ptr0 = passStringToWasm0(identity_key, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);\n        const len0 = WASM_VECTOR_LEN;\n        const ptr1 = passStringToWasm0(one_time_key, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);\n        const len1 = WASM_VECTOR_LEN;\n        const ret = wasm.account_create_outbound_session(this.__wbg_ptr, ptr0, len0, ptr1, len1);\n        if (ret[2]) {\n            throw takeFromExternrefTable0(ret[1]);\n        }\n        return Session.__wrap(ret[0]);\n    }\n    /**\n     * @param {string} identity_key\n     * @param {number} message_type\n     * @param {string} ciphertext\n     * @returns {InboundCreationResult}\n     */\n    create_inbound_session(identity_key, message_type, ciphertext) {\n        const ptr0 = passStringToWasm0(identity_key, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);\n        const len0 = WASM_VECTOR_LEN;\n        const ptr1 = passStringToWasm0(ciphertext, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);\n        const len1 = WASM_VECTOR_LEN;\n        const ret = wasm.account_create_inbound_session(this.__wbg_ptr, ptr0, len0, message_type, ptr1, len1);\n        if (ret[2]) {\n            throw takeFromExternrefTable0(ret[1]);\n        }\n        return InboundCreationResult.__wrap(ret[0]);\n    }\n}\n\nconst DecryptedMessageFinalization = (typeof FinalizationRegistry === 'undefined')\n    ? { register: () => {}, unregister: () => {} }\n    : new FinalizationRegistry(ptr => wasm.__wbg_decryptedmessage_free(ptr >>> 0, 1));\n\nexport class DecryptedMessage {\n\n    static __wrap(ptr) {\n        ptr = ptr >>> 0;\n        const obj = Object.create(DecryptedMessage.prototype);\n        obj.__wbg_ptr = ptr;\n        DecryptedMessageFinalization.register(obj, obj.__wbg_ptr, obj);\n        return obj;\n    }\n\n    __destroy_into_raw() {\n        const ptr = this.__wbg_ptr;\n        this.__wbg_ptr = 0;\n        DecryptedMessageFinalization.unregister(this);\n        return ptr;\n    }\n\n    free() {\n        const ptr = this.__destroy_into_raw();\n        wasm.__wbg_decryptedmessage_free(ptr, 0);\n    }\n    /**\n     * @returns {Uint8Array}\n     */\n    get plaintext() {\n        const ret = wasm.__wbg_get_decryptedmessage_plaintext(this.__wbg_ptr);\n        var v1 = getArrayU8FromWasm0(ret[0], ret[1]).slice();\n        wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);\n        return v1;\n    }\n    /**\n     * @param {Uint8Array} arg0\n     */\n    set plaintext(arg0) {\n        const ptr0 = passArray8ToWasm0(arg0, wasm.__wbindgen_malloc);\n        const len0 = WASM_VECTOR_LEN;\n        wasm.__wbg_set_decryptedmessage_plaintext(this.__wbg_ptr, ptr0, len0);\n    }\n    /**\n     * @returns {number}\n     */\n    get message_index() {\n        const ret = wasm.__wbg_get_decryptedmessage_message_index(this.__wbg_ptr);\n        return ret >>> 0;\n    }\n    /**\n     * @param {number} arg0\n     */\n    set message_index(arg0) {\n        wasm.__wbg_set_decryptedmessage_message_index(this.__wbg_ptr, arg0);\n    }\n}\n\nconst EncryptedOlmMessageFinalization = (typeof FinalizationRegistry === 'undefined')\n    ? { register: () => {}, unregister: () => {} }\n    : new FinalizationRegistry(ptr => wasm.__wbg_encryptedolmmessage_free(ptr >>> 0, 1));\n\nexport class EncryptedOlmMessage {\n\n    static __wrap(ptr) {\n        ptr = ptr >>> 0;\n        const obj = Object.create(EncryptedOlmMessage.prototype);\n        obj.__wbg_ptr = ptr;\n        EncryptedOlmMessageFinalization.register(obj, obj.__wbg_ptr, obj);\n        return obj;\n    }\n\n    __destroy_into_raw() {\n        const ptr = this.__wbg_ptr;\n        this.__wbg_ptr = 0;\n        EncryptedOlmMessageFinalization.unregister(this);\n        return ptr;\n    }\n\n    free() {\n        const ptr = this.__destroy_into_raw();\n        wasm.__wbg_encryptedolmmessage_free(ptr, 0);\n    }\n    /**\n     * @returns {string}\n     */\n    get ciphertext() {\n        let deferred1_0;\n        let deferred1_1;\n        try {\n            const ret = wasm.__wbg_get_encryptedolmmessage_ciphertext(this.__wbg_ptr);\n            deferred1_0 = ret[0];\n            deferred1_1 = ret[1];\n            return getStringFromWasm0(ret[0], ret[1]);\n        } finally {\n            wasm.__wbindgen_free(deferred1_0, deferred1_1, 1);\n        }\n    }\n    /**\n     * @param {string} arg0\n     */\n    set ciphertext(arg0) {\n        const ptr0 = passStringToWasm0(arg0, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);\n        const len0 = WASM_VECTOR_LEN;\n        wasm.__wbg_set_encryptedolmmessage_ciphertext(this.__wbg_ptr, ptr0, len0);\n    }\n    /**\n     * @returns {number}\n     */\n    get message_type() {\n        const ret = wasm.__wbg_get_encryptedolmmessage_message_type(this.__wbg_ptr);\n        return ret >>> 0;\n    }\n    /**\n     * @param {number} arg0\n     */\n    set message_type(arg0) {\n        wasm.__wbg_set_encryptedolmmessage_message_type(this.__wbg_ptr, arg0);\n    }\n}\n\nconst EstablishedSasFinalization = (typeof FinalizationRegistry === 'undefined')\n    ? { register: () => {}, unregister: () => {} }\n    : new FinalizationRegistry(ptr => wasm.__wbg_establishedsas_free(ptr >>> 0, 1));\n\nexport class EstablishedSas {\n\n    static __wrap(ptr) {\n        ptr = ptr >>> 0;\n        const obj = Object.create(EstablishedSas.prototype);\n        obj.__wbg_ptr = ptr;\n        EstablishedSasFinalization.register(obj, obj.__wbg_ptr, obj);\n        return obj;\n    }\n\n    __destroy_into_raw() {\n        const ptr = this.__wbg_ptr;\n        this.__wbg_ptr = 0;\n        EstablishedSasFinalization.unregister(this);\n        return ptr;\n    }\n\n    free() {\n        const ptr = this.__destroy_into_raw();\n        wasm.__wbg_establishedsas_free(ptr, 0);\n    }\n    /**\n     * @param {string} info\n     * @returns {SasBytes}\n     */\n    bytes(info) {\n        const ptr0 = passStringToWasm0(info, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);\n        const len0 = WASM_VECTOR_LEN;\n        const ret = wasm.establishedsas_bytes(this.__wbg_ptr, ptr0, len0);\n        return SasBytes.__wrap(ret);\n    }\n    /**\n     * @param {string} input\n     * @param {string} info\n     * @returns {string}\n     */\n    calculate_mac(input, info) {\n        let deferred3_0;\n        let deferred3_1;\n        try {\n            const ptr0 = passStringToWasm0(input, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);\n            const len0 = WASM_VECTOR_LEN;\n            const ptr1 = passStringToWasm0(info, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);\n            const len1 = WASM_VECTOR_LEN;\n            const ret = wasm.establishedsas_calculate_mac(this.__wbg_ptr, ptr0, len0, ptr1, len1);\n            deferred3_0 = ret[0];\n            deferred3_1 = ret[1];\n            return getStringFromWasm0(ret[0], ret[1]);\n        } finally {\n            wasm.__wbindgen_free(deferred3_0, deferred3_1, 1);\n        }\n    }\n    /**\n     * @param {string} input\n     * @param {string} info\n     * @returns {string}\n     */\n    calculate_mac_invalid_base64(input, info) {\n        let deferred3_0;\n        let deferred3_1;\n        try {\n            const ptr0 = passStringToWasm0(input, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);\n            const len0 = WASM_VECTOR_LEN;\n            const ptr1 = passStringToWasm0(info, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);\n            const len1 = WASM_VECTOR_LEN;\n            const ret = wasm.establishedsas_calculate_mac_invalid_base64(this.__wbg_ptr, ptr0, len0, ptr1, len1);\n            deferred3_0 = ret[0];\n            deferred3_1 = ret[1];\n            return getStringFromWasm0(ret[0], ret[1]);\n        } finally {\n            wasm.__wbindgen_free(deferred3_0, deferred3_1, 1);\n        }\n    }\n    /**\n     * @param {string} input\n     * @param {string} info\n     * @param {string} tag\n     */\n    verify_mac(input, info, tag) {\n        const ptr0 = passStringToWasm0(input, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);\n        const len0 = WASM_VECTOR_LEN;\n        const ptr1 = passStringToWasm0(info, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);\n        const len1 = WASM_VECTOR_LEN;\n        const ptr2 = passStringToWasm0(tag, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);\n        const len2 = WASM_VECTOR_LEN;\n        const ret = wasm.establishedsas_verify_mac(this.__wbg_ptr, ptr0, len0, ptr1, len1, ptr2, len2);\n        if (ret[1]) {\n            throw takeFromExternrefTable0(ret[0]);\n        }\n    }\n}\n\nconst GroupSessionFinalization = (typeof FinalizationRegistry === 'undefined')\n    ? { register: () => {}, unregister: () => {} }\n    : new FinalizationRegistry(ptr => wasm.__wbg_groupsession_free(ptr >>> 0, 1));\n\nexport class GroupSession {\n\n    static __wrap(ptr) {\n        ptr = ptr >>> 0;\n        const obj = Object.create(GroupSession.prototype);\n        obj.__wbg_ptr = ptr;\n        GroupSessionFinalization.register(obj, obj.__wbg_ptr, obj);\n        return obj;\n    }\n\n    __destroy_into_raw() {\n        const ptr = this.__wbg_ptr;\n        this.__wbg_ptr = 0;\n        GroupSessionFinalization.unregister(this);\n        return ptr;\n    }\n\n    free() {\n        const ptr = this.__destroy_into_raw();\n        wasm.__wbg_groupsession_free(ptr, 0);\n    }\n    constructor() {\n        const ret = wasm.groupsession_new();\n        this.__wbg_ptr = ret >>> 0;\n        GroupSessionFinalization.register(this, this.__wbg_ptr, this);\n        return this;\n    }\n    /**\n     * @returns {string}\n     */\n    get session_id() {\n        let deferred1_0;\n        let deferred1_1;\n        try {\n            const ret = wasm.groupsession_session_id(this.__wbg_ptr);\n            deferred1_0 = ret[0];\n            deferred1_1 = ret[1];\n            return getStringFromWasm0(ret[0], ret[1]);\n        } finally {\n            wasm.__wbindgen_free(deferred1_0, deferred1_1, 1);\n        }\n    }\n    /**\n     * @returns {string}\n     */\n    get session_key() {\n        let deferred1_0;\n        let deferred1_1;\n        try {\n            const ret = wasm.groupsession_session_key(this.__wbg_ptr);\n            deferred1_0 = ret[0];\n            deferred1_1 = ret[1];\n            return getStringFromWasm0(ret[0], ret[1]);\n        } finally {\n            wasm.__wbindgen_free(deferred1_0, deferred1_1, 1);\n        }\n    }\n    /**\n     * @returns {number}\n     */\n    get message_index() {\n        const ret = wasm.groupsession_message_index(this.__wbg_ptr);\n        return ret >>> 0;\n    }\n    /**\n     * @param {Uint8Array} plaintext\n     * @returns {string}\n     */\n    encrypt(plaintext) {\n        let deferred2_0;\n        let deferred2_1;\n        try {\n            const ptr0 = passArray8ToWasm0(plaintext, wasm.__wbindgen_malloc);\n            const len0 = WASM_VECTOR_LEN;\n            const ret = wasm.groupsession_encrypt(this.__wbg_ptr, ptr0, len0);\n            deferred2_0 = ret[0];\n            deferred2_1 = ret[1];\n            return getStringFromWasm0(ret[0], ret[1]);\n        } finally {\n            wasm.__wbindgen_free(deferred2_0, deferred2_1, 1);\n        }\n    }\n    /**\n     * @param {Uint8Array} pickle_key\n     * @returns {string}\n     */\n    pickle(pickle_key) {\n        let deferred3_0;\n        let deferred3_1;\n        try {\n            const ptr0 = passArray8ToWasm0(pickle_key, wasm.__wbindgen_malloc);\n            const len0 = WASM_VECTOR_LEN;\n            const ret = wasm.groupsession_pickle(this.__wbg_ptr, ptr0, len0);\n            var ptr2 = ret[0];\n            var len2 = ret[1];\n            if (ret[3]) {\n                ptr2 = 0; len2 = 0;\n                throw takeFromExternrefTable0(ret[2]);\n            }\n            deferred3_0 = ptr2;\n            deferred3_1 = len2;\n            return getStringFromWasm0(ptr2, len2);\n        } finally {\n            wasm.__wbindgen_free(deferred3_0, deferred3_1, 1);\n        }\n    }\n    /**\n     * @param {string} pickle\n     * @param {Uint8Array} pickle_key\n     * @returns {GroupSession}\n     */\n    static from_pickle(pickle, pickle_key) {\n        const ptr0 = passStringToWasm0(pickle, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);\n        const len0 = WASM_VECTOR_LEN;\n        const ptr1 = passArray8ToWasm0(pickle_key, wasm.__wbindgen_malloc);\n        const len1 = WASM_VECTOR_LEN;\n        const ret = wasm.groupsession_from_pickle(ptr0, len0, ptr1, len1);\n        if (ret[2]) {\n            throw takeFromExternrefTable0(ret[1]);\n        }\n        return GroupSession.__wrap(ret[0]);\n    }\n}\n\nconst InboundCreationResultFinalization = (typeof FinalizationRegistry === 'undefined')\n    ? { register: () => {}, unregister: () => {} }\n    : new FinalizationRegistry(ptr => wasm.__wbg_inboundcreationresult_free(ptr >>> 0, 1));\n\nexport class InboundCreationResult {\n\n    static __wrap(ptr) {\n        ptr = ptr >>> 0;\n        const obj = Object.create(InboundCreationResult.prototype);\n        obj.__wbg_ptr = ptr;\n        InboundCreationResultFinalization.register(obj, obj.__wbg_ptr, obj);\n        return obj;\n    }\n\n    __destroy_into_raw() {\n        const ptr = this.__wbg_ptr;\n        this.__wbg_ptr = 0;\n        InboundCreationResultFinalization.unregister(this);\n        return ptr;\n    }\n\n    free() {\n        const ptr = this.__destroy_into_raw();\n        wasm.__wbg_inboundcreationresult_free(ptr, 0);\n    }\n    /**\n     * @returns {Session}\n     */\n    get session() {\n        const ptr = this.__destroy_into_raw();\n        const ret = wasm.inboundcreationresult_session(ptr);\n        return Session.__wrap(ret);\n    }\n    /**\n     * @returns {Uint8Array}\n     */\n    get plaintext() {\n        const ret = wasm.inboundcreationresult_plaintext(this.__wbg_ptr);\n        var v1 = getArrayU8FromWasm0(ret[0], ret[1]).slice();\n        wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);\n        return v1;\n    }\n}\n\nconst InboundGroupSessionFinalization = (typeof FinalizationRegistry === 'undefined')\n    ? { register: () => {}, unregister: () => {} }\n    : new FinalizationRegistry(ptr => wasm.__wbg_inboundgroupsession_free(ptr >>> 0, 1));\n\nexport class InboundGroupSession {\n\n    static __wrap(ptr) {\n        ptr = ptr >>> 0;\n        const obj = Object.create(InboundGroupSession.prototype);\n        obj.__wbg_ptr = ptr;\n        InboundGroupSessionFinalization.register(obj, obj.__wbg_ptr, obj);\n        return obj;\n    }\n\n    __destroy_into_raw() {\n        const ptr = this.__wbg_ptr;\n        this.__wbg_ptr = 0;\n        InboundGroupSessionFinalization.unregister(this);\n        return ptr;\n    }\n\n    free() {\n        const ptr = this.__destroy_into_raw();\n        wasm.__wbg_inboundgroupsession_free(ptr, 0);\n    }\n    /**\n     * @param {string} session_key\n     */\n    constructor(session_key) {\n        const ptr0 = passStringToWasm0(session_key, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);\n        const len0 = WASM_VECTOR_LEN;\n        const ret = wasm.inboundgroupsession_new(ptr0, len0);\n        if (ret[2]) {\n            throw takeFromExternrefTable0(ret[1]);\n        }\n        this.__wbg_ptr = ret[0] >>> 0;\n        InboundGroupSessionFinalization.register(this, this.__wbg_ptr, this);\n        return this;\n    }\n    /**\n     * @param {string} session_key\n     * @returns {InboundGroupSession}\n     */\n    static import(session_key) {\n        const ptr0 = passStringToWasm0(session_key, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);\n        const len0 = WASM_VECTOR_LEN;\n        const ret = wasm.inboundgroupsession_import(ptr0, len0);\n        if (ret[2]) {\n            throw takeFromExternrefTable0(ret[1]);\n        }\n        return InboundGroupSession.__wrap(ret[0]);\n    }\n    /**\n     * @returns {string}\n     */\n    get session_id() {\n        let deferred1_0;\n        let deferred1_1;\n        try {\n            const ret = wasm.inboundgroupsession_session_id(this.__wbg_ptr);\n            deferred1_0 = ret[0];\n            deferred1_1 = ret[1];\n            return getStringFromWasm0(ret[0], ret[1]);\n        } finally {\n            wasm.__wbindgen_free(deferred1_0, deferred1_1, 1);\n        }\n    }\n    /**\n     * @returns {number}\n     */\n    get first_known_index() {\n        const ret = wasm.inboundgroupsession_first_known_index(this.__wbg_ptr);\n        return ret >>> 0;\n    }\n    /**\n     * @param {number} index\n     * @returns {string | undefined}\n     */\n    export_at(index) {\n        const ret = wasm.inboundgroupsession_export_at(this.__wbg_ptr, index);\n        let v1;\n        if (ret[0] !== 0) {\n            v1 = getStringFromWasm0(ret[0], ret[1]).slice();\n            wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);\n        }\n        return v1;\n    }\n    /**\n     * @param {string} ciphertext\n     * @returns {DecryptedMessage}\n     */\n    decrypt(ciphertext) {\n        const ptr0 = passStringToWasm0(ciphertext, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);\n        const len0 = WASM_VECTOR_LEN;\n        const ret = wasm.inboundgroupsession_decrypt(this.__wbg_ptr, ptr0, len0);\n        if (ret[2]) {\n            throw takeFromExternrefTable0(ret[1]);\n        }\n        return DecryptedMessage.__wrap(ret[0]);\n    }\n    /**\n     * @param {Uint8Array} pickle_key\n     * @returns {string}\n     */\n    pickle(pickle_key) {\n        let deferred3_0;\n        let deferred3_1;\n        try {\n            const ptr0 = passArray8ToWasm0(pickle_key, wasm.__wbindgen_malloc);\n            const len0 = WASM_VECTOR_LEN;\n            const ret = wasm.inboundgroupsession_pickle(this.__wbg_ptr, ptr0, len0);\n            var ptr2 = ret[0];\n            var len2 = ret[1];\n            if (ret[3]) {\n                ptr2 = 0; len2 = 0;\n                throw takeFromExternrefTable0(ret[2]);\n            }\n            deferred3_0 = ptr2;\n            deferred3_1 = len2;\n            return getStringFromWasm0(ptr2, len2);\n        } finally {\n            wasm.__wbindgen_free(deferred3_0, deferred3_1, 1);\n        }\n    }\n    /**\n     * @param {string} pickle\n     * @param {Uint8Array} pickle_key\n     * @returns {InboundGroupSession}\n     */\n    static from_pickle(pickle, pickle_key) {\n        const ptr0 = passStringToWasm0(pickle, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);\n        const len0 = WASM_VECTOR_LEN;\n        const ptr1 = passArray8ToWasm0(pickle_key, wasm.__wbindgen_malloc);\n        const len1 = WASM_VECTOR_LEN;\n        const ret = wasm.inboundgroupsession_from_pickle(ptr0, len0, ptr1, len1);\n        if (ret[2]) {\n            throw takeFromExternrefTable0(ret[1]);\n        }\n        return InboundGroupSession.__wrap(ret[0]);\n    }\n    /**\n     * @param {string} pickle\n     * @param {Uint8Array} pickle_key\n     * @returns {InboundGroupSession}\n     */\n    static from_libolm_pickle(pickle, pickle_key) {\n        const ptr0 = passStringToWasm0(pickle, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);\n        const len0 = WASM_VECTOR_LEN;\n        const ptr1 = passArray8ToWasm0(pickle_key, wasm.__wbindgen_malloc);\n        const len1 = WASM_VECTOR_LEN;\n        const ret = wasm.inboundgroupsession_from_libolm_pickle(ptr0, len0, ptr1, len1);\n        if (ret[2]) {\n            throw takeFromExternrefTable0(ret[1]);\n        }\n        return InboundGroupSession.__wrap(ret[0]);\n    }\n}\n\nconst SasFinalization = (typeof FinalizationRegistry === 'undefined')\n    ? { register: () => {}, unregister: () => {} }\n    : new FinalizationRegistry(ptr => wasm.__wbg_sas_free(ptr >>> 0, 1));\n\nexport class Sas {\n\n    __destroy_into_raw() {\n        const ptr = this.__wbg_ptr;\n        this.__wbg_ptr = 0;\n        SasFinalization.unregister(this);\n        return ptr;\n    }\n\n    free() {\n        const ptr = this.__destroy_into_raw();\n        wasm.__wbg_sas_free(ptr, 0);\n    }\n    constructor() {\n        const ret = wasm.sas_new();\n        this.__wbg_ptr = ret >>> 0;\n        SasFinalization.register(this, this.__wbg_ptr, this);\n        return this;\n    }\n    /**\n     * @returns {string}\n     */\n    get public_key() {\n        let deferred1_0;\n        let deferred1_1;\n        try {\n            const ret = wasm.sas_public_key(this.__wbg_ptr);\n            deferred1_0 = ret[0];\n            deferred1_1 = ret[1];\n            return getStringFromWasm0(ret[0], ret[1]);\n        } finally {\n            wasm.__wbindgen_free(deferred1_0, deferred1_1, 1);\n        }\n    }\n    /**\n     * @param {string} key\n     * @returns {EstablishedSas}\n     */\n    diffie_hellman(key) {\n        const ptr = this.__destroy_into_raw();\n        const ptr0 = passStringToWasm0(key, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);\n        const len0 = WASM_VECTOR_LEN;\n        const ret = wasm.sas_diffie_hellman(ptr, ptr0, len0);\n        if (ret[2]) {\n            throw takeFromExternrefTable0(ret[1]);\n        }\n        return EstablishedSas.__wrap(ret[0]);\n    }\n}\n\nconst SasBytesFinalization = (typeof FinalizationRegistry === 'undefined')\n    ? { register: () => {}, unregister: () => {} }\n    : new FinalizationRegistry(ptr => wasm.__wbg_sasbytes_free(ptr >>> 0, 1));\n\nexport class SasBytes {\n\n    static __wrap(ptr) {\n        ptr = ptr >>> 0;\n        const obj = Object.create(SasBytes.prototype);\n        obj.__wbg_ptr = ptr;\n        SasBytesFinalization.register(obj, obj.__wbg_ptr, obj);\n        return obj;\n    }\n\n    __destroy_into_raw() {\n        const ptr = this.__wbg_ptr;\n        this.__wbg_ptr = 0;\n        SasBytesFinalization.unregister(this);\n        return ptr;\n    }\n\n    free() {\n        const ptr = this.__destroy_into_raw();\n        wasm.__wbg_sasbytes_free(ptr, 0);\n    }\n    /**\n     * @returns {Uint8Array}\n     */\n    get emoji_indices() {\n        const ret = wasm.sasbytes_emoji_indices(this.__wbg_ptr);\n        var v1 = getArrayU8FromWasm0(ret[0], ret[1]).slice();\n        wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);\n        return v1;\n    }\n    /**\n     * @returns {Uint16Array}\n     */\n    get decimals() {\n        const ret = wasm.sasbytes_decimals(this.__wbg_ptr);\n        var v1 = getArrayU16FromWasm0(ret[0], ret[1]).slice();\n        wasm.__wbindgen_free(ret[0], ret[1] * 2, 2);\n        return v1;\n    }\n}\n\nconst SessionFinalization = (typeof FinalizationRegistry === 'undefined')\n    ? { register: () => {}, unregister: () => {} }\n    : new FinalizationRegistry(ptr => wasm.__wbg_session_free(ptr >>> 0, 1));\n\nexport class Session {\n\n    static __wrap(ptr) {\n        ptr = ptr >>> 0;\n        const obj = Object.create(Session.prototype);\n        obj.__wbg_ptr = ptr;\n        SessionFinalization.register(obj, obj.__wbg_ptr, obj);\n        return obj;\n    }\n\n    __destroy_into_raw() {\n        const ptr = this.__wbg_ptr;\n        this.__wbg_ptr = 0;\n        SessionFinalization.unregister(this);\n        return ptr;\n    }\n\n    free() {\n        const ptr = this.__destroy_into_raw();\n        wasm.__wbg_session_free(ptr, 0);\n    }\n    /**\n     * @param {Uint8Array} pickle_key\n     * @returns {string}\n     */\n    pickle(pickle_key) {\n        let deferred3_0;\n        let deferred3_1;\n        try {\n            const ptr0 = passArray8ToWasm0(pickle_key, wasm.__wbindgen_malloc);\n            const len0 = WASM_VECTOR_LEN;\n            const ret = wasm.session_pickle(this.__wbg_ptr, ptr0, len0);\n            var ptr2 = ret[0];\n            var len2 = ret[1];\n            if (ret[3]) {\n                ptr2 = 0; len2 = 0;\n                throw takeFromExternrefTable0(ret[2]);\n            }\n            deferred3_0 = ptr2;\n            deferred3_1 = len2;\n            return getStringFromWasm0(ptr2, len2);\n        } finally {\n            wasm.__wbindgen_free(deferred3_0, deferred3_1, 1);\n        }\n    }\n    /**\n     * @param {string} pickle\n     * @param {Uint8Array} pickle_key\n     * @returns {Session}\n     */\n    static from_pickle(pickle, pickle_key) {\n        const ptr0 = passStringToWasm0(pickle, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);\n        const len0 = WASM_VECTOR_LEN;\n        const ptr1 = passArray8ToWasm0(pickle_key, wasm.__wbindgen_malloc);\n        const len1 = WASM_VECTOR_LEN;\n        const ret = wasm.session_from_pickle(ptr0, len0, ptr1, len1);\n        if (ret[2]) {\n            throw takeFromExternrefTable0(ret[1]);\n        }\n        return Session.__wrap(ret[0]);\n    }\n    /**\n     * @param {string} pickle\n     * @param {Uint8Array} pickle_key\n     * @returns {Session}\n     */\n    static from_libolm_pickle(pickle, pickle_key) {\n        const ptr0 = passStringToWasm0(pickle, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);\n        const len0 = WASM_VECTOR_LEN;\n        const ptr1 = passArray8ToWasm0(pickle_key, wasm.__wbindgen_malloc);\n        const len1 = WASM_VECTOR_LEN;\n        const ret = wasm.session_from_libolm_pickle(ptr0, len0, ptr1, len1);\n        if (ret[2]) {\n            throw takeFromExternrefTable0(ret[1]);\n        }\n        return Session.__wrap(ret[0]);\n    }\n    /**\n     * @returns {string}\n     */\n    get session_id() {\n        let deferred1_0;\n        let deferred1_1;\n        try {\n            const ret = wasm.session_session_id(this.__wbg_ptr);\n            deferred1_0 = ret[0];\n            deferred1_1 = ret[1];\n            return getStringFromWasm0(ret[0], ret[1]);\n        } finally {\n            wasm.__wbindgen_free(deferred1_0, deferred1_1, 1);\n        }\n    }\n    /**\n     * @param {number} message_type\n     * @param {string} ciphertext\n     * @returns {boolean}\n     */\n    session_matches(message_type, ciphertext) {\n        const ptr0 = passStringToWasm0(ciphertext, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);\n        const len0 = WASM_VECTOR_LEN;\n        const ret = wasm.session_session_matches(this.__wbg_ptr, message_type, ptr0, len0);\n        return ret !== 0;\n    }\n    /**\n     * @param {Uint8Array} plaintext\n     * @returns {EncryptedOlmMessage}\n     */\n    encrypt(plaintext) {\n        const ptr0 = passArray8ToWasm0(plaintext, wasm.__wbindgen_malloc);\n        const len0 = WASM_VECTOR_LEN;\n        const ret = wasm.session_encrypt(this.__wbg_ptr, ptr0, len0);\n        return EncryptedOlmMessage.__wrap(ret);\n    }\n    /**\n     * @param {number} message_type\n     * @param {string} ciphertext\n     * @returns {Uint8Array}\n     */\n    decrypt(message_type, ciphertext) {\n        const ptr0 = passStringToWasm0(ciphertext, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);\n        const len0 = WASM_VECTOR_LEN;\n        const ret = wasm.session_decrypt(this.__wbg_ptr, message_type, ptr0, len0);\n        if (ret[3]) {\n            throw takeFromExternrefTable0(ret[2]);\n        }\n        var v2 = getArrayU8FromWasm0(ret[0], ret[1]).slice();\n        wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);\n        return v2;\n    }\n    /**\n     * @returns {boolean}\n     */\n    has_received_message() {\n        const ret = wasm.session_has_received_message(this.__wbg_ptr);\n        return ret !== 0;\n    }\n}\n\nasync function __wbg_load(module, imports) {\n    if (typeof Response === 'function' && module instanceof Response) {\n        if (typeof WebAssembly.instantiateStreaming === 'function') {\n            try {\n                return await WebAssembly.instantiateStreaming(module, imports);\n\n            } catch (e) {\n                if (module.headers.get('Content-Type') != 'application/wasm') {\n                    console.warn(\"`WebAssembly.instantiateStreaming` failed because your server does not serve Wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\\n\", e);\n\n                } else {\n                    throw e;\n                }\n            }\n        }\n\n        const bytes = await module.arrayBuffer();\n        return await WebAssembly.instantiate(bytes, imports);\n\n    } else {\n        const instance = await WebAssembly.instantiate(module, imports);\n\n        if (instance instanceof WebAssembly.Instance) {\n            return { instance, module };\n\n        } else {\n            return instance;\n        }\n    }\n}\n\nfunction __wbg_get_imports() {\n    const imports = {};\n    imports.wbg = {};\n    imports.wbg.__wbg_appendChild_8204974b7328bf98 = function() { return handleError(function (arg0, arg1) {\n        const ret = arg0.appendChild(arg1);\n        return ret;\n    }, arguments) };\n    imports.wbg.__wbg_body_942ea927546a04ba = function(arg0) {\n        const ret = arg0.body;\n        return isLikeNone(ret) ? 0 : addToExternrefTable0(ret);\n    };\n    imports.wbg.__wbg_buffer_609cc3eee51ed158 = function(arg0) {\n        const ret = arg0.buffer;\n        return ret;\n    };\n    imports.wbg.__wbg_call_672a4d21634d4a24 = function() { return handleError(function (arg0, arg1) {\n        const ret = arg0.call(arg1);\n        return ret;\n    }, arguments) };\n    imports.wbg.__wbg_call_7cccdd69e0791ae2 = function() { return handleError(function (arg0, arg1, arg2) {\n        const ret = arg0.call(arg1, arg2);\n        return ret;\n    }, arguments) };\n    imports.wbg.__wbg_createElement_8c9931a732ee2fea = function() { return handleError(function (arg0, arg1, arg2) {\n        const ret = arg0.createElement(getStringFromWasm0(arg1, arg2));\n        return ret;\n    }, arguments) };\n    imports.wbg.__wbg_crypto_ed58b8e10a292839 = function(arg0) {\n        const ret = arg0.crypto;\n        return ret;\n    };\n    imports.wbg.__wbg_document_d249400bd7bd996d = function(arg0) {\n        const ret = arg0.document;\n        return isLikeNone(ret) ? 0 : addToExternrefTable0(ret);\n    };\n    imports.wbg.__wbg_getRandomValues_bcb4912f16000dc4 = function() { return handleError(function (arg0, arg1) {\n        arg0.getRandomValues(arg1);\n    }, arguments) };\n    imports.wbg.__wbg_instanceof_Window_def73ea0955fc569 = function(arg0) {\n        let result;\n        try {\n            result = arg0 instanceof Window;\n        } catch (_) {\n            result = false;\n        }\n        const ret = result;\n        return ret;\n    };\n    imports.wbg.__wbg_msCrypto_0a36e2ec3a343d26 = function(arg0) {\n        const ret = arg0.msCrypto;\n        return ret;\n    };\n    imports.wbg.__wbg_new_405e22f390576ce2 = function() {\n        const ret = new Object();\n        return ret;\n    };\n    imports.wbg.__wbg_new_5e0be73521bc8c17 = function() {\n        const ret = new Map();\n        return ret;\n    };\n    imports.wbg.__wbg_new_a12002a7f91c75be = function(arg0) {\n        const ret = new Uint8Array(arg0);\n        return ret;\n    };\n    imports.wbg.__wbg_newnoargs_105ed471475aaf50 = function(arg0, arg1) {\n        const ret = new Function(getStringFromWasm0(arg0, arg1));\n        return ret;\n    };\n    imports.wbg.__wbg_newwithbyteoffsetandlength_d97e637ebe145a9a = function(arg0, arg1, arg2) {\n        const ret = new Uint8Array(arg0, arg1 >>> 0, arg2 >>> 0);\n        return ret;\n    };\n    imports.wbg.__wbg_newwithlength_a381634e90c276d4 = function(arg0) {\n        const ret = new Uint8Array(arg0 >>> 0);\n        return ret;\n    };\n    imports.wbg.__wbg_node_02999533c4ea02e3 = function(arg0) {\n        const ret = arg0.node;\n        return ret;\n    };\n    imports.wbg.__wbg_process_5c1d670bc53614b8 = function(arg0) {\n        const ret = arg0.process;\n        return ret;\n    };\n    imports.wbg.__wbg_randomFillSync_ab2cfe79ebbf2740 = function() { return handleError(function (arg0, arg1) {\n        arg0.randomFillSync(arg1);\n    }, arguments) };\n    imports.wbg.__wbg_require_79b1e9274cde3c87 = function() { return handleError(function () {\n        const ret = module.require;\n        return ret;\n    }, arguments) };\n    imports.wbg.__wbg_set_3fda3bac07393de4 = function(arg0, arg1, arg2) {\n        arg0[arg1] = arg2;\n    };\n    imports.wbg.__wbg_set_65595bdd868b3009 = function(arg0, arg1, arg2) {\n        arg0.set(arg1, arg2 >>> 0);\n    };\n    imports.wbg.__wbg_set_8fc6bf8a5b1071d1 = function(arg0, arg1, arg2) {\n        const ret = arg0.set(arg1, arg2);\n        return ret;\n    };\n    imports.wbg.__wbg_setinnerHTML_31bde41f835786f7 = function(arg0, arg1, arg2) {\n        arg0.innerHTML = getStringFromWasm0(arg1, arg2);\n    };\n    imports.wbg.__wbg_static_accessor_GLOBAL_88a902d13a557d07 = function() {\n        const ret = typeof global === 'undefined' ? null : global;\n        return isLikeNone(ret) ? 0 : addToExternrefTable0(ret);\n    };\n    imports.wbg.__wbg_static_accessor_GLOBAL_THIS_56578be7e9f832b0 = function() {\n        const ret = typeof globalThis === 'undefined' ? null : globalThis;\n        return isLikeNone(ret) ? 0 : addToExternrefTable0(ret);\n    };\n    imports.wbg.__wbg_static_accessor_SELF_37c5d418e4bf5819 = function() {\n        const ret = typeof self === 'undefined' ? null : self;\n        return isLikeNone(ret) ? 0 : addToExternrefTable0(ret);\n    };\n    imports.wbg.__wbg_static_accessor_WINDOW_5de37043a91a9c40 = function() {\n        const ret = typeof window === 'undefined' ? null : window;\n        return isLikeNone(ret) ? 0 : addToExternrefTable0(ret);\n    };\n    imports.wbg.__wbg_subarray_aa9065fa9dc5df96 = function(arg0, arg1, arg2) {\n        const ret = arg0.subarray(arg1 >>> 0, arg2 >>> 0);\n        return ret;\n    };\n    imports.wbg.__wbg_versions_c71aa1626a93e0a1 = function(arg0) {\n        const ret = arg0.versions;\n        return ret;\n    };\n    imports.wbg.__wbindgen_error_new = function(arg0, arg1) {\n        const ret = new Error(getStringFromWasm0(arg0, arg1));\n        return ret;\n    };\n    imports.wbg.__wbindgen_init_externref_table = function() {\n        const table = wasm.__wbindgen_export_2;\n        const offset = table.grow(4);\n        table.set(0, undefined);\n        table.set(offset + 0, undefined);\n        table.set(offset + 1, null);\n        table.set(offset + 2, true);\n        table.set(offset + 3, false);\n        ;\n    };\n    imports.wbg.__wbindgen_is_function = function(arg0) {\n        const ret = typeof(arg0) === 'function';\n        return ret;\n    };\n    imports.wbg.__wbindgen_is_object = function(arg0) {\n        const val = arg0;\n        const ret = typeof(val) === 'object' && val !== null;\n        return ret;\n    };\n    imports.wbg.__wbindgen_is_string = function(arg0) {\n        const ret = typeof(arg0) === 'string';\n        return ret;\n    };\n    imports.wbg.__wbindgen_is_undefined = function(arg0) {\n        const ret = arg0 === undefined;\n        return ret;\n    };\n    imports.wbg.__wbindgen_memory = function() {\n        const ret = wasm.memory;\n        return ret;\n    };\n    imports.wbg.__wbindgen_rethrow = function(arg0) {\n        throw arg0;\n    };\n    imports.wbg.__wbindgen_string_new = function(arg0, arg1) {\n        const ret = getStringFromWasm0(arg0, arg1);\n        return ret;\n    };\n    imports.wbg.__wbindgen_throw = function(arg0, arg1) {\n        throw new Error(getStringFromWasm0(arg0, arg1));\n    };\n\n    return imports;\n}\n\nfunction __wbg_init_memory(imports, memory) {\n\n}\n\nfunction __wbg_finalize_init(instance, module) {\n    wasm = instance.exports;\n    __wbg_init.__wbindgen_wasm_module = module;\n    cachedUint16ArrayMemory0 = null;\n    cachedUint8ArrayMemory0 = null;\n\n\n    wasm.__wbindgen_start();\n    return wasm;\n}\n\nfunction initSync(module) {\n    if (wasm !== undefined) return wasm;\n\n\n    if (typeof module !== 'undefined') {\n        if (Object.getPrototypeOf(module) === Object.prototype) {\n            ({module} = module)\n        } else {\n            console.warn('using deprecated parameters for `initSync()`; pass a single object instead')\n        }\n    }\n\n    const imports = __wbg_get_imports();\n\n    __wbg_init_memory(imports);\n\n    if (!(module instanceof WebAssembly.Module)) {\n        module = new WebAssembly.Module(module);\n    }\n\n    const instance = new WebAssembly.Instance(module, imports);\n\n    return __wbg_finalize_init(instance, module);\n}\n\nasync function __wbg_init(module_or_path) {\n    if (wasm !== undefined) return wasm;\n\n\n    if (typeof module_or_path !== 'undefined') {\n        if (Object.getPrototypeOf(module_or_path) === Object.prototype) {\n            ({module_or_path} = module_or_path)\n        } else {\n            console.warn('using deprecated parameters for the initialization function; pass a single object instead')\n        }\n    }\n\n    if (typeof module_or_path === 'undefined') {\n        module_or_path = new URL('vodozemac_bg.wasm', import.meta.url);\n    }\n    const imports = __wbg_get_imports();\n\n    if (typeof module_or_path === 'string' || (typeof Request === 'function' && module_or_path instanceof Request) || (typeof URL === 'function' && module_or_path instanceof URL)) {\n        module_or_path = fetch(module_or_path);\n    }\n\n    __wbg_init_memory(imports);\n\n    const { instance, module } = await __wbg_load(await module_or_path, imports);\n\n    return __wbg_finalize_init(instance, module);\n}\n\nexport { initSync };\nexport default __wbg_init;\n","function webpackEmptyContext(req) {\n\tvar e = new Error(\"Cannot find module '\" + req + \"'\");\n\te.code = 'MODULE_NOT_FOUND';\n\tthrow e;\n}\nwebpackEmptyContext.keys = () => ([]);\nwebpackEmptyContext.resolve = webpackEmptyContext;\nwebpackEmptyContext.id = 687;\nmodule.exports = webpackEmptyContext;","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\tid: moduleId,\n\t\tloaded: false,\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n\t// Flag the module as loaded\n\tmodule.loaded = true;\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n// expose the modules object (__webpack_modules__)\n__webpack_require__.m = __webpack_modules__;\n\n","__webpack_require__.amdO = {};","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.g = (function() {\n\tif (typeof globalThis === 'object') return globalThis;\n\ttry {\n\t\treturn this || new Function('return this')();\n\t} catch (e) {\n\t\tif (typeof window === 'object') return window;\n\t}\n})();","__webpack_require__.hmd = (module) => {\n\tmodule = Object.create(module);\n\tif (!module.children) module.children = [];\n\tObject.defineProperty(module, 'exports', {\n\t\tenumerable: true,\n\t\tset: () => {\n\t\t\tthrow new Error('ES Modules may not assign module.exports or exports.*, Use ESM export syntax, instead: ' + module.id);\n\t\t}\n\t});\n\treturn module;\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","var scriptUrl;\nif (__webpack_require__.g.importScripts) scriptUrl = __webpack_require__.g.location + \"\";\nvar document = __webpack_require__.g.document;\nif (!scriptUrl && document) {\n\tif (document.currentScript && document.currentScript.tagName.toUpperCase() === 'SCRIPT')\n\t\tscriptUrl = document.currentScript.src;\n\tif (!scriptUrl) {\n\t\tvar scripts = document.getElementsByTagName(\"script\");\n\t\tif(scripts.length) {\n\t\t\tvar i = scripts.length - 1;\n\t\t\twhile (i > -1 && (!scriptUrl || !/^http(s?):/.test(scriptUrl))) scriptUrl = scripts[i--].src;\n\t\t}\n\t}\n}\n// When supporting browsers where an automatic publicPath is not supported you must specify an output.publicPath manually via configuration\n// or pass an empty string (\"\") and set the __webpack_public_path__ variable from your code to use your own logic.\nif (!scriptUrl) throw new Error(\"Automatic publicPath is not supported in this browser\");\nscriptUrl = scriptUrl.replace(/^blob:/, \"\").replace(/#.*$/, \"\").replace(/\\?.*$/, \"\").replace(/\\/[^\\/]+$/, \"/\");\n__webpack_require__.p = scriptUrl;","__webpack_require__.b = (typeof document !== 'undefined' && document.baseURI) || self.location.href;\n\n// object to store loaded and loading chunks\n// undefined = chunk not loaded, null = chunk preloaded/prefetched\n// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded\nvar installedChunks = {\n\t516: 0\n};\n\n// no chunk on demand loading\n\n// no prefetching\n\n// no preloaded\n\n// no HMR\n\n// no HMR manifest\n\n// no on chunks loaded\n\n// no jsonp function","// startup\n// Load entry module and return exports\n// This entry module is referenced by other modules so it can't be inlined\nvar __webpack_exports__ = __webpack_require__(154);\n"],"names":["root","factory","exports","module","define","amd","self","value","other","array","key","length","eq","splice","Array","prototype","ListCache","entries","index","this","clear","entry","set","__data__","size","data","assocIndexOf","pop","call","get","undefined","has","push","global","Object","freeSelf","freeGlobal","Function","Symbol","objectProto","hasOwnProperty","nativeObjectToString","toString","symToStringTag","toStringTag","isOwn","tag","unmasked","e","result","getRawTag","objectToString","type","isObject","baseGetTag","uid","maskSrcKey","exec","coreJsData","keys","IE_PROTO","funcToString","func","reIsHostCtor","funcProto","reIsNative","RegExp","replace","isFunction","test","toSource","object","getValue","baseIsNative","getNative","Hash","nativeCreate","map","MapCache","Map","getMapData","Stack","pairs","LARGE_ARRAY_SIZE","defineProperty","baseAssignValue","iteratee","keysFunc","iterable","props","freeExports","nodeType","freeModule","Buffer","allocUnsafe","buffer","isDeep","slice","constructor","copy","Uint8Array","arrayBuffer","byteLength","typedArray","cloneArrayBuffer","byteOffset","source","objectCreate","create","proto","transform","arg","overArg","getPrototypeOf","Ctor","isPrototype","baseCreate","getPrototype","isObjectLike","propertyIsEnumerable","isArguments","baseIsArguments","arguments","isArray","isLength","isBuffer","objectCtorString","typedArrayTags","freeProcess","process","require","types","binding","nodeIsTypedArray","nodeUtil","isTypedArray","baseUnary","objValue","customizer","isNew","newValue","assignValue","reIsUint","inherited","isArr","isArg","isBuff","isType","skipIndexes","n","baseTimes","String","isIndex","nativeKeysIn","isProto","isArrayLike","arrayLikeKeys","baseKeysIn","srcIndex","mergeFunc","stack","safeGet","srcValue","stacked","assignMergeValue","isCommon","isTyped","copyArray","cloneBuffer","cloneTypedArray","isPlainObject","copyObject","keysIn","toPlainObject","initCloneObject","baseMerge","baseFor","baseMergeDeep","nativeMax","Math","max","string","identity","nativeNow","Date","now","baseSetToString","count","lastCalled","stamp","remaining","apply","start","setToString","args","otherArgs","thisArg","overRest","assigner","baseRest","sources","guard","isIterateeCall","JitsiAudioTranslationErrors","JitsiConferenceErrors","AUTH_ERROR_TYPES","AUTHENTICATION_REQUIRED","CHAT_ERROR","SETTINGS_ERROR","CONFERENCE_DESTROYED","CONFERENCE_MAX_USERS","CONNECTION_ERROR","NOT_ALLOWED_ERROR","MEMBERS_ONLY_ERROR","CONFERENCE_ACCESS_DENIED","DISPLAY_NAME_REQUIRED","FOCUS_DISCONNECTED","FOCUS_LEFT","GRACEFUL_SHUTDOWN","ICE_FAILED","INCOMPATIBLE_SERVER_VERSIONS","OFFER_ANSWER_FAILED","PASSWORD_NOT_SUPPORTED","PASSWORD_REQUIRED","RESERVATION_ERROR","VIDEOBRIDGE_NOT_AVAILABLE","JitsiConferenceEvents","SetCache","values","add","predicate","bitmask","equalFunc","isPartial","arrLength","othLength","arrStacked","othStacked","seen","arrValue","othValue","compared","arraySome","othIndex","forEach","symbolProto","symbolValueOf","valueOf","offset","symbolsFunc","arrayPush","nativeGetSymbols","getOwnPropertySymbols","resIndex","arrayFilter","symbol","stubArray","nativeKeys","baseKeys","baseGetAllKeys","getSymbols","mapTag","promiseTag","setTag","weakMapTag","dataViewTag","dataViewCtorString","DataView","mapCtorString","promiseCtorString","Promise","setCtorString","Set","weakMapCtorString","WeakMap","getTag","ArrayBuffer","resolve","ctorString","argsTag","arrayTag","objectTag","objIsArr","othIsArr","objTag","othTag","objIsObj","othIsObj","isSameTag","equalArrays","name","message","convert","mapToArray","setToArray","equalByTag","objIsWrapped","othIsWrapped","objUnwrapped","othUnwrapped","objProps","getAllKeys","objLength","objStacked","skipCtor","objCtor","othCtor","equalObjects","baseIsEqual","baseIsEqualDeep","JitsiTrackEvents","Browser","PARSER_TO_JITSI_NAME","CHROME","FIREFOX","SAFARI","ELECTRON","Engine","ENGINES","BLINK","WEBKIT","GECKO","_getJitsiBrowserInfo","browserInfo","engine","engineVersion","version","BrowserDetection","_parser","UAParser","navigator","userAgent","_ref","parser","reactNativeInfo","match","product","REACT_NATIVE","_detectReactNative","_parser$getBrowser","getBrowser","_parser$getEngine","getEngine","_detect","_name","_version","_engine","_engineVersion","isChrome","isFirefox","isSafari","isElectron","isReactNative","isChromiumBased","isWebKitBased","getName","getVersion","getEngineVersion","getOS","getOSVersion","isVersionGreaterThan","parseInt","isVersionLessThan","isVersionEqualTo","isEngineVersionGreaterThan","isEngineVersionLessThan","isEngineVersionEqualTo","logger","getLogger","deltaCompression","oldStats","newStatsArg","newStats","JSON","parse","stringify","id","report","timestamp","dumpStream","stream","tracks","getTracks","track","kind","label","enabled","muted","readyState","getRandomValues","rnds8","rng","crypto","bind","msCrypto","Error","byteToHex","i","substr","arr","uuid","toLowerCase","REGEX","validate","TypeError","options","buf","rnds","random","MAX_RECONNECT_TIME","CUSTOM_ERROR_CODES","obfuscateIP","ip","indexOf","obfuscateCandidate","candidate","cand","SDPUtils","protocol","address","relatedAddress","jsonRepr","sdp","line","join","trim","stats","candidateType","port","splitBy","_report$name$split2","split","DummyLocalStorage","EventEmitter","super","_storage","getItem","keyName","_a","setItem","keyValue","removeItem","serialize","ignore","storageCopy","JitsiLocalStorage","storage","_localStorageDisabled","window","localStorage","console","warn","isLocalStorageDisabled","setLocalStorageDisabled","emit","dontEmitChangedEvent","localStorageContent","includes","jitsiLocalStorage","MessageType","safeJsonParse","BourneParse","opener","parent","randomUUID","_options$random","_options$rng","_options","RangeError","unsafeStringify","_v4","randomInt","min","floor","randomElement","randomAlphanumStr","randomHexDigit","randomHexString","len","ret","names","_callStatsUserName","_machineId","callStatsUserName","username","info","_generateStatsId","init","externalStorage","machineId","amDid","jitsiMeetId","uuidv4","replaceAll","generateJitsiMeetId","sessionId","NodeEventEmitter","addEventListener","addListener","removeEventListener","removeListener","RTCStatsEvents","DefaultLogStorage","rtcStats","isReady","isTraceAvailable","storeLogs","logEntries","RTCStats","sendStatsEntry","LOG_EVENT","_defineProperty","_trace","startWithConnection","connection","_options$name","_this$_defaultLogColl","_options$analytics","analytics","_options$analytics2","_options$analytics2$r","rtcstatsEndpoint","endpoint","_options$analytics2$r2","rtcstatsEnabled","_options$analytics2$r3","rtcstatsPollInterval","pollInterval","_options$analytics2$r4","rtcstatsSendSdp","sendSdp","_initialized","_ref2","statsEntry","connectionFilter","useLegacy","_ref2$sendSdp","_ref2$prefixesToWrap","prefixesToWrap","eventCallback","peerconnectioncounter","browserDetection","prefix","OrigPeerConnection","peerconnection","config","constraints","origConfig","_constraints$optional","optional","isP2P","some","option","rtcStatsSFUP2P","pc","__rtcStatsId","nullConfig","iceServers","server","credential","browserType","__dtlsTransport","t","streams","signalingState","iceConnectionState","body","pcId","state","iceGatheringState","connectionState","event","channel","prev","getStats","then","res","m","o","v","k","map2obj","base","response","standardReport","standardStats","getTime","stat","mangleChromeStats","interval","setInterval","clearInterval","error","method","nativeMethod","streamInfo","s","trackOrKind","opts","rtcStatsId","description","err","endsWith","getSenders","sender","transport","newstate","generateCertificate","origGetUserMedia","cb","eb","mediaDevices","getUserMedia","gum","reject","getDisplayMedia","origGetDisplayMedia","gdm","rtcstatsInit","events","RTC_STATS_PC_EVENT","traceOptions","isBreakoutRoom","meetingFqn","_connectTrace","_defaultLogCollector","flush","sendIdentity","confName","_startedWithNewConnection","attachToConference","conference","_Settings$callStatsUs","_conference$options","_conference$options2","_conference$options2$","confConfig","_conference$options2$2","_conference$_statsCur","_statsCurrentId","displayName","_confConfig$analytics","_confConfig$analytics2","_confConfig$analytics3","_confConfig$analytics4","localId","Settings","once","CONFERENCE_JOINED","_conference$getBreako","Boolean","getBreakoutRooms","endpointId","myUserId","meetingUniqueId","getMeetingUniqueId","_this$_defaultLogColl2","identityData","CONFERENCE_UNIQUE_ID_SET","CONFERENCE_LEFT","reset","CONFERENCE_CREATED_TIMESTAMP","CONFERENCE_START_TIMESTAMP_EVENT","BEFORE_STATISTICS_DISPOSED","_this$_defaultLogColl3","traceOptionsComplete","onCloseCallback","RTC_STATS_WC_DISCONNECTED","parentStatsSessionId","keepAliveInterval","reconnectTimeout","_ref$obfuscate","obfuscate","_ref$pingInterval","pingInterval","statsSessionId","reconnectSpentTime","reconnectAttempts","canSendMessage","sequenceNumber","protocolVersion","setTransportParams","sendMessage","msg","copyMsg","assign","WebSocket","OPEN","send","trace","isConnected","isClosed","CLOSED","_len","_key","_len2","_key2","myData","obfuscator","keepAlive","close","connect","isReconnect","headers","onclose","closeEvent","code","reason","reconnectTimeoutTimeCandidate","getTimeout","reconnectTimeoutTime","setTimeout","onopen","onmessage","async","_JSON$parse","firstSN","lastSN","lastReceivedSNIndex","findIndex","clearTimeout","traceInit","_flushPendingStatsEntries","_pendingStatsEntries","pending","statsType","_this$_trace","_this$_defaultLogColl4","_this$_trace2","getDefaultLogCollector","maxEntryLength","Logger","AnalyticsEvents","createConferenceEvent","action","attributes","TYPE_OPERATIONAL","createConnectionStageReachedEvent","stage","actionSubject","createGetUserMediaEvent","createJingleEvent","createP2PEvent","createRemotelyMutedEvent","mediaType","createRtpStatsEvent","StatisticsEvents","_getIOSVersion","Number","_getSafariVersion","supportsRTCRtpEncodingParametersActiveForAudio","doesVideoMuteByStreamRemove","isAndroidBrowser","isIosBrowser","isMobileDevice","isTwa","matchMedia","matches","isSupported","_navigator","_navigator2","RTCPeerConnection","enumerateDevices","MIN_REQUIRED_CHROME_VERSION","MIN_REQUIRED_FIREFOX_VERSION","isSupportedAndroidBrowser","isSupportedIOSBrowser","isUserInteractionRequiredForUnmute","supportsVideoMuteOnConnInterrupted","supportsBandwidthStatistics","supportsCodecPreferences","_window$RTCRtpTransce","_window$RTCRtpReceive","RTCRtpTransceiver","RTCRtpReceiver","getCapabilities","supportsCodecSelectionAPI","supportsDDExtHeaders","supportsDeviceChangeEvent","_navigator$mediaDevic","_navigator$mediaDevic2","ondevicechange","supportsReceiverStats","supportsRTTStatistics","supportsEncodingsConfig","supportsScalabilityModeAPI","supportsTrackBasedStats","supportsVP9","supportsSVC","usesSdpMungingForSimulcast","usesRidsForSimulcast","supportsGetDisplayMedia","_navigator$mediaDevic3","supportsEncodedTransform","RTCRtpScriptTransform","supportsInsertableStreams","_window$RTCRtpSender","RTCRtpSender","createEncodedStreams","ReadableStream","postMessage","supportsAudioRed","_window$RTCRtpSender2","_window$RTCRtpReceive2","codecs","codec","mimeType","supportsVADDetection","supportsRTX","_analytics$watchRTCEn","watchRTCEnabled","isWatchRTCEnabled","browser","disableThirdPartyRequests","disabled","isAnalyticsEnabled","_options$watchRTCConf","watchRTCConfigParams","rtcApiKey","watchRTC","roomName","userName","rtcRoomId","rtcPeerId","_maybeCacheEvent","cache","_sendEvent","analyticsHandlers","handler","sendEvent","_setUserProperties","setUserProperties","permanentProperties","_verifyRequiredFields","TYPE_PAGE","TYPE_UI","TYPE_TRACK","objectType","containerType","containerId","conferenceName","objectId","addPermanentProperties","properties","dispose","debug","setAnalyticsHandlers","disposed","eventName","handlers","setConferenceName","context","LocalStatsCollector","callback","intervalId","intervalMilis","audioLevel","analyser","isLocalStatsSupported","resume","createAnalyser","smoothingTimeConstant","fftSize","createMediaStreamSource","frequencyBinCount","getByteTimeDomainData","samples","maxVolume","parseFloat","toFixed","timeDomainDataToAudioLevel","newLevel","lastLevel","diff","animateLevel","stop","_this$analyser","_this$source","disconnect","connectAudioContext","_window","AudioContext","disconnectAudioContext","suspend","MediaType","RTCEvents","flags","_runInLiteMode","runInLiteMode","_ssrcRewriting","ssrcRewritingEnabled","_rtpMidDemux","rtpMidDemuxEnabled","isRtpMidDemuxSupported","isRunInLiteModeEnabled","isSsrcRewritingSupported","safeCounterIncrement","number","nextValue","MAX_SAFE_INTEGER","calculateAverage","valueArray","reduce","a","b","filterPositiveValues","from","filter","safeSubtract","x","y","isValidNumber","isFinite","calculatePacketLoss","lostPackets","totalPackets","round","SsrcStats","loss","bitrate","download","upload","resolution","framerate","setLoss","setResolution","addBitrate","resetBitrate","setFramerate","setCodec","setEncodeStats","encodeStats","setFramesDecoded","framesDecoded","ConferenceStats","bandwidth","packetLoss","StatsCollector","audioLevelsInterval","statsInterval","eventEmitter","currentStatsReport","previousStatsReport","audioLevelsIntervalId","conferenceStats","audioLevelsIntervalMilis","speakerList","statsIntervalId","statsIntervalMilis","ssrc2stats","_hadBadInboundSsrcs","setSpeakerList","errorCallback","startAudioLevelStats","audioLevels","getAudioLevels","ssrc","AUDIO_LEVEL","processStats","processStatsReport","catch","_processAndEmitReport","bitrateDownload","bitrateUpload","resolutions","framerates","audioBitrateDownload","audioBitrateUpload","videoBitrateDownload","videoBitrateUpload","inboundVideoStats","framesDecodedMap","_codecs$participantId","_slicedToArray","ssrcStats","isDownloadStream","packetsTotal","packetsLost","ssrcBitrateDownload","ssrcBitrateUpload","getTrackBySSRC","isLocal","isAudioTrack","participantId","getParticipantId","fps","audioCodec","videoCodec","isVideoTrack","FeatureFlags","userCodecs","audio","video","height","width","userResolutions","doesTrueSimulcast","localSsrcs","getLocalVideoSSRCs","localSsrc","_this$ssrc2stats$get","ssrcResolution","userFramerates","total","CONNECTION_STATS","INBOUND_VIDEO_STATS","getNonNegativeValue","_calculateBitrate","before","fieldName","bytesNow","bytesBefore","bytesProcessed","timeMs","bitrateKbps","_calculateFps","frameRate","byteSentStats","encodedTimeStatsPerSsrc","inboundAudioPacketsBySsrc","nominated","availableIncomingBitrate","availableOutgoingBitrate","remoteUsedCandidate","remoteCandidateId","localUsedCandidate","localCandidateId","localip","conferenceStatsTransport","localCandidateType","networkType","p2p","remoteCandidateType","rtt","currentRoundTripTime","packetsNow","AUDIO","packetsBefore","packetsDiff","packetsLostNow","packetsLostBefore","packetsLostDiff","frameHeight","frameWidth","_now$active","isStreamActive","active","framesPerSecond","bytesSent","codecId","codecShortType","totalEncodeTime","framesEncoded","encodeTimeStats","encodeTime","qualityLimitationReason","VIDEO","remoteSource","localVideoTracks","getLocalTracks","getSsrcByTrackId","trackIdentifier","BYTE_SENT_STATS","ENCODE_TIME_STATS","INBOUND_AUDIO_STATS","Statistics","instances","_instances","audioLevelsEnabled","disableAudioLevels","pcStatsInterval","LocalStats","WatchRTC","startLocalStats","NO_DATA_FROM_SOURCE","localStat","localStats","LOCAL_TRACK_STOPPED","stopLocalStats","getOriginalStream","sendAnalyticsAndLog","eventToLog","sendAnalytics","rtpStatsMap","xmpp","startRemoteStats","stopRemoteStats","rtpStats","RTPStats","addAudioLevelListener","listener","on","removeAudioLevelListener","addBeforeDisposedListener","BEFORE_DISPOSED","removeBeforeDisposedListener","addConnectionStatsListener","removeConnectionStatsListener","addEncodeTimeStatsListener","removeEncodeTimeStatsListener","addInboundVideoStatsListener","removeInboundVideoStatsListener","addByteSentStatsListener","removeByteSentStatsListener","tpcId","_stopRemoteStats","removeAllListeners","delete","tpc","sendFeedback","overall","comment","FEEDBACK","rating","EventEmitterForwarder","src","dest","listeners","forward","srcEvent","newListener","removeListeners","l","AuthenticationEvents","XMPPEvents","JitsiConferenceEventManager","xmppListeners","_addConferenceXMPPListener","setupChatRoomListeners","chatRoom","room","chatRoomForwarder","PARTICIPANT_FEATURES_CHANGED","features","participant","getParticipantById","Strophe","getResourceFromJid","setFeatures","PARTCIPANT_FEATURES_CHANGED","PERMISSIONS_RECEIVED","AUDIO_MUTED_BY_FOCUS","actor","mutedByFocusActor","rtc","setAudioMute","isMutedByFocus","VIDEO_MUTED_BY_FOCUS","mutedVideoByFocusActor","setVideoMute","isVideoMutedByFocus","DESKTOP_MUTED_BY_FOCUS","DESKTOP","mutedDesktopByFocusActor","setDesktopMute","isDesktopMutedByFocus","SUBJECT_CHANGED","MUC_JOINED","MUC_JOIN_IN_PROGRESS","CONFERENCE_JOIN_IN_PROGRESS","MEETING_ID_SET","CONFERENCE_TIMESTAMP_RECEIVED","_onMucJoined","isJvbConnectionInterrupted","connectionTimes","TRACK_OWNER_SET","owner","sourceName","videoType","getSourceName","TRACK_REMOVED","setOwner","setSourceName","_setVideoType","TRACK_ADDED","cleanDecoder","ROOM_JOIN_ERROR","CONFERENCE_FAILED","ROOM_CONNECT_ERROR","ROOM_CONNECT_NOT_ALLOWED_ERROR","ROOM_CONNECT_MEMBERS_ONLY_ERROR","ROOM_MAX_USERS_ERROR","BRIDGE_DOWN","MUC_DESTROYED","CHAT_ERROR_RECEIVED","CONFERENCE_ERROR","SETTINGS_ERROR_RECEIVED","SESSION_ACCEPT_TIMEOUT","jingleSession","ACTION_JINGLE_SA_TIMEOUT","RECORDER_STATE_CHANGED","session","jid","resource","getStatus","setTerminator","setInitiator","TRANSCRIPTION_STATUS_CHANGED","VIDEO_SIP_GW_AVAILABILITY_CHANGED","VIDEO_SIP_GW_SESSION_STATE_CHANGED","PHONE_NUMBER_CHANGED","setParticipantPropertyListener","prop","setProperty","KICKED","onMemberKicked","SUSPEND_DETECTED","onSuspendDetected","MUC_LOCK_CHANGED","LOCK_STATE_CHANGED","MUC_MEMBERS_ONLY_CHANGED","MEMBERS_ONLY_CHANGED","MUC_VISITORS_SUPPORTED_CHANGED","VISITORS_SUPPORTED_CHANGED","MUC_MEMBER_JOINED","onMemberJoined","MUC_LOBBY_MEMBER_JOINED","LOBBY_USER_JOINED","MUC_LOBBY_MEMBER_UPDATED","LOBBY_USER_UPDATED","MUC_LOBBY_MEMBER_LEFT","LOBBY_USER_LEFT","MUC_MEMBER_BOT_TYPE_CHANGED","_onMemberBotTypeChanged","MUC_MEMBER_LEFT","onMemberLeft","MUC_LEFT","MUC_DENIED_ACCESS","DISPLAY_NAME_CHANGED","onDisplayNameChanged","SILENT_STATUS_CHANGED","onSilentStatusChanged","LOCAL_ROLE_CHANGED","role","onLocalRoleChanged","MUC_ROLE_CHANGED","onUserRoleChanged","IDENTITY_UPDATED","authEnabled","authIdentity","AUTH_STATUS_CHANGED","MESSAGE_RECEIVED","txt","myJid","ts","isVisitor","messageId","replyToId","POLLS_RECEIVE_EVENT","POLL_RECEIVED","POLLS_ANSWER_EVENT","POLL_ANSWER_RECEIVED","REACTION_RECEIVED","reactionList","PRIVATE_MESSAGE_RECEIVED","ofrom","MESSAGE_MODERATED","moderatorJid","moderatorId","MESSAGE_RETRACTED","PRESENCE_STATUS","status","_status","USER_STATUS_CHANGED","JSON_MESSAGE_RECEIVED","payload","ENDPOINT_MESSAGE_RECEIVED","NON_PARTICIPANT_MESSAGE_RECEIVED","BREAKOUT_ROOMS_MOVE_TO_ROOM","BREAKOUT_ROOMS_UPDATED","FILE_SHARING_FILES_RECEIVED","FILE_SHARING_FILE_ADDED","FILE_SHARING_FILE_REMOVED","ROOM_METADATA_UPDATED","metadata","_metadata$recording","startMuted","_updateStartMutedPolicy","recording","isTranscribingEnabled","_setTranscribingEnabled","services","jingle","onReceiveStunAndTurnCredentials","METADATA_UPDATED","setupRTCListeners","REMOTE_TRACK_ADDED","onRemoteTrackAdded","REMOTE_TRACK_REMOVED","onRemoteTrackRemoved","DOMINANT_SPEAKER_CHANGED","dominant","previous","silence","lastDominantSpeaker","dominantSpeakerIsSilent","statistics","sendDominantSpeakerEvent","roomjid","DOMINANT_SPEAKER_CHANGED_EVENT","_conference$statistic","DATA_CHANNEL_OPEN","performance","DATA_CHANNEL_OPENED","DATA_CHANNEL_CLOSED","ev","VIDEO_SSRCS_REMAPPED","jvbJingleSession","processSourceMap","AUDIO_SSRCS_REMAPPED","BRIDGE_BWE_STATS_RECEIVED","bwe","TRANSLATED_SOURCE_SENDING_CHANGED","change","ENDPOINT_STATS_RECEIVED","setupStatisticsListeners","level","setAudioLevel","ENCODE_TIME_STATS_RECEIVED","INBOUND_VIDEO_STATS_RECEIVED","startSilent","getLocalSSRC","onByteSentStatsReceived","setupXMPPListeners","CALL_INCOMING","onIncomingCall","CALL_ACCEPTED","onCallAccepted","TRANSPORT_INFO","onTransportInfo","CALL_ENDED","onCallEnded","AV_MODERATION_CHANGED","actorJid","actorParticipant","getParticipants","find","p","getJid","AV_MODERATION_PARTICIPANT_APPROVED","AV_MODERATION_PARTICIPANT_REJECTED","AV_MODERATION_APPROVED","AV_MODERATION_REJECTED","VISITORS_MESSAGE","VISITORS_REJECTION","removeXMPPListeners","JitsiConnectionEvents","CONNECTION_DISCONNECTED","CONNECTION_ESTABLISHED","CONNECTION_FAILED","CONNECTION_REDIRECTED","CONNECTION_TOKEN_EXPIRED","PROPERTIES_UPDATED","JitsiParticipant","hidden","statsID","isReplacing","isReplaced","isSilent","_jid","_id","_conference","_displayName","_supportsDTMF","_tracks","_role","_hidden","_statsID","_properties","_identity","_isReplacing","_isReplaced","_isSilent","_features","_sources","_isMediaTypeMuted","getType","isMuted","_setSources","_sourceByMediaType","sourceByMediaType","sourceInfo","getBotType","_botType","getConference","getConnectionJid","_connectionJid","getDisplayName","getFeatures","getId","getIdentity","getProperty","getRole","getSources","getStatsID","getTracksByMediaType","hasFeature","feature","isAudioMuted","isHidden","isHiddenFromRecorder","_this$_identity","user","isModerator","isVideoMuted","setBotType","newBotType","setConnectionJid","newJid","newFeatures","setIsReplaced","newIsReplaced","setIsReplacing","newIsReplacing","setIsSilent","newIsSilent","oldValue","PARTICIPANT_PROPERTY_CHANGED","setRole","newRole","supportsDTMF","JitsiTrackErrors","CONSTRAINT_FAILED","ELECTRON_DESKTOP_PICKER_ERROR","ELECTRON_DESKTOP_PICKER_NOT_FOUND","GENERAL","NOT_FOUND","PERMISSION_DENIED","SCREENSHARING_GENERIC_ERROR","SCREENSHARING_NOT_SUPPORTED_ERROR","SCREENSHARING_USER_CANCELED","TIMEOUT","TRACK_IS_DISPOSED","TRACK_NO_STREAM_FOUND","UNSUPPORTED_RESOLUTION","TRACK_TOO_MANY_TRACKS_IN_STREAM","TRACK_NO_STREAM_TRACKS_FOUND","TRACK_ERROR_TO_MESSAGE_MAP","JitsiTrackError","devices","constraintName","constraint","getResolutionFromFailedConstraint","failedConstraintName","_constraints$video","mandatory","minWidth","minHeight","getSymbolsIn","reFlags","regexp","dataView","cloneDataView","lastIndex","nodeIsMap","isMap","nodeIsSet","isSet","funcTag","cloneableTags","baseClone","isFlat","isFull","input","initCloneArray","isFunc","copySymbolsIn","baseAssignIn","copySymbols","baseAssign","initCloneByTag","subValue","getAllKeysIn","arrayEach","CLONE_DEEP_FLAG","VideoType","Listenable","eventId","off","addCancellableListener","listenerCount","BridgeChannel","wsUrl","emitter","_channel","_connected","_eventEmitter","_mode","_areRetriesEnabled","_closedFromClient","datachannel","createDataChannel","_handleChannel","_wsUrl","_initWebSocket","ws","_startConnectionRetries","timeoutS","reload","CONNECTING","isOpen","_retryTimeout","_stopConnectionRetries","_retryWebSocketConnection","createBridgeChannelClosedEvent","mode","sendEndpointStatsMessage","_send","colibriClass","to","msgPayload","sendSetLastNMessage","lastN","sendReceiverAudioSubscriptionMessage","_message$all","_message$exclude","_message$include","all","exclude","include","sendReceiverVideoConstraintsMessage","sendSourceVideoTypeMessage","onerror","obj","estimatedDownlinkBandwidth","_obj2","dominantSpeakerEndpoint","_obj2$previousSpeaker","previousSpeakers","isActive","ENDPOINT_CONN_STATUS_CHANGED","forwardedSources","FORWARDED_SOURCES_CHANGED","maxHeight","SENDER_VIDEO_CONSTRAINTS_CHANGED","sending","isInteger","mappedSources","getParticipantCount","jsonObject","CameraFacingMode","logDisabled_","deprecationWarnings_","extractVersion","uastring","expr","pos","wrapPeerConnectionEvent","eventNameToWrap","wrapper","nativeAddEventListener","nativeEventName","wrappedCallback","modifiedEvent","handleEvent","_eventMap","nativeRemoveEventListener","unwrappedCb","enumerable","configurable","disableLog","bool","disableWarnings","log","deprecated","oldMethod","newMethod","val","compactObject","accumulator","isObj","isEmptyObject","walkStats","resultSet","filterStats","outbound","streamStatsType","filteredResult","trackStats","trackStat","trackId","logging","utils","shimGetUserMedia","browserDetails","constraintsToChrome_","c","cc","r","ideal","exact","oldname_","charAt","toUpperCase","oc","mix","advanced","concat","shimConstraints_","remap","face","facingMode","getSupportedFacingModeLies","getSupportedConstraints","dev","d","deviceId","shimError_","PermissionDeniedError","PermissionDismissedError","InvalidStateError","DevicesNotFoundError","ConstraintNotSatisfiedError","TrackStartError","MediaDeviceFailedDueToShutdown","MediaDeviceKillSwitchOn","TabCaptureError","ScreenCaptureError","DeviceCaptureError","onSuccess","onError","webkitGetUserMedia","cs","getAudioTracks","getVideoTracks","DOMException","shimGetDisplayMedia","getSourceId","sourceId","widthSpecified","heightSpecified","frameRateSpecified","chromeMediaSource","chromeMediaSourceId","maxFrameRate","maxWidth","shimMediaStream","MediaStream","webkitMediaStream","shimOnTrack","_ontrack","f","origSetRemoteDescription","setRemoteDescription","_ontrackpoly","te","receiver","getReceivers","Event","transceiver","dispatchEvent","shimGetSendersWithDtmf","shimSenderWithDtmf","dtmf","_dtmf","createDTMFSender","_pc","_senders","origAddTrack","addTrack","origRemoveTrack","removeTrack","idx","origAddStream","addStream","origRemoveStream","removeStream","origGetSenders","senders","shimGetStats","origGetStats","_arguments","selector","onSucc","onErr","fixChromeStats_","localcandidate","remotecandidate","makeMapStats","successCallbackWrapper_","shimSenderReceiverGetStats","origGetReceivers","receivers","srcElement","MediaStreamTrack","shimAddTrackRemoveTrackWithNative","getLocalStreams","_shimmedLocalStreams","streamId","existingSenders","newSenders","newSender","shimAddTrackRemoveTrack","origGetLocalStreams","nativeStreams","_reverseStreams","_streams","newStream","replaceInternalStreamId","internalId","externalStream","internalStream","RTCSessionDescription","oldStream","methodObj","desc","origSetLocalDescription","setLocalDescription","replaceExternalStreamId","origLocalDescription","getOwnPropertyDescriptor","streamid","shimPeerConnection","webkitRTCPeerConnection","RTCIceCandidate","fixNegotiationNeeded","target","getConfiguration","sdpSemantics","nativeGetUserMedia","getSettings","nativeGetSettings","applyConstraints","nativeApplyConstraints","preferredMediaSource","mediaSource","RTCTrackEvent","mozRTCPeerConnection","modernStatsTypes","inboundrtp","outboundrtp","candidatepair","nativeGetStats","shimSenderGetStats","shimReceiverGetStats","shimRemoveStream","shimRTCDataChannel","DataChannel","RTCDataChannel","shimAddTransceiver","origAddTransceiver","addTransceiver","setParametersPromises","initParameters","shouldPerformCheck","sendEncodings","encodingParam","rid","scaleResolutionDownBy","maxFramerate","params","getParameters","encodings","setParameters","shimGetParameters","origGetParameters","shimCreateOffer","origCreateOffer","createOffer","finally","shimCreateAnswer","origCreateAnswer","createAnswer","shimLocalStreamsAPI","_localStreams","_addTrack","shimRemoteStreamsAPI","getRemoteStreams","_remoteStreams","_onaddstream","_onaddstreampoly","shimCallbacksAPI","addIceCandidate","successCallback","failureCallback","promise","withCallback","_getUserMedia","shimConstraints","errcb","shimRTCIceServerUrls","pcConfig","pcConstraints","newIceServers","urls","url","shimTrackEventTransceiver","shimCreateOfferLegacy","offerOptions","offerToReceiveAudio","audioTransceiver","getTransceivers","direction","setDirection","offerToReceiveVideo","videoTransceiver","shimAudioContext","webkitAudioContext","shimRTCIceCandidate","NativeRTCIceCandidate","nativeCandidate","parsedCandidate","augmentedCandidate","toJSON","sdpMid","sdpMLineIndex","usernameFragment","writable","shimMaxMessageSize","_sctp","sections","shift","mediaSection","mLine","sctpInDescription","getRemoteFirefoxVersion","canSendMMS","remoteIsFirefox","canSendMaxMessageSize","getCanSendMaxMessageSize","remoteMMS","maxMessageSize","getMaxMessageSize","POSITIVE_INFINITY","sctp","shimSendThrowTypeError","wrapDcSend","dc","origDataChannelSend","origCreateDataChannel","dataChannel","shimConnectionState","completed","checking","_onconnectionstatechange","origMethod","_connectionstatechangepoly","_lastConnectionState","newEvent","removeExtmapAllowMixed","nativeSRD","shimAddIceCandidateNullOrEmpty","nativeAddIceCandidate","shimParameterlessSetLocalDescription","nativeSetLocalDescription","shimChrome","shimFirefox","shimSafari","mozGetUserMedia","isSecureContext","RTCIceGatherer","supportsUnifiedPlan","adapter","commonShim","chromeShim","browserShim","firefoxShim","safariShim","adapterFactory","obtainStream","_createObtainStreamMethod","_electronSkipDisplayMedia","_obtainScreenOnElectron","obtainScreenFromGetDisplayMediaRN","_obtainScreenFromGetDisplayMedia","_getAudioConstraints","_this$options$testing","audioQuality","isTestModeEnabled","testing","testMode","supportsRestrictOwnAudio","needsEchoCancellation","stereo","defaultAudioConstraints","autoGainControl","channelCount","echoCancellation","noiseSuppression","restrictOwnAudio","onFailure","_window$JitsiMeetScre","_this","JitsiMeetScreenObtainer","openDesktopPicker","_this$options","desktopSharingFrameRate","desktopSharingResolution","desktopSharingSources","streamType","_desktopSharingFrameR","_desktopSharingResolu","_desktopSharingResolu2","_desktopSharingResolu3","_desktopSharingResolu4","_desktopSharingFrameR2","_desktopSharingResolu5","_desktopSharingResolu6","audioConstraints","optionalConstraints","screen","minFrameRate","setContentHint","sourceType","_this$options2","_this$options3","_this$options4","constraintOpts","_options$desktopShari","_options$resolution","_options$screenShareS","screenShareSettings","preferCurrentTab","desktopPreferCurrentTab","systemAudio","desktopSystemAudio","surfaceSwitching","desktopSurfaceSwitching","desktopDisplaySurface","displaySurface","selfBrowserSurface","desktopSelfBrowserSurface","cursor","_track$getSettings","_this$options$testing2","minFps","trackConstraints","videoTracks","_errorDetails$errorMs","errorDetails","errorCode","errorMsg","errorName","errorStack","NOT_SUPPORTED_ERR","desktopTrack","contentHint","setDesktopSharingFrameRate","maxFps","DEFAULT_CONSTRAINTS","audioOutputDeviceId","audioOutputChanged","disableAP","disableAEC","disableNS","disableAGC","featureDetectionAudioEl","document","createElement","isAudioOutputDeviceChangeAvailable","setSinkId","availableDevicesPollTimer","availableDevices","emptyFuncton","sendDeviceListToAnalytics","deviceList","audioInputDeviceCount","audioOutputDeviceCount","videoInputDeviceCount","videoOutputDeviceCount","device","groupId","AVAILABLE_DEVICE","_initOnce","_options$audioQuality","screenObtainer","ds","DEVICE_LIST_AVAILABLE","attachMediaStream","element","srcObject","isDeviceChangeAvailable","getAudioOutputDevice","ex","_updateKnownDevices","umDevices","timeout","gumTimeout","timeoutExpired","timeoutError","GET_USER_MEDIA_ERROR_EVENT","_updateGrantedPermissions","jitsiError","_getDesktopMedia","_getMissingTracks","requestedDevices","missingDevices","audioDeviceRequested","audioTracksReceived","videoDeviceRequested","videoTracksReceived","_onMediaDevicesListChanged","devicesReceived","DEVICE_LIST_WILL_CHANGE","DEVICE_LIST_CHANGED","pds","newDevices","mediaDeviceInfoToJSON","sort","facing","compareAvailableMediaDevices","um","grantedPermissions","PERMISSIONS_CHANGED","obtainAudioAndVideoPermissions","otherOptions","_objectWithoutProperties","_excluded","mediaStreamsMetaData","maybeRequestDesktopDevice","desktopSharingSourceDevice","matchingDevice","deviceConstraints","maybeRequestCaptureDevices","requestedCaptureDevices","cloneDeep","Resolutions","cameraDeviceId","USER","allowedAudioProps","validConstraints","micDeviceId","getConstraints","desktopStream","desktopAudioTracks","desktopAudioStream","desktopVideoTracks","desktopVideoStream","avStream","audioTracks","audioStream","effects","videoStream","CAMERA","_ref3","stopMediaStream","deviceType","mediaStream","release","isDesktopSharingEnabled","setAudioOutputDevice","AUDIO_OUTPUT_DEVICE_CHANGED","getCurrentlyAvailableMediaDevices","getEventDataForActiveDevice","deviceData","isUserStreamById","trackHandler2Prop","JitsiTrack","streamInactiveHandler","trackMediaType","containers","_streamInactiveHandler","_setStream","_addMediaStreamInactiveHandler","onended","oninactive","_attachTTFMTracker","_container","_onTrackAttach","_onTrackDetach","_setHandler","_unregisterHandlers","videoTrack","isWebRTCTrackMuted","_this$track","attach","container","_decode","RTCUtils","detach","getStreamId","getSsrc","getTrack","getTrackLabel","getTrackId","getUsageLabel","getVideoType","getHeight","getWidth","isLocalAudioTrack","newAudioLevel","TRACK_AUDIO_LEVEL_CHANGED","NO_AUDIO_INPUT","setAudioOutput","allSettled","results","TRACK_AUDIO_OUTPUT_CHANGED","env","wasm","wasmPaths","JitsiLocalTrack","rtcId","_ref$effects","_setEffectInProgress","effect","isEnabled","_startStreamEffect","_this$_constraints$he","_constraints","_encodedStream","_encodedTrack","maxEnabledResolution","_prevSetMuted","_facingMode","_trackEnded","_hasSentData","_testDataSent","_realDeviceId","_sourceName","_ssrc","_trackMutedTS","_onDeviceListWillChange","oldRealDeviceId","_setRealDeviceIdFromDeviceList","_onAudioOutputDeviceChanged","_initNoDataFromSourceHandlers","_addStreamToConferenceAsUnmute","_addLocalTrackToPc","_fireNoDataFromSourceEvent","isReceivingData","createNoDataFromSourceEvent","_isNoDataFromSourceEventsEnabled","TRACK_UNMUTED","_queueSetMuted","setMuted","_setMuted","_removeStreamFromConferenceAsMute","_removeLocalTrackFromPc","logMuteInfo","_this$_streamEffect","_streamEffect","_stopStreamEffect","stopStream","streamOptions","getDeviceId","getCameraFacingMode","streamsInfo","cont","_this$conference","_sendMuteStatus","AUDIO_MUTE_CHANGED_EVENT","VIDEO_MUTE_CHANGED_EVENT","_sendBridgeVideoTypeMessage","TRACK_MUTE_CHANGED","_originalStream","startEffect","_effectEnabled","stopEffect","_switchCamera","ENVIRONMENT","_switchStreamEffect","setEffect","encodingRoutine","canvasEncoded","captureStream","_applyONNXEncoder","imageCapture","ImageCapture","canvasRaw","ctxRaw","getContext","willReadFrequently","ctxEncoded","processFrame","frame","grabFrame","drawImage","encodedImg","createImageData","putImageData","requestAnimationFrame","getEncodedStream","getEncodedTrack","mute","_setTrackMuteStatus","sendPresence","_this$track$getSettin","trackSettings","getCaptureResolution","getDuration","_this$conference2","isEnded","_this$_streamEffect2","_this$track2","_stopStreamInProgress","getConnectionState","NO_BYTES_SENT","setConference","setSsrc","unmute","_this$_streamEffect3","_mediaStreamData2","hasAudioMixEffect","hasConference","audioAnalyser","getAudioAnalyser","_trackRemoved","initialSettings","deviceIdKey","mediaStreamData","_mediaStreamData","constraintsToApply","_trackAdded","CodecMimeType","MediaDirection","SignalingEvents","getSourceNameForJitsiTrack","trackIdx","substring","getMediaTypeFromSourceName","firstLetterOfMediaTypeIdx","lastIndexOf","firstLetterOfMediaType","getEndpointIdFromSourceName","getSourceIndexFromSourceName","nameParts","isTranslatedSourceName","SignalingLayer","getPeerMediaInfo","getPeerSourceInfo","getSSRCOwner","getTrackSourceName","removeSSRCOwners","ssrcList","setSSRCOwner","setTrackMuteStatus","setTrackVideoType","updateSsrcOwnersOnLeave","SIM_LAYERS","scaleFactor","SSRC_GROUP_SEMANTICS","STANDARD_CODEC_SETTINGS","av1","maxBitratesVideo","fullHd","high","low","none","ssHigh","standard","ultraHd","scalabilityModeEnabled","useKSVC","useSimulcast","h264","vp8","vp9","VIDEO_CODECS_BY_COMPLEXITY","AV1","VP9","VP8","VIDEO_QUALITY_LEVELS","VIDEO_QUALITY_SETTINGS","parsePrimarySSRC","group","ssrcs","parseSecondarySSRC","_getSSRCCount","ssrcInfo","MLineWrap","_mLine","ssrcGroups","getSSRCAttrValue","ssrcNumber","attrName","attribute","ssrcObj","removeSSRC","ssrcNum","_this$_mLine$ssrcs","addSSRCAttribute","findGroup","semantics","findGroups","findGroupByPrimarySSRC","primarySSRC","getSSRCCount","containsAnySSRCGroups","getPrimaryVideoSsrc","simGroup","SIM","fidGroup","FID","fecGroup","getRtxSSRC","primarySsrc","getSSRCs","getPrimaryVideoSSRCs","videoSSRCs","ssrcGroupInfo","secondarySsrc","removeGroupsWithSSRC","groupInfo","removeGroupsBySemantics","addSSRCGroup","SdpTransformWrap","rawSDP","parsedSDP","selectMedia","selectedMLines","media","toRawSDP","LocalSdpMunger","localEndpointId","_tpc","_localEndpointId","_transformMediaIdentifiers","ssrcMap","_mediaSection$_mLine$","_mediaSection$_mLine$2","_mediaSection$_mLine$3","mediaDirection","msid","sortedSources","trackSsrcs","isEqual","SENDONLY","SENDRECV","_this$_tpc$getLocalVi","generatedMsid","existingMsid","getLocalVideoTracks","mid","midHasSentTrack","_midsWithSentTrack","RECVONLY","INACTIVE","transformStreamIdentifiers","sessionDesc","_transformer$selectMe","transformer","audioMLine","videoMlines","videoMLine","SDPUtil","buildICECandidate","foundation","component","priority","hasOwnAttribute","tcptype","generation","buildICEPwd","pwd","buildICEUfrag","frag","buildMLine","mline","fmt","buildRTPMap","el","getAttribute","candidateFromJingle","candidateToJingle","elems","network","filterSpecialChars","text","findLine","haystack","needle","sessionpart","lines","j","findLines","needles","generateSsrc","RandomUtil","getSsrcAttribute","attributeName","ssrcLine","getUfrag","ufragLines","startsWith","iceparams","mediadesc","sessiondesc","ufrag","parseICEPwd","parseICEUfrag","parseCrypto","parts","parseExtmap","uri","parseFingerprint","hash","fingerprint","parseFmtp","parseGroupSsrcs","ssrcGroup","ssrcStr","parseICECandidate","parseMID","parseMLine","parseMSIDAttribute","ssrcLines","msidLine","parsePrimaryVideoSsrc","_videoMLine$ssrcGroup","numSsrcs","numGroups","parseRTCPFB","pt","parseRTPMap","clockrate","channels","parseSCTPMap","parseSCTPPort","parseSSRC","parseSSRCGroupLine","parseSourceNameLine","sourceNameLine","ssrcSdpLine","parseVideoTypeLine","videoTypeLine","preferCodec","codecName","sortPayloadTypes","matchingPayloadTypes","rtp","H264","payloadsWithMode0","fmtp","item","reverse","payloadType","unshift","payloadTypes","payloads","payloadIndex","replaceIceCredentialsAndStripCandidates","patched","cr","content","stripCodec","highProfile","highProfileCodecs","removePts","rtxApts","rtxPts","keepPts","rtcpFb","updateAssociatedRtxStream","primarySsrcInfo","rtxSsrc","primarySsrcMsid","primarySsrcCname","cname","previousRtxSSRC","RtxModifier","correspondingRtxSsrcs","clearSsrcCache","setSsrcCache","ssrcMapping","modifyRtxSsrcs","sdpStr","modified","sdpTransformer","videoMLines","modifyRtxSsrcs2","primaryVideoSsrcs","correspondingRtxSsrc","stripRtx","fidGroups","XEP","findAll","querySelectorAll","getText","textContent","exists","querySelector","findFirst","INVALID_XML_CHARS_REGEXP","stripXMLInvalidChars","SDP","_updateSessionAndMediaSections","raw","failICE","removeTcpCandidates","removeUdpCandidates","_adjustMsidSemantic","mediaI","_removeLinesWithPrefix","updateRemoteSources","sourceMap","isAdd","updatedMidIndices","groups","addMlineForNewSource","updatedMsid","_SDPUtil$parseMLine","isRemote","newMid","mids","fromJingle","BUNDLE_MEDIA","_findAll","contents","ICE_UDP_TRANSPORT","DTLS_SRTP","fp","jingle2media","newSession","newMedia","_mLine$ssrcs","APPLICATION","newMline","_mLine$ssrcGroups","_mline$ssrcs","bundleOnly","ssrcId","g","otherSsrc","otherSource","msidSemantic","semantic","token","origin","sessionVersion","getMediaSsrcMap","mediaItem","mediaindex","midLine","linessrc","SCTP_DATA_CHANNEL","setup","setAttribute","parameters","parameter","rtcpFbFromJingle","RTP_HEADER_EXTENSIONS","hdrExt","SOURCE_ATTRIBUTES","children","child","localName","userSources","nonUserSources","isUserSource","sourceStr","_value","_value2","elem","payloadtype","feedbackElementTrrInt","RTP_FEEDBACK","fb","hasAttribute","rtcpFbToJingle","mediaIndex","feedback","xmlns","up","attrs","toJingle","thecreator","mediaTypes","assrcline","isRecvOnly","tree","availableSsrc","ssrcParameters","xmlElement","param","append","_SDPUtil$parseSSRCGro","creator","initialLastN","RTP_MEDIA","format","rtpmap","afmtpline","_ref4","_SDPUtil$parseSSRCGro2","ridLines","rids","ridLine","extmapLine","extmap","transportToJingle","sctpport","sctpmap","sctpAttrs","fingerprints","hasCryptex","setupLine","cryptex","iceParameters","SdpSimulcast","_ssrcCache","_numOfLayers","_fillSsrcsFromCache","cachedSsrcs","newSsrcs","_parseSimLayers","newMsid","_getSsrcAttribute","newCname","_generateNewSsrcsForSimulcast","simSsrcs","simSsrc","_generateSsrc","_mLine$ssrcs2","mungeLocalDescription","_media$ssrcs","_media$ssrcGroups$len","_media$ssrcGroups","_media$ssrcs$","simulcastSsrcs","TrackStreamingStatus","TrackStreamingStatusImpl","_getNewStateForJvbMode","isInForwardedSources","isRestoringTimedout","isVideoTrackFrozen","ACTIVE","INTERRUPTED","RESTORING","_getNewStateForP2PMode","restoringTimer","rtcMutedTimestamp","streamingStatusMap","trackTimer","_lastFramesDecoded","_lastFramesDecodedAt","_statsTrackFrozen","outOfForwardedSourcesTimeout","p2pRtcMuteTimeout","rtcMuteTimeout","_getVideoFrozenTimeout","isP2PActive","_onP2PStatus","figureOutStreamingStatus","P2P_STATUS","_onUserLeft","onUserLeft","USER_LEFT","_onTrackRtcMuted","onTrackRtcMuted","REMOTE_TRACK_MUTE","_onTrackRtcUnmuted","onTrackRtcUnmuted","REMOTE_TRACK_UNMUTE","_onSignallingMuteChanged","onSignallingMuteChanged","_onTrackVideoTypeChanged","onTrackVideoTypeChanged","TRACK_VIDEOTYPE_CHANGED","_onForwardedSourcesChanged","onForwardedSourcesChanged","_onLastNValueChanged","LASTN_VALUE_CHANGED","_onConnectionStats","_handleFramesDecodedUpdate","clearRtcMutedTimestamp","maybeSendTrackStreamingStatusEvent","_changeStreamingStatus","newStatus","getTrackStreamingStatus","_setTrackStreamingStatus","TRACK_STREAMING_STATUS_CHANGED","REMOTE_SOURCE_SUSPENDED_EVENT","REMOTE_SOURCE_INTERRUPTED_EVENT","isVideoRTCMuted","_this$_lastFramesDeco","inP2PMode","isRestoringTimedOut","_isRestoringTimedout","audioOnlyMode","getLastN","newState","_clearRestoringTimer","oldStreamingStatus","streamingStatus","nowMs","startedMs","trackStreamingStatus","createTrackStreamingStatusEvent","leavingForwardedSources","enteringForwardedSources","_clearEnteredForwardedSourcesTimestamp","_setEnteredForwardedSourcesTimestamp","rTimer","enteredForwardedSourcesTimestamp","_getEnteredForwardedSourcesTimestamp","_isCurrentTrack","ort","numThreads","ttfmTrackerAudioAttached","ttfmTrackerVideoAttached","decodingSession","modelPath","InferenceSession","enableCpuMemArena","executionProviders","freeDimensionOverrides","batch","graphOptimizationLevel","loadDecoder","containerEvents","JitsiRemoteTrack","ownerEndpointId","_muted","_rtc","_trackStreamingStatus","_trackStreamingStatusImpl","_enteredForwardedSourcesTimestamp","_addEventListener","_removeEventListener","_hasBeenMuted","_bindTrackHandlers","_containerHandlers","_containerEventHandler","_onTrackMute","_onTrackUnmute","_initTrackStreamingStatus","_disposeTrackStreamingStatus","_playCallback","getConnectionTimes","gumStart","gumEnd","gumDuration","ttfm","_getStatus","_peerConnStatusOutOfLastNTimeout","_p2pConnStatusRtcMuteTimeout","_peerConnStatusRtcMuteTimeout","isDecoderOn","decoderIsOn","increaseResolution","_animationFrameId","trackID","cancelAnimationFrame","canvasDecoded","_decodedStream","_rawVideo","play","ctxDecoded","isProcessingFrame","wasDisposed","videoWidth","videoHeight","HTMLMediaElement","HAVE_CURRENT_DATA","outInference","nwidth","nheight","shouldDecode","dataOutput","inputBuffer","inputTensor","Float32Array","Tensor","ImageData","imageEncode","getImageData","run","output","_outInference","decode","pause","setMute","VideoEncoderScalabilityMode","VIDEO_CODECS","TPCUtils","codecSettings","videoQualitySettings","videoQuality","_codecConfig$maxBitra","_videoQualitySettings","codecConfig","bitrateSettings","maxbitratesvideo","_calculateActiveEncodingParams","localVideoTrack","newHeight","_this$options$videoQu","codecBitrates","trackCaptureHeight","effectiveNewHeight","desktopShareBitrate","desktopbitrate","isScreenshare","scalabilityMode","L3T3_KEY","L3T3","_VIDEO_QUALITY_LEVELS","lvl","maxBitrate","_isScreenshareBitrateCapped","L1T3","ULTRA","FULL","HIGH","STANDARD","L2T3_KEY","L2T3","_getConfiguredVideoCodecsImpl","parsedSdp","_getVideoStreamEncodings","localTrack","captureResolution","cameraMaxbitrate","effectiveScaleFactors","sim","effectiveBitrates","standardSimulcastEncodings","videoTransferActive","encoding","_isRunningInFullSvcMode","_capScreenshareBitrate","_stripSdesMid","mungedSdp","ext","calculateEncodingsActiveState","videoStreamEncodings","activeState","isSpatialScalabilityOn","_videoStreamEncodings","calculateEncodingsBitrates","_this$options$videoQu2","calculateEncodingsScalabilityMode","scalabilityModes","calculateEncodingsScaleFactor","isRunningInSimulcastMode","ensureCorrectOrderOfSsrcs","reorderedSsrcs","getConfiguredVideoCodec","_this$pc$remoteDescri","rtpSender","findSenderForTrack","usesCodecSelectionAPI","remoteDescription","localTrackTransceiverMids","getConfiguredVideoCodecs","_this$pc$localDescrip","currentSdp","localDescription","getDesiredMediaDirection","isAddOperation","hasLocalSource","getStreamEncodings","audioTransferActive","injectSsrcGroupForSimulcast","simulcast","simulcast_03","insertUnifiedPlanSimulcastReceive","simulcastLine","mLines","senderMids","_this$codecSettings","mungeCodecOrder","currentCodecs","ULPFEC","RED","codecList","mungeOpus","enableOpusDtx","opusMaxAverageBitrate","OPUS","fmtpOpus","fmtpConfig","sdpChanged","maxaveragebitrate","usedtx","mungedConfig","setMaxBitrates","isLocalSdp","pcCodecSettings","currentCodec","codecScalabilityModeSettings","isDoingVp9KSvc","limit","TraceablePeerConnection","signalingLayer","_transceiver$sender","_parameters$encodings","_t$sender","_t$receiver","desiredEncodings","tpcUtils","desired","enable","_parameters$encodings2","_sender$track","getMediaTransferDirection","_transceiver","isInitiator","localTracks","webrtcStream","mediaStreamTrack","transceiverInit","_setEncodings","_dtmfSender","_dtmfTonesQueue","_pcId","remoteTracksBySsrc","remoteTracks","localSSRCs","remoteSSRCs","remoteSources","_localUfrag","_remoteUfrag","_dtlsTransport","_signalingLayer","_peerVideoTypeChanged","PEER_VIDEO_TYPE_CHANGED","_peerMutedChanged","PEER_MUTED_CHANGED","_audioQualityConfig$o","_audioQualityConfig$o2","audioQualityConfig","opusMaxAverageBitrateStereo","opusMaxAverageBitrateMono","audioQualityLocal","audioQualityRemote","SOURCE_MUTED_CHANGED","_sourceMutedChanged","SOURCE_VIDEO_TYPE_CHANGED","_sourceVideoTypeChanged","safeConstraints","updateLog","statsinterval","capScreenshareBitrate","_usesCodecSelectionAPI","maxstats","localSdpMunger","getLocalEndpointId","rtxModifier","_senderMaxHeights","_localSsrcMap","_remoteSsrcMap","what","time","onicecandidate","onTrack","evt","_remoteTrackAdded","_remoteTrackRemoved","onsignalingstatechange","oniceconnectionstatechange","onnegotiationneeded","onconnectionstatechange","ondatachannel","_processStat","_lastVideoSenderUpdatePromise","getTransceiverDirection","hasTrack","mediaTransferActive","getRemoteTracks","_getReceiversByEndpointIds","endpoints","remoteTrackIds","remote","_remote$track","_receiver$track","_adjustRemoteMediaDirection","localSources","_getPreferredCodecForScreenshare","defaultCodec","screenshareCodec","_initializeDtlsTransport","onstatechange","_updateVideoSenderParameters","_configureSenderEncodings","_mungeDescription","dumpSDP","mungedDescription","nextFunction","nextPromise","_updateVideoSenderEncodings","preferredCodec","_parameters$encodings3","videoSender","isScreensharingTrack","preference","degradationPreference","codecForCamera","bitrates","scaleFactors","needsUpdate","_encoding$active","_encoding$codec","_encoding$maxBitrate","_encoding$scalability","_encoding$scaleResolu","expectedPattern","matchingCodec","VIDEO_CODEC_CHANGED","LOCAL_TRACK_MAX_ENABLED_RESOLUTION_CHANGED","_onToneChange","tone","_this$_dtmfTonesQueue","tones","duration","interToneGap","insertDTMF","_createOfferOrAnswer","isOffer","logName","handleSuccess","resultSdp","resolveFn","rejectFn","_resultSdp2","_resultSdp","disableRtx","_processAndExtractSourceInfo","handleFailure","_RTCRtpReceiver$getCa","transceivers","_t$receiver2","capabilities","caps","setCodecPreferences","oaPromise","_extractPrimarySSRC","_ssrcObj$groups","_ssrcObj$ssrcs","_sendRtcStatsEvent","SCREENSHARE_MUTE_CHANGED_EVENT","statValue","endTime","startTime","times","h264SimulcastEnabled","disableSimulcast","getSynchronizationSources","_this$localSSRCs$get","remoteTrack","endpointTracksByMediaType","getRemoteSourceInfoBySourceName","getRemoteSourceInfoByParticipant","removeSsrcInfo","primarySsrcs","_sourceInfo$ssrcList","getTargetVideoBitrates","_this$localSSRCs$get2","findTrackById","_this$remoteDescripti","_peerMediaInfo$muted","remoteSDP","mediaLine","mls","trackSsrc","peerMediaInfo","trackDetails","_createRemoteTrack","remoteTracksMap","userTracksByMediaType","_userTracksByMediaTyp","jitsiTrack","toBeRemoved","_removeRemoteTrack","_userTracksByMediaTyp2","localSDP","_ssrcs","trackIndex","parsedGroup","groupSsrcs","oldSsrcInfo","oldSsrc","newSsrc","_getSSRC","isSharingLowFpsScreen","_isSharingScreen","addTrackToPc","_assertTrackBelongs","replaceTrack","shouldRenegotiate","_track$getTrack","_track$getTrack$getSe","_this$audioQualityLoc","_this$audioQualityLoc2","methodName","doesBelong","lowFps","setVideoCodecs","updated","configureVideoSenderEncodings","CODEC_CHANGED_EVENT","camera","screenshare","webRtcStream","findReceiverForTrack","processLocalSdpForTransceiverInfo","_this$localDescriptio","localSdp","oldTrack","newTrack","_newTrack$getType","_newTrack$getTrack","isMuteOperation","isNewLocalSource","currentDirection","stopped","_newTrack$getSourceNa","transceiverMid","_transceiver2","oldTrackSSRC","oldSsrcNum","removeTrackFromPc","_ref6","_ref7","calculateExpectedSendResolution","maxValue","configureAudioSenderEncodings","localAudioTrack","promises","_this$_senderMaxHeigh","setSenderVideoConstraints","_this$_senderMaxHeigh2","localUfrag","LOCAL_UFRAG_CHANGED","remoteUfrag","REMOTE_UFRAG_CHANGED","setMediaTransferActive","_enableSenderEncodings","settledResult","errors","setVideoTransferActive","changed","sendTones","ontonechange","toneBuffer","peerTracks","_removePeerConnection","addRemoteSsrc","existing","peerConnectionIdCounter","rtcTrackIdCounter","_createLocalTracks","metaData","RTC","peerConnections","_lastN","_forwardedSources","_forwardedSourcesChangeListener","_onDeviceListChanged","_updateAudioOutputForAudioTracks","destroy","_channelOpenListener","createLocalTracks","tracksInfo","initializeBridgeChannel","logError","msgType","_receiverVideoConstraints","oldForwardedSources","setReceiverVideoConstraints","sendSourceVideoType","eventType","createPeerConnection","signaling","enableInsertableStreams","encodedInsertableStreams","forceTurnRelay","iceTransportPolicy","bundlePolicy","newConnection","traceablePeerConnection","addLocalTrack","getForwardedSources","getLocalVideoTrack","localVideo","getLocalAudioTrack","localAudio","pcRemoteTracks","mutePromises","audioTrack","removeLocalTrack","elSelector","isWebRtcSupported","closeBridgeChannel","sendChannelMessage","setLastN","remoteAudioTracks","ConnectionQualityEvents","ConnectionQuality","_localStats","connectionQuality","jvbRTT","_lastConnectionQualityUpdate","_remoteStats","_timeIceConnected","_timeVideoUnmuted","ConferenceEvents","_this$_localStats","CONNECTION_INTERRUPTED","_updateLocalConnectionQuality","LOCAL_STATS_UPDATED","_broadcastLocalStats","ICE_CONNECTION_STATE_CHANGED","_updateRemoteStats","disableLocalStats","_updateLocalStats","_maybeUpdateUnmuteTime","_resetVideoUnmuteTime","_MEDIA_SESSION_ACTIVE_CHANGED","SERVER_REGION_CHANGED","serverRegion","PROPERTIES_CHANGED","bridgeCount","disableLocalStatsBroadcast","_calculateConnectionQuality","resolutionName","quality","activeTPC","getActivePeerConnection","_this$_options$config","_this$_options$config2","millisSinceStart","qualityLevel","targetHeight","pow","rampUp","getTarget","maxIncreasePerSecond","prevConnectionQuality","diffSeconds","_data$transport","updateLocalConnectionQuality","isConnectionInterrupted","REMOTE_STATS_UPDATED","IceFailedHandling","_actOnIceFailed","jvbConnection","jvbConnIceState","getIceConnectionState","JVB_ICE_RESTARTED_EVENT","_stopJvbSession","reasonDescription","requestRestart","sendSessionTerminate","ping","_canceled","_iceFailedTimeout","cancel","DetectionEvents","NoAudioSignalDetection","_timeoutTrigger","_hasAudioInput","_audioTrack","_eventFired","_clearTriggerTimeout","_handleAudioInputStateChange","AUDIO_INPUT_STATE_CHANGE","_handleNoAudioInputDetection","_audioLevel","P2PDominantSpeakerDetection","myUserID","createAudioContext","AudioContextImpl","TrackVADEmitter","procNodeSampleRate","vadProcessor","jitsiLocalTrack","_procNodeSampleRate","_vadProcessor","_localTrack","_bufferResidue","_audioContext","sampleRate","getRequiredPCMFrequency","_vadSampleSize","getSampleLength","_onAudioProcess","_initializeAudioContext","_audioSource","_audioProcessingNode","createScriptProcessor","audioEvent","inData","getChannelData","completeInData","sampleTimestamp","pcmSample","vadScore","calculateAudioFrameVAD","VAD_SCORE_PUBLISHED","pcmData","score","_connectAudioGraph","onaudioprocess","destination","_disconnectAudioGraph","_cleanupResources","_destroyed","VADAudioAnalyser","createVADProcessor","_createVADProcessor","_vadEmitter","_isVADEmitterRunning","_detectionServices","_vadInitTracker","_processVADScore","_trackMuteChanged","addVADDetectionService","vadService","DETECTOR_STATE_CHANGE","detector","_stopVADEmitter","_startVADEmitter","processVADScore","_changeDetectorsMuteState","changeMuteState","vadEmitter","VADNoiseDetection","_processing","_scoreArray","_audioLvlArray","_active","_processTimeout","_calculateNoisyScore","scoreAvg","audioLevelAvg","VAD_NOISY_DEVICE","_setActiveState","_recordValues","avgAudioLvl","posAudioLevels","VADTalkMutedDetection","_calculateVADScore","VAD_TALK_WHILE_MUTED","InvalidTokenError","symbolToString","baseToString","arrayMap","isSymbol","reEscapedHtml","reHasEscapedHtml","unescapeHtmlChar","JitsiConnectionErrors","CONFERENCE_REQUEST_FAILED","CONNECTION_DROPPED_ERROR","NOT_LIVE_ERROR","OTHER_ERROR","SERVER_ERROR","SHARD_CHANGED_ERROR","sha1_ft","sha1_kt","safe_add","lsw","rol","num","cnt","SHA1","binarray","triplet","str","binb2b64","olda","oldb","oldc","oldd","olde","w","core_sha1","bin","charCodeAt","str2binb","IDENTITY_PROPERTIES","IDENTITY_PROPERTIES_FOR_COMPARE","compareIdentities","parseDiscoInfo","node","identities","category","Caps","disco","rooms","externalFeatures","emuc","EMUC_ROOM_ADDED","_addChatRoom","EMUC_ROOM_REMOVED","_removeChatRoom","addNamespace","addFeature","NS","CAPS","_getDiscoInfo","_fixChatRoomPresenceMap","_updateRoomWithExternalFeatures","addOrReplaceInPresence","ver","_generateVersion","sortedIdentities","accumulatedValue","tmp","sortedFeatures","sha1","generateSha","_identities","_notifyVersionChanged","removeFromPresence","submit","external","getFeaturesAndIdentities","removeFeature","IDENTITY_TYPE","FileSharing","_mainRoom","_xmpp","_handleMessages","FILE_SHARING_EVENT","fileSharingComponentAddress","getIdentityType","addFile","_sendMessage","removeFile","fileId","$msg","file","files","NETWORK_INFO_EVENT","networkInfo","_current","isOnline","updateNetworkInfo","getJitterDelay","retry","minDelay","ResumeTask","stropheConnection","_stropheConn","_resumeRetryN","_retryDelay","_resumeTimeout","_networkOnlineListener","retryCount","retryDelay","_removeNetworkOnlineListener","_scheduleResume","resumeConnection","cancelResume","streamManagement","resumeToken","getResumeToken","URL","service","search","pattern","oldToken","schedule","NetworkInfo","LastRequestTracker","_lastSuccess","_lastFailedMessage","startTracking","xmppConnection","originalRawInput","rawInput","rawMessage","connected","getLastFailedMessage","getTimeSinceLastSuccess","autoSendCountOnEveryIncomingStanza","requestResponseInterval","_c","_NS","_isStreamManagementEnabled","_serverProcesssedStanzasCounter","_clientProcessedStanzasCounter","_clientSentStanzasCounter","_originalXMLOutput","_requestHandler","_incomingHandler","_requestResponseIntervalCount","_isSupported","_unacknowledgedStanzas","_acknowledgedStanzaListeners","addAcknowledgedStanzaListener","_connectionStatus","Status","CONNECTED","$build","_resumeToken","DISCONNECTED","explicitResourceBinding","_resuming","_originalConnect","_connectArgs","requestAcknowledgement","getOutgoingCounter","getIncomingCounter","conn","xmlOutput","_interceptConnectArgs","_originalOnStreamFeaturesAfterSASL","_onStreamFeaturesAfterSASL","_originalDoDisconnect","_doDisconnect","_interceptDoDisconnect","_originalDisconnect","_interceptDisconnect","disconnecting","_resumeState","timedHandlers","removeTimeds","removeHandlers","addTimeds","addHandlers","_storedJid","_data","getElementsByTagNameNS","statusChanged","BINDREQUIRED","h","_addSysHandler","ns","addTimedHandler","period","deleteTimedHandler","previd","ERROR","deleteHandler","addHandler","_handleServerRequestHandler","_ackHandler","_handleServerAck","_incomingStanzaHandler","_enabledHandler","_handleEnabled","_resumeFailedHandler","_handleResumeFailed","_resumedHandler","_handleResumed","isTagEqual","_increaseSentStanzasCounter","firstElementChild","tagName","firstChild","_changeConnectStatus","handledCount","_handleAcknowledgedStanzas","do_bind","authenticated","restored","stanza","_increaseReceivedStanzasCounter","_answerProcessedStanzas","reportedHandledCount","lastKnownHandledCount","delta","_throwError","getConnectionPluginDefinition","addConnectionPlugin","ConnectionPluginListenable","PingConnectionPlugin","ConnectionPlugin","getTimeSinceLastServerResponse","onPingThresholdExceeded","_ref$pingOptions","pingOptions","failedPings","_onPingThresholdExceeded","_getTimeSinceLastServerResponse","pingTimeout","pingThreshold","threshold","pingTimestampsToKeep","pingExecIntervals","success","_addPingExecutionTimestamp","iq","$iq","PING","sendIQ2","startInterval","remoteJid","_lastServerCheck","errmsg","_this$_onPingThreshol","stopInterval","getPingSuspendTime","pingIntervals","maxInterval","previousTS","currentInterval","TOKEN_REFRESH","ExtendedStatus","XmppConnection","Events","CONN_SHARD_CHANGED","CONN_STATUS_CHANGED","enableWebsocketResume","websocketKeepAlive","websocketKeepAliveUrl","serviceUrl","shard","xmppPing","Connection","registerSASLMechanisms","SASLAnonymous","SASLPlain","SASLSHA1","_usesWebsocket","maxRetries","_rawInputTracker","LastSuccessTracker","_resumeTask","_deferredIQs","_onPingErrorThresholdExceeded","_oneSuccessfulConnect","_this$_stropheConn","websocket","_proto","socket","ATTACHED","isUsingWebSocket","domain","lastResponseHeaders","_this$_stropheConn$_p","pingDomain","_this$_options$pingOp","plugin","sid","_stropheConnectionCb","pass","targetCallback","condition","_this$_options$pingOp2","_maybeEnableStreamResume","_maybeStartWSKeepAlive","_processDeferredIQs","_tryResumingConnection","RESUMING","_wsKeepAlive","_clearDeferredIQs","deferred","closeWebsocket","_this$_stropheConn2","_closeSocket","_onClose","forcedTimeout","_keepAliveAndCheckShard","_this$_options","fetch","responseShard","timeLeft","sendIQ","_this$_stropheConn3","errback","sendUnavailableBeacon","sendBeacon","DISCONNECTING","_buildBody","pres","$pres","CLIENT","cnode","_abortAllRequests","force","refreshToken","_this$_stropheConn$st","timeoutId","unsubscribe","handleStropheError","errResponse","errorObj","errorEl","errorElements","getElementsByTagName","reasonEl","msgEl","outerHTML","STROPHE_ERROR_EVENT","createExpBackoffTimer","step","Moderator","_this$options$hosts","_this$options$hosts2","getNextTimeout","getNextErrorTimeout","sipGatewayEnabled","visitorsSupported","targetJid","hosts","focus","targetUrl","conferenceRequestUrl","focusUserJids","focusUserJid","location","isFocusJid","focusJid","isSipGatewayEnabled","_createConferenceRequest","roomJid","_config$analytics$rtc","_config$analytics","startAudioMuted","startVideoMuted","conferenceRequest","machineUid","iAmRecorder","iAmSipGateway","preferVisitor","visitor","_createConferenceIq","_parseConferenceIq","resultIq","conferenceEl","ready","vnode","authentication","externalAuth","live","sendConferenceRequest","conferenceRequestSent","_handleIqSuccess","_handleIqError","ok","json","resultJson","_handleSuccess","statusText","sessionError","notAuthorized","_handleError","_breakoutMovingToMain","authenticationEnabled","waitMs","operation","userJid","reservationErr","errorTextNode","invalidSession","authenticate","errorIq","_errorEl$children","firstErrorChild","logout","_connection","_items","_onDiscoInfo","DISCO_INFO","_onDiscoItems","DISCO_ITEMS","addIdentity","lang","var_name","addItem","call_back","items","_buildIQResult","query_attrs","iqresult","JitsiTranscriptionStatus","ON","OFF","AVModeration","_moderationEnabledByType","_whitelistAudio","_whitelistDesktop","_whitelistVideo","_onMessage","AV_MODERATION_RECEIVED","avModerationComponentAddress","approve","jidToWhitelist","jidToBlacklist","removed","approved","newWhitelists","whitelists","oldList","newList","FEATURE_KEY","BREAKOUT_ROOM_ACTIONS","ADD","MOVE_TO_ROOM","REMOVE","RENAME","BREAKOUT_ROOM_EVENTS","BreakoutRooms","BREAKOUT_ROOMS_EVENT","_rooms","createBreakoutRoom","subject","removeBreakoutRoom","breakoutRoomJid","renameBreakoutRoom","sendParticipantToRoom","participantJid","isFeatureSupported","breakoutRoomsFeatures","getComponentAddress","breakoutRoomsComponentAddress","_setIsBreakoutRoom","_isBreakoutRoom","getDomainFromJid","myroomjid","_setMainRoomJid","_mainRoomJid","getMainRoomJid","filteredPayload","_filterUpdatePayload","hiddenDomain","filteredRooms","_room$participants","participants","filteredParticipants","abool","anumber","isSafeInteger","abytes","title","bytes","isView","needsLen","aexists","instance","checkFinished","destroyed","finished","u32","Uint32Array","clean","arrays","fill","isLE","wrapCipher","wrappedCipher","nonceLength","varSizeNonce","tagl","tagLength","cipher","checkOutput","fnLength","called","encrypt","decrypt","getOutput","expectedLength","out","onlyAligned","copyBytes","encodeStr","sigma16","sigma32","sigma16_32","sigma32_32","rotl","isAligned32","MAX_COUNTER","U32_EMPTY","of","createCipher","core","_checkOpts","defaults","allowShortKeys","counterLength","counterRight","rounds","checkOpts","extendNonceFn","nonce","counter","toClean","sigma","k32","subarray","nonceNcLen","nc","n32","block","b32","isAligned","d32","o32","take","pos32","posj","runCipher","u8to16","Poly1305","Uint16Array","t0","t1","t2","t3","t4","t5","t6","t7","pad","hibit","r0","r1","r2","r3","r4","r5","r6","r7","r8","r9","h0","h1","h2","h3","h4","h5","h6","h7","h8","h9","d0","d1","d2","d3","d4","d5","d6","d7","d8","d9","finalize","mask","update","blockLen","digestInto","outputLen","aoutput","opos","digest","poly1305","hashCons","hashC","wrapConstructorWithKey","chachaCore","y00","y01","y02","y03","y04","y05","y06","y07","y08","y09","y10","y11","y12","y13","y14","y15","x00","x01","x02","x03","x04","x05","x06","x07","x08","x09","x10","x11","x12","x13","x14","x15","oi","chacha20","xchacha20","ZEROS16","updatePadded","leftover","ZEROS32","computeTag","fn","ciphertext","AAD","authKey","lengths","dataLength","aadLength","view","setBigUint64","BigInt","u64Lengths","_poly1305_aead","xorStream","plaintext","plength","oPlain","passedTag","equalBytes","xchacha20poly1305","blockSize","B","A","u","U","S","TextDecoder","fromString","TextEncoder","encode","toArrayBuffer","fromArrayBuffer","U32_MASK64","_32n","fromBig","rotr","word","byteSwap","swap8IfBE","swap32IfBE","hasHexBuiltin","toHex","fromHex","hexes","_","padStart","utf8ToBytes","createHasher","freeze","randomBytes","bytesLength","globalThis","oidNist","suffix","oid","_0n","_1n","_2n","_7n","_256n","_0x71n","SHA3_PI","SHA3_ROTL","_SHA3_IOTA","R","IOTAS","lst","le","Ah","Al","_fromBig","SHA3_IOTA_H","SHA3_IOTA_L","rotlH","rotlBH","rotlSH","rotlL","rotlBL","rotlSL","Keccak","enableXOF","state32","clone","_cloneInto","keccak","idx1","idx0","B0","B1","Th","Tl","curH","curL","PI","keccakP","posOut","finish","writeInto","bufferOut","xofInto","xof","genKeccak","sha3_256","sha3_512","genShake","dkLen","shake128","shake256","checkU32","isPowerOfTwo","reverseBits","bits","reversed","log2","clz32","bitReversalInplace","FFTCore","F","coreOpts","N","roots","dit","_coreOpts$invertButte","invertButterflies","_coreOpts$skipStages","skipStages","_coreOpts$brp","brp","isDit","m2","stride","grp","i0","i1","omega","mul","sub","randb","splitCoder","getLength","bytesLen","sum","bufs","abytes_","vecCoder","vecLen","cleanBytes","list","getMask","createXofShake","shake","seed","_seed","seedLen","calls","xofs","XOF128","Q","_genCrystals","newPoly","ROOT_OF_UNITY","brvBits","isKyber","mod","modulo","nttZetas","getZettas","field","inv","nttOpts","dif","NTT","smod","bitsCoder","poly","bufLen","genCrystals","polyCoder","compress","polyAdd","BaseCaseMultiply","a0","a1","b0","b1","zeta","c0","c1","MultiplyNTTs","z","_BaseCaseMultiply","SampleNTT","sampleCBD","PRF","eta","bb","createKyber","KPKE","K","XOF","HASH512","ETA1","ETA2","du","dv","poly1","polyV","polyU","publicCoder","secretCoder","cipherCoder","seedCoder","secretKey","publicKey","cipherText","keygen","seedDst","seedHash","_seedCoder$decode2","rho","sHat","tHat","_publicCoder$decode2","rHat","tmp2","e1","e2","privateKey","_cipherCoder$decode2","sk","polySub","genKPKE","HASH256","KDF","KPKESecretCoder","msgRand","_KPKE$keygen","publicKeyHash","getPublicKey","_secretCoder$decode2","encapsulate","eke","ek","kr","sharedSecret","decapsulate","k768","_secretCoder$decode4","Khat","cipherText2","isValid","Kbar","ml_kem768","RBGstrength","base64ToUint8Array","base64","uint8ArrayToBase64","encapsulateKyber","decapsulateKyber","CHAT_AUX","decryptSymmetricallySync","encryptionKey","cipherBuffer","EMAIL_COMMAND","Lobby","mainRoom","maybeJoinLobbyRoom","_maybeJoinLobbyRoom","lobbyRoomJid","lobbySupported","initialDiscoRoomInfoReceived","membersOnlyEnabled","setMembersOnly","unsubscribers","remove","ROOM_DISCO_INFO_UPDATED","ROOM_DISCO_INFO_FAILED","disable","lobbyRoom","sendPrivateMessage","sendMessageRetraction","addMessageRetractionListener","removeMessageRetractionHandler","getLocalId","addMessageListener","removeMessageHandler","leave","setLobbyRoomJid","joined","email","getNodeFromJid","customDomain","createRoom","disableDiscoInfo","disableFocus","disableRoomCreationRetry","enableLobby","addPresenceListener","nick","isHiddenDomain","botType","members","avatar","isSelfPresence","INVITE_MESSAGE_RECEIVED","invitePassword","_this$lobbyRoom","_this$lobbyRoom2","ROOM_CREATION_RESTRICTION","denyAccess","kick","approveAccess","mainRoomJid","membersToApprove","ids","memberRoomJid","msgToSend","COMMAND_ANSWER_POLL","COMMAND_NEW_POLL","Polls","POLLS_EVENT","pollsComponentAddress","createPoll","pollId","question","answers","command","answerPoll","_payload$polls","polls","poll","history","RoomMetadata","ROOM_METADATA_EVENT","_metadata","setMetadata","getMetadata","roomMetadataComponentAddress","JITSI_MEET_MUC_TYPE","EMOJI_REGEX","json2packet","nodes","packet","packet2JSON","attr","xmlunescape","filterNodeFromPresenceJSON","nodeName","MEMBERS_AFFILIATIONS","extractIdentityInformation","hiddenFromRecorderFeatureEnabled","userInfo","HIDDEN_FROM_RECORDER","hiddenFromRecorder","ChatRoom","password","getBareJidFromJid","replaceParticipant","presMap","presHandlers","_removeConnListeners","inProgressEmitted","focusMucJid","noBridgeAvailable","pendingEncryptedMessages","eventsForwarder","moderator","lobby","avModeration","breakoutRooms","fileSharing","roomMetadata","initPresenceMap","lastPresences","phoneNumber","phonePin","participantPropertyListener","locked","transcriptionStatus","E2EE_CHAT_KEY_RECEIVED","setEncryptionKey","xns","statsId","presenceUpdateTime","_extractFeatures","var","_initFocus","focusFeatures","_onConnStatusChanged","presenceSyncTime","_processNode","_this$presHandlers$no","_parseReplyMessage","chatMessage","isVisitorMessage","fromJoin","doLeave","discoRoomInfo","getInfo","meetingIdValEl","setMeetingId","meetingCreatedTSValEl","membersOnly","lobbyRoomField","isBreakoutField","breakoutMainRoomField","meetingId","createNonAnonymousRoom","getForm","form","formSubmit","onPresence","member","statusEl","hasStatusUpdate","hasVersionUpdate","xElement","mucUserItem","isReplaceParticipant","affiliation","isFocus","PRESENCE_RECEIVED","fromHiddenDomain","presence","xEl","region","deploymentInfo","userRegion","permissionEl","permissionsMap","memberOfThis","participantProperties","displayJids","CONFERENCE_PROPERTIES_CHANGED","FEATURE_TRANSCRIBER","att","phone","pin","elementName","cleanMessage","sentMessage","encyptionKey","messageBuffer","concatBytes","encryptSymmetricallySync","SENDING_CHAT_MESSAGE","sendReaction","reaction","receiverId","SENDING_PRIVATE_CHAT_MESSAGE","for","setSubject","valueToProcess","moderateMessage","onPresenceUnavailable","destroySelect","reasonSelect","isKick","membersKeys","actorSelect","actorNick","onMessage","settingsErrorEl","settingsErrorMsg","reactions","reactionElem","bodyEl","subjectText","dateParts","invite","passwordSelect","jsonMessage","parsedJson","tryParseJSONAndVerify","applyToEl","moderatedEl","retractEl","retractedMessageId","displayNameEl","originalFrom","addressesEl","ofromEl","sourceAttrValue","isChatEncrypted","onPresenceError","errorDescriptionNode","anonymousdomain","_this$getBreakoutRoom","_roomCreationRetries","ROOM_UNAUTHENTICATED_ACCESS_DISABLED","NO_MAIN_PARTICIPANTS","PROMOTION_NOT_ALLOWED","NO_VISITORS_LOBBY","lobbyRoomNode","waitingForHost","setAffiliation","grantIQ","kickIQ","lockRoom","onNotSupported","formsubmit","affiliationsIq","sendIq","formToSubmit","matchingNodes","getFromPresence","tagHandlers","removePresenceListener","handlerIdx","mucJid","getMediaPresenceInfo","mutedNode","codecTypeNode","videoTypeNode","codecType","getMemberRole","peerJid","getLastPresence","mucNick","dial","rayo","hangup","getLobby","getAVModeration","getFileSharing","getMetadataHandler","getPolls","getPhoneNumber","getPhonePin","getMeetingId","muteParticipant","iqToFocus","onMute","onMuteVideo","onMuteDesktop","_this$lobby","onMucLeft","doReject","end","endConferenceComponentAddress","getShortTermCredentials","cachedCredentials","cachedShortTermCredentials","host","resultServiceEl","currentDate","expirationDate","MucConnectionPlugin","onVisitors","isRoomCreated","visitors","_createSourceExtension","sourceCompactJson","isVideo","_createSsrcGroupExtension","ssrcGroupCompactJson","_getOrCreateRtpDescription","appendChild","expandSourcesFromJson","jsonMessageXml","_json","audioRtpDescription","videoRtpDescription","ownerSources","videoSources","videoSsrcGroups","audioSources","audioSsrcGroups","_videoSources$i","_audioSources$i","IceRestartReason","RemoteAudioWedgeDetector","_options$wedgeTimeout","packetsBySsrc","_evaluate","_onWedgeDetected","onWedgeDetected","_wedgeTimeoutMs","wedgeTimeoutMs","_started","_eligibleZeroBySsrc","_healthyBySsrc","_recoveryStateBySsrc","candidates","recovery","attempts","cooldownUntil","candidateSsrcs","_packetsBySsrc$get","since","_this$_recoveryStateB","_this$_recoveryStateB2","_onInboundAudioStats","SDPDiffer","mySdp","othersSdp","getNewMedia","mySources","othersSources","othersSource","mySource","othersSsrcs","modify","diffSourceInfo","mediaSsrc","onlyOnce","callFn","_defer","hasQueueMicrotask","queueMicrotask","hasSetImmediate","setImmediate","hasNextTick","nextTick","defer","DLL","head","tail","removeLink","next","empty","insertAfter","newNode","insertBefore","setInitial","toArray","iterator","cur","testFn","curr","dll","handlePromise","invokeCallback","isAsync","asyncFn","asyncify","queue","worker","concurrency","_worker","wrapAsync","numRunning","workersList","drain","saturated","unsaturated","trigger","processingScheduled","_insert","insertAtFront","rejectOnError","rej","promiseCallback","q","started","_createTaskItem","_tasks","_createCB","tasks","_len3","_key3","task","idle","_maybeDrain","eventMethod","handleAndRemove","isProcessing","paused","datum","pushAsync","kill","unshiftAsync","running","defineProperties","ClearedQueueError","AsyncQueue","_queue","_processQueueTasks","_stopped","_taskCallbacks","finishedCallback","shutdown","ELEMENT","NAMESPACE","TRACE_ID_ATTR_NAME","PARENT_ID_ATTR_NAME","TRACE_FLAGS_ATTR_NAME","TraceParentExtension","traceId","parentId","traceFlags","fromElement","traceParentExtension","asAttributes","JingleSessionState","PENDING","ENDED","JingleSession","localJid","mediaConstraints","usedrip","dripContainer","initiatorJid","responderJid","doInitialize","initialize","addIceCandidates","getState","addSources","removeSources","terminate","failure","acceptOffer","MediaSessionEvents","IQ_TIMEOUT","ICE_RESTART_LOG_PREFIX","SSRC_PATTERN","isValidSsrc","getEndpointId","jidOrEndpointId","_addSourceElement","ssrc_","_s$videoType","JingleSessionPC","parseVideoSenders","jingleContents","parseSourceMaxFrameHeight","receiverConstraints","sourceFrameHeightSel","_bridgeSessionId","_cachedOldLocalSdp","_cachedNewLocalSdp","_iceCheckingStartedTimestamp","_gatheringStartedTimestamp","_iceRestartT0","_iceRestartStatsTimer","_lastIceGeneration","_sourceReceiverConstraints","_localSendReceiveVideoActive","_remoteSendReceiveVideoActive","_gatheringReported","lasticecandidate","numRemoteVideoSources","numRemoteAudioSources","remoteSourceMaxFrameHeights","modificationQueue","wasConnected","establishmentDuration","_audioWedgeDetector","_xmppListeners","onXmppStatusChanged","_removeSenderVideoConstraintsChangeListener","_addOrRemoveRemoteStream","logPrefix","_this$peerconnection$","errMsg","currentRemoteSdp","sourceDescription","_processSourceMapFromJingle","modifiedMids","desiredDirection","_renegotiate","_addRemoveTrack","isRemove","operationName","workFunction","_assertNotEnded","_maybeStartAudioWedgeDetector","_recoverWedgedAudioSource","_processNewJingleOfferIq","offerIq","remoteSdp","webrtcIceTcpDisable","webrtcIceUdpDisable","sourceElement","sourceElementArray","descriptionsWithSources","removeSsrcs","_sourceDescription$ge","DESKTOP_HIGH_FPS","detectedSource","_this$peerconnection","currentTrack","_currentTrack$getSour","buildSourceNode","optionalRemoteSdp","oldLocalSDP","answer","notifyMySSRCUpdate","_sendContentModify","sessionModify","initiator","newJingleErrorHandler","_sendIceCandidate","ice","jcand","_sendIceCandidates","cands","fingerprintLine","required","_startIceRestartStatsSampler","_this$_iceRestartT","debugIceRestart","sample","_this$peerconnection2","audioIn","audioOut","reqSent","respRecv","videoFramesDropped","videoFreezeCount","videoFreezeDurationMs","videoIn","videoOut","videoPliCount","pairsById","selectedPairId","_stat$bytesSent","_stat$bytesReceived","_stat$requestsSent","_stat$responsesReceiv","_stat$selectedCandida","_stat$framesDropped","_stat$freezeCount","_stat$totalFreezesDur","_stat$pliCount","bytesReceived","framesDropped","freezeCount","totalFreezesDuration","pliCount","requestsSent","responsesReceived","selectedCandidatePairId","pair","pairStr","_parseIceCandidates","candidateElements","_addIceCandidatesToPeerConnection","iceCandidates","iceCandidate","_sendIceRestartTransportInfo","transportInfo","medialines","_transportInfo$node","transportEl","lastElementChild","_sendSessionAccept","accept","responder","channelLastN","_sendSessionInitiate","offerSdp","_this$room","failureCb","Element","errorElSel","errorResponseChildren","_this$room2","oldSDP","newSDP","getSignaledSourceInfo","sdpDiffer","sourceNames","signaledSsrcs","ctx","removedSsrcInfo","P2P_TERMINATION_REQUIRED","SOURCE_REMOVE","SOURCE_REMOVE_ERROR","addedSsrcInfo","SOURCE_ADD","SOURCE_ADD_ERROR","setOfferAnswerCycle","jingleOfferAnswerIq","addTracks","newRemoteSdp","bridgeSessionId","restartIce","API","sessionInfo","ACTION_JINGLE_ICE_RESTART_REQUESTED","ICE_RESTART_REQUESTED_EVENT","_error$reason","onBridgeIceRestartTransport","dt","_this$peerconnection$2","patchedOffer","ACTION_JINGLE_ICE_RESTART_SUCCESS","ICE_RESTART_APPLIED_EVENT","jingleOffer","SESSION_ACCEPT","SESSION_ACCEPT_ERROR","_elem$","addRemoteStream","replaceTracks","recvOnlyTransceiver","_this$_audioWedgeDete","finishCallback","_this$peerconnection3","_options$testing","_options$testing$enab","_options$testing2","wasstable","pcOptions","gatherStats","enableCodecSelectionAPI","settings","fromEntries","ICE_DURATION","phase","isStable","ICE_STATE_CHANGED","reconnect","CONNECTION_RESTORED","iceStarted","CONNECTION_ICE_FAILED","icestate","getRemoteSourcesRecvMaxFrameHeight","modifyContents","newVideoSenders","sourceMaxFrameHeights","REMOTE_SOURCE_CONSTRAINTS_CHANGED","isRemoteVideoActive","onTerminated","reasonCondition","reasonText","oldSourceName","_this$_signalingLayer","rtx","removeRemoteStream","removeRemoteStreamsOnLeave","setAnswer","jingleAnswer","oldLocalSdp","newLocalSdp","setP2pVideoTransferActive","videoActive","setReceiverVideoConstraint","sourceReceiverConstraints","setSenderVideoConstraint","maxFrameHeight","currentCodecOrder","every","sessionTerminate","restart","_parseService","iceservers","dict","JingleConnectionPlugin","iceConfig","sessions","jvbIceConfig","jvb","p2pIceConfig","onJingle","jingleElement","fromJid","ack","sess","jsonMessages","_audioVideoSsrcs","audioVideoSsrcs","logMessage","transportElement","parseCandidates","candidateAttrs","reasonElement","_reasonElement$childr","firstReasonChild","newP2PJingleSession","me","peer","getStunAndTurnCredentials","v2Res","v1Res","_options$iceServersOv","iceServersOverride","targetType","temp","useTurnUdp","getLog","href","StropheLogger","logIncoming","rawOutput","logOutgoing","RAYO_XMLNS","RayoConnectionPlugin","onRayo","roomPass","req","callResource","lastErrorStatus","resetLastErrorStatusRegExpr","lastErrorStatusRegExpr","FAILURE_REGEX","DEFAULT_STUN_SERVERS","FEATURE_JIGASI","FEATURE_E2EE","XMPP","bosh","_disconnectInProgress","authenticatedUser","_components","_preComponentsMsgs","LogLevel","WARN","DEBUG","errStatusCapture","FATAL","getLastErrorStatus","getStatusString","CONNFAIL","AUTHENTICATING","AUTHFAIL","_ref$serviceUrl","createConnection","details","shard_changed","suspend_time","time_since_last_success","enableGracefulReconnect","header","part","decoded","decodeURIComponent","atob","b64DecodeUnicode","base64UrlDecode","jwtDecode","exp","_initStrophePlugins","initFeaturesList","_onPrivateMessage","disableBeforeUnloadHandlers","_unloadHandler","_unloadEventTypes","_removeUnloadHandlers","_this$options$audioTr","JINGLE","RTP_AUDIO","RTP_VIDEO","enableOpusRed","enableRemb","enableTcc","E2EEncryption","audioTranslation","users","SPEAKER_STATS_RECEIVED","FILE_SHARING_IDENTITY_TYPE","_maybeSendDeploymentInfoStat","acceptedStatuses","CONNTIMEOUT","sendDeploymentInfo","aprops","logObject","_processDiscoInfoIdentities","audioTranslationComponentAddress","speakerStatsComponentAddress","processLobbyFeatures","fr","backendRelease","processBreakoutRoomsFeatures","rename","sendDiscoInfo","_parseConnectionFailedMessage","_connect","_this$connection$_str","_resetState","_sysMessageHandler","_onSystemMessage","connectionHandler","_parseDiscoInfo","_cleanupXmppConnection","evType","sync","_startConnecting","_this$options$p2p","_this$options$p2p2","p2pStunServers","stunServers","_getConnectionFailedReasonDetails","_this$options$deploym","headersArr","_anonymousConnectionFailed","connectionFailed","_lastErrorMsg","_wasDisconnected","getConnection","credentials","statusStr","CONNECTION_STATUS_CHANGED","STROPHE_RECONNECTED_EVENT","STROPHE_DISCONNECTED_EVENT","wasIntentionalDisconnect","lastFailedRawMessage","attaching","configDomain","hostname","onCreateResource","_this$connection$emuc","_this$connection$emuc2","getRoomJid","mucNickname","muc","_this$connection$emuc3","_this$connection$emuc4","getJingleLog","getXmppLog","_this$connection$logg","_this$connection$rayo","getSessions","disconnectListener","sendFaceLandmarksEvent","faceExpression","jsonString","unescape","SHA256_IV","G1s","G2s","_BLAKE2","buffer32","dataOffset","data32","out32","v0","v1","v2","v3","v4","v5","v6","v7","v8","v9","v10","v11","v12","v13","v14","v15","_G1s","_G2s","_G1s2","_G2s2","_G1s3","_G2s3","_G1s4","_G2s4","_G1s5","_G2s5","_G1s6","_G2s6","_G1s7","_G2s7","_G1s8","_G2s8","B3_IV","B3_SIGMA","Id","permute","_BLAKE3","hasContext","IV","contextKey","bufferOut32","b2Compress","bufPos","_compress","isLast","chunkPos","chunksDone","chunk","last","chunks","chunkOut","b2CompressOut","_fromBig2","_compress2","blake3","OLM_MESSAGE_TYPES","PROTOCOL_STATUS","CryptoError","CONTEXT_RATCHET","AES_ALGORITHM","hashKey","hasher","olmKey","pqKey","userID","hex","bytesToHex","getBitsFromString","byteLen","deriveSymmetricCryptoKeyFromTwoKeys","key1","key2","combined_key","encryptSymmetrically","additionalData","freeField","iv","randFiled","freeFiledFixedLength","createNISTbasedIV","encrypted","subtle","decryptSymmetrically","combined","decrypted","genSymmetricKey","AES_KEY_BIT_LENGTH","E2EEcontext","_initializeWorker","_event$data","sas","updateSAS","scriptEl","baseUrl","workerUrl","workerBlob","Blob","createObjectURL","_workerUrl","Worker","_this$scriptEl","cleanupAll","revokeObjectURL","cleanup","handleReceiver","kJitsiE2EE","_receiver$createEncod","readable","readableStream","writableStream","handleSender","_sender$createEncoded","setKey","setKeysCommitment","commitment","setChatKeyHash","chatKeyHash","ratchetKeys","AUX","AUX_CHAT","SessionData","keyToSend","indexChanged","createInboundOLMchannel","account","_account$create_inbou","create_inbound_session","createOutboundOLMchannel","otKey","create_outbound_session","setSecret","kemSecret","isDone","validateStatus","validateCommitment","setStatus","clearSession","_this$session","free","setDone","keyCommitment","createKeyInfoMessage","encryptGivenKeyInfo","pqCiphertext","pqSessionKey","encryptKeyCommitment","commitmentToKeys","encryptKeys","encryptChatKey","chatKeyECC","chatKeyPQ","decryptChatKey","eccKey","pqCipher","keyECC","keyPQ","decryptKeys","pId","deriveSharedPQkey","keyData","importKey","importSymmetricCryptoKey","OlmAdapter","_mediaKey","_olmDataMap","_getParticipantOlmData","initVodozemac","genMyPublicKeys","_olmAccount","Account","_publicCurve25519Key","curve25519_key","_generateKyberKeys","publicKeyBase64","_publicKyberKey","_privateKyberKey","pk","pkKyber","generateOneTimeKeys","generate_one_time_keys","one_time_keys","ratchetMyKeys","ratchetMediaKey","isSessionDone","updateMyKeys","newMediaKey","encryptCurrentKey","olmData","deleteParticipantSession","clearParticipantSession","clearMySession","_this$_olmAccount","createPQsessionInitMessage","publicKyberKey","_encapsulateKyber","encapsKyber","createPQsessionAckMessage","decapsulatedSecret","_encapsulateKyber2","encapsulatedBase64","_await$olmData$encryp","olmEncKeyInfo","pqEncKeyInfo","createSessionAckMessage","_await$olmData$encryp2","createSessionDoneMessage","keyChanged","processSessionDoneMessage","decryptKey","createSessionInitMessage","emojiMapping","ms","ManagedKeyHandler","_this$conference$rtc","_onLocalTrackAdded","sasStr","sasBytes","generateEmojiSas","E2EE_SAS_AVAILABLE","initialized","max_wait","myID","e2eeCtx","E2EEContext","_reqs","askedForChatKey","_participantEventQueue","_processingEvents","initSessions","onUserJoined","_onParticipantJoined","_onParticipantLeft","onEndpointMessageReceived","_onEndpointMessageReceived","onConferenceLeft","_onConferenceLeft","onConferenceJoined","_conferenceJoined","onMediaSessionStarted","_onMediaSessionStarted","onTrackAdded","_onTrackAddedHandler","_setupReceiverE2EEForTrack","onTrackMuteChanged","onSasUpdated","sasUpdatedHandler","USER_JOINED","_MEDIA_SESSION_STARTED","_olmAdapter","getMediaSessions","_setupSenderE2EEForTrack","_this$_olmAdapter$upd","createKeyUpdatePromise","race","createSessionPromise","resolveSessionPromise","resolveAllSessionPromises","resolveKeyUpdatePromise","pID","requestPromise","_handleParticipantJoined","_this$_olmAdapter$rat","_handleParticipantLeft","updateBatch","clearAllSessions","updateKey","updateParticipantKey","isThisParticipantFirst","localParticipantId","localeCompare","olm","_msg$data","setKeyCommitment","_msg$data2","_msg$data3","_await$this$_olmAdapt","_msg$data4","_await$this$_olmAdapt2","E2EE_KEY_SYNC_AFTER_TIMEOUT","_msg$data5","_msg$data6","_msg$data7","_await$this$_olmAdapt3","setMyChatKey","E2EE_CRYPTO_FAILED","hashData","hashChatKeys","_queueParticipantEvent","_processParticipantEvents","enableE2E","_this$_olmAdapter$gen","lastKey","E2EE_KEY_SYNC_FAILED","_this$conference$rtc2","disableE2E","setEnabled","setLocalParticipantProperty","restartMediaSessions","messageReceived","leaveConference","_keyHandler","_config$e2ee","_config$testing","e2ee","disableE2EE","enableEncodedTransformSupport","E2ePingEvents","E2E_PING_REQUEST","E2E_PING_RESPONSE","ParticipantWrapper","e2eping","requests","lastRequestId","sendRequest","handleResponse","maybeLogRttAndStop","scheduleNext","getDelay","removeParticipant","conferenceSize","totalSeconds","numRequests","maxMessagesPerSecond","requestId","requestMessage","timeSent","request","Infinity","numRequestsWithResponses","totalNumRequests","E2E_RTT_CHANGED","E2ePing","maxConferenceSize","participantJoined","participantLeft","conferenceJoined","handleRequest","participantWrapper","kJitsiLiteMode","LiteModeContext","_setupLiteModeForTrack","receiverStreams","transformStream","TransformStream","pipeThrough","pipeTo","DESKTOP_VIDEO_CODEC_ORDER","MOBILE_P2P_VIDEO_CODEC_ORDER","MOBILE_VIDEO_CODEC_ORDER","CodecSelection","codecPreferenceOrder","visitorCodecs","connectionType","_options$connectionTy","disabledCodec","preferenceOrder","_options$connectionTy2","_options$connectionTy3","enableAV1ForFF","supportedCodecs","_getSupportedVideoCodecs","selectedOrder","_disabledCodec","_preferredCodec","isVp9EncodeSupported","selectedCodec","_window$RTCRtpReceive3","supportedCodec","getCodecPreferenceList","getScreenshareCodec","selectPreferredCodec","mediaSession","_remoteParticipants$m","_this$screenshareCode","localPreferredCodecOrder","isE2EEEnabled","remoteParticipants","remoteCodecsPerParticipant","selectedCodecOrder","acc","localCodec","codecNotSupportedByRemote","remoteCodecs","participantCodec","changeCodecPreferenceOrder","getActiveMediaSession","codecOrder","codecsByVideoType","codecIndex","newCodec","updateVisitorCodecs","ReceiverAudioSubscription","ReceiverAudioController","_all","_exclude","_include","audioSubscription","muteRemoteAudio","setAudioSubscriptionMode","resendSubscription","setIncludeSources","_normalizeReceiverAud","_message$list","NONE","INCLUDE","EXCLUDE","normalizeReceiverAudioSubscription","ReceiveVideoController","_config$startLastN","startLastN","_maxFrameHeight","_assumedBandwidthBps","_lastNLimitedByCpu","_receiveResolutionLimitedByCpu","assumedBandwidthBps","_getDefaultSourceReceiverConstraints","_mediaSession$peercon","remoteVideoTracks","_updateIndividualConstraints","individualConstraints","defaultConstraints","getCurrentReceiverConstraints","isLastNLimitedByCpu","setAssumedBandwidthBps","setLastNLimitedByCpu","setPreferredReceiveMaxFrameHeight","setReceiverConstraints","_constraints$assumedB","p2pSession","mappedConstraints","setReceiveResolutionLimitedByCpu","MAX_LOCAL_RESOLUTION","SendVideoController","_preferredSendMaxFrameHeight","_sessionSenderConstraints","_activeSessionMap","activeSession","_propagateSendMaxFrameHeight","sendMaxFrameHeight","_selectSendMaxFrameHeight","_this$_activeSessionM","remoteRecvMaxFrameHeight","configureConstraintsForLocalSources","sourceConstraints","sessionMap","onSenderConstraintsReceived","videoConstraints","_this$_conference$get","normalizedHeight","setPreferredSendMaxFrameHeight","_this$_activeSessionM2","_this$_activeSessionM3","QualityLimitationReason","FixedSizeArray","_maxSize","QualityController","_options$enableAdapti","_audioController","_codecController","_enableAdaptiveMode","enableAdaptiveMode","_encodeTimeStats","_isLastNRampupBlocked","_lastNRampupTime","lastNRampupTime","_notDecodingVideoTracker","_receiveVideoController","_sendVideoController","CONFERENCE_VISITOR_CODECS_CHANGED","debouncedSelectCodec","_debounce","_processOutboundRtpStats","_processInboundVideoStats","delay","_timer","_lowerOrRaiseLastN","cpuLimited","receiveVideoController","newLastN","_this$_conference$opt","videoStreamsReceived","isStillLimitedByCpu","_maybeLowerReceiveResolution","currentLevel","_maybeSwitchVideoCodec","_stats$get","encodeResolution","_limitedByCpuTimeout","updatedStats","latestSourceStats","expectedSendResolution","CPU","codecController","_performQualityOptimizations","sourceStats","_lastNRampupTimeout","ENCODER_CPU_RESTRICTED_EVENT","_this$_notDecodingVid","tracker","consecutiveCycles","isIssueActive","eventData","REMOTE_VIDEO_DECODING_EVENT","REMOTE_VIDEO_DECODING","statsPerTrack","_stats$get2","existingStats","_trackStats$find","_statsPerTrack$get","avgEncodeTime","totalValue","currentValue","_ref5$qualityLimitati","exisitingStats","audioController","sendVideoController","JibriSession","_jibriJid","_statusFromJicofo","_setSessionID","sessionID","_focusMucJid","getError","_error","getID","_sessionID","getInitiator","_initiator","getLiveStreamViewURL","_liveStreamViewURL","getJibriJid","getTerminator","_terminator","getMode","setError","setLiveStreamViewURL","setStatusFromJicofo","setJibriJid","jibriJid","appData","broadcastId","_this$_connection","_createIQ","_response$getElements","_response$getElements2","_this$_connection2","_setErrorFromIq","errorChildren","_chatRoom","getSession","_sessions","getSessionByJibriJid","_handleFocusPresence","_handleJibriPresence","prevStatus","_emitSessionUpdate","startRecording","_addSession","stopRecording","_createSession","jibriStatus","recordingMode","getFocusRecordingUpdate","_getHiddenDomainUpdat","_presence$getElements","_presence$getElements2","_presence$getElements3","liveStreamViewURL","getHiddenDomainUpdate","AverageStatReport","_count","_sum","_samples","addNext","calculate","NaN","appendReport","ConnectionAvgStats","avgRtpStatsReporter","_n","_sampleIdx","_avgRTT","_avgRemoteRTTMap","_avgRtpStatsReporter","_avgEnd2EndRTT","_calculateAvgStats","_onRemoteStatsUpdated","_processRemoteStats","_data$transport2","batchReport","jvbEnd2EndRTT","jvbStatsMonitor","rtt_diff","avgRemoteRTT","_calculateAvgRemoteRTT","avgLocalRTT","end2end_rtt_avg","_resetAvgStats","remoteAvg","avg","validData","rttAvg","AvgRTPStatsReporter","_avgAudioBitrateUp","_avgAudioBitrateDown","_avgVideoBitrateUp","_avgVideoBitrateDown","_avgBandwidthUp","_avgBandwidthDown","_avgPacketLossTotal","_avgPacketLossUp","_avgPacketLossDown","_avgRemoteFPS","_avgRemoteScreenFPS","_avgLocalFPS","_avgLocalScreenFPS","_avgRemoteCameraPixels","_avgRemoteScreenPixels","_avgLocalCameraPixels","_avgLocalScreenPixels","_avgCQ","_cachedTransportStats","_onLocalStatsUpdated","_maybeSendTransportAnalyticsEvent","_onP2PStatusChanged","p2pStatsMonitor","_onJvb121StatusChanged","_resetAvgJvbStats","confSize","_calculateAvgVideoFps","_calculateAvgVideoPixels","_data$transport3","peerResolutions","peerPixelsSum","peerCount","peerID","videosResolution","peerAvgPixels","_calculatePeerAvgVideoPixels","videos","peerSsrcCount","peerSsrcPixels","peerFpsSum","videosFps","peerAvgFPS","_calculatePeerAvgVideoFps","peerSsrcFps","_data$transport4","transportStats","userId","isLocalStats","_userId","setDisplayName","_isLocalStats","setDominantSpeaker","totalDominantSpeakerTime","_dominantSpeakerStart","_isDominantSpeaker","_hasLeft","_faceLandmarks","getUserId","newName","isDominantSpeaker","isNowDominantSpeaker","timeElapsed","getTotalDominantSpeakerTime","hasLeft","markAsHasLeft","getFaceLandmarks","setFaceLandmarks","faceLandmarks","addFaceLandmarks","SpeakerStatsCollector","dominantSpeakerId","SpeakerStats","_onDominantSpeaker","_onUserJoin","_onUserLeave","_onDisplayNameChange","_onFaceLandmarkAdd","_updateStats","oldDominantSpeaker","newDominantSpeaker","savedUser","speakerStatsToUpdate","newParticipant","ComponentsVersions","versions","addCommandListener","_processVersions","getComponentVersion","componentName","VideoSIPGWStatusConstants","VideoSIPGWStateConstants","VideoSIPGWErrorConstants","STATUS_AVAILABLE","STATUS_UNDEFINED","STATUS_BUSY","STATE_ON","STATE_OFF","STATE_PENDING","STATE_RETRYING","STATE_FAILED","ERROR_NO_CONNECTION","ERROR_SESSION_EXISTS","STATE_CHANGED","JitsiVideoSIPGWSession","sipAddress","_sendJibriIQ","nodeTree","setState","VideoSIPGWConstants","failureReason","oldState","addStateListener","removeStateListener","VideoSIPGW","sessionStateChangeListener","sessionStateChanged","handleJibriSIPState","Constants","sipaddress","failure_reason","createVideoSIPGWSession","SOURCE_INFO_PRESENCE_ELEMENT","SignalingLayerImpl","_ssrcOwners","_localSourceState","_remoteSourceState","_addLocalSourceInfoToPresence","_bindChatRoomEventHandlers","emitAudioMutedEvent","_audioMuteHandler","_doesEndpointSendNewSourceInfo","emitVideoMutedEvent","_videoMuteHandler","emitVideoTypeEvent","_videoTypeHandler","_sourceInfoHandler","sourceInfoJSON","emitEventsFromHere","endpointSourceState","negotiatedOwners","_sourceInfoJSON$sourc","negotiatedOwner","sourceChanged","newMutedState","oldSourceState","newVideoType","SOURCE_UPDATED","newSourceNames","_memberLeftHandler","_this$_chatRoom","_logOwnerChangedMessage","_this$_chatRoom2","lastPresence","legacyGetPeerMediaInfo","mediaInfo","codecListNode","_codecListNode$0$valu","_codecListNode$0$valu2","_this$_remoteSourceSt","_this$_ssrcOwners$get","_this$_ssrcOwners$get2","setChatRoom","oldChatRoom","newEndpointId","newSourceName","existingOwner","BridgeVideoType","DEFAULT_TRANSCRIPTION_LANGUAGE","_getCodecMimeType","JitsiConference","_this$connection","_options$config$p2p","_this$options$config$","_this$options$config$2","additionalLogMsg","eventManager","_init","componentsVersions","dtmfManager","somebodySupportsDTMF","startMutedPolicy","wasStopped","avgRtpStatsN","speakerStatsCollector","deferredStartP2PTask","backToP2PDelay","isP2PConnectionInterrupted","p2pJingleSession","videoSIPGWHandler","recordingManager","RecordingManager","_conferenceJoinAnalyticsEventSent","isE2EESupported","_e2eEncryption","_liteModeContext","_audioSenderLimitReached","_videoSenderLimitReached","_firefoxP2pEnabled","enableFirefoxP2p","_iceRestarts","_unsubscribers","staticResourceCreator","resourceCreator","isAuthenticatedUser","_Strophe$getNodeFromJ","_config$statisticsId","_config$e2eping","_config$videoQuality","_config$videoQuality2","_config$videoQuality3","_config$videoQuality4","_config$videoQuality5","_config$videoQuality6","_config$videoQuality7","_config$testing$lastN","_config$testing2","_config$p2p","_config$p2p2","_config$p2p3","_config$p2p4","_config$p2p5","_config$p2p6","_config$deploymentInf","_config$transcription","statisticsId","PARTICIPANT_SOURCE_UPDATED","_onIceConnectionEstablished","_onIceConnectionFailed","_onIceConnectionInterrupted","_onIceConnectionRestored","_onP2PTerminationRequired","_updateProperties","_sendConferenceJoinAnalyticsEvent","_removeLocalSourceOnReject","_updateRoomPresence","_registerRtcListeners","qualityOptions","mobileCodecPreferenceOrder","mobileScreenshareCodec","_config$confID","_config$statisticsDis","qualityController","aliasName","applicationName","confID","statisticsDisplayName","enableTalkWhileMuted","_audioAnalyser","vadTalkMutedDetection","TALK_WHILE_MUTED","enableNoisyMicDetection","vadNoiseDetection","NOISY_MIC","enableNoAudioDetection","_noAudioSignalDetection","hasAudioSignal","p2pDominantSpeakerDetection","transcriptionLanguage","setTranscriptionLanguage","_this$options$config$3","_window$JitsiMeetJS$a","_window$JitsiMeetJS","conferenceConnectionTimes","xmppConnectionTimes","globalNSConnectionTimes","JitsiMeetJS","app","connectedToMUCJoinedTime","connectingToMUCJoinedTime","connecting","numberOfParticipantsOnJoin","_numberOfParticipantsOnJoin","xmppConnectingTime","supportsTurnInRoomMetadata","_sendConferenceLeftAnalyticsEvent","_restartMediaSessions","_stopP2PSession","_maybeStartOrStopP2P","_fireAudioLevelChangeEvent","activeTpc","_fireMuteChangeEvent","actorId","_doReplaceTrack","replaceTrackPromises","_ctx","errorReason","rejectedTracks","TRACK_UNMUTE_REJECTED","_setupNewTrack","_this$getLocalTracks","_setNewVideoType","videoTypeChanged","_maybeClearSITimeout","_sessionInitiateTimeout","_maybeSetSITimeout","ACTION_JINGLE_SI_TIMEOUT","_maybeClearDeferredStartP2P","_removeRemoteJVBTracks","_removeRemoteTracks","_removeRemoteP2PTracks","sessionNickname","_resumeMediaTransferForJvbConnection","_setP2PStatus","p2pFailed","isVideoActive","_startP2PSession","_this$p2pJingleSessio","_suspendMediaTransferForJvbConnection","userLeftEvent","isP2PEnabled","isP2PTestModeEnabled","peers","shouldBeInP2P","_shouldBeInP2PMode","_this$options$config$4","_this$options$config$5","myId","peersId","forceInitiator","forceResponder","ACTION_P2P_SWITCH_TO_JVB","hasBotPeer","_hasVisitors","_transcribingEnabled","_buildDesiredTranslations","_options$reason","_options$reasonDescri","_options$requestResta","wasP2PEstablished","_addRemoteJVBTracks","skip","muteStatusChanged","presenceChanged","_updateFeatures","updateDTMFSupport","_acceptJvbIncomingCall","ACTION_JINGLE_RESTART","ACTION_JINGLE_SI_RECEIVED","_setBridgeChannel","_desktopSharingFrameRate","_this$connection2","_this$connection$opti","_this$connection3","ignoreDomain","bridgeChannel","preferSctp","sctpOffered","firstWsUrl","_rejectIncomingCall","_onIncomingCallP2P","rejectReason","contentName","ACTION_P2P_DECLINED","_acceptP2PIncomingCall","ACTION_P2P_FAILED","jitterDelay","isIceRestartSupported","_restartJvbIceWithFallback","_delayedIceFailed","_this$options$config$6","createJvbIceFailedEvent","ACTION_JVB_ICE_FAILED","fallback","restartJvbIce","_this$jvbJingleSessio","iceState","_error$message","_this$_delayedIceFail","_addRemoteTracks","_addRemoteP2PTracks","p2pEstablishmentDuration","jvbEstablishmentDuration","done","establishmentDurationDiff","ICE_ESTABLISHMENT_DURATION_DIFF","ACTION_P2P_ESTABLISHED","_this$properties$visi","_publishedCodecs","audioLimitReached","videoLimitReached","AUDIO_UNMUTE_PERMISSIONS_CHANGED","VIDEO_UNMUTE_PERMISSIONS_CHANGED","publishedCodecs","_visitorCodecs","_fireIncompatibleVersionsEvent","_isReceiverTranslationActive","_receiverTranslationLanguage","_participantTranslationLanguages","language","_resolveTranslationLanguage","_this$_participantTra","_updateTranslationRequests","_translationRequests","_lang","_sendTranslationRequestStanza","componentAddress","_registerTranslationErrorHandler","_translationRequestSeq","_pendingTranslationRequests","_translationErrorHandler","_onTranslationRequestError","_findFirst","UNKNOWN","endpointIds","AUDIO_TRANSLATION_FAILED","_registerTranslationListenersHandler","_translationListenersHandler","_onTranslationListenersChanged","_child$textContent","parsed","AUDIO_TRANSLATION_LISTENERS_CHANGED","_updateTranslationSubscription","enableIceRestart","localtrack","_options$requestResta2","_options$sendSessionT","removePromises","addPromises","isJoined","START_MUTED_POLICY_CHANGED","botParticipant","BOT_TYPE_CHANGED","authenticateAndUpgradeRole","rejectPromise","onLoginSuccessful","canceled","authenticationError","connectionError","_xmpp2","_this$options$config$7","_this$options$config$8","p2pTestMode","cleanUpWebWorkers","_this$_delayedIceFail2","onLocalTrackRemoved","mJid","_this$xmpp$connection","_this$xmpp$connection2","leaveError","_this$connection4","isEndConferenceSupported","isAuthEnabled","isLoggedIn","getAuthLogin","removeCommandListener","sendTextMessage","useFullJid","sendPrivateTextMessage","_this$room3","sendCommand","sendCommandOnce","removeCommand","nickKey","silent","getTranscriptionStatus","_this$options$config$9","allowMultipleTracks","_this$getLocalTracks2","addTrackPromises","oldVideoType","_this$getLocalTracks3","oldTrackBelongsToConference","lock","unlock","countHidden","grantOwner","revokeOwner","isMyself","isMembersOnly","kickParticipant","setReceiverTranslationLanguage","getReceiverTranslationLanguage","setParticipantTranslationLanguage","_this$_participantTra2","getParticipantTranslationLanguage","clearTranslation","fullJid","_this$p2pJingleSessio2","_this$p2pJingleSessio3","_this$jvbJingleSessio2","_this$jvbJingleSessio3","_this$options$config","audioMuted","videoMuted","numberOfParticipants","mediaSessions","tracksToBeRemoved","kickedParticipantId","kickedParticipant","PARTICIPANT_KICKED","USER_ROLE_CHANGED","removedTrack","ACTION_JINGLE_TERMINATE","stopOptions","DTMF_SUPPORT_CHANGED","isDTMFSupported","_this$room4","peerConnection","isSIPCallingSupported","_this$room$xmpp$moder","_this$room5","setStartMutedPolicy","policy","getStartMutedPolicy","useRawKeys","setLocalParticipantProperties","wasChanged","removeLocalParticipantProperty","getLocalParticipantProperty","property","overallFeedback","detailedFeedback","getSsrcByTrack","_this$getActivePeerCo","sendApplicationLog","sendEndpointMessage","broadcastEndpointMessage","sendThroughVideobridge","messageType","messageToSend","getP2PConnectionState","_this$jvbJingleSessio4","startP2PSession","stopP2PSession","getSpeakerStats","sendFaceLandmarks","_this$_e2eEncryption","toggleE2EE","setMediaEncryptionKey","isLobbySupported","_this$room6","_this$room7","isVisitorsSupported","_this$room8","disableLobby","joinLobby","_this$room$getLobby","myLobbyUserId","sendLobbyMessage","addLobbyMessageListener","removeLobbyMessageHandler","sendLobbyMessageRetraction","_this$room9","addLobbyMessageRetractionListener","_this$room0","removeLobbyMessageRetractionHandler","_this$room1","lobbyDenyAccess","lobbyApproveAccess","isAVModerationSupported","_this$room10","enableAVModeration","disableAVModeration","avModerationApprove","avModerationReject","_this$room11","_this$room12","_this$room13","_this$room14","JitsiConnection","appID","errType","createConnectionFailedEvent","errorType","errorMessage","initJitsiConference","getLogs","ua","JitsiMediaDevicesEvents","AUDIO_PERMISSION_NAME","VIDEO_PERMISSION_NAME","stopActiveDevices","CustomSignalingLayer","ssrcOwners","_owner","_mediaType","_videoType","ACTIONS","ProxyConnectionPC","receiveAudio","receiveVideo","_peerConnection","_onError","_onRemoteStream","_onSendMessage","getPeerJid","processMessage","ACCEPT","_onSessionAccept","INITIATE","_onSessionInitiate","TERMINATE","_onSessionTerminate","_onTransportInfo","_createPeerConnection","connectionStub","pcConfigStub","roomStub","jitsiRemoteTrack","onRemoteStream","onSendMessage","ParsedIceCandidate","iceCandidateStr","typeTransport","extractTypeTransport","ipv6","ipAddress","getString","isHost","isServerReflexive","isPeerReflexive","isRelay","isPublicIp","getTypeTransport","isTypeTransportUdp","isTypeTransportTcp","isTypeTransportTls","getTransport","isUdp","isTcp","getProtocol","isRtp","isRtcp","isIpv6","getIpAddress","getPort","codeBaseType","chrome","firefox","edge","browserName","msie","safari","osName","windows","mac","android","ios","StatsAdapter","codeBase","getIceCandidates","rawData","localCandidates","remoteCandidates","iceCandidatePairs","rawStats","extractRawStats","processRawStatsForIceInfo","candidatePairs","parsedStats","getParsedStats","classifiedStats","statsClassifier","candidatePair","localCandidate","mozLocalTransport","relayType","formatRelayType","remoteCandidate","googActiveConnection","expectedType","typeIsInbound","reportType","selected","GetStatsHandler","isPromiseBased","csioGetStats","iceCandidatesHandler","candidatesObj","statsHandler","getStatsFirefox","getStatsSafari","getStatsChrome","getStatsEdge","csioReactNative","TurnConnection","statshandler","pctpc1","pctpc2","sendChannel","messageCallback","parsedIceResults","resolveCb","rejectCb","localIpAddressInfo","localIpAddresses","localIp","localIpType","numberOfLocalIp","setMessageCallback","setErrorCallback","raiseSendError","assignEvent","attachEvent","CSRTCPeerConnection","continueFlag","datachannelSettings","ordered","maxRetransmits","servers","rejectDisconnect","connectionTimer","binaryType","onIceCandidate","onIceStateChange","onCreateOfferSuccess","onCreateOfferError","iceTimer","getOtherPc","onCreateAnswerError","onSetLocalSuccess","onSetSessionDescriptionError","onSetRemoteSuccess","onSetRemoteSessionDescriptionError","onCreateAnswerSuccess","relayUdpGathered","relayTcpGathered","relayTlsGathered","srflxGathered","onAddIceCandidateSuccess","onAddIceCandidateError","getIceResults","iceResults","turnIpAddress","turnIpVersion","turnTransport","ipv6Supported","ipv4Supported","relayTlsSuccess","relayTcpSuccess","relayUdpSuccess","srflxSuccess","localIP","numberOfLocalIPs","localIPType","localIPNetworkType","ipInfo","foundActiveCand","turnNetworkType","getCurrent","timing","navigationStart","TurnTest","getResults","handleMessage","handleError","forceStopped","initiate","forceStop","failed","LAST_TIMEOUT","RttTest","sendTimer","countSent","rtts","startTimestamp","Timestamps","sendPing","sentTs","calculateRtt","calculateMetrics","fillResults","sentMessages","unAckedMessages","maxMessages","median","average","variance","std","endTimestamp","half","sqrt","randomAsciiString","fromCharCode","MessageMaker","sentBytes","padding","PADDING","make","ThroughputTest","receivedBytes","secondHalfBytes","secondHalfStart","bufferEmpty","chunkSize","messageMaker","intervals","intervalStart","intervalLength","intervalBytes","lastReceivedTimestamp","startSend","lastMessage","intervalDuration","intervalAvg","averageThroughput","milliseconds","bufferListener","fillBuffer","bufferedAmount","bufferFullThreshold","usePolling","bufferedAmountLowThreshold","maxDuration","bytesPrepared","allDuration","allAverage","fractionLostBytes","LossTest","numBufferFill","sentData","msgJson","totalBytes","ResultsHandler","trunc","failures","setStatusStopped","setStatusFailed","setStatusSuccess","tests","getFailureNumber","testName","OnlineCheck","onlineCheck","addEntry","onLine","TEST_NAMES","osVersion","agentVersion","csioGetOsName","csioGetOsVer","os","nVer","fullVersion","verOffset","nAgt","appVersion","opera","clientStrings","splitWords","browserVersion","detect","callsInProgress","turnTests","resultsHandler","startResolve","startReject","turnTestCounter","endpointInfo","buildName","buildVersion","_start","turnConnection","startTurnTests","activeTurnTest","onlineCheckResults","sendResults","getPublicPrecalltestResults","publicResults","mediaConnectivity","throughput","fractionalLoss","jitter","resultsMin","callStarts","callFinished","crashDisconnect","handleTestResults","Deferred","clearRejectTimeout","_timeout","setRejectTimeout","ScriptUtil","loadScript","prepend","relativeURL","loadCallback","script","referenceNode","currentExecutingScript","scriptSrc","baseScriptSrc","onload","parentNode","AudioMixer","_streamsToMix","_streamMSSArray","addMediaStream","_mixedMSD","createMediaStreamDestination","streamMSS","INFO","hasGUMExecuted","getAnalyticsAttributesFromOptions","audio_requested","video_requested","screen_sharing_requested","_permissions","_permissionsApiSupported","_parsePermissionState","_handlePermissionsChange","permissions","query","onchange","supported","isDevicePermissionGranted","permissionStatus","isMultipleAudioInputSupported","ProxyConnectionService","jitsiConnection","_onFatalError","_convertStringToXML","UNAVAILABLE","_selfCloseConnection","localTrackIndex","localSourceNameTrack","xml","xmlString","doc","DOMParser","parseFromString","parserError","parseXML","convertVideoToDesktop","jitsiLocalTracks","stringifiedIq","XMLSerializer","serializeToString","onConnectionClosed","addGlobalLogTransport","globalTransport","constants","iceRestartReason","BUSY","POLICY_VIOLATION","RESOURCE_CONSTRAINT","SERVICE_UNAVAILABLE","UNEXPECTED_REQUEST","FILE","STREAM","sipVideoGW","createAudioMixer","isFirstGUM","startTS","endTS","isCollectingLocalStats","currentlyAvailableMediaDevices","createLocalTracksFromMediaStreams","trackInfo","createTrackVADEmitter","localAudioDeviceId","errorTypes","detection","rtcstats","getActiveAudioDevice","audioDevices","devicePromiseArray","micDevice","devicePromise","outcomeArray","successfulPromises","rejectedPromises","rejectReasons","deviceLabel","rtcstatsStoreLogs","rtcstatsLogFlushSizeBytes","enableAnalyticsLogging","joinConference","_options$connectionOp","appId","connectionOptions","_options$jaas$useStag","_options$jaas","_options$jaas2","useStage","jaas","useStaging","jaasDomain","merge","cleanupListeners","onConnectionEstablished","onConnectionFailed","_options$conferenceOp","conf","conferenceOptions","logLevels","removeGlobalLogTransport","sendIdentityEntry","runPreCallTest","PreCallTest","setGlobalLogOptions","setLogLevel","setLogLevelById","setNetworkInfo","util","ljm","_mergeNamespaceAndModule","internals","firstOptions","reviver","protoAction","scan","SyntaxError","__proto__","safeParse","ignoreError","LogCollector","logStorage","stringifyObjects","storeInterval","levels","logLevel","_log","storeLogsIntervalID","totalLen","outputCache","someObject","formatLogMessage","prevMessage","_flush","_reschedulePublishInterval","_storeLogs","logs","reschedule","logStorageReady","cachedQueue","consoleTransport","globalTransports","addGlobalTransport","removeGlobalTransport","transportIdx","globalOptions","callerInfo","disableCallerInfo","fileLocation","column","getCallerInfo","transports","logPrefixes","toISOString","fullLogParts","methods","setGlobalOptions","setLevel","TRACE","LOG","idLoggers","loggers","curLevel","getUntrackedLogger","ap","Tk","Vk","zP","$j","dL","aM","vP","xt","Zt","UN","IO","zl","S1","initSDK","setConfig","setUserRating","addKeys","disableDataCollection","enableDataCollection","addEvent","mapStream","mapTrack","registerOnStatsListener","persistentEnd","persistentStart","registerStateListener","default","addTags","addStatsListener","qualityrtc","qrtcRun","qrtcStop","__assign","__awaiter","throw","__generator","sent","trys","ops","return","__spreadArray","sdkLogWithoutTrace","sdkLog","projectId","C","T","I","L","P","O","getSdkLogger","getSdkLogWithoutTrace","D","E","M","forceRecreate","reconnecting","nailUp","isDisabledDataCollection","isManualDisconnect","isManualConnect","tryingToConnectSocket","watchrtcConfig","openChannels","isRoomIdOrPeerIdChanged","countOfValidConnections","connectionCount","validateConfig","rtcToken","getConnectionData","proxyUrl","cleanOldTraces","onData","allowBrowserLogCollection","collectConsoleLogEnabled","override","collectConsoleLogLevel","setConsoleLevel","restoreOriginalConsoleMethods","connectionId","collectionInterval","W","oldInterval","sdkVersion","watchRTCSessionId","onOpen","connectionStatus","onClose","wasClean","authFailed","reconnectTimerId","nailUpRef","logGetStats","connections","applyPatchForRTT","subtractNailUpReferenceStats","exposeApplicationStatsForPC","watchRTCInitialized","generateID","getHardwareInfo","hardwareInfo","URLSearchParams","socketService","httpService","watchrtc","validConnection","errorText","__pcId","parameterless","newWatchrtcConfig","validateRating","ratingComment","promiseFuncs","validateEvent","J","progressCallback","codeUrl","configUrl","codeLoad","configAnswer","__qualityRTC","jsonConfig","isProbe","wakeLock","netlifyBaseUrl","configData","qualityRTC","getStreamsFromStats","getTransportFromStats","relayProtocol","remoteId","peerId","mappedName","packetsReceived","packetsLoss","roundTripTime","packetsSent","fractionLost","mediaSourceId","getMonth","getDate","getFullYear","getHours","getMinutes","getSeconds","getMilliseconds","_original_log","old","new","fileName","getGPUTier","loadBenchmarks","cores_count","hardwareConcurrency","memory","jsHeapSizeLimit","totalJSHeapSize","usedJSHeapSize","originalMethodPrefix","methodsToPatch","WeakSet","roundTripTimeMeasurements","cpu","_instance","sendInterval","dataCollection","sendPromises","prevMessageTs","abs","timeSinceLastMessage","compressToEncodedURIComponent","filteredCount","setPrototypeOf","platform","maxTouchPoints","MSStream","isIpad","isMobile","isSafari12","mobileTiers","desktopTiers","glContext","failIfMajorPerformanceCaveat","benchmarksURL","tier","screenSize","renderer","MAX_VALUE","devicePixelRatio","gpu","alpha","antialias","depth","powerPreference","stencil","getExtension","getParameter","UNMASKED_RENDERER_WEBGL","createShader","createProgram","shaderSource","compileShader","attachShader","linkProgram","detachShader","deleteShader","useProgram","createBuffer","bindBuffer","bufferData","getAttribLocation","vertexAttribPointer","enableVertexAttribArray","clearColor","viewport","drawArrays","readPixels","deleteProgram","deleteBuffer","compressToBase64","decompressFromBase64","_decompress","compressToUTF16","decompressFromUTF16","compressToUint8Array","decompressFromUint8Array","decompress","decompressFromEncodedURIComponent","position","scriptReadyRegex","fullPageUrl","pageUrl","scripts","supportsScriptReadyState","isNotOpera","hasNativeCurrentScriptAccessor","stackTraceLimit","hasStackBeforeThrowing","hasStackAfterThrowing","getScriptUrlFromStack","skipStackDepth","ignoreMessage","_nearestExecutingScript","eligibleScripts","getScriptFromUrl","getSoleInlineScript","currentScript","thrownErr","near","far","ReflectOwnKeys","Reflect","ReflectApply","ownKeys","getOwnPropertyNames","NumberIsNaN","isNaN","errorListener","resolver","eventTargetAgnosticAddListener","addErrorHandlerIfEventEmitter","_events","_eventsCount","_maxListeners","defaultMaxListeners","checkListener","_getMaxListeners","that","_addListener","warning","warned","onceWrapper","fired","wrapFn","_onceWrap","wrapped","_listeners","unwrap","evlistener","unwrapListeners","arrayClone","wrapListener","setMaxListeners","getMaxListeners","doError","er","prependListener","prependOnceListener","originalListener","spliceOne","rawListeners","eventNames","WINDOW","JS_MD5_NO_WINDOW","WEB_WORKER","NODE_JS","JS_MD5_NO_NODE_JS","COMMON_JS","JS_MD5_NO_COMMON_JS","AMD","ARRAY_BUFFER","JS_MD5_NO_ARRAY_BUFFER","HEX_CHARS","EXTRA","SHIFT","OUTPUT_TYPES","BASE64_ENCODE_CHAR","blocks","buffer8","JS_MD5_NO_ARRAY_BUFFER_IS_VIEW","createOutputMethod","outputType","Md5","createMethod","nodeWrap","eval","nodeMethod","createHash","sharedMemory","hBytes","finalized","hashed","first","notString","lastByteIndex","bc","da","base64Str","md5","Te","se","bt","gt","St","It","At","Ke","Ot","Lt","Pt","Dt","_t","vt","Mt","Rt","et","Ft","Y","Z","Ae","Wt","Ze","registerBackend","createInferenceSessionHandler","backend","aborted","initPromise","Proxy","yt","Et","Xe","webgl","webgpu","common","Tt","Bt","tensorToDataURL","OffscreenCanvas","dims","tensorLayout","norm","mean","bias","fillStyle","fillRect","toDataURL","tensorToImageData","Ut","Ie","bufferToTensor","_t$norm","_r$mean$","_r$bias$","tensorFormat","HTMLImageElement","ImageBitmap","createCanvas","HTMLCanvasElement","resizedHeight","resizedWidth","Image","crossOrigin","tensorFromTexture","texture","tensorFromGpuBuffer","dataType","gpuBuffer","tensorFromMLTensor","mlTensor","tensorFromPinnedBuffer","Ct","Int8Array","Int16Array","Int32Array","Float64Array","checkTypedArray","BigInt64Array","BigUint64Array","Float16Array","Nt","tensorReshape","dataLocation","cpuData","gpuTextureData","downloader","disposer","gpuBufferData","mlTensorData","Uint8ClampedArray","ceil","fromImage","fromTexture","fromGpuBuffer","fromMLTensor","fromPinnedBuffer","toImageData","ensureValid","getData","isDownloading","reshape","Qe","tt","timeStamp","TRACE_FUNC","_Error$stack","timeEnd","kt","outputNames","inputNames","SharedArrayBuffer","_await$bt2","startProfiling","endProfiling","inputMetadata","outputMetadata","Gt","$t","zt","Ht","jt","nt","Se","TRACE_EVENT_BEGIN","TRACE_EVENT_END","TRACE_FUNC_BEGIN","TRACE_FUNC_END","X","Be","Yt","Un","Jt","qt","xn","Me","ot","Cn","Mn","Qt","Rn","Xt","en","Kt","tn","st","it","Re","nn","Nn","Fn","kn","Le","he","rn","Wn","Gn","$n","ie","zn","sn","ae","Fe","ue","un","ke","We","cn","be","Hn","Pe","De","fe","jn","dn","we","_e","Ue","ln","xe","ve","Ce","ne","ye","$e","ze","Ge","ft","ct","ce","de","Jn","pn","mn","wn","hn","bn","yn","gn","En","qn","He","_globalThis$self","rt","ee","Oe","_e$data","in","epName","model","inputIndices","inputs","outputIndices","getScriptSrc","_document$currentScri","_self$location","inferWasmPathPrefixFromScriptSrc","isSameOrigin","normalizeUrl","fallbackUrl","blob","import","Ye","isMultiThreadSupported","MessageChannel","port1","WebAssembly","isSimdSupported","isRelaxedSimdSupported","_s$href","_u$href","initTimeout","simd","crossOriginIsolated","mjs","wasmBinary","_await$tn2","locateFile","getInstance","Ne","allocWasmString","lengthBytesUTF8","_malloc","stringToUTF8","iterateExtraOptions","stackSave","PTR_SIZE","stackAlloc","_OrtGetLastError","UTF8ToString","stackRestore","logSeverityLevel","logVerbosityLevel","_OrtCreateRunOptions","extra","_OrtAddRunConfigEntry","_OrtReleaseRunOptions","_free","an","use_ort_model_bytes_directly","enableMemPattern","appendSessionConfig","_OrtAddSessionConfigEntry","preferredLayout","setValue","_OrtAppendExecutionProvider","_r$graphOptimizationL","_r$executionMode","_r$logSeverityLevel","_r$logVerbosityLevel","executionMode","logId","optimizedModelFilePath","_OrtCreateSessionOptions","enableProfiling","enableGraphCapture","_ref5","_OrtAddFreeDimensionOverride","_OrtReleaseSessionOptions","at","calculateTensorSizeInBytes","ut","getReader","Memory","initial","maximum","_await$r$read","read","initOrt","_OrtInit","_I$asyncInit","_I","asyncInit","limits","requestDevice","forceFallbackAdapter","requestAdapter","ml","_OrtGetInputOutputCount","getSessionInputOutputMetadata","_OrtGetInputOutputMetadata","HEAP32","HEAPU32","_OrtFree","HEAPU8","_e3","_we2","_await$sn2","_r$webgpuOnCreateSess","_r$jsepOnCreateSessio","externalData","mountExternalData","path","_t$executionProviders","shouldTransferToMLTensor","gpuDevice","re","currentContext","webnnCreateMLContext","_OrtCreateSession","webgpuOnCreateSession","jsepOnCreateSession","webnnRegisterMLContext","_jn2","_dn2","isTensor","shape","_dn4","_OrtReleaseSession","_r$unmountExternalDat","unmountExternalData","_t$jsepOnReleaseSessi","_t$webnnOnReleaseSess","_t$webgpuOnReleaseSes","_n2","_OrtClearBoundOutputs","handle","_OrtReleaseBinding","jsepOnReleaseSession","webnnOnReleaseSession","webgpuOnReleaseSession","jsepRegisterBuffer","webnnRegisterMLTensor","webnnIsGraphInput","webnnIsGraphOutput","webnnCreateTemporaryTensor","webnnUploadTensor","_OrtCreateTensor","lt","_rn2","_s$jsepOnRunStart","_s$webnnOnRunStart","jsepOnRunStart","webnnOnRunStart","_OrtRun","G","_OrtReleaseTensor","mt","$","oe","_OrtGetTensorData","Ve","ge","wt","Bn","H","pe","outputPreferredLocations","V","Ee","ht","jsepGetBuffer","jsepCreateDownloader","webnnEnsureTensor","webnnIsGraphInputOutputTypeSupported","webnnCreateMLTensorDownloader","webnnReleaseTensorId","_ref8","_s$webnnOnRunEnd","webnnOnRunEnd","_OrtEndProfiling","isProxy","proxy","enqueueCallbacks","ensureWorker","_W","_ref9","_ref0","preferredOutputLocation","Sn","encodeTensorMetadata","_e$","_e$2","fetchModelAndCopyToWasmMemory","loadModel","_await$hn2","_s$d","In","OnnxruntimeWebAssemblyBackend","je","initializeFlags","Tn","wasmBackend","Yn","An","qe","cpus","Xn","Zn","grammar","reg","rate","subtype","sessionConfig","raddr","dir2","writer","write","parseFmtpConfig","parseParams","parsePayloads","parseRemoteCandidates","parseImageAttributes","parseSimulcastStreamList","toIntIfInt","parseReg","needsBlank","keyLocation","rawName","attachProperties","validLine","paramReducer","scid","formatRegExp","formatStr","makeLine","defaultOuterOrder","defaultInnerOrder","outerOrder","innerOrder","localCName","generateIdentifier","splitLines","splitSections","getDescription","getMediaSections","matchPrefix","parseCandidate","relatedPort","tcpType","writeCandidate","parseIceOptions","parseRtpMap","clockRate","numChannels","writeRtpMap","preferredPayloadType","writeExtmap","headerExtension","preferredId","kv","writeFmtp","parseRtcpFb","writeRtcpFb","rtcpFeedback","parseSsrcMedia","sp","colon","parseSsrcGroup","getMid","algorithm","getDtlsParameters","writeDtlsParameters","setupType","parseCryptoLine","cryptoSuite","keyParams","sessionParams","writeCryptoLine","writeCryptoKeyParams","parseCryptoKeyParams","keyMethod","keySalt","lifeTime","mkiValue","mkiLength","getCryptoParameters","getIceParameters","writeIceParameters","iceLite","parseRtpParameters","headerExtensions","fecMechanisms","rtcp","profile","rtpmapline","fmtps","wildcardRtcpFb","existingFeedback","writeRtpDescription","maxptime","extension","parseRtpEncodingParameters","encodingParameters","hasRed","hasUlpfec","flows","apt","encParam","codecPayloadType","fec","mechanism","parseRtcpParameters","rtcpParameters","remoteSsrc","rsize","reducedSize","compound","mux","writeRtcpParameters","parseMsid","spec","planB","msidParts","parseSctpDescription","maxSizeLine","sctpPort","sctpMapLines","writeSctpDescription","generateSessionId","writeSessionBoilerplate","sessId","sessVer","sessUser","getDirection","getKind","isRejected","parseOLine","netType","addressType","isValidSDP","global$1","WebSocketImplementation","getWebSocketImplementation","getDOMParserImplementation","DOMParserImplementation","getDummyXMLDOMDocument","createDocument","implementation","documentMode","docStrings","ActiveXObject","_getIEXmlDom","safe_add$1","str2binl","md5_cmn","md5_ff","md5_gg","md5_hh","md5_ii","core_md5","MD5","hexdigest","hex_tab","binl2hex","binl2str","SASLMechanism","isClientFirst","mechname","onStart","onChallenge","challenge","clientChallenge","cookies","cookieName","expires","cookieObj","cookieValue","escape","cookie","core_hmac_sha1","bkey","ipad","opad","binb2str","b64_hmac_sha1","b64_sha1","str_hmac_sha1","str_sha1","Builder","VERSION","HTTPBIND","BOSH","AUTH","ROSTER","PROFILE","MUC","SASL","FRAMING","BIND","SESSION","STANZAS","XHTML_IM","XHTML","tags","css","validTag","validAttribute","validCSS","style","REDIRECT","ATTACHFAIL","ErrorCondition","BAD_FORMAT","CONFLICT","MISSING_JID_NODE","NO_AUTH_MECH","UNKNOWN_REASON","ElementType","NORMAL","TEXT","CDATA","FRAGMENT","SECONDARY_TIMEOUT","forEachChild","elemName","childNodes","childNode","_xmlGenerator","xmlGenerator","xmlTextNode","xmlescape","createTextNode","xmlHtmlNode","html","loadXML","nodeValue","copyElement","createHtml","cssText","cssAttrs","cssName","cssValue","createDocumentFragment","escapeNode","unescapeNode","bare","fatal","sourceURL","lineNumber","_console","getNamedItem","_requestId","_connectionPlugins","ptype","moreattrs","removeAttribute","impNode","xmlGen","importNode","newElem","fragment","innerHTML","xhtml","matchBare","matchBareFromJid","Handler","getNamespace","elNamespace","ignoreNamespaceFragment","namespaceMatch","nsMatch","isMatch","elem_type","TimedHandler","setProtocol","_sasl_data","do_session","mechanisms","protocolErrorHandlers","_idleTimeout","_disconnectTimeout","do_authentication","_uniqueId","_sasl_success_handler","_sasl_failure_handler","_sasl_challenge_handler","_onIdle","iqFallbackHandler","WorkerWebsocket","Websocket","Bosh","_reset","_requests","getUniqueId","addProtocolErrorHandler","status_code","wait","hold","route","authcid","disconnection_timeout","authzid","connect_callback","wind","_attach","restore","_sessionCachingSupported","_restore","sessionStorage","xmlInput","nextValidRid","_queueData","timeoutHandler","iqtype","_sendRestart","thand","handRef","hand","SASLExternal","SASLOAuthBearer","SASLXOAuth2","registerSASLMechanism","Mechanism","_addSysTimedHandler","_onDisconnectTimeout","_disconnect","_dataRecv","_reqToData","strip","_emptyQueue","cond","conflict","UNKOWN_REASON","_connect_cb","_callback","bodyWrap","hasFeatures","_no_auth_received","matched","sortMechanismsByPriority","higher","swap","_attemptSASLAuth","_attemptLegacyAuth","mechanism_found","_sasl_success_cb","_sasl_failure_cb","_sasl_challenge_cb","_sasl_mechanism","request_auth_exchange","btoa","_onLegacyAuthIQResult","_auth2_cb","serverSignature","attribMatch","streamfeature_handlers","_onResourceBindResultIQ","jidNode","_establishSession","_onSessionResultIQ","auth_str","salt","iter","Hi","U_old","responseText","authMessage","cnonce","clientKey","serverKey","clientSignature","test_cnonce","Request","sends","xmlData","origFunc","date","abort","dead","age","timeDead","xhr","_newXHR","getResponse","responseXML","documentElement","XMLHttpRequest","overrideMimeType","onreadystatechange","_conn","inactivity","keepalive","_cacheSession","_onRequestStateChange","_throttledRequestHandler","typ","_sendTerminate","_callProtocolErrorHandlers","reqStatus","_getRequestStatus","err_callback","HTTP","_hitError","time_elapsed","def","getAllResponseHeaders","reqIs0","reqIs1","valid_request","too_many_retries","_removeRequest","_restartRequest","_processRequest","primary_timeout","secondary_timeout","server_error","content_type","contentType","open","setRequestHeader","withCredentials","sendFunc","customHeaders","backoff","new_service","pathname","_buildStream","_checkStreamError","connectstatus","errorString","_onOpen","_onInitialMessage","_handleStreamStart","streamStart","parsedMessage","see_uri","_replaceMessageHandler","_streamWrap","closeString","rawStanza","startString","lmap","SharedWorker","_messageHandler","_onWorkerMessage","_attachCallback","method_name","FUNC_TYPE","UNDEF_TYPE","OBJ_TYPE","STR_TYPE","MAJOR","MODEL","NAME","TYPE","VENDOR","ARCHITECTURE","CONSOLE","MOBILE","TABLET","SMARTTV","WEARABLE","EMBEDDED","AMAZON","APPLE","ASUS","BLACKBERRY","BROWSER","GOOGLE","HUAWEI","LG","MICROSOFT","MOTOROLA","OPERA","SAMSUNG","SHARP","SONY","XIAOMI","ZEBRA","FACEBOOK","CHROMIUM_OS","MAC_OS","enumerize","enums","str1","str2","lowerize","rgxMapper","regex","strMapper","windowsVersionMap","regexes","EDGE","extensions","getResult","_ua","_uach","userAgentData","_rgxmap","mergedRegexes","extend","_isSelfNav","_browser","brave","isBrave","getCPU","_cpu","getDevice","_device","mobile","standalone","_os","getUA","setUA","DEVICE","ENGINE","OS","jQuery","Zepto","addToExternrefTable0","__externref_table_alloc","__wbindgen_export_2","__wbindgen_exn_store","isLikeNone","cachedTextDecoder","ignoreBOM","cachedUint8ArrayMemory0","getUint8ArrayMemory0","getStringFromWasm0","ptr","WASM_VECTOR_LEN","passArray8ToWasm0","malloc","takeFromExternrefTable0","__externref_table_dealloc","cachedTextEncoder","encodeString","encodeInto","written","passStringToWasm0","realloc","mem","getArrayU8FromWasm0","cachedUint16ArrayMemory0","AccountFinalization","FinalizationRegistry","register","unregister","__wbg_account_free","__wrap","__wbg_ptr","__destroy_into_raw","account_new","from_pickle","pickle","pickle_key","ptr0","__wbindgen_malloc","__wbindgen_realloc","len0","ptr1","len1","account_from_pickle","from_libolm_pickle","account_from_libolm_pickle","deferred3_0","deferred3_1","account_pickle","ptr2","len2","__wbindgen_free","ed25519_key","deferred1_0","deferred1_1","account_ed25519_key","account_curve25519_key","sign","deferred2_0","deferred2_1","account_sign","max_number_of_one_time_keys","account_max_number_of_one_time_keys","account_one_time_keys","account_generate_one_time_keys","fallback_key","account_fallback_key","forget_fallback_key","account_forget_fallback_key","generate_fallback_key","account_generate_fallback_key","mark_keys_as_published","account_mark_keys_as_published","identity_key","one_time_key","account_create_outbound_session","Session","message_type","account_create_inbound_session","InboundCreationResult","__wbg_decryptedmessage_free","EncryptedOlmMessageFinalization","__wbg_encryptedolmmessage_free","EncryptedOlmMessage","__wbg_get_encryptedolmmessage_ciphertext","arg0","__wbg_set_encryptedolmmessage_ciphertext","__wbg_get_encryptedolmmessage_message_type","__wbg_set_encryptedolmmessage_message_type","__wbg_establishedsas_free","__wbg_groupsession_free","InboundCreationResultFinalization","__wbg_inboundcreationresult_free","inboundcreationresult_session","inboundcreationresult_plaintext","__wbg_inboundgroupsession_free","__wbg_sas_free","__wbg_sasbytes_free","SessionFinalization","__wbg_session_free","session_pickle","session_from_pickle","session_from_libolm_pickle","session_id","session_session_id","session_matches","session_session_matches","session_encrypt","session_decrypt","has_received_message","session_has_received_message","__wbg_init","module_or_path","imports","wbg","__wbg_appendChild_8204974b7328bf98","arg1","__wbg_body_942ea927546a04ba","__wbg_buffer_609cc3eee51ed158","__wbg_call_672a4d21634d4a24","__wbg_call_7cccdd69e0791ae2","arg2","__wbg_createElement_8c9931a732ee2fea","__wbg_crypto_ed58b8e10a292839","__wbg_document_d249400bd7bd996d","__wbg_getRandomValues_bcb4912f16000dc4","__wbg_instanceof_Window_def73ea0955fc569","Window","__wbg_msCrypto_0a36e2ec3a343d26","__wbg_new_405e22f390576ce2","__wbg_new_5e0be73521bc8c17","__wbg_new_a12002a7f91c75be","__wbg_newnoargs_105ed471475aaf50","__wbg_newwithbyteoffsetandlength_d97e637ebe145a9a","__wbg_newwithlength_a381634e90c276d4","__wbg_node_02999533c4ea02e3","__wbg_process_5c1d670bc53614b8","__wbg_randomFillSync_ab2cfe79ebbf2740","randomFillSync","__wbg_require_79b1e9274cde3c87","__wbg_set_3fda3bac07393de4","__wbg_set_65595bdd868b3009","__wbg_set_8fc6bf8a5b1071d1","__wbg_setinnerHTML_31bde41f835786f7","__wbg_static_accessor_GLOBAL_88a902d13a557d07","__wbg_static_accessor_GLOBAL_THIS_56578be7e9f832b0","__wbg_static_accessor_SELF_37c5d418e4bf5819","__wbg_static_accessor_WINDOW_5de37043a91a9c40","__wbg_subarray_aa9065fa9dc5df96","__wbg_versions_c71aa1626a93e0a1","__wbindgen_error_new","__wbindgen_init_externref_table","table","grow","__wbindgen_is_function","__wbindgen_is_object","__wbindgen_is_string","__wbindgen_is_undefined","__wbindgen_memory","__wbindgen_rethrow","__wbindgen_string_new","__wbindgen_throw","__wbg_get_imports","_await$__wbg_load","Response","instantiateStreaming","instantiate","Instance","__wbg_load","__wbindgen_wasm_module","__wbindgen_start","__wbg_finalize_init","webpackEmptyContext","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","loaded","__webpack_modules__","amdO","getter","__esModule","definition","hmd","scriptUrl","importScripts","baseURI","__webpack_exports__"],"sourceRoot":""}