diff --git a/bigbluebutton-html5/client/compatibility/kurento-extension.js b/bigbluebutton-html5/client/compatibility/kurento-extension.js index 4ca52d78a9..2229844ae4 100644 --- a/bigbluebutton-html5/client/compatibility/kurento-extension.js +++ b/bigbluebutton-html5/client/compatibility/kurento-extension.js @@ -108,34 +108,37 @@ KurentoManager.prototype.exitScreenShare = function () { this.kurentoScreenshare.dispose(); this.kurentoScreenshare = null; } - - if (typeof this.kurentoVideo !== 'undefined' && this.kurentoVideo) { - this.exitVideo(); - } }; KurentoManager.prototype.exitVideo = function () { - if (typeof this.kurentoVideo !== 'undefined' && this.kurentoVideo) { + try { + if (typeof this.kurentoVideo !== 'undefined' && this.kurentoVideo) { + if(this.kurentoVideo.webRtcPeer) { + this.kurentoVideo.webRtcPeer.peerConnection.oniceconnectionstatechange = null; + } - if(this.kurentoVideo.webRtcPeer) { - this.kurentoVideo.webRtcPeer.peerConnection.oniceconnectionstatechange = null; + if (this.kurentoVideo.logger !== null) { + this.kurentoVideo.logger.info(' [exitScreenShare] Exiting screensharing viewing'); + } + + if (this.kurentoVideo.ws !== null) { + this.kurentoVideo.ws.onclose = function () {}; + this.kurentoVideo.ws.close(); + } + + if (this.kurentoVideo.pingInterval) { + clearInterval(this.kurentoVideo.pingInterval); + } + + this.kurentoVideo.dispose(); + this.kurentoVideo = null; } - - if (this.kurentoVideo.logger !== null) { - this.kurentoVideo.logger.info(' [exitScreenShare] Exiting screensharing viewing'); + } + catch (err) { + if (this.kurentoVideo) { + this.kurentoVideo.dispose(); + this.kurentoVideo = null; } - - if (this.kurentoVideo.ws !== null) { - this.kurentoVideo.ws.onclose = function () {}; - this.kurentoVideo.ws.close(); - } - - if (this.kurentoVideo.pingInterval) { - clearInterval(this.kurentoVideo.pingInterval); - } - - this.kurentoVideo.dispose(); - this.kurentoVideo = null; } }; diff --git a/labs/bbb-webrtc-sfu/lib/base/BaseManager.js b/labs/bbb-webrtc-sfu/lib/base/BaseManager.js index 9e7320b2a0..8a88e671fc 100644 --- a/labs/bbb-webrtc-sfu/lib/base/BaseManager.js +++ b/labs/bbb-webrtc-sfu/lib/base/BaseManager.js @@ -137,7 +137,7 @@ module.exports = class BaseManager { } _handleError (logPrefix, connectionId, streamId, role, error) { - if (this._validateErrorMessage(error)) { + if (error && this._validateErrorMessage(error)) { return error; } diff --git a/labs/bbb-webrtc-sfu/lib/bbb/messages/Constants.js b/labs/bbb-webrtc-sfu/lib/bbb/messages/Constants.js index f2d481dcf2..038a0c01dd 100644 --- a/labs/bbb-webrtc-sfu/lib/bbb/messages/Constants.js +++ b/labs/bbb-webrtc-sfu/lib/bbb/messages/Constants.js @@ -69,10 +69,9 @@ const config = require('config'); STOP_TRANSCODER_RESP_2x: "StopTranscoderSysRespMsg", GLOBAL_AUDIO_CONNECTED_2x: "UserConnectedToGlobalAudioMsg", GLOBAL_AUDIO_DISCONNECTED_2x: "UserDisconnectedFromGlobalAudioMsg", - // TODO: Check if this is the correct message in BBB 2.x DICONNECT_ALL_USERS_2x: "DisconnectAllClientsSysMsg", - USER_CAM_BROADCAST_STOPPED_2x: "UserBroadcastCamStopMsg", + PRESENTER_ASSIGNED_2x: "PresenterAssignedEvtMsg", STREAM_IS_RECORDED: "StreamIsRecordedMsg", diff --git a/labs/bbb-webrtc-sfu/lib/bbb/pubsub/bbb-gw.js b/labs/bbb-webrtc-sfu/lib/bbb/pubsub/bbb-gw.js index f55ba1153d..bf6c4d062f 100644 --- a/labs/bbb-webrtc-sfu/lib/bbb/pubsub/bbb-gw.js +++ b/labs/bbb-webrtc-sfu/lib/bbb/pubsub/bbb-gw.js @@ -105,6 +105,11 @@ module.exports = class BigBlueButtonGW extends EventEmitter { payload[C.MEETING_ID_2x] = header[C.MEETING_ID_2x]; this.emit(C.DICONNECT_ALL_USERS_2x, payload); break; + case C.PRESENTER_ASSIGNED_2x: + meetingId = header[C.MEETING_ID_2x]; + payload[C.MEETING_ID_2x] = meetingId; + this.emit(C.PRESENTER_ASSIGNED_2x+meetingId, payload); + break; default: this.emit(C.GATEWAY_MESSAGE, msg); } diff --git a/labs/bbb-webrtc-sfu/lib/connection-manager/WebsocketConnectionManager.js b/labs/bbb-webrtc-sfu/lib/connection-manager/WebsocketConnectionManager.js index dafc004073..b0fbcc3ae7 100644 --- a/labs/bbb-webrtc-sfu/lib/connection-manager/WebsocketConnectionManager.js +++ b/labs/bbb-webrtc-sfu/lib/connection-manager/WebsocketConnectionManager.js @@ -29,7 +29,15 @@ module.exports = class WebsocketConnectionManager { const connectionId = data? data.connectionId : null; const ws = this.webSockets[connectionId]; if (ws) { - this.sendMessage(ws, data); + if (data.id === 'close') { + try { + ws.close(); + } catch (err) { + Logger.warn('[WebsocketConnectionManager] Error on closing WS for', connectionId, err) + } + } else { + this.sendMessage(ws, data); + } } } diff --git a/labs/bbb-webrtc-sfu/lib/screenshare/ScreenshareManager.js b/labs/bbb-webrtc-sfu/lib/screenshare/ScreenshareManager.js index f98c989838..0b42746094 100644 --- a/labs/bbb-webrtc-sfu/lib/screenshare/ScreenshareManager.js +++ b/labs/bbb-webrtc-sfu/lib/screenshare/ScreenshareManager.js @@ -70,6 +70,19 @@ module.exports = class ScreenshareManager extends BaseManager { this._stopSession(sessionId); }); + // listen for presenter change to avoid inconsistent states on reconnection + if (role === C.SEND_ROLE) { + this._bbbGW.once(C.PRESENTER_ASSIGNED_2x+message.internalMeetingId, async (payload) => { + Logger.info(this._logPrefix, "Presenter changed, forcibly closing screensharing session at", message.internalMeetingId); + await this.closeSession(session, connectionId, role, sessionId); + this._bbbGW.publish(JSON.stringify({ + connectionId: connectionId, + type: C.SCREENSHARE_APP, + id : 'close', + }), C.FROM_SCREENSHARE); + }); + } + Logger.info(this._logPrefix, "Sending startResponse to peer", sessionId, "for connection", session._id); } catch (error) { @@ -101,17 +114,7 @@ module.exports = class ScreenshareManager extends BaseManager { case 'close': Logger.info(this._logPrefix, 'Connection ' + connectionId + ' closed'); - - if (session && session.constructor == Screenshare) { - if (role === C.SEND_ROLE && session) { - Logger.info(this._logPrefix, "Stopping presenter " + sessionId); - this._stopSession(sessionId); - } - if (role === C.RECV_ROLE && session) { - Logger.info(this._logPrefix, "Stopping viewer " + sessionId); - session.stopViewer(message.connectionId); - } - } + this.closeSession(session, connectionId, role, sessionId); break; default: @@ -122,4 +125,18 @@ module.exports = class ScreenshareManager extends BaseManager { break; } } + + async closeSession (session, connectionId, role, sessionId) { + if (session && session.constructor == Screenshare) { + if (role === C.SEND_ROLE && session) { + Logger.info(this._logPrefix, "Stopping presenter " + sessionId); + await this._stopSession(sessionId); + return; + } + if (role === C.RECV_ROLE && session) { + Logger.info(this._logPrefix, "Stopping viewer " + sessionId); + await session.stopViewer(connectionId); + } + } + } }; diff --git a/labs/bbb-webrtc-sfu/lib/screenshare/screenshare.js b/labs/bbb-webrtc-sfu/lib/screenshare/screenshare.js index aeab9fc3af..bfb22a0208 100644 --- a/labs/bbb-webrtc-sfu/lib/screenshare/screenshare.js +++ b/labs/bbb-webrtc-sfu/lib/screenshare/screenshare.js @@ -227,6 +227,8 @@ module.exports = class Screenshare extends BaseProvider { start (sessionId, connectionId, sdpOffer, userId, role) { return new Promise(async (resolve, reject) => { + this._status = C.MEDIA_STARTING; + // Forces H264 with a possible preferred profile if (FORCE_H264) { sdpOffer = h264_sdp.transform(sdpOffer, PREFERRED_H264_PROFILE); @@ -347,6 +349,9 @@ module.exports = class Screenshare extends BaseProvider { stop () { return new Promise(async (resolve, reject) => { try { + if (this._status === C.MEDIA_STOPPED) { + return resolve(); + } Logger.info('[screnshare] Stopping and releasing endpoints for MCS user', this.mcsUserId); await this._stopScreensharing(); this._status = C.MEDIA_STOPPED;