123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177 |
- /* global __filename */
-
- import { getLogger } from '@jitsi/logger';
-
- import * as JitsiConferenceEvents from '../../JitsiConferenceEvents';
- import RTCEvents from '../../service/RTC/RTCEvents';
- import browser from '../browser';
- import Deferred from '../util/Deferred';
- import Listenable from '../util/Listenable';
-
- import E2EEContext from './E2EEContext';
-
- const logger = getLogger(__filename);
-
- /**
- * Abstract class that integrates {@link E2EEContext} with a key management system.
- */
- export class KeyHandler extends Listenable {
- /**
- * Build a new KeyHandler instance, which will be used in a given conference.
- * @param {JitsiConference} conference - the current conference.
- * @param {object} options - the options passed to {E2EEContext}, see implemention.
- */
- constructor(conference, options = {}) {
- super();
-
- this.conference = conference;
- this.e2eeCtx = new E2EEContext(options);
-
- this.enabled = false;
- this._enabling = undefined;
-
- // Conference media events in order to attach the encryptor / decryptor.
- // FIXME add events to TraceablePeerConnection which will allow to see when there's new receiver or sender
- // added instead of shenanigans around conference track events and track muted.
- //
-
- this.conference.on(
- JitsiConferenceEvents._MEDIA_SESSION_STARTED,
- this._onMediaSessionStarted.bind(this));
- this.conference.on(
- JitsiConferenceEvents.TRACK_ADDED,
- track => track.isLocal() && this._onLocalTrackAdded(track));
- this.conference.rtc.on(
- RTCEvents.REMOTE_TRACK_ADDED,
- (track, tpc) => this._setupReceiverE2EEForTrack(tpc, track));
- this.conference.on(
- JitsiConferenceEvents.TRACK_MUTE_CHANGED,
- this._trackMuteChanged.bind(this));
- }
-
- /**
- * Indicates whether E2EE is currently enabled or not.
- *
- * @returns {boolean}
- */
- isEnabled() {
- return this.enabled;
- }
-
- /**
- * Enables / disables End-To-End encryption.
- *
- * @param {boolean} enabled - whether E2EE should be enabled or not.
- * @returns {void}
- */
- async setEnabled(enabled) {
- if (enabled === this.enabled) {
- return;
- }
-
- this._enabling && await this._enabling;
-
- this._enabling = new Deferred();
-
- this.enabled = enabled;
-
- if (!enabled) {
- this.e2eeCtx.cleanupAll();
- }
-
- this._setEnabled && await this._setEnabled(enabled);
-
- this.conference.setLocalParticipantProperty('e2ee.enabled', enabled);
-
- this.conference._restartMediaSessions();
-
- this._enabling.resolve();
- }
-
- /**
- * Sets the key for End-to-End encryption.
- *
- * @returns {void}
- */
- setEncryptionKey() {
- throw new Error('Not implemented by subclass');
- }
-
- /**
- * Setup E2EE on the new track that has been added to the conference, apply it on all the open peerconnections.
- * @param {JitsiLocalTrack} track - the new track that's being added to the conference.
- * @private
- */
- _onLocalTrackAdded(track) {
- for (const session of this.conference._getMediaSessions()) {
- this._setupSenderE2EEForTrack(session, track);
- }
- }
-
- /**
- * Setups E2E encryption for the new session.
- * @param {JingleSessionPC} session - the new media session.
- * @private
- */
- _onMediaSessionStarted(session) {
- const localTracks = this.conference.getLocalTracks();
-
- for (const track of localTracks) {
- this._setupSenderE2EEForTrack(session, track);
- }
- }
-
- /**
- * Setup E2EE for the receiving side.
- *
- * @private
- */
- _setupReceiverE2EEForTrack(tpc, track) {
- if (!this.enabled) {
- return;
- }
-
- const receiver = tpc.findReceiverForTrack(track.track);
-
- if (receiver) {
- this.e2eeCtx.handleReceiver(receiver, track.getType(), track.getParticipantId());
- } else {
- logger.warn(`Could not handle E2EE for ${track}: receiver not found in: ${tpc}`);
- }
- }
-
- /**
- * Setup E2EE for the sending side.
- *
- * @param {JingleSessionPC} session - the session which sends the media produced by the track.
- * @param {JitsiLocalTrack} track - the local track for which e2e encoder will be configured.
- * @private
- */
- _setupSenderE2EEForTrack(session, track) {
- if (!this.enabled) {
- return;
- }
-
- const pc = session.peerconnection;
- const sender = pc && pc.findSenderForTrack(track.track);
-
- if (sender) {
- this.e2eeCtx.handleSender(sender, track.getType(), track.getParticipantId());
- } else {
- logger.warn(`Could not handle E2EE for ${track}: sender not found in ${pc}`);
- }
- }
-
- /**
- * Setup E2EE on the sender that is created for the unmuted local video track.
- * @param {JitsiLocalTrack} track - the track for which muted status has changed.
- * @private
- */
- _trackMuteChanged(track) {
- if (browser.doesVideoMuteByStreamRemove() && track.isLocal() && track.isVideoTrack() && !track.isMuted()) {
- for (const session of this.conference._getMediaSessions()) {
- this._setupSenderE2EEForTrack(session, track);
- }
- }
- }
- }
|