@abrar71/lib-jitsi-meet 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -0
- package/README.md +26 -0
- package/dist/esm/JitsiConference.js +3692 -0
- package/dist/esm/JitsiConference.js.map +1 -0
- package/dist/esm/JitsiConferenceErrors.js +126 -0
- package/dist/esm/JitsiConferenceErrors.js.map +1 -0
- package/dist/esm/JitsiConferenceEventManager.js +424 -0
- package/dist/esm/JitsiConferenceEventManager.js.map +1 -0
- package/dist/esm/JitsiConferenceEvents.js +431 -0
- package/dist/esm/JitsiConferenceEvents.js.map +1 -0
- package/dist/esm/JitsiConnection.js +187 -0
- package/dist/esm/JitsiConnection.js.map +1 -0
- package/dist/esm/JitsiConnectionErrors.js +52 -0
- package/dist/esm/JitsiConnectionErrors.js.map +1 -0
- package/dist/esm/JitsiConnectionEvents.js +57 -0
- package/dist/esm/JitsiConnectionEvents.js.map +1 -0
- package/dist/esm/JitsiMediaDevices.js +221 -0
- package/dist/esm/JitsiMediaDevices.js.map +1 -0
- package/dist/esm/JitsiMediaDevicesEvents.js +29 -0
- package/dist/esm/JitsiMediaDevicesEvents.js.map +1 -0
- package/dist/esm/JitsiMeetJS.js +499 -0
- package/dist/esm/JitsiMeetJS.js.map +1 -0
- package/dist/esm/JitsiParticipant.js +323 -0
- package/dist/esm/JitsiParticipant.js.map +1 -0
- package/dist/esm/JitsiTrackError.js +122 -0
- package/dist/esm/JitsiTrackError.js.map +1 -0
- package/dist/esm/JitsiTrackErrors.js +91 -0
- package/dist/esm/JitsiTrackErrors.js.map +1 -0
- package/dist/esm/JitsiTrackEvents.js +60 -0
- package/dist/esm/JitsiTrackEvents.js.map +1 -0
- package/dist/esm/JitsiTranscriptionStatus.js +15 -0
- package/dist/esm/JitsiTranscriptionStatus.js.map +1 -0
- package/dist/esm/modules/RTC/BridgeChannel.js +398 -0
- package/dist/esm/modules/RTC/BridgeChannel.js.map +1 -0
- package/dist/esm/modules/RTC/JitsiLocalTrack.js +896 -0
- package/dist/esm/modules/RTC/JitsiLocalTrack.js.map +1 -0
- package/dist/esm/modules/RTC/JitsiRemoteTrack.js +427 -0
- package/dist/esm/modules/RTC/JitsiRemoteTrack.js.map +1 -0
- package/dist/esm/modules/RTC/JitsiTrack.js +453 -0
- package/dist/esm/modules/RTC/JitsiTrack.js.map +1 -0
- package/dist/esm/modules/RTC/MockClasses.js +388 -0
- package/dist/esm/modules/RTC/MockClasses.js.map +1 -0
- package/dist/esm/modules/RTC/RTC.js +658 -0
- package/dist/esm/modules/RTC/RTC.js.map +1 -0
- package/dist/esm/modules/RTC/RTCUtils.js +762 -0
- package/dist/esm/modules/RTC/RTCUtils.js.map +1 -0
- package/dist/esm/modules/RTC/ScreenObtainer.js +380 -0
- package/dist/esm/modules/RTC/ScreenObtainer.js.map +1 -0
- package/dist/esm/modules/RTC/TPCUtils.js +803 -0
- package/dist/esm/modules/RTC/TPCUtils.js.map +1 -0
- package/dist/esm/modules/RTC/TraceablePeerConnection.js +2223 -0
- package/dist/esm/modules/RTC/TraceablePeerConnection.js.map +1 -0
- package/dist/esm/modules/RTCStats/DefaulLogStorage.js +35 -0
- package/dist/esm/modules/RTCStats/DefaulLogStorage.js.map +1 -0
- package/dist/esm/modules/RTCStats/RTCStats.js +219 -0
- package/dist/esm/modules/RTCStats/RTCStats.js.map +1 -0
- package/dist/esm/modules/RTCStats/RTCStatsEvents.js +92 -0
- package/dist/esm/modules/RTCStats/RTCStatsEvents.js.map +1 -0
- package/dist/esm/modules/RTCStats/interfaces.js +2 -0
- package/dist/esm/modules/RTCStats/interfaces.js.map +1 -0
- package/dist/esm/modules/browser/BrowserCapabilities.js +345 -0
- package/dist/esm/modules/browser/BrowserCapabilities.js.map +1 -0
- package/dist/esm/modules/browser/index.js +3 -0
- package/dist/esm/modules/browser/index.js.map +1 -0
- package/dist/esm/modules/connectivity/ConnectionQuality.js +389 -0
- package/dist/esm/modules/connectivity/ConnectionQuality.js.map +1 -0
- package/dist/esm/modules/connectivity/IceFailedHandling.js +84 -0
- package/dist/esm/modules/connectivity/IceFailedHandling.js.map +1 -0
- package/dist/esm/modules/connectivity/NetworkInfo.js +49 -0
- package/dist/esm/modules/connectivity/NetworkInfo.js.map +1 -0
- package/dist/esm/modules/connectivity/TrackStreamingStatus.js +453 -0
- package/dist/esm/modules/connectivity/TrackStreamingStatus.js.map +1 -0
- package/dist/esm/modules/detection/ActiveDeviceDetector.js +79 -0
- package/dist/esm/modules/detection/ActiveDeviceDetector.js.map +1 -0
- package/dist/esm/modules/detection/DetectionEvents.js +58 -0
- package/dist/esm/modules/detection/DetectionEvents.js.map +1 -0
- package/dist/esm/modules/detection/NoAudioSignalDetection.js +127 -0
- package/dist/esm/modules/detection/NoAudioSignalDetection.js.map +1 -0
- package/dist/esm/modules/detection/P2PDominantSpeakerDetection.js +47 -0
- package/dist/esm/modules/detection/P2PDominantSpeakerDetection.js.map +1 -0
- package/dist/esm/modules/detection/TrackVADEmitter.js +190 -0
- package/dist/esm/modules/detection/TrackVADEmitter.js.map +1 -0
- package/dist/esm/modules/detection/VADAudioAnalyser.js +199 -0
- package/dist/esm/modules/detection/VADAudioAnalyser.js.map +1 -0
- package/dist/esm/modules/detection/VADNoiseDetection.js +168 -0
- package/dist/esm/modules/detection/VADNoiseDetection.js.map +1 -0
- package/dist/esm/modules/detection/VADReportingService.js +203 -0
- package/dist/esm/modules/detection/VADReportingService.js.map +1 -0
- package/dist/esm/modules/detection/VADTalkMutedDetection.js +131 -0
- package/dist/esm/modules/detection/VADTalkMutedDetection.js.map +1 -0
- package/dist/esm/modules/e2ee/Context.js +274 -0
- package/dist/esm/modules/e2ee/Context.js.map +1 -0
- package/dist/esm/modules/e2ee/E2EEContext.js +158 -0
- package/dist/esm/modules/e2ee/E2EEContext.js.map +1 -0
- package/dist/esm/modules/e2ee/E2EEErrors.js +10 -0
- package/dist/esm/modules/e2ee/E2EEErrors.js.map +1 -0
- package/dist/esm/modules/e2ee/E2EEncryption.js +87 -0
- package/dist/esm/modules/e2ee/E2EEncryption.js.map +1 -0
- package/dist/esm/modules/e2ee/ExternallyManagedKeyHandler.js +24 -0
- package/dist/esm/modules/e2ee/ExternallyManagedKeyHandler.js.map +1 -0
- package/dist/esm/modules/e2ee/KeyHandler.js +137 -0
- package/dist/esm/modules/e2ee/KeyHandler.js.map +1 -0
- package/dist/esm/modules/e2ee/ManagedKeyHandler.js +182 -0
- package/dist/esm/modules/e2ee/ManagedKeyHandler.js.map +1 -0
- package/dist/esm/modules/e2ee/OlmAdapter.js +860 -0
- package/dist/esm/modules/e2ee/OlmAdapter.js.map +1 -0
- package/dist/esm/modules/e2ee/SAS.js +128 -0
- package/dist/esm/modules/e2ee/SAS.js.map +1 -0
- package/dist/esm/modules/e2ee/Worker.js +102 -0
- package/dist/esm/modules/e2ee/Worker.js.map +1 -0
- package/dist/esm/modules/e2ee/crypto-utils.js +53 -0
- package/dist/esm/modules/e2ee/crypto-utils.js.map +1 -0
- package/dist/esm/modules/e2ee/utils.js +15 -0
- package/dist/esm/modules/e2ee/utils.js.map +1 -0
- package/dist/esm/modules/e2eping/e2eping.js +314 -0
- package/dist/esm/modules/e2eping/e2eping.js.map +1 -0
- package/dist/esm/modules/flags/FeatureFlags.js +36 -0
- package/dist/esm/modules/flags/FeatureFlags.js.map +1 -0
- package/dist/esm/modules/litemode/LiteModeContext.js +50 -0
- package/dist/esm/modules/litemode/LiteModeContext.js.map +1 -0
- package/dist/esm/modules/proxyconnection/CustomSignalingLayer.js +98 -0
- package/dist/esm/modules/proxyconnection/CustomSignalingLayer.js.map +1 -0
- package/dist/esm/modules/proxyconnection/ProxyConnectionPC.js +348 -0
- package/dist/esm/modules/proxyconnection/ProxyConnectionPC.js.map +1 -0
- package/dist/esm/modules/proxyconnection/ProxyConnectionService.js +279 -0
- package/dist/esm/modules/proxyconnection/ProxyConnectionService.js.map +1 -0
- package/dist/esm/modules/proxyconnection/constants.js +14 -0
- package/dist/esm/modules/proxyconnection/constants.js.map +1 -0
- package/dist/esm/modules/qualitycontrol/CodecSelection.js +222 -0
- package/dist/esm/modules/qualitycontrol/CodecSelection.js.map +1 -0
- package/dist/esm/modules/qualitycontrol/MockClasses.js +120 -0
- package/dist/esm/modules/qualitycontrol/MockClasses.js.map +1 -0
- package/dist/esm/modules/qualitycontrol/QualityController.js +366 -0
- package/dist/esm/modules/qualitycontrol/QualityController.js.map +1 -0
- package/dist/esm/modules/qualitycontrol/ReceiveAudioController.js +73 -0
- package/dist/esm/modules/qualitycontrol/ReceiveAudioController.js.map +1 -0
- package/dist/esm/modules/qualitycontrol/ReceiveVideoController.js +216 -0
- package/dist/esm/modules/qualitycontrol/ReceiveVideoController.js.map +1 -0
- package/dist/esm/modules/qualitycontrol/SendVideoController.js +133 -0
- package/dist/esm/modules/qualitycontrol/SendVideoController.js.map +1 -0
- package/dist/esm/modules/recording/JibriSession.js +279 -0
- package/dist/esm/modules/recording/JibriSession.js.map +1 -0
- package/dist/esm/modules/recording/RecordingManager.js +257 -0
- package/dist/esm/modules/recording/RecordingManager.js.map +1 -0
- package/dist/esm/modules/recording/recordingConstants.js +21 -0
- package/dist/esm/modules/recording/recordingConstants.js.map +1 -0
- package/dist/esm/modules/recording/recordingXMLUtils.js +69 -0
- package/dist/esm/modules/recording/recordingXMLUtils.js.map +1 -0
- package/dist/esm/modules/red/red.js +108 -0
- package/dist/esm/modules/red/red.js.map +1 -0
- package/dist/esm/modules/sdp/LocalSdpMunger.js +143 -0
- package/dist/esm/modules/sdp/LocalSdpMunger.js.map +1 -0
- package/dist/esm/modules/sdp/RtxModifier.js +179 -0
- package/dist/esm/modules/sdp/RtxModifier.js.map +1 -0
- package/dist/esm/modules/sdp/SDP.js +848 -0
- package/dist/esm/modules/sdp/SDP.js.map +1 -0
- package/dist/esm/modules/sdp/SDPDiffer.js +96 -0
- package/dist/esm/modules/sdp/SDPDiffer.js.map +1 -0
- package/dist/esm/modules/sdp/SDPUtil.js +798 -0
- package/dist/esm/modules/sdp/SDPUtil.js.map +1 -0
- package/dist/esm/modules/sdp/SampleSdpStrings.js +589 -0
- package/dist/esm/modules/sdp/SampleSdpStrings.js.map +1 -0
- package/dist/esm/modules/sdp/SdpSimulcast.js +196 -0
- package/dist/esm/modules/sdp/SdpSimulcast.js.map +1 -0
- package/dist/esm/modules/sdp/SdpTransformUtil.js +337 -0
- package/dist/esm/modules/sdp/SdpTransformUtil.js.map +1 -0
- package/dist/esm/modules/sdp/constants.js +2 -0
- package/dist/esm/modules/sdp/constants.js.map +1 -0
- package/dist/esm/modules/settings/Settings.js +95 -0
- package/dist/esm/modules/settings/Settings.js.map +1 -0
- package/dist/esm/modules/statistics/AnalyticsAdapter.js +277 -0
- package/dist/esm/modules/statistics/AnalyticsAdapter.js.map +1 -0
- package/dist/esm/modules/statistics/AvgRTPStatsReporter.js +817 -0
- package/dist/esm/modules/statistics/AvgRTPStatsReporter.js.map +1 -0
- package/dist/esm/modules/statistics/LocalStatsCollector.js +149 -0
- package/dist/esm/modules/statistics/LocalStatsCollector.js.map +1 -0
- package/dist/esm/modules/statistics/PreCallTest.js +15 -0
- package/dist/esm/modules/statistics/PreCallTest.js.map +1 -0
- package/dist/esm/modules/statistics/RTPStatsCollector.js +601 -0
- package/dist/esm/modules/statistics/RTPStatsCollector.js.map +1 -0
- package/dist/esm/modules/statistics/SpeakerStats.js +163 -0
- package/dist/esm/modules/statistics/SpeakerStats.js.map +1 -0
- package/dist/esm/modules/statistics/SpeakerStatsCollector.js +161 -0
- package/dist/esm/modules/statistics/SpeakerStatsCollector.js.map +1 -0
- package/dist/esm/modules/statistics/constants.js +7 -0
- package/dist/esm/modules/statistics/constants.js.map +1 -0
- package/dist/esm/modules/statistics/statistics.js +362 -0
- package/dist/esm/modules/statistics/statistics.js.map +1 -0
- package/dist/esm/modules/util/AsyncQueue.js +102 -0
- package/dist/esm/modules/util/AsyncQueue.js.map +1 -0
- package/dist/esm/modules/util/Deferred.js +41 -0
- package/dist/esm/modules/util/Deferred.js.map +1 -0
- package/dist/esm/modules/util/EventEmitter.js +17 -0
- package/dist/esm/modules/util/EventEmitter.js.map +1 -0
- package/dist/esm/modules/util/EventEmitterForwarder.js +52 -0
- package/dist/esm/modules/util/EventEmitterForwarder.js.map +1 -0
- package/dist/esm/modules/util/Listenable.js +106 -0
- package/dist/esm/modules/util/Listenable.js.map +1 -0
- package/dist/esm/modules/util/MathUtil.js +103 -0
- package/dist/esm/modules/util/MathUtil.js.map +1 -0
- package/dist/esm/modules/util/RandomUtil.js +66 -0
- package/dist/esm/modules/util/RandomUtil.js.map +1 -0
- package/dist/esm/modules/util/Retry.js +15 -0
- package/dist/esm/modules/util/Retry.js.map +1 -0
- package/dist/esm/modules/util/ScriptUtil.js +58 -0
- package/dist/esm/modules/util/ScriptUtil.js.map +1 -0
- package/dist/esm/modules/util/StringUtils.js +21 -0
- package/dist/esm/modules/util/StringUtils.js.map +1 -0
- package/dist/esm/modules/util/TestUtils.js +14 -0
- package/dist/esm/modules/util/TestUtils.js.map +1 -0
- package/dist/esm/modules/util/UsernameGenerator.js +436 -0
- package/dist/esm/modules/util/UsernameGenerator.js.map +1 -0
- package/dist/esm/modules/util/XMLUtils.js +135 -0
- package/dist/esm/modules/util/XMLUtils.js.map +1 -0
- package/dist/esm/modules/version/ComponentsVersions.js +52 -0
- package/dist/esm/modules/version/ComponentsVersions.js.map +1 -0
- package/dist/esm/modules/videosipgw/JitsiVideoSIPGWSession.js +137 -0
- package/dist/esm/modules/videosipgw/JitsiVideoSIPGWSession.js.map +1 -0
- package/dist/esm/modules/videosipgw/VideoSIPGW.js +102 -0
- package/dist/esm/modules/videosipgw/VideoSIPGW.js.map +1 -0
- package/dist/esm/modules/videosipgw/VideoSIPGWConstants.js +65 -0
- package/dist/esm/modules/videosipgw/VideoSIPGWConstants.js.map +1 -0
- package/dist/esm/modules/watchRTC/WatchRTC.js +69 -0
- package/dist/esm/modules/watchRTC/WatchRTC.js.map +1 -0
- package/dist/esm/modules/watchRTC/functions.js +31 -0
- package/dist/esm/modules/watchRTC/functions.js.map +1 -0
- package/dist/esm/modules/watchRTC/interfaces.js +2 -0
- package/dist/esm/modules/watchRTC/interfaces.js.map +1 -0
- package/dist/esm/modules/webaudio/AudioMixer.js +74 -0
- package/dist/esm/modules/webaudio/AudioMixer.js.map +1 -0
- package/dist/esm/modules/webaudio/WebAudioUtils.js +13 -0
- package/dist/esm/modules/webaudio/WebAudioUtils.js.map +1 -0
- package/dist/esm/modules/xmpp/AVModeration.js +156 -0
- package/dist/esm/modules/xmpp/AVModeration.js.map +1 -0
- package/dist/esm/modules/xmpp/BreakoutRooms.js +230 -0
- package/dist/esm/modules/xmpp/BreakoutRooms.js.map +1 -0
- package/dist/esm/modules/xmpp/Caps.js +223 -0
- package/dist/esm/modules/xmpp/Caps.js.map +1 -0
- package/dist/esm/modules/xmpp/ChatRoom.js +1877 -0
- package/dist/esm/modules/xmpp/ChatRoom.js.map +1 -0
- package/dist/esm/modules/xmpp/ConnectionPlugin.js +37 -0
- package/dist/esm/modules/xmpp/ConnectionPlugin.js.map +1 -0
- package/dist/esm/modules/xmpp/FileSharing.js +95 -0
- package/dist/esm/modules/xmpp/FileSharing.js.map +1 -0
- package/dist/esm/modules/xmpp/JingleHelperFunctions.js +168 -0
- package/dist/esm/modules/xmpp/JingleHelperFunctions.js.map +1 -0
- package/dist/esm/modules/xmpp/JingleSession.js +166 -0
- package/dist/esm/modules/xmpp/JingleSession.js.map +1 -0
- package/dist/esm/modules/xmpp/JingleSessionPC.js +1969 -0
- package/dist/esm/modules/xmpp/JingleSessionPC.js.map +1 -0
- package/dist/esm/modules/xmpp/JingleSessionState.js +23 -0
- package/dist/esm/modules/xmpp/JingleSessionState.js.map +1 -0
- package/dist/esm/modules/xmpp/Lobby.js +384 -0
- package/dist/esm/modules/xmpp/Lobby.js.map +1 -0
- package/dist/esm/modules/xmpp/MediaSessionEvents.js +12 -0
- package/dist/esm/modules/xmpp/MediaSessionEvents.js.map +1 -0
- package/dist/esm/modules/xmpp/MockClasses.js +77 -0
- package/dist/esm/modules/xmpp/MockClasses.js.map +1 -0
- package/dist/esm/modules/xmpp/Polls.js +87 -0
- package/dist/esm/modules/xmpp/Polls.js.map +1 -0
- package/dist/esm/modules/xmpp/ResumeTask.js +149 -0
- package/dist/esm/modules/xmpp/ResumeTask.js.map +1 -0
- package/dist/esm/modules/xmpp/RoomMetadata.js +96 -0
- package/dist/esm/modules/xmpp/RoomMetadata.js.map +1 -0
- package/dist/esm/modules/xmpp/SignalingLayerImpl.js +313 -0
- package/dist/esm/modules/xmpp/SignalingLayerImpl.js.map +1 -0
- package/dist/esm/modules/xmpp/StropheErrorHandler.js +53 -0
- package/dist/esm/modules/xmpp/StropheErrorHandler.js.map +1 -0
- package/dist/esm/modules/xmpp/StropheLastSuccess.js +52 -0
- package/dist/esm/modules/xmpp/StropheLastSuccess.js.map +1 -0
- package/dist/esm/modules/xmpp/XmppConnection.js +579 -0
- package/dist/esm/modules/xmpp/XmppConnection.js.map +1 -0
- package/dist/esm/modules/xmpp/moderator.js +524 -0
- package/dist/esm/modules/xmpp/moderator.js.map +1 -0
- package/dist/esm/modules/xmpp/sha1.js +165 -0
- package/dist/esm/modules/xmpp/sha1.js.map +1 -0
- package/dist/esm/modules/xmpp/strophe.disco.js +222 -0
- package/dist/esm/modules/xmpp/strophe.disco.js.map +1 -0
- package/dist/esm/modules/xmpp/strophe.emuc.js +206 -0
- package/dist/esm/modules/xmpp/strophe.emuc.js.map +1 -0
- package/dist/esm/modules/xmpp/strophe.jingle.js +404 -0
- package/dist/esm/modules/xmpp/strophe.jingle.js.map +1 -0
- package/dist/esm/modules/xmpp/strophe.logger.js +44 -0
- package/dist/esm/modules/xmpp/strophe.logger.js.map +1 -0
- package/dist/esm/modules/xmpp/strophe.ping.js +170 -0
- package/dist/esm/modules/xmpp/strophe.ping.js.map +1 -0
- package/dist/esm/modules/xmpp/strophe.rayo.js +117 -0
- package/dist/esm/modules/xmpp/strophe.rayo.js.map +1 -0
- package/dist/esm/modules/xmpp/strophe.stream-management.js +365 -0
- package/dist/esm/modules/xmpp/strophe.stream-management.js.map +1 -0
- package/dist/esm/modules/xmpp/strophe.util.js +116 -0
- package/dist/esm/modules/xmpp/strophe.util.js.map +1 -0
- package/dist/esm/modules/xmpp/xmpp.js +973 -0
- package/dist/esm/modules/xmpp/xmpp.js.map +1 -0
- package/dist/esm/service/RTC/BridgeVideoType.js +24 -0
- package/dist/esm/service/RTC/BridgeVideoType.js.map +1 -0
- package/dist/esm/service/RTC/CameraFacingMode.js +21 -0
- package/dist/esm/service/RTC/CameraFacingMode.js.map +1 -0
- package/dist/esm/service/RTC/CodecMimeType.js +36 -0
- package/dist/esm/service/RTC/CodecMimeType.js.map +1 -0
- package/dist/esm/service/RTC/MediaDirection.js +23 -0
- package/dist/esm/service/RTC/MediaDirection.js.map +1 -0
- package/dist/esm/service/RTC/MediaType.js +20 -0
- package/dist/esm/service/RTC/MediaType.js.map +1 -0
- package/dist/esm/service/RTC/RTCEvents.js +111 -0
- package/dist/esm/service/RTC/RTCEvents.js.map +1 -0
- package/dist/esm/service/RTC/ReceiverAudioSubscription.js +27 -0
- package/dist/esm/service/RTC/ReceiverAudioSubscription.js.map +1 -0
- package/dist/esm/service/RTC/Resolutions.js +56 -0
- package/dist/esm/service/RTC/Resolutions.js.map +1 -0
- package/dist/esm/service/RTC/SignalingEvents.js +42 -0
- package/dist/esm/service/RTC/SignalingEvents.js.map +1 -0
- package/dist/esm/service/RTC/SignalingLayer.js +153 -0
- package/dist/esm/service/RTC/SignalingLayer.js.map +1 -0
- package/dist/esm/service/RTC/StandardVideoQualitySettings.js +180 -0
- package/dist/esm/service/RTC/StandardVideoQualitySettings.js.map +1 -0
- package/dist/esm/service/RTC/VideoEncoderScalabilityMode.js +36 -0
- package/dist/esm/service/RTC/VideoEncoderScalabilityMode.js.map +1 -0
- package/dist/esm/service/RTC/VideoType.js +19 -0
- package/dist/esm/service/RTC/VideoType.js.map +1 -0
- package/dist/esm/service/authentication/AuthenticationEvents.js +13 -0
- package/dist/esm/service/authentication/AuthenticationEvents.js.map +1 -0
- package/dist/esm/service/connectivity/ConnectionQualityEvents.js +13 -0
- package/dist/esm/service/connectivity/ConnectionQualityEvents.js.map +1 -0
- package/dist/esm/service/connectivity/Constants.js +3 -0
- package/dist/esm/service/connectivity/Constants.js.map +1 -0
- package/dist/esm/service/e2eping/E2ePingEvents.js +8 -0
- package/dist/esm/service/e2eping/E2ePingEvents.js.map +1 -0
- package/dist/esm/service/statistics/AnalyticsEvents.js +521 -0
- package/dist/esm/service/statistics/AnalyticsEvents.js.map +1 -0
- package/dist/esm/service/statistics/Events.js +36 -0
- package/dist/esm/service/statistics/Events.js.map +1 -0
- package/dist/esm/service/statistics/constants.js +2 -0
- package/dist/esm/service/statistics/constants.js.map +1 -0
- package/dist/esm/service/xmpp/XMPPEvents.js +359 -0
- package/dist/esm/service/xmpp/XMPPEvents.js.map +1 -0
- package/dist/esm/service/xmpp/XMPPExtensioProtocols.js +64 -0
- package/dist/esm/service/xmpp/XMPPExtensioProtocols.js.map +1 -0
- package/dist/esm/test-setup-polyfill.js +34 -0
- package/dist/esm/test-setup-polyfill.js.map +1 -0
- package/dist/esm/tools/gen-version.js +15 -0
- package/dist/esm/tools/gen-version.js.map +1 -0
- package/dist/esm/version.js +3 -0
- package/dist/esm/version.js.map +1 -0
- package/dist/umd/lib-jitsi-meet.e2ee-worker.js +484 -0
- package/dist/umd/lib-jitsi-meet.min.js +3 -0
- package/dist/umd/lib-jitsi-meet.min.js.LICENSE.txt +18 -0
- package/dist/umd/lib-jitsi-meet.min.map +1 -0
- package/package.json +93 -0
- package/types/index.d.ts +16180 -0
|
@@ -0,0 +1,973 @@
|
|
|
1
|
+
import { safeJsonParse } from '@jitsi/js-utils/json';
|
|
2
|
+
import { getLogger } from '@jitsi/logger';
|
|
3
|
+
import { cloneDeep, unescape } from 'lodash-es';
|
|
4
|
+
import { $msg, Strophe } from 'strophe.js';
|
|
5
|
+
import * as JitsiConnectionErrors from '../../JitsiConnectionErrors';
|
|
6
|
+
import * as JitsiConnectionEvents from '../../JitsiConnectionEvents';
|
|
7
|
+
import { XMPPEvents } from '../../service/xmpp/XMPPEvents';
|
|
8
|
+
import { XEP } from '../../service/xmpp/XMPPExtensioProtocols';
|
|
9
|
+
import RTCStats from '../RTCStats/RTCStats';
|
|
10
|
+
import { RTCStatsEvents } from '../RTCStats/RTCStatsEvents';
|
|
11
|
+
import browser from '../browser';
|
|
12
|
+
import { E2EEncryption } from '../e2ee/E2EEncryption';
|
|
13
|
+
import FeatureFlags from '../flags/FeatureFlags';
|
|
14
|
+
import Statistics from '../statistics/statistics';
|
|
15
|
+
import Listenable from '../util/Listenable';
|
|
16
|
+
import RandomUtil from '../util/RandomUtil';
|
|
17
|
+
import { exists, findFirst, getText } from '../util/XMLUtils';
|
|
18
|
+
import Caps, { parseDiscoInfo } from './Caps';
|
|
19
|
+
import { IDENTITY_TYPE as FILE_SHARING_IDENTITY_TYPE } from './FileSharing';
|
|
20
|
+
import XmppConnection from './XmppConnection';
|
|
21
|
+
import Moderator from './moderator';
|
|
22
|
+
import './strophe.disco';
|
|
23
|
+
import MucConnectionPlugin from './strophe.emuc';
|
|
24
|
+
import JingleConnectionPlugin from './strophe.jingle';
|
|
25
|
+
import initStropheLogger from './strophe.logger';
|
|
26
|
+
import RayoConnectionPlugin from './strophe.rayo';
|
|
27
|
+
import initStropheUtil from './strophe.util';
|
|
28
|
+
const logger = getLogger('xmpp:Xmpp');
|
|
29
|
+
/**
|
|
30
|
+
* Regex to extract exact error message on jwt error.
|
|
31
|
+
*/
|
|
32
|
+
const FAILURE_REGEX = /<failure.*><not-allowed\/><text>(.*)<\/text><\/failure>/gi;
|
|
33
|
+
/**
|
|
34
|
+
* Creates XMPP connection.
|
|
35
|
+
*
|
|
36
|
+
* @param {Object} options
|
|
37
|
+
* @param {string} [options.token] - JWT token used for authentication(JWT authentication module must be enabled in
|
|
38
|
+
* Prosody).
|
|
39
|
+
* @param {string} options.serviceUrl - The service URL for XMPP connection.
|
|
40
|
+
* @param {string} options.shard - The shard where XMPP connection initially landed.
|
|
41
|
+
* @param {string} options.enableWebsocketResume - True to enable stream resumption.
|
|
42
|
+
* @param {number} [options.websocketKeepAlive] - See {@link XmppConnection} constructor.
|
|
43
|
+
* @param {number} [options.websocketKeepAliveUrl] - See {@link XmppConnection} constructor.
|
|
44
|
+
* @param {Object} [options.xmppPing] - See {@link XmppConnection} constructor.
|
|
45
|
+
* @returns {XmppConnection}
|
|
46
|
+
*/
|
|
47
|
+
function createConnection({ enableWebsocketResume, serviceUrl = '/http-bind', shard, token, websocketKeepAlive, websocketKeepAliveUrl }) {
|
|
48
|
+
// Append token as URL param
|
|
49
|
+
if (token) {
|
|
50
|
+
// eslint-disable-next-line no-param-reassign
|
|
51
|
+
serviceUrl += `${serviceUrl.indexOf('?') === -1 ? '?' : '&'}token=${token}`;
|
|
52
|
+
}
|
|
53
|
+
return new XmppConnection({
|
|
54
|
+
enableWebsocketResume,
|
|
55
|
+
serviceUrl,
|
|
56
|
+
shard,
|
|
57
|
+
websocketKeepAlive,
|
|
58
|
+
websocketKeepAliveUrl
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Initializes Strophe plugins that need to work with Strophe.Connection directly rather than the lib-jitsi-meet's
|
|
63
|
+
* {@link XmppConnection} wrapper.
|
|
64
|
+
*
|
|
65
|
+
* @returns {void}
|
|
66
|
+
*/
|
|
67
|
+
function initStropheNativePlugins() {
|
|
68
|
+
initStropheUtil();
|
|
69
|
+
initStropheLogger();
|
|
70
|
+
}
|
|
71
|
+
// FIXME: remove once we have a default config template. -saghul
|
|
72
|
+
/**
|
|
73
|
+
* A list of ice servers to use by default for P2P.
|
|
74
|
+
*/
|
|
75
|
+
export const DEFAULT_STUN_SERVERS = [
|
|
76
|
+
{ urls: 'stun:meet-jit-si-turnrelay.jitsi.net:443' }
|
|
77
|
+
];
|
|
78
|
+
/**
|
|
79
|
+
* The name of the field used to recognize a chat message as carrying a JSON
|
|
80
|
+
* payload from another endpoint.
|
|
81
|
+
* If the json-message of a chat message contains a valid JSON object, and
|
|
82
|
+
* the JSON has this key, then it is a valid json-message to be sent.
|
|
83
|
+
*/
|
|
84
|
+
export const JITSI_MEET_MUC_TYPE = 'type';
|
|
85
|
+
/**
|
|
86
|
+
* The feature used by jigasi participants.
|
|
87
|
+
* @type {string}
|
|
88
|
+
*/
|
|
89
|
+
export const FEATURE_JIGASI = 'http://jitsi.org/protocol/jigasi';
|
|
90
|
+
/**
|
|
91
|
+
* The feature used by jibri participants.
|
|
92
|
+
* @type {string}
|
|
93
|
+
*/
|
|
94
|
+
export const FEATURE_JIBRI = 'http://jitsi.org/protocol/jibri';
|
|
95
|
+
/**
|
|
96
|
+
* The feature used by jigasi transcriber participants.
|
|
97
|
+
* @type {string}
|
|
98
|
+
*/
|
|
99
|
+
export const FEATURE_TRANSCRIBER = 'http://jitsi.org/protocol/transcriber';
|
|
100
|
+
/**
|
|
101
|
+
* The feature used by the lib to mark support for e2ee. We use the feature by putting it in the presence
|
|
102
|
+
* to avoid additional signaling (disco-info).
|
|
103
|
+
* @type {string}
|
|
104
|
+
*/
|
|
105
|
+
export const FEATURE_E2EE = 'https://jitsi.org/meet/e2ee';
|
|
106
|
+
/**
|
|
107
|
+
* @internal
|
|
108
|
+
*/
|
|
109
|
+
export default class XMPP extends Listenable {
|
|
110
|
+
/**
|
|
111
|
+
* FIXME describe all options
|
|
112
|
+
* @param {Object} options
|
|
113
|
+
* @param {String} options.serviceUrl - URL passed to the XMPP client which will be used to establish XMPP
|
|
114
|
+
* connection with the server.
|
|
115
|
+
* @param {boolean} options.enableWebsocketResume - Enables XEP-0198 stream management which will make the XMPP
|
|
116
|
+
* module try to resume the session in case the Websocket connection breaks.
|
|
117
|
+
* @param {number} [options.websocketKeepAlive] - The websocket keep alive interval. See {@link XmppConnection}
|
|
118
|
+
* constructor for more details.
|
|
119
|
+
* @param {number} [options.websocketKeepAliveUrl] - The websocket keep alive url. See {@link XmppConnection}
|
|
120
|
+
* constructor for more details.
|
|
121
|
+
* @param {Object} [options.xmppPing] - The xmpp ping settings.
|
|
122
|
+
* @param {Array<Object>} options.p2pStunServers see {@link JingleConnectionPlugin} for more details.
|
|
123
|
+
* @param token
|
|
124
|
+
*/
|
|
125
|
+
constructor(options, token) {
|
|
126
|
+
super();
|
|
127
|
+
if (options.bosh && !options.serviceUrl) {
|
|
128
|
+
throw new Error('The "bosh" option is no longer supported, please use "serviceUrl" instead');
|
|
129
|
+
}
|
|
130
|
+
this.connection = null;
|
|
131
|
+
this._disconnectInProgress = false;
|
|
132
|
+
this.connectionTimes = {};
|
|
133
|
+
this.options = options;
|
|
134
|
+
this.token = token;
|
|
135
|
+
this.authenticatedUser = false;
|
|
136
|
+
if (!this.options.deploymentInfo) {
|
|
137
|
+
this.options.deploymentInfo = {};
|
|
138
|
+
}
|
|
139
|
+
// Cache of components used for certain features.
|
|
140
|
+
this._components = [];
|
|
141
|
+
// We want to track messages that are received before we process the disco-info components
|
|
142
|
+
// re-order of receiving we may drop some messages
|
|
143
|
+
this._preComponentsMsgs = [];
|
|
144
|
+
initStropheNativePlugins();
|
|
145
|
+
const xmppPing = options.xmppPing || {};
|
|
146
|
+
// let's ping the main domain (in case a guest one is used for the connection)
|
|
147
|
+
xmppPing.domain = options.hosts.domain;
|
|
148
|
+
this.connection = createConnection({
|
|
149
|
+
enableWebsocketResume: options.enableWebsocketResume,
|
|
150
|
+
serviceUrl: options.serviceUrl,
|
|
151
|
+
shard: options.deploymentInfo.shard,
|
|
152
|
+
token,
|
|
153
|
+
websocketKeepAlive: options.websocketKeepAlive,
|
|
154
|
+
websocketKeepAliveUrl: options.websocketKeepAliveUrl,
|
|
155
|
+
xmppPing
|
|
156
|
+
});
|
|
157
|
+
this.moderator = new Moderator(this);
|
|
158
|
+
// forwards the shard changed event
|
|
159
|
+
this.connection.on(XmppConnection.Events.CONN_SHARD_CHANGED, () => {
|
|
160
|
+
/* eslint-disable camelcase */
|
|
161
|
+
const details = {
|
|
162
|
+
shard_changed: true,
|
|
163
|
+
suspend_time: this.connection.ping.getPingSuspendTime(),
|
|
164
|
+
time_since_last_success: this.connection.getTimeSinceLastSuccess()
|
|
165
|
+
};
|
|
166
|
+
/* eslint-enable camelcase */
|
|
167
|
+
if (this.options.testing?.enableGracefulReconnect) {
|
|
168
|
+
this.eventEmitter.emit(JitsiConnectionEvents.CONNECTION_FAILED, JitsiConnectionErrors.SHARD_CHANGED_ERROR);
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
this.eventEmitter.emit(JitsiConnectionEvents.CONNECTION_FAILED, JitsiConnectionErrors.OTHER_ERROR, undefined, undefined, details);
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
this._initStrophePlugins();
|
|
175
|
+
this.caps = new Caps(this.connection, /* clientNode */ 'https://jitsi.org/jitsi-meet');
|
|
176
|
+
// Initialize features advertised in disco-info
|
|
177
|
+
this.initFeaturesList();
|
|
178
|
+
this.connection.addHandler(this._onPrivateMessage.bind(this), null, 'message', null, null);
|
|
179
|
+
// Setup a disconnect on unload as a way to facilitate API consumers. It
|
|
180
|
+
// sounds like they would want that. A problem for them though may be if
|
|
181
|
+
// they wanted to utilize the connected connection in an unload handler
|
|
182
|
+
// of their own. However, it should be fairly easy for them to do that
|
|
183
|
+
// by registering their unload handler before us.
|
|
184
|
+
const events = `${this.options.disableBeforeUnloadHandlers ? '' : 'beforeunload '}unload`;
|
|
185
|
+
const handleDisconnect = ev => {
|
|
186
|
+
// type-checking added as disconnect returns Promise<void> | boolean
|
|
187
|
+
const result = this.disconnect(ev);
|
|
188
|
+
if (result instanceof Promise) {
|
|
189
|
+
result.catch(() => {
|
|
190
|
+
// Ignore errors in order to not break the unload.
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
for (const event of events.split(' ')) {
|
|
195
|
+
window.addEventListener(event, handleDisconnect);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Initializes the list of feature advertised through the disco-info
|
|
200
|
+
* mechanism.
|
|
201
|
+
*/
|
|
202
|
+
initFeaturesList() {
|
|
203
|
+
// http://xmpp.org/extensions/xep-0167.html#support
|
|
204
|
+
// http://xmpp.org/extensions/xep-0176.html#support
|
|
205
|
+
this.caps.addFeature(XEP.JINGLE);
|
|
206
|
+
this.caps.addFeature(XEP.RTP_MEDIA);
|
|
207
|
+
this.caps.addFeature(XEP.ICE_UDP_TRANSPORT);
|
|
208
|
+
this.caps.addFeature(XEP.DTLS_SRTP);
|
|
209
|
+
this.caps.addFeature(XEP.SCTP_DATA_CHANNEL);
|
|
210
|
+
this.caps.addFeature(XEP.RTP_AUDIO);
|
|
211
|
+
this.caps.addFeature(XEP.RTP_VIDEO);
|
|
212
|
+
this.caps.addFeature('http://jitsi.org/json-encoded-sources');
|
|
213
|
+
if (!(this.options.disableRtx || !browser.supportsRTX())) {
|
|
214
|
+
this.caps.addFeature('urn:ietf:rfc:4588');
|
|
215
|
+
}
|
|
216
|
+
if (this.options.enableOpusRed === true && browser.supportsAudioRed()) {
|
|
217
|
+
this.caps.addFeature('http://jitsi.org/opus-red');
|
|
218
|
+
}
|
|
219
|
+
if (typeof this.options.enableRemb === 'undefined' || this.options.enableRemb) {
|
|
220
|
+
this.caps.addFeature('http://jitsi.org/remb');
|
|
221
|
+
}
|
|
222
|
+
// Disable TCC on Firefox 114 and older versions because of a known issue where BWE is halved on every
|
|
223
|
+
// renegotiation.
|
|
224
|
+
if (!(browser.isFirefox() && browser.isVersionLessThan(115))
|
|
225
|
+
&& (typeof this.options.enableTcc === 'undefined' || this.options.enableTcc)) {
|
|
226
|
+
this.caps.addFeature('http://jitsi.org/tcc');
|
|
227
|
+
}
|
|
228
|
+
if (this.connection.rayo) {
|
|
229
|
+
this.caps.addFeature('urn:xmpp:rayo:client:1');
|
|
230
|
+
}
|
|
231
|
+
if (E2EEncryption.isSupported(this.options)) {
|
|
232
|
+
this.caps.addFeature(FEATURE_E2EE, false, true);
|
|
233
|
+
}
|
|
234
|
+
// Advertise source-name signaling when the endpoint supports it.
|
|
235
|
+
logger.debug('Source-name signaling is enabled');
|
|
236
|
+
this.caps.addFeature('http://jitsi.org/source-name');
|
|
237
|
+
logger.debug('Receiving multiple video streams is enabled');
|
|
238
|
+
this.caps.addFeature('http://jitsi.org/receive-multiple-video-streams');
|
|
239
|
+
// Advertise support for ssrc-rewriting.
|
|
240
|
+
if (FeatureFlags.isSsrcRewritingSupported()) {
|
|
241
|
+
this.caps.addFeature('http://jitsi.org/ssrc-rewriting-1');
|
|
242
|
+
}
|
|
243
|
+
// Use "-1" as a version that we can bump later. This should match
|
|
244
|
+
// the version added in moderator.js, this one here is mostly defined
|
|
245
|
+
// for keeping stats, since it is not made available to jocofo at
|
|
246
|
+
// the time of the initial conference-request.
|
|
247
|
+
this.caps.addFeature('http://jitsi.org/visitors-1');
|
|
248
|
+
// Advertise support for startMuted policy through room metadata.
|
|
249
|
+
this.caps.addFeature('http://jitsi.org/start-muted-room-metadata');
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* A private message is received, message that is not addressed to the muc.
|
|
253
|
+
* We expect private message coming from plugins component if it is
|
|
254
|
+
* enabled and running.
|
|
255
|
+
*
|
|
256
|
+
* @param {string} msg - The message.
|
|
257
|
+
*/
|
|
258
|
+
_onPrivateMessage(msg) {
|
|
259
|
+
const from = msg.getAttribute('from');
|
|
260
|
+
if (!this._components.includes(from)) {
|
|
261
|
+
this._preComponentsMsgs.push(msg);
|
|
262
|
+
return true;
|
|
263
|
+
}
|
|
264
|
+
// Use *|xmlns to match xmlns attributes across any namespace (CSS Selectors Level 3)
|
|
265
|
+
const jsonMessage = getText(findFirst(msg, ':scope>json-message[*|xmlns="http://jitsi.org/jitmeet"]'));
|
|
266
|
+
const parsedJson = this.tryParseJSONAndVerify(jsonMessage);
|
|
267
|
+
if (!parsedJson || typeof parsedJson !== 'object') {
|
|
268
|
+
return true;
|
|
269
|
+
}
|
|
270
|
+
if (parsedJson[JITSI_MEET_MUC_TYPE] === 'speakerstats' && parsedJson.users) {
|
|
271
|
+
this.eventEmitter.emit(XMPPEvents.SPEAKER_STATS_RECEIVED, parsedJson.users);
|
|
272
|
+
}
|
|
273
|
+
else if (parsedJson[JITSI_MEET_MUC_TYPE] === 'av_moderation') {
|
|
274
|
+
this.eventEmitter.emit(XMPPEvents.AV_MODERATION_RECEIVED, parsedJson);
|
|
275
|
+
}
|
|
276
|
+
else if (parsedJson[JITSI_MEET_MUC_TYPE] === 'breakout_rooms') {
|
|
277
|
+
this.eventEmitter.emit(XMPPEvents.BREAKOUT_ROOMS_EVENT, parsedJson);
|
|
278
|
+
}
|
|
279
|
+
else if (parsedJson[JITSI_MEET_MUC_TYPE] === FILE_SHARING_IDENTITY_TYPE) {
|
|
280
|
+
this.eventEmitter.emit(XMPPEvents.FILE_SHARING_EVENT, parsedJson);
|
|
281
|
+
}
|
|
282
|
+
else if (parsedJson[JITSI_MEET_MUC_TYPE] === 'room_metadata') {
|
|
283
|
+
this.eventEmitter.emit(XMPPEvents.ROOM_METADATA_EVENT, parsedJson);
|
|
284
|
+
}
|
|
285
|
+
else if (parsedJson[JITSI_MEET_MUC_TYPE] === 'visitors') {
|
|
286
|
+
this.eventEmitter.emit(XMPPEvents.VISITORS_MESSAGE, parsedJson);
|
|
287
|
+
}
|
|
288
|
+
else if (parsedJson[JITSI_MEET_MUC_TYPE] === 'polls') {
|
|
289
|
+
this.eventEmitter.emit(XMPPEvents.POLLS_EVENT, parsedJson);
|
|
290
|
+
}
|
|
291
|
+
return true;
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Sends deployment info to stats if not sent already.
|
|
295
|
+
* We want to try sending it on failure to connect
|
|
296
|
+
* or when we get a sys message(from jiconop2)
|
|
297
|
+
* or after success or failure of disco-info
|
|
298
|
+
* @param force Whether to force sending without checking anything.
|
|
299
|
+
* @private
|
|
300
|
+
*/
|
|
301
|
+
_maybeSendDeploymentInfoStat(force = false) {
|
|
302
|
+
const acceptedStatuses = [
|
|
303
|
+
Strophe.Status.ERROR,
|
|
304
|
+
Strophe.Status.CONNFAIL,
|
|
305
|
+
Strophe.Status.AUTHFAIL,
|
|
306
|
+
Strophe.Status.DISCONNECTED,
|
|
307
|
+
Strophe.Status.CONNTIMEOUT
|
|
308
|
+
];
|
|
309
|
+
if (!force && !(acceptedStatuses.includes(this.connection.status) && this.sendDeploymentInfo)) {
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
// Log deployment-specific information, if available. Defined outside
|
|
313
|
+
// the application by individual deployments
|
|
314
|
+
const aprops = this.options.deploymentInfo;
|
|
315
|
+
if (Object.keys(aprops ?? {}).length > 0) {
|
|
316
|
+
const logObject = { id: undefined };
|
|
317
|
+
for (const attr in aprops) {
|
|
318
|
+
if (aprops.hasOwnProperty(attr)) {
|
|
319
|
+
logObject[attr] = aprops[attr];
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
// Let's push to analytics any updates that may have come from the backend
|
|
323
|
+
Statistics.analytics.addPermanentProperties({ ...logObject });
|
|
324
|
+
logObject.id = 'deployment_info';
|
|
325
|
+
const entry = JSON.stringify(logObject);
|
|
326
|
+
logger.info(entry);
|
|
327
|
+
}
|
|
328
|
+
this.sendDeploymentInfo = false;
|
|
329
|
+
const { region, shard } = aprops;
|
|
330
|
+
if (region || shard) {
|
|
331
|
+
// avoids sending empty values
|
|
332
|
+
this.eventEmitter.emit(JitsiConnectionEvents.PROPERTIES_UPDATED, cloneDeep({ region, shard }));
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* Process received identities.
|
|
337
|
+
* @param {Set<String>} identities The identities to process.
|
|
338
|
+
* @param {Set<String>} features The features to process, optional. If missing lobby component will be queried
|
|
339
|
+
* for more features.
|
|
340
|
+
* @private
|
|
341
|
+
*/
|
|
342
|
+
_processDiscoInfoIdentities(identities, features) {
|
|
343
|
+
// check for speakerstats
|
|
344
|
+
identities.forEach(identity => {
|
|
345
|
+
if (identity.type === 'av_moderation') {
|
|
346
|
+
this.avModerationComponentAddress = identity.name;
|
|
347
|
+
this._components.push(this.avModerationComponentAddress);
|
|
348
|
+
}
|
|
349
|
+
if (identity.type === 'end_conference') {
|
|
350
|
+
this.endConferenceComponentAddress = identity.name;
|
|
351
|
+
this._components.push(this.endConferenceComponentAddress);
|
|
352
|
+
}
|
|
353
|
+
if (identity.type === 'speakerstats') {
|
|
354
|
+
this.speakerStatsComponentAddress = identity.name;
|
|
355
|
+
this._components.push(this.speakerStatsComponentAddress);
|
|
356
|
+
}
|
|
357
|
+
if (identity.type === 'lobbyrooms') {
|
|
358
|
+
this.lobbySupported = true;
|
|
359
|
+
const processLobbyFeatures = f => {
|
|
360
|
+
f.forEach(fr => {
|
|
361
|
+
if (fr.endsWith('#displayname_required')) {
|
|
362
|
+
this.eventEmitter.emit(JitsiConnectionEvents.DISPLAY_NAME_REQUIRED);
|
|
363
|
+
}
|
|
364
|
+
});
|
|
365
|
+
};
|
|
366
|
+
if (features) {
|
|
367
|
+
processLobbyFeatures(features);
|
|
368
|
+
}
|
|
369
|
+
else {
|
|
370
|
+
identity.name && this.caps.getFeaturesAndIdentities(identity.name, identity.type)
|
|
371
|
+
.then(({ features: f }) => processLobbyFeatures(f))
|
|
372
|
+
.catch(e => logger.warn('Error getting features from lobby.', e?.message));
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
if (identity.type === 'shard') {
|
|
376
|
+
this.options.deploymentInfo.shard = this.connection.shard = identity.name;
|
|
377
|
+
}
|
|
378
|
+
if (identity.type === 'region') {
|
|
379
|
+
// @ts-ignore property 'region' does not exist on 'XmppConnection'
|
|
380
|
+
this.options.deploymentInfo.region = this.connection.region = identity.name;
|
|
381
|
+
}
|
|
382
|
+
if (identity.type === 'release') {
|
|
383
|
+
this.options.deploymentInfo.backendRelease = identity.name;
|
|
384
|
+
}
|
|
385
|
+
if (identity.type === 'breakout_rooms') {
|
|
386
|
+
this.breakoutRoomsComponentAddress = identity.name;
|
|
387
|
+
this._components.push(this.breakoutRoomsComponentAddress);
|
|
388
|
+
const processBreakoutRoomsFeatures = f => {
|
|
389
|
+
this.breakoutRoomsFeatures = {};
|
|
390
|
+
f.forEach(fr => {
|
|
391
|
+
if (fr.endsWith('#rename')) {
|
|
392
|
+
this.breakoutRoomsFeatures.rename = true;
|
|
393
|
+
}
|
|
394
|
+
});
|
|
395
|
+
};
|
|
396
|
+
if (features) {
|
|
397
|
+
processBreakoutRoomsFeatures(features);
|
|
398
|
+
}
|
|
399
|
+
else {
|
|
400
|
+
identity.name && this.caps.getFeaturesAndIdentities(identity.name, identity.type)
|
|
401
|
+
.then(({ features: f }) => processBreakoutRoomsFeatures(f))
|
|
402
|
+
.catch(e => logger.warn('Error getting features for breakout rooms.', e?.message));
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
if (identity.type === FILE_SHARING_IDENTITY_TYPE) {
|
|
406
|
+
this.fileSharingComponentAddress = identity.name;
|
|
407
|
+
this._components.push(this.fileSharingComponentAddress);
|
|
408
|
+
}
|
|
409
|
+
if (identity.type === 'room_metadata') {
|
|
410
|
+
this.roomMetadataComponentAddress = identity.name;
|
|
411
|
+
this._components.push(this.roomMetadataComponentAddress);
|
|
412
|
+
}
|
|
413
|
+
if (identity.type === 'visitors') {
|
|
414
|
+
this._components.push(identity.name);
|
|
415
|
+
}
|
|
416
|
+
if (identity.type === 'polls') {
|
|
417
|
+
this.pollsComponentAddress = identity.name;
|
|
418
|
+
this._components.push(this.pollsComponentAddress);
|
|
419
|
+
}
|
|
420
|
+
});
|
|
421
|
+
this._maybeSendDeploymentInfoStat(true);
|
|
422
|
+
if (this._components.length > 0) {
|
|
423
|
+
this._preComponentsMsgs.forEach(this._onPrivateMessage.bind(this));
|
|
424
|
+
}
|
|
425
|
+
this._preComponentsMsgs = [];
|
|
426
|
+
}
|
|
427
|
+
/**
|
|
428
|
+
* Parses a raw failure xmpp xml message received on auth failed.
|
|
429
|
+
*
|
|
430
|
+
* @param {string} msg - The raw failure message from xmpp.
|
|
431
|
+
* @returns {string|null} - The parsed message from the raw xmpp message.
|
|
432
|
+
*/
|
|
433
|
+
_parseConnectionFailedMessage(msg) {
|
|
434
|
+
if (!msg) {
|
|
435
|
+
return null;
|
|
436
|
+
}
|
|
437
|
+
FAILURE_REGEX.lastIndex = 0;
|
|
438
|
+
const matches = FAILURE_REGEX.exec(msg);
|
|
439
|
+
return matches ? matches[1] : null;
|
|
440
|
+
}
|
|
441
|
+
/**
|
|
442
|
+
*
|
|
443
|
+
* @param jid
|
|
444
|
+
* @param password
|
|
445
|
+
*/
|
|
446
|
+
_connect(jid, password) {
|
|
447
|
+
// connection.connect() starts the connection process.
|
|
448
|
+
//
|
|
449
|
+
// As the connection process proceeds, the user supplied callback will
|
|
450
|
+
// be triggered multiple times with status updates. The callback should
|
|
451
|
+
// take two arguments - the status code and the error condition.
|
|
452
|
+
//
|
|
453
|
+
// The status code will be one of the values in the Strophe.Status
|
|
454
|
+
// constants. The error condition will be one of the conditions defined
|
|
455
|
+
// in RFC 3920 or the condition ‘strophe-parsererror’.
|
|
456
|
+
//
|
|
457
|
+
// The Parameters wait, hold and route are optional and only relevant
|
|
458
|
+
// for BOSH connections. Please see XEP 124 for a more detailed
|
|
459
|
+
// explanation of the optional parameters.
|
|
460
|
+
//
|
|
461
|
+
// Connection status constants for use by the connection handler
|
|
462
|
+
// callback.
|
|
463
|
+
//
|
|
464
|
+
// Status.ERROR - An error has occurred (websockets specific)
|
|
465
|
+
// Status.CONNECTING - The connection is currently being made
|
|
466
|
+
// Status.CONNFAIL - The connection attempt failed
|
|
467
|
+
// Status.AUTHENTICATING - The connection is authenticating
|
|
468
|
+
// Status.AUTHFAIL - The authentication attempt failed
|
|
469
|
+
// Status.CONNECTED - The connection has succeeded
|
|
470
|
+
// Status.DISCONNECTED - The connection has been terminated
|
|
471
|
+
// Status.DISCONNECTING - The connection is currently being terminated
|
|
472
|
+
// Status.ATTACHED - The connection has been attached
|
|
473
|
+
this._resetState();
|
|
474
|
+
// we want to send this only on the initial connect
|
|
475
|
+
this.sendDiscoInfo = true;
|
|
476
|
+
this.sendDeploymentInfo = true;
|
|
477
|
+
if (this.connection._stropheConn?._addSysHandler) {
|
|
478
|
+
this._sysMessageHandler = this.connection._stropheConn._addSysHandler(this._onSystemMessage.bind(this), null, 'message');
|
|
479
|
+
}
|
|
480
|
+
else {
|
|
481
|
+
logger.warn('Cannot attach strophe system handler, jiconop cannot operate');
|
|
482
|
+
}
|
|
483
|
+
this.connection.connect(jid, password, this.connectionHandler.bind(this, {
|
|
484
|
+
jid,
|
|
485
|
+
password
|
|
486
|
+
}));
|
|
487
|
+
}
|
|
488
|
+
/**
|
|
489
|
+
* Receives system messages during the connect/login process and checks for services or
|
|
490
|
+
* @param msg The received message.
|
|
491
|
+
* @returns {void}
|
|
492
|
+
* @private
|
|
493
|
+
*/
|
|
494
|
+
_onSystemMessage(msg) {
|
|
495
|
+
// proceed only if the message has any of the expected information
|
|
496
|
+
if (!exists(msg, ':scope>services') && !exists(msg, ':scope>query')) {
|
|
497
|
+
return;
|
|
498
|
+
}
|
|
499
|
+
this.sendDiscoInfo = false;
|
|
500
|
+
const foundIceServers = this.connection.jingle.onReceiveStunAndTurnCredentials(msg) || false;
|
|
501
|
+
const { features, identities } = parseDiscoInfo(msg);
|
|
502
|
+
this._processDiscoInfoIdentities(identities, features);
|
|
503
|
+
if (foundIceServers || identities.size > 0 || features.size > 0) {
|
|
504
|
+
this.connection._stropheConn.deleteHandler(this._sysMessageHandler);
|
|
505
|
+
this._sysMessageHandler = null;
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
/**
|
|
509
|
+
* The method is supposed to gracefully close the XMPP connection and the main goal is to make sure that the current
|
|
510
|
+
* participant will be removed from the conference XMPP MUC, so that it doesn't leave a "ghost" participant behind.
|
|
511
|
+
*
|
|
512
|
+
* @param {Object} ev - Optionally, the event which triggered the necessity to disconnect from the XMPP server
|
|
513
|
+
* (e.g. beforeunload, unload).
|
|
514
|
+
* @private
|
|
515
|
+
* @returns {void}
|
|
516
|
+
*/
|
|
517
|
+
_cleanupXmppConnection(ev) {
|
|
518
|
+
// XXX Strophe is asynchronously sending by default. Unfortunately, that means that there may not be enough time
|
|
519
|
+
// to send an unavailable presence or disconnect at all. Switching Strophe to synchronous sending is not much of
|
|
520
|
+
// an option because it may lead to a noticeable delay in navigating away from the current location. As
|
|
521
|
+
// a compromise, we will try to increase the chances of sending an unavailable presence and/or disconnecting
|
|
522
|
+
// within the short time span that we have upon unloading by invoking flush() on the connection. We flush() once
|
|
523
|
+
// before disconnect() in order to attempt to have its unavailable presence at the top of the send queue. We
|
|
524
|
+
// flush() once more after disconnect() in order to attempt to have its unavailable presence sent as soon as
|
|
525
|
+
// possible.
|
|
526
|
+
!this.connection.isUsingWebSocket && this.connection.flush();
|
|
527
|
+
if (!this.connection.isUsingWebSocket && ev !== null && typeof ev !== 'undefined') {
|
|
528
|
+
const evType = ev.type;
|
|
529
|
+
if (evType === 'beforeunload' || evType === 'unload') {
|
|
530
|
+
// XXX Whatever we said above, synchronous sending is the best (known) way to properly disconnect from
|
|
531
|
+
// the XMPP server. Consequently, it may be fine to have the source code and comment it in or out
|
|
532
|
+
// depending on whether we want to run with it for some time.
|
|
533
|
+
this.connection.options.sync = true;
|
|
534
|
+
// This is needed in some browsers where sync xhr sending is disabled by default on unload.
|
|
535
|
+
if (this.connection.sendUnavailableBeacon()) {
|
|
536
|
+
return;
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
this.connection.disconnect();
|
|
541
|
+
this._startConnecting = false;
|
|
542
|
+
if (this.connection.options.sync !== true) {
|
|
543
|
+
this.connection.flush();
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
/**
|
|
547
|
+
*
|
|
548
|
+
*/
|
|
549
|
+
_initStrophePlugins() {
|
|
550
|
+
const iceConfig = {
|
|
551
|
+
jvb: { iceServers: [] },
|
|
552
|
+
p2p: { iceServers: [], iceTransportPolicy: undefined }
|
|
553
|
+
};
|
|
554
|
+
const p2pStunServers = (this.options.p2p?.stunServers) || DEFAULT_STUN_SERVERS;
|
|
555
|
+
if (Array.isArray(p2pStunServers)) {
|
|
556
|
+
logger.info('P2P STUN servers: ', p2pStunServers);
|
|
557
|
+
iceConfig.p2p.iceServers = p2pStunServers;
|
|
558
|
+
}
|
|
559
|
+
if (this.options.p2p?.iceTransportPolicy) {
|
|
560
|
+
logger.info('P2P ICE transport policy: ', this.options.p2p.iceTransportPolicy);
|
|
561
|
+
iceConfig.p2p.iceTransportPolicy
|
|
562
|
+
= this.options.p2p.iceTransportPolicy;
|
|
563
|
+
}
|
|
564
|
+
this.connection.addConnectionPlugin('emuc', new MucConnectionPlugin(this));
|
|
565
|
+
this.connection.addConnectionPlugin('jingle', new JingleConnectionPlugin(this, this.eventEmitter, iceConfig));
|
|
566
|
+
this.connection.addConnectionPlugin('rayo', new RayoConnectionPlugin());
|
|
567
|
+
}
|
|
568
|
+
/**
|
|
569
|
+
* Returns details about connection failure. Shard change or is it after
|
|
570
|
+
* suspend.
|
|
571
|
+
* @returns { IConnectionFailedReasonDetails} contains details about a connection failure.
|
|
572
|
+
* @private
|
|
573
|
+
*/
|
|
574
|
+
_getConnectionFailedReasonDetails() {
|
|
575
|
+
const details = {};
|
|
576
|
+
// check for moving between shard if information is available
|
|
577
|
+
if (this.options.deploymentInfo?.shard
|
|
578
|
+
&& this.connection.lastResponseHeaders) {
|
|
579
|
+
// split headers by line
|
|
580
|
+
const headersArr = this.connection.lastResponseHeaders
|
|
581
|
+
.trim().split(/[\r\n]+/);
|
|
582
|
+
const headers = {};
|
|
583
|
+
headersArr.forEach(line => {
|
|
584
|
+
const parts = line.split(': ');
|
|
585
|
+
const header = parts.shift();
|
|
586
|
+
const value = parts.join(': ');
|
|
587
|
+
headers[header] = value;
|
|
588
|
+
});
|
|
589
|
+
/* eslint-disable camelcase */
|
|
590
|
+
details.shard_changed
|
|
591
|
+
= this.options.deploymentInfo.shard
|
|
592
|
+
!== headers['x-jitsi-shard'];
|
|
593
|
+
/* eslint-enable camelcase */
|
|
594
|
+
}
|
|
595
|
+
/* eslint-disable camelcase */
|
|
596
|
+
// check for possible suspend
|
|
597
|
+
details.suspend_time = this.connection.ping.getPingSuspendTime();
|
|
598
|
+
details.time_since_last_success = this.connection.getTimeSinceLastSuccess();
|
|
599
|
+
/* eslint-enable camelcase */
|
|
600
|
+
return details;
|
|
601
|
+
}
|
|
602
|
+
/**
|
|
603
|
+
* Resets any state/flag before starting a new connection.
|
|
604
|
+
* @private
|
|
605
|
+
*/
|
|
606
|
+
_resetState() {
|
|
607
|
+
this._anonymousConnectionFailed = false;
|
|
608
|
+
this.connectionFailed = false;
|
|
609
|
+
this._lastErrorMsg = undefined;
|
|
610
|
+
this._disconnectInProgress = undefined;
|
|
611
|
+
this._wasDisconnected = false;
|
|
612
|
+
}
|
|
613
|
+
/**
|
|
614
|
+
* Returns the current XMPP connection instance.
|
|
615
|
+
*/
|
|
616
|
+
getConnection() {
|
|
617
|
+
return this.connection;
|
|
618
|
+
}
|
|
619
|
+
/**
|
|
620
|
+
* Receive connection status changes and handles them.
|
|
621
|
+
*
|
|
622
|
+
* @param {Object} credentials
|
|
623
|
+
* @param {string} credentials.jid - The user's XMPP ID passed to the
|
|
624
|
+
* connect method. For example, 'user@xmpp.com'.
|
|
625
|
+
* @param {string} credentials.password - The password passed to the connect
|
|
626
|
+
* method.
|
|
627
|
+
* @param {string} status - One of Strophe's connection status strings.
|
|
628
|
+
* @param {string} [msg] - The connection error message provided by Strophe.
|
|
629
|
+
*/
|
|
630
|
+
connectionHandler(credentials = {}, status, msg) {
|
|
631
|
+
const now = window.performance.now();
|
|
632
|
+
const statusStr = Strophe.getStatusString(status).toLowerCase();
|
|
633
|
+
this.connectionTimes[statusStr] = now;
|
|
634
|
+
logger.info(`(TIME) Strophe ${statusStr}${msg ? `[${msg}]` : ''}:\t`, now);
|
|
635
|
+
this.eventEmitter.emit(XMPPEvents.CONNECTION_STATUS_CHANGED, credentials, status, msg);
|
|
636
|
+
this._maybeSendDeploymentInfoStat();
|
|
637
|
+
if (status === Strophe.Status.CONNECTED || status === Strophe.Status.ATTACHED) {
|
|
638
|
+
// once connected or attached we no longer need this handle, drop it if it exist
|
|
639
|
+
if (this._sysMessageHandler) {
|
|
640
|
+
this.connection._stropheConn.deleteHandler(this._sysMessageHandler);
|
|
641
|
+
this._sysMessageHandler = null;
|
|
642
|
+
}
|
|
643
|
+
this.sendDiscoInfo && this.connection.jingle.getStunAndTurnCredentials();
|
|
644
|
+
logger.info(`My Jabber ID: ${this.connection.jid}`);
|
|
645
|
+
this._wasDisconnected && RTCStats.sendStatsEntry(RTCStatsEvents.STROPHE_RECONNECTED_EVENT);
|
|
646
|
+
// XmppConnection emits CONNECTED again on reconnect - a good opportunity to clear any "last error" flags
|
|
647
|
+
this._resetState();
|
|
648
|
+
// make sure we will send the info after the features request succeeds or fails
|
|
649
|
+
this.sendDeploymentInfo = false;
|
|
650
|
+
this.sendDiscoInfo && this.caps.getFeaturesAndIdentities(this.options.hosts.domain, undefined)
|
|
651
|
+
.then(({ features, identities }) => {
|
|
652
|
+
if (!features.has(Strophe.NS.PING)) {
|
|
653
|
+
logger.error(`Ping NOT supported by ${this.options.hosts.domain} - please enable ping in your XMPP server config`);
|
|
654
|
+
}
|
|
655
|
+
this._processDiscoInfoIdentities(identities, undefined /* when querying we will query for features */);
|
|
656
|
+
})
|
|
657
|
+
.catch(error => {
|
|
658
|
+
logger.error('Feature discovery error', error);
|
|
659
|
+
this._maybeSendDeploymentInfoStat(true);
|
|
660
|
+
});
|
|
661
|
+
// make sure we don't query again
|
|
662
|
+
this.sendDiscoInfo = false;
|
|
663
|
+
if (credentials.password) {
|
|
664
|
+
this.authenticatedUser = true;
|
|
665
|
+
}
|
|
666
|
+
if (this.connection && this.connection.connected
|
|
667
|
+
&& Strophe.getResourceFromJid(this.connection.jid)) {
|
|
668
|
+
// .connected is true while connecting?
|
|
669
|
+
// this.connection.send($pres());
|
|
670
|
+
this.eventEmitter.emit(JitsiConnectionEvents.CONNECTION_ESTABLISHED, Strophe.getResourceFromJid(this.connection.jid));
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
else if (status === Strophe.Status.CONNFAIL) {
|
|
674
|
+
if (msg === 'x-strophe-bad-non-anon-jid') {
|
|
675
|
+
this._anonymousConnectionFailed = true;
|
|
676
|
+
}
|
|
677
|
+
else {
|
|
678
|
+
this.connectionFailed = true;
|
|
679
|
+
}
|
|
680
|
+
this._lastErrorMsg = msg;
|
|
681
|
+
if (msg === 'giving-up') {
|
|
682
|
+
this.eventEmitter.emit(JitsiConnectionEvents.CONNECTION_FAILED, JitsiConnectionErrors.OTHER_ERROR, msg);
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
else if (status === Strophe.Status.ERROR) {
|
|
686
|
+
this._lastErrorMsg = msg;
|
|
687
|
+
}
|
|
688
|
+
else if (status === Strophe.Status.DISCONNECTED) {
|
|
689
|
+
RTCStats.sendStatsEntry(RTCStatsEvents.STROPHE_DISCONNECTED_EVENT);
|
|
690
|
+
this._wasDisconnected = true;
|
|
691
|
+
// Stop ping interval
|
|
692
|
+
this.connection.ping.stopInterval();
|
|
693
|
+
const wasIntentionalDisconnect = Boolean(this._disconnectInProgress);
|
|
694
|
+
const errMsg = msg || this._lastErrorMsg;
|
|
695
|
+
if (this._anonymousConnectionFailed) {
|
|
696
|
+
// prompt user for username and password
|
|
697
|
+
this.eventEmitter.emit(JitsiConnectionEvents.CONNECTION_FAILED, JitsiConnectionErrors.PASSWORD_REQUIRED);
|
|
698
|
+
}
|
|
699
|
+
else if (this.connectionFailed) {
|
|
700
|
+
this.eventEmitter.emit(JitsiConnectionEvents.CONNECTION_FAILED, JitsiConnectionErrors.OTHER_ERROR, errMsg, undefined, /* credentials */ this._getConnectionFailedReasonDetails());
|
|
701
|
+
}
|
|
702
|
+
else if (wasIntentionalDisconnect) {
|
|
703
|
+
this.eventEmitter.emit(JitsiConnectionEvents.CONNECTION_DISCONNECTED, errMsg);
|
|
704
|
+
}
|
|
705
|
+
else {
|
|
706
|
+
// XXX if Strophe drops the connection while not being asked to,
|
|
707
|
+
// it means that most likely some serious error has occurred.
|
|
708
|
+
// One currently known case is when a BOSH request fails for
|
|
709
|
+
// more than 4 times. The connection is dropped without
|
|
710
|
+
// supplying a reason(error message/event) through the API.
|
|
711
|
+
logger.error('XMPP connection dropped!');
|
|
712
|
+
// XXX if the last request error is within 5xx range it means it
|
|
713
|
+
// was a server failure
|
|
714
|
+
const lastErrorStatus = Strophe.getLastErrorStatus();
|
|
715
|
+
if (lastErrorStatus >= 500 && lastErrorStatus < 600) {
|
|
716
|
+
this.eventEmitter.emit(JitsiConnectionEvents.CONNECTION_FAILED, JitsiConnectionErrors.SERVER_ERROR, errMsg || 'server-error',
|
|
717
|
+
/* credentials */ undefined, this._getConnectionFailedReasonDetails());
|
|
718
|
+
}
|
|
719
|
+
else {
|
|
720
|
+
this.eventEmitter.emit(JitsiConnectionEvents.CONNECTION_FAILED, JitsiConnectionErrors.CONNECTION_DROPPED_ERROR, errMsg || 'connection-dropped-error',
|
|
721
|
+
/* credentials */ undefined, this._getConnectionFailedReasonDetails());
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
else if (status === Strophe.Status.AUTHFAIL) {
|
|
726
|
+
const lastFailedRawMessage = this.getConnection().getLastFailedMessage();
|
|
727
|
+
// wrong password or username, prompt user
|
|
728
|
+
this.eventEmitter.emit(JitsiConnectionEvents.CONNECTION_FAILED, JitsiConnectionErrors.PASSWORD_REQUIRED, msg || this._parseConnectionFailedMessage(lastFailedRawMessage), credentials);
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
/**
|
|
732
|
+
* Attach to existing connection. Can be used for optimizations. For
|
|
733
|
+
* example: if the connection is created on the server we can attach to it
|
|
734
|
+
* and start using it.
|
|
735
|
+
*
|
|
736
|
+
* @param options {object} connecting options - rid, sid, jid and password.
|
|
737
|
+
*/
|
|
738
|
+
attach(options) {
|
|
739
|
+
this._resetState();
|
|
740
|
+
// we want to send this only on the initial connect
|
|
741
|
+
this.sendDiscoInfo = true;
|
|
742
|
+
const now = this.connectionTimes.attaching = window.performance.now();
|
|
743
|
+
logger.info('(TIME) Strophe Attaching:\t', now);
|
|
744
|
+
this.connection.attach(options.jid, options.sid, (Number.parseInt(options.rid, 10) + 1).toString(), this.connectionHandler.bind(this, {
|
|
745
|
+
jid: options.jid,
|
|
746
|
+
password: options.password
|
|
747
|
+
}));
|
|
748
|
+
}
|
|
749
|
+
/**
|
|
750
|
+
*
|
|
751
|
+
* @param jid
|
|
752
|
+
* @param password
|
|
753
|
+
*/
|
|
754
|
+
connect(jid, password) {
|
|
755
|
+
if (!jid) {
|
|
756
|
+
const { anonymousdomain, domain } = this.options.hosts;
|
|
757
|
+
let configDomain = anonymousdomain || domain;
|
|
758
|
+
// Force authenticated domain if room is appended with '?login=true'
|
|
759
|
+
// or if we're joining with the token
|
|
760
|
+
// FIXME Do not rely on window.location because (1) React Native
|
|
761
|
+
// does not have a window.location by default and (2) here we cannot
|
|
762
|
+
// know for sure that query/search has not be stripped from
|
|
763
|
+
// window.location by the time the following executes.
|
|
764
|
+
const { location } = window;
|
|
765
|
+
if (anonymousdomain) {
|
|
766
|
+
const search = location?.search;
|
|
767
|
+
if ((search && search.indexOf('login=true') !== -1)
|
|
768
|
+
|| this.token) {
|
|
769
|
+
configDomain = domain;
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
// eslint-disable-next-line no-param-reassign
|
|
773
|
+
jid = configDomain || (location?.hostname);
|
|
774
|
+
}
|
|
775
|
+
this._startConnecting = true;
|
|
776
|
+
return this._connect(jid, password);
|
|
777
|
+
}
|
|
778
|
+
/**
|
|
779
|
+
* Joins or creates a muc with the provided jid, created from the passed
|
|
780
|
+
* in room name and muc host and onCreateResource result.
|
|
781
|
+
*
|
|
782
|
+
* @param {string} roomName - The name of the muc to join.
|
|
783
|
+
* @param {Object} options - Configuration for how to join the muc.
|
|
784
|
+
* @param {Function} [onCreateResource] - Callback to invoke when a resource
|
|
785
|
+
* is to be added to the jid.
|
|
786
|
+
* @returns {ChatRoom} Resolves with an instance of a strophe muc.
|
|
787
|
+
*/
|
|
788
|
+
createRoom(roomName, options, onCreateResource) {
|
|
789
|
+
// Support passing the domain in a String object as part of the room name.
|
|
790
|
+
const domain = roomName.domain || options.customDomain;
|
|
791
|
+
// There are cases (when using subdomain) where muc can hold an uppercase part
|
|
792
|
+
let roomjid = `${this.getRoomJid(roomName, domain)}/`;
|
|
793
|
+
const mucNickname = onCreateResource
|
|
794
|
+
? onCreateResource(this.connection.jid, this.authenticatedUser)
|
|
795
|
+
: RandomUtil.randomHexString(8).toLowerCase();
|
|
796
|
+
logger.info(`JID ${this.connection.jid} using MUC nickname ${mucNickname}`);
|
|
797
|
+
roomjid += mucNickname;
|
|
798
|
+
return this.connection.emuc?.createRoom?.(roomjid, null, options);
|
|
799
|
+
}
|
|
800
|
+
/**
|
|
801
|
+
* Returns the room JID based on the passed room name and domain.
|
|
802
|
+
*
|
|
803
|
+
* @param {string} roomName - The room name.
|
|
804
|
+
* @param {string} domain - The domain.
|
|
805
|
+
* @returns {string} - The room JID.
|
|
806
|
+
*/
|
|
807
|
+
getRoomJid(roomName, domain) {
|
|
808
|
+
return `${roomName}@${domain ? domain : this.options.hosts.muc.toLowerCase()}`;
|
|
809
|
+
}
|
|
810
|
+
/**
|
|
811
|
+
* Check if a room with the passed JID is already created.
|
|
812
|
+
*
|
|
813
|
+
* @param {string} roomJid - The JID of the room.
|
|
814
|
+
* @returns {boolean}
|
|
815
|
+
*/
|
|
816
|
+
isRoomCreated(roomName, domain) {
|
|
817
|
+
return this.connection.emuc?.isRoomCreated?.(this.getRoomJid(roomName, domain)) || false;
|
|
818
|
+
}
|
|
819
|
+
/**
|
|
820
|
+
* Returns the jid of the participant associated with the Strophe connection.
|
|
821
|
+
*
|
|
822
|
+
* @returns {string} The jid of the participant.
|
|
823
|
+
*/
|
|
824
|
+
getJid() {
|
|
825
|
+
return this.connection.jid;
|
|
826
|
+
}
|
|
827
|
+
/**
|
|
828
|
+
* Returns the logs from strophe.jingle.
|
|
829
|
+
* @returns {Record<string, unknown>} - The jingle logs.
|
|
830
|
+
*/
|
|
831
|
+
getJingleLog() {
|
|
832
|
+
const jingle = this.connection.jingle;
|
|
833
|
+
return jingle ? jingle.getLog() : { metadata: {} };
|
|
834
|
+
}
|
|
835
|
+
/**
|
|
836
|
+
* Returns the logs from strophe.
|
|
837
|
+
*/
|
|
838
|
+
getXmppLog() {
|
|
839
|
+
return this.connection.logger?.log || null;
|
|
840
|
+
}
|
|
841
|
+
/**
|
|
842
|
+
*
|
|
843
|
+
*/
|
|
844
|
+
dial(...args) {
|
|
845
|
+
return this.connection.rayo?.dial(...args);
|
|
846
|
+
}
|
|
847
|
+
/**
|
|
848
|
+
* Pings the server.
|
|
849
|
+
* @param timeout how many ms before a timeout should occur.
|
|
850
|
+
* @returns {Promise} resolved on ping success and reject on an error or
|
|
851
|
+
* a timeout.
|
|
852
|
+
*/
|
|
853
|
+
ping(timeout) {
|
|
854
|
+
return new Promise((resolve, reject) => {
|
|
855
|
+
this.connection.ping.ping(this.connection.pingDomain, resolve, reject, timeout);
|
|
856
|
+
});
|
|
857
|
+
}
|
|
858
|
+
/**
|
|
859
|
+
*
|
|
860
|
+
*/
|
|
861
|
+
getSessions() {
|
|
862
|
+
return this.connection.jingle.sessions;
|
|
863
|
+
}
|
|
864
|
+
/**
|
|
865
|
+
* Disconnects this from the XMPP server (if this is connected).
|
|
866
|
+
*
|
|
867
|
+
* @param {Object} ev - Optionally, the event which triggered the necessity to
|
|
868
|
+
* disconnect from the XMPP server (e.g. beforeunload, unload).
|
|
869
|
+
* @returns {Promise} - Resolves when the disconnect process is finished or rejects with an error.
|
|
870
|
+
*/
|
|
871
|
+
disconnect(ev = undefined) {
|
|
872
|
+
logger.info(`XMPP disconnect triggered by the event=${ev?.type}`);
|
|
873
|
+
if (this._disconnectInProgress) {
|
|
874
|
+
return this._disconnectInProgress;
|
|
875
|
+
}
|
|
876
|
+
else if (!this.connection || !this._startConnecting) {
|
|
877
|
+
// we have created a connection, but never called connect we still want to resolve on calling disconnect
|
|
878
|
+
// this is visitors use case when using http to send conference request.
|
|
879
|
+
return Promise.resolve();
|
|
880
|
+
}
|
|
881
|
+
this._disconnectInProgress = new Promise(resolve => {
|
|
882
|
+
const disconnectListener = (credentials, status) => {
|
|
883
|
+
if (status === Strophe.Status.DISCONNECTED) {
|
|
884
|
+
this.eventEmitter.removeListener(XMPPEvents.CONNECTION_STATUS_CHANGED, disconnectListener);
|
|
885
|
+
resolve();
|
|
886
|
+
}
|
|
887
|
+
};
|
|
888
|
+
this.eventEmitter.on(XMPPEvents.CONNECTION_STATUS_CHANGED, disconnectListener);
|
|
889
|
+
});
|
|
890
|
+
this._cleanupXmppConnection(ev);
|
|
891
|
+
return this._disconnectInProgress;
|
|
892
|
+
}
|
|
893
|
+
/**
|
|
894
|
+
* Notifies speaker stats component if available that we are the new
|
|
895
|
+
* dominant speaker in the conference.
|
|
896
|
+
* @param {String} roomJid - The room jid where the speaker event occurred.
|
|
897
|
+
* @param {boolean} silence - Whether the dominant speaker is silent or not.
|
|
898
|
+
*/
|
|
899
|
+
sendDominantSpeakerEvent(roomJid, silence) {
|
|
900
|
+
// no speaker stats component advertised
|
|
901
|
+
if (!this.speakerStatsComponentAddress || !roomJid) {
|
|
902
|
+
return;
|
|
903
|
+
}
|
|
904
|
+
const msg = $msg({ to: this.speakerStatsComponentAddress });
|
|
905
|
+
msg.c('speakerstats', {
|
|
906
|
+
room: roomJid,
|
|
907
|
+
silence,
|
|
908
|
+
xmlns: 'http://jitsi.org/jitmeet'
|
|
909
|
+
}).up();
|
|
910
|
+
this.connection.send(msg);
|
|
911
|
+
}
|
|
912
|
+
/**
|
|
913
|
+
* Sends face landmarks to speaker stats component.
|
|
914
|
+
* @param {String} roomJid - The room jid where the speaker event occurred.
|
|
915
|
+
* @param {Object} payload - The expression to be sent to the speaker stats.
|
|
916
|
+
*/
|
|
917
|
+
sendFaceLandmarksEvent(roomJid, payload) {
|
|
918
|
+
// no speaker stats component advertised
|
|
919
|
+
if (!this.speakerStatsComponentAddress || !roomJid) {
|
|
920
|
+
return;
|
|
921
|
+
}
|
|
922
|
+
const msg = $msg({ to: this.speakerStatsComponentAddress });
|
|
923
|
+
msg.c('faceLandmarks', {
|
|
924
|
+
duration: payload.duration,
|
|
925
|
+
faceExpression: payload.faceExpression,
|
|
926
|
+
room: roomJid,
|
|
927
|
+
timestamp: payload.timestamp,
|
|
928
|
+
xmlns: 'http://jitsi.org/jitmeet'
|
|
929
|
+
}).up();
|
|
930
|
+
this.connection.send(msg);
|
|
931
|
+
}
|
|
932
|
+
/**
|
|
933
|
+
* Check if the given argument is a valid JSON ENDPOINT_MESSAGE string by
|
|
934
|
+
* parsing it and checking if it has a field called 'type'.
|
|
935
|
+
*
|
|
936
|
+
* @param {string} jsonString check if this string is a valid json string
|
|
937
|
+
* and contains the special structure.
|
|
938
|
+
* @returns {boolean, object} if given object is a valid JSON string, return
|
|
939
|
+
* the json object. Otherwise, returns false.
|
|
940
|
+
*/
|
|
941
|
+
tryParseJSONAndVerify(jsonString) {
|
|
942
|
+
// ignore empty strings, like message errors
|
|
943
|
+
if (!jsonString) {
|
|
944
|
+
return false;
|
|
945
|
+
}
|
|
946
|
+
try {
|
|
947
|
+
// Note: we use `unescape` to also convert HTML entities to UTF-8 since
|
|
948
|
+
// Jigasi seems to encode them like that in some circumstances.
|
|
949
|
+
const json = safeJsonParse(unescape(jsonString));
|
|
950
|
+
// Handle non-exception-throwing cases:
|
|
951
|
+
// Neither JSON.parse(false) or JSON.parse(1234) throw errors,
|
|
952
|
+
// hence the type-checking,
|
|
953
|
+
// but... JSON.parse(null) returns null, and
|
|
954
|
+
// typeof null === "object",
|
|
955
|
+
// so we must check for that, too.
|
|
956
|
+
// Thankfully, null is falsey, so this suffices:
|
|
957
|
+
if (json && typeof json === 'object') {
|
|
958
|
+
const type = json[JITSI_MEET_MUC_TYPE];
|
|
959
|
+
if (typeof type !== 'undefined') {
|
|
960
|
+
return json;
|
|
961
|
+
}
|
|
962
|
+
logger.debug('parsing valid json but does not have correct '
|
|
963
|
+
+ 'structure', 'topic: ', type);
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
catch (e) {
|
|
967
|
+
logger.error(`Error parsing json ${jsonString}`, e);
|
|
968
|
+
return false;
|
|
969
|
+
}
|
|
970
|
+
return false;
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
//# sourceMappingURL=xmpp.js.map
|