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)
|
this.needsSessionBackup.set(true)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
clock: this._clock
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,8 +21,17 @@ import {makeTxnId} from "../common.js";
|
||||||
|
|
||||||
const ENCRYPTED_TYPE = "m.room.encrypted";
|
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 {
|
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._room = room;
|
||||||
this._deviceTracker = deviceTracker;
|
this._deviceTracker = deviceTracker;
|
||||||
this._olmEncryption = olmEncryption;
|
this._olmEncryption = olmEncryption;
|
||||||
|
@ -39,6 +48,7 @@ export class RoomEncryption {
|
||||||
this._storage = storage;
|
this._storage = storage;
|
||||||
this._sessionBackup = sessionBackup;
|
this._sessionBackup = sessionBackup;
|
||||||
this._notifyMissingMegolmSession = notifyMissingMegolmSession;
|
this._notifyMissingMegolmSession = notifyMissingMegolmSession;
|
||||||
|
this._clock = clock;
|
||||||
this._disposed = false;
|
this._disposed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,8 +58,8 @@ export class RoomEncryption {
|
||||||
}
|
}
|
||||||
this._sessionBackup = sessionBackup;
|
this._sessionBackup = sessionBackup;
|
||||||
for(const key of this._eventIdsByMissingSession.keys()) {
|
for(const key of this._eventIdsByMissingSession.keys()) {
|
||||||
const [senderKey, sessionId] = key.split("|");
|
const {senderKey, sessionId} = decodeMissingSessionKey(key);
|
||||||
await this._requestMissingSessionFromBackup(senderKey, sessionId);
|
await this._requestMissingSessionFromBackup(senderKey, sessionId, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,7 +105,7 @@ export class RoomEncryption {
|
||||||
} else if (source === DecryptionSource.Retry) {
|
} else if (source === DecryptionSource.Retry) {
|
||||||
// when retrying, we could have mixed events from at the bottom of the timeline (sync)
|
// 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.
|
// and somewhere else, so create a custom cache we use just for this operation.
|
||||||
customCache = this._megolmEncryption.createSessionCache();
|
customCache = this._megolmDecryption.createSessionCache();
|
||||||
sessionCache = customCache;
|
sessionCache = customCache;
|
||||||
} else {
|
} else {
|
||||||
throw new Error("Unknown source: " + source);
|
throw new Error("Unknown source: " + source);
|
||||||
|
@ -105,13 +115,13 @@ export class RoomEncryption {
|
||||||
if (customCache) {
|
if (customCache) {
|
||||||
customCache.dispose();
|
customCache.dispose();
|
||||||
}
|
}
|
||||||
return new DecryptionPreparation(preparation, errors, {isTimelineOpen}, this);
|
return new DecryptionPreparation(preparation, errors, {isTimelineOpen, source}, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
async _processDecryptionResults(results, errors, flags, txn) {
|
async _processDecryptionResults(results, errors, flags, txn) {
|
||||||
for (const error of errors.values()) {
|
for (const error of errors.values()) {
|
||||||
if (error.code === "MEGOLM_NO_SESSION") {
|
if (error.code === "MEGOLM_NO_SESSION") {
|
||||||
this._addMissingSessionEvent(error.event);
|
this._addMissingSessionEvent(error.event, flags.source);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (flags.isTimelineOpen) {
|
if (flags.isTimelineOpen) {
|
||||||
|
@ -134,25 +144,34 @@ export class RoomEncryption {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_addMissingSessionEvent(event) {
|
_addMissingSessionEvent(event, source) {
|
||||||
const senderKey = event.content?.["sender_key"];
|
const senderKey = event.content?.["sender_key"];
|
||||||
const sessionId = event.content?.["session_id"];
|
const sessionId = event.content?.["session_id"];
|
||||||
const key = `${senderKey}|${sessionId}`;
|
const key = encodeMissingSessionKey(senderKey, sessionId);
|
||||||
let eventIds = this._eventIdsByMissingSession.get(key);
|
let eventIds = this._eventIdsByMissingSession.get(key);
|
||||||
// new missing session
|
// new missing session
|
||||||
if (!eventIds) {
|
if (!eventIds) {
|
||||||
this._requestMissingSessionFromBackup(senderKey, sessionId);
|
this._requestMissingSessionFromBackup(senderKey, sessionId, source);
|
||||||
eventIds = new Set();
|
eventIds = new Set();
|
||||||
this._eventIdsByMissingSession.set(key, eventIds);
|
this._eventIdsByMissingSession.set(key, eventIds);
|
||||||
}
|
}
|
||||||
eventIds.add(event.event_id);
|
eventIds.add(event.event_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
async _requestMissingSessionFromBackup(senderKey, sessionId) {
|
async _requestMissingSessionFromBackup(senderKey, sessionId, source) {
|
||||||
if (!this._sessionBackup) {
|
if (!this._sessionBackup) {
|
||||||
this._notifyMissingMegolmSession();
|
this._notifyMissingMegolmSession();
|
||||||
return;
|
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 {
|
try {
|
||||||
const session = await this._sessionBackup.getSession(this._room.id, sessionId);
|
const session = await this._sessionBackup.getSession(this._room.id, sessionId);
|
||||||
if (session?.algorithm === MEGOLM_ALGORITHM) {
|
if (session?.algorithm === MEGOLM_ALGORITHM) {
|
||||||
|
@ -196,7 +215,7 @@ export class RoomEncryption {
|
||||||
// retry decryption with the new sessions
|
// retry decryption with the new sessions
|
||||||
const retryEventIds = [];
|
const retryEventIds = [];
|
||||||
for (const roomKey of roomKeys) {
|
for (const roomKey of roomKeys) {
|
||||||
const key = `${roomKey.senderKey}|${roomKey.sessionId}`;
|
const key = encodeMissingSessionKey(roomKey.senderKey, roomKey.sessionId);
|
||||||
const entriesForSession = this._eventIdsByMissingSession.get(key);
|
const entriesForSession = this._eventIdsByMissingSession.get(key);
|
||||||
if (entriesForSession) {
|
if (entriesForSession) {
|
||||||
this._eventIdsByMissingSession.delete(key);
|
this._eventIdsByMissingSession.delete(key);
|
||||||
|
|
Reference in a new issue