mirror of
https://github.com/QuasarApp/Heart.git
synced 2025-04-26 09:44:37 +00:00
squash (50 commits, rename project)
This commit is contained in:
parent
1113590fb8
commit
0ec4b738a1
4
.gitignore
vendored
4
.gitignore
vendored
@ -28,6 +28,10 @@ ui_*.h
|
||||
*.jsc
|
||||
Makefile*
|
||||
*build-*
|
||||
|
||||
Heart/build/
|
||||
HeartTests/build/
|
||||
|
||||
ServerProtocol/build/
|
||||
ClientProtocol/build/
|
||||
ProtocolTests/build/
|
||||
|
6
.gitmodules
vendored
6
.gitmodules
vendored
@ -1,7 +1,7 @@
|
||||
[submodule "QuasarAppLib"]
|
||||
path = QuasarAppLib
|
||||
url = https://github.com/QuasarApp/QuasarAppLib.git
|
||||
[submodule "openssl-cmake"]
|
||||
path = openssl-cmake
|
||||
url = https://github.com/QuasarApp/openssl-cmake.git
|
||||
|
||||
[submodule "Heart/Qt-Secret"]
|
||||
path = Heart/Qt-Secret
|
||||
url = https://github.com/QuasarApp/Qt-Secret.git
|
||||
|
@ -5,15 +5,26 @@
|
||||
# of this license document, but changing it is not allowed.
|
||||
#
|
||||
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
project(MainNetworkProtocol)
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
project(Heart)
|
||||
if(TARGET ${PROJECT_NAME})
|
||||
message("The ${PROJECT_NAME} arledy included in main Project")
|
||||
return()
|
||||
endif()
|
||||
|
||||
find_package(Qt5 COMPONENTS Core Test REQUIRED)
|
||||
if(NOT DEFINED BUILD_LVL)
|
||||
set(BUILD_LVL 2)
|
||||
endif()
|
||||
|
||||
include(QuasarAppLib/CMake/ccache.cmake)
|
||||
|
||||
# Add sub directories
|
||||
add_subdirectory(QuasarAppLib)
|
||||
add_subdirectory(openssl-cmake)
|
||||
add_subdirectory(NetworkProtocol)
|
||||
add_subdirectory(ProtocolTests)
|
||||
add_subdirectory(Heart)
|
||||
add_subdirectory(HeartTests)
|
||||
|
||||
include(QuasarAppLib/CMake/QuasarAppCITargets.cmake)
|
||||
initAll()
|
||||
|
||||
addDoc(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/doxygen.conf)
|
||||
|
1533
Heart/AbstractSpace/Diagrams/async.qmodel
Normal file
1533
Heart/AbstractSpace/Diagrams/async.qmodel
Normal file
File diff suppressed because it is too large
Load Diff
0
Heart/AbstractSpace/Diagrams/header.h
Normal file
0
Heart/AbstractSpace/Diagrams/header.h
Normal file
1030
Heart/AbstractSpace/abstractnode.cpp
Normal file
1030
Heart/AbstractSpace/abstractnode.cpp
Normal file
File diff suppressed because it is too large
Load Diff
502
Heart/AbstractSpace/abstractnode.h
Normal file
502
Heart/AbstractSpace/abstractnode.h
Normal file
@ -0,0 +1,502 @@
|
||||
/*
|
||||
* 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 ABSTRACTNODE_H
|
||||
#define ABSTRACTNODE_H
|
||||
|
||||
#include "abstractnodeinfo.h"
|
||||
#include <openssl/evp.h>
|
||||
|
||||
#include <QAbstractSocket>
|
||||
#include <QFutureWatcher>
|
||||
#include <QMutex>
|
||||
#include <QSslConfiguration>
|
||||
#include <QTcpServer>
|
||||
#include <QTimer>
|
||||
#include "abstractdata.h"
|
||||
#include "workstate.h"
|
||||
|
||||
#include "cryptopairkeys.h"
|
||||
#include "icrypto.h"
|
||||
#include "heart_global.h"
|
||||
#include "receivedata.h"
|
||||
#include "packagemanager.h"
|
||||
|
||||
class QSslCertificate;
|
||||
class QSslKey;
|
||||
class QSslConfiguration;
|
||||
|
||||
namespace NP {
|
||||
|
||||
class DataSender;
|
||||
|
||||
/**
|
||||
* @brief The ParserResult enum
|
||||
* Error - parser detect a errorob package
|
||||
* NotProcessed - the parser does not know what to do with the package or has not finished processing it.
|
||||
* Processed - the parser finished processing correctly
|
||||
*/
|
||||
enum class ParserResult {
|
||||
/// parser detect a errorob package
|
||||
Error = 0,
|
||||
/// the parser does not know what to do with the package or has not finished processing it.
|
||||
NotProcessed = 1,
|
||||
/// the parser finished processing correctly
|
||||
Processed = 2
|
||||
};
|
||||
|
||||
enum class SslMode {
|
||||
NoSSL,
|
||||
InitFromSystem,
|
||||
InitSelfSigned
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The SslSrtData struct
|
||||
*/
|
||||
struct SslSrtData {
|
||||
QString country = "BY";
|
||||
QString organization = "QuasarApp";
|
||||
QString commonName = "Dev";
|
||||
long long endTime = 31536000L; //1 year
|
||||
};
|
||||
|
||||
|
||||
#define CRITICAL_ERROOR -50
|
||||
#define LOGICK_ERROOR -20
|
||||
#define REQUEST_ERROR -5
|
||||
|
||||
class Abstract;
|
||||
|
||||
/**
|
||||
* @brief The AbstractNode class - Abstract implementation of node.
|
||||
* this implementation have a methods for send and receive data messages,
|
||||
* and work with crypto method for crease a security connections betwin nodes.
|
||||
* AbstractNode - is thread save class
|
||||
*/
|
||||
class NETWORKPROTOCOLSHARED_EXPORT AbstractNode : public QTcpServer
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief AbstractNode
|
||||
* @param ssl
|
||||
* @param ptr
|
||||
*/
|
||||
AbstractNode(SslMode mode = SslMode::NoSSL, QObject * ptr = nullptr);
|
||||
~AbstractNode() override;
|
||||
|
||||
/**
|
||||
* @brief run
|
||||
* @param addres - If address is empty then serve weel be listen all addreses of all interfaces
|
||||
* @param port
|
||||
* @return true if all good
|
||||
*/
|
||||
virtual bool run(const QString& addres, unsigned short port);
|
||||
|
||||
/**
|
||||
* @brief stop stop this node and close all connections.
|
||||
*/
|
||||
virtual void stop();
|
||||
|
||||
/**
|
||||
* @brief getInfo
|
||||
* @param id of selected node
|
||||
* @return pointer to information about node. if address not found return nullpt
|
||||
*/
|
||||
virtual AbstractNodeInfo* getInfoPtr(const HostAddress &id);
|
||||
|
||||
/**
|
||||
* @brief getInfoPtr
|
||||
* @param id peer adders
|
||||
* @return pointer to information about node. if address not found return nullpt
|
||||
*/
|
||||
virtual const AbstractNodeInfo* getInfoPtr(const HostAddress &id) const;
|
||||
|
||||
/**
|
||||
* @brief ban
|
||||
* @param target id of ban node
|
||||
*/
|
||||
virtual void ban(const HostAddress& target);
|
||||
|
||||
/**
|
||||
* @brief unBan
|
||||
* @param target id of unban node
|
||||
*/
|
||||
virtual void unBan(const HostAddress& target);
|
||||
|
||||
/**
|
||||
* @brief connectToHost - connect to host node
|
||||
* @param address - address of node
|
||||
* @param mode - mode see SslMode
|
||||
*/
|
||||
virtual bool connectToHost(const HostAddress &address, SslMode mode = SslMode::NoSSL);
|
||||
|
||||
/**
|
||||
* @brief connectToHost - connect to host node. this method find ip address of domain befor connecting
|
||||
* @param domain: address of node
|
||||
* @param port - port of node
|
||||
* @param mode - mode see SslMode
|
||||
*/
|
||||
virtual bool connectToHost(const QString &domain, unsigned short port, SslMode mode = SslMode::NoSSL);
|
||||
|
||||
/**
|
||||
* @brief addNode - add new node for connect
|
||||
* @param nodeAdderess - the network addres of a new node.
|
||||
*/
|
||||
void addNode(const HostAddress& nodeAdderess);
|
||||
|
||||
/**
|
||||
* @brief removeNode - remove node
|
||||
* @param nodeAdderess - the adddress of removed node.
|
||||
*/
|
||||
void removeNode(const HostAddress& nodeAdderess);
|
||||
|
||||
/**
|
||||
* @brief address - address of this node
|
||||
* @return return current adders
|
||||
*/
|
||||
HostAddress address() const;
|
||||
|
||||
/**
|
||||
* @brief getSslConfig - configuration of this node.
|
||||
* @return current ssl configuration on this nod
|
||||
*/
|
||||
QSslConfiguration getSslConfig() const;
|
||||
|
||||
/**
|
||||
* @brief getMode
|
||||
* @return
|
||||
*/
|
||||
SslMode getMode() const;
|
||||
|
||||
/**
|
||||
* @brief getWorkState
|
||||
* @return
|
||||
*/
|
||||
virtual WorkState getWorkState() const;
|
||||
|
||||
/**
|
||||
* @brief pareseResultToString
|
||||
* @return string of pareseresult
|
||||
*/
|
||||
QString pareseResultToString(const ParserResult& parseResult) const;
|
||||
|
||||
/**
|
||||
* @brief connectionsCount - return count fo connections (nodes with status connected)
|
||||
* @return
|
||||
*/
|
||||
int connectionsCount() const;
|
||||
|
||||
/**
|
||||
* @brief connectionsCount - return count of nodes with status confirmend
|
||||
* @return
|
||||
*/
|
||||
int confirmendCount() const;
|
||||
|
||||
/**
|
||||
* @brief ping - ping address for testing
|
||||
* @param address - address of other node
|
||||
* @return true if ping sendet
|
||||
*/
|
||||
bool ping( const HostAddress& address);
|
||||
|
||||
signals:
|
||||
void requestError(QString msg);
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* @brief generateRSAforSSL
|
||||
* @param pkey -
|
||||
* @return
|
||||
*/
|
||||
virtual bool generateRSAforSSL(EVP_PKEY* pkey) const;
|
||||
|
||||
/**
|
||||
* @brief generateSslData - generate new ssl data
|
||||
* @param data - sign data
|
||||
* @param r_srt - result srt
|
||||
* @param r_key - result private key
|
||||
* @return true if all good
|
||||
*/
|
||||
virtual bool generateSslDataPrivate(const SslSrtData& data, QSslCertificate& r_srt, QSslKey& r_key);
|
||||
|
||||
/**
|
||||
* @brief selfSignedSslConfiguration
|
||||
* @return generate new keys and use it
|
||||
*/
|
||||
virtual QSslConfiguration selfSignedSslConfiguration();
|
||||
|
||||
/**
|
||||
* @brief createNodeInfo
|
||||
* @return nodeinfo for new connection
|
||||
* override this metho for set your own nodeInfo objects;
|
||||
*/
|
||||
virtual AbstractNodeInfo* createNodeInfo(QAbstractSocket *socket,
|
||||
const HostAddress *clientAddress = nullptr) const;
|
||||
|
||||
/**
|
||||
* @brief registerSocket - this method registration new socket
|
||||
* @param socket - socket pointer
|
||||
* @param incoming - host address of socket. by default is nullptr.
|
||||
* Set this value for nodes created on this host
|
||||
* @return return true if the scoeket has been registered successful
|
||||
*/
|
||||
virtual bool registerSocket(QAbstractSocket *socket, const HostAddress* address = nullptr);
|
||||
|
||||
/**
|
||||
* @brief parsePackage
|
||||
* @param pkg
|
||||
* @param sender
|
||||
* @return item of ParserResult ()
|
||||
*/
|
||||
virtual ParserResult parsePackage(const Package &pkg, const AbstractNodeInfo* sender);
|
||||
|
||||
/**
|
||||
* @brief sendPackage
|
||||
* @param pkg
|
||||
* @param target
|
||||
* @return
|
||||
*/
|
||||
virtual bool sendPackage(const Package &pkg, QAbstractSocket *target) const;
|
||||
|
||||
/**
|
||||
* @brief sendData send data package to address and prepare object to sending.
|
||||
* @param resp - pointer to sendet object
|
||||
* @param address - target addres for sending
|
||||
* @param req - header of request
|
||||
* @return true if data sendet succesful.
|
||||
*/
|
||||
virtual bool sendData(AbstractData *resp, const HostAddress& addere,
|
||||
const Header *req = nullptr);
|
||||
|
||||
/**
|
||||
* @brief sendData this is some as a sendData(AbstractData *resp ...) exept this method not prepare object for sending.
|
||||
* @param resp - pointer to sendet object
|
||||
* @param address - target addres for sending
|
||||
* @param req - header of request
|
||||
* @return true if data sendet succesful.
|
||||
*/
|
||||
virtual bool sendData(const AbstractData *resp, const HostAddress& addere,
|
||||
const Header *req = nullptr);
|
||||
|
||||
/**
|
||||
* @brief badRequestu
|
||||
* @param address
|
||||
* @param req
|
||||
* @param msg - message of error
|
||||
*/
|
||||
virtual void badRequest(const HostAddress &address, const Header &req,
|
||||
const QString msg = "");
|
||||
|
||||
/**
|
||||
* @brief getWorkStateString
|
||||
* @return string of work state
|
||||
*/
|
||||
virtual QString getWorkStateString() const;
|
||||
|
||||
/**
|
||||
* @brief connectionState
|
||||
* @return string with count users state
|
||||
*/
|
||||
virtual QString connectionState() const;
|
||||
|
||||
/**
|
||||
* @brief banedList
|
||||
* @return list of baned nodes
|
||||
*/
|
||||
QList<HostAddress> banedList() const;
|
||||
|
||||
/**
|
||||
* @brief isBanned
|
||||
* @param socket
|
||||
* @return
|
||||
*/
|
||||
bool isBanned(QAbstractSocket* socket) const;
|
||||
|
||||
/**
|
||||
* @brief incomingConnection
|
||||
* @param handle
|
||||
*/
|
||||
void incomingConnection(qintptr handle) override;
|
||||
|
||||
/**
|
||||
* @brief changeTrust change trust of connected node
|
||||
* @param id - id of select node
|
||||
* @param diff
|
||||
* @return true if all good
|
||||
*/
|
||||
virtual bool changeTrust(const HostAddress& id, int diff);
|
||||
|
||||
/**
|
||||
* @brief incomingConnection for ssl sockets
|
||||
* @param handle - handle of socket
|
||||
*/
|
||||
virtual void incomingSsl(qintptr handle);
|
||||
|
||||
/**
|
||||
* @brief incomingConnection for tcp sockets
|
||||
* @param handle - handle of socket
|
||||
*/
|
||||
virtual void incomingTcp(qintptr handle);
|
||||
|
||||
|
||||
/**
|
||||
* @brief setMode - invoke this method befor run method
|
||||
* @param mode
|
||||
*/
|
||||
bool setMode(const SslMode &mode);
|
||||
|
||||
/**
|
||||
* @brief incomingData - this signal invoked when node get command or ansver
|
||||
* @param pkg - get package (in this implementation it is only the Ping command)
|
||||
* @param sender - sender of the package
|
||||
* @note override this method for get a signals.
|
||||
*/
|
||||
virtual void incomingData(AbstractData* pkg,
|
||||
const HostAddress& sender);
|
||||
|
||||
/**
|
||||
* @brief connections - return hash map of all connections of this node.
|
||||
* @return
|
||||
*/
|
||||
QHash<HostAddress, AbstractNodeInfo*> connections() const;
|
||||
|
||||
/**
|
||||
* @brief connectionRegistered Override this method for get registered incoming connections.
|
||||
* @param info - connection information.
|
||||
*/
|
||||
virtual void connectionRegistered(const AbstractNodeInfo *info);
|
||||
|
||||
/**
|
||||
* @brief nodeStatusChanged - This method invoked when status of node chganged.
|
||||
* Base implementation do nothing. Override this method for add own functionality.
|
||||
* @param node - address of changed node.
|
||||
* @param status - new status of node.
|
||||
*
|
||||
*/
|
||||
void nodeStatusChanged(const HostAddress& node, NodeCoonectionStatus status);
|
||||
|
||||
/**
|
||||
* @brief nodeConfirmend - thim method invocked when the node status changed to "confirmend"
|
||||
* default implementatio do nothing
|
||||
* @param node - the address of changed node
|
||||
*/
|
||||
virtual void nodeConfirmend(const HostAddress& node);
|
||||
|
||||
/**
|
||||
* @brief nodeConnected thim method invocked when the node status changed to "connected"
|
||||
* default implementatio do nothing
|
||||
* @param node
|
||||
*/
|
||||
virtual void nodeConnected(const HostAddress& node);
|
||||
|
||||
/**
|
||||
* @brief nodeConnected thim method invocked when the node status changed to "disconnected"
|
||||
* default implementatio do nothing
|
||||
* @param node
|
||||
*/
|
||||
virtual void nodeDisconnected(const HostAddress& node);
|
||||
|
||||
|
||||
/**
|
||||
* @brief pushToQueue - This method add action to queue. When the node status will be equal 'triggerStatus' then node run a action method.
|
||||
* @param node - node.
|
||||
* @param action - lyamda function with action.
|
||||
* @param triggerStatus - node status.
|
||||
*/
|
||||
void pushToQueue(const std::function<void ()> &action,
|
||||
const HostAddress& node,
|
||||
NodeCoonectionStatus triggerStatus);
|
||||
|
||||
/**
|
||||
* @brief takeFromQueue - take the list of actions of node. after invoke take elements will be removed.
|
||||
* @param node - node
|
||||
* @param triggerStatus - status of node
|
||||
* @return list o actions
|
||||
*/
|
||||
QList<std::function<void ()>> takeFromQueue(const HostAddress& node,
|
||||
NodeCoonectionStatus triggerStatus);
|
||||
private slots:
|
||||
|
||||
void avelableBytes();
|
||||
void handleDisconnected();
|
||||
void handleConnected();
|
||||
void handleCheckConfirmendOfNode(HostAddress node);
|
||||
|
||||
/**
|
||||
* @brief handleWorkerStoped
|
||||
*/
|
||||
void handleWorkerStoped();
|
||||
|
||||
/**
|
||||
* @brief handleForceRemoveNode - force remove connection.
|
||||
* @param node
|
||||
*/
|
||||
void handleForceRemoveNode(HostAddress node);
|
||||
|
||||
/**
|
||||
* @brief connectNodePrivate
|
||||
*/
|
||||
void connectNodePrivate(NP::HostAddress);
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
@note just disaable listen method in the node objects.
|
||||
*/
|
||||
bool listen(const HostAddress& address = HostAddress::Any);
|
||||
|
||||
/**
|
||||
* @brief newWork - this method it is wraper of the parsePackage method.
|
||||
* the newWork invoke a parsePackage in the new thread.
|
||||
* @param pkg
|
||||
* @param sender
|
||||
*/
|
||||
void newWork(const Package &pkg, const AbstractNodeInfo* sender, const HostAddress &id);
|
||||
|
||||
|
||||
/**
|
||||
* @brief nodeConfirmet - this metthod invoked when node is confirment.
|
||||
* @param sender - node with new status;
|
||||
*/
|
||||
void nodeConfirmet(const HostAddress &node);
|
||||
|
||||
/**
|
||||
* @brief checkConfirmendOfNode - this method remove old not confirmed node.
|
||||
* @param node - node address
|
||||
*/
|
||||
void checkConfirmendOfNode(const HostAddress& node);
|
||||
|
||||
SslMode _mode;
|
||||
QSslConfiguration _ssl;
|
||||
QHash<HostAddress, AbstractNodeInfo*> _connections;
|
||||
QHash<HostAddress, ReceiveData> _receiveData;
|
||||
|
||||
QHash<HostAddress, QHash<NodeCoonectionStatus, QList<std::function<void()>>>> _actionCache;
|
||||
|
||||
DataSender * _dataSender = nullptr;
|
||||
|
||||
QSet<QFutureWatcher <bool>*> _workers;
|
||||
|
||||
PackageManager _packageManager;
|
||||
|
||||
|
||||
mutable QMutex _connectionsMutex;
|
||||
mutable QMutex _actionCacheMutex;
|
||||
mutable QMutex _confirmNodeMutex;
|
||||
|
||||
friend class WebSocketController;
|
||||
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
#endif // ABSTRACTNODE_H
|
143
Heart/AbstractSpace/abstractnodeinfo.cpp
Normal file
143
Heart/AbstractSpace/abstractnodeinfo.cpp
Normal file
@ -0,0 +1,143 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "abstractnodeinfo.h"
|
||||
#include <hostaddress.h>
|
||||
#include <QAbstractSocket>
|
||||
#include <QDataStream>
|
||||
#include <QHostInfo>
|
||||
|
||||
namespace NP {
|
||||
|
||||
AbstractNodeInfo::AbstractNodeInfo(QAbstractSocket *sct,
|
||||
const HostAddress *address) {
|
||||
setSct(sct);
|
||||
if (address)
|
||||
setNetworkAddress(*address);
|
||||
|
||||
}
|
||||
|
||||
AbstractNodeInfo::~AbstractNodeInfo() {}
|
||||
|
||||
QAbstractSocket *AbstractNodeInfo::sct() const {
|
||||
return _sct;
|
||||
}
|
||||
|
||||
void AbstractNodeInfo::disconnect() {
|
||||
if (_sct) {
|
||||
_sct->close();
|
||||
_sct->deleteLater();
|
||||
_sct = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void AbstractNodeInfo::ban() {
|
||||
_trust = static_cast<int>(TrustNode::Baned);
|
||||
disconnect();
|
||||
}
|
||||
|
||||
bool AbstractNodeInfo::isBanned() const {
|
||||
return _trust < 1;
|
||||
}
|
||||
|
||||
void AbstractNodeInfo::unBan() {
|
||||
_trust = static_cast<int>(TrustNode::Restore);
|
||||
}
|
||||
|
||||
void AbstractNodeInfo::setSct(QAbstractSocket *sct) {
|
||||
_sct = sct;
|
||||
if (_sct && !_sct->peerAddress().isNull()) {
|
||||
setNetworkAddress(HostAddress{_sct->peerAddress(), _sct->peerPort()});
|
||||
}
|
||||
}
|
||||
|
||||
void AbstractNodeInfo::setIsLocal(bool isLocal) {
|
||||
_isLocal = isLocal;
|
||||
}
|
||||
|
||||
NodeCoonectionStatus AbstractNodeInfo::status() const {
|
||||
return _status;
|
||||
}
|
||||
|
||||
void AbstractNodeInfo::setStatus(const NodeCoonectionStatus &status) {
|
||||
_status = status;
|
||||
}
|
||||
|
||||
bool AbstractNodeInfo::confirmData() const {
|
||||
return _status != NodeCoonectionStatus::NotConnected;
|
||||
}
|
||||
|
||||
bool AbstractNodeInfo::isLocal() const {
|
||||
return _isLocal;
|
||||
}
|
||||
|
||||
HostAddress AbstractNodeInfo::networkAddress() const {
|
||||
if (isValid() && _sct->isValid())
|
||||
return HostAddress{_sct->peerAddress(), _sct->peerPort()};
|
||||
|
||||
return _networkAddress;
|
||||
}
|
||||
|
||||
void AbstractNodeInfo::setNetworkAddress(const HostAddress &networkAddress) {
|
||||
|
||||
if (!networkAddress.isNull()) {
|
||||
_networkAddress = networkAddress;
|
||||
|
||||
QHostInfo::lookupHost(_networkAddress.toString(), [this] (QHostInfo info){
|
||||
if (dynamic_cast<AbstractNodeInfo*>(this)) {
|
||||
setInfo(info);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void AbstractNodeInfo::setInfo(const QHostInfo &info) {
|
||||
if (!_info)
|
||||
_info = new QHostInfo();
|
||||
|
||||
*_info = info;
|
||||
}
|
||||
|
||||
QHostInfo *AbstractNodeInfo::info() const {
|
||||
return _info;
|
||||
}
|
||||
|
||||
int AbstractNodeInfo::trust() const {
|
||||
return _trust;
|
||||
}
|
||||
|
||||
void AbstractNodeInfo::setTrust(int trust) {
|
||||
_trust = trust;
|
||||
|
||||
if (isBanned()) {
|
||||
disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
bool AbstractNodeInfo::isValid() const {
|
||||
return _sct;
|
||||
}
|
||||
|
||||
bool AbstractNodeInfo::isConnected() const {
|
||||
return isValid() && _sct->isOpen();
|
||||
}
|
||||
|
||||
QDataStream &AbstractNodeInfo::fromStream(QDataStream &stream) {
|
||||
stream >> _networkAddress;
|
||||
return stream;
|
||||
}
|
||||
|
||||
QDataStream &AbstractNodeInfo::toStream(QDataStream &stream) const {
|
||||
stream << _networkAddress;
|
||||
return stream;
|
||||
}
|
||||
|
||||
uint qHash(NodeCoonectionStatus status) {
|
||||
return static_cast<uint>(status);
|
||||
}
|
||||
|
||||
}
|
213
Heart/AbstractSpace/abstractnodeinfo.h
Normal file
213
Heart/AbstractSpace/abstractnodeinfo.h
Normal file
@ -0,0 +1,213 @@
|
||||
/*
|
||||
* 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 ABSTRACTNODEINFO_H
|
||||
#define ABSTRACTNODEINFO_H
|
||||
#include "hostaddress.h"
|
||||
#include "heart_global.h"
|
||||
|
||||
#include <hostaddress.h>
|
||||
|
||||
|
||||
class QAbstractSocket;
|
||||
class QHostInfo;
|
||||
|
||||
namespace NP {
|
||||
|
||||
/**
|
||||
* @brief The TrustNode enum
|
||||
*/
|
||||
enum class TrustNode: unsigned char {
|
||||
/// undefined node
|
||||
Undefined = 0xFF,
|
||||
|
||||
/// general trust of node
|
||||
Default = 100,
|
||||
|
||||
/// this trusted of unbaned nodes
|
||||
Restore = 20,
|
||||
|
||||
/// node with this trusted is forbidden
|
||||
Baned = 0
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The AbstractNodeState enum - This is status of known nodes.
|
||||
*/
|
||||
enum class NodeCoonectionStatus: int {
|
||||
/// This node not sent data about its envirement
|
||||
NotConnected,
|
||||
/// The node with this status has already sent data about its environment.
|
||||
Connected,
|
||||
/// The node confirmend. Node with it status sent a information
|
||||
/// requarement for confirm in to this node object.
|
||||
Confirmed,
|
||||
};
|
||||
|
||||
uint qHash(NodeCoonectionStatus status);
|
||||
|
||||
/**
|
||||
* @brief The AbstractNodeInfo class
|
||||
*/
|
||||
class NETWORKPROTOCOLSHARED_EXPORT AbstractNodeInfo
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief AbstractNodeInfo
|
||||
* @param sct socket of connection
|
||||
* @param address - address of socket
|
||||
*/
|
||||
AbstractNodeInfo(QAbstractSocket *sct = nullptr,
|
||||
const HostAddress* address = nullptr);
|
||||
|
||||
/**
|
||||
* @brief ~AbstractNodeInfo
|
||||
*/
|
||||
virtual ~AbstractNodeInfo();
|
||||
|
||||
/**
|
||||
* @brief sct
|
||||
* @return return socket of connection
|
||||
*/
|
||||
QAbstractSocket *sct() const;
|
||||
|
||||
/**
|
||||
* @brief disconnect disconnect from host
|
||||
*/
|
||||
virtual void disconnect();
|
||||
|
||||
/**
|
||||
* @brief ban this node
|
||||
*/
|
||||
virtual void ban();
|
||||
|
||||
/**
|
||||
* @brief isBanned
|
||||
* @return true if node baned
|
||||
*/
|
||||
virtual bool isBanned() const;
|
||||
|
||||
/**
|
||||
* @brief unBan
|
||||
*/
|
||||
virtual void unBan();
|
||||
|
||||
/**
|
||||
* @brief trust
|
||||
* @return rtust
|
||||
*/
|
||||
virtual int trust() const;
|
||||
|
||||
/**
|
||||
* @brief setTrust manual set value of trust
|
||||
* @param trust - new value
|
||||
*/
|
||||
virtual void setTrust(int trust);
|
||||
|
||||
/**
|
||||
* @brief isValid
|
||||
* @return true if all data valid
|
||||
*/
|
||||
virtual bool isValid() const;
|
||||
|
||||
/**
|
||||
* @brief isConnected
|
||||
* @return true if the socket connected
|
||||
*/
|
||||
virtual bool isConnected() const;
|
||||
|
||||
/**
|
||||
* @brief fromStream
|
||||
* @param stream
|
||||
* @return stream
|
||||
*/
|
||||
virtual QDataStream& fromStream(QDataStream& stream);
|
||||
|
||||
/**
|
||||
* @brief toStream
|
||||
* @param stream
|
||||
* @return stream
|
||||
*/
|
||||
virtual QDataStream& toStream(QDataStream& stream) const;
|
||||
|
||||
/**
|
||||
* @brief info
|
||||
* @return Host info of this node
|
||||
*/
|
||||
QHostInfo *info() const;
|
||||
|
||||
/**
|
||||
* @brief setInfo - set new temp info for this node
|
||||
* @param info
|
||||
*/
|
||||
void setInfo(const QHostInfo &info);
|
||||
|
||||
/**
|
||||
* @brief networkAddress
|
||||
* @return network adderess of node
|
||||
*/
|
||||
HostAddress networkAddress() const;
|
||||
|
||||
/**
|
||||
* @brief setNetworkAddress - update network address
|
||||
* @param networkAddress - new address
|
||||
*/
|
||||
void setNetworkAddress(const HostAddress &networkAddress);
|
||||
|
||||
/**
|
||||
* @brief status - status of node connection
|
||||
* @return connection status
|
||||
*/
|
||||
NodeCoonectionStatus status() const;
|
||||
|
||||
/**
|
||||
* @brief setStatus - set new value of status node
|
||||
* @param status - new status
|
||||
*/
|
||||
void setStatus(const NodeCoonectionStatus &status);
|
||||
|
||||
/**
|
||||
* @brief confirmData - check all data of node and return true if node is confirmed
|
||||
* @return true if node is confirmed
|
||||
*/
|
||||
virtual bool confirmData() const;
|
||||
|
||||
/**
|
||||
* @brief isLocal - return true if connectuion opened on this node.
|
||||
* @return
|
||||
*/
|
||||
bool isLocal() const;
|
||||
|
||||
/**
|
||||
* @brief setIsLocal - set local status for this Node.
|
||||
* @param isLocal
|
||||
*/
|
||||
void setIsLocal(bool isLocal);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief setSct
|
||||
* @param sct
|
||||
*/
|
||||
void setSct(QAbstractSocket *sct);
|
||||
|
||||
private:
|
||||
|
||||
QHostInfo *_info = nullptr;
|
||||
HostAddress _networkAddress;
|
||||
|
||||
QAbstractSocket *_sct = nullptr;
|
||||
int _trust = static_cast<int>(TrustNode::Default);
|
||||
NodeCoonectionStatus _status = NodeCoonectionStatus::NotConnected;
|
||||
bool _isLocal = false;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
#endif // ABSTRACTNODEINFO_H
|
9
Heart/AbstractSpace/atomicmetatypes.h
Normal file
9
Heart/AbstractSpace/atomicmetatypes.h
Normal file
@ -0,0 +1,9 @@
|
||||
#ifndef ATOMICMETATYPES_H
|
||||
#define ATOMICMETATYPES_H
|
||||
#include <QMetaType>
|
||||
|
||||
Q_DECLARE_METATYPE(const bool*)
|
||||
Q_DECLARE_METATYPE(bool*)
|
||||
|
||||
|
||||
#endif // ATOMICMETATYPES_H
|
41
Heart/AbstractSpace/config.h
Normal file
41
Heart/AbstractSpace/config.h
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* 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 CONFIG_H
|
||||
#define CONFIG_H
|
||||
#include <QStandardPaths>
|
||||
|
||||
|
||||
// network settings
|
||||
#define LOCAL_SERVER "127.0.0.1"
|
||||
|
||||
#define DEFAULT_PORT 3090
|
||||
#define WAIT_CONFIRM_TIME 30000 // 30000 msec = 30 sec
|
||||
|
||||
// Data Base settings
|
||||
#define DEFAULT_DB_NAME "Storage.sqlite"
|
||||
#define DEFAULT_DB_PATH QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)
|
||||
#define DEFAULT_DB_INIT_FILE_PATH ":/sql/DataBaseSpace/Res/BaseDB.sql"
|
||||
#define DEFAULT_UPDATE_INTERVAL 3600000 // 1 hour
|
||||
|
||||
// Transport Protockol settings
|
||||
#define ROUTE_COUNT_LIMIT 1000
|
||||
#define TRANSPORT_PACKAGES_CACHE 1000
|
||||
|
||||
// Node Settings
|
||||
#define PACKAGE_CACHE_SIZE 1000
|
||||
|
||||
// Other settings
|
||||
#ifdef RELEASE_BUILD
|
||||
#define WAIT_TIME 30000
|
||||
#define WAIT_RESPOCE_TIME 10000
|
||||
#else
|
||||
#define WAIT_TIME 300000000
|
||||
#define WAIT_RESPOCE_TIME 100000000
|
||||
#endif
|
||||
|
||||
#endif // CONFIG_H
|
73
Heart/AbstractSpace/cryptopairkeys.cpp
Normal file
73
Heart/AbstractSpace/cryptopairkeys.cpp
Normal file
@ -0,0 +1,73 @@
|
||||
#include "cryptopairkeys.h"
|
||||
|
||||
#include <QDataStream>
|
||||
namespace NP {
|
||||
CryptoPairKeys::CryptoPairKeys() {
|
||||
|
||||
}
|
||||
|
||||
CryptoPairKeys::CryptoPairKeys(const QByteArray &pubKey, const QByteArray &privKey) {
|
||||
setPrivKey(privKey);
|
||||
setPublicKey(pubKey);
|
||||
setBits(privKey.size() * 8);
|
||||
}
|
||||
|
||||
bool CryptoPairKeys::isValid() const {
|
||||
return _privKey.size() && _publicKey.size() && !(_bits % 8) && _bits > 1;
|
||||
}
|
||||
|
||||
QByteArray CryptoPairKeys::privKey() const {
|
||||
return _privKey;
|
||||
}
|
||||
|
||||
void CryptoPairKeys::setPrivKey(const QByteArray &privKey) {
|
||||
_privKey = privKey;
|
||||
}
|
||||
|
||||
QByteArray CryptoPairKeys::publicKey() const {
|
||||
return _publicKey;
|
||||
}
|
||||
|
||||
void CryptoPairKeys::setPublicKey(const QByteArray &publicKey) {
|
||||
_publicKey = publicKey;
|
||||
}
|
||||
|
||||
int CryptoPairKeys::bits() const {
|
||||
return _bits;
|
||||
}
|
||||
|
||||
void CryptoPairKeys::setBits(int bits) {
|
||||
_bits = bits;
|
||||
}
|
||||
|
||||
QDataStream &CryptoPairKeys::fromStream(QDataStream &stream) {
|
||||
|
||||
stream >> _publicKey;
|
||||
stream >> _privKey;
|
||||
stream >> _bits;
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
QDataStream &CryptoPairKeys::toStream(QDataStream &stream) const {
|
||||
stream << _publicKey;
|
||||
stream << _privKey;
|
||||
stream << _bits;
|
||||
|
||||
return stream;
|
||||
|
||||
}
|
||||
|
||||
bool operator ==(const CryptoPairKeys &left, const CryptoPairKeys &right) {
|
||||
return !(left != right);
|
||||
}
|
||||
|
||||
bool operator !=(const CryptoPairKeys &left, const CryptoPairKeys &right) {
|
||||
return left._privKey != right._privKey || left._publicKey != right._publicKey;
|
||||
}
|
||||
|
||||
uint qHash(const CryptoPairKeys &value) {
|
||||
return qHash(value.privKey());
|
||||
}
|
||||
|
||||
}
|
59
Heart/AbstractSpace/cryptopairkeys.h
Normal file
59
Heart/AbstractSpace/cryptopairkeys.h
Normal file
@ -0,0 +1,59 @@
|
||||
#ifndef CRYPTOPAIRKEYS_H
|
||||
#define CRYPTOPAIRKEYS_H
|
||||
|
||||
#include "streambase.h"
|
||||
|
||||
|
||||
namespace NP {
|
||||
|
||||
/**
|
||||
* @brief The CryptoPairKeys class contains pair keys.
|
||||
*/
|
||||
class NETWORKPROTOCOLSHARED_EXPORT CryptoPairKeys: public StreamBase
|
||||
{
|
||||
public:
|
||||
CryptoPairKeys();
|
||||
CryptoPairKeys(const QByteArray& pubKey, const QByteArray& privKey);
|
||||
|
||||
/**
|
||||
* @brief isValid
|
||||
* @return true if this objcet contains pair keys
|
||||
*/
|
||||
bool isValid() const;
|
||||
|
||||
QByteArray privKey() const;
|
||||
void setPrivKey(const QByteArray &privKey);
|
||||
|
||||
QByteArray publicKey() const;
|
||||
void setPublicKey(const QByteArray &publicKey);
|
||||
|
||||
/**
|
||||
* @brief bits
|
||||
* @return bits size of keys pair
|
||||
*/
|
||||
int bits() const;
|
||||
|
||||
/**
|
||||
* @brief setBits
|
||||
* @param bits
|
||||
*/
|
||||
void setBits(int bits);
|
||||
|
||||
friend bool operator != (const CryptoPairKeys& left, const CryptoPairKeys& right);
|
||||
friend bool operator == (const CryptoPairKeys& left, const CryptoPairKeys& right);
|
||||
|
||||
// StreamBase interface
|
||||
protected:
|
||||
QDataStream &fromStream(QDataStream &stream);
|
||||
QDataStream &toStream(QDataStream &stream) const;
|
||||
|
||||
private:
|
||||
QByteArray _privKey;
|
||||
QByteArray _publicKey;
|
||||
|
||||
int _bits;
|
||||
};
|
||||
|
||||
uint qHash(const CryptoPairKeys& value);
|
||||
}
|
||||
#endif // CRYPTOPAIRKEYS_H
|
19
Heart/AbstractSpace/datasender.cpp
Normal file
19
Heart/AbstractSpace/datasender.cpp
Normal file
@ -0,0 +1,19 @@
|
||||
#include "datasender.h"
|
||||
#include <QAbstractSocket>
|
||||
#include <quasarapp.h>
|
||||
#include <QThread>
|
||||
|
||||
namespace NP {
|
||||
|
||||
DataSender::DataSender() {
|
||||
}
|
||||
|
||||
void NP::DataSender::sendPackagePrivate(QByteArray array, void *target) const {
|
||||
auto ptr = static_cast<QAbstractSocket*>(target);
|
||||
if (array.size() != ptr->write(array)) {
|
||||
QuasarAppUtils::Params::log("not writed data to socket", QuasarAppUtils::Error);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
29
Heart/AbstractSpace/datasender.h
Normal file
29
Heart/AbstractSpace/datasender.h
Normal file
@ -0,0 +1,29 @@
|
||||
#ifndef DATASENDER_H
|
||||
#define DATASENDER_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class QAbstractSocket;
|
||||
|
||||
namespace NP {
|
||||
|
||||
/**
|
||||
* @brief The DataSender class - this class create a queue for sendet data to network.
|
||||
* work on a main thread
|
||||
*/
|
||||
class DataSender: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
DataSender();
|
||||
|
||||
public slots:
|
||||
/**
|
||||
* @brief sendPackagePrivate
|
||||
* @param array
|
||||
* @param target
|
||||
*/
|
||||
void sendPackagePrivate(QByteArray array, void *target) const;
|
||||
};
|
||||
}
|
||||
#endif // DATASENDER_H
|
32
Heart/AbstractSpace/header.cpp
Normal file
32
Heart/AbstractSpace/header.cpp
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "header.h"
|
||||
|
||||
#include <QString>
|
||||
|
||||
namespace NP {
|
||||
Header::Header() {
|
||||
reset();
|
||||
}
|
||||
|
||||
bool Header::isValid() const {
|
||||
return command && size && hash;
|
||||
}
|
||||
|
||||
void Header::reset() {
|
||||
size = 0;
|
||||
command = 0;
|
||||
triggerHash = 0;
|
||||
hash = 0;
|
||||
}
|
||||
|
||||
QString Header::toString() const {
|
||||
return QString("Header description: Size - %0, Command - %1, hash - %2, triggerHash - %3").
|
||||
arg(size).arg(command).arg(QString::number(hash, 16)).arg(QString::number(triggerHash, 16));
|
||||
}
|
||||
}
|
71
Heart/AbstractSpace/header.h
Normal file
71
Heart/AbstractSpace/header.h
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* 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 ABSTRACTHEADER_H
|
||||
#define ABSTRACTHEADER_H
|
||||
#include "heart_global.h"
|
||||
|
||||
|
||||
namespace NP {
|
||||
/**
|
||||
* @brief The Header struct 12 byte
|
||||
*/
|
||||
#pragma pack(push, 1)
|
||||
struct NETWORKPROTOCOLSHARED_EXPORT Header{
|
||||
/**
|
||||
* @brief size - size of package data (not header)
|
||||
*/
|
||||
unsigned short size;
|
||||
|
||||
/**
|
||||
* @brief command of pacage
|
||||
*/
|
||||
unsigned short command;
|
||||
|
||||
/**
|
||||
* @brief hash - is uniqueue id of a package. id calc with CRC32 function fo Qt implamentation. qHash(QByteArray)
|
||||
*/
|
||||
unsigned int hash;
|
||||
|
||||
/**
|
||||
* @brief triggerHash - this is hash of request package that this package has been responded
|
||||
* the server should write to which command it responds
|
||||
*/
|
||||
unsigned int triggerHash;
|
||||
|
||||
/**
|
||||
* @brief Header default constructor
|
||||
*/
|
||||
Header();
|
||||
~Header() = default;
|
||||
|
||||
/**
|
||||
* @brief isValid
|
||||
* @return true if header is valid
|
||||
*/
|
||||
bool isValid() const;
|
||||
|
||||
|
||||
/**
|
||||
* @brief reset - reset all data and set for header invalid status
|
||||
*/
|
||||
void reset();
|
||||
|
||||
/**
|
||||
* @brief toString - return string of header of package
|
||||
* @return
|
||||
*/
|
||||
QString toString() const;
|
||||
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif // ABSTRACTHEADER_H
|
60
Heart/AbstractSpace/hostaddress.cpp
Normal file
60
Heart/AbstractSpace/hostaddress.cpp
Normal file
@ -0,0 +1,60 @@
|
||||
#include "hostaddress.h"
|
||||
#include <QDataStream>
|
||||
#include <quasarapp.h>
|
||||
namespace NP {
|
||||
|
||||
HostAddress::HostAddress() {
|
||||
|
||||
}
|
||||
|
||||
HostAddress::HostAddress(const QHostAddress &other, int port):
|
||||
QHostAddress(other) {
|
||||
setPort(port);
|
||||
}
|
||||
|
||||
HostAddress::HostAddress(const QString &other, int port):
|
||||
QHostAddress(other) {
|
||||
setPort(port);
|
||||
}
|
||||
|
||||
HostAddress::HostAddress(const QHostAddress::SpecialAddress &other, int port):
|
||||
QHostAddress(other) {
|
||||
setPort(port);
|
||||
}
|
||||
|
||||
HostAddress::HostAddress(const HostAddress &other):
|
||||
QHostAddress(*static_cast<const HostAddress*>(&other)) {
|
||||
|
||||
setPort(other.port());
|
||||
}
|
||||
|
||||
unsigned short HostAddress::port() const {
|
||||
return _port;
|
||||
}
|
||||
|
||||
void HostAddress::setPort(unsigned short port) {
|
||||
debug_assert(port);
|
||||
|
||||
_port = port;
|
||||
}
|
||||
|
||||
QDataStream &operator >>(QDataStream &stream, HostAddress &address) {
|
||||
stream >> static_cast<QHostAddress&>(address);
|
||||
stream >> address._port;
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
QDataStream &operator <<(QDataStream &stream, const HostAddress &address) {
|
||||
|
||||
stream << static_cast<const QHostAddress&>(address);
|
||||
stream << address._port;
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
uint qHash(const HostAddress &address) {
|
||||
return qHash(QString("%1:%2").arg(address.toString()).arg(address.port()));
|
||||
}
|
||||
|
||||
}
|
39
Heart/AbstractSpace/hostaddress.h
Normal file
39
Heart/AbstractSpace/hostaddress.h
Normal file
@ -0,0 +1,39 @@
|
||||
#ifndef HOSTADDRESS_H
|
||||
#define HOSTADDRESS_H
|
||||
#include "heart_global.h"
|
||||
|
||||
#include <QHostAddress>
|
||||
#include "config.h"
|
||||
|
||||
namespace NP {
|
||||
|
||||
/**
|
||||
* @brief The HostAddress class - this is Wraper of QHostAddress
|
||||
*/
|
||||
class NETWORKPROTOCOLSHARED_EXPORT HostAddress: public QHostAddress
|
||||
{
|
||||
public:
|
||||
explicit HostAddress();
|
||||
explicit HostAddress(const QHostAddress& other, int port = DEFAULT_PORT);
|
||||
explicit HostAddress(const QString& other, int port = DEFAULT_PORT);
|
||||
HostAddress(const SpecialAddress& other, int port = DEFAULT_PORT);
|
||||
|
||||
HostAddress(const HostAddress& other);
|
||||
|
||||
|
||||
unsigned short port() const;
|
||||
void setPort(unsigned short port);
|
||||
|
||||
friend QDataStream& operator << (QDataStream& stream, const HostAddress& address);
|
||||
friend QDataStream& operator >> (QDataStream& stream, HostAddress& address);
|
||||
|
||||
private:
|
||||
unsigned short _port = 0;
|
||||
};
|
||||
|
||||
uint qHash(const HostAddress& address);
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(NP::HostAddress);
|
||||
|
||||
#endif // HOSTADDRESS_H
|
10
Heart/AbstractSpace/icrypto.cpp
Normal file
10
Heart/AbstractSpace/icrypto.cpp
Normal file
@ -0,0 +1,10 @@
|
||||
#include "icrypto.h"
|
||||
|
||||
|
||||
namespace NP {
|
||||
|
||||
ICrypto::ICrypto() = default;
|
||||
|
||||
ICrypto::~ICrypto() = default;
|
||||
|
||||
}
|
95
Heart/AbstractSpace/icrypto.h
Normal file
95
Heart/AbstractSpace/icrypto.h
Normal file
@ -0,0 +1,95 @@
|
||||
#ifndef ICRYPTO_H
|
||||
#define ICRYPTO_H
|
||||
|
||||
#include <QList>
|
||||
#include <QThread>
|
||||
#include "heart_global.h"
|
||||
#include <QByteArray>
|
||||
#include <QHash>
|
||||
#include <QSet>
|
||||
#define RAND_KEY ""
|
||||
|
||||
class QMutex;
|
||||
|
||||
namespace NP {
|
||||
|
||||
class CryptoPairKeys;
|
||||
|
||||
/**
|
||||
* @brief The ICrypto class provide cryptografu functionality.
|
||||
* this is interface for decaration of KeyStorage classes.
|
||||
*/
|
||||
class NETWORKPROTOCOLSHARED_EXPORT ICrypto
|
||||
{
|
||||
|
||||
public:
|
||||
ICrypto();
|
||||
virtual ~ICrypto();
|
||||
|
||||
/**
|
||||
* @brief isValid
|
||||
* @return true if the crypto object is valid.
|
||||
*/
|
||||
virtual bool isValid() const = 0;
|
||||
|
||||
|
||||
/**
|
||||
* @brief crypt
|
||||
* @param data - pointer to data array for crypting.
|
||||
* @note data as ben changed after call this method.
|
||||
* @param publicKey - key for crypting data
|
||||
* @return true if function finished seccussful
|
||||
*/
|
||||
virtual bool crypt(QByteArray *data, const QByteArray& publicKey) = 0;
|
||||
|
||||
/**
|
||||
* @brief decrypt
|
||||
* @param cryptedData - pointer to data array for decrypting.
|
||||
* @note cryptedData as ben changed after call this method.
|
||||
* @param privateKey
|
||||
* @return true if function finished seccussful
|
||||
*/
|
||||
virtual bool decrypt(QByteArray *cryptedData, const QByteArray& privateKey) = 0;
|
||||
|
||||
/**
|
||||
* @brief sign
|
||||
* @param data - pointer to data array for signed.
|
||||
* @note data as ben changed after call this method.
|
||||
* @param privateKey
|
||||
* @return true if function finished seccussful
|
||||
*/
|
||||
virtual bool sign(QByteArray* data, const QByteArray& privateKey) = 0;
|
||||
|
||||
/**
|
||||
* @brief extractSign - extract sign from signed byteArray
|
||||
* @param data - signed message.
|
||||
* @return return array of sign.
|
||||
*/
|
||||
virtual QByteArray extractSign(const QByteArray& data) = 0;
|
||||
|
||||
/**
|
||||
* @brief concatSign
|
||||
* @param data - message data
|
||||
* @return signed message
|
||||
*/
|
||||
virtual QByteArray concatSign(const QByteArray& data, const QByteArray& sign) = 0;
|
||||
|
||||
/**
|
||||
* @brief check
|
||||
* @param publicKey
|
||||
* @return true if function finished seccussful and signedData is valid.
|
||||
*/
|
||||
virtual bool check(const QByteArray& signedData, const QByteArray& publicKey) = 0;
|
||||
|
||||
/**
|
||||
* @brief generate a new key. Default implementation do nothing.
|
||||
* @note Override this method for create of new class with new keys type.
|
||||
* @param genesis
|
||||
* @return crypto pair keys
|
||||
*/
|
||||
virtual CryptoPairKeys generate(const QByteArray& genesis = {}) const = 0;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
#endif // CRYPTO_H
|
383
Heart/AbstractSpace/keystorage.cpp
Normal file
383
Heart/AbstractSpace/keystorage.cpp
Normal file
@ -0,0 +1,383 @@
|
||||
#include "cryptopairkeys.h"
|
||||
#include "icrypto.h"
|
||||
#include "keystorage.h"
|
||||
#include <quasarapp.h>
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QDataStream>
|
||||
#include <QDateTime>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QMutex>
|
||||
#include <QStandardPaths>
|
||||
#include "config.h"
|
||||
|
||||
namespace NP {
|
||||
|
||||
#define THE_CLASS(x) QString::fromLatin1(typeid(*x).name())
|
||||
#define VERSION_FILE "version"
|
||||
|
||||
KeyStorage::KeyStorage(ICrypto * cryptoMethod) {
|
||||
_keyPoolSizeMutex = new QMutex();
|
||||
_keysMutex = new QMutex();
|
||||
_taskMutex = new QMutex();
|
||||
|
||||
_cryptoMethod = cryptoMethod;
|
||||
|
||||
assert(_cryptoMethod);
|
||||
}
|
||||
|
||||
KeyStorage::~KeyStorage() {
|
||||
|
||||
stop();
|
||||
waitForThreadFinished(WAIT_TIME);
|
||||
|
||||
if (!saveStorage()) {
|
||||
QuasarAppUtils::Params::log("save keys to storae is failed!",
|
||||
QuasarAppUtils::Error);
|
||||
}
|
||||
|
||||
delete _keyPoolSizeMutex;
|
||||
delete _keysMutex;
|
||||
delete _taskMutex;
|
||||
delete _cryptoMethod;
|
||||
}
|
||||
|
||||
CryptoPairKeys KeyStorage::getNextPair(const QString &accsessKey,
|
||||
const QByteArray& genesis,
|
||||
int timeout) {
|
||||
|
||||
if (!isInited() && genesis == RAND_KEY) {
|
||||
QuasarAppUtils::Params::log("You want get the random crypto keys pair in a not initialized crypto object.",
|
||||
QuasarAppUtils::Error);
|
||||
return CryptoPairKeys{};
|
||||
}
|
||||
|
||||
if (_keyPoolSize <= 0) {
|
||||
return CryptoPairKeys{};
|
||||
}
|
||||
|
||||
if (!genKey(accsessKey, genesis)) {
|
||||
return {};
|
||||
}
|
||||
|
||||
start();
|
||||
|
||||
if (!waitForGeneratekey(accsessKey, timeout)) {
|
||||
return CryptoPairKeys{};
|
||||
}
|
||||
|
||||
QMutexLocker locker(_keysMutex);
|
||||
|
||||
return _keys.value(accsessKey, {});
|
||||
}
|
||||
|
||||
int KeyStorage::getKeyPoolSize() const {
|
||||
return _keyPoolSize;
|
||||
}
|
||||
|
||||
void KeyStorage::setKeyPoolSize(int keyPoolSize) {
|
||||
_keyPoolSizeMutex->lock();
|
||||
_keyPoolSize = keyPoolSize;
|
||||
_keyPoolSizeMutex->unlock();
|
||||
|
||||
start();
|
||||
}
|
||||
|
||||
bool KeyStorage::isValid() const {
|
||||
return isInited();
|
||||
}
|
||||
|
||||
bool KeyStorage::isInited() const {
|
||||
return _inited;
|
||||
}
|
||||
|
||||
bool KeyStorage::crypt(QByteArray *data, const QByteArray &publicKey) {
|
||||
return _cryptoMethod->crypt(data, publicKey);
|
||||
}
|
||||
|
||||
bool KeyStorage::decrypt(QByteArray *cryptedData, const QByteArray &privateKey) {
|
||||
return _cryptoMethod->decrypt(cryptedData, privateKey);
|
||||
}
|
||||
|
||||
bool KeyStorage::sign(QByteArray *data, const QByteArray &privateKey) {
|
||||
return _cryptoMethod->sign(data, privateKey);
|
||||
}
|
||||
|
||||
QByteArray KeyStorage::extractSign(const QByteArray &data) {
|
||||
return _cryptoMethod->extractSign(data);
|
||||
}
|
||||
|
||||
QByteArray KeyStorage::concatSign(const QByteArray &data, const QByteArray &sign) {
|
||||
return _cryptoMethod->concatSign(data, sign);
|
||||
}
|
||||
|
||||
bool KeyStorage::check(const QByteArray &signedData, const QByteArray &publicKey) {
|
||||
return _cryptoMethod->check(signedData, publicKey);
|
||||
}
|
||||
|
||||
void KeyStorage::setGenesisList(const QList<QByteArray>& list) {
|
||||
_keysMutex->lock();
|
||||
for (const auto& i : list) {
|
||||
_keys.insert(i, {});
|
||||
}
|
||||
_keysMutex->unlock();
|
||||
|
||||
start();
|
||||
}
|
||||
|
||||
bool KeyStorage::toStorage(const QString &key) const {
|
||||
|
||||
if (!isValid())
|
||||
return false;
|
||||
|
||||
_keysMutex->lock();
|
||||
CryptoPairKeys value = _keys.value(key);
|
||||
_keysMutex->unlock();
|
||||
|
||||
auto filePath = storageLocation() + "/" + key;
|
||||
|
||||
QFile file(filePath);
|
||||
|
||||
if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
file.setPermissions(QFile::Permission::ReadOwner | QFile::Permission::WriteOwner);
|
||||
|
||||
QDataStream stream(&file);
|
||||
|
||||
stream << value;
|
||||
|
||||
file.close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool KeyStorage::fromStorage(const QByteArray &key) {
|
||||
auto filePath = storageLocation() + "/" + key;
|
||||
|
||||
QFile file(filePath);
|
||||
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QDataStream stream(&file);
|
||||
|
||||
CryptoPairKeys value;
|
||||
stream >> value;
|
||||
|
||||
file.close();
|
||||
|
||||
_keys.insert(key, value);
|
||||
|
||||
return value.isValid();
|
||||
}
|
||||
|
||||
void KeyStorage::generateKeysByTasks() {
|
||||
_taskMutex->lock();
|
||||
auto tasks = _generateTasks;
|
||||
_taskMutex->unlock();
|
||||
|
||||
for (auto it = tasks.begin(); it != tasks.end(); ++it) {
|
||||
|
||||
if (_stopGenerator) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto& value = _keys.value(it.key());
|
||||
if (!value.isValid()) {
|
||||
|
||||
_keysMutex->lock();
|
||||
|
||||
if (it.value() == RAND_KEY && _randomKeysPool.size()) {
|
||||
_keys[it.key()] = *_randomKeysPool.begin();
|
||||
_randomKeysPool.erase(_randomKeysPool.begin());
|
||||
} else {
|
||||
_keys[it.key()] = _cryptoMethod->generate(it.value());
|
||||
}
|
||||
|
||||
_keysMutex->unlock();
|
||||
|
||||
}
|
||||
|
||||
_taskMutex->lock();
|
||||
_generateTasks.remove(it.key());
|
||||
_taskMutex->unlock();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void KeyStorage::generateRandomKeys() {
|
||||
_keyPoolSizeMutex->lock();
|
||||
int size = _keyPoolSize;
|
||||
_keyPoolSizeMutex->unlock();
|
||||
|
||||
while (size > _randomKeysPool.size()) {
|
||||
|
||||
if ((_stopGenerator))
|
||||
return;
|
||||
|
||||
auto &&keys = _cryptoMethod->generate();
|
||||
|
||||
_keysMutex->lock();
|
||||
_randomKeysPool.insert(keys);
|
||||
_keysMutex->unlock();
|
||||
}
|
||||
}
|
||||
|
||||
void KeyStorage::run() {
|
||||
|
||||
if (_stopGenerator) {
|
||||
return;
|
||||
}
|
||||
|
||||
_keyPoolSizeMutex->lock();
|
||||
int keyPoolSize = _keyPoolSize;
|
||||
_keyPoolSizeMutex->unlock();
|
||||
|
||||
while ((_generateTasks.size() || keyPoolSize > _randomKeysPool.size())
|
||||
&& !_stopGenerator) {
|
||||
|
||||
generateKeysByTasks();
|
||||
generateRandomKeys();
|
||||
|
||||
_keyPoolSizeMutex->lock();
|
||||
keyPoolSize = _keyPoolSize;
|
||||
_keyPoolSizeMutex->unlock();
|
||||
}
|
||||
}
|
||||
|
||||
void KeyStorage::stop() {
|
||||
_stopGenerator = true;
|
||||
}
|
||||
|
||||
bool KeyStorage::waitForGeneratekey(const QString& key, int timeout) const {
|
||||
return waitFor([this, &key](){return _keys.contains(key);}, timeout);
|
||||
}
|
||||
|
||||
bool KeyStorage::waitForThreadFinished(int timeout) const {
|
||||
return waitFor([this](){return !isRunning();}, timeout);
|
||||
}
|
||||
|
||||
bool KeyStorage::waitFor(const std::function<bool()> &checkFunc, int timeout) const {
|
||||
auto waitFor = timeout + QDateTime::currentMSecsSinceEpoch();
|
||||
while (!checkFunc() && waitFor > QDateTime::currentMSecsSinceEpoch()) {
|
||||
QCoreApplication::processEvents();
|
||||
}
|
||||
|
||||
return checkFunc();
|
||||
}
|
||||
|
||||
void KeyStorage::loadAllKeysFromStorage() {
|
||||
auto list = QDir(storageLocation()).entryInfoList(QDir::Files | QDir::NoDotAndDotDot);
|
||||
|
||||
for (const auto& file: list ) {
|
||||
if (file.fileName() != VERSION_FILE) {
|
||||
fromStorage(file.fileName().toLatin1());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool KeyStorage::saveStorage() const {
|
||||
|
||||
bool result = true;
|
||||
for (auto it = _keys.begin(); it != _keys.end(); ++it) {
|
||||
result = result && toStorage(it.key());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool KeyStorage::genKey(const QString &accessKey, const QByteArray &genesis) {
|
||||
|
||||
if (accessKey.isEmpty())
|
||||
return false;
|
||||
|
||||
QMutexLocker locker(_taskMutex);
|
||||
_generateTasks.insert(accessKey, genesis);
|
||||
return true;
|
||||
}
|
||||
|
||||
QString KeyStorage::storageLocation() const {
|
||||
return _storageLocation;
|
||||
}
|
||||
|
||||
bool KeyStorage::initStorageLocation(const QString &value) {
|
||||
QFile version(value + "/" + VERSION_FILE);
|
||||
|
||||
if (!QFile::exists(value)) {
|
||||
|
||||
if (!QDir().mkpath(value)) {
|
||||
QuasarAppUtils::Params::log(" fail to create a key storagge. Into "
|
||||
+ value, QuasarAppUtils::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
QFile::setPermissions(value,
|
||||
QFile::Permission::ExeOwner |
|
||||
QFile::Permission::ReadOwner |
|
||||
QFile::Permission::WriteOwner);
|
||||
|
||||
QFile version(value + "/" + VERSION_FILE);
|
||||
|
||||
if (!version.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QDataStream stream(&version);
|
||||
stream << THE_CLASS(_cryptoMethod);
|
||||
version.close();
|
||||
|
||||
} else {
|
||||
|
||||
if (!version.open(QIODevice::ReadOnly)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QDataStream stream(&version);
|
||||
QString versionName;
|
||||
stream >> versionName;
|
||||
version.close();
|
||||
|
||||
if (THE_CLASS(_cryptoMethod) != versionName) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
_storageLocation = value;
|
||||
|
||||
return _storageLocation.size();
|
||||
|
||||
}
|
||||
|
||||
bool KeyStorage::initDefaultStorageLocation(const QString &dirName) {
|
||||
auto storageLoation =
|
||||
QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) +
|
||||
"/" + dirName;
|
||||
|
||||
if (dirName.isEmpty()) {
|
||||
storageLoation += THE_CLASS(_cryptoMethod);
|
||||
}
|
||||
|
||||
storageLoation += "/crypto/";
|
||||
|
||||
if (!initStorageLocation(storageLoation)) {
|
||||
QuasarAppUtils::Params::log("CryptoStorage not inited",
|
||||
QuasarAppUtils::Error);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
loadAllKeysFromStorage();
|
||||
|
||||
return _inited = true;
|
||||
}
|
||||
|
||||
void KeyStorage::clearStorage() const {
|
||||
QDir::root().remove(storageLocation());
|
||||
}
|
||||
|
||||
}
|
246
Heart/AbstractSpace/keystorage.h
Normal file
246
Heart/AbstractSpace/keystorage.h
Normal file
@ -0,0 +1,246 @@
|
||||
#ifndef KEYSTORAGE_H
|
||||
#define KEYSTORAGE_H
|
||||
|
||||
#include <QList>
|
||||
#include <QThread>
|
||||
#include "heart_global.h"
|
||||
#include <QByteArray>
|
||||
#include <QHash>
|
||||
#include <QSet>
|
||||
#include "config.h"
|
||||
|
||||
#define RAND_KEY ""
|
||||
|
||||
class QMutex;
|
||||
|
||||
|
||||
namespace NP {
|
||||
|
||||
class CryptoPairKeys;
|
||||
class ICrypto;
|
||||
/**
|
||||
* @brief The KeyStorage class - this class provie the functionality of controll crypto keys (generate, save, write);
|
||||
*/
|
||||
class KeyStorage: public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
/**
|
||||
* @brief KeyStorage
|
||||
* @param cryptoMethod - any class inherited from ICrypto
|
||||
*/
|
||||
KeyStorage(ICrypto* cryptoMethod);
|
||||
~KeyStorage();
|
||||
|
||||
/**
|
||||
* @brief getNextPair - take a one pair key from keys pool.
|
||||
* @warning If key pool is empty then this method frease a current thread for awiting f neg generated pair key.
|
||||
* @note if the key is not generated within the specified period of time, an invalid copy of the key pair will be returned.
|
||||
* @param accsessKey - the byte array for get a acceses to key from storage.
|
||||
* @param genesis - set this params to empty for get random key pair or set the byte array for get a key pair for genesis array.
|
||||
* @param timeout_msec - timeout in milisecunds. default is WAIT_TIME (30000)
|
||||
* @return pair of keys.
|
||||
*/
|
||||
CryptoPairKeys getNextPair(const QString &accsessKey,
|
||||
const QByteArray &genesis = RAND_KEY,
|
||||
int timeout_msec = WAIT_TIME);
|
||||
|
||||
/**
|
||||
* @brief getKeyPoolSize
|
||||
* @return
|
||||
*/
|
||||
int getKeyPoolSize() const;
|
||||
|
||||
/**
|
||||
* @brief setKeyPoolSize
|
||||
* @param keyPoolSize
|
||||
*/
|
||||
void setKeyPoolSize(int keyPoolSize);
|
||||
|
||||
/**
|
||||
* @brief isValid
|
||||
* @return true if the crypto object is valid.
|
||||
*/
|
||||
virtual bool isValid() const;
|
||||
|
||||
/**
|
||||
* @brief isInited
|
||||
* @return true if the crypto object has been initialized.
|
||||
*/
|
||||
virtual bool isInited() const;
|
||||
|
||||
/**
|
||||
* @brief crypt
|
||||
* @param data - pointer to data array for crypting.
|
||||
* @note data as ben changed after call this method.
|
||||
* @param publicKey - key for crypting data
|
||||
* @return true if function finished seccussful
|
||||
*/
|
||||
bool crypt(QByteArray *data, const QByteArray& publicKey);
|
||||
|
||||
/**
|
||||
* @brief decrypt
|
||||
* @param cryptedData - pointer to data array for decrypting.
|
||||
* @note cryptedData as ben changed after call this method.
|
||||
* @param privateKey
|
||||
* @return true if function finished seccussful
|
||||
*/
|
||||
bool decrypt(QByteArray *cryptedData, const QByteArray& privateKey);
|
||||
|
||||
/**
|
||||
* @brief sign
|
||||
* @param data - pointer to data array for signed.
|
||||
* @note data as ben changed after call this method.
|
||||
* @param privateKey
|
||||
* @return true if function finished seccussful
|
||||
*/
|
||||
bool sign(QByteArray* data, const QByteArray& privateKey);
|
||||
|
||||
/**
|
||||
* @brief extractSign - extract sign from signed byteArray
|
||||
* @param data - signed message.
|
||||
* @return return array of sign.
|
||||
*/
|
||||
QByteArray extractSign(const QByteArray& data);
|
||||
|
||||
/**
|
||||
* @brief concatSign
|
||||
* @param data - message data
|
||||
* @return signed message
|
||||
*/
|
||||
QByteArray concatSign(const QByteArray& data, const QByteArray& sign);
|
||||
|
||||
/**
|
||||
* @brief check
|
||||
* @param publicKey
|
||||
* @return true if function finished seccussful and signedData is valid.
|
||||
*/
|
||||
bool check(const QByteArray& signedData, const QByteArray& publicKey);
|
||||
|
||||
/**
|
||||
* @brief setGenesisList - set genesis list for generation key pairs
|
||||
*/
|
||||
void setGenesisList(const QList<QByteArray> &list);
|
||||
|
||||
/**
|
||||
* @brief storageLocation
|
||||
* @default QStandardPaths::DataLocation/KeysStorage
|
||||
* @return parth to storage location of crypto keys
|
||||
*/
|
||||
QString storageLocation() const;
|
||||
|
||||
/**
|
||||
* @brief initStorageLocation set a new path for storage location of keys.
|
||||
* @param value - new path
|
||||
*/
|
||||
bool initStorageLocation(const QString &value);
|
||||
|
||||
/**
|
||||
* @brief initDefaultStorageLocation - the some as initStorageLocation, but set default
|
||||
* path.
|
||||
* @param dirName - it is name of storage location. If This parametr weel be empty then
|
||||
* storage location set default dir name. By default is name of crypto class.
|
||||
* @default default path of storage is '/QStandardPaths::AppDataLocation/crypto/dirName'
|
||||
* @return true if the storage inited successful
|
||||
*/
|
||||
bool initDefaultStorageLocation(const QString& dirName = "");
|
||||
|
||||
/**
|
||||
* @brief clearStorage
|
||||
*/
|
||||
void clearStorage() const;
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* @brief toStorage - save key from genesis into local storage.
|
||||
* @param genesis - genesis of key pair
|
||||
* @note override this method if you want to change storage location or method of save of keys.
|
||||
* @return true if key saved successful
|
||||
*/
|
||||
virtual bool toStorage(const QString &genesis) const;
|
||||
|
||||
/**
|
||||
* @brief fromStorage - load keys from local storage
|
||||
* @param genesis - genesis of key pair
|
||||
* @return true if key pair saved seccussful.
|
||||
*/
|
||||
virtual bool fromStorage(const QByteArray& key);
|
||||
|
||||
/**
|
||||
* @brief run - start the key generator.
|
||||
*/
|
||||
void run() override;
|
||||
|
||||
/**
|
||||
* @brief stop - stop generate keys.
|
||||
*/
|
||||
void stop();
|
||||
private:
|
||||
|
||||
/**
|
||||
* @brief waitForGeneratekey
|
||||
* @param timeout - maximum time for generation new key. by default = WAIT_TIME (30000)
|
||||
* @return true if key generated successful
|
||||
*/
|
||||
bool waitForGeneratekey(const QString &key, int timeout = WAIT_TIME) const;
|
||||
|
||||
/**
|
||||
* @brief waitForThreadFinished
|
||||
* @param timeout
|
||||
* @return
|
||||
*/
|
||||
bool waitForThreadFinished(int timeout = WAIT_TIME) const;
|
||||
|
||||
/**
|
||||
* @brief waitFor - base waint function
|
||||
* @param checkFunc - this is lyambda of check event
|
||||
* @param timeout - maximu time line of waiting of event
|
||||
* @return true if event is checkFunc return true
|
||||
*/
|
||||
bool waitFor(const std::function<bool()>& checkFunc, int timeout) const;
|
||||
|
||||
/**
|
||||
* @brief loadAllKeysFromStorage
|
||||
*/
|
||||
void loadAllKeysFromStorage();
|
||||
|
||||
/**
|
||||
* @brief saveStorage
|
||||
* @return true if all keys has been saved in a storage.
|
||||
*/
|
||||
bool saveStorage() const;
|
||||
|
||||
/**
|
||||
* @brief genKey - this method add a new task for generate keys pair
|
||||
* @param accessKey - the byte array for get access of the keys pair.
|
||||
* @param genesis - the byte array for generate new key
|
||||
* @note If access key well be empty then this method return false.
|
||||
* @note for generate random key use a RAND_KEY genesis or empty value.
|
||||
* @return true if task of generation a new pair keys added seccussful else false.
|
||||
*/
|
||||
bool genKey(const QString &accessKey, const QByteArray& genesis = RAND_KEY);
|
||||
|
||||
QHash<QString, CryptoPairKeys> _keys;
|
||||
QSet<CryptoPairKeys> _randomKeysPool;
|
||||
|
||||
QHash<QString, QByteArray> _generateTasks;
|
||||
|
||||
int _keyPoolSize = 1;
|
||||
|
||||
QMutex *_keyPoolSizeMutex = nullptr;
|
||||
QMutex *_keysMutex = nullptr;
|
||||
QMutex *_taskMutex = nullptr;
|
||||
|
||||
QString _storageLocation;
|
||||
|
||||
bool _inited = false;
|
||||
bool _stopGenerator = false;
|
||||
|
||||
ICrypto *_cryptoMethod = nullptr;
|
||||
|
||||
void generateKeysByTasks();
|
||||
void generateRandomKeys();
|
||||
};
|
||||
}
|
||||
#endif // KEYSTORAGE_H
|
78
Heart/AbstractSpace/package.cpp
Normal file
78
Heart/AbstractSpace/package.cpp
Normal file
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "abstractdata.h"
|
||||
#include "package.h"
|
||||
|
||||
#include <QDataStream>
|
||||
|
||||
namespace NP {
|
||||
|
||||
Package::Package() {
|
||||
reset();
|
||||
}
|
||||
|
||||
bool Package::isValid() const {
|
||||
if (!hdr.isValid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto rawint = data.mid(0, sizeof (decltype (hdr.command)));
|
||||
decltype (hdr.command) cmd;
|
||||
memcpy(&cmd, rawint.data(), sizeof (cmd));
|
||||
|
||||
if (data.size() && hdr.command != cmd) {
|
||||
std::reverse(rawint.begin(), rawint.end());
|
||||
memcpy(&cmd, rawint.data(), sizeof (cmd));
|
||||
|
||||
if (hdr.command != cmd)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (hdr.size != data.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return qHash(data) == hdr.hash;
|
||||
}
|
||||
|
||||
void Package::reset() {
|
||||
hdr.reset();
|
||||
data.clear();
|
||||
}
|
||||
|
||||
QString Package::toString() const {
|
||||
return QString("Pakcage description: %0."
|
||||
" Data description: Data size - %1, Data: %2").
|
||||
arg(hdr.toString()).arg(data.size()).arg(QString(data.toHex().toUpper()));
|
||||
}
|
||||
|
||||
QDataStream &Package::fromStream(QDataStream &stream) {
|
||||
reset();
|
||||
stream.readRawData(reinterpret_cast<char*>(&hdr), sizeof(Header));
|
||||
|
||||
char * buf = static_cast<char*>(malloc(hdr.size));
|
||||
stream.readRawData(buf, hdr.size);
|
||||
data.clear();
|
||||
data.insert(0, buf, hdr.size);
|
||||
|
||||
free(buf);
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
QDataStream &Package::toStream(QDataStream &stream) const {
|
||||
stream.writeRawData(reinterpret_cast<const char*>(&hdr),
|
||||
sizeof (hdr));
|
||||
|
||||
stream.writeRawData(data.data(),
|
||||
data.size());
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
}
|
@ -1,9 +1,17 @@
|
||||
/*
|
||||
* 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 ABSTRACTPACKAGE_H
|
||||
#define ABSTRACTPACKAGE_H
|
||||
#include "header.h"
|
||||
#include "networkprotocol_global.h"
|
||||
#include "heart_global.h"
|
||||
|
||||
#include <QByteArray>
|
||||
#include <baseid.h>
|
||||
|
||||
namespace NP {
|
||||
|
||||
@ -11,7 +19,9 @@ class Abstract;
|
||||
/**
|
||||
* @brief The Package struct
|
||||
*/
|
||||
struct NETWORKPROTOCOLSHARED_EXPORT Package {
|
||||
class NETWORKPROTOCOLSHARED_EXPORT Package: public StreamBase {
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief hdr - header of package
|
||||
*/
|
||||
@ -22,6 +32,7 @@ struct NETWORKPROTOCOLSHARED_EXPORT Package {
|
||||
QByteArray data;
|
||||
|
||||
Package();
|
||||
virtual ~Package() = default;
|
||||
|
||||
/**
|
||||
* @brief isValid
|
||||
@ -29,24 +40,21 @@ struct NETWORKPROTOCOLSHARED_EXPORT Package {
|
||||
*/
|
||||
virtual bool isValid() const;
|
||||
|
||||
/**
|
||||
* @brief toBytes
|
||||
* @return bytes array of packag
|
||||
*/
|
||||
virtual QByteArray toBytes() const;
|
||||
|
||||
/**
|
||||
* @brief fromBytes
|
||||
* @return bytes array to packag
|
||||
*/
|
||||
virtual void fromBytes(const QByteArray &array);
|
||||
/**
|
||||
* @brief reset - reset all data and set for package invalid status
|
||||
*/
|
||||
virtual void reset();
|
||||
|
||||
virtual ~Package() = default;
|
||||
/**
|
||||
* @brief toString - convert pakcage information to string label
|
||||
* @return string
|
||||
*/
|
||||
QString toString() const;
|
||||
|
||||
// StreamBase interface
|
||||
protected:
|
||||
QDataStream &fromStream(QDataStream &stream) override;
|
||||
QDataStream &toStream(QDataStream &stream) const override;
|
||||
};
|
||||
|
||||
}
|
59
Heart/AbstractSpace/packagemanager.cpp
Normal file
59
Heart/AbstractSpace/packagemanager.cpp
Normal file
@ -0,0 +1,59 @@
|
||||
#include "packagemanager.h"
|
||||
|
||||
#include <package.h>
|
||||
#include <ctime>
|
||||
#include <config.h>
|
||||
|
||||
namespace NP {
|
||||
|
||||
PackageManager::PackageManager()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
PackageManager::~PackageManager() {
|
||||
for (const auto& data : _parseResults) {
|
||||
delete data;
|
||||
}
|
||||
|
||||
_parseResults.clear();
|
||||
}
|
||||
|
||||
const Package *PackageManager::getPkgFromArhive(const unsigned int &id) const {
|
||||
if (!contains(id))
|
||||
return nullptr;
|
||||
|
||||
QMutexLocker lock(&_processMutex);
|
||||
return _parseResults.value(id)->_data;
|
||||
}
|
||||
|
||||
bool PackageManager::contains(const unsigned int &id) const {
|
||||
QMutexLocker lock(&_processMutex);
|
||||
return _parseResults.contains(id);
|
||||
}
|
||||
|
||||
void PackageManager::processed(const Package &pkg, char processResult) {
|
||||
|
||||
if (!pkg.hdr.hash || !PACKAGE_CACHE_SIZE) {
|
||||
return;
|
||||
}
|
||||
|
||||
QMutexLocker lock(&_processMutex);
|
||||
|
||||
if (_parseResults.size() > PACKAGE_CACHE_SIZE) {
|
||||
_processTime.erase(_processTime.begin());
|
||||
}
|
||||
|
||||
_parseResults.insert(pkg.hdr.hash, new PackaData {
|
||||
processResult,
|
||||
new Package(pkg)
|
||||
});
|
||||
|
||||
_processTime.insert(static_cast<int>(time(0)), pkg.hdr.hash);
|
||||
}
|
||||
|
||||
PackageManager::PackaData::~PackaData() {
|
||||
delete _data;
|
||||
}
|
||||
|
||||
}
|
58
Heart/AbstractSpace/packagemanager.h
Normal file
58
Heart/AbstractSpace/packagemanager.h
Normal file
@ -0,0 +1,58 @@
|
||||
#ifndef PAKCAGEMANAGER_H
|
||||
#define PAKCAGEMANAGER_H
|
||||
|
||||
#include <QMutex>
|
||||
#include <QSharedDataPointer>
|
||||
#include <baseid.h>
|
||||
|
||||
|
||||
namespace NP {
|
||||
|
||||
/**
|
||||
* @brief The PakcageManager class - contains all processed packages
|
||||
*/
|
||||
class PackageManager
|
||||
{
|
||||
public:
|
||||
PackageManager();
|
||||
~PackageManager();
|
||||
|
||||
/**
|
||||
* @brief getPkgFromArhive - return pointer tot package from arhive.
|
||||
* @param id - id of the requariment package.
|
||||
* @result pointer of the processed package, if package not return nullpt
|
||||
*/
|
||||
const Package * getPkgFromArhive(const unsigned int &id) const;
|
||||
|
||||
/**
|
||||
* @brief contains - check packge by id
|
||||
* @param id
|
||||
* @return true if pakcge has been parsed
|
||||
*/
|
||||
bool contains(const unsigned int& id) const;
|
||||
|
||||
/**
|
||||
* @brief processed - add package to arhice
|
||||
* @param pkg - object of package
|
||||
* @param processResult - result of method parsePackage.
|
||||
*/
|
||||
void processed(const Package& pkg, char processResult);
|
||||
private:
|
||||
/**
|
||||
* @brief The PackaData struct - private data of packages
|
||||
*/
|
||||
struct PackaData {
|
||||
char _parseResult;
|
||||
Package *_data = nullptr;
|
||||
|
||||
~PackaData();
|
||||
};
|
||||
|
||||
QMultiMap<int, unsigned int> _processTime;
|
||||
QHash<unsigned int, const PackaData*> _parseResults;
|
||||
|
||||
mutable QMutex _processMutex;
|
||||
};
|
||||
|
||||
}
|
||||
#endif // PAKCAGEMANAGER_H
|
107
Heart/AbstractSpace/packages/abstractdata.cpp
Normal file
107
Heart/AbstractSpace/packages/abstractdata.cpp
Normal file
@ -0,0 +1,107 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "abstractdata.h"
|
||||
#include <QDataStream>
|
||||
#include <QMap>
|
||||
#include <typeinfo>
|
||||
#include "heart.h"
|
||||
#include <limits>
|
||||
#include <quasarapp.h>
|
||||
#include <QCryptographicHash>
|
||||
|
||||
namespace NP {
|
||||
|
||||
unsigned short AbstractData::cmd() const {
|
||||
return _cmd;
|
||||
}
|
||||
|
||||
void AbstractData::setCmd(unsigned short cmd) {
|
||||
_cmd = cmd;
|
||||
}
|
||||
|
||||
bool AbstractData::init() {
|
||||
if (typeid (*this).hash_code() == typeid(AbstractData).hash_code())
|
||||
return false;
|
||||
|
||||
generateCmd();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void AbstractData::generateCmd() {
|
||||
setCmd(H_16(*this));
|
||||
}
|
||||
|
||||
AbstractData::AbstractData() {
|
||||
_cmd = 0;
|
||||
}
|
||||
|
||||
bool AbstractData::fromBytes(const QByteArray &data) {
|
||||
return StreamBase::fromBytes(data);
|
||||
}
|
||||
|
||||
QByteArray AbstractData::toBytes() const {
|
||||
return StreamBase::toBytes();
|
||||
}
|
||||
|
||||
bool AbstractData::toPackage(Package &package,
|
||||
unsigned int triggerHash) const {
|
||||
|
||||
if (!isValid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
package.data = toBytes();
|
||||
|
||||
package.hdr.command = _cmd;
|
||||
package.hdr.triggerHash = triggerHash;
|
||||
package.hdr.size = static_cast<unsigned short>(package.data.size());
|
||||
package.hdr.hash = qHash(package.data);
|
||||
|
||||
return package.isValid();
|
||||
}
|
||||
|
||||
QDataStream &AbstractData::fromStream(QDataStream &stream) {
|
||||
stream >> _cmd;
|
||||
return stream;
|
||||
}
|
||||
|
||||
QDataStream &AbstractData::toStream(QDataStream &stream) const {
|
||||
stream << _cmd;
|
||||
return stream;
|
||||
}
|
||||
|
||||
bool AbstractData::isValid() const {
|
||||
return _cmd;
|
||||
}
|
||||
|
||||
bool AbstractData::copyFrom(const AbstractData *other) {
|
||||
|
||||
return other;
|
||||
}
|
||||
|
||||
QString AbstractData::toString() const {
|
||||
return QString("Object: type:%0, command:%1").
|
||||
arg(typeid(*this).name()).
|
||||
arg(_cmd);
|
||||
}
|
||||
|
||||
bool AbstractData::prepareToSend() {
|
||||
if (isValid()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return init();
|
||||
}
|
||||
|
||||
AbstractData::~AbstractData() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
141
Heart/AbstractSpace/packages/abstractdata.h
Normal file
141
Heart/AbstractSpace/packages/abstractdata.h
Normal file
@ -0,0 +1,141 @@
|
||||
/*
|
||||
* 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 ABSTRACTDATA_H
|
||||
#define ABSTRACTDATA_H
|
||||
#include "package.h"
|
||||
#include <streambase.h>
|
||||
#include <global.h>
|
||||
|
||||
namespace NP {
|
||||
|
||||
/**
|
||||
* @brief The AbstractData class
|
||||
* all data packages inherited this class.
|
||||
*/
|
||||
class NETWORKPROTOCOLSHARED_EXPORT AbstractData : public StreamBase
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~AbstractData() override;
|
||||
|
||||
/**
|
||||
* @brief cmd
|
||||
* @return command of package
|
||||
*/
|
||||
unsigned short cmd() const;
|
||||
|
||||
/**
|
||||
* @brief toBytes
|
||||
* @return byte array for package
|
||||
*/
|
||||
QByteArray toBytes() const;
|
||||
|
||||
|
||||
/**
|
||||
* @brief toPackage
|
||||
* @param package - return value
|
||||
* @param trigeredCommand - old cmd
|
||||
* @return retorn package object created from this object.
|
||||
*/
|
||||
bool toPackage(Package &package, unsigned int triggerHash = 0) const;
|
||||
|
||||
/**
|
||||
* @brief isValid
|
||||
* @return true if class isValid
|
||||
*/
|
||||
virtual bool isValid() const;
|
||||
|
||||
/**
|
||||
* @brief copyFrom this function try cast other object to this class type
|
||||
* and invoke copy operation. cmd option is ignored;
|
||||
* @param other
|
||||
* @return true if all good
|
||||
*/
|
||||
virtual bool copyFrom(const AbstractData*);
|
||||
|
||||
/**
|
||||
* @brief toString - return a string implementation fo this object
|
||||
* @return string of object
|
||||
*/
|
||||
virtual QString toString() const;
|
||||
|
||||
/**
|
||||
* @brief prepareToSend - this method check object to valid and if an object is invalid invoke method init.
|
||||
* @return return true if the object prepared for sending.
|
||||
*/
|
||||
bool prepareToSend();
|
||||
|
||||
/**
|
||||
* @brief create - this is factory method for create a new object with some type that parent object.
|
||||
* @param args - list of arguments for create object
|
||||
* @return pointer toObject
|
||||
*/
|
||||
template<class C, class... Args>
|
||||
C* create(Args&&... args) const {
|
||||
C* object = new C(std::forward<Args>(args)...);
|
||||
object->generateCmd();
|
||||
return object;
|
||||
}
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief AbstractData
|
||||
*/
|
||||
explicit AbstractData();
|
||||
|
||||
/**
|
||||
* @brief fromBytes - private initialisation of object from byte array
|
||||
* @return true if all good
|
||||
*/
|
||||
bool fromBytes(const QByteArray&);
|
||||
|
||||
/**
|
||||
* @brief setCmd
|
||||
* @param cmd
|
||||
*/
|
||||
void setCmd(unsigned short cmd);
|
||||
|
||||
/**
|
||||
* @brief init - this method need to invoke after create object for initialize all componet of ojects.
|
||||
* @note do not invode this method on constructor of object, becose object wel be initialized not correctly.
|
||||
* @default defaul implementation of object init _com of object.
|
||||
* @return true if object initialized correctly.
|
||||
*/
|
||||
virtual bool init();
|
||||
|
||||
|
||||
/**
|
||||
* @brief fromStream
|
||||
* @param stream
|
||||
* @return stream
|
||||
*/
|
||||
QDataStream& fromStream(QDataStream& stream) override;
|
||||
|
||||
/**
|
||||
* @brief toStream
|
||||
* @param stream
|
||||
* @return stream
|
||||
*/
|
||||
QDataStream& toStream(QDataStream& stream) const override;
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief generateCmd set cmd from class name.
|
||||
* @note call this method only after create objects. do not call in constructor of class.
|
||||
*/
|
||||
void generateCmd();
|
||||
/**
|
||||
* @brief _cmd - unique id of class using in Header of package for identification.
|
||||
*/
|
||||
unsigned short _cmd = 0;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif // ABSTRACTDATA_H
|
@ -1,3 +1,10 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "badrequest.h"
|
||||
|
||||
#include <QDataStream>
|
||||
@ -6,7 +13,7 @@ namespace NP{
|
||||
|
||||
|
||||
BadRequest::BadRequest(const QString &err):AbstractData() {
|
||||
INIT_COMMAND
|
||||
|
||||
|
||||
setErr(err);
|
||||
|
@ -1,3 +1,10 @@
|
||||
/*
|
||||
* 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 BADREQUEST_H
|
||||
#define BADREQUEST_H
|
||||
|
8
Heart/AbstractSpace/packages/closeconnection.cpp
Normal file
8
Heart/AbstractSpace/packages/closeconnection.cpp
Normal file
@ -0,0 +1,8 @@
|
||||
#include "closeconnection.h"
|
||||
|
||||
namespace NP {
|
||||
CloseConnection::CloseConnection()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
22
Heart/AbstractSpace/packages/closeconnection.h
Normal file
22
Heart/AbstractSpace/packages/closeconnection.h
Normal file
@ -0,0 +1,22 @@
|
||||
#ifndef CLOSECONNECTION_H
|
||||
#define CLOSECONNECTION_H
|
||||
|
||||
#include "abstractdata.h"
|
||||
|
||||
|
||||
namespace NP{
|
||||
|
||||
/**
|
||||
* @brief The CloseConnection class - This commnad is request for close connection on parent node of connection
|
||||
* This neede becouse QAbstractSocket emit error when connection closed from remote node.
|
||||
*
|
||||
* From QtDocumentation :
|
||||
* ``` If the remote host closes the connection, QAbstractSocket will emit errorOccurred(QAbstractSocket::RemoteHostClosedError), during which the socket state will still be ConnectedState, and then the disconnected() signal will be emitted.```
|
||||
*/
|
||||
class NETWORKPROTOCOLSHARED_EXPORT CloseConnection: public AbstractData
|
||||
{
|
||||
public:
|
||||
CloseConnection();
|
||||
};
|
||||
}
|
||||
#endif // CLOSECONNECTION_H
|
50
Heart/AbstractSpace/packages/ping.cpp
Normal file
50
Heart/AbstractSpace/packages/ping.cpp
Normal file
@ -0,0 +1,50 @@
|
||||
#include "ping.h"
|
||||
|
||||
#include <QDataStream>
|
||||
namespace NP {
|
||||
|
||||
Ping::Ping() {
|
||||
|
||||
}
|
||||
|
||||
Ping::Ping(const Package &from): Ping() {
|
||||
fromBytes(from.data);
|
||||
}
|
||||
|
||||
bool Ping::isValid() const {
|
||||
return AbstractData::isValid();
|
||||
}
|
||||
|
||||
bool Ping::copyFrom(const AbstractData * other) {
|
||||
if (!AbstractData::copyFrom(other))
|
||||
return false;
|
||||
|
||||
auto otherObject = dynamic_cast<const Ping*>(other);
|
||||
if (!otherObject)
|
||||
return false;
|
||||
|
||||
this->_ansver = otherObject->_ansver;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Ping::ansver() const {
|
||||
return _ansver;
|
||||
}
|
||||
|
||||
void Ping::setAnsver(bool ansver) {
|
||||
_ansver = ansver;
|
||||
}
|
||||
|
||||
QDataStream &Ping::fromStream(QDataStream &stream) {
|
||||
AbstractData::fromStream(stream);
|
||||
stream >> _ansver;
|
||||
return stream;
|
||||
|
||||
}
|
||||
|
||||
QDataStream &Ping::toStream(QDataStream &stream) const {
|
||||
AbstractData::toStream(stream);
|
||||
stream << _ansver;
|
||||
return stream;
|
||||
}
|
||||
}
|
34
Heart/AbstractSpace/packages/ping.h
Normal file
34
Heart/AbstractSpace/packages/ping.h
Normal file
@ -0,0 +1,34 @@
|
||||
#ifndef PING_H
|
||||
#define PING_H
|
||||
|
||||
#include "abstractdata.h"
|
||||
|
||||
|
||||
namespace NP {
|
||||
|
||||
/**
|
||||
* @brief The Ping class - test class for translate data on network
|
||||
*/
|
||||
class NETWORKPROTOCOLSHARED_EXPORT Ping: public AbstractData
|
||||
{
|
||||
public:
|
||||
Ping();
|
||||
Ping(const Package& from);
|
||||
|
||||
// AbstractData interface
|
||||
bool isValid() const;
|
||||
bool copyFrom(const AbstractData *);
|
||||
|
||||
bool ansver() const;
|
||||
void setAnsver(bool ansver);
|
||||
|
||||
protected:
|
||||
// StreamBase interface
|
||||
QDataStream &fromStream(QDataStream &stream);
|
||||
QDataStream &toStream(QDataStream &stream) const;
|
||||
|
||||
private:
|
||||
bool _ansver = false;
|
||||
};
|
||||
}
|
||||
#endif // PING_H
|
73
Heart/AbstractSpace/qsecretrsa2048.cpp
Normal file
73
Heart/AbstractSpace/qsecretrsa2048.cpp
Normal file
@ -0,0 +1,73 @@
|
||||
#include "cryptopairkeys.h"
|
||||
#include "qsecretrsa2048.h"
|
||||
#include <QDir>
|
||||
#include <qrsaencryption.h>
|
||||
|
||||
namespace NP {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
44
Heart/AbstractSpace/qsecretrsa2048.h
Normal file
44
Heart/AbstractSpace/qsecretrsa2048.h
Normal file
@ -0,0 +1,44 @@
|
||||
#ifndef QSECRETRSA2048_H
|
||||
#define QSECRETRSA2048_H
|
||||
|
||||
#include "icrypto.h"
|
||||
|
||||
#include <QHash>
|
||||
|
||||
class QRSAEncryption;
|
||||
|
||||
namespace NP {
|
||||
|
||||
/**
|
||||
* @brief The QSecretRSA2048 class Use
|
||||
*/
|
||||
class NETWORKPROTOCOLSHARED_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;
|
||||
|
||||
/**
|
||||
* @brief isValid
|
||||
* @return true if object is valid.
|
||||
*/
|
||||
bool isValid() const override;
|
||||
|
||||
protected:
|
||||
CryptoPairKeys generate(const QByteArray& genesis = {}) const override;
|
||||
|
||||
|
||||
private:
|
||||
QRSAEncryption *qtSecret = nullptr;
|
||||
|
||||
|
||||
};
|
||||
}
|
||||
#endif // QSECRETRSA2048_H
|
9
Heart/AbstractSpace/receivedata.cpp
Normal file
9
Heart/AbstractSpace/receivedata.cpp
Normal file
@ -0,0 +1,9 @@
|
||||
#include "receivedata.h"
|
||||
|
||||
namespace NP {
|
||||
|
||||
ReceiveData::ReceiveData()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
21
Heart/AbstractSpace/receivedata.h
Normal file
21
Heart/AbstractSpace/receivedata.h
Normal file
@ -0,0 +1,21 @@
|
||||
#ifndef RECEIVEDATA_H
|
||||
#define RECEIVEDATA_H
|
||||
|
||||
#include "package.h"
|
||||
|
||||
namespace NP {
|
||||
|
||||
/**
|
||||
* @brief The ReceiveData struct - this structure contains informaton for parse packages
|
||||
*/
|
||||
struct ReceiveData
|
||||
{
|
||||
public:
|
||||
ReceiveData();
|
||||
|
||||
Package _pkg;
|
||||
QByteArray _hdrArray;
|
||||
|
||||
};
|
||||
}
|
||||
#endif // RECEIVEDATA_H
|
23
Heart/AbstractSpace/request.cpp
Normal file
23
Heart/AbstractSpace/request.cpp
Normal file
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "request.h"
|
||||
namespace NP {
|
||||
|
||||
Request::Request() {
|
||||
|
||||
}
|
||||
|
||||
unsigned char Request::getRequestCmd() const {
|
||||
return requestCmd;
|
||||
}
|
||||
|
||||
void Request::setRequestCmd(unsigned char value) {
|
||||
requestCmd = value;
|
||||
}
|
||||
|
||||
}
|
30
Heart/AbstractSpace/request.h
Normal file
30
Heart/AbstractSpace/request.h
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* 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 IREQUEST_H
|
||||
#define IREQUEST_H
|
||||
|
||||
#include "heart_global.h"
|
||||
|
||||
namespace NP {
|
||||
|
||||
/**
|
||||
* @brief The Request class - base request methods for data packages
|
||||
*/
|
||||
class NETWORKPROTOCOLSHARED_EXPORT Request
|
||||
{
|
||||
public:
|
||||
Request();
|
||||
unsigned char getRequestCmd() const;
|
||||
void setRequestCmd(unsigned char value);
|
||||
|
||||
protected:
|
||||
unsigned char requestCmd = 0;
|
||||
|
||||
};
|
||||
}
|
||||
#endif // IREQUEST_H
|
@ -1,3 +1,10 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "package.h"
|
||||
#include "streambase.h"
|
||||
|
@ -1,15 +1,25 @@
|
||||
/*
|
||||
* 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 STREAMBASE_H
|
||||
#define STREAMBASE_H
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QVariantMap>
|
||||
#include "networkprotocol_global.h"
|
||||
#include "heart_global.h"
|
||||
|
||||
class QDataStream;
|
||||
namespace NP {
|
||||
|
||||
class Package;
|
||||
|
||||
/**
|
||||
* @brief The StreamBase class - this class add support for streaming data for all cheldren classes.
|
||||
*/
|
||||
class NETWORKPROTOCOLSHARED_EXPORT StreamBase
|
||||
{
|
||||
public:
|
||||
@ -28,20 +38,6 @@ public:
|
||||
*/
|
||||
QByteArray toBytes() const;
|
||||
|
||||
/**
|
||||
* @brief fromStream
|
||||
* @param stream
|
||||
* @return stream
|
||||
*/
|
||||
virtual QDataStream& fromStream(QDataStream& stream) = 0;
|
||||
|
||||
/**
|
||||
* @brief toStream
|
||||
* @param stream
|
||||
* @return stream
|
||||
*/
|
||||
virtual QDataStream& toStream(QDataStream& stream) const = 0;
|
||||
|
||||
|
||||
/**
|
||||
* @brief operator << it is wraper over toStream
|
||||
@ -60,7 +56,20 @@ public:
|
||||
friend QDataStream& operator>> (QDataStream& stream, StreamBase& obj);
|
||||
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief fromStream
|
||||
* @param stream
|
||||
* @return stream
|
||||
*/
|
||||
virtual QDataStream& fromStream(QDataStream& stream) = 0;
|
||||
|
||||
/**
|
||||
* @brief toStream
|
||||
* @param stream
|
||||
* @return stream
|
||||
*/
|
||||
virtual QDataStream& toStream(QDataStream& stream) const = 0;
|
||||
|
||||
};
|
||||
}
|
@ -1,6 +1,13 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "workstate.h"
|
||||
|
||||
#include <QHostAddress>
|
||||
#include <hostaddress.h>
|
||||
|
||||
namespace NP{
|
||||
|
||||
@ -61,11 +68,11 @@ void WorkState::setMaxConnectionCount(int value) {
|
||||
maxConnectionCount = value;
|
||||
}
|
||||
|
||||
QList<QHostAddress> WorkState::getBanedList() const {
|
||||
QList<HostAddress> WorkState::getBanedList() const {
|
||||
return _banedList;
|
||||
}
|
||||
|
||||
void WorkState::setBanedList(const QList<QHostAddress> &banedList) {
|
||||
void WorkState::setBanedList(const QList<HostAddress> &banedList) {
|
||||
_banedList = banedList;
|
||||
}
|
||||
}
|
@ -1,7 +1,14 @@
|
||||
/*
|
||||
* 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 WORKSTATE_H
|
||||
#define WORKSTATE_H
|
||||
|
||||
#include <QHostAddress>
|
||||
#include <hostaddress.h>
|
||||
#include <QList>
|
||||
|
||||
namespace NP {
|
||||
@ -16,7 +23,7 @@ private:
|
||||
int maxConnectionCount = 0;
|
||||
bool isRun = false;
|
||||
|
||||
QList<QHostAddress> _banedList;
|
||||
QList<HostAddress> _banedList;
|
||||
|
||||
QString getWorkStateString() const;
|
||||
public:
|
||||
@ -60,13 +67,13 @@ public:
|
||||
* @brief getBanedList
|
||||
* @return list of id's of baned nodes
|
||||
*/
|
||||
QList<QHostAddress> getBanedList() const;
|
||||
QList<HostAddress> getBanedList() const;
|
||||
|
||||
/**
|
||||
* @brief setBanedList
|
||||
* @param banedList set new baned list
|
||||
*/
|
||||
void setBanedList(const QList<QHostAddress> &banedList);
|
||||
void setBanedList(const QList<HostAddress> &banedList);
|
||||
|
||||
/**
|
||||
* @brief getIsRun
|
87
Heart/CMakeLists.txt
Normal file
87
Heart/CMakeLists.txt
Normal file
@ -0,0 +1,87 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
include(../QuasarAppLib/CMake/ProjectOut.cmake)
|
||||
include(../QuasarAppLib/CMake/Version.cmake)
|
||||
|
||||
add_subdirectory(Qt-Secret)
|
||||
|
||||
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
|
||||
|
||||
add_definitions(-DNETWORKPROTOCOL_LIBRARY)
|
||||
|
||||
|
||||
find_package(Qt5 COMPONENTS Core Network Sql Concurrent REQUIRED)
|
||||
|
||||
if (${BUILD_LVL} GREATER_EQUAL 0)
|
||||
message("BUILD LVL >= 0")
|
||||
file(GLOB SOURCE_CPP_LVL_0
|
||||
"*.cpp" "*.qrc"
|
||||
"AbstractSpace/*.cpp" "AbstractSpace/*.qrc"
|
||||
"AbstractSpace/packages/*.cpp" "AbstractSpace/packages/*.qrc"
|
||||
"AbstractSpace/Private/*.cpp" "AbstractSpace/Private/*.qrc"
|
||||
|
||||
)
|
||||
|
||||
set(PUBLIC_INCUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
set(PUBLIC_INCUDE_DIR ${PUBLIC_INCUDE_DIR} "${CMAKE_CURRENT_SOURCE_DIR}/AbstractSpace")
|
||||
set(PUBLIC_INCUDE_DIR ${PUBLIC_INCUDE_DIR} "${CMAKE_CURRENT_SOURCE_DIR}/AbstractSpace/packages")
|
||||
set(PRIVATE_INCUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/AbstractSpace/Private")
|
||||
|
||||
endif()
|
||||
|
||||
if (${BUILD_LVL} GREATER_EQUAL 1)
|
||||
message("BUILD LVL >= 1")
|
||||
file(GLOB SOURCE_CPP_LVL_1
|
||||
"DataBaseSpace/*.cpp" "DataBaseSpace/*.qrc"
|
||||
"DataBaseSpace/packages/*.cpp" "DataBaseSpace/packages/*.qrc"
|
||||
"DataBaseSpace/Private/*.cpp" "DataBaseSpace/Private/*.qrc"
|
||||
)
|
||||
|
||||
set(PUBLIC_INCUDE_DIR ${PUBLIC_INCUDE_DIR} "${CMAKE_CURRENT_SOURCE_DIR}/DataBaseSpace")
|
||||
set(PUBLIC_INCUDE_DIR ${PUBLIC_INCUDE_DIR} "${CMAKE_CURRENT_SOURCE_DIR}/DataBaseSpace/packages")
|
||||
|
||||
set(PRIVATE_INCUDE_DIR ${PRIVATE_INCUDE_DIR} "${CMAKE_CURRENT_SOURCE_DIR}/DataBaseSpace/Private")
|
||||
|
||||
endif()
|
||||
|
||||
if (${BUILD_LVL} GREATER_EQUAL 2)
|
||||
message("BUILD LVL >= 2")
|
||||
file(GLOB SOURCE_CPP_LVL_2
|
||||
"NetworkSpace/*.cpp" "NetworkSpace/*.qrc"
|
||||
"NetworkSpace/packages/*.cpp" "NetworkSpace/packages/*.qrc"
|
||||
"NetworkSpace/Private/*.cpp" "NetworkSpace/Private/*.qrc"
|
||||
)
|
||||
|
||||
|
||||
set(PUBLIC_INCUDE_DIR ${PUBLIC_INCUDE_DIR} "${CMAKE_CURRENT_SOURCE_DIR}/NetworkSpace")
|
||||
set(PUBLIC_INCUDE_DIR ${PUBLIC_INCUDE_DIR} "${CMAKE_CURRENT_SOURCE_DIR}/NetworkSpace/packages")
|
||||
|
||||
set(PRIVATE_INCUDE_DIR ${PRIVATE_INCUDE_DIR} "${CMAKE_CURRENT_SOURCE_DIR}/NetworkSpace/Private")
|
||||
|
||||
endif()
|
||||
|
||||
set(SOURCE_CPP ${SOURCE_CPP_LVL_0} ${SOURCE_CPP_LVL_1} ${SOURCE_CPP_LVL_2})
|
||||
|
||||
|
||||
add_library(${PROJECT_NAME} SHARED ${SOURCE_CPP})
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC Qt5::Core Qt5::Network Qt5::Sql Qt5::Concurrent QuasarApp crypto ssl Qt-Secret)
|
||||
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC ${PUBLIC_INCUDE_DIR})
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE ${PRIVATE_INCUDE_DIR})
|
||||
|
||||
|
||||
setVersion(1 1 0)
|
19
Heart/DataBaseSpace/Res/BaseDB.sql
Normal file
19
Heart/DataBaseSpace/Res/BaseDB.sql
Normal file
@ -0,0 +1,19 @@
|
||||
|
||||
CREATE TABLE IF NOT EXISTS NetworkMembers (
|
||||
id VARCHAR(64) PRIMARY KEY NOT NULL,
|
||||
authenticationData BLOB default NULL,
|
||||
trust INTEGER default 0
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS MemberPermisions (
|
||||
memberId VARCHAR(64) NOT NULL,
|
||||
objectTable VARCHAR(100) NOT NULL,
|
||||
objectId VARCHAR(64) NOT NULL,
|
||||
lvl INTEGER NOT NULL,
|
||||
|
||||
FOREIGN KEY(memberId) REFERENCES NetworkMembers(id)
|
||||
ON UPDATE CASCADE
|
||||
ON DELETE CASCADE
|
||||
|
||||
);
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS MemberPermisionsIndex ON MemberPermisions(memberId, objectTable, objectId);
|
1
Heart/DataBaseSpace/abstractkey.cpp
Normal file
1
Heart/DataBaseSpace/abstractkey.cpp
Normal file
@ -0,0 +1 @@
|
||||
#include "abstractkey.h"
|
49
Heart/DataBaseSpace/abstractkey.h
Normal file
49
Heart/DataBaseSpace/abstractkey.h
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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 ABSTRACTKEY_H
|
||||
#define ABSTRACTKEY_H
|
||||
#include "heart_global.h"
|
||||
|
||||
#include <baseid.h>
|
||||
|
||||
namespace NP {
|
||||
|
||||
/**
|
||||
* @brief The Abstractkey class - this class provid one hash function for all keys of database objcets
|
||||
*/
|
||||
class NETWORKPROTOCOLSHARED_EXPORT AbstractKey
|
||||
{
|
||||
public:
|
||||
AbstractKey() = default;
|
||||
|
||||
virtual ~AbstractKey() = default;
|
||||
virtual unsigned int hash() const = 0;
|
||||
virtual bool equal(const AbstractKey* other) const = 0;
|
||||
|
||||
/**
|
||||
* @brief id - this method return id of object
|
||||
* @return BaseId of object.
|
||||
*/
|
||||
virtual const BaseId& id() const = 0;
|
||||
|
||||
/**
|
||||
* @brief table - this method return table name of object
|
||||
* @return table name
|
||||
*/
|
||||
virtual const QString& table() const = 0;
|
||||
|
||||
/**
|
||||
* @brief isValid
|
||||
* @return true if key is valid
|
||||
*/
|
||||
virtual bool isValid() const = 0;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
#endif // ABSTRACTKEY_H
|
@ -1,3 +1,10 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "accesstoken.h"
|
||||
#include <QCryptographicHash>
|
||||
#include <QDataStream>
|
@ -1,3 +1,10 @@
|
||||
/*
|
||||
* 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 ACCSESTOKEN_H
|
||||
#define ACCSESTOKEN_H
|
||||
|
||||
@ -5,7 +12,7 @@
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QDateTime>
|
||||
#include <networkprotocol_global.h>
|
||||
#include <heart_global.h>
|
||||
|
||||
namespace NP {
|
||||
|
235
Heart/DataBaseSpace/asyncsqldbwriter.cpp
Normal file
235
Heart/DataBaseSpace/asyncsqldbwriter.cpp
Normal file
@ -0,0 +1,235 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "asyncsqldbwriter.h"
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QMetaMethod>
|
||||
#include <QThread>
|
||||
#include <dbobject.h>
|
||||
#include <quasarapp.h>
|
||||
|
||||
namespace NP {
|
||||
|
||||
|
||||
AsyncSqlDbWriter::AsyncSqlDbWriter(QObject *ptr):
|
||||
QObject(ptr) {
|
||||
_own = new QThread(this);
|
||||
moveToThread(_own);
|
||||
_own->start();
|
||||
|
||||
}
|
||||
|
||||
AsyncSqlDbWriter::~AsyncSqlDbWriter() {
|
||||
_own->quit();
|
||||
_own->wait();
|
||||
}
|
||||
|
||||
bool AsyncSqlDbWriter::saveObject(const DBObject *saveObject) {
|
||||
if (QThread::currentThread() == thread()) {
|
||||
return SqlDBWriter::saveObject(saveObject);
|
||||
}
|
||||
|
||||
return QMetaObject::invokeMethod(this,
|
||||
"handleSaveObject",
|
||||
Qt::QueuedConnection,
|
||||
Q_ARG(const NP::DBObject *, saveObject),
|
||||
Q_ARG(bool *, nullptr),
|
||||
Q_ARG(bool *, nullptr));
|
||||
|
||||
}
|
||||
|
||||
bool AsyncSqlDbWriter::deleteObject(const DBObject *deleteObject) {
|
||||
if (QThread::currentThread() == thread()) {
|
||||
return SqlDBWriter::deleteObject(deleteObject);
|
||||
}
|
||||
|
||||
return QMetaObject::invokeMethod(this,
|
||||
"handleDeleteObject",
|
||||
Qt::QueuedConnection,
|
||||
Q_ARG(const NP::DBObject *, deleteObject),
|
||||
Q_ARG(bool *, nullptr),
|
||||
Q_ARG(bool *, nullptr));
|
||||
}
|
||||
|
||||
bool AsyncSqlDbWriter::saveObjectWithWait(const DBObject *saveObject) {
|
||||
if (QThread::currentThread() == thread()) {
|
||||
return SqlDBWriter::saveObject(saveObject);
|
||||
}
|
||||
|
||||
bool workOfEnd = false, workResult = false;
|
||||
|
||||
|
||||
bool invoke = QMetaObject::invokeMethod(this,
|
||||
"handleSaveObject",
|
||||
Qt::QueuedConnection,
|
||||
Q_ARG(const NP::DBObject *, saveObject),
|
||||
Q_ARG(bool *, &workResult),
|
||||
Q_ARG(bool *, &workOfEnd));
|
||||
|
||||
if (!invoke) {
|
||||
QuasarAppUtils::Params::log("handleDeleteObject not invokecd", QuasarAppUtils::Debug);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (!waitFor(&workOfEnd)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return workResult;
|
||||
}
|
||||
|
||||
bool AsyncSqlDbWriter::deleteObjectWithWait(const DBObject *deleteObject) {
|
||||
if (QThread::currentThread() == thread()) {
|
||||
return SqlDBWriter::deleteObject(deleteObject);
|
||||
}
|
||||
|
||||
bool workOfEnd = false, workResult = false;
|
||||
|
||||
|
||||
bool invoke = QMetaObject::invokeMethod(this,
|
||||
"handleDeleteObject",
|
||||
Qt::QueuedConnection,
|
||||
Q_ARG(const NP::DBObject *, deleteObject),
|
||||
Q_ARG(bool *, &workResult),
|
||||
Q_ARG(bool *, &workOfEnd));
|
||||
|
||||
if (!invoke) {
|
||||
QuasarAppUtils::Params::log("handleDeleteObject not invokecd", QuasarAppUtils::Debug);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (!waitFor(&workOfEnd)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return workResult;
|
||||
}
|
||||
|
||||
bool AsyncSqlDbWriter::getAllObjects(const DBObject &templateObject, QList<const DBObject *> &result) {
|
||||
|
||||
if (QThread::currentThread() == thread()) {
|
||||
return SqlDBWriter::getAllObjects(templateObject, result);
|
||||
}
|
||||
|
||||
bool workOfEnd = false, workResult = false;
|
||||
|
||||
|
||||
bool invockeResult = QMetaObject::invokeMethod(this,
|
||||
"handleGetAllObject",
|
||||
Qt::QueuedConnection,
|
||||
Q_ARG(const NP::DBObject *, &templateObject),
|
||||
Q_ARG(QList<const NP::DBObject *> *, &result),
|
||||
Q_ARG(bool *, &workResult),
|
||||
Q_ARG(bool *, &workOfEnd));
|
||||
|
||||
if (!invockeResult)
|
||||
return false;
|
||||
|
||||
|
||||
if (!waitFor(&workOfEnd)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return workResult;
|
||||
}
|
||||
|
||||
bool AsyncSqlDbWriter::initDb(const QVariantMap ¶ms) {
|
||||
if (QThread::currentThread() == thread()) {
|
||||
return SqlDBWriter::initDb(params);
|
||||
}
|
||||
|
||||
bool workOfEnd = false, workResult = false;
|
||||
|
||||
|
||||
bool invockeResult = QMetaObject::invokeMethod(this,
|
||||
"handleInitDb",
|
||||
Qt::QueuedConnection,
|
||||
Q_ARG(const QVariantMap &, params),
|
||||
Q_ARG(bool *, &workResult),
|
||||
Q_ARG(bool *, &workOfEnd));
|
||||
|
||||
if (!invockeResult)
|
||||
return false;
|
||||
|
||||
|
||||
if (!waitFor(&workOfEnd)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return workResult;
|
||||
}
|
||||
|
||||
void AsyncSqlDbWriter::handleSaveObject(const DBObject* saveObject,
|
||||
bool *resultOfWork,
|
||||
bool *endOfWork) {
|
||||
if (resultOfWork) {
|
||||
*resultOfWork = SqlDBWriter::saveObject(saveObject);
|
||||
|
||||
if (endOfWork) {
|
||||
*endOfWork = true;
|
||||
}
|
||||
|
||||
} else {
|
||||
if (!SqlDBWriter::saveObject(saveObject)) {
|
||||
QuasarAppUtils::Params::log("AsyncSqlDbWriter: save object fail!",
|
||||
QuasarAppUtils::Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AsyncSqlDbWriter::handleDeleteObject(const DBObject *deleteObject, bool *resultOfWork, bool *endOfWork) {
|
||||
if (resultOfWork) {
|
||||
*resultOfWork = SqlDBWriter::deleteObject(deleteObject);
|
||||
|
||||
if (endOfWork) {
|
||||
*endOfWork = true;
|
||||
}
|
||||
|
||||
} else {
|
||||
if (!SqlDBWriter::deleteObject(deleteObject)) {
|
||||
QuasarAppUtils::Params::log("AsyncSqlDbWriter: delete object fail!",
|
||||
QuasarAppUtils::Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AsyncSqlDbWriter::handleGetAllObject(const DBObject *templateObject,
|
||||
QList<const DBObject *> *result,
|
||||
bool *resultOfWork, bool *endOfWork) {
|
||||
|
||||
|
||||
*resultOfWork = SqlDBWriter::getAllObjects(*templateObject, *result);
|
||||
|
||||
if (endOfWork) {
|
||||
*endOfWork = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void AsyncSqlDbWriter::handleInitDb(const QVariantMap ¶ms,
|
||||
bool *resultOfWork, bool *endOfWork) {
|
||||
|
||||
*resultOfWork = SqlDBWriter::initDb(params);
|
||||
|
||||
if (endOfWork) {
|
||||
*endOfWork = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool AsyncSqlDbWriter::waitFor(bool *condition, int timeout) const {
|
||||
auto curmsec = QDateTime::currentMSecsSinceEpoch() + timeout;
|
||||
while (curmsec > QDateTime::currentMSecsSinceEpoch() && !*condition) {
|
||||
QCoreApplication::processEvents();
|
||||
}
|
||||
QCoreApplication::processEvents();
|
||||
return *condition;
|
||||
}
|
||||
|
||||
}
|
121
Heart/DataBaseSpace/asyncsqldbwriter.h
Normal file
121
Heart/DataBaseSpace/asyncsqldbwriter.h
Normal file
@ -0,0 +1,121 @@
|
||||
/*
|
||||
* 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 ASYNCSQLDBWRITER_H
|
||||
#define ASYNCSQLDBWRITER_H
|
||||
|
||||
#include "sqldbwriter.h"
|
||||
#include "atomicmetatypes.h"
|
||||
|
||||
namespace NP {
|
||||
|
||||
|
||||
/**
|
||||
* @brief The AsyncSqlDbWriter class some as SqlDBWriter bud run all commnad in main thread
|
||||
* is thread save db writer.
|
||||
*/
|
||||
class AsyncSqlDbWriter :public QObject, public SqlDBWriter
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AsyncSqlDbWriter(QObject* ptr = nullptr);
|
||||
~AsyncSqlDbWriter();
|
||||
// iObjectProvider interface
|
||||
/**
|
||||
* @brief saveObject - save object in to database. This implementation work on own thread
|
||||
* @param saveObject - ptr to object
|
||||
* @return true if function finished successful
|
||||
*/
|
||||
bool saveObject(const DBObject* saveObject) override;
|
||||
|
||||
/**
|
||||
* @brief saveObject - delete object in to database. This implementation work on own thread
|
||||
* @param deleteObject - ptr to object
|
||||
* @return true if function finished successful
|
||||
*/
|
||||
bool deleteObject(const DBObject* deleteObject) override;
|
||||
|
||||
/**
|
||||
* @brief saveObjectWithWait - this is owerload of saveObject with wait results of a database thread.
|
||||
* @param saveObject - ptr to object
|
||||
* @return true if function finished successful
|
||||
*/
|
||||
bool saveObjectWithWait(const DBObject* saveObject);
|
||||
|
||||
/**
|
||||
* @brief deleteObjectWithWait - this is owerload of deleteObject with wait results of a database thread.
|
||||
* @param deleteObject - ptr to object
|
||||
* @return true if function finished successful
|
||||
*/
|
||||
bool deleteObjectWithWait(const DBObject* deleteObject);
|
||||
|
||||
/**
|
||||
* @brief getAllObjects - this implementation work on own thread and wait results in current thread.
|
||||
* @param templateObject - template object with request
|
||||
* @param result - list of objects
|
||||
* @return true if function finished successful
|
||||
*/
|
||||
bool getAllObjects(const DBObject &templateObject, QList<const DBObject *> &result) override;
|
||||
|
||||
/**
|
||||
* @brief initDb - this implementation initialise database in own thread and wait result of initialization on current thread
|
||||
* @param initDbParams - initialise parameters
|
||||
* @return true if database initialise successful
|
||||
*/
|
||||
bool initDb(const QVariantMap ¶ms) override;
|
||||
|
||||
protected slots:
|
||||
/**
|
||||
* @brief handleSaveObject - this method call SaveObject on own thread.
|
||||
* @param saveObject - object for save
|
||||
*/
|
||||
void handleSaveObject(const NP::DBObject* saveObject,
|
||||
bool *resultOfWork, bool *endOfWork);
|
||||
|
||||
/**
|
||||
* @brief handleDeleteObject - this method call DeleteObject on own thread.
|
||||
* @param deleteObject object for delete
|
||||
*/
|
||||
void handleDeleteObject(const NP::DBObject* deleteObject,
|
||||
bool *resultOfWork, bool *endOfWork);
|
||||
|
||||
/**
|
||||
* @brief the handleGetAllObject - this method call getAllObjects on own thread.
|
||||
* @param templateObject - the some as in getAllObjects
|
||||
* @param result - the some as in getAllObjects
|
||||
* @param resultOfWork - this ptr contains result of invoked of getAllObjects method on own thread
|
||||
* @param endOfWork - this ptr set true when invocked method is finished
|
||||
* @param cb - this call back method invoke after getAllObjects method
|
||||
*/
|
||||
virtual void handleGetAllObject(const NP::DBObject *templateObject,
|
||||
QList<const NP::DBObject *> *result,
|
||||
bool *resultOfWork, bool *endOfWork = nullptr);
|
||||
|
||||
/**
|
||||
* @brief handleInitDb - this method invoke initDb on own thread
|
||||
* @param params - input parameters data
|
||||
* @param resultOfWork - this ptr contains result of invoked of initDb method on own thread
|
||||
* @param endOfWork - this ptr set true when invocked method is finished
|
||||
*/
|
||||
void handleInitDb(const QVariantMap ¶ms,
|
||||
bool *resultOfWork, bool *endOfWork = nullptr);
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief waitFor - The base wait function.
|
||||
* @param condition - condition for wait
|
||||
* @param timeout - maximu time for wait. By default this value equals WAIT_TIME it is 30000 msec.
|
||||
* @return true if condition is true.
|
||||
*/
|
||||
bool waitFor(bool* condition, int timeout = WAIT_TIME) const;
|
||||
|
||||
QThread *_own = nullptr;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
#endif // ASYNCSQLDBWRITER_H
|
19
Heart/DataBaseSpace/basedefines.h
Normal file
19
Heart/DataBaseSpace/basedefines.h
Normal file
@ -0,0 +1,19 @@
|
||||
#ifndef BASEDEFINES_H
|
||||
#define BASEDEFINES_H
|
||||
|
||||
namespace NP {
|
||||
|
||||
/**
|
||||
* @brief The DBOperationResult enum
|
||||
*/
|
||||
enum class DBOperationResult {
|
||||
/// Node do not know about this operaio
|
||||
Unknown,
|
||||
/// Node allow this operation and exec it
|
||||
Allowed,
|
||||
/// Node forbid this operation.
|
||||
Forbidden,
|
||||
};
|
||||
|
||||
}
|
||||
#endif // BASEDEFINES_H
|
75
Heart/DataBaseSpace/baseid.cpp
Normal file
75
Heart/DataBaseSpace/baseid.cpp
Normal file
@ -0,0 +1,75 @@
|
||||
#include "baseid.h"
|
||||
namespace NP {
|
||||
|
||||
BaseId::BaseId() = default;
|
||||
|
||||
BaseId::BaseId(unsigned int val) {
|
||||
fromRaw(reinterpret_cast<char*>(&val), sizeof (val));
|
||||
}
|
||||
|
||||
BaseId::BaseId(const QByteArray &raw) {
|
||||
fromRaw(raw);
|
||||
}
|
||||
|
||||
BaseId::BaseId(const QString &base64) {
|
||||
fromBase64(base64.toLatin1());
|
||||
}
|
||||
|
||||
bool BaseId::fromBase64(const QByteArray &base64) {
|
||||
return fromRaw(QByteArray::fromBase64(base64, QByteArray::Base64UrlEncoding));
|
||||
}
|
||||
|
||||
bool BaseId::fromRaw(const QByteArray &raw) {
|
||||
_data = raw;
|
||||
return isValid();
|
||||
}
|
||||
|
||||
bool BaseId::fromRaw(const char *data, int len) {
|
||||
_data.clear();
|
||||
_data.insert(0, data, len);
|
||||
return isValid();
|
||||
}
|
||||
|
||||
QByteArray BaseId::toBase64() const {
|
||||
return _data.toBase64(QByteArray::Base64UrlEncoding);
|
||||
}
|
||||
|
||||
const QByteArray& BaseId::toRaw() const {
|
||||
return _data;
|
||||
}
|
||||
|
||||
bool BaseId::isValid() const {
|
||||
return _data.size();
|
||||
}
|
||||
|
||||
void BaseId::clear() {
|
||||
_data.clear();
|
||||
}
|
||||
|
||||
unsigned char BaseId::prefix() const {
|
||||
if (_data.size())
|
||||
return _data[0];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
QDataStream &BaseId::fromStream(QDataStream &stream) {
|
||||
stream >> _data;
|
||||
return stream;
|
||||
}
|
||||
|
||||
QDataStream &BaseId::toStream(QDataStream &stream) const {
|
||||
stream << _data;
|
||||
return stream;
|
||||
}
|
||||
|
||||
bool operator==(const BaseId &left, const BaseId &other) {
|
||||
return left._data == other._data;
|
||||
}
|
||||
|
||||
|
||||
uint qHash(const NP::BaseId &object) {
|
||||
return qHash(object.toRaw());
|
||||
}
|
||||
}
|
||||
|
95
Heart/DataBaseSpace/baseid.h
Normal file
95
Heart/DataBaseSpace/baseid.h
Normal file
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* 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 BaseId_H
|
||||
#define BaseId_H
|
||||
|
||||
#include <QByteArray>
|
||||
#include <streambase.h>
|
||||
|
||||
namespace NP {
|
||||
|
||||
/**
|
||||
* @brief The BaseId class. General class for work with database id.
|
||||
* Database id is '1byte of prefix + hash (sha256)' from object value.
|
||||
*/
|
||||
class NETWORKPROTOCOLSHARED_EXPORT BaseId: public StreamBase
|
||||
{
|
||||
public:
|
||||
BaseId();
|
||||
BaseId(unsigned int val);
|
||||
|
||||
BaseId(const QByteArray& raw);
|
||||
BaseId(const QString& base64);
|
||||
|
||||
/**
|
||||
* @brief fromBase64
|
||||
* @param base64
|
||||
* @return
|
||||
*/
|
||||
bool fromBase64(const QByteArray& base64);
|
||||
|
||||
/**
|
||||
* @brief fromRaw
|
||||
* @param raw
|
||||
* @return
|
||||
*/
|
||||
bool fromRaw(const QByteArray& raw);
|
||||
|
||||
/**
|
||||
* @brief fromRaw
|
||||
* @param raw
|
||||
* @return
|
||||
*/
|
||||
bool fromRaw(const char* data, int len);
|
||||
|
||||
/**
|
||||
* @brief toBase64
|
||||
* @return
|
||||
*/
|
||||
QByteArray toBase64() const;
|
||||
|
||||
/**
|
||||
* @brief toRaw
|
||||
* @return
|
||||
*/
|
||||
const QByteArray& toRaw() const;
|
||||
|
||||
/**
|
||||
* @brief isValid
|
||||
* @return true if object is valid
|
||||
*/
|
||||
virtual bool isValid() const;
|
||||
|
||||
/**
|
||||
* @brief clear
|
||||
* @return
|
||||
*/
|
||||
void clear();
|
||||
|
||||
/**
|
||||
* @brief prefix - return prefix of id. if id is not valid return 0.
|
||||
* @return prefix of id
|
||||
*/
|
||||
unsigned char prefix() const;
|
||||
|
||||
QDataStream &fromStream(QDataStream &stream) override;
|
||||
QDataStream &toStream(QDataStream &stream) const override;
|
||||
|
||||
friend bool operator== (const BaseId& left, const BaseId& other);
|
||||
|
||||
private:
|
||||
QByteArray _data;
|
||||
};
|
||||
|
||||
|
||||
uint qHash(const NP::BaseId& object);
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // BaseId_H
|
37
Heart/DataBaseSpace/basenodeinfo.cpp
Normal file
37
Heart/DataBaseSpace/basenodeinfo.cpp
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "basenodeinfo.h"
|
||||
#include "dbaddress.h"
|
||||
#include <QTcpSocket>
|
||||
#include <hostaddress.h>
|
||||
|
||||
namespace NP {
|
||||
|
||||
|
||||
BaseNodeInfo::BaseNodeInfo(QAbstractSocket *tcp, const HostAddress* address):
|
||||
AbstractNodeInfo(tcp, address){}
|
||||
|
||||
BaseNodeInfo::~BaseNodeInfo() = default;
|
||||
|
||||
bool BaseNodeInfo::isValid() const {
|
||||
return AbstractNodeInfo::isValid();
|
||||
}
|
||||
|
||||
BaseId BaseNodeInfo::selfId() const {
|
||||
return _selfId;
|
||||
}
|
||||
|
||||
void BaseNodeInfo::setSelfId(const BaseId &selfId) {
|
||||
_selfId = selfId;
|
||||
}
|
||||
|
||||
bool BaseNodeInfo::confirmData() const {
|
||||
return AbstractNodeInfo::confirmData();
|
||||
}
|
||||
|
||||
}
|
67
Heart/DataBaseSpace/basenodeinfo.h
Normal file
67
Heart/DataBaseSpace/basenodeinfo.h
Normal file
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* 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 CONNECTIONINFO_H
|
||||
#define CONNECTIONINFO_H
|
||||
|
||||
#include "abstractnodeinfo.h"
|
||||
#include "accesstoken.h"
|
||||
#include "baseid.h"
|
||||
#include "heart_global.h"
|
||||
#include <QByteArray>
|
||||
|
||||
class QAbstractSocket;
|
||||
namespace NP {
|
||||
|
||||
class DbAddress;
|
||||
|
||||
/**
|
||||
* @brief The BaseNodeInfo class contaisn list of nodes id of know this node.
|
||||
*/
|
||||
class NETWORKPROTOCOLSHARED_EXPORT BaseNodeInfo: public AbstractNodeInfo {
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief BaseNodeInfo - create node info from the tcp descriptor
|
||||
* @param tcp - tcp socket dsscriptor
|
||||
*/
|
||||
explicit BaseNodeInfo(QAbstractSocket * tcp = nullptr,
|
||||
const HostAddress* clientAddress = nullptr);
|
||||
~BaseNodeInfo() override;
|
||||
|
||||
/**
|
||||
* @brief isValid
|
||||
* @return true if node is valid.
|
||||
*/
|
||||
bool isValid() const override;
|
||||
|
||||
/**
|
||||
* @brief selfId - it is id of peer node
|
||||
* @return
|
||||
*/
|
||||
BaseId selfId() const;
|
||||
|
||||
/**
|
||||
* @brief setSelfId
|
||||
* @param selfId
|
||||
*/
|
||||
void setSelfId(const BaseId &selfId);
|
||||
|
||||
/**
|
||||
* @brief confirmData - this implementaton check self id of node.
|
||||
* @return true if node contains valid self id.
|
||||
*/
|
||||
bool confirmData() const override;
|
||||
|
||||
protected:
|
||||
BaseId _selfId;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // CONNECTIONINFO_H
|
452
Heart/DataBaseSpace/databasenode.cpp
Normal file
452
Heart/DataBaseSpace/databasenode.cpp
Normal file
@ -0,0 +1,452 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#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 <qsecretrsa2048.h>
|
||||
#include <ping.h>
|
||||
#include <keystorage.h>
|
||||
#include <basenodeinfo.h>
|
||||
#include <networkmember.h>
|
||||
#include <memberpermisionobject.h>
|
||||
|
||||
#define THIS_NODE "this_node_key"
|
||||
namespace NP {
|
||||
|
||||
DataBaseNode::DataBaseNode(NP::SslMode mode, QObject *ptr):
|
||||
AbstractNode(mode, ptr) {
|
||||
|
||||
_webSocketWorker = new WebSocketController(this);
|
||||
|
||||
}
|
||||
|
||||
bool DataBaseNode::initSqlDb(QString DBparamsFile,
|
||||
SqlDBCache *cache,
|
||||
SqlDBWriter *writer) {
|
||||
|
||||
initDefaultDbObjects(cache, writer);
|
||||
|
||||
QVariantMap params;
|
||||
|
||||
if (DBparamsFile.isEmpty()) {
|
||||
params = defaultDbParams();
|
||||
return _db->init(params);
|
||||
}
|
||||
|
||||
if (!_db->init(DBparamsFile)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DataBaseNode::isSqlInited() const {
|
||||
return _db;
|
||||
}
|
||||
|
||||
bool DataBaseNode::run(const QString &addres, unsigned short port) {
|
||||
if (!isSqlInited() && !initSqlDb()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return AbstractNode::run(addres, port);
|
||||
}
|
||||
|
||||
bool DataBaseNode::run(const QString &addres,
|
||||
unsigned short port,
|
||||
const QString &localNodeName) {
|
||||
|
||||
if (localNodeName.isEmpty())
|
||||
return false;
|
||||
|
||||
_localNodeName = localNodeName;
|
||||
|
||||
if (!isSqlInited() && !initSqlDb()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return AbstractNode::run(addres, port);
|
||||
}
|
||||
|
||||
void DataBaseNode::stop() {
|
||||
|
||||
AbstractNode::stop();
|
||||
|
||||
if (db()) {
|
||||
auto writer = _db->writer();
|
||||
delete _db;
|
||||
_db = nullptr;
|
||||
delete writer;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
DataBaseNode::~DataBaseNode() {
|
||||
}
|
||||
|
||||
void DataBaseNode::initDefaultDbObjects(SqlDBCache *cache, SqlDBWriter *writer) {
|
||||
if (!writer) {
|
||||
writer = new AsyncSqlDbWriter();
|
||||
}
|
||||
|
||||
if (!cache) {
|
||||
cache = new SqlDBCache();
|
||||
}
|
||||
|
||||
cache->setWriter(writer);
|
||||
_db = cache;
|
||||
|
||||
connect(_db, &SqlDBCache::sigItemChanged,
|
||||
_webSocketWorker, &WebSocketController::handleItemChanged);
|
||||
}
|
||||
|
||||
|
||||
bool DataBaseNode::welcomeAddress(const HostAddress&) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DataBaseNode::isBanned(const BaseId &node) const {
|
||||
NetworkMember member(node);
|
||||
auto objectFromDataBase = db()->getObject(member);
|
||||
|
||||
return objectFromDataBase->trust() <= 0;
|
||||
}
|
||||
|
||||
void DataBaseNode::nodeConnected(const HostAddress &node) {
|
||||
AbstractNode::nodeConnected(node);
|
||||
welcomeAddress(node);
|
||||
}
|
||||
|
||||
QString DataBaseNode::dbLocation() const {
|
||||
if (db() && db()->writer()) {
|
||||
return db()->writer()->databaseLocation();
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
bool DataBaseNode::sendData(AbstractData *resp,
|
||||
const HostAddress &addere,
|
||||
const Header *req) {
|
||||
return AbstractNode::sendData(resp, addere, req);
|
||||
}
|
||||
|
||||
bool DataBaseNode::sendData(const AbstractData *resp,
|
||||
const HostAddress &addere,
|
||||
const Header *req) {
|
||||
|
||||
return AbstractNode::sendData(resp, addere, req);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool DataBaseNode::sendData(AbstractData *resp,
|
||||
const BaseId &nodeId,
|
||||
const Header *req) {
|
||||
|
||||
|
||||
if (!resp || !resp->prepareToSend()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return sendData(const_cast<const AbstractData*>(resp), nodeId, req);
|
||||
}
|
||||
|
||||
bool DataBaseNode::sendData(const AbstractData *resp, const BaseId &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->selfId() == nodeId) {
|
||||
return sendData(resp, it.key(), req);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void DataBaseNode::badRequest(const HostAddress &address, const Header &req, const QString msg) {
|
||||
AbstractNode::badRequest(address, req, msg);
|
||||
}
|
||||
|
||||
void DataBaseNode::badRequest(const BaseId &address, const Header &req, const QString msg) {
|
||||
|
||||
if (!changeTrust(address, REQUEST_ERROR)) {
|
||||
|
||||
QuasarAppUtils::Params::log("Bad request detected, bud responce command not sendet!"
|
||||
" because trust not changed",
|
||||
QuasarAppUtils::Error);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
auto bad = BadRequest(msg);
|
||||
if (!sendData(&bad, address, &req)) {
|
||||
return;
|
||||
}
|
||||
|
||||
QuasarAppUtils::Params::log("Bad request sendet to adderess: " +
|
||||
address.toBase64(),
|
||||
QuasarAppUtils::Info);
|
||||
}
|
||||
|
||||
bool DataBaseNode::changeTrust(const HostAddress &id, int diff) {
|
||||
return AbstractNode::changeTrust(id, diff);
|
||||
}
|
||||
|
||||
bool DataBaseNode::changeTrust(const BaseId &id, int diff) {
|
||||
if (!_db)
|
||||
return false;
|
||||
|
||||
auto client = _db->getObject(NetworkMember{id});
|
||||
|
||||
if (!client) {
|
||||
|
||||
QuasarAppUtils::Params::log("Bad request detected, bud responce command not sendet!"
|
||||
" because client == null",
|
||||
QuasarAppUtils::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
auto clone = client->clone().staticCast<NetworkMember>();
|
||||
clone->changeTrust(diff);
|
||||
|
||||
if (!_db->saveObject(clone.data())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ParserResult DataBaseNode::parsePackage(const Package &pkg,
|
||||
const AbstractNodeInfo *sender) {
|
||||
auto parentResult = AbstractNode::parsePackage(pkg, sender);
|
||||
if (parentResult != ParserResult::NotProcessed) {
|
||||
return parentResult;
|
||||
}
|
||||
|
||||
if (H_16<WebSocket>() == pkg.hdr.command) {
|
||||
WebSocket obj(pkg);
|
||||
|
||||
BaseId requesterId = getSender(sender, &obj);
|
||||
|
||||
if (!obj.isValid()) {
|
||||
badRequest(sender->networkAddress(), pkg.hdr);
|
||||
return ParserResult::Error;
|
||||
}
|
||||
|
||||
if (!workWithSubscribe(obj, requesterId, *sender)) {
|
||||
badRequest(sender->networkAddress(), pkg.hdr);
|
||||
return ParserResult::Error;
|
||||
}
|
||||
|
||||
return ParserResult::Processed;
|
||||
|
||||
} else if (H_16<WebSocketSubscriptions>() == pkg.hdr.command) {
|
||||
WebSocketSubscriptions obj(pkg);
|
||||
if (!obj.isValid()) {
|
||||
badRequest(sender->networkAddress(), pkg.hdr);
|
||||
return ParserResult::Error;
|
||||
}
|
||||
|
||||
incomingData(&obj, sender->networkAddress());
|
||||
return ParserResult::Processed;
|
||||
}
|
||||
|
||||
return ParserResult::NotProcessed;
|
||||
}
|
||||
|
||||
QString DataBaseNode::hashgenerator(const QByteArray &pass) {
|
||||
return QCryptographicHash::hash(
|
||||
QCryptographicHash::hash(pass, QCryptographicHash::Sha256) + "QuassarAppSoult",
|
||||
QCryptographicHash::Sha256);
|
||||
}
|
||||
|
||||
SqlDBCache *DataBaseNode::db() const {
|
||||
return _db;
|
||||
}
|
||||
|
||||
bool DataBaseNode::workWithSubscribe(const WebSocket &rec,
|
||||
const BaseId &clientOrNodeid,
|
||||
const AbstractNodeInfo & sender) {
|
||||
|
||||
auto _db = db();
|
||||
if (_db)
|
||||
return false;
|
||||
|
||||
switch (static_cast<WebSocketRequest>(rec.getRequestCmd())) {
|
||||
|
||||
case WebSocketRequest::Subscribe: {
|
||||
return _webSocketWorker->subscribe(clientOrNodeid, rec.address());
|
||||
}
|
||||
|
||||
case WebSocketRequest::Unsubscribe: {
|
||||
_webSocketWorker->unsubscribe(clientOrNodeid, rec.address());
|
||||
return true;
|
||||
}
|
||||
|
||||
case WebSocketRequest::SubscribeList: {
|
||||
|
||||
WebSocketSubscriptions resp;
|
||||
resp.setAddresses(_webSocketWorker->list(clientOrNodeid));
|
||||
|
||||
return sendData(&resp, sender.networkAddress());
|
||||
}
|
||||
|
||||
default: break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
QVariantMap DataBaseNode::defaultDbParams() const {
|
||||
|
||||
return {
|
||||
{"DBDriver", "QSQLITE"},
|
||||
{"DBFilePath", DEFAULT_DB_PATH + "/" + _localNodeName + "/" + _localNodeName + "_" + DEFAULT_DB_NAME},
|
||||
{"DBInitFile", DEFAULT_DB_INIT_FILE_PATH}
|
||||
};
|
||||
}
|
||||
|
||||
DBOperationResult NP::DataBaseNode::getObject(const NP::BaseId &requester,
|
||||
const NP::DBObject &templateObj,
|
||||
const 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 DataBaseNode::getObjects(const BaseId &requester,
|
||||
const DBObject &templateObj,
|
||||
QList<const DBObject *> *result) const {
|
||||
if (!_db && !result) {
|
||||
return DBOperationResult::Unknown;
|
||||
}
|
||||
|
||||
if (!_db->getAllObjects(templateObj, *result)) {
|
||||
return DBOperationResult::Unknown;
|
||||
}
|
||||
|
||||
for (const auto& obj: *result) {
|
||||
if (!obj)
|
||||
return DBOperationResult::Unknown;
|
||||
|
||||
auto permisionResult = checkPermission(requester, obj->dbAddress(),
|
||||
Permission::Read);
|
||||
if (permisionResult != DBOperationResult::Allowed) {
|
||||
return permisionResult;
|
||||
}
|
||||
}
|
||||
|
||||
return DBOperationResult::Allowed;
|
||||
}
|
||||
|
||||
DBOperationResult DataBaseNode::setObject(const BaseId &requester,
|
||||
const DBObject *saveObject) {
|
||||
|
||||
if (!_db) {
|
||||
return DBOperationResult::Unknown;
|
||||
}
|
||||
|
||||
auto permisionResult = checkPermission(requester,
|
||||
saveObject->dbAddress(),
|
||||
Permission::Write);
|
||||
if (permisionResult != DBOperationResult::Allowed) {
|
||||
return permisionResult;
|
||||
}
|
||||
|
||||
if (!_db->saveObject(saveObject)) {
|
||||
return DBOperationResult::Unknown;
|
||||
}
|
||||
|
||||
return DBOperationResult::Allowed;
|
||||
}
|
||||
|
||||
BaseId DataBaseNode::getSender(const AbstractNodeInfo *connectInfo, const AbstractData *) const {
|
||||
|
||||
auto info = dynamic_cast<const BaseNodeInfo*>(connectInfo);
|
||||
|
||||
if (!info)
|
||||
return {};
|
||||
|
||||
return info->selfId();
|
||||
}
|
||||
|
||||
DBOperationResult DataBaseNode::checkPermission(const BaseId &requester,
|
||||
const DbAddress &objectAddress,
|
||||
const Permission& requarimentPermision) const {
|
||||
const NetworkMember *member = _db->getObject(NetworkMember{requester});
|
||||
if (!member) {
|
||||
return DBOperationResult::Unknown;
|
||||
}
|
||||
|
||||
const MemberPermisionObject *permision =
|
||||
_db->getObject(MemberPermisionObject({requester, objectAddress}));
|
||||
|
||||
if (!permision) {
|
||||
return DBOperationResult::Unknown;
|
||||
}
|
||||
|
||||
if (permision->permisions() < requarimentPermision) {
|
||||
return DBOperationResult::Forbidden;
|
||||
}
|
||||
|
||||
return DBOperationResult::Allowed;
|
||||
}
|
||||
|
||||
DBOperationResult DataBaseNode::deleteObject(const BaseId &requester,
|
||||
const DBObject *dbObject) {
|
||||
|
||||
if (!_db) {
|
||||
return DBOperationResult::Unknown;
|
||||
}
|
||||
|
||||
auto permisionResult = checkPermission(requester,
|
||||
dbObject->dbAddress(),
|
||||
Permission::Write);
|
||||
if (permisionResult != DBOperationResult::Allowed) {
|
||||
return permisionResult;
|
||||
}
|
||||
|
||||
if (!_db->deleteObject(dbObject)) {
|
||||
return DBOperationResult::Unknown;
|
||||
}
|
||||
|
||||
return DBOperationResult::Allowed;
|
||||
}
|
||||
|
||||
}
|
||||
|
310
Heart/DataBaseSpace/databasenode.h
Normal file
310
Heart/DataBaseSpace/databasenode.h
Normal file
@ -0,0 +1,310 @@
|
||||
/*
|
||||
* 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 DATABASENODE_H
|
||||
#define DATABASENODE_H
|
||||
|
||||
#include "abstractnode.h"
|
||||
#include <dbobject.h>
|
||||
#include <hostaddress.h>
|
||||
#include <permission.h>
|
||||
|
||||
|
||||
namespace NP {
|
||||
|
||||
class SqlDBCache;
|
||||
class SqlDBWriter;
|
||||
class WebSocket;
|
||||
class WebSocketController;
|
||||
class DbAddress;
|
||||
class BaseId;
|
||||
|
||||
|
||||
/**
|
||||
* @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 NETWORKPROTOCOLSHARED_EXPORT DataBaseNode : public AbstractNode
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief BaseNode
|
||||
* @param mode
|
||||
* @param ptr
|
||||
*/
|
||||
DataBaseNode(SslMode mode = SslMode::NoSSL, QObject * ptr = nullptr);
|
||||
~DataBaseNode() override;
|
||||
|
||||
/**
|
||||
* @brief intSqlDb - this function init database of node
|
||||
* @param DBparamsFile - path to json file with all patarams
|
||||
* @param cache - new SqlDBCache object
|
||||
* @param writer - new SqlDBWriter
|
||||
* @return true if all good
|
||||
*/
|
||||
virtual bool initSqlDb( QString DBparamsFile = "",
|
||||
SqlDBCache * cache = nullptr,
|
||||
SqlDBWriter* writer = nullptr);
|
||||
|
||||
/**
|
||||
* @brief isSqlInited
|
||||
* @return return true if intSqlDb invocked correctly;
|
||||
*/
|
||||
bool isSqlInited() const;
|
||||
|
||||
|
||||
/**
|
||||
* @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
|
||||
* @return true if node is deployed successful
|
||||
*/
|
||||
virtual bool run(const QString &addres, unsigned short port,
|
||||
const QString &localNodeName);
|
||||
|
||||
/**
|
||||
* @brief stop - this implementation stop work database and push to database all cache data.
|
||||
*/
|
||||
void stop() override;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief defaultDbParams
|
||||
* @return
|
||||
*/
|
||||
virtual QVariantMap defaultDbParams() const;
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* @brief initDefaultDbObjects create default cache and db writer if pointer is null
|
||||
* @param cache
|
||||
* @param writer
|
||||
*/
|
||||
void initDefaultDbObjects(SqlDBCache *cache, SqlDBWriter *writer);
|
||||
|
||||
/**
|
||||
* @brief parsePackage
|
||||
* @param pkg
|
||||
* @param sender
|
||||
* @return
|
||||
*/
|
||||
ParserResult parsePackage(const Package &pkg,
|
||||
const AbstractNodeInfo* sender) override;
|
||||
|
||||
|
||||
/**
|
||||
* @brief sendData - send data to an ip address
|
||||
* @param resp
|
||||
* @param addere
|
||||
* @param req
|
||||
* @return true if a function finished seccussful
|
||||
*/
|
||||
bool sendData(AbstractData *resp,
|
||||
const HostAddress &addere,
|
||||
const Header *req = nullptr) override;
|
||||
|
||||
/**
|
||||
* @brief sendData - send data to an ip address
|
||||
* @param resp
|
||||
* @param addere
|
||||
* @param req
|
||||
* @return true if a function finished seccussful
|
||||
*/
|
||||
bool sendData(const AbstractData *resp,
|
||||
const HostAddress &addere,
|
||||
const Header *req = nullptr) override;
|
||||
|
||||
/**
|
||||
* @brief sendDataToId - send data to node or clientby them id. This implementation prepare object to sending.
|
||||
* @param resp - responce package
|
||||
* @param nodeId - id of target node
|
||||
* @param req - header of request
|
||||
* @return true if data sendet seccussful
|
||||
*/
|
||||
virtual bool sendData(AbstractData *resp, const BaseId &nodeId,
|
||||
const Header *req = nullptr);
|
||||
|
||||
/**
|
||||
* @brief sendDataToId - send data to node or clientby them id.
|
||||
* @param resp - responce package
|
||||
* @param nodeId - id of target node
|
||||
* @param req - header of request
|
||||
* @return true if data sendet seccussful
|
||||
*/
|
||||
virtual bool sendData(const AbstractData *resp, const BaseId &nodeId,
|
||||
const Header *req = nullptr);
|
||||
/**
|
||||
* @brief badRequest -send bad request and change trus for ip address
|
||||
* @param address
|
||||
* @param req
|
||||
* @param msg
|
||||
*/
|
||||
void badRequest(const HostAddress &address, const Header &req,
|
||||
const QString msg = "") override;
|
||||
|
||||
/**
|
||||
* @brief badRequest - send bad request to node with id
|
||||
* @param address - id of target node or client
|
||||
* @param req - header of an accepted request.
|
||||
* @param msg
|
||||
*/
|
||||
virtual void badRequest(const BaseId &address, const Header &req,
|
||||
const QString msg = "");
|
||||
|
||||
/**
|
||||
* @brief changeTrust - change trust of ip address
|
||||
* @param id - ip address of node
|
||||
* @param diff
|
||||
*/
|
||||
bool changeTrust(const HostAddress &id, int diff) override;
|
||||
|
||||
/**
|
||||
* @brief changeTrust change trus of node with id.
|
||||
* @param id
|
||||
* @param diff
|
||||
* @return true if functin finished seccussful
|
||||
*/
|
||||
virtual bool changeTrust(const BaseId &id, int diff);
|
||||
|
||||
/**
|
||||
* @brief hashgenerator
|
||||
* @param pass
|
||||
*/
|
||||
virtual QString hashgenerator(const QByteArray &pass);
|
||||
|
||||
|
||||
/**
|
||||
* @brief nodeConnected - this implementation call a welcomeAddress method.
|
||||
* @param node
|
||||
*/
|
||||
void nodeConnected(const HostAddress &node) override;
|
||||
|
||||
/**
|
||||
* @brief db
|
||||
* @return pinter to data base
|
||||
*/
|
||||
SqlDBCache* db() const;
|
||||
|
||||
/**
|
||||
* @brief workWithSubscribe - this metod work work with subscribe commnads
|
||||
* @param rec request data
|
||||
* @param address sendet address
|
||||
* @return true if data parsed seccusseful
|
||||
*/
|
||||
bool workWithSubscribe(const WebSocket &rec,
|
||||
const BaseId &clientOrNodeid, const AbstractNodeInfo &sender);
|
||||
|
||||
/**
|
||||
* @brief deleteObject - delete object by address dbObject
|
||||
* @param requester - reqester.
|
||||
* @param dbObject
|
||||
* @return result of operation (allow, forbiden unknown)
|
||||
*/
|
||||
DBOperationResult deleteObject(const BaseId &requester,
|
||||
const DBObject *dbObject);
|
||||
|
||||
/**
|
||||
* @brief getObject - general method for geting object wth check permisions
|
||||
* this function check permishen to requested object and set new object to res if access granted.
|
||||
* @param requester - requser node or client
|
||||
* @param templateObj - object with request
|
||||
* @param result - pointer to pointer of result object
|
||||
* @return operation status
|
||||
*/
|
||||
DBOperationResult getObject(const BaseId &requester,
|
||||
const DBObject &templateObj,
|
||||
const DBObject **result) const;
|
||||
|
||||
|
||||
/**
|
||||
* @brief getObjects - general object for get object
|
||||
* this function check permishen to requested object and set new object to res if access granted.
|
||||
* @param requester - requser node or client
|
||||
* @param templateObj - object with request
|
||||
* @param result - pointer to list of pointers with result objects
|
||||
* @return operation status
|
||||
*/
|
||||
DBOperationResult getObjects(const BaseId &requester,
|
||||
const DBObject &templateObj,
|
||||
QList<const DBObject *> *result) const;
|
||||
|
||||
/**
|
||||
* @brief setObject
|
||||
* @param saveObject
|
||||
* @param requiredNodeAddere
|
||||
* @param dbObject
|
||||
* @return operation status
|
||||
*/
|
||||
DBOperationResult setObject(const BaseId &requester,
|
||||
const DBObject *saveObject);
|
||||
|
||||
/**
|
||||
* @brief getSender - this method return id of requester.
|
||||
* @default Base implementation get id from BaseNdoeInfo.
|
||||
* @param connectInfo - info about connect
|
||||
* @param requestData - data of request
|
||||
* @return id of requester member
|
||||
*/
|
||||
virtual BaseId getSender(const AbstractNodeInfo *connectInfo, const AbstractData *requestData) const;
|
||||
|
||||
/**
|
||||
* @brief checkPermision - check permision of requester to objectAddress
|
||||
* Override this method for your backend
|
||||
* @param requester - user on node or another object of network
|
||||
* @param objectAddress - addres to database object
|
||||
* @param requarimentPermision - needed permision for requester
|
||||
* @return DBOperationResult::Alowed if permission granted
|
||||
*/
|
||||
virtual DBOperationResult checkPermission(const BaseId& requester,
|
||||
const DbAddress& objectAddress,
|
||||
const Permission& requarimentPermision) const;
|
||||
|
||||
/**
|
||||
* @brief dbLocation - return location of database of node.
|
||||
* @return path to the location of database
|
||||
*/
|
||||
QString dbLocation() const;
|
||||
|
||||
/**
|
||||
* @brief welcomeAddress - this method send to the ip information about yaster self.
|
||||
* @param ip - host address of the peer node obeject
|
||||
* @return true if all iformation sendet succesful
|
||||
*/
|
||||
virtual bool welcomeAddress(const HostAddress &ip);
|
||||
|
||||
/**
|
||||
* @brief isBanned - check trust of node, if node trus is lover of 0 return true.
|
||||
* @param member
|
||||
* @return true if node is banned
|
||||
*/
|
||||
bool isBanned(const BaseId& member) const;
|
||||
private:
|
||||
|
||||
SqlDBCache *_db = nullptr;
|
||||
QString _localNodeName;
|
||||
WebSocketController *_webSocketWorker = nullptr;
|
||||
|
||||
|
||||
friend class WebSocketController;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
#endif // DATABASENODE_H
|
70
Heart/DataBaseSpace/dbaddress.cpp
Normal file
70
Heart/DataBaseSpace/dbaddress.cpp
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "dbaddress.h"
|
||||
#include <QDataStream>
|
||||
#include <QHash>
|
||||
|
||||
|
||||
namespace NP {
|
||||
|
||||
qint64 qHash(const DbAddress &address) {
|
||||
return qHash(address.id().toRaw() + address.table());
|
||||
}
|
||||
|
||||
DbAddress::DbAddress(const QString &table, const BaseId &id) {
|
||||
this->_table = table;
|
||||
this->_id = id;
|
||||
}
|
||||
|
||||
bool operator==(const DbAddress & left, const DbAddress &other) {
|
||||
return left._table == other._table && left._id == other._id;
|
||||
}
|
||||
|
||||
QDataStream &DbAddress::fromStream(QDataStream &stream) {
|
||||
stream >> _id;
|
||||
stream >> _table;
|
||||
return stream;
|
||||
}
|
||||
|
||||
QDataStream &DbAddress::toStream(QDataStream &stream) const {
|
||||
stream << _id;
|
||||
stream << _table;
|
||||
return stream;
|
||||
}
|
||||
|
||||
QString DbAddress::toString() const {
|
||||
return QString("DbAddress: id:%0, table:%1").
|
||||
arg(QString(_id.toBase64())).
|
||||
arg(_table);
|
||||
}
|
||||
|
||||
bool operator!=(const DbAddress &left, const DbAddress &other) {
|
||||
return !operator==(left, other);
|
||||
}
|
||||
|
||||
bool DbAddress::isValid() const {
|
||||
return _id.isValid() && _table.size();
|
||||
}
|
||||
|
||||
const QString& DbAddress::table() const {
|
||||
return _table;
|
||||
}
|
||||
|
||||
void DbAddress::setTable(const QString &table) {
|
||||
_table = table;
|
||||
}
|
||||
|
||||
const BaseId& DbAddress::id() const {
|
||||
return _id;
|
||||
}
|
||||
|
||||
void DbAddress::setId(const BaseId &id) {
|
||||
_id = id;
|
||||
}
|
||||
|
||||
}
|
58
Heart/DataBaseSpace/dbaddress.h
Normal file
58
Heart/DataBaseSpace/dbaddress.h
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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 DBADDRESS_H
|
||||
#define DBADDRESS_H
|
||||
|
||||
#include "streambase.h"
|
||||
#include "basedefines.h"
|
||||
#include "baseid.h"
|
||||
|
||||
namespace NP {
|
||||
|
||||
/**
|
||||
* @brief The DbAddress class - this is address of data base object
|
||||
*/
|
||||
class NETWORKPROTOCOLSHARED_EXPORT DbAddress : public StreamBase {
|
||||
|
||||
public:
|
||||
|
||||
DbAddress() = default;
|
||||
DbAddress(const QString& table, const BaseId& id);
|
||||
|
||||
QDataStream &fromStream(QDataStream &stream);
|
||||
QDataStream &toStream(QDataStream &stream) const;
|
||||
|
||||
/**
|
||||
* @brief toString - return a string implementation fo this object
|
||||
* @return string of object
|
||||
*/
|
||||
QString toString() const;
|
||||
|
||||
friend bool operator== (const DbAddress& left, const DbAddress& other);
|
||||
friend bool operator!= (const DbAddress& left, const DbAddress& other);
|
||||
|
||||
bool isValid() const;
|
||||
|
||||
const QString& table() const;
|
||||
void setTable(const QString &table);
|
||||
|
||||
const BaseId &id() const;
|
||||
void setId(const BaseId &id);
|
||||
|
||||
private:
|
||||
|
||||
QString _table;
|
||||
BaseId _id;
|
||||
};
|
||||
|
||||
qint64 qHash(const DbAddress& address);
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // DBADDRESS_H
|
42
Heart/DataBaseSpace/dbaddresskey.cpp
Normal file
42
Heart/DataBaseSpace/dbaddresskey.cpp
Normal file
@ -0,0 +1,42 @@
|
||||
#include "dbaddresskey.h"
|
||||
namespace NP {
|
||||
|
||||
DbAddressKey::DbAddressKey() {
|
||||
|
||||
}
|
||||
|
||||
DbAddressKey::DbAddressKey(const DbAddress &address):
|
||||
DbAddress(address) {
|
||||
|
||||
}
|
||||
|
||||
DbAddressKey::DbAddressKey(const QString &address, const BaseId &id):
|
||||
DbAddress(address, id) {
|
||||
|
||||
}
|
||||
|
||||
unsigned int DbAddressKey::hash() const {
|
||||
return qHash(*static_cast<const DbAddress*>(this));
|
||||
}
|
||||
|
||||
const BaseId &DbAddressKey::id() const {
|
||||
return DbAddress::id();
|
||||
}
|
||||
|
||||
const QString &DbAddressKey::table() const {
|
||||
return DbAddress::table();
|
||||
}
|
||||
|
||||
bool DbAddressKey::equal(const AbstractKey *other) const {
|
||||
auto otherObject = dynamic_cast<const DbAddressKey*>(other);
|
||||
|
||||
if (!otherObject)
|
||||
return false;
|
||||
|
||||
return operator==(*static_cast<const DbAddress*>(this), *otherObject);
|
||||
}
|
||||
|
||||
bool DbAddressKey::isValid() const {
|
||||
return DbAddress::isValid();
|
||||
}
|
||||
}
|
36
Heart/DataBaseSpace/dbaddresskey.h
Normal file
36
Heart/DataBaseSpace/dbaddresskey.h
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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 DBADDRESSKEY_H
|
||||
#define DBADDRESSKEY_H
|
||||
#include "abstractkey.h"
|
||||
#include "dbaddress.h"
|
||||
|
||||
namespace NP {
|
||||
|
||||
/**
|
||||
* @brief The DbAddressKey class - key provider for DbAddress
|
||||
*/
|
||||
class NETWORKPROTOCOLSHARED_EXPORT DbAddressKey: public DbAddress, public AbstractKey
|
||||
{
|
||||
public:
|
||||
DbAddressKey();
|
||||
DbAddressKey(const DbAddress& address);
|
||||
DbAddressKey(const QString& address, const BaseId& id);
|
||||
|
||||
unsigned int hash() const override;
|
||||
|
||||
const BaseId &id() const override;
|
||||
const QString &table() const override;
|
||||
bool equal(const AbstractKey *other) const override;
|
||||
|
||||
bool isValid() const override;
|
||||
|
||||
};
|
||||
}
|
||||
#endif // DBADDRESSKEY_H
|
30
Heart/DataBaseSpace/dbcachekey.cpp
Normal file
30
Heart/DataBaseSpace/dbcachekey.cpp
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
#include "dbcachekey.h"
|
||||
|
||||
#include <abstractkey.cpp>
|
||||
namespace NP {
|
||||
|
||||
DBCacheKey *DBCacheKey::instance() {
|
||||
static auto ptr = new DBCacheKey();
|
||||
return ptr;
|
||||
}
|
||||
|
||||
QString DBCacheKey::description(uint hash) const {
|
||||
auto val = value(hash);
|
||||
|
||||
if (!val)
|
||||
return "";
|
||||
|
||||
return QString("table:%0 id:%1").arg(val->id().toBase64(), val->table());
|
||||
}
|
||||
|
||||
DBCacheKey::DBCacheKey() {}
|
||||
}
|
||||
|
83
Heart/DataBaseSpace/dbcachekey.h
Normal file
83
Heart/DataBaseSpace/dbcachekey.h
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* 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 DBCACHEKEY_H
|
||||
#define DBCACHEKEY_H
|
||||
|
||||
#include "baseid.h"
|
||||
|
||||
#include <abstractkey.h>
|
||||
#include <QHash>
|
||||
#include <heart_global.h>
|
||||
|
||||
namespace NP {
|
||||
|
||||
/**
|
||||
* @brief The DBCacheKey class - is database main key value
|
||||
*/
|
||||
class NETWORKPROTOCOLSHARED_EXPORT DBCacheKey
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief instance
|
||||
* @return singleton of object
|
||||
*/
|
||||
static DBCacheKey* instance();
|
||||
|
||||
template <class TYPE = AbstractKey>
|
||||
/**
|
||||
* @brief value - return vale from key
|
||||
* @param key - hash of ke 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 - return hash key and save object into objects table
|
||||
* @param value - the value of a key objekt
|
||||
* @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 - return string description of id
|
||||
* @param hash
|
||||
* @return
|
||||
*/
|
||||
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
|
35
Heart/DataBaseSpace/iobjectprovider.cpp
Normal file
35
Heart/DataBaseSpace/iobjectprovider.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "iobjectprovider.h"
|
||||
|
||||
namespace NP {
|
||||
iObjectProvider::iObjectProvider() = default;
|
||||
|
||||
iObjectProvider::~iObjectProvider() = default;
|
||||
|
||||
const DBObject *iObjectProvider::getObjectRaw(const DBObject &templateVal) {
|
||||
|
||||
if (!dynamic_cast<const DBObject*>(&templateVal)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QList<const DBObject *> list;
|
||||
if (!getAllObjects(templateVal, list)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (list.size() > 1) {
|
||||
QuasarAppUtils::Params::log("getObject method returned more than one object,"
|
||||
" the first object was selected as the result, all the rest were lost.",
|
||||
QuasarAppUtils::Warning);
|
||||
}
|
||||
|
||||
return list.first();
|
||||
}
|
||||
|
||||
}
|
77
Heart/DataBaseSpace/iobjectprovider.h
Normal file
77
Heart/DataBaseSpace/iobjectprovider.h
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* 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 IOBJECTPROVIDER_H
|
||||
#define IOBJECTPROVIDER_H
|
||||
#include "heart_global.h"
|
||||
|
||||
#include <QSharedPointer>
|
||||
#include <dbobject.h>
|
||||
#include <quasarapp.h>
|
||||
|
||||
namespace NP {
|
||||
|
||||
class AbstractData;
|
||||
|
||||
class NETWORKPROTOCOLSHARED_EXPORT iObjectProvider
|
||||
{
|
||||
public:
|
||||
iObjectProvider();
|
||||
virtual ~iObjectProvider();
|
||||
|
||||
/**
|
||||
* @brief getObject - this method return pointer to DBObject created by select method of template object.
|
||||
* @param obj - template object with a select db request.
|
||||
* @return return pointer to DBObject ot nullptr id object not exits.
|
||||
*/
|
||||
template<class TYPE>
|
||||
const TYPE *getObject(const TYPE &templateVal) {
|
||||
|
||||
auto val = getObjectRaw(templateVal);
|
||||
const TYPE* result = dynamic_cast<const TYPE*>(val);
|
||||
if (!result && val) {
|
||||
QuasarAppUtils::Params::log("getObject method returned object with deffirent type of TYPE,"
|
||||
" check getAllObjects merhod",
|
||||
QuasarAppUtils::Error);
|
||||
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief getObjectRaw - return object without test object type
|
||||
* @note if you want get object with check object type use getObject method.
|
||||
* @param templateVal - template object with request to database
|
||||
* @return - return database object pointer (not casted)
|
||||
*/
|
||||
const DBObject *getObjectRaw(const DBObject &templateVal);
|
||||
|
||||
/**
|
||||
* @brief getAllObjects - executable select method of objects and return list of all selected objects
|
||||
* @param obj - template object with select request.
|
||||
* @param result - return value, list of selected objects.
|
||||
* @return true if objects have in db else false.
|
||||
*/
|
||||
virtual bool getAllObjects(const DBObject &templateObject, QList<const DBObject *> &result) = 0;
|
||||
|
||||
/**
|
||||
* @brief saveObject
|
||||
* @return
|
||||
*/
|
||||
virtual bool saveObject(const DBObject* saveObject) = 0;
|
||||
|
||||
/**
|
||||
* @brief deleteObject
|
||||
* @return
|
||||
*/
|
||||
virtual bool deleteObject(const DBObject* obj) = 0;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
#endif // IOBJECTPROVIDER_H
|
184
Heart/DataBaseSpace/packages/dbobject.cpp
Normal file
184
Heart/DataBaseSpace/packages/dbobject.cpp
Normal file
@ -0,0 +1,184 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "dbaddresskey.h"
|
||||
#include "dbcachekey.h"
|
||||
#include "dbobject.h"
|
||||
#include <QDataStream>
|
||||
#include <QDateTime>
|
||||
#include <QSqlQuery>
|
||||
#include <QHash>
|
||||
#include <QSqlRecord>
|
||||
#include <QVariantMap>
|
||||
#include <QSharedPointer>
|
||||
|
||||
namespace NP {
|
||||
|
||||
DBObject::DBObject(const QString &tableName) {
|
||||
clear();
|
||||
_dbId.setTable(tableName);
|
||||
}
|
||||
|
||||
DBObject::~DBObject() {
|
||||
|
||||
}
|
||||
|
||||
QString DBObject::tableName() const {
|
||||
return _dbId.table();
|
||||
}
|
||||
|
||||
PrepareResult DBObject::prepareSelectQuery(QSqlQuery &q) const {
|
||||
|
||||
QString queryString = "SELECT * FROM %0 " + getWhereBlock();
|
||||
|
||||
queryString = queryString.arg(tableName());
|
||||
|
||||
if (!q.prepare(queryString)) {
|
||||
return PrepareResult::Fail;
|
||||
}
|
||||
|
||||
return PrepareResult::Success;
|
||||
}
|
||||
|
||||
bool DBObject::fromSqlRecord(const QSqlRecord &q) {
|
||||
|
||||
if (q.contains("id")) {
|
||||
setId(q.value("id").toString());
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DBObject::isCached() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DBObject::isBundle() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint DBObject::dbKey() const {
|
||||
return HASH_KEY(DbAddressKey(_dbId));
|
||||
}
|
||||
|
||||
QPair<QString, QString> DBObject::altarnativeKey() const {
|
||||
return {};
|
||||
}
|
||||
|
||||
DbAddress DBObject::dbAddress() const {
|
||||
return _dbId;
|
||||
}
|
||||
|
||||
QSharedPointer<DBObject> DBObject::clone() const {
|
||||
return QSharedPointer<DBObject>(cloneRaw());
|
||||
}
|
||||
|
||||
DBObject *DBObject::cloneRaw() const {
|
||||
auto cloneObject = factory();
|
||||
if (!cloneObject->copyFrom(this)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
cloneObject->init();
|
||||
|
||||
return cloneObject;
|
||||
}
|
||||
|
||||
QString DBObject::toString() const {
|
||||
return AbstractData::toString() +
|
||||
QString(" %0").arg(_dbId.toString());
|
||||
}
|
||||
|
||||
QString DBObject::getWhereBlock() const {
|
||||
QString whereBlock = "WHERE ";
|
||||
|
||||
if (getId().isValid()) {
|
||||
whereBlock += "id='" + getId().toBase64() + "'";
|
||||
} else {
|
||||
auto altKeys = altarnativeKey();
|
||||
if (altKeys.first.isEmpty()) {
|
||||
return {};
|
||||
}
|
||||
whereBlock += altKeys.first + "='" + altKeys.second + "'";
|
||||
|
||||
}
|
||||
|
||||
return whereBlock;
|
||||
}
|
||||
|
||||
PrepareResult DBObject::prepareRemoveQuery(QSqlQuery &q) const {
|
||||
|
||||
QString queryString = "DELETE FROM %0 " + getWhereBlock();
|
||||
|
||||
queryString = queryString.arg(tableName());
|
||||
|
||||
if (!q.prepare(queryString)) {
|
||||
return PrepareResult::Fail;
|
||||
}
|
||||
|
||||
return PrepareResult::Success;
|
||||
}
|
||||
|
||||
QDataStream &DBObject::fromStream(QDataStream &stream) {
|
||||
AbstractData::fromStream(stream);
|
||||
|
||||
stream >> _dbId;
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
QDataStream &DBObject::toStream(QDataStream &stream) const {
|
||||
AbstractData::toStream(stream);
|
||||
|
||||
stream << _dbId;
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
bool DBObject::init() {
|
||||
if (!AbstractData::init())
|
||||
return false;
|
||||
|
||||
if (isBundle()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
_dbId.setId(generateId());
|
||||
return _dbId.isValid();
|
||||
}
|
||||
|
||||
bool DBObject::isValid() const {
|
||||
return AbstractData::isValid() && _dbId.isValid();
|
||||
}
|
||||
|
||||
bool DBObject::copyFrom(const AbstractData * other) {
|
||||
if (!AbstractData::copyFrom(other))
|
||||
return false;
|
||||
|
||||
auto otherObject = dynamic_cast<const DBObject*>(other);
|
||||
if (!otherObject)
|
||||
return false;
|
||||
|
||||
this->_dbId = otherObject->_dbId;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
BaseId DBObject::getId() const {
|
||||
return dbAddress().id();
|
||||
}
|
||||
|
||||
void DBObject::setId(const BaseId& id) {
|
||||
_dbId.setId(id);
|
||||
}
|
||||
|
||||
void DBObject::clear() {
|
||||
setId({});
|
||||
}
|
||||
|
||||
}
|
212
Heart/DataBaseSpace/packages/dbobject.h
Normal file
212
Heart/DataBaseSpace/packages/dbobject.h
Normal file
@ -0,0 +1,212 @@
|
||||
/*
|
||||
* 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 DBOBJECT_H
|
||||
#define DBOBJECT_H
|
||||
#include <QSqlRecord>
|
||||
#include <QVariantMap>
|
||||
#include "abstractdata.h"
|
||||
#include "heart_global.h"
|
||||
#include "dbaddress.h"
|
||||
#include "basedefines.h"
|
||||
#include "dbcachekey.h"
|
||||
|
||||
class QSqlQuery;
|
||||
|
||||
namespace NP {
|
||||
|
||||
/**
|
||||
* @brief The PrepareResult enum - result of work prepare sql query
|
||||
*/
|
||||
enum class PrepareResult {
|
||||
/// prepare finished fail.
|
||||
Fail,
|
||||
/// prepare finished succussful
|
||||
Success,
|
||||
/// prepare disabled for method. Use this case for disable prepare method for object without errors.
|
||||
Disabled,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The DBObject class- main class for work with data base.
|
||||
*/
|
||||
class NETWORKPROTOCOLSHARED_EXPORT DBObject : public AbstractData
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief DBObject
|
||||
*/
|
||||
DBObject(const QString& tableName);
|
||||
|
||||
~DBObject() override;
|
||||
|
||||
//// AbstractData interface
|
||||
bool isValid() const override;
|
||||
|
||||
/**
|
||||
* @brief copyFrom get all data from other
|
||||
* @arg other - other data package
|
||||
* @return return true if method finished seccussful
|
||||
*/
|
||||
bool copyFrom(const AbstractData * other) override;
|
||||
|
||||
/**
|
||||
* @brief getId
|
||||
* @return id of objcet
|
||||
*/
|
||||
BaseId getId() const;
|
||||
|
||||
/**
|
||||
* @brief setId - set new id for db object
|
||||
* @param id
|
||||
*/
|
||||
void setId(const BaseId& id);
|
||||
|
||||
/**
|
||||
* @brief clear
|
||||
*/
|
||||
virtual void clear();
|
||||
|
||||
/**
|
||||
* @brief tableName
|
||||
* @return
|
||||
*/
|
||||
QString tableName() const;
|
||||
|
||||
/**
|
||||
* @brief factory
|
||||
* @return clone of self object pointer
|
||||
*/
|
||||
virtual DBObject* factory() const = 0;
|
||||
|
||||
/**
|
||||
* @brief prepareSelectQuery - override this metod for get item from database
|
||||
* this method need to prepare a query for selected data.
|
||||
* the default implementation generate default select: "select * from [table] where id=[id]".
|
||||
* If id is empty this implementation use data from altarnativeKey method.
|
||||
* @param q - query object
|
||||
* @return true if query is prepared seccussful
|
||||
*/
|
||||
virtual PrepareResult prepareSelectQuery(QSqlQuery& q) const;
|
||||
|
||||
/**
|
||||
* @brief fromSqlRecord- this method need to init this object from executed sqlRecord.
|
||||
* default implementation get general dbObject information ( id and table name )
|
||||
* @note this method weel be invoke for one object. but if isBundle return 'true' then a function fromSqlRecord moust be invoked foreach all elements of list.
|
||||
* @param q - sql record
|
||||
* @return true if method finished succesful
|
||||
*/
|
||||
virtual bool fromSqlRecord(const QSqlRecord& q);
|
||||
|
||||
/**
|
||||
* @brief prepareSaveQuery - override this method for save item into database
|
||||
* this method need to prepare a query for selected data.
|
||||
* @param q - query of requst
|
||||
* @return PrepareResult value
|
||||
*/
|
||||
virtual PrepareResult prepareSaveQuery(QSqlQuery& q) const = 0 ;
|
||||
|
||||
/**
|
||||
* @brief prepareRemoveQuery - override this method for remove this item from database.
|
||||
* this method need to prepare a query for remove this object.
|
||||
* the default implementatin remove item from id or primaryKey.
|
||||
* If id is empty this implementation use data from altarnativeKey method.
|
||||
* @param q - query of requst
|
||||
* @return PrepareResult value
|
||||
*/
|
||||
virtual PrepareResult prepareRemoveQuery(QSqlQuery& q) const;
|
||||
|
||||
/**
|
||||
* @brief isCached
|
||||
* @return return true if item in cache. default implementation retun true only
|
||||
*/
|
||||
virtual bool isCached() const;
|
||||
|
||||
/**
|
||||
* @brief isBundle
|
||||
* If this function return true then SqlDBWriter create only one object after invoked selectquery.
|
||||
* And if the selectquery function return a list of more 1 elements then a method fromSqlRecord moust be invoked foreach all elements of list.
|
||||
* @return true if the object is a selection from a set of database object.
|
||||
*/
|
||||
virtual bool isBundle() const;
|
||||
|
||||
/**
|
||||
* @brief dbAddress - unique address of item in database {id:table}
|
||||
* default implementation
|
||||
* @return unique key of this object
|
||||
*/
|
||||
virtual uint dbKey() const;
|
||||
|
||||
/**
|
||||
* @brief altarnativeKey - this method need to return a altarnative key:value pair for a select object when a object do not have a database id.
|
||||
* @default default implementation return empty pair.
|
||||
* @return pair of altarnative keys. Key : Value.
|
||||
*/
|
||||
virtual QPair<QString, QString> altarnativeKey() const;
|
||||
|
||||
/**
|
||||
* @brief dbAddress
|
||||
* @return
|
||||
*/
|
||||
DbAddress dbAddress() const;
|
||||
|
||||
/**
|
||||
* @brief clone - this nethod create a new object. The new Object is cone of current object.
|
||||
* @note If you want to get raw pointer to cone object use a "cloneRaw" method.
|
||||
* @return return shared pointer to clone of current object
|
||||
*/
|
||||
QSharedPointer<DBObject> clone() const;
|
||||
|
||||
/**
|
||||
* @brief cloneRaw - this method return a raw pointer to clone of this object.
|
||||
* @warning - clone object don not removed automatically and may result in a memory leak.
|
||||
* @note for get a shared pointer of clone object use the "clone" method.
|
||||
* @return retuen raw pointer to cloe of this object.
|
||||
*/
|
||||
DBObject* cloneRaw() const;
|
||||
|
||||
/**
|
||||
* @brief toString - return a string implementation fo this object
|
||||
* @return string of object
|
||||
*/
|
||||
QString toString() const override;
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
//// StreamBase interface
|
||||
QDataStream &fromStream(QDataStream &stream) override;
|
||||
QDataStream &toStream(QDataStream &stream) const override;
|
||||
|
||||
/**
|
||||
* @brief generateId - override this method for all db Objects.
|
||||
* if create id is impasoble ther retrun not valid id.
|
||||
* @return retuern Id of database object
|
||||
*/
|
||||
virtual BaseId generateId() const = 0;
|
||||
|
||||
/**
|
||||
* @brief init - init this object, prepare work with database.
|
||||
* @default - this implementation is create id for object of database.
|
||||
* If method generateId return not valid id this method return false.
|
||||
* @return true if object initialized fuccessful else return false.
|
||||
*/
|
||||
bool init() override;
|
||||
|
||||
private:
|
||||
QString getWhereBlock() const;
|
||||
|
||||
DbAddress _dbId;
|
||||
};
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(const NP::DBObject*)
|
||||
Q_DECLARE_METATYPE(NP::DBObject*)
|
||||
Q_DECLARE_METATYPE(QList<NP::DBObject *>*);
|
||||
Q_DECLARE_METATYPE(QList<const NP::DBObject *>*);
|
||||
|
||||
#endif // DBOBJECT_H
|
179
Heart/DataBaseSpace/packages/memberpermisionobject.cpp
Normal file
179
Heart/DataBaseSpace/packages/memberpermisionobject.cpp
Normal file
@ -0,0 +1,179 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "memberpermisionobject.h"
|
||||
|
||||
#include <QDataStream>
|
||||
#include <QSqlQuery>
|
||||
#include <dbcachekey.h>
|
||||
|
||||
namespace NP {
|
||||
|
||||
MemberPermisionObject::MemberPermisionObject():
|
||||
DBObject("MemberPermisions") {
|
||||
|
||||
}
|
||||
|
||||
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->_permisions = otherObject->_permisions;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
PrepareResult MemberPermisionObject::prepareSaveQuery(QSqlQuery &q) const {
|
||||
|
||||
if (!isValid()) {
|
||||
return PrepareResult::Fail;
|
||||
}
|
||||
|
||||
QString queryString = "INSERT INTO %0(%1) VALUES (%3) "
|
||||
"ON CONFLICT(MemberPermisionsIndex) DO UPDATE SET %2";
|
||||
|
||||
queryString = queryString.arg(tableName());
|
||||
|
||||
queryString = queryString.arg(
|
||||
"memberId, objectTable", "objectId", "lvl");
|
||||
|
||||
queryString = queryString.arg("memberId='" + _key.id().toBase64() + "', " +
|
||||
"objectTable='" + _key.address().table()+ "', " +
|
||||
"objectId='" + _key.address().id().toBase64() + "', " +
|
||||
"lvl='" + QString::number(static_cast<int>(_permisions)) + "'");
|
||||
QString values;
|
||||
|
||||
values += "'" + _key.id().toBase64() + "', ";
|
||||
values += "'" + _key.address().table() + "', ";
|
||||
values += "'" + _key.address().id().toBase64() + "', ";
|
||||
values += QString::number(static_cast<int>(_permisions));
|
||||
|
||||
|
||||
|
||||
queryString = queryString.arg(values);
|
||||
|
||||
if (q.prepare(queryString))
|
||||
return PrepareResult::Success;
|
||||
return PrepareResult::Fail;
|
||||
}
|
||||
|
||||
PrepareResult MemberPermisionObject::prepareRemoveQuery(QSqlQuery &q) const {
|
||||
if (!isValid()) {
|
||||
return PrepareResult::Fail;
|
||||
}
|
||||
|
||||
QString queryString = "DELETE FROM %0 where memberId='%1' and objectTable='%2' and objectId='%3'";
|
||||
queryString = queryString.arg(tableName(),
|
||||
_key.id().toBase64(),
|
||||
_key.address().table(),
|
||||
_key.address().id().toBase64());
|
||||
|
||||
if (q.prepare(queryString))
|
||||
return PrepareResult::Success;
|
||||
return PrepareResult::Fail;
|
||||
}
|
||||
|
||||
PrepareResult MemberPermisionObject::prepareSelectQuery(QSqlQuery &q) const {
|
||||
if (_key.isValid()) {
|
||||
return PrepareResult::Fail;
|
||||
}
|
||||
|
||||
QString queryString = "SELECT * FROM %0 WHERE";
|
||||
bool fOptionAdded = false;
|
||||
|
||||
if (_key.id().isValid()) {
|
||||
queryString += "memberId='" + _key.id().toBase64() + "'";
|
||||
fOptionAdded = true;
|
||||
}
|
||||
|
||||
if (_key.address().table().size()) {
|
||||
if (fOptionAdded)
|
||||
queryString += " and ";
|
||||
queryString += "objectTable='" + _key.address().table() + "'";
|
||||
fOptionAdded = true;
|
||||
}
|
||||
|
||||
if (_key.address().id().isValid()) {
|
||||
if (fOptionAdded)
|
||||
queryString += " and ";
|
||||
queryString += "objectId='" + _key.address().id().toBase64() + "'";
|
||||
fOptionAdded = true;
|
||||
}
|
||||
|
||||
queryString = queryString.arg(tableName());
|
||||
|
||||
if (q.prepare(queryString))
|
||||
return PrepareResult::Success;
|
||||
return PrepareResult::Fail;
|
||||
}
|
||||
|
||||
DBObject *MemberPermisionObject::factory() const {
|
||||
return create<MemberPermisionObject>();
|
||||
}
|
||||
|
||||
uint MemberPermisionObject::dbKey() const {
|
||||
return HASH_KEY(_key);
|
||||
}
|
||||
|
||||
QDataStream &MemberPermisionObject::fromStream(QDataStream &stream) {
|
||||
|
||||
stream >> _key;
|
||||
stream >> _permisions;
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
QDataStream &MemberPermisionObject::toStream(QDataStream &stream) const {
|
||||
stream << _key;
|
||||
stream << _permisions;
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
BaseId MemberPermisionObject::generateId() const {
|
||||
if (!_key.isValid())
|
||||
return {};
|
||||
|
||||
return _key.hash();
|
||||
}
|
||||
|
||||
PermisionData MemberPermisionObject::key() const {
|
||||
return _key;
|
||||
}
|
||||
|
||||
void MemberPermisionObject::setKey(const PermisionData &key) {
|
||||
_key = key;
|
||||
}
|
||||
|
||||
Permission MemberPermisionObject::permisions() const {
|
||||
return _permisions;
|
||||
}
|
||||
|
||||
void MemberPermisionObject::setPermisions(const Permission &permisions) {
|
||||
_permisions = permisions;
|
||||
}
|
||||
}
|
58
Heart/DataBaseSpace/packages/memberpermisionobject.h
Normal file
58
Heart/DataBaseSpace/packages/memberpermisionobject.h
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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 NODESPERMISIONOBJECT_H
|
||||
#define NODESPERMISIONOBJECT_H
|
||||
|
||||
#include "dbcachekey.h"
|
||||
#include "dbobject.h"
|
||||
#include "permisiondata.h"
|
||||
#include "permission.h"
|
||||
|
||||
namespace NP {
|
||||
|
||||
/**
|
||||
* @brief The NodesPermisionObject class - database object of permisions of node
|
||||
*/
|
||||
class NETWORKPROTOCOLSHARED_EXPORT MemberPermisionObject: public DBObject
|
||||
{
|
||||
public:
|
||||
MemberPermisionObject();
|
||||
MemberPermisionObject(const Package& pkg);
|
||||
MemberPermisionObject(const PermisionData& id);
|
||||
|
||||
// AbstractData interface
|
||||
bool isValid() const override;
|
||||
bool copyFrom(const AbstractData *other) override;
|
||||
|
||||
// DBObject interface
|
||||
PrepareResult prepareSaveQuery(QSqlQuery &q) const override;
|
||||
PrepareResult prepareRemoveQuery(QSqlQuery &q) const override;
|
||||
PrepareResult prepareSelectQuery(QSqlQuery &q) const override;
|
||||
DBObject *factory() const override;
|
||||
uint dbKey() const override;
|
||||
|
||||
Permission permisions() const;
|
||||
void setPermisions(const Permission &permisions);
|
||||
|
||||
PermisionData key() const;
|
||||
void setKey(const PermisionData &key);
|
||||
|
||||
protected:
|
||||
// StreamBase interface
|
||||
QDataStream &fromStream(QDataStream &stream) override;
|
||||
QDataStream &toStream(QDataStream &stream) const override;
|
||||
BaseId generateId() const override;
|
||||
|
||||
private:
|
||||
Permission _permisions;
|
||||
PermisionData _key;
|
||||
|
||||
|
||||
};
|
||||
}
|
||||
#endif // NODESPERMISIONOBJECT_H
|
143
Heart/DataBaseSpace/packages/networkmember.cpp
Normal file
143
Heart/DataBaseSpace/packages/networkmember.cpp
Normal file
@ -0,0 +1,143 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
#include "networkmember.h"
|
||||
#include <quasarapp.h>
|
||||
#include <QSqlQuery>
|
||||
#include <QSqlError>
|
||||
#include <QDataStream>
|
||||
#include <QCryptographicHash>
|
||||
|
||||
|
||||
namespace NP {
|
||||
|
||||
NetworkMember::NetworkMember():DBObject("NetworkMembers") {
|
||||
|
||||
}
|
||||
|
||||
NetworkMember::NetworkMember(const Package &pkg):
|
||||
NetworkMember() {
|
||||
fromBytes(pkg.data);
|
||||
}
|
||||
|
||||
NetworkMember::NetworkMember(const BaseId &id):
|
||||
NetworkMember() {
|
||||
setId(id);
|
||||
}
|
||||
|
||||
DBObject *NetworkMember::factory() const {
|
||||
return create<NetworkMember>();
|
||||
}
|
||||
|
||||
PrepareResult NetworkMember::prepareSaveQuery(QSqlQuery &q) const {
|
||||
QString queryString = "INSERT INTO %0(%1) VALUES (%3) "
|
||||
"ON CONFLICT(id) DO UPDATE SET %2";
|
||||
queryString = queryString.arg(tableName());
|
||||
queryString = queryString.arg("id, authenticationData, trust");
|
||||
queryString = queryString.arg("authenticationData=:AuthenticationData, "
|
||||
"trust=" + QString::number(_trust));
|
||||
|
||||
QString values;
|
||||
|
||||
values += "'" + getId().toBase64() + "', ";
|
||||
values += ":AuthenticationData, ";
|
||||
values += QString::number(_trust);
|
||||
|
||||
queryString = queryString.arg(values);
|
||||
|
||||
if (q.prepare(queryString)) {
|
||||
q.bindValue(":AuthenticationData", authenticationData());
|
||||
return PrepareResult::Success;
|
||||
}
|
||||
|
||||
|
||||
QuasarAppUtils::Params::log("Query:" + queryString,
|
||||
QuasarAppUtils::Error);
|
||||
|
||||
return PrepareResult::Fail;
|
||||
}
|
||||
|
||||
bool NetworkMember::fromSqlRecord(const QSqlRecord &q) {
|
||||
if (!DBObject::fromSqlRecord(q)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
setAuthenticationData(q.value("authenticationData").toByteArray());
|
||||
setTrust(q.value("trust").toInt());
|
||||
|
||||
return isValid();
|
||||
}
|
||||
|
||||
QByteArray NetworkMember::authenticationData() const {
|
||||
return _authenticationData;
|
||||
}
|
||||
|
||||
void NetworkMember::setAuthenticationData(const QByteArray &publickKey) {
|
||||
_authenticationData = publickKey;
|
||||
}
|
||||
|
||||
QDataStream &NetworkMember::fromStream(QDataStream &stream) {
|
||||
DBObject::fromStream(stream);
|
||||
|
||||
stream >> _authenticationData;
|
||||
stream >> _trust;
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
QDataStream &NetworkMember::toStream(QDataStream &stream) const {
|
||||
DBObject::toStream(stream);
|
||||
|
||||
stream << _authenticationData;
|
||||
stream << _trust;
|
||||
return stream;
|
||||
}
|
||||
|
||||
BaseId NetworkMember::generateId() const {
|
||||
if (authenticationData().isEmpty()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return QCryptographicHash::hash(authenticationData(), QCryptographicHash::Sha256);
|
||||
}
|
||||
|
||||
int NetworkMember::trust() const {
|
||||
return _trust;
|
||||
}
|
||||
|
||||
void NetworkMember::changeTrust(int diff) {
|
||||
_trust += diff;
|
||||
}
|
||||
|
||||
void NetworkMember::setTrust(int trust) {
|
||||
_trust = trust;
|
||||
}
|
||||
|
||||
bool NetworkMember::isValid() const {
|
||||
return DBObject::isValid() && _authenticationData.size();
|
||||
}
|
||||
|
||||
bool NetworkMember::copyFrom(const AbstractData * other) {
|
||||
if (!DBObject::copyFrom(other))
|
||||
return false;
|
||||
|
||||
auto otherObject = dynamic_cast<const NetworkMember*>(other);
|
||||
if (!otherObject)
|
||||
return false;
|
||||
|
||||
this->_authenticationData = otherObject->_authenticationData;
|
||||
this->_trust = otherObject->_trust;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QPair<QString, QString> NetworkMember::altarnativeKey() const {
|
||||
return {"authenticationData", _authenticationData.toBase64(QByteArray::Base64UrlEncoding)};
|
||||
}
|
||||
|
||||
}
|
58
Heart/DataBaseSpace/packages/networkmember.h
Normal file
58
Heart/DataBaseSpace/packages/networkmember.h
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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 NETWORKMEMBER_H
|
||||
#define NETWORKMEMBER_H
|
||||
|
||||
#include "dbobject.h"
|
||||
|
||||
|
||||
namespace NP {
|
||||
|
||||
/**
|
||||
* @brief The NodeObject class - database structure of node
|
||||
*/
|
||||
class NETWORKPROTOCOLSHARED_EXPORT NetworkMember: public DBObject
|
||||
{
|
||||
public:
|
||||
NetworkMember();
|
||||
NetworkMember(const Package& pkg);
|
||||
NetworkMember(const BaseId& id);
|
||||
|
||||
// DBObject interface
|
||||
DBObject *factory() const override;
|
||||
PrepareResult prepareSaveQuery(QSqlQuery &q) const override;
|
||||
bool fromSqlRecord(const QSqlRecord &q) override;
|
||||
|
||||
QByteArray authenticationData() const;
|
||||
void setAuthenticationData(const QByteArray &publickKey);
|
||||
|
||||
// AbstractData interface
|
||||
bool isValid() const override;
|
||||
bool copyFrom(const AbstractData *) override;
|
||||
|
||||
QPair<QString, QString> altarnativeKey() const override;
|
||||
|
||||
int trust() const;
|
||||
void changeTrust(int diff);
|
||||
void setTrust(int trust);
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
// StreamBase interface
|
||||
QDataStream &fromStream(QDataStream &stream) override;
|
||||
QDataStream &toStream(QDataStream &stream) const override;
|
||||
BaseId generateId() const override;
|
||||
|
||||
private:
|
||||
QByteArray _authenticationData;
|
||||
int _trust;
|
||||
};
|
||||
}
|
||||
#endif // NETWORKMEMBER_H
|
53
Heart/DataBaseSpace/packages/websocket.cpp
Normal file
53
Heart/DataBaseSpace/packages/websocket.cpp
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "websocket.h"
|
||||
|
||||
#include <QDataStream>
|
||||
#include <QSharedPointer>
|
||||
namespace NP {
|
||||
|
||||
WebSocket::WebSocket(): AbstractData(){
|
||||
|
||||
}
|
||||
|
||||
WebSocket::WebSocket(const Package &package):
|
||||
WebSocket() {
|
||||
fromBytes(package.data);
|
||||
|
||||
}
|
||||
|
||||
QDataStream &WebSocket::fromStream(QDataStream &stream) {
|
||||
AbstractData::fromStream(stream);
|
||||
stream >> requestCmd;
|
||||
stream >> _address;
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
QDataStream &WebSocket::toStream(QDataStream &stream) const {
|
||||
AbstractData::toStream(stream);
|
||||
stream << requestCmd;
|
||||
stream << _address;
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
DbAddress WebSocket::address() const {
|
||||
return _address;
|
||||
}
|
||||
|
||||
void WebSocket::setAddress(const DbAddress &address) {
|
||||
_address = address;
|
||||
}
|
||||
|
||||
bool WebSocket::isValid() const {
|
||||
return requestCmd > static_cast<int>(WebSocketRequest::Invalied)
|
||||
&& AbstractData::isValid();
|
||||
}
|
||||
|
||||
}
|
58
Heart/DataBaseSpace/packages/websocket.h
Normal file
58
Heart/DataBaseSpace/packages/websocket.h
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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 WEBSOCKET_H
|
||||
#define WEBSOCKET_H
|
||||
|
||||
#include "dbobject.h"
|
||||
#include "request.h"
|
||||
|
||||
|
||||
namespace NP {
|
||||
|
||||
/**
|
||||
* @brief The WebSocketRequest enum
|
||||
*/
|
||||
enum class WebSocketRequest {
|
||||
/// Invalied data
|
||||
Invalied = 0,
|
||||
/// subscribe to data
|
||||
Subscribe = 1,
|
||||
|
||||
/// unsubscribe
|
||||
Unsubscribe = 2,
|
||||
|
||||
/// get list of curennt subscribes
|
||||
SubscribeList = 3
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The WebSocket class - this class contains methods for work with stream data
|
||||
*/
|
||||
class NETWORKPROTOCOLSHARED_EXPORT WebSocket:
|
||||
public AbstractData, public Request
|
||||
{
|
||||
public:
|
||||
WebSocket();
|
||||
WebSocket(const Package& package);
|
||||
|
||||
bool isValid() const override;
|
||||
|
||||
// DBObject interface
|
||||
DbAddress address() const;
|
||||
void setAddress(const DbAddress &address);
|
||||
|
||||
protected:
|
||||
QDataStream &fromStream(QDataStream &stream) override;
|
||||
QDataStream &toStream(QDataStream &stream) const override;
|
||||
|
||||
private:
|
||||
DbAddress _address;
|
||||
};
|
||||
|
||||
}
|
||||
#endif // WEBSOCKET_H
|
@ -1,3 +1,10 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "websocketsubscriptions.h"
|
||||
|
||||
#include <QDataStream>
|
||||
@ -5,7 +12,7 @@
|
||||
namespace NP {
|
||||
WebSocketSubscriptions::WebSocketSubscriptions()
|
||||
{
|
||||
INIT_COMMAND
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -18,21 +25,21 @@ WebSocketSubscriptions::WebSocketSubscriptions(const NP::Package &package):
|
||||
|
||||
QDataStream &WebSocketSubscriptions::fromStream(QDataStream &stream) {
|
||||
AbstractData::fromStream(stream);
|
||||
|
||||
return stream >> _addresses;
|
||||
}
|
||||
|
||||
QDataStream &WebSocketSubscriptions::toStream(QDataStream &stream) const {
|
||||
AbstractData::toStream(stream);
|
||||
|
||||
return stream << _addresses;
|
||||
}
|
||||
|
||||
QSet<DbAddress> WebSocketSubscriptions::addresses() const
|
||||
{
|
||||
QSet<DbAddress> WebSocketSubscriptions::addresses() const {
|
||||
return _addresses;
|
||||
}
|
||||
|
||||
void WebSocketSubscriptions::setAddresses(const QSet<DbAddress> &addresses)
|
||||
{
|
||||
void WebSocketSubscriptions::setAddresses(const QSet<DbAddress> &addresses) {
|
||||
_addresses = addresses;
|
||||
}
|
||||
|
@ -1,3 +1,10 @@
|
||||
/*
|
||||
* 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 WEBSOCKETSUBSCRIPTIONS_H
|
||||
#define WEBSOCKETSUBSCRIPTIONS_H
|
||||
|
||||
@ -9,6 +16,9 @@
|
||||
|
||||
namespace NP {
|
||||
|
||||
/**
|
||||
* @brief The WebSocketSubscriptions class
|
||||
*/
|
||||
class NETWORKPROTOCOLSHARED_EXPORT WebSocketSubscriptions: public AbstractData
|
||||
{
|
||||
public:
|
72
Heart/DataBaseSpace/permisiondata.cpp
Normal file
72
Heart/DataBaseSpace/permisiondata.cpp
Normal file
@ -0,0 +1,72 @@
|
||||
#include "dbaddress.h"
|
||||
#include "permisiondata.h"
|
||||
#include <quasarapp.h>
|
||||
#include <QDataStream>
|
||||
|
||||
namespace NP {
|
||||
|
||||
bool operator ==(const PermisionData &left, const PermisionData &right) {
|
||||
return left._id == right._id && left._address == right._address;
|
||||
}
|
||||
|
||||
PermisionData::PermisionData(const BaseId &subject, const DbAddress &objcet) {
|
||||
setId(subject);
|
||||
setAddress(objcet);
|
||||
}
|
||||
|
||||
unsigned int PermisionData::hash() const {
|
||||
QByteArray data;
|
||||
QDataStream stream(&data, QIODevice::WriteOnly);
|
||||
|
||||
stream << _id;
|
||||
stream << _address;
|
||||
return qHash(data);
|
||||
}
|
||||
|
||||
const BaseId &PermisionData::id() const {
|
||||
return _id;
|
||||
}
|
||||
|
||||
const QString &PermisionData::table() const {
|
||||
return _address.table();
|
||||
}
|
||||
|
||||
bool PermisionData::isValid() const {
|
||||
return address().isValid() && _id.isValid();
|
||||
}
|
||||
|
||||
bool PermisionData::equal(const AbstractKey *other) const {
|
||||
auto otherObject = dynamic_cast<const PermisionData*>(other);
|
||||
if (!otherObject)
|
||||
return false;
|
||||
|
||||
return _address == otherObject->_address && _id == otherObject->_id;
|
||||
}
|
||||
|
||||
DbAddress PermisionData::address() const {
|
||||
return _address;
|
||||
}
|
||||
|
||||
void PermisionData::setAddress(const DbAddress &address) {
|
||||
_address = address;
|
||||
}
|
||||
|
||||
QDataStream &PermisionData::fromStream(QDataStream &stream) {
|
||||
stream >> _id;
|
||||
stream >> _address;
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
QDataStream &PermisionData::toStream(QDataStream &stream) const {
|
||||
stream << _id;
|
||||
stream << _address;
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
void PermisionData::setId(const BaseId &Id) {
|
||||
_id = Id;
|
||||
}
|
||||
|
||||
}
|
57
Heart/DataBaseSpace/permisiondata.h
Normal file
57
Heart/DataBaseSpace/permisiondata.h
Normal file
@ -0,0 +1,57 @@
|
||||
#ifndef PERMISIONDATA_H
|
||||
#define PERMISIONDATA_H
|
||||
|
||||
#include <QString>
|
||||
#include <abstractkey.h>
|
||||
#include "dbaddress.h"
|
||||
|
||||
namespace NP {
|
||||
|
||||
/**
|
||||
* @brief The PermisionData class- this class provide unique key for permison of subject (id) to object (address).
|
||||
*/
|
||||
class NETWORKPROTOCOLSHARED_EXPORT PermisionData: public AbstractKey, public StreamBase {
|
||||
|
||||
public:
|
||||
|
||||
PermisionData() = default;
|
||||
PermisionData(const BaseId& subject, const DbAddress& objcet);
|
||||
|
||||
friend bool operator == (const PermisionData& left, const PermisionData& right);
|
||||
|
||||
/**
|
||||
* @brief qHash - calc unique key of PermisionData
|
||||
* @param userPermision
|
||||
* @return unique key
|
||||
*/
|
||||
unsigned int hash() const override;
|
||||
|
||||
|
||||
const BaseId & id() const override;
|
||||
const QString &table() const override;
|
||||
bool isValid() const override;
|
||||
bool equal(const AbstractKey *other) const override;
|
||||
|
||||
void setId(const BaseId &Id);
|
||||
|
||||
DbAddress address() const;
|
||||
void setAddress(const DbAddress &address);
|
||||
|
||||
// StreamBase interface
|
||||
protected:
|
||||
QDataStream &fromStream(QDataStream &stream) override;
|
||||
QDataStream &toStream(QDataStream &stream) const override;
|
||||
|
||||
private:
|
||||
|
||||
/// id of user of node
|
||||
BaseId _id;
|
||||
|
||||
/// table of target object (second part of key)
|
||||
DbAddress _address;
|
||||
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
#endif // PERMISIONDATA_H
|
17
Heart/DataBaseSpace/permission.h
Normal file
17
Heart/DataBaseSpace/permission.h
Normal file
@ -0,0 +1,17 @@
|
||||
#ifndef PERMISIONS_H
|
||||
#define PERMISIONS_H
|
||||
namespace NP {
|
||||
|
||||
/**
|
||||
* @brief The Permission enum
|
||||
* permision to data in database
|
||||
*/
|
||||
enum class Permission: unsigned char {
|
||||
NoPermission = 0x00,
|
||||
Read = 0x01,
|
||||
Update = 0x02,
|
||||
Write = 0x03,
|
||||
};
|
||||
|
||||
}
|
||||
#endif // PERMISIONS_H
|
255
Heart/DataBaseSpace/sqldbcache.cpp
Normal file
255
Heart/DataBaseSpace/sqldbcache.cpp
Normal file
@ -0,0 +1,255 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#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 NP {
|
||||
|
||||
void SqlDBCache::globalUpdateDataBasePrivate(qint64 currentTime) {
|
||||
|
||||
QMutexLocker lock(&_saveLaterMutex);
|
||||
|
||||
for (uint it : _needToSaveCache) {
|
||||
|
||||
auto async = dynamic_cast<AsyncSqlDbWriter*>(_writer);
|
||||
|
||||
if (_writer && _writer->isValid()) {
|
||||
|
||||
auto obj = getFromCache(it);
|
||||
|
||||
if (!obj || !obj->isValid()) {
|
||||
deleteFromCache(obj);
|
||||
|
||||
QuasarAppUtils::Params::log("writeUpdateItemIntoDB failed when"
|
||||
" db object is not valid! key=" + DESCRIPTION_KEY(it) +
|
||||
" " + obj->toString(),
|
||||
QuasarAppUtils::VerboseLvl::Error);
|
||||
continue;
|
||||
}
|
||||
|
||||
bool saveResult = false;
|
||||
if (async)
|
||||
saveResult = async->saveObjectWithWait(obj);
|
||||
else
|
||||
saveResult = _writer->saveObject(obj);
|
||||
|
||||
|
||||
|
||||
if (!saveResult ) {
|
||||
QuasarAppUtils::Params::log("writeUpdateItemIntoDB failed when"
|
||||
" work globalUpdateDataRelease!!! key=" + DESCRIPTION_KEY(it) +
|
||||
" " + obj->toString(),
|
||||
QuasarAppUtils::VerboseLvl::Error);
|
||||
}
|
||||
} else {
|
||||
|
||||
QuasarAppUtils::Params::log("writeUpdateItemIntoDB failed when"
|
||||
" db writer is npt inited! ",
|
||||
QuasarAppUtils::VerboseLvl::Error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
_needToSaveCache.clear();
|
||||
|
||||
lastUpdateTime = currentTime;
|
||||
}
|
||||
|
||||
void SqlDBCache::globalUpdateDataBase(SqlDBCasheWriteMode mode) {
|
||||
qint64 currentTime = QDateTime::currentMSecsSinceEpoch();
|
||||
|
||||
if (currentTime - lastUpdateTime > updateInterval ||
|
||||
static_cast<bool>(mode & SqlDBCasheWriteMode::Force)) {
|
||||
|
||||
if (static_cast<bool>(mode & SqlDBCasheWriteMode::On_New_Thread)) {
|
||||
|
||||
QtConcurrent::run([currentTime, this](){
|
||||
globalUpdateDataBasePrivate(currentTime);
|
||||
});
|
||||
|
||||
} else {
|
||||
globalUpdateDataBasePrivate(currentTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SqlDBCache::SqlDBCache(qint64 updateInterval) {
|
||||
lastUpdateTime = QDateTime::currentMSecsSinceEpoch();
|
||||
this->updateInterval = updateInterval;
|
||||
}
|
||||
|
||||
SqlDBCache::~SqlDBCache() {
|
||||
globalUpdateDataBase(SqlDBCasheWriteMode::Force);
|
||||
}
|
||||
|
||||
SqlDBWriter *SqlDBCache::writer() const {
|
||||
return _writer;
|
||||
}
|
||||
|
||||
void SqlDBCache::setWriter(SqlDBWriter *writer) {
|
||||
_writer = writer;
|
||||
}
|
||||
|
||||
bool SqlDBCache::getAllObjects(const DBObject &templateObject, QList<const DBObject *> &result) {
|
||||
|
||||
DBObject* obj = getFromCache(templateObject.dbKey());
|
||||
if(obj) {
|
||||
result.push_back(obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_writer && _writer->isValid()) {
|
||||
if (!_writer->getAllObjects(templateObject, result)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto object: result) {
|
||||
if (object->isCached() && !saveToCache(object)) {
|
||||
QuasarAppUtils::Params::log("Selected object from database can not be saved into database cache. " +
|
||||
object->toString(),
|
||||
QuasarAppUtils::Warning);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SqlDBCache::saveObject(const DBObject *saveObject) {
|
||||
|
||||
if (!saveObject || !saveObject->isValid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
saveToCache(saveObject);
|
||||
|
||||
if (getMode() == SqlDBCasheWriteMode::Force) {
|
||||
if (_writer && _writer->isValid()) {
|
||||
if (!_writer->saveObject(saveObject)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
_needToSaveCache.insert(saveObject->dbKey());
|
||||
globalUpdateDataBase(_mode);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
bool SqlDBCache::deleteObject(const DBObject *delObj) {
|
||||
|
||||
if (!delObj)
|
||||
return false;
|
||||
|
||||
deleteFromCache(delObj);
|
||||
|
||||
if (_writer && _writer->isValid()) {
|
||||
return _writer->deleteObject(delObj);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
bool SqlDBCache::init(const QString &initDbParams) {
|
||||
|
||||
if (!_writer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return _writer->initDb(initDbParams);
|
||||
}
|
||||
|
||||
bool SqlDBCache::init(const QVariantMap ¶ms) {
|
||||
|
||||
if (!_writer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return _writer->initDb(params);
|
||||
}
|
||||
|
||||
void SqlDBCache::deleteFromCache(const DBObject *delObj) {
|
||||
if (!delObj)
|
||||
return;
|
||||
|
||||
_cacheMutex.lock();
|
||||
_cache.remove(delObj->dbKey());
|
||||
_cacheMutex.unlock();
|
||||
}
|
||||
|
||||
bool SqlDBCache::saveToCache(const DBObject *obj) {
|
||||
if (!obj)
|
||||
return false;
|
||||
|
||||
QMutexLocker lock(&_cacheMutex);
|
||||
|
||||
auto existsObject = _cache.value(obj->dbKey(), nullptr);
|
||||
if (!existsObject) {
|
||||
|
||||
_cache[obj->dbKey()] = obj->cloneRaw();
|
||||
|
||||
} else if (existsObject->cmd() != obj->cmd()) {
|
||||
|
||||
delete existsObject;
|
||||
_cache[obj->dbKey()] = obj->cloneRaw();
|
||||
|
||||
} else {
|
||||
|
||||
if (!existsObject->copyFrom(obj)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
emit sigItemChanged(obj);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
DBObject* SqlDBCache::getFromCache(uint objKey) {
|
||||
|
||||
QMutexLocker locker(&_cacheMutex);
|
||||
|
||||
return _cache.value(objKey, nullptr);
|
||||
}
|
||||
|
||||
SqlDBCasheWriteMode SqlDBCache::getMode() const {
|
||||
return _mode;
|
||||
}
|
||||
|
||||
void SqlDBCache::setMode(const SqlDBCasheWriteMode &mode) {
|
||||
_mode = mode;
|
||||
}
|
||||
|
||||
qint64 SqlDBCache::getUpdateInterval() const {
|
||||
return updateInterval;
|
||||
}
|
||||
|
||||
void SqlDBCache::setUpdateInterval(const qint64 &value) {
|
||||
updateInterval = value;
|
||||
}
|
||||
|
||||
}
|
@ -1,19 +1,29 @@
|
||||
/*
|
||||
* 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 SQLDBCASHE_H
|
||||
#define SQLDBCASHE_H
|
||||
|
||||
#include "dbcachekey.h"
|
||||
#include "iobjectprovider.h"
|
||||
|
||||
#include <QMap>
|
||||
#include <QHash>
|
||||
#include <QSet>
|
||||
#include <QVariantMap>
|
||||
#include <networkprotocol.h>
|
||||
#include <QMutex>
|
||||
#include "config.h"
|
||||
#include "basedefines.h"
|
||||
|
||||
namespace NP {
|
||||
|
||||
class SqlDBWriter;
|
||||
class DBObject;
|
||||
class DbAddress;
|
||||
|
||||
enum class SqlDBCasheWriteMode: int {
|
||||
Default = 0x0,
|
||||
@ -37,19 +47,18 @@ public:
|
||||
* @brief writer
|
||||
* @return weak pointer to writer
|
||||
*/
|
||||
WP<SqlDBWriter> writer() const;
|
||||
SqlDBWriter* writer() const;
|
||||
|
||||
/**
|
||||
* @brief setWriter
|
||||
* @param writer
|
||||
*/
|
||||
void setWriter(const WP<SqlDBWriter> &writer);
|
||||
void setWriter(SqlDBWriter* writer);
|
||||
|
||||
bool getObject(SP<DBObject> &obj) override;
|
||||
SP<DBObject> &getObjectFromCache(const QString& table, int id);
|
||||
bool getAllObjects(const DBObject &templateObject, QList<const DBObject *> &result) override;
|
||||
|
||||
bool saveObject(const WP<AbstractData> &saveObject) override;
|
||||
bool deleteObject(const WP<AbstractData>& delObj) override;
|
||||
bool saveObject(const DBObject* saveObject) override;
|
||||
bool deleteObject(const DBObject* delObj) override;
|
||||
|
||||
/**
|
||||
* @brief getUpdateInterval of SqlDBCasheWriteMode::Default mode
|
||||
@ -83,14 +92,20 @@ protected:
|
||||
* @param id in table of object
|
||||
* @return true if all good
|
||||
*/
|
||||
virtual void deleteFromCache(const QString &table, int id);
|
||||
virtual void deleteFromCache(const DBObject *delObj);
|
||||
|
||||
/**
|
||||
* @brief saveToCache
|
||||
* @param obj
|
||||
*/
|
||||
virtual void saveToCache(const WP<AbstractData> &obj);
|
||||
virtual bool saveToCache(const DBObject *obj);
|
||||
|
||||
/**
|
||||
* @brief getFromCache - get database objcet from cache.
|
||||
* @param objKey
|
||||
* @return object from cache. if object with objKey not exits return nullptr
|
||||
*/
|
||||
virtual DBObject* getFromCache(uint objKey);
|
||||
|
||||
/**
|
||||
* @brief getMode
|
||||
@ -104,24 +119,35 @@ protected:
|
||||
*/
|
||||
void setMode(const SqlDBCasheWriteMode &mode);
|
||||
|
||||
QMutex _saveLaterMutex;
|
||||
|
||||
/**
|
||||
* @brief globalUpdateDataBasePrivate
|
||||
* @param currentTime
|
||||
*/
|
||||
virtual void globalUpdateDataBasePrivate(qint64 currentTime);
|
||||
|
||||
/**
|
||||
* @brief globalUpdateDataBase
|
||||
* @param mode
|
||||
*/
|
||||
virtual void globalUpdateDataBase(SqlDBCasheWriteMode mode = SqlDBCasheWriteMode::Default);
|
||||
|
||||
SqlDBWriter* _writer = nullptr;
|
||||
private:
|
||||
qint64 lastUpdateTime = 0;
|
||||
qint64 updateInterval = DEFAULT_UPDATE_INTERVAL;
|
||||
QMutex _saveLaterMutex;
|
||||
QMutex _cacheMutex;
|
||||
|
||||
SqlDBCasheWriteMode _mode;
|
||||
|
||||
SP<SqlDBWriter> _writer = nullptr;
|
||||
QHash<uint, DBObject*> _cache;
|
||||
QSet<uint> _needToSaveCache;
|
||||
|
||||
QHash<QString, QHash <int, SP<DBObject>>> _cache;
|
||||
QHash<QString, QList<int>> _needToSaveCache;
|
||||
|
||||
virtual void globalUpdateDataBasePrivate(qint64 currentTime);
|
||||
virtual void globalUpdateDataBase(SqlDBCasheWriteMode mode = SqlDBCasheWriteMode::Default);
|
||||
|
||||
signals:
|
||||
void sigItemChanged(const WP<AbstractData> &obj);
|
||||
void sigItemChanged(const DBObject *obj);
|
||||
|
||||
};
|
||||
|
@ -1,5 +1,10 @@
|
||||
#include "dbobjectsfactory.h"
|
||||
#include "dbtablebase.h"
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "sqldbwriter.h"
|
||||
|
||||
#include <QRegularExpression>
|
||||
@ -8,12 +13,13 @@
|
||||
#include <QDebug>
|
||||
#include <QSqlError>
|
||||
#include <quasarapp.h>
|
||||
#include <networkprotocol.h>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QHash>
|
||||
#include <dbobject.h>
|
||||
#include <QSqlRecord>
|
||||
#include <QStandardPaths>
|
||||
#include <QCoreApplication>
|
||||
|
||||
namespace NP {
|
||||
|
||||
@ -115,7 +121,6 @@ QVariantMap SqlDBWriter::defaultInitPararm() const {
|
||||
QVariantMap params;
|
||||
params["DBDriver"] = "QSQLITE";
|
||||
params["DBFile"] = DEFAULT_DB_PATH;
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
@ -191,45 +196,139 @@ bool SqlDBWriter::isValid() const {
|
||||
return db.isValid() && db.isOpen() && initSuccessful;
|
||||
}
|
||||
|
||||
bool SqlDBWriter::getObject(SP<DBObject>& obj) {
|
||||
return selectQuery(obj);
|
||||
bool SqlDBWriter::getAllObjects(const DBObject &templateObject, QList<const DBObject *> &result) {
|
||||
return selectQuery(templateObject, result);
|
||||
}
|
||||
|
||||
bool SqlDBWriter::saveObject(const WP<AbstractData> &saveObject) {
|
||||
return saveQuery(saveObject);
|
||||
bool SqlDBWriter::saveObject(const DBObject* ptr) {
|
||||
return saveQuery(ptr);
|
||||
}
|
||||
|
||||
bool SqlDBWriter::deleteObject(const WP<AbstractData> &deleteObject) {
|
||||
return deleteQuery(deleteObject);
|
||||
bool SqlDBWriter::deleteObject(const DBObject* ptr) {
|
||||
return deleteQuery(ptr);
|
||||
}
|
||||
|
||||
QString SqlDBWriter::databaseLocation() const {
|
||||
return db.databaseName();
|
||||
}
|
||||
|
||||
SqlDBWriter::~SqlDBWriter() {
|
||||
db.close();
|
||||
}
|
||||
|
||||
bool SqlDBWriter::saveQuery(const WP<AbstractData>& ptr) const {
|
||||
bool SqlDBWriter::saveQuery(const DBObject* ptr) const {
|
||||
if (!ptr)
|
||||
return false;
|
||||
|
||||
QSqlQuery q(db);
|
||||
|
||||
auto obj = ptr.toStrongRef().dynamicCast<DBObject>();
|
||||
if (obj.isNull())
|
||||
auto prepare = [ptr](QSqlQuery&q) {
|
||||
return ptr->prepareSaveQuery(q);
|
||||
};
|
||||
|
||||
auto cb = [](){return true;};
|
||||
|
||||
return workWithQuery(q, prepare, cb);
|
||||
}
|
||||
|
||||
bool SqlDBWriter::selectQuery(const DBObject& requestObject, QList<const DBObject *> &result) {
|
||||
|
||||
QSqlQuery q(db);
|
||||
auto prepare = [&requestObject](QSqlQuery&q) {
|
||||
return requestObject.prepareSelectQuery(q);
|
||||
};
|
||||
|
||||
auto cb = [&q, &requestObject, &result]() -> bool {
|
||||
|
||||
if (requestObject.isBundle()) {
|
||||
auto newObject = requestObject.factory();
|
||||
|
||||
if (!newObject)
|
||||
return false;
|
||||
|
||||
while (q.next()) {
|
||||
if (!newObject->fromSqlRecord(q.record())) {
|
||||
QuasarAppUtils::Params::log("Init sql object error.",
|
||||
QuasarAppUtils::Error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
result.push_back(newObject);
|
||||
|
||||
} else {
|
||||
while (q.next()) {
|
||||
auto newObject = requestObject.factory();
|
||||
|
||||
if (!newObject)
|
||||
return false;
|
||||
|
||||
if (!newObject->fromSqlRecord(q.record())) {
|
||||
QuasarAppUtils::Params::log("Init sql object error.",
|
||||
QuasarAppUtils::Error);
|
||||
return false;
|
||||
}
|
||||
result.push_back(newObject);
|
||||
}
|
||||
}
|
||||
|
||||
return result.size();
|
||||
};
|
||||
|
||||
return workWithQuery(q, prepare, cb);
|
||||
}
|
||||
|
||||
bool SqlDBWriter::deleteQuery(const DBObject *deleteObject) const {
|
||||
if (!deleteObject)
|
||||
return false;
|
||||
|
||||
return obj->save(q);
|
||||
QSqlQuery q(db);
|
||||
|
||||
auto prepare = [deleteObject](QSqlQuery&q) {
|
||||
return deleteObject->prepareRemoveQuery(q);
|
||||
};
|
||||
|
||||
auto cb = []() -> bool {
|
||||
return true;
|
||||
};
|
||||
|
||||
return workWithQuery(q, prepare, cb);
|
||||
}
|
||||
|
||||
bool SqlDBWriter::selectQuery(const SP<DBObject>& obj) {
|
||||
if (obj.isNull())
|
||||
bool SqlDBWriter::workWithQuery(QSqlQuery &q,
|
||||
const std::function< PrepareResult (QSqlQuery &)> &prepareFunc,
|
||||
const std::function<bool ()> &cb) const {
|
||||
|
||||
switch (prepareFunc(q)) {
|
||||
case PrepareResult::Success: {
|
||||
|
||||
if (!q.exec()) {
|
||||
|
||||
QuasarAppUtils::Params::log("exec sql error: " + q.lastError().text(),
|
||||
QuasarAppUtils::Error);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return cb();
|
||||
}
|
||||
case PrepareResult::Disabled: {
|
||||
QuasarAppUtils::Params::log("call disabled operator! ",
|
||||
QuasarAppUtils::Warning);
|
||||
return true;
|
||||
}
|
||||
|
||||
case PrepareResult::Fail: {
|
||||
QuasarAppUtils::Params::log("prepare sql error: " + q.lastError().text(),
|
||||
QuasarAppUtils::Error);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
QSqlQuery query(db);
|
||||
return obj->select(query);
|
||||
}
|
||||
}
|
||||
|
||||
bool SqlDBWriter::deleteQuery(const WP<AbstractData> &deleteObject) const {
|
||||
QSqlQuery query(db);
|
||||
auto ref = deleteObject.toStrongRef().dynamicCast<DBObject>();
|
||||
return false;
|
||||
|
||||
return ref->remove(query);
|
||||
}
|
||||
|
||||
}
|
@ -1,3 +1,10 @@
|
||||
/*
|
||||
* 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 SQLDBWRITER_H
|
||||
#define SQLDBWRITER_H
|
||||
|
||||
@ -5,32 +12,74 @@
|
||||
#include <QSqlDatabase>
|
||||
#include <QDir>
|
||||
#include <QSqlQuery>
|
||||
#include "networkprotocol_global.h"
|
||||
#include "heart_global.h"
|
||||
#include "config.h"
|
||||
#include "dbtablebase.h"
|
||||
#include "iobjectprovider.h"
|
||||
#include <QVariant>
|
||||
#include <QCoreApplication>
|
||||
#include <dbobject.h>
|
||||
|
||||
class QSqlQuery;
|
||||
class QSqlDatabase;
|
||||
class QSqlQuery;
|
||||
class PlayerDBData;
|
||||
|
||||
namespace NP {
|
||||
|
||||
class DBObject;
|
||||
class AbstractData;
|
||||
/**
|
||||
* @brief The SqlDBWriter class
|
||||
*/
|
||||
class NETWORKPROTOCOLSHARED_EXPORT SqlDBWriter : public iObjectProvider
|
||||
{
|
||||
private:
|
||||
public:
|
||||
SqlDBWriter();
|
||||
|
||||
bool exec(QSqlQuery *sq, const QString &sqlFile);
|
||||
/**
|
||||
* @brief initDb
|
||||
* @param path
|
||||
* @return
|
||||
*/
|
||||
virtual bool initDb(const QString &initDbParams = DEFAULT_DB_PATH);
|
||||
|
||||
bool initSuccessful = false;
|
||||
QVariantMap _config;
|
||||
/**
|
||||
* @brief initDb
|
||||
* @param path
|
||||
* @return
|
||||
*/
|
||||
virtual bool initDb(const QVariantMap ¶ms);
|
||||
|
||||
/**
|
||||
* @brief isValid
|
||||
* @return
|
||||
*/
|
||||
virtual bool isValid() const;
|
||||
|
||||
/**
|
||||
* @brief getAllObjects - executable select method of objects and return list of all selected objects
|
||||
* @param obj - template object with select request.
|
||||
* @param result - return value, list of selected objects.
|
||||
* @return true if objects have in db else false.
|
||||
*/
|
||||
bool getAllObjects(const DBObject &templateObject, QList<const DBObject *> &result) override;
|
||||
|
||||
/**
|
||||
* @brief saveObject
|
||||
* @return
|
||||
*/
|
||||
bool saveObject(const NP::DBObject *ptr) override;
|
||||
|
||||
/**
|
||||
* @brief deleteObject
|
||||
* @return
|
||||
*/
|
||||
bool deleteObject(const NP::DBObject *ptr) override;
|
||||
|
||||
/**
|
||||
* @brief databaseLocation - return location of database.
|
||||
* if it is sqllite then return path to db file else return database name.
|
||||
* @return path or name of database.
|
||||
*/
|
||||
QString databaseLocation() const;
|
||||
|
||||
virtual ~SqlDBWriter() override;
|
||||
|
||||
protected:
|
||||
|
||||
@ -73,12 +122,13 @@ protected:
|
||||
virtual QVariantMap defaultInitPararm() const;
|
||||
|
||||
QSqlDatabase db;
|
||||
QHash<QString, DbTableBase> _dbStruct;
|
||||
|
||||
// 0 - table name
|
||||
// 1 - headers of update values
|
||||
// 2 - update values
|
||||
virtual bool saveQuery(const WP<AbstractData> &ptr) const;
|
||||
/**
|
||||
* @brief saveQuery - exec save query of object
|
||||
* @param ptr
|
||||
* @return true if function finished seccussful
|
||||
*/
|
||||
virtual bool saveQuery(const NP::DBObject *ptr) const;
|
||||
|
||||
/**
|
||||
* @brief selectQuery generate select query to database from parameters
|
||||
@ -88,56 +138,30 @@ protected:
|
||||
* @param val - compare value
|
||||
* @return true if all goodelse false
|
||||
*/
|
||||
virtual bool selectQuery(const SP<DBObject> &obj);
|
||||
virtual bool selectQuery(const DBObject &requestObject, QList<const DBObject *> &result);
|
||||
|
||||
virtual bool deleteQuery(const WP<AbstractData> &deleteObject) const;
|
||||
virtual bool deleteQuery(const NP::DBObject *deleteObject) const;
|
||||
|
||||
public:
|
||||
SqlDBWriter();
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* @brief initDb
|
||||
* @param path
|
||||
* @return
|
||||
* @brief workWithQuery - this base function for all prepareQuery functions.
|
||||
* steps work : call prepareFunc, call exec , call cb.
|
||||
* @param q - query object with a request
|
||||
* @param prepareFunc - function with pripare data for query
|
||||
* @param cb - call after success exec and prepare steps
|
||||
* @return true if all steps finished successful
|
||||
*/
|
||||
virtual bool initDb(const QString &initDbParams = DEFAULT_DB_PATH);
|
||||
bool workWithQuery(QSqlQuery &q,
|
||||
const std::function< PrepareResult (QSqlQuery &)> &prepareFunc,
|
||||
const std::function<bool()>& cb) const;
|
||||
|
||||
/**
|
||||
* @brief initDb
|
||||
* @param path
|
||||
* @return
|
||||
*/
|
||||
virtual bool initDb(const QVariantMap ¶ms);
|
||||
bool exec(QSqlQuery *sq, const QString &sqlFile);
|
||||
|
||||
/**
|
||||
* @brief isValid
|
||||
* @return
|
||||
*/
|
||||
virtual bool isValid() const;
|
||||
bool initSuccessful = false;
|
||||
QVariantMap _config;
|
||||
|
||||
/**
|
||||
* @brief getObject
|
||||
* @return
|
||||
*/
|
||||
bool getObject(SP<DBObject> &obj) override;
|
||||
|
||||
/**
|
||||
* @brief saveObject
|
||||
* @return
|
||||
*/
|
||||
bool saveObject(const WP<AbstractData> &saveObject) override;
|
||||
|
||||
/**
|
||||
* @brief deleteObject
|
||||
* @return
|
||||
*/
|
||||
bool deleteObject(const WP<AbstractData> &deleteObject) override;
|
||||
|
||||
virtual ~SqlDBWriter() override;
|
||||
|
||||
|
||||
QHash<QString, SP<DbTableBase> > getDbStruct() const;
|
||||
void setDbStruct(const QHash<QString, SP<DbTableBase> > &dbStruct);
|
||||
};
|
||||
|
||||
}
|
82
Heart/DataBaseSpace/websocketcontroller.cpp
Normal file
82
Heart/DataBaseSpace/websocketcontroller.cpp
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "databasenode.h"
|
||||
#include "abstractnodeinfo.h"
|
||||
#include "websocketcontroller.h"
|
||||
#include <quasarapp.h>
|
||||
#include <permission.h>
|
||||
|
||||
namespace NP {
|
||||
|
||||
|
||||
WebSocketController::WebSocketController(DataBaseNode *node) {
|
||||
_node = node;
|
||||
assert(_node);
|
||||
}
|
||||
|
||||
bool WebSocketController::subscribe(const BaseId& subscriber,
|
||||
const DbAddress &item) {
|
||||
|
||||
_subscribsMutex.lock();
|
||||
_subscribs[item].insert(subscriber);
|
||||
_subscribsMutex.unlock();
|
||||
|
||||
_itemsMutex.lock();
|
||||
_items[subscriber].insert(item);
|
||||
_itemsMutex.unlock();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void WebSocketController::unsubscribe(const BaseId &subscriber,
|
||||
const DbAddress& item) {
|
||||
_subscribsMutex.lock();
|
||||
_subscribs[item].remove(subscriber);
|
||||
_subscribsMutex.unlock();
|
||||
|
||||
_itemsMutex.lock();
|
||||
_items[subscriber].remove(item);
|
||||
_itemsMutex.unlock();
|
||||
|
||||
}
|
||||
|
||||
const QSet<DbAddress> &WebSocketController::list(const BaseId &subscriber) {
|
||||
QMutexLocker locker(&_itemsMutex);
|
||||
return _items[subscriber];
|
||||
}
|
||||
|
||||
void WebSocketController::handleItemChanged(const DBObject *item) {
|
||||
auto obj = dynamic_cast<const DBObject*>(item);
|
||||
if (obj)
|
||||
return;
|
||||
|
||||
QMutexLocker locker(&_subscribsMutex);
|
||||
|
||||
foreachSubscribers(item, _subscribs.value(obj->dbAddress()));
|
||||
}
|
||||
|
||||
void WebSocketController::foreachSubscribers(const DBObject *item,
|
||||
const QSet<BaseId> &subscribersList) {
|
||||
|
||||
for (const auto &subscriber : subscribersList) {
|
||||
bool fAllowed = _node->checkPermission(subscriber, item->dbAddress(), Permission::Read) ==
|
||||
DBOperationResult::Allowed;
|
||||
|
||||
if (fAllowed && !_node->sendData(item, subscriber)) {
|
||||
QuasarAppUtils::Params::log("Send update failed for " + subscriber.toBase64(),
|
||||
QuasarAppUtils::Warning);
|
||||
}
|
||||
|
||||
if (!fAllowed) {
|
||||
QuasarAppUtils::Params::log(QString("Internal Error. Member:%0 not have permission to object %1").
|
||||
arg(QString(subscriber.toBase64())).arg(item->toString()),
|
||||
QuasarAppUtils::Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
59
Heart/DataBaseSpace/websocketcontroller.h
Normal file
59
Heart/DataBaseSpace/websocketcontroller.h
Normal file
@ -0,0 +1,59 @@
|
||||
|
||||
/*
|
||||
* 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 WEBSOCKETCONTROLLER_H
|
||||
#define WEBSOCKETCONTROLLER_H
|
||||
|
||||
#include <QHash>
|
||||
#include <QSharedPointer>
|
||||
#include <dbobject.h>
|
||||
#include <baseid.h>
|
||||
#include <QMutex>
|
||||
|
||||
namespace NP {
|
||||
|
||||
class AbstractNodeInfo;
|
||||
class DataBaseNode;
|
||||
|
||||
/**
|
||||
* @brief The WebSocketController class - manage subscribe
|
||||
*/
|
||||
class NETWORKPROTOCOLSHARED_EXPORT WebSocketController : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
WebSocketController(DataBaseNode *node);
|
||||
bool subscribe(const BaseId &subscriber,
|
||||
const DbAddress &item);
|
||||
|
||||
void unsubscribe(const BaseId &subscriber,
|
||||
const DbAddress &item);
|
||||
|
||||
const QSet<DbAddress> &list(const BaseId& subscriber);
|
||||
|
||||
public slots:
|
||||
void handleItemChanged(const DBObject *item);
|
||||
|
||||
private:
|
||||
void foreachSubscribers(const DBObject *item,
|
||||
const QSet<BaseId> &subscribersList);
|
||||
|
||||
/// subscribers it is nodes or clients
|
||||
QHash<DbAddress, QSet<BaseId>> _subscribs;
|
||||
QHash<BaseId, QSet<DbAddress>> _items;
|
||||
|
||||
QMutex _subscribsMutex;
|
||||
QMutex _itemsMutex;
|
||||
|
||||
DataBaseNode *_node = nullptr;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
#endif // WEBSOCKETCONTROLLER_H
|
11
Heart/NetworkSpace/consensus.cpp
Normal file
11
Heart/NetworkSpace/consensus.cpp
Normal file
@ -0,0 +1,11 @@
|
||||
#include "consensus.h"
|
||||
|
||||
namespace NP {
|
||||
|
||||
const QStringList Consensus::Nodes = {
|
||||
"QuasarApp.ddns.net"
|
||||
};
|
||||
|
||||
const short Consensus::networkPort = 8211;
|
||||
|
||||
}
|
26
Heart/NetworkSpace/consensus.h
Normal file
26
Heart/NetworkSpace/consensus.h
Normal file
@ -0,0 +1,26 @@
|
||||
#ifndef CONSENSUS_H
|
||||
#define CONSENSUS_H
|
||||
|
||||
#include "heart_global.h"
|
||||
#include <QStringList>
|
||||
|
||||
namespace NP {
|
||||
|
||||
/**
|
||||
* @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
|
492
Heart/NetworkSpace/networknode.cpp
Normal file
492
Heart/NetworkSpace/networknode.cpp
Normal file
@ -0,0 +1,492 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#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 <networkmember.h>
|
||||
#include <networknodeinfo.h>
|
||||
#include <nodeobject.h>
|
||||
|
||||
|
||||
#define THIS_NODE "this_node_key"
|
||||
namespace NP {
|
||||
|
||||
NetworkNode::NetworkNode(NP::SslMode mode, QObject *ptr):
|
||||
DataBaseNode(mode, 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;
|
||||
}
|
||||
|
||||
BaseId NetworkNode::nodeId() const {
|
||||
|
||||
auto keys = _nodeKeys->getNextPair(THIS_NODE);
|
||||
return QCryptographicHash::hash(keys.publicKey(), QCryptographicHash::Sha256);
|
||||
}
|
||||
|
||||
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()});
|
||||
return _nodeKeys->check(_nodeKeys->concatSign(object->dataForSigned(),
|
||||
object->sign()), node->authenticationData());
|
||||
}
|
||||
|
||||
NodeObject NetworkNode::thisNode() const {
|
||||
NodeObject res;
|
||||
auto keys = _nodeKeys->getNextPair(THIS_NODE);
|
||||
|
||||
res.setAuthenticationData(keys.publicKey());
|
||||
res.setTrust(0);
|
||||
|
||||
res.prepareToSend();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
QSet<BaseId> NetworkNode::myKnowAddresses() const {
|
||||
QSet<BaseId> res;
|
||||
|
||||
for (const AbstractNodeInfo *i : connections()) {
|
||||
auto info = dynamic_cast<const BaseNodeInfo*>(i);
|
||||
if (info && info->selfId().isValid()) {
|
||||
res += info->selfId();
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
bool NetworkNode::welcomeAddress(const HostAddress& ip) {
|
||||
NodeObject self = thisNode();
|
||||
|
||||
if (!sendData(&self, ip)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (connections().size()) {
|
||||
|
||||
auto knowAddresses = myKnowAddresses();
|
||||
if (knowAddresses.size()) {
|
||||
KnowAddresses addressesData;
|
||||
addressesData.setKnowAddresses(knowAddresses);
|
||||
|
||||
if (!sendData(&addressesData, ip)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
void NetworkNode::nodeConnected(const HostAddress &node) {
|
||||
DataBaseNode::nodeConnected(node);
|
||||
|
||||
welcomeAddress(node);
|
||||
|
||||
}
|
||||
|
||||
void NetworkNode::nodeConfirmend(const HostAddress &node) {
|
||||
DataBaseNode::nodeConfirmend(node);
|
||||
|
||||
auto nodeInfo = dynamic_cast<NetworkNodeInfo*>(getInfoPtr(node));
|
||||
if (!nodeInfo) {
|
||||
return;
|
||||
}
|
||||
|
||||
_connectionsMutex.lock();
|
||||
NetworkNodeInfo* oldNodeInfo = _connections.value(nodeInfo->selfId(), nullptr);
|
||||
_connectionsMutex.unlock();
|
||||
|
||||
if (oldNodeInfo) {
|
||||
removeNode(node);
|
||||
return;
|
||||
}
|
||||
|
||||
_connectionsMutex.lock();
|
||||
_connections.insert(nodeInfo->selfId(), nodeInfo);
|
||||
|
||||
_connectionsMutex.unlock();
|
||||
|
||||
}
|
||||
|
||||
void NetworkNode::nodeDisconnected(const HostAddress &node) {
|
||||
AbstractNode::nodeDisconnected(node);
|
||||
|
||||
auto nodeInfo = dynamic_cast<BaseNodeInfo*>(getInfoPtr(node));
|
||||
if (!nodeInfo) {
|
||||
return;
|
||||
}
|
||||
|
||||
_connectionsMutex.lock();
|
||||
_connections.remove(nodeInfo->selfId());
|
||||
_connectionsMutex.unlock();
|
||||
}
|
||||
|
||||
void NetworkNode::incomingData(AbstractData *, const BaseId &) {}
|
||||
|
||||
QString NetworkNode::keyStorageLocation() const {
|
||||
return _nodeKeys->storageLocation();
|
||||
}
|
||||
|
||||
ParserResult NetworkNode::parsePackage(const Package &pkg,
|
||||
const AbstractNodeInfo *sender) {
|
||||
auto parentResult = AbstractNode::parsePackage(pkg, sender);
|
||||
if (parentResult != ParserResult::NotProcessed) {
|
||||
return parentResult;
|
||||
}
|
||||
|
||||
auto baseSender = dynamic_cast<const BaseNodeInfo*>(sender);
|
||||
if (!baseSender) {
|
||||
QuasarAppUtils::Params::log("Sender is not basenode info!",
|
||||
QuasarAppUtils::Error);
|
||||
return ParserResult::Error;
|
||||
}
|
||||
|
||||
if (H_16<BadNodeRequest>() == pkg.hdr.command) {
|
||||
BadNodeRequest cmd(pkg);
|
||||
|
||||
incomingData(&cmd, baseSender->selfId());
|
||||
emit requestError(cmd.err());
|
||||
|
||||
return ParserResult::Processed;
|
||||
|
||||
} else if (H_16<TransportData>() == pkg.hdr.command) {
|
||||
TransportData cmd(pkg);
|
||||
return workWithTransportData(&cmd, sender, pkg);
|
||||
|
||||
|
||||
} else if (H_16<NodeObject>() == pkg.hdr.command) {
|
||||
NodeObject obj(pkg);
|
||||
if (!obj.isValid()) {
|
||||
badRequest(sender->networkAddress(), pkg.hdr);
|
||||
return ParserResult::Error;
|
||||
}
|
||||
|
||||
if (!workWithNodeObjectData(obj, sender)) {
|
||||
badRequest(obj.senderID(), pkg.hdr);
|
||||
return ParserResult::Error;
|
||||
}
|
||||
|
||||
return ParserResult::Processed;
|
||||
} else if (H_16<KnowAddresses>() == pkg.hdr.command) {
|
||||
KnowAddresses obj(pkg);
|
||||
if (!obj.isValid()) {
|
||||
badRequest(sender->networkAddress(), pkg.hdr);
|
||||
return ParserResult::Error;
|
||||
}
|
||||
|
||||
if (!workWithKnowAddresses(obj, sender)) {
|
||||
badRequest(sender->networkAddress(), pkg.hdr);
|
||||
return ParserResult::Error;
|
||||
}
|
||||
|
||||
return ParserResult::Processed;
|
||||
} else if (H_16<LongPing>() == pkg.hdr.command) {
|
||||
LongPing cmd(pkg);
|
||||
|
||||
if (!cmd.ansver()) {
|
||||
cmd.setAnsver(true);
|
||||
sendData(&cmd, cmd.senderID(), &pkg.hdr);
|
||||
}
|
||||
|
||||
incomingData(&cmd, baseSender->selfId());
|
||||
return ParserResult::Processed;
|
||||
} else if (H_16<NetworkRequest>() == pkg.hdr.command) {
|
||||
NetworkRequest cmd(pkg);
|
||||
|
||||
if (!cmd.isValid()) {
|
||||
badRequest(baseSender->selfId(), pkg.hdr);
|
||||
return ParserResult::Error;
|
||||
}
|
||||
|
||||
workWithNetworkRequest(&cmd, baseSender);
|
||||
return ParserResult::Processed;
|
||||
}
|
||||
|
||||
return ParserResult::NotProcessed;
|
||||
}
|
||||
|
||||
bool NetworkNode::workWithNodeObjectData(NodeObject &node,
|
||||
const AbstractNodeInfo* nodeInfo) {
|
||||
|
||||
if (!db()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto localObjec = db()->getObject(node);
|
||||
|
||||
if (localObjec) {
|
||||
node.setTrust(std::min(node.trust(), localObjec->trust()));
|
||||
} else {
|
||||
node.setTrust(0);
|
||||
}
|
||||
|
||||
if (!db()->saveObject(&node)) {
|
||||
return false;
|
||||
};
|
||||
|
||||
auto peerNodeInfo = dynamic_cast<NetworkNodeInfo*>(getInfoPtr(nodeInfo->networkAddress()));
|
||||
if (!peerNodeInfo)
|
||||
return false;
|
||||
|
||||
peerNodeInfo->setSelfId(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(AbstractData *transportData,
|
||||
const AbstractNodeInfo* sender,
|
||||
const Package& pkg) {
|
||||
|
||||
// convert transoprt pakcage
|
||||
auto cmd = dynamic_cast<TransportData*>(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(cmd->data(), 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, *it, &pkg.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);
|
||||
}
|
||||
|
||||
routeFromSenderToHere.erase(routeFromSenderToHere.begin(), routeFromSenderToHere.begin() + index);
|
||||
// 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, cmd->targetAddress(), &pkg.hdr)) {
|
||||
return ParserResult::Error;
|
||||
}
|
||||
}
|
||||
|
||||
_router->addProcesedPackage(cmd->packageId());
|
||||
return ParserResult::Processed;
|
||||
|
||||
}
|
||||
|
||||
ParserResult NetworkNode::workWithNetworkRequest(AbstractData *networkRequest,
|
||||
const AbstractNodeInfo *sender) {
|
||||
// convert transoprt pakcage
|
||||
auto cmd = dynamic_cast<NetworkRequest*>(networkRequest);
|
||||
|
||||
if (!cmd)
|
||||
return ParserResult::Error;
|
||||
|
||||
if (cmd->isComplete()) {
|
||||
if (cmd->askedNodes().contains(nodeId())) {
|
||||
return parsePackage(cmd->dataResponce(), 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);
|
||||
}
|
||||
|
||||
bool NetworkNode::sendData(const AbstractData *resp, const BaseId &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){
|
||||
bool result = false;
|
||||
for (auto it = nodes.begin(); it != nodes.end(); ++it) {
|
||||
result = result || sendData(data, it.key(), req);
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
bool NetworkNode::sendData(AbstractData *resp, const BaseId &nodeId, const Header *req) {
|
||||
return DataBaseNode::sendData(resp, nodeId, req);
|
||||
}
|
||||
|
||||
bool NetworkNode::sendData(const AbstractData *resp, const HostAddress &nodeId, const Header *req) {
|
||||
return DataBaseNode::sendData(resp, nodeId, req);
|
||||
}
|
||||
|
||||
bool NetworkNode::sendData(AbstractData *resp, const HostAddress &nodeId, const Header *req) {
|
||||
return DataBaseNode::sendData(resp, nodeId, req);
|
||||
}
|
||||
|
||||
bool NetworkNode::ping(const BaseId &id) {
|
||||
LongPing cmd(nodeId());
|
||||
return sendData(&cmd, id);
|
||||
}
|
||||
|
||||
}
|
||||
|
256
Heart/NetworkSpace/networknode.h
Normal file
256
Heart/NetworkSpace/networknode.h
Normal file
@ -0,0 +1,256 @@
|
||||
/*
|
||||
* 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 NETWORKNODE_H
|
||||
#define NETWORKNODE_H
|
||||
|
||||
#include <databasenode.h>
|
||||
#include <dbobject.h>
|
||||
#include <hostaddress.h>
|
||||
#include <nodeobject.h>
|
||||
|
||||
|
||||
namespace NP {
|
||||
|
||||
class NetworkMember;
|
||||
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 NETWORKPROTOCOLSHARED_EXPORT NetworkNode : public DataBaseNode
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief BaseNode
|
||||
* @param mode
|
||||
* @param ptr
|
||||
*/
|
||||
NetworkNode(SslMode mode = SslMode::NoSSL, 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
|
||||
* @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 address
|
||||
* @return
|
||||
*/
|
||||
bool ping( const BaseId& id);
|
||||
|
||||
/**
|
||||
* @brief nodeId
|
||||
* @return
|
||||
*/
|
||||
BaseId nodeId() const;
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* @brief sendDataToId - send data to node or clientby them id.
|
||||
* @param resp - responce package
|
||||
* @param nodeId - id of target node
|
||||
* @param req - header of request
|
||||
* @return true if data sendet seccussful
|
||||
*/
|
||||
bool sendData(const AbstractData *resp, const BaseId &nodeId,
|
||||
const Header *req = nullptr) override;
|
||||
|
||||
bool sendData(AbstractData *resp, const BaseId &nodeId,
|
||||
const Header *req = nullptr) override;
|
||||
bool sendData(const AbstractData *resp, const HostAddress &nodeId,
|
||||
const Header *req = nullptr) override;
|
||||
bool sendData(AbstractData *resp, const HostAddress &nodeId,
|
||||
const Header *req = nullptr) override;
|
||||
|
||||
/**
|
||||
* @brief initDefaultDbObjects create default cache and db writer if pointer is null
|
||||
* @param cache
|
||||
* @param writer
|
||||
*/
|
||||
void initDefaultDbObjects(SqlDBCache *cache, SqlDBWriter *writer);
|
||||
|
||||
/**
|
||||
* @brief parsePackage
|
||||
* @param pkg
|
||||
* @param sender
|
||||
* @return
|
||||
*/
|
||||
ParserResult parsePackage(const Package &pkg,
|
||||
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 NodeObject &node, const MemberPermisionObject& permision);
|
||||
/**
|
||||
* @brief checkSignOfRequest
|
||||
* @param request - package
|
||||
* @return true if request signed.
|
||||
*/
|
||||
virtual bool checkSignOfRequest(const AbstractData *request);
|
||||
|
||||
/**
|
||||
* @brief thisNode
|
||||
* @return This node object value.
|
||||
*/
|
||||
NodeObject thisNode() const;
|
||||
|
||||
/**
|
||||
* @brief myKnowAddresses
|
||||
* @return set of know addresses
|
||||
*/
|
||||
QSet<BaseId> myKnowAddresses() const;
|
||||
|
||||
/**
|
||||
* @brief welcomeAddress - this method send to the ip information about yaster self.
|
||||
* @param ip - host address of the peer node obeject
|
||||
* @return true if all iformation sendet succesful
|
||||
*/
|
||||
bool welcomeAddress(const HostAddress &ip) override;
|
||||
|
||||
/**
|
||||
* @brief connectionRegistered - this impletation send incomming node welcom message with information about yaster self.
|
||||
* @param info incominng node info.
|
||||
*/
|
||||
void nodeConnected(const HostAddress& node) override;
|
||||
|
||||
/**
|
||||
* @brief nodeConfirmend - this implementation test nodes to double connections
|
||||
* @param mode
|
||||
*/
|
||||
void nodeConfirmend(const HostAddress& sender) override;
|
||||
|
||||
/**
|
||||
* @brief nodeDisconnected - this implementation remove nodes info from connection cache
|
||||
* @param sender
|
||||
*/
|
||||
void nodeDisconnected(const HostAddress& 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(AbstractData* pkg,
|
||||
const BaseId& sender);
|
||||
|
||||
/**
|
||||
* @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(NodeObject &node, const AbstractNodeInfo *nodeInfo);
|
||||
|
||||
/**
|
||||
* @brief workWithKnowAddresses
|
||||
* @param node
|
||||
* @param nodeInfo
|
||||
* @return
|
||||
*/
|
||||
bool workWithKnowAddresses(const KnowAddresses &obj, const AbstractNodeInfo *nodeInfo);
|
||||
|
||||
/**
|
||||
* @brief workWithTransportData
|
||||
* @param transportData
|
||||
* @param sender
|
||||
* @param pkg
|
||||
* @return
|
||||
*/
|
||||
ParserResult workWithTransportData(AbstractData* transportData, const AbstractNodeInfo *sender, const Package &pkg);
|
||||
|
||||
/**
|
||||
* @brief workWithNetworkRequest
|
||||
* @param networkRequest
|
||||
* @param sender
|
||||
* @param pkg
|
||||
* @return
|
||||
*/
|
||||
ParserResult workWithNetworkRequest(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 BaseId& 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(AbstractData* pkg,
|
||||
const HostAddress& sender) override final;
|
||||
|
||||
|
||||
KeyStorage *_nodeKeys = nullptr;
|
||||
|
||||
Router *_router = nullptr;
|
||||
|
||||
QHash<BaseId, NetworkNodeInfo*> _connections;
|
||||
|
||||
mutable QMutex _connectionsMutex;
|
||||
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
#endif // NETWORKNODE_H
|
42
Heart/NetworkSpace/networknodeinfo.cpp
Normal file
42
Heart/NetworkSpace/networknodeinfo.cpp
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "networknodeinfo.h"
|
||||
#include "dbaddress.h"
|
||||
#include <QTcpSocket>
|
||||
#include <hostaddress.h>
|
||||
|
||||
namespace NP {
|
||||
|
||||
|
||||
NetworkNodeInfo::NetworkNodeInfo(QAbstractSocket *tcp, const HostAddress* address):
|
||||
BaseNodeInfo(tcp, address){}
|
||||
|
||||
NetworkNodeInfo::~NetworkNodeInfo() = default;
|
||||
|
||||
bool NetworkNodeInfo::isValid() const {
|
||||
return BaseNodeInfo::isValid();
|
||||
}
|
||||
|
||||
bool NetworkNodeInfo::isKnowAddress(const BaseId &address) const {
|
||||
return _knowAddresses.contains(address);
|
||||
}
|
||||
|
||||
void NetworkNodeInfo::setSelfId(const BaseId &selfId) {
|
||||
BaseNodeInfo::setSelfId(selfId);
|
||||
_knowAddresses.insert(_selfId);
|
||||
}
|
||||
|
||||
void NetworkNodeInfo::addKnowAddresses(const QSet<BaseId> &newAddressses) {
|
||||
_knowAddresses += newAddressses;
|
||||
}
|
||||
|
||||
bool NetworkNodeInfo::confirmData() const {
|
||||
return BaseNodeInfo::confirmData() && _selfId.isValid();
|
||||
}
|
||||
|
||||
}
|
73
Heart/NetworkSpace/networknodeinfo.h
Normal file
73
Heart/NetworkSpace/networknodeinfo.h
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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 NETWORKCONNECTIONINFO_H
|
||||
#define NETWORKCONNECTIONINFO_H
|
||||
|
||||
#include "basenodeinfo.h"
|
||||
#include "accesstoken.h"
|
||||
#include "baseid.h"
|
||||
#include "heart_global.h"
|
||||
#include <QByteArray>
|
||||
|
||||
class QAbstractSocket;
|
||||
namespace NP {
|
||||
|
||||
class DbAddress;
|
||||
|
||||
/**
|
||||
* @brief The BaseNodeInfo class contaisn list of nodes id of know this node.
|
||||
*/
|
||||
class NETWORKPROTOCOLSHARED_EXPORT NetworkNodeInfo: public BaseNodeInfo {
|
||||
|
||||
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 BaseId& address) const;
|
||||
|
||||
/**
|
||||
* @brief setSelfId
|
||||
* @param selfId
|
||||
*/
|
||||
void setSelfId(const BaseId &selfId);
|
||||
|
||||
/**
|
||||
* @brief addKnowAddresses
|
||||
*/
|
||||
void addKnowAddresses(const QSet<BaseId> &newAddressses);
|
||||
|
||||
/**
|
||||
* @brief confirmData - this implementaton check self id of node.
|
||||
* @return true if node contains valid self id.
|
||||
*/
|
||||
bool confirmData() const override;
|
||||
|
||||
protected:
|
||||
QSet<BaseId> _knowAddresses;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // NETWORKCONNECTIONINFO_H
|
55
Heart/NetworkSpace/packages/badnoderequest.cpp
Normal file
55
Heart/NetworkSpace/packages/badnoderequest.cpp
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "badnoderequest.h"
|
||||
namespace NP {
|
||||
|
||||
BadNodeRequest::BadNodeRequest() {
|
||||
|
||||
}
|
||||
|
||||
BadNodeRequest::BadNodeRequest(const QString &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);
|
||||
|
||||
BaseId senderNode;
|
||||
stream >> senderNode;
|
||||
setSenderID(senderNode);
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
QDataStream &BadNodeRequest::toStream(QDataStream &stream) const {
|
||||
BadRequest::toStream(stream);
|
||||
stream << senderID();
|
||||
|
||||
return stream;
|
||||
}
|
||||
}
|
37
Heart/NetworkSpace/packages/badnoderequest.h
Normal file
37
Heart/NetworkSpace/packages/badnoderequest.h
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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 BADNODEREQUEST_H
|
||||
#define BADNODEREQUEST_H
|
||||
|
||||
#include "senderdata.h"
|
||||
|
||||
#include <badrequest.h>
|
||||
|
||||
namespace NP {
|
||||
|
||||
/**
|
||||
* @brief The BadNodeRequest class - bad request command for bae node level
|
||||
*/
|
||||
class NETWORKPROTOCOLSHARED_EXPORT BadNodeRequest: public BadRequest, public SenderData
|
||||
{
|
||||
public:
|
||||
explicit BadNodeRequest();
|
||||
explicit BadNodeRequest(const QString & 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
|
57
Heart/NetworkSpace/packages/knowaddresses.cpp
Normal file
57
Heart/NetworkSpace/packages/knowaddresses.cpp
Normal file
@ -0,0 +1,57 @@
|
||||
#include "knowaddresses.h"
|
||||
|
||||
#include <QDataStream>
|
||||
|
||||
namespace NP {
|
||||
|
||||
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<BaseId> KnowAddresses::knowAddresses() const {
|
||||
return _knowAddresses;
|
||||
}
|
||||
|
||||
void KnowAddresses::setKnowAddresses(const QSet<BaseId> &knowAddresses) {
|
||||
_knowAddresses = knowAddresses;
|
||||
}
|
||||
|
||||
}
|
36
Heart/NetworkSpace/packages/knowaddresses.h
Normal file
36
Heart/NetworkSpace/packages/knowaddresses.h
Normal file
@ -0,0 +1,36 @@
|
||||
#ifndef KNOWADDRESSES_H
|
||||
#define KNOWADDRESSES_H
|
||||
|
||||
#include <QSet>
|
||||
#include <abstractdata.h>
|
||||
#include <baseid.h>
|
||||
|
||||
namespace NP {
|
||||
|
||||
/**
|
||||
* @brief The KnowAddresses class - this class is package for send the list of know addresses of node to other node object.
|
||||
*/
|
||||
class NETWORKPROTOCOLSHARED_EXPORT KnowAddresses: public AbstractData
|
||||
{
|
||||
public:
|
||||
KnowAddresses();
|
||||
KnowAddresses(const Package &pkg);
|
||||
|
||||
// AbstractData interface
|
||||
bool isValid() const override;
|
||||
bool copyFrom(const AbstractData *) override;
|
||||
|
||||
QSet<BaseId> knowAddresses() const;
|
||||
void setKnowAddresses(const QSet<BaseId> &knowAddresses);
|
||||
|
||||
|
||||
// StreamBase interface
|
||||
protected:
|
||||
QDataStream &fromStream(QDataStream &stream) override;
|
||||
QDataStream &toStream(QDataStream &stream) const override;
|
||||
|
||||
private:
|
||||
QSet<BaseId> _knowAddresses;
|
||||
};
|
||||
}
|
||||
#endif // KNOWADDRESSES_H
|
42
Heart/NetworkSpace/packages/longping.cpp
Normal file
42
Heart/NetworkSpace/packages/longping.cpp
Normal file
@ -0,0 +1,42 @@
|
||||
#include "longping.h"
|
||||
|
||||
namespace NP {
|
||||
|
||||
LongPing::LongPing(const BaseId& 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 &NP::LongPing::fromStream(QDataStream &stream) {
|
||||
Ping::fromStream(stream);
|
||||
stream >> _senderID;
|
||||
return stream;
|
||||
}
|
||||
|
||||
QDataStream &LongPing::toStream(QDataStream &stream) const {
|
||||
Ping::toStream(stream);
|
||||
stream << _senderID;
|
||||
return stream;
|
||||
}
|
||||
|
||||
}
|
29
Heart/NetworkSpace/packages/longping.h
Normal file
29
Heart/NetworkSpace/packages/longping.h
Normal file
@ -0,0 +1,29 @@
|
||||
#ifndef LONGPING_H
|
||||
#define LONGPING_H
|
||||
|
||||
#include "ping.h"
|
||||
#include <senderdata.h>
|
||||
|
||||
namespace NP {
|
||||
|
||||
/**
|
||||
* @brief The LongPing class - test class for big network with return addresse
|
||||
*/
|
||||
class NETWORKPROTOCOLSHARED_EXPORT LongPing: public Ping, public SenderData
|
||||
{
|
||||
public:
|
||||
LongPing(const BaseId &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
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user