Skip to content

Commit 9fac290

Browse files
committed
Added close_abort() function to WiFiClient
This branch adds a close_abort() method to the WiFiClient class. How it works, what it does: Calling `close_abort()` will close and abort the client connection it is invoked on and, as a result, free its resources (i.e. memory). **WARNING:** aborting connections without a good reason violates the TCP protocol, because a closed connection would normally need to spend some time in `TIME_WAIT` state before its resources are freed. Usage example: WiFiClient client; // set up a client { /* do things with your client */ } client.stop_abort() // when you're done,abort the // connection if you must Why it's useful: 1. Give programmers a way to shut down connections immediately if need be. The underlying `tcp.c` file has an abort function, but this has not been directly accessible via the `WiFiClient` class until now. 2. There are a number of reported issues for the repository addressing the heap corruption that can result from trying to retain too many connections in `TIME_WAIT` state (most notably: esp8266#230, esp8266#1070, esp8266#1923). Although the warning above holds, there may be circumstances where this isn't very important. For example an ESP8266 running in AP mode hosting a page, which requests a new connection every second via an AJAX script to monitor a sensor/button/etc. continusously. Currently existing alternative approach: When building a project, defining the `-D MEMP_NUM_TCP_PCB_TIME_WAIT=5`compiler directive will limit the maximum number of clients allowed to stay in TIME_WAIT state. `5` is the default, lower it as necessary. See reference [here](https://github.com/esp8266/Arduino/blob/master/tools/sdk/lwip/include/lwipopts.h#L263) Thanks: Thank you to @me-no-dev, @everslick and @Palatis for bringing the ` MEMP_NUM_TCP_PCB_TIME_WAIT` option to my attention.
1 parent 7b32e6a commit 9fac290

File tree

3 files changed

+46
-0
lines changed

3 files changed

+46
-0
lines changed

libraries/ESP8266WiFi/src/WiFiClient.cpp

+9
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,15 @@ void WiFiClient::stop()
269269
_client = 0;
270270
}
271271

272+
void WiFiClient::stop_abort() //Compare this to ::stop
273+
{
274+
if (!_client)
275+
return;
276+
277+
_client->unref_abort();
278+
_client = 0;
279+
}
280+
272281
uint8_t WiFiClient::connected()
273282
{
274283
if (!_client)

libraries/ESP8266WiFi/src/WiFiClient.h

+1
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ class WiFiClient : public Client, public SList<WiFiClient> {
6464
}
6565
virtual void flush();
6666
virtual void stop();
67+
virtual void stop_abort();
6768
virtual uint8_t connected();
6869
virtual operator bool();
6970

libraries/ESP8266WiFi/src/include/ClientContext.h

+36
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,27 @@ class ClientContext
8686
}
8787
return err;
8888
}
89+
90+
err_t close_abort()
91+
{
92+
/* ERR_ABRT must be sent back on abortion as specified in the comments
93+
* of tools/sdk/lwip/src/core/tcp.c at the footnote of tcp_abort() */
94+
err_t err = ERR_ABRT;
95+
if(_pcb) {
96+
DEBUGV(":close\r\n");
97+
tcp_arg(_pcb, NULL);
98+
tcp_sent(_pcb, NULL);
99+
tcp_recv(_pcb, NULL);
100+
tcp_err(_pcb, NULL);
101+
tcp_close(_pcb);
102+
/* Without delay some clients fail to receive the response and
103+
* report a 'cannot connect' error message */
104+
delay(10);
105+
tcp_abort(_pcb);
106+
_pcb = 0;
107+
}
108+
return err;
109+
}
89110

90111
~ClientContext()
91112
{
@@ -123,6 +144,21 @@ class ClientContext
123144
}
124145
}
125146
}
147+
148+
void unref_abort()
149+
{
150+
if(this != 0) {
151+
DEBUGV(":ur_abrt %d\r\n", _refcnt);
152+
if(--_refcnt == 0) {
153+
flush();
154+
close_abort();
155+
if(_discard_cb)
156+
_discard_cb(_discard_cb_arg, this);
157+
DEBUGV(":del\r\n");
158+
delete this;
159+
}
160+
}
161+
}
126162

127163
void setNoDelay(bool nodelay)
128164
{

0 commit comments

Comments
 (0)