diff options
author | Tobias Fella <fella@posteo.de> | 2021-05-21 00:29:08 +0200 |
---|---|---|
committer | Tobias Fella <fella@posteo.de> | 2021-12-01 21:56:11 +0100 |
commit | 265f105d77bf91c127c363b0c880357f91df7db4 (patch) | |
tree | 697c46084064a1eb21b1ef0447f913fd17ca0a48 /lib | |
parent | 5d3fe54fdfae4b74272a80c4bbe8f5d8a3e4c5cb (diff) | |
download | libquotient-265f105d77bf91c127c363b0c880357f91df7db4.tar.gz libquotient-265f105d77bf91c127c363b0c880357f91df7db4.zip |
Cache deviceslist across restarts
Diffstat (limited to 'lib')
-rw-r--r-- | lib/connection.cpp | 99 | ||||
-rw-r--r-- | lib/csapi/keys.h | 5 |
2 files changed, 103 insertions, 1 deletions
diff --git a/lib/connection.cpp b/lib/connection.cpp index 6facd316..e7a26f4b 100644 --- a/lib/connection.cpp +++ b/lib/connection.cpp @@ -258,6 +258,8 @@ public: #ifdef Quotient_E2EE_ENABLED void loadOutdatedUserDevices(); void createDevicesList(); + void saveDevicesList(); + void loadDevicesList(); #endif }; @@ -482,7 +484,7 @@ void Connection::Private::completeSetup(const QString& mxId) q->reloadCapabilities(); #ifdef Quotient_E2EE_ENABLED connectSingleShot(q, &Connection::syncDone, q, [=](){ - createDevicesList(); + loadDevicesList(); }); #endif } @@ -1873,6 +1875,7 @@ void Connection::Private::loadOutdatedUserDevices() } outdatedUsers -= user; } + saveDevicesList(); }); } @@ -1888,4 +1891,98 @@ void Connection::encryptionUpdate(Room *room) d->loadOutdatedUserDevices(); } } + +void Connection::Private::saveDevicesList() +{ + if (!cacheState) + return; + + QElapsedTimer et; + et.start(); + + QFile outFile { q->stateCacheDir().filePath("deviceslist.json") }; + if (!outFile.open(QFile::WriteOnly)) { + qCWarning(MAIN) << "Error opening" << outFile.fileName() << ":" + << outFile.errorString(); + qCWarning(MAIN) << "Caching the rooms state disabled"; + cacheState = false; + return; + } + + QJsonObject rootObj { + { QStringLiteral("cache_version"), + QJsonObject { + { QStringLiteral("major"), SyncData::cacheVersion().first }, + { QStringLiteral("minor"), SyncData::cacheVersion().second } } } + }; + { + QJsonObject trackedUsersJson; + QJsonObject outdatedUsersJson; + for (const auto &user : trackedUsers) { + trackedUsersJson.insert(user, QJsonValue::Null); + } + for (const auto &user : outdatedUsers) { + outdatedUsersJson.insert(user, QJsonValue::Null); + } + rootObj.insert(QStringLiteral("tracked_users"), trackedUsersJson); + rootObj.insert(QStringLiteral("outdated_users"), outdatedUsersJson); + QJsonObject devicesList = toJson<QHash<QString, QHash<QString, QueryKeysJob::DeviceInformation>>>(deviceKeys); + rootObj.insert(QStringLiteral("devices_list"), devicesList); + rootObj.insert(QStringLiteral("sync_token"), q->nextBatchToken()); + } + +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) + const auto data = + cacheToBinary ? QCborValue::fromJsonValue(rootObj).toCbor() + : QJsonDocument(rootObj).toJson(QJsonDocument::Compact); +#else + QJsonDocument json { rootObj }; + const auto data = cacheToBinary ? json.toBinaryData() + : json.toJson(QJsonDocument::Compact); +#endif + qCDebug(PROFILER) << "DeviceList generated in" << et; + + outFile.write(data.data(), data.size()); + qCDebug(E2EE) << "DevicesList saved to" << outFile.fileName(); +} + +void Connection::Private::loadDevicesList() +{ + QFile file { q->stateCacheDir().filePath("deviceslist.json") }; + if(!file.exists() || !file.open(QIODevice::ReadOnly)) { + qCDebug(E2EE) << "No devicesList cache exists. Creating new"; + createDevicesList(); + return; + } + auto data = file.readAll(); + const auto json = data.startsWith('{') + ? QJsonDocument::fromJson(data).object() +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) + : QCborValue::fromCbor(data).toJsonValue().toObject() +#else + : QJsonDocument::fromBinaryData(data).object() +#endif + ; + if (json.isEmpty()) { + qCWarning(MAIN) << "DevicesList cache is broken or empty, discarding"; + createDevicesList(); + return; + } + for(const auto &user : json["tracked_users"].toArray()) { + trackedUsers += user.toString(); + } + for(const auto &user : json["outdated_users"].toArray()) { + outdatedUsers += user.toString(); + } + + deviceKeys = fromJson<QHash<QString, QHash<QString, QueryKeysJob::DeviceInformation>>>(json["devices_list"].toObject()); + auto oldToken = json["sync_token"].toString(); + auto changesJob = q->callApi<GetKeysChangesJob>(oldToken, q->nextBatchToken()); + connect(changesJob, &BaseJob::success, q, [=](){ + for(const auto &user : changesJob->changed()) { + outdatedUsers += user; + } + loadOutdatedUserDevices(); + }); +} #endif diff --git a/lib/csapi/keys.h b/lib/csapi/keys.h index 7db09e8d..b1cc640c 100644 --- a/lib/csapi/keys.h +++ b/lib/csapi/keys.h @@ -166,6 +166,11 @@ struct JsonObjectConverter<QueryKeysJob::DeviceInformation> { fillFromJson<DeviceKeys>(jo, result); fromJson(jo.value("unsigned"_ls), result.unsignedData); } + static void dumpTo(QJsonObject& jo, const QueryKeysJob::DeviceInformation& deviceInformation) + { + jo = toJson<DeviceKeys>(deviceInformation); + //addParam<>(jo, "unsigned"_ls, deviceInformation.unsignedData); + } }; /*! \brief Claim one-time encryption keys. |