From 8108d98fa744129af809b1b193066d671e9ae252 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Sat, 3 Apr 2021 13:15:35 +0200 Subject: [PATCH 1/2] Store state events with state keys --- src/Cache.cpp | 11 +++++++---- src/Cache_p.h | 43 +++++++++++++++++++++++++++++++++++++++---- 2 files changed, 46 insertions(+), 8 deletions(-) diff --git a/src/Cache.cpp b/src/Cache.cpp index f3407e48..3e1057c0 100644 --- a/src/Cache.cpp +++ b/src/Cache.cpp @@ -1181,11 +1181,14 @@ Cache::saveState(const mtx::responses::Sync &res) // Save joined rooms for (const auto &room : res.rooms.join) { - auto statesdb = getStatesDb(txn, room.first); - auto membersdb = getMembersDb(txn, room.first); + auto statesdb = getStatesDb(txn, room.first); + auto stateskeydb = getStatesKeyDb(txn, room.first); + auto membersdb = getMembersDb(txn, room.first); - saveStateEvents(txn, statesdb, membersdb, room.first, room.second.state.events); - saveStateEvents(txn, statesdb, membersdb, room.first, room.second.timeline.events); + saveStateEvents( + txn, statesdb, stateskeydb, membersdb, room.first, room.second.state.events); + saveStateEvents( + txn, statesdb, stateskeydb, membersdb, room.first, room.second.timeline.events); saveTimelineMessages(txn, room.first, room.second.timeline); diff --git a/src/Cache_p.h b/src/Cache_p.h index 62927923..51dc4cbc 100644 --- a/src/Cache_p.h +++ b/src/Cache_p.h @@ -273,6 +273,18 @@ public: return false; } + static int compare_state_key(const MDB_val *a, const MDB_val *b) + { + auto get_skey = [](const MDB_val *v) { + return nlohmann::json::parse( + std::string_view(static_cast(v->mv_data), + v->mv_size)) + .value("key", ""); + }; + + return get_skey(a).compare(get_skey(b)); + } + signals: void newReadReceipts(const QString &room_id, const std::vector &event_ids); void roomReadStatus(const std::map &status); @@ -323,17 +335,19 @@ private: template void saveStateEvents(lmdb::txn &txn, lmdb::dbi &statesdb, + lmdb::dbi &stateskeydb, lmdb::dbi &membersdb, const std::string &room_id, const std::vector &events) { for (const auto &e : events) - saveStateEvent(txn, statesdb, membersdb, room_id, e); + saveStateEvent(txn, statesdb, stateskeydb, membersdb, room_id, e); } template void saveStateEvent(lmdb::txn &txn, lmdb::dbi &statesdb, + lmdb::dbi &stateskeydb, lmdb::dbi &membersdb, const std::string &room_id, const T &event) @@ -371,9 +385,22 @@ private: } std::visit( - [&txn, &statesdb](auto e) { - if (isStateEvent(e) && e.type != EventType::Unsupported) - statesdb.put(txn, to_string(e.type), json(e).dump()); + [&txn, &statesdb, &stateskeydb](auto e) { + if constexpr (isStateEvent(e)) + if (e.type != EventType::Unsupported) { + if (e.state_key.empty()) + statesdb.put( + txn, to_string(e.type), json(e).dump()); + else + stateskeydb.put( + txn, + to_string(e.type), + json::object({ + {"key", e.state_key}, + {"id", e.event_id}, + }) + .dump()); + } }, event); } @@ -461,6 +488,14 @@ private: return lmdb::dbi::open(txn, std::string(room_id + "/state").c_str(), MDB_CREATE); } + lmdb::dbi getStatesKeyDb(lmdb::txn &txn, const std::string &room_id) + { + auto db = + lmdb::dbi::open(txn, std::string(room_id + "/state_by_key").c_str(), MDB_CREATE); + lmdb::dbi_set_dupsort(txn, db, compare_state_key); + return db; + } + lmdb::dbi getAccountDataDb(lmdb::txn &txn, const std::string &room_id) { return lmdb::dbi::open( From 99314c948edf1258829b0b6772664dc448625044 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Tue, 13 Apr 2021 23:42:18 +0200 Subject: [PATCH 2/2] Fix broken olm channels automatically --- CMakeLists.txt | 2 +- io.github.NhekoReborn.Nheko.yaml | 2 +- src/Olm.cpp | 20 ++++++++++++++++++++ 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ca66e167..b208756e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -361,7 +361,7 @@ if(USE_BUNDLED_MTXCLIENT) FetchContent_Declare( MatrixClient GIT_REPOSITORY https://github.com/Nheko-Reborn/mtxclient.git - GIT_TAG 808605299937203696a572c585a51509b1de28cf + GIT_TAG 5b7654c5d4512abc38806a0f44efc199029ceef4 ) set(BUILD_LIB_EXAMPLES OFF CACHE INTERNAL "") set(BUILD_LIB_TESTS OFF CACHE INTERNAL "") diff --git a/io.github.NhekoReborn.Nheko.yaml b/io.github.NhekoReborn.Nheko.yaml index f5191271..3db57d57 100644 --- a/io.github.NhekoReborn.Nheko.yaml +++ b/io.github.NhekoReborn.Nheko.yaml @@ -148,7 +148,7 @@ modules: buildsystem: cmake-ninja name: mtxclient sources: - - commit: 7194b4f058406b1c10d3741d83abcf2d8963d849 + - commit: 5b7654c5d4512abc38806a0f44efc199029ceef4 type: git url: https://github.com/Nheko-Reborn/mtxclient.git - config-opts: diff --git a/src/Olm.cpp b/src/Olm.cpp index 895afee4..95aae99a 100644 --- a/src/Olm.cpp +++ b/src/Olm.cpp @@ -359,6 +359,26 @@ handle_olm_message(const OlmMessage &msg) return; } } + + try { + auto otherUserDeviceKeys = cache::userKeys(msg.sender); + + if (!otherUserDeviceKeys) + return; + + std::map> targets; + for (auto [device_id, key] : otherUserDeviceKeys->device_keys) { + if (key.keys.at("curve25519:" + device_id) == msg.sender_key) + targets[msg.sender].push_back(device_id); + } + + send_encrypted_to_device_messages( + targets, mtx::events::DeviceEvent{}, true); + nhlog::crypto()->info( + "Recovering from broken olm channel with {}:{}", msg.sender, msg.sender_key); + } catch (std::exception &e) { + nhlog::crypto()->error("Failed to recover from broken olm sessions: {}", e.what()); + } } nlohmann::json