mirror of
https://github.com/tnodir/fort
synced 2024-11-15 10:35:10 +00:00
UI: Prepare RPC.
This commit is contained in:
parent
ed750dc6ee
commit
5bda1022e8
@ -116,6 +116,7 @@ SOURCES += \
|
||||
util/json/jsonutil.cpp \
|
||||
util/json/mapwrapper.cpp \
|
||||
util/logger.cpp \
|
||||
util/metaclassutil.cpp \
|
||||
util/model/stringlistmodel.cpp \
|
||||
util/model/tableitemmodel.cpp \
|
||||
util/model/tablesqlmodel.cpp \
|
||||
@ -238,6 +239,7 @@ HEADERS += \
|
||||
task/taskworker.h \
|
||||
task/taskzonedownloader.h \
|
||||
translationmanager.h \
|
||||
util/classhelpers.h \
|
||||
util/conf/addressrange.h \
|
||||
util/conf/confappswalker.h \
|
||||
util/conf/confutil.h \
|
||||
@ -251,6 +253,7 @@ HEADERS += \
|
||||
util/json/jsonutil.h \
|
||||
util/json/mapwrapper.h \
|
||||
util/logger.h \
|
||||
util/metaclassutil.h \
|
||||
util/model/stringlistmodel.h \
|
||||
util/model/tableitemmodel.h \
|
||||
util/model/tablesqlmodel.h \
|
||||
|
@ -5,10 +5,16 @@
|
||||
|
||||
namespace Control {
|
||||
|
||||
enum Command : qint8 {
|
||||
CommandNone = 0,
|
||||
CommandConf,
|
||||
CommandProg,
|
||||
enum Command : qint8 { CommandNone = 0, CommandConf, CommandProg, CommandRpc };
|
||||
|
||||
enum RpcObject : qint8 {
|
||||
Rpc_None = 0,
|
||||
Rpc_AppInfoManager,
|
||||
Rpc_ConfManager,
|
||||
Rpc_DriverManager,
|
||||
Rpc_QuotaManager,
|
||||
Rpc_StatManager,
|
||||
Rpc_TaskManager,
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -85,7 +85,7 @@ bool ControlManager::postCommand()
|
||||
if (args.isEmpty())
|
||||
return false;
|
||||
|
||||
return worker.postCommand(command, args);
|
||||
return worker.sendCommand(command, Control::Rpc_None, 0, args) && worker.waitForSent();
|
||||
}
|
||||
|
||||
void ControlManager::onNewConnection()
|
||||
|
@ -9,20 +9,57 @@ constexpr int commandMaxArgs = 7;
|
||||
constexpr int commandArgMaxSize = 4 * 1024;
|
||||
constexpr int dataMaxSize = 4 * 1024 * 1024;
|
||||
|
||||
struct DataHeader
|
||||
template<typename T>
|
||||
T *bufferAs(QByteArray &buffer, int offset = 0)
|
||||
{
|
||||
DataHeader(Control::Command command = Control::CommandNone, int dataSize = 0) :
|
||||
m_command(command), m_dataSize(dataSize)
|
||||
{
|
||||
return reinterpret_cast<T *>(buffer.data() + offset);
|
||||
}
|
||||
|
||||
bool buildArgsData(QByteArray &data, const QVariantList &args)
|
||||
{
|
||||
const int argsCount = args.count();
|
||||
if (argsCount == 0)
|
||||
return true;
|
||||
|
||||
if (argsCount > commandMaxArgs)
|
||||
return false;
|
||||
|
||||
QDataStream stream(&data,
|
||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
||||
QIODevice::WriteOnly
|
||||
#else
|
||||
QDataStream::WriteOnly
|
||||
#endif
|
||||
);
|
||||
|
||||
stream << qint8(argsCount);
|
||||
|
||||
for (const auto &arg : args) {
|
||||
stream << arg;
|
||||
}
|
||||
|
||||
Control::Command command() const { return static_cast<Control::Command>(m_command); }
|
||||
int dataSize() const { return m_dataSize; }
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
quint32 m_command : 8;
|
||||
quint32 m_dataSize : 24;
|
||||
};
|
||||
bool parseArgsData(const QByteArray &data, QVariantList &args)
|
||||
{
|
||||
QDataStream stream(data);
|
||||
|
||||
qint8 argsCount;
|
||||
stream >> argsCount;
|
||||
|
||||
if (argsCount > commandMaxArgs)
|
||||
return false;
|
||||
|
||||
while (--argsCount >= 0) {
|
||||
QVariant arg;
|
||||
stream >> arg;
|
||||
|
||||
args.append(arg);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -45,16 +82,25 @@ void ControlWorker::abort()
|
||||
socket()->close();
|
||||
}
|
||||
|
||||
bool ControlWorker::postCommand(Control::Command command, const QVariantList &args)
|
||||
bool ControlWorker::sendCommand(Control::Command command, Control::RpcObject rpcObj,
|
||||
int methodIndex, const QVariantList &args)
|
||||
{
|
||||
QByteArray data;
|
||||
if (!buildArgsData(data, args))
|
||||
QByteArray buffer;
|
||||
|
||||
if (!buildArgsData(buffer, args))
|
||||
return false;
|
||||
|
||||
writeDataHeader(command, data.size());
|
||||
writeData(data);
|
||||
new (bufferAs<DataHeader>(buffer))
|
||||
DataHeader(command, rpcObj, methodIndex, buffer.size() - sizeof(DataHeader));
|
||||
|
||||
return socket()->waitForBytesWritten(1000);
|
||||
socket()->write(buffer);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ControlWorker::waitForSent(int msecs) const
|
||||
{
|
||||
return socket()->waitForBytesWritten(msecs);
|
||||
}
|
||||
|
||||
void ControlWorker::processRequest()
|
||||
@ -67,29 +113,26 @@ void ControlWorker::processRequest()
|
||||
|
||||
void ControlWorker::clearRequest()
|
||||
{
|
||||
m_requestCommand = Control::CommandNone;
|
||||
m_requestDataSize = 0;
|
||||
m_request.clear();
|
||||
m_requestData.clear();
|
||||
}
|
||||
|
||||
bool ControlWorker::readRequest()
|
||||
{
|
||||
if (m_requestCommand == Control::CommandNone
|
||||
&& !readDataHeader(m_requestCommand, m_requestDataSize))
|
||||
if (m_request.command() == Control::CommandNone && !readRequestHeader())
|
||||
return false;
|
||||
|
||||
if (m_requestDataSize > 0) {
|
||||
if (m_request.dataSize() > 0) {
|
||||
if (socket()->bytesAvailable() == 0)
|
||||
return true; // need more data
|
||||
|
||||
const QByteArray data = readData(m_requestDataSize);
|
||||
const QByteArray data = socket()->read(m_request.dataSize() - m_requestData.size());
|
||||
if (data.isEmpty())
|
||||
return false;
|
||||
|
||||
m_requestData += data;
|
||||
m_requestDataSize -= data.size();
|
||||
|
||||
if (m_requestDataSize > 0)
|
||||
if (m_requestData.size() < m_request.dataSize())
|
||||
return true; // need more data
|
||||
}
|
||||
|
||||
@ -97,85 +140,23 @@ bool ControlWorker::readRequest()
|
||||
if (!m_requestData.isEmpty() && !parseArgsData(m_requestData, args))
|
||||
return false;
|
||||
|
||||
emit requestReady(m_requestCommand, args);
|
||||
emit requestReady(m_request.command(), args);
|
||||
clearRequest();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ControlWorker::writeDataHeader(Control::Command command, int dataSize)
|
||||
bool ControlWorker::readRequestHeader()
|
||||
{
|
||||
DataHeader dataHeader(command, dataSize);
|
||||
socket()->write((const char *) &dataHeader, sizeof(DataHeader));
|
||||
}
|
||||
|
||||
bool ControlWorker::readDataHeader(Control::Command &command, int &dataSize)
|
||||
{
|
||||
DataHeader dataHeader;
|
||||
if (socket()->read((char *) &dataHeader, sizeof(DataHeader)) != sizeof(DataHeader))
|
||||
if (socket()->read((char *) &m_request, sizeof(DataHeader)) != sizeof(DataHeader))
|
||||
return false;
|
||||
|
||||
command = dataHeader.command();
|
||||
dataSize = dataHeader.dataSize();
|
||||
|
||||
if (dataSize > dataMaxSize)
|
||||
if (m_request.dataSize() > dataMaxSize)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ControlWorker::writeData(const QByteArray &data)
|
||||
{
|
||||
socket()->write(data);
|
||||
}
|
||||
|
||||
QByteArray ControlWorker::readData(int dataSize)
|
||||
{
|
||||
return socket()->read(dataSize);
|
||||
}
|
||||
|
||||
bool ControlWorker::buildArgsData(QByteArray &data, const QVariantList &args)
|
||||
{
|
||||
QDataStream stream(&data,
|
||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
||||
QIODevice::WriteOnly
|
||||
#else
|
||||
QDataStream::WriteOnly
|
||||
#endif
|
||||
);
|
||||
|
||||
const int argsCount = args.count();
|
||||
if (argsCount > commandMaxArgs)
|
||||
return false;
|
||||
|
||||
stream << qint8(argsCount);
|
||||
|
||||
for (const auto &arg : args) {
|
||||
stream << arg;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ControlWorker::parseArgsData(const QByteArray &data, QVariantList &args)
|
||||
{
|
||||
QDataStream stream(data);
|
||||
|
||||
qint8 argsCount;
|
||||
stream >> argsCount;
|
||||
if (argsCount > commandMaxArgs)
|
||||
return false;
|
||||
|
||||
while (--argsCount >= 0) {
|
||||
QVariant arg;
|
||||
stream >> arg;
|
||||
|
||||
args.append(arg);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QVariantList ControlWorker::buildArgs(const QStringList &list)
|
||||
{
|
||||
QVariantList args;
|
||||
|
@ -22,7 +22,10 @@ public:
|
||||
|
||||
void setupForAsync();
|
||||
|
||||
bool postCommand(Control::Command command, const QVariantList &args);
|
||||
bool sendCommand(Control::Command command, Control::RpcObject rpcObj, int methodIndex,
|
||||
const QVariantList &args);
|
||||
|
||||
bool waitForSent(int msecs = 1000) const;
|
||||
|
||||
static QVariantList buildArgs(const QStringList &list);
|
||||
|
||||
@ -39,20 +42,41 @@ private:
|
||||
void clearRequest();
|
||||
bool readRequest();
|
||||
|
||||
void writeDataHeader(Control::Command command, int dataSize);
|
||||
bool readDataHeader(Control::Command &command, int &dataSize);
|
||||
|
||||
void writeData(const QByteArray &data);
|
||||
QByteArray readData(int dataSize);
|
||||
|
||||
static bool buildArgsData(QByteArray &data, const QVariantList &args);
|
||||
static bool parseArgsData(const QByteArray &data, QVariantList &args);
|
||||
bool readRequestHeader();
|
||||
|
||||
private:
|
||||
struct DataHeader
|
||||
{
|
||||
DataHeader(Control::Command command = Control::CommandNone,
|
||||
Control::RpcObject rpcObj = Control::Rpc_None, qint16 methodIndex = 0,
|
||||
qint32 dataSize = 0) :
|
||||
m_command(command), m_rpcObj(rpcObj), m_methodIndex(methodIndex), m_dataSize(dataSize)
|
||||
{
|
||||
}
|
||||
|
||||
Control::Command command() const { return m_command; }
|
||||
Control::RpcObject rpcObj() const { return m_rpcObj; }
|
||||
qint16 methodIndex() const { return m_methodIndex; }
|
||||
qint32 dataSize() const { return m_dataSize; }
|
||||
|
||||
void clear()
|
||||
{
|
||||
m_command = Control::CommandNone;
|
||||
m_rpcObj = Control::Rpc_None;
|
||||
m_methodIndex = 0;
|
||||
m_dataSize = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
Control::Command m_command;
|
||||
Control::RpcObject m_rpcObj;
|
||||
qint16 m_methodIndex;
|
||||
quint32 m_dataSize;
|
||||
};
|
||||
|
||||
bool m_isServiceClient = false;
|
||||
|
||||
Control::Command m_requestCommand = Control::CommandNone;
|
||||
int m_requestDataSize = 0;
|
||||
DataHeader m_request;
|
||||
QByteArray m_requestData;
|
||||
|
||||
QLocalSocket *m_socket = nullptr;
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
#include "../fortmanager.h"
|
||||
#include "../rpc/rpcmanager.h"
|
||||
#include "../util/metaclassutil.h"
|
||||
|
||||
AppInfoManagerRpc::AppInfoManagerRpc(
|
||||
const QString &filePath, FortManager *fortManager, QObject *parent) :
|
||||
@ -18,7 +19,8 @@ RpcManager *AppInfoManagerRpc::rpcManager() const
|
||||
|
||||
void AppInfoManagerRpc::lookupAppInfo(const QString &appPath)
|
||||
{
|
||||
rpcManager()->invokeOnServer(RpcManager::Obj_AppInfoManager, "lookupAppInfo", { appPath });
|
||||
static const int methodIndex = MetaClassUtil::indexOfMethod(&AppInfoManager::lookupAppInfo);
|
||||
rpcManager()->invokeOnServer(Control::Rpc_AppInfoManager, methodIndex, { appPath });
|
||||
}
|
||||
|
||||
void AppInfoManagerRpc::updateAppAccessTime(const QString & /*appPath*/) { }
|
||||
|
@ -5,7 +5,12 @@
|
||||
#include "../fortmanager.h"
|
||||
#include "../fortsettings.h"
|
||||
#include "../rpc/appinfomanagerrpc.h"
|
||||
#include "../rpc/confmanagerrpc.h"
|
||||
#include "../rpc/drivermanagerrpc.h"
|
||||
#include "../rpc/quotamanagerrpc.h"
|
||||
#include "../rpc/statmanagerrpc.h"
|
||||
#include "../rpc/taskmanagerrpc.h"
|
||||
#include "../util/metaclassutil.h"
|
||||
|
||||
RpcManager::RpcManager(FortManager *fortManager, QObject *parent) :
|
||||
QObject(parent), m_fortManager(fortManager)
|
||||
@ -39,36 +44,63 @@ void RpcManager::setupServerSignals()
|
||||
|
||||
void RpcManager::setupAppInfoManagerSignals()
|
||||
{
|
||||
constexpr qint8 rpcObj = Obj_AppInfoManager;
|
||||
constexpr Control::RpcObject rpcObj = Control::Rpc_AppInfoManager;
|
||||
auto o = fortManager()->appInfoManager();
|
||||
|
||||
connect(o, &AppInfoManager::lookupFinished, this,
|
||||
[&](const QString &appPath, const AppInfo & /*appInfo*/) {
|
||||
invokeOnClients(rpcObj, "checkLookupFinished", { appPath });
|
||||
static const int methodIndex =
|
||||
MetaClassUtil::indexOfMethod(&AppInfoManager::checkLookupFinished);
|
||||
invokeOnClients(rpcObj, methodIndex, { appPath });
|
||||
});
|
||||
}
|
||||
|
||||
void RpcManager::setupQuotaManagerSignals()
|
||||
{
|
||||
constexpr qint8 rpcObj = Obj_QuotaManager;
|
||||
constexpr Control::RpcObject rpcObj = Control::Rpc_QuotaManager;
|
||||
auto o = fortManager()->quotaManager();
|
||||
|
||||
connect(o, &QuotaManager::alert, this,
|
||||
[&](qint8 alertType) { invokeOnClients(rpcObj, "alert", { alertType }); });
|
||||
connect(o, &QuotaManager::alert, this, [&](qint8 alertType) {
|
||||
static const int methodIndex = MetaClassUtil::indexOfSignal(&QuotaManager::alert);
|
||||
invokeOnClients(rpcObj, methodIndex, { alertType });
|
||||
});
|
||||
}
|
||||
|
||||
void RpcManager::invokeOnServer(qint8 rpcObj, const char *member, const QVariantList &args)
|
||||
void RpcManager::invokeOnServer(
|
||||
Control::RpcObject rpcObj, int methodIndex, const QVariantList &args)
|
||||
{
|
||||
// TODO: Send RPC to Server
|
||||
m_client->sendCommand(Control::CommandRpc, rpcObj, methodIndex, args);
|
||||
}
|
||||
|
||||
void RpcManager::invokeOnClients(qint8 rpcObj, const char *member, const QVariantList &args)
|
||||
void RpcManager::invokeOnClients(
|
||||
Control::RpcObject rpcObj, int methodIndex, const QVariantList &args)
|
||||
{
|
||||
const auto clients = controlManager()->clients();
|
||||
for (ControlWorker *w : clients) {
|
||||
if (!w->isServiceClient())
|
||||
continue;
|
||||
|
||||
// TODO: Send RPC to Client
|
||||
w->sendCommand(Control::CommandRpc, rpcObj, methodIndex, args);
|
||||
}
|
||||
}
|
||||
|
||||
QObject *RpcManager::getRpcObject(Control::RpcObject rpcObj) const
|
||||
{
|
||||
switch (rpcObj) {
|
||||
case Control::Rpc_AppInfoManager:
|
||||
return fortManager()->appInfoManager();
|
||||
case Control::Rpc_ConfManager:
|
||||
return fortManager()->confManager();
|
||||
case Control::Rpc_DriverManager:
|
||||
return fortManager()->driverManager();
|
||||
case Control::Rpc_QuotaManager:
|
||||
return fortManager()->quotaManager();
|
||||
case Control::Rpc_StatManager:
|
||||
return fortManager()->statManager();
|
||||
case Control::Rpc_TaskManager:
|
||||
return fortManager()->taskManager();
|
||||
default:
|
||||
Q_UNREACHABLE();
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,10 @@
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include "../control/control.h"
|
||||
|
||||
class ControlManager;
|
||||
class ControlWorker;
|
||||
class FortManager;
|
||||
class FortSettings;
|
||||
|
||||
@ -12,15 +15,6 @@ class RpcManager : public QObject
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum RpcObject : qint8 {
|
||||
Obj_AppInfoManager = 1,
|
||||
Obj_ConfManager,
|
||||
Obj_DriverManager,
|
||||
Obj_QuotaManager,
|
||||
Obj_StatManager,
|
||||
Obj_TaskManager,
|
||||
};
|
||||
|
||||
explicit RpcManager(FortManager *fortManager, QObject *parent = nullptr);
|
||||
|
||||
FortManager *fortManager() const { return m_fortManager; }
|
||||
@ -29,17 +23,21 @@ public:
|
||||
|
||||
void initialize();
|
||||
|
||||
void invokeOnServer(qint8 rpcObj, const char *member, const QVariantList &args);
|
||||
void invokeOnServer(Control::RpcObject rpcObj, int methodIndex, const QVariantList &args);
|
||||
|
||||
private:
|
||||
void setupServerSignals();
|
||||
void setupAppInfoManagerSignals();
|
||||
void setupQuotaManagerSignals();
|
||||
|
||||
void invokeOnClients(qint8 rpcObj, const char *member, const QVariantList &args);
|
||||
void invokeOnClients(Control::RpcObject rpcObj, int methodIndex, const QVariantList &args);
|
||||
|
||||
QObject *getRpcObject(Control::RpcObject rpcObj) const;
|
||||
|
||||
private:
|
||||
FortManager *m_fortManager = nullptr;
|
||||
|
||||
ControlWorker *m_client = nullptr;
|
||||
};
|
||||
|
||||
#endif // RPCMANAGER_H
|
||||
|
9
src/ui/util/metaclassutil.cpp
Normal file
9
src/ui/util/metaclassutil.cpp
Normal file
@ -0,0 +1,9 @@
|
||||
#include "metaclassutil.h"
|
||||
|
||||
int MetaClassUtil::getIndexOfMethod(const QMetaObject &metaObj, void **method)
|
||||
{
|
||||
int methodIndex = -1;
|
||||
void *metaArgs[] = { &methodIndex, reinterpret_cast<void **>(&method) };
|
||||
metaObj.static_metacall(QMetaObject::IndexOfMethod, 0, metaArgs);
|
||||
return methodIndex;
|
||||
}
|
28
src/ui/util/metaclassutil.h
Normal file
28
src/ui/util/metaclassutil.h
Normal file
@ -0,0 +1,28 @@
|
||||
#ifndef METACLASSUTIL_H
|
||||
#define METACLASSUTIL_H
|
||||
|
||||
#include <QMetaMethod>
|
||||
|
||||
class MetaClassUtil
|
||||
{
|
||||
public:
|
||||
template<typename Func>
|
||||
static int indexOfSignal(Func signal)
|
||||
{
|
||||
const QMetaMethod method = QMetaMethod::fromSignal(signal);
|
||||
return method.methodIndex();
|
||||
}
|
||||
|
||||
template<typename Func>
|
||||
static int indexOfMethod(Func method)
|
||||
{
|
||||
using FuncType = QtPrivate::FunctionPointer<Func>;
|
||||
return getIndexOfMethod(
|
||||
FuncType::Object::staticMetaObject, reinterpret_cast<void **>(&method));
|
||||
}
|
||||
|
||||
private:
|
||||
static int getIndexOfMethod(const QMetaObject &metaObj, void **method);
|
||||
};
|
||||
|
||||
#endif // METACLASSUTIL_H
|
Loading…
Reference in New Issue
Block a user