Browse Source

ref(e2ee): extract E2EEncryption module

Moves the logics which deal with JitsiConference events to a separate module.
dev1
paweldomas 5 years ago
parent
commit
ddb3ed92b5
3 changed files with 147 additions and 94 deletions
  1. 8
    93
      JitsiConference.js
  2. 18
    1
      modules/RTC/TraceablePeerConnection.js
  3. 121
    0
      modules/e2ee/E2EEncryption.js

+ 8
- 93
JitsiConference.js View File

@@ -26,7 +26,7 @@ import IceFailedHandling
26 26
     from './modules/connectivity/IceFailedHandling';
27 27
 import ParticipantConnectionStatusHandler
28 28
     from './modules/connectivity/ParticipantConnectionStatus';
29
-import E2EEContext from './modules/e2ee/E2EEContext';
29
+import { E2EEncryption } from './modules/e2ee/E2EEncryption';
30 30
 import E2ePing from './modules/e2eping/e2eping';
31 31
 import Jvb121EventGenerator from './modules/event/Jvb121EventGenerator';
32 32
 import RecordingManager from './modules/recording/RecordingManager';
@@ -235,10 +235,8 @@ export default function JitsiConference(options) {
235 235
     this.recordingManager = new RecordingManager(this.room);
236 236
     this._conferenceJoinAnalyticsEventSent = false;
237 237
 
238
-    const config = this.options.config;
239
-
240
-    if (browser.supportsInsertableStreams() && !(config.testing && config.testing.disableE2EE)) {
241
-        this._e2eeCtx = new E2EEContext({ salt: this.options.name });
238
+    if (this.isE2EESupported()) {
239
+        this._e2eEncryption = new E2EEncryption(this, { salt: this.options.name });
242 240
     }
243 241
 }
244 242
 
@@ -975,16 +973,6 @@ JitsiConference.prototype._fireMuteChangeEvent = function(track) {
975 973
         actorParticipant = this.participants[actorId];
976 974
     }
977 975
 
978
-    // Setup E2EE on the sender that is created for the unmuted track.
979
-    if (this._e2eeCtx && !track.isMuted() && browser.doesVideoMuteByStreamRemove()) {
980
-        if (this.p2pJingleSession) {
981
-            this._setupSenderE2EEForTrack(this.p2pJingleSession, track);
982
-        }
983
-        if (this.jvbJingleSession) {
984
-            this._setupSenderE2EEForTrack(this.jvbJingleSession, track);
985
-        }
986
-    }
987
-
988 976
     this.eventEmitter.emit(JitsiConferenceEvents.TRACK_MUTE_CHANGED, track, actorParticipant);
989 977
 };
990 978
 
@@ -1130,17 +1118,6 @@ JitsiConference.prototype._setupNewTrack = function(newTrack) {
1130 1118
         this.room.setVideoMute(newTrack.isMuted());
1131 1119
     }
1132 1120
 
1133
-    // Setup E2EE on the new track that has been added
1134
-    // to the conference, apply it on all the open peerconnections.
1135
-    if (this._e2eeCtx) {
1136
-        if (this.p2pJingleSession) {
1137
-            this._setupSenderE2EEForTrack(this.p2pJingleSession, newTrack);
1138
-        }
1139
-        if (this.jvbJingleSession) {
1140
-            this._setupSenderE2EEForTrack(this.jvbJingleSession, newTrack);
1141
-        }
1142
-    }
1143
-
1144 1121
     newTrack.muteHandler = this._fireMuteChangeEvent.bind(this, newTrack);
1145 1122
     newTrack.audioLevelHandler = this._fireAudioLevelChangeEvent.bind(this);
1146 1123
     newTrack.addEventListener(
@@ -1698,9 +1675,6 @@ JitsiConference.prototype.onRemoteTrackAdded = function(track) {
1698 1675
         return;
1699 1676
     }
1700 1677
 
1701
-    // Setup E2EE handling, if supported.
1702
-    this._setupReceiverE2EEForTrack(track);
1703
-
1704 1678
     const id = track.getParticipantId();
1705 1679
     const participant = this.getParticipantById(id);
1706 1680
 
@@ -1750,13 +1724,6 @@ JitsiConference.prototype.onCallAccepted = function(session, answer) {
1750 1724
     if (this.p2pJingleSession === session) {
1751 1725
         logger.info('P2P setAnswer');
1752 1726
 
1753
-        // Setup E2EE.
1754
-        const localTracks = this.getLocalTracks();
1755
-
1756
-        for (const track of localTracks) {
1757
-            this._setupSenderE2EEForTrack(session, track);
1758
-        }
1759
-
1760 1727
         this.p2pJingleSession.setAnswer(answer);
1761 1728
         this.eventEmitter.emit(JitsiConferenceEvents._MEDIA_SESSION_STARTED, this.p2pJingleSession);
1762 1729
     }
@@ -1943,11 +1910,6 @@ JitsiConference.prototype._acceptJvbIncomingCall = function(
1943 1910
                         JitsiConferenceEvents._MEDIA_SESSION_ACTIVE_CHANGED,
1944 1911
                         jingleSession);
1945 1912
                 }
1946
-
1947
-                // Setup E2EE.
1948
-                for (const track of localTracks) {
1949
-                    this._setupSenderE2EEForTrack(jingleSession, track);
1950
-                }
1951 1913
             },
1952 1914
             error => {
1953 1915
                 GlobalOnErrorHandler.callErrorHandler(error);
@@ -2703,11 +2665,6 @@ JitsiConference.prototype._acceptP2PIncomingCall = function(
2703 2665
             this.eventEmitter.emit(
2704 2666
                 JitsiConferenceEvents._MEDIA_SESSION_STARTED,
2705 2667
                 this.p2pJingleSession);
2706
-
2707
-            // Setup E2EE.
2708
-            for (const track of localTracks) {
2709
-                this._setupSenderE2EEForTrack(jingleSession, track);
2710
-            }
2711 2668
         },
2712 2669
         error => {
2713 2670
             logger.error(
@@ -3383,7 +3340,9 @@ JitsiConference.prototype._sendConferenceJoinAnalyticsEvent = function() {
3383 3340
  * @returns {boolean}
3384 3341
  */
3385 3342
 JitsiConference.prototype.isE2EESupported = function() {
3386
-    return Boolean(this._e2eeCtx);
3343
+    const config = this.options.config;
3344
+
3345
+    return browser.supportsInsertableStreams() && !(config.testing && config.testing.disableE2EE);
3387 3346
 };
3388 3347
 
3389 3348
 /**
@@ -3393,13 +3352,13 @@ JitsiConference.prototype.isE2EESupported = function() {
3393 3352
  * @returns {void}
3394 3353
  */
3395 3354
 JitsiConference.prototype.setE2EEKey = function(key) {
3396
-    if (!this._e2eeCtx) {
3355
+    if (!this._e2eEncryption) {
3397 3356
         logger.warn('Cannot set E2EE key: there is no defined context, platform is likely unsupported.');
3398 3357
 
3399 3358
         return;
3400 3359
     }
3401 3360
 
3402
-    this._e2eeCtx.setKey(key);
3361
+    this._e2eEncryption.setKey(key);
3403 3362
 };
3404 3363
 
3405 3364
 /**
@@ -3480,47 +3439,3 @@ JitsiConference.prototype.lobbyApproveAccess = function(id) {
3480 3439
         this.room.getLobby().approveAccess(id);
3481 3440
     }
3482 3441
 };
3483
-
3484
-/**
3485
- * Setup E2EE for the sending side, if supported.
3486
- * Note that this is only done for the JVB Peer Connecction.
3487
- *
3488
- * @returns {void}
3489
- */
3490
-JitsiConference.prototype._setupSenderE2EEForTrack = function(session, track) {
3491
-    if (!this._e2eeCtx) {
3492
-        return;
3493
-    }
3494
-    const pc = session.peerconnection;
3495
-    const sender = pc.findSenderForTrack(track.track);
3496
-
3497
-    if (sender) {
3498
-        this._e2eeCtx.handleSender(sender, track.getType(), track.getParticipantId());
3499
-    } else {
3500
-        logger.warn(`Could not handle E2EE for local ${track.getType()} track: sender not found`);
3501
-    }
3502
-};
3503
-
3504
-/**
3505
- * Setup E2EE for the receiving side, if supported.
3506
- * Note that this is only done for the JVB Peer Connecction.
3507
- *
3508
- * @returns {void}
3509
- */
3510
-JitsiConference.prototype._setupReceiverE2EEForTrack = function(track) {
3511
-    if (!this._e2eeCtx) {
3512
-        return;
3513
-    }
3514
-    const session = track.isP2P ? this.p2pJingleSession : this.jvbJingleSession;
3515
-    const pc = session && session.peerconnection;
3516
-
3517
-    if (pc) {
3518
-        const receiver = pc.findReceiverForTrack(track.track);
3519
-
3520
-        if (receiver) {
3521
-            this._e2eeCtx.handleReceiver(receiver, track.getType(), track.getParticipantId());
3522
-        } else {
3523
-            logger.warn(`Could not handle E2EE for remote ${track.getType()} track: receiver not found`);
3524
-        }
3525
-    }
3526
-};

+ 18
- 1
modules/RTC/TraceablePeerConnection.js View File

@@ -858,7 +858,7 @@ TraceablePeerConnection.prototype._createRemoteTrack = function(
858 858
 
859 859
     remoteTracksMap.set(mediaType, remoteTrack);
860 860
 
861
-    this.eventEmitter.emit(RTCEvents.REMOTE_TRACK_ADDED, remoteTrack);
861
+    this.eventEmitter.emit(RTCEvents.REMOTE_TRACK_ADDED, remoteTrack, this);
862 862
 };
863 863
 
864 864
 /* eslint-enable max-params */
@@ -1441,6 +1441,23 @@ TraceablePeerConnection.prototype._getSSRC = function(rtcId) {
1441 1441
     return this.localSSRCs.get(rtcId);
1442 1442
 };
1443 1443
 
1444
+/**
1445
+ * Checks if given track belongs to this peerconnection instance.
1446
+ *
1447
+ * @param {JitsiLocalTrack|JitsiRemoteTrack} track - The track to be checked.
1448
+ * @returns {boolean}
1449
+ */
1450
+TraceablePeerConnection.prototype.containsTrack = function(track) {
1451
+    if (track.isLocal()) {
1452
+        return this.localTracks.has(track.rtcId);
1453
+    }
1454
+
1455
+    const participantId = track.getParticipantId();
1456
+    const remoteTracksMap = this.remoteTracks.get(participantId);
1457
+
1458
+    return Boolean(remoteTracksMap && remoteTracksMap.get(track.getType()) === track);
1459
+};
1460
+
1444 1461
 /**
1445 1462
  * Add {@link JitsiLocalTrack} to this TPC.
1446 1463
  * @param {JitsiLocalTrack} track

+ 121
- 0
modules/e2ee/E2EEncryption.js View File

@@ -0,0 +1,121 @@
1
+/* global __filename */
2
+import { getLogger } from 'jitsi-meet-logger';
3
+
4
+import * as JitsiConferenceEvents from '../../JitsiConferenceEvents';
5
+import browser from '../browser';
6
+import RTCEvents from '../../service/RTC/RTCEvents';
7
+
8
+import E2EEContext from './E2EEContext';
9
+
10
+const logger = getLogger(__filename);
11
+
12
+/**
13
+ * This module integrates {@link E2EEContext} with {@link JitsiConference} in order to enable E2E encryption.
14
+ */
15
+export class E2EEncryption {
16
+    /**
17
+     * A constructor.
18
+     * @param {JitsiConference} conference - The conference instance for which E2E encryption is to be enabled.
19
+     * @param {Object} options
20
+     * @param {string} options.salt - Salt to be used for key deviation. Check {@link E2EEContext} for more details.
21
+     */
22
+    constructor(conference, { salt }) {
23
+        this.conference = conference;
24
+        this._e2eeCtx = new E2EEContext({ salt });
25
+        this.conference.on(
26
+            JitsiConferenceEvents._MEDIA_SESSION_STARTED,
27
+            this._onMediaSessionStarted.bind(this));
28
+
29
+        // FIXME add events to TraceablePeerConnection which will allow to see when there's new receiver or sender
30
+        //  added instead of shenanigans around conference track events and track muted.
31
+        this.conference.on(
32
+            JitsiConferenceEvents.TRACK_ADDED,
33
+            track => track.isLocal() && this._onLocalTrackAdded(track));
34
+        this.conference.rtc.on(
35
+            RTCEvents.REMOTE_TRACK_ADDED,
36
+            (track, tpc) => this._setupReceiverE2EEForTrack(tpc, track));
37
+        this.conference.on(
38
+            JitsiConferenceEvents.TRACK_MUTE_CHANGED,
39
+            this._trackMuteChanged.bind(this));
40
+    }
41
+
42
+    /**
43
+     * Setups E2E encryption for the new session.
44
+     * @param {JingleSessionPC} session - the new media session.
45
+     * @private
46
+     */
47
+    _onMediaSessionStarted(session) {
48
+        const localTracks = this.conference.getLocalTracks();
49
+
50
+        for (const track of localTracks) {
51
+            this._setupSenderE2EEForTrack(session, track);
52
+        }
53
+    }
54
+
55
+    /**
56
+     * Setup E2EE on the new track that has been added to the conference, apply it on all the open peerconnections.
57
+     * @param {JitsiLocalTrack} track - the new track that's being added to the conference.
58
+     * @private
59
+     */
60
+    _onLocalTrackAdded(track) {
61
+        for (const session of this.conference._getMediaSessions()) {
62
+            this._setupSenderE2EEForTrack(session, track);
63
+        }
64
+    }
65
+
66
+    /**
67
+     * Sets the key to be used for End-To-End encryption.
68
+     *
69
+     * @param {string} key - the key to be used.
70
+     * @returns {void}
71
+     */
72
+    setKey(key) {
73
+        this._e2eeCtx.setKey(key);
74
+    }
75
+
76
+    /**
77
+     * Setup E2EE for the receiving side.
78
+     *
79
+     * @returns {void}
80
+     */
81
+    _setupReceiverE2EEForTrack(tpc, track) {
82
+        const receiver = tpc.findReceiverForTrack(track.track);
83
+
84
+        if (receiver) {
85
+            this._e2eeCtx.handleReceiver(receiver, track.getType(), track.getParticipantId());
86
+        } else {
87
+            logger.warn(`Could not handle E2EE for ${track}: receiver not found in: ${tpc}`);
88
+        }
89
+    }
90
+
91
+    /**
92
+     * Setup E2EE for the sending side.
93
+     *
94
+     * @param {JingleSessionPC} session - the session which sends the media produced by the track.
95
+     * @param {JitsiLocalTrack} track - the local track for which e2e encoder will be configured.
96
+     * @returns {void}
97
+     */
98
+    _setupSenderE2EEForTrack(session, track) {
99
+        const pc = session.peerconnection;
100
+        const sender = pc && pc.findSenderForTrack(track.track);
101
+
102
+        if (sender) {
103
+            this._e2eeCtx.handleSender(sender, track.getType(), track.getParticipantId());
104
+        } else {
105
+            logger.warn(`Could not handle E2EE for ${track}: sender not found in ${pc}`);
106
+        }
107
+    }
108
+
109
+    /**
110
+     * Setup E2EE on the sender that is created for the unmuted local video track.
111
+     * @param {JitsiLocalTrack} track - the track for which muted status has changed.
112
+     * @private
113
+     */
114
+    _trackMuteChanged(track) {
115
+        if (browser.doesVideoMuteByStreamRemove() && track.isLocal() && track.isVideoTrack() && !track.isMuted()) {
116
+            for (const session of this.conference._getMediaSessions()) {
117
+                this._setupSenderE2EEForTrack(session, track);
118
+            }
119
+        }
120
+    }
121
+}

Loading…
Cancel
Save