#include "cmd_object.h" // This file is part of MRCI. // MRCI is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // MRCI is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with MRCI under the LICENSE.md file. If not, see // . IPCWorker::IPCWorker(const QString &pipe, QObject *parent) : QObject(parent) { pipeName = pipe; idleTimer = new IdleTimer(this); ipcSocket = new QLocalSocket(this); flags = 0; connect(ipcSocket, &QLocalSocket::readyRead, this, &IPCWorker::rdFromIPC); connect(ipcSocket, &QLocalSocket::disconnected, this, &IPCWorker::ipcClosed); connect(ipcSocket, &QLocalSocket::connected, this, &IPCWorker::ipcOpened); connect(idleTimer, &IdleTimer::timeout, this, &IPCWorker::termProc); idleTimer->attach(ipcSocket, 60000); //1min idle timeout } void IPCWorker::rdFromIPC() { if (flags & FRAME_RDY) { if (ipcSocket->bytesAvailable() >= ipcDataSize) { emit dataOut(ipcSocket->read(ipcDataSize), ipcTypeId); flags ^= FRAME_RDY; rdFromIPC(); } } else if (ipcSocket->bytesAvailable() >= (FRAME_HEADER_SIZE - 4)) { QByteArray header = ipcSocket->read(FRAME_HEADER_SIZE - 4); ipcTypeId = static_cast(header[0]); ipcDataSize = static_cast(rdInt(header.mid(1, 3))); flags |= FRAME_RDY; rdFromIPC(); } } void IPCWorker::dataIn(const QByteArray &data, quint8 typeId) { // format: [typeId][payload_len][payload] ipcSocket->write(wrInt(typeId, 8) + wrInt(data.size(), MAX_FRAME_BITS) + data); } void IPCWorker::connectIPC() { ipcSocket->connectToServer(pipeName); } CmdObject::CmdObject(QObject *parent) : MemShare(parent) { flags = 0; QStringList args = QCoreApplication::instance()->arguments(); QString pipe = getParam("-pipe_name", args); QString sMemKey = getParam("-mem_ses", args); QString hMemKey = getParam("-mem_host", args); if (attachSharedMem(sMemKey, hMemKey)) { ipcWorker = new IPCWorker(pipe, nullptr); keepAliveTimer = new QTimer(this); auto *thr = new QThread(nullptr); serializeThread(thr); setupDataBlocks(); connect(thr, &QThread::started, ipcWorker, &IPCWorker::connectIPC); connect(this, &CmdObject::destroyed, thr, &QThread::deleteLater); connect(this, &CmdObject::procOut, ipcWorker, &IPCWorker::dataIn); connect(keepAliveTimer, &QTimer::timeout, this, &CmdObject::keepAlive); connect(ipcWorker, &IPCWorker::dataOut, this, &CmdObject::preProc); connect(ipcWorker, &IPCWorker::termProc, this, &CmdObject::kill); connect(ipcWorker, &IPCWorker::ipcClosed, this, &CmdObject::term); connect(ipcWorker, &IPCWorker::ipcOpened, this, &CmdObject::onIPCConnected); keepAliveTimer->setSingleShot(false); keepAliveTimer->setInterval(30000); //30sec keep alive ipcWorker->moveToThread(thr); thr->start(); } else { kill(); } } void CmdObject::term() { if (flags & (MORE_INPUT | HALT_STATE | LOOPING)) { flags = 0; postProc(); } } void CmdObject::kill() { term(); QCoreApplication::instance()->exit(); } void CmdObject::preProc(const QByteArray &data, quint8 typeId) { if (typeId == TERM_CMD) { term(); } else if (typeId == KILL_CMD) { kill(); } else if (typeId == HALT_CMD) { if (flags & LOOPING) { flags |= HALT_STATE; flags &= ~LOOPING; } } else if (typeId == RESUME_CMD) { if (flags & HALT_STATE) { flags |= LOOPING; flags &= ~HALT_STATE; } } else { sharedMem->lock(); procIn(data, typeId); sharedMem->unlock(); postProc(); } } void CmdObject::postProc() { if (flags & LOOPING) { preProc(QByteArray(), TEXT); } else if (flags & (MORE_INPUT | HALT_STATE)) { keepAliveTimer->start(); } else { keepAliveTimer->stop(); emit procOut(QByteArray(), IDLE); } } void CmdObject::mainTxt(const QString &txt) { emit procOut(toTEXT(txt), TEXT); } void CmdObject::errTxt(const QString &txt) { emit procOut(toTEXT(txt), ERR); } void CmdObject::privTxt(const QString &txt) { emit procOut(toTEXT(txt), PRIV_TEXT); } void CmdObject::bigTxt(const QString &txt) { emit procOut(toTEXT(txt), BIG_TEXT); } void CmdObject::async(quint16 asyncId, quint8 asyncType, const QByteArray &data) { emit procOut(wrInt(asyncId, 16) + data, asyncType); } void CmdObject::keepAlive() { async(ASYNC_KEEP_ALIVE, PRIV_IPC); } QString CmdObject::libName() { return QCoreApplication::applicationName() + " v" + QCoreApplication::applicationVersion() + " " + QString::number(QSysInfo::WordSize) + "Bit"; }