diff options
author | Alexey Rusakov <Kitsune-Ral@users.sf.net> | 2022-06-17 10:35:22 +0200 |
---|---|---|
committer | Alexey Rusakov <Kitsune-Ral@users.sf.net> | 2022-06-17 10:38:40 +0200 |
commit | f779b235ddac990d17a9a8d8dd222b9e0e7abd49 (patch) | |
tree | c56650a322fa5b4a6fc66b9230152e3b8f9d4f9a /lib | |
parent | da5156f5e2da08123549b554d9eafcf366fa4e11 (diff) | |
download | libquotient-f779b235ddac990d17a9a8d8dd222b9e0e7abd49.tar.gz libquotient-f779b235ddac990d17a9a8d8dd222b9e0e7abd49.zip |
Make Connection::sendToDevices() an actual slot
Although Qt 5 didn't complain about that, you could never really use
sendToDevices() in its slot (or even invocable) capacity because
Qt's meta-type system could not handle move-only UsersToDevicesToEvents.
Qt 6 is more stringent; the build fails at trying to instantiate
QMetaType for that type (with a rather unhelpful error message thrown
by Clang, and more helpful but very verbose diagnostic from MSVC)
because it does not provide a copy constructor.
However, sendToDevice doesn't really need to have full-blown events
in that parameter; just the content of the event is equally fine.
This commit does exactly that: replaces UsersToDevicesToEvents with
UsersToDevicesToContent that contains QJsonObject's instead of
EventPtr's. The code around is updated accordingly.
Also: factor out the key event JSON creation from
makeMessageEventForSessionKey() because it's the same JSON for each
target device; the function therefore is called encryptSessionKeyEvent()
now.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/connection.cpp | 74 | ||||
-rw-r--r-- | lib/connection.h | 5 |
2 files changed, 34 insertions, 45 deletions
diff --git a/lib/connection.cpp b/lib/connection.cpp index 101bef89..3e44513b 100644 --- a/lib/connection.cpp +++ b/lib/connection.cpp @@ -381,10 +381,9 @@ public: const QString& device) const; QString edKeyForUserDevice(const QString& userId, const QString& device) const; - std::unique_ptr<EncryptedEvent> makeEventForSessionKey( - const QString& roomId, const QString& targetUserId, - const QString& targetDeviceId, const QByteArray& sessionId, - const QByteArray& sessionKey) const; + QJsonObject encryptSessionKeyEvent(QJsonObject payloadJson, + const QString& targetUserId, + const QString& targetDeviceId) const; #endif void saveAccessTokenToKeychain() const @@ -1365,17 +1364,10 @@ ForgetRoomJob* Connection::forgetRoom(const QString& id) } SendToDeviceJob* Connection::sendToDevices( - const QString& eventType, const UsersToDevicesToEvents& eventsMap) + const QString& eventType, const UsersToDevicesToContent& contents) { - QHash<QString, QHash<QString, QJsonObject>> json; - json.reserve(int(eventsMap.size())); - for (const auto& [userId, devicesToEvents] : eventsMap) { - auto& jsonUser = json[userId]; - for (const auto& [deviceId, event] : devicesToEvents) - jsonUser.insert(deviceId, event->contentJson()); - } return callApi<SendToDeviceJob>(BackgroundRequest, eventType, - generateTxnId(), json); + generateTxnId(), contents); } SendMessageJob* Connection::sendMessage(const QString& roomId, @@ -2354,30 +2346,15 @@ bool Connection::Private::createOlmSession(const QString& targetUserId, return true; } -std::unique_ptr<EncryptedEvent> Connection::Private::makeEventForSessionKey( - const QString& roomId, const QString& targetUserId, - const QString& targetDeviceId, const QByteArray& sessionId, - const QByteArray& sessionKey) const +QJsonObject Connection::Private::encryptSessionKeyEvent( + QJsonObject payloadJson, const QString& targetUserId, + const QString& targetDeviceId) const { - // Noisy but nice for debugging - // qDebug(E2EE) << "Creating the payload for" << data->userId() << device << - // sessionId << sessionKey.toHex(); - const auto event = makeEvent<RoomKeyEvent>("m.megolm.v1.aes-sha2", roomId, - sessionId, sessionKey, - data->userId()); - auto payloadJson = event->fullJson(); payloadJson.insert("recipient"_ls, targetUserId); - payloadJson.insert(SenderKeyL, data->userId()); payloadJson.insert("recipient_keys"_ls, QJsonObject { { Ed25519Key, edKeyForUserDevice(targetUserId, targetDeviceId) } }); - payloadJson.insert("keys"_ls, - QJsonObject { - { Ed25519Key, - QString(olmAccount->identityKeys().ed25519) } }); - payloadJson.insert("sender_device"_ls, data->deviceId()); - const auto [type, cipherText] = olmEncryptMessage( targetUserId, targetDeviceId, QJsonDocument(payloadJson).toJson(QJsonDocument::Compact)); @@ -2387,8 +2364,8 @@ std::unique_ptr<EncryptedEvent> Connection::Private::makeEventForSessionKey( { "body"_ls, QString(cipherText) } } } }; - return makeEvent<EncryptedEvent>(encrypted, - olmAccount->identityKeys().curve25519); + return EncryptedEvent(encrypted, olmAccount->identityKeys().curve25519) + .contentJson(); } void Connection::sendSessionKeyToDevices( @@ -2409,11 +2386,21 @@ void Connection::sendSessionKeyToDevices( if (hash.isEmpty()) return; + auto keyEventJson = RoomKeyEvent(MegolmV1AesSha2AlgoKey, roomId, sessionId, + sessionKey, userId()) + .fullJson(); + keyEventJson.insert(SenderKeyL, userId()); + keyEventJson.insert("sender_device"_ls, deviceId()); + keyEventJson.insert( + "keys"_ls, + QJsonObject { + { Ed25519Key, QString(olmAccount()->identityKeys().ed25519) } }); + auto job = callApi<ClaimKeysJob>(hash); - connect(job, &BaseJob::success, this, [job, this, roomId, sessionId, sessionKey, devices, index] { - UsersToDevicesToEvents usersToDevicesToEvents; - const auto oneTimeKeys = job->oneTimeKeys(); - for (const auto& [targetUserId, targetDeviceId] : + connect(job, &BaseJob::success, this, [job, this, roomId, sessionId, keyEventJson, devices, index] { + QHash<QString, QHash<QString, QJsonObject>> usersToDevicesToContent; + for (const auto oneTimeKeys = job->oneTimeKeys(); + const auto& [targetUserId, targetDeviceId] : asKeyValueRange(devices)) { if (!hasOlmSession(targetUserId, targetDeviceId) && !d->createOlmSession( @@ -2421,12 +2408,15 @@ void Connection::sendSessionKeyToDevices( oneTimeKeys[targetUserId][targetDeviceId])) continue; - usersToDevicesToEvents[targetUserId][targetDeviceId] = - d->makeEventForSessionKey(roomId, targetUserId, targetDeviceId, - sessionId, sessionKey); + // Noisy but nice for debugging +// qDebug(E2EE) << "Creating the payload for" << targetUserId +// << targetDeviceId << sessionId << sessionKey.toHex(); + usersToDevicesToContent[targetUserId][targetDeviceId] = + d->encryptSessionKeyEvent(keyEventJson, targetUserId, + targetDeviceId); } - if (!usersToDevicesToEvents.empty()) { - sendToDevices(EncryptedEvent::TypeId, usersToDevicesToEvents); + if (!usersToDevicesToContent.empty()) { + sendToDevices(EncryptedEvent::TypeId, usersToDevicesToContent); QVector<std::tuple<QString, QString, QString>> receivedDevices; receivedDevices.reserve(devices.size()); for (const auto& [user, device] : asKeyValueRange(devices)) diff --git a/lib/connection.h b/lib/connection.h index 5b806350..b8246ecb 100644 --- a/lib/connection.h +++ b/lib/connection.h @@ -133,8 +133,7 @@ class QUOTIENT_API Connection : public QObject { Q_PROPERTY(bool canChangePassword READ canChangePassword NOTIFY capabilitiesLoaded) public: - using UsersToDevicesToEvents = - UnorderedMap<QString, UnorderedMap<QString, EventPtr>>; + using UsersToDevicesToContent = QHash<QString, QHash<QString, QJsonObject>>; enum RoomVisibility { PublishRoom, @@ -689,7 +688,7 @@ public Q_SLOTS: ForgetRoomJob* forgetRoom(const QString& id); SendToDeviceJob* sendToDevices(const QString& eventType, - const UsersToDevicesToEvents& eventsMap); + const UsersToDevicesToContent& contents); /** \deprecated This method is experimental and may be removed any time */ SendMessageJob* sendMessage(const QString& roomId, const RoomEvent& event); |