bigbluebutton-Github/bigbluebutton-html5/imports/ui/services/network-information/index.js

230 lines
6.1 KiB
JavaScript

import NetworkInformation from '/imports/api/network-information';
import { makeCall } from '/imports/ui/services/api';
import Auth from '/imports/ui/services/auth';
import Users from '/imports/api/users';
import _ from 'lodash';
const NetworkInformationLocal = new Mongo.Collection(null);
const NAVIGATOR_CONNECTION = 'NAVIGATOR_CONNECTION';
const NUMBER_OF_WEBCAMS_CHANGED = 'NUMBER_OF_WEBCAMS_CHANGED';
const STARTED_WEBCAM_SHARING = 'STARTED_WEBCAM_SHARING';
const STOPPED_WEBCAM_SHARING = 'STOPPED_WEBCAM_SHARING';
const WEBCAMS_GET_STATUS = 'WEBCAMS_GET_STATUS';
const DANGER_BEGIN_TIME = 5000;
const DANGER_END_TIME = 30000;
const WARNING_END_TIME = 60000;
let monitoringIntervalRef;
export const updateCurrentWebcamsConnection = (connections) => {
const doc = {
timestamp: new Date().getTime(),
event: NUMBER_OF_WEBCAMS_CHANGED,
payload: Object.keys(connections),
};
NetworkInformationLocal.insert(doc);
};
export const deleteWebcamConnection = (id) => {
const doc = {
timestamp: new Date().getTime(),
event: STOPPED_WEBCAM_SHARING,
payload: { id },
};
NetworkInformationLocal.insert(doc);
};
export const getCurrentWebcams = () => NetworkInformationLocal
.findOne({
event: NUMBER_OF_WEBCAMS_CHANGED,
}, { sort: { timestamp: -1 } });
export const newWebcamConnection = (id) => {
const doc = {
timestamp: new Date().getTime(),
event: STARTED_WEBCAM_SHARING,
payload: { id },
};
NetworkInformationLocal.insert(doc);
};
export const startBandwidthMonitoring = () => {
monitoringIntervalRef = setInterval(() => {
const monitoringTime = new Date().getTime();
const dangerLowerBoundary = monitoringTime - DANGER_BEGIN_TIME;
const warningLowerBoundary = monitoringTime - DANGER_END_TIME;
const warningUpperBoundary = monitoringTime - WARNING_END_TIME;
// Remove old documents to reduce the size of the local collection.
NetworkInformationLocal.remove({
event: WEBCAMS_GET_STATUS,
timestamp: { $lt: warningUpperBoundary },
});
const usersWatchingWebcams = Users.find({
userId: { $ne: Auth.userID },
viewParticipantsWebcams: true,
connectionStatus: 'online',
}).map(user => user.userId);
const warningZone = NetworkInformationLocal
.find({
event: WEBCAMS_GET_STATUS,
timestamp: { $lte: warningLowerBoundary, $gt: warningUpperBoundary },
$or: [
{
'payload.id': Auth.userID,
'payload.stats.deltaPliCount': { $gt: 0 },
},
{
'payload.id': { $ne: Auth.userID },
'payload.stats.deltaPacketsLost': { $gt: 0 },
},
],
}).count();
const warningZoneReceivers = NetworkInformation
.find({
receiver: { $in: usersWatchingWebcams },
sender: Auth.userID,
time: { $lte: warningLowerBoundary, $gt: warningUpperBoundary },
}).count();
const dangerZone = _.uniqBy(NetworkInformationLocal
.find({
event: WEBCAMS_GET_STATUS,
timestamp: { $lt: dangerLowerBoundary, $gte: warningLowerBoundary },
$or: [
{
'payload.id': Auth.userID,
'payload.stats.deltaPliCount': { $gt: 0 },
},
{
'payload.id': { $ne: Auth.userID },
'payload.stats.deltaPacketsLost': { $gt: 0 },
},
],
}).fetch(), 'payload.id').length;
const dangerZoneReceivers = _.uniqBy(NetworkInformation
.find({
receiver: { $in: usersWatchingWebcams },
sender: Auth.userID,
time: { $lt: dangerLowerBoundary, $gte: warningLowerBoundary },
}).fetch(), 'receiver').length;
let effectiveType = 'good';
if (dangerZone) {
if (!dangerZoneReceivers) {
effectiveType = 'danger';
}
if (dangerZoneReceivers === usersWatchingWebcams.length) {
effectiveType = 'danger';
}
} else if (warningZone) {
if (!warningZoneReceivers) {
effectiveType = 'warning';
}
if (warningZoneReceivers === usersWatchingWebcams.length) {
effectiveType = 'warning';
}
}
const lastEffectiveConnectionType = Users.findOne({ userId: Auth.userID });
if (lastEffectiveConnectionType
&& lastEffectiveConnectionType.effectiveConnectionType !== effectiveType) {
makeCall('setUserEffectiveConnectionType', effectiveType);
}
}, 5000);
};
export const stopBandwidthMonitoring = () => {
clearInterval(monitoringIntervalRef);
};
export const updateNavigatorConnection = ({ effectiveType, downlink, rtt }) => {
const doc = {
timestamp: new Date().getTime(),
event: NAVIGATOR_CONNECTION,
payload: {
effectiveType,
downlink,
rtt,
},
};
NetworkInformationLocal.insert(doc);
};
export const updateWebcamStats = (id, stats) => {
if (!stats) return;
const lastStatus = NetworkInformationLocal
.findOne(
{ event: WEBCAMS_GET_STATUS, 'payload.id': id },
{ sort: { timestamp: -1 } },
);
const { video } = stats;
const doc = {
timestamp: new Date().getTime(),
event: WEBCAMS_GET_STATUS,
payload: { id, stats: video },
};
if (lastStatus) {
const {
payload: {
stats: {
packetsLost,
packetsReceived,
packetsSent,
pliCount,
},
},
} = lastStatus;
const normalizedVideo = { ...video };
normalizedVideo.deltaPacketsLost = video.packetsLost - packetsLost;
normalizedVideo.deltaPacketsReceived = video.packetsReceived - packetsReceived;
normalizedVideo.deltaPacketsSent = video.packetsSent - packetsSent;
normalizedVideo.deltaPliCount = video.pliCount - pliCount;
doc.payload = {
id,
stats: normalizedVideo,
};
if (normalizedVideo.deltaPacketsLost > 0) {
makeCall('userInstabilityDetected', id);
}
}
NetworkInformationLocal.insert(doc);
};
export default {
NetworkInformationLocal,
updateCurrentWebcamsConnection,
deleteWebcamConnection,
getCurrentWebcams,
newWebcamConnection,
startBandwidthMonitoring,
stopBandwidthMonitoring,
updateNavigatorConnection,
updateWebcamStats,
};