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/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);
-
- saveStateEvents(txn, statesdb, membersdb, room.first, room.second.state.events);
- saveStateEvents(txn, statesdb, membersdb, room.first, room.second.timeline.events);
+ auto statesdb = getStatesDb(txn, room.first);
+ auto stateskeydb = getStatesKeyDb(txn, room.first);
+ auto membersdb = getMembersDb(txn, room.first);
+
+ 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<const char *>(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<QString> &event_ids);
void roomReadStatus(const std::map<QString, bool> &status);
@@ -323,17 +335,19 @@ private:
template<class T>
void saveStateEvents(lmdb::txn &txn,
lmdb::dbi &statesdb,
+ lmdb::dbi &stateskeydb,
lmdb::dbi &membersdb,
const std::string &room_id,
const std::vector<T> &events)
{
for (const auto &e : events)
- saveStateEvent(txn, statesdb, membersdb, room_id, e);
+ saveStateEvent(txn, statesdb, stateskeydb, membersdb, room_id, e);
}
template<class T>
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(
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<std::string, std::vector<std::string>> 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<mtx::events::msg::Dummy>{}, 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
|