Füge Unterstützung für die Verwaltung von WebSocket-Verbindungen im ChatRoom und SSLServer hinzu
- Implementiere die Methode `findUserByToken` in `ChatRoom`, um Benutzer anhand ihres Tokens zu finden. - Ergänze die Logik zur Entfernung von WebSocket-Verbindungen im `SSLServer`, wenn ein Benutzer die Verbindung trennt. - Füge die Methode `isWebSocket` in `ChatUser` hinzu, um zu überprüfen, ob ein Benutzer über eine WebSocket-Verbindung verfügt. - Aktualisiere die Verarbeitung von Verbindungsabbrüchen, um sicherzustellen, dass sowohl die ChatRoom- als auch die SSLServer-Verbindungen korrekt verwaltet werden. - Ergänze Debug-Ausgaben zur Nachverfolgbarkeit der WebSocket-Verbindungen und deren Status.
This commit is contained in:
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
|
#include "ssl_server.h"
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
@@ -375,6 +376,23 @@ namespace Yc
|
|||||||
{
|
{
|
||||||
// Spezielle Nachricht für Verbindungsabbrüche
|
// Spezielle Nachricht für Verbindungsabbrüche
|
||||||
addMessage(ChatUser::system, std::string("user_disconnected"), (*it)->name(), (*it)->color());
|
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);
|
_users.erase(it);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -519,6 +537,18 @@ namespace Yc
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<ChatUser> ChatRoom::findUserByToken(std::string token)
|
||||||
|
{
|
||||||
|
for (auto &user : _users)
|
||||||
|
{
|
||||||
|
if (user->getToken() == token)
|
||||||
|
{
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
void ChatRoom::_handleDice()
|
void ChatRoom::_handleDice()
|
||||||
{
|
{
|
||||||
if (((_type & rounds) == rounds))
|
if (((_type & rounds) == rounds))
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ namespace Yc
|
|||||||
bool accessAllowed(std::string userName, std::string password);
|
bool accessAllowed(std::string userName, std::string password);
|
||||||
bool userIsInRoom(std::string userName);
|
bool userIsInRoom(std::string userName);
|
||||||
std::shared_ptr<ChatUser> findUserByName(std::string userName);
|
std::shared_ptr<ChatUser> findUserByName(std::string userName);
|
||||||
|
std::shared_ptr<ChatUser> findUserByToken(std::string token);
|
||||||
void addUserWhenQueueEmpty(std::shared_ptr<ChatUser> user);
|
void addUserWhenQueueEmpty(std::shared_ptr<ChatUser> user);
|
||||||
bool userToNewRoom(std::shared_ptr<ChatUser> user, std::string newRoom, std::string password);
|
bool userToNewRoom(std::shared_ptr<ChatUser> user, std::string newRoom, std::string password);
|
||||||
unsigned int flags();
|
unsigned int flags();
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include "server.h"
|
#include "server.h"
|
||||||
#include "lib/tools.h"
|
#include "lib/tools.h"
|
||||||
#include "lib/base.h"
|
#include "lib/base.h"
|
||||||
|
#include <libwebsockets.h>
|
||||||
#include <json/json.h>
|
#include <json/json.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
@@ -385,6 +386,11 @@ namespace Yc
|
|||||||
return (toValidate.get() == this);
|
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)
|
void ChatUser::sendMsg(MsgType type, const char *message, std::string userName, std::string color)
|
||||||
{
|
{
|
||||||
sendMsg(type, std::string(message), userName, color);
|
sendMsg(type, std::string(message), userName, color);
|
||||||
@@ -453,11 +459,17 @@ namespace Yc
|
|||||||
heartbeatCounter = 0;
|
heartbeatCounter = 0;
|
||||||
|
|
||||||
// Prüfe Verbindung mit MSG_PEEK (nicht-blockierend)
|
// Prüfe Verbindung mit MSG_PEEK (nicht-blockierend)
|
||||||
// Für WebSocket: Skip heartbeat check da libwebsockets das verwaltet
|
|
||||||
if (_wsi) {
|
if (_wsi) {
|
||||||
|
// WebSocket-Verbindung prüfen
|
||||||
#ifdef YC_DEBUG
|
#ifdef YC_DEBUG
|
||||||
std::cout << "[Debug] WebSocket user, skipping socket check" << std::endl;
|
std::cout << "[Debug] WebSocket user, checking connection status" << std::endl;
|
||||||
#endif
|
#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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ namespace Yc
|
|||||||
std::string getToken() const;
|
std::string getToken() const;
|
||||||
bool validateToken(std::string token);
|
bool validateToken(std::string token);
|
||||||
bool isUser(std::shared_ptr<ChatUser> toValidate);
|
bool isUser(std::shared_ptr<ChatUser> toValidate);
|
||||||
|
bool isWebSocket() const;
|
||||||
void sendMsg(MsgType type, std::string message, std::string userName, std::string color);
|
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, const char *message, std::string userName, std::string color);
|
||||||
void sendMsg(MsgType type, Json::Value message, std::string userName, std::string color);
|
void sendMsg(MsgType type, Json::Value message, std::string userName, std::string color);
|
||||||
|
|||||||
@@ -196,6 +196,15 @@ int SSLServer::wsCallback(struct lws *wsi, enum lws_callback_reasons reason, voi
|
|||||||
break;
|
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: {
|
case LWS_CALLBACK_SERVER_WRITEABLE: {
|
||||||
// Send ping to keep connection alive
|
// Send ping to keep connection alive
|
||||||
unsigned char buf[LWS_PRE + 4];
|
unsigned char buf[LWS_PRE + 4];
|
||||||
@@ -204,9 +213,6 @@ int SSLServer::wsCallback(struct lws *wsi, enum lws_callback_reasons reason, voi
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case LWS_CALLBACK_CLOSED:
|
|
||||||
// Connection closed - no need to access user data
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
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;
|
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<std::shared_mutex> 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) {
|
void SSLServer::removeConnection(const std::string& token) {
|
||||||
std::unique_lock<std::shared_mutex> lock(_connectionsMutex);
|
std::unique_lock<std::shared_mutex> lock(_connectionsMutex);
|
||||||
_connections.erase(token);
|
_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;
|
std::cout << "[YourChat] Verbindung für Token " << token << " entfernt" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SSLServer* SSLServer::getInstance() {
|
||||||
|
return _instance;
|
||||||
|
}
|
||||||
|
|
||||||
std::shared_ptr<ChatUser> SSLServer::getUserByToken(const std::string& token) {
|
std::shared_ptr<ChatUser> SSLServer::getUserByToken(const std::string& token) {
|
||||||
std::shared_lock<std::shared_mutex> lock(_connectionsMutex);
|
std::shared_lock<std::shared_mutex> lock(_connectionsMutex);
|
||||||
auto it = _users.find(token);
|
auto it = _users.find(token);
|
||||||
|
|||||||
@@ -58,12 +58,16 @@ public:
|
|||||||
// WebSocket callbacks
|
// WebSocket callbacks
|
||||||
static int wsCallback(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len);
|
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:
|
private:
|
||||||
void startServer();
|
void startServer();
|
||||||
void processMessageQueue();
|
void processMessageQueue();
|
||||||
void handleWebSocketMessage(struct lws *wsi, const std::string& message);
|
void handleWebSocketMessage(struct lws *wsi, const std::string& message);
|
||||||
|
void handleWebSocketDisconnect(struct lws *wsi);
|
||||||
void addConnection(const std::string& token, struct lws *wsi);
|
void addConnection(const std::string& token, struct lws *wsi);
|
||||||
void removeConnection(const std::string& token);
|
|
||||||
std::shared_ptr<ChatUser> getUserByToken(const std::string& token);
|
std::shared_ptr<ChatUser> getUserByToken(const std::string& token);
|
||||||
|
|
||||||
std::shared_ptr<Config> _config;
|
std::shared_ptr<Config> _config;
|
||||||
|
|||||||
Reference in New Issue
Block a user