Merge pull request #6058 from prlanzarin/screenshare-fix-presenter-switch

Fix screenshare edge case with presenter switch
This commit is contained in:
Anton Georgiev 2018-09-12 14:57:35 -04:00 committed by GitHub
commit 10ae980fd4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 74 additions and 37 deletions

View File

@ -108,15 +108,11 @@ KurentoManager.prototype.exitScreenShare = function () {
this.kurentoScreenshare.dispose(); this.kurentoScreenshare.dispose();
this.kurentoScreenshare = null; this.kurentoScreenshare = null;
} }
if (typeof this.kurentoVideo !== 'undefined' && this.kurentoVideo) {
this.exitVideo();
}
}; };
KurentoManager.prototype.exitVideo = function () { KurentoManager.prototype.exitVideo = function () {
try {
if (typeof this.kurentoVideo !== 'undefined' && this.kurentoVideo) { if (typeof this.kurentoVideo !== 'undefined' && this.kurentoVideo) {
if(this.kurentoVideo.webRtcPeer) { if(this.kurentoVideo.webRtcPeer) {
this.kurentoVideo.webRtcPeer.peerConnection.oniceconnectionstatechange = null; this.kurentoVideo.webRtcPeer.peerConnection.oniceconnectionstatechange = null;
} }
@ -137,6 +133,13 @@ KurentoManager.prototype.exitVideo = function () {
this.kurentoVideo.dispose(); this.kurentoVideo.dispose();
this.kurentoVideo = null; this.kurentoVideo = null;
} }
}
catch (err) {
if (this.kurentoVideo) {
this.kurentoVideo.dispose();
this.kurentoVideo = null;
}
}
}; };
KurentoManager.prototype.exitAudio = function () { KurentoManager.prototype.exitAudio = function () {

View File

@ -137,7 +137,7 @@ module.exports = class BaseManager {
} }
_handleError (logPrefix, connectionId, streamId, role, error) { _handleError (logPrefix, connectionId, streamId, role, error) {
if (this._validateErrorMessage(error)) { if (error && this._validateErrorMessage(error)) {
return error; return error;
} }

View File

@ -69,10 +69,9 @@ const config = require('config');
STOP_TRANSCODER_RESP_2x: "StopTranscoderSysRespMsg", STOP_TRANSCODER_RESP_2x: "StopTranscoderSysRespMsg",
GLOBAL_AUDIO_CONNECTED_2x: "UserConnectedToGlobalAudioMsg", GLOBAL_AUDIO_CONNECTED_2x: "UserConnectedToGlobalAudioMsg",
GLOBAL_AUDIO_DISCONNECTED_2x: "UserDisconnectedFromGlobalAudioMsg", GLOBAL_AUDIO_DISCONNECTED_2x: "UserDisconnectedFromGlobalAudioMsg",
// TODO: Check if this is the correct message in BBB 2.x
DICONNECT_ALL_USERS_2x: "DisconnectAllClientsSysMsg", DICONNECT_ALL_USERS_2x: "DisconnectAllClientsSysMsg",
USER_CAM_BROADCAST_STOPPED_2x: "UserBroadcastCamStopMsg", USER_CAM_BROADCAST_STOPPED_2x: "UserBroadcastCamStopMsg",
PRESENTER_ASSIGNED_2x: "PresenterAssignedEvtMsg",
STREAM_IS_RECORDED: "StreamIsRecordedMsg", STREAM_IS_RECORDED: "StreamIsRecordedMsg",

View File

@ -105,6 +105,11 @@ module.exports = class BigBlueButtonGW extends EventEmitter {
payload[C.MEETING_ID_2x] = header[C.MEETING_ID_2x]; payload[C.MEETING_ID_2x] = header[C.MEETING_ID_2x];
this.emit(C.DICONNECT_ALL_USERS_2x, payload); this.emit(C.DICONNECT_ALL_USERS_2x, payload);
break; 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: default:
this.emit(C.GATEWAY_MESSAGE, msg); this.emit(C.GATEWAY_MESSAGE, msg);
} }

View File

@ -29,9 +29,17 @@ module.exports = class WebsocketConnectionManager {
const connectionId = data? data.connectionId : null; const connectionId = data? data.connectionId : null;
const ws = this.webSockets[connectionId]; const ws = this.webSockets[connectionId];
if (ws) { if (ws) {
if (data.id === 'close') {
try {
ws.close();
} catch (err) {
Logger.warn('[WebsocketConnectionManager] Error on closing WS for', connectionId, err)
}
} else {
this.sendMessage(ws, data); this.sendMessage(ws, data);
} }
} }
}
_onNewConnection (ws) { _onNewConnection (ws) {
ws.id = connectionIDCounter++; ws.id = connectionIDCounter++;

View File

@ -70,6 +70,19 @@ module.exports = class ScreenshareManager extends BaseManager {
this._stopSession(sessionId); 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); Logger.info(this._logPrefix, "Sending startResponse to peer", sessionId, "for connection", session._id);
} }
catch (error) { catch (error) {
@ -101,17 +114,7 @@ module.exports = class ScreenshareManager extends BaseManager {
case 'close': case 'close':
Logger.info(this._logPrefix, 'Connection ' + connectionId + ' closed'); Logger.info(this._logPrefix, 'Connection ' + connectionId + ' closed');
this.closeSession(session, connectionId, role, sessionId);
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);
}
}
break; break;
default: default:
@ -122,4 +125,18 @@ module.exports = class ScreenshareManager extends BaseManager {
break; 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);
}
}
}
}; };

View File

@ -227,6 +227,8 @@ module.exports = class Screenshare extends BaseProvider {
start (sessionId, connectionId, sdpOffer, userId, role) { start (sessionId, connectionId, sdpOffer, userId, role) {
return new Promise(async (resolve, reject) => { return new Promise(async (resolve, reject) => {
this._status = C.MEDIA_STARTING;
// Forces H264 with a possible preferred profile // Forces H264 with a possible preferred profile
if (FORCE_H264) { if (FORCE_H264) {
sdpOffer = h264_sdp.transform(sdpOffer, PREFERRED_H264_PROFILE); sdpOffer = h264_sdp.transform(sdpOffer, PREFERRED_H264_PROFILE);
@ -347,6 +349,9 @@ module.exports = class Screenshare extends BaseProvider {
stop () { stop () {
return new Promise(async (resolve, reject) => { return new Promise(async (resolve, reject) => {
try { try {
if (this._status === C.MEDIA_STOPPED) {
return resolve();
}
Logger.info('[screnshare] Stopping and releasing endpoints for MCS user', this.mcsUserId); Logger.info('[screnshare] Stopping and releasing endpoints for MCS user', this.mcsUserId);
await this._stopScreensharing(); await this._stopScreensharing();
this._status = C.MEDIA_STOPPED; this._status = C.MEDIA_STOPPED;