Reverted Websocket Code to previous commit
This commit is contained in:
@@ -105,83 +105,53 @@ void WebSocketServer::onConnect(AsyncWebSocketClient* client) {
|
|||||||
|
|
||||||
void WebSocketServer::onDisconnect(AsyncWebSocketClient* client) {
|
void WebSocketServer::onDisconnect(AsyncWebSocketClient* client) {
|
||||||
LOG_INFO("WebSocket client #%u disconnected", client->id());
|
LOG_INFO("WebSocket client #%u disconnected", client->id());
|
||||||
|
|
||||||
// Clean up any fragment buffer for this client
|
|
||||||
_fragmentBuffers.erase(client->id());
|
|
||||||
|
|
||||||
_clientManager.removeClient(client->id());
|
_clientManager.removeClient(client->id());
|
||||||
_clientManager.cleanupDisconnectedClients();
|
_clientManager.cleanupDisconnectedClients();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebSocketServer::onData(AsyncWebSocketClient* client, void* arg, uint8_t* data, size_t len) {
|
void WebSocketServer::onData(AsyncWebSocketClient* client, void* arg, uint8_t* data, size_t len) {
|
||||||
AwsFrameInfo* info = (AwsFrameInfo*)arg;
|
AwsFrameInfo* info = (AwsFrameInfo*)arg;
|
||||||
uint32_t clientId = client->id();
|
|
||||||
|
// Only handle complete, single-frame text messages
|
||||||
// Use message_opcode to get the actual message type (not the frame opcode)
|
if (info->final && info->index == 0 && info->len == len && info->opcode == WS_TEXT) {
|
||||||
uint8_t messageOpcode = info->message_opcode;
|
// Allocate buffer for payload
|
||||||
|
char* payload = (char*)malloc(len + 1);
|
||||||
// Only handle TEXT and BINARY messages
|
if (!payload) {
|
||||||
if (messageOpcode != WS_TEXT && messageOpcode != WS_BINARY) {
|
LOG_ERROR("Failed to allocate memory for WebSocket payload");
|
||||||
LOG_DEBUG("WebSocket client #%u: ignoring non-text/binary message (opcode: %u)", clientId, messageOpcode);
|
String errorResponse = ResponseBuilder::error("memory_error", "Out of memory");
|
||||||
return;
|
_clientManager.sendToClient(client->id(), errorResponse);
|
||||||
}
|
return;
|
||||||
|
|
||||||
// NOTE: As of ESPAsyncWebServer v3.9.3, the library automatically unmasks the data
|
|
||||||
// before calling this handler. The 'data' pointer contains plain, unmasked bytes.
|
|
||||||
|
|
||||||
// Handle fragmented messages - reassemble them
|
|
||||||
if (info->index == 0) {
|
|
||||||
// First chunk - create or reset buffer
|
|
||||||
FragmentBuffer& buffer = _fragmentBuffers[clientId];
|
|
||||||
buffer.data = "";
|
|
||||||
|
|
||||||
if (info->len > 0 && info->len < 65536) {
|
|
||||||
buffer.data.reserve(info->len);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer.opcode = messageOpcode;
|
memcpy(payload, data, len);
|
||||||
buffer.lastUpdate = millis();
|
payload[len] = '\0';
|
||||||
|
|
||||||
if (info->len > len) {
|
LOG_DEBUG("WebSocket client #%u sent: %s", client->id(), payload);
|
||||||
LOG_DEBUG("WebSocket client #%u: started fragmented message (%llu bytes total)", clientId, info->len);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get or create buffer for this client
|
|
||||||
FragmentBuffer& buffer = _fragmentBuffers[clientId];
|
|
||||||
|
|
||||||
// Append this chunk to the buffer (data is already unmasked by the library)
|
|
||||||
buffer.data.concat((const char*)data, len);
|
|
||||||
buffer.lastUpdate = millis();
|
|
||||||
|
|
||||||
// Check if message is complete
|
|
||||||
if (info->final && buffer.data.length() >= info->len) {
|
|
||||||
String completeMessage = buffer.data;
|
|
||||||
uint8_t opcode = buffer.opcode;
|
|
||||||
_fragmentBuffers.erase(clientId);
|
|
||||||
|
|
||||||
LOG_DEBUG("WebSocket client #%u sent (%u bytes): %s",
|
|
||||||
clientId, completeMessage.length(), completeMessage.c_str());
|
|
||||||
|
|
||||||
// Parse JSON
|
// Parse JSON
|
||||||
StaticJsonDocument<2048> doc;
|
StaticJsonDocument<2048> doc;
|
||||||
DeserializationError error = deserializeJson(doc, completeMessage);
|
DeserializationError error = deserializeJson(doc, payload);
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
LOG_ERROR("Failed to parse WebSocket JSON from client #%u: %s", clientId, error.c_str());
|
LOG_ERROR("Failed to parse WebSocket JSON from client #%u: %s", client->id(), error.c_str());
|
||||||
String errorResponse = ResponseBuilder::error("parse_error", "Invalid JSON");
|
String errorResponse = ResponseBuilder::error("parse_error", "Invalid JSON");
|
||||||
_clientManager.sendToClient(clientId, errorResponse);
|
_clientManager.sendToClient(client->id(), errorResponse);
|
||||||
} else {
|
} else {
|
||||||
// Update client last seen time
|
// Update client last seen time
|
||||||
_clientManager.updateClientLastSeen(clientId);
|
_clientManager.updateClientLastSeen(client->id());
|
||||||
|
|
||||||
// Call user callback if set
|
// Call user callback if set
|
||||||
if (_messageCallback) {
|
if (_messageCallback) {
|
||||||
LOG_DEBUG("Routing message from client #%u to callback handler", clientId);
|
LOG_DEBUG("Routing message from client #%u to callback handler", client->id());
|
||||||
_messageCallback(clientId, doc);
|
_messageCallback(client->id(), doc);
|
||||||
} else {
|
} else {
|
||||||
LOG_WARNING("WebSocket message received but no callback handler is set!");
|
LOG_WARNING("WebSocket message received but no callback handler is set!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(payload);
|
||||||
|
} else {
|
||||||
|
LOG_WARNING("Received fragmented or non-text WebSocket message from client #%u - ignoring", client->id());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,6 @@
|
|||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <ESPAsyncWebServer.h>
|
#include <ESPAsyncWebServer.h>
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
#include <map>
|
|
||||||
#include "../../ClientManager/ClientManager.hpp"
|
#include "../../ClientManager/ClientManager.hpp"
|
||||||
|
|
||||||
class WebSocketServer {
|
class WebSocketServer {
|
||||||
@@ -78,14 +77,6 @@ private:
|
|||||||
ClientManager& _clientManager;
|
ClientManager& _clientManager;
|
||||||
MessageCallback _messageCallback;
|
MessageCallback _messageCallback;
|
||||||
|
|
||||||
// Fragment reassembly buffer (stores incomplete messages per client)
|
|
||||||
struct FragmentBuffer {
|
|
||||||
String data;
|
|
||||||
uint8_t opcode;
|
|
||||||
unsigned long lastUpdate;
|
|
||||||
};
|
|
||||||
std::map<uint32_t, FragmentBuffer> _fragmentBuffers;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Static WebSocket event handler
|
* @brief Static WebSocket event handler
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user