#include "lts_web_socket_server.h" #include "connection_handler.h" #include "client_connection.h" #include namespace LtsWebSocket { LtsWebSocketServer::LtsWebSocketServer(AbstractClientMessageFactory *messageFactory, QObject *parent) : QObject(parent) , m_queueTimer(new QTimer(this)) , m_messageFactory(messageFactory) , m_connectionHandler(nullptr) , m_logger(getLogger("LtsWebSocketServer")) { connect(m_queueTimer, &QTimer::timeout, this, &LtsWebSocketServer::onQueueTimerTimeout); m_queueTimer->setSingleShot(true); } LtsWebSocketServer::~LtsWebSocketServer() = default; bool LtsWebSocketServer::init(const QString &serviceName, const unsigned short port) { m_connectionHandler.reset(new ConnectionHandler(this)); if (!m_connectionHandler->init(serviceName, port)) { ERROR_LOG(m_logger) << "Could not init m_connectionHandler with servicename: " << serviceName << ((port == 0) ? QStringLiteral(" random port") : QStringLiteral(" port: ") + QString::number(port)); m_connectionHandler.reset(); return false; } connect(m_connectionHandler.get(), &ConnectionHandler::newTextMessageFromClient, this, &LtsWebSocketServer::onNewTextMessage); connect(m_connectionHandler.get(), &ConnectionHandler::clientDisconnected, this, &LtsWebSocketServer::clientDisconnected); connect(m_connectionHandler.get(), &ConnectionHandler::clientConnected, this, &LtsWebSocketServer::clientConnected); m_queueTimer->start(m_messageDelay); return true; } bool LtsWebSocketServer::init(const QString &serviceName, const QPair &portRange) { if (portRange.first < 1025 || portRange.first > portRange.second) return init(serviceName); for (quint16 currentPort = portRange.first; currentPort <= portRange.second; ++ currentPort) { if (init(serviceName, currentPort)) return true; } return init(serviceName); } void LtsWebSocketServer::sendToAllClients(ReplyMessage *message) { DEBUG_LOG(m_logger) << "Sending message to all clients: " << message->toJsonString(); m_connectionHandler->sendToAllClients(message); } unsigned short LtsWebSocketServer::webSocketPort() const { return m_connectionHandler->webSocketPort(); } void LtsWebSocketServer::setMessageDelay(qint32 delay) { m_messageDelay = delay; } void LtsWebSocketServer::onNewTextMessage(ReplyHandler *client, const QString &message) { const QString pingMsg(QStringLiteral("ping")); if (message.startsWith(pingMsg)) { client->addReply(new PongMessage(message.mid(pingMsg.size()))); return; } DEBUG_LOG(m_logger) << "Got new message: " << message; m_messageQueue.append({client, message}); if (!m_queueTimer->isActive()) m_queueTimer->start(m_messageDelay); } void LtsWebSocketServer::onQueueTimerTimeout() { if (m_messageQueue.isEmpty()) return; MessageCredentials credentials = m_messageQueue.takeFirst(); AbstractClientMessage *clientMessage = nullptr; auto result = m_messageFactory->parseMessage(credentials.message); if (QJsonParseError::NoError == result.error) clientMessage = m_messageFactory->createMessage(credentials.client, credentials.message); else { WARNING_LOG(m_logger) << "Could not parse incoming message: '" << credentials.message << "', error: " << result.errorString(); clientMessage = new InvalidMessage(credentials.client, QString(), QStringLiteral("Got message which is not JSON conform")); } if (clientMessage) clientMessage->process(); delete clientMessage; m_queueTimer->start(m_messageDelay); } }