fix(e2ee): Optimize.

This commit is contained in:
Hristo Terezov 2023-02-23 17:00:47 -06:00
parent b033d0268a
commit 42ce6dcc58
8 changed files with 80 additions and 208 deletions

View File

@ -429,11 +429,12 @@ StateListenerRegistry.register(
'e2ee.enabled': (participant: IJitsiParticipant, value: string) =>
_e2eeUpdated(store, conference, participant.getId(), value),
'features_e2ee': (participant: IJitsiParticipant, value: boolean) =>
store.dispatch(participantUpdated({
conference,
id: participant.getId(),
e2eeSupported: value
})),
getParticipantById(store.getState(), participant.getId())?.e2eeSupported !== value
&& store.dispatch(participantUpdated({
conference,
id: participant.getId(),
e2eeSupported: value
})),
'features_jigasi': (participant: IJitsiParticipant, value: boolean) =>
store.dispatch(participantUpdated({
conference,
@ -506,7 +507,12 @@ StateListenerRegistry.register(
function _e2eeUpdated({ getState, dispatch }: IStore, conference: IJitsiConference,
participantId: string, newValue: string | boolean) {
const e2eeEnabled = newValue === 'true';
const { e2ee = {} } = getState()['features/base/config'];
const state = getState();
const { e2ee = {} } = state['features/base/config'];
if (e2eeEnabled === getParticipantById(state, participantId)?.e2eeEnabled) {
return;
}
dispatch(participantUpdated({
conference,

View File

@ -67,6 +67,8 @@ const DEFAULT_STATE = {
fakeParticipants: new Map(),
local: undefined,
localScreenShare: undefined,
numberOfParticipantsDisabledE2EE: 0,
numberOfParticipantsNotSupportingE2EE: 0,
overwrittenNameList: {},
pinnedParticipant: undefined,
raisedHandsQueue: [],
@ -83,6 +85,8 @@ export interface IParticipantsState {
fakeParticipants: Map<string, IParticipant>;
local?: ILocalParticipant;
localScreenShare?: IParticipant;
numberOfParticipantsDisabledE2EE: number;
numberOfParticipantsNotSupportingE2EE: number;
overwrittenNameList: { [id: string]: string; };
pinnedParticipant?: string;
raisedHandsQueue: Array<{ id: string; raisedHandTimestamp: number; }>;
@ -208,8 +212,9 @@ ReducerRegistry.register<IParticipantsState>('features/base/participants',
newParticipant = state.local = _participant(state.local, action);
}
if (newParticipant) {
const oldParticipant = local ? state.local : state.remote.get(id);
if (newParticipant) {
// everyoneIsModerator calculation:
const isModerator = isParticipantModerator(newParticipant);
@ -220,6 +225,15 @@ ReducerRegistry.register<IParticipantsState>('features/base/participants',
}
}
if (oldParticipant && newParticipant && !newParticipant.fakeParticipant) {
if (oldParticipant.e2eeEnabled !== newParticipant.e2eeEnabled) {
state.numberOfParticipantsDisabledE2EE += newParticipant.e2eeEnabled ? -1 : 1;
}
if (!local && oldParticipant.e2eeSupported !== newParticipant.e2eeSupported) {
state.numberOfParticipantsNotSupportingE2EE += newParticipant.e2eeSupported ? -1 : 1;
}
}
return {
...state
};
@ -276,6 +290,18 @@ ReducerRegistry.register<IParticipantsState>('features/base/participants',
state.everyoneIsModerator = true;
}
if (!fakeParticipant) {
const { e2eeEnabled, e2eeSupported } = participant as IParticipant;
if (!e2eeEnabled) {
state.numberOfParticipantsDisabledE2EE += 1;
}
if (!participant.local && !e2eeSupported) {
state.numberOfParticipantsNotSupportingE2EE += 1;
}
}
if (participant.local) {
return {
...state,
@ -407,6 +433,18 @@ ReducerRegistry.register<IParticipantsState>('features/base/participants',
state.sortedRemoteVirtualScreenshareParticipants = new Map(sortedRemoteVirtualScreenshareParticipants);
}
if (oldParticipant && !oldParticipant.fakeParticipant) {
const { e2eeEnabled, e2eeSupported } = oldParticipant;
if (!e2eeEnabled) {
state.numberOfParticipantsDisabledE2EE -= 1;
}
if (!oldParticipant.local && !e2eeSupported) {
state.numberOfParticipantsNotSupportingE2EE -= 1;
}
}
return { ...state };
}
case PARTICIPANT_SOURCES_UPDATED: {

View File

@ -7,25 +7,6 @@
*/
export const TOGGLE_E2EE = 'TOGGLE_E2EE';
/**
* The type of the action which signals to set new value whether everyone has E2EE enabled.
*
* {
* type: SET_EVERYONE_ENABLED_E2EE,
* everyoneEnabledE2EE: boolean
* }
*/
export const SET_EVERYONE_ENABLED_E2EE = 'SET_EVERYONE_ENABLED_E2EE';
/**
* The type of the action which signals to set new value whether everyone supports E2EE.
*
* {
* type: SET_EVERYONE_SUPPORT_E2EE
* }
*/
export const SET_EVERYONE_SUPPORT_E2EE = 'SET_EVERYONE_SUPPORT_E2EE';
/**
* The type of the action which signals to set new value E2EE maxMode.
*

View File

@ -1,7 +1,5 @@
import {
PARTICIPANT_VERIFIED,
SET_EVERYONE_ENABLED_E2EE,
SET_EVERYONE_SUPPORT_E2EE,
SET_MAX_MODE,
SET_MEDIA_ENCRYPTION_KEY,
START_VERIFICATION,
@ -20,38 +18,6 @@ export function toggleE2EE(enabled: boolean) {
};
}
/**
* Set new value whether everyone has E2EE enabled.
*
* @param {boolean} everyoneEnabledE2EE - The new value.
* @returns {{
* type: SET_EVERYONE_ENABLED_E2EE,
* everyoneEnabledE2EE: boolean
* }}
*/
export function setEveryoneEnabledE2EE(everyoneEnabledE2EE: boolean) {
return {
type: SET_EVERYONE_ENABLED_E2EE,
everyoneEnabledE2EE
};
}
/**
* Set new value whether everyone support E2EE.
*
* @param {boolean} everyoneSupportE2EE - The new value.
* @returns {{
* type: SET_EVERYONE_SUPPORT_E2EE,
* everyoneSupportE2EE: boolean
* }}
*/
export function setEveryoneSupportE2EE(everyoneSupportE2EE: boolean) {
return {
type: SET_EVERYONE_SUPPORT_E2EE,
everyoneSupportE2EE
};
}
/**
* Dispatches an action to set E2EE maxMode.
*

View File

@ -27,6 +27,6 @@ export function _mapStateToProps(state: IReduxState) {
return {
_e2eeLabels: e2ee.labels,
_showLabel: state['features/e2ee'].everyoneEnabledE2EE
_showLabel: state['features/base/participants'].numberOfParticipantsDisabledE2EE === 0
};
}

View File

@ -1,6 +1,6 @@
import { IReduxState } from '../app/types';
import { IStateful } from '../base/app/types';
import { getParticipantById, getParticipantCount } from '../base/participants/functions';
import { getParticipantById, getParticipantCount, getParticipantCountWithFake } from '../base/participants/functions';
import { toState } from '../base/redux/functions';
@ -19,17 +19,17 @@ import { MAX_MODE_LIMIT, MAX_MODE_THRESHOLD } from './constants';
*/
export function doesEveryoneSupportE2EE(stateful: IStateful) {
const state = toState(stateful);
const { everyoneSupportE2EE } = state['features/e2ee'];
const { numberOfParticipantsNotSupportingE2EE } = state['features/base/participants'];
const { e2eeSupported } = state['features/base/conference'];
const participantCount = getParticipantCount(state);
const participantCount = getParticipantCountWithFake(state);
if (typeof everyoneSupportE2EE === 'undefined' && participantCount === 1) {
if (participantCount === 1) {
// This will happen if we are alone.
return e2eeSupported;
}
return everyoneSupportE2EE;
return numberOfParticipantsNotSupportingE2EE === 0;
}
/**

View File

@ -1,4 +1,3 @@
import { batch } from 'react-redux';
import { IStore } from '../app/types';
import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../base/app/actionTypes';
@ -6,13 +5,11 @@ import { CONFERENCE_JOINED } from '../base/conference/actionTypes';
import { getCurrentConference } from '../base/conference/functions';
import { openDialog } from '../base/dialog/actions';
import { JitsiConferenceEvents } from '../base/lib-jitsi-meet';
import { PARTICIPANT_JOINED, PARTICIPANT_LEFT, PARTICIPANT_UPDATED } from '../base/participants/actionTypes';
import { PARTICIPANT_JOINED, PARTICIPANT_LEFT } from '../base/participants/actionTypes';
import { participantUpdated } from '../base/participants/actions';
import {
getLocalParticipant,
getParticipantById,
getParticipantCount,
getRemoteParticipants,
isScreenShareParticipant
} from '../base/participants/functions';
import MiddlewareRegistry from '../base/redux/MiddlewareRegistry';
@ -20,7 +17,7 @@ import StateListenerRegistry from '../base/redux/StateListenerRegistry';
import { playSound, registerSound, unregisterSound } from '../base/sounds/actions';
import { PARTICIPANT_VERIFIED, SET_MEDIA_ENCRYPTION_KEY, START_VERIFICATION, TOGGLE_E2EE } from './actionTypes';
import { setE2EEMaxMode, setEveryoneEnabledE2EE, setEveryoneSupportE2EE, toggleE2EE } from './actions';
import { setE2EEMaxMode, toggleE2EE } from './actions';
import ParticipantVerificationDialog from './components/ParticipantVerificationDialog';
import { E2EE_OFF_SOUND_ID, E2EE_ON_SOUND_ID, MAX_MODE } from './constants';
import { isMaxModeReached, isMaxModeThresholdReached } from './functions';
@ -58,137 +55,24 @@ MiddlewareRegistry.register(({ dispatch, getState }) => next => action => {
break;
case PARTICIPANT_UPDATED: {
const { id, e2eeEnabled, e2eeSupported } = action.participant;
const oldParticipant = getParticipantById(getState(), id);
const result = next(action);
if (e2eeEnabled !== oldParticipant?.e2eeEnabled
|| e2eeSupported !== oldParticipant?.e2eeSupported) {
const state = getState();
let newEveryoneSupportE2EE = true;
let newEveryoneEnabledE2EE = true;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
for (const [ key, p ] of getRemoteParticipants(state)) {
if (!p.e2eeEnabled) {
newEveryoneEnabledE2EE = false;
}
if (!p.e2eeSupported) {
newEveryoneSupportE2EE = false;
}
if (!newEveryoneEnabledE2EE && !newEveryoneSupportE2EE) {
break;
}
}
if (!getLocalParticipant(state)?.e2eeEnabled) {
newEveryoneEnabledE2EE = false;
}
batch(() => {
dispatch(setEveryoneEnabledE2EE(newEveryoneEnabledE2EE));
dispatch(setEveryoneSupportE2EE(newEveryoneSupportE2EE));
});
}
return result;
}
case PARTICIPANT_JOINED: {
const result = next(action);
const { e2eeEnabled, e2eeSupported, local } = action.participant;
const { everyoneEnabledE2EE } = getState()['features/e2ee'];
const participantCount = getParticipantCount(getState);
if (isScreenShareParticipant(action.participant)) {
return result;
if (!isScreenShareParticipant(action.participant) && !action.participant.local) {
_updateMaxMode(dispatch, getState);
}
// the initial values
if (participantCount === 1) {
batch(() => {
dispatch(setEveryoneEnabledE2EE(e2eeEnabled));
dispatch(setEveryoneSupportE2EE(e2eeSupported));
});
}
// if all had it enabled and this one disabled it, change value in store
// otherwise there is no change in the value we store
if (everyoneEnabledE2EE && !e2eeEnabled) {
dispatch(setEveryoneEnabledE2EE(false));
}
if (local) {
return result;
}
const { everyoneSupportE2EE } = getState()['features/e2ee'];
// if all supported it and this one does not, change value in store
// otherwise there is no change in the value we store
if (everyoneSupportE2EE && !e2eeSupported) {
dispatch(setEveryoneSupportE2EE(false));
}
_updateMaxMode(dispatch, getState);
return result;
}
case PARTICIPANT_LEFT: {
const previosState = getState();
const participant = getParticipantById(previosState, action.participant?.id);
const participant = getParticipantById(getState(), action.participant?.id);
const result = next(action);
const newState = getState();
const { e2eeEnabled = false, e2eeSupported = false } = participant ?? {};
if (isScreenShareParticipant(participant)) {
return result;
if (!isScreenShareParticipant(participant)) {
_updateMaxMode(dispatch, getState);
}
const { everyoneEnabledE2EE, everyoneSupportE2EE } = newState['features/e2ee'];
// if it was not enabled by everyone, and the participant leaving had it disabled, or if it was not supported
// by everyone, and the participant leaving had it not supported let's check is it enabled for all that stay
if ((!everyoneEnabledE2EE && !e2eeEnabled) || (!everyoneSupportE2EE && !e2eeSupported)) {
let latestEveryoneEnabledE2EE = true;
let latestEveryoneSupportE2EE = true;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
for (const [ key, p ] of getRemoteParticipants(newState)) {
if (!p.e2eeEnabled) {
latestEveryoneEnabledE2EE = false;
}
if (!p.e2eeSupported) {
latestEveryoneSupportE2EE = false;
}
if (!latestEveryoneEnabledE2EE && !latestEveryoneSupportE2EE) {
break;
}
}
if (!getLocalParticipant(newState)?.e2eeEnabled) {
latestEveryoneEnabledE2EE = false;
}
batch(() => {
if (!everyoneEnabledE2EE && latestEveryoneEnabledE2EE) {
dispatch(setEveryoneEnabledE2EE(true));
}
if (!everyoneSupportE2EE && latestEveryoneSupportE2EE) {
dispatch(setEveryoneSupportE2EE(true));
}
});
}
_updateMaxMode(dispatch, getState);
return result;
}
@ -314,12 +198,23 @@ function _updateMaxMode(dispatch: IStore['dispatch'], getState: IStore['getState
return;
}
if (isMaxModeThresholdReached(state)) {
dispatch(setE2EEMaxMode(MAX_MODE.THRESHOLD_EXCEEDED));
dispatch(toggleE2EE(false));
const { maxMode, enabled } = state['features/e2ee'];
const isMaxModeThresholdReachedValue = isMaxModeThresholdReached(state);
let newMaxMode: string;
if (isMaxModeThresholdReachedValue) {
newMaxMode = MAX_MODE.THRESHOLD_EXCEEDED;
} else if (isMaxModeReached(state)) {
dispatch(setE2EEMaxMode(MAX_MODE.ENABLED));
newMaxMode = MAX_MODE.ENABLED;
} else {
dispatch(setE2EEMaxMode(MAX_MODE.DISABLED));
newMaxMode = MAX_MODE.DISABLED;
}
if (maxMode !== newMaxMode) {
dispatch(setE2EEMaxMode(newMaxMode));
}
if (isMaxModeThresholdReachedValue && !enabled) {
dispatch(toggleE2EE(false));
}
}

View File

@ -1,8 +1,6 @@
import ReducerRegistry from '../base/redux/ReducerRegistry';
import {
SET_EVERYONE_ENABLED_E2EE,
SET_EVERYONE_SUPPORT_E2EE,
SET_MAX_MODE,
TOGGLE_E2EE
} from './actionTypes';
@ -15,8 +13,6 @@ const DEFAULT_STATE = {
export interface IE2EEState {
enabled: boolean;
everyoneEnabledE2EE?: boolean;
everyoneSupportE2EE?: boolean;
maxMode: string;
}
@ -34,16 +30,6 @@ ReducerRegistry.register<IE2EEState>('features/e2ee', (state = DEFAULT_STATE, ac
...state,
enabled: action.enabled
};
case SET_EVERYONE_ENABLED_E2EE:
return {
...state,
everyoneEnabledE2EE: action.everyoneEnabledE2EE
};
case SET_EVERYONE_SUPPORT_E2EE:
return {
...state,
everyoneSupportE2EE: action.everyoneSupportE2EE
};
case SET_MAX_MODE: {
return {