diff options
| author | Thomas Vanbesien <tvanbesi@proton.me> | 2026-03-13 11:58:45 +0100 |
|---|---|---|
| committer | Thomas Vanbesien <tvanbesi@proton.me> | 2026-03-13 11:58:45 +0100 |
| commit | 02fe86ab2a04a02b114d7ca8ce4374a29a1d5f45 (patch) | |
| tree | ebec2643d7238d0447a236a278757c718b0ef0ac /mock-server/MockServer.cpp | |
| parent | a2b1ccf17845e55caef7f69a5e68f49a55b6a166 (diff) | |
| download | QtXpl2-02fe86ab2a04a02b114d7ca8ce4374a29a1d5f45.tar.gz QtXpl2-02fe86ab2a04a02b114d7ca8ce4374a29a1d5f45.zip | |
Coalesce mock server into single MockServer class
Replace three independent EchoServer instances with one MockServer
that owns three QTcpServers, shares a single KA_PING timer, and
uses a flat client list with localPort() for port resolution.
Diffstat (limited to 'mock-server/MockServer.cpp')
| -rw-r--r-- | mock-server/MockServer.cpp | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/mock-server/MockServer.cpp b/mock-server/MockServer.cpp new file mode 100644 index 0000000..52db5a1 --- /dev/null +++ b/mock-server/MockServer.cpp @@ -0,0 +1,122 @@ +/** + * @file MockServer.cpp + * @brief Mock XPL2 server — listens on all three protocol ports. + */ +#include "MockServer.h" + +#include <QTcpSocket> + +MockServer::MockServer (QObject *parent) : QObject (parent) +{ + setupPort (m_command, "Command", 9110); + setupPort (m_imaging, "Imaging", 9111); + setupPort (m_status, "Status", 9112); + + connect (&m_pingTimer, &QTimer::timeout, this, &MockServer::sendKaPing); + m_pingTimer.start (1000); +} + +void +MockServer::setupPort (Port &port, const char *name, quint16 number) +{ + port.name = name; + port.number = number; + + connect (&port.server, &QTcpServer::newConnection, this, + &MockServer::onNewConnection); + + if (!port.server.listen (QHostAddress::Any, number)) + qCritical ("Failed to listen on %s port %d: %s", name, number, + qPrintable (port.server.errorString ())); + else + qInfo ("Listening on %s port %d", name, number); +} + +const char * +MockServer::portName (quint16 localPort) const +{ + if (localPort == m_command.number) + return m_command.name; + if (localPort == m_imaging.number) + return m_imaging.name; + if (localPort == m_status.number) + return m_status.name; + return "Unknown"; +} + +void +MockServer::onNewConnection () +{ + auto *server = qobject_cast<QTcpServer *> (sender ()); + while (auto *sock = server->nextPendingConnection ()) + { + quint16 lp = sock->localPort (); + qInfo ("[%s:%d] client connected", portName (lp), lp); + m_clients.append (sock); + connect (sock, &QTcpSocket::readyRead, this, + &MockServer::onClientMessageReady); + connect (sock, &QTcpSocket::disconnected, this, + &MockServer::onClientDisconnected); + } +} + +void +MockServer::onClientMessageReady () +{ + auto *sock = qobject_cast<QTcpSocket *> (sender ()); + while (sock->canReadLine ()) + { + QByteArray line = sock->readLine (); + handleCommand (sock, line); + } +} + +void +MockServer::onClientDisconnected () +{ + auto *sock = qobject_cast<QTcpSocket *> (sender ()); + quint16 lp = sock->localPort (); + qInfo ("[%s:%d] client disconnected", portName (lp), lp); + m_clients.removeOne (sock); + sock->deleteLater (); +} + +void +MockServer::sendKaPing () +{ + for (auto *client : m_clients) + { + if (client->state () == QAbstractSocket::ConnectedState) + client->write ("KA_PING\n"); + } +} + +void +MockServer::handleCommand (QTcpSocket *client, const QByteArray &line) +{ + QByteArray trimmed = line.trimmed (); + if (trimmed.isEmpty ()) + return; + + quint16 lp = client->localPort (); + + /* Split on first comma to get command token. */ + int comma = trimmed.indexOf (','); + QByteArray cmd = (comma >= 0) ? trimmed.left (comma) : trimmed; + + if (cmd == "KA_PING") + { + qDebug ("[%s:%d] KA_PING ACK received", portName (lp), lp); + return; + } + + if (cmd == "GS_JC_VERSION") + { + qInfo ("[%s:%d] -> GS_JC_VERSION reply", portName (lp), lp); + client->write ("GS_JC_VERSION,1,\"1.05\",\"2.00\",15\n"); + return; + } + + qWarning ("[%s:%d] Unknown command: %s", portName (lp), lp, + trimmed.constData ()); +} |
