diff --git a/doc/esp8266wifi/client-class.rst b/doc/esp8266wifi/client-class.rst index 11e412181..7875a416f 100644 --- a/doc/esp8266wifi/client-class.rst +++ b/doc/esp8266wifi/client-class.rst @@ -29,6 +29,35 @@ Default input value 0 means that effective value is left at the discretion of th ``stop()`` returns ``false`` in case of an issue when closing the client (for instance a timed-out ``flush``). Depending on implementation, its parameter can be passed to ``flush()``. +abort +~~~~~ + +.. code:: cpp + + void abort(); + + +Originally proposed in `#8738 `__ +Unlike ``stop()``, immediately shuts down internal connection object. + +Under usual circumstances, we either enter ``CLOSE_WAIT`` or ``TIME_WAIT`` state. But, the connection object is not freed right away, and requires us to either +* wait until ``malloc()`` returns ``NULL`` when our TCP stack tries to allocate memory for a new connection +* manually call ``tcp_kill_timewait()`` to forcibly stop the 'oldest' connection + +This API frees up resources used by the connection. Consider using it instead of ``stop()`` if your application handles a lot of clients and frequently runs out of available heap memory. + +*Example:* + +.. code:: cpp + # define MIN_HEAP_FREE 20000 // or whatever min available heap memory convienent for your application + auto client = server.accept(); + // ... do something with the client object ... + if (ESP.getFreeHeap() >= MIN_HEAP_FREE) { + client.stop(); + } else { + client.abort(); + } + setNoDelay ~~~~~~~~~~ diff --git a/libraries/ESP8266WiFi/src/WiFiClient.cpp b/libraries/ESP8266WiFi/src/WiFiClient.cpp index 6cdd5d180..fb10209ec 100644 --- a/libraries/ESP8266WiFi/src/WiFiClient.cpp +++ b/libraries/ESP8266WiFi/src/WiFiClient.cpp @@ -376,6 +376,17 @@ uint16_t WiFiClient::localPort() return _client->getLocalPort(); } +// Api for heap saving. Optional use instead of WiFiClient::stop to systematically retreive some heap memory +// and avoiding server crashes in case of frequent clients connections. +void WiFiClient::abort() +{ + if (!_client) + return; + + flush(0); // Flush output buffer. Don't make any use of return boolean. + _client->abort(); // Wich in turn calls tcp_abort which calls tcp_abandon(). +} + void WiFiClient::stopAll() { for (WiFiClient* it = _s_first; it; it = it->_next) { diff --git a/libraries/ESP8266WiFi/src/WiFiClient.h b/libraries/ESP8266WiFi/src/WiFiClient.h index 170c983c0..41ec5d854 100644 --- a/libraries/ESP8266WiFi/src/WiFiClient.h +++ b/libraries/ESP8266WiFi/src/WiFiClient.h @@ -103,7 +103,7 @@ public: friend class WiFiServer; using Print::write; - + static void stopAll(); static void stopAllExcept(WiFiClient * c); @@ -148,6 +148,10 @@ public: virtual bool outputCanTimeout () override { return connected(); } virtual bool inputCanTimeout () override { return connected(); } + // Immediately stops this client instance. + // Unlike stop(), does not wait to gracefuly shutdown the connection. + void abort(); + protected: static int8_t _s_connected(void* arg, void* tpcb, int8_t err);