squawk/qomemo/database.cpp

181 lines
4.4 KiB
C++

/*
* Created by victoria on 2021-05-13.
*/
#include "database.h"
#include "bundle.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);
}
std::optional<QByteArray> Database::loadIdentityKeySecret(int deviceId) { return std::nullopt; }
bool Database::saveIdentityKeySecret(int deviceId,
const QByteArray &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());
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;
}
std::optional<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);
mdb_txn_abort(txn);
return std::nullopt;
}
if (value.mv_size != sizeof(int)) {
qWarning() << "mv_size is" << value.mv_size << "instead of" << sizeof(int);
mdb_txn_abort(txn);
return std::nullopt;
}
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;
}
bool Database::saveIdentityKey(int deviceId, const QByteArray &identityKey) {
return false;
}
std::optional<QByteArray> Database::loadIdentityKey(int deviceId) {
return std::nullopt;
}
bool Database::containsPreKey() {
return false;
}
std::optional<KeyPair> Database::loadPreKey(int deviceId, int id) {
return std::nullopt;
}
bool Database::savePreKey(int deviceId, int id, const KeyPair &preKey) {
return false;
}
std::optional<Bundle> Database::loadBundle(int deviceId) {
Bundle result{};
auto ik = loadIdentityKey(deviceId);
result.ik = ik.value();
auto spk = loadSignedPreKey(deviceId);
result.spk = spk->key.publicKey;
result.spks = spk->signature;
result.spkId = spk->id;
// PreKeys
return result;
}
bool Database::saveBundle(int deviceId, const Bundle &bundle) {
return false;
}
std::optional<SignedPreKey> Database::loadSignedPreKey(int deviceId) {
return std::optional<SignedPreKey>();
}
bool Database::saveSignedPreKey(int deviceId, const SignedPreKey &signedPreKey) {
return false;
}