4
1
mirror of https://github.com/QuasarApp/Heart.git synced 2025-05-12 01:19:42 +00:00

remove rudiment code

This commit is contained in:
Andrei Yankovich 2022-11-25 00:07:51 +03:00
parent 102aae32d6
commit 7d5aa6070e
95 changed files with 316 additions and 7501 deletions
Heart
HeartTests/DataBaseSpace

@ -13,6 +13,7 @@
#include <abstractnode.h>
#include <cmath>
#include <params.h>
#include <bigdatawraper.h>
#define TIMEOUT_INTERVAL 30000
@ -20,9 +21,11 @@ namespace QH {
BigDataParser::BigDataParser(AbstractNode* parentNode): iParser(parentNode) {
registerPackageType<PKG::BigDataWraper>();
registerPackageType<PKG::BigDataRequest>();
registerPackageType<PKG::BigDataHeader>();
registerPackageType<PKG::BigDataPart>();
}
ParserResult BigDataParser::parsePackage(const QSharedPointer<PKG::AbstractData> &pkg,
@ -37,6 +40,13 @@ ParserResult BigDataParser::parsePackage(const QSharedPointer<PKG::AbstractData>
return result;
}
result = commandHandler<PKG::BigDataWraper>(this,
&BigDataParser::processBigDataWraper,
pkg, sender, pkgHeader);
if (result != QH::ParserResult::NotProcessed) {
return result;
}
result = commandHandler<PKG::BigDataHeader>(this,
&BigDataParser::newPackage,
pkg, sender, pkgHeader);
@ -174,6 +184,12 @@ bool BigDataParser::processRequest(const QSharedPointer<PKG::BigDataRequest> &re
return true;
}
bool BigDataParser::processBigDataWraper(const QSharedPointer<PKG::BigDataWraper> &request,
AbstractNodeInfo *sender,
const Header &pkgHeader) {
return sendBigDataPackage(request->data(), sender, &pkgHeader);
}
bool BigDataParser::sendBigDataPackage(const PKG::AbstractData *data,
const AbstractNodeInfo *sender,
const QH::Header *pkgHeader) {

@ -18,6 +18,7 @@ namespace PKG {
class BigDataHeader;
class BigDataPart;
class BigDataRequest;
class BigDataWraper;
}
class AbstractNode;
@ -85,13 +86,24 @@ protected:
* @param pkgHeader requested header.
* @return true if package sent successful
*/
bool sendBigDataPackage(const PKG::AbstractData *data,
const QH::AbstractNodeInfo *sender,
const Header *pkgHeader);
bool processBigDataWraper(const QSharedPointer<PKG::BigDataWraper> &request,
AbstractNodeInfo *sender,
const Header &pkgHeader);
private:
/**
* @brief sendBigDataPackage This method separate big pacakge and sent only heder ot serve.
* @param data This is package that will be sent to remote node.
* @param sender This is request object.
* @param pkgHeader requested header.
* @return true if package sent successful
*/
bool sendBigDataPackage(const PKG::AbstractData *data,
const QH::AbstractNodeInfo *sender,
const Header *pkgHeader);
void insertNewBigData(const QSharedPointer<PKG::BigDataHeader> &header);
void checkOutDatedPacakges(unsigned int currentProcessedId);

@ -1,62 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#include "versionparser.h"
namespace QH {
VersionParser::VersionParser() {
}
ParserResult VersionParser::parsePackage(const QSharedPointer<PKG::AbstractData> &pkg,
const Header &pkgHeader,
const AbstractNodeInfo *sender) {
// auto parentResult = AbstractNode::parsePackage(pkg, pkgHeader, sender);
// if (parentResult != QH::ParserResult::NotProcessed) {
// return parentResult;
// }
// here node must be receive version of connected application.
// if not use the default version (0)ApplicationVersion
parentResult = commandHandler<ApplicationVersion>(this, &BaseNode::processAppVersion,
pkg, sender, pkgHeader);
if (parentResult != QH::ParserResult::NotProcessed) {
return parentResult;
}
// here node must be receive responce that version is delivered.
// when node receive this message then node status are confirmed
parentResult = commandHandler<VersionIsReceived>(this, &BaseNode::versionDeliveredSuccessful,
pkg, sender, pkgHeader);
if (parentResult != QH::ParserResult::NotProcessed) {
return parentResult;
}
auto distVersion = static_cast<const NodeInfo*>(sender)->version();
auto parser = selectParser(distVersion);
if (!parser) {
QuasarAppUtils::Params::log(QString("Can't found requeried parser for versions: %0-%1").
arg(distVersion.minimum()).
arg(distVersion.maximum()),
QuasarAppUtils::Warning);
return QH::ParserResult::NotProcessed;
}
return parser->parsePackage(pkg, pkgHeader, sender);
}
int VersionParser::version() const {
return 0;
}
QString VersionParser::parserId() const {
return "QHNodeVersionParser";
}
}

@ -1,34 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#ifndef VERSIONPARSER_H
#define VERSIONPARSER_H
#include <iparser.h>
namespace QH {
/**
* @brief The VersionParser class This is base parser. This parser have only one version is 0 because node du not has any version information in this step.
*/
class VersionParser: public QH::iParser
{
public:
VersionParser();
// iParser interface
public:
ParserResult parsePackage(const QSharedPointer<PKG::AbstractData> &pkg,
const Header &pkgHeader,
const AbstractNodeInfo *sender) override;
int version() const override;
QString parserId() const override;
};
}
#endif // VERSIONPARSER_H

@ -43,13 +43,18 @@
#include <apiversion.h>
#include <versionisreceived.h>
#include <taskscheduler.h>
#include <qaglobalutils.h>
#include <bigdatawraper.h>
#include <bigdataparser.h>
#include <abstractnodeparser.h>
namespace QH {
using namespace PKG;
AbstractNode::AbstractNode( QObject *ptr):
QTcpServer(ptr) {
QTcpServer(ptr),
iParser(this) {
initThreadId();
@ -64,6 +69,9 @@ AbstractNode::AbstractNode( QObject *ptr):
_tasksheduller = new TaskScheduler();
_apiVersionParser = new APIVersionParser(this);
_apiVersionParser->addApiParser<BigDataParser>();
_apiVersionParser->addApiParser<AbstractNodeParser>();
qRegisterMetaType<QSharedPointer<QH::AbstractTask>>();
#ifdef USE_HEART_SSL
qRegisterMetaType<QList<QSslError>>();
@ -241,7 +249,7 @@ bool AbstractNode::addNode(const QString &domain, unsigned short port,
if (info.error() != QHostInfo::NoError) {
QuasarAppUtils::Params::log("The domain name :" + domain +
" has error: " + info.errorString(),
" has error: " + info.errorString(),
QuasarAppUtils::Error);
addNodeFailed(AddNodeError::HostNotFound);
return;
@ -251,7 +259,7 @@ bool AbstractNode::addNode(const QString &domain, unsigned short port,
if (addresses.size() > 1) {
QuasarAppUtils::Params::log("The domain name :" + domain +
" has more 1 ip addresses.",
" has more 1 ip addresses.",
QuasarAppUtils::Warning);
}
@ -316,29 +324,29 @@ bool AbstractNode::generateRSAforSSL(EVP_PKEY *pkey) const {
return false;
}
//#if OPENSSL_VERSION_MAJOR >= 3
//#if OPENSSL_VERSION_MAJOR >= 3
// EVP_PKEY_CTX *pctx =
// EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL);
// EVP_PKEY_CTX *pctx =
// EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL);
// unsigned int primes = 3;
// unsigned int bits = 4096;
// OSSL_PARAM params[3];
// unsigned int primes = 3;
// unsigned int bits = 4096;
// OSSL_PARAM params[3];
// pkey = EVP_RSA_gen(4096);
// pkey = EVP_RSA_gen(4096);
// EVP_PKEY_keygen_init(pctx);
// EVP_PKEY_keygen_init(pctx);
// params[0] = OSSL_PARAM_construct_uint("bits", &bits);
// params[1] = OSSL_PARAM_construct_uint("primes", &primes);
// params[2] = OSSL_PARAM_construct_end();
// EVP_PKEY_CTX_set_params(pctx, params);
// params[0] = OSSL_PARAM_construct_uint("bits", &bits);
// params[1] = OSSL_PARAM_construct_uint("primes", &primes);
// params[2] = OSSL_PARAM_construct_end();
// EVP_PKEY_CTX_set_params(pctx, params);
// EVP_PKEY_generate(pctx, &pkey);
// EVP_PKEY_CTX_free(pctx);
// EVP_PKEY_generate(pctx, &pkey);
// EVP_PKEY_CTX_free(pctx);
//#else
//#else
BIGNUM * bn = BN_new();
int rc = BN_set_word(bn, RSA_F4);
@ -357,7 +365,7 @@ bool AbstractNode::generateRSAforSSL(EVP_PKEY *pkey) const {
q_check_ptr(rsa);
if (EVP_PKEY_assign_RSA(pkey, rsa) <= 0)
return false;
//#endif
//#endif
return true;
}
@ -531,7 +539,7 @@ bool AbstractNode::useSelfSignedSslConfiguration(const SslSrtData &crtData) {
_ignoreSslErrors.push_back(QSslError{QSslError::SelfSignedCertificate});
if(!_ignoreSslErrors.contains(QSslError{QSslError::SelfSignedCertificateInChain}))
_ignoreSslErrors.push_back(QSslError{QSslError::SelfSignedCertificateInChain});
_ignoreSslErrors.push_back(QSslError{QSslError::SelfSignedCertificateInChain});
return !_ssl.isNull();
}
@ -669,9 +677,9 @@ ParserResult AbstractNode::parsePackage(const QSharedPointer<AbstractData> &pkg,
return _apiVersionParser->parsePackage(pkg, pkgHeader, sender);
}
QSharedPointer<AbstractData>
AbstractNode::genPackage(unsigned short cmd) const {
QSharedPointer<AbstractData> AbstractNode::genPackage(unsigned short ) const {
debug_assert(false, "the AbstractNode::genPackage is disabled. use the searchPackage");
return nullptr;
}
bool AbstractNode::sendPackage(const Package &pkg, QAbstractSocket *target) const {
@ -715,7 +723,7 @@ unsigned int AbstractNode::sendData(const PKG::AbstractData *resp,
Package pkg;
bool convert = false;
if (req) {
if (req && req->isValid()) {
convert = resp->toPackage(pkg, req->hash);
} else {
convert = resp->toPackage(pkg);
@ -726,9 +734,9 @@ unsigned int AbstractNode::sendData(const PKG::AbstractData *resp,
if (static_cast<unsigned int>(pkg.data.size()) > Package::maximumSize()) {
// big data
if (!_bigdatamanager->sendBigDataPackage(resp,
node,
req)) {
auto wrap = QSharedPointer<BigDataWraper>::create();
wrap->setData(resp);
if ( parsePackage(wrap, {}, getInfoPtr(node->networkAddress())) != ParserResult::Processed) {
return 0;
}
@ -759,7 +767,7 @@ void AbstractNode::badRequest(const HostAddress &address, const Header &req,
QuasarAppUtils::Error);
QuasarAppUtils::Params::log("SECURITY LOG: Force block the " + address.toString() +
" because trust defined",
" because trust defined",
QuasarAppUtils::Error);
ban(address);
@ -773,7 +781,7 @@ void AbstractNode::badRequest(const HostAddress &address, const Header &req,
}
QuasarAppUtils::Params::log("Bad request sendet to adderess: " +
address.toString(),
address.toString(),
QuasarAppUtils::Info);
}
@ -1066,9 +1074,11 @@ bool AbstractNode::listen(const HostAddress &address) {
return QTcpServer::listen(address, address.port());
}
QSharedPointer<AbstractData> AbstractNode::prepareData(const Package &pkg) const {
QSharedPointer<AbstractData>
AbstractNode::prepareData(const Package &pkg,
AbstractNodeInfo *sender) const {
auto value = genPackage (pkg.hdr.command);
auto value = _apiVersionParser->searchPackage(pkg.hdr.command, sender);
if (!value) {
QuasarAppUtils::Params::log("You try parse not registered package type."
" Plese use the registerPackageType method befor parsing."
@ -1149,7 +1159,7 @@ void AbstractNode::newWork(const Package &pkg, AbstractNodeInfo *sender,
auto executeObject = [pkg, sender, id, this]() {
auto data = prepareData(pkg);
auto data = prepareData(pkg, sender);
if (!data)
return false;
@ -1158,7 +1168,7 @@ void AbstractNode::newWork(const Package &pkg, AbstractNodeInfo *sender,
if (parseResult != ParserResult::Processed) {
auto message = QString("Package not parsed! %0 \nresult: %1. \n%2").
arg(pkg.toString(), pareseResultToString(parseResult), data->toString());
arg(pkg.toString(), pareseResultToString(parseResult), data->toString());
QuasarAppUtils::Params::log(message, QuasarAppUtils::Warning);
@ -1277,8 +1287,8 @@ void AbstractNode::nodeErrorOccured(AbstractNodeInfo *nodeInfo,
QString message("Network error occured on the %0 node. Message: %1");
QuasarAppUtils::Params::log(
message.arg(nodeInfo->networkAddress().toString(), errorString),
QuasarAppUtils::Error);
message.arg(nodeInfo->networkAddress().toString(), errorString),
QuasarAppUtils::Error);
auto &actions = _connectActions[NodeCoonectionStatus::Connected];
actions.remove(nodeInfo->networkAddress());

@ -28,8 +28,6 @@
#include "workstate.h"
#include "package.h"
#include "heart_global.h"
#include "packagemanager.h"
#include "abstracterrorcodes.h"
#include <iparser.h>
namespace QH {
@ -544,10 +542,11 @@ protected:
/**
* @brief prepareData This is private method for preparing package from the byteArray.
* @param pkg This is a raw package value.
* @param sender This is sender of the @a pkg.
* @return pointer into prepared data.
* @warning The return value do not clear automatically.
*/
QSharedPointer<PKG::AbstractData> prepareData(const Package& pkg) const;
QSharedPointer<PKG::AbstractData> prepareData(const Package& pkg, AbstractNodeInfo *sender) const;
/**
* @brief connectionsList This method return list of all node connections
@ -657,7 +656,7 @@ private:
AbstractNodeInfo *sender) override;
QSharedPointer<PKG::AbstractData>
genPackage(unsigned short cmd) const override;
genPackage(unsigned short cmd) const override final;
int version() const override;
QString parserId() const override;

@ -220,9 +220,19 @@ void AbstractNodeInfo::reset() {
setTrust(static_cast<int>(TrustNode::Default));
setStatus(NodeCoonectionStatus::NotConnected);
setIsLocal(false);
_parsersMap.clear();
}
QSharedPointer<QH::iParser> AbstractNodeInfo::getParser(unsigned short cmd) {
return _parsersMap.value(cmd, nullptr);
}
void QH::AbstractNodeInfo::addParser(unsigned short cmd,
QSharedPointer<QH::iParser> parser) {
_parsersMap[cmd] = parser;
}
uint qHash(NodeCoonectionStatus status) {
return static_cast<uint>(status);
}

@ -18,6 +18,8 @@ class QHostInfo;
namespace QH {
class iParser;
/**
* @brief The DistVersion class This is infirmation of supported versions of the distanation api.
*/
@ -33,7 +35,7 @@ struct DistVersion {
/**
* @brief VersionData This is array of all avalable apis and supported its versions.
*/
typedef QHash<QString, DistVersion> VersionData;
typedef QHash<QString, unsigned int> VersionData;
/**
* @brief The TrustNode enum contains cases for trust of the client or nodes.
@ -296,6 +298,22 @@ signals:
*/
void statusChaned(QH::AbstractNodeInfo* thisNode, QH::NodeCoonectionStatus status);
/**
* @brief getParser This method return parser of choosed command.
* @param cmd This is command that need to parse.
* @return parser of the @a cmd comand.
*/
QSharedPointer<iParser> getParser(unsigned short cmd);
/**
* @brief addParser This method add to cache new parser for command .
* @param cmd
* @param parser
* @note All parsers will be removed after reconnect of this node.
*/
void addParser(unsigned short cmd, QSharedPointer<QH::iParser> parser);
protected:
/**
@ -316,6 +334,8 @@ private:
NodeCoonectionStatus _status = NodeCoonectionStatus::NotConnected;
bool _isLocal = false;
QHash<unsigned short, QSharedPointer<iParser>> _parsersMap;
VersionData _version;
bool _fVersionReceived = false;
bool _fVersionDelivered = false;

@ -41,25 +41,17 @@ ParserResult APIVersionParser::parsePackage(const QSharedPointer<PKG::AbstractDa
}
auto distVersion = sender->version();
const auto parsers = selectParser(distVersion);
const auto parser = selectParser(pkg->cmd(), sender);
if (parsers.isEmpty()) {
if (!parser) {
QuasarAppUtils::Params::log(QString("Can't found requeried parser for versions"),
QuasarAppUtils::Warning);
return ParserResult::NotProcessed;
}
for (const auto& parser: parsers) {
if (!parser) {
QuasarAppUtils::Params::log(QString("Internal Error with selection parasers."),
QuasarAppUtils::Error);
continue;
}
auto perserResult = parser->parsePackage(pkg, pkgHeader, sender);
if (perserResult != QH::ParserResult::NotProcessed) {
return perserResult;
}
auto perserResult = parser->parsePackage(pkg, pkgHeader, sender);
if (perserResult != QH::ParserResult::NotProcessed) {
return perserResult;
}
return ParserResult::NotProcessed;
@ -73,8 +65,12 @@ QString APIVersionParser::parserId() const {
return "APIVersionParser";
}
I shold be create method that can create package by commnad with needed version.
QSharedPointer<PKG::AbstractData> APIVersionParser::genPackage(unsigned short cmd) const {
QSharedPointer<PKG::AbstractData>
APIVersionParser::searchPackage(unsigned short cmd,
AbstractNodeInfo *sender) const {
if (!sender)
return nullptr;
auto distVersion = sender->version();
const auto parsers = selectParser(distVersion);
@ -89,11 +85,11 @@ QSharedPointer<PKG::AbstractData> APIVersionParser::genPackage(unsigned short cm
continue;
}
auto perserResult = parser->parsePackage(pkg, pkgHeader, sender);
if (perserResult != QH::ParserResult::NotProcessed) {
return perserResult;
}
if (auto package = parser->genPackage(cmd))
return package;
}
return nullptr;
}
QSharedPointer<iParser>
@ -121,6 +117,31 @@ APIVersionParser::selectParser(const VersionData &distVersion) const {
return result;
}
QSharedPointer<iParser> APIVersionParser::selectParser(unsigned short cmd,
AbstractNodeInfo *sender) {
auto parser = sender->getParser(cmd);
if (!parser) {
parser = selectParserImpl(cmd, sender);
}
return parser;
}
QSharedPointer<iParser> APIVersionParser::selectParserImpl(unsigned short cmd,
AbstractNodeInfo *sender) {
auto version = sender->version();
const auto availableParser = selectParser(version);
for (const auto& parser: availableParser) {
if (parser->checkCommand(cmd)) {
sender->addParser(cmd, parser);
return parser;
}
}
return nullptr;
}
unsigned short APIVersionParser::maximumApiVersion(const QString &apiKey) const {
auto availableVersion = _apiParsers.value(apiKey, {});

@ -32,7 +32,16 @@ public:
AbstractNodeInfo *sender) override;
int version() const override;
QString parserId() const override;
QSharedPointer<PKG::AbstractData> genPackage(unsigned short cmd) const override;
/**
* @brief searchPackage This method search package recursive in all registered pararsers. Searching will be in compatibility versions.
* Before search methd choose compatibly verson.
* @param cmd This is command for that shold be create pacakge object.
* @param sender This is node that sent @a the cmd.
* @return Package generated from cmd.
*/
QSharedPointer<PKG::AbstractData>
searchPackage(unsigned short cmd, AbstractNodeInfo *sender) const;
/**
* @brief getSelectedApiParser This method return apiParser for selected node
@ -66,6 +75,15 @@ public:
QHash<QString, QSharedPointer<QH::iParser>>
selectParser(const VersionData& distVersion) const;
/**
* @brief selectParser This method select parser by command and sender.
* @param cmd this is command that need to parse.
* @param sender this is node that sent this command.
* @return parser for the @a cmd command
*/
QSharedPointer<QH::iParser>
selectParser(unsigned short cmd, AbstractNodeInfo *sender);
/**
* @brief maximumApiVersion This method return maximum supported api version of this node.
* @param apiKey This is api key.
@ -90,6 +108,10 @@ signals:
void sigNoLongerSupport(const QString& ApiKey, unsigned short version);
private:
QSharedPointer<QH::iParser>
selectParserImpl(unsigned short cmd, AbstractNodeInfo *sender);
bool processAppVersion(const QSharedPointer<APIVersion> &message,
AbstractNodeInfo *sender,
const QH::Header &);

@ -153,7 +153,7 @@ public:
inline ParserResult commandHandler(HandlerType handlerObject, HandlerMethod method,
const QSharedPointer<QH::PKG::AbstractData> &pkg,
const QH::AbstractNodeInfo *sender,
QH::AbstractNodeInfo *sender,
const QH::Header &pkgHeader) {
if (PackageClass::command() == pkg->cmd()) {

@ -0,0 +1,37 @@
//#
//# Copyright (C) 2022-2022 QuasarApp.
//# Distributed under the lgplv3 software license, see the accompanying
//# Everyone is permitted to copy and distribute verbatim copies
//# of this license document, but changing it is not allowed.
//#
#include "bigdatawraper.h"
namespace QH {
namespace PKG {
const AbstractData *BigDataWraper::data() const {
return _data;
}
void BigDataWraper::setData(const AbstractData *newData) {
_data = newData;
}
QString BigDataWraper::toString() const {
if (_data)
return QString("Wrapper of : %0").arg(_data->toString());
return QString("Wrapper of : null");
}
QDataStream &BigDataWraper::fromStream(QDataStream &stream) {
return stream;
}
QDataStream &BigDataWraper::toStream(QDataStream &stream) const {
return stream;
}
}
}

@ -0,0 +1,52 @@
//#
//# Copyright (C) 2022-2022 QuasarApp.
//# Distributed under the lgplv3 software license, see the accompanying
//# Everyone is permitted to copy and distribute verbatim copies
//# of this license document, but changing it is not allowed.
//#
#ifndef BIGDATAWRAPER_H
#define BIGDATAWRAPER_H
#include "abstractdata.h"
namespace QH {
namespace PKG {
/**
* @brief The BigDataWraper class is wrapper of any big data commands.
*/
class BigDataWraper: public AbstractData
{
QH_PACKAGE(BigDataWraper, "BigDataWraper")
public:
BigDataWraper();
/**
* @brief data This method sets data that shold be sent as big data.
* @return
*/
const AbstractData *data() const;
/**
* @brief setData This method sets new data for this wrapper.
* @param newData this is new data object.
*/
void setData(const AbstractData *newData);
QString toString() const override;
// StreamBase interface
protected:
QDataStream &fromStream(QDataStream &stream) override;
QDataStream &toStream(QDataStream &stream) const override;
private:
const AbstractData *_data = nullptr;
};
}
}
#endif // BIGDATAWRAPER_H

@ -1,18 +0,0 @@
#include "singleserverdb.h"
namespace QH {
SingleServerDB::SingleServerDB()
{
}
ISqlDBCache *QH::SingleServerDB::rawDb() const {
return DataBase::db();
}
QStringList SingleServerDB::SQLSources() const {
return {":/sql/DataBaseSpace/Res/UserDB.sql"};
}
}

@ -1,26 +0,0 @@
#ifndef SINGLESERVERDB_H
#define SINGLESERVERDB_H
#include <database.h>
namespace QH {
class SingleServerDB: public DataBase
{
Q_OBJECT
public:
SingleServerDB();
/**
* @brief rawDb This node return pointer to database object.
* @return The pointer to data base.
*/
ISqlDBCache* rawDb() const;
QStringList SQLSources() const override;
friend class SingleServer;
};
}
#endif // SINGLESERVERDB_H

@ -1,27 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#ifndef BASEDEFINES_H
#define BASEDEFINES_H
namespace QH {
/**
* @brief The DBOperationResult enum contains the statuses of database operations.
*/
enum class DBOperationResult {
/// The Node don't know about a permission of operation.
Unknown,
/// The Node allow this operation and execute it.
Allowed,
/// The Node forbid this operation.
Forbidden,
};
}
#endif // BASEDEFINES_H

@ -1,51 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#include "basenodeinfo.h"
#include "dbaddress.h"
#include <QTcpSocket>
#include <hostaddress.h>
namespace QH {
BaseNodeInfo::BaseNodeInfo(QAbstractSocket *tcp, const HostAddress* address):
AbstractNodeInfo(tcp, address){}
BaseNodeInfo::~BaseNodeInfo() = default;
bool BaseNodeInfo::isValid() const {
return AbstractNodeInfo::isValid();
}
const AccessToken &BaseNodeInfo::token() const {
return _token;
}
void BaseNodeInfo::setToken(const AccessToken &token) {
_token = token;
}
void BaseNodeInfo::reset() {
AbstractNodeInfo::reset();
setToken(AccessToken{});
setId({});
}
bool BaseNodeInfo::confirmData() const {
return AbstractNodeInfo::confirmData();
}
const QString& BaseNodeInfo::id() const {
return _id;
}
void BaseNodeInfo::setId(const QString &id) {
_id = id;
}
}

@ -1,75 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#ifndef CONNECTIONINFO_H
#define CONNECTIONINFO_H
#include "abstractnodeinfo.h"
#include "accesstoken.h"
#include "heart_global.h"
#include <QByteArray>
class QAbstractSocket;
namespace QH {
class DbAddress;
/**
* @brief The BaseNodeInfo class contains the unique node id.
* This object created in the DataBaseNode::createNodeInfo method.
*/
class HEARTSHARED_EXPORT BaseNodeInfo: public AbstractNodeInfo {
public:
/**
* @brief BaseNodeInfo This constructor initialize the node info object from the tcp descriptor
* @param tcp This is tcp socket descriptor.
* @param clientAddress This is network address of socket.
*/
explicit BaseNodeInfo(QAbstractSocket * tcp = nullptr,
const HostAddress* clientAddress = nullptr);
~BaseNodeInfo() override;
bool isValid() const override;
/**
* @brief token This method return id of peer node or client.
* @return The id of peer node or client.
*/
const AccessToken& token() const;
/**
* @brief setToken This method set an token for the peer node or the client.
* @param token New value of token of the peer node.
*/
void setToken(const AccessToken &token);
void reset() override;
bool confirmData() const override;
/**
* @brief id This method return id of the connected user.
* @return User id.
*/
const QString &id() const;
/**
* @brief setId This method set userId for connected object.
* @param id This is new value of user id.
*/
void setId(const QString &id);
protected:
AccessToken _token;
QString _id;
};
}
#endif // CONNECTIONINFO_H

@ -5,7 +5,6 @@
* of this license document, but changing it is not allowed.
*/
#include "accesstoken.h"
#include "database.h"
#include "sqldbcache.h"
#include "sqldbwriter.h"
@ -13,13 +12,10 @@
#include <quasarapp.h>
#include <QCoreApplication>
#include <basenodeinfo.h>
#include <abstractnetworkmember.h>
#include <memberpermisionobject.h>
#include <networkmember.h>
#include <deleteobject.h>
#include <QSet>
#include <defaultpermision.h>
#include <itoken.h>
#include <sqlitedbcache.h>
#include <sqldb.h>
@ -35,7 +31,7 @@ DataBase::DataBase(QObject *ptr): QObject(ptr) {
}
bool DataBase::initSqlDb(QString DBparamsFile,
ISqlDBCache *cache,
ISqlDB *cache,
SqlDBWriter *writer) {
initDefaultDbObjects(cache, writer);
@ -67,11 +63,11 @@ bool DataBase::initSqlDb(QString DBparamsFile,
QuasarAppUtils::Params::log(QString("Database loaded from: %0").arg(dbLocation()),
QuasarAppUtils::Debug);
connect(_db, &ISqlDBCache::sigItemChanged,
connect(_db, &ISqlDB::sigItemChanged,
this, &DataBase::sigObjectChanged,
Qt::DirectConnection);
connect(_db, &ISqlDBCache::sigItemDeleted,
connect(_db, &ISqlDB::sigItemDeleted,
this, &DataBase::sigObjectDeleted,
Qt::DirectConnection);
@ -117,7 +113,7 @@ DataBase::~DataBase() {
stop();
}
void DataBase::initDefaultDbObjects(ISqlDBCache *cache,
void DataBase::initDefaultDbObjects(ISqlDB *cache,
SqlDBWriter *writer) {
if (!writer) {
writer = new AsyncSqlDBWriter();
@ -182,14 +178,6 @@ void DataBase::addDBPatch(const DBPatch &patch) {
_targetDBVersion = std::max(_targetDBVersion, patch.versionTo);
}
void DataBase::memberSubsribed(const QVariant &, unsigned int ) {
return;
}
void DataBase::memberUnsubsribed(const QVariant &, unsigned int ) {
return;
}
QString DataBase::dbLocation() const {
if (db() && db()->writer()) {
return db()->writer()->databaseLocation();
@ -216,7 +204,7 @@ bool DataBase::changeTrust(const QString &id, int diff) {
return _db->changeObjects(NetworkMember{id}, action);
}
ISqlDBCache *DataBase::db() const {
ISqlDB *DataBase::db() const {
return _db;
}
@ -314,259 +302,5 @@ QVariantMap DataBase::defaultDbParams() const {
{"DBFilePath", DEFAULT_DB_PATH + "/" + localNodeName() + "/" + localNodeName() + "_" + DEFAULT_DB_NAME},
};
}
DBOperationResult
QH::DataBase::getObject(const QString &requester,
const QH::DBObject &templateObj,
QSharedPointer<QH::PKG::DBObject> &result) const {
if (!(_db && result)) {
return DBOperationResult::Unknown;
}
DBOperationResult permisionResult = checkPermission(requester, templateObj.dbAddress(),
Permission::Read);
if (permisionResult != DBOperationResult::Allowed) {
return permisionResult;
}
auto obj = _db->getObject(templateObj);
if (!obj || (obj->dbAddress() != templateObj.dbAddress())) {
return DBOperationResult::Unknown;
}
result = obj;
return DBOperationResult::Allowed;
}
DBOperationResult
DataBase::getObjects(const QString &requester,
const DBObject &templateObj,
QList<QSharedPointer<DBObject>> &result) const {
if (!_db) {
return DBOperationResult::Unknown;
}
if (!_db->getAllObjects(templateObj, result)) {
return DBOperationResult::Unknown;
}
for (const auto& obj: qAsConst(result)) {
if (!obj)
return DBOperationResult::Unknown;
auto permisionResult = checkPermission(requester, obj->dbAddress(),
Permission::Read);
if (permisionResult != DBOperationResult::Allowed) {
return permisionResult;
}
}
return DBOperationResult::Allowed;
}
DBOperationResult
DataBase::updateObject(const QString &requester,
const QSharedPointer<DBObject> &saveObject) {
if (!_db) {
return DBOperationResult::Unknown;
}
auto permisionResult = checkPermission(requester,
saveObject->dbAddress(),
Permission::Write);
if (permisionResult != DBOperationResult::Allowed) {
return permisionResult;
}
if (!_db->updateObject(saveObject)) {
return DBOperationResult::Unknown;
}
return DBOperationResult::Allowed;
}
DBOperationResult
DataBase::createObject(const QString &requester,
const QSharedPointer<DBObject> &obj) {
if (!_db) {
return DBOperationResult::Unknown;
}
if (isForbidenTable(obj->table())) {
return DBOperationResult::Forbidden;
}
if (!_db->insertObject(obj)) {
return DBOperationResult::Unknown;
}
if (!addUpdatePermission(requester, obj->dbAddress(), Permission::Write)) {
_db->deleteObject(obj);
return DBOperationResult::Forbidden;
}
return DBOperationResult::Allowed;
}
DBOperationResult
DataBase::updateIfNotExistsCreateObject(const QString &requester,
const QSharedPointer<DBObject> &obj) {
auto opResult = updateObject(requester, obj);
if (opResult != QH::DBOperationResult::Unknown) {
return opResult;
}
return createObject(requester, obj);
}
DBOperationResult
DataBase::changeObjects(const QString &requester,
const DBObject &templateObj,
const std::function<bool (const QSharedPointer<DBObject> &)> &changeAction) {
DBOperationResult result = DBOperationResult::Unknown;
if (!_db) {
return result;
}
auto execWithCheck = [this, requester, &result, &changeAction]
(const QSharedPointer<DBObject> & obj) {
result = checkPermission(requester, obj->dbAddress(), Permission::Update);
if (result != DBOperationResult::Allowed) {
return false;
}
return changeAction(obj);
};
if (!db()->changeObjects(templateObj, execWithCheck)) {
return result;
}
return result;
}
QVariant DataBase::getSender(const AbstractNodeInfo *connectInfo,
const AbstractData *) const {
auto info = dynamic_cast<const BaseNodeInfo*>(connectInfo);
if (!info)
return {};
return info->id();
}
DBOperationResult
DataBase::checkPermission(const QString &requester,
const DbAddress &objectAddress,
const Permission& requarimentPermision) const {
if (!requester.isEmpty())
return DBOperationResult::Unknown;
if (!_db) {
return DBOperationResult::Unknown;
}
auto member = _db->getObjectRaw(NetworkMember{requester});
if (!member) {
return DBOperationResult::Unknown;
}
auto permision =
_db->getObject(MemberPermisionObject({requester, objectAddress}));
if (!permision) {
permision = _db->getObject(DefaultPermision({requester, objectAddress}));
if (!permision)
return DBOperationResult::Unknown;
}
if (permision->permisions() < requarimentPermision) {
return DBOperationResult::Forbidden;
}
return DBOperationResult::Allowed;
}
bool DataBase::addUpdatePermission(const QVariant &member,
const DbAddress &objectAddress,
const Permission &permision,
const Permission &defaultPermision) const {
if (!_db) {
return false;
}
auto object = QSharedPointer<MemberPermisionObject>::create();
object->setKey(PermisionData(member, objectAddress));
object->setPermisions(permision);
if (!_db->insertObject(object) && !_db->updateObject(object)) {
return false;
}
auto defaultPermisionObject = QSharedPointer<DefaultPermision>::create();
defaultPermisionObject->setKey(PermisionData({}, objectAddress));
defaultPermisionObject->setPermisions(defaultPermision);
if (!_db->insertObject(defaultPermisionObject) &&
!_db->updateObject(defaultPermisionObject)) {
return false;
}
return true;
}
bool DataBase::removePermission(const QVariant &member,
const DbAddress &objectAddress) const {
if (!_db) {
return false;
}
auto object = QSharedPointer<MemberPermisionObject>::create();
object->setKey(PermisionData(member, objectAddress));
if (!_db->deleteObject(object)) {
return false;
}
return true;
}
DBOperationResult
DataBase::deleteObject(const QString &requester,
const QSharedPointer<DBObject> &dbObject) {
if (!_db) {
return DBOperationResult::Unknown;
}
auto permisionResult = checkPermission(requester,
dbObject->dbAddress(),
Permission::Write);
if (permisionResult != DBOperationResult::Allowed) {
return permisionResult;
}
auto address = dbObject->dbAddress();
if (!_db->deleteObject(dbObject)) {
return DBOperationResult::Unknown;
}
return DBOperationResult::Allowed;
}
}

@ -11,7 +11,6 @@
#include "dbpatch.h"
#include <dbobject.h>
#include <hostaddress.h>
#include <permission.h>
namespace QH {
@ -22,7 +21,7 @@ class ISubscribableData;
}
class ISqlDBCache;
class ISqlDB;
class SqlDBWriter;
class DbAddress;
class NodeId;
@ -55,7 +54,7 @@ public:
* @return True if the database initialized successful.
*/
virtual bool initSqlDb( QString DBparamsFile = "",
ISqlDBCache * cache = nullptr,
ISqlDB * cache = nullptr,
SqlDBWriter* writer = nullptr);
/**
@ -90,92 +89,6 @@ public:
*/
virtual QVariantMap defaultDbParams() const;
/**
* @brief deleteObject This method delete object by database address.
* @note If you want to delete any object use only this method because this method check permission of requester to execute this action.
* @param requester This is pointer to network member that send this request.
* @param dbObject This is pointer to object of database to remove.
* @return result of operation (allow, forbidden, unknown).
* For more information about results see the DBOperationResult enum.
*/
DBOperationResult deleteObject(const QString &requester,
const QSharedPointer<PKG::DBObject> &dbObject);
/**
* @brief getObject This method try get an object by database address.
* @note If you want to get any object use only this method because this method check permission of requester to execute this action
* @param requester This is pointer to network member that send this request.
* @param templateObj This is pointer to object of database with data for generation the sql select request.
* @param result This is a shared pointer for save result of request.
* @return result of operation (allow, forbidden, unknown).
* For more information about results see the DBOperationResult enum.
*/
DBOperationResult getObject(const QString &requester,
const PKG::DBObject &templateObj,
QSharedPointer<PKG::DBObject> &result) const;
/**
* @brief getObjects This method try get objects by template object.
* @note If you want to get any objects use only this method because this method check permission of requester to execute this action
* @param requester This is pointer to network member that send this request.
* @param templateObj This is pointer to object of database with data for generation the sql select request.
* @param result This is reference to the list of result objects.
* @return result of operation (allow, forbidden, unknown).
* For more information about results see the DBOperationResult enum.
*/
DBOperationResult getObjects(const QString &requester,
const PKG::DBObject &templateObj,
QList<QSharedPointer<PKG::DBObject>> &result) const;
/**
* @brief updateObject This method try save or update database object.
* @note If you want to save or update any objects use only this method because this method check permission of requester to execute this action
* @param requester This is network mebmer that send this request.
* @param saveObject This is pointer to object of database for save or update.
* @return result of operation (allow, forbidden, unknown).
* For more information about results see the DBOperationResult enum.
*/
DBOperationResult updateObject(const QString &requester,
const QSharedPointer<PKG::DBObject> &saveObject);
/**
* @brief createObject This method create a new object in the database and add all permissions for the objects creator.
* @note If you want to create any objects use only this method because this method check permission of requester to execute this action
* @param requester This is network member that send this request.
* @param obj This is pointer to object of database for save or update.
* @return result of operation (allow, forbidden, unknown).
* For more information about results see the DBOperationResult enum.
*/
DBOperationResult createObject(const QString &requester,
const QSharedPointer<PKG::DBObject> &obj);
/**
* @brief updateIfNotExistsCreateObject This is wraper of the updateObject and createObjects methods.
* 1. Try update object
* 2. If object not exists Try create new object.
* 3. Return operation result
* @param requester This is network member that send this request.
* @param obj This is initializing object.
* @return result of operation (allow, forbidden, unknown).
* For more information about results see the DBOperationResult enum.
*/
DBOperationResult updateIfNotExistsCreateObject(const QString &requester,
const QSharedPointer<PKG::DBObject> &obj);
/**
* @brief changeObjects This is wrapper of the "ISqlDBCache::changeObjects" method.
* Key difference between a base method is checking of the permision for needed action.
* @note If you want to change any objects use only this method because this method check permission of requester to execute this action
* @param requester This is network member that send this request.
* @param templateObj This is pointer to object of database with data for generation the sql select request.
* @param changeAction This is action function for change all selected objects.
* @return result of operation (allow, forbidden, unknown).
* For more information about results see the DBOperationResult enum.
*/
DBOperationResult changeObjects(const QString &requester,
const PKG::DBObject &templateObj,
const std::function<bool (const QSharedPointer<QH::PKG::DBObject>&)> &changeAction);
/**
* @brief isBanned This method check trust of node, if node trust is lover of 0 return true.
* @param member This is member of network (node, client or server).
@ -242,75 +155,13 @@ protected:
* @param cache This is Cache database object.
* @param writer This is Database writerObject.
*/
virtual void initDefaultDbObjects(ISqlDBCache *cache, SqlDBWriter *writer);
/**
* @brief memberSubsribed This method invoked when client with @a clientId subscribed on object with @a subscribeId.
* @param clientId This is id of the client member.
* @param subscribeId This is id of the subscribeObject.
*/
virtual void memberSubsribed(const QVariant &clientId, unsigned int subscribeId);
/**
* @brief memberUnSubsribed This method invoked when client with @a clientId unsubsribed on object with @a subscribeId
* @param clientId This is id of the client member.
* @param subscribeId This is id of the subscribeObject.
*/
virtual void memberUnsubsribed(const QVariant &clientId, unsigned int subscribeId);
virtual void initDefaultDbObjects(ISqlDB *cache, SqlDBWriter *writer);
/**
* @brief db This node return pointer to database object.
* @return The pointer to data base.
*/
ISqlDBCache* db() const;
/**
* @brief getSender This method return id of requester.
* By Default base implementation get id from BaseNdoeInfo.
* override this method for correctly work of the DataBaseNode::ParsePacakge method.
* @param connectInfo This is info about connection.
* @param requestData This is data of request.
* @return id of requester member.
*/
virtual QVariant getSender(const AbstractNodeInfo *connectInfo, const PKG::AbstractData *requestData) const;
/**
* @brief checkPermision This method check a permision of requester, to database object with objectAddress.
* Override this method if you have a custom database structure.
* @param requester This is user, node or another object of network
* @param objectAddress This is address to database object
* @param requarimentPermision This is needed permission for requester
* @return DBOperationResult::Alowed if permission granted.
* For more information about result see the DBOperationResult enum.
*/
virtual DBOperationResult checkPermission(const QString &requester,
const DbAddress& objectAddress,
const Permission& requarimentPermision) const;
/**
* @brief addUpdatePermission This method added or update permission for member.
* @warning This method do not have a validation. It is just change a NetworkMembers table, so use this carefully.
* @param member This is member id (user of node).
* @param objectAddress This is database object for which the permissions will be set.
* @param permision This is permission level.
* @param defaultPermision This is default permision for all of rest objects. By default This is Permission::Read
* @return true if method finished successful.
*/
virtual bool addUpdatePermission(const QVariant &member,
const DbAddress& objectAddress,
const Permission& permision,
const Permission& defaultPermision = Permission::Read) const;
/**
* @brief removePermission This method use to removed permission for member.
* @warning This method do not have a validation. It is just change a NetworkMembers table, so use this carefully.
* @param member This is member id (user of node)
* @param objectAddress This is database object for which the permissions will be removed
* @return true if method finished successful.
*/
virtual bool removePermission(const QVariant &member,
const DbAddress& objectAddress) const;
ISqlDB* db() const;
/**
* @brief welcomeAddress This method send to the node information about self.
@ -462,7 +313,7 @@ private:
bool isForbidenTable(const QString& table);
ISqlDBCache *_db = nullptr;
ISqlDB *_db = nullptr;
unsigned short _targetDBVersion = 0;
DBPatchMap _dbPatches;
QString _localNodeName;

@ -1,414 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#include "accesstoken.h"
#include "databasenode.h"
#include "abstractnodeinfo.h"
#include "sqldbcache.h"
#include "sqldbwriter.h"
#include "websocketcontroller.h"
#include "asyncsqldbwriter.h"
#include <badrequest.h>
#include <quasarapp.h>
#include <websocket.h>
#include <websocketsubscriptions.h>
#include <websocketcontroller.h>
#include <QCoreApplication>
#include <ping.h>
#include <basenodeinfo.h>
#include <abstractnetworkmember.h>
#include <memberpermisionobject.h>
#include <networkmember.h>
#include <deleteobject.h>
#include "dberrorcodes.h"
#include <QSet>
#include <defaultpermision.h>
#include <isubscribabledata.h>
#include <itoken.h>
#include <sqlitedbcache.h>
#include <sqldb.h>
#include <QCryptographicHash>
#include "getsinglevalue.h"
#include "setsinglevalue.h"
#include "database.h"
#define THIS_NODE "this_node_key"
namespace QH {
using namespace PKG;
DataBaseNode::DataBaseNode(QObject *ptr):
AbstractNode(ptr) {
_webSocketWorker = new WebSocketController(this);
qRegisterMetaType<QSharedPointer<QH::PKG::DBObject>>();
registerPackageType<WebSocket>();
registerPackageType<WebSocketSubscriptions>();
registerPackageType<DeleteObject>();
}
bool DataBaseNode::initDatabase() {
setDb(new DataBase());
return true;
}
void DataBaseNode::setDb(DataBase *newDb) {
if (_db) {
disconnect(_db, &DataBase::sigObjectChanged,
this, &DataBaseNode::handleObjectChanged);
disconnect(_db, &DataBase::sigObjectDeleted,
this, &DataBaseNode::handleObjectDeleted);
delete _db;
}
_db = newDb;
if (_db) {
connect(_db, &DataBase::sigObjectChanged,
this, &DataBaseNode::handleObjectChanged,
Qt::DirectConnection);
connect(_db, &DataBase::sigObjectDeleted,
this, &DataBaseNode::handleObjectDeleted,
Qt::DirectConnection);
}
}
bool DataBaseNode::isSqlInited() const {
return _db && _db->isSqlInited();
}
DBOperationResult DataBaseNode::checkPermission(const QString &requester,
const DbAddress &objectAddress,
const Permission &requarimentPermision) const {
if (!_db) {
return DBOperationResult::Unknown;
}
return _db->checkPermission(requester, objectAddress, requarimentPermision);
}
bool DataBaseNode::run(const QString &addres, unsigned short port) {
return initDatabase() && _db->run() &&AbstractNode::run(addres, port);
}
bool DataBaseNode::run(const QString &addres,
unsigned short port,
const QString &localNodeName) {
return initDatabase() && _db->run(localNodeName) && AbstractNode::run(addres, port);
}
void DataBaseNode::stop() {
AbstractNode::stop();
if (_db)
_db->stop();
}
DataBaseNode::~DataBaseNode() {
if (_db)
delete _db;
}
bool DataBaseNode::welcomeAddress(AbstractNodeInfo *) {
return true;
}
bool DataBaseNode::isBanned(const QString &node) const {
return db()->isBanned(node);
}
bool DataBaseNode::isBanned(const AbstractNodeInfo *node) const {
return AbstractNode::isBanned(node);
}
bool DataBaseNode::notifyObjectChanged(const QSharedPointer<PKG::ISubscribableData> &item) {
if (!item.dynamicCast<PKG::AbstractData>()) {
return false;
}
_webSocketWorker->handleItemChanged(item);
return true;
}
void DataBaseNode::objectRemoved(const DbAddress &) {
}
void DataBaseNode::objectChanged(const QSharedPointer<DBObject> &) {
}
void DataBaseNode::handleObjectChanged(const QSharedPointer<DBObject> &item) {
notifyObjectChanged(item.staticCast<PKG::ISubscribableData>());
objectChanged(item);
}
void DataBaseNode::handleObjectDeleted(const DbAddress &item) {
objectRemoved(item);
}
void DataBaseNode::nodeConnected(AbstractNodeInfo *node) {
AbstractNode::nodeConnected(node);
welcomeAddress(node);
}
void DataBaseNode::nodeDisconnected(AbstractNodeInfo *node) {
AbstractNode::nodeDisconnected(node);
auto baseInfo = dynamic_cast<BaseNodeInfo*>(node);
if (baseInfo) {
baseInfo->reset();
}
}
void DataBaseNode::memberSubsribed(const QVariant &, unsigned int ) {
return;
}
void DataBaseNode::memberUnsubsribed(const QVariant &, unsigned int ) {
return;
}
QString DataBaseNode::dbLocation() const {
if (!db()) {
return "";
}
return db()->dbLocation();
}
AbstractNodeInfo *DataBaseNode::createNodeInfo(QAbstractSocket *socket, const HostAddress *clientAddress) const {
return new BaseNodeInfo(socket, clientAddress);
}
bool DataBaseNode::changeTrust(const HostAddress &id, int diff) {
auto info = dynamic_cast<const BaseNodeInfo*>(getInfoPtr(id));
if (!info)
return false;
if (info->id().size())
return changeTrust(info->id(), diff);
return AbstractNode::changeTrust(id, diff);
}
bool DataBaseNode::changeTrust(const QString &id, int diff) {
if (!_db)
return false;
return _db->changeTrust(id, diff);
}
unsigned int DataBaseNode::sendData(const AbstractData *resp,
const QVariant &nodeId,
const Header *req) {
auto nodes = connections();
for (auto it = nodes.begin(); it != nodes.end(); ++it) {
auto info = dynamic_cast<BaseNodeInfo*>(it.value());
if (info && info->id() == nodeId) {
return sendData(resp, info, req);
}
}
return 0;
}
unsigned int DataBaseNode::sendData(const AbstractData *resp, const HostAddress &nodeId,
const Header *req) {
return AbstractNode::sendData(resp, nodeId, req);
}
unsigned int DataBaseNode::sendData(const PKG::AbstractData *resp,
const AbstractNodeInfo *node,
const Header *req) {
return AbstractNode::sendData(resp, node, req);
}
ParserResult DataBaseNode::parsePackage(const QSharedPointer<AbstractData> &pkg,
const Header &pkgHeader,
const AbstractNodeInfo *sender) {
auto parentResult = AbstractNode::parsePackage(pkg, pkgHeader, sender);
if (parentResult != ParserResult::NotProcessed) {
return parentResult;
}
if (WebSocket::command() == pkg->cmd()) {
WebSocket *obj = static_cast<WebSocket*>(pkg.data());
auto requesterId = getSender(sender, obj);
if (!obj->isValid()) {
badRequest(sender->networkAddress(), pkgHeader,
{
ErrorCodes::InvalidRequest,
"WebSocket request is invalid"
});
return ParserResult::Error;
}
if (!workWithSubscribe(*obj, requesterId, sender)) {
badRequest(sender->networkAddress(), pkgHeader, {
ErrorCodes::InvalidRequest,
"WebSocket request is invalid"
});
return ParserResult::Error;
}
return ParserResult::Processed;
}
return ParserResult::NotProcessed;
}
QByteArray DataBaseNode::hashgenerator(const QByteArray &pass) const {
if (pass.isEmpty())
return {};
return QCryptographicHash::hash(
QCryptographicHash::hash(pass, QCryptographicHash::Sha256) + "QuassarAppSoult",
QCryptographicHash::Sha256);
}
DataBase *DataBaseNode::db() const {
return _db;
}
bool DataBaseNode::workWithSubscribe(const WebSocket &rec,
const QString &clientOrNodeid,
const AbstractNodeInfo * sender) {
auto _db = db();
if (!_db)
return false;
switch (static_cast<WebSocketRequest>(rec.getRequestCmd())) {
case WebSocketRequest::Subscribe: {
_webSocketWorker->subscribe(clientOrNodeid, rec.subscribeId());
memberSubsribed(clientOrNodeid, rec.subscribeId());
return true;
}
case WebSocketRequest::Unsubscribe: {
_webSocketWorker->unsubscribe(clientOrNodeid, rec.subscribeId());
memberUnsubsribed(clientOrNodeid, rec.subscribeId());
return true;
}
case WebSocketRequest::SubscribeList: {
WebSocketSubscriptions resp;
resp.setAddresses(_webSocketWorker->list(clientOrNodeid));
return sendData(&resp, sender);
}
default: break;
}
return false;
}
DBOperationResult
QH::DataBaseNode::getObject(const QString &requester,
const QH::DBObject &templateObj,
QSharedPointer<QH::PKG::DBObject> &result) const {
if (!_db) {
return DBOperationResult::Unknown;
}
return _db->getObject(requester, templateObj, result);
}
DBOperationResult
DataBaseNode::getObjects(const QString &requester,
const DBObject &templateObj,
QList<QSharedPointer<DBObject>> &result) const {
if (!_db) {
return DBOperationResult::Unknown;
}
return _db->getObjects(requester, templateObj, result);
}
DBOperationResult
DataBaseNode::updateObject(const QString &requester,
const QSharedPointer<DBObject> &saveObject) {
if (!_db) {
return DBOperationResult::Unknown;
}
return _db->updateObject(requester, saveObject);
}
DBOperationResult
DataBaseNode::createObject(const QString &requester,
const QSharedPointer<DBObject> &obj) {
if (!_db) {
return DBOperationResult::Unknown;
}
return _db->createObject(requester, obj);
}
DBOperationResult
DataBaseNode::updateIfNotExistsCreateObject(const QString &requester,
const QSharedPointer<DBObject> &obj) {
if (!_db) {
return DBOperationResult::Unknown;
}
return _db->updateIfNotExistsCreateObject(requester, obj);
}
DBOperationResult
DataBaseNode::changeObjects(const QString &requester,
const DBObject &templateObj,
const std::function<bool (const QSharedPointer<DBObject> &)> &changeAction) {
if (!_db) {
return DBOperationResult::Unknown;
}
return _db->changeObjects(requester, templateObj, changeAction);
}
QString DataBaseNode::getSender(const AbstractNodeInfo *connectInfo,
const AbstractData *) const {
auto info = dynamic_cast<const BaseNodeInfo*>(connectInfo);
if (!info)
return {};
return info->id();
}
DBOperationResult
DataBaseNode::deleteObject(const QString &requester,
const QSharedPointer<DBObject> &dbObject) {
if (!_db) {
return DBOperationResult::Unknown;
}
return _db->deleteObject(requester, dbObject);
}
}

@ -1,332 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#ifndef DATABASENODE_H
#define DATABASENODE_H
#include "abstractnode.h"
#include <dbobject.h>
#include <hostaddress.h>
#include <permission.h>
namespace QH {
namespace PKG {
class WebSocket;
class ISubscribableData;
}
class ISqlDBCache;
class SqlDBWriter;
class WebSocketController;
class DbAddress;
class NodeId;
class iObjectProvider;
class DataBase;
/**
* @brief The BaseNode class is database base implementation of nodes or servers.
* This implementation contains methods for work with database.
* DataBaseNode is thread save class.
* @see DBObject
*/
class HEARTSHARED_EXPORT DataBaseNode : public AbstractNode
{
Q_OBJECT
public:
DataBaseNode(QObject * ptr = nullptr);
~DataBaseNode() override;
bool run(const QString &addres, unsigned short port) override;
/**
* @brief run This method is some as AbstractNode::run but set for node custom work folder.
* This maybe use for multiple deployment nodes on one host.
* @param addres This is network address of work node or server.
* If address is empty then server will be listen all addresses of all interfaces else listen only selected address.
* @param port This is port of deployment node (server).
* @return Result of deployment node (sever). (True if deploy finished successful else false).
* @param localNodeName This is name of node and work folder of node.
*/
virtual bool run(const QString &addres, unsigned short port,
const QString &localNodeName);
void stop() override;
/**
* @brief sendData This method is some as AbstractNode::sendData but it try send data to the id.
* This implementation do not prepare object to sending.
* @param resp This is sending object to the nodeId.
* @param nodeId This is id of target node.
* @param req This is header of request.
* @return true if a data send successful.
*/
virtual unsigned int sendData(const PKG::AbstractData *resp, const QVariant &nodeId,
const Header *req = nullptr);
unsigned int sendData(const PKG::AbstractData *resp, const HostAddress &nodeId,
const Header *req = nullptr) override;
unsigned int sendData(const PKG::AbstractData *resp, const AbstractNodeInfo *node,
const Header *req = nullptr) override;
/**
* @brief deleteObject This method delete object by database address.
* @note If you want to delete any object use only this method because this method check permission of requester to execute this action.
* @param requester This is pointer to network member that send this request.
* @param dbObject This is pointer to object of database to remove.
* @return result of operation (allow, forbidden, unknown).
* For more information about results see the DBOperationResult enum.
*/
DBOperationResult deleteObject(const QString &requester,
const QSharedPointer<PKG::DBObject> &dbObject);
/**
* @brief getObject This method try get an object by database address.
* @note If you want to get any object use only this method because this method check permission of requester to execute this action
* @param requester This is pointer to network member that send this request.
* @param templateObj This is pointer to object of database with data for generation the sql select request.
* @param result This is a shared pointer for save result of request.
* @return result of operation (allow, forbidden, unknown).
* For more information about results see the DBOperationResult enum.
*/
DBOperationResult getObject(const QString &requester,
const PKG::DBObject &templateObj,
QSharedPointer<PKG::DBObject> &result) const;
/**
* @brief getObjects This method try get objects by template object.
* @note If you want to get any objects use only this method because this method check permission of requester to execute this action
* @param requester This is pointer to network member that send this request.
* @param templateObj This is pointer to object of database with data for generation the sql select request.
* @param result This is reference to the list of result objects.
* @return result of operation (allow, forbidden, unknown).
* For more information about results see the DBOperationResult enum.
*/
DBOperationResult getObjects(const QString &requester,
const PKG::DBObject &templateObj,
QList<QSharedPointer<PKG::DBObject>> &result) const;
/**
* @brief updateObject This method try save or update database object.
* @note If you want to save or update any objects use only this method because this method check permission of requester to execute this action
* @param requester This is network mebmer that send this request.
* @param saveObject This is pointer to object of database for save or update.
* @return result of operation (allow, forbidden, unknown).
* For more information about results see the DBOperationResult enum.
*/
DBOperationResult updateObject(const QString &requester,
const QSharedPointer<PKG::DBObject> &saveObject);
/**
* @brief createObject This method create a new object in the database and add all permissions for the objects creator.
* @note If you want to create any objects use only this method because this method check permission of requester to execute this action
* @param requester This is network member that send this request.
* @param obj This is pointer to object of database for save or update.
* @return result of operation (allow, forbidden, unknown).
* For more information about results see the DBOperationResult enum.
*/
DBOperationResult createObject(const QString &requester,
const QSharedPointer<PKG::DBObject> &obj);
/**
* @brief updateIfNotExistsCreateObject This is wraper of the updateObject and createObjects methods.
* 1. Try update object
* 2. If object not exists Try create new object.
* 3. Return operation result
* @param requester This is network member that send this request.
* @param obj This is initializing object.
* @return result of operation (allow, forbidden, unknown).
* For more information about results see the DBOperationResult enum.
*/
DBOperationResult updateIfNotExistsCreateObject(const QString &requester,
const QSharedPointer<PKG::DBObject> &obj);
/**
* @brief changeObjects This is wrapper of the "ISqlDBCache::changeObjects" method.
* Key difference between a base method is checking of the permision for needed action.
* @note If you want to change any objects use only this method because this method check permission of requester to execute this action
* @param requester This is network member that send this request.
* @param templateObj This is pointer to object of database with data for generation the sql select request.
* @param changeAction This is action function for change all selected objects.
* @return result of operation (allow, forbidden, unknown).
* For more information about results see the DBOperationResult enum.
*/
DBOperationResult changeObjects(const QString &requester,
const PKG::DBObject &templateObj,
const std::function<bool (const QSharedPointer<QH::PKG::DBObject>&)> &changeAction);
/**
* @brief isSqlInited This method return true if database initialized successful.
* @return True if database initialized successful.
*/
bool isSqlInited() const;
/**
* @brief checkPermision This method check a permision of requester, to database object with objectAddress.
* Override this method if you have a custom database structure.
* @param requester This is user, node or another object of network
* @param objectAddress This is address to database object
* @param requarimentPermision This is needed permission for requester
* @return DBOperationResult::Alowed if permission granted.
* For more information about result see the DBOperationResult enum.
*/
DBOperationResult checkPermission(const QString &requester,
const DbAddress& objectAddress,
const Permission& requarimentPermision) const;
protected:
/**
* @brief setDb This method sets new object of the database.
* @param newDb this is new object of the database
* @note use in the initDatabase method.
*/
void setDb(DataBase *newDb);
ParserResult parsePackage(const QSharedPointer<PKG::AbstractData> &pkg,
const Header& pkgHeader,
const AbstractNodeInfo* sender) override;
AbstractNodeInfo *createNodeInfo(QAbstractSocket *socket, const HostAddress *clientAddress) const override;
bool changeTrust(const HostAddress &id, int diff) override;
/**
* @brief changeTrust This implementation of change trust is change trust node or user by self id.
* All changes of trust saving into local database.
* @param id This is id of user of other network member object.
* @param diff This is difference of trust.
* @return true if trust of user changed successful.
*/
virtual bool changeTrust(const QString &id, int diff);
/**
* @brief hashgenerator This method generate a hash from any value.
* Override this method for set your custom salt.
* @param data This input byte array.
*/
virtual QByteArray hashgenerator(const QByteArray &data) const;
void nodeConnected(AbstractNodeInfo *node) override;
void nodeDisconnected(AbstractNodeInfo *node) override;
/**
* @brief memberSubsribed This method invoked when client with @a clientId subscribed on object with @a subscribeId.
* @param clientId This is id of the client member.
* @param subscribeId This is id of the subscribeObject.
*/
virtual void memberSubsribed(const QVariant &clientId, unsigned int subscribeId);
/**
* @brief memberUnSubsribed This method invoked when client with @a clientId unsubsribed on object with @a subscribeId
* @param clientId This is id of the client member.
* @param subscribeId This is id of the subscribeObject.
*/
virtual void memberUnsubsribed(const QVariant &clientId, unsigned int subscribeId);
/**
* @brief db This node return pointer to database object.
* @return The pointer to data base.
*/
DataBase* db() const;
/**
* @brief getSender This method return id of requester.
* By Default base implementation get id from BaseNdoeInfo.
* override this method for correctly work of the DataBaseNode::ParsePacakge method.
* @param connectInfo This is info about connection.
* @param requestData This is data of request.
* @return id of requester member.
*/
virtual QString getSender(const AbstractNodeInfo *connectInfo, const PKG::AbstractData *requestData) const;
/**
* @brief dbLocation This method return location of nodes or clients database.
* @return path to the location of database.
*/
QString dbLocation() const;
/**
* @brief welcomeAddress This method send to the node information about self.
* Override this method if you want send custom data to incoming connection.
* @param node This is info object of the peer node.
* @return true if all information sender successful.
*/
virtual bool welcomeAddress(AbstractNodeInfo *node);
/**
* @brief isBanned This method check trust of node, if node trust is lover of 0 return true.
* @param member This is member of network (node, client or server).
* @return true if node is banned.
*/
bool isBanned(const QString &member) const;
bool isBanned(const AbstractNodeInfo *member) const override;
/**
* @brief notifyObjectChanged This method send all subscriptions message with this object.
* @param item changed object.
* @return true if an item object sendible.
*/
bool notifyObjectChanged(const QSharedPointer<PKG::ISubscribableData> &item);
/**
* @brief objectRemoved This method invoked when object with @a address removed from database.
* Oberride this method for handle this event. Default implementation do nothing.
* @param address This is address of the deteted object.
*/
virtual void objectRemoved(const DbAddress& address);
/**
* @brief objectChanged This method invoked when object with @a address changed in database.
* Override this method for handle this event. Default implementation do nothing.
* @param obj This is address of the changed object.
*/
virtual void objectChanged(const QSharedPointer<PKG::DBObject>& obj);
/**
* @brief initDatabase This method initialize the default DataBase object.
* @return true if database initialized succesful else false.
* @see DataBase;
*/
virtual bool initDatabase();
private slots:
void handleObjectChanged(const QSharedPointer<PKG::DBObject> &item);
void handleObjectDeleted(const QH::DbAddress &item);
private:
/**
* @brief workWithSubscribe This method work with subscribe commnads.
* @param rec This is request data.
* @param address This is sender address.
* @return true if data parsed successful.
*/
bool workWithSubscribe(const PKG::WebSocket &rec,
const QString &clientOrNodeid,
const AbstractNodeInfo *sender);
DataBase *_db = nullptr;
WebSocketController *_webSocketWorker = nullptr;
friend class WebSocketController;
};
}
#endif // DATABASENODE_H

@ -9,7 +9,6 @@
#define DBADDRESS_H
#include "streambase.h"
#include "basedefines.h"
namespace QH {

@ -1,30 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#include "dbcachekey.h"
#include <abstractkey.cpp>
namespace QH {
DBCacheKey *DBCacheKey::instance() {
static auto ptr = new DBCacheKey();
return ptr;
}
QString DBCacheKey::description(uint hash) const {
auto val = value(hash);
if (!val)
return "";
return val->toString();
}
DBCacheKey::DBCacheKey() {}
}

@ -1,95 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#ifndef DBCACHEKEY_H
#define DBCACHEKEY_H
#include <abstractkey.h>
#include <QHash>
#include <heart_global.h>
namespace QH {
/**
* @brief The DBCacheKey class is memory storage for registered key values.
* This class have a static array for contains all child classes of the AbstractKey class.
*
* Description:
*
* Any key it is unsigned int implementation of any AbstractKey child objects.
* This class provide functions:
* - The Get of value of AbstractKey child classes (it hash). for more information see the AbstractKey::hash method.
* For this use the HASH_KEY(X) macros.
* - The Calc of hash value of any AbstractKey child classes (it hash).
* If the hash is has been calculated then hash returned from the cache of DBCacheKey.
* For this use the VALUE_KEY(X) macros.
* - The Generate of keys description.
* For this use the DESCRIPTION_KEY(X) macros.
*
* @note This class is implementation of the Singleton pattern. Use carefully.
*/
class HEARTSHARED_EXPORT DBCacheKey
{
public:
/**
* @brief instance This method return instance of this singleton object.
* @return singleton of object.
*/
static DBCacheKey* instance();
template <class TYPE = AbstractKey>
/**
* @brief value This method return the value from key. For more convenient use the HASH_KEY(X) macros.
* @param key This is hash of key value
* @return value of key.
*/
const TYPE* value(uint key) const {
return dynamic_cast<const TYPE*>(_data.value(key, nullptr));
}
template <class TYPE>
/**
* @brief key This method return hash key and save object into objects table. For more convenient use the VALUE_KEY(X) macros
* @param value This is value of a key object.
* @return hash of input value.
*/
uint key(const TYPE& value) {
auto object = dynamic_cast<const AbstractKey*>(&value);
if (!object) {
return 0;
}
uint hash = object->hash();
if (_data.contains(hash)) {
_data[hash] = new TYPE(value);
}
return hash;
}
/**
* @brief description This method return string description of id (hash). For more convenient use the DESCRIPTION_KEY(X) macros.
* @param hash This is hash value of object (id).
* @return information about this hash value.
*/
QString description(uint hash) const;
private:
QHash<uint, AbstractKey*> _data;
DBCacheKey();
};
#define HASH_KEY(X) DBCacheKey::instance()->key(X)
#define VALUE_KEY(X) DBCacheKey::instance()->value(X)
#define DESCRIPTION_KEY(X) DBCacheKey::instance()->description(X)
}
#endif // DBCACHEKEY_H

@ -1,63 +0,0 @@
/*
* Copyright (C) 2020-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#ifndef DB_ERRORCODES_H
#define DB_ERRORCODES_H
#include "abstracterrorcodes.h"
namespace QH {
namespace ErrorCodes {
/**
* @brief The DBErrorCodes enum This is AuthRequest error codes. For more information see the QH::AuthRequest class.
*/
enum DBErrorCodes: Code {
/// User not registered because database not inited or other error occurred.
InternalError = AbstractErrorCodes::AbstractErrorCodes,
/// User not have a permission of execute a requested operation.
OperatioForbiden,
/// User not registered because user already exists.
UserExits,
/// User not logged because you need register user before login.
UserNotExits,
/// User is not Logged.
UserNotLogged,
/// User not logged because have an invalid password.
UserInvalidPasswoed,
/// User Already Logged.
UserAlreadyLogged,
/// User not logged or registered because time out. Emitted after 10 sec if not response from server.
TimeOutError,
/// This case using for inheritance new enum classes.
DBErrorCodes,
};
/**
* @brief The DBErrorCodesHelper class use for translate the error codes to the string values.
* This class known about all error codes of the DBErrorCodes enum and AbstractErrorCodes enum.
*/
class HEARTSHARED_EXPORT DBErrorCodesHelper {
public:
/**
* @brief toString This method have a cases for the translate all ErrorCodes of the QuasarApp Heart library.
* @param enumData This is error code.
* @return string value of the error code.
* @note This helper support all enum from the AbstractErrorCodesHelper class.
*/
static QString toString(Code enumData);
private:
DBErrorCodesHelper() = default;
};
}
}
#endif // SingleERRORCODES_H

@ -5,7 +5,7 @@
* of this license document, but changing it is not allowed.
*/
#include "isqldbcache.h"
#include "isqldb.h"
#include "quasarapp.h"
#include "sqldbwriter.h"
#include "dbaddresskey.h"
@ -22,7 +22,7 @@ namespace QH {
using namespace PKG;
void ISqlDBCache::globalUpdateDataBase(SqlDBCasheWriteMode mode) {
void ISqlDB::globalUpdateDataBase(SqlDBCasheWriteMode mode) {
qint64 currentTime = QDateTime::currentMSecsSinceEpoch();
if (currentTime - lastUpdateTime > updateInterval ||
@ -50,7 +50,7 @@ void ISqlDBCache::globalUpdateDataBase(SqlDBCasheWriteMode mode) {
}
}
bool ISqlDBCache::updateObjectP(const QSharedPointer<DBObject> &saveObject,
bool ISqlDB::updateObjectP(const QSharedPointer<DBObject> &saveObject,
bool wait) {
if (updateCache(saveObject)) {
@ -70,7 +70,7 @@ bool ISqlDBCache::updateObjectP(const QSharedPointer<DBObject> &saveObject,
_writer->updateObject(saveObject, wait);
}
bool ISqlDBCache::deleteObjectP(const QSharedPointer<DBObject> &delObj,
bool ISqlDB::deleteObjectP(const QSharedPointer<DBObject> &delObj,
bool wait) {
deleteFromCache(delObj);
@ -83,7 +83,7 @@ bool ISqlDBCache::deleteObjectP(const QSharedPointer<DBObject> &delObj,
return false;
}
bool ISqlDBCache::insertObjectP(const QSharedPointer<DBObject> &saveObject,
bool ISqlDB::insertObjectP(const QSharedPointer<DBObject> &saveObject,
bool wait) {
if (insertToCache(saveObject)) {
@ -104,41 +104,41 @@ bool ISqlDBCache::insertObjectP(const QSharedPointer<DBObject> &saveObject,
_writer->insertObject(saveObject, wait);
}
qint64 ISqlDBCache::getLastUpdateTime() const {
qint64 ISqlDB::getLastUpdateTime() const {
return lastUpdateTime;
}
void ISqlDBCache::setLastUpdateTime(const qint64 &value) {
void ISqlDB::setLastUpdateTime(const qint64 &value) {
lastUpdateTime = value;
}
void ISqlDBCache::pushToQueue(const QSharedPointer<DBObject> &obj,
void ISqlDB::pushToQueue(const QSharedPointer<DBObject> &obj,
CacheAction type) {
_saveLaterMutex.lock();
_changes.insert(type, obj);
_saveLaterMutex.unlock();
}
ISqlDBCache::ISqlDBCache(qint64 updateInterval, SqlDBCasheWriteMode mode) {
ISqlDB::ISqlDB(qint64 updateInterval, SqlDBCasheWriteMode mode) {
lastUpdateTime = QDateTime::currentMSecsSinceEpoch();
this->updateInterval = updateInterval;
setMode(mode);
}
ISqlDBCache::~ISqlDBCache() {
ISqlDB::~ISqlDB() {
}
SqlDBWriter *ISqlDBCache::writer() const {
SqlDBWriter *ISqlDB::writer() const {
return _writer;
}
void ISqlDBCache::setWriter(SqlDBWriter *writer) {
void ISqlDB::setWriter(SqlDBWriter *writer) {
_writer = writer;
}
bool ISqlDBCache::getAllObjects(const DBObject &templateObject,
bool ISqlDB::getAllObjects(const DBObject &templateObject,
QList<QSharedPointer<QH::PKG::DBObject>> &result) {
result = getFromCache(&templateObject);
@ -165,7 +165,7 @@ bool ISqlDBCache::getAllObjects(const DBObject &templateObject,
return false;
}
bool ISqlDBCache::deleteObject(const QSharedPointer<DBObject> &delObj,
bool ISqlDB::deleteObject(const QSharedPointer<DBObject> &delObj,
bool wait) {
if (!delObj)
@ -184,7 +184,7 @@ bool ISqlDBCache::deleteObject(const QSharedPointer<DBObject> &delObj,
}
bool ISqlDBCache::updateObject(const QSharedPointer<DBObject> &saveObject,
bool ISqlDB::updateObject(const QSharedPointer<DBObject> &saveObject,
bool wait) {
if (!saveObject || !saveObject->isValid()) {
@ -200,7 +200,7 @@ bool ISqlDBCache::updateObject(const QSharedPointer<DBObject> &saveObject,
return true;
}
bool ISqlDBCache::insertObject(const QSharedPointer<DBObject> &saveObject, bool wait) {
bool ISqlDB::insertObject(const QSharedPointer<DBObject> &saveObject, bool wait) {
if (!saveObject || !saveObject->isValid()) {
return false;
}
@ -214,7 +214,7 @@ bool ISqlDBCache::insertObject(const QSharedPointer<DBObject> &saveObject, bool
return true;
}
bool ISqlDBCache::doQuery(const QString &query, bool wait,
bool ISqlDB::doQuery(const QString &query, bool wait,
QSqlQuery *result) const {
if (!_writer) {
@ -224,7 +224,7 @@ bool ISqlDBCache::doQuery(const QString &query, bool wait,
return _writer->doQuery(query, wait, result);
}
bool ISqlDBCache::doSql(const QString &sqlFile, bool wait) const {
bool ISqlDB::doSql(const QString &sqlFile, bool wait) const {
if (!_writer) {
return false;
}
@ -232,7 +232,7 @@ bool ISqlDBCache::doSql(const QString &sqlFile, bool wait) const {
return _writer->doSql(sqlFile, wait);
}
bool ISqlDBCache::init(const QString &initDbParams) {
bool ISqlDB::init(const QString &initDbParams) {
if (!_writer) {
return false;
@ -241,7 +241,7 @@ bool ISqlDBCache::init(const QString &initDbParams) {
return _writer->initDb(initDbParams);
}
bool ISqlDBCache::init(const QVariantMap &params) {
bool ISqlDB::init(const QVariantMap &params) {
if (!_writer) {
return false;
@ -250,17 +250,17 @@ bool ISqlDBCache::init(const QVariantMap &params) {
return _writer->initDb(params);
}
void ISqlDBCache::setSQLSources(const QStringList &list) {
void ISqlDB::setSQLSources(const QStringList &list) {
auto db = writer();
if (db)
db->setSQLSources(list);
}
void ISqlDBCache::prepareForDelete() {
void ISqlDB::prepareForDelete() {
globalUpdateDataBase(SqlDBCasheWriteMode::Force);
}
bool ISqlDBCache::changeObjects(const DBObject &templateObject,
bool ISqlDB::changeObjects(const DBObject &templateObject,
const std::function<bool (const QSharedPointer<QH::PKG::DBObject>&)> &changeAction) {
QList<QSharedPointer<DBObject>> list;
@ -285,15 +285,15 @@ bool ISqlDBCache::changeObjects(const DBObject &templateObject,
return true;
}
SqlDBCasheWriteMode ISqlDBCache::getMode() const {
SqlDBCasheWriteMode ISqlDB::getMode() const {
return _mode;
}
void ISqlDBCache::setMode(const SqlDBCasheWriteMode &mode) {
void ISqlDB::setMode(const SqlDBCasheWriteMode &mode) {
_mode = mode;
}
void ISqlDBCache::globalUpdateDataBasePrivate(qint64 currentTime) {
void ISqlDB::globalUpdateDataBasePrivate(qint64 currentTime) {
QMutexLocker lock(&_saveLaterMutex);
for (auto it = _changes.begin(); it != _changes.end(); ++it) {
@ -355,11 +355,11 @@ void ISqlDBCache::globalUpdateDataBasePrivate(qint64 currentTime) {
setLastUpdateTime(currentTime);
}
qint64 ISqlDBCache::getUpdateInterval() const {
qint64 ISqlDB::getUpdateInterval() const {
return updateInterval;
}
void ISqlDBCache::setUpdateInterval(const qint64 &value) {
void ISqlDB::setUpdateInterval(const qint64 &value) {
updateInterval = value;
}

@ -5,10 +5,9 @@
* of this license document, but changing it is not allowed.
*/
#ifndef ISQLDBCACHE_H
#define ISQLDBCACHE_H
#ifndef ISQLDB_H
#define ISQLDB_H
#include "dbcachekey.h"
#include "iobjectprovider.h"
#include <QMap>
@ -17,7 +16,6 @@
#include <QVariantMap>
#include <QMutex>
#include <AbstractSpace/config.h>
#include "basedefines.h"
#include "softdelete.h"
namespace QH {
@ -55,7 +53,7 @@ enum class CacheAction: int {
};
/**
* @brief The ISqlDBCache class it is db cache and bridge for DbWriters.
* @brief The ISqlDB class it is db cache and bridge for DbWriters.
* Work Scheme of the database cache:
*
* \image html DatabseCache.svg width=800px
@ -71,19 +69,19 @@ enum class CacheAction: int {
* If you try delete this object without using softDelete method then destructor of this object emit runtime error exception (on the debug mode only).
*
*/
class HEARTSHARED_EXPORT ISqlDBCache: public QObject, public iObjectProvider, public SoftDelete
class HEARTSHARED_EXPORT ISqlDB: public QObject, public iObjectProvider, public SoftDelete
{
Q_OBJECT
public:
/**
* @brief SqlDBCache This is default constructor of dbcache.
* @brief ISqlDB This is default constructor of dbcache.
* @param updateInterval See the SqlDBCache::setUpdateInterval for more information.
* @param mode See the SqlDBCache::setMode method for more information.
*/
ISqlDBCache(qint64 updateInterval = DEFAULT_UPDATE_INTERVAL,
ISqlDB(qint64 updateInterval = DEFAULT_UPDATE_INTERVAL,
SqlDBCasheWriteMode mode = SqlDBCasheWriteMode::Default);
~ISqlDBCache() override;
~ISqlDB() override;
/**
* @brief writer This method return is database writer object. For more inforamation about writer see the SqlDBWriter class.
@ -275,4 +273,4 @@ constexpr inline uint qHash(CacheAction action) {
}
#endif // ISQLDBCACHE_H
#endif // ISQLDB_H

@ -1,128 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#include "abstractnetworkmember.h"
#include <quasarapp.h>
#include <QSqlQuery>
#include <QSqlError>
#include <QDataStream>
namespace QH {
namespace PKG {
AbstractNetworkMember::AbstractNetworkMember() {
}
AbstractNetworkMember::AbstractNetworkMember(const Package &pkg):
AbstractNetworkMember() {
fromBytes(pkg.data);
}
AbstractNetworkMember::AbstractNetworkMember(const QString& id):
AbstractNetworkMember() {
setId(id);
}
bool AbstractNetworkMember::fromSqlRecord(const QSqlRecord &q) {
setId(q.value("id").toString());
setAuthenticationData(q.value("authenticationData").toByteArray());
setTrust(q.value("trust").toInt());
return AbstractNetworkMember::isValid();
}
QByteArray AbstractNetworkMember::authenticationData() const {
return _authenticationData;
}
void AbstractNetworkMember::setAuthenticationData(const QByteArray &publickKey) {
_authenticationData = publickKey;
}
QDataStream &AbstractNetworkMember::fromStream(QDataStream &stream) {
DBObject::fromStream(stream);
stream >> _id;
stream >> _authenticationData;
stream >> _trust;
return stream;
}
QDataStream &AbstractNetworkMember::toStream(QDataStream &stream) const {
stream << _id;
stream << _authenticationData;
stream << _trust;
return stream;
}
DBVariantMap AbstractNetworkMember::variantMap() const {
return {{"id", {_id, QH::PKG::MemberType::PrimaryKey}},
{"authenticationData", {_authenticationData, QH::PKG::MemberType::InsertUpdate}},
{"trust", {_trust, QH::PKG::MemberType::InsertUpdate}},
};
}
QString AbstractNetworkMember::primaryKey() const {
return "id";
}
QString AbstractNetworkMember::primaryValue() const {
return _id;
}
const QString &AbstractNetworkMember::getId() const {
return _id;
}
void AbstractNetworkMember::setId(const QString &newId) {
_id = newId;
}
QString AbstractNetworkMember::table() const {
return "NetworkMembers";
}
int AbstractNetworkMember::trust() const {
return _trust;
}
void AbstractNetworkMember::changeTrust(int diff) {
_trust += diff;
}
void AbstractNetworkMember::setTrust(int trust) {
_trust = trust;
}
bool AbstractNetworkMember::isValid() const {
return DBObject::isValid();
}
bool AbstractNetworkMember::copyFrom(const AbstractData * other) {
if (!DBObject::copyFrom(other))
return false;
auto otherObject = dynamic_cast<const AbstractNetworkMember*>(other);
if (!otherObject)
return false;
this->_id = otherObject->_id;
this->_authenticationData = otherObject->_authenticationData;
this->_trust = otherObject->_trust;
return true;
}
}
}

@ -1,100 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#ifndef ABSTRACTNETWORKMEMBER_H
#define ABSTRACTNETWORKMEMBER_H
#include "dbobject.h"
namespace QH {
namespace PKG {
/**
* @brief The AbstractNetworkMember class is structure of network member.
* Usually it is base informations of node or client.
*/
class HEARTSHARED_EXPORT AbstractNetworkMember: public DBObject
{
QH_PACKAGE(AbstractNetworkMember, "AbstractNetworkMember")
public:
AbstractNetworkMember();
AbstractNetworkMember(const Package& pkg);
AbstractNetworkMember(const QString &id);
// DBObject interface
bool fromSqlRecord(const QSqlRecord &q) override;
/**
* @brief authenticationData is data array requirement for authentication node or client on the network.
* @return The byte Array of authentication data.
*/
QByteArray authenticationData() const;
/**
* @brief setAuthenticationData This method set new array of authentication data.
* @param data This is new data of authentication data.
*/
void setAuthenticationData(const QByteArray &data);
// AbstractData interface
bool isValid() const override;
bool copyFrom(const AbstractData *) override;
DBVariantMap variantMap() const override;
/**
* @brief trust This is trust level of current Network member.
* IF the trust level less then 0 node or client will be blocked (banned).
* @return current trust level of this node.
*/
int trust() const;
/**
* @brief changeTrust This method change a current trust level.
* @param diff This is a diff of current value. (currentTrust += diff;)
*/
void changeTrust(int diff);
/**
* @brief setTrust This method set a new value of trust level of the node.
* @param trust This is a new value.
*/
void setTrust(int trust);
/**
* @brief getId This method return id of this object in database.
* @return id of this object in database.
*/
const QString &getId() const;
/**
* @brief setId This method sets new id of this object.
* @param newId This is new value of @a id of this object.
*/
void setId(const QString &newId);
QString table() const override;
protected:
// StreamBase interface
QDataStream &fromStream(QDataStream &stream) override;
QDataStream &toStream(QDataStream &stream) const override;
QString primaryKey() const override;
QString primaryValue() const override;
private:
QString _id;
QByteArray _authenticationData;
int _trust;
};
}
}
#endif // ABSTRACTNETWORKMEMBER_H

@ -1,46 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#include "authrequest.h"
#include <QDataStream>
namespace QH {
namespace PKG {
AuthRequest::AuthRequest() {
}
AuthRequest::AuthRequest(const Package &pkg) {
fromBytes(pkg.data);
}
unsigned char AuthRequest::getRequestCmd() const {
return static_cast<unsigned char>(_request);
}
QDataStream &AuthRequest::fromStream(QDataStream &stream) {
UserMember::fromStream(stream);
stream >> _request;
return stream;
}
QDataStream &AuthRequest::toStream(QDataStream &stream) const {
UserMember::toStream(stream);
stream << _request;
return stream;
}
void AuthRequest::setRequest(const UserRequestType &request) {
_request = request;
}
}
}

@ -1,62 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#ifndef AUTHREQUEST_H
#define AUTHREQUEST_H
#include "usermember.h"
#include <request.h>
namespace QH {
namespace PKG {
/**
* @brief The UserRequestType enum is types of request.
*/
enum class UserRequestType: unsigned char {
/// Request to registration a new user.
SignUp,
/// Request to login an exists user.
LogIn,
/// Request to logout an exists user. This request remove the generated accesses token from server.
LogOut
};
/**
* @brief The AuthRequest class This class using for send to the SingleServer request to login or registration.
* Use the Request::getRequestCmd and Request::setRequestCmd methods for set an UserRequestType value.
*/
class HEARTSHARED_EXPORT AuthRequest: public UserMember, public Request
{
QH_PACKAGE(AuthRequest, "AuthRequest")
public:
AuthRequest();
AuthRequest(const Package& pkg);
unsigned char getRequestCmd() const override;
// StreamBase interface
/**
* @brief setRequest This method set request type for this object.
* @param request
*/
void setRequest(const UserRequestType &request);
protected:
QDataStream &fromStream(QDataStream &stream) override;
QDataStream &toStream(QDataStream &stream) const override;
private:
UserRequestType _request;
};
}
}
#endif // AUTHREQUEST_H

@ -6,7 +6,6 @@
*/
#include "dbaddresskey.h"
#include "dbcachekey.h"
#include "dbobject.h"
#include <QDataStream>
#include <QDateTime>
@ -327,14 +326,6 @@ bool DBObject::copyFrom(const AbstractData * other) {
return AbstractData::copyFrom(other);
}
unsigned int DBObject::subscribeId() const {
return dbKey();
}
unsigned int DBObject::subscribeId(const DbAddress &address) {
return HASH_KEY(DbAddressKey(address));
}
bool DBObject::isHaveAPrimaryKey() const {
return primaryKey().size();
}

@ -12,9 +12,6 @@
#include "abstractdata.h"
#include "heart_global.h"
#include "dbaddress.h"
#include "basedefines.h"
#include "dbcachekey.h"
#include "isubscribabledata.h"
class QSqlQuery;
@ -96,7 +93,7 @@ typedef QMap<QString, DBVariant> DBVariantMap;
* @warning Object with empty table name is invalid.
* @see DataBaseNode
*/
class HEARTSHARED_EXPORT DBObject : public AbstractData, public ISubscribableData
class HEARTSHARED_EXPORT DBObject : public AbstractData
{
QH_PACKAGE(DBObject, "DBObject")
@ -108,14 +105,6 @@ public:
bool isValid() const override;
bool copyFrom(const AbstractData * other) override;
unsigned int subscribeId() const override;
/**
* @brief subscribeId This static method convert database address to the subscribe id.
* @param address This is input value of the database address.
* @return subscribe id.
*/
static unsigned int subscribeId(const DbAddress& address);
/**
* @brief isHaveAPrimaryKey This method return true if this object has a primary key.

@ -1,56 +0,0 @@
/*
* Copyright (C) 2021-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#include "defaultpermision.h"
namespace QH {
namespace PKG {
DefaultPermision::DefaultPermision():
MemberPermisionObject() {
}
DefaultPermision::DefaultPermision(const PermisionData &permision):
DefaultPermision() {
setKey(permision);
}
DBVariantMap DefaultPermision::variantMap() const {
return {{"dbAddress", {key().addressHash(), MemberType::PrimaryKey}},
{"lvl", {static_cast<unsigned char>(permisions()), MemberType::InsertUpdate}}};
}
bool DefaultPermision::isValid() const {
return key().addressHash().size();
}
DBObject *DefaultPermision::createDBObject() const {
return create<DefaultPermision>();
}
bool DefaultPermision::fromSqlRecord(const QSqlRecord &q) {
PermisionData permision({}, q.value("dbAddress").toString());
setKey(permision);
setPermisions(static_cast<Permission>(q.value("lvl").toUInt()));
return isValid();
}
QString DefaultPermision::condition() const {
QString result;
result += "dbAddress='" + key().addressHash() + "'";
return result;
}
QString DefaultPermision::table() const {
return "DefaultPermissions";
}
}
}

@ -1,42 +0,0 @@
/*
* Copyright (C) 2021-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#ifndef DEFAULTPERMISION_H
#define DEFAULTPERMISION_H
#include "memberpermisionobject.h"
#include "permission.h"
namespace QH {
namespace PKG {
/**
* @brief The DefaultPermision class contains default of network members
* This class works with the DefaultPermissions sql table.
*/
class HEARTSHARED_EXPORT DefaultPermision: public MemberPermisionObject
{
QH_PACKAGE(DefaultPermision, "DefaultPermision")
public:
DefaultPermision();
DefaultPermision(const PermisionData& permision);
DBVariantMap variantMap() const override;
bool isValid() const override;
bool fromSqlRecord(const QSqlRecord &q) override;
DBObject *createDBObject() const override;
QString condition() const override;
QString table () const override;
};
}
}
#endif // DEFAULTPERMISION_H

@ -1,16 +0,0 @@
/*
* Copyright (C) 2021-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#include "isubscribabledata.h"
namespace QH {
namespace PKG {
ISubscribableData::ISubscribableData() {
}
}
}

@ -1,37 +0,0 @@
/*
* Copyright (C) 2021-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#ifndef ISUBSCRIBABLEDATA_H
#define ISUBSCRIBABLEDATA_H
#include "heart_global.h"
#include <QMetaType>
namespace QH {
namespace PKG {
/**
* @brief The ISubscribableData class is interface provide subscribe functionality.
* If you want to create a data object with support of the subscribe functionality then you need to inherit form this class.
*/
class HEARTSHARED_EXPORT ISubscribableData
{
public:
ISubscribableData();
/**
* @brief subscribeId All subscribable object should be override this method.
* This method should be return signed int id.
* @return unique id of the subscribe object.
*/
virtual unsigned int subscribeId() const = 0;
};
}
}
#endif // ISUBSCRIBABLEDATA_H

@ -1,138 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#include "memberpermisionobject.h"
#include <QDataStream>
#include <QSqlQuery>
#include <dbcachekey.h>
namespace QH {
namespace PKG {
MemberPermisionObject::MemberPermisionObject() {
}
MemberPermisionObject::MemberPermisionObject(const Package &pkg):
MemberPermisionObject() {
fromBytes(pkg.data);
}
MemberPermisionObject::MemberPermisionObject(const PermisionData &id):
MemberPermisionObject() {
setKey(id);
}
bool MemberPermisionObject::isValid() const {
return _key.isValid();
}
bool MemberPermisionObject::copyFrom(const AbstractData *other) {
if (!DBObject::copyFrom(other))
return false;
auto otherObject = dynamic_cast<const MemberPermisionObject*>(other);
if (!otherObject)
return false;
this->_key = otherObject->_key;
this->_permision = otherObject->_permision;
return true;
}
DBObject *MemberPermisionObject::createDBObject() const {
return create<MemberPermisionObject>();
}
uint MemberPermisionObject::dbKey() const {
return HASH_KEY(_key);
}
bool MemberPermisionObject::fromSqlRecord(const QSqlRecord &q) {
PermisionData permision(q.value("memberId").toString(),
q.value("dbAddress").toString());
setKey(permision);
setPermisions(static_cast<Permission>(q.value("lvl").toUInt()));
return isValid();
}
bool MemberPermisionObject::isCached() const {
return true;
}
QDataStream &MemberPermisionObject::fromStream(QDataStream &stream) {
stream >> _key;
stream >> _permision;
return stream;
}
QDataStream &MemberPermisionObject::toStream(QDataStream &stream) const {
stream << _key;
stream << _permision;
return stream;
}
DBVariantMap MemberPermisionObject::variantMap() const {
return {{"memberId", {_key.id(), MemberType::InsertUpdate}},
{"dbAddress", {_key.addressHash(), MemberType::InsertUpdate}},
{"lvl", {static_cast<unsigned char>(_permision), MemberType::InsertUpdate}}};
}
QString MemberPermisionObject::table() const {
return "MemberPermisions";
}
QString MemberPermisionObject::condition() const {
QString result;
if (_key.id().isValid()) {
result += "memberId='" + _key.id().toString() + "'";
}
if (_key.addressHash().size()) {
if (result.size()) {
result += " AND ";
}
result += "dbAddress='" + _key.addressHash()+ "'";
}
return result;
}
QString MemberPermisionObject::primaryKey() const {
return "";
}
QString MemberPermisionObject::primaryValue() const {
return "";
}
PermisionData MemberPermisionObject::key() const {
return _key;
}
void MemberPermisionObject::setKey(const PermisionData &key) {
_key = key;
}
Permission MemberPermisionObject::permisions() const {
return _permision;
}
void MemberPermisionObject::setPermisions(const Permission &permisions) {
_permision = permisions;
}
}
}

@ -1,86 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#ifndef NODESPERMISIONOBJECT_H
#define NODESPERMISIONOBJECT_H
#include "dbcachekey.h"
#include "dbobject.h"
#include "permisiondata.h"
#include "permission.h"
namespace QH {
namespace PKG {
/**
* @brief The NodesPermisionObject class contains permissions data of node or client.
* This class is representation of database object from the MemberPermisions table.
*/
class HEARTSHARED_EXPORT MemberPermisionObject: public DBObject
{
QH_PACKAGE(MemberPermisionObject, "MemberPermisionObject")
public:
MemberPermisionObject();
MemberPermisionObject(const Package& pkg);
MemberPermisionObject(const PermisionData& id);
// AbstractData interface
bool isValid() const override;
bool copyFrom(const AbstractData *other) override;
// DBObject interface
DBObject *createDBObject() const override;
uint dbKey() const override;
bool fromSqlRecord(const QSqlRecord &q) override;
bool isCached() const override;
DBVariantMap variantMap() const override;
QString table() const override;
/**
* @brief permisions This method return value permission of object.
* For select object set it id using a MemberPermisionObject::setKey method.
* @return Permission level. For more information see the Permission enum.
*/
Permission permisions() const;
/**
* @brief setPermisions This method set a new value of permissions level.
* @param permisions This is a new value of permissions.
*/
void setPermisions(const Permission &permisions);
/**
* @brief key This method return key (database address) of a checked object.
* @return PermisionData key. For more information see PermisionData class.
*/
PermisionData key() const;
/**
* @brief setKey This method set new value of PermisionData.
* @param key This is new value of PermisionData.
*/
void setKey(const PermisionData &key);
protected:
// StreamBase interface
QDataStream &fromStream(QDataStream &stream) override;
QDataStream &toStream(QDataStream &stream) const override;
QString condition() const override;
QString primaryKey() const override;
QString primaryValue() const override;
private:
Permission _permision;
PermisionData _key;
};
}
}
#endif // NODESPERMISIONOBJECT_H

@ -1,26 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#include "networkmember.h"
namespace QH {
namespace PKG {
NetworkMember::NetworkMember() {
}
NetworkMember::NetworkMember(const QString &id): AbstractNetworkMember(id) {
}
DBObject *NetworkMember::createDBObject() const {
return create<NetworkMember>();
}
}
}

@ -1,35 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#ifndef NETWORKMEMBER_H
#define NETWORKMEMBER_H
#include <abstractnetworkmember.h>
namespace QH {
namespace PKG {
/**
* @brief The NetworkMember class is base implementation of the AbstractNetworkMember.
* This class contains all default settings of the AbstractNetworkMember class.
* If you want to create a own member class then use the AbstractNetworkMember class.
*/
class HEARTSHARED_EXPORT NetworkMember: public AbstractNetworkMember
{
QH_PACKAGE(NetworkMember, "NetworkMember")
public:
NetworkMember();
NetworkMember(const QString& id);
public:
DBObject *createDBObject() const override;
};
}
}
#endif // NETWORKMEMBER_H

@ -1,82 +0,0 @@
#include "usermember.h"
#include <QDataStream>
namespace QH {
namespace PKG {
UserMember::UserMember() {
setTrust(100);
}
UserMember::UserMember(const Package &pkg):
UserMember() {
fromBytes(pkg.data);
}
UserMember::UserMember(const QString &id):
UserMember() {
setId(id);
}
bool UserMember::copyFrom(const AbstractData *other) {
if (!AbstractNetworkMember::copyFrom(other))
return false;
auto otherObject = dynamic_cast<const UserMember*>(other);
if (!otherObject)
return false;
this->_token = otherObject->_token;
return true;
}
bool UserMember::fromSqlRecord(const QSqlRecord &q) {
if (!AbstractNetworkMember::fromSqlRecord(q)) {
return false;
}
setSignToken(AccessToken(q.value("token").toByteArray()));
return UserMember::isValid();
}
DBObject *UserMember::createDBObject() const {
return create<UserMember>();
}
bool UserMember::isValid() const {
return AbstractNetworkMember::isValid() && trust() <= 100;
}
QDataStream &UserMember::fromStream(QDataStream &stream) {
AbstractNetworkMember::fromStream(stream);
stream >> _token;
return stream;
}
QDataStream &UserMember::toStream(QDataStream &stream) const {
AbstractNetworkMember::toStream(stream);
stream << _token;
return stream;
}
const AccessToken &UserMember::getSignToken() const {
return _token;
}
DBVariantMap UserMember::variantMap() const {
auto map = AbstractNetworkMember::variantMap();
map.insert("token", {_token.toBytes(), MemberType::InsertUpdate});
return map;
}
void UserMember::setSignToken(const AccessToken &token) {
_token = token;
}
}
}

@ -1,51 +0,0 @@
#ifndef USER_H
#define USER_H
#include "abstractnetworkmember.h"
#include "accesstoken.h"
#include "itoken.h"
namespace QH {
namespace PKG {
/**
* @brief The UserMember class is some as a AbstractNetworkMember class.
* All registered users on the singelServer have own list database object with own permissions.
* If you want create a custom permissions table with the custom user then override this class.
*
* @note The UserMember class has no members of its own, so it is safe to use static_cast on User <<>> AbstractNetworkMember.
*/
class HEARTSHARED_EXPORT UserMember: public AbstractNetworkMember
{
QH_PACKAGE(UserMember, "UserMember")
public:
UserMember();
UserMember(const Package &pkg);
UserMember(const QString &id);
bool copyFrom(const AbstractData *other) override;
bool fromSqlRecord(const QSqlRecord &q) override;
DBObject *createDBObject() const override;
bool isValid() const override;
DBVariantMap variantMap() const override;
void setSignToken(const AccessToken &token);
const AccessToken &getSignToken() const;
protected:
QDataStream &fromStream(QDataStream &stream) override;
QDataStream &toStream(QDataStream &stream) const override;
private:
AccessToken _token;
};
}
}
#endif // USER_H

@ -1,61 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#include "websocket.h"
#include <QDataStream>
#include <QSharedPointer>
namespace QH {
namespace PKG {
WebSocket::WebSocket(): AbstractData(){
}
WebSocket::WebSocket(const Package &package):
WebSocket() {
fromBytes(package.data);
}
QDataStream &WebSocket::fromStream(QDataStream &stream) {
stream >> _request;
stream >> _subscribeId;
return stream;
}
QDataStream &WebSocket::toStream(QDataStream &stream) const {
stream << _request;
stream << _subscribeId;
return stream;
}
unsigned char WebSocket::getRequestCmd() const {
return static_cast<unsigned char>(_request);
}
unsigned int WebSocket::subscribeId() const {
return _subscribeId;
}
void WebSocket::setSubscribeId(unsigned int address) {
_subscribeId = address;
}
void WebSocket::setRequestCommnad(const WebSocketRequest &requset) {
_request = requset;
}
bool WebSocket::isValid() const {
return _request > WebSocketRequest::Invalied
&& AbstractData::isValid();
}
}
}

@ -1,80 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#ifndef WEBSOCKET_H
#define WEBSOCKET_H
#include "dbobject.h"
#include "request.h"
namespace QH {
namespace PKG {
/**
* @brief The WebSocketRequest enum This enum is list of available request of WebSocket functions.
*/
enum class WebSocketRequest {
/// This is value for reserve invalid data. All request must be not equal 0.
Invalied = 0,
/// Subscribe to changes of the databases object.
Subscribe = 1,
/// Subscribe to changes of the databases object.
Unsubscribe = 2,
/// send request of get a list of current subscribes.
SubscribeList = 3
};
/**
* @brief The WebSocket class is contains methods for work with stream data.
*/
class HEARTSHARED_EXPORT WebSocket:
public AbstractData, public Request
{
QH_PACKAGE(WebSocket, "WebSocket")
public:
WebSocket();
WebSocket(const Package& package);
bool isValid() const override;
/**
* @brief subscribeId This method return address(unique id) of the subscribe object.
* @return unique id of the subscribe object.
*/
unsigned int subscribeId() const;
/**
* @brief setSubscribeId This method set a unique id of the subscribe object.
* @param address This is a new database unique id of the subscribe object.
*/
void setSubscribeId(unsigned int address);
/**
* @brief setRequestCommnad This method sets requset command.
* @param requset This is new request command.
*/
void setRequestCommnad(const WebSocketRequest& requset);
unsigned char getRequestCmd() const override;
protected:
QDataStream &fromStream(QDataStream &stream) override;
QDataStream &toStream(QDataStream &stream) const override;
private:
unsigned int _subscribeId;
WebSocketRequest _request = WebSocketRequest::Invalied;
// Request interface
};
}
}
#endif // WEBSOCKET_H

@ -1,48 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#include "websocketsubscriptions.h"
#include <QDataStream>
namespace QH {
namespace PKG {
WebSocketSubscriptions::WebSocketSubscriptions()
{
}
WebSocketSubscriptions::WebSocketSubscriptions(const QH::Package &package):
WebSocketSubscriptions()
{
fromBytes(package.data);
}
QDataStream &WebSocketSubscriptions::fromStream(QDataStream &stream) {
return stream >> _subscribeIds;
}
QDataStream &WebSocketSubscriptions::toStream(QDataStream &stream) const {
return stream << _subscribeIds;
}
QSet<unsigned int> WebSocketSubscriptions::addresses() const {
return _subscribeIds;
}
void WebSocketSubscriptions::setAddresses(const QSet<unsigned int> &addresses) {
_subscribeIds = addresses;
}
}
}

@ -1,54 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#ifndef WEBSOCKETSUBSCRIPTIONS_H
#define WEBSOCKETSUBSCRIPTIONS_H
#include "abstractdata.h"
#include <QSet>
#include <dbaddress.h>
namespace QH {
namespace PKG {
/**
* @brief The WebSocketSubscriptions class is list of subscribers object.
* Using for transporting a informations about subscribers.
*/
class HEARTSHARED_EXPORT WebSocketSubscriptions: public AbstractData
{
QH_PACKAGE(WebSocketSubscriptions, "WebSocketSubscriptions")
public:
WebSocketSubscriptions();
WebSocketSubscriptions(const Package& package);
QDataStream &fromStream(QDataStream &stream) override;
QDataStream &toStream(QDataStream &stream) const override;
/**
* @brief addresses This is list of subscribers.
*/
QSet<unsigned int> addresses() const;
/**
* @brief setAddresses This method set a new list of subscribers.
* @param addresses This is a new list of subscribers.
*/
void setAddresses(const QSet<unsigned int> &addresses);
private:
QSet<unsigned int> _subscribeIds;
};
}
}
#endif // WEBSOCKETSUBSCRIPTIONS_H

@ -1,91 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#include "dbaddress.h"
#include "permisiondata.h"
#include <quasarapp.h>
#include <QDataStream>
#include <QIODevice>
namespace QH {
bool operator ==(const PermisionData &left, const PermisionData &right) {
return left._id == right._id && left._addressHash == right._addressHash;
}
PermisionData::PermisionData(const QVariant &subject, const DbAddress &objcet) {
setId(subject);
setAddress(objcet);
}
PermisionData::PermisionData(const QVariant &subject, const QString &objectAddress) {
setId(subject);
setAddress(objectAddress);
}
unsigned int PermisionData::hash() const {
QByteArray data;
QDataStream stream(&data, QIODevice::WriteOnly);
stream << _id;
stream << _addressHash;
return qHash(data);
}
bool PermisionData::isValid() const {
return _addressHash.size() && _id.isValid();
}
bool PermisionData::equal(const AbstractKey *other) const {
auto otherObject = dynamic_cast<const PermisionData*>(other);
if (!otherObject)
return false;
return _addressHash == otherObject->_addressHash && _id == otherObject->_id;
}
QString PermisionData::toString() const {
return QString("DBAddressHash: %0, Owner Id: %1").
arg(_addressHash, _id.toString());
}
const QString& PermisionData::addressHash() const {
return _addressHash;
}
void PermisionData::setAddress(const DbAddress &address) {
setAddress(address.SHA256Hash().toBase64(QByteArray::Base64UrlEncoding));
}
void PermisionData::setAddress(const QString &addressHash) {
_addressHash = addressHash;
}
QDataStream &PermisionData::fromStream(QDataStream &stream) {
stream >> _id;
stream >> _addressHash;
return stream;
}
QDataStream &PermisionData::toStream(QDataStream &stream) const {
stream << _id;
stream << _addressHash;
return stream;
}
const QVariant& PermisionData::id() const {
return _id;
}
void PermisionData::setId(const QVariant &Id) {
_id = Id;
}
}

@ -1,79 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#ifndef PERMISIONDATA_H
#define PERMISIONDATA_H
#include <QString>
#include <abstractkey.h>
#include "dbaddress.h"
namespace QH {
/**
* @brief The PermisionData class stores one correspondence to a network member and an object in the database.
* Network member - database address.
*/
class HEARTSHARED_EXPORT PermisionData: public AbstractKey, public StreamBase {
public:
PermisionData() = default;
PermisionData(const QVariant& subject, const DbAddress& objcet);
PermisionData(const QVariant& subject, const QString& objectAddress);
friend bool operator == (const PermisionData& left, const PermisionData& right);
unsigned int hash() const override;
bool isValid() const override;
bool equal(const AbstractKey *other) const override;
QString toString() const override;
/**
* @brief setId This method set id of Network member.
* @param Id Value of network member id.
*/
void setId(const QVariant &Id);
/**
* @brief addressHash This method return sha256 hash of the address of database object.
* The hash encoded as a base64.
* @return address of database object.
*/
const QString &addressHash() const;
/**
* @brief setAddress This method set address of database object.
* @param address This is new value of database address.
*/
void setAddress(const DbAddress &address);
/**
* @brief setAddress This implementation sets sha256 hash of the address (hash must be write in base64 encoding)
* @param addressHash This is base64 string of a sha256 hash code.
*/
void setAddress(const QString &addressHash);
// StreamBase interface
const QVariant &id() const;
protected:
QDataStream &fromStream(QDataStream &stream) override;
QDataStream &toStream(QDataStream &stream) const override;
private:
/// id of user of node
QVariant _id;
/// table of target object (second part of key)
QString _addressHash;
};
}
#endif // PERMISIONDATA_H

@ -1,29 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#ifndef PERMISIONS_H
#define PERMISIONS_H
namespace QH {
/**
* @brief The Permission enum
* permision to data in database
*/
enum class Permission: unsigned char {
/// The network member do not have any permissions for an object.
NoPermission = 0x00,
/// The network member can read a object.
Read = 0x01,
/// The network member can Read and Write a new data into object. But can not be removed.
Update = 0x02,
/// The network member have all permissions to an object.
Write = 0x03,
};
}
#endif // PERMISIONS_H

@ -1,20 +0,0 @@
#include "itoken.h"
#include "singlebase.h"
#include <abstractnetworkmember.h>
#include <websocket.h>
#include <websocketsubscriptions.h>
#include "usermember.h"
namespace QH {
SingleBase::SingleBase() {
registerPackageType<PKG::UserMember>();
}
bool SingleBase::checkToken(const PKG::AbstractData *pkg) const {
return dynamic_cast<const IToken*>(pkg);
}
}

@ -1,37 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#ifndef SINGLESERVERBASE_H
#define SINGLESERVERBASE_H
#include "databasenode.h"
namespace QH {
/**
* @brief The SingleServerBase class This is base class of SingleClient adn SingleServer
*/
class HEARTSHARED_EXPORT SingleBase: public DataBaseNode
{
Q_OBJECT
public:
SingleBase();
protected:
/**
* @brief checkToken This method check pkg on token validation support.
* @param pkg This is parsed package.
* @return true if the package not support token validation.
*
* For get more information see IToken class.
*/
bool checkToken(const PKG::AbstractData *pkg) const;
};
}
#endif // SINGLESERVERBASE_H

@ -1,521 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#include "singleclient.h"
#include "quasarapp.h"
#include "authrequest.h"
#include "dberrorcodes.h"
#include <deleteobject.h>
#include <websocket.h>
#include <websocketsubscriptions.h>
#include <qaglobalutils.h>
namespace QH {
SingleClient::SingleClient() {
qRegisterMetaType<QH::ClientStatus>();
setMaxPendingConnections(1);
registerPackageType<PKG::AuthRequest>();
connect(this, &SingleClient::requestError,
this, &SingleClient::handleError);
}
ParserResult SingleClient::parsePackage(const QSharedPointer<PKG::AbstractData> &pkg,
const Header& pkgHeader,
const AbstractNodeInfo* sender) {
auto parentResult = DataBaseNode::parsePackage(pkg, pkgHeader, sender);
if (parentResult != QH::ParserResult::NotProcessed) {
return parentResult;
}
if (QH::PKG::UserMember::command() == pkg->cmd()) {
QH::PKG::UserMember *obj = static_cast<QH::PKG::UserMember*>(pkg.data());
if (!(obj->isValid() && obj->getSignToken().isValid())) {
return ParserResult::Error;
}
setMember(*obj);
setStatus(ClientStatus::Logined);
emit currentUserChanged();
return QH::ParserResult::Processed;
} else if (PKG::WebSocketSubscriptions::command() == pkg->cmd()) {
PKG::WebSocketSubscriptions *obj = static_cast<PKG::WebSocketSubscriptions*>(pkg.data());
if (!obj->isValid()) {
return ParserResult::Error;
}
setSubscribersList(obj->addresses());
return ParserResult::Processed;
}
handleRestRequest(pkg, pkgHeader);
return QH::ParserResult::NotProcessed;
}
ClientStatus SingleClient::getStatus() const {
return _status;
}
bool SingleClient::login(const QString &userId, const QString &rawPassword) {
if (getStatus() < ClientStatus::Connected) {
QuasarAppUtils::Params::log("You try make login on the offline client."
" Please wait of ClientStatus::Connected status.",
QuasarAppUtils::Error);
return false;
}
if (!p_login(userId, hashgenerator(rawPassword.toLatin1()))) {
return false;
};
if (getStatus() < ClientStatus::Loginning) {
setStatus(ClientStatus::Loginning);
}
return true;
}
bool SingleClient::login(const PKG::UserMember &memberData) {
if (memberData.getSignToken() == getMember().getSignToken()) {
if (isLogined()) {
return true;
}
return login();
}
setMember(memberData);
return login();
}
bool SingleClient::logout() {
if (getStatus() < ClientStatus::Logined) {
QuasarAppUtils::Params::log("You try logout on the not Loggined client."
" Please wait of ClientStatus::Logined status.",
QuasarAppUtils::Error);
return false;
}
QH::PKG::AuthRequest request;
request.copyFrom(&getMember());
request.setRequest(PKG::UserRequestType::LogOut);
if (!sendData(&request, realServerAddress())) {
return false;
};
resetUser();
return true;
}
bool SingleClient::signup(const QString &userId, const QString &rawPassword) {
if (getStatus() < ClientStatus::Connected) {
QuasarAppUtils::Params::log("You try make signup on the offline client."
" Please wait of ClientStatus::Connected status.",
QuasarAppUtils::Error);
return false;
}
if (!p_signup(userId, hashgenerator(rawPassword.toLatin1()))) {
return false;
};
if (getStatus() < ClientStatus::Loginning) {
setStatus(ClientStatus::Loginning);
}
return true;
}
bool SingleClient::removeUser() {
if (getStatus() < ClientStatus::Logined) {
QuasarAppUtils::Params::log("You try make remove on the not Loggined client."
" Please wait of ClientStatus::Logined status.",
QuasarAppUtils::Error);
return false;
}
QH::PKG::DeleteObject request;
request.setAddress(getMember().dbAddress());
if (!sendData(&request, realServerAddress())) {
return false;
};
return true;
}
bool SingleClient::connectToServer() {
if (getStatus() >= ClientStatus::Connected) {
QuasarAppUtils::Params::log(" This client alredy connected to server.",
QuasarAppUtils::Warning);
return true;
}
if (getStatus() < ClientStatus::Connecting) {
setStatus(ClientStatus::Connecting);
}
auto address = serverAddress();
DataBaseNode::addNode(address.first, address.second);
return true;
}
void SingleClient::disconnectFromServer() {
if (getStatus() == ClientStatus::Dissconnected) {
return;
}
DataBaseNode::removeNode(realServerAddress());
}
void SingleClient::setStatus(const ClientStatus &status) {
if (status == _status)
return;
auto oldStatus = _status;
if (status == ClientStatus::Connecting || status == ClientStatus::Loginning) {
QTimer::singleShot(WAIT_RESPOCE_TIME, this, [this, oldStatus]() {
if (_status == ClientStatus::Connecting || _status == ClientStatus::Loginning) {
setStatus(oldStatus);
emit requestError(static_cast<unsigned char >(ErrorCodes::TimeOutError),
ErrorCodes::DBErrorCodesHelper::toString(ErrorCodes::TimeOutError));
}
});
}
_status = status;
emit statusChanged(_status);
}
void SingleClient::handleError(unsigned char code, QString error) {
QuasarAppUtils::Params::log(error, QuasarAppUtils::Error);
if (code != ErrorCodes::NoError && getStatus() == ClientStatus::Loginning) {
setStatus(ClientStatus::Connected);
}
_lastError = code;
}
bool SingleClient::p_login(const QString &userId, const QByteArray &hashPassword) {
const auto &userMember = getMember();
if ((userId.isEmpty() || hashPassword.isEmpty()) && !userMember.isValid()) {
return false;
}
QH::PKG::AuthRequest request;
if (userId.isEmpty())
request.setId(userMember.getId());
else
request.setId(userId);
request.setRequest(QH::PKG::UserRequestType::LogIn);
if (hashPassword.isEmpty()) {
if (!userMember.getSignToken().isValid()) {
return false;
}
request.setSignToken(userMember.getSignToken());
} else {
request.setAuthenticationData(hashPassword);
}
return sendData(&request, realServerAddress());
}
bool SingleClient::p_signup(const QString &userId, const QByteArray &hashPassword) {
QH::PKG::AuthRequest request;
request.setId(userId);
request.setAuthenticationData(hashPassword);
request.setRequest(QH::PKG::UserRequestType::SignUp);
return sendData(&request, realServerAddress());
}
void SingleClient::handleRestRequest(const QSharedPointer<PKG::AbstractData> &pkg,
const Header& pkgHeader) {
QMutexLocker lock(&_handlerCacheMutex);
if (_handlersCache.contains(pkgHeader.triggerHash)) {
auto action = _handlersCache.take(pkgHeader.triggerHash);
action(pkg);
}
}
void SingleClient::setRealServerAddress(const HostAddress &realServerAddress) {
_realServerAddress = realServerAddress;
}
void SingleClient::addToSubscribesList(unsigned int id) {
QMutexLocker lock(&_subscribesMutex);
_subscribes.insert(id);
}
void SingleClient::removeFromSubscribesList(unsigned int id) {
QMutexLocker lock(&_subscribesMutex);
_subscribes.remove(id);
}
void SingleClient::setSubscribersList(QSet<unsigned int> ids) {
QMutexLocker lock(&_subscribesMutex);
_subscribes = ids;
}
const HostAddress &SingleClient::realServerAddress() const {
return _realServerAddress;
}
void SingleClient::nodeErrorOccured(AbstractNodeInfo *nodeInfo,
QAbstractSocket::SocketError errorCode,
QString errorString) {
setStatus(ClientStatus::Dissconnected);
SingleBase::nodeErrorOccured(nodeInfo, errorCode, errorString);
}
const PKG::UserMember &SingleClient::getMember() const {
return _member;
}
QPair<QString, unsigned short> SingleClient::serverAddress() const {
return {"localhost", DEFAULT_PORT};
}
void SingleClient::nodeConfirmend(AbstractNodeInfo *node) {
Q_UNUSED(node)
}
void QH::SingleClient::nodeConnected(AbstractNodeInfo *node) {
debug_assert(!realServerAddress().isValid(),
"Internal Error detected in "
"the QH::SingleClient::nodeConnected(AbstractNodeInfo *node) method"
" If you see this error message"
" please send your bug report to the official github page"
" https://github.com/QuasarApp/Heart/issues/new" );
setRealServerAddress(node->networkAddress());
setStatus(ClientStatus::Connected);
}
void QH::SingleClient::nodeDisconnected(AbstractNodeInfo *node) {
Q_UNUSED(node)
setRealServerAddress(HostAddress{});
setStatus(ClientStatus::Dissconnected);
}
unsigned int SingleClient::sendData(const PKG::AbstractData *resp,
const HostAddress &address,
const Header *req) {
return DataBaseNode::sendData(resp, address, req);
}
unsigned int SingleClient::sendData(const PKG::AbstractData *resp,
const AbstractNodeInfo *node,
const Header *req) {
return DataBaseNode::sendData(resp, node, req);
}
unsigned int SingleClient::sendData(const PKG::AbstractData *resp,
const QVariant &nodeId,
const Header *req) {
return DataBaseNode::sendData(resp, nodeId, req);
}
unsigned int SingleClient::sendData(PKG::AbstractData *resp,
const HostAddress &address,
const Header *req) {
if (!signPackageWithToken(resp)) {
return 0;
}
return DataBaseNode::sendData(resp, address, req);
}
unsigned int SingleClient::sendData(PKG::AbstractData *resp,
const AbstractNodeInfo *node,
const Header *req) {
if (!signPackageWithToken(resp)) {
return 0;
}
return DataBaseNode::sendData(resp, node, req);
}
unsigned int SingleClient::sendData(PKG::AbstractData *resp,
const QVariant &nodeId,
const Header *req) {
if (!signPackageWithToken(resp)) {
return 0;
}
return DataBaseNode::sendData(resp, nodeId, req);
}
void SingleClient::resetUser() {
setMember({});
if (getStatus() > ClientStatus::Connected)
setStatus(ClientStatus::Connected);
}
void SingleClient::setMember(const PKG::UserMember &member) {
QMutexLocker lock (&_handlerMemberMutex);
_member = member;
}
ErrorCodes::Code SingleClient::getLastError() const {
return _lastError;
}
ErrorCodes::Code SingleClient::takeLastError() {
auto result = _lastError;
setLastError(ErrorCodes::NoError);
return result;
}
QString SingleClient::getLastErrorString() const {
return ErrorCodes::DBErrorCodesHelper::toString(_lastError);
}
bool SingleClient::isConnected() const {
return getStatus() >= ClientStatus::Connected;
}
bool SingleClient::isLogined() const {
return getStatus() >= ClientStatus::Logined;
}
bool SingleClient::subscribe(unsigned int id) {
if (getStatus() < ClientStatus::Logined) {
return false;
}
PKG::WebSocket request;
request.setSubscribeId(id);
request.setRequestCommnad(PKG::WebSocketRequest::Subscribe);
if (!sendData(&request, realServerAddress())) {
return false;
}
addToSubscribesList(id);
return true;
}
bool SingleClient::unsubscribe(unsigned int id) {
if (getStatus() < ClientStatus::Logined) {
return false;
}
PKG::WebSocket request;
request.setSubscribeId(id);
request.setRequestCommnad(PKG::WebSocketRequest::Unsubscribe);
if (!sendData(&request, realServerAddress())) {
return false;
}
removeFromSubscribesList(id);
return true;
}
QSet<unsigned int> SingleClient::subscribesList() const {
QMutexLocker lock(&_subscribesMutex);
return _subscribes;
}
bool SingleClient::isSubscribed(unsigned int subscribeId) const {
QMutexLocker lock(&_subscribesMutex);
return _subscribes.contains(subscribeId);
}
bool SingleClient::syncSybscribeListWithServer(const std::function<void(const QSet<unsigned int> &)> &cb) {
QMutexLocker lock(&_subscribesMutex);
PKG::WebSocket request;
request.setRequestCommnad(PKG::WebSocketRequest::SubscribeList);
auto handler = [cb, this](const QSharedPointer<const PKG::AbstractData> & result){
auto subscribes = static_cast<const PKG::WebSocketSubscriptions*>(result.data());
setSubscribersList(subscribes->addresses());
cb(_subscribes);
};
return restRequest(&request, handler);
}
bool SingleClient::signPackageWithToken(PKG::AbstractData *pkg) const {
auto tokenObject = dynamic_cast<IToken*>(pkg);
if (!tokenObject) {
return true;
}
auto token = getMember().getSignToken();
if (!token.isValid())
return false;
tokenObject->setSignToken(token);
return true;
}
bool SingleClient::restRequest(PKG::AbstractData *req,
const HandlerMethod &handler) {
if (!signPackageWithToken(req)) {
QuasarAppUtils::Params::log("Fail to sign package with token", QuasarAppUtils::Error);
return false;
}
unsigned int pkgHash = sendData(req, realServerAddress());
if (!pkgHash)
return false;
QMutexLocker lock(&_handlerCacheMutex);
_handlersCache[pkgHash] = handler;
QTimer::singleShot(WAIT_RESPOCE_TIME, this, [this, pkgHash]() {
QMutexLocker lock(&_handlerCacheMutex);
_handlersCache.remove(pkgHash);
});
return true;
}
void SingleClient::setLastError(const ErrorCodes::Code &lastError) {
_lastError = lastError;
}
}

@ -1,409 +0,0 @@
/*
* Copyright (C) 2018-2020 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#ifndef SINGLECLIENT_H
#define SINGLECLIENT_H
#include <usermember.h>
#include "dberrorcodes.h"
#include "singlebase.h"
namespace QH {
/**
* @brief The ClientStatus enum contains network statuses of the client.
*/
enum class ClientStatus: unsigned char {
/// The Client is offline and do not tried connecting to server. (offline mode)
Dissconnected,
/// The Client is offline but the connectToServer method has been invoked.
/// This is mode of wait to connecting .
Connecting,
/// The Client successfully connected to server.
/// This is Online mode. In This mode client is ready to work with server but in read only mode.
Connected,
/// The Client successfully connected to server and the login method has been invoked.
/// This is mode of wait of logging.
Loginning,
/// The client successfully Loggined and ready to work with server.
Logined
};
/**
* @brief The SingleClient class This class provide login and singup user functionality for the SingleServer class.
*
* @note All pacakges that will be processed in this class should be sopport the token validation.
* For get more information about token validation see the IToken class.
*
* @note The client have next syntetic limitation:
* 1. Maximum connection count = 1
* 2. Connect possible only for one server overridden in the serverAddress method.
* 3. addNode and removeNode methods unavalable in the client node.
*
*
*/
class HEARTSHARED_EXPORT SingleClient: public SingleBase
{
Q_OBJECT
public:
typedef std::function<void (const QSharedPointer<const PKG::AbstractData> &)> HandlerMethod;
typedef QHash<unsigned int, HandlerMethod> HandlersCache;
SingleClient();
bool addNode(const HostAddress& address) = delete;
bool addNode(const QString& address, unsigned short) = delete;
bool removeNode(const HostAddress& address) = delete;
QH::ParserResult parsePackage(const QSharedPointer<PKG::AbstractData> &pkg,
const Header& pkgHeader,
const AbstractNodeInfo* sender) override;
/**
* @brief getStatus This method return current status of the client.
* For get more information see the ClientStatus enum.
* @return status of the client.
*/
ClientStatus getStatus() const;
/**
* @brief login This method try to loggin client.
* @param userId This is userID. In The base implementation it is String value.
* The userId must be unique for all users.
* If You want you can use the email address of the user as a user id.
* If you want login uses your local user data just sets userId is empty. This method try login uses data from the getMember method.
* @param rawPassword This is raw passwork of the userId. This method calc hash from the rawPassword and send getting value to server. For calculated hash uses the hashgenerator method. If you want to override own behavior for hashing or add an own salt then you need to override the hashgenerator method.
* @return true if the user send authorization request successful.
*/
bool login(const QString &userId = {}, const QString &rawPassword = {});
/**
* @brief login This method try to login client with new memberData by token.
* @param memberData This is new member data, the client try login.
* @return true if the user send authorization request successful.
*/
bool login(const PKG::UserMember& memberData);
/**
* @brief logout This method send to server request for logout.
* @return true if the user send logout request successful.
*/
bool logout();
/**
* @brief signup This method try to register new user.
* @param userId This is userID. In The base implementation it is String value.
* The userId must be unique for all users.
* If You want you can use the email address of the user as a user id.
* @param rawPassword This is raw passwork of the userId.
* This method calc hash from the rawPassword and send getting value to server.
* For calculated hash uses the hashgenerator method.
* If you want to override own behavior for hashing or add an own salt then you need to override the hashgenerator method.
* @return true if the user send registration request successful.
*/
bool signup(const QString &userId, const QString &rawPassword);
/**
* @brief removeUser This method send to server the remove user and user data request.
* @return true if the user send remove request successful.
*/
bool removeUser();
/**
* @brief connectToServer This method try connect client or server.
* @return true if the connect request send successful.
*/
bool connectToServer();
/**
* @brief disconnectFromServer This method disconnect the client from server.
*/
void disconnectFromServer();
/**
* @brief getLastError return last error code.
* @return last error code.
*/
ErrorCodes::Code getLastError() const;
/**
* @brief takeLastError This method take last erro code. after call this object sets no error to last error.
* @return LastError code.
*/
ErrorCodes::Code takeLastError();
/**
* @brief getLastErrorString This method return the string implementation of a last code error.
* @return string value of the last error.
*/
QString getLastErrorString() const;
/**
* @brief isConnected This method return true if the client is connected to server.
* @return true if the server has "Connected" status.
*/
bool isConnected() const;
/**
* @brief isLogined This method return true if the client is logged.
* @return true if the server has "Logged" status.
*/
bool isLogined() const;
/**
* @brief subscribe This method subscribe current logged user to the object with @a id.
* @param id This is subscriber id of the object.
* @return true if subscribe request sent successful.
* \sa { syncSybscribeListWithServer, unsubscribe, isSubscribed, subscribesList }
*/
bool subscribe(unsigned int id);
/**
* @brief unsubscribe This method unsubscribe current logged user to the object with @a id.
* @param id This is unsubscribe id of the object.
* @return true if unsubscribe request sent successful.
* \sa { syncSybscribeListWithServer, subscribe, isSubscribed, subscribesList }
*/
bool unsubscribe(unsigned int id);
/**
* @brief subscribesList This method returns local reference to local list with subsribes.
* @warning This list updated when invoked subscribe and unsubscribe methods, so if your client have a unstable network connectin this value may be wrong.
* @return lvalue to a subscrubes ids list.]
*
* @note This method is thread safe, so if you want check is subscribe only then use the SingleClient::isSubscribed method.
* \sa { syncSybscribeListWithServer, subscribe, isSubscribed, unsubscribe }
*/
QSet<unsigned int> subscribesList() const;
/**
* @brief isSubscribed This method check object with @a subscribeId to isSubscribed.
* @warning This method use the local subscribed list, so it is may be works wrong if your client have a unstable network connection this value may be wrong.
* @return true if the your client subscribed to subscribeId.
* \sa { unsubscribe, subscribe, syncSybscribeListWithServer, subscribesList }
*/
bool isSubscribed(unsigned int subscribeId) const;
/**
* @brief syncSybscribeListWithServer This method sends to server rest request to get subscribers list.
* @param cb This is call back functions with a new subcribes list.
* @return true if the reqest sendet successful.
* \sa { unsubscribe, subscribe, isSubscribed }
*/
bool syncSybscribeListWithServer(const std::function<void (const QSet<unsigned int>&)> &cb = {});
/**
* @brief restRequest This method send to server rest request and if the server send response invoke a handler method.
* @param req This is request object. This maybe any objects from the PKH name space.
* @param handler This is lambda function. This function invoked when client receive from server response of the sent request.
* @return True if the request sent successfull.
*
* @b Example
* @code{cpp}
* auto cb = [](const QSharedPointer<PKG::AbstractData> &pkg) {
* ...
*
* };
*
* MyDataRequest request;
request.setId(userId);
*
* restRequest()
* @endcode
*/
bool restRequest(PKG::AbstractData *req, const HandlerMethod& handler);
/**
* @brief sendData This method is wraper of default sendData method but add sign to sendet pacakge.
* @param resp This is pointer to sendet object.
* @param address This is target addres for sending.
* @param req This is header of request.
* @return hash of the sendet package. If function is failed then return 0.
*/
unsigned int sendData(const PKG::AbstractData *resp,
const HostAddress &address,
const Header *req = nullptr) override;
/**
* @brief sendData This method is wraper of default sendData method but add sign to sendet pacakge.
* @param resp This is pointer to sendet object.
* @param address This is target addres for sending.
* @param req This is header of request.
* @return hash of the sendet package. If function is failed then return 0.
*/
unsigned int sendData(const PKG::AbstractData *resp,
const AbstractNodeInfo *node,
const Header *req = nullptr) override;
/**
* @brief sendData This method is wraper of default sendData method but add sign to sendet pacakge.
* @param resp This is sending object to the nodeId.
* @param nodeId This is id of target node.
* @param req This is header of request.
* @return true if a data send successful.
*/
unsigned int sendData(const PKG::AbstractData *resp,
const QVariant &nodeId,
const Header *req = nullptr) override;
/**
* @brief sendData This method is wraper of default sendData method but add sign to sendet pacakge.
* @param resp This is pointer to sendet object.
* @param address This is target addres for sending.
* @param req This is header of request.
* @return hash of the sendet package. If function is failed then return 0.
*/
virtual unsigned int sendData(PKG::AbstractData *resp,
const HostAddress &address,
const Header *req = nullptr);
/**
* @brief sendData This method is wraper of default sendData method but add sign to sendet pacakge.
* @param resp This is pointer to sendet object.
* @param address This is target addres for sending.
* @param req This is header of request.
* @return hash of the sendet package. If function is failed then return 0.
*/
virtual unsigned int sendData(PKG::AbstractData *resp,
const AbstractNodeInfo *node,
const Header *req = nullptr);
/**
* @brief sendData This method is wraper of default sendData method but add sign to sendet pacakge.
* @param resp This is sending object to the nodeId.
* @param nodeId This is id of target node.
* @param req This is header of request.
* @return true if a data send successful.
*/
virtual unsigned int sendData(PKG::AbstractData *resp,
const QVariant &nodeId,
const Header *req = nullptr);
signals:
/**
* @brief statusChanged This signal emitted when the client change an own status.
* @param status This is new status of the client.
* For more information about the statuses see the ClientStatus enum.
*/
void statusChanged(QH::ClientStatus status);
/**
* @brief currentUserChanged This method invoked when user is logged and receive new token from server.
* handle this signal if you want to save token in to database.
*/
void currentUserChanged();
protected:
/**
* @brief setStatus This method sets a new status of the client. This method will be emitted the statusChanged signal.
* @param status This is new status of the client.
* @note The ClientStatus::Loginning and ClientStatus::Connecting statuses create a singleshot timer for check if the server response times out.
*/
void setStatus(const ClientStatus &status);
/**
* @brief getMember This method return the UserMember object of logged user.
* @return UserMember object.
*/
const PKG::UserMember &getMember() const;
/**
* @brief setLastError This method sets new error code.
* @param lastError This is new error code.
*/
void setLastError(const ErrorCodes::Code &lastError);
/**
* @brief serverAddress This method return the pair {ip/domain,port} of server.
* Override this method for change server address.
* Default implementation return the localhost address with the 3090 port.
* @return host of the server.
*/
virtual QPair<QString, unsigned short> serverAddress() const;
/**
* @brief signPackageWithToken This method insert token into sending package. The package @a pkg should be inherited of the IToken interface. IF @a pkg do not have a Itoken parent then this method ignore this validation and return true.
* @param pkg This is pointer to the package object.
* @note The @a pkg object will be changed after invoke this method.
* @return true if the package get a token successful or package not support token validation else false.
*/
bool signPackageWithToken(PKG::AbstractData *pkg) const;
/**
* @brief resetUser This method remove user member data and sets new status for this node (client).
* If user alredy loggined then status will be changed to connected.
*/
void resetUser();
void nodeConfirmend(AbstractNodeInfo *node) override;
void nodeConnected(AbstractNodeInfo *node) override;
void nodeDisconnected(AbstractNodeInfo *node) override;
/**
* @brief realServerAddress This method return the real server address that connected with this node.
* @return The real server address that connected with this node.
*/
const HostAddress& realServerAddress() const;
protected slots:
void nodeErrorOccured(QH::AbstractNodeInfo *nodeInfo,
QAbstractSocket::SocketError errorCode,
QString errorString) override;
private slots:
/**
* @brief handleError This handle method invoked when the client received the BadRequest from server.
* Override this method for add actions for this event.
* @param code This is number of the error code.
* @param error This is test message from a server.
*/
void handleError(unsigned char code, QString error);
// AbstractNode interface
private:
/**
* @brief setMember This method sets member data. Use this method if you restore your account data from the local storage.
* @param member This is new network member data.
*/
void setMember(const PKG::UserMember &member);
bool p_login(const QString &userId, const QByteArray &hashPassword = {});
bool p_signup(const QString &userId, const QByteArray &hashPassword);
void handleRestRequest(const QSharedPointer<PKG::AbstractData> &pkg, const Header &pkgHeader);
void setRealServerAddress(const HostAddress &realServerAddress);
void addToSubscribesList(unsigned int id);
void removeFromSubscribesList(unsigned int id);
void setSubscribersList(QSet<unsigned int> ids);
mutable QMutex _subscribesMutex;
QSet<unsigned int> _subscribes;
ClientStatus _status = ClientStatus::Dissconnected;
QMutex _handlerMemberMutex;
PKG::UserMember _member;
ErrorCodes::Code _lastError = ErrorCodes::NoError;
QMutex _handlerCacheMutex;
HandlersCache _handlersCache;
HostAddress _realServerAddress;
};
}
Q_DECLARE_METATYPE(QH::ClientStatus)
#endif // SINGLECLIENT_H

@ -1,298 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#include "itoken.h"
#include "singleserver.h"
#include <authrequest.h>
#include <sqldbcache.h>
#include <basenodeinfo.h>
#include <badrequest.h>
#include <getmaxintegerid.h>
#include <singleserverdb.h>
#include "deleteobject.h"
#include "getsinglevalue.h"
#include "isqldbcache.h"
namespace QH {
SingleServer::SingleServer()
{
registerPackageType<QH::PKG::AuthRequest>();
}
ErrorCodes::Code SingleServer::registerNewUser(PKG::UserMember user,
const AbstractNodeInfo *info) {
auto sdb = dynamic_cast<SingleServerDB*>(db());
if (!sdb) {
return ErrorCodes::InternalError;
}
auto rawDb = sdb->rawDb();
if (!rawDb) {
return ErrorCodes::InternalError;
}
auto localObject = rawDb->getObject(user);
if (localObject) {
return ErrorCodes::UserExits;
}
auto rawPassword = user.authenticationData();
user.setAuthenticationData(hashgenerator(rawPassword));
if (!rawDb->insertObject(QSharedPointer<decltype(user)>::create(user), true)) {
return ErrorCodes::InternalError;
};
user.setAuthenticationData(rawPassword);
// get id of the user
sdb->addUpdatePermission(user.getId(), user.dbAddress(), Permission::Write);
return loginUser(user, info);
}
// To-Do fix me bug #12 https://github.com/QuasarApp/Heart/issues/12
ErrorCodes::Code SingleServer::loginUser(const PKG::UserMember &user,
const AbstractNodeInfo *info) {
auto sdb = dynamic_cast<SingleServerDB*>(db());
if (!sdb) {
return ErrorCodes::InternalError;
}
auto rawDb = sdb->rawDb();
if (!rawDb) {
return ErrorCodes::InternalError;
}
QSharedPointer<PKG::UserMember> localObject = rawDb->getObject<PKG::UserMember>(user);
if (!localObject) {
return ErrorCodes::UserNotExits;
}
auto nodeinfo = dynamic_cast<const BaseNodeInfo*>(info);
if (!nodeinfo)
return ErrorCodes::InternalError;
if (!(user.getSignToken().isValid() && localObject->getSignToken() == user.getSignToken())) {
if (localObject->authenticationData() != hashgenerator(user.authenticationData())) {
return ErrorCodes::UserInvalidPasswoed;
}
}
auto editableNodeInfo = static_cast<BaseNodeInfo*>(getInfoPtr(info->networkAddress()));
if (!editableNodeInfo)
return ErrorCodes::InternalError;
if (!localObject->getSignToken().isValid()) {
localObject->setSignToken(generateToken(AccessToken::Year));
if (!rawDb->updateObject(localObject, true)) {
return ErrorCodes::InternalError;
}
}
editableNodeInfo->setToken(localObject->getSignToken());
editableNodeInfo->setId(localObject->getId());
localObject->setAuthenticationData("");
if (!sendData(localObject.data(), info->networkAddress())) {
return ErrorCodes::InternalError;
};
return ErrorCodes::NoError;
}
ErrorCodes::Code SingleServer::logOutUser(const PKG::UserMember &user,
const AbstractNodeInfo *info) {
auto sdb = dynamic_cast<SingleServerDB*>(db());
if (!sdb) {
return ErrorCodes::InternalError;
}
auto rawDb = sdb->rawDb();
if (!rawDb) {
return ErrorCodes::InternalError;
}
auto localObject = rawDb->getObject(user);
if (!localObject) {
return ErrorCodes::UserNotExits;
}
auto nodeinfo = dynamic_cast<const BaseNodeInfo*>(info);
if (!nodeinfo)
return ErrorCodes::InternalError;
AccessToken token((nodeinfo->token().toBytes()));
if (!token.isValid()) {
return ErrorCodes::UserNotLogged;
}
if (user.getSignToken() != token) {
return ErrorCodes::UserNotLogged;
}
auto mutableNodeInfo = dynamic_cast<BaseNodeInfo*>(getInfoPtr(info->networkAddress()));
if (!mutableNodeInfo)
return ErrorCodes::InternalError;
mutableNodeInfo->setToken(AccessToken{});
mutableNodeInfo->setId({});
return ErrorCodes::NoError;
}
bool SingleServer::signValidation(const PKG::AbstractData *data, const AbstractNodeInfo *sender) const {
auto iToken = dynamic_cast<const IToken*>(data);
auto senderInfo = dynamic_cast<const BaseNodeInfo*>(sender);
if (!(iToken && senderInfo ))
return false;
return iToken->getSignToken() == senderInfo->token();
}
AccessToken SingleServer::generateToken(int length) {
return AccessToken(length);
}
ParserResult SingleServer::parsePackage(const QSharedPointer<PKG::AbstractData> &pkg,
const Header &pkgHeader,
const AbstractNodeInfo *sender) {
auto parentResult = DataBaseNode::parsePackage(pkg, pkgHeader, sender);
if (parentResult != QH::ParserResult::NotProcessed) {
return parentResult;
}
if (QH::PKG::AuthRequest::command() == pkg->cmd()) {
auto obj = pkg.staticCast<QH::PKG::AuthRequest>();
if (!obj->isValid()) {
prepareAndSendBadRequest(sender->networkAddress(), pkgHeader,
ErrorCodes::InvalidRequest, REQUEST_ERROR);
return ParserResult::Error;
}
if (!workWithUserRequest(obj, pkgHeader, sender)) {
return QH::ParserResult::Error;
}
return QH::ParserResult::Processed;
}
if (!signValidation(pkg.data(), sender)) {
prepareAndSendBadRequest(sender->networkAddress(), pkgHeader,
ErrorCodes::OperatioForbiden, REQUEST_ERROR);
QuasarAppUtils::Params::log("For The SingleServerClient classes you must be add"
" support of the Token validation."
" All package classes must be inherited"
" of the IToken interface",
QuasarAppUtils::Error);
return ParserResult::Error;
};
if (PKG::DeleteObject::command() == pkg->cmd()) {
auto obj = pkg.staticCast<PKG::DeleteObject>();
auto requesterId = getSender(sender, obj.data());
if (deleteObject(requesterId, obj) == DBOperationResult::Forbidden) {
badRequest(sender->networkAddress(), pkgHeader, {
ErrorCodes::OperatioForbiden,
"Permision denied"
});
return ParserResult::Error;
}
return QH::ParserResult::Processed;
}
return QH::ParserResult::NotProcessed;
}
QByteArray SingleServer::hashgenerator(const QByteArray &data) const {
return DataBaseNode::hashgenerator(data + "singelserversoult");
}
bool SingleServer::workWithUserRequest(const QSharedPointer<PKG::UserMember>& obj,
const Header &hdr,
const AbstractNodeInfo *sender) {
ErrorCodes::Code result = ErrorCodes::InternalError;
auto request = obj.dynamicCast<Request>();
if (!request) {
return false;
}
if (request->getRequestCmd() == static_cast<quint8>(PKG::UserRequestType::LogIn)) {
result = loginUser(*obj, sender);
} else if (request->getRequestCmd() == static_cast<quint8>(PKG::UserRequestType::SignUp)) {
result = registerNewUser(*obj, sender);
} else if (request->getRequestCmd() == static_cast<quint8>(PKG::UserRequestType::LogOut)) {
result = logOutUser(*obj, sender);
}
if (result == ErrorCodes::InternalError) {
QuasarAppUtils::Params::log("Internal error ocured in the loginUser or registerNewUser method.",
QuasarAppUtils::Error);
prepareAndSendBadRequest(sender->networkAddress(), hdr,
result, REQUEST_INTERNAL_ERROR);
return false;
}
if (result != ErrorCodes::NoError) {
prepareAndSendBadRequest(sender->networkAddress(), hdr,
result, REQUEST_INTERNAL_ERROR);
}
return true;
}
void SingleServer::prepareAndSendBadRequest(const HostAddress& address,
const Header& lastHeader,
unsigned char error,
int punishment) {
badRequest(address, lastHeader,
{
error,
ErrorCodes::DBErrorCodesHelper::toString(error)
},
punishment);
}
bool SingleServer::initDatabase() {
setDb(new SingleServerDB);
return true;
}
}

@ -1,124 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#ifndef SINGLESERVER_H
#define SINGLESERVER_H
#include <accesstoken.h>
#include "dberrorcodes.h"
#include "singlebase.h"
namespace QH {
namespace PKG {
class AuthRequest;
class UserMember;
}
#define REQUEST_INTERNAL_ERROR 0
#define REQUEST_LOGIN_ERROR -1
/**
* @brief The SingleServer class This class is classic server with support all base server functions.
* classic server support:
* - ssl encryption (See the SslMode enum).
* - multitrading working.
* - user registration (See The PKG::User class).
* - working with dabase (See the DBObject class).
*
* Examples
*
* \code{cpp}
* \endcode
*
* @note All packges that will be processed in this class should be support the token validation.
* For get more information about token validation see the IToken class.
*
*/
class HEARTSHARED_EXPORT SingleServer : public SingleBase
{
Q_OBJECT
public:
SingleServer();
// AbstractNode interface
protected:
/**
* @brief registerNewUser This method add record into database about new user. After registered this method invoke the SingleServer::loginUser method.
* @param user This is data of new user.
* @param info This is info about requested client.
* @return status of registration a new user. For more information about result statuses see the UserOperationResult enum.
*
* @note This method send userData with new token to the client.
*/
virtual ErrorCodes::Code registerNewUser(PKG::UserMember user,
const AbstractNodeInfo* info);
/**
* @brief loginUser This method generate the token for a requested user.
* @param user This is user data with name and password.
* For login use PKG::User::getID and PKG::User::authenticationData like userName and password hash.
* @param info This is info about requested client.
* @return status of login a user. For more information about result statuses see the UserOperationResult enum.
*
* @note This method send userData with new token to the client.
*/
virtual ErrorCodes::Code loginUser(const PKG::UserMember &user, const AbstractNodeInfo* info);
/**
* @brief logOutUser This method remove the generated accesses token from server.
* @param user This is network member data (user data)
* @param info This is info about requested client.
* @return status of operation. For more information about result statuses see the UserOperationResult enum.
*/
virtual ErrorCodes::Code logOutUser(const PKG::UserMember &user, const AbstractNodeInfo* info);
/**
* @brief signValidation This method return true if the package of the user have a token and it token is valid.
* Except is login request. User must be send own login and hash password.
* @param data This is validation package data.
* @param sender This is package sender node information.
* @return true if the token is valid.
*/
virtual bool signValidation(const PKG::AbstractData* data, const AbstractNodeInfo *sender) const;
/**
* @brief generateToken This method generate a new token.
* @param duration This is duration of valid.
* @return A new token.
*/
AccessToken generateToken(int duration = AccessToken::Day);
ParserResult parsePackage(const QSharedPointer<PKG::AbstractData> &pkg,
const Header& pkgHeader,
const AbstractNodeInfo* sender) override;
QByteArray hashgenerator(const QByteArray &data) const override;
bool initDatabase() override;
private:
bool workWithUserRequest(const QSharedPointer<PKG::UserMember> &obj,
const Header &pkg,
const AbstractNodeInfo *sender);
void prepareAndSendBadRequest(const HostAddress& address,
const Header& lastHeader,
unsigned char error,
int punishment);
};
}
#endif // SINGLESERVER_H

@ -9,7 +9,7 @@
namespace QH {
SqlDB::SqlDB():
ISqlDBCache(0, SqlDBCasheWriteMode::Force) {
ISqlDB(0, SqlDBCasheWriteMode::Force) {
}
void SqlDB::deleteFromCache(const QSharedPointer<PKG::DBObject> &delObj) {

@ -7,7 +7,7 @@
#ifndef SQLDB_H
#define SQLDB_H
#include "isqldbcache.h"
#include "isqldb.h"
namespace QH {
@ -15,7 +15,7 @@ namespace QH {
* @brief The SqlDB class This is base implementation fo datatbase.
* The SqlDB do not use caches, all request run on the sqlwtiter class.
*/
class HEARTSHARED_EXPORT SqlDB final: public ISqlDBCache {
class HEARTSHARED_EXPORT SqlDB final: public ISqlDB {
Q_OBJECT
public:
SqlDB();

@ -1,112 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#ifdef HEART_DB_CACHE
#include "sqldbcache.h"
#include "quasarapp.h"
#include "sqldbwriter.h"
#include "dbaddresskey.h"
#include "permisiondata.h"
#include <dbobject.h>
#include <asyncsqldbwriter.h>
#include <QDateTime>
#include <QtConcurrent/QtConcurrent>
namespace QH {
using namespace PKG;
QSharedPointer<DBObject> SqlDBCache::getFromCacheById(quint32 dbKey) {
QMutexLocker locker(&_cacheMutex);
return _cache.value(dbKey, nullptr);
}
SqlDBCache::SqlDBCache(qint64 updateInterval):
ISqlDBCache(updateInterval, SqlDBCasheWriteMode::Force) {
}
SqlDBCache::~SqlDBCache() {
}
void SqlDBCache::deleteFromCache(const QSharedPointer<DBObject>& delObj) {
if (!delObj)
return;
_cacheMutex.lock();
_cache.remove(delObj->dbKey());
_cacheMutex.unlock();
}
bool SqlDBCache::insertToCache(const QSharedPointer<DBObject>& obj) {
if (!obj || !obj->isCached())
return false;
// obj must be have valid id of save into cache
if (!obj->getId().isValid())
return false;
QMutexLocker lock(&_cacheMutex);
if (_cache.contains(obj->dbKey())) {
return false;
}
_cache[obj->dbKey()] = obj->clone();
return true;
}
bool SqlDBCache::updateCache(const QSharedPointer<DBObject>& obj) {
if (!obj || !obj->isCached())
return false;
QMutexLocker lock(&_cacheMutex);
auto existsObject = _cache.value(obj->dbKey(), nullptr);
if (!existsObject) {
return false;
}
if (existsObject->cmd() != obj->cmd()) {
_cache[obj->dbKey()] = obj->clone();
} else {
if (!existsObject->copyFrom(obj.data())) {
return false;
}
}
return true;
}
QList<QSharedPointer<DBObject> >
SqlDBCache::getFromCache(const DBObject *obj) {
using resultType = QList<QSharedPointer<QH::PKG::DBObject>>;
if (obj->getId().isValid()) {
auto result = getFromCacheById(obj->dbKey());
if (!result)
return resultType{};
return resultType{result};
}
return resultType{};
}
}
#endif

@ -1,55 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#ifdef HEART_DB_CACHE
#ifndef SQLDBCASHE_H
#define SQLDBCASHE_H
#include "iobjectprovider.h"
#include "isqldbcache.h"
namespace QH {
/**
* @brief The SqlDBCache class is universal implementation of the database cache.
* This implementation have a one hashMap for the database object.
* This is work for all Databases types but some objects like a DBObjectSet or DBObjectsRequest class not supported because this is set objects.
* @note This cache works only for select queries. Uses SqlDBCasheWriteMode::Force mode For more information about modes see the SqlDBCasheWriteMode enum class.
*/
class HEARTSHARED_EXPORT SqlDBCache final: public ISqlDBCache
{
Q_OBJECT
public:
SqlDBCache(qint64 updateInterval = DEFAULT_UPDATE_INTERVAL);
~SqlDBCache();
// ISqlDBCache interface
protected:
void deleteFromCache(const QSharedPointer<QH::PKG::DBObject>& delObj) override;
bool insertToCache(const QSharedPointer<QH::PKG::DBObject>& obj) override;
bool updateCache(const QSharedPointer<QH::PKG::DBObject>& obj) override;
QList<QSharedPointer<QH::PKG::DBObject>>
getFromCache(const PKG::DBObject *obj) override;
private:
QSharedPointer<QH::PKG::DBObject> getFromCacheById(quint32 dbKey);
QMutex _saveLaterMutex;
QMutex _cacheMutex;
QHash<uint, QSharedPointer<PKG::DBObject>> _cache;
QHash<PKG::MemberType, QSharedPointer<QH::PKG::DBObject>> _changes;
};
}
#endif // SQLDBCASHE_H
#endif

@ -1,112 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#include "databasenode.h"
#include "abstractnodeinfo.h"
#include "websocketcontroller.h"
#include <quasarapp.h>
#include <permission.h>
namespace QH {
using namespace PKG;
WebSocketController::WebSocketController(DataBaseNode *node) {
_node = node;
assert(_node);
}
void WebSocketController::subscribe(const QString &subscriber,
unsigned int item) {
_subscribsMutex.lock();
_itemsMutex.lock();
subscribePrivate(subscriber, item);
_itemsMutex.unlock();
_subscribsMutex.unlock();
}
void WebSocketController::unsubscribe(const QString &subscriber,
unsigned int item) {
_subscribsMutex.lock();
_itemsMutex.lock();
unsubscribePrivate(subscriber, item);
_itemsMutex.unlock();
_subscribsMutex.unlock();
}
QSet<unsigned int> WebSocketController::list(const QString &subscriber) {
QMutexLocker locker(&_itemsMutex);
return _items[subscriber];
}
void WebSocketController::handleItemChanged(const QSharedPointer<ISubscribableData> &item) {
QMutexLocker locker(&_subscribsMutex);
foreachSubscribers(item, _subscribs.value(item->subscribeId()));
}
void WebSocketController::foreachSubscribers(const QSharedPointer<ISubscribableData> &item,
const QSet<QString> &subscribersList) {
for (const auto &subscriber : subscribersList) {
auto abstractItem = item.dynamicCast<AbstractData>();
if (!abstractItem) {
QuasarAppUtils::Params::log("All Subsribable objects must be child classes of the AbstractData." + subscriber,
QuasarAppUtils::Error);
unsubscribePrivate(subscriber, item->subscribeId());
}
auto dbObject = item.dynamicCast<DBObject>();
bool fAllowed = true;
if (dbObject) {
fAllowed = _node->checkPermission(subscriber, dbObject->dbAddress(), Permission::Read) ==
DBOperationResult::Allowed;
}
if (fAllowed && !_node->sendData(abstractItem.data(), subscriber)) {
QuasarAppUtils::Params::log("Send update failed for " + subscriber,
QuasarAppUtils::Warning);
unsubscribePrivate(subscriber, item->subscribeId());
}
if (!fAllowed) {
QuasarAppUtils::Params::log(QString("Internal Error. Member:%0 not have permission to object %1").
arg(subscriber, abstractItem->toString()),
QuasarAppUtils::Error);
unsubscribePrivate(subscriber, item->subscribeId());
}
}
}
void WebSocketController::unsubscribePrivate(const QString &subscriber,
unsigned int item) {
_subscribs[item].remove(subscriber);
_items[subscriber].remove(item);
}
void WebSocketController::subscribePrivate(const QString &subscriber,
unsigned int item) {
_subscribs[item].insert(subscriber);
_items[subscriber].insert(item);
}
}
uint qHash(const QVariant &variant) {
return qHash(variant.toByteArray());
}

@ -1,90 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#ifndef WEBSOCKETCONTROLLER_H
#define WEBSOCKETCONTROLLER_H
#include <QHash>
#include <QSharedPointer>
#include <dbobject.h>
#include <QMutex>
namespace QH {
class AbstractNodeInfo;
class DataBaseNode;
/**
* @brief The WebSocketController class is manage subscribe. This class contains information about users and him subscriptions.
*/
class HEARTSHARED_EXPORT WebSocketController
{
public:
/**
* @brief WebSocketController default constructor.
* @param node This is pointer to node object.
*/
WebSocketController(DataBaseNode *node);
/**
* @brief subscribe This method subscribe a subscriber to the item.
* @param subscriber This is network member that want get information about update of the item.
* @param item This is a subscribable object id.
* @return true if method finished successful.
*/
void subscribe(const QString &subscriber,
unsigned int item);
/**
* @brief unsubscribe This method unsubscribe a subscriber from the item.
* @param subscriber This is network member that want disable getting information about update of the item.
* @param item This is a subscribable object id.
* @return true if method finished successful.
*/
void unsubscribe(const QString &subscriber,
unsigned int item);
/**
* @brief list This method return a list of subscribed items of subscriber.
* @param subscriber This is network member that want get a list of own subscription.
* @return true if method finished successful.
*/
QSet<unsigned int> list(const QString& subscriber);
/**
* @brief handleItemChanged This method invoked when item on database changed.
* @param item This is changed item.
*/
void handleItemChanged(const QSharedPointer<PKG::ISubscribableData> &item);
private:
void foreachSubscribers(const QSharedPointer<PKG::ISubscribableData> &item,
const QSet<QString> &subscribersList);
void unsubscribePrivate(const QString &subscriber,
unsigned int item);
void subscribePrivate(const QString &subscriber,
unsigned int item);
/// subscribers it is nodes or clients
QHash<unsigned int, QSet<QString>> _subscribs;
QHash<QString, QSet<unsigned int>> _items;
QMutex _subscribsMutex;
QMutex _itemsMutex;
DataBaseNode *_node = nullptr;
};
}
uint qHash(const QVariant& variant);
#endif // WEBSOCKETCONTROLLER_H

@ -1,17 +0,0 @@
CREATE TABLE IF NOT EXISTS NetworkMembers (
id VARCHAR(64) PRIMARY KEY NOT NULL ,
authenticationData BLOB NOT NULL,
trust INTEGER default 0
);
CREATE TABLE IF NOT EXISTS MemberPermisions (
memberId VARCHAR(64) NOT NULL,
dbAddress BLOB NOT NULL,
lvl tinyint NOT NULL,
FOREIGN KEY(memberId) REFERENCES NetworkMembers(id)
ON UPDATE CASCADE
ON DELETE CASCADE
);
CREATE UNIQUE INDEX IF NOT EXISTS MemberPermisionsIndex ON MemberPermisions(memberId, dbAddress);

@ -1,19 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#include "consensus.h"
namespace QH {
const QStringList Consensus::Nodes = {
"QuasarApp.ddns.net"
};
const short Consensus::networkPort = 8211;
}

@ -1,34 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#ifndef CONSENSUS_H
#define CONSENSUS_H
#include "heart_global.h"
#include <QStringList>
namespace QH {
/**
* @brief The Consensus namespace - a bundle of general rules constants for behavior of nodes network.
*/
namespace Consensus {
/**
* @brief Nodes - list of main nodes of network
*/
extern const QStringList Nodes;
/**
* @brief networkPort - sync network port
*/
extern const short networkPort;
};
}
#endif // CONSENSUS_Hs

@ -1,21 +0,0 @@
#ifndef NETWORKERRORCODES_H
#define NETWORKERRORCODES_H
#include "dberrorcodes.h"
namespace QH {
namespace ErrorCodes {
/**
* @brief The AbstractEccorCodes enum This enum with dafault error codes.
*/
enum NetworkErrorCodes: unsigned char {
/// This case using for inheritance new enum classes.
NetworkErrorCodes = DBErrorCodes::DBErrorCodes,
};
}
}
#endif // NETWORKERRORCODES_H

@ -1,610 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#include "accesstoken.h"
#include "networknode.h"
#include "basenodeinfo.h"
#include "sqldbcache.h"
#include "sqldbwriter.h"
#include "websocketcontroller.h"
#include "badnoderequest.h"
#include "sign.h"
#include "asyncsqldbwriter.h"
#include "router.h"
#include <badrequest.h>
#include <quasarapp.h>
#include <transportdata.h>
#include <websocket.h>
#include <websocketsubscriptions.h>
#include <websocketcontroller.h>
#include <QCoreApplication>
#include <qsecretrsa2048.h>
#include <ping.h>
#include <keystorage.h>
#include <knowaddresses.h>
#include <longping.h>
#include <networkrequest.h>
#include <abstractnetworkmember.h>
#include <networknodeinfo.h>
#include <nodeobject.h>
#include <networkmember.h>
#include <QSharedPointer>
#include "networkerrorcodes.h"
#define THIS_NODE "this_node_key"
namespace QH {
using namespace PKG;
NetworkNode::NetworkNode(QObject *ptr):
DataBaseNode(ptr) {
_nodeKeys = new KeyStorage(new QSecretRSA2048());
_router = new Router();
}
bool NetworkNode::run(const QString &addres, unsigned short port) {
if (!DataBaseNode::run(addres, port)) {
return false;
}
_nodeKeys->initDefaultStorageLocation();
_nodeKeys->start();
return true;
}
bool NetworkNode::run(const QString &addres,
unsigned short port,
const QString &localNodeName) {
if (!DataBaseNode::run(addres, port, localNodeName)) {
return false;
}
_nodeKeys->initDefaultStorageLocation(localNodeName);
_nodeKeys->start();
return true;
}
void NetworkNode::stop() {
DataBaseNode::stop();
}
NetworkNode::~NetworkNode() {
delete _nodeKeys;
delete _router;
}
NodeId NetworkNode::nodeId() const {
auto keys = _nodeKeys->getNextPair(THIS_NODE);
return QCryptographicHash::hash(keys.publicKey(), QCryptographicHash::Sha256);
}
unsigned int NetworkNode::sendData(AbstractData *resp, const QVariant &nodeId, const Header *req) {
return sendData(resp, NodeId(nodeId), req);
}
unsigned int NetworkNode::sendData(const AbstractData *resp, const QVariant &nodeId, const Header *req) {
return sendData(resp, NodeId(nodeId), req);
}
unsigned int NetworkNode::sendData(AbstractData *resp,
const HostAddress &nodeId,
const Header *req) {
return DataBaseNode::sendData(resp, nodeId, req);
}
unsigned int NetworkNode::sendData(const AbstractData *resp,
const HostAddress &nodeId,
const Header *req) {
return DataBaseNode::sendData(resp, nodeId, req);
}
unsigned int NetworkNode::sendData(const AbstractData *resp,
const NodeId &nodeId,
const Header *req) {
auto nodes = connections();
for (auto it = nodes.begin(); it != nodes.end(); ++it) {
auto info = dynamic_cast<NetworkNodeInfo*>(it.value());
if (info && info->isKnowAddress(nodeId)) {
return sendData(resp, it.key(), req);
}
}
auto brodcast = [this, &nodes, req](const AbstractData *data) -> unsigned int {
bool result = false;
unsigned int hashCode = 0;
for (auto it = nodes.begin(); it != nodes.end(); ++it) {
hashCode = sendData(data, it.key(), req);
result += hashCode;
}
if (result) {
return hashCode;
}
return 0;
};
if (resp->cmd() != H_16<TransportData>()) {
TransportData data(address());
data.setTargetAddress(nodeId);
if (!data.setData(*resp)) {
return false;
}
data.setRoute(_router->getRoute(nodeId));
data.setSenderID(this->nodeId());
data.prepareToSend();
return brodcast(&data);
}
return brodcast(resp);
}
unsigned int NetworkNode::sendData(AbstractData *resp, const NodeId &nodeId, const Header *req) {
if (!resp || !resp->prepareToSend()) {
return false;
}
return sendData(const_cast<const AbstractData*>(resp), nodeId, req);
}
bool NetworkNode::checkSignOfRequest(const AbstractData *request) {
auto object = dynamic_cast<const Sign*>(request);
auto dbObject = dynamic_cast<const SenderData*>(request);
if (!(object && dbObject)) {
return false;
}
auto node = db()->getObject(NetworkMember{dbObject->senderID().toRaw()});
return _nodeKeys->check(_nodeKeys->concatSign(object->dataForSigned(),
object->sign()), node->authenticationData());
}
void NetworkNode::thisNode(NodeObject& res) const {
auto keys = _nodeKeys->getNextPair(THIS_NODE);
res.setAuthenticationData(keys.publicKey());
res.setTrust(0);
res.prepareToSend();
}
QSet<NodeId> NetworkNode::myKnowAddresses() const {
QSet<NodeId> res;
const auto connects = connections();
for (const AbstractNodeInfo *i : connects) {
auto info = dynamic_cast<const NetworkNodeInfo*>(i);
if (info && info->selfId().isValid()) {
res += info->selfId();
}
}
return res;
}
bool NetworkNode::welcomeAddress(AbstractNodeInfo *node) {
NodeObject self;
thisNode(self);
if (!sendData(&self, node->networkAddress())) {
return false;
}
if (connections().size()) {
auto knowAddresses = myKnowAddresses();
if (knowAddresses.size()) {
KnowAddresses addressesData;
addressesData.setKnowAddresses(knowAddresses);
if (!sendData(&addressesData, node->networkAddress())) {
return false;
}
}
}
return true;
}
void NetworkNode::nodeConnected(AbstractNodeInfo *node) {
DataBaseNode::nodeConnected(node);
}
void NetworkNode::nodeConfirmend(AbstractNodeInfo *node) {
DataBaseNode::nodeConfirmend(node);
auto nodeInfo = dynamic_cast<NetworkNodeInfo*>(node);
if (!nodeInfo) {
return;
}
_connectionsMutex.lock();
NetworkNodeInfo* oldNodeInfo = _connections.value(nodeInfo->selfId(), nullptr);
_connectionsMutex.unlock();
if (oldNodeInfo) {
removeNode(node->networkAddress());
return;
}
_connectionsMutex.lock();
_connections.insert(nodeInfo->selfId(), nodeInfo);
_connectionsMutex.unlock();
}
void NetworkNode::nodeDisconnected(AbstractNodeInfo *node) {
AbstractNode::nodeDisconnected(node);
auto nodeInfo = dynamic_cast<NetworkNodeInfo*>(node);
if (!nodeInfo) {
return;
}
_connectionsMutex.lock();
_connections.remove(nodeInfo->selfId());
_connectionsMutex.unlock();
}
void NetworkNode::incomingData(AbstractData *, const NodeId &) {}
void NetworkNode::incomingData(AbstractData *pkg, const AbstractNodeInfo *sender) {
DataBaseNode::incomingData(pkg, sender);
}
QString NetworkNode::keyStorageLocation() const {
return _nodeKeys->storageLocation();
}
ParserResult NetworkNode::parsePackage(const QSharedPointer<AbstractData> &pkg,
const Header &pkgHeader,
const AbstractNodeInfo *sender) {
auto parentResult = DataBaseNode::parsePackage(pkg, pkgHeader, sender);
if (parentResult != ParserResult::NotProcessed) {
return parentResult;
}
auto baseSender = dynamic_cast<const NetworkNodeInfo*>(sender);
if (!baseSender) {
QuasarAppUtils::Params::log("Sender is not basenode info!",
QuasarAppUtils::Error);
return ParserResult::Error;
}
if (H_16<BadNodeRequest>() == pkgHeader.command) {
auto cmd = pkg.staticCast<BadNodeRequest>();
incomingData(cmd.data(), baseSender->selfId());
emit requestError(cmd->errCode(), cmd->err());
return ParserResult::Processed;
} else if (H_16<TransportData>() == pkgHeader.command) {
auto cmd = pkg.staticCast<TransportData>();
return workWithTransportData(cmd.data(), sender, pkgHeader);
} else if (H_16<NodeObject>() == pkgHeader.command) {
auto obj = QSharedPointer<NodeObject>::create(pkg);
if (!obj->isValid()) {
badRequest(sender->networkAddress(), pkgHeader,
{
ErrorCodes::InvalidRequest,
"NodeObject request is invalid"
}
);
return ParserResult::Error;
}
if (!workWithNodeObjectData(obj, sender)) {
badRequest(obj->senderID(), pkgHeader,
{
ErrorCodes::InvalidRequest,
"NodeObject request is invalid"
}
);
return ParserResult::Error;
}
return ParserResult::Processed;
} else if (H_16<KnowAddresses>() == pkgHeader.command) {
auto obj = pkg.staticCast<KnowAddresses>();
if (!obj->isValid()) {
badRequest(sender->networkAddress(), pkgHeader,
{
ErrorCodes::InvalidRequest,
"KnowAddresses request is invalid"
}
);
return ParserResult::Error;
}
if (!workWithKnowAddresses(*obj, sender)) {
badRequest(sender->networkAddress(), pkgHeader,
{
ErrorCodes::InvalidRequest,
"KnowAddresses request is invalid"
}
);
return ParserResult::Error;
}
return ParserResult::Processed;
} else if (H_16<LongPing>() == pkgHeader.command) {
auto cmd = pkg.staticCast<LongPing>();
if (!cmd->ansver()) {
cmd->setAnsver(true);
sendData(cmd.data(), cmd->senderID(), &pkgHeader);
}
incomingData(cmd.data(), baseSender->selfId());
return ParserResult::Processed;
} else if (H_16<NetworkRequest>() == pkgHeader.command) {
auto cmd = pkg.staticCast<NetworkRequest>();
if (!cmd->isValid()) {
badRequest(baseSender->selfId(), pkgHeader,
{
ErrorCodes::InvalidRequest,
"NetworkRequest request is invalid"
}
);
return ParserResult::Error;
}
workWithNetworkRequest(cmd.data(), baseSender);
return ParserResult::Processed;
}
return ParserResult::NotProcessed;
}
bool NetworkNode::workWithNodeObjectData(const QSharedPointer<NodeObject> &node,
const AbstractNodeInfo* nodeInfo) {
if (!db()) {
return false;
}
auto localObjec = db()->getObject(*node.data());
if (localObjec) {
node->setTrust(std::min(node->trust(), localObjec->trust()));
if (!db()->updateObject(node)) {
QuasarAppUtils::Params::log("Error on precessing of NodeObject updateObject is failed");
return false;
};
} else {
node->setTrust(0);
if (!db()->insertObject(node)) {
QuasarAppUtils::Params::log("Error on precessing of NodeObject insertObject is failed");
return false;
};
}
auto peerNodeInfo = dynamic_cast<NetworkNodeInfo*>(getInfoPtr(nodeInfo->networkAddress()));
if (!peerNodeInfo) {
QuasarAppUtils::Params::log("Error on precessing of NodeObject peerNodeInfo is null");
return false;
}
peerNodeInfo->setSelfId(NodeId(node->getId()));
return true;
}
bool NetworkNode::workWithKnowAddresses(const KnowAddresses &obj,
const AbstractNodeInfo *nodeInfo) {
auto peerNodeInfo = dynamic_cast<NetworkNodeInfo*>(getInfoPtr(nodeInfo->networkAddress()));
if (!peerNodeInfo)
return false;
peerNodeInfo->addKnowAddresses(obj.knowAddresses());
return true;
}
ParserResult NetworkNode::workWithTransportData(const QSharedPointer<PKG::AbstractData> & transportData,
const AbstractNodeInfo* sender,
const Header& hdr) {
// convert transoprt pakcage
auto cmd = transportData.dynamicCast<TransportData>();
if (!cmd)
return ParserResult::Error;
// ignore processed packages
if (_router->isProcessed(cmd->packageId()))
return ParserResult::Processed;
// check distanation
if (cmd->targetAddress() == nodeId()) {
// inversion route and update route to sender
_router->updateRoute(cmd->senderID(),
{cmd->route().rbegin(), cmd->route().rend()});
return parsePackage(transportData, hdr, sender);
}
bool fRouteIsValid = false;
// find route if transport command do not have own route.
if (!cmd->isHaveRoute() && _router->contains(cmd->targetAddress())) {
auto route = _router->getRoute(cmd->targetAddress());
auto cmdRute = cmd->route();
cmdRute.push_back(address());
cmdRute.append(route);
cmd->setRoute(cmdRute);
}
// check exists route
if (cmd->isHaveRoute()) {
// if package have a route then remove all nodes from sender to this node from route and update route
if (!sender)
return ParserResult::Error;
cmd->strip(sender->networkAddress(), address());
// send this package to first available node of knownnodes route nodes
auto it = cmd->route().rbegin();
while (it != cmd->route().rend() && !sendData(cmd.data(), *it, &hdr)) {
it++;
}
fRouteIsValid = it != cmd->route().rend();
} else {
// if command not have a route or route is not completed then add this node to end route
cmd->addNodeToRoute(address());
}
// save route for sender node from this node
auto routeFromSenderToHere = cmd->route();
int index = routeFromSenderToHere.indexOf(address());
if (index < 0) {
QuasarAppUtils::Params::log("own node no findet on route.",
QuasarAppUtils::Error);
}
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
routeFromSenderToHere.erase(routeFromSenderToHere.cbegin(), routeFromSenderToHere.cbegin() + index);
#else
routeFromSenderToHere.erase(routeFromSenderToHere.begin(), routeFromSenderToHere.begin() + index);
#endif
// inversion route and update route to sender
_router->updateRoute(cmd->senderID(),
{routeFromSenderToHere.rbegin(), routeFromSenderToHere.rend()});
// remove invalid route nodes and fix exists route.
if (!fRouteIsValid) {
cmd->setRoute(routeFromSenderToHere);
cmd->completeRoute(false);
// send bodcast if route is invalid
if (!sendData(cmd.data(), cmd->targetAddress(), &hdr)) {
return ParserResult::Error;
}
}
_router->addProcesedPackage(cmd->packageId());
return ParserResult::Processed;
}
ParserResult NetworkNode::workWithNetworkRequest(const QSharedPointer<PKG::AbstractData> &networkRequest,
const AbstractNodeInfo *sender) {
// convert transoprt pakcage
auto cmd = networkRequest.dynamicCast<NetworkRequest>();
if (!cmd)
return ParserResult::Error;
if (cmd->isComplete()) {
if (cmd->askedNodes().contains(nodeId())) {
auto data = prepareData(cmd->dataResponce());
if (!data)
return ParserResult::Error;
return parsePackage(data, sender);
}
return ParserResult::Processed;
}
return parsePackage(cmd->dataRequest(), sender);
}
void NetworkNode::incomingData(AbstractData *pkg, const HostAddress &sender) {
AbstractNode::incomingData(pkg, sender);
}
AbstractNodeInfo *NetworkNode::createNodeInfo(QAbstractSocket *socket,
const HostAddress* clientAddress) const {
return new NetworkNodeInfo(socket, clientAddress);
}
void NetworkNode::badRequest(const HostAddress &address, const Header &req,
const ErrorData &err, qint8 diff) {
DataBaseNode::badRequest(address, req, err, diff);
}
void NetworkNode::badRequest(const NodeId &address, const Header &req,
const ErrorData &err, qint8 diff) {
if (!changeTrust(address, diff)) {
QuasarAppUtils::Params::log("Bad request detected, bud response command not sent!"
" because trust not changed",
QuasarAppUtils::Error);
return;
}
auto bad = BadRequest(err);
if (!sendData(&bad, address, &req)) {
return;
}
QuasarAppUtils::Params::log("Bad request sendet to adderess: " +
address.toString(),
QuasarAppUtils::Info);
}
bool NetworkNode::changeTrust(const QVariant &id, int diff) {
return DataBaseNode::changeTrust(id, diff);
}
bool NetworkNode::changeTrust(const HostAddress &id, int diff) {
return DataBaseNode::changeTrust(id, diff);
}
QStringList NetworkNode::SQLSources() const {
return {":/sql/NetworkSpace/Res/NetworkDB.sql"};
}
bool NetworkNode::changeTrust(const NodeId &id, int diff) {
return DataBaseNode::changeTrust(id.toRaw(), diff);
}
bool NetworkNode::ping(const NodeId &id) {
LongPing cmd(nodeId());
return sendData(&cmd, id);
}
}

@ -1,300 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#ifndef NETWORKNODE_H
#define NETWORKNODE_H
#include <databasenode.h>
#include <dbobject.h>
#include <hostaddress.h>
#include <nodeobject.h>
#include "nodeid.h"
namespace QH {
namespace PKG {
class AbstractNetworkMember;
class MemberPermisionObject;
class KnowAddresses;
}
class KeyStorage;
class Router;
class NetworkNodeInfo;
/**
* @brief The BaseNode class - base inplementation of nodes. This implementation contains methods for work with database and work with data transopt on network.
* BaseNode - is thread save class
*/
class HEARTSHARED_EXPORT NetworkNode : public DataBaseNode
{
Q_OBJECT
public:
/**
* @brief BaseNode
* @param ptr
*/
NetworkNode(QObject * ptr = nullptr);
~NetworkNode() override;
/**
* @brief run server on address an port
* @param addres - If address is empty then serve weel be listen all addreses of all interfaces
* @param port
* @return recomendet befor invoke this method call the intSqlDb.
* If you skeap a call of intSqlDb method then data base inited with default parameters.
*/
bool run(const QString &addres, unsigned short port) override;
/**
* @brief run server on address an port with local name of storage of keys
* @param addres - network address of node
* @param port - port of node
* @param localNodeName - this is locale node name. Sets name of folder with the data for current node.
* @return true if node is deployed successful
*/
bool run(const QString &addres, unsigned short port,
const QString &localNodeName) override;
/**
* @brief stop - this implementation stop work database and push to database all cache data.
*/
void stop() override;
/**
* @brief ping - ping node by node id
* @param id
* @return
*/
bool ping( const NodeId& id);
/**
* @brief nodeId
* @return
*/
NodeId nodeId() const;
protected:
/**
* @brief sendData This implementation of the sendData sending pacakge to the network by node id.
* @param resp This is sendet pacakge
* @param nodeId This is id of target node
* @param req This is header of pacakga that this pacakge ansvered.
* @return true if the package sendet successful.
*/
virtual unsigned int sendData(PKG::AbstractData *resp, const NodeId &nodeId,
const Header *req = nullptr);
/**
* @brief sendData This implementation no prepare data for sendint. for prepare data for sending use the not const object of resp.
* @param resp This is sendet pacakge
* @param nodeId This is id of target node
* @param req This is header of pacakga that this pacakge ansvered.
* @return true if the package sendet successful.
*/
virtual unsigned int sendData(const PKG::AbstractData *resp, const NodeId &nodeId,
const Header *req = nullptr);
unsigned int sendData(PKG::AbstractData *resp, const HostAddress &nodeId,
const Header *req = nullptr) override;
unsigned int sendData(const PKG::AbstractData *resp, const HostAddress &nodeId,
const Header *req = nullptr) override;
unsigned int sendData(PKG::AbstractData *resp, const QVariant &nodeId,
const Header *req = nullptr) override;
unsigned int sendData(const PKG::AbstractData *resp, const QVariant &nodeId,
const Header *req = nullptr) override;
void badRequest(const HostAddress &address, const Header &req,
const PKG::ErrorData& err, qint8 diff = REQUEST_ERROR) override;
/**
* @brief badRequest This implementation of the AbstractNode::badRequest method
* send bad request to node with id.
* @param address This is id of target node or client
* @param req This is header of request.
* @param err This is message and code for target node about error. For more onformation see the PKG::ErrorData struct.
* @param diff This is difference of current trust (currenTrus += diff)
* By default diff equals REQUEST_ERROR
*/
virtual void badRequest(const NodeId &address, const Header &req,
const PKG::ErrorData& err, qint8 diff = REQUEST_ERROR);
bool changeTrust(const QVariant &id, int diff) override;
bool changeTrust(const HostAddress &id, int diff) override;
QStringList SQLSources() const override;
/**
* @brief changeTrust This implementation is some as AbstractNode::changeTrust but change trust of node by id and save changes on local database.
* @param id This is id of node or client.
* @param diff This is integer value of trust lavel changes.
* @return true if functin finished seccussful
*/
virtual bool changeTrust(const NodeId &id, int diff);
/**
* @brief parsePackage
* @param pkg
* @param sender
* @return
*/
ParserResult parsePackage(const QSharedPointer<PKG::AbstractData> &pkg,
const Header& pkgHeader,
const AbstractNodeInfo* sender) override;
/**
* @brief createNodeInfo - this method create a new node from socket. override this mehod if you want to create a own clasess of nodes.
* @param socket
* @return pointer to new node info
*/
AbstractNodeInfo* createNodeInfo(QAbstractSocket *socket, const HostAddress *clientAddress) const override;
/**
* @brief savePermision - this method save a new changes in to permisions table.
* Befor save new data node can be validate new data with consensus.
* @param permision - data of new permision
* @return true if new cghanges saved successful.
*/
bool savePermision(const PKG::NodeObject &node, const PKG::MemberPermisionObject& permision);
/**
* @brief checkSignOfRequest
* @param request - package
* @return true if request signed.
*/
virtual bool checkSignOfRequest(const PKG::AbstractData *request);
/**
* @brief thisNode This method return the node object of this node
* @param returnValue This is return value of nodeobject
* @return This node object value.
*/
void thisNode(PKG::NodeObject & returnValue) const;
/**
* @brief myKnowAddresses
* @return set of know addresses
*/
QSet<NodeId> myKnowAddresses() const;
bool welcomeAddress(AbstractNodeInfo *node) override;
/**
* @brief connectionRegistered - this impletation send incomming node welcom message with information about yaster self.
* @param info incominng node info.
*/
void nodeConnected(AbstractNodeInfo *node) override;
/**
* @brief nodeConfirmend - this implementation test nodes to double connections
* @param mode
*/
void nodeConfirmend(AbstractNodeInfo *sender) override;
/**
* @brief nodeDisconnected - this implementation remove nodes info from connection cache
* @param sender
*/
void nodeDisconnected(AbstractNodeInfo *node) override;
/**
* @brief incomingData - this signal invoked when node get command or ansver
* @param pkg - received package
* @param sender - sender of the package
* @note override this method for get a signals.
*/
virtual void incomingData(PKG::AbstractData* pkg,
const NodeId& sender);
void incomingData(PKG::AbstractData* pkg,
const AbstractNodeInfo* sender) override;
/**
* @brief keyStorageLocation - return location of storagge of keys.
* @return path to the location of keys storage
*/
QString keyStorageLocation() const;
private:
/**
* @brief workWithNodeObjectData - this method working with received node object data.
* @param node
* @param nodeInfo
* @return true if function finished successful
*/
bool workWithNodeObjectData(const QSharedPointer<PKG::NodeObject> &node, const AbstractNodeInfo *nodeInfo);
/**
* @brief workWithKnowAddresses
* @param node
* @param nodeInfo
* @return
*/
bool workWithKnowAddresses(const PKG::KnowAddresses &obj, const AbstractNodeInfo *nodeInfo);
/**
* @brief workWithTransportData
* @param transportData
* @param sender
* @param pkg
* @return
*/
ParserResult workWithTransportData(const QSharedPointer<PKG::AbstractData> &,
const AbstractNodeInfo *sender, const Header &hdr);
/**
* @brief workWithNetworkRequest
* @param networkRequest
* @param sender
* @param pkg
* @return
*/
ParserResult workWithNetworkRequest(const QSharedPointer<PKG::AbstractData> &networkRequest,
const AbstractNodeInfo *sender);
/**
* @brief optimizeRoute - this method reduces the size of the route by removing unnecessary nodes.
* @param node
* @param rawRoute
* @return
*/
bool optimizeRoute(const NodeId& node,
const HostAddress& currentNodeAddress, const AbstractNodeInfo *sender,
QList<HostAddress> rawRoute);
/**
* @brief incomingData - this implementation move old incoming method into private section
* becouse base node work with BaseID addresses.
* @warning Do not call this implementation on this class,
* use the ncomingData(AbstractData* pkg, const HostAddress& sender) implementation.
*/
void incomingData(PKG::AbstractData* pkg,
const HostAddress& sender) override final;
KeyStorage *_nodeKeys = nullptr;
Router *_router = nullptr;
QHash<NodeId, NetworkNodeInfo*> _connections;
mutable QMutex _connectionsMutex;
};
}
#endif // NETWORKNODE_H

@ -1,47 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#include "networknodeinfo.h"
#include "dbaddress.h"
#include <QTcpSocket>
#include <hostaddress.h>
namespace QH {
NetworkNodeInfo::NetworkNodeInfo(QAbstractSocket *tcp, const HostAddress* address):
AbstractNodeInfo(tcp, address){}
NetworkNodeInfo::~NetworkNodeInfo() = default;
bool NetworkNodeInfo::isValid() const {
return AbstractNodeInfo::isValid();
}
bool NetworkNodeInfo::isKnowAddress(const NodeId &address) const {
return _knowAddresses.contains(address);
}
void NetworkNodeInfo::setSelfId(const NodeId &selfId) {
_selfId = selfId;
_knowAddresses.insert(_selfId);
}
void NetworkNodeInfo::addKnowAddresses(const QSet<NodeId> &newAddressses) {
_knowAddresses += newAddressses;
}
bool NetworkNodeInfo::confirmData() const {
return AbstractNodeInfo::confirmData() && _selfId.isValid();
}
const NodeId &NetworkNodeInfo::selfId() const
{
return _selfId;
}
}

@ -1,79 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#ifndef NETWORKCONNECTIONINFO_H
#define NETWORKCONNECTIONINFO_H
#include "basenodeinfo.h"
#include "nodeid.h"
#include "heart_global.h"
#include <QByteArray>
class QAbstractSocket;
namespace QH {
class DbAddress;
/**
* @brief The BaseNodeInfo class contaisn list of nodes id of know this node.
*/
class HEARTSHARED_EXPORT NetworkNodeInfo: public AbstractNodeInfo {
public:
/**
* @brief NetworkNodeInfo - create node info from the tcp descriptor
* @param tcp - tcp socket dsscriptor
*/
explicit NetworkNodeInfo(QAbstractSocket * tcp = nullptr,
const HostAddress* clientAddress = nullptr);
~NetworkNodeInfo() override;
/**
* @brief isValid
* @return true if node is valid.
*/
bool isValid() const override;
/**
* @brief isKnowAddress
* @param address
* @return
*/
bool isKnowAddress(const NodeId& address) const;
/**
* @brief setSelfId
* @param selfId
*/
void setSelfId(const NodeId &selfId);
/**
* @brief addKnowAddresses
*/
void addKnowAddresses(const QSet<NodeId> &newAddressses);
/**
* @brief confirmData - this implementaton check self id of node.
* @return true if node contains valid self id.
*/
bool confirmData() const override;
/**
* @brief selfId This method return id of This node.
* @return return selfId object
*/
const NodeId& selfId() const;
protected:
QSet<NodeId> _knowAddresses;
NodeId _selfId;
};
}
#endif // NETWORKCONNECTIONINFO_H

@ -1,94 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#include "nodeid.h"
namespace QH {
NodeId::NodeId() = default;
QH::NodeId::NodeId(const QVariant &val) {
QVariant::Type type = val.type();
if(type == QVariant::Type::ByteArray) {
fromRaw(val.toByteArray());
} else if (type == QVariant::Type::String) {
fromBase64(val.toByteArray());
} else {
unsigned int integer = val.toUInt();
fromRaw(reinterpret_cast<char*>(&integer), sizeof (integer));
}
}
NodeId::NodeId(unsigned int val) {
fromRaw(reinterpret_cast<char*>(&val), sizeof (val));
}
NodeId::NodeId(const QByteArray &raw) {
fromRaw(raw);
}
NodeId::NodeId(const QString &base64) {
fromBase64(base64.toLatin1());
}
bool NodeId::fromBase64(const QByteArray &base64) {
return fromRaw(QByteArray::fromBase64(base64, QByteArray::Base64UrlEncoding));
}
bool NodeId::fromRaw(const QByteArray &raw) {
_data = raw;
return isValid();
}
bool NodeId::fromRaw(const char *data, int len) {
_data.clear();
_data.insert(0, data, len);
return isValid();
}
QByteArray NodeId::toBase64() const {
return _data.toBase64(QByteArray::Base64UrlEncoding);
}
const QByteArray& NodeId::toRaw() const {
return _data;
}
bool NodeId::isValid() const {
return _data.size();
}
void NodeId::clear() {
_data.clear();
}
QString NodeId::toString() const {
return toBase64();
}
QDataStream &NodeId::fromStream(QDataStream &stream) {
stream >> _data;
return stream;
}
QDataStream &NodeId::toStream(QDataStream &stream) const {
stream << _data;
return stream;
}
bool operator==(const NodeId &left, const NodeId &other) {
return left._data == other._data;
}
uint qHash(const QH::NodeId &object) {
return qHash(object.toRaw());
}
}

@ -1,122 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#ifndef BaseId_H
#define BaseId_H
#include <QByteArray>
#include <streambase.h>
namespace QH {
/**
* @brief The NodeId class. General class for work with database id.
* The Database id is hash (sha256) from object value.
* For more information about get hash code of databae objects see the DBObject::generateId method.
*/
class HEARTSHARED_EXPORT NodeId: public StreamBase
{
public:
NodeId();
/**
* @brief NodeId This constructor for init NodeId from the QVariantObject
* @param val
*/
explicit NodeId(const QVariant& val);
/**
* @brief NodeId This contructor init the id from int value.
* @param val This is new data value.
*/
NodeId(unsigned int val);
/**
* @brief NodeId This contructor init this object from raw bytearray.
* @param raw
*/
NodeId(const QByteArray& raw);
/**
* @brief NodeId This constructor init this object from base 64 codec.
* @param base64 string with base 64 codec. This string will bew converted to a bytes array.
*/
NodeId(const QString& base64);
/**
* @brief fromBase64 This method is wraper of QByteArray::fromBase64 method of Qt.
* @param base64 string with base 64 codec. This string will bew converted to a bytes array.
* @return True if the initialize of this object fuinished successful.
*/
bool fromBase64(const QByteArray& base64);
/**
* @brief fromRaw This method conver a raw QByteArray to the BaseId key.
* @param raw This is raw bytes array.
* @return True if the initialize of this object fuinished successful.
*/
bool fromRaw(const QByteArray& raw);
/**
* @brief fromRaw This is wraper initializing from the C bytes array.
* @param data This is raw data array.
* @param len This is length of data.
* @return True if the initialize of this object fuinished successful.
*/
bool fromRaw(const char* data, int len);
/**
* @brief toBase64 This method convert this object to the base 64 string.
* @return The base64 string value.
*/
QByteArray toBase64() const;
/**
* @brief toRaw This method convert this object to raw bytes array.
* @return raw data array.
*/
const QByteArray& toRaw() const;
/**
* @brief isValid This method check this object to valid.
* @return true if object is valid.
*/
bool isValid() const;
/**
* @brief clear This method reset all data members of this object.
*/
void clear();
/**
* @brief toString This method return base64 stringValue of the address.
* @return string value of address.
*/
QString toString() const;
QDataStream &fromStream(QDataStream &stream) override;
QDataStream &toStream(QDataStream &stream) const override;
friend bool operator== (const NodeId& left, const NodeId& other);
private:
QByteArray _data;
};
/**
* @brief qHash This function calc the 32bit hash of the BaseId object.
* @param object This is input object data.
* @return unsigned int 32 value.
*/
uint qHash(const QH::NodeId& object);
}
#endif // BaseId_H

@ -1,57 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#include "badnoderequest.h"
namespace QH {
namespace PKG {
BadNodeRequest::BadNodeRequest() {
}
BadNodeRequest::BadNodeRequest(const ErrorData &err):BadRequest(err) {
}
BadNodeRequest::BadNodeRequest(const Package &package): BadRequest(package) {
}
bool BadNodeRequest::isValid() const {
return BadRequest::isValid() && senderID().isValid();
}
bool BadNodeRequest::copyFrom(const AbstractData * other) {
if (!BadRequest::copyFrom(other))
return false;
auto otherObject = dynamic_cast<const BadNodeRequest*>(other);
if (!otherObject)
return false;
setSenderID(otherObject->senderID());
return true;
}
QDataStream &BadNodeRequest::fromStream(QDataStream &stream) {
BadRequest::fromStream(stream);
NodeId senderNode;
stream >> senderNode;
setSenderID(senderNode);
return stream;
}
QDataStream &BadNodeRequest::toStream(QDataStream &stream) const {
BadRequest::toStream(stream);
stream << senderID();
return stream;
}
}
}

@ -1,39 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#ifndef BADNODEREQUEST_H
#define BADNODEREQUEST_H
#include "senderdata.h"
#include <badrequest.h>
namespace QH {
namespace PKG {
/**
* @brief The BadNodeRequest class - bad request command for bae node level
*/
class HEARTSHARED_EXPORT BadNodeRequest: public BadRequest, public SenderData
{
public:
explicit BadNodeRequest();
explicit BadNodeRequest(const ErrorData &err);
explicit BadNodeRequest(const Package& package);
// AbstractData interface
bool isValid() const;
bool copyFrom(const AbstractData *);
// StreamBase interface
protected:
QDataStream &fromStream(QDataStream &stream);
QDataStream &toStream(QDataStream &stream) const;
};
}
}
#endif // BADNODEREQUEST_H

@ -1,65 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#include "knowaddresses.h"
#include <QDataStream>
namespace QH {
namespace PKG {
KnowAddresses::KnowAddresses() {
}
KnowAddresses::KnowAddresses(const Package &pkg) {
fromBytes(pkg.toBytes());
}
bool KnowAddresses::isValid() const {
return AbstractData::isValid();
}
bool KnowAddresses::copyFrom(const AbstractData * other) {
if (!AbstractData::copyFrom(other))
return false;
auto otherObject = dynamic_cast<const KnowAddresses*>(other);
if (!otherObject)
return false;
this->_knowAddresses = otherObject->_knowAddresses;
return true;
}
QDataStream &KnowAddresses::fromStream(QDataStream &stream) {
AbstractData::fromStream(stream);
stream >> _knowAddresses;
return stream;
}
QDataStream &KnowAddresses::toStream(QDataStream &stream) const {
AbstractData::toStream(stream);
stream << _knowAddresses;
return stream;
}
QSet<NodeId> KnowAddresses::knowAddresses() const {
return _knowAddresses;
}
void KnowAddresses::setKnowAddresses(const QSet<NodeId> &knowAddresses) {
_knowAddresses = knowAddresses;
}
}
}

@ -1,46 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#ifndef KNOWADDRESSES_H
#define KNOWADDRESSES_H
#include <QSet>
#include <abstractdata.h>
#include <nodeid.h>
namespace QH {
namespace PKG {
/**
* @brief The KnowAddresses class - this class is package for send the list of know addresses of node to other node object.
*/
class HEARTSHARED_EXPORT KnowAddresses: public AbstractData
{
public:
KnowAddresses();
KnowAddresses(const Package &pkg);
// AbstractData interface
bool isValid() const override;
bool copyFrom(const AbstractData *) override;
QSet<NodeId> knowAddresses() const;
void setKnowAddresses(const QSet<NodeId> &knowAddresses);
// StreamBase interface
protected:
QDataStream &fromStream(QDataStream &stream) override;
QDataStream &toStream(QDataStream &stream) const override;
private:
QSet<NodeId> _knowAddresses;
};
}
}
#endif // KNOWADDRESSES_H

@ -1,51 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#include "longping.h"
namespace QH {
namespace PKG {
LongPing::LongPing(const NodeId &sender) {
setSenderID(sender);
}
LongPing::LongPing(const Package &from) {
fromBytes(from.data);
}
bool LongPing::isValid() const {
return Ping::isValid() && _senderID.isValid();
}
bool LongPing::copyFrom(const AbstractData * other) {
if (!Ping::copyFrom(other))
return false;
auto otherObject = dynamic_cast<const LongPing*>(other);
if (!otherObject)
return false;
this->_senderID = otherObject->_senderID;
return true;
}
QDataStream &LongPing::fromStream(QDataStream &stream) {
Ping::fromStream(stream);
stream >> _senderID;
return stream;
}
QDataStream &LongPing::toStream(QDataStream &stream) const {
Ping::toStream(stream);
stream << _senderID;
return stream;
}
}
}

@ -1,39 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#ifndef LONGPING_H
#define LONGPING_H
#include "ping.h"
#include <senderdata.h>
namespace QH {
namespace PKG {
/**
* @brief The LongPing class - test class for big network with return addresse
*/
class HEARTSHARED_EXPORT LongPing: public Ping, public SenderData
{
public:
LongPing(const NodeId &sender);
LongPing(const Package& from);
// AbstractData interface
bool isValid() const override;
bool copyFrom(const AbstractData *) override;
// StreamBase interface
protected:
QDataStream &fromStream(QDataStream &stream) override;
QDataStream &toStream(QDataStream &stream) const override;
};
}
}
#endif // LONGPING_H

@ -1,98 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#include "networkrequest.h"
#include <QDataStream>
namespace QH {
namespace PKG {
NetworkRequest::NetworkRequest() {
}
NetworkRequest::NetworkRequest(const Package &package):
NetworkRequest() {
fromBytes(package.data);
}
bool NetworkRequest::isValid() const {
return AbstractData::isValid() && _askedNodes.size() && _dataRequest.isValid();
}
bool NetworkRequest::copyFrom(const AbstractData * other) {
if (!AbstractData::copyFrom(other))
return false;
auto otherObject = dynamic_cast<const NetworkRequest*>(other);
if (!otherObject)
return false;
this->_dataRequest = otherObject->_dataRequest;
this->_askedNodes = otherObject->_askedNodes;
this->_dataResponce = otherObject->_dataResponce;
return true;
}
Package NetworkRequest::dataRequest() const {
return _dataRequest;
}
void NetworkRequest::setDataRequest(const Package &data) {
_dataRequest = data;
}
Package NetworkRequest::dataResponce() const {
return _dataResponce;
}
void NetworkRequest::setDataResponce(const Package &data) {
_dataResponce = data;
}
bool NetworkRequest::isComplete() const {
return _dataResponce.isValid();
}
void NetworkRequest::addNodeRequiringData(const NodeId &node) {
_askedNodes.insert(node);
}
QDataStream &NetworkRequest::fromStream(QDataStream &stream) {
AbstractData::fromStream(stream);
stream >> _dataRequest;
stream >> _askedNodes;
stream >> _dataResponce;
return stream;
}
QDataStream &NetworkRequest::toStream(QDataStream &stream) const {
AbstractData::toStream(stream);
stream << _dataRequest;
stream << _askedNodes;
stream << _dataResponce;
return stream;
}
QSet<NodeId> NetworkRequest::askedNodes() const {
return _askedNodes;
}
void NetworkRequest::removeNodeFromAskedList(const NodeId &node) {
_askedNodes.remove(node);
}
}
}

@ -1,108 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#ifndef NETWORKREQUEST_H
#define NETWORKREQUEST_H
#include <QSet>
#include <abstractdata.h>
#include <nodeid.h>
namespace QH {
namespace PKG {
/**
* @brief The NetworkRequest class - this is pakcage wraper for sending requests to network.
* this packages generated when current node can not process a request from client node.
* This request moving by network while do not get a ansver.
* The Ansver (or Responce) it is package with all needed data for processing of a request.
*/
class HEARTSHARED_EXPORT NetworkRequest: public AbstractData
{
public:
explicit NetworkRequest();
explicit NetworkRequest(const Package& package);
// AbstractData interface
/**
* @brief isValid chck this package
* @return true if package is valid
*/
bool isValid() const override;
/**
* @brief copyFrom - create a copy of this pacakge
* @return
*/
bool copyFrom(const AbstractData *) override;
/**
* @brief dataRequest - this is package of not processed reqest.
* @return Package of request
*/
Package dataRequest() const;
/**
* @brief setDataRequest - set Data of Reqest Package.
* @param data new pakcage.
*/
void setDataRequest(const Package &data);
/**
* @brief dataResponce - this is package of responce of request.
* The Responce package contains all needed data for procesing a request.
* @return pakage of Responce
*/
Package dataResponce() const;
/**
* @brief setDataResponce - set Data of Responce package.
* @note If this package contains a responce of request then package is completed.
* @param data - is Responce pacakge
*/
void setDataResponce(const Package &data);
/**
* @brief isComplete - return complete status. If this package contains a responce of request then package is completed.
* @return true if package is complete.
*/
bool isComplete() const;
/**
* @brief addNodeRequiringData - add a node to the list of nodes that need a responce of the request
* @param node - id of node
*/
void addNodeRequiringData(const NodeId& node);
/**
* @brief askedNodes - return list of nodes that need a responce of the request
* @return list of nodes id.
*/
QSet<NodeId> askedNodes() const;
/**
* @brief removeNodeFromAskedList - remove a node from list of nodes that need a responce of the request.
* Invoke this method when the node will get a responce.
* @param node
*/
void removeNodeFromAskedList(const NodeId& node);
protected:
QDataStream &fromStream(QDataStream &stream) override;
QDataStream &toStream(QDataStream &stream) const override;
private:
Package _dataRequest;
QSet<NodeId> _askedNodes;
Package _dataResponce;
};
}
}
#endif // NETWORKREQUEST_H

@ -1,74 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#include "nodeobject.h"
#include <QCryptographicHash>
namespace QH {
namespace PKG {
NodeObject::NodeObject() {
}
NodeObject::NodeObject(const Package &pkg):
AbstractNetworkMember(pkg) {
}
QDataStream &NodeObject::fromStream(QDataStream &stream) {
AbstractNetworkMember::fromStream(stream);
stream >> _senderID;
return stream;
}
QDataStream &NodeObject::toStream(QDataStream &stream) const {
AbstractNetworkMember::toStream(stream);
stream << _senderID;
return stream;
}
bool NodeObject::init() {
if (!AbstractNetworkMember::init())
return false;
if (authenticationData().isEmpty()) {
return true;
}
setId(QString(NodeId(QCryptographicHash::hash(authenticationData(),
QCryptographicHash::Sha256)).toBase64()));
return true;
}
DBObject *NodeObject::createDBObject() const {
return create<NodeObject>();
}
bool NodeObject::copyFrom(const AbstractData *other) {
if (!AbstractNetworkMember::copyFrom(other)) {
return false;
}
auto otherObject = dynamic_cast<const NodeObject*>(other);
if (!otherObject)
return false;
_senderID = otherObject->_senderID;
return true;
}
}
}

@ -1,37 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#ifndef NODEOBJECT_H
#define NODEOBJECT_H
#include <abstractnetworkmember.h>
#include <senderdata.h>
namespace QH {
namespace PKG {
/**
* @brief The NodeObject class
*/
class HEARTSHARED_EXPORT NodeObject: public AbstractNetworkMember, public SenderData
{
public:
NodeObject();
NodeObject(const Package& pkg);
DBObject *createDBObject() const override;
bool copyFrom(const AbstractData *other) override;
// StreamBase interface
protected:
QDataStream &fromStream(QDataStream &stream) override;
QDataStream &toStream(QDataStream &stream) const override;
bool init() override;
};
}
}
#endif // NODEOBJECT_H

@ -1,159 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#include "transportdata.h"
#include <QCryptographicHash>
#include <QDataStream>
#include <QDateTime>
namespace QH {
namespace PKG {
TransportData::TransportData() {
}
TransportData::TransportData(const HostAddress &sender):
TransportData() {
addNodeToRoute(sender);
}
TransportData::TransportData(const Package &package):
TransportData() {
fromBytes(package.data);
}
void TransportData::completeRoute(bool fRouteIsComplete) {
_fRouteIsComplete = fRouteIsComplete;
}
const Package &TransportData::data() const {
return _data;
}
void TransportData::setData(const Package &data) {
_data = data;
QByteArray tmp = _data.data;
quint64 time = QDateTime::currentMSecsSinceEpoch();
tmp.insert(sizeof(time), reinterpret_cast<char*>(&time));
_packageId.fromRaw(QCryptographicHash::hash(tmp, QCryptographicHash::Sha256));
}
bool TransportData::setData(const AbstractData &data) {
Package pkg;
if (!data.toPackage(pkg)) {
return false;
}
setData(pkg);
return true;
}
QDataStream &TransportData::fromStream(QDataStream &stream) {
AbstractData::fromStream(stream);
stream >> _targetAddress;
stream >> _senderID;
stream >> _packageId;
stream >> _fRouteIsComplete;
stream >> _route;
QByteArray array;
stream >> array;
_data.fromBytes(array);
return stream;
}
QDataStream &TransportData::toStream(QDataStream &stream) const {
AbstractData::toStream(stream);
stream << _targetAddress;
stream << _senderID;
stream << _packageId;
stream << _fRouteIsComplete;
stream << _route;
stream << _data.toBytes();
return stream;
}
const NodeId& TransportData::packageId() const {
return _packageId;
}
const QList<HostAddress>& TransportData::route() const {
return _route;
}
bool TransportData::setRoute(const QList<HostAddress> &route) {
QSet<HostAddress> test;
for (const auto& address: route) {
if (test.contains(address))
return false;
test.insert(address);
}
_route = route;
completeRoute(_route.size());
return _route.size();
}
void TransportData::addNodeToRoute(const HostAddress &node) {
_route.push_back(node);
}
bool TransportData::strip(const HostAddress &correntAddress,
const HostAddress &availabelTarget) {
QList<HostAddress>::Iterator begin = _route.end();
QList<HostAddress>::Iterator end = _route.end();
for (auto it = _route.begin(); it != _route.end(); ++it) {
if (correntAddress == *it) {
begin = it;
}
if (availabelTarget == *it) {
end = it;
break;
}
}
if (begin != _route.end() && end != _route.end()) {
_route.erase(begin, end);
return true;
}
return false;
}
const NodeId &TransportData::targetAddress() const {
return _targetAddress;
}
void TransportData::setTargetAddress(const NodeId &targetAddress) {
_targetAddress = targetAddress;
}
bool TransportData::isValid() const {
return AbstractData::isValid() && _data.isValid() && _targetAddress.isValid();
}
bool TransportData::isHaveRoute() const {
return isValid() && _route.size() && _fRouteIsComplete;
}
}
}

@ -1,97 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#ifndef TRANSPORTDATA_H
#define TRANSPORTDATA_H
#include "abstractdata.h"
#include "senderdata.h"
#include "hostaddress.h"
namespace QH {
namespace PKG {
class HEARTSHARED_EXPORT TransportData: public AbstractData, public SenderData
{
public:
explicit TransportData(const HostAddress& sender);
explicit TransportData(const Package& package);
const Package& data() const;
void setData(const Package &data);
bool setData(const AbstractData& data);
bool isValid() const;
bool isHaveRoute() const;
/**
* @brief targetAddress - targetAddress
* @return
*/
const NodeId& targetAddress() const;
void setTargetAddress(const NodeId &targetAddress);
/**
* @brief route - is list of addresses of node was the TransportData has been moved.
* @return
*/
const QList<HostAddress> &route() const;
/**
* @brief setRoute - set and validate route.
* @param route
* @return true if a new route is valid
*/
bool setRoute(const QList<HostAddress> &route);
/**
* @brief addNodeToRoute - push back new node to route
* @param node - node address
*/
void addNodeToRoute(const HostAddress &node);
/**
* @brief strip - this method remove a range addresses from route of transport data. from correntAddress to availabelTarget
* @param correntAddress - begin of remove
* @param availabelTarget - end of remove
* @return true if all addresses is removed
*/
bool strip(const HostAddress& correntAddress, const HostAddress& availabelTarget);
/**
* @brief packageId
* @return unique package id.
*/
const NodeId &packageId() const;
/**
* @brief completeRoute - set bool variable of route complete.
* @param fRouteIsComplete - new value for complete route default is true
*/
void completeRoute(bool fRouteIsComplete = true);
protected:
QDataStream &fromStream(QDataStream &stream);
QDataStream &toStream(QDataStream &stream) const;
private:
explicit TransportData();
Package _data;
NodeId _targetAddress;
QList<HostAddress> _route;
NodeId _packageId;
bool _fRouteIsComplete = false;
};
}
}
#endif // TRANSPORTDATA_H

@ -1,81 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#include "cryptopairkeys.h"
#include "qsecretrsa2048.h"
#include <QDir>
#include <qrsaencryption.h>
namespace QH {
QSecretRSA2048::QSecretRSA2048() {
qtSecret = new QRSAEncryption(QRSAEncryption::RSA_2048);
}
CryptoPairKeys QSecretRSA2048::generate(const QByteArray &genesis) const {
QByteArray pubKey;
QByteArray privKey;
qtSecret->generatePairKey(pubKey, privKey, genesis);
return {pubKey, privKey};
}
bool QSecretRSA2048::crypt(QByteArray *data,
const QByteArray &publicKey) {
*data = qtSecret->encode(*data, publicKey);
return data->size();
}
bool QSecretRSA2048::decrypt(QByteArray *cryptedData,
const QByteArray &privateKey) {
*cryptedData = qtSecret->decode(*cryptedData, privateKey);
return cryptedData->size();
}
bool QSecretRSA2048::sign(QByteArray *data,
const QByteArray &privateKey) {
*data = qtSecret->signMessage(*data, privateKey);
return data->size();
}
bool QSecretRSA2048::check(const QByteArray &signedData,
const QByteArray &publicKey) {
return qtSecret->checkSignMessage(signedData, publicKey);
}
QByteArray QSecretRSA2048::extractSign(const QByteArray &data) {
int end = data.lastIndexOf("-SIGN-");
int begin = data.lastIndexOf("-SIGN-", end);
if (end < 0 || begin < 0) {
return {};
}
return QByteArray::fromHex(data.mid(begin, begin - end));
}
QByteArray QSecretRSA2048::concatSign(const QByteArray &data, const QByteArray &sign) {
return data + "-SIGN-" + sign.toHex() + "-SIGN-";
}
bool QSecretRSA2048::isValid() const {
return qtSecret;
}
QSecretRSA2048::~QSecretRSA2048() {
delete qtSecret;
}
}

@ -1,48 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#ifndef QSECRETRSA2048_H
#define QSECRETRSA2048_H
#include "icrypto.h"
#include <QHash>
class QRSAEncryption;
namespace QH {
/**
* @brief The QSecretRSA2048 class Use a QtSecret library for implementation RSA alghoritms.
*/
class HEARTSHARED_EXPORT QSecretRSA2048: public ICrypto
{
// ICrypto interface
public:
QSecretRSA2048();
~QSecretRSA2048() override;
bool crypt(QByteArray *data, const QByteArray &publicKey) override;
bool decrypt(QByteArray *cryptedData, const QByteArray &privateKey) override;
bool sign(QByteArray *data, const QByteArray &privateKey) override;
bool check(const QByteArray &signedData, const QByteArray &publicKey) override;
QByteArray extractSign(const QByteArray &data) override;
QByteArray concatSign(const QByteArray &data, const QByteArray &sign) override;
bool isValid() const override;
protected:
CryptoPairKeys generate(const QByteArray& genesis = {}) const override;
private:
QRSAEncryption *qtSecret = nullptr;
};
}
#endif // QSECRETRSA2048_H

@ -1,64 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#include "router.h"
#include <config.h>
#include <QDateTime>
#include <quasarapp.h>
namespace QH {
Router::Router() {
}
QList<HostAddress> Router::getRoute(const NodeId &node) const {
QMutexLocker locker(&_routesMutex);
return _routes.value(node);
}
bool Router::contains(const NodeId &node) const {
QMutexLocker locker(&_routesMutex);
return _routes.contains(node);
}
void Router::updateRoute(const NodeId &node, const QList<HostAddress> &route) {
QMutexLocker locker(&_routesMutex);
debug_assert(node.isValid());
if (!_routes.contains(node) || _routes.value(node).size() > route.size()) {
_routesTimeMap.insert(QDateTime::currentSecsSinceEpoch(), node);
_routes.insert(node, route);
if (ROUTE_CACHE_LIMIT < _processedPackages.size()) {
_routes.remove(*_routesTimeMap.begin());
_routesTimeMap.erase(_routesTimeMap.begin());
}
}
}
void Router::addProcesedPackage(const NodeId &id) {
QMutexLocker locker(&_processedPackagesMutex);
_processedPackages.insert(id);
_processedPackagesTimeMap.insert(QDateTime::currentSecsSinceEpoch(), id);
if (TRANSPORT_PACKAGES_CACHE < _processedPackages.size()) {
_processedPackages.remove(*_processedPackagesTimeMap.begin());
_processedPackagesTimeMap.erase(_processedPackagesTimeMap.begin());
}
}
bool Router::isProcessed(const NodeId &id) const {
QMutexLocker locker(&_processedPackagesMutex);
return _processedPackages.contains(id);
}
}

@ -1,72 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#ifndef ROUTER_H
#define ROUTER_H
#include <QHash>
#include "nodeid.h"
#include <QMutex>
#include <hostaddress.h>
#include <QMap>
namespace QH {
/**
* @brief The Router class - this class contains routes of nodes and optimise exists routes
* router - is thread save class.
*/
class Router
{
public:
Router();
/**
* @brief getRoute
* @return return route to node from this node
*/
QList<HostAddress> getRoute(const NodeId& node) const;
/**
* @brief contains - check contains route fo node id.
* @param node - id of node
* @return true if route findet.
*/
bool contains(const NodeId& node) const;
/**
* @brief updateRoute - set a new route for a node if the new route is shorter than the old route
* @param node
* @param route
*/
void updateRoute(const NodeId& node, const QList<HostAddress>& route);
/**
* @brief addProcesedPackage - add id of processed package
* @param id
*/
void addProcesedPackage(const NodeId& id);
/**
* @brief isProcessed
* @param id
* @return true if package is processed
*/
bool isProcessed(const NodeId& id) const;
private:
QHash<NodeId, QList<HostAddress>> _routes;
QMap<qint64, NodeId> _routesTimeMap;
mutable QMutex _routesMutex;
QSet<NodeId> _processedPackages;
QMap<qint64, NodeId> _processedPackagesTimeMap;
mutable QMutex _processedPackagesMutex;
};
}
#endif // ROUTER_H

@ -1,22 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#include "senderdata.h"
namespace QH {
SenderData::SenderData() {
}
const NodeId &SenderData::senderID() const {
return _senderID;
}
void SenderData::setSenderID(const NodeId &senderID) {
_senderID = senderID;
}
}

@ -1,29 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#ifndef SENDERDATA_H
#define SENDERDATA_H
#include "nodeid.h"
namespace QH {
/**
* @brief The SenderData class - this is base interface class for get sender id of data base objects
*/
class HEARTSHARED_EXPORT SenderData
{
public:
SenderData();
const NodeId& senderID() const;
void setSenderID(const NodeId &senderID);
protected:
NodeId _senderID;
};
}
#endif // SENDERDATA_H

@ -1,24 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#include "sign.h"
namespace QH {
Sign::Sign()
{
}
QByteArray Sign::sign() const {
return _sign;
}
void Sign::setSign(const QByteArray &sign) {
_sign = sign;
}
}

@ -1,41 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#ifndef SIGN_H
#define SIGN_H
#include <QByteArray>
#include "heart_global.h"
namespace QH {
/**
* @brief The Sign class - this class contains sign of child data package.
*/
class HEARTSHARED_EXPORT Sign
{
public:
Sign();
QByteArray sign() const;
void setSign(const QByteArray &sign);
QByteArray& sign();
/**
* @brief dataForSigned - thism metho return byte array for signed
* @return data array
*/
virtual QByteArray dataForSigned() const = 0;
private:
QByteArray _sign;
};
}
#endif // SIGN_H

@ -4,7 +4,7 @@
#include <QString>
namespace QH {
class ISqlDBCache;
class ISqlDB;
class SqlDBWriter;
}
@ -12,7 +12,7 @@ template <class BASE, class CACHE, class WRITER>
class DataBaseTestNode: public BASE {
protected:
void initDefaultDbObjects(QH::ISqlDBCache *cache,
void initDefaultDbObjects(QH::ISqlDB *cache,
QH::SqlDBWriter *writer) override {
if (!writer) {
writer = new WRITER();

@ -5,7 +5,7 @@
#include <QSqlResult>
#include <iobjectprovider.h>
#include <QtTest>
#include <isqldbcache.h>
#include <isqldb.h>
#include <database.h>
#include <qaglobalutils.h>