first draft of retrying decryption when receiving room keys

This commit is contained in:
Bruno Windels 2020-09-04 12:10:12 +02:00
parent 502ba5deea
commit fe9245dd04
3 changed files with 48 additions and 0 deletions

View file

@ -55,6 +55,8 @@ export class DeviceMessageHandler {
_applyDecryptChanges(rooms, {roomKeys}) { _applyDecryptChanges(rooms, {roomKeys}) {
const roomKeysByRoom = groupBy(roomKeys, s => s.roomId); const roomKeysByRoom = groupBy(roomKeys, s => s.roomId);
for (const [roomId, roomKeys] of roomKeysByRoom) { for (const [roomId, roomKeys] of roomKeysByRoom) {
const room = rooms.get(roomId);
room?.notifyRoomKeys(roomKeys);
} }
} }

View file

@ -30,6 +30,8 @@ export class RoomEncryption {
this._megolmBackfillCache = this._megolmDecryption.createSessionCache(); this._megolmBackfillCache = this._megolmDecryption.createSessionCache();
this._megolmSyncCache = this._megolmDecryption.createSessionCache(); this._megolmSyncCache = this._megolmDecryption.createSessionCache();
// not `event_id`, but an internal event id passed in to the decrypt methods
this._eventIdsByMissingSession = new Map();
} }
notifyTimelineClosed() { notifyTimelineClosed() {
@ -45,21 +47,56 @@ export class RoomEncryption {
async decryptNewSyncEvent(id, event, txn) { async decryptNewSyncEvent(id, event, txn) {
const payload = await this._megolmDecryption.decryptNewEvent( const payload = await this._megolmDecryption.decryptNewEvent(
this._room.id, event, this._megolmSyncCache, txn); this._room.id, event, this._megolmSyncCache, txn);
if (!payload) {
this._addMissingSessionEvent(id, event);
}
return payload; return payload;
} }
async decryptNewGapEvent(id, event, txn) { async decryptNewGapEvent(id, event, txn) {
const payload = await this._megolmDecryption.decryptNewEvent( const payload = await this._megolmDecryption.decryptNewEvent(
this._room.id, event, this._megolmBackfillCache, txn); this._room.id, event, this._megolmBackfillCache, txn);
if (!payload) {
this._addMissingSessionEvent(id, event);
}
return payload; return payload;
} }
async decryptStoredEvent(id, event, txn) { async decryptStoredEvent(id, event, txn) {
const payload = await this._megolmDecryption.decryptStoredEvent( const payload = await this._megolmDecryption.decryptStoredEvent(
this._room.id, event, this._megolmBackfillCache, txn); this._room.id, event, this._megolmBackfillCache, txn);
if (!payload) {
this._addMissingSessionEvent(id, event);
}
return payload; return payload;
} }
_addMissingSessionEvent(id, event) {
const senderKey = event.content?.["sender_key"];
const sessionId = event.content?.["session_id"];
const key = `${senderKey}|${sessionId}`;
let eventIds = this._eventIdsByMissingSession.get(key);
if (!eventIds) {
eventIds = new Set();
this._eventIdsByMissingSession.set(key, eventIds);
}
eventIds.add(id);
}
applyRoomKeys(roomKeys) {
// retry decryption with the new sessions
const idsToRetry = [];
for (const roomKey of roomKeys) {
const key = `${roomKey.senderKey}|${roomKey.sessionId}`;
const idsForSession = this._eventIdsByMissingSession.get(key);
if (idsForSession) {
this._eventIdsByMissingSession.delete(key);
idsToRetry.push(...Array.from(idsForSession));
}
}
return idsToRetry;
}
async encrypt(type, content, hsApi) { async encrypt(type, content, hsApi) {
const megolmResult = await this._megolmEncryption.encrypt(this._room.id, type, content, this._encryptionParams); const megolmResult = await this._megolmEncryption.encrypt(this._room.id, type, content, this._encryptionParams);
// share the new megolm session if needed // share the new megolm session if needed

View file

@ -45,6 +45,15 @@ export class Room extends EventEmitter {
this._roomEncryption = null; this._roomEncryption = null;
} }
notifyRoomKeys(roomKeys) {
if (this._roomEncryption) {
const internalIdsToRetry = this._roomEncryption.applyRoomKeys(roomKeys);
if (this._timeline) {
}
}
}
async _decryptSyncEntries(entries, txn) { async _decryptSyncEntries(entries, txn) {
await Promise.all(entries.map(async e => { await Promise.all(entries.map(async e => {
if (e.eventType === "m.room.encrypted") { if (e.eventType === "m.room.encrypted") {