Files
qt5-legatus-legacy/Lts/Proxies/TrainingAreaBase/Plugins/AdlerJson/ws_handler.cpp
T
2026-08-13 18:33:10 +02:00

240 lines
6.4 KiB
C++
Executable File

#include "ws_handler.h"
#include <QWebSocket>
#include <QJsonDocument>
namespace TrainingAreaBase {
WebSocketHandler::WebSocketHandler(QObject *parent)
: WebSocketInterface(parent)
, m_webSocketServer(new QWebSocketServer(QStringLiteral("WebsocketServer_SAA"), QWebSocketServer::NonSecureMode,this))
, m_logger(AdlerJson::getLogger("WebsocketHandler"))
{}
WebSocketHandler::~WebSocketHandler(){}
bool WebSocketHandler::init(quint16 listenPort)
{
//INFO_LOG(m_logger) << "Init WebSocketHandler.";
if (!m_webSocketServer->listen(QHostAddress::Any, listenPort))
{
//ERROR_LOG(m_logger) << "Can not listen on port " << listenPort << " - aborting";
return false;
}
connect(m_webSocketServer, &QWebSocketServer::newConnection,
this, &WebSocketHandler::onNewConnection);
return true;
}
bool WebSocketHandler::isConnected() const
{
return !m_connections.isEmpty();
}
quint16 WebSocketHandler::getPort() const
{
return m_webSocketServer->serverPort();
}
bool WebSocketHandler::sendTelegram(int typeId, const QJsonObject *data, int exerciseId)
{
// TODO check wheter we need this method
Q_UNUSED(exerciseId);
QJsonObject obj;
obj[QStringLiteral("typeId")] = typeId;
obj[QStringLiteral("data")] = *data;
const QString jsonStr = QString::fromUtf8(QJsonDocument(obj).toJson(QJsonDocument::Compact));
bool bOk = false; // TODO
// for (const auto &wsw : qAsConst(m_webSockets))
// {
// if (wsw->sendTextMessage(jsonStr, exerciseId))
// bOk = true;
// }
return bOk;
}
bool WebSocketHandler::sendTelegram(const int wsId, const QJsonObject *data)
{
DEBUG_LOG(m_logger) << "Send Telegram esId=" << wsId
<< ", m_connections.size=" << m_connections.size();
for (auto it = m_connections.begin(); it != m_connections.end(); it++)
DEBUG_LOG(m_logger) << "key: " << it.key();
const QString jsonStr = QString::fromUtf8(QJsonDocument(*data).toJson(QJsonDocument::Compact));
if(!m_connections.contains(wsId))
{
DEBUG_LOG(m_logger) << "!m_connections.contains(" << wsId << ") return false;";
return false;
}
std::shared_ptr<WebSocketWrapper> ws = m_connections.value(wsId);
DEBUG_LOG(m_logger) << "Send Telegram to SAA: " << jsonStr<< " \n LocalPort" << ws->webSocket()->localAddress().toString()
<< "." << ws->webSocket()->localPort()
<< " PeerPort " << ws->webSocket()->peerAddress().toString()
<< ":" <<ws->webSocket()->peerPort();
DEBUG_LOG(m_logger) << "VERSION " << ws->webSocket()->version();
return ws->sendTextMessage(jsonStr);
}
bool WebSocketHandler::disconnectWs(int wsId)
{
if(!m_connections.contains(wsId))
{
DEBUG_LOG(m_logger) << "!m_connections.contains(" << wsId << ") return false;";
return false;
}
std::shared_ptr<WebSocketWrapper> ws = m_connections.value(wsId);
ws->webSocket()->close(QWebSocketProtocol::CloseCodeGoingAway, QStringLiteral("Timeout"));
m_connections.remove(wsId);
return true;
}
QString WebSocketHandler::getPeerAddress(int wsId) const
{
if (!m_connections.contains(wsId))
return QString();
const auto ws = m_connections[wsId];
QHostAddress address = ws->webSocket()->peerAddress();
bool ok = false;
quint32 ipv4 = address.toIPv4Address(&ok);
if (ok)
address = QHostAddress(ipv4);
return address.toString();
}
QUrl WebSocketHandler::getPeerUrl(int wsId) const
{
if (!m_connections.contains(wsId))
return {};
const auto ws = m_connections[wsId];
return ws->webSocket()->requestUrl();
}
int WebSocketHandler::getExerciseId(int wsId) const
{
if (!m_connections.contains(wsId))
return -1;
const auto ws = m_connections[wsId];
return ws->exerciseId();
}
void WebSocketHandler::onTextMessageReceived(const QByteArray &baJson)
{
DEBUG_LOG(m_logger) << "Receive Telegram from SAA <<<<< " << baJson;
using namespace TrainingAreaBase::TetraIcd;
WebSocketWrapper *wsw = qobject_cast<WebSocketWrapper *>(sender());
int wsId = getWSIdFromWS(wsw);
if (!wsw)
return;
if (baJson.isEmpty())
return;
const QJsonObject obj = QJsonDocument::fromJson(baJson).object();
emit recivedTelegram(wsId, obj);
}
void WebSocketHandler::onNewConnection()
{
QWebSocket *ws = m_webSocketServer->nextPendingConnection();
if (!ws)
return;
// TODO: add wsID to newConnection Signal
DEBUG_LOG(m_logger) << "New websocket connection from " << ws->peerAddress().toString() << ":" << ws->peerPort();
auto wsw = std::make_shared<WebSocketWrapper>(ws);
int wsId = m_nextWsId;
connect(wsw.get(), &WebSocketWrapper::textMessageReceived,
this, &WebSocketHandler::onTextMessageReceived);
connect(ws, &QWebSocket::disconnected,
this, &WebSocketHandler::onWebSocketDisconnected);
wsw->setWsId(wsId);
emit newConnection( wsId, ws->peerAddress().toString(),ws->peerPort());
m_connections.insert(wsId ,wsw);
DEBUG_LOG(m_logger) << "m_connections.insert"
<< ", wsId :" << wsId;
m_nextWsId++;
//m_webSockets += wsw;
}
int WebSocketHandler::getWSIdFromWS( WebSocketWrapper* wsw ){
for(auto pair : m_connections)
{
if(pair.get() == wsw){return pair->getWsId();}
}
return -1;
}
void WebSocketHandler::onWebSocketDisconnected()
{
QWebSocket *ws = qobject_cast<QWebSocket *>(sender());
if (!ws)
return;
auto copy = m_connections;
for (auto it = copy.begin(); it != copy.end(); ++it)
{
auto wsw = *it;
DEBUG_LOG(m_logger) << "peerPort :" << wsw->webSocket()->peerPort() << ", localPort :" << wsw->webSocket()->localPort();
if (wsw->webSocket() == ws)
{
DEBUG_LOG(m_logger) << it.key() << " Emit Disconnect ------------------------------------- esId=" << it.key();
emit wsDisconnected(it.key());
m_connections.remove(it.key());
break;
}
}
}
//
// WebSocketWrapper
//
WebSocketWrapper::WebSocketWrapper(QWebSocket *ws)
: m_webSocket(ws)
, m_exerciseId(-1)
{
connect(m_webSocket, &QWebSocket::textMessageReceived,
this, &WebSocketWrapper::onTextMessageReceived);
}
WebSocketWrapper::~WebSocketWrapper()
{
if (m_webSocket)
{
m_webSocket->disconnect(this);
m_webSocket->close();
}
delete m_webSocket;
}
bool WebSocketWrapper::sendTextMessage(const QString &msg)
{
m_webSocket->sendTextMessage(msg);
return true;
}
void WebSocketWrapper::setExerciseId(int exerciseId)
{
m_exerciseId = exerciseId;
}
void WebSocketWrapper::onTextMessageReceived(const QString &data)
{
emit textMessageReceived(data.toUtf8());
}
}