File indexing completed on 2024-05-12 05:51:07

0001 /*
0002     SPDX-FileCopyrightText: 2022 Héctor Mesa Jiménez <wmj.py@gmx.com>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "settings.h"
0008 
0009 #include <QTimer>
0010 #include <memory>
0011 
0012 #include "dapclient_debug.h"
0013 #include "socketprocessbus.h"
0014 
0015 constexpr int TIMEOUT = 1000;
0016 
0017 namespace dap
0018 {
0019 SocketProcessBus::SocketProcessBus(QObject *parent)
0020     : Bus(parent)
0021 {
0022     connect(&socket, &QTcpSocket::readyRead, this, &Bus::readyRead);
0023     connect(&socket, &QTcpSocket::stateChanged, this, &SocketProcessBus::onSocketStateChanged);
0024     connect(&process, &QProcess::stateChanged, this, &SocketProcessBus::onProcessStateChanged);
0025 
0026     connect(&process, &QProcess::readyReadStandardError, this, &SocketProcessBus::readError);
0027     connect(&process, &QProcess::readyReadStandardOutput, this, &SocketProcessBus::readOutput);
0028 }
0029 
0030 SocketProcessBus::~SocketProcessBus()
0031 {
0032     blockSignals(true);
0033     if (socket.state() == QTcpSocket::SocketState::ConnectedState) {
0034         socket.close();
0035     }
0036     bool finished = process.state() == QProcess::NotRunning;
0037     if (!finished) {
0038         process.terminate();
0039         finished = process.waitForFinished(500);
0040     }
0041     if (!finished) {
0042         process.kill();
0043         process.waitForFinished(300);
0044     }
0045 }
0046 
0047 QByteArray SocketProcessBus::read()
0048 {
0049     return socket.readAll();
0050 }
0051 
0052 quint16 SocketProcessBus::write(const QByteArray &data)
0053 {
0054     return socket.write(data);
0055 }
0056 
0057 bool SocketProcessBus::start(const settings::BusSettings &configuration)
0058 {
0059     if (!configuration.hasConnection() || !configuration.hasCommand())
0060         return false;
0061 
0062     const auto &connection = configuration.connection.value();
0063 
0064     m_connectionHandler.reset();
0065     m_connectionHandler = [this, connection]() {
0066         this->socket.connectToHost(connection.host, connection.port);
0067     };
0068 
0069     configuration.command->start(process);
0070 
0071     return true;
0072 }
0073 
0074 void SocketProcessBus::closeResources()
0075 {
0076     qCDebug(DAPCLIENT) << "[BUS] closing resources";
0077     if (socket.state() == QTcpSocket::SocketState::ConnectedState) {
0078         socket.close();
0079     }
0080     if (process.state() != QProcess::NotRunning) {
0081         if (m_tryClose == None) {
0082             m_tryClose = Terminate;
0083             process.terminate();
0084         } else if (m_tryClose == None) {
0085             m_tryClose = Kill;
0086             process.kill();
0087         } else {
0088             process.waitForFinished(500);
0089         }
0090     }
0091 }
0092 
0093 void SocketProcessBus::onSocketStateChanged(const QAbstractSocket::SocketState &state)
0094 {
0095     qCDebug(DAPCLIENT) << "SOCKET STATE " << state;
0096 
0097     const bool socketError = socket.error() != QAbstractSocket::SocketError::UnknownSocketError;
0098     if (socketError)
0099         qCDebug(DAPCLIENT) << socket.errorString();
0100 
0101     if (state == QTcpSocket::SocketState::ConnectedState) {
0102         m_connectionHandler.reset();
0103         setState(State::Running);
0104         return;
0105     }
0106     if (socketError) {
0107         Q_EMIT error(process.errorString());
0108         close();
0109     }
0110 }
0111 
0112 void SocketProcessBus::onProcessStateChanged(const QProcess::ProcessState &state)
0113 {
0114     qCDebug(DAPCLIENT) << "PROCESS STATE " << state;
0115 
0116     const bool processError = process.error() != QProcess::ProcessError::UnknownError;
0117     if (processError) {
0118         Q_EMIT error(process.errorString());
0119         close();
0120         return;
0121     }
0122     switch (state) {
0123     case QProcess::ProcessState::Running:
0124         QTimer::singleShot(TIMEOUT, this, &SocketProcessBus::connectSocket);
0125         break;
0126     case QProcess::ProcessState::NotRunning:
0127         close();
0128         break;
0129     default:;
0130     }
0131 }
0132 
0133 void SocketProcessBus::connectSocket()
0134 {
0135     qCDebug(DAPCLIENT) << "connect to socket INIT";
0136     if (!m_connectionHandler)
0137         return;
0138     qCDebug(DAPCLIENT) << "connect to socket with handler";
0139     (*m_connectionHandler)();
0140 }
0141 
0142 void SocketProcessBus::close()
0143 {
0144     closeResources();
0145     setState(State::Closed);
0146 }
0147 
0148 void SocketProcessBus::readError()
0149 {
0150     const auto &message = process.readAllStandardError();
0151     // process' standard error
0152     qCDebug(DAPCLIENT) << "[BUS] STDERR << " << message;
0153 
0154     Q_EMIT serverOutput(QString::fromLocal8Bit(message));
0155 }
0156 
0157 void SocketProcessBus::readOutput()
0158 {
0159     const auto &message = process.readAllStandardOutput();
0160     qCDebug(DAPCLIENT) << "[BUS] STDOUT << " << message;
0161 
0162     Q_EMIT processOutput(QString::fromLocal8Bit(message));
0163 }
0164 
0165 }
0166 
0167 #include "moc_socketprocessbus.cpp"