Skip to content

Commit

Permalink
ESP8266WebServer - drop current HC_WAIT_READ connection sooner when a…
Browse files Browse the repository at this point in the history
…nother has data

Safari sometimes opens two connections when loading a page and only
sends a request over the second one, resulting in a 5 second wait
(HTTP_MAX_DATA_WAIT) before the request is processed. This commit
drops the current connection after 30ms (HTTP_MAX_DATA_AVAILABLE_WAIT)
when there is a new connection with data available or the buffer of
pending TCP clients is full (currently 5).
  • Loading branch information
aWZHY0yQH81uOYvH committed Jul 23, 2021
1 parent 40876dc commit e56cd84
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 4 deletions.
2 changes: 2 additions & 0 deletions doc/esp8266wifi/server-class.rst
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ Other Function Calls
.. code:: cpp
bool hasClient ()
size_t hasClientData ()
bool hasMaxPendingClients ()
bool getNoDelay ()
virtual size_t write (const uint8_t *buf, size_t size)
uint8_t status ()
Expand Down
15 changes: 11 additions & 4 deletions libraries/ESP8266WebServer/src/ESP8266WebServer-impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -335,11 +335,18 @@ void ESP8266WebServerTemplate<ServerType>::handleClient() {
} // switch _parseRequest()
} else {
// !_currentClient.available(): waiting for more data
if (millis() - _statusChange <= HTTP_MAX_DATA_WAIT) {
keepCurrentClient = true;
unsigned long timeSinceChange = millis() - _statusChange;
// Use faster connection drop timeout if any other client has data
// or the buffer of pending clients is full
if ((_server.hasClientData() || _server.hasMaxPendingClients())
&& timeSinceChange > HTTP_MAX_DATA_AVAILABLE_WAIT)
DBGWS("webserver: closing since there's another connection to read from\n");
else {
if (timeSinceChange > HTTP_MAX_DATA_WAIT)
DBGWS("webserver: closing after read timeout\n");
else
keepCurrentClient = true;
}
else
DBGWS("webserver: closing after read timeout\n");
callYield = true;
}
break;
Expand Down
1 change: 1 addition & 0 deletions libraries/ESP8266WebServer/src/ESP8266WebServer.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ enum HTTPAuthMethod { BASIC_AUTH, DIGEST_AUTH };
#endif

#define HTTP_MAX_DATA_WAIT 5000 //ms to wait for the client to send the request
#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
#define HTTP_MAX_POST_WAIT 5000 //ms to wait for POST data to arrive
#define HTTP_MAX_SEND_WAIT 5000 //ms to wait for data chunk to be ACKed
#define HTTP_MAX_CLOSE_WAIT 2000 //ms to wait for the client to close the connection
Expand Down
19 changes: 19 additions & 0 deletions libraries/ESP8266WiFi/src/WiFiServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,25 @@ bool WiFiServer::hasClient() {
return false;
}

size_t WiFiServer::hasClientData() {
ClientContext *next = _unclaimed;
while (next) {
size_t s = next->getSize();
// return the amount of data available from the first connection that has any
if (s) return s;
next = next->next();
}
return 0;
}

bool WiFiServer::hasMaxPendingClients() {
#if TCP_LISTEN_BACKLOG
return ((struct tcp_pcb_listen *)_listen_pcb)->accepts_pending >= MAX_PENDING_CLIENTS_PER_PORT;
#else
return false;
#endif
}

WiFiClient WiFiServer::available(byte* status) {
(void) status;
if (_unclaimed) {
Expand Down
7 changes: 7 additions & 0 deletions libraries/ESP8266WiFi/src/WiFiServer.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,13 @@ class WiFiServer : public Server {
virtual ~WiFiServer() {}
WiFiClient available(uint8_t* status = NULL);
bool hasClient();
// hasClientData():
// returns the amount of data available from the first client
// or 0 if there is none
size_t hasClientData();
// hasMaxPendingClients():
// returns true if the queue of pending clients is full
bool hasMaxPendingClients();
void begin();
void begin(uint16_t port);
void begin(uint16_t port, uint8_t backlog);
Expand Down

0 comments on commit e56cd84

Please sign in to comment.