diff --git a/src/websocket_server.cpp b/src/websocket_server.cpp index 6937da9..9b4b418 100644 --- a/src/websocket_server.cpp +++ b/src/websocket_server.cpp @@ -337,7 +337,8 @@ int WebSocketServer::wsCallback(struct lws *wsi, break; } - // Prüfe Mainadmin-Rechte + // Prüfe Mainadmin-Rechte und sende Antwort asynchron + // (nicht während des Callbacks, um Verbindungsprobleme zu vermeiden) try { if (!instance || !instance->isMainAdmin(ud->userId)) { std::cerr << "[RECEIVE] getConnections: Zugriff verweigert für User " << ud->userId << std::endl; @@ -352,7 +353,8 @@ int WebSocketServer::wsCallback(struct lws *wsi, break; } - // Hole aktive Verbindungen + // Hole aktive Verbindungen und sende Antwort + // Wichtig: getActiveConnections() sollte schnell sein und keine langen Operationen durchführen json connections = instance->getActiveConnections(); json response = { {"event", "getConnectionsResponse"}, @@ -360,11 +362,26 @@ int WebSocketServer::wsCallback(struct lws *wsi, {"data", connections} }; if (instance && wsi) { + // Sende die Nachricht, aber nicht während des Callbacks + // Die Nachricht wird in die Queue gelegt und beim nächsten WRITEABLE gesendet instance->sendMessageToConnection(wsi, response.dump()); - std::cout << "[RECEIVE] getConnections: Verbindungen an Mainadmin gesendet" << std::endl; + std::cout << "[RECEIVE] getConnections: Verbindungen an Mainadmin gesendet (" << response.dump().length() << " Bytes)" << std::endl; } } catch (const std::exception &e) { std::cerr << "[RECEIVE] Fehler bei getConnections: " << e.what() << std::endl; + // Sende Fehlerantwort + try { + json errorResponse = { + {"event", "getConnectionsResponse"}, + {"success", false}, + {"error", std::string("Fehler beim Abrufen der Verbindungen: ") + e.what()} + }; + if (instance && wsi) { + instance->sendMessageToConnection(wsi, errorResponse.dump()); + } + } catch (...) { + // Ignoriere Fehler beim Senden der Fehlerantwort + } } } else { std::cout << "[RECEIVE] Unbekanntes Event: " << event << std::endl; @@ -393,12 +410,34 @@ int WebSocketServer::wsCallback(struct lws *wsi, } if (!messageToSend.empty()) { + // Prüfe ob Nachricht zu groß ist (max 4096 Bytes) + if (messageToSend.length() > 4096) { + std::cerr << "[WRITEABLE] Warnung: Nachricht zu groß (" << messageToSend.length() << " Bytes), wird abgeschnitten" << std::endl; + messageToSend = messageToSend.substr(0, 4096); + } + // Nachricht senden - std::cout << "[WRITEABLE] Sende Nachricht: " << messageToSend << std::endl; + std::cout << "[WRITEABLE] Sende Nachricht (" << messageToSend.length() << " Bytes): " << (messageToSend.length() > 100 ? messageToSend.substr(0, 100) + "..." : messageToSend) << std::endl; unsigned char buf[LWS_PRE + messageToSend.length()]; memcpy(buf + LWS_PRE, messageToSend.c_str(), messageToSend.length()); - lws_write(wsi, buf + LWS_PRE, messageToSend.length(), LWS_WRITE_TEXT); - std::cout << "[WRITEABLE] Nachricht erfolgreich gesendet" << std::endl; + int ret = lws_write(wsi, buf + LWS_PRE, messageToSend.length(), LWS_WRITE_TEXT); + if (ret < 0) { + std::cerr << "[WRITEABLE] Fehler beim Senden: lws_write returned " << ret << " - Verbindung wird möglicherweise geschlossen" << std::endl; + // Bei Fehler: Verbindung wird wahrscheinlich geschlossen, entferne aus Queue + { + std::lock_guard lock(ud->messageQueueMutex); + // Leere die Queue, da die Verbindung nicht mehr funktioniert + while (!ud->messageQueue.empty()) { + ud->messageQueue.pop(); + } + } + // Keine weitere Aktion - die Verbindung wird durch libwebsockets geschlossen + return -1; // Signalisiert libwebsockets, dass die Verbindung geschlossen werden soll + } else if (ret != static_cast(messageToSend.length())) { + std::cerr << "[WRITEABLE] Warnung: Nur " << ret << " von " << messageToSend.length() << " Bytes gesendet" << std::endl; + } else { + std::cout << "[WRITEABLE] Nachricht erfolgreich gesendet (" << ret << " Bytes)" << std::endl; + } // Wenn noch weitere Nachrichten in der Queue sind, wieder schreibbereit machen { @@ -711,10 +750,7 @@ void WebSocketServer::sendMessageToConnection(struct lws *wsi, const std::string // Nur wenn die Queue leer war, den Callback aufrufen // (sonst wird er bereits durch den WRITEABLE-Handler aufgerufen) if (wasEmpty) { - // Verwende lws_cancel_service, um den Service zu benachrichtigen, anstatt - // lws_callback_on_writable direkt aufzurufen (sicherer während Callbacks) - lws_cancel_service(context); - // Alternativ: lws_callback_on_writable(wsi) sollte auch funktionieren + // lws_callback_on_writable kann sicher während eines Callbacks aufgerufen werden lws_callback_on_writable(wsi); } } catch (const std::exception &e) {