ref(omemo): bundle separate, add db

This commit is contained in:
vae 2021-05-13 17:50:59 +03:00
parent 2654e38665
commit 574210f5d9
Signed by: vae
GPG Key ID: A9A33351400E00E5
9 changed files with 189 additions and 14 deletions

View File

@ -64,7 +64,9 @@ QXmppIq QXmpp::Omemo::Bundle::toIq(int deviceId) const {
item.appendChild(toXml()); item.appendChild(toXml());
auto publish = createElement("publish"); auto publish = createElement("publish");
publish.setAttribute("node", QString("eu.siacs.conversations.axolotl.bundles:%s").arg(deviceId)); publish.setAttribute(
"node",
QString("eu.siacs.conversations.axolotl.bundles:%s").arg(deviceId));
publish.appendChild(item); publish.appendChild(item);
auto pubSub = createElement("pubsub", "http://jabber.org/protocol/pubsub"); auto pubSub = createElement("pubsub", "http://jabber.org/protocol/pubsub");
@ -116,7 +118,8 @@ void QXmpp::Omemo::Bundle::fromXml(const QXmppElement &element) {
QXmppPubSubIq QXmpp::Omemo::Bundle::fetchDeviceBundleIq(int deviceId) { QXmppPubSubIq QXmpp::Omemo::Bundle::fetchDeviceBundleIq(int deviceId) {
QXmppPubSubIq iq{}; QXmppPubSubIq iq{};
iq.setType(QXmppIq::Get); iq.setType(QXmppIq::Get);
iq.setQueryNode(QString("eu.siacs.conversations.axolotl.bundles:%1").arg(deviceId)); iq.setQueryNode(
QString("eu.siacs.conversations.axolotl.bundles:%1").arg(deviceId));
QXmppPubSubItem item{}; QXmppPubSubItem item{};
item.setId(QString::number(deviceId)); item.setId(QString::number(deviceId));

View File

@ -38,4 +38,4 @@ public:
QList<PreKey> prekeys; QList<PreKey> prekeys;
}; };
} } // namespace QXmpp::Omemo

126
qomemo/database.cpp Normal file
View File

@ -0,0 +1,126 @@
/*
* Created by victoria on 2021-05-13.
*/
#include "database.h"
#include <QDebug>
#include <QDir>
#include <QException>
#include <QStandardPaths>
#include <QString>
using namespace QXmpp::Omemo;
Database::Database(QString jid) : jid(std::move(jid)) {
auto cacheLocation =
QStandardPaths::writableLocation(QStandardPaths::CacheLocation);
auto path = QString("%1/.omemo/%2").arg(cacheLocation, jid);
QDir cache(path);
if (!cache.exists() && !cache.mkpath(path)) {
qWarning() << "Could not create:" << path;
throw QException();
}
mdb_env_create(&env);
mdb_env_set_maxdbs(env, 5);
mdb_env_set_mapsize(env, 512UL * 1024UL * 1024UL);
mdb_env_open(env, path.toStdString().c_str(), 0, 0664);
MDB_txn *txn;
mdb_txn_begin(env, nullptr, 0, &txn);
mdb_dbi_open(txn, "keys", MDB_CREATE, &dbiKeys);
mdb_dbi_open(txn, "devices", MDB_CREATE, &dbiDevices);
mdb_dbi_open(txn, "identity_keys", MDB_CREATE, &dbiIdentityKeys);
mdb_txn_commit(txn);
}
Database::~Database() {
mdb_dbi_close(env, dbiKeys);
mdb_dbi_close(env, dbiDevices);
mdb_dbi_close(env, dbiIdentityKeys);
mdb_env_close(env);
}
QBuffer Database::loadIdentityKeySecret(int deviceId) { return QBuffer(); }
bool Database::saveIdentityKeySecret(int deviceId,
const QBuffer &identityKeySecret) {
MDB_val mdbKey, mdbValue;
auto key = QString("%1/secret").arg(QString::number(deviceId)).toStdString();
mdbKey.mv_data = key.data();
mdbKey.mv_size = key.size();
mdbValue.mv_data = const_cast<char *>(identityKeySecret.data().data());
mdbValue.mv_size = identityKeySecret.size();
MDB_txn *txn;
mdb_txn_begin(env, nullptr, 0, &txn);
auto err = mdb_put(txn, dbiIdentityKeys, &mdbKey, &mdbValue, MDB_NOOVERWRITE);
if (!err) {
mdb_txn_commit(txn);
return true;
}
qWarning() << "could not save identity key secret:" << mdb_strerror(err);
mdb_txn_abort(txn);
return false;
}
int Database::loadActiveDeviceId() {
MDB_val key, value;
key.mv_data = (void *)"active";
key.mv_size = sizeof("active");
MDB_txn *txn;
mdb_txn_begin(env, nullptr, 0, &txn);
auto err = mdb_get(txn, dbiIdentityKeys, &key, &value);
if (err) {
qWarning() << "could not load active device id:" << mdb_strerror(err);
return 0;
}
if (value.mv_size != sizeof(int)) {
qWarning() << "mv_size is" << value.mv_size << "instead of" << sizeof(int);
return 0;
}
auto id = *reinterpret_cast<int *>(value.mv_data);
mdb_txn_abort(txn);
return id;
}
bool Database::saveActiveDeviceId(int deviceId) {
MDB_val key, value;
key.mv_data = (void *)"active";
key.mv_size = sizeof("active");
value.mv_data = &deviceId;
value.mv_size = sizeof(deviceId);
MDB_txn *txn;
mdb_txn_begin(env, nullptr, 0, &txn);
auto err = mdb_put(txn, dbiIdentityKeys, &key, &value, 0);
if (err) {
qWarning() << "could not save active device id" << mdb_strerror(err);
return false;
}
err = mdb_txn_commit(txn);
if (err) {
qWarning() << "could not save active device id" << mdb_strerror(err);
return false;
}
return true;
}

40
qomemo/database.h Normal file
View File

@ -0,0 +1,40 @@
/*
* Created by victoria on 2021-05-13.
*/
#pragma once
#include <QBuffer>
#include <QString>
#include <lmdb.h>
namespace QXmpp::Omemo {
class Database {
public:
explicit Database(QString jid);
~Database();
Database(const Database &) = delete;
Database(Database &&) = delete;
Database &operator=(const Database &) = delete;
QBuffer loadIdentityKey();
bool saveIdentityKey(const QBuffer &identityKey);
int loadActiveDeviceId();
bool saveActiveDeviceId(int deviceId);
QBuffer loadIdentityKeySecret(int deviceId);
bool saveIdentityKeySecret(int deviceId, const QBuffer &identityKeySecret);
const QString jid;
private:
MDB_env *env{};
MDB_dbi dbiDevices{};
MDB_dbi dbiKeys{};
MDB_dbi dbiPreKeys{};
MDB_dbi dbiIdentityKeys{};
};
} // namespace QXmpp::Omemo

View File

@ -20,7 +20,7 @@ public:
explicit DeviceService(QObject *parent); explicit DeviceService(QObject *parent);
public slots: public slots:
void onDeviceListReceived(const QString& jid, const DeviceList& list); void onDeviceListReceived(const QString &jid, const DeviceList &list);
private: private:
QMap<QString, UserDeviceList> device_lists{}; QMap<QString, UserDeviceList> device_lists{};

View File

@ -15,8 +15,11 @@
using namespace QXmpp::Omemo; using namespace QXmpp::Omemo;
Manager::Manager() : deviceService(new DeviceService(this)), omemoVariant(new Variant::Conversations) { Manager::Manager()
connect(this, &Manager::deviceListReceived, deviceService.get(), &DeviceService::onDeviceListReceived); : deviceService(new DeviceService(this)),
omemoVariant(new Variant::Conversations) {
connect(this, &Manager::deviceListReceived, deviceService.get(),
&DeviceService::onDeviceListReceived);
} }
bool QXmpp::Omemo::Manager::handleStanza(const QDomElement &stanza) { bool QXmpp::Omemo::Manager::handleStanza(const QDomElement &stanza) {
@ -31,7 +34,8 @@ bool QXmpp::Omemo::Manager::handleStanza(const QDomElement &stanza) {
auto pubsub = stanza.firstChildElement("pubsub"); auto pubsub = stanza.firstChildElement("pubsub");
if (!pubsub.isNull()) { if (!pubsub.isNull()) {
auto items = pubsub.firstChildElement("items"); auto items = pubsub.firstChildElement("items");
if (items.attribute("node") == "eu.siacs.conversations.axolotl.devicelist") { if (items.attribute("node") ==
"eu.siacs.conversations.axolotl.devicelist") {
auto item = items.firstChildElement("item"); auto item = items.firstChildElement("item");
if (!item.isNull()) { if (!item.isNull()) {
auto list = item.firstChildElement("list"); auto list = item.firstChildElement("list");
@ -56,7 +60,8 @@ void QXmpp::Omemo::Manager::setClient(QXmppClient *client) {
if (!client) if (!client)
return; return;
QObject::connect(client, &QXmppClient::connected, this, &Manager::fetchOwnDevices); QObject::connect(client, &QXmppClient::connected, this,
&Manager::fetchOwnDevices);
} }
void QXmpp::Omemo::Manager::fetchOwnDevices() { void QXmpp::Omemo::Manager::fetchOwnDevices() {

View File

@ -4,8 +4,8 @@
#pragma once #pragma once
#include <QXmppElement.h>
#include <QDateTime> #include <QDateTime>
#include <QXmppElement.h>
namespace QXmpp::Sce { namespace QXmpp::Sce {

View File

@ -5,6 +5,7 @@
#pragma once #pragma once
#include <QString> #include <QString>
namespace QXmpp::Omemo { namespace QXmpp::Omemo {
class UserDeviceList { class UserDeviceList {

View File

@ -18,12 +18,12 @@ class Base {
public: public:
virtual ~Base() = default; virtual ~Base() = default;
virtual QXmppElement deviceToXml(const Device& device) = 0; virtual QXmppElement deviceToXml(const Device &device) = 0;
virtual Device deviceFromXml(const QXmppElement& xml) = 0; virtual Device deviceFromXml(const QXmppElement &xml) = 0;
virtual QXmppElement deviceListToXml(const DeviceList& deviceList) = 0; virtual QXmppElement deviceListToXml(const DeviceList &deviceList) = 0;
virtual DeviceList deviceListFromXml(const QXmppElement& xml) = 0; virtual DeviceList deviceListFromXml(const QXmppElement &xml) = 0;
virtual QXmppIq deviceListSetIq(const DeviceList& deviceList) = 0; virtual QXmppIq deviceListSetIq(const DeviceList &deviceList) = 0;
}; };
} // namespace Variant } // namespace Variant