serveLiveLeds: Use dynamic buffer

There were three problems here:
- AsyncWebServer is going to copy to a heap buffer anyways, so we might
   as well just pass it one it can use
- The buffer size estimate was wrong -- we need 9 bytes per pixel
   ("RRGGBB",), so the buffer could overflow, and it was not
   considering the extra 2D requirements
- On ESP8266, the stack allocation was overflowing the stack, causing
  corruption and crashes.
This commit is contained in:
Will Miles
2024-03-14 22:06:51 -04:00
committed by Frank
parent 9103f6a4df
commit 775e07c6d6

View File

@@ -1554,10 +1554,20 @@ bool serveLiveLeds(AsyncWebServerRequest* request, uint32_t wsClient)
uint16_t used = strip.getLengthTotal();
uint16_t n = (used -1) /MAX_LIVE_LEDS +1; //only serve every n'th LED if count over MAX_LIVE_LEDS
char buffer[2000];
strcpy_P(buffer, PSTR("{\"leds\":["));
obuf = buffer;
olen = 9;
#ifndef WLED_DISABLE_2D
if (strip.isMatrix) {
// ignore anything behid matrix (i.e. extra strip)
used = Segment::maxWidth*Segment::maxHeight; // always the size of matrix (more or less than strip.getLengthTotal())
n = 1;
if (used > MAX_LIVE_LEDS) n = 2;
if (used > MAX_LIVE_LEDS*4) n = 4;
}
#endif
DynamicBuffer buffer(9 + (9*MAX_LIVE_LEDS) + 7 + 5 + 6 + 5 + 6 + 5 + 2);
char* buf = buffer.data(); // assign buffer for oappnd() functions
strncpy_P(buffer.data(), PSTR("{\"leds\":["), buffer.size());
buf += 9; // sizeof(PSTR()) from last line
for (size_t i= 0; i < used; i += n)
{
@@ -1575,20 +1585,21 @@ bool serveLiveLeds(AsyncWebServerRequest* request, uint32_t wsClient)
g = qadd8(w, G(c));
b = qadd8(w, B(c));
}
olen += sprintf(obuf + olen, "\"%06X\",", RGBW32(r,g,b,0));
buf += sprintf_P(buf, PSTR("\"%06X\","), RGBW32(r,g,b,0));
}
olen -= 1;
oappend((const char*)F("],\"n\":"));
oappendi(n);
oappend("}");
buf--; // remove last comma
buf += sprintf_P(buf, PSTR("],\"n\":%d"), n);
(*buf++) = '}';
(*buf++) = 0;
if (request) {
request->send(200, "application/json", buffer);
request->send(200, "application/json", toString(std::move(buffer)));
}
#ifdef WLED_ENABLE_WEBSOCKETS
else {
wsc->text(obuf, olen);
wsc->text(toString(std::move(buffer)));
}
#endif
#endif
return true;
}
#endif