diff --git a/src/websocket_server.cpp b/src/websocket_server.cpp index a8cacc2..5e90ab6 100644 --- a/src/websocket_server.cpp +++ b/src/websocket_server.cpp @@ -322,6 +322,8 @@ int WebSocketServer::wsCallback(struct lws *wsi, if (ud->userId.empty()) { std::cerr << "[RECEIVE] getConnections: User-ID nicht gesetzt" << std::endl; + // Sende Fehlerantwort nicht während des Callbacks, sondern lege sie in die Queue + // und triggere den WRITEABLE-Callback später try { json errorResponse = { {"event", "getConnectionsResponse"}, @@ -329,7 +331,15 @@ int WebSocketServer::wsCallback(struct lws *wsi, {"error", "User-ID nicht gesetzt"} }; if (instance && wsi && ud) { - instance->sendMessageToConnection(wsi, ud, errorResponse.dump()); + // Lege Nachricht in die Queue, ohne sofort lws_callback_on_writable aufzurufen + { + std::lock_guard lock(ud->messageQueueMutex); + ud->messageQueue.push(errorResponse.dump()); + } + // Verwende lws_cancel_service, um den Service zu benachrichtigen + if (instance->context) { + lws_cancel_service(instance->context); + } } } catch (const std::exception &e) { std::cerr << "[RECEIVE] Fehler beim Senden der Fehlerantwort: " << e.what() << std::endl; @@ -350,7 +360,15 @@ int WebSocketServer::wsCallback(struct lws *wsi, {"error", "Zugriff verweigert: Nur Mainadmin-User können Verbindungen abfragen"} }; if (instance && wsi && ud) { - instance->sendMessageToConnection(wsi, ud, errorResponse.dump()); + // Lege Nachricht in die Queue, ohne sofort lws_callback_on_writable aufzurufen + { + std::lock_guard lock(ud->messageQueueMutex); + ud->messageQueue.push(errorResponse.dump()); + } + // Verwende lws_cancel_service, um den Service zu benachrichtigen + if (instance->context) { + lws_cancel_service(instance->context); + } } break; } @@ -366,7 +384,14 @@ int WebSocketServer::wsCallback(struct lws *wsi, if (instance && wsi && ud) { // 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, ud, response.dump()); + { + std::lock_guard lock(ud->messageQueueMutex); + ud->messageQueue.push(response.dump()); + } + // Verwende lws_cancel_service, um den Service zu benachrichtigen + if (instance->context) { + lws_cancel_service(instance->context); + } std::cout << "[RECEIVE] getConnections: Verbindungen an Mainadmin gesendet (" << response.dump().length() << " Bytes)" << std::endl; } } catch (const std::exception &e) { @@ -379,7 +404,15 @@ int WebSocketServer::wsCallback(struct lws *wsi, {"error", std::string("Fehler beim Abrufen der Verbindungen: ") + e.what()} }; if (instance && wsi && ud) { - instance->sendMessageToConnection(wsi, ud, errorResponse.dump()); + // Lege Nachricht in die Queue, ohne sofort lws_callback_on_writable aufzurufen + { + std::lock_guard lock(ud->messageQueueMutex); + ud->messageQueue.push(errorResponse.dump()); + } + // Verwende lws_cancel_service, um den Service zu benachrichtigen + if (instance->context) { + lws_cancel_service(instance->context); + } } } catch (...) { // Ignoriere Fehler beim Senden der Fehlerantwort @@ -756,6 +789,9 @@ void WebSocketServer::sendMessageToConnection(struct lws *wsi, WebSocketUserData } try { + // Prüfe ob wsi noch gültig ist (wenn verfügbar) + // lws_wsi_is_valid ist nicht in allen Versionen verfügbar, daher try-catch + bool wasEmpty = false; { std::lock_guard lock(ud->messageQueueMutex); @@ -766,11 +802,17 @@ void WebSocketServer::sendMessageToConnection(struct lws *wsi, WebSocketUserData // Nur wenn die Queue leer war, den Callback aufrufen // (sonst wird er bereits durch den WRITEABLE-Handler aufgerufen) if (wasEmpty) { - // lws_callback_on_writable kann sicher während eines Callbacks aufgerufen werden - lws_callback_on_writable(wsi); + // Verwende lws_cancel_service, um den Service zu benachrichtigen + // Das ist sicherer, wenn wir uns in einem Callback befinden + // lws_cancel_service triggert einen Service-Loop, der dann LWS_CALLBACK_SERVER_WRITEABLE aufruft + if (context) { + lws_cancel_service(context); + } } } catch (const std::exception &e) { std::cerr << "[sendMessageToConnection] Fehler: " << e.what() << std::endl; + } catch (...) { + std::cerr << "[sendMessageToConnection] Unbekannter Fehler" << std::endl; } }