diff --git a/src/Cache.cpp b/src/Cache.cpp index c08ecad4..f113f716 100644 --- a/src/Cache.cpp +++ b/src/Cache.cpp @@ -361,7 +361,8 @@ Cache::inboundMegolmSessionExists(const MegolmSessionIndex &index) } void -Cache::updateOutboundMegolmSession(const std::string &room_id, int message_index) +Cache::updateOutboundMegolmSession(const std::string &room_id, + mtx::crypto::OutboundGroupSessionPtr &ptr) { using namespace mtx::crypto; @@ -369,21 +370,14 @@ Cache::updateOutboundMegolmSession(const std::string &room_id, int message_index return; OutboundGroupSessionData data; - OlmOutboundGroupSession *session; - { - std::unique_lock lock(session_storage.group_outbound_mtx); - data = session_storage.group_outbound_session_data[room_id]; - session = session_storage.group_outbound_sessions[room_id].get(); - - // Update with the current message. - data.message_index = message_index; - session_storage.group_outbound_session_data[room_id] = data; - } + data.message_index = olm_outbound_group_session_message_index(ptr.get()); + data.session_id = mtx::crypto::session_id(ptr.get()); + data.session_key = mtx::crypto::session_key(ptr.get()); // Save the updated pickled data for the session. json j; j["data"] = data; - j["session"] = pickle(session, SECRET); + j["session"] = pickle(ptr.get(), SECRET); auto txn = lmdb::txn::begin(env_); lmdb::dbi_put(txn, outboundMegolmSessionDb_, lmdb::val(room_id), lmdb::val(j.dump())); @@ -399,10 +393,6 @@ Cache::dropOutboundMegolmSession(const std::string &room_id) return; { - std::unique_lock lock(session_storage.group_outbound_mtx); - session_storage.group_outbound_session_data.erase(room_id); - session_storage.group_outbound_sessions.erase(room_id); - auto txn = lmdb::txn::begin(env_); lmdb::dbi_del(txn, outboundMegolmSessionDb_, lmdb::val(room_id), nullptr); txn.commit(); @@ -424,30 +414,40 @@ Cache::saveOutboundMegolmSession(const std::string &room_id, auto txn = lmdb::txn::begin(env_); lmdb::dbi_put(txn, outboundMegolmSessionDb_, lmdb::val(room_id), lmdb::val(j.dump())); txn.commit(); - - { - std::unique_lock lock(session_storage.group_outbound_mtx); - session_storage.group_outbound_session_data[room_id] = data; - session_storage.group_outbound_sessions[room_id] = std::move(session); - } } bool Cache::outboundMegolmSessionExists(const std::string &room_id) noexcept { - std::unique_lock lock(session_storage.group_outbound_mtx); - return (session_storage.group_outbound_sessions.find(room_id) != - session_storage.group_outbound_sessions.end()) && - (session_storage.group_outbound_session_data.find(room_id) != - session_storage.group_outbound_session_data.end()); + try { + auto txn = lmdb::txn::begin(env_, nullptr, MDB_RDONLY); + lmdb::val value; + return lmdb::dbi_get(txn, outboundMegolmSessionDb_, lmdb::val(room_id), value); + } catch (std::exception &e) { + nhlog::db()->error("Failed to retrieve outbound Megolm Session: {}", e.what()); + return false; + } } OutboundGroupSessionDataRef Cache::getOutboundMegolmSession(const std::string &room_id) { - std::unique_lock lock(session_storage.group_outbound_mtx); - return OutboundGroupSessionDataRef{session_storage.group_outbound_sessions[room_id].get(), - session_storage.group_outbound_session_data[room_id]}; + try { + using namespace mtx::crypto; + + auto txn = lmdb::txn::begin(env_, nullptr, MDB_RDONLY); + lmdb::val value; + lmdb::dbi_get(txn, outboundMegolmSessionDb_, lmdb::val(room_id), value); + auto obj = json::parse(std::string_view(value.data(), value.size())); + + OutboundGroupSessionDataRef ref{}; + ref.data = obj.at("data").get(); + ref.session = unpickle(obj.at("session"), SECRET); + return ref; + } catch (std::exception &e) { + nhlog::db()->error("Failed to retrieve outbound Megolm Session: {}", e.what()); + return {}; + } } // @@ -557,44 +557,6 @@ Cache::saveOlmAccount(const std::string &data) txn.commit(); } -void -Cache::restoreSessions() -{ - using namespace mtx::crypto; - - auto txn = lmdb::txn::begin(env_, nullptr, MDB_RDONLY); - std::string key, value; - - // - // Outbound Megolm Sessions - // - { - auto cursor = lmdb::cursor::open(txn, outboundMegolmSessionDb_); - while (cursor.get(key, value, MDB_NEXT)) { - json obj; - - try { - obj = json::parse(value); - - session_storage.group_outbound_session_data[key] = - obj.at("data").get(); - - auto session = - unpickle(obj.at("session"), SECRET); - session_storage.group_outbound_sessions[key] = std::move(session); - } catch (const nlohmann::json::exception &e) { - nhlog::db()->critical( - "failed to parse outbound megolm session data: {}", e.what()); - } - } - cursor.close(); - } - - txn.commit(); - - nhlog::db()->info("sessions restored"); -} - std::string Cache::restoreOlmAccount() { @@ -4151,9 +4113,10 @@ outboundMegolmSessionExists(const std::string &room_id) noexcept return instance_->outboundMegolmSessionExists(room_id); } void -updateOutboundMegolmSession(const std::string &room_id, int message_index) +updateOutboundMegolmSession(const std::string &room_id, + mtx::crypto::OutboundGroupSessionPtr &session) { - instance_->updateOutboundMegolmSession(room_id, message_index); + instance_->updateOutboundMegolmSession(room_id, session); } void dropOutboundMegolmSession(const std::string &room_id) @@ -4228,10 +4191,4 @@ restoreOlmAccount() { return instance_->restoreOlmAccount(); } - -void -restoreSessions() -{ - return instance_->restoreSessions(); -} } // namespace cache diff --git a/src/Cache.h b/src/Cache.h index d2af9a1b..4418414d 100644 --- a/src/Cache.h +++ b/src/Cache.h @@ -241,7 +241,8 @@ getOutboundMegolmSession(const std::string &room_id); bool outboundMegolmSessionExists(const std::string &room_id) noexcept; void -updateOutboundMegolmSession(const std::string &room_id, int message_index); +updateOutboundMegolmSession(const std::string &room_id, + mtx::crypto::OutboundGroupSessionPtr &session); void dropOutboundMegolmSession(const std::string &room_id); @@ -277,9 +278,7 @@ getLatestOlmSession(const std::string &curve25519); void saveOlmAccount(const std::string &pickled); + std::string restoreOlmAccount(); - -void -restoreSessions(); } diff --git a/src/CacheCryptoStructs.h b/src/CacheCryptoStructs.h index 80153255..9f2cfe54 100644 --- a/src/CacheCryptoStructs.h +++ b/src/CacheCryptoStructs.h @@ -21,7 +21,7 @@ from_json(const nlohmann::json &obj, OutboundGroupSessionData &msg); struct OutboundGroupSessionDataRef { - OlmOutboundGroupSession *session; + mtx::crypto::OutboundGroupSessionPtr session; OutboundGroupSessionData data; }; @@ -52,16 +52,6 @@ to_json(nlohmann::json &obj, const MegolmSessionIndex &msg); void from_json(const nlohmann::json &obj, MegolmSessionIndex &msg); -struct OlmSessionStorage -{ - // Megolm sessions - std::map group_outbound_sessions; - std::map group_outbound_session_data; - - // Guards for accessing megolm sessions. - std::mutex group_outbound_mtx; -}; - struct StoredOlmSession { std::uint64_t last_message_ts = 0; diff --git a/src/Cache_p.h b/src/Cache_p.h index f9562a65..f8c4ceaf 100644 --- a/src/Cache_p.h +++ b/src/Cache_p.h @@ -235,7 +235,8 @@ public: mtx::crypto::OutboundGroupSessionPtr session); OutboundGroupSessionDataRef getOutboundMegolmSession(const std::string &room_id); bool outboundMegolmSessionExists(const std::string &room_id) noexcept; - void updateOutboundMegolmSession(const std::string &room_id, int message_index); + void updateOutboundMegolmSession(const std::string &room_id, + mtx::crypto::OutboundGroupSessionPtr &session); void dropOutboundMegolmSession(const std::string &room_id); void importSessionKeys(const mtx::crypto::ExportedSessionKeys &keys); @@ -265,8 +266,6 @@ public: void saveOlmAccount(const std::string &pickled); std::string restoreOlmAccount(); - void restoreSessions(); - signals: void newReadReceipts(const QString &room_id, const std::vector &event_ids); void roomReadStatus(const std::map &status); @@ -578,7 +577,6 @@ private: QString localUserId_; QString cacheDirectory_; - OlmSessionStorage session_storage; VerificationStorage verification_storage; }; diff --git a/src/ChatPage.cpp b/src/ChatPage.cpp index cb5f242f..dab414a9 100644 --- a/src/ChatPage.cpp +++ b/src/ChatPage.cpp @@ -526,7 +526,6 @@ ChatPage::loadStateFromCache() nhlog::db()->info("restoring state from cache"); try { - cache::restoreSessions(); olm::client()->load(cache::restoreOlmAccount(), STORAGE_SECRET_KEY); emit initializeEmptyViews(cache::client()->roomIds()); diff --git a/src/Olm.cpp b/src/Olm.cpp index 0f2d583f..88e67159 100644 --- a/src/Olm.cpp +++ b/src/Olm.cpp @@ -294,23 +294,23 @@ encrypt_group_message(const std::string &room_id, const std::string &device_id, // Always check before for existence. auto res = cache::getOutboundMegolmSession(room_id); - auto payload = olm::client()->encrypt_group_message(res.session, body.dump()); + auto payload = olm::client()->encrypt_group_message(res.session.get(), body.dump()); // Prepare the m.room.encrypted event. msg::Encrypted data; data.ciphertext = std::string((char *)payload.data(), payload.size()); data.sender_key = olm::client()->identity_keys().curve25519; - data.session_id = res.data.session_id; + data.session_id = mtx::crypto::session_id(res.session.get()); data.device_id = device_id; data.algorithm = MEGOLM_ALGO; data.relates_to = relation; data.r_relates_to = r_relation; - auto message_index = olm_outbound_group_session_message_index(res.session); - nhlog::crypto()->debug("next message_index {}", message_index); + res.data.message_index = olm_outbound_group_session_message_index(res.session.get()); + nhlog::crypto()->debug("next message_index {}", res.data.message_index); // We need to re-pickle the session after we send a message to save the new message_index. - cache::updateOutboundMegolmSession(room_id, message_index); + cache::updateOutboundMegolmSession(room_id, res.session); return data; }