mirror of
https://github.com/QuasarApp/Patronum.git
synced 2025-04-26 15:44:32 +00:00
267 lines
6.7 KiB
C++
267 lines
6.7 KiB
C++
/*
|
|
* Copyright (C) 2018-2024 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 "pcommon.h"
|
|
#include "serviceprivate.h"
|
|
#include "installersystemd.h"
|
|
|
|
#include "IPService.h"
|
|
#include "localsocket.h"
|
|
#include "package.h"
|
|
#include <QCoreApplication>
|
|
#include <QFile>
|
|
#include <QProcess>
|
|
#include <QTimer>
|
|
#include <quasarapp.h>
|
|
#include "parser.h"
|
|
#include <csignal>
|
|
|
|
void handleTermSignals(int sig) {
|
|
QuasarAppUtils::Params::log(QString("Shutdown application with %0 signal.").arg(sig),
|
|
QuasarAppUtils::Info);
|
|
QCoreApplication::exit(0);
|
|
}
|
|
|
|
namespace Patronum {
|
|
|
|
Patronum::ServicePrivate::ServicePrivate(IService *service, QObject *parent):
|
|
QObject(parent) {
|
|
QString name = PCommon::instance()->getServiceName();
|
|
|
|
_socket = new LocalSocket(name, this);
|
|
|
|
_service = service;
|
|
|
|
#ifdef Q_OS_LINUX
|
|
_installer = new InstallerSystemD();
|
|
#endif
|
|
|
|
_parser = new Parser();
|
|
QObject::connect(_socket, &LocalSocket::sigReceve,
|
|
this, &ServicePrivate::handleReceve);
|
|
|
|
signal(SIGINT, &handleTermSignals);
|
|
signal(SIGTERM, &handleTermSignals);
|
|
|
|
}
|
|
|
|
ServicePrivate::~ServicePrivate() {
|
|
delete _parser;
|
|
delete _socket;
|
|
|
|
if (_installer) {
|
|
delete _installer;
|
|
}
|
|
}
|
|
|
|
bool ServicePrivate::sendCmdResult(const QVariantMap &result) {
|
|
|
|
if (!_socket->isValid()) {
|
|
QuasarAppUtils::Params::log("scoket is closed!",
|
|
QuasarAppUtils::Error);
|
|
return false;
|
|
}
|
|
|
|
return _socket->send(_parser->createPackage(Command::FeatureResponce, result));
|
|
}
|
|
|
|
bool ServicePrivate::sendCloseConnection() {
|
|
if (!_socket->isValid()) {
|
|
QuasarAppUtils::Params::log("scoket is closed!",
|
|
QuasarAppUtils::Error);
|
|
return false;
|
|
}
|
|
|
|
return _socket->send(_parser->createPackage(Command::CloseConnection));
|
|
}
|
|
|
|
bool ServicePrivate::install(const QString &user) {
|
|
|
|
if (!_installer) {
|
|
QuasarAppUtils::Params::log(errorToString(UnsupportedPlatform),
|
|
QuasarAppUtils::Error);
|
|
return false;
|
|
}
|
|
|
|
if (!_installer->install(getServiceLauncher(), user)) {
|
|
return false;
|
|
}
|
|
|
|
QuasarAppUtils::Params::log("The service installed successful", QuasarAppUtils::Info);
|
|
return true;
|
|
}
|
|
|
|
bool ServicePrivate::uninstall() {
|
|
if (!_installer) {
|
|
QuasarAppUtils::Params::log(errorToString(UnsupportedPlatform),
|
|
QuasarAppUtils::Error);
|
|
return false;
|
|
}
|
|
|
|
if (!_installer->uninstall()) {
|
|
return false;
|
|
}
|
|
|
|
QuasarAppUtils::Params::log("The service uninstalled successful", QuasarAppUtils::Info);
|
|
return true;
|
|
}
|
|
|
|
bool ServicePrivate::start() {
|
|
|
|
if (!_socket->listen()) {
|
|
QuasarAppUtils::Params::log("Fail to create a terminal socket!",
|
|
QuasarAppUtils::Error);
|
|
return false;
|
|
};
|
|
|
|
return _service->onStart();
|
|
}
|
|
|
|
bool ServicePrivate::startDeamon() {
|
|
|
|
if (_socket->isRunning()) {
|
|
QuasarAppUtils::Params::log("Failed to start a service because an another service alredy started",
|
|
QuasarAppUtils::Error);
|
|
return false;
|
|
}
|
|
|
|
QProcess proc;
|
|
proc.setProgram(QuasarAppUtils::Params::getCurrentExecutable());
|
|
|
|
proc.setArguments({"start"});
|
|
proc.setProcessEnvironment(QProcessEnvironment::systemEnvironment());
|
|
proc.setProcessChannelMode(QProcess::SeparateChannels);
|
|
|
|
qint64 pid;
|
|
if (!proc.startDetached(&pid)) {
|
|
QuasarAppUtils::Params::log("fail to start detached process: " + proc.errorString(),
|
|
QuasarAppUtils::Error);
|
|
return false;
|
|
}
|
|
|
|
QFile pidFile(PCommon::instance()->getPidfile());
|
|
if (!pidFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
|
|
return false;
|
|
}
|
|
|
|
pidFile.write(QByteArray::number(pid));
|
|
pidFile.close();
|
|
|
|
QuasarAppUtils::Params::log("The service started successful", QuasarAppUtils::Info);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool ServicePrivate::handleStandartCmd(QHash<QString, Feature> *cmds) {
|
|
|
|
if (!cmds)
|
|
return false;
|
|
|
|
if (!_service)
|
|
return false;
|
|
|
|
if (cmds->contains("stop")) {
|
|
_service->onStop();
|
|
cmds->remove("stop");
|
|
|
|
} else if (cmds->contains("pause")) {
|
|
_service->onPause();
|
|
cmds->remove("pause");
|
|
|
|
} else if (cmds->contains("resume")) {
|
|
_service->onResume();
|
|
cmds->remove("resume");
|
|
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
QString ServicePrivate::getServiceLauncher() const {
|
|
const QByteArray P_RUN_FILE = qgetenv("P_RUN_FILE");
|
|
if (P_RUN_FILE.size()) {
|
|
return P_RUN_FILE;
|
|
}
|
|
|
|
const QByteArray CQT_RUN_FILE = qgetenv("CQT_RUN_FILE");
|
|
if (CQT_RUN_FILE.size()) {
|
|
return CQT_RUN_FILE;
|
|
}
|
|
|
|
return QuasarAppUtils::Params::getCurrentExecutable();
|
|
}
|
|
|
|
void ServicePrivate::handleReceve(QByteArray data) {
|
|
|
|
QList<Package> packages;
|
|
if (!_parser->parse(data, packages)) {
|
|
return;
|
|
}
|
|
|
|
for (const auto &pkg: std::as_const(packages)) {
|
|
if (!pkg.isValid()) {
|
|
QuasarAppUtils::Params::log("receive package is not valid!",
|
|
QuasarAppUtils::Warning);
|
|
return;
|
|
}
|
|
|
|
if (!_service) {
|
|
QuasarAppUtils::Params::log("System error, service is not inited!",
|
|
QuasarAppUtils::Error);
|
|
return;;
|
|
}
|
|
|
|
if (!_socket->isValid()) {
|
|
QuasarAppUtils::Params::log("scoket is closed!",
|
|
QuasarAppUtils::Error);
|
|
return;
|
|
}
|
|
|
|
switch (pkg.cmd()) {
|
|
|
|
case Command::FeaturesRequest: {
|
|
|
|
if (!_socket->send(_parser->createPackage(Command::Features,
|
|
_service->supportedFeatures()))) {
|
|
QuasarAppUtils::Params::log("Fail to send ",
|
|
QuasarAppUtils::Error);
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case Command::Feature: {
|
|
|
|
QDataStream stream(pkg.data());
|
|
|
|
QHash<QString, Feature> feature;
|
|
stream >> feature;
|
|
handleStandartCmd(&feature);
|
|
|
|
if (feature.size())
|
|
_service->handleReceiveData(feature);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default: {
|
|
QuasarAppUtils::Params::log("Wrong command!",
|
|
QuasarAppUtils::Error);
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
sendCloseConnection();
|
|
|
|
}
|
|
|
|
}
|