{"version":3,"file":"lib-jitsi-meet.min.js","mappings":"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","sources":["webpack://JitsiMeetJS/webpack/universalModuleDefinition","webpack://JitsiMeetJS/./index.js","webpack://JitsiMeetJS/./modules/statistics/SpeakerStats.js","webpack://JitsiMeetJS/./modules/util/RandomUtil.js","webpack://JitsiMeetJS/./modules/util/ScriptUtil.js","webpack://JitsiMeetJS/./modules/util/UsernameGenerator.js","webpack://JitsiMeetJS/./node_modules/@hapi/bourne/lib/index.js","webpack://JitsiMeetJS/./node_modules/@jitsi/js-utils/node_modules/ua-parser-js/src/ua-parser.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/sdp-interop/node_modules/sdp-transform/lib/grammar.js","webpack://JitsiMeetJS/./node_modules/@jitsi/sdp-interop/node_modules/sdp-transform/lib/index.js","webpack://JitsiMeetJS/./node_modules/@jitsi/sdp-interop/node_modules/sdp-transform/lib/parser.js","webpack://JitsiMeetJS/./node_modules/@jitsi/sdp-interop/node_modules/sdp-transform/lib/writer.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/webpack:/watchRTC/webpack/runtime/hasOwnProperty shorthand","webpack://JitsiMeetJS/./node_modules/base64-js/index.js","webpack://JitsiMeetJS/./node_modules/current-executing-script/dist/currentExecutingScript.js","webpack://JitsiMeetJS/./node_modules/events/events.js","webpack://JitsiMeetJS/./node_modules/jquery/dist/jquery.slim.min.js","webpack://JitsiMeetJS/./node_modules/js-md5/src/md5.js","webpack://JitsiMeetJS/./node_modules/lodash.clonedeep/index.js","webpack://JitsiMeetJS/./node_modules/lodash.debounce/index.js","webpack://JitsiMeetJS/./node_modules/lodash.isequal/index.js","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/../src/strophe.disco.js","webpack://JitsiMeetJS/../src/strophe.stream-management.js","webpack://JitsiMeetJS/./node_modules/uuid/dist/bytesToUuid.js","webpack://JitsiMeetJS/./node_modules/uuid/dist/index.js","webpack://JitsiMeetJS/./node_modules/uuid/dist/md5-browser.js","webpack://JitsiMeetJS/./node_modules/uuid/dist/rng-browser.js","webpack://JitsiMeetJS/./node_modules/uuid/dist/sha1-browser.js","webpack://JitsiMeetJS/./node_modules/uuid/dist/v1.js","webpack://JitsiMeetJS/./node_modules/uuid/dist/v3.js","webpack://JitsiMeetJS/./node_modules/uuid/dist/v35.js","webpack://JitsiMeetJS/./node_modules/uuid/dist/v4.js","webpack://JitsiMeetJS/./node_modules/uuid/dist/v5.js","webpack://JitsiMeetJS/./service/RTC/RTCEvents.ts","webpack://JitsiMeetJS/./service/RTC/Resolutions.js","webpack://JitsiMeetJS/./service/RTC/VideoType.ts","webpack://JitsiMeetJS/./service/authentication/AuthenticationEvents.js","webpack://JitsiMeetJS/./service/statistics/constants.ts","webpack://JitsiMeetJS/./service/xmpp/XMPPEvents.ts","webpack://JitsiMeetJS/./JitsiConferenceErrors.ts","webpack://JitsiMeetJS/./JitsiConferenceEvents.ts","webpack://JitsiMeetJS/./JitsiTrackEvents.ts","webpack://JitsiMeetJS/./service/statistics/AnalyticsEvents.ts","webpack://JitsiMeetJS/./service/statistics/Events.ts","webpack://JitsiMeetJS/./node_modules/@jitsi/js-utils/browser-detection/constants.js","webpack://JitsiMeetJS/./node_modules/@jitsi/js-utils/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/rtcstats/obfuscator.js","webpack://JitsiMeetJS/./node_modules/@jitsi/rtcstats/trace-ws.js","webpack://JitsiMeetJS/./modules/RTCStats/RTCStatsEvents.ts","webpack://JitsiMeetJS/./modules/util/EventEmitter.js","webpack://JitsiMeetJS/./node_modules/@jitsi/js-utils/jitsi-local-storage/index.js","webpack://JitsiMeetJS/./modules/settings/Settings.js","webpack://JitsiMeetJS/./modules/RTCStats/RTCStats.ts","webpack://JitsiMeetJS/./modules/browser/index.js","webpack://JitsiMeetJS/./modules/browser/BrowserCapabilities.js","webpack://JitsiMeetJS/./modules/watchRTC/WatchRTC.ts","webpack://JitsiMeetJS/./modules/watchRTC/functions.ts","webpack://JitsiMeetJS/./modules/statistics/AnalyticsAdapter.js","webpack://JitsiMeetJS/./modules/statistics/LocalStatsCollector.js","webpack://JitsiMeetJS/./modules/util/MathUtil.js","webpack://JitsiMeetJS/./modules/statistics/PerformanceObserverStats.js","webpack://JitsiMeetJS/./service/RTC/MediaType.ts","webpack://JitsiMeetJS/./modules/flags/FeatureFlags.ts","webpack://JitsiMeetJS/./modules/statistics/RTPStatsCollector.js","webpack://JitsiMeetJS/./modules/statistics/statistics.js","webpack://JitsiMeetJS/./modules/util/EventEmitterForwarder.ts","webpack://JitsiMeetJS/./JitsiConferenceEventManager.js","webpack://JitsiMeetJS/./modules/statistics/constants.js","webpack://JitsiMeetJS/./JitsiParticipant.js","webpack://JitsiMeetJS/./JitsiTrackErrors.ts","webpack://JitsiMeetJS/./JitsiTrackError.js","webpack://JitsiMeetJS/./JitsiConnectionEvents.ts","webpack://JitsiMeetJS/./node_modules/@jitsi/js-utils/json.js","webpack://JitsiMeetJS/./JitsiConnectionErrors.ts","webpack://JitsiMeetJS/./modules/util/Deferred.js","webpack://JitsiMeetJS/./modules/util/Listenable.js","webpack://JitsiMeetJS/./modules/e2ee/E2EEContext.js","webpack://JitsiMeetJS/./modules/e2ee/KeyHandler.js","webpack://JitsiMeetJS/./modules/e2ee/ExternallyManagedKeyHandler.js","webpack://JitsiMeetJS/./node_modules/uuid/wrapper.mjs","webpack://JitsiMeetJS/./modules/e2ee/E2EEErrors.ts","webpack://JitsiMeetJS/./modules/e2ee/SAS.js","webpack://JitsiMeetJS/./modules/e2ee/OlmAdapter.js","webpack://JitsiMeetJS/./modules/e2ee/ManagedKeyHandler.js","webpack://JitsiMeetJS/./modules/e2ee/crypto-utils.js","webpack://JitsiMeetJS/./modules/e2ee/E2EEncryption.js","webpack://JitsiMeetJS/./modules/xmpp/sha1.js","webpack://JitsiMeetJS/./modules/xmpp/Caps.js","webpack://JitsiMeetJS/./modules/connectivity/NetworkInfo.js","webpack://JitsiMeetJS/./modules/util/Retry.js","webpack://JitsiMeetJS/./modules/xmpp/ResumeTask.js","webpack://JitsiMeetJS/./modules/xmpp/StropheLastSuccess.js","webpack://JitsiMeetJS/./modules/xmpp/ConnectionPlugin.js","webpack://JitsiMeetJS/./modules/xmpp/strophe.ping.js","webpack://JitsiMeetJS/./modules/xmpp/XmppConnection.js","webpack://JitsiMeetJS/./modules/xmpp/moderator.js","webpack://JitsiMeetJS/./JitsiTranscriptionStatus.ts","webpack://JitsiMeetJS/./modules/xmpp/AVModeration.js","webpack://JitsiMeetJS/./modules/xmpp/BreakoutRooms.js","webpack://JitsiMeetJS/./modules/xmpp/Lobby.js","webpack://JitsiMeetJS/./modules/xmpp/RoomMetadata.ts","webpack://JitsiMeetJS/./modules/xmpp/ChatRoom.js","webpack://JitsiMeetJS/./modules/xmpp/strophe.emuc.js","webpack://JitsiMeetJS/./modules/xmpp/JingleHelperFunctions.js","webpack://JitsiMeetJS/./service/RTC/CodecMimeType.ts","webpack://JitsiMeetJS/./service/RTC/MediaDirection.ts","webpack://JitsiMeetJS/./modules/RTC/ScreenObtainer.js","webpack://JitsiMeetJS/./modules/sdp/SDPUtil.js","webpack://JitsiMeetJS/./modules/sdp/SDP.js","webpack://JitsiMeetJS/./modules/sdp/SDPDiffer.js","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.js","webpack://JitsiMeetJS/./node_modules/async-es/queue.js","webpack://JitsiMeetJS/./modules/xmpp/JingleSessionState.ts","webpack://JitsiMeetJS/./modules/xmpp/JingleSession.js","webpack://JitsiMeetJS/./modules/xmpp/MediaSessionEvents.ts","webpack://JitsiMeetJS/./modules/xmpp/JingleSessionPC.js","webpack://JitsiMeetJS/./modules/xmpp/strophe.jingle.js","webpack://JitsiMeetJS/./modules/xmpp/strophe.logger.js","webpack://JitsiMeetJS/./modules/xmpp/strophe.rayo.js","webpack://JitsiMeetJS/./modules/xmpp/strophe.util.js","webpack://JitsiMeetJS/./modules/xmpp/xmpp.js","webpack://JitsiMeetJS/./authenticateAndUpgradeRole.js","webpack://JitsiMeetJS/./modules/RTC/BridgeChannel.js","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/./modules/RTC/RTCUtils.js","webpack://JitsiMeetJS/./modules/RTC/JitsiTrack.js","webpack://JitsiMeetJS/./modules/RTC/JitsiLocalTrack.js","webpack://JitsiMeetJS/./node_modules/@jitsi/sdp-interop/lib/transform.js","webpack://JitsiMeetJS/./node_modules/@jitsi/sdp-interop/lib/interop.js","webpack://JitsiMeetJS/./service/RTC/SignalingEvents.ts","webpack://JitsiMeetJS/./service/RTC/SignalingLayer.js","webpack://JitsiMeetJS/./service/RTC/StandardVideoQualitySettings.ts","webpack://JitsiMeetJS/./modules/sdp/SdpTransformUtil.js","webpack://JitsiMeetJS/./modules/sdp/LocalSdpMunger.js","webpack://JitsiMeetJS/./modules/sdp/RtxModifier.js","webpack://JitsiMeetJS/./modules/sdp/SdpSimulcast.ts","webpack://JitsiMeetJS/./modules/connectivity/TrackStreamingStatus.ts","webpack://JitsiMeetJS/./modules/RTC/JitsiRemoteTrack.js","webpack://JitsiMeetJS/./service/RTC/VideoEncoderScalabilityMode.ts","webpack://JitsiMeetJS/./modules/RTC/TPCUtils.js","webpack://JitsiMeetJS/./modules/RTC/TraceablePeerConnection.js","webpack://JitsiMeetJS/./modules/RTC/RTC.js","webpack://JitsiMeetJS/./service/connectivity/ConnectionQualityEvents.ts","webpack://JitsiMeetJS/./modules/connectivity/ConnectionQuality.js","webpack://JitsiMeetJS/./modules/connectivity/IceFailedHandling.js","webpack://JitsiMeetJS/./modules/detection/DetectionEvents.ts","webpack://JitsiMeetJS/./modules/detection/NoAudioSignalDetection.js","webpack://JitsiMeetJS/./modules/detection/P2PDominantSpeakerDetection.js","webpack://JitsiMeetJS/./modules/webaudio/WebAudioUtils.js","webpack://JitsiMeetJS/./modules/detection/TrackVADEmitter.js","webpack://JitsiMeetJS/./modules/detection/VADAudioAnalyser.js","webpack://JitsiMeetJS/./modules/detection/VADNoiseDetection.js","webpack://JitsiMeetJS/./modules/detection/VADTalkMutedDetection.js","webpack://JitsiMeetJS/./service/e2eping/E2ePingEvents.ts","webpack://JitsiMeetJS/./modules/e2eping/e2eping.js","webpack://JitsiMeetJS/./modules/event/Jvb121EventGenerator.js","webpack://JitsiMeetJS/./modules/litemode/LiteModeContext.js","webpack://JitsiMeetJS/./modules/qualitycontrol/CodecSelection.js","webpack://JitsiMeetJS/./modules/qualitycontrol/ReceiveVideoController.js","webpack://JitsiMeetJS/./modules/qualitycontrol/SendVideoController.js","webpack://JitsiMeetJS/./modules/qualitycontrol/QualityController.ts","webpack://JitsiMeetJS/./modules/recording/recordingXMLUtils.js","webpack://JitsiMeetJS/./modules/recording/JibriSession.js","webpack://JitsiMeetJS/./modules/recording/RecordingManager.js","webpack://JitsiMeetJS/./modules/statistics/AvgRTPStatsReporter.js","webpack://JitsiMeetJS/./modules/statistics/SpeakerStatsCollector.js","webpack://JitsiMeetJS/./modules/version/ComponentsVersions.ts","webpack://JitsiMeetJS/./modules/videosipgw/VideoSIPGWConstants.ts","webpack://JitsiMeetJS/./modules/videosipgw/JitsiVideoSIPGWSession.js","webpack://JitsiMeetJS/./modules/videosipgw/VideoSIPGW.js","webpack://JitsiMeetJS/./modules/xmpp/SignalingLayerImpl.js","webpack://JitsiMeetJS/./service/RTC/BridgeVideoType.ts","webpack://JitsiMeetJS/./JitsiConference.js","webpack://JitsiMeetJS/./JitsiConnection.js","webpack://JitsiMeetJS/./JitsiMediaDevicesEvents.ts","webpack://JitsiMeetJS/./JitsiMediaDevices.js","webpack://JitsiMeetJS/./modules/detection/ActiveDeviceDetector.js","webpack://JitsiMeetJS/./modules/proxyconnection/CustomSignalingLayer.js","webpack://JitsiMeetJS/./modules/proxyconnection/constants.ts","webpack://JitsiMeetJS/./modules/proxyconnection/ProxyConnectionPC.js","webpack://JitsiMeetJS/./modules/proxyconnection/ProxyConnectionService.js","webpack://JitsiMeetJS/./modules/webaudio/AudioMixer.js","webpack://JitsiMeetJS/./JitsiMeetJS.ts","webpack://JitsiMeetJS/./modules/recording/recordingConstants.js","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/hasOwnProperty shorthand","webpack://JitsiMeetJS/webpack/runtime/make namespace object","webpack://JitsiMeetJS/webpack/runtime/node module decorator","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 ","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 ? Object.assign({}, window.JitsiMeetJS, module)\n : module);\n}\n\nmodule.exports = _mergeNamespaceAndModule(ljm);\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 /**\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, displayName, isLocalStats) {\n this._userId = userId;\n this.setDisplayName(displayName);\n this._isLocalStats = isLocalStats || false;\n this.setDominantSpeaker(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() {\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() {\n return this.displayName;\n }\n\n /**\n * Updates the last known name of the user being tracked.\n *\n * @param {string} - The user name.\n * @returns {void}\n */\n setDisplayName(newName) {\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() {\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() {\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 - Indecates whether the dominant speaker is silent or not.\n * @returns {void}\n */\n setDominantSpeaker(isNowDominantSpeaker, silence) {\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() {\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() {\n return this._hasLeft;\n }\n\n /**\n * Set the user as having left the meeting.\n *\n * @returns {void}\n */\n markAsHasLeft() {\n this._hasLeft = true;\n this.setDominantSpeaker(false);\n }\n\n /**\n * Gets the face landmarks of the user.\n *\n * @returns {Object}\n */\n getFaceLandmarks() {\n return this._faceLandmarks;\n }\n\n /**\n * Sets the face landmarks of the user.\n *\n * @param {Object} faceLandmarks - object with face expressions.\n * @returns {void}\n */\n setFaceLandmarks(faceLandmarks) {\n this._faceLandmarks = faceLandmarks;\n }\n\n /**\n * Adds new face landmarks to speaker stats.\n *\n * @param {string} faceExpression\n * @param {number} duration\n */\n addFaceLandmarks(faceLandmarks) {\n this._faceLandmarks.push(faceLandmarks);\n }\n}\n\nmodule.exports = SpeakerStats;\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 */\nfunction randomInt(min, max) {\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 */\nfunction randomElement(arr) {\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 */\nfunction randomAlphanumStr(length) {\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 randomHexDigit() {\n return randomElement(HEX_DIGITS);\n },\n\n /**\n * Returns a random string of hex digits with length 'len'.\n * @param len the length.\n */\n randomHexString(len) {\n let ret = '';\n\n while (len--) { // eslint-disable-line no-param-reassign\n ret += this.randomHexDigit();\n }\n\n return ret;\n },\n randomElement,\n randomAlphanumStr,\n randomInt\n};\n\nmodule.exports = RandomUtil;\n","const currentExecutingScript = require('current-executing-script');\n\n/* eslint-disable max-params */\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 *\n * @param src the source from the which the script is to be (down)loaded\n * @param async true to asynchronously load the script or false to\n * synchronously load the script\n * @param 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 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 loadCallback on load callback function\n * @param 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 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\nmodule.exports = ScriptUtil;\n","const RandomUtil = require('./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 = [\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() {\n const name = RandomUtil.randomElement(names);\n const suffix = RandomUtil.randomAlphanumStr(3);\n\n return `${name}-${suffix}`;\n}\n\nmodule.exports = {\n generateUsername\n};\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","/////////////////////////////////////////////////////////////////////////////////\n/* UAParser.js v1.0.35\n Copyright © 2012-2021 Faisal Salman \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 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","/* 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 LogCollector. Class implements LoggerTransport\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 Logger 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 LogCollector\n * will use the logStorage 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 LogCollector requests log entry storage. The method's argument\n * is an array which can contain strings and objects. 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 boolean 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 LogCollector configuration options.\n * @param {number} options.maxEntryLength the size limit for a single log entry\n * to be stored. The LogCollector will push the entry as soon as it\n * reaches or exceeds this limit given that logStorage.isReady\n * returns true. Otherwise the log entry will be cached until the log\n * storage becomes ready. Note that the \"is ready\" condition is checked every\n * options.storeInterval milliseconds.\n * @param {number} options.storeInterval how often the logs should be stored in\n * case maxEntryLength was not exceeded.\n * @param {boolean} options.stringifyObjects indicates whether or not object\n * arguments should be \"stringified\" with JSON.stringify 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 * null 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 * Object 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 JSON.stringify and\n * returns \"[object with circular refs?]\" instead of an object if it fails.\n *\n * @param {object} someObject the object to be stringified.\n *\n * @return {string} the result of JSON.stringify 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 * Logger'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 null then\n * the message wil be discarded by this LogCollector.\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 true if the next periodic task should be\n * scheduled after the log entry is stored. false 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 LogCollector.\n */\n LogCollector: LogCollector\n};\n","var grammar = module.exports = {\n v: [{\n name: 'version',\n reg: /^(\\d*)$/\n }],\n o: [{\n // 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: [{\n // t=0 0\n name: 'timing',\n reg: /^(\\d*) (\\d*)/,\n names: ['start', 'stop'],\n format: '%d %d'\n }],\n c: [{\n // 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: [{\n // 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: [{\n // 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 {\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 {\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 {\n // a=control:streamid=0\n name: 'control',\n reg: /^control:(.*)/,\n format: 'control:%s'\n },\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 {\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:%s trr-int %d'\n },\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 {\n // a=extmap:2 urn:ietf:params:rtp-hdrext:toffset\n // a=extmap:1/recvonly URI-gps-string\n // a=extmap:3 urn:ietf:params:rtp-hdrext:encrypt urn:ietf:params:rtp-hdrext:smpte-tc 25@600/24\n push: 'ext',\n reg: /^extmap:(\\d+)(?:\\/(\\w+))?(?: (urn:ietf:params:rtp-hdrext:encrypt))? (\\S*)(?: (\\S*))?/,\n names: ['value', 'direction', 'encrypt-uri', 'uri', 'config'],\n format: function (o) {\n return (\n 'extmap:%d' +\n (o.direction ? '/%s' : '%v') +\n (o['encrypt-uri'] ? ' %s' : '%v') +\n ' %s' +\n (o.config ? ' %s' : '')\n );\n }\n },\n {\n // a=extmap-allow-mixed\n name: 'extmapAllowMixed',\n reg: /^(extmap-allow-mixed)/\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 {\n // a=setup:actpass\n name: 'setup',\n reg: /^setup:(\\w*)/,\n format: 'setup:%s'\n },\n {\n // a=connection:new\n name: 'connectionType',\n reg: /^connection:(new|existing)/,\n format: 'connection:%s'\n },\n {\n // a=mid:1\n name: 'mid',\n reg: /^mid:([^\\s]*)/,\n format: 'mid:%s'\n },\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 {\n // a=ptime:20\n name: 'ptime',\n reg: /^ptime:(\\d*(?:\\.\\d*)*)/,\n format: 'ptime:%d'\n },\n {\n // a=maxptime:60\n name: 'maxptime',\n reg: /^maxptime:(\\d*(?:\\.\\d*)*)/,\n format: 'maxptime:%d'\n },\n {\n // a=sendrecv\n name: 'direction',\n reg: /^(sendrecv|recvonly|sendonly|inactive)/\n },\n {\n // a=ice-lite\n name: 'icelite',\n reg: /^(ice-lite)/\n },\n {\n // a=ice-ufrag:F7gI\n name: 'iceUfrag',\n reg: /^ice-ufrag:(\\S*)/,\n format: 'ice-ufrag:%s'\n },\n {\n // a=ice-pwd:x9cml/YzichV2+XlhiMu8g\n name: 'icePwd',\n reg: /^ice-pwd:(\\S*)/,\n format: 'ice-pwd:%s'\n },\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 {\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 {\n // a=end-of-candidates (keep after the candidates line for readability)\n name: 'endOfCandidates',\n reg: /^(end-of-candidates)/\n },\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 {\n // a=ice-options:google-ice\n name: 'iceOptions',\n reg: /^ice-options:(\\S*)/,\n format: 'ice-options:%s'\n },\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 {\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 {\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 {\n // a=group:BUNDLE audio video\n push: 'groups',\n reg: /^group:(\\w*) (.*)/,\n names: ['type', 'mids'],\n format: 'group:%s %s'\n },\n {\n // a=rtcp-mux\n name: 'rtcpMux',\n reg: /^(rtcp-mux)/\n },\n {\n // a=rtcp-rsize\n name: 'rtcpRsize',\n reg: /^(rtcp-rsize)/\n },\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 {\n // a=x-google-flag:conference\n name: 'xGoogleFlag',\n reg: /^x-google-flag:([^\\s]*)/,\n format: 'x-google-flag:%s'\n },\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 {\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 {\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 {\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 {\n // RFC4570\n // a=source-filter: incl IN IP4 239.5.2.31 10.1.15.5\n name: 'sourceFilter',\n reg: /^source-filter: *(excl|incl) (\\S*) (IP4|IP6|\\*) (\\S*) (.*)/,\n names: ['filterMode', 'netType', 'addressTypes', 'destAddress', 'srcList'],\n format: 'source-filter: %s %s %s %s %s'\n },\n {\n // a=bundle-only\n name: 'bundleOnly',\n reg: /^(bundle-only)/\n },\n {\n // a=label:1\n name: 'label',\n reg: /^label:(.+)/,\n format: 'label:%s'\n },\n {\n // RFC version 26 for SCTP over DTLS\n // https://tools.ietf.org/html/draft-ietf-mmusic-sctp-sdp-26#section-5\n name: 'sctpPort',\n reg: /^sctp-port:(\\d+)$/,\n format: 'sctp-port:%s'\n },\n {\n // RFC version 26 for SCTP over DTLS\n // https://tools.ietf.org/html/draft-ietf-mmusic-sctp-sdp-26#section-6\n name: 'maxMessageSize',\n reg: /^max-message-size:(\\d+)$/,\n format: 'max-message-size:%s'\n },\n {\n // RFC7273\n // a=ts-refclk:ptp=IEEE1588-2008:39-A7-94-FF-FE-07-CB-D0:37\n push:'tsRefClocks',\n reg: /^ts-refclk:([^\\s=]*)(?:=(\\S*))?/,\n names: ['clksrc', 'clksrcExt'],\n format: function (o) {\n return 'ts-refclk:%s' + (o.clksrcExt != null ? '=%s' : '');\n }\n },\n {\n // RFC7273\n // a=mediaclk:direct=963214424\n name:'mediaClk',\n reg: /^mediaclk:(?:id=(\\S*))? *([^\\s=]*)(?:=(\\S*))?(?: *rate=(\\d+)\\/(\\d+))?/,\n names: ['id', 'mediaClockName', 'mediaClockValue', 'rateNumerator', 'rateDenominator'],\n format: function (o) {\n var str = 'mediaclk:';\n str += (o.id != null ? 'id=%s %s' : '%v%s');\n str += (o.mediaClockValue != null ? '=%s' : '');\n str += (o.rateNumerator != null ? ' rate=%s' : '');\n str += (o.rateDenominator != null ? '/%s' : '');\n return str;\n }\n },\n {\n // a=keywds:keywords\n name: 'keywords',\n reg: /^keywds:(.+)$/,\n format: 'keywds:%s'\n },\n {\n // a=content:main\n name: 'content',\n reg: /^content:(.+)/,\n format: 'content:%s'\n },\n // BFCP https://tools.ietf.org/html/rfc4583\n {\n // a=floorctrl:c-s\n name: 'bfcpFloorCtrl',\n reg: /^floorctrl:(c-only|s-only|c-s)/,\n format: 'floorctrl:%s'\n },\n {\n // a=confid:1\n name: 'bfcpConfId',\n reg: /^confid:(\\d+)/,\n format: 'confid:%s'\n },\n {\n // a=userid:1\n name: 'bfcpUserId',\n reg: /^userid:(\\d+)/,\n format: 'userid:%s'\n },\n {\n // a=floorid:1\n name: 'bfcpFloorId',\n reg: /^floorid:(.+) (?:m-stream|mstrm):(.+)/,\n names: ['id', 'mStream'],\n format: 'floorid:%s mstrm:%s'\n },\n {\n // any a= that we don't understand is kept 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.parseParams = parser.parseParams;\nexports.parseFmtpConfig = parser.parseFmtpConfig; // Alias of 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 } else if (s.length === 1 && expr.length > 1) {\n acc[s[0]] = undefined;\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.toString().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","(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, \"×tamp=\").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))","'use strict'\n\nexports.byteLength = byteLength\nexports.toByteArray = toByteArray\nexports.fromByteArray = fromByteArray\n\nvar lookup = []\nvar revLookup = []\nvar Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array\n\nvar code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'\nfor (var i = 0, len = code.length; i < len; ++i) {\n lookup[i] = code[i]\n revLookup[code.charCodeAt(i)] = i\n}\n\n// Support decoding URL-safe base64 strings, as Node.js does.\n// See: https://en.wikipedia.org/wiki/Base64#URL_applications\nrevLookup['-'.charCodeAt(0)] = 62\nrevLookup['_'.charCodeAt(0)] = 63\n\nfunction getLens (b64) {\n var len = b64.length\n\n if (len % 4 > 0) {\n throw new Error('Invalid string. Length must be a multiple of 4')\n }\n\n // Trim off extra bytes after placeholder bytes are found\n // See: https://github.com/beatgammit/base64-js/issues/42\n var validLen = b64.indexOf('=')\n if (validLen === -1) validLen = len\n\n var placeHoldersLen = validLen === len\n ? 0\n : 4 - (validLen % 4)\n\n return [validLen, placeHoldersLen]\n}\n\n// base64 is 4/3 + up to two characters of the original data\nfunction byteLength (b64) {\n var lens = getLens(b64)\n var validLen = lens[0]\n var placeHoldersLen = lens[1]\n return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen\n}\n\nfunction _byteLength (b64, validLen, placeHoldersLen) {\n return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen\n}\n\nfunction toByteArray (b64) {\n var tmp\n var lens = getLens(b64)\n var validLen = lens[0]\n var placeHoldersLen = lens[1]\n\n var arr = new Arr(_byteLength(b64, validLen, placeHoldersLen))\n\n var curByte = 0\n\n // if there are placeholders, only get up to the last complete 4 chars\n var len = placeHoldersLen > 0\n ? validLen - 4\n : validLen\n\n var i\n for (i = 0; i < len; i += 4) {\n tmp =\n (revLookup[b64.charCodeAt(i)] << 18) |\n (revLookup[b64.charCodeAt(i + 1)] << 12) |\n (revLookup[b64.charCodeAt(i + 2)] << 6) |\n revLookup[b64.charCodeAt(i + 3)]\n arr[curByte++] = (tmp >> 16) & 0xFF\n arr[curByte++] = (tmp >> 8) & 0xFF\n arr[curByte++] = tmp & 0xFF\n }\n\n if (placeHoldersLen === 2) {\n tmp =\n (revLookup[b64.charCodeAt(i)] << 2) |\n (revLookup[b64.charCodeAt(i + 1)] >> 4)\n arr[curByte++] = tmp & 0xFF\n }\n\n if (placeHoldersLen === 1) {\n tmp =\n (revLookup[b64.charCodeAt(i)] << 10) |\n (revLookup[b64.charCodeAt(i + 1)] << 4) |\n (revLookup[b64.charCodeAt(i + 2)] >> 2)\n arr[curByte++] = (tmp >> 8) & 0xFF\n arr[curByte++] = tmp & 0xFF\n }\n\n return arr\n}\n\nfunction tripletToBase64 (num) {\n return lookup[num >> 18 & 0x3F] +\n lookup[num >> 12 & 0x3F] +\n lookup[num >> 6 & 0x3F] +\n lookup[num & 0x3F]\n}\n\nfunction encodeChunk (uint8, start, end) {\n var tmp\n var output = []\n for (var i = start; i < end; i += 3) {\n tmp =\n ((uint8[i] << 16) & 0xFF0000) +\n ((uint8[i + 1] << 8) & 0xFF00) +\n (uint8[i + 2] & 0xFF)\n output.push(tripletToBase64(tmp))\n }\n return output.join('')\n}\n\nfunction fromByteArray (uint8) {\n var tmp\n var len = uint8.length\n var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes\n var parts = []\n var maxChunkLength = 16383 // must be multiple of 3\n\n // go through the array every three bytes, we'll deal with trailing stuff later\n for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) {\n parts.push(encodeChunk(\n uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength)\n ))\n }\n\n // pad the end with zeros, but make sure to not forget the extra bytes\n if (extraBytes === 1) {\n tmp = uint8[len - 1]\n parts.push(\n lookup[tmp >> 2] +\n lookup[(tmp << 4) & 0x3F] +\n '=='\n )\n } else if (extraBytes === 2) {\n tmp = (uint8[len - 2] << 8) + uint8[len - 1]\n parts.push(\n lookup[tmp >> 10] +\n lookup[(tmp >> 4) & 0x3F] +\n lookup[(tmp << 2) & 0x3F] +\n '='\n )\n }\n\n return parts.join('')\n}\n","/*!\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. `click`\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. `click`\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. `click`\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 // \n // \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 // \n // \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 // \n // \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","/*! jQuery v3.6.1 -ajax,-ajax/jsonp,-ajax/load,-ajax/script,-ajax/var/location,-ajax/var/nonce,-ajax/var/rquery,-ajax/xhr,-manipulation/_evalUrl,-deprecated/ajax-event-alias,-effects,-effects/Tween,-effects/animatedSelector | (c) OpenJS Foundation and other contributors | jquery.org/license */\n!function(e,t){\"use strict\";\"object\"==typeof module&&\"object\"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error(\"jQuery requires a window with a document\");return t(e)}:t(e)}(\"undefined\"!=typeof window?window:this,function(g,e){\"use strict\";var t=[],r=Object.getPrototypeOf,s=t.slice,v=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,y=n.hasOwnProperty,a=y.toString,l=a.call(Object),m={},b=function(e){return\"function\"==typeof e&&\"number\"!=typeof e.nodeType&&\"function\"!=typeof e.item},x=function(e){return null!=e&&e===e.window},w=g.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function C(e,t,n){var r,i,o=(n=n||w).createElement(\"script\");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function T(e){return null==e?e+\"\":\"object\"==typeof e||\"function\"==typeof e?n[o.call(e)]||\"object\":typeof e}var f=\"3.6.1 -ajax,-ajax/jsonp,-ajax/load,-ajax/script,-ajax/var/location,-ajax/var/nonce,-ajax/var/rquery,-ajax/xhr,-manipulation/_evalUrl,-deprecated/ajax-event-alias,-effects,-effects/Tween,-effects/animatedSelector\",E=function(e,t){return new E.fn.init(e,t)};function d(e){var t=!!e&&\"length\"in e&&e.length,n=T(e);return!b(e)&&!x(e)&&(\"array\"===n||0===t||\"number\"==typeof t&&0+~]|\"+R+\")\"+R+\"*\"),U=new RegExp(R+\"|>\"),V=new RegExp(W),X=new RegExp(\"^\"+B+\"$\"),Q={ID:new RegExp(\"^#(\"+B+\")\"),CLASS:new RegExp(\"^\\\\.(\"+B+\")\"),TAG:new RegExp(\"^(\"+B+\"|[*])\"),ATTR:new RegExp(\"^\"+M),PSEUDO:new RegExp(\"^\"+W),CHILD:new RegExp(\"^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\\\(\"+R+\"*(even|odd|(([+-]|)(\\\\d*)n|)\"+R+\"*(?:([+-]|)\"+R+\"*(\\\\d+)|))\"+R+\"*\\\\)|)\",\"i\"),bool:new RegExp(\"^(?:\"+I+\")$\",\"i\"),needsContext:new RegExp(\"^\"+R+\"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\\\(\"+R+\"*((?:-\\\\d)?\\\\d*)\"+R+\"*\\\\)|)(?=[^-]|$)\",\"i\")},Y=/HTML$/i,G=/^(?:input|select|textarea|button)$/i,K=/^h\\d$/i,J=/^[^{]+\\{\\s*\\[native \\w/,Z=/^(?:#([\\w-]+)|(\\w+)|\\.([\\w-]+))$/,ee=/[+~]/,te=new RegExp(\"\\\\\\\\[\\\\da-fA-F]{1,6}\"+R+\"?|\\\\\\\\([^\\\\r\\\\n\\\\f])\",\"g\"),ne=function(e,t){var n=\"0x\"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\\0-\\x1f\\x7f]|^-?\\d)|^-$|[^\\0-\\x1f\\x7f-\\uFFFF\\w-]/g,ie=function(e,t){return t?\"\\0\"===e?\"\\ufffd\":e.slice(0,-1)+\"\\\\\"+e.charCodeAt(e.length-1).toString(16)+\" \":\"\\\\\"+e},oe=function(){C()},ae=xe(function(e){return!0===e.disabled&&\"fieldset\"===e.nodeName.toLowerCase()},{dir:\"parentNode\",next:\"legend\"});try{O.apply(t=P.call(d.childNodes),d.childNodes),t[d.childNodes.length].nodeType}catch(e){O={apply:t.length?function(e,t){q.apply(e,P.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,d=e?e.nodeType:9;if(n=n||[],\"string\"!=typeof t||!t||1!==d&&9!==d&&11!==d)return n;if(!r&&(C(e),e=e||T,E)){if(11!==d&&(u=Z.exec(t)))if(i=u[1]){if(9===d){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return O.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&p.getElementsByClassName&&e.getElementsByClassName)return O.apply(n,e.getElementsByClassName(i)),n}if(p.qsa&&!k[t+\" \"]&&(!v||!v.test(t))&&(1!==d||\"object\"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===d&&(U.test(t)||_.test(t))){(f=ee.test(t)&&ye(e.parentNode)||e)===e&&p.scope||((s=e.getAttribute(\"id\"))?s=s.replace(re,ie):e.setAttribute(\"id\",s=A)),o=(l=h(t)).length;while(o--)l[o]=(s?\"#\"+s:\":scope\")+\" \"+be(l[o]);c=l.join(\",\")}try{return O.apply(n,f.querySelectorAll(c)),n}catch(e){k(t,!0)}finally{s===A&&e.removeAttribute(\"id\")}}}return g(t.replace($,\"$1\"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+\" \")>x.cacheLength&&delete e[r.shift()],e[t+\" \"]=n}}function le(e){return e[A]=!0,e}function ce(e){var t=T.createElement(\"fieldset\");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split(\"|\"),r=n.length;while(r--)x.attrHandle[n[r]]=t}function de(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function pe(t){return function(e){return\"input\"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return(\"input\"===t||\"button\"===t)&&e.type===n}}function ge(t){return function(e){return\"form\"in e?e.parentNode&&!1===e.disabled?\"label\"in e?\"label\"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:\"label\"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&\"undefined\"!=typeof e.getElementsByTagName&&e}for(e in p=se.support={},i=se.isXML=function(e){var t=e&&e.namespaceURI,n=e&&(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||\"HTML\")},C=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:d;return r!=T&&9===r.nodeType&&r.documentElement&&(a=(T=r).documentElement,E=!i(T),d!=T&&(n=T.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener(\"unload\",oe,!1):n.attachEvent&&n.attachEvent(\"onunload\",oe)),p.scope=ce(function(e){return a.appendChild(e).appendChild(T.createElement(\"div\")),\"undefined\"!=typeof e.querySelectorAll&&!e.querySelectorAll(\":scope fieldset div\").length}),p.attributes=ce(function(e){return e.className=\"i\",!e.getAttribute(\"className\")}),p.getElementsByTagName=ce(function(e){return e.appendChild(T.createComment(\"\")),!e.getElementsByTagName(\"*\").length}),p.getElementsByClassName=J.test(T.getElementsByClassName),p.getById=ce(function(e){return a.appendChild(e).id=A,!T.getElementsByName||!T.getElementsByName(A).length}),p.getById?(x.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute(\"id\")===t}},x.find.ID=function(e,t){if(\"undefined\"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(x.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t=\"undefined\"!=typeof e.getAttributeNode&&e.getAttributeNode(\"id\");return t&&t.value===n}},x.find.ID=function(e,t){if(\"undefined\"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode(\"id\"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode(\"id\"))&&n.value===e)return[o]}return[]}}),x.find.TAG=p.getElementsByTagName?function(e,t){return\"undefined\"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):p.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if(\"*\"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},x.find.CLASS=p.getElementsByClassName&&function(e,t){if(\"undefined\"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(p.qsa=J.test(T.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML=\"\",e.querySelectorAll(\"[msallowcapture^='']\").length&&v.push(\"[*^$]=\"+R+\"*(?:''|\\\"\\\")\"),e.querySelectorAll(\"[selected]\").length||v.push(\"\\\\[\"+R+\"*(?:value|\"+I+\")\"),e.querySelectorAll(\"[id~=\"+A+\"-]\").length||v.push(\"~=\"),(t=T.createElement(\"input\")).setAttribute(\"name\",\"\"),e.appendChild(t),e.querySelectorAll(\"[name='']\").length||v.push(\"\\\\[\"+R+\"*name\"+R+\"*=\"+R+\"*(?:''|\\\"\\\")\"),e.querySelectorAll(\":checked\").length||v.push(\":checked\"),e.querySelectorAll(\"a#\"+A+\"+*\").length||v.push(\".#.+[+~]\"),e.querySelectorAll(\"\\\\\\f\"),v.push(\"[\\\\r\\\\n\\\\f]\")}),ce(function(e){e.innerHTML=\"\";var t=T.createElement(\"input\");t.setAttribute(\"type\",\"hidden\"),e.appendChild(t).setAttribute(\"name\",\"D\"),e.querySelectorAll(\"[name=d]\").length&&v.push(\"name\"+R+\"*[*^$|!~]?=\"),2!==e.querySelectorAll(\":enabled\").length&&v.push(\":enabled\",\":disabled\"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(\":disabled\").length&&v.push(\":enabled\",\":disabled\"),e.querySelectorAll(\"*,:x\"),v.push(\",.*:\")})),(p.matchesSelector=J.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){p.disconnectedMatch=c.call(e,\"*\"),c.call(e,\"[s!='']:x\"),s.push(\"!=\",W)}),v=v.length&&new RegExp(v.join(\"|\")),s=s.length&&new RegExp(s.join(\"|\")),t=J.test(a.compareDocumentPosition),y=t||J.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!p.sortDetached&&t.compareDocumentPosition(e)===n?e==T||e.ownerDocument==d&&y(d,e)?-1:t==T||t.ownerDocument==d&&y(d,t)?1:u?H(u,e)-H(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==T?-1:t==T?1:i?-1:o?1:u?H(u,e)-H(u,t):0;if(i===o)return de(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?de(a[r],s[r]):a[r]==d?-1:s[r]==d?1:0}),T},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(C(e),p.matchesSelector&&E&&!k[t+\" \"]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||p.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){k(t,!0)}return 0\":{dir:\"parentNode\",first:!0},\" \":{dir:\"parentNode\"},\"+\":{dir:\"previousSibling\",first:!0},\"~\":{dir:\"previousSibling\"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||\"\").replace(te,ne),\"~=\"===e[2]&&(e[3]=\" \"+e[3]+\" \"),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),\"nth\"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*(\"even\"===e[3]||\"odd\"===e[3])),e[5]=+(e[7]+e[8]||\"odd\"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return Q.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||\"\":n&&V.test(n)&&(t=h(n,!0))&&(t=n.indexOf(\")\",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return\"*\"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+\" \"];return t||(t=new RegExp(\"(^|\"+R+\")\"+e+\"(\"+R+\"|$)\"))&&m(e,function(e){return t.test(\"string\"==typeof e.className&&e.className||\"undefined\"!=typeof e.getAttribute&&e.getAttribute(\"class\")||\"\")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?\"!=\"===r:!r||(t+=\"\",\"=\"===r?t===i:\"!=\"===r?t!==i:\"^=\"===r?i&&0===t.indexOf(i):\"*=\"===r?i&&-1\",\"#\"===e.firstChild.getAttribute(\"href\")})||fe(\"type|href|height|width\",function(e,t,n){if(!n)return e.getAttribute(t,\"type\"===t.toLowerCase()?1:2)}),p.attributes&&ce(function(e){return e.innerHTML=\"\",e.firstChild.setAttribute(\"value\",\"\"),\"\"===e.firstChild.getAttribute(\"value\")})||fe(\"value\",function(e,t,n){if(!n&&\"input\"===e.nodeName.toLowerCase())return e.defaultValue}),ce(function(e){return null==e.getAttribute(\"disabled\")})||fe(I,function(e,t,n){var r;if(!n)return!0===e[t]?t.toLowerCase():(r=e.getAttributeNode(t))&&r.specified?r.value:null}),se}(g);E.find=p,E.expr=p.selectors,E.expr[\":\"]=E.expr.pseudos,E.uniqueSort=E.unique=p.uniqueSort,E.text=p.getText,E.isXMLDoc=p.isXML,E.contains=p.contains,E.escapeSelector=p.escape;var h=function(e,t,n){var r=[],i=void 0!==n;while((e=e[t])&&9!==e.nodeType)if(1===e.nodeType){if(i&&E(e).is(n))break;r.push(e)}return r},A=function(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n},N=E.expr.match.needsContext;function S(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()}var k=/^<([a-z][^\\/\\0>:\\x20\\t\\r\\n\\f]*)[\\x20\\t\\r\\n\\f]*\\/?>(?:<\\/\\1>|)$/i;function D(e,n,r){return b(n)?E.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?E.grep(e,function(e){return e===n!==r}):\"string\"!=typeof n?E.grep(e,function(e){return-1)[^>]*|#([\\w-]+))$/;(E.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||L,\"string\"==typeof e){if(!(r=\"<\"===e[0]&&\">\"===e[e.length-1]&&3<=e.length?[null,e,null]:j.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof E?t[0]:t,E.merge(this,E.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:w,!0)),k.test(r[1])&&E.isPlainObject(t))for(r in t)b(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=w.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):b(e)?void 0!==n.ready?n.ready(e):e(E):E.makeArray(e,this)}).prototype=E.fn,L=E(w);var q=/^(?:parents|prev(?:Until|All))/,O={children:!0,contents:!0,next:!0,prev:!0};function P(e,t){while((e=e[t])&&1!==e.nodeType);return e}E.fn.extend({has:function(e){var t=E(e,this),n=t.length;return this.filter(function(){for(var e=0;e\\x20\\t\\r\\n\\f]*)/i,pe=/^$|^module$|\\/(?:java|ecma)script/i;le=w.createDocumentFragment().appendChild(w.createElement(\"div\")),(ce=w.createElement(\"input\")).setAttribute(\"type\",\"radio\"),ce.setAttribute(\"checked\",\"checked\"),ce.setAttribute(\"name\",\"t\"),le.appendChild(ce),m.checkClone=le.cloneNode(!0).cloneNode(!0).lastChild.checked,le.innerHTML=\"\",m.noCloneChecked=!!le.cloneNode(!0).lastChild.defaultValue,le.innerHTML=\"\",m.option=!!le.lastChild;var he={thead:[1,\"\",\"
\"],col:[2,\"\",\"
\"],tr:[2,\"\",\"
\"],td:[3,\"\",\"
\"],_default:[0,\"\",\"\"]};function ge(e,t){var n;return n=\"undefined\"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||\"*\"):\"undefined\"!=typeof e.querySelectorAll?e.querySelectorAll(t||\"*\"):[],void 0===t||t&&S(e,t)?E.merge([e],n):n}function ve(e,t){for(var n=0,r=e.length;n\",\"\"]);var ye=/<|&#?\\w+;/;function me(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),d=[],p=0,h=e.length;p\\s*$/g;function ke(e,t){return S(e,\"table\")&&S(11!==t.nodeType?t:t.firstChild,\"tr\")&&E(e).children(\"tbody\")[0]||e}function De(e){return e.type=(null!==e.getAttribute(\"type\"))+\"/\"+e.type,e}function Le(e){return\"true/\"===(e.type||\"\").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute(\"type\"),e}function je(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,\"handle events\"),s)for(n=0,r=s[i].length;n
\",2===ft.childNodes.length),E.parseHTML=function(e,t,n){return\"string\"!=typeof e?[]:(\"boolean\"==typeof t&&(n=t,t=!1),t||(m.createHTMLDocument?((r=(t=w.implementation.createHTMLDocument(\"\")).createElement(\"base\")).href=w.location.href,t.head.appendChild(r)):t=w),o=!n&&[],(i=k.exec(e))?[t.createElement(i[1])]:(i=me([e],t,o),o&&o.length&&E(o).remove(),E.merge([],i.childNodes)));var r,i,o},E.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=E.css(e,\"position\"),c=E(e),f={};\"static\"===l&&(e.style.position=\"relative\"),s=c.offset(),o=E.css(e,\"top\"),u=E.css(e,\"left\"),(\"absolute\"===l||\"fixed\"===l)&&-1<(o+u).indexOf(\"auto\")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),b(t)&&(t=t.call(e,n,E.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),\"using\"in t?t.using.call(e,f):c.css(f)}},E.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){E.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if(\"fixed\"===E.css(r,\"position\"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&\"static\"===E.css(e,\"position\"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=E(e).offset()).top+=E.css(e,\"borderTopWidth\",!0),i.left+=E.css(e,\"borderLeftWidth\",!0))}return{top:t.top-i.top-E.css(r,\"marginTop\",!0),left:t.left-i.left-E.css(r,\"marginLeft\",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&\"static\"===E.css(e,\"position\"))e=e.offsetParent;return e||re})}}),E.each({scrollLeft:\"pageXOffset\",scrollTop:\"pageYOffset\"},function(t,i){var o=\"pageYOffset\"===i;E.fn[t]=function(e){return $(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),E.each([\"top\",\"left\"],function(e,n){E.cssHooks[n]=$e(m.pixelPosition,function(e,t){if(t)return t=Fe(e,n),Pe.test(t)?E(e).position()[n]+\"px\":t})}),E.each({Height:\"height\",Width:\"width\"},function(a,s){E.each({padding:\"inner\"+a,content:s,\"\":\"outer\"+a},function(r,o){E.fn[o]=function(e,t){var n=arguments.length&&(r||\"boolean\"!=typeof e),i=r||(!0===e||!0===t?\"margin\":\"border\");return $(this,function(e,t,n){var r;return x(e)?0===o.indexOf(\"outer\")?e[\"inner\"+a]:e.document.documentElement[\"client\"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body[\"scroll\"+a],r[\"scroll\"+a],e.body[\"offset\"+a],r[\"offset\"+a],r[\"client\"+a])):void 0===n?E.css(e,t,i):E.style(e,t,n,i)},s,n?e:void 0,n)}})}),E.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,\"**\"):this.off(t,e||\"**\",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),E.each(\"blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu\".split(\" \"),function(e,n){E.fn[n]=function(e,t){return 0> 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","/**\n * lodash (Custom Build) \n * Build: `lodash modularize exports=\"npm\" -o ./`\n * Copyright jQuery Foundation and other contributors \n * Released under MIT license \n * Based on Underscore.js 1.8.3 \n * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n */\n\n/** Used as the size to enable large array optimizations. */\nvar LARGE_ARRAY_SIZE = 200;\n\n/** Used to stand-in for `undefined` hash values. */\nvar HASH_UNDEFINED = '__lodash_hash_undefined__';\n\n/** Used as references for various `Number` constants. */\nvar MAX_SAFE_INTEGER = 9007199254740991;\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 promiseTag = '[object Promise]',\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/**\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 match `RegExp` flags from their coerced string values. */\nvar reFlags = /\\w*$/;\n\n/** Used to detect host constructors (Safari). */\nvar reIsHostCtor = /^\\[object .+?Constructor\\]$/;\n\n/** Used to detect unsigned integer values. */\nvar reIsUint = /^(?:0|[1-9]\\d*)$/;\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/** Detect free variable `global` from Node.js. */\nvar freeGlobal = typeof global == 'object' && global && global.Object === Object && global;\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\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/**\n * Adds the key-value `pair` to `map`.\n *\n * @private\n * @param {Object} map The map to modify.\n * @param {Array} pair The key-value pair to add.\n * @returns {Object} Returns `map`.\n */\nfunction addMapEntry(map, pair) {\n // Don't return `map.set` because it's not chainable in IE 11.\n map.set(pair[0], pair[1]);\n return map;\n}\n\n/**\n * Adds `value` to `set`.\n *\n * @private\n * @param {Object} set The set to modify.\n * @param {*} value The value to add.\n * @returns {Object} Returns `set`.\n */\nfunction addSetEntry(set, value) {\n // Don't return `set.add` because it's not chainable in IE 11.\n set.add(value);\n return set;\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 ? array.length : 0;\n\n while (++index < length) {\n if (iteratee(array[index], index, array) === false) {\n break;\n }\n }\n return array;\n}\n\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\n/**\n * A specialized version of `_.reduce` 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 * @param {*} [accumulator] The initial value.\n * @param {boolean} [initAccum] Specify using the first element of `array` as\n * the initial value.\n * @returns {*} Returns the accumulated value.\n */\nfunction arrayReduce(array, iteratee, accumulator, initAccum) {\n var index = -1,\n length = array ? array.length : 0;\n\n if (initAccum && length) {\n accumulator = array[++index];\n }\n while (++index < length) {\n accumulator = iteratee(accumulator, array[index], index, array);\n }\n return accumulator;\n}\n\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\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\n/**\n * Checks if `value` is a host object in IE < 9.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a host object, else `false`.\n */\nfunction isHostObject(value) {\n // Many host objects are `Object` objects that can coerce to strings\n // despite having improperly defined `toString` methods.\n var result = false;\n if (value != null && typeof value.toString != 'function') {\n try {\n result = !!(value + '');\n } catch (e) {}\n }\n return result;\n}\n\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\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\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\n/** Used for built-in method references. */\nvar arrayProto = Array.prototype,\n funcProto = Function.prototype,\n objectProto = Object.prototype;\n\n/** Used to detect overreaching core-js shims. */\nvar coreJsData = root['__core-js_shared__'];\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/** 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/**\n * Used to resolve the\n * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar objectToString = objectProto.toString;\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/** Built-in value references. */\nvar Buffer = moduleExports ? root.Buffer : undefined,\n Symbol = root.Symbol,\n Uint8Array = root.Uint8Array,\n getPrototype = overArg(Object.getPrototypeOf, Object),\n objectCreate = Object.create,\n propertyIsEnumerable = objectProto.propertyIsEnumerable,\n splice = arrayProto.splice;\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeGetSymbols = Object.getOwnPropertySymbols,\n nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined,\n nativeKeys = overArg(Object.keys, Object);\n\n/* Built-in method references that are verified to be native. */\nvar DataView = getNative(root, 'DataView'),\n Map = getNative(root, 'Map'),\n Promise = getNative(root, 'Promise'),\n Set = getNative(root, 'Set'),\n WeakMap = getNative(root, 'WeakMap'),\n nativeCreate = getNative(Object, 'create');\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/** 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 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 ? entries.length : 0;\n\n this.clear();\n while (++index < length) {\n var entry = entries[index];\n this.set(entry[0], entry[1]);\n }\n}\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}\n\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 return this.has(key) && delete this.__data__[key];\n}\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\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\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 data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value;\n return this;\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\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 ? entries.length : 0;\n\n this.clear();\n while (++index < length) {\n var entry = entries[index];\n this.set(entry[0], entry[1]);\n }\n}\n\n/**\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}\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 return true;\n}\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\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\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 data.push([key, value]);\n } else {\n data[index][1] = value;\n }\n return this;\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\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 ? entries.length : 0;\n\n this.clear();\n while (++index < length) {\n var entry = entries[index];\n this.set(entry[0], entry[1]);\n }\n}\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.__data__ = {\n 'hash': new Hash,\n 'map': new (Map || ListCache),\n 'string': new Hash\n };\n}\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 return getMapData(this, key)['delete'](key);\n}\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\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\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 getMapData(this, key).set(key, value);\n return this;\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\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 this.__data__ = new ListCache(entries);\n}\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}\n\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 return this.__data__['delete'](key);\n}\n\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\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\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 cache = this.__data__;\n if (cache instanceof ListCache) {\n var pairs = cache.__data__;\n if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) {\n pairs.push([key, value]);\n return this;\n }\n cache = this.__data__ = new MapCache(pairs);\n }\n cache.set(key, value);\n return this;\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\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 // Safari 8.1 makes `arguments.callee` enumerable in strict mode.\n // Safari 9 makes `arguments.length` enumerable in strict mode.\n var result = (isArray(value) || isArguments(value))\n ? baseTimes(value.length, String)\n : [];\n\n var length = result.length,\n skipIndexes = !!length;\n\n for (var key in value) {\n if ((inherited || hasOwnProperty.call(value, key)) &&\n !(skipIndexes && (key == 'length' || isIndex(key, length)))) {\n result.push(key);\n }\n }\n return result;\n}\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 object[key] = value;\n }\n}\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\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\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} [isDeep] Specify a deep clone.\n * @param {boolean} [isFull] Specify a clone including 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, isDeep, isFull, customizer, key, object, stack) {\n var result;\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 if (isHostObject(value)) {\n return object ? value : {};\n }\n result = initCloneObject(isFunc ? {} : value);\n if (!isDeep) {\n return copySymbols(value, baseAssign(result, value));\n }\n } else {\n if (!cloneableTags[tag]) {\n return object ? value : {};\n }\n result = initCloneByTag(value, tag, baseClone, 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 (!isArr) {\n var props = isFull ? getAllKeys(value) : keys(value);\n }\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, isDeep, isFull, customizer, key, value, stack));\n });\n return result;\n}\n\n/**\n * The base implementation of `_.create` without support for assigning\n * properties to the created object.\n *\n * @private\n * @param {Object} prototype The object to inherit from.\n * @returns {Object} Returns the new object.\n */\nfunction baseCreate(proto) {\n return isObject(proto) ? objectCreate(proto) : {};\n}\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\n/**\n * The base implementation of `getTag`.\n *\n * @private\n * @param {*} value The value to query.\n * @returns {string} Returns the `toStringTag`.\n */\nfunction baseGetTag(value) {\n return objectToString.call(value);\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) || isHostObject(value)) ? reIsNative : reIsHostCtor;\n return pattern.test(toSource(value));\n}\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\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 result = new buffer.constructor(buffer.length);\n buffer.copy(result);\n return result;\n}\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\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\n/**\n * Creates a clone of `map`.\n *\n * @private\n * @param {Object} map The map to clone.\n * @param {Function} cloneFunc The function to clone values.\n * @param {boolean} [isDeep] Specify a deep clone.\n * @returns {Object} Returns the cloned map.\n */\nfunction cloneMap(map, isDeep, cloneFunc) {\n var array = isDeep ? cloneFunc(mapToArray(map), true) : mapToArray(map);\n return arrayReduce(array, addMapEntry, new map.constructor);\n}\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\n/**\n * Creates a clone of `set`.\n *\n * @private\n * @param {Object} set The set to clone.\n * @param {Function} cloneFunc The function to clone values.\n * @param {boolean} [isDeep] Specify a deep clone.\n * @returns {Object} Returns the cloned set.\n */\nfunction cloneSet(set, isDeep, cloneFunc) {\n var array = isDeep ? cloneFunc(setToArray(set), true) : setToArray(set);\n return arrayReduce(array, addSetEntry, new set.constructor);\n}\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\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\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\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 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 assignValue(object, key, newValue === undefined ? source[key] : newValue);\n }\n return object;\n}\n\n/**\n * Copies own symbol properties 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\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\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\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\n/**\n * Creates an array of the own enumerable symbol properties 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 ? overArg(nativeGetSymbols, Object) : stubArray;\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,\n// for data views in Edge < 14, and promises in Node.js.\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 = objectToString.call(value),\n Ctor = result == objectTag ? value.constructor : undefined,\n ctorString = Ctor ? toSource(Ctor) : undefined;\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\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 = 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\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\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`, `Number`, `RegExp`, 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 {Function} cloneFunc The function to clone values.\n * @param {boolean} [isDeep] Specify a deep clone.\n * @returns {Object} Returns the initialized clone.\n */\nfunction initCloneByTag(object, tag, cloneFunc, 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 cloneMap(object, isDeep, cloneFunc);\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 cloneSet(object, isDeep, cloneFunc);\n\n case symbolTag:\n return cloneSymbol(object);\n }\n}\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 length = length == null ? MAX_SAFE_INTEGER : length;\n return !!length &&\n (typeof value == 'number' || reIsUint.test(value)) &&\n (value > -1 && value % 1 == 0 && value < length);\n}\n\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\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\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\n/**\n * Converts `func` to its source code.\n *\n * @private\n * @param {Function} func The function to process.\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\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, true, true);\n}\n\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\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 */\nfunction isArguments(value) {\n // Safari 8.1 makes `arguments.callee` enumerable in strict mode.\n return isArrayLikeObject(value) && hasOwnProperty.call(value, 'callee') &&\n (!propertyIsEnumerable.call(value, 'callee') || objectToString.call(value) == argsTag);\n}\n\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\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\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\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\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 // The use of `Object#toString` avoids issues with the `typeof` operator\n // in Safari 8-9 which returns 'object' for typed array and other constructors.\n var tag = isObject(value) ? objectToString.call(value) : '';\n return tag == funcTag || tag == genTag;\n}\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\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 && (type == 'object' || type == 'function');\n}\n\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 && typeof value == 'object';\n}\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\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\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\nmodule.exports = cloneDeep;\n","/**\n * lodash (Custom Build) \n * Build: `lodash modularize exports=\"npm\" -o ./`\n * Copyright jQuery Foundation and other contributors \n * Released under MIT license \n * Based on Underscore.js 1.8.3 \n * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n */\n\n/** Used as the `TypeError` message for \"Functions\" methods. */\nvar FUNC_ERROR_TEXT = 'Expected a function';\n\n/** Used as references for various `Number` constants. */\nvar NAN = 0 / 0;\n\n/** `Object#toString` result references. */\nvar symbolTag = '[object Symbol]';\n\n/** Used to match leading and trailing whitespace. */\nvar reTrim = /^\\s+|\\s+$/g;\n\n/** Used to detect bad signed hexadecimal string values. */\nvar reIsBadHex = /^[-+]0x[0-9a-f]+$/i;\n\n/** Used to detect binary string values. */\nvar reIsBinary = /^0b[01]+$/i;\n\n/** Used to detect octal string values. */\nvar reIsOctal = /^0o[0-7]+$/i;\n\n/** Built-in method references without a dependency on `root`. */\nvar freeParseInt = parseInt;\n\n/** Detect free variable `global` from Node.js. */\nvar freeGlobal = typeof global == 'object' && global && global.Object === Object && global;\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\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 objectToString = objectProto.toString;\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeMax = Math.max,\n nativeMin = Math.min;\n\n/**\n * Gets the timestamp of the number of milliseconds that have elapsed since\n * the Unix epoch (1 January 1970 00:00:00 UTC).\n *\n * @static\n * @memberOf _\n * @since 2.4.0\n * @category Date\n * @returns {number} Returns the timestamp.\n * @example\n *\n * _.defer(function(stamp) {\n * console.log(_.now() - stamp);\n * }, _.now());\n * // => Logs the number of milliseconds it took for the deferred invocation.\n */\nvar now = function() {\n return root.Date.now();\n};\n\n/**\n * Creates a debounced function that delays invoking `func` until after `wait`\n * milliseconds have elapsed since the last time the debounced function was\n * invoked. The debounced function comes with a `cancel` method to cancel\n * delayed `func` invocations and a `flush` method to immediately invoke them.\n * Provide `options` to indicate whether `func` should be invoked on the\n * leading and/or trailing edge of the `wait` timeout. The `func` is invoked\n * with the last arguments provided to the debounced function. Subsequent\n * calls to the debounced function return the result of the last `func`\n * invocation.\n *\n * **Note:** If `leading` and `trailing` options are `true`, `func` is\n * invoked on the trailing edge of the timeout only if the debounced function\n * is invoked more than once during the `wait` timeout.\n *\n * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred\n * until to the next tick, similar to `setTimeout` with a timeout of `0`.\n *\n * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)\n * for details over the differences between `_.debounce` and `_.throttle`.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Function\n * @param {Function} func The function to debounce.\n * @param {number} [wait=0] The number of milliseconds to delay.\n * @param {Object} [options={}] The options object.\n * @param {boolean} [options.leading=false]\n * Specify invoking on the leading edge of the timeout.\n * @param {number} [options.maxWait]\n * The maximum time `func` is allowed to be delayed before it's invoked.\n * @param {boolean} [options.trailing=true]\n * Specify invoking on the trailing edge of the timeout.\n * @returns {Function} Returns the new debounced function.\n * @example\n *\n * // Avoid costly calculations while the window size is in flux.\n * jQuery(window).on('resize', _.debounce(calculateLayout, 150));\n *\n * // Invoke `sendMail` when clicked, debouncing subsequent calls.\n * jQuery(element).on('click', _.debounce(sendMail, 300, {\n * 'leading': true,\n * 'trailing': false\n * }));\n *\n * // Ensure `batchLog` is invoked once after 1 second of debounced calls.\n * var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 });\n * var source = new EventSource('/stream');\n * jQuery(source).on('message', debounced);\n *\n * // Cancel the trailing debounced invocation.\n * jQuery(window).on('popstate', debounced.cancel);\n */\nfunction debounce(func, wait, options) {\n var lastArgs,\n lastThis,\n maxWait,\n result,\n timerId,\n lastCallTime,\n lastInvokeTime = 0,\n leading = false,\n maxing = false,\n trailing = true;\n\n if (typeof func != 'function') {\n throw new TypeError(FUNC_ERROR_TEXT);\n }\n wait = toNumber(wait) || 0;\n if (isObject(options)) {\n leading = !!options.leading;\n maxing = 'maxWait' in options;\n maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait;\n trailing = 'trailing' in options ? !!options.trailing : trailing;\n }\n\n function invokeFunc(time) {\n var args = lastArgs,\n thisArg = lastThis;\n\n lastArgs = lastThis = undefined;\n lastInvokeTime = time;\n result = func.apply(thisArg, args);\n return result;\n }\n\n function leadingEdge(time) {\n // Reset any `maxWait` timer.\n lastInvokeTime = time;\n // Start the timer for the trailing edge.\n timerId = setTimeout(timerExpired, wait);\n // Invoke the leading edge.\n return leading ? invokeFunc(time) : result;\n }\n\n function remainingWait(time) {\n var timeSinceLastCall = time - lastCallTime,\n timeSinceLastInvoke = time - lastInvokeTime,\n result = wait - timeSinceLastCall;\n\n return maxing ? nativeMin(result, maxWait - timeSinceLastInvoke) : result;\n }\n\n function shouldInvoke(time) {\n var timeSinceLastCall = time - lastCallTime,\n timeSinceLastInvoke = time - lastInvokeTime;\n\n // Either this is the first call, activity has stopped and we're at the\n // trailing edge, the system time has gone backwards and we're treating\n // it as the trailing edge, or we've hit the `maxWait` limit.\n return (lastCallTime === undefined || (timeSinceLastCall >= wait) ||\n (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait));\n }\n\n function timerExpired() {\n var time = now();\n if (shouldInvoke(time)) {\n return trailingEdge(time);\n }\n // Restart the timer.\n timerId = setTimeout(timerExpired, remainingWait(time));\n }\n\n function trailingEdge(time) {\n timerId = undefined;\n\n // Only invoke if we have `lastArgs` which means `func` has been\n // debounced at least once.\n if (trailing && lastArgs) {\n return invokeFunc(time);\n }\n lastArgs = lastThis = undefined;\n return result;\n }\n\n function cancel() {\n if (timerId !== undefined) {\n clearTimeout(timerId);\n }\n lastInvokeTime = 0;\n lastArgs = lastCallTime = lastThis = timerId = undefined;\n }\n\n function flush() {\n return timerId === undefined ? result : trailingEdge(now());\n }\n\n function debounced() {\n var time = now(),\n isInvoking = shouldInvoke(time);\n\n lastArgs = arguments;\n lastThis = this;\n lastCallTime = time;\n\n if (isInvoking) {\n if (timerId === undefined) {\n return leadingEdge(lastCallTime);\n }\n if (maxing) {\n // Handle invocations in a tight loop.\n timerId = setTimeout(timerExpired, wait);\n return invokeFunc(lastCallTime);\n }\n }\n if (timerId === undefined) {\n timerId = setTimeout(timerExpired, wait);\n }\n return result;\n }\n debounced.cancel = cancel;\n debounced.flush = flush;\n return debounced;\n}\n\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 && (type == 'object' || type == 'function');\n}\n\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 && typeof value == 'object';\n}\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) && objectToString.call(value) == symbolTag);\n}\n\n/**\n * Converts `value` to a number.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to process.\n * @returns {number} Returns the number.\n * @example\n *\n * _.toNumber(3.2);\n * // => 3.2\n *\n * _.toNumber(Number.MIN_VALUE);\n * // => 5e-324\n *\n * _.toNumber(Infinity);\n * // => Infinity\n *\n * _.toNumber('3.2');\n * // => 3.2\n */\nfunction toNumber(value) {\n if (typeof value == 'number') {\n return value;\n }\n if (isSymbol(value)) {\n return NAN;\n }\n if (isObject(value)) {\n var other = typeof value.valueOf == 'function' ? value.valueOf() : value;\n value = isObject(other) ? (other + '') : other;\n }\n if (typeof value != 'string') {\n return value === 0 ? value : +value;\n }\n value = value.replace(reTrim, '');\n var isBinary = reIsBinary.test(value);\n return (isBinary || reIsOctal.test(value))\n ? freeParseInt(value.slice(2), isBinary ? 2 : 8)\n : (reIsBadHex.test(value) ? NAN : +value);\n}\n\nmodule.exports = debounce;\n","/**\n * Lodash (Custom Build) \n * Build: `lodash modularize exports=\"npm\" -o ./`\n * Copyright JS Foundation and other contributors \n * Released under MIT license \n * Based on Underscore.js 1.8.3 \n * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n */\n\n/** Used as the size to enable large array optimizations. */\nvar LARGE_ARRAY_SIZE = 200;\n\n/** Used to stand-in for `undefined` hash values. */\nvar HASH_UNDEFINED = '__lodash_hash_undefined__';\n\n/** Used to compose bitmasks for value comparisons. */\nvar COMPARE_PARTIAL_FLAG = 1,\n COMPARE_UNORDERED_FLAG = 2;\n\n/** Used as references for various `Number` constants. */\nvar MAX_SAFE_INTEGER = 9007199254740991;\n\n/** `Object#toString` result references. */\nvar argsTag = '[object Arguments]',\n arrayTag = '[object Array]',\n asyncTag = '[object AsyncFunction]',\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 nullTag = '[object Null]',\n objectTag = '[object Object]',\n promiseTag = '[object Promise]',\n proxyTag = '[object Proxy]',\n regexpTag = '[object RegExp]',\n setTag = '[object Set]',\n stringTag = '[object String]',\n symbolTag = '[object Symbol]',\n undefinedTag = '[object Undefined]',\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/**\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 to detect unsigned integer values. */\nvar reIsUint = /^(?:0|[1-9]\\d*)$/;\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/** Detect free variable `global` from Node.js. */\nvar freeGlobal = typeof global == 'object' && global && global.Object === Object && global;\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\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 return freeProcess && freeProcess.binding && freeProcess.binding('util');\n } catch (e) {}\n}());\n\n/* Node.js helper references. */\nvar nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray;\n\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\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\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\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\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\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\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\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\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\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\n/** Used for built-in method references. */\nvar arrayProto = Array.prototype,\n funcProto = Function.prototype,\n objectProto = Object.prototype;\n\n/** Used to detect overreaching core-js shims. */\nvar coreJsData = root['__core-js_shared__'];\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 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 * 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/** 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/** Built-in value references. */\nvar Buffer = moduleExports ? root.Buffer : undefined,\n Symbol = root.Symbol,\n Uint8Array = root.Uint8Array,\n propertyIsEnumerable = objectProto.propertyIsEnumerable,\n splice = arrayProto.splice,\n symToStringTag = Symbol ? Symbol.toStringTag : undefined;\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeGetSymbols = Object.getOwnPropertySymbols,\n nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined,\n nativeKeys = overArg(Object.keys, Object);\n\n/* Built-in method references that are verified to be native. */\nvar DataView = getNative(root, 'DataView'),\n Map = getNative(root, 'Map'),\n Promise = getNative(root, 'Promise'),\n Set = getNative(root, 'Set'),\n WeakMap = getNative(root, 'WeakMap'),\n nativeCreate = getNative(Object, 'create');\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/** 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 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/**\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\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\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\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\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\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\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/**\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\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\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\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\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\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\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/**\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\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\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\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\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\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\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/**\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\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 {number} Returns `true` if `value` is found, else `false`.\n */\nfunction setCacheHas(value) {\n return this.__data__.has(value);\n}\n\n// Add methods to `SetCache`.\nSetCache.prototype.add = SetCache.prototype.push = setCacheAdd;\nSetCache.prototype.has = setCacheHas;\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/**\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\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\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\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\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\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\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\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\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\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\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\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\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\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\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\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\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 // Assume cyclic values are equal.\n var stacked = stack.get(array);\n if (stacked && stack.get(other)) {\n return stacked == other;\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\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\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 // Assume cyclic values are equal.\n var stacked = stack.get(object);\n if (stacked && stack.get(other)) {\n return stacked == other;\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\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\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\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\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\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\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\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 length = length == null ? MAX_SAFE_INTEGER : length;\n return !!length &&\n (typeof value == 'number' || reIsUint.test(value)) &&\n (value > -1 && value % 1 == 0 && value < length);\n}\n\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\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\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\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\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\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\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\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\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\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\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\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\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\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\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\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\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\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\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\nmodule.exports = isEqual;\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).substr(2, 10);\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.substr(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.substr(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.substr(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 };\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 + '\\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\nSDPUtils.parseFmtp = function(line) {\n const parsed = {};\n let kv;\n const parts = line.substr(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.substr(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.substr(7, sp - 7), 10),\n };\n const colon = line.indexOf(':', sp);\n if (colon > -1) {\n parts.attribute = line.substr(sp + 1, colon - sp - 1);\n parts.value = line.substr(colon + 1);\n } else {\n parts.attribute = line.substr(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.substr(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.substr(6);\n }\n};\n\n// Parses a fingerprint line for DTLS-SRTP.\nSDPUtils.parseFingerprint = function(line) {\n const parts = line.substr(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.substr(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.substr(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.substr(12),\n password: pwd.substr(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 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: 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 // 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 += ' 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.substr(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].substr(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].substr(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].substr(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].substr(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].substr(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 .substr(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, 21);\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].substr(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].substr(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].substr(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.substr(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 try {\n WebSocketImplementation = require('ws');\n } catch (err) {\n throw new Error('You must install the \"ws\" package to use Strophe in nodejs.');\n }\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 try {\n DOMParserImplementation = require('@xmldom/xmldom').DOMParser;\n } catch (err) {\n throw new Error('You must install the \"@xmldom/xmldom\" package to use Strophe in nodejs.');\n }\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 = require('@xmldom/xmldom').DOMImplementation;\n\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 for information about changing priority and 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 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 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 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 * Implementation of atob() according to the HTML and Infra specs, except that\n * instead of throwing INVALID_CHARACTER_ERR we return null.\n */\n\n function atob$2(data) {\n if (arguments.length === 0) {\n throw new TypeError(\"1 argument required, but only 0 present.\");\n } // Web IDL requires DOMStrings to just be converted using ECMAScript\n // ToString, which in our case amounts to using a template literal.\n\n\n data = `${data}`; // \"Remove all ASCII whitespace from data.\"\n\n data = data.replace(/[ \\t\\n\\f\\r]/g, \"\"); // \"If data's length divides by 4 leaving no remainder, then: if data ends\n // with one or two U+003D (=) code points, then remove them from data.\"\n\n if (data.length % 4 === 0) {\n data = data.replace(/==?$/, \"\");\n } // \"If data's length divides by 4 leaving a remainder of 1, then return\n // failure.\"\n //\n // \"If data contains a code point that is not one of\n //\n // U+002B (+)\n // U+002F (/)\n // ASCII alphanumeric\n //\n // then return failure.\"\n\n\n if (data.length % 4 === 1 || /[^+/0-9A-Za-z]/.test(data)) {\n return null;\n } // \"Let output be an empty byte sequence.\"\n\n\n let output = \"\"; // \"Let buffer be an empty buffer that can have bits appended to it.\"\n //\n // We append bits via left-shift and or. accumulatedBits is used to track\n // when we've gotten to 24 bits.\n\n let buffer = 0;\n let accumulatedBits = 0; // \"Let position be a position variable for data, initially pointing at the\n // start of data.\"\n //\n // \"While position does not point past the end of data:\"\n\n for (let i = 0; i < data.length; i++) {\n // \"Find the code point pointed to by position in the second column of\n // Table 1: The Base 64 Alphabet of RFC 4648. Let n be the number given in\n // the first cell of the same row.\n //\n // \"Append to buffer the six bits corresponding to n, most significant bit\n // first.\"\n //\n // atobLookup() implements the table from RFC 4648.\n buffer <<= 6;\n buffer |= atobLookup(data[i]);\n accumulatedBits += 6; // \"If buffer has accumulated 24 bits, interpret them as three 8-bit\n // big-endian numbers. Append three bytes with values equal to those\n // numbers to output, in the same order, and then empty buffer.\"\n\n if (accumulatedBits === 24) {\n output += String.fromCharCode((buffer & 0xff0000) >> 16);\n output += String.fromCharCode((buffer & 0xff00) >> 8);\n output += String.fromCharCode(buffer & 0xff);\n buffer = accumulatedBits = 0;\n } // \"Advance position by 1.\"\n\n } // \"If buffer is not empty, it contains either 12 or 18 bits. If it contains\n // 12 bits, then discard the last four and interpret the remaining eight as\n // an 8-bit big-endian number. If it contains 18 bits, then discard the last\n // two and interpret the remaining 16 as two 8-bit big-endian numbers. Append\n // the one or two bytes with values equal to those one or two numbers to\n // output, in the same order.\"\n\n\n if (accumulatedBits === 12) {\n buffer >>= 4;\n output += String.fromCharCode(buffer);\n } else if (accumulatedBits === 18) {\n buffer >>= 2;\n output += String.fromCharCode((buffer & 0xff00) >> 8);\n output += String.fromCharCode(buffer & 0xff);\n } // \"Return output.\"\n\n\n return output;\n }\n /**\n * A lookup table for atob(), which converts an ASCII character to the\n * corresponding six-bit number.\n */\n\n\n const keystr$1 = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\n function atobLookup(chr) {\n const index = keystr$1.indexOf(chr); // Throw exception if character is not in the lookup string; should not be hit in tests\n\n return index < 0 ? undefined : index;\n }\n\n var atob_1 = atob$2;\n\n /**\n * btoa() as defined by the HTML and Infra specs, which mostly just references\n * RFC 4648.\n */\n\n function btoa$2(s) {\n if (arguments.length === 0) {\n throw new TypeError(\"1 argument required, but only 0 present.\");\n }\n\n let i; // String conversion as required by Web IDL.\n\n s = `${s}`; // \"The btoa() method must throw an \"InvalidCharacterError\" DOMException if\n // data contains any character whose code point is greater than U+00FF.\"\n\n for (i = 0; i < s.length; i++) {\n if (s.charCodeAt(i) > 255) {\n return null;\n }\n }\n\n let out = \"\";\n\n for (i = 0; i < s.length; i += 3) {\n const groupsOfSix = [undefined, undefined, undefined, undefined];\n groupsOfSix[0] = s.charCodeAt(i) >> 2;\n groupsOfSix[1] = (s.charCodeAt(i) & 0x03) << 4;\n\n if (s.length > i + 1) {\n groupsOfSix[1] |= s.charCodeAt(i + 1) >> 4;\n groupsOfSix[2] = (s.charCodeAt(i + 1) & 0x0f) << 2;\n }\n\n if (s.length > i + 2) {\n groupsOfSix[2] |= s.charCodeAt(i + 2) >> 6;\n groupsOfSix[3] = s.charCodeAt(i + 2) & 0x3f;\n }\n\n for (let j = 0; j < groupsOfSix.length; j++) {\n if (typeof groupsOfSix[j] === \"undefined\") {\n out += \"=\";\n } else {\n out += btoaLookup(groupsOfSix[j]);\n }\n }\n }\n\n return out;\n }\n /**\n * Lookup table for btoa(), which converts a six-bit number into the\n * corresponding ASCII character.\n */\n\n\n const keystr = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\n function btoaLookup(index) {\n if (index >= 0 && index < 64) {\n return keystr[index];\n } // Throw INVALID_CHARACTER_ERR exception here -- won't be hit in the tests.\n\n\n return undefined;\n }\n\n var btoa_1 = btoa$2;\n\n const atob$1 = atob_1;\n\n const btoa$1 = btoa_1;\n\n var abab = {\n atob: atob$1,\n btoa: btoa$1\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 element as the root.\n *\n * Parameters:\n * (Object) attrs - The 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 element as the root.\n *\n * Parameters:\n * (Object) attrs - The 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 element as the root.\n *\n * Parameters:\n * (Object) attrs - The 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, \"&\");\n text = text.replace(//g, \">\");\n text = text.replace(/'/g, \"'\");\n text = text.replace(/\"/g, \""\");\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(/\\&/g, \"&\");\n text = text.replace(/</g, \"<\");\n text = text.replace(/>/g, \">\");\n text = text.replace(/'/g, \"'\");\n text = text.replace(/"/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, \"\\\\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 += \"\";\n }\n }\n\n result += \"\";\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 * > \n * > \n * > \n * > \n * > \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 elements.\n *\n * All 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 * tag for WebSocket-Connoctions will be passed as selfclosing here.\n *\n * BOSH-Connections will have all stanzas wrapped in a tag. See\n * 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 * tag for WebSocket-Connoctions will be passed as selfclosing here.\n *\n * BOSH-Connections will have all stanzas wrapped in a tag. See\n * 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(abab.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 = abab.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(abab.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 \n * for legacy authentication. It builds an authentication 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 = abab.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 * 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 wrapper for BOSH.\n *\n * Returns:\n * A Strophe.Builder with a 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 tag when\n * passed to or .\n * To strip this tag, User code can set to \"body\":\n *\n * > Strophe.Bosh.prototype.strip = \"body\";\n *\n * This will enable stripping of the body tag in both\n * and .\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 start tag for WebSockets\n *\n * Returns:\n * A Strophe.Builder with a 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 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 tag.\n */\n\n\n _handleStreamStart(message) {\n let error = false; // Check for errors in the tag\n\n const ns = message.getAttribute(\"xmlns\");\n\n if (typeof ns !== \"string\") {\n error = \"Missing xmlns in \";\n } else if (ns !== Strophe.NS.FRAMING) {\n error = \"Wrong xmlns in : \" + ns;\n }\n\n const ver = message.getAttribute(\"version\");\n\n if (typeof ver !== \"string\") {\n error = \"Missing version in \";\n } else if (ver !== \"1.0\") {\n error = \"Wrong version in : \" + 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(\"\\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(\"\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 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 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 \"\" + stanza + '';\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 * \n *\n * The first stanza will always fail to be parsed.\n *\n * Additionally, the seconds stanza will always be 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 = '';\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(\" 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","import { $iq, Strophe } from 'strophe.js';\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 for (var i=0; i 0;\n\n\t\treturn this._originalOnStreamFeaturesAfterSASL.apply(this._c, arguments);\n\t},\n\n\tstatusChanged: function (status) {\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) {\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) {\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');\n\n\t\tthis._c.resume();\n\n\t\treturn true;\n\t},\n\n\t_handleResumeFailed: function(elem) {\n\t\tconst error = elem && (\n\t\t\t(elem.firstElementChild && elem.firstElementChild.tagName)\n\t\t\t|| (elem.firstChild && elem.firstChild.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) {\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) {\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, lastKnownHandledCount) {\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() {\n\t\tthis._answerProcessedStanzas();\n\n\t\treturn true;\n\t},\n\n\t_handleServerAck: function(elem){\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() {\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) {\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() {\n\t\tif (this._isStreamManagementEnabled) {\n\t\t\tthis._clientProcessedStanzasCounter++;\n\t\t}\n\t},\n\n\t_throwError: function(msg) {\n\t\tStrophe.error(msg);\n\t\tthrow new Error(msg);\n\t}\n\n});\n","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\n/**\n * Convert array of 16 byte values to UUID string format of the form:\n * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX\n */\nconst byteToHex = [];\n\nfor (let i = 0; i < 256; ++i) {\n byteToHex.push((i + 0x100).toString(16).substr(1));\n}\n\nfunction bytesToUuid(buf, offset) {\n const i = offset || 0;\n const bth = byteToHex; // 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\n return (bth[buf[i + 0]] + bth[buf[i + 1]] + bth[buf[i + 2]] + bth[buf[i + 3]] + '-' + bth[buf[i + 4]] + bth[buf[i + 5]] + '-' + bth[buf[i + 6]] + bth[buf[i + 7]] + '-' + bth[buf[i + 8]] + bth[buf[i + 9]] + '-' + bth[buf[i + 10]] + bth[buf[i + 11]] + bth[buf[i + 12]] + bth[buf[i + 13]] + bth[buf[i + 14]] + bth[buf[i + 15]]).toLowerCase();\n}\n\nvar _default = bytesToUuid;\nexports.default = _default;","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nObject.defineProperty(exports, \"v1\", {\n enumerable: true,\n get: function () {\n return _v.default;\n }\n});\nObject.defineProperty(exports, \"v3\", {\n enumerable: true,\n get: function () {\n return _v2.default;\n }\n});\nObject.defineProperty(exports, \"v4\", {\n enumerable: true,\n get: function () {\n return _v3.default;\n }\n});\nObject.defineProperty(exports, \"v5\", {\n enumerable: true,\n get: function () {\n return _v4.default;\n }\n});\n\nvar _v = _interopRequireDefault(require(\"./v1.js\"));\n\nvar _v2 = _interopRequireDefault(require(\"./v3.js\"));\n\nvar _v3 = _interopRequireDefault(require(\"./v4.js\"));\n\nvar _v4 = _interopRequireDefault(require(\"./v5.js\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\n/*\n * Browser-compatible JavaScript MD5\n *\n * Modification of JavaScript MD5\n * https://github.com/blueimp/JavaScript-MD5\n *\n * Copyright 2011, Sebastian Tschan\n * https://blueimp.net\n *\n * Licensed under the MIT license:\n * https://opensource.org/licenses/MIT\n *\n * Based on\n * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message\n * Digest Algorithm, as defined in RFC 1321.\n * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009\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 */\nfunction md5(bytes) {\n if (typeof bytes === 'string') {\n const msg = unescape(encodeURIComponent(bytes)); // UTF8 escape\n\n bytes = new Uint8Array(msg.length);\n\n for (let i = 0; i < msg.length; ++i) {\n bytes[i] = msg.charCodeAt(i);\n }\n }\n\n return md5ToHexEncodedArray(wordsToMd5(bytesToWords(bytes), bytes.length * 8));\n}\n/*\n * Convert an array of little-endian words to an array of bytes\n */\n\n\nfunction md5ToHexEncodedArray(input) {\n const output = [];\n const length32 = input.length * 32;\n const hexTab = '0123456789abcdef';\n\n for (let i = 0; i < length32; i += 8) {\n const x = input[i >> 5] >>> i % 32 & 0xff;\n const hex = parseInt(hexTab.charAt(x >>> 4 & 0x0f) + hexTab.charAt(x & 0x0f), 16);\n output.push(hex);\n }\n\n return output;\n}\n/**\n * Calculate output length with padding and bit length\n */\n\n\nfunction getOutputLength(inputLength8) {\n return (inputLength8 + 64 >>> 9 << 4) + 14 + 1;\n}\n/*\n * Calculate the MD5 of an array of little-endian words, and a bit length.\n */\n\n\nfunction wordsToMd5(x, len) {\n /* append padding */\n x[len >> 5] |= 0x80 << len % 32;\n x[getOutputLength(len) - 1] = len;\n let a = 1732584193;\n let b = -271733879;\n let c = -1732584194;\n let d = 271733878;\n\n for (let i = 0; i < x.length; i += 16) {\n const olda = a;\n const oldb = b;\n const oldc = c;\n const oldd = d;\n a = md5ff(a, b, c, d, x[i], 7, -680876936);\n d = md5ff(d, a, b, c, x[i + 1], 12, -389564586);\n c = md5ff(c, d, a, b, x[i + 2], 17, 606105819);\n b = md5ff(b, c, d, a, x[i + 3], 22, -1044525330);\n a = md5ff(a, b, c, d, x[i + 4], 7, -176418897);\n d = md5ff(d, a, b, c, x[i + 5], 12, 1200080426);\n c = md5ff(c, d, a, b, x[i + 6], 17, -1473231341);\n b = md5ff(b, c, d, a, x[i + 7], 22, -45705983);\n a = md5ff(a, b, c, d, x[i + 8], 7, 1770035416);\n d = md5ff(d, a, b, c, x[i + 9], 12, -1958414417);\n c = md5ff(c, d, a, b, x[i + 10], 17, -42063);\n b = md5ff(b, c, d, a, x[i + 11], 22, -1990404162);\n a = md5ff(a, b, c, d, x[i + 12], 7, 1804603682);\n d = md5ff(d, a, b, c, x[i + 13], 12, -40341101);\n c = md5ff(c, d, a, b, x[i + 14], 17, -1502002290);\n b = md5ff(b, c, d, a, x[i + 15], 22, 1236535329);\n a = md5gg(a, b, c, d, x[i + 1], 5, -165796510);\n d = md5gg(d, a, b, c, x[i + 6], 9, -1069501632);\n c = md5gg(c, d, a, b, x[i + 11], 14, 643717713);\n b = md5gg(b, c, d, a, x[i], 20, -373897302);\n a = md5gg(a, b, c, d, x[i + 5], 5, -701558691);\n d = md5gg(d, a, b, c, x[i + 10], 9, 38016083);\n c = md5gg(c, d, a, b, x[i + 15], 14, -660478335);\n b = md5gg(b, c, d, a, x[i + 4], 20, -405537848);\n a = md5gg(a, b, c, d, x[i + 9], 5, 568446438);\n d = md5gg(d, a, b, c, x[i + 14], 9, -1019803690);\n c = md5gg(c, d, a, b, x[i + 3], 14, -187363961);\n b = md5gg(b, c, d, a, x[i + 8], 20, 1163531501);\n a = md5gg(a, b, c, d, x[i + 13], 5, -1444681467);\n d = md5gg(d, a, b, c, x[i + 2], 9, -51403784);\n c = md5gg(c, d, a, b, x[i + 7], 14, 1735328473);\n b = md5gg(b, c, d, a, x[i + 12], 20, -1926607734);\n a = md5hh(a, b, c, d, x[i + 5], 4, -378558);\n d = md5hh(d, a, b, c, x[i + 8], 11, -2022574463);\n c = md5hh(c, d, a, b, x[i + 11], 16, 1839030562);\n b = md5hh(b, c, d, a, x[i + 14], 23, -35309556);\n a = md5hh(a, b, c, d, x[i + 1], 4, -1530992060);\n d = md5hh(d, a, b, c, x[i + 4], 11, 1272893353);\n c = md5hh(c, d, a, b, x[i + 7], 16, -155497632);\n b = md5hh(b, c, d, a, x[i + 10], 23, -1094730640);\n a = md5hh(a, b, c, d, x[i + 13], 4, 681279174);\n d = md5hh(d, a, b, c, x[i], 11, -358537222);\n c = md5hh(c, d, a, b, x[i + 3], 16, -722521979);\n b = md5hh(b, c, d, a, x[i + 6], 23, 76029189);\n a = md5hh(a, b, c, d, x[i + 9], 4, -640364487);\n d = md5hh(d, a, b, c, x[i + 12], 11, -421815835);\n c = md5hh(c, d, a, b, x[i + 15], 16, 530742520);\n b = md5hh(b, c, d, a, x[i + 2], 23, -995338651);\n a = md5ii(a, b, c, d, x[i], 6, -198630844);\n d = md5ii(d, a, b, c, x[i + 7], 10, 1126891415);\n c = md5ii(c, d, a, b, x[i + 14], 15, -1416354905);\n b = md5ii(b, c, d, a, x[i + 5], 21, -57434055);\n a = md5ii(a, b, c, d, x[i + 12], 6, 1700485571);\n d = md5ii(d, a, b, c, x[i + 3], 10, -1894986606);\n c = md5ii(c, d, a, b, x[i + 10], 15, -1051523);\n b = md5ii(b, c, d, a, x[i + 1], 21, -2054922799);\n a = md5ii(a, b, c, d, x[i + 8], 6, 1873313359);\n d = md5ii(d, a, b, c, x[i + 15], 10, -30611744);\n c = md5ii(c, d, a, b, x[i + 6], 15, -1560198380);\n b = md5ii(b, c, d, a, x[i + 13], 21, 1309151649);\n a = md5ii(a, b, c, d, x[i + 4], 6, -145523070);\n d = md5ii(d, a, b, c, x[i + 11], 10, -1120210379);\n c = md5ii(c, d, a, b, x[i + 2], 15, 718787259);\n b = md5ii(b, c, d, a, x[i + 9], 21, -343485551);\n a = safeAdd(a, olda);\n b = safeAdd(b, oldb);\n c = safeAdd(c, oldc);\n d = safeAdd(d, oldd);\n }\n\n return [a, b, c, d];\n}\n/*\n * Convert an array bytes to an array of little-endian words\n * Characters >255 have their high-byte silently ignored.\n */\n\n\nfunction bytesToWords(input) {\n if (input.length === 0) {\n return [];\n }\n\n const length8 = input.length * 8;\n const output = new Uint32Array(getOutputLength(length8));\n\n for (let i = 0; i < length8; i += 8) {\n output[i >> 5] |= (input[i / 8] & 0xff) << i % 32;\n }\n\n return output;\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\nfunction safeAdd(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\nfunction bitRotateLeft(num, cnt) {\n return num << cnt | num >>> 32 - cnt;\n}\n/*\n * These functions implement the four basic operations the algorithm uses.\n */\n\n\nfunction md5cmn(q, a, b, x, s, t) {\n return safeAdd(bitRotateLeft(safeAdd(safeAdd(a, q), safeAdd(x, t)), s), b);\n}\n\nfunction md5ff(a, b, c, d, x, s, t) {\n return md5cmn(b & c | ~b & d, a, b, x, s, t);\n}\n\nfunction md5gg(a, b, c, d, x, s, t) {\n return md5cmn(b & d | c & ~d, a, b, x, s, t);\n}\n\nfunction md5hh(a, b, c, d, x, s, t) {\n return md5cmn(b ^ c ^ d, a, b, x, s, t);\n}\n\nfunction md5ii(a, b, c, d, x, s, t) {\n return md5cmn(c ^ (b | ~d), a, b, x, s, t);\n}\n\nvar _default = md5;\nexports.default = _default;","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = rng;\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()).\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.\nconst getRandomValues = typeof crypto !== 'undefined' && crypto.getRandomValues && crypto.getRandomValues.bind(crypto) || typeof msCrypto !== 'undefined' && typeof msCrypto.getRandomValues === 'function' && msCrypto.getRandomValues.bind(msCrypto);\nconst rnds8 = new Uint8Array(16);\n\nfunction rng() {\n if (!getRandomValues) {\n throw new Error('crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported');\n }\n\n return getRandomValues(rnds8);\n}","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\n// Adapted from Chris Veness' SHA1 code at\n// http://www.movable-type.co.uk/scripts/sha1.html\nfunction f(s, x, y, z) {\n switch (s) {\n case 0:\n return x & y ^ ~x & z;\n\n case 1:\n return x ^ y ^ z;\n\n case 2:\n return x & y ^ x & z ^ y & z;\n\n case 3:\n return x ^ y ^ z;\n }\n}\n\nfunction ROTL(x, n) {\n return x << n | x >>> 32 - n;\n}\n\nfunction sha1(bytes) {\n const K = [0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6];\n const H = [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0];\n\n if (typeof bytes === 'string') {\n const msg = unescape(encodeURIComponent(bytes)); // UTF8 escape\n\n bytes = [];\n\n for (let i = 0; i < msg.length; ++i) {\n bytes.push(msg.charCodeAt(i));\n }\n }\n\n bytes.push(0x80);\n const l = bytes.length / 4 + 2;\n const N = Math.ceil(l / 16);\n const M = new Array(N);\n\n for (let i = 0; i < N; ++i) {\n const arr = new Uint32Array(16);\n\n for (let j = 0; j < 16; ++j) {\n arr[j] = bytes[i * 64 + j * 4] << 24 | bytes[i * 64 + j * 4 + 1] << 16 | bytes[i * 64 + j * 4 + 2] << 8 | bytes[i * 64 + j * 4 + 3];\n }\n\n M[i] = arr;\n }\n\n M[N - 1][14] = (bytes.length - 1) * 8 / Math.pow(2, 32);\n M[N - 1][14] = Math.floor(M[N - 1][14]);\n M[N - 1][15] = (bytes.length - 1) * 8 & 0xffffffff;\n\n for (let i = 0; i < N; ++i) {\n const W = new Uint32Array(80);\n\n for (let t = 0; t < 16; ++t) {\n W[t] = M[i][t];\n }\n\n for (let t = 16; t < 80; ++t) {\n W[t] = ROTL(W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16], 1);\n }\n\n let a = H[0];\n let b = H[1];\n let c = H[2];\n let d = H[3];\n let e = H[4];\n\n for (let t = 0; t < 80; ++t) {\n const s = Math.floor(t / 20);\n const T = ROTL(a, 5) + f(s, b, c, d) + e + K[s] + W[t] >>> 0;\n e = d;\n d = c;\n c = ROTL(b, 30) >>> 0;\n b = a;\n a = T;\n }\n\n H[0] = H[0] + a >>> 0;\n H[1] = H[1] + b >>> 0;\n H[2] = H[2] + c >>> 0;\n H[3] = H[3] + d >>> 0;\n H[4] = H[4] + e >>> 0;\n }\n\n return [H[0] >> 24 & 0xff, H[0] >> 16 & 0xff, H[0] >> 8 & 0xff, H[0] & 0xff, H[1] >> 24 & 0xff, H[1] >> 16 & 0xff, H[1] >> 8 & 0xff, H[1] & 0xff, H[2] >> 24 & 0xff, H[2] >> 16 & 0xff, H[2] >> 8 & 0xff, H[2] & 0xff, H[3] >> 24 & 0xff, H[3] >> 16 & 0xff, H[3] >> 8 & 0xff, H[3] & 0xff, H[4] >> 24 & 0xff, H[4] >> 16 & 0xff, H[4] >> 8 & 0xff, H[4] & 0xff];\n}\n\nvar _default = sha1;\nexports.default = _default;","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\nvar _rng = _interopRequireDefault(require(\"./rng.js\"));\n\nvar _bytesToUuid = _interopRequireDefault(require(\"./bytesToUuid.js\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n// **`v1()` - Generate time-based UUID**\n//\n// Inspired by https://github.com/LiosK/UUID.js\n// and http://docs.python.org/library/uuid.html\nlet _nodeId;\n\nlet _clockseq; // Previous uuid creation time\n\n\nlet _lastMSecs = 0;\nlet _lastNSecs = 0; // See https://github.com/uuidjs/uuid for API details\n\nfunction v1(options, buf, offset) {\n let i = buf && offset || 0;\n const b = buf || [];\n options = options || {};\n let node = options.node || _nodeId;\n let clockseq = options.clockseq !== undefined ? options.clockseq : _clockseq; // node and clockseq need to be initialized to random values if they're not\n // specified. We do this lazily to minimize issues related to insufficient\n // system entropy. See #189\n\n if (node == null || clockseq == null) {\n const seedBytes = options.random || (options.rng || _rng.default)();\n\n if (node == null) {\n // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1)\n node = _nodeId = [seedBytes[0] | 0x01, seedBytes[1], seedBytes[2], seedBytes[3], seedBytes[4], seedBytes[5]];\n }\n\n if (clockseq == null) {\n // Per 4.2.2, randomize (14 bit) clockseq\n clockseq = _clockseq = (seedBytes[6] << 8 | seedBytes[7]) & 0x3fff;\n }\n } // UUID timestamps are 100 nano-second units since the Gregorian epoch,\n // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so\n // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs'\n // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00.\n\n\n let msecs = options.msecs !== undefined ? options.msecs : Date.now(); // Per 4.2.1.2, use count of uuid's generated during the current clock\n // cycle to simulate higher resolution clock\n\n let nsecs = options.nsecs !== undefined ? options.nsecs : _lastNSecs + 1; // Time since last uuid creation (in msecs)\n\n const dt = msecs - _lastMSecs + (nsecs - _lastNSecs) / 10000; // Per 4.2.1.2, Bump clockseq on clock regression\n\n if (dt < 0 && options.clockseq === undefined) {\n clockseq = clockseq + 1 & 0x3fff;\n } // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new\n // time interval\n\n\n if ((dt < 0 || msecs > _lastMSecs) && options.nsecs === undefined) {\n nsecs = 0;\n } // Per 4.2.1.2 Throw error if too many uuids are requested\n\n\n if (nsecs >= 10000) {\n throw new Error(\"uuid.v1(): Can't create more than 10M uuids/sec\");\n }\n\n _lastMSecs = msecs;\n _lastNSecs = nsecs;\n _clockseq = clockseq; // Per 4.1.4 - Convert from unix epoch to Gregorian epoch\n\n msecs += 12219292800000; // `time_low`\n\n const tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000;\n b[i++] = tl >>> 24 & 0xff;\n b[i++] = tl >>> 16 & 0xff;\n b[i++] = tl >>> 8 & 0xff;\n b[i++] = tl & 0xff; // `time_mid`\n\n const tmh = msecs / 0x100000000 * 10000 & 0xfffffff;\n b[i++] = tmh >>> 8 & 0xff;\n b[i++] = tmh & 0xff; // `time_high_and_version`\n\n b[i++] = tmh >>> 24 & 0xf | 0x10; // include version\n\n b[i++] = tmh >>> 16 & 0xff; // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant)\n\n b[i++] = clockseq >>> 8 | 0x80; // `clock_seq_low`\n\n b[i++] = clockseq & 0xff; // `node`\n\n for (let n = 0; n < 6; ++n) {\n b[i + n] = node[n];\n }\n\n return buf || (0, _bytesToUuid.default)(b);\n}\n\nvar _default = v1;\nexports.default = _default;","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\nvar _v = _interopRequireDefault(require(\"./v35.js\"));\n\nvar _md = _interopRequireDefault(require(\"./md5.js\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nconst v3 = (0, _v.default)('v3', 0x30, _md.default);\nvar _default = v3;\nexports.default = _default;","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = _default;\nexports.URL = exports.DNS = void 0;\n\nvar _bytesToUuid = _interopRequireDefault(require(\"./bytesToUuid.js\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction uuidToBytes(uuid) {\n // Note: We assume we're being passed a valid uuid string\n const bytes = [];\n uuid.replace(/[a-fA-F0-9]{2}/g, function (hex) {\n bytes.push(parseInt(hex, 16));\n });\n return bytes;\n}\n\nfunction stringToBytes(str) {\n str = unescape(encodeURIComponent(str)); // UTF8 escape\n\n const bytes = [];\n\n for (let i = 0; i < str.length; ++i) {\n bytes.push(str.charCodeAt(i));\n }\n\n return bytes;\n}\n\nconst DNS = '6ba7b810-9dad-11d1-80b4-00c04fd430c8';\nexports.DNS = DNS;\nconst URL = '6ba7b811-9dad-11d1-80b4-00c04fd430c8';\nexports.URL = URL;\n\nfunction _default(name, version, hashfunc) {\n function generateUUID(value, namespace, buf, offset) {\n const off = buf && offset || 0;\n if (typeof value === 'string') value = stringToBytes(value);\n if (typeof namespace === 'string') namespace = uuidToBytes(namespace);\n\n if (!Array.isArray(value)) {\n throw TypeError('value must be an array of bytes');\n }\n\n if (!Array.isArray(namespace) || namespace.length !== 16) {\n throw TypeError('namespace must be uuid string or an Array of 16 byte values');\n } // Per 4.3\n\n\n const bytes = hashfunc(namespace.concat(value));\n bytes[6] = bytes[6] & 0x0f | version;\n bytes[8] = bytes[8] & 0x3f | 0x80;\n\n if (buf) {\n for (let idx = 0; idx < 16; ++idx) {\n buf[off + idx] = bytes[idx];\n }\n }\n\n return buf || (0, _bytesToUuid.default)(bytes);\n } // Function#name is not settable on some platforms (#270)\n\n\n try {\n generateUUID.name = name; // eslint-disable-next-line no-empty\n } catch (err) {} // For CommonJS default export support\n\n\n generateUUID.DNS = DNS;\n generateUUID.URL = URL;\n return generateUUID;\n}","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\nvar _rng = _interopRequireDefault(require(\"./rng.js\"));\n\nvar _bytesToUuid = _interopRequireDefault(require(\"./bytesToUuid.js\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction v4(options, buf, offset) {\n if (typeof options === 'string') {\n buf = options === 'binary' ? new Uint8Array(16) : null;\n options = null;\n }\n\n options = options || {};\n\n const rnds = options.random || (options.rng || _rng.default)(); // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`\n\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 const start = offset || 0;\n\n for (let i = 0; i < 16; ++i) {\n buf[start + i] = rnds[i];\n }\n\n return buf;\n }\n\n return (0, _bytesToUuid.default)(rnds);\n}\n\nvar _default = v4;\nexports.default = _default;","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\nvar _v = _interopRequireDefault(require(\"./v35.js\"));\n\nvar _sha = _interopRequireDefault(require(\"./sha1.js\"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nconst v5 = (0, _v.default)('v5', 0x50, _sha.default);\nvar _default = v5;\nexports.default = _default;","export enum RTCEvents {\n /**\n * Indicates error while create answer call.\n */\n CREATE_ANSWER_FAILED = 'rtc.create_answer_failed',\n\n /**\n * Indicates error while create offer call.\n */\n CREATE_OFFER_FAILED = 'rtc.create_offer_failed',\n DATA_CHANNEL_OPEN = 'rtc.data_channel_open',\n DATA_CHANNEL_CLOSED = 'rtc.data_channel_closed',\n ENDPOINT_CONN_STATUS_CHANGED = 'rtc.endpoint_conn_status_changed',\n DOMINANT_SPEAKER_CHANGED = 'rtc.dominant_speaker_changed',\n FORWARDED_SOURCES_CHANGED = 'rtc.forwarded_sources_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 SENDER_VIDEO_CONSTRAINTS_CHANGED = 'rtc.sender_video_constraints_changed',\n\n /**\n * Event emitted when {@link RTC.setLastN} method is called to update with\n * 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 * Event emitted when ssrc for a local track is extracted and stored\n * in {@link TraceablePeerConnection}.\n * @param {JitsiLocalTrack} track which ssrc was updated\n * @param {string} ssrc that was stored\n */\n LOCAL_TRACK_SSRC_UPDATED = 'rtc.local_track_ssrc_updated',\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 TRACK_ATTACHED = 'rtc.track_attached',\n\n /**\n * Event fired when we remote track is added to the conference.\n * 1st event argument is the added JitsiRemoteTrack 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 * Indicates error while set local description.\n */\n SET_LOCAL_DESCRIPTION_FAILED = 'rtc.set_local_description_failed',\n\n /**\n * Indicates error while set remote description.\n */\n SET_REMOTE_DESCRIPTION_FAILED = 'rtc.set_remote_description_failed',\n AUDIO_OUTPUT_DEVICE_CHANGED = 'rtc.audio_output_device_changed',\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 DEVICE_LIST_AVAILABLE = 'rtc.device_list_available',\n\n /**\n * Indicates that a message from another participant is received on\n * 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 * 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 TraceablePeerConnection 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 * 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 TraceablePeerConnection which\n * 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 * Designates an event indicating that some received video SSRCs will now map to\n * new remote sources.\n */\n VIDEO_SSRCS_REMAPPED = 'rtc.video_ssrcs_remapped',\n\n /**\n * Designates an event indicating that some received audio SSRCs will now map to\n * new remote sources.\n */\n AUDIO_SSRCS_REMAPPED = 'rtc.audio_ssrcs_remapped'\n}\n\nexport const CREATE_ANSWER_FAILED = RTCEvents.CREATE_ANSWER_FAILED;\nexport const CREATE_OFFER_FAILED = RTCEvents.CREATE_OFFER_FAILED;\nexport const DATA_CHANNEL_OPEN = RTCEvents.DATA_CHANNEL_OPEN;\nexport const DATA_CHANNEL_CLOSED = RTCEvents.DATA_CHANNEL_CLOSED;\nexport const ENDPOINT_CONN_STATUS_CHANGED = RTCEvents.ENDPOINT_CONN_STATUS_CHANGED;\nexport const DOMINANT_SPEAKER_CHANGED = RTCEvents.DOMINANT_SPEAKER_CHANGED;\nexport const FORWARDED_SOURCES_CHANGED = RTCEvents.FORWARDED_SOURCES_CHANGED;\nexport const PERMISSIONS_CHANGED = RTCEvents.PERMISSIONS_CHANGED;\nexport const SENDER_VIDEO_CONSTRAINTS_CHANGED = RTCEvents.SENDER_VIDEO_CONSTRAINTS_CHANGED;\nexport const LASTN_VALUE_CHANGED = RTCEvents.LASTN_VALUE_CHANGED;\nexport const LOCAL_TRACK_SSRC_UPDATED = RTCEvents.LOCAL_TRACK_SSRC_UPDATED;\nexport const LOCAL_TRACK_MAX_ENABLED_RESOLUTION_CHANGED = RTCEvents.LOCAL_TRACK_MAX_ENABLED_RESOLUTION_CHANGED;\nexport const TRACK_ATTACHED = RTCEvents.TRACK_ATTACHED;\nexport const REMOTE_TRACK_ADDED = RTCEvents.REMOTE_TRACK_ADDED;\nexport const REMOTE_TRACK_MUTE = RTCEvents.REMOTE_TRACK_MUTE;\nexport const REMOTE_TRACK_REMOVED = RTCEvents.REMOTE_TRACK_REMOVED;\nexport const REMOTE_TRACK_UNMUTE = RTCEvents.REMOTE_TRACK_UNMUTE;\nexport const SET_LOCAL_DESCRIPTION_FAILED = RTCEvents.SET_LOCAL_DESCRIPTION_FAILED;\nexport const SET_REMOTE_DESCRIPTION_FAILED = RTCEvents.SET_REMOTE_DESCRIPTION_FAILED;\nexport const AUDIO_OUTPUT_DEVICE_CHANGED = RTCEvents.AUDIO_OUTPUT_DEVICE_CHANGED;\nexport const DEVICE_LIST_CHANGED = RTCEvents.DEVICE_LIST_CHANGED;\nexport const DEVICE_LIST_WILL_CHANGE = RTCEvents.DEVICE_LIST_WILL_CHANGE;\nexport const DEVICE_LIST_AVAILABLE = RTCEvents.DEVICE_LIST_AVAILABLE;\nexport const ENDPOINT_MESSAGE_RECEIVED = RTCEvents.ENDPOINT_MESSAGE_RECEIVED;\nexport const ENDPOINT_STATS_RECEIVED = RTCEvents.ENDPOINT_STATS_RECEIVED;\nexport const LOCAL_UFRAG_CHANGED = RTCEvents.LOCAL_UFRAG_CHANGED;\nexport const REMOTE_UFRAG_CHANGED = RTCEvents.REMOTE_UFRAG_CHANGED;\nexport const VIDEO_SSRCS_REMAPPED = RTCEvents.VIDEO_SSRCS_REMAPPED;\nexport const AUDIO_SSRCS_REMAPPED = RTCEvents.AUDIO_SSRCS_REMAPPED;\n\n// TODO: this was a pre-ES6 module using module.exports = RTCEvents which doesn't translate well\n// it is used in a number of places and should be updated to use the named export\n\nexport default RTCEvents;","const Resolutions = {\n '2160': {\n width: 3840,\n height: 2160\n },\n '4k': {\n width: 3840,\n height: 2160\n },\n '1080': {\n width: 1920,\n height: 1080\n },\n 'fullhd': {\n width: 1920,\n height: 1080\n },\n '720': {\n width: 1280,\n height: 720\n },\n 'hd': {\n width: 1280,\n height: 720\n },\n '540': {\n width: 960,\n height: 540\n },\n 'qhd': {\n width: 960,\n height: 540\n },\n '480': {\n width: 640,\n height: 480\n },\n 'vga': {\n width: 640,\n height: 480\n },\n '360': {\n width: 640,\n height: 360\n },\n '240': {\n width: 320,\n height: 240\n },\n '180': {\n width: 320,\n height: 180\n }\n};\n\nmodule.exports = Resolutions;\n","/**\n * Enumeration of the video types\n */\nexport enum VideoType {\n /**\n * The camera video type.\n */\n CAMERA = 'camera',\n\n /**\n * The desktop video type.\n */\n DESKTOP = 'desktop'\n}\n","const 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\nmodule.exports = AuthenticationEvents;\n","export const LOCAL_JID = 'local'\n","export enum XMPPEvents {\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 // 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 AUTHENTICATION_REQUIRED = 'xmpp.authentication_required',\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 // Designates an event indicating that an offer (e.g. Jingle\n // session-initiate) was received.\n CALL_INCOMING = 'xmpp.callincoming.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 CHAT_ERROR_RECEIVED = 'xmpp.chat_error_received',\n SETTINGS_ERROR_RECEIVED = 'xmpp.settings_error_received',\n\n // The conference properties (as advertised by jicofo) have changed\n CONFERENCE_PROPERTIES_CHANGED = 'xmpp.conference_properties_changed',\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 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 // 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 call has been migrated to a different\n // bridge and that the client needs to be restarted for a successful transition.\n CONNECTION_RESTARTED = 'xmpp.connection.restart',\n\n /**\n * Designates an event indicating connection status changes.\n */\n CONNECTION_STATUS_CHANGED = 'xmpp.connection.status.changed',\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 ETHERPAD = 'xmpp.etherpad',\n FOCUS_DISCONNECTED = 'xmpp.focus_disconnected',\n FOCUS_LEFT = 'xmpp.focus_left',\n GRACEFUL_SHUTDOWN = 'xmpp.graceful_shutdown',\n\n /**\n * Event fired when 'transport-replace' Jingle message has been received,\n * before the new offer is set on the PeerConnection.\n */\n ICE_RESTARTING = 'rtc.ice_restarting',\n\n /**\n * Event fired after the 'transport-replace' message has been processed\n * and the new offer has been set successfully.\n */\n ICE_RESTART_SUCCESS = 'rtc.ice_restart_success',\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 // 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 a reaction XMPP message in the MUC\n // was received.\n REACTION_RECEIVED = \"xmpp.reaction_received\",\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 // Designates an event indicating that a private XMPP message in the MUC was\n // received.\n PRIVATE_MESSAGE_RECEIVED = 'xmpp.private_message_received',\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 the XMPP MUC was destroyed.\n MUC_DESTROYED = 'xmpp.muc_destroyed',\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 we have joined the XMPP MUC.\n MUC_JOINED = 'xmpp.muc_joined',\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 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 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 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 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 local participant left the muc\n MUC_LEFT = 'xmpp.muc_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 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 the MUC visitors support has changed.\n MUC_VISITORS_SUPPORTED_CHANGED = 'xmpp.muc_visitors_supported_changed',\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 // 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 /**\n * Indicates that the features of the participant has been changed.\n */\n PARTICIPANT_FEATURES_CHANGED = 'xmpp.participant_features_changed',\n PASSWORD_REQUIRED = 'xmpp.password_required',\n\n /**\n * Indicates that phone number changed.\n */\n PHONE_NUMBER_CHANGED = 'conference.phoneNumberChanged',\n PRESENCE_RECEIVED = 'xmpp.presence_received',\n PRESENCE_STATUS = 'xmpp.presence_status',\n PROMPT_FOR_LOGIN = 'xmpp.prompt_for_login',\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 /**\n * Indicates that the offer / answer renegotiation has failed.\n */\n RENEGOTIATION_FAILED = 'xmpp.renegotiation_failed',\n RESERVATION_ERROR = 'xmpp.room_reservation_error',\n ROOM_CONNECT_ERROR = 'xmpp.room_connect_error',\n ROOM_CONNECT_NOT_ALLOWED_ERROR = 'xmpp.room_connect_error.not_allowed',\n ROOM_JOIN_ERROR = 'xmpp.room_join_error',\n ROOM_CONNECT_MEMBERS_ONLY_ERROR = 'xmpp.room_connect_error.members_only',\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 ROOM_DISCO_INFO_FAILED = 'xmpp.room_disco_info_failed',\n\n /**\n * Indicates that max users limit has been reached.\n */\n ROOM_MAX_USERS_ERROR = 'xmpp.room_max_users_error',\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 /**\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 /**\n * Event fired when conference creation timestamp is received.\n */\n CONFERENCE_TIMESTAMP_RECEIVED = 'xmpp.conference_timestamp_received',\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 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 AV moderation.\n */\n AV_MODERATION_RECEIVED = 'xmpp.av_moderation.received',\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 approved.\n */\n AV_MODERATION_PARTICIPANT_REJECTED = 'xmpp.av_moderation.participant.rejected',\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 we receive a message for breakout rooms.\n */\n BREAKOUT_ROOMS_EVENT = 'xmpp.breakout-rooms.event',\n\n /**\n * Event fired when the breakout rooms data was updated.\n */\n BREAKOUT_ROOMS_UPDATED = 'xmpp.breakout-rooms.updated',\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 should join the conference with\n // audio and/or video muted.\n START_MUTED_FROM_FOCUS = 'xmpp.start_muted_from_focus',\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 /**\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 // 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 /**\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 * The errors for the conference.\n */\n\nexport enum JitsiConferenceErrors {\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 settings error occurred.\n */\n SETTINGS_ERROR = 'conference.settingsError',\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 client has been forced to restart by jicofo when the\n * conference was migrated from one bridge to another.\n */\n CONFERENCE_RESTARTED = 'conference.restarted',\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 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 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 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 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 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}\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 CONFERENCE_RESTARTED = JitsiConferenceErrors.CONFERENCE_RESTARTED;\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","/**\n * The events for the conference.\n */\nexport enum JitsiConferenceEvents {\n /**\n * An event(library-private) fired when the conference switches the currently active media session.\n * @type {string}\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 * @type {string}\n * @private\n */\n _MEDIA_SESSION_STARTED = 'conference.media_session.started',\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 indicates that the permission for unmuting audio has changed based on the number of audio senders in the call\n * 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 * 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 is in progress of joining.\n */\n CONFERENCE_JOIN_IN_PROGRESS = 'conference.join_in_progress',\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 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_VERIFICATION_AVAILABLE = 'conference.e2ee.verification.available',\n\n E2EE_VERIFICATION_COMPLETED = 'conference.e2ee.verification.completed',\n\n E2EE_VERIFICATION_READY = 'conference.e2ee.verification.ready',\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 * The forwarded sources set is changed.\n *\n * @param {Array} leavingForwardedSources the sourceNames of all the tracks which are leaving forwarded\n * sources\n * @param {Array} enteringForwardedSources the sourceNames of all the tracks which are entering forwarded\n * sources\n */\n FORWARDED_SOURCES_CHANGED = 'conference.forwardedSourcesChanged',\n\n /**\n * NOTE This is lib-jitsi-meet internal event and can be removed at any time !\n *\n * Event emitted when conference transits, between one to one and multiparty JVB\n * conference. If the conference switches to P2P it's neither one to one nor\n * a multiparty JVB conference, but P2P (the status argument of this event will\n * be false).\n *\n * The first argument is a boolean which carries the previous value and\n * the seconds argument is a boolean with the new status. The event is emitted\n * only if the previous and the new values are different.\n *\n * @type {string}\n */\n JVB121_STATUS = 'conference.jvb121Status',\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|null} leavingEndpointIds the ids of all the endpoints\n * which are leaving Last N\n * @param {Array|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 boolean which when set to\n * true 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 * New text message was received.\n */\n MESSAGE_RECEIVED = 'conference.messageReceived',\n\n /**\n * New reaction was received.\n */\n REACTION_RECEIVED = 'conference.reactionReceived',\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 selected input device has no signal\n */\n NO_AUDIO_INPUT = 'conference.no_audio_input',\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 * Indicates that the conference has switched between JVB and P2P connections.\n * The first argument of this event is a boolean which when set to\n * true 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 phone number changed.\n */\n PHONE_NUMBER_CHANGED = 'conference.phoneNumberChanged',\n\n /**\n * New private text message was received.\n */\n PRIVATE_MESSAGE_RECEIVED = 'conference.privateMessageReceived',\n /**\n * The conference properties changed.\n * @type {string}\n */\n PROPERTIES_CHANGED = 'conference.propertiesChanged',\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 * @type {string} the region.\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 the local user has started muted.\n */\n STARTED_MUTED = 'conference.started_muted',\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 * 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 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 call\n * and the video sender limit configured in Jicofo.\n */\n VIDEO_UNMUTE_PERMISSIONS_CHANGED = 'conference.video_unmute_permissions_changed',\n\n /**\n * Indicates that the conference has support for visitors.\n */\n VISITORS_SUPPORTED_CHANGED = 'conference.visitorsSupported',\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// exported for backward compatibility\nexport const _MEDIA_SESSION_STARTED = JitsiConferenceEvents._MEDIA_SESSION_STARTED;\nexport const _MEDIA_SESSION_ACTIVE_CHANGED = JitsiConferenceEvents._MEDIA_SESSION_ACTIVE_CHANGED;\nexport const AUDIO_INPUT_STATE_CHANGE = JitsiConferenceEvents.AUDIO_INPUT_STATE_CHANGE;\nexport const AUDIO_UNMUTE_PERMISSIONS_CHANGED = JitsiConferenceEvents.AUDIO_UNMUTE_PERMISSIONS_CHANGED;\nexport const AUTH_STATUS_CHANGED = JitsiConferenceEvents.AUTH_STATUS_CHANGED;\nexport const AV_MODERATION_APPROVED = JitsiConferenceEvents.AV_MODERATION_APPROVED;\nexport const AV_MODERATION_CHANGED = JitsiConferenceEvents.AV_MODERATION_CHANGED;\nexport const AV_MODERATION_PARTICIPANT_APPROVED = JitsiConferenceEvents.AV_MODERATION_PARTICIPANT_APPROVED;\nexport const AV_MODERATION_PARTICIPANT_REJECTED = JitsiConferenceEvents.AV_MODERATION_PARTICIPANT_REJECTED;\nexport const AV_MODERATION_REJECTED = JitsiConferenceEvents.AV_MODERATION_REJECTED;\nexport const BEFORE_STATISTICS_DISPOSED = JitsiConferenceEvents.BEFORE_STATISTICS_DISPOSED;\nexport const BOT_TYPE_CHANGED = JitsiConferenceEvents.BOT_TYPE_CHANGED;\nexport const BREAKOUT_ROOMS_MOVE_TO_ROOM = JitsiConferenceEvents.BREAKOUT_ROOMS_MOVE_TO_ROOM;\nexport const BREAKOUT_ROOMS_UPDATED = JitsiConferenceEvents.BREAKOUT_ROOMS_UPDATED;\nexport const CONFERENCE_CREATED_TIMESTAMP = JitsiConferenceEvents.CONFERENCE_CREATED_TIMESTAMP;\nexport const CONFERENCE_ERROR = JitsiConferenceEvents.CONFERENCE_ERROR;\nexport const CONFERENCE_FAILED = JitsiConferenceEvents.CONFERENCE_FAILED;\nexport const CONFERENCE_JOIN_IN_PROGRESS = JitsiConferenceEvents.CONFERENCE_JOIN_IN_PROGRESS;\nexport const CONFERENCE_JOINED = JitsiConferenceEvents.CONFERENCE_JOINED;\nexport const CONFERENCE_LEFT = JitsiConferenceEvents.CONFERENCE_LEFT;\nexport const CONFERENCE_UNIQUE_ID_SET = JitsiConferenceEvents.CONFERENCE_UNIQUE_ID_SET;\nexport const CONFERENCE_VISITOR_CODECS_CHANGED = JitsiConferenceEvents.CONFERENCE_VISITOR_CODECS_CHANGED;\nexport const CONNECTION_ESTABLISHED = JitsiConferenceEvents.CONNECTION_ESTABLISHED;\nexport const CONNECTION_INTERRUPTED = JitsiConferenceEvents.CONNECTION_INTERRUPTED;\nexport const CONNECTION_RESTORED = JitsiConferenceEvents.CONNECTION_RESTORED;\nexport const DATA_CHANNEL_CLOSED = JitsiConferenceEvents.DATA_CHANNEL_CLOSED;\nexport const DATA_CHANNEL_OPENED = JitsiConferenceEvents.DATA_CHANNEL_OPENED;\nexport const DISPLAY_NAME_CHANGED = JitsiConferenceEvents.DISPLAY_NAME_CHANGED;\nexport const DOMINANT_SPEAKER_CHANGED = JitsiConferenceEvents.DOMINANT_SPEAKER_CHANGED;\nexport const DTMF_SUPPORT_CHANGED = JitsiConferenceEvents.DTMF_SUPPORT_CHANGED;\nexport const E2EE_VERIFICATION_AVAILABLE = JitsiConferenceEvents.E2EE_VERIFICATION_AVAILABLE;\nexport const E2EE_VERIFICATION_COMPLETED = JitsiConferenceEvents.E2EE_VERIFICATION_COMPLETED;\nexport const E2EE_VERIFICATION_READY = JitsiConferenceEvents.E2EE_VERIFICATION_READY;\nexport const ENCODE_TIME_STATS_RECEIVED = JitsiConferenceEvents.ENCODE_TIME_STATS_RECEIVED;\nexport const ENDPOINT_MESSAGE_RECEIVED = JitsiConferenceEvents.ENDPOINT_MESSAGE_RECEIVED;\nexport const ENDPOINT_STATS_RECEIVED = JitsiConferenceEvents.ENDPOINT_STATS_RECEIVED;\nexport const FORWARDED_SOURCES_CHANGED = JitsiConferenceEvents.FORWARDED_SOURCES_CHANGED;\nexport const JVB121_STATUS = JitsiConferenceEvents.JVB121_STATUS;\nexport const KICKED = JitsiConferenceEvents.KICKED;\nexport const LAST_N_ENDPOINTS_CHANGED = JitsiConferenceEvents.LAST_N_ENDPOINTS_CHANGED;\nexport const LOBBY_USER_JOINED = JitsiConferenceEvents.LOBBY_USER_JOINED;\nexport const LOBBY_USER_LEFT = JitsiConferenceEvents.LOBBY_USER_LEFT;\nexport const LOBBY_USER_UPDATED = JitsiConferenceEvents.LOBBY_USER_UPDATED;\nexport const LOCK_STATE_CHANGED = JitsiConferenceEvents.LOCK_STATE_CHANGED;\nexport const MEMBERS_ONLY_CHANGED = JitsiConferenceEvents.MEMBERS_ONLY_CHANGED;\nexport const MESSAGE_RECEIVED = JitsiConferenceEvents.MESSAGE_RECEIVED;\nexport const METADATA_UPDATED = JitsiConferenceEvents.METADATA_UPDATED;\nexport const NO_AUDIO_INPUT = JitsiConferenceEvents.NO_AUDIO_INPUT;\nexport const NOISY_MIC = JitsiConferenceEvents.NOISY_MIC;\nexport const NON_PARTICIPANT_MESSAGE_RECEIVED = JitsiConferenceEvents.NON_PARTICIPANT_MESSAGE_RECEIVED;\nexport const P2P_STATUS = JitsiConferenceEvents.P2P_STATUS;\nexport const PARTICIPANT_KICKED = JitsiConferenceEvents.PARTICIPANT_KICKED;\nexport const PARTICIPANT_SOURCE_UPDATED = JitsiConferenceEvents.PARTICIPANT_SOURCE_UPDATED;\nexport const PRIVATE_MESSAGE_RECEIVED = JitsiConferenceEvents.PRIVATE_MESSAGE_RECEIVED;\nexport const PARTCIPANT_FEATURES_CHANGED = JitsiConferenceEvents.PARTCIPANT_FEATURES_CHANGED;\nexport const PARTICIPANT_PROPERTY_CHANGED = JitsiConferenceEvents.PARTICIPANT_PROPERTY_CHANGED;\nexport const PHONE_NUMBER_CHANGED = JitsiConferenceEvents.PHONE_NUMBER_CHANGED;\nexport const PROPERTIES_CHANGED = JitsiConferenceEvents.PROPERTIES_CHANGED;\nexport const RECORDER_STATE_CHANGED = JitsiConferenceEvents.RECORDER_STATE_CHANGED;\nexport const SERVER_REGION_CHANGED = JitsiConferenceEvents.SERVER_REGION_CHANGED;\nexport const SILENT_STATUS_CHANGED = JitsiConferenceEvents.SILENT_STATUS_CHANGED;\nexport const START_MUTED_POLICY_CHANGED = JitsiConferenceEvents.START_MUTED_POLICY_CHANGED;\nexport const STARTED_MUTED = JitsiConferenceEvents.STARTED_MUTED;\nexport const SUBJECT_CHANGED = JitsiConferenceEvents.SUBJECT_CHANGED;\nexport const SUSPEND_DETECTED = JitsiConferenceEvents.SUSPEND_DETECTED;\nexport const TALK_WHILE_MUTED = JitsiConferenceEvents.TALK_WHILE_MUTED;\nexport const TRACK_ADDED = JitsiConferenceEvents.TRACK_ADDED;\nexport const TRACK_AUDIO_LEVEL_CHANGED = JitsiConferenceEvents.TRACK_AUDIO_LEVEL_CHANGED;\nexport const TRACK_MUTE_CHANGED = JitsiConferenceEvents.TRACK_MUTE_CHANGED;\nexport const TRACK_REMOVED = JitsiConferenceEvents.TRACK_REMOVED;\nexport const TRACK_UNMUTE_REJECTED = JitsiConferenceEvents.TRACK_UNMUTE_REJECTED;\nexport const TRANSCRIPTION_STATUS_CHANGED = JitsiConferenceEvents.TRANSCRIPTION_STATUS_CHANGED;\nexport const USER_JOINED = JitsiConferenceEvents.USER_JOINED;\nexport const USER_LEFT = JitsiConferenceEvents.USER_LEFT;\nexport const USER_ROLE_CHANGED = JitsiConferenceEvents.USER_ROLE_CHANGED;\nexport const USER_STATUS_CHANGED = JitsiConferenceEvents.USER_STATUS_CHANGED;\nexport const VIDEO_SIP_GW_AVAILABILITY_CHANGED = JitsiConferenceEvents.VIDEO_SIP_GW_AVAILABILITY_CHANGED;\nexport const VIDEO_SIP_GW_SESSION_STATE_CHANGED = JitsiConferenceEvents.VIDEO_SIP_GW_SESSION_STATE_CHANGED;\nexport const VIDEO_UNMUTE_PERMISSIONS_CHANGED = JitsiConferenceEvents.VIDEO_UNMUTE_PERMISSIONS_CHANGED;\nexport const VISITORS_SUPPORTED_CHANGED = JitsiConferenceEvents.VISITORS_SUPPORTED_CHANGED;\nexport const VISITORS_MESSAGE = JitsiConferenceEvents.VISITORS_MESSAGE;\nexport const VISITORS_REJECTION = JitsiConferenceEvents.VISITORS_REJECTION;\n","export enum JitsiTrackEvents {\n /**\n * The media track was removed to the conference.\n */\n LOCAL_TRACK_STOPPED = 'track.stopped',\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 TraceablePeerConnection 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 undefined).\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 * The video type(\"camera\" or \"desktop\") of the track was changed.\n */\n TRACK_VIDEOTYPE_CHANGED = 'track.videoTypeChanged',\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 * 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 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 currently\n * - active - the connection is active.\n * - inactive - the connection is inactive, was intentionally interrupted by the bridge because of low BWE or because\n * 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// exported for backward compatibility\nexport const LOCAL_TRACK_STOPPED = JitsiTrackEvents.LOCAL_TRACK_STOPPED;\nexport const TRACK_AUDIO_LEVEL_CHANGED = JitsiTrackEvents.TRACK_AUDIO_LEVEL_CHANGED;\nexport const TRACK_AUDIO_OUTPUT_CHANGED = JitsiTrackEvents.TRACK_AUDIO_OUTPUT_CHANGED;\nexport const TRACK_MUTE_CHANGED = JitsiTrackEvents.TRACK_MUTE_CHANGED;\nexport const TRACK_VIDEOTYPE_CHANGED = JitsiTrackEvents.TRACK_VIDEOTYPE_CHANGED;\nexport const NO_DATA_FROM_SOURCE = JitsiTrackEvents.NO_DATA_FROM_SOURCE;\nexport const NO_AUDIO_INPUT = JitsiTrackEvents.NO_AUDIO_INPUT;\nexport const TRACK_OWNER_SET = JitsiTrackEvents.TRACK_OWNER_SET;\nexport const TRACK_STREAMING_STATUS_CHANGED = JitsiTrackEvents.TRACK_STREAMING_STATUS_CHANGED;\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 * 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 * 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 Jingle events which indicates that a transport-replace\n * was received.\n */\n ACTION_JINGLE_TR_RECEIVED = 'transport-replace.received',\n\n /**\n * The \"action\" value for Jingle events which indicates that a transport-replace\n * succeeded (TODO: verify/fix the documentation)\n */\n ACTION_JINGLE_TR_SUCCESS = 'transport-replace.success',\n\n /**\n * The \"action\" value for P2P events which indicates that P2P session initiate message has been rejected by the client\n * 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 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// exported for backward compatibility\nexport const TYPE_OPERATIONAL = AnalyticsEvents.TYPE_OPERATIONAL;\nexport const TYPE_PAGE = AnalyticsEvents.TYPE_PAGE;\nexport const TYPE_TRACK = AnalyticsEvents.TYPE_TRACK;\nexport const TYPE_UI = AnalyticsEvents.TYPE_UI;\nexport const ACTION_JINGLE_RESTART = AnalyticsEvents.ACTION_JINGLE_RESTART;\nexport const ACTION_JINGLE_SA_TIMEOUT = AnalyticsEvents.ACTION_JINGLE_SA_TIMEOUT;\nexport const ACTION_JINGLE_SI_RECEIVED = AnalyticsEvents.ACTION_JINGLE_SI_RECEIVED;\nexport const ACTION_JINGLE_SI_TIMEOUT = AnalyticsEvents.ACTION_JINGLE_SI_TIMEOUT;\nexport const ACTION_JINGLE_TERMINATE = AnalyticsEvents.ACTION_JINGLE_TERMINATE;\nexport const ACTION_JINGLE_TR_RECEIVED = AnalyticsEvents.ACTION_JINGLE_TR_RECEIVED;\nexport const ACTION_JINGLE_TR_SUCCESS = AnalyticsEvents.ACTION_JINGLE_TR_SUCCESS;\nexport const ACTION_P2P_DECLINED = AnalyticsEvents.ACTION_P2P_DECLINED;\nexport const ACTION_P2P_ESTABLISHED = AnalyticsEvents.ACTION_P2P_ESTABLISHED;\nexport const ACTION_P2P_FAILED = AnalyticsEvents.ACTION_P2P_FAILED;\nexport const ACTION_P2P_SWITCH_TO_JVB = AnalyticsEvents.ACTION_P2P_SWITCH_TO_JVB;\nexport const AVAILABLE_DEVICE = AnalyticsEvents.AVAILABLE_DEVICE;\nexport const CONNECTION_DISCONNECTED = AnalyticsEvents.CONNECTION_DISCONNECTED;\nexport const FEEDBACK = AnalyticsEvents.FEEDBACK;\nexport const ICE_DURATION = AnalyticsEvents.ICE_DURATION;\nexport const ICE_ESTABLISHMENT_DURATION_DIFF = AnalyticsEvents.ICE_ESTABLISHMENT_DURATION_DIFF;\nexport const ICE_STATE_CHANGED = AnalyticsEvents.ICE_STATE_CHANGED;\nexport const NO_BYTES_SENT = AnalyticsEvents.NO_BYTES_SENT;\nexport const TRACK_UNMUTED = AnalyticsEvents.TRACK_UNMUTED;\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 action: 'bridge.down',\n actionSubject: 'bridge.down',\n type: TYPE_OPERATIONAL\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 type: AnalyticsEvents.TYPE_OPERATIONAL,\n action: 'connection.failed',\n attributes: {\n 'error_type': errorType,\n 'error_message': errorMessage,\n ...details\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 action,\n attributes,\n source: 'conference',\n type: AnalyticsEvents.TYPE_OPERATIONAL\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 action: 'connection.stage.reached',\n actionSubject: stage,\n attributes,\n source: 'connection.stage.reached',\n type: AnalyticsEvents.TYPE_OPERATIONAL\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 attributes: {\n 'participant_id': participantId,\n region,\n rtt\n },\n name: 'e2e_rtt',\n type: AnalyticsEvents.TYPE_OPERATIONAL\n} );\n\n/**\n * Creates an event which indicates that the focus has left the MUC.\n */\nexport const createFocusLeftEvent = () => ( {\n action: 'focus.left',\n actionSubject: 'focus.left',\n type: AnalyticsEvents.TYPE_OPERATIONAL\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 type: AnalyticsEvents.TYPE_OPERATIONAL,\n source: 'get.user.media',\n action,\n attributes\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 type: AnalyticsEvents.TYPE_OPERATIONAL,\n source: 'peer.conn.status',\n action: 'duration',\n attributes\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 type: AnalyticsEvents.TYPE_OPERATIONAL,\n source: 'track.streaming.status',\n action: 'duration',\n attributes\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 type: AnalyticsEvents.TYPE_OPERATIONAL,\n action,\n source: 'jingle',\n attributes\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 attributes: {\n 'media_type': mediaType,\n value\n },\n action: 'track.no.data.from.source',\n type: AnalyticsEvents.TYPE_OPERATIONAL\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 type: AnalyticsEvents.TYPE_OPERATIONAL,\n action,\n source: 'p2p',\n attributes\n} )\n\n/**\n * Indicates that we received a remote command to mute.\n */\nexport const createRemotelyMutedEvent = ( mediaType: unknown ) => ( {\n type: AnalyticsEvents.TYPE_OPERATIONAL,\n action: 'remotely.muted',\n mediaType\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 type: AnalyticsEvents.TYPE_OPERATIONAL,\n action: 'rtp.stats',\n attributes\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 type: AnalyticsEvents.TYPE_OPERATIONAL,\n action: 'rtt.by.region',\n attributes\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 type: AnalyticsEvents.TYPE_OPERATIONAL,\n action: 'transport.stats',\n attributes\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 = ( userID: string, localAudioLevels: unknown, remoteAudioLevels: unknown ) => ( {\n type: AnalyticsEvents.TYPE_OPERATIONAL,\n action: 'audio.output.problem',\n attributes: {\n userID,\n localAudioLevels,\n remoteAudioLevels\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 type: AnalyticsEvents.TYPE_OPERATIONAL,\n action: 'bridge-channel.error',\n attributes: {\n code,\n reason\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 Events {\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 ssrc according to\n * RTP statistics.\n * @param {boolean} isLocal - true if ssrc identifies the\n * local endpoint/participant; otherwise, false.\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 bandwidth, bitrate, packetLoss,\n * resolution, and transport.\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 performance stats.\n */\n LONG_TASKS_STATS = 'statistics.long_tasks_stats'\n};\n\n// exported for backward compatibility\nexport const AUDIO_LEVEL = Events.AUDIO_LEVEL;\nexport const BEFORE_DISPOSED = Events.BEFORE_DISPOSED;\nexport const BYTE_SENT_STATS = Events.BYTE_SENT_STATS;\nexport const CONNECTION_STATS = Events.CONNECTION_STATS;\nexport const ENCODE_TIME_STATS = Events.ENCODE_TIME_STATS;\nexport const LONG_TASKS_STATS = Events.LONG_TASKS_STATS;\n","// TODO: Maybe fix the values to 'Chrome', 'Internet Explorer', etc. Currently\n// this values needs to be as they are becuse they are going to analytics,\n// callstats, etc.\n\nexport const CHROME = 'chrome';\n\nexport const FIREFOX = 'firefox';\n\nexport const SAFARI = 'safari';\n\nexport const ELECTRON = 'electron';\n\nexport const REACT_NATIVE = 'react-native';\n\nexport const WEBKIT_BROWSER = 'webkit-browser';\n\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': CHROME,\n 'Firefox': FIREFOX,\n 'Safari': SAFARI,\n 'Electron': ELECTRON\n};\n\nexport const BLINK = 'blink';\n\nexport const WEBKIT = 'webkit';\n\nexport const GECKO = 'gecko';\n\nexport const ENGINES = {\n 'Blink': BLINK,\n 'WebKit': WEBKIT,\n 'Gecko': GECKO\n};\n","import { UAParser } from 'ua-parser-js';\n\nimport {\n BLINK,\n CHROME,\n ELECTRON,\n ENGINES,\n GECKO,\n PARSER_TO_JITSI_NAME,\n REACT_NATIVE,\n SAFARI,\n WEBKIT\n} from './constants.js';\n\n/**\n * Detects React Native environment.\n * @returns {Object|undefined} - The name (REACT_NATIVE) and version.\n */\nfunction _detectReactNative() {\n const match\n = navigator.userAgent.match(/\\b(react[ \\t_-]*native)(?:\\/(\\S+))?/i);\n let version;\n\n // If we're remote debugging a React Native app, it may be treated as\n // Chrome. Check navigator.product as well and always return some version\n // even if we can't get the real one.\n\n if (match || navigator.product === 'ReactNative') {\n let name;\n\n if (match && match.length > 2) {\n name = match[1];\n version = match[2];\n }\n name || (name = 'react-native');\n version || (version = 'unknown');\n\n return {\n name: REACT_NATIVE,\n version\n };\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 return {\n name: PARSER_TO_JITSI_NAME[browserInfo.name],\n version: browserInfo.version,\n engine: ENGINES[browserInfo.engine],\n engineVersion: browserInfo.engineVersion\n };\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\n if (reactNativeInfo) {\n return reactNativeInfo;\n }\n\n const { name, version } = parser.getBrowser();\n const { name: engine, version: engineVersion } = parser.getEngine();\n\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\n const {\n name,\n version,\n engine,\n engineVersion\n } = browserInfo ? _getJitsiBrowserInfo(browserInfo) : _detect(this._parser);\n\n this._name = name;\n this._version = version;\n this._engine = engine;\n this._engineVersion = engineVersion;\n }\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 === CHROME || this._engine === BLINK;\n }\n\n /**\n * Checks if current browser is Firefox.\n * @returns {boolean}\n */\n isFirefox() {\n return this._engine === GECKO;\n }\n\n /**\n * Checks if current browser is Safari.\n * @returns {boolean}\n */\n isSafari() {\n return this._name === SAFARI;\n }\n\n /**\n * Checks if current environment is Electron.\n * @returns {boolean}\n */\n isElectron() {\n return this._name === ELECTRON;\n }\n\n /**\n * Checks if current environment is React Native.\n * @returns {boolean}\n */\n isReactNative() {\n return this._name === REACT_NATIVE;\n }\n\n /**\n * Checks if current browser is based on chromium.\n * @returns {boolean}\n */\n isChromiumBased() {\n return this._engine === BLINK;\n }\n\n /**\n * Checks if current browser is based on webkit.\n * @returns {boolean}\n */\n isWebKitBased() {\n return this._engine === WEBKIT;\n }\n\n /**\n * Gets current browser name.\n * @returns {string}\n */\n getName() {\n if (this._name) {\n return this._name;\n }\n\n return this._parser.getBrowser().name;\n }\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\n return this._parser.getBrowser().version;\n }\n\n /**\n * Gets current engine name of the browser.\n * @returns {string}\n */\n getEngine() {\n return this._engine;\n }\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 /**\n * Returns the operating system.\n */\n getOS() {\n return this._parser.getOS().name;\n }\n\n /**\n * Return the os version.\n */\n getOSVersion() {\n return this._parser.getOS().version;\n }\n\n /**\n * Compares the passed version with the current browser version.\n *\n * @param {number|string} version - The version to compare with.\n * @returns {boolean|undefined} - Returns true if the current version is\n * greater than the passed version and false otherwise. Returns undefined if\n * the current browser version is unknown.\n */\n isVersionGreaterThan(version) {\n if (this._version) {\n return parseInt(this._version, 10) > parseInt(version, 10);\n }\n }\n\n /**\n * Compares the passed version with the current browser version.\n *\n * @param {number|string} version - The version to compare with.\n * @returns {boolean|undefined} - Returns true if the current version is\n * lower than the passed version and false otherwise. Returns undefined if\n * the current browser version is unknown.\n */\n isVersionLessThan(version) {\n if (this._version) {\n return parseInt(this._version, 10) < parseInt(version, 10);\n }\n }\n\n /**\n * Compares the passed version with the current browser version.\n *\n * @param {number|string} version - The version to compare with.\n * @returns {boolean|undefined} - Returns true if the current version is\n * equal to the passed version and false otherwise. Returns undefined if\n * the current browser version is unknown.\n * A loose-equality operator is used here so that it matches the sub-versions as well.\n */\n isVersionEqualTo(version) {\n if (this._version) {\n return parseInt(this._version, 10) === parseInt(version, 10);\n }\n }\n\n /**\n * Compares the passed version with the current engine version.\n *\n * @param {number|string} version - The version to compare with.\n * @returns {boolean|undefined} - Returns true if the current version is\n * greater than the passed version and false otherwise. Returns undefined if\n * the current engine version is unknown.\n */\n isEngineVersionGreaterThan(version) {\n if (this._engineVersion) {\n return parseInt(this._engineVersion, 10) > parseInt(version, 10);\n }\n }\n\n /**\n * Compares the passed version with the current engine version.\n *\n * @param {number|string} version - The version to compare with.\n * @returns {boolean|undefined} - Returns true if the current version is\n * lower than the passed version and false otherwise. Returns undefined if\n * the current engine version is unknown.\n */\n isEngineVersionLessThan(version) {\n if (this._engineVersion) {\n return parseInt(this._engineVersion, 10) < parseInt(version, 10);\n }\n }\n\n /**\n * Compares the passed version with the current engine version.\n *\n * @param {number|string} version - The version to compare with.\n * @returns {boolean|undefined} - Returns true if the current version is\n * equal to the passed version and false otherwise. Returns undefined if\n * the current engine version is unknown.\n * A loose-equality operator is used here so that it matches the sub-versions as well.\n */\n isEngineVersionEqualTo(version) {\n if (this._engineVersion) {\n return parseInt(this._engineVersion, 10) === parseInt(version, 10);\n }\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","// 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","/* 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 // 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(reconnectSpentTime);\n const reconnectTimeoutTime = reconnectSpentTime + reconnectTimeoutTimeCandidate < MAX_RECONNECT_TIME\n ? reconnectTimeoutTimeCandidate\n : MAX_RECONNECT_TIME - reconnectSpentTime;\n\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 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 * Events emitted by the RTCStats module.\n */\nexport enum RTCStatsEvents {\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 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// exported for backward compatibility\nexport const RTC_STATS_WC_DISCONNECTED = RTCStatsEvents.RTC_STATS_WC_DISCONNECTED;\nexport const RTC_STATS_PC_EVENT = RTCStatsEvents.RTC_STATS_PC_EVENT;\n","import { EventEmitter as NodeEventEmitter } from 'events';\n\n/**\n * The class creates our own EventEmitter instance\n */\nexport default class EventEmitter extends NodeEventEmitter {\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","import EventEmitter from 'events';\n\n/**\n * Dummy implementation of Storage interface.\n */\nclass DummyLocalStorage extends EventEmitter {\n\n /**\n * The object used for storage.\n */\n _storage = {};\n\n /**\n * Empties all keys out of the storage.\n *\n * @returns {void}\n */\n clear() {\n this._storage = {};\n }\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 /**\n * Will return that key's value associated to the passed key name.\n *\n * @param {string} keyName - The key name.\n * @returns {*} - The key value.\n */\n getItem(keyName) {\n return this._storage[keyName];\n }\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 {*} keyValue - The key value.\n * @returns {void}\n */\n setItem(keyName, keyValue) {\n this._storage[keyName] = keyValue;\n }\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 /**\n * When passed a number n, this method will return the name of the nth key in the storage.\n *\n * @param {number} idx - The index of the key.\n * @returns {string} - The nth key name.\n */\n key(n) {\n const keys = Object.keys(this._storage);\n\n if (keys.length <= n) {\n return undefined;\n }\n\n return keys[n];\n }\n\n /**\n * Serializes the content of the storage.\n *\n * @param {Array} 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\n const storageCopy = { ...this._storage };\n\n ignore.forEach(key => {\n delete storageCopy[key];\n });\n\n return JSON.stringify(storageCopy);\n }\n}\n\n/**\n * Wrapper class for browser's local storage object.\n */\nclass JitsiLocalStorage extends EventEmitter {\n /**\n * @constructor\n * @param {Storage} storage browser's local storage object.\n */\n constructor() {\n super();\n\n try {\n this._storage = window.localStorage;\n this._localStorageDisabled = false;\n } catch (ignore) {\n // localStorage throws an exception.\n }\n\n if (!this._storage) { // Handles the case when window.localStorage is undefined or throws an exception.\n console.warn('Local storage is disabled.');\n this._storage = new DummyLocalStorage();\n this._localStorageDisabled = true;\n }\n }\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 /**\n * Switch between window.localStorage and DummyLocalStorage.\n */\n setLocalStorageDisabled(value) {\n this._localStorageDisabled = value;\n\n try {\n this._storage = value ? new DummyLocalStorage() : window.localStorage;\n } catch (ignore) {\n // localStorage throws an exception.\n }\n\n if (!this._storage) {\n this._storage = new DummyLocalStorage();\n }\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 /**\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 /**\n * Returns that passed key's value.\n * @param {string} keyName the name of the key you want to retrieve\n * the value of.\n * @returns {String|null} the value of the key. If the key does not exist,\n * null is returned.\n */\n getItem(keyName) {\n return this._storage.getItem(keyName);\n }\n\n /**\n * Adds a key to the storage, or update key's value if it already exists.\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\n * creating/updating.\n * @param {boolean} dontEmitChangedEvent - If true a changed event won't be emitted.\n */\n setItem(keyName, keyValue, dontEmitChangedEvent = false) {\n this._storage.setItem(keyName, keyValue);\n\n if (!dontEmitChangedEvent) {\n this.emit('changed');\n }\n }\n\n /**\n * Remove a key from the storage.\n * @param {string} keyName the name of the key you want to remove.\n */\n removeItem(keyName) {\n this._storage.removeItem(keyName);\n this.emit('changed');\n }\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}\n */\n key(i) {\n return this._storage.key(i);\n }\n\n /**\n * Serializes the content of the storage.\n *\n * @param {Array} 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\n const length = this._storage.length;\n const localStorageContent = {};\n\n for (let i = 0; i < length; i++) {\n const key = this._storage.key(i);\n\n if (!ignore.includes(key)) {\n localStorageContent[key] = this._storage.getItem(key);\n }\n }\n\n return JSON.stringify(localStorageContent);\n }\n}\n\nexport const jitsiLocalStorage = new JitsiLocalStorage();\n","import { jitsiLocalStorage } from '@jitsi/js-utils';\nimport { getLogger } from '@jitsi/logger';\n\nconst logger = getLogger(__filename);\n\nimport UsernameGenerator from '../util/UsernameGenerator';\n\nlet _callStatsUserName;\n\nlet _machineId;\n\n/**\n *\n */\nexport default {\n\n /**\n * The storage used to store the settings.\n */\n _storage: jitsiLocalStorage,\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) {\n this._storage = externalStorage || jitsiLocalStorage;\n },\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() {\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 * Returns current machine id.\n * @returns {string} machine id\n */\n get machineId() {\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() {\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) {\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 = UsernameGenerator.generateUsername();\n\n logger.log('generated stats id', username);\n\n return username;\n}\n\n/**\n * Generate unique id.\n * @returns {string} random unique id\n */\nfunction generateJitsiMeetId() {\n const jitsiMeetId = generateUniqueId();\n\n logger.log('generated id', jitsiMeetId);\n\n return jitsiMeetId;\n}\n\n/**\n *\n */\nfunction generateUniqueId() {\n return _p8() + _p8() + _p8() + _p8();\n}\n\n/**\n *\n */\nfunction _p8() {\n return `${Math.random().toString(16)}000000000`.substr(2, 8);\n}\n","import { getLogger } from '@jitsi/logger';\n\nimport rtcstatsInit from '@jitsi/rtcstats/rtcstats';\nimport traceInit from '@jitsi/rtcstats/trace-ws';\n\nimport {\n CONFERENCE_CREATED_TIMESTAMP,\n CONFERENCE_JOINED,\n CONFERENCE_LEFT,\n CONFERENCE_UNIQUE_ID_SET\n} from '../../JitsiConferenceEvents';\nimport JitsiConference from '../../JitsiConference';\nimport { IRTCStatsConfiguration } from './interfaces';\nimport { RTC_STATS_PC_EVENT, RTC_STATS_WC_DISCONNECTED } from './RTCStatsEvents';\nimport EventEmitter from '../util/EventEmitter';\nimport Settings from '../settings/Settings';\n\nconst logger = getLogger(__filename);\n\n/**\n * RTCStats Singleton that is initialized only once for the lifetime of the app, subsequent calls to init will be ignored.\n * Config and conference changes are handled by the start method.\n */\nclass RTCStats {\n private _initialized: boolean = false;\n private _trace: any = null;\n public events: EventEmitter = new EventEmitter();\n\n /**\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 when lib-jitsi-meet is loaded.\n *\n * @param {IRTCStatsConfiguration} initConfig initial config for rtcstats.\n * @returns {void}\n */\n init(initConfig: IRTCStatsConfiguration) {\n const {\n analytics: {\n rtcstatsUseLegacy: useLegacy = false,\n rtcstatsPollInterval: pollInterval= 10000,\n rtcstatsSendSdp: sendSdp = false,\n rtcstatsEnabled = false\n } = {}\n } = initConfig;\n\n // If rtcstats is not enabled or 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 (!rtcstatsEnabled || this._initialized) return;\n\n rtcstatsInit(\n { statsEntry: this.sendStatsEntry.bind(this) },\n { pollInterval,\n useLegacy,\n sendSdp,\n eventCallback: (event) => this.events.emit(RTC_STATS_PC_EVENT, event)}\n );\n\n this._initialized = 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 start(conference: JitsiConference) {\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 rtcstatsUseLegacy: useLegacy = false\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 // Reset the trace module in case it wasn't during the previous conference.\n // Closing the underlying websocket connection and deleting the trace obj.\n this.reset();\n\n // The new conference config might have rtcstats disabled, so we need to check again.\n if (!rtcstatsEnabled) return;\n\n // If rtcstats proxy module is not initialized, do nothing.\n if (!this._initialized) {\n logger.error('Calling start 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(CONFERENCE_JOINED, () => {\n const traceOptions = {\n endpoint,\n meetingFqn: confName,\n onCloseCallback: (event) => this.events.emit(RTC_STATS_WC_DISCONNECTED, event),\n useLegacy\n };\n\n const isBreakoutRoom = Boolean(conference.getBreakoutRooms()?.isBreakoutRoom());\n const endpointId = conference.myUserId();\n const meetingUniqueId = conference.getMeetingUniqueId();\n\n this._trace = traceInit(traceOptions);\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 this._trace.connect(isBreakoutRoom);\n\n const identityData = {\n ...confConfig,\n endpointId,\n confName,\n displayName,\n meetingUniqueId,\n isBreakoutRoom,\n localId\n }\n\n this.sendIdentity(identityData);\n });\n\n // Note, this will only be called for normal rooms, not breakout rooms.\n conference.once(CONFERENCE_UNIQUE_ID_SET, (meetingUniqueId) => {\n this.sendIdentity({meetingUniqueId});\n });\n\n conference.once(CONFERENCE_LEFT, () => {\n this.reset();\n });\n\n conference.once(CONFERENCE_CREATED_TIMESTAMP, (timestamp: number) => {\n this.sendStatsEntry('conferenceStartTimestamp', null, timestamp);\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) {\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() {\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, pcId, data) {\n this._trace?.statsEntry(statsType, pcId, data);\n }\n}\n\nexport default new RTCStats();\n","import BrowserCapabilities from './BrowserCapabilities';\n\nexport default new BrowserCapabilities();\n","import { BrowserDetection } from '@jitsi/js-utils';\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 * Tells whether or not the MediaStream/tt> is removed from the PeerConnection 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} true if the current browser supports this strategy or false otherwise.\n */\n doesVideoMuteByStreamRemove() {\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() {\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() {\n return !this.isReactNative() && this.getOS() === 'iOS';\n }\n\n /**\n * Checks if the client is running on a mobile device.\n */\n isMobileDevice() {\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() {\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() {\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 * @returns {boolean} true if the browser is supported for Android devices\n */\n isSupportedAndroidBrowser() {\n return this.isChromiumBased() || this.isFirefox();\n }\n\n /**\n * Returns whether the browser is supported for iOS\n * @returns {boolean} true if the browser is supported for iOS devices\n */\n isSupportedIOSBrowser() {\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() {\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 * @returns {*|boolean} 'true' if the event is supported or 'false'\n * otherwise.\n */\n supportsVideoMuteOnConnInterrupted() {\n return this.isChromiumBased() || this.isReactNative();\n }\n\n /**\n * Checks if the current browser reports upload and download bandwidth\n * statistics.\n * @return {boolean}\n */\n supportsBandwidthStatistics() {\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 * @returns {boolean}\n */\n supportsCodecPreferences() {\n return Boolean(window.RTCRtpTransceiver\n && 'setCodecPreferences' in window.RTCRtpTransceiver.prototype\n && window.RTCRtpReceiver\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\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() {\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() {\n return !this.isFirefox();\n }\n\n /**\n * Checks if the current browser support the device change event.\n * @return {boolean}\n */\n supportsDeviceChangeEvent() {\n return navigator.mediaDevices\n && typeof navigator.mediaDevices.ondevicechange !== 'undefined'\n && typeof navigator.mediaDevices.addEventListener !== 'undefined';\n }\n\n /**\n * Checks if the current browser supports the Long Tasks API that lets us observe\n * performance measurement events and be notified of tasks that take longer than\n * 50ms to execute on the main thread.\n */\n supportsPerformanceObserver() {\n return typeof window.PerformanceObserver !== 'undefined'\n && PerformanceObserver.supportedEntryTypes.indexOf('longtask') > -1;\n }\n\n /**\n * Checks if the current browser supports audio level stats on the receivers.\n */\n supportsReceiverStats() {\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\n * the ICE candidate pair.\n * @return {boolean}\n */\n supportsRTTStatistics() {\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 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() {\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 * @returns {boolean}\n */\n supportsTrackBasedStats() {\n return this.isChromiumBased() && this.isEngineVersionLessThan(112);\n }\n\n /**\n * Returns true if VP9 is supported by the client on the browser. VP9 is currently disabled on Firefox and Safari\n * because of issues with rendering. Please check https://bugzilla.mozilla.org/show_bug.cgi?id=1492500,\n * https://bugs.webkit.org/show_bug.cgi?id=231071 and https://bugs.webkit.org/show_bug.cgi?id=231074 for details.\n */\n supportsVP9() {\n return this.isChromiumBased() || this.isReactNative();\n }\n\n /**\n * Checks if the browser uses SDP munging for turning on simulcast.\n *\n * @returns {boolean}\n */\n usesSdpMungingForSimulcast() {\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 usesRidsForSimulcast() {\n return false;\n }\n\n /**\n * Checks if the browser supports getDisplayMedia.\n * @returns {boolean} {@code true} if the browser supports getDisplayMedia.\n */\n supportsGetDisplayMedia() {\n return typeof navigator.getDisplayMedia !== 'undefined'\n || (typeof navigator.mediaDevices !== 'undefined'\n && typeof navigator.mediaDevices.getDisplayMedia\n !== '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() {\n return Boolean(window.RTCRtpScriptTransform);\n }\n\n /**\n * Checks if the browser supports insertable streams, needed for E2EE.\n * @returns {boolean} {@code true} if the browser supports insertable streams.\n */\n supportsInsertableStreams() {\n if (!(typeof window.RTCRtpSender !== 'undefined'\n && 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 supportsAudioRed() {\n return Boolean(window.RTCRtpSender\n && window.RTCRtpSender.getCapabilities\n && window.RTCRtpSender.getCapabilities('audio').codecs.some(codec => codec.mimeType === 'audio/red')\n && window.RTCRtpReceiver\n && window.RTCRtpReceiver.getCapabilities\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() {\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() {\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 /**\n * Returns the version of a Safari browser.\n *\n * @returns {Number}\n */\n _getSafariVersion() {\n if (this.isSafari()) {\n return Number.parseInt(this.getVersion(), 10);\n }\n\n return -1;\n }\n\n /**\n * Returns the version of an ios browser.\n *\n * @returns {Number}\n */\n _getIOSVersion() {\n if (this.isWebKitBased()) {\n return Number.parseInt(this.getOSVersion(), 10);\n }\n\n return -1;\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(__filename);\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 return;\n }\n\n if (!isAnalyticsEnabled(options)) {\n logger.error('Cannot initialize WatchRTC when analytics or third party requests are disabled.');\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 * 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 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 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 return analytics?.watchRTCEnabled ?? false;\n}\n","import { getLogger } from '@jitsi/logger';\n\nimport {\n TYPE_OPERATIONAL,\n TYPE_PAGE,\n TYPE_TRACK,\n TYPE_UI\n} from '../../service/statistics/AnalyticsEvents';\nimport browser from '../browser';\n\nconst MAX_CACHE_SIZE = 100;\n\nconst logger = getLogger(__filename);\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 * Creates new AnalyticsAdapter instance.\n */\n constructor() {\n this.reset();\n }\n\n /**\n * Reset the state to the initial one.\n *\n * @returns {void}\n */\n reset() {\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 this.disposed = false;\n\n /**\n * The set of handlers to which events will be sent.\n * @type {Set}\n */\n this.analyticsHandlers = new Set();\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 {Array}\n */\n this.cache = [];\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 this.permanentProperties = {};\n\n /**\n * The name of the conference that this AnalyticsAdapter is associated\n * with.\n * @type {null}\n */\n this.conferenceName = '';\n\n this.addPermanentProperties({\n 'user_agent': navigator.userAgent,\n 'browser_name': browser.getName()\n });\n }\n\n /**\n * Dispose analytics. Clears all handlers.\n */\n dispose() {\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 * Sets the handlers that are going to be used to send analytics. Sends any\n * cached events.\n * @param {Array} handlers the handlers\n */\n setAnalyticsHandlers(handlers) {\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 * Set the user properties to the analytics handlers.\n *\n * @returns {void}\n */\n _setUserProperties() {\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 * 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 {Object} properties the properties to add\n */\n addPermanentProperties(properties) {\n this.permanentProperties = {\n ...this.permanentProperties,\n ...properties\n };\n\n this._setUserProperties();\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 setConferenceName(name) {\n this.conferenceName = name;\n this.addPermanentProperties({ 'conference_name': name });\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|Object} 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 {Object} properties the properties/attributes to attach to the\n * event, if eventName is a string.\n */\n sendEvent(eventName, properties = {}) {\n if (this.disposed) {\n return;\n }\n\n let event = null;\n\n if (typeof eventName === 'string') {\n event = {\n type: TYPE_OPERATIONAL,\n action: eventName,\n actionSubject: eventName,\n source: eventName,\n attributes: properties\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 * 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 _verifyRequiredFields(event) {\n if (!event) {\n return false;\n }\n\n if (!event.type) {\n event.type = TYPE_OPERATIONAL;\n }\n\n const type = event.type;\n\n if (type !== TYPE_OPERATIONAL && type !== TYPE_PAGE\n && type !== TYPE_UI && type !== TYPE_TRACK) {\n logger.error(`Unknown event type: ${type}`);\n\n return false;\n }\n\n if (type === 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 === 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 * 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 _maybeCacheEvent(event) {\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 _sendEvent(event) {\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\nexport default new AnalyticsAdapter();\n","/**\n * Provides statistics for the local stream.\n */\n\nconst logger = require('@jitsi/logger').getLogger(__filename);\n\n/**\n * Size of the webaudio analyzer buffer.\n * @type {number}\n */\nconst WEBAUDIO_ANALYZER_FFT_SIZE = 2048;\n\n/**\n * Value of the webaudio analyzer smoothing time parameter.\n * @type {number}\n */\nconst WEBAUDIO_ANALYZER_SMOOTING_TIME = 0.8;\n\nwindow.AudioContext = window.AudioContext || window.webkitAudioContext;\n\n/**\n * The audio context.\n * @type {AudioContext}\n */\nlet context = null;\n\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) {\n\n let maxVolume = 0;\n\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 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, lastLevel) {\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 parseFloat(value.toFixed(3));\n}\n\n\n/**\n * LocalStatsCollector calculates statistics for the local stream.\n *\n * @param stream the local stream\n * @param interval stats refresh interval given in ms.\n * @param callback function that receives the audio levels.\n * @constructor\n */\nexport default function LocalStatsCollector(stream, interval, callback) {\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 */\nLocalStatsCollector.prototype.start = function() {\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 */\nLocalStatsCollector.prototype.stop = function() {\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 */\nLocalStatsCollector.init = function() {\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 */\nLocalStatsCollector.isLocalStatsSupported = function() {\n return Boolean(window?.AudioContext);\n};\n\n/**\n * Disconnects the audio context.\n */\nLocalStatsCollector.disconnectAudioContext = async function() {\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 */\nLocalStatsCollector.connectAudioContext = function() {\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/**\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) {\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 am Array of numbers.\n *\n * @param {Float32Array} valueArray - Array of numbers.\n * @returns {number} - Number array average.\n */\nexport function calculateAverage(valueArray) {\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) {\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 {Array} - Array of positive numbers.\n */\nexport function filterPositiveValues(valueArray) {\n return 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 /**\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) {\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() {\n return this.average;\n }\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 is not a number.\n */\nexport function safeSubtract(x, y) {\n return !isNaN(x) && !isNaN(y) ? x - y : 0;\n}\n","\nimport { getLogger } from '@jitsi/logger';\n\nimport * as StatisticsEvents from '../../service/statistics/Events';\nimport { RunningAverage } from '../util/MathUtil';\n\nconst logger = getLogger(__filename);\nconst MILLI_SECONDS = 1000;\nconst SECONDS = 60;\n\n/**\n * This class creates an observer that monitors browser's performance measurement events\n * as they are recorded in the browser's performance timeline and computes an average and\n * a maximum value for the long task events. Tasks are classified as long tasks if they take\n * longer than 50ms to execute on the main thread.\n */\nexport class PerformanceObserverStats {\n /**\n * Creates a new instance of Performance observer statistics.\n *\n * @param {*} emitter Event emitter for emitting stats periodically\n * @param {*} statsInterval interval for calculating the stats\n */\n constructor(emitter, statsInterval) {\n this.eventEmitter = emitter;\n this.longTasks = 0;\n this.maxDuration = 0;\n this.performanceStatsInterval = statsInterval;\n this.stats = new RunningAverage();\n }\n\n /**\n * Obtains the average rate of long tasks observed per min and the\n * duration of the longest task recorded by the observer.\n * @returns {Object}\n */\n getLongTasksStats() {\n return {\n avgRatePerMinute: (this.stats.getAverage() * SECONDS).toFixed(2), // calc rate per min\n maxDurationMs: this.maxDuration\n };\n }\n\n /**\n * Starts the performance observer by registering the callback function\n * that calculates the performance statistics periodically.\n * @returns {void}\n */\n startObserver() {\n // Create a handler for when the long task event is fired.\n this.longTaskEventHandler = list => {\n const entries = list.getEntries();\n\n for (const task of entries) {\n this.longTasks++;\n this.maxDuration = Math.max(this.maxDuration, task.duration).toFixed(3);\n }\n };\n\n // Create an observer for monitoring long tasks.\n logger.info('Creating a Performance Observer for monitoring Long Tasks');\n this.observer = new PerformanceObserver(this.longTaskEventHandler);\n this.observer.observe({ type: 'longtask',\n buffered: true });\n const startTime = Date.now();\n\n // Calculate the average # of events/sec and emit a stats event.\n this.longTasksIntervalId = setInterval(() => {\n const now = Date.now();\n const interval = this._lastTimeStamp\n ? (now - this._lastTimeStamp) / MILLI_SECONDS\n : (now - startTime) / MILLI_SECONDS;\n const rate = this.longTasks / interval;\n\n this.stats.addNext(rate);\n this.eventEmitter.emit(\n StatisticsEvents.LONG_TASKS_STATS, this.getLongTasksStats());\n\n // Reset the counter and start counting events again.\n this.longTasks = 0;\n this._lastTimeStamp = Date.now();\n }, this.performanceStatsInterval);\n }\n\n /**\n * Stops the performance observer.\n * @returns {void}\n */\n stopObserver() {\n this.observer && this.observer.disconnect();\n this.longTaskEventHandler = null;\n if (this.longTasksIntervalId) {\n clearInterval(this.longTasksIntervalId);\n this.longTasksIntervalId = null;\n }\n }\n}\n","export enum MediaType {\n /**\n * The audio type.\n */\n AUDIO = 'audio',\n\n /**\n * The video type.\n */\n VIDEO = 'video'\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 \n /**\n * Configures the module.\n *\n * @param {object} flags - The feature flags.\n * @param {boolean=} flags.runInLiteMode - Enables lite mode for testing to disable media decoding.\n * @param {boolean=} flags.ssrcRewritingEnabled - Use SSRC rewriting.\n */\n init(flags: { runInLiteMode?: boolean | undefined; ssrcRewritingEnabled?: boolean | undefined; }) {\n this._runInLiteMode = Boolean(flags.runInLiteMode);\n this._ssrcRewriting = Boolean(flags.ssrcRewritingEnabled);\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","import { getLogger } from '@jitsi/logger';\n\nimport { MediaType } from '../../service/RTC/MediaType';\nimport * as StatisticsEvents from '../../service/statistics/Events';\nimport browser from '../browser';\nimport FeatureFlags from '../flags/FeatureFlags';\n\nconst logger = getLogger(__filename);\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 * @constructor\n */\nfunction SsrcStats() {\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 */\nSsrcStats.prototype.setLoss = function(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 */\nSsrcStats.prototype.setResolution = function(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 */\nSsrcStats.prototype.addBitrate = function(bitrate) {\n this.bitrate.download += bitrate.download;\n this.bitrate.upload += bitrate.upload;\n};\n\n/**\n * Resets the bit rate for given ssrc that belong to the peer\n * represented by this instance.\n */\nSsrcStats.prototype.resetBitrate = function() {\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 */\nSsrcStats.prototype.setFramerate = function(framerate) {\n this.framerate = framerate || 0;\n};\n\nSsrcStats.prototype.setCodec = function(codec) {\n this.codec = codec || '';\n};\n\nSsrcStats.prototype.setEncodeStats = function(encodeStats) {\n this.encodeStats = encodeStats || {};\n};\n\n/**\n *\n */\nfunction ConferenceStats() {\n\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/* eslint-disable max-params */\n\n/**\n * StatsCollector registers for stats updates of given\n * peerconnection in given interval. On each update particular\n * stats are extracted and put in {@link SsrcStats} objects. Once the processing\n * is done audioLevelsUpdateCallback is called with this\n * instance as an event source.\n *\n * @param peerconnection WebRTC PeerConnection object.\n * @param audioLevelsInterval\n * @param statsInterval stats refresh interval given in ms.\n * @param eventEmitter\n * @constructor\n */\nexport default function StatsCollector(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} speakerList - Endpoint ids.\n * @returns {void}\n */\nStatsCollector.prototype.setSpeakerList = function(speakerList) {\n this.speakerList = speakerList;\n};\n\n/**\n * Stops stats updates.\n */\nStatsCollector.prototype.stop = function() {\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 getStats method.\n * @param error an error that occurred on getStats call.\n */\nStatsCollector.prototype.errorCallback = function(error) {\n logger.error('Get stats error', error);\n this.stop();\n};\n\n/**\n * Starts stats updates.\n */\nStatsCollector.prototype.start = function(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 *\n */\nStatsCollector.prototype._processAndEmitReport = function() {\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 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 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; // eslint-disable-line no-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 || isNaN(resolution?.height)\n || isNaN(resolution?.width)\n || resolution.height === -1\n || resolution.width === -1) {\n continue; // eslint-disable-line no-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 upload: bitrateUpload,\n download: bitrateDownload\n };\n\n this.conferenceStats.bitrate.audio = {\n upload: audioBitrateUpload,\n download: audioBitrateDownload\n };\n\n this.conferenceStats.bitrate.video = {\n upload: videoBitrateUpload,\n download: videoBitrateDownload\n };\n\n this.conferenceStats.packetLoss = {\n total:\n calculatePacketLoss(\n lostPackets.download + lostPackets.upload,\n totalPackets.download + totalPackets.upload),\n download:\n calculatePacketLoss(lostPackets.download, totalPackets.download),\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 packetLoss: this.conferenceStats.packetLoss,\n resolution: resolutions,\n framerate: framerates,\n codec: codecs,\n transport: this.conferenceStats.transport\n });\n this.conferenceStats.transport = [];\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 */\nStatsCollector.prototype.getNonNegativeValue = function(v) {\n let value = v;\n\n if (typeof value !== 'number') {\n value = Number(value);\n }\n\n if (isNaN(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 */\nStatsCollector.prototype._calculateBitrate = function(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 */\nStatsCollector.prototype._calculateFps = function(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 */\nStatsCollector.prototype.processStatsReport = function() {\n const byteSentStats = {};\n const encodedTimeStatsPerSsrc = 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 type,\n localip,\n p2p: this.peerconnection.isP2P,\n localCandidateType: localUsedCandidate.candidateType,\n remoteCandidateType: remoteUsedCandidate.candidateType,\n networkType: localUsedCandidate.networkType,\n rtt: now.currentRoundTripTime * 1000\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 (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 packetsTotal: packetsDiff + packetsLostDiff,\n packetsLost: packetsLostDiff,\n isDownloadStream\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 } else if (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 && this.peerconnection.usesCodecSelectionAPI()\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 this._processAndEmitReport();\n};\n","import * as JitsiConferenceEvents from '../../JitsiConferenceEvents';\nimport { JitsiTrackEvents } from '../../JitsiTrackEvents';\nimport { FEEDBACK } from '../../service/statistics/AnalyticsEvents';\nimport * as StatisticsEvents from '../../service/statistics/Events';\nimport RTCStats from '../RTCStats/RTCStats';\nimport browser from '../browser';\nimport EventEmitter from '../util/EventEmitter';\nimport WatchRTC from '../watchRTC/WatchRTC';\n\nimport analytics from './AnalyticsAdapter';\nimport LocalStats from './LocalStatsCollector';\nimport { PerformanceObserverStats } from './PerformanceObserverStats';\nimport RTPStats from './RTPStatsCollector';\n\nconst logger = require('@jitsi/logger').getLogger(__filename);\n\n/**\n * Stores all active {@link Statistics} instances.\n * @type {Set}\n */\nlet _instances;\n\n/**\n * Init statistic options\n * @param options\n */\nStatistics.init = function(options) {\n Statistics.audioLevelsEnabled = !options.disableAudioLevels;\n if (typeof options.pcStatsInterval === 'number') {\n Statistics.pcStatsInterval = options.pcStatsInterval;\n }\n\n if (typeof options.audioLevelsInterval === 'number') {\n Statistics.audioLevelsInterval = options.audioLevelsInterval;\n }\n\n if (typeof options.longTasksStatsInterval === 'number') {\n Statistics.longTasksStatsInterval = options.longTasksStatsInterval;\n }\n\n Statistics.disableThirdPartyRequests = options.disableThirdPartyRequests;\n\n LocalStats.init();\n WatchRTC.init(options);\n RTCStats.init(options);\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 */\nexport default function Statistics(conference, options) {\n /**\n * {@link RTPStats} mapped by {@link TraceablePeerConnection.id} which\n * collect RTP statistics for each peerconnection.\n * @type {Map}\n */\n get() {\n if (!_instances) {\n _instances = new Set();\n }\n\n return _instances;\n }\n});\n\n/**\n * Starts collecting RTP stats for given peerconnection.\n * @param {TraceablePeerConnection} peerconnection\n */\nStatistics.prototype.startRemoteStats = function(peerconnection) {\n this.stopRemoteStats(peerconnection);\n\n try {\n const rtpStats\n = new RTPStats(\n peerconnection,\n Statistics.audioLevelsInterval,\n Statistics.pcStatsInterval,\n this.eventEmitter);\n\n rtpStats.start(Statistics.audioLevelsEnabled);\n this.rtpStatsMap.set(peerconnection.id, rtpStats);\n } catch (e) {\n logger.error(`Failed to start collecting remote statistics: ${e}`);\n }\n};\n\nStatistics.localStats = [];\n\nStatistics.startLocalStats = function(track, callback) {\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 /**\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 => {\n if (value) {\n for (const localStat of Statistics.localStats) {\n localStat.stop();\n }\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\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,\n callback);\n\n this.localStats.push(localStats);\n localStats.start();\n};\n\nStatistics.prototype.addAudioLevelListener = function(listener) {\n if (!Statistics.audioLevelsEnabled) {\n return;\n }\n this.eventEmitter.on(StatisticsEvents.AUDIO_LEVEL, listener);\n};\n\nStatistics.prototype.removeAudioLevelListener = function(listener) {\n if (!Statistics.audioLevelsEnabled) {\n return;\n }\n this.eventEmitter.removeListener(StatisticsEvents.AUDIO_LEVEL, listener);\n};\n\nStatistics.prototype.addBeforeDisposedListener = function(listener) {\n this.eventEmitter.on(StatisticsEvents.BEFORE_DISPOSED, listener);\n};\n\nStatistics.prototype.removeBeforeDisposedListener = function(listener) {\n this.eventEmitter.removeListener(\n StatisticsEvents.BEFORE_DISPOSED, listener);\n};\n\nStatistics.prototype.addConnectionStatsListener = function(listener) {\n this.eventEmitter.on(StatisticsEvents.CONNECTION_STATS, listener);\n};\n\nStatistics.prototype.removeConnectionStatsListener = function(listener) {\n this.eventEmitter.removeListener(\n StatisticsEvents.CONNECTION_STATS,\n listener);\n};\n\nStatistics.prototype.addEncodeTimeStatsListener = function(listener) {\n this.eventEmitter.on(StatisticsEvents.ENCODE_TIME_STATS, listener);\n};\n\nStatistics.prototype.removeEncodeTimeStatsListener = function(listener) {\n this.eventEmitter.removeListener(StatisticsEvents.ENCODE_TIME_STATS, listener);\n};\n\nStatistics.prototype.addByteSentStatsListener = function(listener) {\n this.eventEmitter.on(StatisticsEvents.BYTE_SENT_STATS, listener);\n};\n\nStatistics.prototype.removeByteSentStatsListener = function(listener) {\n this.eventEmitter.removeListener(StatisticsEvents.BYTE_SENT_STATS,\n listener);\n};\n\n/**\n * Add a listener that would be notified on a LONG_TASKS_STATS event.\n *\n * @param {Function} listener a function that would be called when notified.\n * @returns {void}\n */\nStatistics.prototype.addLongTasksStatsListener = function(listener) {\n this.eventEmitter.on(StatisticsEvents.LONG_TASKS_STATS, listener);\n};\n\n/**\n * Creates an instance of {@link PerformanceObserverStats} and starts the\n * observer that records the stats periodically.\n *\n * @returns {void}\n */\nStatistics.prototype.attachLongTasksStats = function() {\n if (!browser.supportsPerformanceObserver()) {\n logger.warn('Performance observer for long tasks not supported by browser!');\n\n return;\n }\n\n this.performanceObserverStats = new PerformanceObserverStats(\n this.eventEmitter,\n Statistics.longTasksStatsInterval);\n\n this.conference.on(\n JitsiConferenceEvents.CONFERENCE_JOINED,\n () => this.performanceObserverStats.startObserver());\n this.conference.on(\n JitsiConferenceEvents.CONFERENCE_LEFT,\n () => this.performanceObserverStats.stopObserver());\n};\n\n/**\n * Obtains the current value of the LongTasks event statistics.\n *\n * @returns {Object|null} stats object if the observer has been\n * created, null otherwise.\n */\nStatistics.prototype.getLongTasksStats = function() {\n return this.performanceObserverStats\n ? this.performanceObserverStats.getLongTasksStats()\n : null;\n};\n\n/**\n * Removes the given listener for the LONG_TASKS_STATS event.\n *\n * @param {Function} listener the listener we want to remove.\n * @returns {void}\n */\nStatistics.prototype.removeLongTasksStatsListener = function(listener) {\n this.eventEmitter.removeListener(StatisticsEvents.LONG_TASKS_STATS, 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} speakerList The list of remote endpoint ids.\n * @returns {void}\n */\nStatistics.prototype.setSpeakerList = function(speakerList) {\n for (const rtpStats of Array.from(this.rtpStatsMap.values())) {\n if (!rtpStats.peerconnection.isP2P) {\n rtpStats.setSpeakerList(speakerList);\n }\n }\n};\n\nStatistics.prototype.dispose = function() {\n try {\n this.eventEmitter.emit(StatisticsEvents.BEFORE_DISPOSED);\n\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\nStatistics.stopLocalStats = function(track) {\n if (!Statistics.audioLevelsEnabled) {\n return;\n }\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 * Stops remote RTP stats for given peerconnection ID.\n * @param {string} tpcId {@link TraceablePeerConnection.id}\n * @private\n */\nStatistics.prototype._stopRemoteStats = function(tpcId) {\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 */\nStatistics.prototype.stopRemoteStats = function(tpc) {\n this._stopRemoteStats(tpc.id);\n};\n\n/**\n * Sends the given feedback\n *\n * @param overall an integer between 1 and 5 indicating the user's rating.\n * @param comment the comment from the user.\n * @returns {Promise} Resolves immediately.\n */\nStatistics.prototype.sendFeedback = function(overall, comment) {\n // Statistics.analytics.sendEvent is currently fire and forget, without\n // confirmation of successful send.\n Statistics.analytics.sendEvent(\n FEEDBACK,\n {\n rating: overall,\n comment\n });\n\n return Promise.resolve();\n};\n\nStatistics.LOCAL_JID = require('../../service/statistics/constants').LOCAL_JID;\n\n/**\n * Sends event to analytics and logs a message to the logger/console.\n *\n * @param {string | Object} event the event name, or an object which\n * represents the entire event.\n * @param {Object} properties properties to attach to the event (if an event\n * name as opposed to an event object is provided).\n */\nStatistics.sendAnalyticsAndLog = function(event, properties = {}) {\n if (!event) {\n logger.warn('No event or event name given.');\n\n return;\n }\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\n logger.log(JSON.stringify(eventToLog));\n\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 *\n * @param {string | Object} eventName the event name, or an object which\n * represents the entire event.\n * @param {Object} properties properties to attach to the event\n */\nStatistics.sendAnalytics = function(eventName, properties = {}) {\n this.analytics.sendEvent(eventName, properties);\n};\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;\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","import { getLogger } from '@jitsi/logger';\nimport { Strophe } from 'strophe.js';\n\nimport * as JitsiConferenceErrors from './JitsiConferenceErrors';\nimport * as JitsiConferenceEvents from './JitsiConferenceEvents';\nimport * as JitsiTrackEvents from './JitsiTrackEvents';\nimport { SPEAKERS_AUDIO_LEVELS } from './modules/statistics/constants';\nimport Statistics from './modules/statistics/statistics';\nimport EventEmitterForwarder from './modules/util/EventEmitterForwarder';\nimport { MediaType } from './service/RTC/MediaType';\nimport RTCEvents from './service/RTC/RTCEvents';\nimport AuthenticationEvents\n from './service/authentication/AuthenticationEvents';\nimport {\n ACTION_JINGLE_SA_TIMEOUT,\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(__filename);\n\n/**\n * Setups all event listeners related to conference\n * @param conference {JitsiConference} the conference\n */\nexport default function JitsiConferenceEventManager(conference) {\n this.conference = conference;\n this.xmppListeners = {};\n}\n\n/**\n * Setups event listeners related to conference.chatRoom\n */\nJitsiConferenceEventManager.prototype.setupChatRoomListeners = function() {\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.ICE_RESTARTING, jingleSession => {\n if (!jingleSession.isP2P) {\n // If using DataChannel as bridge channel, it must be closed\n // before ICE restart, otherwise Chrome will not trigger \"opened\"\n // event for the channel established with the new bridge.\n // TODO: This may be bypassed when using a WebSocket as bridge\n // channel.\n conference.rtc.closeBridgeChannel();\n }\n\n // else: there are no DataChannels in P2P session (at least for now)\n });\n\n chatRoom.addListener(XMPPEvents.PARTICIPANT_FEATURES_CHANGED, (from, features) => {\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 chatRoom.addListener(\n XMPPEvents.ICE_RESTART_SUCCESS,\n (jingleSession, offerIq) => {\n // The JVB data chanel needs to be reopened in case the conference\n // has been moved to a new bridge.\n !jingleSession.isP2P\n && conference._setBridgeChannel(\n offerIq, jingleSession.peerconnection);\n });\n\n\n chatRoom.addListener(XMPPEvents.AUDIO_MUTED_BY_FOCUS,\n actor => {\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(true).then(\n () => {\n conference.isMutedByFocus = true;\n conference.mutedByFocusActor = null;\n })\n .catch(\n 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 => {\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(true).then(\n () => {\n conference.isVideoMutedByFocus = true;\n conference.mutedVideoByFocusActor = null;\n })\n .catch(\n error => {\n conference.mutedVideoByFocusActor = null;\n logger.warn(\n 'Error while 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(XMPPEvents.RENEGOTIATION_FAILED, (e, session) => {\n if (!session.isP2P) {\n conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_FAILED,\n JitsiConferenceErrors.OFFER_ANSWER_FAILED, e);\n }\n });\n\n chatRoom.addListener(JitsiTrackEvents.TRACK_OWNER_SET, (track, owner, sourceName, 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 owner && conference.eventEmitter.emit(JitsiConferenceEvents.TRACK_ADDED, track);\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 chatRoom.addListener(XMPPEvents.CONNECTION_RESTARTED,\n jingleSession => {\n conference._onConferenceRestarted(jingleSession);\n });\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 => {\n Statistics.sendAnalyticsAndLog(\n createJingleEvent(\n ACTION_JINGLE_SA_TIMEOUT,\n { p2p: jingleSession.isP2P }));\n });\n\n chatRoom.addListener(XMPPEvents.RECORDER_STATE_CHANGED,\n (session, jid) => {\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((node, from) => {\n const participant = conference.getParticipantById(from);\n\n if (!participant) {\n return;\n }\n\n participant.setProperty(\n node.tagName.substring('jitsi_participant_'.length),\n node.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 => {\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, authIdentity) => {\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, txt, myJid, ts, nick, isGuest, messageId) => {\n const participantId = Strophe.getResourceFromJid(jid);\n\n conference.eventEmitter.emit(\n JitsiConferenceEvents.MESSAGE_RECEIVED,\n participantId, txt, ts, nick, isGuest, messageId);\n });\n\n chatRoom.addListener(\n XMPPEvents.REACTION_RECEIVED,\n\n (jid, reactionList, messageId) => {\n\n conference.eventEmitter.emit(\n JitsiConferenceEvents.REACTION_RECEIVED,\n jid, reactionList, messageId);\n });\n\n chatRoom.addListener(\n XMPPEvents.PRIVATE_MESSAGE_RECEIVED,\n\n // eslint-disable-next-line max-params\n (jid, txt, myJid, ts, messageId) => {\n const participantId = Strophe.getResourceFromJid(jid);\n\n conference.eventEmitter.emit(\n JitsiConferenceEvents.PRIVATE_MESSAGE_RECEIVED,\n participantId, txt, ts, messageId);\n });\n\n chatRoom.addListener(XMPPEvents.PRESENCE_STATUS,\n (jid, status) => {\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, payload) => {\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 chatRoom.addPresenceListener('startmuted', (data, from) => {\n // Ignore the strartmuted policy if the presence is received from self. The moderator should join with\n // available local sources and the policy needs to be applied only on users that join the call after.\n if (conference.myUserId() === from) {\n return;\n }\n const participant = conference.getParticipantById(from);\n\n if (!participant || !participant.isModerator()) {\n return;\n }\n const startAudioMuted = data.attributes.audio === 'true';\n const startVideoMuted = data.attributes.video === 'true';\n\n let updated = false;\n\n if (startAudioMuted !== conference.startMutedPolicy.audio) {\n conference.startMutedPolicy.audio = startAudioMuted;\n updated = true;\n }\n\n if (startVideoMuted !== conference.startMutedPolicy.video) {\n conference.startMutedPolicy.video = startVideoMuted;\n updated = true;\n }\n\n if (updated) {\n conference.eventEmitter.emit(\n JitsiConferenceEvents.START_MUTED_POLICY_CHANGED,\n conference.startMutedPolicy\n );\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 // Room metadata.\n this.chatRoomForwarder.forward(XMPPEvents.ROOM_METADATA_UPDATED,\n JitsiConferenceEvents.METADATA_UPDATED);\n};\n\n/**\n * Setups event listeners related to conference.rtc\n */\nJitsiConferenceEventManager.prototype.setupRTCListeners = function() {\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, previous, silence) => {\n if ((conference.lastDominantSpeaker !== dominant || conference.dominantSpeakerIsSilent !== silence)\n && conference.room) {\n conference.lastDominantSpeaker = dominant;\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 }\n if (conference.lastDominantSpeaker !== dominant) {\n if (previous && 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 && 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.log(`(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 => {\n conference.eventEmitter.emit(JitsiConferenceEvents.DATA_CHANNEL_CLOSED, ev);\n });\n\n rtc.addListener(RTCEvents.VIDEO_SSRCS_REMAPPED, msg => {\n this.conference.jvbJingleSession.processSourceMap(msg, MediaType.VIDEO);\n });\n\n rtc.addListener(RTCEvents.AUDIO_SSRCS_REMAPPED, msg => {\n this.conference.jvbJingleSession.processSourceMap(msg, MediaType.AUDIO);\n });\n\n rtc.addListener(RTCEvents.ENDPOINT_MESSAGE_RECEIVED,\n (from, payload) => {\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, payload) => {\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 rtc.addListener(RTCEvents.CREATE_ANSWER_FAILED,\n (e, tpc) => {\n if (!tpc.isP2P) {\n conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_FAILED,\n JitsiConferenceErrors.OFFER_ANSWER_FAILED, e);\n }\n });\n\n rtc.addListener(RTCEvents.CREATE_OFFER_FAILED,\n (e, tpc) => {\n if (!tpc.isP2P) {\n conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_FAILED,\n JitsiConferenceErrors.OFFER_ANSWER_FAILED, e);\n }\n });\n\n rtc.addListener(RTCEvents.SET_LOCAL_DESCRIPTION_FAILED,\n (e, tpc) => {\n if (!tpc.isP2P) {\n conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_FAILED,\n JitsiConferenceErrors.OFFER_ANSWER_FAILED, e);\n }\n });\n\n rtc.addListener(RTCEvents.SET_REMOTE_DESCRIPTION_FAILED,\n (e, tpc) => {\n if (!tpc.isP2P) {\n conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_FAILED,\n JitsiConferenceErrors.OFFER_ANSWER_FAILED, e);\n }\n });\n};\n\n/**\n * Removes event listeners related to conference.xmpp\n */\nJitsiConferenceEventManager.prototype.removeXMPPListeners = function() {\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/**\n * Setups event listeners related to conference.xmpp\n */\nJitsiConferenceEventManager.prototype.setupXMPPListeners = function() {\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.START_MUTED_FROM_FOCUS,\n (audioMuted, videoMuted) => {\n if (conference.options.config.ignoreStartMuted) {\n return;\n }\n\n conference.startAudioMuted = audioMuted;\n conference.startVideoMuted = videoMuted;\n\n if (audioMuted) {\n conference.isMutedByFocus = true;\n }\n\n if (videoMuted) {\n conference.isVideoMutedByFocus = true;\n }\n\n // mute existing local tracks because this is initial mute from\n // Jicofo\n conference.getLocalTracks().forEach(track => {\n switch (track.getType()) {\n case MediaType.AUDIO:\n conference.startAudioMuted && track.mute();\n break;\n case MediaType.VIDEO:\n conference.startVideoMuted && track.mute();\n break;\n }\n });\n\n conference.eventEmitter.emit(JitsiConferenceEvents.STARTED_MUTED);\n });\n\n this._addConferenceXMPPListener(XMPPEvents.AV_MODERATION_CHANGED,\n (value, mediaType, actorJid) => {\n const actorParticipant = conference.getParticipants().find(p => p.getJid() === actorJid);\n\n conference.eventEmitter.emit(JitsiConferenceEvents.AV_MODERATION_CHANGED, {\n enabled: value,\n mediaType,\n actor: actorParticipant\n });\n });\n this._addConferenceXMPPListener(XMPPEvents.AV_MODERATION_PARTICIPANT_APPROVED,\n (mediaType, jid) => {\n const participant = conference.getParticipantById(Strophe.getResourceFromJid(jid));\n\n if (participant) {\n conference.eventEmitter.emit(JitsiConferenceEvents.AV_MODERATION_PARTICIPANT_APPROVED, {\n participant,\n mediaType\n });\n }\n });\n this._addConferenceXMPPListener(XMPPEvents.AV_MODERATION_PARTICIPANT_REJECTED,\n (mediaType, jid) => {\n const participant = conference.getParticipantById(Strophe.getResourceFromJid(jid));\n\n if (participant) {\n conference.eventEmitter.emit(JitsiConferenceEvents.AV_MODERATION_PARTICIPANT_REJECTED, {\n participant,\n mediaType\n });\n }\n });\n this._addConferenceXMPPListener(XMPPEvents.AV_MODERATION_APPROVED,\n value => conference.eventEmitter.emit(JitsiConferenceEvents.AV_MODERATION_APPROVED, { mediaType: value }));\n this._addConferenceXMPPListener(XMPPEvents.AV_MODERATION_REJECTED,\n value => {\n conference.eventEmitter.emit(JitsiConferenceEvents.AV_MODERATION_REJECTED, { mediaType: value });\n });\n\n this._addConferenceXMPPListener(XMPPEvents.VISITORS_MESSAGE,\n value => conference.eventEmitter.emit(JitsiConferenceEvents.VISITORS_MESSAGE, value));\n this._addConferenceXMPPListener(XMPPEvents.VISITORS_REJECTION,\n () => conference.eventEmitter.emit(JitsiConferenceEvents.VISITORS_REJECTION));\n};\n\n/**\n * Add XMPP listener and save its reference for remove on leave conference.\n */\nJitsiConferenceEventManager.prototype._addConferenceXMPPListener = function(\n eventName, listener) {\n this.xmppListeners[eventName] = listener;\n this.conference.xmpp.addListener(eventName, listener);\n};\n\n/**\n * Setups event listeners related to conference.statistics\n */\nJitsiConferenceEventManager.prototype.setupStatisticsListeners = function() {\n const conference = this.conference;\n\n if (!conference.statistics) {\n return;\n }\n\n /* eslint-disable max-params */\n conference.statistics.addAudioLevelListener((tpc, ssrc, level, isLocal) => {\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, stats) => {\n conference.eventEmitter.emit(\n JitsiConferenceEvents.ENCODE_TIME_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, stats) => {\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 * 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 = 5;\n","\nimport { Strophe } from 'strophe.js';\n\n\nimport * as JitsiConferenceEvents from './JitsiConferenceEvents';\nimport { MediaType } from './service/RTC/MediaType';\n\n/**\n * Represents a participant in (i.e. a member of) a conference.\n */\nexport default class JitsiParticipant {\n\n /* eslint-disable max-params */\n\n /**\n * Initializes a new JitsiParticipant instance.\n *\n * @constructor\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(jid, conference, displayName, hidden, statsID, status, identity, isReplacing, isReplaced, isSilent) {\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 = {};\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>\n *\n * mediaType - 'audio' or 'video'.\n * sourceName - name of the remote source.\n * sourceInfo: {\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) {\n return this.getTracks().reduce(\n (muted, track) =>\n muted && (track.getType() !== mediaType || track.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 {string} sourceName The name of the source.\n * @param {string} videoType The video type of the source.\n * @returns {void}\n */\n _setSources(mediaType, muted, sourceName, videoType) {\n let sourceByMediaType = this._sources.get(mediaType);\n const sourceInfo = {\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 {string|undefined} - The bot type of the participant.\n */\n getBotType() {\n return this._botType;\n }\n\n /**\n * @returns {JitsiConference} The conference that this participant belongs\n * to.\n */\n getConference() {\n return this._conference;\n }\n\n /**\n * Returns the connection jid for the participant.\n *\n * @returns {string|undefined} - The connection jid of the participant.\n */\n getConnectionJid() {\n return this._connectionJid;\n }\n\n /**\n * @returns {String} The human-readable display name of this participant.\n */\n getDisplayName() {\n return this._displayName;\n }\n\n /**\n * Returns a set with the features for the participant.\n * @returns {Promise>}\n */\n getFeatures() {\n return Promise.resolve(this._features);\n }\n\n /**\n * @returns {String} The ID of this participant.\n */\n getId() {\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 {object|undefined} - XMPP user identity.\n */\n getIdentity() {\n return this._identity;\n }\n\n /**\n * @returns {String} The JID of this participant.\n */\n getJid() {\n return this._jid;\n }\n\n /**\n * Gets the value of a property of this participant.\n */\n getProperty(name) {\n return this._properties[name];\n }\n\n /**\n * @returns {String} The role of this participant.\n */\n getRole() {\n return this._role;\n }\n\n /**\n * Returns the sources associated with this participant.\n * @returns Map>\n */\n getSources() {\n return this._sources;\n }\n\n /**\n * @returns {String} The stats ID of this participant.\n */\n getStatsID() {\n return this._statsID;\n }\n\n /**\n * @returns {String} The status of the participant.\n */\n getStatus() {\n return this._status;\n }\n\n /**\n * @returns {Array.} The list of media tracks for this\n * participant.\n */\n getTracks() {\n return this._tracks.slice();\n }\n\n /**\n * @param {MediaType} mediaType\n * @returns {Array.} an array of media tracks for this\n * participant, for given media type.\n */\n getTracksByMediaType(mediaType) {\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} true if this participant contains the\n * feature.\n */\n hasFeature(feature) {\n return this._features.has(feature);\n }\n\n /**\n * @returns {Boolean} Whether this participant has muted their audio.\n */\n isAudioMuted() {\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() {\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() {\n return this._identity?.user?.['hidden-from-recorder'] === 'true';\n }\n\n /**\n * @returns {Boolean} Whether this participant is a moderator or not.\n */\n isModerator() {\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() {\n return this._isReplaced;\n }\n\n /**\n * @returns {Boolean} Whether this participant replaces another participant\n * from the meeting.\n */\n isReplacing() {\n return this._isReplacing;\n }\n\n /**\n * @returns {Boolean} Whether this participant has joined without audio.\n */\n isSilent() {\n return this._isSilent;\n }\n\n /**\n * @returns {Boolean} Whether this participant has muted their video.\n */\n isVideoMuted() {\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) {\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) {\n this._connectionJid = newJid;\n }\n\n /**\n * Set new features.\n * @param {Set|undefined} newFeatures - Sets new features.\n */\n setFeatures(newFeatures) {\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) {\n this._isReplaced = newIsReplaced;\n }\n\n /**\n * Sets whether participant is replacing another based on jwt.\n * @param {String} newIsReplacing - whether is replacing.\n */\n setIsReplacing(newIsReplacing) {\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) {\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 * @name the name of the property.\n * @value the value to set.\n */\n setProperty(name, value) {\n const oldValue = this._properties[name];\n\n if (value !== oldValue) {\n this._properties[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) {\n this._role = newRole;\n }\n\n /**\n *\n */\n supportsDTMF() {\n return this._supportsDTMF;\n }\n}\n","/**\n * The errors for the JitsiTrack objects.\n */\n\nexport enum JitsiTrackErrors {\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 * 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 requested video resolution is not supported\n * by a webcam.\n */\n UNSUPPORTED_RESOLUTION = 'gum.unsupported_resolution',\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 no tracks were found in the media stream\n */\n TRACK_NO_STREAM_TRACKS_FOUND = 'track.no_stream_tracks_found',\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_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\nconst TRACK_ERROR_TO_MESSAGE_MAP = {};\n\nTRACK_ERROR_TO_MESSAGE_MAP[JitsiTrackErrors.UNSUPPORTED_RESOLUTION]\n = 'Video resolution is not supported: ';\nTRACK_ERROR_TO_MESSAGE_MAP[JitsiTrackErrors.SCREENSHARING_USER_CANCELED]\n = 'User canceled screen sharing prompt';\nTRACK_ERROR_TO_MESSAGE_MAP[JitsiTrackErrors.SCREENSHARING_GENERIC_ERROR]\n = 'Unknown error from screensharing';\nTRACK_ERROR_TO_MESSAGE_MAP[JitsiTrackErrors.ELECTRON_DESKTOP_PICKER_ERROR]\n = 'Unkown error from desktop picker';\nTRACK_ERROR_TO_MESSAGE_MAP[JitsiTrackErrors.ELECTRON_DESKTOP_PICKER_NOT_FOUND]\n = 'Failed to detect desktop picker';\nTRACK_ERROR_TO_MESSAGE_MAP[JitsiTrackErrors.GENERAL]\n = 'Generic getUserMedia error';\nTRACK_ERROR_TO_MESSAGE_MAP[JitsiTrackErrors.PERMISSION_DENIED]\n = 'User denied permission to use device(s): ';\nTRACK_ERROR_TO_MESSAGE_MAP[JitsiTrackErrors.NOT_FOUND]\n = 'Requested device(s) was/were not found: ';\nTRACK_ERROR_TO_MESSAGE_MAP[JitsiTrackErrors.CONSTRAINT_FAILED]\n = 'Constraint could not be satisfied: ';\nTRACK_ERROR_TO_MESSAGE_MAP[JitsiTrackErrors.TIMEOUT]\n = 'Could not start media source. Timeout occured!';\nTRACK_ERROR_TO_MESSAGE_MAP[JitsiTrackErrors.TRACK_IS_DISPOSED]\n = 'Track has been already disposed';\nTRACK_ERROR_TO_MESSAGE_MAP[JitsiTrackErrors.TRACK_NO_STREAM_FOUND]\n = 'Track does not have an associated Media Stream';\n\n// FIXME: Using prototype inheritance because otherwise instanceof is not\n// working properly (see https://github.com/babel/babel/issues/3083)\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 *\n * @extends Error\n *\n *\n * @constructor\n * @param {Object|string} error - error object or error name\n * @param {Object|string} (options) - getUserMedia constraints object or\n * error message\n * @param {('audio'|'video'|'desktop'|'screen'|'audiooutput')[]} (devices) -\n * list of getUserMedia requested devices\n */\nfunction JitsiTrackError(error, options, devices) {\n if (typeof error === 'object' && typeof error.name !== 'undefined') {\n /**\n * Additional information about original getUserMedia error\n * and constraints.\n * @type {{\n * error: Object,\n * constraints: Object,\n * devices: Array.<'audio'|'video'|'desktop'|'screen'>\n * }}\n */\n this.gum = {\n error,\n constraints: options,\n devices: devices && Array.isArray(devices)\n ? devices.slice(0)\n : undefined\n };\n\n switch (error.name) {\n case 'NotAllowedError':\n case 'PermissionDeniedError':\n case 'SecurityError':\n this.name = JitsiTrackErrors.PERMISSION_DENIED;\n this.message\n = TRACK_ERROR_TO_MESSAGE_MAP[this.name]\n + (this.gum.devices || []).join(', ');\n break;\n case 'DevicesNotFoundError':\n case 'NotFoundError':\n this.name = JitsiTrackErrors.NOT_FOUND;\n this.message\n = TRACK_ERROR_TO_MESSAGE_MAP[this.name]\n + (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 (options\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\n = TRACK_ERROR_TO_MESSAGE_MAP[this.name]\n + getResolutionFromFailedConstraint(\n constraintName,\n options);\n } else {\n this.name = JitsiTrackErrors.CONSTRAINT_FAILED;\n this.message\n = TRACK_ERROR_TO_MESSAGE_MAP[this.name]\n + error.constraintName;\n }\n break;\n }\n\n default:\n this.name = JitsiTrackErrors.GENERAL;\n this.message\n = 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 = 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 = error.stack || new Error().stack;\n}\n\nJitsiTrackError.prototype = Object.create(Error.prototype);\nJitsiTrackError.prototype.constructor = JitsiTrackError;\n\n/**\n * Gets failed resolution constraint from corresponding object.\n * @param {string} failedConstraintName\n * @param {Object} constraints\n * @returns {string|number}\n */\nfunction getResolutionFromFailedConstraint(failedConstraintName, constraints) {\n if (constraints && constraints.video && 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\nexport default JitsiTrackError;\n","/**\n * The events for the connection.\n */\n\nexport enum JitsiConnectionEvents {\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 * Indicates that the performed action cannot be executed because the\n * connection is not in the correct state(connected, disconnected, etc.)\n */\n WRONG_STATE = 'connection.wrongState',\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 WRONG_STATE = JitsiConnectionEvents.WRONG_STATE;\nexport const DISPLAY_NAME_REQUIRED = JitsiConnectionEvents.DISPLAY_NAME_REQUIRED;\nexport const PROPERTIES_UPDATED = JitsiConnectionEvents.PROPERTIES_UPDATED;\n","import Bourne from '@hapi/bourne';\n\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 Bourne.parse(data);\n}\n","/**\n * The errors for the connection.\n */\n\nexport enum JitsiConnectionErrors {\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// exported for backward compatibility\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;\n","\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 {\n /**\n * Instantiates a Deferred object.\n */\n constructor() {\n this.promise = new Promise((resolve, reject) => {\n this.resolve = (...args) => {\n this.clearRejectTimeout();\n resolve(...args);\n };\n this.reject = (...args) => {\n this.clearRejectTimeout();\n reject(...args);\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() {\n clearTimeout(this._timeout);\n }\n\n /**\n * Rejects the promise after the given timeout.\n */\n setRejectTimeout(ms) {\n this._timeout = setTimeout(() => {\n this.reject(new Error('timeout'));\n }, ms);\n }\n}\n","import EventEmitter 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 * Creates new instance.\n * @constructor\n */\n constructor() {\n this.eventEmitter = new EventEmitter();\n\n // aliases for addListener/removeListener\n this.addEventListener = this.on = this.addListener;\n this.removeEventListener = this.off = this.removeListener;\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, listener) {\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, listener) {\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, listener) {\n return this.eventEmitter.removeListener(eventName, listener);\n }\n\n /**\n * Emits an event.\n * @param {string} event - event name\n */\n emit(event, ...args) {\n this.eventEmitter.emit(event, ...args);\n }\n}\n","/* global RTCRtpScriptTransform */\n\nimport { getLogger } from '@jitsi/logger';\n\nconst logger = getLogger(__filename);\n\n// Flag to set on senders / receivers to avoid setting up the encryption transform\n// more than once.\nconst kJitsiE2EE = Symbol('kJitsiE2EE');\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 * The encoded frame format is explained below in the _encodeFunction method.\n * High level design goals were:\n * - do not require changes to existing SFUs and retain (VP8) metadata.\n * - allow the SFU to rewrite SSRCs, timestamp, pictureId.\n * - allow for the key to be rotated frequently.\n */\nexport default class E2EEcontext {\n /**\n * Build a new E2EE context instance, which will be used in a given conference.\n * @param {boolean} [options.sharedKey] - whether there is a uniques key shared amoung all participants.\n */\n constructor({ sharedKey } = {}) {\n // Determine the URL for the worker script. Relative URLs are relative to\n // the entry point, not the script that launches the worker.\n let baseUrl = '';\n const ljm = document.querySelector('script[src*=\"lib-jitsi-meet\"]');\n\n if (ljm) {\n const idx = ljm.src.lastIndexOf('/');\n\n baseUrl = `${ljm.src.substring(0, idx)}/`;\n }\n\n let workerUrl = `${baseUrl}lib-jitsi-meet.e2ee-worker.js`;\n\n // If there is no baseUrl then we create the worker in a normal way\n // as you cant load scripts inside blobs from relative paths.\n // See: https://www.html5rocks.com/en/tutorials/workers/basics/#toc-inlineworkers-loadingscripts\n if (baseUrl && baseUrl !== '/') {\n // Initialize the E2EE worker. In order to avoid CORS issues, start the worker and have it\n // synchronously load the JS.\n const workerBlob\n = new Blob([ `importScripts(\"${workerUrl}\");` ], { type: 'application/javascript' });\n\n workerUrl = window.URL.createObjectURL(workerBlob);\n }\n\n this._worker = new Worker(workerUrl, { name: 'E2EE Worker' });\n\n this._worker.onerror = e => logger.error(e);\n\n this._worker.postMessage({\n operation: 'initialize',\n sharedKey\n });\n }\n\n /**\n * Cleans up all state associated with the given participant. This is needed when a\n * participant leaves the current conference.\n *\n * @param {string} participantId - The participant that just left.\n */\n cleanup(participantId) {\n this._worker.postMessage({\n operation: 'cleanup',\n participantId\n });\n }\n\n /**\n * Cleans up all state associated with all participants in the conference. This is needed when disabling e2ee.\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} kind - The kind of track this receiver belongs to.\n * @param {string} participantId - The participant id that this receiver belongs to.\n */\n handleReceiver(receiver, kind, participantId) {\n if (receiver[kJitsiE2EE]) {\n return;\n }\n receiver[kJitsiE2EE] = true;\n\n if (window.RTCRtpScriptTransform) {\n const options = {\n operation: 'decode',\n participantId\n };\n\n receiver.transform = new RTCRtpScriptTransform(this._worker, options);\n } else {\n const receiverStreams = receiver.createEncodedStreams();\n\n this._worker.postMessage({\n operation: 'decode',\n readableStream: receiverStreams.readable,\n writableStream: receiverStreams.writable,\n participantId\n }, [ receiverStreams.readable, receiverStreams.writable ]);\n }\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} kind - The kind of track this sender belongs to.\n * @param {string} participantId - The participant id that this sender belongs to.\n */\n handleSender(sender, kind, participantId) {\n if (sender[kJitsiE2EE]) {\n return;\n }\n sender[kJitsiE2EE] = true;\n\n if (window.RTCRtpScriptTransform) {\n const options = {\n operation: 'encode',\n participantId\n };\n\n sender.transform = new RTCRtpScriptTransform(this._worker, options);\n } else {\n const senderStreams = sender.createEncodedStreams();\n\n this._worker.postMessage({\n operation: 'encode',\n readableStream: senderStreams.readable,\n writableStream: senderStreams.writable,\n participantId\n }, [ senderStreams.readable, senderStreams.writable ]);\n }\n }\n\n /**\n * Set the E2EE key for the specified participant.\n *\n * @param {string} participantId - the ID of the participant who's key we are setting.\n * @param {Uint8Array | boolean} key - they key for the given participant.\n * @param {Number} keyIndex - the key index.\n */\n setKey(participantId, key, keyIndex) {\n this._worker.postMessage({\n operation: 'setKey',\n key,\n keyIndex,\n participantId\n });\n }\n}\n","import { getLogger } from '@jitsi/logger';\n\nimport * as JitsiConferenceEvents from '../../JitsiConferenceEvents';\nimport RTCEvents from '../../service/RTC/RTCEvents';\nimport browser from '../browser';\nimport Deferred from '../util/Deferred';\nimport Listenable from '../util/Listenable';\n\nimport E2EEContext from './E2EEContext';\n\nconst logger = getLogger(__filename);\n\n/**\n * Abstract class that integrates {@link E2EEContext} with a key management system.\n */\nexport class KeyHandler extends Listenable {\n /**\n * Build a new KeyHandler instance, which will be used in a given conference.\n * @param {JitsiConference} conference - the current conference.\n * @param {object} options - the options passed to {E2EEContext}, see implemention.\n */\n constructor(conference, options = {}) {\n super();\n\n this.conference = conference;\n this.e2eeCtx = new E2EEContext(options);\n\n this.enabled = false;\n this._enabling = undefined;\n\n // Conference media events in order to attach the encryptor / decryptor.\n // FIXME add events to TraceablePeerConnection which will allow to see when there's new receiver or sender\n // added instead of shenanigans around conference track events and track muted.\n //\n\n this.conference.on(\n JitsiConferenceEvents._MEDIA_SESSION_STARTED,\n this._onMediaSessionStarted.bind(this));\n this.conference.on(\n JitsiConferenceEvents.TRACK_ADDED,\n track => track.isLocal() && this._onLocalTrackAdded(track));\n this.conference.rtc.on(\n RTCEvents.REMOTE_TRACK_ADDED,\n (track, tpc) => this._setupReceiverE2EEForTrack(tpc, track));\n this.conference.on(\n JitsiConferenceEvents.TRACK_MUTE_CHANGED,\n this._trackMuteChanged.bind(this));\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 / 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) {\n this._enabling && await this._enabling;\n\n if (enabled === this.enabled) {\n return;\n }\n\n this._enabling = new Deferred();\n\n this.enabled = enabled;\n\n if (!enabled) {\n this.e2eeCtx.cleanupAll();\n }\n\n this._setEnabled && await this._setEnabled(enabled);\n\n this.conference.setLocalParticipantProperty('e2ee.enabled', enabled);\n\n this.conference._restartMediaSessions();\n\n this._enabling.resolve();\n }\n\n /**\n * Sets the key for End-to-End encryption.\n *\n * @returns {void}\n */\n setEncryptionKey() {\n throw new Error('Not implemented by subclass');\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 _onLocalTrackAdded(track) {\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 _onMediaSessionStarted(session) {\n const localTracks = this.conference.getLocalTracks();\n\n for (const track of localTracks) {\n this._setupSenderE2EEForTrack(session, track);\n }\n }\n\n /**\n * Setup E2EE for the receiving side.\n *\n * @private\n */\n _setupReceiverE2EEForTrack(tpc, track) {\n if (!this.enabled) {\n return;\n }\n\n const receiver = tpc.findReceiverForTrack(track.track);\n\n if (receiver) {\n this.e2eeCtx.handleReceiver(receiver, track.getType(), track.getParticipantId());\n } else {\n logger.warn(`Could not handle E2EE for ${track}: receiver not found in: ${tpc}`);\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 _setupSenderE2EEForTrack(session, track) {\n if (!this.enabled) {\n return;\n }\n\n const pc = session.peerconnection;\n const sender = pc && pc.findSenderForTrack(track.track);\n\n if (sender) {\n this.e2eeCtx.handleSender(sender, track.getType(), track.getParticipantId());\n } else {\n logger.warn(`Could not handle E2EE for ${track}: sender not found in ${pc}`);\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 _trackMuteChanged(track) {\n if (browser.doesVideoMuteByStreamRemove() && track.isLocal() && track.isVideoTrack() && !track.isMuted()) {\n for (const session of this.conference.getMediaSessions()) {\n this._setupSenderE2EEForTrack(session, track);\n }\n }\n }\n}\n","import { KeyHandler } from './KeyHandler';\n\n/**\n * This module integrates {@link E2EEContext} with {external} in order to set the keys for encryption.\n */\nexport class ExternallyManagedKeyHandler extends KeyHandler {\n /**\n * Build a new ExternallyManagedKeyHandler instance, which will be used in a given conference.\n * @param conference - the current conference.\n */\n constructor(conference) {\n super(conference, { sharedKey: true });\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 setKey(keyInfo) {\n this.e2eeCtx.setKey(undefined, { encryptionKey: keyInfo.encryptionKey }, keyInfo.index);\n }\n}\n","import uuid from './dist/index.js';\nexport const v1 = uuid.v1;\nexport const v3 = uuid.v3;\nexport const v4 = uuid.v4;\nexport const v5 = uuid.v5;\n","export enum E2EEErrors {\n E2EE_SAS_KEYS_MAC_MISMATCH = 'e2ee.sas.keys-mac-mismatch',\n E2EE_SAS_MAC_MISMATCH = 'e2ee.sas.mac-mismatch',\n E2EE_SAS_MISSING_KEY = 'e2ee.sas.missing-key',\n E2EE_SAS_COMMITMENT_MISMATCHED = 'e2ee.sas.commitment-mismatched',\n E2EE_SAS_CHANNEL_VERIFICATION_FAILED = 'e2ee.sas.channel-verification-failed',\n E2EE_SAS_INVALID_SAS_VERIFICATION = 'e2ee.sas.invalid-sas-verification',\n}\n","/* eslint-disable no-bitwise */\n/* eslint-disable no-mixed-operators */\n\n/**\n * Generates a SAS composed of decimal numbers.\n * Borrowed from the Matrix JS SDK.\n *\n * @param {Uint8Array} sasBytes - The bytes from sas.generate_bytes.\n * @returns Array\n */\nfunction generateDecimalSas(sasBytes) {\n /**\n * +--------+--------+--------+--------+--------+\n * | Byte 0 | Byte 1 | Byte 2 | Byte 3 | Byte 4 |\n * +--------+--------+--------+--------+--------+\n * bits: 87654321 87654321 87654321 87654321 87654321\n * \\____________/\\_____________/\\____________/\n * 1st number 2nd number 3rd number\n */\n return [\n (sasBytes[0] << 5 | sasBytes[1] >> 3) + 1000,\n ((sasBytes[1] & 0x7) << 10 | sasBytes[2] << 2 | sasBytes[3] >> 6) + 1000,\n ((sasBytes[3] & 0x3f) << 7 | sasBytes[4] >> 1) + 1000\n ];\n}\n\nconst 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 * Generates a SAS composed of defimal numbers.\n * Borrowed from the Matrix JS SDK.\n *\n * @param {Uint8Array} sasBytes - The bytes from sas.generate_bytes.\n * @returns Array\n */\nfunction generateEmojiSas(sasBytes) {\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\nconst sasGenerators = {\n decimal: generateDecimalSas,\n emoji: generateEmojiSas\n};\n\n/**\n * Generates multiple SAS for the given bytes.\n *\n * @param {Uint8Array} sasBytes - The bytes from sas.generate_bytes.\n * @returns {object}\n */\nexport function generateSas(sasBytes) {\n const sas = {};\n\n for (const method in sasGenerators) {\n if (sasGenerators.hasOwnProperty(method)) {\n sas[method] = sasGenerators[method](sasBytes);\n }\n }\n\n return sas;\n}\n","/* global Olm */\n\nimport { safeJsonParse as _safeJsonParse } from '@jitsi/js-utils/json';\nimport { getLogger } from '@jitsi/logger';\nimport base64js from 'base64-js';\nimport isEqual from 'lodash.isequal';\nimport { v4 as uuidv4 } from 'uuid';\n\nimport * as JitsiConferenceEvents from '../../JitsiConferenceEvents';\nimport Deferred from '../util/Deferred';\nimport Listenable from '../util/Listenable';\nimport { FEATURE_E2EE, JITSI_MEET_MUC_TYPE } from '../xmpp/xmpp';\n\nimport { E2EEErrors } from './E2EEErrors';\nimport { generateSas } from './SAS';\n\nconst logger = getLogger(__filename);\n\nconst REQ_TIMEOUT = 5 * 1000;\nconst OLM_MESSAGE_TYPE = 'olm';\nconst OLM_MESSAGE_TYPES = {\n ERROR: 'error',\n KEY_INFO: 'key-info',\n KEY_INFO_ACK: 'key-info-ack',\n SESSION_ACK: 'session-ack',\n SESSION_INIT: 'session-init',\n SAS_START: 'sas-start',\n SAS_ACCEPT: 'sas-accept',\n SAS_KEY: 'sas-key',\n SAS_MAC: 'sas-mac'\n};\n\nconst OLM_SAS_NUM_BYTES = 6;\nconst OLM_KEY_VERIFICATION_MAC_INFO = 'Jitsi-KEY_VERIFICATION_MAC';\nconst OLM_KEY_VERIFICATION_MAC_KEY_IDS = 'Jitsi-KEY_IDS';\n\nconst kOlmData = Symbol('OlmData');\n\nconst OlmAdapterEvents = {\n PARTICIPANT_E2EE_CHANNEL_READY: 'olm.participant_e2ee_channel_ready',\n PARTICIPANT_SAS_AVAILABLE: 'olm.participant_sas_available',\n PARTICIPANT_SAS_READY: 'olm.participant_sas_ready',\n PARTICIPANT_KEY_UPDATED: 'olm.partitipant_key_updated',\n PARTICIPANT_VERIFICATION_COMPLETED: 'olm.participant_verification_completed'\n};\n\n/**\n * This class implements an End-to-End Encrypted communication channel between every two peers\n * in the conference. This channel uses libolm to achieve E2EE.\n *\n * The created channel is then used to exchange the secret key that each participant will use\n * to encrypt the actual media (see {@link E2EEContext}).\n *\n * A simple JSON message based protocol is implemented, which follows a request - response model:\n * - session-init: Initiates an olm session establishment procedure. This message will be sent\n * by the participant who just joined, to everyone else.\n * - session-ack: Completes the olm session etablishment. This messsage may contain ancilliary\n * encrypted data, more specifically the sender's current key.\n * - key-info: Includes the sender's most up to date key information.\n * - key-info-ack: Acknowledges the reception of a key-info request. In addition, it may contain\n * the sender's key information, if available.\n * - error: Indicates a request processing error has occurred.\n *\n * These requessts and responses are transport independent. Currently they are sent using XMPP\n * MUC private messages.\n */\nexport class OlmAdapter extends Listenable {\n /**\n * Creates an adapter instance for the given conference.\n */\n constructor(conference) {\n super();\n\n this._conf = conference;\n this._init = new Deferred();\n this._mediaKey = undefined;\n this._mediaKeyIndex = -1;\n this._reqs = new Map();\n this._sessionInitialization = undefined;\n\n if (OlmAdapter.isSupported()) {\n this._bootstrapOlm();\n\n this._conf.on(JitsiConferenceEvents.ENDPOINT_MESSAGE_RECEIVED, this._onEndpointMessageReceived.bind(this));\n this._conf.on(JitsiConferenceEvents.CONFERENCE_LEFT, this._onConferenceLeft.bind(this));\n this._conf.on(JitsiConferenceEvents.USER_LEFT, this._onParticipantLeft.bind(this));\n this._conf.on(JitsiConferenceEvents.PARTICIPANT_PROPERTY_CHANGED,\n this._onParticipantPropertyChanged.bind(this));\n } else {\n this._init.reject(new Error('Olm not supported'));\n }\n }\n\n /**\n * Returns the current participants conference ID.\n *\n * @returns {string}\n */\n get myId() {\n return this._conf.myUserId();\n }\n\n /**\n * Starts new olm sessions with every other participant that has the participantId \"smaller\" the localParticipantId.\n */\n async initSessions() {\n if (this._sessionInitialization) {\n throw new Error('OlmAdapter initSessions called multiple times');\n } else {\n this._sessionInitialization = new Deferred();\n\n await this._init;\n\n const promises = [];\n const localParticipantId = this._conf.myUserId();\n\n for (const participant of this._conf.getParticipants()) {\n if (participant.hasFeature(FEATURE_E2EE) && localParticipantId < participant.getId()) {\n promises.push(this._sendSessionInit(participant));\n }\n }\n\n await Promise.allSettled(promises);\n\n // TODO: retry failed ones.\n\n this._sessionInitialization.resolve();\n this._sessionInitialization = undefined;\n }\n }\n\n /**\n * Indicates if olm is supported on the current platform.\n *\n * @returns {boolean}\n */\n static isSupported() {\n return typeof window.Olm !== 'undefined';\n }\n\n /**\n * Updates the current participant key and distributes it to all participants in the conference\n * by sending a key-info message.\n *\n * @param {Uint8Array|boolean} key - The new key.\n * @retrns {Promise}\n */\n async updateKey(key) {\n // Store it locally for new sessions.\n this._mediaKey = key;\n this._mediaKeyIndex++;\n\n // Broadcast it.\n const promises = [];\n\n for (const participant of this._conf.getParticipants()) {\n const pId = participant.getId();\n const olmData = this._getParticipantOlmData(participant);\n\n // TODO: skip those who don't support E2EE.\n if (!olmData.session) {\n logger.warn(`Tried to send key to participant ${pId} but we have no session`);\n\n // eslint-disable-next-line no-continue\n continue;\n }\n\n const uuid = uuidv4();\n const data = {\n [JITSI_MEET_MUC_TYPE]: OLM_MESSAGE_TYPE,\n olm: {\n type: OLM_MESSAGE_TYPES.KEY_INFO,\n data: {\n ciphertext: this._encryptKeyInfo(olmData.session),\n uuid\n }\n }\n };\n const d = new Deferred();\n\n d.setRejectTimeout(REQ_TIMEOUT);\n d.catch(() => {\n this._reqs.delete(uuid);\n });\n this._reqs.set(uuid, d);\n promises.push(d);\n\n this._sendMessage(data, pId);\n }\n\n await Promise.allSettled(promises);\n\n // TODO: retry failed ones?\n\n return this._mediaKeyIndex;\n }\n\n /**\n * Updates the current participant key.\n * @param {Uint8Array|boolean} key - The new key.\n * @returns {number}\n */\n updateCurrentMediaKey(key) {\n this._mediaKey = key;\n\n return this._mediaKeyIndex;\n }\n\n /**\n * Frees the olmData session for the given participant.\n *\n */\n clearParticipantSession(participant) {\n const olmData = this._getParticipantOlmData(participant);\n\n if (olmData.session) {\n olmData.session.free();\n olmData.session = undefined;\n }\n }\n\n /**\n * Frees the olmData sessions for all participants.\n *\n */\n clearAllParticipantsSessions() {\n for (const participant of this._conf.getParticipants()) {\n this.clearParticipantSession(participant);\n }\n }\n\n /**\n * Sends sacMac if channel verification waas successful.\n *\n */\n markParticipantVerified(participant, isVerified) {\n const olmData = this._getParticipantOlmData(participant);\n\n const pId = participant.getId();\n\n if (!isVerified) {\n olmData.sasVerification = undefined;\n logger.warn(`Verification failed for participant ${pId}`);\n this.eventEmitter.emit(\n OlmAdapterEvents.PARTICIPANT_VERIFICATION_COMPLETED,\n pId,\n false,\n E2EEErrors.E2EE_SAS_CHANNEL_VERIFICATION_FAILED);\n\n return;\n }\n\n if (!olmData.sasVerification) {\n logger.warn(`Participant ${pId} does not have valid sasVerification`);\n this.eventEmitter.emit(\n OlmAdapterEvents.PARTICIPANT_VERIFICATION_COMPLETED,\n pId,\n false,\n E2EEErrors.E2EE_SAS_INVALID_SAS_VERIFICATION);\n\n return;\n }\n\n const { sas, sasMacSent } = olmData.sasVerification;\n\n if (sas && sas.is_their_key_set() && !sasMacSent) {\n this._sendSasMac(participant);\n\n // Mark the MAC as sent so we don't send it multiple times.\n olmData.sasVerification.sasMacSent = true;\n }\n }\n\n /**\n * Internal helper to bootstrap the olm library.\n *\n * @returns {Promise}\n * @private\n */\n async _bootstrapOlm() {\n logger.debug('Initializing Olm...');\n\n try {\n await Olm.init();\n\n this._olmAccount = new Olm.Account();\n this._olmAccount.create();\n\n this._idKeys = _safeJsonParse(this._olmAccount.identity_keys());\n\n logger.debug(`Olm ${Olm.get_library_version().join('.')} initialized`);\n this._init.resolve();\n this._onIdKeysReady(this._idKeys);\n } catch (e) {\n logger.error('Failed to initialize Olm', e);\n this._init.reject(e);\n }\n }\n\n /**\n * Starts the verification process for the given participant as described here\n * https://spec.matrix.org/latest/client-server-api/#short-authentication-string-sas-verification\n *\n * | |\n | m.key.verification.start |\n |-------------------------------->|\n | |\n | m.key.verification.accept |\n |<--------------------------------|\n | |\n | m.key.verification.key |\n |-------------------------------->|\n | |\n | m.key.verification.key |\n |<--------------------------------|\n | |\n | m.key.verification.mac |\n |-------------------------------->|\n | |\n | m.key.verification.mac |\n |<--------------------------------|\n | |\n *\n * @param {JitsiParticipant} participant - The target participant.\n * @returns {Promise}\n * @private\n */\n startVerification(participant) {\n const pId = participant.getId();\n const olmData = this._getParticipantOlmData(participant);\n\n if (!olmData.session) {\n logger.warn(`Tried to start verification with participant ${pId} but we have no session`);\n\n return;\n }\n\n if (olmData.sasVerification) {\n logger.warn(`There is already a verification in progress with participant ${pId}`);\n\n return;\n }\n\n olmData.sasVerification = {\n sas: new Olm.SAS(),\n transactionId: uuidv4()\n };\n\n const startContent = {\n transactionId: olmData.sasVerification.transactionId\n };\n\n olmData.sasVerification.startContent = startContent;\n olmData.sasVerification.isInitiator = true;\n\n const startMessage = {\n [JITSI_MEET_MUC_TYPE]: OLM_MESSAGE_TYPE,\n olm: {\n type: OLM_MESSAGE_TYPES.SAS_START,\n data: startContent\n }\n };\n\n this._sendMessage(startMessage, pId);\n }\n\n /**\n * Publishes our own Olmn id key in presence.\n * @private\n */\n _onIdKeysReady(idKeys) {\n logger.debug(`Olm id key ready: ${idKeys}`);\n\n // Publish it in presence.\n for (const keyType in idKeys) {\n if (idKeys.hasOwnProperty(keyType)) {\n const key = idKeys[keyType];\n\n this._conf.setLocalParticipantProperty(`e2ee.idKey.${keyType}`, key);\n }\n }\n }\n\n /**\n * Event posted when the E2EE signalling channel has been established with the given participant.\n * @private\n */\n _onParticipantE2EEChannelReady(id) {\n logger.debug(`E2EE channel with participant ${id} is ready`);\n }\n\n /**\n * Internal helper for encrypting the current key information for a given participant.\n *\n * @param {Olm.Session} session - Participant's session.\n * @returns {string} - The encrypted text with the key information.\n * @private\n */\n _encryptKeyInfo(session) {\n const keyInfo = {};\n\n if (this._mediaKey !== undefined) {\n keyInfo.key = this._mediaKey ? base64js.fromByteArray(this._mediaKey) : false;\n keyInfo.keyIndex = this._mediaKeyIndex;\n }\n\n return session.encrypt(JSON.stringify(keyInfo));\n }\n\n /**\n * Internal helper for getting the olm related data associated with a participant.\n *\n * @param {JitsiParticipant} participant - Participant whose data wants to be extracted.\n * @returns {Object}\n * @private\n */\n _getParticipantOlmData(participant) {\n participant[kOlmData] = participant[kOlmData] || {};\n\n return participant[kOlmData];\n }\n\n /**\n * Handles leaving the conference, cleaning up olm sessions.\n *\n * @private\n */\n async _onConferenceLeft() {\n logger.debug('Conference left');\n\n await this._init;\n\n for (const participant of this._conf.getParticipants()) {\n this._onParticipantLeft(participant.getId(), participant);\n }\n\n if (this._olmAccount) {\n this._olmAccount.free();\n this._olmAccount = undefined;\n }\n }\n\n /**\n * Main message handler. Handles 1-to-1 messages received from other participants\n * and send the appropriate replies.\n *\n * @private\n */\n async _onEndpointMessageReceived(participant, payload) {\n if (payload[JITSI_MEET_MUC_TYPE] !== OLM_MESSAGE_TYPE) {\n return;\n }\n\n if (!payload.olm) {\n logger.warn('Incorrectly formatted message');\n\n return;\n }\n\n await this._init;\n\n const msg = payload.olm;\n const pId = participant.getId();\n const olmData = this._getParticipantOlmData(participant);\n\n switch (msg.type) {\n case OLM_MESSAGE_TYPES.SESSION_INIT: {\n if (olmData.session) {\n logger.warn(`Participant ${pId} already has a session`);\n\n this._sendError(participant, 'Session already established');\n } else {\n // Create a session for communicating with this participant.\n\n const session = new Olm.Session();\n\n session.create_outbound(this._olmAccount, msg.data.idKey, msg.data.otKey);\n olmData.session = session;\n\n // Send ACK\n const ack = {\n [JITSI_MEET_MUC_TYPE]: OLM_MESSAGE_TYPE,\n olm: {\n type: OLM_MESSAGE_TYPES.SESSION_ACK,\n data: {\n ciphertext: this._encryptKeyInfo(session),\n uuid: msg.data.uuid\n }\n }\n };\n\n this._sendMessage(ack, pId);\n this._onParticipantE2EEChannelReady(pId);\n }\n break;\n }\n case OLM_MESSAGE_TYPES.SESSION_ACK: {\n if (olmData.session) {\n logger.warn(`Participant ${pId} already has a session`);\n\n this._sendError(participant, 'No session found');\n } else if (msg.data.uuid === olmData.pendingSessionUuid) {\n const { ciphertext } = msg.data;\n const d = this._reqs.get(msg.data.uuid);\n const session = new Olm.Session();\n\n session.create_inbound(this._olmAccount, ciphertext.body);\n\n // Remove OT keys that have been used to setup this session.\n this._olmAccount.remove_one_time_keys(session);\n\n // Decrypt first message.\n const data = session.decrypt(ciphertext.type, ciphertext.body);\n\n olmData.session = session;\n olmData.pendingSessionUuid = undefined;\n\n this._onParticipantE2EEChannelReady(pId);\n\n this._reqs.delete(msg.data.uuid);\n d.resolve();\n\n const json = safeJsonParse(data);\n\n if (json.key) {\n const key = base64js.toByteArray(json.key);\n const keyIndex = json.keyIndex;\n\n olmData.lastKey = key;\n this.eventEmitter.emit(OlmAdapterEvents.PARTICIPANT_KEY_UPDATED, pId, key, keyIndex);\n }\n } else {\n logger.warn('Received ACK with the wrong UUID');\n\n this._sendError(participant, 'Invalid UUID');\n }\n break;\n }\n case OLM_MESSAGE_TYPES.ERROR: {\n logger.error(msg.data.error);\n\n break;\n }\n case OLM_MESSAGE_TYPES.KEY_INFO: {\n if (olmData.session) {\n const { ciphertext } = msg.data;\n const data = olmData.session.decrypt(ciphertext.type, ciphertext.body);\n const json = safeJsonParse(data);\n\n if (json.key !== undefined && json.keyIndex !== undefined) {\n const key = json.key ? base64js.toByteArray(json.key) : false;\n const keyIndex = json.keyIndex;\n\n if (!isEqual(olmData.lastKey, key)) {\n olmData.lastKey = key;\n this.eventEmitter.emit(OlmAdapterEvents.PARTICIPANT_KEY_UPDATED, pId, key, keyIndex);\n }\n\n // Send ACK.\n const ack = {\n [JITSI_MEET_MUC_TYPE]: OLM_MESSAGE_TYPE,\n olm: {\n type: OLM_MESSAGE_TYPES.KEY_INFO_ACK,\n data: {\n ciphertext: this._encryptKeyInfo(olmData.session),\n uuid: msg.data.uuid\n }\n }\n };\n\n this._sendMessage(ack, pId);\n }\n } else {\n logger.debug(`Received key info message from ${pId} but we have no session for them!`);\n\n this._sendError(participant, 'No session found while processing key-info');\n }\n break;\n }\n case OLM_MESSAGE_TYPES.KEY_INFO_ACK: {\n if (olmData.session) {\n const { ciphertext } = msg.data;\n const data = olmData.session.decrypt(ciphertext.type, ciphertext.body);\n const json = safeJsonParse(data);\n\n if (json.key !== undefined && json.keyIndex !== undefined) {\n const key = json.key ? base64js.toByteArray(json.key) : false;\n const keyIndex = json.keyIndex;\n\n if (!isEqual(olmData.lastKey, key)) {\n olmData.lastKey = key;\n this.eventEmitter.emit(OlmAdapterEvents.PARTICIPANT_KEY_UPDATED, pId, key, keyIndex);\n }\n }\n\n const d = this._reqs.get(msg.data.uuid);\n\n this._reqs.delete(msg.data.uuid);\n d.resolve();\n } else {\n logger.debug(`Received key info ack message from ${pId} but we have no session for them!`);\n\n this._sendError(participant, 'No session found while processing key-info-ack');\n }\n break;\n }\n case OLM_MESSAGE_TYPES.SAS_START: {\n if (!olmData.session) {\n logger.debug(`Received sas init message from ${pId} but we have no session for them!`);\n\n this._sendError(participant, 'No session found while processing sas-init');\n\n return;\n }\n\n if (olmData.sasVerification?.sas) {\n logger.warn(`SAS already created for participant ${pId}`);\n this.eventEmitter.emit(\n OlmAdapterEvents.PARTICIPANT_VERIFICATION_COMPLETED,\n pId,\n false,\n E2EEErrors.E2EE_SAS_INVALID_SAS_VERIFICATION);\n\n return;\n }\n\n const { transactionId } = msg.data;\n\n const sas = new Olm.SAS();\n\n olmData.sasVerification = {\n sas,\n transactionId,\n isInitiator: false\n };\n\n const pubKey = olmData.sasVerification.sas.get_pubkey();\n const commitment = this._computeCommitment(pubKey, msg.data);\n\n /* The first phase of the verification process, the Key agreement phase\n https://spec.matrix.org/latest/client-server-api/#short-authentication-string-sas-verification\n */\n const acceptMessage = {\n [JITSI_MEET_MUC_TYPE]: OLM_MESSAGE_TYPE,\n olm: {\n type: OLM_MESSAGE_TYPES.SAS_ACCEPT,\n data: {\n transactionId,\n commitment\n }\n }\n };\n\n this._sendMessage(acceptMessage, pId);\n break;\n }\n case OLM_MESSAGE_TYPES.SAS_ACCEPT: {\n if (!olmData.session) {\n logger.debug(`Received sas accept message from ${pId} but we have no session for them!`);\n\n this._sendError(participant, 'No session found while processing sas-accept');\n\n return;\n }\n\n const { commitment, transactionId } = msg.data;\n\n\n if (!olmData.sasVerification) {\n logger.warn(`SAS_ACCEPT Participant ${pId} does not have valid sasVerification`);\n this.eventEmitter.emit(\n OlmAdapterEvents.PARTICIPANT_VERIFICATION_COMPLETED,\n pId,\n false,\n E2EEErrors.E2EE_SAS_INVALID_SAS_VERIFICATION);\n\n return;\n }\n\n if (olmData.sasVerification.sasCommitment) {\n logger.debug(`Already received sas commitment message from ${pId}!`);\n\n this._sendError(participant, 'Already received sas commitment message from ${pId}!');\n\n return;\n }\n\n olmData.sasVerification.sasCommitment = commitment;\n\n const pubKey = olmData.sasVerification.sas.get_pubkey();\n\n // Send KEY.\n const keyMessage = {\n [JITSI_MEET_MUC_TYPE]: OLM_MESSAGE_TYPE,\n olm: {\n type: OLM_MESSAGE_TYPES.SAS_KEY,\n data: {\n key: pubKey,\n transactionId\n }\n }\n };\n\n this._sendMessage(keyMessage, pId);\n\n olmData.sasVerification.keySent = true;\n break;\n }\n case OLM_MESSAGE_TYPES.SAS_KEY: {\n if (!olmData.session) {\n logger.debug(`Received sas key message from ${pId} but we have no session for them!`);\n\n this._sendError(participant, 'No session found while processing sas-key');\n\n return;\n }\n\n if (!olmData.sasVerification) {\n logger.warn(`SAS_KEY Participant ${pId} does not have valid sasVerification`);\n this.eventEmitter.emit(\n OlmAdapterEvents.PARTICIPANT_VERIFICATION_COMPLETED,\n pId,\n false,\n E2EEErrors.E2EE_SAS_INVALID_SAS_VERIFICATION);\n\n return;\n }\n\n const { isInitiator, sas, sasCommitment, startContent, keySent } = olmData.sasVerification;\n\n if (sas.is_their_key_set()) {\n logger.warn('SAS already has their key!');\n\n return;\n }\n\n const { key: theirKey, transactionId } = msg.data;\n\n if (sasCommitment) {\n const commitment = this._computeCommitment(theirKey, startContent);\n\n if (sasCommitment !== commitment) {\n this._sendError(participant, 'OlmAdapter commitments mismatched');\n this.eventEmitter.emit(\n OlmAdapterEvents.PARTICIPANT_VERIFICATION_COMPLETED,\n pId,\n false,\n E2EEErrors.E2EE_SAS_COMMITMENT_MISMATCHED);\n olmData.sasVerification.free();\n\n return;\n }\n }\n\n sas.set_their_key(theirKey);\n\n const pubKey = sas.get_pubkey();\n\n const myInfo = `${this.myId}|${pubKey}`;\n const theirInfo = `${pId}|${theirKey}`;\n\n const info = isInitiator ? `${myInfo}|${theirInfo}` : `${theirInfo}|${myInfo}`;\n\n const sasBytes = sas.generate_bytes(info, OLM_SAS_NUM_BYTES);\n const generatedSas = generateSas(sasBytes);\n\n this.eventEmitter.emit(OlmAdapterEvents.PARTICIPANT_SAS_READY, pId, generatedSas);\n\n if (keySent) {\n return;\n }\n\n const keyMessage = {\n [JITSI_MEET_MUC_TYPE]: OLM_MESSAGE_TYPE,\n olm: {\n type: OLM_MESSAGE_TYPES.SAS_KEY,\n data: {\n key: pubKey,\n transactionId\n }\n }\n };\n\n this._sendMessage(keyMessage, pId);\n\n olmData.sasVerification.keySent = true;\n break;\n }\n case OLM_MESSAGE_TYPES.SAS_MAC: {\n if (!olmData.session) {\n logger.debug(`Received sas mac message from ${pId} but we have no session for them!`);\n\n this._sendError(participant, 'No session found while processing sas-mac');\n\n return;\n }\n\n const { keys, mac, transactionId } = msg.data;\n\n if (!mac || !keys) {\n logger.warn('Invalid SAS MAC message');\n\n return;\n }\n\n if (!olmData.sasVerification) {\n logger.warn(`SAS_MAC Participant ${pId} does not have valid sasVerification`);\n\n return;\n }\n\n const sas = olmData.sasVerification.sas;\n\n // Verify the received MACs.\n const baseInfo = `${OLM_KEY_VERIFICATION_MAC_INFO}${pId}${this.myId}${transactionId}`;\n const keysMac = sas.calculate_mac(\n Object.keys(mac).sort().join(','), // eslint-disable-line newline-per-chained-call\n baseInfo + OLM_KEY_VERIFICATION_MAC_KEY_IDS\n );\n\n if (keysMac !== keys) {\n logger.error('SAS verification error: keys MAC mismatch');\n this.eventEmitter.emit(\n OlmAdapterEvents.PARTICIPANT_VERIFICATION_COMPLETED,\n pId,\n false,\n E2EEErrors.E2EE_SAS_KEYS_MAC_MISMATCH);\n\n return;\n }\n\n if (!olmData.ed25519) {\n logger.warn('SAS verification error: Missing ed25519 key');\n\n this.eventEmitter.emit(\n OlmAdapterEvents.PARTICIPANT_VERIFICATION_COMPLETED,\n pId,\n false,\n E2EEErrors.E2EE_SAS_MISSING_KEY);\n\n return;\n }\n\n for (const [ keyInfo, computedMac ] of Object.entries(mac)) {\n const ourComputedMac = sas.calculate_mac(\n olmData.ed25519,\n baseInfo + keyInfo\n );\n\n if (computedMac !== ourComputedMac) {\n logger.error('SAS verification error: MAC mismatch');\n this.eventEmitter.emit(\n OlmAdapterEvents.PARTICIPANT_VERIFICATION_COMPLETED,\n pId,\n false,\n E2EEErrors.E2EE_SAS_MAC_MISMATCH);\n\n return;\n }\n }\n\n logger.info(`SAS MAC verified for participant ${pId}`);\n this.eventEmitter.emit(OlmAdapterEvents.PARTICIPANT_VERIFICATION_COMPLETED, pId, true);\n\n break;\n }\n }\n }\n\n /**\n * Handles a participant leaving. When a participant leaves their olm session is destroyed.\n *\n * @private\n */\n _onParticipantLeft(id, participant) {\n logger.debug(`Participant ${id} left`);\n\n this.clearParticipantSession(participant);\n }\n\n /**\n * Handles an update in a participant's presence property.\n *\n * @param {JitsiParticipant} participant - The participant.\n * @param {string} name - The name of the property that changed.\n * @param {*} oldValue - The property's previous value.\n * @param {*} newValue - The property's new value.\n * @private\n */\n async _onParticipantPropertyChanged(participant, name, oldValue, newValue) {\n const participantId = participant.getId();\n const olmData = this._getParticipantOlmData(participant);\n\n switch (name) {\n case 'e2ee.enabled':\n if (newValue && this._conf.isE2EEEnabled()) {\n const localParticipantId = this._conf.myUserId();\n const participantFeatures = await participant.getFeatures();\n\n if (participantFeatures.has(FEATURE_E2EE) && localParticipantId < participantId) {\n if (this._sessionInitialization) {\n await this._sessionInitialization;\n }\n await this._sendSessionInit(participant);\n\n const uuid = uuidv4();\n\n const d = new Deferred();\n\n d.setRejectTimeout(REQ_TIMEOUT);\n d.catch(() => {\n this._reqs.delete(uuid);\n olmData.pendingSessionUuid = undefined;\n });\n this._reqs.set(uuid, d);\n\n const data = {\n [JITSI_MEET_MUC_TYPE]: OLM_MESSAGE_TYPE,\n olm: {\n type: OLM_MESSAGE_TYPES.KEY_INFO,\n data: {\n ciphertext: this._encryptKeyInfo(olmData.session),\n uuid\n }\n }\n };\n\n this._sendMessage(data, participantId);\n }\n }\n break;\n case 'e2ee.idKey.ed25519':\n olmData.ed25519 = newValue;\n this.eventEmitter.emit(OlmAdapterEvents.PARTICIPANT_SAS_AVAILABLE, participantId);\n break;\n }\n }\n\n /**\n * Builds and sends an error message to the target participant.\n *\n * @param {JitsiParticipant} participant - The target participant.\n * @param {string} error - The error message.\n * @returns {void}\n */\n _sendError(participant, error) {\n const pId = participant.getId();\n const err = {\n [JITSI_MEET_MUC_TYPE]: OLM_MESSAGE_TYPE,\n olm: {\n type: OLM_MESSAGE_TYPES.ERROR,\n data: {\n error\n }\n }\n };\n\n this._sendMessage(err, pId);\n }\n\n /**\n * Internal helper to send the given object to the given participant ID.\n * This function merely exists so the transport can be easily swapped.\n * Currently messages are transmitted via XMPP MUC private messages.\n *\n * @param {object} data - The data that will be sent to the target participant.\n * @param {string} participantId - ID of the target participant.\n */\n _sendMessage(data, participantId) {\n this._conf.sendMessage(data, participantId);\n }\n\n /**\n * Builds and sends the session-init request to the target participant.\n *\n * @param {JitsiParticipant} participant - Participant to whom we'll send the request.\n * @returns {Promise} - The promise will be resolved when the session-ack is received.\n * @private\n */\n _sendSessionInit(participant) {\n const pId = participant.getId();\n const olmData = this._getParticipantOlmData(participant);\n\n if (olmData.session) {\n logger.warn(`Tried to send session-init to ${pId} but we already have a session`);\n\n return Promise.reject();\n }\n\n if (olmData.pendingSessionUuid !== undefined) {\n logger.warn(`Tried to send session-init to ${pId} but we already have a pending session`);\n\n return Promise.reject();\n }\n\n // Generate a One Time Key.\n this._olmAccount.generate_one_time_keys(1);\n\n const otKeys = _safeJsonParse(this._olmAccount.one_time_keys());\n const otKey = Object.values(otKeys.curve25519)[0];\n\n if (!otKey) {\n return Promise.reject(new Error('No one-time-keys generated'));\n }\n\n // Mark the OT keys (one really) as published so they are not reused.\n this._olmAccount.mark_keys_as_published();\n\n const uuid = uuidv4();\n const init = {\n [JITSI_MEET_MUC_TYPE]: OLM_MESSAGE_TYPE,\n olm: {\n type: OLM_MESSAGE_TYPES.SESSION_INIT,\n data: {\n idKey: this._idKeys.curve25519,\n otKey,\n uuid\n }\n }\n };\n\n const d = new Deferred();\n\n d.setRejectTimeout(REQ_TIMEOUT);\n d.catch(() => {\n this._reqs.delete(uuid);\n olmData.pendingSessionUuid = undefined;\n });\n this._reqs.set(uuid, d);\n\n this._sendMessage(init, pId);\n\n // Store the UUID for matching with the ACK.\n olmData.pendingSessionUuid = uuid;\n\n return d;\n }\n\n /**\n * Builds and sends the SAS MAC message to the given participant.\n * The second phase of the verification process, the Key verification phase\n https://spec.matrix.org/latest/client-server-api/#short-authentication-string-sas-verification\n */\n _sendSasMac(participant) {\n const pId = participant.getId();\n const olmData = this._getParticipantOlmData(participant);\n const { sas, transactionId } = olmData.sasVerification;\n\n // Calculate and send MAC with the keys to be verified.\n const mac = {};\n const keyList = [];\n const baseInfo = `${OLM_KEY_VERIFICATION_MAC_INFO}${this.myId}${pId}${transactionId}`;\n\n const deviceKeyId = `ed25519:${pId}`;\n\n mac[deviceKeyId] = sas.calculate_mac(\n this._idKeys.ed25519,\n baseInfo + deviceKeyId);\n keyList.push(deviceKeyId);\n\n const keys = sas.calculate_mac(\n keyList.sort().join(','),\n baseInfo + OLM_KEY_VERIFICATION_MAC_KEY_IDS\n );\n\n const macMessage = {\n [JITSI_MEET_MUC_TYPE]: OLM_MESSAGE_TYPE,\n olm: {\n type: OLM_MESSAGE_TYPES.SAS_MAC,\n data: {\n keys,\n mac,\n transactionId\n }\n }\n };\n\n this._sendMessage(macMessage, pId);\n }\n\n /**\n * Computes the commitment.\n */\n _computeCommitment(pubKey, data) {\n const olmUtil = new Olm.Utility();\n const commitment = olmUtil.sha256(pubKey + JSON.stringify(data));\n\n olmUtil.free();\n\n return commitment;\n }\n}\n\n/**\n * Helper to ensure JSON parsing always returns an object.\n *\n * @param {string} data - The data that needs to be parsed.\n * @returns {object} - Parsed data or empty object in case of failure.\n */\nfunction safeJsonParse(data) {\n try {\n return _safeJsonParse(data);\n } catch (e) {\n return {};\n }\n}\n\nOlmAdapter.events = OlmAdapterEvents;\n","import { getLogger } from '@jitsi/logger';\nimport debounce from 'lodash.debounce';\n\nimport * as JitsiConferenceEvents from '../../JitsiConferenceEvents';\n\nimport { KeyHandler } from './KeyHandler';\nimport { OlmAdapter } from './OlmAdapter';\nimport { importKey, ratchet } from './crypto-utils';\n\nconst logger = getLogger(__filename);\n\n// Period which we'll wait before updating / rotating our keys when a participant\n// joins or leaves.\nconst DEBOUNCE_PERIOD = 5000;\n\n/**\n * This module integrates {@link E2EEContext} with {@link OlmAdapter} in order to distribute the keys for encryption.\n */\nexport class ManagedKeyHandler extends KeyHandler {\n /**\n * Build a new AutomaticKeyHandler instance, which will be used in a given conference.\n */\n constructor(conference) {\n super(conference);\n\n this._key = undefined;\n this._conferenceJoined = false;\n\n this._olmAdapter = new OlmAdapter(conference);\n\n this._rotateKey = debounce(this._rotateKeyImpl, DEBOUNCE_PERIOD);\n this._ratchetKey = debounce(this._ratchetKeyImpl, DEBOUNCE_PERIOD);\n\n // Olm signalling events.\n this._olmAdapter.on(\n OlmAdapter.events.PARTICIPANT_KEY_UPDATED,\n this._onParticipantKeyUpdated.bind(this));\n\n this._olmAdapter.on(\n OlmAdapter.events.PARTICIPANT_SAS_READY,\n this._onParticipantSasReady.bind(this));\n\n this._olmAdapter.on(\n OlmAdapter.events.PARTICIPANT_SAS_AVAILABLE,\n this._onParticipantSasAvailable.bind(this));\n\n this._olmAdapter.on(\n OlmAdapter.events.PARTICIPANT_VERIFICATION_COMPLETED,\n this._onParticipantVerificationCompleted.bind(this));\n\n this.conference.on(\n JitsiConferenceEvents.PARTICIPANT_PROPERTY_CHANGED,\n this._onParticipantPropertyChanged.bind(this));\n this.conference.on(\n JitsiConferenceEvents.USER_JOINED,\n this._onParticipantJoined.bind(this));\n this.conference.on(\n JitsiConferenceEvents.USER_LEFT,\n this._onParticipantLeft.bind(this));\n this.conference.on(\n JitsiConferenceEvents.CONFERENCE_JOINED,\n () => {\n this._conferenceJoined = true;\n });\n }\n\n /**\n * Returns the sasVerficiation object.\n *\n * @returns {Object}\n */\n get sasVerification() {\n return this._olmAdapter;\n }\n\n /**\n * When E2EE is enabled it initializes sessions and sets the key.\n * Cleans up the sessions when disabled.\n *\n * @param {boolean} enabled - whether E2EE should be enabled or not.\n * @returns {void}\n */\n async _setEnabled(enabled) {\n if (enabled) {\n await this._olmAdapter.initSessions();\n } else {\n this._olmAdapter.clearAllParticipantsSessions();\n }\n\n // Generate a random key in case we are enabling.\n this._key = enabled ? this._generateKey() : false;\n\n // Send it to others using the E2EE olm channel.\n const index = await this._olmAdapter.updateKey(this._key);\n\n // Set our key so we begin encrypting.\n this.e2eeCtx.setKey(this.conference.myUserId(), this._key, index);\n }\n\n /**\n * Handles an update in a participant's presence property.\n *\n * @param {JitsiParticipant} participant - The participant.\n * @param {string} name - The name of the property that changed.\n * @param {*} oldValue - The property's previous value.\n * @param {*} newValue - The property's new value.\n * @private\n */\n async _onParticipantPropertyChanged(participant, name, oldValue, newValue) {\n switch (name) {\n case 'e2ee.idKey':\n logger.debug(`Participant ${participant.getId()} updated their id key: ${newValue}`);\n break;\n case 'e2ee.enabled':\n if (!newValue && this.enabled) {\n this._olmAdapter.clearParticipantSession(participant);\n }\n break;\n }\n }\n\n /**\n * Advances (using ratcheting) the current key when a new participant joins the conference.\n * @private\n */\n _onParticipantJoined() {\n if (this._conferenceJoined && this.enabled) {\n this._ratchetKey();\n }\n }\n\n /**\n * Rotates the current key when a participant leaves the conference.\n * @private\n */\n _onParticipantLeft(id) {\n this.e2eeCtx.cleanup(id);\n\n if (this.enabled) {\n this._rotateKey();\n }\n }\n\n /**\n * Rotates the local key. Rotating the key implies creating a new one, then distributing it\n * to all participants and once they all received it, start using it.\n *\n * @private\n */\n async _rotateKeyImpl() {\n logger.debug('Rotating key');\n\n this._key = this._generateKey();\n const index = await this._olmAdapter.updateKey(this._key);\n\n this.e2eeCtx.setKey(this.conference.myUserId(), this._key, index);\n }\n\n /**\n * Advances the current key by using ratcheting.\n *\n * @private\n */\n async _ratchetKeyImpl() {\n logger.debug('Ratchetting key');\n\n const material = await importKey(this._key);\n const newKey = await ratchet(material);\n\n this._key = new Uint8Array(newKey);\n\n const index = this._olmAdapter.updateCurrentMediaKey(this._key);\n\n this.e2eeCtx.setKey(this.conference.myUserId(), this._key, index);\n }\n\n /**\n * Handles an update in a participant's key.\n *\n * @param {string} id - The participant ID.\n * @param {Uint8Array | boolean} key - The new key for the participant.\n * @param {Number} index - The new key's index.\n * @private\n */\n _onParticipantKeyUpdated(id, key, index) {\n logger.debug(`Participant ${id} updated their key`);\n\n this.e2eeCtx.setKey(id, key, index);\n }\n\n /**\n * Handles the SAS ready event.\n *\n * @param {string} pId - The participant ID.\n * @param {Uint8Array} sas - The bytes from sas.generate_bytes..\n * @private\n */\n _onParticipantSasReady(pId, sas) {\n this.conference.eventEmitter.emit(JitsiConferenceEvents.E2EE_VERIFICATION_READY, pId, sas);\n }\n\n /**\n * Handles the sas available event.\n *\n * @param {string} pId - The participant ID.\n * @private\n */\n _onParticipantSasAvailable(pId) {\n this.conference.eventEmitter.emit(JitsiConferenceEvents.E2EE_VERIFICATION_AVAILABLE, pId);\n }\n\n\n /**\n * Handles the SAS completed event.\n *\n * @param {string} pId - The participant ID.\n * @param {boolean} success - Wheter the verification was succesfull.\n * @private\n */\n _onParticipantVerificationCompleted(pId, success, message) {\n this.conference.eventEmitter.emit(JitsiConferenceEvents.E2EE_VERIFICATION_COMPLETED, pId, success, message);\n }\n\n /**\n * Generates a new 256 bit random key.\n *\n * @returns {Uint8Array}\n * @private\n */\n _generateKey() {\n return window.crypto.getRandomValues(new Uint8Array(32));\n }\n}\n","/**\n * Derives a set of keys from the master key.\n * @param {CryptoKey} material - master key to derive from\n *\n * See https://tools.ietf.org/html/draft-omara-sframe-00#section-4.3.1\n */\nexport async function deriveKeys(material) {\n const info = new ArrayBuffer();\n const textEncoder = new TextEncoder();\n\n // https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/deriveKey#HKDF\n // https://developer.mozilla.org/en-US/docs/Web/API/HkdfParams\n const encryptionKey = await crypto.subtle.deriveKey({\n name: 'HKDF',\n salt: textEncoder.encode('JFrameEncryptionKey'),\n hash: 'SHA-256',\n info\n }, material, {\n name: 'AES-GCM',\n length: 128\n }, false, [ 'encrypt', 'decrypt' ]);\n\n return {\n material,\n encryptionKey\n };\n}\n\n/**\n * Ratchets a key. See\n * https://tools.ietf.org/html/draft-omara-sframe-00#section-4.3.5.1\n * @param {CryptoKey} material - base key material\n * @returns {Promise} - ratcheted key material\n */\nexport async function ratchet(material) {\n const textEncoder = new TextEncoder();\n\n // https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/deriveBits\n return crypto.subtle.deriveBits({\n name: 'HKDF',\n salt: textEncoder.encode('JFrameRatchetKey'),\n hash: 'SHA-256',\n info: new ArrayBuffer()\n }, material, 256);\n}\n\n/**\n * Converts a raw key into a WebCrypto key object with default options\n * suitable for our usage.\n * @param {ArrayBuffer} keyBytes - raw key\n * @param {Array} keyUsages - key usages, see importKey documentation\n * @returns {Promise} - the WebCrypto key.\n */\nexport async function importKey(keyBytes) {\n // https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/importKey\n return crypto.subtle.importKey('raw', keyBytes, 'HKDF', false, [ 'deriveBits', 'deriveKey' ]);\n}\n","import browser from '../browser';\n\nimport { ExternallyManagedKeyHandler } from './ExternallyManagedKeyHandler';\nimport { ManagedKeyHandler } from './ManagedKeyHandler';\nimport { OlmAdapter } from './OlmAdapter';\n\n/**\n * This module integrates {@link KeyHandler} with {@link JitsiConference} in order to enable E2E encryption.\n */\nexport class E2EEncryption {\n /**\n * A constructor.\n * @param {JitsiConference} conference - The conference instance for which E2E encryption is to be enabled.\n */\n constructor(conference) {\n const { e2ee = {} } = conference.options.config;\n\n this._externallyManaged = e2ee.externallyManagedKey;\n\n if (this._externallyManaged) {\n this._keyHandler = new ExternallyManagedKeyHandler(conference);\n } else {\n this._keyHandler = new ManagedKeyHandler(conference);\n }\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 const { e2ee = {} } = config;\n\n if (!e2ee.externallyManagedKey && !OlmAdapter.isSupported()) {\n return false;\n }\n\n return !(config.testing && config.testing.disableE2EE)\n && (browser.supportsInsertableStreams()\n || (config.enableEncodedTransformSupport && browser.supportsEncodedTransform()));\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 /**\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) {\n await this._keyHandler.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 setEncryptionKey(keyInfo) {\n this._keyHandler.setKey(keyInfo);\n }\n\n /**\n * Starts the verification process of the participant\n *\n * @param {Participant} - participant to be verified.\n * @returns {void}\n */\n startVerification(participant) {\n this._keyHandler.sasVerification?.startVerification(participant);\n }\n\n /**\n * Marks the channel as verified\n *\n * @param {Participant} - participant to be verified.\n * @param {boolean} isVerified - whether the verification was succesfull.\n * @returns {void}\n */\n markParticipantVerified(participant, isVerified) {\n this._keyHandler.sasVerification?.markParticipantVerified(participant, isVerified);\n }\n}\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, len) {\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, b, c, d) {\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) {\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, data) {\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, 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/*\n * Bitwise rotate a 32-bit number to the left.\n */\nfunction rol(num, cnt) {\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) {\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) {\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) {\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, data){ return binb2b64(core_hmac_sha1(key, data)); },\n b64_sha1: function (s) { 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, data){ return binb2str(core_hmac_sha1(key, data)); },\n str_sha1: function (s) { return binb2str(core_sha1(str2binb(s),s.length * 8)); },\n};\nexport { SHA1 as default };\n","import $ from 'jquery';\nimport { Strophe } from 'strophe.js'; // eslint-disable-line camelcase\n\nimport { XMPPEvents } from '../../service/xmpp/XMPPEvents';\nimport Listenable from '../util/Listenable';\n\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\n/**\n *\n * @param a\n * @param b\n */\nfunction compareIdentities(a, b) {\n let res = 0;\n\n IDENTITY_PROPERTIES_FOR_COMPARE.some(key =>\n (res = ((a[key] > b[key]) && 1) || ((a[key] < b[key]) && -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} identities - The identity objects.\n * @param {Array} features - The features.\n * @returns {string}\n */\nfunction generateSha(identities, features) {\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] ? identity[key] : ''),\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, identities: Set}}\n */\nexport function parseDiscoInfo(node) {\n const features = new Set();\n const identities = new Set();\n\n $(node).find('>query>feature')\n .each((_, el) => features.add(el.getAttribute('var')));\n $(node).find('>query>identity')\n .each((_, el) => identities.add({\n type: el.getAttribute('type'),\n name: el.getAttribute('name'),\n category: el.getAttribute('category')\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 /**\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 = {}, node = '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();\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();\n\n const emuc = connection.emuc;\n\n emuc.addListener(XMPPEvents.EMUC_ROOM_ADDED,\n room => this._addChatRoom(room));\n emuc.addListener(XMPPEvents.EMUC_ROOM_REMOVED,\n room => this._removeChatRoom(room));\n Object.keys(emuc.rooms).forEach(jid => {\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 * 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 addFeature(feature, submit = false, external = false) {\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 * 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 removeFeature(feature, submit = false, external = false) {\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 submit() {\n this.rooms.forEach(room => room.sendPresence());\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 _updateRoomWithExternalFeatures(room) {\n if (this.externalFeatures.size === 0) {\n room.removeFromPresence('features');\n } else {\n const children = [];\n\n this.externalFeatures.forEach(f => {\n children.push({\n 'tagName': 'feature',\n attributes: { 'var': f }\n });\n });\n\n room.addOrReplaceInPresence('features', { children });\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>}\n */\n getFeaturesAndIdentities(jid, node, timeout = 5000) {\n return this._getDiscoInfo(jid, node, timeout);\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}\n * @private\n */\n _getDiscoInfo(jid, node, timeout) {\n return new Promise((resolve, reject) =>\n this.disco.info(jid, node, response => {\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 _addChatRoom(room) {\n this.rooms.add(room);\n this._fixChatRoomPresenceMap(room);\n\n this._updateRoomWithExternalFeatures(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 _removeChatRoom(room) {\n this.rooms.delete(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 _fixChatRoomPresenceMap(room) {\n room.addOrReplaceInPresence('c', {\n attributes: {\n xmlns: Strophe.NS.CAPS,\n hash: HASH,\n node: this.node,\n ver: this.version\n }\n });\n }\n\n /**\n * Handles this.version changes.\n */\n _notifyVersionChanged() {\n // update the version for all rooms\n this.rooms.forEach(room => this._fixChatRoomPresenceMap(room));\n }\n\n /**\n * Generates the value for the \"ver\" attribute.\n */\n _generateVersion() {\n this.version\n = generateSha(this.disco._identities, this.disco._features);\n\n this._notifyVersionChanged();\n }\n}\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(__filename);\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 /**\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 }) {\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() {\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, minDelay = 500, base = 2) {\n return Math.floor((Math.random() * ((Math.pow(base, retry) * 1000) - minDelay)) + minDelay);\n}\n","import { getLogger } from '@jitsi/logger';\n\nimport {\n NETWORK_INFO_EVENT,\n default as NetworkInfo\n} from '../connectivity/NetworkInfo';\nimport { getJitterDelay } from '../util/Retry';\n\nconst logger = getLogger(__filename);\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 /**\n * Initializes new {@code RetryTask}.\n * @param {Strophe.Connection} stropheConnection - The Strophe connection instance.\n */\n constructor(stropheConnection) {\n this._stropheConn = stropheConnection;\n\n /**\n * The counter increased before each resume retry attempt, used to calculate exponential backoff.\n * @type {number}\n * @private\n */\n this._resumeRetryN = 0;\n\n this._retryDelay = undefined;\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() {\n return this._retryDelay;\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() {\n this._cancelResume();\n this._removeNetworkOnlineListener();\n\n this._resumeRetryN += 1;\n\n this._networkOnlineListener\n = NetworkInfo.addCancellableListener(\n NETWORK_INFO_EVENT,\n ({ isOnline }) => {\n if (isOnline) {\n this._scheduleResume();\n } else {\n this._cancelResume();\n }\n });\n\n NetworkInfo.isOnline() && this._scheduleResume();\n }\n\n /**\n * Schedules a delayed timeout which will execute the resume action.\n * @private\n * @returns {void}\n */\n _scheduleResume() {\n if (this._resumeTimeout) {\n\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._resumeRetryN = Math.min(3, this._resumeRetryN);\n this._retryDelay = getJitterDelay(\n /* retry */ this._resumeRetryN,\n /* minDelay */ this._resumeRetryN * 1500,\n 3);\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 * @private\n * @returns {void}\n */\n _cancelResume() {\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 * Removes network online listener for the NETWORK_INFO_EVENT event.\n *\n * @private\n * @returns {void}\n */\n _removeNetworkOnlineListener() {\n if (this._networkOnlineListener) {\n this._networkOnlineListener();\n this._networkOnlineListener = null;\n }\n }\n\n /**\n * Resumes the XMPP connection using the stream management plugin.\n *\n * @private\n * @returns {void}\n */\n _resumeConnection() {\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 connnection', 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() {\n this._cancelResume();\n this._removeNetworkOnlineListener();\n this._resumeRetryN = 0;\n }\n}\n","/**\n * Attaches to the {@link Strophe.Connection.rawInput} which is called whenever any data is received from the server.\n */\nexport default class LastRequestTracker {\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 {Object} stropheConnection - Strophe connection instance.\n */\n startTracking(xmppConnection, stropheConnection) {\n const originalRawInput = stropheConnection.rawInput;\n\n stropheConnection.rawInput = (...args) => {\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 {string|null}\n */\n getLastFailedMessage() {\n return this._lastFailedMessage;\n }\n\n /**\n * Returns how many milliseconds have passed since the last successful BOSH request.\n *\n * @returns {number|null}\n */\n getTimeSinceLastSuccess() {\n return this._lastSuccess\n ? Date.now() - this._lastSuccess\n : null;\n }\n}\n","import Listenable from '../util/Listenable';\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(base = class {}) {\n /**\n * Base class for strophe connection plugins.\n */\n return class extends base {\n /**\n *\n */\n constructor(...args) {\n super(...args);\n this.connection = null;\n }\n\n /**\n *\n * @param connection\n */\n init(connection) {\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\n = getConnectionPluginDefinition(Listenable);\n","import { getLogger } from '@jitsi/logger';\nimport { $iq, Strophe } from 'strophe.js';\n\nimport ConnectionPlugin from './ConnectionPlugin';\n\n\nconst logger = getLogger(__filename);\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\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 /**\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 = {} }) {\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 init(connection) {\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 jid\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 error callback is called with undefined error argument.\n */\n ping(jid, success, error, timeout) {\n this._addPingExecutionTimestamp();\n\n const iq = $iq({\n type: 'get',\n to: jid\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 stopInterval\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) {\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 && 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() {\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() {\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() {\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';\nimport 'strophejs-plugin-stream-management';\n\nimport Listenable from '../util/Listenable';\n\nimport ResumeTask from './ResumeTask';\nimport LastSuccessTracker from './StropheLastSuccess';\nimport PingConnectionPlugin from './strophe.ping';\n\nconst logger = getLogger(__filename);\n\n/**\n * The lib-jitsi-meet layer for {@link Strophe.Connection}.\n */\nexport default class XmppConnection extends Listenable {\n /**\n * The list of {@link XmppConnection} events.\n *\n * @returns {Object}\n */\n static get Events() {\n return {\n CONN_STATUS_CHANGED: 'CONN_STATUS_CHANGED',\n CONN_SHARD_CHANGED: 'CONN_SHARD_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;\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 }) {\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 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}\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() {\n const websocket = this._stropheConn && this._stropheConn._proto && 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() {\n return this._stropheConn.disconnecting === true;\n }\n\n /**\n * A getter for the domain.\n *\n * @returns {string|null}\n */\n get domain() {\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() {\n return this._usesWebsocket;\n }\n\n /**\n * A getter for the JID.\n *\n * @returns {string|null}\n */\n get jid() {\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() {\n return this._stropheConn._proto && 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() {\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() {\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) {\n this._options.shard = value;\n\n // shard setting changed so let's schedule a new keep-alive check if connected\n if (this._oneSuccessfulConnect) {\n this._maybeStartWSKeepAlive();\n }\n }\n\n /**\n * Returns the current connection status.\n *\n * @returns {Strophe.Status}\n */\n get 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 {ConnectionPluginListenable} plugin - The plugin to add.\n */\n addConnectionPlugin(name, plugin) {\n this[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) {\n return this._stropheConn.addHandler(...args);\n }\n\n /**\n * See {@link Strophe.Connection.deleteHandler}\n *\n * @returns {void}\n */\n deleteHandler(...args) {\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, sid, rid, callback, ...args) {\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, pass, callback, ...args) {\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, status, ...args) {\n this._status = status;\n\n let blockCallback = false;\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 && this._oneSuccessfulConnect) {\n this._keepAliveAndCheckShard();\n }\n this._oneSuccessfulConnect = true;\n\n this._maybeStartWSKeepAlive();\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 // FIXME add RECONNECTING state instead of blocking the DISCONNECTED update\n blockCallback = this._tryResumingConnection();\n if (!blockCallback) {\n clearTimeout(this._wsKeepAlive);\n }\n }\n\n if (!blockCallback) {\n targetCallback(status, ...args);\n this.eventEmitter.emit(XmppConnection.Events.CONN_STATUS_CHANGED, status);\n }\n }\n\n /**\n * Clears the list of IQs and rejects deferred Promises with an error.\n *\n * @private\n */\n _clearDeferredIQs() {\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() {\n if (this._stropheConn && 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) {\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) {\n this._stropheConn.flush(...args);\n }\n\n /**\n * See {@link LastRequestTracker.getTimeSinceLastSuccess}.\n *\n * @returns {number|null}\n */\n getTimeSinceLastSuccess() {\n return this._rawInputTracker.getTimeSinceLastSuccess();\n }\n\n /**\n * See {@link LastRequestTracker.getLastFailedMessage}.\n *\n * @returns {string|null}\n */\n getLastFailedMessage() {\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() {\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 * @private\n * @returns {void}\n */\n _maybeStartWSKeepAlive() {\n const { websocketKeepAlive } = this._options;\n\n if (this._usesWebsocket && websocketKeepAlive > 0) {\n this._wsKeepAlive || logger.info(`WebSocket keep alive interval: ${websocketKeepAlive}ms`);\n clearTimeout(this._wsKeepAlive);\n\n const intervalWithJitter = /* base */ websocketKeepAlive + /* jitter */ (Math.random() * 60 * 1000);\n\n logger.debug(`Scheduling next WebSocket keep-alive in ${intervalWithJitter}ms`);\n\n this._wsKeepAlive = setTimeout(\n () => this._keepAliveAndCheckShard()\n .then(() => this._maybeStartWSKeepAlive()),\n intervalWithJitter);\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() {\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 if (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() {\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) {\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, callback, errback, timeout) {\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, { timeout }) {\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 = {\n iq,\n resolve,\n reject,\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() {\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, callback, errback, timeout) {\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() {\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 xmlns: Strophe.NS.CLIENT,\n type: 'unavailable'\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}\n */\n _tryResumingConnection() {\n const { streamManagement } = this._stropheConn;\n const resumeToken = streamManagement && streamManagement.getResumeToken();\n\n if (resumeToken) {\n this._resumeTask.schedule();\n\n return true;\n }\n\n return false;\n }\n}\n","/* eslint-disable newline-per-chained-call */\nimport { getLogger } from '@jitsi/logger';\nimport $ from 'jquery';\nimport { $iq } from 'strophe.js';\n\nimport { NOT_LIVE_ERROR } from '../../JitsiConnectionErrors';\nimport { CONNECTION_FAILED, CONNECTION_REDIRECTED } from '../../JitsiConnectionEvents';\nimport Settings from '../settings/Settings';\nimport Listenable from '../util/Listenable';\n\nconst AuthenticationEvents\n = require('../../service/authentication/AuthenticationEvents');\nconst { XMPPEvents } = require('../../service/xmpp/XMPPEvents');\n\nconst logger = getLogger(__filename);\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 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 if (window.addEventListener) {\n window.addEventListener('message', listener, false);\n } else {\n window.attachEvent('onmessage', listener);\n }\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 properties,\n machineUid: Settings.machineId,\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 xmlns: 'http://jitsi.org/protocol/focus',\n room: roomJid,\n 'machine-uid': conferenceRequest.machineUid\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 conferenceRequest.focusJid = $(resultIq)\n .find('conference')\n .attr('focusjid');\n conferenceRequest.sessionId = $(resultIq)\n .find('conference')\n .attr('session-id');\n conferenceRequest.identity = $(resultIq)\n .find('>conference')\n .attr('identity');\n conferenceRequest.ready = $(resultIq)\n .find('conference')\n .attr('ready') === 'true';\n conferenceRequest.vnode = $(resultIq)\n .find('conference')\n .attr('vnode');\n\n if ($(resultIq).find('>conference>property[name=\\'authentication\\'][value=\\'true\\']').length > 0) {\n conferenceRequest.properties.authentication = 'true';\n }\n\n if ($(resultIq).find('>conference>property[name=\\'externalAuth\\'][value=\\'true\\']').length > 0) {\n conferenceRequest.properties.externalAuth = 'true';\n }\n\n // Check if jicofo has jigasi support enabled.\n if ($(resultIq).find('>conference>property[name=\\'sipGatewayEnabled\\'][value=\\'true\\']').length > 0) {\n conferenceRequest.properties.sipGatewayEnabled = 'true';\n }\n\n // check for explicit false, all other cases is considered live\n if ($(resultIq).find('>conference>property[name=\\'live\\'][value=\\'false\\']').length > 0) {\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 => {\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),\n error => this._handleIqError(roomJid, error, resolve));\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 method: 'POST',\n body: JSON.stringify(this._createConferenceRequest(roomJid)),\n headers: { 'Content-Type': 'application/json' }\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);\n })\n .catch(error => {\n logger.warn(`Error: ${error}`);\n this._handleError(roomJid);\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);\n });\n })\n .catch(error => {\n logger.warn(`Error: ${error}`);\n this._handleError(roomJid);\n });\n }\n }).then(() => {\n this.conferenceRequestSent = true;\n });\n }\n\n /**\n * Handles success response for conference IQ.\n * @param roomJid\n * @param conferenceRequest\n * @param callback\n * @private\n */\n _handleSuccess(roomJid, conferenceRequest, callback) {\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' && this.options.preferVisitor) {\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 return;\n }\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 if (conferenceRequest.vnode && !this.options.iAmRecorder && !this.options.iAmSipGateway) {\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 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),\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 * @private\n */\n _handleError(roomJid, sessionError, notAuthorized, callback) {\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 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), 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 // TODO: change the event name to something accurate.\n this.eventEmitter.emit(XMPPEvents.FOCUS_DISCONNECTED);\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 */\n _handleIqError(roomJid, error, callback) {\n // The reservation system only works over XMPP. Handle the error separately.\n // Check for error returned by the reservation system\n const reservationErr = $(error).find('>error>reservation-error');\n\n if (reservationErr.length) {\n // Trigger error event\n const errorCode = reservationErr.attr('error-code');\n const errorTextNode = $(error).find('>error>text');\n let errorMsg;\n\n if (errorTextNode) {\n errorMsg = errorTextNode.text();\n }\n this.eventEmitter.emit(\n XMPPEvents.RESERVATION_ERROR,\n errorCode,\n errorMsg);\n\n return;\n }\n\n const invalidSession = Boolean($(error).find('>error>session-invalid').length\n || $(error).find('>error>not-acceptable').length);\n\n // Not authorized to create new room\n const notAuthorized = $(error).find('>error>not-authorized').length > 0;\n\n this._handleError(roomJid, invalidSession, notAuthorized, callback);\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 */\n _handleIqSuccess(roomJid, result, callback) {\n // Setup config options\n const conferenceRequest = this._parseConferenceIq(result);\n\n this._handleSuccess(roomJid, conferenceRequest, callback);\n }\n\n /**\n * Authenticate by sending a conference IQ.\n * @param roomJid The room jid.\n * @returns {Promise}\n */\n authenticate(roomJid) {\n return new Promise((resolve, reject) => {\n this.connection.sendIQ(\n this._createConferenceIq(roomJid),\n result => {\n const sessionId = $(result)\n .find('conference')\n .attr('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 => reject({\n error: $(errorIq)\n .find('iq>error :first')\n .prop('tagName'),\n message: $(errorIq)\n .find('iq>error>text')\n .text()\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 xmlns: 'http://jitsi.org/protocol/focus',\n 'session-id': sessionId\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 logger.error('Logout error', error);\n }\n );\n }\n}\n","export enum JitsiTranscriptionStatus {\n /**\n * The transcription is on.\n */\n ON = 'on',\n\n /**\n * The transcription is off.\n */\n OFF = 'off'\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\nconst logger = getLogger(__filename);\n\n/**\n * The AVModeration logic.\n */\nexport default class AVModeration {\n\n /**\n * Constructs AV moderation room.\n *\n * @param {ChatRoom} room the main room.\n */\n constructor(room) {\n this._xmpp = room.xmpp;\n\n this._mainRoom = room;\n\n this._moderationEnabledByType = {\n [MediaType.AUDIO]: false,\n [MediaType.VIDEO]: false\n };\n\n this._whitelistAudio = [];\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, 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, jid) {\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 mediaType,\n jidToWhitelist: jid }).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, jid) {\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 mediaType,\n jidToBlacklist: jid\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) {\n const { removed, mediaType: media, enabled, approved, actor, whitelists: newWhitelists } = obj;\n\n if (newWhitelists) {\n const oldList = media === MediaType.AUDIO\n ? this._whitelistAudio\n : this._whitelistVideo;\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 if (media === MediaType.AUDIO) {\n this._whitelistAudio = newList;\n } else {\n this._whitelistVideo = newList;\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(__filename);\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 const message = {\n type: BREAKOUT_ROOM_ACTIONS.ADD,\n subject\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 const message = {\n type: BREAKOUT_ROOM_ACTIONS.REMOVE,\n breakoutRoomJid\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 const message = {\n type: BREAKOUT_ROOM_ACTIONS.RENAME,\n breakoutRoomJid,\n subject\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 const message = {\n type: BREAKOUT_ROOM_ACTIONS.MOVE_TO_ROOM,\n participantJid,\n roomJid\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","import { getLogger } from '@jitsi/logger';\nimport { $msg, Strophe } from 'strophe.js';\n\nimport { XMPPEvents } from '../../service/xmpp/XMPPEvents';\n\nconst logger = getLogger(__filename);\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 * 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 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 return;\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_NOT_ALLOWED_ERROR, reject);\n this.lobbyRoom.addEventListener(XMPPEvents.ROOM_CONNECT_ERROR, reject);\n\n this.lobbyRoom.join();\n });\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 logger.error(`Error sending invite for ${membersToApprove}`, e);\n });\n }\n }\n}\n","import { getLogger } from '@jitsi/logger';\nimport isEqual from 'lodash.isequal';\nimport { $msg } from 'strophe.js';\n\nimport { XMPPEvents } from '../../service/xmpp/XMPPEvents';\n\nimport { JITSI_MEET_MUC_TYPE } from './xmpp';\n\nconst logger = getLogger(__filename);\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() || !this.room.isModerator()) {\n logger.error(`Cannot set room metadata - supported:${this.isSupported()},\n moderator:${this.room.isModerator()}`);\n\n return;\n }\n\n const message = {\n key,\n data\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 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 { safeJsonParse } from '@jitsi/js-utils/json';\nimport { getLogger } from '@jitsi/logger';\nimport $ from 'jquery';\nimport isEqual from 'lodash.isequal';\nimport { $iq, $msg, $pres, Strophe } from 'strophe.js';\nimport { v4 as uuidv4 } from 'uuid';\n\nimport { AUTH_ERROR_TYPES } from '../../JitsiConferenceErrors';\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';\n\nimport AVModeration from './AVModeration';\nimport BreakoutRooms from './BreakoutRooms';\nimport Lobby from './Lobby';\nimport RoomMetadata from './RoomMetadata';\nimport XmppConnection from './XmppConnection';\n\nconst logger = getLogger(__filename);\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 packet2JSON(xmlElement, nodes) {\n for (const child of Array.from(xmlElement.children)) {\n const node = {\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 json2packet(nodes, packet) {\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};\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, nodeName) {\n const res = [];\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, hiddenFromRecorderFeatureEnabled) {\n const identity = {};\n const userInfo = node.children.find(c => c.tagName === 'user');\n\n if (userInfo) {\n identity.user = {};\n const tags = [ 'id', 'name', 'avatar' ];\n\n if (hiddenFromRecorderFeatureEnabled) {\n tags.push('hidden-from-recorder');\n }\n\n for (const tag of tags) {\n const child\n = userInfo.children.find(c => c.tagName === tag);\n\n if (child) {\n identity.user[tag] = child.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 /* 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, jid, password, xmpp, options) {\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 = {};\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\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.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\n /* eslint-enable max-params */\n\n /**\n *\n */\n initPresenceMap(options = {}) {\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 * 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 join(password, replaceParticipant) {\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 : 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 });\n }\n\n /**\n *\n * @param fromJoin - Whether this is initial presence to join the room.\n */\n sendPresence(fromJoin) {\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 // 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 doLeave(reason) {\n logger.log('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 discoRoomInfo() {\n // https://xmpp.org/extensions/xep-0045.html#disco-roominfo\n\n const getInfo\n = $iq({\n type: 'get',\n to: this.roomjid\n })\n .c('query', { xmlns: Strophe.NS.DISCO_INFO });\n\n this.connection.sendIQ(getInfo, result => {\n const locked\n = $(result).find('>query>feature[var=\"muc_passwordprotected\"]')\n .length\n === 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\n = $(result).find('>query>x[type=\"result\"]>field[var=\"muc#roominfo_meetingId\"]>value');\n\n if (meetingIdValEl.length) {\n this.setMeetingId(meetingIdValEl.text());\n } else {\n logger.warn('No meeting ID from backend');\n }\n\n const meetingCreatedTSValEl\n = $(result).find('>query>x[type=\"result\"]>field[var=\"muc#roominfo_created_timestamp\"]>value');\n\n if (meetingCreatedTSValEl.length) {\n this.eventEmitter.emit(XMPPEvents.CONFERENCE_TIMESTAMP_RECEIVED, meetingCreatedTSValEl.text());\n } else {\n logger.warn('No conference duration from backend');\n }\n\n const membersOnly = $(result).find('>query>feature[var=\"muc_membersonly\"]').length === 1;\n\n const lobbyRoomField\n = $(result).find('>query>x[type=\"result\"]>field[var=\"muc#roominfo_lobbyroom\"]>value');\n\n if (this.lobby) {\n this.lobby.setLobbyRoomJid(lobbyRoomField && lobbyRoomField.length ? lobbyRoomField.text() : undefined);\n }\n\n const isBreakoutField\n = $(result).find('>query>x[type=\"result\"]>field[var=\"muc#roominfo_isbreakout\"]>value');\n const isBreakoutRoom = Boolean(isBreakoutField?.text());\n\n this.breakoutRooms._setIsBreakoutRoom(isBreakoutRoom);\n\n const breakoutMainRoomField\n = $(result).find('>query>x[type=\"result\"]>field[var=\"muc#roominfo_breakout_main_room\"]>value');\n\n if (breakoutMainRoomField?.length) {\n this.breakoutRooms._setMainRoomJid(breakoutMainRoomField.text());\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 visitorsSupported = $(result)\n .find('>query>x[type=\"result\"]>field[var=\"muc#roominfo_visitorsEnabled\"]>value').text() === '1';\n\n if (visitorsSupported !== this.visitorsSupported) {\n this.visitorsSupported = visitorsSupported;\n this.eventEmitter.emit(XMPPEvents.MUC_VISITORS_SUPPORTED_CHANGED, visitorsSupported);\n }\n\n const roomMetadataEl\n = $(result).find('>query>x[type=\"result\"]>field[var=\"muc#roominfo_jitsimetadata\"]>value');\n const roomMetadataText = roomMetadataEl?.text();\n\n if (roomMetadataText) {\n try {\n this.roomMetadata._handleMessages(safeJsonParse(roomMetadataText));\n } catch (e) {\n logger.warn('Failed to set room metadata', e);\n }\n }\n\n this.initialDiscoRoomInfoReceived = true;\n this.eventEmitter.emit(XMPPEvents.ROOM_DISCO_INFO_UPDATED);\n }, error => {\n logger.error('Error getting room info: ', error);\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 setMeetingId(meetingId) {\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 createNonAnonymousRoom() {\n // http://xmpp.org/extensions/xep-0045.html#createroom-reserved\n\n if (this.options.disableDiscoInfo) {\n return;\n }\n\n const getForm = $iq({ type: 'get',\n to: this.roomjid })\n .c('query', { xmlns: 'http://jabber.org/protocol/muc#owner' })\n .c('x', { xmlns: 'jabber:x:data',\n type: 'submit' });\n\n this.connection.sendIQ(getForm, form => {\n if (!$(form).find(\n '>query>x[xmlns=\"jabber:x:data\"]'\n + '>field[var=\"muc#roomconfig_whois\"]').length) {\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', { xmlns: 'jabber:x:data',\n type: 'submit' });\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);\n\n }, error => {\n logger.error('Error getting room configuration form: ', error);\n });\n }\n\n /**\n * Handles Xmpp Connection status updates.\n *\n * @param {Strophe.Status} status - The Strophe connection status.\n */\n onConnStatusChanged(status) {\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 pres\n */\n onPresence(pres) {\n const from = pres.getAttribute('from');\n const member = {};\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 && xElement.getElementsByTagName('item')[0];\n\n member.isReplaceParticipant\n = pres.getElementsByTagName('flip_device').length;\n\n member.affiliation\n = mucUserItem && mucUserItem.getAttribute('affiliation');\n member.role = mucUserItem && mucUserItem.getAttribute('role');\n\n // Focus recognition\n const jid = mucUserItem && mucUserItem.getAttribute('jid');\n\n member.jid = jid;\n member.isFocus = this.xmpp.moderator.isFocusJid(jid);\n member.isHiddenDomain\n = jid && 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 presence: pres\n });\n\n const xEl = pres.querySelector('x');\n\n if (xEl) {\n xEl.remove();\n }\n\n const nodes = [];\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 = 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 '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.log('(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\n = member.affiliation === 'owner' ? member.role : 'none';\n\n if (this.role !== newRole) {\n this.role = newRole;\n this.eventEmitter.emit(\n XMPPEvents.LOCAL_ROLE_CHANGED,\n this.role);\n }\n if (!this.joined) {\n this.joined = true;\n const now = this.connectionTimes['muc.joined']\n = window.performance.now();\n\n logger.log('(TIME) MUC joined:\\t', now);\n\n // set correct initial state of locked\n if (this.password) {\n this.locked = true;\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 } 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.log('entered', from, member);\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 // .\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 // 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 = 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 && attributes.key) {\n properties[attributes.key] = attributes.value;\n }\n }\n\n this.eventEmitter.emit(XMPPEvents.CONFERENCE_PROPERTIES_CHANGED, properties);\n\n // Log if Jicofo supports restart by terminate only once. This conference property does not change\n // during the call.\n if (typeof this.restartByTerminateSupported === 'undefined') {\n this.restartByTerminateSupported = properties['support-terminate-restart'] === 'true';\n logger.info(`Jicofo supports restart by terminate: ${this.supportsRestartByTerminate()}`);\n }\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 this.transcriptionStatus = status;\n this.eventEmitter.emit(\n XMPPEvents.TRANSCRIPTION_STATUS_CHANGED,\n status\n );\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 default:\n this.processNode(node, from);\n }\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 * 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 _extractFeatures(node) {\n const features = new Set();\n\n for (let j = 0; j < node.children.length; j++) {\n const { attributes } = node.children[j];\n\n if (attributes && 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 _initFocus(from, features) {\n this.focusMucJid = from;\n this.focusFeatures = features;\n }\n\n /**\n * Sets the special listener to be used for \"command\"s whose name starts\n * with \"jitsi_participant_\".\n */\n setParticipantPropertyListener(listener) {\n this.participantPropertyListener = listener;\n }\n\n /**\n * Checks if Jicofo supports restarting Jingle session after 'session-terminate'.\n * @returns {boolean}\n */\n supportsRestartByTerminate() {\n return this.restartByTerminateSupported;\n }\n\n /**\n *\n * @param node\n * @param from\n */\n processNode(node, from) {\n // make sure we catch all errors coming from any handler\n // otherwise we can remove the presence handler from strophe\n try {\n let tagHandlers = this.presHandlers[node.tagName];\n\n if (node.tagName.startsWith('jitsi_participant_')) {\n tagHandlers = [ this.participantPropertyListener ];\n }\n\n if (tagHandlers) {\n tagHandlers.forEach(handler => {\n handler(node, Strophe.getResourceFromJid(from), from);\n });\n }\n } catch (e) {\n logger.error(`Error processing:${node.tagName} node.`, e);\n }\n }\n\n /**\n * Send text message to the other participants in the conference\n * @param message\n * @param elementName\n */\n sendMessage(message, elementName) {\n const msg = $msg({ to: this.roomjid,\n type: 'groupchat' });\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, {}, message);\n } else {\n msg.c(elementName, { xmlns: 'http://jitsi.org/jitmeet' }, message);\n }\n\n this.connection.send(msg);\n this.eventEmitter.emit(XMPPEvents.SENDING_CHAT_MESSAGE, message);\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 sendReaction(reaction, messageId, receiverId) {\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', {}, reaction)\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 */\n sendPrivateMessage(id, message, elementName) {\n const msg = $msg({ to: `${this.roomjid}/${id}`,\n type: 'chat' });\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, message).up();\n } else {\n msg.c(elementName, { xmlns: 'http://jitsi.org/jitmeet' }, message)\n .up();\n }\n\n this.connection.send(msg);\n this.eventEmitter.emit(\n XMPPEvents.SENDING_PRIVATE_CHAT_MESSAGE, message);\n }\n /* eslint-enable max-params */\n\n /**\n *\n * @param subject\n */\n setSubject(subject) {\n const msg = $msg({ to: this.roomjid,\n type: 'groupchat' });\n\n msg.c('subject', subject);\n this.connection.send(msg);\n }\n\n /**\n *\n * @param pres\n * @param from\n */\n onPresenceUnavailable(pres, from) {\n // ignore presence\n if ($(pres).find('>ignore[xmlns=\"http://jitsi.org/jitmeet/\"]').length) {\n return true;\n }\n\n // room destroyed ?\n const destroySelect = $(pres).find('>x[xmlns=\"http://jabber.org/protocol/muc#user\"]>destroy');\n\n if (destroySelect.length) {\n let reason;\n const reasonSelect\n = $(pres).find(\n '>x[xmlns=\"http://jabber.org/protocol/muc#user\"]'\n + '>destroy>reason');\n\n if (reasonSelect.length) {\n reason = reasonSelect.text();\n }\n\n this.eventEmitter.emit(XMPPEvents.MUC_DESTROYED, reason, destroySelect.attr('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\n = $(pres)\n .find(\n '>x[xmlns=\"http://jabber.org/protocol/muc#user\"]>'\n + 'status[code=\"110\"]')\n .length;\n const isKick\n = $(pres)\n .find(\n '>x[xmlns=\"http://jabber.org/protocol/muc#user\"]'\n + '>status[code=\"307\"]')\n .length;\n const membersKeys = Object.keys(this.members);\n const isReplaceParticipant = $(pres).find('flip_device').length;\n\n if (isKick) {\n const actorSelect\n = $(pres)\n .find('>x[xmlns=\"http://jabber.org/protocol/muc#user\"]>item>actor');\n let actorNick;\n\n if (actorSelect.length) {\n actorNick = actorSelect.attr('nick');\n }\n\n let reason;\n const reasonSelect\n = $(pres).find(\n '>x[xmlns=\"http://jabber.org/protocol/muc#user\"]'\n + '>item>reason');\n\n if (reasonSelect.length) {\n reason = reasonSelect.text();\n }\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 = $(pres).find('>status');\n const member = this.members[from];\n let reason;\n\n if (reasonSelect.length) {\n reason = reasonSelect.text();\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 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 */\n onMessage(msg, from) {\n const type = msg.getAttribute('type');\n\n if (type === 'error') {\n const settingsErrorMsg = $(msg).find('>settings-error>text').text();\n\n if (settingsErrorMsg.length) {\n this.eventEmitter.emit(XMPPEvents.SETTINGS_ERROR_RECEIVED, settingsErrorMsg);\n\n return true;\n }\n const errorMsg = $(msg).find('>error>text').text();\n\n this.eventEmitter.emit(XMPPEvents.CHAT_ERROR_RECEIVED, errorMsg);\n\n return true;\n }\n\n const reactions = $(msg).find('>[xmlns=\"urn:xmpp:reactions:0\"]>reaction');\n\n if (reactions.length > 0) {\n const messageId = $(msg).find('>[xmlns=\"urn:xmpp:reactions:0\"]').attr('id');\n const reactionList = [];\n\n reactions.each((_, reactionElem) => {\n const reaction = $(reactionElem).text();\n\n reactionList.push(reaction);\n });\n\n this.eventEmitter.emit(XMPPEvents.REACTION_RECEIVED, from, reactionList, messageId);\n\n return true;\n }\n\n\n const txt = $(msg).find('>body').text();\n const subject = $(msg).find('>subject');\n\n if (subject.length) {\n const subjectText = subject.text();\n\n if (subjectText || subjectText === '') {\n this.eventEmitter.emit(XMPPEvents.SUBJECT_CHANGED, subjectText);\n logger.log(`Subject is changed to ${subjectText}`);\n }\n }\n\n // xep-0203 delay\n let stamp = $(msg).find('>delay').attr('stamp');\n\n if (!stamp) {\n // or xep-0091 delay, UTC timestamp\n stamp = $(msg).find('>[xmlns=\"jabber:x:delay\"]').attr('stamp');\n\n if (stamp) {\n // the format is CCYYMMDDThh:mm:ss\n const dateParts\n = stamp.match(/(\\d{4})(\\d{2})(\\d{2}T\\d{2}:\\d{2}:\\d{2})/);\n\n stamp = `${dateParts[1]}-${dateParts[2]}-${dateParts[3]}Z`;\n }\n }\n\n if (from === this.roomjid) {\n let invite;\n\n if ($(msg).find('>x[xmlns=\"http://jabber.org/protocol/muc#user\"]>status[code=\"104\"]').length) {\n this.discoRoomInfo();\n } else if ((invite = $(msg).find('>x[xmlns=\"http://jabber.org/protocol/muc#user\"]>invite'))\n && invite.length) {\n const passwordSelect = $(msg).find('>x[xmlns=\"http://jabber.org/protocol/muc#user\"]>password');\n let password;\n\n if (passwordSelect && passwordSelect.length) {\n password = passwordSelect.text();\n }\n\n this.eventEmitter.emit(XMPPEvents.INVITE_MESSAGE_RECEIVED,\n from, invite.attr('from'), txt, password);\n }\n }\n\n const jsonMessage = $(msg).find('>json-message').text();\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 undefined.\n // e.g. - subtitles should not be displayed if delayed.\n if (parsedJson && stamp === undefined) {\n this.eventEmitter.emit(XMPPEvents.JSON_MESSAGE_RECEIVED,\n from, parsedJson);\n\n return;\n }\n }\n\n if (txt) {\n\n const messageId = $(msg).attr('id') || uuidv4();\n\n if (type === 'chat') {\n this.eventEmitter.emit(XMPPEvents.PRIVATE_MESSAGE_RECEIVED,\n from, txt, this.myroomjid, stamp, messageId);\n } else if (type === 'groupchat') {\n const nickEl = $(msg).find('>nick');\n let nick;\n\n if (nickEl.length > 0) {\n nick = nickEl.text();\n }\n\n // we will fire explicitly that this is a guest(isGuest:true) to the conference\n // informing that this is probably a message from a guest to the conference (visitor)\n // a message with explicit name set\n this.eventEmitter.emit(XMPPEvents.MESSAGE_RECEIVED,\n from, txt, this.myroomjid, stamp, nick, Boolean(nick), messageId);\n }\n }\n }\n\n /**\n *\n * @param pres\n * @param from\n */\n onPresenceError(pres, from) {\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 if ($(pres)\n .find(\n '>error[type=\"auth\"]'\n + '>not-authorized['\n + 'xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\"]')\n .length) {\n logger.log('on password required', from);\n this.eventEmitter.emit(XMPPEvents.PASSWORD_REQUIRED);\n } else if ($(pres)\n .find(\n '>error[type=\"cancel\"]'\n + '>not-allowed['\n + 'xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\"]')\n .length) {\n const toDomain = Strophe.getDomainFromJid(pres.getAttribute('to'));\n\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 = $(pres).find('>error[type=\"cancel\"]>text[xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\"]');\n const txt = txtNode.length && txtNode.text();\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 type = AUTH_ERROR_TYPES.ROOM_CREATION_RESTRICTION;\n\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 } else if ($(pres).find(\n '>error[type=\"cancel\"]>no-main-participants[xmlns=\"jitsi:visitors\"]').length > 0) {\n type = AUTH_ERROR_TYPES.NO_MAIN_PARTICIPANTS;\n } else if ($(pres).find(\n '>error[type=\"cancel\"]>promotion-not-allowed[xmlns=\"jitsi:visitors\"]').length > 0) {\n type = AUTH_ERROR_TYPES.PROMOTION_NOT_ALLOWED;\n } else if ($(pres).find(\n '>error[type=\"cancel\"]>no-visitors-lobby[xmlns=\"jitsi:visitors\"]').length > 0) {\n type = AUTH_ERROR_TYPES.NO_VISITORS_LOBBY;\n }\n\n this.eventEmitter.emit(XMPPEvents.ROOM_CONNECT_NOT_ALLOWED_ERROR, type, txt);\n }\n } else if ($(pres).find('>error>service-unavailable').length) {\n logger.warn('Maximum users limit for the room has been reached',\n pres);\n this.eventEmitter.emit(XMPPEvents.ROOM_MAX_USERS_ERROR);\n } else if ($(pres)\n .find(\n '>error[type=\"auth\"]'\n + '>registration-required['\n + 'xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\"]').length) {\n\n // let's extract the lobby jid from the custom field\n const lobbyRoomNode = $(pres).find('>error[type=\"auth\"]>lobbyroom');\n let lobbyRoomJid;\n\n if (lobbyRoomNode.length) {\n lobbyRoomJid = lobbyRoomNode.text();\n }\n\n const waitingForHost = $(pres).find('>error[type=\"auth\"]>waiting-for-host').length > 0;\n\n this.eventEmitter.emit(XMPPEvents.ROOM_CONNECT_MEMBERS_ONLY_ERROR, lobbyRoomJid, waitingForHost);\n } else if ((errorDescriptionNode = $(pres).find(\n '>error[type=\"modify\"]>displayname-required[xmlns=\"http://jitsi.org/jitmeet\"]')).length) {\n logger.warn('display name required ', pres);\n this.eventEmitter.emit(XMPPEvents.DISPLAY_NAME_REQUIRED, errorDescriptionNode[0].attributes.lobby?.value);\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 setAffiliation(jid, affiliation) {\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.log('Set affiliation of participant with jid: ', jid, 'to', affiliation, result),\n error => logger.log('Set affiliation of participant error: ', error));\n }\n\n /**\n *\n * @param jid\n * @param reason\n */\n kick(jid, reason = 'You have been kicked.') {\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.log('Kick participant with jid: ', jid, result),\n error => logger.log('Kick participant error: ', error));\n }\n\n /* eslint-disable max-params */\n\n /**\n *\n * @param key\n * @param onSuccess\n * @param onError\n * @param onNotSupported\n */\n lockRoom(key, onSuccess, onError, onNotSupported) {\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 if ($(res)\n .find(\n '>query>x[xmlns=\"jabber:x:data\"]'\n + '>field[var=\"muc#roomconfig_roomsecret\"]')\n .length) {\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 xmlns: 'jabber:x:data',\n type: 'submit'\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 onError);\n } else {\n onNotSupported();\n }\n },\n onError);\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 setMembersOnly(enabled, onSuccess, onError) {\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());\n }\n\n const errorCallback = onError ? onError : () => {}; // eslint-disable-line no-empty-function\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 if ($(res).find('>query>x[xmlns=\"jabber:x:data\"]>field[var=\"muc#roomconfig_membersonly\"]').length) {\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 xmlns: 'jabber:x:data',\n type: 'submit'\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, errorCallback);\n } else {\n errorCallback(new Error('Setting members only room not supported!'));\n }\n },\n errorCallback);\n }\n\n /**\n * Adds the key to the presence map, overriding any previous value.\n * This method is used by jibri.\n *\n * @param key The key to add or replace.\n * @param values The new values.\n * @returns {boolean|null} true if the operation succeeded or false when no add or replce was\n * performed as the value was already there.\n * @deprecated Use 'addOrReplaceInPresence' instead. TODO: remove it from here and jibri.\n */\n addToPresence(key, values) {\n return this.addOrReplaceInPresence(key, values);\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} true if the operation succeeded or false when no add or replace was\n * performed as the value was already there.\n */\n addOrReplaceInPresence(key, values) {\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 */\n getFromPresence(key) {\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 */\n removeFromPresence(key) {\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 */\n addPresenceListener(name, handler) {\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 */\n removePresenceListener(name, handler) {\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 mucJid is the conference\n * focus.\n * @param mucJid the full MUC address of the user to be checked.\n * @returns {boolean|null} true if MUC user is the conference focus\n * or false if is not. When given mucJid does not exist in\n * the MUC then null is returned.\n */\n isFocus(mucJid) {\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 isModerator() {\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 null either if there\n * is no presence available or if the media type given is invalid.\n */\n getMediaPresenceInfo(endpointId, mediaType) {\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 = {\n muted: true, // muted by default\n videoType: mediaType === MediaType.VIDEO ? VideoType.CAMERA : undefined // 'camera' by default\n };\n let mutedNode = 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 getMemberRole(peerJid) {\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 */\n getLastPresence(mucNick) {\n return this.lastPresences[`${this.roomjid}/${mucNick}`];\n }\n\n /**\n * Dials a number.\n * @param number the number\n */\n dial(number) {\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 hangup() {\n return this.connection.rayo.hangup();\n }\n\n /**\n *\n * @returns {Lobby}\n */\n getLobby() {\n return this.lobby;\n }\n\n /**\n * @returns {AVModeration}\n */\n getAVModeration() {\n return this.avModeration;\n }\n\n /**\n * @returns {BreakoutRooms}\n */\n getBreakoutRooms() {\n return this.breakoutRooms;\n }\n\n /**\n * @returns {RoomMetadata}\n */\n getMetadataHandler() {\n return this.roomMetadata;\n }\n\n /**\n * Returns the phone number for joining the conference.\n */\n getPhoneNumber() {\n return this.phoneNumber;\n }\n\n /**\n * Returns the pin for joining the conference with phone.\n */\n getPhonePin() {\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 getMeetingId() {\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 muteParticipant(jid, mute, mediaType) {\n logger.info('set mute', mute, jid);\n const iqToFocus = $iq(\n { to: this.focusMucJid,\n type: 'set' })\n .c('mute', {\n xmlns: `http://jitsi.org/jitmeet/${mediaType}`,\n jid\n })\n .t(mute.toString())\n .up();\n\n this.connection.sendIQ(\n iqToFocus,\n result => logger.log('set mute', result),\n error => logger.log('set mute error', error));\n }\n\n /**\n * TODO: Document\n * @param iq\n */\n onMute(iq) {\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 = $(iq).find('mute');\n\n if (mute.length && mute.text() === 'true') {\n this.eventEmitter.emit(XMPPEvents.AUDIO_MUTED_BY_FOCUS, mute.attr('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 * TODO: Document\n * @param iq\n */\n onMuteVideo(iq) {\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 = $(iq).find('mute');\n\n if (mute.length && mute.text() === 'true') {\n this.eventEmitter.emit(XMPPEvents.VIDEO_MUTED_BY_FOCUS, mute.attr('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 * Clean any listeners or resources, executed on leaving.\n */\n clean() {\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 * 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 leave(reason) {\n this.avModeration.dispose();\n this.breakoutRooms.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 = -1;\n\n const onMucLeft = (doReject = false) => {\n this.eventEmitter.removeListener(XMPPEvents.MUC_LEFT, onMucLeft);\n clearTimeout(timeout);\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();\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();\n }\n }));\n\n return Promise.allSettled(promises);\n }\n\n /**\n * Ends the conference for all participants.\n */\n end() {\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/* eslint-enable newline-per-chained-call */\n","import { getLogger } from '@jitsi/logger';\nimport $ from 'jquery';\nimport { Strophe } from 'strophe.js';\n\nimport { CONNECTION_REDIRECTED } from '../../JitsiConnectionEvents';\nimport { XMPPEvents } from '../../service/xmpp/XMPPEvents';\n\nimport ChatRoom from './ChatRoom';\nimport { ConnectionPluginListenable } from './ConnectionPlugin';\n\nconst logger = getLogger(__filename);\n\n/**\n * MUC connection plugin.\n */\nexport default class MucConnectionPlugin extends ConnectionPluginListenable {\n /**\n *\n * @param xmpp\n */\n constructor(xmpp) {\n super();\n this.xmpp = xmpp;\n this.rooms = {};\n }\n\n /**\n *\n * @param connection\n */\n init(connection) {\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.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, password, options) {\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) {\n return roomJid in this.rooms;\n }\n\n /**\n *\n * @param jid\n */\n doLeave(jid) {\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) {\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 if ($(pres).find('>x[xmlns=\"http://jabber.org/protocol/muc#user\"]'\n + '>status[code=\"201\"]').length) {\n room.createNonAnonymousRoom();\n }\n\n room.onPresence(pres);\n\n return true;\n }\n\n /**\n *\n * @param pres\n */\n onPresenceUnavailable(pres) {\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) {\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) {\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 * TODO: Document\n * @param iq\n */\n onMute(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.onMute(iq);\n\n return true;\n }\n\n /**\n * TODO: Document\n * @param iq\n */\n onMuteVideo(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.onMuteVideo(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) {\n const from = iq.getAttribute('from');\n const room = this.rooms[Strophe.getBareJidFromJid(from)];\n\n if (!room) {\n return true;\n }\n\n const visitors = $(iq).find('>visitors[xmlns=\"jitsi:visitors\"]');\n const response = $(iq).find('promotion-response');\n\n if (visitors.length && response.length) {\n if (String(response.attr('allow')).toLowerCase() === 'true') {\n logger.info('Promotion request accepted. Redirected to main room.');\n this.xmpp.eventEmitter.emit(\n CONNECTION_REDIRECTED, undefined, visitors.attr('focusjid'), response.attr('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 $ from 'jquery';\nimport { $build } from 'strophe.js';\n\nimport { MediaType } from '../../service/RTC/MediaType';\n\nconst logger = getLogger(__filename);\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 * @returns the created \"source\" XML element.\n */\nfunction _createSourceExtension(owner, sourceCompactJson) {\n const node = $build('source', {\n xmlns: 'urn:xmpp:jingle:apps:rtp:ssma:0',\n ssrc: sourceCompactJson.s,\n name: sourceCompactJson.n\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 xmlns: 'http://jitsi.org/jitmeet',\n owner\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) {\n const node = $build('ssrc-group', {\n xmlns: 'urn:xmpp:jingle:apps:rtp:ssma:0',\n semantics: _getSemantics(ssrcGroupCompactJson[0])\n });\n\n for (let i = 1; i < ssrcGroupCompactJson.length; i++) {\n node.c('source', {\n xmlns: 'urn:xmpp:jingle:apps:rtp:ssma:0',\n ssrc: ssrcGroupCompactJson[i]\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, mediaType) {\n const jingle = $(iq).find('jingle')[0];\n let content = $(jingle).find(`content[name=\"${mediaType}\"]`);\n let description;\n\n if (content.length) {\n content = content[0];\n } else {\n // I'm not suree if \"creator\" and \"senders\" are required.\n content = $build('content', {\n name: mediaType\n }).node;\n jingle.appendChild(content);\n }\n\n description = $(content).find('description');\n\n if (description.length) {\n description = description[0];\n } else {\n description = $build('description', {\n xmlns: 'urn:xmpp:jingle:apps:rtp:1',\n media: mediaType\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) {\n if (str === 'f') {\n return 'FID';\n } else if (str === 's') {\n return '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} The audio and video ssrcs extracted from the JSON-encoded message with remote\n * endpoint id as the key.\n */\nexport function expandSourcesFromJson(iq, jsonMessageXml) {\n let json;\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();\n\n for (const owner in json.sources) {\n if (json.sources.hasOwnProperty(owner)) {\n const ssrcs = [];\n const ownerSources = json.sources[owner];\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]));\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 * 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 * 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 * 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","\nimport JitsiTrackError from '../../JitsiTrackError';\nimport * as JitsiTrackErrors from '../../JitsiTrackErrors';\nimport browser from '../browser';\n\nconst logger = require('@jitsi/logger').getLogger(__filename);\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 */\nconst ScreenObtainer = {\n /**\n * If not null it means that the initialization process is still in\n * progress. It is used to make desktop stream request wait and continue\n * after it's done.\n * {@type Promise|null}\n */\n\n obtainStream: null,\n\n /**\n * Initializes the function used to obtain a screen capture\n * (this.obtainStream).\n *\n * @param {object} options\n */\n init(options = {}) {\n this.options = options;\n this.obtainStream = this._createObtainStreamMethod();\n\n if (!this.obtainStream) {\n logger.info('Desktop sharing disabled');\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 _createObtainStreamMethod() {\n if (browser.isElectron()) {\n return this.obtainScreenOnElectron;\n } else if (browser.isReactNative() && browser.supportsGetDisplayMedia()) {\n return this.obtainScreenFromGetDisplayMediaRN;\n } else if (browser.supportsGetDisplayMedia()) {\n return this.obtainScreenFromGetDisplayMedia;\n }\n logger.log('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 {Object|boolean}\n */\n _getAudioConstraints() {\n const { audioQuality } = this.options;\n const audio = audioQuality?.stereo ? {\n autoGainControl: false,\n channelCount: 2,\n echoCancellation: false,\n noiseSuppression: false\n } : true;\n\n return audio;\n },\n\n /**\n * Checks whether obtaining a screen capture is supported in the current\n * environment.\n * @returns {boolean}\n */\n isSupported() {\n return this.obtainStream !== null;\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 obtainScreenOnElectron(onSuccess, onFailure, options = {}) {\n if (window.JitsiMeetScreenObtainer && window.JitsiMeetScreenObtainer.openDesktopPicker) {\n const { desktopSharingFrameRate, desktopSharingResolution, desktopSharingSources } = this.options;\n\n window.JitsiMeetScreenObtainer.openDesktopPicker(\n {\n desktopSharingSources:\n options.desktopSharingSources || desktopSharingSources || [ 'screen', 'window' ]\n },\n (streamId, streamType, screenShareAudio = false) => {\n if (streamId) {\n let audioConstraints = 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.mandatory = {\n chromeMediaSource: 'desktop'\n };\n }\n }\n\n const constraints = {\n audio: audioConstraints,\n video: {\n mandatory: {\n chromeMediaSource: 'desktop',\n chromeMediaSourceId: streamId,\n minFrameRate: desktopSharingFrameRate?.min ?? SS_DEFAULT_FRAME_RATE,\n maxFrameRate: desktopSharingFrameRate?.max ?? SS_DEFAULT_FRAME_RATE,\n minWidth: desktopSharingResolution?.width?.min,\n minHeight: desktopSharingResolution?.height?.min,\n maxWidth: desktopSharingResolution?.width?.max ?? window.screen.width,\n maxHeight: desktopSharingResolution?.height?.max ?? window.screen.height\n }\n }\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 stream,\n sourceId: streamId,\n sourceType: streamType\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 */\n obtainScreenFromGetDisplayMedia(callback, errorCallback) {\n let getDisplayMedia;\n\n if (navigator.getDisplayMedia) {\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 = {};\n const constraintOpts = {};\n const {\n desktopSharingFrameRate,\n screenShareSettings\n } = this.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 video,\n audio,\n ...constraintOpts,\n cursor: 'always'\n };\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 contraints = {\n frameRate: {\n min: minFps\n }\n };\n\n try {\n track.applyConstraints(contraints);\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 callback({\n stream,\n sourceId: stream.id\n });\n })\n .catch(error => {\n const errorDetails = {\n errorName: error && error.name,\n errorMsg: error && error.message,\n errorStack: error && error.stack\n };\n\n logger.error('getDisplayMedia error', JSON.stringify(constraints), JSON.stringify(errorDetails));\n\n if (errorDetails.errorMsg && 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\n return;\n }\n\n errorCallback(new JitsiTrackError(JitsiTrackErrors.SCREENSHARING_USER_CANCELED));\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 */\n obtainScreenFromGetDisplayMediaRN(callback, errorCallback) {\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 stream,\n sourceId: stream.id });\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 setContentHint(stream) {\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 * 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 setDesktopSharingFrameRate(maxFps) {\n logger.info(`Setting the desktop capture rate to ${maxFps}`);\n\n this.options.desktopSharingFrameRate = {\n min: SS_DEFAULT_FRAME_RATE,\n max: maxFps\n };\n }\n};\n\nexport default ScreenObtainer;\n","import { getLogger } from '@jitsi/logger';\nconst logger = getLogger(__filename);\n\nimport { CodecMimeType } from '../../service/RTC/CodecMimeType';\nimport { MediaDirection } from '../../service/RTC/MediaDirection';\nimport browser from '../browser';\nimport RandomUtil from '../util/RandomUtil';\n\nconst SDPUtil = {\n filterSpecialChars(text) {\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 iceparams(mediadesc, sessiondesc) {\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 ufrag: SDPUtil.parseICEUfrag(ufrag),\n pwd: SDPUtil.parseICEPwd(pwd)\n };\n }\n\n return data;\n },\n parseICEUfrag(line) {\n return line.substring(12);\n },\n buildICEUfrag(frag) {\n return `a=ice-ufrag:${frag}`;\n },\n parseICEPwd(line) {\n return line.substring(10);\n },\n buildICEPwd(pwd) {\n return `a=ice-pwd:${pwd}`;\n },\n parseMID(line) {\n return line.substring(6);\n },\n\n /**\n * Finds the MSID attribute in the given array of SSRC attribute lines and returns the value.\n *\n * @param {string[]} ssrcLines - an array of lines similar to 'a:213123 msid:stream-id track-id'.\n * @returns {undefined|string}\n */\n parseMSIDAttribute(ssrcLines) {\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 parseMLine(line) {\n const data = {};\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;\n },\n buildMLine(mline) {\n return (\n `m=${mline.media} ${mline.port} ${mline.proto} ${\n mline.fmt.join(' ')}`);\n },\n parseRTPMap(line) {\n const data = {};\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;\n },\n\n /**\n * Parses SDP line \"a=sctpmap:...\" and extracts SCTP port from it.\n * @param line eg. \"a=sctpmap:5000 webrtc-datachannel\"\n * @returns [SCTP port number, protocol, streams]\n */\n parseSCTPMap(line) {\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 parseSCTPPort(line) {\n return line.substring(12);\n },\n buildRTPMap(el) {\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 parseCrypto(line) {\n const data = {};\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;\n },\n parseFingerprint(line) { // RFC 4572\n const data = {};\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;\n },\n parseFmtp(line) {\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 parseICECandidate(line) {\n const candidate = {};\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;\n },\n buildICECandidate(cand) {\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 parseSSRC(desc) {\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 * Gets the source name out of the name attribute \"a=ssrc:254321 name:name1\".\n *\n * @param {string[]} ssrcLines\n * @returns {string | undefined}\n */\n parseSourceNameLine(ssrcLines) {\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 {string | undefined}\n */\n parseVideoTypeLine(ssrcLines) {\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 parseRTCPFB(line) {\n const parts = line.substr(10).split(' ');\n const data = {};\n\n data.pt = parts.shift();\n data.type = parts.shift();\n data.params = parts;\n\n return data;\n },\n parseExtmap(line) {\n const parts = line.substr(9).split(' ');\n const data = {};\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;\n },\n findLine(haystack, needle, sessionpart) {\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 false;\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 false;\n },\n findLines(haystack, needle, sessionpart) {\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 candidateToJingle(line) {\n // a=candidate:2979166662 1 udp 2113937151 192.168.2.100 57698 typ host\n // generation 0\n // \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 = {};\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;\n },\n candidateFromJingle(cand) {\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 * Parse the 'most' primary video ssrc from the given m line\n * @param {object} mLine object as parsed from transform.parse\n * @return {number} the primary video ssrc from the given m line\n */\n parsePrimaryVideoSsrc(videoMLine) {\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 && 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 = 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 === 'FID');\n\n if (fidGroup) {\n primarySsrc = fidGroup.ssrcs.split(' ')[0];\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 === 'SIM');\n\n if (simGroup) {\n primarySsrc = simGroup.ssrcs.split(' ')[0];\n }\n }\n\n return primarySsrc;\n },\n\n /**\n * Generate an ssrc\n * @returns {number} an ssrc\n */\n generateSsrc() {\n return RandomUtil.randomInt(1, 0xffffffff);\n },\n\n /**\n * Get an attribute for the given ssrc with the given attributeName\n * from the given mline\n * @param {object} mLine an mLine object as parsed from transform.parse\n * @param {number} ssrc the ssrc for which an attribute is desired\n * @param {string} attributeName the name of the desired attribute\n * @returns {string} the value corresponding to the given ssrc\n * and attributeName\n */\n getSsrcAttribute(mLine, ssrc, attributeName) {\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 * Parses the ssrcs from the group sdp line and\n * returns them as a list of numbers\n * @param {object} the ssrcGroup object as parsed from\n * sdp-transform\n * @returns {list} a list of the ssrcs in the group\n * parsed as numbers\n */\n parseGroupSsrcs(ssrcGroup) {\n return ssrcGroup\n .ssrcs\n .split(' ')\n .map(ssrcStr => parseInt(ssrcStr, 10));\n },\n\n /**\n * Get the mline of the given type from the given sdp\n * @param {object} sdp sdp as parsed from transform.parse\n * @param {string} type the type of the desired mline (e.g. \"video\")\n * @returns {object} a media object\n */\n getMedia(sdp, type) {\n return sdp.media.find(m => m.type === type);\n },\n\n /**\n * Extracts the ICE username fragment from an SDP string.\n * @param {string} sdp the SDP in raw text format\n */\n getUfrag(sdp) {\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 * 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 {object} 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, codecName, sortPayloadTypes = false) {\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 * 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 {object} 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, codecName, highProfile = false) {\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 return codec.toLowerCase() === CodecMimeType.VP9\n ? !item.config.includes('profile-id=0')\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(item.payload) !== -1);\n }\n }\n }\n};\n\nexport default SDPUtil;\n","import $ from 'jquery';\nimport clonedeep from 'lodash.clonedeep';\nimport transform from 'sdp-transform';\n\nimport { MediaDirection } from '../../service/RTC/MediaDirection';\nimport browser from '../browser';\n\nimport SDPUtil from './SDPUtil';\n\n/**\n *\n * @param sdp\n */\nexport default function SDP(sdp) {\n const media = sdp.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 const session = `${media.shift()}\\r\\n`;\n\n this.media = media;\n this.raw = session + media.join('');\n this.session = session;\n}\n\n/**\n * A flag will make {@link transportToJingle} and {@link jingle2media} replace\n * ICE candidates IPs with invalid value of '1.1.1.1' which will cause ICE\n * failure. The flag is used in the automated testing.\n * @type {boolean}\n */\nSDP.prototype.failICE = false;\n\n/**\n * Whether or not to remove TCP ice candidates when translating from/to jingle.\n * @type {boolean}\n */\nSDP.prototype.removeTcpCandidates = false;\n\n/**\n * Whether or not to remove UDP ice candidates when translating from/to jingle.\n * @type {boolean}\n */\nSDP.prototype.removeUdpCandidates = false;\n\n/**\n * Adds a new m-line to the description so that a new local source can then be attached to the transceiver that gets\n * added after a reneogtiation cycle.\n *\n * @param {MediaType} mediaType media type of the new source that is being added.\n */\nSDP.prototype.addMlineForNewLocalSource = function(mediaType) {\n const mid = this.media.length;\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 = mid;\n mline.direction = MediaDirection.RECVONLY;\n\n // Remove the ssrcs and source groups.\n mline.msid = undefined;\n mline.ssrcs = undefined;\n mline.ssrcGroups = undefined;\n\n sdp.media = sdp.media.concat(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 const mids = group.mids.split(' ');\n\n mids.push(mid);\n group.mids = mids.join(' ');\n }\n });\n this.raw = transform.write(sdp);\n};\n\n/**\n * Returns map of MediaChannel mapped per channel idx.\n */\nSDP.prototype.getMediaSsrcMap = function() {\n const mediaSSRCs = {};\n\n for (let mediaindex = 0; mediaindex < this.media.length; mediaindex++) {\n const mid\n = SDPUtil.parseMID(\n SDPUtil.findLine(this.media[mediaindex], 'a=mid:'));\n const media = {\n mediaindex,\n mid,\n ssrcs: {},\n ssrcGroups: []\n };\n\n mediaSSRCs[mediaindex] = media;\n\n SDPUtil.findLines(this.media[mediaindex], 'a=ssrc:').forEach(line => {\n const linessrc = line.substring(7).split(' ')[0];\n\n // allocate new ChannelSsrc\n\n if (!media.ssrcs[linessrc]) {\n media.ssrcs[linessrc] = {\n ssrc: linessrc,\n lines: []\n };\n }\n media.ssrcs[linessrc].lines.push(line);\n });\n SDPUtil.findLines(this.media[mediaindex], 'a=ssrc-group:').forEach(line => {\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\n return mediaSSRCs;\n};\n\n/**\n * Returns true if this SDP contains given SSRC.\n * @param ssrc the ssrc to check.\n * @returns {boolean} true if this SDP contains given SSRC.\n */\nSDP.prototype.containsSSRC = function(ssrc) {\n // FIXME this code is really strange - improve it if you can\n const medias = this.getMediaSsrcMap();\n let result = false;\n\n Object.keys(medias).forEach(mediaindex => {\n if (result) {\n return;\n }\n if (medias[mediaindex].ssrcs[ssrc]) {\n result = true;\n }\n });\n\n return result;\n};\n\n// add content's to a jingle element\nSDP.prototype.toJingle = function(elem, thecreator) {\n // https://xmpp.org/extensions/xep-0338.html\n SDPUtil.findLines(this.session, 'a=group:').forEach(line => {\n const parts = line.split(' ');\n const semantics = parts.shift().substr(8);\n\n elem.c('group', { xmlns: 'urn:xmpp:jingle:apps:grouping:0',\n semantics });\n for (let j = 0; j < parts.length; j++) {\n elem.c('content', { name: parts[j] }).up();\n }\n elem.up();\n });\n\n for (let i = 0; i < this.media.length; i++) {\n const mline = SDPUtil.parseMLine(this.media[i].split('\\r\\n')[0]);\n\n if (!(mline.media === 'audio'\n || mline.media === 'video'\n || mline.media === 'application')) {\n continue; // eslint-disable-line no-continue\n }\n\n let ssrc;\n const assrcline = SDPUtil.findLine(this.media[i], 'a=ssrc:');\n\n if (assrcline) {\n ssrc = assrcline.substring(7).split(' ')[0]; // take the first\n } else {\n ssrc = false;\n }\n\n elem.c('content', { creator: thecreator,\n name: mline.media });\n const amidline = SDPUtil.findLine(this.media[i], 'a=mid:');\n\n if (amidline) {\n // prefer identifier from a=mid if present\n const mid = SDPUtil.parseMID(amidline);\n\n elem.attrs({ name: mid });\n }\n\n if (mline.media === 'video' && typeof this.initialLastN === 'number') {\n elem.c('initial-last-n',\n { xmlns: 'jitsi:colibri2',\n value: this.initialLastN }).up();\n }\n\n if (mline.media === 'audio' || mline.media === 'video') {\n elem.c('description',\n { xmlns: 'urn:xmpp:jingle:apps:rtp:1',\n media: mline.media });\n if (ssrc) {\n elem.attrs({ ssrc });\n }\n for (let j = 0; j < mline.fmt.length; j++) {\n const rtpmap\n = SDPUtil.findLine(\n this.media[i],\n `a=rtpmap:${mline.fmt[j]}`);\n\n elem.c('payload-type', SDPUtil.parseRTPMap(rtpmap));\n\n // put any 'a=fmtp:' + mline.fmt[j] lines into \n const afmtpline\n = SDPUtil.findLine(\n this.media[i],\n `a=fmtp:${mline.fmt[j]}`);\n\n if (afmtpline) {\n const fmtpParameters = SDPUtil.parseFmtp(afmtpline);\n\n // eslint-disable-next-line max-depth\n for (let k = 0; k < fmtpParameters.length; k++) {\n elem.c('parameter', fmtpParameters[k]).up();\n }\n }\n\n // XEP-0293 -- map a=rtcp-fb\n this.rtcpFbToJingle(i, elem, mline.fmt[j]);\n\n elem.up();\n }\n\n if (ssrc) {\n const ssrcMap = SDPUtil.parseSSRC(this.media[i]);\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 ssrc: availableSsrc,\n name: sourceName,\n videoType,\n xmlns: 'urn:xmpp:jingle:apps:rtp:ssma:0'\n });\n\n const msid = SDPUtil.parseMSIDAttribute(ssrcParameters);\n\n // eslint-disable-next-line max-depth\n if (msid) {\n elem.c('parameter');\n elem.attrs({ name: 'msid' });\n elem.attrs({ value: msid });\n elem.up();\n }\n\n elem.up();\n }\n\n // XEP-0339 handle ssrc-group attributes\n const ssrcGroupLines\n = SDPUtil.findLines(this.media[i], 'a=ssrc-group:');\n\n ssrcGroupLines.forEach(line => {\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 elem.c('ssrc-group', { semantics,\n xmlns: 'urn:xmpp:jingle:apps:rtp:ssma:0' });\n ssrcs.forEach(s => elem.c('source', { ssrc: s }).up());\n elem.up();\n }\n });\n }\n\n const ridLines = SDPUtil.findLines(this.media[i], 'a=rid:');\n\n if (ridLines.length && browser.usesRidsForSimulcast()) {\n // Map a line which looks like \"a=rid:2 send\" to just\n // the rid (\"2\")\n const rids = ridLines\n .map(ridLine => ridLine.split(':')[1])\n .map(ridInfo => ridInfo.split(' ')[0]);\n\n rids.forEach(rid => {\n elem.c('source', {\n rid,\n xmlns: 'urn:xmpp:jingle:apps:rtp:ssma:0'\n });\n elem.up();\n });\n const unifiedSimulcast\n = SDPUtil.findLine(this.media[i], 'a=simulcast:');\n\n if (unifiedSimulcast) {\n elem.c('rid-group', {\n semantics: 'SIM',\n xmlns: 'urn:xmpp:jingle:apps:rtp:ssma:0'\n });\n rids.forEach(rid => {\n elem.c('source', { rid }).up();\n });\n elem.up();\n }\n }\n\n if (SDPUtil.findLine(this.media[i], 'a=rtcp-mux')) {\n elem.c('rtcp-mux').up();\n }\n\n // XEP-0293 -- map a=rtcp-fb:*\n this.rtcpFbToJingle(i, elem, '*');\n\n // XEP-0294\n const extmapLines = SDPUtil.findLines(this.media[i], 'a=extmap:', this.session);\n\n for (let j = 0; j < extmapLines.length; j++) {\n const extmap = SDPUtil.parseExtmap(extmapLines[j]);\n\n elem.c('rtp-hdrext', {\n xmlns: 'urn:xmpp:jingle:apps:rtp:rtp-hdrext:0',\n uri: extmap.uri,\n id: extmap.value\n });\n\n // eslint-disable-next-line max-depth\n if (extmap.hasOwnProperty('direction')) {\n\n // eslint-disable-next-line max-depth\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 // TODO: handle params\n elem.up();\n }\n\n if (SDPUtil.findLine(this.media[i], 'a=extmap-allow-mixed', this.session)) {\n elem.c('extmap-allow-mixed', {\n xmlns: 'urn:xmpp:jingle:apps:rtp:rtp-hdrext:0'\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 const m = this.media[i];\n\n if (SDPUtil.findLine(m, `a=${MediaDirection.SENDRECV}`)) {\n elem.attrs({ senders: 'both' });\n } else if (SDPUtil.findLine(m, `a=${MediaDirection.SENDONLY}`)) {\n elem.attrs({ senders: 'initiator' });\n } else if (SDPUtil.findLine(m, `a=${MediaDirection.RECVONLY}`)) {\n elem.attrs({ senders: 'responder' });\n } else if (SDPUtil.findLine(m, `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(m, 'a=bundle-only', this.session)) {\n // estos hack to reject an m-line\n elem.attrs({ senders: 'rejected' });\n }\n elem.up(); // end of content\n }\n elem.up();\n\n return elem;\n};\n\nSDP.prototype.transportToJingle = function(mediaindex, elem) {\n elem.c('transport');\n\n // XEP-0343 DTLS/SCTP\n const sctpport\n = SDPUtil.findLine(this.media[mediaindex], 'a=sctp-port:', this.session);\n const sctpmap\n = SDPUtil.findLine(this.media[mediaindex], 'a=sctpmap:', this.session);\n\n if (sctpport) {\n const sctpAttrs = SDPUtil.parseSCTPPort(sctpport);\n\n elem.c('sctpmap', {\n xmlns: 'urn:xmpp:jingle:transports:dtls-sctp:1',\n number: sctpAttrs, /* SCTP port */\n protocol: 'webrtc-datachannel' /* protocol */\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 xmlns: 'urn:xmpp:jingle:transports:dtls-sctp:1',\n number: sctpAttrs[0], /* SCTP port */\n protocol: sctpAttrs[1] /* protocol */\n });\n\n // Optional stream count attribute\n if (sctpAttrs.length > 2) {\n elem.attrs({ streams: sctpAttrs[2] });\n } else {\n elem.attrs({ streams: 0 });\n }\n elem.up();\n }\n\n // XEP-0320\n const fingerprints\n = SDPUtil.findLines(\n this.media[mediaindex],\n 'a=fingerprint:',\n this.session);\n\n fingerprints.forEach(line => {\n const fingerprint = SDPUtil.parseFingerprint(line);\n\n fingerprint.xmlns = 'urn:xmpp:jingle:apps:dtls:0';\n elem.c('fingerprint').t(fingerprint.fingerprint);\n delete fingerprint.fingerprint;\n\n const setupLine\n = SDPUtil.findLine(\n this.media[mediaindex],\n 'a=setup:',\n this.session);\n\n if (setupLine) {\n fingerprint.setup = setupLine.substr(8);\n }\n elem.attrs(fingerprint);\n elem.up(); // end of fingerprint\n });\n const iceParameters = SDPUtil.iceparams(this.media[mediaindex], this.session);\n\n if (iceParameters) {\n iceParameters.xmlns = 'urn:xmpp:jingle:transports:ice-udp:1';\n elem.attrs(iceParameters);\n\n // XEP-0176\n const candidateLines\n = SDPUtil.findLines(\n this.media[mediaindex],\n 'a=candidate:',\n 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 const protocol\n = candidate && typeof candidate.protocol === 'string'\n ? candidate.protocol.toLowerCase()\n : '';\n\n if ((this.removeTcpCandidates\n && (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// XEP-0293\nSDP.prototype.rtcpFbToJingle = function(mediaindex, elem, payloadtype) {\n const lines\n = SDPUtil.findLines(\n this.media[mediaindex],\n `a=rtcp-fb:${payloadtype}`);\n\n lines.forEach(line => {\n const feedback = SDPUtil.parseRTCPFB(line);\n\n if (feedback.type === 'trr-int') {\n elem.c('rtcp-fb-trr-int', {\n xmlns: 'urn:xmpp:jingle:apps:rtp:rtcp-fb:0',\n value: feedback.params[0]\n });\n elem.up();\n } else {\n elem.c('rtcp-fb', {\n xmlns: 'urn:xmpp:jingle:apps:rtp:rtcp-fb:0',\n type: feedback.type\n });\n if (feedback.params.length > 0) {\n elem.attrs({ 'subtype': feedback.params[0] });\n }\n elem.up();\n }\n });\n};\n\nSDP.prototype.rtcpFbFromJingle = function(elem, payloadtype) { // XEP-0293\n let sdp = '';\n const feedbackElementTrrInt\n = elem.find(\n '>rtcp-fb-trr-int[xmlns=\"urn:xmpp:jingle:apps:rtp:rtcp-fb:0\"]');\n\n if (feedbackElementTrrInt.length) {\n sdp += 'a=rtcp-fb:* trr-int ';\n if (feedbackElementTrrInt.attr('value')) {\n sdp += feedbackElementTrrInt.attr('value');\n } else {\n sdp += '0';\n }\n sdp += '\\r\\n';\n }\n\n const feedbackElements = elem.find('>rtcp-fb[xmlns=\"urn:xmpp:jingle:apps:rtp:rtcp-fb:0\"]');\n\n feedbackElements.each((_, 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// construct an SDP from a jingle stanza\nSDP.prototype.fromJingle = function(jingle) {\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 // http://tools.ietf.org/html/draft-ietf-mmusic-sdp-bundle-negotiation-04\n // #section-8\n const groups\n = $(jingle).find('>group[xmlns=\"urn:xmpp:jingle:apps:grouping:0\"]');\n\n if (groups.length) {\n groups.each((idx, group) => {\n const contents\n = $(group)\n .find('>content')\n .map((_, content) => content.getAttribute('name'))\n .get();\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 this.session = this.raw;\n jingle.find('>content').each((_, content) => {\n const m = this.jingle2media($(content));\n\n this.media.push(m);\n });\n\n // reconstruct msid-semantic -- apparently not necessary\n /*\n var msid = SDPUtil.parseSSRC(this.raw);\n if (msid.hasOwnProperty('mslabel')) {\n this.session += \"a=msid-semantic: WMS \" + msid.mslabel + \"\\r\\n\";\n }\n */\n\n this.raw = this.session + this.media.join('');\n};\n\n// translate a jingle content element into an an SDP media part\nSDP.prototype.jingle2media = function(content) {\n const desc = content.find('>description');\n const transport = content.find('>transport[xmlns=\"urn:xmpp:jingle:transports:ice-udp:1\"]');\n let sdp = '';\n const sctp = transport.find(\n '>sctpmap[xmlns=\"urn:xmpp:jingle:transports:dtls-sctp:1\"]');\n\n const media = { media: desc.attr('media') };\n\n media.port = '9';\n if (content.attr('senders') === 'rejected') {\n // estos hack to reject an m-line.\n media.port = '0';\n }\n if (transport.find('>fingerprint[xmlns=\"urn:xmpp:jingle:apps:dtls:0\"]').length) {\n media.proto = sctp.length ? 'UDP/DTLS/SCTP' : 'UDP/TLS/RTP/SAVPF';\n } else {\n media.proto = 'UDP/TLS/RTP/SAVPF';\n }\n if (sctp.length) {\n sdp += `m=application ${media.port} UDP/DTLS/SCTP webrtc-datachannel\\r\\n`;\n sdp += `a=sctp-port:${sctp.attr('number')}\\r\\n`;\n sdp += 'a=max-message-size:262144\\r\\n';\n } else {\n media.fmt\n = desc\n .find('>payload-type')\n .map((_, payloadType) => payloadType.getAttribute('id'))\n .get();\n sdp += `${SDPUtil.buildMLine(media)}\\r\\n`;\n }\n\n sdp += 'c=IN IP4 0.0.0.0\\r\\n';\n if (!sctp.length) {\n sdp += 'a=rtcp:1 IN IP4 0.0.0.0\\r\\n';\n }\n\n // XEP-0176 ICE parameters\n if (transport.length) {\n if (transport.attr('ufrag')) {\n sdp += `${SDPUtil.buildICEUfrag(transport.attr('ufrag'))}\\r\\n`;\n }\n if (transport.attr('pwd')) {\n sdp += `${SDPUtil.buildICEPwd(transport.attr('pwd'))}\\r\\n`;\n }\n transport.find('>fingerprint[xmlns=\"urn:xmpp:jingle:apps:dtls:0\"]').each((_, fingerprint) => {\n sdp += `a=fingerprint:${fingerprint.getAttribute('hash')}`;\n sdp += ` ${$(fingerprint).text()}`;\n sdp += '\\r\\n';\n if (fingerprint.hasAttribute('setup')) {\n sdp += `a=setup:${fingerprint.getAttribute('setup')}\\r\\n`;\n }\n });\n }\n\n // XEP-0176 ICE candidates\n transport.find('>candidate')\n .each((_, candidate) => {\n let protocol = candidate.getAttribute('protocol');\n\n protocol\n = typeof protocol === 'string' ? protocol.toLowerCase() : '';\n\n if ((this.removeTcpCandidates\n && (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 switch (content.attr('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:${content.attr('name')}\\r\\n`;\n\n // \n // see http://code.google.com/p/libjingle/issues/detail?id=309 -- no spec\n // though\n // and http://mail.jabber.org/pipermail/jingle/2011-December/001761.html\n if (desc.find('>rtcp-mux').length) {\n sdp += 'a=rtcp-mux\\r\\n';\n }\n\n desc.find('>payload-type').each((_, payloadType) => {\n sdp += `${SDPUtil.buildRTPMap(payloadType)}\\r\\n`;\n if ($(payloadType).find('>parameter').length) {\n sdp += `a=fmtp:${payloadType.getAttribute('id')} `;\n sdp\n += $(payloadType)\n .find('>parameter')\n .map((__, parameter) => {\n const name = parameter.getAttribute('name');\n\n return (\n (name ? `${name}=` : '')\n + parameter.getAttribute('value'));\n })\n .get()\n .join(';');\n sdp += '\\r\\n';\n }\n\n // xep-0293\n sdp += this.rtcpFbFromJingle($(payloadType), payloadType.getAttribute('id'));\n });\n\n // xep-0293\n sdp += this.rtcpFbFromJingle(desc, '*');\n\n // xep-0294\n desc\n .find('>rtp-hdrext[xmlns=\"urn:xmpp:jingle:apps:rtp:rtp-hdrext:0\"]')\n .each((_, hdrExt) => {\n sdp\n += `a=extmap:${hdrExt.getAttribute('id')} ${\n hdrExt.getAttribute('uri')}\\r\\n`;\n });\n if (desc.find('>extmap-allow-mixed[xmlns=\"urn:xmpp:jingle:apps:rtp:rtp-hdrext:0\"]').length > 0) {\n sdp += 'a=extmap-allow-mixed\\r\\n';\n }\n\n // XEP-0339 handle ssrc-group attributes\n desc\n .find('>ssrc-group[xmlns=\"urn:xmpp:jingle:apps:rtp:ssma:0\"]')\n .each((_, ssrcGroup) => {\n const semantics = ssrcGroup.getAttribute('semantics');\n const ssrcs\n = $(ssrcGroup)\n .find('>source')\n .map((__, source) => source.getAttribute('ssrc'))\n .get();\n\n if (ssrcs.length) {\n sdp += `a=ssrc-group:${semantics} ${ssrcs.join(' ')}\\r\\n`;\n }\n });\n\n // XEP-0339 handle source attributes\n let userSources = '';\n let nonUserSources = '';\n\n desc\n .find('>source[xmlns=\"urn:xmpp:jingle:apps:rtp:ssma:0\"]')\n .each((_, source) => {\n const ssrc = source.getAttribute('ssrc');\n let isUserSource = true;\n let sourceStr = '';\n\n $(source)\n .find('>parameter')\n .each((__, parameter) => {\n const name = parameter.getAttribute('name');\n let value = parameter.getAttribute('value');\n\n value = SDPUtil.filterSpecialChars(value);\n sourceStr += `a=ssrc:${ssrc} ${name}`;\n\n if (value && 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 // The sdp-interop package is relying the mixedmslabel m line to be the first one in order to set the direction\n // to sendrecv.\n sdp += nonUserSources + userSources;\n\n return sdp;\n};\n","\nimport SDPUtil from './SDPUtil';\n\n// this could be useful in Array.prototype.\n/**\n *\n * @param array1\n * @param array2\n */\nfunction arrayEquals(array1, array2) {\n // if the other array is a falsy value, return\n if (!array2) {\n return false;\n }\n\n // compare lengths - can save a lot of time\n if (array1.length !== array2.length) {\n return false;\n }\n\n for (let i = 0, l = array1.length; i < l; i++) {\n // Check if we have nested arrays\n if (array1[i] instanceof Array && array2[i] instanceof Array) {\n // recurse into the nested arrays\n if (!array1[i].equals(array2[i])) {\n return false;\n }\n } else if (array1[i] !== array2[i]) {\n // Warning - two different object instances will never be\n // equal: {x:20} != {x:20}\n return false;\n }\n }\n\n return true;\n}\n\n/**\n *\n * @param mySDP\n * @param otherSDP\n */\nexport default function SDPDiffer(mySDP, otherSDP) {\n this.mySDP = mySDP;\n this.otherSDP = otherSDP;\n if (!mySDP) {\n throw new Error('\"mySDP\" is undefined!');\n } else if (!otherSDP) {\n throw new Error('\"otherSDP\" is undefined!');\n }\n}\n\n/**\n * Returns map of MediaChannel that contains media contained in\n * 'mySDP', but not contained in 'otherSdp'. Mapped by channel idx.\n */\nSDPDiffer.prototype.getNewMedia = function() {\n\n const myMedias = this.mySDP.getMediaSsrcMap();\n const othersMedias = this.otherSDP.getMediaSsrcMap();\n const newMedia = {};\n\n Object.keys(othersMedias).forEach(othersMediaIdx => {\n const myMedia = myMedias[othersMediaIdx];\n const othersMedia = othersMedias[othersMediaIdx];\n\n if (!myMedia && othersMedia) {\n // Add whole channel\n newMedia[othersMediaIdx] = othersMedia;\n\n return;\n }\n\n // Look for new ssrcs across the channel\n Object.keys(othersMedia.ssrcs).forEach(ssrc => {\n if (Object.keys(myMedia.ssrcs).indexOf(ssrc) === -1) {\n // Allocate channel if we've found ssrc that doesn't exist in\n // our channel\n if (!newMedia[othersMediaIdx]) {\n newMedia[othersMediaIdx] = {\n mediaindex: othersMedia.mediaindex,\n mid: othersMedia.mid,\n ssrcs: {},\n ssrcGroups: []\n };\n }\n newMedia[othersMediaIdx].ssrcs[ssrc] = othersMedia.ssrcs[ssrc];\n } else if (othersMedia.ssrcs[ssrc].lines\n && myMedia.ssrcs[ssrc].lines) {\n // we want to detect just changes in adding/removing msid\n const myContainMsid = myMedia.ssrcs[ssrc].lines.find(\n line => line.indexOf('msid') !== -1) !== undefined;\n const newContainMsid = othersMedia.ssrcs[ssrc].lines.find(\n line => line.indexOf('msid') !== -1) !== undefined;\n\n if (myContainMsid !== newContainMsid) {\n if (!newMedia[othersMediaIdx]) {\n newMedia[othersMediaIdx] = {\n mediaindex: othersMedia.mediaindex,\n mid: othersMedia.mid,\n ssrcs: {},\n ssrcGroups: []\n };\n }\n newMedia[othersMediaIdx].ssrcs[ssrc]\n = othersMedia.ssrcs[ssrc];\n }\n }\n });\n\n // Look for new ssrc groups across the channels\n othersMedia.ssrcGroups.forEach(otherSsrcGroup => {\n\n // try to match the other ssrc-group with an ssrc-group of ours\n let matched = false;\n\n for (let i = 0; i < myMedia.ssrcGroups.length; i++) {\n const mySsrcGroup = myMedia.ssrcGroups[i];\n\n if (otherSsrcGroup.semantics === mySsrcGroup.semantics\n && arrayEquals(otherSsrcGroup.ssrcs, mySsrcGroup.ssrcs)) {\n\n matched = true;\n break;\n }\n }\n\n if (!matched) {\n // Allocate channel if we've found an ssrc-group that doesn't\n // exist in our channel\n\n if (!newMedia[othersMediaIdx]) {\n newMedia[othersMediaIdx] = {\n mediaindex: othersMedia.mediaindex,\n mid: othersMedia.mid,\n ssrcs: {},\n ssrcGroups: []\n };\n }\n newMedia[othersMediaIdx].ssrcGroups.push(otherSsrcGroup);\n }\n });\n });\n\n return newMedia;\n};\n\n/**\n * TODO: document!\n */\nSDPDiffer.prototype.toJingle = function(modify) {\n const sdpMediaSsrcs = this.getNewMedia();\n\n let modified = false;\n\n Object.keys(sdpMediaSsrcs).forEach(mediaindex => {\n modified = true;\n const media = sdpMediaSsrcs[mediaindex];\n\n modify.c('content', { name: media.mid });\n\n modify.c('description',\n { xmlns: 'urn:xmpp:jingle:apps:rtp:1',\n media: media.mid });\n\n // FIXME: not completely sure this operates on blocks and / or handles\n // different ssrcs correctly\n // generate sources from lines\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: 'urn:xmpp:jingle:apps:rtp:ssma:0' });\n modify.attrs({\n name: sourceName,\n videoType,\n ssrc: mediaSsrc.ssrc\n });\n\n // Only MSID attribute is sent\n const msid = SDPUtil.parseMSIDAttribute(ssrcLines);\n\n if (msid) {\n modify.c('parameter');\n modify.attrs({ name: 'msid' });\n modify.attrs({ value: msid });\n modify.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: 'urn:xmpp:jingle:apps:rtp:ssma:0'\n });\n\n ssrcGroup.ssrcs.forEach(ssrc => {\n modify.c('source', { ssrc })\n .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","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 { queue } from 'async-es';\n\nconst logger = getLogger(__filename);\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) {\n super(message);\n this.name = 'ClearedQueueError';\n }\n}\n\n/**\n * A queue for async task execution.\n */\nexport default class AsyncQueue {\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 * Removes any pending tasks from the queue.\n */\n clear() {\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 * Internal task processing implementation which makes things work.\n */\n _processQueueTasks(task, finishedCallback) {\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 * Pauses the execution of the tasks on the queue.\n */\n pause() {\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 {function} task - The task to be executed. See the description above.\n * @param {function} [callback] - Optional callback to be called after the task has been executed.\n */\n push(task, callback) {\n if (this._stopped) {\n callback && 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() {\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() {\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","export enum JingleSessionState {\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 * 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// exported for backward compatibility\nexport const PENDING = JingleSessionState.PENDING;\nexport const ACTIVE = JingleSessionState.ACTIVE;\nexport const ENDED = JingleSessionState.ENDED;\n","import { getLogger } from '@jitsi/logger';\n\nimport Listenable from '../util/Listenable';\n\nimport * as JingleSessionState from './JingleSessionState';\n\nconst logger = getLogger(__filename);\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 /* eslint-disable max-params */\n\n /**\n * Creates new JingleSession.\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,\n localJid,\n remoteJid,\n connection,\n mediaConstraints,\n pcConfig,\n isInitiator) {\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 {SignalingLayerImpl | null}\n * @private\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() {\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() {\n return this.isInitiator ? this.remoteJid : this.localJid;\n }\n\n /* eslint-enable max-params */\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 initialize(room, rtc, signalingLayer, options) {\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 * 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 doInitialize(options) { } // eslint-disable-line no-unused-vars, no-empty-function, max-len\n\n /* eslint-disable no-unused-vars, no-empty-function */\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 addIceCandidates(contents) {}\n\n /* eslint-enable no-unused-vars, no-empty-function */\n\n /**\n * Returns current state of this JingleSession instance.\n * @returns {JingleSessionState} the current state of this session instance.\n */\n getState() {\n return this.state;\n }\n\n /* eslint-disable no-unused-vars, no-empty-function */\n\n /**\n * Handles an 'add-source' event.\n *\n * @param contents an array of Jingle 'content' elements.\n */\n addSources(contents) {}\n\n /**\n * Handles a 'remove-source' event.\n *\n * @param contents an array of Jingle 'content' elements.\n */\n removeSources(contents) {}\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 terminate(success, failure, options) {}\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 acceptOffer(jingle, success, failure) {}\n\n /* eslint-enable no-unused-vars, no-empty-function */\n}\n","enum MediaSessionEvents {\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\nexport default MediaSessionEvents;","import { getLogger } from '@jitsi/logger';\nimport $ from 'jquery';\nimport { $build, $iq, Strophe } from 'strophe.js';\n\nimport { JitsiTrackEvents } from '../../JitsiTrackEvents';\nimport { CodecMimeType } from '../../service/RTC/CodecMimeType';\nimport { MediaDirection } from '../../service/RTC/MediaDirection';\nimport { MediaType } from '../../service/RTC/MediaType';\nimport {\n ICE_DURATION,\n ICE_STATE_CHANGED\n} from '../../service/statistics/AnalyticsEvents';\nimport { XMPPEvents } from '../../service/xmpp/XMPPEvents';\nimport { SS_DEFAULT_FRAME_RATE } from '../RTC/ScreenObtainer';\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';\n\nimport browser from './../browser';\nimport JingleSession from './JingleSession';\nimport * as JingleSessionState from './JingleSessionState';\nimport MediaSessionEvents from './MediaSessionEvents';\nimport XmppConnection from './XmppConnection';\n\nconst logger = getLogger(__filename);\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 = 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 = 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 = 150;\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) {\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, s, ssrc_, msid) {\n\n description.c('source', {\n xmlns: 'urn:xmpp:jingle:apps:rtp:ssma:0',\n ssrc: ssrc_,\n name: s.source\n })\n .c('parameter', {\n name: 'msid',\n value: msid\n })\n .up()\n .c('ssrc-info', {\n xmlns: 'http://jitsi.org/jitmeet',\n owner: s.owner\n })\n .up()\n .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 * true 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 */\n/**\n *\n */\nexport default class JingleSessionPC extends JingleSession {\n /**\n * Parses 'senders' attribute of the video content.\n * @param {jQuery} jingleContents\n * @return {string|null} 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 null will be returned.\n * @private\n */\n static parseVideoSenders(jingleContents) {\n const videoContents = jingleContents.find('>content[name=\"video\"]');\n\n if (videoContents.length) {\n const senders = videoContents[0].getAttribute('senders');\n\n if (senders === 'both'\n || senders === 'initiator'\n || senders === 'responder'\n || senders === 'none') {\n return senders;\n }\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 {jQuery} jingleContents - A jQuery selector pointing to the '>jingle' element.\n * @returns {Object|null}\n */\n static parseSourceMaxFrameHeight(jingleContents) {\n const receiverConstraints = [];\n const sourceFrameHeightSel = jingleContents.find('>content[name=\"video\"]>source-frame-height');\n let maxHeight, sourceName;\n\n if (sourceFrameHeightSel.length) {\n sourceFrameHeightSel.each((_, 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 JingleSessionPC\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 false 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,\n localJid,\n remoteJid,\n connection,\n mediaConstraints,\n pcConfig,\n isP2P,\n isInitiator) {\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' or 'transport-replace'.\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 {SDP|undefined}\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 {SDP|undefined}\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 {number|null} null if no value has been stored yet\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 {number|null} null if no value has been stored yet\n * @private\n */\n this._gatheringStartedTimestamp = null;\n\n /**\n * Receiver constraints (max height) set by the application per remote source. Will be used for p2p connection.\n *\n * @type {Map}\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 false 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 false to true 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 true 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 * false.\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, after eventual 'transport-replace' (JVB\n * conference migration/ICE restart).\n * @type {boolean}\n * @private\n */\n this._gatheringReported = false;\n\n this.lasticecandidate = false;\n this.closed = false;\n\n /**\n * Indicates whether or not this JingleSessionPC is used in\n * a peer to peer type of session.\n * @type {boolean} true if it's a peer to peer\n * session or false if it's a JVB session\n */\n this.isP2P = isP2P;\n\n /**\n * Remote preference for the receive video max frame height.\n *\n * @type {Number|undefined}\n */\n this.remoteRecvMaxFrameHeight = undefined;\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 {Map|undefined}\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._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 /* eslint-enable max-params */\n\n /**\n * Checks whether or not this session instance is still operational.\n * @private\n * @returns {boolean} {@code true} if operation or {@code false} otherwise.\n */\n _assertNotEnded() {\n return this.state !== JingleSessionState.ENDED;\n }\n\n /**\n * @inheritDoc\n * @param {JingleSessionPCOptions} options - a set of config options.\n */\n doInitialize(options) {\n this.failICE = Boolean(options.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 = { disableRtx: options.disableRtx };\n\n if (options.gatherStats) {\n pcOptions.maxstats = DEFAULT_MAX_STATS;\n }\n pcOptions.capScreenshareBitrate = false;\n pcOptions.codecSettings = options.codecSettings;\n pcOptions.enableInsertableStreams = options.enableInsertableStreams;\n pcOptions.usesCodecSelectionAPI = this.usesCodecSelectionAPI\n = browser.supportsCodecSelectionAPI() && options.testing?.enableCodecSelectionAPI && !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 pcOptions.forceTurnRelay = options.forceTurnRelay;\n pcOptions.audioQuality = options.audioQuality;\n pcOptions.disableSimulcast = this.isP2P ? true : options.disableSimulcast;\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 (candidate) {\n if (this._gatheringStartedTimestamp === null) {\n this._gatheringStartedTimestamp = now;\n }\n\n // Discard candidates of disabled protocols.\n let protocol = candidate.protocol;\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 ICE_DURATION,\n {\n phase: 'gathering',\n value: now - this._gatheringStartedTimestamp,\n p2p: this.isP2P,\n initiator: this.isInitiator\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.log(`(TIME) ICE ${this.peerconnection.iceConnectionState} ${this.isP2P ? 'P2P' : 'JVB'}:\\t`, now);\n\n Statistics.sendAnalytics(\n ICE_STATE_CHANGED,\n {\n p2p: this.isP2P,\n state: this.peerconnection.iceConnectionState,\n 'signaling_state': this.peerconnection.signalingState,\n reconnect: this.isReconnect,\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 const usesTerminateForRestart = !this.options.enableIceRestart\n && this.room.supportsRestartByTerminate();\n\n if (this.isReconnect || usesTerminateForRestart) {\n this.room.eventEmitter.emit(\n XMPPEvents.CONNECTION_RESTORED, this);\n }\n }\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 ICE_DURATION,\n {\n phase: 'checking',\n value: now - this._iceCheckingStartedTimestamp,\n p2p: this.isP2P,\n initiator: this.isInitiator\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 ICE_DURATION,\n {\n phase: 'establishment',\n value: this.establishmentDuration,\n p2p: this.isP2P,\n initiator: this.isInitiator\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 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 = finishedCallback => {\n this._renegotiate()\n .then(() => this.peerconnection.configureAudioSenderEncodings())\n .then(() => finishedCallback(), error => finishedCallback(error));\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 * Remote preference for receive video max frame height.\n *\n * @returns {Number|undefined}\n */\n getRemoteRecvMaxFrameHeight() {\n if (this.isP2P) {\n return this.remoteRecvMaxFrameHeight;\n }\n\n return undefined;\n }\n\n /**\n * Remote preference for receive video max frame heights when source-name signaling is enabled.\n *\n * @returns {Map|undefined}\n */\n getRemoteSourcesRecvMaxFrameHeight() {\n if (this.isP2P) {\n return this.remoteSourceMaxFrameHeights;\n }\n\n return undefined;\n }\n\n /**\n * Sends given candidate in Jingle 'transport-info' message.\n * @param {RTCIceCandidate} candidate the WebRTC ICE candidate instance\n * @private\n */\n sendIceCandidate(candidate) {\n const localSDP = new SDP(this.peerconnection.localDescription.sdp);\n\n if (candidate && 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 = 'urn:xmpp:jingle:transports:ice-udp:1';\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.log(`${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 * @param {Array} candidates an array of the WebRTC ICE\n * candidate instances\n * @private\n */\n sendIceCandidates(candidates) {\n if (!this._assertNotEnded('sendIceCandidates')) {\n\n return;\n }\n\n logger.log(`${this} sendIceCandidates ${JSON.stringify(candidates)}`);\n const cand = $iq({ to: this.remoteJid,\n type: 'set' })\n .c('jingle', { xmlns: 'urn:xmpp:jingle:1',\n action: 'transport-info',\n initiator: this.initiatorJid,\n sid: this.sid });\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 = 'urn:xmpp:jingle:transports:ice-udp:1';\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.log('was this the last candidate', this.lasticecandidate);\n this.connection.sendIQ(\n cand, null, this.newJingleErrorHandler(cand), IQ_TIMEOUT);\n }\n\n /**\n * Sends Jingle 'session-info' message which includes custom Jitsi Meet\n * 'ice-state' element with the text value 'failed' to let Jicofo know\n * that the ICE connection has entered the failed state. It can then\n * choose to re-create JVB channels and send 'transport-replace' to\n * retry the connection.\n */\n sendIceFailedNotification() {\n const sessionInfo\n = $iq({\n to: this.remoteJid,\n type: 'set' })\n .c('jingle', { xmlns: 'urn:xmpp:jingle:1',\n action: 'session-info',\n initiator: this.initiatorJid,\n sid: this.sid })\n .c('ice-state', { xmlns: 'http://jitsi.org/protocol/focus' })\n .t('failed')\n .up();\n\n this._bridgeSessionId\n && sessionInfo.c(\n 'bridge-session', {\n xmlns: 'http://jitsi.org/protocol/focus',\n id: this._bridgeSessionId\n });\n\n this.connection.sendIQ2(\n sessionInfo, {\n /*\n * This message will be often sent when there are connectivity\n * issues, so make it slightly longer than Prosody's default BOSH\n * inactivity timeout of 60 seconds.\n */\n timeout: 65\n })\n .catch(this.newJingleErrorHandler(sessionInfo));\n }\n\n /**\n * {@inheritDoc}\n */\n addIceCandidates(elem) {\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 = [];\n\n elem.find('>content>transport>candidate')\n .each((idx, 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 const rtcCandidate = new RTCIceCandidate({\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 candidate: line\n });\n\n iceCandidates.push(rtcCandidate);\n });\n\n if (!iceCandidates.length) {\n logger.error(`${this} No ICE candidates to add ?`, elem[0] && 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 for (const iceCandidate of iceCandidates) {\n this.peerconnection.addIceCandidate(iceCandidate)\n .then(\n () => logger.debug(`${this} addIceCandidate ok!`),\n err => logger.error(`${this} addIceCandidate failed!`, err));\n }\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 *\n * @param contents\n */\n readSsrcInfo(contents) {\n const ssrcs = $(contents).find('>description>source[xmlns=\"urn:xmpp:jingle:apps:rtp:ssma:0\"]');\n\n ssrcs.each((i, ssrcElement) => {\n const ssrc = Number(ssrcElement.getAttribute('ssrc'));\n let sourceName;\n\n if (ssrcElement.hasAttribute('name')) {\n sourceName = ssrcElement.getAttribute('name');\n }\n\n if (this.isP2P) {\n // In P2P all SSRCs are owner by the remote peer\n this._signalingLayer.setSSRCOwner(ssrc, Strophe.getResourceFromJid(this.remoteJid), sourceName);\n } else {\n $(ssrcElement)\n .find('>ssrc-info[xmlns=\"http://jitsi.org/jitmeet\"]')\n .each((i3, ssrcInfoElement) => {\n const owner = ssrcInfoElement.getAttribute('owner');\n\n if (owner?.length) {\n if (isNaN(ssrc) || ssrc < 0) {\n logger.warn(`${this} Invalid SSRC ${ssrc} value received for ${owner}`);\n } else {\n this._signalingLayer.setSSRCOwner(ssrc, getEndpointId(owner), sourceName);\n }\n }\n });\n }\n });\n }\n\n /**\n * Accepts incoming Jingle 'session-initiate' and should send 'session-accept' in result.\n *\n * @param jingleOffer jQuery selector 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} [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 acceptOffer(jingleOffer, success, failure, localTracks = []) {\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 });\n },\n failure,\n localTracks);\n }\n\n /**\n * Creates an offer and sends Jingle 'session-initiate' to the remote peer.\n *\n * @param {Array} 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 */\n invite(localTracks = []) {\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 Promise.all(addTracks)\n .then(() => this.peerconnection.createOffer(this.mediaConstraints))\n .then(offerSdp => this.peerconnection.setLocalDescription(offerSdp))\n .then(() => {\n this.peerconnection.processLocalSdpForTransceiverInfo(localTracks);\n this.sendSessionInitiate(this.peerconnection.localDescription.sdp);\n })\n .then(() => {\n logger.debug(`${this} invite executed - OK`);\n })\n .catch(error => {\n logger.error(`${this} invite error`, error);\n });\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\n * used to generate an offer.\n * @private\n */\n sendSessionInitiate(offerSdp) {\n let init = $iq({\n to: this.remoteJid,\n type: 'set'\n }).c('jingle', {\n xmlns: 'urn:xmpp:jingle:1',\n action: 'session-initiate',\n initiator: this.initiatorJid,\n sid: this.sid\n });\n\n new SDP(offerSdp).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 logger.error(`${this} \"session-initiate\" error`, error);\n },\n IQ_TIMEOUT);\n }\n\n /**\n * Sets the answer received from the remote peer as the remote description.\n *\n * @param jingleAnswer\n */\n setAnswer(jingleAnswer) {\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 = new RTCSessionDescription({\n type: 'answer',\n sdp: newRemoteSdp.raw\n });\n\n this.peerconnection.setRemoteDescription(remoteDescription)\n .then(() => {\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 })\n .then(() => {\n logger.debug(`${this} setAnswer task done`);\n })\n .catch(error => {\n logger.error(`${this} setAnswer task failed: ${error}`);\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 jQuery selector 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} [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 */\n setOfferAnswerCycle(jingleOfferAnswerIq, success, failure, localTracks = []) {\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 = $(jingleOfferAnswerIq).find('>bridge-session[xmlns=\"http://jitsi.org/protocol/focus\"]');\n const bridgeSessionId = bridgeSession.attr('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 * Updates the codecs on the peerconnection and initiates a renegotiation for the\n * new codec config to take effect.\n *\n * @param {Array} codecList - Preferred codecs for video.\n * @param {CodecMimeType} screenshareCodec - The preferred screenshare codec.\n */\n setVideoCodecs(codecList, screenshareCodec) {\n if (this._assertNotEnded()) {\n logger.info(`${this} setVideoCodecs: codecList=${codecList}, screenshareCodec=${screenshareCodec}`);\n this.peerconnection.setVideoCodecs(codecList, screenshareCodec);\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 // Initiate a renegotiate for the codec setting to take effect.\n const workFunction = finishedCallback => {\n this._renegotiate()\n .then(() => this.peerconnection.configureVideoSenderEncodings())\n .then(\n () => {\n logger.debug(`${this} setVideoCodecs task is done`);\n\n return finishedCallback();\n }, 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 /* eslint-enable max-params */\n\n /**\n * Although it states \"replace transport\" it does accept full Jingle offer\n * which should contain new ICE transport details.\n * @param jingleOfferElem an element Jingle IQ that contains new offer and\n * transport info.\n * @param success callback called when we succeed to accept new offer.\n * @param failure function(error) called when we fail to accept new offer.\n */\n replaceTransport(jingleOfferElem, success, failure) {\n if (this.options.enableForcedReload) {\n const sdp = new SDP(this.peerconnection.localDescription.sdp);\n\n this.sendTransportAccept(sdp, success, failure);\n this.room.eventEmitter.emit(XMPPEvents.CONNECTION_RESTARTED, this);\n\n return;\n }\n this.room.eventEmitter.emit(XMPPEvents.ICE_RESTARTING, this);\n\n // We need to first reject the 'data' section to have the SCTP stack\n // cleaned up to signal the known data channel is now invalid. After\n // that the original offer is set to have the SCTP connection\n // established with the new bridge.\n const originalOffer = jingleOfferElem.clone();\n\n jingleOfferElem\n .find('>content[name=\\'data\\']')\n .attr('senders', 'rejected');\n\n // Remove all remote sources in order to reset the client's state\n // for the remote MediaStreams. When a conference is moved to\n // another bridge it will start streaming with a sequence number\n // that is not in sync with the most recently seen by the client.\n // The symptoms include frozen or black video and lots of \"failed to\n // unprotect SRTP packets\" in Chrome logs.\n jingleOfferElem\n .find('>content>description>source')\n .remove();\n jingleOfferElem\n .find('>content>description>ssrc-group')\n .remove();\n\n // On the JVB it's not a real ICE restart and all layers are re-initialized from scratch as Jicofo does\n // the restart by re-allocating new channels. Chrome (or WebRTC stack) needs to have the DTLS transport layer\n // reset to start a new handshake with fresh DTLS transport on the bridge. Make it think that the DTLS\n // fingerprint has changed by setting an all zeros key.\n const newFingerprint = jingleOfferElem.find('>content>transport>fingerprint');\n\n newFingerprint.attr('hash', 'sha-1');\n newFingerprint.text('00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00');\n\n const workFunction = finishedCallback => {\n // First set an offer with a rejected 'data' section\n this.setOfferAnswerCycle(\n jingleOfferElem,\n () => {\n // Now set the original offer(with the 'data' section)\n this.setOfferAnswerCycle(\n originalOffer,\n () => {\n const localSDP = new SDP(this.peerconnection.localDescription.sdp);\n\n if (typeof this.options.channelLastN === 'number' && this.options.channelLastN >= 0) {\n localSDP.initialLastN = this.options.channelLastN;\n }\n\n this.sendTransportAccept(localSDP, success, failure);\n\n this.room.eventEmitter.emit(\n XMPPEvents.ICE_RESTART_SUCCESS,\n this,\n originalOffer);\n\n finishedCallback();\n }, error => finishedCallback(error)\n );\n }, error => finishedCallback(error)\n );\n };\n\n logger.debug(`${this} Queued ICE restart task`);\n\n // Queue and execute\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} ICE restart task aborted: session terminated`);\n success();\n\n return;\n }\n logger.error(`${this} ICE restart task failed: ${error}`);\n failure(error);\n } else {\n logger.debug(`${this} ICE restart task done`);\n success();\n }\n });\n }\n\n /**\n * Sends Jingle 'session-accept' message.\n * @param {function()} success callback called when we receive 'RESULT'\n * packet for the 'session-accept'\n * @param {function(error)} failure called when we receive an error response\n * or when the request has timed out.\n * @private\n */\n sendSessionAccept(success, failure) {\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);\n const accept = $iq({ to: this.remoteJid,\n type: 'set' })\n .c('jingle', { xmlns: 'urn:xmpp:jingle:1',\n action: 'session-accept',\n initiator: this.initiatorJid,\n responder: this.responderJid,\n sid: this.sid });\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 localSDP.initialLastN = this.options.channelLastN;\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(accept, 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 * Will send 'content-modify' IQ in order to ask the remote peer to\n * either stop or resume sending video media or to adjust sender's video constraints.\n * @private\n */\n 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 xmlns: 'urn:xmpp:jingle:1',\n action: 'content-modify',\n initiator: this.initiatorJid,\n sid: this.sid\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 sourceName,\n maxHeight\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(sessionModify),\n IQ_TIMEOUT);\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} sourceReceiverConstraints - The receiver constraints per source.\n */\n setReceiverVideoConstraint(sourceReceiverConstraints) {\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 * Sends Jingle 'transport-accept' message which is a response to\n * 'transport-replace'.\n * @param localSDP the 'SDP' object with local session description\n * @param success callback called when we receive 'RESULT' packet for\n * 'transport-replace'\n * @param failure function(error) called when we receive an error response\n * or when the request has timed out.\n * @private\n */\n sendTransportAccept(localSDP, success, failure) {\n const transportAccept = $iq({ to: this.remoteJid,\n type: 'set' })\n .c('jingle', {\n xmlns: 'urn:xmpp:jingle:1',\n action: 'transport-accept',\n initiator: this.initiatorJid,\n sid: this.sid\n });\n\n localSDP.media.forEach((medialines, idx) => {\n const mline = SDPUtil.parseMLine(medialines.split('\\r\\n')[0]);\n\n transportAccept.c('content',\n {\n creator:\n this.initiatorJid === this.localJid\n ? 'initiator'\n : 'responder',\n name: mline.media\n }\n );\n localSDP.transportToJingle(idx, transportAccept);\n transportAccept.up();\n });\n\n logger.info(`${this} Sending transport-accept`);\n logger.debug(transportAccept.tree());\n\n this.connection.sendIQ(transportAccept,\n success,\n this.newJingleErrorHandler(transportAccept, failure),\n IQ_TIMEOUT);\n }\n\n /**\n * Sends Jingle 'transport-reject' message which is a response to\n * 'transport-replace'.\n * @param success callback called when we receive 'RESULT' packet for\n * 'transport-replace'\n * @param failure function(error) called when we receive an error response\n * or when the request has timed out.\n *\n * FIXME method should be marked as private, but there's some spaghetti that\n * needs to be fixed prior doing that\n */\n sendTransportReject(success, failure) {\n // Send 'transport-reject', so that the focus will\n // know that we've failed\n const transportReject = $iq({ to: this.remoteJid,\n type: 'set' })\n .c('jingle', {\n xmlns: 'urn:xmpp:jingle:1',\n action: 'transport-reject',\n initiator: this.initiatorJid,\n sid: this.sid\n });\n\n logger.info(`${this} Sending 'transport-reject'`);\n logger.debug(transportReject.tree());\n\n this.connection.sendIQ(transportReject,\n success,\n this.newJingleErrorHandler(transportReject, failure),\n IQ_TIMEOUT);\n }\n\n /**\n * Sets the resolution constraint on the local camera track.\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 setSenderVideoConstraint(maxFrameHeight, sourceName = null) {\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 * @inheritDoc\n */\n terminate(success, failure, options) {\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 xmlns: 'urn:xmpp:jingle:1',\n action: 'session-terminate',\n initiator: this.initiatorJid,\n sid: this.sid\n })\n .c('reason')\n .c((options && options.reason) || 'success')\n .up();\n\n if (options && 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 xmlns: 'http://jitsi.org/protocol/focus',\n id: this._bridgeSessionId,\n restart: options && options.requestRestart === true\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(sessionTerminate, 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 strope.jingle.js\n this.connection.jingle.terminate(this.sid);\n }\n\n /**\n *\n * @param reasonCondition\n * @param reasonText\n */\n onTerminated(reasonCondition, reasonText) {\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(JitsiTrackEvents.TRACK_REMOVED, track);\n });\n }\n\n this.close();\n }\n\n /**\n * Handles XMPP connection state changes.\n *\n * @param {XmppConnection.Status} status - The new status.\n */\n onXmppStatusChanged(status) {\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 * Parse the information from the xml sourceAddElem and translate it\n * into sdp lines\n * @param {jquery xml element} sourceAddElem the source-add\n * element from jingle\n * @param {SDP object} currentRemoteSdp the current remote\n * sdp (as of this new source-add)\n * @returns {list} a list of SDP line strings that should\n * be added to the remote SDP\n */\n _parseSsrcInfoFromSourceAdd(sourceAddElem, currentRemoteSdp) {\n const addSsrcInfo = [];\n const self = this;\n\n $(sourceAddElem).each((i1, content) => {\n const name = $(content).attr('name');\n let lines = '';\n\n $(content)\n .find('ssrc-group[xmlns=\"urn:xmpp:jingle:apps:rtp:ssma:0\"]')\n .each(function() {\n // eslint-disable-next-line no-invalid-this\n const semantics = this.getAttribute('semantics');\n const ssrcs\n = $(this) // eslint-disable-line no-invalid-this\n .find('>source')\n .map(function() {\n // eslint-disable-next-line no-invalid-this\n return this.getAttribute('ssrc');\n })\n .get();\n\n if (ssrcs.length) {\n lines += `a=ssrc-group:${semantics} ${ssrcs.join(' ')}\\r\\n`;\n }\n });\n\n // handles both >source and >description>source\n const tmp\n = $(content).find(\n 'source[xmlns=\"urn:xmpp:jingle:apps:rtp:ssma:0\"]');\n\n /* eslint-disable no-invalid-this */\n tmp.each(function() {\n const ssrc = $(this).attr('ssrc');\n\n if (currentRemoteSdp.containsSSRC(ssrc)) {\n\n // Do not print the warning for unified plan p2p case since ssrcs are never removed from the SDP.\n !self.isP2P && logger.warn(`${self} Source-add request for existing SSRC: ${ssrc}`);\n\n return;\n }\n\n // eslint-disable-next-line newline-per-chained-call\n $(this).find('>parameter').each(function() {\n lines += `a=ssrc:${ssrc} ${$(this).attr('name')}`;\n if ($(this).attr('value') && $(this).attr('value').length) {\n lines += `:${$(this).attr('value')}`;\n }\n lines += '\\r\\n';\n });\n });\n\n let midFound = false;\n\n /* eslint-enable no-invalid-this */\n currentRemoteSdp.media.forEach((media, i2) => {\n if (!SDPUtil.findLine(media, `a=mid:${name}`)) {\n return;\n }\n if (!addSsrcInfo[i2]) {\n addSsrcInfo[i2] = '';\n }\n addSsrcInfo[i2] += lines;\n midFound = true;\n });\n\n // In p2p unified mode with multi-stream enabled, the new sources will have content name that doesn't exist\n // in the current remote description. Add a new m-line for this newly signaled source.\n if (!midFound && this.isP2P) {\n addSsrcInfo[name] = lines;\n }\n });\n\n return addSsrcInfo;\n }\n\n /**\n * Handles a Jingle source-add message for this Jingle session.\n * @param elem An array of Jingle \"content\" elements.\n */\n addRemoteStream(elem) {\n this._addOrRemoveRemoteStream(true /* add */, elem);\n }\n\n /**\n * Handles a Jingle source-remove message for this Jingle session.\n * @param elem An array of Jingle \"content\" elements.\n */\n removeRemoteStream(elem) {\n this._addOrRemoveRemoteStream(false /* remove */, elem);\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 processSourceMap(message, mediaType) {\n if (!FeatureFlags.isSsrcRewritingSupported()) {\n return;\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, source);\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\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 muted && 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 xmlns: 'urn:xmpp:jingle:1',\n name: mediaType\n }).c('description', {\n xmlns: 'urn:xmpp:jingle:apps:rtp:1',\n media: mediaType\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 xmlns: 'urn:xmpp:jingle:apps:rtp:ssma:0',\n semantics: 'FID'\n })\n .c('source', {\n xmlns: 'urn:xmpp:jingle:apps:rtp:ssma:0',\n ssrc\n })\n .up()\n .c('source', {\n xmlns: 'urn:xmpp:jingle:apps:rtp:ssma:0',\n ssrc: rtx\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 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 removeRemoteStreamsOnLeave(id) {\n const workFunction = finishCallback => {\n const removeSsrcInfo = this.peerconnection.getRemoteSourceInfoByParticipant(id);\n\n if (removeSsrcInfo.length) {\n const newRemoteSdp = this._processRemoteRemoveSource(removeSsrcInfo);\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 * Handles either Jingle 'source-add' or 'source-remove' message for this\n * Jingle session.\n * @param {boolean} isAdd true for 'source-add' or false\n * otherwise.\n * @param {Array} elem an array of Jingle \"content\" elements.\n * @private\n */\n _addOrRemoveRemoteStream(isAdd, elem) {\n const logPrefix = isAdd ? 'addRemoteStream' : 'removeRemoteStream';\n\n if (isAdd) {\n this.readSsrcInfo(elem);\n }\n\n const workFunction = finishedCallback => {\n if (!this.peerconnection.localDescription\n || !this.peerconnection.localDescription.sdp) {\n const errMsg = `${logPrefix} - localDescription not ready yet`;\n\n logger.error(errMsg);\n finishedCallback(errMsg);\n\n return;\n }\n\n logger.log(`${this} Processing ${logPrefix}`);\n\n const sdp = new SDP(this.peerconnection.remoteDescription.sdp);\n const addOrRemoveSsrcInfo\n = isAdd\n ? this._parseSsrcInfoFromSourceAdd(elem, sdp)\n : this._parseSsrcInfoFromSourceRemove(elem, sdp);\n const newRemoteSdp\n = isAdd\n ? this._processRemoteAddSource(addOrRemoveSsrcInfo)\n : this._processRemoteRemoveSource(addOrRemoveSsrcInfo);\n\n this._renegotiate(newRemoteSdp.raw).then(() => {\n logger.log(`${this} ${logPrefix} - OK`);\n finishedCallback();\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 * Takes in a jingle offer iq, returns the new sdp offer\n * @param {jquery xml element} offerIq the incoming offer\n * @returns {SDP object} the jingle offer translated to SDP\n */\n _processNewJingleOfferIq(offerIq) {\n const remoteSdp = new SDP('');\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.readSsrcInfo($(offerIq).find('>content'));\n\n return remoteSdp;\n }\n\n /**\n * Remove the given ssrc lines from the current remote sdp\n * @param {list} removeSsrcInfo a list of SDP line strings that\n * should be removed from the remote SDP\n * @returns type {SDP Object} the new remote SDP (after removing the lines\n * in removeSsrcInfo\n */\n _processRemoteRemoveSource(removeSsrcInfo) {\n const remoteSdp = new SDP(this.peerconnection.peerconnection.remoteDescription.sdp);\n let ssrcs;\n\n removeSsrcInfo.forEach(lines => {\n // eslint-disable-next-line no-param-reassign\n lines = lines.split('\\r\\n');\n lines.pop(); // remove empty last element;\n ssrcs = lines.map(line => Number(line.split('a=ssrc:')[1]?.split(' ')[0]));\n\n let mid;\n\n lines.forEach(line => {\n mid = remoteSdp.media.findIndex(mLine => mLine.includes(line));\n if (mid > -1) {\n remoteSdp.media[mid] = remoteSdp.media[mid].replace(`${line}\\r\\n`, '');\n if (this.isP2P) {\n const mediaType = SDPUtil.parseMLine(remoteSdp.media[mid].split('\\r\\n')[0])?.media;\n const desiredDirection = this.peerconnection.getDesiredMediaDirection(mediaType, false);\n\n [ MediaDirection.SENDRECV, MediaDirection.SENDONLY ].forEach(direction => {\n remoteSdp.media[mid] = remoteSdp.media[mid]\n .replace(`a=${direction}`, `a=${desiredDirection}`);\n });\n } else {\n // Jvb connections will have direction set to 'sendonly' for the remote sources.\n remoteSdp.media[mid] = remoteSdp.media[mid]\n .replace(`a=${MediaDirection.SENDONLY}`, `a=${MediaDirection.INACTIVE}`);\n\n // Reject the m-line so that the browser removes the associated transceiver from the list\n // of available transceivers. This will prevent the client from trying to re-use these\n // inactive transceivers when additional video sources are added to the peerconnection.\n const { media, port } = SDPUtil.parseMLine(remoteSdp.media[mid].split('\\r\\n')[0]);\n\n remoteSdp.media[mid] = remoteSdp.media[mid].replace(`m=${media} ${port}`, `m=${media} 0`);\n }\n }\n });\n });\n\n // Update the ssrc owners list.\n ssrcs?.length && this._signalingLayer.removeSSRCOwners(ssrcs);\n\n remoteSdp.raw = remoteSdp.session + remoteSdp.media.join('');\n\n return remoteSdp;\n }\n\n /**\n * Add the given ssrc lines to the current remote sdp\n * @param {list} addSsrcInfo a list of SDP line strings that\n * should be added to the remote SDP\n * @returns type {SDP Object} the new remote SDP (after removing the lines\n * in removeSsrcInfo\n */\n _processRemoteAddSource(addSsrcInfo) {\n let remoteSdp = new SDP(this.peerconnection.remoteDescription.sdp);\n\n // Add a new m-line in the remote description if the source info for a secondary video source is recceived from\n // the remote p2p peer when multi-stream support is enabled.\n if (addSsrcInfo.length > remoteSdp.media.length && this.isP2P) {\n remoteSdp.addMlineForNewLocalSource(MediaType.VIDEO);\n remoteSdp = new SDP(remoteSdp.raw);\n }\n addSsrcInfo.forEach((lines, idx) => {\n remoteSdp.media[idx] += lines;\n\n // Make sure to change the direction to 'sendrecv/sendonly' only for p2p connections. For jvb connections,\n // a new m-line is added for the new remote sources.\n if (this.isP2P) {\n const mediaType = SDPUtil.parseMLine(remoteSdp.media[idx].split('\\r\\n')[0])?.media;\n const desiredDirection = this.peerconnection.getDesiredMediaDirection(mediaType, true);\n\n [ MediaDirection.RECVONLY, MediaDirection.INACTIVE ].forEach(direction => {\n remoteSdp.media[idx] = remoteSdp.media[idx]\n .replace(`a=${direction}`, `a=${desiredDirection}`);\n });\n }\n });\n remoteSdp.raw = remoteSdp.session + remoteSdp.media.join('');\n\n return remoteSdp;\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 _renegotiate(optionalRemoteSdp) {\n if (this.peerconnection.signalingState === 'closed') {\n const error = new Error('Attempted to renegotiate in state closed');\n\n this.room.eventEmitter.emit(XMPPEvents.RENEGOTIATION_FAILED, error, this);\n\n return Promise.reject(error);\n }\n\n const remoteSdp = optionalRemoteSdp || this.peerconnection.remoteDescription.sdp;\n\n if (!remoteSdp) {\n const error = new Error(`Can not renegotiate without remote description, current state: ${this.state}`);\n\n this.room.eventEmitter.emit(XMPPEvents.RENEGOTIATION_FAILED, error, this);\n\n return Promise.reject(error);\n }\n\n const remoteDescription = new RTCSessionDescription({\n type: 'offer',\n sdp: remoteSdp\n });\n\n const oldLocalSDP = this.peerconnection.localDescription.sdp;\n\n logger.debug(`${this} Renegotiate: setting remote description`);\n\n return this.peerconnection.setRemoteDescription(remoteDescription)\n .then(() => {\n logger.debug(`${this} Renegotiate: creating answer`);\n\n return this.peerconnection.createAnswer(this.mediaConstraints);\n })\n .then(answer => {\n logger.debug(`${this} Renegotiate: setting local description`);\n\n return this.peerconnection.setLocalDescription(answer);\n })\n .then(() => {\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 });\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} localTracks - Tracks to be added to the peer connection.\n * @returns {Promise} that resolves when the track is successfully added to the peerconnection, rejected\n * otherwise.\n */\n addTracks(localTracks = null) {\n if (!localTracks?.length) {\n Promise.reject(new Error('No tracks passed'));\n }\n\n if (localTracks.find(track => track.getType() !== MediaType.VIDEO)) {\n return Promise.reject(new Error('Multiple tracks of the given media type are not supported'));\n }\n\n const replaceTracks = [];\n const workFunction = finishedCallback => {\n const remoteSdp = new SDP(this.peerconnection.peerconnection.remoteDescription.sdp);\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.addMlineForNewLocalSource(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 * Resumes or suspends media transfer over the underlying peer connection.\n *\n * @param {boolean} active - true to enable media transfer or false to suspend media transmission\n * @returns {Promise}\n */\n setMediaTransferActive(active) {\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.tpcUtils.setMediaTransferActive(active)\n .then(() => {\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\n return Promise.allSettled(promises);\n });\n }\n\n /**\n * Replaces oldTrack with newTrack and performs a single\n * offer/answer cycle after both operations are done. Either\n * oldTrack or newTrack can be null; replacing a valid\n * oldTrack with a null newTrack effectively just removes\n * oldTrack\n * @param {JitsiLocalTrack|null} oldTrack the current track in use to be\n * replaced\n * @param {JitsiLocalTrack|null} newTrack the new track to use\n * @returns {Promise} which resolves once the replacement is complete\n * with no arguments or rejects with an error {string}\n */\n replaceTrack(oldTrack, newTrack) {\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 * Parse the information from the xml sourceRemoveElem and translate it\n * into sdp lines\n * @param {jquery xml element} sourceRemoveElem the source-remove\n * element from jingle\n * @param {SDP object} currentRemoteSdp the current remote\n * sdp (as of this new source-remove)\n * @returns {list} a list of SDP line strings that should\n * be removed from the remote SDP\n */\n _parseSsrcInfoFromSourceRemove(sourceRemoveElem, currentRemoteSdp) {\n const removeSsrcInfo = [];\n\n $(sourceRemoveElem).each((i1, content) => {\n const name = $(content).attr('name');\n let lines = '';\n\n $(content)\n .find('ssrc-group[xmlns=\"urn:xmpp:jingle:apps:rtp:ssma:0\"]')\n .each(function() {\n /* eslint-disable no-invalid-this */\n const semantics = this.getAttribute('semantics');\n const ssrcs\n = $(this)\n .find('>source')\n .map(function() {\n return this.getAttribute('ssrc');\n })\n .get();\n\n if (ssrcs.length) {\n lines\n += `a=ssrc-group:${semantics} ${\n ssrcs.join(' ')}\\r\\n`;\n }\n\n /* eslint-enable no-invalid-this */\n });\n const ssrcs = [];\n\n // handles both >source and >description>source versions\n const tmp\n = $(content).find(\n 'source[xmlns=\"urn:xmpp:jingle:apps:rtp:ssma:0\"]');\n\n tmp.each(function() {\n // eslint-disable-next-line no-invalid-this\n const ssrc = $(this).attr('ssrc');\n\n ssrcs.push(ssrc);\n });\n currentRemoteSdp.media.forEach((media, i2) => {\n if (!SDPUtil.findLine(media, `a=mid:${name}`)) {\n return;\n }\n if (!removeSsrcInfo[i2]) {\n removeSsrcInfo[i2] = '';\n }\n ssrcs.forEach(ssrc => {\n const ssrcLines\n = SDPUtil.findLines(media, `a=ssrc:${ssrc}`);\n\n if (ssrcLines.length) {\n removeSsrcInfo[i2] += `${ssrcLines.join('\\r\\n')}\\r\\n`;\n }\n });\n removeSsrcInfo[i2] += lines;\n });\n });\n\n return removeSsrcInfo;\n }\n\n /**\n * Adds local track back to the peerconnection associated with this session.\n * @param {JitsiLocalTrack} track\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 string that provides some error\n * details in case something goes wrong.\n */\n addTrackToPc(track) {\n return this._addRemoveTrack(false /* add */, track)\n .then(() => {\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 return this.peerconnection.configureVideoSenderEncodings(track);\n }\n });\n }\n\n /**\n * Remove local track as part of the mute operation.\n * @param {JitsiLocalTrack} track the local track to be removed\n * @return {Promise} a promise which will be resolved once the local track\n * is removed from this session and the renegotiation is performed.\n * The promise will be rejected with a string that the describes\n * the error if anything goes wrong.\n */\n removeTrackFromPc(track) {\n return this._addRemoveTrack(true /* remove */, track);\n }\n\n /**\n * See {@link addTrackToPc} and {@link removeTrackFromPc}.\n * @param {boolean} isRemove true for \"remove\" operation or false for \"add\" operation.\n * @param {JitsiLocalTrack} track the track that will be added/removed\n * @private\n */\n _addRemoveTrack(isRemove, track) {\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 * Resumes or suspends video media transfer over the p2p peer connection.\n *\n * @param {boolean} videoActive true to enable video media transfer or false to suspend video\n * media transmission.\n * @return {Promise} a Promise 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 setP2pVideoTransferActive(videoActive) {\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 * 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 modifyContents(jingleContents) {\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 * Figures out added/removed ssrcs and send update IQs.\n * @param oldSDP SDP object for old description.\n * @param newSDP SDP object for new description.\n */\n notifyMySSRCUpdate(oldSDP, newSDP) {\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\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].mid;\n if (signaledSsrcs?.length) {\n ssrcs = ssrcs.concat(signaledSsrcs);\n }\n });\n\n return {\n mediaType,\n ssrcs\n };\n };\n\n // send source-remove IQ.\n let sdpDiffer = new SDPDiffer(newSDP, oldSDP);\n const remove = $iq({ to: this.remoteJid,\n type: 'set' })\n .c('jingle', {\n xmlns: 'urn:xmpp:jingle:1',\n action: 'source-remove',\n initiator: this.initiatorJid,\n sid: this.sid\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 // 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(remove, 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);\n const add = $iq({ to: this.remoteJid,\n type: 'set' })\n .c('jingle', {\n xmlns: 'urn:xmpp:jingle:1',\n action: 'source-add',\n initiator: this.initiatorJid,\n sid: this.sid\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(add, error => {\n this.room.eventEmitter.emit(XMPPEvents.SOURCE_ADD_ERROR, this, error, addedSsrcInfo.mediaType, ctx);\n }),\n IQ_TIMEOUT);\n }\n }\n\n /**\n * Method returns function(errorResponse) which is a callback to be passed\n * to Strophe connection.sendIQ method. An 'error' structure is created that\n * is passed as 1st argument to given failureCb. 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 IQ_TIMEOUT milliseconds}\n * source: {request.tree() that provides original request}\n * session: {this JingleSessionPC.toString()}\n * }\n * @param request Strophe IQ instance which is the request to be dumped into\n * the error structure\n * @param failureCb function(error) called when error response was returned\n * or when a timeout has occurred.\n * @returns {function(this:JingleSessionPC)}\n */\n newJingleErrorHandler(request, failureCb) {\n return errResponse => {\n\n const error = {};\n\n // Get XMPP error code and condition(reason)\n const errorElSel = $(errResponse).find('error');\n\n if (errorElSel.length) {\n error.code = errorElSel.attr('code');\n const errorReasonSel = $(errResponse).find('error :first');\n\n if (errorReasonSel.length) {\n error.reason = errorReasonSel[0].tagName;\n }\n\n const errorMsgSel = errorElSel.find('>text');\n\n if (errorMsgSel.length) {\n error.msg = errorMsgSel.text();\n }\n }\n\n if (!errResponse) {\n error.reason = 'timeout';\n }\n\n error.session = this.toString();\n\n if (failureCb) {\n failureCb(error);\n } else if (this.state === JingleSessionState.ENDED\n && error.reason === 'item-not-found') {\n // When remote peer decides to terminate the session, but it\n // still have few messages on the queue for processing,\n // it will first send us 'session-terminate' (we enter ENDED)\n // and then follow with 'item-not-found' for the queued requests\n // We don't want to have that logged on error level.\n logger.debug(`${this} Jingle error: ${JSON.stringify(error)}`);\n } else {\n logger.error(`Jingle error: ${JSON.stringify(error)}`);\n }\n };\n }\n\n /**\n * Returns the ice connection state for the peer connection.\n * @returns the ice connection state for the peer connection.\n */\n getIceConnectionState() {\n return this.peerconnection.getConnectionState();\n }\n\n /**\n * Closes the peerconnection.\n */\n close() {\n this.state = JingleSessionState.ENDED;\n this.establishmentDuration = undefined;\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 && 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 * Converts to string with minor summary.\n * @return {string}\n */\n toString() {\n return `JingleSessionPC[session=${this.isP2P ? 'P2P' : 'JVB'},initiator=${this.isInitiator},sid=${this.sid}]`;\n }\n}\n","import { getLogger } from '@jitsi/logger';\nimport $ from 'jquery';\nimport clonedeep from 'lodash.clonedeep';\nimport { $iq, Strophe } from 'strophe.js';\n\nimport { MediaType } from '../../service/RTC/MediaType';\nimport {\n ACTION_JINGLE_TR_RECEIVED,\n ACTION_JINGLE_TR_SUCCESS,\n createJingleEvent\n} from '../../service/statistics/AnalyticsEvents';\nimport { XMPPEvents } from '../../service/xmpp/XMPPEvents';\nimport Statistics from '../statistics/statistics';\nimport RandomUtil from '../util/RandomUtil';\n\nimport ConnectionPlugin from './ConnectionPlugin';\nimport { expandSourcesFromJson } from './JingleHelperFunctions';\nimport JingleSessionPC from './JingleSessionPC';\n\nconst logger = getLogger(__filename);\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}\n */\nfunction _parseIceCandidates(transport) {\n const candidates = $(transport).find('>candidate');\n const parseCandidates = [];\n\n // Extract the candidate information from the IQ.\n candidates.each((_, 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 *\n */\nexport default class JingleConnectionPlugin extends ConnectionPlugin {\n /**\n * Creates new JingleConnectionPlugin\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 PeerConnection.\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 sid = $(iq).find('jingle').attr('sid');\n const action = $(iq).find('jingle').attr('action');\n const fromJid = iq.getAttribute('from');\n\n // send ack first\n const ack = $iq({ type: 'result',\n to: fromJid,\n id: iq.getAttribute('id')\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 = $(iq).find('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.log('(TIME) received session-initiate:\\t', now);\n const startMuted = $(iq).find('jingle>startmuted');\n\n isP2P && logger.debug(`Received ${action} from ${fromJid}`);\n if (startMuted?.length) {\n const audioMuted = startMuted.attr(MediaType.AUDIO);\n const videoMuted = startMuted.attr(MediaType.VIDEO);\n\n this.eventEmitter.emit(\n XMPPEvents.START_MUTED_FROM_FOCUS,\n audioMuted === 'true',\n videoMuted === 'true');\n }\n const pcConfig = isP2P ? this.p2pIceConfig : this.jvbIceConfig;\n\n sess\n = new JingleSessionPC(\n $(iq).find('jingle').attr('sid'),\n $(iq).attr('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, $(iq).find('>jingle'), now);\n break;\n }\n case 'session-accept': {\n const ssrcs = [];\n const contents = $(iq).find('jingle>content');\n\n // Extract the SSRCs from the session-accept received from a p2p peer.\n for (const content of contents) {\n const ssrc = $(content).find('description').attr('ssrc');\n\n ssrc && ssrcs.push(ssrc);\n }\n logger.debug(`Received ${action} from ${fromJid} with ssrcs=${ssrcs}`);\n this.eventEmitter.emit(XMPPEvents.CALL_ACCEPTED, sess, $(iq).find('>jingle'));\n break;\n }\n case 'content-modify': {\n logger.debug(`Received ${action} from ${fromJid}`);\n sess.modifyContents($(iq).find('>jingle'));\n break;\n }\n case 'transport-info': {\n const candidates = _parseIceCandidates($(iq).find('jingle>content>transport'));\n\n logger.debug(`Received ${action} from ${fromJid} for candidates=${candidates.join(', ')}`);\n this.eventEmitter.emit(XMPPEvents.TRANSPORT_INFO, sess, $(iq).find('>jingle'));\n break;\n }\n case 'session-terminate': {\n logger.log('terminating...', sess.sid);\n let reasonCondition = null;\n let reasonText = null;\n\n if ($(iq).find('>jingle>reason').length) {\n reasonCondition\n = $(iq).find('>jingle>reason>:first')[0].tagName;\n reasonText = $(iq).find('>jingle>reason>text').text();\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.info('(TIME) Start transport replace:\\t', now);\n const transport = $(iq).find('jingle>content>transport');\n const candidates = _parseIceCandidates(transport);\n const iceUfrag = $(transport).attr('ufrag');\n const icePwd = $(transport).attr('pwd');\n const dtlsFingerprint = $(transport).find('>fingerprint')?.text();\n\n logger.debug(`Received ${action} from ${fromJid} with iceUfrag=${iceUfrag},`\n + ` icePwd=${icePwd}, DTLS fingerprint=${dtlsFingerprint}, candidates=${candidates.join(', ')}`);\n\n Statistics.sendAnalytics(createJingleEvent(\n ACTION_JINGLE_TR_RECEIVED,\n {\n p2p: isP2P,\n value: now\n }));\n\n sess.replaceTransport($(iq).find('>jingle'), () => {\n const successTime = window.performance.now();\n\n logger.info('(TIME) Transport replace success:\\t', successTime);\n Statistics.sendAnalytics(createJingleEvent(\n ACTION_JINGLE_TR_SUCCESS,\n {\n p2p: isP2P,\n value: successTime\n }));\n }, error => {\n logger.error('Transport replace failed', error);\n sess.sendTransportReject();\n });\n break;\n }\n case 'source-add':\n sess.addRemoteStream($(iq).find('>jingle>content'));\n break;\n case 'source-remove':\n sess.removeRemoteStream($(iq).find('>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 JingleSessionPC 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, reasonText) {\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({ type: 'get',\n to: this.xmpp.options.hosts.domain })\n .c('services', { xmlns: 'urn:xmpp:extdisco:2' }),\n v2Res => this.onReceiveStunAndTurnCredentials(v2Res),\n () => {\n logger.warn('getting turn credentials with extdisco:2 failed, trying extdisco:1');\n this.connection.sendIQ(\n $iq({ type: 'get',\n to: this.xmpp.options.hosts.domain })\n .c('services', { xmlns: 'urn:xmpp:extdisco:1' }),\n v1Res => this.onReceiveStunAndTurnCredentials(v1Res),\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 $(res).find('>services>service').each((idx, el) => {\n // eslint-disable-next-line no-param-reassign\n el = $(el);\n const dict = {};\n const type = el.attr('type');\n\n switch (type) {\n case 'stun':\n dict.urls = `stun:${el.attr('host')}`;\n if (el.attr('port')) {\n dict.urls += `:${el.attr('port')}`;\n }\n iceservers.push(dict);\n break;\n case 'turn':\n case 'turns': {\n dict.urls = `${type}:`;\n dict.username = el.attr('username');\n dict.urls += el.attr('host');\n const port = el.attr('port');\n\n if (port) {\n dict.urls += `:${port}`;\n }\n const transport = el.attr('transport');\n\n if (transport && transport !== 'udp') {\n dict.urls += `?transport=${transport}`;\n }\n\n dict.credential = el.attr('password') || dict.credential;\n iceservers.push(dict);\n break;\n }\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 */\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 updateLog: pc.updateLog,\n stats: pc.stats,\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 * Logs raw stanzas and makes them available for download as JSON\n */\nclass StropheLogger extends ConnectionPlugin {\n /**\n *\n */\n constructor() {\n super();\n this.log = [];\n }\n\n /**\n *\n * @param connection\n */\n init(connection) {\n super.init(connection);\n this.connection.rawInput = this.logIncoming.bind(this);\n this.connection.rawOutput = this.logOutgoing.bind(this);\n }\n\n /**\n *\n * @param stanza\n */\n logIncoming(stanza) {\n this.log.push([ new Date().getTime(), 'incoming', stanza ]);\n }\n\n /**\n *\n * @param stanza\n */\n logOutgoing(stanza) {\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 $ from 'jquery';\nimport { $iq } from 'strophe.js';\n\nimport ConnectionPlugin from './ConnectionPlugin';\n\nconst logger = getLogger(__filename);\n\nconst RAYO_XMLNS = 'urn:xmpp:rayo:1';\n\n/**\n *\n */\nexport default class RayoConnectionPlugin extends ConnectionPlugin {\n /**\n *\n * @param connection\n */\n init(connection) {\n super.init(connection);\n\n this.connection.addHandler(\n this.onRayo.bind(this), RAYO_XMLNS, 'iq', 'set', null, null);\n }\n\n /**\n *\n * @param iq\n */\n onRayo(iq) {\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(to, from, roomName, roomPass, focusMucJid) {\n return new Promise((resolve, reject) => {\n if (!focusMucJid) {\n reject(new Error('Internal error!'));\n\n return;\n }\n const req = $iq({\n type: 'set',\n to: focusMucJid\n });\n\n req.c('dial', {\n xmlns: RAYO_XMLNS,\n to,\n from\n });\n req.c('header', {\n name: 'JvbRoomName',\n value: roomName\n }).up();\n\n if (roomPass && roomPass.length) {\n req.c('header', {\n name: 'JvbRoomPassword',\n value: roomPass\n }).up();\n }\n\n this.connection.sendIQ(\n req,\n result => {\n logger.info('Dial result ', result);\n\n // eslint-disable-next-line newline-per-chained-call\n const resource = $(result).find('ref').attr('uri');\n\n this.callResource = resource.substr('xmpp:'.length);\n logger.info(`Received call resource: ${this.callResource}`);\n resolve();\n },\n error => {\n logger.info('Dial error ', error);\n reject(error);\n });\n });\n }\n\n /* eslint-enable max-params */\n\n /**\n *\n */\n hangup() {\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 type: 'set',\n to: this.callResource\n });\n\n req.c('hangup', {\n xmlns: RAYO_XMLNS\n });\n\n this.connection.sendIQ(req, result => {\n logger.info('Hangup result ', result);\n this.callResource = null;\n resolve();\n }, error => {\n logger.info('Hangup error ', error);\n this.callResource = null;\n reject(new Error('Hangup error '));\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(__filename);\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 = -1;\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 = /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\n = /request errored, status: (\\d+), number of errors: \\d+/;\n\n/**\n *\n */\nexport default function() {\n\n Strophe.log = function(level, msg) {\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 && 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() {\n return lastErrorStatus;\n };\n\n Strophe.getStatusString = function(status) {\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 $ from 'jquery';\nimport { $msg, Strophe } from 'strophe.js';\nimport 'strophejs-plugin-disco';\n\nimport * as JitsiConnectionErrors from '../../JitsiConnectionErrors';\nimport * as JitsiConnectionEvents from '../../JitsiConnectionEvents';\nimport { XMPPEvents } from '../../service/xmpp/XMPPEvents';\nimport browser from '../browser';\nimport { E2EEncryption } from '../e2ee/E2EEncryption';\nimport FeatureFlags from '../flags/FeatureFlags';\nimport Statistics from '../statistics/statistics';\nimport Listenable from '../util/Listenable';\nimport RandomUtil from '../util/RandomUtil';\n\nimport Caps, { parseDiscoInfo } from './Caps';\nimport XmppConnection from './XmppConnection';\nimport Moderator from './moderator';\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(__filename);\n\n/**\n* Regex to extract exact error message on jwt error.\n*/\nconst FAILURE_REGEX = /(.*)<\\/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 }) {\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 websocketKeepAlive,\n websocketKeepAliveUrl,\n xmppPing,\n shard\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() {\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 = [\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 = 'type';\n\n/**\n * The feature used by jigasi participants.\n * @type {string}\n */\nexport const FEATURE_JIGASI = 'http://jitsi.org/protocol/jigasi';\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 = 'https://jitsi.org/meet/e2ee';\n\n/**\n *\n */\nexport default class XMPP extends Listenable {\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} options.p2pStunServers see {@link JingleConnectionPlugin} for more details.\n * @param token\n */\n constructor(options, token) {\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 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 token,\n websocketKeepAlive: options.websocketKeepAlive,\n websocketKeepAliveUrl: options.websocketKeepAliveUrl,\n xmppPing,\n shard: options.deploymentInfo.shard\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 = {\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 this.eventEmitter.emit(\n JitsiConnectionEvents.CONNECTION_FAILED,\n JitsiConnectionErrors.OTHER_ERROR,\n undefined,\n undefined,\n details);\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 // 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 $(window).on(`${this.options.disableBeforeUnloadHandlers ? '' : 'beforeunload '}unload`, ev => {\n this.disconnect(ev).catch(() => {\n // ignore errors in order to not brake the unload.\n });\n });\n }\n\n /**\n * Initializes the list of feature advertised through the disco-info\n * mechanism.\n */\n initFeaturesList() {\n // http://xmpp.org/extensions/xep-0167.html#support\n // http://xmpp.org/extensions/xep-0176.html#support\n this.caps.addFeature('urn:xmpp:jingle:1');\n this.caps.addFeature('urn:xmpp:jingle:apps:rtp:1');\n this.caps.addFeature('urn:xmpp:jingle:transports:ice-udp:1');\n this.caps.addFeature('urn:xmpp:jingle:apps:dtls:0');\n this.caps.addFeature('urn:xmpp:jingle:transports:dtls-sctp:1');\n this.caps.addFeature('urn:xmpp:jingle:apps:rtp:audio');\n this.caps.addFeature('urn:xmpp:jingle:apps: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\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 // 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\n /**\n *\n */\n getConnection() {\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 connectionHandler(credentials = {}, status, msg) {\n const now = window.performance.now();\n const statusStr = Strophe.getStatusString(status).toLowerCase();\n\n this.connectionTimes[statusStr] = now;\n logger.log(\n `(TIME) Strophe ${statusStr}${msg ? `[${msg}]` : ''}:\\t`,\n 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\n this.sendDiscoInfo && this.connection.jingle.getStunAndTurnCredentials();\n\n logger.info(`My Jabber ID: ${this.connection.jid}`);\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)\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 // 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 }\n\n /**\n * Process received identities.\n * @param {Set} identities The identities to process.\n * @param {Set} features The features to process, optional. If missing lobby component will be queried\n * for more features.\n * @private\n */\n _processDiscoInfoIdentities(identities, features) {\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 === '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 && 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 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 && e.message));\n }\n }\n\n if (identity.type === 'room_metadata') {\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\n this._maybeSendDeploymentInfoStat(true);\n\n if (this._components.length > 0) {\n this.connection.addHandler(this._onPrivateMessage.bind(this), null, 'message', null, null);\n }\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 _parseConnectionFailedMessage(msg) {\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 _connect(jid, password) {\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 && 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 _onSystemMessage(msg) {\n // proceed only if the message has any of the expected information\n if ($(msg).find('>services').length === 0 && $(msg).find('>query').length === 0) {\n return;\n }\n\n this.sendDiscoInfo = false;\n\n const foundIceServers = this.connection.jingle.onReceiveStunAndTurnCredentials(msg);\n\n const { features, identities } = parseDiscoInfo(msg);\n\n this._processDiscoInfoIdentities(identities, features);\n\n if (foundIceServers || identities.size > 0 || features.size > 0) {\n this.connection._stropheConn.deleteHandler(this._sysMessageHandler);\n this._sysMessageHandler = null;\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 attach(options) {\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.log('(TIME) Strophe Attaching:\\t', now);\n this.connection.attach(options.jid, options.sid,\n parseInt(options.rid, 10) + 1,\n this.connectionHandler.bind(this, {\n jid: options.jid,\n password: options.password\n }));\n }\n\n /**\n * Resets any state/flag before starting a new connection.\n * @private\n */\n _resetState() {\n this.anonymousConnectionFailed = false;\n this.connectionFailed = false;\n this.lastErrorMsg = undefined;\n this.disconnectInProgress = undefined;\n }\n\n /**\n *\n * @param jid\n * @param password\n */\n connect(jid, password) {\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 && 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 && 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 {Promise} Resolves with an instance of a strophe muc.\n */\n createRoom(roomName, options, onCreateResource) {\n // Support passing the domain in a String object as part of the room name.\n const domain = roomName.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 getRoomJid(roomName, domain) {\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 isRoomCreated(roomName, domain) {\n return this.connection.emuc.isRoomCreated(this.getRoomJid(roomName, domain));\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 getJid() {\n return this.connection.jid;\n }\n\n /**\n * Returns the logs from strophe.jingle.\n * @returns {Object}\n */\n getJingleLog() {\n const jingle = this.connection.jingle;\n\n\n return jingle ? jingle.getLog() : {};\n }\n\n /**\n * Returns the logs from strophe.\n */\n getXmppLog() {\n return (this.connection.logger || {}).log || null;\n }\n\n /**\n *\n */\n dial(...args) {\n 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 ping(timeout) {\n return new Promise((resolve, reject) => {\n this.connection.ping.ping(this.connection.pingDomain, resolve, reject, timeout);\n });\n }\n\n /**\n *\n */\n getSessions() {\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 disconnect(ev) {\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 * 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 _cleanupXmppConnection(ev) {\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 _initStrophePlugins() {\n const iceConfig = {\n jvb: { iceServers: [ ] },\n p2p: { iceServers: [ ] }\n };\n\n const p2pStunServers = (this.options.p2p\n && 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 && 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 {object} contains details about a connection failure.\n * @private\n */\n _getConnectionFailedReasonDetails() {\n const details = {};\n\n // check for moving between shard if information is available\n if (this.options.deploymentInfo\n && 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 * 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 sendDominantSpeakerEvent(roomJid, silence) {\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 xmlns: 'http://jitsi.org/jitmeet',\n room: roomJid,\n silence })\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 sendFaceLandmarksEvent(roomJid, payload) {\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 xmlns: 'http://jitsi.org/jitmeet',\n room: roomJid,\n faceExpression: payload.faceExpression,\n timestamp: payload.timestamp,\n duration: payload.duration\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 tryParseJSONAndVerify(jsonString) {\n // ignore empty strings, like message errors\n if (!jsonString) {\n return false;\n }\n\n try {\n const json = safeJsonParse(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 * 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 _onPrivateMessage(msg) {\n const from = msg.getAttribute('from');\n\n if (!this._components.includes(from)) {\n return true;\n }\n\n const jsonMessage = $(msg).find('>json-message')\n .text();\n const parsedJson = this.tryParseJSONAndVerify(jsonMessage);\n\n if (!parsedJson) {\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] === '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 }\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 _maybeSendDeploymentInfoStat(force) {\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 (aprops && Object.keys(aprops).length > 0) {\n const logObject = {};\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, JSON.parse(JSON.stringify({\n region,\n shard\n })));\n }\n\n }\n}\n","import {\n CONNECTION_DISCONNECTED,\n CONNECTION_ESTABLISHED,\n CONNECTION_FAILED\n} from './JitsiConnectionEvents';\nimport XMPP from './modules/xmpp/xmpp';\n\n/**\n * @typedef {Object} UpgradeRoleError\n *\n * @property {JitsiConnectionErrors} [connectionError] - One of\n * {@link JitsiConnectionErrors} which occurred when trying to connect to the\n * XMPP server.\n * @property {String} [authenticationError] - One of XMPP error conditions\n * returned by Jicofo on authentication attempt. See\n * {@link https://xmpp.org/rfcs/rfc3920.html#streams-error}.\n * @property {String} [message] - More details about the error.\n * @property {Object} [credentials] - The credentials that failed the\n * authentication.\n * @property {String} [credentials.jid] - The XMPP ID part of the credentials\n * that failed the authentication.\n * @property {string} [credentials.password] - The password part of the\n * credentials that failed the authentication.\n *\n * NOTE If neither one of the errors is present, then the operation has been\n * canceled.\n */\n\n/* eslint-disable no-invalid-this */\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 {Object} options\n * @param {string} options.id - XMPP user's ID to log in. For example,\n * user@xmpp-server.com.\n * @param {string} options.password - XMPP user's password to log in with.\n * @param {Function} [options.onCreateResource]\n * @param {Function} [options.onLoginSuccessful] - Callback called when logging\n * into the XMPP server was successful. The next step will be to obtain a new\n * session ID from Jicofo and join the MUC using it which will effectively\n * upgrade the user's role to moderator.\n * @returns {Object} A thenable which (1) settles when the process of\n * authenticating and upgrading the role of the specified XMPP user finishes and\n * (2) has a cancel method that allows the caller to interrupt the\n * process. If the process finishes successfully, the session ID has been stored\n * in the settings and the thenable is resolved. If the process\n * finishes with failure, the thenable is rejected with reason of type\n * {@link UpgradeRoleError} which will have either connectionError or\n * authenticationError property set depending on which of the steps has\n * failed. If cancel is called before the process finishes, then the\n * thenable will be rejected with an empty object (i.e. no error property will\n * be set on the rejection reason).\n */\nexport default function authenticateAndUpgradeRole({\n // 1. Log the specified XMPP user in.\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}) {\n let canceled = false;\n let rejectPromise;\n let xmpp = new XMPP(this.connection.options);\n\n const process = new Promise((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\n\n xmpp.addListener(\n CONNECTION_DISCONNECTED,\n () => {\n xmpp = undefined;\n });\n xmpp.addListener(\n CONNECTION_ESTABLISHED,\n () => {\n if (canceled) {\n return;\n }\n\n // Let the caller know that the XMPP login was successful.\n onLoginSuccessful && onLoginSuccessful();\n\n // Now authenticate with Jicofo and get a new session ID.\n const room = xmpp.createRoom(\n this.options.name,\n this.options.config,\n onCreateResource\n );\n\n room.xmpp.moderator.authenticate(room.roomjid)\n .then(() => {\n xmpp && 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).finally(resolve);\n })\n .catch(({ error, message }) => {\n xmpp.disconnect();\n\n reject({\n authenticationError: error,\n message\n });\n });\n });\n xmpp.addListener(\n CONNECTION_FAILED,\n (connectionError, message, credentials) => {\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.cancel = () => {\n canceled = true;\n rejectPromise({});\n xmpp && xmpp.disconnect();\n };\n\n return process;\n}\n\n/* eslint-enable no-invalid-this */\n","import { safeJsonParse } from '@jitsi/js-utils/json';\nimport { getLogger } from '@jitsi/logger';\n\nimport RTCEvents from '../../service/RTC/RTCEvents';\nimport { createBridgeChannelClosedEvent } from '../../service/statistics/AnalyticsEvents';\nimport Statistics from '../statistics/statistics';\n\nconst logger = getLogger(__filename);\n\n/**\n * Handles a WebRTC RTCPeerConnection or a WebSocket instance to communicate\n * with the videobridge.\n */\nexport default class BridgeChannel {\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 {RTCPeerConnection} [peerconnection] WebRTC peer connection\n * instance.\n * @param {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(peerconnection, wsUrl, emitter, conference) {\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() {\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() {\n let timeoutS = 1;\n\n const reload = () => {\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(this._wsUrl);\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() {\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) {\n if (!this._areRetriesEnabled) {\n return;\n }\n const { code, reason } = closeEvent;\n\n Statistics.sendAnalytics(createBridgeChannelClosedEvent(code, 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() {\n return this._mode;\n }\n\n /**\n * Closes the currently opened channel.\n */\n close() {\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() {\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) {\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, payload) {\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) {\n logger.log(`Sending lastN=${value}.`);\n\n this._send({\n colibriClass: 'LastNChangedEvent',\n lastN: value\n });\n }\n\n /**\n * Sends a 'ReceiverVideoConstraints' message via the bridge channel.\n *\n * @param {ReceiverVideoConstraints} constraints video constraints.\n */\n sendReceiverVideoConstraintsMessage(constraints) {\n logger.log(`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, videoType) {\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) {\n const emitter = this._eventEmitter;\n\n channel.onopen = () => {\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 => {\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 }) => {\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 '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 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 '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 => {\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) {\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 * 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","import { getLogger } from '@jitsi/logger';\nimport clonedeep from 'lodash.clonedeep';\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 { AVAILABLE_DEVICE } from '../../service/statistics/AnalyticsEvents';\nimport browser from '../browser';\nimport Statistics from '../statistics/statistics';\nimport Listenable from '../util/Listenable';\n\nimport screenObtainer from './ScreenObtainer';\n\nconst logger = getLogger(__filename);\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 height: {\n ideal: 720,\n max: 720,\n min: 180\n },\n width: {\n ideal: 1280,\n max: 1280,\n min: 320\n },\n frameRate: {\n min: 15,\n max: 30\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');\nconst isAudioOutputDeviceChangeAvailable\n = typeof featureDetectionAudioEl.setSinkId !== 'undefined';\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 (!constraints.video) {\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.frameRate) {\n constraints.video.frameRate = 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 }\n\n constraints.audio = {\n autoGainControl: !disableAGC && !disableAP,\n echoCancellation: !disableAEC && !disableAP,\n noiseSuppression: !disableNS && !disableAP\n };\n\n if (options.micDeviceId) {\n constraints.audio.deviceId = { exact: options.micDeviceId };\n }\n\n if (stereo) {\n Object.assign(constraints.audio, { channelCount: 2 });\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 kind: info.kind,\n deviceId: info.deviceId,\n groupId: info.groupId,\n label: info.label,\n facing: info.facing\n });\n }\n}\n\n/**\n * Sends analytics event with the passed device list.\n *\n * @param {Array} 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 'video_input_device_count': videoInputDeviceCount,\n 'video_output_device_count': videoOutputDeviceCount,\n 'device_id': device.deviceId,\n 'device_group_id': device.groupId,\n 'device_kind': device.kind,\n 'device_label': device.label\n };\n\n Statistics.sendAnalytics(AVAILABLE_DEVICE, attributes);\n });\n}\n\n/**\n *\n */\nclass RTCUtils extends Listenable {\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 window.clearInterval(availableDevicesPollTimer);\n availableDevicesPollTimer = undefined;\n\n if (!browser.isReactNative()) {\n this.attachMediaStream\n = wrapAttachMediaStream((element, stream) => {\n if (element) {\n element.srcObject = stream;\n }\n });\n }\n\n this.pcConstraints = {};\n\n screenObtainer.init(options);\n\n if (this.isDeviceListAvailable()) {\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 /**\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 (typeof timeout === 'number' && !isNaN(timeout) && timeout > 0) {\n gumTimeout = setTimeout(() => {\n timeoutExpired = true;\n gumTimeout = undefined;\n reject(new JitsiTrackError(JitsiTrackErrors.TIMEOUT));\n }, timeout);\n }\n\n navigator.mediaDevices.getUserMedia(constraints)\n .then(stream => {\n logger.log('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 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 // else {\n // Probably the error is not caused by the lack of permissions and we don't need to update them.\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} 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 {Array} options.desktopSharingSources - The types of sources (\"screen\", \"window\", etc)\n * from which the user can select what to share.\n * @returns {Promise} 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 } = 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({ desktopSharingSources });\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 stream: desktopAudioStream,\n sourceId,\n sourceType,\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 stream: desktopVideoStream,\n sourceId,\n sourceType,\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 stream: audioStream,\n track: audioStream.getAudioTracks()[0],\n effects: otherOptions.effects\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 stream: videoStream,\n track: videoStream.getVideoTracks()[0],\n videoType: VideoType.CAMERA,\n effects: otherOptions.effects\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 * Checks whether it is possible to enumerate available cameras/microphones.\n *\n * @returns {boolean} {@code true} if the device listing is available;\n * {@code false}, otherwise.\n */\n isDeviceListAvailable() {\n return Boolean(\n navigator.mediaDevices\n && navigator.mediaDevices.enumerateDevices);\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.log(`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 whether available devices have permissions granted\n * @returns {Boolean}\n */\n arePermissionsGrantedForAvailableDevices() {\n return availableDevices.some(device => Boolean(device.label));\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 kind: device.kind,\n label: device.label,\n groupId: device.groupId\n };\n\n deviceList.push(deviceData);\n\n return { deviceList };\n }\n\n /**\n * Returns true 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\nconst rtcUtils = new RTCUtils();\n\n/**\n * Wraps original attachMediaStream function to set current audio output device\n * if this is supported.\n * @param {Function} origAttachMediaStream\n * @returns {Function}\n */\nfunction wrapAttachMediaStream(origAttachMediaStream) {\n return function(element, stream) {\n // eslint-disable-next-line prefer-rest-params\n origAttachMediaStream.apply(rtcUtils, arguments);\n\n if (stream\n && rtcUtils.isDeviceChangeAvailable('output')\n && stream.getAudioTracks\n && stream.getAudioTracks().length\n\n // we skip setting audio output if there was no explicit change\n && audioOutputChanged) {\n return element.setSinkId(rtcUtils.getAudioOutputDevice()).catch(ex => {\n const err\n = new JitsiTrackError(ex, null, [ 'audiooutput' ]);\n\n logger.warn(\n 'Failed to set audio output device for the element.'\n + ' Default audio output device will be used'\n + ' instead',\n element?.id,\n err);\n\n throw err;\n });\n }\n\n return Promise.resolve();\n };\n}\n\nexport default rtcUtils;\n","import { getLogger } from '@jitsi/logger';\n\nimport * as JitsiTrackEvents from '../../JitsiTrackEvents';\nimport { MediaType } from '../../service/RTC/MediaType';\nimport browser from '../browser';\nimport EventEmitter from '../util/EventEmitter';\n\nimport RTCUtils from './RTCUtils';\n\nconst logger = getLogger(__filename);\n\n/**\n * Maps our handler types to MediaStreamTrack properties.\n */\nconst trackHandler2Prop = {\n 'track_mute': 'onmute', // Not supported on FF\n 'track_unmute': 'onunmute',\n 'track_ended': 'onended'\n};\n\n/**\n * Represents a single media track (either audio or video).\n */\nexport default class JitsiTrack extends EventEmitter {\n /* eslint-disable max-params */\n /**\n * Represents a single media track (either audio or video).\n * @constructor\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 stream.\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,\n stream,\n track,\n streamInactiveHandler,\n trackMediaType,\n videoType) {\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 * MediaStream 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 _addMediaStreamInactiveHandler(handler) {\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 * @private\n */\n _attachTTFMTracker(container) { // eslint-disable-line no-unused-vars\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 * @private\n */\n _onTrackAttach(container) { // eslint-disable-line no-unused-vars\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 * @private\n */\n _onTrackDetach(container) { // eslint-disable-line no-unused-vars\n // Should be defined by the classes that are extending JitsiTrack\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 */\n _setHandler(type, handler) {\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 * Sets the stream property of JitsiTrack object and sets all stored\n * handlers to it.\n *\n * @param {MediaStream} stream the new stream.\n * @protected\n */\n _setStream(stream) {\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 * @private\n */\n _unregisterHandlers() {\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 * 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 attach(container) {\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 * null or undefined, 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 detach(container) {\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 dispose() {\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 getId() {\n return this.getStreamId();\n }\n\n /**\n * Returns the WebRTC MediaStream instance.\n */\n getOriginalStream() {\n return this.stream;\n }\n\n /**\n * Returns the source name of the track.\n * @returns {String|undefined}\n */\n getSourceName() { // eslint-disable-line no-unused-vars\n // Should be defined by the classes that are extending JitsiTrack\n }\n\n /**\n * Returns the primary SSRC associated with the track.\n * @returns {number}\n */\n getSsrc() { // eslint-disable-line no-unused-vars\n // Should be defined by the classes that are extending JitsiTrack\n }\n\n /**\n * Returns the ID of the underlying WebRTC Media Stream(if any)\n * @returns {String|null}\n */\n getStreamId() {\n return this.stream ? this.stream.id : null;\n }\n\n /**\n * Return the underlying WebRTC MediaStreamTrack\n * @returns {MediaStreamTrack}\n */\n getTrack() {\n return this.track;\n }\n\n /**\n * Return the underlying WebRTC MediaStreamTrack label\n * @returns {string}\n */\n getTrackLabel() {\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 getTrackId() {\n return this.track ? this.track.id : null;\n }\n\n /**\n * Returns the type (audio or video) of this track.\n */\n getType() {\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 getUsageLabel() {\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 getVideoType() {\n return this.videoType;\n }\n\n /**\n * Returns the height of the track in normalized landscape format.\n */\n getHeight() {\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 getWidth() {\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 isActive() {\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 isAudioTrack() {\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 isLocal() {\n throw new Error('Not implemented by subclass');\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 isLocalAudioTrack() {\n return this.isAudioTrack() && this.isLocal();\n }\n\n /**\n * Check if this is a video track.\n */\n isVideoTrack() {\n return this.getType() === MediaType.VIDEO;\n }\n\n /**\n * Checks whether the underlying WebRTC MediaStreamTrack is muted\n * according to it's 'muted' field status.\n * @return {boolean} true if the underlying\n * MediaStreamTrack is muted or false otherwise.\n */\n isWebRTCTrackMuted() {\n return this.track && this.track.muted;\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 undefined for\n * a local track if the audio level was measured outside of the\n * peerconnection (see /modules/statistics/LocalStatsCollector.js).\n */\n setAudioLevel(audioLevel, tpc) {\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.\n * @param {string} audioOutputDeviceId - id of 'audiooutput' device from\n * navigator.mediaDevices.enumerateDevices(), '' for default device\n * @emits JitsiTrackEvents.TRACK_AUDIO_OUTPUT_CHANGED\n * @returns {Promise}\n */\n setAudioOutput(audioOutputDeviceId) {\n if (!RTCUtils.isDeviceChangeAvailable('output')) {\n return Promise.reject(\n new Error('Audio output device change is not supported'));\n }\n\n // All audio communication is done through audio tracks, so ignore\n // changing audio output for video tracks at all.\n if (this.isVideoTrack()) {\n return Promise.resolve();\n }\n\n return (\n Promise.all(\n this.containers.map(\n element =>\n element.setSinkId(audioOutputDeviceId)\n .catch(error => {\n logger.warn(\n 'Failed to change audio output device on'\n + ' element. Default or previously set'\n + ' audio output device will be used.',\n element,\n error);\n throw error;\n }))\n )\n .then(() => {\n this.emit(\n JitsiTrackEvents.TRACK_AUDIO_OUTPUT_CHANGED,\n audioOutputDeviceId);\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 setSourceName(name) { // eslint-disable-line no-unused-vars\n // Should be defined by the classes that are extending JitsiTrack\n }\n}\n","import { getLogger } from '@jitsi/logger';\n\nimport JitsiTrackError from '../../JitsiTrackError';\nimport {\n TRACK_IS_DISPOSED,\n TRACK_NO_STREAM_FOUND\n} from '../../JitsiTrackErrors';\nimport {\n LOCAL_TRACK_STOPPED,\n NO_DATA_FROM_SOURCE,\n TRACK_MUTE_CHANGED\n} 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 NO_BYTES_SENT,\n TRACK_UNMUTED,\n createNoDataFromSourceEvent\n} from '../../service/statistics/AnalyticsEvents';\nimport browser from '../browser';\nimport Statistics from '../statistics/statistics';\n\nimport JitsiTrack from './JitsiTrack';\nimport RTCUtils from './RTCUtils';\n\nconst logger = getLogger(__filename);\n\n/**\n * Represents a single media track(either audio or video).\n * One JitsiLocalTrack corresponds to one WebRTC MediaStreamTrack.\n */\nexport default class JitsiLocalTrack extends JitsiTrack {\n /**\n * Constructs a new JitsiLocalTrack instance.\n *\n * @constructor\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} 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 constructor({\n constraints,\n deviceId,\n facingMode,\n mediaType,\n rtcId,\n sourceId,\n sourceType,\n stream,\n track,\n videoType,\n effects = []\n }) {\n super(\n /* conference */ null,\n stream,\n track,\n /* streamInactiveHandler */ () => this.emit(LOCAL_TRACK_STOPPED, this),\n mediaType,\n videoType);\n\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\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 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 (isNaN(this._constraints.height.ideal) && isNaN(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 (isNaN(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 Promise 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 => {\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\n /**\n * Adds stream to conference and marks it as \"unmute\" operation.\n *\n * @private\n * @returns {Promise}\n */\n _addStreamToConferenceAsUnmute() {\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 => 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 _fireNoDataFromSourceEvent() {\n const value = !this.isReceivingData();\n\n this.emit(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 _initNoDataFromSourceHandlers() {\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 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 _isNoDataFromSourceEventsEnabled() {\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 _setMuted with.\n * @private\n * @returns {Promise}\n */\n _queueSetMuted(muted) {\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 _removeStreamFromConferenceAsMute(successCallback, errorCallback) {\n if (!this.conference) {\n successCallback();\n\n return;\n }\n this.conference._removeLocalTrackFromPc(this).then(\n successCallback,\n error => errorCallback(new Error(error)));\n }\n\n /**\n * Sends mute status for a track to conference if any.\n *\n * @param {boolean} mute - If track is muted.\n * @private\n * @returns {void}\n */\n _sendMuteStatus(mute) {\n if (this.conference) {\n this.conference._setTrackMuteStatus(this.getType(), this, mute) && this.conference.room.sendPresence();\n }\n }\n\n /**\n * Mutes / unmutes this track.\n *\n * @param {boolean} muted - If true, this track will be muted; otherwise, this track will be unmuted.\n * @private\n * @returns {Promise}\n */\n _setMuted(muted) {\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.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 && 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 // This path is only for camera.\n const streamOptions = {\n cameraDeviceId: this.getDeviceId(),\n devices: [ MediaType.VIDEO ],\n effects: this._streamEffect ? [ this._streamEffect ] : [],\n facingMode: this.getCameraFacingMode()\n };\n\n promise\n = RTCUtils.obtainAudioAndVideoPermissions(Object.assign(\n {},\n streamOptions,\n { constraints: { video: this._constraints } }));\n\n promise = promise.then(streamsInfo => {\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\n // Send the videoType message to the bridge.\n this.isVideoTrack() && this.conference && this.conference._sendBridgeVideoTypeMessage(this);\n this.emit(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 _setRealDeviceIdFromDeviceList(devices) {\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 * Sets the stream property of JitsiLocalTrack object and sets all stored handlers to it.\n *\n * @param {MediaStream} stream - The new MediaStream.\n * @private\n * @returns {void}\n */\n _setStream(stream) {\n super._setStream(stream);\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 _startStreamEffect(effect) {\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 }\n\n /**\n * Stops the effect process and returns the original stream.\n *\n * @private\n * @returns {void}\n */\n _stopStreamEffect() {\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 }\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 _switchCamera() {\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 _switchStreamEffect(effect) {\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 * @extends JitsiTrack#dispose\n * @returns {Promise}\n */\n async dispose() {\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();\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 * 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 {CameraFacingMode|undefined}\n */\n getCameraFacingMode() {\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;\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() {\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() {\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() {\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() {\n return this.conference && this.conference.myUserId();\n }\n\n /**\n * Returns the source name associated with the jitsi track.\n *\n * @returns {string | null} source name\n */\n getSourceName() {\n return this._sourceName;\n }\n\n /**\n * Returns the primary SSRC associated with the track.\n * @returns {number}\n */\n getSsrc() {\n return this._ssrc;\n }\n\n /**\n * Returns if associated MediaStreamTrack is in the 'ended' state\n *\n * @returns {boolean}\n */\n isEnded() {\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 true.\n *\n * @returns {boolean} true\n */\n isLocal() {\n return true;\n }\n\n /**\n * Returns true - if the stream is muted and false otherwise.\n *\n * @returns {boolean} true - if the stream is muted and false otherwise.\n */\n isMuted() {\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 && this._streamEffect.isMuted) {\n return this._streamEffect.isMuted();\n }\n\n return !this.track || !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() {\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() {\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, bytesSent) {\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(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) {\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) {\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 => {\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 */\n setSourceName(name) {\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) {\n if (!isNaN(ssrc)) {\n this._ssrc = ssrc;\n }\n }\n\n /**\n * Stops the associated MediaStream.\n *\n * @returns {void}\n */\n stopStream() {\n /**\n * Indicates that we are executing {@link #stopStream} i.e.\n * {@link RTCUtils#stopMediaStream} for the MediaStream\n * associated with this JitsiTrack 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 toString() {\n return `LocalTrack[${this.rtcId},${this.getType()}]`;\n }\n\n /**\n * Asynchronously unmutes this track.\n *\n * @returns {Promise}\n */\n unmute() {\n return this._queueSetMuted(false);\n }\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 */\n\nimport transform from 'sdp-transform';\n\n/**\n * Rewrites the source information in the way sdp-transform expects.\n * Source information is split into multiple ssrc objects each containing\n * an id, attribute and value.\n * @param {Object} media - media description to be modified.\n * @returns {void}\n */\nconst write = function(session, opts) {\n if (typeof session !== 'undefined' && typeof session.media !== 'undefined' && Array.isArray(session.media)) {\n session.media.forEach(mLine => {\n if (mLine.sources && mLine.sources.length) {\n mLine.ssrcs = [];\n mLine.sources.forEach(source => {\n Object.keys(source).forEach(attribute => {\n if (attribute === 'id') {\n return;\n }\n mLine.ssrcs.push({\n id: source.id,\n attribute,\n value: source[attribute]\n });\n });\n });\n delete mLine.sources;\n }\n\n // join ssrcs in ssrc groups\n if (mLine.ssrcGroups && mLine.ssrcGroups.length) {\n mLine.ssrcGroups.forEach(ssrcGroup => {\n if (typeof ssrcGroup.ssrcs !== 'undefined'\n && Array.isArray(ssrcGroup.ssrcs)) {\n ssrcGroup.ssrcs = ssrcGroup.ssrcs.join(' ');\n }\n });\n }\n });\n }\n\n return transform.write(session, opts);\n};\n\n/**\n * Rewrites the source information that we get from sdp-transform.\n * All the ssrc lines with different attributes that belong to the\n * same ssrc are grouped into a single soure object with multiple key value pairs.\n * @param {Object} media - media description to be modified.\n * @returns {void}\n */\nconst parse = function(sdp) {\n const session = transform.parse(sdp);\n\n if (typeof session !== 'undefined' && typeof session.media !== 'undefined' && Array.isArray(session.media)) {\n session.media.forEach(mLine => {\n // group sources attributes by ssrc\n if (typeof mLine.ssrcs !== 'undefined' && Array.isArray(mLine.ssrcs)) {\n mLine.sources = [];\n mLine.ssrcs.forEach(ssrc => {\n const found = mLine.sources.findIndex(source => source.id === ssrc.id);\n\n if (found > -1) {\n mLine.sources[found][ssrc.attribute] = ssrc.value;\n } else {\n const src = { id: ssrc.id };\n\n src[ssrc.attribute] = ssrc.value;\n mLine.sources.push(src);\n }\n });\n delete mLine.ssrcs;\n }\n\n // split ssrcs in ssrc groups\n if (typeof mLine.ssrcGroups !== 'undefined' && Array.isArray(mLine.ssrcGroups)) {\n mLine.ssrcGroups.forEach(ssrcGroup => {\n if (typeof ssrcGroup.ssrcs === 'string') {\n ssrcGroup.ssrcs = ssrcGroup.ssrcs.split(' ');\n }\n });\n }\n });\n }\n\n return session;\n};\n\nexport default {\n write,\n parse\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 */\n\nimport clonedeep from 'lodash.clonedeep';\n\nimport transform from './transform.js';\n\nconst PLAN_B_MIDS = [ 'audio', 'video', 'data' ];\nconst findSimGroup = ssrcGroup => ssrcGroup.find(grp => grp.semantics === 'SIM');\nconst findFidGroup = ssrcGroup => ssrcGroup.find(grp => grp.semantics === 'FID');\n\n/**\n * Add the ssrcs of the SIM group and their corresponding FID group ssrcs\n * to the m-line.\n * @param {Object} mLine - The m-line to which ssrcs have to be added.\n * @param {Object} simGroup - The SIM group whose ssrcs have to be added to\n * the m-line.\n * @param {Object} sourceGroups - inverted source-group map.\n * @param {Array} sourceList - array containing all the sources.\n */\nfunction addSimGroupSources(mLine, simGroup, sourceGroups, sourceList) {\n if (!mLine || !simGroup) {\n return;\n }\n const findSourcebyId = src => sourceList.find(source => source.id.toString() === src);\n\n simGroup.ssrcs.forEach(src => {\n mLine.sources.push(findSourcebyId(src));\n\n // find the related FID group member for this ssrc.\n const relatedFidGroup = sourceGroups[parseInt(src, 10)].find(grp => grp.semantics === 'FID');\n\n if (relatedFidGroup) {\n const relatedSsrc = relatedFidGroup.ssrcs.find(s => s !== src);\n\n mLine.sources.push(findSourcebyId(relatedSsrc));\n mLine.ssrcGroups.push(relatedFidGroup);\n }\n });\n\n // Add the SIM group last.\n mLine.ssrcGroups.push(simGroup);\n}\n\n/**\n * Add ssrcs and ssrc-groups to the m-line. When a primary ssrc, i.e., the\n * first ssrc in a SIM group is passed, all the other ssrcs from the SIM\n * group and the other ssrcs from the related FID groups are added to the same\n * m-line since they all belong to the same remote source. Since the ssrcs are\n * not guaranteed to be in the correct order, try to find if a SIM group exists,\n * if not, just add the FID group.\n * @param {Object} mLine - The m-line to which ssrcs have to be added.\n * @param {Object} ssrc - the primary ssrc.\n * @param {Object} sourceGroups - inverted source-group map.\n * @param {Array} sourceList - array containing all the sources.\n * @returns {void}\n */\nfunction addSourcesToMline(mLine, ssrc, sourceGroups, sourceList) {\n if (!mLine || !ssrc) {\n return;\n }\n mLine.sources = [];\n mLine.ssrcGroups = [];\n\n // If there are no associated ssrc-groups, just add the ssrc and msid.\n if (!sourceGroups[ssrc.id]) {\n mLine.sources.push(ssrc);\n mLine.msid = ssrc.msid;\n\n return;\n }\n const findSourcebyId = src => sourceList.find(source => source.id.toString() === src);\n\n // Find the SIM and FID groups that this ssrc belongs to.\n const simGroup = findSimGroup(sourceGroups[ssrc.id]);\n const fidGroup = findFidGroup(sourceGroups[ssrc.id]);\n\n // Add the ssrcs for the SIM group and their corresponding FID groups.\n if (simGroup) {\n addSimGroupSources(mLine, simGroup, sourceGroups, sourceList);\n } else if (fidGroup) {\n // check if the other ssrc from this FID group is part of a SIM group\n const otherSsrc = fidGroup.ssrcs.find(s => s !== ssrc);\n const simGroup2 = findSimGroup(sourceGroups[otherSsrc]);\n\n if (simGroup2) {\n addSimGroupSources(mLine, simGroup2, sourceGroups, sourceList);\n } else {\n // Add the FID group ssrcs.\n fidGroup.ssrcs.forEach(src => {\n mLine.sources.push(findSourcebyId(src));\n });\n mLine.ssrcGroups.push(fidGroup);\n }\n }\n\n // Set the msid for the media description using the msid attribute of the ssrcs.\n mLine.msid = mLine.sources[0].msid;\n}\n\n/**\n * Checks if there is a mline for the given ssrc or its related primary ssrc.\n * We always implode the SIM group to the first ssrc in the SIM group before sRD,\n * so we also check if mline for that ssrc exists.\n * For example:\n * If the following ssrcs are in a SIM group,\n * \n * \n * \n * \n * \n * This method returns true for any one of the 3 ssrcs if there is a mline for 1806330949.\n * @param {Object} ssrc - ssrc to check.\n * @param {Object} sourceGroups - inverted source-group map.\n * @param {Array} mlines - mlines in the description\n\n * @returns {Boolean} - Returns true if mline for the given ssrc or the related primary ssrc\n * exists, returns false otherwise.\n */\nfunction checkIfMlineForSsrcExists(ssrc, sourceGroups, mlines) {\n const findMatchingMline = mline => {\n if (mline.sources) {\n return mline.sources.some(source => source.id === ssrc.id);\n }\n\n return false;\n };\n\n if (!mlines.find(findMatchingMline)) {\n // check if this ssrc is member of a SIM group. If so, check if there\n // is a matching m-line for the primary ssrc of the SIM group.\n if (!sourceGroups[ssrc.id]) {\n return false;\n }\n const simGroup = findSimGroup(sourceGroups[ssrc.id]);\n const fidGroup = findFidGroup(sourceGroups[ssrc.id]);\n\n if (simGroup) {\n return mlines.some(mline => mline.sources\n && mline.sources.some(src => src.id.toString() === simGroup.ssrcs[0]));\n } else if (fidGroup && ssrc.id.toString() !== fidGroup.ssrcs[0]) {\n const otherSsrc = { id: fidGroup.ssrcs[0] };\n\n return checkIfMlineForSsrcExists(otherSsrc, sourceGroups, mlines);\n\n }\n\n return false;\n }\n\n return true;\n}\n\n/**\n * Create an inverted sourceGroup map to put all the grouped ssrcs\n * in the same m-line.\n * @param {Array} sourceGroups\n * @returns {Object} - An inverted sourceGroup map.\n */\nfunction createSourceGroupMap(sourceGroups) {\n const ssrc2group = {};\n\n if (!sourceGroups || !Array.isArray(sourceGroups)) {\n return ssrc2group;\n }\n sourceGroups.forEach(group => {\n if (group.ssrcs && Array.isArray(group.ssrcs)) {\n group.ssrcs.forEach(ssrc => {\n if (typeof ssrc2group[ssrc] === 'undefined') {\n ssrc2group[ssrc] = [];\n }\n ssrc2group[ssrc].push(group);\n });\n }\n });\n\n return ssrc2group;\n}\n\n/**\n * Check if a new SDP requests an ICE restart.\n * @param {Object} - the parsed new SDP\n * @param {Object} - the parsed previous SDP\n * @returns {Boolean} - Returns true if an ICE restart is requested otherwise false.\n */\nfunction checkForIceRestart(newDesc, oldDesc) {\n if (!newDesc || !oldDesc || newDesc.media.length === 0 || oldDesc.media.length === 0) {\n return false;\n }\n\n const newMLine = newDesc.media[0];\n const oldMLine = oldDesc.media[0];\n\n return newMLine.iceUfrag !== oldMLine.iceUfrag || newMLine.icePwd !== oldMLine.icePwd;\n}\n\n/**\n * Interop provides an API for tranforming a Plan B SDP to a Unified Plan SDP and\n * vice versa.\n */\nexport class Interop {\n /**\n * This method transforms a Unified Plan SDP to an equivalent Plan B SDP.\n * @param {RTCSessionDescription} description - The description in Unified plan format.\n * @returns RTCSessionDescription - The transformed session description.\n */\n toPlanB(description) {\n if (!description || typeof description.sdp !== 'string') {\n console.warn('An empty description was passed as an argument.');\n\n return description;\n }\n\n // Objectify the SDP for easier manipulation.\n const session = transform.parse(description.sdp);\n\n // If the SDP contains no media, there's nothing to transform.\n if (!session.media || !session.media.length) {\n console.warn('The description has no media.');\n\n return description;\n }\n\n // Make sure this is a unified plan sdp\n if (session.media.every(m => PLAN_B_MIDS.indexOf(m.mid) !== -1)) {\n console.warn('The description does not look like unified plan sdp');\n\n return description;\n }\n\n const media = {};\n const sessionMedia = session.media;\n\n session.media = [];\n sessionMedia.forEach(mLine => {\n const type = mLine.type;\n\n if (type === 'application') {\n mLine.mid = 'data';\n media[mLine.mid] = mLine;\n\n return;\n }\n if (typeof media[type] === 'undefined') {\n const bLine = clonedeep(mLine);\n\n // Copy the msid attribute to all the ssrcs if they belong to the same source group\n if (bLine.sources && Array.isArray(bLine.sources)) {\n bLine.sources.forEach(source => {\n mLine.msid ? source.msid = mLine.msid : delete source.msid;\n });\n }\n\n // Do not signal the FID groups if there is no msid attribute present\n // on the sources as sesison-accept with this source info will fail strophe\n // validation and the session will not be established. This behavior is seen\n // on Firefox (with RTX enabled) when no video source is added at the join time.\n // FF generates two recvonly ssrcs with no msid and a corresponding FID group in\n // this case.\n if (!bLine.ssrcGroups || !mLine.msid) {\n bLine.ssrcGroups = [];\n }\n delete bLine.msid;\n bLine.mid = type;\n media[type] = bLine;\n } else if (mLine.msid) {\n // Add sources and source-groups to the existing m-line of the same media type.\n const bLine = clonedeep(mLine);\n\n if (bLine.sources && Array.isArray(bLine.sources)) {\n // Copy the msid attribute to each ssrc.\n bLine.sources.forEach(ssrc => {\n ssrc.msid = mLine.msid;\n });\n media[type].sources = (media[type].sources || []).concat(bLine.sources);\n }\n if (typeof bLine.ssrcGroups !== 'undefined' && Array.isArray(bLine.ssrcGroups)) {\n media[type].ssrcGroups = (media[type].ssrcGroups || []).concat(bLine.ssrcGroups);\n }\n }\n });\n session.media = Object.values(media);\n\n // Bundle the media only if it is active.\n const bundle = [];\n\n Object.values(media).forEach(mline => {\n if (mline.direction !== 'inactive') {\n bundle.push(mline.mid);\n }\n });\n\n // We regenerate the BUNDLE group with the new mids.\n session.groups.forEach(group => {\n if (group.type === 'BUNDLE') {\n group.mids = bundle.join(' ');\n }\n });\n\n // msid semantic\n session.msidSemantic = {\n semantic: 'WMS',\n token: '*'\n };\n const resStr = transform.write(session);\n\n return new RTCSessionDescription({\n type: description.type,\n sdp: resStr\n });\n }\n\n /**\n * This method transforms a Plan B SDP to an equivalent Unified Plan SDP.\n * @param {RTCSessionDescription} description - The description in plan-b format.\n * @param {RTCSessionDescription} current - The current description set on\n * the peerconnection in Unified-plan format, i.e., the readonly attribute\n * remoteDescription on the RTCPeerConnection object.\n * @returns RTCSessionDescription - The transformed session description.\n */\n toUnifiedPlan(description, current = null) {\n if (!description || typeof description.sdp !== 'string') {\n console.warn('An empty description was passed as an argument.');\n\n return description;\n }\n\n // Objectify the SDP for easier manipulation.\n const session = transform.parse(description.sdp);\n\n // If the SDP contains no media, there's nothing to transform.\n if (!session.media || !session.media.length) {\n console.warn('The description has no media.');\n\n return description;\n }\n\n // Make sure this is a plan-b sdp.\n if (session.media.length > 3 || session.media.every(m => PLAN_B_MIDS.indexOf(m.mid) === -1)) {\n console.warn('The description does not look like plan-b');\n\n return description;\n }\n const currentDesc = current ? transform.parse(current.sdp) : null;\n const iceRestart = checkForIceRestart(session, currentDesc);\n const newIceUfrag = session.media[0].iceUfrag;\n const newIcePwd = session.media[0].icePwd;\n const newFingerprint = session.media[0].fingerprint;\n const media = {};\n\n session.media.forEach(mLine => {\n const type = mLine.type;\n\n if (type === 'application') {\n if (!currentDesc || !currentDesc.media) {\n const newMline = clonedeep(mLine);\n\n newMline.mid = Object.keys(media).length.toString();\n media[mLine.mid] = newMline;\n\n return;\n }\n const mLineForData = currentDesc.media.findIndex(m => m.type === type);\n\n if (mLineForData) {\n currentDesc.media[mLineForData] = mLine;\n currentDesc.media[mLineForData].mid = mLineForData;\n }\n\n return;\n }\n\n // Create an inverted sourceGroup map here to put all the grouped SSRCs in the same m-line.\n const ssrc2group = createSourceGroupMap(mLine.ssrcGroups);\n\n // If there are no sources advertised for a media type, add the description if this is the first\n // remote offer, i.e., no current description was passed. Chrome in Unified plan does not produce\n // recvonly ssrcs unlike Firefox and Safari.\n if (!mLine.sources) {\n if (!currentDesc) {\n const newMline = clonedeep(mLine);\n\n newMline.mid = Object.keys(media).length.toString();\n media[mLine.mid] = newMline;\n }\n\n return;\n }\n mLine.sources.forEach((ssrc, idx) => {\n // Do not add the receive-only ssrcs that Jicofo sends in the source-add.\n // These ssrcs do not have the \"msid\" attribute set.\n if (!ssrc.msid) {\n return;\n }\n\n // If there is no description set on the peerconnection, create new m-lines.\n if (!currentDesc || !currentDesc.media) {\n if (checkIfMlineForSsrcExists(ssrc, ssrc2group, Object.values(media))) {\n return;\n }\n const newMline = clonedeep(mLine);\n\n newMline.mid = Object.keys(media).length.toString();\n newMline.direction = idx\n ? 'sendonly'\n : mLine.direction === 'sendonly' ? 'sendonly' : 'sendrecv';\n newMline.bundleOnly = undefined;\n addSourcesToMline(newMline, ssrc, ssrc2group, mLine.sources);\n media[newMline.mid] = newMline;\n\n return;\n }\n\n // Create and append the m-lines to the existing description.\n if (checkIfMlineForSsrcExists(ssrc, ssrc2group, currentDesc.media)) {\n return;\n }\n const newMline = clonedeep(mLine);\n\n newMline.mid = currentDesc.media.length.toString();\n newMline.direction = 'sendonly';\n addSourcesToMline(newMline, ssrc, ssrc2group, mLine.sources);\n currentDesc.media.push(newMline);\n });\n });\n session.media = currentDesc ? currentDesc.media : Object.values(media);\n const mids = [];\n\n session.media.forEach(mLine => {\n mids.push(mLine.mid);\n if (iceRestart) {\n mLine.iceUfrag = newIceUfrag;\n mLine.icePwd = newIcePwd;\n mLine.fingerprint = newFingerprint;\n }\n });\n\n // We regenerate the BUNDLE group (since we regenerated the mids)\n session.groups.forEach(group => {\n if (group.type === 'BUNDLE') {\n group.mids = mids.join(' ');\n }\n });\n\n // msid semantic\n session.msidSemantic = {\n semantic: 'WMS',\n token: '*'\n };\n\n // Increment the session version every time.\n session.origin.sessionVersion++;\n const resultSdp = transform.write(session);\n\n return new RTCSessionDescription({\n type: description.type,\n sdp: resultSdp\n });\n }\n}\n","export enum SignalingEvents {\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\n// exported for backward compatibility\nexport const PEER_MUTED_CHANGED = SignalingEvents.PEER_MUTED_CHANGED;\nexport const PEER_VIDEO_TYPE_CHANGED = SignalingEvents.PEER_VIDEO_TYPE_CHANGED;\nexport const SOURCE_MUTED_CHANGED = SignalingEvents.SOURCE_MUTED_CHANGED;\nexport const SOURCE_UPDATED = SignalingEvents.SOURCE_UPDATED;\nexport const SOURCE_VIDEO_TYPE_CHANGED = SignalingEvents.SOURCE_VIDEO_TYPE_CHANGED;\n","\nimport Listenable from '../../modules/util/Listenable';\nimport { MediaType } from '../../service/RTC/MediaType';\n\n/**\n * @typedef {string} EndpointId\n */\n/**\n * @typedef {string} SourceName\n */\n/**\n * @typedef {Object} SourceInfo\n *\n * @property {SourceName} sourceName - Name of the media source.\n * @property {boolean} [muted=false] - Tells if the source is muted (paused?).\n * @property {string} [videoType] - Type of the video for video type.\n */\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, mediaType, trackIdx) {\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) {\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 for (const type of Object.values(MediaType)) {\n if (type.substr(0, 1) === firstLetterOfMediaType) {\n return type;\n }\n }\n\n throw new Error(`Invalid source name: ${sourceName}`);\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) {\n const nameParts = sourceName.split('-');\n const trackIdx = Number(nameParts[nameParts.length - 1].substring(1));\n\n if (Number.isNaN(trackIdx)) {\n throw new Error(`Failed to parse track idx for source name: ${sourceName}`);\n }\n\n return trackIdx;\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} PeerMediaInfo\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 {PeerMediaInfo|null} presenceInfo an object with media presence\n * info or null 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(owner, mediaType, sourceName) { // eslint-disable-line no-unused-vars\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 {SourceInfo | undefined}\n */\n getPeerSourceInfo(owner, sourceName) { // eslint-disable-line no-unused-vars\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 {string|null} the endpoint ID for given media SSRC.\n */\n getSSRCOwner(ssrc) { // eslint-disable-line no-unused-vars\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 {SourceName | undefined} the track's source name.\n */\n getTrackSourceName(ssrc) { // eslint-disable-line no-unused-vars\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) { // eslint-disable-line no-unused-vars\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 {string} sourceName - The related source name.\n * @throws TypeError if ssrc is not a number.\n */\n setSSRCOwner(ssrc, endpointId, sourceName) { // eslint-disable-line no-unused-vars\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, muted) { // eslint-disable-line no-unused-vars\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, videoType) { // eslint-disable-line no-unused-vars\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) { // eslint-disable-line no-unused-vars\n }\n}\n","import browser from '../../modules/browser';\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 * Standard scalability mode settings for different video codecs and the default bitrates.\n */\nexport const STANDARD_CODEC_SETTINGS = {\n av1: {\n maxBitratesVideo: {\n low: 100000,\n standard: 300000,\n high: 1000000,\n fullHd: 2000000,\n ultraHd: 4000000,\n ssHigh: 2500000,\n none: 0\n },\n scalabilityModeEnabled: browser.supportsScalabilityModeAPI(),\n useSimulcast: false, // defaults to SVC.\n useKSVC: true // defaults to L3T3_KEY for SVC mode.\n },\n h264: {\n maxBitratesVideo: {\n low: 400000,\n standard: 800000,\n high: 2000000,\n fullHd: 4000000,\n ultraHd: 8000000,\n ssHigh: 2500000,\n none: 0\n },\n scalabilityModeEnabled: browser.supportsScalabilityModeAPI()\n },\n vp8: {\n maxBitratesVideo: {\n low: 200000,\n standard: 500000,\n high: 1500000,\n fullHd: 3000000,\n ultraHd: 6000000,\n ssHigh: 2500000,\n none: 0\n },\n scalabilityModeEnabled: false\n },\n vp9: {\n maxBitratesVideo: {\n low: 100000,\n standard: 300000,\n high: 1200000,\n fullHd: 2500000,\n ultraHd: 5000000,\n ssHigh: 2500000,\n none: 0\n },\n scalabilityModeEnabled: browser.supportsScalabilityModeAPI(),\n useSimulcast: false, // defaults to SVC.\n useKSVC: true // defaults to L3T3_KEY for SVC mode.\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 // 3840x2160 or 4k.\n ULTRA = 'ultraHd',\n\n // 1920x1080 or full High Definition.\n FULL = 'fullHd',\n\n // 1280x720 or High Definition.\n HIGH = 'high',\n\n // 640x360 or Standard Definition.\n STANDARD = 'standard',\n\n // 320x180 or Low Definition.\n LOW = 'low',\n\n // When the camera is turned off.\n NONE = 'none'\n}\n","import * as transform from 'sdp-transform';\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) {\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) {\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} mLine the media line object as defined by 'sdp-transform' lib\n * @return {number}\n */\nfunction _getSSRCCount(mLine) {\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 */\nclass MLineWrap {\n\n /**\n * Creates new MLineWrap>\n * @param {Object} mLine the media line object as defined by 'sdp-transform'\n * lib.\n */\n constructor(mLine) {\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} an array of 'sdp-transform' SSRC attributes\n * objects.\n */\n get 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} ssrcs an array of 'sdp-transform' SSRC attributes\n * objects.\n */\n set ssrcs(ssrcs) {\n this.mLine.ssrcs = ssrcs;\n }\n\n /**\n * Returns the direction of the underlying media description.\n * @return {string} the media direction name as defined in the SDP.\n */\n get direction() {\n return this.mLine.direction;\n }\n\n /**\n * Modifies the direction of the underlying media description.\n * @param {string} direction the new direction to be set\n */\n set direction(direction) {\n this.mLine.direction = direction;\n }\n\n /**\n * Exposes the SSRC group array of the underlying media description object.\n * @return {Array.}\n */\n get 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 {Array.} ssrcGroups\n */\n set ssrcGroups(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 {string|undefined} the value of SSRC attribute or\n * undefined if no such attribute exists.\n */\n getSSRCAttrValue(ssrcNumber, attrName) {\n const attribute = this.ssrcs.find(\n ssrcObj => ssrcObj.id === ssrcNumber\n && ssrcObj.attribute === attrName);\n\n\n return attribute && 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) {\n if (!this.mLine.ssrcs || !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) {\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 {object|undefined} the SSRC group object or undefined if\n * not found.\n */\n findGroup(semantics, ssrcs) {\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 {Array.} an array of SSRC group objects as defined by\n * the 'sdp-transform' lib.\n */\n findGroups(semantics) {\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 {Object} SSRC group object as defined by the 'sdp-transform' lib.\n */\n findGroupByPrimarySSRC(semantics, primarySSRC) {\n return this.ssrcGroups.find(\n group => group.semantics === semantics\n && parsePrimarySSRC(group) === primarySSRC);\n }\n\n /**\n * @param {string|null} msid the media stream id or null to match\n * the first SSRC object with any 'msid' value.\n * @return {Object|undefined} the SSRC object as defined by 'sdp-transform'\n * lib.\n */\n findSSRCByMSID(msid) {\n return this.ssrcs.find(\n ssrcObj => ssrcObj.attribute === 'msid'\n && (msid === null || ssrcObj.value === msid));\n }\n\n /**\n * Gets the SSRC count for the underlying media description.\n * @return {number}\n */\n getSSRCCount() {\n return _getSSRCCount(this.mLine);\n }\n\n /**\n * Checks whether the underlying media description contains any SSRC groups.\n * @return {boolean} true if there are any SSRC groups or\n * false otherwise.\n */\n containsAnySSRCGroups() {\n return this.mLine.ssrcGroups !== undefined;\n }\n\n /**\n * Finds the primary video SSRC.\n * @returns {number|undefined} the primary video ssrc\n * @throws Error if the underlying media description is not a video\n */\n getPrimaryVideoSsrc() {\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('SIM');\n\n if (simGroup) {\n return parsePrimarySSRC(simGroup);\n }\n const fidGroup = this.findGroup('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 /**\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 {number|undefined} the rtx ssrc (or undefined if there isn't\n * one)\n */\n getRtxSSRC(primarySsrc) {\n const fidGroup = this.findGroupByPrimarySSRC('FID', primarySsrc);\n\n\n return fidGroup && parseSecondarySSRC(fidGroup);\n }\n\n /**\n * Obtains all SSRCs contained in the underlying media description.\n * @return {Array.} an array with all SSRC as numbers.\n */\n getSSRCs() {\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.} an array of all primary video SSRCs as numbers.\n * @throws Error if the wrapped media description is not a video.\n */\n getPrimaryVideoSSRCs() {\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 === '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 * Dumps all SSRC groups of this media description to JSON.\n */\n dumpSSRCGroups() {\n return JSON.stringify(this.mLine.ssrcGroups);\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) {\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) {\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 * Replaces SSRC (does not affect SSRC groups, but only attributes).\n * @param {number} oldSSRC the old SSRC number\n * @param {number} newSSRC the new SSRC number\n */\n replaceSSRC(oldSSRC, newSSRC) {\n if (this.mLine.ssrcs) {\n this.mLine.ssrcs.forEach(ssrcInfo => {\n if (ssrcInfo.id === oldSSRC) {\n ssrcInfo.id = newSSRC;\n }\n });\n }\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) {\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\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) {\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 null if not found. The\n * object returned references the underlying SDP state held by this SdpTransformWrap instance (it's not a\n * copy).\n */\n selectMedia(mediaType) {\n const selectedMLines = this.parsedSDP.media\n .filter(mLine => mLine.type === mediaType)\n .map(mLine => new MLineWrap(mLine));\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() {\n return transform.write(this.parsedSDP);\n }\n}\n","import { getLogger } from '@jitsi/logger';\n\nimport { MediaDirection } from '../../service/RTC/MediaDirection';\nimport { MediaType } from '../../service/RTC/MediaType';\nimport { getSourceNameForJitsiTrack } from '../../service/RTC/SignalingLayer';\nimport browser from '../browser';\n\nimport { SdpTransformWrap } from './SdpTransformUtil';\n\nconst logger = getLogger(__filename);\n\n/**\n * Fakes local SDP exposed to {@link JingleSessionPC} through the local\n * description getter. Modifies the SDP, so that it will contain muted local\n * video tracks description, even though their underlying {MediaStreamTrack}s\n * are no longer in the WebRTC peerconnection. That prevents from SSRC updates\n * being sent to Jicofo/remote peer and prevents sRD/sLD cycle on the remote\n * side.\n */\nexport default class LocalSdpMunger {\n\n /**\n * Creates new LocalSdpMunger instance.\n *\n * @param {TraceablePeerConnection} tpc\n * @param {string} localEndpointId - The endpoint id of the local user.\n */\n constructor(tpc, localEndpointId) {\n this.tpc = tpc;\n this.localEndpointId = localEndpointId;\n this.audioSourcesToMsidMap = new Map();\n this.videoSourcesToMsidMap = new Map();\n }\n\n /**\n * Returns a string that can be set as the MSID attribute for a source.\n *\n * @param {string} mediaType - Media type of the source.\n * @param {string} trackId - Id of the MediaStreamTrack associated with the source.\n * @param {string} streamId - Id of the MediaStream associated with the source.\n * @returns {string|null}\n */\n _generateMsidAttribute(mediaType, trackId, streamId) {\n if (!(mediaType && trackId)) {\n logger.error(`Unable to munge local MSID - track id=${trackId} or media type=${mediaType} is missing`);\n\n return null;\n }\n const pcId = this.tpc.id;\n\n return `${streamId}-${pcId} ${trackId}-${pcId}`;\n }\n\n /**\n * Updates or adds a 'msid' attribute in the format '---'\n * example - d8ff91-video-0-1\n * All other attributes like 'cname', 'label' and 'mslabel' are removed since 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 _transformMediaIdentifiers(mediaSection) {\n const mediaType = mediaSection.mLine?.type;\n const mediaDirection = mediaSection.mLine?.direction;\n const msidLine = mediaSection.mLine?.msid;\n const sources = [ ...new Set(mediaSection.mLine?.ssrcs?.map(s => s.id)) ];\n const streamId = `${this.localEndpointId}-${mediaType}`;\n let trackId = msidLine ? msidLine.split(' ')[1] : `${this.localEndpointId}-${mediaSection.mLine.mid}`;\n\n // Always overwrite msid since we want the msid to be in this format even if the browser generates one.\n for (const source of sources) {\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 this._updateSourcesToMsidMap(mediaType, streamId, trackId);\n const storedStreamId = mediaType === MediaType.VIDEO\n ? this.videoSourcesToMsidMap.get(trackId)\n : this.audioSourcesToMsidMap.get(trackId);\n\n const generatedMsid = this._generateMsidAttribute(mediaType, trackId, storedStreamId);\n\n // Update the msid if the 'msid' attribute exists.\n if (msid) {\n msid.value = generatedMsid;\n\n // Generate the 'msid' attribute if there is a local source.\n } else if (mediaDirection === MediaDirection.SENDONLY || mediaDirection === MediaDirection.SENDRECV) {\n mediaSection.ssrcs.push({\n id: source,\n attribute: 'msid',\n value: generatedMsid\n });\n }\n }\n\n // Ignore the 'cname', 'label' and 'mslabel' attributes and only have the 'msid' attribute.\n mediaSection.ssrcs = mediaSection.ssrcs.filter(ssrc => ssrc.attribute === 'msid');\n\n // On FF when the user has started muted create answer will generate a recv only SSRC. We don't want to signal\n // this SSRC in order to reduce the load of the xmpp server for large calls. Therefore the SSRC needs to be\n // removed from the SDP.\n //\n // For all other use cases (when the user has had media but then the user has stopped it) we want to keep the\n // receive only SSRCs in the SDP. Otherwise source-remove will be triggered and the next time the user add a\n // track we will reuse the SSRCs and send source-add with the same SSRCs. This is problematic because of issues\n // on Chrome and FF (https://bugzilla.mozilla.org/show_bug.cgi?id=1768729) when removing and then adding the\n // same SSRC in the remote sdp the remote track is not rendered.\n if (browser.isFirefox()\n && (mediaDirection === MediaDirection.RECVONLY || mediaDirection === MediaDirection.INACTIVE)\n && (\n (mediaType === MediaType.VIDEO && !this.tpc._hasHadVideoTrack)\n || (mediaType === MediaType.AUDIO && !this.tpc._hasHadAudioTrack)\n )\n ) {\n mediaSection.ssrcs = undefined;\n mediaSection.ssrcGroups = undefined;\n }\n }\n\n /**\n * Updates the MSID map.\n *\n * @param {string} mediaType The media type.\n * @param {string} streamId The stream id.\n * @param {string} trackId The track id.\n * @returns {void}\n */\n _updateSourcesToMsidMap(mediaType, streamId, trackId) {\n if (mediaType === MediaType.VIDEO) {\n if (!this.videoSourcesToMsidMap.has(trackId)) {\n const generatedStreamId = `${streamId}-${this.videoSourcesToMsidMap.size}`;\n\n this.videoSourcesToMsidMap.set(trackId, generatedStreamId);\n }\n } else if (!this.audioSourcesToMsidMap.has(trackId)) {\n const generatedStreamId = `${streamId}-${this.audioSourcesToMsidMap.size}`;\n\n this.audioSourcesToMsidMap.set(trackId, generatedStreamId);\n }\n }\n\n /**\n * This transformation will make sure that stream identifiers are unique\n * across all of the local PeerConnections even if the same stream is used\n * by multiple instances at the same time.\n * Each PeerConnection assigns different SSRCs to the same local\n * MediaStream, but the MSID remains the same as it's used to identify\n * the stream by the WebRTC backend. The transformation will append\n * {@link TraceablePeerConnection#id} at the end of each stream's identifier\n * (\"cname\", \"msid\", \"label\" and \"mslabel\").\n *\n * @param {RTCSessionDescription} sessionDesc - The local session\n * description (this instance remains unchanged).\n * @return {RTCSessionDescription} - Transformed local session description\n * (a modified copy of the one given as the input).\n */\n transformStreamIdentifiers(sessionDesc) {\n if (!sessionDesc || !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);\n this._injectSourceNames(audioMLine);\n }\n\n const videoMlines = transformer.selectMedia(MediaType.VIDEO);\n\n for (const videoMLine of videoMlines) {\n this._transformMediaIdentifiers(videoMLine);\n this._injectSourceNames(videoMLine);\n }\n\n // Reset the local tracks based maps for msid after every transformation since Chrome 122 is generating\n // a new set of SSRCs for the same source when the direction of transceiver changes because of a remote\n // source getting added on the p2p connection.\n this.audioSourcesToMsidMap.clear();\n this.videoSourcesToMsidMap.clear();\n\n return new RTCSessionDescription({\n type: sessionDesc.type,\n sdp: transformer.toRawSDP()\n });\n }\n\n /**\n * Injects source names. Source names are need to for multiple streams per endpoint support. The final plan is to\n * use the \"mid\" attribute for source names, but because the SDP to Jingle conversion still operates in the Plan-B\n * semantics (one source name per media), a custom \"name\" attribute is injected into SSRC lines..\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 _injectSourceNames(mediaSection) {\n const sources = [ ...new Set(mediaSection.mLine?.ssrcs?.map(s => s.id)) ];\n const mediaType = mediaSection.mLine?.type;\n\n if (!mediaType) {\n throw new Error('_transformMediaIdentifiers - no media type in mediaSection');\n }\n\n for (const source of sources) {\n const nameExists = mediaSection.ssrcs.find(ssrc => ssrc.id === source && ssrc.attribute === 'name');\n const msid = mediaSection.ssrcs.find(ssrc => ssrc.id === source && ssrc.attribute === 'msid').value;\n const streamId = msid.split(' ')[0];\n\n // Example stream id: d8ff91-video-8-1\n // In the example above 8 is the track index\n const trackIndexParts = streamId.split('-');\n const trackIndex = trackIndexParts[trackIndexParts.length - 2];\n const sourceName = getSourceNameForJitsiTrack(this.localEndpointId, mediaType, trackIndex);\n\n if (!nameExists) {\n // Inject source names as a=ssrc:3124985624 name:endpointA-v0\n mediaSection.ssrcs.push({\n id: source,\n attribute: 'name',\n value: sourceName\n });\n }\n\n if (mediaType === MediaType.VIDEO) {\n const videoType = this.tpc.getLocalVideoTracks().find(track => track.getSourceName() === sourceName)\n ?.getVideoType();\n\n if (videoType) {\n // Inject videoType as a=ssrc:1234 videoType:desktop.\n mediaSection.ssrcs.push({\n id: source,\n attribute: 'videoType',\n value: videoType\n });\n }\n }\n }\n }\n}\n","import { getLogger } from '@jitsi/logger';\n\nimport { MediaDirection } from '../../service/RTC/MediaDirection';\nimport { MediaType } from '../../service/RTC/MediaType';\n\nimport SDPUtil from './SDPUtil';\nimport { SdpTransformWrap, parseSecondarySSRC } from './SdpTransformUtil';\n\nconst logger = getLogger(__filename);\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 id: rtxSsrc,\n attribute: 'cname',\n value: primarySsrcCname\n });\n primarySsrcMsid && mLine.addSSRCAttribute({\n id: rtxSsrc,\n attribute: 'msid',\n value: primarySsrcMsid\n });\n mLine.addSSRCGroup({\n 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} true if the SDP wrapped by {@link SdpTransformWrap} has been modified or\n * false 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 id: ssrc,\n cname,\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('FID');\n\n // Remove the fid groups from the mline\n videoMLine.removeGroupsBySemantics('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","import { MediaDirection } from '../../service/RTC/MediaDirection';\nimport { MediaType } from '../../service/RTC/MediaType';\nimport { SIM_LAYERS } from '../../service/RTC/StandardVideoQualitySettings';\n\nimport * as transform from 'sdp-transform';\n\ninterface Description {\n type: RTCSdpType;\n sdp: string;\n}\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>;\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 id: ssrc,\n attribute: 'msid',\n value: newMsid\n });\n mLine.ssrcs.push({\n id: ssrc,\n attribute: 'cname',\n value: newCname\n });\n }\n\n mLine.ssrcGroups.push({\n 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 const addAssociatedAttributes = (mLine: transform.MediaDescription, ssrc: number) => {\n mLine.ssrcs.push({\n id: ssrc,\n attribute: 'cname',\n value: cname\n });\n mLine.ssrcs.push({\n id: ssrc,\n attribute: 'msid',\n value: msid\n });\n }\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 id: ssrc.id,\n attribute: 'msid',\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 addAssociatedAttributes(mLine, simSsrc);\n simSsrcs.push(simSsrc);\n }\n\n mLine.ssrcGroups = mLine.ssrcGroups || [];\n mLine.ssrcGroups.push({\n 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) : string | undefined {\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) : Array | null {\n const simGroup = mLine.ssrcGroups?.find(group => 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: Description) : Description {\n if (!description || !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 === '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 type: description.type,\n sdp: transform.write(session)\n });\n }\n}\n","import { getLogger } from '@jitsi/logger';\n\nimport { JitsiConferenceEvents } from '../../JitsiConferenceEvents';\nimport * as JitsiTrackEvents from '../../JitsiTrackEvents';\nimport RTCEvents from '../../service/RTC/RTCEvents';\nimport { createTrackStreamingStatusEvent } from '../../service/statistics/AnalyticsEvents';\nimport browser from '../browser';\nimport Statistics from '../statistics/statistics';\nimport JitsiRemoteTrack from '../RTC/JitsiRemoteTrack';\nimport { VideoType } from '../../service/RTC/VideoType';\nimport RTC from '../RTC/RTC';\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 videoType?: VideoType,\n startedMs?: number,\n p2p?: boolean,\n streamingStatus?: string,\n value?: number\n};\n\nconst logger = getLogger(__filename);\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: any; // TODO: needs JitsiConference type\n track: JitsiRemoteTrack;\n\n /** This holds the timeout callback ID scheduled using window.setTimeout. */\n trackTimer: number | null;\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 Date.now().\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: number | null;\n\n /** This holds the restoring timeout callback ID scheduled using window.setTimeout. */\n restoringTimer: ReturnType | null;\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\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\n if (browser.supportsVideoMuteOnConnInterrupted()) {\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()) {\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 TrackStreamingStatus.\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: any, 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\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 TrackStreamingStatus 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\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 }\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 }\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 true if the video has frozen or false 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 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 * 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 streamingStatus: newState,\n p2p: inP2PMode,\n startedMs: nowMs\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 true 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 const sourceName = this.track.getSourceName();\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 videoType: type,\n startedMs: nowMs\n };\n }\n}\n\nexport default TrackStreamingStatusImpl;\n","import * as JitsiTrackEvents from '../../JitsiTrackEvents';\nimport { VideoType } from '../../service/RTC/VideoType';\nimport { createTtfmEvent } from '../../service/statistics/AnalyticsEvents';\nimport TrackStreamingStatusImpl, { TrackStreamingStatus } from '../connectivity/TrackStreamingStatus';\nimport Statistics from '../statistics/statistics';\n\nimport JitsiTrack from './JitsiTrack';\n\nconst logger = require('@jitsi/logger').getLogger(__filename);\n\nconst RTCEvents = require('../../service/RTC/RTCEvents');\n\nlet ttfmTrackerAudioAttached = false;\nlet ttfmTrackerVideoAttached = false;\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 */\nexport default class JitsiRemoteTrack extends JitsiTrack {\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 ssrc is not a number.\n * @constructor\n */\n constructor(\n rtc,\n conference,\n ownerEndpointId,\n stream,\n track,\n mediaType,\n videoType,\n ssrc,\n muted,\n isP2P,\n sourceName) {\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\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 if (this.rtc && this.track) {\n this._bindTrackHandlers();\n }\n this._containerHandlers = {};\n containerEvents.forEach(event => {\n this._containerHandlers[event] = this._containerEventHandler.bind(this, event);\n });\n }\n\n /* eslint-enable max-params */\n /**\n * Attaches the track handlers.\n *\n * @returns {void}\n */\n _bindTrackHandlers() {\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 _addEventListener(event, handler) {\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 _removeEventListener(event, handler) {\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 _onTrackMute() {\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 _onTrackUnmute() {\n logger.debug(`\"onunmute\" event(${Date.now()}): ${this}`);\n\n this.rtc.eventEmitter.emit(RTCEvents.REMOTE_TRACK_UNMUTE, this);\n }\n\n /**\n * Removes attached event listeners and dispose TrackStreamingStatus .\n *\n * @returns {Promise}\n */\n dispose() {\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 */\n setMute(value) {\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} true if the track is\n * muted and false otherwise.\n */\n isMuted() {\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() {\n return this.ownerEndpointId;\n }\n\n /**\n * Return false;\n */\n isLocal() {\n return false;\n }\n\n /**\n * Returns the synchronization source identifier (SSRC) of this remote\n * track.\n *\n * @returns {number} the SSRC of this remote track.\n */\n getSSRC() {\n return this.ssrc;\n }\n\n\n /**\n * Returns the tracks source name\n *\n * @returns {string} the track's source name\n */\n getSourceName() {\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 */\n setOwner(owner) {\n this.ownerEndpointId = owner;\n }\n\n /**\n * Sets the name of the source associated with the remtoe track.\n *\n * @param {string} name - The source name to be associated with the track.\n */\n setSourceName(name) {\n this._sourceName = name;\n }\n\n /**\n * Changes the video type of the track.\n *\n * @param {string} type - The new video type(\"camera\", \"desktop\").\n */\n _setVideoType(type) {\n if (this.videoType === type) {\n return;\n }\n this.videoType = type;\n this.emit(JitsiTrackEvents.TRACK_VIDEOTYPE_CHANGED, type);\n }\n\n /**\n * Handles track play events.\n */\n _playCallback() {\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 = !isNaN(gumEnd) && !isNaN(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 * 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 * @private\n */\n _attachTTFMTracker(container) {\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 /**\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 * @private\n */\n _onTrackAttach(container) {\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 * @private\n */\n _onTrackDetach(container) {\n containerEvents.forEach(event => {\n container.removeEventListener(event, this._containerHandlers[event]);\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 _containerEventHandler(type) {\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 _getStatus() {\n const { enabled, muted, readyState } = this.track;\n\n return `readyState: ${readyState}, muted: ${muted}, enabled: ${enabled}`;\n }\n\n /**\n * Initializes trackStreamingStatusImpl.\n */\n _initTrackStreamingStatus() {\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 p2pRtcMuteTimeout: config._p2pConnStatusRtcMuteTimeout,\n rtcMuteTimeout: config._peerConnStatusRtcMuteTimeout,\n outOfForwardedSourcesTimeout: config._peerConnStatusOutOfLastNTimeout\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 _disposeTrackStreamingStatus() {\n if (this._trackStreamingStatusImpl) {\n this._trackStreamingStatusImpl.dispose();\n this._trackStreamingStatusImpl = null;\n this._trackStreamingStatus = null;\n }\n }\n\n /**\n * Updates track's streaming status.\n *\n * @param {string} state the current track streaming state. {@link TrackStreamingStatus}.\n */\n _setTrackStreamingStatus(status) {\n this._trackStreamingStatus = status;\n }\n\n /**\n * Returns track's streaming status.\n *\n * @returns {string} the streaming status TrackStreamingStatus of the track. Returns null\n * if trackStreamingStatusImpl hasn't been initialized.\n *\n * {@link TrackStreamingStatus}.\n */\n getTrackStreamingStatus() {\n return this._trackStreamingStatus;\n }\n\n /**\n * Clears the timestamp of when the track entered forwarded sources.\n */\n _clearEnteredForwardedSourcesTimestamp() {\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 */\n _setEnteredForwardedSourcesTimestamp(timestamp) {\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 */\n _getEnteredForwardedSourcesTimestamp() {\n return this._enteredForwardedSourcesTimestamp;\n }\n\n /**\n * Creates a text representation of this remote track instance.\n * @return {string}\n */\n toString() {\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 * 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.clonedeep';\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 { getSourceIndexFromSourceName } from '../../service/RTC/SignalingLayer';\nimport {\n SIM_LAYERS,\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';\n\nconst logger = getLogger(__filename);\nconst VIDEO_CODECS = [ CodecMimeType.AV1, CodecMimeType.H264, CodecMimeType.VP8, CodecMimeType.VP9 ];\n\n/**\n * Handles track related operations on TraceablePeerConnection when browser is\n * running in unified plan mode.\n */\nexport class TPCUtils {\n /**\n * Creates a new instance for a given TraceablePeerConnection\n *\n * @param peerconnection - the tpc instance for which we have utility functions.\n */\n constructor(peerconnection) {\n this.pc = peerconnection;\n this.codecSettings = clonedeep(STANDARD_CODEC_SETTINGS);\n const videoQualitySettings = this.pc.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\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 */\n _calculateActiveEncodingParams(localVideoTrack, codec, newHeight) {\n const codecBitrates = this.codecSettings[codec].maxBitratesVideo;\n const trackCaptureHeight = localVideoTrack.getCaptureResolution();\n const effectiveNewHeight = newHeight > trackCaptureHeight ? trackCaptureHeight : newHeight;\n const desktopShareBitrate = this.pc.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 = {\n active: effectiveNewHeight > 0,\n maxBitrate,\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 * 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 _configureSenderEncodings(localTrack) {\n const mediaType = localTrack.getType();\n const transceiver = localTrack?.track && localTrack.getOriginalStream()\n ? this.pc.peerconnection.getTransceivers().find(t => t.sender?.track?.id === localTrack.getTrackId())\n : this.pc.peerconnection.getTransceivers().find(t => t.receiver?.track?.kind === mediaType);\n const parameters = transceiver?.sender?.getParameters();\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 Promise.resolve();\n }\n\n parameters.encodings = this._getStreamEncodings(localTrack);\n\n return 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 _enableSenderEncodings(sender, enable) {\n const parameters = sender.getParameters();\n\n if (parameters?.encodings?.length) {\n for (const encoding of parameters.encodings) {\n encoding.active = enable;\n }\n }\n\n return sender.setParameters(parameters);\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 */\n _getStreamEncodings(localTrack) {\n if (localTrack.isAudioTrack()) {\n return [ { active: this.pc.audioTransferActive } ];\n }\n const codec = this.pc.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 * The startup configuration for the stream encodings that are applicable to\n * the video stream when a new sender is created on the peerconnection. The initial\n * config takes into account the differences in browser's simulcast 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\n * based on the encoding's resolution and 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\n * original resolution of the captured video.\n *\n * @param {JitsiLocalTrack} localTrack\n * @param {String} codec\n */\n _getVideoStreamEncodings(localTrack, codec) {\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() && (videoType === VideoType.DESKTOP || browser.isVersionLessThan(117))) {\n effectiveBitrates = effectiveBitrates.reverse();\n effectiveScaleFactors = effectiveScaleFactors.reverse();\n }\n\n const standardSimulcastEncodings = [\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 scaleResolutionDownBy: effectiveScaleFactors[2],\n scalabilityMode: this.codecSettings[codec].useKSVC\n ? VideoEncoderScalabilityMode.L3T3_KEY : VideoEncoderScalabilityMode.L3T3\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\n * @returns boolean\n */\n _isRunningInFullSvcMode(codec) {\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}\n */\n _isScreenshareBitrateCapped(localVideoTrack) {\n return localVideoTrack.getVideoType() === VideoType.DESKTOP\n && this.pc._capScreenshareBitrate\n && !browser.isWebKitBased();\n }\n\n /**\n * Updates the sender parameters in the stream encodings.\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 _updateSenderEncodings(sender, enable) {\n const parameters = sender.getParameters();\n\n if (parameters?.encodings?.length) {\n for (const encoding of parameters.encodings) {\n encoding.active = enable;\n }\n }\n\n return sender.setParameters(parameters);\n }\n\n /**\n * Adds {@link JitsiLocalTrack} to the WebRTC peerconnection for the first time.\n * @param {JitsiLocalTrack} track - track to be added to the peerconnection.\n * @param {boolean} isInitiator - boolean that indicates if the endpoint is offerer in a p2p connection.\n * @returns {void}\n */\n addTrack(localTrack, isInitiator) {\n const track = localTrack.getTrack();\n\n if (isInitiator) {\n const streams = [];\n\n if (localTrack.getOriginalStream()) {\n streams.push(localTrack.getOriginalStream());\n }\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 streams,\n sendEncodings: []\n };\n\n if (!browser.isFirefox()) {\n transceiverInit.sendEncodings = this._getStreamEncodings(localTrack);\n }\n this.pc.peerconnection.addTransceiver(track, 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 this.pc.peerconnection.addTrack(track);\n }\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}\n */\n calculateEncodingsActiveState(localVideoTrack, codec, newHeight) {\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}\n */\n calculateEncodingsBitrates(localVideoTrack, codec, newHeight) {\n const codecBitrates = this.codecSettings[codec].maxBitratesVideo;\n const desktopShareBitrate = this.pc.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 : 0;\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 {Array | undefined}\n */\n calculateEncodingsScalabilityMode(localVideoTrack, codec, maxHeight) {\n if (!this.pc.isSpatialScalabilityOn() || !this.codecSettings[codec].scalabilityModeEnabled) {\n return;\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;\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}\n */\n calculateEncodingsScaleFactor(localVideoTrack, codec, maxHeight) {\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.,\n * the primary ssrc first and the secondary rtx ssrc later. This is important for unified\n * plan since we have only one FID group per media description.\n * @param {Object} description the webRTC session description instance for the remote\n * description.\n * @private\n */\n ensureCorrectOrderOfSsrcs(description) {\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 || !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 type: description.type,\n sdp: transform.write(parsedSdp)\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 *\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) {\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 id: SIM_LAYERS[0].rid,\n direction: 'recv'\n },\n {\n id: SIM_LAYERS[1].rid,\n direction: 'recv'\n },\n {\n id: SIM_LAYERS[2].rid,\n direction: 'recv'\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 // Make sure the simulcast recv line is only set on video descriptions that are associated with senders.\n if (senderMids.find(sender => mLine.mid.toString() === sender.toString()) || idx === 0) {\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 type: desc.type,\n sdp: transform.write(sdp)\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} codec - The video codec in use.\n * @returns {boolean}\n */\n isRunningInSimulcastMode(codec) {\n return codec === CodecMimeType.VP8 // VP8 always\n\n // K-SVC mode for VP9 when no scalability mode is set. Though only one outbound-rtp stream is present,\n // three separate encodings have to be configured.\n || (!this.codecSettings[codec].scalabilityModeEnabled && codec === CodecMimeType.VP9)\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[codec].scalabilityModeEnabled\n && (codec === CodecMimeType.H264 || this.codecSettings[codec].useSimulcast));\n }\n\n /**\n * Replaces the existing track on a RTCRtpSender with the given track.\n *\n * @param {JitsiLocalTrack} oldTrack - existing track on the sender that needs to be removed.\n * @param {JitsiLocalTrack} newTrack - new track that needs to be added to the sender.\n * @returns {Promise} - resolved with the associated transceiver when done, rejected otherwise.\n */\n replaceTrack(oldTrack, newTrack) {\n const mediaType = newTrack?.getType() ?? oldTrack?.getType();\n const localTracks = this.pc.getLocalTracks(mediaType);\n const track = newTrack?.getTrack() ?? null;\n const isNewLocalSource = localTracks?.length\n && !oldTrack\n && newTrack\n && !localTracks.find(t => t === newTrack);\n let transceiver;\n\n // If old track exists, replace the track on the corresponding sender.\n if (oldTrack && !oldTrack.isMuted()) {\n transceiver = this.pc.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.pc.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.pc.isP2P && t.currentDirection === MediaDirection.RECVONLY)\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.pc.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.pc.isP2P) {\n transceiver = this.pc.peerconnection.getTransceivers()\n .filter(t => t.receiver.track.kind === mediaType)[trackIndex];\n } else if (oldTrack) {\n const transceiverMid = this.pc._localTrackTransceiverMids.get(oldTrack.rtcId);\n\n transceiver = this.pc.peerconnection.getTransceivers().find(t => t.mid === transceiverMid);\n } else if (trackIndex) {\n transceiver = this.pc.peerconnection.getTransceivers()\n .filter(t => t.receiver.track.kind === mediaType\n && t.direction !== MediaDirection.RECVONLY)[trackIndex];\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 logger.debug(`${this.pc} Replacing ${oldTrack} with ${newTrack}`);\n\n return transceiver.sender.replaceTrack(track)\n .then(() => Promise.resolve(transceiver));\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} - resolved when done.\n */\n setEncodings(localTrack) {\n if (localTrack.getType() === MediaType.VIDEO) {\n return this.pc._updateVideoSenderParameters(() => this._configureSenderEncodings(localTrack));\n }\n\n return this._configureSenderEncodings(localTrack);\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, mediaType) {\n logger.info(`${this.pc} ${enable ? 'Resuming' : 'Suspending'} media transfer.`);\n\n const senders = this.pc.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.pc._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","import { getLogger } from '@jitsi/logger';\nimport { Interop } from '@jitsi/sdp-interop';\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 * as SignalingEvents from '../../service/RTC/SignalingEvents';\nimport { getSourceIndexFromSourceName } from '../../service/RTC/SignalingLayer';\nimport { VIDEO_QUALITY_LEVELS } from '../../service/RTC/StandardVideoQualitySettings';\nimport { VideoType } from '../../service/RTC/VideoType';\nimport { SS_DEFAULT_FRAME_RATE } from '../RTC/ScreenObtainer';\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';\n\nimport JitsiRemoteTrack from './JitsiRemoteTrack';\nimport RTCUtils from './RTCUtils';\nimport { TPCUtils } from './TPCUtils';\n\n// FIXME SDP tools should end up in some kind of util module\n\nconst logger = getLogger(__filename);\nconst DEGRADATION_PREFERENCE_CAMERA = 'maintain-framerate';\nconst DEGRADATION_PREFERENCE_DESKTOP = 'maintain-resolution';\nconst DD_HEADER_EXT_URI\n = 'https://aomediacodec.github.io/av1-rtp-spec/#dependency-descriptor-rtp-header-extension';\nconst DD_HEADER_EXT_ID = 11;\n\n/* eslint-disable max-params */\n\n/**\n * Creates new instance of 'TraceablePeerConnection'.\n *\n * @param {RTC} rtc the instance of RTC 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 TracablePeerConnection 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} 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 */\nexport default function TraceablePeerConnection(\n rtc,\n id,\n signalingLayer,\n pcConfig,\n constraints,\n isP2P,\n options) {\n\n /**\n * Indicates whether or not this peer connection instance is actively\n * sending/receiving audio media. When set to false the SDP audio\n * media direction will be adjusted to 'inactive' in order to suspend\n * the transmission.\n * @type {boolean}\n * @private\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}\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 false the SDP video\n * media direction will be adjusted to 'inactive' in order to suspend\n * the transmission.\n * @type {boolean}\n * @private\n */\n this.videoTransferActive = true;\n\n /**\n * The parent instance of RTC service which created this\n * TracablePeerConnection.\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 * 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}\n */\n this.remoteTracksBySsrc = new Map();\n\n /**\n * The map holds remote tracks associated with this peer connection. It maps user's JID to media type and a set of\n * remote tracks.\n * @type {Map>>}\n */\n this.remoteTracks = new Map();\n\n /**\n * A map which stores local tracks mapped by {@link JitsiLocalTrack.rtcId}\n * @type {Map}\n */\n this.localTracks = new Map();\n\n /**\n * @typedef {Object} TPCGroupInfo\n * @property {string} semantics the SSRC groups semantics\n * @property {Array} 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} ssrcs an array which holds all track's SSRCs\n * @property {Array} 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}\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}\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}\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 // 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 this.peerconnection = new RTCPeerConnection(pcConfig, safeConstraints);\n\n this.tpcUtils = new TPCUtils(this);\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 /**\n * Indicates whether an audio track has ever been added to the peer connection.\n */\n this._hasHadAudioTrack = false;\n\n /**\n * Indicates whether a video track has ever been added to the peer connection.\n */\n this._hasHadVideoTrack = false;\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.interop = new Interop();\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}\n */\n this._senderMaxHeights = new Map();\n\n /**\n * Flag indicating bridge support for AV1 codec. On the bridge connection, it is supported only when support for\n * Dependency Descriptor header extensions is offered by Jicofo. H.264 simulcast is also possible when these\n * header extensions are negotiated.\n */\n this._supportsDDHeaderExt = false;\n\n /**\n * Holds the RTCRtpTransceiver mids that the local tracks are attached to, mapped per their\n * {@link JitsiLocalTrack.rtcId}.\n * @type {Map}\n */\n this._localTrackTransceiverMids = 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 => {\n if (typeof stats?.result === 'function') {\n const results = stats.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.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/* 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 */\nTraceablePeerConnection.prototype._processStat\n = function(report, name, statValue) {\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 startTime: now,\n endTime: now,\n values: [],\n times: []\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 * Returns a string representation of a SessionDescription object.\n */\nconst dumpSDP = function(description) {\n if (typeof description === 'undefined' || description === null) {\n return '';\n }\n\n return `type: ${description.type}\\r\\n${description.sdp}`;\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 {string}\n */\nTraceablePeerConnection.prototype.getConnectionState = function() {\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\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.) which should be used when setting\n * local description on the peerconnection.\n * @private\n */\nTraceablePeerConnection.prototype.getDesiredMediaDirection = function(mediaType, isAddOperation = false) {\n const hasLocalSource = this.hasAnyTracksOfType(mediaType);\n\n if (isAddOperation) {\n return hasLocalSource ? MediaDirection.SENDRECV : MediaDirection.SENDONLY;\n }\n\n return hasLocalSource ? MediaDirection.RECVONLY : MediaDirection.INACTIVE;\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} endpoints list of the endpoints\n * @param {string} mediaType 'audio' or 'video'\n * @returns {Array} list of receivers created by the peerconnection.\n */\nTraceablePeerConnection.prototype._getReceiversByEndpointIds = function(endpoints, mediaType) {\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\n && receiver.track.kind === mediaType\n && remoteTrackIds.find(trackId => trackId === receiver.track.id));\n\n return receivers;\n};\n\n/**\n * Tells whether or not this TPC instance has spatial scalability enabled.\n * @return {boolean} true if spatial scalability is enabled and active or\n * false if it's turned off.\n */\nTraceablePeerConnection.prototype.isSpatialScalabilityOn = function() {\n const h264SimulcastEnabled = this.tpcUtils.codecSettings[CodecMimeType.H264].scalabilityModeEnabled\n && this._supportsDDHeaderExt;\n\n return !this.options.disableSimulcast\n && (this.codecSettings.codecList[0] !== CodecMimeType.H264 || h264SimulcastEnabled);\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 */\nTraceablePeerConnection.prototype._peerVideoTypeChanged = function(endpointId, videoType) {\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 * 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 */\nTraceablePeerConnection.prototype._peerMutedChanged = function(endpointId, mediaType, isMuted) {\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 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 */\nTraceablePeerConnection.prototype._sourceMutedChanged = function(sourceName, isMuted) {\n const track = this.getRemoteTracks().find(t => t.getSourceName() === sourceName);\n\n if (!track) {\n if (FeatureFlags.isSsrcRewritingSupported()) {\n logger.debug(`Remote track not found for source=${sourceName}, mute update failed!`);\n }\n\n return;\n }\n\n track.setMute(isMuted);\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 */\nTraceablePeerConnection.prototype._sourceVideoTypeChanged = function(sourceName, videoType) {\n const track = this.getRemoteTracks().find(t => t.getSourceName() === sourceName);\n\n if (!track) {\n return;\n }\n\n track._setVideoType(videoType);\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} 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 */\nTraceablePeerConnection.prototype.getAudioLevels = function(speakerList = []) {\n const audioLevels = {};\n const audioReceivers = speakerList.length\n ? this._getReceiversByEndpointIds(speakerList, MediaType.AUDIO)\n : this.peerconnection.getReceivers()\n .filter(receiver => receiver.track && receiver.track.kind === MediaType.AUDIO && receiver.track.enabled);\n\n audioReceivers.forEach(remote => {\n const ssrc = remote.getSynchronizationSources();\n\n if (ssrc && 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 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 */\nTraceablePeerConnection.prototype.doesTrueSimulcast = function(localTrack) {\n const currentCodec = this.getConfiguredVideoCodec(localTrack);\n\n return this.isSpatialScalabilityOn() && this.tpcUtils.isRunningInSimulcastMode(currentCodec);\n};\n\n/**\n * Returns the SSRCs associated with a given local video track.\n *\n * @param {JitsiLocalTrack} localTrack\n * @returns\n */\nTraceablePeerConnection.prototype.getLocalVideoSSRCs = function(localTrack) {\n const ssrcs = [];\n\n if (!localTrack || !localTrack.isVideoTrack()) {\n return ssrcs;\n }\n\n const ssrcGroup = this.isSpatialScalabilityOn() ? 'SIM' : 'FID';\n\n return this.localSSRCs.get(localTrack.rtcId)?.groups?.find(group => group.semantics === ssrcGroup)?.ssrcs || ssrcs;\n};\n\n/**\n * Obtains local tracks for given {@link MediaType}. If the mediaType\n * argument is omitted the list of all local tracks will be returned.\n * @param {MediaType} [mediaType]\n * @return {Array}\n */\nTraceablePeerConnection.prototype.getLocalTracks = function(mediaType) {\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} - local video tracks.\n */\nTraceablePeerConnection.prototype.getLocalVideoTracks = function() {\n return this.getLocalTracks(MediaType.VIDEO);\n};\n\n/**\n * Checks whether or not this {@link TraceablePeerConnection} instance contains any local tracks for given\n * mediaType.\n *\n * @param {MediaType} mediaType - The media type.\n * @return {boolean}\n */\nTraceablePeerConnection.prototype.hasAnyTracksOfType = function(mediaType) {\n if (!mediaType) {\n throw new Error('\"mediaType\" is required');\n }\n\n return this.getLocalTracks(mediaType).length > 0;\n};\n\n/**\n * Obtains all remote tracks currently known to this PeerConnection instance.\n *\n * @param {string} [endpointId] - The track owner's identifier (MUC nickname)\n * @param {MediaType} [mediaType] - The remote tracks will be filtered by their media type if this argument is\n * specified.\n * @return {Array}\n */\nTraceablePeerConnection.prototype.getRemoteTracks = function(endpointId, mediaType) {\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 * Parses the remote description and returns the sdp lines of the sources associated with a remote participant.\n *\n * @param {string} id Endpoint id of the remote participant.\n * @returns {Array} The sdp lines that have the ssrc information.\n */\nTraceablePeerConnection.prototype.getRemoteSourceInfoByParticipant = function(id) {\n const removeSsrcInfo = [];\n const remoteTracks = this.getRemoteTracks(id);\n\n if (!remoteTracks?.length) {\n return removeSsrcInfo;\n }\n const primarySsrcs = remoteTracks.map(track => track.getSSRC());\n const sdp = new SDP(this.remoteDescription.sdp);\n\n primarySsrcs.forEach((ssrc, idx) => {\n for (const media of sdp.media) {\n let lines = '';\n let ssrcLines = SDPUtil.findLines(media, `a=ssrc:${ssrc}`);\n\n if (ssrcLines.length) {\n if (!removeSsrcInfo[idx]) {\n removeSsrcInfo[idx] = '';\n }\n\n // Check if there are any FID groups present for the primary ssrc.\n const fidLines = SDPUtil.findLines(media, `a=ssrc-group:FID ${ssrc}`);\n\n if (fidLines.length) {\n const secondarySsrc = fidLines[0].split(' ')[2];\n\n lines += `${fidLines[0]}\\r\\n`;\n ssrcLines = ssrcLines.concat(SDPUtil.findLines(media, `a=ssrc:${secondarySsrc}`));\n }\n removeSsrcInfo[idx] += `${ssrcLines.join('\\r\\n')}\\r\\n`;\n removeSsrcInfo[idx] += lines;\n }\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 */\nTraceablePeerConnection.prototype.getTargetVideoBitrates = function(localTrack) {\n const currentCodec = this.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 {JitsiTrack|null}\n */\nTraceablePeerConnection.prototype.getTrackBySSRC = function(ssrc) {\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);\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 {number|null}\n */\nTraceablePeerConnection.prototype.getSsrcByTrackId = function(id) {\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 */\nTraceablePeerConnection.prototype._remoteTrackAdded = function(stream, track, transceiver = null) {\n const streamId = stream.id;\n const mediaType = track.kind;\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.peerconnection.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 mediaLine = remoteSDP.media.find(mls => SDPUtil.findLine(mls, `a=mid:${mid}`));\n } else {\n mediaLine = remoteSDP.media.find(mls => {\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(`Matching media line not found in remote SDP for remote stream[id=${streamId},type=${mediaType}],`\n + 'track creation failed!');\n\n return;\n }\n\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 (isNaN(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 // Assume default presence state for remote source. Presence can be received after source signaling. This shouldn't\n // prevent the endpoint from creating a remote track for the source.\n let muted = true;\n let videoType = mediaType === MediaType.VIDEO ? VideoType.CAMERA : undefined; // 'camera' by default\n\n if (peerMediaInfo) {\n muted = peerMediaInfo.muted;\n videoType = peerMediaInfo.videoType; // can be undefined\n } else {\n logger.info(`${this}: no source-info available for ${ownerEndpointId}:${sourceName}, assuming default state`);\n }\n\n this._createRemoteTrack(ownerEndpointId, stream, track, mediaType, videoType, trackSsrc, muted, sourceName);\n};\n\n// FIXME cleanup params\n/* eslint-disable max-params */\n\n/**\n * Initializes a new JitsiRemoteTrack instance with the data provided by\n * the signaling layer and SDP.\n *\n * @param {string} ownerEndpointId the owner's endpoint ID (MUC nickname)\n * @param {MediaStream} stream the WebRTC stream instance\n * @param {MediaStreamTrack} track the WebRTC track instance\n * @param {MediaType} mediaType the track's type of the media\n * @param {VideoType} [videoType] the track's type of the video (if applicable)\n * @param {number} ssrc the track's main SSRC number\n * @param {boolean} muted the initial muted status\n * @param {String} sourceName the track's source name\n */\nTraceablePeerConnection.prototype._createRemoteTrack = function(\n ownerEndpointId,\n stream,\n track,\n mediaType,\n videoType,\n ssrc,\n muted,\n sourceName) {\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 => 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 */\nTraceablePeerConnection.prototype._remoteTrackRemoved = function(stream, track) {\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 JitsiRemoteTrack instance. Emits {@link RTCEvents.REMOTE_TRACK_REMOVED}.\n *\n * @param {JitsiRemoteTrack} toBeRemoved - The remote track to be removed.\n * @returns {void}\n */\nTraceablePeerConnection.prototype._removeRemoteTrack = function(toBeRemoved) {\n logger.info(`${this} Removing remote track stream[id=${toBeRemoved.getStreamId()},`\n + `trackId=${toBeRemoved.getTrackId()}]`);\n\n toBeRemoved.dispose();\n const participantId = toBeRemoved.getParticipantId();\n\n if (FeatureFlags.isSsrcRewritingSupported() && !participantId) {\n return;\n } else if (!FeatureFlags.isSsrcRewritingSupported()) {\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 * Returns a map with keys msid/mediaType and TrackSSRCInfo values.\n * @param {RTCSessionDescription} desc the local description.\n * @return {Map}\n */\nTraceablePeerConnection.prototype._extractSSRCMap = function(desc) {\n /**\n * Track SSRC infos mapped by stream ID (msid) or mediaType (unified-plan)\n * @type {Map}\n */\n const ssrcMap = new Map();\n\n /**\n * Groups mapped by primary SSRC number\n * @type {Map>}\n */\n const groupsMap = new Map();\n\n if (typeof desc !== 'object' || desc === null\n || typeof desc.sdp !== 'string') {\n logger.warn('An empty description was passed as an argument');\n\n return ssrcMap;\n }\n\n const session = transform.parse(desc.sdp);\n\n if (!Array.isArray(session.media)) {\n return ssrcMap;\n }\n\n let media = session.media;\n\n media = media.filter(mline => mline.direction === MediaDirection.SENDONLY\n || mline.direction === MediaDirection.SENDRECV);\n\n let index = 0;\n\n for (const mLine of media) {\n if (!Array.isArray(mLine.ssrcs)) {\n continue; // eslint-disable-line no-continue\n }\n\n if (Array.isArray(mLine.ssrcGroups)) {\n for (const group of mLine.ssrcGroups) {\n if (typeof group.semantics !== 'undefined' && typeof group.ssrcs !== 'undefined') {\n // Parse SSRCs and store as numbers\n const groupSSRCs = group.ssrcs.split(' ').map(ssrcStr => parseInt(ssrcStr, 10));\n const primarySSRC = groupSSRCs[0];\n\n // Note that group.semantics is already present\n group.ssrcs = groupSSRCs;\n\n // eslint-disable-next-line max-depth\n if (!groupsMap.has(primarySSRC)) {\n groupsMap.set(primarySSRC, []);\n }\n groupsMap.get(primarySSRC).push(group);\n }\n }\n\n const simGroup = mLine.ssrcGroups.find(group => group.semantics === 'SIM');\n\n // Add a SIM group if its missing in the description (happens on Firefox).\n if (!simGroup) {\n const groupSsrcs = mLine.ssrcGroups.map(group => group.ssrcs[0]);\n\n groupsMap.get(groupSsrcs[0]).push({\n semantics: 'SIM',\n ssrcs: groupSsrcs\n });\n }\n }\n\n let ssrcs = mLine.ssrcs;\n\n // Filter the ssrcs with 'cname' attribute.\n ssrcs = ssrcs.filter(s => s.attribute === 'cname');\n\n for (const ssrc of ssrcs) {\n // Use the mediaType as key for the source map for unified plan clients since msids are not part of\n // the standard and the unified plan SDPs do not have a proper msid attribute for the sources.\n // Also the ssrcs for sources do not change for Unified plan clients since RTCRtpSender#replaceTrack is\n // used for switching the tracks so it is safe to use the mediaType as the key for the TrackSSRCInfo map.\n const key = `${mLine.type}-${index}`;\n const ssrcNumber = ssrc.id;\n let ssrcInfo = ssrcMap.get(key);\n\n if (!ssrcInfo) {\n ssrcInfo = {\n ssrcs: [],\n groups: [],\n msid: key\n };\n ssrcMap.set(key, ssrcInfo);\n }\n ssrcInfo.ssrcs.push(ssrcNumber);\n\n if (groupsMap.has(ssrcNumber)) {\n const ssrcGroups = groupsMap.get(ssrcNumber);\n\n for (const group of ssrcGroups) {\n ssrcInfo.groups.push(group);\n }\n }\n }\n\n // Currently multi-stream is supported for video only.\n mLine.type === MediaType.VIDEO && index++;\n }\n\n return ssrcMap;\n};\n\n/**\n *\n * @param {JitsiLocalTrack} localTrack\n */\nTraceablePeerConnection.prototype.getLocalSSRC = function(localTrack) {\n const ssrcInfo = this._getSSRC(localTrack.rtcId);\n\n return ssrcInfo && ssrcInfo.ssrcs[0];\n};\n\n/**\n * When doing unified plan simulcast, we'll have a set of ssrcs but no ssrc-groups on Firefox. Unfortunately, Jicofo\n * will complain if it sees ssrcs with matching msids but no ssrc-group, so a ssrc-group line is injected to make\n * Jicofo happy.\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 */\nTraceablePeerConnection.prototype._injectSsrcGroupForUnifiedSimulcast = function(desc) {\n const sdp = transform.parse(desc.sdp);\n const video = sdp.media.find(mline => mline.type === 'video');\n\n // Check if the browser supports RTX, add only the primary ssrcs to the SIM group if that is the case.\n video.ssrcGroups = video.ssrcGroups || [];\n const fidGroups = video.ssrcGroups.filter(group => group.semantics === 'FID');\n\n if (video.simulcast || video.simulcast_03) {\n const ssrcs = [];\n\n if (fidGroups && fidGroups.length) {\n fidGroups.forEach(group => {\n ssrcs.push(group.ssrcs.split(' ')[0]);\n });\n } else {\n video.ssrcs.forEach(ssrc => {\n if (ssrc.attribute === 'msid') {\n ssrcs.push(ssrc.id);\n }\n });\n }\n if (video.ssrcGroups.find(group => group.semantics === 'SIM')) {\n // Group already exists, no need to do anything\n return desc;\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: 'SIM',\n ssrcs: simSsrcs.join(' ')\n });\n }\n }\n\n return new RTCSessionDescription({\n type: desc.type,\n sdp: transform.write(sdp)\n });\n};\n\n/* eslint-disable-next-line vars-on-top */\nconst getters = {\n signalingState() {\n return this.peerconnection.signalingState;\n },\n iceConnectionState() {\n return this.peerconnection.iceConnectionState;\n },\n connectionState() {\n return this.peerconnection.connectionState;\n },\n localDescription() {\n let desc = this.peerconnection.localDescription;\n\n if (!desc) {\n logger.debug(`${this} getLocalDescription no localDescription found`);\n\n return {};\n }\n\n this.trace('getLocalDescription::preTransform', dumpSDP(desc));\n\n // For a jvb connection, transform the SDP to Plan B first.\n if (!this.isP2P) {\n desc = this.interop.toPlanB(desc);\n this.trace('getLocalDescription::postTransform (Plan B)', dumpSDP(desc));\n\n desc = this._injectSsrcGroupForUnifiedSimulcast(desc);\n this.trace('getLocalDescription::postTransform (inject ssrc group)', dumpSDP(desc));\n }\n\n // See the method's doc for more info about this transformation.\n desc = this.localSdpMunger.transformStreamIdentifiers(desc);\n\n return desc;\n },\n remoteDescription() {\n let desc = this.peerconnection.remoteDescription;\n\n if (!desc) {\n logger.debug(`${this} getRemoteDescription no remoteDescription found`);\n\n return {};\n }\n this.trace('getRemoteDescription::preTransform', dumpSDP(desc));\n\n if (this.isP2P) {\n // Adjust the media direction for p2p based on whether a local source has been added.\n desc = this._adjustRemoteMediaDirection(desc);\n } else {\n // If this is a jvb connection, transform the SDP to Plan B first.\n desc = this.interop.toPlanB(desc);\n this.trace('getRemoteDescription::postTransform (Plan B)', dumpSDP(desc));\n }\n\n return desc;\n }\n};\n\nObject.keys(getters).forEach(prop => {\n Object.defineProperty(\n TraceablePeerConnection.prototype,\n prop, {\n get: getters[prop]\n }\n );\n});\n\nTraceablePeerConnection.prototype._getSSRC = function(rtcId) {\n return this.localSSRCs.get(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 */\nTraceablePeerConnection.prototype.isSharingLowFpsScreen = function() {\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 */\nTraceablePeerConnection.prototype._isSharingScreen = function() {\n const tracks = this.getLocalVideoTracks();\n\n return Boolean(tracks.find(track => track.videoType === VideoType.DESKTOP));\n};\n\n/**\n * Munges the order of the codecs in the SDP passed based on the preference\n * set through config.js settings. All instances of the specified codec are\n * moved up to the top of the list when it is preferred. The specified codec\n * is deleted from the list if the configuration specifies that the codec be\n * disabled.\n * @param {RTCSessionDescription} description that needs to be munged.\n * @returns {RTCSessionDescription} the munged description.\n */\nTraceablePeerConnection.prototype._mungeCodecOrder = function(description) {\n if (!this.codecSettings) {\n return description;\n }\n\n const parsedSdp = transform.parse(description.sdp);\n const mLines = parsedSdp.media.filter(m => m.type === this.codecSettings.mediaType);\n\n if (!mLines.length) {\n return description;\n }\n\n for (const mLine of mLines) {\n const currentCodecs = this.getConfiguredVideoCodecs(description);\n\n for (const codec of currentCodecs) {\n if (this.isP2P) {\n // 1. Strip the high profile H264 codecs on all clients. macOS started offering encoder for H.264 level\n // 5.2 but a decoder only for level 3.1. Therfore, strip all main and high level codecs for H.264.\n // 2. There are multiple VP9 payload types generated by the browser, more payload types are added if the\n // endpoint doesn't have a local video source. Therefore, strip all the high profile codec variants\n // 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.usesCodecSelectionAPI()) {\n for (const codec of this.codecSettings.codecList.slice().reverse()) {\n SDPUtil.preferCodec(mLine, codec, this.isP2P);\n }\n }\n }\n\n return new RTCSessionDescription({\n type: description.type,\n sdp: transform.write(parsedSdp)\n });\n};\n\n/**\n * Checks if the AV1 Dependency descriptors are negotiated on the bridge peerconnection and disables them when the\n * codec selected is VP8 or VP9.\n *\n * @param {RTCSessionDescription} description that needs to be munged.\n * @returns {RTCSessionDescription} the munged description.\n */\nTraceablePeerConnection.prototype._updateAv1DdHeaders = function(description) {\n const parsedSdp = transform.parse(description.sdp);\n const mLines = parsedSdp.media.filter(m => m.type === MediaType.VIDEO);\n\n if (!mLines.length || !browser.supportsDDExtHeaders()) {\n return description;\n }\n\n mLines.forEach((mLine, idx) => {\n const senderMids = Array.from(this._localTrackTransceiverMids.values());\n const isSender = senderMids.length\n ? senderMids.find(mid => mLine.mid.toString() === mid.toString())\n : idx === 0;\n const payload = mLine.payloads.split(' ')[0];\n let { codec } = mLine.rtp.find(rtp => rtp.payload === Number(payload));\n\n codec = codec.toLowerCase();\n\n if (isSender && mLine.ext?.length) {\n const headerIndex = mLine.ext.findIndex(ext => ext.uri === DD_HEADER_EXT_URI);\n const shouldNegotiateHeaderExts = codec === CodecMimeType.AV1 || codec === CodecMimeType.H264;\n\n if (!this._supportsDDHeaderExt && headerIndex >= 0) {\n this._supportsDDHeaderExt = true;\n }\n\n if (this._supportsDDHeaderExt && shouldNegotiateHeaderExts && headerIndex < 0) {\n mLine.ext.push({\n value: DD_HEADER_EXT_ID,\n uri: DD_HEADER_EXT_URI\n });\n } else if (!shouldNegotiateHeaderExts && headerIndex >= 0) {\n mLine.ext.splice(headerIndex, 1);\n }\n }\n });\n\n return new RTCSessionDescription({\n type: description.type,\n sdp: transform.write(parsedSdp)\n });\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} - resolved when done.\n */\nTraceablePeerConnection.prototype.addTrack = function(track, isInitiator = false) {\n const rtcId = track.rtcId;\n\n logger.info(`${this} adding ${track}`);\n if (this.localTracks.has(rtcId)) {\n\n return Promise.reject(new Error(`${track} is already in ${this}`));\n }\n\n this.localTracks.set(rtcId, track);\n const webrtcStream = track.getOriginalStream();\n\n try {\n this.tpcUtils.addTrack(track, isInitiator);\n if (track) {\n if (track.isAudioTrack()) {\n this._hasHadAudioTrack = true;\n } else {\n this._hasHadVideoTrack = true;\n }\n }\n } catch (error) {\n logger.error(`${this} Adding track=${track} failed: ${error?.message}`);\n\n return Promise.reject(error);\n }\n\n let promiseChain = Promise.resolve();\n\n // On Firefox, the encodings have to be configured on the sender only after the transceiver is created.\n if (browser.isFirefox()) {\n promiseChain = promiseChain.then(() => webrtcStream && this.tpcUtils.setEncodings(track));\n }\n\n return promiseChain;\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} 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 */\nTraceablePeerConnection.prototype.addTrackToPc = function(track) {\n logger.info(`${this} Adding track=${track} to PC`);\n\n if (!this._assertTrackBelongs('addTrackToPc', track)) {\n // Abort\n\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.tpcUtils.replaceTrack(null, track).then(() => {\n if (track) {\n if (track.isAudioTrack()) {\n this._hasHadAudioTrack = true;\n } else {\n this._hasHadVideoTrack = true;\n }\n }\n\n return false;\n });\n};\n\n/**\n * This method when called will check if given localTrack 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} true if given local track belongs to this TPC or\n * false otherwise.\n * @private\n */\nTraceablePeerConnection.prototype._assertTrackBelongs = function(\n methodName,\n localTrack) {\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 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 *\n */\nTraceablePeerConnection.prototype.getConfiguredVideoCodec = function(localTrack) {\n const localVideoTrack = localTrack ?? this.getLocalVideoTracks()[0];\n const rtpSender = this.findSenderForTrack(localVideoTrack.getTrack());\n\n if (this.usesCodecSelectionAPI() && rtpSender) {\n const { codecs } = rtpSender.getParameters();\n\n return codecs[0].mimeType.split('/')[1].toLowerCase();\n }\n\n const sdp = this.peerconnection.remoteDescription?.sdp;\n const defaultCodec = CodecMimeType.VP8;\n\n if (!sdp) {\n return defaultCodec;\n }\n const parsedSdp = transform.parse(sdp);\n const mLine = parsedSdp.media\n .find(m => m.mid.toString() === this._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 defaultCodec;\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 */\nTraceablePeerConnection.prototype.getConfiguredVideoCodecs = function(description) {\n const currentSdp = description?.sdp ?? this.peerconnection.localDescription?.sdp;\n\n if (!currentSdp) {\n return [];\n }\n const parsedSdp = transform.parse(currentSdp);\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);\n};\n\n/**\n * Checks if the client has negotiated not to receive video encoded using the given codec, i.e., the codec has been\n * removed from the local description.\n */\nTraceablePeerConnection.prototype.isVideoCodecDisabled = function(codec) {\n const sdp = this.peerconnection.localDescription?.sdp;\n\n if (!sdp) {\n return false;\n }\n const parsedSdp = transform.parse(sdp);\n const mLine = parsedSdp.media.find(m => m.type === MediaType.VIDEO);\n\n return !mLine.rtp.find(r => r.codec === codec);\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 */\nTraceablePeerConnection.prototype.setDesktopSharingFrameRate = function(maxFps) {\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} codecList - Preferred codecs for video.\n * @param {CodecMimeType} screenshareCodec - The preferred codec for screenshare.\n * @returns {void}\n */\nTraceablePeerConnection.prototype.setVideoCodecs = function(codecList, screenshareCodec) {\n if (!this.codecSettings || !codecList?.length) {\n return;\n }\n\n this.codecSettings.codecList = codecList;\n if (screenshareCodec) {\n this.codecSettings.screenshareCodec = screenshareCodec;\n }\n\n if (this.usesCodecSelectionAPI()) {\n this.configureVideoSenderEncodings();\n }\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 */\nTraceablePeerConnection.prototype.removeTrack = function(localTrack) {\n const webRtcStream = localTrack.getOriginalStream();\n\n this.trace(\n 'removeStream',\n localTrack.rtcId, 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 this.peerconnection.removeStream(webRtcStream);\n }\n};\n\n/**\n * Returns the sender corresponding to the given media type.\n * @param {MEDIA_TYPE} mediaType - The media type 'audio' or 'video' to be used for the search.\n * @returns {RTPSender|undefined} - The found sender or undefined if no sender\n * was found.\n */\nTraceablePeerConnection.prototype.findSenderByKind = function(mediaType) {\n if (this.peerconnection.getSenders) {\n return this.peerconnection.getSenders().find(s => s.track && s.track.kind === mediaType);\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 {RTCRtpReceiver|undefined} - The found receiver or undefined if no receiver\n * was found.\n */\nTraceablePeerConnection.prototype.findReceiverForTrack = function(track) {\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 {RTCRtpSender|undefined} - The found sender or undefined if no sender\n * was found.\n */\nTraceablePeerConnection.prototype.findSenderForTrack = function(track) {\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} localTracks - local tracks that are added to the peerconnection.\n * @returns {void}\n */\nTraceablePeerConnection.prototype.processLocalSdpForTransceiverInfo = function(localTracks) {\n const localSdp = this.peerconnection.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 oldTrack with newTrack from the peer connection.\n * Either oldTrack or newTrack can be null; replacing a valid\n * oldTrack with a null newTrack effectively just removes\n * oldTrack\n *\n * @param {JitsiLocalTrack|null} oldTrack - The current track in use to be replaced on the pc.\n * @param {JitsiLocalTrack|null} newTrack - The new track to be used.\n *\n * @returns {Promise} - If the promise resolves with true, renegotiation will be needed.\n * Otherwise no renegotiation is needed.\n */\nTraceablePeerConnection.prototype.replaceTrack = function(oldTrack, newTrack) {\n if (!(oldTrack || newTrack)) {\n logger.info(`${this} replaceTrack called with no new track and no old track`);\n\n return Promise.resolve();\n }\n\n logger.info(`${this} TPC.replaceTrack old=${oldTrack}, new=${newTrack}`);\n\n return this.tpcUtils.replaceTrack(oldTrack, newTrack)\n .then(transceiver => {\n if (oldTrack) {\n this.localTracks.delete(oldTrack.rtcId);\n this._localTrackTransceiverMids.delete(oldTrack.rtcId);\n }\n\n if (newTrack) {\n if (newTrack.isAudioTrack()) {\n this._hasHadAudioTrack = true;\n } else {\n this._hasHadVideoTrack = true;\n }\n this._localTrackTransceiverMids.set(newTrack.rtcId, transceiver?.mid?.toString());\n this.localTracks.set(newTrack.rtcId, newTrack);\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\n if (transceiver) {\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 back to the approach of not removing the track for FF and instead using the\n // enabled property for mute or stopping screensharing 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 transceiver.direction\n = newTrack || browser.isFirefox() ? MediaDirection.SENDRECV : MediaDirection.RECVONLY;\n }\n\n // Avoid re-configuring the encodings on Chromium/Safari, this is needed only on Firefox.\n const configureEncodingsPromise\n = !newTrack || browser.usesSdpMungingForSimulcast()\n ? Promise.resolve()\n : this.tpcUtils.setEncodings(newTrack);\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} 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 */\nTraceablePeerConnection.prototype.removeTrackFromPc = function(localTrack) {\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.tpcUtils.replaceTrack(localTrack, null).then(() => false);\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 */\nTraceablePeerConnection.prototype.usesCodecSelectionAPI = function() {\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\nTraceablePeerConnection.prototype.createDataChannel = function(label, opts) {\n this.trace('createDataChannel', label, opts);\n\n return this.peerconnection.createDataChannel(label, opts);\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 instance for the remote description.\n * @returns the transformed remoteDescription.\n * @private\n */\nTraceablePeerConnection.prototype._adjustRemoteMediaDirection = function(remoteDescription) {\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, 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 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 type: remoteDescription.type,\n sdp: transformer.toRawSDP()\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 */\nTraceablePeerConnection.prototype._getPreferredCodecForScreenshare = function(defaultCodec) {\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 * Munges the stereo flag as well as the opusMaxAverageBitrate in the SDP, based\n * on values set through config.js, if present.\n *\n * @param {RTCSessionDescription} description that needs to be munged.\n * @returns {RTCSessionDescription} the munged description.\n */\nTraceablePeerConnection.prototype._mungeOpus = function(description) {\n const { audioQuality } = this.options;\n\n if (!audioQuality?.enableOpusDtx && !audioQuality?.stereo && !audioQuality?.opusMaxAverageBitrate) {\n return description;\n }\n\n const parsedSdp = transform.parse(description.sdp);\n const mLines = parsedSdp.media;\n\n for (const mLine of mLines) {\n if (mLine.type === 'audio') {\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 payload,\n config: ''\n };\n }\n\n const fmtpConfig = transform.parseParams(fmtpOpus.config);\n let sdpChanged = false;\n\n if (audioQuality?.stereo) {\n fmtpConfig.stereo = 1;\n sdpChanged = true;\n }\n\n if (audioQuality?.opusMaxAverageBitrate) {\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\n return new RTCSessionDescription({\n type: description.type,\n sdp: transform.write(parsedSdp)\n });\n};\n\n/**\n * Munges the SDP to set all directions to inactive and drop all ssrc and ssrc-groups.\n *\n * @param {RTCSessionDescription} description that needs to be munged.\n * @returns {RTCSessionDescription} the munged description.\n */\nTraceablePeerConnection.prototype._mungeInactive = function(description) {\n const parsedSdp = transform.parse(description.sdp);\n const mLines = parsedSdp.media;\n\n for (const mLine of mLines) {\n mLine.direction = MediaDirection.INACTIVE;\n mLine.ssrcs = undefined;\n mLine.ssrcGroups = undefined;\n }\n\n return new RTCSessionDescription({\n type: description.type,\n sdp: transform.write(parsedSdp)\n });\n};\n\n/**\n * Sets up the _dtlsTransport object and initializes callbacks for it.\n */\nTraceablePeerConnection.prototype._initializeDtlsTransport = function() {\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 * Sets the max bitrates on the video m-lines when VP9/AV1 is the selected codec.\n *\n * @param {RTCSessionDescription} description - The local description 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 RTCSessionDescription\n */\nTraceablePeerConnection.prototype._setMaxBitrates = function(description, isLocalSdp = false) {\n if (!this.codecSettings) {\n return description;\n }\n const parsedSdp = transform.parse(description.sdp);\n\n // Find all the m-lines associated with the local sources.\n const direction = isLocalSdp ? MediaDirection.RECVONLY : MediaDirection.SENDONLY;\n const mLines = parsedSdp.media.filter(m => m.type === MediaType.VIDEO && m.direction !== direction);\n const currentCodec = this.codecSettings.codecList[0];\n const codecScalabilityModeSettings = this.tpcUtils.codecSettings[currentCodec];\n\n for (const mLine of mLines) {\n const isDoingVp9KSvc = currentCodec === CodecMimeType.VP9\n && !codecScalabilityModeSettings.scalabilityModeEnabled;\n const localTrack = this.getLocalVideoTracks()\n .find(track => this._localTrackTransceiverMids.get(track.rtcId) === mLine.mid.toString());\n\n if ((isDoingVp9KSvc || this.tpcUtils._isRunningInFullSvcMode(currentCodec)) && localTrack) {\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 type: 'AS',\n limit\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 new RTCSessionDescription({\n type: description.type,\n sdp: transform.write(parsedSdp)\n });\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 */\nTraceablePeerConnection.prototype.calculateExpectedSendResolution = function(localTrack) {\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();\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 {JitsiLocalTrack} localAudioTrack - The local audio track.\n * @returns {Promise} promise that will be resolved when the operation is successful and rejected otherwise.\n */\nTraceablePeerConnection.prototype.configureAudioSenderEncodings = function(localAudioTrack = null) {\n if (localAudioTrack) {\n return this.tpcUtils.setEncodings(localAudioTrack);\n }\n const promises = [];\n\n for (const track of this.getLocalTracks(MediaType.AUDIO)) {\n promises.push(this.tpcUtils.setEncodings(track));\n }\n\n return Promise.allSettled(promises);\n};\n\n/**\n * Configures the stream encodings depending on the video type, scalability mode and the bitrate settings for the codec\n * that is currently selected.\n *\n * @param {JitsiLocalTrack} - The local track for which the sender encodings have to configured.\n * @returns {Promise} promise that will be resolved when the operation is successful and rejected otherwise.\n */\nTraceablePeerConnection.prototype.configureVideoSenderEncodings = function(localVideoTrack = null) {\n const preferredCodec = this.codecSettings.codecList[0];\n\n if (localVideoTrack) {\n return this.setSenderVideoConstraints(\n this._senderMaxHeights.get(localVideoTrack.getSourceName()),\n localVideoTrack,\n 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\nTraceablePeerConnection.prototype.setLocalDescription = function(description) {\n let localDescription = description;\n\n this.trace('setLocalDescription::preTransform', dumpSDP(localDescription));\n\n // Munge stereo flag and opusMaxAverageBitrate based on config.js\n localDescription = this._mungeOpus(localDescription);\n\n // Munge the order of the codecs based on the preferences set through config.js.\n localDescription = this._mungeCodecOrder(localDescription);\n localDescription = this._setMaxBitrates(localDescription, true);\n localDescription = this._updateAv1DdHeaders(localDescription);\n\n this.trace('setLocalDescription::postTransform', dumpSDP(localDescription));\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 this.eventEmitter.emit(RTCEvents.SET_LOCAL_DESCRIPTION_FAILED, err, this);\n reject(err);\n });\n });\n};\n\nTraceablePeerConnection.prototype.setRemoteDescription = function(description) {\n let remoteDescription = description;\n\n this.trace('setRemoteDescription::preTransform', dumpSDP(description));\n\n // Munge stereo flag and opusMaxAverageBitrate based on config.js\n remoteDescription = this._mungeOpus(remoteDescription);\n\n if (!this.isP2P) {\n const currentDescription = this.peerconnection.remoteDescription;\n\n remoteDescription = this.interop.toUnifiedPlan(remoteDescription, currentDescription);\n this.trace('setRemoteDescription::postTransform (Unified)', dumpSDP(remoteDescription));\n }\n if (this.isSpatialScalabilityOn()) {\n remoteDescription = this.tpcUtils.insertUnifiedPlanSimulcastReceive(remoteDescription);\n this.trace('setRemoteDescription::postTransform (sim receive)', dumpSDP(remoteDescription));\n }\n remoteDescription = this.tpcUtils.ensureCorrectOrderOfSsrcs(remoteDescription);\n this.trace('setRemoteDescription::postTransform (correct ssrc order)', dumpSDP(remoteDescription));\n\n // Munge the order of the codecs based on the preferences set through config.js.\n remoteDescription = this._mungeCodecOrder(remoteDescription);\n remoteDescription = this._setMaxBitrates(remoteDescription);\n remoteDescription = this._updateAv1DdHeaders(remoteDescription);\n this.trace('setRemoteDescription::postTransform (munge codec order)', dumpSDP(remoteDescription));\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 }, err => {\n this.trace('setRemoteDescriptionOnFailure', err);\n this.eventEmitter.emit(RTCEvents.SET_REMOTE_DESCRIPTION_FAILED, err, this);\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 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 sender associated with the video source.\n * @returns {Promise} promise that will be resolved when the operation is successful and rejected otherwise.\n */\nTraceablePeerConnection.prototype.setSenderVideoConstraints = function(frameHeight, localVideoTrack, preferredCodec) {\n if (frameHeight < 0 || isNaN(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 // Ignore sender constraints if the video track is muted.\n if (localVideoTrack.isMuted()) {\n this._senderMaxHeights.set(sourceName, frameHeight);\n\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 * Returns a wrapped-up promise so that the setParameters() call on the RTCRtpSender for video sources are chained.\n * This is needed on Chrome as it resets the transaction id after 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 */\nTraceablePeerConnection.prototype._updateVideoSenderParameters = function(nextFunction) {\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 the sender associated with the video source.\n * @returns {Promise} promise that will be resolved when the operation is successful and rejected otherwise.\n */\nTraceablePeerConnection.prototype._updateVideoSenderEncodings = function(frameHeight, localVideoTrack, preferredCodec) {\n const videoSender = this.findSenderForTrack(localVideoTrack.getTrack());\n const isScreensharingTrack = localVideoTrack.getVideoType() === VideoType.DESKTOP;\n\n if (!videoSender) {\n return Promise.resolve();\n }\n const parameters = videoSender.getParameters();\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.getConfiguredVideoCodec(localVideoTrack);\n const codec = isScreensharingTrack ? this._getPreferredCodecForScreenshare(codecForCamera) : codecForCamera;\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 const sourceName = localVideoTrack.getSourceName();\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 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 && 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 {\n active = undefined,\n codec: currentCodec = undefined,\n maxBitrate = undefined,\n scalabilityMode = undefined,\n scaleResolutionDownBy = undefined\n } = parameters.encodings[idx];\n\n if (active !== activeState[idx]) {\n parameters.encodings[idx].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() && (parameters.encodings[idx].degradationPreference = preference);\n\n if (scaleResolutionDownBy !== scaleFactors[idx]) {\n parameters.encodings[idx].scaleResolutionDownBy = scaleFactors[idx];\n needsUpdate = true;\n }\n if (maxBitrate !== bitrates[idx]) {\n parameters.encodings[idx].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 parameters.encodings[idx].scalabilityMode = scalabilityModes[idx];\n needsUpdate = true;\n }\n } else {\n parameters.encodings[idx].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 parameters.encodings[idx].codec = matchingCodec;\n needsUpdate = true;\n }\n }\n }\n\n if (!needsUpdate) {\n this._senderMaxHeights.set(sourceName, frameHeight);\n\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 this._senderMaxHeights.set(sourceName, frameHeight);\n localVideoTrack.maxEnabledResolution = frameHeight;\n this.eventEmitter.emit(RTCEvents.LOCAL_TRACK_MAX_ENABLED_RESOLUTION_CHANGED, localVideoTrack);\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 true to enable video media transmission or false 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 */\nTraceablePeerConnection.prototype.setVideoTransferActive = function(active) {\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.tpcUtils.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 */\nTraceablePeerConnection.prototype.sendTones = function(tones, duration = 200, interToneGap = 200) {\n if (!this._dtmfSender) {\n if (this.peerconnection.getSenders) {\n const rtpSender = this.peerconnection.getSenders().find(s => s.dtmf);\n\n this._dtmfSender = rtpSender && 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 if (this.peerconnection.createDTMFSender && localAudioTrack) {\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 tones,\n duration,\n interToneGap\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 * 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 */\nTraceablePeerConnection.prototype._onToneChange = function(event) {\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 * 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 */\nTraceablePeerConnection.prototype.close = function() {\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\nTraceablePeerConnection.prototype.createAnswer = function(constraints) {\n return this._createOfferOrAnswer(false /* answer */, constraints);\n};\n\nTraceablePeerConnection.prototype.createOffer = function(constraints) {\n return this._createOfferOrAnswer(true /* offer */, constraints);\n};\n\nTraceablePeerConnection.prototype._createOfferOrAnswer = function(\n isOffer,\n constraints) {\n const logName = isOffer ? 'Offer' : 'Answer';\n\n this.trace(`create${logName}`, JSON.stringify(constraints, null, ' '));\n\n const handleSuccess = (resultSdp, resolveFn, rejectFn) => {\n try {\n this.trace(\n `create${logName}OnSuccess::preTransform`, 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)`, dumpSDP(resultSdp));\n }\n\n if (!this.options.disableRtx && browser.usesSdpMungingForSimulcast()) {\n // eslint-disable-next-line no-param-reassign\n resultSdp = new RTCSessionDescription({\n type: resultSdp.type,\n sdp: this.rtxModifier.modifyRtxSsrcs(resultSdp.sdp)\n });\n\n this.trace(\n `create${logName}`\n + 'OnSuccess::postTransform (rtx modifier)',\n dumpSDP(resultSdp));\n }\n\n const ssrcMap = this._extractSSRCMap(resultSdp);\n\n this._processLocalSSRCsMap(ssrcMap);\n\n resolveFn(resultSdp);\n } catch (e) {\n this.trace(`create${logName}OnError`, e);\n this.trace(`create${logName}OnError`, dumpSDP(resultSdp));\n logger.error(`${this} create${logName}OnError`, e, dumpSDP(resultSdp));\n\n rejectFn(e);\n }\n };\n\n const handleFailure = (err, rejectFn) => {\n this.trace(`create${logName}OnFailure`, err);\n const eventType\n = isOffer\n ? RTCEvents.CREATE_OFFER_FAILED\n : RTCEvents.CREATE_ANSWER_FAILED;\n\n this.eventEmitter.emit(eventType, err, this);\n\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 TrackSSRCInfo} object.\n * @param {TrackSSRCInfo} ssrcObj\n * @return {number|null} the primary SSRC or null\n */\nTraceablePeerConnection.prototype._extractPrimarySSRC = function(ssrcObj) {\n if (ssrcObj && ssrcObj.groups && ssrcObj.groups.length) {\n return ssrcObj.groups[0].ssrcs[0];\n } else if (ssrcObj && ssrcObj.ssrcs && ssrcObj.ssrcs.length) {\n return ssrcObj.ssrcs[0];\n }\n\n return null;\n};\n\n/**\n * Goes over the SSRC map extracted from the latest local description and tries\n * to match them with the local tracks (by MSID). Will update the values\n * currently stored in the {@link TraceablePeerConnection.localSSRCs} map.\n * @param {Map} ssrcMap\n * @private\n */\nTraceablePeerConnection.prototype._processLocalSSRCsMap = function(ssrcMap) {\n for (const track of this.localTracks.values()) {\n const sourceName = track.getSourceName();\n const sourceIndex = getSourceIndexFromSourceName(sourceName);\n const sourceIdentifier = `${track.getType()}-${sourceIndex}`;\n\n if (ssrcMap.has(sourceIdentifier)) {\n const newSSRC = ssrcMap.get(sourceIdentifier);\n\n if (!newSSRC) {\n logger.error(`${this} No SSRC found for stream=${sourceIdentifier}`);\n\n return;\n }\n const oldSSRC = this.localSSRCs.get(track.rtcId);\n const newSSRCNum = this._extractPrimarySSRC(newSSRC);\n const oldSSRCNum = this._extractPrimarySSRC(oldSSRC);\n\n // eslint-disable-next-line no-negated-condition\n if (newSSRCNum !== oldSSRCNum) {\n oldSSRCNum && logger.error(`${this} Overwriting SSRC for track=${track}] with ssrc=${newSSRC}`);\n this.localSSRCs.set(track.rtcId, newSSRC);\n track.setSsrc(newSSRCNum);\n this.eventEmitter.emit(RTCEvents.LOCAL_TRACK_SSRC_UPDATED, track, newSSRCNum);\n }\n } else if (!track.isVideoTrack() && !track.isMuted()) {\n // It is normal to find no SSRCs for a muted video track in\n // the local SDP as the recv-only SSRC is no longer munged in.\n // So log the warning only if it's not a muted video track.\n logger.warn(`${this} No SSRCs found in the local SDP for track=${track}, stream=${sourceIdentifier}`);\n }\n }\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 */\nTraceablePeerConnection.prototype.addRemoteSsrc = function(ssrc) {\n const existing = this.remoteSSRCs.has(ssrc);\n\n if (!existing) {\n this.remoteSSRCs.add(ssrc);\n }\n\n return !existing;\n};\n\nTraceablePeerConnection.prototype.addIceCandidate = function(candidate) {\n this.trace('addIceCandidate', JSON.stringify({\n candidate: candidate.candidate,\n sdpMid: candidate.sdpMid,\n sdpMLineIndex: candidate.sdpMLineIndex,\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} Promise which resolves with data providing statistics about\n * the peerconnection.\n */\nTraceablePeerConnection.prototype.getStats = function() {\n return this.peerconnection.getStats();\n};\n\n/**\n * Creates a text representation of this TraceablePeerConnection\n * instance.\n * @return {string}\n */\nTraceablePeerConnection.prototype.toString = function() {\n return `TPC[id=${this.id},type=${this.isP2P ? 'P2P' : 'JVB'}]`;\n};\n","import { getLogger } from '@jitsi/logger';\nimport clonedeep from 'lodash.clonedeep';\n\nimport * as JitsiConferenceEvents from '../../JitsiConferenceEvents';\nimport { MediaType } from '../../service/RTC/MediaType';\nimport RTCEvents from '../../service/RTC/RTCEvents';\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(__filename);\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 * MediaStreamTracks.\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 facingMode,\n mediaType: track.kind,\n rtcId: rtcTrackIdCounter,\n sourceId,\n sourceType,\n stream,\n track,\n videoType: videoType || null,\n effects\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 TraceablePeerConnection.\n * @type {Map.}\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|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} tracksInfo\n * @returns {Array}\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 this._receiverVideoConstraints = 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 TraceablePeerConnection\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} 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 = clonedeep(RTCUtils.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} true if the given peer connection was removed\n * successfully or false 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|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}\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 let tracks = this.localTracks.slice();\n\n if (mediaType !== undefined) {\n tracks = tracks.filter(\n track => track.getType() === mediaType);\n }\n\n return tracks;\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}\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 * @param value The mute value.\n * @returns {Promise}\n */\n setAudioMute(value) {\n const mutePromises = [];\n\n this.getLocalTracks(MediaType.AUDIO).forEach(audioTrack => {\n // this is a Promise\n mutePromises.push(value ? audioTrack.mute() : audioTrack.unmute());\n });\n\n // We return a Promise from all Promises so we can wait for their\n // execution.\n return Promise.all(mutePromises);\n }\n\n /**\n * Set mute for all local video streams attached to the conference.\n * @param value The mute value.\n * @returns {Promise}\n */\n setVideoMute(value) {\n const mutePromises = [];\n\n this.getLocalTracks(MediaType.VIDEO)\n .forEach(videoTrack => {\n // this is a Promise\n mutePromises.push(value ? videoTrack.mute() : videoTrack.unmute());\n });\n\n // We return a Promise from all Promises so we can wait for their\n // execution.\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 retrieving the list of input devices is supported\n * and false if not.\n */\n static isDeviceListAvailable() {\n return RTCUtils.isDeviceListAvailable();\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 whether available devices have permissions granted\n * @returns {Boolean}\n */\n static arePermissionsGrantedForAvailableDevices() {\n return RTCUtils.arePermissionsGrantedForAvailableDevices();\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 * 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 * 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\n// exported for backward compatibility\nexport const LOCAL_STATS_UPDATED = ConnectionQualityEvents.LOCAL_STATS_UPDATED;\nexport const REMOTE_STATS_UPDATED = ConnectionQualityEvents.REMOTE_STATS_UPDATED;\n\n","import { getLogger } from '@jitsi/logger';\n\nimport * as ConferenceEvents from '../../JitsiConferenceEvents';\nimport * as RTCEvents from '../../service/RTC/RTCEvents';\nimport { VIDEO_QUALITY_LEVELS } from '../../service/RTC/StandardVideoQualitySettings';\nimport * as ConnectionQualityEvents from '../../service/connectivity/ConnectionQualityEvents';\n\nconst Resolutions = require('../../service/RTC/Resolutions');\nconst { VideoType } = require('../../service/RTC/VideoType');\nconst { XMPPEvents } = require('../../service/xmpp/XMPPEvents');\n\nconst logger = getLogger(__filename);\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 */\nlet 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, resolution, millisSinceStart, bitrates) {\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) {\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\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 /**\n *\n * @param conference\n * @param eventEmitter\n * @param options\n */\n constructor(conference, eventEmitter, options) {\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 // We assume a global startBitrate value for the sake of simplicity.\n if (this._options.config?.startBitrate > 0) {\n startBitrate = this._options.config.startBitrate;\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(\n ConnectionQualityEvents.LOCAL_STATS_UPDATED,\n this._localStats);\n this._broadcastLocalStats();\n });\n\n conference.room.addListener(\n XMPPEvents.ICE_CONNECTION_STATE_CHANGED,\n (jingleSession, newState) => {\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, payload) => {\n if (payload.type === STATS_MESSAGE_TYPE) {\n this._updateRemoteStats(\n participant.getId(), payload.values);\n }\n });\n\n conference.on(\n ConferenceEvents.ENDPOINT_STATS_RECEIVED,\n (participant, payload) => {\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 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 * Sets _timeVideoUnmuted if it was previously unset. If it was already set,\n * doesn't change it.\n */\n _maybeUpdateUnmuteTime() {\n if (this._timeVideoUnmuted < 0) {\n this._timeVideoUnmuted = window.performance.now();\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 _calculateConnectionQuality(videoType, isMuted, resolutionName) {\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\n if (this._localStats.packetLoss) {\n packetLoss = this._localStats.packetLoss.upload;\n\n // Ugly Hack Alert (UHA):\n // The packet loss for the upload direction is calculated based on\n // incoming RTCP Receiver Reports. Since we don't have RTCP\n // termination for audio, these reports come from the actual\n // receivers in the conference and therefore the reported packet\n // loss includes loss from the bridge to the receiver.\n // When we are sending video this effect is small, because the\n // number of video packets is much larger than the number of audio\n // packets (and our calculation is based on the total number of\n // received and lost packets).\n // When video is muted, however, the effect might be significant,\n // but we don't know what it is. We do know that it is positive, so\n // as a temporary solution, until RTCP termination is implemented\n // for the audio streams, we relax the packet loss checks here.\n if (isMuted) {\n packetLoss *= 0.5;\n }\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(),\n resolution,\n millisSinceStart,\n activeTPC.getTargetVideoBitrates());\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 * Updates the localConnectionQuality value\n * @param values {number} the new value. Should be in [0, 100].\n */\n _updateLocalConnectionQuality(value) {\n this._localStats.connectionQuality = value;\n this._lastConnectionQualityUpdate = window.performance.now();\n }\n\n /**\n * Broadcasts the local statistics to all other participants in the\n * conference.\n */\n _broadcastLocalStats() {\n // Send only the data that remote participants care about.\n const data = {\n bitrate: this._localStats.bitrate,\n packetLoss: this._localStats.packetLoss,\n connectionQuality: this._localStats.connectionQuality,\n jvbRTT: this._localStats.jvbRTT,\n serverRegion: this._localStats.serverRegion,\n maxEnabledResolution: this._localStats.maxEnabledResolution\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 * Updates the local statistics\n * @param {TraceablePeerConnection} tpc the peerconnection which emitted\n * the stats\n * @param data new statistics\n */\n _updateLocalStats(tpc, data) {\n // Update jvbRTT\n if (!tpc.isP2P) {\n const jvbRTT\n = data.transport\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\n = !this._conference.isConnectionInterrupted();\n const localVideoTrack\n = this._conference.getLocalVideoTrack();\n const videoType\n = localVideoTrack ? localVideoTrack.videoType : undefined;\n const isMuted = localVideoTrack ? localVideoTrack.isMuted() : true;\n const resolution = localVideoTrack\n ? Math.min(localVideoTrack.resolution, localVideoTrack.maxEnabledResolution) : 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 this._localStats[key] = data[key];\n }\n }\n\n // And re-calculate the connectionQuality field.\n if (updateLocalConnectionQuality) {\n this._updateLocalConnectionQuality(\n this._calculateConnectionQuality(\n videoType,\n isMuted,\n resolution));\n }\n\n this.eventEmitter.emit(\n ConnectionQualityEvents.LOCAL_STATS_UPDATED,\n 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 _updateRemoteStats(id, data) {\n // Use only the fields we need\n this._remoteStats[id] = {\n bitrate: data.bitrate,\n packetLoss: data.packetLoss,\n connectionQuality: data.connectionQuality,\n jvbRTT: data.jvbRTT,\n serverRegion: data.serverRegion,\n maxEnabledResolution: data.maxEnabledResolution\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 getStats() {\n return this._localStats;\n }\n}\n","import { getLogger } from '@jitsi/logger';\n\nimport * as JitsiConferenceErrors from '../../JitsiConferenceErrors';\nimport * as JitsiConferenceEvents from '../../JitsiConferenceEvents';\n\nconst logger = getLogger(__filename);\n\n/**\n * This class deals with shenanigans around JVB media session's ICE failed status handling.\n *\n * If ICE restarts are NOT explicitly enabled by the {@code enableIceRestart} config option, then the conference will\n * delay emitting the {@JitsiConferenceErrors.ICE_FAILED} event by 15 seconds. If the network info module reports\n * the internet offline status then the time will start counting after the internet comes back online.\n *\n * If ICE restart are enabled, then a delayed ICE failed notification to Jicofo will be sent, only if the ICE connection\n * does not recover soon after or before the XMPP connection is restored (if it was ever broken). If ICE fails while\n * the XMPP connection is not broken then the notifications will be sent after 2 seconds delay.\n */\nexport default class IceFailedHandling {\n /**\n * Creates new {@code DelayedIceFailed} task.\n * @param {JitsiConference} conference\n */\n constructor(conference) {\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() {\n if (!this._conference.room) {\n return;\n }\n\n const { enableForcedReload, enableIceRestart } = this._conference.options.config;\n const explicitlyDisabled = typeof enableIceRestart !== 'undefined' && !enableIceRestart;\n const supportsRestartByTerminate = this._conference.room.supportsRestartByTerminate();\n const useTerminateForRestart = supportsRestartByTerminate && !enableIceRestart;\n\n logger.info('ICE failed,'\n + ` enableForcedReload: ${enableForcedReload},`\n + ` enableIceRestart: ${enableIceRestart},`\n + ` supports restart by terminate: ${supportsRestartByTerminate}`);\n\n if (explicitlyDisabled || (!enableIceRestart && !supportsRestartByTerminate) || enableForcedReload) {\n logger.info('ICE failed, but ICE restarts are disabled');\n const reason = enableForcedReload\n ? JitsiConferenceErrors.CONFERENCE_RESTARTED\n : JitsiConferenceErrors.ICE_FAILED;\n\n this._conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_FAILED, reason);\n\n return;\n }\n\n const jvbConnection = this._conference.jvbJingleSession;\n const jvbConnIceState = jvbConnection && 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, '\n + `ICE state: ${jvbConnIceState}, `\n + `use 'session-terminate': ${useTerminateForRestart}`);\n if (useTerminateForRestart) {\n this._conference._stopJvbSession({\n reason: 'connectivity-error',\n reasonDescription: 'ICE FAILED',\n requestRestart: true,\n sendSessionTerminate: true\n });\n } else {\n this._conference.jvbJingleSession.sendIceFailedNotification();\n }\n }\n }\n\n /**\n * Starts the task.\n */\n start() {\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 */\n cancel() {\n this._canceled = true;\n window.clearTimeout(this._iceFailedTimeout);\n }\n}\n","export enum DetectionEvents {\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 {@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 /** Event triggered by NoAudioSignalDetector when the local audio device associated with a JitsiConference goes silent\n * 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, one score for each monitored device.\n * @event VAD_REPORT_PUBLISHED\n * @type Array 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\n// exported for backward compatibility\nexport const DETECTOR_STATE_CHANGE = DetectionEvents.DETECTOR_STATE_CHANGE;\nexport const AUDIO_INPUT_STATE_CHANGE = DetectionEvents.AUDIO_INPUT_STATE_CHANGE;\nexport const NO_AUDIO_INPUT = DetectionEvents.NO_AUDIO_INPUT;\nexport const VAD_NOISY_DEVICE = DetectionEvents.VAD_NOISY_DEVICE;\nexport const VAD_REPORT_PUBLISHED = DetectionEvents.VAD_REPORT_PUBLISHED;\nexport const VAD_SCORE_PUBLISHED = DetectionEvents.VAD_SCORE_PUBLISHED;\nexport const VAD_TALK_WHILE_MUTED = DetectionEvents.VAD_TALK_WHILE_MUTED;\n","import * as JitsiConferenceEvents from '../../JitsiConferenceEvents';\nimport * as JitsiTrackEvents from '../../JitsiTrackEvents';\nimport EventEmitter from '../util/EventEmitter';\n\nimport * as 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 /**\n * Creates new NoAudioSignalDetection.\n *\n * @param conference the JitsiConference instance that created us.\n * @constructor\n */\n constructor(conference) {\n super();\n\n this._conference = conference;\n this._timeoutTrigger = null;\n this._hasAudioInput = null;\n\n conference.on(JitsiConferenceEvents.TRACK_ADDED, this._trackAdded.bind(this));\n }\n\n /**\n * Clear the timeout state.\n */\n _clearTriggerTimeout() {\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 {*} audioLevel - The audio level of the ssrc.\n * @fires DetectionEvents.AUDIO_INPUT_STATE_CHANGE\n */\n _handleAudioInputStateChange(audioLevel) {\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 _handleNoAudioInputDetection(audioLevel) {\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 _audioLevel(tpc, ssrc, audioLevel, isLocal) {\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 || !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 _trackAdded(track) {\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 => {\n this._handleNoAudioInputDetection(audioLevel);\n }\n );\n track.on(\n JitsiTrackEvents.TRACK_AUDIO_LEVEL_CHANGED,\n audioLevel => {\n this._handleNoAudioInputDetection(audioLevel);\n this._handleAudioInputStateChange(audioLevel);\n }\n );\n }\n }\n}\n","import * as 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 = 0.6;\n\n/**\n * The P2PDominantSpeakerDetection 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 /**\n * Creates P2PDominantSpeakerDetection\n * @param conference the JitsiConference instance that created us.\n * @constructor\n */\n constructor(conference) {\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 _audioLevel(id, audioLevel) {\n\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 {AudioContext} - Return a new AudioContext or undefined if the browser does not support it.\n */\nexport function createAudioContext(options) {\n const AudioContextImpl = window.AudioContext || window.webkitAudioContext;\n\n if (!AudioContextImpl) {\n return undefined;\n }\n\n return new AudioContextImpl(options);\n}\n","import RTC from '../RTC/RTC';\nimport EventEmitter from '../util/EventEmitter';\nimport { createAudioContext } from '../webaudio/WebAudioUtils';\n\nimport { VAD_SCORE_PUBLISHED } from './DetectionEvents';\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 /**\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, vadProcessor, 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 * - getSampleLength() - Returns the sample size accepted by getSampleLength.\n * - getRequiredPCMFrequency() - Returns the PCM frequency at which the processor operates.\n * - calculateAudioFrameVAD(pcmSample) - Process a 32 float pcm sample of getSampleLength size.\n * @returns {Promise} - Promise resolving in a new instance of TrackVADEmitter.\n */\n static create(micDeviceId, procNodeSampleRate, vadProcessor) {\n return RTC.obtainAudioAndVideoPermissions({\n devices: [ 'audio' ],\n micDeviceId\n }).then(localTrack => {\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() {\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) {\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(VAD_SCORE_PUBLISHED, {\n timestamp: sampleTimestamp,\n score: vadScore,\n pcmData: pcmSample,\n deviceId: this._localTrack.getDeviceId()\n });\n }\n\n this._bufferResidue = 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() {\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() {\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 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() {\n this._disconnectAudioGraph();\n this._localTrack.stopStream();\n }\n\n /**\n * Get the associated track device ID.\n *\n * @returns {string}\n */\n getDeviceId() {\n return this._localTrack.getDeviceId();\n }\n\n\n /**\n * Get the associated track label.\n *\n * @returns {string}\n */\n getTrackLabel() {\n return this._localTrack.getDeviceLabel();\n }\n\n /**\n * Start the emitter by connecting the audio graph.\n *\n * @returns {void}\n */\n start() {\n this._connectAudioGraph();\n }\n\n /**\n * Stops the emitter by disconnecting the audio graph.\n *\n * @returns {void}\n */\n stop() {\n this._disconnectAudioGraph();\n this._bufferResidue = [];\n }\n\n /**\n * Destroy TrackVADEmitter instance (release resources and stop callbacks).\n *\n * @returns {void}\n */\n destroy() {\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 * as JitsiConferenceEvents from '../../JitsiConferenceEvents';\nimport EventEmitter from '../util/EventEmitter';\n\nimport { DETECTOR_STATE_CHANGE, VAD_SCORE_PUBLISHED } from './DetectionEvents';\nimport TrackVADEmitter from './TrackVADEmitter';\n\nconst logger = getLogger(__filename);\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 = 4096;\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 /**\n * Creates VADAudioAnalyser\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 * - getSampleLength() - Returns the sample size accepted by getSampleLength.\n * - getRequiredPCMFrequency() - Returns the PCM frequency at which the processor operates.\n * - calculateAudioFrameVAD(pcmSample) - Process a 32 float pcm sample of getSampleLength size.\n * @constructor\n */\n constructor(conference, createVADProcessor) {\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) {\n this._detectionServices.push(vadService);\n vadService.on(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() {\n if (this._vadEmitter) {\n this._vadEmitter.on(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() {\n if (this._vadEmitter) {\n this._vadEmitter.removeListener(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) {\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) {\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 {JitsiTrack} track - The added track.\n * @returns {void}\n * @listens TRACK_ADDED\n */\n _trackAdded(track) {\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 =>\n TrackVADEmitter.create(track.getDeviceId(), VAD_EMITTER_SAMPLE_RATE, vadProcessor)\n )\n .then(vadEmitter => {\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 {JitsiTrack} track - The track whose mute state has changed.\n * @returns {void}\n * @listens TRACK_MUTE_CHANGED\n */\n _trackMuteChanged(track) {\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 {JitsiTrack} track - The removed track.\n * @returns {void}\n * @listens TRACK_REMOVED\n */\n _trackRemoved(track) {\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\n}\n","import EventEmitter from '../util/EventEmitter';\nimport { calculateAverage, filterPositiveValues } from '../util/MathUtil';\n\nimport { DETECTOR_STATE_CHANGE, VAD_NOISY_DEVICE } from './DetectionEvents';\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 = 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 = 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 = 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 = 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 = 1500;\n\n/**\n * Detect if provided VAD score and PCM data is considered noise.\n */\nexport default class VADNoiseDetection extends EventEmitter {\n /**\n * Creates VADNoiseDetection\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 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 _calculateNoisyScore() {\n const scoreAvg = calculateAverage(this._scoreArray);\n const audioLevelAvg = calculateAverage(this._audioLvlArray);\n\n if (scoreAvg < VAD_NOISE_AVG_THRESHOLD && audioLevelAvg > NOISY_AUDIO_LEVEL_THRESHOLD) {\n this.emit(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 * 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 _recordValues(vadScore, avgAudioLvl) {\n this._scoreArray.push(vadScore);\n this._audioLvlArray.push(avgAudioLvl);\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 _setActiveState(active) {\n this._active = active;\n this.emit(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 changeMuteState(isMuted) {\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 isActive() {\n return this._active;\n }\n\n /**\n * Reset the processing context, clear buffers, cancel the timeout trigger.\n *\n * @returns {void}\n */\n reset() {\n this._processing = false;\n this._scoreArray = [];\n this._audioLvlArray = [];\n clearTimeout(this._processTimeout);\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 {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} 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 processVADScore(vadScore) {\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 posAudioLevels = filterPositiveValues(vadScore.pcmData);\n\n this._recordValues(vadScore.score, calculateAverage(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 posAudioLevels = filterPositiveValues(vadScore.pcmData);\n const avgAudioLvl = calculateAverage(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","import EventEmitter from '../util/EventEmitter';\nimport { calculateAverage } from '../util/MathUtil';\n\nimport { DETECTOR_STATE_CHANGE, VAD_TALK_WHILE_MUTED } from './DetectionEvents';\n\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\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 /**\n * Creates VADTalkMutedDetection\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\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 _calculateVADScore() {\n const score = calculateAverage(this._scoreArray);\n\n if (score > VAD_AVG_THRESHOLD) {\n this.emit(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 _setActiveState(active) {\n this._active = active;\n this.emit(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 changeMuteState(isMuted) {\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 isActive() {\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 {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 {string} vadScore.deviceId - Device id of the associated track.\n * @listens VAD_SCORE_PUBLISHED\n */\n processVADScore(vadScore) {\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 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 reset() {\n this._processing = false;\n this._scoreArray = [];\n clearTimeout(this._processTimeout);\n }\n}\n","export enum E2ePingEvents {\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\n// exported for backward compatibility\nexport const E2E_RTT_CHANGED = E2ePingEvents.E2E_RTT_CHANGED;\n","import { getLogger } from '@jitsi/logger';\n\nimport * as JitsiConferenceEvents from '../../JitsiConferenceEvents';\nimport * as JitsiE2EPingEvents from '../../service/e2eping/E2ePingEvents';\n\nconst logger = getLogger(__filename);\n\n/**\n * The 'type' of a message which designates an e2e ping request.\n * @type {string}\n */\nconst E2E_PING_REQUEST = '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 = 'e2e-ping-response';\n\n/**\n * The number of requests to wait for before emitting an RTT value.\n */\nconst DEFAULT_NUM_REQUESTS = 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 = 250;\n\n/**\n * The conference size beyond which e2e pings will be disabled.\n */\nconst DEFAULT_MAX_CONFERENCE_SIZE = 200;\n\n/**\n * Saves e2e ping related state for a single JitsiParticipant.\n */\nclass ParticipantWrapper {\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, 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() {\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() {\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() {\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() {\n const requestId = this.lastRequestId++;\n const requestMessage = {\n type: E2E_PING_REQUEST,\n id: requestId\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) {\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() {\n // The RTT we'll report is the minimum RTT measured\n let rtt = Infinity;\n let request, requestId;\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 JitsiE2EPingEvents.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 * @param {JitsiConference} conference - The conference.\n * @param {Function} sendMessage - The function to use to send a message.\n * @param {Object} options\n */\n constructor(conference, options, sendMessage) {\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 && 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() {\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, payload) {\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, participant) {\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) {\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) {\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, request) {\n // If it's a valid request, just send a response.\n if (request && request.id) {\n const response = {\n type: E2E_PING_RESPONSE,\n id: request.id\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, response) {\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() {\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\n","import { getLogger } from '@jitsi/logger';\n\nimport * as JitsiConferenceEvents from '../../JitsiConferenceEvents';\n\nconst logger = getLogger(__filename);\n\n/**\n * Emits {@link JitsiConferenceEvents.JVB121_STATUS} events based on the current\n * P2P status and the conference participants count. See the event description\n * for more info.\n */\nexport default class Jvb121EventGenerator {\n /**\n * Creates new Jvb121EventGenerator for the given conference.\n * @param {JitsiConference} conference\n */\n constructor(conference) {\n this._conference = conference;\n\n /**\n * Indicates whether it's a one to one JVB conference (true)\n * or a multiparty (false). Will be also false if\n * the conference is currently in the P2P mode.\n * @type {boolean}\n * @private\n */\n this._jvb121 = true;\n\n this._conference.addEventListener(\n JitsiConferenceEvents.USER_JOINED, () => this.evaluateStatus());\n this._conference.addEventListener(\n JitsiConferenceEvents.USER_LEFT, () => this.evaluateStatus());\n this._conference.addEventListener(\n JitsiConferenceEvents.P2P_STATUS, () => this.evaluateStatus());\n }\n\n /**\n * Checks whether the JVB121 value should be updated and a new event\n * emitted.\n */\n evaluateStatus() {\n const oldStatus = this._jvb121;\n const newStatus\n = !this._conference.isP2PActive()\n && this._conference.getParticipantCount() <= 2;\n\n if (oldStatus !== newStatus) {\n this._jvb121 = newStatus;\n logger.debug(`JVB121 status ${oldStatus} => ${newStatus}`);\n this._conference.eventEmitter.emit(\n JitsiConferenceEvents.JVB121_STATUS, oldStatus, newStatus);\n }\n }\n}\n","/* global TransformStream */\nimport { getLogger } from '@jitsi/logger';\n\nimport RTCEvents from '../../service/RTC/RTCEvents';\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(__filename);\n\n/**\n * This module implements a discard-all insertable stream. Use to reduce decoder CPU load for testing.\n */\nexport class LiteModeContext {\n /**\n * A constructor.\n * @param {JitsiConference} conference - The conference instance for which lite mode is to be enabled.\n */\n constructor(conference) {\n this.enabled = FeatureFlags.isRunInLiteModeEnabled();\n if (!this.enabled) {\n return;\n }\n\n conference.rtc.on(\n RTCEvents.REMOTE_TRACK_ADDED,\n (track, tpc) => this._setupLiteModeForTrack(tpc, track));\n }\n\n /**\n * Setup Lite Mode for a track.\n *\n * @private\n */\n _setupLiteModeForTrack(tpc, track) {\n if (!this.enabled) {\n return;\n }\n\n const receiver = tpc.findReceiverForTrack(track.track);\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","\nimport { getLogger } from '@jitsi/logger';\n\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 browser from '../browser';\n\nconst logger = getLogger(__filename);\n\n// Default video codec preferences on mobile and desktop endpoints.\nconst DESKTOP_VIDEO_CODEC_ORDER = [ CodecMimeType.VP9, CodecMimeType.VP8, CodecMimeType.H264, CodecMimeType.AV1 ];\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\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 /**\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, options) {\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 // eslint-disable-next-line prefer-const\n let { disabledCodec, preferredCodec, preferenceOrder, 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 VP9 to the end of the list so that the client continues to decode VP9 even if its not\n // preferable to encode VP9 (because of browser bugs on the encoding side or added complexity on mobile\n // devices). Currently, VP9 encode is supported on Chrome and on Safari (only for p2p).\n const isVp9EncodeSupported = browser.supportsVP9() || (browser.isWebKitBased() && connectionType === 'p2p');\n\n if (!isVp9EncodeSupported || this.conference.isE2EEEnabled()) {\n const index = selectedOrder.findIndex(codec => codec === CodecMimeType.VP9);\n\n if (index !== -1) {\n selectedOrder.splice(index, 1);\n\n // Remove VP9 from the list when E2EE is enabled since it is not supported.\n // TODO - remove this check when support for VP9-E2EE is introduced.\n if (!this.conference.isE2EEEnabled()) {\n selectedOrder.push(CodecMimeType.VP9);\n }\n }\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) {\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}\n */\n getCodecPreferenceList(connectionType) {\n return this.codecPreferenceOrder[connectionType];\n }\n\n /**\n * Returns the preferred screenshare codec for the given connection type.\n *\n * @param {String} connectionType The media connection type, 'p2p' or 'jvb'.\n * @returns CodecMimeType\n */\n getScreenshareCodec(connectionType) {\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) {\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((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\n if (!codecNotSupportedByRemote) {\n acc.push(localCodec);\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);\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, codec) {\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) {\n if (this.visitorCodecs === codecList) {\n return;\n }\n\n this.visitorCodecs = codecList;\n this.selectPreferredCodec();\n }\n}\n","import { getLogger } from '@jitsi/logger';\nimport isEqual from 'lodash.isequal';\n\nimport { MediaType } from '../../service/RTC/MediaType';\nimport { ASSUMED_BANDWIDTH_BPS, LAST_N_UNLIMITED } from '../../service/RTC/StandardVideoQualitySettings';\n\nconst logger = getLogger(__filename);\nconst MAX_HEIGHT = 2160;\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 /**\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) {\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\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(mediaSession, maxFrameHeight) {\n const height = maxFrameHeight ?? MAX_HEIGHT;\n const remoteVideoTracks = mediaSession.peerconnection?.getRemoteTracks(null, MediaType.VIDEO) || [];\n const receiverConstraints = new Map();\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 * @returns {void}\n */\n _updateIndividualConstraints() {\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 = 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 {Object}\n */\n getCurrentReceiverConstraints() {\n return this._receiverVideoConstraints;\n }\n\n /**\n * Returns the lastN value for the conference.\n *\n * @returns {number}\n */\n getLastN() {\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() {\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) {\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) {\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) {\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) {\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) {\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();\n this._rtc.setReceiverVideoConstraints(this._receiverVideoConstraints);\n }\n }\n }\n\n /**\n * Sets the receiver constraints for the conference.\n *\n * @param {Object} constraints The video constraints.\n */\n setReceiverConstraints(constraints) {\n if (!constraints) {\n return;\n }\n\n const isEndpointsFormat = Object.keys(constraints).includes('onStageEndpoints', 'selectedEndpoints');\n\n if (isEndpointsFormat) {\n throw new Error(\n '\"onStageEndpoints\" and \"selectedEndpoints\" are not supported when sourceNameSignaling is enabled.'\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 contraints 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 = Array.from(Object.entries(this._receiverVideoConstraints.constraints))\n .map(constraint => {\n constraint[1] = constraint[1].maxHeight;\n\n return constraint;\n });\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 {booem} enabled\n * @return {void}\n */\n setReceiveResolutionLimitedByCpu(enabled) {\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 MediaSessionEvents from '../xmpp/MediaSessionEvents';\n\nconst logger = getLogger(__filename);\nconst MAX_LOCAL_RESOLUTION = 2160;\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 /**\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) {\n this._conference = conference;\n this._preferredSendMaxFrameHeight = MAX_LOCAL_RESOLUTION;\n\n /**\n * Source name based sender constraints.\n * @type {Map};\n */\n this._sourceSenderConstraints = new Map();\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}\n * @private\n */\n _propagateSendMaxFrameHeight(sourceName) {\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 >= 0) {\n for (const session of this._conference.getMediaSessions()) {\n promises.push(session.setSenderVideoConstraint(sendMaxFrameHeight, sourceName));\n }\n }\n\n return 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 {number|undefined}\n * @private\n */\n _selectSendMaxFrameHeight(sourceName) {\n if (!sourceName) {\n throw new Error('sourceName missing for calculating the sendMaxHeight for video tracks');\n }\n const activeMediaSession = this._conference.getActiveMediaSession();\n const remoteRecvMaxFrameHeight = activeMediaSession\n ? this._sourceSenderConstraints.get(sourceName)\n : undefined;\n\n if (this._preferredSendMaxFrameHeight >= 0 && remoteRecvMaxFrameHeight >= 0) {\n return Math.min(this._preferredSendMaxFrameHeight, remoteRecvMaxFrameHeight);\n } else if (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() {\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) {\n mediaSession.addListener(\n MediaSessionEvents.REMOTE_SOURCE_CONSTRAINTS_CHANGED,\n (session, sourceConstraints) => {\n session === this._conference.getActiveMediaSession()\n && sourceConstraints.forEach(constraint => this.onSenderConstraintsReceived(constraint));\n });\n }\n\n /**\n * Propagates the video constraints if they have changed.\n *\n * @param {Object} videoConstraints - The sender video constraints received from the bridge.\n * @returns {Promise}\n */\n onSenderConstraintsReceived(videoConstraints) {\n const { maxHeight, sourceName } = videoConstraints;\n const localVideoTracks = this._conference.getLocalVideoTracks() ?? [];\n\n for (const track of localVideoTracks) {\n // Propagate the sender constraint only if it has changed.\n if (track.getSourceName() === sourceName\n && this._sourceSenderConstraints.get(sourceName) !== maxHeight) {\n this._sourceSenderConstraints.set(\n sourceName,\n maxHeight === -1\n ? Math.min(MAX_LOCAL_RESOLUTION, this._preferredSendMaxFrameHeight)\n : maxHeight);\n logger.debug(`Sender constraints for source:${sourceName} changed to maxHeight:${maxHeight}`);\n this._propagateSendMaxFrameHeight(sourceName);\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} - resolved when the operation is complete.\n */\n setPreferredSendMaxFrameHeight(maxFrameHeight) {\n this._preferredSendMaxFrameHeight = maxFrameHeight;\n const promises = [];\n\n for (const sourceName of this._sourceSenderConstraints.keys()) {\n promises.push(this._propagateSendMaxFrameHeight(sourceName));\n }\n\n return 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 JitsiLocalTrack from \"../RTC/JitsiLocalTrack\";\nimport TraceablePeerConnection from \"../RTC/TraceablePeerConnection\";\nimport JingleSessionPC from \"../xmpp/JingleSessionPC\";\nimport { CodecSelection } from \"./CodecSelection\";\nimport ReceiveVideoController from \"./ReceiveVideoController\";\nimport SendVideoController from \"./SendVideoController\";\nimport {\n DEFAULT_LAST_N,\n LAST_N_UNLIMITED,\n VIDEO_CODECS_BY_COMPLEXITY,\n VIDEO_QUALITY_LEVELS\n} from '../../service/RTC/StandardVideoQualitySettings';\n\nconst logger = getLogger(__filename);\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 qaulity issues.\nconst MIN_LAST_N = 3;\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\ninterface 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\ninterface IVideoConstraints {\n maxHeight: number;\n sourceName: string;\n}\n\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): ISourceStats | undefined {\n if (index < 0 || index >= this._data.length) {\n throw new Error(\"Index out of bounds\");\n }\n return this._data[index];\n }\n\n size(): number {\n return this._data.length;\n }\n}\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 _codecController: CodecSelection;\n private _conference: JitsiConference;\n private _enableAdaptiveMode: boolean;\n private _encodeTimeStats: Map;\n private _isLastNRampupBlocked: boolean;\n private _lastNRampupTime: number;\n private _lastNRampupTimeout: number | undefined;\n private _limitedByCpuTimeout: number | undefined;\n private _receiveVideoController: ReceiveVideoController;\n private _sendVideoController: SendVideoController;\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._conference = conference;\n const { jvb, p2p } = options;\n this._codecController = new CodecSelection(conference, { jvb, p2p });\n this._enableAdaptiveMode = options.enableAdaptiveMode;\n this._encodeTimeStats = new Map();\n this._isLastNRampupBlocked = false;\n this._lastNRampupTime = options.lastNRampupTime;\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 this._conference.on(\n JitsiConferenceEvents.USER_JOINED,\n () => this._codecController.selectPreferredCodec(this._conference.jvbJingleSession));\n this._conference.on(\n JitsiConferenceEvents.USER_LEFT,\n () => this._codecController.selectPreferredCodec(this._conference.jvbJingleSession));\n this._conference.rtc.on(\n RTCEvents.SENDER_VIDEO_CONSTRAINTS_CHANGED,\n (videoConstraints: IVideoConstraints) => this._sendVideoController.onSenderConstraintsReceived(videoConstraints));\n this._conference.on(\n JitsiConferenceEvents.ENCODE_TIME_STATS_RECEIVED,\n (tpc: TraceablePeerConnection, stats: Map) => this._processOutboundRtpStats(tpc, stats));\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 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\n // If the encoder is still limited by CPU, switch to a lower complexity codec.\n if (latestSourceStats.qualityLimitationReason === QualityLimitationReason.CPU\n || encodeResolution < Math.min(localTrack.maxEnabledResolution, localTrack.getCaptureResolution())) {\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\n const { encodeResolution, localTrack, qualityLimitationReason, tpc } = sourceStats;\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 // 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 || (encodeResolution < tpc.calculateExpectedSendResolution(localTrack)\n && qualityLimitationReason !== QualityLimitationReason.BANDWIDTH)) {\n\n if (this._lastNRampupTimeout) {\n window.clearTimeout(this._lastNRampupTimeout);\n this._lastNRampupTimeout = undefined;\n this._isLastNRampupBlocked = true;\n }\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 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} stats - Outbound-rtp stream stats per SSRC.\n * @returns void\n */\n _processOutboundRtpStats(tpc: TraceablePeerConnection, stats: Map): 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 qualityLimitationReason,\n localTrack,\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 get codecController() {\n return this._codecController;\n }\n\n get receiveVideoController() {\n return this._receiveVideoController;\n }\n\n get sendVideoController() {\n return this._sendVideoController;\n }\n}\n","/**\n * A collection of utility functions for taking in XML and parsing it to return\n * certain values.\n */\nexport default {\n /**\n * Parses the presence update of the focus and returns an object with the\n * statuses related to recording.\n *\n * @param {Node} presence - An XMPP presence update.\n * @returns {Object} The current presence values related to recording.\n */\n getFocusRecordingUpdate(presence) {\n const jibriStatus = presence\n && 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 {Node} presence - An XMPP presence update.\n * @returns {Object} The current presence values related to recording.\n */\n getHiddenDomainUpdate(presence) {\n const liveStreamViewURLContainer\n = presence.getElementsByTagName('live-stream-view-url')[0];\n const liveStreamViewURL = liveStreamViewURLContainer\n && liveStreamViewURLContainer.textContent;\n const modeContainer\n = presence.getElementsByTagName('mode')[0];\n const mode = modeContainer\n && modeContainer.textContent\n && modeContainer.textContent.toLowerCase();\n const sessionIDContainer\n = presence.getElementsByTagName('session_id')[0];\n const sessionID\n = sessionIDContainer && sessionIDContainer.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 {Node} response - The response from the IQ.\n * @returns {string} The session ID of the recording session.\n */\n getSessionIdFromIq(response) {\n const jibri = response && response.getElementsByTagName('jibri')[0];\n\n return jibri && jibri.getAttribute('session_id');\n },\n\n /**\n * Returns the recording session ID from a presence, if it exists.\n *\n * @param {Node} presence - An XMPP presence update.\n * @returns {string|undefined} The session ID of the recording session.\n */\n getSessionId(presence) {\n const sessionIdContainer\n = presence.getElementsByTagName('session_id')[0];\n const sessionId = sessionIdContainer && sessionIdContainer.textContent;\n\n return sessionId;\n },\n\n /**\n * Returns whether or not a presence is from the focus.\n *\n * @param {Node} presence - An XMPP presence update.\n * @returns {boolean} True if the presence is from the focus.\n */\n isFromFocus(presence) {\n return presence.getAttribute('from').includes('focus');\n }\n};\n","import { $iq } from 'strophe.js';\n\nimport recordingXMLUtils from './recordingXMLUtils';\n\n/**\n * Represents a recording session.\n */\nexport default class JibriSession {\n /**\n * Initializes a new JibriSession instance.\n *\n * @constructor\n */\n constructor(options = {}) {\n this._connection = options.connection;\n this._mode = options.mode;\n this._jibriJid = null;\n this._statusFromJicofo = '';\n\n this._setSessionID(options.sessionID);\n this.setStatus(options.status);\n }\n\n /**\n * Returns the error related to the session instance, if any.\n *\n * @returns {string|undefined}\n */\n getError() {\n return this._error;\n }\n\n /**\n * Returns the session ID of the session instance.\n *\n * @returns {string|undefined}\n */\n getID() {\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() {\n return this._initiator;\n }\n\n /**\n * Returns the streaming URL of the session.\n *\n * @returns {string|undefined}\n */\n getLiveStreamViewURL() {\n return this._liveStreamViewURL;\n }\n\n /**\n * Returns the current status of the session.\n *\n * @returns {string|undefined}\n */\n getStatus() {\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 {string|undefined} the JID of jibri associated with this session.\n */\n getJibriJid() {\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() {\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() {\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) {\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) {\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) {\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) {\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) {\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) {\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) {\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 the\n * recording.\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 {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 Promise\n */\n start({ appData, broadcastId, focusMucJid, streamId }) {\n return new Promise((resolve, reject) => {\n this._connection.sendIQ(\n this._createIQ({\n action: 'start',\n appData,\n focusMucJid,\n broadcastId,\n streamId\n }),\n result => {\n // All users will eventually receive the 'pending' status\n // from the backend, but for the user initiating the session\n // it's better to give some instant feedback that recording\n // is starting so fire 'pending' here manually.\n this.setStatus('pending');\n this._setSessionID(\n recordingXMLUtils.getSessionIdFromIq(result));\n\n resolve();\n },\n error => {\n this._setErrorFromIq(error);\n\n reject(error);\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\n * recording.\n * @param {Object} options.focusMucJid - The JID of the focus participant\n * that controls recording.\n * @returns Promise\n */\n stop({ focusMucJid }) {\n return new Promise((resolve, reject) => {\n this._connection.sendIQ(\n this._createIQ({\n action: 'stop',\n focusMucJid\n }),\n resolve,\n reject);\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 {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 _createIQ({ action, appData, broadcastId, focusMucJid, streamId }) {\n return $iq({\n to: focusMucJid,\n type: 'set'\n })\n .c('jibri', {\n 'xmlns': 'http://jitsi.org/protocol/jibri',\n 'action': action,\n 'app_data': appData,\n 'recording_mode': this._mode,\n 'streamid': streamId,\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) {\n const error = errorIq.getElementsByTagName('error')[0];\n\n this.setError(error.children[0].tagName);\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) {\n this._sessionID = sessionID;\n }\n}\n","import { getLogger } from '@jitsi/logger';\n\nimport { XMPPEvents } from '../../service/xmpp/XMPPEvents';\n\nimport JibriSession from './JibriSession';\nimport recordingXMLUtils from './recordingXMLUtils';\n\nconst logger = getLogger(__filename);\n\n/**\n * A class responsible for starting and stopping recording sessions and emitting\n * state updates for them.\n */\nclass RecordingManager {\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) {\n /**\n * All known recording sessions from the current conference.\n */\n this._sessions = {};\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 {JibriSession|undefined}\n */\n getSession(sessionID) {\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) {\n let s;\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 {Node} 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 * @returns {void}\n */\n onPresence({ fromHiddenDomain, presence }) {\n if (recordingXMLUtils.isFromFocus(presence)) {\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) {\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) {\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) {\n const session = this.getSession(sessionID);\n\n if (session) {\n return session.stop({ focusMucJid: this._chatRoom.focusMucJid });\n }\n\n return Promise.reject(new Error('Could not find session'));\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) {\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, status, mode) {\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, initiator) {\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 {Node} presence - An XMPP presence update.\n * @returns {void}\n */\n _handleFocusPresence(presence) {\n const jibriStatus = recordingXMLUtils.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 (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 {Node} presence - An XMPP presence update.\n * @returns {void}\n */\n _handleJibriPresence(presence) {\n const { liveStreamViewURL, mode, sessionID }\n = recordingXMLUtils.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.isequal';\n\nimport * as ConferenceEvents from '../../JitsiConferenceEvents';\nimport { MediaType } from '../../service/RTC/MediaType';\nimport { VideoType } from '../../service/RTC/VideoType';\nimport * as ConnectionQualityEvents\n from '../../service/connectivity/ConnectionQualityEvents';\nimport {\n createRtpStatsEvent,\n createTransportStatsEvent\n} from '../../service/statistics/AnalyticsEvents';\nimport browser from '../browser';\n\nimport Statistics from './statistics';\n\n\nconst logger = getLogger(__filename);\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 /**\n * Creates new AverageStatReport 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) {\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 {number} nextValue\n */\n addNext(nextValue) {\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 (!isNaN(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 NaN\n * if no samples were collected.\n */\n calculate() {\n return this.sum / this.count;\n }\n\n /**\n * Appends the report to the analytics \"data\" object. The object will be\n * set under prefix + {@link this.name} key.\n * @param {Object} report the analytics \"data\" object\n */\n appendReport(report) {\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() {\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 /**\n * Creates new ConnectionAvgStats\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, isP2P, n) {\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 * false.\n *\n * @type {Map}\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 * false.\n *\n * @type {number}\n */\n this._avgEnd2EndRTT = undefined;\n\n this._onConnectionStats = (tpc, stats) => {\n if (this.isP2P === tpc.isP2P) {\n this._calculateAvgStats(stats);\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 => this._avgRemoteRTTMap.delete(id);\n conference.on(ConferenceEvents.USER_LEFT, this._onUserLeft);\n\n this._onRemoteStatsUpdated\n = (id, data) => 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 _calculateAvgStats(data) {\n if (!data) {\n logger.error('No stats');\n\n return;\n }\n\n if (browser.supportsRTTStatistics()) {\n if (data.transport && 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 = {\n p2p: this.isP2P,\n 'conference_size': conference.getParticipantCount()\n };\n\n if (data.transport && 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 (!isNaN(jvbEnd2EndRTT)) {\n // eslint-disable-next-line dot-notation\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 (!isNaN(avgLocalRTT) && !isNaN(avgRemoteRTT)) {\n // eslint-disable-next-line dot-notation\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 _calculateAvgRemoteRTT() {\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 (!isNaN(avg)) {\n sum += avg;\n count += 1;\n remoteAvg.reset();\n }\n }\n\n return 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 _processRemoteStats(id, data) {\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 * @private\n */\n _resetAvgStats() {\n this._avgRTT.reset();\n if (this._avgRemoteRTTMap) {\n this._avgRemoteRTTMap.clear();\n }\n this._sampleIdx = 0;\n }\n\n /**\n *\n */\n dispose() {\n\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 * Creates new instance of AvgRTPStatsReporter\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, n) {\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 NaN).\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 NaN).\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 NaN).\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 NaN).\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 NaN).\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\n this._cachedTransportStats = undefined;\n\n this._onLocalStatsUpdated = data => {\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 = (oldStatus, newStatus) => {\n // We want to reset only on the transition from false => true,\n // because otherwise those stats are resetted on JVB <=> P2P\n // transition.\n if (newStatus === true) {\n logger.info('Resetting JVB avg RTP stats');\n this._resetAvgJvbStats();\n }\n };\n conference.on(\n ConferenceEvents.JVB121_STATUS,\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 {go figure} data\n * @private\n */\n _calculateAvgStats(data) {\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\n const batchReport = {\n p2p: isP2P,\n 'conference_size': confSize\n };\n\n if (data.transport && 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 (!isNaN(this._avgRemoteScreenFPS.calculate())) {\n this._avgRemoteScreenFPS.appendReport(batchReport);\n }\n this._avgLocalFPS.appendReport(batchReport);\n if (!isNaN(this._avgLocalScreenFPS.calculate())) {\n this._avgLocalScreenFPS.appendReport(batchReport);\n }\n\n this._avgRemoteCameraPixels.appendReport(batchReport);\n if (!isNaN(this._avgRemoteScreenPixels.calculate())) {\n this._avgRemoteScreenPixels.appendReport(batchReport);\n }\n this._avgLocalCameraPixels.appendReport(batchReport);\n if (!isNaN(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 false if for remote videos.\n * @param {VideoType} videoType\n * @return {number|NaN} average number of pixels or NaN if there\n * are no samples.\n * @private\n */\n _calculateAvgVideoPixels(peerResolutions, isLocal, videoType) {\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 (!isNaN(peerAvgPixels)) {\n peerPixelsSum += peerAvgPixels;\n peerCount += 1;\n }\n }\n }\n }\n\n return 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 * null 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 * NaN if currently not available\n * @private\n */\n _calculatePeerAvgVideoPixels(videos, participant, videoType) {\n let ssrcs = Object.keys(videos).map(ssrc => Number(ssrc));\n let videoTracks = 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) === 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 (!isNaN(peerSsrcPixels) && peerSsrcPixels > 0) {\n peerPixelsSum += peerSsrcPixels;\n peerSsrcCount += 1;\n }\n }\n\n return peerPixelsSum / peerSsrcCount;\n }\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 false if for remote videos.\n * @param {VideoType} videoType\n * @return {number|NaN} average FPS or NaN if there are no samples.\n * @private\n */\n _calculateAvgVideoFps(frameRate, isLocal, videoType) {\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 (!isNaN(peerAvgFPS)) {\n peerFpsSum += peerAvgFPS;\n peerCount += 1;\n }\n }\n }\n }\n\n return 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 * null 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 * NaN if currently not available\n * @private\n */\n _calculatePeerAvgVideoFps(videos, participant, videoType) {\n let ssrcs = Object.keys(videos).map(ssrc => Number(ssrc));\n let videoTracks = 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) === 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 (!isNaN(peerSsrcFps) && peerSsrcFps > 0) {\n peerFpsSum += peerSsrcFps;\n peerSsrcCount += 1;\n }\n }\n\n return 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 _maybeSendTransportAnalyticsEvent(data) {\n if (!data || !data.transport || !data.transport.length) {\n return;\n }\n const transportStats = {\n p2p: data.transport[0].p2p,\n 'local_candidate_type': data.transport[0].localCandidateType,\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 _resetAvgJvbStats() {\n this._resetAvgStats();\n this.jvbStatsMonitor._resetAvgStats();\n }\n\n /**\n * Reset cache of all averages and {@link _sampleIdx}.\n * @private\n */\n _resetAvgStats() {\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 dispose() {\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.JVB121_STATUS,\n this._onJvb121StatusChanged);\n this.jvbStatsMonitor.dispose();\n this.p2pStatsMonitor.dispose();\n }\n}\n","import * as JitsiConferenceEvents from '../../JitsiConferenceEvents';\nimport { XMPPEvents } from '../../service/xmpp/XMPPEvents';\n\nimport SpeakerStats from './SpeakerStats';\n\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\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 /**\n * Initializes a new SpeakerStatsCollector instance.\n *\n * @constructor\n * @param {JitsiConference} conference - The conference to track.\n * @returns {void}\n */\n constructor(conference) {\n this.stats = {\n users: {\n\n // userId: SpeakerStats\n },\n dominantSpeakerId: null\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, { type, faceLandmarks }) => {\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, previous, silence) {\n const oldDominantSpeaker\n = this.stats.users[this.stats.dominantSpeakerId];\n const newDominantSpeaker = this.stats.users[dominantSpeakerId];\n\n oldDominantSpeaker && oldDominantSpeaker.setDominantSpeaker(false);\n newDominantSpeaker && 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, participant) {\n if (participant.isHidden()) {\n return;\n }\n\n if (!this.stats.users[userId]) {\n this.stats.users[userId] = new SpeakerStats(userId, participant.getDisplayName());\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) {\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, newName) {\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 {Object} data - The face landmark object.\n * @returns {void}\n * @private\n */\n _onFaceLandmarkAdd(userId, data) {\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() {\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) {\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 || !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);\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\nconst logger = getLogger(__filename);\n\n/**\n * Discovers component versions in a conference.\n */\nexport default class ComponentsVersions {\n versions: {[key: string]: string};\n conference: any;\n\n /**\n * Creates new instance of ComponentsVersions which will be discovering\n * the versions of conferencing system components in given\n * JitsiConference.\n * @param conference JitsiConference 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 componentName or undefined if not found.\n */\n getComponentVersion(componentName) {\n return this.versions[componentName];\n }\n}\n","export enum VideoSIPGWStatusConstants {\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 not available.\n */\n STATUS_UNDEFINED = 'undefined',\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\nexport enum VideoSIPGWStateConstants {\n /**\n * Video SIP GW session state, currently running.\n */\n STATE_ON = 'on',\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 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 /**\n * Video SIP GW session state, tried to start but it failed.\n */\n STATE_FAILED = 'failed'\n};\n\nexport enum VideoSIPGWErrorConstants {\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';\n\nimport * as VideoSIPGWConstants from './VideoSIPGWConstants';\n\nconst logger = getLogger(__filename);\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 = '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\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, displayName, 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 * Stops the current session.\n */\n stop() {\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() {\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, failureReason) {\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 failureReason,\n oldState,\n newState: this.state,\n displayName: this.displayName\n }\n );\n }\n\n /**\n * Subscribes the passed listener to the event for state change of this\n * session.\n *\n * @param {Function} listener - The function that will receive the event.\n */\n addStateListener(listener) {\n this.addListener(STATE_CHANGED, listener);\n }\n\n /**\n * Unsubscribes the passed handler.\n *\n * @param {Function} listener - The function to be removed.\n */\n removeStateListener(listener) {\n this.removeListener(STATE_CHANGED, listener);\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 _sendJibriIQ(action) {\n const attributes = {\n 'xmlns': 'http://jitsi.org/protocol/jibri',\n 'action': action,\n sipaddress: this.sipAddress\n };\n\n attributes.displayname = this.displayName;\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 no-empty-function\n error => {\n logger.error(\n `Failed to ${action} video SIP GW session, error: `, error);\n this.setState(VideoSIPGWConstants.STATE_FAILED);\n });\n }\n}\n","import { getLogger } from '@jitsi/logger';\nconst logger = getLogger(__filename);\n\nimport { XMPPEvents } from '../../service/xmpp/XMPPEvents';\n\nimport JitsiVideoSIPGWSession from './JitsiVideoSIPGWSession';\nimport * as Constants from './VideoSIPGWConstants';\n\n/**\n * Main video SIP GW handler. Stores references of all created sessions.\n */\nexport default class VideoSIPGW {\n\n /**\n * Creates new handler.\n *\n * @param {ChatRoom} chatRoom - Tha chat room to handle.\n */\n constructor(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) {\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, displayName) {\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);\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) {\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);\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 * as SignalingEvents from '../../service/RTC/SignalingEvents';\nimport SignalingLayer, { getMediaTypeFromSourceName } from '../../service/RTC/SignalingLayer';\nimport { VideoType } from '../../service/RTC/VideoType';\nimport { XMPPEvents } from '../../service/xmpp/XMPPEvents';\nimport FeatureFlags from '../flags/FeatureFlags';\n\nimport { filterNodeFromPresenceJSON } from './ChatRoom';\n\nconst logger = getLogger(__filename);\n\nexport const SOURCE_INFO_PRESENCE_ELEMENT = 'SourceInfo';\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 * Creates new instance.\n */\n constructor() {\n super();\n\n /**\n * A map that stores SSRCs of remote streams and the corresponding jid and source name.\n * FIXME: This map got filled and never cleaned and can grow during long\n * conference\n * @type {Map} maps SSRC number to jid and source name.\n */\n this.ssrcOwners = new Map();\n\n /**\n *\n * @type {ChatRoom|null}\n */\n this.chatRoom = null;\n\n /**\n * @type {Map}\n * @private\n */\n this._localSourceState = { };\n\n /**\n * @type {Map>}\n * @private\n */\n this._remoteSourceState = { };\n }\n\n /**\n * Adds element to the local presence.\n *\n * @returns {void}\n * @private\n */\n _addLocalSourceInfoToPresence() {\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 _bindChatRoomEventHandlers(room) {\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, muted) => {\n this.eventEmitter.emit(\n SignalingEvents.PEER_MUTED_CHANGED,\n endpointId,\n MediaType.AUDIO,\n muted);\n };\n\n this._audioMuteHandler = (node, from) => {\n if (!this._doesEndpointSendNewSourceInfo(from)) {\n emitAudioMutedEvent(from, node.value === 'true');\n }\n };\n room.addPresenceListener('audiomuted', this._audioMuteHandler);\n\n const emitVideoMutedEvent = (endpointId, muted) => {\n this.eventEmitter.emit(\n SignalingEvents.PEER_MUTED_CHANGED,\n endpointId,\n MediaType.VIDEO,\n muted);\n };\n\n this._videoMuteHandler = (node, from) => {\n if (!this._doesEndpointSendNewSourceInfo(from)) {\n emitVideoMutedEvent(from, node.value === 'true');\n }\n };\n room.addPresenceListener('videomuted', this._videoMuteHandler);\n\n const emitVideoTypeEvent = (endpointId, videoType) => {\n this.eventEmitter.emit(\n SignalingEvents.PEER_VIDEO_TYPE_CHANGED,\n endpointId, videoType);\n };\n\n this._videoTypeHandler = (node, from) => {\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, mucNick) => {\n const endpointId = mucNick;\n const { value } = node;\n const sourceInfoJSON = safeJsonParse(value);\n const emitEventsFromHere = this._doesEndpointSendNewSourceInfo(endpointId);\n const endpointSourceState\n = this._remoteSourceState[endpointId] || (this._remoteSourceState[endpointId] = {});\n\n for (const sourceName of Object.keys(sourceInfoJSON)) {\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 => {\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 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 _doesEndpointSendNewSourceInfo(endpointId) {\n const presence = this.chatRoom?.getLastPresence(endpointId);\n\n return Boolean(presence && presence.find(node => 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 _logOwnerChangedMessage(message) {\n if (FeatureFlags.isSsrcRewritingSupported()) {\n logger.debug(message);\n } else {\n logger.error(message);\n }\n }\n\n /**\n * @inheritDoc\n */\n getPeerMediaInfo(owner, mediaType, sourceName) {\n const legacyGetPeerMediaInfo = () => {\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 = {\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 getPeerSourceInfo(owner, sourceName) {\n const mediaType = getMediaTypeFromSourceName(sourceName);\n const mediaInfo = {\n muted: true, // muted by default\n videoType: mediaType === MediaType.VIDEO ? VideoType.CAMERA : undefined // 'camera' by default\n };\n\n return this._remoteSourceState[owner]\n ? this._remoteSourceState[owner][sourceName] ?? mediaInfo\n : undefined;\n }\n\n /**\n * @inheritDoc\n */\n getSSRCOwner(ssrc) {\n return this.ssrcOwners.get(ssrc)?.endpointId;\n }\n\n /**\n * @inheritDoc\n */\n getTrackSourceName(ssrc) {\n return this.ssrcOwners.get(ssrc)?.sourceName;\n }\n\n /**\n * @inheritDoc\n */\n removeSSRCOwners(ssrcList) {\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 ChatRoom instance used and binds presence listeners.\n * @param {ChatRoom} room\n */\n setChatRoom(room) {\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 setSSRCOwner(ssrc, newEndpointId, newSourceName) {\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 setTrackMuteStatus(sourceName, muted) {\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 setTrackVideoType(sourceName, videoType) {\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 updateSsrcOwnersOnLeave(id) {\n const ssrcs = [];\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","/**\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 * 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 $ from 'jquery';\nimport isEqual from 'lodash.isequal';\nimport { Strophe } from 'strophe.js';\n\nimport * as JitsiConferenceErrors from './JitsiConferenceErrors';\nimport JitsiConferenceEventManager from './JitsiConferenceEventManager';\nimport * as JitsiConferenceEvents from './JitsiConferenceEvents';\nimport JitsiParticipant from './JitsiParticipant';\nimport JitsiTrackError from './JitsiTrackError';\nimport * as JitsiTrackErrors from './JitsiTrackErrors';\nimport * as JitsiTrackEvents from './JitsiTrackEvents';\nimport authenticateAndUpgradeRole from './authenticateAndUpgradeRole';\nimport RTC from './modules/RTC/RTC';\nimport { SS_DEFAULT_FRAME_RATE } from './modules/RTC/ScreenObtainer';\nimport browser from './modules/browser';\nimport ConnectionQuality from './modules/connectivity/ConnectionQuality';\nimport IceFailedHandling from './modules/connectivity/IceFailedHandling';\nimport * as DetectionEvents from './modules/detection/DetectionEvents';\nimport NoAudioSignalDetection from './modules/detection/NoAudioSignalDetection';\nimport P2PDominantSpeakerDetection from './modules/detection/P2PDominantSpeakerDetection';\nimport VADAudioAnalyser from './modules/detection/VADAudioAnalyser';\nimport VADNoiseDetection from './modules/detection/VADNoiseDetection';\nimport VADTalkMutedDetection from './modules/detection/VADTalkMutedDetection';\nimport { E2EEncryption } from './modules/e2ee/E2EEncryption';\nimport E2ePing from './modules/e2eping/e2eping';\nimport Jvb121EventGenerator from './modules/event/Jvb121EventGenerator';\nimport FeatureFlags from './modules/flags/FeatureFlags';\nimport { LiteModeContext } from './modules/litemode/LiteModeContext';\nimport { QualityController } from './modules/qualitycontrol/QualityController';\nimport RecordingManager from './modules/recording/RecordingManager';\nimport Settings from './modules/settings/Settings';\nimport AvgRTPStatsReporter from './modules/statistics/AvgRTPStatsReporter';\nimport LocalStatsCollector from './modules/statistics/LocalStatsCollector';\nimport SpeakerStatsCollector from './modules/statistics/SpeakerStatsCollector';\nimport Statistics from './modules/statistics/statistics';\nimport EventEmitter from './modules/util/EventEmitter';\nimport { safeSubtract } from './modules/util/MathUtil';\nimport RandomUtil from './modules/util/RandomUtil';\nimport { getJitterDelay } from './modules/util/Retry';\nimport ComponentsVersions from './modules/version/ComponentsVersions';\nimport VideoSIPGW from './modules/videosipgw/VideoSIPGW';\nimport * as VideoSIPGWConstants from './modules/videosipgw/VideoSIPGWConstants';\nimport SignalingLayerImpl from './modules/xmpp/SignalingLayerImpl';\nimport {\n FEATURE_E2EE,\n FEATURE_JIGASI,\n JITSI_MEET_MUC_TYPE\n} from './modules/xmpp/xmpp';\nimport { BridgeVideoType } from './service/RTC/BridgeVideoType';\nimport { CodecMimeType } from './service/RTC/CodecMimeType';\nimport { MediaType } from './service/RTC/MediaType';\nimport RTCEvents from './service/RTC/RTCEvents';\nimport { SignalingEvents } from './service/RTC/SignalingEvents';\nimport { getMediaTypeFromSourceName, getSourceNameForJitsiTrack } from './service/RTC/SignalingLayer';\nimport { VideoType } from './service/RTC/VideoType';\nimport {\n ACTION_JINGLE_RESTART,\n ACTION_JINGLE_SI_RECEIVED,\n ACTION_JINGLE_SI_TIMEOUT,\n ACTION_JINGLE_TERMINATE,\n ACTION_P2P_DECLINED,\n ACTION_P2P_ESTABLISHED,\n ACTION_P2P_FAILED,\n ACTION_P2P_SWITCH_TO_JVB,\n ICE_ESTABLISHMENT_DURATION_DIFF,\n createConferenceEvent,\n createJingleEvent,\n createP2PEvent\n} from './service/statistics/AnalyticsEvents';\nimport { XMPPEvents } from './service/xmpp/XMPPEvents';\n\nconst logger = getLogger(__filename);\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 = 5000;\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) {\n if (typeof codec === 'string') {\n return Object.values(CodecMimeType).find(value => value === codec.toLowerCase());\n }\n\n return null;\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 {@link AvgRTPStatsReporter}, before arithmetic mean is\n * calculated and submitted to the analytics module.\n * @param {boolean} [options.config.enableIceRestart=false] - enables the ICE\n * restart logic.\n * @param {boolean} [options.config.p2p.enabled] when set to true\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 * @constructor\n *\n * FIXME Make all methods which are called from lib-internal classes\n * to non-public (use _). To name a few:\n * {@link JitsiConference.onLocalRoleChanged}\n * {@link JitsiConference.onUserRoleChanged}\n * {@link JitsiConference.onMemberLeft}\n * and so on...\n */\nexport default function JitsiConference(options) {\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 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 this.eventEmitter = new EventEmitter();\n this.options = options;\n this.eventManager = new JitsiConferenceEventManager(this);\n\n /**\n * List of all the participants in the conference.\n * @type {Map};\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.startAudioMuted = false;\n this.startVideoMuted = false;\n this.startMutedPolicy = {\n audio: false,\n video: false\n };\n this.isMutedByFocus = false;\n\n // when muted by focus we receive the jid of the initiator of the mute\n this.mutedByFocusActor = null;\n\n this.isVideoMutedByFocus = false;\n\n // when video muted by focus we receive the jid of the initiator of the mute\n this.mutedVideoByFocusActor = 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\n = new ConnectionQuality(this, this.eventEmitter, options);\n\n /**\n * Reports average RTP statistics to the analytics module.\n * @type {AvgRTPStatsReporter}\n */\n this.avgRtpStatsReporter\n = 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\n = parseInt(options.config.p2p && options.config.p2p.backToP2PDelay, 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 = isNaN(delay) ? 5 : delay;\n logger.info(`backToP2PDelay: ${this.backToP2PDelay}`);\n\n /**\n * If set to true it means the P2P ICE is no longer connected.\n * When false 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 true 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\n this._e2eEncryption = new E2EEncryption(this);\n }\n\n if (FeatureFlags.isRunInLiteModeEnabled()) {\n logger.info('Lite mode enabled');\n\n this._liteModeContext = new LiteModeContext(this);\n }\n\n /**\n * Flag set to true 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 from the client until it gets reset\n * again by Jicofo.\n */\n this._audioSenderLimitReached = undefined;\n\n /**\n * Flag set to true 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 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}\n\n// FIXME convert JitsiConference to ES6 - ASAP !\nJitsiConference.prototype.constructor = JitsiConference;\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 * @static\n */\nJitsiConference.resourceCreator = function(jid, isAuthenticatedUser) {\n let mucNickname;\n\n if (isAuthenticatedUser) {\n // For authenticated users generate a random ID.\n mucNickname = RandomUtil.randomHexString(8).toLowerCase();\n } else {\n // We try to use the first part of the node (which for anonymous users\n // on prosody is a UUID) to match the previous behavior (and maybe make\n // debugging easier).\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 */\nJitsiConference.prototype._init = function(options = {}) {\n this.eventManager.setupXMPPListeners();\n\n const { config } = this.options;\n\n this._statsCurrentId = config.statisticsId ? config.statisticsId : Settings.callStatsUserName;\n this.room = this.xmpp.createRoom(\n this.options.name, {\n ...config,\n statsId: this._statsCurrentId\n },\n JitsiConference.resourceCreator\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._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 && 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 lastNRampupTime: config.testing?.lastNRampupTime ?? 60000,\n jvb: {\n preferenceOrder: browser.isMobileDevice() && config.videoQuality?.mobileCodecPreferenceOrder\n ? config.videoQuality.mobileCodecPreferenceOrder\n : config.videoQuality?.codecPreferenceOrder,\n disabledCodec: _getCodecMimeType(config.videoQuality?.disabledCodec),\n preferredCodec: _getCodecMimeType(config.videoQuality?.preferredCodec),\n screenshareCodec: browser.isMobileDevice()\n ? _getCodecMimeType(config.videoQuality?.mobileScreenshareCodec)\n : _getCodecMimeType(config.videoQuality?.screenshareCodec)\n },\n p2p: {\n preferenceOrder: browser.isMobileDevice() && config.p2p?.mobileCodecPreferenceOrder\n ? config.p2p.mobileCodecPreferenceOrder\n : config.p2p?.codecPreferenceOrder,\n disabledCodec: _getCodecMimeType(config.p2p?.disabledCodec),\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 aliasName: this._statsCurrentId,\n userName: config.statisticsDisplayName ? config.statisticsDisplayName : this.myUserId(),\n confID: config.confID || `${this.connection.options.hosts.domain}/${this.options.name}`,\n roomName: this.options.name,\n applicationName: config.applicationName\n });\n Statistics.analytics.addPermanentProperties({\n 'callstats_name': this._statsCurrentId\n });\n\n // Start performance observer for monitoring long tasks\n if (config.longTasksStatsInterval) {\n this.statistics.attachLongTasksStats();\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\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\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 && 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 });\n this._noAudioSignalDetection.on(DetectionEvents.AUDIO_INPUT_STATE_CHANGE, hasAudioSignal => {\n this.eventEmitter.emit(JitsiConferenceEvents.AUDIO_INPUT_STATE_CHANGE, hasAudioSignal);\n });\n }\n\n if ('channelLastN' in config) {\n this.setLastN(config.channelLastN);\n }\n\n /**\n * Emits {@link JitsiConferenceEvents.JVB121_STATUS}.\n * @type {Jvb121EventGenerator}\n */\n this.jvb121Status = new Jvb121EventGenerator(this);\n\n // creates dominant speaker detection that works only in p2p mode\n this.p2pDominantSpeakerDetection = new P2PDominantSpeakerDetection(this);\n\n if (config && config.deploymentInfo && config.deploymentInfo.userRegion) {\n this.setLocalParticipantProperty(\n 'region', config.deploymentInfo.userRegion);\n }\n\n // Publish the codec preference to presence.\n this.setLocalParticipantProperty('codecList', 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 if (config && config.transcriptionLanguage && config.transcriptionLanguage !== 'en-US') {\n this.setLocalParticipantProperty('transcription_language', config.transcriptionLanguage);\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 */\nJitsiConference.prototype.join = function(password, replaceParticipant = false) {\n if (this.room) {\n this.room.join(password, replaceParticipant).then(() => this._maybeSetSITimeout());\n }\n};\n\n/**\n * Authenticates and upgrades the role of the local participant/user.\n *\n * @returns {Object} A thenable which (1) settles when the process of\n * authenticating and upgrading the role of the local participant/user finishes\n * and (2) has a cancel method that allows the caller to interrupt the\n * process.\n */\nJitsiConference.prototype.authenticateAndUpgradeRole = function(options) {\n return authenticateAndUpgradeRole.call(this, {\n ...options,\n onCreateResource: JitsiConference.resourceCreator\n });\n};\n\n/**\n * Check if joined to the conference.\n */\nJitsiConference.prototype.isJoined = function() {\n return this.room && this.room.joined;\n};\n\n/**\n * Tells whether or not the P2P mode is enabled in the configuration.\n * @return {boolean}\n */\nJitsiConference.prototype.isP2PEnabled = function() {\n return Boolean(this.options.config.p2p && 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 * When in P2P test mode, the conference will not automatically switch to P2P\n * when there 2 participants.\n * @return {boolean}\n */\nJitsiConference.prototype.isP2PTestModeEnabled = function() {\n return Boolean(this.options.config.testing\n && this.options.config.testing.p2pTestMode);\n};\n\n/**\n * Leaves the conference.\n * @param reason {string|undefined} The reason for leaving the conference.\n * @returns {Promise}\n */\nJitsiConference.prototype.leave = async function(reason) {\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._delayedIceFailed && 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 throw new Error('You have already left the conference');\n }\n\n const room = this.room;\n\n // Unregister connection state listeners\n room.removeListener(\n XMPPEvents.CONNECTION_INTERRUPTED,\n this._onIceConnectionInterrupted);\n room.removeListener(\n XMPPEvents.CONNECTION_RESTORED,\n this._onIceConnectionRestored);\n room.removeListener(\n XMPPEvents.CONNECTION_ESTABLISHED,\n this._onIceConnectionEstablished);\n\n room.removeListener(\n XMPPEvents.CONFERENCE_PROPERTIES_CHANGED,\n this._updateProperties);\n\n room.removeListener(XMPPEvents.MEETING_ID_SET, this._sendConferenceJoinAnalyticsEvent);\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 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 if (this.rtc) {\n this.rtc.destroy();\n }\n\n if (leaveError) {\n throw leaveError;\n }\n};\n\n/**\n * Returns true if end conference support is enabled in the backend.\n *\n * @returns {boolean} whether end conference is supported in the backend.\n */\nJitsiConference.prototype.isEndConferenceSupported = function() {\n return Boolean(this.room && this.room.xmpp.endConferenceComponentAddress);\n};\n\n/**\n * Ends the conference.\n */\nJitsiConference.prototype.end = function() {\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 *\n * @returns {JingleSessionPC|undefined}\n */\nJitsiConference.prototype.getActiveMediaSession = function() {\n return this.isP2PActive() ? this.p2pJingleSession : this.jvbJingleSession;\n};\n\n/**\n * Returns an array containing all media sessions existing in this conference.\n *\n * @returns {Array}\n */\nJitsiConference.prototype.getMediaSessions = function() {\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 * 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 */\nJitsiConference.prototype._registerRtcListeners = function(rtc) {\n rtc.addListener(RTCEvents.DATA_CHANNEL_OPEN, () => {\n for (const localTrack of this.rtc.localTracks) {\n localTrack.isVideoTrack() && this._sendBridgeVideoTypeMessage(localTrack);\n }\n });\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 * @private\n */\nJitsiConference.prototype._sendBridgeVideoTypeMessage = function(localtrack) {\n let videoType = !localtrack || localtrack.isMuted() ? BridgeVideoType.NONE : localtrack.getVideoType();\n\n if (videoType === BridgeVideoType.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 * Returns name of this conference.\n */\nJitsiConference.prototype.getName = function() {\n return this.options.name.toString();\n};\n\n/**\n * Returns the {@link JitsiConnection} used by this this conference.\n */\nJitsiConference.prototype.getConnection = function() {\n return this.connection;\n};\n\n/**\n * Check if authentication is enabled for this conference.\n */\nJitsiConference.prototype.isAuthEnabled = function() {\n return this.authEnabled;\n};\n\n/**\n * Check if user is logged in.\n */\nJitsiConference.prototype.isLoggedIn = function() {\n return Boolean(this.authIdentity);\n};\n\n/**\n * Get authorized login.\n */\nJitsiConference.prototype.getAuthLogin = function() {\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 */\nJitsiConference.prototype.getLocalTracks = function(mediaType) {\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 * @return {JitsiLocalTrack|null}\n */\nJitsiConference.prototype.getLocalAudioTrack = function() {\n return this.rtc ? this.rtc.getLocalAudioTrack() : null;\n};\n\n/**\n * Obtains local video track.\n * @return {JitsiLocalTrack|null}\n */\nJitsiConference.prototype.getLocalVideoTrack = function() {\n return this.rtc ? this.rtc.getLocalVideoTrack() : null;\n};\n\n/**\n * Returns all the local video tracks.\n * @returns {Array}\n */\nJitsiConference.prototype.getLocalVideoTracks = function() {\n return this.rtc ? this.rtc.getLocalVideoTracks() : null;\n};\n\n/**\n * Obtains the performance statistics.\n * @returns {Object|null}\n */\nJitsiConference.prototype.getPerformanceStats = function() {\n return {\n longTasksStats: this.statistics.getLongTasksStats()\n };\n};\n\n/**\n * Attaches a handler for events(For example - \"participant joined\".) in the\n * conference. All possible event are defined in JitsiConferenceEvents.\n * @param eventId the event ID.\n * @param handler handler for the event.\n *\n * Note: consider adding eventing functionality by extending an EventEmitter\n * impl, instead of rolling ourselves\n */\nJitsiConference.prototype.on = function(eventId, handler) {\n if (this.eventEmitter) {\n this.eventEmitter.on(eventId, handler);\n }\n};\n\n/**\n * Adds a one-time`listener` function for the event.\n * @param eventId the event ID.\n * @param handler handler for the event.\n *\n */\nJitsiConference.prototype.once = function(eventId, handler) {\n if (this.eventEmitter) {\n this.eventEmitter.once(eventId, handler);\n }\n};\n\n/**\n * Removes event listener\n * @param eventId the event ID.\n * @param [handler] optional, the specific handler to unbind\n *\n * Note: consider adding eventing functionality by extending an EventEmitter\n * impl, instead of rolling ourselves\n */\nJitsiConference.prototype.off = function(eventId, handler) {\n if (this.eventEmitter) {\n this.eventEmitter.removeListener(eventId, handler);\n }\n};\n\n// Common aliases for event emitter\nJitsiConference.prototype.addEventListener = JitsiConference.prototype.on;\nJitsiConference.prototype.removeEventListener = JitsiConference.prototype.off;\n\n/**\n * Receives notifications from other participants about commands / custom events\n * (sent by sendCommand or sendCommandOnce methods).\n * @param command {String} the name of the command\n * @param handler {Function} handler for the command\n */\nJitsiConference.prototype.addCommandListener = function(command, handler) {\n if (this.room) {\n this.room.addPresenceListener(command, handler);\n }\n};\n\n/**\n * Removes command listener\n * @param command {String} the name of the command\n * @param handler {Function} handler to remove for the command\n */\nJitsiConference.prototype.removeCommandListener = function(command, handler) {\n if (this.room) {\n this.room.removePresenceListener(command, handler);\n }\n};\n\n/**\n * Sends text message to the other participants in the conference\n * @param message the text message.\n * @param elementName the element name to encapsulate the message.\n * @deprecated Use 'sendMessage' instead. TODO: this should be private.\n */\nJitsiConference.prototype.sendTextMessage = function(message, elementName = 'body') {\n if (this.room) {\n this.room.sendMessage(message, elementName);\n }\n};\n\n/**\n * Sends a reaction to the other participants in the conference\n * @param reaction the reaction.\n * @param messageId the ID of the message to attach the reaction to.\n * @param receiverId the intended recipient, if the message is private.\n */\nJitsiConference.prototype.sendReaction = function(reaction, messageId, receiverId) {\n if (this.room) {\n this.room.sendReaction(reaction, messageId, receiverId);\n }\n};\n\n/**\n * Send private text message to another participant of the conference\n * @param id the id of the participant to send a private message.\n * @param message the text message.\n * @param elementName the element name to encapsulate the message.\n * @deprecated Use 'sendMessage' instead. TODO: this should be private.\n */\nJitsiConference.prototype.sendPrivateTextMessage = function(id, message, elementName = 'body') {\n if (this.room) {\n this.room.sendPrivateMessage(id, message, elementName);\n }\n};\n\n/**\n * Send presence command.\n * @param name {String} the name of the command.\n * @param values {Object} with keys and values that will be sent.\n **/\nJitsiConference.prototype.sendCommand = function(name, values) {\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 name {String} the name of the command.\n * @param values {Object} with keys and values that will be sent.\n **/\nJitsiConference.prototype.sendCommandOnce = function(name, values) {\n this.sendCommand(name, values);\n this.removeCommand(name);\n};\n\n/**\n * Removes presence command.\n * @param name {String} the name of the command.\n **/\nJitsiConference.prototype.removeCommand = function(name) {\n if (this.room) {\n this.room.removeFromPresence(name);\n }\n};\n\n/**\n * Sets the display name for this conference.\n * @param name the display name to set\n */\nJitsiConference.prototype.setDisplayName = function(name) {\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();\n } else if (this.room.getFromPresence(nickKey)) {\n this.room.removeFromPresence(nickKey);\n this.room.sendPresence();\n }\n }\n};\n\n/**\n * Set join without audio\n * @param silent whether user joined without audio\n */\nJitsiConference.prototype.setIsSilent = function(silent) {\n if (this.room) {\n this.room.addOrReplaceInPresence('silent', {\n attributes: { xmlns: 'http://jitsi.org/protocol/silent' },\n value: silent\n }) && this.room.sendPresence();\n }\n};\n\n/**\n * Set new subject for this conference. (available only for moderator)\n * @param {string} subject new subject\n */\nJitsiConference.prototype.setSubject = function(subject) {\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 *\n * @returns {String} \"on\" or \"off\".\n */\nJitsiConference.prototype.getTranscriptionStatus = function() {\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}\n * @throws {Error} if the specified track is a video track and there is already\n * another video track in the conference.\n */\nJitsiConference.prototype.addTrack = function(track) {\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 client happens to attempt to add the same local track twice.\n if (track === localTracks[0]) {\n return Promise.resolve(track);\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 (mediaType === MediaType.VIDEO\n && !localTracks.find(t => 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 this._sendBridgeVideoTypeMessage(track);\n this._updateRoomPresence(this.getActiveMediaSession());\n\n if (this.isMutedByFocus || this.isVideoMutedByFocus) {\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 * Fires TRACK_AUDIO_LEVEL_CHANGED change conference event (for local tracks).\n * @param {number} audioLevel the audio level\n * @param {TraceablePeerConnection} [tpc]\n */\nJitsiConference.prototype._fireAudioLevelChangeEvent = function(audioLevel, tpc) {\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 track the JitsiTrack object related to the event.\n */\nJitsiConference.prototype._fireMuteChangeEvent = function(track) {\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() && !track.isMuted()) {\n this.isVideoMutedByFocus = false;\n\n // unmute local user on server\n this.room.muteParticipant(this.room.myroomjid, false, MediaType.VIDEO);\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 const actorId = Strophe.getResourceFromJid(this.mutedVideoByFocusActor);\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 * Returns the list of local tracks that need to be added to the peerconnection on join.\n * This takes the startAudioMuted/startVideoMuted flags into consideration since we do not\n * want to add the tracks if the user joins the call audio/video muted. The tracks will be\n * added when the user unmutes for the first time.\n * @returns {Array} - list of local tracks that are unmuted.\n */\nJitsiConference.prototype._getInitialLocalTracks = function() {\n // Always add the audio track on certain platforms:\n // * Safari / WebKit: because of a known issue where audio playout doesn't happen\n // if the user joins audio and video muted.\n // * React Native: after iOS 15, if a user joins muted they won't be able to unmute.\n return this.getLocalTracks()\n .filter(track => {\n const trackType = track.getType();\n\n if (trackType === MediaType.AUDIO\n && (!(this.isStartAudioMuted() || this.startMutedPolicy.audio)\n || browser.isWebKitBased()\n || browser.isReactNative())) {\n return true;\n } else if (trackType === MediaType.VIDEO && !this.isStartVideoMuted() && !this.startMutedPolicy.video) {\n return true;\n }\n\n // Remove the track from the conference.\n this.onLocalTrackRemoved(track);\n\n return false;\n });\n};\n\n/**\n * Clear JitsiLocalTrack properties and listeners.\n * @param track the JitsiLocalTrack object.\n */\nJitsiConference.prototype.onLocalTrackRemoved = function(track) {\n track.setConference(null);\n this.rtc.removeLocalTrack(track);\n track.removeEventListener(JitsiTrackEvents.TRACK_MUTE_CHANGED, track.muteHandler);\n if (track.isAudioTrack()) {\n track.removeEventListener(JitsiTrackEvents.TRACK_AUDIO_LEVEL_CHANGED, track.audioLevelHandler);\n }\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\n * @returns {Promise}\n */\nJitsiConference.prototype.removeTrack = function(track) {\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 */\nJitsiConference.prototype.replaceTrack = function(oldTrack, newTrack) {\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(`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 // 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._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 * 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 null if the method should act as \"add track\"\n * @param {JitsiLocalTrack|null} newTrack the new track to be added or\n * null 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 */\nJitsiConference.prototype._doReplaceTrack = function(oldTrack, newTrack) {\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 return Promise.all(replaceTrackPromises);\n};\n\n/**\n * Handler for when a source-add for a local source is rejected by Jicofo.\n *\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 * @returns {void}\n */\nJitsiConference.prototype._removeLocalSourceOnReject = function(jingleSession, error, mediaType) {\n if (!jingleSession) {\n return;\n }\n logger.warn(`Source-add rejected on ${jingleSession}, reason=\"${error?.reason}\", message=\"${error?.msg}\"`);\n const track = this.getLocalTracks(mediaType)[0];\n\n this.eventEmitter.emit(JitsiConferenceEvents.TRACK_UNMUTE_REJECTED, track);\n};\n\n/**\n * Operations related to creating a new track\n * @param {JitsiLocalTrack} newTrack the new track being created\n */\nJitsiConference.prototype._setupNewTrack = function(newTrack) {\n const mediaType = newTrack.getType();\n\n // Create a source name for this track if it doesn't exist.\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 // Add event handlers.\n newTrack.muteHandler = this._fireMuteChangeEvent.bind(this, newTrack);\n newTrack.addEventListener(JitsiTrackEvents.TRACK_MUTE_CHANGED, newTrack.muteHandler);\n\n if (newTrack.isAudioTrack()) {\n newTrack.audioLevelHandler = this._fireAudioLevelChangeEvent.bind(this);\n newTrack.addEventListener(JitsiTrackEvents.TRACK_AUDIO_LEVEL_CHANGED, newTrack.audioLevelHandler);\n }\n\n this.eventEmitter.emit(JitsiConferenceEvents.TRACK_ADDED, newTrack);\n};\n\n/**\n * Sets the video type.\n * @param track\n * @return true if video type was changed in presence.\n * @private\n */\nJitsiConference.prototype._setNewVideoType = function(track) {\n let videoTypeChanged = false;\n\n if (track) {\n videoTypeChanged = this._signalingLayer.setTrackVideoType(track.getSourceName(), track.videoType);\n }\n\n return videoTypeChanged;\n};\n\n/**\n * Sets mute status.\n * @param mediaType\n * @param localTrack\n * @param isMuted\n * @param true when presence was changed, false otherwise.\n * @private\n */\nJitsiConference.prototype._setTrackMuteStatus = function(mediaType, localTrack, isMuted) {\n let presenceChanged = false;\n\n if (localTrack) {\n presenceChanged = this._signalingLayer.setTrackMuteStatus(localTrack.getSourceName(), isMuted);\n presenceChanged && logger.debug(`Mute state of ${localTrack} changed to muted=${isMuted}`);\n }\n\n return presenceChanged;\n};\n\n/**\n * Method called by the {@link JitsiLocalTrack} in order to add the underlying MediaStream to the RTCPeerConnection.\n *\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 */\nJitsiConference.prototype._addLocalTrackToPc = function(track) {\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 return Promise.allSettled(addPromises);\n};\n\n/**\n * Method called by the {@link JitsiLocalTrack} in order to remove the underlying MediaStream from the\n * RTCPeerConnection.\n *\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 */\nJitsiConference.prototype._removeLocalTrackFromPc = function(track) {\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 * Get role of the local user.\n * @returns {string} user role: 'moderator' or 'none'\n */\nJitsiConference.prototype.getRole = function() {\n return this.room.role;\n};\n\n/**\n * Returns whether or not the current conference has been joined as a hidden\n * user.\n *\n * @returns {boolean|null} True if hidden, false otherwise. Will return null if\n * no connection is active.\n */\nJitsiConference.prototype.isHidden = function() {\n if (!this.connection) {\n return null;\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|null} true if local user is moderator, false otherwise. If\n * we're no longer in the conference room then null is returned.\n */\nJitsiConference.prototype.isModerator = function() {\n return this.room ? this.room.isModerator() : null;\n};\n\n/**\n * Set password for the room.\n * @param {string} password new password for the room.\n * @returns {Promise}\n */\nJitsiConference.prototype.lock = function(password) {\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 => reject(err),\n () => reject(JitsiConferenceErrors.PASSWORD_NOT_SUPPORTED));\n });\n};\n\n/**\n * Remove password from the room.\n * @returns {Promise}\n */\nJitsiConference.prototype.unlock = function() {\n return this.lock();\n};\n\n/**\n * Obtains the current value for \"lastN\". See {@link setLastN} for more info.\n * @returns {number}\n */\nJitsiConference.prototype.getLastN = function() {\n return this.qualityController.receiveVideoController.getLastN();\n};\n\n/**\n * Obtains the forwarded sources list in this conference.\n * @return {Array|null}\n */\nJitsiConference.prototype.getForwardedSources = function() {\n return this.rtc.getForwardedSources();\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 */\nJitsiConference.prototype.setLastN = function(lastN) {\n if (!Number.isInteger(lastN) && !Number.parseInt(lastN, 10)) {\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 an array of all participants in this conference.\n */\nJitsiConference.prototype.getParticipants = function() {\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 **/\nJitsiConference.prototype.getParticipantCount = function(countHidden = false) {\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 */\nJitsiConference.prototype.getParticipantById = function(id) {\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 */\nJitsiConference.prototype.grantOwner = function(id) {\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 */\nJitsiConference.prototype.revokeOwner = function(id) {\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 */\nJitsiConference.prototype.kickParticipant = function(id, reason) {\n const participant = this.getParticipantById(id);\n\n if (!participant) {\n return;\n }\n this.room.kick(participant.getJid(), reason);\n};\n\n/**\n * Maybe clears the timeout which emits {@link ACTION_JINGLE_SI_TIMEOUT}\n * analytics event.\n * @private\n */\nJitsiConference.prototype._maybeClearSITimeout = function() {\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 */\nJitsiConference.prototype._maybeSetSITimeout = function() {\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 ACTION_JINGLE_SI_TIMEOUT,\n {\n p2p: false,\n value: JINGLE_SI_TIMEOUT\n }));\n }, JINGLE_SI_TIMEOUT);\n }\n};\n\n/**\n * Mutes a participant.\n * @param {string} id The id of the participant to mute.\n */\nJitsiConference.prototype.muteParticipant = function(id, mediaType) {\n const muteMediaType = mediaType ? mediaType : MediaType.AUDIO;\n\n if (muteMediaType !== MediaType.AUDIO && muteMediaType !== MediaType.VIDEO) {\n logger.error(`Unsupported media type: ${muteMediaType}`);\n\n return;\n }\n\n const participant = this.getParticipantById(id);\n\n if (!participant) {\n return;\n }\n this.room.muteParticipant(participant.getJid(), true, muteMediaType);\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 botType, if any\n * @param isReplaceParticipant whether this join replaces a participant with\n * the same jwt.\n */\nJitsiConference.prototype.onMemberJoined = function(\n jid, nick, role, isHidden, statsID, status, identity, botType, fullJid, features, isReplaceParticipant) {\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 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};\n\n/* eslint-enable max-params */\n\n/**\n * Get notified when we joined the room.\n *\n * @private\n */\nJitsiConference.prototype._onMucJoined = function() {\n this._numberOfParticipantsOnJoin = this.getParticipantCount();\n this._maybeStartOrStopP2P();\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 */\nJitsiConference.prototype._updateFeatures = function(participant) {\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 * Get notified when member bot type had changed.\n * @param jid the member jid\n * @param botType the new botType value\n * @private\n */\nJitsiConference.prototype._onMemberBotTypeChanged = function(jid, botType) {\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\nJitsiConference.prototype.onMemberLeft = function(jid, reason) {\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 }\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\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 */\nJitsiConference.prototype.onMemberKicked = function(\n isSelfPresence,\n actorId,\n kickedParticipantId,\n reason,\n isReplaceParticipant) {\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 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 */\nJitsiConference.prototype.onLocalRoleChanged = function(role) {\n // Emit role changed for local JID\n this.eventEmitter.emit(\n JitsiConferenceEvents.USER_ROLE_CHANGED, this.myUserId(), role);\n};\n\nJitsiConference.prototype.onUserRoleChanged = function(jid, role) {\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\nJitsiConference.prototype.onDisplayNameChanged = function(jid, displayName) {\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\nJitsiConference.prototype.onSilentStatusChanged = function(jid, isSilent) {\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 */\nJitsiConference.prototype.onRemoteTrackAdded = function(track) {\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 track.addEventListener(\n JitsiTrackEvents.TRACK_MUTE_CHANGED,\n () => emitter.emit(JitsiConferenceEvents.TRACK_MUTE_CHANGED, track));\n track.isAudioTrack() && track.addEventListener(\n JitsiTrackEvents.TRACK_AUDIO_LEVEL_CHANGED,\n (audioLevel, tpc) => {\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 * Callback called by the Jingle plugin when 'session-answer' is received.\n * @param {JingleSessionPC} session the Jingle session for which an answer was\n * received.\n * @param {jQuery} answer a jQuery selector pointing to 'jingle' IQ element\n */\n// eslint-disable-next-line no-unused-vars\nJitsiConference.prototype.onCallAccepted = function(session, answer) {\n if (this.p2pJingleSession === session) {\n logger.info('P2P setAnswer');\n\n this.p2pJingleSession.setAnswer(answer);\n this.eventEmitter.emit(JitsiConferenceEvents._MEDIA_SESSION_STARTED, this.p2pJingleSession);\n }\n};\n\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\n * received\n * @param {jQuery} transportInfo a jQuery selector pointing to 'jingle' IQ\n * element\n */\n// eslint-disable-next-line no-unused-vars\nJitsiConference.prototype.onTransportInfo = function(session, transportInfo) {\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\n * the conference.\n *\n * @param {JitsiRemoteTrack} removedTrack\n */\nJitsiConference.prototype.onRemoteTrackRemoved = function(removedTrack) {\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 for the P2P jingle session.\n */\nJitsiConference.prototype._onIncomingCallP2P = function(jingleSession, jingleOffer) {\n let rejectReason;\n const contentName = jingleOffer.find('>content').attr('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 reason: 'decline',\n reasonDescription: 'P2P disabled',\n errorMsg: 'P2P across two endpoints in different SDP modes is disabled'\n };\n } else if ((!this.isP2PEnabled() && !this.isP2PTestModeEnabled())\n || (browser.isFirefox() && !this._firefoxP2pEnabled)) {\n rejectReason = {\n reason: 'decline',\n reasonDescription: 'P2P disabled',\n errorMsg: 'P2P mode disabled in the configuration or browser unsupported'\n };\n } else if (this.p2pJingleSession) {\n // Reject incoming P2P call (already in progress)\n rejectReason = {\n reason: 'busy',\n reasonDescription: 'P2P already in progress',\n errorMsg: 'Duplicated P2P \"session-initiate\"'\n };\n } else if (!this._shouldBeInP2PMode()) {\n rejectReason = {\n reason: 'decline',\n reasonDescription: 'P2P requirements not met',\n errorMsg: 'Received P2P \"session-initiate\" when should not be in P2P mode'\n };\n Statistics.sendAnalytics(createJingleEvent(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 * Handles an incoming call event.\n */\nJitsiConference.prototype.onIncomingCall = function(jingleSession, jingleOffer, now) {\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 reason: 'security-error',\n reasonDescription: description,\n errorMsg: description\n });\n\n return;\n }\n this._acceptJvbIncomingCall(jingleSession, jingleOffer, now);\n }\n};\n\n/**\n * Accepts an incoming call event for the JVB jingle session.\n */\nJitsiConference.prototype._acceptJvbIncomingCall = function(jingleSession, jingleOffer, now) {\n\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(ACTION_JINGLE_RESTART, { p2p: false }));\n }\n\n const serverRegion\n = $(jingleOffer)\n .find('>bridge-session[xmlns=\"http://jitsi.org/protocol/focus\"]')\n .attr('region');\n\n this.eventEmitter.emit(JitsiConferenceEvents.SERVER_REGION_CHANGED, serverRegion);\n\n this._maybeClearSITimeout();\n Statistics.sendAnalytics(createJingleEvent(\n 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 mediaType: MediaType.VIDEO,\n codecList: this.qualityController.codecController.getCodecPreferenceList('jvb'),\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._getInitialLocalTracks();\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 error => {\n logger.error('Failed to accept incoming Jingle session', 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 {jQuery} offerIq a jQuery selector 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 */\nJitsiConference.prototype._setBridgeChannel = function(offerIq, pc) {\n const ignoreDomain = this.connection?.options?.bridgeChannel?.ignoreDomain;\n const preferSctp = this.connection?.options?.bridgeChannel?.preferSctp ?? true;\n const sctpOffered = $(offerIq).find('>content[name=\"data\"]')\n .first().length === 1;\n let wsUrl = null;\n\n logger.info(`SCTP: offered=${sctpOffered}, prefered=${preferSctp}`);\n\n if (!(sctpOffered && preferSctp)) {\n $(offerIq).find('>content>transport>web-socket')\n .toArray()\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 = $(offerIq).find('>content>transport>web-socket')\n .first();\n\n if (firstWsUrl.length === 1) {\n wsUrl = firstWsUrl[0].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, 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]\n * @param {string} options.reason the name of the reason element as defined\n * by Jingle\n * @param {string} options.reasonDescription the reason description which will\n * be included in Jingle 'session-terminate' message.\n * @param {string} options.errorMsg an error message to be logged on global\n * error handler\n * @private\n */\nJitsiConference.prototype._rejectIncomingCall = function(jingleSession, options) {\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 && options.reason,\n reasonDescription: options && options.reasonDescription,\n sendSessionTerminate: true\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\n * 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 */\nJitsiConference.prototype.onCallEnded = function(jingleSession, reasonCondition, reasonText) {\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(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 = {};\n\n if (reasonCondition === 'connectivity-error' && reasonText === 'ICE FAILED') {\n // It can happen that the other peer detects ICE failed and 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 * Handles the suspend detected event. Leaves the room and fires suspended.\n * @param {JingleSessionPC} jingleSession\n */\nJitsiConference.prototype.onSuspendDetected = function(jingleSession) {\n if (!jingleSession.isP2P) {\n this.leave();\n this.eventEmitter.emit(JitsiConferenceEvents.SUSPEND_DETECTED);\n }\n};\n\nJitsiConference.prototype.updateDTMFSupport = function() {\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\n * that supports DTMF.\n * @returns {boolean} true if somebody supports DTMF, false otherwise\n */\nJitsiConference.prototype.isDTMFSupported = function() {\n return this.somebodySupportsDTMF;\n};\n\n/**\n * Returns the local user's ID\n * @return {string} local user's ID\n */\nJitsiConference.prototype.myUserId = function() {\n return (\n this.room && this.room.myroomjid\n ? Strophe.getResourceFromJid(this.room.myroomjid)\n : null);\n};\n\nJitsiConference.prototype.sendTones = function(tones, duration, pause) {\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 {Object} options - Configuration for the recording. See\n * {@link Chatroom#startRecording} for more info.\n * @returns {Promise} See {@link Chatroom#startRecording} for more info.\n */\nJitsiConference.prototype.startRecording = function(options) {\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 * Stop a recording session.\n *\n * @param {string} sessionID - The ID of the recording session that\n * should be stopped.\n * @returns {Promise} See {@link Chatroom#stopRecording} for more info.\n */\nJitsiConference.prototype.stopRecording = function(sessionID) {\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 the SIP calls are supported and false otherwise\n */\nJitsiConference.prototype.isSIPCallingSupported = function() {\n return this.room?.xmpp?.moderator?.isSipGatewayEnabled() ?? false;\n};\n\n/**\n * Dials a number.\n * @param number the number\n */\nJitsiConference.prototype.dial = function(number) {\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 * Hangup an existing call\n */\nJitsiConference.prototype.hangup = function() {\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 */\nJitsiConference.prototype.getPhoneNumber = function() {\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 with phone.\n */\nJitsiConference.prototype.getPhonePin = function() {\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 *\n * @returns {string|undefined}\n */\nJitsiConference.prototype.getMeetingUniqueId = function() {\n if (this.room) {\n return this.room.getMeetingId();\n }\n};\n\n/**\n * Will return P2P or JVB TraceablePeerConnection depending on\n * which connection is currently active.\n *\n * @return {TraceablePeerConnection|null} null if there isn't any active\n * TraceablePeerConnection currently available.\n * @public (FIXME how to make package local ?)\n */\nJitsiConference.prototype.getActivePeerConnection = function() {\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. Its ice connection state\n * for its session.\n * NOTE that \"completed\" ICE state which can appear on the P2P connection will\n * be converted to \"connected\".\n * @return {string|null} ICE state name or null if there is no active\n * peer connection at this time.\n */\nJitsiConference.prototype.getConnectionState = function() {\n const peerConnection = this.getActivePeerConnection();\n\n return peerConnection ? peerConnection.getConnectionState() : null;\n};\n\n/**\n * Make all new participants mute their audio/video on join.\n * @param policy {Object} object with 2 boolean properties for video and audio:\n * @param {boolean} audio if audio should be muted.\n * @param {boolean} video if video should be muted.\n */\nJitsiConference.prototype.setStartMutedPolicy = function(policy) {\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 // Do not apply the startMutedPolicy locally on the moderator, the moderator should join with available local\n // sources and the policy needs to be applied only on users that join the call after.\n // this.startMutedPolicy = policy;\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\n/**\n * Returns current start muted policy\n * @returns {Object} with 2 properties - audio and video.\n */\nJitsiConference.prototype.getStartMutedPolicy = function() {\n return this.startMutedPolicy;\n};\n\n/**\n * Check if audio is muted on join.\n */\nJitsiConference.prototype.isStartAudioMuted = function() {\n return this.startAudioMuted;\n};\n\n/**\n * Check if video is muted on join.\n */\nJitsiConference.prototype.isStartVideoMuted = function() {\n return this.startVideoMuted;\n};\n\n/**\n * Returns measured connectionTimes.\n */\nJitsiConference.prototype.getConnectionTimes = function() {\n return this.room.connectionTimes;\n};\n\n/**\n * Sets a property for the local participant.\n */\nJitsiConference.prototype.setLocalParticipantProperty = function(name, value) {\n this.sendCommand(`jitsi_participant_${name}`, { value });\n};\n\n/**\n * Removes a property for the local participant and sends the updated presence.\n */\nJitsiConference.prototype.removeLocalParticipantProperty = function(name) {\n this.removeCommand(`jitsi_participant_${name}`);\n this.room.sendPresence();\n};\n\n/**\n * Gets a local participant property.\n *\n * @return value of the local participant property if the tagName exists in the\n * list of properties, otherwise returns undefined.\n */\nJitsiConference.prototype.getLocalParticipantProperty = function(name) {\n const property = this.room.presMap.nodes.find(prop =>\n prop.tagName === `jitsi_participant_${name}`\n );\n\n return property ? property.value : undefined;\n};\n\n/**\n * Sends the given feedback if enabled.\n *\n * @param overallFeedback an integer between 1 and 5 indicating the\n * user feedback\n * @param detailedFeedback detailed feedback from the user. Not yet used\n * @returns {Promise} Resolves if feedback is submitted successfully.\n */\nJitsiConference.prototype.sendFeedback = function(overallFeedback, detailedFeedback) {\n return this.statistics.sendFeedback(overallFeedback, detailedFeedback);\n};\n\n/**\n * @returns false, since callstats in not supported anymore.\n * @deprecated\n */\nJitsiConference.prototype.isCallstatsEnabled = function() {\n logger.warn('Callstats is no longer supported');\n\n return false;\n};\n\n/**\n * Finds the SSRC of a given track\n *\n * @param track\n * @returns {number|undefined} the SSRC of the specificed track, otherwise undefined.\n */\nJitsiConference.prototype.getSsrcByTrack = function(track) {\n return track.isLocal() ? this.getActivePeerConnection()?.getLocalSSRC(track) : track.getSSRC();\n};\n\n/**\n * This is a no-op since callstats is no longer supported.\n */\n// eslint-disable-next-line no-empty-function\nJitsiConference.prototype.sendApplicationLog = function() { };\n\n/**\n * Checks if the user identified by given mucJid is the conference focus.\n * @param mucJid the full MUC address of the user to be checked.\n * @returns {boolean|null} true if MUC user is the conference focus,\n * false when is not. null if we're not in the MUC anymore and\n * are unable to figure out the status or if given mucJid is invalid.\n */\nJitsiConference.prototype.isFocus = function(mucJid) {\n return this.room ? this.room.isFocus(mucJid) : null;\n};\n\n/**\n * Fires CONFERENCE_FAILED event with INCOMPATIBLE_SERVER_VERSIONS parameter\n */\nJitsiConference.prototype._fireIncompatibleVersionsEvent = function() {\n this.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_FAILED,\n JitsiConferenceErrors.INCOMPATIBLE_SERVER_VERSIONS);\n};\n\n/**\n * Sends a message via the data channel.\n * @param to {string} the id of the endpoint that should receive the message.\n * If \"\" the message will be sent to all participants.\n * @param payload {object} the payload of the message.\n * @throws NetworkError or InvalidStateError or Error if the operation fails.\n * @deprecated Use 'sendMessage' instead. TODO: this should be private.\n */\nJitsiConference.prototype.sendEndpointMessage = function(to, payload) {\n this.rtc.sendChannelMessage(to, payload);\n};\n\n/**\n * Sends local stats via the bridge channel which then forwards to other endpoints selectively.\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 */\nJitsiConference.prototype.sendEndpointStatsMessage = function(payload) {\n this.rtc.sendEndpointStatsMessage(payload);\n};\n\n/**\n * Sends a broadcast message via the data channel.\n * @param payload {object} the payload of the message.\n * @throws NetworkError or InvalidStateError or Error if the operation fails.\n * @deprecated Use 'sendMessage' instead. TODO: this should be private.\n */\nJitsiConference.prototype.broadcastEndpointMessage = function(payload) {\n this.sendEndpointMessage('', payload);\n};\n\n/**\n * Sends a message to a given endpoint (if 'to' is a non-empty string), or\n * broadcasts it to all endpoints in the conference.\n * @param {string} to The ID of the endpoint/participant which is to receive\n * the message, or '' to broadcast the message to all endpoints in the\n * conference.\n * @param {string|object} message the message to send. If this is of type\n * 'string' it will be sent as a chat message. If it is of type 'object', it\n * will be encapsulated in a format recognized by jitsi-meet and converted to\n * JSON before being sent.\n * @param {boolean} sendThroughVideobridge Whether to send the message through\n * jitsi-videobridge (via the COLIBRI data channel or web socket), or through\n * the XMPP MUC. Currently only objects can be sent through jitsi-videobridge.\n */\nJitsiConference.prototype.sendMessage = function(message, to = '', sendThroughVideobridge = false) {\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);\n } else {\n // Broadcast\n this.sendTextMessage(messageToSend, elementName);\n }\n }\n\n};\n\nJitsiConference.prototype.isConnectionInterrupted = function() {\n return this.isP2PActive()\n ? this.isP2PConnectionInterrupted : this.isJvbConnectionInterrupted;\n};\n\n/**\n * Handles {@link XMPPEvents.CONNECTION_RESTARTED} event. This happens when the bridge goes down\n * and Jicofo moves conferences away to a different bridge.\n * @param {JingleSessionPC} session\n * @private\n */\nJitsiConference.prototype._onConferenceRestarted = function(session) {\n if (!session.isP2P && this.options.config.enableForcedReload) {\n this.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_FAILED, JitsiConferenceErrors.CONFERENCE_RESTARTED);\n }\n};\n\n/**\n * Handles {@link XMPPEvents.CONNECTION_INTERRUPTED}\n * @param {JingleSessionPC} session\n * @private\n */\nJitsiConference.prototype._onIceConnectionInterrupted = function(session) {\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 {@link XMPPEvents.CONNECTION_ICE_FAILED}\n * @param {JingleSessionPC} session\n * @private\n */\nJitsiConference.prototype._onIceConnectionFailed = function(session) {\n // We do nothing for the JVB connection, because it's up to the Jicofo to\n // eventually come up with the new offer (at least for the time being).\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 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) {\n // Use an exponential backoff timer for ICE restarts.\n const jitterDelay = getJitterDelay(this._iceRestarts, 1000 /* min. delay */);\n\n this._delayedIceFailed = new IceFailedHandling(this);\n setTimeout(() => {\n logger.error(`triggering ice restart after ${jitterDelay} `);\n this._delayedIceFailed.start(session);\n this._iceRestarts++;\n }, jitterDelay);\n }\n};\n\n/**\n * Handles {@link XMPPEvents.CONNECTION_RESTORED}\n * @param {JingleSessionPC} session\n * @private\n */\nJitsiConference.prototype._onIceConnectionRestored = function(session) {\n if (session.isP2P) {\n this.isP2PConnectionInterrupted = false;\n } else {\n this.isJvbConnectionInterrupted = false;\n this._delayedIceFailed && this._delayedIceFailed.cancel();\n }\n\n if (session.isP2P === this.isP2PActive()) {\n this.eventEmitter.emit(JitsiConferenceEvents.CONNECTION_RESTORED);\n }\n};\n\n/**\n * Accept incoming P2P Jingle call.\n * @param {JingleSessionPC} jingleSession the session instance\n * @param {jQuery} jingleOffer a jQuery selector pointing to 'jingle' IQ element\n * @private\n */\nJitsiConference.prototype._acceptP2PIncomingCall = function(jingleSession, jingleOffer) {\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 mediaType: MediaType.VIDEO,\n codecList: this.qualityController.codecController.getCodecPreferenceList('p2p'),\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 error => {\n logger.error(\n 'Failed to accept incoming P2P Jingle session', error);\n },\n localTracks);\n};\n\n/**\n * Adds remote tracks to the conference associated with the JVB session.\n * @private\n */\nJitsiConference.prototype._addRemoteJVBTracks = function() {\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 */\nJitsiConference.prototype._addRemoteP2PTracks = function() {\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} remoteTracks the tracks that will be added\n * @private\n */\nJitsiConference.prototype._addRemoteTracks = function(logName, remoteTracks) {\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 * Called when {@link XMPPEvents.CONNECTION_ESTABLISHED} event is\n * triggered for a {@link JingleSessionPC}. Switches the conference to use\n * the P2P connection if the event comes from the P2P session.\n * @param {JingleSessionPC} jingleSession the session instance.\n * @private\n */\nJitsiConference.prototype._onIceConnectionEstablished = function(jingleSession) {\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 (!isNaN(this.p2pEstablishmentDuration)\n && !isNaN(this.jvbEstablishmentDuration)) {\n const establishmentDurationDiff\n = this.p2pEstablishmentDuration - this.jvbEstablishmentDuration;\n\n Statistics.sendAnalytics(\n 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 ACTION_P2P_ESTABLISHED,\n {\n initiator: this.p2pJingleSession.isInitiator\n }));\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 */\nJitsiConference.prototype._updateProperties = function(properties = {}) {\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 * Gets a conference property with a given key.\n *\n * @param {string} key - The key.\n * @returns {*} The value\n */\nJitsiConference.prototype.getProperty = function(key) {\n return this.properties[key];\n};\n\n/**\n * Clears the deferred start P2P task if it has been scheduled.\n * @private\n */\nJitsiConference.prototype._maybeClearDeferredStartP2P = function() {\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 */\nJitsiConference.prototype._removeRemoteJVBTracks = function() {\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 */\nJitsiConference.prototype._removeRemoteP2PTracks = function() {\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} remoteTracks the tracks that will be removed\n * @private\n */\nJitsiConference.prototype._removeRemoteTracks = function(sessionNickname, remoteTracks) {\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 */\nJitsiConference.prototype._resumeMediaTransferForJvbConnection = function() {\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 JitsiConference.\n * @param {boolean} newStatus the new P2P status value, true means that\n * P2P is now in use, false means that the JVB connection is now in use\n * @private\n */\nJitsiConference.prototype._setP2PStatus = function(newStatus) {\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 */\nJitsiConference.prototype._startP2PSession = function(remoteJid) {\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 mediaType: MediaType.VIDEO,\n codecList: this.qualityController.codecController.getCodecPreferenceList('p2p'),\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};\n\n/**\n * Suspends media transfer over the JVB connection.\n * @private\n */\nJitsiConference.prototype._suspendMediaTransferForJvbConnection = function() {\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 true it means that the call\n * originates from the user left event.\n * @private\n */\nJitsiConference.prototype._maybeStartOrStopP2P = function(userLeftEvent) {\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\n\n const myId = this.myUserId();\n const peersId = peer.getId();\n\n if (myId > peersId) {\n logger.debug(\n 'I\\'m the bigger peersId - '\n + '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 const jid = peer.getJid();\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(\n `Will start P2P with: ${jid} after ${\n this.backToP2PDelay} seconds...`);\n this.deferredStartP2PTask = 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 } 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(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 */\nJitsiConference.prototype._shouldBeInP2PMode = function() {\n const peers = this.getParticipants();\n const peerCount = peers.length;\n const hasBotPeer = peers.find(p => p.getBotType() === 'poltergeist' || p.hasFeature(FEATURE_JIGASI)) !== undefined;\n const shouldBeInP2P = peerCount === 1 && !hasBotPeer && !this._hasVisitors;\n\n logger.debug(`P2P? peerCount: ${peerCount}, hasBotPeer: ${hasBotPeer} => ${shouldBeInP2P}`);\n\n return shouldBeInP2P;\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 in the session terminate message.\n * @param {boolean} options.requestRestart - Whether this is due to 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 */\nJitsiConference.prototype._stopJvbSession = function(options = {}) {\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 * 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 included in the session terminate message.\n * @param {boolean} requestRestart - Whether this is due to a session restart, in which case\n * media will not be resumed on the JVB.\n * @private\n */\nJitsiConference.prototype._stopP2PSession = function(options = {}) {\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: this.room\n && this.getParticipantById(\n Strophe.getResourceFromJid(this.p2pJingleSession.remoteJid))\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 */\nJitsiConference.prototype._updateRoomPresence = function(jingleSession, ctx) {\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, videoTypeChanged;\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.getType(), 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 * 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} true if in P2P mode or false otherwise.\n */\nJitsiConference.prototype.isP2PActive = function() {\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 null if there's currently\n * no P2P connection.\n */\nJitsiConference.prototype.getP2PConnectionState = function() {\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 */\nJitsiConference.prototype.setDesktopSharingFrameRate = function(maxFps) {\n if (typeof maxFps !== 'number' || isNaN(maxFps)) {\n logger.error(`Invalid value ${maxFps} specified for desktop capture frame rate`);\n\n return false;\n }\n\n this._desktopSharingFrameRate = maxFps;\n\n // Set capture fps for screenshare.\n this.jvbJingleSession && this.jvbJingleSession.peerconnection.setDesktopSharingFrameRate(maxFps);\n\n // Set the capture rate for desktop sharing.\n this.rtc.setDesktopSharingFrameRate(maxFps);\n\n return true;\n};\n\n/**\n * Manually starts new P2P session (should be used only in the tests).\n */\nJitsiConference.prototype.startP2PSession = function() {\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 */\nJitsiConference.prototype.stopP2PSession = function(options) {\n this._stopP2PSession(options);\n};\n\n/**\n * Get a summary of how long current participants have been the dominant speaker\n * @returns {object}\n */\nJitsiConference.prototype.getSpeakerStats = function() {\n return this.speakerStatsCollector.getStats();\n};\n\n/**\n * Sends a face landmarks object to the xmpp server.\n * @param {Object} payload\n */\nJitsiConference.prototype.sendFaceLandmarks = function(payload) {\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 {Object} 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. 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 */\nJitsiConference.prototype.setReceiverConstraints = function(videoConstraints) {\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 */\nJitsiConference.prototype.setAssumedBandwidthBps = function(assumedBandwidthBps) {\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 */\nJitsiConference.prototype.setReceiverVideoConstraint = function(maxFrameHeight) {\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 */\nJitsiConference.prototype.setSenderVideoConstraint = function(maxFrameHeight) {\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 {@link JitsiConference.isVideoSIPGWAvailable}. 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 */\nJitsiConference.prototype.createVideoSIPGWSession = function(sipAddress, displayName) {\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 * Sends a conference.join analytics event.\n *\n * @returns {void}\n */\nJitsiConference.prototype._sendConferenceJoinAnalyticsEvent = function() {\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 gumDuration: safeSubtract(gumEnd, gumStart),\n xmppConnectingTime: safeSubtract(xmppConnectionTimes.connected, xmppConnectionTimes.connecting),\n connectedToMUCJoinedTime: safeSubtract(\n conferenceConnectionTimes['muc.joined'], xmppConnectionTimes.connected),\n connectingToMUCJoinedTime: safeSubtract(\n conferenceConnectionTimes['muc.joined'], xmppConnectionTimes.connecting),\n numberOfParticipantsOnJoin: this._numberOfParticipantsOnJoin\n };\n\n Statistics.sendAnalytics(createConferenceEvent('joined', {\n ...connectionTimes,\n meetingId,\n participantId: `${meetingId}.${this._statsCurrentId}`\n }));\n this._conferenceJoinAnalyticsEventSent = Date.now();\n};\n\n/**\n * Sends conference.left analytics event.\n * @private\n */\nJitsiConference.prototype._sendConferenceLeftAnalyticsEvent = function() {\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 perf: this.getPerformanceStats()\n }\n }));\n};\n\n/**\n * Restarts all active media sessions.\n *\n * @returns {void}\n */\nJitsiConference.prototype._restartMediaSessions = function() {\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 * Returns whether End-To-End encryption is enabled.\n *\n * @returns {boolean}\n */\nJitsiConference.prototype.isE2EEEnabled = function() {\n return Boolean(this._e2eEncryption && 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 */\nJitsiConference.prototype.isE2EESupported = function() {\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 */\nJitsiConference.prototype.toggleE2EE = function(enabled) {\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 */\nJitsiConference.prototype.setMediaEncryptionKey = function(keyInfo) {\n this._e2eEncryption.setEncryptionKey(keyInfo);\n};\n\n/**\n * Starts the participant verification process.\n *\n * @param {string} participantId The participant which will be marked as verified.\n * @returns {void}\n */\nJitsiConference.prototype.startVerification = function(participantId) {\n const participant = this.getParticipantById(participantId);\n\n if (!participant) {\n return;\n }\n\n this._e2eEncryption.startVerification(participant);\n};\n\n/**\n * Marks the given participant as verified. After this is done, MAC verification will\n * be performed and an event will be emitted with the result.\n *\n * @param {string} participantId The participant which will be marked as verified.\n * @param {boolean} isVerified - whether the verification was succesfull.\n * @returns {void}\n */\nJitsiConference.prototype.markParticipantVerified = function(participantId, isVerified) {\n const participant = this.getParticipantById(participantId);\n\n if (!participant) {\n return;\n }\n\n this._e2eEncryption.markParticipantVerified(participant, isVerified);\n};\n\n/**\n * Returns true if lobby support is enabled in the backend.\n *\n * @returns {boolean} whether lobby is supported in the backend.\n */\nJitsiConference.prototype.isLobbySupported = function() {\n return Boolean(this.room && this.room.getLobby().isSupported());\n};\n\n/**\n * Returns true if the room has members only enabled.\n *\n * @returns {boolean} whether conference room is members only.\n */\nJitsiConference.prototype.isMembersOnly = function() {\n return Boolean(this.room && this.room.membersOnlyEnabled);\n};\n\n/**\n * Returns true if the room supports visitors feature.\n *\n * @returns {boolean} whether conference room has visitors support.\n */\nJitsiConference.prototype.isVisitorsSupported = function() {\n return Boolean(this.room && 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 */\nJitsiConference.prototype.enableLobby = function() {\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 */\nJitsiConference.prototype.disableLobby = function() {\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}\n */\nJitsiConference.prototype.joinLobby = function(displayName, email) {\n if (this.room) {\n return this.room.getLobby().join(displayName, email);\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 */\nJitsiConference.prototype.myLobbyUserId = function() {\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 {message} Object The message to send\n * @param {string} id The participant id.\n *\n * @returns {void}\n */\nJitsiConference.prototype.sendLobbyMessage = function(message, id) {\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 */\nJitsiConference.prototype.addLobbyMessageListener = function(listener) {\n if (this.room) {\n return this.room.getLobby().addMessageListener(listener);\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 */\nJitsiConference.prototype.removeLobbyMessageHandler = function(handler) {\n if (this.room) {\n return this.room.getLobby().removeMessageHandler(handler);\n }\n};\n\n/**\n * Denies an occupant in the lobby room access to the conference.\n * @param {string} id The participant id.\n */\nJitsiConference.prototype.lobbyDenyAccess = function(id) {\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} param The participant id or an array of ids.\n */\nJitsiConference.prototype.lobbyApproveAccess = function(param) {\n if (this.room) {\n this.room.getLobby().approveAccess(param);\n }\n};\n\n/**\n * Returns true if AV Moderation support is enabled in the backend.\n *\n * @returns {boolean} whether AV Moderation is supported in the backend.\n */\nJitsiConference.prototype.isAVModerationSupported = function() {\n return Boolean(this.room && this.room.getAVModeration().isSupported());\n};\n\n/**\n * Enables AV Moderation.\n * @param {MediaType} mediaType \"audio\" or \"video\"\n */\nJitsiConference.prototype.enableAVModeration = function(mediaType) {\n if (this.room && this.isModerator()\n && (mediaType === MediaType.AUDIO || 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\" or \"video\"\n */\nJitsiConference.prototype.disableAVModeration = function(mediaType) {\n if (this.room && this.isModerator()\n && (mediaType === MediaType.AUDIO || 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\" or \"video\"\n * @param id the id of the participant.\n */\nJitsiConference.prototype.avModerationApprove = function(mediaType, id) {\n if (this.room && this.isModerator()\n && (mediaType === MediaType.AUDIO || 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\" or \"video\"\n * @param id the id of the participant.\n */\nJitsiConference.prototype.avModerationReject = function(mediaType, id) {\n if (this.room && this.isModerator()\n && (mediaType === MediaType.AUDIO || 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 {Object} the breakout rooms manager.\n */\nJitsiConference.prototype.getBreakoutRooms = function() {\n return this.room?.getBreakoutRooms();\n};\n\n/**\n * Returns the metadata handler object.\n *\n * @returns {Object} the room metadata handler.\n */\nJitsiConference.prototype.getMetadataHandler = function() {\n return this.room?.getMetadataHandler();\n};\n","import JitsiConference from './JitsiConference';\nimport * as JitsiConnectionEvents from './JitsiConnectionEvents';\nimport FeatureFlags from './modules/flags/FeatureFlags';\nimport Statistics from './modules/statistics/statistics';\nimport XMPP from './modules/xmpp/xmpp';\nimport {\n CONNECTION_DISCONNECTED as ANALYTICS_CONNECTION_DISCONNECTED,\n createConnectionFailedEvent\n} from './service/statistics/AnalyticsEvents';\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 * @param appID identification for the provider of Jitsi Meet video conferencing\n * 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\n * the server.\n * @constructor\n */\nexport default function JitsiConnection(appID, token, options) {\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 /* eslint-disable max-params */\n this.addEventListener(JitsiConnectionEvents.CONNECTION_FAILED,\n (errType, msg, credentials, details) => {\n Statistics.sendAnalyticsAndLog(\n createConnectionFailedEvent(errType, msg, details));\n });\n /* eslint-enable max-params */\n\n this.addEventListener(JitsiConnectionEvents.CONNECTION_DISCONNECTED,\n msg => {\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 ANALYTICS_CONNECTION_DISCONNECTED,\n { message: msg });\n }\n });\n}\n\n/**\n * Connect the client with the server.\n * @param options {object} connecting options (for example authentications parameters).\n * @param options.id {string} The username to use when connecting, if any.\n * @param options.password {string} The password to use when connecting with username, if any.\n * @param options.name {string} 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 */\nJitsiConnection.prototype.connect = function(options = {}) {\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 this.xmpp.moderator.sendConferenceRequest(this.xmpp.getRoomJid(options.name))\n .then(() => {\n this.xmpp.connect(options.id, options.password);\n });\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 {object} connecting options - rid, sid and jid.\n */\nJitsiConnection.prototype.attach = function(options) {\n this.xmpp.attach(options);\n};\n\n/**\n * Disconnect the client from the server.\n * @returns {Promise} - Resolves when the disconnect process is finished or rejects with an error.\n */\nJitsiConnection.prototype.disconnect = function(...args) {\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 {string} The jid of the participant.\n */\nJitsiConnection.prototype.getJid = function() {\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 */\nJitsiConnection.prototype.setToken = function(token) {\n this.token = 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 {JitsiConference} returns the new conference object.\n */\nJitsiConnection.prototype.initJitsiConference = function(name, options) {\n return new JitsiConference({\n name,\n config: options,\n connection: this\n });\n};\n\n/**\n * Subscribes the passed listener to the event.\n * @param event {JitsiConnectionEvents} the connection event.\n * @param listener {Function} the function that will receive the event\n */\nJitsiConnection.prototype.addEventListener = function(event, listener) {\n this.xmpp.addListener(event, listener);\n};\n\n/**\n * Unsubscribes the passed handler.\n * @param event {JitsiConnectionEvents} the connection event.\n * @param listener {Function} the function that will receive the event\n */\nJitsiConnection.prototype.removeEventListener = function(event, listener) {\n this.xmpp.removeListener(event, listener);\n};\n\n/**\n * Returns measured connectionTimes.\n */\nJitsiConnection.prototype.getConnectionTimes = function() {\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 {String} feature the name of the feature.\n * @param {boolean} submit if true - the new list of features will be\n * immediately submitted to the others.\n */\nJitsiConnection.prototype.addFeature = function(feature, submit = false) {\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 {String} feature the name of the feature.\n * @param {boolean} submit if true - the new list of features will be\n * immediately submitted to the others.\n */\nJitsiConnection.prototype.removeFeature = function(feature, submit = false) {\n this.xmpp.caps.removeFeature(feature, submit, true);\n};\n\n/**\n * Get object with internal logs.\n */\nJitsiConnection.prototype.getLogs = function() {\n const data = this.xmpp.getJingleLog();\n\n const metadata = {};\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 * The events for the media devices.\n */\n\nexport enum JitsiMediaDevicesEvents {\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\n// exported for backward compatibility\nexport const DEVICE_LIST_CHANGED = JitsiMediaDevicesEvents.DEVICE_LIST_CHANGED;\nexport const PERMISSIONS_CHANGED = JitsiMediaDevicesEvents.PERMISSIONS_CHANGED;\nexport const PERMISSION_PROMPT_IS_SHOWN = JitsiMediaDevicesEvents.PERMISSION_PROMPT_IS_SHOWN;\n","import * as 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';\nconst PERMISSION_GRANTED_STATUS = 'granted';\nconst VIDEO_PERMISSION_NAME = 'camera';\n\n/**\n * Media devices utilities for Jitsi.\n */\nclass JitsiMediaDevices extends Listenable {\n /**\n * Initializes a {@code JitsiMediaDevices} object. There will be a single\n * instance of this class.\n */\n constructor() {\n super();\n this._permissions = {};\n }\n\n /**\n * Initialize. Start listening for device changes and initialize permissions checks.\n */\n init() {\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 self = this;\n\n const promises = [];\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 = function() {\n try {\n self._handlePermissionsChange({\n [MediaType.VIDEO]: self._parsePermissionState(this)\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 = function() {\n try {\n self._handlePermissionsChange({\n [MediaType.AUDIO]: self._parsePermissionState(this)\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 * 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 _parsePermissionState(permissionStatus = {}) {\n // The status attribute is deprecated, and state\n // should be used instead, but check both for now\n // for backwards compatibility.\n const status = permissionStatus.state || permissionStatus.status;\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 {@code true} or {@code false} respectively.\n *\n * @param {Object} permissions - Object with the permissions.\n */\n _handlePermissionsChange(permissions) {\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 // eslint-disable-next-line no-empty-function\n this.enumerateDevices(() => {});\n }\n }\n }\n\n /**\n * Executes callback with list of media devices connected.\n * @param {function} callback\n */\n enumerateDevices(callback) {\n RTC.enumerateDevices(callback);\n }\n\n /**\n * Checks if its possible to enumerate available cameras/micropones.\n * @returns {Promise} a Promise which will be resolved only once\n * the WebRTC stack is ready, either with true if the device listing is\n * available available or with false otherwise.\n */\n isDeviceListAvailable() {\n return RTC.isDeviceListAvailable();\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) {\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}\n */\n isDevicePermissionGranted(type) {\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 = [];\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() {\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() {\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) {\n return RTC.setAudioOutputDevice(deviceId);\n }\n}\n\nexport default new JitsiMediaDevices();\n","import { getLogger } from '@jitsi/logger';\n\nimport * as JitsiTrackEvents from '../../JitsiTrackEvents';\nimport RTC from '../RTC/RTC';\nimport Statistics from '../statistics/statistics';\n\n\nconst logger = getLogger(__filename);\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 - Object containing information about the found device.\n */\nexport default function getActiveAudioDevice() {\n\n return new Promise(resolve => {\n RTC.enumerateDevices(devices => {\n const audioDevices = devices.filter(device => device.kind === 'audioinput');\n const devicePromiseArray = [];\n\n\n for (const micDevice of audioDevices) {\n const devicePromise = RTC.obtainAudioAndVideoPermissions({ devices: [ 'audio' ],\n micDeviceId: micDevice.deviceId }).then(tracks => {\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.value);\n const rejectReasons = rejectedPromises.map(p => p.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({ deviceId: device.deviceId,\n deviceLabel: device.track.label });\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} deviceList - Array of JitsiLocalTracks to stop.\n * @returns {void}\n */\nfunction stopActiveDevices(deviceList) {\n for (const device of deviceList) {\n device.stopStream();\n }\n}\n","import { getLogger } from '@jitsi/logger';\n\nimport SignalingLayer from '../../service/RTC/SignalingLayer';\n\nconst logger = getLogger(__filename);\n\n/**\n * Custom semi-mock implementation for the Proxy connection service.\n */\nexport default class CustomSignalingLayer extends SignalingLayer {\n /**\n * Creates new instance.\n */\n constructor() {\n super();\n\n /**\n * A map that stores SSRCs of remote streams.\n * @type {Map} maps SSRC number to jid\n */\n this.ssrcOwners = new Map();\n\n /**\n *\n * @type {ChatRoom|null}\n */\n this.chatRoom = null;\n }\n\n /**\n * @inheritDoc\n */\n getPeerMediaInfo(owner, mediaType, sourceName) { // eslint-disable-line no-unused-vars\n return {};\n }\n\n /**\n * @inheritDoc\n */\n getPeerSourceInfo(owner, sourceName) { // eslint-disable-line no-unused-vars\n return undefined;\n }\n\n /**\n * @inheritDoc\n */\n getSSRCOwner(ssrc) {\n return this.ssrcOwners.get(ssrc);\n }\n\n /**\n * @inheritDoc\n */\n getTrackSourceName(ssrc) { // eslint-disable-line no-unused-vars\n return undefined;\n }\n\n /**\n * @inheritDoc\n */\n removeSSRCOwners(ssrcList) {\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 ChatRoom instance used.\n * @param {ChatRoom} room\n */\n setChatRoom(room) {\n this.chatRoom = room;\n }\n\n /**\n * @inheritDoc\n */\n setSSRCOwner(ssrc, endpointId) {\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 setTrackMuteStatus(sourceName, muted) { // eslint-disable-line no-unused-vars\n return false;\n }\n\n /**\n * @inheritDoc\n */\n setTrackVideoType(sourceName, videoType) { // eslint-disable-line no-unused-vars\n return false;\n }\n\n /**\n * @inheritDoc\n */\n updateSsrcOwnersOnLeave(id) {\n const ssrcs = Array.from(this.ssrcOwners)\n .filter(entry => entry[1] === id)\n .map(entry => 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 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(__filename);\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 pcConfig: {},\n isInitiator: false,\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}\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 {Object} $jingle - An XML jingle element, wrapped in query,\n * describing how the peer connection should be updated.\n * @returns {void}\n */\n processMessage($jingle) {\n switch ($jingle.attr('action')) {\n case ACTIONS.ACCEPT:\n this._onSessionAccept($jingle);\n break;\n\n case ACTIONS.INITIATE:\n this._onSessionInitiate($jingle);\n break;\n\n case ACTIONS.TERMINATE:\n this._onSessionTerminate($jingle);\n break;\n\n case ACTIONS.TRANSPORT_INFO:\n this._onTransportInfo($jingle);\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} 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 connected: true,\n jingle: {\n terminate: () => { /** no-op */ }\n },\n sendIQ: this._onSendMessage,\n\n // Returns empty function, because it does not add any listeners for real.\n // eslint-disable-next-line no-empty-function\n addEventListener: () => () => { },\n\n // eslint-disable-next-line no-empty-function\n addCancellableListener: () => () => { }\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 supportsRestartByTerminate: () => false\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 occured.\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 {Object} $jingle - The jingle element wrapped in jQuery.\n * @private\n * @returns {void}\n */\n _onSessionAccept($jingle) {\n if (!this._peerConnection) {\n logger.error('Received an answer when no peer connection exists.');\n\n return;\n }\n\n this._peerConnection.setAnswer($jingle);\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 {Object} $jingle - The jingle element wrapped in jQuery.\n * @private\n * @returns {void}\n */\n _onSessionInitiate($jingle) {\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 $jingle,\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 {Object} $jingle - The jingle element wrapped in jQuery.\n * @private\n * @returns {void}\n */\n _onTransportInfo($jingle) {\n this._peerConnection.addIceCandidates($jingle);\n }\n}\n","import { getLogger } from '@jitsi/logger';\nimport $ from 'jquery';\nimport { $iq } from 'strophe.js';\n\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(__filename);\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 $jingle = iq && iq.find('jingle');\n const action = $jingle && $jingle.attr('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) {\n this._peerConnection.processMessage($jingle);\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 return;\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} 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 wrapped in jQuery.\n *\n * @param {string} xml - The XML in string form.\n * @private\n * @returns {Object|null} A jQuery 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 = new DOMParser().parseFromString(xml, 'text/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 pcConfig: this._options.pcConfig,\n onError: this._onFatalError,\n onRemoteStream: this._onRemoteStream,\n onSendMessage: this._onSendMessage,\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 occured.\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 xmlns: 'urn:xmpp:jingle:1',\n action: errorType\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","import { getLogger } from '@jitsi/logger';\n\nimport { createAudioContext } from './WebAudioUtils';\n\nconst logger = getLogger(__filename);\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 /**\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) {\n if (!stream.getAudioTracks()) {\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 {MediaStream} - MediaStream containing added streams mixed together, or null if no MediaStream\n * is added.\n */\n start() {\n // If the mixer was already started just return the existing mixed stream.\n if (this._started) {\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() {\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 }\n}\n","import Logger from '@jitsi/logger';\n\nimport * as JitsiConferenceErrors from './JitsiConferenceErrors';\nimport * as JitsiConferenceEvents from './JitsiConferenceEvents';\nimport JitsiConnection from './JitsiConnection';\nimport * as JitsiConnectionErrors from './JitsiConnectionErrors';\nimport * as JitsiConnectionEvents from './JitsiConnectionEvents';\nimport JitsiMediaDevices from './JitsiMediaDevices';\nimport * as JitsiMediaDevicesEvents from './JitsiMediaDevicesEvents';\nimport JitsiTrackError from './JitsiTrackError';\nimport * as JitsiTrackErrors from './JitsiTrackErrors';\nimport * as JitsiTrackEvents from './JitsiTrackEvents';\nimport * as JitsiTranscriptionStatus from './JitsiTranscriptionStatus';\nimport RTC from './modules/RTC/RTC';\nimport RTCStats from './modules/RTCStats/RTCStats';\nimport browser from './modules/browser';\nimport NetworkInfo from './modules/connectivity/NetworkInfo';\nimport { TrackStreamingStatus } from './modules/connectivity/TrackStreamingStatus';\nimport getActiveAudioDevice from './modules/detection/ActiveDeviceDetector';\nimport * as 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 Statistics from './modules/statistics/statistics';\nimport ScriptUtil from './modules/util/ScriptUtil';\nimport * as VideoSIPGWConstants from './modules/videosipgw/VideoSIPGWConstants';\nimport AudioMixer from './modules/webaudio/AudioMixer';\nimport { MediaType } from './service/RTC/MediaType';\nimport * as ConnectionQualityEvents\n from './service/connectivity/ConnectionQualityEvents';\nimport * as E2ePingEvents from './service/e2eping/E2ePingEvents';\nimport { createGetUserMediaEvent } from './service/statistics/AnalyticsEvents';\nimport * as RTCStatsEvents from './modules/RTCStats/RTCStatsEvents';\nimport { VideoType } from './service/RTC/VideoType';\n\nconst logger = Logger.getLogger(__filename);\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 attributes['audio_requested'] = options.devices.includes('audio');\n attributes['video_requested'] = options.devices.includes('video');\n attributes['screen_sharing_requested'] = options.devices.includes('desktop');\n\n if (attributes.video_requested) {\n attributes.resolution = options.resolution;\n }\n\n return attributes;\n}\n\ninterface ICreateLocalTrackOptions {\n cameraDeviceId?: string;\n devices?: any[];\n firePermissionPromptIsShownEvent?: boolean;\n fireSlowPromiseEvent?: boolean;\n micDeviceId?: string;\n resolution?: string;\n}\n\ninterface IJitsiMeetJSOptions {\n enableAnalyticsLogging?: boolean;\n enableWindowOnErrorHandler?: boolean;\n externalStorage?: Storage;\n flags?: {\n runInLiteMode?: boolean;\n ssrcRewritingEnabled?: boolean;\n }\n}\n\ninterface ICreateLocalTrackFromMediaStreamOptions {\n stream: MediaStream,\n sourceType: string,\n mediaType: MediaType,\n videoType?: VideoType\n}\n\n/**\n * The public API of the Jitsi Meet library (a.k.a. {@code JitsiMeetJS}).\n */\nexport default {\n\n version: '{#COMMIT_HASH#}',\n\n JitsiConnection,\n\n /**\n * {@code ProxyConnectionService} is used to connect a remote peer to a\n * local Jitsi participant without going through a Jitsi conference. It is\n * currently used for room integration development, specifically wireless\n * screensharing. Its API is experimental and will likely change; usage of\n * it is advised against.\n */\n ProxyConnectionService,\n\n constants: {\n recording: recordingConstants,\n sipVideoGW: VideoSIPGWConstants,\n transcriptionStatus: JitsiTranscriptionStatus,\n trackStreamingStatus: TrackStreamingStatus\n },\n events: {\n conference: JitsiConferenceEvents,\n connection: JitsiConnectionEvents,\n detection: DetectionEvents,\n track: JitsiTrackEvents,\n mediaDevices: JitsiMediaDevicesEvents,\n connectionQuality: ConnectionQualityEvents,\n e2eping: E2ePingEvents,\n rtcstats: RTCStatsEvents\n },\n errors: {\n conference: JitsiConferenceErrors,\n connection: JitsiConnectionErrors,\n track: JitsiTrackErrors\n },\n errorTypes: {\n JitsiTrackError\n },\n logLevels: Logger.levels,\n mediaDevices: JitsiMediaDevices as unknown,\n analytics: Statistics.analytics as unknown,\n init(options: IJitsiMeetJSOptions = {}) {\n Logger.setLogLevel(Logger.levels.INFO);\n\n // @ts-ignore\n logger.info(`This appears to be ${browser.getName()}, ver: ${browser.getVersion()}`);\n\n JitsiMediaDevices.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 return RTC.init(options);\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 * 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 isWebRtcSupported() {\n return RTC.isWebRtcSupported();\n },\n\n setLogLevel(level) {\n Logger.setLogLevel(level);\n },\n\n /**\n * Expose rtcstats to the public API.\n */\n rtcstats: {\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, data) {\n RTCStats.sendStatsEntry(statsType, null, data);\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 /**\n * Sets the log level to the Logger 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 * 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 * 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 * 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 * Creates local media tracks.\n *\n * @param options Object with properties / settings specifying the tracks\n * which should be created. should be created or some additional\n * configurations about resolution for example.\n * @param {Array} options.effects optional effects array for the track\n * @param {boolean} options.firePermissionPromptIsShownEvent - if event\n * JitsiMediaDevicesEvents.PERMISSION_PROMPT_IS_SHOWN should be fired\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.}, JitsiConferenceError>} A promise\n * that returns an array of created JitsiTracks if resolved, or a\n * JitsiConferenceError if rejected.\n */\n createLocalTracks(options: ICreateLocalTrackOptions = {}) {\n const { firePermissionPromptIsShownEvent, ...restOptions } = options;\n\n if (firePermissionPromptIsShownEvent && !RTC.arePermissionsGrantedForAvailableDevices()) {\n // @ts-ignore\n JitsiMediaDevices.emit(JitsiMediaDevicesEvents.PERMISSION_PROMPT_IS_SHOWN, browser.getName());\n }\n\n let isFirstGUM = false;\n let 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(restOptions)\n .then(tracks => {\n let 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(restOptions)));\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 let 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} tracksInfo - array of track information\n * @returns {Array} - created local tracks\n */\n createLocalTracksFromMediaStreams(tracksInfo) {\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 throw new JitsiTrackError(JitsiTrackErrors.TRACK_NO_STREAM_TRACKS_FOUND, null, null);\n }\n\n if (tracks.length > 1) {\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 * @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 * - getSampleLength() - Returns the sample size accepted by calculateAudioFrameVAD.\n * - getRequiredPCMFrequency() - Returns the PCM frequency at which the processor operates.\n * i.e. (16KHz, 44.1 KHz etc.)\n * - calculateAudioFrameVAD(pcmSample) - Process a 32 float pcm sample of getSampleLength size.\n * @returns {Promise}\n */\n createTrackVADEmitter(localAudioDeviceId, sampleRate, vadProcessor) {\n return TrackVADEmitter.create(localAudioDeviceId, sampleRate, vadProcessor);\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 * Go through all audio devices on the system and return one that is active, i.e. has audio signal.\n *\n * @returns Promise - Object containing information about the found device.\n */\n getActiveAudioDevice() {\n return getActiveAudioDevice();\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 * Checks if local tracks can collect stats and collection is enabled.\n *\n * @param {boolean} True if stats are being collected for local tracks.\n */\n isCollectingLocalStats() {\n return Statistics.audioLevelsEnabled && LocalStatsCollector.isLocalStatsSupported();\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 - {@code true} if the internet connectivity is online or {@code 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};\n","export default {\n error: {\n BUSY: 'busy',\n ERROR: 'error',\n RESOURCE_CONSTRAINT: 'resource-constraint',\n UNEXPECTED_REQUEST: 'unexpected-request',\n SERVICE_UNAVAILABLE: 'service-unavailable'\n },\n mode: {\n FILE: 'file',\n STREAM: 'stream'\n },\n status: {\n OFF: 'off',\n ON: 'on',\n PENDING: 'pending'\n }\n};\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\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","__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__.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};","__webpack_require__.nmd = (module) => {\n\tmodule.paths = [];\n\tif (!module.children) module.children = [];\n\treturn module;\n};","// 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__(449);\n"],"names":["root","factory","exports","module","define","amd","self","ljm","require","window","JitsiMeetJS","Object","assign","_mergeNamespaceAndModule","constructor","userId","displayName","isLocalStats","this","_userId","setDisplayName","_isLocalStats","setDominantSpeaker","totalDominantSpeakerTime","_dominantSpeakerStart","_isDominantSpeaker","_isSilent","_hasLeft","_faceLandmarks","getUserId","getDisplayName","newName","isDominantSpeaker","isNowDominantSpeaker","silence","Date","now","timeElapsed","getTotalDominantSpeakerTime","total","hasLeft","markAsHasLeft","getFaceLandmarks","setFaceLandmarks","faceLandmarks","addFaceLandmarks","push","randomInt","min","max","Math","floor","random","randomElement","arr","length","RandomUtil","randomHexDigit","randomHexString","len","ret","randomAlphanumStr","result","i","currentExecutingScript","ScriptUtil","loadScript","src","async","prepend","relativeURL","loadCallback","errorCallback","d","document","tagName","script","createElement","referenceNode","getElementsByTagName","scriptEl","scriptSrc","baseScriptSrc","substring","lastIndexOf","onload","onerror","parentNode","insertBefore","appendChild","names","generateUsername","internals","parse","text","firstOptions","arguments","undefined","reviver","options","obj","JSON","protoAction","match","scan","next","nodes","node","prototype","hasOwnProperty","call","SyntaxError","__proto__","key","value","safeParse","ignoreError","FUNC_TYPE","UNDEF_TYPE","OBJ_TYPE","STR_TYPE","MAJOR","MODEL","NAME","TYPE","VENDOR","VERSION","ARCHITECTURE","CONSOLE","MOBILE","TABLET","SMARTTV","WEARABLE","EMBEDDED","AMAZON","APPLE","ASUS","BLACKBERRY","BROWSER","CHROME","FIREFOX","GOOGLE","HUAWEI","LG","MICROSOFT","MOTOROLA","OPERA","SAMSUNG","SHARP","SONY","XIAOMI","ZEBRA","FACEBOOK","CHROMIUM_OS","MAC_OS","enumerize","enums","toUpperCase","has","str1","str2","lowerize","indexOf","str","toLowerCase","trim","replace","rgxMapper","ua","arrays","j","k","p","q","matches","regex","props","exec","test","strMapper","map","windowsVersionMap","regexes","browser","cpu","device","engine","EDGE","os","UAParser","extensions","getResult","_navigator","navigator","_ua","userAgent","_uach","userAgentData","_rgxmap","mergedRegexes","concat","extend","_isSelfNav","getBrowser","version","_browser","split","brave","isBrave","getCPU","_cpu","getDevice","_device","mobile","standalone","maxTouchPoints","getEngine","_engine","getOS","_os","platform","getUA","setUA","CPU","DEVICE","ENGINE","OS","$","jQuery","Zepto","parser","get","set","prop","Logger","LogCollector","logStorage","stringifyObjects","storeInterval","maxEntryLength","values","levels","forEach","logLevel","_log","apply","bind","storeLogsIntervalID","queue","totalLen","outputCache","stringify","someObject","error","formatLogMessage","msg","arg","Error","toString","stack","timestamp","prevMessage","count","_flush","start","_reschedulePublishInterval","clearTimeout","setTimeout","flush","_storeLogs","logs","storeLogs","console","force","reschedule","logStorageReady","isReady","cachedQueue","stop","consoleTransport","globalTransports","addGlobalTransport","transport","removeGlobalTransport","transportIdx","splice","globalOptions","log","logger","level","args","Array","slice","callerInfo","disableCallerInfo","methodName","fileLocation","line","column","m","substr","getCallerInfo","transports","t","l","logPrefixes","toISOString","id","fullLogParts","methods","keys","setGlobalOptions","setLevel","TRACE","DEBUG","INFO","LOG","WARN","ERROR","idLoggers","loggers","curLevel","getLogger","getUntrackedLogger","setLogLevelById","setLogLevel","grammar","v","name","reg","o","format","s","u","e","z","r","c","b","a","encoding","rate","address","subtype","direction","config","sessionConfig","raddr","tcptype","generation","attribute","maxMessageSize","params","RegExp","dir2","clksrcExt","mediaClockValue","rateNumerator","rateDenominator","writer","write","parseParams","parseFmtpConfig","parsePayloads","parseRemoteCandidates","parseImageAttributes","parseSimulcastStreamList","toIntIfInt","String","Number","parseReg","location","content","needsBlank","keyLocation","rawName","attachProperties","validLine","sdp","session","media","filter","type","rtp","fmtp","paramReducer","acc","expr","reduce","candidates","parts","component","ip","port","item","stream","scid","paused","formatRegExp","formatStr","x","makeLine","Function","n","defaultOuterOrder","defaultInnerOrder","opts","mLine","payloads","outerOrder","innerOrder","el","join","sdk_1","watchrtcConfig","services","initSDK","setConfig","_rtcTags","rating","comment","setUserRating","addKeys","disableDataCollection","enableDataCollection","event","addEvent","mapStream","mapTrack","connect","disconnect","listener","registerOnStatsListener","nailUpCallEnd","persistentEnd","roomId","peerId","persistentStart","registerStateListener","default","init","addTags","addStatsListener","addStateListener","qualityrtc","run","qrtcRun","qrtcStop","__assign","__awaiter","thisArg","_arguments","P","generator","Promise","resolve","reject","fulfilled","step","rejected","done","then","__generator","body","f","y","g","_","label","sent","trys","ops","verb","Symbol","iterator","op","TypeError","pop","__spreadArray","to","from","pack","ar","defineProperty","sdkLogWithoutTrace","sdkLog","trace","getStatsInterval","hardwareInfo","currentAudioOutputId","reconnectTimerId","watchrtcsocket_1","watchrtchttp_1","utils_1","version_1","isBrowser","globalContext","isFirefox","mozRTCPeerConnection","openChannels","RTCPeerConnection","webkitGetUserMedia","peerconnectioncounter","connectionData","watchrtcIdentifiers","rtcRoomId","rtcPeerId","projectId","http","socket","lastConnectionOpen","tryingToConnectSocket","authFailed","lostConnectionTs","isManualConnect","isManualDisconnect","getStatsCallback","stateListener","freshConnection","getSdkLogger","getSdkLogWithoutTrace","debugTrack","track","kind","readyState","muted","mappedTrack","maybeOpenWebsocketConnection","_a","_b","_c","forceRecreate","_d","reconnecting","_e","pcId","_f","nailUp","isDisabledDataCollection","disabled","connection","WebSocket","OPEN","isRoomIdOrPeerIdChanged","close","connectionCount","countOfValidConnections","canConnect","validateConfig","useToken","rtcToken","wsConnectionData","getConnectionData","rtcApiKey","proxyUrl","startStatsCollection","wsOpeningTimestamp","url","cleanOldTraces","onData","data","_i","entries","allowBrowserLogCollection","Boolean","collectConsoleLogEnabled","override","collectConsoleLogLevel","setConsoleLevel","restoreOriginalConsoleMethods","buffer","connectionId","interval","collectionInterval","oldInterval","resetConnectionState","sdkVersion","watchRTCSessionId","onError","onOpen","connectionStatus","reconnectDuration","clearInterval","delta","onClose","closeEvent","code","reason","wasClean","setInterval","_loop_1","pcInfo","pc","signalingState","getStats","res","report","map2obj","nailUpRef","stats","peer","streams","logGetStats","connections","__reject","id_1","pc_1","prev_1","prev","nailUpRef_1","base","applyPatchForRTT","subtractNailUpReferenceStats","deltaCompression","exposeApplicationStatsForPC","watchrtc","prefixesToWrap","watchRTCInitialized","generateID","getHardwareStartTime","getHardwareInfo","hwInfo","getHardwareTime","catch","err","message","urlParams","URLSearchParams","search","socketService","httpService","wsUrl","debug","prefix","origPeerConnection","peerconnection","constraints","__rtcStatsId","validConnection","nullConfig","iceServers","server","credential","browserType","addEventListener","candidate","errorCode","errorText","getTracks","iceConnectionState","iceGatheringState","connectionState","channel","HTMLMediaElement","nativeMethod_1","setSinkId","selectedDeviceId","mediaDevices","enumerateDevices","devices","currentDevice","find","deviceId","RTCRtpTransceiver","origRTCRtpTransceiver","nativeMethod_2","setCodecPreferences","__pcId","RTCRtpSender","nativeMethod_3","origRTCRtpSender","setParameters","nativeMethod_4","replaceTrack","originalTrack","method","nativeMethod","_this_1","trackOrKind","transceiver","sender","streamInfo","transceivers","getTransceivers","rtcStatsId","description","_this","needToHandleSDPInSuccessCallback","parameterless","localDescription","generateCertificate","origGetUserMedia","cb","eb","dumpStream","errorData","httpReportError","getUserMedia","origGetUserMedia_1","getDisplayMedia","origGetDisplayMedia_1","newWatchrtcConfig","ratingComment","validateRating","opened","promiseFuncs","httpTrace","wasConnected","validateEvent","validatedEvent","source","httpConnectionData","apiKey","loadJS","head","qrtcStopRequest","progressCallback","answer","codeUrl","queryParams_1","isNetlifyRequest","configUrl","configAnswer","codeLoad","qualityRTC","progressCallbackWrapper","configData","netlifyBaseUrl","all","fetch","json","__qualityRTC","progress","jsonConfig","URL","origin","isProbe","wakeLock","getStreamsFromStats","getTransportFromStats","reports","reportKeys","keyPairs","reportKey","nominated","localCandidateId_1","localCandidateId","remoteCandidateId_1","remoteCandidateId","localCandidateKey","remoteCandidateKey","localCandidate","remoteCandidate","candidateType","relayProtocol","previous","current","currentReportsKeys","streamKey","currentReport","previousReport","currentRemoteReport","remoteId","previousRemoteReport","deltaSeconds","frameWidth","frameHeight","framerate","framesPerSecond","jitter","mappedName","trackIdentifier","bytesReceived","packetsReceived","packetsLost","packetsLoss","bitrate","roundTripTime","bytesSent","packetsSent","fractionLost","mediaSourceKey","mediaSourceId","outboundTrackIdentifier","codecKey","codecId","mimeType","codec","includes","mangleChromeStats","logPrefix","GPU","stats_1","getCurrTimeStamp","date","getMonth","getDate","getFullYear","getHours","getMinutes","getSeconds","getMilliseconds","logLevels","sdkLogger","getLogLevel","object","allowed","allowedValue","currentValue","_original_log","oldStats","newStats","getTime","isArray","response","standardReport","standardStats","stat","tracks","enabled","proxyURL","localUrl","staging1Url","staging2Url","productionUrl","production1Url","splitted","changed","old","new","channels","parameters","number_format","num","round","toFixed","loadBenchmarks","gpuInfo","memory","fileName","shift","getGPUTier","cores_count","hardwareConcurrency","performance","jsHeapSizeLimit","totalJSHeapSize","usedJSHeapSize","patchConsoleConfig","originalMethodPrefix","methodsToPatch","patchConsoleMethod","originalMethod","currentMethodIndex","configMethodIndex","stringifyArgs","currentIndex","previousIndex","mappedTradk","replacerFunc","visited","WeakSet","_key","add","hasOldStats","statsHaveRTTMeasurements","roundTripTimeMeasurements","NaN","referenceStats","referenceReport_1","bandwidth","other","none","WatchRTCHttp","_instance","mode","cache","credentials","headers","LZString","WatchRTCSocket","sendInterval","dataCollection","sendPromises","prevMessageTs","timeSinceLastMessage","abs","lines","compressedMessage","compressToEncodedURIComponent","send","timeThreshold_1","relevantTraces","filteredCount","onopen","onclose","onmessage","setPrototypeOf","throw","return","MSStream","isIpad","isMobile","isSafari12","charCodeAt","h","create","mobileTiers","desktopTiers","glContext","w","failIfMajorPerformanceCaveat","benchmarksURL","A","S","C","E","L","M","B","O","T","U","I","D","R","G","N","K","W","tier","screenSize","screen","parseInt","renderer","sort","MAX_VALUE","devicePixelRatio","width","height","fps","gpu","alpha","antialias","depth","powerPreference","stencil","getContext","getExtension","getParameter","UNMASKED_RENDERER_WEBGL","createShader","createProgram","shaderSource","compileShader","attachShader","linkProgram","detachShader","deleteShader","useProgram","createBuffer","bindBuffer","bufferData","Float32Array","getAttribLocation","vertexAttribPointer","enableVertexAttribArray","clearColor","clear","viewport","drawArrays","Uint8Array","readPixels","deleteProgram","deleteBuffer","webpackContext","req","webpackContextResolve","__webpack_require__","charAt","fromCharCode","compressToBase64","_compress","decompressFromBase64","_decompress","compressToUTF16","decompressFromUTF16","compressToUint8Array","compress","decompressFromUint8Array","decompress","decompressFromEncodedURIComponent","pow","val","position","index","__webpack_module_cache__","moduleId","__webpack_modules__","globalThis","byteLength","b64","lens","getLens","validLen","placeHoldersLen","toByteArray","tmp","Arr","_byteLength","curByte","revLookup","fromByteArray","uint8","extraBytes","maxChunkLength","len2","encodeChunk","lookup","end","output","scriptReadyRegex","fullPageUrl","href","pageUrl","scripts","supportsScriptReadyState","isNotOpera","opera","hasNativeCurrentScriptAccessor","stackTraceLimit","Infinity","hasStackBeforeThrowing","hasStackAfterThrowing","getScriptUrlFromStack","skipStackDepth","ignoreMessage","_nearestExecutingScript","eligibleScripts","getScriptFromUrl","hasAttribute","getSoleInlineScript","currentScript","thrownErr","near","far","ReflectOwnKeys","Reflect","ReflectApply","target","receiver","ownKeys","getOwnPropertySymbols","getOwnPropertyNames","NumberIsNaN","isNaN","EventEmitter","once","emitter","errorListener","removeListener","resolver","eventTargetAgnosticAddListener","handler","flags","on","addErrorHandlerIfEventEmitter","_events","_eventsCount","_maxListeners","defaultMaxListeners","checkListener","_getMaxListeners","that","_addListener","events","existing","warning","newListener","emit","unshift","warned","warn","onceWrapper","fired","wrapFn","_onceWrap","state","wrapped","_listeners","unwrap","evlistener","unwrapListeners","arrayClone","listenerCount","copy","wrapListener","removeEventListener","enumerable","RangeError","getPrototypeOf","setMaxListeners","getMaxListeners","doError","er","context","listeners","addListener","prependListener","prependOnceListener","list","originalListener","spliceOne","off","removeAllListeners","rawListeners","eventNames","flat","nodeType","nonce","noModule","getAttribute","setAttribute","removeChild","fn","jquery","toArray","pushStack","merge","prevObject","each","first","eq","last","even","grep","odd","isPlainObject","expando","noop","isEmptyObject","globalEval","makeArray","inArray","guid","support","ue","H","F","V","X","Q","ID","CLASS","TAG","ATTR","PSEUDO","CHILD","bool","needsContext","Y","J","Z","ee","te","ne","re","ie","oe","ae","xe","nodeName","dir","childNodes","se","ownerDocument","getElementById","getElementsByClassName","qsa","ye","scope","be","querySelectorAll","removeAttribute","cacheLength","le","ce","fe","attrHandle","de","sourceIndex","nextSibling","pe","he","ge","isDisabled","ve","isXML","namespaceURI","documentElement","setDocument","defaultView","top","attachEvent","attributes","className","createComment","getById","getElementsByName","getAttributeNode","innerHTML","matchesSelector","webkitMatchesSelector","mozMatchesSelector","oMatchesSelector","msMatchesSelector","disconnectedMatch","compareDocumentPosition","contains","sortDetached","attr","specified","escape","uniqueSort","detectDuplicates","sortStable","getText","textContent","firstChild","nodeValue","selectors","createPseudo","relative","preFilter","lastChild","uniqueID","pseudos","setFilters","not","lang","hash","focus","activeElement","hasFocus","tabIndex","checked","selected","selectedIndex","empty","parent","header","input","button","lt","gt","nth","radio","checkbox","file","password","image","submit","reset","me","we","Ce","Te","Ee","filters","tokenize","compile","selector","select","defaultValue","unique","isXMLDoc","escapeSelector","is","parseHTML","ready","children","contents","closest","prevAll","addBack","parents","parentsUntil","nextAll","nextUntil","prevUntil","siblings","contentDocument","reverse","promise","fail","Callbacks","stopOnFalse","remove","disable","lock","locked","fireWith","fire","Deferred","always","pipe","notify","notifyWith","resolveWith","exceptionHook","stackTrace","rejectWith","getStackHook","when","readyException","readyWait","doScroll","uid","configurable","access","hasData","removeData","_data","_removeData","dequeue","_queueHooks","clearQueue","composed","getRootNode","style","display","css","show","hide","toggle","createDocumentFragment","checkClone","cloneNode","noCloneChecked","option","thead","col","tr","td","_default","tbody","tfoot","colgroup","caption","th","optgroup","htmlPrefilter","createTextNode","namespace","isTrigger","special","delegateType","stopPropagation","stopImmediatePropagation","preventDefault","trigger","Event","global","handle","triggered","dispatch","bindType","origType","delegateCount","setup","teardown","removeEvent","fix","delegateTarget","preDispatch","handlers","isPropagationStopped","currentTarget","elem","isImmediatePropagationStopped","rnamespace","handleObj","postDispatch","addProp","originalEvent","writable","load","noBubble","click","beforeunload","returnValue","isDefaultPrevented","defaultPrevented","relatedTarget","timeStamp","isSimulated","altKey","bubbles","cancelable","changedTouches","ctrlKey","detail","eventPhase","metaKey","pageX","pageY","shiftKey","view","charCode","keyCode","buttons","clientX","clientY","offsetX","offsetY","pointerId","pointerType","screenX","screenY","targetTouches","toElement","touches","which","blur","mouseenter","mouseleave","pointerenter","pointerleave","one","Ae","Ne","Se","ke","De","Le","je","qe","html","clone","_evalUrl","Oe","cleanData","detach","append","before","after","replaceWith","replaceChild","appendTo","prependTo","insertAfter","replaceAll","Pe","He","Ie","opener","getComputedStyle","Re","Be","Me","We","Fe","getPropertyValue","pixelBoxStyles","minWidth","maxWidth","$e","cssText","marginLeft","right","offsetWidth","parseFloat","backgroundClip","clearCloneStyle","boxSizingReliable","pixelPosition","reliableMarginLeft","scrollboxSize","reliableTrDimensions","borderTopWidth","borderBottomWidth","offsetHeight","ze","Ue","Ve","cssProps","Xe","Qe","Ye","Ge","visibility","Ke","letterSpacing","fontWeight","Je","Ze","ceil","et","getClientRects","cssHooks","opacity","cssNumber","animationIterationCount","columnCount","fillOpacity","flexGrow","flexShrink","gridArea","gridColumn","gridColumnEnd","gridColumnStart","gridRow","gridRowEnd","gridRowStart","lineHeight","order","orphans","widows","zIndex","zoom","setProperty","isFinite","getBoundingClientRect","left","margin","padding","border","expand","delay","fx","speeds","checkOn","optSelected","radioValue","tt","nt","removeAttr","attrHooks","rt","it","ot","at","st","removeProp","propFix","propHooks","addClass","removeClass","toggleClass","hasClass","ut","valHooks","focusin","ct","parentWindow","simulate","triggerHandler","parseXML","DOMParser","parseFromString","ft","dt","pt","ht","vt","param","encodeURIComponent","serialize","serializeArray","wrapAll","firstElementChild","wrapInner","wrap","hidden","visible","createHTMLDocument","implementation","offset","setOffset","using","pageYOffset","pageXOffset","offsetParent","scrollLeft","scrollTop","scrollTo","Height","Width","unbind","delegate","undelegate","hover","yt","proxy","holdReady","parseJSON","isFunction","isWindow","camelCase","isNumeric","mt","bt","noConflict","WINDOW","JS_MD5_NO_WINDOW","WEB_WORKER","NODE_JS","JS_MD5_NO_NODE_JS","process","versions","COMMON_JS","JS_MD5_NO_COMMON_JS","AMD","ARRAY_BUFFER","JS_MD5_NO_ARRAY_BUFFER","ArrayBuffer","HEX_CHARS","EXTRA","SHIFT","OUTPUT_TYPES","BASE64_ENCODE_CHAR","blocks","buffer8","Uint32Array","JS_MD5_NO_ARRAY_BUFFER_IS_VIEW","isView","createOutputMethod","outputType","Md5","update","createMethod","nodeWrap","crypto","eval","Buffer","nodeMethod","createHash","digest","sharedMemory","h0","h1","h2","h3","bytes","hBytes","finalized","hashed","notString","lastByteIndex","finalize","bc","da","hex","array","arrayBuffer","base64","v1","v2","v3","base64Str","md5","HASH_UNDEFINED","MAX_SAFE_INTEGER","argsTag","boolTag","dateTag","funcTag","genTag","mapTag","numberTag","objectTag","promiseTag","regexpTag","setTag","stringTag","symbolTag","weakMapTag","arrayBufferTag","dataViewTag","float32Tag","float64Tag","int8Tag","int16Tag","int32Tag","uint8Tag","uint8ClampedTag","uint16Tag","uint32Tag","reFlags","reIsHostCtor","reIsUint","cloneableTags","freeGlobal","freeSelf","freeExports","freeModule","moduleExports","addMapEntry","pair","addSetEntry","arrayReduce","iteratee","accumulator","initAccum","isHostObject","mapToArray","size","overArg","func","transform","setToArray","arrayProto","funcProto","objectProto","coreJsData","maskSrcKey","IE_PROTO","funcToString","objectToString","reIsNative","getPrototype","objectCreate","propertyIsEnumerable","nativeGetSymbols","nativeIsBuffer","isBuffer","nativeKeys","DataView","getNative","Map","Set","WeakMap","nativeCreate","dataViewCtorString","toSource","mapCtorString","promiseCtorString","setCtorString","weakMapCtorString","symbolProto","symbolValueOf","valueOf","Hash","entry","ListCache","MapCache","Stack","__data__","assignValue","objValue","assocIndexOf","baseClone","isDeep","isFull","customizer","isObject","isArr","initCloneArray","copyArray","tag","getTag","isFunc","cloneBuffer","isPrototype","proto","initCloneObject","copyObject","getSymbols","copySymbols","baseAssign","cloneFunc","symbol","Ctor","cloneArrayBuffer","dataView","byteOffset","cloneDataView","typedArray","cloneTypedArray","cloneMap","regexp","lastIndex","cloneRegExp","cloneSet","initCloneByTag","stacked","keysFunc","symbolsFunc","arrayPush","baseGetAllKeys","getAllKeys","arrayEach","subValue","newValue","getMapData","getValue","baseIsNative","pairs","LARGE_ARRAY_SIZE","isIndex","ctorString","isArrayLike","isLength","inherited","isObjectLike","isArrayLikeObject","isArguments","baseTimes","skipIndexes","arrayLikeKeys","baseKeys","NAN","reTrim","reIsBadHex","reIsBinary","reIsOctal","freeParseInt","nativeMax","nativeMin","toNumber","isSymbol","isBinary","wait","lastArgs","lastThis","maxWait","timerId","lastCallTime","lastInvokeTime","leading","maxing","trailing","invokeFunc","time","shouldInvoke","timeSinceLastCall","timerExpired","trailingEdge","remainingWait","debounced","isInvoking","leadingEdge","cancel","COMPARE_PARTIAL_FLAG","COMPARE_UNORDERED_FLAG","arrayTag","asyncTag","errorTag","nullTag","proxyTag","undefinedTag","typedArrayTags","freeProcess","nodeUtil","binding","nodeIsTypedArray","isTypedArray","arraySome","predicate","nativeObjectToString","symToStringTag","toStringTag","SetCache","baseGetTag","isOwn","unmasked","getRawTag","baseIsArguments","baseIsEqual","bitmask","equalFunc","objIsArr","othIsArr","objTag","othTag","objIsObj","othIsObj","isSameTag","equalArrays","convert","isPartial","equalByTag","objIsWrapped","othIsWrapped","objUnwrapped","othUnwrapped","objProps","objLength","skipCtor","othValue","compared","objCtor","othCtor","equalObjects","baseIsEqualDeep","arrLength","othLength","seen","arrValue","othIndex","isMasked","resIndex","arrayFilter","baseUnary","isArg","isBuff","isType","SDPUtils","localCName","generateIdentifier","splitLines","blob","splitSections","part","getDescription","sections","getMediaSections","matchPrefix","parseCandidate","foundation","protocol","priority","relatedAddress","relatedPort","tcpType","ufrag","usernameFragment","writeCandidate","parseIceOptions","parseRtpMap","parsed","payloadType","clockRate","numChannels","writeRtpMap","preferredPayloadType","parseExtmap","uri","writeExtmap","headerExtension","preferredId","parseFmtp","kv","writeFmtp","parseRtcpFb","parameter","writeRtcpFb","rtcpFeedback","fb","parseSsrcMedia","sp","ssrc","colon","parseSsrcGroup","semantics","ssrcs","getMid","mediaSection","mid","parseFingerprint","algorithm","getDtlsParameters","sessionpart","role","fingerprints","writeDtlsParameters","setupType","fp","parseCryptoLine","cryptoSuite","keyParams","sessionParams","writeCryptoLine","writeCryptoKeyParams","parseCryptoKeyParams","keyMethod","keySalt","lifeTime","mkiValue","mkiLength","getCryptoParameters","getIceParameters","pwd","writeIceParameters","iceLite","parseRtpParameters","codecs","headerExtensions","fecMechanisms","rtcp","mline","rtpmapline","fmtps","writeRtpDescription","caps","maxptime","extension","parseRtpEncodingParameters","encodingParameters","hasRed","hasUlpfec","primarySsrc","secondarySsrc","flows","apt","encParam","codecPayloadType","rtx","fec","mechanism","maxBitrate","parseRtcpParameters","rtcpParameters","remoteSsrc","cname","rsize","reducedSize","compound","mux","writeRtcpParameters","parseMsid","spec","planB","msidParts","parseSctpDescription","parseMLine","maxSizeLine","sctpPort","fmt","sctpMapLines","writeSctpDescription","sctp","generateSessionId","writeSessionBoilerplate","sessId","sessVer","sessUser","sessionId","getDirection","getKind","isRejected","parseOLine","username","sessionVersion","netType","addressType","isValidSDP","global$1","WebSocketImplementation","getWebSocketImplementation","DOMParserImplementation","getDOMParserImplementation","getDummyXMLDOMDocument","createDocument","documentMode","doc","docStrings","ActiveXObject","_getIEXmlDom","safe_add$1","lsw","str2binl","bin","md5_cmn","cnt","md5_ff","md5_gg","md5_hh","md5_ii","core_md5","olda","oldb","oldc","oldd","MD5","hexdigest","binarray","hex_tab","binl2hex","binl2str","SASLMechanism","isClientFirst","mechname","onStart","_connection","onChallenge","challenge","clientChallenge","onFailure","onSuccess","utils","out","cookies","cookieName","expires","domain","path","cookieObj","isObj","cookieValue","unescape","cookie","core_sha1","olde","rol","safe_add","sha1_ft","sha1_kt","core_hmac_sha1","bkey","str2binb","ipad","opad","binb2b64","triplet","binb2str","SHA1","b64_hmac_sha1","b64_sha1","str_hmac_sha1","str_sha1","keystr$1","atobLookup","chr","keystr","btoaLookup","abab","atob","accumulatedBits","btoa","groupsOfSix","$build","attrs","Strophe","Builder","$msg","$iq","$pres","NS","HTTPBIND","BOSH","CLIENT","AUTH","ROSTER","PROFILE","DISCO_INFO","DISCO_ITEMS","MUC","SASL","STREAM","FRAMING","BIND","SESSION","STANZAS","XHTML_IM","XHTML","tags","validTag","validAttribute","validCSS","Status","CONNECTING","CONNFAIL","AUTHENTICATING","AUTHFAIL","CONNECTED","DISCONNECTED","DISCONNECTING","ATTACHED","REDIRECT","CONNTIMEOUT","BINDREQUIRED","ATTACHFAIL","ErrorCondition","BAD_FORMAT","CONFLICT","MISSING_JID_NODE","NO_AUTH_MECH","UNKNOWN_REASON","LogLevel","FATAL","ElementType","NORMAL","TEXT","CDATA","FRAGMENT","TIMEOUT","SECONDARY_TIMEOUT","addNamespace","forEachChild","elemName","childNode","isTagEqual","_xmlGenerator","xmlGenerator","xmlElement","xmlTextNode","xmlescape","xmlunescape","xmlHtmlNode","loadXML","copyElement","createHtml","cssAttrs","cssName","cssValue","escapeNode","unescapeNode","getNodeFromJid","jid","getDomainFromJid","bare","getBareJidFromJid","getResourceFromJid","_handleError","fatal","sourceURL","lineNumber","_console","info","tree","getNamedItem","child","_requestId","_connectionPlugins","addConnectionPlugin","ptype","xmlns","nodeTree","up","moreattrs","cnode","impNode","xmlGen","importNode","newElem","fragment","xhtml","ns","matchBare","matchBareFromJid","user","Handler","getNamespace","elNamespace","ignoreNamespaceFragment","namespaceMatch","nsMatch","isMatch","elem_type","TimedHandler","period","lastCalled","Connection","service","setProtocol","features","_sasl_data","do_bind","do_session","mechanisms","timedHandlers","removeTimeds","removeHandlers","addTimeds","addHandlers","protocolErrorHandlers","_idleTimeout","_disconnectTimeout","authenticated","connected","disconnecting","do_authentication","restored","_uniqueId","_sasl_success_handler","_sasl_failure_handler","_sasl_challenge_handler","maxRetries","_onIdle","registerSASLMechanisms","iqFallbackHandler","iq","worker","_proto","WorkerWebsocket","Websocket","Bosh","_reset","_requests","pause","resume","getUniqueId","suffix","uuid","addProtocolErrorHandler","status_code","callback","pass","hold","route","authcid","disconnection_timeout","authzid","connect_callback","_changeConnectStatus","_connect","attach","sid","rid","wind","_attach","restore","_sessionCachingSupported","_restore","sessionStorage","setItem","removeItem","xmlInput","xmlOutput","rawInput","rawOutput","nextValidRid","_queueData","_send","sendPresence","errback","timeout","timeoutHandler","addHandler","stanza","deleteTimedHandler","addTimedHandler","deleteHandler","sendIQ","iqtype","element","_sendRestart","thand","handRef","hand","SASLAnonymous","SASLExternal","SASLOAuthBearer","SASLXOAuth2","SASLPlain","SASLSHA1","registerSASLMechanism","Mechanism","pres","_addSysTimedHandler","_onDisconnectTimeout","_disconnect","_abortAllRequests","_doDisconnect","status","condition","plugin","statusChanged","_dataRecv","raw","_reqToData","strip","_emptyQueue","cond","conflict","UNKOWN_REASON","_connect_cb","_callback","bodyWrap","hasFeatures","getElementsByTagNameNS","_no_auth_received","matched","authenticate","sortMechanismsByPriority","higher","swap","_attemptSASLAuth","_attemptLegacyAuth","mechanism_found","_addSysHandler","_sasl_success_cb","_sasl_failure_cb","_sasl_challenge_cb","_sasl_mechanism","request_auth_exchange","_onLegacyAuthIQResult","_auth2_cb","serverSignature","attribMatch","streamfeature_handlers","wrapper","_onStreamFeaturesAfterSASL","explicitResourceBinding","_onResourceBindResultIQ","resource","jidNode","_establishSession","_onSessionResultIQ","newList","super","auth_str","salt","iter","Hi","U_old","responseText","authMessage","cnonce","clientKey","serverKey","clientSignature","test_cnonce","core","Request","sends","xmlData","origFunc","abort","dead","age","timeDead","xhr","_newXHR","getResponse","responseXML","querySelector","XMLHttpRequest","overrideMimeType","onreadystatechange","_conn","errors","inactivity","lastResponseHeaders","_buildBody","keepalive","_cacheSession","_onRequestStateChange","_throttledRequestHandler","getItem","typ","_sendTerminate","_callProtocolErrorHandlers","reqStatus","_getRequestStatus","err_callback","HTTP","_hitError","time_elapsed","static","def","getAllResponseHeaders","reqIs0","reqIs1","valid_request","too_many_retries","_removeRequest","_restartRequest","_processRequest","primary_timeout","secondary_timeout","server_error","content_type","contentType","open","sync","setRequestHeader","withCredentials","e2","sendFunc","customHeaders","backoff","new_service","host","pathname","_buildStream","_checkStreamError","connectstatus","errorString","_closeSocket","_onOpen","_onError","_onClose","_onInitialMessage","_handleStreamStart","ver","streamStart","parsedMessage","see_uri","_replaceMessageHandler","string","_streamWrap","_onMessage","CLOSED","closeString","rawStanza","startString","lmap","SharedWorker","postMessage","_messageHandler","ev","_onWorkerMessage","_attachCallback","method_name","_identities","_features","_items","conn","_onDiscoInfo","_onDiscoItems","addIdentity","category","addFeature","var_name","removeFeature","addItem","call_back","success","items","_buildIQResult","query_attrs","iqresult","logging","autoSendCountOnEveryIncomingStanza","requestResponseInterval","_NS","_isStreamManagementEnabled","_serverProcesssedStanzasCounter","_clientProcessedStanzasCounter","_clientSentStanzasCounter","_originalXMLOutput","_requestHandler","_incomingHandler","_requestResponseIntervalCount","_isSupported","_unacknowledgedStanzas","_acknowledgedStanzaListeners","addAcknowledgedStanzaListener","enable","_connectionStatus","getResumeToken","_resumeToken","isSupported","_resuming","_originalConnect","_connectArgs","requestAcknowledgement","getOutgoingCounter","getIncomingCounter","_interceptConnectArgs","_originalOnStreamFeaturesAfterSASL","_originalDoDisconnect","_interceptDoDisconnect","_originalDisconnect","_interceptDisconnect","_resumeState","_storedJid","previd","_handleServerRequestHandler","_ackHandler","_handleServerAck","_incomingStanzaHandler","_enabledHandler","_handleEnabled","_resumeFailedHandler","_handleResumeFailed","_resumedHandler","_handleResumed","_increaseSentStanzasCounter","handledCount","_handleAcknowledgedStanzas","_increaseReceivedStanzasCounter","_answerProcessedStanzas","reportedHandledCount","lastKnownHandledCount","_throwError","byteToHex","buf","bth","_v","_v2","_v3","_v4","_interopRequireDefault","__esModule","getOutputLength","inputLength8","safeAdd","md5cmn","md5ff","md5gg","md5hh","md5ii","length32","hexTab","md5ToHexEncodedArray","wordsToMd5","length8","bytesToWords","getRandomValues","rnds8","msCrypto","ROTL","_rng","_bytesToUuid","_nodeId","_clockseq","_lastMSecs","_lastNSecs","clockseq","seedBytes","rng","msecs","nsecs","tl","tmh","_md","hashfunc","generateUUID","stringToBytes","uuidToBytes","idx","DNS","rnds","_sha","RTCEvents","CREATE_ANSWER_FAILED","CREATE_OFFER_FAILED","DATA_CHANNEL_OPEN","DATA_CHANNEL_CLOSED","ENDPOINT_CONN_STATUS_CHANGED","DOMINANT_SPEAKER_CHANGED","FORWARDED_SOURCES_CHANGED","PERMISSIONS_CHANGED","SENDER_VIDEO_CONSTRAINTS_CHANGED","LASTN_VALUE_CHANGED","LOCAL_TRACK_SSRC_UPDATED","LOCAL_TRACK_MAX_ENABLED_RESOLUTION_CHANGED","TRACK_ATTACHED","REMOTE_TRACK_ADDED","REMOTE_TRACK_MUTE","REMOTE_TRACK_REMOVED","REMOTE_TRACK_UNMUTE","SET_LOCAL_DESCRIPTION_FAILED","SET_REMOTE_DESCRIPTION_FAILED","AUDIO_OUTPUT_DEVICE_CHANGED","DEVICE_LIST_CHANGED","DEVICE_LIST_WILL_CHANGE","DEVICE_LIST_AVAILABLE","ENDPOINT_MESSAGE_RECEIVED","ENDPOINT_STATS_RECEIVED","LOCAL_UFRAG_CHANGED","REMOTE_UFRAG_CHANGED","VIDEO_SSRCS_REMAPPED","AUDIO_SSRCS_REMAPPED","VideoType","IDENTITY_UPDATED","LOCAL_JID","XMPPEvents","JitsiConferenceErrors","AUTH_ERROR_TYPES","AUTHENTICATION_REQUIRED","CHAT_ERROR","SETTINGS_ERROR","CONFERENCE_DESTROYED","CONFERENCE_MAX_USERS","CONNECTION_ERROR","CONFERENCE_RESTARTED","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","_MEDIA_SESSION_STARTED","_MEDIA_SESSION_ACTIVE_CHANGED","AUDIO_INPUT_STATE_CHANGE","AUDIO_UNMUTE_PERMISSIONS_CHANGED","AUTH_STATUS_CHANGED","AV_MODERATION_APPROVED","AV_MODERATION_CHANGED","AV_MODERATION_PARTICIPANT_APPROVED","AV_MODERATION_PARTICIPANT_REJECTED","AV_MODERATION_REJECTED","BEFORE_STATISTICS_DISPOSED","BOT_TYPE_CHANGED","BREAKOUT_ROOMS_MOVE_TO_ROOM","BREAKOUT_ROOMS_UPDATED","CONFERENCE_CREATED_TIMESTAMP","CONFERENCE_ERROR","CONFERENCE_FAILED","CONFERENCE_JOIN_IN_PROGRESS","CONFERENCE_JOINED","CONFERENCE_LEFT","CONFERENCE_UNIQUE_ID_SET","CONFERENCE_VISITOR_CODECS_CHANGED","CONNECTION_ESTABLISHED","CONNECTION_INTERRUPTED","CONNECTION_RESTORED","DATA_CHANNEL_OPENED","DISPLAY_NAME_CHANGED","DTMF_SUPPORT_CHANGED","E2EE_VERIFICATION_AVAILABLE","E2EE_VERIFICATION_COMPLETED","E2EE_VERIFICATION_READY","ENCODE_TIME_STATS_RECEIVED","JVB121_STATUS","KICKED","LAST_N_ENDPOINTS_CHANGED","LOBBY_USER_JOINED","LOBBY_USER_LEFT","LOBBY_USER_UPDATED","LOCK_STATE_CHANGED","MEMBERS_ONLY_CHANGED","MESSAGE_RECEIVED","METADATA_UPDATED","NO_AUDIO_INPUT","NOISY_MIC","NON_PARTICIPANT_MESSAGE_RECEIVED","P2P_STATUS","PARTICIPANT_KICKED","PARTICIPANT_SOURCE_UPDATED","PRIVATE_MESSAGE_RECEIVED","PARTCIPANT_FEATURES_CHANGED","PARTICIPANT_PROPERTY_CHANGED","PHONE_NUMBER_CHANGED","PROPERTIES_CHANGED","RECORDER_STATE_CHANGED","SERVER_REGION_CHANGED","SILENT_STATUS_CHANGED","START_MUTED_POLICY_CHANGED","STARTED_MUTED","SUBJECT_CHANGED","SUSPEND_DETECTED","TALK_WHILE_MUTED","TRACK_ADDED","TRACK_AUDIO_LEVEL_CHANGED","TRACK_MUTE_CHANGED","TRACK_REMOVED","TRACK_UNMUTE_REJECTED","TRANSCRIPTION_STATUS_CHANGED","USER_JOINED","USER_LEFT","USER_ROLE_CHANGED","USER_STATUS_CHANGED","VIDEO_SIP_GW_AVAILABILITY_CHANGED","VIDEO_SIP_GW_SESSION_STATE_CHANGED","VIDEO_UNMUTE_PERMISSIONS_CHANGED","VISITORS_SUPPORTED_CHANGED","VISITORS_MESSAGE","VISITORS_REJECTION","JitsiTrackEvents","LOCAL_TRACK_STOPPED","TRACK_AUDIO_OUTPUT_CHANGED","TRACK_VIDEOTYPE_CHANGED","NO_DATA_FROM_SOURCE","TRACK_OWNER_SET","TRACK_STREAMING_STATUS_CHANGED","AnalyticsEvents","TYPE_OPERATIONAL","TYPE_PAGE","TYPE_TRACK","TYPE_UI","ACTION_JINGLE_RESTART","ACTION_JINGLE_SA_TIMEOUT","ACTION_JINGLE_SI_RECEIVED","ACTION_JINGLE_SI_TIMEOUT","ACTION_JINGLE_TERMINATE","ACTION_JINGLE_TR_RECEIVED","ACTION_JINGLE_TR_SUCCESS","ACTION_P2P_DECLINED","ACTION_P2P_ESTABLISHED","ACTION_P2P_FAILED","ACTION_P2P_SWITCH_TO_JVB","AVAILABLE_DEVICE","CONNECTION_DISCONNECTED","FEEDBACK","ICE_DURATION","ICE_ESTABLISHMENT_DURATION_DIFF","ICE_STATE_CHANGED","NO_BYTES_SENT","TRACK_UNMUTED","createConnectionFailedEvent","errorType","errorMessage","details","action","createConferenceEvent","createConnectionStageReachedEvent","stage","actionSubject","createGetUserMediaEvent","createJingleEvent","createP2PEvent","createRemotelyMutedEvent","mediaType","createRtpStatsEvent","Events","AUDIO_LEVEL","BEFORE_DISPOSED","BYTE_SENT_STATS","CONNECTION_STATS","ENCODE_TIME_STATS","LONG_TASKS_STATS","SAFARI","ELECTRON","REACT_NATIVE","PARSER_TO_JITSI_NAME","BLINK","WEBKIT","GECKO","ENGINES","_getJitsiBrowserInfo","browserInfo","engineVersion","BrowserDetection","_parser","reactNativeInfo","product","_detectReactNative","_detect","_name","_version","_engineVersion","isChrome","isSafari","isElectron","isReactNative","isChromiumBased","isWebKitBased","getName","getVersion","getEngineVersion","getOSVersion","isVersionGreaterThan","isVersionLessThan","isVersionEqualTo","isEngineVersionGreaterThan","isEngineVersionLessThan","isEngineVersionEqualTo","newStatsArg","REGEX","validate","PROTOCOL_ITERATION","MAX_RECONNECT_TIME","messageTypes","SequenceNumber","CONFERENCE_LEAVE_CODE","DUMP_ERROR_CODE","CUSTOM_ERROR_CODES","BUFFER_LIMIT","obfuscateIP","obfuscateCandidate","cand","_ref","parentStatsSessionId","keepAliveInterval","reconnectTimeout","endpoint","meetingFqn","onCloseCallback","useLegacy","obfuscate","pingInterval","statsSessionId","uuidv4","reconnectSpentTime","canSendMessage","sequenceNumber","protocolVersion","setTransportParams","sendMessage","copyMsg","isConnected","isClosed","identity","_len","statsEntry","_len2","_key2","myData","jsonRepr","splitBy","obfuscator","keepAlive","isBreakoutRoom","isReconnect","reconnectTimeoutTimeCandidate","reconnectTimeoutTime","firstSN","lastSN","lastReceivedSNIndex","findIndex","RTCStatsEvents","RTC_STATS_WC_DISCONNECTED","RTC_STATS_PC_EVENT","NodeEventEmitter","DummyLocalStorage","_storage","keyName","keyValue","ignore","storageCopy","jitsiLocalStorage","localStorage","_localStorageDisabled","isLocalStorageDisabled","setLocalStorageDisabled","dontEmitChangedEvent","localStorageContent","_callStatsUserName","_machineId","externalStorage","callStatsUserName","UsernameGenerator","_generateStatsId","machineId","amDid","jitsiMeetId","_p8","generateJitsiMeetId","_defineProperty","initConfig","analytics","rtcstatsUseLegacy","rtcstatsPollInterval","pollInterval","rtcstatsSendSdp","sendSdp","rtcstatsEnabled","_initialized","_ref2","sendStatsEntry","connectionFilter","eventCallback","browserDetection","OrigPeerConnection","origConfig","optional","isP2P","some","rtcStatsSFUP2P","__dtlsTransport","endsWith","getSenders","newstate","gum","origGetDisplayMedia","gdm","rtcstatsInit","conference","_Settings$callStatsUs","confConfig","confName","_statsCurrentId","rtcstatsEndpoint","localId","Settings","_conference$getBreako","traceOptions","getBreakoutRooms","endpointId","myUserId","meetingUniqueId","getMeetingUniqueId","_trace","traceInit","identityData","sendIdentity","_this$_trace","_this$_trace2","statsType","_this$_trace3","doesVideoMuteByStreamRemove","isAndroidBrowser","isIosBrowser","isMobileDevice","isTwa","matchMedia","_getSafariVersion","MIN_REQUIRED_CHROME_VERSION","MIN_REQUIRED_FIREFOX_VERSION","isSupportedAndroidBrowser","isSupportedIOSBrowser","_getIOSVersion","isUserInteractionRequiredForUnmute","supportsVideoMuteOnConnInterrupted","supportsBandwidthStatistics","supportsCodecPreferences","RTCRtpReceiver","getCapabilities","supportsCodecSelectionAPI","supportsDDExtHeaders","supportsDeviceChangeEvent","ondevicechange","supportsPerformanceObserver","PerformanceObserver","supportedEntryTypes","supportsReceiverStats","supportsRTTStatistics","supportsScalabilityModeAPI","supportsTrackBasedStats","supportsVP9","usesSdpMungingForSimulcast","usesRidsForSimulcast","supportsGetDisplayMedia","supportsEncodedTransform","RTCRtpScriptTransform","supportsInsertableStreams","createEncodedStreams","ReadableStream","supportsAudioRed","supportsVADDetection","supportsRTX","_analytics$watchRTCEn","watchRTCEnabled","isWatchRTCEnabled","disableThirdPartyRequests","isAnalyticsEnabled","_options$watchRTCConf","watchRTCConfigParams","watchRTC","roomName","userName","disposed","analyticsHandlers","permanentProperties","conferenceName","addPermanentProperties","dispose","setAnalyticsHandlers","_setUserProperties","_sendEvent","setUserProperties","properties","setConferenceName","sendEvent","eventName","_verifyRequiredFields","objectType","containerType","containerId","objectId","_maybeCacheEvent","AudioContext","webkitAudioContext","LocalStatsCollector","intervalId","intervalMilis","audioLevel","analyser","safeCounterIncrement","number","nextValue","calculateAverage","valueArray","filterPositiveValues","isLocalStatsSupported","createAnalyser","smoothingTimeConstant","fftSize","createMediaStreamSource","frequencyBinCount","getByteTimeDomainData","samples","maxVolume","timeDomainDataToAudioLevel","newLevel","lastLevel","diff","animateLevel","_this$analyser","_this$source","connectAudioContext","_window","disconnectAudioContext","suspend","RunningAverage","average","addNext","getAverage","safeSubtract","PerformanceObserverStats","statsInterval","eventEmitter","longTasks","maxDuration","performanceStatsInterval","getLongTasksStats","avgRatePerMinute","maxDurationMs","startObserver","longTaskEventHandler","getEntries","task","duration","observer","observe","buffered","startTime","longTasksIntervalId","_lastTimeStamp","StatisticsEvents","stopObserver","MediaType","_runInLiteMode","runInLiteMode","_ssrcRewriting","ssrcRewritingEnabled","isRunInLiteModeEnabled","isSsrcRewritingSupported","calculatePacketLoss","lostPackets","totalPackets","SsrcStats","loss","download","upload","resolution","ConferenceStats","packetLoss","StatsCollector","audioLevelsInterval","currentStatsReport","previousStatsReport","audioLevelsIntervalId","conferenceStats","audioLevelsIntervalMilis","speakerList","statsIntervalId","statsIntervalMilis","ssrc2stats","setLoss","setResolution","addBitrate","resetBitrate","setFramerate","setCodec","setEncodeStats","encodeStats","setSpeakerList","startAudioLevelStats","audioLevels","getAudioLevels","processStats","processStatsReport","_processAndEmitReport","bitrateDownload","bitrateUpload","resolutions","framerates","audioBitrateDownload","audioBitrateUpload","videoBitrateDownload","videoBitrateUpload","ssrcStats","_codecs$participantId","isDownloadStream","packetsTotal","ssrcBitrateDownload","ssrcBitrateUpload","getTrackBySSRC","audioCodec","videoCodec","isAudioTrack","participantId","getParticipantId","FeatureFlags","userCodecs","audio","video","isVideoTrack","userResolutions","isLocal","doesTrueSimulcast","localSsrcs","getLocalVideoSSRCs","localSsrc","_this$ssrc2stats$get","ssrcResolution","userFramerates","getNonNegativeValue","_calculateBitrate","fieldName","bytesNow","bytesBefore","bytesProcessed","timeMs","bitrateKbps","_calculateFps","frameRate","byteSentStats","encodedTimeStatsPerSsrc","availableIncomingBitrate","availableOutgoingBitrate","remoteUsedCandidate","localUsedCandidate","localip","conferenceStatsTransport","p2p","localCandidateType","remoteCandidateType","networkType","rtt","currentRoundTripTime","packetsNow","packetsBefore","packetsDiff","packetsLostNow","packetsLostBefore","packetsLostDiff","_now$active","isStreamActive","active","codecShortType","usesCodecSelectionAPI","totalEncodeTime","framesEncoded","encodeTimeStats","encodeTime","qualityLimitationReason","VIDEO","remoteSource","localVideoTracks","getLocalTracks","getSsrcByTrackId","_instances","Statistics","rtpStatsMap","xmpp","instances","RTCStats","WatchRTC","audioLevelsEnabled","disableAudioLevels","pcStatsInterval","longTasksStatsInterval","LocalStats","startRemoteStats","stopRemoteStats","rtpStats","RTPStats","localStats","startLocalStats","localStat","stopLocalStats","getOriginalStream","addAudioLevelListener","removeAudioLevelListener","addBeforeDisposedListener","removeBeforeDisposedListener","addConnectionStatsListener","removeConnectionStatsListener","addEncodeTimeStatsListener","removeEncodeTimeStatsListener","addByteSentStatsListener","removeByteSentStatsListener","addLongTasksStatsListener","attachLongTasksStats","performanceObserverStats","removeLongTasksStatsListener","tpcId","_stopRemoteStats","delete","tpc","sendFeedback","overall","sendAnalyticsAndLog","eventToLog","sendAnalytics","EventEmitterForwarder","dest","forward","srcEvent","removeListeners","JitsiConferenceEventManager","xmppListeners","setupChatRoomListeners","chatRoom","room","chatRoomForwarder","jingleSession","rtc","closeBridgeChannel","participant","getParticipantById","setFeatures","offerIq","_setBridgeChannel","actor","AUDIO","mutedByFocusActor","setAudioMute","isMutedByFocus","mutedVideoByFocusActor","setVideoMute","isVideoMutedByFocus","_onMucJoined","isJvbConnectionInterrupted","connectionTimes","owner","sourceName","videoType","getSourceName","setOwner","setSourceName","_setVideoType","_onConferenceRestarted","getStatus","setTerminator","setInitiator","setParticipantPropertyListener","onMemberKicked","onSuspendDetected","onMemberJoined","_onMemberBotTypeChanged","onMemberLeft","onDisplayNameChanged","onSilentStatusChanged","onLocalRoleChanged","onUserRoleChanged","AuthenticationEvents","authEnabled","authIdentity","txt","myJid","ts","nick","isGuest","messageId","reactionList","_status","payload","addPresenceListener","isModerator","startAudioMuted","startVideoMuted","updated","startMutedPolicy","setupRTCListeners","onRemoteTrackAdded","onRemoteTrackRemoved","dominant","lastDominantSpeaker","dominantSpeakerIsSilent","statistics","sendDominantSpeakerEvent","roomjid","jvbJingleSession","processSourceMap","removeXMPPListeners","setupXMPPListeners","_addConferenceXMPPListener","onIncomingCall","onCallAccepted","onTransportInfo","onCallEnded","audioMuted","videoMuted","ignoreStartMuted","getType","mute","actorJid","actorParticipant","getParticipants","getJid","setupStatisticsListeners","setAudioLevel","startSilent","getLocalSSRC","onByteSentStatsReceived","JitsiParticipant","statsID","isReplacing","isReplaced","isSilent","_jid","_id","_conference","_displayName","_supportsDTMF","_tracks","_role","_hidden","_statsID","_properties","_identity","_isReplacing","_isReplaced","_sources","_isMediaTypeMuted","isMuted","_setSources","_sourceByMediaType","sourceByMediaType","sourceInfo","getBotType","_botType","getConference","getConnectionJid","_connectionJid","getFeatures","getId","getIdentity","getProperty","getRole","getSources","getStatsID","getTracksByMediaType","hasFeature","feature","isAudioMuted","isHidden","isHiddenFromRecorder","_this$_identity","_this$_identity$user","isVideoMuted","setBotType","newBotType","setConnectionJid","newJid","newFeatures","setIsReplaced","newIsReplaced","setIsReplacing","newIsReplacing","setIsSilent","newIsSilent","oldValue","setRole","newRole","supportsDTMF","JitsiTrackErrors","CONSTRAINT_FAILED","ELECTRON_DESKTOP_PICKER_ERROR","ELECTRON_DESKTOP_PICKER_NOT_FOUND","GENERAL","NOT_FOUND","PERMISSION_DENIED","SCREENSHARING_GENERIC_ERROR","SCREENSHARING_USER_CANCELED","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","constraintName","constraint","failedConstraintName","mandatory","minHeight","getResolutionFromFailedConstraint","JitsiConnectionEvents","CONNECTION_FAILED","CONNECTION_REDIRECTED","WRONG_STATE","PROPERTIES_UPDATED","safeJsonParse","Bourne","JitsiConnectionErrors","CONNECTION_DROPPED_ERROR","NOT_LIVE_ERROR","OTHER_ERROR","SERVER_ERROR","clearRejectTimeout","_timeout","setRejectTimeout","ms","Listenable","addCancellableListener","kJitsiE2EE","E2EEcontext","sharedKey","baseUrl","workerUrl","workerBlob","Blob","createObjectURL","_worker","Worker","operation","cleanup","cleanupAll","handleReceiver","receiverStreams","readableStream","readable","writableStream","handleSender","senderStreams","setKey","keyIndex","KeyHandler","e2eeCtx","E2EEContext","_enabling","_onMediaSessionStarted","_onLocalTrackAdded","_setupReceiverE2EEForTrack","_trackMuteChanged","isEnabled","_setEnabled","setLocalParticipantProperty","_restartMediaSessions","setEncryptionKey","getMediaSessions","_setupSenderE2EEForTrack","localTracks","findReceiverForTrack","findSenderForTrack","ExternallyManagedKeyHandler","keyInfo","encryptionKey","E2EEErrors","emojiMapping","sasGenerators","decimal","sasBytes","emoji","REQ_TIMEOUT","OLM_MESSAGE_TYPE","OLM_MESSAGE_TYPES","OLM_KEY_VERIFICATION_MAC_INFO","OLM_KEY_VERIFICATION_MAC_KEY_IDS","kOlmData","OlmAdapterEvents","PARTICIPANT_E2EE_CHANNEL_READY","PARTICIPANT_SAS_AVAILABLE","PARTICIPANT_SAS_READY","PARTICIPANT_KEY_UPDATED","PARTICIPANT_VERIFICATION_COMPLETED","OlmAdapter","_conf","_init","_mediaKey","_mediaKeyIndex","_reqs","_sessionInitialization","_bootstrapOlm","_onEndpointMessageReceived","_onConferenceLeft","_onParticipantLeft","_onParticipantPropertyChanged","myId","promises","localParticipantId","FEATURE_E2EE","_sendSessionInit","allSettled","Olm","pId","olmData","_getParticipantOlmData","JITSI_MEET_MUC_TYPE","olm","ciphertext","_encryptKeyInfo","_sendMessage","updateCurrentMediaKey","clearParticipantSession","free","clearAllParticipantsSessions","markParticipantVerified","isVerified","sasVerification","E2EE_SAS_CHANNEL_VERIFICATION_FAILED","E2EE_SAS_INVALID_SAS_VERIFICATION","sas","sasMacSent","is_their_key_set","_sendSasMac","_olmAccount","Account","_idKeys","_safeJsonParse","identity_keys","get_library_version","_onIdKeysReady","startVerification","SAS","transactionId","startContent","isInitiator","startMessage","idKeys","keyType","_onParticipantE2EEChannelReady","base64js","encrypt","_sendError","Session","create_outbound","idKey","otKey","ack","pendingSessionUuid","create_inbound","remove_one_time_keys","decrypt","lastKey","isEqual","_olmData$sasVerificat","pubKey","get_pubkey","commitment","_computeCommitment","acceptMessage","sasCommitment","keyMessage","keySent","theirKey","E2EE_SAS_COMMITMENT_MISMATCHED","set_their_key","myInfo","theirInfo","generatedSas","generateSas","generate_bytes","mac","baseInfo","calculate_mac","E2EE_SAS_KEYS_MAC_MISMATCH","ed25519","E2EE_SAS_MISSING_KEY","computedMac","E2EE_SAS_MAC_MISMATCH","isE2EEEnabled","generate_one_time_keys","otKeys","one_time_keys","curve25519","mark_keys_as_published","keyList","deviceKeyId","macMessage","olmUtil","Utility","sha256","ManagedKeyHandler","_conferenceJoined","_olmAdapter","_rotateKey","debounce","_rotateKeyImpl","_ratchetKey","_ratchetKeyImpl","_onParticipantKeyUpdated","_onParticipantSasReady","_onParticipantSasAvailable","_onParticipantVerificationCompleted","_onParticipantJoined","initSessions","_generateKey","updateKey","material","keyBytes","subtle","importKey","newKey","textEncoder","TextEncoder","deriveBits","encode","ratchet","E2EEncryption","e2ee","_externallyManaged","externallyManagedKey","_keyHandler","testing","disableE2EE","enableEncodedTransformSupport","setEnabled","_this$_keyHandler$sas","_this$_keyHandler$sas2","IDENTITY_PROPERTIES","IDENTITY_PROPERTIES_FOR_COMPARE","compareIdentities","parseDiscoInfo","identities","Caps","disco","rooms","externalFeatures","emuc","_addChatRoom","_removeChatRoom","external","_generateVersion","_updateRoomWithExternalFeatures","removeFromPresence","addOrReplaceInPresence","getFeaturesAndIdentities","_getDiscoInfo","_fixChatRoomPresenceMap","_notifyVersionChanged","sortedIdentities","accumulatedValue","sortedFeatures","sha1","generateSha","NETWORK_INFO_EVENT","_current","isOnline","updateNetworkInfo","getJitterDelay","retry","minDelay","ResumeTask","stropheConnection","_stropheConn","_resumeRetryN","_retryDelay","retryDelay","schedule","_cancelResume","_removeNetworkOnlineListener","_networkOnlineListener","NetworkInfo","_scheduleResume","_resumeTimeout","_resumeConnection","streamManagement","resumeToken","pattern","oldToken","LastRequestTracker","_lastSuccess","_lastFailedMessage","startTracking","xmppConnection","originalRawInput","rawMessage","getLastFailedMessage","getTimeSinceLastSuccess","getConnectionPluginDefinition","ConnectionPluginListenable","PingConnectionPlugin","ConnectionPlugin","getTimeSinceLastServerResponse","onPingThresholdExceeded","pingOptions","failedPings","_onPingThresholdExceeded","_getTimeSinceLastServerResponse","pingTimeout","pingThreshold","threshold","pingTimestampsToKeep","pingExecIntervals","ping","_addPingExecutionTimestamp","sendIQ2","startInterval","remoteJid","_lastServerCheck","errmsg","stopInterval","getPingSuspendTime","pingIntervals","maxInterval","previousTS","currentInterval","XmppConnection","CONN_STATUS_CHANGED","CONN_SHARD_CHANGED","enableWebsocketResume","websocketKeepAlive","websocketKeepAliveUrl","serviceUrl","shard","xmppPing","_options","_usesWebsocket","startsWith","_rawInputTracker","LastSuccessTracker","_resumeTask","_deferredIQs","_onPingErrorThresholdExceeded","_oneSuccessfulConnect","websocket","isUsingWebSocket","pingDomain","_this$_options$pingOp","_maybeStartWSKeepAlive","_stropheConnectionCb","targetCallback","blockCallback","_this$_options$pingOp2","_maybeEnableStreamResume","_keepAliveAndCheckShard","_processDeferredIQs","_tryResumingConnection","_wsKeepAlive","_len3","_key3","_clearDeferredIQs","deferred","closeWebsocket","intervalWithJitter","responseShard","timeLeft","_this$_stropheConn","_this$_stropheConn$_p","_this$_stropheConn$_p2","sendUnavailableBeacon","sendBeacon","createExpBackoffTimer","Moderator","_this$options$hosts","_this$options$hosts2","getNextTimeout","getNextErrorTimeout","sipGatewayEnabled","targetJid","hosts","targetUrl","conferenceRequestUrl","focusUserJids","focusUserJid","isFocusJid","focusJid","isSipGatewayEnabled","_createConferenceRequest","roomJid","_config$analytics$rtc","_config$analytics","conferenceRequest","machineUid","iAmRecorder","iAmSipGateway","preferVisitor","visitor","_createConferenceIq","_parseConferenceIq","resultIq","vnode","authentication","externalAuth","live","sendConferenceRequest","conferenceRequestSent","_handleIqSuccess","_handleIqError","ok","resultJson","_handleSuccess","statusText","sessionError","notAuthorized","authenticationEnabled","waitMs","reservationErr","errorTextNode","errorMsg","invalidSession","errorIq","logout","JitsiTranscriptionStatus","ON","OFF","AVModeration","_xmpp","_mainRoom","_moderationEnabledByType","_whitelistAudio","_whitelistVideo","avModerationComponentAddress","approve","jidToWhitelist","jidToBlacklist","removed","approved","whitelists","newWhitelists","oldList","FEATURE_KEY","BREAKOUT_ROOM_ACTIONS","ADD","MOVE_TO_ROOM","REMOVE","RENAME","BREAKOUT_ROOM_EVENTS","BreakoutRooms","_handleMessages","_rooms","createBreakoutRoom","subject","removeBreakoutRoom","breakoutRoomJid","renameBreakoutRoom","sendParticipantToRoom","participantJid","isFeatureSupported","breakoutRoomsFeatures","getComponentAddress","breakoutRoomsComponentAddress","_setIsBreakoutRoom","_isBreakoutRoom","myroomjid","_setMainRoomJid","_mainRoomJid","getMainRoomJid","filteredPayload","_filterUpdatePayload","hiddenDomain","filteredRooms","participants","filteredParticipants","EMAIL_COMMAND","Lobby","mainRoom","maybeJoinLobbyRoom","_maybeJoinLobbyRoom","lobbyRoomJid","lobbySupported","initialDiscoRoomInfoReceived","membersOnlyEnabled","setMembersOnly","unsubscribers","unsubscribe","lobbyRoom","sendPrivateMessage","getLocalId","addMessageListener","removeMessageHandler","leave","setLobbyRoomJid","joined","email","customDomain","createRoom","disableDiscoInfo","disableFocus","enableLobby","isHiddenDomain","botType","members","avatar","clean","isSelfPresence","invitePassword","_this$lobbyRoom","denyAccess","kick","approveAccess","mainRoomJid","membersToApprove","ids","memberRoomJid","msgToSend","RoomMetadata","_metadata","setMetadata","getMetadata","roomMetadataComponentAddress","metadata","packet2JSON","json2packet","packet","filterNodeFromPresenceJSON","MEMBERS_AFFILIATIONS","extractIdentityInformation","hiddenFromRecorderFeatureEnabled","userInfo","groupInfo","group","ChatRoom","replaceParticipant","presMap","presHandlers","_removeConnListeners","inProgressEmitted","focusMucJid","noBridgeAvailable","eventsForwarder","moderator","lobby","avModeration","breakoutRooms","roomMetadata","initPresenceMap","lastPresences","phoneNumber","phonePin","participantPropertyListener","transcriptionStatus","xns","statsId","presenceUpdateTime","onConnStatusChanged","fromJoin","presenceSyncTime","doLeave","discoRoomInfo","getInfo","meetingIdValEl","setMeetingId","meetingCreatedTSValEl","membersOnly","lobbyRoomField","isBreakoutField","breakoutMainRoomField","visitorsSupported","roomMetadataEl","roomMetadataText","meetingId","createNonAnonymousRoom","getForm","form","formSubmit","onPresence","member","statusEl","hasStatusUpdate","hasVersionUpdate","xElement","mucUserItem","isReplaceParticipant","affiliation","isFocus","fromHiddenDomain","presence","xEl","_extractFeatures","_initFocus","memberOfThis","displayJids","restartByTerminateSupported","supportsRestartByTerminate","att","phone","pin","processNode","var","focusFeatures","tagHandlers","elementName","sendReaction","reaction","receiverId","setSubject","onPresenceUnavailable","destroySelect","reasonSelect","isKick","membersKeys","actorSelect","actorNick","onMessage","settingsErrorMsg","reactions","reactionElem","subjectText","stamp","dateParts","invite","passwordSelect","jsonMessage","parsedJson","tryParseJSONAndVerify","nickEl","onPresenceError","errorDescriptionNode","anonymousdomain","txtNode","ROOM_CREATION_RESTRICTION","_roomCreationRetries","NO_MAIN_PARTICIPANTS","PROMOTION_NOT_ALLOWED","NO_VISITORS_LOBBY","lobbyRoomNode","waitingForHost","_errorDescriptionNode","setAffiliation","grantIQ","kickIQ","lockRoom","onNotSupported","formsubmit","affiliationsIq","sendIq","formToSubmit","addToPresence","matchingNodes","getFromPresence","removePresenceListener","handlerIdx","mucJid","getMediaPresenceInfo","mutedNode","codecTypeNode","videoTypeNode","codecType","getMemberRole","peerJid","getLastPresence","mucNick","dial","rayo","hangup","getLobby","getAVModeration","getMetadataHandler","getPhoneNumber","getPhonePin","getMeetingId","muteParticipant","iqToFocus","onMute","onMuteVideo","_this$lobby","onMucLeft","doReject","endConferenceComponentAddress","MucConnectionPlugin","onVisitors","isRoomCreated","visitors","_createSourceExtension","sourceCompactJson","_createSsrcGroupExtension","ssrcGroupCompactJson","_getOrCreateRtpDescription","jingle","expandSourcesFromJson","jsonMessageXml","_json","sources","audioRtpDescription","videoRtpDescription","ssrcMap","ownerSources","videoSources","videoSsrcGroups","audioSources","audioSsrcGroups","_videoSources$i","_audioSources$i","CodecMimeType","MediaDirection","obtainStream","_createObtainStreamMethod","obtainScreenOnElectron","obtainScreenFromGetDisplayMediaRN","obtainScreenFromGetDisplayMedia","_getAudioConstraints","audioQuality","stereo","autoGainControl","channelCount","echoCancellation","noiseSuppression","JitsiMeetScreenObtainer","openDesktopPicker","desktopSharingFrameRate","desktopSharingResolution","desktopSharingSources","streamId","streamType","_desktopSharingFrameR","_desktopSharingFrameR2","_desktopSharingResolu","_desktopSharingResolu2","_desktopSharingResolu3","_desktopSharingResolu4","_desktopSharingResolu5","_desktopSharingResolu6","audioConstraints","optionalConstraints","chromeMediaSource","chromeMediaSourceId","minFrameRate","maxFrameRate","maxHeight","setContentHint","sourceId","sourceType","constraintOpts","screenShareSettings","preferCurrentTab","desktopPreferCurrentTab","systemAudio","desktopSystemAudio","surfaceSwitching","desktopSurfaceSwitching","desktopDisplaySurface","displaySurface","selfBrowserSurface","desktopSelfBrowserSurface","cursor","getVideoTracks","minFps","contraints","applyConstraints","errorDetails","errorName","errorStack","desktopTrack","contentHint","setDesktopSharingFrameRate","maxFps","SDPUtil","filterSpecialChars","iceparams","mediadesc","sessiondesc","findLine","parseICEUfrag","parseICEPwd","buildICEUfrag","frag","buildICEPwd","parseMID","parseMSIDAttribute","ssrcLines","msidLine","buildMLine","parseRTPMap","clockrate","parseSCTPMap","parseSCTPPort","buildRTPMap","parseCrypto","fingerprint","parseICECandidate","elems","network","buildICECandidate","hasOwnAttribute","parseSSRC","desc","parseSourceNameLine","sourceNameLine","ssrcSdpLine","parseVideoTypeLine","videoTypeLine","parseRTCPFB","haystack","needle","findLines","needles","candidateToJingle","candidateFromJingle","parsePrimaryVideoSsrc","videoMLine","numSsrcs","ssrcInfo","numGroups","ssrcGroups","fidGroup","simGroup","generateSsrc","getSsrcAttribute","attributeName","ssrcLine","parseGroupSsrcs","ssrcGroup","ssrcStr","getMedia","getUfrag","ufragLines","preferCodec","codecName","sortPayloadTypes","matchingPayloadTypes","H264","payloadsWithMode0","payloadTypes","payloadIndex","stripCodec","highProfile","highProfileCodecs","removePts","VP9","rtxApts","rtxPts","keepPts","INACTIVE","rtcpFb","SDP","mediaI","arrayEquals","array1","array2","equals","SDPDiffer","mySDP","otherSDP","onlyOnce","callFn","failICE","removeTcpCandidates","removeUdpCandidates","addMlineForNewLocalSource","clonedeep","RECVONLY","msid","groups","mids","getMediaSsrcMap","mediaSSRCs","mediaindex","linessrc","containsSSRC","medias","toJingle","thecreator","assrcline","creator","amidline","initialLastN","rtpmap","afmtpline","fmtpParameters","rtcpFbToJingle","availableSsrc","ssrcParameters","ridLines","rids","ridLine","ridInfo","extmapLines","extmap","SENDONLY","senders","SENDRECV","transportToJingle","sctpport","sctpmap","sctpAttrs","setupLine","iceParameters","payloadtype","feedback","rtcpFbFromJingle","feedbackElementTrrInt","fromJingle","jingle2media","__","hdrExt","userSources","nonUserSources","isUserSource","sourceStr","_value","getNewMedia","myMedias","othersMedias","newMedia","othersMediaIdx","myMedia","othersMedia","otherSsrcGroup","mySsrcGroup","modify","sdpMediaSsrcs","modified","ssrcNum","mediaSsrc","_defer","hasQueueMicrotask","queueMicrotask","hasSetImmediate","setImmediate","hasNextTick","nextTick","defer","DLL","tail","removeLink","newNode","setInitial","cur","testFn","curr","dll","handlePromise","invokeCallback","isAsync","asyncFn","concurrency","wrapAsync","numRunning","workersList","drain","saturated","unsaturated","processingScheduled","_insert","insertAtFront","rejectOnError","rej","promiseCallback","started","_createTaskItem","_tasks","_createCB","tasks","idle","_maybeDrain","eventMethod","handleAndRemove","isProcessing","datum","pushAsync","kill","unshiftAsync","running","defineProperties","ClearedQueueError","AsyncQueue","_queue","_processQueueTasks","_stopped","_taskCallbacks","finishedCallback","shutdown","JingleSessionState","PENDING","ACTIVE","ENDED","JingleSession","localJid","mediaConstraints","pcConfig","usedrip","dripContainer","_signalingLayer","initiatorJid","responderJid","initialize","signalingLayer","doInitialize","addIceCandidates","getState","addSources","removeSources","terminate","failure","acceptOffer","MediaSessionEvents","IQ_TIMEOUT","_addSourceElement","ssrc_","JingleSessionPC","jingleContents","videoContents","receiverConstraints","sourceFrameHeightSel","_bridgeSessionId","_cachedOldLocalSdp","_cachedNewLocalSdp","_iceCheckingStartedTimestamp","_gatheringStartedTimestamp","_sourceReceiverConstraints","_localSendReceiveVideoActive","_remoteSendReceiveVideoActive","_gatheringReported","lasticecandidate","closed","remoteRecvMaxFrameHeight","numRemoteVideoSources","numRemoteAudioSources","remoteSourceMaxFrameHeights","modificationQueue","establishmentDuration","_xmppListeners","onXmppStatusChanged","_removeSenderVideoConstraintsChangeListener","_assertNotEnded","_options$testing","wasstable","webrtcIceUdpDisable","webrtcIceTcpDisable","pcOptions","disableRtx","gatherStats","maxstats","capScreenshareBitrate","codecSettings","enableInsertableStreams","enableCodecSelectionAPI","videoQuality","settings","fromEntries","_options$desktopShari","forceTurnRelay","disableSimulcast","createPeerConnection","onicecandidate","phase","initiator","sendIceCandidate","onsignalingstatechange","oniceconnectionstatechange","isStable","reconnect","usesTerminateForRestart","enableIceRestart","iceStarted","onconnectionstatechange","icestate","onnegotiationneeded","remoteDescription","workFunction","_renegotiate","configureAudioSenderEncodings","getRemoteRecvMaxFrameHeight","getRemoteSourcesRecvMaxFrameHeight","localSDP","ice","sdpMLineIndex","jcand","sendIceCandidates","cands","sdpMid","fingerprintLine","required","newJingleErrorHandler","sendIceFailedNotification","sessionInfo","iceCandidates","rtcCandidate","RTCIceCandidate","iceCandidate","addIceCandidate","outerHTML","readSsrcInfo","ssrcElement","setSSRCOwner","i3","ssrcInfoElement","jidOrEndpointId","jingleOffer","setOfferAnswerCycle","sendSessionAccept","videoTracks","addTracks","addTrack","createOffer","offerSdp","setLocalDescription","processLocalSdpForTransceiverInfo","sendSessionInitiate","setAnswer","jingleAnswer","newRemoteSdp","_processNewJingleOfferIq","oldLocalSdp","RTCSessionDescription","setRemoteDescription","newLocalSdp","sendContentModify","notifyMySSRCUpdate","jingleOfferAnswerIq","audioTracks","bridgeSessionId","setVideoCodecs","codecList","screenshareCodec","currentCodecOrder","getConfiguredVideoCodecs","every","configureVideoSenderEncodings","replaceTransport","jingleOfferElem","enableForcedReload","sendTransportAccept","originalOffer","newFingerprint","channelLastN","accept","responder","sessionModify","setReceiverVideoConstraint","sourceReceiverConstraints","transportAccept","medialines","sendTransportReject","transportReject","setSenderVideoConstraint","maxFrameHeight","jitsiLocalTrack","getLocalVideoTracks","getLocalVideoTrack","setSenderVideoConstraints","sendSessionTerminate","sessionTerminate","reasonDescription","restart","requestRestart","onTerminated","reasonCondition","reasonText","getRemoteTracks","_parseSsrcInfoFromSourceAdd","sourceAddElem","currentRemoteSdp","addSsrcInfo","i1","midFound","i2","addRemoteStream","_addOrRemoveRemoteStream","removeRemoteStream","newSsrcs","mappedSources","addRemoteSsrc","oldSsrc","remoteSources","removeSSRCOwners","getPeerMediaInfo","_sourceMutedChanged","removeRemoteStreamsOnLeave","finishCallback","removeSsrcInfo","getRemoteSourceInfoByParticipant","_processRemoteRemoveSource","isAdd","errMsg","addOrRemoveSsrcInfo","_parseSsrcInfoFromSourceRemove","_processRemoteAddSource","remoteSdp","_ssrcs","_line$split$","_SDPUtil$parseMLine","desiredDirection","getDesiredMediaDirection","_SDPUtil$parseMLine2","optionalRemoteSdp","oldLocalSDP","createAnswer","replaceTracks","recvOnlyTransceiver","currentDirection","setMediaTransferActive","audioTransferActive","videoTransferActive","tpcUtils","oldTrack","newTrack","shouldRenegotiate","sourceRemoveElem","addTrackToPc","_addRemoveTrack","removeTrackFromPc","isRemove","operationName","setP2pVideoTransferActive","videoActive","setVideoTransferActive","modifyContents","newVideoSenders","parseVideoSenders","sourceMaxFrameHeights","parseSourceMaxFrameHeight","isRemoteVideoActive","oldSDP","newSDP","getSignaledSourceInfo","sdpDiffer","mediaIndex","signaledSsrcs","ctx","removedSsrcInfo","addedSsrcInfo","request","failureCb","errResponse","errorElSel","errorReasonSel","errorMsgSel","getIceConnectionState","getConnectionState","_parseIceCandidates","parseCandidates","candidateAttrs","JingleConnectionPlugin","iceConfig","sessions","jvbIceConfig","jvb","p2pIceConfig","offerToReceiveAudio","offerToReceiveVideo","onJingle","fromJid","sess","jsonMessages","_audioVideoSsrcs","audioVideoSsrcs","logMessage","startMuted","_$$find","iceUfrag","icePwd","dtlsFingerprint","successTime","newP2PJingleSession","getStunAndTurnCredentials","v2Res","onReceiveStunAndTurnCredentials","v1Res","iceservers","dict","urls","iceServersOverride","targetType","temp","useTurnUdp","getLog","updateLog","StropheLogger","logIncoming","logOutgoing","RAYO_XMLNS","RayoConnectionPlugin","onRayo","roomPass","callResource","lastErrorStatus","resetLastErrorStatusRegExpr","lastErrorStatusRegExpr","FAILURE_REGEX","DEFAULT_STUN_SERVERS","FEATURE_JIGASI","XMPP","token","bosh","disconnectInProgress","authenticatedUser","deploymentInfo","_components","errStatusCapture","createConnection","shard_changed","suspend_time","time_since_last_success","_initStrophePlugins","initFeaturesList","disableBeforeUnloadHandlers","enableOpusRed","enableRemb","enableTcc","getConnection","connectionHandler","statusStr","_maybeSendDeploymentInfoStat","_sysMessageHandler","sendDiscoInfo","_resetState","sendDeploymentInfo","_processDiscoInfoIdentities","anonymousConnectionFailed","connectionFailed","lastErrorMsg","wasIntentionalDisconnect","_getConnectionFailedReasonDetails","lastFailedRawMessage","_parseConnectionFailedMessage","speakerStatsComponentAddress","processLobbyFeatures","fr","_ref3","region","backendRelease","processBreakoutRoomsFeatures","rename","_ref4","_onPrivateMessage","_onSystemMessage","foundIceServers","attaching","configDomain","hostname","_startConnecting","onCreateResource","getRoomJid","mucNickname","muc","getJingleLog","getXmppLog","getSessions","disconnectListener","_cleanupXmppConnection","evType","p2pStunServers","stunServers","iceTransportPolicy","headersArr","sendFaceLandmarksEvent","faceExpression","jsonString","users","acceptedStatuses","aprops","logObject","authenticateAndUpgradeRole","rejectPromise","onLoginSuccessful","canceled","finally","authenticationError","connectionError","BridgeChannel","_channel","_connected","_eventEmitter","_mode","_areRetriesEnabled","_closedFromClient","datachannel","createDataChannel","_handleChannel","_wsUrl","_initWebSocket","ws","_startConnectionRetries","timeoutS","reload","isOpen","_retryTimeout","_stopConnectionRetries","_retryWebSocketConnection","createBridgeChannelClosedEvent","sendEndpointStatsMessage","colibriClass","msgPayload","sendSetLastNMessage","lastN","sendReceiverVideoConstraintsMessage","sendSourceVideoTypeMessage","dominantSpeakerEndpoint","previousSpeakers","isActive","forwardedSources","getParticipantCount","jsonObject","CameraFacingMode","logDisabled_","deprecationWarnings_","extractVersion","uastring","pos","wrapPeerConnectionEvent","eventNameToWrap","nativeAddEventListener","nativeEventName","wrappedCallback","modifiedEvent","handleEvent","_eventMap","nativeRemoveEventListener","unwrappedCb","disableLog","disableWarnings","deprecated","oldMethod","newMethod","compactObject","walkStats","resultSet","filterStats","outbound","streamStatsType","filteredResult","trackStats","trackStat","trackId","shimGetUserMedia","browserDetails","constraintsToChrome_","cc","ideal","exact","oldname_","oc","mix","advanced","shimConstraints_","remap","face","facingMode","getSupportedFacingModeLies","getSupportedConstraints","dev","shimError_","PermissionDeniedError","PermissionDismissedError","InvalidStateError","DevicesNotFoundError","ConstraintNotSatisfiedError","TrackStartError","MediaDeviceFailedDueToShutdown","MediaDeviceKillSwitchOn","TabCaptureError","ScreenCaptureError","DeviceCaptureError","cs","getAudioTracks","DOMException","shimGetDisplayMedia","getSourceId","widthSpecified","heightSpecified","frameRateSpecified","shimMediaStream","MediaStream","webkitMediaStream","shimOnTrack","_ontrack","origSetRemoteDescription","_ontrackpoly","getReceivers","dispatchEvent","shimGetSendersWithDtmf","shimSenderWithDtmf","dtmf","_dtmf","createDTMFSender","_pc","_senders","origAddTrack","origRemoveTrack","removeTrack","origAddStream","addStream","origRemoveStream","removeStream","origGetSenders","shimGetStats","origGetStats","onSucc","onErr","fixChromeStats_","localcandidate","remotecandidate","makeMapStats","successCallbackWrapper_","shimSenderReceiverGetStats","origGetReceivers","receivers","srcElement","MediaStreamTrack","shimAddTrackRemoveTrackWithNative","getLocalStreams","_shimmedLocalStreams","existingSenders","newSenders","newSender","shimAddTrackRemoveTrack","origGetLocalStreams","nativeStreams","_reverseStreams","_streams","newStream","replaceInternalStreamId","internalId","externalStream","internalStream","oldStream","methodObj","origSetLocalDescription","replaceExternalStreamId","origLocalDescription","getOwnPropertyDescriptor","streamid","shimPeerConnection","webkitRTCPeerConnection","fixNegotiationNeeded","getConfiguration","sdpSemantics","nativeGetUserMedia","getSettings","nativeGetSettings","nativeApplyConstraints","preferredMediaSource","mediaSource","RTCTrackEvent","modernStatsTypes","inboundrtp","outboundrtp","candidatepair","nativeGetStats","shimSenderGetStats","shimReceiverGetStats","shimRemoveStream","shimRTCDataChannel","DataChannel","RTCDataChannel","shimAddTransceiver","origAddTransceiver","addTransceiver","setParametersPromises","initParameters","shouldPerformCheck","sendEncodings","encodingParam","scaleResolutionDownBy","maxFramerate","getParameters","encodings","shimGetParameters","origGetParameters","shimCreateOffer","origCreateOffer","shimCreateAnswer","origCreateAnswer","shimLocalStreamsAPI","_localStreams","_addTrack","shimRemoteStreamsAPI","getRemoteStreams","_remoteStreams","_onaddstream","_onaddstreampoly","shimCallbacksAPI","successCallback","failureCallback","withCallback","_getUserMedia","shimConstraints","errcb","shimRTCIceServerUrls","pcConstraints","newIceServers","shimTrackEventTransceiver","shimCreateOfferLegacy","offerOptions","audioTransceiver","setDirection","videoTransceiver","shimAudioContext","shimRTCIceCandidate","NativeRTCIceCandidate","nativeCandidate","parsedCandidate","augmentedCandidate","toJSON","shimMaxMessageSize","_sctp","sctpInDescription","getRemoteFirefoxVersion","canSendMMS","remoteIsFirefox","canSendMaxMessageSize","getCanSendMaxMessageSize","remoteMMS","getMaxMessageSize","POSITIVE_INFINITY","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","DEFAULT_CONSTRAINTS","audioOutputDeviceId","audioOutputChanged","disableAP","disableAEC","disableNS","disableAGC","featureDetectionAudioEl","isAudioOutputDeviceChangeAvailable","availableDevicesPollTimer","availableDevices","emptyFuncton","sendDeviceListToAnalytics","deviceList","audioInputDeviceCount","audioOutputDeviceCount","videoInputDeviceCount","videoOutputDeviceCount","groupId","rtcUtils","_options$audioQuality","origAttachMediaStream","attachMediaStream","srcObject","isDeviceChangeAvailable","getAudioOutputDevice","ex","screenObtainer","isDeviceListAvailable","ds","_updateKnownDevices","umDevices","gumTimeout","timeoutExpired","_updateGrantedPermissions","jitsiError","_getDesktopMedia","_getMissingTracks","requestedDevices","missingDevices","audioDeviceRequested","audioTracksReceived","videoDeviceRequested","videoTracksReceived","_onMediaDevicesListChanged","devicesReceived","pds","newDevices","mediaDeviceInfoToJSON","facing","compareAvailableMediaDevices","um","grantedPermissions","obtainAudioAndVideoPermissions","otherOptions","mediaStreamsMetaData","maybeRequestDesktopDevice","desktopSharingSourceDevice","matchingDevice","deviceConstraints","maybeRequestCaptureDevices","requestedCaptureDevices","Resolutions","cameraDeviceId","USER","micDeviceId","getConstraints","desktopStream","desktopAudioTracks","desktopAudioStream","desktopVideoTracks","desktopVideoStream","avStream","audioStream","effects","videoStream","stopMediaStream","deviceType","mediaStream","release","isDesktopSharingEnabled","setAudioOutputDevice","getCurrentlyAvailableMediaDevices","arePermissionsGrantedForAvailableDevices","getEventDataForActiveDevice","deviceData","isUserStreamById","trackHandler2Prop","JitsiTrack","streamInactiveHandler","trackMediaType","containers","_streamInactiveHandler","_setStream","_addMediaStreamInactiveHandler","onended","oninactive","_attachTTFMTracker","container","_onTrackAttach","_onTrackDetach","_setHandler","_unregisterHandlers","videoTrack","RTCUtils","getStreamId","getSsrc","getTrack","getTrackLabel","getTrackId","getUsageLabel","getVideoType","getHeight","getWidth","isLocalAudioTrack","isWebRTCTrackMuted","newAudioLevel","setAudioOutput","JitsiLocalTrack","rtcId","_setEffectInProgress","effect","_startStreamEffect","_this$_constraints$he","_constraints","maxEnabledResolution","_prevSetMuted","_facingMode","_trackEnded","_hasSentData","_testDataSent","_realDeviceId","_sourceName","_ssrc","_trackMutedTS","_onDeviceListWillChange","oldRealDeviceId","_setRealDeviceIdFromDeviceList","_onAudioOutputDeviceChanged","_initNoDataFromSourceHandlers","_addStreamToConferenceAsUnmute","_addLocalTrackToPc","_fireNoDataFromSourceEvent","isReceivingData","createNoDataFromSourceEvent","_isNoDataFromSourceEventsEnabled","_queueSetMuted","setMuted","_setMuted","_removeStreamFromConferenceAsMute","_removeLocalTrackFromPc","_sendMuteStatus","_setTrackMuteStatus","logMuteInfo","_streamEffect","_stopStreamEffect","stopStream","streamOptions","getDeviceId","getCameraFacingMode","streamsInfo","cont","_sendBridgeVideoTypeMessage","_originalStream","startEffect","stopEffect","_switchCamera","ENVIRONMENT","_switchStreamEffect","setEffect","_this$track$getSettin","_this$track","trackSettings","getCaptureResolution","getDuration","isEnded","_stopStreamInProgress","_effectEnabled","setConference","setSsrc","unmute","found","PLAN_B_MIDS","findSimGroup","grp","findFidGroup","addSimGroupSources","sourceGroups","sourceList","findSourcebyId","relatedFidGroup","relatedSsrc","addSourcesToMline","otherSsrc","simGroup2","checkIfMlineForSsrcExists","mlines","Interop","toPlanB","sessionMedia","bLine","bundle","msidSemantic","semantic","resStr","toUnifiedPlan","currentDesc","iceRestart","newDesc","oldDesc","newMLine","oldMLine","checkForIceRestart","newIceUfrag","newIcePwd","newMline","mLineForData","ssrc2group","createSourceGroupMap","bundleOnly","resultSdp","SignalingEvents","PEER_MUTED_CHANGED","PEER_VIDEO_TYPE_CHANGED","SOURCE_MUTED_CHANGED","SOURCE_UPDATED","SOURCE_VIDEO_TYPE_CHANGED","getSourceNameForJitsiTrack","trackIdx","getMediaTypeFromSourceName","firstLetterOfMediaTypeIdx","firstLetterOfMediaType","getSourceIndexFromSourceName","nameParts","SignalingLayer","getPeerSourceInfo","getSSRCOwner","getTrackSourceName","ssrcList","setTrackMuteStatus","setTrackVideoType","updateSsrcOwnersOnLeave","DEFAULT_LAST_N","SIM_LAYERS","scaleFactor","STANDARD_CODEC_SETTINGS","av1","maxBitratesVideo","low","standard","high","fullHd","ultraHd","ssHigh","scalabilityModeEnabled","useSimulcast","useKSVC","h264","vp8","vp9","VIDEO_CODECS_BY_COMPLEXITY","AV1","VP8","VIDEO_QUALITY_LEVELS","VIDEO_QUALITY_SETTINGS","parsePrimarySSRC","parseSecondarySSRC","_getSSRCCount","MLineWrap","getSSRCAttrValue","ssrcNumber","attrName","ssrcObj","removeSSRC","addSSRCAttribute","findGroup","findGroups","findGroupByPrimarySSRC","primarySSRC","findSSRCByMSID","getSSRCCount","containsAnySSRCGroups","getPrimaryVideoSsrc","fecGroup","getRtxSSRC","getSSRCs","getPrimaryVideoSSRCs","videoSSRCs","ssrcGroupInfo","dumpSSRCGroups","removeGroupsWithSSRC","removeGroupsBySemantics","replaceSSRC","oldSSRC","newSSRC","addSSRCGroup","SdpTransformWrap","rawSDP","parsedSDP","selectMedia","selectedMLines","toRawSDP","LocalSdpMunger","localEndpointId","audioSourcesToMsidMap","videoSourcesToMsidMap","_generateMsidAttribute","_transformMediaIdentifiers","_mediaSection$mLine","_mediaSection$mLine2","_mediaSection$mLine3","_mediaSection$mLine4","_mediaSection$mLine4$","mediaDirection","_updateSourcesToMsidMap","storedStreamId","generatedMsid","_hasHadVideoTrack","_hasHadAudioTrack","generatedStreamId","transformStreamIdentifiers","sessionDesc","_transformer$selectMe","transformer","audioMLine","_injectSourceNames","videoMlines","_mediaSection$mLine5","_mediaSection$mLine5$","_mediaSection$mLine6","nameExists","trackIndexParts","trackIndex","_this$tpc$getLocalVid","updateAssociatedRtxStream","primarySsrcInfo","rtxSsrc","primarySsrcMsid","primarySsrcCname","previousRtxSSRC","RtxModifier","correspondingRtxSsrcs","clearSsrcCache","setSsrcCache","ssrcMapping","modifyRtxSsrcs","sdpStr","sdpTransformer","videoMLines","modifyRtxSsrcs2","primaryVideoSsrcs","correspondingRtxSsrc","stripRtx","fidGroups","SdpSimulcast","_ssrcCache","_numOfLayers","_fillSsrcsFromCache","cachedSsrcs","_parseSimLayers","newMsid","_getSsrcAttribute","newCname","_generateNewSsrcsForSimulcast","addAssociatedAttributes","simSsrcs","simSsrc","_generateSsrc","_mLine$ssrcs","_mLine$ssrcs$find","_mLine$ssrcGroups","_mLine$ssrcs2","mungeLocalDescription","_media$ssrcs","_media$ssrcGroups$len","_media$ssrcGroups","_media$ssrcs$","simulcastSsrcs","TrackStreamingStatus","TrackStreamingStatusImpl","isInForwardedSources","isRestoringTimedout","isVideoTrackFrozen","INTERRUPTED","RESTORING","restoringTimer","rtcMutedTimestamp","streamingStatusMap","trackTimer","outOfForwardedSourcesTimeout","p2pRtcMuteTimeout","rtcMuteTimeout","_getVideoFrozenTimeout","isP2PActive","_onP2PStatus","figureOutStreamingStatus","_onUserLeft","onUserLeft","_onTrackRtcMuted","onTrackRtcMuted","_onTrackRtcUnmuted","onTrackRtcUnmuted","_onSignallingMuteChanged","onSignallingMuteChanged","_onTrackVideoTypeChanged","onTrackVideoTypeChanged","_onForwardedSourcesChanged","onForwardedSourcesChanged","_onLastNValueChanged","clearRtcMutedTimestamp","maybeSendTrackStreamingStatusEvent","_changeStreamingStatus","newStatus","getTrackStreamingStatus","_setTrackStreamingStatus","isVideoRTCMuted","inP2PMode","isRestoringTimedOut","_isRestoringTimedout","audioOnlyMode","getLastN","newState","_getNewStateForP2PMode","_getNewStateForJvbMode","_clearRestoringTimer","oldStreamingStatus","streamingStatus","nowMs","startedMs","trackStreamingStatus","createTrackStreamingStatusEvent","leavingForwardedSources","enteringForwardedSources","_clearEnteredForwardedSourcesTimestamp","_setEnteredForwardedSourcesTimestamp","rTimer","enteredForwardedSourcesTimestamp","_getEnteredForwardedSourcesTimestamp","_isCurrentTrack","ttfmTrackerAudioAttached","ttfmTrackerVideoAttached","containerEvents","JitsiRemoteTrack","ownerEndpointId","_trackStreamingStatus","_trackStreamingStatusImpl","_enteredForwardedSourcesTimestamp","_addEventListener","_removeEventListener","hasBeenMuted","_bindTrackHandlers","_containerHandlers","_containerEventHandler","_onTrackMute","_onTrackUnmute","_initTrackStreamingStatus","_disposeTrackStreamingStatus","setMute","getSSRC","_playCallback","getConnectionTimes","gumStart","gumEnd","gumDuration","ttfm","_getStatus","_p2pConnStatusRtcMuteTimeout","_peerConnStatusRtcMuteTimeout","_peerConnStatusOutOfLastNTimeout","VideoEncoderScalabilityMode","VIDEO_CODECS","TPCUtils","_this$pc$options","videoQualitySettings","_codecConfig$maxBitra","codecConfig","bitrateSettings","maxbitratesvideo","_calculateActiveEncodingParams","localVideoTrack","newHeight","_this$pc$options2","_this$pc$options2$vid","codecBitrates","trackCaptureHeight","effectiveNewHeight","desktopShareBitrate","desktopbitrate","isScreenshare","scalabilityMode","L3T3_KEY","L3T3","lvl","_isScreenshareBitrateCapped","L1T3","ULTRA","FULL","HIGH","STANDARD","L2T3_KEY","L2T3","_configureSenderEncodings","localTrack","_transceiver$sender","_parameters$encodings","_t$sender","_t$sender$track","_t$receiver","_t$receiver$track","_getStreamEncodings","_enableSenderEncodings","_parameters$encodings2","getConfiguredVideoCodec","isSpatialScalabilityOn","_getVideoStreamEncodings","captureResolution","cameraMaxbitrate","effectiveScaleFactors","sim","effectiveBitrates","standardSimulcastEncodings","_isRunningInFullSvcMode","_capScreenshareBitrate","_updateSenderEncodings","_parameters$encodings3","transceiverInit","calculateEncodingsActiveState","videoStreamEncodings","activeState","_videoStreamEncodings","calculateEncodingsBitrates","_this$pc$options3","_this$pc$options3$vid","calculateEncodingsScalabilityMode","scalabilityModes","calculateEncodingsScaleFactor","isRunningInSimulcastMode","ensureCorrectOrderOfSsrcs","parsedSdp","reorderedSsrcs","insertUnifiedPlanSimulcastReceive","simulcastLine","mLines","senderMids","_localTrackTransceiverMids","simulcast_03","simulcast","_newTrack$getType","_newTrack$getTrack","isNewLocalSource","stopped","_newTrack$getSourceNa","transceiverMid","setEncodings","_updateVideoSenderParameters","settledResult","DD_HEADER_EXT_URI","TraceablePeerConnection","_dtmfSender","_dtmfTonesQueue","remoteTracksBySsrc","remoteTracks","localSSRCs","remoteSSRCs","localUfrag","remoteUfrag","_dtlsTransport","_peerVideoTypeChanged","_peerMutedChanged","_sourceVideoTypeChanged","safeConstraints","statsinterval","_usesCodecSelectionAPI","interop","localSdpMunger","getLocalEndpointId","rtxModifier","_senderMaxHeights","_supportsDDHeaderExt","what","onTrack","evt","_remoteTrackAdded","_remoteTrackRemoved","ondatachannel","results","_processStat","_lastVideoSenderUpdatePromise","statValue","endTime","times","dumpSDP","isAddOperation","hasLocalSource","hasAnyTracksOfType","_getReceiversByEndpointIds","endpoints","remoteTrackIds","remote","_remote$track","h264SimulcastEnabled","getSynchronizationSources","currentCodec","_this$localSSRCs$get","_this$localSSRCs$get$","_this$localSSRCs$get$2","remoteTrack","endpointTracksByMediaType","primarySsrcs","fidLines","getTargetVideoBitrates","findTrackById","remoteSDP","mediaLine","mls","trackSsrc","peerMediaInfo","_createRemoteTrack","remoteTracksMap","userTracksByMediaType","_userTracksByMediaTyp","jitsiTrack","toBeRemoved","_removeRemoteTrack","_userTracksByMediaTyp2","_extractSSRCMap","groupsMap","groupSSRCs","groupSsrcs","_getSSRC","_injectSsrcGroupForUnifiedSimulcast","getters","_adjustRemoteMediaDirection","isSharingLowFpsScreen","_isSharingScreen","_mungeCodecOrder","currentCodecs","ULPFEC","RED","_updateAv1DdHeaders","_mLine$ext","isSender","ext","headerIndex","shouldNegotiateHeaderExts","webrtcStream","promiseChain","_assertTrackBelongs","doesBelong","_this$peerconnection$","rtpSender","defaultCodec","_description$sdp","_this$peerconnection$2","currentSdp","isVideoCodecDisabled","_this$peerconnection$3","lowFps","webRtcStream","findSenderByKind","_this$peerconnection$4","localSdp","_transceiver$mid","oldTrackSSRC","oldSsrcNum","_extractPrimarySSRC","localSources","_getPreferredCodecForScreenshare","_mungeOpus","enableOpusDtx","opusMaxAverageBitrate","OPUS","fmtpOpus","fmtpConfig","sdpChanged","maxaveragebitrate","usedtx","mungedConfig","_mungeInactive","_initializeDtlsTransport","onstatechange","_setMaxBitrates","isLocalSdp","codecScalabilityModeSettings","isDoingVp9KSvc","limit","calculateExpectedSendResolution","maxValue","localAudioTrack","preferredCodec","_this$_senderMaxHeigh","currentDescription","_updateVideoSenderEncodings","nextFunction","nextPromise","videoSender","isScreensharingTrack","preference","degradationPreference","codecForCamera","bitrates","scaleFactors","needsUpdate","expectedPattern","matchingCodec","sendTones","tones","interToneGap","ontonechange","_onToneChange","toneBuffer","insertDTMF","tone","peerTracks","_removePeerConnection","_createOfferOrAnswer","isOffer","logName","handleSuccess","resolveFn","rejectFn","_processLocalSSRCsMap","handleFailure","eventType","_RTCRtpReceiver$getCa","capabilities","oaPromise","sourceIdentifier","newSSRCNum","oldSSRCNum","ConnectionQualityEvents","peerConnectionIdCounter","rtcTrackIdCounter","_createLocalTracks","metaData","RTC","peerConnections","_lastN","_forwardedSources","_forwardedSourcesChangeListener","_onDeviceListChanged","_updateAudioOutputForAudioTracks","destroy","_channelOpenListener","tracksInfo","initializeBridgeChannel","logError","msgType","_receiverVideoConstraints","oldForwardedSources","setReceiverVideoConstraints","sendSourceVideoType","signaling","encodedInsertableStreams","bundlePolicy","newConnection","traceablePeerConnection","addLocalTrack","getForwardedSources","localVideo","getLocalAudioTrack","localAudio","pcRemoteTracks","mutePromises","audioTrack","removeLocalTrack","elSelector","sendChannelMessage","setLastN","remoteAudioTracks","LOCAL_STATS_UPDATED","REMOTE_STATS_UPDATED","startBitrate","ConnectionQuality","_this$_options$config","_localStats","connectionQuality","jvbRTT","_lastConnectionQualityUpdate","_remoteStats","_timeIceConnected","_timeVideoUnmuted","ConferenceEvents","_updateLocalConnectionQuality","_broadcastLocalStats","ICE_CONNECTION_STATE_CHANGED","_updateRemoteStats","disableLocalStats","_updateLocalStats","_maybeUpdateUnmuteTime","serverRegion","bridgeCount","_calculateConnectionQuality","resolutionName","quality","DESKTOP","activeTPC","getActivePeerConnection","_this$_options$config2","_this$_options$config3","millisSinceStart","qualityLevel","targetHeight","rampUp","getTarget","maxIncreasePerSecond","prevConnectionQuality","diffSeconds","updateLocalConnectionQuality","isConnectionInterrupted","IceFailedHandling","_actOnIceFailed","explicitlyDisabled","useTerminateForRestart","jvbConnection","jvbConnIceState","_stopJvbSession","_canceled","_iceFailedTimeout","DetectionEvents","DETECTOR_STATE_CHANGE","VAD_NOISY_DEVICE","VAD_REPORT_PUBLISHED","VAD_SCORE_PUBLISHED","VAD_TALK_WHILE_MUTED","NoAudioSignalDetection","_timeoutTrigger","_hasAudioInput","_trackAdded","_clearTriggerTimeout","_handleAudioInputStateChange","_handleNoAudioInputDetection","_eventFired","_audioLevel","_audioTrack","P2PDominantSpeakerDetection","myUserID","createAudioContext","AudioContextImpl","TrackVADEmitter","procNodeSampleRate","vadProcessor","_procNodeSampleRate","_vadProcessor","_localTrack","_bufferResidue","_audioContext","sampleRate","getRequiredPCMFrequency","_vadSampleSize","getSampleLength","_onAudioProcess","_initializeAudioContext","_audioSource","_audioProcessingNode","createScriptProcessor","audioEvent","inData","inputBuffer","getChannelData","completeInData","sampleTimestamp","pcmSample","vadScore","calculateAudioFrameVAD","score","pcmData","_connectAudioGraph","onaudioprocess","destination","_disconnectAudioGraph","_cleanupResources","getDeviceLabel","_destroyed","VADAudioAnalyser","createVADProcessor","_createVADProcessor","_vadEmitter","_isVADEmitterRunning","_detectionServices","_vadInitTracker","_processVADScore","_trackRemoved","addVADDetectionService","vadService","detector","_stopVADEmitter","_startVADEmitter","processVADScore","_changeDetectorsMuteState","changeMuteState","vadEmitter","VADNoiseDetection","_processing","_scoreArray","_audioLvlArray","_active","_calculateNoisyScore","scoreAvg","audioLevelAvg","_setActiveState","_recordValues","avgAudioLvl","_processTimeout","posAudioLevels","VADTalkMutedDetection","_calculateVADScore","E2ePingEvents","E2E_RTT_CHANGED","E2E_PING_REQUEST","E2E_PING_RESPONSE","ParticipantWrapper","e2eping","requests","lastRequestId","sendRequest","handleResponse","maybeLogRttAndStop","scheduleNext","getDelay","removeParticipant","conferenceSize","totalSeconds","numRequests","maxMessagesPerSecond","requestId","requestMessage","timeSent","numRequestsWithResponses","totalNumRequests","JitsiE2EPingEvents","E2ePing","maxConferenceSize","participantJoined","participantLeft","messageReceived","conferenceJoined","handleRequest","participantWrapper","Jvb121EventGenerator","_jvb121","evaluateStatus","oldStatus","kJitsiLiteMode","LiteModeContext","_setupLiteModeForTrack","transformStream","TransformStream","pipeThrough","pipeTo","DESKTOP_VIDEO_CODEC_ORDER","MOBILE_P2P_VIDEO_CODEC_ORDER","MOBILE_VIDEO_CODEC_ORDER","CodecSelection","codecPreferenceOrder","visitorCodecs","connectionType","disabledCodec","preferenceOrder","supportedCodecs","_getSupportedVideoCodecs","selectedOrder","_disabledCodec","_preferredCodec","_window$RTCRtpReceive","_window$RTCRtpReceive2","_window$RTCRtpReceive3","_window$RTCRtpReceive4","supportedCodec","getCodecPreferenceList","getScreenshareCodec","selectPreferredCodec","mediaSession","_this$screenshareCode","localPreferredCodecOrder","remoteParticipants","remoteCodecsPerParticipant","selectedCodecOrder","localCodec","codecNotSupportedByRemote","remoteCodecs","participantCodec","changeCodecPreferenceOrder","getActiveMediaSession","codecOrder","codecsByVideoType","codecIndex","newCodec","updateVisitorCodecs","ReceiveVideoController","_config$startLastN","_rtc","startLastN","_maxFrameHeight","_assumedBandwidthBps","_lastNLimitedByCpu","_receiveResolutionLimitedByCpu","assumedBandwidthBps","_getDefaultSourceReceiverConstraints","_mediaSession$peercon","remoteVideoTracks","_updateIndividualConstraints","individualConstraints","defaultConstraints","getCurrentReceiverConstraints","isLastNLimitedByCpu","onMediaSessionStarted","setAssumedBandwidthBps","setLastNLimitedByCpu","setPreferredReceiveMaxFrameHeight","setReceiverConstraints","_constraints$assumedB","p2pSession","mappedConstraints","setReceiveResolutionLimitedByCpu","SendVideoController","_preferredSendMaxFrameHeight","_sourceSenderConstraints","_propagateSendMaxFrameHeight","sendMaxFrameHeight","_selectSendMaxFrameHeight","configureConstraintsForLocalSources","sourceConstraints","onSenderConstraintsReceived","videoConstraints","_this$_conference$get","setPreferredSendMaxFrameHeight","QualityLimitationReason","FixedSizeArray","_maxSize","QualityController","_codecController","_enableAdaptiveMode","enableAdaptiveMode","_encodeTimeStats","_isLastNRampupBlocked","_lastNRampupTime","lastNRampupTime","_receiveVideoController","_sendVideoController","_processOutboundRtpStats","_lowerOrRaiseLastN","cpuLimited","receiveVideoController","newLastN","videoStreamsReceived","isStillLimitedByCpu","_maybeLowerReceiveResolution","currentLevel","_maybeSwitchVideoCodec","encodeResolution","_limitedByCpuTimeout","updatedStats","codecController","_performQualityOptimizations","sourceStats","NONE","_lastNRampupTimeout","BANDWIDTH","statsPerTrack","existingStats","_trackStats$find","avgEncodeTime","totalValue","exisitingStats","sendVideoController","getFocusRecordingUpdate","jibriStatus","recordingMode","sessionID","getHiddenDomainUpdate","liveStreamViewURLContainer","liveStreamViewURL","modeContainer","sessionIDContainer","getSessionIdFromIq","jibri","getSessionId","sessionIdContainer","isFromFocus","JibriSession","_jibriJid","_statusFromJicofo","_setSessionID","setStatus","getError","_error","getID","_sessionID","getInitiator","_initiator","getLiveStreamViewURL","_liveStreamViewURL","getJibriJid","getTerminator","_terminator","getMode","setError","setLiveStreamViewURL","setStatusFromJicofo","setJibriJid","jibriJid","appData","broadcastId","_createIQ","recordingXMLUtils","_setErrorFromIq","_sessions","_chatRoom","getSession","getSessionByJibriJid","_handleFocusPresence","_handleJibriPresence","prevStatus","_emitSessionUpdate","startRecording","_addSession","stopRecording","_createSession","AverageStatReport","sum","calculate","appendReport","ConnectionAvgStats","avgRtpStatsReporter","_n","_sampleIdx","_avgRTT","_avgRemoteRTTMap","_avgRtpStatsReporter","_avgEnd2EndRTT","_onConnectionStats","_calculateAvgStats","_onRemoteStatsUpdated","_processRemoteStats","batchReport","jvbEnd2EndRTT","jvbStatsMonitor","avgRemoteRTT","_calculateAvgRemoteRTT","avgLocalRTT","_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","peerResolutions","peerPixelsSum","peerCount","myID","peerID","videosResolution","peerAvgPixels","_calculatePeerAvgVideoPixels","videos","peerSsrcCount","peerSsrcPixels","peerFpsSum","videosFps","peerAvgFPS","_calculatePeerAvgVideoFps","peerSsrcFps","transportStats","SpeakerStatsCollector","dominantSpeakerId","SpeakerStats","_onDominantSpeaker","_onUserJoin","_onUserLeave","_onDisplayNameChange","_onFaceLandmarkAdd","_updateStats","oldDominantSpeaker","newDominantSpeaker","savedUser","speakerStatsToUpdate","newParticipant","ComponentsVersions","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","VideoSIPGWConstants","_sendJibriIQ","setState","failureReason","oldState","removeStateListener","sipaddress","displayname","VideoSIPGW","sessionStateChangeListener","sessionStateChanged","handleJibriSIPState","Constants","failure_reason","createVideoSIPGWSession","SOURCE_INFO_PRESENCE_ELEMENT","SignalingLayerImpl","ssrcOwners","_localSourceState","_remoteSourceState","_addLocalSourceInfoToPresence","_bindChatRoomEventHandlers","emitAudioMutedEvent","_audioMuteHandler","_doesEndpointSendNewSourceInfo","emitVideoMutedEvent","_videoMuteHandler","emitVideoTypeEvent","_videoTypeHandler","_sourceInfoHandler","sourceInfoJSON","emitEventsFromHere","endpointSourceState","_sourceInfoJSON$sourc","sourceChanged","newMutedState","oldSourceState","newVideoType","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","_getCodecMimeType","JitsiConference","_this$connection","_this$options$config$","_this$options$config$2","additionalLogMsg","eventManager","componentsVersions","dtmfManager","somebodySupportsDTMF","wasStopped","avgRtpStatsN","speakerStatsCollector","deferredStartP2PTask","backToP2PDelay","isP2PConnectionInterrupted","p2pJingleSession","videoSIPGWHandler","recordingManager","RecordingManager","_conferenceJoinAnalyticsEventSent","isE2EESupported","_e2eEncryption","_liteModeContext","_audioSenderLimitReached","_videoSenderLimitReached","_firefoxP2pEnabled","enableFirefoxP2p","_iceRestarts","JitsiConnection","appID","errType","ANALYTICS_CONNECTION_DISCONNECTED","JitsiMediaDevicesEvents","resourceCreator","isAuthenticatedUser","_Strophe$getNodeFromJ","_config$e2eping","_config$videoQuality","_config$testing$lastN","_config$testing","_config$videoQuality2","_config$videoQuality3","_config$videoQuality4","_config$videoQuality5","_config$videoQuality6","_config$videoQuality7","_config$p2p","_config$p2p2","_config$p2p3","_config$p2p4","_config$p2p5","_config$p2p6","statisticsId","_onIceConnectionEstablished","_onIceConnectionFailed","_onIceConnectionInterrupted","_onIceConnectionRestored","_updateProperties","_sendConferenceJoinAnalyticsEvent","_removeLocalSourceOnReject","_updateRoomPresence","_registerRtcListeners","qualityOptions","mobileCodecPreferenceOrder","mobileScreenshareCodec","qualityController","aliasName","statisticsDisplayName","confID","applicationName","enableTalkWhileMuted","_audioAnalyser","vadTalkMutedDetection","enableNoisyMicDetection","vadNoiseDetection","enableNoAudioDetection","_noAudioSignalDetection","hasAudioSignal","jvb121Status","p2pDominantSpeakerDetection","userRegion","transcriptionLanguage","_maybeSetSITimeout","isJoined","isP2PEnabled","isP2PTestModeEnabled","p2pTestMode","onLocalTrackRemoved","_sendConferenceLeftAnalyticsEvent","_delayedIceFailed","_maybeClearSITimeout","leaveError","isEndConferenceSupported","localtrack","_desktopSharingFrameRate","DESKTOP_HIGH_FPS","isAuthEnabled","isLoggedIn","getAuthLogin","getPerformanceStats","longTasksStats","eventId","command","removeCommandListener","sendTextMessage","sendPrivateTextMessage","sendCommand","sendCommandOnce","removeCommand","nickKey","silent","getTranscriptionStatus","_this$getLocalTracks","addTrackPromises","_setupNewTrack","_fireMuteChangeEvent","_fireAudioLevelChangeEvent","activeTpc","actorId","_getInitialLocalTracks","trackType","isStartAudioMuted","isStartVideoMuted","muteHandler","audioLevelHandler","oldVideoType","_this$getLocalTracks2","oldTrackBelongsToConference","_doReplaceTrack","replaceTrackPromises","_this$getLocalTracks3","_setNewVideoType","videoTypeChanged","presenceChanged","addPromises","removePromises","unlock","isInteger","isVideoActive","countHidden","grantOwner","revokeOwner","isMyself","isMembersOnly","kickParticipant","_sessionInitiateTimeout","muteMediaType","fullJid","_this$p2pJingleSessio","_this$p2pJingleSessio2","_this$jvbJingleSessio","_this$jvbJingleSessio2","_updateFeatures","_maybeStartOrStopP2P","_numberOfParticipantsOnJoin","updateDTMFSupport","botParticipant","mediaSessions","tracksToBeRemoved","kickedParticipantId","kickedParticipant","transportInfo","removedTrack","_onIncomingCallP2P","rejectReason","contentName","_shouldBeInP2PMode","_rejectIncomingCall","_acceptP2PIncomingCall","_acceptJvbIncomingCall","_suspendMediaTransferForJvbConnection","_this$connection2","_this$connection2$opt","_this$connection2$opt2","_this$connection$opti","_this$connection3","_this$connection3$opt","_this$connection3$opt2","ignoreDomain","bridgeChannel","preferSctp","sctpOffered","firstWsUrl","stopOptions","p2pFailed","_stopP2PSession","isDTMFSupported","peerConnection","isSIPCallingSupported","_this$room$xmpp$moder","_this$room","_this$room$xmpp","_this$room$xmpp$moder2","setStartMutedPolicy","policy","getStartMutedPolicy","removeLocalParticipantProperty","getLocalParticipantProperty","property","overallFeedback","detailedFeedback","isCallstatsEnabled","getSsrcByTrack","_this$getActivePeerCo","sendApplicationLog","_fireIncompatibleVersionsEvent","sendEndpointMessage","broadcastEndpointMessage","sendThroughVideobridge","messageType","messageToSend","jitterDelay","_addRemoteJVBTracks","_addRemoteTracks","_addRemoteP2PTracks","p2pEstablishmentDuration","jvbEstablishmentDuration","establishmentDurationDiff","_setP2PStatus","_removeRemoteJVBTracks","_this$properties$visi","_publishedCodecs","audioLimitReached","videoLimitReached","publishedCodecs","_visitorCodecs","_hasVisitors","_maybeClearDeferredStartP2P","_removeRemoteTracks","_removeRemoteP2PTracks","sessionNickname","_resumeMediaTransferForJvbConnection","_startP2PSession","userLeftEvent","peers","shouldBeInP2P","peersId","hasBotPeer","wasP2PEstablished","skip","muteStatusChanged","getP2PConnectionState","startP2PSession","stopP2PSession","getSpeakerStats","sendFaceLandmarks","_window$JitsiMeetJS$a","_window$JitsiMeetJS","_window$JitsiMeetJS$a2","conferenceConnectionTimes","xmppConnectionTimes","globalNSConnectionTimes","app","xmppConnectingTime","connecting","connectedToMUCJoinedTime","connectingToMUCJoinedTime","numberOfParticipantsOnJoin","perf","toggleE2EE","setMediaEncryptionKey","isLobbySupported","isVisitorsSupported","disableLobby","joinLobby","myLobbyUserId","sendLobbyMessage","addLobbyMessageListener","removeLobbyMessageHandler","lobbyDenyAccess","lobbyApproveAccess","isAVModerationSupported","enableAVModeration","disableAVModeration","avModerationApprove","avModerationReject","_this$room2","_this$room3","setToken","initJitsiConference","getLogs","PERMISSION_PROMPT_IS_SHOWN","AUDIO_PERMISSION_NAME","VIDEO_PERMISSION_NAME","_permissions","permissions","_handlePermissionsChange","_permissionsApiSupported","query","_parsePermissionState","onchange","supported","permissionStatus","isDevicePermissionGranted","isMultipleAudioInputSupported","stopActiveDevices","CustomSignalingLayer","ACTIONS","ProxyConnectionPC","receiveAudio","receiveVideo","_peerConnection","_onRemoteStream","_onSendMessage","getPeerJid","processMessage","$jingle","ACCEPT","_onSessionAccept","INITIATE","_onSessionInitiate","TERMINATE","_onSessionTerminate","TRANSPORT_INFO","_onTransportInfo","_createPeerConnection","connectionStub","pcConfigStub","roomStub","jitsiRemoteTrack","onRemoteStream","onSendMessage","AudioMixer","_started","_streamsToMix","_streamMSSArray","addMediaStream","_mixedMSD","createMediaStreamDestination","streamMSS","hasGUMExecuted","getAnalyticsAttributesFromOptions","video_requested","ProxyConnectionService","jitsiConnection","_onFatalError","_convertStringToXML","UNAVAILABLE","_selfCloseConnection","localTrackIndex","localSourceNameTrack","xml","xmlDom","isVideo","convertVideoToDesktop","jitsiLocalTracks","createLocalTracks","stringifiedIq","XMLSerializer","serializeToString","onConnectionClosed","constants","recording","BUSY","RESOURCE_CONSTRAINT","UNEXPECTED_REQUEST","SERVICE_UNAVAILABLE","FILE","sipVideoGW","detection","rtcstats","errorTypes","JitsiMediaDevices","enableAnalyticsLogging","isWebRtcSupported","sendIdentityEntry","addGlobalLogTransport","globalTransport","removeGlobalLogTransport","setGlobalLogOptions","firePermissionPromptIsShownEvent","restOptions","isFirstGUM","startTS","endTS","isCollectingLocalStats","currentlyAvailableMediaDevices","createLocalTracksFromMediaStreams","trackInfo","createTrackVADEmitter","localAudioDeviceId","createAudioMixer","getActiveAudioDevice","audioDevices","devicePromiseArray","micDevice","devicePromise","outcomeArray","successfulPromises","rejectedPromises","rejectReasons","deviceLabel","setNetworkInfo","util","cachedModule","loaded","amdO","getter","definition","nmd","paths","__webpack_exports__"],"sourceRoot":""}