diff --git a/libraries/ESP8266WiFi/src/WiFiServer.cpp b/libraries/ESP8266WiFi/src/WiFiServer.cpp index 494bf61dd5..2ba5c6c970 100644 --- a/libraries/ESP8266WiFi/src/WiFiServer.cpp +++ b/libraries/ESP8266WiFi/src/WiFiServer.cpp @@ -35,12 +35,17 @@ extern "C" { #include "lwip/opt.h" #include "lwip/tcp.h" #include "lwip/inet.h" +#include "lwip/init.h" // LWIP_VERSION_ #include +#ifndef MAX_PENDING_CLIENTS_PER_PORT +#define MAX_PENDING_CLIENTS_PER_PORT 5 +#endif + WiFiServer::WiFiServer(const IPAddress& addr, uint16_t port) : _port(port) , _addr(addr) -, _pcb(nullptr) +, _listen_pcb(nullptr) , _unclaimed(nullptr) , _discarded(nullptr) { @@ -49,7 +54,7 @@ WiFiServer::WiFiServer(const IPAddress& addr, uint16_t port) WiFiServer::WiFiServer(uint16_t port) : _port(port) , _addr(IP_ANY_TYPE) -, _pcb(nullptr) +, _listen_pcb(nullptr) , _unclaimed(nullptr) , _discarded(nullptr) { @@ -60,9 +65,14 @@ void WiFiServer::begin() { } void WiFiServer::begin(uint16_t port) { + return begin(port, MAX_PENDING_CLIENTS_PER_PORT); +} + +void WiFiServer::begin(uint16_t port, uint8_t backlog) { close(); + if (!backlog) + return; _port = port; - err_t err; tcp_pcb* pcb = tcp_new(); if (!pcb) return; @@ -70,20 +80,23 @@ void WiFiServer::begin(uint16_t port) { pcb->so_options |= SOF_REUSEADDR; // (IPAddress _addr) operator-converted to (const ip_addr_t*) - err = tcp_bind(pcb, _addr, _port); - - if (err != ERR_OK) { + if (tcp_bind(pcb, _addr, _port) != ERR_OK) { tcp_close(pcb); return; } +#if LWIP_VERSION_MAJOR == 1 tcp_pcb* listen_pcb = tcp_listen(pcb); +#else + tcp_pcb* listen_pcb = tcp_listen_with_backlog(pcb, backlog); +#endif + if (!listen_pcb) { tcp_close(pcb); return; } - _pcb = listen_pcb; - _port = _pcb->local_port; + _listen_pcb = listen_pcb; + _port = _listen_pcb->local_port; tcp_accept(listen_pcb, &WiFiServer::_s_accept); tcp_arg(listen_pcb, (void*) this); } @@ -111,6 +124,10 @@ WiFiClient WiFiServer::available(byte* status) { (void) status; if (_unclaimed) { WiFiClient result(_unclaimed); +#if LWIP_VERSION_MAJOR != 1 + _unclaimed->acceptPCB(); + tcp_backlog_accepted(_unclaimed->getPCB()); +#endif _unclaimed = _unclaimed->next(); result.setNoDelay(getNoDelay()); DEBUGV("WS:av\r\n"); @@ -122,9 +139,9 @@ WiFiClient WiFiServer::available(byte* status) { } uint8_t WiFiServer::status() { - if (!_pcb) + if (!_listen_pcb) return CLOSED; - return _pcb->state; + return _listen_pcb->state; } uint16_t WiFiServer::port() const { @@ -132,11 +149,11 @@ uint16_t WiFiServer::port() const { } void WiFiServer::close() { - if (!_pcb) { + if (!_listen_pcb) { return; } - tcp_close(_pcb); - _pcb = nullptr; + tcp_close(_listen_pcb); + _listen_pcb = nullptr; } void WiFiServer::stop() { @@ -169,9 +186,36 @@ T* slist_append_tail(T* head, T* item) { long WiFiServer::_accept(tcp_pcb* apcb, long err) { (void) err; DEBUGV("WS:ac\r\n"); + +#if LWIP_VERSION_MAJOR == 1 + ClientContext* client = new ClientContext(apcb, &WiFiServer::_s_discard, this); + tcp_accepted(_listen_pcb); + +#else + + // backlog doc: + // http://lwip.100.n7.nabble.com/Problem-re-opening-listening-pbc-tt32484.html#a32494 + // https://www.nongnu.org/lwip/2_1_x/group__tcp__raw.html#gaeff14f321d1eecd0431611f382fcd338 + + // lwip-v2: Tell ClientContext to not accept yet the connection (final 'false' below) + ClientContext* client = new ClientContext(apcb, &WiFiServer::_s_discard, this, false); + // increase lwIP's backlog + tcp_backlog_delayed(apcb); + + // Optimization Path: + // when lwip-v1.4 is not allowed anymore, + // - _accept() should not create ClientContext anymore + // - apcb should be stored into some sort of linked list (->_unclaimed) + // (the linked list would store tcp_pcb* instead of ClientContext*) + // (TCP_PCB_EXTARGS might be used for that (lwIP's struct tcp_pcb)) + // - on available(), get the pcb back and create the ClientContext + // (this is not done today for better source readability with lwip-1.4 around) + +#endif + _unclaimed = slist_append_tail(_unclaimed, client); - tcp_accepted(_pcb); + return ERR_OK; } diff --git a/libraries/ESP8266WiFi/src/WiFiServer.h b/libraries/ESP8266WiFi/src/WiFiServer.h index 7a4a3246d3..9df758bf05 100644 --- a/libraries/ESP8266WiFi/src/WiFiServer.h +++ b/libraries/ESP8266WiFi/src/WiFiServer.h @@ -31,6 +31,37 @@ extern "C" { #include "Server.h" #include "IPAddress.h" +// lwIP-v2 backlog facility allows to keep memory safe by limiting the +// maximum number of incoming *pending clients*. Default number of possibly +// simultaneously pending clients is defined in WiFiServer.cpp +// (MAX_PENDING_CLIENTS_PER_PORT=5). User can overide it at runtime from +// sketch: +// WiFiServer::begin(port, max-simultaneous-pending-clients); +// +// An "incoming pending" client is a new incoming TCP connection trying to +// reach the TCP server. It is "pending" until lwIP acknowledges it and +// "accepted / no more pending" when user calls WiFiServer::available(). +// +// Before the backlog feature or with lwIP-v1.4, there was no pending +// connections: They were immediately accepted and filling RAM. +// +// Several pending clients can appear during the time when one client is +// served by a long not-async service like ESP8266WebServer. During that +// time WiFiServer::available() cannot be called. +// +// Note: This *does not limit* the number of *simultaneously accepted +// clients*. Such limit management is left to the user. +// +// Thus, when the maximum number of pending connections is reached, new +// connections are delayed. +// By "delayed", it is meant that WiFiServer(lwIP) will not answer to the +// SYN packet until there is room for a new one: The TCP server on that port +// will be mute. The TCP client will regularly try to connect until success +// or a timeout occurs (72s on windows). +// +// When user calls WiFiServer::available(), the tcp server stops muting and +// answers to newcomers (until the "backlog" pending list is full again). + class ClientContext; class WiFiClient; @@ -39,7 +70,7 @@ class WiFiServer : public Server { protected: uint16_t _port; IPAddress _addr; - tcp_pcb* _pcb; + tcp_pcb* _listen_pcb; ClientContext* _unclaimed; ClientContext* _discarded; @@ -53,6 +84,7 @@ class WiFiServer : public Server { bool hasClient(); void begin(); void begin(uint16_t port); + void begin(uint16_t port, uint8_t backlog); void setNoDelay(bool nodelay); bool getNoDelay(); virtual size_t write(uint8_t); diff --git a/libraries/ESP8266WiFi/src/include/ClientContext.h b/libraries/ESP8266WiFi/src/include/ClientContext.h index 806fc5e399..4afe647a2a 100644 --- a/libraries/ESP8266WiFi/src/include/ClientContext.h +++ b/libraries/ESP8266WiFi/src/include/ClientContext.h @@ -36,16 +36,27 @@ bool getDefaultPrivateGlobalSyncValue (); class ClientContext { public: - ClientContext(tcp_pcb* pcb, discard_cb_t discard_cb, void* discard_cb_arg) : + ClientContext(tcp_pcb* pcb, discard_cb_t discard_cb, void* discard_cb_arg, bool acceptNow = true) : _pcb(pcb), _rx_buf(0), _rx_buf_offset(0), _discard_cb(discard_cb), _discard_cb_arg(discard_cb_arg), _refcnt(0), _next(0), _sync(::getDefaultPrivateGlobalSyncValue()) { - tcp_setprio(pcb, TCP_PRIO_MIN); - tcp_arg(pcb, this); - tcp_recv(pcb, &_s_recv); - tcp_sent(pcb, &_s_acked); - tcp_err(pcb, &_s_error); - tcp_poll(pcb, &_s_poll, 1); + if (acceptNow) + acceptPCB(); + } + + tcp_pcb* getPCB () + { + return _pcb; + } + + void acceptPCB() + { + tcp_setprio(_pcb, TCP_PRIO_MIN); + tcp_arg(_pcb, this); + tcp_recv(_pcb, &_s_recv); + tcp_sent(_pcb, &_s_acked); + tcp_err(_pcb, &_s_error); + tcp_poll(_pcb, &_s_poll, 1); // keep-alive not enabled by default //keepAlive(); diff --git a/tests/host/common/MockWiFiServer.cpp b/tests/host/common/MockWiFiServer.cpp index 6b8b7e83c5..132ca5e88a 100644 --- a/tests/host/common/MockWiFiServer.cpp +++ b/tests/host/common/MockWiFiServer.cpp @@ -59,7 +59,7 @@ WiFiClient WiFiServer::available (uint8_t* status) { (void)status; if (hasClient()) - return WiFiClient(new ClientContext(serverAccept(pcb2int(_pcb)))); + return WiFiClient(new ClientContext(serverAccept(pcb2int(_listen_pcb)))); return WiFiClient(); } diff --git a/tests/host/common/MockWiFiServerSocket.cpp b/tests/host/common/MockWiFiServerSocket.cpp index c791577d0f..f56b9f4245 100644 --- a/tests/host/common/MockWiFiServerSocket.cpp +++ b/tests/host/common/MockWiFiServerSocket.cpp @@ -60,6 +60,13 @@ int serverAccept (int srvsock) void WiFiServer::begin (uint16_t port) { + return begin(port, !0); +} + +void WiFiServer::begin (uint16_t port, uint8_t backlog) +{ + if (!backlog) + return; _port = port; return begin(); } @@ -109,13 +116,13 @@ void WiFiServer::begin () // store int into pointer - _pcb = int2pcb(sock); + _listen_pcb = int2pcb(sock); } bool WiFiServer::hasClient () { struct pollfd p; - p.fd = pcb2int(_pcb); + p.fd = pcb2int(_listen_pcb); p.events = POLLIN; return poll(&p, 1, 0) && p.revents == POLLIN; } @@ -134,7 +141,7 @@ size_t WiFiServer::write (const uint8_t *buf, size_t size) void WiFiServer::close () { - if (pcb2int(_pcb) >= 0) - ::close(pcb2int(_pcb)); - _pcb = int2pcb(-1); + if (pcb2int(_listen_pcb) >= 0) + ::close(pcb2int(_listen_pcb)); + _listen_pcb = int2pcb(-1); } diff --git a/tools/sdk/lib/liblwip2-1460-feat.a b/tools/sdk/lib/liblwip2-1460-feat.a index 4dc84bf8bd..a4d969e50f 100644 Binary files a/tools/sdk/lib/liblwip2-1460-feat.a and b/tools/sdk/lib/liblwip2-1460-feat.a differ diff --git a/tools/sdk/lib/liblwip2-1460.a b/tools/sdk/lib/liblwip2-1460.a index 95c1712037..a733ace329 100644 Binary files a/tools/sdk/lib/liblwip2-1460.a and b/tools/sdk/lib/liblwip2-1460.a differ diff --git a/tools/sdk/lib/liblwip2-536-feat.a b/tools/sdk/lib/liblwip2-536-feat.a index 6de957e3e6..b077ff0a78 100644 Binary files a/tools/sdk/lib/liblwip2-536-feat.a and b/tools/sdk/lib/liblwip2-536-feat.a differ diff --git a/tools/sdk/lib/liblwip2-536.a b/tools/sdk/lib/liblwip2-536.a index 04b92dc840..93d6c99577 100644 Binary files a/tools/sdk/lib/liblwip2-536.a and b/tools/sdk/lib/liblwip2-536.a differ diff --git a/tools/sdk/lib/liblwip6-1460-feat.a b/tools/sdk/lib/liblwip6-1460-feat.a index 3256c5f9b5..f278e75f93 100644 Binary files a/tools/sdk/lib/liblwip6-1460-feat.a and b/tools/sdk/lib/liblwip6-1460-feat.a differ diff --git a/tools/sdk/lib/liblwip6-536-feat.a b/tools/sdk/lib/liblwip6-536-feat.a index 4c8fea6157..56968ba786 100644 Binary files a/tools/sdk/lib/liblwip6-536-feat.a and b/tools/sdk/lib/liblwip6-536-feat.a differ diff --git a/tools/sdk/lwip2/builder b/tools/sdk/lwip2/builder index 354887a25f..b543b1f1f4 160000 --- a/tools/sdk/lwip2/builder +++ b/tools/sdk/lwip2/builder @@ -1 +1 @@ -Subproject commit 354887a25f83064dc0c795e11704190845812713 +Subproject commit b543b1f1f4aff4787693da71b6ea91ca23e9b01f diff --git a/tools/sdk/lwip2/include/lwip-git-hash.h b/tools/sdk/lwip2/include/lwip-git-hash.h index 42aca1818e..0fb03f0df1 100644 --- a/tools/sdk/lwip2/include/lwip-git-hash.h +++ b/tools/sdk/lwip2/include/lwip-git-hash.h @@ -1,5 +1,5 @@ // generated by makefiles/make-lwip2-hash #ifndef LWIP_HASH_H #define LWIP_HASH_H -#define LWIP_HASH_STR "STABLE-2_1_2_RELEASE/glue:1.2-16-ge23a07e" +#define LWIP_HASH_STR "STABLE-2_1_2_RELEASE/glue:1.2-29-gb543b1f" #endif // LWIP_HASH_H diff --git a/tools/sdk/lwip2/include/lwipopts.h b/tools/sdk/lwip2/include/lwipopts.h index e2ae90030d..6ee039f7c0 100644 --- a/tools/sdk/lwip2/include/lwipopts.h +++ b/tools/sdk/lwip2/include/lwipopts.h @@ -1402,7 +1402,7 @@ * TCP_LISTEN_BACKLOG: Enable the backlog option for tcp listen pcb. */ #if !defined TCP_LISTEN_BACKLOG || defined __DOXYGEN__ -#define TCP_LISTEN_BACKLOG 0 +#define TCP_LISTEN_BACKLOG LWIP_FEATURES // 0 #endif /** @@ -2278,6 +2278,12 @@ * @ingroup lwip_opts_infrastructure * @{ */ +/** + * LWIP_CHKSUM_ALGORITHM==3: Checksum algorithm fastest for ESP8266 + */ +#if !defined LWIP_CHKSUM_ALGORITHM || defined __DOXYGEN__ +#define LWIP_CHKSUM_ALGORITHM 3 // 2 +#endif /** * LWIP_CHECKSUM_CTRL_PER_NETIF==1: Checksum generation/check can be enabled/disabled * per netif. @@ -3573,7 +3579,7 @@ extern "C" { #define SNTP_SUPPRESS_DELAY_CHECK 1 #define SNTP_UPDATE_DELAY_DEFAULT 3600000 // update delay defined by a default weak function #define SNTP_UPDATE_DELAY sntp_update_delay_MS_rfc_not_less_than_15000() -extern uint32_t SNTP_UPDATE_DELAY; +uint32_t SNTP_UPDATE_DELAY; #if LWIP_FEATURES // esp8266/arduino/lwip-1.4 had 3 possible SNTP servers (constant was harcoded) @@ -3591,7 +3597,7 @@ extern uint32_t SNTP_UPDATE_DELAY; #define SNTP_STARTUP_DELAY 1 // enable startup delay #define SNTP_STARTUP_DELAY_FUNC_DEFAULT 0 // to 0 by default via a default weak function #define SNTP_STARTUP_DELAY_FUNC sntp_startup_delay_MS_rfc_not_less_than_60000() -extern uint32_t SNTP_STARTUP_DELAY_FUNC; +uint32_t SNTP_STARTUP_DELAY_FUNC; /* -------------------------------------------------- @@ -3611,7 +3617,7 @@ struct netif; #error LWIP_ERR_T definition should come from lwip1.4 from espressif #endif //#define LWIP_ERR_T s8 -LWIP_ERR_T lwip_unhandled_packet (struct pbuf* pbuf, struct netif* netif) __attribute__((weak)); +LWIP_ERR_T lwip_unhandled_packet (struct pbuf* pbuf, struct netif* netif); /* -------------------------------------------------- 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