aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorTobias Fella <fella@posteo.de>2021-05-21 00:29:08 +0200
committerTobias Fella <fella@posteo.de>2021-12-01 21:56:11 +0100
commit265f105d77bf91c127c363b0c880357f91df7db4 (patch)
tree697c46084064a1eb21b1ef0447f913fd17ca0a48 /lib
parent5d3fe54fdfae4b74272a80c4bbe8f5d8a3e4c5cb (diff)
downloadlibquotient-265f105d77bf91c127c363b0c880357f91df7db4.tar.gz
libquotient-265f105d77bf91c127c363b0c880357f91df7db4.zip
Cache deviceslist across restarts
Diffstat (limited to 'lib')
-rw-r--r--lib/connection.cpp99
-rw-r--r--lib/csapi/keys.h5
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.