Merge pull request #95 from mathieucarbou/issue-94

(fix #94) Remove MAX_PRINTF_LEN limitation and fixed wrong usage of vsnprintf
This commit is contained in:
Mathieu Carbou
2024-09-04 22:58:14 +02:00
committed by GitHub
2 changed files with 90 additions and 70 deletions

View File

@@ -26,6 +26,7 @@
AsyncWebServer server(80); AsyncWebServer server(80);
AsyncEventSource events("/events"); AsyncEventSource events("/events");
AsyncWebSocket ws("/ws");
const char* PARAM_MESSAGE PROGMEM = "message"; const char* PARAM_MESSAGE PROGMEM = "message";
const char* SSE_HTLM PROGMEM = R"( const char* SSE_HTLM PROGMEM = R"(
@@ -195,7 +196,32 @@ void setup() {
request->send(200, "text/html", SSE_HTLM); request->send(200, "text/html", SSE_HTLM);
}); });
ws.onEvent([](AsyncWebSocket* server, AsyncWebSocketClient* client, AwsEventType type, void* arg, uint8_t* data, size_t len) {
(void) len;
if (type == WS_EVT_CONNECT) {
Serial.println("ws connect");
client->setCloseClientOnQueueFull(false);
client->ping();
} else if (type == WS_EVT_DISCONNECT) {
Serial.println("ws disconnect");
} else if (type == WS_EVT_ERROR) {
Serial.println("ws error");
} else if (type == WS_EVT_PONG) {
Serial.println("ws pong");
} else if (type == WS_EVT_DATA) {
AwsFrameInfo* info = (AwsFrameInfo*)arg;
String msg = "";
if (info->final && info->index == 0 && info->len == len) {
if (info->opcode == WS_TEXT) {
data[len] = 0;
Serial.printf("ws text: %s\n", (char*)data);
}
}
}
});
server.addHandler(&events); server.addHandler(&events);
server.addHandler(&ws);
server.addHandler(jsonHandler); server.addHandler(jsonHandler);
server.addHandler(msgPackHandler); server.addHandler(msgPackHandler);
@@ -205,12 +231,19 @@ void setup() {
} }
uint32_t lastSSE = 0; uint32_t lastSSE = 0;
uint32_t delta = 5; uint32_t deltaSSE = 5;
uint32_t lastWS = 0;
uint32_t deltaWS = 100;
void loop() { void loop() {
uint32_t now = millis(); uint32_t now = millis();
if (now - lastSSE >= delta) { if (now - lastSSE >= deltaSSE) {
events.send(String("ping-") + now, "heartbeat", now); events.send(String("ping-") + now, "heartbeat", now);
lastSSE = millis(); lastSSE = millis();
} }
if (now - lastWS >= deltaWS) {
ws.printfAll("kp%.4f", (10.0 / 3.0));
lastWS = millis();
}
} }

View File

@@ -36,11 +36,8 @@
#include <Hash.h> #include <Hash.h>
#endif #endif
#define MAX_PRINTF_LEN 64
using namespace asyncsrv; using namespace asyncsrv;
size_t webSocketSendFrameWindow(AsyncClient* client) { size_t webSocketSendFrameWindow(AsyncClient* client) {
if (!client->canSend()) if (!client->canSend())
return 0; return 0;
@@ -589,30 +586,23 @@ void AsyncWebSocketClient::_onData(void* pbuf, size_t plen) {
size_t AsyncWebSocketClient::printf(const char* format, ...) { size_t AsyncWebSocketClient::printf(const char* format, ...) {
va_list arg; va_list arg;
va_start(arg, format); va_start(arg, format);
char* temp = new char[MAX_PRINTF_LEN]; size_t len = vsnprintf(nullptr, 0, format, arg);
if (!temp) {
va_end(arg);
return 0;
}
char* buffer = temp;
size_t len = vsnprintf(temp, MAX_PRINTF_LEN, format, arg);
va_end(arg); va_end(arg);
if (len > (MAX_PRINTF_LEN - 1)) { if (len == 0)
buffer = new char[len + 1];
if (!buffer) {
delete[] temp;
return 0; return 0;
}
char* buffer = new char[len + 1];
if (!buffer)
return 0;
va_start(arg, format); va_start(arg, format);
vsnprintf(buffer, len + 1, format, arg); len = vsnprintf(buffer, len + 1, format, arg);
va_end(arg); va_end(arg);
}
text(buffer, len); text(buffer, len);
if (buffer != temp) {
delete[] buffer; delete[] buffer;
}
delete[] temp;
return len; return len;
} }
@@ -620,30 +610,23 @@ size_t AsyncWebSocketClient::printf(const char* format, ...) {
size_t AsyncWebSocketClient::printf_P(PGM_P formatP, ...) { size_t AsyncWebSocketClient::printf_P(PGM_P formatP, ...) {
va_list arg; va_list arg;
va_start(arg, formatP); va_start(arg, formatP);
char* temp = new char[MAX_PRINTF_LEN]; size_t len = vsnprintf_P(nullptr, 0, formatP, arg);
if (!temp) {
va_end(arg);
return 0;
}
char* buffer = temp;
size_t len = vsnprintf_P(temp, MAX_PRINTF_LEN, formatP, arg);
va_end(arg); va_end(arg);
if (len > (MAX_PRINTF_LEN - 1)) { if (len == 0)
buffer = new char[len + 1];
if (!buffer) {
delete[] temp;
return 0; return 0;
}
char* buffer = new char[len + 1];
if (!buffer)
return 0;
va_start(arg, formatP); va_start(arg, formatP);
vsnprintf_P(buffer, len + 1, formatP, arg); len = vsnprintf_P(buffer, len + 1, formatP, arg);
va_end(arg); va_end(arg);
}
text(buffer, len); text(buffer, len);
if (buffer != temp) {
delete[] buffer; delete[] buffer;
}
delete[] temp;
return len; return len;
} }
#endif #endif
@@ -1008,22 +991,24 @@ size_t AsyncWebSocket::printf(uint32_t id, const char* format, ...) {
size_t AsyncWebSocket::printfAll(const char* format, ...) { size_t AsyncWebSocket::printfAll(const char* format, ...) {
va_list arg; va_list arg;
char* temp = new char[MAX_PRINTF_LEN]; va_start(arg, format);
if (!temp) size_t len = vsnprintf(nullptr, 0, format, arg);
va_end(arg);
if (len == 0)
return 0;
char* buffer = new char[len + 1];
if (!buffer)
return 0; return 0;
va_start(arg, format); va_start(arg, format);
size_t len = vsnprintf(temp, MAX_PRINTF_LEN, format, arg); len = vsnprintf(buffer, len + 1, format, arg);
va_end(arg);
delete[] temp;
AsyncWebSocketSharedBuffer buffer = std::make_shared<std::vector<uint8_t>>(len);
va_start(arg, format);
vsnprintf((char*)buffer->data(), len + 1, format, arg);
va_end(arg); va_end(arg);
textAll(buffer); textAll(buffer, len);
delete[] buffer;
return len; return len;
} }
@@ -1042,22 +1027,24 @@ size_t AsyncWebSocket::printf_P(uint32_t id, PGM_P formatP, ...) {
size_t AsyncWebSocket::printfAll_P(PGM_P formatP, ...) { size_t AsyncWebSocket::printfAll_P(PGM_P formatP, ...) {
va_list arg; va_list arg;
char* temp = new char[MAX_PRINTF_LEN]; va_start(arg, formatP);
if (!temp) size_t len = vsnprintf_P(nullptr, 0, formatP, arg);
va_end(arg);
if (len == 0)
return 0;
char* buffer = new char[len + 1];
if (!buffer)
return 0; return 0;
va_start(arg, formatP); va_start(arg, formatP);
size_t len = vsnprintf_P(temp, MAX_PRINTF_LEN, formatP, arg); len = vsnprintf_P(buffer, len + 1, formatP, arg);
va_end(arg);
delete[] temp;
AsyncWebSocketSharedBuffer buffer = std::make_shared<std::vector<uint8_t>>(len + 1);
va_start(arg, formatP);
vsnprintf_P((char*)buffer->data(), len + 1, formatP, arg);
va_end(arg); va_end(arg);
textAll(buffer); textAll(buffer, len);
delete[] buffer;
return len; return len;
} }
#endif #endif