Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
9810636
fix(track) Updates the mute state on remote track when ssrc gets rema…
jallamsetty1 Jan 21, 2026
916ebe5
fix(JitsiConference): handles mute state updates arriving before trac…
mihhu Jan 22, 2026
80df84a
fix: Fixes sending initial keep-alive.
damencho Jan 23, 2026
ea81361
fix(moderator) remove deprecated IE11 attachEvent fallback
dhiraj-143r Jan 26, 2026
ca79852
dispose of webworkers
TamaraFinogina Jan 29, 2026
2c5e119
add extra logs, up the version for tests
TamaraFinogina Jan 30, 2026
edbb404
bring package.json from master
TamaraFinogina Jan 30, 2026
94f9d77
Merge remote-tracking branch 'origin/master' into cleanup_webworkers
TamaraFinogina Jan 30, 2026
5d5ef5f
set test version
TamaraFinogina Jan 30, 2026
12b5a69
add worker clean up on connection failed
TamaraFinogina Jan 30, 2026
e9887c2
fix(JitsiConference) Avoids throwing an error when P2P is killed mid …
jallamsetty1 Jan 30, 2026
dd4daf9
add unsubscribe for signals, remove worker clean up from connectin fa…
TamaraFinogina Feb 2, 2026
f217dd9
fix test
TamaraFinogina Feb 2, 2026
060c84d
Revert "fix(JitsiConference): handles mute state updates arriving bef…
mihhu Feb 3, 2026
b2c5891
remove listeners, remove scypt
TamaraFinogina Feb 3, 2026
e9926fd
add missing cleanup in remotetracks
TamaraFinogina Feb 3, 2026
e6008c1
fix(xmpp) Adds logs for shard changed events
jallamsetty1 Feb 4, 2026
a189bca
chore(deps-dev): bump webpack from 5.98.0 to 5.105.0
dependabot[bot] Feb 5, 2026
7955803
bring changes from jitsi
TamaraFinogina Feb 10, 2026
cb35d09
fix lock.json
TamaraFinogina Feb 10, 2026
69edbe6
remove moderator, the first person ntered the meeting will generate a…
TamaraFinogina Feb 10, 2026
70e5445
add version
TamaraFinogina Feb 10, 2026
19807b4
use ===
TamaraFinogina Feb 10, 2026
8f41fc0
use ===
TamaraFinogina Feb 10, 2026
2ef610b
add sorting
TamaraFinogina Feb 10, 2026
7820ba8
Merge pull request #107 from internxt/remove_moderator
TamaraFinogina Feb 10, 2026
18eeee5
revert version upgrade
TamaraFinogina Feb 10, 2026
f076012
Merge pull request #103 from internxt/cleanup_webworkers
TamaraFinogina Feb 10, 2026
a68980b
Merge pull request #106 from internxt/updates_from_jitsi
TamaraFinogina Feb 10, 2026
d1173e7
keep the message formating
TamaraFinogina Feb 11, 2026
379cbcc
add logs
TamaraFinogina Feb 11, 2026
7c2551b
remove useless if
TamaraFinogina Feb 11, 2026
1849574
remove log
TamaraFinogina Feb 11, 2026
26f024e
up webpack, remove object tests
TamaraFinogina Feb 11, 2026
0ea909b
fix typo
TamaraFinogina Feb 12, 2026
0647832
merge new_version
TamaraFinogina Feb 12, 2026
ed38157
fix lock file
TamaraFinogina Feb 12, 2026
d5253d1
Merge pull request #109 from internxt/keep_formating_chat
TamaraFinogina Feb 12, 2026
d6d328b
run npm audit fix
TamaraFinogina Feb 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions JitsiConference.ts
Original file line number Diff line number Diff line change
Expand Up @@ -522,7 +522,7 @@ export default class JitsiConference extends Listenable {
this._iceRestarts = 0;
this._unsubscribers = [];

this.eventEmitter.on(JitsiConferenceEvents.E2EE_CHAT_KEY_RECEIVED, key => {
this.eventEmitter.once(JitsiConferenceEvents.E2EE_CHAT_KEY_RECEIVED, key => {
this.room.eventEmitter.emit(JitsiConferenceEvents.E2EE_CHAT_KEY_RECEIVED, key);
});
}
Expand Down Expand Up @@ -1243,7 +1243,7 @@ export default class JitsiConference extends Listenable {

this.p2pJingleSession.invite(localTracks)
.then(() => {
this.p2pJingleSession.addEventListener(MediaSessionEvents.VIDEO_CODEC_CHANGED, () => {
this.p2pJingleSession?.addEventListener(MediaSessionEvents.VIDEO_CODEC_CHANGED, () => {
this.eventEmitter.emit(JitsiConferenceEvents.VIDEO_CODEC_CHANGED);
});
})
Expand Down Expand Up @@ -2482,6 +2482,13 @@ export default class JitsiConference extends Listenable {
);
}

public cleanUpWebWorkers(): void {
if (this._e2eEncryption) {
this._e2eEncryption.dispose();
this._e2eEncryption = null;
}
}

/**
* Leaves the conference.
* @param {string|undefined} reason - The reason for leaving the conference.
Expand All @@ -2508,6 +2515,8 @@ export default class JitsiConference extends Listenable {
this.statistics.dispose();
}

this.cleanUpWebWorkers();

this._delayedIceFailed?.cancel();

this._maybeClearSITimeout();
Expand Down
5 changes: 3 additions & 2 deletions modules/RTC/JitsiRemoteTrack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,6 @@ export default class JitsiRemoteTrack extends JitsiTrack {
public isP2P: boolean;
public rtcId: Nullable<string>;
public inputTensor: Nullable<any>;
public imageDataOutput: Nullable<ImageData>;
public dataOutput: Nullable<ImageData>;
public input: Nullable<any>;
public frame: Nullable<ImageBitmap>;
Expand Down Expand Up @@ -186,7 +185,6 @@ export default class JitsiRemoteTrack extends JitsiTrack {
this._decodedTrack = null;
// Steam objects
this.inputTensor = null;
this.imageDataOutput = null;
this.dataOutput = null;
this.input = {
input: null
Expand Down Expand Up @@ -720,6 +718,9 @@ export default class JitsiRemoteTrack extends JitsiTrack {
this.attachoff = false;
this.width = 0;
this.height = 0;
this.dataOutput = null;
this.input = null;
this.inputBuffer = null;
if (this.disposed) {
return;
}
Expand Down
27 changes: 23 additions & 4 deletions modules/e2ee-internxt/E2EEContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ const logger = getLogger('modules/e2ee-internxt/E2EEContext');
*/
export default class E2EEcontext extends Listenable {
private readonly _worker: Worker;
private _workerUrl: string | null = null;
private scriptEl: HTMLScriptElement | null = null;

constructor() {
super();
Expand All @@ -31,15 +33,15 @@ export default class E2EEcontext extends Listenable {
}

private _initializeWorker(): Worker {
const scriptEl = document.querySelector<HTMLScriptElement>(
this.scriptEl = document.querySelector<HTMLScriptElement>(
'script[src*="lib-jitsi-meet"]',
);
let baseUrl = '';

if (scriptEl) {
const idx = scriptEl.src.lastIndexOf('/');
if (this.scriptEl) {
const idx = this.scriptEl.src.lastIndexOf('/');

baseUrl = `${scriptEl.src.substring(0, idx)}/`;
baseUrl = `${this.scriptEl.src.substring(0, idx)}/`;
}

let workerUrl = `${baseUrl}lib-jitsi-meet.e2ee-worker.js`;
Expand All @@ -50,6 +52,7 @@ export default class E2EEcontext extends Listenable {
});

workerUrl = URL.createObjectURL(workerBlob);
this._workerUrl = workerUrl;
}

return new Worker(workerUrl, { name: 'E2EE Worker' });
Expand All @@ -59,6 +62,22 @@ export default class E2EEcontext extends Listenable {
this.emit('sasUpdated', sas);
}

/**
* Disposes of the worker and cleans up resources.
*/
dispose() {
logger.info('E2EE: Disposing E2EE context and terminating worker');

this.cleanupAll();
this._worker.terminate();
if (this._workerUrl) {
URL.revokeObjectURL(this._workerUrl);
this._workerUrl = null;
}
this.scriptEl?.remove();
this.scriptEl = null;
}

cleanup(participantId: string) {
this._worker.postMessage({
operation: 'cleanup',
Expand Down
4 changes: 4 additions & 0 deletions modules/e2ee-internxt/E2EEncryption.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ export class E2EEncryption {
return this._keyHandler.isEnabled();
}

dispose() {
this._keyHandler.dispose();
}

/**
* Enables / disables End-To-End encryption.
*
Expand Down
157 changes: 126 additions & 31 deletions modules/e2ee-internxt/ManagedKeyHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { JitsiConferenceEvents } from '../../JitsiConferenceEvents';
import JitsiParticipant from '../../JitsiParticipant';
import { RTCEvents } from '../../service/RTC/RTCEvents';
import JitsiLocalTrack from '../RTC/JitsiLocalTrack';
import JitsiTrack from '../RTC/JitsiTrack';
import TraceablePeerConnection from '../RTC/TraceablePeerConnection';
import browser from '../browser';
import Listenable from '../util/Listenable';
Expand Down Expand Up @@ -63,6 +64,17 @@ export class ManagedKeyHandler extends Listenable {
_olmAdapter: OlmAdapter;
_conferenceJoined: boolean;

onUserJoined: EventListener;
onUserLeft: EventListener;
onEndpointMessageReceived: EventListener;
onConferenceJoined: EventListener;
onConferenceLeft: EventListener;
onMediaSessionStarted: EventListener;
onTrackAdded: EventListener;
onRemoteTrackAdded: EventListener;
onTrackMuteChanged: EventListener;
onSasUpdated: EventListener;

/**
* Build a new AutomaticKeyHandler instance, which will be used in a given conference.
*/
Expand All @@ -83,59 +95,77 @@ export class ManagedKeyHandler extends Listenable {
this._participantEventQueue = [];
this._processingEvents = false;

this.onUserJoined = this._onParticipantJoined.bind(this);
this.onUserLeft = this._onParticipantLeft.bind(this);
this.onEndpointMessageReceived = this._onEndpointMessageReceived.bind(this);
this.onConferenceLeft = this._onConferenceLeft.bind(this);
this.onConferenceJoined = () => this._conferenceJoined = true;
this.onMediaSessionStarted = this._onMediaSessionStarted.bind(this);
this.onTrackAdded = this._onTrackAddedHandler.bind(this);
this.onRemoteTrackAdded = this._setupReceiverE2EEForTrack.bind(this);
this.onTrackMuteChanged = this._trackMuteChanged.bind(this);
this.onSasUpdated = this.sasUpdatedHandler.bind(this);

this.conference.on(
JitsiConferenceEvents.USER_JOINED,
this._onParticipantJoined.bind(this),
this.onUserJoined,
);
this.conference.on(
JitsiConferenceEvents.USER_LEFT,
this._onParticipantLeft.bind(this),
this.onUserLeft,
);
this.conference.on(
JitsiConferenceEvents.ENDPOINT_MESSAGE_RECEIVED,
this._onEndpointMessageReceived.bind(this),
this.onEndpointMessageReceived,
);
this.conference.on(
JitsiConferenceEvents.CONFERENCE_LEFT,
this._onConferenceLeft.bind(this),
this.onConferenceLeft,
);
this.conference.on(
JitsiConferenceEvents.CONFERENCE_JOINED,
this.onConferenceJoined
);
this.conference.on(JitsiConferenceEvents.CONFERENCE_JOINED, () => {
this._conferenceJoined = true;
});
this.conference.on(
JitsiConferenceEvents._MEDIA_SESSION_STARTED,
this._onMediaSessionStarted.bind(this),
this.onMediaSessionStarted,
);
this.conference.on(
JitsiConferenceEvents.TRACK_ADDED,
(track: JitsiLocalTrack) =>
track.isLocal() && this._onLocalTrackAdded(track),
this.onTrackAdded,
);
this.conference.rtc.on(
RTCEvents.REMOTE_TRACK_ADDED,
(track: JitsiLocalTrack, tpc: TraceablePeerConnection) =>
this._setupReceiverE2EEForTrack(tpc, track),
this.onRemoteTrackAdded,
);
this.conference.on(
JitsiConferenceEvents.TRACK_MUTE_CHANGED,
this._trackMuteChanged.bind(this),
this.onTrackMuteChanged,
);

this._conferenceJoined = false;

this._olmAdapter = new OlmAdapter(this.myID);

this.e2eeCtx.on('sasUpdated', (sasStr: string) => {
const sas = generateEmojiSas(sasStr);

this.log('info', `Emitting SAS: ${sas.join(', ')}`);
this.conference.eventEmitter.emit(
JitsiConferenceEvents.E2EE_SAS_AVAILABLE,
sas,
);
});
this.e2eeCtx.on('sasUpdated', this.onSasUpdated);
}

private _onTrackAddedHandler = (track: JitsiTrack) => {
if (track.isLocal()) {
this._onLocalTrackAdded(track as JitsiLocalTrack);
}
};

private sasUpdatedHandler = (sasStr: string) => {
const sas = generateEmojiSas(sasStr);

this.log('info', `Emitting SAS: ${sas.join(', ')}`);
this.conference.eventEmitter.emit(
JitsiConferenceEvents.E2EE_SAS_AVAILABLE,
sas,
);
};

private async init() {
await this._olmAdapter.init();
this.initialized = true;
Expand Down Expand Up @@ -222,8 +252,8 @@ export class ManagedKeyHandler extends Listenable {
* @private
*/
private _setupReceiverE2EEForTrack(
tpc: TraceablePeerConnection,
track: JitsiLocalTrack,
tpc: TraceablePeerConnection,
) {
if (!this.enabled) {
return;
Expand Down Expand Up @@ -390,8 +420,8 @@ export class ManagedKeyHandler extends Listenable {
}

private _onConferenceLeft() {
this.clearAllSessions();
this._olmAdapter.clearMySession();
this._conferenceJoined = false;
this.dispose();
}

private async updateKey(pId: string, ciphertext: string, pqCiphertext: string) {
Expand All @@ -410,12 +440,20 @@ export class ManagedKeyHandler extends Listenable {
}
}

private noOtherModerators(): boolean {
if (this.conference.isModerator()) return true;

private isThisParticipantFirst(pId: string): boolean {
const localParticipantId = this.myID;
const participants = this.conference.getParticipants();
const list = participants.filter(
participant =>
(participant.hasFeature(FEATURE_E2EE)
|| participant.getProperty('e2ee.enabled') === 'true')
&& localParticipantId > participant.getId(),
).sort((a, b) => a.getId().localeCompare(b.getId()));

if (list.length === 0) return false;
const firstParticipant = list[0].getId();

return !participants.some(p => p.isModerator());
return firstParticipant === pId;
}

private async _onEndpointMessageReceived(participant: JitsiParticipant, payload) {
Expand Down Expand Up @@ -516,7 +554,7 @@ export class ManagedKeyHandler extends Listenable {
pId,
);

if (!this.askedForChatKey && (participant.isModerator() || this.noOtherModerators())) {
if (!this.askedForChatKey && this.isThisParticipantFirst(pId)) {
this.log('info', `Requesting chat key from ${pId}.`);
this._sendMessage(
OLM_MESSAGE_TYPES.CHAT_KEY_REQUEST,
Expand Down Expand Up @@ -787,7 +825,7 @@ export class ManagedKeyHandler extends Listenable {
`Should send session-init to IDs: [ ${list.map(p => p.getId())}]`,
);

if (!this.askedForChatKey && list.length == 0) {
if (!this.askedForChatKey && list.length === 0) {
this.log('info', 'Generated chat keys');
const chatKeyECC = genSymmetricKey();
const chatKeyPQ = genSymmetricKey();
Expand Down Expand Up @@ -853,6 +891,63 @@ export class ManagedKeyHandler extends Listenable {
await this.initSessions;
}

dispose() {
this._olmAdapter.clearMySession();
this.clearAllSessions();
this.conference.off(
JitsiConferenceEvents.USER_JOINED,
this.onUserJoined,
);
this.conference.off(
JitsiConferenceEvents.USER_LEFT,
this.onUserLeft,
);
this.conference.off(
JitsiConferenceEvents.ENDPOINT_MESSAGE_RECEIVED,
this.onEndpointMessageReceived,
);
this.conference.off(
JitsiConferenceEvents.CONFERENCE_LEFT,
this.onConferenceLeft,
);
this.conference.off(
JitsiConferenceEvents.CONFERENCE_JOINED,
this.onConferenceJoined
);
this.conference.off(
JitsiConferenceEvents._MEDIA_SESSION_STARTED,
this.onMediaSessionStarted,
);
this.conference.off(
JitsiConferenceEvents.TRACK_ADDED,
this.onTrackAdded,
);
this.conference.rtc.off(
RTCEvents.REMOTE_TRACK_ADDED,
this.onRemoteTrackAdded,
);
this.conference.off(
JitsiConferenceEvents.TRACK_MUTE_CHANGED,
this.onTrackMuteChanged,
);
this.e2eeCtx.off('sasUpdated', this.onSasUpdated);

this.onUserJoined = null;
this.onUserLeft = null;
this.onEndpointMessageReceived = null;
this.onConferenceJoined = null;
this.onConferenceLeft = null;
this.onMediaSessionStarted = null;
this.onTrackAdded = null;
this.onRemoteTrackAdded = null;
this.onTrackMuteChanged = null;
this.onSasUpdated = null;

this.e2eeCtx.dispose();
this._reqs.clear();
this.update.clear();
}

/**
* Disables End-To-End encryption.
*/
Expand Down
1 change: 1 addition & 0 deletions modules/e2ee-internxt/OlmAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ export class OlmAdapter {

async clearMySession() {
this._olmAccount?.free();
this._olmDataMap.clear();
}

async createPQsessionInitMessage(
Expand Down
Loading