diff --git a/src/core/chat_room.cpp b/src/core/chat_room.cpp index 30be6c0..3d26fc4 100755 --- a/src/core/chat_room.cpp +++ b/src/core/chat_room.cpp @@ -2,6 +2,7 @@ #include #include "server.h" +#include "ssl_server.h" #include #include #include @@ -375,6 +376,23 @@ namespace Yc { // Spezielle Nachricht für Verbindungsabbrüche addMessage(ChatUser::system, std::string("user_disconnected"), (*it)->name(), (*it)->color()); + + // Entferne auch die SSL-Server-Verbindung falls vorhanden + if ((*it)->isWebSocket()) { + // Finde den Token für diese Verbindung + std::string token = (*it)->getToken(); + if (!token.empty()) { + // Entferne die Verbindung aus dem SSL-Server + SSLServer* sslServer = SSLServer::getInstance(); + if (sslServer) { + sslServer->removeConnection(token); + #ifdef YC_DEBUG + std::cout << "[Debug] Removed SSL connection for token: " << token << std::endl; + #endif + } + } + } + _users.erase(it); break; } @@ -519,6 +537,18 @@ namespace Yc return nullptr; } + std::shared_ptr ChatRoom::findUserByToken(std::string token) + { + for (auto &user : _users) + { + if (user->getToken() == token) + { + return user; + } + } + return nullptr; + } + void ChatRoom::_handleDice() { if (((_type & rounds) == rounds)) diff --git a/src/core/chat_room.h b/src/core/chat_room.h index 610d86a..95bdd2b 100755 --- a/src/core/chat_room.h +++ b/src/core/chat_room.h @@ -62,6 +62,7 @@ namespace Yc bool accessAllowed(std::string userName, std::string password); bool userIsInRoom(std::string userName); std::shared_ptr findUserByName(std::string userName); + std::shared_ptr findUserByToken(std::string token); void addUserWhenQueueEmpty(std::shared_ptr user); bool userToNewRoom(std::shared_ptr user, std::string newRoom, std::string password); unsigned int flags(); diff --git a/src/core/chat_user.cpp b/src/core/chat_user.cpp index d9b90a5..4cc1403 100644 --- a/src/core/chat_user.cpp +++ b/src/core/chat_user.cpp @@ -4,6 +4,7 @@ #include "server.h" #include "lib/tools.h" #include "lib/base.h" +#include #include #include #include @@ -385,6 +386,11 @@ namespace Yc return (toValidate.get() == this); } + bool ChatUser::isWebSocket() const + { + return _wsi != nullptr; + } + void ChatUser::sendMsg(MsgType type, const char *message, std::string userName, std::string color) { sendMsg(type, std::string(message), userName, color); @@ -452,14 +458,20 @@ namespace Yc if (heartbeatCounter >= HEARTBEAT_INTERVAL) { heartbeatCounter = 0; - // Prüfe Verbindung mit MSG_PEEK (nicht-blockierend) - // Für WebSocket: Skip heartbeat check da libwebsockets das verwaltet - if (_wsi) { - #ifdef YC_DEBUG - std::cout << "[Debug] WebSocket user, skipping socket check" << std::endl; - #endif - continue; - } + // Prüfe Verbindung mit MSG_PEEK (nicht-blockierend) + if (_wsi) { + // WebSocket-Verbindung prüfen + #ifdef YC_DEBUG + std::cout << "[Debug] WebSocket user, checking connection status" << std::endl; + #endif + + // Für WebSocket-Verbindungen verwenden wir einen einfacheren Ansatz: + // Wir senden einen Ping und prüfen, ob die Verbindung noch aktiv ist + // Da libwebsockets die Verbindung verwaltet, können wir nicht direkt prüfen + // Stattdessen verlassen wir uns auf die libwebsockets-Callbacks + // für die Erkennung von Verbindungsabbrüchen + continue; + } char peek; ssize_t r = recv(_socket, &peek, 1, MSG_PEEK | MSG_DONTWAIT); diff --git a/src/core/chat_user.h b/src/core/chat_user.h index 4a5a0e3..5735799 100644 --- a/src/core/chat_user.h +++ b/src/core/chat_user.h @@ -43,6 +43,7 @@ namespace Yc std::string getToken() const; bool validateToken(std::string token); bool isUser(std::shared_ptr toValidate); + bool isWebSocket() const; void sendMsg(MsgType type, std::string message, std::string userName, std::string color); void sendMsg(MsgType type, const char *message, std::string userName, std::string color); void sendMsg(MsgType type, Json::Value message, std::string userName, std::string color); diff --git a/src/core/ssl_server.cpp b/src/core/ssl_server.cpp index be69638..1a1dffe 100644 --- a/src/core/ssl_server.cpp +++ b/src/core/ssl_server.cpp @@ -196,6 +196,15 @@ int SSLServer::wsCallback(struct lws *wsi, enum lws_callback_reasons reason, voi break; } + case LWS_CALLBACK_CLOSED: + std::cout << "[YourChat] WebSocket-Verbindung geschlossen" << std::endl; + #ifdef YC_DEBUG + std::cout << "[Debug] WebSocket connection closed" << std::endl; + #endif + // Finde den User für diese Verbindung und entferne ihn + _instance->handleWebSocketDisconnect(wsi); + break; + case LWS_CALLBACK_SERVER_WRITEABLE: { // Send ping to keep connection alive unsigned char buf[LWS_PRE + 4]; @@ -204,9 +213,6 @@ int SSLServer::wsCallback(struct lws *wsi, enum lws_callback_reasons reason, voi break; } - case LWS_CALLBACK_CLOSED: - // Connection closed - no need to access user data - break; default: break; @@ -714,6 +720,39 @@ void SSLServer::addConnection(const std::string& token, struct lws *wsi) { std::cout << "[YourChat] Verbindung für Token " << token << " gespeichert" << std::endl; } +void SSLServer::handleWebSocketDisconnect(struct lws *wsi) { + // Finde den User für diese WebSocket-Verbindung + std::shared_lock lock(_connectionsMutex); + for (auto it = _connections.begin(); it != _connections.end(); ++it) { + if (it->second == wsi) { + std::string token = it->first; + lock.unlock(); // Unlock before calling removeConnection + + #ifdef YC_DEBUG + std::cout << "[Debug] WebSocket disconnect detected for token: " << token << std::endl; + #endif + + // Finde den User in den Räumen und entferne ihn + for (auto &room: _rooms) { + if (room) { + auto user = room->findUserByToken(token); + if (user) { + #ifdef YC_DEBUG + std::cout << "[Debug] Removing disconnected user: " << user->name() << std::endl; + #endif + room->removeUserDisconnected(user); + break; + } + } + } + + // Entferne die Verbindung + removeConnection(token); + return; + } + } +} + void SSLServer::removeConnection(const std::string& token) { std::unique_lock lock(_connectionsMutex); _connections.erase(token); @@ -721,6 +760,10 @@ void SSLServer::removeConnection(const std::string& token) { std::cout << "[YourChat] Verbindung für Token " << token << " entfernt" << std::endl; } +SSLServer* SSLServer::getInstance() { + return _instance; +} + std::shared_ptr SSLServer::getUserByToken(const std::string& token) { std::shared_lock lock(_connectionsMutex); auto it = _users.find(token); diff --git a/src/core/ssl_server.h b/src/core/ssl_server.h index 3c9757c..6f81b47 100644 --- a/src/core/ssl_server.h +++ b/src/core/ssl_server.h @@ -58,12 +58,16 @@ public: // WebSocket callbacks static int wsCallback(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len); + // Connection management + void removeConnection(const std::string& token); + static SSLServer* getInstance(); + private: void startServer(); void processMessageQueue(); void handleWebSocketMessage(struct lws *wsi, const std::string& message); + void handleWebSocketDisconnect(struct lws *wsi); void addConnection(const std::string& token, struct lws *wsi); - void removeConnection(const std::string& token); std::shared_ptr getUserByToken(const std::string& token); std::shared_ptr _config;