BUILD FAILS! some ideas of storage and cache

This commit is contained in:
Blue 2022-09-03 14:39:42 +03:00
parent 87973b3b67
commit 820dc845ea
Signed by untrusted user: blue
GPG Key ID: 9B203B252A63EE38
10 changed files with 198 additions and 89 deletions

View File

@ -35,7 +35,12 @@ option(WITH_OMEMO "Build OMEMO support module" ON)
# Dependencies # Dependencies
## Qt ## Qt
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets DBus Gui Xml Network Core) if (NOT DEFINED QT_VERSION_MAJOR)
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets DBus Gui Xml Network Core)
else ()
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets DBus Gui Xml Network Core)
endif()
find_package(Boost COMPONENTS) find_package(Boost COMPONENTS)
target_include_directories(squawk PRIVATE ${Boost_INCLUDE_DIRS}) target_include_directories(squawk PRIVATE ${Boost_INCLUDE_DIRS})
@ -51,21 +56,15 @@ target_include_directories(squawk PRIVATE ${Qt${QT_VERSION_MAJOR}Core_INCLUDE_DI
if (WITH_OMEMO) if (WITH_OMEMO)
find_package(PkgConfig) find_package(PkgConfig)
if (PKG_CONFIG_FOUND) if (PKG_CONFIG_FOUND)
pkg_check_modules(OMEMO libomemo) pkg_check_modules(OMEMO libomemo-c)
if (OMEMO_FOUND) if (OMEMO_FOUND)
pkg_check_modules(SIGNAL libsignal-protocol-c) message("Building with support of OMEMO")
if (SIGNAL_FOUND)
message("Building with support of OMEMO")
else ()
message("signal-protocol package wasn't found, trying to build without OMEMO support")
set(WITH_OMEMO OFF)
endif()
else () else ()
message("libomemo package wasn't found, trying to build without OMEMO support") message("libomemo-c package wasn't found, trying to build without OMEMO support")
set(WITH_OMEMO OFF) set(WITH_OMEMO OFF)
endif () endif ()
else () else ()
message("PKG_CONFIG module wasn't found, can not check libomemo and libsignal-protocol support, trying to build without OMEMO support") message("PKG_CONFIG module wasn't found, can not check libomemo-c support, trying to build without OMEMO support")
set(WITH_OMEMO OFF) set(WITH_OMEMO OFF)
endif () endif ()
endif () endif ()
@ -129,16 +128,18 @@ endif()
if (NOT SYSTEM_QXMPP) if (NOT SYSTEM_QXMPP)
message("Building with bundled QXmpp") message("Building with bundled QXmpp")
target_include_directories(squawk PRIVATE ${CMAKE_SOURCE_DIR}/external/qxmpp/src/base)
target_include_directories(squawk PRIVATE ${CMAKE_SOURCE_DIR}/external/qxmpp/src/client)
if (WITH_OMEMO) if (WITH_OMEMO)
target_include_directories(squawk PRIVATE ${CMAKE_SOURCE_DIR}/external/qxmpp/src/omemo)
target_include_directories(squawk PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/external/qxmpp/src/omemo)
set(BUILD_OMEMO ON) set(BUILD_OMEMO ON)
target_compile_definitions(squawk PRIVATE WITH_OMEMO)
else () else ()
set(BUILD_OMEMO OFF) set(BUILD_OMEMO OFF)
endif () endif ()
add_subdirectory(external/qxmpp) add_subdirectory(external/qxmpp)
if (WITH_OMEMO)
target_include_directories(QXmppOmemo PRIVATE ${SIGNAL_INCLUDE_DIRS})
target_include_directories(QXmppOmemo PRIVATE ${OMEMO_INCLUDE_DIRS})
endif ()
target_link_libraries(squawk PRIVATE qxmpp) target_link_libraries(squawk PRIVATE qxmpp)
else () else ()

View File

@ -304,12 +304,16 @@ void Core::Account::onPresenceReceived(const QXmppPresence& p_presence)
break; break;
case QXmppPresence::Subscribe: case QXmppPresence::Subscribe:
qDebug("xmpp presence \"subscribe\" received, do not yet know what to do, skipping"); qDebug("xmpp presence \"subscribe\" received, do not yet know what to do, skipping");
break;
case QXmppPresence::Subscribed: case QXmppPresence::Subscribed:
qDebug("xmpp presence \"subscribed\" received, do not yet know what to do, skipping"); qDebug("xmpp presence \"subscribed\" received, do not yet know what to do, skipping");
break;
case QXmppPresence::Unsubscribe: case QXmppPresence::Unsubscribe:
qDebug("xmpp presence \"unsubscribe\" received, do not yet know what to do, skipping"); qDebug("xmpp presence \"unsubscribe\" received, do not yet know what to do, skipping");
break;
case QXmppPresence::Unsubscribed: case QXmppPresence::Unsubscribed:
qDebug("xmpp presence \"unsubscribed\" received, do not yet know what to do, skipping"); qDebug("xmpp presence \"unsubscribed\" received, do not yet know what to do, skipping");
break;
case QXmppPresence::Probe: case QXmppPresence::Probe:
qDebug("xmpp presence \"probe\" received, do not yet know what to do, skipping"); qDebug("xmpp presence \"probe\" received, do not yet know what to do, skipping");
break; break;

View File

@ -47,7 +47,7 @@ public slots:
private: private:
std::map<QString, Shared::ClientInfo> requested; std::map<QString, Shared::ClientInfo> requested;
Cache<Shared::ClientInfo> cache; Cache<QString, Shared::ClientInfo> cache;
std::map<QString, Shared::ClientInfo> specific; std::map<QString, Shared::ClientInfo> specific;
}; };

View File

@ -7,4 +7,6 @@ target_sources(squawk PRIVATE
vcardhandler.h vcardhandler.h
discoveryhandler.cpp discoveryhandler.cpp
discoveryhandler.h discoveryhandler.h
omemohandler.cpp
omemohandler.h
) )

View File

@ -0,0 +1,17 @@
// Squawk messenger.
// Copyright (C) 2019 Yury Gubich <blue@macaw.me>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "omemohandler.h"

View File

@ -0,0 +1,57 @@
// Squawk messenger.
// Copyright (C) 2019 Yury Gubich <blue@macaw.me>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef CORE_OMEMOHANDLER_H
#define CORE_OMEMOHANDLER_H
#include <QXmppOmemoStorage.h>
#include <core/storage/cache.h>
namespace Core {
class OmemoHandler : public QXmppOmemoStorage
{
public:
OmemoHandler();
~OmemoHandler() override;
QFuture<OmemoData> allData() override;
QFuture<void> setOwnDevice(const std::optional<OwnDevice> &device) override;
QFuture<void> addSignedPreKeyPair(uint32_t keyId, const SignedPreKeyPair &keyPair) override;
QFuture<void> removeSignedPreKeyPair(uint32_t keyId) override;
QFuture<void> addPreKeyPairs(const QHash<uint32_t, QByteArray> &keyPairs) override;
QFuture<void> removePreKeyPair(uint32_t keyId) override;
QFuture<void> addDevice(const QString &jid, uint32_t deviceId, const Device &device) override;
QFuture<void> removeDevice(const QString &jid, uint32_t deviceId) override;
QFuture<void> removeDevices(const QString &jid) override;
QFuture<void> resetAll() override;
private:
std::optional<OwnDevice> ownDevice;
Cache<QString, QHash<uint32_t, Device>> devices;
Cache<uint32_t, QByteArray> preKeyPairs;
Cache<uint32_t, QXmppOmemoStorage::SignedPreKeyPair> signedPreKeyPairs;
};
}
#endif // CORE_OMEMOHANDLER_H

View File

@ -26,7 +26,7 @@
namespace Core { namespace Core {
template <class T> template <class K, class V>
class Cache class Cache
{ {
public: public:
@ -36,16 +36,16 @@ public:
void open(); void open();
void close(); void close();
void addRecord(const QString& key, const T& value); void addRecord(const K& key, const V& value);
void changeRecord(const QString& key, const T& value); void changeRecord(const K& key, const V& value);
void removeRecord(const QString& key); void removeRecord(const K& key);
T getRecord(const QString& key) const; V getRecord(const K& key) const;
bool checkRecord(const QString& key) const; bool checkRecord(const K& key) const;
private: private:
Core::Storage<T> storage; Core::Storage<K, V> storage;
std::map<QString, T>* cache; std::map<K, V>* cache;
std::set<QString>* abscent; std::set<K>* abscent;
}; };
} }

View File

@ -18,44 +18,44 @@
#define CORE_CACHE_HPP #define CORE_CACHE_HPP
#include "cache.h" #include "cache.h"
template <class T> template <class K, class V>
Core::Cache<T>::Cache(const QString& name): Core::Cache<K, V>::Cache(const QString& name):
storage(name), storage(name),
cache(new std::map<QString, T> ()), cache(new std::map<K, V> ()),
abscent(new std::set<QString> ()) {} abscent(new std::set<K> ()) {}
template <class T> template <class K, class V>
Core::Cache<T>::~Cache() { Core::Cache<K, V>::~Cache() {
close(); close();
delete cache; delete cache;
delete abscent; delete abscent;
} }
template <class T> template <class K, class V>
void Core::Cache<T>::open() { void Core::Cache<K, V>::open() {
storage.open();} storage.open();}
template <class T> template <class K, class V>
void Core::Cache<T>::close() { void Core::Cache<K, V>::close() {
storage.close();} storage.close();}
template <class T> template <class K, class V>
void Core::Cache<T>::addRecord(const QString& key, const T& value) { void Core::Cache<K, V>::addRecord(const K& key, const V& value) {
storage.addRecord(key, value); storage.addRecord(key, value);
cache->insert(std::make_pair(key, value)); cache->insert(std::make_pair(key, value));
abscent->erase(key); abscent->erase(key);
} }
template <class T> template <class K, class V>
T Core::Cache<T>::getRecord(const QString& key) const { V Core::Cache<K, V>::getRecord(const K& key) const {
typename std::map<QString, T>::const_iterator itr = cache->find(key); typename std::map<K, V>::const_iterator itr = cache->find(key);
if (itr == cache->end()) { if (itr == cache->end()) {
if (abscent->count(key) > 0) { if (abscent->count(key) > 0) {
throw Archive::NotFound(key, storage.getName().toStdString()); throw Archive::NotFound(std::to_string(key), storage.getName().toStdString());
} }
try { try {
T value = storage.getRecord(key); V value = storage.getRecord(key);
itr = cache->insert(std::make_pair(key, value)).first; itr = cache->insert(std::make_pair(key, value)).first;
} catch (const Archive::NotFound& error) { } catch (const Archive::NotFound& error) {
abscent->insert(key); abscent->insert(key);
@ -66,9 +66,9 @@ T Core::Cache<T>::getRecord(const QString& key) const {
return itr->second; return itr->second;
} }
template<class T> template<class K, class V>
bool Core::Cache<T>::checkRecord(const QString& key) const { bool Core::Cache<K, V>::checkRecord(const K& key) const {
typename std::map<QString, T>::const_iterator itr = cache->find(key); typename std::map<K, V>::const_iterator itr = cache->find(key);
if (itr != cache->end()) if (itr != cache->end())
return true; return true;
@ -76,7 +76,7 @@ bool Core::Cache<T>::checkRecord(const QString& key) const {
return false; return false;
try { try {
T value = storage.getRecord(key); V value = storage.getRecord(key);
itr = cache->insert(std::make_pair(key, value)).first; itr = cache->insert(std::make_pair(key, value)).first;
} catch (const Archive::NotFound& error) { } catch (const Archive::NotFound& error) {
return false; return false;
@ -85,15 +85,15 @@ bool Core::Cache<T>::checkRecord(const QString& key) const {
return true; return true;
} }
template<typename T> template<class K, class V>
void Core::Cache<T>::changeRecord(const QString& key, const T& value) { void Core::Cache<K, V>::changeRecord(const K& key, const V& value) {
storage.changeRecord(key, value); //there is a non straightforward behaviour: if there was no element at the sorage it will be added storage.changeRecord(key, value); //there is a non straightforward behaviour: if there was no element at the sorage it will be added
cache->at(key) = value; cache->at(key) = value;
abscent->erase(key); //so... this line here is to make it coherent with the storage abscent->erase(key); //so... this line here is to make it coherent with the storage
} }
template<typename T> template<class K, class V>
void Core::Cache<T>::removeRecord(const QString& key) { void Core::Cache<K, V>::removeRecord(const K& key) {
storage.removeRecord(key); storage.removeRecord(key);
cache->erase(key); cache->erase(key);
abscent->insert(key); abscent->insert(key);

View File

@ -29,7 +29,7 @@ namespace Core {
/** /**
* @todo write docs * @todo write docs
*/ */
template <class T> template <class K, class V>
class Storage class Storage
{ {
public: public:
@ -39,10 +39,10 @@ public:
void open(); void open();
void close(); void close();
void addRecord(const QString& key, const T& value); void addRecord(const K& key, const V& value);
void changeRecord(const QString& key, const T& value); void changeRecord(const K& key, const V& value);
void removeRecord(const QString& key); void removeRecord(const K& key);
T getRecord(const QString& key) const; V getRecord(const K& key) const;
QString getName() const; QString getName() const;
@ -55,6 +55,16 @@ private:
} }
MDB_val& operator << (MDB_val& data, QString& value);
MDB_val& operator >> (MDB_val& data, QString& value);
MDB_val& operator << (MDB_val& data, uint32_t& value);
MDB_val& operator >> (MDB_val& data, uint32_t& value);
namespace std {
std::string to_string(const QString& str);
}
#include "storage.hpp" #include "storage.hpp"
#endif // CORE_STORAGE_H #endif // CORE_STORAGE_H

View File

@ -22,9 +22,10 @@
#include <QDir> #include <QDir>
#include "storage.h" #include "storage.h"
#include <cstring>
template <class T> template <class K, class V>
Core::Storage<T>::Storage(const QString& p_name): Core::Storage<K, V>::Storage(const QString& p_name):
name(p_name), name(p_name),
opened(false), opened(false),
environment(), environment(),
@ -32,14 +33,14 @@ Core::Storage<T>::Storage(const QString& p_name):
{ {
} }
template <class T> template <class K, class V>
Core::Storage<T>::~Storage() Core::Storage<K, V>::~Storage()
{ {
close(); close();
} }
template <class T> template <class K, class V>
void Core::Storage<T>::open() void Core::Storage<K, V>::open()
{ {
if (!opened) { if (!opened) {
mdb_env_create(&environment); mdb_env_create(&environment);
@ -66,8 +67,8 @@ void Core::Storage<T>::open()
} }
} }
template <class T> template <class K, class V>
void Core::Storage<T>::close() void Core::Storage<K, V>::close()
{ {
if (opened) { if (opened) {
mdb_dbi_close(environment, base); mdb_dbi_close(environment, base);
@ -76,20 +77,19 @@ void Core::Storage<T>::close()
} }
} }
template <class T> template <class K, class V>
void Core::Storage<T>::addRecord(const QString& key, const T& value) void Core::Storage<K, V>::addRecord(const K& key, const V& value)
{ {
if (!opened) { if (!opened) {
throw Archive::Closed("addRecord", name.toStdString()); throw Archive::Closed("addRecord", name.toStdString());
} }
QByteArray ba; QByteArray ba;
QDataStream ds(&ba, QIODevice::WriteOnly); QDataStream ds(&ba, QIODevice::WriteOnly);
const std::string& id = key.toStdString();
ds << value; ds << value;
MDB_val lmdbKey, lmdbData; MDB_val lmdbKey, lmdbData;
lmdbKey.mv_size = id.size(); lmdbKey << key;
lmdbKey.mv_data = (char*)id.c_str();
lmdbData.mv_size = ba.size(); lmdbData.mv_size = ba.size();
lmdbData.mv_data = (uint8_t*)ba.data(); lmdbData.mv_data = (uint8_t*)ba.data();
MDB_txn *txn; MDB_txn *txn;
@ -99,7 +99,7 @@ void Core::Storage<T>::addRecord(const QString& key, const T& value)
if (rc != 0) { if (rc != 0) {
mdb_txn_abort(txn); mdb_txn_abort(txn);
if (rc == MDB_KEYEXIST) { if (rc == MDB_KEYEXIST) {
throw Archive::Exist(name.toStdString(), id); throw Archive::Exist(name.toStdString(), std::to_string(key));
} else { } else {
throw Archive::Unknown(name.toStdString(), mdb_strerror(rc)); throw Archive::Unknown(name.toStdString(), mdb_strerror(rc));
} }
@ -108,8 +108,8 @@ void Core::Storage<T>::addRecord(const QString& key, const T& value)
} }
} }
template <class T> template <class K, class V>
void Core::Storage<T>::changeRecord(const QString& key, const T& value) void Core::Storage<K, V>::changeRecord(const K& key, const V& value)
{ {
if (!opened) { if (!opened) {
throw Archive::Closed("changeRecord", name.toStdString()); throw Archive::Closed("changeRecord", name.toStdString());
@ -117,12 +117,10 @@ void Core::Storage<T>::changeRecord(const QString& key, const T& value)
QByteArray ba; QByteArray ba;
QDataStream ds(&ba, QIODevice::WriteOnly); QDataStream ds(&ba, QIODevice::WriteOnly);
const std::string& id = key.toStdString();
ds << value; ds << value;
MDB_val lmdbKey, lmdbData; MDB_val lmdbKey, lmdbData;
lmdbKey.mv_size = id.size(); lmdbKey << key;
lmdbKey.mv_data = (char*)id.c_str();
lmdbData.mv_size = ba.size(); lmdbData.mv_size = ba.size();
lmdbData.mv_data = (uint8_t*)ba.data(); lmdbData.mv_data = (uint8_t*)ba.data();
MDB_txn *txn; MDB_txn *txn;
@ -139,17 +137,15 @@ void Core::Storage<T>::changeRecord(const QString& key, const T& value)
} }
} }
template <class T> template <class K, class V>
T Core::Storage<T>::getRecord(const QString& key) const V Core::Storage<K, V>::getRecord(const K& key) const
{ {
if (!opened) { if (!opened) {
throw Archive::Closed("addElement", name.toStdString()); throw Archive::Closed("addElement", name.toStdString());
} }
const std::string& id = key.toStdString();
MDB_val lmdbKey, lmdbData; MDB_val lmdbKey, lmdbData;
lmdbKey.mv_size = id.size(); lmdbKey << key;
lmdbKey.mv_data = (char*)id.c_str();
MDB_txn *txn; MDB_txn *txn;
int rc; int rc;
@ -158,14 +154,14 @@ T Core::Storage<T>::getRecord(const QString& key) const
if (rc) { if (rc) {
mdb_txn_abort(txn); mdb_txn_abort(txn);
if (rc == MDB_NOTFOUND) { if (rc == MDB_NOTFOUND) {
throw Archive::NotFound(id, name.toStdString()); throw Archive::NotFound(std::to_string(key), name.toStdString());
} else { } else {
throw Archive::Unknown(name.toStdString(), mdb_strerror(rc)); throw Archive::Unknown(name.toStdString(), mdb_strerror(rc));
} }
} else { } else {
QByteArray ba((char*)lmdbData.mv_data, lmdbData.mv_size); QByteArray ba((char*)lmdbData.mv_data, lmdbData.mv_size);
QDataStream ds(&ba, QIODevice::ReadOnly); QDataStream ds(&ba, QIODevice::ReadOnly);
T value; V value;
ds >> value; ds >> value;
mdb_txn_abort(txn); mdb_txn_abort(txn);
@ -173,17 +169,15 @@ T Core::Storage<T>::getRecord(const QString& key) const
} }
} }
template <class T> template <class K, class V>
void Core::Storage<T>::removeRecord(const QString& key) void Core::Storage<K, V>::removeRecord(const K& key)
{ {
if (!opened) { if (!opened) {
throw Archive::Closed("addElement", name.toStdString()); throw Archive::Closed("addElement", name.toStdString());
} }
const std::string& id = key.toStdString();
MDB_val lmdbKey; MDB_val lmdbKey;
lmdbKey.mv_size = id.size(); lmdbKey << key;
lmdbKey.mv_data = (char*)id.c_str();
MDB_txn *txn; MDB_txn *txn;
int rc; int rc;
@ -192,7 +186,7 @@ void Core::Storage<T>::removeRecord(const QString& key)
if (rc) { if (rc) {
mdb_txn_abort(txn); mdb_txn_abort(txn);
if (rc == MDB_NOTFOUND) { if (rc == MDB_NOTFOUND) {
throw Archive::NotFound(id, name.toStdString()); throw Archive::NotFound(std::to_string(key), name.toStdString());
} else { } else {
throw Archive::Unknown(name.toStdString(), mdb_strerror(rc)); throw Archive::Unknown(name.toStdString(), mdb_strerror(rc));
} }
@ -201,8 +195,32 @@ void Core::Storage<T>::removeRecord(const QString& key)
} }
} }
template <class T> template <class K, class V>
QString Core::Storage<T>::getName() const { QString Core::Storage<K, V>::getName() const {
return name;} return name;}
MDB_val& operator << (MDB_val& data, const QString& value) {
QByteArray ba = value.toUtf8();
data.mv_size = ba.size();
data.mv_data = ba.data();
return data;
}
MDB_val& operator >> (MDB_val& data, QString& value) {
value = QString::fromUtf8((const char*)data.mv_data, data.mv_size);
return data;
}
MDB_val& operator << (MDB_val& data, uint32_t& value) {
data.mv_size = 4;
data.mv_data = &value;
return data;
}
MDB_val& operator >> (MDB_val& data, uint32_t& value) {
std::memcpy(&value, data.mv_data, data.mv_size);
return data;
}
std::string std::to_string(const QString& str) {
return str.toStdString();
}
#endif //CORE_STORAGE_HPP #endif //CORE_STORAGE_HPP