#include "lts_projection_workstation.h" #include "WebSocket/message_factory.h" #include "WebSocket/json_keys.h" #include #include #include #include #include #include #include namespace LtsProjectionWorkstation { static LtsProjectionWorkstation *s_ltsProjectionWorkstation = nullptr; LtsProjectionWorkstation *LtsProjectionWorkstation::getInstance() { if (!s_ltsProjectionWorkstation) { s_ltsProjectionWorkstation = new LtsProjectionWorkstation; qAddPostRoutine(&cleanupLtsProjectionWorkstation); } return s_ltsProjectionWorkstation; } void LtsProjectionWorkstation::cleanupLtsProjectionWorkstation() { delete s_ltsProjectionWorkstation; s_ltsProjectionWorkstation = nullptr; } bool LtsProjectionWorkstation::hasInstance() { return !!s_ltsProjectionWorkstation; } LtsProjectionWorkstation::LtsProjectionWorkstation(QObject *parent) : QObject(parent) , m_logger(getLogger("LtsProjetionWorkstation")) , m_messageFactory(new MessageFactory(this, m_logger)) , m_webSocketServer(new LtsWebSocket::LtsWebSocketServer(m_messageFactory, this)) , m_pendingLoginRequest(nullptr) , m_vncManager(new VncServerManager(m_logger, this)) { connect(m_webSocketServer, &LtsWebSocket::LtsWebSocketServer::clientDisconnected, this, &LtsProjectionWorkstation::clientDisconnected); connect(m_webSocketServer, &LtsWebSocket::LtsWebSocketServer::clientConnected, this, &LtsProjectionWorkstation::clientConnected); int port = NGL::Connections::port(NGL::Connections::eConnection::PWS_WEBSOCKET); if (m_webSocketServer->init(QStringLiteral("LtsProjectionWorkstation"), port)) { if (m_vncManager->init(qApp->screens())) m_vncManager->startScreens(); } } LtsProjectionWorkstation::~LtsProjectionWorkstation() { delete m_vncManager; delete m_messageFactory; delete m_webSocketServer; } LoginInformation LtsProjectionWorkstation::pendingLoginRequest() { if (!m_pendingLoginRequest) return {}; LoginInformation result = *m_pendingLoginRequest; INFO_LOG(m_logger) << " reset pendingLoginRequest.."; delete m_pendingLoginRequest; m_pendingLoginRequest = nullptr; return result; } void LtsProjectionWorkstation::handleMessage(LtsWebSocket::AbstractClientMessage *message) { CTS::LoginRequest *login = dynamic_cast(message); if (login) { INFO_LOG(m_logger) << "Login request received!" << ", login->userId()=" << login->userId() << " with login->priority()=" << login->priority() << " ;;; m_lastLoginRequest.m_userId=" << m_lastLoginRequest.m_userId << ", m_priority=" << m_lastLoginRequest.m_priority; if (login->userId() > 0 && login->priority() > 0 && login->exerciseId() > 0) { if ( login->userId() == m_lastLoginRequest.m_userId || (login->priority() > m_lastLoginRequest.m_priority) ) { m_webSocketServer->sendToAllClients( (new STC::DedicatedDisconnect(QUuid::createUuid().toString(), login->userId()))->toReplyMessage() ); DEBUG_LOG(m_logger) << "Login request received and DedicatedDisconnect distributed, wait some seconds..."; int i=0; while(i<20) { DEBUG_LOG(m_logger) << "Login request received and DedicatedDisconnect distributed, wait some seconds...i=" << i; qApp->processEvents(QEventLoop::AllEvents, 50); QThread::msleep(50); ++i; } INFO_LOG(m_logger) << "Login request received and DedicatedDisconnect distributed, wait some seconds... done"; login->addReply((new STC::LoginRequestReply(QUuid::createUuid().toString(), STC::LoginRequestReply::LoginSuccessful, login->userId(), m_vncManager->screens()) )->toReplyMessage()); m_lastLoginRequest.m_userId = login->userId(); m_lastLoginRequest.m_priority = login->priority(); m_lastLoginRequest.m_exerciseId = login->exerciseId(); m_lastLoginRequest.m_settingsData = login->settingsData(); slotLoginRequestReceived(login->userId(), login->exerciseId()); INFO_LOG(m_logger) << "Valid login request received -> userId: " << login->userId() << " priority: " << login->priority() << " exerciseId: " << login->exerciseId(); DEBUG_LOG(m_logger) << "Logging in now!"; } else { login->addReply((new STC::LoginRequestReply(QUuid::createUuid().toString(), STC::LoginRequestReply::OtherUser, m_lastLoginRequest.m_userId, QVector()) )->toReplyMessage()); DEBUG_LOG(m_logger) << "Higher prioritized login received -> userId: " << login->userId() << " priority: " << login->priority() << " exerciseId: " << login->exerciseId(); DEBUG_LOG(m_logger) << "Last login data was -> userId: " << m_lastLoginRequest.m_userId << " priority: " << m_lastLoginRequest.m_priority << " exerciseId: " << m_lastLoginRequest.m_exerciseId; } } else ERROR_LOG(m_logger) << "invalid login request received -> userId: " << login->userId() << " priority: " << login->priority() << " exerciseId: " << login->exerciseId(); return; } CTS::LogoutRequest *logout = dynamic_cast(message); if (logout) { DEBUG_LOG(m_logger) << "Logging out now!"; slotLogoutRequestReceived(); return; } CTS::DisconnectRequest *discon = dynamic_cast(message); if (discon) { int disconnectingUserId = discon->userId(); INFO_LOG(m_logger) << "Disconnecting now! " << ", disconnectingUserId=" << disconnectingUserId << ", m_pendingLoginRequest=" << m_pendingLoginRequest; m_lastLoginRequest = LoginInformation(); return; } } void LtsProjectionWorkstation::slotLoginRequestReceived(int userId, int exerciseId) { INFO_LOG(m_logger) << "slotLoginRequestReceived.." << ", userId=" << userId << ", exerciseId=" << exerciseId; delete m_pendingLoginRequest; m_pendingLoginRequest = new LoginInformation(m_lastLoginRequest); emit signalLoginRequestReceived(userId, exerciseId); } void LtsProjectionWorkstation::slotLogoutRequestReceived() { emit signalLogoutRequestReceived(); } void LtsProjectionWorkstation::slotLogoffDone() { if (hasPendingLoginRequest()) return; for (LtsWebSocket::ClientConnection *con : qAsConst(m_connections)) con->webSocket()->close(); } void LtsProjectionWorkstation::clientDisconnected(LtsWebSocket::ClientConnection *client) { INFO_LOG(m_logger) << LOGFUNCTION << " START" << ", m_connections.size = " << m_connections.size(); m_connections.removeOne(client); if ( m_connections.size() == 0 && (m_lastLoginRequest.m_userId != 0 || m_lastLoginRequest.m_priority != 0)) { INFO_LOG(m_logger) << LOGFUNCTION << " reset m_lastLoginRequest"; m_lastLoginRequest = LoginInformation(); } INFO_LOG(m_logger) << LOGFUNCTION << " END" << ", m_connections.size = " << m_connections.size(); } void LtsProjectionWorkstation::clientConnected(LtsWebSocket::ClientConnection *client) { m_connections.append(client); } void LtsProjectionWorkstation::setProjectionOperatorPreset(const QString &operatorName, const QString &operatorPassword) { m_projectionOperatorPreset.first = operatorName; m_projectionOperatorPreset.second = operatorPassword; } }