From d53b5eefb393a709bc202f42d56136c430cf69d5 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 23 Sep 2020 17:59:42 +0200 Subject: [PATCH] fill in the blanks --- src/matrix/e2ee/RoomEncryption.js | 21 +++++++++++++++++-- src/matrix/room/Room.js | 14 +++++++++---- src/matrix/room/RoomSummary.js | 6 ++++++ .../timeline/persistence/TimelineReader.js | 9 +++++--- 4 files changed, 41 insertions(+), 9 deletions(-) diff --git a/src/matrix/e2ee/RoomEncryption.js b/src/matrix/e2ee/RoomEncryption.js index 7b45a60c..dac362c0 100644 --- a/src/matrix/e2ee/RoomEncryption.js +++ b/src/matrix/e2ee/RoomEncryption.js @@ -222,9 +222,26 @@ export class RoomEncryption { return eventIds; } + /** + * caches mapping of session to event id of all encrypted candidates + * and filters to return only the candidates for the given room key + */ findAndCacheEntriesForRoomKey(roomKey, candidateEntries) { - // add all to _missingSessionCandidates - // filter messages to roomKey + const matches = []; + + for (const entry of candidateEntries) { + if (entry.eventType === ENCRYPTED_TYPE) { + this._missingSessionCandidates.addEvent(entry.event); + const senderKey = entry.event?.content?.["sender_key"]; + const sessionId = entry.event?.content?.["session_id"]; + if (senderKey === roomKey.senderKey && sessionId === roomKey.sessionId) { + matches.push(entry); + } + } + } + + return matches; + } async encrypt(type, content, hsApi) { diff --git a/src/matrix/room/Room.js b/src/matrix/room/Room.js index c9a490cb..a0cea456 100644 --- a/src/matrix/room/Room.js +++ b/src/matrix/room/Room.js @@ -15,9 +15,10 @@ limitations under the License. */ import {EventEmitter} from "../../utils/EventEmitter.js"; -import {RoomSummary, needsHeroes} from "./RoomSummary.js"; +import {RoomSummary} from "./RoomSummary.js"; import {SyncWriter} from "./timeline/persistence/SyncWriter.js"; import {GapWriter} from "./timeline/persistence/GapWriter.js"; +import {readRawTimelineEntriesWithTxn} from "./timeline/persistence/TimelineReader.js"; import {Timeline} from "./timeline/Timeline.js"; import {FragmentIdComparer} from "./timeline/FragmentIdComparer.js"; import {SendQueue} from "./sending/SendQueue.js"; @@ -26,6 +27,8 @@ import {fetchOrLoadMembers} from "./members/load.js"; import {MemberList} from "./members/MemberList.js"; import {Heroes} from "./members/Heroes.js"; import {EventEntry} from "./timeline/entries/EventEntry.js"; +import {EventKey} from "./timeline/EventKey.js"; +import {Direction} from "./timeline/Direction.js"; import {DecryptionSource} from "../e2ee/common.js"; const EVENT_ENCRYPTED_TYPE = "m.room.encrypted"; @@ -54,10 +57,13 @@ export class Room extends EventEmitter { _readRetryDecryptCandidateEntries(sinceEventKey, txn) { if (sinceEventKey) { - return readFromWithTxn(sinceEventKey, Direction.Forward, Number.MAX_SAFE_INTEGER, txn); + return readRawTimelineEntriesWithTxn(sinceEventKey, Direction.Forward, Number.MAX_SAFE_INTEGER, txn); } else { - // all messages for room - return readFromWithTxn(this._syncWriter.lastMessageKey, Direction.Backward, Number.MAX_SAFE_INTEGER, txn); + // all messages for room ... + // if you haven't decrypted any message in a room yet, + // it's unlikely you will have tons of them. + // so this should be fine as a last resort + return readRawTimelineEntriesWithTxn(this._syncWriter.lastMessageKey, Direction.Backward, Number.MAX_SAFE_INTEGER, txn); } } diff --git a/src/matrix/room/RoomSummary.js b/src/matrix/room/RoomSummary.js index 1ec55d5c..392bf755 100644 --- a/src/matrix/room/RoomSummary.js +++ b/src/matrix/room/RoomSummary.js @@ -131,6 +131,12 @@ function processTimelineEvent(data, eventEntry, isInitialSync, isTimelineOpen, o try { hasLargerEventKey = eventEntry.compare(data.lastDecryptedEventKey) > 0; } catch (err) { + // TODO: load the fragments in between here? + // this could happen if an earlier event gets decrypted that + // is in a fragment different from the live one and the timeline is not open. + // In this case, we will just read too many events once per app load + // and then keep the mapping in memory. When eventually an event is decrypted in + // the live fragment, this should stop failing and the event key will be written. hasLargerEventKey = false; } } diff --git a/src/matrix/room/timeline/persistence/TimelineReader.js b/src/matrix/room/timeline/persistence/TimelineReader.js index b2bb8fbf..bf4d2766 100644 --- a/src/matrix/room/timeline/persistence/TimelineReader.js +++ b/src/matrix/room/timeline/persistence/TimelineReader.js @@ -37,8 +37,11 @@ class ReaderRequest { } } - -export async function readFromWithTxn(eventKey, direction, amount, r, txn) { +/** + * Raw because it doesn't do decryption and in the future it should not read relations either. + * It is just about reading entries and following fragment links + */ +export async function readRawTimelineEntriesWithTxn(eventKey, direction, amount, r, txn) { let entries = []; const timelineStore = txn.timelineEvents; const fragmentStore = txn.timelineFragments; @@ -130,7 +133,7 @@ export class TimelineReader { } async _readFrom(eventKey, direction, amount, r, txn) { - const entries = readFromWithTxn(eventKey, direction, amount, r, txn); + const entries = readRawTimelineEntriesWithTxn(eventKey, direction, amount, r, txn); if (this._decryptEntries) { r.decryptRequest = this._decryptEntries(entries, txn); try {