Skip to content

Commit cc6da5e

Browse files
Merge pull request esphome#7 from ESP32Async/issue-4
Introduce -D ASYNCWEBSERVER_USE_CHUNK_INFLIGHT=0|1 to be able to enabled/disable inflight in chunk response
2 parents 8183c6d + 1d154df commit cc6da5e

File tree

6 files changed

+35
-3
lines changed

6 files changed

+35
-3
lines changed

.github/workflows/ci.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,9 @@ jobs:
109109
- env: ci-arduino-3-no-json
110110
board: esp32dev
111111

112+
- env: ci-arduino-3-chunk-inflight
113+
board: esp32dev
114+
112115
- env: ci-esp8266
113116
board: huzzah
114117
- env: ci-esp8266

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,8 @@ I personally use the following configuration in my projects:
208208
-D CONFIG_ASYNC_TCP_STACK_SIZE=4096 // reduce the stack size (default is 16K)
209209
```
210210

211+
If you need to server long / slow requests using chunk encoding (like fiel download from SD Card), you might need to set `-D ASYNCWEBSERVER_USE_CHUNK_INFLIGHT=1`.
212+
211213
## `AsyncWebSocketMessageBuffer` and `makeBuffer()`
212214

213215
The fork from [yubox-node-org](https://github.com/yubox-node-org/ESPAsyncWebServer) introduces some breaking API changes compared to the original library, especially regarding the use of `std::shared_ptr<std::vector<uint8_t>>` for WebSocket.

platformio.ini

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ lib_deps =
5050
; board = esp32-s3-devkitc-1
5151
; board = esp32-c6-devkitc-1
5252

53+
[env:arduino-3-chunk-inflight]
54+
build_flags = ${env.build_flags}
55+
-D ASYNCWEBSERVER_USE_CHUNK_INFLIGHT=1
56+
5357
[env:perf-test-AsyncTCP]
5458
build_flags = ${env.build_flags}
5559
-D PERF_TEST=1
@@ -94,6 +98,11 @@ board = ${sysenv.PIO_BOARD}
9498
lib_deps =
9599
ESP32Async/AsyncTCP @ 3.3.2
96100

101+
[env:ci-arduino-3-chunk-inflight]
102+
board = ${sysenv.PIO_BOARD}
103+
build_flags = ${env.build_flags}
104+
-D ASYNCWEBSERVER_USE_CHUNK_INFLIGHT=1
105+
97106
[env:ci-esp8266]
98107
platform = espressif8266
99108
board = ${sysenv.PIO_BOARD}

src/ESPAsyncWebServer.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,12 @@
6060
#define ASYNCWEBSERVER_REGEX_ATTRIBUTE __attribute__((warning("ASYNCWEBSERVER_REGEX not defined")))
6161
#endif
6262

63+
// See https://github.com/ESP32Async/ESPAsyncWebServer/commit/3d3456e9e81502a477f6498c44d0691499dda8f9#diff-646b25b11691c11dce25529e3abce843f0ba4bd07ab75ec9eee7e72b06dbf13fR388-R392
64+
// This setting slowdown chunk serving but avoids crashing or deadlocks in the case where slow chunk responses are created, like file serving form SD Card
65+
#ifndef ASYNCWEBSERVER_USE_CHUNK_INFLIGHT
66+
#define ASYNCWEBSERVER_USE_CHUNK_INFLIGHT 0
67+
#endif
68+
6369
class AsyncWebServer;
6470
class AsyncWebServerRequest;
6571
class AsyncWebServerResponse;

src/WebResponseImpl.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,12 @@ class AsyncBasicResponse : public AsyncWebServerResponse {
4747

4848
class AsyncAbstractResponse : public AsyncWebServerResponse {
4949
private:
50+
#if ASYNCWEBSERVER_USE_CHUNK_INFLIGHT
5051
// amount of responce data in-flight, i.e. sent, but not acked yet
5152
size_t _in_flight{0};
5253
// in-flight queue credits
5354
size_t _in_flight_credit{2};
55+
#endif
5456
String _head;
5557
// Data is inserted into cache at begin().
5658
// This is inefficient with vector, but if we use some other container,

src/WebResponses.cpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -352,21 +352,25 @@ size_t AsyncAbstractResponse::_ack(AsyncWebServerRequest* request, size_t len, u
352352
request->client()->close();
353353
return 0;
354354
}
355+
356+
#if ASYNCWEBSERVER_USE_CHUNK_INFLIGHT
355357
// return a credit for each chunk of acked data (polls does not give any credits)
356358
if (len)
357359
++_in_flight_credit;
358360

359361
// for chunked responses ignore acks if there are no _in_flight_credits left
360362
if (_chunked && !_in_flight_credit) {
361-
#ifdef ESP32
363+
#ifdef ESP32
362364
log_d("(chunk) out of in-flight credits");
363-
#endif
365+
#endif
364366
return 0;
365367
}
366368

367-
_ackedLength += len;
368369
_in_flight -= (_in_flight > len) ? len : _in_flight;
369370
// get the size of available sock space
371+
#endif
372+
373+
_ackedLength += len;
370374
size_t space = request->client()->space();
371375

372376
size_t headLen = _head.length();
@@ -378,13 +382,16 @@ size_t AsyncAbstractResponse::_ack(AsyncWebServerRequest* request, size_t len, u
378382
String out = _head.substring(0, space);
379383
_head = _head.substring(space);
380384
_writtenLength += request->client()->write(out.c_str(), out.length());
385+
#if ASYNCWEBSERVER_USE_CHUNK_INFLIGHT
381386
_in_flight += out.length();
382387
--_in_flight_credit; // take a credit
388+
#endif
383389
return out.length();
384390
}
385391
}
386392

387393
if (_state == RESPONSE_CONTENT) {
394+
#if ASYNCWEBSERVER_USE_CHUNK_INFLIGHT
388395
// for response data we need to control the queue and in-flight fragmentation. Sending small chunks could give low latency,
389396
// but flood asynctcp's queue and fragment socket buffer space for large responses.
390397
// Let's ignore polled acks and acks in case when we have more in-flight data then the available socket buff space.
@@ -396,6 +403,7 @@ size_t AsyncAbstractResponse::_ack(AsyncWebServerRequest* request, size_t len, u
396403
--_in_flight_credit;
397404
return 0;
398405
}
406+
#endif
399407

400408
size_t outLen;
401409
if (_chunked) {
@@ -451,8 +459,10 @@ size_t AsyncAbstractResponse::_ack(AsyncWebServerRequest* request, size_t len, u
451459

452460
if (outLen) {
453461
_writtenLength += request->client()->write((const char*)buf, outLen);
462+
#if ASYNCWEBSERVER_USE_CHUNK_INFLIGHT
454463
_in_flight += outLen;
455464
--_in_flight_credit; // take a credit
465+
#endif
456466
}
457467

458468
if (_chunked) {

0 commit comments

Comments
 (0)