Initial commit

This commit is contained in:
torsten committed 2026-08-13 18:33:10 +02:00
commit b7d90b9afe
16245 files changed
+3396666

No files matched your search

@@ -0,0 +1,94 @@
/**
* @RDE_HEADER@
* The ClientConnection class represents a connection to a single client.
* $Id$
* $HeadURL$
* $Author$
* Created by Hannes Fritsche, SLSE, 2017-09-07
*/
#include "client_connection.h"
#include "WebSocketInterface/Messages/reply_message.h"
#include <QtWebSockets/QWebSocket>
#include <QtCore/QTimer>
using namespace CombatNetRadio::WebSocketInterface::Connection;
ClientConnection::ClientConnection(QWebSocket *socket, QObject *parent)
: QObject(parent)
, m_socket(socket)
, m_ip(socket->peerAddress())
, m_logger(getLogger(QLatin1String("ClientConnection")))
{}
ClientConnection::~ClientConnection()
{
if (m_socket)
{
m_socket->disconnect(this);
m_socket->close();
}
delete m_socket;
}
bool ClientConnection::init()
{
if (m_socket == nullptr)
{
ERROR_LOG(m_logger) << "Initialisation failed due to an invalid socket";
return false;
}
connect(m_socket, &QWebSocket::textMessageReceived, this, &ClientConnection::onNewTextMessageFromSocket);
connect(m_socket, &QWebSocket::connected, this, &ClientConnection::sendMessagesFromQueue);
connect(m_socket, &QWebSocket::disconnected, this, &ClientConnection::onSocketDisconnect);
return true;
}
QHostAddress ClientConnection::ip() const
{
return m_ip;
}
void ClientConnection::addMessage(const CombatNetRadio::WebSocketInterface::Messages::ReplyMessage &message)
{
if (!m_socket || m_socket->state() != QAbstractSocket::ConnectedState)
{
m_messageQueue.enqueue(message);
DEBUG_LOG(m_logger) << "Adding message to queue, size: " << m_messageQueue.size();
return;
}
const QString msg(message.toJsonString());
DEBUG_LOG(m_logger) << "Send msg: " << msg;
m_socket->sendTextMessage(msg);
}
void ClientConnection::onNewTextMessageFromSocket(const QString &message)
{
DEBUG_LOG(m_logger) << "Recv msg: " << message;
emit newTextMessage(this, message);
}
void ClientConnection::sendMessagesFromQueue()
{
if (m_socket->state() != QAbstractSocket::ConnectedState)
return;
while (!m_messageQueue.isEmpty())
{
Messages::ReplyMessage message = m_messageQueue.dequeue();
const QString msg(message.toJsonString());
TRACE_LOG(m_logger) << "Send msg: " << msg;
m_socket->sendTextMessage(msg);
DEBUG_LOG(m_logger) << "Sent message from queue, new size: " << m_messageQueue.size();
}
}
void ClientConnection::onSocketDisconnect()
{
DEBUG_LOG(m_logger) << "Client with ip "
<< m_ip.toString()
<< " disconnected";
emit disconnected(this);
}
@@ -0,0 +1,60 @@
/**
* @RDE_HEADER@
* The ClientConnection class represents a connection to a single client.
* $Id$
* $HeadURL$
* $Author$
* Created by Hannes Fritsche, SLSE, 2017-09-07
*/
#pragma once
#include <QtCore/QQueue>
#include <QtNetwork/QHostAddress>
#include "WebSocketInterface/Messages/message_transmitter.h"
#include "logger.h"
class QWebSocket;
class QTimer;
namespace CombatNetRadio
{
namespace WebSocketInterface
{
namespace Connection
{
class ClientConnection
: public QObject
, public Messages::MessageTransmitter
{
Q_OBJECT
public:
explicit ClientConnection(QWebSocket *socket, QObject *parent = nullptr);
~ClientConnection();
bool init();
QHostAddress ip() const;
void addMessage(const Messages::ReplyMessage &message) override final;
Q_SIGNALS:
void newTextMessage(MessageTransmitter *transmitter, const QString &message);
void disconnected(ClientConnection *conn);
private Q_SLOTS:
void onNewTextMessageFromSocket(const QString &message);
void sendMessagesFromQueue();
void onSocketDisconnect();
private: // methods
void sendMessages();
private: // attributes
QWebSocket *m_socket;
QQueue<Messages::ReplyMessage> m_messageQueue;
QHostAddress m_ip;
LOGGER_T m_logger;
}; // class ClientConnection
} // namespace Connection
} // namespace WebSocketInterface
} // namespace CombatNetRadio
@@ -0,0 +1,114 @@
/**
* @RDE_HEADER@
* The ConnectionHandler class functions as a WebSocket server and manages incoming client connections.
* $Id$
* $HeadURL$
* $Author$
* Created by Hannes Fritsche, SLSE, 2017-09-07
*/
#include "connection_handler.h"
#include "client_connection.h"
#include <QtWebSockets/QWebSocketServer>
#include <QtWebSockets/QWebSocket>
using namespace CombatNetRadio::WebSocketInterface::Connection;
ConnectionHandler::ConnectionHandler()
: m_server(nullptr)
, m_logger(getLogger("ConnectionHandler"))
{
}
ConnectionHandler::~ConnectionHandler()
{
for (auto s : qAsConst(m_connections))
s->disconnect(this);
qDeleteAll(m_connections);
}
bool ConnectionHandler::init()
{
if (m_server != nullptr)
{
m_server->disconnect();
delete m_server;
}
// TODO: get a server name from config ?
// TODO: get the SslMode from config ?
m_server = new QWebSocketServer(QStringLiteral("RDE-EXC"), QWebSocketServer::NonSecureMode, this);
connect(m_server, &QWebSocketServer::newConnection, this, &ConnectionHandler::onNewConnection);
connect(m_server, &QWebSocketServer::serverError, this, &ConnectionHandler::onServerError);
// TODO: read port from config?
quint16 port = 2081;
DEBUG_LOG(m_logger) << "Trying to listen to port " << port;
if (!m_server->listen(QHostAddress::Any, port))
{
ERROR_LOG(m_logger) << "Not possible to listen to port " << port;
return false;
}
DEBUG_LOG(m_logger) << "... ok";
return true;
}
void ConnectionHandler::onUpdate()
{
emit clearFrequencyPlanningStatus();
for (ClientConnection *currentConnection : qAsConst(m_connections))
currentConnection->addMessage(Messages::UpdateMessage());
}
void ConnectionHandler::onNewMessage(CombatNetRadio::WebSocketInterface::Messages::MessageTransmitter *transmitter, const QString &message)
{
emit newTextMessageFromClient(transmitter, message);
}
void ConnectionHandler::onServerError(QWebSocketProtocol::CloseCode closeCode)
{
ERROR_LOG(m_logger) << "Got server error with close code " << closeCode;
}
void ConnectionHandler::onNewConnection()
{
while (m_server->hasPendingConnections())
{
QWebSocket *socket = m_server->nextPendingConnection();
ClientConnection *newConnection = new ClientConnection(socket, this);
if (!newConnection->init())
{
ERROR_LOG(m_logger) << "Failed to initialise new client";
delete newConnection;
newConnection = nullptr;
continue;
}
connect(newConnection, &ClientConnection::newTextMessage, this, &ConnectionHandler::onNewMessage);
connect(newConnection, &ClientConnection::disconnected, this, &ConnectionHandler::onDisconnected);
m_connections.append(newConnection);
DEBUG_LOG(m_logger) << "New client with ip " << newConnection->ip().toString() << " connected";
emit newClientConnection((qint64) static_cast<WebSocketInterface::Connection::ClientConnection::MessageTransmitter*>(newConnection));
}
}
void ConnectionHandler::onDisconnected(ClientConnection *conn)
{
bool removeCount = m_connections.removeOne(conn);
Q_ASSERT(removeCount == 1);
conn->deleteLater(); // use deleteLater() as the signal is emitted from with ClientConnection
emit clientConnectionClosed((qint64) static_cast<WebSocketInterface::Connection::ClientConnection::MessageTransmitter*>(conn));
if (m_connections.empty())
emit lastConnectionClosed();
}
void ConnectionHandler::onPositions(const CombatNetRadio::WebSocketInterface::Messages::ReplyMessage &positionsCnr)
{
for (ClientConnection *currentConnection : qAsConst(m_connections))
currentConnection->addMessage(positionsCnr);
}
@@ -0,0 +1,66 @@
/**
* @RDE_HEADER@
* The ConnectionHandler class functions as a WebSocket server and manages incoming client connections.
* $Id$
* $HeadURL$
* $Author$
* Created by Hannes Fritsche, SLSE, 2017-09-07
*/
#pragma once
#include <QtNetwork/QHostAddress>
#include <QtWebSockets/qwebsocketprotocol.h>
#include "../Messages/reply_message.h"
#include "logger.h"
class QWebSocketServer;
namespace CombatNetRadio
{
namespace WebSocketInterface
{
namespace Messages
{
class MessageTransmitter;
}
namespace Connection
{
class ClientConnection;
class ConnectionHandler
: public QObject
{
Q_OBJECT
public:
explicit ConnectionHandler();
~ConnectionHandler();
bool init();
Q_SIGNALS:
void newTextMessageFromClient(Messages::MessageTransmitter *transmitter, const QString &message);
void lastConnectionClosed();
void newClientConnection(qint64 id);
void clientConnectionClosed(qint64 id);
void clearFrequencyPlanningStatus();
public Q_SLOTS:
void onUpdate();
void onPositions(const Messages::ReplyMessage &positionsCnr);
private Q_SLOTS:
void onNewMessage(Messages::MessageTransmitter *transmitter, const QString &message);
void onServerError(QWebSocketProtocol::CloseCode closeCode);
void onNewConnection();
void onDisconnected(ClientConnection *conn);
private: // attributes
QWebSocketServer *m_server;
QVector<ClientConnection *> m_connections;
LOGGER_T m_logger;
};
} // namespace Connection
} // namespace WebSocketInterface
} // namespace CombatNetRadio