330 lines
6.9 KiB
C++
Executable File
330 lines
6.9 KiB
C++
Executable File
|
|
|
|
|
|
#include "commandinterface.h"
|
|
#include "workerbase.h"
|
|
#include "tcpserver.h"
|
|
#include "tcpserver_logger.h"
|
|
|
|
#include <QtCore/QDebug>
|
|
#include <QtCore/QStringList>
|
|
#include <QtNetwork/QAbstractSocket>
|
|
|
|
class CommandInterface::Private
|
|
{
|
|
public:
|
|
explicit Private(unsigned short port_, const QByteArray &command_)
|
|
: command(command_)
|
|
, port(port_)
|
|
{}
|
|
|
|
QByteArray m_connString;
|
|
QByteArray command;
|
|
QAbstractSocket *dev = nullptr;
|
|
WorkerBase *wb = nullptr;
|
|
int writeTimeout = 1000;
|
|
unsigned short port;
|
|
bool autoWriteEOL = true;
|
|
bool bWriteError = false;
|
|
bool closeConnection = false;
|
|
|
|
static QByteArray defaultSuccessMessage;
|
|
static QByteArray defaultErrorMessage;
|
|
};
|
|
QByteArray CommandInterface::Private::defaultSuccessMessage("OK");
|
|
QByteArray CommandInterface::Private::defaultErrorMessage("ERROR");
|
|
|
|
CommandInterface::CommandInterface(unsigned short port, const QByteArray &command)
|
|
: d(new Private(port, command))
|
|
{}
|
|
|
|
CommandInterface::~CommandInterface()
|
|
{
|
|
delete d;
|
|
}
|
|
|
|
void CommandInterface::handleCommand(const QVector<QByteArray> &args)
|
|
{
|
|
Q_ASSERT(d->dev);
|
|
d->bWriteError = false;
|
|
d->closeConnection = false;
|
|
d->m_connString = WorkerBase::formatForDebug(d->dev);
|
|
handleCommandInternal(args);
|
|
if (d->autoWriteEOL)
|
|
writeEOL();
|
|
d->dev->flush();
|
|
if (d->closeConnection)
|
|
{
|
|
|
|
d->dev->disconnectFromHost();
|
|
|
|
d->dev = nullptr;
|
|
}
|
|
}
|
|
|
|
void CommandInterface::newPlainData()
|
|
{
|
|
Q_ASSERT(false);
|
|
TCPSERVER_ERROR("CommandInterface::newData called which should never happen!");
|
|
}
|
|
|
|
void CommandInterface::writeData(const char *payload)
|
|
{
|
|
writeData(QByteArray::fromRawData(payload, strlen(payload)));
|
|
}
|
|
|
|
void CommandInterface::writeData(const QByteArray &payload)
|
|
{
|
|
Q_ASSERT(d->dev);
|
|
|
|
if (!d->dev->isOpen())
|
|
return;
|
|
|
|
if (!payload.size())
|
|
return;
|
|
|
|
TCPSERVER_DEBUG("Sending \'" << WorkerBase::formatForDebug(payload).constData()
|
|
<< "\' (" << payload.size() << " Bytes) to "
|
|
<< d->m_connString.constData())
|
|
|
|
qint64 bytesToWrite = payload.size();
|
|
qint64 bytesWritten = 0;
|
|
do
|
|
{
|
|
bytesWritten += d->dev->write(&payload.data()[bytesWritten], bytesToWrite - bytesWritten);
|
|
if (!d->dev->waitForBytesWritten(d->writeTimeout))
|
|
{
|
|
TCPSERVER_ERROR("waitForBytesWritten returned false for connection "
|
|
<< d->m_connString.constData()
|
|
<< " "
|
|
<< d->dev->error()
|
|
<< " "
|
|
<< d->dev->errorString())
|
|
d->bWriteError = true;
|
|
return;
|
|
}
|
|
}
|
|
while (bytesToWrite != bytesWritten);
|
|
}
|
|
|
|
void CommandInterface::writeData(const QString &payload)
|
|
{
|
|
writeData(payload.toUtf8());
|
|
}
|
|
|
|
void CommandInterface::writeData(const QList<QByteArray> &payload)
|
|
{
|
|
QByteArray cmd;
|
|
for (QByteArray s : payload)
|
|
{
|
|
s.replace('\"', "\\\"");
|
|
if (s.contains(' '))
|
|
s = '"' + s + '"';
|
|
cmd += s + ' ';
|
|
}
|
|
writeData(cmd);
|
|
}
|
|
|
|
void CommandInterface::writeData(const QStringList &payload)
|
|
{
|
|
QList<QByteArray> baList;
|
|
baList.reserve(payload.size());
|
|
for (const QString &ba : payload)
|
|
baList += ba.toUtf8();
|
|
writeData(baList);
|
|
}
|
|
|
|
void CommandInterface::writeOk(const QString &additionalMsg)
|
|
{
|
|
writeData(Private::defaultSuccessMessage);
|
|
if (!additionalMsg.isEmpty())
|
|
{
|
|
writeData(" ");
|
|
writeData(additionalMsg);
|
|
}
|
|
}
|
|
|
|
void CommandInterface::writeError(const QString &additionalMsg)
|
|
{
|
|
writeData(Private::defaultErrorMessage);
|
|
if (!additionalMsg.isEmpty())
|
|
{
|
|
writeData(" ");
|
|
writeData(additionalMsg);
|
|
}
|
|
}
|
|
|
|
void CommandInterface::writeEOL()
|
|
{
|
|
writeData("\n");
|
|
|
|
Q_ASSERT(d->dev);
|
|
d->dev->flush();
|
|
}
|
|
|
|
QByteArray CommandInterface::quote(const QByteArray &payload)
|
|
{
|
|
static const QByteArray escapedQuote("\"");
|
|
int idx = payload.indexOf(' ');
|
|
if (idx < 0)
|
|
return payload;
|
|
QByteArray ret = payload;
|
|
return escapedQuote + ret.replace('\"', "\\\"") + escapedQuote;
|
|
}
|
|
|
|
QAbstractSocket *CommandInterface::socket()
|
|
{
|
|
return d->dev;
|
|
}
|
|
void CommandInterface::setSocket(QAbstractSocket *socket)
|
|
{
|
|
d->dev = socket;
|
|
}
|
|
|
|
WorkerBase *CommandInterface::workerBase()
|
|
{
|
|
return d->wb;
|
|
}
|
|
|
|
void CommandInterface::setWorkerBase(WorkerBase *wb)
|
|
{
|
|
d->wb = wb;
|
|
}
|
|
|
|
QByteArray CommandInterface::command() const
|
|
{
|
|
return d->command;
|
|
}
|
|
|
|
void CommandInterface::setWriteTimeout(int iMS)
|
|
{
|
|
d->writeTimeout = iMS < 0 ? 1000 : iMS;
|
|
}
|
|
|
|
void CommandInterface::setAutoWriteEOL(bool newAutoWriteEOL)
|
|
{
|
|
d->autoWriteEOL = newAutoWriteEOL;
|
|
}
|
|
|
|
bool CommandInterface::autoWriteEOL() const
|
|
{
|
|
return d->autoWriteEOL;
|
|
}
|
|
|
|
bool CommandInterface::errorOccured() const
|
|
{
|
|
return d->bWriteError;
|
|
}
|
|
|
|
void CommandInterface::setDefaultSuccessMessage(const QString &msg)
|
|
{
|
|
Private::defaultSuccessMessage = msg.isEmpty() ? "OK" : msg.toUtf8();
|
|
}
|
|
|
|
void CommandInterface::setDefaultErrorMessage(const QString &msg)
|
|
{
|
|
Private::defaultErrorMessage = msg.isEmpty() ? "ERROR" : msg.toUtf8();
|
|
}
|
|
|
|
unsigned short CommandInterface::port() const
|
|
{
|
|
return d->port;
|
|
}
|
|
|
|
void CommandInterface::closeConnection()
|
|
{
|
|
d->closeConnection = true;
|
|
}
|
|
|
|
bool CommandInterface::socketIsOpen() const
|
|
{
|
|
return d->dev && d->dev->isOpen();
|
|
}
|
|
|
|
void CommandInterface::conversionError(const QByteArray &arg, const QByteArray &type)
|
|
{
|
|
writeError(QLatin1String("Can not convert ") + QString::fromUtf8(arg) +
|
|
QLatin1String(" to ") + QString::fromUtf8(type));
|
|
}
|
|
|
|
bool CommandInterface::getValue(const QByteArray &arg, bool &value)
|
|
{
|
|
bool bOk;
|
|
int intValue;
|
|
|
|
if (arg.startsWith("0x"))
|
|
intValue = arg.mid(2).toInt(&bOk, 16);
|
|
else
|
|
intValue = arg.toInt(&bOk);
|
|
if (!bOk)
|
|
conversionError(arg, "bool");
|
|
value = (intValue != 0);
|
|
return bOk;
|
|
}
|
|
|
|
bool CommandInterface::getValue(const QByteArray &arg, long &value)
|
|
{
|
|
bool bOk;
|
|
if (arg.startsWith("0x"))
|
|
value = arg.mid(2).toLong(&bOk, 16);
|
|
else
|
|
value = arg.toLong(&bOk);
|
|
if (!bOk)
|
|
conversionError(arg, "long");
|
|
return bOk;
|
|
}
|
|
|
|
bool CommandInterface::getValue(const QByteArray &arg, unsigned long &value)
|
|
{
|
|
bool bOk;
|
|
if (arg.startsWith("0x"))
|
|
value = arg.mid(2).toULong(&bOk, 16);
|
|
else
|
|
value = arg.toUInt(&bOk);
|
|
if (!bOk)
|
|
conversionError(arg, "unsigned long");
|
|
return bOk;
|
|
}
|
|
|
|
bool CommandInterface::getValue(const QByteArray &arg, int &value)
|
|
{
|
|
bool bOk;
|
|
if (arg.startsWith("0x"))
|
|
value = arg.mid(2).toInt(&bOk, 16);
|
|
else
|
|
value = arg.toInt(&bOk);
|
|
if (!bOk)
|
|
conversionError(arg, "int");
|
|
return bOk;
|
|
}
|
|
|
|
bool CommandInterface::getValue(const QByteArray &arg, unsigned int &value)
|
|
{
|
|
bool bOk;
|
|
if (arg.startsWith("0x"))
|
|
value = arg.mid(2).toUInt(&bOk, 16);
|
|
else
|
|
value = arg.toUInt(&bOk);
|
|
if (!bOk)
|
|
conversionError(arg, "unsigned int");
|
|
return bOk;
|
|
}
|
|
|
|
bool CommandInterface::getValue(const QByteArray &arg, float &value)
|
|
{
|
|
bool bOk;
|
|
value = arg.toFloat(&bOk);
|
|
if (!bOk)
|
|
conversionError(arg, "float");
|
|
return bOk;
|
|
}
|
|
|
|
bool CommandInterface::getValue(const QByteArray &arg, double &value)
|
|
{
|
|
bool bOk;
|
|
value = arg.toDouble(&bOk);
|
|
if (!bOk)
|
|
conversionError(arg, "double");
|
|
return bOk;
|
|
}
|