Skip to content

Commit e752e96

Browse files
authored
lwip2 updates: no more git sub-sub-module deps, faster checksum, backlog limitation and other fixes (#6887)
* upstream lwIP is now downloaded by a makefile, not subsubmoduled * lwip2: upstream lwIP not sub-sub-modules anymore lwip2: Allow IPv4 and IPv6 DNS and SNTP server configured via DHCP to co-exist (patch against upstream) * lwip2: enable tcp-listen-with-backlog feature * lwip2 submodule update: - enable more efficient chksum algorithm thanks to Richard Allen - enable tcp listener with backlog * more comments, fix backlog management, fix API * move default value definition in .cpp because one must not believe it can be redefined before including WiFiServer.h * improved backlog handling, it is no more a breaking change
1 parent bc4f000 commit e752e96

File tree

14 files changed

+134
-34
lines changed

14 files changed

+134
-34
lines changed

libraries/ESP8266WiFi/src/WiFiServer.cpp

Lines changed: 58 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,17 @@ extern "C" {
3535
#include "lwip/opt.h"
3636
#include "lwip/tcp.h"
3737
#include "lwip/inet.h"
38+
#include "lwip/init.h" // LWIP_VERSION_
3839
#include <include/ClientContext.h>
3940

41+
#ifndef MAX_PENDING_CLIENTS_PER_PORT
42+
#define MAX_PENDING_CLIENTS_PER_PORT 5
43+
#endif
44+
4045
WiFiServer::WiFiServer(const IPAddress& addr, uint16_t port)
4146
: _port(port)
4247
, _addr(addr)
43-
, _pcb(nullptr)
48+
, _listen_pcb(nullptr)
4449
, _unclaimed(nullptr)
4550
, _discarded(nullptr)
4651
{
@@ -49,7 +54,7 @@ WiFiServer::WiFiServer(const IPAddress& addr, uint16_t port)
4954
WiFiServer::WiFiServer(uint16_t port)
5055
: _port(port)
5156
, _addr(IP_ANY_TYPE)
52-
, _pcb(nullptr)
57+
, _listen_pcb(nullptr)
5358
, _unclaimed(nullptr)
5459
, _discarded(nullptr)
5560
{
@@ -60,30 +65,38 @@ void WiFiServer::begin() {
6065
}
6166

6267
void WiFiServer::begin(uint16_t port) {
68+
return begin(port, MAX_PENDING_CLIENTS_PER_PORT);
69+
}
70+
71+
void WiFiServer::begin(uint16_t port, uint8_t backlog) {
6372
close();
73+
if (!backlog)
74+
return;
6475
_port = port;
65-
err_t err;
6676
tcp_pcb* pcb = tcp_new();
6777
if (!pcb)
6878
return;
6979

7080
pcb->so_options |= SOF_REUSEADDR;
7181

7282
// (IPAddress _addr) operator-converted to (const ip_addr_t*)
73-
err = tcp_bind(pcb, _addr, _port);
74-
75-
if (err != ERR_OK) {
83+
if (tcp_bind(pcb, _addr, _port) != ERR_OK) {
7684
tcp_close(pcb);
7785
return;
7886
}
7987

88+
#if LWIP_VERSION_MAJOR == 1
8089
tcp_pcb* listen_pcb = tcp_listen(pcb);
90+
#else
91+
tcp_pcb* listen_pcb = tcp_listen_with_backlog(pcb, backlog);
92+
#endif
93+
8194
if (!listen_pcb) {
8295
tcp_close(pcb);
8396
return;
8497
}
85-
_pcb = listen_pcb;
86-
_port = _pcb->local_port;
98+
_listen_pcb = listen_pcb;
99+
_port = _listen_pcb->local_port;
87100
tcp_accept(listen_pcb, &WiFiServer::_s_accept);
88101
tcp_arg(listen_pcb, (void*) this);
89102
}
@@ -111,6 +124,10 @@ WiFiClient WiFiServer::available(byte* status) {
111124
(void) status;
112125
if (_unclaimed) {
113126
WiFiClient result(_unclaimed);
127+
#if LWIP_VERSION_MAJOR != 1
128+
_unclaimed->acceptPCB();
129+
tcp_backlog_accepted(_unclaimed->getPCB());
130+
#endif
114131
_unclaimed = _unclaimed->next();
115132
result.setNoDelay(getNoDelay());
116133
DEBUGV("WS:av\r\n");
@@ -122,21 +139,21 @@ WiFiClient WiFiServer::available(byte* status) {
122139
}
123140

124141
uint8_t WiFiServer::status() {
125-
if (!_pcb)
142+
if (!_listen_pcb)
126143
return CLOSED;
127-
return _pcb->state;
144+
return _listen_pcb->state;
128145
}
129146

130147
uint16_t WiFiServer::port() const {
131148
return _port;
132149
}
133150

134151
void WiFiServer::close() {
135-
if (!_pcb) {
152+
if (!_listen_pcb) {
136153
return;
137154
}
138-
tcp_close(_pcb);
139-
_pcb = nullptr;
155+
tcp_close(_listen_pcb);
156+
_listen_pcb = nullptr;
140157
}
141158

142159
void WiFiServer::stop() {
@@ -169,9 +186,36 @@ T* slist_append_tail(T* head, T* item) {
169186
long WiFiServer::_accept(tcp_pcb* apcb, long err) {
170187
(void) err;
171188
DEBUGV("WS:ac\r\n");
189+
190+
#if LWIP_VERSION_MAJOR == 1
191+
172192
ClientContext* client = new ClientContext(apcb, &WiFiServer::_s_discard, this);
193+
tcp_accepted(_listen_pcb);
194+
195+
#else
196+
197+
// backlog doc:
198+
// http://lwip.100.n7.nabble.com/Problem-re-opening-listening-pbc-tt32484.html#a32494
199+
// https://www.nongnu.org/lwip/2_1_x/group__tcp__raw.html#gaeff14f321d1eecd0431611f382fcd338
200+
201+
// lwip-v2: Tell ClientContext to not accept yet the connection (final 'false' below)
202+
ClientContext* client = new ClientContext(apcb, &WiFiServer::_s_discard, this, false);
203+
// increase lwIP's backlog
204+
tcp_backlog_delayed(apcb);
205+
206+
// Optimization Path:
207+
// when lwip-v1.4 is not allowed anymore,
208+
// - _accept() should not create ClientContext anymore
209+
// - apcb should be stored into some sort of linked list (->_unclaimed)
210+
// (the linked list would store tcp_pcb* instead of ClientContext*)
211+
// (TCP_PCB_EXTARGS might be used for that (lwIP's struct tcp_pcb))
212+
// - on available(), get the pcb back and create the ClientContext
213+
// (this is not done today for better source readability with lwip-1.4 around)
214+
215+
#endif
216+
173217
_unclaimed = slist_append_tail(_unclaimed, client);
174-
tcp_accepted(_pcb);
218+
175219
return ERR_OK;
176220
}
177221

libraries/ESP8266WiFi/src/WiFiServer.h

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,37 @@ extern "C" {
3131
#include "Server.h"
3232
#include "IPAddress.h"
3333

34+
// lwIP-v2 backlog facility allows to keep memory safe by limiting the
35+
// maximum number of incoming *pending clients*. Default number of possibly
36+
// simultaneously pending clients is defined in WiFiServer.cpp
37+
// (MAX_PENDING_CLIENTS_PER_PORT=5). User can overide it at runtime from
38+
// sketch:
39+
// WiFiServer::begin(port, max-simultaneous-pending-clients);
40+
//
41+
// An "incoming pending" client is a new incoming TCP connection trying to
42+
// reach the TCP server. It is "pending" until lwIP acknowledges it and
43+
// "accepted / no more pending" when user calls WiFiServer::available().
44+
//
45+
// Before the backlog feature or with lwIP-v1.4, there was no pending
46+
// connections: They were immediately accepted and filling RAM.
47+
//
48+
// Several pending clients can appear during the time when one client is
49+
// served by a long not-async service like ESP8266WebServer. During that
50+
// time WiFiServer::available() cannot be called.
51+
//
52+
// Note: This *does not limit* the number of *simultaneously accepted
53+
// clients*. Such limit management is left to the user.
54+
//
55+
// Thus, when the maximum number of pending connections is reached, new
56+
// connections are delayed.
57+
// By "delayed", it is meant that WiFiServer(lwIP) will not answer to the
58+
// SYN packet until there is room for a new one: The TCP server on that port
59+
// will be mute. The TCP client will regularly try to connect until success
60+
// or a timeout occurs (72s on windows).
61+
//
62+
// When user calls WiFiServer::available(), the tcp server stops muting and
63+
// answers to newcomers (until the "backlog" pending list is full again).
64+
3465
class ClientContext;
3566
class WiFiClient;
3667

@@ -39,7 +70,7 @@ class WiFiServer : public Server {
3970
protected:
4071
uint16_t _port;
4172
IPAddress _addr;
42-
tcp_pcb* _pcb;
73+
tcp_pcb* _listen_pcb;
4374

4475
ClientContext* _unclaimed;
4576
ClientContext* _discarded;
@@ -53,6 +84,7 @@ class WiFiServer : public Server {
5384
bool hasClient();
5485
void begin();
5586
void begin(uint16_t port);
87+
void begin(uint16_t port, uint8_t backlog);
5688
void setNoDelay(bool nodelay);
5789
bool getNoDelay();
5890
virtual size_t write(uint8_t);

libraries/ESP8266WiFi/src/include/ClientContext.h

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,27 @@ bool getDefaultPrivateGlobalSyncValue ();
3636
class ClientContext
3737
{
3838
public:
39-
ClientContext(tcp_pcb* pcb, discard_cb_t discard_cb, void* discard_cb_arg) :
39+
ClientContext(tcp_pcb* pcb, discard_cb_t discard_cb, void* discard_cb_arg, bool acceptNow = true) :
4040
_pcb(pcb), _rx_buf(0), _rx_buf_offset(0), _discard_cb(discard_cb), _discard_cb_arg(discard_cb_arg), _refcnt(0), _next(0),
4141
_sync(::getDefaultPrivateGlobalSyncValue())
4242
{
43-
tcp_setprio(pcb, TCP_PRIO_MIN);
44-
tcp_arg(pcb, this);
45-
tcp_recv(pcb, &_s_recv);
46-
tcp_sent(pcb, &_s_acked);
47-
tcp_err(pcb, &_s_error);
48-
tcp_poll(pcb, &_s_poll, 1);
43+
if (acceptNow)
44+
acceptPCB();
45+
}
46+
47+
tcp_pcb* getPCB ()
48+
{
49+
return _pcb;
50+
}
51+
52+
void acceptPCB()
53+
{
54+
tcp_setprio(_pcb, TCP_PRIO_MIN);
55+
tcp_arg(_pcb, this);
56+
tcp_recv(_pcb, &_s_recv);
57+
tcp_sent(_pcb, &_s_acked);
58+
tcp_err(_pcb, &_s_error);
59+
tcp_poll(_pcb, &_s_poll, 1);
4960

5061
// keep-alive not enabled by default
5162
//keepAlive();

tests/host/common/MockWiFiServer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ WiFiClient WiFiServer::available (uint8_t* status)
5959
{
6060
(void)status;
6161
if (hasClient())
62-
return WiFiClient(new ClientContext(serverAccept(pcb2int(_pcb))));
62+
return WiFiClient(new ClientContext(serverAccept(pcb2int(_listen_pcb))));
6363
return WiFiClient();
6464
}
6565

tests/host/common/MockWiFiServerSocket.cpp

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,13 @@ int serverAccept (int srvsock)
6060

6161
void WiFiServer::begin (uint16_t port)
6262
{
63+
return begin(port, !0);
64+
}
65+
66+
void WiFiServer::begin (uint16_t port, uint8_t backlog)
67+
{
68+
if (!backlog)
69+
return;
6370
_port = port;
6471
return begin();
6572
}
@@ -109,13 +116,13 @@ void WiFiServer::begin ()
109116

110117

111118
// store int into pointer
112-
_pcb = int2pcb(sock);
119+
_listen_pcb = int2pcb(sock);
113120
}
114121

115122
bool WiFiServer::hasClient ()
116123
{
117124
struct pollfd p;
118-
p.fd = pcb2int(_pcb);
125+
p.fd = pcb2int(_listen_pcb);
119126
p.events = POLLIN;
120127
return poll(&p, 1, 0) && p.revents == POLLIN;
121128
}
@@ -134,7 +141,7 @@ size_t WiFiServer::write (const uint8_t *buf, size_t size)
134141

135142
void WiFiServer::close ()
136143
{
137-
if (pcb2int(_pcb) >= 0)
138-
::close(pcb2int(_pcb));
139-
_pcb = int2pcb(-1);
144+
if (pcb2int(_listen_pcb) >= 0)
145+
::close(pcb2int(_listen_pcb));
146+
_listen_pcb = int2pcb(-1);
140147
}

tools/sdk/lib/liblwip2-1460-feat.a

7.1 KB
Binary file not shown.

tools/sdk/lib/liblwip2-1460.a

4.14 KB
Binary file not shown.

tools/sdk/lib/liblwip2-536-feat.a

7.1 KB
Binary file not shown.

tools/sdk/lib/liblwip2-536.a

4.14 KB
Binary file not shown.

tools/sdk/lib/liblwip6-1460-feat.a

8.69 KB
Binary file not shown.

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy