From 411a4c52c7dbf8c992bc0ec6d16b7f6afabab702 Mon Sep 17 00:00:00 2001 From: "Torsten Schulz (local)" Date: Fri, 5 Sep 2025 10:42:23 +0200 Subject: [PATCH] Verbessere Socket-Validierung und Fehlerbehandlung in ChatUser und Base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Füge Überprüfungen hinzu, um sicherzustellen, dass der Socket gültig ist, bevor Nachrichten gesendet werden. - Implementiere detaillierte Fehlerprotokollierung für verschiedene Socket-Fehler, um die Diagnose zu erleichtern. - Ergänze eine kurze Verzögerung im ChatRoom, um den Abschluss des WebSocket-Handshakes zu gewährleisten. --- src/core/chat_room.cpp | 3 +++ src/core/chat_user.cpp | 29 +++++++++++++++++++++ src/lib/base.cpp | 59 ++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 89 insertions(+), 2 deletions(-) diff --git a/src/core/chat_room.cpp b/src/core/chat_room.cpp index 22dd4c3..a6c546b 100755 --- a/src/core/chat_room.cpp +++ b/src/core/chat_room.cpp @@ -128,6 +128,9 @@ namespace Yc newUser->sendMsg(ChatUser::roomList, roomList, "", ""); } + // Kurze Pause, damit der WebSocket-Handshake vollständig abgeschlossen ist + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + // Sende aktuelle Userliste an den neuen User Json::Value currentUserList = userList(); newUser->sendMsg(ChatUser::userListe, currentUserList, "", ""); diff --git a/src/core/chat_user.cpp b/src/core/chat_user.cpp index 4fc5ca6..154e8fb 100644 --- a/src/core/chat_user.cpp +++ b/src/core/chat_user.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include "chat_room.h" #include #include @@ -336,6 +337,8 @@ namespace Yc void ChatUser::stop() { _stop = true; + // Socket als ungültig markieren + _socket = -1; } std::string ChatUser::color() const @@ -349,12 +352,38 @@ namespace Yc } void ChatUser::send(std::string out) { + // Prüfe ob Socket noch gültig ist + if (_socket < 0 || _stop) { + #ifdef YC_DEBUG + std::cout << "[Debug] Skipping send - socket invalid or user stopped" << std::endl; + #endif + return; + } + + // Zusätzliche Socket-Validierung mit fcntl + int flags = fcntl(_socket, F_GETFL); + if (flags == -1) { + #ifdef YC_DEBUG + std::cout << "[Debug] Socket " << _socket << " is invalid (fcntl failed), skipping send" << std::endl; + #endif + _socket = -1; // Markiere als ungültig + return; + } + // Entferne ggf. Token-Felder aus JSON-Strings und sende über Socket/WebSocket Base::sanitizeTokensInString(out); Base::send(_socket, out); } void ChatUser::send(Json::Value out) { + // Prüfe ob Socket noch gültig ist + if (_socket < 0 || _stop) { + #ifdef YC_DEBUG + std::cout << "[Debug] Skipping send - socket invalid or user stopped" << std::endl; + #endif + return; + } + // Entferne rekursiv alle Token-Felder und sende über Socket/WebSocket Base::sanitizeTokens(out); Base::send(_socket, out); diff --git a/src/lib/base.cpp b/src/lib/base.cpp index befc3b4..74c9eb0 100755 --- a/src/lib/base.cpp +++ b/src/lib/base.cpp @@ -64,9 +64,35 @@ namespace Yc { sendWebSocketMessage(socket, out); return; } + + // Socket-Validierung vor dem Senden + if (socket < 0) { + #ifdef YC_DEBUG + std::cout << "[Debug] Invalid socket (< 0), skipping send" << std::endl; + #endif + return; + } + ssize_t result = write(socket, out.c_str(), out.length()); if (result < 0) { - std::cout << "[Error] Fehler beim Senden auf Socket (vermutlich Verbindung verloren): " << strerror(errno) << std::endl; + int error = errno; + // Nur kritische Fehler loggen, nicht alle "Bad file descriptor" Fehler + if (error == EBADF) { + #ifdef YC_DEBUG + std::cout << "[Debug] Socket " << socket << " closed by client, skipping send" << std::endl; + #endif + } else if (error == EPIPE) { + #ifdef YC_DEBUG + std::cout << "[Debug] Broken pipe on socket " << socket << ", connection closed" << std::endl; + #endif + } else if (error == ECONNRESET) { + #ifdef YC_DEBUG + std::cout << "[Debug] Connection reset by peer on socket " << socket << std::endl; + #endif + } else { + // Nur unbekannte Fehler als Error loggen + std::cout << "[Error] Fehler beim Senden auf Socket " << socket << ": " << strerror(error) << std::endl; + } } } @@ -209,6 +235,14 @@ namespace Yc { } void Base::sendWebSocketMessage(int socket, const std::string& out) { + // Socket-Validierung vor dem Senden + if (socket < 0) { + #ifdef YC_DEBUG + std::cout << "[Debug] Invalid WebSocket socket (< 0), skipping send" << std::endl; + #endif + return; + } + std::string frame; unsigned char hdr[2]; hdr[0] = 0x80 | 0x1; // FIN + text @@ -230,7 +264,28 @@ namespace Yc { frame.append(reinterpret_cast(ext), 8); } frame.append(out); - ::send(socket, frame.data(), frame.size(), 0); + + ssize_t result = ::send(socket, frame.data(), frame.size(), 0); + if (result < 0) { + int error = errno; + // Nur kritische Fehler loggen, nicht alle "Bad file descriptor" Fehler + if (error == EBADF) { + #ifdef YC_DEBUG + std::cout << "[Debug] WebSocket " << socket << " closed by client, skipping send" << std::endl; + #endif + } else if (error == EPIPE) { + #ifdef YC_DEBUG + std::cout << "[Debug] Broken pipe on WebSocket " << socket << ", connection closed" << std::endl; + #endif + } else if (error == ECONNRESET) { + #ifdef YC_DEBUG + std::cout << "[Debug] Connection reset by peer on WebSocket " << socket << std::endl; + #endif + } else { + // Nur unbekannte Fehler als Error loggen + std::cout << "[Error] Fehler beim Senden auf WebSocket " << socket << ": " << strerror(error) << std::endl; + } + } } Json::Value Base::getJsonTree(const std::string& msg) {