🪄 Updates eventsocket protocol

This commit is contained in:
Rune Harlyk
2024-06-18 16:03:07 +02:00
committed by Rune Harlyk
parent e4ea3992b3
commit 283c420f98
4 changed files with 1443 additions and 1367 deletions
+82 -21
View File
@@ -2,6 +2,49 @@
SemaphoreHandle_t clientSubscriptionsMutex = xSemaphoreCreateMutex();
message_type_t char_to_message_type(char c) {
switch(c) {
case '0': return CONNECT;
case '1': return DISCONNECT;
case '2': return EVENT;
case '3': return PING;
case '4': return PONG;
case '5': return BINARY_EVENT;
default: throw std::invalid_argument("Invalid message type");
}
}
const char* getEventName(const char* msg) {
const char* start = strchr(msg, '/');
if (!start) return nullptr;
start++;
const char* end = strchr(start, '[');
if (!end) return start;
static char eventName[32];
int len = end - start;
strncpy(eventName, start, len);
eventName[len] = '\0';
return eventName;
}
const char* getEventPayload(const char* msg) {
const char* start = strchr(msg + 4, '\"') - 1;
const char* end = msg + strlen(msg) - 1;
if (*start == '\"') {
start++;
}
if (*(end - 1) == '\"') {
end--;
}
int len = end - start;
if (len < 0) return nullptr;
char* payload = new char[len + 1];
strncpy(payload, start, len);
payload[len] = '\0';
return payload;
}
EventSocket::EventSocket(PsychicHttpServer *server,
SecurityManager *securityManager,
AuthenticationPredicate authenticationPredicate) : _server(server),
@@ -42,30 +85,48 @@ esp_err_t EventSocket::onFrame(PsychicWebSocketRequest *request, httpd_ws_frame
if (frame->type == HTTPD_WS_TYPE_TEXT)
{
ESP_LOGV("EventSocket", "ws[%s][%u] request: %s", request->client()->remoteIP().toString().c_str(),
request->client()->socket(), (char *)frame->payload);
ESP_LOGV("EventSocket", "Received message: %s", (char *)frame->payload);
char* msg = (char *)frame->payload;
JsonDocument doc;
DeserializationError error = deserializeJson(doc, (char *)frame->payload, frame->len);
message_type_t message_type = char_to_message_type(msg[0]);
if (!error && doc.is<JsonObject>())
{
String event = doc["event"];
if (event == "subscribe")
{
// only subscribe to events that are registered
client_subscriptions[doc["data"]].push_back(request->client()->socket());
handleSubscribeCallbacks(doc["data"], String(request->client()->socket()));
if (message_type == PING) {
ESP_LOGV("EventSocket", "Ping");
request->client()->sendMessage("3");
return ESP_OK;
} else if (message_type == PONG) {
ESP_LOGV("EventSocket", "Pong");
return ESP_OK;
}
const char* event = getEventName(msg);
if (!event) {
ESP_LOGE("EventSocket", "Invalid event name");
return ESP_OK;
}
if (message_type == CONNECT) {
ESP_LOGV("EventSocket", "Connect: %s", event);
client_subscriptions[event].push_back(request->client()->socket());
handleSubscribeCallbacks(event, String(request->client()->socket()));
} else if (message_type == DISCONNECT) {
ESP_LOGV("EventSocket", "Disconnect: %s", event);
client_subscriptions[event].remove(request->client()->socket());
} else if (message_type == EVENT) {
const char* payload = getEventPayload(msg);
if (!payload) {
ESP_LOGE("EventSocket", "Invalid event payload");
return ESP_OK;
}
else if (event == "unsubscribe")
{
client_subscriptions[doc["data"]].remove(request->client()->socket());
}
else
{
JsonObject jsonObject = doc["data"].as<JsonObject>();
handleEventCallbacks(event, jsonObject, request->client()->socket());
JsonDocument doc;
DeserializationError error = deserializeJson(doc, payload);
if (error) {
ESP_LOGE("EventSocket", "Failed to parse JSON payload");
return ESP_OK;
}
JsonObject jsonObject = doc.as<JsonObject>();
handleEventCallbacks(event, jsonObject, request->client()->socket());
return ESP_OK;
}
}
@@ -83,7 +144,7 @@ void EventSocket::emit(const char *event, const char *payload, const char *origi
return;
}
char msg[strlen(event) + strlen(payload) + 10];
snprintf(msg, sizeof(msg), "[\"%s\",%s]", event, payload);
snprintf(msg, sizeof(msg), "2/%s[%s]", event, payload);
// if onlyToSameOrigin == true, send the message back to the origin
if (onlyToSameOrigin && originSubscriptionId > 0)