aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/connection.cpp96
-rw-r--r--lib/connection.h6
-rw-r--r--lib/converters.h8
-rw-r--r--lib/e2ee/qolminboundsession.cpp4
-rw-r--r--lib/e2ee/qolminboundsession.h2
-rw-r--r--lib/events/callanswerevent.cpp11
-rw-r--r--lib/events/callanswerevent.h4
-rw-r--r--lib/events/callinviteevent.cpp2
-rw-r--r--lib/events/callinviteevent.h4
-rw-r--r--lib/events/roomkeyevent.h5
-rw-r--r--lib/jobs/syncjob.h2
-rw-r--r--lib/room.cpp38
-rw-r--r--lib/room.h5
-rw-r--r--lib/syncdata.cpp10
-rw-r--r--lib/syncdata.h10
15 files changed, 105 insertions, 102 deletions
diff --git a/lib/connection.cpp b/lib/connection.cpp
index 1ea394a1..bd4d9251 100644
--- a/lib/connection.cpp
+++ b/lib/connection.cpp
@@ -96,7 +96,6 @@ public:
/// as of the last sync
QHash<QString, QString> roomAliasMap;
QVector<QString> roomIdsToForget;
- QVector<Room*> firstTimeRooms;
QVector<QString> pendingStateRoomIds;
QMap<QString, User*> userMap;
DirectChatsMap directChats;
@@ -220,7 +219,9 @@ public:
}
q->database()->saveOlmSession(senderKey, session->sessionId(), std::get<QByteArray>(pickleResult), QDateTime::currentDateTime());
}
- std::pair<QString, QString> sessionDecryptPrekey(const QOlmMessage& message, const QString &senderKey, std::unique_ptr<QOlmAccount>& olmAccount)
+
+ std::pair<QString, QString> sessionDecryptPrekey(const QOlmMessage& message,
+ const QString& senderKey)
{
Q_ASSERT(message.type() == QOlmMessage::PreKey);
for(auto& session : olmSessions[senderKey]) {
@@ -274,24 +275,19 @@ public:
}
std::pair<QString, QString> sessionDecryptMessage(
- const QJsonObject& personalCipherObject, const QByteArray& senderKey, std::unique_ptr<QOlmAccount>& account)
+ const QJsonObject& personalCipherObject, const QByteArray& senderKey)
{
- QString decrypted;
- QString olmSessionId;
- int type = personalCipherObject.value(TypeKeyL).toInt(-1);
- QByteArray body = personalCipherObject.value(BodyKeyL).toString().toLatin1();
- if (type == QOlmMessage::PreKey) {
- QOlmMessage preKeyMessage(body, QOlmMessage::PreKey);
- auto result = sessionDecryptPrekey(preKeyMessage, senderKey, account);
- decrypted = result.first;
- olmSessionId = result.second;
- } else if (type == QOlmMessage::General) {
- QOlmMessage message(body, QOlmMessage::General);
- auto result = sessionDecryptGeneral(message, senderKey);
- decrypted = result.first;
- olmSessionId = result.second;
- }
- return { decrypted, olmSessionId };
+ QOlmMessage message {
+ personalCipherObject.value(BodyKeyL).toString().toLatin1(),
+ static_cast<QOlmMessage::Type>(
+ personalCipherObject.value(TypeKeyL).toInt(-1))
+ };
+ if (message.type() == QOlmMessage::PreKey)
+ return sessionDecryptPrekey(message, senderKey);
+ if (message.type() == QOlmMessage::General)
+ return sessionDecryptGeneral(message, senderKey);
+ qCWarning(E2EE) << "Olm message has incorrect type" << message.type();
+ return {};
}
#endif
@@ -311,8 +307,9 @@ public:
qCDebug(E2EE) << "Encrypted event is not for the current device";
return {};
}
- const auto [decrypted, olmSessionId] = sessionDecryptMessage(
- personalCipherObject, encryptedEvent.senderKey().toLatin1(), olmAccount);
+ const auto [decrypted, olmSessionId] =
+ sessionDecryptMessage(personalCipherObject,
+ encryptedEvent.senderKey().toLatin1());
if (decrypted.isEmpty()) {
qCDebug(E2EE) << "Problem with new session from senderKey:"
<< encryptedEvent.senderKey()
@@ -833,16 +830,14 @@ void Connection::Private::consumeRoomData(SyncDataList&& roomDataList,
}
if (auto* r = q->provideRoom(roomData.roomId, roomData.joinState)) {
pendingStateRoomIds.removeOne(roomData.roomId);
- r->updateData(std::move(roomData), fromCache);
- if (firstTimeRooms.removeOne(r)) {
- emit q->loadedRoomState(r);
- if (capabilities.roomVersions)
- r->checkVersion();
- // Otherwise, the version will be checked in reloadCapabilities()
- }
+ // Update rooms one by one, giving time to update the UI.
+ QMetaObject::invokeMethod(
+ r,
+ [r, rd = std::move(roomData), fromCache] () mutable {
+ r->updateData(std::move(rd), fromCache);
+ },
+ Qt::QueuedConnection);
}
- // Let UI update itself after updating each room
- QCoreApplication::processEvents();
}
}
@@ -953,8 +948,6 @@ void Connection::Private::consumeToDeviceEvents(Events&& toDeviceEvents)
outdatedUsers += event.senderId();
encryptionUpdateRequired = true;
pendingEncryptedEvents.push_back(std::make_unique<EncryptedEvent>(event.fullJson()));
- }, [](const Event& e){
- // Unhandled
});
}
#endif
@@ -970,7 +963,7 @@ void Connection::Private::handleEncryptedToDeviceEvent(const EncryptedEvent& eve
}
switchOnType(*decryptedEvent,
- [this, senderKey = event.senderKey(), &event, olmSessionId = olmSessionId](const RoomKeyEvent& roomKeyEvent) {
+ [this, &event, olmSessionId = olmSessionId](const RoomKeyEvent& roomKeyEvent) {
if (auto* detectedRoom = q->room(roomKeyEvent.roomId())) {
detectedRoom->handleRoomKeyEvent(roomKeyEvent, event.senderId(), olmSessionId);
} else {
@@ -1707,9 +1700,14 @@ Room* Connection::provideRoom(const QString& id, Omittable<JoinState> joinState)
return nullptr;
}
d->roomMap.insert(roomKey, room);
- d->firstTimeRooms.push_back(room);
connect(room, &Room::beforeDestruction, this,
&Connection::aboutToDeleteRoom);
+ connect(room, &Room::baseStateLoaded, this, [this, room] {
+ emit loadedRoomState(room);
+ if (d->capabilities.roomVersions)
+ room->checkVersion();
+ // Otherwise, the version will be checked in reloadCapabilities()
+ });
emit newRoom(room);
}
if (!joinState)
@@ -2072,12 +2070,13 @@ void Connection::Private::loadOutdatedUserDevices()
saveDevicesList();
for(size_t i = 0; i < pendingEncryptedEvents.size();) {
- if (q->isKnownCurveKey(pendingEncryptedEvents[i]->fullJson()[SenderKeyL].toString(), pendingEncryptedEvents[i]->contentJson()["sender_key"].toString())) {
- handleEncryptedToDeviceEvent(*(pendingEncryptedEvents[i].get()));
+ if (q->isKnownCurveKey(
+ pendingEncryptedEvents[i]->fullJson()[SenderKeyL].toString(),
+ pendingEncryptedEvents[i]->contentPart<QString>("sender_key"_ls))) {
+ handleEncryptedToDeviceEvent(*pendingEncryptedEvents[i]);
pendingEncryptedEvents.erase(pendingEncryptedEvents.begin() + i);
- } else {
- i++;
- }
+ } else
+ ++i;
}
});
}
@@ -2186,13 +2185,10 @@ void Connection::saveOlmAccount()
#ifdef Quotient_E2EE_ENABLED
QJsonObject Connection::decryptNotification(const QJsonObject &notification)
{
- auto room = this->room(notification["room_id"].toString());
+ auto r = room(notification["room_id"].toString());
auto event = makeEvent<EncryptedEvent>(notification["event"].toObject());
- auto decrypted = room->decryptMessage(*event);
- if(!decrypted) {
- return QJsonObject();
- }
- return decrypted->fullJson();
+ const auto decrypted = r->decryptMessage(*event);
+ return decrypted ? decrypted->fullJson() : QJsonObject();
}
Database* Connection::database()
@@ -2200,14 +2196,18 @@ Database* Connection::database()
return d->database;
}
-UnorderedMap<QString, QOlmInboundGroupSessionPtr> Connection::loadRoomMegolmSessions(Room* room)
+UnorderedMap<QString, QOlmInboundGroupSessionPtr>
+Connection::loadRoomMegolmSessions(const Room* room)
{
return database()->loadMegolmSessions(room->id(), picklingMode());
}
-void Connection::saveMegolmSession(Room* room, QOlmInboundGroupSession* session)
+void Connection::saveMegolmSession(const Room* room,
+ const QOlmInboundGroupSession& session)
{
- database()->saveMegolmSession(room->id(), session->sessionId(), session->pickle(picklingMode()), session->senderId(), session->olmSessionId());
+ database()->saveMegolmSession(room->id(), session.sessionId(),
+ session.pickle(picklingMode()),
+ session.senderId(), session.olmSessionId());
}
QStringList Connection::devicesForUser(User* user) const
diff --git a/lib/connection.h b/lib/connection.h
index 29731593..b75bd5b5 100644
--- a/lib/connection.h
+++ b/lib/connection.h
@@ -317,8 +317,10 @@ public:
#ifdef Quotient_E2EE_ENABLED
QOlmAccount* olmAccount() const;
Database* database();
- UnorderedMap<QString, QOlmInboundGroupSessionPtr> loadRoomMegolmSessions(Room* room);
- void saveMegolmSession(Room* room, QOlmInboundGroupSession* session);
+ UnorderedMap<QString, QOlmInboundGroupSessionPtr> loadRoomMegolmSessions(
+ const Room* room);
+ void saveMegolmSession(const Room* room,
+ const QOlmInboundGroupSession& session);
#endif // Quotient_E2EE_ENABLED
Q_INVOKABLE Quotient::SyncJob* syncJob() const;
Q_INVOKABLE int millisToReconnect() const;
diff --git a/lib/converters.h b/lib/converters.h
index 6515310a..5e3becb8 100644
--- a/lib/converters.h
+++ b/lib/converters.h
@@ -163,6 +163,14 @@ inline qint64 fromJson(const QJsonValue& jv) { return qint64(jv.toDouble()); }
template <>
inline QString fromJson(const QJsonValue& jv) { return jv.toString(); }
+//! Use fromJson<QString> and use toLatin1()/toUtf8()/... to make QByteArray
+//!
+//! QJsonValue can only convert to QString and there's ambiguity whether
+//! conversion to QByteArray should use (fast but very limited) toLatin1() or
+//! (all encompassing and conforming to the JSON spec but slow) toUtf8().
+template <>
+inline QByteArray fromJson(const QJsonValue& jv) = delete;
+
template <>
inline QJsonArray fromJson(const QJsonValue& jv) { return jv.toArray(); }
diff --git a/lib/e2ee/qolminboundsession.cpp b/lib/e2ee/qolminboundsession.cpp
index 60d871ef..62856831 100644
--- a/lib/e2ee/qolminboundsession.cpp
+++ b/lib/e2ee/qolminboundsession.cpp
@@ -154,9 +154,9 @@ QString QOlmInboundGroupSession::olmSessionId() const
{
return m_olmSessionId;
}
-void QOlmInboundGroupSession::setOlmSessionId(const QString& olmSessionId)
+void QOlmInboundGroupSession::setOlmSessionId(const QString& newOlmSessionId)
{
- m_olmSessionId = olmSessionId;
+ m_olmSessionId = newOlmSessionId;
}
QString QOlmInboundGroupSession::senderId() const
diff --git a/lib/e2ee/qolminboundsession.h b/lib/e2ee/qolminboundsession.h
index 32112b97..13515434 100644
--- a/lib/e2ee/qolminboundsession.h
+++ b/lib/e2ee/qolminboundsession.h
@@ -44,7 +44,7 @@ public:
//! The olm session that this session was received from.
//! Required to get the device this session is from.
QString olmSessionId() const;
- void setOlmSessionId(const QString& setOlmSessionId);
+ void setOlmSessionId(const QString& newOlmSessionId);
//! The sender of this session.
QString senderId() const;
diff --git a/lib/events/callanswerevent.cpp b/lib/events/callanswerevent.cpp
index be83d9d0..f75f8ad3 100644
--- a/lib/events/callanswerevent.cpp
+++ b/lib/events/callanswerevent.cpp
@@ -14,7 +14,6 @@ m.call.answer
"type": "answer"
},
"call_id": "12345",
- "lifetime": 60000,
"version": 0
},
"event_id": "$WLGTSEFSEF:localhost",
@@ -33,16 +32,6 @@ CallAnswerEvent::CallAnswerEvent(const QJsonObject& obj)
qCDebug(EVENTS) << "Call Answer event";
}
-CallAnswerEvent::CallAnswerEvent(const QString& callId, const int lifetime,
- const QString& sdp)
- : CallEventBase(
- typeId(), matrixTypeId(), callId, 0,
- { { QStringLiteral("lifetime"), lifetime },
- { QStringLiteral("answer"),
- QJsonObject { { QStringLiteral("type"), QStringLiteral("answer") },
- { QStringLiteral("sdp"), sdp } } } })
-{}
-
CallAnswerEvent::CallAnswerEvent(const QString& callId, const QString& sdp)
: CallEventBase(
typeId(), matrixTypeId(), callId, 0,
diff --git a/lib/events/callanswerevent.h b/lib/events/callanswerevent.h
index 70292a7a..4d539b85 100644
--- a/lib/events/callanswerevent.h
+++ b/lib/events/callanswerevent.h
@@ -13,12 +13,8 @@ public:
explicit CallAnswerEvent(const QJsonObject& obj);
- explicit CallAnswerEvent(const QString& callId, const int lifetime,
- const QString& sdp);
explicit CallAnswerEvent(const QString& callId, const QString& sdp);
- QUO_CONTENT_GETTER(int, lifetime) // FIXME: Omittable<>?
-
QString sdp() const
{
return contentPart<QJsonObject>("answer"_ls).value("sdp"_ls).toString();
diff --git a/lib/events/callinviteevent.cpp b/lib/events/callinviteevent.cpp
index 11d50768..2f26a1cb 100644
--- a/lib/events/callinviteevent.cpp
+++ b/lib/events/callinviteevent.cpp
@@ -33,7 +33,7 @@ CallInviteEvent::CallInviteEvent(const QJsonObject& obj)
qCDebug(EVENTS) << "Call Invite event";
}
-CallInviteEvent::CallInviteEvent(const QString& callId, const int lifetime,
+CallInviteEvent::CallInviteEvent(const QString& callId, int lifetime,
const QString& sdp)
: CallEventBase(
typeId(), matrixTypeId(), callId, 0,
diff --git a/lib/events/callinviteevent.h b/lib/events/callinviteevent.h
index 1b1f4f0f..5b4ca0df 100644
--- a/lib/events/callinviteevent.h
+++ b/lib/events/callinviteevent.h
@@ -13,10 +13,10 @@ public:
explicit CallInviteEvent(const QJsonObject& obj);
- explicit CallInviteEvent(const QString& callId, const int lifetime,
+ explicit CallInviteEvent(const QString& callId, int lifetime,
const QString& sdp);
- QUO_CONTENT_GETTER(int, lifetime) // FIXME: Omittable<>?
+ QUO_CONTENT_GETTER(int, lifetime)
QString sdp() const
{
return contentPart<QJsonObject>("offer"_ls).value("sdp"_ls).toString();
diff --git a/lib/events/roomkeyevent.h b/lib/events/roomkeyevent.h
index c4df7936..ed4c9440 100644
--- a/lib/events/roomkeyevent.h
+++ b/lib/events/roomkeyevent.h
@@ -16,7 +16,10 @@ public:
QString algorithm() const { return contentPart<QString>("algorithm"_ls); }
QString roomId() const { return contentPart<QString>(RoomIdKeyL); }
QString sessionId() const { return contentPart<QString>("session_id"_ls); }
- QString sessionKey() const { return contentPart<QString>("session_key"_ls); }
+ QByteArray sessionKey() const
+ {
+ return contentPart<QString>("session_key"_ls).toLatin1();
+ }
};
REGISTER_EVENT_TYPE(RoomKeyEvent)
} // namespace Quotient
diff --git a/lib/jobs/syncjob.h b/lib/jobs/syncjob.h
index 830a7c71..b7bfbbb3 100644
--- a/lib/jobs/syncjob.h
+++ b/lib/jobs/syncjob.h
@@ -15,7 +15,7 @@ public:
explicit SyncJob(const QString& since, const Filter& filter,
int timeout = -1, const QString& presence = {});
- SyncData&& takeData() { return std::move(d); }
+ SyncData takeData() { return std::move(d); }
protected:
Status prepareResult() override;
diff --git a/lib/room.cpp b/lib/room.cpp
index 4d9f952c..0a997b9c 100644
--- a/lib/room.cpp
+++ b/lib/room.cpp
@@ -339,14 +339,16 @@ public:
#ifdef Quotient_E2EE_ENABLED
UnorderedMap<QString, QOlmInboundGroupSessionPtr> groupSessions;
- bool addInboundGroupSession(QString sessionId, QString sessionKey, const QString& senderId, const QString& olmSessionId)
+ bool addInboundGroupSession(QString sessionId, QByteArray sessionKey,
+ const QString& senderId,
+ const QString& olmSessionId)
{
- if (groupSessions.find(sessionId) != groupSessions.end()) {
+ if (groupSessions.contains(sessionId)) {
qCWarning(E2EE) << "Inbound Megolm session" << sessionId << "already exists";
return false;
}
- auto megolmSession = QOlmInboundGroupSession::create(sessionKey.toLatin1());
+ auto megolmSession = QOlmInboundGroupSession::create(sessionKey);
if (megolmSession->sessionId() != sessionId) {
qCWarning(E2EE) << "Session ID mismatch in m.room_key event";
return false;
@@ -354,13 +356,12 @@ public:
megolmSession->setSenderId(senderId);
megolmSession->setOlmSessionId(olmSessionId);
qCWarning(E2EE) << "Adding inbound session";
- connection->saveMegolmSession(q, megolmSession.get());
+ connection->saveMegolmSession(q, *megolmSession);
groupSessions[sessionId] = std::move(megolmSession);
return true;
}
QString groupSessionDecryptMessage(QByteArray cipher,
- const QString& senderKey,
const QString& sessionId,
const QString& eventId,
QDateTime timestamp,
@@ -415,11 +416,6 @@ Room::Room(Connection* connection, QString id, JoinState initialJoinState)
// https://marcmutz.wordpress.com/translated-articles/pimp-my-pimpl-%E2%80%94-reloaded/
d->q = this;
d->displayname = d->calculateDisplayname(); // Set initial "Empty room" name
- connectUntil(connection, &Connection::loadedRoomState, this, [this](Room* r) {
- if (this == r)
- emit baseStateLoaded();
- return this == r; // loadedRoomState fires only once per room
- });
#ifdef Quotient_E2EE_ENABLED
connectSingleShot(this, &Room::encryption, this, [this, connection](){
connection->encryptionUpdate(this);
@@ -1483,9 +1479,9 @@ RoomEventPtr Room::decryptMessage(const EncryptedEvent& encryptedEvent)
return {};
}
QString decrypted = d->groupSessionDecryptMessage(
- encryptedEvent.ciphertext(), encryptedEvent.senderKey(),
- encryptedEvent.sessionId(), encryptedEvent.id(),
- encryptedEvent.originTimestamp(), encryptedEvent.senderId());
+ encryptedEvent.ciphertext(), encryptedEvent.sessionId(),
+ encryptedEvent.id(), encryptedEvent.originTimestamp(),
+ encryptedEvent.senderId());
if (decrypted.isEmpty()) {
// qCWarning(E2EE) << "Encrypted message is empty";
return {};
@@ -1514,7 +1510,8 @@ void Room::handleRoomKeyEvent(const RoomKeyEvent& roomKeyEvent,
<< roomKeyEvent.algorithm() << "in m.room_key event";
}
if (d->addInboundGroupSession(roomKeyEvent.sessionId(),
- roomKeyEvent.sessionKey(), senderId, olmSessionId)) {
+ roomKeyEvent.sessionKey(), senderId,
+ olmSessionId)) {
qCWarning(E2EE) << "added new inboundGroupSession:"
<< d->groupSessions.size();
auto undecryptedEvents = d->undecryptedEvents[roomKeyEvent.sessionId()];
@@ -1820,6 +1817,9 @@ Room::Changes Room::Private::updateStatsFromSyncData(const SyncRoomData& data,
void Room::updateData(SyncRoomData&& data, bool fromCache)
{
+ qCDebug(MAIN) << "--- Updating room" << id() << "/" << objectName();
+ bool firstUpdate = d->baseState.empty();
+
if (d->prevBatch.isEmpty())
d->prevBatch = data.timelinePrevBatch;
setJoinState(data.joinState);
@@ -1845,6 +1845,9 @@ void Room::updateData(SyncRoomData&& data, bool fromCache)
emit namesChanged(this);
d->postprocessChanges(roomChanges, !fromCache);
+ if (firstUpdate)
+ emit baseStateLoaded();
+ qCDebug(MAIN) << "--- Finished updating room" << id() << "/" << objectName();
}
void Room::Private::postprocessChanges(Changes changes, bool saveState)
@@ -2231,11 +2234,12 @@ void Room::sendCallCandidates(const QString& callId,
d->sendEvent<CallCandidatesEvent>(callId, candidates);
}
-void Room::answerCall(const QString& callId, const int lifetime,
+void Room::answerCall(const QString& callId, [[maybe_unused]] int lifetime,
const QString& sdp)
{
- Q_ASSERT(supportsCalls());
- d->sendEvent<CallAnswerEvent>(callId, lifetime, sdp);
+ qCWarning(MAIN) << "To client developer: drop lifetime parameter from "
+ "Room::answerCall(), it is no more accepted";
+ answerCall(callId, sdp);
}
void Room::answerCall(const QString& callId, const QString& sdp)
diff --git a/lib/room.h b/lib/room.h
index 7e53aed0..6e6071f0 100644
--- a/lib/room.h
+++ b/lib/room.h
@@ -871,8 +871,9 @@ public Q_SLOTS:
void inviteCall(const QString& callId, const int lifetime,
const QString& sdp);
void sendCallCandidates(const QString& callId, const QJsonArray& candidates);
- void answerCall(const QString& callId, const int lifetime,
- const QString& sdp);
+ //! \deprecated Lifetime argument is no more passed; use 2-arg
+ //! Room::answerCall() instead
+ void answerCall(const QString& callId, int lifetime, const QString& sdp);
void answerCall(const QString& callId, const QString& sdp);
void hangupCall(const QString& callId);
diff --git a/lib/syncdata.cpp b/lib/syncdata.cpp
index 78957cbe..95d3c7e4 100644
--- a/lib/syncdata.cpp
+++ b/lib/syncdata.cpp
@@ -142,7 +142,7 @@ SyncData::SyncData(const QString& cacheFileName)
<< "is required; discarding the cache";
}
-SyncDataList&& SyncData::takeRoomData() { return move(roomData); }
+SyncDataList SyncData::takeRoomData() { return move(roomData); }
QString SyncData::fileNameForRoom(QString roomId)
{
@@ -150,18 +150,18 @@ QString SyncData::fileNameForRoom(QString roomId)
return roomId + ".json";
}
-Events&& SyncData::takePresenceData() { return std::move(presenceData); }
+Events SyncData::takePresenceData() { return std::move(presenceData); }
-Events&& SyncData::takeAccountData() { return std::move(accountData); }
+Events SyncData::takeAccountData() { return std::move(accountData); }
-Events&& SyncData::takeToDeviceEvents() { return std::move(toDeviceEvents); }
+Events SyncData::takeToDeviceEvents() { return std::move(toDeviceEvents); }
std::pair<int, int> SyncData::cacheVersion()
{
return { MajorCacheVersion, 2 };
}
-DevicesList&& SyncData::takeDevicesList() { return std::move(devicesList); }
+DevicesList SyncData::takeDevicesList() { return std::move(devicesList); }
QJsonObject SyncData::loadJson(const QString& fileName)
{
diff --git a/lib/syncdata.h b/lib/syncdata.h
index 6b70140d..9358ec8f 100644
--- a/lib/syncdata.h
+++ b/lib/syncdata.h
@@ -98,15 +98,15 @@ public:
*/
void parseJson(const QJsonObject& json, const QString& baseDir = {});
- Events&& takePresenceData();
- Events&& takeAccountData();
- Events&& takeToDeviceEvents();
+ Events takePresenceData();
+ Events takeAccountData();
+ Events takeToDeviceEvents();
const QHash<QString, int>& deviceOneTimeKeysCount() const
{
return deviceOneTimeKeysCount_;
}
- SyncDataList&& takeRoomData();
- DevicesList&& takeDevicesList();
+ SyncDataList takeRoomData();
+ DevicesList takeDevicesList();
QString nextBatch() const { return nextBatch_; }