Heart/Heart/AbstractSpace/abstractnode.h

800 lines
29 KiB
C
Raw Normal View History

2020-09-15 21:16:35 +03:00
/*
* Copyright (C) 2018-2021 QuasarApp.
2020-09-15 21:16:35 +03:00
* 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.
*/
2021-09-02 18:40:14 +03:00
2020-09-15 21:16:35 +03:00
#ifndef ABSTRACTNODE_H
#define ABSTRACTNODE_H
#include "abstractnodeinfo.h"
2021-10-31 22:03:57 +03:00
#ifdef USE_HEART_SSL
2020-09-15 21:16:35 +03:00
#include <openssl/evp.h>
#include <QSslConfiguration>
#endif
2020-09-15 21:16:35 +03:00
#include <QAbstractSocket>
#include <QFutureWatcher>
#include <QMutex>
2021-02-23 19:12:25 +03:00
#include <QSharedPointer>
2020-09-15 21:16:35 +03:00
#include <QTcpServer>
#include <QThreadPool>
2020-09-15 21:16:35 +03:00
#include <QTimer>
#include <softdelete.h>
2020-09-15 21:16:35 +03:00
#include "abstractdata.h"
#include "workstate.h"
#include "package.h"
2020-09-15 21:16:35 +03:00
#include "cryptopairkeys.h"
#include "icrypto.h"
#include "heart_global.h"
#include "packagemanager.h"
2020-10-29 20:23:50 +03:00
#include "abstracterrorcodes.h"
2020-09-15 21:16:35 +03:00
2020-09-15 22:07:49 +03:00
namespace QH {
2020-09-15 21:16:35 +03:00
class DataSender;
class ReceiveData;
class SocketFactory;
class AsyncLauncher;
2021-10-01 22:54:49 +03:00
class BigDataManager;
2021-10-11 20:42:13 +03:00
class TaskScheduler;
class AbstractTask;
2021-10-31 22:03:57 +03:00
class SslSocket;
2020-09-15 21:16:35 +03:00
2020-10-29 20:23:50 +03:00
namespace PKG {
class ErrorData;
}
2020-09-15 21:16:35 +03:00
/**
* @brief The ParserResult enum.
* Error - parser detect a errorob package.
2020-09-15 21:16:35 +03:00
* NotProcessed - the parser does not know what to do with the package or has not finished processing it.
* Processed - the parser finished processing correctly.
2020-09-15 21:16:35 +03:00
*/
enum class ParserResult {
/// parser detect a errorob package.
2020-09-15 21:16:35 +03:00
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.
2020-09-15 21:16:35 +03:00
Processed = 2
};
/**
* @brief The SslMode enum This enum contatins options for set ssl mode of node (server).
* For more information see AbstractNode::useSelfSignedSslConfiguration AbstractNode::useSystemSslConfiguration and AbstractNode::disableSSL methods.
*/
2020-09-15 21:16:35 +03:00
enum class SslMode {
/// This is not secure connection without ssl encription. It is default value of new any node see AbstractNode(SslMode mode = SslMode::NoSSL, QObject * ptr = nullptr).
2020-09-15 21:16:35 +03:00
NoSSL,
2021-10-31 22:03:57 +03:00
#ifdef USE_HEART_SSL
/// This option try enable ssl connection from system configuration form fore information see Qt Documentation https://doc.qt.io/qt-5/qsslconfiguration.html
2020-09-15 21:16:35 +03:00
InitFromSystem,
/// This option force a current node geneerate self signed sertificat and work with it. For more information see a SslSrtData struct.
2020-09-15 21:16:35 +03:00
InitSelfSigned
#endif
2020-09-15 21:16:35 +03:00
};
2021-10-31 22:03:57 +03:00
#ifdef USE_HEART_SSL
2020-09-15 21:16:35 +03:00
/**
* @brief The SslSrtData struct This structure contains base information for generate self signed ssl certefication.
* If you want change selfSigned certificate then use method AbstractNode::useSelfSignedSslConfiguration.
2020-09-15 21:16:35 +03:00
*/
struct SslSrtData {
QString country = "BY";
QString organization = "QuasarApp";
2021-11-01 18:35:42 +03:00
QString commonName = "";
2020-09-15 21:16:35 +03:00
long long endTime = 31536000L; //1 year
};
#endif
2020-09-15 21:16:35 +03:00
2021-11-01 11:07:24 +03:00
#define CRITICAL_ERROOR -50
#define LOGICK_ERROOR -20
#define REQUEST_ERROR -5
#define NOTSUPPORT_ERROR -1
2020-09-15 21:16:35 +03:00
2021-10-02 22:12:39 +03:00
#define BIG_DATA_HASH_ID 0xFFFF
2020-09-15 21:16:35 +03:00
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.
2021-09-25 14:26:47 +03:00
*
* @note For correctly working this class you should be register all you data types using the AbstractNode::registerPackageType method.
2021-09-03 10:15:56 +03:00
* @see AbstractData
2021-09-25 14:26:47 +03:00
* @see AbstractNode::registerPackageType
* @see AbstractNode::parsePackage
2020-09-15 21:16:35 +03:00
*/
class HEARTSHARED_EXPORT AbstractNode : public QTcpServer, public SoftDelete
2020-09-15 21:16:35 +03:00
{
Q_OBJECT
public:
/**
* @brief AbstractNode - Base constructor of node.
* @param ptr - Pointrt to parent Qt object, the AbstractNode class is Q_OBJECT.
2021-09-25 14:26:47 +03:00
* @note For correctly working this class you should be register all you data types using the AbstractNode::registerPackageType method.
2020-09-15 21:16:35 +03:00
*/
AbstractNode(QObject * ptr = nullptr);
2020-09-15 21:16:35 +03:00
~AbstractNode() override;
/**
2020-09-26 15:16:12 +03:00
* @brief run This method implement deployment a network node (server) on selected address.
* @param addres This is network address of work node or server.
* If address is empty then server weel be listen all addreses of all interfaces else listen only selected address.
* @param port This is port of deployment node (server)
* @return Result of deployment node (sever). (True if deploy finished successful else false).
2020-09-15 21:16:35 +03:00
*/
virtual bool run(const QString& addres, unsigned short port);
/**
* @brief stop - Stopped this node and close all network connections.
2020-09-15 21:16:35 +03:00
*/
virtual void stop();
/**
* @brief getInfoPtr - This method return information class pointer about netwok connection.
* If Connection with id not found then return nullptr.
* @param id - It is network address of requested node.
* @return The pointer of information about node. if address not found return nullptr.
2020-09-15 21:16:35 +03:00
*/
virtual AbstractNodeInfo* getInfoPtr(const HostAddress &id);
/**
* @brief getInfoPtr - This is some that getInfoPtr(const HostAddress &id) bod it is constant implementation.
* @param id - It is network address of requested node.
* @return The pointer of information about node. if address not found return nullptr.
2020-09-15 21:16:35 +03:00
*/
virtual const AbstractNodeInfo* getInfoPtr(const HostAddress &id) const;
/**
* @brief ban - This method set for target connection a trust property to 0 and target connection will been aborted.
* @param target - It is network address of target connection.
2020-09-15 21:16:35 +03:00
*/
virtual void ban(const HostAddress& target);
/**
* @brief unBan - This method set for target connection a trust property to 100.
* @param target - It is network address of target connection.
2020-09-15 21:16:35 +03:00
*/
virtual void unBan(const HostAddress& target);
/**
2021-03-22 19:56:33 +03:00
* @brief addNode - Connect to node (server) with address.
* @param address - This is Network address of node (server).
2021-03-24 15:55:49 +03:00
* @return true if the node aaded successful
2020-09-15 21:16:35 +03:00
*/
2021-03-22 19:56:33 +03:00
bool addNode(const HostAddress &address);
2020-09-15 21:16:35 +03:00
/**
2021-03-22 19:56:33 +03:00
* @brief addNode - Connect to node (server) with domain, bud this method find ip address of domain befor connecting.
* @param domain - This is domain address of node (server).
* @param port - This is target port of node (server).
2021-03-24 15:55:49 +03:00
* @return true if the node aaded successful
2020-09-15 21:16:35 +03:00
*/
2021-03-22 19:56:33 +03:00
bool addNode(const QString &domain, unsigned short port);
2020-09-15 21:16:35 +03:00
/**
* @brief removeNode - Remove node and disconnected forom node (server).
* @param nodeAdderess - This is network adddress of removed node (server).
2021-03-24 15:55:49 +03:00
* @return true if the node removed successful. If the nde with @a nodeAdderess is not exits return false.
2020-09-15 21:16:35 +03:00
*/
2021-03-24 15:55:49 +03:00
bool removeNode(const HostAddress& nodeAdderess);
2020-09-15 21:16:35 +03:00
2021-09-30 12:30:16 +03:00
/**
* @brief removeNode - Remove node and disconnected forom node (server).
* @param node - This is removed node (server).
* @return true if the node removed successful. If the nde with @a nodeAdderess is not exits return false.
*/
bool removeNode(AbstractNodeInfo* node);
2020-09-15 21:16:35 +03:00
/**
* @brief address - Thim method return own network address of current node (server).
* @return The current network adderss.
2020-09-15 21:16:35 +03:00
*/
HostAddress address() const;
2021-10-31 22:03:57 +03:00
#ifdef USE_HEART_SSL
2020-09-15 21:16:35 +03:00
/**
* @brief getSslConfig - This method return ssl configuration of current node (server).
* @return current ssl configuration on this node (server).
2020-09-15 21:16:35 +03:00
*/
QSslConfiguration getSslConfig() const;
#endif
2020-09-15 21:16:35 +03:00
/**
* @brief getMode - This method return SSL mode of corrent node (server).
* @return current mode for more information see SslMode.
2020-09-15 21:16:35 +03:00
*/
SslMode getMode() const;
/**
* @brief getWorkState - This method collect general information about this server.
* For more information about returned data see getWorkState
* @return state value for more information see WorkState class.
2020-09-15 21:16:35 +03:00
*/
virtual WorkState getWorkState() const;
/**
* @brief pareseResultToString This method convert ParserResult value to string.
* @return The String value of pareseresult.
2020-09-15 21:16:35 +03:00
*/
QString pareseResultToString(const ParserResult& parseResult) const;
/**
* @brief connectionsCount - Return count fo connections (connections with status connected)
* @return Count valid connections.
2020-09-15 21:16:35 +03:00
*/
int connectionsCount() const;
/**
* @brief connectionsCount - Return count of nodes with status confirmend.
* @return return confirmend connections of this node (server).
2020-09-15 21:16:35 +03:00
*/
int confirmendCount() const;
/**
* @brief ping This method send ping package to address for testing connection.
* @param address This is address of target node (server).
* @return true if ping sendet successful.
2020-09-15 21:16:35 +03:00
*/
bool ping( const HostAddress& address);
2021-03-23 23:02:28 +03:00
/**
* @brief mainThreadID This method return the pointer to main thread
* @return pointer to main thread
*/
2021-04-30 22:41:34 +03:00
static QThread *mainThreadID();
2021-03-23 23:02:28 +03:00
2021-10-12 00:47:39 +03:00
/**
* @brief sheduleTask This method shedule execute task on this node.
* @param task This is task that will be sheduled.
2021-10-14 13:45:03 +03:00
* @return true if task added successfull else flase
2021-10-12 00:47:39 +03:00
* @see AbstractNode::removeTask
* @see AbstractNode::sheduledTaskCount
*/
2021-10-14 13:45:03 +03:00
bool sheduleTask(const QSharedPointer<AbstractTask>& task);
2021-10-12 00:47:39 +03:00
/**
* @brief removeTask This method remove task from sheduler.
* @param taskId This is task id that will be removed.
* @see AbstractNode::sheduleTask
* @see AbstractNode::sheduledTaskCount
*/
void removeTask(int taskId);
/**
* @brief sheduledTaskCount This method return count of sheduled tasks.
* @return count of sheduled tasks.
* @see AbstractNode::sheduleTask
* @see AbstractNode::removeTask
*/
int sheduledTaskCount() const;
2021-11-01 22:58:05 +03:00
#ifdef USE_HEART_SSL
/**
* @brief ignoreSslErrors This method return list of ignored ssl errors
* @return list of ignored ssl errors.
* @see handleSslErrorOcurred
*/
const QList<QSslError> &ignoreSslErrors() const;
#endif
2020-09-15 21:16:35 +03:00
signals:
/**
* @brief requestError This signal emited when client or node received from remoute server or node the BadRequest package.
2020-10-29 20:23:50 +03:00
* @param code This is code of error.
* @param msg - received text of remoute node (server).
*/
void requestError(unsigned char code, QString msg);
2020-09-15 21:16:35 +03:00
2021-03-23 23:02:28 +03:00
2020-09-15 21:16:35 +03:00
protected:
2021-10-31 22:03:57 +03:00
#ifdef USE_HEART_SSL
2021-11-01 22:58:05 +03:00
/**
* @brief setIgnoreSslErrors This list sets new ignored errors.
* @param newIgnoreSslErrors This is new list of ignored errors.
* @see handleSslErrorOcurred
*/
void setIgnoreSslErrors(const QList<QSslError> &newIgnoreSslErrors);
2020-09-15 21:16:35 +03:00
/**
* @brief generateRSAforSSL This method generate ssl rsa pair keys for using in selfsigned cetificate.
* By default generate RSA 2048, if you want change algorithm or keys size then override this method.
* @param pkey This is openssl pointer to RSA pair key.
* @return True if keys generated successful.
2020-09-15 21:16:35 +03:00
*/
virtual bool generateRSAforSSL(EVP_PKEY* pkey) const;
/**
* @brief generateSslDataPrivate This method generate a ssl certificate and a ssl keys using The SslSrtData structure.
* @param data The data for generate a selfSigned certificate.
* @param r_srt This is return value of a certivicate.
* @param r_key - This is return value of private ssl key.
* @return True if generate the selfSigned certificate finished succesful.
2020-09-15 21:16:35 +03:00
*/
virtual bool generateSslDataPrivate(const SslSrtData& data, QSslCertificate& r_srt, QSslKey& r_key);
/**
* @brief selfSignedSslConfiguration This method create a new ssl configuration with selfsigned certificates.
* @param data This is data for generate selfsigned certification for more information see SslSrtData structure.
* @return The new selfsigned ssl configuration.
2020-09-15 21:16:35 +03:00
*/
virtual QSslConfiguration selfSignedSslConfiguration( const SslSrtData& data = {});
#endif
2020-09-15 21:16:35 +03:00
/**
* @brief createNodeInfo This method create a nodeInfo object.
* override this method for create your own nodeInfo objects. for more in
* @param socket This is socket of network address.
* @param clientAddress This parameter need to set when the socket du not contains a address or invalid.
* @return return pointer to info object.
2020-09-15 21:16:35 +03:00
*/
virtual AbstractNodeInfo* createNodeInfo(QAbstractSocket *socket,
const HostAddress *clientAddress = nullptr) const;
/**
* @brief registerSocket This method registration new socket object.
* @param socket This is incomming socket pointer.
* @param address This is 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.
2020-09-15 21:16:35 +03:00
*/
virtual bool registerSocket(QAbstractSocket *socket, const HostAddress* address = nullptr);
/**
* @brief parsePackage This is main method of all childs classes of an AbstractNode class.
* This method work on own thread.
* If you ovveride this method you need to create this than an example:
* \code{cpp}
2021-02-22 19:58:07 +03:00
ParserResult DataBaseNode::parsePackage(PKG::AbstractData *pkg,
const Header& pkgHeader,
const AbstractNodeInfo* sender) {
auto parentResult = AbstractNode::parsePackage(pkg, sender);
if (parentResult != ParserResult::NotProcessed) {
return parentResult;
}
2021-09-25 14:26:47 +03:00
// you can use parsing without the commandHandler method
2021-10-06 12:29:06 +03:00
if (MyCommand::command() == pkg->cmd()) {
BaseId requesterId = getSender(sender, &obj);
...
if (FailCondition) {
return ParserResult::Error;
}
...
return ParserResult::Processed;
}
2021-09-25 14:26:47 +03:00
// Or with the commandHandler method
2021-09-25 20:44:58 +03:00
auto result = commandHandler<MyPackage>(this, &MyClass::processMyPackage, pkg, sender, pkgHeader);
2021-09-25 14:26:47 +03:00
if (result != QH::ParserResult::NotProcessed) {
return result;
}
return ParserResult::NotProcessed;
}
* \endcode
* @param pkg This is package with incomming data.
2021-05-14 14:48:34 +03:00
* @param sender This is sender this pacakge.
* @param pkgHeader This is header of the incoming packet is used to create a response.
* @return item of ParserResult. For more information see The ParserResult enum.
2021-09-25 14:52:42 +03:00
* @see AbstractNode::commandHandler
* @see AbstractNode::sendData
* @see AbstractNode::badRequest
2020-09-15 21:16:35 +03:00
*/
2021-09-25 14:26:47 +03:00
virtual ParserResult parsePackage(const QSharedPointer<PKG::AbstractData> &pkg,
const Header& pkgHeader, const AbstractNodeInfo* sender);
2020-09-15 21:16:35 +03:00
/**
* @brief sendPackage This method prepare and send to target address a package.
* @param pkg This is sendet pakcage to target node.
* @param target This is target node.
* @return return true if The package is sendet succesfull.
*
* @note All packages sendets on the sender threaed. But thread of the node is wait for sends result.
* This is done that allthe data that is sent when node are dissconected come without fail.
2020-09-15 21:16:35 +03:00
*/
virtual bool sendPackage(const Package &pkg, QAbstractSocket *target) const;
/**
2021-10-06 12:29:06 +03:00
* @brief sendData This method send data object another to node
* @param resp This is pointer to sendet object.
* @param address This is target addres for sending.
* @param req This is header of request.
2021-03-05 20:24:50 +03:00
* @return hash of the sendet package. If function is failed then return 0.
2020-09-15 21:16:35 +03:00
*/
2021-03-05 20:24:50 +03:00
virtual unsigned int sendData(const PKG::AbstractData *resp, const HostAddress& address,
2021-10-06 12:29:06 +03:00
const Header *req = nullptr);
2021-09-30 12:30:16 +03:00
/**
2021-10-06 12:29:06 +03:00
* @brief sendData This method send data object another to node
2021-09-30 12:30:16 +03:00
* @param resp This is pointer to sendet object.
* @param address This is target addres for sending.
* @param req This is header of request.
* @return hash of the sendet package. If function is failed then return 0.
*/
virtual unsigned int sendData(const PKG::AbstractData *resp, const AbstractNodeInfo *node,
2021-10-06 12:29:06 +03:00
const Header *req = nullptr);
2021-09-30 12:30:16 +03:00
2020-09-15 21:16:35 +03:00
/**
* @brief badRequest This method is send data about error of request.
* @param address This is addrees of receiver.
* @param req This is header of incomming request.
2020-10-29 20:23:50 +03:00
* @param err This is message and code of error. For more information see the ErrorData struct.
* @param diff This is difference of current trust (currenTrus += diff).
2020-10-26 14:21:33 +03:00
* By default diff equals REQUEST_ERROR
2020-09-15 21:16:35 +03:00
*/
virtual void badRequest(const HostAddress &address, const Header &req,
2020-12-08 17:51:30 +03:00
const PKG::ErrorData& err, qint8 diff = REQUEST_ERROR);
2020-09-15 21:16:35 +03:00
/**
* @brief getWorkStateString This method generate string about work state of server.
* @return string of work state.
2020-09-15 21:16:35 +03:00
*/
virtual QString getWorkStateString() const;
/**
* @brief connectionState This method return string value about the cocction state.
* @return string with count users state.
2020-09-15 21:16:35 +03:00
*/
virtual QString connectionState() const;
/**
* @brief banedList This method retrun list of banned clients of nodes.
* @return list of baned nodes.
2020-09-15 21:16:35 +03:00
*/
QList<HostAddress> banedList() const;
// TO-DO Need to add new method fo collect banned addresses for exmaple use the mask.
// See Task https://github.com/QuasarApp/Heart/issues/13
2020-09-15 21:16:35 +03:00
/**
* @brief isBanned This method checks if the node is banned.
* @param socket This is node info object for validation.
* @return true if node is banned.
2020-09-15 21:16:35 +03:00
*/
bool isBanned(QAbstractSocket* socket) const;
/**
* @brief incomingConnection This is ovverided method of QTCPServer.
* @param handle This is socket handle.
2020-09-15 21:16:35 +03:00
*/
void incomingConnection(qintptr handle) override final;
2020-09-15 21:16:35 +03:00
/**
* @brief changeTrust This method change trust of connected node.
* @param id This is id of select node.
* @param diff This is difference of current trust (currenTrus += diff).
* @return true if node trust is changed successful.
2020-09-15 21:16:35 +03:00
*/
virtual bool changeTrust(const HostAddress& id, int diff);
2021-10-31 22:03:57 +03:00
#ifdef USE_HEART_SSL
2020-09-15 21:16:35 +03:00
/**
* @brief useSelfSignedSslConfiguration This method reconfigure current node to use selfSigned certificate.
2021-03-09 16:10:26 +03:00
* @note Befor invoke this method stop this node (server) see AbstractNode::stop.
* if mode will be working then this method return false.
* The self signed certificate is temp value, this is will be changed after reboot node (server)
* @param crtData - This is data for generation a new self signed certification.
* @return result of change node ssl configuration.
*/
bool useSelfSignedSslConfiguration(const SslSrtData& crtData);
2020-09-15 21:16:35 +03:00
/**
* @brief useSystemSslConfiguration This method reconfigure current node to use sslConfig.
2021-03-09 16:10:26 +03:00
* @note Befor invoke this method stop this node (server) see AbstractNode::stop.
* if mode will be working then this method return false.
2021-11-01 22:58:05 +03:00
* @param config This is system ssl configuration. by default used QSslConfiguration::defaultConfiguration() method.
* @return result of change node ssl configuration.
2020-09-15 21:16:35 +03:00
*/
2021-11-01 22:58:05 +03:00
bool useSystemSslConfiguration(QSslConfiguration config = QSslConfiguration::defaultConfiguration());
/**
* @brief disableSSL This method disable ssl mode for this node.
2021-03-09 16:10:26 +03:00
* @note Befor invoke this method stop this node (server) see AbstractNode::stop.
* if mode will be working then this method return false.
* @return true if changes is completed.
*/
bool disableSSL();
#endif
2020-09-15 21:16:35 +03:00
/**
2021-03-09 16:10:26 +03:00
* @brief incomingData This method invoked when node get command or ansver.
* This method invoked befor parsing in the parsePackage method.
* @note use this method for handling received data, but do not change the @a pkg object.
* If You want change pkg object use the parsePackage method.
* @param pkg This is received package (in this implementation it is only the Ping command)
* @param sender This is information of sender of the package.
2020-09-15 21:16:35 +03:00
* @note override this method for get a signals.
2021-03-09 16:10:26 +03:00
* @note This method will be invoked in the own thread.
2020-09-15 21:16:35 +03:00
*/
2021-03-09 16:10:26 +03:00
virtual void incomingData(const PKG::AbstractData* pkg,
2021-02-09 21:17:52 +03:00
const AbstractNodeInfo* sender);
2020-09-15 21:16:35 +03:00
/**
* @brief connections - Return hash map of all connections of this node.
* @return return map of connections.
2020-09-15 21:16:35 +03:00
*/
2020-11-11 23:03:18 +03:00
QHash<HostAddress, AbstractNodeInfo *> connections() const;
2020-09-15 21:16:35 +03:00
/**
* @brief connectionRegistered Override this method for get registered incoming connections.
* @param info - Connection information.
2020-09-15 21:16:35 +03:00
*/
virtual void connectionRegistered(const AbstractNodeInfo *info);
/**
* @brief nodeConfirmend This method invocked when the node status changed to "confirmend"
* default implementatio do nothing.
* @param node This is address of changed node.
2020-09-15 21:16:35 +03:00
*/
virtual void nodeConfirmend(AbstractNodeInfo *node);
2020-09-15 21:16:35 +03:00
/**
* @brief nodeConnected This method invocked when the node status changed to "connected"
* default implementatio do nothing.
* @param node This is address of changed node.
2020-09-15 21:16:35 +03:00
*/
virtual void nodeConnected(AbstractNodeInfo *node);
2020-09-15 21:16:35 +03:00
/**
* @brief nodeConnected This method invocked when the node status changed to "disconnected"
* default implementatio do nothing.
* @param node This is address of changed node.
2020-09-15 21:16:35 +03:00
*/
virtual void nodeDisconnected(AbstractNodeInfo *node);
2021-02-22 19:58:07 +03:00
template<class T>
/**
* @brief registerPackageType This method register package type T.
* This is need to prepare pacakge for parsing in the parsePackage method.
*/
void registerPackageType() {
2021-10-06 12:29:06 +03:00
_registeredTypes[T::command()] = [](){
2021-02-22 19:58:07 +03:00
return new T();
};
};
void prepareForDelete() override;
2021-03-05 20:24:50 +03:00
/**
* @brief prepareData This is private method for preparing package from the byteArray.
* @param pkg This is a raw package value.
* @return pointer into prepared data.
* @warning The return value do not clear automatically.
2021-03-05 20:24:50 +03:00
*/
QSharedPointer<PKG::AbstractData> prepareData(const Package& pkg) const;
2021-10-01 22:54:49 +03:00
/**
* @brief genPackage This is factory method that generate data pacakge objects by command.
* All object should be registered before using this method.
* @param cmd This is command of pacakge see Header::command.
* @return shared pointer to new data object.
* @see AbstractNode::registerPackageType
* @see Header::command
*/
QSharedPointer<PKG::AbstractData> genPackage(unsigned short cmd) const ;
2021-03-10 17:21:26 +03:00
/**
* @brief checkCommand This method check command are if registered type or not.
* @brief cmd This is command of a verifiable package.
* @return True if the package is registered in a node.
*/
bool checkCommand(unsigned short cmd) const;
2021-04-30 22:41:34 +03:00
/**
* @brief connectionsList This method return list of all node connections
* @return list of node connections.
* @warning do not use this method for validation is connected.
*/
QList<HostAddress> connectionsList() const;
2021-10-08 16:02:50 +03:00
/**
* @brief activeConnectionsList This method return list of actived nodes connections
* @return list of actived nodes connections.
* @warning do not use this method for validation is connected.
*/
QList<HostAddress> activeConnectionsList() const;
2021-10-11 20:42:13 +03:00
2021-09-25 14:26:47 +03:00
/**
* @brief commandHandler This method it is simple wrapper for the handle pacakges in the AbstractNode::parsePackage method.
* Exmaple of use :
* @code{cpp}
2021-09-25 20:44:58 +03:00
* auto result = commandHandler<MyPackage>(this, &MyClass::processMyPackage, pkg, sender, pkgHeader);
2021-09-25 14:26:47 +03:00
if (result != QH::ParserResult::NotProcessed) {
return result;
}
...
* @endcode
* @tparam PackageClass This is class name that you want handle. All classes mist be inhert of the QH::PKG::AbstractData class.
2021-09-25 20:44:58 +03:00
* @tparam HandlerType This is type of the handler object that will invoke @a HandlerMethod method.
2021-09-25 14:26:47 +03:00
* @tparam HandlerMethod This is name of the handler method.
* The handler method should be support next signature:
* **bool Method(const QSharedPointer<QH::PKG::PackageClass> &, const QH::Header &pkgHeader, const QH::AbstractNodeInfo *sender)**.
2021-09-25 20:44:58 +03:00
* @param handlerObject This is pointer to handler object.
2021-09-25 14:26:47 +03:00
* @param method This is handler method.
* @param pkg This is package data from the AbstractNode::parsePackage argumetns
* @param pkgHeader This is header of an incomming package.
* @param sender This is socket object of a sender that send this package.
* @return item of ParserResult. For more information see The ParserResult enum.
*
* @see AbstractNode::parsePackage
* @see ParserResult
*/
2021-09-25 20:44:58 +03:00
template<class PackageClass,class HandlerType, class HandlerMethod>
2021-09-25 14:26:47 +03:00
2021-09-25 20:44:58 +03:00
inline ParserResult commandHandler(HandlerType handlerObject, HandlerMethod method,
2021-09-25 14:26:47 +03:00
const QSharedPointer<QH::PKG::AbstractData> &pkg,
const QH::AbstractNodeInfo *sender,
const QH::Header &pkgHeader) {
2021-10-06 12:29:06 +03:00
if (PackageClass::command() == pkg->cmd()) {
2021-09-25 14:26:47 +03:00
auto data = pkg.staticCast<PackageClass>();
if (!data->isValid()) {
return QH::ParserResult::Error;
}
2021-09-25 20:44:58 +03:00
if(!(handlerObject->*method)(data, sender, pkgHeader)) {
2021-09-25 14:26:47 +03:00
return QH::ParserResult::Error;
}
return QH::ParserResult::Processed;
}
2021-09-25 20:44:58 +03:00
return QH::ParserResult::NotProcessed;
2021-09-25 14:26:47 +03:00
}
protected slots:
/**
* @brief nodeErrorOccured This slot invoked when error ocured in the @a nodeInfo.
* @param nodeInfo This is pinter to modeInfoObject.
2021-05-14 14:48:34 +03:00
* @param errorCode This is error code.
* @param errorString This is string value of the error.
* @note default implementation do nothing. Override this method if you want to handle nodes network errors.
*/
virtual void nodeErrorOccured(AbstractNodeInfo *nodeInfo,
QAbstractSocket::SocketError errorCode,
QString errorString);
2020-09-15 21:16:35 +03:00
private slots:
2021-01-27 21:59:31 +03:00
void avelableBytes(AbstractNodeInfo* sender);
/**
* @brief handleNodeStatusChanged This method invoked when status of peer node chganged.
* @param node This is address of changed node.
* @param status This is new status of node.
*
*/
void handleNodeStatusChanged(AbstractNodeInfo* node, NodeCoonectionStatus status);
2020-09-15 21:16:35 +03:00
/**
* @brief handleWorkerStoped
*/
void handleWorkerStoped();
/**
* @brief handleForceRemoveNode - force remove connection.
* @param node
*/
void handleForceRemoveNode(HostAddress node);
2021-10-11 20:42:13 +03:00
/**
* @brief handleBeginWork This method run task on new thread.
* @param work This is new work task
*/
void handleBeginWork(QSharedPointer<QH::AbstractTask> work);
2021-11-01 22:58:05 +03:00
#ifdef USE_HEART_SSL
2021-10-31 22:03:57 +03:00
/**
2021-11-01 22:58:05 +03:00
* @brief handleSslErrorOcurred This method invoked when a ssl socket receive an error mesage.
* Default implementation just pront error messages
* @param errors This is errors list.
2021-10-31 22:03:57 +03:00
*/
2021-11-01 22:58:05 +03:00
void handleSslErrorOcurred(SslSocket *sender, const QList<QSslError> & errors);
2021-10-31 22:03:57 +03:00
/**
2021-11-01 22:58:05 +03:00
* @brief handleEncrypted invoke when a ssl socket is encripted!
2021-10-31 22:03:57 +03:00
*/
2021-11-01 22:58:05 +03:00
void handleEncrypted(AbstractNodeInfo *node);
#endif
2021-10-31 22:03:57 +03:00
2020-09-15 21:16:35 +03:00
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
*/
2021-01-27 21:59:31 +03:00
void newWork(const Package &pkg, AbstractNodeInfo *sender, const HostAddress &id);
2020-09-15 21:16:35 +03:00
/**
* @brief checkConfirmendOfNode - this method remove old not confirmed node.
* @param node - Node address.
2020-09-15 21:16:35 +03:00
*/
void checkConfirmendOfNode(AbstractNodeInfo *node);
2020-09-15 21:16:35 +03:00
2021-03-23 23:02:28 +03:00
/**
* @brief initThreadId This method save curent thread as a main thread.
*/
void initThreadId() const;
2021-03-25 16:17:26 +03:00
/**
* @brief initThreadPool This method initialize thread pool of the workers
*/
void initThreadPool();
/**
* @brief deinitThreadPool This method remove all workers threads
*/
void deinitThreadPool();
2021-10-31 22:03:57 +03:00
2020-09-21 16:50:31 +03:00
SslMode _mode = SslMode::NoSSL;
2021-10-31 22:03:57 +03:00
#ifdef USE_HEART_SSL
bool configureSslSocket(AbstractNodeInfo *node, bool fServer);
2020-09-15 21:16:35 +03:00
QSslConfiguration _ssl;
2021-11-01 22:58:05 +03:00
QList<QSslError> _ignoreSslErrors;
#endif
2020-09-15 21:16:35 +03:00
QHash<HostAddress, AbstractNodeInfo*> _connections;
QHash<HostAddress, ReceiveData*> _receiveData;
2020-09-15 21:16:35 +03:00
DataSender * _dataSender = nullptr;
AsyncLauncher * _socketWorker = nullptr;
QThread *_senderThread = nullptr;
2021-10-01 22:54:49 +03:00
BigDataManager *_bigdatamanager = nullptr;
2021-10-11 20:42:13 +03:00
TaskScheduler *_tasksheduller = nullptr;
2020-09-15 21:16:35 +03:00
QSet<QFutureWatcher <bool>*> _workers;
mutable QMutex _connectionsMutex;
mutable QMutex _confirmNodeMutex;
2021-03-24 10:39:04 +03:00
mutable QMutex _threadPoolMutex;
2020-09-15 21:16:35 +03:00
QThreadPool *_threadPool = nullptr;
2021-02-22 19:58:07 +03:00
QHash<unsigned short, std::function<PKG::AbstractData*()>> _registeredTypes;
2020-09-15 21:16:35 +03:00
friend class WebSocketController;
friend class SocketFactory;
2021-10-01 18:31:19 +03:00
friend class BigDataManager;
2020-09-15 21:16:35 +03:00
};
}
#endif // ABSTRACTNODE_H