Compare commits
9 commits
Author | SHA1 | Date | |
---|---|---|---|
|
fd57796114 | ||
|
0198da6595 | ||
|
6595738d64 | ||
|
4981372e8f | ||
|
9e2518fa9b | ||
|
1ddc4ff755 | ||
|
d37369ad4f | ||
|
95db23458f | ||
|
529a4a8be9 |
7 changed files with 440 additions and 163 deletions
|
@ -1,6 +1,6 @@
|
||||||
cmake_minimum_required(VERSION 3.5)
|
cmake_minimum_required(VERSION 3.5)
|
||||||
|
|
||||||
project(smsub LANGUAGES CXX)
|
project(smsub LANGUAGES CXX VERSION 0.10.1)
|
||||||
|
|
||||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||||
|
|
||||||
|
@ -18,6 +18,18 @@ else()
|
||||||
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED)
|
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED)
|
||||||
endif()
|
endif()
|
||||||
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Network WebSockets REQUIRED)
|
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Network WebSockets REQUIRED)
|
||||||
|
set(SMSUB_LIBS Qt${QT_VERSION_MAJOR}::Network Qt${QT_VERSION_MAJOR}::WebSockets)
|
||||||
|
|
||||||
|
option(WITH_BOOST "Use Boost library" ON)
|
||||||
|
if(WITH_BOOST)
|
||||||
|
find_package(Boost COMPONENTS json REQUIRED)
|
||||||
|
list(APPEND SMSUB_LIBS
|
||||||
|
Boost::json
|
||||||
|
)
|
||||||
|
list(APPEND SMSUB_DEFINES
|
||||||
|
BOOST_JSON
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
set(SMSUB_SOURCES
|
set(SMSUB_SOURCES
|
||||||
main.cpp
|
main.cpp
|
||||||
|
@ -31,11 +43,7 @@ set(SMSUB_HEADERS
|
||||||
SMSubServer.h
|
SMSubServer.h
|
||||||
)
|
)
|
||||||
|
|
||||||
add_executable(smsub
|
add_executable(smsub ${SMSUB_HEADERS} ${SMSUB_SOURCES})
|
||||||
${SMSUB_HEADERS}
|
target_compile_definitions(smsub PRIVATE ${SMSUB_DEFINES})
|
||||||
${SMSUB_SOURCES}
|
target_link_libraries(smsub PRIVATE ${SMSUB_LIBS})
|
||||||
)
|
|
||||||
|
|
||||||
target_link_libraries(smsub PRIVATE Qt${QT_VERSION_MAJOR}::Network Qt${QT_VERSION_MAJOR}::WebSockets)
|
|
||||||
|
|
||||||
install(TARGETS smsub DESTINATION bin)
|
install(TARGETS smsub DESTINATION bin)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* smsub Server Manager Subprocess
|
* smsub Server Manager Subprocess
|
||||||
* Copyright (C) 2020-2021 Syping
|
* Copyright (C) 2020-2024 Syping
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
* are permitted provided that the following conditions are met:
|
* are permitted provided that the following conditions are met:
|
||||||
|
@ -18,55 +18,79 @@
|
||||||
|
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <QTextStream>
|
#include <QTextStream>
|
||||||
|
#include <QDateTime>
|
||||||
#include "SMSubProcess.h"
|
#include "SMSubProcess.h"
|
||||||
#include "smsub.h"
|
#include "smsub.h"
|
||||||
#include <QDebug>
|
|
||||||
|
|
||||||
SMSubProcess::SMSubProcess(const QString &executable, const QStringList &arguments, const QString &workingDirectory, const int &termTimeout) :
|
SMSubProcess::SMSubProcess(const QString &executable, const QStringList &arguments, const QString &workingDirectory, const int termTimeout, const bool buffReads, const bool keepAlive) :
|
||||||
termTimeout(termTimeout)
|
termTimeout(termTimeout), buffReads(buffReads), keepAlive(keepAlive)
|
||||||
{
|
{
|
||||||
// Set process executable, arguments and working directory
|
// Set process executable, arguments and working directory
|
||||||
process.setProgram(executable);
|
process.setProgram(executable);
|
||||||
process.setArguments(arguments);
|
process.setArguments(arguments);
|
||||||
process.setWorkingDirectory(workingDirectory);
|
process.setWorkingDirectory(workingDirectory);
|
||||||
|
|
||||||
// stdout and stderr in same IO stream
|
// manage input channel
|
||||||
|
process.setInputChannelMode(QProcess::ManagedInputChannel);
|
||||||
|
|
||||||
|
// stdout and stderr in same I/O stream
|
||||||
process.setProcessChannelMode(QProcess::MergedChannels);
|
process.setProcessChannelMode(QProcess::MergedChannels);
|
||||||
|
|
||||||
// Connect process signal handlers
|
// Connect process signal handlers
|
||||||
QObject::connect(&process, &QProcess::readyRead, this, &SMSubProcess::readyRead);
|
QObject::connect(&process, &QProcess::readyRead, this, &SMSubProcess::readyRead);
|
||||||
QObject::connect(&process, &QProcess::errorOccurred, this, &SMSubProcess::processError);
|
QObject::connect(&process, &QProcess::errorOccurred, this, &SMSubProcess::processError);
|
||||||
QObject::connect(&process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, [=](int exitCode) {
|
QObject::connect(&process, &QProcess::started, this, [=]() {
|
||||||
// Exit with the same exit code as the process
|
QTextStream(stderr) << "Subprocess started!" << smsub_endl;
|
||||||
emit processStopped();
|
emit statusUpdated(true, QDateTime::currentDateTimeUtc().toSecsSinceEpoch());
|
||||||
QCoreApplication::exit(exitCode);
|
});
|
||||||
|
QObject::connect(&process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, [=](int exitCode) {
|
||||||
|
QTextStream(stderr) << "Subprocess exited!" << smsub_endl;
|
||||||
|
// Exit with the same exit code as the process
|
||||||
|
emit statusUpdated(false, QDateTime::currentDateTimeUtc().toSecsSinceEpoch());
|
||||||
|
if (!keepAlive)
|
||||||
|
QCoreApplication::exit(exitCode);
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
void SMSubProcess::start()
|
|
||||||
{
|
|
||||||
process.start(QIODevice::ReadWrite);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SMSubProcess::readyRead()
|
void SMSubProcess::readyRead()
|
||||||
{
|
{
|
||||||
|
#ifdef SMSUB_IODEBUG
|
||||||
|
QTextStream(stderr) << "Subprocess I/O RR!" << smsub_endl;
|
||||||
|
#endif
|
||||||
// Read process output and emit event
|
// Read process output and emit event
|
||||||
while (process.canReadLine()) {
|
if (buffReads) {
|
||||||
const QByteArray readData = process.readLine().trimmed();
|
while (process.bytesAvailable()) {
|
||||||
emit outputWritten(readData + '\n');
|
#ifdef SMSUB_IODEBUG
|
||||||
|
QTextStream(stderr) << "Subprocess I/O W!" << smsub_endl;
|
||||||
|
#endif
|
||||||
|
const QByteArray readData = process.read(1024);
|
||||||
|
if (!readData.isEmpty())
|
||||||
|
emit outputWritten(readData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
while (process.canReadLine()) {
|
||||||
|
#ifdef SMSUB_IODEBUG
|
||||||
|
QTextStream(stderr) << "Subprocess I/O WL!" << smsub_endl;
|
||||||
|
#endif
|
||||||
|
const QByteArray readData = process.readLine().trimmed();
|
||||||
|
emit outputWritten(readData + '\n');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SMSubProcess::processError(QProcess::ProcessError error)
|
void SMSubProcess::processError(QProcess::ProcessError error)
|
||||||
{
|
{
|
||||||
// Handle process errors
|
// Handle process errors
|
||||||
if (likely(error == QProcess::FailedToStart)) {
|
if (Q_LIKELY(error == QProcess::FailedToStart)) {
|
||||||
QTextStream(stderr) << "Process failed to start!" << smsub_endl;
|
QTextStream(stderr) << "Process failed to start!" << smsub_endl;
|
||||||
QCoreApplication::exit(1);
|
if (!keepAlive)
|
||||||
|
QCoreApplication::exit(1);
|
||||||
}
|
}
|
||||||
else if (error == QProcess::UnknownError) {
|
else if (error == QProcess::UnknownError) {
|
||||||
QTextStream(stderr) << "Unknown error occurred!" << smsub_endl;
|
QTextStream(stderr) << "Unknown error occurred!" << smsub_endl;
|
||||||
QCoreApplication::exit(1);
|
if (!keepAlive)
|
||||||
|
QCoreApplication::exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,24 +105,33 @@ void SMSubProcess::aboutToQuit()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SMSubProcess::killProcess()
|
void SMSubProcess::startProcess()
|
||||||
{
|
{
|
||||||
// Kill process as requested
|
// Start process as requested
|
||||||
if (process.state() == QProcess::Running) {
|
if (process.state() == QProcess::NotRunning)
|
||||||
process.kill();
|
process.start(QIODevice::ReadWrite);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SMSubProcess::stopProcess()
|
void SMSubProcess::stopProcess()
|
||||||
{
|
{
|
||||||
// Terminate process as requested
|
// Terminate process as requested
|
||||||
if (process.state() == QProcess::Running) {
|
if (process.state() == QProcess::Running)
|
||||||
process.terminate();
|
process.terminate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SMSubProcess::killProcess()
|
||||||
|
{
|
||||||
|
// Kill process as requested
|
||||||
|
if (process.state() == QProcess::Running)
|
||||||
|
process.kill();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SMSubProcess::writeInput(const QByteArray &input)
|
void SMSubProcess::writeInput(const QByteArray &input)
|
||||||
{
|
{
|
||||||
|
#ifdef SMSUB_IODEBUG
|
||||||
|
QTextStream(stderr) << "Subprocess I/O IN!" << smsub_endl;
|
||||||
|
#endif
|
||||||
// Write input from Unix/IPC socket to process
|
// Write input from Unix/IPC socket to process
|
||||||
process.write(input);
|
if (process.state() == QProcess::Running)
|
||||||
|
process.write(input);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* smsub Server Manager Subprocess
|
* smsub Server Manager Subprocess
|
||||||
* Copyright (C) 2020-2021 Syping
|
* Copyright (C) 2020-2024 Syping
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
* are permitted provided that the following conditions are met:
|
* are permitted provided that the following conditions are met:
|
||||||
|
@ -26,17 +26,19 @@ class SMSubProcess : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
SMSubProcess(const QString &executable, const QStringList &arguments, const QString& workingDirectory, const int &termTimeout = 60000);
|
SMSubProcess(const QString &executable, const QStringList &arguments, const QString &workingDirectory, const int termTimeout = 60000, const bool buffReads = false, const bool keepAlive = false);
|
||||||
void start();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QProcess process;
|
QProcess process;
|
||||||
int termTimeout;
|
int termTimeout;
|
||||||
|
bool buffReads;
|
||||||
|
bool keepAlive;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void aboutToQuit();
|
void aboutToQuit();
|
||||||
void killProcess();
|
void startProcess();
|
||||||
void stopProcess();
|
void stopProcess();
|
||||||
|
void killProcess();
|
||||||
void writeInput(const QByteArray &input);
|
void writeInput(const QByteArray &input);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
@ -45,8 +47,7 @@ private slots:
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void outputWritten(const QByteArray &output);
|
void outputWritten(const QByteArray &output);
|
||||||
void processStopped();
|
void statusUpdated(const bool status, const qint64 time);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SMSUBPROCESS_H
|
#endif // SMSUBPROCESS_H
|
||||||
|
|
227
SMSubServer.cpp
227
SMSubServer.cpp
|
@ -1,6 +1,6 @@
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* smsub Server Manager Subprocess
|
* smsub Server Manager Subprocess
|
||||||
* Copyright (C) 2020-2021 Syping
|
* Copyright (C) 2020-2024 Syping
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
* are permitted provided that the following conditions are met:
|
* are permitted provided that the following conditions are met:
|
||||||
|
@ -21,6 +21,12 @@
|
||||||
#include <QUuid>
|
#include <QUuid>
|
||||||
#include "SMSubServer.h"
|
#include "SMSubServer.h"
|
||||||
#include "smsub.h"
|
#include "smsub.h"
|
||||||
|
#ifdef BOOST_JSON
|
||||||
|
#include <boost/json.hpp>
|
||||||
|
#else
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#endif
|
||||||
|
|
||||||
SMSubServer::SMSubServer(SMSubServerSettings *serverSettings, const QString &socket) : serverSettings(serverSettings)
|
SMSubServer::SMSubServer(SMSubServerSettings *serverSettings, const QString &socket) : serverSettings(serverSettings)
|
||||||
{
|
{
|
||||||
|
@ -32,22 +38,31 @@ SMSubServer::SMSubServer(SMSubServerSettings *serverSettings, const QString &soc
|
||||||
|
|
||||||
type = ServerType::Local;
|
type = ServerType::Local;
|
||||||
server = localServer;
|
server = localServer;
|
||||||
|
status = false;
|
||||||
|
startTime = QDateTime::currentDateTimeUtc().toSecsSinceEpoch();
|
||||||
|
stopTime = startTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
SMSubServer::SMSubServer(SMSubServerSettings *serverSettings, const QString &serverName, const quint16 &port) : serverSettings(serverSettings)
|
SMSubServer::SMSubServer(SMSubServerSettings *serverSettings, const QString &serverName, const quint16 &port) : serverSettings(serverSettings)
|
||||||
{
|
{
|
||||||
QWebSocketServer *webSocketServer = new QWebSocketServer(serverName, QWebSocketServer::NonSecureMode, this);
|
QWebSocketServer *webSocketServer = new QWebSocketServer(serverName, QWebSocketServer::NonSecureMode, this);
|
||||||
|
#if QT_VERSION >= 0x060400
|
||||||
|
webSocketServer->setSupportedSubprotocols(QStringList() << "smsub" << "smsub_json");
|
||||||
|
#endif
|
||||||
webSocketServer->listen(QHostAddress::LocalHost, port);
|
webSocketServer->listen(QHostAddress::LocalHost, port);
|
||||||
|
|
||||||
QObject::connect(webSocketServer, &QWebSocketServer::newConnection, this, &SMSubServer::newConnection);
|
QObject::connect(webSocketServer, &QWebSocketServer::newConnection, this, &SMSubServer::newConnection);
|
||||||
|
|
||||||
type = ServerType::WebSocket;
|
type = ServerType::WebSocket;
|
||||||
server = webSocketServer;
|
server = webSocketServer;
|
||||||
|
status = false;
|
||||||
|
startTime = QDateTime::currentDateTimeUtc().toSecsSinceEpoch();
|
||||||
|
stopTime = startTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SMSubServer::isListening()
|
bool SMSubServer::isListening()
|
||||||
{
|
{
|
||||||
if (likely(type == ServerType::Local)) {
|
if (type == ServerType::Local) {
|
||||||
return static_cast<QLocalServer*>(server)->isListening();
|
return static_cast<QLocalServer*>(server)->isListening();
|
||||||
}
|
}
|
||||||
else if (type == ServerType::WebSocket) {
|
else if (type == ServerType::WebSocket) {
|
||||||
|
@ -59,12 +74,13 @@ bool SMSubServer::isListening()
|
||||||
void SMSubServer::newConnection()
|
void SMSubServer::newConnection()
|
||||||
{
|
{
|
||||||
QObject *socket;
|
QObject *socket;
|
||||||
if (likely(type == ServerType::Local)) {
|
if (Q_LIKELY(type == ServerType::Local)) {
|
||||||
QLocalSocket *localSocket = static_cast<QLocalServer*>(server)->nextPendingConnection();
|
QLocalSocket *localSocket = static_cast<QLocalServer*>(server)->nextPendingConnection();
|
||||||
QObject::connect(localSocket, &QLocalSocket::readyRead, this, &SMSubServer::lsReadyRead);
|
QObject::connect(localSocket, &QLocalSocket::readyRead, this, &SMSubServer::lsReadyRead);
|
||||||
QObject::connect(localSocket, &QLocalSocket::disconnected, this, &SMSubServer::deleteSocket);
|
QObject::connect(localSocket, &QLocalSocket::disconnected, this, &SMSubServer::deleteSocket);
|
||||||
localSocket->write(QString("SMSub Version %1\n").arg(QCoreApplication::applicationVersion()).toUtf8());
|
localSocket->write(QString("SMSub Version %1\n").arg(QCoreApplication::applicationVersion()).toUtf8());
|
||||||
socket = localSocket;
|
socket = localSocket;
|
||||||
|
QTextStream(stderr) << "LocalSocket connected!" << smsub_endl;
|
||||||
}
|
}
|
||||||
else if (type == ServerType::WebSocket) {
|
else if (type == ServerType::WebSocket) {
|
||||||
QWebSocket *webSocket = static_cast<QWebSocketServer*>(server)->nextPendingConnection();
|
QWebSocket *webSocket = static_cast<QWebSocketServer*>(server)->nextPendingConnection();
|
||||||
|
@ -72,6 +88,12 @@ void SMSubServer::newConnection()
|
||||||
QObject::connect(webSocket, &QWebSocket::disconnected, this, &SMSubServer::deleteSocket);
|
QObject::connect(webSocket, &QWebSocket::disconnected, this, &SMSubServer::deleteSocket);
|
||||||
webSocket->sendBinaryMessage(QString("SMSub Version %1\n").arg(QCoreApplication::applicationVersion()).toUtf8());
|
webSocket->sendBinaryMessage(QString("SMSub Version %1\n").arg(QCoreApplication::applicationVersion()).toUtf8());
|
||||||
socket = webSocket;
|
socket = webSocket;
|
||||||
|
QTextStream(stderr) << QString("WebSocket %1:%2 connected!").arg(webSocket->peerAddress().toString(), QString::number(webSocket->peerPort())) << smsub_endl;
|
||||||
|
|
||||||
|
#if QT_VERSION >= 0x060400
|
||||||
|
if (webSocket->subprotocol() == "smsub_json")
|
||||||
|
socket->setProperty("ReceiveJson", true);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Just for being sure
|
// Just for being sure
|
||||||
|
@ -91,57 +113,109 @@ void SMSubServer::newConnection()
|
||||||
bool SMSubServer::messageReceived(QObject *socket, const QByteArray &message)
|
bool SMSubServer::messageReceived(QObject *socket, const QByteArray &message)
|
||||||
{
|
{
|
||||||
// Only allow commands being sent if authenticated
|
// Only allow commands being sent if authenticated
|
||||||
const bool isAuthenticated = socket->property("Authenticated").toBool();
|
const bool isAuthenticated = isVariantTrue(socket->property("Authenticated"));
|
||||||
if (likely(isAuthenticated)) {
|
if (isAuthenticated) {
|
||||||
if (message.startsWith("+dbg")) {
|
if (message == "+dbg") {
|
||||||
socket->setProperty("ReceiveDbgMsg", true);
|
socket->setProperty("ReceiveDbgMsg", true);
|
||||||
sendMessage(socket, "Debug messages enabled!\n");
|
debugOutput(socket, "Debug messages enabled!");
|
||||||
}
|
}
|
||||||
else if (message.startsWith("-dbg")) {
|
else if (message == "-dbg") {
|
||||||
|
debugOutput(socket, "Debug messages disabled!");
|
||||||
socket->setProperty("ReceiveDbgMsg", false);
|
socket->setProperty("ReceiveDbgMsg", false);
|
||||||
sendMessage(socket, "Debug messages disabled!\n");
|
|
||||||
}
|
}
|
||||||
else if (message.startsWith("+log")) {
|
else if (message == "+json") {
|
||||||
|
socket->setProperty("ReceiveJson", true);
|
||||||
|
debugOutput(socket, "JSON output enabled!");
|
||||||
|
}
|
||||||
|
else if (message == "-json") {
|
||||||
|
socket->setProperty("ReceiveJson", false);
|
||||||
|
debugOutput(socket, "JSON output disabled!");
|
||||||
|
}
|
||||||
|
else if (message == "+log") {
|
||||||
socket->setProperty("ReceiveLog", true);
|
socket->setProperty("ReceiveLog", true);
|
||||||
debugOutput(socket, "Log output enabled!");
|
debugOutput(socket, "Log output enabled!");
|
||||||
}
|
}
|
||||||
else if (message.startsWith("-log")) {
|
else if (message == "-log") {
|
||||||
socket->setProperty("ReceiveLog", false);
|
socket->setProperty("ReceiveLog", false);
|
||||||
debugOutput(socket, "Log output disabled!");
|
debugOutput(socket, "Log output disabled!");
|
||||||
}
|
}
|
||||||
else if (message.startsWith("+reg")) {
|
else if (message == "+status") {
|
||||||
if (likely(serverSettings->canRegister)) {
|
socket->setProperty("ReceiveStatus", true);
|
||||||
QByteArray authUuid = QUuid::createUuid().toByteArray(QUuid::Id128);
|
debugOutput(socket, "Status updates enabled!");
|
||||||
|
}
|
||||||
|
else if (message == "-status") {
|
||||||
|
socket->setProperty("ReceiveStatus", false);
|
||||||
|
debugOutput(socket, "Status updates disabled!");
|
||||||
|
}
|
||||||
|
else if (message == "+reg") {
|
||||||
|
if (serverSettings->canRegister) {
|
||||||
|
QByteArray authUuid = QUuid::createUuid().toByteArray(QUuid::Id128) +
|
||||||
|
QUuid::createUuid().toByteArray(QUuid::Id128);
|
||||||
authUuid = QByteArray::fromHex(authUuid).toBase64(QByteArray::OmitTrailingEquals);
|
authUuid = QByteArray::fromHex(authUuid).toBase64(QByteArray::OmitTrailingEquals);
|
||||||
emit tokenRegistered(QString::fromUtf8(authUuid));
|
emit tokenRegistered(authUuid);
|
||||||
sendMessage(socket, "Token: " + authUuid + '\n');
|
sendMessage(socket, "Token: " + authUuid + '\n');
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
sendMessage(socket, "Permission denied!\n");
|
sendMessage(socket, "Permission denied!\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (message.startsWith("kill")) {
|
else if (message == "status") {
|
||||||
emit killRequested();
|
if (isVariantTrue(socket->property("ReceiveJson"))) {
|
||||||
debugOutput(socket, "Killing server!");
|
#ifdef BOOST_JSON
|
||||||
|
boost::json::object object;
|
||||||
|
object["type"] = "status";
|
||||||
|
object["status"] = status;
|
||||||
|
object["start"] = startTime;
|
||||||
|
object["stop"] = stopTime;
|
||||||
|
const std::string json = boost::json::serialize(object) + '\n';
|
||||||
|
sendMessage(socket, QByteArray::fromRawData(json.data(), json.size()));
|
||||||
|
#else
|
||||||
|
QJsonObject object;
|
||||||
|
object["type"] = "status";
|
||||||
|
object["status"] = status;
|
||||||
|
object["start"] = startTime;
|
||||||
|
object["stop"] = stopTime;
|
||||||
|
sendMessage(socket, QJsonDocument(object).toJson(QJsonDocument::Compact) + '\n');
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sendMessage(socket, QString("Status: %1\nLast Start: %2\nLast Stop: %3\n").arg(status ? "on" : "off", QString::number(startTime), QString::number(stopTime)).toUtf8());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (message.startsWith("stop")) {
|
else if (message == "start") {
|
||||||
|
emit startRequested();
|
||||||
|
debugOutput(socket, "Starting server!");
|
||||||
|
}
|
||||||
|
else if (message == "stop") {
|
||||||
emit stopRequested();
|
emit stopRequested();
|
||||||
debugOutput(socket, "Stopping server!");
|
debugOutput(socket, "Stopping server!");
|
||||||
}
|
}
|
||||||
else if (message.startsWith("wl")) {
|
else if (message == "kill") {
|
||||||
|
emit killRequested();
|
||||||
|
debugOutput(socket, "Killing server!");
|
||||||
|
}
|
||||||
|
else if (message == "quit") {
|
||||||
|
QTimer::singleShot(0, qApp, &QCoreApplication::quit);
|
||||||
|
debugOutput(socket, "Qutting smsub!");
|
||||||
|
}
|
||||||
|
else if (message == "wl") {
|
||||||
|
emit inputWritten("\n");
|
||||||
|
debugOutput(socket, "Writing line!");
|
||||||
|
}
|
||||||
|
else if (message.startsWith("wl ")) {
|
||||||
const QByteArray writeData = message.mid(3);
|
const QByteArray writeData = message.mid(3);
|
||||||
emit inputWritten(writeData + '\n');
|
emit inputWritten(writeData + '\n');
|
||||||
debugOutput(socket, "Write line \"" + writeData + "\"!");
|
debugOutput(socket, "Writing line: " + writeData);
|
||||||
}
|
}
|
||||||
else if (message.startsWith("w")) {
|
else if (message.startsWith("w ")) {
|
||||||
const QByteArray writeData = message.mid(2);
|
const QByteArray writeData = message.mid(2);
|
||||||
emit inputWritten(writeData);
|
emit inputWritten(writeData);
|
||||||
debugOutput(socket, "Write \"" + writeData + "\"!");
|
debugOutput(socket, "Writing: " + writeData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Authenticate when token is valid, otherwise disconnect
|
// Authenticate when token is valid, otherwise disconnect
|
||||||
if (unlikely(tokens.contains(QString::fromUtf8(message)))) {
|
if (tokens.contains(message)) {
|
||||||
// Set client as authenticated and add it to vector
|
// Set client as authenticated and add it to vector
|
||||||
socket->setProperty("Authenticated", true);
|
socket->setProperty("Authenticated", true);
|
||||||
sendMessage(socket, "Login successful!\n");
|
sendMessage(socket, "Login successful!\n");
|
||||||
|
@ -149,7 +223,7 @@ bool SMSubServer::messageReceived(QObject *socket, const QByteArray &message)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Stop receiving data and disconnect socket
|
// Stop receiving data and disconnect socket
|
||||||
if (likely(type == ServerType::Local)) {
|
if (type == ServerType::Local) {
|
||||||
QLocalSocket *localSocket = static_cast<QLocalSocket*>(socket);
|
QLocalSocket *localSocket = static_cast<QLocalSocket*>(socket);
|
||||||
QObject::disconnect(localSocket, &QLocalSocket::readyRead, this, &SMSubServer::lsReadyRead);
|
QObject::disconnect(localSocket, &QLocalSocket::readyRead, this, &SMSubServer::lsReadyRead);
|
||||||
localSocket->write("Incorrect token!\n");
|
localSocket->write("Incorrect token!\n");
|
||||||
|
@ -168,6 +242,18 @@ bool SMSubServer::messageReceived(QObject *socket, const QByteArray &message)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SMSubServer::isVariantTrue(const QVariant &variant)
|
||||||
|
{
|
||||||
|
#if QT_VERSION >= 0x060000
|
||||||
|
if (variant.typeId() == QMetaType::Bool) {
|
||||||
|
#else
|
||||||
|
if (variant.type() == QVariant::Bool) {
|
||||||
|
#endif
|
||||||
|
return variant.toBool();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void SMSubServer::wsMessageReceived(const QByteArray &message)
|
void SMSubServer::wsMessageReceived(const QByteArray &message)
|
||||||
{
|
{
|
||||||
QWebSocket *socket = static_cast<QWebSocket*>(sender());
|
QWebSocket *socket = static_cast<QWebSocket*>(sender());
|
||||||
|
@ -177,7 +263,13 @@ void SMSubServer::wsMessageReceived(const QByteArray &message)
|
||||||
void SMSubServer::lsReadyRead()
|
void SMSubServer::lsReadyRead()
|
||||||
{
|
{
|
||||||
QLocalSocket *socket = static_cast<QLocalSocket*>(sender());
|
QLocalSocket *socket = static_cast<QLocalSocket*>(sender());
|
||||||
|
#ifdef SMSUB_IODEBUG
|
||||||
|
QTextStream(stderr) << "LocalSocket I/O RR!" << smsub_endl;
|
||||||
|
#endif
|
||||||
while (socket->canReadLine()) {
|
while (socket->canReadLine()) {
|
||||||
|
#ifdef SMSUB_IODEBUG
|
||||||
|
QTextStream(stderr) << "LocalSocket I/O WL!" << smsub_endl;
|
||||||
|
#endif
|
||||||
const QByteArray message = socket->readLine().trimmed();
|
const QByteArray message = socket->readLine().trimmed();
|
||||||
if (!messageReceived(socket, message))
|
if (!messageReceived(socket, message))
|
||||||
return;
|
return;
|
||||||
|
@ -195,10 +287,22 @@ void SMSubServer::deleteSocket()
|
||||||
void SMSubServer::debugOutput(QObject *socket, const QByteArray &message)
|
void SMSubServer::debugOutput(QObject *socket, const QByteArray &message)
|
||||||
{
|
{
|
||||||
// Only send debug messages when the client opted-in
|
// Only send debug messages when the client opted-in
|
||||||
const QVariant variant = socket->property("ReceiveDbgMsg");
|
if (isVariantTrue(socket->property("ReceiveDbgMsg"))) {
|
||||||
if (unlikely(variant.type() == QVariant::Bool)) {
|
if (isVariantTrue(socket->property("ReceiveJson"))) {
|
||||||
bool receiveDbgMsg = variant.toBool();
|
#ifdef BOOST_JSON
|
||||||
if (likely(receiveDbgMsg)) {
|
boost::json::object object;
|
||||||
|
object["type"] = "debug";
|
||||||
|
object["message"] = message.toBase64(QByteArray::OmitTrailingEquals).constData();
|
||||||
|
const std::string json = boost::json::serialize(object) + '\n';
|
||||||
|
sendMessage(socket, QByteArray::fromRawData(json.data(), json.size()));
|
||||||
|
#else
|
||||||
|
QJsonObject object;
|
||||||
|
object["type"] = "debug";
|
||||||
|
object["message"] = QString::fromUtf8(message.toBase64(QByteArray::OmitTrailingEquals));
|
||||||
|
sendMessage(socket, QJsonDocument(object).toJson(QJsonDocument::Compact) + '\n');
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else {
|
||||||
sendMessage(socket, message + '\n');
|
sendMessage(socket, message + '\n');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -207,11 +311,26 @@ void SMSubServer::debugOutput(QObject *socket, const QByteArray &message)
|
||||||
void SMSubServer::writeOutput(const QByteArray &output)
|
void SMSubServer::writeOutput(const QByteArray &output)
|
||||||
{
|
{
|
||||||
// Read process output when client opted-in for log
|
// Read process output when client opted-in for log
|
||||||
|
QByteArray json_output;
|
||||||
for (auto it = sockets.constBegin(); it != sockets.constEnd(); it++) {
|
for (auto it = sockets.constBegin(); it != sockets.constEnd(); it++) {
|
||||||
const QVariant variant = (*it)->property("ReceiveLog");
|
if (isVariantTrue((*it)->property("ReceiveLog"))) {
|
||||||
if (unlikely(variant.type() == QVariant::Bool)) {
|
if (isVariantTrue((*it)->property("ReceiveJson"))) {
|
||||||
bool receiveLog = variant.toBool();
|
if (json_output.isEmpty()) {
|
||||||
if (likely(receiveLog)) {
|
#ifdef BOOST_JSON
|
||||||
|
boost::json::object object;
|
||||||
|
object["type"] = "log";
|
||||||
|
object["message"] = output.toBase64(QByteArray::OmitTrailingEquals).constData();
|
||||||
|
json_output = QByteArray::fromStdString(boost::json::serialize(object) + '\n');
|
||||||
|
#else
|
||||||
|
QJsonObject object;
|
||||||
|
object["type"] = "log";
|
||||||
|
object["message"] = QString::fromUtf8(output.toBase64(QByteArray::OmitTrailingEquals));
|
||||||
|
json_output = QJsonDocument(object).toJson(QJsonDocument::Compact) + '\n';
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
sendMessage(*it, json_output);
|
||||||
|
}
|
||||||
|
else {
|
||||||
sendMessage(*it, output);
|
sendMessage(*it, output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -220,7 +339,7 @@ void SMSubServer::writeOutput(const QByteArray &output)
|
||||||
|
|
||||||
void SMSubServer::sendMessage(QObject *socket, const QByteArray &message)
|
void SMSubServer::sendMessage(QObject *socket, const QByteArray &message)
|
||||||
{
|
{
|
||||||
if (likely(type == ServerType::Local)) {
|
if (type == ServerType::Local) {
|
||||||
QLocalSocket *localSocket = static_cast<QLocalSocket*>(socket);
|
QLocalSocket *localSocket = static_cast<QLocalSocket*>(socket);
|
||||||
localSocket->write(message);
|
localSocket->write(message);
|
||||||
}
|
}
|
||||||
|
@ -230,7 +349,7 @@ void SMSubServer::sendMessage(QObject *socket, const QByteArray &message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SMSubServer::registerToken(const QString &token)
|
void SMSubServer::registerToken(const QByteArray &token)
|
||||||
{
|
{
|
||||||
// Register temporary token for a secure remote connection
|
// Register temporary token for a secure remote connection
|
||||||
tokens << token;
|
tokens << token;
|
||||||
|
@ -238,3 +357,41 @@ void SMSubServer::registerToken(const QString &token)
|
||||||
tokens.removeAll(token);
|
tokens.removeAll(token);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SMSubServer::statusUpdated(const bool status_, const qint64 time)
|
||||||
|
{
|
||||||
|
status = status_;
|
||||||
|
status ? (startTime = time) : (stopTime = time);
|
||||||
|
|
||||||
|
QByteArray output, json_output;
|
||||||
|
for (auto it = sockets.constBegin(); it != sockets.constEnd(); it++) {
|
||||||
|
if (isVariantTrue((*it)->property("ReceiveStatus"))) {
|
||||||
|
if (isVariantTrue((*it)->property("ReceiveJson"))) {
|
||||||
|
if (json_output.isEmpty()) {
|
||||||
|
#ifdef BOOST_JSON
|
||||||
|
boost::json::object object;
|
||||||
|
object["type"] = "status";
|
||||||
|
object["status"] = status;
|
||||||
|
object["start"] = startTime;
|
||||||
|
object["stop"] = stopTime;
|
||||||
|
json_output = QByteArray::fromStdString(boost::json::serialize(object) + '\n');
|
||||||
|
#else
|
||||||
|
QJsonObject object;
|
||||||
|
object["type"] = "status";
|
||||||
|
object["status"] = status;
|
||||||
|
object["start"] = startTime;
|
||||||
|
object["stop"] = stopTime;
|
||||||
|
json_output = QJsonDocument(object).toJson(QJsonDocument::Compact) + '\n';
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
sendMessage(*it, json_output);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (output.isEmpty()) {
|
||||||
|
output = QString("Status: %1\nLast Start: %2\nLast Stop: %3\n").arg(status ? "on" : "off", QString::number(startTime), QString::number(stopTime)).toUtf8();
|
||||||
|
}
|
||||||
|
sendMessage(*it, json_output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* smsub Server Manager Subprocess
|
* smsub Server Manager Subprocess
|
||||||
* Copyright (C) 2020-2021 Syping
|
* Copyright (C) 2020-2024 Syping
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
* are permitted provided that the following conditions are met:
|
* are permitted provided that the following conditions are met:
|
||||||
|
@ -44,7 +44,8 @@ public:
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void writeOutput(const QByteArray &output);
|
void writeOutput(const QByteArray &output);
|
||||||
void registerToken(const QString &token);
|
void registerToken(const QByteArray &token);
|
||||||
|
void statusUpdated(const bool status, const qint64 time);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void wsMessageReceived(const QByteArray &message);
|
void wsMessageReceived(const QByteArray &message);
|
||||||
|
@ -56,17 +57,22 @@ private:
|
||||||
inline void debugOutput(QObject *socket, const QByteArray &message);
|
inline void debugOutput(QObject *socket, const QByteArray &message);
|
||||||
inline void sendMessage(QObject *socket, const QByteArray &message);
|
inline void sendMessage(QObject *socket, const QByteArray &message);
|
||||||
bool messageReceived(QObject *socket, const QByteArray &message);
|
bool messageReceived(QObject *socket, const QByteArray &message);
|
||||||
|
inline bool isVariantTrue(const QVariant &variant);
|
||||||
SMSubServerSettings *serverSettings;
|
SMSubServerSettings *serverSettings;
|
||||||
QVector<QObject*> sockets;
|
QVector<QObject*> sockets;
|
||||||
QVector<QString> tokens;
|
QVector<QByteArray> tokens;
|
||||||
|
qint64 startTime;
|
||||||
|
qint64 stopTime;
|
||||||
ServerType type;
|
ServerType type;
|
||||||
QObject *server;
|
QObject *server;
|
||||||
|
bool status;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void tokenRegistered(const QString &password);
|
void tokenRegistered(const QByteArray &token);
|
||||||
void inputWritten(const QByteArray &input);
|
void inputWritten(const QByteArray &input);
|
||||||
void killRequested();
|
void startRequested();
|
||||||
void stopRequested();
|
void stopRequested();
|
||||||
|
void killRequested();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SMSUBSERVER_H
|
#endif // SMSUBSERVER_H
|
||||||
|
|
214
main.cpp
214
main.cpp
|
@ -1,6 +1,6 @@
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* smsub Server Manager Subprocess
|
* smsub Server Manager Subprocess
|
||||||
* Copyright (C) 2020-2021 Syping
|
* Copyright (C) 2020-2024 Syping
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
* are permitted provided that the following conditions are met:
|
* are permitted provided that the following conditions are met:
|
||||||
|
@ -33,7 +33,6 @@
|
||||||
#ifdef Q_OS_UNIX
|
#ifdef Q_OS_UNIX
|
||||||
#include <initializer_list>
|
#include <initializer_list>
|
||||||
#include "signal.h"
|
#include "signal.h"
|
||||||
#include "unistd.h"
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef Q_OS_UNIX
|
#ifdef Q_OS_UNIX
|
||||||
|
@ -135,15 +134,18 @@ int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
QCoreApplication a(argc, argv);
|
QCoreApplication a(argc, argv);
|
||||||
a.setApplicationName("Server Manager Subprocess");
|
a.setApplicationName("Server Manager Subprocess");
|
||||||
a.setApplicationVersion("0.5.1");
|
a.setApplicationVersion("0.10.1");
|
||||||
|
|
||||||
#ifdef Q_OS_UNIX
|
#ifdef Q_OS_UNIX
|
||||||
catchUnixSignals({SIGINT, SIGHUP, SIGQUIT, SIGTERM});
|
catchUnixSignals({SIGINT, SIGHUP, SIGQUIT, SIGTERM});
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool rportSet = false;
|
bool rportSet = false;
|
||||||
|
bool autoStart = true;
|
||||||
|
bool buffReads = false;
|
||||||
|
bool keepAlive = false;
|
||||||
bool timeoutSet = false;
|
bool timeoutSet = false;
|
||||||
int termTimeout = 60000;
|
size_t termTimeout = 60000;
|
||||||
quint16 rport;
|
quint16 rport;
|
||||||
QString socket;
|
QString socket;
|
||||||
QString rsocket;
|
QString rsocket;
|
||||||
|
@ -151,25 +153,28 @@ int main(int argc, char *argv[])
|
||||||
QString workingDirectory;
|
QString workingDirectory;
|
||||||
QStringList argumentList;
|
QStringList argumentList;
|
||||||
|
|
||||||
QByteArray envEnvironmentMode = qgetenv("SMSUB_ENVIRONMENT_MODE");
|
const QByteArray envEnvironmentMode = qgetenv("SMSUB_ENVIRONMENT_MODE");
|
||||||
QByteArray envManifest = qgetenv("SMSUB_JSON");
|
const QByteArray envAutoStart = qgetenv("SMSUB_AUTOSTART");
|
||||||
QByteArray envExecutable = qgetenv("SMSUB_EXEC");
|
const QByteArray envBuffReads = qgetenv("SMSUB_BUFFERED_READS");
|
||||||
QByteArray envArguments = qgetenv("SMSUB_ARGS");
|
const QByteArray envKeepAlive = qgetenv("SMSUB_KEEPALIVE");
|
||||||
QByteArray envSocket = qgetenv("SMSUB_SOCK");
|
const QByteArray envManifest = qgetenv("SMSUB_JSON");
|
||||||
QByteArray envRemotePort = qgetenv("SMSUB_RPORT");
|
const QByteArray envExecutable = qgetenv("SMSUB_EXEC");
|
||||||
QByteArray envRemoteSocket = qgetenv("SMSUB_RSOCK");
|
const QByteArray envArguments = qgetenv("SMSUB_ARGS");
|
||||||
QByteArray envTimeout = qgetenv("SMSUB_TIMEOUT");
|
const QByteArray envSocket = qgetenv("SMSUB_SOCK");
|
||||||
QByteArray envWorkDir = qgetenv("SMSUB_WORKDIR");
|
const QByteArray envRemotePort = qgetenv("SMSUB_RPORT");
|
||||||
|
const QByteArray envRemoteSocket = qgetenv("SMSUB_RSOCK");
|
||||||
|
const QByteArray envTimeout = qgetenv("SMSUB_TIMEOUT");
|
||||||
|
const QByteArray envWorkDir = qgetenv("SMSUB_WORKDIR");
|
||||||
|
|
||||||
if (unlikely(envEnvironmentMode == "1" || envEnvironmentMode.toLower() == "true")) {
|
if (envEnvironmentMode == "1" || envEnvironmentMode.toLower() == "true" || envEnvironmentMode.toLower() == "yes") {
|
||||||
if (likely(envExecutable.isEmpty() && envArguments.isEmpty())) {
|
if (envExecutable.isEmpty() && envArguments.isEmpty()) {
|
||||||
QStringList arguments = a.arguments();
|
QStringList arguments = a.arguments();
|
||||||
arguments.removeFirst();
|
arguments.removeFirst();
|
||||||
executable = arguments.takeFirst();
|
executable = arguments.takeFirst();
|
||||||
argumentList = arguments;
|
argumentList = arguments;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (likely(!envExecutable.isEmpty())) {
|
if (!envExecutable.isEmpty()) {
|
||||||
executable = QString::fromUtf8(envExecutable);
|
executable = QString::fromUtf8(envExecutable);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -177,7 +182,7 @@ int main(int argc, char *argv[])
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (likely(!envArguments.isEmpty())) {
|
if (!envArguments.isEmpty()) {
|
||||||
argumentList = parseStringArguments(QString::fromUtf8(envArguments));
|
argumentList = parseStringArguments(QString::fromUtf8(envArguments));
|
||||||
if (argumentList.empty()) {
|
if (argumentList.empty()) {
|
||||||
QTextStream(stderr) << "Arguments can't be parsed properly!" << smsub_endl;
|
QTextStream(stderr) << "Arguments can't be parsed properly!" << smsub_endl;
|
||||||
|
@ -190,7 +195,7 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unlikely(!envTimeout.isEmpty())) {
|
if (!envTimeout.isEmpty()) {
|
||||||
bool ok;
|
bool ok;
|
||||||
const int _termTimeout = envTimeout.toInt(&ok);
|
const int _termTimeout = envTimeout.toInt(&ok);
|
||||||
if (ok) {
|
if (ok) {
|
||||||
|
@ -203,14 +208,32 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unlikely(!envWorkDir.isEmpty())) {
|
if (!envAutoStart.isEmpty()) {
|
||||||
|
if (envAutoStart == "0" || envAutoStart.toLower() == "false" || envAutoStart.toLower() == "no") {
|
||||||
|
autoStart = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!envBuffReads.isEmpty()) {
|
||||||
|
if (envBuffReads == "1" || envBuffReads.toLower() == "true" || envBuffReads.toLower() == "yes") {
|
||||||
|
buffReads = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!envKeepAlive.isEmpty()) {
|
||||||
|
if (envKeepAlive == "1" || envKeepAlive.toLower() == "true" || envKeepAlive.toLower() == "yes") {
|
||||||
|
keepAlive = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!envWorkDir.isEmpty()) {
|
||||||
workingDirectory = QString::fromUtf8(envWorkDir);
|
workingDirectory = QString::fromUtf8(envWorkDir);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
workingDirectory = QFileInfo(executable).absolutePath();
|
workingDirectory = QFileInfo(executable).absolutePath();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (likely(!envSocket.isEmpty())) {
|
if (!envSocket.isEmpty()) {
|
||||||
socket = QString::fromUtf8(envSocket);
|
socket = QString::fromUtf8(envSocket);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -222,11 +245,11 @@ int main(int argc, char *argv[])
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unlikely(!envRemoteSocket.isEmpty())) {
|
if (!envRemoteSocket.isEmpty()) {
|
||||||
rsocket = QString::fromUtf8(envRemoteSocket);
|
rsocket = QString::fromUtf8(envRemoteSocket);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unlikely(!envRemotePort.isEmpty())) {
|
if (!envRemotePort.isEmpty()) {
|
||||||
bool ok;
|
bool ok;
|
||||||
const quint16 _rport = envRemotePort.toUShort(&ok);
|
const quint16 _rport = envRemotePort.toUShort(&ok);
|
||||||
if (ok) {
|
if (ok) {
|
||||||
|
@ -270,31 +293,37 @@ int main(int argc, char *argv[])
|
||||||
#endif
|
#endif
|
||||||
commandLineParser.addOption(subprocessRemoteSocket);
|
commandLineParser.addOption(subprocessRemoteSocket);
|
||||||
|
|
||||||
|
QCommandLineOption processAutoStart("autostart", "SMSub autostart mode.", "autostart");
|
||||||
|
commandLineParser.addOption(processAutoStart);
|
||||||
|
|
||||||
|
QCommandLineOption processKeepAlive("keepalive", "SMSub keepalive mode.", "keepalive");
|
||||||
|
commandLineParser.addOption(processKeepAlive);
|
||||||
|
|
||||||
QCommandLineOption processTimeout("timeout", "SMSub termination timeout.", "timeout");
|
QCommandLineOption processTimeout("timeout", "SMSub termination timeout.", "timeout");
|
||||||
commandLineParser.addOption(processTimeout);
|
commandLineParser.addOption(processTimeout);
|
||||||
|
|
||||||
commandLineParser.process(a);
|
commandLineParser.process(a);
|
||||||
|
|
||||||
if (unlikely(commandLineParser.isSet(processManifest) && commandLineParser.isSet(processExecutable) ||
|
if (commandLineParser.isSet(processManifest) && commandLineParser.isSet(processExecutable) ||
|
||||||
!envManifest.isEmpty() && !envExecutable.isEmpty() ||
|
!envManifest.isEmpty() && !envExecutable.isEmpty() ||
|
||||||
commandLineParser.isSet(processManifest) && !envExecutable.isEmpty() ||
|
commandLineParser.isSet(processManifest) && !envExecutable.isEmpty() ||
|
||||||
!envManifest.isEmpty() && commandLineParser.isSet(processExecutable))) {
|
!envManifest.isEmpty() && commandLineParser.isSet(processExecutable)) {
|
||||||
QTextStream(stderr) << "You can't define a Process executable and a JSON process manifest at the same time!" << smsub_endl;
|
QTextStream(stderr) << "You can't define a Process executable and a JSON process manifest at the same time!" << smsub_endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unlikely(commandLineParser.isSet(processManifest) && commandLineParser.isSet(processArguments) ||
|
if (commandLineParser.isSet(processManifest) && commandLineParser.isSet(processArguments) ||
|
||||||
!envManifest.isEmpty() && !envArguments.isEmpty() ||
|
!envManifest.isEmpty() && !envArguments.isEmpty() ||
|
||||||
commandLineParser.isSet(processManifest) && !envArguments.isEmpty() ||
|
commandLineParser.isSet(processManifest) && !envArguments.isEmpty() ||
|
||||||
!envManifest.isEmpty() && commandLineParser.isSet(processArguments))) {
|
!envManifest.isEmpty() && commandLineParser.isSet(processArguments)) {
|
||||||
QTextStream(stderr) << "You can't define a Process arguments and a JSON process manifest at the same time!" << smsub_endl;
|
QTextStream(stderr) << "You can't define Process arguments and a JSON process manifest at the same time!" << smsub_endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unlikely(commandLineParser.isSet(subprocessRemotePort) && commandLineParser.isSet(subprocessRemoteSocket) ||
|
if (commandLineParser.isSet(subprocessRemotePort) && commandLineParser.isSet(subprocessRemoteSocket) ||
|
||||||
!envRemotePort.isEmpty() && !envRemoteSocket.isEmpty() ||
|
!envRemotePort.isEmpty() && !envRemoteSocket.isEmpty() ||
|
||||||
commandLineParser.isSet(subprocessRemotePort) && !envRemoteSocket.isEmpty() ||
|
commandLineParser.isSet(subprocessRemotePort) && !envRemoteSocket.isEmpty() ||
|
||||||
!envRemotePort.isEmpty() && commandLineParser.isSet(subprocessRemoteSocket))) {
|
!envRemotePort.isEmpty() && commandLineParser.isSet(subprocessRemoteSocket)) {
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
QTextStream(stderr) << "You can't define a WebSockets port and a IPC socket at same time!" << smsub_endl;
|
QTextStream(stderr) << "You can't define a WebSockets port and a IPC socket at same time!" << smsub_endl;
|
||||||
#else
|
#else
|
||||||
|
@ -303,9 +332,9 @@ int main(int argc, char *argv[])
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unlikely(commandLineParser.isSet(processTimeout))) {
|
if (commandLineParser.isSet(processTimeout)) {
|
||||||
bool ok;
|
bool ok;
|
||||||
const int _termTimeout = commandLineParser.value(processTimeout).toInt(&ok);
|
const int _termTimeout = commandLineParser.value(processTimeout).toInt(&ok, 10);
|
||||||
if (ok) {
|
if (ok) {
|
||||||
termTimeout = _termTimeout;
|
termTimeout = _termTimeout;
|
||||||
timeoutSet = true;
|
timeoutSet = true;
|
||||||
|
@ -315,9 +344,9 @@ int main(int argc, char *argv[])
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (unlikely(!envTimeout.isEmpty())) {
|
else if (!envTimeout.isEmpty()) {
|
||||||
bool ok;
|
bool ok;
|
||||||
const int _termTimeout = envTimeout.toInt(&ok);
|
const int _termTimeout = envTimeout.toInt(&ok, 10);
|
||||||
if (ok) {
|
if (ok) {
|
||||||
termTimeout = _termTimeout;
|
termTimeout = _termTimeout;
|
||||||
timeoutSet = true;
|
timeoutSet = true;
|
||||||
|
@ -328,14 +357,44 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unlikely(commandLineParser.isSet(processExecutable))) {
|
if (commandLineParser.isSet(processExecutable)) {
|
||||||
executable = commandLineParser.value(processExecutable);
|
executable = commandLineParser.value(processExecutable);
|
||||||
}
|
}
|
||||||
else if (unlikely(!envExecutable.isEmpty())) {
|
else if (!envExecutable.isEmpty()) {
|
||||||
executable = QString::fromUtf8(envExecutable);
|
executable = QString::fromUtf8(envExecutable);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unlikely(!envWorkDir.isEmpty())) {
|
if (commandLineParser.isSet(processAutoStart)) {
|
||||||
|
const QString claAutoStart = commandLineParser.value(processAutoStart);
|
||||||
|
if (claAutoStart == "0" || claAutoStart.toLower() == "false" || claAutoStart.toLower() == "no") {
|
||||||
|
autoStart = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!envAutoStart.isEmpty()) {
|
||||||
|
if (envAutoStart == "0" || envAutoStart.toLower() == "false" || envAutoStart.toLower() == "no") {
|
||||||
|
autoStart = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!envBuffReads.isEmpty()) {
|
||||||
|
if (envBuffReads == "1" || envBuffReads.toLower() == "true" || envBuffReads.toLower() == "yes") {
|
||||||
|
buffReads = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (commandLineParser.isSet(processKeepAlive)) {
|
||||||
|
const QString claKeepAlive = commandLineParser.value(processKeepAlive);
|
||||||
|
if (claKeepAlive == "1" || claKeepAlive.toLower() == "true" || claKeepAlive.toLower() == "yes") {
|
||||||
|
keepAlive = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!envKeepAlive.isEmpty()) {
|
||||||
|
if (envKeepAlive == "1" || envKeepAlive.toLower() == "true" || envKeepAlive.toLower() == "yes") {
|
||||||
|
keepAlive = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!envWorkDir.isEmpty()) {
|
||||||
workingDirectory = QString::fromUtf8(envWorkDir);
|
workingDirectory = QString::fromUtf8(envWorkDir);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -343,23 +402,23 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
QString manifestPath;
|
QString manifestPath;
|
||||||
if (likely(commandLineParser.isSet(processManifest))) {
|
if (commandLineParser.isSet(processManifest)) {
|
||||||
manifestPath = commandLineParser.value(processManifest);
|
manifestPath = commandLineParser.value(processManifest);
|
||||||
}
|
}
|
||||||
else if (!envManifest.isEmpty()) {
|
else if (!envManifest.isEmpty()) {
|
||||||
manifestPath = QString::fromUtf8(envManifest);
|
manifestPath = QString::fromUtf8(envManifest);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (likely(!manifestPath.isEmpty())) {
|
if (!manifestPath.isEmpty()) {
|
||||||
QFile manifestFile(manifestPath);
|
QFile manifestFile(manifestPath);
|
||||||
if (likely(manifestFile.open(QIODevice::ReadOnly))) {
|
if (manifestFile.open(QIODevice::ReadOnly)) {
|
||||||
const QByteArray jsonData = manifestFile.readAll();
|
const QByteArray jsonData = manifestFile.readAll();
|
||||||
QJsonDocument jsonDocument = QJsonDocument::fromJson(jsonData);
|
QJsonDocument jsonDocument = QJsonDocument::fromJson(jsonData);
|
||||||
QJsonObject jsonObject = jsonDocument.object();
|
QJsonObject jsonObject = jsonDocument.object();
|
||||||
|
|
||||||
if (likely(jsonObject.contains("Executable"))) {
|
if (jsonObject.contains("Executable")) {
|
||||||
const QJsonValue jsonExecutable = jsonObject.value("Executable");
|
const QJsonValue jsonExecutable = jsonObject.value("Executable");
|
||||||
if (unlikely(!jsonExecutable.isString())) {
|
if (!jsonExecutable.isString()) {
|
||||||
QTextStream(stderr) << "Executable is not a string in manifest, aborting!" << smsub_endl;
|
QTextStream(stderr) << "Executable is not a string in manifest, aborting!" << smsub_endl;
|
||||||
manifestFile.close();
|
manifestFile.close();
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -372,9 +431,29 @@ int main(int argc, char *argv[])
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (likely(jsonObject.contains("WorkingDirectory"))) {
|
if (jsonObject.contains("AutoStart")) {
|
||||||
|
const QJsonValue jsonAutoStart = jsonObject.value("AutoStart");
|
||||||
|
if (!jsonAutoStart.isBool()) {
|
||||||
|
QTextStream(stderr) << "AutoStart is not a bool in manifest, aborting!" << smsub_endl;
|
||||||
|
manifestFile.close();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
autoStart = jsonAutoStart.toBool();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (jsonObject.contains("KeepAlive")) {
|
||||||
|
const QJsonValue jsonKeepAlive = jsonObject.value("KeepAlive");
|
||||||
|
if (!jsonKeepAlive.isBool()) {
|
||||||
|
QTextStream(stderr) << "KeepAlive is not a bool in manifest, aborting!" << smsub_endl;
|
||||||
|
manifestFile.close();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
keepAlive = jsonKeepAlive.toBool();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (jsonObject.contains("WorkingDirectory")) {
|
||||||
const QJsonValue jsonWorkingDirectory = jsonObject.value("WorkingDirectory");
|
const QJsonValue jsonWorkingDirectory = jsonObject.value("WorkingDirectory");
|
||||||
if (unlikely(!jsonWorkingDirectory.isString())) {
|
if (!jsonWorkingDirectory.isString()) {
|
||||||
QTextStream(stderr) << "Working Directory is not a string in manifest, aborting!" << smsub_endl;
|
QTextStream(stderr) << "Working Directory is not a string in manifest, aborting!" << smsub_endl;
|
||||||
manifestFile.close();
|
manifestFile.close();
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -382,9 +461,9 @@ int main(int argc, char *argv[])
|
||||||
workingDirectory = jsonWorkingDirectory.toString();
|
workingDirectory = jsonWorkingDirectory.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (likely(jsonObject.contains("Arguments"))) {
|
if (jsonObject.contains("Arguments")) {
|
||||||
const QJsonValue jsonArguments = jsonObject.value("Arguments");
|
const QJsonValue jsonArguments = jsonObject.value("Arguments");
|
||||||
if (likely(jsonArguments.isArray())) {
|
if (jsonArguments.isArray()) {
|
||||||
const QJsonArray jsonArray = jsonArguments.toArray();
|
const QJsonArray jsonArray = jsonArguments.toArray();
|
||||||
for (auto it = jsonArray.constBegin(); it != jsonArray.constEnd(); it++) {
|
for (auto it = jsonArray.constBegin(); it != jsonArray.constEnd(); it++) {
|
||||||
argumentList << it->toString();
|
argumentList << it->toString();
|
||||||
|
@ -397,9 +476,9 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unlikely(!timeoutSet && jsonObject.contains("TerminationTimeout"))) {
|
if (!timeoutSet && jsonObject.contains("TerminationTimeout")) {
|
||||||
const QJsonValue jsonTimeout = jsonObject.value("TerminationTimeout");
|
const QJsonValue jsonTimeout = jsonObject.value("TerminationTimeout");
|
||||||
if (unlikely(!jsonTimeout.isDouble())) {
|
if (!jsonTimeout.isDouble()) {
|
||||||
termTimeout = qRound(jsonTimeout.toDouble());
|
termTimeout = qRound(jsonTimeout.toDouble());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -411,14 +490,14 @@ int main(int argc, char *argv[])
|
||||||
manifestFile.close();
|
manifestFile.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (unlikely(commandLineParser.isSet(processArguments))) {
|
else if (commandLineParser.isSet(processArguments)) {
|
||||||
argumentList = parseStringArguments(commandLineParser.value(processArguments));
|
argumentList = parseStringArguments(commandLineParser.value(processArguments));
|
||||||
if (argumentList.empty()) {
|
if (argumentList.empty()) {
|
||||||
QTextStream(stderr) << "Arguments can't be parsed properly!" << smsub_endl;
|
QTextStream(stderr) << "Arguments can't be parsed properly!" << smsub_endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (unlikely(!envArguments.isEmpty())) {
|
else if (!envArguments.isEmpty()) {
|
||||||
argumentList = parseStringArguments(QString::fromUtf8(envArguments));
|
argumentList = parseStringArguments(QString::fromUtf8(envArguments));
|
||||||
if (argumentList.empty()) {
|
if (argumentList.empty()) {
|
||||||
QTextStream(stderr) << "Arguments can't be parsed properly!" << smsub_endl;
|
QTextStream(stderr) << "Arguments can't be parsed properly!" << smsub_endl;
|
||||||
|
@ -426,7 +505,7 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (likely(commandLineParser.isSet(subprocessSocket))) {
|
if (commandLineParser.isSet(subprocessSocket)) {
|
||||||
socket = commandLineParser.value(subprocessSocket);
|
socket = commandLineParser.value(subprocessSocket);
|
||||||
}
|
}
|
||||||
else if (!envSocket.isEmpty()) {
|
else if (!envSocket.isEmpty()) {
|
||||||
|
@ -441,14 +520,14 @@ int main(int argc, char *argv[])
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unlikely(commandLineParser.isSet(subprocessRemoteSocket))) {
|
if (commandLineParser.isSet(subprocessRemoteSocket)) {
|
||||||
rsocket = commandLineParser.value(subprocessRemoteSocket);
|
rsocket = commandLineParser.value(subprocessRemoteSocket);
|
||||||
}
|
}
|
||||||
else if (unlikely(!envRemoteSocket.isEmpty())) {
|
else if (!envRemoteSocket.isEmpty()) {
|
||||||
rsocket = QString::fromUtf8(envRemoteSocket);
|
rsocket = QString::fromUtf8(envRemoteSocket);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unlikely(commandLineParser.isSet(subprocessRemotePort))) {
|
if (commandLineParser.isSet(subprocessRemotePort)) {
|
||||||
bool ok;
|
bool ok;
|
||||||
const quint16 _rport = commandLineParser.value(subprocessRemotePort).toUShort(&ok);
|
const quint16 _rport = commandLineParser.value(subprocessRemotePort).toUShort(&ok);
|
||||||
if (ok) {
|
if (ok) {
|
||||||
|
@ -478,7 +557,7 @@ int main(int argc, char *argv[])
|
||||||
localSettings.isLocal = true;
|
localSettings.isLocal = true;
|
||||||
|
|
||||||
SMSubServer subLocal(&localSettings, socket);
|
SMSubServer subLocal(&localSettings, socket);
|
||||||
if (unlikely(!subLocal.isListening())) {
|
if (!subLocal.isListening()) {
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
QTextStream(stderr) << "Failed to start local IPC socket!" << smsub_endl;
|
QTextStream(stderr) << "Failed to start local IPC socket!" << smsub_endl;
|
||||||
#else
|
#else
|
||||||
|
@ -487,15 +566,15 @@ int main(int argc, char *argv[])
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
SMSubProcess subProcess(executable, argumentList, workingDirectory, termTimeout);
|
SMSubProcess subProcess(executable, argumentList, workingDirectory, termTimeout, buffReads, keepAlive);
|
||||||
|
|
||||||
SMSubServerSettings remoteSettings;
|
SMSubServerSettings remoteSettings;
|
||||||
remoteSettings.canRegister = false;
|
remoteSettings.canRegister = false;
|
||||||
remoteSettings.isLocal = false;
|
remoteSettings.isLocal = false;
|
||||||
|
|
||||||
if (unlikely(!rsocket.isEmpty())) {
|
if (!rsocket.isEmpty()) {
|
||||||
SMSubServer *subRemote = new SMSubServer(&remoteSettings, rsocket);
|
SMSubServer *subRemote = new SMSubServer(&remoteSettings, rsocket);
|
||||||
if (unlikely(!subRemote->isListening())) {
|
if (!subRemote->isListening()) {
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
QTextStream(stderr) << "Failed to start remote IPC socket!" << smsub_endl;
|
QTextStream(stderr) << "Failed to start remote IPC socket!" << smsub_endl;
|
||||||
#else
|
#else
|
||||||
|
@ -506,34 +585,43 @@ int main(int argc, char *argv[])
|
||||||
localSettings.canRegister = true;
|
localSettings.canRegister = true;
|
||||||
QObject::connect(&subLocal, &SMSubServer::tokenRegistered, subRemote, &SMSubServer::registerToken);
|
QObject::connect(&subLocal, &SMSubServer::tokenRegistered, subRemote, &SMSubServer::registerToken);
|
||||||
QObject::connect(&subProcess, &SMSubProcess::outputWritten, subRemote, &SMSubServer::writeOutput);
|
QObject::connect(&subProcess, &SMSubProcess::outputWritten, subRemote, &SMSubServer::writeOutput);
|
||||||
|
QObject::connect(&subProcess, &SMSubProcess::statusUpdated, subRemote, &SMSubServer::statusUpdated);
|
||||||
QObject::connect(subRemote, &SMSubServer::inputWritten, &subProcess, &SMSubProcess::writeInput);
|
QObject::connect(subRemote, &SMSubServer::inputWritten, &subProcess, &SMSubProcess::writeInput);
|
||||||
QObject::connect(subRemote, &SMSubServer::killRequested, &subProcess, &SMSubProcess::killProcess);
|
QObject::connect(subRemote, &SMSubServer::startRequested, &subProcess, &SMSubProcess::startProcess);
|
||||||
QObject::connect(subRemote, &SMSubServer::stopRequested, &subProcess, &SMSubProcess::stopProcess);
|
QObject::connect(subRemote, &SMSubServer::stopRequested, &subProcess, &SMSubProcess::stopProcess);
|
||||||
|
QObject::connect(subRemote, &SMSubServer::killRequested, &subProcess, &SMSubProcess::killProcess);
|
||||||
}
|
}
|
||||||
else if (unlikely(rportSet)) {
|
else if (rportSet) {
|
||||||
SMSubServer *subRemote = new SMSubServer(&remoteSettings, QString(), rport);
|
SMSubServer *subRemote = new SMSubServer(&remoteSettings, QString(), rport);
|
||||||
if (unlikely(!subRemote->isListening())) {
|
if (!subRemote->isListening()) {
|
||||||
QTextStream(stderr) << "Failed to start remote WebSockets server!" << smsub_endl;
|
QTextStream(stderr) << "Failed to start remote WebSockets server!" << smsub_endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
localSettings.canRegister = true;
|
localSettings.canRegister = true;
|
||||||
QObject::connect(&subLocal, &SMSubServer::tokenRegistered, subRemote, &SMSubServer::registerToken);
|
QObject::connect(&subLocal, &SMSubServer::tokenRegistered, subRemote, &SMSubServer::registerToken);
|
||||||
QObject::connect(&subProcess, &SMSubProcess::outputWritten, subRemote, &SMSubServer::writeOutput);
|
QObject::connect(&subProcess, &SMSubProcess::outputWritten, subRemote, &SMSubServer::writeOutput);
|
||||||
|
QObject::connect(&subProcess, &SMSubProcess::statusUpdated, subRemote, &SMSubServer::statusUpdated);
|
||||||
QObject::connect(subRemote, &SMSubServer::inputWritten, &subProcess, &SMSubProcess::writeInput);
|
QObject::connect(subRemote, &SMSubServer::inputWritten, &subProcess, &SMSubProcess::writeInput);
|
||||||
QObject::connect(subRemote, &SMSubServer::killRequested, &subProcess, &SMSubProcess::killProcess);
|
QObject::connect(subRemote, &SMSubServer::startRequested, &subProcess, &SMSubProcess::startProcess);
|
||||||
QObject::connect(subRemote, &SMSubServer::stopRequested, &subProcess, &SMSubProcess::stopProcess);
|
QObject::connect(subRemote, &SMSubServer::stopRequested, &subProcess, &SMSubProcess::stopProcess);
|
||||||
|
QObject::connect(subRemote, &SMSubServer::killRequested, &subProcess, &SMSubProcess::killProcess);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
localSettings.canRegister = false;
|
localSettings.canRegister = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QObject::connect(&subProcess, &SMSubProcess::outputWritten, &subLocal, &SMSubServer::writeOutput);
|
QObject::connect(&subProcess, &SMSubProcess::outputWritten, &subLocal, &SMSubServer::writeOutput);
|
||||||
|
QObject::connect(&subProcess, &SMSubProcess::statusUpdated, &subLocal, &SMSubServer::statusUpdated);
|
||||||
QObject::connect(&subLocal, &SMSubServer::inputWritten, &subProcess, &SMSubProcess::writeInput);
|
QObject::connect(&subLocal, &SMSubServer::inputWritten, &subProcess, &SMSubProcess::writeInput);
|
||||||
QObject::connect(&subLocal, &SMSubServer::killRequested, &subProcess, &SMSubProcess::killProcess);
|
QObject::connect(&subLocal, &SMSubServer::startRequested, &subProcess, &SMSubProcess::startProcess);
|
||||||
QObject::connect(&subLocal, &SMSubServer::stopRequested, &subProcess, &SMSubProcess::stopProcess);
|
QObject::connect(&subLocal, &SMSubServer::stopRequested, &subProcess, &SMSubProcess::stopProcess);
|
||||||
|
QObject::connect(&subLocal, &SMSubServer::killRequested, &subProcess, &SMSubProcess::killProcess);
|
||||||
QObject::connect(&a, &QCoreApplication::aboutToQuit, &subProcess, &SMSubProcess::aboutToQuit);
|
QObject::connect(&a, &QCoreApplication::aboutToQuit, &subProcess, &SMSubProcess::aboutToQuit);
|
||||||
|
|
||||||
subProcess.start();
|
if (autoStart)
|
||||||
|
subProcess.startProcess();
|
||||||
|
|
||||||
|
QTextStream(stderr) << QString("SMSub Version %1 initialized!").arg(QCoreApplication::applicationVersion()) << smsub_endl;
|
||||||
|
|
||||||
return a.exec();
|
return a.exec();
|
||||||
}
|
}
|
||||||
|
|
20
smsub.h
20
smsub.h
|
@ -1,6 +1,6 @@
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* smsub Server Manager Subprocess
|
* smsub Server Manager Subprocess
|
||||||
* Copyright (C) 2020-2021 Syping
|
* Copyright (C) 2020-2023 Syping
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
* are permitted provided that the following conditions are met:
|
* are permitted provided that the following conditions are met:
|
||||||
|
@ -20,23 +20,7 @@
|
||||||
#define SMSUB_H
|
#define SMSUB_H
|
||||||
#include <QtGlobal>
|
#include <QtGlobal>
|
||||||
|
|
||||||
#ifndef SMSUB_WITHOUT_EXPECT
|
#if QT_VERSION >= 0x050F00
|
||||||
#ifndef likely
|
|
||||||
#define likely(x) __builtin_expect((x),1)
|
|
||||||
#endif
|
|
||||||
#ifndef unlikely
|
|
||||||
#define unlikely(x) __builtin_expect((x),0)
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
#ifndef likely
|
|
||||||
#define likely(x) (x)
|
|
||||||
#endif
|
|
||||||
#ifndef unlikely
|
|
||||||
#define unlikely(x) (x)
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
|
|
||||||
#define smsub_endl Qt::endl
|
#define smsub_endl Qt::endl
|
||||||
#else
|
#else
|
||||||
#define smsub_endl endl
|
#define smsub_endl endl
|
||||||
|
|
Loading…
Reference in a new issue