diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2f83a865..4f6a6a38 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -340,7 +340,7 @@ if(USE_BUNDLED_MTXCLIENT)
FetchContent_Declare(
MatrixClient
GIT_REPOSITORY https://github.com/Nheko-Reborn/mtxclient.git
- GIT_TAG ad5575bc24089dc385e97d9ace026414b618775c
+ GIT_TAG da9958e14e035fbf22d498074d381b2ea0092a9d
)
FetchContent_MakeAvailable(MatrixClient)
else()
diff --git a/io.github.NhekoReborn.Nheko.json b/io.github.NhekoReborn.Nheko.json
index 59f4fa46..5f08dee0 100644
--- a/io.github.NhekoReborn.Nheko.json
+++ b/io.github.NhekoReborn.Nheko.json
@@ -146,7 +146,7 @@
"name": "mtxclient",
"sources": [
{
- "commit": "ad5575bc24089dc385e97d9ace026414b618775c",
+ "commit": "da9958e14e035fbf22d498074d381b2ea0092a9d",
"type": "git",
"url": "https://github.com/Nheko-Reborn/mtxclient.git"
}
diff --git a/src/ChatPage.cpp b/src/ChatPage.cpp
index e61df263..8b6f1123 100644
--- a/src/ChatPage.cpp
+++ b/src/ChatPage.cpp
@@ -1250,6 +1250,12 @@ ChatPage::unbanUser(QString userid, QString reason)
}
void
+ChatPage::receivedSessionKey(const std::string &room_id, const std::string &session_id)
+{
+ view_manager_->receivedSessionKey(room_id, session_id);
+}
+
+void
ChatPage::sendTypingNotifications()
{
if (!userSettings_->typingNotifications())
diff --git a/src/ChatPage.h b/src/ChatPage.h
index f0e12ab5..bf649cc9 100644
--- a/src/ChatPage.h
+++ b/src/ChatPage.h
@@ -107,6 +107,8 @@ public slots:
void banUser(QString userid, QString reason);
void unbanUser(QString userid, QString reason);
+ void receivedSessionKey(const std::string &room_id, const std::string &session_id);
+
signals:
void connectionLost();
void connectionRestored();
diff --git a/src/Olm.cpp b/src/Olm.cpp
index 730a3ea5..79b00774 100644
--- a/src/Olm.cpp
+++ b/src/Olm.cpp
@@ -388,9 +388,10 @@ import_inbound_megolm_session(
return;
}
- // TODO(Nico): Reload messages encrypted with this key.
nhlog::crypto()->info(
"established inbound megolm session ({}, {})", roomKey.content.room_id, roomKey.sender);
+
+ ChatPage::instance()->receivedSessionKey(index.room_id, index.session_id);
}
void
@@ -401,48 +402,24 @@ mark_keys_as_published()
}
void
-request_keys(const std::string &room_id, const std::string &event_id)
-{
- nhlog::crypto()->info("requesting keys for event {} at {}", event_id, room_id);
-
- http::client()->get_event(
- room_id,
- event_id,
- [event_id, room_id](const mtx::events::collections::TimelineEvents &res,
- mtx::http::RequestErr err) {
- using namespace mtx::events;
-
- if (err) {
- nhlog::net()->warn(
- "failed to retrieve event {} from {}", event_id, room_id);
- return;
- }
-
- if (!std::holds_alternative<EncryptedEvent<msg::Encrypted>>(res)) {
- nhlog::net()->info(
- "retrieved event is not encrypted: {} from {}", event_id, room_id);
- return;
- }
-
- olm::send_key_request_for(room_id, std::get<EncryptedEvent<msg::Encrypted>>(res));
- });
-}
-
-void
-send_key_request_for(const std::string &room_id,
- const mtx::events::EncryptedEvent<mtx::events::msg::Encrypted> &e)
+send_key_request_for(mtx::events::EncryptedEvent<mtx::events::msg::Encrypted> e,
+ const std::string &request_id,
+ bool cancel)
{
using namespace mtx::events;
- nhlog::crypto()->debug("sending key request: {}", json(e).dump(2));
+ nhlog::crypto()->debug("sending key request: sender_key {}, session_id {}",
+ e.content.sender_key,
+ e.content.session_id);
mtx::events::msg::KeyRequest request;
- request.action = mtx::events::msg::RequestAction::Request;
+ request.action = !cancel ? mtx::events::msg::RequestAction::Request
+ : mtx::events::msg::RequestAction::Cancellation;
request.algorithm = MEGOLM_ALGO;
- request.room_id = room_id;
+ request.room_id = e.room_id;
request.sender_key = e.content.sender_key;
request.session_id = e.content.session_id;
- request.request_id = "key_request." + http::client()->generate_txn_id();
+ request.request_id = request_id;
request.requesting_device_id = http::client()->device_id();
nhlog::crypto()->debug("m.room_key_request: {}", json(request).dump(2));
diff --git a/src/Olm.h b/src/Olm.h
index ce362e26..322affa1 100644
--- a/src/Olm.h
+++ b/src/Olm.h
@@ -96,11 +96,9 @@ mark_keys_as_published();
//! Request the encryption keys from sender's device for the given event.
void
-request_keys(const std::string &room_id, const std::string &event_id);
-
-void
-send_key_request_for(const std::string &room_id,
- const mtx::events::EncryptedEvent<mtx::events::msg::Encrypted> &);
+send_key_request_for(mtx::events::EncryptedEvent<mtx::events::msg::Encrypted> e,
+ const std::string &request_id,
+ bool cancel = false);
void
handle_key_request_message(const mtx::events::DeviceEvent<mtx::events::msg::KeyRequest> &);
diff --git a/src/timeline/EventStore.cpp b/src/timeline/EventStore.cpp
index 3564ffc0..22809a20 100644
--- a/src/timeline/EventStore.cpp
+++ b/src/timeline/EventStore.cpp
@@ -213,6 +213,28 @@ EventStore::clearTimeline()
}
void
+EventStore::receivedSessionKey(const std::string &session_id)
+{
+ if (!pending_key_requests.count(session_id))
+ return;
+
+ auto request = pending_key_requests.at(session_id);
+ pending_key_requests.erase(session_id);
+
+ olm::send_key_request_for(request.events.front(), request.request_id, true);
+
+ for (const auto &e : request.events) {
+ auto idx = idToIndex(e.event_id);
+ if (idx) {
+ decryptedEvents_.remove({room_id_, e.event_id});
+ events_by_id_.remove({room_id_, e.event_id});
+ events_.remove({room_id_, toInternalIdx(*idx)});
+ emit dataChanged(*idx, *idx);
+ }
+ }
+}
+
+void
EventStore::handleSync(const mtx::responses::Timeline &events)
{
if (this->thread() != QThread::currentThread())
@@ -294,18 +316,6 @@ EventStore::handleSync(const mtx::responses::Timeline &events)
*d_event)) {
handle_room_verification(*d_event);
}
- // else {
- // // only the key.verification.ready sent by localuser's other
- // device
- // // is of significance as it is used for detecting accepted request
- // if (std::get_if<mtx::events::RoomEvent<
- // mtx::events::msg::KeyVerificationReady>>(d_event)) {
- // auto msg = std::get_if<mtx::events::RoomEvent<
- // mtx::events::msg::KeyVerificationReady>>(d_event);
- // ChatPage::instance()->receivedDeviceVerificationReady(
- // msg->content);
- // }
- //}
}
}
}
@@ -501,7 +511,7 @@ EventStore::decryptEvent(const IdIndex &idx,
if (decryptionResult.error) {
switch (*decryptionResult.error) {
- case olm::DecryptionErrorCode::MissingSession:
+ case olm::DecryptionErrorCode::MissingSession: {
dummy.content.body =
tr("-- Encrypted Event (No keys found for decryption) --",
"Placeholder, when the message was not decrypted yet or can't be "
@@ -512,8 +522,21 @@ EventStore::decryptEvent(const IdIndex &idx,
index.session_id,
e.sender);
// TODO: Check if this actually works and look in key backup
- olm::send_key_request_for(room_id_, e);
+ auto copy = e;
+ copy.room_id = room_id_;
+ if (pending_key_requests.count(e.content.session_id)) {
+ pending_key_requests.at(e.content.session_id)
+ .events.push_back(copy);
+ } else {
+ PendingKeyRequests request;
+ request.request_id =
+ "key_request." + http::client()->generate_txn_id();
+ request.events.push_back(copy);
+ olm::send_key_request_for(copy, request.request_id);
+ pending_key_requests[e.content.session_id] = request;
+ }
break;
+ }
case olm::DecryptionErrorCode::DbError:
nhlog::db()->critical(
"failed to retrieve megolm session with index ({}, {}, {})",
diff --git a/src/timeline/EventStore.h b/src/timeline/EventStore.h
index 7f8e2396..2d5fb1be 100644
--- a/src/timeline/EventStore.h
+++ b/src/timeline/EventStore.h
@@ -104,6 +104,7 @@ signals:
public slots:
void addPending(mtx::events::collections::TimelineEvents event);
+ void receivedSessionKey(const std::string &session_id);
void clearTimeline();
private:
@@ -121,6 +122,13 @@ private:
static QCache<Index, mtx::events::collections::TimelineEvents> events_;
static QCache<IdIndex, mtx::events::collections::TimelineEvents> events_by_id_;
+ struct PendingKeyRequests
+ {
+ std::string request_id;
+ std::vector<mtx::events::EncryptedEvent<mtx::events::msg::Encrypted>> events;
+ };
+ std::map<std::string, PendingKeyRequests> pending_key_requests;
+
std::string current_txn;
int current_txn_error_count = 0;
bool noMoreMessages = false;
diff --git a/src/timeline/TimelineModel.h b/src/timeline/TimelineModel.h
index 9f250b33..e1fb9196 100644
--- a/src/timeline/TimelineModel.h
+++ b/src/timeline/TimelineModel.h
@@ -264,6 +264,10 @@ public slots:
}
void setDecryptDescription(bool decrypt) { decryptDescription = decrypt; }
void clearTimeline() { events.clearTimeline(); }
+ void receivedSessionKey(const std::string &session_key)
+ {
+ events.receivedSessionKey(session_key);
+ }
QString roomName() const;
QString roomTopic() const;
diff --git a/src/timeline/TimelineViewManager.cpp b/src/timeline/TimelineViewManager.cpp
index 783584c9..1e8ed243 100644
--- a/src/timeline/TimelineViewManager.cpp
+++ b/src/timeline/TimelineViewManager.cpp
@@ -441,6 +441,15 @@ TimelineViewManager::updateReadReceipts(const QString &room_id,
}
void
+TimelineViewManager::receivedSessionKey(const std::string &room_id, const std::string &session_id)
+{
+ auto room = models.find(QString::fromStdString(room_id));
+ if (room != models.end()) {
+ room.value()->receivedSessionKey(session_id);
+ }
+}
+
+void
TimelineViewManager::initWithMessages(const std::map<QString, mtx::responses::Timeline> &msgs)
{
for (const auto &e : msgs) {
diff --git a/src/timeline/TimelineViewManager.h b/src/timeline/TimelineViewManager.h
index 5e441562..b6f8b443 100644
--- a/src/timeline/TimelineViewManager.h
+++ b/src/timeline/TimelineViewManager.h
@@ -92,6 +92,7 @@ signals:
public slots:
void updateReadReceipts(const QString &room_id, const std::vector<QString> &event_ids);
+ void receivedSessionKey(const std::string &room_id, const std::string &session_id);
void initWithMessages(const std::map<QString, mtx::responses::Timeline> &msgs);
void setHistoryView(const QString &room_id);
|