From 1ddc4ff755484dd850dc45de16c0eac81fa1b73a Mon Sep 17 00:00:00 2001 From: Syping Date: Tue, 7 May 2024 17:29:23 +0200 Subject: [PATCH] add BufferedReads, add AutoStart and KeepAlive command line options --- CMakeLists.txt | 2 +- SMSubProcess.cpp | 33 ++++++++++++++++++--------------- SMSubProcess.h | 3 ++- SMSubServer.cpp | 33 +++++++++++++++++---------------- main.cpp | 48 ++++++++++++++++++++++++++++++++++++++++-------- 5 files changed, 78 insertions(+), 41 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bf8df83..9486a27 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.5) -project(smsub LANGUAGES CXX VERSION 0.8) +project(smsub LANGUAGES CXX VERSION 0.9) set(CMAKE_INCLUDE_CURRENT_DIR ON) diff --git a/SMSubProcess.cpp b/SMSubProcess.cpp index e9016c6..9b19b51 100644 --- a/SMSubProcess.cpp +++ b/SMSubProcess.cpp @@ -22,8 +22,8 @@ #include "SMSubProcess.h" #include "smsub.h" -SMSubProcess::SMSubProcess(const QString &executable, const QStringList &arguments, const QString &workingDirectory, const int &termTimeout, const bool &keepAlive) : - termTimeout(termTimeout), keepAlive(keepAlive) +SMSubProcess::SMSubProcess(const QString &executable, const QStringList &arguments, const QString &workingDirectory, const int termTimeout, const bool buffReads, const bool keepAlive) : + termTimeout(termTimeout), buffReads(buffReads), keepAlive(keepAlive) { // Set process executable, arguments and working directory process.setProgram(executable); @@ -33,7 +33,7 @@ SMSubProcess::SMSubProcess(const QString &executable, const QStringList &argumen // manage input channel process.setInputChannelMode(QProcess::ManagedInputChannel); - // stdout and stderr in same IO stream + // stdout and stderr in same I/O stream process.setProcessChannelMode(QProcess::MergedChannels); // Connect process signal handlers @@ -58,22 +58,25 @@ void SMSubProcess::readyRead() QTextStream(stderr) << "Subprocess I/O RR!" << smsub_endl; #endif // Read process output and emit event -#ifdef SMSUB_BUFFERED_READS + if (buffReads) { + while (process.bytesAvailable()) { #ifdef SMSUB_IODEBUG - QTextStream(stderr) << "Subprocess I/O W!" << smsub_endl; + 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'); + 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) diff --git a/SMSubProcess.h b/SMSubProcess.h index 568cf9a..0402192 100644 --- a/SMSubProcess.h +++ b/SMSubProcess.h @@ -26,11 +26,12 @@ class SMSubProcess : public QObject { Q_OBJECT public: - SMSubProcess(const QString &executable, const QStringList &arguments, const QString &workingDirectory, const int &termTimeout = 60000, const bool &keepAlive = false); + SMSubProcess(const QString &executable, const QStringList &arguments, const QString &workingDirectory, const int termTimeout = 60000, const bool buffReads = false, const bool keepAlive = false); private: QProcess process; int termTimeout; + bool buffReads; bool keepAlive; public slots: diff --git a/SMSubServer.cpp b/SMSubServer.cpp index 3e8402a..d08f727 100644 --- a/SMSubServer.cpp +++ b/SMSubServer.cpp @@ -79,7 +79,7 @@ void SMSubServer::newConnection() QObject::connect(webSocket, &QWebSocket::disconnected, this, &SMSubServer::deleteSocket); webSocket->sendBinaryMessage(QString("SMSub Version %1\n").arg(QCoreApplication::applicationVersion()).toUtf8()); socket = webSocket; - QTextStream(stderr) << QString("WebSocket %1:%2 connected!").arg(webSocket->peerName(), QString::number(webSocket->peerPort())) << smsub_endl; + QTextStream(stderr) << QString("WebSocket %1:%2 connected!").arg(webSocket->peerAddress().toString(), QString::number(webSocket->peerPort())) << smsub_endl; } else { // Just for being sure @@ -101,25 +101,26 @@ bool SMSubServer::messageReceived(QObject *socket, const QByteArray &message) // Only allow commands being sent if authenticated const bool isAuthenticated = socket->property("Authenticated").toBool(); if (Q_LIKELY(isAuthenticated)) { - if (message.startsWith("+dbg")) { + if (message == "+dbg") { socket->setProperty("ReceiveDbgMsg", true); sendMessage(socket, "Debug messages enabled!\n"); } - else if (message.startsWith("-dbg")) { + else if (message == "-dbg") { socket->setProperty("ReceiveDbgMsg", false); sendMessage(socket, "Debug messages disabled!\n"); } - else if (message.startsWith("+log")) { + else if (message == "+log") { socket->setProperty("ReceiveLog", true); debugOutput(socket, "Log output enabled!"); } - else if (message.startsWith("-log")) { + else if (message == "-log") { socket->setProperty("ReceiveLog", false); debugOutput(socket, "Log output disabled!"); } - else if (message.startsWith("+reg")) { + else if (message == "+reg") { if (Q_LIKELY(serverSettings->canRegister)) { - QByteArray authUuid = QUuid::createUuid().toByteArray(QUuid::Id128); + QByteArray authUuid = QUuid::createUuid().toByteArray(QUuid::Id128) + + QUuid::createUuid().toByteArray(QUuid::Id128); authUuid = QByteArray::fromHex(authUuid).toBase64(QByteArray::OmitTrailingEquals); emit tokenRegistered(QString::fromUtf8(authUuid)); sendMessage(socket, "Token: " + authUuid + '\n'); @@ -128,7 +129,7 @@ bool SMSubServer::messageReceived(QObject *socket, const QByteArray &message) sendMessage(socket, "Permission denied!\n"); } } - else if (message.startsWith("status")) { + else if (message == "status") { if (status) { sendMessage(socket, QString("Status: on\nLast Start: %1\nLast Stop: %2\n").arg(QString::number(startTime), QString::number(stopTime)).toUtf8()); } @@ -136,31 +137,31 @@ bool SMSubServer::messageReceived(QObject *socket, const QByteArray &message) sendMessage(socket, QString("Status: off\nLast Start: %1\nLast Stop: %2\n").arg(QString::number(startTime), QString::number(stopTime)).toUtf8()); } } - else if (message.startsWith("start")) { + else if (message == "start") { emit startRequested(); debugOutput(socket, "Starting server!"); } - else if (message.startsWith("stop")) { + else if (message == "stop") { emit stopRequested(); debugOutput(socket, "Stopping server!"); } - else if (message.startsWith("kill")) { + else if (message == "kill") { emit killRequested(); debugOutput(socket, "Killing server!"); } - else if (message.startsWith("quit")) { + else if (message == "quit") { QTimer::singleShot(0, qApp, &QCoreApplication::quit); debugOutput(socket, "Qutting smsub!"); } - else if (message.startsWith("wl")) { + else if (message.startsWith("wl ")) { const QByteArray writeData = message.mid(3); emit inputWritten(writeData + '\n'); - debugOutput(socket, "Write line \"" + writeData + "\"!"); + debugOutput(socket, "Write line: " + writeData); } - else if (message.startsWith("w")) { + else if (message.startsWith("w ")) { const QByteArray writeData = message.mid(2); emit inputWritten(writeData); - debugOutput(socket, "Write \"" + writeData + "\"!"); + debugOutput(socket, "Write: " + writeData); } } else { diff --git a/main.cpp b/main.cpp index adf5f7b..3b52d92 100644 --- a/main.cpp +++ b/main.cpp @@ -134,7 +134,7 @@ int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); a.setApplicationName("Server Manager Subprocess"); - a.setApplicationVersion("0.8"); + a.setApplicationVersion("0.9"); #ifdef Q_OS_UNIX catchUnixSignals({SIGINT, SIGHUP, SIGQUIT, SIGTERM}); @@ -142,9 +142,10 @@ int main(int argc, char *argv[]) bool rportSet = false; bool autoStart = true; + bool buffReads = false; bool keepAlive = false; bool timeoutSet = false; - int termTimeout = 60000; + size_t termTimeout = 60000; quint16 rport; QString socket; QString rsocket; @@ -154,6 +155,7 @@ int main(int argc, char *argv[]) const QByteArray envEnvironmentMode = qgetenv("SMSUB_ENVIRONMENT_MODE"); const QByteArray envAutoStart = qgetenv("SMSUB_AUTOSTART"); + const QByteArray envBuffReads = qgetenv("SMSUB_BUFFERED_READS"); const QByteArray envKeepAlive = qgetenv("SMSUB_KEEPALIVE"); const QByteArray envManifest = qgetenv("SMSUB_JSON"); const QByteArray envExecutable = qgetenv("SMSUB_EXEC"); @@ -212,6 +214,12 @@ int main(int argc, char *argv[]) } } + 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; @@ -285,6 +293,12 @@ int main(int argc, char *argv[]) #endif commandLineParser.addOption(subprocessRemoteSocket); + QCommandLineOption processAutoStart("autostart", "SMSub autostart mode setting.", "autostart"); + commandLineParser.addOption(processAutoStart); + + QCommandLineOption processKeepAlive("keepalive", "SMSub keepalive mode setting.", "keepalive"); + commandLineParser.addOption(processKeepAlive); + QCommandLineOption processTimeout("timeout", "SMSub termination timeout.", "timeout"); commandLineParser.addOption(processTimeout); @@ -302,7 +316,7 @@ int main(int argc, char *argv[]) !envManifest.isEmpty() && !envArguments.isEmpty() || commandLineParser.isSet(processManifest) && !envArguments.isEmpty() || !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; } @@ -320,7 +334,7 @@ int main(int argc, char *argv[]) if (commandLineParser.isSet(processTimeout)) { bool ok; - const int _termTimeout = commandLineParser.value(processTimeout).toInt(&ok); + const int _termTimeout = commandLineParser.value(processTimeout).toInt(&ok, 10); if (ok) { termTimeout = _termTimeout; timeoutSet = true; @@ -332,7 +346,7 @@ int main(int argc, char *argv[]) } else if (!envTimeout.isEmpty()) { bool ok; - const int _termTimeout = envTimeout.toInt(&ok); + const int _termTimeout = envTimeout.toInt(&ok, 10); if (ok) { termTimeout = _termTimeout; timeoutSet = true; @@ -350,13 +364,31 @@ int main(int argc, char *argv[]) executable = QString::fromUtf8(envExecutable); } - if (!envAutoStart.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 (!envKeepAlive.isEmpty()) { + 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 != "0" || claKeepAlive.toLower() != "false" || claKeepAlive.toLower() != "no") { + keepAlive = true; + } + } + else if (!envKeepAlive.isEmpty()) { if (envKeepAlive == "1" || envKeepAlive.toLower() == "true" || envKeepAlive.toLower() == "yes") { keepAlive = true; } @@ -534,7 +566,7 @@ int main(int argc, char *argv[]) return 1; } - SMSubProcess subProcess(executable, argumentList, workingDirectory, termTimeout, keepAlive); + SMSubProcess subProcess(executable, argumentList, workingDirectory, termTimeout, buffReads, keepAlive); SMSubServerSettings remoteSettings; remoteSettings.canRegister = false;