#include "ws_handler.h" #include #include 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 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() << ":" <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 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(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(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(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()); } }