Verbessere Socket-Validierung und Fehlerbehandlung in ChatUser und Base
- 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.
This commit is contained in:
@@ -128,6 +128,9 @@ namespace Yc
|
|||||||
newUser->sendMsg(ChatUser::roomList, roomList, "", "");
|
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
|
// Sende aktuelle Userliste an den neuen User
|
||||||
Json::Value currentUserList = userList();
|
Json::Value currentUserList = userList();
|
||||||
newUser->sendMsg(ChatUser::userListe, currentUserList, "", "");
|
newUser->sendMsg(ChatUser::userListe, currentUserList, "", "");
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <fcntl.h>
|
||||||
#include "chat_room.h"
|
#include "chat_room.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
@@ -336,6 +337,8 @@ namespace Yc
|
|||||||
void ChatUser::stop()
|
void ChatUser::stop()
|
||||||
{
|
{
|
||||||
_stop = true;
|
_stop = true;
|
||||||
|
// Socket als ungültig markieren
|
||||||
|
_socket = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ChatUser::color() const
|
std::string ChatUser::color() const
|
||||||
@@ -349,12 +352,38 @@ namespace Yc
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ChatUser::send(std::string out) {
|
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
|
// Entferne ggf. Token-Felder aus JSON-Strings und sende über Socket/WebSocket
|
||||||
Base::sanitizeTokensInString(out);
|
Base::sanitizeTokensInString(out);
|
||||||
Base::send(_socket, out);
|
Base::send(_socket, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatUser::send(Json::Value 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
|
// Entferne rekursiv alle Token-Felder und sende über Socket/WebSocket
|
||||||
Base::sanitizeTokens(out);
|
Base::sanitizeTokens(out);
|
||||||
Base::send(_socket, out);
|
Base::send(_socket, out);
|
||||||
|
|||||||
@@ -64,9 +64,35 @@ namespace Yc {
|
|||||||
sendWebSocketMessage(socket, out);
|
sendWebSocketMessage(socket, out);
|
||||||
return;
|
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());
|
ssize_t result = write(socket, out.c_str(), out.length());
|
||||||
if (result < 0) {
|
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) {
|
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;
|
std::string frame;
|
||||||
unsigned char hdr[2];
|
unsigned char hdr[2];
|
||||||
hdr[0] = 0x80 | 0x1; // FIN + text
|
hdr[0] = 0x80 | 0x1; // FIN + text
|
||||||
@@ -230,7 +264,28 @@ namespace Yc {
|
|||||||
frame.append(reinterpret_cast<char*>(ext), 8);
|
frame.append(reinterpret_cast<char*>(ext), 8);
|
||||||
}
|
}
|
||||||
frame.append(out);
|
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) {
|
Json::Value Base::getJsonTree(const std::string& msg) {
|
||||||
|
|||||||
Reference in New Issue
Block a user