Clean up key requests + autoreload

This commit is contained in:
Nicolas Werner 2020-10-20 19:46:37 +02:00
parent 983690c94f
commit cea7f4574f
11 changed files with 84 additions and 56 deletions

View File

@ -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()

View File

@ -146,7 +146,7 @@
"name": "mtxclient",
"sources": [
{
"commit": "ad5575bc24089dc385e97d9ace026414b618775c",
"commit": "da9958e14e035fbf22d498074d381b2ea0092a9d",
"type": "git",
"url": "https://github.com/Nheko-Reborn/mtxclient.git"
}

View File

@ -1249,6 +1249,12 @@ ChatPage::unbanUser(QString userid, QString reason)
reason.trimmed().toStdString());
}
void
ChatPage::receivedSessionKey(const std::string &room_id, const std::string &session_id)
{
view_manager_->receivedSessionKey(room_id, session_id);
}
void
ChatPage::sendTypingNotifications()
{

View File

@ -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();

View File

@ -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));

View File

@ -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> &);

View File

@ -212,6 +212,28 @@ EventStore::clearTimeline()
emit endResetModel();
}
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)
{
@ -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 ({}, {}, {})",

View File

@ -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;

View File

@ -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;

View File

@ -440,6 +440,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)
{

View File

@ -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);