Skip to content

Commit

Permalink
add flag to enable monitoring, correct who can see network problems a…
Browse files Browse the repository at this point in the history
…nd update logic
  • Loading branch information
Joao Siebel committed May 9, 2019
1 parent ae7c16f commit fea22d5
Show file tree
Hide file tree
Showing 10 changed files with 125 additions and 26 deletions.
2 changes: 2 additions & 0 deletions bigbluebutton-html5/imports/api/users/server/methods.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import removeUser from './methods/removeUser';
import toggleUserLock from './methods/toggleUserLock';
import setUserEffectiveConnectionType from './methods/setUserEffectiveConnectionType';
import userActivitySign from './methods/userActivitySign';
import userChangedSettings from './methods/userChangedSettings';

Meteor.methods({
setEmojiStatus,
Expand All @@ -17,4 +18,5 @@ Meteor.methods({
toggleUserLock,
setUserEffectiveConnectionType,
userActivitySign,
userChangedSettings,
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { Meteor } from 'meteor/meteor';
import { check } from 'meteor/check';
import RedisPubSub from '/imports/startup/server/redis';
import setChangedSettings from '../modifiers/setChangedSettings';

export default function userChangedSettings(credentials, setting, value) {
const REDIS_CONFIG = Meteor.settings.private.redis;
const CHANNEL = REDIS_CONFIG.channels.toAkkaApps;
const EVENT_NAME = 'UserChangedSettingsEvtMsg';

const { meetingId, requesterUserId } = credentials;

if (!meetingId || !requesterUserId) return;

check(meetingId, String);
check(requesterUserId, String);
check(setting, String);

const payload = {
meetingId,
requesterUserId,
setting,
value,
};

setChangedSettings(requesterUserId, setting, value);

RedisPubSub.publishUserMessage(CHANNEL, EVENT_NAME, meetingId, requesterUserId, payload);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { check } from 'meteor/check';
import Users from '/imports/api/users';
import Logger from '/imports/startup/server/logger';

export default function setChangedSettings(userId, setting, value) {
check(userId, String);
check(setting, Match.Maybe(String));

const selector = {
userId,
};

const modifier = {
$set: {},
};

modifier.$set[setting] = value;

const cb = (err, numChanged) => {
if (err) {
Logger.error(`${err}`);
}

if (numChanged) {
Logger.info(`Updated setting ${setting} to ${value} for user ${userId}`);
}
};

return Users.update(selector, modifier, cb);
}
12 changes: 8 additions & 4 deletions bigbluebutton-html5/imports/ui/components/app/component.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const MOBILE_MEDIA = 'only screen and (max-width: 40em)';
const APP_CONFIG = Meteor.settings.public.app;
const DESKTOP_FONT_SIZE = APP_CONFIG.desktopFontSize;
const MOBILE_FONT_SIZE = APP_CONFIG.mobileFontSize;
const ENABLE_NETWORK_INFORMATION = APP_CONFIG.enableNetworkInformation;

const intlMessages = defineMessages({
userListLabel: {
Expand Down Expand Up @@ -111,12 +112,15 @@ class App extends Component {
this.handleWindowResize();
window.addEventListener('resize', this.handleWindowResize, false);

if (navigator.connection) {
this.handleNetworkConnection();
navigator.connection.addEventListener('change', this.handleNetworkConnection);
if (ENABLE_NETWORK_INFORMATION) {
if (navigator.connection) {
this.handleNetworkConnection();
navigator.connection.addEventListener('change', this.handleNetworkConnection);
}

startBandwidthMonitoring();
}

startBandwidthMonitoring();

logger.info({ logCode: 'app_component_componentdidmount' }, 'Client loaded successfully');
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const METEOR_SETTINGS_APP = Meteor.settings.public.app;

// https://github.com/bigbluebutton/bigbluebutton/issues/5286#issuecomment-465342716
const SLOW_CONNECTIONS_TYPES = METEOR_SETTINGS_APP.effectiveConnection;
const ENABLE_NETWORK_INFORMATION = METEOR_SETTINGS_APP.enableNetworkInformation;

const HELP_LINK = METEOR_SETTINGS_APP.helpLink;

Expand Down Expand Up @@ -125,7 +126,7 @@ export default injectIntl(withTracker(({ intl }) => {

if (user) {
const { effectiveConnectionType } = user;
if (SLOW_CONNECTIONS_TYPES.includes(effectiveConnectionType)) {
if (ENABLE_NETWORK_INFORMATION && SLOW_CONNECTIONS_TYPES.includes(effectiveConnectionType)) {
data.message = (
<SlowConnection effectiveConnectionType={effectiveConnectionType}>
{intl.formatMessage(intlMessages.slowEffectiveConnectionDetected)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,7 @@ class UserDropdown extends PureComponent {
render() {
const {
compact,
currentUser,
user,
intl,
isMeetingLocked,
Expand All @@ -508,6 +509,8 @@ class UserDropdown extends PureComponent {

const userItemContentsStyle = {};

const { isModerator } = currentUser;

userItemContentsStyle[styles.dropdown] = true;
userItemContentsStyle[styles.userListItem] = !isActionsOpen;
userItemContentsStyle[styles.usertListItemWithMenu] = isActionsOpen;
Expand Down Expand Up @@ -551,6 +554,7 @@ class UserDropdown extends PureComponent {
{<UserIcons
{...{
user,
isModerator,
}}
/>}
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import React from 'react';
import React, { memo } from 'react';
import PropTypes from 'prop-types';
import Icon from '/imports/ui/components/icon/component';
import SlowConnection from '/imports/ui/components/slow-connection/component';
import Auth from '/imports/ui/services/auth';
import { styles } from './styles';

const SLOW_CONNECTIONS_TYPES = Meteor.settings.public.app.effectiveConnection;
const METEOR_SETTINGS_APP = Meteor.settings.public.app;

const SLOW_CONNECTIONS_TYPES = METEOR_SETTINGS_APP.effectiveConnection;
const ENABLE_NETWORK_INFORMATION = METEOR_SETTINGS_APP.enableNetworkInformation;

const propTypes = {
isModerator: PropTypes.bool.isRequired,
user: PropTypes.shape({
name: PropTypes.string.isRequired,
isPresenter: PropTypes.bool.isRequired,
Expand All @@ -18,23 +22,21 @@ const propTypes = {

const UserIcons = (props) => {
const {
isModerator,
user: {
isSharingWebcam,
effectiveConnectionType,
id,
},
} = props;

const showNetworkInformation = ENABLE_NETWORK_INFORMATION
&& SLOW_CONNECTIONS_TYPES.includes(effectiveConnectionType)
&& (id === Auth.userID || isModerator);

return (
<div className={styles.userIcons}>
{
isSharingWebcam ? (
<span className={styles.userIconsContainer}>
<Icon iconName="video" />
</span>
) : null
}
{
SLOW_CONNECTIONS_TYPES.includes(effectiveConnectionType) ? (
showNetworkInformation ? (
<span className={styles.userIconsContainer}>
<SlowConnection effectiveConnectionType={effectiveConnectionType} iconOnly />
</span>
Expand All @@ -45,4 +47,4 @@ const UserIcons = (props) => {
};

UserIcons.propTypes = propTypes;
export default UserIcons;
export default memo(UserIcons);
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ 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);

Expand Down Expand Up @@ -67,6 +68,12 @@ export const startBandwidthMonitoring = () => {
const warningLowerBoundary = monitoringTime - DANGER_END_TIME;
const warningUpperBoundary = monitoringTime - WARNING_END_TIME;

const usersWatchingWebcams = Users.find({
userId: { $ne: Auth.userID },
viewParticipantsWebcams: true,
connectionStatus: 'online',
}).map(user => user.userId);

const warningZone = NetworkInformationLocal
.find({
event: WEBCAMS_GET_STATUS,
Expand All @@ -85,11 +92,12 @@ export const startBandwidthMonitoring = () => {

const warningZoneReceivers = NetworkInformation
.find({
receiver: { $in: usersWatchingWebcams },
sender: Auth.userID,
time: { $lte: warningLowerBoundary, $gt: warningUpperBoundary },
}).count();

const dangerZone = NetworkInformationLocal
const dangerZone = _.uniqBy(NetworkInformationLocal
.find({
event: WEBCAMS_GET_STATUS,
timestamp: { $lt: dangerLowerBoundary, $gte: warningLowerBoundary },
Expand All @@ -103,24 +111,33 @@ export const startBandwidthMonitoring = () => {
'payload.stats.deltaPacketsLost': { $gt: 0 },
},
],
}).count();
}).fetch(), 'payload.id').length;

const dangerZoneReceivers = NetworkInformation
const dangerZoneReceivers = _.uniqBy(NetworkInformation
.find({
receiver: { $in: usersWatchingWebcams },
sender: Auth.userID,
time: { $lt: dangerLowerBoundary, $gte: warningLowerBoundary },
}).count();
}).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 });
Expand Down
17 changes: 13 additions & 4 deletions bigbluebutton-html5/imports/ui/services/settings/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Storage from '/imports/ui/services/storage/session';
import _ from 'lodash';
import { makeCall } from '/imports/ui/services/api';

const SETTINGS = [
'application',
Expand Down Expand Up @@ -33,9 +34,9 @@ class Settings {
});

// Sets default locale to browser locale
defaultValues.application.locale = navigator.languages ? navigator.languages[0] : false ||
navigator.language ||
defaultValues.application.locale;
defaultValues.application.locale = navigator.languages ? navigator.languages[0] : false
|| navigator.language
|| defaultValues.application.locale;

this.setDefault(defaultValues);
}
Expand All @@ -55,7 +56,15 @@ class Settings {
}

save() {
Object.keys(this).forEach(k => Storage.setItem(`settings${k}`, this[k].value));
Object.keys(this).forEach((k) => {
if (k === '_dataSaving') {
const { value: { viewParticipantsWebcams } } = this[k];

makeCall('userChangedSettings', 'viewParticipantsWebcams', viewParticipantsWebcams);
}

Storage.setItem(`settings${k}`, this[k].value);
});
}
}

Expand Down
1 change: 1 addition & 0 deletions bigbluebutton-html5/private/config/settings.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public:
basename: "/html5client"
askForFeedbackOnLogout: false
allowUserLookup: false
enableNetworkInformation: true
defaultSettings:
application:
animations: true
Expand Down

0 comments on commit fea22d5

Please sign in to comment.