Skip to content

Commit

Permalink
fix(core): prevent global media limiter from applying to renegotiated…
Browse files Browse the repository at this point in the history
… medias as well

Also moved around the room/user threshold checks
  • Loading branch information
prlanzarin committed Sep 13, 2021
1 parent 5d48fe2 commit de8df12
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 47 deletions.
78 changes: 39 additions & 39 deletions lib/mcs-core/lib/media/media-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -160,12 +160,16 @@ module.exports = class MediaController {
return;
}

_isAboveThreshold () {
if (GLOBAL_MEDIA_THRESHOLD > 0 && this.medias.size >= GLOBAL_MEDIA_THRESHOLD) {
Logger.error(LOG_PREFIX, `Server has exceeded the media threshold`,
{ threshold: GLOBAL_MEDIA_THRESHOLD, current: this.medias.size }
);
return true;
isAboveGlobalMediaThreshold ({ mediaId, ignoreThresholds = false }) {
if (GLOBAL_MEDIA_THRESHOLD > 0 && !ignoreThresholds) {
const preExistantMedia = mediaId ? this.hasMediaSession(mediaId) : false;

if (!preExistantMedia && this.medias.size >= GLOBAL_MEDIA_THRESHOLD) {
Logger.error(LOG_PREFIX, `Server has exceeded the media threshold`,
{ threshold: GLOBAL_MEDIA_THRESHOLD, current: this.medias.size }
);
return true;
}
}
return false;
}
Expand Down Expand Up @@ -202,6 +206,13 @@ module.exports = class MediaController {
throw (this._handleError(C.ERROR.MEDIA_ADAPTER_OBJECT_NOT_FOUND));
}

if (this.isAboveGlobalMediaThreshold(params)) {
throw (this._handleError({
...C.ERROR.MEDIA_SERVER_NO_RESOURCES,
details: `Threshold exceeded. Threshold: ${GLOBAL_MEDIA_THRESHOLD}`,
}));
}

try {
user = this.getUser(userId);
room = this.getRoom(user.roomId);
Expand All @@ -210,21 +221,13 @@ module.exports = class MediaController {
throw error;
}

if (!params.ignoreThresholds && this.isAboveMediaThresholds(room, user)) {
throw (this._handleError({
...C.ERROR.MEDIA_SERVER_NO_RESOURCES,
details: `Threshold exceeded. Threshold: ${GLOBAL_MEDIA_THRESHOLD}`,
}));
}

try {
({ session, answer } = await user.publish(params.descriptor, type, params));
} catch (error) {
throw (this._handleError(error));
}

this.addMediaSession(session);
room.addMediaSession(session);

if (source) {
try {
Expand Down Expand Up @@ -252,6 +255,13 @@ module.exports = class MediaController {
throw (this._handleError(C.ERROR.MEDIA_ADAPTER_OBJECT_NOT_FOUND));
}

if (this.isAboveGlobalMediaThreshold(params)) {
throw (this._handleError({
...C.ERROR.MEDIA_SERVER_NO_RESOURCES,
details: `Threshold exceeded. Threshold: ${GLOBAL_MEDIA_THRESHOLD}`,
}));
}

try {
user = this.getUser(userId);
room = this.getRoom(user.roomId);
Expand All @@ -260,21 +270,13 @@ module.exports = class MediaController {
throw error;
}

if (!params.ignoreThresholds && this.isAboveMediaThresholds(room, user)) {
throw (this._handleError({
...C.ERROR.MEDIA_SERVER_NO_RESOURCES,
details: `Threshold exceeded. Threshold: ${GLOBAL_MEDIA_THRESHOLD}`,
}));
}

try {
({ session, answer } = await user.publish(params.descriptor, type, params));
} catch (error) {
throw (this._handleError(error));
}

this.addMediaSession(session);
room.addMediaSession(session);
session.sessionStarted();
return ({ descriptor: answer, mediaId: session.id });
}
Expand All @@ -295,6 +297,13 @@ module.exports = class MediaController {
throw (this._handleError(C.ERROR.MEDIA_ADAPTER_OBJECT_NOT_FOUND));
}

if (this.isAboveGlobalMediaThreshold(params)) {
throw (this._handleError({
...C.ERROR.MEDIA_SERVER_NO_RESOURCES,
details: `Threshold exceeded. Threshold: ${GLOBAL_MEDIA_THRESHOLD}`,
}));
}

try {
user = this.getUser(userId);
room = this.getRoom(user.roomId);
Expand All @@ -303,13 +312,6 @@ module.exports = class MediaController {
throw error;
}

if (!params.ignoreThresholds && this.isAboveMediaThresholds(room, user)) {
throw (this._handleError({
...C.ERROR.MEDIA_SERVER_NO_RESOURCES,
details: `Threshold exceeded. Threshold: ${GLOBAL_MEDIA_THRESHOLD}`,
}));
}

try {
if (sourceId === C.MEDIA_PROFILE.CONTENT) {
source = this.getMediaSession(room._contentFloor.id);
Expand All @@ -329,7 +331,6 @@ module.exports = class MediaController {
}

this.addMediaSession(session);
room.addMediaSession(session);
session.sessionStarted();
return ({descriptor: answer, mediaId: session.id});
}
Expand Down Expand Up @@ -388,6 +389,13 @@ module.exports = class MediaController {
throw (this._handleError(C.ERROR.MEDIA_ADAPTER_OBJECT_NOT_FOUND));
}

if (this.isAboveGlobalMediaThreshold(params)) {
throw (this._handleError({
...C.ERROR.MEDIA_SERVER_NO_RESOURCES,
details: `Threshold exceeded. Threshold: ${GLOBAL_MEDIA_THRESHOLD}`,
}));
}

try {
user = this.getUser(userId);
room = this.getRoom(user.roomId);
Expand All @@ -398,13 +406,6 @@ module.exports = class MediaController {
throw (this._handleError(error));
}

if (!params.ignoreThresholds && this.isAboveMediaThresholds(room, user)) {
throw (this._handleError({
...C.ERROR.MEDIA_SERVER_NO_RESOURCES,
details: `Threshold exceeded. Threshold: ${GLOBAL_MEDIA_THRESHOLD}`,
}));
}

try {
({ recordingSession, answer } = await user.startRecording(
recordingPath,
Expand All @@ -419,7 +420,6 @@ module.exports = class MediaController {
}

this.addMediaSession(recordingSession);
room.addMediaSession(recordingSession);
recordingSession.sessionStarted();
return answer;
}
Expand Down Expand Up @@ -613,7 +613,7 @@ module.exports = class MediaController {
}

// No pre-existing externalUserId sent in the join procedure, create a new one
user = new User(roomId, type, params);
user = new User(room, type, params);
this.users.set(user.id, user);
if (user.externalUserId !== user.id) this.users.set(user.externalUserId, user);
room.addUser(user);
Expand Down
4 changes: 4 additions & 0 deletions lib/mcs-core/lib/model/media-session.js
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,10 @@ module.exports = class MediaSession {
this._mediaProfile = options.mediaProfile;
// Media specs for the media. If not specified, falls back to the default
this.mediaSpecs = options.mediaSpecs? options.mediaSpecs : {...MEDIA_SPECS};
// API-specified media profiles (audio|video|content: 'string'|boolean =>
// 'recvonly'|'sendonly'|'sendrecv'|true|false
this.profiles = options.profiles || DEFAULT_PROFILES;
// Whether this media session should be ignored by the media limiter
this.ignoreThresholds = options.ignoreThresholds || false;
}
}
34 changes: 26 additions & 8 deletions lib/mcs-core/lib/model/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,22 @@ const MCS_USER_EJECTION_TIMER = config.has('mcsUserEjectionTimer')
const LOG_PREFIX = "[mcs-user]";

module.exports = class User extends EventEmitter {
constructor(roomId, type, params = {}) {
constructor(room, type, params = {}) {
super();
this.id = rid();
this.externalUserId = params.externalUserId || this.id;
this.autoLeave = typeof params.autoLeave !== 'undefined'? params.autoLeave : false;
this.roomId = roomId;
this.room = room;
this.type = type;
this.name = params.name ? params.name : this.id;
this.mediaSessions = {}
this._clientTrackingIds = {};
}

get roomId () {
return this.room.id;
}

async _startSession (sessionId) {
const session = this.mediaSessions[sessionId];
try {
Expand Down Expand Up @@ -70,6 +74,14 @@ module.exports = class User extends EventEmitter {
return false;
}

addMediaSession (mediaSession) {
this.mediaSessions[mediaSession.id] = mediaSession;
}

getMediaSession (id) {
return this.mediaSessions[id];
}

createMediaSession (descriptor, type, params = {}) {
const { mediaId } = params;

Expand All @@ -79,7 +91,7 @@ module.exports = class User extends EventEmitter {
// If it doesn't exist, just create a new one since it's an optional parameter
// which should be ignored in case it doesn't make sense
if (mediaId) {
const targetMediaSession = this.mediaSessions[mediaId];
const targetMediaSession = this.getMediaSession(mediaId);
if (targetMediaSession) {
const updatedParams = { ...targetMediaSession.options, ...params };
targetMediaSession.remoteDescriptor = descriptor;
Expand All @@ -88,6 +100,14 @@ module.exports = class User extends EventEmitter {
}
}

if (!params.ignoreThresholds
&& (this.isAboveThreshold() || this.room.isAboveThreshold())) {
throw (this._handleError({
...C.ERROR.MEDIA_SERVER_NO_RESOURCES,
details: 'Threshold exceeded',
}));
}

const mediaSession = MediaFactory.createMediaSession(
descriptor,
type,
Expand All @@ -96,8 +116,10 @@ module.exports = class User extends EventEmitter {
params
);

this.addMediaSession(mediaSession);
this.room.addMediaSession(mediaSession);

this._trackMediaDisconnection(mediaSession);
this.mediaSessions[mediaSession.id] = mediaSession;
if (this.ejectionRoutine) this._clearEjectionTimeout();

return mediaSession;
Expand Down Expand Up @@ -245,10 +267,6 @@ module.exports = class User extends EventEmitter {
});
}

getMediaSession (id) {
return this.mediaSessions[id];
}

getUserInfo () {
const mediasList = Object.keys(this.mediaSessions).map(key => {
let mi = this.mediaSessions[key].getMediaInfo();
Expand Down

0 comments on commit de8df12

Please sign in to comment.