Included extra BigBlueButton messages to connect a listen only user

This commit is contained in:
Pedro Beschorner Marin 2018-02-19 11:57:24 -03:00 committed by prlanzarin
parent 11e6c445da
commit 722ab679e3
8 changed files with 228 additions and 3 deletions

View File

@ -57,7 +57,7 @@ module.exports = class AudioManager {
this._audioSessions[sessionId] = session;
// starts audio session by sending sessionID, websocket and sdpoffer
session.start(sessionId, connectionId, message.sdpOffer, message.callerName, (error, sdpAnswer) => {
session.start(sessionId, connectionId, message.sdpOffer, message.callerName, message.userId, message.userName, (error, sdpAnswer) => {
Logger.info("[AudioManager] Started presenter ", sessionId, " for connection", connectionId);
Logger.debug("[AudioManager] SDP answer was", sdpAnswer);
if (error) {

View File

@ -6,7 +6,7 @@ const kurentoUrl = config.get('kurentoUrl');
const MCSApi = require('../mcs-core/lib/media/MCSApiStub');
const C = require('../bbb/messages/Constants');
const Logger = require('../utils/Logger');
const Messaging = require('../bbb/messages/Messaging');
module.exports = class Audio {
constructor(_bbbGW, _id, voiceBridge) {
@ -21,6 +21,7 @@ module.exports = class Audio {
this.webRtcEndpoint = null;
this.userId;
this.connectedUsers = {};
this.candidatesQueue = {}
}
@ -56,6 +57,43 @@ module.exports = class Audio {
}
}
/**
* Include user to a hash object indexed by it's connectionId
* @param {String} connectionId Current connection id at the media manager
* @param {Object} user {userId: String, userName: String}
*/
addUser(connectionId, user) {
if (this.connectedUsers.hasOwnProperty(connectionId)) {
Logger.warn("[audio] Updating user for connectionId", connectionId)
}
this.connectedUsers[connectionId] = user;
};
/**
* Exclude user from a hash object indexed by it's connectionId
* @param {String} connectionId Current connection id at the media manager
*/
removeUser(connectionId) {
if (this.connectedUsers.hasOwnProperty(connectionId)) {
delete this.connectedUsers[connectionId];
} else {
Logger.error("[audio] Missing connectionId", connectionId);
}
};
/**
* Consult user from a hash object indexed by it's connectionId
* @param {String} connectionId Current connection id at the media manager
* @return {Object} user {userId: String, userName: String}
*/
getUser(connectionId) {
if (this.connectedUsers.hasOwnProperty(connectionId)) {
return this.connectedUsers[connectionId];
} else {
Logger.error("[audio] Missing connectionId", connectionId);
}
};
mediaState (event) {
let msEvent = event.event;
@ -96,16 +134,26 @@ module.exports = class Audio {
break;
case "MediaFlowInStateChange":
Logger.info('[audio]', msEvent.type, '[' + msEvent.state? msEvent.state : 'UNKNOWN_STATE' + ']', 'for media session ', event.id);
if (msEvent.state === 'FLOWING') {
this._onRtpMediaFlowing(id);
} else {
this._onRtpMediaNotFlowing(id);
}
break;
default: Logger.warn("[audio] Unrecognized event", event);
}
}
async start (sessionId, connectionId, sdpOffer, callerName, callback) {
async start (sessionId, connectionId, sdpOffer, callerName, userId, userName, callback) {
Logger.info("[audio] Starting audio instance for", this.id);
let sdpAnswer;
// Storing the user data to be used by the pub calls
let user = {userId: userId, userName: userName};
this.addUser(connectionId, user);
try {
if (!this.sourceAudioStarted) {
this.userId = await this.mcs.join(this.voiceBridge, 'SFU', {});
@ -151,6 +199,8 @@ module.exports = class Audio {
let listener = this.audioEndpoints[id];
Logger.info('[audio] Releasing endpoints for', listener);
this.sendUserDisconnectedFromGlobalAudioMessage(id);
if (listener) {
try {
if (this.audioEndpoints && Object.keys(this.audioEndpoints).length === 1) {
@ -187,6 +237,10 @@ module.exports = class Audio {
delete this.candidatesQueue[queue];
}
for (var connection in this.connectedUsers) {
this.sendUserDisconnectedFromGlobalAudioMessage(connection);
}
this.sourceAudioStarted = false;
Promise.resolve();
@ -197,4 +251,56 @@ module.exports = class Audio {
}
return;
};
sendUserDisconnectedFromGlobalAudioMessage(connectionId) {
let user = this.getUser(connectionId);
let msg = Messaging.generateUserDisconnectedFromGlobalAudioMessage(this.voiceBridge, user.userId, user.userName);
Logger.info('[audio] Sending global audio disconnection for user', user);
// Interoperability between transcoder messages
switch (C.COMMON_MESSAGE_VERSION) {
case "1.x":
this.bbbGW.publish(msg, C.TO_BBB_MEETING_CHAN, function(error) {});
break;
default:
this.bbbGW.publish(msg, C.TO_AKKA_APPS_CHAN_2x, function(error) {});
}
this.removeUser(connectionId);
};
sendUserConnectedToGlobalAudioMessage(connectionId) {
let user = this.getUser(connectionId);
let msg = Messaging.generateUserConnectedToGlobalAudioMessage(this.voiceBridge, user.userId, user.userName);
Logger.info('[audio] Sending global audio connection for user', user);
// Interoperability between transcoder messages
switch (C.COMMON_MESSAGE_VERSION) {
case "1.x":
this.bbbGW.publish(msg, C.TO_BBB_MEETING_CHAN, function(error) {});
break;
default:
this.bbbGW.publish(msg, C.TO_AKKA_APPS_CHAN_2x, function(error) {});
}
};
_onRtpMediaFlowing(connectionId) {
Logger.info("[audio] RTP Media FLOWING for voice bridge", this.voiceBridge);
this.sendUserConnectedToGlobalAudioMessage(connectionId);
this.bbbGW.publish(JSON.stringify({
connectionId: connectionId,
id: "webRTCAudioSuccess",
success: "MEDIA_FLOWING"
}), C.FROM_AUDIO);
};
_onRtpMediaNotFlowing(connectionId) {
Logger.warn("[audio] RTP Media NOT FLOWING for voice bridge" + this.voiceBridge);
this.bbbGW.publish(JSON.stringify({
connectionId: connectionId,
id: "webRTCAudioError",
error: C.MEDIA_ERROR
}), C.FROM_AUDIO);
this.removeUser(connectionId);
};
};

View File

@ -29,6 +29,8 @@ const config = require('config');
FROM_BBB_TRANSCODE_SYSTEM_CHAN : "bigbluebutton:from-bbb-transcode:system",
FROM_VOICE_CONF_SYSTEM_CHAN: "from-voice-conf-redis-channel",
TO_BBB_TRANSCODE_SYSTEM_CHAN: "bigbluebutton:to-bbb-transcode:system",
TO_BBB_MEETING_CHAN: "bigbluebutton:to-bbb-apps:meeting",
TO_AKKA_APPS_CHAN_2x: "to-akka-apps-redis-channel",
FROM_SCREENSHARE: config.get('from-screenshare'),
TO_SCREENSHARE: config.get('to-screenshare'),
FROM_VIDEO: config.get('from-video'),
@ -49,6 +51,8 @@ const config = require('config');
STOP_TRANSCODER_REPLY: "stop_transcoder_reply_message",
DESKSHARE_RTMP_BROADCAST_STARTED: "deskshare_rtmp_broadcast_started_message",
DESKSHARE_RTMP_BROADCAST_STOPPED: "deskshare_rtmp_broadcast_stopped_message",
GLOBAL_AUDIO_CONNECTED: "user_connected_to_global_audio",
GLOBAL_AUDIO_DISCONNECTED: "user_disconnected_from_global_audio",
//Message identifiers 2x
SCREENSHARE_RTMP_BROADCAST_STARTED_2x: "ScreenshareRtmpBroadcastStartedVoiceConfEvtMsg",
@ -57,6 +61,8 @@ const config = require('config');
START_TRANSCODER_RESP_2x: "StartTranscoderSysRespMsg",
STOP_TRANSCODER_REQ_2x: "StopTranscoderSysReqMsg",
STOP_TRANSCODER_RESP_2x: "StopTranscoderSysRespMsg",
GLOBAL_AUDIO_CONNECTED_2x: "UserConnectedToGlobalAudioMsg",
GLOBAL_AUDIO_DISCONNECTED_2x: "UserDisconnectedFromGlobalAudioMsg",
USER_CAM_BROADCAST_STARTED_2x: "UserBroadcastCamStartMsg",
USER_CAM_BROADCAST_STOPPED_2x: "UserBroadcastCamStopMsg",
@ -86,6 +92,10 @@ const config = require('config');
VIDEO_WIDTH: "vidWidth",
VIDEO_HEIGHT: "vidHeight",
// Audio
NAME: "name",
USERID: "userid",
// RTP params
MEETING_ID : "meeting_id",
VOICE_CONF : "voice_conf",

View File

@ -23,6 +23,14 @@ let ScreenshareRTMPBroadcastStoppedEventMessage2x =
let UserCamBroadcastStoppedEventMessage2x =
require('./video/UserCamBroadcastStoppedEventMessage2x.js')(Constants);
let WebRTCShareEvent = require('./video/WebRTCShareEvent.js')(Constants);
let UserConnectedToGlobalAudio =
require('./audio/UserConnectedToGlobalAudio.js')(Constants);
let UserDisconnectedFromGlobalAudio =
require('./audio/UserDisconnectedFromGlobalAudio.js')(Constants);
let UserConnectedToGlobalAudio2x =
require('./audio/UserConnectedToGlobalAudio2x.js')(Constants);
let UserDisconnectedFromGlobalAudio2x =
require('./audio/UserDisconnectedFromGlobalAudio2x.js')(Constants);
/**
* @classdesc
@ -78,4 +86,31 @@ Messaging.prototype.generateWebRTCShareEvent =
let stodrbem = new WebRTCShareEvent(name, meetingId, streamUrl);
return stodrbem.payload;
}
Messaging.prototype.generateUserConnectedToGlobalAudioMessage =
function(voiceConf, userId, name) {
let msg;
switch (Constants.COMMON_MESSAGE_VERSION) {
case "1.x":
msg = new UserConnectedToGlobalAudio(voiceConf, userId, name);
break;
default:
msg = new UserConnectedToGlobalAudio2x(voiceConf, userId, name);
}
return msg.toJson();
}
Messaging.prototype.generateUserDisconnectedFromGlobalAudioMessage =
function(voiceConf, userId, name) {
let msg;
switch (Constants.COMMON_MESSAGE_VERSION) {
case "1.x":
msg = new UserDisconnectedFromGlobalAudio(voiceConf, userId, name);
break;
default:
msg = new UserDisconnectedFromGlobalAudio2x(voiceConf, userId, name);
}
return msg.toJson();
}
module.exports = new Messaging();

View File

@ -0,0 +1,16 @@
var inherits = require('inherits');
var OutMessage = require('../OutMessage');
module.exports = function(Constants) {
function UserConnectedToGlobalAudio(voiceConf, userId, name) {
UserConnectedToGlobalAudio.super_.call(this, Constants.GLOBAL_AUDIO_CONNECTED);
this.payload = {};
this.payload[Constants.VOICE_CONF] = voiceConf;
this.payload[Constants.USERID] = userId;
this.payload[Constants.NAME] = name;
};
inherits(UserConnectedToGlobalAudio, OutMessage);
return UserConnectedToGlobalAudio;
}

View File

@ -0,0 +1,21 @@
var inherits = require('inherits');
var OutMessage2x = require('../OutMessage2x');
// TODO: Check if this is correct!
module.exports = function(Constants) {
function UserConnectedToGlobalAudio2x(voiceConf, userId, name) {
UserConnectedToGlobalAudio2x.super_.call(
this,
Constants.GLOBAL_AUDIO_CONNECTED_2x,
{voiceConf: voiceConf},
{voiceConf: voiceConf}
);
this.core.body = {};
this.core.body[Constants.USER_ID_2x] = userId;
this.core.body[Constants.NAME] = name;
};
inherits(UserConnectedToGlobalAudio2x, OutMessage2x);
return UserConnectedToGlobalAudio2x;
};

View File

@ -0,0 +1,16 @@
var inherits = require('inherits');
var OutMessage = require('../OutMessage');
module.exports = function(Constants) {
function UserDisconnectedFromGlobalAudio(voiceConf, userId, name) {
UserDisconnectedFromGlobalAudio.super_.call(this, Constants.GLOBAL_AUDIO_DISCONNECTED);
this.payload = {};
this.payload[Constants.VOICE_CONF] = voiceConf;
this.payload[Constants.USERID] = userId;
this.payload[Constants.NAME] = name;
};
inherits(UserDisconnectedFromGlobalAudio, OutMessage);
return UserDisconnectedFromGlobalAudio;
}

View File

@ -0,0 +1,21 @@
var inherits = require('inherits');
var OutMessage2x = require('../OutMessage2x');
// TODO: Check if this is correct!
module.exports = function(Constants) {
function UserDisconnectedFromGlobalAudio2x(voiceConf, userId, name) {
UserDisconnectedFromGlobalAudio2x.super_.call(
this,
Constants.GLOBAL_AUDIO_DISCONNECTED_2x,
{voiceConf: voiceConf},
{voiceConf: voiceConf}
);
this.core.body = {};
this.core.body[Constants.USER_ID_2x] = userId;
this.core.body[Constants.NAME] = name;
};
inherits(UserDisconnectedFromGlobalAudio2x, OutMessage2x);
return UserDisconnectedFromGlobalAudio2x;
};