UI: Straightforward RPC.

This commit is contained in:
Nodir Temirkhodjaev 2021-04-29 09:43:19 +03:00
parent 1c16d3b5d0
commit 21f302dbdf
11 changed files with 115 additions and 181 deletions

View File

@ -104,7 +104,6 @@ SOURCES += \
task/taskworker.cpp \ task/taskworker.cpp \
task/taskzonedownloader.cpp \ task/taskzonedownloader.cpp \
translationmanager.cpp \ translationmanager.cpp \
util/classutil.cpp \
util/conf/addressrange.cpp \ util/conf/addressrange.cpp \
util/conf/confutil.cpp \ util/conf/confutil.cpp \
util/dateutil.cpp \ util/dateutil.cpp \
@ -240,7 +239,6 @@ HEADERS += \
task/taskzonedownloader.h \ task/taskzonedownloader.h \
translationmanager.h \ translationmanager.h \
util/classhelpers.h \ util/classhelpers.h \
util/classutil.h \
util/conf/addressrange.h \ util/conf/addressrange.h \
util/conf/confappswalker.h \ util/conf/confappswalker.h \
util/conf/confutil.h \ util/conf/confutil.h \

View File

@ -5,16 +5,17 @@
namespace Control { namespace Control {
enum Command : qint8 { CommandNone = 0, CommandConf, CommandProg, CommandRpc }; enum Command : qint8 {
CommandNone = 0,
enum RpcObject : qint8 { Conf,
Rpc_None = 0, Prog,
Rpc_AppInfoManager, Rpc_AppInfoManager_lookupAppInfo,
Rpc_ConfManager, Rpc_AppInfoManager_checkLookupFinished,
Rpc_DriverManager, Rpc_ConfManager_,
Rpc_QuotaManager, Rpc_DriverManager_,
Rpc_StatManager, Rpc_QuotaManager_alert,
Rpc_TaskManager, Rpc_StatManager_,
Rpc_TaskManager_,
}; };
} }

View File

@ -64,9 +64,9 @@ bool ControlManager::postCommand()
{ {
Control::Command command; Control::Command command;
if (settings()->controlCommand() == "conf") { if (settings()->controlCommand() == "conf") {
command = Control::CommandConf; command = Control::Conf;
} else if (settings()->controlCommand() == "prog") { } else if (settings()->controlCommand() == "prog") {
command = Control::CommandProg; command = Control::Prog;
} else { } else {
logWarning() << "Unknown control command:" << settings()->controlCommand(); logWarning() << "Unknown control command:" << settings()->controlCommand();
return false; return false;
@ -91,7 +91,7 @@ bool ControlManager::postCommand()
if (args.isEmpty()) if (args.isEmpty())
return false; return false;
return worker.sendCommand(command, Control::Rpc_None, 0, args) && worker.waitForSent(); return worker.sendCommand(command, args) && worker.waitForSent();
} }
void ControlManager::onNewConnection() void ControlManager::onNewConnection()
@ -115,35 +115,31 @@ void ControlManager::onNewConnection()
} }
} }
bool ControlManager::processRequest(Control::Command command, Control::RpcObject rpcObj, bool ControlManager::processRequest(Control::Command command, const QVariantList &args)
qint16 methodIndex, const QVariantList &args)
{ {
QString errorMessage; QString errorMessage;
if (!processCommand(command, rpcObj, methodIndex, args, errorMessage)) { if (!processCommand(command, args, errorMessage)) {
logWarning() << "Bad control command" << errorMessage << ':' << command << args; logWarning() << "Bad control command" << errorMessage << ':' << command << args;
return false; return false;
} }
return true; return true;
} }
bool ControlManager::processCommand(Control::Command command, Control::RpcObject rpcObj, bool ControlManager::processCommand(
qint16 methodIndex, const QVariantList &args, QString &errorMessage) Control::Command command, const QVariantList &args, QString &errorMessage)
{ {
switch (command) { switch (command) {
case Control::CommandConf: case Control::Conf:
if (processCommandConf(args, errorMessage)) if (processCommandConf(args, errorMessage))
return true; return true;
break; break;
case Control::CommandProg: case Control::Prog:
if (processCommandProg(args, errorMessage)) if (processCommandProg(args, errorMessage))
return true; return true;
break; break;
case Control::CommandRpc:
if (rpcManager()->processCommandRpc(rpcObj, methodIndex, args, errorMessage))
return true;
break;
default: default:
errorMessage = "Unknown command"; if (rpcManager()->processCommandRpc(command, args, errorMessage))
return true;
} }
if (errorMessage.isEmpty()) { if (errorMessage.isEmpty()) {

View File

@ -36,17 +36,15 @@ public:
bool postCommand(); bool postCommand();
signals: signals:
void rpcRequestReady(Control::RpcObject rpcObj, qint16 methodIndex, const QVariantList &args); void rpcRequestReady(Control::Command command, const QVariantList &args);
private slots: private slots:
void onNewConnection(); void onNewConnection();
bool processRequest(Control::Command command, Control::RpcObject rpcObj, qint16 methodIndex, bool processRequest(Control::Command command, const QVariantList &args);
const QVariantList &args);
private: private:
bool processCommand(Control::Command command, Control::RpcObject rpcObj, qint16 methodIndex, bool processCommand(Control::Command command, const QVariantList &args, QString &errorMessage);
const QVariantList &args, QString &errorMessage);
bool processCommandConf(const QVariantList &args, QString &errorMessage); bool processCommandConf(const QVariantList &args, QString &errorMessage);
bool processCommandProg(const QVariantList &args, QString &errorMessage); bool processCommandProg(const QVariantList &args, QString &errorMessage);

View File

@ -76,14 +76,13 @@ void ControlWorker::abort()
socket()->close(); socket()->close();
} }
bool ControlWorker::sendCommand(Control::Command command, Control::RpcObject rpcObj, bool ControlWorker::sendCommand(Control::Command command, const QVariantList &args)
int methodIndex, const QVariantList &args)
{ {
QByteArray buffer; QByteArray buffer;
if (!buildArgsData(buffer, args)) if (!buildArgsData(buffer, args))
return false; return false;
RequestHeader request(command, rpcObj, methodIndex, buffer.size()); RequestHeader request(command, buffer.size());
socket()->write((const char *) &request, sizeof(RequestHeader)); socket()->write((const char *) &request, sizeof(RequestHeader));
@ -138,12 +137,10 @@ bool ControlWorker::readRequest()
return false; return false;
const Control::Command command = m_requestHeader.command(); const Control::Command command = m_requestHeader.command();
const Control::RpcObject rpcObj = m_requestHeader.rpcObj();
const qint16 methodIndex = m_requestHeader.methodIndex();
clearRequest(); clearRequest();
emit requestReady(command, rpcObj, methodIndex, args); emit requestReady(command, args);
return true; return true;
} }

View File

@ -22,16 +22,14 @@ public:
void setupForAsync(); void setupForAsync();
bool sendCommand(Control::Command command, Control::RpcObject rpcObj, int methodIndex, bool sendCommand(Control::Command command, const QVariantList &args);
const QVariantList &args);
bool waitForSent(int msecs = 1000) const; bool waitForSent(int msecs = 1000) const;
static QVariantList buildArgs(const QStringList &list); static QVariantList buildArgs(const QStringList &list);
signals: signals:
void requestReady(Control::Command command, Control::RpcObject rpcObj, qint16 methodIndex, void requestReady(Control::Command command, const QVariantList &args);
const QVariantList &args);
public slots: public slots:
void abort(); void abort();
@ -48,31 +46,23 @@ private:
private: private:
struct RequestHeader struct RequestHeader
{ {
RequestHeader(Control::Command command = Control::CommandNone, RequestHeader(Control::Command command = Control::CommandNone, quint32 dataSize = 0) :
Control::RpcObject rpcObj = Control::Rpc_None, qint16 methodIndex = 0, m_command(command), m_dataSize(dataSize)
quint32 dataSize = 0) :
m_command(command), m_rpcObj(rpcObj), m_methodIndex(methodIndex), m_dataSize(dataSize)
{ {
} }
Control::Command command() const { return m_command; } Control::Command command() const { return static_cast<Control::Command>(m_command); }
Control::RpcObject rpcObj() const { return m_rpcObj; }
qint16 methodIndex() const { return m_methodIndex; }
quint32 dataSize() const { return m_dataSize; } quint32 dataSize() const { return m_dataSize; }
void clear() void clear()
{ {
m_command = Control::CommandNone; m_command = Control::CommandNone;
m_rpcObj = Control::Rpc_None;
m_methodIndex = 0;
m_dataSize = 0; m_dataSize = 0;
} }
private: private:
Control::Command m_command; quint32 m_command : 8;
Control::RpcObject m_rpcObj; quint32 m_dataSize : 24;
qint16 m_methodIndex;
quint32 m_dataSize;
}; };
bool m_isServiceClient = false; bool m_isServiceClient = false;

View File

@ -4,7 +4,6 @@
#include "../fortmanager.h" #include "../fortmanager.h"
#include "../rpc/rpcmanager.h" #include "../rpc/rpcmanager.h"
#include "../util/classutil.h"
AppInfoManagerRpc::AppInfoManagerRpc( AppInfoManagerRpc::AppInfoManagerRpc(
const QString &filePath, FortManager *fortManager, QObject *parent) : const QString &filePath, FortManager *fortManager, QObject *parent) :
@ -19,8 +18,7 @@ RpcManager *AppInfoManagerRpc::rpcManager() const
void AppInfoManagerRpc::lookupAppInfo(const QString &appPath) void AppInfoManagerRpc::lookupAppInfo(const QString &appPath)
{ {
static const int methodIndex = ClassUtil::indexOfMethod(&AppInfoManager::lookupAppInfo); rpcManager()->invokeOnServer(Control::Rpc_AppInfoManager_lookupAppInfo, { appPath });
rpcManager()->invokeOnServer(Control::Rpc_AppInfoManager, methodIndex, { appPath });
} }
void AppInfoManagerRpc::updateAppAccessTime(const QString & /*appPath*/) { } void AppInfoManagerRpc::updateAppAccessTime(const QString & /*appPath*/) { }

View File

@ -10,7 +10,6 @@
#include "../rpc/quotamanagerrpc.h" #include "../rpc/quotamanagerrpc.h"
#include "../rpc/statmanagerrpc.h" #include "../rpc/statmanagerrpc.h"
#include "../rpc/taskmanagerrpc.h" #include "../rpc/taskmanagerrpc.h"
#include "../util/classutil.h"
RpcManager::RpcManager(FortManager *fortManager, QObject *parent) : RpcManager::RpcManager(FortManager *fortManager, QObject *parent) :
QObject(parent), m_fortManager(fortManager) QObject(parent), m_fortManager(fortManager)
@ -27,6 +26,36 @@ ControlManager *RpcManager::controlManager() const
return fortManager()->controlManager(); return fortManager()->controlManager();
} }
AppInfoManager *RpcManager::appInfoManager() const
{
return fortManager()->appInfoManager();
}
ConfManager *RpcManager::confManager() const
{
return fortManager()->confManager();
}
DriverManager *RpcManager::driverManager() const
{
return fortManager()->driverManager();
}
QuotaManager *RpcManager::quotaManager() const
{
return fortManager()->quotaManager();
}
StatManager *RpcManager::statManager() const
{
return fortManager()->statManager();
}
TaskManager *RpcManager::taskManager() const
{
return fortManager()->taskManager();
}
void RpcManager::initialize() void RpcManager::initialize()
{ {
if (settings()->isService()) { if (settings()->isService()) {
@ -34,18 +63,6 @@ void RpcManager::initialize()
} }
} }
bool RpcManager::processCommandRpc(
Control::RpcObject rpcObj, int methodIndex, const QVariantList &args, QString &errorMessage)
{
QObject *o = getRpcObject(rpcObj);
if (!o) {
errorMessage = "Bad RPC: No object";
return false;
}
return ClassUtil::invokeMethod(o, methodIndex, args);
}
void RpcManager::setupServerSignals() void RpcManager::setupServerSignals()
{ {
setupAppInfoManagerSignals(); setupAppInfoManagerSignals();
@ -54,62 +71,62 @@ void RpcManager::setupServerSignals()
void RpcManager::setupAppInfoManagerSignals() void RpcManager::setupAppInfoManagerSignals()
{ {
constexpr Control::RpcObject rpcObj = Control::Rpc_AppInfoManager; connect(appInfoManager(), &AppInfoManager::lookupFinished, this,
auto o = fortManager()->appInfoManager();
connect(o, &AppInfoManager::lookupFinished, this,
[&](const QString &appPath, const AppInfo & /*appInfo*/) { [&](const QString &appPath, const AppInfo & /*appInfo*/) {
static const int methodIndex = invokeOnClients(Control::Rpc_AppInfoManager_checkLookupFinished, { appPath });
ClassUtil::indexOfMethod(&AppInfoManager::checkLookupFinished);
invokeOnClients(rpcObj, methodIndex, { appPath });
}); });
} }
void RpcManager::setupQuotaManagerSignals() void RpcManager::setupQuotaManagerSignals()
{ {
constexpr Control::RpcObject rpcObj = Control::Rpc_QuotaManager; connect(quotaManager(), &QuotaManager::alert, this, [&](qint8 alertType) {
auto o = fortManager()->quotaManager(); invokeOnClients(Control::Rpc_QuotaManager_alert, { alertType });
connect(o, &QuotaManager::alert, this, [&](qint8 alertType) {
static const int methodIndex = ClassUtil::indexOfSignal(&QuotaManager::alert);
invokeOnClients(rpcObj, methodIndex, { alertType });
}); });
} }
void RpcManager::invokeOnServer( void RpcManager::invokeOnServer(Control::Command cmd, const QVariantList &args)
Control::RpcObject rpcObj, int methodIndex, const QVariantList &args)
{ {
m_client->sendCommand(Control::CommandRpc, rpcObj, methodIndex, args); m_client->sendCommand(cmd, args);
} }
void RpcManager::invokeOnClients( void RpcManager::invokeOnClients(Control::Command cmd, const QVariantList &args)
Control::RpcObject rpcObj, int methodIndex, const QVariantList &args)
{ {
const auto clients = controlManager()->clients(); const auto clients = controlManager()->clients();
for (ControlWorker *w : clients) { for (ControlWorker *w : clients) {
if (!w->isServiceClient()) if (!w->isServiceClient())
continue; continue;
w->sendCommand(Control::CommandRpc, rpcObj, methodIndex, args); w->sendCommand(cmd, args);
} }
} }
QObject *RpcManager::getRpcObject(Control::RpcObject rpcObj) const bool RpcManager::processCommandRpc(
Control::Command cmd, const QVariantList &args, QString &errorMessage)
{ {
switch (rpcObj) { switch (cmd) {
case Control::Rpc_AppInfoManager: case Control::Rpc_AppInfoManager_lookupAppInfo:
return fortManager()->appInfoManager(); appInfoManager()->lookupAppInfo(args.value(0).toString());
case Control::Rpc_ConfManager: return true;
return fortManager()->confManager(); case Control::Rpc_AppInfoManager_checkLookupFinished:
case Control::Rpc_DriverManager: appInfoManager()->checkLookupFinished(args.value(0).toString());
return fortManager()->driverManager(); return true;
case Control::Rpc_QuotaManager: case Control::Rpc_ConfManager_:
return fortManager()->quotaManager(); confManager();
case Control::Rpc_StatManager: return true;
return fortManager()->statManager(); case Control::Rpc_DriverManager_:
case Control::Rpc_TaskManager: driverManager();
return fortManager()->taskManager(); return true;
case Control::Rpc_QuotaManager_alert:
quotaManager();
return true;
case Control::Rpc_StatManager_:
statManager();
return true;
case Control::Rpc_TaskManager_:
taskManager();
return true;
default: default:
return nullptr; errorMessage = "Unknown command";
return false;
} }
} }

View File

@ -6,10 +6,16 @@
#include "../control/control.h" #include "../control/control.h"
class AppInfoManager;
class ConfManager;
class ControlManager; class ControlManager;
class ControlWorker; class ControlWorker;
class DriverManager;
class FortManager; class FortManager;
class FortSettings; class FortSettings;
class QuotaManager;
class StatManager;
class TaskManager;
class RpcManager : public QObject class RpcManager : public QObject
{ {
@ -21,22 +27,25 @@ public:
FortManager *fortManager() const { return m_fortManager; } FortManager *fortManager() const { return m_fortManager; }
FortSettings *settings() const; FortSettings *settings() const;
ControlManager *controlManager() const; ControlManager *controlManager() const;
AppInfoManager *appInfoManager() const;
ConfManager *confManager() const;
DriverManager *driverManager() const;
QuotaManager *quotaManager() const;
StatManager *statManager() const;
TaskManager *taskManager() const;
void initialize(); void initialize();
bool processCommandRpc(Control::RpcObject rpcObj, int methodIndex, const QVariantList &args, void invokeOnServer(Control::Command cmd, const QVariantList &args);
QString &errorMessage);
void invokeOnServer(Control::RpcObject rpcObj, int methodIndex, const QVariantList &args); bool processCommandRpc(Control::Command cmd, const QVariantList &args, QString &errorMessage);
private: private:
void setupServerSignals(); void setupServerSignals();
void setupAppInfoManagerSignals(); void setupAppInfoManagerSignals();
void setupQuotaManagerSignals(); void setupQuotaManagerSignals();
void invokeOnClients(Control::RpcObject rpcObj, int methodIndex, const QVariantList &args); void invokeOnClients(Control::Command cmd, const QVariantList &args);
QObject *getRpcObject(Control::RpcObject rpcObj) const;
private: private:
FortManager *m_fortManager = nullptr; FortManager *m_fortManager = nullptr;

View File

@ -1,38 +0,0 @@
#include "classutil.h"
bool ClassUtil::invokeMethod(
QObject *object, int methodIndex, const QVariantList &args, QVariant *result)
{
const QMetaMethod metaMethod = object->metaObject()->method(methodIndex);
constexpr int maxArgsCount = 5;
Q_ASSERT(metaMethod.parameterTypes().size() == args.size() && args.size() <= maxArgsCount);
QVector<QGenericArgument> arguments(maxArgsCount);
for (const auto &arg : args) {
void *data = const_cast<void *>(arg.constData()); // data() detaches it
arguments.append(QGenericArgument(arg.typeName(), data));
}
QVariant returnValue(metaMethod.returnMetaType(), nullptr);
QGenericReturnArgument returnArgument(
metaMethod.typeName(), const_cast<void *>(returnValue.constData()));
if (!metaMethod.invoke(object, Qt::DirectConnection, returnArgument, arguments.value(0),
arguments.value(1), arguments.value(2), arguments.value(3), arguments.value(4)))
return false;
if (result) {
*result = returnValue;
}
return true;
}
int ClassUtil::getIndexOfMethod(const QMetaObject &metaObject, void **method)
{
int i = -1;
void *args[] = { &i, method };
metaObject.static_metacall(QMetaObject::IndexOfMethod, 0, args);
return i;
}

View File

@ -1,32 +0,0 @@
#ifndef CLASSUTIL_H
#define CLASSUTIL_H
#include <QMetaMethod>
#include <QVariant>
class ClassUtil
{
public:
static bool invokeMethod(QObject *object, int methodIndex, const QVariantList &args = {},
QVariant *result = nullptr);
template<typename PointerToMemberFunction>
static int indexOfSignal(PointerToMemberFunction signal)
{
const QMetaMethod method = QMetaMethod::fromSignal(signal);
return method.methodIndex();
}
template<typename PointerToMemberFunction>
static int indexOfMethod(PointerToMemberFunction method)
{
using MemberFunctionType = QtPrivate::FunctionPointer<PointerToMemberFunction>;
return getIndexOfMethod(
MemberFunctionType::Object::staticMetaObject, reinterpret_cast<void **>(&method));
}
private:
static int getIndexOfMethod(const QMetaObject &metaObject, void **method);
};
#endif // CLASSUTIL_H