delay backup 10s if missing session event came from sync
This commit is contained in:
parent
3aead4eae2
commit
da780d0aa2
2 changed files with 31 additions and 11 deletions
|
@ -147,6 +147,7 @@ export class Session {
|
|||
this.needsSessionBackup.set(true)
|
||||
}
|
||||
},
|
||||
clock: this._clock
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -21,8 +21,17 @@ import {makeTxnId} from "../common.js";
|
|||
|
||||
const ENCRYPTED_TYPE = "m.room.encrypted";
|
||||
|
||||
function encodeMissingSessionKey(senderKey, sessionId) {
|
||||
return `${senderKey}|${sessionId}`;
|
||||
}
|
||||
|
||||
function decodeMissingSessionKey(key) {
|
||||
const [senderKey, sessionId] = key.split("|");
|
||||
return {senderKey, sessionId};
|
||||
}
|
||||
|
||||
export class RoomEncryption {
|
||||
constructor({room, deviceTracker, olmEncryption, megolmEncryption, megolmDecryption, encryptionParams, storage, sessionBackup, notifyMissingMegolmSession}) {
|
||||
constructor({room, deviceTracker, olmEncryption, megolmEncryption, megolmDecryption, encryptionParams, storage, sessionBackup, notifyMissingMegolmSession, clock}) {
|
||||
this._room = room;
|
||||
this._deviceTracker = deviceTracker;
|
||||
this._olmEncryption = olmEncryption;
|
||||
|
@ -39,6 +48,7 @@ export class RoomEncryption {
|
|||
this._storage = storage;
|
||||
this._sessionBackup = sessionBackup;
|
||||
this._notifyMissingMegolmSession = notifyMissingMegolmSession;
|
||||
this._clock = clock;
|
||||
this._disposed = false;
|
||||
}
|
||||
|
||||
|
@ -48,8 +58,8 @@ export class RoomEncryption {
|
|||
}
|
||||
this._sessionBackup = sessionBackup;
|
||||
for(const key of this._eventIdsByMissingSession.keys()) {
|
||||
const [senderKey, sessionId] = key.split("|");
|
||||
await this._requestMissingSessionFromBackup(senderKey, sessionId);
|
||||
const {senderKey, sessionId} = decodeMissingSessionKey(key);
|
||||
await this._requestMissingSessionFromBackup(senderKey, sessionId, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -95,7 +105,7 @@ export class RoomEncryption {
|
|||
} else if (source === DecryptionSource.Retry) {
|
||||
// when retrying, we could have mixed events from at the bottom of the timeline (sync)
|
||||
// and somewhere else, so create a custom cache we use just for this operation.
|
||||
customCache = this._megolmEncryption.createSessionCache();
|
||||
customCache = this._megolmDecryption.createSessionCache();
|
||||
sessionCache = customCache;
|
||||
} else {
|
||||
throw new Error("Unknown source: " + source);
|
||||
|
@ -105,13 +115,13 @@ export class RoomEncryption {
|
|||
if (customCache) {
|
||||
customCache.dispose();
|
||||
}
|
||||
return new DecryptionPreparation(preparation, errors, {isTimelineOpen}, this);
|
||||
return new DecryptionPreparation(preparation, errors, {isTimelineOpen, source}, this);
|
||||
}
|
||||
|
||||
async _processDecryptionResults(results, errors, flags, txn) {
|
||||
for (const error of errors.values()) {
|
||||
if (error.code === "MEGOLM_NO_SESSION") {
|
||||
this._addMissingSessionEvent(error.event);
|
||||
this._addMissingSessionEvent(error.event, flags.source);
|
||||
}
|
||||
}
|
||||
if (flags.isTimelineOpen) {
|
||||
|
@ -134,25 +144,34 @@ export class RoomEncryption {
|
|||
}
|
||||
}
|
||||
|
||||
_addMissingSessionEvent(event) {
|
||||
_addMissingSessionEvent(event, source) {
|
||||
const senderKey = event.content?.["sender_key"];
|
||||
const sessionId = event.content?.["session_id"];
|
||||
const key = `${senderKey}|${sessionId}`;
|
||||
const key = encodeMissingSessionKey(senderKey, sessionId);
|
||||
let eventIds = this._eventIdsByMissingSession.get(key);
|
||||
// new missing session
|
||||
if (!eventIds) {
|
||||
this._requestMissingSessionFromBackup(senderKey, sessionId);
|
||||
this._requestMissingSessionFromBackup(senderKey, sessionId, source);
|
||||
eventIds = new Set();
|
||||
this._eventIdsByMissingSession.set(key, eventIds);
|
||||
}
|
||||
eventIds.add(event.event_id);
|
||||
}
|
||||
|
||||
async _requestMissingSessionFromBackup(senderKey, sessionId) {
|
||||
async _requestMissingSessionFromBackup(senderKey, sessionId, source) {
|
||||
if (!this._sessionBackup) {
|
||||
this._notifyMissingMegolmSession();
|
||||
return;
|
||||
}
|
||||
// if the message came from sync, wait 10s to see if the room key arrives,
|
||||
// and only after that proceed to request from backup
|
||||
if (source === DecryptionSource.Sync) {
|
||||
await this._clock.createTimeout(10000).elapsed();
|
||||
if (this._disposed || !this._eventIdsByMissingSession.has(encodeMissingSessionKey(senderKey, sessionId))) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const session = await this._sessionBackup.getSession(this._room.id, sessionId);
|
||||
if (session?.algorithm === MEGOLM_ALGORITHM) {
|
||||
|
@ -196,7 +215,7 @@ export class RoomEncryption {
|
|||
// retry decryption with the new sessions
|
||||
const retryEventIds = [];
|
||||
for (const roomKey of roomKeys) {
|
||||
const key = `${roomKey.senderKey}|${roomKey.sessionId}`;
|
||||
const key = encodeMissingSessionKey(roomKey.senderKey, roomKey.sessionId);
|
||||
const entriesForSession = this._eventIdsByMissingSession.get(key);
|
||||
if (entriesForSession) {
|
||||
this._eventIdsByMissingSession.delete(key);
|
||||
|
|
Reference in a new issue