Skip to content

Commit 0969901

Browse files
Fix timeout in WebServer::_uploadReadByte and handleClient() (#2290)
Upstream patch espressif/arduino-esp32#9991
1 parent ea2de46 commit 0969901

File tree

3 files changed

+37
-9
lines changed

3 files changed

+37
-9
lines changed

Diff for: libraries/WebServer/src/HTTPServer.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ enum HTTPAuthMethod { BASIC_AUTH, DIGEST_AUTH };
4949
#define HTTP_MAX_DATA_AVAILABLE_WAIT 30 //ms to wait for the client to send the request when there is another client with data available
5050
#define HTTP_MAX_POST_WAIT 5000 //ms to wait for POST data to arrive
5151
#define HTTP_MAX_SEND_WAIT 5000 //ms to wait for data chunk to be ACKed
52-
#define HTTP_MAX_CLOSE_WAIT 2000 //ms to wait for the client to close the connection
52+
#define HTTP_MAX_CLOSE_WAIT 5000 //ms to wait for the client to close the connection
5353

5454
#define CONTENT_LENGTH_UNKNOWN ((size_t) -1)
5555
#define CONTENT_LENGTH_NOT_SET ((size_t) -2)
@@ -73,7 +73,7 @@ typedef struct {
7373
HTTPRawStatus status;
7474
size_t totalSize; // content size
7575
size_t currentSize; // size of data currently in buf
76-
uint8_t buf[HTTP_UPLOAD_BUFLEN];
76+
uint8_t buf[HTTP_RAW_BUFLEN];
7777
void *data; // additional data
7878
} HTTPRaw;
7979

Diff for: libraries/WebServer/src/Parsing.cpp

+34-5
Original file line numberDiff line numberDiff line change
@@ -360,13 +360,42 @@ int HTTPServer::_uploadReadByte(WiFiClient * client) {
360360
int res = client->read();
361361

362362
if (res < 0) {
363-
while (!client->available() && client->connected()) {
364-
delay(2);
365-
}
363+
// keep trying until you either read a valid byte or timeout
364+
const unsigned long startMillis = millis();
365+
const unsigned long timeoutIntervalMillis = client->getTimeout();
366+
bool timedOut = false;
367+
for (;;) {
368+
if (!client->connected()) {
369+
return -1;
370+
}
371+
// loosely modeled after blinkWithoutDelay pattern
372+
while (!timedOut && !client->available() && client->connected()) {
373+
delay(2);
374+
timedOut = (millis() - startMillis) >= timeoutIntervalMillis;
375+
}
366376

367-
res = client->read();
377+
res = client->read();
378+
if (res >= 0) {
379+
return res; // exit on a valid read
380+
}
381+
// NOTE: it is possible to get here and have all of the following
382+
// assertions hold true
383+
//
384+
// -- client.available() > 0
385+
// -- client.connected == true
386+
// -- res == -1
387+
//
388+
// a simple retry strategy overcomes this which is to say the
389+
// assertion is not permanent, but the reason that this works
390+
// is elusive, and possibly indicative of a more subtle underlying
391+
// issue
392+
393+
timedOut = (millis() - startMillis) >= timeoutIntervalMillis;
394+
if (timedOut) {
395+
return res; // exit on a timeout
396+
}
397+
}
368398
}
369-
370399
return res;
371400
}
372401

Diff for: libraries/WebServer/src/WebServerTemplate.h

+1-2
Original file line numberDiff line numberDiff line change
@@ -111,10 +111,9 @@ void WebServerTemplate<ServerType, DefaultPort>::handleClient() {
111111
case HC_WAIT_READ:
112112
// Wait for data from client to become available
113113
if (_currentClient->available()) {
114+
_currentClient->setTimeout(HTTP_MAX_SEND_WAIT);
114115
switch (_parseRequest(_currentClient)) {
115116
case CLIENT_REQUEST_CAN_CONTINUE:
116-
// Because HTTP_MAX_SEND_WAIT is expressed in milliseconds, it must be divided by 1000
117-
_currentClient->setTimeout(HTTP_MAX_SEND_WAIT / 1000);
118117
_contentLength = CONTENT_LENGTH_NOT_SET;
119118
_handleRequest();
120119
/* fallthrough */

0 commit comments

Comments
 (0)